美文网首页
node(koa2+ejs) 通过 node-xlsx xlsx

node(koa2+ejs) 通过 node-xlsx xlsx

作者: seaflyj | 来源:发表于2021-04-14 13:33 被阅读0次

    近日收到一个任务,使用程序自动生成考勤报表,条件是单元格格式必须与模板完全一致,行高、列宽,字体样式等,于是就尝试用node搞一个,遇见了一些坑,不过都趟过去了,接下来一步步展示

    首先上效果图


    微信截图_20210414104933.png

    源码地址:https://github.com/jianghaifei/nodeWriteExcel.git

    一、框架搭建:

    使用的是 node(koa2) + ejs 框架,前后端不分离,框架是次要的,主要还是生成 excel 模块才是重点;

    配置 bin 里面的 www 文件可以修改服务端口,目前默认是3000;

    在 app.js 中可以配置自己的中间件;

    项目代码下载后,先执行 npm install

    然后测我环境运营项目可以执行 npm run dev

    二、页面引用关系

    app.js 注册路由,路由文件在 routes 里面,前后端路由地址都在 write.js 文件中,数据操作在 controller 中;

    三、引入生成 excel 相关的插件

    安装 node-xlsx 执行命令:npm install node-xlsx

    目前只需要引入这一个插件就可以,实际上还需要 xlsx-style xlsx 这两个插件,但是这两个并不完善,需要我们自行修改源码,才能达到使用需求,所以这里就不需要安装,我将源码直接放在public/node-xlsx-c中,在使用中直接引用就好;

    微信截图_20210414123537.png

    这里修改源码为:

    1、index.js 中,将第 12 行引用修改为

    var _xlsx = _interopRequireDefault(require("./xlsx"));
    
    var _bufferFrom = _interopRequireDefault(require("buffer-from"));
    
    var _helpers = require("./helpers");
    
    var _workbook = _interopRequireDefault(require("./workbook"));
    

    目的是为了引入 xlsx-style ,因为 xlsx-style 也需要修改,所以引入 xlsx.js 文件;修改的目的是为了让单元格样式生效,如 字体颜色,边框,局中等;

    2、修改 hepler.js,在136行增加如下代码

    if (options['!rows']) {
        workSheet['!rows'] = options['!rows'];
    }
    

    目的是让opts里的rows能够被添加至workSheet当中

    然后再修改在xlsx-style里的xlsx.js write_ws_xml_data 方法,添加设置行高的代码,在10608行

        var DEF_PPI = 96,
            PPI = DEF_PPI;
        function px2pt(px) {
            return (px * 96) / PPI;
        }
        function write_ws_xml_data(ws, opts, idx, wb) {
            var o = [],
                r = [],
                range = safe_decode_range(ws["!ref"]),
                cell,
                ref,
                rr = "",
                cols = [],
                R,
                C,
                rows = ws["!rows"];
            for (C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
            for (R = range.s.r; R <= range.e.r; ++R) {
                r = [];
                rr = encode_row(R);
                for (C = range.s.c; C <= range.e.c; ++C) {
                    ref = cols[C] + rr;
                    if (ws[ref] === undefined) continue;
                    if (
                        (cell = write_ws_xml_cell(
                            ws[ref],
                            ref,
                            ws,
                            opts,
                            idx,
                            wb
                        )) != null
                    )
                        r.push(cell);
                }
                if (r.length > 0) {
                    params = { r: rr };
                    if (rows && rows[R]) {
                        row = rows[R];
                        if (row.hidden) params.hidden = 1;
                        height = -1;
                        if (row.hpx) height = px2pt(row.hpx);
                        else if (row.hpt) height = row.hpt;
                        if (height > -1) {
                            params.ht = height;
                            params.customHeight = 1;
                        }
                        if (row.level) {
                            params.outlineLevel = row.level;
                        }
                    }
                    o[o.length] = writextag("row", r.join(""), params);
                }
            }
            if (rows)
                for (; R < rows.length; ++R) {
                    if (rows && rows[R]) {
                        params = { r: R + 1 };
                        row = rows[R];
                        if (row.hidden) params.hidden = 1;
                        height = -1;
                        if (row.hpx) height = px2pt(row.hpx);
                        else if (row.hpt) height = row.hpt;
                        if (height > -1) {
                            params.ht = height;
                            params.customHeight = 1;
                        }
                        if (row.level) {
                            params.outlineLevel = row.level;
                        }
                        o[o.length] = writextag("row", "", params);
                    }
                }
            return o.join("");
        }
        
    

    需要修改源码的部分就结束了,直接引入

    const nodeXlsx = require('../public/node-xlsx-c'); // 引入二次封装好的 xlsx-style xlsx

    四、关键的导出代码如下:

        // 定义表格数据,列宽,行高,单元格合并
        let newdata = [],colArray=[],rowArray=[],range=[];
        
        // 表头样式
        const headerStyle = {
          font: {
            name: '宋体',
            bold: true,
            sz: '20',
          },
          alignment: {
            horizontal: 'center',
            vertical: 'center',
          },
        };
        
        // 添加表头数据
        newdata.push(
          [
            {
              v: '考 勤 记 录 表',
              s: headerStyle,
            },
          ],[]
          )
          
        // 设定列宽
        colArray.push({ wch: 3.91 });
        
        // 设置行高
        rowArray.push({ hpx: 15.6 });
        
        // 设置单元格合并
        range.push({
            s: { c: 0, r: lie },
            e: { c: weekarry.length - 1, r: lie },
        });
    
        // 文件名称
        let name = `${query.title} ${month + 1}月打卡记录`;
    
        // 配置属性,分别为 列宽/行高/单元格合并
        const options = {
          '!cols': colArray,
          '!rows': rowArray,
          '!merges': range,
        };
    
        // 创建二进制流
        const buffer = nodeXlsx.build([{ name: 'sheet1', data: newdata }], options);
    
        // 生成文件
        fs.writeFileSync('./public/excelnew/' + name + '.xls', buffer, 'binary');
    

    五、参数配置介绍

    原文地址:https://www.npmjs.com/package/xlsx-style

    微信截图_20210414132323.png

    最后配置上系统截图


    微信截图_20210414133208.png

    目前提供的源码只支持导出excel,读取的代码并不复杂,会在下一篇文章体现出来,如有代码遗漏,还请同学们告知。

    相关文章

      网友评论

          本文标题:node(koa2+ejs) 通过 node-xlsx xlsx

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