美文网首页
excel表格合并-js

excel表格合并-js

作者: 姬歌 | 来源:发表于2023-02-21 16:09 被阅读0次

office EXCEL文档有合并表格功能,WPS基础功能免费,但合并表格要充SSSSSS VIP
我又没有office EXCEL,我又不想充 WPS VIP,所以我研究了这个用js合并的方法。
如果你对js和excel有兴趣,你也可以好好研究 js-xlsx,用代码去处理excel。代码的灵活性要比WPS强多了。
界面如图左侧所示。(右侧绿框是按F12弹出的调试界面,可显示调试信息)
按顺序操作1,2,3,4,5,即可拼接第1个表和第2个表。

图1-网页
(上图)左下角可生成示例用于拼接的表1和表2
图2-示例表
  • 拼接表的必要条件是:有相同的属性(列名/字段)-且该属性值是唯一的,如学号220101,不管你一条数据还是一百万条数据,这个学号都不能重复。但姓名可以重复,所以姓名不应用来做拼接数据的ID。
  • 表2需要被拼接的字段,如这里的语文、数学,需要拼接哪个就填到第二个输入框里。但是因为表1已经有学号、姓名,所以这里不需要重复填写学号姓名。‘’随机排序‘’字段是我用随机数生成的,用于打乱排序,验证能否找到相同学号对应行数据。你可以忽略这个字段。
  • 注意,表1是全体学生表,表2是部分学生成绩。表2的学号一定存在于表1。
拼接效果:
图3-拼接结果表
点此去github下载代码
下载说明

THE END.

如果能正常下载zip,下面内容可以不用看了。下载文件夹找到直接双击join.htm即可使用。




DIY----想要得到图1的“网页”,需要:

1、新建文件夹(任意名字,任意目录),例如叫‘js处理excel’,放桌面


图4-文档文件夹

2、其中,join.htm是我参照别人写的‘网页’,xlsxtool.js是工具文件(实际这里文件都是txt文档-纯文本,然后修改后缀,.txt改为.htm,.js。)
后面会给出join.htm,xlsxtool.js的代码。
【js】这个目录/文件夹,就必须起'js'这个名字(否则你就要改代码里的引用路径)并放在'js处理excel'目录下。
【js】里面是三个js文件,其中1,2是网上下载的官方工具插件,3是我抄写的工具。

图5-目录1
图6-目录2
xlsx.core.min.js下载
JQuery各版本下载
xlsx.xxxxx.js直接就能下载。
jquery各个版本都能用,但如果下载其他版本,需要把名称改为'jquery-3.0.0.min.js',或者在代码里修改引用名。这个文件好像不能直接下载,你可以复制如下图红字‘\color{red}{2}’处的路径,粘贴到浏览器地址栏后,即可得到插件代码。然后'Alt+A'全选,复制代码,粘贴到一个空的txt文本。修改文本名称(包括txt后缀)为'jquery-3.0.0.min.js'保存即可。
至于官网各个版本,uncompressed,minified,slim,slim minified,实际就是全功能版本、简化功能版本的区别。我们只要简化版本就可以了,否则文件体积会较大。
图7-JQuery下载

最后,是我们自己的代码:

不要看到‘代码’就害怕,无非都是一些txt纯文本,只不过有固定格式而已,然后把后缀'xxx.txt'改成'xxx.htm','xxx.js'而已
join.htm

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <!-- 网络加载 jquery -->
    <!-- <script src="https://code.jquery.com/jquery-3.0.0.min.js" integrity="sha256-JmvOoLtYsmqlsWxa7mDSLMwa6dZ9rrIdtrrVYRnDRH0=" crossorigin="anonymous"></script> -->
    <!-- 本地jquery -->
    <script src="js/jquery-3.0.0.min.js"></script>

    <script src="js/xlsx.core.min.js"></script>
    <script src="js/xlsxtool.js"></script>
</head>
 
<body>
    <p id="p1">第1个表</p>
    <input type="file" id="excel-file1" name="">
    <p id="p2">第2个表</p>
    <input type="file" id="excel-file2" name="">
    
    <p><a style="color:blue;">ID</a>(匹配字段-2个表中相同的列名称,如2个表的学生学号一致且值唯一,就填"<a style="color:red;">学号</a>")</p>
    <p style="font-size: smaller">表1第1行和表2哪一行拼接呢?那肯定是张三的成绩拼到张三那一行啊!但学校可能有2个张三,但学号是唯一的,所以用学号做ID(数据匹配依据)</p>
    <input type="text" id="tbID" placeholder="2个表相同且值唯一的列名">
    <p><a style="color:blue;">拼接字段</a>(第2个表参与拼接的列,如要把第2个表的数学、语文列拼接到新表,则填"<a style="color:red;">数学,语文</a>",中间逗号隔开)</p>
    <input type="text" id="appends" placeholder="新增列名1,列名2,..">
    <p>拼接2个表</p>
    <button type="button" onclick="clickJoin(this)">拼接2个成表</button>

    <p class="tips">测试数据-示例</p>
    <button class="btn-gen1" type="button" onclick="clickGenTable1(this)">下载学生表</button>
    <button class="btn-gen2" type="button" onclick="clickGenTable2(this)">下载学生成绩表</button>
</body>
 
<script>
    $('#excel-file1').change(function (e) {
        document.getElementById('p1').innerHTML = '第1个表(已获取)'
        var files = e.target.files;
        var fileReader = new FileReader();
        fileReader.onload = function (ev) {
            try {
                var data = ev.target.result,
                    workbook = XLSX.read(data, {
                        type: 'binary'
                    }), // 以二进制流方式读取得到整份excel表格对象
                    persons = []; // 存储获取到的数据
            } catch (e) {
                console.log('文件类型不正确');
                return;
            }
 
            // 表格的表格范围,可用于判断表头是否数量是否正确
            var fromTo = '';
            // 遍历每张表读取
            // !!!workbook.Sheets是一个对象!!不是数组!
            console.log('=====workbook1=====:') 
            console.log(workbook) 
            for (var propertyName in workbook.Sheets) {
                console.log('propertyName: ' + propertyName) 
                if (workbook.Sheets.hasOwnProperty(propertyName)) {
                   var sheet = workbook.Sheets[propertyName]
                   // console.log(sheet)
                   fromTo = sheet['!ref'];
                   console.log('fromTo: ' + fromTo);
                   firstTableRows = XLSX.utils.sheet_to_json(sheet)
                   persons = persons.concat(firstTableRows);
                   break; // 如果只取第一张表,就取消注释这行
                }
            }
            console.log('表-json对象1:');
            console.log(firstTableRows);
            // let jsonString = JSON.stringify(firstTableRows)
            // console.log(jsonString);
        };
        // 以二进制方式打开文件
        fileReader.readAsBinaryString(files[0]);
    });
    $('#excel-file2').change(function (e) {
        document.getElementById('p2').innerHTML = '第2个表(已获取)'
        var files = e.target.files;
        var fileReader = new FileReader();
        fileReader.onload = function (ev) {
            try {
                var data = ev.target.result,
                    workbook = XLSX.read(data, {
                        type: 'binary'
                    }), // 以二进制流方式读取得到整份excel表格对象
                    persons = []; // 存储获取到的数据
            } catch (e) {
                console.log('文件类型不正确');
                return;
            }
 
            // 表格的表格范围,可用于判断表头是否数量是否正确
            var fromTo = '';
            // 遍历每张表读取
            // !!!workbook.Sheets是一个对象!!不是数组!
            console.log('=====workbook2=====:') 
            console.log(workbook) 
            for (var propertyName in workbook.Sheets) {
                console.log('propertyName: ' + propertyName)
                if (workbook.Sheets.hasOwnProperty(propertyName)) {
                   var sheet = workbook.Sheets[propertyName]
                   // console.log(sheet)
                   fromTo = sheet['!ref'];
                   console.log('fromTo: ' + fromTo);
                   secondTableRows = XLSX.utils.sheet_to_json(sheet)
                   persons = persons.concat(secondTableRows);
                   break; // 如果只取第一张表,就取消注释这行
                }
            }
            console.log('表-json对象2:');
            console.log(secondTableRows);
        };
        // 以二进制方式打开文件
        fileReader.readAsBinaryString(files[0]);
    });

    function clickJoin(argument) {
        // body...
        console.log('点击了‘拼接’按钮')
        // jsonToExcel(    sheet1data,    'demo.xls');
        // testGen()
        if(!firstTableRows) {
            alert('请先选择第1个表')
        }else if(!secondTableRows) {
            alert('请先选择第2个表')
        }else {
            let idStr =  document.getElementById('tbID').value
            console.log(idStr)
            let appends = document.getElementById('appends').value
            console.log(appends)   
            if (!idStr) {
                alert('请先填写ID')
                return
            }      
            if(!appends) {
                alert('请先填写拼接字段')
                return
            }
            let appendsArr = []
            if(appends.indexOf(',') != -1) {
                appendsArr = appends.split(',')
            }else if(appends.indexOf(',') != -1) {
                appendsArr = appends.split(',')
            }else if(appends.indexOf(';') != -1) {
                appendsArr = appends.split(';')
            }else if(appends.indexOf(';') != -1) {
                appendsArr = appends.split(';')
            }

            console.log(appendsArr)
            for (var i = 0; i < firstTableRows.length; i++) {
                let t1row = firstTableRows[i]
                for (var j = 0; j < secondTableRows.length; j++) {
                    let t2row = secondTableRows[j]
                    // if(t2row['学号'] == t1row['学号']) {
                    //     t1row['语文'] = t2row['语文']
                    //     t1row['数学'] = t2row['数学']
                    // }

                    if (t2row[idStr] == t1row[idStr]) {
                        for (var k = 0; k < appendsArr.length; k++) {
                            let key = appendsArr[k]
                            // console.log('key = ' + key)
                            if (t2row[key] !== undefined) {
                                t1row[key] = t2row[key]
                            }
                        }
                    }
                }
            }
            xtGenExcel(firstTableRows, '拼接表')
        }
    }

    function clickGenTable1(argument) {
        // body...
        testGenStudents()

    }
    function clickGenTable2(argument) {
        // body...
        testGenResults()
    }

// demo调用演示
let sheet1data = [ // 注意数组中每列key的排序,因为导出列表时按照key的排序导出的
    { 部门: '行政部', 姓名: 'zhangsan', age: 18 },
    { 部门: 'IT', 姓名: 'lisi', age: 19 },
];

var firstTableRows = undefined
var secondTableRows = undefined


</script>
<style type="text/css">
    .tips {
        position: fixed;
        bottom: 30px;
        left: 20px;
        color: #333333;
        font-size: small;
    }
    .btn-gen1 {
        position: fixed;
        bottom: 10px;
        left: 20px;
        color: blue;
    }
    .btn-gen2 {
        position: fixed;
        bottom: 10px;
        left: 120px;
        color: blue;
    }
</style>
 
</html>

xlsxtool.js


// 导入文件
document.write("<script language = javascript src = 'js/xlsx.core.min.js'></script>")

function testGen() {
    // body...
    xtGenExcel(testData)
}

function testGenStudents() {
    // body...
    xtGenExcel(students, '学生表')
}

function testGenResults() {
    // body...
    xtGenExcel(examResults, '学生成绩表')
}

function xtGenExcel(rows, bookName = 'MYBOOK', sheetName = 'sheet1') {
    // body...
    const workbook = XLSX.utils.book_new();
    const worksheet = XLSX.utils.json_to_sheet(rows);

    XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);

    // 给 sheet 添加【表头】
    // XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });

    // 调整适应列宽
    // const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
    // 第一列列宽 = max_width, 第二列列宽 = 10。 wch:
    // worksheet["!cols"] = [ { wch: max_width } , {wch: 10}];

    // 输出 excel
    XLSX.writeFile(workbook, bookName + ".xlsx", { compression: true });
}

// 这个方法不需要 xlsx 插件。
function jsonToExcel(jsonData, filename = 'export.xls') {
    if (!Array.isArray(jsonData) || !jsonData?.length) {
        return;
    }
    let str = '';
    // 列标题
    Object.keys(jsonData[0]).forEach(k => {
        str += k + '\t,';
    });
    str += '\n';
    // 增加\t为了不让表格显示科学计数法或者其他格式
    for (let i = 0; i < jsonData.length; i++) {
        // eslint-disable-next-line no-loop-func
        Object.keys(jsonData[i]).forEach(key => {
            str += `${jsonData[i][key] + '\t'},`;
        });
        str += '\n';
    }
    console.log(str)
    // str = '1,2,3,4,\n11,22,33,44,55,66,\na,b,c,d,\nhello'   // \n 换行,也是excel换行。逗号则是代表一列
    // encodeURIComponent解决中文乱码
    const uri = `data:text/${filename.split('.').pop()};charset=utf-8,\ufeff${encodeURIComponent(str)}`;
    console.log(uri)
    // 通过创建a标签实现
    let dom = document.createElement('a');
    dom.download = filename;
    dom.style.display = 'none';
    dom.href = uri;
    document.body.appendChild(dom);
    dom.click();
    setTimeout(() => {
        document.body.removeChild(dom);
    }, 1000);
}

const students = [{"学号":220101,"姓名":"细狗你","班级":1,"性别":"男","年龄":12},{"学号":220102,"姓名":"细鬼","班级":1,"性别":"男","年龄":11},{"学号":220103,"姓名":"渣渣辉","班级":1,"性别":"男","年龄":14},{"学号":220201,"姓名":"吴君如","班级":2,"性别":"女","年龄":12},{"学号":220202,"姓名":"苑琼丹","班级":2,"性别":"女","年龄":13},{"学号":220301,"姓名":"张三","班级":3,"性别":"男","年龄":13},{"学号":220302,"姓名":"王麻子","班级":3,"性别":"女","年龄":12},{"学号":220303,"姓名":"二狗子","班级":3,"性别":"男","年龄":12},{"学号":220304,"姓名":"李四","班级":3,"性别":"男","年龄":13},{"学号":220305,"姓名":"陈华春","班级":3,"性别":"女","年龄":14},{"学号":220306,"姓名":"赵丽华","班级":3,"性别":"女","年龄":12},{"学号":220401,"姓名":"坤哥","班级":4,"性别":"男","年龄":12},{"学号":220402,"姓名":"梁坤","班级":4,"性别":"男","年龄":12},{"学号":220403,"姓名":"梁晨","班级":4,"性别":"男","年龄":12},{"学号":220404,"姓名":"梅静","班级":4,"性别":"女","年龄":12},{"学号":220405,"姓名":"韩汉晨","班级":4,"性别":"男","年龄":13},{"学号":220406,"姓名":"凌楚峰","班级":4,"性别":"男","年龄":12}]
const examResults = [{"学号":220303,"姓名":"二狗子","语文":62,"数学":88,"随机排序":0.534449607369229},{"学号":220301,"姓名":"张三","语文":64,"数学":98,"随机排序":0.166291769352402},{"学号":220101,"姓名":"细狗你","语文":99,"数学":96,"随机排序":0.298748966878335},{"学号":220305,"姓名":"陈华春","语文":83,"数学":94,"随机排序":0.981885816605045},{"学号":220306,"姓名":"赵丽华","语文":87,"数学":97,"随机排序":0.777319924734964},{"学号":220405,"姓名":"韩汉晨","语文":63,"数学":100,"随机排序":0.0758610844747052},{"学号":220403,"姓名":"梁晨","语文":69,"数学":76,"随机排序":0.160749347477528},{"学号":220402,"姓名":"梁坤","语文":52,"数学":83,"随机排序":0.329833118669286},{"学号":220404,"姓名":"梅静","语文":43,"数学":100,"随机排序":0.844087333621201},{"学号":220302,"姓名":"王麻子","语文":67,"数学":66,"随机排序":0.376213770771804},{"学号":220401,"姓名":"坤哥","语文":100,"数学":97,"随机排序":0.736891795092198},{"学号":220304,"姓名":"李四","语文":47,"数学":59,"随机排序":0.801160817943515},{"学号":220406,"姓名":"凌楚峰","语文":55,"数学":98,"随机排序":0.0735291866946264}]

const testData = [
    { name: "George Washington", birthday: "1732-02-22" },
    { name: "John Adams", birthday: "1735-10-19" },
    ]

相关文章

网友评论

      本文标题:excel表格合并-js

      本文链接:https://www.haomeiwen.com/subject/qionkdtx.html