@vdhewei/xlsx-template-lib 1.5.0 → 1.6.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/bin.js CHANGED
@@ -6,34 +6,2396 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJS = (cb, mod) => function __require() {
10
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
+ };
9
12
  var __copyProps = (to, from, except, desc) => {
10
13
  if (from && typeof from === "object" || typeof from === "function") {
11
14
  for (let key of __getOwnPropNames(from))
12
15
  if (!__hasOwnProp.call(to, key) && key !== except)
13
16
  __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
17
  }
15
- return to;
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+
29
+ // node_modules/.pnpm/dotenv@17.3.1/node_modules/dotenv/package.json
30
+ var require_package = __commonJS({
31
+ "node_modules/.pnpm/dotenv@17.3.1/node_modules/dotenv/package.json"(exports2, module2) {
32
+ module2.exports = {
33
+ name: "dotenv",
34
+ version: "17.3.1",
35
+ description: "Loads environment variables from .env file",
36
+ main: "lib/main.js",
37
+ types: "lib/main.d.ts",
38
+ exports: {
39
+ ".": {
40
+ types: "./lib/main.d.ts",
41
+ require: "./lib/main.js",
42
+ default: "./lib/main.js"
43
+ },
44
+ "./config": "./config.js",
45
+ "./config.js": "./config.js",
46
+ "./lib/env-options": "./lib/env-options.js",
47
+ "./lib/env-options.js": "./lib/env-options.js",
48
+ "./lib/cli-options": "./lib/cli-options.js",
49
+ "./lib/cli-options.js": "./lib/cli-options.js",
50
+ "./package.json": "./package.json"
51
+ },
52
+ scripts: {
53
+ "dts-check": "tsc --project tests/types/tsconfig.json",
54
+ lint: "standard",
55
+ pretest: "npm run lint && npm run dts-check",
56
+ test: "tap run tests/**/*.js --allow-empty-coverage --disable-coverage --timeout=60000",
57
+ "test:coverage": "tap run tests/**/*.js --show-full-coverage --timeout=60000 --coverage-report=text --coverage-report=lcov",
58
+ prerelease: "npm test",
59
+ release: "standard-version"
60
+ },
61
+ repository: {
62
+ type: "git",
63
+ url: "git://github.com/motdotla/dotenv.git"
64
+ },
65
+ homepage: "https://github.com/motdotla/dotenv#readme",
66
+ funding: "https://dotenvx.com",
67
+ keywords: [
68
+ "dotenv",
69
+ "env",
70
+ ".env",
71
+ "environment",
72
+ "variables",
73
+ "config",
74
+ "settings"
75
+ ],
76
+ readmeFilename: "README.md",
77
+ license: "BSD-2-Clause",
78
+ devDependencies: {
79
+ "@types/node": "^18.11.3",
80
+ decache: "^4.6.2",
81
+ sinon: "^14.0.1",
82
+ standard: "^17.0.0",
83
+ "standard-version": "^9.5.0",
84
+ tap: "^19.2.0",
85
+ typescript: "^4.8.4"
86
+ },
87
+ engines: {
88
+ node: ">=12"
89
+ },
90
+ browser: {
91
+ fs: false
92
+ }
93
+ };
94
+ }
95
+ });
96
+
97
+ // node_modules/.pnpm/dotenv@17.3.1/node_modules/dotenv/lib/main.js
98
+ var require_main = __commonJS({
99
+ "node_modules/.pnpm/dotenv@17.3.1/node_modules/dotenv/lib/main.js"(exports2, module2) {
100
+ "use strict";
101
+ var fs5 = require("fs");
102
+ var path4 = require("path");
103
+ var os = require("os");
104
+ var crypto = require("crypto");
105
+ var packageJson = require_package();
106
+ var version = packageJson.version;
107
+ var TIPS = [
108
+ "\u{1F510} encrypt with Dotenvx: https://dotenvx.com",
109
+ "\u{1F510} prevent committing .env to code: https://dotenvx.com/precommit",
110
+ "\u{1F510} prevent building .env in docker: https://dotenvx.com/prebuild",
111
+ "\u{1F916} agentic secret storage: https://dotenvx.com/as2",
112
+ "\u26A1\uFE0F secrets for agents: https://dotenvx.com/as2",
113
+ "\u{1F6E1}\uFE0F auth for agents: https://vestauth.com",
114
+ "\u{1F6E0}\uFE0F run anywhere with `dotenvx run -- yourcommand`",
115
+ "\u2699\uFE0F specify custom .env file path with { path: '/custom/path/.env' }",
116
+ "\u2699\uFE0F enable debug logging with { debug: true }",
117
+ "\u2699\uFE0F override existing env vars with { override: true }",
118
+ "\u2699\uFE0F suppress all logs with { quiet: true }",
119
+ "\u2699\uFE0F write to custom object with { processEnv: myObject }",
120
+ "\u2699\uFE0F load multiple .env files with { path: ['.env.local', '.env'] }"
121
+ ];
122
+ function _getRandomTip() {
123
+ return TIPS[Math.floor(Math.random() * TIPS.length)];
124
+ }
125
+ function parseBoolean(value) {
126
+ if (typeof value === "string") {
127
+ return !["false", "0", "no", "off", ""].includes(value.toLowerCase());
128
+ }
129
+ return Boolean(value);
130
+ }
131
+ function supportsAnsi() {
132
+ return process.stdout.isTTY;
133
+ }
134
+ function dim(text) {
135
+ return supportsAnsi() ? `\x1B[2m${text}\x1B[0m` : text;
136
+ }
137
+ var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
138
+ function parse2(src) {
139
+ const obj = {};
140
+ let lines = src.toString();
141
+ lines = lines.replace(/\r\n?/mg, "\n");
142
+ let match;
143
+ while ((match = LINE.exec(lines)) != null) {
144
+ const key = match[1];
145
+ let value = match[2] || "";
146
+ value = value.trim();
147
+ const maybeQuote = value[0];
148
+ value = value.replace(/^(['"`])([\s\S]*)\1$/mg, "$2");
149
+ if (maybeQuote === '"') {
150
+ value = value.replace(/\\n/g, "\n");
151
+ value = value.replace(/\\r/g, "\r");
152
+ }
153
+ obj[key] = value;
154
+ }
155
+ return obj;
156
+ }
157
+ function _parseVault(options) {
158
+ options = options || {};
159
+ const vaultPath = _vaultPath(options);
160
+ options.path = vaultPath;
161
+ const result = DotenvModule.configDotenv(options);
162
+ if (!result.parsed) {
163
+ const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
164
+ err.code = "MISSING_DATA";
165
+ throw err;
166
+ }
167
+ const keys = _dotenvKey(options).split(",");
168
+ const length = keys.length;
169
+ let decrypted;
170
+ for (let i = 0; i < length; i++) {
171
+ try {
172
+ const key = keys[i].trim();
173
+ const attrs = _instructions(result, key);
174
+ decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
175
+ break;
176
+ } catch (error) {
177
+ if (i + 1 >= length) {
178
+ throw error;
179
+ }
180
+ }
181
+ }
182
+ return DotenvModule.parse(decrypted);
183
+ }
184
+ function _warn(message) {
185
+ console.error(`[dotenv@${version}][WARN] ${message}`);
186
+ }
187
+ function _debug(message) {
188
+ console.log(`[dotenv@${version}][DEBUG] ${message}`);
189
+ }
190
+ function _log(message) {
191
+ console.log(`[dotenv@${version}] ${message}`);
192
+ }
193
+ function _dotenvKey(options) {
194
+ if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
195
+ return options.DOTENV_KEY;
196
+ }
197
+ if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
198
+ return process.env.DOTENV_KEY;
199
+ }
200
+ return "";
201
+ }
202
+ function _instructions(result, dotenvKey) {
203
+ let uri;
204
+ try {
205
+ uri = new URL(dotenvKey);
206
+ } catch (error) {
207
+ if (error.code === "ERR_INVALID_URL") {
208
+ const err = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
209
+ err.code = "INVALID_DOTENV_KEY";
210
+ throw err;
211
+ }
212
+ throw error;
213
+ }
214
+ const key = uri.password;
215
+ if (!key) {
216
+ const err = new Error("INVALID_DOTENV_KEY: Missing key part");
217
+ err.code = "INVALID_DOTENV_KEY";
218
+ throw err;
219
+ }
220
+ const environment = uri.searchParams.get("environment");
221
+ if (!environment) {
222
+ const err = new Error("INVALID_DOTENV_KEY: Missing environment part");
223
+ err.code = "INVALID_DOTENV_KEY";
224
+ throw err;
225
+ }
226
+ const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
227
+ const ciphertext = result.parsed[environmentKey];
228
+ if (!ciphertext) {
229
+ const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
230
+ err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
231
+ throw err;
232
+ }
233
+ return { ciphertext, key };
234
+ }
235
+ function _vaultPath(options) {
236
+ let possibleVaultPath = null;
237
+ if (options && options.path && options.path.length > 0) {
238
+ if (Array.isArray(options.path)) {
239
+ for (const filepath of options.path) {
240
+ if (fs5.existsSync(filepath)) {
241
+ possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
242
+ }
243
+ }
244
+ } else {
245
+ possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
246
+ }
247
+ } else {
248
+ possibleVaultPath = path4.resolve(process.cwd(), ".env.vault");
249
+ }
250
+ if (fs5.existsSync(possibleVaultPath)) {
251
+ return possibleVaultPath;
252
+ }
253
+ return null;
254
+ }
255
+ function _resolveHome(envPath) {
256
+ return envPath[0] === "~" ? path4.join(os.homedir(), envPath.slice(1)) : envPath;
257
+ }
258
+ function _configVault(options) {
259
+ const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
260
+ const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options && options.quiet);
261
+ if (debug || !quiet) {
262
+ _log("Loading env from encrypted .env.vault");
263
+ }
264
+ const parsed = DotenvModule._parseVault(options);
265
+ let processEnv = process.env;
266
+ if (options && options.processEnv != null) {
267
+ processEnv = options.processEnv;
268
+ }
269
+ DotenvModule.populate(processEnv, parsed, options);
270
+ return { parsed };
271
+ }
272
+ function configDotenv(options) {
273
+ const dotenvPath = path4.resolve(process.cwd(), ".env");
274
+ let encoding = "utf8";
275
+ let processEnv = process.env;
276
+ if (options && options.processEnv != null) {
277
+ processEnv = options.processEnv;
278
+ }
279
+ let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options && options.debug);
280
+ let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options && options.quiet);
281
+ if (options && options.encoding) {
282
+ encoding = options.encoding;
283
+ } else {
284
+ if (debug) {
285
+ _debug("No encoding is specified. UTF-8 is used by default");
286
+ }
287
+ }
288
+ let optionPaths = [dotenvPath];
289
+ if (options && options.path) {
290
+ if (!Array.isArray(options.path)) {
291
+ optionPaths = [_resolveHome(options.path)];
292
+ } else {
293
+ optionPaths = [];
294
+ for (const filepath of options.path) {
295
+ optionPaths.push(_resolveHome(filepath));
296
+ }
297
+ }
298
+ }
299
+ let lastError;
300
+ const parsedAll = {};
301
+ for (const path5 of optionPaths) {
302
+ try {
303
+ const parsed = DotenvModule.parse(fs5.readFileSync(path5, { encoding }));
304
+ DotenvModule.populate(parsedAll, parsed, options);
305
+ } catch (e) {
306
+ if (debug) {
307
+ _debug(`Failed to load ${path5} ${e.message}`);
308
+ }
309
+ lastError = e;
310
+ }
311
+ }
312
+ const populated = DotenvModule.populate(processEnv, parsedAll, options);
313
+ debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug);
314
+ quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet);
315
+ if (debug || !quiet) {
316
+ const keysCount = Object.keys(populated).length;
317
+ const shortPaths = [];
318
+ for (const filePath of optionPaths) {
319
+ try {
320
+ const relative = path4.relative(process.cwd(), filePath);
321
+ shortPaths.push(relative);
322
+ } catch (e) {
323
+ if (debug) {
324
+ _debug(`Failed to load ${filePath} ${e.message}`);
325
+ }
326
+ lastError = e;
327
+ }
328
+ }
329
+ _log(`injecting env (${keysCount}) from ${shortPaths.join(",")} ${dim(`-- tip: ${_getRandomTip()}`)}`);
330
+ }
331
+ if (lastError) {
332
+ return { parsed: parsedAll, error: lastError };
333
+ } else {
334
+ return { parsed: parsedAll };
335
+ }
336
+ }
337
+ function config(options) {
338
+ if (_dotenvKey(options).length === 0) {
339
+ return DotenvModule.configDotenv(options);
340
+ }
341
+ const vaultPath = _vaultPath(options);
342
+ if (!vaultPath) {
343
+ _warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
344
+ return DotenvModule.configDotenv(options);
345
+ }
346
+ return DotenvModule._configVault(options);
347
+ }
348
+ function decrypt(encrypted, keyStr) {
349
+ const key = Buffer.from(keyStr.slice(-64), "hex");
350
+ let ciphertext = Buffer.from(encrypted, "base64");
351
+ const nonce = ciphertext.subarray(0, 12);
352
+ const authTag = ciphertext.subarray(-16);
353
+ ciphertext = ciphertext.subarray(12, -16);
354
+ try {
355
+ const aesgcm = crypto.createDecipheriv("aes-256-gcm", key, nonce);
356
+ aesgcm.setAuthTag(authTag);
357
+ return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
358
+ } catch (error) {
359
+ const isRange = error instanceof RangeError;
360
+ const invalidKeyLength = error.message === "Invalid key length";
361
+ const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
362
+ if (isRange || invalidKeyLength) {
363
+ const err = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
364
+ err.code = "INVALID_DOTENV_KEY";
365
+ throw err;
366
+ } else if (decryptionFailed) {
367
+ const err = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
368
+ err.code = "DECRYPTION_FAILED";
369
+ throw err;
370
+ } else {
371
+ throw error;
372
+ }
373
+ }
374
+ }
375
+ function populate(processEnv, parsed, options = {}) {
376
+ const debug = Boolean(options && options.debug);
377
+ const override = Boolean(options && options.override);
378
+ const populated = {};
379
+ if (typeof parsed !== "object") {
380
+ const err = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
381
+ err.code = "OBJECT_REQUIRED";
382
+ throw err;
383
+ }
384
+ for (const key of Object.keys(parsed)) {
385
+ if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
386
+ if (override === true) {
387
+ processEnv[key] = parsed[key];
388
+ populated[key] = parsed[key];
389
+ }
390
+ if (debug) {
391
+ if (override === true) {
392
+ _debug(`"${key}" is already defined and WAS overwritten`);
393
+ } else {
394
+ _debug(`"${key}" is already defined and was NOT overwritten`);
395
+ }
396
+ }
397
+ } else {
398
+ processEnv[key] = parsed[key];
399
+ populated[key] = parsed[key];
400
+ }
401
+ }
402
+ return populated;
403
+ }
404
+ var DotenvModule = {
405
+ configDotenv,
406
+ _configVault,
407
+ _parseVault,
408
+ config,
409
+ decrypt,
410
+ parse: parse2,
411
+ populate
412
+ };
413
+ module2.exports.configDotenv = DotenvModule.configDotenv;
414
+ module2.exports._configVault = DotenvModule._configVault;
415
+ module2.exports._parseVault = DotenvModule._parseVault;
416
+ module2.exports.config = DotenvModule.config;
417
+ module2.exports.decrypt = DotenvModule.decrypt;
418
+ module2.exports.parse = DotenvModule.parse;
419
+ module2.exports.populate = DotenvModule.populate;
420
+ module2.exports = DotenvModule;
421
+ }
422
+ });
423
+
424
+ // src/bin.ts
425
+ var import_chalk2 = __toESM(require("chalk"));
426
+ var import_commander = require("commander");
427
+ var fs4 = __toESM(require("fs/promises"));
428
+ var import_node_fs2 = require("fs");
429
+ var path3 = __toESM(require("path"));
430
+
431
+ // src/core.ts
432
+ var path = __toESM(require("path"));
433
+ var fs = __toESM(require("fs"));
434
+ var etree = __toESM(require("elementtree"));
435
+ var import_jszip = __toESM(require("jszip"));
436
+ var console2 = __toESM(require("console"));
437
+ var import_image_size = require("image-size");
438
+ var import_types = require("util/types");
439
+ var DOCUMENT_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
440
+ var CALC_CHAIN_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain";
441
+ var SHARED_STRINGS_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
442
+ var HYPERLINK_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
443
+ function _getSimple(obj, key) {
444
+ if (key.includes("[")) {
445
+ const parts = key.split(/[\[\]]/);
446
+ const property = parts[0];
447
+ const index = parts[1];
448
+ if (property && index !== void 0) {
449
+ return obj?.[property]?.[index];
450
+ }
451
+ }
452
+ if ((0, import_types.isMap)(obj)) {
453
+ return obj.get(key);
454
+ }
455
+ return obj?.[key];
456
+ }
457
+ function valueDotGet(obj, path4, defaultValue) {
458
+ if (!path4 || !obj) return defaultValue;
459
+ const keys = path4.split(".");
460
+ let current = obj;
461
+ for (const key of keys) {
462
+ if (current === null || current === void 0) return defaultValue;
463
+ current = _getSimple(current, key);
464
+ }
465
+ return current === void 0 ? defaultValue : current;
466
+ }
467
+ function defaultValueDotGet(obj, p) {
468
+ return valueDotGet(obj, p.name, p.default || "");
469
+ }
470
+ var dateFormatter = (value, _placeholder, _key) => {
471
+ if (value instanceof Date) {
472
+ return Number(value.getTime() / (1e3 * 60 * 60 * 24) + 25569).toString();
473
+ }
474
+ return void 0;
475
+ };
476
+ var numberFormatter = (value, _placeholder, _key) => {
477
+ if (typeof value === "number") {
478
+ return value.toString();
479
+ }
480
+ return void 0;
481
+ };
482
+ var booleanFormatter = (value, _placeholder, _key) => {
483
+ if (typeof value === "boolean") {
484
+ return Number(value).toString();
485
+ }
486
+ return void 0;
487
+ };
488
+ var stringFormatter = (value, _placeholder, _key) => {
489
+ if (typeof value === "string") {
490
+ return value.toString();
491
+ }
492
+ return void 0;
493
+ };
494
+ var defaultRe = /\${(?:([^{}:]+?):)?([^{}:]+?)(?:\.([^{}:]+?))?(?::([^{}:]+?))??}/g;
495
+ var defaultExtractPlaceholders = (inputString, options) => {
496
+ const matches = [];
497
+ const re = options.customPlaceholderRegex || defaultRe;
498
+ if (options.enableDefaultParsing && options.customPlaceholderRegex) {
499
+ let match2;
500
+ while ((match2 = defaultRe.exec(inputString)) !== null) {
501
+ matches.push({
502
+ placeholder: match2[0],
503
+ type: match2[1] || "normal",
504
+ name: match2[2],
505
+ key: match2[3],
506
+ subType: match2[4],
507
+ full: match2[0].length === inputString.length
508
+ });
509
+ }
510
+ }
511
+ let match;
512
+ re.lastIndex = 0;
513
+ while ((match = re.exec(inputString)) !== null) {
514
+ if (options.enableDefaultParsing && options.customPlaceholderRegex) {
515
+ const isDuplicate = matches.some((m) => m.placeholder === match[0]);
516
+ if (isDuplicate) continue;
517
+ }
518
+ matches.push({
519
+ placeholder: match[0],
520
+ type: match[1] || "normal",
521
+ name: match[2],
522
+ key: match[3],
523
+ subType: match[4],
524
+ full: match[0].length === inputString.length
525
+ });
526
+ }
527
+ return matches;
528
+ };
529
+ var defaultFormatters = [
530
+ dateFormatter,
531
+ numberFormatter,
532
+ booleanFormatter,
533
+ stringFormatter
534
+ ];
535
+ 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");
536
+ var toArrayBuffer = function(buffer) {
537
+ const ab = new ArrayBuffer(buffer.length);
538
+ const view = new Uint8Array(ab);
539
+ for (let i = 0; i < buffer.length; ++i) {
540
+ view[i] = buffer[i];
541
+ }
542
+ return ab;
543
+ };
544
+ var Workbook = class _Workbook {
545
+ // ==================== 构造函数 ====================
546
+ constructor(option) {
547
+ this.sharedStrings = [];
548
+ this.sharedStringsLookup = {};
549
+ this.sharedStringsPath = "";
550
+ this.sheets = [];
551
+ this.sheet = null;
552
+ this.workbook = null;
553
+ this.workbookPath = null;
554
+ this.contentTypes = null;
555
+ this.prefix = null;
556
+ this.workbookRels = null;
557
+ this.calChainRel = null;
558
+ this.calcChainPath = "";
559
+ // RichData 相关属性
560
+ this.richDataIsInit = false;
561
+ this._relsrichValueRel = null;
562
+ this.rdrichvalue = null;
563
+ this.rdrichvaluestructure = null;
564
+ this.rdRichValueTypes = null;
565
+ this.richValueRel = null;
566
+ this.metadata = null;
567
+ this.option = {
568
+ moveImages: false,
569
+ substituteAllTableRow: false,
570
+ moveSameLineImages: false,
571
+ imageRatio: 100,
572
+ pushDownPageBreakOnTableSubstitution: false,
573
+ imageRootPath: null,
574
+ handleImageError: null,
575
+ ...option
576
+ };
577
+ }
578
+ // ==================== parse 构造函数 ====================
579
+ static async parse(data, option) {
580
+ const w = new _Workbook(option);
581
+ await w.loadTemplate(data);
582
+ return w;
583
+ }
584
+ // ==================== 扩展方法 ====================
585
+ /**
586
+ * 添加自定义替换器
587
+ * @param replacer - 替换函数
588
+ * @returns this(支持链式调用)
589
+ */
590
+ addReplacer(replacer) {
591
+ if (!this.option.replacers) {
592
+ this.option.replacers = [];
593
+ }
594
+ this.option.replacers.push(replacer);
595
+ return this;
596
+ }
597
+ /**
598
+ * 添加自定义格式化器
599
+ * @param formatter - 格式化函数
600
+ * @returns this(支持链式调用)
601
+ */
602
+ addFormatter(formatter) {
603
+ if (!this.option.formatters) {
604
+ this.option.formatters = [];
605
+ }
606
+ this.option.formatters.push(formatter);
607
+ return this;
608
+ }
609
+ /**
610
+ * 设置替换前钩子
611
+ * @param hook - 钩子函数
612
+ * @returns this(支持链式调用)
613
+ */
614
+ setBeforeReplaceHook(hook) {
615
+ this.option.beforeReplace = hook;
616
+ return this;
617
+ }
618
+ /**
619
+ * 设置替换后钩子
620
+ * @param hook - 钩子函数
621
+ * @returns this(支持链式调用)
622
+ */
623
+ setAfterReplaceHook(hook) {
624
+ this.option.afterReplace = hook;
625
+ return this;
626
+ }
627
+ /**
628
+ * 设置自定义占位符提取器
629
+ * @param extractor - 提取函数
630
+ * @returns this(支持链式调用)
631
+ */
632
+ setPlaceholderExtractor(extractor) {
633
+ this.option.customPlaceholderExtractor = extractor;
634
+ return this;
635
+ }
636
+ /**
637
+ * 设置自定义模板正则表达式
638
+ * @param regex - 正则表达式
639
+ * @param enableDefaultParsing - 是否同时启用默认解析,默认 false
640
+ * @returns this(支持链式调用)
641
+ */
642
+ setPlaceholderRegex(regex, enableDefaultParsing = false) {
643
+ this.option.customPlaceholderRegex = regex;
644
+ this.option.enableDefaultParsing = enableDefaultParsing;
645
+ return this;
646
+ }
647
+ /**
648
+ * 设置数值查询器
649
+ * @param h QueryFunction - 设置数值查询器
650
+ * @returns this(支持链式调用)
651
+ */
652
+ setQueryFunctionHandler(h) {
653
+ this.option.customQueryFunction = h;
654
+ return this;
655
+ }
656
+ // ==================== 扩展点执行方法 ====================
657
+ /**
658
+ * 执行自定义替换器链
659
+ * @param cell - 单元格元素
660
+ * @param stringValue - 字符串值
661
+ * @param placeholder - 占位符信息
662
+ * @param substitution - 替换值
663
+ * @returns 替换结果或 undefined
664
+ */
665
+ executeReplacers(cell, stringValue, placeholder, substitution) {
666
+ if (this.option.customReplacer) {
667
+ const result = this.option.customReplacer(cell, stringValue, placeholder, substitution);
668
+ if (result !== void 0 && result !== null) {
669
+ return result;
670
+ }
671
+ }
672
+ if (this.option.replacers && this.option.replacers.length > 0) {
673
+ for (const replacer of this.option.replacers) {
674
+ const result = replacer(cell, stringValue, placeholder, substitution);
675
+ if (result !== void 0 && result !== null) {
676
+ return result;
677
+ }
678
+ }
679
+ }
680
+ return void 0;
681
+ }
682
+ /**
683
+ * 执行格式化器链
684
+ * @param value - 原始值
685
+ * @param placeholder - 占位符信息
686
+ * @param key - 可选键名
687
+ * @returns 格式化后的字符串
688
+ */
689
+ executeFormatters(value, placeholder, key) {
690
+ if (this.option.formatters && this.option.formatters.length > 0) {
691
+ for (const formatter of this.option.formatters) {
692
+ const result = formatter(value, placeholder, key);
693
+ if (result !== void 0 && result !== null) {
694
+ return result;
695
+ }
696
+ }
697
+ }
698
+ for (const formatter of defaultFormatters) {
699
+ const result = formatter(value, placeholder, key);
700
+ if (result !== void 0 && result !== null) {
701
+ return result;
702
+ }
703
+ }
704
+ return "";
705
+ }
706
+ /**
707
+ * 执行替换前钩子
708
+ */
709
+ executeBeforeReplaceHook(stringValue, substitutions) {
710
+ if (this.option.beforeReplace) {
711
+ const result = this.option.beforeReplace(stringValue, substitutions);
712
+ if (result !== void 0 && result !== null) {
713
+ return result;
714
+ }
715
+ }
716
+ return stringValue;
717
+ }
718
+ /**
719
+ * 执行替换后钩子
720
+ */
721
+ executeAfterReplaceHook(resultString, stringValue, substitutions) {
722
+ if (this.option.afterReplace) {
723
+ return this.option.afterReplace(resultString, stringValue, substitutions);
724
+ }
725
+ return resultString;
726
+ }
727
+ // ==================== 核心方法 ====================
728
+ /**
729
+ * 删除工作表
730
+ */
731
+ async deleteSheet(sheetName) {
732
+ const sheet = await this.loadSheet(sheetName);
733
+ const sh = this.workbook.find(`sheets/sheet[@sheetId='${sheet.id}']`);
734
+ const sheets = this.workbook.findall("sheets/sheet");
735
+ const sheetIndex = sheets.indexOf(sh);
736
+ const definedNamesParent = this.workbook.find("definedNames");
737
+ if (definedNamesParent) {
738
+ const toRemove = [];
739
+ this.workbook.findall("definedNames/definedName").forEach((def) => {
740
+ if (def.attrib.localSheetId !== void 0) {
741
+ const localId = parseInt(def.attrib.localSheetId);
742
+ if (localId === sheetIndex) {
743
+ toRemove.push(def);
744
+ } else if (localId > sheetIndex) {
745
+ def.attrib.localSheetId = (localId - 1).toString();
746
+ }
747
+ }
748
+ });
749
+ toRemove.forEach((def) => {
750
+ definedNamesParent.remove(def);
751
+ });
752
+ }
753
+ this.workbook.find("sheets").remove(sh);
754
+ const rel = this.workbookRels.find(`Relationship[@Id='${sh.attrib["r:id"]}']`);
755
+ this.workbookRels.remove(rel);
756
+ this._rebuild();
757
+ return this;
758
+ }
759
+ /**
760
+ * 复制工作表
761
+ */
762
+ async copySheet(sheetName, copyName, binary = true) {
763
+ if (binary === false && !process.env.JEST_WORKER_ID) {
764
+ console2.warn("Warning: copySheet() called with binary=false. UTF-8 characters may be corrupted.");
765
+ }
766
+ const sheet = await this.loadSheet(sheetName);
767
+ const newSheetIndex = (this.workbook.findall("sheets/sheet").length + 1).toString();
768
+ const fileName = "worksheets/sheet" + newSheetIndex + ".xml";
769
+ const arcName = this.prefix + "/" + fileName;
770
+ const sourceSheetFile = this.archive.file(sheet.filename);
771
+ let sheetContent = await sourceSheetFile.async(`nodebuffer`);
772
+ this.archive.file(arcName, sheetContent);
773
+ this.archive.files[arcName].options.compression = binary ? "STORE" : "DEFLATE";
774
+ const sheetContentType = etree.SubElement(this.contentTypes, "Override");
775
+ sheetContentType.attrib.PartName = "/" + arcName;
776
+ sheetContentType.attrib.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml";
777
+ const newSheet = etree.SubElement(this.workbook.find("sheets"), "sheet");
778
+ const finalSheetName = copyName || "Sheet" + newSheetIndex;
779
+ newSheet.attrib.name = finalSheetName;
780
+ newSheet.attrib.sheetId = newSheetIndex;
781
+ newSheet.attrib["r:id"] = "rId" + newSheetIndex;
782
+ this.workbook.findall("definedNames/definedName").forEach((element) => {
783
+ if (element.text && element.text.split("!").length && element.text.split("!")[0] == sheetName) {
784
+ const newDefinedName = etree.SubElement(this.workbook.find("definedNames"), "definedName", element.attrib);
785
+ newDefinedName.text = finalSheetName + "!" + element.text.split("!")[1];
786
+ const index = Number.parseInt(newSheetIndex, 10) - 1;
787
+ newDefinedName.attrib.localSheetId = `${index}`;
788
+ }
789
+ });
790
+ const newRel = etree.SubElement(this.workbookRels, "Relationship");
791
+ newRel.attrib.Type = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet";
792
+ newRel.attrib.Target = fileName;
793
+ const sourceRels = await this.loadSheetRels(sheet.filename);
794
+ const relFileName = "worksheets/_rels/sheet" + newSheetIndex + ".xml.rels";
795
+ const relArcName = this.prefix + "/" + relFileName;
796
+ const newRelsRoot = this.cloneElement(sourceRels.root, true);
797
+ const newCommentUuid = this.generateUUID();
798
+ sourceRels.root.findall("Relationship").forEach((rel, index) => {
799
+ const relType = rel.attrib.Type;
800
+ const target = rel.attrib.Target;
801
+ const needsFileCopy = [
802
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",
803
+ "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment",
804
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing"
805
+ ];
806
+ if (needsFileCopy.indexOf(relType) !== -1) {
807
+ const sheetDirectory = path.dirname(sheet.filename);
808
+ const sourceFilePath = path.join(sheetDirectory, target).replace(/\\/g, "/");
809
+ const sourceFile = this.archive.file(sourceFilePath);
810
+ if (sourceFile) {
811
+ const fileExtension = path.extname(target);
812
+ const fileBaseName = path.basename(target, fileExtension);
813
+ const fileDir = path.dirname(target);
814
+ const baseNameWithoutNumber = fileBaseName.replace(/\d+$/, "");
815
+ const newFileName = baseNameWithoutNumber + newSheetIndex + fileExtension;
816
+ const newTarget = path.join(fileDir, newFileName).replace(/\\/g, "/");
817
+ const newFilePath = path.join(sheetDirectory, newTarget).replace(/\\/g, "/");
818
+ const content = sourceFile.async(`string`);
819
+ content.then((binaryContent) => {
820
+ if (relType === "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") {
821
+ binaryContent = binaryContent.replace(/data="\d+"/, 'data="' + newSheetIndex + '"');
822
+ } else if (relType === "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments") {
823
+ const uuidWithoutBraces = newCommentUuid.replace(/[{}]/g, "");
824
+ 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");
825
+ 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");
826
+ const commentsContentType = etree.SubElement(this.contentTypes, "Override");
827
+ commentsContentType.attrib.PartName = "/" + newFilePath;
828
+ commentsContentType.attrib.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml";
829
+ } else if (relType === "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment") {
830
+ const uuidWithoutBraces = newCommentUuid.replace(/[{}]/g, "");
831
+ 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");
832
+ const threadedCommentContentType = etree.SubElement(this.contentTypes, "Override");
833
+ threadedCommentContentType.attrib.PartName = "/" + newFilePath;
834
+ threadedCommentContentType.attrib.ContentType = "application/vnd.ms-excel.threadedcomments+xml";
835
+ }
836
+ this.archive.file(newFilePath, binaryContent);
837
+ this.archive.files[newFilePath].options.compression = binary ? "STORE" : "DEFLATE";
838
+ const newRelInRels = newRelsRoot.findall("Relationship")[index];
839
+ if (newRelInRels) {
840
+ newRelInRels.attrib.Target = newTarget;
841
+ }
842
+ }).catch((err) => {
843
+ console2.log(err);
844
+ });
845
+ }
846
+ }
847
+ });
848
+ this.archive.file(relArcName, etree.tostring(newRelsRoot, { encoding: "utf-8" }));
849
+ this.archive.files[relArcName].options.compression = binary ? "STORE" : "DEFLATE";
850
+ this.archive.file("[Content_Types].xml", etree.tostring(this.contentTypes, { encoding: "utf-8" }));
851
+ this._rebuild();
852
+ return this;
853
+ }
854
+ /**
855
+ * 部分重建(复制/删除工作表后)
856
+ */
857
+ _rebuild() {
858
+ const order = ["worksheet", "theme", "styles", "sharedStrings"];
859
+ this.workbookRels.findall("*").sort((rel1, rel2) => {
860
+ const index1 = order.indexOf(path.basename(rel1.attrib.Type));
861
+ const index2 = order.indexOf(path.basename(rel2.attrib.Type));
862
+ if (index1 < 0 && index2 >= 0) return 1;
863
+ if (index1 >= 0 && index2 < 0) return -1;
864
+ if (index1 < 0 && index2 < 0) return 0;
865
+ if (index1 + index2 === 0) {
866
+ if (rel1.attrib.Id && rel2.attrib.Id) {
867
+ return rel1.attrib.Id.substring(3) - rel2.attrib.Id.substring(3);
868
+ }
869
+ return rel1._id - rel2._id;
870
+ }
871
+ return index1 - index2;
872
+ }).forEach((item, index) => {
873
+ item.attrib.Id = "rId" + (index + 1);
874
+ });
875
+ this.workbook.findall("sheets/sheet").forEach((item, index) => {
876
+ item.attrib["r:id"] = "rId" + (index + 1);
877
+ item.attrib.sheetId = (index + 1).toString();
878
+ });
879
+ this.archive.file(
880
+ this.prefix + "/_rels/" + path.basename(this.workbookPath) + ".rels",
881
+ etree.tostring(this.workbookRels, { encoding: "utf-8" })
882
+ );
883
+ this.archive.file(this.workbookPath, etree.tostring(this.workbook, { encoding: "utf-8" }));
884
+ this.sheets = this.loadSheets(this.prefix, this.workbook, this.workbookRels);
885
+ }
886
+ /**
887
+ * 从字节数组加载 .xlsx 文件
888
+ */
889
+ async loadTemplate(data) {
890
+ if (Buffer.isBuffer(data)) {
891
+ data = data.toString("binary");
892
+ }
893
+ this.archive = await import_jszip.default.loadAsync(data, { base64: false, checkCRC32: true });
894
+ const text = await this.archive.file("_rels/.rels").async("string");
895
+ const rels = etree.parse(text).getroot();
896
+ const workbookPath = rels.find(`Relationship[@Type='${DOCUMENT_RELATIONSHIP}']`).attrib.Target;
897
+ this.workbookPath = workbookPath;
898
+ this.prefix = path.dirname(workbookPath);
899
+ const workbookText = await this.archive.file(workbookPath).async(`string`);
900
+ this.workbook = etree.parse(workbookText).getroot();
901
+ const refText = await this.archive.file(this.prefix + "/_rels/" + path.basename(workbookPath) + ".rels").async(`string`);
902
+ this.workbookRels = etree.parse(refText).getroot();
903
+ this.sheets = this.loadSheets(this.prefix, this.workbook, this.workbookRels);
904
+ this.calChainRel = this.workbookRels.find(`Relationship[@Type='${CALC_CHAIN_RELATIONSHIP}']`);
905
+ if (this.calChainRel) {
906
+ this.calcChainPath = this.prefix + "/" + this.calChainRel.attrib.Target;
907
+ }
908
+ this.sharedStringsPath = this.prefix + "/" + this.workbookRels.find(`Relationship[@Type='${SHARED_STRINGS_RELATIONSHIP}']`).attrib.Target;
909
+ this.sharedStrings = [];
910
+ this.sharedStringsLookup = {};
911
+ const sharedText = await this.archive.file(this.sharedStringsPath).async(`string`);
912
+ etree.parse(sharedText).getroot().findall("si").forEach((si) => {
913
+ const t = { text: "" };
914
+ si.findall("t").forEach((tmp) => {
915
+ t.text += tmp.text;
916
+ });
917
+ si.findall("r/t").forEach((tmp) => {
918
+ t.text += tmp.text;
919
+ });
920
+ this.sharedStrings.push(t.text);
921
+ this.sharedStringsLookup[t.text] = this.sharedStrings.length - 1;
922
+ });
923
+ const contentTypeText = await this.archive.file("[Content_Types].xml").async(`string`);
924
+ this.contentTypes = etree.parse(contentTypeText).getroot();
925
+ const jpgType = this.contentTypes.find('Default[@Extension="jpg"]');
926
+ if (jpgType === null) {
927
+ etree.SubElement(this.contentTypes, "Default", { "ContentType": "image/png", "Extension": "jpg" });
928
+ }
929
+ }
930
+ /**
931
+ * 使用给定的替换数据对所有工作表进行插值
932
+ */
933
+ async substituteAll(substitutions) {
934
+ const sheets = this.loadSheets(this.prefix, this.workbook, this.workbookRels);
935
+ for (let sheet of sheets) {
936
+ await this.substitute(sheet.id, substitutions);
937
+ }
938
+ }
939
+ /**
940
+ * 使用给定的替换数据对指定工作表进行插值
941
+ */
942
+ async substitute(sheetName, substitutions) {
943
+ const sheet = await this.loadSheet(sheetName);
944
+ this.sheet = sheet;
945
+ const dimension = sheet.root.find("dimension");
946
+ const sheetData = sheet.root.find("sheetData");
947
+ let currentRow = null;
948
+ let totalRowsInserted = 0;
949
+ let totalColumnsInserted = 0;
950
+ const namedTables = await this.loadTables(sheet.root, sheet.filename);
951
+ const rows = [];
952
+ let drawing = null;
953
+ const rels = await this.loadSheetRels(sheet.filename);
954
+ for (let row of sheetData.findall("row")) {
955
+ currentRow = this.getCurrentRow(row, totalRowsInserted);
956
+ row.attrib.r = `${currentRow}`;
957
+ rows.push(row);
958
+ let cells = [];
959
+ let cellsInserted = 0;
960
+ const newTableRows = [];
961
+ const cellsSubstituteTable = [];
962
+ for (let cell of row.findall("c")) {
963
+ let appendCell = true;
964
+ cell.attrib.r = this.getCurrentCell(cell, currentRow, cellsInserted);
965
+ if (cell.attrib.t === "s") {
966
+ const cellValue = cell.find("v");
967
+ const stringIndex = parseInt(cellValue.text.toString(), 10);
968
+ let strValue = this.sharedStrings[stringIndex];
969
+ if (strValue === void 0) {
970
+ break;
971
+ }
972
+ strValue = this.executeBeforeReplaceHook(strValue, substitutions);
973
+ for (let placeholder of this.extractPlaceholders(strValue)) {
974
+ let newCellsInserted = 0;
975
+ let substitution = this.valueGet(substitutions, placeholder);
976
+ const customResult = this.executeReplacers(cell, strValue, placeholder, substitution);
977
+ if (customResult !== void 0) {
978
+ strValue = customResult;
979
+ return;
980
+ }
981
+ if (placeholder.full && placeholder.type === "table" && substitution instanceof Array) {
982
+ if (placeholder.subType === "image" && drawing == null) {
983
+ if (rels) {
984
+ drawing = await this.loadDrawing(sheet.root, sheet.filename, rels.root);
985
+ } else {
986
+ console2.log("Need to implement initRels. Or init this with Excel");
987
+ }
988
+ }
989
+ cellsSubstituteTable.push(cell);
990
+ newCellsInserted = await this.substituteTable(
991
+ row,
992
+ newTableRows,
993
+ cells,
994
+ cell,
995
+ namedTables,
996
+ substitution,
997
+ placeholder,
998
+ drawing
999
+ );
1000
+ if (newCellsInserted !== 0 || substitution.length) {
1001
+ if (substitution.length === 1) {
1002
+ appendCell = true;
1003
+ }
1004
+ if (substitution[0][placeholder.key] instanceof Array) {
1005
+ appendCell = false;
1006
+ }
1007
+ }
1008
+ if (newCellsInserted !== 0) {
1009
+ cellsInserted += newCellsInserted;
1010
+ this.pushRight(this.workbook, sheet.root, cell.attrib.r, newCellsInserted);
1011
+ }
1012
+ }
1013
+ if (placeholder.full && placeholder.type === "normal" && substitution instanceof Array) {
1014
+ appendCell = false;
1015
+ newCellsInserted = this.substituteArray(cells, cell, substitution);
1016
+ if (newCellsInserted !== 0) {
1017
+ cellsInserted += newCellsInserted;
1018
+ this.pushRight(this.workbook, sheet.root, cell.attrib.r, newCellsInserted);
1019
+ }
1020
+ }
1021
+ if (placeholder.type === "image" && placeholder.full) {
1022
+ if (rels != null) {
1023
+ if (drawing == null) {
1024
+ drawing = await this.loadDrawing(sheet.root, sheet.filename, rels.root);
1025
+ }
1026
+ this.substituteImage(cell, strValue, placeholder, substitution, drawing);
1027
+ } else {
1028
+ console2.log("Need to implement initRels. Or init this with Excel");
1029
+ }
1030
+ }
1031
+ if (placeholder.type === "imageincell" && placeholder.full) {
1032
+ await this.substituteImageInCell(cell, substitution);
1033
+ } else {
1034
+ if (placeholder.key) {
1035
+ substitution = this.valueGet(substitutions, placeholder, true);
1036
+ }
1037
+ strValue = this.substituteScalar(cell, strValue, placeholder, substitution);
1038
+ }
1039
+ }
1040
+ strValue = this.executeAfterReplaceHook(strValue, strValue, substitutions);
1041
+ }
1042
+ if (appendCell) {
1043
+ cells.push(cell);
1044
+ }
1045
+ }
1046
+ this.replaceChildren(row, cells);
1047
+ if (cellsInserted !== 0) {
1048
+ this.updateRowSpan(row, cellsInserted);
1049
+ if (cellsInserted > totalColumnsInserted) {
1050
+ totalColumnsInserted = cellsInserted;
1051
+ }
1052
+ }
1053
+ if (newTableRows.length > 0) {
1054
+ if (this.option["moveImages"] && rels) {
1055
+ if (drawing == null) {
1056
+ drawing = await this.loadDrawing(sheet.root, sheet.filename, rels.root);
1057
+ }
1058
+ if (drawing != null) {
1059
+ this.moveAllImages(drawing, row.attrib.r, newTableRows.length);
1060
+ }
1061
+ }
1062
+ const cellsOverTable = row.findall("c").filter(
1063
+ (cell) => !cellsSubstituteTable.includes(cell)
1064
+ );
1065
+ newTableRows.forEach((newRow) => {
1066
+ if (this.option && this.option.substituteAllTableRow) {
1067
+ cellsOverTable.forEach((cellOverTable) => {
1068
+ const newCell = this.cloneElement(cellOverTable);
1069
+ newCell.attrib.r = this.joinRef({
1070
+ row: newRow.attrib.r,
1071
+ col: this.splitRef(newCell.attrib.r).col
1072
+ });
1073
+ newRow.append(newCell);
1074
+ });
1075
+ const newSortRow = newRow.findall("c").sort((a, b) => {
1076
+ const colA = this.splitRef(a.attrib.r).col;
1077
+ const colB = this.splitRef(b.attrib.r).col;
1078
+ return this.charToNum(colA) - this.charToNum(colB);
1079
+ });
1080
+ this.replaceChildren(newRow, newSortRow);
1081
+ }
1082
+ rows.push(newRow);
1083
+ ++totalRowsInserted;
1084
+ });
1085
+ this.pushDown(this.workbook, sheet.root, namedTables, currentRow, newTableRows.length);
1086
+ }
1087
+ }
1088
+ this.replaceChildren(sheetData, rows);
1089
+ this.substituteTableColumnHeaders(namedTables, substitutions);
1090
+ this.substituteHyperlinks(rels, substitutions);
1091
+ if (dimension) {
1092
+ if (totalRowsInserted > 0 || totalColumnsInserted > 0) {
1093
+ const dimensionRange = this.splitRange(dimension.attrib.ref);
1094
+ const dimensionEndRef = this.splitRef(dimensionRange.end);
1095
+ dimensionEndRef.row += totalRowsInserted;
1096
+ dimensionEndRef.col = this.numToChar(this.charToNum(dimensionEndRef.col) + totalColumnsInserted);
1097
+ dimensionRange.end = this.joinRef(dimensionEndRef);
1098
+ dimension.attrib.ref = this.joinRange(dimensionRange);
1099
+ }
1100
+ }
1101
+ sheetData.findall("row").forEach((row) => {
1102
+ row.findall("c").forEach((cell) => {
1103
+ const formulas = cell.findall("f");
1104
+ if (formulas && formulas.length > 0) {
1105
+ cell.findall("v").forEach((v) => {
1106
+ cell.remove(v);
1107
+ });
1108
+ }
1109
+ });
1110
+ });
1111
+ this.archive.file(sheet.filename, etree.tostring(sheet.root, { encoding: "utf-8" }));
1112
+ this.archive.file(this.workbookPath, etree.tostring(this.workbook, { encoding: "utf-8" }));
1113
+ if (rels) {
1114
+ this.archive.file(rels.filename, etree.tostring(rels.root, { encoding: "utf-8" }));
1115
+ }
1116
+ this.writeRichData();
1117
+ this.archive.file("[Content_Types].xml", etree.tostring(this.contentTypes, { encoding: "utf-8" }));
1118
+ if (this.calcChainPath && this.archive.file(this.calcChainPath)) {
1119
+ this.archive.remove(this.calcChainPath);
1120
+ }
1121
+ await this.writeSharedStrings();
1122
+ this.writeTables(namedTables);
1123
+ this.writeDrawing(drawing);
1124
+ }
1125
+ /**
1126
+ * 生成新的二进制 .xlsx 文件
1127
+ */
1128
+ async generate(options) {
1129
+ return await this.archive.generateAsync(options);
1130
+ }
1131
+ /**
1132
+ * 查询占位符合数据值
1133
+ * @param substitutions 数据对象
1134
+ * @param p 占位符
1135
+ * @param full 是否fullKey
1136
+ * @return any
1137
+ */
1138
+ valueGet(substitutions, p, full) {
1139
+ if (this.option.customQueryFunction === void 0) {
1140
+ if (full !== void 0 && typeof full === "boolean" && full && p.key) {
1141
+ return valueDotGet(substitutions, p.name + "." + p.key, p.default || "");
1142
+ }
1143
+ return valueDotGet(substitutions, p.name, p.default || "");
1144
+ }
1145
+ if (full !== void 0 && typeof full === "boolean" && full && p.key && !p.name.endsWith(`.${p.key}`)) {
1146
+ p.name = p.name + "." + p.key;
1147
+ }
1148
+ return this.option.customQueryFunction(substitutions, p);
1149
+ }
1150
+ // ==================== 辅助方法 ====================
1151
+ async writeSharedStrings() {
1152
+ const content = await this.archive.file(this.sharedStringsPath).async("string");
1153
+ const root = etree.parse(content).getroot();
1154
+ const children = root.getchildren();
1155
+ root.delSlice(0, children.length);
1156
+ this.sharedStrings.forEach((string) => {
1157
+ const si = etree.Element("si");
1158
+ const t = etree.Element("t");
1159
+ t.text = string;
1160
+ si.append(t);
1161
+ root.append(si);
1162
+ });
1163
+ root.attrib.count = `${this.sharedStrings.length}`;
1164
+ root.attrib.uniqueCount = `${this.sharedStrings.length}`;
1165
+ this.archive.file(this.sharedStringsPath, etree.tostring(root, { encoding: "utf-8" }));
1166
+ }
1167
+ addSharedString(s) {
1168
+ const idx = this.sharedStrings.length;
1169
+ this.sharedStrings.push(s);
1170
+ this.sharedStringsLookup[s] = idx;
1171
+ return idx;
1172
+ }
1173
+ stringIndex(s) {
1174
+ let idx = this.sharedStringsLookup[s];
1175
+ if (idx === void 0) {
1176
+ idx = this.addSharedString(s);
1177
+ }
1178
+ return idx;
1179
+ }
1180
+ replaceString(oldString, newString) {
1181
+ let idx = this.sharedStringsLookup[oldString];
1182
+ if (idx === void 0) {
1183
+ idx = this.addSharedString(newString);
1184
+ } else {
1185
+ this.sharedStrings[idx] = newString;
1186
+ delete this.sharedStringsLookup[oldString];
1187
+ this.sharedStringsLookup[newString] = idx;
1188
+ }
1189
+ return idx;
1190
+ }
1191
+ loadSheets(prefix, workbook, workbookRels) {
1192
+ const sheets = [];
1193
+ for (const sheet of workbook.findall("sheets/sheet")) {
1194
+ const sheetId = sheet.attrib.sheetId;
1195
+ const relId = sheet.attrib["r:id"];
1196
+ const relationship = workbookRels.find(`Relationship[@Id='${relId}']`);
1197
+ const filename = prefix + "/" + relationship.attrib.Target;
1198
+ sheets.push({
1199
+ root: sheet,
1200
+ filename,
1201
+ name: sheet.attrib.name,
1202
+ id: parseInt(sheetId, 10)
1203
+ });
1204
+ }
1205
+ return sheets;
1206
+ }
1207
+ async loadSheet(sheet) {
1208
+ let info = null;
1209
+ for (let i = 0; i < this.sheets.length; ++i) {
1210
+ if (typeof sheet === "number" && this.sheets[i].id === sheet || this.sheets[i].name === sheet) {
1211
+ info = this.sheets[i];
1212
+ break;
1213
+ }
1214
+ }
1215
+ if (info === null && typeof sheet === "number") {
1216
+ info = this.sheets[sheet - 1];
1217
+ }
1218
+ if (info === null) {
1219
+ throw new Error("Sheet " + sheet + " not found");
1220
+ }
1221
+ const content = await this.archive.file(info.filename).async("string");
1222
+ return {
1223
+ filename: info.filename,
1224
+ name: info.name,
1225
+ id: info.id,
1226
+ root: etree.parse(content).getroot()
1227
+ };
1228
+ }
1229
+ async loadSheetRels(sheetFilename) {
1230
+ const sheetDirectory = path.dirname(sheetFilename);
1231
+ const sheetName = path.basename(sheetFilename);
1232
+ const relsFilename = path.join(sheetDirectory, "_rels", sheetName + ".rels").replace(/\\/g, "/");
1233
+ const relsFile = this.archive.file(relsFilename);
1234
+ if (relsFile === null) {
1235
+ return this.initSheetRels(sheetFilename);
1236
+ }
1237
+ const content = await relsFile.async("string");
1238
+ return {
1239
+ filename: relsFilename,
1240
+ root: etree.parse(content).getroot()
1241
+ };
1242
+ }
1243
+ initSheetRels(sheetFilename) {
1244
+ const sheetDirectory = path.dirname(sheetFilename);
1245
+ const sheetName = path.basename(sheetFilename);
1246
+ const relsFilename = path.join(sheetDirectory, "_rels", sheetName + ".rels").replace(/\\/g, "/");
1247
+ const element = etree.Element;
1248
+ const ElementTree2 = etree.ElementTree;
1249
+ const root = element("Relationships");
1250
+ root.set("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships");
1251
+ const relsEtree = new ElementTree2(root);
1252
+ return {
1253
+ filename: relsFilename,
1254
+ root: relsEtree.getroot()
1255
+ };
1256
+ }
1257
+ async loadDrawing(sheet, sheetFilename, rels) {
1258
+ const sheetDirectory = path.dirname(sheetFilename);
1259
+ const drawing = { filename: "", root: null };
1260
+ const drawingPart = sheet.find("drawing");
1261
+ if (drawingPart === null) {
1262
+ return this.initDrawing(sheet, rels);
1263
+ }
1264
+ const relationshipId = drawingPart.attrib["r:id"];
1265
+ const target = rels.find(`Relationship[@Id='${relationshipId}']`).attrib.Target;
1266
+ const drawingFilename = path.join(sheetDirectory, target).replace(/\\/g, "/");
1267
+ const drawContent = await this.archive.file(drawingFilename).async("string");
1268
+ const drawingTree = etree.parse(drawContent);
1269
+ drawing.filename = drawingFilename;
1270
+ drawing.root = drawingTree.getroot();
1271
+ drawing.relFilename = path.dirname(drawingFilename) + "/_rels/" + path.basename(drawingFilename) + ".rels";
1272
+ const relFile = this.archive.file(drawing.relFilename);
1273
+ if (relFile === null) {
1274
+ drawing.relRoot = etree.Element("Relationships");
1275
+ drawing.relRoot.set("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships");
1276
+ } else {
1277
+ const relContent = await relFile.async("string");
1278
+ drawing.relRoot = etree.parse(relContent).getroot();
1279
+ }
1280
+ return drawing;
1281
+ }
1282
+ addContentType(partName, contentType) {
1283
+ etree.SubElement(this.contentTypes, "Override", { "ContentType": contentType, "PartName": partName });
1284
+ }
1285
+ initDrawing(sheet, rels) {
1286
+ const maxId = this.findMaxId(rels, "Relationship", "Id", /rId(\d*)/);
1287
+ const rel = etree.SubElement(rels, "Relationship");
1288
+ sheet.insert(sheet._children.length, etree.Element("drawing", { "r:id": "rId" + maxId }));
1289
+ rel.set("Id", "rId" + maxId);
1290
+ rel.set("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing");
1291
+ const drawing = {};
1292
+ const drawingFilename = "drawing" + this.findMaxFileId(/xl\/drawings\/drawing\d*\.xml/, /drawing(\d*)\.xml/) + ".xml";
1293
+ rel.set("Target", "../drawings/" + drawingFilename);
1294
+ drawing.root = etree.Element("xdr:wsDr");
1295
+ drawing.root.set("xmlns:xdr", "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing");
1296
+ drawing.root.set("xmlns:a", "http://schemas.openxmlformats.org/drawingml/2006/main");
1297
+ drawing.filename = "xl/drawings/" + drawingFilename;
1298
+ drawing.relFilename = "xl/drawings/_rels/" + drawingFilename + ".rels";
1299
+ drawing.relRoot = etree.Element("Relationships");
1300
+ drawing.relRoot.set("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships");
1301
+ this.addContentType("/" + drawing.filename, "application/vnd.openxmlformats-officedocument.drawing+xml");
1302
+ return drawing;
1303
+ }
1304
+ writeDrawing(drawing) {
1305
+ if (drawing !== null) {
1306
+ this.archive.file(drawing.filename, etree.tostring(drawing.root, { encoding: "utf-8" }));
1307
+ this.archive.file(drawing.relFilename, etree.tostring(drawing.relRoot, { encoding: "utf-8" }));
1308
+ }
1309
+ }
1310
+ moveAllImages(drawing, fromRow, nbRow) {
1311
+ drawing.root.getchildren().forEach((drawElement) => {
1312
+ if (drawElement.tag == "xdr:twoCellAnchor") {
1313
+ this._moveTwoCellAnchor(drawElement, fromRow, nbRow);
1314
+ }
1315
+ });
1316
+ }
1317
+ _moveTwoCellAnchor(drawingElement, fromRow, nbRow) {
1318
+ const _moveImage = (drawingElement2, fromRow2, nbRow2) => {
1319
+ let num;
1320
+ if (typeof nbRow2 === "string") {
1321
+ num = Number.parseInt(nbRow2, 10);
1322
+ } else {
1323
+ num = nbRow2;
1324
+ }
1325
+ drawingElement2.find("xdr:from").find("xdr:row").text = Number.parseInt(drawingElement2.find("xdr:from").find("xdr:row").text, 10) + num;
1326
+ drawingElement2.find("xdr:to").find("xdr:row").text = Number.parseInt(drawingElement2.find("xdr:to").find("xdr:row").text, 10) + num;
1327
+ };
1328
+ if (this.option["moveSameLineImages"]) {
1329
+ if (parseInt(drawingElement.find("xdr:from").find("xdr:row").text) + 1 >= parseInt(fromRow)) {
1330
+ _moveImage(drawingElement, fromRow, nbRow);
1331
+ }
1332
+ } else {
1333
+ if (parseInt(drawingElement.find("xdr:from").find("xdr:row").text) + 1 > parseInt(fromRow)) {
1334
+ _moveImage(drawingElement, fromRow, nbRow);
1335
+ }
1336
+ }
1337
+ }
1338
+ async loadTables(sheet, sheetFilename) {
1339
+ const sheetDirectory = path.dirname(sheetFilename);
1340
+ const sheetName = path.basename(sheetFilename);
1341
+ const relsFilename = sheetDirectory + "/_rels/" + sheetName + ".rels";
1342
+ const relsFile = this.archive.file(relsFilename);
1343
+ const tables = [];
1344
+ if (relsFile === null) {
1345
+ return tables;
1346
+ }
1347
+ const relsContent = await relsFile.async("string");
1348
+ const rels = etree.parse(relsContent).getroot();
1349
+ for (let tablePart of sheet.findall("tableParts/tablePart")) {
1350
+ const relationshipId = tablePart.attrib["r:id"];
1351
+ const target = rels.find(`Relationship[@Id='${relationshipId}']`).attrib.Target;
1352
+ const tableFilename = target.replace("..", this.prefix);
1353
+ const content = await this.archive.file(tableFilename).async("string");
1354
+ const tableTree = etree.parse(content);
1355
+ tables.push({
1356
+ filename: tableFilename,
1357
+ root: tableTree.getroot()
1358
+ });
1359
+ }
1360
+ return tables;
1361
+ }
1362
+ writeTables(tables) {
1363
+ tables.forEach((namedTable) => {
1364
+ this.archive.file(namedTable.filename, etree.tostring(namedTable.root, { encoding: "utf-8" }));
1365
+ });
1366
+ }
1367
+ substituteHyperlinks(rels, substitutions) {
1368
+ if (rels === null) {
1369
+ return;
1370
+ }
1371
+ const relationships = rels.root._children;
1372
+ relationships.forEach((relationship) => {
1373
+ if (relationship.attrib.Type === HYPERLINK_RELATIONSHIP) {
1374
+ let target = relationship.attrib.Target;
1375
+ target = decodeURI(decodeURI(target));
1376
+ this.extractPlaceholders(target).forEach((placeholder) => {
1377
+ const substitution = substitutions[placeholder.name];
1378
+ if (substitution === void 0) {
1379
+ return;
1380
+ }
1381
+ target = target.replace(placeholder.placeholder, this.stringify(substitution));
1382
+ relationship.attrib.Target = encodeURI(target);
1383
+ });
1384
+ }
1385
+ });
1386
+ }
1387
+ substituteTableColumnHeaders(tables, substitutions) {
1388
+ tables.forEach((table) => {
1389
+ const root = table.root;
1390
+ const columns = root.find("tableColumns");
1391
+ const autoFilter = root.find("autoFilter");
1392
+ const tableRange = this.splitRange(root.attrib.ref);
1393
+ let idx = 0;
1394
+ let inserted = 0;
1395
+ const newColumns = [];
1396
+ columns.findall("tableColumn").forEach((col) => {
1397
+ ++idx;
1398
+ col.attrib.id = Number(idx).toString();
1399
+ newColumns.push(col);
1400
+ let name = col.attrib.name;
1401
+ this.extractPlaceholders(name).forEach((placeholder) => {
1402
+ const substitution = substitutions[placeholder.name];
1403
+ if (substitution === void 0) {
1404
+ return;
1405
+ }
1406
+ if (placeholder.full && placeholder.type === "normal" && substitution instanceof Array) {
1407
+ substitution.forEach((element, i) => {
1408
+ let newCol = col;
1409
+ if (i > 0) {
1410
+ newCol = this.cloneElement(newCol);
1411
+ newCol.attrib.id = Number(++idx).toString();
1412
+ newColumns.push(newCol);
1413
+ ++inserted;
1414
+ tableRange.end = this.nextCol(tableRange.end);
1415
+ }
1416
+ newCol.attrib.name = this.stringify(element);
1417
+ });
1418
+ } else {
1419
+ name = name.replace(placeholder.placeholder, this.stringify(substitution));
1420
+ col.attrib.name = name;
1421
+ }
1422
+ });
1423
+ });
1424
+ this.replaceChildren(columns, newColumns);
1425
+ if (inserted > 0) {
1426
+ columns.attrib.count = Number(idx).toString();
1427
+ root.attrib.ref = this.joinRange(tableRange);
1428
+ if (autoFilter !== null) {
1429
+ autoFilter.attrib.ref = this.joinRange(tableRange);
1430
+ }
1431
+ }
1432
+ const tableRoot = table.root;
1433
+ const tableRange2 = this.splitRange(tableRoot.attrib.ref);
1434
+ const tableStart = this.splitRef(tableRange2.start);
1435
+ const tableEnd = this.splitRef(tableRange2.end);
1436
+ if (tableRoot.attrib.totalsRowCount) {
1437
+ const autoFilter2 = tableRoot.find("autoFilter");
1438
+ if (autoFilter2 !== null) {
1439
+ autoFilter2.attrib.ref = this.joinRange({
1440
+ start: this.joinRef(tableStart),
1441
+ end: this.joinRef(tableEnd)
1442
+ });
1443
+ }
1444
+ ++tableEnd.row;
1445
+ tableRoot.attrib.ref = this.joinRange({
1446
+ start: this.joinRef(tableStart),
1447
+ end: this.joinRef(tableEnd)
1448
+ });
1449
+ }
1450
+ });
1451
+ }
1452
+ /**
1453
+ * 提取字符串中可能存在的占位符标记
1454
+ * 支持扩展:自定义正则表达式和自定义提取器
1455
+ */
1456
+ extractPlaceholders(inputString) {
1457
+ if (this.option.customPlaceholderExtractor) {
1458
+ return this.option.customPlaceholderExtractor(inputString, this.option);
1459
+ }
1460
+ return defaultExtractPlaceholders(inputString, this.option);
1461
+ }
1462
+ splitRef(ref) {
1463
+ const match = ref.match(/(?:(.+)!)?(\$)?([A-Z]+)?(\$)?([0-9]+)/);
1464
+ return {
1465
+ table: match && match[1] || null,
1466
+ colAbsolute: Boolean(match && match[2]),
1467
+ col: match && match[3] || "",
1468
+ rowAbsolute: Boolean(match && match[4]),
1469
+ row: parseInt(match && match[5], 10)
1470
+ };
1471
+ }
1472
+ joinRef(ref) {
1473
+ return (ref.table ? ref.table + "!" : "") + (ref.colAbsolute ? "$" : "") + ref.col.toUpperCase() + (ref.rowAbsolute ? "$" : "") + Number(ref.row).toString();
1474
+ }
1475
+ nextCol(ref) {
1476
+ ref = ref.toUpperCase();
1477
+ return ref.replace(/[A-Z]+/, (match) => {
1478
+ return this.numToChar(this.charToNum(match) + 1);
1479
+ });
1480
+ }
1481
+ nextRow(ref) {
1482
+ ref = ref.toUpperCase();
1483
+ return ref.replace(/[0-9]+/, (match) => {
1484
+ return (parseInt(match, 10) + 1).toString();
1485
+ });
1486
+ }
1487
+ charToNum(str) {
1488
+ let num = 0;
1489
+ if (typeof str === "string") {
1490
+ for (let idx = str.length - 1, iteration = 0; idx >= 0; --idx, ++iteration) {
1491
+ const thisChar = str.charCodeAt(idx) - 64;
1492
+ const multiplier = Math.pow(26, iteration);
1493
+ num += multiplier * thisChar;
1494
+ }
1495
+ } else {
1496
+ num = str;
1497
+ }
1498
+ return num;
1499
+ }
1500
+ numToChar(num) {
1501
+ let str = "";
1502
+ for (let i = 0; num > 0; ++i) {
1503
+ let remainder = num % 26;
1504
+ let charCode = remainder + 64;
1505
+ num = (num - remainder) / 26;
1506
+ if (remainder === 0) {
1507
+ charCode = 90;
1508
+ --num;
1509
+ }
1510
+ str = String.fromCharCode(charCode) + str;
1511
+ }
1512
+ return str;
1513
+ }
1514
+ generateUUID() {
1515
+ const hexDigits = "0123456789ABCDEF";
1516
+ let uuid = "{";
1517
+ for (let i = 0; i < 36; i++) {
1518
+ if (i === 8 || i === 13 || i === 18 || i === 23) {
1519
+ uuid += "-";
1520
+ } else {
1521
+ uuid += hexDigits[Math.floor(Math.random() * 16)];
1522
+ }
1523
+ }
1524
+ uuid += "}";
1525
+ return uuid;
1526
+ }
1527
+ isRange(ref) {
1528
+ return ref.indexOf(":") !== -1;
1529
+ }
1530
+ isWithin(ref, startRef, endRef) {
1531
+ const start = this.splitRef(startRef);
1532
+ const end = this.splitRef(endRef);
1533
+ const target = this.splitRef(ref);
1534
+ start.col = `${this.charToNum(start.col)}`;
1535
+ end.col = `${this.charToNum(end.col)}`;
1536
+ target.col = `${this.charToNum(target.col)}`;
1537
+ return start.row <= target.row && target.row <= end.row && start.col <= target.col && target.col <= end.col;
1538
+ }
1539
+ /**
1540
+ * 将任意类型的值转换为字符串
1541
+ * 支持扩展:使用自定义格式化器
1542
+ */
1543
+ stringify(value, placeholder, key) {
1544
+ if (placeholder) {
1545
+ return this.executeFormatters(value, placeholder, key);
1546
+ }
1547
+ if (value instanceof Date) {
1548
+ return Number(value.getTime() / (1e3 * 60 * 60 * 24) + 25569).toString();
1549
+ } else if (typeof value === "number" || typeof value === "boolean") {
1550
+ return Number(value).toString();
1551
+ } else if (typeof value === "string") {
1552
+ return String(value).toString();
1553
+ }
1554
+ return "";
1555
+ }
1556
+ insertCellValue(cell, substitution) {
1557
+ const cellValue = cell.find("v");
1558
+ const stringify = this.stringify(substitution);
1559
+ if (typeof substitution === "string" && substitution[0] === "=") {
1560
+ const formula = etree.Element("f");
1561
+ formula.text = substitution.substring(1);
1562
+ cell.insert(1, formula);
1563
+ delete cell.attrib.t;
1564
+ return formula.text.toString();
1565
+ }
1566
+ if (typeof substitution === "number" || substitution instanceof Date) {
1567
+ delete cell.attrib.t;
1568
+ cellValue.text = stringify;
1569
+ } else if (typeof substitution === "boolean") {
1570
+ cell.attrib.t = "b";
1571
+ cellValue.text = stringify;
1572
+ } else {
1573
+ cell.attrib.t = "s";
1574
+ cellValue.text = Number(this.stringIndex(stringify)).toString();
1575
+ }
1576
+ return stringify;
1577
+ }
1578
+ /**
1579
+ * 执行单个值的替换
1580
+ * 支持扩展:调用自定义替换器
1581
+ */
1582
+ substituteScalar(cell, string, placeholder, substitution) {
1583
+ const customResult = this.executeReplacers(cell, string, placeholder, substitution);
1584
+ if (customResult !== void 0) {
1585
+ if (placeholder.full) {
1586
+ return this.insertCellValue(cell, customResult);
1587
+ } else {
1588
+ cell.attrib.t = "s";
1589
+ return this.insertCellValue(cell, customResult);
1590
+ }
1591
+ }
1592
+ if (placeholder.full) {
1593
+ return this.insertCellValue(cell, substitution);
1594
+ } else {
1595
+ const newString = string.replace(placeholder.placeholder, this.stringify(substitution, placeholder));
1596
+ cell.attrib.t = "s";
1597
+ return this.insertCellValue(cell, newString);
1598
+ }
1599
+ }
1600
+ substituteArray(cells, cell, substitution) {
1601
+ let newCellsInserted = -1;
1602
+ let currentCell = cell.attrib.r;
1603
+ substitution.forEach((element) => {
1604
+ ++newCellsInserted;
1605
+ if (newCellsInserted > 0) {
1606
+ currentCell = this.nextCol(currentCell);
1607
+ }
1608
+ const newCell = this.cloneElement(cell);
1609
+ this.insertCellValue(newCell, element);
1610
+ newCell.attrib.r = currentCell;
1611
+ cells.push(newCell);
1612
+ });
1613
+ return newCellsInserted;
1614
+ }
1615
+ async substituteTable(row, newTableRows, cells, cell, namedTables, substitution, placeholder, drawing) {
1616
+ let newCellsInserted = 0;
1617
+ if (substitution.length === 0) {
1618
+ delete cell.attrib.t;
1619
+ this.replaceChildren(cell, []);
1620
+ } else {
1621
+ const parentTables = namedTables.filter((namedTable) => {
1622
+ const range = this.splitRange(namedTable.root.attrib.ref);
1623
+ return this.isWithin(cell.attrib.r, range.start, range.end);
1624
+ });
1625
+ for (const [idx, element] of substitution.entries()) {
1626
+ let newRow;
1627
+ let newCell;
1628
+ let newCellsInsertedOnNewRow = 0;
1629
+ const newCells = [];
1630
+ const value = this.valueGet(element, placeholder);
1631
+ if (idx === 0) {
1632
+ if (value instanceof Array) {
1633
+ newCellsInserted = this.substituteArray(cells, cell, value);
1634
+ } else if (placeholder.subType == "image" && value != "") {
1635
+ this.substituteImage(cell, placeholder.placeholder, placeholder, value, drawing);
1636
+ } else if (placeholder.subType === "imageincell" && value != "") {
1637
+ await this.substituteImageInCell(cell, value);
1638
+ } else {
1639
+ const customResult = this.executeReplacers(cell, "", placeholder, value);
1640
+ if (customResult !== void 0) {
1641
+ this.insertCellValue(cell, customResult);
1642
+ } else {
1643
+ this.insertCellValue(cell, value);
1644
+ }
1645
+ }
1646
+ } else {
1647
+ if (idx - 1 < newTableRows.length) {
1648
+ newRow = newTableRows[idx - 1];
1649
+ } else {
1650
+ newRow = this.cloneElement(row, false);
1651
+ newRow.attrib.r = this.getCurrentRow(row, newTableRows.length + 1);
1652
+ newTableRows.push(newRow);
1653
+ }
1654
+ newCell = this.cloneElement(cell);
1655
+ newCell.attrib.r = this.joinRef({
1656
+ row: newRow.attrib.r,
1657
+ col: this.splitRef(newCell.attrib.r).col
1658
+ });
1659
+ if (value instanceof Array) {
1660
+ newCellsInsertedOnNewRow = this.substituteArray(newCells, newCell, value);
1661
+ newCells.forEach((nc) => {
1662
+ newRow.append(nc);
1663
+ });
1664
+ this.updateRowSpan(newRow, newCellsInsertedOnNewRow);
1665
+ } else if (placeholder.subType == "image" && value != "") {
1666
+ this.substituteImage(newCell, placeholder.placeholder, placeholder, value, drawing);
1667
+ } else if (placeholder.subType === "imageincell" && value != "") {
1668
+ await this.substituteImageInCell(newCell, value);
1669
+ newRow.append(newCell);
1670
+ } else {
1671
+ const customResult = this.executeReplacers(newCell, "", placeholder, value);
1672
+ if (customResult !== void 0) {
1673
+ this.insertCellValue(newCell, customResult);
1674
+ } else {
1675
+ this.insertCellValue(newCell, value);
1676
+ }
1677
+ newRow.append(newCell);
1678
+ }
1679
+ const mergeCell = this.sheet.root.findall("mergeCells/mergeCell").find((c) => this.splitRange(c.attrib.ref).start === cell.attrib.r);
1680
+ const isMergeCell = mergeCell != null;
1681
+ if (isMergeCell) {
1682
+ const originalMergeRange = this.splitRange(mergeCell.attrib.ref);
1683
+ const originalMergeStart = this.splitRef(originalMergeRange.start);
1684
+ const originalMergeEnd = this.splitRef(originalMergeRange.end);
1685
+ for (let column = this.charToNum(originalMergeStart.col) + 1; column <= this.charToNum(originalMergeEnd.col); column++) {
1686
+ const data = this.sheet.root.find("sheetData");
1687
+ const children = data.getchildren();
1688
+ const originalRow = children.find((f) => f.attrib.r == originalMergeStart.row);
1689
+ const col = this.numToChar(column);
1690
+ const originalCell = originalRow.getchildren().find((f) => f.attrib.r.startsWith(col));
1691
+ const additionalCell = this.cloneElement(originalCell);
1692
+ additionalCell.attrib.r = this.joinRef({
1693
+ row: newRow.attrib.r,
1694
+ col: this.numToChar(column)
1695
+ });
1696
+ newRow.append(additionalCell);
1697
+ }
1698
+ }
1699
+ parentTables.forEach((namedTable) => {
1700
+ const tableRoot = namedTable.root;
1701
+ const autoFilter = tableRoot.find("autoFilter");
1702
+ const range = this.splitRange(tableRoot.attrib.ref);
1703
+ if (!this.isWithin(newCell.attrib.r, range.start, range.end)) {
1704
+ range.end = this.nextRow(range.end);
1705
+ tableRoot.attrib.ref = this.joinRange(range);
1706
+ if (autoFilter !== null) {
1707
+ autoFilter.attrib.ref = tableRoot.attrib.ref;
1708
+ }
1709
+ }
1710
+ });
1711
+ }
1712
+ }
1713
+ }
1714
+ return newCellsInserted;
1715
+ }
1716
+ async initRichData() {
1717
+ if (!this.richDataIsInit) {
1718
+ const _relsrichValueRel = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1719
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
1720
+ </Relationships>`;
1721
+ const rdrichvalue = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1722
+ <rvData xmlns="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata" count="0">
1723
+ </rvData>`;
1724
+ const rdrichvaluestructure = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1725
+ <rvStructures xmlns="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata" count="1">
1726
+ <s t="_localImage">
1727
+ <k n="_rvRel:LocalImageIdentifier" t="i"/>
1728
+ <k n="CalcOrigin" t="i"/>
1729
+ </s>
1730
+ </rvStructures>`;
1731
+ const rdRichValueTypes = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1732
+ <rvTypesInfo xmlns="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata2"
1733
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x"
1734
+ xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
1735
+ <global>
1736
+ <keyFlags>
1737
+ <key name="_Self">
1738
+ <flag name="ExcludeFromFile" value="1"/>
1739
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1740
+ </key>
1741
+ <key name="_DisplayString">
1742
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1743
+ </key>
1744
+ <key name="_Flags">
1745
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1746
+ </key>
1747
+ <key name="_Format">
1748
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1749
+ </key>
1750
+ <key name="_SubLabel">
1751
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1752
+ </key>
1753
+ <key name="_Attribution">
1754
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1755
+ </key>
1756
+ <key name="_Icon">
1757
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1758
+ </key>
1759
+ <key name="_Display">
1760
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1761
+ </key>
1762
+ <key name="_CanonicalPropertyNames">
1763
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1764
+ </key>
1765
+ <key name="_ClassificationId">
1766
+ <flag name="ExcludeFromCalcComparison" value="1"/>
1767
+ </key>
1768
+ </keyFlags>
1769
+ </global>
1770
+ </rvTypesInfo>`;
1771
+ const richValueRel = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1772
+ <richValueRels xmlns="http://schemas.microsoft.com/office/spreadsheetml/2022/richvaluerel"
1773
+ xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
1774
+ </richValueRels>`;
1775
+ const metadata = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1776
+ <metadata xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
1777
+ xmlns:xlrd="http://schemas.microsoft.com/office/spreadsheetml/2017/richdata">
1778
+ <metadataTypes count="1">
1779
+ <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"/>
1780
+ </metadataTypes>
1781
+ <futureMetadata name="XLRICHVALUE" count="0">
1782
+ </futureMetadata>
1783
+ <valueMetadata count="0">
1784
+ </valueMetadata>
1785
+ </metadata>`;
1786
+ const _relsrichValueRelFileName = "xl/richData/_rels/richValueRel.xml.rels";
1787
+ const rdrichvalueFileName = "xl/richData/rdrichvalue.xml";
1788
+ const rdrichvaluestructureFileName = "xl/richData/rdrichvaluestructure.xml";
1789
+ const rdRichValueTypesFileName = "xl/richData/rdRichValueTypes.xml";
1790
+ const richValueRelFileName = "xl/richData/richValueRel.xml";
1791
+ const metadataFileName = "xl/metadata.xml";
1792
+ this._relsrichValueRel = etree.parse(_relsrichValueRel).getroot();
1793
+ this.rdrichvalue = etree.parse(rdrichvalue).getroot();
1794
+ this.rdrichvaluestructure = etree.parse(rdrichvaluestructure).getroot();
1795
+ this.rdRichValueTypes = etree.parse(rdRichValueTypes).getroot();
1796
+ this.richValueRel = etree.parse(richValueRel).getroot();
1797
+ this.metadata = etree.parse(metadata).getroot();
1798
+ if (this.archive.file(_relsrichValueRelFileName)) {
1799
+ const content = await this.archive.file(_relsrichValueRelFileName).async("string");
1800
+ this._relsrichValueRel = etree.parse(content).getroot();
1801
+ }
1802
+ if (this.archive.file(rdrichvalueFileName)) {
1803
+ const content = await this.archive.file(rdrichvalueFileName).async("string");
1804
+ this.rdrichvalue = etree.parse(content).getroot();
1805
+ }
1806
+ if (this.archive.file(rdrichvaluestructureFileName)) {
1807
+ const content = await this.archive.file(rdrichvaluestructureFileName).async("string");
1808
+ this.rdrichvaluestructure = etree.parse(content).getroot();
1809
+ }
1810
+ if (this.archive.file(rdRichValueTypesFileName)) {
1811
+ const content = await this.archive.file(rdRichValueTypesFileName).async("string");
1812
+ this.rdRichValueTypes = etree.parse(content).getroot();
1813
+ }
1814
+ if (this.archive.file(richValueRelFileName)) {
1815
+ const content = await this.archive.file(richValueRelFileName).async("string");
1816
+ this.richValueRel = etree.parse(content).getroot();
1817
+ }
1818
+ if (this.archive.file(metadataFileName)) {
1819
+ const content = await this.archive.file(metadataFileName).async("string");
1820
+ this.metadata = etree.parse(content).getroot();
1821
+ }
1822
+ this.richDataIsInit = true;
1823
+ }
1824
+ }
1825
+ writeRichDataAlreadyExist(element, elementSearchName, attributeName, attributeValue) {
1826
+ for (const e of element.findall(elementSearchName)) {
1827
+ if (e.attrib[attributeName] == attributeValue) {
1828
+ return true;
1829
+ }
1830
+ }
1831
+ return false;
1832
+ }
1833
+ writeRichData() {
1834
+ if (this.richDataIsInit) {
1835
+ const _relsrichValueRelFileName = "xl/richData/_rels/richValueRel.xml.rels";
1836
+ const rdrichvalueFileName = "xl/richData/rdrichvalue.xml";
1837
+ const rdrichvaluestructureFileName = "xl/richData/rdrichvaluestructure.xml";
1838
+ const rdRichValueTypesFileName = "xl/richData/rdRichValueTypes.xml";
1839
+ const richValueRelFileName = "xl/richData/richValueRel.xml";
1840
+ const metadataFileName = "xl/metadata.xml";
1841
+ const options = { encoding: "utf-8" };
1842
+ this.archive.file(_relsrichValueRelFileName, etree.tostring(this._relsrichValueRel, options));
1843
+ this.archive.file(rdrichvalueFileName, etree.tostring(this.rdrichvalue, options));
1844
+ this.archive.file(rdrichvaluestructureFileName, etree.tostring(this.rdrichvaluestructure, options));
1845
+ this.archive.file(rdRichValueTypesFileName, etree.tostring(this.rdRichValueTypes, options));
1846
+ this.archive.file(richValueRelFileName, etree.tostring(this.richValueRel, options));
1847
+ this.archive.file(metadataFileName, etree.tostring(this.metadata, options));
1848
+ const broadsideMax = this.findMaxId(this.workbookRels, "Relationship", "Id", /rId(\d*)/);
1849
+ let _rel;
1850
+ if (!this.writeRichDataAlreadyExist(this.workbookRels, "Relationship", "Target", "richData/rdrichvaluestructure.xml")) {
1851
+ _rel = etree.SubElement(this.workbookRels, "Relationship");
1852
+ _rel.set("Id", "rId" + broadsideMax);
1853
+ _rel.set("Type", "http://schemas.microsoft.com/office/2017/06/relationships/rdRichValueStructure");
1854
+ _rel.set("Target", "richData/rdrichvaluestructure.xml");
1855
+ }
1856
+ if (!this.writeRichDataAlreadyExist(this.workbookRels, "Relationship", "Target", "richData/rdrichvalue.xml")) {
1857
+ _rel = etree.SubElement(this.workbookRels, "Relationship");
1858
+ _rel.set("Id", "rId" + (broadsideMax + 1));
1859
+ _rel.set("Type", "http://schemas.microsoft.com/office/2017/06/relationships/rdRichValue");
1860
+ _rel.set("Target", "richData/rdrichvalue.xml");
1861
+ }
1862
+ if (!this.writeRichDataAlreadyExist(this.workbookRels, "Relationship", "Target", "richData/richValueRel.xml")) {
1863
+ _rel = etree.SubElement(this.workbookRels, "Relationship");
1864
+ _rel.set("Id", "rId" + (broadsideMax + 2));
1865
+ _rel.set("Type", "http://schemas.microsoft.com/office/2022/10/relationships/richValueRel");
1866
+ _rel.set("Target", "richData/richValueRel.xml");
1867
+ }
1868
+ if (!this.writeRichDataAlreadyExist(this.workbookRels, "Relationship", "Target", "metadata.xml")) {
1869
+ _rel = etree.SubElement(this.workbookRels, "Relationship");
1870
+ _rel.set("Id", "rId" + (broadsideMax + 3));
1871
+ _rel.set("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata");
1872
+ _rel.set("Target", "metadata.xml");
1873
+ }
1874
+ if (!this.writeRichDataAlreadyExist(this.workbookRels, "Relationship", "Target", "richData/rdRichValueTypes.xml")) {
1875
+ _rel = etree.SubElement(this.workbookRels, "Relationship");
1876
+ _rel.set("Id", "rId" + (broadsideMax + 4));
1877
+ _rel.set("Type", "http://schemas.microsoft.com/office/2017/06/relationships/rdRichValueTypes");
1878
+ _rel.set("Target", "richData/rdRichValueTypes.xml");
1879
+ }
1880
+ if (!this.writeRichDataAlreadyExist(this.contentTypes, "Override", "PartName", "/xl/metadata.xml")) {
1881
+ let ctOverride = etree.SubElement(this.contentTypes, "Override");
1882
+ ctOverride.set("PartName", "/xl/metadata.xml");
1883
+ ctOverride.set("ContentType", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml");
1884
+ }
1885
+ if (!this.writeRichDataAlreadyExist(this.contentTypes, "Override", "PartName", "/xl/richData/richValueRel.xml")) {
1886
+ let ctOverride = etree.SubElement(this.contentTypes, "Override");
1887
+ ctOverride.set("PartName", "/xl/richData/richValueRel.xml");
1888
+ ctOverride.set("ContentType", "application/vnd.ms-excel.richvaluerel+xml");
1889
+ }
1890
+ if (!this.writeRichDataAlreadyExist(this.contentTypes, "Override", "PartName", "/xl/richData/rdrichvalue.xml")) {
1891
+ let ctOverride = etree.SubElement(this.contentTypes, "Override");
1892
+ ctOverride.set("PartName", "/xl/richData/rdrichvalue.xml");
1893
+ ctOverride.set("ContentType", "application/vnd.ms-excel.rdrichvalue+xml");
1894
+ }
1895
+ if (!this.writeRichDataAlreadyExist(this.contentTypes, "Override", "PartName", "/xl/richData/rdrichvaluestructure.xml")) {
1896
+ let ctOverride = etree.SubElement(this.contentTypes, "Override");
1897
+ ctOverride.set("PartName", "/xl/richData/rdrichvaluestructure.xml");
1898
+ ctOverride.set("ContentType", "application/vnd.ms-excel.rdrichvaluestructure+xml");
1899
+ }
1900
+ if (!this.writeRichDataAlreadyExist(this.contentTypes, "Override", "PartName", "/xl/richData/rdRichValueTypes.xml")) {
1901
+ let ctOverride = etree.SubElement(this.contentTypes, "Override");
1902
+ ctOverride.set("PartName", "/xl/richData/rdRichValueTypes.xml");
1903
+ ctOverride.set("ContentType", "application/vnd.ms-excel.rdrichvaluetypes+xml");
1904
+ }
1905
+ this._rebuild();
1906
+ }
1907
+ }
1908
+ async substituteImageInCell(cell, substitution) {
1909
+ if (substitution == null || substitution == "") {
1910
+ this.insertCellValue(cell, "");
1911
+ return true;
1912
+ }
1913
+ await this.initRichData();
1914
+ const maxFildId = this.findMaxFileId(/xl\/media\/image\d*\..*/, /image(\d*)\./);
1915
+ const fileExtension = "jpg";
1916
+ try {
1917
+ substitution = this.imageToBuffer(substitution);
1918
+ } catch (error) {
1919
+ if (this.option && this.option.handleImageError && typeof this.option.handleImageError === "function") {
1920
+ this.option.handleImageError(substitution, error);
1921
+ } else {
1922
+ throw error;
1923
+ }
1924
+ }
1925
+ this.archive.file("xl/media/image" + maxFildId + "." + fileExtension, toArrayBuffer(substitution), {
1926
+ binary: true,
1927
+ base64: false
1928
+ });
1929
+ const maxIdRichData = this.findMaxId(this._relsrichValueRel, "Relationship", "Id", /rId(\d*)/);
1930
+ const _rel = etree.SubElement(this._relsrichValueRel, "Relationship");
1931
+ _rel.set("Id", "rId" + maxIdRichData);
1932
+ _rel.set("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
1933
+ _rel.set("Target", "../media/image" + maxFildId + "." + fileExtension);
1934
+ const currentCountedRichValue = this.rdrichvalue.get("count");
1935
+ this.rdrichvalue.set("count", parseInt(currentCountedRichValue) + 1);
1936
+ const rv = etree.SubElement(this.rdrichvalue, "rv");
1937
+ rv.set("s", "0");
1938
+ const firstV = etree.SubElement(rv, "v");
1939
+ const secondV = etree.SubElement(rv, "v");
1940
+ firstV.text = currentCountedRichValue;
1941
+ secondV.text = "5";
1942
+ const rel = etree.SubElement(this.richValueRel, "rel");
1943
+ rel.set("r:id", "rId" + maxIdRichData);
1944
+ const futureMetadata = this.metadata.findall("futureMetadata").find((fm) => {
1945
+ return fm.attrib.name === "XLRICHVALUE";
1946
+ });
1947
+ const futureMetadataCount = futureMetadata.get("count");
1948
+ futureMetadata.set("count", parseInt(futureMetadataCount) + 1);
1949
+ const bk = etree.SubElement(futureMetadata, "bk");
1950
+ const extLst = etree.SubElement(bk, "extLst");
1951
+ const ext = etree.SubElement(extLst, "ext");
1952
+ ext.set("uri", "{3e2802c4-a4d2-4d8b-9148-e3be6c30e623}");
1953
+ const xlrd_rvb = etree.SubElement(ext, "xlrd:rvb");
1954
+ xlrd_rvb.set("i", futureMetadataCount);
1955
+ const valueMetadataCount = this.metadata.find("valueMetadata").get("count");
1956
+ this.metadata.find("valueMetadata").set("count", parseInt(valueMetadataCount) + 1);
1957
+ const bk_VM = etree.SubElement(this.metadata.find("valueMetadata"), "bk");
1958
+ const rc = etree.SubElement(bk_VM, "rc");
1959
+ const XLRICHVALUEMetaDataTypeIndex = this.metadata.find("metadataTypes").findall("metadataType").findIndex((el) => {
1960
+ return el.attrib.name === "XLRICHVALUE";
1961
+ });
1962
+ rc.set("t", "" + (XLRICHVALUEMetaDataTypeIndex + 1));
1963
+ rc.set("v", valueMetadataCount);
1964
+ cell.set("t", "e");
1965
+ cell.set("vm", parseInt(currentCountedRichValue) + 1);
1966
+ this.insertCellValue(cell, "#VALUE!");
1967
+ return true;
1968
+ }
1969
+ substituteImage(cell, string, placeholder, substitution, drawing) {
1970
+ this.substituteScalar(cell, string, placeholder, "");
1971
+ if (substitution == null || substitution == "") {
1972
+ return true;
1973
+ }
1974
+ const maxId = this.findMaxId(drawing.relRoot, "Relationship", "Id", /rId(\d*)/);
1975
+ const maxFildId = this.findMaxFileId(/xl\/media\/image\d*.jpg/, /image(\d*)\.jpg/);
1976
+ const rel = etree.SubElement(drawing.relRoot, "Relationship");
1977
+ rel.set("Id", "rId" + maxId);
1978
+ rel.set("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
1979
+ rel.set("Target", "../media/image" + maxFildId + ".jpg");
1980
+ try {
1981
+ substitution = this.imageToBuffer(substitution);
1982
+ } catch (error) {
1983
+ if (this.option && this.option.handleImageError && typeof this.option.handleImageError === "function") {
1984
+ this.option.handleImageError(substitution, error);
1985
+ } else {
1986
+ throw error;
1987
+ }
1988
+ }
1989
+ this.archive.file("xl/media/image" + maxFildId + ".jpg", toArrayBuffer(substitution), {
1990
+ binary: true,
1991
+ base64: false
1992
+ });
1993
+ const dimension = (0, import_image_size.imageSize)(substitution);
1994
+ let imageWidth = this.pixelsToEMUs(dimension.width);
1995
+ let imageHeight = this.pixelsToEMUs(dimension.height);
1996
+ let imageInMergeCell = false;
1997
+ for (let mergeCell of this.sheet.root.findall("mergeCells/mergeCell")) {
1998
+ if (this.cellInMergeCells(cell, mergeCell)) {
1999
+ const mergeCellWidth = this.getWidthMergeCell(mergeCell, this.sheet);
2000
+ const mergeCellHeight = this.getHeightMergeCell(mergeCell, this.sheet);
2001
+ const mergeWidthEmus = this.columnWidthToEMUs(mergeCellWidth);
2002
+ const mergeHeightEmus = this.rowHeightToEMUs(mergeCellHeight);
2003
+ const widthRate = imageWidth / mergeWidthEmus;
2004
+ const heightRate = imageHeight / mergeHeightEmus;
2005
+ if (widthRate > heightRate) {
2006
+ imageWidth = Math.floor(imageWidth / widthRate);
2007
+ imageHeight = Math.floor(imageHeight / widthRate);
2008
+ } else {
2009
+ imageWidth = Math.floor(imageWidth / heightRate);
2010
+ imageHeight = Math.floor(imageHeight / heightRate);
2011
+ }
2012
+ imageInMergeCell = true;
2013
+ }
2014
+ }
2015
+ if (!imageInMergeCell) {
2016
+ let ratio = 100;
2017
+ if (this.option && this.option.imageRatio) {
2018
+ ratio = this.option.imageRatio;
2019
+ }
2020
+ if (ratio <= 0) {
2021
+ ratio = 100;
2022
+ }
2023
+ imageWidth = Math.floor(imageWidth * ratio / 100);
2024
+ imageHeight = Math.floor(imageHeight * ratio / 100);
2025
+ }
2026
+ const imagePart = etree.SubElement(drawing.root, "xdr:oneCellAnchor");
2027
+ const fromPart = etree.SubElement(imagePart, "xdr:from");
2028
+ const fromCol = etree.SubElement(fromPart, "xdr:col");
2029
+ fromCol.text = (this.charToNum(this.splitRef(cell.attrib.r).col) - 1).toString();
2030
+ const fromColOff = etree.SubElement(fromPart, "xdr:colOff");
2031
+ fromColOff.text = "0";
2032
+ const fromRow = etree.SubElement(fromPart, "xdr:row");
2033
+ fromRow.text = (this.splitRef(cell.attrib.r).row - 1).toString();
2034
+ const fromRowOff = etree.SubElement(fromPart, "xdr:rowOff");
2035
+ fromRowOff.text = "0";
2036
+ const extImagePart = etree.SubElement(imagePart, "xdr:ext", { cx: `${imageWidth}`, cy: `${imageHeight}` });
2037
+ const picNode = etree.SubElement(imagePart, "xdr:pic");
2038
+ const nvPicPr = etree.SubElement(picNode, "xdr:nvPicPr");
2039
+ const cNvPr = etree.SubElement(nvPicPr, "xdr:cNvPr", { id: `${maxId}`, name: "image_" + maxId, descr: "" });
2040
+ const cNvPicPr = etree.SubElement(nvPicPr, "xdr:cNvPicPr");
2041
+ const picLocks = etree.SubElement(cNvPicPr, "a:picLocks", { noChangeAspect: "1" });
2042
+ const blipFill = etree.SubElement(picNode, "xdr:blipFill");
2043
+ const blip = etree.SubElement(blipFill, "a:blip", {
2044
+ "xmlns:r": "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
2045
+ "r:embed": "rId" + maxId
2046
+ });
2047
+ const stretch = etree.SubElement(blipFill, "a:stretch");
2048
+ const fillRect = etree.SubElement(stretch, "a:fillRect");
2049
+ const spPr = etree.SubElement(picNode, "xdr:spPr");
2050
+ const xfrm = etree.SubElement(spPr, "a:xfrm");
2051
+ const off = etree.SubElement(xfrm, "a:off", { x: "0", y: "0" });
2052
+ const ext = etree.SubElement(xfrm, "a:ext", { cx: `${imageWidth}`, cy: `${imageHeight}` });
2053
+ const prstGeom = etree.SubElement(spPr, "a:prstGeom", { "prst": "rect" });
2054
+ const avLst = etree.SubElement(prstGeom, "a:avLst");
2055
+ const clientData = etree.SubElement(imagePart, "xdr:clientData");
2056
+ return true;
2057
+ }
2058
+ cloneElement(element, deep) {
2059
+ const newElement = etree.Element(element.tag, element.attrib);
2060
+ newElement.text = element.text;
2061
+ newElement.tail = element.tail;
2062
+ if (deep !== false) {
2063
+ element.getchildren().forEach((child) => {
2064
+ newElement.append(this.cloneElement(child, deep));
2065
+ });
2066
+ }
2067
+ return newElement;
2068
+ }
2069
+ replaceChildren(parent, children) {
2070
+ parent.delSlice(0, parent.len());
2071
+ children.forEach((child) => {
2072
+ parent.append(child);
2073
+ });
2074
+ }
2075
+ getCurrentRow(row, rowsInserted) {
2076
+ return parseInt(row.attrib.r, 10) + rowsInserted;
2077
+ }
2078
+ getCurrentCell(cell, currentRow, cellsInserted) {
2079
+ const colRef = this.splitRef(cell.attrib.r).col;
2080
+ const colNum = this.charToNum(colRef);
2081
+ return this.joinRef({
2082
+ row: currentRow,
2083
+ col: this.numToChar(colNum + cellsInserted)
2084
+ });
2085
+ }
2086
+ updateRowSpan(row, cellsInserted) {
2087
+ if (cellsInserted !== 0 && row.attrib.spans) {
2088
+ const rowSpan = row.attrib.spans.split(":").map((f) => parseInt(f, 10));
2089
+ rowSpan[1] += cellsInserted;
2090
+ row.attrib.spans = rowSpan.join(":");
2091
+ }
2092
+ }
2093
+ splitRange(range) {
2094
+ const split = range.split(":");
2095
+ return {
2096
+ start: split[0],
2097
+ end: split[1]
2098
+ };
2099
+ }
2100
+ joinRange(range) {
2101
+ return range.start + ":" + range.end;
2102
+ }
2103
+ pushRight(workbook, sheet, currentCell, numCols) {
2104
+ const cellRef = this.splitRef(currentCell);
2105
+ const currentRow = cellRef.row;
2106
+ const currentCol = this.charToNum(cellRef.col);
2107
+ sheet.findall("mergeCells/mergeCell").forEach((mergeCell) => {
2108
+ const mergeRange = this.splitRange(mergeCell.attrib.ref);
2109
+ const mergeStart = this.splitRef(mergeRange.start);
2110
+ const mergeStartCol = this.charToNum(mergeStart.col);
2111
+ const mergeEnd = this.splitRef(mergeRange.end);
2112
+ const mergeEndCol = this.charToNum(mergeEnd.col);
2113
+ if (mergeStart.row === currentRow && currentCol < mergeStartCol) {
2114
+ mergeStart.col = this.numToChar(mergeStartCol + numCols);
2115
+ mergeEnd.col = this.numToChar(mergeEndCol + numCols);
2116
+ mergeCell.attrib.ref = this.joinRange({
2117
+ start: this.joinRef(mergeStart),
2118
+ end: this.joinRef(mergeEnd)
2119
+ });
2120
+ }
2121
+ });
2122
+ workbook.findall("definedNames/definedName").forEach((name) => {
2123
+ const ref = name.text;
2124
+ if (this.isRange(ref)) {
2125
+ const namedRange = this.splitRange(ref);
2126
+ const namedStart = this.splitRef(namedRange.start);
2127
+ const namedStartCol = this.charToNum(namedStart.col);
2128
+ const namedEnd = this.splitRef(namedRange.end);
2129
+ const namedEndCol = this.charToNum(namedEnd.col);
2130
+ if (namedStart.row === currentRow && currentCol < namedStartCol) {
2131
+ namedStart.col = this.numToChar(namedStartCol + numCols);
2132
+ namedEnd.col = this.numToChar(namedEndCol + numCols);
2133
+ name.text = this.joinRange({
2134
+ start: this.joinRef(namedStart),
2135
+ end: this.joinRef(namedEnd)
2136
+ });
2137
+ }
2138
+ } else {
2139
+ const namedRef = this.splitRef(ref);
2140
+ const namedCol = this.charToNum(namedRef.col);
2141
+ if (namedRef.row === currentRow && currentCol < namedCol) {
2142
+ namedRef.col = this.numToChar(namedCol + numCols);
2143
+ name.text = this.joinRef(namedRef);
2144
+ }
2145
+ }
2146
+ });
2147
+ sheet.findall("hyperlinks/hyperlink").forEach((hyperlink) => {
2148
+ const ref = this.splitRef(hyperlink.attrib.ref);
2149
+ const colNumber = this.charToNum(ref.col);
2150
+ if (colNumber > currentCol) {
2151
+ ref.col = this.numToChar(colNumber + numCols);
2152
+ hyperlink.attrib.ref = this.joinRef(ref);
2153
+ }
2154
+ });
2155
+ }
2156
+ pushDown(workbook, sheet, tables, currentRow, numRows) {
2157
+ const mergeCells = sheet.find("mergeCells");
2158
+ sheet.findall("mergeCells/mergeCell").forEach((mergeCell) => {
2159
+ const mergeRange = this.splitRange(mergeCell.attrib.ref);
2160
+ const mergeStart = this.splitRef(mergeRange.start);
2161
+ const mergeEnd = this.splitRef(mergeRange.end);
2162
+ if (mergeStart.row > currentRow) {
2163
+ mergeStart.row += numRows;
2164
+ mergeEnd.row += numRows;
2165
+ mergeCell.attrib.ref = this.joinRange({
2166
+ start: this.joinRef(mergeStart),
2167
+ end: this.joinRef(mergeEnd)
2168
+ });
2169
+ }
2170
+ if (mergeStart.row == currentRow) {
2171
+ for (let i = 1; i <= numRows; i++) {
2172
+ const newMergeCell = this.cloneElement(mergeCell);
2173
+ mergeStart.row += 1;
2174
+ mergeEnd.row += 1;
2175
+ newMergeCell.attrib.ref = this.joinRange({
2176
+ start: this.joinRef(mergeStart),
2177
+ end: this.joinRef(mergeEnd)
2178
+ });
2179
+ mergeCells.attrib.count += 1;
2180
+ mergeCells._children.push(newMergeCell);
2181
+ }
2182
+ }
2183
+ });
2184
+ tables.forEach((table) => {
2185
+ const tableRoot = table.root;
2186
+ const tableRange = this.splitRange(tableRoot.attrib.ref);
2187
+ const tableStart = this.splitRef(tableRange.start);
2188
+ const tableEnd = this.splitRef(tableRange.end);
2189
+ if (tableStart.row > currentRow) {
2190
+ tableStart.row += numRows;
2191
+ tableEnd.row += numRows;
2192
+ tableRoot.attrib.ref = this.joinRange({
2193
+ start: this.joinRef(tableStart),
2194
+ end: this.joinRef(tableEnd)
2195
+ });
2196
+ const autoFilter = tableRoot.find("autoFilter");
2197
+ if (autoFilter !== null) {
2198
+ autoFilter.attrib.ref = tableRoot.attrib.ref;
2199
+ }
2200
+ }
2201
+ });
2202
+ workbook.findall("definedNames/definedName").forEach((name) => {
2203
+ const ref = name.text;
2204
+ if (this.isRange(ref)) {
2205
+ const namedRange = this.splitRange(ref);
2206
+ const namedStart = this.splitRef(namedRange.start);
2207
+ const namedEnd = this.splitRef(namedRange.end);
2208
+ if (namedStart) {
2209
+ if (namedStart.row > currentRow) {
2210
+ namedStart.row += numRows;
2211
+ namedEnd.row += numRows;
2212
+ name.text = this.joinRange({
2213
+ start: this.joinRef(namedStart),
2214
+ end: this.joinRef(namedEnd)
2215
+ });
2216
+ }
2217
+ }
2218
+ if (this.option && this.option.pushDownPageBreakOnTableSubstitution) {
2219
+ if (this.sheet.name == name.text.split("!")[0].replace(/'/gi, "") && namedEnd) {
2220
+ if (namedEnd.row > currentRow) {
2221
+ namedEnd.row += numRows;
2222
+ name.text = this.joinRange({
2223
+ start: this.joinRef(namedStart),
2224
+ end: this.joinRef(namedEnd)
2225
+ });
2226
+ }
2227
+ }
2228
+ }
2229
+ } else {
2230
+ const namedRef = this.splitRef(ref);
2231
+ if (namedRef.row > currentRow) {
2232
+ namedRef.row += numRows;
2233
+ name.text = this.joinRef(namedRef);
2234
+ }
2235
+ }
2236
+ });
2237
+ sheet.findall("hyperlinks/hyperlink").forEach((hyperlink) => {
2238
+ const ref = this.splitRef(hyperlink.attrib.ref);
2239
+ if (ref.row > currentRow) {
2240
+ ref.row += numRows;
2241
+ hyperlink.attrib.ref = this.joinRef(ref);
2242
+ }
2243
+ });
2244
+ }
2245
+ async hideCols(sheetName, hideItemIndexes) {
2246
+ const sheet = await this.loadSheet(sheetName);
2247
+ this.sheet = sheet;
2248
+ if (Array.isArray(hideItemIndexes) && hideItemIndexes.length) {
2249
+ const cols = sheet.root.find("cols");
2250
+ if (cols) {
2251
+ hideItemIndexes.forEach((hideIndex) => {
2252
+ const colIndex = hideIndex + 1;
2253
+ const col = cols.findall("col").find((c) => {
2254
+ const min = parseInt(c.attrib.min, 10);
2255
+ const max = parseInt(c.attrib.max, 10);
2256
+ return colIndex >= min && colIndex <= max;
2257
+ });
2258
+ if (col) {
2259
+ col.attrib.hidden = "1";
2260
+ }
2261
+ });
2262
+ }
2263
+ }
2264
+ this.archive.file(sheet.filename, etree.tostring(sheet.root, { encoding: "utf-8" }));
2265
+ this._rebuild();
2266
+ return this;
2267
+ }
2268
+ getWidthCell(numCol, sheet) {
2269
+ let defaultWidth = sheet.root.find("sheetFormatPr").attrib["defaultColWidth"];
2270
+ if (!defaultWidth) {
2271
+ defaultWidth = "11.42578125";
2272
+ }
2273
+ let finalWidth = defaultWidth;
2274
+ sheet.root.findall("cols/col").forEach((col) => {
2275
+ if (numCol >= col.attrib["min"] && numCol <= col.attrib["max"]) {
2276
+ if (col.attrib["width"] != void 0) {
2277
+ finalWidth = col.attrib["width"];
2278
+ }
2279
+ }
2280
+ });
2281
+ return Number.parseFloat(finalWidth);
2282
+ }
2283
+ getWidthMergeCell(mergeCell, sheet) {
2284
+ let mergeWidth = 0;
2285
+ const mergeRange = this.splitRange(mergeCell.attrib.ref);
2286
+ const mergeStartCol = this.charToNum(this.splitRef(mergeRange.start).col);
2287
+ const mergeEndCol = this.charToNum(this.splitRef(mergeRange.end).col);
2288
+ for (let i = mergeStartCol; i < mergeEndCol + 1; i++) {
2289
+ mergeWidth += this.getWidthCell(i, sheet);
2290
+ }
2291
+ return mergeWidth;
2292
+ }
2293
+ getHeightCell(numRow, sheet) {
2294
+ let finalHeight = sheet.root.find("sheetFormatPr").attrib["defaultRowHeight"];
2295
+ sheet.root.findall("sheetData/row").forEach((row) => {
2296
+ if (numRow == row.attrib["r"]) {
2297
+ if (row.attrib["ht"] != void 0) {
2298
+ finalHeight = row.attrib["ht"];
2299
+ }
2300
+ }
2301
+ });
2302
+ return Number.parseFloat(finalHeight);
2303
+ }
2304
+ getHeightMergeCell(mergeCell, sheet) {
2305
+ let mergeHeight = 0;
2306
+ const mergeRange = this.splitRange(mergeCell.attrib.ref);
2307
+ const mergeStartRow = this.splitRef(mergeRange.start).row;
2308
+ const mergeEndRow = this.splitRef(mergeRange.end).row;
2309
+ for (let i = mergeStartRow; i < mergeEndRow + 1; i++) {
2310
+ mergeHeight += this.getHeightCell(i, sheet);
2311
+ }
2312
+ return mergeHeight;
2313
+ }
2314
+ getNbRowOfMergeCell(mergeCell) {
2315
+ const mergeRange = this.splitRange(mergeCell.attrib.ref);
2316
+ const mergeStartRow = this.splitRef(mergeRange.start).row;
2317
+ const mergeEndRow = this.splitRef(mergeRange.end).row;
2318
+ return mergeEndRow - mergeStartRow + 1;
2319
+ }
2320
+ pixelsToEMUs(pixels) {
2321
+ return Math.round(pixels * 914400 / 96);
2322
+ }
2323
+ columnWidthToEMUs(width) {
2324
+ return this.pixelsToEMUs(width * 7.625579987895905);
2325
+ }
2326
+ rowHeightToEMUs(height) {
2327
+ return Math.round(height / 72 * 914400);
2328
+ }
2329
+ findMaxFileId(fileNameRegex, idRegex) {
2330
+ const files = this.archive.file(fileNameRegex);
2331
+ const maxId = files.reduce((p, c) => {
2332
+ const num = parseInt(idRegex.exec(c.name)[1]);
2333
+ if (p == null) {
2334
+ return num;
2335
+ }
2336
+ return p > num ? p : num;
2337
+ }, 0);
2338
+ return maxId + 1;
2339
+ }
2340
+ cellInMergeCells(cell, mergeCell) {
2341
+ const cellCol = this.charToNum(this.splitRef(cell.attrib.r).col);
2342
+ const cellRow = this.splitRef(cell.attrib.r).row;
2343
+ const mergeRange = this.splitRange(mergeCell.attrib.ref);
2344
+ const mergeStartCol = this.charToNum(this.splitRef(mergeRange.start).col);
2345
+ const mergeEndCol = this.charToNum(this.splitRef(mergeRange.end).col);
2346
+ const mergeStartRow = this.splitRef(mergeRange.start).row;
2347
+ const mergeEndRow = this.splitRef(mergeRange.end).row;
2348
+ if (cellCol >= mergeStartCol && cellCol <= mergeEndCol) {
2349
+ if (cellRow >= mergeStartRow && cellRow <= mergeEndRow) {
2350
+ return true;
2351
+ }
2352
+ }
2353
+ return false;
2354
+ }
2355
+ imageToBuffer(imageObj) {
2356
+ function checkImage(buffer) {
2357
+ try {
2358
+ (0, import_image_size.imageSize)(buffer);
2359
+ return buffer;
2360
+ } catch (error) {
2361
+ throw new TypeError("imageObj cannot be parse as a buffer image");
2362
+ }
2363
+ }
2364
+ if (!imageObj) {
2365
+ throw new TypeError("imageObj cannot be null");
2366
+ }
2367
+ if (imageObj instanceof Buffer) {
2368
+ return checkImage(imageObj);
2369
+ }
2370
+ if (typeof imageObj === "string" || imageObj instanceof String) {
2371
+ imageObj = imageObj.toString();
2372
+ const imagePath = this.option && this.option.imageRootPath ? this.option.imageRootPath + "/" + imageObj : imageObj;
2373
+ if (fs.existsSync(imagePath)) {
2374
+ return checkImage(Buffer.from(fs.readFileSync(imagePath, { encoding: "base64" }), "base64"));
2375
+ }
2376
+ try {
2377
+ return checkImage(Buffer.from(imageObj, "base64"));
2378
+ } catch (error) {
2379
+ throw new TypeError("imageObj cannot be parse as a buffer");
2380
+ }
2381
+ }
2382
+ throw new TypeError("imageObj type is not supported : " + typeof imageObj);
2383
+ }
2384
+ findMaxId(element, tag, attr, idRegex) {
2385
+ let maxId = 0;
2386
+ element.findall(tag).forEach((el) => {
2387
+ const match = idRegex.exec(el.attrib[attr]);
2388
+ if (match == null) {
2389
+ throw new Error("Can not find the id!");
2390
+ }
2391
+ const cid = parseInt(match[1]);
2392
+ if (cid > maxId) {
2393
+ maxId = cid;
2394
+ }
2395
+ });
2396
+ return ++maxId;
2397
+ }
16
2398
  };
17
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
- // If the importer is in node compatibility mode or this is not an ESM
19
- // file that has been converted to a CommonJS file using a Babel-
20
- // compatible transform (i.e. "__esModule" has not been set), then set
21
- // "default" to the CommonJS "module.exports" for node compatibility.
22
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
- mod
24
- ));
25
-
26
- // src/bin.ts
27
- var import_chalk = __toESM(require("chalk"));
28
- var import_commander = require("commander");
29
-
30
- // src/core.ts
31
- var etree = __toESM(require("elementtree"));
32
- var import_jszip = __toESM(require("jszip"));
33
- var console2 = __toESM(require("console"));
34
- var import_image_size = require("image-size");
35
- var import_types = require("util/types");
36
- 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");
37
2399
 
38
2400
  // src/helper.ts
39
2401
  var import_exceljs = __toESM(require("exceljs"));
@@ -929,7 +3291,7 @@ function base64ToArrayBuffer(base64) {
929
3291
  }
930
3292
  var resolveCompileMacroGen = (ctx, expr, currentCellIndex) => {
931
3293
  let parts = [];
932
- let join = ".";
3294
+ let join3 = ".";
933
3295
  const m = ctx.getContextMap();
934
3296
  const aliasToken = TokenParserManger.getTokenByCtx(m, "@" /* UseAliasToken */);
935
3297
  const genToken = TokenParserManger.getTokenByCtx(m, "compile:GenCell" /* CompileGenToken */);
@@ -945,7 +3307,15 @@ var resolveCompileMacroGen = (ctx, expr, currentCellIndex) => {
945
3307
  parts.push(resolveAliasExpr(ctx, item.value, currentCellIndex));
946
3308
  }
947
3309
  }
948
- return parts.join(join);
3310
+ if (parts.length === 1) {
3311
+ return parts[0];
3312
+ }
3313
+ let end = parts[parts.length - 1];
3314
+ if (end.startsWith('"') && end.length >= 3 && end.endsWith('"')) {
3315
+ join3 = end;
3316
+ return parts.slice(0, parts.length - 1).join(join3);
3317
+ }
3318
+ return parts.join(join3);
949
3319
  };
950
3320
  var getExprEnd = function(macroExpr, matchIndex, rparenToken) {
951
3321
  return macroExpr.indexOf(rparenToken, matchIndex);
@@ -993,7 +3363,17 @@ var __codeKey = (str, expr) => {
993
3363
  return str.toUpperCase();
994
3364
  };
995
3365
  var __numberKey = (str, expr) => {
996
- return Number.parseInt(str, 10).toString();
3366
+ if (str === "NaN" || str === "Infinity" || str === "null" || str === "[object object]") {
3367
+ return str;
3368
+ }
3369
+ if (str.startsWith("0x")) {
3370
+ return str.substring(2);
3371
+ }
3372
+ let v = Number.parseInt(str, 10);
3373
+ if (isNaN(v)) {
3374
+ return str;
3375
+ }
3376
+ return v.toString();
997
3377
  };
998
3378
  var __codeAliasKey = (str, expr) => {
999
3379
  const key = __codeKey(str);
@@ -1567,7 +3947,7 @@ var fetchAlias = (m) => {
1567
3947
  return alias;
1568
3948
  };
1569
3949
  var removeUnExportSheets = (w, options) => {
1570
- const removes = [];
3950
+ let removes = [];
1571
3951
  if (typeof options.skipRemoveUnExportSheet === "boolean" && options.skipRemoveUnExportSheet === true) {
1572
3952
  return w;
1573
3953
  }
@@ -1585,6 +3965,9 @@ var removeUnExportSheets = (w, options) => {
1585
3965
  }
1586
3966
  }
1587
3967
  }
3968
+ if (removes.length === w.worksheets.length && w.worksheets[0].name === removes[0]) {
3969
+ removes = removes.slice(1, removes.length);
3970
+ }
1588
3971
  for (const [_, name] of removes.entries()) {
1589
3972
  w.removeWorksheet(name);
1590
3973
  }
@@ -1614,23 +3997,619 @@ ExprResolver.resolveCompileMacroExpr = resolveCompileMacroExpr;
1614
3997
 
1615
3998
  // src/extends.ts
1616
3999
  var import_promises = __toESM(require("fs/promises"));
4000
+ function hasToString(obj) {
4001
+ return obj != null && typeof obj.toString === "function";
4002
+ }
4003
+ var tokenNextIter = [`root`, `groups`, `suffix`, `default`];
4004
+ var aliasKey = `__alias`;
4005
+ var ArgumentData = class {
4006
+ constructor(fn, p) {
4007
+ this.default = "";
4008
+ this.groups = [];
4009
+ this.tokenIterIndex = 0;
4010
+ this.p = p;
4011
+ this.func = fn;
4012
+ this.groups = [];
4013
+ }
4014
+ To() {
4015
+ return {
4016
+ p: this.p,
4017
+ root: this.root,
4018
+ alias: this.alias,
4019
+ groups: this.groups,
4020
+ suffix: this.suffix,
4021
+ default: this.default,
4022
+ func: this.func
4023
+ };
4024
+ }
4025
+ Add(startToken, value) {
4026
+ if (value === void 0) {
4027
+ this.tokenIterIndex++;
4028
+ return;
4029
+ }
4030
+ switch (startToken) {
4031
+ case `(`:
4032
+ if (tokenNextIter[this.tokenIterIndex] === "root") {
4033
+ this.root = value;
4034
+ this.tokenIterIndex++;
4035
+ }
4036
+ break;
4037
+ case `[`:
4038
+ if (tokenNextIter[this.tokenIterIndex] === "groups") {
4039
+ this.groups.push(value);
4040
+ }
4041
+ break;
4042
+ case `]`:
4043
+ if (tokenNextIter[this.tokenIterIndex] === "groups") {
4044
+ this.groups.push(value);
4045
+ }
4046
+ break;
4047
+ case `,`:
4048
+ const token = tokenNextIter[this.tokenIterIndex];
4049
+ if (token === "root") {
4050
+ this.root = value;
4051
+ this.tokenIterIndex++;
4052
+ } else if (token === "groups") {
4053
+ this.groups.push(value);
4054
+ } else if (token === "suffix") {
4055
+ this.suffix = value;
4056
+ this.tokenIterIndex++;
4057
+ } else if (token === "default") {
4058
+ this.default = value;
4059
+ this.tokenIterIndex++;
4060
+ }
4061
+ break;
4062
+ case `)`:
4063
+ this.tokenIterIndex++;
4064
+ break;
4065
+ }
4066
+ }
4067
+ ParseAlias(alias) {
4068
+ if (alias === void 0 || this.root === void 0 || this.root === "") {
4069
+ return;
4070
+ }
4071
+ const value = valueDotGet(alias, this.root);
4072
+ if (value === void 0 || typeof value !== "string" || !hasToString(value)) {
4073
+ return;
4074
+ }
4075
+ this.alias = this.root;
4076
+ this.root = value;
4077
+ }
4078
+ };
4079
+ var ArgumentValue = class {
4080
+ constructor(value, defValue) {
4081
+ this.value = value;
4082
+ this.defaultValue = defValue;
4083
+ }
4084
+ isUndefined() {
4085
+ return this.value === void 0;
4086
+ }
4087
+ getDefault() {
4088
+ return this.defaultValue;
4089
+ }
4090
+ getNumber() {
4091
+ return Number(this.value);
4092
+ }
4093
+ toString() {
4094
+ if (this.isUndefined()) {
4095
+ return "";
4096
+ }
4097
+ if (typeof this.value === "string") {
4098
+ return this.value;
4099
+ }
4100
+ if (hasToString(this.value)) {
4101
+ return this.value.toString();
4102
+ }
4103
+ return "";
4104
+ }
4105
+ };
4106
+ var ArgumentValueLoader = (values, args) => {
4107
+ let all = [];
4108
+ for (let v of args.groups) {
4109
+ let key = `${args.root}.${v}`;
4110
+ if (args.suffix !== void 0 && args.suffix !== "") {
4111
+ key = `${key}.${args.suffix}`;
4112
+ }
4113
+ all.push(key);
4114
+ }
4115
+ if (all.length <= 0) {
4116
+ return args.default || "";
4117
+ }
4118
+ const items = [];
4119
+ for (let k of all) {
4120
+ let vs = valueDotGet(values, k);
4121
+ items.push(new ArgumentValue(vs, args.default));
4122
+ }
4123
+ return items;
4124
+ };
4125
+ var sum_all = (values, argument) => {
4126
+ let sum = NaN;
4127
+ let emptyTimes = 0;
4128
+ let argc = argument.groups.length;
4129
+ let items = ArgumentValueLoader(values, argument);
4130
+ for (let value of items) {
4131
+ let num = value.getNumber();
4132
+ if (value.isUndefined()) {
4133
+ emptyTimes++;
4134
+ num = Number(argument.default);
4135
+ }
4136
+ if (isNaN(sum)) {
4137
+ sum = num;
4138
+ } else {
4139
+ sum = sum + Number(num);
4140
+ }
4141
+ }
4142
+ if (emptyTimes === argc) {
4143
+ return void 0;
4144
+ }
4145
+ if (isNaN(sum)) {
4146
+ throw new Error(`parse ${argument.p.name} NaN error`);
4147
+ }
4148
+ return sum;
4149
+ };
4150
+ var sub_value = (values, argument) => {
4151
+ let sub = NaN;
4152
+ let emptyTimes = 0;
4153
+ let argc = argument.groups.length;
4154
+ let items = ArgumentValueLoader(values, argument);
4155
+ for (let value of items) {
4156
+ let num = value.getNumber();
4157
+ if (value.isUndefined()) {
4158
+ emptyTimes++;
4159
+ num = Number(argument.default);
4160
+ }
4161
+ if (isNaN(num)) {
4162
+ continue;
4163
+ }
4164
+ if (isNaN(sub)) {
4165
+ sub = num;
4166
+ } else {
4167
+ sub = sub - Number(num);
4168
+ }
4169
+ }
4170
+ if (emptyTimes === argc) {
4171
+ return void 0;
4172
+ }
4173
+ if (isNaN(sub)) {
4174
+ throw new Error(`parse ${argument.p.name} NaN error`);
4175
+ }
4176
+ return sub;
4177
+ };
4178
+ var defaultCommands = /* @__PURE__ */ new Map([
4179
+ ["sum", sum_all],
4180
+ ["sub", sub_value]
4181
+ ]);
4182
+ var resolveFunc = function(value) {
4183
+ if (value.indexOf("(") > 0 && value.endsWith(")")) {
4184
+ const names = value.split("(");
4185
+ return names[0];
4186
+ }
4187
+ return "";
4188
+ };
4189
+ var resolveArgument = function(p, data) {
4190
+ const value = p.name;
4191
+ const fn = resolveFunc(value);
4192
+ const args = new ArgumentData(fn, p);
4193
+ if (fn !== "") {
4194
+ let key = "";
4195
+ let startT = "";
4196
+ const endToken = [`)`, `,`, `]`];
4197
+ const startToken = [`(`, `,`, `[`];
4198
+ const tokenRow = value.split(`${fn}`)[1];
4199
+ const len = tokenRow.length;
4200
+ for (let i = 0; i < len; i++) {
4201
+ let start = startToken.includes(tokenRow[i]);
4202
+ let end = endToken.includes(tokenRow[i]);
4203
+ if (start) {
4204
+ startT = tokenRow[i];
4205
+ }
4206
+ if (startT !== "" && tokenRow[i] !== startT && !end) {
4207
+ key = `${key}${tokenRow[i]}`;
4208
+ }
4209
+ if (end) {
4210
+ if (key === "") {
4211
+ args.Add(startT, void 0);
4212
+ } else {
4213
+ args.Add(startT, key);
4214
+ key = "";
4215
+ }
4216
+ }
4217
+ }
4218
+ }
4219
+ const alias = valueDotGet(data, aliasKey);
4220
+ if (alias !== void 0) {
4221
+ args.ParseAlias(alias);
4222
+ }
4223
+ return args.To();
4224
+ };
4225
+ var commandExtendQuery = function(values, p) {
4226
+ if (p.type !== "fn") {
4227
+ return defaultValueDotGet(values, p);
4228
+ }
4229
+ const argument = resolveArgument(p, values);
4230
+ if (argument.func !== "" && defaultCommands.has(argument.func)) {
4231
+ return defaultCommands.get(argument.func)(values, argument);
4232
+ }
4233
+ return defaultValueDotGet(values, p);
4234
+ };
4235
+ var compileRuleSheetName = "export_metadata.config";
4236
+ var mergeMap = function(source, dest) {
4237
+ for (const [key, value] of dest.entries()) {
4238
+ source.set(key, value);
4239
+ }
4240
+ return source;
4241
+ };
4242
+ var autoRegisterAlias = function(values, configure) {
4243
+ let alias = ExprResolver.fetchAlias(configure);
4244
+ if (values[aliasKey] !== void 0 && values[aliasKey] instanceof Map) {
4245
+ alias = mergeMap(alias, values[aliasKey]);
4246
+ }
4247
+ values[aliasKey] = alias;
4248
+ return values;
4249
+ };
4250
+ var compileAll = async (buf, compileOpts, renderData) => {
4251
+ if (compileOpts === void 0 || compileOpts.sheetName === "") {
4252
+ return buf;
4253
+ }
4254
+ const result = await ExprResolver.compile(buf, compileOpts.sheetName, compileOpts);
4255
+ if (result.errs !== void 0 && result.errs.length > 0) {
4256
+ throw result.errs[0];
4257
+ }
4258
+ if (compileOpts.remove !== void 0 && compileOpts.remove === true) {
4259
+ result.workbook = ExprResolver.removeUnExportSheets(result.workbook, compileOpts);
4260
+ }
4261
+ if (renderData !== void 0) {
4262
+ autoRegisterAlias(renderData, result.configure);
4263
+ }
4264
+ return await ExprResolver.toBuffer(result.workbook);
4265
+ };
1617
4266
 
1618
4267
  // src/biz.ts
1619
4268
  var import_node_path = require("path");
1620
4269
  var import_lodash = require("lodash");
1621
4270
  var import_adm_zip = __toESM(require("adm-zip"));
4271
+ var XlsxRender = class _XlsxRender extends Workbook {
4272
+ constructor(option) {
4273
+ super(option);
4274
+ }
4275
+ static async create(data, option) {
4276
+ const w = await super.parse(data, option);
4277
+ w.setQueryFunctionHandler(commandExtendQuery);
4278
+ const app = new _XlsxRender(option);
4279
+ Object.assign(app, { ...w });
4280
+ return app;
4281
+ }
4282
+ async render(values, sheetName) {
4283
+ await this.substitute(sheetName, values);
4284
+ }
4285
+ getSheets() {
4286
+ return this.sheets;
4287
+ }
4288
+ };
4289
+
4290
+ // src/bin-helpers.ts
4291
+ var path2 = __toESM(require("path"));
4292
+ var url = __toESM(require("url"));
4293
+ var import_node_fs = require("fs");
4294
+ var fs3 = __toESM(require("fs/promises"));
4295
+ var import_chalk = __toESM(require("chalk"));
4296
+ var import_meta = {};
4297
+ function generateOutputFilename(inputFile) {
4298
+ const basename3 = path2.basename(inputFile, path2.extname(inputFile));
4299
+ const timestamp = Date.now();
4300
+ return `${basename3}_${timestamp}.xlsx`;
4301
+ }
4302
+ async function resolveFilePath(filePath) {
4303
+ const resolvedPath = path2.resolve(filePath);
4304
+ if ((0, import_node_fs.existsSync)(resolvedPath)) {
4305
+ return resolvedPath;
4306
+ }
4307
+ const scriptDir = path2.dirname(url.fileURLToPath(import_meta.url));
4308
+ const relativePath = path2.resolve(scriptDir, filePath);
4309
+ if ((0, import_node_fs.existsSync)(relativePath)) {
4310
+ return relativePath;
4311
+ }
4312
+ throw new Error(`File not found: ${filePath}`);
4313
+ }
4314
+ async function parseRenderData(dataOption) {
4315
+ if (!dataOption) {
4316
+ return {};
4317
+ }
4318
+ try {
4319
+ return JSON.parse(dataOption);
4320
+ } catch (e) {
4321
+ try {
4322
+ const filePath = await resolveFilePath(dataOption);
4323
+ const fileContent = await fs3.readFile(filePath, "utf-8");
4324
+ return JSON.parse(fileContent);
4325
+ } catch (e2) {
4326
+ if (dataOption.startsWith("http://") || dataOption.startsWith("https://")) {
4327
+ let fetch;
4328
+ try {
4329
+ fetch = globalThis.fetch;
4330
+ } catch (e3) {
4331
+ try {
4332
+ const nodeFetch = await import("node-fetch");
4333
+ fetch = nodeFetch.default;
4334
+ } catch (e4) {
4335
+ throw new Error("Remote URLs require Node.js 18+ or node-fetch package");
4336
+ }
4337
+ }
4338
+ const response = await fetch(dataOption);
4339
+ return response.json();
4340
+ }
4341
+ throw new Error(`Failed to parse render data from: ${dataOption}`);
4342
+ }
4343
+ }
4344
+ }
4345
+ function checkSheetAndPlaceholders(xlsx, sheetName) {
4346
+ const sheets = xlsx.getSheets();
4347
+ const sheet = sheets.find((s) => s.name === sheetName);
4348
+ if (!sheet) {
4349
+ throw new Error(`Sheet "${sheetName}" not found in Excel file`);
4350
+ }
4351
+ }
4352
+ async function addRuleToSheet(xlsxBuffer, ruleType, ruleExpr, sheetName = "export_metadata.config") {
4353
+ const workbook = await loadWorkbook(xlsxBuffer);
4354
+ let worksheet = workbook.getWorksheet(sheetName);
4355
+ if (!worksheet) {
4356
+ worksheet = workbook.addWorksheet(sheetName);
4357
+ console.log(import_chalk.default.gray(`Created new sheet: ${sheetName}`));
4358
+ }
4359
+ let startRow = 1;
4360
+ let currentRow = 1;
4361
+ let columnCount = 0;
4362
+ worksheet.eachRow((row, rowNumber) => {
4363
+ const cell = row.getCell(1);
4364
+ const cellValue = cell.value?.toString().trim();
4365
+ if (!cellValue) {
4366
+ return;
4367
+ }
4368
+ if (cellValue.toLowerCase() === ruleType.toLowerCase()) {
4369
+ let col = 2;
4370
+ while (col <= 4) {
4371
+ const ruleCell = row.getCell(col);
4372
+ if (ruleCell.value) {
4373
+ columnCount++;
4374
+ }
4375
+ col++;
4376
+ }
4377
+ if (columnCount < 4) {
4378
+ currentRow = rowNumber;
4379
+ startRow = rowNumber;
4380
+ } else {
4381
+ currentRow = rowNumber + 1;
4382
+ }
4383
+ }
4384
+ });
4385
+ if (startRow === 1 && currentRow === 1 && worksheet.rowCount === 0) {
4386
+ currentRow = 1;
4387
+ }
4388
+ let targetRow = worksheet.getRow(currentRow);
4389
+ if (!targetRow.getCell(1).value) {
4390
+ const typeCell = targetRow.getCell(1);
4391
+ typeCell.value = ruleType;
4392
+ typeCell.font = { bold: true };
4393
+ typeCell.alignment = { horizontal: "center", vertical: "middle" };
4394
+ }
4395
+ let ruleCol = 2;
4396
+ while (ruleCol <= 4) {
4397
+ const existingCell = targetRow.getCell(ruleCol);
4398
+ if (!existingCell.value) {
4399
+ break;
4400
+ }
4401
+ ruleCol++;
4402
+ }
4403
+ if (ruleCol <= 4) {
4404
+ const ruleCell = targetRow.getCell(ruleCol);
4405
+ ruleCell.value = ruleExpr;
4406
+ ruleCell.alignment = { vertical: "middle" };
4407
+ const column = worksheet.getColumn(ruleCol);
4408
+ column.width = Math.max(column.width || 10, ruleExpr.length + 2);
4409
+ console.log(import_chalk.default.gray(`Added rule ${ruleType} at row ${currentRow}, column ${ruleCol}`));
4410
+ } else {
4411
+ throw new Error(`Cannot add more than 4 rules for type: ${ruleType}`);
4412
+ }
4413
+ const buffer = await workbook.xlsx.writeBuffer();
4414
+ return Buffer.from(buffer);
4415
+ }
4416
+ async function parseRulesFromFile(filePath) {
4417
+ const resolvedPath = await resolveFilePath(filePath);
4418
+ const fileContent = await fs3.readFile(resolvedPath, "utf-8");
4419
+ const lines = fileContent.split("\n");
4420
+ const rules = [];
4421
+ const validTypes = ["cell", "alias", "rowCell", "mergeCell"];
4422
+ for (let i = 0; i < lines.length; i++) {
4423
+ const line = lines[i].trim();
4424
+ if (!line || line.startsWith("#")) {
4425
+ continue;
4426
+ }
4427
+ const spaceIndex = line.indexOf(" ");
4428
+ if (spaceIndex === -1) {
4429
+ console.log(import_chalk.default.yellow(`\u26A0 Line ${i + 1}: Invalid format. Expected "<type> ruleExpr"`));
4430
+ continue;
4431
+ }
4432
+ const type = line.substring(0, spaceIndex).trim();
4433
+ const rule = line.substring(spaceIndex + 1).trim();
4434
+ if (!type || !rule) {
4435
+ console.log(import_chalk.default.yellow(`\u26A0 Line ${i + 1}: Invalid format. Expected "<type> ruleExpr"`));
4436
+ continue;
4437
+ }
4438
+ if (!validTypes.includes(type)) {
4439
+ console.log(import_chalk.default.yellow(`\u26A0 Line ${i + 1}: Invalid rule type "${type}". Must be one of: ${validTypes.join(", ")}`));
4440
+ continue;
4441
+ }
4442
+ rules.push({ type, rule });
4443
+ }
4444
+ if (rules.length === 0) {
4445
+ throw new Error("No valid rules found in file");
4446
+ }
4447
+ return rules;
4448
+ }
4449
+ async function addMultipleRulesToSheet(xlsxBuffer, rules) {
4450
+ let buffer = xlsxBuffer;
4451
+ for (const { type, rule } of rules) {
4452
+ console.log(import_chalk.default.gray(`Adding ${type} rule: ${rule}`));
4453
+ buffer = await addRuleToSheet(buffer, type, rule);
4454
+ }
4455
+ return buffer;
4456
+ }
1622
4457
 
1623
4458
  // src/bin.ts
1624
- var program = new import_commander.Command();
1625
- program.name("xlsx-cli").version("1.0.0");
1626
- program.command("compile").argument("<string>", "xlsx file path").option("-s,--save <string>", "save compiled xlsx file to user dir").option("-r,--remove", "remove configure rules sheet", false).action((cmd, xlsxFile, options) => {
1627
- const resolver = ExprResolver;
1628
- console.log(import_chalk.default.green("xlsxFile %s"), xlsxFile);
1629
- console.log(import_chalk.default.red("options %s"), options);
1630
- });
1631
- program.command("render").argument("<string>", "xlsx file path").option("-c,--compile", "auto compile flag", false).option("-s,--save <string>", "save render xlsx file to user dir").action((cmd, xlsxFile, options) => {
1632
- console.log(import_chalk.default.green("xlsxFile %s"), xlsxFile);
1633
- console.log(import_chalk.default.red("options %s"), options);
4459
+ async function main() {
4460
+ let version = "1.0.0";
4461
+ try {
4462
+ const possiblePaths = [
4463
+ path3.join(process.cwd(), "package.json"),
4464
+ path3.join(process.cwd(), "..", "package.json")
4465
+ ];
4466
+ for (const packagePath of possiblePaths) {
4467
+ if ((0, import_node_fs2.existsSync)(packagePath)) {
4468
+ const packageJson = JSON.parse(await fs4.readFile(packagePath, "utf-8"));
4469
+ version = packageJson.version;
4470
+ break;
4471
+ }
4472
+ }
4473
+ } catch (e) {
4474
+ }
4475
+ const envPath = path3.join(process.cwd(), ".env");
4476
+ if ((0, import_node_fs2.existsSync)(envPath)) {
4477
+ try {
4478
+ const dotenv = (await Promise.resolve().then(() => __toESM(require_main()))).default;
4479
+ dotenv.config({ debug: false, path: envPath });
4480
+ } catch (e) {
4481
+ }
4482
+ }
4483
+ const program = new import_commander.Command();
4484
+ program.name("xlsx-cli").version(version);
4485
+ program.command("compile").argument("<string>", "xlsx file path").option("-s,--save <string>", "save compiled xlsx file to user dir").option("-n,--sheet-name <string>", "compile xlsx sheet name when xlsx has multiple sheets").option("-r,--remove", "remove configure rules sheet", false).action(async (xlsxFile, options) => {
4486
+ try {
4487
+ console.log(import_chalk2.default.green("\u{1F4C4} Compiling Excel file..."));
4488
+ const filePath = await resolveFilePath(xlsxFile);
4489
+ console.log(import_chalk2.default.gray(`Loading file: ${filePath}`));
4490
+ const buffer = await fs4.readFile(filePath);
4491
+ const xlsx = await XlsxRender.create(buffer);
4492
+ const sheets = xlsx.getSheets();
4493
+ const sheetName = options.sheetName || sheets[0].name;
4494
+ console.log(import_chalk2.default.gray(`Target sheet: ${sheetName}`));
4495
+ const ruleSheetName = options.sheetName || compileRuleSheetName;
4496
+ console.log(import_chalk2.default.gray("Compiling rules..."));
4497
+ const compiledBuffer = await compileAll(buffer, {
4498
+ sheetName: ruleSheetName,
4499
+ remove: options.remove || false
4500
+ });
4501
+ console.log(import_chalk2.default.green("\u2713 Compilation completed"));
4502
+ const outputFile = options.save || path3.join(process.cwd(), generateOutputFilename(xlsxFile));
4503
+ console.log(import_chalk2.default.gray(`Saving to: ${outputFile}`));
4504
+ await fs4.writeFile(outputFile, compiledBuffer);
4505
+ console.log(import_chalk2.default.green("\u2713 Excel file compiled successfully!"));
4506
+ console.log(import_chalk2.default.green(`\u{1F4C1} Output: ${outputFile}`));
4507
+ } catch (error) {
4508
+ console.error(import_chalk2.default.red("\u2717 Compilation failed:"));
4509
+ console.error(import_chalk2.default.red(error instanceof Error ? error.message : String(error)));
4510
+ process.exit(1);
4511
+ }
4512
+ });
4513
+ program.command("render").argument("<string>", "xlsx file path").option("-c,--compile", "auto compile flag", false).option("-n,--sheet-name <string>", "render xlsx sheet name when xlsx has multiple sheets").option("-s,--save <string>", "save render xlsx file to user dir").option("-d,--data <string>", "render xlsx file data from").action(async (xlsxFile, options) => {
4514
+ try {
4515
+ console.log(import_chalk2.default.green("\u{1F4C4} Rendering Excel template..."));
4516
+ const filePath = await resolveFilePath(xlsxFile);
4517
+ console.log(import_chalk2.default.gray(`Loading file: ${filePath}`));
4518
+ let buffer = await fs4.readFile(filePath);
4519
+ let xlsx = await XlsxRender.create(buffer);
4520
+ const sheets = xlsx.getSheets();
4521
+ const sheetName = options.sheetName || sheets[0].name;
4522
+ console.log(import_chalk2.default.gray(`Target sheet: ${sheetName}`));
4523
+ checkSheetAndPlaceholders(xlsx, sheetName);
4524
+ console.log(import_chalk2.default.gray("Sheet validation passed"));
4525
+ const renderData = await parseRenderData(options.data);
4526
+ if (Object.keys(renderData).length > 0) {
4527
+ console.log(import_chalk2.default.gray(`Render data loaded with ${Object.keys(renderData).length} keys`));
4528
+ }
4529
+ if (options.compile) {
4530
+ console.log(import_chalk2.default.gray("Auto-compiling rules..."));
4531
+ const ruleSheetName = options.sheetName || compileRuleSheetName;
4532
+ const compiledResult = await compileAll(buffer, {
4533
+ sheetName: ruleSheetName,
4534
+ remove: false
4535
+ // Don't remove rule sheet during render
4536
+ });
4537
+ buffer = Buffer.from(compiledResult);
4538
+ xlsx = await XlsxRender.create(buffer);
4539
+ console.log(import_chalk2.default.green("\u2713 Auto-compilation completed"));
4540
+ }
4541
+ console.log(import_chalk2.default.gray("Rendering template..."));
4542
+ await xlsx.render(renderData, sheetName);
4543
+ const outputBuffer = await xlsx.generate({
4544
+ type: "nodebuffer" /* NodeBuffer */,
4545
+ compression: "DEFLATE",
4546
+ compressionOptions: {
4547
+ level: 9
4548
+ }
4549
+ });
4550
+ const outputFile = options.save || path3.join(process.cwd(), generateOutputFilename(xlsxFile));
4551
+ console.log(import_chalk2.default.gray(`Saving to: ${outputFile}`));
4552
+ await fs4.writeFile(outputFile, outputBuffer);
4553
+ console.log(import_chalk2.default.green("\u2713 Excel template rendered successfully!"));
4554
+ console.log(import_chalk2.default.green(`\u{1F4C1} Output: ${outputFile}`));
4555
+ } catch (error) {
4556
+ console.error(import_chalk2.default.red("\u2717 Rendering failed:"));
4557
+ console.error(import_chalk2.default.red(error instanceof Error ? error.message : String(error)));
4558
+ process.exit(1);
4559
+ }
4560
+ });
4561
+ program.command("rules").argument("<string>", "xlsx compile rules setting").option("-t,--type <string>", "xlsx compile rule type <cell,alias,rowCell,mergeCell> (optional when using -f)").option("-r,--rule <string>", "xlsx compile rule expr (can be specified multiple times)").option("-f,--file <string>", "read rules from file (format: <type> ruleExpr per line)").option("-s,--save <string>", "save compiled xlsx file to user dir").action(async (xlsxFile, options) => {
4562
+ try {
4563
+ console.log(import_chalk2.default.green("\u{1F4DD} Adding rule configuration..."));
4564
+ const validTypes = ["cell", "alias", "rowCell", "mergeCell"];
4565
+ let rules = [];
4566
+ if (options.file) {
4567
+ console.log(import_chalk2.default.gray(`Reading rules from file: ${options.file}`));
4568
+ rules = await parseRulesFromFile(options.file);
4569
+ console.log(import_chalk2.default.green(`\u2713 Loaded ${rules.length} rules from file`));
4570
+ } else if (options.rule) {
4571
+ const ruleArray = Array.isArray(options.rule) ? options.rule : [options.rule];
4572
+ if (options.type) {
4573
+ if (!validTypes.includes(options.type)) {
4574
+ console.error(import_chalk2.default.red(`Invalid rule type: ${options.type}. Must be one of: ${validTypes.join(", ")}`));
4575
+ process.exit(1);
4576
+ }
4577
+ for (const rule of ruleArray) {
4578
+ rules.push({ type: options.type, rule });
4579
+ }
4580
+ } else {
4581
+ console.error(import_chalk2.default.red("Error: -t,--type is required when using -r,--rule"));
4582
+ process.exit(1);
4583
+ }
4584
+ console.log(import_chalk2.default.green(`\u2713 Loaded ${rules.length} rules from command line`));
4585
+ } else {
4586
+ console.error(import_chalk2.default.red("Error: Either -f,--file or -r,--rule must be specified"));
4587
+ process.exit(1);
4588
+ }
4589
+ if (rules.length === 0) {
4590
+ console.error(import_chalk2.default.red("Error: No rules to add"));
4591
+ process.exit(1);
4592
+ }
4593
+ const filePath = await resolveFilePath(xlsxFile);
4594
+ console.log(import_chalk2.default.gray(`Loading file: ${filePath}`));
4595
+ const buffer = await fs4.readFile(filePath);
4596
+ const updatedBuffer = await addMultipleRulesToSheet(buffer, rules);
4597
+ const outputFile = options.save || path3.join(process.cwd(), generateOutputFilename(xlsxFile));
4598
+ console.log(import_chalk2.default.gray(`Saving to: ${outputFile}`));
4599
+ await fs4.writeFile(outputFile, updatedBuffer);
4600
+ console.log(import_chalk2.default.green("\u2713 All rules added successfully!"));
4601
+ console.log(import_chalk2.default.green(`\u{1F4C1} Output: ${outputFile}`));
4602
+ } catch (error) {
4603
+ console.error(import_chalk2.default.red("\u2717 Failed to add rule configuration:"));
4604
+ console.error(import_chalk2.default.red(error instanceof Error ? error.message : String(error)));
4605
+ process.exit(1);
4606
+ }
4607
+ });
4608
+ program.parse(process.argv);
4609
+ }
4610
+ main().catch((error) => {
4611
+ console.error(import_chalk2.default.red("\u2717 Fatal error:"));
4612
+ console.error(import_chalk2.default.red(error instanceof Error ? error.message : String(error)));
4613
+ process.exit(1);
1634
4614
  });
1635
- program.parse(process.argv);
1636
4615
  //# sourceMappingURL=bin.js.map