Skip to content

Commit 613a607

Browse files
authored
Merge pull request #3650 from yangdan8/develop
#3648 Improve the performance of exporting Excel
2 parents 49a2964 + b4837ac commit 613a607

3 files changed

Lines changed: 78 additions & 19 deletions

File tree

docs/assets/guide/en/export/excel.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,12 @@ const excelOption = {
137137
};
138138
await downloadExcel(await exportVTableToExcel(tableInstance, excelOption));
139139
```
140+
141+
### equestIdleCallback
142+
143+
`@visactor/vtable-export` uses the `exceljs` library as a tool for exporting Excel files. If you need tosolve the impact on page performance during the export process, you can set the `optimization` parameter to enable `requestIdleCallback`.
144+
145+
```js
146+
const excelOption = {};
147+
await downloadExcel(await exportVTableToExcel(tableInstance, excelOption, true));
148+
```

docs/assets/guide/zh/export/excel.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,12 @@ const excelOption = {
137137
};
138138
await downloadExcel(await exportVTableToExcel(tableInstance, excelOption));
139139
```
140+
141+
### equestIdleCallback
142+
143+
`@visactor/vtable-export`使用`exceljs`库作为导出 Excel 文件的工具,如果需要解决导出对页面性能影响,可以设置`requestIdleCallback`的启用参数`optimization`
144+
145+
```js
146+
const excelOption = {};
147+
await downloadExcel(await exportVTableToExcel(tableInstance, excelOption, true));
148+
```

packages/vtable-export/src/excel/index.ts

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,15 @@ export type ExportVTableToExcelOptions = {
3333
skipImageExportCellType?: SkipImageExportCellType[];
3434
};
3535

36-
export async function exportVTableToExcel(tableInstance: IVTable, options?: ExportVTableToExcelOptions) {
36+
function requestIdleCallbackPromise(options?: IdleRequestOptions) {
37+
return new Promise<IdleDeadline>((resolve) => {
38+
requestIdleCallback((deadline) => {
39+
resolve(deadline);
40+
}, options);
41+
});
42+
}
43+
44+
export async function exportVTableToExcel(tableInstance: IVTable, options?: ExportVTableToExcelOptions, optimization = false) {
3745
const workbook = new ExcelJS.Workbook();
3846
const worksheet = workbook.addWorksheet('sheet1');
3947
worksheet.properties.defaultRowHeight = 40;
@@ -46,30 +54,63 @@ export async function exportVTableToExcel(tableInstance: IVTable, options?: Expo
4654
const mergeCells = [];
4755
const mergeCellSet = new Set();
4856

49-
for (let col = minCol; col <= maxCol; col++) {
50-
const colWith = tableInstance.getColWidth(col);
51-
columns[col] = { width: colWith / 6 };
52-
for (let row = minRow; row <= maxRow; row++) {
53-
if (col === minCol) {
54-
const rowHeight = tableInstance.getRowHeight(row);
55-
const worksheetRow = worksheet.getRow(row + 1);
56-
// worksheetRow.height = rowHeight * 0.75;
57-
worksheetRow.height = rowHeight;
58-
}
57+
const SLICE_SIZE = 100;
58+
let currentRow = minRow;
5959

60-
await addCell(col, row, tableInstance, worksheet, workbook, options);
60+
function processSlice(deadline?: IdleDeadline) {
61+
return new Promise<void>(async resolve => {
62+
while (currentRow <= maxRow && (!optimization || (deadline?.timeRemaining() > 0))) {
63+
const endRow = Math.min(currentRow + SLICE_SIZE - 1, maxRow);
64+
for (let col = minCol; col <= maxCol; col++) {
65+
const colWidth = tableInstance.getColWidth(col);
66+
if (columns[col] === undefined) {
67+
columns[col] = { width: colWidth / 6 };
68+
}
69+
for (let row = currentRow; row <= endRow; row++) {
70+
if (col === minCol) {
71+
const rowHeight = tableInstance.getRowHeight(row);
72+
const worksheetRow = worksheet.getRow(row + 1);
73+
// worksheetRow.height = rowHeight * 0.75;
74+
worksheetRow.height = rowHeight;
75+
}
6176

62-
const cellRange = tableInstance.getCellRange(col, row);
63-
if (cellRange.start.col !== cellRange.end.col || cellRange.start.row !== cellRange.end.row) {
64-
const key = `${cellRange.start.col},${cellRange.start.row}:${cellRange.end.col},${cellRange.end.row}}`;
65-
if (!mergeCellSet.has(key)) {
66-
mergeCellSet.add(key);
67-
mergeCells.push(cellRange);
77+
await addCell(col, row, tableInstance, worksheet, workbook, options);
78+
79+
const cellRange = tableInstance.getCellRange(col, row);
80+
if (cellRange.start.col !== cellRange.end.col || cellRange.start.row !== cellRange.end.row) {
81+
const key = `${cellRange.start.col},${cellRange.start.row}:${cellRange.end.col},${cellRange.end.row}`;
82+
if (!mergeCellSet.has(key)) {
83+
mergeCellSet.add(key);
84+
mergeCells.push(cellRange);
85+
}
86+
}
87+
}
6888
}
89+
currentRow = endRow + 1;
6990
}
70-
}
91+
92+
if (currentRow > maxRow) {
93+
resolve();
94+
} else {
95+
let nextDeadline: IdleDeadline | undefined;
96+
if (optimization) {
97+
nextDeadline = await requestIdleCallbackPromise()
98+
}
99+
await processSlice(nextDeadline);
100+
resolve();
101+
}
102+
});
71103
}
72104

105+
await new Promise<void>(async resolve => {
106+
let deadline: IdleDeadline | undefined;
107+
if (optimization) {
108+
deadline = await requestIdleCallbackPromise()
109+
}
110+
await processSlice(deadline);
111+
resolve();
112+
});
113+
73114
worksheet.columns = columns;
74115
mergeCells.forEach(mergeCell => {
75116
worksheet.mergeCells(

0 commit comments

Comments
 (0)