export-to-exceljs-util 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -65,7 +65,7 @@ const data = [
65
65
  const fileName = "测试数据.xlsx";
66
66
 
67
67
  // 其他信息(可选)
68
- const otherInfo = null;
68
+ const otherInfo = '注释:这里是一些其他信息';
69
69
 
70
70
  // 创建 Excel 导出实例
71
71
  const excelExporter = new ExcelExporter(columns, data, fileName, otherInfo);
package/defaultExport.js CHANGED
@@ -20,7 +20,7 @@ const borderStyle = {
20
20
  right: { style: "thin" },
21
21
  };
22
22
  export default class DefaultExport {
23
- constructor(columns, data, filename = "export.xlsx", describe = []) {
23
+ constructor(columns, data, filename = "export.xlsx", describe = "") {
24
24
  this.columns = columns;
25
25
  this.data = data;
26
26
  this.filename = filename;
@@ -180,19 +180,33 @@ export default class DefaultExport {
180
180
 
181
181
  generateDescribe(worksheet) {
182
182
  if (this.describe) {
183
- // 定义开始的位置
184
- const startCell = this.data.length + 7;
185
- const endCell = startCell + 9;
186
- worksheet.mergeCells(`A${startCell}:E${endCell}`);
183
+ // 定义开始和结束单元格的位置
184
+ let startCell = this.data.length + 7;
185
+ let endCell = 0;
187
186
 
188
187
  // 在表格底部加上文字解释
189
188
  let combinedText = this.describe;
189
+
190
+ // 合并单元格处理,根据描述信息的类型
191
+ if (typeof this.describe === "string") {
192
+ endCell = startCell + 10;
193
+ } else if (Array.isArray(this.describe)) {
194
+ endCell = startCell + this.describe.length;
195
+ combinedText = this.describe.join("\n");
196
+ } else {
197
+ endCell = startCell;
198
+ }
199
+ worksheet.mergeCells(`A${startCell}:H${endCell}`);
200
+
190
201
  const mergedCells = [
191
202
  `A${startCell}`,
192
203
  `B${startCell}`,
193
204
  `C${startCell}`,
194
205
  `D${startCell}`,
195
206
  `E${startCell}`,
207
+ `F${startCell}`,
208
+ `G${startCell}`,
209
+ `H${startCell}`,
196
210
  ];
197
211
 
198
212
  // 设置每个合并单元格的自动换行属性
package/index.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import { saveAs } from "file-saver";
2
2
  import DefaultExport from "./defaultExport.js";
3
- import { workerUrl, retainTitleAndKey } from "./utils/index";
4
-
5
- class ExcelExporter1 {
3
+ import { workerScript, retainTitleAndKey } from "./utils/index";
4
+ class ExcelExporter {
6
5
  constructor(columns, data, filename = "导出数据.xlsx", describe = []) {
7
6
  this.columns = columns;
8
7
  this.data = data;
@@ -10,27 +9,28 @@ class ExcelExporter1 {
10
9
  this.describe = describe;
11
10
  }
12
11
 
13
- async exportToExcel() {
14
- try {
15
- if (this.data.length > 10000) {
16
- await this.exportLargeDataSet();
17
- } else {
18
- await this.exportSmallDataSet();
19
- }
20
- } catch (error) {
21
- console.error("Export failed:", error);
12
+ exportToExcel() {
13
+ if (this.data.length > 10000) {
14
+ this.exportLargeDataSet();
15
+ } else {
16
+ this.exportSmallDataSet();
22
17
  }
23
18
  }
24
19
 
25
- async exportLargeDataSet() {
20
+ exportLargeDataSet() {
21
+ // 创建 Blob 对象
22
+ const blob = new Blob([workerScript()], { type: "text/javascript" });
23
+
24
+ // 创建指向 Blob 的 URL
25
+ const workerUrl = URL.createObjectURL(blob);
26
26
 
27
27
  // 创建 Web Worker 实例
28
28
  const writeBufferWorker = new Worker(workerUrl);
29
29
 
30
- // 格式化数组数据
30
+ // 处理数据格式,保留标题和键
31
31
  const formatColumns = retainTitleAndKey(this.columns);
32
32
 
33
- // 发送数据到 Web Worker
33
+ // Web Worker 实例发送数据
34
34
  writeBufferWorker.postMessage({
35
35
  columns: formatColumns,
36
36
  data: this.data,
@@ -38,24 +38,28 @@ class ExcelExporter1 {
38
38
  filename: this.filename,
39
39
  });
40
40
 
41
- // 监听 Web Worker 的消息
41
+ // 监听 Web Worker 实例的消息
42
42
  writeBufferWorker.onmessage = (e) => {
43
+ // 下载文件
43
44
  const { buffer, filename } = e.data;
44
45
  const blob = new Blob([buffer], { type: "application/octet-stream" });
45
- // 下载文件
46
46
  saveAs(blob, filename);
47
+
47
48
  // 释放对象 URL
48
49
  URL.revokeObjectURL(workerUrl);
50
+
49
51
  // 终止 Web Worker
50
52
  writeBufferWorker.terminate();
51
53
  };
52
54
 
53
55
  writeBufferWorker.onerror = (error) => {
54
56
  console.error("Worker error:", error);
57
+ URL.revokeObjectURL(workerUrl);
58
+ writeBufferWorker.terminate();
55
59
  };
56
60
  }
57
61
 
58
- async exportSmallDataSet() {
62
+ exportSmallDataSet() {
59
63
  const defaultExport = new DefaultExport(
60
64
  this.columns,
61
65
  this.data,
@@ -66,4 +70,4 @@ class ExcelExporter1 {
66
70
  }
67
71
  }
68
72
 
69
- export default ExcelExporter1;
73
+ export default ExcelExporter;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "export-to-exceljs-util",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "使用exceljs导出excel文件",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/utils/index.js CHANGED
@@ -1,221 +1,221 @@
1
1
  export function retainTitleAndKey(items) {
2
- return items.map((item) => {
3
- // 如果项目是一个数组,递归调用这个函数
4
- if (Array.isArray(item)) {
5
- return retainTitleAndKey(item);
6
- }
7
- // 如果项目是一个对象,处理 title, key 和 children 属性
8
- if (typeof item === "object" && item !== null) {
9
- // 创建一个新对象,只包含 title 和 key 属性
10
- let newItem = {
11
- title: item.title,
12
- key: item.key,
13
- };
14
- // 如果存在 children 属性,递归处理它
15
- if (item.children && Array.isArray(item.children)) {
16
- newItem.children = retainTitleAndKey(item.children);
2
+ return items.map((item) => {
3
+ // 如果项目是一个数组,递归调用这个函数
4
+ if (Array.isArray(item)) {
5
+ return retainTitleAndKey(item);
17
6
  }
18
- return newItem;
19
- }
20
- // 如果项目既不是数组也不是对象,直接返回它
21
- return item;
22
- });
23
- }
24
-
25
- function getworkerUrl() {
26
- const workerScript = `
27
- importScripts("https://cdn.bootcdn.net/ajax/libs/exceljs/4.4.0/exceljs.min.js");
28
- const fontStyle = {
29
- name: "Arial",
30
- size: 10,
31
- bold: true, // 设置文字加粗
32
- color: { argb: "FF000000" },
33
- };
34
- const alignmentStyle = (vertical = "middle", horizontal = "center") => {
35
- return {
36
- vertical,
37
- horizontal,
38
- };
39
- };
40
-
41
- const borderStyle = {
42
- top: { style: "thin" },
43
- left: { style: "thin" },
44
- bottom: { style: "thin" },
45
- right: { style: "thin" },
46
- };
47
-
48
- function generateHeaders(worksheet, columns, rowIndex = 1, colIndexStart = 1, maxDepth = null) {
49
- let maxRowIndex = rowIndex;
50
- let colIndex = colIndexStart;
51
-
52
- // 计算整个表头的最大深度(用于单级表头行合并)
53
- if (maxDepth === null) {
54
- maxDepth = getMaxDepth(columns);
55
- }
56
-
57
- columns.forEach((column) => {
58
- const currentRowIndex = rowIndex;
59
- const currentColIndex = colIndex;
60
-
61
- // 计算列的跨度和行的跨度
62
- const colSpan = getColSpan(column);
63
- const rowSpan = getRowSpan(column, maxDepth - rowIndex + 1);
64
-
65
- // 设置表头单元格值并应用样式
66
- const cell = worksheet.getCell(currentRowIndex, currentColIndex);
67
- cell.value = column.title;
68
- cell.alignment = alignmentStyle();
69
- cell.border = borderStyle;
70
- cell.font = fontStyle;
71
- cell.fill = {
72
- type: "pattern",
73
- pattern: "solid",
74
- fgColor: { argb: "87CEEB" },
75
- };
76
-
77
- // 合并单元格处理
78
- if (colSpan > 1) {
79
- worksheet.mergeCells(
80
- currentRowIndex,
81
- currentColIndex,
82
- currentRowIndex,
83
- currentColIndex + colSpan - 1
84
- );
85
- }
86
-
87
- // 处理跨行合并的情况
88
- if (rowSpan > 1) {
89
- worksheet.mergeCells(
90
- currentRowIndex,
91
- currentColIndex,
92
- currentRowIndex + rowSpan - 1,
93
- currentColIndex
94
- );
95
- }
96
-
97
- // 处理子列
98
- if (column.children && column.children.length > 0) {
99
- const childMaxRowIndex = generateHeaders(
100
- worksheet,
101
- column.children,
102
- currentRowIndex + 1,
103
- currentColIndex,
104
- maxDepth
105
- );
106
- maxRowIndex = Math.max(maxRowIndex, childMaxRowIndex);
107
- } else {
108
- maxRowIndex = Math.max(maxRowIndex, currentRowIndex + rowSpan - 1);
109
- }
110
-
111
- colIndex += colSpan;
112
- });
113
-
114
- return maxRowIndex;
115
- }
116
-
117
- function getColSpan(column) {
118
- if (!column.children || column.children.length === 0) {
119
- return 1;
120
- }
121
- return column.children.reduce((sum, child) => sum + getColSpan(child), 0);
7
+ // 如果项目是一个对象,处理 title, key 和 children 属性
8
+ if (typeof item === "object" && item !== null) {
9
+ // 创建一个新对象,只包含 title 和 key 属性
10
+ let newItem = {
11
+ title: item.title,
12
+ key: item.key,
13
+ };
14
+ // 如果存在 children 属性,递归处理它
15
+ if (item.children && Array.isArray(item.children)) {
16
+ newItem.children = retainTitleAndKey(item.children);
17
+ }
18
+ return newItem;
122
19
  }
123
-
124
- function getRowSpan(column, remainingDepth) {
125
- if (!column.children || column.children.length === 0) {
126
- return remainingDepth;
127
- }
128
- return 1;
129
- }
130
-
131
- function getMaxDepth(columns) {
132
- return columns.reduce((max, column) => {
133
- const depth = column.children ? 1 + getMaxDepth(column.children) : 1;
134
- return Math.max(max, depth);
135
- }, 1);
136
- }
137
-
138
- function fillData(worksheet, data, columns) {
139
- const rows = data.map((rowData) =>
140
- columns.flatMap((col) => extractValues(rowData, col))
141
- );
142
- worksheet.addRows(rows);
143
- }
144
-
145
- function autoFitColumns(worksheet) {
146
- worksheet.columns.forEach((column) => {
147
- let maxLength = 0;
148
- column.eachCell({ includeEmpty: true }, (cell) => {
149
- const columnLength = cell.value ? cell.value.toString().length : 10;
150
- if (columnLength > maxLength) {
151
- maxLength = columnLength;
152
- }
153
- });
154
- column.width = maxLength < 10 ? maxLength + 5 : maxLength;
155
- });
156
- }
157
-
158
- function generateDescribe(worksheet, describe, data) {
20
+ // 如果项目既不是数组也不是对象,直接返回它
21
+ return item;
22
+ });
23
+ }
24
+
25
+ export function workerScript() {
26
+ const workerScript = `
27
+ importScripts("https://cdn.bootcdn.net/ajax/libs/exceljs/4.4.0/exceljs.min.js");
28
+ const fontStyle = {
29
+ name: "Arial",
30
+ size: 10,
31
+ bold: true, // 设置文字加粗
32
+ color: { argb: "FF000000" },
33
+ };
34
+ const alignmentStyle = (vertical = "middle", horizontal = "center") => {
35
+ return {
36
+ vertical,
37
+ horizontal,
38
+ };
39
+ };
40
+
41
+ const borderStyle = {
42
+ top: { style: "thin" },
43
+ left: { style: "thin" },
44
+ bottom: { style: "thin" },
45
+ right: { style: "thin" },
46
+ };
47
+
48
+ function generateHeaders(worksheet, columns, rowIndex = 1, colIndexStart = 1, maxDepth = null) {
49
+ let maxRowIndex = rowIndex;
50
+ let colIndex = colIndexStart;
51
+
52
+ // 计算整个表头的最大深度(用于单级表头行合并)
53
+ if (maxDepth === null) {
54
+ maxDepth = getMaxDepth(columns);
55
+ }
56
+
57
+ columns.forEach((column) => {
58
+ const currentRowIndex = rowIndex;
59
+ const currentColIndex = colIndex;
60
+
61
+ // 计算列的跨度和行的跨度
62
+ const colSpan = getColSpan(column);
63
+ const rowSpan = getRowSpan(column, maxDepth - rowIndex + 1);
64
+
65
+ // 设置表头单元格值并应用样式
66
+ const cell = worksheet.getCell(currentRowIndex, currentColIndex);
67
+ cell.value = column.title;
68
+ cell.alignment = alignmentStyle();
69
+ cell.border = borderStyle;
70
+ cell.font = fontStyle;
71
+ cell.fill = {
72
+ type: "pattern",
73
+ pattern: "solid",
74
+ fgColor: { argb: "87CEEB" },
75
+ };
76
+
77
+ // 合并单元格处理
78
+ if (colSpan > 1) {
79
+ worksheet.mergeCells(
80
+ currentRowIndex,
81
+ currentColIndex,
82
+ currentRowIndex,
83
+ currentColIndex + colSpan - 1
84
+ );
85
+ }
86
+
87
+ // 处理跨行合并的情况
88
+ if (rowSpan > 1) {
89
+ worksheet.mergeCells(
90
+ currentRowIndex,
91
+ currentColIndex,
92
+ currentRowIndex + rowSpan - 1,
93
+ currentColIndex
94
+ );
95
+ }
96
+
97
+ // 处理子列
98
+ if (column.children && column.children.length > 0) {
99
+ const childMaxRowIndex = generateHeaders(
100
+ worksheet,
101
+ column.children,
102
+ currentRowIndex + 1,
103
+ currentColIndex,
104
+ maxDepth
105
+ );
106
+ maxRowIndex = Math.max(maxRowIndex, childMaxRowIndex);
107
+ } else {
108
+ maxRowIndex = Math.max(maxRowIndex, currentRowIndex + rowSpan - 1);
109
+ }
110
+
111
+ colIndex += colSpan;
112
+ });
113
+
114
+ return maxRowIndex;
115
+ }
116
+
117
+ function getColSpan(column) {
118
+ if (!column.children || column.children.length === 0) {
119
+ return 1;
120
+ }
121
+ return column.children.reduce((sum, child) => sum + getColSpan(child), 0);
122
+ }
123
+
124
+ function getRowSpan(column, remainingDepth) {
125
+ if (!column.children || column.children.length === 0) {
126
+ return remainingDepth;
127
+ }
128
+ return 1;
129
+ }
130
+
131
+ function getMaxDepth(columns) {
132
+ return columns.reduce((max, column) => {
133
+ const depth = column.children ? 1 + getMaxDepth(column.children) : 1;
134
+ return Math.max(max, depth);
135
+ }, 1);
136
+ }
137
+
138
+ function fillData(worksheet, data, columns) {
139
+ const rows = data.map((rowData) =>
140
+ columns.flatMap((col) => extractValues(rowData, col))
141
+ );
142
+ worksheet.addRows(rows);
143
+ }
144
+
145
+ function autoFitColumns(worksheet) {
146
+ worksheet.columns.forEach((column) => {
147
+ let maxLength = 0;
148
+ column.eachCell({ includeEmpty: true }, (cell) => {
149
+ const columnLength = cell.value ? cell.value.toString().length : 10;
150
+ if (columnLength > maxLength) {
151
+ maxLength = columnLength;
152
+ }
153
+ });
154
+ column.width = maxLength < 10 ? maxLength + 5 : maxLength;
155
+ });
156
+ }
157
+
158
+ function generateDescribe(worksheet, describe, data) {
159
159
  if (describe) {
160
- console.log('describe',describe);
161
- // 定义开始的位置
162
- const startCell = data.length + 7;
163
- const endCell = startCell + 9;
164
-
160
+ // 定义开始和结束单元格的位置
161
+ let startCell = data.length + 7;
162
+ let endCell = 0;
163
+ // 在表格底部加上文字解释
164
+ let combinedText = describe;
165
+ if (typeof describe === "string") {
166
+ endCell = startCell + 10;
167
+ } else if (Array.isArray(describe)) {
168
+ endCell = startCell + describe.length;
169
+ combinedText = describe.join("\\n");
170
+ } else {
171
+ endCell = startCell;
172
+ }
165
173
  // 合并单元格的范围
166
174
  const mergeStart = 'A' + startCell;
167
- const mergeEnd = 'E' + endCell;
168
- worksheet.mergeCells(mergeStart + ':' + mergeEnd);
169
-
170
- // 在表格底部加上文字解释
171
- let combinedText = describe.join('\\n');
175
+ const mergeEnd = 'H' + endCell;
172
176
  const mergedCells = [
173
- 'A' + startCell,
174
- 'B' + startCell,
175
- 'C' + startCell,
176
- 'D' + startCell,
177
- 'E' + startCell,
177
+ 'A' + startCell,
178
+ 'B' + startCell,
179
+ 'C' + startCell,
180
+ 'D' + startCell,
181
+ 'E' + startCell,
182
+ 'F' + startCell,
183
+ 'G' + startCell,
184
+ 'H' + startCell
178
185
  ];
179
-
180
186
  // 设置每个合并单元格的自动换行属性
181
187
  mergedCells.forEach(function(cell) {
182
- const currentCell = worksheet.getCell(cell);
183
- currentCell.value = combinedText;
184
- currentCell.font = fontStyle;
185
- currentCell.alignment = {
186
- vertical: "top",
187
- horizontal: "left",
188
- wrapText: true // 设置自动换行
189
- };
188
+ const currentCell = worksheet.getCell(cell);
189
+ currentCell.value = combinedText;
190
+ currentCell.font = fontStyle;
191
+ currentCell.alignment = {
192
+ vertical: "top",
193
+ horizontal: "left",
194
+ wrapText: true // 设置自动换行
195
+ };
190
196
  });
191
197
  worksheet.getCell(mergeStart).border = borderStyle;
192
198
  }
193
- }
194
-
195
- function extractValues(rowData, column) {
196
- if (column.children && column.children.length > 0) {
197
- return column.children.flatMap((child) => extractValues(rowData, child));
198
- } else {
199
- return [rowData[column.key]];
200
- }
201
- }
202
- self.onmessage = async function (e) {
203
- const { data, columns, describe, filename } = e.data;
204
- const workbook = new ExcelJS.Workbook();
205
- const worksheet = workbook.addWorksheet("Sheet1");
206
- generateHeaders(worksheet, columns);
207
- fillData(worksheet, data, columns);
208
- generateDescribe(worksheet, describe, data);
209
- const buffer = await workbook.xlsx.writeBuffer();
210
- self.postMessage({ buffer, filename });
211
- const endTime = performance.now();
212
- };`;
213
-
214
- // 创建 Blob 对象
215
- const blob = new Blob([workerScript], { type: "text/javascript" });
216
-
217
- // 创建指向 Blob 的 URL
218
- return URL.createObjectURL(blob);
219
- }
220
-
221
- export const workerUrl = getworkerUrl();
199
+ }
200
+
201
+ function extractValues(rowData, column) {
202
+ if (column.children && column.children.length > 0) {
203
+ return column.children.flatMap((child) => extractValues(rowData, child));
204
+ } else {
205
+ return [rowData[column.key]];
206
+ }
207
+ }
208
+ self.onmessage = async function (e) {
209
+ const { data, columns, describe, filename } = e.data;
210
+ const workbook = new ExcelJS.Workbook();
211
+ const worksheet = workbook.addWorksheet("Sheet1");
212
+ generateHeaders(worksheet, columns);
213
+ fillData(worksheet, data, columns);
214
+ generateDescribe(worksheet, describe, data);
215
+ const buffer = await workbook.xlsx.writeBuffer();
216
+ self.postMessage({ buffer, filename });
217
+ const endTime = performance.now();
218
+ };`;
219
+ return workerScript
220
+ }
221
+