node(koa2+ejs) 通过 node-xlsx xlsx-style xlsx 生成带有格式的 excel

近日收到一个任务,使用程序自动生成考勤报表,条件是单元格格式必须与模板完全一致,行高、列宽,字体样式等,于是就尝试用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-style xlsx 生成带有格式的 excel)