1 安装之后报错
npm install xlsx --savenpm install xlsx-style --save
Umi运行会报错
自己代码
import XLSX from "xlsx";
import XLSXStyle from "xlsx-style";const data = [["demo1","demo2","demo3","demo4","demo5","是否开启(填写注意: 0为否,1为是)",],["1", "2", "3", "4", "5", "0"],
];
const wsWidths = [20, 20, 20, 20, 20, 20];const book = XLSX.utils.book_new(); //没有工作表的空工作簿
const workSheet = XLSX.utils.aoa_to_sheet(data);
if (Array.isArray(wsWidths) && wsWidths.length === columnNames[0].length) {workSheet["!cols"] = wsWidths.map((width) => ({ wch: width }));
}
if (merge) {/***合并单元格:// s 意为 start ,即开始的单元格// r 是 row ,表示行号,从 0 计起// c 是 col ,表示列号,从 0 计起const merge = [// 纵向合并,范围是第1列的行1到行2{ s: { r: 0, c: 0 }, e: { r: 1, c: 0 } },// 纵向合并,范围是第2列的行1到行2{ s: { r: 0, c: 1 }, e: { r: 1, c: 1 } },// 横向合并,范围是第1行的列3到列5{ s: { r: 0, c: 2 }, e: { r: 0, c: 4 } },// 横向合并,范围是第1行的列6到列11{ s: { r: 0, c: 5 }, e: { r: 0, c: 10 } },// 横向合并,范围是第1行的列12到列17{ s: { r: 0, c: 11 }, e: { r: 0, c: 16 } },// 横向合并,范围是第1行的列18到列23{ s: { r: 0, c: 17 }, e: { r: 0, c: 22 } },// 横向合并,范围是第1行的列24到列29{ s: { r: 0, c: 23 }, e: { r: 0, c: 28 } },// 横向合并,范围是第1行的列30到列35{ s: { r: 0, c: 29 }, e: { r: 0, c: 34 } }];*/workSheet["!merges"] = merge;
}
const colKeys = Object.keys(workSheet).filter((k) => /[A-Z]/.test(k[0]));
styles.forEach((s, i) => {const t = columnNames[0][i];const j = colKeys.findIndex((k) => workSheet[k].v === t);if (s && j > -1) {workSheet[colKeys[j]].s = s;}
});
XLSX.utils.book_append_sheet(book, workSheet, sheetName);
XLSXStyle.writeFile(book, filename, {defaultCellStyle /* {font: { name: "Verdana", sz: 14, color: {rgb: "FFFF0000"}},fill: {fgColor: {rgb: "FF00FF00"}},alignment: {vertical: 'center'}} */,
});
解决方案1:配置webpack
externals: {'./cptable': 'var cptable',
},
Umi在config.ts中配置。
解决方案2:删除两个导入 (最佳方案)
import XLSX from "xlsx";
import XLSXStyle from "xlsx-style";
删除之后,上面的代码就能正常使用,编译也不报错了,也不需要进行webpack配置。
因为这两个库不支持ES 6的导出,导出的值是undefined。
解决方案3
使用方案1生成表格时候报错:
意思就是
XLSX为undefined,我去这不是import导入进来了吗,怎么就undefined了。
直接进入XLSX源码查看。
源码里面根本就没有导出XLSX。直接挂在window上面的,什么玩意啊。
修改自己的代码
const data = [["demo1","demo2","demo3","demo4","demo5","是否开启(填写注意: 0为否,1为是)",],["1", "2", "3", "4", "5", "0"],
];
const wsWidths = [20, 20, 20, 20, 20, 20];const book = window.XLSX.utils.book_new(); //没有工作表的空工作簿
const workSheet = window.XLSX.utils.aoa_to_sheet(data);
if (Array.isArray(wsWidths) && wsWidths.length === columnNames[0].length) {workSheet["!cols"] = wsWidths.map((width) => ({ wch: width }));
}
if (merge) {/***合并单元格:// s 意为 start ,即开始的单元格// r 是 row ,表示行号,从 0 计起// c 是 col ,表示列号,从 0 计起const merge = [// 纵向合并,范围是第1列的行1到行2{ s: { r: 0, c: 0 }, e: { r: 1, c: 0 } },// 纵向合并,范围是第2列的行1到行2{ s: { r: 0, c: 1 }, e: { r: 1, c: 1 } },// 横向合并,范围是第1行的列3到列5{ s: { r: 0, c: 2 }, e: { r: 0, c: 4 } },// 横向合并,范围是第1行的列6到列11{ s: { r: 0, c: 5 }, e: { r: 0, c: 10 } },// 横向合并,范围是第1行的列12到列17{ s: { r: 0, c: 11 }, e: { r: 0, c: 16 } },// 横向合并,范围是第1行的列18到列23{ s: { r: 0, c: 17 }, e: { r: 0, c: 22 } },// 横向合并,范围是第1行的列24到列29{ s: { r: 0, c: 23 }, e: { r: 0, c: 28 } },// 横向合并,范围是第1行的列30到列35{ s: { r: 0, c: 29 }, e: { r: 0, c: 34 } }];*/workSheet["!merges"] = merge;
}
const colKeys = Object.keys(workSheet).filter((k) => /[A-Z]/.test(k[0]));
styles.forEach((s, i) => {const t = columnNames[0][i];const j = colKeys.findIndex((k) => workSheet[k].v === t);if (s && j > -1) {workSheet[colKeys[j]].s = s;}
});window.XLSX.utils.book_append_sheet(book, workSheet, sheetName);window.XLSXStyle.writeFile(book, filename, {defaultCellStyle /* {font: { name: "Verdana", sz: 14, color: {rgb: "FFFF0000"}},fill: {fgColor: {rgb: "FF00FF00"}},alignment: {vertical: 'center'}} */,});
直接使用window点对应的方法。
生成文件内容
2 文件解析
import { Upload } from "antd";
<Uploadaccept=".xlsx"fileList={[]}beforeUpload={(file) => onBeforeUpload(file)}
><Button>批量上传</Button>
</Upload>;
const isBinary =typeof FileReader !== "undefined" &&typeof FileReader.prototype !== "undefined" &&typeof FileReader.prototype.readAsBinaryString !== "undefined";let myParseWorker;function formatData(data) {var o = "",l = 0,w = 10240;for (; l < data.byteLength / w; ++l)o += String.fromCharCode.apply(null,new Uint8Array(data.slice(l * w, l * w + w)));o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)));return o;
}
function parseWorker(data) {if (!myParseWorker) {myParseWorker = new Worker(`${window.location.protocol +"//" +window.location.host +window.location.pathname}xlsx.worker.js`);}return new Promise((resolve, reject) => {myParseWorker.onmessage = function (e) {switch (e.data.type) {case "error":reject(e.data.data);break;case "xlsx":return resolve(JSON.parse(e.data.data));}};data = isBinary ? data : btoa(formatData(data));myParseWorker.postMessage({ data, binary: isBinary });});
}const onBeforeUpload = async (file) => {try {const res = new Promise((resolve, reject) => {const myFileReader = new FileReader();myFileReader.onload = (e) => {try {parseWorker(e.target.result).then((res) => {//if里面可以增加自己的校验方法if (true) {return resolve(file);}return reject(e);}).catch((error) => {console.log(error);reject(error);});} catch (error) {console.log(error);reject(error);}};if (isBinary) {myFileReader.readAsBinaryString(file);} else {myFileReader.readAsArrayBuffer(file);}});return file;} catch (error) {console.log(error);} finally {}
};
parseWorker里面then中res