@vdhewei/xlsx-template-lib 1.2.1

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/dist/index.mjs ADDED
@@ -0,0 +1,3941 @@
1
+ // src/core.ts
2
+ import * as path from "path";
3
+ import * as fs from "fs";
4
+ import * as etree from "elementtree";
5
+ import JsZip from "jszip";
6
+ import * as console from "console";
7
+ import { imageSize as sizeOf } from "image-size";
8
+ import { isMap } from "util/types";
9
+ var DOCUMENT_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
10
+ var CALC_CHAIN_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain";
11
+ var SHARED_STRINGS_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
12
+ var HYPERLINK_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
13
+ var BufferType = /* @__PURE__ */ ((BufferType2) => {
14
+ BufferType2["Base64"] = "base64";
15
+ BufferType2["String"] = "string";
16
+ BufferType2["Text"] = "text";
17
+ BufferType2["Blob"] = "blob";
18
+ BufferType2["Array"] = "array";
19
+ BufferType2["NodeBuffer"] = "nodebuffer";
20
+ BufferType2["Uint8array"] = "uint8array";
21
+ BufferType2["Arraybuffer"] = "arraybuffer";
22
+ BufferType2["BinaryString"] = "binarystring";
23
+ return BufferType2;
24
+ })(BufferType || {});
25
+ function _getSimple(obj, key) {
26
+ if (key.includes("[")) {
27
+ const parts = key.split(/[\[\]]/);
28
+ const property = parts[0];
29
+ const index = parts[1];
30
+ if (property && index !== void 0) {
31
+ return obj?.[property]?.[index];
32
+ }
33
+ }
34
+ if (isMap(obj)) {
35
+ return obj.get(key);
36
+ }
37
+ return obj?.[key];
38
+ }
39
+ function valueDotGet(obj, path2, defaultValue) {
40
+ if (!path2 || !obj) return defaultValue;
41
+ const keys = path2.split(".");
42
+ let current = obj;
43
+ for (const key of keys) {
44
+ if (current === null || current === void 0) return defaultValue;
45
+ current = _getSimple(current, key);
46
+ }
47
+ return current === void 0 ? defaultValue : current;
48
+ }
49
+ function defaultValueDotGet(obj, p) {
50
+ return valueDotGet(obj, p.name, p.default || "");
51
+ }
52
+ var dateFormatter = (value, _placeholder, _key) => {
53
+ if (value instanceof Date) {
54
+ return Number(value.getTime() / (1e3 * 60 * 60 * 24) + 25569).toString();
55
+ }
56
+ return void 0;
57
+ };
58
+ var numberFormatter = (value, _placeholder, _key) => {
59
+ if (typeof value === "number") {
60
+ return value.toString();
61
+ }
62
+ return void 0;
63
+ };
64
+ var booleanFormatter = (value, _placeholder, _key) => {
65
+ if (typeof value === "boolean") {
66
+ return Number(value).toString();
67
+ }
68
+ return void 0;
69
+ };
70
+ var stringFormatter = (value, _placeholder, _key) => {
71
+ if (typeof value === "string") {
72
+ return value.toString();
73
+ }
74
+ return void 0;
75
+ };
76
+ var defaultRe = /\${(?:([^{}:]+?):)?([^{}:]+?)(?:\.([^{}:]+?))?(?::([^{}:]+?))??}/g;
77
+ var defaultExtractPlaceholders = (inputString, options) => {
78
+ const matches = [];
79
+ const re = options.customPlaceholderRegex || defaultRe;
80
+ if (options.enableDefaultParsing && options.customPlaceholderRegex) {
81
+ let match2;
82
+ while ((match2 = defaultRe.exec(inputString)) !== null) {
83
+ matches.push({
84
+ placeholder: match2[0],
85
+ type: match2[1] || "normal",
86
+ name: match2[2],
87
+ key: match2[3],
88
+ subType: match2[4],
89
+ full: match2[0].length === inputString.length
90
+ });
91
+ }
92
+ }
93
+ let match;
94
+ re.lastIndex = 0;
95
+ while ((match = re.exec(inputString)) !== null) {
96
+ if (options.enableDefaultParsing && options.customPlaceholderRegex) {
97
+ const isDuplicate = matches.some((m) => m.placeholder === match[0]);
98
+ if (isDuplicate) continue;
99
+ }
100
+ matches.push({
101
+ placeholder: match[0],
102
+ type: match[1] || "normal",
103
+ name: match[2],
104
+ key: match[3],
105
+ subType: match[4],
106
+ full: match[0].length === inputString.length
107
+ });
108
+ }
109
+ return matches;
110
+ };
111
+ var defaultFormatters = [
112
+ dateFormatter,
113
+ numberFormatter,
114
+ booleanFormatter,
115
+ stringFormatter
116
+ ];
117
+ var pattern = new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$", "i");
118
+ var isUrl = function(str) {
119
+ return !!pattern.test(str);
120
+ };
121
+ var toArrayBuffer = function(buffer) {
122
+ const ab = new ArrayBuffer(buffer.length);
123
+ const view = new Uint8Array(ab);
124
+ for (let i = 0; i < buffer.length; ++i) {
125
+ view[i] = buffer[i];
126
+ }
127
+ return ab;
128
+ };
129
+ var Workbook = class _Workbook {
130
+ // ==================== 构造函数 ====================
131
+ constructor(option) {
132
+ this.sharedStrings = [];
133
+ this.sharedStringsLookup = {};
134
+ this.sharedStringsPath = "";
135
+ this.sheets = [];
136
+ this.sheet = null;
137
+ this.workbook = null;
138
+ this.workbookPath = null;
139
+ this.contentTypes = null;
140
+ this.prefix = null;
141
+ this.workbookRels = null;
142
+ this.calChainRel = null;
143
+ this.calcChainPath = "";
144
+ // RichData 相关属性
145
+ this.richDataIsInit = false;
146
+ this._relsrichValueRel = null;
147
+ this.rdrichvalue = null;
148
+ this.rdrichvaluestructure = null;
149
+ this.rdRichValueTypes = null;
150
+ this.richValueRel = null;
151
+ this.metadata = null;
152
+ this.option = {
153
+ moveImages: false,
154
+ substituteAllTableRow: false,
155
+ moveSameLineImages: false,
156
+ imageRatio: 100,
157
+ pushDownPageBreakOnTableSubstitution: false,
158
+ imageRootPath: null,
159
+ handleImageError: null,
160
+ ...option
161
+ };
162
+ }
163
+ // ==================== parse 构造函数 ====================
164
+ static async parse(data, option) {
165
+ const w = new _Workbook(option);
166
+ await w.loadTemplate(data);
167
+ return w;
168
+ }
169
+ // ==================== 扩展方法 ====================
170
+ /**
171
+ * 添加自定义替换器
172
+ * @param replacer - 替换函数
173
+ * @returns this(支持链式调用)
174
+ */
175
+ addReplacer(replacer) {
176
+ if (!this.option.replacers) {
177
+ this.option.replacers = [];
178
+ }
179
+ this.option.replacers.push(replacer);
180
+ return this;
181
+ }
182
+ /**
183
+ * 添加自定义格式化器
184
+ * @param formatter - 格式化函数
185
+ * @returns this(支持链式调用)
186
+ */
187
+ addFormatter(formatter) {
188
+ if (!this.option.formatters) {
189
+ this.option.formatters = [];
190
+ }
191
+ this.option.formatters.push(formatter);
192
+ return this;
193
+ }
194
+ /**
195
+ * 设置替换前钩子
196
+ * @param hook - 钩子函数
197
+ * @returns this(支持链式调用)
198
+ */
199
+ setBeforeReplaceHook(hook) {
200
+ this.option.beforeReplace = hook;
201
+ return this;
202
+ }
203
+ /**
204
+ * 设置替换后钩子
205
+ * @param hook - 钩子函数
206
+ * @returns this(支持链式调用)
207
+ */
208
+ setAfterReplaceHook(hook) {
209
+ this.option.afterReplace = hook;
210
+ return this;
211
+ }
212
+ /**
213
+ * 设置自定义占位符提取器
214
+ * @param extractor - 提取函数
215
+ * @returns this(支持链式调用)
216
+ */
217
+ setPlaceholderExtractor(extractor) {
218
+ this.option.customPlaceholderExtractor = extractor;
219
+ return this;
220
+ }
221
+ /**
222
+ * 设置自定义模板正则表达式
223
+ * @param regex - 正则表达式
224
+ * @param enableDefaultParsing - 是否同时启用默认解析,默认 false
225
+ * @returns this(支持链式调用)
226
+ */
227
+ setPlaceholderRegex(regex, enableDefaultParsing = false) {
228
+ this.option.customPlaceholderRegex = regex;
229
+ this.option.enableDefaultParsing = enableDefaultParsing;
230
+ return this;
231
+ }
232
+ /**
233
+ * 设置数值查询器
234
+ * @param h QueryFunction - 设置数值查询器
235
+ * @returns this(支持链式调用)
236
+ */
237
+ setQueryFunctionHandler(h) {
238
+ this.option.customQueryFunction = h;
239
+ return this;
240
+ }
241
+ // ==================== 扩展点执行方法 ====================
242
+ /**
243
+ * 执行自定义替换器链
244
+ * @param cell - 单元格元素
245
+ * @param stringValue - 字符串值
246
+ * @param placeholder - 占位符信息
247
+ * @param substitution - 替换值
248
+ * @returns 替换结果或 undefined
249
+ */
250
+ executeReplacers(cell, stringValue, placeholder, substitution) {
251
+ if (this.option.customReplacer) {
252
+ const result = this.option.customReplacer(cell, stringValue, placeholder, substitution);
253
+ if (result !== void 0 && result !== null) {
254
+ return result;
255
+ }
256
+ }
257
+ if (this.option.replacers && this.option.replacers.length > 0) {
258
+ for (const replacer of this.option.replacers) {
259
+ const result = replacer(cell, stringValue, placeholder, substitution);
260
+ if (result !== void 0 && result !== null) {
261
+ return result;
262
+ }
263
+ }
264
+ }
265
+ return void 0;
266
+ }
267
+ /**
268
+ * 执行格式化器链
269
+ * @param value - 原始值
270
+ * @param placeholder - 占位符信息
271
+ * @param key - 可选键名
272
+ * @returns 格式化后的字符串
273
+ */
274
+ executeFormatters(value, placeholder, key) {
275
+ if (this.option.formatters && this.option.formatters.length > 0) {
276
+ for (const formatter of this.option.formatters) {
277
+ const result = formatter(value, placeholder, key);
278
+ if (result !== void 0 && result !== null) {
279
+ return result;
280
+ }
281
+ }
282
+ }
283
+ for (const formatter of defaultFormatters) {
284
+ const result = formatter(value, placeholder, key);
285
+ if (result !== void 0 && result !== null) {
286
+ return result;
287
+ }
288
+ }
289
+ return "";
290
+ }
291
+ /**
292
+ * 执行替换前钩子
293
+ */
294
+ executeBeforeReplaceHook(stringValue, substitutions) {
295
+ if (this.option.beforeReplace) {
296
+ const result = this.option.beforeReplace(stringValue, substitutions);
297
+ if (result !== void 0 && result !== null) {
298
+ return result;
299
+ }
300
+ }
301
+ return stringValue;
302
+ }
303
+ /**
304
+ * 执行替换后钩子
305
+ */
306
+ executeAfterReplaceHook(resultString, stringValue, substitutions) {
307
+ if (this.option.afterReplace) {
308
+ return this.option.afterReplace(resultString, stringValue, substitutions);
309
+ }
310
+ return resultString;
311
+ }
312
+ // ==================== 核心方法 ====================
313
+ /**
314
+ * 删除工作表
315
+ */
316
+ async deleteSheet(sheetName) {
317
+ const sheet = await this.loadSheet(sheetName);
318
+ const sh = this.workbook.find(`sheets/sheet[@sheetId='${sheet.id}']`);
319
+ const sheets = this.workbook.findall("sheets/sheet");
320
+ const sheetIndex = sheets.indexOf(sh);
321
+ const definedNamesParent = this.workbook.find("definedNames");
322
+ if (definedNamesParent) {
323
+ const toRemove = [];
324
+ this.workbook.findall("definedNames/definedName").forEach((def) => {
325
+ if (def.attrib.localSheetId !== void 0) {
326
+ const localId = parseInt(def.attrib.localSheetId);
327
+ if (localId === sheetIndex) {
328
+ toRemove.push(def);
329
+ } else if (localId > sheetIndex) {
330
+ def.attrib.localSheetId = (localId - 1).toString();
331
+ }
332
+ }
333
+ });
334
+ toRemove.forEach((def) => {
335
+ definedNamesParent.remove(def);
336
+ });
337
+ }
338
+ this.workbook.find("sheets").remove(sh);
339
+ const rel = this.workbookRels.find(`Relationship[@Id='${sh.attrib["r:id"]}']`);
340
+ this.workbookRels.remove(rel);
341
+ this._rebuild();
342
+ return this;
343
+ }
344
+ /**
345
+ * 复制工作表
346
+ */
347
+ async copySheet(sheetName, copyName, binary = true) {
348
+ if (binary === false && !process.env.JEST_WORKER_ID) {
349
+ console.warn("Warning: copySheet() called with binary=false. UTF-8 characters may be corrupted.");
350
+ }
351
+ const sheet = await this.loadSheet(sheetName);
352
+ const newSheetIndex = (this.workbook.findall("sheets/sheet").length + 1).toString();
353
+ const fileName = "worksheets/sheet" + newSheetIndex + ".xml";
354
+ const arcName = this.prefix + "/" + fileName;
355
+ const sourceSheetFile = this.archive.file(sheet.filename);
356
+ let sheetContent = await sourceSheetFile.async(`nodebuffer`);
357
+ this.archive.file(arcName, sheetContent);
358
+ this.archive.files[arcName].options.compression = binary ? "STORE" : "DEFLATE";
359
+ const sheetContentType = etree.SubElement(this.contentTypes, "Override");
360
+ sheetContentType.attrib.PartName = "/" + arcName;
361
+ sheetContentType.attrib.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml";
362
+ const newSheet = etree.SubElement(this.workbook.find("sheets"), "sheet");
363
+ const finalSheetName = copyName || "Sheet" + newSheetIndex;
364
+ newSheet.attrib.name = finalSheetName;
365
+ newSheet.attrib.sheetId = newSheetIndex;
366
+ newSheet.attrib["r:id"] = "rId" + newSheetIndex;
367
+ this.workbook.findall("definedNames/definedName").forEach((element) => {
368
+ if (element.text && element.text.split("!").length && element.text.split("!")[0] == sheetName) {
369
+ const newDefinedName = etree.SubElement(this.workbook.find("definedNames"), "definedName", element.attrib);
370
+ newDefinedName.text = finalSheetName + "!" + element.text.split("!")[1];
371
+ const index = Number.parseInt(newSheetIndex, 10) - 1;
372
+ newDefinedName.attrib.localSheetId = `${index}`;
373
+ }
374
+ });
375
+ const newRel = etree.SubElement(this.workbookRels, "Relationship");
376
+ newRel.attrib.Type = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet";
377
+ newRel.attrib.Target = fileName;
378
+ const sourceRels = await this.loadSheetRels(sheet.filename);
379
+ const relFileName = "worksheets/_rels/sheet" + newSheetIndex + ".xml.rels";
380
+ const relArcName = this.prefix + "/" + relFileName;
381
+ const newRelsRoot = this.cloneElement(sourceRels.root, true);
382
+ const newCommentUuid = this.generateUUID();
383
+ sourceRels.root.findall("Relationship").forEach((rel, index) => {
384
+ const relType = rel.attrib.Type;
385
+ const target = rel.attrib.Target;
386
+ const needsFileCopy = [
387
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",
388
+ "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment",
389
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing"
390
+ ];
391
+ if (needsFileCopy.indexOf(relType) !== -1) {
392
+ const sheetDirectory = path.dirname(sheet.filename);
393
+ const sourceFilePath = path.join(sheetDirectory, target).replace(/\\/g, "/");
394
+ const sourceFile = this.archive.file(sourceFilePath);
395
+ if (sourceFile) {
396
+ const fileExtension = path.extname(target);
397
+ const fileBaseName = path.basename(target, fileExtension);
398
+ const fileDir = path.dirname(target);
399
+ const baseNameWithoutNumber = fileBaseName.replace(/\d+$/, "");
400
+ const newFileName = baseNameWithoutNumber + newSheetIndex + fileExtension;
401
+ const newTarget = path.join(fileDir, newFileName).replace(/\\/g, "/");
402
+ const newFilePath = path.join(sheetDirectory, newTarget).replace(/\\/g, "/");
403
+ const content = sourceFile.async(`string`);
404
+ content.then((binaryContent) => {
405
+ if (relType === "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") {
406
+ binaryContent = binaryContent.replace(/data="\d+"/, 'data="' + newSheetIndex + '"');
407
+ } else if (relType === "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments") {
408
+ const uuidWithoutBraces = newCommentUuid.replace(/[{}]/g, "");
409
+ binaryContent = binaryContent.replace(/(<author>tc=\{)[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}(\}<\/author>)/gi, "$1" + uuidWithoutBraces + "$2");
410
+ binaryContent = binaryContent.replace(/(xr:uid="\{)[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}(\}\")/gi, "$1" + uuidWithoutBraces + "$2");
411
+ const commentsContentType = etree.SubElement(this.contentTypes, "Override");
412
+ commentsContentType.attrib.PartName = "/" + newFilePath;
413
+ commentsContentType.attrib.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml";
414
+ } else if (relType === "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment") {
415
+ const uuidWithoutBraces = newCommentUuid.replace(/[{}]/g, "");
416
+ binaryContent = binaryContent.replace(/(\sid="\{)[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}(\}")/gi, "$1" + uuidWithoutBraces + "$2");
417
+ const threadedCommentContentType = etree.SubElement(this.contentTypes, "Override");
418
+ threadedCommentContentType.attrib.PartName = "/" + newFilePath;
419
+ threadedCommentContentType.attrib.ContentType = "application/vnd.ms-excel.threadedcomments+xml";
420
+ }
421
+ this.archive.file(newFilePath, binaryContent);
422
+ this.archive.files[newFilePath].options.compression = binary ? "STORE" : "DEFLATE";
423
+ const newRelInRels = newRelsRoot.findall("Relationship")[index];
424
+ if (newRelInRels) {
425
+ newRelInRels.attrib.Target = newTarget;
426
+ }
427
+ }).catch((err) => {
428
+ console.log(err);
429
+ });
430
+ }
431
+ }
432
+ });
433
+ this.archive.file(relArcName, etree.tostring(newRelsRoot, { encoding: "utf-8" }));
434
+ this.archive.files[relArcName].options.compression = binary ? "STORE" : "DEFLATE";
435
+ this.archive.file("[Content_Types].xml", etree.tostring(this.contentTypes, { encoding: "utf-8" }));
436
+ this._rebuild();
437
+ return this;
438
+ }
439
+ /**
440
+ * 部分重建(复制/删除工作表后)
441
+ */
442
+ _rebuild() {
443
+ const order = ["worksheet", "theme", "styles", "sharedStrings"];
444
+ this.workbookRels.findall("*").sort((rel1, rel2) => {
445
+ const index1 = order.indexOf(path.basename(rel1.attrib.Type));
446
+ const index2 = order.indexOf(path.basename(rel2.attrib.Type));
447
+ if (index1 < 0 && index2 >= 0) return 1;
448
+ if (index1 >= 0 && index2 < 0) return -1;
449
+ if (index1 < 0 && index2 < 0) return 0;
450
+ if (index1 + index2 === 0) {
451
+ if (rel1.attrib.Id && rel2.attrib.Id) {
452
+ return rel1.attrib.Id.substring(3) - rel2.attrib.Id.substring(3);
453
+ }
454
+ return rel1._id - rel2._id;
455
+ }
456
+ return index1 - index2;
457
+ }).forEach((item, index) => {
458
+ item.attrib.Id = "rId" + (index + 1);
459
+ });
460
+ this.workbook.findall("sheets/sheet").forEach((item, index) => {
461
+ item.attrib["r:id"] = "rId" + (index + 1);
462
+ item.attrib.sheetId = (index + 1).toString();
463
+ });
464
+ this.archive.file(
465
+ this.prefix + "/_rels/" + path.basename(this.workbookPath) + ".rels",
466
+ etree.tostring(this.workbookRels, { encoding: "utf-8" })
467
+ );
468
+ this.archive.file(this.workbookPath, etree.tostring(this.workbook, { encoding: "utf-8" }));
469
+ this.sheets = this.loadSheets(this.prefix, this.workbook, this.workbookRels);
470
+ }
471
+ /**
472
+ * 从字节数组加载 .xlsx 文件
473
+ */
474
+ async loadTemplate(data) {
475
+ if (Buffer.isBuffer(data)) {
476
+ data = data.toString("binary");
477
+ }
478
+ this.archive = await JsZip.loadAsync(data, { base64: false, checkCRC32: true });
479
+ const text = await this.archive.file("_rels/.rels").async("string");
480
+ const rels = etree.parse(text).getroot();
481
+ const workbookPath = rels.find(`Relationship[@Type='${DOCUMENT_RELATIONSHIP}']`).attrib.Target;
482
+ this.workbookPath = workbookPath;
483
+ this.prefix = path.dirname(workbookPath);
484
+ const workbookText = await this.archive.file(workbookPath).async(`string`);
485
+ this.workbook = etree.parse(workbookText).getroot();
486
+ const refText = await this.archive.file(this.prefix + "/_rels/" + path.basename(workbookPath) + ".rels").async(`string`);
487
+ this.workbookRels = etree.parse(refText).getroot();
488
+ this.sheets = this.loadSheets(this.prefix, this.workbook, this.workbookRels);
489
+ this.calChainRel = this.workbookRels.find(`Relationship[@Type='${CALC_CHAIN_RELATIONSHIP}']`);
490
+ if (this.calChainRel) {
491
+ this.calcChainPath = this.prefix + "/" + this.calChainRel.attrib.Target;
492
+ }
493
+ this.sharedStringsPath = this.prefix + "/" + this.workbookRels.find(`Relationship[@Type='${SHARED_STRINGS_RELATIONSHIP}']`).attrib.Target;
494
+ this.sharedStrings = [];
495
+ this.sharedStringsLookup = {};
496
+ const sharedText = await this.archive.file(this.sharedStringsPath).async(`string`);
497
+ etree.parse(sharedText).getroot().findall("si").forEach((si) => {
498
+ const t = { text: "" };
499
+ si.findall("t").forEach((tmp) => {
500
+ t.text += tmp.text;
501
+ });
502
+ si.findall("r/t").forEach((tmp) => {
503
+ t.text += tmp.text;
504
+ });
505
+ this.sharedStrings.push(t.text);
506
+ this.sharedStringsLookup[t.text] = this.sharedStrings.length - 1;
507
+ });
508
+ const contentTypeText = await this.archive.file("[Content_Types].xml").async(`string`);
509
+ this.contentTypes = etree.parse(contentTypeText).getroot();
510
+ const jpgType = this.contentTypes.find('Default[@Extension="jpg"]');
511
+ if (jpgType === null) {
512
+ etree.SubElement(this.contentTypes, "Default", { "ContentType": "image/png", "Extension": "jpg" });
513
+ }
514
+ }
515
+ /**
516
+ * 使用给定的替换数据对所有工作表进行插值
517
+ */
518
+ async substituteAll(substitutions) {
519
+ const sheets = this.loadSheets(this.prefix, this.workbook, this.workbookRels);
520
+ for (let sheet of sheets) {
521
+ await this.substitute(sheet.id, substitutions);
522
+ }
523
+ }
524
+ /**
525
+ * 使用给定的替换数据对指定工作表进行插值
526
+ */
527
+ async substitute(sheetName, substitutions) {
528
+ const sheet = await this.loadSheet(sheetName);
529
+ this.sheet = sheet;
530
+ const dimension = sheet.root.find("dimension");
531
+ const sheetData = sheet.root.find("sheetData");
532
+ let currentRow = null;
533
+ let totalRowsInserted = 0;
534
+ let totalColumnsInserted = 0;
535
+ const namedTables = await this.loadTables(sheet.root, sheet.filename);
536
+ const rows = [];
537
+ let drawing = null;
538
+ const rels = await this.loadSheetRels(sheet.filename);
539
+ for (let row of sheetData.findall("row")) {
540
+ currentRow = this.getCurrentRow(row, totalRowsInserted);
541
+ row.attrib.r = `${currentRow}`;
542
+ rows.push(row);
543
+ let cells = [];
544
+ let cellsInserted = 0;
545
+ const newTableRows = [];
546
+ const cellsSubstituteTable = [];
547
+ for (let cell of row.findall("c")) {
548
+ let appendCell = true;
549
+ cell.attrib.r = this.getCurrentCell(cell, currentRow, cellsInserted);
550
+ if (cell.attrib.t === "s") {
551
+ const cellValue = cell.find("v");
552
+ const stringIndex = parseInt(cellValue.text.toString(), 10);
553
+ let strValue = this.sharedStrings[stringIndex];
554
+ if (strValue === void 0) {
555
+ break;
556
+ }
557
+ strValue = this.executeBeforeReplaceHook(strValue, substitutions);
558
+ for (let placeholder of this.extractPlaceholders(strValue)) {
559
+ let newCellsInserted = 0;
560
+ let substitution = this.valueGet(substitutions, placeholder);
561
+ const customResult = this.executeReplacers(cell, strValue, placeholder, substitution);
562
+ if (customResult !== void 0) {
563
+ strValue = customResult;
564
+ return;
565
+ }
566
+ if (placeholder.full && placeholder.type === "table" && substitution instanceof Array) {
567
+ if (placeholder.subType === "image" && drawing == null) {
568
+ if (rels) {
569
+ drawing = await this.loadDrawing(sheet.root, sheet.filename, rels.root);
570
+ } else {
571
+ console.log("Need to implement initRels. Or init this with Excel");
572
+ }
573
+ }
574
+ cellsSubstituteTable.push(cell);
575
+ newCellsInserted = await this.substituteTable(
576
+ row,
577
+ newTableRows,
578
+ cells,
579
+ cell,
580
+ namedTables,
581
+ substitution,
582
+ placeholder,
583
+ drawing
584
+ );
585
+ if (newCellsInserted !== 0 || substitution.length) {
586
+ if (substitution.length === 1) {
587
+ appendCell = true;
588
+ }
589
+ if (substitution[0][placeholder.key] instanceof Array) {
590
+ appendCell = false;
591
+ }
592
+ }
593
+ if (newCellsInserted !== 0) {
594
+ cellsInserted += newCellsInserted;
595
+ this.pushRight(this.workbook, sheet.root, cell.attrib.r, newCellsInserted);
596
+ }
597
+ }
598
+ if (placeholder.full && placeholder.type === "normal" && substitution instanceof Array) {
599
+ appendCell = false;
600
+ newCellsInserted = this.substituteArray(cells, cell, substitution);
601
+ if (newCellsInserted !== 0) {
602
+ cellsInserted += newCellsInserted;
603
+ this.pushRight(this.workbook, sheet.root, cell.attrib.r, newCellsInserted);
604
+ }
605
+ }
606
+ if (placeholder.type === "image" && placeholder.full) {
607
+ if (rels != null) {
608
+ if (drawing == null) {
609
+ drawing = await this.loadDrawing(sheet.root, sheet.filename, rels.root);
610
+ }
611
+ this.substituteImage(cell, strValue, placeholder, substitution, drawing);
612
+ } else {
613
+ console.log("Need to implement initRels. Or init this with Excel");
614
+ }
615
+ }
616
+ if (placeholder.type === "imageincell" && placeholder.full) {
617
+ await this.substituteImageInCell(cell, substitution);
618
+ } else {
619
+ if (placeholder.key) {
620
+ substitution = this.valueGet(substitutions, placeholder, true);
621
+ }
622
+ strValue = this.substituteScalar(cell, strValue, placeholder, substitution);
623
+ }
624
+ }
625
+ strValue = this.executeAfterReplaceHook(strValue, strValue, substitutions);
626
+ }
627
+ if (appendCell) {
628
+ cells.push(cell);
629
+ }
630
+ }
631
+ this.replaceChildren(row, cells);
632
+ if (cellsInserted !== 0) {
633
+ this.updateRowSpan(row, cellsInserted);
634
+ if (cellsInserted > totalColumnsInserted) {
635
+ totalColumnsInserted = cellsInserted;
636
+ }
637
+ }
638
+ if (newTableRows.length > 0) {
639
+ if (this.option["moveImages"] && rels) {
640
+ if (drawing == null) {
641
+ drawing = await this.loadDrawing(sheet.root, sheet.filename, rels.root);
642
+ }
643
+ if (drawing != null) {
644
+ this.moveAllImages(drawing, row.attrib.r, newTableRows.length);
645
+ }
646
+ }
647
+ const cellsOverTable = row.findall("c").filter(
648
+ (cell) => !cellsSubstituteTable.includes(cell)
649
+ );
650
+ newTableRows.forEach((newRow) => {
651
+ if (this.option && this.option.substituteAllTableRow) {
652
+ cellsOverTable.forEach((cellOverTable) => {
653
+ const newCell = this.cloneElement(cellOverTable);
654
+ newCell.attrib.r = this.joinRef({
655
+ row: newRow.attrib.r,
656
+ col: this.splitRef(newCell.attrib.r).col
657
+ });
658
+ newRow.append(newCell);
659
+ });
660
+ const newSortRow = newRow.findall("c").sort((a, b) => {
661
+ const colA = this.splitRef(a.attrib.r).col;
662
+ const colB = this.splitRef(b.attrib.r).col;
663
+ return this.charToNum(colA) - this.charToNum(colB);
664
+ });
665
+ this.replaceChildren(newRow, newSortRow);
666
+ }
667
+ rows.push(newRow);
668
+ ++totalRowsInserted;
669
+ });
670
+ this.pushDown(this.workbook, sheet.root, namedTables, currentRow, newTableRows.length);
671
+ }
672
+ }
673
+ this.replaceChildren(sheetData, rows);
674
+ this.substituteTableColumnHeaders(namedTables, substitutions);
675
+ this.substituteHyperlinks(rels, substitutions);
676
+ if (dimension) {
677
+ if (totalRowsInserted > 0 || totalColumnsInserted > 0) {
678
+ const dimensionRange = this.splitRange(dimension.attrib.ref);
679
+ const dimensionEndRef = this.splitRef(dimensionRange.end);
680
+ dimensionEndRef.row += totalRowsInserted;
681
+ dimensionEndRef.col = this.numToChar(this.charToNum(dimensionEndRef.col) + totalColumnsInserted);
682
+ dimensionRange.end = this.joinRef(dimensionEndRef);
683
+ dimension.attrib.ref = this.joinRange(dimensionRange);
684
+ }
685
+ }
686
+ sheetData.findall("row").forEach((row) => {
687
+ row.findall("c").forEach((cell) => {
688
+ const formulas = cell.findall("f");
689
+ if (formulas && formulas.length > 0) {
690
+ cell.findall("v").forEach((v) => {
691
+ cell.remove(v);
692
+ });
693
+ }
694
+ });
695
+ });
696
+ this.archive.file(sheet.filename, etree.tostring(sheet.root, { encoding: "utf-8" }));
697
+ this.archive.file(this.workbookPath, etree.tostring(this.workbook, { encoding: "utf-8" }));
698
+ if (rels) {
699
+ this.archive.file(rels.filename, etree.tostring(rels.root, { encoding: "utf-8" }));
700
+ }
701
+ this.writeRichData();
702
+ this.archive.file("[Content_Types].xml", etree.tostring(this.contentTypes, { encoding: "utf-8" }));
703
+ if (this.calcChainPath && this.archive.file(this.calcChainPath)) {
704
+ this.archive.remove(this.calcChainPath);
705
+ }
706
+ await this.writeSharedStrings();
707
+ this.writeTables(namedTables);
708
+ this.writeDrawing(drawing);
709
+ }
710
+ /**
711
+ * 生成新的二进制 .xlsx 文件
712
+ */
713
+ async generate(options) {
714
+ return await this.archive.generateAsync(options);
715
+ }
716
+ /**
717
+ * 查询占位符合数据值
718
+ * @param substitutions 数据对象
719
+ * @param p 占位符
720
+ * @param full 是否fullKey
721
+ * @return any
722
+ */
723
+ valueGet(substitutions, p, full) {
724
+ if (this.option.customQueryFunction === void 0) {
725
+ if (full !== void 0 && typeof full === "boolean" && full && p.key) {
726
+ return valueDotGet(substitutions, p.name + "." + p.key, p.default || "");
727
+ }
728
+ return valueDotGet(substitutions, p.name, p.default || "");
729
+ }
730
+ if (full !== void 0 && typeof full === "boolean" && full && p.key && !p.name.endsWith(`.${p.key}`)) {
731
+ p.name = p.name + "." + p.key;
732
+ }
733
+ return this.option.customQueryFunction(substitutions, p);
734
+ }
735
+ // ==================== 辅助方法 ====================
736
+ async writeSharedStrings() {
737
+ const content = await this.archive.file(this.sharedStringsPath).async("string");
738
+ const root = etree.parse(content).getroot();
739
+ const children = root.getchildren();
740
+ root.delSlice(0, children.length);
741
+ this.sharedStrings.forEach((string) => {
742
+ const si = etree.Element("si");
743
+ const t = etree.Element("t");
744
+ t.text = string;
745
+ si.append(t);
746
+ root.append(si);
747
+ });
748
+ root.attrib.count = `${this.sharedStrings.length}`;
749
+ root.attrib.uniqueCount = `${this.sharedStrings.length}`;
750
+ this.archive.file(this.sharedStringsPath, etree.tostring(root, { encoding: "utf-8" }));
751
+ }
752
+ addSharedString(s) {
753
+ const idx = this.sharedStrings.length;
754
+ this.sharedStrings.push(s);
755
+ this.sharedStringsLookup[s] = idx;
756
+ return idx;
757
+ }
758
+ stringIndex(s) {
759
+ let idx = this.sharedStringsLookup[s];
760
+ if (idx === void 0) {
761
+ idx = this.addSharedString(s);
762
+ }
763
+ return idx;
764
+ }
765
+ replaceString(oldString, newString) {
766
+ let idx = this.sharedStringsLookup[oldString];
767
+ if (idx === void 0) {
768
+ idx = this.addSharedString(newString);
769
+ } else {
770
+ this.sharedStrings[idx] = newString;
771
+ delete this.sharedStringsLookup[oldString];
772
+ this.sharedStringsLookup[newString] = idx;
773
+ }
774
+ return idx;
775
+ }
776
+ loadSheets(prefix, workbook, workbookRels) {
777
+ const sheets = [];
778
+ for (const sheet of workbook.findall("sheets/sheet")) {
779
+ const sheetId = sheet.attrib.sheetId;
780
+ const relId = sheet.attrib["r:id"];
781
+ const relationship = workbookRels.find(`Relationship[@Id='${relId}']`);
782
+ const filename = prefix + "/" + relationship.attrib.Target;
783
+ sheets.push({
784
+ root: sheet,
785
+ filename,
786
+ name: sheet.attrib.name,
787
+ id: parseInt(sheetId, 10)
788
+ });
789
+ }
790
+ return sheets;
791
+ }
792
+ async loadSheet(sheet) {
793
+ let info = null;
794
+ for (let i = 0; i < this.sheets.length; ++i) {
795
+ if (typeof sheet === "number" && this.sheets[i].id === sheet || this.sheets[i].name === sheet) {
796
+ info = this.sheets[i];
797
+ break;
798
+ }
799
+ }
800
+ if (info === null && typeof sheet === "number") {
801
+ info = this.sheets[sheet - 1];
802
+ }
803
+ if (info === null) {
804
+ throw new Error("Sheet " + sheet + " not found");
805
+ }
806
+ const content = await this.archive.file(info.filename).async("string");
807
+ return {
808
+ filename: info.filename,
809
+ name: info.name,
810
+ id: info.id,
811
+ root: etree.parse(content).getroot()
812
+ };
813
+ }
814
+ async loadSheetRels(sheetFilename) {
815
+ const sheetDirectory = path.dirname(sheetFilename);
816
+ const sheetName = path.basename(sheetFilename);
817
+ const relsFilename = path.join(sheetDirectory, "_rels", sheetName + ".rels").replace(/\\/g, "/");
818
+ const relsFile = this.archive.file(relsFilename);
819
+ if (relsFile === null) {
820
+ return this.initSheetRels(sheetFilename);
821
+ }
822
+ const content = await relsFile.async("string");
823
+ return {
824
+ filename: relsFilename,
825
+ root: etree.parse(content).getroot()
826
+ };
827
+ }
828
+ initSheetRels(sheetFilename) {
829
+ const sheetDirectory = path.dirname(sheetFilename);
830
+ const sheetName = path.basename(sheetFilename);
831
+ const relsFilename = path.join(sheetDirectory, "_rels", sheetName + ".rels").replace(/\\/g, "/");
832
+ const element = etree.Element;
833
+ const ElementTree2 = etree.ElementTree;
834
+ const root = element("Relationships");
835
+ root.set("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships");
836
+ const relsEtree = new ElementTree2(root);
837
+ return {
838
+ filename: relsFilename,
839
+ root: relsEtree.getroot()
840
+ };
841
+ }
842
+ async loadDrawing(sheet, sheetFilename, rels) {
843
+ const sheetDirectory = path.dirname(sheetFilename);
844
+ const drawing = { filename: "", root: null };
845
+ const drawingPart = sheet.find("drawing");
846
+ if (drawingPart === null) {
847
+ return this.initDrawing(sheet, rels);
848
+ }
849
+ const relationshipId = drawingPart.attrib["r:id"];
850
+ const target = rels.find(`Relationship[@Id='${relationshipId}']`).attrib.Target;
851
+ const drawingFilename = path.join(sheetDirectory, target).replace(/\\/g, "/");
852
+ const drawContent = await this.archive.file(drawingFilename).async("string");
853
+ const drawingTree = etree.parse(drawContent);
854
+ drawing.filename = drawingFilename;
855
+ drawing.root = drawingTree.getroot();
856
+ drawing.relFilename = path.dirname(drawingFilename) + "/_rels/" + path.basename(drawingFilename) + ".rels";
857
+ const relFile = this.archive.file(drawing.relFilename);
858
+ if (relFile === null) {
859
+ drawing.relRoot = etree.Element("Relationships");
860
+ drawing.relRoot.set("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships");
861
+ } else {
862
+ const relContent = await relFile.async("string");
863
+ drawing.relRoot = etree.parse(relContent).getroot();
864
+ }
865
+ return drawing;
866
+ }
867
+ addContentType(partName, contentType) {
868
+ etree.SubElement(this.contentTypes, "Override", { "ContentType": contentType, "PartName": partName });
869
+ }
870
+ initDrawing(sheet, rels) {
871
+ const maxId = this.findMaxId(rels, "Relationship", "Id", /rId(\d*)/);
872
+ const rel = etree.SubElement(rels, "Relationship");
873
+ sheet.insert(sheet._children.length, etree.Element("drawing", { "r:id": "rId" + maxId }));
874
+ rel.set("Id", "rId" + maxId);
875
+ rel.set("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing");
876
+ const drawing = {};
877
+ const drawingFilename = "drawing" + this.findMaxFileId(/xl\/drawings\/drawing\d*\.xml/, /drawing(\d*)\.xml/) + ".xml";
878
+ rel.set("Target", "../drawings/" + drawingFilename);
879
+ drawing.root = etree.Element("xdr:wsDr");
880
+ drawing.root.set("xmlns:xdr", "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing");
881
+ drawing.root.set("xmlns:a", "http://schemas.openxmlformats.org/drawingml/2006/main");
882
+ drawing.filename = "xl/drawings/" + drawingFilename;
883
+ drawing.relFilename = "xl/drawings/_rels/" + drawingFilename + ".rels";
884
+ drawing.relRoot = etree.Element("Relationships");
885
+ drawing.relRoot.set("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships");
886
+ this.addContentType("/" + drawing.filename, "application/vnd.openxmlformats-officedocument.drawing+xml");
887
+ return drawing;
888
+ }
889
+ writeDrawing(drawing) {
890
+ if (drawing !== null) {
891
+ this.archive.file(drawing.filename, etree.tostring(drawing.root, { encoding: "utf-8" }));
892
+ this.archive.file(drawing.relFilename, etree.tostring(drawing.relRoot, { encoding: "utf-8" }));
893
+ }
894
+ }
895
+ moveAllImages(drawing, fromRow, nbRow) {
896
+ drawing.root.getchildren().forEach((drawElement) => {
897
+ if (drawElement.tag == "xdr:twoCellAnchor") {
898
+ this._moveTwoCellAnchor(drawElement, fromRow, nbRow);
899
+ }
900
+ });
901
+ }
902
+ _moveTwoCellAnchor(drawingElement, fromRow, nbRow) {
903
+ const _moveImage = (drawingElement2, fromRow2, nbRow2) => {
904
+ let num;
905
+ if (typeof nbRow2 === "string") {
906
+ num = Number.parseInt(nbRow2, 10);
907
+ } else {
908
+ num = nbRow2;
909
+ }
910
+ drawingElement2.find("xdr:from").find("xdr:row").text = Number.parseInt(drawingElement2.find("xdr:from").find("xdr:row").text, 10) + num;
911
+ drawingElement2.find("xdr:to").find("xdr:row").text = Number.parseInt(drawingElement2.find("xdr:to").find("xdr:row").text, 10) + num;
912
+ };
913
+ if (this.option["moveSameLineImages"]) {
914
+ if (parseInt(drawingElement.find("xdr:from").find("xdr:row").text) + 1 >= parseInt(fromRow)) {
915
+ _moveImage(drawingElement, fromRow, nbRow);
916
+ }
917
+ } else {
918
+ if (parseInt(drawingElement.find("xdr:from").find("xdr:row").text) + 1 > parseInt(fromRow)) {
919
+ _moveImage(drawingElement, fromRow, nbRow);
920
+ }
921
+ }
922
+ }
923
+ async loadTables(sheet, sheetFilename) {
924
+ const sheetDirectory = path.dirname(sheetFilename);
925
+ const sheetName = path.basename(sheetFilename);
926
+ const relsFilename = sheetDirectory + "/_rels/" + sheetName + ".rels";
927
+ const relsFile = this.archive.file(relsFilename);
928
+ const tables = [];
929
+ if (relsFile === null) {
930
+ return tables;
931
+ }
932
+ const relsContent = await relsFile.async("string");
933
+ const rels = etree.parse(relsContent).getroot();
934
+ for (let tablePart of sheet.findall("tableParts/tablePart")) {
935
+ const relationshipId = tablePart.attrib["r:id"];
936
+ const target = rels.find(`Relationship[@Id='${relationshipId}']`).attrib.Target;
937
+ const tableFilename = target.replace("..", this.prefix);
938
+ const content = await this.archive.file(tableFilename).async("string");
939
+ const tableTree = etree.parse(content);
940
+ tables.push({
941
+ filename: tableFilename,
942
+ root: tableTree.getroot()
943
+ });
944
+ }
945
+ return tables;
946
+ }
947
+ writeTables(tables) {
948
+ tables.forEach((namedTable) => {
949
+ this.archive.file(namedTable.filename, etree.tostring(namedTable.root, { encoding: "utf-8" }));
950
+ });
951
+ }
952
+ substituteHyperlinks(rels, substitutions) {
953
+ if (rels === null) {
954
+ return;
955
+ }
956
+ const relationships = rels.root._children;
957
+ relationships.forEach((relationship) => {
958
+ if (relationship.attrib.Type === HYPERLINK_RELATIONSHIP) {
959
+ let target = relationship.attrib.Target;
960
+ target = decodeURI(decodeURI(target));
961
+ this.extractPlaceholders(target).forEach((placeholder) => {
962
+ const substitution = substitutions[placeholder.name];
963
+ if (substitution === void 0) {
964
+ return;
965
+ }
966
+ target = target.replace(placeholder.placeholder, this.stringify(substitution));
967
+ relationship.attrib.Target = encodeURI(target);
968
+ });
969
+ }
970
+ });
971
+ }
972
+ substituteTableColumnHeaders(tables, substitutions) {
973
+ tables.forEach((table) => {
974
+ const root = table.root;
975
+ const columns = root.find("tableColumns");
976
+ const autoFilter = root.find("autoFilter");
977
+ const tableRange = this.splitRange(root.attrib.ref);
978
+ let idx = 0;
979
+ let inserted = 0;
980
+ const newColumns = [];
981
+ columns.findall("tableColumn").forEach((col) => {
982
+ ++idx;
983
+ col.attrib.id = Number(idx).toString();
984
+ newColumns.push(col);
985
+ let name = col.attrib.name;
986
+ this.extractPlaceholders(name).forEach((placeholder) => {
987
+ const substitution = substitutions[placeholder.name];
988
+ if (substitution === void 0) {
989
+ return;
990
+ }
991
+ if (placeholder.full && placeholder.type === "normal" && substitution instanceof Array) {
992
+ substitution.forEach((element, i) => {
993
+ let newCol = col;
994
+ if (i > 0) {
995
+ newCol = this.cloneElement(newCol);
996
+ newCol.attrib.id = Number(++idx).toString();
997
+ newColumns.push(newCol);
998
+ ++inserted;
999
+ tableRange.end = this.nextCol(tableRange.end);
1000
+ }
1001
+ newCol.attrib.name = this.stringify(element);
1002
+ });
1003
+ } else {
1004
+ name = name.replace(placeholder.placeholder, this.stringify(substitution));
1005
+ col.attrib.name = name;
1006
+ }
1007
+ });
1008
+ });
1009
+ this.replaceChildren(columns, newColumns);
1010
+ if (inserted > 0) {
1011
+ columns.attrib.count = Number(idx).toString();
1012
+ root.attrib.ref = this.joinRange(tableRange);
1013
+ if (autoFilter !== null) {
1014
+ autoFilter.attrib.ref = this.joinRange(tableRange);
1015
+ }
1016
+ }
1017
+ const tableRoot = table.root;
1018
+ const tableRange2 = this.splitRange(tableRoot.attrib.ref);
1019
+ const tableStart = this.splitRef(tableRange2.start);
1020
+ const tableEnd = this.splitRef(tableRange2.end);
1021
+ if (tableRoot.attrib.totalsRowCount) {
1022
+ const autoFilter2 = tableRoot.find("autoFilter");
1023
+ if (autoFilter2 !== null) {
1024
+ autoFilter2.attrib.ref = this.joinRange({
1025
+ start: this.joinRef(tableStart),
1026
+ end: this.joinRef(tableEnd)
1027
+ });
1028
+ }
1029
+ ++tableEnd.row;
1030
+ tableRoot.attrib.ref = this.joinRange({
1031
+ start: this.joinRef(tableStart),
1032
+ end: this.joinRef(tableEnd)
1033
+ });
1034
+ }
1035
+ });
1036
+ }
1037
+ /**
1038
+ * 提取字符串中可能存在的占位符标记
1039
+ * 支持扩展:自定义正则表达式和自定义提取器
1040
+ */
1041
+ extractPlaceholders(inputString) {
1042
+ if (this.option.customPlaceholderExtractor) {
1043
+ return this.option.customPlaceholderExtractor(inputString, this.option);
1044
+ }
1045
+ return defaultExtractPlaceholders(inputString, this.option);
1046
+ }
1047
+ splitRef(ref) {
1048
+ const match = ref.match(/(?:(.+)!)?(\$)?([A-Z]+)?(\$)?([0-9]+)/);
1049
+ return {
1050
+ table: match && match[1] || null,
1051
+ colAbsolute: Boolean(match && match[2]),
1052
+ col: match && match[3] || "",
1053
+ rowAbsolute: Boolean(match && match[4]),
1054
+ row: parseInt(match && match[5], 10)
1055
+ };
1056
+ }
1057
+ joinRef(ref) {
1058
+ return (ref.table ? ref.table + "!" : "") + (ref.colAbsolute ? "$" : "") + ref.col.toUpperCase() + (ref.rowAbsolute ? "$" : "") + Number(ref.row).toString();
1059
+ }
1060
+ nextCol(ref) {
1061
+ ref = ref.toUpperCase();
1062
+ return ref.replace(/[A-Z]+/, (match) => {
1063
+ return this.numToChar(this.charToNum(match) + 1);
1064
+ });
1065
+ }
1066
+ nextRow(ref) {
1067
+ ref = ref.toUpperCase();
1068
+ return ref.replace(/[0-9]+/, (match) => {
1069
+ return (parseInt(match, 10) + 1).toString();
1070
+ });
1071
+ }
1072
+ charToNum(str) {
1073
+ let num = 0;
1074
+ if (typeof str === "string") {
1075
+ for (let idx = str.length - 1, iteration = 0; idx >= 0; --idx, ++iteration) {
1076
+ const thisChar = str.charCodeAt(idx) - 64;
1077
+ const multiplier = Math.pow(26, iteration);
1078
+ num += multiplier * thisChar;
1079
+ }
1080
+ } else {
1081
+ num = str;
1082
+ }
1083
+ return num;
1084
+ }
1085
+ numToChar(num) {
1086
+ let str = "";
1087
+ for (let i = 0; num > 0; ++i) {
1088
+ let remainder = num % 26;
1089
+ let charCode = remainder + 64;
1090
+ num = (num - remainder) / 26;
1091
+ if (remainder === 0) {
1092
+ charCode = 90;
1093
+ --num;
1094
+ }
1095
+ str = String.fromCharCode(charCode) + str;
1096
+ }
1097
+ return str;
1098
+ }
1099
+ generateUUID() {
1100
+ const hexDigits = "0123456789ABCDEF";
1101
+ let uuid = "{";
1102
+ for (let i = 0; i < 36; i++) {
1103
+ if (i === 8 || i === 13 || i === 18 || i === 23) {
1104
+ uuid += "-";
1105
+ } else {
1106
+ uuid += hexDigits[Math.floor(Math.random() * 16)];
1107
+ }
1108
+ }
1109
+ uuid += "}";
1110
+ return uuid;
1111
+ }
1112
+ isRange(ref) {
1113
+ return ref.indexOf(":") !== -1;
1114
+ }
1115
+ isWithin(ref, startRef, endRef) {
1116
+ const start = this.splitRef(startRef);
1117
+ const end = this.splitRef(endRef);
1118
+ const target = this.splitRef(ref);
1119
+ start.col = `${this.charToNum(start.col)}`;
1120
+ end.col = `${this.charToNum(end.col)}`;
1121
+ target.col = `${this.charToNum(target.col)}`;
1122
+ return start.row <= target.row && target.row <= end.row && start.col <= target.col && target.col <= end.col;
1123
+ }
1124
+ /**
1125
+ * 将任意类型的值转换为字符串
1126
+ * 支持扩展:使用自定义格式化器
1127
+ */
1128
+ stringify(value, placeholder, key) {
1129
+ if (placeholder) {
1130
+ return this.executeFormatters(value, placeholder, key);
1131
+ }
1132
+ if (value instanceof Date) {
1133
+ return Number(value.getTime() / (1e3 * 60 * 60 * 24) + 25569).toString();
1134
+ } else if (typeof value === "number" || typeof value === "boolean") {
1135
+ return Number(value).toString();
1136
+ } else if (typeof value === "string") {
1137
+ return String(value).toString();
1138
+ }
1139
+ return "";
1140
+ }
1141
+ insertCellValue(cell, substitution) {
1142
+ const cellValue = cell.find("v");
1143
+ const stringify = this.stringify(substitution);
1144
+ if (typeof substitution === "string" && substitution[0] === "=") {
1145
+ const formula = etree.Element("f");
1146
+ formula.text = substitution.substring(1);
1147
+ cell.insert(1, formula);
1148
+ delete cell.attrib.t;
1149
+ return formula.text.toString();
1150
+ }
1151
+ if (typeof substitution === "number" || substitution instanceof Date) {
1152
+ delete cell.attrib.t;
1153
+ cellValue.text = stringify;
1154
+ } else if (typeof substitution === "boolean") {
1155
+ cell.attrib.t = "b";
1156
+ cellValue.text = stringify;
1157
+ } else {
1158
+ cell.attrib.t = "s";
1159
+ cellValue.text = Number(this.stringIndex(stringify)).toString();
1160
+ }
1161
+ return stringify;
1162
+ }
1163
+ /**
1164
+ * 执行单个值的替换
1165
+ * 支持扩展:调用自定义替换器
1166
+ */
1167
+ substituteScalar(cell, string, placeholder, substitution) {
1168
+ const customResult = this.executeReplacers(cell, string, placeholder, substitution);
1169
+ if (customResult !== void 0) {
1170
+ if (placeholder.full) {
1171
+ return this.insertCellValue(cell, customResult);
1172
+ } else {
1173
+ cell.attrib.t = "s";
1174
+ return this.insertCellValue(cell, customResult);
1175
+ }
1176
+ }
1177
+ if (placeholder.full) {
1178
+ return this.insertCellValue(cell, substitution);
1179
+ } else {
1180
+ const newString = string.replace(placeholder.placeholder, this.stringify(substitution, placeholder));
1181
+ cell.attrib.t = "s";
1182
+ return this.insertCellValue(cell, newString);
1183
+ }
1184
+ }
1185
+ substituteArray(cells, cell, substitution) {
1186
+ let newCellsInserted = -1;
1187
+ let currentCell = cell.attrib.r;
1188
+ substitution.forEach((element) => {
1189
+ ++newCellsInserted;
1190
+ if (newCellsInserted > 0) {
1191
+ currentCell = this.nextCol(currentCell);
1192
+ }
1193
+ const newCell = this.cloneElement(cell);
1194
+ this.insertCellValue(newCell, element);
1195
+ newCell.attrib.r = currentCell;
1196
+ cells.push(newCell);
1197
+ });
1198
+ return newCellsInserted;
1199
+ }
1200
+ async substituteTable(row, newTableRows, cells, cell, namedTables, substitution, placeholder, drawing) {
1201
+ let newCellsInserted = 0;
1202
+ if (substitution.length === 0) {
1203
+ delete cell.attrib.t;
1204
+ this.replaceChildren(cell, []);
1205
+ } else {
1206
+ const parentTables = namedTables.filter((namedTable) => {
1207
+ const range = this.splitRange(namedTable.root.attrib.ref);
1208
+ return this.isWithin(cell.attrib.r, range.start, range.end);
1209
+ });
1210
+ for (const [idx, element] of substitution.entries()) {
1211
+ let newRow;
1212
+ let newCell;
1213
+ let newCellsInsertedOnNewRow = 0;
1214
+ const newCells = [];
1215
+ const value = this.valueGet(element, placeholder);
1216
+ if (idx === 0) {
1217
+ if (value instanceof Array) {
1218
+ newCellsInserted = this.substituteArray(cells, cell, value);
1219
+ } else if (placeholder.subType == "image" && value != "") {
1220
+ this.substituteImage(cell, placeholder.placeholder, placeholder, value, drawing);
1221
+ } else if (placeholder.subType === "imageincell" && value != "") {
1222
+ await this.substituteImageInCell(cell, value);
1223
+ } else {
1224
+ const customResult = this.executeReplacers(cell, "", placeholder, value);
1225
+ if (customResult !== void 0) {
1226
+ this.insertCellValue(cell, customResult);
1227
+ } else {
1228
+ this.insertCellValue(cell, value);
1229
+ }
1230
+ }
1231
+ } else {
1232
+ if (idx - 1 < newTableRows.length) {
1233
+ newRow = newTableRows[idx - 1];
1234
+ } else {
1235
+ newRow = this.cloneElement(row, false);
1236
+ newRow.attrib.r = this.getCurrentRow(row, newTableRows.length + 1);
1237
+ newTableRows.push(newRow);
1238
+ }
1239
+ newCell = this.cloneElement(cell);
1240
+ newCell.attrib.r = this.joinRef({
1241
+ row: newRow.attrib.r,
1242
+ col: this.splitRef(newCell.attrib.r).col
1243
+ });
1244
+ if (value instanceof Array) {
1245
+ newCellsInsertedOnNewRow = this.substituteArray(newCells, newCell, value);
1246
+ newCells.forEach((nc) => {
1247
+ newRow.append(nc);
1248
+ });
1249
+ this.updateRowSpan(newRow, newCellsInsertedOnNewRow);
1250
+ } else if (placeholder.subType == "image" && value != "") {
1251
+ this.substituteImage(newCell, placeholder.placeholder, placeholder, value, drawing);
1252
+ } else if (placeholder.subType === "imageincell" && value != "") {
1253
+ await this.substituteImageInCell(newCell, value);
1254
+ newRow.append(newCell);
1255
+ } else {
1256
+ const customResult = this.executeReplacers(newCell, "", placeholder, value);
1257
+ if (customResult !== void 0) {
1258
+ this.insertCellValue(newCell, customResult);
1259
+ } else {
1260
+ this.insertCellValue(newCell, value);
1261
+ }
1262
+ newRow.append(newCell);
1263
+ }
1264
+ const mergeCell = this.sheet.root.findall("mergeCells/mergeCell").find((c) => this.splitRange(c.attrib.ref).start === cell.attrib.r);
1265
+ const isMergeCell = mergeCell != null;
1266
+ if (isMergeCell) {
1267
+ const originalMergeRange = this.splitRange(mergeCell.attrib.ref);
1268
+ const originalMergeStart = this.splitRef(originalMergeRange.start);
1269
+ const originalMergeEnd = this.splitRef(originalMergeRange.end);
1270
+ for (let column = this.charToNum(originalMergeStart.col) + 1; column <= this.charToNum(originalMergeEnd.col); column++) {
1271
+ const data = this.sheet.root.find("sheetData");
1272
+ const children = data.getchildren();
1273
+ const originalRow = children.find((f) => f.attrib.r == originalMergeStart.row);
1274
+ const col = this.numToChar(column);
1275
+ const originalCell = originalRow.getchildren().find((f) => f.attrib.r.startsWith(col));
1276
+ const additionalCell = this.cloneElement(originalCell);
1277
+ additionalCell.attrib.r = this.joinRef({
1278
+ row: newRow.attrib.r,
1279
+ col: this.numToChar(column)
1280
+ });
1281
+ newRow.append(additionalCell);
1282
+ }
1283
+ }
1284
+ parentTables.forEach((namedTable) => {
1285
+ const tableRoot = namedTable.root;
1286
+ const autoFilter = tableRoot.find("autoFilter");
1287
+ const range = this.splitRange(tableRoot.attrib.ref);
1288
+ if (!this.isWithin(newCell.attrib.r, range.start, range.end)) {
1289
+ range.end = this.nextRow(range.end);
1290
+ tableRoot.attrib.ref = this.joinRange(range);
1291
+ if (autoFilter !== null) {
1292
+ autoFilter.attrib.ref = tableRoot.attrib.ref;
1293
+ }
1294
+ }
1295
+ });
1296
+ }
1297
+ }
1298
+ }
1299
+ return newCellsInserted;
1300
+ }
1301
+ async initRichData() {
1302
+ if (!this.richDataIsInit) {
1303
+ const _relsrichValueRel = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1304
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
1305
+ </Relationships>`;
1306
+ const rdrichvalue = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1307
+ <rvData xmlns="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata" count="0">
1308
+ </rvData>`;
1309
+ const rdrichvaluestructure = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1310
+ <rvStructures xmlns="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata" count="1">
1311
+ <s t="_localImage">
1312
+ <k n="_rvRel:LocalImageIdentifier" t="i"/>
1313
+ <k n="CalcOrigin" t="i"/>
1314
+ </s>
1315
+ </rvStructures>`;
1316
+ const rdRichValueTypes = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1317
+ <rvTypesInfo xmlns="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata2"
1318
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x"
1319
+ xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
1320
+ <global>
1321
+ <keyFlags>
1322
+ <key name="_Self">
1323
+ <flag name="ExcludeFromFile" value="1"/>
1324
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1325
+ </key>
1326
+ <key name="_DisplayString">
1327
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1328
+ </key>
1329
+ <key name="_Flags">
1330
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1331
+ </key>
1332
+ <key name="_Format">
1333
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1334
+ </key>
1335
+ <key name="_SubLabel">
1336
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1337
+ </key>
1338
+ <key name="_Attribution">
1339
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1340
+ </key>
1341
+ <key name="_Icon">
1342
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1343
+ </key>
1344
+ <key name="_Display">
1345
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1346
+ </key>
1347
+ <key name="_CanonicalPropertyNames">
1348
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1349
+ </key>
1350
+ <key name="_ClassificationId">
1351
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1352
+ </key>
1353
+ </keyFlags>
1354
+ </global>
1355
+ </rvTypesInfo>`;
1356
+ const richValueRel = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1357
+ <richValueRels xmlns="http://schemas.microsoft.com/office/spreadsheetml/2022/richvaluerel"
1358
+ xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
1359
+ </richValueRels>`;
1360
+ const metadata = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1361
+ <metadata xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
1362
+ xmlns:xlrd="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata">
1363
+ <metadataTypes count="1">
1364
+ <metadataType name="XLRICHVALUE" minSupportedVersion="120000" copy="1" pasteAll="1" pasteValues="1" merge="1" splitFirst="1" rowColShift="1" clearFormats="1" clearComments="1" assign="1" coerce="1"/>
1365
+ </metadataTypes>
1366
+ <futureMetadata name="XLRICHVALUE" count="0">
1367
+ </futureMetadata>
1368
+ <valueMetadata count="0">
1369
+ </valueMetadata>
1370
+ </metadata>`;
1371
+ const _relsrichValueRelFileName = "xl/richData/_rels/richValueRel.xml.rels";
1372
+ const rdrichvalueFileName = "xl/richData/rdrichvalue.xml";
1373
+ const rdrichvaluestructureFileName = "xl/richData/rdrichvaluestructure.xml";
1374
+ const rdRichValueTypesFileName = "xl/richData/rdRichValueTypes.xml";
1375
+ const richValueRelFileName = "xl/richData/richValueRel.xml";
1376
+ const metadataFileName = "xl/metadata.xml";
1377
+ this._relsrichValueRel = etree.parse(_relsrichValueRel).getroot();
1378
+ this.rdrichvalue = etree.parse(rdrichvalue).getroot();
1379
+ this.rdrichvaluestructure = etree.parse(rdrichvaluestructure).getroot();
1380
+ this.rdRichValueTypes = etree.parse(rdRichValueTypes).getroot();
1381
+ this.richValueRel = etree.parse(richValueRel).getroot();
1382
+ this.metadata = etree.parse(metadata).getroot();
1383
+ if (this.archive.file(_relsrichValueRelFileName)) {
1384
+ const content = await this.archive.file(_relsrichValueRelFileName).async("string");
1385
+ this._relsrichValueRel = etree.parse(content).getroot();
1386
+ }
1387
+ if (this.archive.file(rdrichvalueFileName)) {
1388
+ const content = await this.archive.file(rdrichvalueFileName).async("string");
1389
+ this.rdrichvalue = etree.parse(content).getroot();
1390
+ }
1391
+ if (this.archive.file(rdrichvaluestructureFileName)) {
1392
+ const content = await this.archive.file(rdrichvaluestructureFileName).async("string");
1393
+ this.rdrichvaluestructure = etree.parse(content).getroot();
1394
+ }
1395
+ if (this.archive.file(rdRichValueTypesFileName)) {
1396
+ const content = await this.archive.file(rdRichValueTypesFileName).async("string");
1397
+ this.rdRichValueTypes = etree.parse(content).getroot();
1398
+ }
1399
+ if (this.archive.file(richValueRelFileName)) {
1400
+ const content = await this.archive.file(richValueRelFileName).async("string");
1401
+ this.richValueRel = etree.parse(content).getroot();
1402
+ }
1403
+ if (this.archive.file(metadataFileName)) {
1404
+ const content = await this.archive.file(metadataFileName).async("string");
1405
+ this.metadata = etree.parse(content).getroot();
1406
+ }
1407
+ this.richDataIsInit = true;
1408
+ }
1409
+ }
1410
+ writeRichDataAlreadyExist(element, elementSearchName, attributeName, attributeValue) {
1411
+ for (const e of element.findall(elementSearchName)) {
1412
+ if (e.attrib[attributeName] == attributeValue) {
1413
+ return true;
1414
+ }
1415
+ }
1416
+ return false;
1417
+ }
1418
+ writeRichData() {
1419
+ if (this.richDataIsInit) {
1420
+ const _relsrichValueRelFileName = "xl/richData/_rels/richValueRel.xml.rels";
1421
+ const rdrichvalueFileName = "xl/richData/rdrichvalue.xml";
1422
+ const rdrichvaluestructureFileName = "xl/richData/rdrichvaluestructure.xml";
1423
+ const rdRichValueTypesFileName = "xl/richData/rdRichValueTypes.xml";
1424
+ const richValueRelFileName = "xl/richData/richValueRel.xml";
1425
+ const metadataFileName = "xl/metadata.xml";
1426
+ const options = { encoding: "utf-8" };
1427
+ this.archive.file(_relsrichValueRelFileName, etree.tostring(this._relsrichValueRel, options));
1428
+ this.archive.file(rdrichvalueFileName, etree.tostring(this.rdrichvalue, options));
1429
+ this.archive.file(rdrichvaluestructureFileName, etree.tostring(this.rdrichvaluestructure, options));
1430
+ this.archive.file(rdRichValueTypesFileName, etree.tostring(this.rdRichValueTypes, options));
1431
+ this.archive.file(richValueRelFileName, etree.tostring(this.richValueRel, options));
1432
+ this.archive.file(metadataFileName, etree.tostring(this.metadata, options));
1433
+ const broadsideMax = this.findMaxId(this.workbookRels, "Relationship", "Id", /rId(\d*)/);
1434
+ let _rel;
1435
+ if (!this.writeRichDataAlreadyExist(this.workbookRels, "Relationship", "Target", "richData/rdrichvaluestructure.xml")) {
1436
+ _rel = etree.SubElement(this.workbookRels, "Relationship");
1437
+ _rel.set("Id", "rId" + broadsideMax);
1438
+ _rel.set("Type", "http://schemas.microsoft.com/office/2017/06/relationships/rdRichValueStructure");
1439
+ _rel.set("Target", "richData/rdrichvaluestructure.xml");
1440
+ }
1441
+ if (!this.writeRichDataAlreadyExist(this.workbookRels, "Relationship", "Target", "richData/rdrichvalue.xml")) {
1442
+ _rel = etree.SubElement(this.workbookRels, "Relationship");
1443
+ _rel.set("Id", "rId" + (broadsideMax + 1));
1444
+ _rel.set("Type", "http://schemas.microsoft.com/office/2017/06/relationships/rdRichValue");
1445
+ _rel.set("Target", "richData/rdrichvalue.xml");
1446
+ }
1447
+ if (!this.writeRichDataAlreadyExist(this.workbookRels, "Relationship", "Target", "richData/richValueRel.xml")) {
1448
+ _rel = etree.SubElement(this.workbookRels, "Relationship");
1449
+ _rel.set("Id", "rId" + (broadsideMax + 2));
1450
+ _rel.set("Type", "http://schemas.microsoft.com/office/2022/10/relationships/richValueRel");
1451
+ _rel.set("Target", "richData/richValueRel.xml");
1452
+ }
1453
+ if (!this.writeRichDataAlreadyExist(this.workbookRels, "Relationship", "Target", "metadata.xml")) {
1454
+ _rel = etree.SubElement(this.workbookRels, "Relationship");
1455
+ _rel.set("Id", "rId" + (broadsideMax + 3));
1456
+ _rel.set("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata");
1457
+ _rel.set("Target", "metadata.xml");
1458
+ }
1459
+ if (!this.writeRichDataAlreadyExist(this.workbookRels, "Relationship", "Target", "richData/rdRichValueTypes.xml")) {
1460
+ _rel = etree.SubElement(this.workbookRels, "Relationship");
1461
+ _rel.set("Id", "rId" + (broadsideMax + 4));
1462
+ _rel.set("Type", "http://schemas.microsoft.com/office/2017/06/relationships/rdRichValueTypes");
1463
+ _rel.set("Target", "richData/rdRichValueTypes.xml");
1464
+ }
1465
+ if (!this.writeRichDataAlreadyExist(this.contentTypes, "Override", "PartName", "/xl/metadata.xml")) {
1466
+ let ctOverride = etree.SubElement(this.contentTypes, "Override");
1467
+ ctOverride.set("PartName", "/xl/metadata.xml");
1468
+ ctOverride.set("ContentType", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml");
1469
+ }
1470
+ if (!this.writeRichDataAlreadyExist(this.contentTypes, "Override", "PartName", "/xl/richData/richValueRel.xml")) {
1471
+ let ctOverride = etree.SubElement(this.contentTypes, "Override");
1472
+ ctOverride.set("PartName", "/xl/richData/richValueRel.xml");
1473
+ ctOverride.set("ContentType", "application/vnd.ms-excel.richvaluerel+xml");
1474
+ }
1475
+ if (!this.writeRichDataAlreadyExist(this.contentTypes, "Override", "PartName", "/xl/richData/rdrichvalue.xml")) {
1476
+ let ctOverride = etree.SubElement(this.contentTypes, "Override");
1477
+ ctOverride.set("PartName", "/xl/richData/rdrichvalue.xml");
1478
+ ctOverride.set("ContentType", "application/vnd.ms-excel.rdrichvalue+xml");
1479
+ }
1480
+ if (!this.writeRichDataAlreadyExist(this.contentTypes, "Override", "PartName", "/xl/richData/rdrichvaluestructure.xml")) {
1481
+ let ctOverride = etree.SubElement(this.contentTypes, "Override");
1482
+ ctOverride.set("PartName", "/xl/richData/rdrichvaluestructure.xml");
1483
+ ctOverride.set("ContentType", "application/vnd.ms-excel.rdrichvaluestructure+xml");
1484
+ }
1485
+ if (!this.writeRichDataAlreadyExist(this.contentTypes, "Override", "PartName", "/xl/richData/rdRichValueTypes.xml")) {
1486
+ let ctOverride = etree.SubElement(this.contentTypes, "Override");
1487
+ ctOverride.set("PartName", "/xl/richData/rdRichValueTypes.xml");
1488
+ ctOverride.set("ContentType", "application/vnd.ms-excel.rdrichvaluetypes+xml");
1489
+ }
1490
+ this._rebuild();
1491
+ }
1492
+ }
1493
+ async substituteImageInCell(cell, substitution) {
1494
+ if (substitution == null || substitution == "") {
1495
+ this.insertCellValue(cell, "");
1496
+ return true;
1497
+ }
1498
+ await this.initRichData();
1499
+ const maxFildId = this.findMaxFileId(/xl\/media\/image\d*\..*/, /image(\d*)\./);
1500
+ const fileExtension = "jpg";
1501
+ try {
1502
+ substitution = this.imageToBuffer(substitution);
1503
+ } catch (error) {
1504
+ if (this.option && this.option.handleImageError && typeof this.option.handleImageError === "function") {
1505
+ this.option.handleImageError(substitution, error);
1506
+ } else {
1507
+ throw error;
1508
+ }
1509
+ }
1510
+ this.archive.file("xl/media/image" + maxFildId + "." + fileExtension, toArrayBuffer(substitution), {
1511
+ binary: true,
1512
+ base64: false
1513
+ });
1514
+ const maxIdRichData = this.findMaxId(this._relsrichValueRel, "Relationship", "Id", /rId(\d*)/);
1515
+ const _rel = etree.SubElement(this._relsrichValueRel, "Relationship");
1516
+ _rel.set("Id", "rId" + maxIdRichData);
1517
+ _rel.set("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
1518
+ _rel.set("Target", "../media/image" + maxFildId + "." + fileExtension);
1519
+ const currentCountedRichValue = this.rdrichvalue.get("count");
1520
+ this.rdrichvalue.set("count", parseInt(currentCountedRichValue) + 1);
1521
+ const rv = etree.SubElement(this.rdrichvalue, "rv");
1522
+ rv.set("s", "0");
1523
+ const firstV = etree.SubElement(rv, "v");
1524
+ const secondV = etree.SubElement(rv, "v");
1525
+ firstV.text = currentCountedRichValue;
1526
+ secondV.text = "5";
1527
+ const rel = etree.SubElement(this.richValueRel, "rel");
1528
+ rel.set("r:id", "rId" + maxIdRichData);
1529
+ const futureMetadata = this.metadata.findall("futureMetadata").find((fm) => {
1530
+ return fm.attrib.name === "XLRICHVALUE";
1531
+ });
1532
+ const futureMetadataCount = futureMetadata.get("count");
1533
+ futureMetadata.set("count", parseInt(futureMetadataCount) + 1);
1534
+ const bk = etree.SubElement(futureMetadata, "bk");
1535
+ const extLst = etree.SubElement(bk, "extLst");
1536
+ const ext = etree.SubElement(extLst, "ext");
1537
+ ext.set("uri", "{3e2802c4-a4d2-4d8b-9148-e3be6c30e623}");
1538
+ const xlrd_rvb = etree.SubElement(ext, "xlrd:rvb");
1539
+ xlrd_rvb.set("i", futureMetadataCount);
1540
+ const valueMetadataCount = this.metadata.find("valueMetadata").get("count");
1541
+ this.metadata.find("valueMetadata").set("count", parseInt(valueMetadataCount) + 1);
1542
+ const bk_VM = etree.SubElement(this.metadata.find("valueMetadata"), "bk");
1543
+ const rc = etree.SubElement(bk_VM, "rc");
1544
+ const XLRICHVALUEMetaDataTypeIndex = this.metadata.find("metadataTypes").findall("metadataType").findIndex((el) => {
1545
+ return el.attrib.name === "XLRICHVALUE";
1546
+ });
1547
+ rc.set("t", "" + (XLRICHVALUEMetaDataTypeIndex + 1));
1548
+ rc.set("v", valueMetadataCount);
1549
+ cell.set("t", "e");
1550
+ cell.set("vm", parseInt(currentCountedRichValue) + 1);
1551
+ this.insertCellValue(cell, "#VALUE!");
1552
+ return true;
1553
+ }
1554
+ substituteImage(cell, string, placeholder, substitution, drawing) {
1555
+ this.substituteScalar(cell, string, placeholder, "");
1556
+ if (substitution == null || substitution == "") {
1557
+ return true;
1558
+ }
1559
+ const maxId = this.findMaxId(drawing.relRoot, "Relationship", "Id", /rId(\d*)/);
1560
+ const maxFildId = this.findMaxFileId(/xl\/media\/image\d*.jpg/, /image(\d*)\.jpg/);
1561
+ const rel = etree.SubElement(drawing.relRoot, "Relationship");
1562
+ rel.set("Id", "rId" + maxId);
1563
+ rel.set("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
1564
+ rel.set("Target", "../media/image" + maxFildId + ".jpg");
1565
+ try {
1566
+ substitution = this.imageToBuffer(substitution);
1567
+ } catch (error) {
1568
+ if (this.option && this.option.handleImageError && typeof this.option.handleImageError === "function") {
1569
+ this.option.handleImageError(substitution, error);
1570
+ } else {
1571
+ throw error;
1572
+ }
1573
+ }
1574
+ this.archive.file("xl/media/image" + maxFildId + ".jpg", toArrayBuffer(substitution), {
1575
+ binary: true,
1576
+ base64: false
1577
+ });
1578
+ const dimension = sizeOf(substitution);
1579
+ let imageWidth = this.pixelsToEMUs(dimension.width);
1580
+ let imageHeight = this.pixelsToEMUs(dimension.height);
1581
+ let imageInMergeCell = false;
1582
+ for (let mergeCell of this.sheet.root.findall("mergeCells/mergeCell")) {
1583
+ if (this.cellInMergeCells(cell, mergeCell)) {
1584
+ const mergeCellWidth = this.getWidthMergeCell(mergeCell, this.sheet);
1585
+ const mergeCellHeight = this.getHeightMergeCell(mergeCell, this.sheet);
1586
+ const mergeWidthEmus = this.columnWidthToEMUs(mergeCellWidth);
1587
+ const mergeHeightEmus = this.rowHeightToEMUs(mergeCellHeight);
1588
+ const widthRate = imageWidth / mergeWidthEmus;
1589
+ const heightRate = imageHeight / mergeHeightEmus;
1590
+ if (widthRate > heightRate) {
1591
+ imageWidth = Math.floor(imageWidth / widthRate);
1592
+ imageHeight = Math.floor(imageHeight / widthRate);
1593
+ } else {
1594
+ imageWidth = Math.floor(imageWidth / heightRate);
1595
+ imageHeight = Math.floor(imageHeight / heightRate);
1596
+ }
1597
+ imageInMergeCell = true;
1598
+ }
1599
+ }
1600
+ if (!imageInMergeCell) {
1601
+ let ratio = 100;
1602
+ if (this.option && this.option.imageRatio) {
1603
+ ratio = this.option.imageRatio;
1604
+ }
1605
+ if (ratio <= 0) {
1606
+ ratio = 100;
1607
+ }
1608
+ imageWidth = Math.floor(imageWidth * ratio / 100);
1609
+ imageHeight = Math.floor(imageHeight * ratio / 100);
1610
+ }
1611
+ const imagePart = etree.SubElement(drawing.root, "xdr:oneCellAnchor");
1612
+ const fromPart = etree.SubElement(imagePart, "xdr:from");
1613
+ const fromCol = etree.SubElement(fromPart, "xdr:col");
1614
+ fromCol.text = (this.charToNum(this.splitRef(cell.attrib.r).col) - 1).toString();
1615
+ const fromColOff = etree.SubElement(fromPart, "xdr:colOff");
1616
+ fromColOff.text = "0";
1617
+ const fromRow = etree.SubElement(fromPart, "xdr:row");
1618
+ fromRow.text = (this.splitRef(cell.attrib.r).row - 1).toString();
1619
+ const fromRowOff = etree.SubElement(fromPart, "xdr:rowOff");
1620
+ fromRowOff.text = "0";
1621
+ const extImagePart = etree.SubElement(imagePart, "xdr:ext", { cx: `${imageWidth}`, cy: `${imageHeight}` });
1622
+ const picNode = etree.SubElement(imagePart, "xdr:pic");
1623
+ const nvPicPr = etree.SubElement(picNode, "xdr:nvPicPr");
1624
+ const cNvPr = etree.SubElement(nvPicPr, "xdr:cNvPr", { id: `${maxId}`, name: "image_" + maxId, descr: "" });
1625
+ const cNvPicPr = etree.SubElement(nvPicPr, "xdr:cNvPicPr");
1626
+ const picLocks = etree.SubElement(cNvPicPr, "a:picLocks", { noChangeAspect: "1" });
1627
+ const blipFill = etree.SubElement(picNode, "xdr:blipFill");
1628
+ const blip = etree.SubElement(blipFill, "a:blip", {
1629
+ "xmlns:r": "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
1630
+ "r:embed": "rId" + maxId
1631
+ });
1632
+ const stretch = etree.SubElement(blipFill, "a:stretch");
1633
+ const fillRect = etree.SubElement(stretch, "a:fillRect");
1634
+ const spPr = etree.SubElement(picNode, "xdr:spPr");
1635
+ const xfrm = etree.SubElement(spPr, "a:xfrm");
1636
+ const off = etree.SubElement(xfrm, "a:off", { x: "0", y: "0" });
1637
+ const ext = etree.SubElement(xfrm, "a:ext", { cx: `${imageWidth}`, cy: `${imageHeight}` });
1638
+ const prstGeom = etree.SubElement(spPr, "a:prstGeom", { "prst": "rect" });
1639
+ const avLst = etree.SubElement(prstGeom, "a:avLst");
1640
+ const clientData = etree.SubElement(imagePart, "xdr:clientData");
1641
+ return true;
1642
+ }
1643
+ cloneElement(element, deep) {
1644
+ const newElement = etree.Element(element.tag, element.attrib);
1645
+ newElement.text = element.text;
1646
+ newElement.tail = element.tail;
1647
+ if (deep !== false) {
1648
+ element.getchildren().forEach((child) => {
1649
+ newElement.append(this.cloneElement(child, deep));
1650
+ });
1651
+ }
1652
+ return newElement;
1653
+ }
1654
+ replaceChildren(parent, children) {
1655
+ parent.delSlice(0, parent.len());
1656
+ children.forEach((child) => {
1657
+ parent.append(child);
1658
+ });
1659
+ }
1660
+ getCurrentRow(row, rowsInserted) {
1661
+ return parseInt(row.attrib.r, 10) + rowsInserted;
1662
+ }
1663
+ getCurrentCell(cell, currentRow, cellsInserted) {
1664
+ const colRef = this.splitRef(cell.attrib.r).col;
1665
+ const colNum = this.charToNum(colRef);
1666
+ return this.joinRef({
1667
+ row: currentRow,
1668
+ col: this.numToChar(colNum + cellsInserted)
1669
+ });
1670
+ }
1671
+ updateRowSpan(row, cellsInserted) {
1672
+ if (cellsInserted !== 0 && row.attrib.spans) {
1673
+ const rowSpan = row.attrib.spans.split(":").map((f) => parseInt(f, 10));
1674
+ rowSpan[1] += cellsInserted;
1675
+ row.attrib.spans = rowSpan.join(":");
1676
+ }
1677
+ }
1678
+ splitRange(range) {
1679
+ const split = range.split(":");
1680
+ return {
1681
+ start: split[0],
1682
+ end: split[1]
1683
+ };
1684
+ }
1685
+ joinRange(range) {
1686
+ return range.start + ":" + range.end;
1687
+ }
1688
+ pushRight(workbook, sheet, currentCell, numCols) {
1689
+ const cellRef = this.splitRef(currentCell);
1690
+ const currentRow = cellRef.row;
1691
+ const currentCol = this.charToNum(cellRef.col);
1692
+ sheet.findall("mergeCells/mergeCell").forEach((mergeCell) => {
1693
+ const mergeRange = this.splitRange(mergeCell.attrib.ref);
1694
+ const mergeStart = this.splitRef(mergeRange.start);
1695
+ const mergeStartCol = this.charToNum(mergeStart.col);
1696
+ const mergeEnd = this.splitRef(mergeRange.end);
1697
+ const mergeEndCol = this.charToNum(mergeEnd.col);
1698
+ if (mergeStart.row === currentRow && currentCol < mergeStartCol) {
1699
+ mergeStart.col = this.numToChar(mergeStartCol + numCols);
1700
+ mergeEnd.col = this.numToChar(mergeEndCol + numCols);
1701
+ mergeCell.attrib.ref = this.joinRange({
1702
+ start: this.joinRef(mergeStart),
1703
+ end: this.joinRef(mergeEnd)
1704
+ });
1705
+ }
1706
+ });
1707
+ workbook.findall("definedNames/definedName").forEach((name) => {
1708
+ const ref = name.text;
1709
+ if (this.isRange(ref)) {
1710
+ const namedRange = this.splitRange(ref);
1711
+ const namedStart = this.splitRef(namedRange.start);
1712
+ const namedStartCol = this.charToNum(namedStart.col);
1713
+ const namedEnd = this.splitRef(namedRange.end);
1714
+ const namedEndCol = this.charToNum(namedEnd.col);
1715
+ if (namedStart.row === currentRow && currentCol < namedStartCol) {
1716
+ namedStart.col = this.numToChar(namedStartCol + numCols);
1717
+ namedEnd.col = this.numToChar(namedEndCol + numCols);
1718
+ name.text = this.joinRange({
1719
+ start: this.joinRef(namedStart),
1720
+ end: this.joinRef(namedEnd)
1721
+ });
1722
+ }
1723
+ } else {
1724
+ const namedRef = this.splitRef(ref);
1725
+ const namedCol = this.charToNum(namedRef.col);
1726
+ if (namedRef.row === currentRow && currentCol < namedCol) {
1727
+ namedRef.col = this.numToChar(namedCol + numCols);
1728
+ name.text = this.joinRef(namedRef);
1729
+ }
1730
+ }
1731
+ });
1732
+ sheet.findall("hyperlinks/hyperlink").forEach((hyperlink) => {
1733
+ const ref = this.splitRef(hyperlink.attrib.ref);
1734
+ const colNumber = this.charToNum(ref.col);
1735
+ if (colNumber > currentCol) {
1736
+ ref.col = this.numToChar(colNumber + numCols);
1737
+ hyperlink.attrib.ref = this.joinRef(ref);
1738
+ }
1739
+ });
1740
+ }
1741
+ pushDown(workbook, sheet, tables, currentRow, numRows) {
1742
+ const mergeCells = sheet.find("mergeCells");
1743
+ sheet.findall("mergeCells/mergeCell").forEach((mergeCell) => {
1744
+ const mergeRange = this.splitRange(mergeCell.attrib.ref);
1745
+ const mergeStart = this.splitRef(mergeRange.start);
1746
+ const mergeEnd = this.splitRef(mergeRange.end);
1747
+ if (mergeStart.row > currentRow) {
1748
+ mergeStart.row += numRows;
1749
+ mergeEnd.row += numRows;
1750
+ mergeCell.attrib.ref = this.joinRange({
1751
+ start: this.joinRef(mergeStart),
1752
+ end: this.joinRef(mergeEnd)
1753
+ });
1754
+ }
1755
+ if (mergeStart.row == currentRow) {
1756
+ for (let i = 1; i <= numRows; i++) {
1757
+ const newMergeCell = this.cloneElement(mergeCell);
1758
+ mergeStart.row += 1;
1759
+ mergeEnd.row += 1;
1760
+ newMergeCell.attrib.ref = this.joinRange({
1761
+ start: this.joinRef(mergeStart),
1762
+ end: this.joinRef(mergeEnd)
1763
+ });
1764
+ mergeCells.attrib.count += 1;
1765
+ mergeCells._children.push(newMergeCell);
1766
+ }
1767
+ }
1768
+ });
1769
+ tables.forEach((table) => {
1770
+ const tableRoot = table.root;
1771
+ const tableRange = this.splitRange(tableRoot.attrib.ref);
1772
+ const tableStart = this.splitRef(tableRange.start);
1773
+ const tableEnd = this.splitRef(tableRange.end);
1774
+ if (tableStart.row > currentRow) {
1775
+ tableStart.row += numRows;
1776
+ tableEnd.row += numRows;
1777
+ tableRoot.attrib.ref = this.joinRange({
1778
+ start: this.joinRef(tableStart),
1779
+ end: this.joinRef(tableEnd)
1780
+ });
1781
+ const autoFilter = tableRoot.find("autoFilter");
1782
+ if (autoFilter !== null) {
1783
+ autoFilter.attrib.ref = tableRoot.attrib.ref;
1784
+ }
1785
+ }
1786
+ });
1787
+ workbook.findall("definedNames/definedName").forEach((name) => {
1788
+ const ref = name.text;
1789
+ if (this.isRange(ref)) {
1790
+ const namedRange = this.splitRange(ref);
1791
+ const namedStart = this.splitRef(namedRange.start);
1792
+ const namedEnd = this.splitRef(namedRange.end);
1793
+ if (namedStart) {
1794
+ if (namedStart.row > currentRow) {
1795
+ namedStart.row += numRows;
1796
+ namedEnd.row += numRows;
1797
+ name.text = this.joinRange({
1798
+ start: this.joinRef(namedStart),
1799
+ end: this.joinRef(namedEnd)
1800
+ });
1801
+ }
1802
+ }
1803
+ if (this.option && this.option.pushDownPageBreakOnTableSubstitution) {
1804
+ if (this.sheet.name == name.text.split("!")[0].replace(/'/gi, "") && namedEnd) {
1805
+ if (namedEnd.row > currentRow) {
1806
+ namedEnd.row += numRows;
1807
+ name.text = this.joinRange({
1808
+ start: this.joinRef(namedStart),
1809
+ end: this.joinRef(namedEnd)
1810
+ });
1811
+ }
1812
+ }
1813
+ }
1814
+ } else {
1815
+ const namedRef = this.splitRef(ref);
1816
+ if (namedRef.row > currentRow) {
1817
+ namedRef.row += numRows;
1818
+ name.text = this.joinRef(namedRef);
1819
+ }
1820
+ }
1821
+ });
1822
+ sheet.findall("hyperlinks/hyperlink").forEach((hyperlink) => {
1823
+ const ref = this.splitRef(hyperlink.attrib.ref);
1824
+ if (ref.row > currentRow) {
1825
+ ref.row += numRows;
1826
+ hyperlink.attrib.ref = this.joinRef(ref);
1827
+ }
1828
+ });
1829
+ }
1830
+ async hideCols(sheetName, hideItemIndexes) {
1831
+ const sheet = await this.loadSheet(sheetName);
1832
+ this.sheet = sheet;
1833
+ if (Array.isArray(hideItemIndexes) && hideItemIndexes.length) {
1834
+ const cols = sheet.root.find("cols");
1835
+ if (cols) {
1836
+ hideItemIndexes.forEach((hideIndex) => {
1837
+ const colIndex = hideIndex + 1;
1838
+ const col = cols.findall("col").find((c) => {
1839
+ const min = parseInt(c.attrib.min, 10);
1840
+ const max = parseInt(c.attrib.max, 10);
1841
+ return colIndex >= min && colIndex <= max;
1842
+ });
1843
+ if (col) {
1844
+ col.attrib.hidden = "1";
1845
+ }
1846
+ });
1847
+ }
1848
+ }
1849
+ this.archive.file(sheet.filename, etree.tostring(sheet.root, { encoding: "utf-8" }));
1850
+ this._rebuild();
1851
+ return this;
1852
+ }
1853
+ getWidthCell(numCol, sheet) {
1854
+ let defaultWidth = sheet.root.find("sheetFormatPr").attrib["defaultColWidth"];
1855
+ if (!defaultWidth) {
1856
+ defaultWidth = "11.42578125";
1857
+ }
1858
+ let finalWidth = defaultWidth;
1859
+ sheet.root.findall("cols/col").forEach((col) => {
1860
+ if (numCol >= col.attrib["min"] && numCol <= col.attrib["max"]) {
1861
+ if (col.attrib["width"] != void 0) {
1862
+ finalWidth = col.attrib["width"];
1863
+ }
1864
+ }
1865
+ });
1866
+ return Number.parseFloat(finalWidth);
1867
+ }
1868
+ getWidthMergeCell(mergeCell, sheet) {
1869
+ let mergeWidth = 0;
1870
+ const mergeRange = this.splitRange(mergeCell.attrib.ref);
1871
+ const mergeStartCol = this.charToNum(this.splitRef(mergeRange.start).col);
1872
+ const mergeEndCol = this.charToNum(this.splitRef(mergeRange.end).col);
1873
+ for (let i = mergeStartCol; i < mergeEndCol + 1; i++) {
1874
+ mergeWidth += this.getWidthCell(i, sheet);
1875
+ }
1876
+ return mergeWidth;
1877
+ }
1878
+ getHeightCell(numRow, sheet) {
1879
+ let finalHeight = sheet.root.find("sheetFormatPr").attrib["defaultRowHeight"];
1880
+ sheet.root.findall("sheetData/row").forEach((row) => {
1881
+ if (numRow == row.attrib["r"]) {
1882
+ if (row.attrib["ht"] != void 0) {
1883
+ finalHeight = row.attrib["ht"];
1884
+ }
1885
+ }
1886
+ });
1887
+ return Number.parseFloat(finalHeight);
1888
+ }
1889
+ getHeightMergeCell(mergeCell, sheet) {
1890
+ let mergeHeight = 0;
1891
+ const mergeRange = this.splitRange(mergeCell.attrib.ref);
1892
+ const mergeStartRow = this.splitRef(mergeRange.start).row;
1893
+ const mergeEndRow = this.splitRef(mergeRange.end).row;
1894
+ for (let i = mergeStartRow; i < mergeEndRow + 1; i++) {
1895
+ mergeHeight += this.getHeightCell(i, sheet);
1896
+ }
1897
+ return mergeHeight;
1898
+ }
1899
+ getNbRowOfMergeCell(mergeCell) {
1900
+ const mergeRange = this.splitRange(mergeCell.attrib.ref);
1901
+ const mergeStartRow = this.splitRef(mergeRange.start).row;
1902
+ const mergeEndRow = this.splitRef(mergeRange.end).row;
1903
+ return mergeEndRow - mergeStartRow + 1;
1904
+ }
1905
+ pixelsToEMUs(pixels) {
1906
+ return Math.round(pixels * 914400 / 96);
1907
+ }
1908
+ columnWidthToEMUs(width) {
1909
+ return this.pixelsToEMUs(width * 7.625579987895905);
1910
+ }
1911
+ rowHeightToEMUs(height) {
1912
+ return Math.round(height / 72 * 914400);
1913
+ }
1914
+ findMaxFileId(fileNameRegex, idRegex) {
1915
+ const files = this.archive.file(fileNameRegex);
1916
+ const maxId = files.reduce((p, c) => {
1917
+ const num = parseInt(idRegex.exec(c.name)[1]);
1918
+ if (p == null) {
1919
+ return num;
1920
+ }
1921
+ return p > num ? p : num;
1922
+ }, 0);
1923
+ return maxId + 1;
1924
+ }
1925
+ cellInMergeCells(cell, mergeCell) {
1926
+ const cellCol = this.charToNum(this.splitRef(cell.attrib.r).col);
1927
+ const cellRow = this.splitRef(cell.attrib.r).row;
1928
+ const mergeRange = this.splitRange(mergeCell.attrib.ref);
1929
+ const mergeStartCol = this.charToNum(this.splitRef(mergeRange.start).col);
1930
+ const mergeEndCol = this.charToNum(this.splitRef(mergeRange.end).col);
1931
+ const mergeStartRow = this.splitRef(mergeRange.start).row;
1932
+ const mergeEndRow = this.splitRef(mergeRange.end).row;
1933
+ if (cellCol >= mergeStartCol && cellCol <= mergeEndCol) {
1934
+ if (cellRow >= mergeStartRow && cellRow <= mergeEndRow) {
1935
+ return true;
1936
+ }
1937
+ }
1938
+ return false;
1939
+ }
1940
+ imageToBuffer(imageObj) {
1941
+ function checkImage(buffer) {
1942
+ try {
1943
+ sizeOf(buffer);
1944
+ return buffer;
1945
+ } catch (error) {
1946
+ throw new TypeError("imageObj cannot be parse as a buffer image");
1947
+ }
1948
+ }
1949
+ if (!imageObj) {
1950
+ throw new TypeError("imageObj cannot be null");
1951
+ }
1952
+ if (imageObj instanceof Buffer) {
1953
+ return checkImage(imageObj);
1954
+ }
1955
+ if (typeof imageObj === "string" || imageObj instanceof String) {
1956
+ imageObj = imageObj.toString();
1957
+ const imagePath = this.option && this.option.imageRootPath ? this.option.imageRootPath + "/" + imageObj : imageObj;
1958
+ if (fs.existsSync(imagePath)) {
1959
+ return checkImage(Buffer.from(fs.readFileSync(imagePath, { encoding: "base64" }), "base64"));
1960
+ }
1961
+ try {
1962
+ return checkImage(Buffer.from(imageObj, "base64"));
1963
+ } catch (error) {
1964
+ throw new TypeError("imageObj cannot be parse as a buffer");
1965
+ }
1966
+ }
1967
+ throw new TypeError("imageObj type is not supported : " + typeof imageObj);
1968
+ }
1969
+ findMaxId(element, tag, attr, idRegex) {
1970
+ let maxId = 0;
1971
+ element.findall(tag).forEach((el) => {
1972
+ const match = idRegex.exec(el.attrib[attr]);
1973
+ if (match == null) {
1974
+ throw new Error("Can not find the id!");
1975
+ }
1976
+ const cid = parseInt(match[1]);
1977
+ if (cid > maxId) {
1978
+ maxId = cid;
1979
+ }
1980
+ });
1981
+ return ++maxId;
1982
+ }
1983
+ };
1984
+ var generateXlsxTemplate = async function(data, values, options) {
1985
+ const w = await Workbook.parse(data, options);
1986
+ await w.substituteAll(values);
1987
+ return w.generate(options);
1988
+ };
1989
+
1990
+ // src/helper.ts
1991
+ import exceljs from "exceljs";
1992
+ import { Stream } from "stream";
1993
+ var isPureNumber = /^[0-9]+$/;
1994
+ var isPureUppercase = /^[A-Z]+$/;
1995
+ var exprSingle = `expr`;
1996
+ var exprArr = `exprArr`;
1997
+ var exprIndex = `index`;
1998
+ var defaultKey = `!!`;
1999
+ var numberKey = `!!number`;
2000
+ var codeKey = `!!codeKey`;
2001
+ var funcCommand = "fn:";
2002
+ var RuleToken = /* @__PURE__ */ ((RuleToken2) => {
2003
+ RuleToken2["AliasToken"] = "alias";
2004
+ RuleToken2["CellToken"] = "cell";
2005
+ RuleToken2["MergeCellToken"] = "mergeCell";
2006
+ RuleToken2["RowCellToken"] = "rowCell";
2007
+ RuleToken2["UseAliasToken"] = "@";
2008
+ RuleToken2["RangeToken"] = "-";
2009
+ RuleToken2["PosToken"] = ":";
2010
+ RuleToken2["FunctionPatternToken"] = "<?>";
2011
+ RuleToken2["AnyToken"] = "?";
2012
+ RuleToken2["VarPatternToken"] = "${?}";
2013
+ RuleToken2["UndefinedToken"] = "";
2014
+ RuleToken2["EqualToken"] = "=";
2015
+ RuleToken2["ArgPosToken"] = ",";
2016
+ RuleToken2["LparenToken"] = "(";
2017
+ RuleToken2["RparenToken"] = ")";
2018
+ RuleToken2["DotGetToken"] = ".";
2019
+ RuleToken2["CompileGenToken"] = "compile:GenCell";
2020
+ RuleToken2["CompileMacroToken"] = "compile:Macro";
2021
+ return RuleToken2;
2022
+ })(RuleToken || {});
2023
+ var RuleMapOptions = class _RuleMapOptions {
2024
+ constructor(m) {
2025
+ // rule configure area
2026
+ this.startLine = 1;
2027
+ this.startColumn = 1;
2028
+ if (m === void 0) {
2029
+ this.ruleKeyMap = defaultRuleTokenMap;
2030
+ } else {
2031
+ this.ruleKeyMap = m;
2032
+ }
2033
+ }
2034
+ static withAllSheets(w, excludes) {
2035
+ const compileSheets = [];
2036
+ const options = new _RuleMapOptions();
2037
+ if (excludes === void 0) {
2038
+ excludes = [];
2039
+ }
2040
+ if (w.worksheets.length > 0 && excludes.length > 0) {
2041
+ for (const [index, sheet] of w.worksheets.entries()) {
2042
+ if (excludes.includes(index.toString()) || excludes.includes(sheet.name)) {
2043
+ continue;
2044
+ }
2045
+ if (sheet.name.endsWith(".json")) {
2046
+ continue;
2047
+ }
2048
+ compileSheets.push(sheet.name);
2049
+ }
2050
+ }
2051
+ options.compileSheets = compileSheets;
2052
+ return options;
2053
+ }
2054
+ parseDefault(worksheet) {
2055
+ this.ruleKeyMap = mergeOption(this.ruleKeyMap, defaultRuleTokenMap);
2056
+ if (this.startLine === void 0) {
2057
+ this.startLine = 1;
2058
+ }
2059
+ if (this.endLine === void 0) {
2060
+ this.endLine = worksheet.rowCount;
2061
+ }
2062
+ if (this.startColumn === void 0) {
2063
+ this.startColumn = 1;
2064
+ }
2065
+ if (this.endColumn === void 0) {
2066
+ this.endColumn = worksheet.columnCount;
2067
+ }
2068
+ return this;
2069
+ }
2070
+ addRuleMap(key, value) {
2071
+ this.ruleKeyMap.set(key, value);
2072
+ return this;
2073
+ }
2074
+ setStartRow(start) {
2075
+ this.startLine = start;
2076
+ return this;
2077
+ }
2078
+ setStartColumn(start) {
2079
+ this.startColumn = start;
2080
+ return this;
2081
+ }
2082
+ setEndRow(end) {
2083
+ this.endLine = end;
2084
+ return this;
2085
+ }
2086
+ setEndColumn(end) {
2087
+ this.endColumn = end;
2088
+ return this;
2089
+ }
2090
+ parseToken(value) {
2091
+ if (value === "") {
2092
+ return "" /* UndefinedToken */;
2093
+ }
2094
+ for (const [token, alias] of this.ruleKeyMap.entries()) {
2095
+ if (alias === value) {
2096
+ return token;
2097
+ }
2098
+ }
2099
+ return "" /* UndefinedToken */;
2100
+ }
2101
+ getContextMap() {
2102
+ const ctx = /* @__PURE__ */ new Map();
2103
+ for (const [token, expr] of this.ruleKeyMap.entries()) {
2104
+ if (!isRuleToken(token)) {
2105
+ const value = [{
2106
+ express: expr,
2107
+ key: expr,
2108
+ tokens: [token],
2109
+ value: token.toString()
2110
+ }];
2111
+ ctx.set(token, value);
2112
+ }
2113
+ }
2114
+ return ctx;
2115
+ }
2116
+ getCompileCheckHandlers() {
2117
+ if (this.compileCheckers !== void 0 && this.compileCheckers.length > 0) {
2118
+ return this.compileCheckers;
2119
+ }
2120
+ return void 0;
2121
+ }
2122
+ };
2123
+ var CompileContext = class _CompileContext extends RuleMapOptions {
2124
+ constructor(m) {
2125
+ super(m);
2126
+ this.aliasMap = /* @__PURE__ */ new Map();
2127
+ }
2128
+ static create(r) {
2129
+ const ctx = new _CompileContext(r.ruleKeyMap);
2130
+ Object.assign(ctx, { ...r });
2131
+ return ctx.init();
2132
+ }
2133
+ init() {
2134
+ if (this.ruleKeyMap === void 0) {
2135
+ this.ruleKeyMap = defaultRuleTokenMap;
2136
+ }
2137
+ return this;
2138
+ }
2139
+ loadAlias(m) {
2140
+ if (m.size <= 0 || !m.has("alias" /* AliasToken */)) {
2141
+ return this;
2142
+ }
2143
+ const values = m.get("alias" /* AliasToken */);
2144
+ for (const vs of values) {
2145
+ if (typeof vs.value === "string") {
2146
+ this.aliasMap.set(vs.key, vs.value);
2147
+ }
2148
+ }
2149
+ return this;
2150
+ }
2151
+ /**
2152
+ * 设置别名缓存
2153
+ */
2154
+ setAlias(key, value) {
2155
+ this.aliasMap.set(key, value);
2156
+ }
2157
+ /**
2158
+ * 获取别名缓存值
2159
+ */
2160
+ getAlias(key) {
2161
+ return this.aliasMap.get(key);
2162
+ }
2163
+ /**
2164
+ * 检查别名是否存在
2165
+ */
2166
+ hasAlias(key) {
2167
+ return this.aliasMap.has(key);
2168
+ }
2169
+ filterSheet(sheetName) {
2170
+ if (sheetName !== "" && this.compileSheets !== void 0 && this.compileSheets.length > 0) {
2171
+ return this.compileSheets.includes(sheetName);
2172
+ }
2173
+ return false;
2174
+ }
2175
+ };
2176
+ var defaultRuleTokenMap = /* @__PURE__ */ new Map([
2177
+ ["alias" /* AliasToken */, "alias" /* AliasToken */.toString()],
2178
+ ["?" /* AnyToken */, "?" /* AnyToken */.toString()],
2179
+ ["cell" /* CellToken */, "cell" /* CellToken */.toString()],
2180
+ ["rowCell" /* RowCellToken */, "rowCell" /* RowCellToken */.toString()],
2181
+ ["mergeCell" /* MergeCellToken */, "mergeCell" /* MergeCellToken */.toString()],
2182
+ ["@" /* UseAliasToken */, "@" /* UseAliasToken */.toString()],
2183
+ [":" /* PosToken */, ":" /* PosToken */.toString()],
2184
+ ["-" /* RangeToken */, "-" /* RangeToken */.toString()],
2185
+ ["<?>" /* FunctionPatternToken */, "<?>" /* FunctionPatternToken */.toString()],
2186
+ ["${?}" /* VarPatternToken */, "${?}" /* VarPatternToken */.toString()],
2187
+ ["=" /* EqualToken */, "=" /* EqualToken */.toString()],
2188
+ ["," /* ArgPosToken */, "," /* ArgPosToken */.toString()],
2189
+ ["(" /* LparenToken */, "(" /* LparenToken */.toString()],
2190
+ [")" /* RparenToken */, ")" /* RparenToken */.toString()],
2191
+ ["." /* DotGetToken */, "." /* DotGetToken */.toString()],
2192
+ ["compile:Macro" /* CompileMacroToken */, "compile:Macro" /* CompileMacroToken */.toString()],
2193
+ ["compile:GenCell" /* CompileGenToken */, "compile:GenCell" /* CompileGenToken */.toString()]
2194
+ ]);
2195
+ var DefaultPlaceholderCellValue = class {
2196
+ constructor(p, merge) {
2197
+ this.placeholder = p;
2198
+ this.mergeCellPlaceholder = merge === void 0 ? "" : merge;
2199
+ }
2200
+ mergeCell(values) {
2201
+ if (this.mergeCellPlaceholder !== void 0) {
2202
+ return this.mergeCellPlaceholder.replace("?", values.join(","));
2203
+ }
2204
+ return "";
2205
+ }
2206
+ toString() {
2207
+ return this.placeholder;
2208
+ }
2209
+ };
2210
+ var _getCells = (thisArg) => {
2211
+ let cells = [];
2212
+ for (let j = thisArg.minColumn; j <= thisArg.maxColumn; j += thisArg.stepColumn) {
2213
+ for (let i = thisArg.minRow; i <= thisArg.maxRow; i += thisArg.stepRow) {
2214
+ cells.push({
2215
+ Row: i,
2216
+ Column: j
2217
+ });
2218
+ }
2219
+ }
2220
+ return cells;
2221
+ };
2222
+ var TokenParserManger = class _TokenParserManger {
2223
+ // T=xxx
2224
+ static aliasParse(ctx, token, value) {
2225
+ if (token !== "alias" /* AliasToken */) {
2226
+ return {
2227
+ ok: false
2228
+ };
2229
+ }
2230
+ const parser = getTokenParser("=" /* EqualToken */);
2231
+ const { values, expr, ok } = parser.handler(ctx, "=" /* EqualToken */, value);
2232
+ if (!ok) {
2233
+ return {
2234
+ ok: false
2235
+ };
2236
+ }
2237
+ if (typeof expr.value !== "string" || expr.value === "") {
2238
+ return {
2239
+ ok: false,
2240
+ error: new Error(`alias express right value cannot be a empty value.`)
2241
+ };
2242
+ }
2243
+ return {
2244
+ ok: true,
2245
+ expr: {
2246
+ express: value,
2247
+ key: expr.key,
2248
+ // alias key
2249
+ value: expr.value,
2250
+ // alias value
2251
+ tokens: [token, "=" /* EqualToken */]
2252
+ // express tokens
2253
+ },
2254
+ values
2255
+ };
2256
+ }
2257
+ // x=xx
2258
+ static equalParse(ctx, token, value) {
2259
+ if (token !== "=" /* EqualToken */) {
2260
+ return {
2261
+ ok: false
2262
+ };
2263
+ }
2264
+ const equalToken = _TokenParserManger.getTokenByCtx(ctx, "=" /* EqualToken */);
2265
+ const offset = equalToken.length;
2266
+ const index = value.indexOf(equalToken);
2267
+ if (index < 0) {
2268
+ return {
2269
+ ok: false
2270
+ };
2271
+ }
2272
+ const len = value.length;
2273
+ const key = value.substring(0, index);
2274
+ const rightValue = value.substring(index + offset, len);
2275
+ if (rightValue === "") {
2276
+ return {
2277
+ ok: false,
2278
+ error: new Error(`equal express right value cannot be a empty value.`)
2279
+ };
2280
+ }
2281
+ const expr = {
2282
+ key,
2283
+ value: rightValue,
2284
+ express: value,
2285
+ tokens: [token]
2286
+ };
2287
+ return {
2288
+ ok: true,
2289
+ values: [key, rightValue],
2290
+ expr
2291
+ };
2292
+ }
2293
+ //cell| X:Y=${?}
2294
+ static cellParse(ctx, token, value) {
2295
+ if (token !== "cell" /* CellToken */) {
2296
+ return {
2297
+ ok: false
2298
+ };
2299
+ }
2300
+ const equalToken = _TokenParserManger.getTokenByCtx(ctx, "=" /* EqualToken */);
2301
+ const eqOffset = equalToken.length;
2302
+ const posToken = _TokenParserManger.getTokenByCtx(ctx, ":" /* PosToken */);
2303
+ const eqIndex = value.indexOf(equalToken);
2304
+ const posIndex = value.indexOf(posToken);
2305
+ if (eqIndex < 0 || posIndex < 0) {
2306
+ return {
2307
+ ok: false
2308
+ };
2309
+ }
2310
+ const parser = getTokenParser(":" /* PosToken */);
2311
+ const varParser = getTokenParser("${?}" /* VarPatternToken */);
2312
+ const posValue = value.substring(0, eqIndex);
2313
+ const varValue = value.substring(eqIndex + eqOffset);
2314
+ const posReply = parser.handler(ctx, ":" /* PosToken */, posValue);
2315
+ if (!posReply.ok) {
2316
+ return {
2317
+ ok: false,
2318
+ ...posReply
2319
+ };
2320
+ }
2321
+ const varReply = varParser.handler(ctx, "${?}" /* VarPatternToken */, varValue);
2322
+ if (!varReply.ok) {
2323
+ return {
2324
+ ok: false,
2325
+ ...varReply
2326
+ };
2327
+ }
2328
+ const expr = {
2329
+ ...varReply.expr
2330
+ };
2331
+ expr.express = value;
2332
+ expr.cells = posReply.expr.cells;
2333
+ expr.value = varReply.expr.value;
2334
+ expr.ref = varReply.expr.ref;
2335
+ expr.tokens = [token, "=" /* EqualToken */, ...posReply.expr.tokens, ...varReply.expr.tokens];
2336
+ return {
2337
+ ok: true,
2338
+ expr,
2339
+ values: [posReply.values, varReply.values]
2340
+ };
2341
+ }
2342
+ static useAliasParse(ctx, token, value) {
2343
+ if (token !== "@" /* UseAliasToken */) {
2344
+ return {
2345
+ ok: false
2346
+ };
2347
+ }
2348
+ const useAliasToken = _TokenParserManger.getTokenByCtx(ctx, "@" /* UseAliasToken */);
2349
+ const offset = useAliasToken.length;
2350
+ const has = offset !== 0 && value.indexOf(useAliasToken) >= 0;
2351
+ if (!has) {
2352
+ return {
2353
+ ok: false
2354
+ };
2355
+ }
2356
+ const endTokens = ["@" /* UseAliasToken */, "(" /* LparenToken */, "," /* ArgPosToken */, "." /* DotGetToken */];
2357
+ const values = _TokenParserManger.scanToken(value, useAliasToken, _TokenParserManger.toList(ctx, endTokens));
2358
+ if (values === void 0 || values.length <= 0) {
2359
+ return {
2360
+ ok: false
2361
+ };
2362
+ }
2363
+ const keys = [];
2364
+ const tokens = [];
2365
+ const expr = {
2366
+ express: value,
2367
+ tokens,
2368
+ value: keys,
2369
+ ref: []
2370
+ };
2371
+ for (const v of values) {
2372
+ tokens.push(token);
2373
+ keys.push(v.token);
2374
+ expr.ref.push(v.value);
2375
+ }
2376
+ expr.value = keys;
2377
+ expr.tokens = tokens;
2378
+ return {
2379
+ expr,
2380
+ ok: true,
2381
+ values
2382
+ };
2383
+ }
2384
+ static rangeParse(ctx, token, value) {
2385
+ if (token !== "-" /* RangeToken */) {
2386
+ return {
2387
+ ok: false
2388
+ };
2389
+ }
2390
+ const rangeToken = _TokenParserManger.getTokenByCtx(ctx, "-" /* RangeToken */);
2391
+ const offset = rangeToken.length;
2392
+ const index = value.indexOf(rangeToken);
2393
+ if (index < 0 || offset <= 0) {
2394
+ return {
2395
+ ok: false
2396
+ };
2397
+ }
2398
+ let setup = 1;
2399
+ let startNumber = NaN;
2400
+ let endNumber = NaN;
2401
+ let startPos = value.substring(0, index).trim();
2402
+ let endPos = value.substring(index + offset).trim();
2403
+ const argPosToken = _TokenParserManger.getTokenByCtx(ctx, "," /* ArgPosToken */);
2404
+ const endSetupIndex = endPos.indexOf(argPosToken);
2405
+ if (endSetupIndex > 0) {
2406
+ setup = Number.parseInt(endPos.substring(endSetupIndex).trim(), 10);
2407
+ endPos = endPos.substring(0, endSetupIndex).trim();
2408
+ }
2409
+ if (isNaN(setup)) {
2410
+ return {
2411
+ ok: false,
2412
+ error: new Error(`rangeToken parse setup NaN, ${value}`)
2413
+ };
2414
+ }
2415
+ endNumber = _TokenParserManger.parsePosNumber(endPos);
2416
+ startNumber = _TokenParserManger.parsePosNumber(startPos);
2417
+ if (isNaN(startNumber) || isNaN(endNumber)) {
2418
+ return {
2419
+ ok: false,
2420
+ error: new Error(`rangeToken parse start,end has NaN, ${value}`)
2421
+ };
2422
+ }
2423
+ const expr = {
2424
+ express: value,
2425
+ tokens: [token],
2426
+ value: [startNumber, endNumber, setup]
2427
+ };
2428
+ return {
2429
+ expr,
2430
+ ok: true,
2431
+ values: [startNumber, endNumber, setup]
2432
+ };
2433
+ }
2434
+ static posParse(ctx, token, value) {
2435
+ if (token !== ":" /* PosToken */) {
2436
+ return {
2437
+ ok: false
2438
+ };
2439
+ }
2440
+ const posToken = _TokenParserManger.getTokenByCtx(ctx, ":" /* PosToken */);
2441
+ const offset = posToken.length;
2442
+ const index = value.indexOf(posToken);
2443
+ const len = value.length;
2444
+ const column = value.substring(0, index).trim();
2445
+ const row = value.substring(index + offset, len).trim();
2446
+ const rangeToken = _TokenParserManger.getTokenByCtx(ctx, "-" /* RangeToken */);
2447
+ const columnRange = column.indexOf(rangeToken);
2448
+ const rowRange = row.indexOf(rangeToken);
2449
+ if (rowRange > 0 || columnRange > 0) {
2450
+ return _TokenParserManger.parseRangeValue(ctx, { rowRange, columnRange, row, column, token, express: value });
2451
+ }
2452
+ const cell = {
2453
+ Row: Number.parseInt(row, 10),
2454
+ Column: columnLetterToNumber(column)
2455
+ };
2456
+ const expr = {
2457
+ value: cell,
2458
+ cells: [cell],
2459
+ express: value,
2460
+ tokens: [token]
2461
+ };
2462
+ return {
2463
+ ok: true,
2464
+ values: [row, column],
2465
+ expr
2466
+ };
2467
+ }
2468
+ // value input: A-AQ:13-15=<sum(#,[compile:Macro(exprArr,[F],[13,15],!codeKey)],compile:Marco(index),0)>
2469
+ // output: {
2470
+ // A:13 => sum(#,[ codeKey(F:13.value),codeKey(F:14.value),codeKey(F:15.value)],1,0),
2471
+ // B:13 => sum(#,[ codeKey(F:13.value),codeKey(F:14.value),codeKey(F:15.value)],2,0),
2472
+ // C:13 => sum(#,[ codeKey(F:13.value),codeKey(F:14.value),codeKey(F:15.value)],3,0),
2473
+ // ....,
2474
+ // A:14 => sum(#,[ codeKey(F:13.value),codeKey(F:14.value),codeKey(F:15.value)],1,0),
2475
+ // B:14 => sum(#,[ codeKey(F:13.value),codeKey(F:14.value),codeKey(F:15.value)],2,0),
2476
+ // C:14 => sum(#,[ codeKey(F:13.value),codeKey(F:14.value),codeKey(F:15.value)],3,0),
2477
+ // }
2478
+ static mergeCellParse(ctx, token, value) {
2479
+ if (token !== "mergeCell" /* MergeCellToken */ && token !== "rowCell" /* RowCellToken */) {
2480
+ return { ok: false };
2481
+ }
2482
+ const equalToken = _TokenParserManger.getTokenByCtx(ctx, "=" /* EqualToken */);
2483
+ const index = value.indexOf(equalToken);
2484
+ const offset = equalToken.length;
2485
+ if (index <= 0) return { ok: false, error: new Error(`merge cell config syntax error: ${value}`) };
2486
+ const rangeStr = value.substring(0, index).trim();
2487
+ const exprStr = value.substring(index + offset);
2488
+ const posParser = getTokenParser(":" /* PosToken */);
2489
+ const posReply = posParser.handler(ctx, ":" /* PosToken */, rangeStr);
2490
+ const functionToken = getTokenParser("<?>" /* FunctionPatternToken */);
2491
+ if (!posReply.ok) return { ok: false, ...posReply };
2492
+ const macroGenToken = _TokenParserManger.getTokenByCtx(ctx, "compile:GenCell" /* CompileGenToken */);
2493
+ const expr = {
2494
+ express: value,
2495
+ value: exprStr,
2496
+ // The template expression
2497
+ posExpr: posReply.expr,
2498
+ tokens: [token, ...posReply.expr.tokens]
2499
+ };
2500
+ if (exprStr.startsWith(macroGenToken)) {
2501
+ const argsSplitToken = _TokenParserManger.getTokenByCtx(ctx, "," /* ArgPosToken */);
2502
+ const args = _TokenParserManger.split(exprStr, argsSplitToken, [`(`, `)`]);
2503
+ const macro = _TokenParserManger.filterMacro(args);
2504
+ const aliasTokens = _TokenParserManger.extractUseAliasTokens(ctx, args);
2505
+ if (aliasTokens !== void 0 && aliasTokens.length > 0) {
2506
+ expr.tokens.push(...aliasTokens);
2507
+ }
2508
+ if (macro !== void 0 && macro.tokens.length > 0) {
2509
+ expr.macro = macro;
2510
+ expr.tokens.push(...macro.tokens);
2511
+ }
2512
+ } else {
2513
+ const exprReply = functionToken.handler(ctx, "<?>" /* FunctionPatternToken */, exprStr);
2514
+ if (exprReply.error !== void 0 && exprReply.error instanceof Error) {
2515
+ return {
2516
+ ok: false,
2517
+ ...exprReply
2518
+ };
2519
+ }
2520
+ if (exprReply.ok && exprReply.expr !== void 0) {
2521
+ expr.funcExpr = exprReply.expr;
2522
+ expr.tokens.push(...exprReply.expr.tokens);
2523
+ }
2524
+ }
2525
+ return {
2526
+ ok: true,
2527
+ expr,
2528
+ values: [rangeStr, exprStr]
2529
+ };
2530
+ }
2531
+ // G-AQ:12=compile:GenCell(compile:Macro(expr,F,12),'.',compile:Marco(index))
2532
+ static rowCellParse(ctx, token, value) {
2533
+ if (token !== "rowCell" /* RowCellToken */) {
2534
+ return { ok: false };
2535
+ }
2536
+ return _TokenParserManger.mergeCellParse(ctx, token, value);
2537
+ }
2538
+ // $functionName($arg0:string,$arg1:string[],$arg2:string|number,$arg3:string|number)
2539
+ // eg: func(A,[xx1,xx2],xxx3), sum(#,[F,12,13],1,0)
2540
+ // $functionName not in compile:Macro,compile:GenCell
2541
+ // extract => {func:$functionName, arguments:[$arg0,$arg1,$arg2,$argN...]}
2542
+ // output: {func:"sum",arguments:["A",["F","12","13"],"1","0"]}
2543
+ static functionPatternParse(ctx, token, value) {
2544
+ if (token !== "<?>" /* FunctionPatternToken */) {
2545
+ return { ok: false };
2546
+ }
2547
+ const wordToken = _TokenParserManger.getTokenByCtx(ctx, "?" /* AnyToken */);
2548
+ const funcToken = _TokenParserManger.getTokenByCtx(ctx, "<?>" /* FunctionPatternToken */);
2549
+ const splitIndex = funcToken.indexOf(wordToken);
2550
+ const splitOffset = wordToken.length;
2551
+ const funcStartToken = funcToken.substring(0, splitIndex);
2552
+ const funcEndToken = funcToken.substring(splitIndex + splitOffset);
2553
+ const rparenToken = _TokenParserManger.getTokenByCtx(ctx, ")" /* RparenToken */);
2554
+ const lparenToken = _TokenParserManger.getTokenByCtx(ctx, "(" /* LparenToken */);
2555
+ const argsSplitToken = _TokenParserManger.getTokenByCtx(ctx, "," /* ArgPosToken */);
2556
+ if (value.startsWith(funcStartToken) && value.endsWith(funcEndToken)) {
2557
+ const content = value.substring(1, value.length - 1);
2558
+ const lparen = content.indexOf(lparenToken);
2559
+ const rparen = content.lastIndexOf(rparenToken);
2560
+ if (lparen > 0 && rparen > lparen) {
2561
+ const funcName = content.substring(0, lparen);
2562
+ const argsStr = content.substring(lparen + lparenToken.length, rparen);
2563
+ const args = _TokenParserManger.split(argsStr, argsSplitToken, [`[`, `]`]);
2564
+ const macro = _TokenParserManger.filterMacro(args);
2565
+ const tokens = [token];
2566
+ const expr = {
2567
+ express: value,
2568
+ func: funcName,
2569
+ value: args,
2570
+ // arguments array
2571
+ tokens
2572
+ };
2573
+ const alias = _TokenParserManger.extractUseAliasTokens(ctx, args);
2574
+ if (alias !== void 0 && alias.length > 0) {
2575
+ expr.tokens.push(...alias);
2576
+ }
2577
+ if (macro !== void 0 && macro.tokens.length > 0) {
2578
+ expr.macro = macro;
2579
+ expr.tokens.push(...macro.tokens);
2580
+ }
2581
+ return {
2582
+ ok: true,
2583
+ expr,
2584
+ values: [funcName, args]
2585
+ };
2586
+ }
2587
+ }
2588
+ return {
2589
+ ok: false,
2590
+ error: new Error(`function express systax error`)
2591
+ };
2592
+ }
2593
+ static varPatternParse(ctx, token, value) {
2594
+ if (token !== "${?}" /* VarPatternToken */) {
2595
+ return { ok: false };
2596
+ }
2597
+ const wordToken = _TokenParserManger.getTokenByCtx(ctx, "?" /* AnyToken */);
2598
+ const varToken = _TokenParserManger.getTokenByCtx(ctx, "${?}" /* VarPatternToken */);
2599
+ const index = varToken.indexOf(wordToken);
2600
+ const workTokenOffset = wordToken.length;
2601
+ const startToken = varToken.substring(0, index);
2602
+ const endToken = varToken.substring(workTokenOffset + index);
2603
+ if (!value.startsWith(startToken) || !value.endsWith(endToken)) {
2604
+ return {
2605
+ ok: false,
2606
+ error: new Error(`variable expression syntax error,\${ or } flag is miss`)
2607
+ };
2608
+ }
2609
+ const innerContent = value.substring(startToken.length, value.length - endToken.length);
2610
+ if (innerContent === "") {
2611
+ return {
2612
+ ok: false,
2613
+ error: new Error("variable expression syntax error, variable name is empty")
2614
+ };
2615
+ }
2616
+ const expr = {
2617
+ express: value,
2618
+ value: innerContent,
2619
+ tokens: [token]
2620
+ };
2621
+ const aliasToken = _TokenParserManger.getTokenByCtx(ctx, "@" /* UseAliasToken */);
2622
+ if (innerContent.indexOf(aliasToken) >= 0) {
2623
+ const parser = getTokenParser("@" /* UseAliasToken */);
2624
+ const aliasReply = parser.handler(ctx, "@" /* UseAliasToken */, innerContent);
2625
+ if (aliasReply.ok) {
2626
+ expr.ref = aliasReply.expr.ref;
2627
+ expr.alias = aliasReply.values;
2628
+ expr.tokens.push(...aliasReply.expr.tokens);
2629
+ }
2630
+ }
2631
+ return {
2632
+ expr,
2633
+ ok: true,
2634
+ values: [innerContent]
2635
+ };
2636
+ }
2637
+ // compile:GenCell(expr1,expr2,...,) => {G:13=>`${expr1}${expr2}..`,G:14=>`${expr1}${expr2}..`,G:15=>`${expr1}${expr2}..`,...}
2638
+ // compile:Macro($exprType,$X,$Y,$formater)
2639
+ // $exprType: enums [ expr:(single value), exprArr:(array value) ]
2640
+ // $X: column index value, number|string or number[]|string[]
2641
+ // $Y: row index value, number or number[]
2642
+ // $formater: enums [ codeKey(a function for format string),number(a function for string to number) ]
2643
+ // compile:Macro(exprArr,[X1,X2],[Y1,Y2],!codeKey) =>
2644
+ // codeKey(X1:Y1.value),codeKey(X1:Y2.value),codeKey(X2:Y1.value),codeKey(X2:Y2.value)
2645
+ // compile:Macro(exprArr,[X1],[Y1,Y2],!codeKey) => codeKey(X1:Y1.value),codeKey(X1:Y2.value)
2646
+ // compile:Marco(index,!number) => number(i),number(i+1),number(i+2) ,i=1
2647
+ static compileExprExtract(value) {
2648
+ const results = [];
2649
+ const lp = "(" /* LparenToken */.toString();
2650
+ const args = "," /* ArgPosToken */.toString();
2651
+ const values = value.split(lp);
2652
+ for (const v of values) {
2653
+ let items = [];
2654
+ if (v.indexOf(args) >= 0) {
2655
+ items = v.split(args);
2656
+ } else {
2657
+ items.push(v);
2658
+ }
2659
+ for (const it of items) {
2660
+ if (it === "compile:Macro" /* CompileMacroToken */.toString() || it.startsWith("compile:Macro" /* CompileMacroToken */) || it.endsWith("compile:Macro" /* CompileMacroToken */)) {
2661
+ results.push("compile:Macro" /* CompileMacroToken */);
2662
+ } else if (it === "compile:GenCell" /* CompileGenToken */.toString() || it.startsWith("compile:GenCell" /* CompileGenToken */) || it.endsWith("compile:GenCell" /* CompileGenToken */)) {
2663
+ results.push("compile:GenCell" /* CompileGenToken */);
2664
+ }
2665
+ }
2666
+ }
2667
+ return results;
2668
+ }
2669
+ static getTokenByCtx(ctx, token) {
2670
+ if (ctx.size <= 0 || !ctx.has(token)) {
2671
+ return token.toString();
2672
+ }
2673
+ const values = ctx.get(token);
2674
+ if (values.length <= 0 || values[0].key === "") {
2675
+ return token.toString();
2676
+ }
2677
+ return values[0].key;
2678
+ }
2679
+ static scanToken(value, startToken, endTokens) {
2680
+ let token = "";
2681
+ let data = "";
2682
+ let end = false;
2683
+ let start = false;
2684
+ const items = [];
2685
+ const offset = [startToken, ...endTokens].sort((a, b) => a.length - b.length)[0].length;
2686
+ const size = value.length;
2687
+ for (let i = 0; i < size; i += offset) {
2688
+ let leftToken;
2689
+ if (value[i] === startToken) {
2690
+ start = true;
2691
+ if (token !== "") {
2692
+ items.push({
2693
+ token,
2694
+ value: ""
2695
+ });
2696
+ }
2697
+ token = startToken;
2698
+ } else {
2699
+ start = token === startToken;
2700
+ leftToken = `${token}${value[i]}`;
2701
+ }
2702
+ let subfix = endTokens.filter((s) => s === leftToken);
2703
+ end = endTokens.includes(value[i]) || subfix.length > 0;
2704
+ if (subfix.length > 0) {
2705
+ token = leftToken;
2706
+ data = "";
2707
+ }
2708
+ if (start && end) {
2709
+ continue;
2710
+ }
2711
+ if (!end) {
2712
+ token = `${token}${value[i]}`;
2713
+ data = `${data}${value[i]}`;
2714
+ }
2715
+ if (end || i + offset >= size) {
2716
+ if (data !== "") {
2717
+ items.push({
2718
+ token,
2719
+ value: data
2720
+ });
2721
+ }
2722
+ token = "";
2723
+ data = "";
2724
+ end = false;
2725
+ }
2726
+ }
2727
+ return items;
2728
+ }
2729
+ static split(argsStr, argsSplitToken, ignoreTokenRange) {
2730
+ let value = "";
2731
+ let depth = 0;
2732
+ const items = [];
2733
+ const splitLen = argsSplitToken.length;
2734
+ const startLen = ignoreTokenRange[0].length;
2735
+ const endLen = ignoreTokenRange[1].length;
2736
+ const startToken = ignoreTokenRange[0];
2737
+ const endToken = ignoreTokenRange[1];
2738
+ const isToggleMode = startToken === endToken;
2739
+ for (let i = 0; i < argsStr.length; ) {
2740
+ const substr = argsStr.substring(i);
2741
+ if (depth > 0 && substr.startsWith(endToken)) {
2742
+ value += endToken;
2743
+ i += endLen;
2744
+ depth = isToggleMode ? 0 : depth - 1;
2745
+ continue;
2746
+ }
2747
+ if (substr.startsWith(startToken)) {
2748
+ if (!isToggleMode || depth === 0) {
2749
+ value += startToken;
2750
+ i += startLen;
2751
+ depth++;
2752
+ continue;
2753
+ }
2754
+ }
2755
+ if (depth === 0 && substr.startsWith(argsSplitToken)) {
2756
+ items.push(value);
2757
+ value = "";
2758
+ i += splitLen;
2759
+ continue;
2760
+ }
2761
+ value += argsStr[i];
2762
+ i++;
2763
+ }
2764
+ if (value !== "") {
2765
+ items.push(value);
2766
+ }
2767
+ return items;
2768
+ }
2769
+ static filterMacro(values) {
2770
+ const filter = {
2771
+ tokens: [],
2772
+ express: []
2773
+ };
2774
+ for (const expr of values) {
2775
+ let items = _TokenParserManger.compileExprExtract(expr);
2776
+ if (items === void 0 || items.length <= 0) {
2777
+ continue;
2778
+ }
2779
+ filter.express.push(expr);
2780
+ filter.tokens.push(...items);
2781
+ }
2782
+ return filter.tokens.push() <= 0 ? void 0 : filter;
2783
+ }
2784
+ static extractUseAliasTokens(ctx, args) {
2785
+ const tokens = [];
2786
+ const useAliasToken = _TokenParserManger.getTokenByCtx(ctx, "@" /* UseAliasToken */);
2787
+ args.forEach((v) => v.startsWith(useAliasToken) && tokens.push("@" /* UseAliasToken */));
2788
+ return tokens;
2789
+ }
2790
+ static toList(ctx, endTokens) {
2791
+ const items = [];
2792
+ for (const token of endTokens) {
2793
+ items.push(_TokenParserManger.getTokenByCtx(ctx, token));
2794
+ }
2795
+ return items;
2796
+ }
2797
+ static parseRangeValue(ctx, options) {
2798
+ let rowReply;
2799
+ let columnReply;
2800
+ const rangeCell = {
2801
+ stepRow: 1,
2802
+ stepColumn: 1,
2803
+ minColumn: 0,
2804
+ minRow: 0,
2805
+ maxRow: 0,
2806
+ maxColumn: 0,
2807
+ getCells: function() {
2808
+ return _getCells(this);
2809
+ }
2810
+ };
2811
+ const { rowRange, row, column, columnRange, express, token } = options;
2812
+ const rangeParse = getTokenParser("-" /* RangeToken */);
2813
+ if (rowRange > 0) {
2814
+ columnReply = rangeParse.handler(ctx, "-" /* RangeToken */, row);
2815
+ } else {
2816
+ const rowValue = Number.parseInt(row, 10);
2817
+ rangeCell.maxRow = rowValue;
2818
+ rangeCell.minRow = rowValue;
2819
+ }
2820
+ if (columnRange > 0) {
2821
+ rowReply = rangeParse.handler(ctx, "-" /* RangeToken */, column);
2822
+ } else {
2823
+ const columnValue = columnLetterToNumber(column);
2824
+ rangeCell.maxColumn = columnValue;
2825
+ rangeCell.minColumn = columnValue;
2826
+ }
2827
+ if (columnReply !== void 0) {
2828
+ if (!columnReply.ok || columnReply.values === void 0) {
2829
+ return columnReply;
2830
+ }
2831
+ const values = columnReply.values;
2832
+ let min = values[0];
2833
+ let max = values[1];
2834
+ let setup = values[2] ?? 1;
2835
+ rangeCell.minRow = min;
2836
+ rangeCell.maxRow = max;
2837
+ rangeCell.stepRow = setup;
2838
+ }
2839
+ if (rowReply !== void 0) {
2840
+ if (!rowReply.ok || rowReply.values === void 0) {
2841
+ return rowReply;
2842
+ }
2843
+ const values = rowReply.values;
2844
+ let min = values[0];
2845
+ let max = values[1];
2846
+ let setup = values[2] ?? 1;
2847
+ rangeCell.minColumn = min;
2848
+ rangeCell.maxColumn = max;
2849
+ rangeCell.stepColumn = setup;
2850
+ }
2851
+ const expr = {
2852
+ express,
2853
+ tokens: [token],
2854
+ // express tokens
2855
+ value: rangeCell
2856
+ // alias value
2857
+ };
2858
+ return {
2859
+ ok: true,
2860
+ expr,
2861
+ values: rangeCell
2862
+ };
2863
+ }
2864
+ static parsePosNumber(value) {
2865
+ let num = NaN;
2866
+ if (isPureNumber.test(value)) {
2867
+ num = Number.parseInt(value, 10);
2868
+ } else if (isPureUppercase.test(value)) {
2869
+ num = columnLetterToNumber(value);
2870
+ }
2871
+ return !isNaN(num) && num <= 0 ? NaN : num;
2872
+ }
2873
+ };
2874
+ var defaultRuleTokenParserMap = /* @__PURE__ */ new Map([
2875
+ ["alias" /* AliasToken */, TokenParserManger.aliasParse],
2876
+ ["cell" /* CellToken */, TokenParserManger.cellParse],
2877
+ ["=" /* EqualToken */, TokenParserManger.equalParse],
2878
+ ["mergeCell" /* MergeCellToken */, TokenParserManger.mergeCellParse],
2879
+ ["rowCell" /* RowCellToken */, TokenParserManger.rowCellParse],
2880
+ ["@" /* UseAliasToken */, TokenParserManger.useAliasParse],
2881
+ ["-" /* RangeToken */, TokenParserManger.rangeParse],
2882
+ [":" /* PosToken */, TokenParserManger.posParse],
2883
+ ["${?}" /* VarPatternToken */, TokenParserManger.varPatternParse],
2884
+ ["<?>" /* FunctionPatternToken */, TokenParserManger.functionPatternParse]
2885
+ ]);
2886
+ var macroTokens = ["compile:GenCell" /* CompileGenToken */, "compile:Macro" /* CompileMacroToken */];
2887
+ function columnLetterToNumber(letter) {
2888
+ let num = 0;
2889
+ for (let i = 0; i < letter.length; i++) {
2890
+ num = num * 26 + (letter.charCodeAt(i) - 64);
2891
+ }
2892
+ return num;
2893
+ }
2894
+ function columnNumberToLetter(num) {
2895
+ if (num <= 0) {
2896
+ return "";
2897
+ }
2898
+ let letter = "";
2899
+ while (num > 0) {
2900
+ let remainder = (num - 1) % 26;
2901
+ letter = String.fromCharCode(65 + remainder) + letter;
2902
+ num = Math.floor((num - 1) / 26);
2903
+ }
2904
+ return letter;
2905
+ }
2906
+ function isBase64(str) {
2907
+ if (str.length < 20) return false;
2908
+ if (str.includes("\\") || str.includes(" ")) return false;
2909
+ if (str.indexOf("./") >= 0 || str.startsWith("file://") || str.startsWith("/") || str.startsWith(".")) {
2910
+ return false;
2911
+ }
2912
+ const data = str.replace(/^data:.*?;base64,/, "");
2913
+ const cleanedStr = data.replace(/[\r\n]/g, "");
2914
+ try {
2915
+ return Buffer.from(cleanedStr, "base64").toString("utf-8") !== "";
2916
+ } catch (e) {
2917
+ return false;
2918
+ }
2919
+ }
2920
+ function base64ToArrayBuffer(base64) {
2921
+ const data = base64.replace(/^data:.*?;base64,/, "");
2922
+ const binaryString = atob(data);
2923
+ const bytes = new Uint8Array(binaryString.length);
2924
+ for (let i = 0; i < binaryString.length; i++) {
2925
+ bytes[i] = binaryString.charCodeAt(i);
2926
+ }
2927
+ return bytes.buffer;
2928
+ }
2929
+ function getMergeRange(ws, row, col) {
2930
+ const merges = ws.model.merges;
2931
+ for (const mergeStr of merges) {
2932
+ const parts = mergeStr.split(":");
2933
+ const tl = ws.getCell(parts[0]);
2934
+ const br = ws.getCell(parts[1]);
2935
+ const tlRow = Number(tl.row);
2936
+ const tlCol = Number(tl.col);
2937
+ const brRow = Number(br.row);
2938
+ const brCol = Number(br.col);
2939
+ if (row >= tlRow && row <= brRow && col >= tlCol && col <= brCol) {
2940
+ return {
2941
+ top: tlRow,
2942
+ left: tlCol,
2943
+ bottom: brRow,
2944
+ right: brCol
2945
+ };
2946
+ }
2947
+ }
2948
+ return null;
2949
+ }
2950
+ var resolveCompileMacroGen = (ctx, expr, currentCellIndex) => {
2951
+ let parts = [];
2952
+ let join2 = ".";
2953
+ const m = ctx.getContextMap();
2954
+ const aliasToken = TokenParserManger.getTokenByCtx(m, "@" /* UseAliasToken */);
2955
+ const genToken = TokenParserManger.getTokenByCtx(m, "compile:GenCell" /* CompileGenToken */);
2956
+ const endTokens = ["compile:GenCell" /* CompileGenToken */, "(" /* LparenToken */, "," /* ArgPosToken */, ")" /* RparenToken */];
2957
+ const values = TokenParserManger.scanToken(expr, genToken, TokenParserManger.toList(m, endTokens));
2958
+ for (const [_, item] of values.entries()) {
2959
+ if (item.value === void 0 && item.value !== "") {
2960
+ continue;
2961
+ }
2962
+ if (!item.token.startsWith(aliasToken) && item.value !== exprIndex) {
2963
+ parts.push(item.value);
2964
+ } else {
2965
+ parts.push(resolveAliasExpr(ctx, item.value, currentCellIndex));
2966
+ }
2967
+ }
2968
+ return parts.join(join2);
2969
+ };
2970
+ var getExprEnd = function(macroExpr, matchIndex, rparenToken) {
2971
+ return macroExpr.indexOf(rparenToken, matchIndex);
2972
+ };
2973
+ var macroFormatters = [numberKey, codeKey];
2974
+ var extractMacro = function(expr, options) {
2975
+ let end = NaN;
2976
+ const offset = options.startToken.length;
2977
+ const startIndex = expr.indexOf(options.startToken);
2978
+ const endIndex = expr.indexOf(options.endToken);
2979
+ const argValues = expr.substring(startIndex + offset, endIndex);
2980
+ const values = argValues.split(options.argToken);
2981
+ const extracResult = { type: values[0], rowParam: [], columnParam: void 0 };
2982
+ if (values.length > 1) {
2983
+ extracResult.columnParam = columnLetterToNumber(values[1]);
2984
+ }
2985
+ if (macroFormatters.includes(values[values.length - 1])) {
2986
+ end = values.length - 1;
2987
+ extracResult.formatter = values[end];
2988
+ }
2989
+ if (!isNaN(end) && values.length > 2) {
2990
+ extracResult.rowParam = values.slice(2, end).map((x) => Number.parseInt(x, 10));
2991
+ } else if (values.length > 2) {
2992
+ extracResult.rowParam = values.slice(2, values.length).map((x) => Number.parseInt(x, 10));
2993
+ }
2994
+ if (extracResult.rowParam !== void 0 && extracResult.rowParam instanceof Array && extracResult.rowParam.length === 1) {
2995
+ extracResult.rowParam = extracResult.rowParam[0];
2996
+ }
2997
+ return extracResult;
2998
+ };
2999
+ var __codeKey = (str) => {
3000
+ let vs = str.trim().replace("-", "_").replace("/", "_").trim();
3001
+ for (; vs.indexOf("__") >= 0; ) {
3002
+ vs = vs.replace("__", "_");
3003
+ }
3004
+ for (; vs.indexOf(" ") >= 0; ) {
3005
+ vs = vs.replace(" ", "");
3006
+ }
3007
+ return vs.trim().toUpperCase();
3008
+ };
3009
+ var __numberKey = (str) => {
3010
+ return Number.parseInt(str, 10).toString();
3011
+ };
3012
+ var macroFormatter = /* @__PURE__ */ new Map([
3013
+ [codeKey, __codeKey],
3014
+ [numberKey, __numberKey],
3015
+ [defaultKey, (v) => v]
3016
+ ]);
3017
+ var execMacroFormat = function(value, formatter) {
3018
+ if (!macroFormatter.has(formatter)) {
3019
+ return value;
3020
+ }
3021
+ return macroFormatter.get(formatter)(value);
3022
+ };
3023
+ var toCellRow = (rowVals, setup) => {
3024
+ if (setup === void 0) {
3025
+ setup = 1;
3026
+ }
3027
+ if (rowVals.length == 2) {
3028
+ const values = [];
3029
+ for (let start = rowVals[0]; start <= rowVals[1]; start += setup) {
3030
+ values.push(start);
3031
+ }
3032
+ return values;
3033
+ }
3034
+ return rowVals;
3035
+ };
3036
+ var toCellColumn = (columnVals, setup) => {
3037
+ return toCellRow(columnVals, setup);
3038
+ };
3039
+ var resolveCompileMacroExpr = (ctx, macroExpr, macroTokens2, currentCellIndex, totalCells) => {
3040
+ if (macroTokens2 === void 0 || macroTokens2.length <= 0) {
3041
+ return macroExpr;
3042
+ }
3043
+ const sheet = ctx.sheet;
3044
+ if (sheet === void 0) {
3045
+ throw new Error(`miss context worksheet`);
3046
+ }
3047
+ const m = ctx.getContextMap();
3048
+ const argToken = TokenParserManger.getTokenByCtx(m, "," /* ArgPosToken */);
3049
+ const rparenToken = TokenParserManger.getTokenByCtx(m, ")" /* RparenToken */);
3050
+ const lparenToken = TokenParserManger.getTokenByCtx(m, "(" /* LparenToken */);
3051
+ const genToken = TokenParserManger.getTokenByCtx(m, "compile:GenCell" /* CompileGenToken */);
3052
+ const maroToken = TokenParserManger.getTokenByCtx(m, "compile:Macro" /* CompileMacroToken */);
3053
+ const tokenMap = /* @__PURE__ */ new Map();
3054
+ for (const [index, token] of macroTokens2.entries()) {
3055
+ let items = [];
3056
+ if (tokenMap.has(token)) {
3057
+ items = tokenMap.get(token);
3058
+ }
3059
+ items.push(index);
3060
+ tokenMap.set(token, items);
3061
+ }
3062
+ const resolveArray = (param) => {
3063
+ if (param instanceof Array) {
3064
+ return param;
3065
+ }
3066
+ return [param];
3067
+ };
3068
+ if (tokenMap.has("compile:Macro" /* CompileMacroToken */)) {
3069
+ let offset = 0;
3070
+ let exprValue = macroExpr;
3071
+ const times = tokenMap.get("compile:Macro" /* CompileMacroToken */).length;
3072
+ for (let i = times; i > 0; i--) {
3073
+ const matchIndex = exprValue.indexOf(maroToken, offset);
3074
+ if (matchIndex < 0) {
3075
+ break;
3076
+ }
3077
+ offset = getExprEnd(exprValue, matchIndex, rparenToken);
3078
+ const macroCurrent = exprValue.substring(matchIndex, offset + rparenToken.length);
3079
+ const opts = { startToken: lparenToken, endToken: rparenToken, argToken };
3080
+ let { type, columnParam, rowParam, formatter } = extractMacro(macroCurrent, opts);
3081
+ let rowVals;
3082
+ let columnVals;
3083
+ const parts = [];
3084
+ if (columnParam !== void 0 && rowParam !== void 0) {
3085
+ rowVals = resolveArray(rowParam);
3086
+ columnVals = resolveArray(columnParam);
3087
+ const rowItems = toCellRow(rowVals);
3088
+ const columnItems = toCellColumn(columnVals);
3089
+ rowItems.forEach((r) => {
3090
+ columnItems.forEach((c) => {
3091
+ const cellValue = sheet.findCell(r, c);
3092
+ if (cellValue === void 0 || cellValue.value === null) {
3093
+ return;
3094
+ }
3095
+ const value = cellValue.value;
3096
+ parts.push(execMacroFormat(value.toString(), formatter));
3097
+ });
3098
+ });
3099
+ }
3100
+ if (type === exprArr) {
3101
+ macroExpr = macroExpr.replace(macroCurrent, parts.join(","));
3102
+ } else if (type === exprSingle) {
3103
+ macroExpr = macroExpr.replace(macroCurrent, parts[0]);
3104
+ } else if (type === exprIndex) {
3105
+ const indexValue = currentCellIndex + 1;
3106
+ macroExpr = macroExpr.replace(macroCurrent, indexValue.toString());
3107
+ }
3108
+ }
3109
+ }
3110
+ if (tokenMap.has("compile:GenCell" /* CompileGenToken */)) {
3111
+ let exprValue = macroExpr;
3112
+ const times = tokenMap.get("compile:GenCell" /* CompileGenToken */).length;
3113
+ for (let i = times; i > 0; i--) {
3114
+ const matchIndex = exprValue.indexOf(genToken);
3115
+ if (matchIndex < 0) {
3116
+ break;
3117
+ }
3118
+ const offset = getExprEnd(exprValue, matchIndex, rparenToken);
3119
+ const macroCurrent = exprValue.substring(matchIndex, offset + rparenToken.length);
3120
+ exprValue = resolveCompileMacroGen(ctx, macroCurrent, currentCellIndex);
3121
+ }
3122
+ macroExpr = exprValue;
3123
+ }
3124
+ return macroExpr;
3125
+ };
3126
+ var loadWorkbook = async function(data) {
3127
+ const w = new exceljs.Workbook();
3128
+ if (typeof data === "string") {
3129
+ if (!isBase64(data)) {
3130
+ await w.xlsx.readFile(data);
3131
+ } else {
3132
+ await w.xlsx.load(base64ToArrayBuffer(data));
3133
+ }
3134
+ } else if (data instanceof Stream) {
3135
+ await w.xlsx.read(data);
3136
+ } else if (data instanceof ArrayBuffer) {
3137
+ await w.xlsx.load(data);
3138
+ } else if (data instanceof Buffer) {
3139
+ await w.xlsx.load(data);
3140
+ } else {
3141
+ throw new Error(`unSupport buffer type ${typeof data}`);
3142
+ }
3143
+ return w;
3144
+ };
3145
+ var scanCellSetPlaceholder = async function(excelBuffer, cell, placeholder) {
3146
+ const workbook = await loadWorkbook(excelBuffer);
3147
+ const worksheet = workbook.getWorksheet(cell.Sheet);
3148
+ if (!worksheet) return void 0;
3149
+ workSheetSetPlaceholder(worksheet, cell, placeholder);
3150
+ return workbook.xlsx.writeBuffer();
3151
+ };
3152
+ var workSheetSetPlaceholder = function(worksheet, cell, placeholder) {
3153
+ const colNum = columnLetterToNumber(cell.Row);
3154
+ const rowNum = cell.Column;
3155
+ const targetCell = worksheet.getCell(rowNum, colNum);
3156
+ if (targetCell.isMerged) {
3157
+ const range = getMergeRange(worksheet, rowNum, colNum);
3158
+ if (range) {
3159
+ const leftCol = colNum - 1;
3160
+ const values = [];
3161
+ if (leftCol > 0) {
3162
+ for (let r = range.top; r <= range.bottom; r++) {
3163
+ const val = worksheet.getCell(r, leftCol).value;
3164
+ if (val !== null && val !== void 0 && val !== "") {
3165
+ values.push(String(val));
3166
+ }
3167
+ }
3168
+ }
3169
+ if (values.length === 0) {
3170
+ targetCell.value = placeholder.toString();
3171
+ } else {
3172
+ targetCell.value = placeholder.mergeCell(values);
3173
+ }
3174
+ return worksheet;
3175
+ }
3176
+ }
3177
+ const currentValue = targetCell.value;
3178
+ if (currentValue === null || currentValue === void 0 || currentValue === "") {
3179
+ targetCell.value = placeholder.toString();
3180
+ }
3181
+ return worksheet;
3182
+ };
3183
+ var compileCellTokens = ["cell" /* CellToken */, "mergeCell" /* MergeCellToken */, "rowCell" /* RowCellToken */];
3184
+ var ruleTokens = ["alias" /* AliasToken */, "cell" /* CellToken */, "mergeCell" /* MergeCellToken */, "rowCell" /* RowCellToken */];
3185
+ var isRuleToken = function(t) {
3186
+ return ruleTokens.includes(t);
3187
+ };
3188
+ var mergeOption = function(ruleKeyMap, defaultRuleTokenMap2) {
3189
+ for (const [key, value] of defaultRuleTokenMap2.entries()) {
3190
+ if (!ruleKeyMap.has(key)) {
3191
+ ruleKeyMap.set(key, value);
3192
+ }
3193
+ }
3194
+ return ruleKeyMap;
3195
+ };
3196
+ var getTokenParser = function(token) {
3197
+ if (!defaultRuleTokenParserMap.has(token)) {
3198
+ return {
3199
+ exists: false
3200
+ };
3201
+ }
3202
+ return {
3203
+ exists: true,
3204
+ handler: defaultRuleTokenParserMap.get(token)
3205
+ };
3206
+ };
3207
+ var registerTokenParser = function(token, h) {
3208
+ if (defaultRuleTokenParserMap.has(token)) {
3209
+ return false;
3210
+ }
3211
+ defaultRuleTokenParserMap.set(token, h);
3212
+ return true;
3213
+ };
3214
+ var registerTokenParserMust = function(token, h) {
3215
+ defaultRuleTokenParserMap.set(token, h);
3216
+ };
3217
+ var scanWorkSheetRules = function(worksheet, options) {
3218
+ const result = { rules: options.getContextMap() };
3219
+ for (let r = options.startLine; r <= options.endLine; r++) {
3220
+ let emptyValue = false;
3221
+ let ruleToken = "" /* UndefinedToken */;
3222
+ for (let c = options.startColumn; c <= options.endColumn; c++) {
3223
+ const cell = worksheet.findCell(r, c);
3224
+ if (cell === void 0 || cell.value === void 0 || cell.value === null) {
3225
+ continue;
3226
+ }
3227
+ const cellValue = cell.value;
3228
+ const value = cellValue.toString();
3229
+ let isStartCell = c === options.startColumn;
3230
+ if (emptyValue && ruleToken === "" /* UndefinedToken */) {
3231
+ isStartCell = true;
3232
+ }
3233
+ if (value === "" && isStartCell) {
3234
+ emptyValue = true;
3235
+ continue;
3236
+ }
3237
+ if (isStartCell) {
3238
+ ruleToken = options.parseToken(value);
3239
+ continue;
3240
+ } else {
3241
+ if (!isRuleToken(ruleToken)) {
3242
+ break;
3243
+ }
3244
+ emptyValue = false;
3245
+ }
3246
+ const { handler, exists } = getTokenParser(ruleToken);
3247
+ if (!exists) {
3248
+ continue;
3249
+ }
3250
+ let values = [];
3251
+ if (result.rules.has(ruleToken)) {
3252
+ values = result.rules.get(ruleToken);
3253
+ }
3254
+ const { expr, ok } = handler(result.rules, ruleToken, value);
3255
+ if (ok && expr !== void 0) {
3256
+ values.push(expr);
3257
+ }
3258
+ result.rules.set(ruleToken, values);
3259
+ }
3260
+ }
3261
+ return result;
3262
+ };
3263
+ var parseWorkSheetRules = function(worksheet, options) {
3264
+ const result = { rules: /* @__PURE__ */ new Map() };
3265
+ if (worksheet === void 0 || worksheet === null) {
3266
+ return result;
3267
+ }
3268
+ if (options === void 0) {
3269
+ options = new RuleMapOptions();
3270
+ }
3271
+ return scanWorkSheetRules(worksheet, options.parseDefault(worksheet));
3272
+ };
3273
+ var compileCheck = function(iv, ctx) {
3274
+ if (iv.rules.size <= 0) {
3275
+ return void 0;
3276
+ }
3277
+ const errs = [];
3278
+ const values = iv.rules.get("alias" /* AliasToken */);
3279
+ if (values !== void 0 && values.length > 0) {
3280
+ const set = /* @__PURE__ */ new Set();
3281
+ for (const [idx, value] of values.entries()) {
3282
+ if (idx === 0) {
3283
+ set.add(value.key);
3284
+ continue;
3285
+ }
3286
+ if (set.has(value.key)) {
3287
+ errs.push(Error(`Duplicate alias(${value.key},${value.express}) configuration`));
3288
+ }
3289
+ }
3290
+ }
3291
+ const handlers = ctx.getCompileCheckHandlers();
3292
+ if (handlers !== void 0 && handlers.length > 0) {
3293
+ for (const h of handlers) {
3294
+ let err = h(iv, ctx);
3295
+ if (err !== void 0 && err.length > 0) {
3296
+ errs.push(...err);
3297
+ }
3298
+ }
3299
+ }
3300
+ if (errs.length > 0) {
3301
+ return errs;
3302
+ }
3303
+ return void 0;
3304
+ };
3305
+ var getMacroTokens = function(expr) {
3306
+ const tokens = [];
3307
+ for (const token of expr.tokens) {
3308
+ if (macroTokens.includes(token)) {
3309
+ tokens.push(token);
3310
+ }
3311
+ }
3312
+ return tokens;
3313
+ };
3314
+ var toRowCells = function(cells) {
3315
+ const indexes = [];
3316
+ const rows = [];
3317
+ const rowMap = /* @__PURE__ */ new Map();
3318
+ for (const cell of cells) {
3319
+ let cells2 = [];
3320
+ if (rowMap.has(cell.Row)) {
3321
+ cells2 = rowMap.get(cell.Row);
3322
+ } else {
3323
+ indexes.push(cell.Row);
3324
+ }
3325
+ cells2.push(cell);
3326
+ rowMap.set(cell.Row, cells2);
3327
+ }
3328
+ indexes.sort((a, b) => a - b);
3329
+ for (const row of indexes) {
3330
+ const values = rowMap.get(row);
3331
+ rows.push(values);
3332
+ }
3333
+ return rows;
3334
+ };
3335
+ var resolveFunctionExpr = (ctx, templateValue, expr) => {
3336
+ const anyToken = defaultRuleTokenMap.get("?" /* AnyToken */);
3337
+ const funToken = defaultRuleTokenMap.get("<?>" /* FunctionPatternToken */);
3338
+ const functionTokens = expr.tokens.filter((s) => s === "<?>" /* FunctionPatternToken */);
3339
+ if (functionTokens === void 0 || functionTokens.length <= 0) {
3340
+ return templateValue;
3341
+ }
3342
+ const [start, end] = funToken.split(anyToken);
3343
+ for (let times = functionTokens.length; times > 0; times--) {
3344
+ const index = templateValue.indexOf(start);
3345
+ const offset = templateValue.indexOf(end);
3346
+ if (offset > 0 && index >= 0) {
3347
+ templateValue = templateValue.replace(start, funcCommand).replace(end, "");
3348
+ }
3349
+ }
3350
+ return templateValue;
3351
+ };
3352
+ var searchIndexOf = (str, substr, position) => {
3353
+ let index = NaN;
3354
+ for (let sub of substr) {
3355
+ if (position === void 0 || position === null) {
3356
+ index = str.indexOf(sub);
3357
+ } else {
3358
+ index = str.indexOf(sub, position);
3359
+ }
3360
+ if (!isNaN(index) && index >= 0) {
3361
+ return index;
3362
+ }
3363
+ }
3364
+ return -1;
3365
+ };
3366
+ var resolveAliasExpr = (ctx, templateValue, index) => {
3367
+ const expr = ctx.currentExpr;
3368
+ if (expr === void 0) {
3369
+ throw new Error(`miss context expr value`);
3370
+ }
3371
+ let compileValue = templateValue;
3372
+ const aliasToken = defaultRuleTokenMap.get("@" /* UseAliasToken */);
3373
+ let aliasTokens = expr.tokens.filter((s) => s === "@" /* UseAliasToken */);
3374
+ if (aliasTokens.length <= 0) {
3375
+ const num = templateValue.split(aliasToken).length - 1;
3376
+ if (num > 0) {
3377
+ aliasTokens = new Array(num).fill(aliasToken);
3378
+ }
3379
+ }
3380
+ if (aliasTokens !== void 0 && aliasTokens.length > 0) {
3381
+ for (let i = 0; i < aliasTokens.length; ++i) {
3382
+ const token = aliasToken;
3383
+ const start = compileValue.indexOf(token);
3384
+ if (start < 0) {
3385
+ break;
3386
+ }
3387
+ const offset = aliasTokens[i].length;
3388
+ let end = searchIndexOf(compileValue, [",", ".", ")", "]"], start);
3389
+ if (end < 0) {
3390
+ end = compileValue.length;
3391
+ }
3392
+ const sv = compileValue.substring(start + offset, end);
3393
+ const pl = `${token}${sv}`;
3394
+ const value = ctx.getAlias(sv);
3395
+ if (value !== void 0) {
3396
+ if (compileValue === pl) {
3397
+ compileValue = value;
3398
+ } else {
3399
+ compileValue = compileValue.replace(`${pl}`, value);
3400
+ }
3401
+ }
3402
+ }
3403
+ }
3404
+ return compileValue;
3405
+ };
3406
+ var resolveValueExpr = (ctx, templateValue) => {
3407
+ const expr = ctx.currentExpr;
3408
+ if (expr === void 0 || expr.tokens.length <= 0) {
3409
+ return templateValue;
3410
+ }
3411
+ const m = ctx.getContextMap();
3412
+ const token = TokenParserManger.getTokenByCtx(m, "${?}" /* VarPatternToken */);
3413
+ const anyToken = TokenParserManger.getTokenByCtx(m, "?" /* AnyToken */);
3414
+ const [start, end] = token.split(anyToken);
3415
+ if (!templateValue.startsWith(start)) {
3416
+ templateValue = `${start}${templateValue}`;
3417
+ }
3418
+ if (!templateValue.endsWith(end)) {
3419
+ templateValue = `${templateValue}${end}`;
3420
+ }
3421
+ return templateValue;
3422
+ };
3423
+ var compileRowCells = function(ctx, expr, cellPoints, rowIndex, errs) {
3424
+ if (ctx.sheet === void 0) {
3425
+ errs.push(new Error(`ctx miss worksheet`));
3426
+ return;
3427
+ }
3428
+ ctx.currentExpr = expr;
3429
+ cellPoints.forEach((cellPoint, index) => {
3430
+ const r = cellPoint.Row;
3431
+ const sheet = ctx.sheet;
3432
+ const c = cellPoint.Column;
3433
+ const cell = sheet.findCell(r, c);
3434
+ if (cell === void 0 || cell.value !== void 0 && cell.value !== null && cell.value !== "") {
3435
+ return;
3436
+ }
3437
+ let templateValue = String(expr.value);
3438
+ const macroTokens2 = getMacroTokens(expr);
3439
+ templateValue = resolveFunctionExpr(ctx, templateValue, expr);
3440
+ templateValue = resolveCompileMacroExpr(ctx, templateValue, macroTokens2, index, cellPoints.length);
3441
+ templateValue = resolveAliasExpr(ctx, templateValue, index);
3442
+ cell.value = resolveValueExpr(ctx, templateValue);
3443
+ });
3444
+ };
3445
+ var generateWorkSheetCellsPlaceholder = function(ctx, expr, sheet) {
3446
+ const errs = [];
3447
+ const posExpr = expr.posExpr;
3448
+ let cellsItems = expr.cells;
3449
+ if ((cellsItems === void 0 || cellsItems.length <= 0) && posExpr !== void 0 && posExpr.value !== void 0) {
3450
+ const r = posExpr.value;
3451
+ if (r !== void 0) {
3452
+ cellsItems = r.getCells();
3453
+ }
3454
+ }
3455
+ if (!cellsItems || cellsItems.length === 0) {
3456
+ return void 0;
3457
+ }
3458
+ ctx.sheet = sheet;
3459
+ const cells = cellsItems;
3460
+ toRowCells(cells).forEach((cellPoints, index) => compileRowCells(ctx, expr, cellPoints, index, errs));
3461
+ return errs.length > 0 ? errs : void 0;
3462
+ };
3463
+ var hasGeneratorToken = function(tokens) {
3464
+ for (const t of tokens) {
3465
+ if (compileCellTokens.includes(t)) {
3466
+ return true;
3467
+ }
3468
+ }
3469
+ return false;
3470
+ };
3471
+ var compileWorkSheetPlaceholder = function(ctx, sheet, result) {
3472
+ if (ctx.compileSheets !== void 0 && ctx.compileSheets.length > 0 && !ctx.compileSheets.includes(sheet.name)) {
3473
+ return void 0;
3474
+ }
3475
+ const errs = [];
3476
+ for (const [token, express] of result.rules.entries()) {
3477
+ if (!isRuleToken(token)) {
3478
+ continue;
3479
+ }
3480
+ for (const expr of express) {
3481
+ if (expr.tokens.length <= 0 || !hasGeneratorToken(expr.tokens)) {
3482
+ continue;
3483
+ }
3484
+ let err = generateWorkSheetCellsPlaceholder(ctx, expr, sheet);
3485
+ if (err !== void 0 && err.length > 0) {
3486
+ errs.push(...err);
3487
+ }
3488
+ }
3489
+ }
3490
+ if (errs.length > 0) {
3491
+ return errs;
3492
+ }
3493
+ return void 0;
3494
+ };
3495
+ var compile = async function(data, ruleSheetName, options) {
3496
+ const workbook = await loadWorkbook(data);
3497
+ const sheet = workbook.getWorksheet(ruleSheetName);
3498
+ if (sheet === void 0) {
3499
+ return {
3500
+ workbook,
3501
+ errs: [new Error(`compile error, ${ruleSheetName} not exists!`)]
3502
+ };
3503
+ }
3504
+ if (workbook.worksheets === void 0) {
3505
+ return {
3506
+ workbook,
3507
+ errs: [new Error(`worksheet, ${ruleSheetName} not exists!`)]
3508
+ };
3509
+ }
3510
+ if (options === void 0) {
3511
+ const excludes = [ruleSheetName];
3512
+ options = RuleMapOptions.withAllSheets(workbook, excludes);
3513
+ }
3514
+ const result = parseWorkSheetRules(sheet, options);
3515
+ const errs = compileCheck(result, options);
3516
+ if (errs !== void 0) {
3517
+ return {
3518
+ errs,
3519
+ workbook,
3520
+ configure: result
3521
+ };
3522
+ }
3523
+ const compileErrs = [];
3524
+ const ctx = CompileContext.create(options).loadAlias(result.rules);
3525
+ for (const [i, w] of workbook.worksheets.entries()) {
3526
+ if (w.name === ruleSheetName || i === ruleSheetName || !ctx.filterSheet(w.name)) {
3527
+ continue;
3528
+ }
3529
+ let err = compileWorkSheetPlaceholder(ctx, w, result);
3530
+ if (err !== void 0 && err.length > 0) {
3531
+ compileErrs.push(...err);
3532
+ }
3533
+ }
3534
+ if (compileErrs.length > 0) {
3535
+ return {
3536
+ workbook,
3537
+ configure: result,
3538
+ errs: compileErrs
3539
+ };
3540
+ }
3541
+ return {
3542
+ workbook,
3543
+ configure: result
3544
+ };
3545
+ };
3546
+ var compileWorkSheet = async function(data, sheetName, options) {
3547
+ const reply = await compile(data, sheetName, options);
3548
+ if (reply.errs !== void 0 && reply.errs.length > 0) {
3549
+ return reply.errs;
3550
+ }
3551
+ return reply.workbook.xlsx;
3552
+ };
3553
+ var fetchAlias = (m) => {
3554
+ let sv;
3555
+ const alias = /* @__PURE__ */ new Map();
3556
+ if (!(m instanceof Map) && m.rules !== void 0) {
3557
+ sv = m.rules;
3558
+ } else if (m instanceof Map) {
3559
+ if (m.size <= 0 || !m.has("alias" /* AliasToken */)) {
3560
+ return alias;
3561
+ }
3562
+ sv = m;
3563
+ } else {
3564
+ return alias;
3565
+ }
3566
+ const values = sv.get("alias" /* AliasToken */);
3567
+ for (const vs of values) {
3568
+ if (typeof vs.value === "string") {
3569
+ alias.set(vs.key, vs.value);
3570
+ }
3571
+ }
3572
+ return alias;
3573
+ };
3574
+ var removeUnExportSheets = (w, options) => {
3575
+ const removes = [];
3576
+ if (options.compileSheets === void 0 || options.compileSheets.length <= 0) {
3577
+ for (const [i, v] of w.worksheets.entries()) {
3578
+ const sheetName = v.name;
3579
+ if (sheetName.endsWith(".config") || sheetName.endsWith(".json")) {
3580
+ removes.push(sheetName);
3581
+ }
3582
+ }
3583
+ } else {
3584
+ for (const [i, v] of w.worksheets.entries()) {
3585
+ if (!options.compileSheets.includes(v.name)) {
3586
+ removes.push(v.name);
3587
+ }
3588
+ }
3589
+ }
3590
+ for (const [_, name] of removes.entries()) {
3591
+ w.removeWorksheet(name);
3592
+ }
3593
+ return w;
3594
+ };
3595
+ var toBuffer = async (w) => {
3596
+ const arrayBuffer = await w.xlsx.writeBuffer();
3597
+ return Buffer.from(arrayBuffer);
3598
+ };
3599
+ var ExprResolver = class {
3600
+ };
3601
+ ExprResolver.toBuffer = toBuffer;
3602
+ ExprResolver.compile = compile;
3603
+ ExprResolver.toRowCells = toRowCells;
3604
+ ExprResolver.fetchAlias = fetchAlias;
3605
+ ExprResolver.getExprEnd = getExprEnd;
3606
+ ExprResolver.compileCheck = compileCheck;
3607
+ ExprResolver.extractMacro = extractMacro;
3608
+ ExprResolver.compileRowCells = compileRowCells;
3609
+ ExprResolver.searchIndexOf = searchIndexOf;
3610
+ ExprResolver.resolveAliasExpr = resolveAliasExpr;
3611
+ ExprResolver.resolveValueExpr = resolveValueExpr;
3612
+ ExprResolver.resolveFunctionExpr = resolveFunctionExpr;
3613
+ ExprResolver.removeUnExportSheets = removeUnExportSheets;
3614
+ ExprResolver.resolveCompileMacroGen = resolveCompileMacroGen;
3615
+ ExprResolver.resolveCompileMacroExpr = resolveCompileMacroExpr;
3616
+
3617
+ // src/extends.ts
3618
+ function hasToString(obj) {
3619
+ return obj != null && typeof obj.toString === "function";
3620
+ }
3621
+ var tokenNextIter = [`root`, `groups`, `suffix`, `default`];
3622
+ var aliasKey = `__alias`;
3623
+ var ArgumentData = class {
3624
+ constructor(fn, p) {
3625
+ this.default = "";
3626
+ this.groups = [];
3627
+ this.tokenIterIndex = 0;
3628
+ this.p = p;
3629
+ this.func = fn;
3630
+ this.groups = [];
3631
+ }
3632
+ To() {
3633
+ return {
3634
+ p: this.p,
3635
+ root: this.root,
3636
+ alias: this.alias,
3637
+ groups: this.groups,
3638
+ suffix: this.suffix,
3639
+ default: this.default,
3640
+ func: this.func
3641
+ };
3642
+ }
3643
+ Add(startToken, value) {
3644
+ if (value === void 0) {
3645
+ this.tokenIterIndex++;
3646
+ return;
3647
+ }
3648
+ switch (startToken) {
3649
+ case `(`:
3650
+ if (tokenNextIter[this.tokenIterIndex] === "root") {
3651
+ this.root = value;
3652
+ this.tokenIterIndex++;
3653
+ }
3654
+ break;
3655
+ case `[`:
3656
+ if (tokenNextIter[this.tokenIterIndex] === "groups") {
3657
+ this.groups.push(value);
3658
+ }
3659
+ break;
3660
+ case `]`:
3661
+ if (tokenNextIter[this.tokenIterIndex] === "groups") {
3662
+ this.groups.push(value);
3663
+ }
3664
+ break;
3665
+ case `,`:
3666
+ const token = tokenNextIter[this.tokenIterIndex];
3667
+ if (token === "root") {
3668
+ this.root = value;
3669
+ this.tokenIterIndex++;
3670
+ } else if (token === "groups") {
3671
+ this.groups.push(value);
3672
+ } else if (token === "suffix") {
3673
+ this.suffix = value;
3674
+ this.tokenIterIndex++;
3675
+ } else if (token === "default") {
3676
+ this.default = value;
3677
+ this.tokenIterIndex++;
3678
+ }
3679
+ break;
3680
+ case `)`:
3681
+ this.tokenIterIndex++;
3682
+ break;
3683
+ }
3684
+ }
3685
+ ParseAlias(alias) {
3686
+ if (alias === void 0 || this.root === void 0 || this.root === "") {
3687
+ return;
3688
+ }
3689
+ const value = valueDotGet(alias, this.root);
3690
+ if (value === void 0 || typeof value !== "string" || !hasToString(value)) {
3691
+ return;
3692
+ }
3693
+ this.alias = this.root;
3694
+ this.root = value;
3695
+ }
3696
+ };
3697
+ var ArgumentValue = class {
3698
+ constructor(value, defValue) {
3699
+ this.value = value;
3700
+ this.defaultValue = defValue;
3701
+ }
3702
+ isUndefined() {
3703
+ return this.value === void 0;
3704
+ }
3705
+ getDefault() {
3706
+ return this.defaultValue;
3707
+ }
3708
+ getNumber() {
3709
+ return Number(this.value);
3710
+ }
3711
+ toString() {
3712
+ if (this.isUndefined()) {
3713
+ return "";
3714
+ }
3715
+ if (typeof this.value === "string") {
3716
+ return this.value;
3717
+ }
3718
+ if (hasToString(this.value)) {
3719
+ return this.value.toString();
3720
+ }
3721
+ return "";
3722
+ }
3723
+ };
3724
+ var ArgumentValueLoader = (values, args) => {
3725
+ let all = [];
3726
+ for (let v of args.groups) {
3727
+ let key = `${args.root}.${v}`;
3728
+ if (args.suffix !== void 0 && args.suffix !== "") {
3729
+ key = `${key}.${args.suffix}`;
3730
+ }
3731
+ all.push(key);
3732
+ }
3733
+ if (all.length <= 0) {
3734
+ return args.default || "";
3735
+ }
3736
+ const items = [];
3737
+ for (let k of all) {
3738
+ let vs = valueDotGet(values, k);
3739
+ items.push(new ArgumentValue(vs, args.default));
3740
+ }
3741
+ return items;
3742
+ };
3743
+ var sum_all = (values, argument) => {
3744
+ let sum = NaN;
3745
+ let emptyTimes = 0;
3746
+ let argc = argument.groups.length;
3747
+ let items = ArgumentValueLoader(values, argument);
3748
+ for (let value of items) {
3749
+ let num = value.getNumber();
3750
+ if (value.isUndefined()) {
3751
+ emptyTimes++;
3752
+ num = Number(argument.default);
3753
+ }
3754
+ if (isNaN(sum)) {
3755
+ sum = num;
3756
+ } else {
3757
+ sum = sum + Number(num);
3758
+ }
3759
+ }
3760
+ if (emptyTimes === argc) {
3761
+ return void 0;
3762
+ }
3763
+ if (isNaN(sum)) {
3764
+ throw new Error(`parse ${argument.p.name} NaN error`);
3765
+ }
3766
+ return sum;
3767
+ };
3768
+ var sub_value = (values, argument) => {
3769
+ let sub = NaN;
3770
+ let emptyTimes = 0;
3771
+ let argc = argument.groups.length;
3772
+ let items = ArgumentValueLoader(values, argument);
3773
+ for (let value of items) {
3774
+ let num = value.getNumber();
3775
+ if (value.isUndefined()) {
3776
+ emptyTimes++;
3777
+ num = Number(argument.default);
3778
+ }
3779
+ if (isNaN(num)) {
3780
+ continue;
3781
+ }
3782
+ if (isNaN(sub)) {
3783
+ sub = num;
3784
+ } else {
3785
+ sub = sub - Number(num);
3786
+ }
3787
+ }
3788
+ if (emptyTimes === argc) {
3789
+ return void 0;
3790
+ }
3791
+ if (isNaN(sub)) {
3792
+ throw new Error(`parse ${argument.p.name} NaN error`);
3793
+ }
3794
+ return sub;
3795
+ };
3796
+ var defaultCommands = /* @__PURE__ */ new Map([
3797
+ ["sum", sum_all],
3798
+ ["sub", sub_value]
3799
+ ]);
3800
+ var resolveFunc = function(value) {
3801
+ if (value.indexOf("(") > 0 && value.endsWith(")")) {
3802
+ const names = value.split("(");
3803
+ return names[0];
3804
+ }
3805
+ return "";
3806
+ };
3807
+ var resolveArgument = function(p, data) {
3808
+ const value = p.name;
3809
+ const fn = resolveFunc(value);
3810
+ const args = new ArgumentData(fn, p);
3811
+ if (fn !== "") {
3812
+ let key = "";
3813
+ let startT = "";
3814
+ const endToken = [`)`, `,`, `]`];
3815
+ const startToken = [`(`, `,`, `[`];
3816
+ const tokenRow = value.split(`${fn}`)[1];
3817
+ const len = tokenRow.length;
3818
+ for (let i = 0; i < len; i++) {
3819
+ let start = startToken.includes(tokenRow[i]);
3820
+ let end = endToken.includes(tokenRow[i]);
3821
+ if (start) {
3822
+ startT = tokenRow[i];
3823
+ }
3824
+ if (startT !== "" && tokenRow[i] !== startT && !end) {
3825
+ key = `${key}${tokenRow[i]}`;
3826
+ }
3827
+ if (end) {
3828
+ if (key === "") {
3829
+ args.Add(startT, void 0);
3830
+ } else {
3831
+ args.Add(startT, key);
3832
+ key = "";
3833
+ }
3834
+ }
3835
+ }
3836
+ }
3837
+ const alias = valueDotGet(data, aliasKey);
3838
+ if (alias !== void 0) {
3839
+ args.ParseAlias(alias);
3840
+ }
3841
+ return args.To();
3842
+ };
3843
+ var commandExtendQuery = function(values, p) {
3844
+ if (p.type !== "fn") {
3845
+ return defaultValueDotGet(values, p);
3846
+ }
3847
+ const argument = resolveArgument(p, values);
3848
+ if (argument.func !== "" && defaultCommands.has(argument.func)) {
3849
+ return defaultCommands.get(argument.func)(values, argument);
3850
+ }
3851
+ return defaultValueDotGet(values, p);
3852
+ };
3853
+ var AddCommand = (key, h) => {
3854
+ if (defaultCommands.has(key)) {
3855
+ return false;
3856
+ }
3857
+ defaultCommands.set(key, h);
3858
+ return true;
3859
+ };
3860
+ var AddCommandMust = (key, h) => {
3861
+ defaultCommands.set(key, h);
3862
+ };
3863
+ var generateCommandsXlsxTemplate = async function(data, values, options) {
3864
+ const w = await Workbook.parse(data, options);
3865
+ w.setQueryFunctionHandler(commandExtendQuery);
3866
+ await w.substituteAll(values);
3867
+ return w.generate(options);
3868
+ };
3869
+ var getCommands = () => {
3870
+ return defaultCommands;
3871
+ };
3872
+ var compileRuleSheetName = "export_metadata.config";
3873
+ var mergeMap = function(source, dest) {
3874
+ for (const [key, value] of dest.entries()) {
3875
+ source.set(key, value);
3876
+ }
3877
+ return source;
3878
+ };
3879
+ var generateCommandsXlsxTemplateWithCompile = async function(data, values, compileOptions, options) {
3880
+ if (compileOptions.sheetName === void 0 || compileOptions.sheetName === "") {
3881
+ compileOptions.sheetName = compileRuleSheetName;
3882
+ }
3883
+ const result = await ExprResolver.compile(data, compileOptions.sheetName, compileOptions);
3884
+ if (result.errs !== void 0 && result.errs.length > 0) {
3885
+ throw result.errs[0];
3886
+ }
3887
+ let alias = ExprResolver.fetchAlias(result.configure);
3888
+ if (values[aliasKey] !== void 0 && values[aliasKey] instanceof Map) {
3889
+ alias = mergeMap(alias, values[aliasKey]);
3890
+ }
3891
+ values[aliasKey] = alias;
3892
+ result.workbook = ExprResolver.removeUnExportSheets(result.workbook, compileOptions);
3893
+ const wb = await ExprResolver.toBuffer(result.workbook);
3894
+ const w = await Workbook.parse(wb, options);
3895
+ w.setQueryFunctionHandler(commandExtendQuery);
3896
+ await w.substituteAll(values);
3897
+ return w.generate(options);
3898
+ };
3899
+ export {
3900
+ AddCommand,
3901
+ AddCommandMust,
3902
+ ArgumentData,
3903
+ ArgumentValue,
3904
+ ArgumentValueLoader,
3905
+ BufferType,
3906
+ CompileContext,
3907
+ DefaultPlaceholderCellValue,
3908
+ ExprResolver,
3909
+ RuleMapOptions,
3910
+ RuleToken,
3911
+ TokenParserManger,
3912
+ Workbook,
3913
+ columnLetterToNumber,
3914
+ columnNumberToLetter,
3915
+ commandExtendQuery,
3916
+ compileRuleSheetName,
3917
+ compileWorkSheet,
3918
+ compileWorkSheetPlaceholder,
3919
+ defaultExtractPlaceholders,
3920
+ defaultFormatters,
3921
+ defaultValueDotGet,
3922
+ exceljs,
3923
+ generateCommandsXlsxTemplate,
3924
+ generateCommandsXlsxTemplateWithCompile,
3925
+ generateXlsxTemplate,
3926
+ getCommands,
3927
+ getTokenParser,
3928
+ hasGeneratorToken,
3929
+ isRuleToken,
3930
+ isUrl,
3931
+ loadWorkbook,
3932
+ parseWorkSheetRules,
3933
+ registerTokenParser,
3934
+ registerTokenParserMust,
3935
+ resolveArgument,
3936
+ scanCellSetPlaceholder,
3937
+ toArrayBuffer,
3938
+ valueDotGet,
3939
+ workSheetSetPlaceholder
3940
+ };
3941
+ //# sourceMappingURL=index.mjs.map