1、引入
npm install xlsx
npm install xlsx-style
我使用的对应版本如下图
2、解决报错
打开node_ modules文件下找到xlsx,复制xlsx.full.min.js文件,放到对应文件并在index.html中引入
引入到html文件中
然后解决xlsx-style的报错问题
vue解决问题:
打开项目根目录的vue.config.js文件,没有就新建一个,写入以下代码
module.exports = {
configureWebpack: {
resolve: {
fallback: {
fs: false // 禁用fs模块 否则 xlsx-style 模块会报错
}
},
externals: {
'./cptable': 'var cptable' // 去除 xlsx-style 模块的报错
}
},
}
react解决问题如下:(查看项目中是否存在 craco.config.js、config-overrides.js 其中的一种)
如果存在craco.config.js文件,则在craco.config.js文件中修改配置,如下
module.exports = {
webpack: {
configure: (webpackConfig, { env, paths }) => {
webpackConfig.resolve.fallback = {
crypto: false, // 禁用crypto模块 否则控制台会有警告
fs: false, // 禁用fs模块 否则 xlsx-style 模块会报错
}
webpackConfig.externals = {
'./cptable': 'var cptable' // 去除 xlsx-style 模块的报错
}
return webpackConfig
},
},
};
如果存在config-overrides.js 文件,就在config-overrides.js文件中修改以下配置
const {
override,
} = require("customize-cra");
module.exports = override(
(config, env) => {
// 设置 resolve.fallback
config.resolve.fallback = {
crypto: false, // 或者提供一个 polyfill,如 'crypto-browserify'
fs: false, // fs 模块在浏览器中通常不可用,设置为 false 表示不尝试加载它
// 可以添加其他需要 fallback 的模块
};
// 设置 externals
config.externals = {
'./cptable': 'var cptable' // 去除 xlsx-style 模块的报错
};
return config;
},
);
如果以上两个文件都不存在,则打开项目根目录的webpack.config.js文件,没有新建一个,写入以下代码
module.exports = {
resolve: {
fallback: {
fs: false // 禁用fs模块 否则 xlsx-style 模块会报错
}
},
externals: {
'./cptable': 'var cptable' // 去除 xlsx-style 模块的报错
},
};
3、导出数据
import XLSXStyle from "xlsx-style"; // 使用 XLSXStyle 引入
// 通用 Excel 导出工具函数
export function exportToExcel(data, columnWidths, filename) {
if (!data || !Array.isArray(data) || data.length === 0) {
console.warn("数据不能为空");
return;
}
// 将数据转换为 Excel 的 sheet
const sheet = XLSX.utils.aoa_to_sheet(data);
// 设置单元格样式:水平居中、垂直居中、边框
const borderAll = {
top: { style: "thin" },
bottom: { style: "thin" },
left: { style: "thin" },
right: { style: "thin" },
};
// 遍历所有单元格,应用样式
for (const key in sheet) {
if (sheet.hasOwnProperty(key) && key[0] !== '!') {
sheet[key].s = {
alignment: {
horizontal: "center", // 水平居中
vertical: "center", // 垂直居中
},
font: {
name: "Arial", // 字体
sz: 12, // 字体大小
},
border: borderAll, // 边框
};
}
}
// 设置列宽
sheet['!cols'] = columnWidths.map(width => ({ wpx: width }));
// 调用下载函数
openDownloadDialog(sheet2blob(sheet), `${filename}.xlsx`);
}
/**
* 打开下载对话框的方法
* @param {Blob} url Blob 对象
* @param {String} saveName 文件名
*/
function openDownloadDialog(url, saveName) {
const aLink = document.createElement("a");
const blob = url instanceof Blob ? URL.createObjectURL(url) : url;
aLink.href = blob;
aLink.download = saveName || "download.xlsx";
aLink.click();
}
/**
* 将sheet对象转换为blob对象
* @param {Object} sheet sheet对象
* @param {String} sheetName sheet名称,默认 "Sheet1"
* @returns {Blob}
*/
function sheet2blob(sheet, sheetName = "Sheet1") {
const workbook = {
SheetNames: [sheetName],
Sheets: { [sheetName]: sheet },
};
const wopts = {
bookType: 'xlsx',
bookSST: false,
type: 'binary'
};
const wbout = XLSXStyle.write(workbook, wopts);
// 将输出的文件内容转换为 Blob 对象
function s2ab(s) {
const buf = new ArrayBuffer(s.length);
const view = new Uint8Array(buf);
for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
return new Blob([s2ab(wbout)], { type: 'application/octet-stream' });
}
vue组件使用(注意引入路径)
<template>
<div class="page">
<el-button type="primary" @click="exportExcel">下载Excel</el-button>
</div>
</template>
<script>
import { exportToExcel } from '@/utils/excel.js' //写直接的路径
export default {
methods: {
// 下载excel
exportExcel() {
const data = [
['年份', '省份/城市', '数量', '增长率'],
['2021', '北京', 100, '20%'],
['2021', '上海', 200, '15%'],
['2022', '广州', 150, '10%']
];
const columnWidths = [100, 200, 100, 100]; // 每列的宽度
const filename = 'data.xlsx';
exportToExcel(data, columnWidths, filename);
},
}
};
</script>