Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/assets/guide/en/export/excel.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,12 @@ const excelOption = {
};
await downloadExcel(await exportVTableToExcel(tableInstance, excelOption));
```

### equestIdleCallback

`@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`.

```js
const excelOption = {};
await downloadExcel(await exportVTableToExcel(tableInstance, excelOption, true));
```
9 changes: 9 additions & 0 deletions docs/assets/guide/zh/export/excel.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,12 @@ const excelOption = {
};
await downloadExcel(await exportVTableToExcel(tableInstance, excelOption));
```

### equestIdleCallback

`@visactor/vtable-export`使用`exceljs`库作为导出 Excel 文件的工具,如果需要解决导出对页面性能影响,可以设置`requestIdleCallback`的启用参数`optimization`

```js
const excelOption = {};
await downloadExcel(await exportVTableToExcel(tableInstance, excelOption, true));
```
79 changes: 60 additions & 19 deletions packages/vtable-export/src/excel/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,15 @@ export type ExportVTableToExcelOptions = {
skipImageExportCellType?: SkipImageExportCellType[];
};

export async function exportVTableToExcel(tableInstance: IVTable, options?: ExportVTableToExcelOptions) {
function requestIdleCallbackPromise(options?: IdleRequestOptions) {
return new Promise<IdleDeadline>((resolve) => {
requestIdleCallback((deadline) => {
resolve(deadline);
}, options);
});
}

export async function exportVTableToExcel(tableInstance: IVTable, options?: ExportVTableToExcelOptions, optimization = false) {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('sheet1');
worksheet.properties.defaultRowHeight = 40;
Expand All @@ -46,30 +54,63 @@ export async function exportVTableToExcel(tableInstance: IVTable, options?: Expo
const mergeCells = [];
const mergeCellSet = new Set();

for (let col = minCol; col <= maxCol; col++) {
const colWith = tableInstance.getColWidth(col);
columns[col] = { width: colWith / 6 };
for (let row = minRow; row <= maxRow; row++) {
if (col === minCol) {
const rowHeight = tableInstance.getRowHeight(row);
const worksheetRow = worksheet.getRow(row + 1);
// worksheetRow.height = rowHeight * 0.75;
worksheetRow.height = rowHeight;
}
const SLICE_SIZE = 100;
let currentRow = minRow;

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

const cellRange = tableInstance.getCellRange(col, row);
if (cellRange.start.col !== cellRange.end.col || cellRange.start.row !== cellRange.end.row) {
const key = `${cellRange.start.col},${cellRange.start.row}:${cellRange.end.col},${cellRange.end.row}}`;
if (!mergeCellSet.has(key)) {
mergeCellSet.add(key);
mergeCells.push(cellRange);
await addCell(col, row, tableInstance, worksheet, workbook, options);

const cellRange = tableInstance.getCellRange(col, row);
if (cellRange.start.col !== cellRange.end.col || cellRange.start.row !== cellRange.end.row) {
const key = `${cellRange.start.col},${cellRange.start.row}:${cellRange.end.col},${cellRange.end.row}`;
if (!mergeCellSet.has(key)) {
mergeCellSet.add(key);
mergeCells.push(cellRange);
}
}
}
}
currentRow = endRow + 1;
}
}

if (currentRow > maxRow) {
resolve();
} else {
let nextDeadline: IdleDeadline | undefined;
if (optimization) {
nextDeadline = await requestIdleCallbackPromise()
}
await processSlice(nextDeadline);
resolve();
}
});
}

await new Promise<void>(async resolve => {
let deadline: IdleDeadline | undefined;
if (optimization) {
deadline = await requestIdleCallbackPromise()
}
await processSlice(deadline);
resolve();
});

worksheet.columns = columns;
mergeCells.forEach(mergeCell => {
worksheet.mergeCells(
Expand Down