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`);
}

浙公网安备 33010602011771号