• 关于导出的Excel文件的本质


    上篇文章中提到关于xlsx改造冻结窗格的代码,我是怎么知道要加pane的呢,加下来就把我的心路历程记录一下。

    我改造之前也是没有头绪的,我网上查了很多,只告诉我如何使用,但源码里没有针对!freeze的处理,所以即便把!freeze传过去也是无用的。于是我想既然js可以实现excel的导出,那应该有办法能实现,只是原作者写到pro版里了,那么我能不能加上呢,如何加呢?

    我先贴上部分代码

    1. // 冻结第一行和第一列:
    2. worksheet['!freeze'] = {
    3. xSplit: "0", //冻结列
    4. ySplit: "1", //冻结行
    5. // topLeftCell: "A2", //在未冻结区域的左上角显示的单元格,默认为第一个未冻结的单元格
    6. state: "frozen"
    7. }
    8. var wbout = XLSX.write(workbook, {
    9. bookType: 'xlsx',
    10. bookSST: false,
    11. type: 'binary'
    12. })

    第一步

    首先我打印了wbout,发现是一个二进制文件,然后找到xlsx.write的write

    1. // 部分代码
    2. ...
    3. XLSX.parse_zip = parse_zip;
    4. XLSX.read = readSync; //xlsread
    5. XLSX.readFile = readFileSync; //readFile
    6. XLSX.readFileSync = readFileSync;
    7. XLSX.write = writeSync;
    8. XLSX.writeFile = writeFileSync;
    9. XLSX.writeFileSync = writeFileSync;
    10. XLSX.writeFileAsync = writeFileAsync;
    11. XLSX.utils = utils;
    12. XLSX.writeXLSX = writeSyncXLSX;
    13. XLSX.writeFileXLSX = writeFileSyncXLSX;
    14. XLSX.SSF = SSF;

    第二步

    然后找到writeSync方法 -》 write_zip_type -》 write_zip -》write_zip_xlsx

    1. function write_zip(wb, opts) {
    2. console.log('write_zip', opts.bookType)
    3. if(opts.bookType == "ods") return write_ods(wb, opts);
    4. if(opts.bookType == "numbers") return write_numbers_iwa(wb, opts);
    5. if(opts.bookType == "xlsb") return write_zip_xlsxb(wb, opts);
    6. return write_zip_xlsx(wb, opts);
    7. }

     关键点就在write_zip_xlsx方法中

    在write_zip_xlsx方法中,我们找到xl/worksheets/sheet的下面的write_ws_xml方法,

    write_ws_xml方法返回的就是一段字符串,就是我们要导出的excel的内容

    1. // 部分代码
    2. ...
    3. var wsrels = {'!id':{}};
    4. var ws = wb.Sheets[wb.SheetNames[rId-1]];
    5. var _type = (ws || {})["!type"] || "sheet";
    6. switch(_type) {
    7. case "chart":
    8. /* falls through */
    9. default:
    10. f = "xl/worksheets/sheet" + rId + "." + wbext;
    11. zip_add_file(zip, f, write_ws_xml(rId-1, opts, wb, wsrels));
    12. ct.sheets.push(f);
    13. add_rels(opts.wbrels, -1, "worksheets/sheet" + rId + "." + wbext, RELS.WS[0]);
    14. }

    第三步

    这里我们在write_zip_xlsx方法的xl/worksheets/sheet的下面打印一下console.log(write_ws_xml(rId-1, opts, wb, wsrels))

     这里我们可以看见返回的是一个类似xml格式的字符串

    (这里我加上!freeze代码之后的打印结果,没加之前是没有这串字符的)

    我们就想了excel的原理是不是就是xml格式呢,我怎么往里面添加上它能识别的标签呢??

    带着疑问,我查找了下面的资料:

    Excel2007格式分析和XML解析

    Excel文件的本质:一个包含XML、图片文件的压缩文件夹-压缩文件-上犹电脑信息网

    根据资料,我试着本地新建一个excel文件,分别一次设置冻结窗口,一个不设置,然后将文件后缀改为zip、解压,得到的目录和资料中的一致,对比两个xl/worksheets/sheet1.xml的区别,发现是标签,知道冻结窗口的标签了,接下来就简单了,我们就可以添加下面的代码了

    1. //部分代码
    2. ...
    3. // 冻结窗口
    4. var pane = null;
    5. var freeze = ws['!freeze'];
    6. console.log(freeze)
    7. if (freeze !== undefined) {
    8. pane = writextag('pane', null, {
    9. xSplit: freeze.xSplit, // 冻结列
    10. ySplit: freeze.ySplit, // 冻结行
    11. topLeftCell: freeze.topLeftCell, // 在未冻结区域的左上角显示的单元格,默认为第一个未冻结的单元格
    12. activePane: freeze.activePane,
    13. state: freeze.state || 'frozen'
    14. })
    15. }
    16. return writextag("sheetViews", writextag("sheetView", pane, sview), {});

    以上就是完整的流程,改造冻结窗口只是示例,通过类似的过程,我们可以改造成我们想要的其他格式。 

     

  • 相关阅读:
    QT 样式插件示例
    java Map遍历的5种方法和一些基本使用
    Magisk搞机器记录(小米Mix3)
    设计模式之观察者模式(Observer)
    unity之C#中级开发
    File类与IO流相关面试知识(一)
    新能源时代来袭,电桩控制板开发为绿色城市发展蓄能
    紫光同创FPGA实现UDP协议栈网络视频传输,带录像和抓拍功能,基于YT8511和RTL8211,提供2套PDS工程源码和技术支持
    动态规划求数组中相邻两数的最小差值( 即相差的绝对值 ) java 实现
    linux下安装ffmpeg的教程
  • 原文地址:https://blog.csdn.net/cs23405/article/details/133775893