UNPKG

tav-ui

Version:
696 lines (693 loc) 22.6 kB
import ExcelJS from 'exceljs'; import XEUtils from 'xe-utils'; import '../../../locales/index2.mjs'; import { useMessage } from '../../../hooks/web/useMessage2.mjs'; import { SELECT_COMPONENTS, ACTION_COLUMNS } from './const2.mjs'; import { tavI18n } from '../../../locales/transfer2.mjs'; let vxetable; let defaultHeaderHeight = 26; let defaultHeaderBackgroundColor = "f5f6f7"; let defaultHeaderFontSize = 11; let defaultCellHeight = 24; let defaultCellFontColor = "1f2329"; let defaultCellFontSize = 10; let defaultCellBorderStyle = "thin"; let defaultCellBorderColor = "dee0e3"; let defaultFooterHeight = defaultHeaderHeight; let defaultFooterBackgroundColor = defaultHeaderBackgroundColor; let defaultFooterFontSize = defaultHeaderFontSize; let defaultDescriptionHeight = 40; let defaultDescriptionBackgroundColor = "fff258"; let defaultDescriptionFontSize = 14; let defaultDescriptionAlign = "left"; const { createMessage } = useMessage(); function getCellLabel(column, cellValue) { if (cellValue) { if (column.type === "seq") { return XEUtils.toValueString(cellValue); } switch (column.cellType) { case "string": return XEUtils.toValueString(cellValue); case "number": if (!isNaN(cellValue)) { return Number(cellValue); } break; default: if (cellValue.length < 12 && !isNaN(cellValue)) { return Number(cellValue); } break; } } return cellValue; } function getFooterData(opts, footerData) { const { footerFilterMethod } = opts; return footerFilterMethod ? footerData.filter((items, index) => footerFilterMethod({ items, $rowIndex: index })) : footerData; } function getFooterCellValue($table, opts, rows, column) { const cellValue = getCellLabel(column, rows[$table.getVMColumnIndex(column)]); return cellValue; } function getValidColumn(column) { const { childNodes } = column; const isColGroup = childNodes && childNodes.length; if (isColGroup) { return getValidColumn(childNodes[0]); } return column; } function setExcelRowHeight(excelRow, height, type) { if (height) { if (type === "header") { excelRow.height = Math.min(XEUtils.floor(height * 0.75, 12), defaultHeaderHeight); } else if (type === "footer") { excelRow.height = Math.min(XEUtils.floor(height * 0.75, 12), defaultFooterHeight); } else { excelRow.height = Math.min(XEUtils.floor(height * 0.75, 12), defaultCellHeight); } } } function setExcelCellStyle(excelCell, align) { excelCell.protection = { locked: false }; excelCell.alignment = { vertical: "middle", horizontal: align || "left" }; } function getDefaultBorderStyle() { return { top: { style: defaultCellBorderStyle, color: { argb: defaultCellBorderColor } }, left: { style: defaultCellBorderStyle, color: { argb: defaultCellBorderColor } }, bottom: { style: defaultCellBorderStyle, color: { argb: defaultCellBorderColor } }, right: { style: defaultCellBorderStyle, color: { argb: defaultCellBorderColor } } }; } function deleteNotRequiredColumns(columns) { const handler = (columns2) => columns2.filter((column) => column.type && !SELECT_COMPONENTS.includes(column.type) || column.field && !ACTION_COLUMNS.includes(column.field)); return handler(columns); } function setDescription(sheet, useStyle, fileDescription) { sheet.spliceRows(1, 0, []); sheet._rows[0].height = defaultDescriptionHeight; const mergeColRange = []; sheet.columns.forEach((column) => { mergeColRange.push(column.letter); }); sheet.mergeCells(`${mergeColRange[0]}1`, `${mergeColRange[mergeColRange.length - 1]}1`); const cell = sheet.getCell(`${mergeColRange[0]}1`); cell.value = fileDescription; setExcelCellStyle(cell, defaultDescriptionAlign || allAlign); if (useStyle) { Object.assign(cell, { font: { size: defaultDescriptionFontSize, color: { argb: defaultCellFontColor }, bold: true }, fill: { type: "pattern", pattern: "solid", fgColor: { argb: defaultDescriptionBackgroundColor } }, border: getDefaultBorderStyle() }); } } function setSeq(sheet, useStyle, fileDescription, headerList, contentList, footerList) { const headerDeep = headerList.length; const seqValues = []; for (let i = 0; i < sheet._rows.length; i++) { if (i < (fileDescription ? headerDeep + 1 : headerDeep)) { seqValues.push(""); } else if (footerList.length > 0 && i > (fileDescription ? headerDeep + 1 : headerDeep) + contentList.length - 1) { seqValues.push(""); } else { seqValues.push(fileDescription ? i - headerDeep : i - headerDeep + 1); } } sheet.spliceColumns(1, 0, seqValues); sheet._columns[0].eachCell((cell) => { if (useStyle) { setExcelCellStyle(cell, defaultDescriptionAlign || allAlign); Object.assign(cell, { font: { size: defaultCellFontSize, color: { argb: defaultCellFontColor } }, border: getDefaultBorderStyle() }); } }); const mergeColRange = []; sheet.columns.forEach((column) => { mergeColRange.push(column.letter); }); sheet.mergeCells(`${mergeColRange[0]}${fileDescription ? 1 + 1 : 1}`, `${mergeColRange[0]}${fileDescription ? headerDeep + 1 : headerDeep}`); const firstCell = sheet.getCell(`${mergeColRange[0]}${fileDescription ? 1 + 1 : 1}`); firstCell.value = tavI18n("Tav.tablePro.columns.1"); setExcelCellStyle(firstCell, defaultDescriptionAlign || allAlign); if (useStyle) { Object.assign(firstCell, { font: { size: defaultHeaderFontSize, color: { argb: defaultCellFontColor }, bold: true }, fill: { type: "pattern", pattern: "solid", fgColor: { argb: defaultHeaderBackgroundColor } }, border: getDefaultBorderStyle() }); } if (fileDescription) { Reflect.deleteProperty(sheet._merges, `${mergeColRange[0]}1`); sheet.mergeCells(`${mergeColRange[0]}1`, `${mergeColRange[mergeColRange.length - 1 - 1]}1`); const cell = sheet.getCell(`${mergeColRange[0]}1`); cell.value = fileDescription; setExcelCellStyle(cell, defaultDescriptionAlign || allAlign); if (useStyle) { Object.assign(cell, { font: { size: defaultDescriptionFontSize, color: { argb: defaultCellFontColor }, bold: true }, fill: { type: "pattern", pattern: "solid", fgColor: { argb: defaultDescriptionBackgroundColor } }, border: getDefaultBorderStyle() }); } } } function setFooter(sheet, useStyle, fileSeq, $table, options, fileDescription, headerList, contentList, _footerData) { const headerDeep = headerList.length; const totalRowCount = sheet._rows.length; const { footerData } = $table.getTableData(); const footers = getFooterData(options, _footerData || footerData); const fillFooterTitle = (row, value) => { if (fileSeq) { row.getCell(1).value = value; } }; for (let i = totalRowCount - footers.length; i < totalRowCount; i++) { const idx = (fileDescription ? headerDeep + 1 : headerDeep) + contentList.length; const row = sheet.getRow(i + 1); fillFooterTitle(row, footers[i - idx][0]); row.eachCell((excelCell) => { setExcelCellStyle(excelCell, defaultDescriptionAlign || allAlign); if (useStyle) { Object.assign(excelCell, { font: { size: defaultFooterFontSize, color: { argb: defaultCellFontColor }, bold: true }, fill: { type: "pattern", pattern: "solid", fgColor: { argb: defaultFooterBackgroundColor } }, border: getDefaultBorderStyle() }); } }); } } async function exportXLSX(params) { const msgKey = "xlsx"; const { modal, t } = vxetable; const { $table, options, columns: _columns, colgroups, datas } = params; const { props, reactData } = $table; const { headerAlign: allHeaderAlign, align: allAlign2, footerAlign: allFooterAlign } = props; const { rowHeight } = reactData; const { message, sheetName, isHeader, isFooter, isMerge, isColgroup, original, useStyle, sheetMethod, fileDescription, fileSeq, backupColumns, exportModalClose, fileStyles } = options; const columns = deleteNotRequiredColumns(_columns); defaultHeaderHeight = fileStyles.headerHeight ?? defaultHeaderHeight; defaultHeaderBackgroundColor = fileStyles.headerBackgroundColor ?? defaultHeaderBackgroundColor; defaultHeaderFontSize = fileStyles.headerFontSize ?? defaultHeaderFontSize; defaultCellHeight = fileStyles.cellHeight ?? defaultCellHeight; defaultCellFontColor = fileStyles.cellFontColor ?? defaultCellFontColor; defaultCellFontSize = fileStyles.cellFontSize ?? defaultCellFontSize; defaultCellBorderStyle = fileStyles.cellBorderStyle ?? defaultCellBorderStyle; defaultCellBorderColor = fileStyles.cellBorderColor ?? defaultCellBorderColor; defaultFooterHeight = fileStyles.footerHeight ?? defaultHeaderHeight; defaultFooterBackgroundColor = fileStyles.footerBackgroundColor ?? defaultHeaderBackgroundColor; defaultFooterFontSize = fileStyles.footerFontSize ?? defaultHeaderFontSize; defaultDescriptionHeight = fileStyles.descriptionHeight ?? defaultDescriptionHeight; defaultDescriptionBackgroundColor = fileStyles.descriptionBackgroundColor ?? defaultDescriptionBackgroundColor; defaultDescriptionFontSize = fileStyles.descriptionFontSize ?? defaultDescriptionFontSize; defaultDescriptionAlign = fileStyles.descriptionAlign ?? defaultDescriptionAlign; const showMsg = message !== false; const mergeCells = $table.getMergeCells(); const colList = []; const footList = []; const sheetCols = []; const sheetMerges = []; let beforeRowCount = 0; const colHead = {}; const _footerData = $table.props.footerMethod ? $table.props.footerMethod({ columns, data: datas.map((d) => d._row) }) : null; columns.forEach((column) => { const { id, field, renderWidth, width, minWidth } = column; colHead[id] = original ? field : column.getTitle(); sheetCols.push({ key: id, width: XEUtils.ceil((renderWidth || width || minWidth) / 8, 1) }); }); if (isHeader) { if (isColgroup && colgroups) { colgroups.forEach((cols, rIndex) => { const groupHead = {}; columns.forEach((column) => { groupHead[column.id] = null; }); cols.forEach((column) => { const { _colSpan, _rowSpan } = column; const validColumn = getValidColumn(column); const columnIndex = columns.indexOf(validColumn); const title = column.getTitle ? column.getTitle() : validColumn.parentId ? $table.getColumnById(validColumn.parentId).title : validColumn.field; groupHead[validColumn.id] = original ? validColumn.field : title; if (_colSpan > 1 || _rowSpan > 1) { sheetMerges.push({ s: { r: rIndex + 1, c: columnIndex + 1 }, e: { r: rIndex + _rowSpan - 1 + 1, c: columnIndex + _colSpan - 1 + 1 } }); } }); colList.push(groupHead); }); } else { colList.push(colHead); } beforeRowCount += colList.length; } if (isMerge) { mergeCells.forEach((mergeItem) => { const { row: mergeRowIndex, rowspan: mergeRowspan, col: mergeColIndex, colspan: mergeColspan } = mergeItem; sheetMerges.push({ s: { r: mergeRowIndex + beforeRowCount + 1, c: mergeColIndex + 1 }, e: { r: mergeRowIndex + beforeRowCount + mergeRowspan - 1 + 1, c: mergeColIndex + mergeColspan - 1 + 1 } }); }); } const rowList = datas.map((item) => { const rest = {}; columns.forEach((column) => { let cellValue = item[column.id]; if (column.params && column.params.cellContent) { cellValue = column.params.cellContent({ row: item._row || {} }) || ""; } rest[column.id] = getCellLabel(column, cellValue); }); return rest; }); beforeRowCount += rowList.length; if (isFooter) { const { footerData } = $table.getTableData(); const footers = getFooterData(options, _footerData || footerData); const mergeFooterItems = $table.getMergeFooterItems(); if (isMerge) { mergeFooterItems.forEach((mergeItem) => { const { row: mergeRowIndex, rowspan: mergeRowspan, col: mergeColIndex, colspan: mergeColspan } = mergeItem; sheetMerges.push({ s: { r: mergeRowIndex + beforeRowCount + 1, c: mergeColIndex + 1 }, e: { r: mergeRowIndex + beforeRowCount + mergeRowspan - 1 + 1, c: mergeColIndex + mergeColspan - 1 + 1 } }); }); } footers.forEach((rows) => { const item = {}; columns.forEach((column) => { item[column.id] = getFooterCellValue($table, options, rows, column) || ""; }); footList.push(item); }); } const exportMethod = () => { const workbook = new ExcelJS.Workbook(); const sheet = workbook.addWorksheet(sheetName); workbook.creator = "i7eo"; sheet.views = [{}]; sheet.columns = sheetCols; if (isHeader) { sheet.addRows(colList).forEach((excelRow) => { if (useStyle) { setExcelRowHeight(excelRow, rowHeight, "header"); } excelRow.eachCell((excelCell) => { const excelCol = sheet.getColumn(excelCell.col); const column = $table.getColumnById(excelCol.key); const { headerAlign, align } = column; setExcelCellStyle(excelCell, headerAlign || align || allHeaderAlign || allAlign2); if (useStyle) { Object.assign(excelCell, { font: { size: defaultHeaderFontSize, color: { argb: defaultCellFontColor }, bold: true }, fill: { type: "pattern", pattern: "solid", fgColor: { argb: defaultHeaderBackgroundColor } }, border: getDefaultBorderStyle() }); } }); }); } sheet.addRows(rowList).forEach((excelRow) => { if (useStyle) { setExcelRowHeight(excelRow, rowHeight); } excelRow.eachCell((excelCell) => { const excelCol = sheet.getColumn(excelCell.col); const column = $table.getColumnById(excelCol.key); const { align } = column; setExcelCellStyle(excelCell, align || allAlign2); if (useStyle) { Object.assign(excelCell, { font: { size: defaultCellFontSize, color: { argb: defaultCellFontColor } }, border: getDefaultBorderStyle() }); } if (column.params && column.params.cellFormat) { excelCell.numFmt = column.params.cellFormat(excelCell); } else { excelCell.numFmt = "@"; } }); }); if (isFooter) { sheet.addRows(footList).forEach((excelRow) => { if (useStyle) { setExcelRowHeight(excelRow, rowHeight, "footer"); } excelRow.eachCell((excelCell) => { const excelCol = sheet.getColumn(excelCell.col); const column = $table.getColumnById(excelCol.key); const { footerAlign, align } = column; setExcelCellStyle(excelCell, footerAlign || align || allFooterAlign || allAlign2); if (useStyle) { Object.assign(excelCell, { font: { size: defaultFooterFontSize, color: { argb: defaultCellFontColor } }, fill: { type: "pattern", pattern: "solid", fgColor: { argb: defaultFooterBackgroundColor } }, border: getDefaultBorderStyle() }); } if (column.params && column.params.cellFormat) { excelCell.numFmt = column.params.cellFormat(excelCell); } else { excelCell.numFmt = "@"; } }); }); } if (useStyle && sheetMethod) { sheetMethod({ options, workbook, worksheet: sheet, columns, colgroups, datas, $table }); } fileDescription && setDescription(sheet, useStyle, fileDescription); fileSeq && setSeq(sheet, useStyle, fileDescription, colList, rowList, footList); footList.length > 0 && setFooter(sheet, useStyle, fileSeq, $table, options, fileDescription, colList, rowList, _footerData); sheetMerges.forEach(({ s, e }) => { if (fileDescription) { if (fileSeq) { sheet.mergeCells(s.r + 1, s.c + 1, e.r + 1, e.c + 1); } else { sheet.mergeCells(s.r + 1, s.c, e.r + 1, e.c); } } else { if (fileSeq) { sheet.mergeCells(s.r, s.c + 1, e.r, e.c + 1); } else { sheet.mergeCells(s.r, s.c, e.r, e.c); } } }); workbook.xlsx.writeBuffer().then((buffer) => { const blob = new Blob([buffer], { type: "application/octet-stream" }); downloadFile(blob, options, $table); if (showMsg && modal) { modal.close(msgKey); } $table.loadColumn(backupColumns.value); exportModalClose(); }); }; if (showMsg && modal) { createMessage.loading(tavI18n("Tav.tablePro.export.6"), 2).then(() => exportMethod(), () => { }); } else { exportMethod(); } } function downloadFile(blob, options) { const { modal, t } = vxetable; const { message, filename, type } = options; const showMsg = message !== false; if (window.Blob) { if (navigator.msSaveBlob) { ; navigator.msSaveBlob(blob, `${filename}.${type}`); } else { const linkElem = document.createElement("a"); linkElem.target = "_blank"; linkElem.download = `${filename}.${type}`; linkElem.href = URL.createObjectURL(blob); document.body.appendChild(linkElem); linkElem.click(); document.body.removeChild(linkElem); } } else { if (showMsg && modal) { createMessage.error(t("vxe.error.notExp")); } } } function checkImportData(tableFields, fields) { return fields.some((field) => tableFields.indexOf(field) > -1); } function importError(params) { const { modal, t } = vxetable; const { $table, options } = params; const { internalData } = $table; const { _importReject } = internalData; const showMsg = options.message !== false; if (showMsg && modal) { createMessage.error(t("vxe.error.impFields")); } if (_importReject) { _importReject({ status: false }); } } function importXLSX(params) { const { modal, t } = vxetable; const { $table, columns, options, file } = params; const { internalData } = $table; const { _importResolve } = internalData; const showMsg = options.message !== false; const fileReader = new FileReader(); fileReader.onerror = () => { importError(params); }; fileReader.onload = (evnt) => { const tableFields = []; columns.forEach((column) => { const field = column.field; if (field) { tableFields.push(field); } }); const workbook = new ExcelJS.Workbook(); const readerTarget = evnt.target; if (readerTarget) { workbook.xlsx.load(readerTarget.result).then((wb) => { const firstSheet = wb.worksheets[0]; if (firstSheet) { const sheetValues = firstSheet.getSheetValues(); const fieldIndex = XEUtils.findIndexOf(sheetValues, (list) => list && list.length > 0); const fields = sheetValues[fieldIndex]; const status = checkImportData(tableFields, fields); if (status) { const records = sheetValues.slice(fieldIndex).map((list) => { const item = {}; list.forEach((cellValue, cIndex) => { item[fields[cIndex]] = cellValue; }); const record = {}; tableFields.forEach((field) => { record[field] = XEUtils.isUndefined(item[field]) ? null : item[field]; }); return record; }); $table.createData(records).then((data) => { let loadRest; if (options.mode === "insert") { loadRest = $table.insertAt(data, -1); } else { loadRest = $table.reloadData(data); } return loadRest.then(() => { if (_importResolve) { _importResolve({ status: true }); } }); }); if (showMsg && modal) { createMessage.success(t("vxe.table.impSuccess")); } } else { importError(params); } } else { importError(params); } }); } else { importError(params); } }; fileReader.readAsArrayBuffer(file); } function handleImportEvent(params) { if (params.options.type === "xlsx") { importXLSX(params); return false; } } function handleExportEvent(params) { if (params.options.type === "xlsx") { exportXLSX(params); return false; } } const VXETablePluginExportXLSX = { install(vxetablecore) { const { setup, interceptor } = vxetablecore; vxetable = vxetablecore; setup({ export: { types: { xlsx: 0 } } }); interceptor.mixin({ "event.import": handleImportEvent, "event.export": handleExportEvent }); } }; if (typeof window !== "undefined" && window.VXETable && window.VXETable.use) { window.VXETable.use(VXETablePluginExportXLSX); } export { VXETablePluginExportXLSX, VXETablePluginExportXLSX as default }; //# sourceMappingURL=vxe-table-plugin-export2.mjs.map