Exporting Vue el-Table Data to Formatted Excel Files
Dependecny Installation
npm install xlsx xlsx-style file-saver
Webpack Configuraiton
Add to vue.config.js to resolve xlsx-style conflicts:
module.exports = {
chainWebpack: config => {
config.externals({
"./cptable": "var cptable"
});
}
}
Export Utility Implemantation
Create tableExport.js:
import * as XLSX from 'xlsx';
import XLSXStyle from 'xlsx-style';
import { saveAs } from 'file-saver';
export function generateExcelSheet(targetTable, sheetLabel, exportName, headerRows) {
const exportConfig = { sheet: sheetLabel, raw: true };
const fixedSection = targetTable.querySelector('.el-table__fixed');
let workbook;
if (fixedSection) {
targetTable.removeChild(fixedSection);
workbook = XLSX.utils.table_to_book(targetTable, exportConfig);
targetTable.appendChild(fixedSection);
} else {
workbook = XLSX.utils.table_to_book(targetTable, exportConfig);
}
const worksheet = workbook.Sheets[sheetLabel];
const dataRange = XLSX.utils.decode_range(worksheet['!ref']);
// Cell border definition
const cellBorders = {
top: { style: 'thin', color: { rgb: '000000' } },
bottom: { style: 'thin', color: { rgb: '000000' } },
left: { style: 'thin', color: { rgb: '000000' } },
right: { style: 'thin', color: { rgb: '000000' } }
};
const columnDimensions = [];
for (let colIdx = dataRange.s.c; colIdx <= dataRange.e.c; colIdx++) {
let colWidth = 100;
const maxColWidth = 400;
for (let rowIdx = dataRange.s.r; rowIdx <= dataRange.e.r; rowIdx++) {
const cellPosition = { c: colIdx, r: rowIdx };
const cellId = XLSX.utils.encode_cell(cellPosition);
if (worksheet[cellId]) {
// Header row styling
if (rowIdx < headerRows) {
worksheet[cellId].s = {
font: { color: { rgb: '060B0E' }, bold: true },
alignment: { horizontal: 'center', vertical: 'center' },
fill: { fgColor: { rgb: 'E4E4E4' } },
border: cellBorders
};
} else {
worksheet[cellId].s = {
alignment: { horizontal: 'center', vertical: 'center' },
border: cellBorders
};
}
// Dynamic width calculation
const cellContent = String(worksheet[cellId].v);
const chineseChars = cellContent.match(/[\u4e00-\u9fa5]/g) || [];
const nonChineseChars = cellContent.replace(/[^\u0000-\u00FF]/g, '');
let charWidth = 0;
charWidth += chineseChars.join('').length * 20;
charWidth += nonChineseChars.length * 10;
if (charWidth > colWidth) colWidth = charWidth;
}
}
columnDimensions.push({ wpx: Math.min(colWidth, maxColWidth) });
}
worksheet['!cols'] = columnDimensions;
const writeOpts = { bookType: 'xlsx', bookSST: false, type: 'binary' };
const excelData = XLSXStyle.write(workbook, writeOpts);
const blob = new Blob([convertToArrayBuffer(excelData)], { type: '' });
saveAs(blob, `${exportName}.xlsx`);
}
function convertToArrayBuffer(data) {
const buffer = new ArrayBuffer(data.length);
const view = new Uint8Array(buffer);
for (let i = 0; i < data.length; i++) {
view[i] = data.charCodeAt(i) & 0xFF;
}
return buffer;
}
Usage Exammple
Triggger export in component:
const tableNode = document.getElementById('export-table');
generateExcelSheet(
tableNode,
'AssessmentDetails',
'PerformanceMetrics',
3
);