jjzjj

excel表格合并-js

组仙 2023-09-28 原文

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',或者在代码里修改引用名。这个文件好像不能直接下载,你可以复制如下图红字‘’处的路径,粘贴到浏览器地址栏后,即可得到插件代码。然后'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(';')
            }else {
                appendsArr.push(appends)
            }

            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的更多相关文章

  1. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  2. ruby-on-rails - Prawn - 表格单元格内的链接 - 2

    我正在尝试用Prawn生成PDF。在我的PDF模板中,我有带单元格的表格。在其中一个单元格中,我有一个电子邮件地址:cell_email=pdf.make_cell(:content=>booking.user_email,:border_width=>0)我想让电子邮件链接到“mailto”链接。我知道我可以这样链接:pdf.formatted_text([{:text=>booking.user_email,:link=>"mailto:#{booking.user_email}"}])但是将这两行组合起来(将格式化文本作为内容)不起作用:cell_email=pdf.make_c

  3. git使用常见问题(提交代码,合并冲突) - 2

    文章目录git常用命令(简介,详细参数往下看)Git提交代码步骤gitpullgitstatusgitaddgitcommitgitpushgit代码冲突合并问题方法一:放弃本地代码方法二:合并代码常用命令以及详细参数gitadd将文件添加到仓库:gitdiff比较文件异同gitlog查看历史记录gitreset代码回滚版本库相关操作远程仓库相关操作分支相关操作创建分支查看分支:gitbranch合并分支:gitmerge删除分支:gitbranch-ddev查看分支合并图:gitlog–graph–pretty=oneline–abbrev-commit撤消某次提交git用户名密码相关配置g

  4. ruby - 如何使用 Ruby 将 CSV 文件读入 HTML 表格? - 2

    我正在尝试将一个简单的CSV文件读入HTML表格以在浏览器中显示,但我遇到了麻烦。这就是我正在尝试的:Controller:defshow@csv=CSV.open("file.csv",:headers=>true)end查看:输出:NameStartDateEndDateQuantityPostalCode基本上我只获取标题,而不会读取和呈现CSV正文。 最佳答案 这最终成为最终解决方案:Controller:defshow#OpenaCSVfile,andthenreaditintoaCSV::Tableobjectforda

  5. Ruby 哈希直接访问与合并 - 2

    有什么区别:@attr[:field]=new_value和@attr.merge(:field=>new_value) 最佳答案 如果您使用的是merge!而不是merge,则没有区别。唯一的区别是您可以在合并参数中使用多个字段(意思是:另一个散列)。例子:h1={"a"=>100,"b"=>200}h2={"b"=>254,"c"=>300}h3=h1.merge(h2)putsh1#=>{"a"=>100,"b"=>200}putsh3#=>{"a"=>100,"b"=>254,"c"=>300}h1.merge!(h2)pu

  6. ruby - 如何使用 Nokogiri 解析纯 HTML 表格? - 2

    我想用Nokogiri解析HTML页面。页面的一部分有一个表,它没有使用任何特定的ID。是否可以提取如下内容:Today,3,455,34Today,1,1300,3664Today,10,100000,3444,Yesterday,3454,5656,3Yesterday,3545,1000,10Yesterday,3411,36223,15来自这个HTML:TodayYesterdayQntySizeLengthLengthSizeQnty345534345456563113003664354510001010100000344434113622315

  7. ruby-on-rails - prawnto 显示新页面时不会中断的表格 - 2

    我有可变数量的表格和可变数量的行,我想让它们一个接一个地显示,但如果表格不适合当前页面,请将其放在下一页,然后继续。我已将表格放入事务中,以便我可以回滚然后打印它(如果高度适合当前页面),但我如何获得表格高度?我现在有这段代码pdf.transactiondopdf.table@data,:font_size=>12,:border_style=>:grid,:horizontal_padding=>10,:vertical_padding=>3,:border_width=>2,:position=>:left,:row_colors=>["FFFFFF","DDDDDD"]pdf.

  8. ruby - 如何以表格格式快速打印 Ruby 哈希值? - 2

    有没有办法快速将表格格式的ruby​​哈希打印到文件中?如:keyAkeyBkeyC...1232343451253474456...其中散列的值是不同大小的数组。还是使用双循环是唯一的方法?谢谢 最佳答案 试试我写的这个gem(在表中打印散列、ruby对象、ActiveRecord对象):http://github.com/arches/table_print 关于ruby-如何以表格格式快速打印Ruby哈希值?,我们在StackOverflow上找到一个类似的问题:

  9. ruby - 在两个 ActiveRecord 类之间合并/复制属性的好方法? - 2

    之前有人问过这个问题,我发现了以下clip关于如何一次设置一个类对象的所有属性,但由于批量分配保护,这在Rails中是不可能的。(例如,您不能Object.attributes={})有没有一种很好的方法可以将一个类的属性合并到另一个类中?object1.attributes=object2.attributes.inject({}){|h,(k,v)|h[k]=vifObjectModel.column_names.include?(k);h}谢谢。 最佳答案 利用assign_attributes使用:without_prote

  10. ruby-on-rails - Assets 管道损坏 : Not compiling on the fly css and js files - 2

    我开始了一个新的Rails3.2.5项目,Assets管道不再工作了。CSS和Javascript文件不再编译。这是尝试生成Assets时日志的输出:StartedGET"/assets/application.css?body=1"for127.0.0.1at2012-06-1623:59:11-0700Servedasset/application.css-200OK(0ms)[2012-06-1623:59:11]ERRORNoMethodError:undefinedmethod`each'fornil:NilClass/Users/greg/.rbenv/versions/1

随机推荐