@justybase/spreadsheet-tasks 1.3.3 → 2.1.0
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/CHANGELOG.md +63 -0
- package/README.md +151 -54
- package/browser/browser-spreadsheet.js +3044 -0
- package/browser/justybase-spreadsheet.min.js +36 -0
- package/dist/cjs/index.d.ts +559 -0
- package/dist/cjs/index.js +4971 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/index.js +4914 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/docs/API.md +166 -9
- package/docs/PACKAGING.md +32 -0
- package/docs/PUBLISHING.md +8 -1
- package/examples/basic-read.ts +2 -2
- package/examples/basic-write.ts +1 -1
- package/examples/datetime-widths.ts +1 -1
- package/examples/formats-verify.ts +1 -2
- package/examples/large-dataset.ts +2 -2
- package/examples/multiple-sheets.ts +1 -1
- package/examples/streaming-example.ts +3 -1
- package/examples/update-existing.ts +53 -0
- package/package.json +29 -14
- package/dist/BiffReaderWriter.d.ts +0 -44
- package/dist/BiffReaderWriter.d.ts.map +0 -1
- package/dist/BiffReaderWriter.js +0 -282
- package/dist/BiffReaderWriter.js.map +0 -1
- package/dist/BigBuffer.d.ts +0 -24
- package/dist/BigBuffer.d.ts.map +0 -1
- package/dist/BigBuffer.js +0 -120
- package/dist/BigBuffer.js.map +0 -1
- package/dist/ExcelReaderAbstract.d.ts +0 -17
- package/dist/ExcelReaderAbstract.d.ts.map +0 -1
- package/dist/ExcelReaderAbstract.js +0 -25
- package/dist/ExcelReaderAbstract.js.map +0 -1
- package/dist/Formats.d.ts +0 -34
- package/dist/Formats.d.ts.map +0 -1
- package/dist/Formats.js +0 -48
- package/dist/Formats.js.map +0 -1
- package/dist/ReaderFactory.d.ts +0 -6
- package/dist/ReaderFactory.d.ts.map +0 -1
- package/dist/ReaderFactory.js +0 -56
- package/dist/ReaderFactory.js.map +0 -1
- package/dist/XlsbReader.d.ts +0 -24
- package/dist/XlsbReader.d.ts.map +0 -1
- package/dist/XlsbReader.js +0 -186
- package/dist/XlsbReader.js.map +0 -1
- package/dist/XlsbWriter.d.ts +0 -80
- package/dist/XlsbWriter.d.ts.map +0 -1
- package/dist/XlsbWriter.js +0 -964
- package/dist/XlsbWriter.js.map +0 -1
- package/dist/XlsxReader.d.ts +0 -30
- package/dist/XlsxReader.d.ts.map +0 -1
- package/dist/XlsxReader.js +0 -341
- package/dist/XlsxReader.js.map +0 -1
- package/dist/XlsxWriter.d.ts +0 -51
- package/dist/XlsxWriter.d.ts.map +0 -1
- package/dist/XlsxWriter.js +0 -632
- package/dist/XlsxWriter.js.map +0 -1
- package/dist/index.d.ts +0 -10
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -29
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,4971 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
BiffReaderWriter: () => BiffReaderWriter,
|
|
34
|
+
BigBuffer: () => BigBuffer,
|
|
35
|
+
ExcelReaderAbstract: () => ExcelReaderAbstract,
|
|
36
|
+
F: () => F,
|
|
37
|
+
INVALID_SHEET_NAME_CHARS: () => INVALID_SHEET_NAME_CHARS,
|
|
38
|
+
ReaderFactory: () => ReaderFactory,
|
|
39
|
+
StreamingSheetState: () => StreamingSheetState,
|
|
40
|
+
XlsbReader: () => XlsbReader,
|
|
41
|
+
XlsbUpdater: () => XlsbUpdater,
|
|
42
|
+
XlsbWriter: () => XlsbWriter,
|
|
43
|
+
XlsxReader: () => XlsxReader,
|
|
44
|
+
XlsxUpdater: () => XlsxUpdater,
|
|
45
|
+
XlsxWriter: () => XlsxWriter,
|
|
46
|
+
applyHeaderWidths: () => applyHeaderWidths,
|
|
47
|
+
defaultColWidth: () => defaultColWidth,
|
|
48
|
+
getFormat: () => getFormat,
|
|
49
|
+
initColWidths: () => initColWidths,
|
|
50
|
+
isFormattedCell: () => isFormattedCell,
|
|
51
|
+
sanitizeSheetName: () => sanitizeSheetName,
|
|
52
|
+
unwrapCell: () => unwrapCell,
|
|
53
|
+
updateColWidthsFromRows: () => updateColWidthsFromRows
|
|
54
|
+
});
|
|
55
|
+
module.exports = __toCommonJS(index_exports);
|
|
56
|
+
|
|
57
|
+
// src/BigBuffer.ts
|
|
58
|
+
var import_buffer = require("buffer");
|
|
59
|
+
var BigBuffer = class {
|
|
60
|
+
constructor(chunkSize = 65536) {
|
|
61
|
+
this.chunkSize = chunkSize;
|
|
62
|
+
this.chunks = [];
|
|
63
|
+
this.currentBuffer = import_buffer.Buffer.alloc(chunkSize);
|
|
64
|
+
this.cursor = 0;
|
|
65
|
+
}
|
|
66
|
+
ensureCapacity(size) {
|
|
67
|
+
if (this.cursor + size > this.chunkSize) {
|
|
68
|
+
this._flush();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
_ensureCapacity(size) {
|
|
72
|
+
this.ensureCapacity(size);
|
|
73
|
+
}
|
|
74
|
+
_flush() {
|
|
75
|
+
if (this.cursor > 0) {
|
|
76
|
+
this.chunks.push(this.currentBuffer.subarray(0, this.cursor));
|
|
77
|
+
this.currentBuffer = import_buffer.Buffer.alloc(this.chunkSize);
|
|
78
|
+
this.cursor = 0;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
write(buffer) {
|
|
82
|
+
let len = buffer.length;
|
|
83
|
+
let offset = 0;
|
|
84
|
+
while (len > 0) {
|
|
85
|
+
let available = this.chunkSize - this.cursor;
|
|
86
|
+
if (available === 0) {
|
|
87
|
+
this._flush();
|
|
88
|
+
available = this.chunkSize;
|
|
89
|
+
}
|
|
90
|
+
const toWrite = Math.min(len, available);
|
|
91
|
+
buffer.copy(this.currentBuffer, this.cursor, offset, offset + toWrite);
|
|
92
|
+
this.cursor += toWrite;
|
|
93
|
+
offset += toWrite;
|
|
94
|
+
len -= toWrite;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
writeByte(val) {
|
|
98
|
+
this._ensureCapacity(1);
|
|
99
|
+
this.currentBuffer[this.cursor] = val;
|
|
100
|
+
this.cursor++;
|
|
101
|
+
}
|
|
102
|
+
writeUnsafeByte(val) {
|
|
103
|
+
this.currentBuffer[this.cursor++] = val;
|
|
104
|
+
}
|
|
105
|
+
writeInt32LE(val) {
|
|
106
|
+
this._ensureCapacity(4);
|
|
107
|
+
this.currentBuffer.writeInt32LE(val, this.cursor);
|
|
108
|
+
this.cursor += 4;
|
|
109
|
+
}
|
|
110
|
+
writeUnsafeInt32LE(val) {
|
|
111
|
+
this.currentBuffer.writeInt32LE(val, this.cursor);
|
|
112
|
+
this.cursor += 4;
|
|
113
|
+
}
|
|
114
|
+
writeDoubleLE(val) {
|
|
115
|
+
this._ensureCapacity(8);
|
|
116
|
+
this.currentBuffer.writeDoubleLE(val, this.cursor);
|
|
117
|
+
this.cursor += 8;
|
|
118
|
+
}
|
|
119
|
+
writeUnsafeDoubleLE(val) {
|
|
120
|
+
this.currentBuffer.writeDoubleLE(val, this.cursor);
|
|
121
|
+
this.cursor += 8;
|
|
122
|
+
}
|
|
123
|
+
writeString(str) {
|
|
124
|
+
const byteLength = import_buffer.Buffer.byteLength(str, "utf8");
|
|
125
|
+
if (this.cursor + byteLength <= this.chunkSize) {
|
|
126
|
+
this.cursor += this.currentBuffer.write(str, this.cursor, "utf8");
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
this._flush();
|
|
130
|
+
if (byteLength > this.chunkSize) {
|
|
131
|
+
this.chunks.push(import_buffer.Buffer.from(str, "utf8"));
|
|
132
|
+
} else {
|
|
133
|
+
this.cursor += this.currentBuffer.write(str, this.cursor, "utf8");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
writeUtf16LE(str) {
|
|
137
|
+
const byteLength = str.length * 2;
|
|
138
|
+
if (this.cursor + byteLength <= this.chunkSize) {
|
|
139
|
+
for (let i = 0; i < str.length; i++) {
|
|
140
|
+
const code = str.charCodeAt(i);
|
|
141
|
+
this.currentBuffer[this.cursor++] = code & 255;
|
|
142
|
+
this.currentBuffer[this.cursor++] = code >> 8 & 255;
|
|
143
|
+
}
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
this._flush();
|
|
147
|
+
if (byteLength > this.chunkSize) {
|
|
148
|
+
this.chunks.push(import_buffer.Buffer.from(str, "utf16le"));
|
|
149
|
+
} else {
|
|
150
|
+
for (let i = 0; i < str.length; i++) {
|
|
151
|
+
const code = str.charCodeAt(i);
|
|
152
|
+
this.currentBuffer[this.cursor++] = code & 255;
|
|
153
|
+
this.currentBuffer[this.cursor++] = code >> 8 & 255;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
getChunks() {
|
|
158
|
+
if (this.cursor > 0) {
|
|
159
|
+
this.chunks.push(this.currentBuffer.subarray(0, this.cursor));
|
|
160
|
+
this.currentBuffer = import_buffer.Buffer.alloc(this.chunkSize);
|
|
161
|
+
this.cursor = 0;
|
|
162
|
+
}
|
|
163
|
+
return this.chunks;
|
|
164
|
+
}
|
|
165
|
+
reset() {
|
|
166
|
+
this.chunks = [];
|
|
167
|
+
this.cursor = 0;
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// src/ExcelReaderAbstract.ts
|
|
172
|
+
var ExcelReaderAbstract = class {
|
|
173
|
+
constructor() {
|
|
174
|
+
this.fieldCount = 0;
|
|
175
|
+
this.rowCount = 0;
|
|
176
|
+
this.actualSheetName = "";
|
|
177
|
+
this.resultsCount = 0;
|
|
178
|
+
this._oaEpoch = Date.UTC(1899, 11, 30);
|
|
179
|
+
}
|
|
180
|
+
async close() {
|
|
181
|
+
}
|
|
182
|
+
dispose() {
|
|
183
|
+
}
|
|
184
|
+
getDateTimeFromOaDate(oaDate) {
|
|
185
|
+
const ms = oaDate * 864e5 + this._oaEpoch;
|
|
186
|
+
return new Date(ms);
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// src/BiffReaderWriter.ts
|
|
191
|
+
var BiffReaderWriter = class {
|
|
192
|
+
constructor(buffer) {
|
|
193
|
+
this._isSheet = false;
|
|
194
|
+
this._workbookId = 0;
|
|
195
|
+
this._recId = null;
|
|
196
|
+
this._workbookName = null;
|
|
197
|
+
this._inCellXf = false;
|
|
198
|
+
this._inNumberFormat = false;
|
|
199
|
+
this._numberFormatIndex = 0;
|
|
200
|
+
this._format = 0;
|
|
201
|
+
this._formatString = null;
|
|
202
|
+
this._sharedStringValue = null;
|
|
203
|
+
this._sharedStringUniqueCount = 0;
|
|
204
|
+
this._cellType = 0;
|
|
205
|
+
this._intValue = 0;
|
|
206
|
+
this._doubleVal = 0;
|
|
207
|
+
this._boolValue = false;
|
|
208
|
+
this._stringValue = null;
|
|
209
|
+
this._columnNum = -1;
|
|
210
|
+
this._xfIndex = 0;
|
|
211
|
+
this._readCell = false;
|
|
212
|
+
this._rowIndex = -1;
|
|
213
|
+
// Start of the current record data (excluding ID and Length)
|
|
214
|
+
this._recordStart = 0;
|
|
215
|
+
this._xfIndexToNumFmtId = [];
|
|
216
|
+
this._customNumFmts = /* @__PURE__ */ new Set();
|
|
217
|
+
if (!Buffer.isBuffer(buffer)) {
|
|
218
|
+
throw new Error("BiffReaderWriter expects a Buffer");
|
|
219
|
+
}
|
|
220
|
+
this.buffer = buffer;
|
|
221
|
+
this.pos = 0;
|
|
222
|
+
this.length = buffer.length;
|
|
223
|
+
}
|
|
224
|
+
_tryReadVariableValue() {
|
|
225
|
+
if (this.pos >= this.length) return null;
|
|
226
|
+
const b1 = this.buffer[this.pos++];
|
|
227
|
+
let value = (b1 & 127) >>> 0;
|
|
228
|
+
if ((b1 & 128) === 0) return value;
|
|
229
|
+
if (this.pos >= this.length) return null;
|
|
230
|
+
const b2 = this.buffer[this.pos++];
|
|
231
|
+
value = ((b2 & 127) << 7 | value) >>> 0;
|
|
232
|
+
if ((b2 & 128) === 0) return value;
|
|
233
|
+
if (this.pos >= this.length) return null;
|
|
234
|
+
const b3 = this.buffer[this.pos++];
|
|
235
|
+
value = ((b3 & 127) << 14 | value) >>> 0;
|
|
236
|
+
if ((b3 & 128) === 0) return value;
|
|
237
|
+
if (this.pos >= this.length) return null;
|
|
238
|
+
const b4 = this.buffer[this.pos++];
|
|
239
|
+
value = ((b4 & 127) << 21 | value) >>> 0;
|
|
240
|
+
return value;
|
|
241
|
+
}
|
|
242
|
+
_getDWord(offset) {
|
|
243
|
+
return this.buffer.readUInt32LE(this._recordStart + offset);
|
|
244
|
+
}
|
|
245
|
+
_getInt32(offset) {
|
|
246
|
+
return this.buffer.readInt32LE(this._recordStart + offset);
|
|
247
|
+
}
|
|
248
|
+
_getWord(offset) {
|
|
249
|
+
return this.buffer.readUInt16LE(this._recordStart + offset);
|
|
250
|
+
}
|
|
251
|
+
_getByte(offset) {
|
|
252
|
+
return this.buffer[this._recordStart + offset];
|
|
253
|
+
}
|
|
254
|
+
_getDouble(offset) {
|
|
255
|
+
return this.buffer.readDoubleLE(this._recordStart + offset);
|
|
256
|
+
}
|
|
257
|
+
_getString(offset, length) {
|
|
258
|
+
const start = this._recordStart + offset;
|
|
259
|
+
const end = start + length * 2;
|
|
260
|
+
if (end > this.buffer.length) return "";
|
|
261
|
+
return this.buffer.toString("utf16le", start, end);
|
|
262
|
+
}
|
|
263
|
+
_getNullableString(offsetRef) {
|
|
264
|
+
const length = this._getDWord(offsetRef.val);
|
|
265
|
+
offsetRef.val += 4;
|
|
266
|
+
if (length === 4294967295) return null;
|
|
267
|
+
const str = this._getString(offsetRef.val, length);
|
|
268
|
+
offsetRef.val += length * 2;
|
|
269
|
+
return str;
|
|
270
|
+
}
|
|
271
|
+
readWorkbook() {
|
|
272
|
+
const recordId = this._tryReadVariableValue();
|
|
273
|
+
const recordLength = this._tryReadVariableValue();
|
|
274
|
+
if (recordId === null || recordLength === null) return false;
|
|
275
|
+
const startPos = this.pos;
|
|
276
|
+
if (startPos + recordLength > this.length) return false;
|
|
277
|
+
this._recordStart = startPos;
|
|
278
|
+
this.pos += recordLength;
|
|
279
|
+
this._isSheet = false;
|
|
280
|
+
if (recordId === 156) {
|
|
281
|
+
this._workbookId = this._getDWord(4);
|
|
282
|
+
const offsetRef = { val: 8 };
|
|
283
|
+
this._recId = this._getNullableString(offsetRef);
|
|
284
|
+
const nameLength = this._getDWord(offsetRef.val);
|
|
285
|
+
this._workbookName = this._getString(offsetRef.val + 4, nameLength);
|
|
286
|
+
this._isSheet = true;
|
|
287
|
+
}
|
|
288
|
+
return true;
|
|
289
|
+
}
|
|
290
|
+
readSharedStrings() {
|
|
291
|
+
const recordId = this._tryReadVariableValue();
|
|
292
|
+
const recordLength = this._tryReadVariableValue();
|
|
293
|
+
if (recordId === null || recordLength === null) return false;
|
|
294
|
+
const startPos = this.pos;
|
|
295
|
+
if (startPos + recordLength > this.length) return false;
|
|
296
|
+
this._recordStart = startPos;
|
|
297
|
+
this.pos += recordLength;
|
|
298
|
+
this._sharedStringValue = null;
|
|
299
|
+
if (recordId === 19) {
|
|
300
|
+
const length = this._getDWord(1);
|
|
301
|
+
this._sharedStringValue = this._getString(5, length);
|
|
302
|
+
} else if (recordId === 159) {
|
|
303
|
+
this._sharedStringUniqueCount = this._getDWord(4);
|
|
304
|
+
}
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
readStyles() {
|
|
308
|
+
const recordId = this._tryReadVariableValue();
|
|
309
|
+
const recordLength = this._tryReadVariableValue();
|
|
310
|
+
if (recordId === null || recordLength === null) return false;
|
|
311
|
+
const startPos = this.pos;
|
|
312
|
+
if (startPos + recordLength > this.length) return false;
|
|
313
|
+
this._recordStart = startPos;
|
|
314
|
+
this.pos += recordLength;
|
|
315
|
+
const _cellXfStart = 617;
|
|
316
|
+
const _cellXfEnd = 618;
|
|
317
|
+
const _numberFormatStart = 615;
|
|
318
|
+
const _numberFormatEnd = 616;
|
|
319
|
+
const _xf = 47;
|
|
320
|
+
const _numberFormat = 44;
|
|
321
|
+
switch (recordId) {
|
|
322
|
+
case _cellXfStart:
|
|
323
|
+
this._inCellXf = true;
|
|
324
|
+
break;
|
|
325
|
+
case _cellXfEnd:
|
|
326
|
+
this._inCellXf = false;
|
|
327
|
+
break;
|
|
328
|
+
case _numberFormatStart:
|
|
329
|
+
this._inNumberFormat = true;
|
|
330
|
+
break;
|
|
331
|
+
case _numberFormatEnd:
|
|
332
|
+
this._inNumberFormat = false;
|
|
333
|
+
break;
|
|
334
|
+
case _xf:
|
|
335
|
+
if (this._inCellXf) {
|
|
336
|
+
this._numberFormatIndex = this._getWord(2);
|
|
337
|
+
this._xfIndexToNumFmtId.push(this._numberFormatIndex);
|
|
338
|
+
}
|
|
339
|
+
break;
|
|
340
|
+
case _numberFormat:
|
|
341
|
+
if (this._inNumberFormat) {
|
|
342
|
+
this._format = this._getWord(0);
|
|
343
|
+
const length = this._getDWord(2);
|
|
344
|
+
this._formatString = this._getString(6, length);
|
|
345
|
+
const code = this._formatString.toLowerCase();
|
|
346
|
+
if (code.includes("yy") || code.includes("mm") || code.includes("dd") || code.includes("h:mm")) {
|
|
347
|
+
this._customNumFmts.add(this._format);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
_getRkNumber(offset) {
|
|
355
|
+
const flags = this._getByte(offset);
|
|
356
|
+
let result = 0;
|
|
357
|
+
if ((flags & 2) !== 0) {
|
|
358
|
+
const intVal = this._getInt32(offset);
|
|
359
|
+
result = intVal >> 2;
|
|
360
|
+
} else {
|
|
361
|
+
const raw = this._getInt32(offset);
|
|
362
|
+
const highBits = raw & 4294967292;
|
|
363
|
+
const dBuf = Buffer.allocUnsafe(8);
|
|
364
|
+
dBuf.writeInt32LE(0, 0);
|
|
365
|
+
dBuf.writeInt32LE(highBits, 4);
|
|
366
|
+
result = dBuf.readDoubleLE(0);
|
|
367
|
+
}
|
|
368
|
+
if ((flags & 1) !== 0) {
|
|
369
|
+
result /= 100;
|
|
370
|
+
}
|
|
371
|
+
return result;
|
|
372
|
+
}
|
|
373
|
+
readWorksheet() {
|
|
374
|
+
const recordId = this._tryReadVariableValue();
|
|
375
|
+
const recordLength = this._tryReadVariableValue();
|
|
376
|
+
if (recordId === null || recordLength === null) return false;
|
|
377
|
+
const startPos = this.pos;
|
|
378
|
+
if (startPos + recordLength > this.length) return false;
|
|
379
|
+
this._recordStart = startPos;
|
|
380
|
+
this.pos += recordLength;
|
|
381
|
+
this._readCell = false;
|
|
382
|
+
this._columnNum = -1;
|
|
383
|
+
const _row = 0;
|
|
384
|
+
const _blank = 1;
|
|
385
|
+
const _number = 2;
|
|
386
|
+
const _boolError = 3;
|
|
387
|
+
const _bool = 4;
|
|
388
|
+
const _float = 5;
|
|
389
|
+
const _string = 6;
|
|
390
|
+
const _sharedString = 7;
|
|
391
|
+
const _formulaString = 8;
|
|
392
|
+
const _formulaNumber = 9;
|
|
393
|
+
const _formulaBool = 10;
|
|
394
|
+
const _formulaError = 11;
|
|
395
|
+
switch (recordId) {
|
|
396
|
+
case _row:
|
|
397
|
+
this._rowIndex = this._getInt32(0);
|
|
398
|
+
break;
|
|
399
|
+
case _blank:
|
|
400
|
+
case _boolError:
|
|
401
|
+
case _formulaError:
|
|
402
|
+
this._readCell = true;
|
|
403
|
+
this._cellType = 0;
|
|
404
|
+
break;
|
|
405
|
+
case _number:
|
|
406
|
+
this._doubleVal = this._getRkNumber(8);
|
|
407
|
+
this._readCell = true;
|
|
408
|
+
this._cellType = 3;
|
|
409
|
+
break;
|
|
410
|
+
case _bool:
|
|
411
|
+
case _formulaBool:
|
|
412
|
+
this._boolValue = this._getByte(8) === 1;
|
|
413
|
+
this._readCell = true;
|
|
414
|
+
this._cellType = 4;
|
|
415
|
+
break;
|
|
416
|
+
case _formulaNumber:
|
|
417
|
+
case _float:
|
|
418
|
+
this._doubleVal = this._getDouble(8);
|
|
419
|
+
this._readCell = true;
|
|
420
|
+
this._cellType = 3;
|
|
421
|
+
break;
|
|
422
|
+
case _string:
|
|
423
|
+
case _formulaString: {
|
|
424
|
+
const length = this._getDWord(8);
|
|
425
|
+
this._stringValue = this._getString(12, length);
|
|
426
|
+
this._readCell = true;
|
|
427
|
+
this._cellType = 5;
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
case _sharedString:
|
|
431
|
+
this._intValue = this._getDWord(8);
|
|
432
|
+
this._readCell = true;
|
|
433
|
+
this._cellType = 2;
|
|
434
|
+
break;
|
|
435
|
+
}
|
|
436
|
+
if (this._readCell) {
|
|
437
|
+
this._columnNum = this._getDWord(0);
|
|
438
|
+
this._xfIndex = this._getDWord(4) & 16777215;
|
|
439
|
+
}
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
// src/XlsbReader.ts
|
|
445
|
+
var import_adm_zip = __toESM(require("adm-zip"));
|
|
446
|
+
var XlsbReader = class extends ExcelReaderAbstract {
|
|
447
|
+
constructor() {
|
|
448
|
+
super();
|
|
449
|
+
this.zip = null;
|
|
450
|
+
this.sharedStrings = [];
|
|
451
|
+
this.sheetNames = [];
|
|
452
|
+
this.sheets = [];
|
|
453
|
+
this._currentSheetIndex = -1;
|
|
454
|
+
this._reader = null;
|
|
455
|
+
this._currentRow = [];
|
|
456
|
+
this._pendingRowIndex = -1;
|
|
457
|
+
this._eof = false;
|
|
458
|
+
this.xfIdToNumFmtId = [];
|
|
459
|
+
this.customDateFormats = null;
|
|
460
|
+
}
|
|
461
|
+
async open(path2, readSharedStrings = true) {
|
|
462
|
+
this.zip = new import_adm_zip.default(path2);
|
|
463
|
+
const wbEntry = this.zip.getEntry("xl/workbook.bin");
|
|
464
|
+
if (wbEntry) {
|
|
465
|
+
const buf = wbEntry.getData();
|
|
466
|
+
const reader = new BiffReaderWriter(buf);
|
|
467
|
+
while (reader.readWorkbook()) {
|
|
468
|
+
if (reader._isSheet) {
|
|
469
|
+
const name = reader._workbookName;
|
|
470
|
+
const rId = reader._recId;
|
|
471
|
+
this.sheetNames.push(name);
|
|
472
|
+
this.sheets.push({ name, rId, path: null });
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
const relsEntry = this.zip.getEntry("xl/_rels/workbook.bin.rels");
|
|
477
|
+
if (relsEntry) {
|
|
478
|
+
const xml = relsEntry.getData().toString("utf8");
|
|
479
|
+
const relRegex = /<Relationship[^>]*Id="([^"]*)"[^>]*Target="([^"]*)"/g;
|
|
480
|
+
let match;
|
|
481
|
+
const rIdToTarget = {};
|
|
482
|
+
while ((match = relRegex.exec(xml)) !== null) {
|
|
483
|
+
rIdToTarget[match[1]] = match[2];
|
|
484
|
+
}
|
|
485
|
+
for (const sheet of this.sheets) {
|
|
486
|
+
let target = rIdToTarget[sheet.rId];
|
|
487
|
+
if (target) {
|
|
488
|
+
if (target.startsWith("/")) target = target.substring(1);
|
|
489
|
+
if (!target.startsWith("xl/")) target = "xl/" + target;
|
|
490
|
+
sheet.path = target;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
if (readSharedStrings) {
|
|
495
|
+
const ssPath = "xl/sharedStrings.bin";
|
|
496
|
+
if (this.zip.getEntry(ssPath)) {
|
|
497
|
+
this._readSharedStrings(ssPath);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
const stylesPath = "xl/styles.bin";
|
|
501
|
+
if (this.zip.getEntry(stylesPath)) {
|
|
502
|
+
this._readStyles(stylesPath);
|
|
503
|
+
}
|
|
504
|
+
this.resultsCount = this.sheets.length;
|
|
505
|
+
this._currentSheetIndex = -1;
|
|
506
|
+
}
|
|
507
|
+
_readSharedStrings(path2) {
|
|
508
|
+
const entry = this.zip.getEntry(path2);
|
|
509
|
+
if (!entry) return;
|
|
510
|
+
const reader = new BiffReaderWriter(entry.getData());
|
|
511
|
+
while (reader.readSharedStrings()) {
|
|
512
|
+
if (reader._sharedStringValue !== null) {
|
|
513
|
+
this.sharedStrings.push(reader._sharedStringValue);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
_readStyles(path2) {
|
|
518
|
+
const entry = this.zip.getEntry(path2);
|
|
519
|
+
if (!entry) return;
|
|
520
|
+
const reader = new BiffReaderWriter(entry.getData());
|
|
521
|
+
while (reader.readStyles()) {
|
|
522
|
+
}
|
|
523
|
+
this.xfIdToNumFmtId = reader._xfIndexToNumFmtId;
|
|
524
|
+
this.customDateFormats = reader._customNumFmts;
|
|
525
|
+
}
|
|
526
|
+
getSheetNames() {
|
|
527
|
+
return this.sheetNames;
|
|
528
|
+
}
|
|
529
|
+
async read() {
|
|
530
|
+
if (this._currentSheetIndex === -1) {
|
|
531
|
+
this._currentSheetIndex = 0;
|
|
532
|
+
if (!this._initSheet(0)) return false;
|
|
533
|
+
}
|
|
534
|
+
if (this._eof) return false;
|
|
535
|
+
this._currentRow = [];
|
|
536
|
+
while (true) {
|
|
537
|
+
const hasRecord = this._reader.readWorksheet();
|
|
538
|
+
if (!hasRecord) {
|
|
539
|
+
this._eof = true;
|
|
540
|
+
return true;
|
|
541
|
+
}
|
|
542
|
+
if (this._reader._rowIndex !== -1 && this._reader._rowIndex !== this._pendingRowIndex) {
|
|
543
|
+
this._pendingRowIndex = this._reader._rowIndex;
|
|
544
|
+
return true;
|
|
545
|
+
}
|
|
546
|
+
if (this._reader._readCell) {
|
|
547
|
+
const col = this._reader._columnNum;
|
|
548
|
+
let val = null;
|
|
549
|
+
switch (this._reader._cellType) {
|
|
550
|
+
case 2:
|
|
551
|
+
val = this.sharedStrings[this._reader._intValue];
|
|
552
|
+
break;
|
|
553
|
+
case 3: {
|
|
554
|
+
val = this._reader._doubleVal;
|
|
555
|
+
const xfIndex = this._reader._xfIndex;
|
|
556
|
+
let numFmtId = 0;
|
|
557
|
+
if (this.xfIdToNumFmtId && xfIndex < this.xfIdToNumFmtId.length) {
|
|
558
|
+
numFmtId = this.xfIdToNumFmtId[xfIndex];
|
|
559
|
+
}
|
|
560
|
+
const isDate = numFmtId >= 14 && numFmtId <= 22 || numFmtId >= 45 && numFmtId <= 47 || this.customDateFormats && this.customDateFormats.has(numFmtId);
|
|
561
|
+
if (isDate) {
|
|
562
|
+
try {
|
|
563
|
+
val = this.getDateTimeFromOaDate(val);
|
|
564
|
+
} catch {
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
break;
|
|
568
|
+
}
|
|
569
|
+
case 4:
|
|
570
|
+
val = this._reader._boolValue;
|
|
571
|
+
break;
|
|
572
|
+
case 5:
|
|
573
|
+
val = this._reader._stringValue;
|
|
574
|
+
break;
|
|
575
|
+
default:
|
|
576
|
+
val = null;
|
|
577
|
+
}
|
|
578
|
+
this._currentRow[col] = val;
|
|
579
|
+
if (col >= this.fieldCount) this.fieldCount = col + 1;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
_initSheet(index) {
|
|
584
|
+
if (index >= this.sheets.length) return false;
|
|
585
|
+
const sheet = this.sheets[index];
|
|
586
|
+
const entry = this.zip.getEntry(sheet.path);
|
|
587
|
+
if (!entry) return false;
|
|
588
|
+
this._reader = new BiffReaderWriter(entry.getData());
|
|
589
|
+
this._eof = false;
|
|
590
|
+
this._pendingRowIndex = -1;
|
|
591
|
+
while (this._reader.readWorksheet()) {
|
|
592
|
+
if (this._reader._rowIndex !== -1) {
|
|
593
|
+
this._pendingRowIndex = this._reader._rowIndex;
|
|
594
|
+
return true;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
this._eof = true;
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
getValue(i) {
|
|
601
|
+
if (i < 0 || i >= this._currentRow.length) return null;
|
|
602
|
+
return this._currentRow[i];
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
// src/XlsxReader.ts
|
|
607
|
+
var import_yauzl = __toESM(require("yauzl"));
|
|
608
|
+
|
|
609
|
+
// src/xmlUtils.ts
|
|
610
|
+
function hasInvalidControlChars(str) {
|
|
611
|
+
for (let i = 0; i < str.length; i++) {
|
|
612
|
+
const c = str.charCodeAt(i);
|
|
613
|
+
if (c < 32 && c !== 9 && c !== 10 && c !== 13) {
|
|
614
|
+
return true;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
return false;
|
|
618
|
+
}
|
|
619
|
+
function stripInvalidControlChars(str) {
|
|
620
|
+
let out = "";
|
|
621
|
+
for (let i = 0; i < str.length; i++) {
|
|
622
|
+
const c = str.charCodeAt(i);
|
|
623
|
+
if (c === 9 || c === 10 || c === 13 || c >= 32 && c <= 55295 || c >= 57344 && c <= 65533) {
|
|
624
|
+
out += str[i];
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
return out;
|
|
628
|
+
}
|
|
629
|
+
function escapeXmlText(str) {
|
|
630
|
+
if (!/&|<|>|"|'/.test(str) && !hasInvalidControlChars(str)) {
|
|
631
|
+
return str;
|
|
632
|
+
}
|
|
633
|
+
let out = str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
634
|
+
if (hasInvalidControlChars(out)) {
|
|
635
|
+
out = stripInvalidControlChars(out);
|
|
636
|
+
}
|
|
637
|
+
return out;
|
|
638
|
+
}
|
|
639
|
+
function unescapeXml(str) {
|
|
640
|
+
if (!str || str.indexOf("&") === -1) return str;
|
|
641
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
|
|
642
|
+
}
|
|
643
|
+
function columnIndexToLetter(colIndex) {
|
|
644
|
+
let n = colIndex + 1;
|
|
645
|
+
let result = "";
|
|
646
|
+
while (n > 0) {
|
|
647
|
+
const rem = (n - 1) % 26;
|
|
648
|
+
result = String.fromCharCode(65 + rem) + result;
|
|
649
|
+
n = Math.floor((n - 1) / 26);
|
|
650
|
+
}
|
|
651
|
+
return result;
|
|
652
|
+
}
|
|
653
|
+
function columnLetterToIndex(letter) {
|
|
654
|
+
let column = 0;
|
|
655
|
+
const length = letter.length;
|
|
656
|
+
for (let i = 0; i < length; i++) {
|
|
657
|
+
column += (letter.charCodeAt(i) - 64) * Math.pow(26, length - i - 1);
|
|
658
|
+
}
|
|
659
|
+
return column - 1;
|
|
660
|
+
}
|
|
661
|
+
function trimTrailingEmptyRows(rows) {
|
|
662
|
+
let end = rows.length;
|
|
663
|
+
while (end > 0 && rows[end - 1].every((v) => v === null || v === void 0)) {
|
|
664
|
+
end--;
|
|
665
|
+
}
|
|
666
|
+
return end === rows.length ? rows : rows.slice(0, end);
|
|
667
|
+
}
|
|
668
|
+
function parseSharedStringsXml(xml) {
|
|
669
|
+
const result = [];
|
|
670
|
+
let pos = 0;
|
|
671
|
+
while (true) {
|
|
672
|
+
const siStart = xml.indexOf("<si>", pos);
|
|
673
|
+
if (siStart === -1) break;
|
|
674
|
+
const siEnd = xml.indexOf("</si>", siStart);
|
|
675
|
+
if (siEnd === -1) break;
|
|
676
|
+
const content = xml.substring(siStart, siEnd);
|
|
677
|
+
let val = "";
|
|
678
|
+
let tPos = 0;
|
|
679
|
+
while (true) {
|
|
680
|
+
const tStart = content.indexOf("<t", tPos);
|
|
681
|
+
if (tStart === -1) break;
|
|
682
|
+
const tagEnd = content.indexOf(">", tStart);
|
|
683
|
+
const tEnd = content.indexOf("</t>", tagEnd);
|
|
684
|
+
if (tEnd === -1) break;
|
|
685
|
+
val += content.substring(tagEnd + 1, tEnd);
|
|
686
|
+
tPos = tEnd + 4;
|
|
687
|
+
}
|
|
688
|
+
result.push(unescapeXml(val));
|
|
689
|
+
pos = siEnd + 5;
|
|
690
|
+
}
|
|
691
|
+
return result;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// src/XlsxReader.ts
|
|
695
|
+
var XlsxReader = class extends ExcelReaderAbstract {
|
|
696
|
+
constructor() {
|
|
697
|
+
super();
|
|
698
|
+
this.zipfile = null;
|
|
699
|
+
this.sharedStrings = [];
|
|
700
|
+
this.sheetNames = [];
|
|
701
|
+
this.sheets = [];
|
|
702
|
+
this.entries = /* @__PURE__ */ new Map();
|
|
703
|
+
this._currentSheetIndex = -1;
|
|
704
|
+
this._sheetXml = null;
|
|
705
|
+
this._xmlPos = 0;
|
|
706
|
+
this._currentRow = [];
|
|
707
|
+
this.xfIdToNumFmtId = [];
|
|
708
|
+
this.customDateFormats = /* @__PURE__ */ new Set();
|
|
709
|
+
}
|
|
710
|
+
async open(path2, readSharedStrings = true) {
|
|
711
|
+
return new Promise((resolve, reject) => {
|
|
712
|
+
import_yauzl.default.open(path2, { lazyEntries: true, autoClose: false }, async (err, zipfile) => {
|
|
713
|
+
if (err) return reject(err);
|
|
714
|
+
this.zipfile = zipfile;
|
|
715
|
+
this.entries = /* @__PURE__ */ new Map();
|
|
716
|
+
zipfile.on("entry", (entry) => {
|
|
717
|
+
this.entries.set(entry.fileName, entry);
|
|
718
|
+
zipfile.readEntry();
|
|
719
|
+
});
|
|
720
|
+
zipfile.on("end", async () => {
|
|
721
|
+
try {
|
|
722
|
+
const wbRelsContent = await this._readZipEntryContent("xl/_rels/workbook.xml.rels");
|
|
723
|
+
const rIdToTarget = {};
|
|
724
|
+
if (wbRelsContent) {
|
|
725
|
+
const relRegex = /<Relationship[^>]*Id="([^"]*)"[^>]*Target="([^"]*)"/g;
|
|
726
|
+
let match;
|
|
727
|
+
while ((match = relRegex.exec(wbRelsContent)) !== null) {
|
|
728
|
+
rIdToTarget[match[1]] = match[2];
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
const wbContent = await this._readZipEntryContent("xl/workbook.xml");
|
|
732
|
+
if (wbContent) {
|
|
733
|
+
const sheetRegex = /<sheet[^>]*name="([^"]*)"[^>]*sheetId="([^"]*)"[^>]*r:id="([^"]*)"/g;
|
|
734
|
+
let match;
|
|
735
|
+
while ((match = sheetRegex.exec(wbContent)) !== null) {
|
|
736
|
+
const name = unescapeXml(match[1]);
|
|
737
|
+
const sheetId = match[2];
|
|
738
|
+
const rId = match[3];
|
|
739
|
+
const target = rIdToTarget[rId];
|
|
740
|
+
let fullPath = target;
|
|
741
|
+
if (!fullPath.startsWith("xl/")) {
|
|
742
|
+
fullPath = "xl/" + fullPath;
|
|
743
|
+
}
|
|
744
|
+
this.sheetNames.push(name);
|
|
745
|
+
this.sheets.push({ name, sheetId, rId, path: fullPath });
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
if (readSharedStrings) {
|
|
749
|
+
const ssContent = await this._readZipEntryContent("xl/sharedStrings.xml");
|
|
750
|
+
if (ssContent) {
|
|
751
|
+
this._parseSharedStrings(ssContent);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
const stylesContent = await this._readZipEntryContent("xl/styles.xml");
|
|
755
|
+
if (stylesContent) {
|
|
756
|
+
this._parseStyles(stylesContent);
|
|
757
|
+
}
|
|
758
|
+
this.resultsCount = this.sheets.length;
|
|
759
|
+
this._currentSheetIndex = -1;
|
|
760
|
+
resolve();
|
|
761
|
+
} catch (e) {
|
|
762
|
+
reject(e);
|
|
763
|
+
}
|
|
764
|
+
});
|
|
765
|
+
zipfile.readEntry();
|
|
766
|
+
});
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
async close() {
|
|
770
|
+
if (this.zipfile) {
|
|
771
|
+
this.zipfile.close();
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
async _readZipEntryContent(path2) {
|
|
775
|
+
const entry = this.entries.get(path2);
|
|
776
|
+
if (!entry) return null;
|
|
777
|
+
return new Promise((resolve, reject) => {
|
|
778
|
+
this.zipfile.openReadStream(entry, (err, readStream) => {
|
|
779
|
+
if (err) return reject(err);
|
|
780
|
+
const chunks = [];
|
|
781
|
+
readStream.on("data", (chunk) => chunks.push(chunk));
|
|
782
|
+
readStream.on("end", () => {
|
|
783
|
+
resolve(Buffer.concat(chunks).toString("utf8"));
|
|
784
|
+
});
|
|
785
|
+
readStream.on("error", reject);
|
|
786
|
+
});
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
_parseSharedStrings(xml) {
|
|
790
|
+
this.sharedStrings = parseSharedStringsXml(xml);
|
|
791
|
+
}
|
|
792
|
+
_parseStyles(xml) {
|
|
793
|
+
const numFmtRegex = /<numFmt\s+[^>]*numFmtId="(\d+)"[^>]*formatCode="([^"]*)"/g;
|
|
794
|
+
let match;
|
|
795
|
+
this.customDateFormats = /* @__PURE__ */ new Set();
|
|
796
|
+
while ((match = numFmtRegex.exec(xml)) !== null) {
|
|
797
|
+
const id = parseInt(match[1]);
|
|
798
|
+
const code = match[2];
|
|
799
|
+
if (code.toLowerCase().includes("yy") || code.toLowerCase().includes("mm") || code.toLowerCase().includes("dd") || code.toLowerCase().includes("h:mm")) {
|
|
800
|
+
this.customDateFormats.add(id);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
this.xfIdToNumFmtId = [];
|
|
804
|
+
const cellXfsStart = xml.indexOf("<cellXfs");
|
|
805
|
+
if (cellXfsStart !== -1) {
|
|
806
|
+
const cellXfsEnd = xml.indexOf("</cellXfs>", cellXfsStart);
|
|
807
|
+
if (cellXfsEnd !== -1) {
|
|
808
|
+
const cellXfsContent = xml.substring(cellXfsStart, cellXfsEnd);
|
|
809
|
+
const xfRegex = /<xf\s+[^>]*numFmtId="(\d+)"/g;
|
|
810
|
+
while ((match = xfRegex.exec(cellXfsContent)) !== null) {
|
|
811
|
+
const numFmtId = parseInt(match[1]);
|
|
812
|
+
this.xfIdToNumFmtId.push(numFmtId);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
getSheetNames() {
|
|
818
|
+
return this.sheetNames;
|
|
819
|
+
}
|
|
820
|
+
async read() {
|
|
821
|
+
if (this._currentSheetIndex === -1) {
|
|
822
|
+
this._currentSheetIndex = 0;
|
|
823
|
+
await this._initSheet(this._currentSheetIndex);
|
|
824
|
+
}
|
|
825
|
+
if (this._readNextRow()) {
|
|
826
|
+
return true;
|
|
827
|
+
} else {
|
|
828
|
+
return false;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
async _initSheet(index) {
|
|
832
|
+
if (index >= this.sheets.length) return;
|
|
833
|
+
const sheet = this.sheets[index];
|
|
834
|
+
this.actualSheetName = sheet.name;
|
|
835
|
+
this._sheetXml = await this._readZipEntryContent(sheet.path);
|
|
836
|
+
if (!this._sheetXml) {
|
|
837
|
+
this._sheetXml = "";
|
|
838
|
+
}
|
|
839
|
+
this._xmlPos = 0;
|
|
840
|
+
const sd = this._sheetXml.indexOf("<sheetData>");
|
|
841
|
+
if (sd !== -1) this._xmlPos = sd + 11;
|
|
842
|
+
}
|
|
843
|
+
_readNextRow() {
|
|
844
|
+
if (!this._sheetXml) return false;
|
|
845
|
+
const rowStart = this._sheetXml.indexOf("<row", this._xmlPos);
|
|
846
|
+
if (rowStart === -1) return false;
|
|
847
|
+
const rowEnd = this._sheetXml.indexOf("</row>", rowStart);
|
|
848
|
+
if (rowEnd === -1) return false;
|
|
849
|
+
this._xmlPos = rowEnd + 6;
|
|
850
|
+
this._parseRowByIndex(rowStart, rowEnd);
|
|
851
|
+
return true;
|
|
852
|
+
}
|
|
853
|
+
_parseRowByIndex(rowStart, rowEnd) {
|
|
854
|
+
this._currentRow = [];
|
|
855
|
+
const xml = this._sheetXml;
|
|
856
|
+
let pos = xml.indexOf(">", rowStart) + 1;
|
|
857
|
+
while (pos < rowEnd) {
|
|
858
|
+
const cStart = xml.indexOf("<c", pos);
|
|
859
|
+
if (cStart === -1 || cStart >= rowEnd) break;
|
|
860
|
+
const nextTagClose = xml.indexOf(">", cStart);
|
|
861
|
+
let colIndex = -1;
|
|
862
|
+
let type = "n";
|
|
863
|
+
let styleIndex = 0;
|
|
864
|
+
let currentIdx = cStart + 2;
|
|
865
|
+
while (currentIdx < nextTagClose) {
|
|
866
|
+
while (xml.charCodeAt(currentIdx) <= 32 && currentIdx < nextTagClose) currentIdx++;
|
|
867
|
+
if (currentIdx >= nextTagClose) break;
|
|
868
|
+
const keyStart = currentIdx;
|
|
869
|
+
while (xml.charCodeAt(currentIdx) !== 61 && currentIdx < nextTagClose) currentIdx++;
|
|
870
|
+
const key = xml.substring(keyStart, currentIdx);
|
|
871
|
+
currentIdx++;
|
|
872
|
+
if (xml.charCodeAt(currentIdx) === 34) {
|
|
873
|
+
currentIdx++;
|
|
874
|
+
const valStart = currentIdx;
|
|
875
|
+
while (xml.charCodeAt(currentIdx) !== 34 && currentIdx < nextTagClose) currentIdx++;
|
|
876
|
+
const val2 = xml.substring(valStart, currentIdx);
|
|
877
|
+
currentIdx++;
|
|
878
|
+
if (key === "r") {
|
|
879
|
+
let letterLen = 0;
|
|
880
|
+
while (letterLen < val2.length && val2.charCodeAt(letterLen) >= 65) letterLen++;
|
|
881
|
+
colIndex = columnLetterToIndex(val2.substring(0, letterLen));
|
|
882
|
+
} else if (key === "t") {
|
|
883
|
+
type = val2;
|
|
884
|
+
} else if (key === "s") {
|
|
885
|
+
styleIndex = parseInt(val2, 10);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
let val = null;
|
|
890
|
+
if (xml.charCodeAt(nextTagClose - 1) === 47) {
|
|
891
|
+
pos = nextTagClose + 1;
|
|
892
|
+
} else {
|
|
893
|
+
const cEnd = xml.indexOf("</c>", nextTagClose);
|
|
894
|
+
const cellContentEnd = cEnd !== -1 && cEnd < rowEnd ? cEnd : rowEnd;
|
|
895
|
+
const vStart = xml.indexOf("<v>", nextTagClose);
|
|
896
|
+
if (vStart !== -1 && vStart < cellContentEnd) {
|
|
897
|
+
const vInnerStart = vStart + 3;
|
|
898
|
+
const vEnd = xml.indexOf("</v>", vInnerStart);
|
|
899
|
+
if (vEnd !== -1 && vEnd < cellContentEnd) {
|
|
900
|
+
val = xml.substring(vInnerStart, vEnd);
|
|
901
|
+
}
|
|
902
|
+
} else {
|
|
903
|
+
if (type === "inlineStr") {
|
|
904
|
+
const tStart = xml.indexOf("<t", nextTagClose);
|
|
905
|
+
if (tStart !== -1 && tStart < cellContentEnd) {
|
|
906
|
+
const tContentStart = xml.indexOf(">", tStart) + 1;
|
|
907
|
+
const tEnd = xml.indexOf("</t>", tContentStart);
|
|
908
|
+
if (tEnd !== -1 && tEnd < cellContentEnd) {
|
|
909
|
+
val = xml.substring(tContentStart, tEnd);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
pos = cellContentEnd + 4;
|
|
915
|
+
}
|
|
916
|
+
let finalVal = null;
|
|
917
|
+
if (val !== null) {
|
|
918
|
+
if (type === "s") {
|
|
919
|
+
const idx = parseInt(val, 10);
|
|
920
|
+
finalVal = this.sharedStrings[idx];
|
|
921
|
+
} else if (type === "b") {
|
|
922
|
+
finalVal = val === "1" || val === "true";
|
|
923
|
+
} else if (type === "inlineStr") {
|
|
924
|
+
finalVal = unescapeXml(val);
|
|
925
|
+
} else if (type === "n" || type === "") {
|
|
926
|
+
finalVal = parseFloat(val);
|
|
927
|
+
if (styleIndex > 0 && this.xfIdToNumFmtId) {
|
|
928
|
+
let numFmtId = 0;
|
|
929
|
+
if (styleIndex < this.xfIdToNumFmtId.length) {
|
|
930
|
+
numFmtId = this.xfIdToNumFmtId[styleIndex];
|
|
931
|
+
}
|
|
932
|
+
const isDate = numFmtId >= 14 && numFmtId <= 22 || numFmtId >= 45 && numFmtId <= 47 || this.customDateFormats && this.customDateFormats.has(numFmtId);
|
|
933
|
+
if (isDate) {
|
|
934
|
+
try {
|
|
935
|
+
finalVal = this.getDateTimeFromOaDate(finalVal);
|
|
936
|
+
} catch {
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
if (colIndex !== -1) {
|
|
943
|
+
this._currentRow[colIndex] = finalVal;
|
|
944
|
+
if (colIndex >= this.fieldCount) this.fieldCount = colIndex + 1;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
getValue(i) {
|
|
949
|
+
if (i < 0 || i >= this._currentRow.length) return null;
|
|
950
|
+
return this._currentRow[i];
|
|
951
|
+
}
|
|
952
|
+
};
|
|
953
|
+
|
|
954
|
+
// src/ReaderFactory.ts
|
|
955
|
+
var path = __toESM(require("path"));
|
|
956
|
+
var ReaderFactory = class {
|
|
957
|
+
/**
|
|
958
|
+
* @param filePath Path ending in `.xlsb` or `.xlsx`
|
|
959
|
+
* @throws if the extension is unsupported
|
|
960
|
+
*/
|
|
961
|
+
static create(filePath) {
|
|
962
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
963
|
+
if (ext === ".xlsx") {
|
|
964
|
+
return new XlsxReader();
|
|
965
|
+
} else if (ext === ".xlsb") {
|
|
966
|
+
return new XlsbReader();
|
|
967
|
+
} else {
|
|
968
|
+
throw new Error(`Unsupported extension: ${ext}`);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
|
|
973
|
+
// src/XlsbWriter.ts
|
|
974
|
+
var fs = __toESM(require("fs"));
|
|
975
|
+
var import_archiver = __toESM(require("archiver"));
|
|
976
|
+
var import_stream = require("stream");
|
|
977
|
+
|
|
978
|
+
// src/Formats.ts
|
|
979
|
+
var F = {
|
|
980
|
+
THOUSANDS_SEP: "#,##0",
|
|
981
|
+
CURRENCY_PLN: '#,##0.00 "z\u0142"',
|
|
982
|
+
CURRENCY_EUR: "#,##0.00 \u20AC",
|
|
983
|
+
PERCENTAGE: "0%",
|
|
984
|
+
SCIENTIFIC: "0.00E+00",
|
|
985
|
+
TWO_DECIMALS: "#,##0.00",
|
|
986
|
+
TEXT: "@",
|
|
987
|
+
LEADING_ZEROS: "000000000",
|
|
988
|
+
DATE_SHORT: "dd.mm.yyyy",
|
|
989
|
+
DATE_LONG: "d mmmm yyyy",
|
|
990
|
+
DATE_DAY_MONTH_YEAR: "dd-mm-yyyy",
|
|
991
|
+
DATE_ISO: "yyyy-mm-dd",
|
|
992
|
+
DATE_MONTH_YEAR: "mmmm yyyy",
|
|
993
|
+
DATE_WEEKDAY: "dddd, d mmmm yyyy",
|
|
994
|
+
DATE_DAY_MONTH: "d mmmm",
|
|
995
|
+
DATE_YEAR_ONLY: "yyyy",
|
|
996
|
+
DATETIME_SHORT: "dd.mm.yyyy hh:mm",
|
|
997
|
+
DATETIME_LONG: "d mmmm yyyy hh:mm:ss",
|
|
998
|
+
TIME_HH_MM: "hh:mm",
|
|
999
|
+
TIME_HH_MM_SS: "hh:mm:ss",
|
|
1000
|
+
TIME_12H: "h:mm AM/PM",
|
|
1001
|
+
DATETIME_24H: "dd.mm.yyyy hh:mm:ss",
|
|
1002
|
+
DATETIME_ISO: 'yyyy-mm-dd"T"hh:mm:ss',
|
|
1003
|
+
TIME_MS: "hh:mm:ss.000"
|
|
1004
|
+
};
|
|
1005
|
+
function isFormattedCell(val) {
|
|
1006
|
+
return val !== null && val !== void 0 && typeof val === "object" && "format" in val && typeof val.format === "string";
|
|
1007
|
+
}
|
|
1008
|
+
function unwrapCell(val) {
|
|
1009
|
+
if (isFormattedCell(val)) {
|
|
1010
|
+
return val.value;
|
|
1011
|
+
}
|
|
1012
|
+
return val;
|
|
1013
|
+
}
|
|
1014
|
+
function getFormat(val) {
|
|
1015
|
+
if (isFormattedCell(val)) {
|
|
1016
|
+
return val.format;
|
|
1017
|
+
}
|
|
1018
|
+
return null;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
// src/writerHelpers.ts
|
|
1022
|
+
var INVALID_SHEET_NAME_CHARS = /[\\/*?[\]:]/g;
|
|
1023
|
+
function sanitizeSheetName(name, sheetCount) {
|
|
1024
|
+
if (!name || typeof name !== "string") {
|
|
1025
|
+
return `Sheet${sheetCount + 1}`;
|
|
1026
|
+
}
|
|
1027
|
+
let sanitized = name.replace(INVALID_SHEET_NAME_CHARS, "_");
|
|
1028
|
+
if (sanitized.length > 31) {
|
|
1029
|
+
sanitized = sanitized.substring(0, 31);
|
|
1030
|
+
}
|
|
1031
|
+
if (sanitized.trim().length === 0) {
|
|
1032
|
+
sanitized = `Sheet${sheetCount + 1}`;
|
|
1033
|
+
}
|
|
1034
|
+
return sanitized;
|
|
1035
|
+
}
|
|
1036
|
+
function initColWidths(columnCount) {
|
|
1037
|
+
return new Array(columnCount).fill(-1);
|
|
1038
|
+
}
|
|
1039
|
+
function applyHeaderWidths(colWidths, headers, columnCount) {
|
|
1040
|
+
for (let i = 0; i < columnCount; i++) {
|
|
1041
|
+
const len = headers[i] ? headers[i].length + 1 : 0;
|
|
1042
|
+
let width = 1.25 * len + 2;
|
|
1043
|
+
if (width > 80) width = 80;
|
|
1044
|
+
if (colWidths[i] < width) colWidths[i] = width;
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
function updateColWidthsFromRows(colWidths, rows, sampleLimit = 100) {
|
|
1048
|
+
for (let r = 0; r < Math.min(rows.length, sampleLimit); r++) {
|
|
1049
|
+
const row = rows[r];
|
|
1050
|
+
for (let c = 0; c < row.length; c++) {
|
|
1051
|
+
const raw = row[c];
|
|
1052
|
+
if (raw === null || raw === void 0) continue;
|
|
1053
|
+
const val = isFormattedCell(raw) ? raw.value : raw;
|
|
1054
|
+
const len = val instanceof Date ? 20 : String(val).length + 1;
|
|
1055
|
+
let width = 1.25 * len + 2;
|
|
1056
|
+
if (width > 80) width = 80;
|
|
1057
|
+
if (colWidths[c] < width) colWidths[c] = width;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
function defaultColWidth(width, floor = false) {
|
|
1062
|
+
if (width > 0) {
|
|
1063
|
+
return floor ? Math.floor(width) : width;
|
|
1064
|
+
}
|
|
1065
|
+
return 10;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
// src/StreamingSheetState.ts
|
|
1069
|
+
var StreamingSheetState = class {
|
|
1070
|
+
constructor() {
|
|
1071
|
+
this.isStreaming = false;
|
|
1072
|
+
this.rowNum = 0;
|
|
1073
|
+
this.startCol = 0;
|
|
1074
|
+
this.endCol = 0;
|
|
1075
|
+
this.doAutofilter = false;
|
|
1076
|
+
this.colWidths = [];
|
|
1077
|
+
this.buffer = null;
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* Begin a streaming sheet session.
|
|
1081
|
+
* @throws if already streaming
|
|
1082
|
+
*/
|
|
1083
|
+
begin(columnCount, doAutofilter, buffer) {
|
|
1084
|
+
if (this.isStreaming) {
|
|
1085
|
+
throw new Error("Already in streaming mode. Call endSheet() first.");
|
|
1086
|
+
}
|
|
1087
|
+
this.isStreaming = true;
|
|
1088
|
+
this.buffer = buffer;
|
|
1089
|
+
this.rowNum = 0;
|
|
1090
|
+
this.startCol = 0;
|
|
1091
|
+
this.endCol = columnCount;
|
|
1092
|
+
this.doAutofilter = doAutofilter;
|
|
1093
|
+
this.colWidths = initColWidths(columnCount);
|
|
1094
|
+
}
|
|
1095
|
+
/** Assert streaming mode and return the active buffer. */
|
|
1096
|
+
assertStreaming() {
|
|
1097
|
+
if (!this.isStreaming || !this.buffer) {
|
|
1098
|
+
throw new Error("Not in streaming mode. Call startSheet() first.");
|
|
1099
|
+
}
|
|
1100
|
+
return this.buffer;
|
|
1101
|
+
}
|
|
1102
|
+
/** Reset after endSheet(). */
|
|
1103
|
+
end() {
|
|
1104
|
+
this.isStreaming = false;
|
|
1105
|
+
this.buffer = null;
|
|
1106
|
+
this.rowNum = 0;
|
|
1107
|
+
this.startCol = 0;
|
|
1108
|
+
this.endCol = 0;
|
|
1109
|
+
this.doAutofilter = false;
|
|
1110
|
+
this.colWidths = [];
|
|
1111
|
+
}
|
|
1112
|
+
};
|
|
1113
|
+
|
|
1114
|
+
// src/XlsbWriter.ts
|
|
1115
|
+
var XlsbWriter = class _XlsbWriter {
|
|
1116
|
+
/**
|
|
1117
|
+
* @param filePath Destination `.xlsb` path on disk.
|
|
1118
|
+
*/
|
|
1119
|
+
constructor(filePath) {
|
|
1120
|
+
this.sheetCount = 0;
|
|
1121
|
+
this.sheetList = [];
|
|
1122
|
+
this.sstDic = /* @__PURE__ */ new Map();
|
|
1123
|
+
this.sstCntUnique = 0;
|
|
1124
|
+
this.sstCntAll = 0;
|
|
1125
|
+
this._autofilterIsOn = false;
|
|
1126
|
+
this._nextFmtId = 167;
|
|
1127
|
+
this._nextXfIdx = 4;
|
|
1128
|
+
this._stFmtRecords = /* @__PURE__ */ new Map();
|
|
1129
|
+
this.stream = new StreamingSheetState();
|
|
1130
|
+
this.output = fs.createWriteStream(filePath);
|
|
1131
|
+
this.archive = (0, import_archiver.default)("zip");
|
|
1132
|
+
this.archive.pipe(this.output);
|
|
1133
|
+
this._oaEpoch = Date.UTC(1899, 11, 30);
|
|
1134
|
+
this._sheet1Bytes = Buffer.from([
|
|
1135
|
+
129,
|
|
1136
|
+
1,
|
|
1137
|
+
0,
|
|
1138
|
+
147,
|
|
1139
|
+
1,
|
|
1140
|
+
23,
|
|
1141
|
+
203,
|
|
1142
|
+
4,
|
|
1143
|
+
2,
|
|
1144
|
+
0,
|
|
1145
|
+
64,
|
|
1146
|
+
0,
|
|
1147
|
+
0,
|
|
1148
|
+
0,
|
|
1149
|
+
0,
|
|
1150
|
+
0,
|
|
1151
|
+
0,
|
|
1152
|
+
255,
|
|
1153
|
+
255,
|
|
1154
|
+
255,
|
|
1155
|
+
255,
|
|
1156
|
+
255,
|
|
1157
|
+
255,
|
|
1158
|
+
255,
|
|
1159
|
+
255,
|
|
1160
|
+
0,
|
|
1161
|
+
0,
|
|
1162
|
+
0,
|
|
1163
|
+
0,
|
|
1164
|
+
148,
|
|
1165
|
+
1,
|
|
1166
|
+
16,
|
|
1167
|
+
0,
|
|
1168
|
+
0,
|
|
1169
|
+
0,
|
|
1170
|
+
0,
|
|
1171
|
+
0,
|
|
1172
|
+
0,
|
|
1173
|
+
0,
|
|
1174
|
+
0,
|
|
1175
|
+
0,
|
|
1176
|
+
0,
|
|
1177
|
+
0,
|
|
1178
|
+
0,
|
|
1179
|
+
0,
|
|
1180
|
+
0,
|
|
1181
|
+
0,
|
|
1182
|
+
0,
|
|
1183
|
+
133,
|
|
1184
|
+
1,
|
|
1185
|
+
0,
|
|
1186
|
+
137,
|
|
1187
|
+
1,
|
|
1188
|
+
30,
|
|
1189
|
+
220,
|
|
1190
|
+
3,
|
|
1191
|
+
0,
|
|
1192
|
+
0,
|
|
1193
|
+
0,
|
|
1194
|
+
0,
|
|
1195
|
+
0,
|
|
1196
|
+
0,
|
|
1197
|
+
0,
|
|
1198
|
+
0,
|
|
1199
|
+
0,
|
|
1200
|
+
0,
|
|
1201
|
+
0,
|
|
1202
|
+
0,
|
|
1203
|
+
64,
|
|
1204
|
+
0,
|
|
1205
|
+
0,
|
|
1206
|
+
0,
|
|
1207
|
+
100,
|
|
1208
|
+
0,
|
|
1209
|
+
0,
|
|
1210
|
+
0,
|
|
1211
|
+
0,
|
|
1212
|
+
0,
|
|
1213
|
+
0,
|
|
1214
|
+
0,
|
|
1215
|
+
0,
|
|
1216
|
+
0,
|
|
1217
|
+
0,
|
|
1218
|
+
0,
|
|
1219
|
+
152,
|
|
1220
|
+
1,
|
|
1221
|
+
36,
|
|
1222
|
+
3,
|
|
1223
|
+
0,
|
|
1224
|
+
0,
|
|
1225
|
+
0,
|
|
1226
|
+
0,
|
|
1227
|
+
0,
|
|
1228
|
+
0,
|
|
1229
|
+
0,
|
|
1230
|
+
0,
|
|
1231
|
+
0,
|
|
1232
|
+
0,
|
|
1233
|
+
0,
|
|
1234
|
+
0,
|
|
1235
|
+
0,
|
|
1236
|
+
0,
|
|
1237
|
+
0,
|
|
1238
|
+
1,
|
|
1239
|
+
0,
|
|
1240
|
+
0,
|
|
1241
|
+
0,
|
|
1242
|
+
0,
|
|
1243
|
+
0,
|
|
1244
|
+
0,
|
|
1245
|
+
0,
|
|
1246
|
+
0,
|
|
1247
|
+
0,
|
|
1248
|
+
0,
|
|
1249
|
+
0,
|
|
1250
|
+
0,
|
|
1251
|
+
0,
|
|
1252
|
+
0,
|
|
1253
|
+
0,
|
|
1254
|
+
0,
|
|
1255
|
+
0,
|
|
1256
|
+
0,
|
|
1257
|
+
0,
|
|
1258
|
+
138,
|
|
1259
|
+
1,
|
|
1260
|
+
0,
|
|
1261
|
+
134,
|
|
1262
|
+
1,
|
|
1263
|
+
0,
|
|
1264
|
+
37,
|
|
1265
|
+
6,
|
|
1266
|
+
1,
|
|
1267
|
+
0,
|
|
1268
|
+
2,
|
|
1269
|
+
14,
|
|
1270
|
+
0,
|
|
1271
|
+
128,
|
|
1272
|
+
149,
|
|
1273
|
+
8,
|
|
1274
|
+
2,
|
|
1275
|
+
5,
|
|
1276
|
+
0,
|
|
1277
|
+
38,
|
|
1278
|
+
0,
|
|
1279
|
+
229,
|
|
1280
|
+
3,
|
|
1281
|
+
12,
|
|
1282
|
+
255,
|
|
1283
|
+
255,
|
|
1284
|
+
255,
|
|
1285
|
+
255,
|
|
1286
|
+
8,
|
|
1287
|
+
0,
|
|
1288
|
+
44,
|
|
1289
|
+
1,
|
|
1290
|
+
0,
|
|
1291
|
+
0,
|
|
1292
|
+
0,
|
|
1293
|
+
0,
|
|
1294
|
+
145,
|
|
1295
|
+
1,
|
|
1296
|
+
0,
|
|
1297
|
+
37,
|
|
1298
|
+
6,
|
|
1299
|
+
1,
|
|
1300
|
+
0,
|
|
1301
|
+
2,
|
|
1302
|
+
14,
|
|
1303
|
+
0,
|
|
1304
|
+
128,
|
|
1305
|
+
128,
|
|
1306
|
+
8,
|
|
1307
|
+
2,
|
|
1308
|
+
5,
|
|
1309
|
+
0,
|
|
1310
|
+
38,
|
|
1311
|
+
0,
|
|
1312
|
+
0,
|
|
1313
|
+
25,
|
|
1314
|
+
0,
|
|
1315
|
+
0,
|
|
1316
|
+
0,
|
|
1317
|
+
0,
|
|
1318
|
+
0,
|
|
1319
|
+
0,
|
|
1320
|
+
0,
|
|
1321
|
+
0,
|
|
1322
|
+
44,
|
|
1323
|
+
1,
|
|
1324
|
+
0,
|
|
1325
|
+
0,
|
|
1326
|
+
0,
|
|
1327
|
+
1,
|
|
1328
|
+
0,
|
|
1329
|
+
0,
|
|
1330
|
+
0,
|
|
1331
|
+
0,
|
|
1332
|
+
0,
|
|
1333
|
+
0,
|
|
1334
|
+
0,
|
|
1335
|
+
0,
|
|
1336
|
+
0,
|
|
1337
|
+
0,
|
|
1338
|
+
0,
|
|
1339
|
+
7,
|
|
1340
|
+
12,
|
|
1341
|
+
0,
|
|
1342
|
+
0,
|
|
1343
|
+
0,
|
|
1344
|
+
0,
|
|
1345
|
+
0,
|
|
1346
|
+
0,
|
|
1347
|
+
0,
|
|
1348
|
+
0,
|
|
1349
|
+
0,
|
|
1350
|
+
0,
|
|
1351
|
+
0,
|
|
1352
|
+
0,
|
|
1353
|
+
146,
|
|
1354
|
+
1,
|
|
1355
|
+
0,
|
|
1356
|
+
151,
|
|
1357
|
+
4,
|
|
1358
|
+
66,
|
|
1359
|
+
0,
|
|
1360
|
+
0,
|
|
1361
|
+
0,
|
|
1362
|
+
0,
|
|
1363
|
+
0,
|
|
1364
|
+
0,
|
|
1365
|
+
1,
|
|
1366
|
+
0,
|
|
1367
|
+
0,
|
|
1368
|
+
0,
|
|
1369
|
+
1,
|
|
1370
|
+
0,
|
|
1371
|
+
0,
|
|
1372
|
+
0,
|
|
1373
|
+
0,
|
|
1374
|
+
0,
|
|
1375
|
+
0,
|
|
1376
|
+
0,
|
|
1377
|
+
0,
|
|
1378
|
+
0,
|
|
1379
|
+
0,
|
|
1380
|
+
0,
|
|
1381
|
+
0,
|
|
1382
|
+
0,
|
|
1383
|
+
0,
|
|
1384
|
+
0,
|
|
1385
|
+
0,
|
|
1386
|
+
0,
|
|
1387
|
+
0,
|
|
1388
|
+
0,
|
|
1389
|
+
0,
|
|
1390
|
+
0,
|
|
1391
|
+
0,
|
|
1392
|
+
0,
|
|
1393
|
+
0,
|
|
1394
|
+
0,
|
|
1395
|
+
0,
|
|
1396
|
+
0,
|
|
1397
|
+
0,
|
|
1398
|
+
0,
|
|
1399
|
+
0,
|
|
1400
|
+
0,
|
|
1401
|
+
0,
|
|
1402
|
+
0,
|
|
1403
|
+
0,
|
|
1404
|
+
0,
|
|
1405
|
+
1,
|
|
1406
|
+
0,
|
|
1407
|
+
0,
|
|
1408
|
+
0,
|
|
1409
|
+
0,
|
|
1410
|
+
0,
|
|
1411
|
+
0,
|
|
1412
|
+
0,
|
|
1413
|
+
0,
|
|
1414
|
+
0,
|
|
1415
|
+
0,
|
|
1416
|
+
0,
|
|
1417
|
+
0,
|
|
1418
|
+
0,
|
|
1419
|
+
0,
|
|
1420
|
+
0,
|
|
1421
|
+
1,
|
|
1422
|
+
0,
|
|
1423
|
+
0,
|
|
1424
|
+
0,
|
|
1425
|
+
221,
|
|
1426
|
+
3,
|
|
1427
|
+
2,
|
|
1428
|
+
16,
|
|
1429
|
+
0,
|
|
1430
|
+
220,
|
|
1431
|
+
3,
|
|
1432
|
+
48,
|
|
1433
|
+
102,
|
|
1434
|
+
102,
|
|
1435
|
+
102,
|
|
1436
|
+
102,
|
|
1437
|
+
102,
|
|
1438
|
+
102,
|
|
1439
|
+
230,
|
|
1440
|
+
63,
|
|
1441
|
+
102,
|
|
1442
|
+
102,
|
|
1443
|
+
102,
|
|
1444
|
+
102,
|
|
1445
|
+
102,
|
|
1446
|
+
102,
|
|
1447
|
+
230,
|
|
1448
|
+
63,
|
|
1449
|
+
0,
|
|
1450
|
+
0,
|
|
1451
|
+
0,
|
|
1452
|
+
0,
|
|
1453
|
+
0,
|
|
1454
|
+
0,
|
|
1455
|
+
232,
|
|
1456
|
+
63,
|
|
1457
|
+
0,
|
|
1458
|
+
0,
|
|
1459
|
+
0,
|
|
1460
|
+
0,
|
|
1461
|
+
0,
|
|
1462
|
+
0,
|
|
1463
|
+
232,
|
|
1464
|
+
63,
|
|
1465
|
+
51,
|
|
1466
|
+
51,
|
|
1467
|
+
51,
|
|
1468
|
+
51,
|
|
1469
|
+
51,
|
|
1470
|
+
51,
|
|
1471
|
+
211,
|
|
1472
|
+
63,
|
|
1473
|
+
51,
|
|
1474
|
+
51,
|
|
1475
|
+
51,
|
|
1476
|
+
51,
|
|
1477
|
+
51,
|
|
1478
|
+
51,
|
|
1479
|
+
211,
|
|
1480
|
+
63,
|
|
1481
|
+
37,
|
|
1482
|
+
6,
|
|
1483
|
+
1,
|
|
1484
|
+
0,
|
|
1485
|
+
0,
|
|
1486
|
+
16,
|
|
1487
|
+
0,
|
|
1488
|
+
128,
|
|
1489
|
+
128,
|
|
1490
|
+
24,
|
|
1491
|
+
16,
|
|
1492
|
+
0,
|
|
1493
|
+
0,
|
|
1494
|
+
0,
|
|
1495
|
+
0,
|
|
1496
|
+
1,
|
|
1497
|
+
0,
|
|
1498
|
+
0,
|
|
1499
|
+
0,
|
|
1500
|
+
0,
|
|
1501
|
+
0,
|
|
1502
|
+
0,
|
|
1503
|
+
0,
|
|
1504
|
+
0,
|
|
1505
|
+
0,
|
|
1506
|
+
0,
|
|
1507
|
+
0,
|
|
1508
|
+
38,
|
|
1509
|
+
0,
|
|
1510
|
+
130,
|
|
1511
|
+
1,
|
|
1512
|
+
0
|
|
1513
|
+
]);
|
|
1514
|
+
this._workbookBinStart = Buffer.from([
|
|
1515
|
+
131,
|
|
1516
|
+
1,
|
|
1517
|
+
0,
|
|
1518
|
+
128,
|
|
1519
|
+
1,
|
|
1520
|
+
50,
|
|
1521
|
+
0,
|
|
1522
|
+
0,
|
|
1523
|
+
0,
|
|
1524
|
+
0,
|
|
1525
|
+
0,
|
|
1526
|
+
0,
|
|
1527
|
+
0,
|
|
1528
|
+
0,
|
|
1529
|
+
0,
|
|
1530
|
+
0,
|
|
1531
|
+
0,
|
|
1532
|
+
0,
|
|
1533
|
+
0,
|
|
1534
|
+
0,
|
|
1535
|
+
0,
|
|
1536
|
+
0,
|
|
1537
|
+
2,
|
|
1538
|
+
0,
|
|
1539
|
+
0,
|
|
1540
|
+
0,
|
|
1541
|
+
120,
|
|
1542
|
+
0,
|
|
1543
|
+
108,
|
|
1544
|
+
0,
|
|
1545
|
+
1,
|
|
1546
|
+
0,
|
|
1547
|
+
0,
|
|
1548
|
+
0,
|
|
1549
|
+
55,
|
|
1550
|
+
0,
|
|
1551
|
+
1,
|
|
1552
|
+
0,
|
|
1553
|
+
0,
|
|
1554
|
+
0,
|
|
1555
|
+
54,
|
|
1556
|
+
0,
|
|
1557
|
+
5,
|
|
1558
|
+
0,
|
|
1559
|
+
0,
|
|
1560
|
+
0,
|
|
1561
|
+
50,
|
|
1562
|
+
0,
|
|
1563
|
+
52,
|
|
1564
|
+
0,
|
|
1565
|
+
51,
|
|
1566
|
+
0,
|
|
1567
|
+
50,
|
|
1568
|
+
0,
|
|
1569
|
+
54,
|
|
1570
|
+
0,
|
|
1571
|
+
153,
|
|
1572
|
+
1,
|
|
1573
|
+
12,
|
|
1574
|
+
32,
|
|
1575
|
+
0,
|
|
1576
|
+
1,
|
|
1577
|
+
0,
|
|
1578
|
+
0,
|
|
1579
|
+
0,
|
|
1580
|
+
0,
|
|
1581
|
+
0,
|
|
1582
|
+
0,
|
|
1583
|
+
0,
|
|
1584
|
+
0,
|
|
1585
|
+
0,
|
|
1586
|
+
37,
|
|
1587
|
+
6,
|
|
1588
|
+
1,
|
|
1589
|
+
0,
|
|
1590
|
+
3,
|
|
1591
|
+
15,
|
|
1592
|
+
0,
|
|
1593
|
+
128,
|
|
1594
|
+
151,
|
|
1595
|
+
16,
|
|
1596
|
+
52,
|
|
1597
|
+
24,
|
|
1598
|
+
0,
|
|
1599
|
+
0,
|
|
1600
|
+
0,
|
|
1601
|
+
67,
|
|
1602
|
+
0,
|
|
1603
|
+
58,
|
|
1604
|
+
0,
|
|
1605
|
+
92,
|
|
1606
|
+
0,
|
|
1607
|
+
115,
|
|
1608
|
+
0,
|
|
1609
|
+
113,
|
|
1610
|
+
0,
|
|
1611
|
+
108,
|
|
1612
|
+
0,
|
|
1613
|
+
115,
|
|
1614
|
+
0,
|
|
1615
|
+
92,
|
|
1616
|
+
0,
|
|
1617
|
+
84,
|
|
1618
|
+
0,
|
|
1619
|
+
101,
|
|
1620
|
+
0,
|
|
1621
|
+
115,
|
|
1622
|
+
0,
|
|
1623
|
+
116,
|
|
1624
|
+
0,
|
|
1625
|
+
121,
|
|
1626
|
+
0,
|
|
1627
|
+
90,
|
|
1628
|
+
0,
|
|
1629
|
+
97,
|
|
1630
|
+
0,
|
|
1631
|
+
112,
|
|
1632
|
+
0,
|
|
1633
|
+
105,
|
|
1634
|
+
0,
|
|
1635
|
+
115,
|
|
1636
|
+
0,
|
|
1637
|
+
117,
|
|
1638
|
+
0,
|
|
1639
|
+
88,
|
|
1640
|
+
0,
|
|
1641
|
+
108,
|
|
1642
|
+
0,
|
|
1643
|
+
115,
|
|
1644
|
+
0,
|
|
1645
|
+
98,
|
|
1646
|
+
0,
|
|
1647
|
+
92,
|
|
1648
|
+
0,
|
|
1649
|
+
38,
|
|
1650
|
+
0,
|
|
1651
|
+
37,
|
|
1652
|
+
6,
|
|
1653
|
+
1,
|
|
1654
|
+
0,
|
|
1655
|
+
0,
|
|
1656
|
+
16,
|
|
1657
|
+
0,
|
|
1658
|
+
128,
|
|
1659
|
+
129,
|
|
1660
|
+
24,
|
|
1661
|
+
130,
|
|
1662
|
+
1,
|
|
1663
|
+
0,
|
|
1664
|
+
0,
|
|
1665
|
+
0,
|
|
1666
|
+
0,
|
|
1667
|
+
0,
|
|
1668
|
+
0,
|
|
1669
|
+
0,
|
|
1670
|
+
0,
|
|
1671
|
+
47,
|
|
1672
|
+
0,
|
|
1673
|
+
0,
|
|
1674
|
+
0,
|
|
1675
|
+
49,
|
|
1676
|
+
0,
|
|
1677
|
+
51,
|
|
1678
|
+
0,
|
|
1679
|
+
95,
|
|
1680
|
+
0,
|
|
1681
|
+
110,
|
|
1682
|
+
0,
|
|
1683
|
+
99,
|
|
1684
|
+
0,
|
|
1685
|
+
114,
|
|
1686
|
+
0,
|
|
1687
|
+
58,
|
|
1688
|
+
0,
|
|
1689
|
+
49,
|
|
1690
|
+
0,
|
|
1691
|
+
95,
|
|
1692
|
+
0,
|
|
1693
|
+
123,
|
|
1694
|
+
0,
|
|
1695
|
+
49,
|
|
1696
|
+
0,
|
|
1697
|
+
54,
|
|
1698
|
+
0,
|
|
1699
|
+
53,
|
|
1700
|
+
0,
|
|
1701
|
+
48,
|
|
1702
|
+
0,
|
|
1703
|
+
56,
|
|
1704
|
+
0,
|
|
1705
|
+
68,
|
|
1706
|
+
0,
|
|
1707
|
+
54,
|
|
1708
|
+
0,
|
|
1709
|
+
57,
|
|
1710
|
+
0,
|
|
1711
|
+
45,
|
|
1712
|
+
0,
|
|
1713
|
+
67,
|
|
1714
|
+
0,
|
|
1715
|
+
70,
|
|
1716
|
+
0,
|
|
1717
|
+
56,
|
|
1718
|
+
0,
|
|
1719
|
+
55,
|
|
1720
|
+
0,
|
|
1721
|
+
45,
|
|
1722
|
+
0,
|
|
1723
|
+
52,
|
|
1724
|
+
0,
|
|
1725
|
+
55,
|
|
1726
|
+
0,
|
|
1727
|
+
54,
|
|
1728
|
+
0,
|
|
1729
|
+
57,
|
|
1730
|
+
0,
|
|
1731
|
+
45,
|
|
1732
|
+
0,
|
|
1733
|
+
56,
|
|
1734
|
+
0,
|
|
1735
|
+
52,
|
|
1736
|
+
0,
|
|
1737
|
+
53,
|
|
1738
|
+
0,
|
|
1739
|
+
54,
|
|
1740
|
+
0,
|
|
1741
|
+
45,
|
|
1742
|
+
0,
|
|
1743
|
+
68,
|
|
1744
|
+
0,
|
|
1745
|
+
52,
|
|
1746
|
+
0,
|
|
1747
|
+
65,
|
|
1748
|
+
0,
|
|
1749
|
+
52,
|
|
1750
|
+
0,
|
|
1751
|
+
48,
|
|
1752
|
+
0,
|
|
1753
|
+
49,
|
|
1754
|
+
0,
|
|
1755
|
+
49,
|
|
1756
|
+
0,
|
|
1757
|
+
51,
|
|
1758
|
+
0,
|
|
1759
|
+
49,
|
|
1760
|
+
0,
|
|
1761
|
+
53,
|
|
1762
|
+
0,
|
|
1763
|
+
54,
|
|
1764
|
+
0,
|
|
1765
|
+
55,
|
|
1766
|
+
0,
|
|
1767
|
+
125,
|
|
1768
|
+
0,
|
|
1769
|
+
47,
|
|
1770
|
+
0,
|
|
1771
|
+
0,
|
|
1772
|
+
0,
|
|
1773
|
+
47,
|
|
1774
|
+
0,
|
|
1775
|
+
0,
|
|
1776
|
+
0,
|
|
1777
|
+
0,
|
|
1778
|
+
0,
|
|
1779
|
+
0,
|
|
1780
|
+
0,
|
|
1781
|
+
0,
|
|
1782
|
+
0,
|
|
1783
|
+
0,
|
|
1784
|
+
0,
|
|
1785
|
+
0,
|
|
1786
|
+
0,
|
|
1787
|
+
0,
|
|
1788
|
+
0,
|
|
1789
|
+
0,
|
|
1790
|
+
0,
|
|
1791
|
+
0,
|
|
1792
|
+
0,
|
|
1793
|
+
38,
|
|
1794
|
+
0,
|
|
1795
|
+
135,
|
|
1796
|
+
1,
|
|
1797
|
+
0,
|
|
1798
|
+
37,
|
|
1799
|
+
6,
|
|
1800
|
+
1,
|
|
1801
|
+
0,
|
|
1802
|
+
2,
|
|
1803
|
+
16,
|
|
1804
|
+
0,
|
|
1805
|
+
128,
|
|
1806
|
+
128,
|
|
1807
|
+
24,
|
|
1808
|
+
16,
|
|
1809
|
+
0,
|
|
1810
|
+
0,
|
|
1811
|
+
0,
|
|
1812
|
+
0,
|
|
1813
|
+
13,
|
|
1814
|
+
0,
|
|
1815
|
+
0,
|
|
1816
|
+
0,
|
|
1817
|
+
255,
|
|
1818
|
+
255,
|
|
1819
|
+
255,
|
|
1820
|
+
255,
|
|
1821
|
+
0,
|
|
1822
|
+
0,
|
|
1823
|
+
0,
|
|
1824
|
+
0,
|
|
1825
|
+
38,
|
|
1826
|
+
0,
|
|
1827
|
+
158,
|
|
1828
|
+
1,
|
|
1829
|
+
29,
|
|
1830
|
+
0,
|
|
1831
|
+
0,
|
|
1832
|
+
0,
|
|
1833
|
+
0,
|
|
1834
|
+
158,
|
|
1835
|
+
22,
|
|
1836
|
+
0,
|
|
1837
|
+
0,
|
|
1838
|
+
180,
|
|
1839
|
+
105,
|
|
1840
|
+
0,
|
|
1841
|
+
0,
|
|
1842
|
+
232,
|
|
1843
|
+
38,
|
|
1844
|
+
0,
|
|
1845
|
+
0,
|
|
1846
|
+
88,
|
|
1847
|
+
2,
|
|
1848
|
+
0,
|
|
1849
|
+
0,
|
|
1850
|
+
0,
|
|
1851
|
+
0,
|
|
1852
|
+
0,
|
|
1853
|
+
0,
|
|
1854
|
+
0,
|
|
1855
|
+
0,
|
|
1856
|
+
0,
|
|
1857
|
+
0,
|
|
1858
|
+
120,
|
|
1859
|
+
136,
|
|
1860
|
+
1,
|
|
1861
|
+
0,
|
|
1862
|
+
143,
|
|
1863
|
+
1,
|
|
1864
|
+
0
|
|
1865
|
+
]);
|
|
1866
|
+
this._workbookBinMiddle = Buffer.from([144, 1, 0]);
|
|
1867
|
+
this._workbookBinEnd = Buffer.from([
|
|
1868
|
+
157,
|
|
1869
|
+
1,
|
|
1870
|
+
26,
|
|
1871
|
+
53,
|
|
1872
|
+
234,
|
|
1873
|
+
2,
|
|
1874
|
+
0,
|
|
1875
|
+
1,
|
|
1876
|
+
0,
|
|
1877
|
+
0,
|
|
1878
|
+
0,
|
|
1879
|
+
100,
|
|
1880
|
+
0,
|
|
1881
|
+
0,
|
|
1882
|
+
0,
|
|
1883
|
+
252,
|
|
1884
|
+
169,
|
|
1885
|
+
241,
|
|
1886
|
+
210,
|
|
1887
|
+
77,
|
|
1888
|
+
98,
|
|
1889
|
+
80,
|
|
1890
|
+
63,
|
|
1891
|
+
1,
|
|
1892
|
+
0,
|
|
1893
|
+
0,
|
|
1894
|
+
0,
|
|
1895
|
+
106,
|
|
1896
|
+
0,
|
|
1897
|
+
155,
|
|
1898
|
+
1,
|
|
1899
|
+
1,
|
|
1900
|
+
0,
|
|
1901
|
+
35,
|
|
1902
|
+
4,
|
|
1903
|
+
3,
|
|
1904
|
+
15,
|
|
1905
|
+
0,
|
|
1906
|
+
0,
|
|
1907
|
+
171,
|
|
1908
|
+
16,
|
|
1909
|
+
1,
|
|
1910
|
+
1,
|
|
1911
|
+
36,
|
|
1912
|
+
0,
|
|
1913
|
+
132,
|
|
1914
|
+
1,
|
|
1915
|
+
0
|
|
1916
|
+
]);
|
|
1917
|
+
this._stylesBin = Buffer.from([
|
|
1918
|
+
150,
|
|
1919
|
+
2,
|
|
1920
|
+
0,
|
|
1921
|
+
231,
|
|
1922
|
+
4,
|
|
1923
|
+
4,
|
|
1924
|
+
2,
|
|
1925
|
+
0,
|
|
1926
|
+
0,
|
|
1927
|
+
0,
|
|
1928
|
+
44,
|
|
1929
|
+
44,
|
|
1930
|
+
164,
|
|
1931
|
+
0,
|
|
1932
|
+
19,
|
|
1933
|
+
0,
|
|
1934
|
+
0,
|
|
1935
|
+
0,
|
|
1936
|
+
121,
|
|
1937
|
+
0,
|
|
1938
|
+
121,
|
|
1939
|
+
0,
|
|
1940
|
+
121,
|
|
1941
|
+
0,
|
|
1942
|
+
121,
|
|
1943
|
+
0,
|
|
1944
|
+
92,
|
|
1945
|
+
0,
|
|
1946
|
+
45,
|
|
1947
|
+
0,
|
|
1948
|
+
109,
|
|
1949
|
+
0,
|
|
1950
|
+
109,
|
|
1951
|
+
0,
|
|
1952
|
+
92,
|
|
1953
|
+
0,
|
|
1954
|
+
45,
|
|
1955
|
+
0,
|
|
1956
|
+
100,
|
|
1957
|
+
0,
|
|
1958
|
+
100,
|
|
1959
|
+
0,
|
|
1960
|
+
92,
|
|
1961
|
+
0,
|
|
1962
|
+
32,
|
|
1963
|
+
0,
|
|
1964
|
+
104,
|
|
1965
|
+
0,
|
|
1966
|
+
104,
|
|
1967
|
+
0,
|
|
1968
|
+
58,
|
|
1969
|
+
0,
|
|
1970
|
+
109,
|
|
1971
|
+
0,
|
|
1972
|
+
109,
|
|
1973
|
+
0,
|
|
1974
|
+
44,
|
|
1975
|
+
30,
|
|
1976
|
+
166,
|
|
1977
|
+
0,
|
|
1978
|
+
12,
|
|
1979
|
+
0,
|
|
1980
|
+
0,
|
|
1981
|
+
0,
|
|
1982
|
+
121,
|
|
1983
|
+
0,
|
|
1984
|
+
121,
|
|
1985
|
+
0,
|
|
1986
|
+
121,
|
|
1987
|
+
0,
|
|
1988
|
+
121,
|
|
1989
|
+
0,
|
|
1990
|
+
92,
|
|
1991
|
+
0,
|
|
1992
|
+
45,
|
|
1993
|
+
0,
|
|
1994
|
+
109,
|
|
1995
|
+
0,
|
|
1996
|
+
109,
|
|
1997
|
+
0,
|
|
1998
|
+
92,
|
|
1999
|
+
0,
|
|
2000
|
+
45,
|
|
2001
|
+
0,
|
|
2002
|
+
100,
|
|
2003
|
+
0,
|
|
2004
|
+
100,
|
|
2005
|
+
0,
|
|
2006
|
+
232,
|
|
2007
|
+
4,
|
|
2008
|
+
0,
|
|
2009
|
+
227,
|
|
2010
|
+
4,
|
|
2011
|
+
4,
|
|
2012
|
+
1,
|
|
2013
|
+
0,
|
|
2014
|
+
0,
|
|
2015
|
+
0,
|
|
2016
|
+
43,
|
|
2017
|
+
39,
|
|
2018
|
+
220,
|
|
2019
|
+
0,
|
|
2020
|
+
0,
|
|
2021
|
+
0,
|
|
2022
|
+
144,
|
|
2023
|
+
1,
|
|
2024
|
+
0,
|
|
2025
|
+
0,
|
|
2026
|
+
0,
|
|
2027
|
+
2,
|
|
2028
|
+
0,
|
|
2029
|
+
0,
|
|
2030
|
+
7,
|
|
2031
|
+
1,
|
|
2032
|
+
0,
|
|
2033
|
+
0,
|
|
2034
|
+
0,
|
|
2035
|
+
0,
|
|
2036
|
+
0,
|
|
2037
|
+
255,
|
|
2038
|
+
2,
|
|
2039
|
+
7,
|
|
2040
|
+
0,
|
|
2041
|
+
0,
|
|
2042
|
+
0,
|
|
2043
|
+
67,
|
|
2044
|
+
0,
|
|
2045
|
+
97,
|
|
2046
|
+
0,
|
|
2047
|
+
108,
|
|
2048
|
+
0,
|
|
2049
|
+
105,
|
|
2050
|
+
0,
|
|
2051
|
+
98,
|
|
2052
|
+
0,
|
|
2053
|
+
114,
|
|
2054
|
+
0,
|
|
2055
|
+
105,
|
|
2056
|
+
0,
|
|
2057
|
+
43,
|
|
2058
|
+
39,
|
|
2059
|
+
220,
|
|
2060
|
+
0,
|
|
2061
|
+
1,
|
|
2062
|
+
0,
|
|
2063
|
+
188,
|
|
2064
|
+
2,
|
|
2065
|
+
0,
|
|
2066
|
+
0,
|
|
2067
|
+
0,
|
|
2068
|
+
2,
|
|
2069
|
+
238,
|
|
2070
|
+
0,
|
|
2071
|
+
7,
|
|
2072
|
+
1,
|
|
2073
|
+
0,
|
|
2074
|
+
0,
|
|
2075
|
+
0,
|
|
2076
|
+
0,
|
|
2077
|
+
0,
|
|
2078
|
+
255,
|
|
2079
|
+
2,
|
|
2080
|
+
7,
|
|
2081
|
+
0,
|
|
2082
|
+
0,
|
|
2083
|
+
0,
|
|
2084
|
+
67,
|
|
2085
|
+
0,
|
|
2086
|
+
97,
|
|
2087
|
+
0,
|
|
2088
|
+
108,
|
|
2089
|
+
0,
|
|
2090
|
+
105,
|
|
2091
|
+
0,
|
|
2092
|
+
98,
|
|
2093
|
+
0,
|
|
2094
|
+
114,
|
|
2095
|
+
0,
|
|
2096
|
+
105,
|
|
2097
|
+
0,
|
|
2098
|
+
37,
|
|
2099
|
+
6,
|
|
2100
|
+
1,
|
|
2101
|
+
0,
|
|
2102
|
+
2,
|
|
2103
|
+
14,
|
|
2104
|
+
0,
|
|
2105
|
+
128,
|
|
2106
|
+
129,
|
|
2107
|
+
8,
|
|
2108
|
+
0,
|
|
2109
|
+
38,
|
|
2110
|
+
0,
|
|
2111
|
+
228,
|
|
2112
|
+
4,
|
|
2113
|
+
0,
|
|
2114
|
+
219,
|
|
2115
|
+
4,
|
|
2116
|
+
4,
|
|
2117
|
+
2,
|
|
2118
|
+
0,
|
|
2119
|
+
0,
|
|
2120
|
+
0,
|
|
2121
|
+
45,
|
|
2122
|
+
68,
|
|
2123
|
+
0,
|
|
2124
|
+
0,
|
|
2125
|
+
0,
|
|
2126
|
+
0,
|
|
2127
|
+
3,
|
|
2128
|
+
64,
|
|
2129
|
+
0,
|
|
2130
|
+
0,
|
|
2131
|
+
0,
|
|
2132
|
+
0,
|
|
2133
|
+
0,
|
|
2134
|
+
255,
|
|
2135
|
+
3,
|
|
2136
|
+
65,
|
|
2137
|
+
0,
|
|
2138
|
+
0,
|
|
2139
|
+
255,
|
|
2140
|
+
255,
|
|
2141
|
+
255,
|
|
2142
|
+
255,
|
|
2143
|
+
0,
|
|
2144
|
+
0,
|
|
2145
|
+
0,
|
|
2146
|
+
0,
|
|
2147
|
+
0,
|
|
2148
|
+
0,
|
|
2149
|
+
0,
|
|
2150
|
+
0,
|
|
2151
|
+
0,
|
|
2152
|
+
0,
|
|
2153
|
+
0,
|
|
2154
|
+
0,
|
|
2155
|
+
0,
|
|
2156
|
+
0,
|
|
2157
|
+
0,
|
|
2158
|
+
0,
|
|
2159
|
+
0,
|
|
2160
|
+
0,
|
|
2161
|
+
0,
|
|
2162
|
+
0,
|
|
2163
|
+
0,
|
|
2164
|
+
0,
|
|
2165
|
+
0,
|
|
2166
|
+
0,
|
|
2167
|
+
0,
|
|
2168
|
+
0,
|
|
2169
|
+
0,
|
|
2170
|
+
0,
|
|
2171
|
+
0,
|
|
2172
|
+
0,
|
|
2173
|
+
0,
|
|
2174
|
+
0,
|
|
2175
|
+
0,
|
|
2176
|
+
0,
|
|
2177
|
+
0,
|
|
2178
|
+
0,
|
|
2179
|
+
0,
|
|
2180
|
+
0,
|
|
2181
|
+
0,
|
|
2182
|
+
0,
|
|
2183
|
+
0,
|
|
2184
|
+
0,
|
|
2185
|
+
0,
|
|
2186
|
+
0,
|
|
2187
|
+
0,
|
|
2188
|
+
0,
|
|
2189
|
+
0,
|
|
2190
|
+
0,
|
|
2191
|
+
45,
|
|
2192
|
+
68,
|
|
2193
|
+
17,
|
|
2194
|
+
0,
|
|
2195
|
+
0,
|
|
2196
|
+
0,
|
|
2197
|
+
3,
|
|
2198
|
+
64,
|
|
2199
|
+
0,
|
|
2200
|
+
0,
|
|
2201
|
+
0,
|
|
2202
|
+
0,
|
|
2203
|
+
0,
|
|
2204
|
+
255,
|
|
2205
|
+
3,
|
|
2206
|
+
65,
|
|
2207
|
+
0,
|
|
2208
|
+
0,
|
|
2209
|
+
255,
|
|
2210
|
+
255,
|
|
2211
|
+
255,
|
|
2212
|
+
255,
|
|
2213
|
+
0,
|
|
2214
|
+
0,
|
|
2215
|
+
0,
|
|
2216
|
+
0,
|
|
2217
|
+
0,
|
|
2218
|
+
0,
|
|
2219
|
+
0,
|
|
2220
|
+
0,
|
|
2221
|
+
0,
|
|
2222
|
+
0,
|
|
2223
|
+
0,
|
|
2224
|
+
0,
|
|
2225
|
+
0,
|
|
2226
|
+
0,
|
|
2227
|
+
0,
|
|
2228
|
+
0,
|
|
2229
|
+
0,
|
|
2230
|
+
0,
|
|
2231
|
+
0,
|
|
2232
|
+
0,
|
|
2233
|
+
0,
|
|
2234
|
+
0,
|
|
2235
|
+
0,
|
|
2236
|
+
0,
|
|
2237
|
+
0,
|
|
2238
|
+
0,
|
|
2239
|
+
0,
|
|
2240
|
+
0,
|
|
2241
|
+
0,
|
|
2242
|
+
0,
|
|
2243
|
+
0,
|
|
2244
|
+
0,
|
|
2245
|
+
0,
|
|
2246
|
+
0,
|
|
2247
|
+
0,
|
|
2248
|
+
0,
|
|
2249
|
+
0,
|
|
2250
|
+
0,
|
|
2251
|
+
0,
|
|
2252
|
+
0,
|
|
2253
|
+
0,
|
|
2254
|
+
0,
|
|
2255
|
+
0,
|
|
2256
|
+
0,
|
|
2257
|
+
0,
|
|
2258
|
+
0,
|
|
2259
|
+
0,
|
|
2260
|
+
0,
|
|
2261
|
+
220,
|
|
2262
|
+
4,
|
|
2263
|
+
0,
|
|
2264
|
+
229,
|
|
2265
|
+
4,
|
|
2266
|
+
4,
|
|
2267
|
+
1,
|
|
2268
|
+
0,
|
|
2269
|
+
0,
|
|
2270
|
+
0,
|
|
2271
|
+
46,
|
|
2272
|
+
51,
|
|
2273
|
+
0,
|
|
2274
|
+
0,
|
|
2275
|
+
0,
|
|
2276
|
+
1,
|
|
2277
|
+
0,
|
|
2278
|
+
0,
|
|
2279
|
+
0,
|
|
2280
|
+
0,
|
|
2281
|
+
0,
|
|
2282
|
+
0,
|
|
2283
|
+
0,
|
|
2284
|
+
0,
|
|
2285
|
+
0,
|
|
2286
|
+
1,
|
|
2287
|
+
0,
|
|
2288
|
+
0,
|
|
2289
|
+
0,
|
|
2290
|
+
0,
|
|
2291
|
+
0,
|
|
2292
|
+
0,
|
|
2293
|
+
0,
|
|
2294
|
+
0,
|
|
2295
|
+
0,
|
|
2296
|
+
1,
|
|
2297
|
+
0,
|
|
2298
|
+
0,
|
|
2299
|
+
0,
|
|
2300
|
+
0,
|
|
2301
|
+
0,
|
|
2302
|
+
0,
|
|
2303
|
+
0,
|
|
2304
|
+
0,
|
|
2305
|
+
0,
|
|
2306
|
+
1,
|
|
2307
|
+
0,
|
|
2308
|
+
0,
|
|
2309
|
+
0,
|
|
2310
|
+
0,
|
|
2311
|
+
0,
|
|
2312
|
+
0,
|
|
2313
|
+
0,
|
|
2314
|
+
0,
|
|
2315
|
+
0,
|
|
2316
|
+
1,
|
|
2317
|
+
0,
|
|
2318
|
+
0,
|
|
2319
|
+
0,
|
|
2320
|
+
0,
|
|
2321
|
+
0,
|
|
2322
|
+
0,
|
|
2323
|
+
0,
|
|
2324
|
+
230,
|
|
2325
|
+
4,
|
|
2326
|
+
0,
|
|
2327
|
+
242,
|
|
2328
|
+
4,
|
|
2329
|
+
4,
|
|
2330
|
+
1,
|
|
2331
|
+
0,
|
|
2332
|
+
0,
|
|
2333
|
+
0,
|
|
2334
|
+
47,
|
|
2335
|
+
16,
|
|
2336
|
+
255,
|
|
2337
|
+
255,
|
|
2338
|
+
0,
|
|
2339
|
+
0,
|
|
2340
|
+
0,
|
|
2341
|
+
0,
|
|
2342
|
+
0,
|
|
2343
|
+
0,
|
|
2344
|
+
0,
|
|
2345
|
+
0,
|
|
2346
|
+
0,
|
|
2347
|
+
0,
|
|
2348
|
+
16,
|
|
2349
|
+
16,
|
|
2350
|
+
0,
|
|
2351
|
+
0,
|
|
2352
|
+
243,
|
|
2353
|
+
4,
|
|
2354
|
+
0,
|
|
2355
|
+
233,
|
|
2356
|
+
4,
|
|
2357
|
+
4,
|
|
2358
|
+
4,
|
|
2359
|
+
0,
|
|
2360
|
+
0,
|
|
2361
|
+
0,
|
|
2362
|
+
47,
|
|
2363
|
+
16,
|
|
2364
|
+
0,
|
|
2365
|
+
0,
|
|
2366
|
+
0,
|
|
2367
|
+
0,
|
|
2368
|
+
0,
|
|
2369
|
+
0,
|
|
2370
|
+
0,
|
|
2371
|
+
0,
|
|
2372
|
+
0,
|
|
2373
|
+
0,
|
|
2374
|
+
0,
|
|
2375
|
+
0,
|
|
2376
|
+
16,
|
|
2377
|
+
16,
|
|
2378
|
+
0,
|
|
2379
|
+
0,
|
|
2380
|
+
47,
|
|
2381
|
+
16,
|
|
2382
|
+
0,
|
|
2383
|
+
0,
|
|
2384
|
+
164,
|
|
2385
|
+
0,
|
|
2386
|
+
0,
|
|
2387
|
+
0,
|
|
2388
|
+
0,
|
|
2389
|
+
0,
|
|
2390
|
+
0,
|
|
2391
|
+
0,
|
|
2392
|
+
0,
|
|
2393
|
+
0,
|
|
2394
|
+
16,
|
|
2395
|
+
16,
|
|
2396
|
+
1,
|
|
2397
|
+
0,
|
|
2398
|
+
47,
|
|
2399
|
+
16,
|
|
2400
|
+
0,
|
|
2401
|
+
0,
|
|
2402
|
+
166,
|
|
2403
|
+
0,
|
|
2404
|
+
0,
|
|
2405
|
+
0,
|
|
2406
|
+
0,
|
|
2407
|
+
0,
|
|
2408
|
+
0,
|
|
2409
|
+
0,
|
|
2410
|
+
0,
|
|
2411
|
+
0,
|
|
2412
|
+
16,
|
|
2413
|
+
16,
|
|
2414
|
+
1,
|
|
2415
|
+
0,
|
|
2416
|
+
47,
|
|
2417
|
+
16,
|
|
2418
|
+
0,
|
|
2419
|
+
0,
|
|
2420
|
+
0,
|
|
2421
|
+
1,
|
|
2422
|
+
1,
|
|
2423
|
+
0,
|
|
2424
|
+
0,
|
|
2425
|
+
0,
|
|
2426
|
+
0,
|
|
2427
|
+
0,
|
|
2428
|
+
0,
|
|
2429
|
+
0,
|
|
2430
|
+
16,
|
|
2431
|
+
16,
|
|
2432
|
+
0,
|
|
2433
|
+
0,
|
|
2434
|
+
234,
|
|
2435
|
+
4,
|
|
2436
|
+
0,
|
|
2437
|
+
235,
|
|
2438
|
+
4,
|
|
2439
|
+
4,
|
|
2440
|
+
1,
|
|
2441
|
+
0,
|
|
2442
|
+
0,
|
|
2443
|
+
0,
|
|
2444
|
+
37,
|
|
2445
|
+
6,
|
|
2446
|
+
1,
|
|
2447
|
+
0,
|
|
2448
|
+
2,
|
|
2449
|
+
17,
|
|
2450
|
+
0,
|
|
2451
|
+
128,
|
|
2452
|
+
128,
|
|
2453
|
+
24,
|
|
2454
|
+
16,
|
|
2455
|
+
0,
|
|
2456
|
+
0,
|
|
2457
|
+
0,
|
|
2458
|
+
0,
|
|
2459
|
+
0,
|
|
2460
|
+
0,
|
|
2461
|
+
0,
|
|
2462
|
+
0,
|
|
2463
|
+
0,
|
|
2464
|
+
0,
|
|
2465
|
+
0,
|
|
2466
|
+
0,
|
|
2467
|
+
0,
|
|
2468
|
+
0,
|
|
2469
|
+
0,
|
|
2470
|
+
0,
|
|
2471
|
+
38,
|
|
2472
|
+
0,
|
|
2473
|
+
48,
|
|
2474
|
+
28,
|
|
2475
|
+
0,
|
|
2476
|
+
0,
|
|
2477
|
+
0,
|
|
2478
|
+
0,
|
|
2479
|
+
1,
|
|
2480
|
+
0,
|
|
2481
|
+
0,
|
|
2482
|
+
0,
|
|
2483
|
+
8,
|
|
2484
|
+
0,
|
|
2485
|
+
0,
|
|
2486
|
+
0,
|
|
2487
|
+
78,
|
|
2488
|
+
0,
|
|
2489
|
+
111,
|
|
2490
|
+
0,
|
|
2491
|
+
114,
|
|
2492
|
+
0,
|
|
2493
|
+
109,
|
|
2494
|
+
0,
|
|
2495
|
+
97,
|
|
2496
|
+
0,
|
|
2497
|
+
108,
|
|
2498
|
+
0,
|
|
2499
|
+
110,
|
|
2500
|
+
0,
|
|
2501
|
+
121,
|
|
2502
|
+
0,
|
|
2503
|
+
236,
|
|
2504
|
+
4,
|
|
2505
|
+
0,
|
|
2506
|
+
249,
|
|
2507
|
+
3,
|
|
2508
|
+
4,
|
|
2509
|
+
0,
|
|
2510
|
+
0,
|
|
2511
|
+
0,
|
|
2512
|
+
0,
|
|
2513
|
+
250,
|
|
2514
|
+
3,
|
|
2515
|
+
0,
|
|
2516
|
+
252,
|
|
2517
|
+
3,
|
|
2518
|
+
80,
|
|
2519
|
+
0,
|
|
2520
|
+
0,
|
|
2521
|
+
0,
|
|
2522
|
+
0,
|
|
2523
|
+
17,
|
|
2524
|
+
0,
|
|
2525
|
+
0,
|
|
2526
|
+
0,
|
|
2527
|
+
84,
|
|
2528
|
+
0,
|
|
2529
|
+
97,
|
|
2530
|
+
0,
|
|
2531
|
+
98,
|
|
2532
|
+
0,
|
|
2533
|
+
108,
|
|
2534
|
+
0,
|
|
2535
|
+
101,
|
|
2536
|
+
0,
|
|
2537
|
+
83,
|
|
2538
|
+
0,
|
|
2539
|
+
116,
|
|
2540
|
+
0,
|
|
2541
|
+
121,
|
|
2542
|
+
0,
|
|
2543
|
+
108,
|
|
2544
|
+
0,
|
|
2545
|
+
101,
|
|
2546
|
+
0,
|
|
2547
|
+
77,
|
|
2548
|
+
0,
|
|
2549
|
+
101,
|
|
2550
|
+
0,
|
|
2551
|
+
100,
|
|
2552
|
+
0,
|
|
2553
|
+
105,
|
|
2554
|
+
0,
|
|
2555
|
+
117,
|
|
2556
|
+
0,
|
|
2557
|
+
109,
|
|
2558
|
+
0,
|
|
2559
|
+
50,
|
|
2560
|
+
0,
|
|
2561
|
+
17,
|
|
2562
|
+
0,
|
|
2563
|
+
0,
|
|
2564
|
+
0,
|
|
2565
|
+
80,
|
|
2566
|
+
0,
|
|
2567
|
+
105,
|
|
2568
|
+
0,
|
|
2569
|
+
118,
|
|
2570
|
+
0,
|
|
2571
|
+
111,
|
|
2572
|
+
0,
|
|
2573
|
+
116,
|
|
2574
|
+
0,
|
|
2575
|
+
83,
|
|
2576
|
+
0,
|
|
2577
|
+
116,
|
|
2578
|
+
0,
|
|
2579
|
+
121,
|
|
2580
|
+
0,
|
|
2581
|
+
108,
|
|
2582
|
+
0,
|
|
2583
|
+
101,
|
|
2584
|
+
0,
|
|
2585
|
+
76,
|
|
2586
|
+
0,
|
|
2587
|
+
105,
|
|
2588
|
+
0,
|
|
2589
|
+
103,
|
|
2590
|
+
0,
|
|
2591
|
+
104,
|
|
2592
|
+
0,
|
|
2593
|
+
116,
|
|
2594
|
+
0,
|
|
2595
|
+
49,
|
|
2596
|
+
0,
|
|
2597
|
+
54,
|
|
2598
|
+
0,
|
|
2599
|
+
253,
|
|
2600
|
+
3,
|
|
2601
|
+
0,
|
|
2602
|
+
35,
|
|
2603
|
+
4,
|
|
2604
|
+
2,
|
|
2605
|
+
14,
|
|
2606
|
+
0,
|
|
2607
|
+
0,
|
|
2608
|
+
235,
|
|
2609
|
+
8,
|
|
2610
|
+
0,
|
|
2611
|
+
246,
|
|
2612
|
+
8,
|
|
2613
|
+
42,
|
|
2614
|
+
0,
|
|
2615
|
+
0,
|
|
2616
|
+
0,
|
|
2617
|
+
0,
|
|
2618
|
+
17,
|
|
2619
|
+
0,
|
|
2620
|
+
0,
|
|
2621
|
+
0,
|
|
2622
|
+
83,
|
|
2623
|
+
0,
|
|
2624
|
+
108,
|
|
2625
|
+
0,
|
|
2626
|
+
105,
|
|
2627
|
+
0,
|
|
2628
|
+
99,
|
|
2629
|
+
0,
|
|
2630
|
+
101,
|
|
2631
|
+
0,
|
|
2632
|
+
114,
|
|
2633
|
+
0,
|
|
2634
|
+
83,
|
|
2635
|
+
0,
|
|
2636
|
+
116,
|
|
2637
|
+
0,
|
|
2638
|
+
121,
|
|
2639
|
+
0,
|
|
2640
|
+
108,
|
|
2641
|
+
0,
|
|
2642
|
+
101,
|
|
2643
|
+
0,
|
|
2644
|
+
76,
|
|
2645
|
+
0,
|
|
2646
|
+
105,
|
|
2647
|
+
0,
|
|
2648
|
+
103,
|
|
2649
|
+
0,
|
|
2650
|
+
104,
|
|
2651
|
+
0,
|
|
2652
|
+
116,
|
|
2653
|
+
0,
|
|
2654
|
+
49,
|
|
2655
|
+
0,
|
|
2656
|
+
247,
|
|
2657
|
+
8,
|
|
2658
|
+
0,
|
|
2659
|
+
236,
|
|
2660
|
+
8,
|
|
2661
|
+
0,
|
|
2662
|
+
36,
|
|
2663
|
+
0,
|
|
2664
|
+
35,
|
|
2665
|
+
4,
|
|
2666
|
+
3,
|
|
2667
|
+
15,
|
|
2668
|
+
0,
|
|
2669
|
+
0,
|
|
2670
|
+
176,
|
|
2671
|
+
16,
|
|
2672
|
+
0,
|
|
2673
|
+
178,
|
|
2674
|
+
16,
|
|
2675
|
+
50,
|
|
2676
|
+
0,
|
|
2677
|
+
0,
|
|
2678
|
+
0,
|
|
2679
|
+
0,
|
|
2680
|
+
21,
|
|
2681
|
+
0,
|
|
2682
|
+
0,
|
|
2683
|
+
0,
|
|
2684
|
+
84,
|
|
2685
|
+
0,
|
|
2686
|
+
105,
|
|
2687
|
+
0,
|
|
2688
|
+
109,
|
|
2689
|
+
0,
|
|
2690
|
+
101,
|
|
2691
|
+
0,
|
|
2692
|
+
83,
|
|
2693
|
+
0,
|
|
2694
|
+
108,
|
|
2695
|
+
0,
|
|
2696
|
+
105,
|
|
2697
|
+
0,
|
|
2698
|
+
99,
|
|
2699
|
+
0,
|
|
2700
|
+
101,
|
|
2701
|
+
0,
|
|
2702
|
+
114,
|
|
2703
|
+
0,
|
|
2704
|
+
83,
|
|
2705
|
+
0,
|
|
2706
|
+
116,
|
|
2707
|
+
0,
|
|
2708
|
+
121,
|
|
2709
|
+
0,
|
|
2710
|
+
108,
|
|
2711
|
+
0,
|
|
2712
|
+
101,
|
|
2713
|
+
0,
|
|
2714
|
+
76,
|
|
2715
|
+
0,
|
|
2716
|
+
105,
|
|
2717
|
+
0,
|
|
2718
|
+
103,
|
|
2719
|
+
0,
|
|
2720
|
+
104,
|
|
2721
|
+
0,
|
|
2722
|
+
116,
|
|
2723
|
+
0,
|
|
2724
|
+
49,
|
|
2725
|
+
0,
|
|
2726
|
+
179,
|
|
2727
|
+
16,
|
|
2728
|
+
0,
|
|
2729
|
+
177,
|
|
2730
|
+
16,
|
|
2731
|
+
0,
|
|
2732
|
+
36,
|
|
2733
|
+
0,
|
|
2734
|
+
151,
|
|
2735
|
+
2,
|
|
2736
|
+
0
|
|
2737
|
+
]);
|
|
2738
|
+
this._binaryIndexBin = Buffer.from([
|
|
2739
|
+
42,
|
|
2740
|
+
24,
|
|
2741
|
+
0,
|
|
2742
|
+
0,
|
|
2743
|
+
0,
|
|
2744
|
+
0,
|
|
2745
|
+
32,
|
|
2746
|
+
0,
|
|
2747
|
+
0,
|
|
2748
|
+
0,
|
|
2749
|
+
0,
|
|
2750
|
+
0,
|
|
2751
|
+
0,
|
|
2752
|
+
0,
|
|
2753
|
+
0,
|
|
2754
|
+
0,
|
|
2755
|
+
0,
|
|
2756
|
+
0,
|
|
2757
|
+
0,
|
|
2758
|
+
0,
|
|
2759
|
+
0,
|
|
2760
|
+
0,
|
|
2761
|
+
0,
|
|
2762
|
+
0,
|
|
2763
|
+
0,
|
|
2764
|
+
0,
|
|
2765
|
+
149,
|
|
2766
|
+
2,
|
|
2767
|
+
0
|
|
2768
|
+
]);
|
|
2769
|
+
this._rRkIntegerLowerLimit = -1 << 29;
|
|
2770
|
+
this._rRkIntegerUpperLimit = (1 << 29) - 1;
|
|
2771
|
+
this._autoFilterStartBytes = Buffer.from([161, 1, 16]);
|
|
2772
|
+
this._autoFilterEndBytes = Buffer.from([162, 1, 0]);
|
|
2773
|
+
this._stickHeaderA1bytes = Buffer.from([
|
|
2774
|
+
151,
|
|
2775
|
+
1,
|
|
2776
|
+
29,
|
|
2777
|
+
0,
|
|
2778
|
+
0,
|
|
2779
|
+
0,
|
|
2780
|
+
0,
|
|
2781
|
+
0,
|
|
2782
|
+
0,
|
|
2783
|
+
0,
|
|
2784
|
+
0,
|
|
2785
|
+
0,
|
|
2786
|
+
0,
|
|
2787
|
+
0,
|
|
2788
|
+
0,
|
|
2789
|
+
0,
|
|
2790
|
+
0,
|
|
2791
|
+
240,
|
|
2792
|
+
63,
|
|
2793
|
+
1,
|
|
2794
|
+
0,
|
|
2795
|
+
0,
|
|
2796
|
+
0,
|
|
2797
|
+
0,
|
|
2798
|
+
0,
|
|
2799
|
+
0,
|
|
2800
|
+
0,
|
|
2801
|
+
2,
|
|
2802
|
+
0,
|
|
2803
|
+
0,
|
|
2804
|
+
0,
|
|
2805
|
+
3
|
|
2806
|
+
]);
|
|
2807
|
+
this._magicFilterExcel2016Fix0 = Buffer.from([225, 2, 0, 229, 2, 0, 234, 2]);
|
|
2808
|
+
this._magicFilterExcel2016Fix1 = Buffer.from([
|
|
2809
|
+
39,
|
|
2810
|
+
70,
|
|
2811
|
+
33,
|
|
2812
|
+
0,
|
|
2813
|
+
0,
|
|
2814
|
+
0,
|
|
2815
|
+
0,
|
|
2816
|
+
255,
|
|
2817
|
+
0,
|
|
2818
|
+
0,
|
|
2819
|
+
0,
|
|
2820
|
+
15,
|
|
2821
|
+
0,
|
|
2822
|
+
0,
|
|
2823
|
+
0,
|
|
2824
|
+
95,
|
|
2825
|
+
0,
|
|
2826
|
+
70,
|
|
2827
|
+
0,
|
|
2828
|
+
105,
|
|
2829
|
+
0,
|
|
2830
|
+
108,
|
|
2831
|
+
0,
|
|
2832
|
+
116,
|
|
2833
|
+
0,
|
|
2834
|
+
101,
|
|
2835
|
+
0,
|
|
2836
|
+
114,
|
|
2837
|
+
0,
|
|
2838
|
+
68,
|
|
2839
|
+
0,
|
|
2840
|
+
97,
|
|
2841
|
+
0,
|
|
2842
|
+
116,
|
|
2843
|
+
0,
|
|
2844
|
+
97,
|
|
2845
|
+
0,
|
|
2846
|
+
98,
|
|
2847
|
+
0,
|
|
2848
|
+
97,
|
|
2849
|
+
0,
|
|
2850
|
+
115,
|
|
2851
|
+
0,
|
|
2852
|
+
101,
|
|
2853
|
+
0,
|
|
2854
|
+
15,
|
|
2855
|
+
0,
|
|
2856
|
+
0,
|
|
2857
|
+
0,
|
|
2858
|
+
59,
|
|
2859
|
+
255,
|
|
2860
|
+
0
|
|
2861
|
+
]);
|
|
2862
|
+
this._magicFilterExcel2016Fix2 = Buffer.from([0, 0, 0, 0, 255, 255, 255, 255]);
|
|
2863
|
+
}
|
|
2864
|
+
/** @deprecated Internal; kept for unit-test access. Prefer sanitizeSheetName(). */
|
|
2865
|
+
_sanitizeSheetName(name) {
|
|
2866
|
+
return sanitizeSheetName(name, this.sheetCount);
|
|
2867
|
+
}
|
|
2868
|
+
_registerFormat(fmtString) {
|
|
2869
|
+
if (this._stFmtRecords.has(fmtString)) {
|
|
2870
|
+
return this._stFmtRecords.get(fmtString).xfIndex;
|
|
2871
|
+
}
|
|
2872
|
+
const numfmtId = this._nextFmtId++;
|
|
2873
|
+
const xfIndex = this._nextXfIdx++;
|
|
2874
|
+
this._stFmtRecords.set(fmtString, { numfmtId, xfIndex });
|
|
2875
|
+
return xfIndex;
|
|
2876
|
+
}
|
|
2877
|
+
static _buildBrtRecord(type, data) {
|
|
2878
|
+
const header = _XlsbWriter._encodeVlq(type);
|
|
2879
|
+
header.push(..._XlsbWriter._encodeVlq(data.length));
|
|
2880
|
+
return Buffer.concat([Buffer.from(header), data]);
|
|
2881
|
+
}
|
|
2882
|
+
static _encodeVlq(value) {
|
|
2883
|
+
const result = [];
|
|
2884
|
+
while (value >= 128) {
|
|
2885
|
+
result.push(value & 127 | 128);
|
|
2886
|
+
value >>>= 7;
|
|
2887
|
+
}
|
|
2888
|
+
result.push(value & 127);
|
|
2889
|
+
return result;
|
|
2890
|
+
}
|
|
2891
|
+
static _buildStFmtRecord(ifmt, fmtString) {
|
|
2892
|
+
const cch = fmtString.length;
|
|
2893
|
+
const remaining = 2 + 4 + cch * 2;
|
|
2894
|
+
const data = Buffer.alloc(2 + remaining);
|
|
2895
|
+
data[0] = 44;
|
|
2896
|
+
data[1] = remaining;
|
|
2897
|
+
data.writeUInt16LE(ifmt, 2);
|
|
2898
|
+
data.writeUInt32LE(cch, 4);
|
|
2899
|
+
data.write(fmtString, 8, cch * 2, "utf16le");
|
|
2900
|
+
return data;
|
|
2901
|
+
}
|
|
2902
|
+
static _buildXfRecord(fontId, ifmt, flags, byte6Extra = 0) {
|
|
2903
|
+
const data = Buffer.alloc(18);
|
|
2904
|
+
data[0] = 47;
|
|
2905
|
+
data[1] = 16;
|
|
2906
|
+
data.writeUInt16LE(fontId, 2);
|
|
2907
|
+
data.writeUInt16LE(ifmt, 4);
|
|
2908
|
+
data[6] = byte6Extra;
|
|
2909
|
+
data[14] = 16;
|
|
2910
|
+
data[15] = 16;
|
|
2911
|
+
data.writeUInt16LE(flags, 16);
|
|
2912
|
+
return data;
|
|
2913
|
+
}
|
|
2914
|
+
_buildStylesBin() {
|
|
2915
|
+
if (this._stFmtRecords.size === 0) {
|
|
2916
|
+
return this._stylesBin;
|
|
2917
|
+
}
|
|
2918
|
+
const base = this._stylesBin;
|
|
2919
|
+
let fontEndOff = -1;
|
|
2920
|
+
for (let i = 3; i < base.length - 3; i++) {
|
|
2921
|
+
if (base[i] === 232 && base[i + 1] === 4 && base[i + 2] === 0) {
|
|
2922
|
+
fontEndOff = i;
|
|
2923
|
+
break;
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
let xfBeginOff = -1;
|
|
2927
|
+
for (let i = fontEndOff + 3; i < base.length - 2; i++) {
|
|
2928
|
+
if (base[i] === 233 && base[i + 1] === 4) {
|
|
2929
|
+
xfBeginOff = i;
|
|
2930
|
+
break;
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
let xfEndOff = -1;
|
|
2934
|
+
for (let i = xfBeginOff; i < base.length - 3; i++) {
|
|
2935
|
+
if (base[i] === 234 && base[i + 1] === 4 && base[i + 2] === 0) {
|
|
2936
|
+
xfEndOff = i;
|
|
2937
|
+
break;
|
|
2938
|
+
}
|
|
2939
|
+
}
|
|
2940
|
+
let fillBeginOff = -1;
|
|
2941
|
+
for (let i = fontEndOff + 3; i < base.length - 2; i++) {
|
|
2942
|
+
if (base[i] === 227 && base[i + 1] === 4) {
|
|
2943
|
+
fillBeginOff = i;
|
|
2944
|
+
break;
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
const totalFmt = 2 + this._stFmtRecords.size;
|
|
2948
|
+
const totalXf = 4 + this._stFmtRecords.size;
|
|
2949
|
+
const parts = [];
|
|
2950
|
+
parts.push(base.subarray(0, 3));
|
|
2951
|
+
const fmtHeader = Buffer.alloc(4);
|
|
2952
|
+
fmtHeader.writeUInt16LE(totalFmt, 0);
|
|
2953
|
+
parts.push(_XlsbWriter._buildBrtRecord(615, fmtHeader));
|
|
2954
|
+
parts.push(_XlsbWriter._buildStFmtRecord(164, "yyyy\\-mm\\-dd\\ hh:mm"));
|
|
2955
|
+
parts.push(_XlsbWriter._buildStFmtRecord(166, "yyyy\\-mm\\-dd"));
|
|
2956
|
+
for (const [fmtString, st] of this._stFmtRecords) {
|
|
2957
|
+
parts.push(_XlsbWriter._buildStFmtRecord(st.numfmtId, fmtString));
|
|
2958
|
+
}
|
|
2959
|
+
parts.push(_XlsbWriter._buildBrtRecord(616, Buffer.alloc(0)));
|
|
2960
|
+
parts.push(base.subarray(fillBeginOff, xfBeginOff));
|
|
2961
|
+
const xfHeader = Buffer.alloc(4);
|
|
2962
|
+
xfHeader.writeUInt16LE(totalXf, 0);
|
|
2963
|
+
parts.push(_XlsbWriter._buildBrtRecord(617, xfHeader));
|
|
2964
|
+
parts.push(_XlsbWriter._buildXfRecord(0, 0, 0));
|
|
2965
|
+
parts.push(_XlsbWriter._buildXfRecord(0, 164, 1));
|
|
2966
|
+
parts.push(_XlsbWriter._buildXfRecord(0, 166, 1));
|
|
2967
|
+
parts.push(_XlsbWriter._buildXfRecord(1, 0, 0, 1));
|
|
2968
|
+
const sortedXf = [...this._stFmtRecords.entries()].sort((a, b) => a[1].xfIndex - b[1].xfIndex);
|
|
2969
|
+
for (const [, st] of sortedXf) {
|
|
2970
|
+
parts.push(_XlsbWriter._buildXfRecord(0, st.numfmtId, 1));
|
|
2971
|
+
}
|
|
2972
|
+
parts.push(_XlsbWriter._buildBrtRecord(618, Buffer.alloc(0)));
|
|
2973
|
+
parts.push(base.subarray(xfEndOff + 3));
|
|
2974
|
+
return Buffer.concat(parts);
|
|
2975
|
+
}
|
|
2976
|
+
/**
|
|
2977
|
+
* Register a worksheet (metadata only). Prefer `writeSheet` / `startSheet` for data.
|
|
2978
|
+
* @param sheetName Display name (sanitized to Excel rules)
|
|
2979
|
+
* @param hidden Whether the sheet is hidden in Excel
|
|
2980
|
+
*/
|
|
2981
|
+
addSheet(sheetName, hidden = false) {
|
|
2982
|
+
const sanitizedName = sanitizeSheetName(sheetName, this.sheetCount);
|
|
2983
|
+
this.sheetCount++;
|
|
2984
|
+
this.sheetList.push({
|
|
2985
|
+
name: sanitizedName,
|
|
2986
|
+
pathInArchive: `xl/worksheets/sheet${this.sheetCount}.bin`,
|
|
2987
|
+
hidden,
|
|
2988
|
+
nameInArchive: `sheet${this.sheetCount}.bin`,
|
|
2989
|
+
sheetId: this.sheetCount,
|
|
2990
|
+
filterHeaderRange: null
|
|
2991
|
+
});
|
|
2992
|
+
}
|
|
2993
|
+
/**
|
|
2994
|
+
* Start a new sheet in streaming mode. Call writeRow() for each row, then endSheet() when done.
|
|
2995
|
+
* @param sheetName Name of the sheet
|
|
2996
|
+
* @param columnCount Number of columns in the sheet
|
|
2997
|
+
* @param headers Optional header row
|
|
2998
|
+
* @param options Optional settings (hidden, doAutofilter)
|
|
2999
|
+
*/
|
|
3000
|
+
startSheet(sheetName, columnCount, headers, options = {}) {
|
|
3001
|
+
const { hidden = false, doAutofilter = true, sampleRows } = options;
|
|
3002
|
+
this.addSheet(sheetName, hidden);
|
|
3003
|
+
this.stream.begin(columnCount, doAutofilter && headers !== void 0, new BigBuffer());
|
|
3004
|
+
const bigBuf = this.stream.buffer;
|
|
3005
|
+
if (headers) {
|
|
3006
|
+
applyHeaderWidths(this.stream.colWidths, headers, columnCount);
|
|
3007
|
+
}
|
|
3008
|
+
if (sampleRows) {
|
|
3009
|
+
updateColWidthsFromRows(this.stream.colWidths, sampleRows);
|
|
3010
|
+
}
|
|
3011
|
+
const sheetHeader = Buffer.from(this._sheet1Bytes);
|
|
3012
|
+
sheetHeader.writeInt32LE(this.stream.startCol, 40);
|
|
3013
|
+
sheetHeader.writeInt32LE(this.stream.endCol, 44);
|
|
3014
|
+
if (this.sheetCount !== 1) {
|
|
3015
|
+
sheetHeader[54] = 156;
|
|
3016
|
+
}
|
|
3017
|
+
bigBuf.write(sheetHeader.subarray(0, 84));
|
|
3018
|
+
if (headers) {
|
|
3019
|
+
bigBuf.write(this._stickHeaderA1bytes);
|
|
3020
|
+
}
|
|
3021
|
+
bigBuf.write(sheetHeader.subarray(84, 159));
|
|
3022
|
+
bigBuf.writeByte(134);
|
|
3023
|
+
bigBuf.writeByte(3);
|
|
3024
|
+
for (let i = this.stream.startCol; i < this.stream.endCol; i++) {
|
|
3025
|
+
bigBuf.writeByte(0);
|
|
3026
|
+
bigBuf.writeByte(60);
|
|
3027
|
+
bigBuf.writeByte(18);
|
|
3028
|
+
bigBuf.writeInt32LE(i);
|
|
3029
|
+
bigBuf.writeInt32LE(i);
|
|
3030
|
+
const width = defaultColWidth(this.stream.colWidths[i], true);
|
|
3031
|
+
bigBuf.writeByte(0);
|
|
3032
|
+
bigBuf.writeByte(Math.max(0, Math.min(255, width)));
|
|
3033
|
+
bigBuf.writeByte(0);
|
|
3034
|
+
bigBuf.writeByte(0);
|
|
3035
|
+
bigBuf.writeByte(0);
|
|
3036
|
+
bigBuf.writeByte(0);
|
|
3037
|
+
bigBuf.writeByte(0);
|
|
3038
|
+
bigBuf.writeByte(0);
|
|
3039
|
+
bigBuf.writeByte(2);
|
|
3040
|
+
}
|
|
3041
|
+
bigBuf.writeByte(0);
|
|
3042
|
+
bigBuf.writeByte(135);
|
|
3043
|
+
bigBuf.writeByte(3);
|
|
3044
|
+
bigBuf.writeByte(0);
|
|
3045
|
+
bigBuf.write(sheetHeader.subarray(159, 175));
|
|
3046
|
+
bigBuf.write(Buffer.from([38, 0]));
|
|
3047
|
+
if (headers) {
|
|
3048
|
+
this.createRowHeader(bigBuf, this.stream.rowNum, this.stream.startCol, this.stream.endCol);
|
|
3049
|
+
for (let c = 0; c < headers.length; c++) {
|
|
3050
|
+
this.writeString(bigBuf, headers[c], c, true);
|
|
3051
|
+
}
|
|
3052
|
+
this.stream.rowNum++;
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
/**
|
|
3056
|
+
* Write a single row in streaming mode. Must be called between startSheet() and endSheet().
|
|
3057
|
+
* @param row Array of cell values
|
|
3058
|
+
*/
|
|
3059
|
+
writeRow(row) {
|
|
3060
|
+
const bigBuf = this.stream.assertStreaming();
|
|
3061
|
+
if (row.length !== this.stream.endCol - this.stream.startCol) {
|
|
3062
|
+
throw new Error(
|
|
3063
|
+
`Row length mismatch. Expected ${this.stream.endCol - this.stream.startCol} columns, got ${row.length}`
|
|
3064
|
+
);
|
|
3065
|
+
}
|
|
3066
|
+
this.createRowHeader(bigBuf, this.stream.rowNum, this.stream.startCol, this.stream.endCol);
|
|
3067
|
+
for (let c = 0; c < row.length; c++) {
|
|
3068
|
+
const raw = row[c];
|
|
3069
|
+
if (raw === null || raw === void 0) continue;
|
|
3070
|
+
const fmtString = getFormat(raw);
|
|
3071
|
+
const val = fmtString !== null ? unwrapCell(raw) : raw;
|
|
3072
|
+
const styleNum = fmtString !== null ? this._registerFormat(fmtString) : 0;
|
|
3073
|
+
if (typeof val === "number") {
|
|
3074
|
+
if (Number.isInteger(val)) {
|
|
3075
|
+
if (val >= this._rRkIntegerLowerLimit && val <= this._rRkIntegerUpperLimit) {
|
|
3076
|
+
this.writeRkNumberInteger(bigBuf, val, c, styleNum);
|
|
3077
|
+
} else {
|
|
3078
|
+
this.writeDouble(bigBuf, val, c, styleNum);
|
|
3079
|
+
}
|
|
3080
|
+
} else {
|
|
3081
|
+
this.writeDouble(bigBuf, val, c, styleNum);
|
|
3082
|
+
}
|
|
3083
|
+
} else if (typeof val === "bigint") {
|
|
3084
|
+
this.writeString(bigBuf, val.toString(), c);
|
|
3085
|
+
} else if (typeof val === "boolean") {
|
|
3086
|
+
this.writeBool(bigBuf, val, c);
|
|
3087
|
+
} else if (val instanceof Date) {
|
|
3088
|
+
const oaDate = (val.getTime() - this._oaEpoch) / 864e5;
|
|
3089
|
+
this.writeDouble(bigBuf, oaDate, c, fmtString !== null ? styleNum : 1);
|
|
3090
|
+
} else if (val !== null && val !== void 0) {
|
|
3091
|
+
this.writeString(bigBuf, val.toString(), c, false, fmtString !== null ? styleNum : void 0);
|
|
3092
|
+
}
|
|
3093
|
+
}
|
|
3094
|
+
this.stream.rowNum++;
|
|
3095
|
+
}
|
|
3096
|
+
/**
|
|
3097
|
+
* Finalize the current streaming sheet and add it to the archive.
|
|
3098
|
+
* Must be called after startSheet() and writeRow() calls.
|
|
3099
|
+
*/
|
|
3100
|
+
endSheet() {
|
|
3101
|
+
const bigBuf = this.stream.assertStreaming();
|
|
3102
|
+
const sheetHeader = Buffer.from(this._sheet1Bytes);
|
|
3103
|
+
bigBuf.write(sheetHeader.subarray(218, 290));
|
|
3104
|
+
if (this.stream.doAutofilter) {
|
|
3105
|
+
this._autofilterIsOn = true;
|
|
3106
|
+
const endRow = this.stream.rowNum;
|
|
3107
|
+
bigBuf.write(this._autoFilterStartBytes);
|
|
3108
|
+
const rowBuf = Buffer.alloc(8);
|
|
3109
|
+
rowBuf.writeInt32LE(0, 0);
|
|
3110
|
+
rowBuf.writeInt32LE(endRow - 1, 4);
|
|
3111
|
+
bigBuf.write(rowBuf);
|
|
3112
|
+
const colBuf = Buffer.alloc(8);
|
|
3113
|
+
colBuf.writeInt32LE(this.stream.startCol, 0);
|
|
3114
|
+
colBuf.writeInt32LE(this.stream.endCol - 1, 4);
|
|
3115
|
+
bigBuf.write(colBuf);
|
|
3116
|
+
bigBuf.write(this._autoFilterEndBytes);
|
|
3117
|
+
const sheet = this.sheetList[this.sheetCount - 1];
|
|
3118
|
+
sheet.filterData = {
|
|
3119
|
+
startRow: 0,
|
|
3120
|
+
endRow: endRow - 1,
|
|
3121
|
+
startColumn: this.stream.startCol,
|
|
3122
|
+
endColumn: this.stream.endCol - 1
|
|
3123
|
+
};
|
|
3124
|
+
}
|
|
3125
|
+
bigBuf.write(sheetHeader.subarray(290));
|
|
3126
|
+
this.archive.append(import_stream.Readable.from(bigBuf.getChunks()), {
|
|
3127
|
+
name: this.sheetList[this.sheetCount - 1].pathInArchive
|
|
3128
|
+
});
|
|
3129
|
+
this.stream.end();
|
|
3130
|
+
}
|
|
3131
|
+
/**
|
|
3132
|
+
* Write an entire sheet in one call (batch mode).
|
|
3133
|
+
* @param rows Data rows (`CellValue` cells; null/undefined = blank)
|
|
3134
|
+
* @param headers Optional header row (bold + frozen + autofilter when enabled)
|
|
3135
|
+
* @param doAutofilter Enable autofilter when headers are present (default true)
|
|
3136
|
+
*/
|
|
3137
|
+
writeSheet(rows, headers = null, doAutofilter = true) {
|
|
3138
|
+
const bigBuf = new BigBuffer();
|
|
3139
|
+
let columnCount = 0;
|
|
3140
|
+
if (rows.length > 0) {
|
|
3141
|
+
columnCount = rows[0].length;
|
|
3142
|
+
} else if (headers) {
|
|
3143
|
+
columnCount = headers.length;
|
|
3144
|
+
}
|
|
3145
|
+
const colWidths = initColWidths(columnCount);
|
|
3146
|
+
if (headers) {
|
|
3147
|
+
applyHeaderWidths(colWidths, headers, columnCount);
|
|
3148
|
+
}
|
|
3149
|
+
updateColWidthsFromRows(colWidths, rows);
|
|
3150
|
+
const sheetHeader = Buffer.from(this._sheet1Bytes);
|
|
3151
|
+
const startCol = 0;
|
|
3152
|
+
const endCol = columnCount;
|
|
3153
|
+
sheetHeader.writeInt32LE(startCol, 40);
|
|
3154
|
+
sheetHeader.writeInt32LE(endCol, 44);
|
|
3155
|
+
if (this.sheetCount !== 1) {
|
|
3156
|
+
sheetHeader[54] = 156;
|
|
3157
|
+
}
|
|
3158
|
+
bigBuf.write(sheetHeader.subarray(0, 84));
|
|
3159
|
+
if (headers) {
|
|
3160
|
+
bigBuf.write(this._stickHeaderA1bytes);
|
|
3161
|
+
}
|
|
3162
|
+
bigBuf.write(sheetHeader.subarray(84, 159));
|
|
3163
|
+
bigBuf.writeByte(134);
|
|
3164
|
+
bigBuf.writeByte(3);
|
|
3165
|
+
for (let i = startCol; i < endCol; i++) {
|
|
3166
|
+
bigBuf.writeByte(0);
|
|
3167
|
+
bigBuf.writeByte(60);
|
|
3168
|
+
bigBuf.writeByte(18);
|
|
3169
|
+
bigBuf.writeInt32LE(i);
|
|
3170
|
+
bigBuf.writeInt32LE(i);
|
|
3171
|
+
const width = defaultColWidth(colWidths[i], true);
|
|
3172
|
+
bigBuf.writeByte(0);
|
|
3173
|
+
bigBuf.writeByte(Math.max(0, Math.min(255, width)));
|
|
3174
|
+
bigBuf.writeByte(0);
|
|
3175
|
+
bigBuf.writeByte(0);
|
|
3176
|
+
bigBuf.writeByte(0);
|
|
3177
|
+
bigBuf.writeByte(0);
|
|
3178
|
+
bigBuf.writeByte(0);
|
|
3179
|
+
bigBuf.writeByte(0);
|
|
3180
|
+
bigBuf.writeByte(2);
|
|
3181
|
+
}
|
|
3182
|
+
bigBuf.writeByte(0);
|
|
3183
|
+
bigBuf.writeByte(135);
|
|
3184
|
+
bigBuf.writeByte(3);
|
|
3185
|
+
bigBuf.writeByte(0);
|
|
3186
|
+
bigBuf.write(sheetHeader.subarray(159, 175));
|
|
3187
|
+
bigBuf.write(Buffer.from([38, 0]));
|
|
3188
|
+
let rowNum = 0;
|
|
3189
|
+
if (headers) {
|
|
3190
|
+
this.createRowHeader(bigBuf, rowNum, startCol, endCol);
|
|
3191
|
+
for (let c = 0; c < headers.length; c++) {
|
|
3192
|
+
this.writeString(bigBuf, headers[c], c, true);
|
|
3193
|
+
}
|
|
3194
|
+
rowNum++;
|
|
3195
|
+
}
|
|
3196
|
+
for (let r = 0; r < rows.length; r++) {
|
|
3197
|
+
this.createRowHeader(bigBuf, rowNum, startCol, endCol);
|
|
3198
|
+
const row = rows[r];
|
|
3199
|
+
for (let c = 0; c < row.length; c++) {
|
|
3200
|
+
const raw = row[c];
|
|
3201
|
+
if (raw === null || raw === void 0) continue;
|
|
3202
|
+
const fmtString = getFormat(raw);
|
|
3203
|
+
const val = fmtString !== null ? unwrapCell(raw) : raw;
|
|
3204
|
+
const styleNum = fmtString !== null ? this._registerFormat(fmtString) : 0;
|
|
3205
|
+
if (typeof val === "number") {
|
|
3206
|
+
if (Number.isInteger(val)) {
|
|
3207
|
+
if (val >= this._rRkIntegerLowerLimit && val <= this._rRkIntegerUpperLimit) {
|
|
3208
|
+
this.writeRkNumberInteger(bigBuf, val, c, styleNum);
|
|
3209
|
+
} else {
|
|
3210
|
+
this.writeDouble(bigBuf, val, c, styleNum);
|
|
3211
|
+
}
|
|
3212
|
+
} else {
|
|
3213
|
+
this.writeDouble(bigBuf, val, c, styleNum);
|
|
3214
|
+
}
|
|
3215
|
+
} else if (typeof val === "bigint") {
|
|
3216
|
+
this.writeString(bigBuf, val.toString(), c);
|
|
3217
|
+
} else if (typeof val === "boolean") {
|
|
3218
|
+
this.writeBool(bigBuf, val, c);
|
|
3219
|
+
} else if (val instanceof Date) {
|
|
3220
|
+
const oaDate = (val.getTime() - this._oaEpoch) / 864e5;
|
|
3221
|
+
this.writeDouble(bigBuf, oaDate, c, fmtString !== null ? styleNum : 1);
|
|
3222
|
+
} else if (val !== null && val !== void 0) {
|
|
3223
|
+
this.writeString(bigBuf, val.toString(), c, false, fmtString !== null ? styleNum : void 0);
|
|
3224
|
+
}
|
|
3225
|
+
}
|
|
3226
|
+
rowNum++;
|
|
3227
|
+
}
|
|
3228
|
+
bigBuf.write(sheetHeader.subarray(218, 290));
|
|
3229
|
+
if (doAutofilter && headers) {
|
|
3230
|
+
this._autofilterIsOn = true;
|
|
3231
|
+
const endRow = rows.length + 1;
|
|
3232
|
+
bigBuf.write(this._autoFilterStartBytes);
|
|
3233
|
+
const rowBuf = Buffer.alloc(8);
|
|
3234
|
+
rowBuf.writeInt32LE(0, 0);
|
|
3235
|
+
rowBuf.writeInt32LE(endRow - 1, 4);
|
|
3236
|
+
bigBuf.write(rowBuf);
|
|
3237
|
+
const colBuf = Buffer.alloc(8);
|
|
3238
|
+
colBuf.writeInt32LE(startCol, 0);
|
|
3239
|
+
colBuf.writeInt32LE(endCol - 1, 4);
|
|
3240
|
+
bigBuf.write(colBuf);
|
|
3241
|
+
bigBuf.write(this._autoFilterEndBytes);
|
|
3242
|
+
const sheet = this.sheetList[this.sheetCount - 1];
|
|
3243
|
+
sheet.filterData = {
|
|
3244
|
+
startRow: 0,
|
|
3245
|
+
endRow: rows.length,
|
|
3246
|
+
startColumn: startCol,
|
|
3247
|
+
endColumn: endCol - 1
|
|
3248
|
+
};
|
|
3249
|
+
}
|
|
3250
|
+
bigBuf.write(sheetHeader.subarray(290));
|
|
3251
|
+
this.archive.append(import_stream.Readable.from(bigBuf.getChunks()), { name: this.sheetList[this.sheetCount - 1].pathInArchive });
|
|
3252
|
+
}
|
|
3253
|
+
createRowHeader(bigBuf, rowNumber, startCol, endCol) {
|
|
3254
|
+
bigBuf.ensureCapacity(27);
|
|
3255
|
+
bigBuf.writeUnsafeByte(0);
|
|
3256
|
+
bigBuf.writeUnsafeByte(25);
|
|
3257
|
+
bigBuf.writeUnsafeInt32LE(rowNumber);
|
|
3258
|
+
bigBuf.writeUnsafeInt32LE(0);
|
|
3259
|
+
bigBuf.writeUnsafeByte(44);
|
|
3260
|
+
bigBuf.writeUnsafeByte(1);
|
|
3261
|
+
bigBuf.writeUnsafeByte(0);
|
|
3262
|
+
bigBuf.writeUnsafeByte(0);
|
|
3263
|
+
bigBuf.writeUnsafeByte(0);
|
|
3264
|
+
bigBuf.writeUnsafeByte(1);
|
|
3265
|
+
bigBuf.writeUnsafeByte(0);
|
|
3266
|
+
bigBuf.writeUnsafeByte(0);
|
|
3267
|
+
bigBuf.writeUnsafeByte(0);
|
|
3268
|
+
bigBuf.writeUnsafeInt32LE(startCol);
|
|
3269
|
+
bigBuf.writeUnsafeInt32LE(endCol);
|
|
3270
|
+
}
|
|
3271
|
+
writeRkNumberInteger(bigBuf, val, colNum, styleNum = 0) {
|
|
3272
|
+
bigBuf.ensureCapacity(14);
|
|
3273
|
+
bigBuf.writeUnsafeByte(2);
|
|
3274
|
+
bigBuf.writeUnsafeByte(12);
|
|
3275
|
+
bigBuf.writeUnsafeInt32LE(colNum);
|
|
3276
|
+
bigBuf.writeUnsafeByte(styleNum);
|
|
3277
|
+
bigBuf.writeUnsafeByte(0);
|
|
3278
|
+
bigBuf.writeUnsafeByte(0);
|
|
3279
|
+
bigBuf.writeUnsafeByte(0);
|
|
3280
|
+
const rkVal = val << 2 | 2;
|
|
3281
|
+
bigBuf.writeUnsafeInt32LE(rkVal);
|
|
3282
|
+
}
|
|
3283
|
+
writeDouble(bigBuf, val, colNum, styleNum = 0) {
|
|
3284
|
+
bigBuf.ensureCapacity(18);
|
|
3285
|
+
bigBuf.writeUnsafeByte(5);
|
|
3286
|
+
bigBuf.writeUnsafeByte(16);
|
|
3287
|
+
bigBuf.writeUnsafeInt32LE(colNum);
|
|
3288
|
+
bigBuf.writeUnsafeByte(styleNum);
|
|
3289
|
+
bigBuf.writeUnsafeByte(0);
|
|
3290
|
+
bigBuf.writeUnsafeByte(0);
|
|
3291
|
+
bigBuf.writeUnsafeByte(0);
|
|
3292
|
+
bigBuf.writeUnsafeDoubleLE(val);
|
|
3293
|
+
}
|
|
3294
|
+
writeBool(bigBuf, val, colNum) {
|
|
3295
|
+
bigBuf.ensureCapacity(13);
|
|
3296
|
+
bigBuf.writeUnsafeByte(4);
|
|
3297
|
+
bigBuf.writeUnsafeByte(9);
|
|
3298
|
+
bigBuf.writeUnsafeInt32LE(colNum);
|
|
3299
|
+
bigBuf.writeUnsafeInt32LE(0);
|
|
3300
|
+
bigBuf.writeUnsafeByte(val ? 1 : 0);
|
|
3301
|
+
}
|
|
3302
|
+
writeDateTime(bigBuf, date, colNum) {
|
|
3303
|
+
const oaDate = (date.getTime() - this._oaEpoch) / 864e5;
|
|
3304
|
+
this.writeDouble(bigBuf, oaDate, colNum, 1);
|
|
3305
|
+
}
|
|
3306
|
+
_getDateWidth(_date) {
|
|
3307
|
+
return 19;
|
|
3308
|
+
}
|
|
3309
|
+
writeString(bigBuf, val, colNum, bolded = false, styleOverride) {
|
|
3310
|
+
let index;
|
|
3311
|
+
if (this.sstDic.has(val)) {
|
|
3312
|
+
index = this.sstDic.get(val);
|
|
3313
|
+
} else {
|
|
3314
|
+
index = this.sstCntUnique;
|
|
3315
|
+
this.sstDic.set(val, index);
|
|
3316
|
+
this.sstCntUnique++;
|
|
3317
|
+
}
|
|
3318
|
+
this.sstCntAll++;
|
|
3319
|
+
const styleNum = styleOverride !== void 0 ? styleOverride : bolded ? 3 : 0;
|
|
3320
|
+
bigBuf.ensureCapacity(17);
|
|
3321
|
+
bigBuf.writeUnsafeByte(7);
|
|
3322
|
+
bigBuf.writeUnsafeByte(12);
|
|
3323
|
+
bigBuf.writeUnsafeInt32LE(colNum);
|
|
3324
|
+
bigBuf.writeUnsafeByte(styleNum);
|
|
3325
|
+
bigBuf.writeUnsafeByte(0);
|
|
3326
|
+
bigBuf.writeUnsafeByte(0);
|
|
3327
|
+
bigBuf.writeUnsafeByte(0);
|
|
3328
|
+
bigBuf.writeUnsafeInt32LE(index);
|
|
3329
|
+
}
|
|
3330
|
+
saveSst() {
|
|
3331
|
+
const bigBuf = new BigBuffer();
|
|
3332
|
+
bigBuf.writeByte(159);
|
|
3333
|
+
bigBuf.writeByte(1);
|
|
3334
|
+
bigBuf.writeByte(8);
|
|
3335
|
+
bigBuf.writeInt32LE(this.sstCntUnique);
|
|
3336
|
+
bigBuf.writeInt32LE(this.sstCntAll);
|
|
3337
|
+
for (const [txt] of this.sstDic) {
|
|
3338
|
+
const txtLen = txt.length;
|
|
3339
|
+
bigBuf.writeByte(19);
|
|
3340
|
+
const recLen = 5 + 2 * txtLen;
|
|
3341
|
+
if (recLen >= 128) {
|
|
3342
|
+
bigBuf.writeByte(128 + recLen % 128);
|
|
3343
|
+
const tmp = recLen >> 7;
|
|
3344
|
+
if (tmp >= 256) {
|
|
3345
|
+
bigBuf.writeByte(128 + tmp % 128);
|
|
3346
|
+
} else {
|
|
3347
|
+
bigBuf.writeByte(tmp);
|
|
3348
|
+
}
|
|
3349
|
+
bigBuf.writeByte(recLen >> 14);
|
|
3350
|
+
if (recLen >> 14 > 0) {
|
|
3351
|
+
bigBuf.writeByte(0);
|
|
3352
|
+
}
|
|
3353
|
+
} else {
|
|
3354
|
+
bigBuf.writeByte(recLen & 255);
|
|
3355
|
+
bigBuf.writeByte(recLen >> 8 & 255);
|
|
3356
|
+
}
|
|
3357
|
+
bigBuf.writeInt32LE(txtLen);
|
|
3358
|
+
bigBuf.writeUtf16LE(txt);
|
|
3359
|
+
}
|
|
3360
|
+
bigBuf.writeByte(160);
|
|
3361
|
+
bigBuf.writeByte(1);
|
|
3362
|
+
bigBuf.writeByte(0);
|
|
3363
|
+
this.archive.append(import_stream.Readable.from(bigBuf.getChunks()), { name: "xl/sharedStrings.bin" });
|
|
3364
|
+
}
|
|
3365
|
+
_writeFilterDefinedName(wbBuffers, sheet, sheetNum) {
|
|
3366
|
+
const filterData = sheet.filterData;
|
|
3367
|
+
const sheetIndex = sheet.sheetId - 1;
|
|
3368
|
+
const fix1 = Buffer.alloc(this._magicFilterExcel2016Fix1.length);
|
|
3369
|
+
this._magicFilterExcel2016Fix1.copy(fix1);
|
|
3370
|
+
const lastIdx = this._magicFilterExcel2016Fix1.length - 2;
|
|
3371
|
+
fix1[7] = sheetIndex;
|
|
3372
|
+
fix1[lastIdx] = sheetNum;
|
|
3373
|
+
wbBuffers.push(fix1);
|
|
3374
|
+
const rowBuf = Buffer.alloc(8);
|
|
3375
|
+
rowBuf.writeInt32LE(filterData.startRow, 0);
|
|
3376
|
+
rowBuf.writeInt32LE(filterData.endRow, 4);
|
|
3377
|
+
wbBuffers.push(rowBuf);
|
|
3378
|
+
const colBuf = Buffer.alloc(4);
|
|
3379
|
+
colBuf.writeInt16LE(filterData.startColumn, 0);
|
|
3380
|
+
colBuf.writeInt16LE(filterData.endColumn, 2);
|
|
3381
|
+
wbBuffers.push(colBuf);
|
|
3382
|
+
wbBuffers.push(this._magicFilterExcel2016Fix2);
|
|
3383
|
+
}
|
|
3384
|
+
/**
|
|
3385
|
+
* Finalize the ZIP package and close the output stream.
|
|
3386
|
+
* Must be awaited before the file is fully written.
|
|
3387
|
+
*/
|
|
3388
|
+
finalize() {
|
|
3389
|
+
return new Promise((resolve, reject) => {
|
|
3390
|
+
try {
|
|
3391
|
+
this.saveSst();
|
|
3392
|
+
this.archive.append(this._buildStylesBin(), { name: "xl/styles.bin" });
|
|
3393
|
+
const wbBuffers = [];
|
|
3394
|
+
wbBuffers.push(this._workbookBinStart);
|
|
3395
|
+
for (const sheet of this.sheetList) {
|
|
3396
|
+
const rId = `rId${sheet.sheetId}`;
|
|
3397
|
+
const recLen = 4 + 12 + sheet.name.length * 2 + rId.length * 2;
|
|
3398
|
+
const buf = Buffer.alloc(3 + recLen);
|
|
3399
|
+
buf[0] = 156;
|
|
3400
|
+
buf[1] = 1;
|
|
3401
|
+
buf[2] = recLen;
|
|
3402
|
+
let pos = 3;
|
|
3403
|
+
buf.writeInt32LE(sheet.hidden ? 1 : 0, pos);
|
|
3404
|
+
pos += 4;
|
|
3405
|
+
buf.writeInt32LE(sheet.sheetId, pos);
|
|
3406
|
+
pos += 4;
|
|
3407
|
+
buf.writeInt32LE(rId.length, pos);
|
|
3408
|
+
pos += 4;
|
|
3409
|
+
for (let i = 0; i < rId.length; i++) {
|
|
3410
|
+
const c = rId.charCodeAt(i);
|
|
3411
|
+
buf[pos++] = c & 255;
|
|
3412
|
+
buf[pos++] = c >> 8 & 255;
|
|
3413
|
+
}
|
|
3414
|
+
buf.writeInt32LE(sheet.name.length, pos);
|
|
3415
|
+
pos += 4;
|
|
3416
|
+
for (let i = 0; i < sheet.name.length; i++) {
|
|
3417
|
+
const c = sheet.name.charCodeAt(i);
|
|
3418
|
+
buf[pos++] = c & 255;
|
|
3419
|
+
buf[pos++] = c >> 8 & 255;
|
|
3420
|
+
}
|
|
3421
|
+
wbBuffers.push(buf);
|
|
3422
|
+
}
|
|
3423
|
+
wbBuffers.push(this._workbookBinMiddle);
|
|
3424
|
+
if (this._autofilterIsOn) {
|
|
3425
|
+
const filteredSheets = this.sheetList.filter((s) => s.filterData);
|
|
3426
|
+
const cnt = filteredSheets.length;
|
|
3427
|
+
if (cnt > 0) {
|
|
3428
|
+
wbBuffers.push(this._magicFilterExcel2016Fix0);
|
|
3429
|
+
const firstByte = cnt <= 20 ? 16 + (cnt - 1) * 12 : 128 + (cnt - 21) * 12;
|
|
3430
|
+
const countBuf = cnt <= 10 ? Buffer.from([firstByte, cnt, 0, 0, 0]) : Buffer.from([firstByte, Math.floor((cnt - 1) / 10), cnt, 0, 0, 0]);
|
|
3431
|
+
wbBuffers.push(countBuf);
|
|
3432
|
+
for (let nm = 0; nm < cnt; nm++) {
|
|
3433
|
+
const sheetIndex = filteredSheets[nm].sheetId - 1;
|
|
3434
|
+
const idxBuf = Buffer.alloc(12);
|
|
3435
|
+
idxBuf.writeInt32LE(0, 0);
|
|
3436
|
+
idxBuf[4] = sheetIndex;
|
|
3437
|
+
idxBuf[8] = sheetIndex;
|
|
3438
|
+
wbBuffers.push(idxBuf);
|
|
3439
|
+
}
|
|
3440
|
+
wbBuffers.push(Buffer.from([226, 2, 0]));
|
|
3441
|
+
for (let sheetNum = 0; sheetNum < cnt; sheetNum++) {
|
|
3442
|
+
const sheet = filteredSheets[sheetNum];
|
|
3443
|
+
this._writeFilterDefinedName(wbBuffers, sheet, sheetNum);
|
|
3444
|
+
}
|
|
3445
|
+
}
|
|
3446
|
+
}
|
|
3447
|
+
wbBuffers.push(this._workbookBinEnd);
|
|
3448
|
+
this.archive.append(Buffer.concat(wbBuffers), { name: "xl/workbook.bin" });
|
|
3449
|
+
for (const sheet of this.sheetList) {
|
|
3450
|
+
this.archive.append(this._binaryIndexBin, { name: `xl/worksheets/binaryIndex${sheet.sheetId}.bin` });
|
|
3451
|
+
}
|
|
3452
|
+
let contentTypes = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
3453
|
+
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
|
|
3454
|
+
<Default Extension="bin" ContentType="application/vnd.ms-excel.sheet.binary.macroEnabled.main"/>
|
|
3455
|
+
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
|
|
3456
|
+
<Default Extension="xml" ContentType="application/xml"/>`;
|
|
3457
|
+
for (const sheet of this.sheetList) {
|
|
3458
|
+
contentTypes += `<Override PartName="/${sheet.pathInArchive}" ContentType="application/vnd.ms-excel.worksheet"/>`;
|
|
3459
|
+
contentTypes += `<Override PartName="/xl/worksheets/binaryIndex${sheet.sheetId}.bin" ContentType="application/vnd.ms-excel.binIndexWs"/>`;
|
|
3460
|
+
}
|
|
3461
|
+
contentTypes += `<Override PartName="/xl/styles.bin" ContentType="application/vnd.ms-excel.styles"/>
|
|
3462
|
+
<Override PartName="/xl/sharedStrings.bin" ContentType="application/vnd.ms-excel.sharedStrings"/>
|
|
3463
|
+
</Types>`;
|
|
3464
|
+
this.archive.append(contentTypes, { name: "[Content_Types].xml" });
|
|
3465
|
+
let wbRels = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
3466
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">`;
|
|
3467
|
+
for (const sheet of this.sheetList) {
|
|
3468
|
+
const rId = `rId${sheet.sheetId}`;
|
|
3469
|
+
wbRels += `<Relationship Id="${rId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/${sheet.nameInArchive}"/>`;
|
|
3470
|
+
}
|
|
3471
|
+
wbRels += `<Relationship Id="rId${this.sheetList.length + 2}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.bin"/>
|
|
3472
|
+
<Relationship Id="rId${this.sheetList.length + 3}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.bin"/>
|
|
3473
|
+
</Relationships>`;
|
|
3474
|
+
this.archive.append(wbRels, { name: "xl/_rels/workbook.bin.rels" });
|
|
3475
|
+
const globalRels = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
3476
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
3477
|
+
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.bin"/>
|
|
3478
|
+
</Relationships>`;
|
|
3479
|
+
this.archive.append(globalRels, { name: "_rels/.rels" });
|
|
3480
|
+
for (const sheet of this.sheetList) {
|
|
3481
|
+
const wsRels = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
3482
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
3483
|
+
<Relationship Id="rId1" Type="http://schemas.microsoft.com/office/2006/relationships/xlBinaryIndex" Target="binaryIndex${sheet.sheetId}.bin"/>
|
|
3484
|
+
</Relationships>`;
|
|
3485
|
+
this.archive.append(wsRels, { name: `xl/worksheets/_rels/${sheet.nameInArchive}.rels` });
|
|
3486
|
+
}
|
|
3487
|
+
this.output.on("close", () => resolve());
|
|
3488
|
+
this.archive.on("error", (err) => reject(err));
|
|
3489
|
+
this.archive.finalize();
|
|
3490
|
+
} catch (err) {
|
|
3491
|
+
reject(err);
|
|
3492
|
+
}
|
|
3493
|
+
});
|
|
3494
|
+
}
|
|
3495
|
+
};
|
|
3496
|
+
|
|
3497
|
+
// src/XlsxWriter.ts
|
|
3498
|
+
var fs2 = __toESM(require("fs"));
|
|
3499
|
+
var import_archiver2 = __toESM(require("archiver"));
|
|
3500
|
+
var import_stream2 = require("stream");
|
|
3501
|
+
var COLUMN_LETTERS = (() => {
|
|
3502
|
+
const letters = [];
|
|
3503
|
+
for (let i = 65; i < 91; i++) {
|
|
3504
|
+
letters.push(String.fromCharCode(i));
|
|
3505
|
+
}
|
|
3506
|
+
const temp = [];
|
|
3507
|
+
for (const p of letters) {
|
|
3508
|
+
for (let i = 65; i < 91; i++) {
|
|
3509
|
+
temp.push(p + String.fromCharCode(i));
|
|
3510
|
+
}
|
|
3511
|
+
}
|
|
3512
|
+
letters.push(...temp);
|
|
3513
|
+
return letters;
|
|
3514
|
+
})();
|
|
3515
|
+
var XlsxWriter = class {
|
|
3516
|
+
/**
|
|
3517
|
+
* @param filePath Destination `.xlsx` path on disk.
|
|
3518
|
+
*/
|
|
3519
|
+
constructor(filePath) {
|
|
3520
|
+
this.sheetCount = 0;
|
|
3521
|
+
this.sheetList = [];
|
|
3522
|
+
this.sstArray = [];
|
|
3523
|
+
this.sstMap = /* @__PURE__ */ new Map();
|
|
3524
|
+
this.sstCntAll = 0;
|
|
3525
|
+
this._autofilterIsOn = false;
|
|
3526
|
+
// Format registry
|
|
3527
|
+
this._formatRegistry = /* @__PURE__ */ new Map();
|
|
3528
|
+
this._formatXfMap = /* @__PURE__ */ new Map();
|
|
3529
|
+
this._nextNumfmtId = 165;
|
|
3530
|
+
this._nextXfIndex = 4;
|
|
3531
|
+
this.stream = new StreamingSheetState();
|
|
3532
|
+
this.currentColLetters = [];
|
|
3533
|
+
this.output = fs2.createWriteStream(filePath);
|
|
3534
|
+
this.archive = (0, import_archiver2.default)("zip");
|
|
3535
|
+
this.archive.pipe(this.output);
|
|
3536
|
+
this._oaEpoch = Date.UTC(1899, 11, 30);
|
|
3537
|
+
}
|
|
3538
|
+
_getColumnLetter(colIndex) {
|
|
3539
|
+
return colIndex < COLUMN_LETTERS.length ? COLUMN_LETTERS[colIndex] : "A";
|
|
3540
|
+
}
|
|
3541
|
+
/** @deprecated Internal; kept for unit-test access. Prefer sanitizeSheetName(). */
|
|
3542
|
+
_sanitizeSheetName(name) {
|
|
3543
|
+
return sanitizeSheetName(name, this.sheetCount);
|
|
3544
|
+
}
|
|
3545
|
+
_escapeSheetNameForXml(name) {
|
|
3546
|
+
return name.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
3547
|
+
}
|
|
3548
|
+
_formatSheetNameForFormula(name) {
|
|
3549
|
+
if (/[\s\-+=()!@#$%^&]/.test(name) || /^[0-9]/.test(name)) {
|
|
3550
|
+
const escaped = name.replace(/'/g, "''");
|
|
3551
|
+
return `'${escaped}'`;
|
|
3552
|
+
}
|
|
3553
|
+
return name;
|
|
3554
|
+
}
|
|
3555
|
+
/**
|
|
3556
|
+
* Register a worksheet (metadata only). Prefer `writeSheet` / `startSheet` for data.
|
|
3557
|
+
*/
|
|
3558
|
+
addSheet(sheetName, hidden = false) {
|
|
3559
|
+
const sanitizedName = sanitizeSheetName(sheetName, this.sheetCount);
|
|
3560
|
+
this.sheetCount++;
|
|
3561
|
+
const rId = `rId${this.sheetCount}`;
|
|
3562
|
+
const sheetFileName = `sheet${this.sheetCount}.xml`;
|
|
3563
|
+
this.sheetList.push({
|
|
3564
|
+
name: sanitizedName,
|
|
3565
|
+
pathInArchive: `xl/worksheets/${sheetFileName}`,
|
|
3566
|
+
hidden,
|
|
3567
|
+
nameInArchive: sheetFileName,
|
|
3568
|
+
sheetId: this.sheetCount,
|
|
3569
|
+
rId,
|
|
3570
|
+
filterHeaderRange: null
|
|
3571
|
+
});
|
|
3572
|
+
}
|
|
3573
|
+
_needsEscape(str) {
|
|
3574
|
+
for (let i = 0; i < str.length; i++) {
|
|
3575
|
+
const c = str.charCodeAt(i);
|
|
3576
|
+
if (c === 38 || c === 60 || c === 62 || c === 34 || c === 39 || c >= 0 && c <= 8 || c === 11 || c === 12 || c >= 14 && c <= 31) {
|
|
3577
|
+
return true;
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
return false;
|
|
3581
|
+
}
|
|
3582
|
+
_escape(str) {
|
|
3583
|
+
if (typeof str !== "string") return str;
|
|
3584
|
+
if (!this._needsEscape(str)) return str;
|
|
3585
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f]/g, "");
|
|
3586
|
+
}
|
|
3587
|
+
/**
|
|
3588
|
+
* Start streaming a sheet. Call `writeRow` for each row, then `endSheet`.
|
|
3589
|
+
*/
|
|
3590
|
+
startSheet(sheetName, columnCount, headers, options = {}) {
|
|
3591
|
+
const { hidden = false, doAutofilter = true, sampleRows } = options;
|
|
3592
|
+
this.addSheet(sheetName, hidden);
|
|
3593
|
+
this.stream.begin(columnCount, doAutofilter && headers !== void 0, new BigBuffer());
|
|
3594
|
+
const bigBuf = this.stream.buffer;
|
|
3595
|
+
const colLetters = new Array(columnCount);
|
|
3596
|
+
for (let i = 0; i < columnCount; i++) {
|
|
3597
|
+
colLetters[i] = this._getColumnLetter(i);
|
|
3598
|
+
}
|
|
3599
|
+
this.currentColLetters = colLetters;
|
|
3600
|
+
if (headers) {
|
|
3601
|
+
applyHeaderWidths(this.stream.colWidths, headers, columnCount);
|
|
3602
|
+
}
|
|
3603
|
+
if (sampleRows) {
|
|
3604
|
+
updateColWidthsFromRows(this.stream.colWidths, sampleRows);
|
|
3605
|
+
}
|
|
3606
|
+
bigBuf.writeString('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>');
|
|
3607
|
+
bigBuf.writeString('<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">');
|
|
3608
|
+
bigBuf.writeString('<dimension ref="A1"/>');
|
|
3609
|
+
const isFirstSheet = this.sheetCount === 1;
|
|
3610
|
+
if (headers) {
|
|
3611
|
+
if (isFirstSheet) {
|
|
3612
|
+
bigBuf.writeString('<sheetViews><sheetView tabSelected="1" workbookViewId="0"><pane ySplit="1" topLeftCell="A2" activePane="bottomLeft" state="frozen" /><selection pane="bottomLeft" /></sheetView></sheetViews><sheetFormatPr defaultRowHeight="15"/>');
|
|
3613
|
+
} else {
|
|
3614
|
+
bigBuf.writeString('<sheetViews><sheetView workbookViewId="0"><pane ySplit="1" topLeftCell="A2" activePane="bottomLeft" state="frozen" /><selection pane="bottomLeft" /></sheetView></sheetViews><sheetFormatPr defaultRowHeight="15"/>');
|
|
3615
|
+
}
|
|
3616
|
+
} else {
|
|
3617
|
+
if (isFirstSheet) {
|
|
3618
|
+
bigBuf.writeString('<sheetViews><sheetView tabSelected="1" workbookViewId="0"/></sheetViews><sheetFormatPr defaultRowHeight="15"/>');
|
|
3619
|
+
} else {
|
|
3620
|
+
bigBuf.writeString('<sheetViews><sheetView workbookViewId="0"/></sheetViews><sheetFormatPr defaultRowHeight="15"/>');
|
|
3621
|
+
}
|
|
3622
|
+
}
|
|
3623
|
+
bigBuf.writeString("<cols>");
|
|
3624
|
+
for (let i = 0; i < columnCount; i++) {
|
|
3625
|
+
const width = defaultColWidth(this.stream.colWidths[i]);
|
|
3626
|
+
bigBuf.writeString(`<col min="${i + 1}" max="${i + 1}" width="${width}" bestFit="1" customWidth="1" />`);
|
|
3627
|
+
}
|
|
3628
|
+
bigBuf.writeString("</cols><sheetData>");
|
|
3629
|
+
if (headers) {
|
|
3630
|
+
this.stream.rowNum++;
|
|
3631
|
+
bigBuf.writeString(`<row r="${this.stream.rowNum}">`);
|
|
3632
|
+
for (let c = 0; c < headers.length; c++) {
|
|
3633
|
+
this._writeStringCell(bigBuf, headers[c], colLetters[c], this.stream.rowNum, 3);
|
|
3634
|
+
}
|
|
3635
|
+
bigBuf.writeString("</row>");
|
|
3636
|
+
}
|
|
3637
|
+
}
|
|
3638
|
+
/** Write one data row in streaming mode. */
|
|
3639
|
+
writeRow(row) {
|
|
3640
|
+
const bigBuf = this.stream.assertStreaming();
|
|
3641
|
+
if (row.length !== this.stream.endCol - this.stream.startCol) {
|
|
3642
|
+
throw new Error(
|
|
3643
|
+
`Row length mismatch. Expected ${this.stream.endCol - this.stream.startCol} columns, got ${row.length}`
|
|
3644
|
+
);
|
|
3645
|
+
}
|
|
3646
|
+
this.stream.rowNum++;
|
|
3647
|
+
bigBuf.writeString(`<row r="${this.stream.rowNum}">`);
|
|
3648
|
+
for (let c = 0; c < row.length; c++) {
|
|
3649
|
+
const raw = row[c];
|
|
3650
|
+
if (raw === null || raw === void 0) continue;
|
|
3651
|
+
const fmtString = getFormat(raw);
|
|
3652
|
+
const val = fmtString !== null ? unwrapCell(raw) : raw;
|
|
3653
|
+
const xfIdx = fmtString !== null ? this._registerFormat(fmtString) : -1;
|
|
3654
|
+
const styleAttr = xfIdx >= 0 ? ` s="${xfIdx}"` : "";
|
|
3655
|
+
const colRef = this.currentColLetters[c];
|
|
3656
|
+
if (typeof val === "number") {
|
|
3657
|
+
if (Number.isFinite(val)) {
|
|
3658
|
+
bigBuf.writeString(`<c r="${colRef}${this.stream.rowNum}"${styleAttr}><v>${val}</v></c>`);
|
|
3659
|
+
} else {
|
|
3660
|
+
this._writeStringCell(bigBuf, val.toString(), colRef, this.stream.rowNum, xfIdx >= 0 ? xfIdx : void 0);
|
|
3661
|
+
}
|
|
3662
|
+
} else if (typeof val === "bigint") {
|
|
3663
|
+
this._writeStringCell(bigBuf, val.toString(), colRef, this.stream.rowNum, xfIdx >= 0 ? xfIdx : void 0);
|
|
3664
|
+
} else if (typeof val === "boolean") {
|
|
3665
|
+
bigBuf.writeString(`<c r="${colRef}${this.stream.rowNum}" t="b"${styleAttr}><v>${val ? 1 : 0}</v></c>`);
|
|
3666
|
+
} else if (val instanceof Date) {
|
|
3667
|
+
const oaDate = this._toOADate(val);
|
|
3668
|
+
if (Number.isFinite(oaDate)) {
|
|
3669
|
+
const finalStyle = xfIdx >= 0 ? xfIdx : 1;
|
|
3670
|
+
bigBuf.writeString(`<c r="${colRef}${this.stream.rowNum}" s="${finalStyle}"><v>${oaDate}</v></c>`);
|
|
3671
|
+
} else {
|
|
3672
|
+
this._writeStringCell(bigBuf, val.toString(), colRef, this.stream.rowNum, xfIdx >= 0 ? xfIdx : void 0);
|
|
3673
|
+
}
|
|
3674
|
+
} else if (val !== null && val !== void 0) {
|
|
3675
|
+
this._writeStringCell(bigBuf, val.toString(), colRef, this.stream.rowNum, xfIdx >= 0 ? xfIdx : void 0);
|
|
3676
|
+
}
|
|
3677
|
+
}
|
|
3678
|
+
bigBuf.writeString("</row>");
|
|
3679
|
+
}
|
|
3680
|
+
/** Finish the current streaming sheet and append it to the archive. */
|
|
3681
|
+
endSheet() {
|
|
3682
|
+
const bigBuf = this.stream.assertStreaming();
|
|
3683
|
+
bigBuf.writeString("</sheetData>");
|
|
3684
|
+
if (this.stream.doAutofilter && this.stream.endCol > 0) {
|
|
3685
|
+
this._autofilterIsOn = true;
|
|
3686
|
+
const filterRef = `A1:${this.currentColLetters[this.stream.endCol - 1]}${this.stream.rowNum}`;
|
|
3687
|
+
bigBuf.writeString(`<autoFilter ref="${filterRef}"/>`);
|
|
3688
|
+
const sheet = this.sheetList[this.sheetCount - 1];
|
|
3689
|
+
const formulaSheetName = this._formatSheetNameForFormula(sheet.name);
|
|
3690
|
+
sheet.filterHeaderRange = `${formulaSheetName}!$A$1:$${this.currentColLetters[this.stream.endCol - 1]}$${this.stream.rowNum}`;
|
|
3691
|
+
}
|
|
3692
|
+
bigBuf.writeString("</worksheet>");
|
|
3693
|
+
this.archive.append(import_stream2.Readable.from(bigBuf.getChunks()), {
|
|
3694
|
+
name: this.sheetList[this.sheetCount - 1].pathInArchive
|
|
3695
|
+
});
|
|
3696
|
+
this.stream.end();
|
|
3697
|
+
this.currentColLetters = [];
|
|
3698
|
+
}
|
|
3699
|
+
/**
|
|
3700
|
+
* Write an entire sheet in one call (batch mode).
|
|
3701
|
+
*/
|
|
3702
|
+
writeSheet(rows, headers = null, doAutofilter = true) {
|
|
3703
|
+
const bigBuf = new BigBuffer();
|
|
3704
|
+
let columnCount = 0;
|
|
3705
|
+
if (rows.length > 0) {
|
|
3706
|
+
columnCount = rows[0].length;
|
|
3707
|
+
} else if (headers) {
|
|
3708
|
+
columnCount = headers.length;
|
|
3709
|
+
}
|
|
3710
|
+
const colWidths = initColWidths(columnCount);
|
|
3711
|
+
const colLetters = new Array(columnCount);
|
|
3712
|
+
for (let i = 0; i < columnCount; i++) {
|
|
3713
|
+
colLetters[i] = this._getColumnLetter(i);
|
|
3714
|
+
}
|
|
3715
|
+
if (headers) {
|
|
3716
|
+
applyHeaderWidths(colWidths, headers, columnCount);
|
|
3717
|
+
}
|
|
3718
|
+
updateColWidthsFromRows(colWidths, rows);
|
|
3719
|
+
bigBuf.writeString('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>');
|
|
3720
|
+
bigBuf.writeString('<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">');
|
|
3721
|
+
const totalRows = rows.length + (headers ? 1 : 0);
|
|
3722
|
+
if (totalRows > 0 && columnCount > 0) {
|
|
3723
|
+
bigBuf.writeString(`<dimension ref="A1:${colLetters[columnCount - 1]}${totalRows}"/>`);
|
|
3724
|
+
} else {
|
|
3725
|
+
bigBuf.writeString('<dimension ref="A1"/>');
|
|
3726
|
+
}
|
|
3727
|
+
const isFirstSheet = this.sheetCount === 1;
|
|
3728
|
+
if (headers) {
|
|
3729
|
+
if (isFirstSheet) {
|
|
3730
|
+
bigBuf.writeString('<sheetViews><sheetView tabSelected="1" workbookViewId="0"><pane ySplit="1" topLeftCell="A2" activePane="bottomLeft" state="frozen" /><selection pane="bottomLeft" /></sheetView></sheetViews><sheetFormatPr defaultRowHeight="15"/>');
|
|
3731
|
+
} else {
|
|
3732
|
+
bigBuf.writeString('<sheetViews><sheetView workbookViewId="0"><pane ySplit="1" topLeftCell="A2" activePane="bottomLeft" state="frozen" /><selection pane="bottomLeft" /></sheetView></sheetViews><sheetFormatPr defaultRowHeight="15"/>');
|
|
3733
|
+
}
|
|
3734
|
+
} else {
|
|
3735
|
+
if (isFirstSheet) {
|
|
3736
|
+
bigBuf.writeString('<sheetViews><sheetView tabSelected="1" workbookViewId="0"/></sheetViews><sheetFormatPr defaultRowHeight="15"/>');
|
|
3737
|
+
} else {
|
|
3738
|
+
bigBuf.writeString('<sheetViews><sheetView workbookViewId="0"/></sheetViews><sheetFormatPr defaultRowHeight="15"/>');
|
|
3739
|
+
}
|
|
3740
|
+
}
|
|
3741
|
+
bigBuf.writeString("<cols>");
|
|
3742
|
+
for (let i = 0; i < columnCount; i++) {
|
|
3743
|
+
const width = defaultColWidth(colWidths[i]);
|
|
3744
|
+
bigBuf.writeString(`<col min="${i + 1}" max="${i + 1}" width="${width}" bestFit="1" customWidth="1" />`);
|
|
3745
|
+
}
|
|
3746
|
+
bigBuf.writeString("</cols><sheetData>");
|
|
3747
|
+
let rowNum = 0;
|
|
3748
|
+
if (headers) {
|
|
3749
|
+
rowNum++;
|
|
3750
|
+
bigBuf.writeString(`<row r="${rowNum}">`);
|
|
3751
|
+
for (let c = 0; c < headers.length; c++) {
|
|
3752
|
+
this._writeStringCell(bigBuf, headers[c], colLetters[c], rowNum, 3);
|
|
3753
|
+
}
|
|
3754
|
+
bigBuf.writeString("</row>");
|
|
3755
|
+
}
|
|
3756
|
+
for (let r = 0; r < rows.length; r++) {
|
|
3757
|
+
rowNum++;
|
|
3758
|
+
bigBuf.writeString(`<row r="${rowNum}">`);
|
|
3759
|
+
const row = rows[r];
|
|
3760
|
+
for (let c = 0; c < row.length; c++) {
|
|
3761
|
+
const raw = row[c];
|
|
3762
|
+
if (raw === null || raw === void 0) continue;
|
|
3763
|
+
const fmtString = getFormat(raw);
|
|
3764
|
+
const val = fmtString !== null ? unwrapCell(raw) : raw;
|
|
3765
|
+
const xfIdx = fmtString !== null ? this._registerFormat(fmtString) : -1;
|
|
3766
|
+
const styleAttr = xfIdx >= 0 ? ` s="${xfIdx}"` : "";
|
|
3767
|
+
const colRef = colLetters[c];
|
|
3768
|
+
if (typeof val === "number") {
|
|
3769
|
+
if (Number.isFinite(val)) {
|
|
3770
|
+
bigBuf.writeString(`<c r="${colRef}${rowNum}"${styleAttr}><v>${val}</v></c>`);
|
|
3771
|
+
} else {
|
|
3772
|
+
this._writeStringCell(bigBuf, val.toString(), colRef, rowNum, xfIdx >= 0 ? xfIdx : void 0);
|
|
3773
|
+
}
|
|
3774
|
+
} else if (typeof val === "bigint") {
|
|
3775
|
+
this._writeStringCell(bigBuf, val.toString(), colRef, rowNum, xfIdx >= 0 ? xfIdx : void 0);
|
|
3776
|
+
} else if (typeof val === "boolean") {
|
|
3777
|
+
bigBuf.writeString(`<c r="${colRef}${rowNum}" t="b"${styleAttr}><v>${val ? 1 : 0}</v></c>`);
|
|
3778
|
+
} else if (val instanceof Date) {
|
|
3779
|
+
const oaDate = this._toOADate(val);
|
|
3780
|
+
if (Number.isFinite(oaDate)) {
|
|
3781
|
+
const finalStyle = xfIdx >= 0 ? xfIdx : 1;
|
|
3782
|
+
bigBuf.writeString(`<c r="${colRef}${rowNum}" s="${finalStyle}"><v>${oaDate}</v></c>`);
|
|
3783
|
+
} else {
|
|
3784
|
+
this._writeStringCell(bigBuf, val.toString(), colRef, rowNum, xfIdx >= 0 ? xfIdx : void 0);
|
|
3785
|
+
}
|
|
3786
|
+
} else if (val !== null && val !== void 0) {
|
|
3787
|
+
this._writeStringCell(bigBuf, val.toString(), colRef, rowNum, xfIdx >= 0 ? xfIdx : void 0);
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
bigBuf.writeString("</row>");
|
|
3791
|
+
}
|
|
3792
|
+
bigBuf.writeString("</sheetData>");
|
|
3793
|
+
if (doAutofilter && headers && columnCount > 0) {
|
|
3794
|
+
this._autofilterIsOn = true;
|
|
3795
|
+
const filterRef = `A1:${colLetters[columnCount - 1]}${totalRows}`;
|
|
3796
|
+
bigBuf.writeString(`<autoFilter ref="${filterRef}"/>`);
|
|
3797
|
+
const sheet = this.sheetList[this.sheetCount - 1];
|
|
3798
|
+
const formulaSheetName = this._formatSheetNameForFormula(sheet.name);
|
|
3799
|
+
sheet.filterHeaderRange = `${formulaSheetName}!$A$1:$${colLetters[columnCount - 1]}$${totalRows}`;
|
|
3800
|
+
}
|
|
3801
|
+
bigBuf.writeString("</worksheet>");
|
|
3802
|
+
this.archive.append(import_stream2.Readable.from(bigBuf.getChunks()), {
|
|
3803
|
+
name: this.sheetList[this.sheetCount - 1].pathInArchive
|
|
3804
|
+
});
|
|
3805
|
+
}
|
|
3806
|
+
_writeStringCell(bigBuf, val, colRef, rowNum, styleOverride) {
|
|
3807
|
+
let index = this.sstMap.get(val);
|
|
3808
|
+
if (index === void 0) {
|
|
3809
|
+
index = this.sstArray.length;
|
|
3810
|
+
this.sstArray.push(val);
|
|
3811
|
+
this.sstMap.set(val, index);
|
|
3812
|
+
}
|
|
3813
|
+
this.sstCntAll++;
|
|
3814
|
+
const styleAttr = styleOverride !== void 0 ? ` s="${styleOverride}"` : "";
|
|
3815
|
+
bigBuf.writeString(`<c r="${colRef}${rowNum}" t="s"${styleAttr}><v>${index}</v></c>`);
|
|
3816
|
+
}
|
|
3817
|
+
_registerFormat(fmtString) {
|
|
3818
|
+
if (this._formatXfMap.has(fmtString)) {
|
|
3819
|
+
return this._formatXfMap.get(fmtString);
|
|
3820
|
+
}
|
|
3821
|
+
const numfmtId = this._nextNumfmtId++;
|
|
3822
|
+
this._formatRegistry.set(fmtString, numfmtId);
|
|
3823
|
+
const xfIndex = this._nextXfIndex++;
|
|
3824
|
+
this._formatXfMap.set(fmtString, xfIndex);
|
|
3825
|
+
return xfIndex;
|
|
3826
|
+
}
|
|
3827
|
+
_toOADate(date) {
|
|
3828
|
+
return (date.getTime() - this._oaEpoch) / 864e5;
|
|
3829
|
+
}
|
|
3830
|
+
_getDateWidth(_date) {
|
|
3831
|
+
return 19;
|
|
3832
|
+
}
|
|
3833
|
+
/** Finalize the ZIP package and close the output stream. */
|
|
3834
|
+
finalize() {
|
|
3835
|
+
return new Promise((resolve, reject) => {
|
|
3836
|
+
try {
|
|
3837
|
+
this._writeSharedStrings();
|
|
3838
|
+
this._writeStyles();
|
|
3839
|
+
this._writeWorkbook();
|
|
3840
|
+
this._writeContentTypes();
|
|
3841
|
+
this._writeRels();
|
|
3842
|
+
this.output.on("close", () => {
|
|
3843
|
+
resolve();
|
|
3844
|
+
});
|
|
3845
|
+
this.archive.on("error", (err) => {
|
|
3846
|
+
reject(err);
|
|
3847
|
+
});
|
|
3848
|
+
this.archive.finalize();
|
|
3849
|
+
} catch (err) {
|
|
3850
|
+
reject(err);
|
|
3851
|
+
}
|
|
3852
|
+
});
|
|
3853
|
+
}
|
|
3854
|
+
_writeSharedStrings() {
|
|
3855
|
+
const bigBuf = new BigBuffer();
|
|
3856
|
+
bigBuf.writeString('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>');
|
|
3857
|
+
bigBuf.writeString(`<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="${this.sstCntAll}" uniqueCount="${this.sstArray.length}">`);
|
|
3858
|
+
for (let i = 0; i < this.sstArray.length; i++) {
|
|
3859
|
+
const txt = this.sstArray[i];
|
|
3860
|
+
const cleanTxt = this._escape(txt);
|
|
3861
|
+
if (cleanTxt.length > 0 && (cleanTxt[0] === " " || cleanTxt[cleanTxt.length - 1] === " " || /[\t\n\r]/.test(cleanTxt))) {
|
|
3862
|
+
bigBuf.writeString(`<si><t xml:space="preserve">${cleanTxt}</t></si>`);
|
|
3863
|
+
} else {
|
|
3864
|
+
bigBuf.writeString(`<si><t>${cleanTxt}</t></si>`);
|
|
3865
|
+
}
|
|
3866
|
+
}
|
|
3867
|
+
bigBuf.writeString("</sst>");
|
|
3868
|
+
this.archive.append(import_stream2.Readable.from(bigBuf.getChunks()), { name: "xl/sharedStrings.xml" });
|
|
3869
|
+
}
|
|
3870
|
+
_writeStyles() {
|
|
3871
|
+
let numFmts = "";
|
|
3872
|
+
let numFmtCount = 0;
|
|
3873
|
+
const xfEntries = [];
|
|
3874
|
+
xfEntries.push('<xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0"/>');
|
|
3875
|
+
xfEntries.push('<xf numFmtId="14" fontId="0" fillId="0" borderId="0" xfId="0" applyNumberFormat="1"/>');
|
|
3876
|
+
xfEntries.push('<xf numFmtId="22" fontId="0" fillId="0" borderId="0" xfId="0" applyNumberFormat="1"/>');
|
|
3877
|
+
xfEntries.push('<xf numFmtId="0" fontId="1" fillId="0" borderId="0" xfId="0" applyFont="1"/>');
|
|
3878
|
+
for (const [fmtString, numfmtId] of this._formatRegistry) {
|
|
3879
|
+
const escapedFmt = fmtString.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
3880
|
+
numFmts += `<numFmt numFmtId="${numfmtId}" formatCode="${escapedFmt}"/>`;
|
|
3881
|
+
numFmtCount++;
|
|
3882
|
+
}
|
|
3883
|
+
const sortedFormats = [...this._formatXfMap.entries()].sort((a, b) => a[1] - b[1]);
|
|
3884
|
+
for (const [fmtString] of sortedFormats) {
|
|
3885
|
+
const numfmtId = this._formatRegistry.get(fmtString);
|
|
3886
|
+
xfEntries.push(`<xf numFmtId="${numfmtId}" fontId="0" fillId="0" borderId="0" xfId="0" applyNumberFormat="1"/>`);
|
|
3887
|
+
}
|
|
3888
|
+
const totalXf = xfEntries.length;
|
|
3889
|
+
const numFmtsSection = numFmtCount > 0 ? `<numFmts count="${numFmtCount}">${numFmts}</numFmts>` : "";
|
|
3890
|
+
const styles = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
3891
|
+
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
|
3892
|
+
${numFmtsSection}
|
|
3893
|
+
<fonts count="2">
|
|
3894
|
+
<font><sz val="11"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font>
|
|
3895
|
+
<font><b/><sz val="11"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font>
|
|
3896
|
+
</fonts>
|
|
3897
|
+
<fills count="2">
|
|
3898
|
+
<fill><patternFill patternType="none"/></fill>
|
|
3899
|
+
<fill><patternFill patternType="gray125"/></fill>
|
|
3900
|
+
</fills>
|
|
3901
|
+
<borders count="1">
|
|
3902
|
+
<border><left/><right/><top/><bottom/><diagonal/></border>
|
|
3903
|
+
</borders>
|
|
3904
|
+
<cellStyleXfs count="1">
|
|
3905
|
+
<xf numFmtId="0" fontId="0" fillId="0" borderId="0"/>
|
|
3906
|
+
</cellStyleXfs>
|
|
3907
|
+
<cellXfs count="${totalXf}">
|
|
3908
|
+
${xfEntries.join("\n")}
|
|
3909
|
+
</cellXfs>
|
|
3910
|
+
<cellStyles count="1">
|
|
3911
|
+
<cellStyle name="Normal" xfId="0" builtinId="0"/>
|
|
3912
|
+
</cellStyles>
|
|
3913
|
+
<dxfs count="0"/>
|
|
3914
|
+
<tableStyles count="0" defaultTableStyle="TableStyleMedium2" defaultPivotStyle="PivotStyleLight16"/>
|
|
3915
|
+
</styleSheet>`;
|
|
3916
|
+
this.archive.append(styles, { name: "xl/styles.xml" });
|
|
3917
|
+
}
|
|
3918
|
+
_writeWorkbook() {
|
|
3919
|
+
let xml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
3920
|
+
<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
|
|
3921
|
+
<fileVersion appName="xl" lastEdited="4" lowestEdited="4" rupBuild="4505"/>
|
|
3922
|
+
<workbookPr defaultThemeVersion="124226"/>
|
|
3923
|
+
<bookViews><workbookView xWindow="240" yWindow="15" windowWidth="16095" windowHeight="9660"/></bookViews>
|
|
3924
|
+
<sheets>`;
|
|
3925
|
+
for (const sheet of this.sheetList) {
|
|
3926
|
+
const state = sheet.hidden ? ' state="hidden"' : "";
|
|
3927
|
+
const escapedName = this._escapeSheetNameForXml(sheet.name);
|
|
3928
|
+
xml += `<sheet name="${escapedName}" sheetId="${sheet.sheetId}"${state} r:id="${sheet.rId}"/>`;
|
|
3929
|
+
}
|
|
3930
|
+
xml += `</sheets>`;
|
|
3931
|
+
if (this._autofilterIsOn) {
|
|
3932
|
+
xml += "<definedNames>";
|
|
3933
|
+
for (const sheet of this.sheetList) {
|
|
3934
|
+
if (sheet.filterHeaderRange) {
|
|
3935
|
+
const localSheetId = sheet.sheetId - 1;
|
|
3936
|
+
const escapedRange = this._escape(sheet.filterHeaderRange);
|
|
3937
|
+
xml += `<definedName name="_xlnm._FilterDatabase" localSheetId="${localSheetId}" hidden="1">${escapedRange}</definedName>`;
|
|
3938
|
+
}
|
|
3939
|
+
}
|
|
3940
|
+
xml += "</definedNames>";
|
|
3941
|
+
}
|
|
3942
|
+
xml += '<calcPr calcId="124519" fullCalcOnLoad="1"/>';
|
|
3943
|
+
xml += `</workbook>`;
|
|
3944
|
+
this.archive.append(xml, { name: "xl/workbook.xml" });
|
|
3945
|
+
}
|
|
3946
|
+
_writeContentTypes() {
|
|
3947
|
+
let xml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
3948
|
+
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
|
|
3949
|
+
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
|
|
3950
|
+
<Default Extension="xml" ContentType="application/xml"/>
|
|
3951
|
+
<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
|
|
3952
|
+
<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
|
|
3953
|
+
<Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>`;
|
|
3954
|
+
for (const sheet of this.sheetList) {
|
|
3955
|
+
xml += `<Override PartName="/${sheet.pathInArchive}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>`;
|
|
3956
|
+
}
|
|
3957
|
+
xml += `</Types>`;
|
|
3958
|
+
this.archive.append(xml, { name: "[Content_Types].xml" });
|
|
3959
|
+
}
|
|
3960
|
+
_writeRels() {
|
|
3961
|
+
const globalRels = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
3962
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
3963
|
+
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
|
|
3964
|
+
</Relationships>`;
|
|
3965
|
+
this.archive.append(globalRels, { name: "_rels/.rels" });
|
|
3966
|
+
let wbRels = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
3967
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">`;
|
|
3968
|
+
for (const sheet of this.sheetList) {
|
|
3969
|
+
wbRels += `<Relationship Id="${sheet.rId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/${sheet.nameInArchive}"/>`;
|
|
3970
|
+
}
|
|
3971
|
+
let nextId = this.sheetList.length + 1;
|
|
3972
|
+
wbRels += `<Relationship Id="rId${nextId++}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>`;
|
|
3973
|
+
wbRels += `<Relationship Id="rId${nextId++}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>`;
|
|
3974
|
+
wbRels += `</Relationships>`;
|
|
3975
|
+
this.archive.append(wbRels, { name: "xl/_rels/workbook.xml.rels" });
|
|
3976
|
+
}
|
|
3977
|
+
};
|
|
3978
|
+
|
|
3979
|
+
// src/XlsxUpdater.ts
|
|
3980
|
+
var fs3 = __toESM(require("fs"));
|
|
3981
|
+
var import_adm_zip2 = __toESM(require("adm-zip"));
|
|
3982
|
+
var XlsxUpdater = class {
|
|
3983
|
+
/**
|
|
3984
|
+
* @param path Path to an existing `.xlsx` file.
|
|
3985
|
+
*/
|
|
3986
|
+
constructor(path2) {
|
|
3987
|
+
this.sheetNameToPath = /* @__PURE__ */ new Map();
|
|
3988
|
+
this.pivotCacheDefs = [];
|
|
3989
|
+
this.pivotTableDefPaths = [];
|
|
3990
|
+
this.sharedStringsXml = null;
|
|
3991
|
+
this.sharedStringsValues = [];
|
|
3992
|
+
this.sharedStringsOriginalLength = 0;
|
|
3993
|
+
this.sharedStringsCount = 0;
|
|
3994
|
+
this.stringIndexMap = /* @__PURE__ */ new Map();
|
|
3995
|
+
this.sourcePath = path2;
|
|
3996
|
+
this._oaEpoch = Date.UTC(1899, 11, 30);
|
|
3997
|
+
if (!fs3.existsSync(path2)) {
|
|
3998
|
+
throw new Error(`XlsxUpdater: file not found: ${path2}`);
|
|
3999
|
+
}
|
|
4000
|
+
this.zip = new import_adm_zip2.default(path2);
|
|
4001
|
+
if (this.zip.getEntry("xl/workbook.bin")) {
|
|
4002
|
+
throw new Error(
|
|
4003
|
+
"XlsxUpdater: XLSB files are not supported yet. Convert the workbook to XLSX first."
|
|
4004
|
+
);
|
|
4005
|
+
}
|
|
4006
|
+
if (!this.zip.getEntry("xl/workbook.xml")) {
|
|
4007
|
+
throw new Error("XlsxUpdater: not a valid XLSX workbook (xl/workbook.xml missing).");
|
|
4008
|
+
}
|
|
4009
|
+
this._loadWorkbookStructure();
|
|
4010
|
+
}
|
|
4011
|
+
/** Worksheet names in workbook order. */
|
|
4012
|
+
getSheetNames() {
|
|
4013
|
+
return [...this.sheetNameToPath.keys()];
|
|
4014
|
+
}
|
|
4015
|
+
/**
|
|
4016
|
+
* Clear the entire cell data of the target sheet and write new rows in its place.
|
|
4017
|
+
* All other parts of the workbook (pivot tables, other sheets, styles, …) are preserved.
|
|
4018
|
+
*
|
|
4019
|
+
* @param sheetName Name of the worksheet to replace.
|
|
4020
|
+
* @param rows New data rows (`CellValue` cells; null/undefined = blank).
|
|
4021
|
+
* @param options See {@link ReplaceSheetDataOptions}.
|
|
4022
|
+
*/
|
|
4023
|
+
replaceSheetData(sheetName, rows, options = {}) {
|
|
4024
|
+
const { headers, styleFallback = "inherit" } = options;
|
|
4025
|
+
rows = trimTrailingEmptyRows(rows);
|
|
4026
|
+
const sheetPath = this.sheetNameToPath.get(sheetName);
|
|
4027
|
+
if (!sheetPath) {
|
|
4028
|
+
throw new Error(`XlsxUpdater: sheet "${sheetName}" not found in the workbook.`);
|
|
4029
|
+
}
|
|
4030
|
+
const entry = this.zip.getEntry(sheetPath);
|
|
4031
|
+
if (!entry) {
|
|
4032
|
+
throw new Error(`XlsxUpdater: worksheet part missing for sheet "${sheetName}".`);
|
|
4033
|
+
}
|
|
4034
|
+
const sheetXml = entry.getData().toString("utf8");
|
|
4035
|
+
this._ensureSharedStringsLoaded();
|
|
4036
|
+
let colStyles = /* @__PURE__ */ new Map();
|
|
4037
|
+
let headerStyles = /* @__PURE__ */ new Map();
|
|
4038
|
+
let dateStyle = null;
|
|
4039
|
+
if (styleFallback !== "general") {
|
|
4040
|
+
const collected = this._collectExistingStyles(sheetXml);
|
|
4041
|
+
colStyles = collected.dataStyles;
|
|
4042
|
+
headerStyles = collected.headerStyles;
|
|
4043
|
+
dateStyle = this._findDateStyleIndex();
|
|
4044
|
+
}
|
|
4045
|
+
const lastCol = Math.max(rows.reduce((m, r) => Math.max(m, r.length), 0), (headers == null ? void 0 : headers.length) ?? 0) - 1;
|
|
4046
|
+
const totalRows = rows.length + (headers ? 1 : 0);
|
|
4047
|
+
const newSheetData = this._buildSheetData(rows, headers, colStyles, headerStyles, dateStyle);
|
|
4048
|
+
const newXml = this._patchSheetXml(sheetXml, newSheetData, totalRows, lastCol);
|
|
4049
|
+
this.zip.updateFile(sheetPath, Buffer.from(newXml, "utf8"));
|
|
4050
|
+
if (this.sharedStringsXml !== null) {
|
|
4051
|
+
this._commitSharedStrings();
|
|
4052
|
+
}
|
|
4053
|
+
const dimRef = totalRows > 0 && lastCol >= 0 ? `A1:${columnIndexToLetter(lastCol)}${totalRows}` : "A1";
|
|
4054
|
+
this._updatePivotCaches(sheetName, dimRef, rows.length);
|
|
4055
|
+
this._addRefreshOnLoadToPivotTables();
|
|
4056
|
+
}
|
|
4057
|
+
/**
|
|
4058
|
+
* Write the updated workbook to disk.
|
|
4059
|
+
* @param outputPath Destination path; defaults to the source file (overwrites in place).
|
|
4060
|
+
*/
|
|
4061
|
+
save(outputPath) {
|
|
4062
|
+
const target = outputPath ?? this.sourcePath;
|
|
4063
|
+
fs3.writeFileSync(target, this.zip.toBuffer());
|
|
4064
|
+
}
|
|
4065
|
+
/** The updated workbook as an in-memory ZIP buffer. */
|
|
4066
|
+
toBuffer() {
|
|
4067
|
+
return this.zip.toBuffer();
|
|
4068
|
+
}
|
|
4069
|
+
// ------------------------------------------------------------------
|
|
4070
|
+
// Workbook structure
|
|
4071
|
+
// ------------------------------------------------------------------
|
|
4072
|
+
_loadWorkbookStructure() {
|
|
4073
|
+
const relsEntry = this.zip.getEntry("xl/_rels/workbook.xml.rels");
|
|
4074
|
+
const rIdToTarget = {};
|
|
4075
|
+
if (relsEntry) {
|
|
4076
|
+
const rels = relsEntry.getData().toString("utf8");
|
|
4077
|
+
const relRegex = /<Relationship[^>]*Id="([^"]*)"[^>]*Target="([^"]*)"/g;
|
|
4078
|
+
let match2;
|
|
4079
|
+
while ((match2 = relRegex.exec(rels)) !== null) {
|
|
4080
|
+
rIdToTarget[match2[1]] = match2[2];
|
|
4081
|
+
}
|
|
4082
|
+
}
|
|
4083
|
+
const wbEntry = this.zip.getEntry("xl/workbook.xml");
|
|
4084
|
+
const wbXml = wbEntry ? wbEntry.getData().toString("utf8") : "";
|
|
4085
|
+
const sheetRe = /<sheet\b[^>]*>/g;
|
|
4086
|
+
let match;
|
|
4087
|
+
while ((match = sheetRe.exec(wbXml)) !== null) {
|
|
4088
|
+
const tag = match[0];
|
|
4089
|
+
const nameMatch = /name="([^"]*)"/.exec(tag);
|
|
4090
|
+
const rIdMatch = /r:id="([^"]*)"/.exec(tag);
|
|
4091
|
+
if (!nameMatch || !rIdMatch) continue;
|
|
4092
|
+
const name = nameMatch[1].replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
|
|
4093
|
+
const target = rIdToTarget[rIdMatch[1]] ?? "";
|
|
4094
|
+
let fullPath = target;
|
|
4095
|
+
if (fullPath.startsWith("/")) {
|
|
4096
|
+
fullPath = fullPath.substring(1);
|
|
4097
|
+
} else if (!fullPath.startsWith("xl/")) {
|
|
4098
|
+
fullPath = "xl/" + fullPath;
|
|
4099
|
+
}
|
|
4100
|
+
if (fullPath) {
|
|
4101
|
+
this.sheetNameToPath.set(name, fullPath);
|
|
4102
|
+
}
|
|
4103
|
+
}
|
|
4104
|
+
for (const entry of this.zip.getEntries()) {
|
|
4105
|
+
const name = entry.entryName;
|
|
4106
|
+
if (/^xl\/pivotCache\/pivotCacheDefinition\d*\.xml$/.test(name)) {
|
|
4107
|
+
this.pivotCacheDefs.push({ path: name, xml: entry.getData().toString("utf8") });
|
|
4108
|
+
} else if (/^xl\/pivotTables\/pivotTable\d*\.xml$/.test(name)) {
|
|
4109
|
+
this.pivotTableDefPaths.push(name);
|
|
4110
|
+
}
|
|
4111
|
+
}
|
|
4112
|
+
}
|
|
4113
|
+
// ------------------------------------------------------------------
|
|
4114
|
+
// Shared strings
|
|
4115
|
+
// ------------------------------------------------------------------
|
|
4116
|
+
_ensureSharedStringsLoaded() {
|
|
4117
|
+
if (this.stringIndexMap.size > 0 || this.sharedStringsXml !== null) {
|
|
4118
|
+
return;
|
|
4119
|
+
}
|
|
4120
|
+
const entry = this.zip.getEntry("xl/sharedStrings.xml");
|
|
4121
|
+
if (!entry) {
|
|
4122
|
+
this.sharedStringsXml = null;
|
|
4123
|
+
return;
|
|
4124
|
+
}
|
|
4125
|
+
this.sharedStringsXml = entry.getData().toString("utf8");
|
|
4126
|
+
this.sharedStringsValues = parseSharedStringsXml(this.sharedStringsXml);
|
|
4127
|
+
const countMatch = /<sst\b[^>]*>/.exec(this.sharedStringsXml);
|
|
4128
|
+
const countAttr = countMatch ? /count="(\d+)"/.exec(countMatch[0]) : null;
|
|
4129
|
+
this.sharedStringsCount = countAttr ? parseInt(countAttr[1], 10) : 0;
|
|
4130
|
+
this.sharedStringsValues.forEach((value, index) => {
|
|
4131
|
+
if (!this.stringIndexMap.has(value)) {
|
|
4132
|
+
this.stringIndexMap.set(value, index);
|
|
4133
|
+
}
|
|
4134
|
+
});
|
|
4135
|
+
this.sharedStringsOriginalLength = this.sharedStringsValues.length;
|
|
4136
|
+
}
|
|
4137
|
+
_commitSharedStrings() {
|
|
4138
|
+
if (this.sharedStringsXml === null || this.sharedStringsValues.length === this.sharedStringsOriginalLength) {
|
|
4139
|
+
return;
|
|
4140
|
+
}
|
|
4141
|
+
let xml = this.sharedStringsXml;
|
|
4142
|
+
const sstStart = xml.indexOf("<sst");
|
|
4143
|
+
const sstTagEnd = xml.indexOf(">", sstStart);
|
|
4144
|
+
if (sstStart !== -1 && sstTagEnd !== -1) {
|
|
4145
|
+
const tag = xml.substring(sstStart, sstTagEnd + 1);
|
|
4146
|
+
const newTag = tag.replace(/count="\d+"/, `count="${this.sharedStringsCount}"`).replace(/uniqueCount="\d+"/, `uniqueCount="${this.sharedStringsValues.length}"`);
|
|
4147
|
+
xml = xml.substring(0, sstStart) + newTag + xml.substring(sstTagEnd + 1);
|
|
4148
|
+
}
|
|
4149
|
+
const sstEnd = xml.lastIndexOf("</sst>");
|
|
4150
|
+
if (sstEnd === -1) {
|
|
4151
|
+
return;
|
|
4152
|
+
}
|
|
4153
|
+
let appended = "";
|
|
4154
|
+
for (let i = this.sharedStringsOriginalLength; i < this.sharedStringsValues.length; i++) {
|
|
4155
|
+
const txt = this.sharedStringsValues[i];
|
|
4156
|
+
const clean = escapeXmlText(txt);
|
|
4157
|
+
const preserve = clean.length > 0 && (clean[0] === " " || clean[clean.length - 1] === " " || /[\t\n\r]/.test(clean));
|
|
4158
|
+
appended += preserve ? `<si><t xml:space="preserve">${clean}</t></si>` : `<si><t>${clean}</t></si>`;
|
|
4159
|
+
}
|
|
4160
|
+
xml = xml.substring(0, sstEnd) + appended + xml.substring(sstEnd);
|
|
4161
|
+
this.zip.updateFile("xl/sharedStrings.xml", Buffer.from(xml, "utf8"));
|
|
4162
|
+
}
|
|
4163
|
+
// ------------------------------------------------------------------
|
|
4164
|
+
// Styles
|
|
4165
|
+
// ------------------------------------------------------------------
|
|
4166
|
+
_collectExistingStyles(sheetXml) {
|
|
4167
|
+
const dataCounts = /* @__PURE__ */ new Map();
|
|
4168
|
+
const headerStyles = /* @__PURE__ */ new Map();
|
|
4169
|
+
const sdStart = sheetXml.indexOf("<sheetData>");
|
|
4170
|
+
if (sdStart === -1) return { dataStyles: /* @__PURE__ */ new Map(), headerStyles };
|
|
4171
|
+
const sdEnd = sheetXml.indexOf("</sheetData>", sdStart);
|
|
4172
|
+
if (sdEnd === -1) return { dataStyles: /* @__PURE__ */ new Map(), headerStyles };
|
|
4173
|
+
const region = sheetXml.substring(sdStart, sdEnd);
|
|
4174
|
+
const cellRe = /<c\b[^>]*>/g;
|
|
4175
|
+
let m;
|
|
4176
|
+
while ((m = cellRe.exec(region)) !== null) {
|
|
4177
|
+
const tag = m[0];
|
|
4178
|
+
const rMatch = /r="([A-Z]+)(\d+)"/.exec(tag);
|
|
4179
|
+
if (!rMatch) continue;
|
|
4180
|
+
const col = columnLetterToIndex(rMatch[1]);
|
|
4181
|
+
const row = parseInt(rMatch[2], 10);
|
|
4182
|
+
const sMatch = /s="(\d+)"/.exec(tag);
|
|
4183
|
+
if (!sMatch) continue;
|
|
4184
|
+
const s = parseInt(sMatch[1], 10);
|
|
4185
|
+
if (s <= 0) continue;
|
|
4186
|
+
if (row === 1) {
|
|
4187
|
+
if (!headerStyles.has(col)) headerStyles.set(col, s);
|
|
4188
|
+
continue;
|
|
4189
|
+
}
|
|
4190
|
+
let colCounts = dataCounts.get(col);
|
|
4191
|
+
if (!colCounts) {
|
|
4192
|
+
colCounts = /* @__PURE__ */ new Map();
|
|
4193
|
+
dataCounts.set(col, colCounts);
|
|
4194
|
+
}
|
|
4195
|
+
colCounts.set(s, (colCounts.get(s) ?? 0) + 1);
|
|
4196
|
+
}
|
|
4197
|
+
const dataStyles = /* @__PURE__ */ new Map();
|
|
4198
|
+
for (const [col, colCounts] of dataCounts) {
|
|
4199
|
+
let best = 0;
|
|
4200
|
+
let bestCount = -1;
|
|
4201
|
+
for (const [s, count] of colCounts) {
|
|
4202
|
+
if (count > bestCount) {
|
|
4203
|
+
best = s;
|
|
4204
|
+
bestCount = count;
|
|
4205
|
+
}
|
|
4206
|
+
}
|
|
4207
|
+
if (bestCount > 0) dataStyles.set(col, best);
|
|
4208
|
+
}
|
|
4209
|
+
return { dataStyles, headerStyles };
|
|
4210
|
+
}
|
|
4211
|
+
_findDateStyleIndex() {
|
|
4212
|
+
const entry = this.zip.getEntry("xl/styles.xml");
|
|
4213
|
+
if (!entry) return null;
|
|
4214
|
+
const xml = entry.getData().toString("utf8");
|
|
4215
|
+
const customDateFormats = /* @__PURE__ */ new Set();
|
|
4216
|
+
const numFmtRe = /<numFmt\s+[^>]*numFmtId="(\d+)"[^>]*formatCode="([^"]*)"/g;
|
|
4217
|
+
let m;
|
|
4218
|
+
while ((m = numFmtRe.exec(xml)) !== null) {
|
|
4219
|
+
const id = parseInt(m[1], 10);
|
|
4220
|
+
const code = m[2].toLowerCase();
|
|
4221
|
+
if (code.includes("yy") || code.includes("mm") || code.includes("dd") || code.includes("h:mm")) {
|
|
4222
|
+
customDateFormats.add(id);
|
|
4223
|
+
}
|
|
4224
|
+
}
|
|
4225
|
+
const cellXfsStart = xml.indexOf("<cellXfs");
|
|
4226
|
+
if (cellXfsStart === -1) return null;
|
|
4227
|
+
const cellXfsEnd = xml.indexOf("</cellXfs>", cellXfsStart);
|
|
4228
|
+
if (cellXfsEnd === -1) return null;
|
|
4229
|
+
const cellXfsContent = xml.substring(cellXfsStart, cellXfsEnd);
|
|
4230
|
+
const xfRe = /<xf\b[^>]*>/g;
|
|
4231
|
+
let index = 0;
|
|
4232
|
+
while ((m = xfRe.exec(cellXfsContent)) !== null) {
|
|
4233
|
+
const nfMatch = /numFmtId="(\d+)"/.exec(m[0]);
|
|
4234
|
+
const nfId = nfMatch ? parseInt(nfMatch[1], 10) : 0;
|
|
4235
|
+
const isDate = nfId >= 14 && nfId <= 22 || nfId >= 45 && nfId <= 47 || customDateFormats.has(nfId);
|
|
4236
|
+
if (isDate) return index;
|
|
4237
|
+
index++;
|
|
4238
|
+
}
|
|
4239
|
+
return null;
|
|
4240
|
+
}
|
|
4241
|
+
// ------------------------------------------------------------------
|
|
4242
|
+
// Cell / row serialization
|
|
4243
|
+
// ------------------------------------------------------------------
|
|
4244
|
+
_buildSheetData(rows, headers, colStyles, headerStyles, dateStyle) {
|
|
4245
|
+
let out = "";
|
|
4246
|
+
let rowNum = 0;
|
|
4247
|
+
if (headers) {
|
|
4248
|
+
rowNum = 1;
|
|
4249
|
+
out += '<row r="1">';
|
|
4250
|
+
for (let c = 0; c < headers.length; c++) {
|
|
4251
|
+
const style = headerStyles.get(c) ?? 0;
|
|
4252
|
+
out += this._stringCell(headers[c], c, rowNum, style);
|
|
4253
|
+
}
|
|
4254
|
+
out += "</row>";
|
|
4255
|
+
}
|
|
4256
|
+
for (const row of rows) {
|
|
4257
|
+
rowNum++;
|
|
4258
|
+
out += `<row r="${rowNum}">`;
|
|
4259
|
+
for (let c = 0; c < row.length; c++) {
|
|
4260
|
+
const raw = row[c];
|
|
4261
|
+
if (raw === null || raw === void 0) continue;
|
|
4262
|
+
out += this._valueCell(raw, c, rowNum, colStyles, dateStyle);
|
|
4263
|
+
}
|
|
4264
|
+
out += "</row>";
|
|
4265
|
+
}
|
|
4266
|
+
return out;
|
|
4267
|
+
}
|
|
4268
|
+
_valueCell(raw, col, rowNum, colStyles, dateStyle) {
|
|
4269
|
+
const colRef = columnIndexToLetter(col);
|
|
4270
|
+
const fmtString = getFormat(raw);
|
|
4271
|
+
const val = fmtString !== null ? unwrapCell(raw) : raw;
|
|
4272
|
+
const colStyle = colStyles.get(col) ?? 0;
|
|
4273
|
+
if (typeof val === "number") {
|
|
4274
|
+
if (Number.isFinite(val)) {
|
|
4275
|
+
return `<c r="${colRef}${rowNum}"${colStyle > 0 ? ` s="${colStyle}"` : ""}><v>${val}</v></c>`;
|
|
4276
|
+
}
|
|
4277
|
+
return this._stringCell(val.toString(), col, rowNum, colStyle);
|
|
4278
|
+
}
|
|
4279
|
+
if (typeof val === "bigint") {
|
|
4280
|
+
return this._stringCell(val.toString(), col, rowNum, colStyle);
|
|
4281
|
+
}
|
|
4282
|
+
if (typeof val === "boolean") {
|
|
4283
|
+
return `<c r="${colRef}${rowNum}" t="b"${colStyle > 0 ? ` s="${colStyle}"` : ""}><v>${val ? 1 : 0}</v></c>`;
|
|
4284
|
+
}
|
|
4285
|
+
if (val instanceof Date) {
|
|
4286
|
+
const oaDate = (val.getTime() - this._oaEpoch) / 864e5;
|
|
4287
|
+
if (Number.isFinite(oaDate)) {
|
|
4288
|
+
const style = colStyle > 0 ? colStyle : dateStyle !== null ? dateStyle : 0;
|
|
4289
|
+
return `<c r="${colRef}${rowNum}"${style > 0 ? ` s="${style}"` : ""}><v>${oaDate}</v></c>`;
|
|
4290
|
+
}
|
|
4291
|
+
return this._stringCell(val.toString(), col, rowNum, colStyle);
|
|
4292
|
+
}
|
|
4293
|
+
if (val !== null && val !== void 0) {
|
|
4294
|
+
return this._stringCell(String(val), col, rowNum, colStyle);
|
|
4295
|
+
}
|
|
4296
|
+
return "";
|
|
4297
|
+
}
|
|
4298
|
+
_stringCell(text, col, rowNum, style) {
|
|
4299
|
+
const colRef = columnIndexToLetter(col);
|
|
4300
|
+
const styleAttr = style > 0 ? ` s="${style}"` : "";
|
|
4301
|
+
if (this.sharedStringsXml === null) {
|
|
4302
|
+
const clean = escapeXmlText(text);
|
|
4303
|
+
const preserve = clean.length > 0 && (clean[0] === " " || clean[clean.length - 1] === " " || /[\t\n\r]/.test(clean));
|
|
4304
|
+
const tAttr = preserve ? ' xml:space="preserve"' : "";
|
|
4305
|
+
return `<c r="${colRef}${rowNum}" t="inlineStr"${styleAttr}><is><t${tAttr}>${clean}</t></is></c>`;
|
|
4306
|
+
}
|
|
4307
|
+
let index = this.stringIndexMap.get(text);
|
|
4308
|
+
if (index === void 0) {
|
|
4309
|
+
index = this.sharedStringsValues.length;
|
|
4310
|
+
this.sharedStringsValues.push(text);
|
|
4311
|
+
this.stringIndexMap.set(text, index);
|
|
4312
|
+
}
|
|
4313
|
+
this.sharedStringsCount++;
|
|
4314
|
+
return `<c r="${colRef}${rowNum}" t="s"${styleAttr}><v>${index}</v></c>`;
|
|
4315
|
+
}
|
|
4316
|
+
// ------------------------------------------------------------------
|
|
4317
|
+
// Worksheet XML patching
|
|
4318
|
+
// ------------------------------------------------------------------
|
|
4319
|
+
_patchSheetXml(sheetXml, newSheetData, totalRows, lastCol) {
|
|
4320
|
+
let xml = sheetXml;
|
|
4321
|
+
const dimRef = totalRows > 0 && lastCol >= 0 ? `A1:${columnIndexToLetter(lastCol)}${totalRows}` : "A1";
|
|
4322
|
+
const dimRe = /<dimension\b[^>]*>/;
|
|
4323
|
+
const dimMatch = dimRe.exec(xml);
|
|
4324
|
+
if (dimMatch) {
|
|
4325
|
+
xml = xml.substring(0, dimMatch.index) + dimMatch[0].replace(/ref="[^"]*"/, `ref="${dimRef}"`) + xml.substring(dimMatch.index + dimMatch[0].length);
|
|
4326
|
+
} else {
|
|
4327
|
+
const rootRe = /<worksheet\b[^>]*>/;
|
|
4328
|
+
const rootMatch = rootRe.exec(xml);
|
|
4329
|
+
if (rootMatch) {
|
|
4330
|
+
const insertAt = rootMatch.index + rootMatch[0].length;
|
|
4331
|
+
xml = xml.substring(0, insertAt) + `<dimension ref="${dimRef}"/>` + xml.substring(insertAt);
|
|
4332
|
+
}
|
|
4333
|
+
}
|
|
4334
|
+
const sdOpen = "<sheetData>";
|
|
4335
|
+
const sdStart = xml.indexOf(sdOpen);
|
|
4336
|
+
if (sdStart === -1) {
|
|
4337
|
+
const selfClosing = /<sheetData\s*\/\s*>/;
|
|
4338
|
+
const scMatch = selfClosing.exec(xml);
|
|
4339
|
+
if (scMatch) {
|
|
4340
|
+
xml = xml.substring(0, scMatch.index) + "<sheetData>" + newSheetData + "</sheetData>" + xml.substring(scMatch.index + scMatch[0].length);
|
|
4341
|
+
return xml;
|
|
4342
|
+
}
|
|
4343
|
+
throw new Error("XlsxUpdater: <sheetData> element not found in worksheet XML.");
|
|
4344
|
+
}
|
|
4345
|
+
const sdEnd = xml.indexOf("</sheetData>", sdStart);
|
|
4346
|
+
if (sdEnd === -1) {
|
|
4347
|
+
throw new Error("XlsxUpdater: <sheetData> element not closed in worksheet XML.");
|
|
4348
|
+
}
|
|
4349
|
+
xml = xml.substring(0, sdStart + sdOpen.length) + newSheetData + xml.substring(sdEnd);
|
|
4350
|
+
const afRe = /<autoFilter\b[^>]*>/;
|
|
4351
|
+
const afMatch = afRe.exec(xml);
|
|
4352
|
+
if (afMatch && totalRows > 0 && lastCol >= 0 && afMatch[0].includes("ref=")) {
|
|
4353
|
+
xml = xml.substring(0, afMatch.index) + afMatch[0].replace(/ref="[^"]*"/, `ref="${dimRef}"`) + xml.substring(afMatch.index + afMatch[0].length);
|
|
4354
|
+
}
|
|
4355
|
+
return xml;
|
|
4356
|
+
}
|
|
4357
|
+
// ------------------------------------------------------------------
|
|
4358
|
+
// Pivot table integration
|
|
4359
|
+
// ------------------------------------------------------------------
|
|
4360
|
+
_updatePivotCaches(sheetName, dimRef, recordCount) {
|
|
4361
|
+
for (const cache of this.pivotCacheDefs) {
|
|
4362
|
+
const wsRe = /<worksheetSource\b[^>]*>/;
|
|
4363
|
+
const wsMatch = wsRe.exec(cache.xml);
|
|
4364
|
+
if (!wsMatch) continue;
|
|
4365
|
+
const wsTag = wsMatch[0];
|
|
4366
|
+
const sheetAttr = /sheet="([^"]*)"/.exec(wsTag);
|
|
4367
|
+
if (!sheetAttr || sheetAttr[1] !== sheetName) continue;
|
|
4368
|
+
let xml = cache.xml;
|
|
4369
|
+
xml = xml.substring(0, wsMatch.index) + wsTag.replace(/ref="[^"]*"/, `ref="${dimRef}"`) + xml.substring(wsMatch.index + wsTag.length);
|
|
4370
|
+
const rootRe = /<pivotCacheDefinition\b[^>]*>/;
|
|
4371
|
+
const rootMatch = rootRe.exec(xml);
|
|
4372
|
+
if (rootMatch) {
|
|
4373
|
+
let rootTag = rootMatch[0];
|
|
4374
|
+
if (/recordCount="\d+"/.test(rootTag)) {
|
|
4375
|
+
rootTag = rootTag.replace(/recordCount="\d+"/, `recordCount="${recordCount}"`);
|
|
4376
|
+
} else if (!/\/>$/.test(rootTag)) {
|
|
4377
|
+
rootTag = rootTag.replace(/>$/, ` recordCount="${recordCount}">`);
|
|
4378
|
+
}
|
|
4379
|
+
xml = xml.substring(0, rootMatch.index) + rootTag + xml.substring(rootMatch.index + rootMatch[0].length);
|
|
4380
|
+
}
|
|
4381
|
+
this.zip.updateFile(cache.path, Buffer.from(xml, "utf8"));
|
|
4382
|
+
}
|
|
4383
|
+
}
|
|
4384
|
+
_addRefreshOnLoadToPivotTables() {
|
|
4385
|
+
for (const path2 of this.pivotTableDefPaths) {
|
|
4386
|
+
const entry = this.zip.getEntry(path2);
|
|
4387
|
+
if (!entry) continue;
|
|
4388
|
+
let xml = entry.getData().toString("utf8");
|
|
4389
|
+
const rootRe = /<pivotTableDefinition\b[^>]*>/;
|
|
4390
|
+
const rootMatch = rootRe.exec(xml);
|
|
4391
|
+
if (!rootMatch || rootMatch[0].includes("refreshOnLoad")) continue;
|
|
4392
|
+
const newTag = rootMatch[0].replace(/(\/?>)$/, ' refreshOnLoad="1"$1');
|
|
4393
|
+
xml = xml.substring(0, rootMatch.index) + newTag + xml.substring(rootMatch.index + rootMatch[0].length);
|
|
4394
|
+
this.zip.updateFile(path2, Buffer.from(xml, "utf8"));
|
|
4395
|
+
}
|
|
4396
|
+
}
|
|
4397
|
+
};
|
|
4398
|
+
|
|
4399
|
+
// src/XlsbUpdater.ts
|
|
4400
|
+
var fs4 = __toESM(require("fs"));
|
|
4401
|
+
var import_adm_zip3 = __toESM(require("adm-zip"));
|
|
4402
|
+
|
|
4403
|
+
// src/biff12Utils.ts
|
|
4404
|
+
function readVlq(buf, pos) {
|
|
4405
|
+
let value = 0;
|
|
4406
|
+
let shift = 0;
|
|
4407
|
+
let byte;
|
|
4408
|
+
do {
|
|
4409
|
+
byte = buf[pos++];
|
|
4410
|
+
value |= (byte & 127) << shift;
|
|
4411
|
+
shift += 7;
|
|
4412
|
+
} while ((byte & 128) !== 0);
|
|
4413
|
+
return { value, nextPos: pos };
|
|
4414
|
+
}
|
|
4415
|
+
function vlqBytes(value) {
|
|
4416
|
+
const out = [];
|
|
4417
|
+
while (value >= 128) {
|
|
4418
|
+
out.push(value & 127 | 128);
|
|
4419
|
+
value >>>= 7;
|
|
4420
|
+
}
|
|
4421
|
+
out.push(value & 127);
|
|
4422
|
+
return out;
|
|
4423
|
+
}
|
|
4424
|
+
function readRecord(buf, pos, rec) {
|
|
4425
|
+
const idRes = readVlq(buf, pos);
|
|
4426
|
+
if (idRes.nextPos > buf.length) return false;
|
|
4427
|
+
const lenRes = readVlq(buf, idRes.nextPos);
|
|
4428
|
+
if (lenRes.nextPos + lenRes.value > buf.length) return false;
|
|
4429
|
+
rec.headerStart = pos;
|
|
4430
|
+
rec.dataStart = lenRes.nextPos;
|
|
4431
|
+
rec.dataEnd = lenRes.nextPos + lenRes.value;
|
|
4432
|
+
rec.id = idRes.value;
|
|
4433
|
+
rec.len = lenRes.value;
|
|
4434
|
+
return true;
|
|
4435
|
+
}
|
|
4436
|
+
function buildRecord(id, payload) {
|
|
4437
|
+
const idBytes = vlqBytes(id);
|
|
4438
|
+
const lenBytes = vlqBytes(payload.length);
|
|
4439
|
+
const header = Buffer.alloc(idBytes.length + lenBytes.length);
|
|
4440
|
+
idBytes.forEach((b, i) => header[i] = b);
|
|
4441
|
+
lenBytes.forEach((b, i) => header[idBytes.length + i] = b);
|
|
4442
|
+
return Buffer.concat([header, payload]);
|
|
4443
|
+
}
|
|
4444
|
+
function readUtf16(buf, start, charCount) {
|
|
4445
|
+
const end = start + charCount * 2;
|
|
4446
|
+
if (end > buf.length) return "";
|
|
4447
|
+
return buf.toString("utf16le", start, end);
|
|
4448
|
+
}
|
|
4449
|
+
function parseSharedStringsBin(buf) {
|
|
4450
|
+
const values = [];
|
|
4451
|
+
let total = 0;
|
|
4452
|
+
let unique = 0;
|
|
4453
|
+
let endSstOffset = buf.length;
|
|
4454
|
+
const rec = { headerStart: 0, dataStart: 0, dataEnd: 0, id: 0, len: 0 };
|
|
4455
|
+
let pos = 0;
|
|
4456
|
+
while (readRecord(buf, pos, rec)) {
|
|
4457
|
+
pos = rec.dataEnd;
|
|
4458
|
+
if (rec.id === 159) {
|
|
4459
|
+
total = buf.readUInt32LE(rec.dataStart);
|
|
4460
|
+
unique = buf.readUInt32LE(rec.dataStart + 4);
|
|
4461
|
+
} else if (rec.id === 19) {
|
|
4462
|
+
const cch = buf.readUInt32LE(rec.dataStart + 1);
|
|
4463
|
+
values.push(readUtf16(buf, rec.dataStart + 5, cch));
|
|
4464
|
+
} else if (rec.id === 160) {
|
|
4465
|
+
endSstOffset = rec.headerStart;
|
|
4466
|
+
}
|
|
4467
|
+
}
|
|
4468
|
+
return { values, total, unique, endSstOffset };
|
|
4469
|
+
}
|
|
4470
|
+
|
|
4471
|
+
// src/XlsbUpdater.ts
|
|
4472
|
+
var CELL_RECORDS = /* @__PURE__ */ new Set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
|
|
4473
|
+
var RK_INT_LOWER = -1 << 29;
|
|
4474
|
+
var RK_INT_UPPER = (1 << 29) - 1;
|
|
4475
|
+
var XlsbUpdater = class {
|
|
4476
|
+
/**
|
|
4477
|
+
* @param path Path to an existing `.xlsb` file.
|
|
4478
|
+
*/
|
|
4479
|
+
constructor(path2) {
|
|
4480
|
+
this.sheetNameToPath = /* @__PURE__ */ new Map();
|
|
4481
|
+
this.pivotCacheDefPaths = [];
|
|
4482
|
+
this.sharedStringsBuf = null;
|
|
4483
|
+
this.sharedStringsValues = [];
|
|
4484
|
+
this.sharedStringsTotal = 0;
|
|
4485
|
+
this.sharedStringsUnique = 0;
|
|
4486
|
+
this.sharedStringsEndSst = 0;
|
|
4487
|
+
this.stringIndexMap = /* @__PURE__ */ new Map();
|
|
4488
|
+
// ------------------------------------------------------------------
|
|
4489
|
+
// Shared strings
|
|
4490
|
+
// ------------------------------------------------------------------
|
|
4491
|
+
this._appendCount = 0;
|
|
4492
|
+
this.sourcePath = path2;
|
|
4493
|
+
this._oaEpoch = Date.UTC(1899, 11, 30);
|
|
4494
|
+
if (!fs4.existsSync(path2)) {
|
|
4495
|
+
throw new Error(`XlsbUpdater: file not found: ${path2}`);
|
|
4496
|
+
}
|
|
4497
|
+
this.zip = new import_adm_zip3.default(path2);
|
|
4498
|
+
if (!this.zip.getEntry("xl/workbook.bin")) {
|
|
4499
|
+
throw new Error(
|
|
4500
|
+
"XlsbUpdater: not an XLSB workbook (xl/workbook.bin missing). Convert the file to XLSB first."
|
|
4501
|
+
);
|
|
4502
|
+
}
|
|
4503
|
+
this._loadWorkbookStructure();
|
|
4504
|
+
}
|
|
4505
|
+
/** Worksheet names in workbook order. */
|
|
4506
|
+
getSheetNames() {
|
|
4507
|
+
return [...this.sheetNameToPath.keys()];
|
|
4508
|
+
}
|
|
4509
|
+
/**
|
|
4510
|
+
* Clear the entire cell data of the target sheet and write new rows in its place.
|
|
4511
|
+
* All other parts of the workbook (pivot tables, other sheets, styles, …) are preserved.
|
|
4512
|
+
*
|
|
4513
|
+
* @param sheetName Name of the worksheet to replace.
|
|
4514
|
+
* @param rows New data rows (`CellValue` cells; null/undefined = blank).
|
|
4515
|
+
* @param options See {@link ReplaceSheetDataOptions}.
|
|
4516
|
+
*/
|
|
4517
|
+
replaceSheetData(sheetName, rows, options = {}) {
|
|
4518
|
+
const { headers, styleFallback = "inherit" } = options;
|
|
4519
|
+
rows = trimTrailingEmptyRows(rows);
|
|
4520
|
+
const sheetPath = this.sheetNameToPath.get(sheetName);
|
|
4521
|
+
if (!sheetPath) {
|
|
4522
|
+
throw new Error(`XlsbUpdater: sheet "${sheetName}" not found in the workbook.`);
|
|
4523
|
+
}
|
|
4524
|
+
const entry = this.zip.getEntry(sheetPath);
|
|
4525
|
+
if (!entry) {
|
|
4526
|
+
throw new Error(`XlsbUpdater: worksheet part missing for sheet "${sheetName}".`);
|
|
4527
|
+
}
|
|
4528
|
+
const sheetBuf = entry.getData();
|
|
4529
|
+
this._ensureSharedStringsLoaded();
|
|
4530
|
+
let dataStyles = /* @__PURE__ */ new Map();
|
|
4531
|
+
let headerStyles = /* @__PURE__ */ new Map();
|
|
4532
|
+
let dateXf = null;
|
|
4533
|
+
if (styleFallback !== "general") {
|
|
4534
|
+
const collected = this._collectStyles(sheetBuf);
|
|
4535
|
+
dataStyles = collected.dataStyles;
|
|
4536
|
+
headerStyles = collected.headerStyles;
|
|
4537
|
+
dateXf = this._findDateXf();
|
|
4538
|
+
}
|
|
4539
|
+
const lastCol = Math.max(0, Math.max(
|
|
4540
|
+
rows.reduce((m, r) => Math.max(m, r.length), 0),
|
|
4541
|
+
(headers == null ? void 0 : headers.length) ?? 0
|
|
4542
|
+
) - 1);
|
|
4543
|
+
const newRows = this._buildRows(rows, headers, dataStyles, headerStyles, dateXf);
|
|
4544
|
+
const { rowsStart, rowsEnd, autoFilterRanges } = this._findRowsRegion(sheetBuf);
|
|
4545
|
+
const newSheet = Buffer.alloc(sheetBuf.length - (rowsEnd - rowsStart) + newRows.length);
|
|
4546
|
+
sheetBuf.copy(newSheet, 0, 0, rowsStart);
|
|
4547
|
+
newRows.copy(newSheet, rowsStart);
|
|
4548
|
+
sheetBuf.copy(newSheet, rowsStart + newRows.length, rowsEnd);
|
|
4549
|
+
const lastRowIdx = rows.length + (headers ? 1 : 0) - 1;
|
|
4550
|
+
const delta = newRows.length - (rowsEnd - rowsStart);
|
|
4551
|
+
for (const af of autoFilterRanges) {
|
|
4552
|
+
const newAf = af + delta;
|
|
4553
|
+
newSheet.writeInt32LE(lastCol, newAf + 12);
|
|
4554
|
+
newSheet.writeInt32LE(lastRowIdx, newAf + 4);
|
|
4555
|
+
}
|
|
4556
|
+
this._patchDimension(newSheet, lastRowIdx, lastCol);
|
|
4557
|
+
this.zip.updateFile(sheetPath, newSheet);
|
|
4558
|
+
if (this.sharedStringsBuf !== null && this._appendCount > 0) {
|
|
4559
|
+
this._commitSharedStrings();
|
|
4560
|
+
}
|
|
4561
|
+
const rwLast = Math.max(0, rows.length + (headers ? 1 : 0) - 1);
|
|
4562
|
+
const colLast = lastCol;
|
|
4563
|
+
this._patchPivotCaches(sheetName, rwLast, colLast);
|
|
4564
|
+
}
|
|
4565
|
+
/**
|
|
4566
|
+
* Write the updated workbook to disk.
|
|
4567
|
+
* @param outputPath Destination path; defaults to the source file (overwrites in place).
|
|
4568
|
+
*/
|
|
4569
|
+
save(outputPath) {
|
|
4570
|
+
const target = outputPath ?? this.sourcePath;
|
|
4571
|
+
fs4.writeFileSync(target, this.zip.toBuffer());
|
|
4572
|
+
}
|
|
4573
|
+
/** The updated workbook as an in-memory ZIP buffer. */
|
|
4574
|
+
toBuffer() {
|
|
4575
|
+
return this.zip.toBuffer();
|
|
4576
|
+
}
|
|
4577
|
+
// ------------------------------------------------------------------
|
|
4578
|
+
// Workbook structure
|
|
4579
|
+
// ------------------------------------------------------------------
|
|
4580
|
+
_loadWorkbookStructure() {
|
|
4581
|
+
const relsEntry = this.zip.getEntry("xl/_rels/workbook.bin.rels");
|
|
4582
|
+
const rIdToTarget = {};
|
|
4583
|
+
if (relsEntry) {
|
|
4584
|
+
const rels = relsEntry.getData().toString("utf8");
|
|
4585
|
+
const relRegex = /<Relationship[^>]*Id="([^"]*)"[^>]*Target="([^"]*)"/g;
|
|
4586
|
+
let match;
|
|
4587
|
+
while ((match = relRegex.exec(rels)) !== null) {
|
|
4588
|
+
rIdToTarget[match[1]] = match[2];
|
|
4589
|
+
}
|
|
4590
|
+
}
|
|
4591
|
+
const wbEntry = this.zip.getEntry("xl/workbook.bin");
|
|
4592
|
+
if (wbEntry) {
|
|
4593
|
+
const wbBuf = wbEntry.getData();
|
|
4594
|
+
const rec = { headerStart: 0, dataStart: 0, dataEnd: 0, id: 0, len: 0 };
|
|
4595
|
+
let pos = 0;
|
|
4596
|
+
while (readRecord(wbBuf, pos, rec)) {
|
|
4597
|
+
pos = rec.dataEnd;
|
|
4598
|
+
if (rec.id !== 156 || rec.len < 8) continue;
|
|
4599
|
+
let o = rec.dataStart + 8;
|
|
4600
|
+
const rIdLen = wbBuf.readUInt32LE(o);
|
|
4601
|
+
o += 4;
|
|
4602
|
+
const rId = readUtf16(wbBuf, o, rIdLen);
|
|
4603
|
+
o += rIdLen * 2;
|
|
4604
|
+
const nameLen = wbBuf.readUInt32LE(o);
|
|
4605
|
+
o += 4;
|
|
4606
|
+
const name = readUtf16(wbBuf, o, nameLen);
|
|
4607
|
+
let target = rIdToTarget[rId] ?? "";
|
|
4608
|
+
if (target.startsWith("/")) target = target.substring(1);
|
|
4609
|
+
else if (!target.startsWith("xl/")) target = "xl/" + target;
|
|
4610
|
+
if (target) {
|
|
4611
|
+
this.sheetNameToPath.set(name, target);
|
|
4612
|
+
}
|
|
4613
|
+
}
|
|
4614
|
+
}
|
|
4615
|
+
for (const e of this.zip.getEntries()) {
|
|
4616
|
+
if (/^xl\/pivotCache\/pivotCacheDefinition\d*\.bin$/.test(e.entryName)) {
|
|
4617
|
+
this.pivotCacheDefPaths.push(e.entryName);
|
|
4618
|
+
}
|
|
4619
|
+
}
|
|
4620
|
+
}
|
|
4621
|
+
_ensureSharedStringsLoaded() {
|
|
4622
|
+
if (this.stringIndexMap.size > 0 || this.sharedStringsBuf !== null) {
|
|
4623
|
+
return;
|
|
4624
|
+
}
|
|
4625
|
+
const entry = this.zip.getEntry("xl/sharedStrings.bin");
|
|
4626
|
+
if (!entry) {
|
|
4627
|
+
this.sharedStringsBuf = null;
|
|
4628
|
+
return;
|
|
4629
|
+
}
|
|
4630
|
+
this.sharedStringsBuf = entry.getData();
|
|
4631
|
+
const parsed = parseSharedStringsBin(this.sharedStringsBuf);
|
|
4632
|
+
this.sharedStringsValues = parsed.values;
|
|
4633
|
+
this.sharedStringsTotal = parsed.total;
|
|
4634
|
+
this.sharedStringsUnique = parsed.unique;
|
|
4635
|
+
this.sharedStringsEndSst = parsed.endSstOffset;
|
|
4636
|
+
this.sharedStringsValues.forEach((value, index) => {
|
|
4637
|
+
if (!this.stringIndexMap.has(value)) {
|
|
4638
|
+
this.stringIndexMap.set(value, index);
|
|
4639
|
+
}
|
|
4640
|
+
});
|
|
4641
|
+
this._appendCount = 0;
|
|
4642
|
+
}
|
|
4643
|
+
_commitSharedStrings() {
|
|
4644
|
+
if (this.sharedStringsBuf === null || this._appendCount === 0) return;
|
|
4645
|
+
const originalValuesLength = this.sharedStringsValues.length - this._appendCount;
|
|
4646
|
+
let newItems = Buffer.alloc(0);
|
|
4647
|
+
for (let i = originalValuesLength; i < this.sharedStringsValues.length; i++) {
|
|
4648
|
+
const text = this.sharedStringsValues[i];
|
|
4649
|
+
const payload = Buffer.alloc(1 + 4 + text.length * 2);
|
|
4650
|
+
payload[0] = 0;
|
|
4651
|
+
payload.writeUInt32LE(text.length, 1);
|
|
4652
|
+
payload.write(text, 5, text.length * 2, "utf16le");
|
|
4653
|
+
newItems = Buffer.concat([newItems, buildRecord(19, payload)]);
|
|
4654
|
+
}
|
|
4655
|
+
const out = Buffer.alloc(this.sharedStringsBuf.length + newItems.length);
|
|
4656
|
+
this.sharedStringsBuf.copy(out, 0, 0, this.sharedStringsEndSst);
|
|
4657
|
+
newItems.copy(out, this.sharedStringsEndSst);
|
|
4658
|
+
this.sharedStringsBuf.copy(out, this.sharedStringsEndSst + newItems.length, this.sharedStringsEndSst);
|
|
4659
|
+
const rec = { headerStart: 0, dataStart: 0, dataEnd: 0, id: 0, len: 0 };
|
|
4660
|
+
let pos = 0;
|
|
4661
|
+
while (readRecord(out, pos, rec)) {
|
|
4662
|
+
if (rec.id === 159) {
|
|
4663
|
+
out.writeUInt32LE(this.sharedStringsTotal, rec.dataStart);
|
|
4664
|
+
out.writeUInt32LE(this.sharedStringsUnique, rec.dataStart + 4);
|
|
4665
|
+
break;
|
|
4666
|
+
}
|
|
4667
|
+
pos = rec.dataEnd;
|
|
4668
|
+
}
|
|
4669
|
+
this.zip.updateFile("xl/sharedStrings.bin", out);
|
|
4670
|
+
}
|
|
4671
|
+
// ------------------------------------------------------------------
|
|
4672
|
+
// Styles
|
|
4673
|
+
// ------------------------------------------------------------------
|
|
4674
|
+
_collectStyles(sheetBuf) {
|
|
4675
|
+
const dataCounts = /* @__PURE__ */ new Map();
|
|
4676
|
+
const headerStyles = /* @__PURE__ */ new Map();
|
|
4677
|
+
const rec = { headerStart: 0, dataStart: 0, dataEnd: 0, id: 0, len: 0 };
|
|
4678
|
+
let pos = 0;
|
|
4679
|
+
let row = -1;
|
|
4680
|
+
while (readRecord(sheetBuf, pos, rec)) {
|
|
4681
|
+
pos = rec.dataEnd;
|
|
4682
|
+
if (rec.id === 0) {
|
|
4683
|
+
row = sheetBuf.readInt32LE(rec.dataStart);
|
|
4684
|
+
continue;
|
|
4685
|
+
}
|
|
4686
|
+
if (!CELL_RECORDS.has(rec.id) || rec.len < 8) continue;
|
|
4687
|
+
const col = sheetBuf.readUInt32LE(rec.dataStart);
|
|
4688
|
+
const xf = sheetBuf.readUInt32LE(rec.dataStart + 4) & 16777215;
|
|
4689
|
+
if (xf <= 0) continue;
|
|
4690
|
+
if (row === 0) {
|
|
4691
|
+
if (!headerStyles.has(col)) headerStyles.set(col, xf);
|
|
4692
|
+
continue;
|
|
4693
|
+
}
|
|
4694
|
+
let colCounts = dataCounts.get(col);
|
|
4695
|
+
if (!colCounts) {
|
|
4696
|
+
colCounts = /* @__PURE__ */ new Map();
|
|
4697
|
+
dataCounts.set(col, colCounts);
|
|
4698
|
+
}
|
|
4699
|
+
colCounts.set(xf, (colCounts.get(xf) ?? 0) + 1);
|
|
4700
|
+
}
|
|
4701
|
+
const dataStyles = /* @__PURE__ */ new Map();
|
|
4702
|
+
for (const [col, colCounts] of dataCounts) {
|
|
4703
|
+
let best = 0;
|
|
4704
|
+
let bestCount = -1;
|
|
4705
|
+
for (const [xf, count] of colCounts) {
|
|
4706
|
+
if (count > bestCount) {
|
|
4707
|
+
best = xf;
|
|
4708
|
+
bestCount = count;
|
|
4709
|
+
}
|
|
4710
|
+
}
|
|
4711
|
+
if (bestCount > 0) dataStyles.set(col, best);
|
|
4712
|
+
}
|
|
4713
|
+
return { dataStyles, headerStyles };
|
|
4714
|
+
}
|
|
4715
|
+
_findDateXf() {
|
|
4716
|
+
const entry = this.zip.getEntry("xl/styles.bin");
|
|
4717
|
+
if (!entry) return null;
|
|
4718
|
+
const stylesBuf = entry.getData();
|
|
4719
|
+
const rec = { headerStart: 0, dataStart: 0, dataEnd: 0, id: 0, len: 0 };
|
|
4720
|
+
let pos = 0;
|
|
4721
|
+
let inCellXfs = false;
|
|
4722
|
+
let xfIndex = 0;
|
|
4723
|
+
while (readRecord(stylesBuf, pos, rec)) {
|
|
4724
|
+
pos = rec.dataEnd;
|
|
4725
|
+
if (rec.id === 617) {
|
|
4726
|
+
inCellXfs = true;
|
|
4727
|
+
xfIndex = 0;
|
|
4728
|
+
continue;
|
|
4729
|
+
}
|
|
4730
|
+
if (rec.id === 618) {
|
|
4731
|
+
inCellXfs = false;
|
|
4732
|
+
continue;
|
|
4733
|
+
}
|
|
4734
|
+
if (inCellXfs && rec.id === 47 && rec.len >= 4) {
|
|
4735
|
+
const numFmtId = stylesBuf.readUInt16LE(rec.dataStart + 2);
|
|
4736
|
+
const isDate = numFmtId >= 14 && numFmtId <= 22 || numFmtId >= 45 && numFmtId <= 47;
|
|
4737
|
+
if (isDate) return xfIndex;
|
|
4738
|
+
xfIndex++;
|
|
4739
|
+
}
|
|
4740
|
+
}
|
|
4741
|
+
return null;
|
|
4742
|
+
}
|
|
4743
|
+
// ------------------------------------------------------------------
|
|
4744
|
+
// Row / cell serialization
|
|
4745
|
+
// ------------------------------------------------------------------
|
|
4746
|
+
_buildRows(rows, headers, dataStyles, headerStyles, dateXf) {
|
|
4747
|
+
const chunks = [];
|
|
4748
|
+
const maxCol = Math.max(rows.reduce((m, r) => Math.max(m, r.length), 0), (headers == null ? void 0 : headers.length) ?? 0, 0);
|
|
4749
|
+
const colLast = Math.max(0, maxCol - 1);
|
|
4750
|
+
const pushRow = (rowNum2, cellBytes) => {
|
|
4751
|
+
const header = Buffer.alloc(27);
|
|
4752
|
+
header[0] = 0;
|
|
4753
|
+
header[1] = 25;
|
|
4754
|
+
header.writeInt32LE(rowNum2, 2);
|
|
4755
|
+
header[10] = 44;
|
|
4756
|
+
header[11] = 1;
|
|
4757
|
+
header[15] = 1;
|
|
4758
|
+
header.writeInt32LE(0, 19);
|
|
4759
|
+
header.writeInt32LE(colLast, 23);
|
|
4760
|
+
chunks.push(header);
|
|
4761
|
+
for (const cell of cellBytes) {
|
|
4762
|
+
chunks.push(cell);
|
|
4763
|
+
}
|
|
4764
|
+
};
|
|
4765
|
+
if (headers) {
|
|
4766
|
+
const cells = [];
|
|
4767
|
+
for (let c = 0; c < headers.length; c++) {
|
|
4768
|
+
const style = headerStyles.get(c) ?? 0;
|
|
4769
|
+
cells.push(this._stringCellBytes(c, style, headers[c]));
|
|
4770
|
+
}
|
|
4771
|
+
pushRow(0, cells);
|
|
4772
|
+
}
|
|
4773
|
+
let rowNum = headers ? 1 : 0;
|
|
4774
|
+
for (const row of rows) {
|
|
4775
|
+
const cells = [];
|
|
4776
|
+
for (let c = 0; c < row.length; c++) {
|
|
4777
|
+
const raw = row[c];
|
|
4778
|
+
if (raw === null || raw === void 0) continue;
|
|
4779
|
+
cells.push(this._valueCellBytes(raw, c, dataStyles, dateXf));
|
|
4780
|
+
}
|
|
4781
|
+
pushRow(rowNum, cells);
|
|
4782
|
+
rowNum++;
|
|
4783
|
+
}
|
|
4784
|
+
return Buffer.concat(chunks);
|
|
4785
|
+
}
|
|
4786
|
+
_valueCellBytes(raw, col, dataStyles, dateXf) {
|
|
4787
|
+
const fmtString = getFormat(raw);
|
|
4788
|
+
const val = fmtString !== null ? unwrapCell(raw) : raw;
|
|
4789
|
+
const colStyle = dataStyles.get(col) ?? 0;
|
|
4790
|
+
if (typeof val === "number") {
|
|
4791
|
+
if (Number.isFinite(val) && Number.isInteger(val) && val >= RK_INT_LOWER && val <= RK_INT_UPPER) {
|
|
4792
|
+
const payload = Buffer.alloc(12);
|
|
4793
|
+
payload.writeUInt32LE(col, 0);
|
|
4794
|
+
payload.writeUInt32LE(colStyle, 4);
|
|
4795
|
+
payload.writeInt32LE(val << 2 | 2, 8);
|
|
4796
|
+
return buildRecord(2, payload);
|
|
4797
|
+
}
|
|
4798
|
+
if (Number.isFinite(val)) {
|
|
4799
|
+
const payload = Buffer.alloc(16);
|
|
4800
|
+
payload.writeUInt32LE(col, 0);
|
|
4801
|
+
payload.writeUInt32LE(colStyle, 4);
|
|
4802
|
+
payload.writeDoubleLE(val, 8);
|
|
4803
|
+
return buildRecord(5, payload);
|
|
4804
|
+
}
|
|
4805
|
+
return this._stringCellBytes(col, colStyle, val.toString());
|
|
4806
|
+
}
|
|
4807
|
+
if (typeof val === "bigint") {
|
|
4808
|
+
return this._stringCellBytes(col, colStyle, val.toString());
|
|
4809
|
+
}
|
|
4810
|
+
if (typeof val === "boolean") {
|
|
4811
|
+
const payload = Buffer.alloc(9);
|
|
4812
|
+
payload.writeUInt32LE(col, 0);
|
|
4813
|
+
payload.writeUInt32LE(colStyle, 4);
|
|
4814
|
+
payload[8] = val ? 1 : 0;
|
|
4815
|
+
return buildRecord(4, payload);
|
|
4816
|
+
}
|
|
4817
|
+
if (val instanceof Date) {
|
|
4818
|
+
const oaDate = (val.getTime() - this._oaEpoch) / 864e5;
|
|
4819
|
+
if (Number.isFinite(oaDate)) {
|
|
4820
|
+
const style = colStyle > 0 ? colStyle : dateXf !== null ? dateXf : 0;
|
|
4821
|
+
const payload = Buffer.alloc(16);
|
|
4822
|
+
payload.writeUInt32LE(col, 0);
|
|
4823
|
+
payload.writeUInt32LE(style, 4);
|
|
4824
|
+
payload.writeDoubleLE(oaDate, 8);
|
|
4825
|
+
return buildRecord(5, payload);
|
|
4826
|
+
}
|
|
4827
|
+
return this._stringCellBytes(col, colStyle, val.toString());
|
|
4828
|
+
}
|
|
4829
|
+
if (val !== null && val !== void 0) {
|
|
4830
|
+
return this._stringCellBytes(col, colStyle, String(val));
|
|
4831
|
+
}
|
|
4832
|
+
return this._stringCellBytes(col, colStyle, "");
|
|
4833
|
+
}
|
|
4834
|
+
_stringCellBytes(col, style, text) {
|
|
4835
|
+
if (this.sharedStringsBuf === null) {
|
|
4836
|
+
const payload2 = Buffer.alloc(12 + text.length * 2);
|
|
4837
|
+
payload2.writeUInt32LE(col, 0);
|
|
4838
|
+
payload2.writeUInt32LE(style, 4);
|
|
4839
|
+
payload2.writeUInt32LE(text.length, 8);
|
|
4840
|
+
payload2.write(text, 12, text.length * 2, "utf16le");
|
|
4841
|
+
return buildRecord(6, payload2);
|
|
4842
|
+
}
|
|
4843
|
+
let index = this.stringIndexMap.get(text);
|
|
4844
|
+
if (index === void 0) {
|
|
4845
|
+
index = this.sharedStringsValues.length;
|
|
4846
|
+
this.sharedStringsValues.push(text);
|
|
4847
|
+
this.stringIndexMap.set(text, index);
|
|
4848
|
+
this.sharedStringsUnique++;
|
|
4849
|
+
this._appendCount++;
|
|
4850
|
+
}
|
|
4851
|
+
this.sharedStringsTotal++;
|
|
4852
|
+
const payload = Buffer.alloc(12);
|
|
4853
|
+
payload.writeUInt32LE(col, 0);
|
|
4854
|
+
payload.writeUInt32LE(style, 4);
|
|
4855
|
+
payload.writeUInt32LE(index, 8);
|
|
4856
|
+
return buildRecord(7, payload);
|
|
4857
|
+
}
|
|
4858
|
+
// ------------------------------------------------------------------
|
|
4859
|
+
// Rows region detection
|
|
4860
|
+
// ------------------------------------------------------------------
|
|
4861
|
+
_findRowsRegion(sheetBuf) {
|
|
4862
|
+
const autoFilterRanges = [];
|
|
4863
|
+
let rowsStart = -1;
|
|
4864
|
+
let lastCellEnd = -1;
|
|
4865
|
+
let lastW25 = -1;
|
|
4866
|
+
const rec = { headerStart: 0, dataStart: 0, dataEnd: 0, id: 0, len: 0 };
|
|
4867
|
+
let pos = 0;
|
|
4868
|
+
while (readRecord(sheetBuf, pos, rec)) {
|
|
4869
|
+
if (rec.id === 0) {
|
|
4870
|
+
if (rowsStart === -1) rowsStart = rec.headerStart;
|
|
4871
|
+
} else if (rec.id >= 1 && rec.id <= 11) {
|
|
4872
|
+
lastCellEnd = rec.dataEnd;
|
|
4873
|
+
} else if (rec.id === 37 && rec.len === 6) {
|
|
4874
|
+
lastW25 = rec.headerStart;
|
|
4875
|
+
} else if (rec.id === 161 && rec.len >= 16) {
|
|
4876
|
+
autoFilterRanges.push(rec.dataStart);
|
|
4877
|
+
}
|
|
4878
|
+
pos = rec.dataEnd;
|
|
4879
|
+
}
|
|
4880
|
+
if (rowsStart === -1) {
|
|
4881
|
+
const insertAt = lastW25 >= 0 ? lastW25 : sheetBuf.length;
|
|
4882
|
+
return { rowsStart: insertAt, rowsEnd: insertAt, autoFilterRanges };
|
|
4883
|
+
}
|
|
4884
|
+
const rowsEnd = lastCellEnd >= 0 ? lastCellEnd : lastW25 >= 0 ? lastW25 : sheetBuf.length;
|
|
4885
|
+
return { rowsStart, rowsEnd, autoFilterRanges };
|
|
4886
|
+
}
|
|
4887
|
+
/**
|
|
4888
|
+
* Keep the sheet dimension record (0x98) in sync with the new data.
|
|
4889
|
+
* Excel uses its rwLast (payload offset 24) and colLast (payload offset 32)
|
|
4890
|
+
* fields to read the full row range; stale values make the last written row
|
|
4891
|
+
* invisible to Excel (and drop it from pivot refreshes).
|
|
4892
|
+
*/
|
|
4893
|
+
_patchDimension(sheetBuf, lastRowIdx, lastCol) {
|
|
4894
|
+
const rec = { headerStart: 0, dataStart: 0, dataEnd: 0, id: 0, len: 0 };
|
|
4895
|
+
let pos = 0;
|
|
4896
|
+
while (readRecord(sheetBuf, pos, rec)) {
|
|
4897
|
+
if (rec.id === 152 && rec.len >= 36) {
|
|
4898
|
+
sheetBuf.writeInt32LE(lastRowIdx, rec.dataStart + 24);
|
|
4899
|
+
sheetBuf.writeInt32LE(lastCol, rec.dataStart + 32);
|
|
4900
|
+
return;
|
|
4901
|
+
}
|
|
4902
|
+
pos = rec.dataEnd;
|
|
4903
|
+
}
|
|
4904
|
+
}
|
|
4905
|
+
// ------------------------------------------------------------------
|
|
4906
|
+
// Pivot cache integration
|
|
4907
|
+
// ------------------------------------------------------------------
|
|
4908
|
+
_patchPivotCaches(sheetName, rwLast, colLast) {
|
|
4909
|
+
for (const path2 of this.pivotCacheDefPaths) {
|
|
4910
|
+
const entry = this.zip.getEntry(path2);
|
|
4911
|
+
if (!entry) continue;
|
|
4912
|
+
const buf = Buffer.from(entry.getData());
|
|
4913
|
+
const rec = { headerStart: 0, dataStart: 0, dataEnd: 0, id: 0, len: 0 };
|
|
4914
|
+
let pos = 0;
|
|
4915
|
+
let patched = false;
|
|
4916
|
+
let refreshXfPatched = false;
|
|
4917
|
+
while (readRecord(buf, pos, rec)) {
|
|
4918
|
+
pos = rec.dataEnd;
|
|
4919
|
+
if (rec.id === 179 && rec.len >= 4 && !refreshXfPatched) {
|
|
4920
|
+
if (rec.dataStart + 4 <= buf.length) {
|
|
4921
|
+
const v = buf[rec.dataStart + 3];
|
|
4922
|
+
if ((v & 4) === 0) {
|
|
4923
|
+
buf[rec.dataStart + 3] = v | 4;
|
|
4924
|
+
patched = true;
|
|
4925
|
+
}
|
|
4926
|
+
}
|
|
4927
|
+
refreshXfPatched = true;
|
|
4928
|
+
}
|
|
4929
|
+
if (rec.id === 187 && rec.len >= 23) {
|
|
4930
|
+
const cch = buf.readUInt32LE(rec.dataStart + 3);
|
|
4931
|
+
const nameStart = rec.dataStart + 7;
|
|
4932
|
+
const refStart = nameStart + cch * 2;
|
|
4933
|
+
const name = readUtf16(buf, nameStart, cch);
|
|
4934
|
+
if (name === sheetName && refStart + 16 <= buf.length) {
|
|
4935
|
+
buf.writeInt32LE(rwLast, refStart + 4);
|
|
4936
|
+
buf.writeInt32LE(colLast, refStart + 12);
|
|
4937
|
+
patched = true;
|
|
4938
|
+
}
|
|
4939
|
+
}
|
|
4940
|
+
}
|
|
4941
|
+
if (patched) {
|
|
4942
|
+
this.zip.updateFile(path2, buf);
|
|
4943
|
+
}
|
|
4944
|
+
}
|
|
4945
|
+
}
|
|
4946
|
+
};
|
|
4947
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
4948
|
+
0 && (module.exports = {
|
|
4949
|
+
BiffReaderWriter,
|
|
4950
|
+
BigBuffer,
|
|
4951
|
+
ExcelReaderAbstract,
|
|
4952
|
+
F,
|
|
4953
|
+
INVALID_SHEET_NAME_CHARS,
|
|
4954
|
+
ReaderFactory,
|
|
4955
|
+
StreamingSheetState,
|
|
4956
|
+
XlsbReader,
|
|
4957
|
+
XlsbUpdater,
|
|
4958
|
+
XlsbWriter,
|
|
4959
|
+
XlsxReader,
|
|
4960
|
+
XlsxUpdater,
|
|
4961
|
+
XlsxWriter,
|
|
4962
|
+
applyHeaderWidths,
|
|
4963
|
+
defaultColWidth,
|
|
4964
|
+
getFormat,
|
|
4965
|
+
initColWidths,
|
|
4966
|
+
isFormattedCell,
|
|
4967
|
+
sanitizeSheetName,
|
|
4968
|
+
unwrapCell,
|
|
4969
|
+
updateColWidthsFromRows
|
|
4970
|
+
});
|
|
4971
|
+
//# sourceMappingURL=index.js.map
|