egg 生成Excel

2020-12-30  本文已影响0人  w晚风

项目中因为某些特定环境导致 不能前端去生成Excel只能通过后端接口去做 网上找了很大示例 总算是写出来了 趁着空闲来记录下

egg项目搭建我这里就不说了,再提一下,我这里使用的是ts版本的

我这边使用了某个npm插件
npm install exceljs
安装好后就可以用了 下面我来写下具体示例

公共方法

app/server/common.ts

import { Service } from 'egg';
const Excel = require('exceljs');

export default class Test extends Service {

  /**
   * 数据并生成excel
   * @param {Array} headers excel标题栏
   * @param {Array} param 数据参数
   * @param {string} name 文件名称
   */
  public async excelCommon(headers:any, data:any, name: string,) {
    let columns:any = [];// exceljs要求的columns
    let hjRow = {};// 合计行
    let titleRows = headers.length;// 标题栏行数

    // 处理表头
    for (let i = 0; i < titleRows; i++) {
        let row = headers[i];
        for (let j = 0, rlen = row.length; j < rlen; j++) {
            let col = row[j];
            let { f, t, w = 15 } = col;
            if (!f) continue;// 不存在f则跳过

            if (col.totalRow) hjRow[f] = true;
            if (col.totalRowText) hjRow[f] = col.totalRowText;
            col.style = { alignment: { vertical: 'middle', horizontal: 'center' } };
            col.header = t;
            col.key = f;
            col.width = w;
            columns.push(col);
        }
    }


    let workbook = new Excel.Workbook();
    let sheet = workbook.addWorksheet('My Sheet', { views: [{ xSplit: 1, ySplit: 1 }] });
    sheet.columns = columns;
    sheet.addRows(data);

    // 处理复杂表头
    if (titleRows > 1) {
        for (let i = 1; i < titleRows; i++)  sheet.spliceRows(1, 0, []);// 头部插入空行

        for (let i = 0; i < titleRows; i++) {
            let row = headers[i];
            for (let j = 0, rlen = row.length; j < rlen; j++) {
                let col = row[j];
                if (!col.m1) continue;

                sheet.getCell(col.m1).value = col.t;
                sheet.mergeCells(col.m1 + ":" + col.m2);
            }
        }
    }

    // 处理样式、日期、字典项
    sheet.eachRow(function (row, rowNumber) {
        // 设置行高
        row.height = 25;

        row.eachCell({ includeEmpty: true },  (cell)=> {
              // 设置边框 黑色 细实线
              const top:any = { style: 'thin', color: { argb: '000000' } };
              const left:any = { style: 'thin', color: { argb: '000000' } };
              const bottom:any = { style: 'thin', color: { argb: '000000' } };
              const right:any = { style: 'thin', color: { argb: '000000' } };
              cell.border = { top, left, bottom, right };

              // 设置标题部分为粗体
              if (rowNumber <= titleRows) { cell.font = { bold: true }; return; }
          });
      });


      this.ctx.set('Content-Type', 'application/vnd.openxmlformats');
      // 这个地方的空格不要更改
      this.ctx.set('Content-Disposition', "attachment;filename*=UTF-8' '" + encodeURIComponent(name) + '.xlsx');
      this.ctx.body = await workbook.xlsx.writeBuffer();
    }
}

控制器方法调用

app/controller/home.ts

import { Controller } from 'egg';


export default class HomeController extends Controller {
  public async index() {
      const { ctx } = this;
        let headers = [
          [ 
              { t: '下单时间', f: 'trade_time', totalRow: true },
              { t: '订单类型', f: 'order_type', totalRow: true },
              { t: '手机号码', f: 'phone_number', totalRow: true },
              { t: '扫描状态', f: 'scan_status', totalRow: true },
              { t: '交易状态', f: 'ctf_order_status', totalRow: true },
              { t: '订单份额(克)', f: 'trade_share', totalRow: true },
              { t: '当时账号总份额(克)', f: 'account_share', totalRow: true },
              { t: '订单号', f: 'order_no', totalRow: true },
          ]
        ];
        let data = [
            { trade_time: '2020-12-10', order_type:'线上', phone_number:'18374009921', scan_status:'1', ctf_order_status:'1', trade_share:'2', account_share:'2', order_no:'164656456546' },
            { trade_time: '2020-12-10', order_type:'线下', phone_number:'18374009921', scan_status:'1', ctf_order_status:'1', trade_share:'2', account_share:'2', order_no:'164656456546' }
        ] // 需要在这边自己适配数据,这边为空

    await ctx.service.common.excelCommon(headers, data, '订单信息');
  }  
}

路由

import { Application } from 'egg';

export default (app: Application) => {
  const { controller, router } = app;

  router.get('/Execl', controller.home.index);
};

这样就可以生成了 直接拿着接口去浏览器输出就好了


image.png

这里借鉴了这个大佬的 https://github.com/Wuwei9536/egg-exceljs

https://github.com/exceljs/exceljs/blob/HEAD/README_zh.md#add-rows 中文

上一篇下一篇

猜你喜欢

热点阅读