@simplysm/excel 13.0.69 → 13.0.71
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 +19 -516
- package/dist/excel-cell.d.ts +28 -28
- package/dist/excel-cell.d.ts.map +1 -1
- package/dist/excel-cell.js +24 -24
- package/dist/excel-cell.js.map +1 -1
- package/dist/excel-col.d.ts +4 -4
- package/dist/excel-col.d.ts.map +1 -1
- package/dist/excel-col.js +3 -3
- package/dist/excel-row.d.ts +3 -3
- package/dist/excel-row.d.ts.map +1 -1
- package/dist/excel-row.js +2 -2
- package/dist/excel-workbook.d.ts +23 -23
- package/dist/excel-workbook.d.ts.map +1 -1
- package/dist/excel-workbook.js +15 -15
- package/dist/excel-workbook.js.map +1 -1
- package/dist/excel-worksheet.d.ts +32 -32
- package/dist/excel-worksheet.d.ts.map +1 -1
- package/dist/excel-worksheet.js +32 -32
- package/dist/excel-worksheet.js.map +1 -1
- package/dist/excel-wrapper.d.ts +7 -7
- package/dist/excel-wrapper.js +7 -7
- package/dist/excel-wrapper.js.map +1 -1
- package/dist/types.d.ts +16 -16
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/excel-utils.d.ts +23 -23
- package/dist/utils/excel-utils.d.ts.map +1 -1
- package/dist/utils/excel-utils.js +25 -25
- package/dist/utils/excel-utils.js.map +1 -1
- package/dist/utils/zip-cache.d.ts +6 -6
- package/dist/xml/excel-xml-content-type.d.ts +2 -2
- package/dist/xml/excel-xml-drawing.d.ts +2 -2
- package/dist/xml/excel-xml-relationship.d.ts +2 -2
- package/dist/xml/excel-xml-relationship.js +1 -1
- package/dist/xml/excel-xml-relationship.js.map +1 -1
- package/dist/xml/excel-xml-shared-string.d.ts +2 -2
- package/dist/xml/excel-xml-style.d.ts +2 -2
- package/dist/xml/excel-xml-style.js +6 -6
- package/dist/xml/excel-xml-style.js.map +1 -1
- package/dist/xml/excel-xml-unknown.d.ts +2 -2
- package/dist/xml/excel-xml-workbook.d.ts +2 -2
- package/dist/xml/excel-xml-workbook.js +1 -1
- package/dist/xml/excel-xml-workbook.js.map +1 -1
- package/dist/xml/excel-xml-worksheet.d.ts +6 -6
- package/dist/xml/excel-xml-worksheet.d.ts.map +1 -1
- package/dist/xml/excel-xml-worksheet.js +9 -8
- package/dist/xml/excel-xml-worksheet.js.map +1 -1
- package/package.json +6 -5
- package/src/excel-cell.ts +35 -35
- package/src/excel-col.ts +4 -4
- package/src/excel-row.ts +3 -3
- package/src/excel-workbook.ts +30 -30
- package/src/excel-worksheet.ts +47 -47
- package/src/excel-wrapper.ts +18 -18
- package/src/index.ts +3 -3
- package/src/types.ts +15 -17
- package/src/utils/excel-utils.ts +38 -38
- package/src/utils/zip-cache.ts +6 -6
- package/src/xml/excel-xml-content-type.ts +3 -3
- package/src/xml/excel-xml-drawing.ts +2 -2
- package/src/xml/excel-xml-relationship.ts +3 -3
- package/src/xml/excel-xml-shared-string.ts +2 -2
- package/src/xml/excel-xml-style.ts +11 -11
- package/src/xml/excel-xml-unknown.ts +2 -2
- package/src/xml/excel-xml-workbook.ts +5 -5
- package/src/xml/excel-xml-worksheet.ts +44 -43
- package/tests/excel-cell.spec.ts +448 -0
- package/tests/excel-col.spec.ts +112 -0
- package/tests/excel-row.spec.ts +71 -0
- package/tests/excel-workbook.spec.ts +219 -0
- package/tests/excel-worksheet.spec.ts +389 -0
- package/tests/excel-wrapper.spec.ts +296 -0
- package/tests/fixtures/logo.png +0 -0
- package/tests/fixtures//354/264/210/352/270/260/355/231/224.xlsx +0 -0
- package/tests/image-insert.spec.ts +190 -0
- package/tests/utils/excel-utils.spec.ts +242 -0
package/src/excel-cell.ts
CHANGED
|
@@ -18,23 +18,23 @@ import { ExcelXmlStyle as ExcelXmlStyleClass } from "./xml/excel-xml-style";
|
|
|
18
18
|
import { ExcelUtils } from "./utils/excel-utils";
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
* Class representing an Excel cell.
|
|
22
|
+
* Provides value read/write, formula, style, and cell merge functionality.
|
|
23
23
|
*
|
|
24
24
|
* @remarks
|
|
25
|
-
* ##
|
|
25
|
+
* ## Async Method Design
|
|
26
26
|
*
|
|
27
|
-
* `getVal()`, `setVal()`
|
|
28
|
-
* -
|
|
29
|
-
* -
|
|
30
|
-
* -
|
|
31
|
-
* -
|
|
27
|
+
* Why all cell methods like `getVal()`, `setVal()` are `async`:
|
|
28
|
+
* - Only the XML needed for the cell type is selectively loaded
|
|
29
|
+
* - String cell: loads SharedStrings.xml
|
|
30
|
+
* - Number cell: does not load SharedStrings
|
|
31
|
+
* - Styled cell: loads Styles.xml
|
|
32
32
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
33
|
+
* Since the cell to be read cannot be known in advance, a synchronous design is not feasible.
|
|
34
|
+
* A synchronous design would require preloading all XML, causing memory issues with large files.
|
|
35
35
|
*/
|
|
36
36
|
export class ExcelCell {
|
|
37
|
-
/**
|
|
37
|
+
/** Cell address (0-based row/column index) */
|
|
38
38
|
readonly addr: ExcelAddressPoint;
|
|
39
39
|
|
|
40
40
|
constructor(
|
|
@@ -48,7 +48,7 @@ export class ExcelCell {
|
|
|
48
48
|
|
|
49
49
|
//#region Value Methods
|
|
50
50
|
|
|
51
|
-
/**
|
|
51
|
+
/** Set formula on cell (undefined: remove formula) */
|
|
52
52
|
async setFormula(val: string | undefined): Promise<void> {
|
|
53
53
|
if (val === undefined) {
|
|
54
54
|
await this._deleteCell(this.addr);
|
|
@@ -60,13 +60,13 @@ export class ExcelCell {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
/**
|
|
63
|
+
/** Return cell formula */
|
|
64
64
|
async getFormula(): Promise<string | undefined> {
|
|
65
65
|
const wsData = await this._getWsData();
|
|
66
66
|
return wsData.getCellFormula(this.addr);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
/**
|
|
69
|
+
/** Set cell value (undefined: delete cell) */
|
|
70
70
|
async setVal(val: ExcelValueType): Promise<void> {
|
|
71
71
|
if (val === undefined) {
|
|
72
72
|
await this._deleteCell(this.addr);
|
|
@@ -102,12 +102,12 @@ export class ExcelCell {
|
|
|
102
102
|
});
|
|
103
103
|
} else {
|
|
104
104
|
throw new Error(
|
|
105
|
-
`[${ExcelUtils.stringifyAddr(this.addr)}]
|
|
105
|
+
`[${ExcelUtils.stringifyAddr(this.addr)}] Unsupported type: ${typeof val}`,
|
|
106
106
|
);
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
/**
|
|
110
|
+
/** Return cell value */
|
|
111
111
|
async getVal(): Promise<ExcelValueType> {
|
|
112
112
|
const wsData = await this._getWsData();
|
|
113
113
|
const cellVal = wsData.getCellVal(this.addr);
|
|
@@ -121,7 +121,7 @@ export class ExcelCell {
|
|
|
121
121
|
const ssId = numParseInt(cellVal);
|
|
122
122
|
if (ssId == null) {
|
|
123
123
|
throw new Error(
|
|
124
|
-
`[${ExcelUtils.stringifyAddr(this.addr)}] SharedString ID
|
|
124
|
+
`[${ExcelUtils.stringifyAddr(this.addr)}] Failed to parse SharedString ID: ${cellVal}`,
|
|
125
125
|
);
|
|
126
126
|
}
|
|
127
127
|
return ssData.getStringById(ssId);
|
|
@@ -135,10 +135,10 @@ export class ExcelCell {
|
|
|
135
135
|
return parseFloat(cellVal);
|
|
136
136
|
} else if (cellType === "e") {
|
|
137
137
|
throw new Error(
|
|
138
|
-
`[${ExcelUtils.stringifyAddr(this.addr)}]
|
|
138
|
+
`[${ExcelUtils.stringifyAddr(this.addr)}] Cell type analysis failed: cell contains error value (${cellVal})`,
|
|
139
139
|
);
|
|
140
140
|
} else {
|
|
141
|
-
// cellType === undefined:
|
|
141
|
+
// cellType === undefined: number or date/time type
|
|
142
142
|
const cellStyleId = wsData.getCellStyleId(this.addr);
|
|
143
143
|
if (cellStyleId === undefined) {
|
|
144
144
|
return parseFloat(cellVal);
|
|
@@ -162,7 +162,7 @@ export class ExcelCell {
|
|
|
162
162
|
const numFmtIdNum = numParseInt(numFmtId);
|
|
163
163
|
if (numFmtIdNum == null) {
|
|
164
164
|
throw new Error(
|
|
165
|
-
`[${ExcelUtils.stringifyAddr(this.addr)}]
|
|
165
|
+
`[${ExcelUtils.stringifyAddr(this.addr)}] Failed to parse numFmtId: ${numFmtId}`,
|
|
166
166
|
);
|
|
167
167
|
}
|
|
168
168
|
numFmt = ExcelUtils.convertNumFmtIdToName(numFmtIdNum);
|
|
@@ -177,7 +177,7 @@ export class ExcelCell {
|
|
|
177
177
|
const dateNum = numParseFloat(cellVal);
|
|
178
178
|
if (dateNum == null) {
|
|
179
179
|
throw new Error(
|
|
180
|
-
`[${ExcelUtils.stringifyAddr(this.addr)}]
|
|
180
|
+
`[${ExcelUtils.stringifyAddr(this.addr)}] Failed to parse date number: ${cellVal}`,
|
|
181
181
|
);
|
|
182
182
|
}
|
|
183
183
|
const tick = ExcelUtils.convertNumberToTimeTick(dateNum);
|
|
@@ -197,11 +197,11 @@ export class ExcelCell {
|
|
|
197
197
|
//#region Merge Methods
|
|
198
198
|
|
|
199
199
|
/**
|
|
200
|
-
*
|
|
201
|
-
* @param r
|
|
202
|
-
* @param c
|
|
200
|
+
* Merge cells from current cell to the specified end coordinates
|
|
201
|
+
* @param r End row index of merge (0-based)
|
|
202
|
+
* @param c End column index of merge (0-based)
|
|
203
203
|
* @example
|
|
204
|
-
* // A1
|
|
204
|
+
* // Called from cell A1, merges range A1:C3 (3 rows x 3 columns)
|
|
205
205
|
* await ws.cell(0, 0).merge(2, 2);
|
|
206
206
|
*/
|
|
207
207
|
async merge(r: number, c: number): Promise<void> {
|
|
@@ -213,33 +213,33 @@ export class ExcelCell {
|
|
|
213
213
|
|
|
214
214
|
//#region Style Methods
|
|
215
215
|
|
|
216
|
-
/**
|
|
216
|
+
/** Return cell style ID */
|
|
217
217
|
async getStyleId(): Promise<string | undefined> {
|
|
218
218
|
const wsData = await this._getWsData();
|
|
219
219
|
return wsData.getCellStyleId(this.addr);
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
/**
|
|
222
|
+
/** Set cell style ID */
|
|
223
223
|
async setStyleId(styleId: string | undefined): Promise<void> {
|
|
224
224
|
const wsData = await this._getWsData();
|
|
225
225
|
wsData.setCellStyleId(this.addr, styleId);
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
/**
|
|
229
|
-
*
|
|
230
|
-
* @param opts
|
|
231
|
-
* @param opts.background
|
|
232
|
-
* @param opts.border
|
|
233
|
-
* @param opts.horizontalAlign
|
|
234
|
-
* @param opts.verticalAlign
|
|
235
|
-
* @param opts.numberFormat
|
|
229
|
+
* Set cell style
|
|
230
|
+
* @param opts Style options
|
|
231
|
+
* @param opts.background Background color (ARGB format, 8-digit hex. e.g. "FFFF0000")
|
|
232
|
+
* @param opts.border Border position array (e.g. ["left", "right", "top", "bottom"])
|
|
233
|
+
* @param opts.horizontalAlign Horizontal alignment ("left", "center", "right")
|
|
234
|
+
* @param opts.verticalAlign Vertical alignment ("top", "center", "bottom")
|
|
235
|
+
* @param opts.numberFormat Number format ("number", "DateOnly", "DateTime", "Time", "string")
|
|
236
236
|
*/
|
|
237
237
|
async setStyle(opts: ExcelStyleOptions): Promise<void> {
|
|
238
238
|
const style: ExcelStyle = {};
|
|
239
239
|
|
|
240
240
|
if (opts.background != null) {
|
|
241
241
|
if (!/^[0-9A-F]{8}$/i.test(opts.background)) {
|
|
242
|
-
throw new Error("
|
|
242
|
+
throw new Error("Invalid color format. (Format: 00000000: alpha(reversed)+rgb)");
|
|
243
243
|
}
|
|
244
244
|
style.background = opts.background;
|
|
245
245
|
}
|
package/src/excel-col.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { ExcelCell } from "./excel-cell";
|
|
|
3
3
|
import type { ExcelXmlWorksheet } from "./xml/excel-xml-worksheet";
|
|
4
4
|
import type { ZipCache } from "./utils/zip-cache";
|
|
5
5
|
|
|
6
|
-
/**
|
|
6
|
+
/** Class representing a column in an Excel worksheet. Provides cell access and column width configuration. */
|
|
7
7
|
export class ExcelCol {
|
|
8
8
|
private readonly _cellMap = new Map<number, ExcelCell>();
|
|
9
9
|
|
|
@@ -13,7 +13,7 @@ export class ExcelCol {
|
|
|
13
13
|
private readonly _c: number,
|
|
14
14
|
) {}
|
|
15
15
|
|
|
16
|
-
/**
|
|
16
|
+
/** Return cell at the given row index (0-based) */
|
|
17
17
|
cell(r: number): ExcelCell {
|
|
18
18
|
return this._cellMap.getOrCreate(
|
|
19
19
|
r,
|
|
@@ -21,7 +21,7 @@ export class ExcelCol {
|
|
|
21
21
|
);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/**
|
|
24
|
+
/** Return all cells in the column */
|
|
25
25
|
async getCells(): Promise<ExcelCell[]> {
|
|
26
26
|
const result: ExcelCell[] = [];
|
|
27
27
|
const wsData = await this._getWsData();
|
|
@@ -34,7 +34,7 @@ export class ExcelCol {
|
|
|
34
34
|
return result;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
/**
|
|
37
|
+
/** Set column width */
|
|
38
38
|
async setWidth(size: number): Promise<void> {
|
|
39
39
|
const wsData = await this._getWsData();
|
|
40
40
|
wsData.setColWidth((this._c + 1).toString(), size.toString());
|
package/src/excel-row.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { ExcelCell } from "./excel-cell";
|
|
|
3
3
|
import type { ExcelXmlWorksheet } from "./xml/excel-xml-worksheet";
|
|
4
4
|
import type { ZipCache } from "./utils/zip-cache";
|
|
5
5
|
|
|
6
|
-
/**
|
|
6
|
+
/** Class representing a row in an Excel worksheet. Provides cell access functionality. */
|
|
7
7
|
export class ExcelRow {
|
|
8
8
|
private readonly _cellMap = new Map<number, ExcelCell>();
|
|
9
9
|
|
|
@@ -13,7 +13,7 @@ export class ExcelRow {
|
|
|
13
13
|
private readonly _r: number,
|
|
14
14
|
) {}
|
|
15
15
|
|
|
16
|
-
/**
|
|
16
|
+
/** Return cell at the given column index (0-based) */
|
|
17
17
|
cell(c: number): ExcelCell {
|
|
18
18
|
return this._cellMap.getOrCreate(
|
|
19
19
|
c,
|
|
@@ -21,7 +21,7 @@ export class ExcelRow {
|
|
|
21
21
|
);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/**
|
|
24
|
+
/** Return all cells in the row */
|
|
25
25
|
async getCells(): Promise<ExcelCell[]> {
|
|
26
26
|
const result: ExcelCell[] = [];
|
|
27
27
|
const wsData = await this._getWsData();
|
package/src/excel-workbook.ts
CHANGED
|
@@ -8,32 +8,32 @@ import { ExcelXmlWorkbook as ExcelXmlWorkbookClass } from "./xml/excel-xml-workb
|
|
|
8
8
|
import { ExcelXmlWorksheet as ExcelXmlWorksheetClass } from "./xml/excel-xml-worksheet";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Excel
|
|
11
|
+
* Excel workbook processing class
|
|
12
12
|
*
|
|
13
13
|
* @remarks
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* This class internally manages ZIP resources.
|
|
15
|
+
* Resources must be released after use.
|
|
16
16
|
*
|
|
17
|
-
* ##
|
|
17
|
+
* ## Async Design
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
* - ZIP
|
|
21
|
-
* - SharedStrings
|
|
22
|
-
* -
|
|
19
|
+
* Adopts a Lazy Loading architecture for memory efficiency with large Excel files:
|
|
20
|
+
* - XML inside the ZIP is read and parsed only at the point of access
|
|
21
|
+
* - Large XML such as SharedStrings and Styles is loaded only when needed
|
|
22
|
+
* - Memory efficient even in extreme cases (e.g., reading a single number cell from a file with 1TB SharedStrings)
|
|
23
23
|
*
|
|
24
24
|
* @example
|
|
25
25
|
* ```typescript
|
|
26
|
-
* // await using
|
|
26
|
+
* // Using await using (recommended)
|
|
27
27
|
* await using wb = new ExcelWorkbook(bytes);
|
|
28
28
|
* const ws = await wb.getWorksheet(0);
|
|
29
|
-
* // ...
|
|
30
|
-
* //
|
|
29
|
+
* // ... perform operations
|
|
30
|
+
* // Resources automatically released at scope exit
|
|
31
31
|
*
|
|
32
|
-
* //
|
|
32
|
+
* // Or using try-finally
|
|
33
33
|
* const wb = new ExcelWorkbook(bytes);
|
|
34
34
|
* try {
|
|
35
35
|
* const ws = await wb.getWorksheet(0);
|
|
36
|
-
* // ...
|
|
36
|
+
* // ... perform operations
|
|
37
37
|
* } finally {
|
|
38
38
|
* await wb.close();
|
|
39
39
|
* }
|
|
@@ -45,7 +45,7 @@ export class ExcelWorkbook {
|
|
|
45
45
|
private _isClosed = false;
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
|
-
* @param arg
|
|
48
|
+
* @param arg Existing Excel file data (Blob or Uint8Array). Creates a new workbook if omitted.
|
|
49
49
|
*/
|
|
50
50
|
constructor(arg?: Blob | Bytes) {
|
|
51
51
|
if (arg != null) {
|
|
@@ -80,18 +80,18 @@ export class ExcelWorkbook {
|
|
|
80
80
|
|
|
81
81
|
private _ensureNotClosed(): void {
|
|
82
82
|
if (this._isClosed) {
|
|
83
|
-
throw new Error("ExcelWorkbook
|
|
83
|
+
throw new Error("ExcelWorkbook is already closed. Cannot use after calling close().");
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
/**
|
|
87
|
+
/** Return all worksheet names in the workbook */
|
|
88
88
|
async getWorksheetNames(): Promise<string[]> {
|
|
89
89
|
this._ensureNotClosed();
|
|
90
90
|
const wbData = (await this.zipCache.get("xl/workbook.xml")) as ExcelXmlWorkbook;
|
|
91
91
|
return wbData.sheetNames;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
/**
|
|
94
|
+
/** Create and return a new worksheet */
|
|
95
95
|
async createWorksheet(name: string): Promise<ExcelWorksheet> {
|
|
96
96
|
this._ensureNotClosed();
|
|
97
97
|
// Workbook
|
|
@@ -124,7 +124,7 @@ export class ExcelWorkbook {
|
|
|
124
124
|
return ws;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
/**
|
|
127
|
+
/** Look up a worksheet by name or index (0-based) */
|
|
128
128
|
async getWorksheet(nameOrIndex: string | number): Promise<ExcelWorksheet> {
|
|
129
129
|
this._ensureNotClosed();
|
|
130
130
|
const wbData = (await this.zipCache.get("xl/workbook.xml")) as ExcelXmlWorkbook;
|
|
@@ -135,9 +135,9 @@ export class ExcelWorkbook {
|
|
|
135
135
|
|
|
136
136
|
if (wsId === undefined) {
|
|
137
137
|
if (typeof nameOrIndex === "string") {
|
|
138
|
-
throw new Error(
|
|
138
|
+
throw new Error(`Cannot find sheet with name '${nameOrIndex}'.`);
|
|
139
139
|
} else {
|
|
140
|
-
throw new Error(`'${nameOrIndex}'
|
|
140
|
+
throw new Error(`Cannot find sheet at index '${nameOrIndex}'.`);
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -148,13 +148,13 @@ export class ExcelWorkbook {
|
|
|
148
148
|
const relData = (await this.zipCache.get("xl/_rels/workbook.xml.rels")) as ExcelXmlRelationship;
|
|
149
149
|
const targetFilePath = relData.getTargetByRelId(wsId);
|
|
150
150
|
if (targetFilePath == null) {
|
|
151
|
-
throw new Error(
|
|
151
|
+
throw new Error(`Cannot find sheet relationship information: rId${wsId}`);
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
//
|
|
154
|
+
// Extract filename directly instead of path.basename (browser compatibility)
|
|
155
155
|
const fileName = targetFilePath.split("/").pop();
|
|
156
156
|
if (fileName == null) {
|
|
157
|
-
throw new Error(
|
|
157
|
+
throw new Error(`Cannot extract sheet filename: ${targetFilePath}`);
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
const ws = new ExcelWorksheet(this.zipCache, wsId, fileName);
|
|
@@ -166,13 +166,13 @@ export class ExcelWorkbook {
|
|
|
166
166
|
|
|
167
167
|
//#region Export Methods
|
|
168
168
|
|
|
169
|
-
/**
|
|
169
|
+
/** Export workbook as byte array */
|
|
170
170
|
async getBytes(): Promise<Bytes> {
|
|
171
171
|
this._ensureNotClosed();
|
|
172
172
|
return this.zipCache.toBytes();
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
/**
|
|
175
|
+
/** Export workbook as Blob */
|
|
176
176
|
async getBlob(): Promise<Blob> {
|
|
177
177
|
this._ensureNotClosed();
|
|
178
178
|
const bytes = await this.zipCache.toBytes();
|
|
@@ -186,16 +186,16 @@ export class ExcelWorkbook {
|
|
|
186
186
|
//#region Lifecycle Methods
|
|
187
187
|
|
|
188
188
|
/**
|
|
189
|
-
*
|
|
189
|
+
* Release workbook resources
|
|
190
190
|
*
|
|
191
191
|
* @remarks
|
|
192
|
-
* ZIP
|
|
193
|
-
*
|
|
194
|
-
*
|
|
192
|
+
* Cleans up the ZIP reader and internal cache.
|
|
193
|
+
* The workbook instance cannot be used after this call.
|
|
194
|
+
* Safe to call on an already closed workbook (no-op).
|
|
195
195
|
*/
|
|
196
196
|
async close(): Promise<void> {
|
|
197
197
|
if (this._isClosed) {
|
|
198
|
-
return; //
|
|
198
|
+
return; // Ignore if already closed
|
|
199
199
|
}
|
|
200
200
|
this._isClosed = true;
|
|
201
201
|
this._wsMap.clear();
|