|
@@ -1,20 +1,21 @@
|
|
|
-import { saveAs } from "file-saver";
|
|
|
-import * as XLSX from "xlsx";
|
|
|
+import { saveAs } from 'file-saver'
|
|
|
+import * as XLSX from 'xlsx'
|
|
|
+import { ElMessage } from 'element-plus'
|
|
|
|
|
|
function generateArray(table) {
|
|
|
- var out = [];
|
|
|
- var rows = table.querySelectorAll("tr");
|
|
|
- var ranges = [];
|
|
|
+ var out = []
|
|
|
+ var rows = table.querySelectorAll('tr')
|
|
|
+ var ranges = []
|
|
|
for (var R = 0; R < rows.length; ++R) {
|
|
|
- var outRow = [];
|
|
|
- var row = rows[R];
|
|
|
- var columns = row.querySelectorAll("td");
|
|
|
+ var outRow = []
|
|
|
+ var row = rows[R]
|
|
|
+ var columns = row.querySelectorAll('td')
|
|
|
for (var C = 0; C < columns.length; ++C) {
|
|
|
- var cell = columns[C];
|
|
|
- var colspan = cell.getAttribute("colspan");
|
|
|
- var rowspan = cell.getAttribute("rowspan");
|
|
|
- var cellValue = cell.innerText;
|
|
|
- if (cellValue !== "" && cellValue === +cellValue) cellValue = +cellValue;
|
|
|
+ var cell = columns[C]
|
|
|
+ var colspan = cell.getAttribute('colspan')
|
|
|
+ var rowspan = cell.getAttribute('rowspan')
|
|
|
+ var cellValue = cell.innerText
|
|
|
+ if (cellValue !== '' && cellValue === +cellValue) cellValue = +cellValue
|
|
|
|
|
|
//Skip ranges
|
|
|
ranges.forEach(function (range) {
|
|
@@ -24,14 +25,14 @@ function generateArray(table) {
|
|
|
outRow.length >= range.s.c &&
|
|
|
outRow.length <= range.e.c
|
|
|
) {
|
|
|
- for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
|
|
|
+ for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null)
|
|
|
}
|
|
|
- });
|
|
|
+ })
|
|
|
|
|
|
//Handle Row Span
|
|
|
if (rowspan || colspan) {
|
|
|
- rowspan = rowspan || 1;
|
|
|
- colspan = colspan || 1;
|
|
|
+ rowspan = rowspan || 1
|
|
|
+ colspan = colspan || 1
|
|
|
ranges.push({
|
|
|
s: {
|
|
|
r: R,
|
|
@@ -41,28 +42,28 @@ function generateArray(table) {
|
|
|
r: R + rowspan - 1,
|
|
|
c: outRow.length + colspan - 1,
|
|
|
},
|
|
|
- });
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
//Handle Value
|
|
|
- outRow.push(cellValue !== "" ? cellValue : null);
|
|
|
+ outRow.push(cellValue !== '' ? cellValue : null)
|
|
|
|
|
|
//Handle Colspan
|
|
|
- if (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
|
|
|
+ if (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null)
|
|
|
}
|
|
|
- out.push(outRow);
|
|
|
+ out.push(outRow)
|
|
|
}
|
|
|
- return [out, ranges];
|
|
|
+ return [out, ranges]
|
|
|
}
|
|
|
|
|
|
function datenum(v, date1904) {
|
|
|
- if (date1904) v += 1462;
|
|
|
- var epoch = Date.parse(v);
|
|
|
- return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
|
|
|
+ if (date1904) v += 1462
|
|
|
+ var epoch = Date.parse(v)
|
|
|
+ return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000)
|
|
|
}
|
|
|
|
|
|
function sheet_from_array_of_arrays(data, opts) {
|
|
|
- var ws = {};
|
|
|
+ var ws = {}
|
|
|
var range = {
|
|
|
s: {
|
|
|
c: 10000000,
|
|
@@ -72,82 +73,82 @@ function sheet_from_array_of_arrays(data, opts) {
|
|
|
c: 0,
|
|
|
r: 0,
|
|
|
},
|
|
|
- };
|
|
|
+ }
|
|
|
for (var R = 0; R != data.length; ++R) {
|
|
|
for (var C = 0; C != data[R].length; ++C) {
|
|
|
- if (range.s.r > R) range.s.r = R;
|
|
|
- if (range.s.c > C) range.s.c = C;
|
|
|
- if (range.e.r < R) range.e.r = R;
|
|
|
- if (range.e.c < C) range.e.c = C;
|
|
|
+ if (range.s.r > R) range.s.r = R
|
|
|
+ if (range.s.c > C) range.s.c = C
|
|
|
+ if (range.e.r < R) range.e.r = R
|
|
|
+ if (range.e.c < C) range.e.c = C
|
|
|
var cell = {
|
|
|
v: data[R][C],
|
|
|
- };
|
|
|
- if (cell.v == null) continue;
|
|
|
+ }
|
|
|
+ if (cell.v == null) continue
|
|
|
var cell_ref = XLSX.utils.encode_cell({
|
|
|
c: C,
|
|
|
r: R,
|
|
|
- });
|
|
|
+ })
|
|
|
|
|
|
- if (typeof cell.v === "number") cell.t = "n";
|
|
|
- else if (typeof cell.v === "boolean") cell.t = "b";
|
|
|
+ if (typeof cell.v === 'number') cell.t = 'n'
|
|
|
+ else if (typeof cell.v === 'boolean') cell.t = 'b'
|
|
|
else if (cell.v instanceof Date) {
|
|
|
- cell.t = "n";
|
|
|
- cell.z = XLSX.SSF._table[14];
|
|
|
- cell.v = datenum(cell.v);
|
|
|
- } else cell.t = "s";
|
|
|
+ cell.t = 'n'
|
|
|
+ cell.z = XLSX.SSF._table[14]
|
|
|
+ cell.v = datenum(cell.v)
|
|
|
+ } else cell.t = 's'
|
|
|
|
|
|
- ws[cell_ref] = cell;
|
|
|
+ ws[cell_ref] = cell
|
|
|
}
|
|
|
}
|
|
|
- if (range.s.c < 10000000) ws["!ref"] = XLSX.utils.encode_range(range);
|
|
|
- return ws;
|
|
|
+ if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range)
|
|
|
+ return ws
|
|
|
}
|
|
|
|
|
|
function Workbook() {
|
|
|
- if (!(this instanceof Workbook)) return new Workbook();
|
|
|
- this.SheetNames = [];
|
|
|
- this.Sheets = {};
|
|
|
+ if (!(this instanceof Workbook)) return new Workbook()
|
|
|
+ this.SheetNames = []
|
|
|
+ this.Sheets = {}
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
+ 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
|
|
|
}
|
|
|
|
|
|
export function export_table_to_excel(id) {
|
|
|
- var theTable = document.getElementById(id);
|
|
|
- var oo = generateArray(theTable);
|
|
|
- var ranges = oo[1];
|
|
|
+ var theTable = document.getElementById(id)
|
|
|
+ var oo = generateArray(theTable)
|
|
|
+ var ranges = oo[1]
|
|
|
|
|
|
/* original data */
|
|
|
- var data = oo[0];
|
|
|
- var ws_name = "SheetJS";
|
|
|
+ var data = oo[0]
|
|
|
+ var ws_name = 'SheetJS'
|
|
|
|
|
|
var wb = new Workbook(),
|
|
|
- ws = sheet_from_array_of_arrays(data);
|
|
|
+ ws = sheet_from_array_of_arrays(data)
|
|
|
|
|
|
/* add ranges to worksheet */
|
|
|
// ws['!cols'] = ['apple', 'banan'];
|
|
|
- ws["!merges"] = ranges;
|
|
|
+ ws['!merges'] = ranges
|
|
|
|
|
|
/* add worksheet to workbook */
|
|
|
- wb.SheetNames.push(ws_name);
|
|
|
- wb.Sheets[ws_name] = ws;
|
|
|
+ wb.SheetNames.push(ws_name)
|
|
|
+ wb.Sheets[ws_name] = ws
|
|
|
|
|
|
var wbout = XLSX.write(wb, {
|
|
|
- bookType: "xlsx",
|
|
|
+ bookType: 'xlsx',
|
|
|
bookSST: false,
|
|
|
- type: "binary",
|
|
|
- });
|
|
|
+ type: 'binary',
|
|
|
+ })
|
|
|
|
|
|
saveAs(
|
|
|
new Blob([s2ab(wbout)], {
|
|
|
- type: "application/octet-stream",
|
|
|
+ type: 'application/octet-stream',
|
|
|
}),
|
|
|
- "test.xlsx"
|
|
|
- );
|
|
|
+ 'test.xlsx'
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
export function export_json_to_excel({
|
|
@@ -157,26 +158,26 @@ export function export_json_to_excel({
|
|
|
filename,
|
|
|
merges = [],
|
|
|
autoWidth = true,
|
|
|
- bookType = "xlsx",
|
|
|
+ bookType = 'xlsx',
|
|
|
} = {}) {
|
|
|
/* original data */
|
|
|
- filename = filename || "excel-list";
|
|
|
- data = [...data];
|
|
|
- data.unshift(header);
|
|
|
+ filename = filename || 'excel-list'
|
|
|
+ data = [...data]
|
|
|
+ data.unshift(header)
|
|
|
|
|
|
for (let i = multiHeader.length - 1; i > -1; i--) {
|
|
|
- data.unshift(multiHeader[i]);
|
|
|
+ data.unshift(multiHeader[i])
|
|
|
}
|
|
|
|
|
|
- var ws_name = "Sheet1";
|
|
|
+ var ws_name = 'Sheet1'
|
|
|
var wb = new Workbook(),
|
|
|
- ws = sheet_from_array_of_arrays(data);
|
|
|
+ ws = sheet_from_array_of_arrays(data)
|
|
|
|
|
|
if (merges.length > 0) {
|
|
|
- if (!ws["!merges"]) ws["!merges"] = [];
|
|
|
+ if (!ws['!merges']) ws['!merges'] = []
|
|
|
merges.forEach((item) => {
|
|
|
- ws["!merges"].push(XLSX.utils.decode_range(item));
|
|
|
- });
|
|
|
+ ws['!merges'].push(XLSX.utils.decode_range(item))
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
if (autoWidth) {
|
|
@@ -187,44 +188,161 @@ export function export_json_to_excel({
|
|
|
if (val == null) {
|
|
|
return {
|
|
|
wch: 10,
|
|
|
- };
|
|
|
+ }
|
|
|
} else if (val.toString().charCodeAt(0) > 255) {
|
|
|
/*再判断是否为中文*/
|
|
|
return {
|
|
|
wch: val.toString().length * 2,
|
|
|
- };
|
|
|
+ }
|
|
|
} else {
|
|
|
return {
|
|
|
wch: val.toString().length,
|
|
|
- };
|
|
|
+ }
|
|
|
}
|
|
|
})
|
|
|
- );
|
|
|
+ )
|
|
|
/*以第一行为初始值*/
|
|
|
- let result = colWidth[0];
|
|
|
+ let result = colWidth[0]
|
|
|
for (let i = 1; i < colWidth.length; i++) {
|
|
|
for (let j = 0; j < colWidth[i].length; j++) {
|
|
|
- if (result[j]["wch"] < colWidth[i][j]["wch"]) {
|
|
|
- result[j]["wch"] = colWidth[i][j]["wch"];
|
|
|
+ if (result[j]['wch'] < colWidth[i][j]['wch']) {
|
|
|
+ result[j]['wch'] = colWidth[i][j]['wch']
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- ws["!cols"] = result;
|
|
|
+ ws['!cols'] = result
|
|
|
}
|
|
|
|
|
|
/* add worksheet to workbook */
|
|
|
- wb.SheetNames.push(ws_name);
|
|
|
- wb.Sheets[ws_name] = ws;
|
|
|
+ wb.SheetNames.push(ws_name)
|
|
|
+ wb.Sheets[ws_name] = ws
|
|
|
|
|
|
var wbout = XLSX.write(wb, {
|
|
|
bookType: bookType,
|
|
|
bookSST: false,
|
|
|
- type: "binary",
|
|
|
- });
|
|
|
+ type: 'binary',
|
|
|
+ })
|
|
|
saveAs(
|
|
|
new Blob([s2ab(wbout)], {
|
|
|
- type: "application/octet-stream",
|
|
|
+ type: 'application/octet-stream',
|
|
|
}),
|
|
|
`${filename}.${bookType}`
|
|
|
- );
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+function devideGroup(cellName) {
|
|
|
+ const stringArray = cellName.split('')
|
|
|
+ const length = stringArray.length
|
|
|
+ let index = 0
|
|
|
+ for (let i = 0; i < length; i++) {
|
|
|
+ if (isNaN(parseInt(stringArray[i]))) {
|
|
|
+ index += stringArray[i].charCodeAt(0) - 'A'.charCodeAt(0) + i * 26
|
|
|
+ } else {
|
|
|
+ return {
|
|
|
+ columnIndex: index,
|
|
|
+ rowIndex: Number(stringArray.slice(i).join('')) - 1,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export function exportToExcel(table, tableName, fileName, headerRowNumber = 1) {
|
|
|
+ try {
|
|
|
+ // 设置了列的fixed属性后会有两个table元素,导出数据会重复,需要去掉一个table
|
|
|
+ const fixedTable = table.querySelector('.el-table__fixed')
|
|
|
+ fixedTable && table.removeChild(fixedTable)
|
|
|
+ // 自定义的表头里包含筛选,直接导出会把筛选的下拉数据也写到表头单元格里,需要先去掉筛选弹出框
|
|
|
+ const tableHeaderCellPopovers = table.querySelectorAll(
|
|
|
+ '.table-header-cell-popover'
|
|
|
+ )
|
|
|
+ tableHeaderCellPopovers.forEach((node) => {
|
|
|
+ if (node.querySelector('.el-popover')) {
|
|
|
+ node.removeChild(node.querySelector('.el-popover'))
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // 生成要导出的xlsx数据,raw: true表示不使用excel的格式解析,输出为纯文本,sheet设置xlsx这一页的标题
|
|
|
+ const tableBook = XLSX.utils.table_to_book(table, {
|
|
|
+ raw: true,
|
|
|
+ sheet: tableName,
|
|
|
+ })
|
|
|
+ // 计算每一列的单元格的最大宽度(包含表头),单元格的key为'A12'、'AA2'等,和excel里一致
|
|
|
+ const xlsxDatas = tableBook.Sheets[tableName]
|
|
|
+ const columnWidths: any = []
|
|
|
+ for (const cellName in xlsxDatas) {
|
|
|
+ if (
|
|
|
+ !['!rows', '!cols', '!fullref', '!ref', '!merges'].includes(cellName)
|
|
|
+ ) {
|
|
|
+ const { columnIndex, rowIndex } = devideGroup(cellName) as any
|
|
|
+ const cellWidth = Math.max(
|
|
|
+ ...xlsxDatas[cellName].v
|
|
|
+ .toString()
|
|
|
+ .split('\n')
|
|
|
+ .map((cellRow) =>
|
|
|
+ cellRow.split('').reduce((pre, curr) => {
|
|
|
+ const letterSize = curr.charCodeAt(0) > 255 ? 2 : 1
|
|
|
+ return pre + letterSize
|
|
|
+ }, 0)
|
|
|
+ )
|
|
|
+ )
|
|
|
+ if (
|
|
|
+ (!columnWidths[columnIndex] && cellWidth > 0) ||
|
|
|
+ cellWidth > columnWidths[columnIndex]
|
|
|
+ ) {
|
|
|
+ columnWidths[columnIndex] = cellWidth
|
|
|
+ }
|
|
|
+ let cellStyle: any = {
|
|
|
+ alignment: {
|
|
|
+ horizontal: 'center',
|
|
|
+ vertical: 'center',
|
|
|
+ wrapText: true,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ if (rowIndex < headerRowNumber) {
|
|
|
+ const borderStyle = {
|
|
|
+ style: 'medium',
|
|
|
+ color: {
|
|
|
+ rgb: 'FFFFFF',
|
|
|
+ },
|
|
|
+ }
|
|
|
+ cellStyle = {
|
|
|
+ ...cellStyle,
|
|
|
+ border: {
|
|
|
+ top: borderStyle,
|
|
|
+ right: borderStyle,
|
|
|
+ bottom: borderStyle,
|
|
|
+ left: borderStyle,
|
|
|
+ },
|
|
|
+ font: {
|
|
|
+ color: {
|
|
|
+ rgb: 'FFFFFF',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ fill: {
|
|
|
+ fgColor: {
|
|
|
+ rgb: '3366FF',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ cellStyle.alignment.horizontal = 'left'
|
|
|
+ }
|
|
|
+ xlsxDatas[cellName].s = cellStyle
|
|
|
+ }
|
|
|
+ }
|
|
|
+ xlsxDatas['!cols'] = columnWidths.map((width) => ({
|
|
|
+ wch: width + 2,
|
|
|
+ }))
|
|
|
+ const tableWrite = XLSX.write(tableBook, {
|
|
|
+ bookType: 'xlsx',
|
|
|
+ bookSST: true,
|
|
|
+ type: 'buffer',
|
|
|
+ cellStyles: true,
|
|
|
+ })
|
|
|
+ saveAs(
|
|
|
+ new Blob([tableWrite], { type: 'application/octet-stream' }),
|
|
|
+ fileName
|
|
|
+ )
|
|
|
+ } catch (error: any) {
|
|
|
+ ElMessage.error(error.message)
|
|
|
+ }
|
|
|
}
|