vue项目通过xlsx-js-style导出数据为EXCEL

排除工具

xlsx(sheet.js):
缺点:社区版无法自定义格式,需要购买pro版本
xlsx-style:
缺点:代码多年未更新,存在bug,需要改动node_modules包
 
选用工具

安装xlsx-js-style

npm install xlsx-js-style

使用思路

设定每个单元格基础格式,遍历所有数据,填入所需要的格式

使用方法

引入

import * as XLSXStyle from "xlsx-js-style";

 设定基础样式

class ConstantCell {
  constructor(obj) {
    this.obj = {
      r: obj.r,
      c: obj.c,
      v: {
        v: obj.v,
        ct: { fa: "General", t: "g" },
        bg: obj.bg || "ffffff",
        bl: obj.bl || 0,
        it: 0,
        fc: obj.fc || "#000",
        ff: 1,
        fs: "11",
        ht: 0,
        vt: 0,
        m: obj.m,
        bold: false
      }
    };
  }
}

获取基础数据

我的数据格式,可以自己设定

pAll = [{data.content:[数据]}]
tables=[{label:'sheet名称',columns:[{label:'列名称',prop:'列字段'}]}]
fileName = '表名称'

将数据改写为EXCEL导出所需格式

function formatData(pAll, tables, fileName) {
  const mapRes = new Map();

  pAll.map((v, i) => {
    let content = [];
    if (v.data) {
      content = v.data.content;
    }
    mapRes.set(tables[i].label, {
      tableData: content,
      columns: tables[i].columns
    });
  });
  const sheetDataArr = [];
  for (let key of mapRes.keys()) {
    const tableList = [];
    const headerList = [];
    const { tableData, columns } = mapRes.get(key);
    let objColIndex = 0;
    //设定表头
    columns.map(({ prop, label }) => {
      objColIndex = objColIndex + 1;
      const  headerConstantCellObj = new ConstantCell({
          r: 0,
          c: objColIndex,
          v: label,
          bg: "f8f8f9",
          m: label,
          bl: 1
        });
      
      headerList.push(headerConstantCellObj.obj);
    });

    tableList.push(headerList);
//设定行
    tableData.map((v, i) => {
      const rowList = [];
      objColIndex = 0;
      columns.map(({ prop, label }) => {
        objColIndex = objColIndex + 1;
        let fc = null;
        const ConstantCellObj = new ConstantCell({
          r: i + 1,
          c: objColIndex,
          v: v[prop],
          bg: "ffffff",
          m: v[prop],
          fc
        });
        rowList.push(ConstantCellObj.obj);
      });
      tableList.push(rowList);
    });
    sheetDataArr.push({ tableList, sheetTitle: key });
  }
  formatExcel(sheetDataArr, fileName);
}    

根据自己所需设置样式:(A1:每个单元格信息)

网上复制的

function formatExcel(sheetDataArr, fileName) {
  const SheetNames = [];
  const Sheets = {};
  sheetDataArr.map(({ tableList, sheetTitle }, sheetDataIndex) => {
    let downOriginData = tableList;
    let arr = []; // 所有的单元格数据组成的二维数组
    let bgConfig = {};
    let percentageReg = /%$/;
    let cellValue = null;
    //列下标 数字转字母

    function chatatABC(n) {
      var orda = "a".charCodeAt(0);
      var ordz = "z".charCodeAt(0);
      var len = ordz - orda + 1;
      var s = "";
      while (n >= 0) {
        s = String.fromCharCode((n % len) + orda) + s;
        n = Math.floor(n / len) - 1;
      }
      return s.toUpperCase();
    }

    // 设置样式
    function setStyle(row, col, cellValue) {
      var colA = chatatABC(col);
      var key = colA + (row + 1);
      bgConfig[key] = cellValue;
      // bgConfig[key] = cellValue.bg.replace(/\#?/, "");
    }

    // 判断值类型是否为百分比 %
    function isPercentage(value) {
      return percentageReg.test(value.m) && value.ct && value.ct.t === "n";
    }

    // 获取二维数组
    for (let row = 0; row < downOriginData.length; row++) {
      let arrRow = [];
      for (let col = 0; col < downOriginData[row].length; col++) {
        cellValue = downOriginData[row][col].v;

        setStyle(row, col, cellValue);
        if (cellValue.ct != null && cellValue.ct.t == "d") {
          //  d为时间格式  2019-01-01   或者2019-01-01 10:10:10
          arrRow.push(new Date(cellValue.m.replace(/\-/g, "/"))); //兼容IE
        } else if (cellValue.m && isPercentage(cellValue)) {
          //百分比问题
          arrRow.push(cellValue.m);
        } else {
          arrRow.push(cellValue.v);
        }
        // }
      }
      arr.push(arrRow);
    }

    let opts = {
      dateNF: "m/d/yy h:mm",
      cellDates: true,
      cellStyles: true
    };
    const wb = XLSXStyle.utils.book_new();
    let ws = XLSXStyle.utils.aoa_to_sheet(arr, opts);
    XLSXStyle.utils.book_append_sheet(wb, ws, "readme demo");
    let reg = /[\u4e00-\u9fa5]/g;
    for (let key in ws) {
      let item = ws[key];
      if (item.t === "d") {
        if (item.w) {
          //时间格式的设置
          let arr = item.w.split(" ");
          if (arr[1] && arr[1] == "0:00") {
            ws[key].z = "m/d/yy";
          } else {
            item.z = "yyyy/m/d h:mm:ss";
          }
        }
      }
      // 设置单元格样式
      if (bgConfig[key]) {
        const { bg, bold, fc } = bgConfig[key];
        ws[key]["s"] = {
          alignment: { vertical: "center", horizontal: "center" },
          fill: {
            bgColor: { indexed: 32 },
            fgColor: { rgb: bg }
          },
          font: { bold, color: { rgb: fc } },
          border: {
            top: { style: "thin", color: { rgb: "999999" } },
            bottom: { style: "thin", color: { rgb: "999999" } },
            left: { style: "thin", color: { rgb: "999999" } },
            right: { style: "thin", color: { rgb: "999999" } }
          }
        };
      }
    }

    //第四步:组装下载数据格式
    SheetNames.push(sheetTitle);
    Sheets[sheetTitle] = Object.assign({}, ws);
  });
  let tmpWB = {
    SheetNames, //保存的表标题
    Sheets
  };

  // 第六步:写入文件
  XLSXStyle.writeFile(tmpWB, fileName + ".xlsx");
} 

最简单的基本功能完成,后续根据需求慢慢完善

更新,简易版

import XLSX from 'xlsx-js-style';

export function exportUtil(tableColumnList, tableDataList, title = '导出表格') {
  // 创建一个新的工作簿
  const wb = XLSX.utils.book_new();

  // 创建工作表数据
  const wsData = [
    tableColumnList.map((col) => col.label), // 表头
    ...tableDataList.map((item) => tableColumnList.map((col) => item[col.prop] || '')) // 数据行
  ];

  // 创建工作表
  const ws = XLSX.utils.aoa_to_sheet(wsData);

  // 设置列宽
  ws['!cols'] = tableColumnList.map((col) => ({ wpx: col.width || 100 }));

  // 设置样式
  wsData.forEach((row, rowIndex) => {
    row.forEach((cell, colIndex) => {
      const cellAddress = XLSX.utils.encode_cell({ c: colIndex, r: rowIndex });
      if (!ws[cellAddress]) ws[cellAddress] = { v: cell };
      ws[cellAddress].s = {
        font: { name: 'Arial', sz: 12 },
        alignment: { vertical: 'center', horizontal: 'center' },
        border: {
          top: { style: 'thin', color: { rgb: '000000' } },
          bottom: { style: 'thin', color: { rgb: '000000' } },
          left: { style: 'thin', color: { rgb: '000000' } },
          right: { style: 'thin', color: { rgb: '000000' } }
        }
      };

      // 设置特定列的字体颜色
      if (tableColumnList[colIndex].color) {
        ws[cellAddress].s.font.color = { rgb: tableColumnList[colIndex].color };
      }
      // 设置表头样式
      if (rowIndex === 0) {
        ws[cellAddress].s.fill = { fgColor: { rgb: 'EDEEFE' } }; // 背景色蓝色
        ws[cellAddress].s.font.color = { rgb: '333333' }; // 文字颜色白色
        ws[cellAddress].s.font.bold = true; // 加粗
      }
    });
  });

  // 将工作表添加到工作簿
  XLSX.utils.book_append_sheet(wb, ws, title);

  // 导出Excel文件
  XLSX.writeFile(wb, `${title}.xlsx`);
}

 

import XLSX from 'xlsx-js-style';

export function exportUtil(tableColumnList, tableDataList, title = '导出表格') {
  // 创建一个新的工作簿
  const wb = XLSX.utils.book_new();

  // 创建工作表数据
  const wsData = [
    tableColumnList.map((col) => col.label), // 表头
    ...tableDataList.map((item) => tableColumnList.map((col) => item[col.prop] || '')) // 数据行
  ];

  // 创建工作表
  const ws = XLSX.utils.aoa_to_sheet(wsData);

  // 设置列宽
  ws['!cols'] = tableColumnList.map((col) => ({ wpx: col.width || 100 }));

  // 设置样式
  wsData.forEach((row, rowIndex) => {
    row.forEach((cell, colIndex) => {
      const cellAddress = XLSX.utils.encode_cell({ c: colIndex, r: rowIndex });
      if (!ws[cellAddress]) ws[cellAddress] = { v: cell };
      ws[cellAddress].s = {
        font: { name: 'Arial', sz: 12 },
        alignment: { vertical: 'center', horizontal: 'center' },
        border: {
          top: { style: 'thin', color: { rgb: '000000' } },
          bottom: { style: 'thin', color: { rgb: '000000' } },
          left: { style: 'thin', color: { rgb: '000000' } },
          right: { style: 'thin', color: { rgb: '000000' } }
        }
      };

      // 设置特定列的字体颜色
      if (tableColumnList[colIndex].color) {
        ws[cellAddress].s.font.color = { rgb: tableColumnList[colIndex].color };
      }
      // 设置表头样式
      if (rowIndex === 0) {
        ws[cellAddress].s.fill = { fgColor: { rgb: 'EDEEFE' } }; // 背景色蓝色
        ws[cellAddress].s.font.color = { rgb: '333333' }; // 文字颜色白色
        ws[cellAddress].s.font.bold = true; // 加粗
      }
    });
  });

  // 将工作表添加到工作簿
  XLSX.utils.book_append_sheet(wb, ws, title);

  // 导出Excel文件
  XLSX.writeFile(wb, `${title}.xlsx`);
}
posted @ 2022-09-29 16:34  朱依漾  阅读(95)  评论(0编辑  收藏  举报