vue 導出xlsx (報錯./cptable in ./node modules/xlsx-style/dist/cpexcel.js)
- 安裝 xlsx 和 xlsx-style
- src下創建文件夾utils , utils文件夾下創建index.js文件,index.js文件內容如下:
* Created by Anqi on 16/11/18.
*/
/**
* Parse the time to string
* @param {(Object|string|number)} time
* @param {string} cFormat
* @returns {string | null}
*/
// import XLSX from 'xlsx-style';
import XLSX from 'yxg-xlsx-style'
export function parseTime(time, cFormat) {
if (arguments.length === 0) {
return null;
}
const format = cFormat || '{y}-{m}-w0obha2h00 {h}:{i}:{s}';
let date;
if (typeof time === 'object') {
date = time;
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time);
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000;
}
date = new Date(time);
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
};
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
const value = formatObj[key];
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ]; }
return value.toString().padStart(2, '0');
});
return time_str;
}
/**
* @param {number} time
* @param {string} option
* @returns {string}
*/
export function formatTime(time, option) {
if (('' + time).length === 10) {
time = parseInt(time) * 1000;
} else {
time = +time;
}
const d = new Date(time);
const now = Date.now();
const diff = (now - d) / 1000;
if (diff < 30) {
return '剛剛';
} else if (diff < 3600) {
// less 1 hour
return Math.ceil(diff / 60) + '分鐘前';
} else if (diff < 3600 * 24) {
return Math.ceil(diff / 3600) + '小時前';
} else if (diff < 3600 * 24 * 2) {
return '1天前';
}
if (option) {
return parseTime(time, option);
} else {
return (
d.getMonth() +
1 +
'月' +
d.getDate() +
'日' +
d.getHours() +
'時' +
d.getMinutes() +
'分'
);
}
}
/**
* @param {string} url
* @returns {Object}
*/
export function param2Obj(url) {
const search = url.split('?')[1];
if (!search) {
return {};
}
return JSON.parse(
'{"' +
decodeURIComponent(search)
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"')
.replace(/\+/g, ' ') +
'"}'
);
}
export function downloadFile(fileName, res) {
const blob = new Blob([res.data], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click();
URL.revokeObjectURL(link.href);
}
export function resizeListener(chart) {
window.addEventListener('resize', function() {
chart.resize();
});
}
// 為合并項添加邊框
export const addRangeBorder = (range, ws) => {
const arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
range.forEach(item => {
const startColNumber = Number(item.s.r); const endColNumber = Number(item.e.r); // 0-0
const startRowNumber = Number(item.s.c); const endRowNumber = Number(item.e.c); // 0-16
const test = ws[arr[startRowNumber] + (startColNumber + 1)]; // 合并項第一個單元格中的內容
for (let col = startColNumber; col <= endColNumber; col++) { // 0-0
for (let row = startRowNumber; row <= endRowNumber; row++) { // 0-16
ws[arr[row] + (col + 1)] = test; // A1-P1
}
}
});
return ws;
};
// 將一個sheet轉成最終的excel文件的blob對象
export const sheet2blob = (sheet, sheetName) => {
// console.log(sheet, sheetName, 'sheet, sheetName')
sheetName = sheetName || 'sheet1';
console.log(sheetName, 'sheetName');
var workbook = {
SheetNames: [sheetName],
Sheets: {}
};
workbook.Sheets[sheetName] = sheet; // 生成excel的配置項
var wopts = {
bookType: 'xlsx', // 要生成的文件類型
bookSST: false, // 是否生成Shared String Table,官方解釋是,如果開啟生成速度會下降,但在低版本IOS設備上有更好的兼容性
type: 'binary'
};
var wbout = XLSX.write(workbook, wopts);
var blob = new Blob([s2ab(wbout)], {
type: 'application/octet-stream'
}); // 字符串轉ArrayBuffer
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
return blob;
};
export const openDownloadDialog = (url, saveName) => {
if (typeof url === 'object' && url instanceof Blob) {
url = URL.createObjectURL(url); // 創建blob地址
}
var aLink = document.createElement('a');
aLink.href = url;
aLink.download = saveName || ''; // HTML5新增的屬性,指定保存文件名,可以不要后綴,注意,file:///模式下不會生效
var event;
if (window.MouseEvent) event = new MouseEvent('click');
else {
event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
}
aLink.dispatchEvent(event);
};
3. 注意!!!!!!!直接引用 import XLSX from 'xlsx-style' 會報錯,報錯信息如下圖:

想要解決此錯誤需要修改model包里源碼,需要修改源碼:在\node_modules\xlsx-style\dist\cpexcel.js 807行 的 var cpt = require(’./cpt’ + ‘able’); 改成 var cpt = cptable;,修改之后問題解決可以解決,但是另一個問題就來了,
因為修改了xlsx-style源碼所以我們npm i的時候不能獲取修改后的包,但是其實可以將修改后的源碼上傳自己的npm再下載自己修改后的包。但是由于本人實在懶得可怕,找了一位博主上傳好的直接下載了!!!!!!!!!
下載 npm install --save yxg-xlsx-style , 頁面引入 :import XLSX from 'yxg-xlsx-style'
vue頁面使用如下:
exportFn() {
var wb = XLSX2.utils.table_to_sheet(document.querySelector('#table'));// mytable為表格的id名
console.log(wb);
if (!wb['!fullref']) {
this.$message.warning('無法導出:報表無數據');
return;
}
// 設置列寬(這里用到列的數量是用來設置不同列的不同寬度的)
const sum = 8; // 列的數量,根據自身項目進行數據的更改
for (var i = 0; i < sum; i++) {
wb['!cols'][i] = { wpx: 160 };
}
for (const key in wb) {
if (key.indexOf('!') === -1) { // 排除帶!的字段,只要單元格字段
wb[key].s = {
font: { // 字體設置
sz: 13,
bold: false,
color: {
rgb: '000000'// 十六進制,不帶#
}
},
border: { // 設置邊框
top: { style: 'thin' },
bottom: { style: 'thin' },
left: { style: 'thin' },
right: { style: 'thin' }
},
alignment: { // 文字居中 //字體水平居中、垂直居中、自動換行
horizontal: 'center',
vertical: 'center',
wrap_text: true
}
};
}
}
// var data = addRangeBorder(wb['!merges'], wb); // 合并項添加邊框
let a = dayjs(this.queryParams.time[0]).format('YYYYMMDDHHmmss');
let b = dayjs(this.queryParams.time[1]).format('YYYYMMDDHHmmss');
var filedata = sheet2blob(wb); // 將一個sheet轉成最終的excel文件的blob對象
openDownloadDialog(filedata, `數據_${a}_${b}.xlsx`); // 下載報表
},
別忘記在el-table 上定義 ID !!!!!!!!!!!!!!!

浙公網安備 33010602011771號