@vdhewei/xlsx-template-lib 1.5.1 → 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/README.md +1012 -2
- package/README.zh-CN.md +1016 -0
- package/dist/bin.js +3015 -36
- package/dist/bin.js.map +1 -1
- package/dist/bin.mjs +334 -14
- package/dist/bin.mjs.map +1 -1
- package/dist/chunk-3GDQP6AS.mjs +16 -0
- package/dist/chunk-3GDQP6AS.mjs.map +1 -0
- package/dist/{chunk-X6Y7DXP6.mjs → chunk-NSFBG6PV.mjs} +24 -3
- package/dist/{chunk-X6Y7DXP6.mjs.map → chunk-NSFBG6PV.mjs.map} +1 -1
- package/dist/index.js +23 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/main-UKT22V6T.mjs +400 -0
- package/dist/main-UKT22V6T.mjs.map +1 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,7 +1,1017 @@
|
|
|
1
|
-
|
|
1
|
+
# xlsx-template-lib
|
|
2
|
+
|
|
3
|
+
[中文文档](./README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
A powerful XLSX template rendering library based on ExcelJS, supporting template-based Excel file generation and data substitution.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Template Rendering**: Render Excel files using templates with placeholders
|
|
10
|
+
- **Data Substitution**: Dynamic data substitution with expressions and functions
|
|
11
|
+
- **Rule Configuration**: Configure rendering rules via dedicated rule sheets
|
|
12
|
+
- **Custom Commands**: Extend functionality with custom command functions (e.g., `fn:sum`, `fn:sub`)
|
|
13
|
+
- **ZIP Support**: Batch process multiple Excel files within a ZIP archive
|
|
14
|
+
- **TypeScript Support**: Full TypeScript support with type definitions
|
|
15
|
+
- **CLI Tool**: Command-line interface for quick processing
|
|
2
16
|
|
|
3
17
|
## Installation
|
|
4
18
|
|
|
5
19
|
```bash
|
|
6
20
|
npm install @vdhewei/xlsx-template-lib
|
|
7
|
-
```
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Template Syntax
|
|
24
|
+
|
|
25
|
+
### Placeholder Format
|
|
26
|
+
|
|
27
|
+
Use `${variableName}` format in Excel cells for data substitution:
|
|
28
|
+
|
|
29
|
+
| Template (Before) | Rendered (After) |
|
|
30
|
+
|:------------------|:-----------------|
|
|
31
|
+
| `${contract.contractCode}` | `CTR-2024-001` |
|
|
32
|
+
| `${exportData.LRR.mothOrYear}` | `2024-01` |
|
|
33
|
+
| `${contract.contractTitle}` | `Construction Project A` |
|
|
34
|
+
|
|
35
|
+
### Placeholder Types
|
|
36
|
+
|
|
37
|
+
#### 1. Simple Values (Scalars)
|
|
38
|
+
|
|
39
|
+
Replace a placeholder with a single value.
|
|
40
|
+
|
|
41
|
+
**Excel template:**
|
|
42
|
+
```
|
|
43
|
+
A B
|
|
44
|
+
1 Extracted on: ${extractDate}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Code:**
|
|
48
|
+
```typescript
|
|
49
|
+
const values = {
|
|
50
|
+
extractDate: new Date('2024-01-15')
|
|
51
|
+
};
|
|
52
|
+
template.substitute(1, values);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Result:**
|
|
56
|
+
```
|
|
57
|
+
A B
|
|
58
|
+
1 Extracted on: Jan-15-2024
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Notes:**
|
|
62
|
+
- Placeholders can be standalone in a cell or part of text: "Total: ${amount}"
|
|
63
|
+
- Excel cell formatting (date, number, currency) is preserved
|
|
64
|
+
|
|
65
|
+
#### 2. Array Indexing
|
|
66
|
+
|
|
67
|
+
Access specific array elements directly in templates.
|
|
68
|
+
|
|
69
|
+
**Excel template:**
|
|
70
|
+
```
|
|
71
|
+
A B
|
|
72
|
+
1 First date: ${dates[0]}
|
|
73
|
+
2 Second date: ${dates[1]}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Code:**
|
|
77
|
+
```typescript
|
|
78
|
+
const values = {
|
|
79
|
+
dates: [new Date('2024-01-01'), new Date('2024-02-01')]
|
|
80
|
+
};
|
|
81
|
+
template.substitute(1, values);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Result:**
|
|
85
|
+
```
|
|
86
|
+
A B
|
|
87
|
+
1 First date: Jan-01-2024
|
|
88
|
+
2 Second date: Feb-01-2024
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### 3. Column Arrays
|
|
92
|
+
|
|
93
|
+
Expand an array horizontally across columns.
|
|
94
|
+
|
|
95
|
+
**Excel template:**
|
|
96
|
+
```
|
|
97
|
+
A
|
|
98
|
+
1 ${dates}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Code:**
|
|
102
|
+
```typescript
|
|
103
|
+
const values = {
|
|
104
|
+
dates: [
|
|
105
|
+
new Date('2024-01-01'),
|
|
106
|
+
new Date('2024-02-01'),
|
|
107
|
+
new Date('2024-03-01')
|
|
108
|
+
]
|
|
109
|
+
};
|
|
110
|
+
template.substitute(1, values);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Result:**
|
|
114
|
+
```
|
|
115
|
+
A B C
|
|
116
|
+
1 Jan-01-2024 Feb-01-2024 Mar-01-2024
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Note:** The placeholder must be the only content in its cell
|
|
120
|
+
|
|
121
|
+
#### 4. Table Rows
|
|
122
|
+
|
|
123
|
+
Generate multiple rows from an array of objects.
|
|
124
|
+
|
|
125
|
+
**Excel template:**
|
|
126
|
+
```
|
|
127
|
+
A B C
|
|
128
|
+
1 Name Age Department
|
|
129
|
+
2 ${team.name} ${team.age} ${team.dept}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Code:**
|
|
133
|
+
```typescript
|
|
134
|
+
const values = {
|
|
135
|
+
team: [
|
|
136
|
+
{ name: 'Alice Johnson', age: 28, dept: 'Engineering' },
|
|
137
|
+
{ name: 'Bob Smith', age: 34, dept: 'Marketing' },
|
|
138
|
+
{ name: 'Carol White', age: 25, dept: 'Sales' }
|
|
139
|
+
]
|
|
140
|
+
};
|
|
141
|
+
template.substitute(1, values);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Result:**
|
|
145
|
+
```
|
|
146
|
+
A B C
|
|
147
|
+
1 Name Age Department
|
|
148
|
+
2 Alice Johnson 28 Engineering
|
|
149
|
+
3 Bob Smith 34 Marketing
|
|
150
|
+
4 Carol White 25 Sales
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Syntax:** `${table:arrayName.propertyName}`
|
|
154
|
+
- Each object in the array creates a new row
|
|
155
|
+
- If a property is an array, it expands horizontally
|
|
156
|
+
|
|
157
|
+
#### 5. Images
|
|
158
|
+
|
|
159
|
+
Insert images into cells.
|
|
160
|
+
|
|
161
|
+
**Excel template:**
|
|
162
|
+
```
|
|
163
|
+
A B
|
|
164
|
+
1 Logo: ${image:companyLogo}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Code:**
|
|
168
|
+
```typescript
|
|
169
|
+
const values = {
|
|
170
|
+
companyLogo: '/path/to/logo.png' // or Base64, Buffer
|
|
171
|
+
};
|
|
172
|
+
template.substitute(1, values);
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**Result:**
|
|
176
|
+
```
|
|
177
|
+
A B
|
|
178
|
+
1 Logo: 🖼️
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Supported image formats:**
|
|
182
|
+
- File path (absolute or relative): '/path/to/image.png'
|
|
183
|
+
- Base64 string: 'data:image/png;base64,iVBORw0KG...'
|
|
184
|
+
- Buffer: fs.readFileSync('image.png')
|
|
185
|
+
|
|
186
|
+
**Image options:**
|
|
187
|
+
```typescript
|
|
188
|
+
const template = new XlsxTemplate(data, {
|
|
189
|
+
imageRootPath: '/absolute/path/to/images', // Base path for relative image paths
|
|
190
|
+
imageRatio: 75 // Scale images to 75%
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Table images:**
|
|
195
|
+
```
|
|
196
|
+
A B
|
|
197
|
+
1 Product Photo
|
|
198
|
+
2 ${products.name} ${products.photo:image}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Code:**
|
|
202
|
+
```typescript
|
|
203
|
+
const values = {
|
|
204
|
+
products: [
|
|
205
|
+
{ name: 'Product 1', photo: 'product1.jpg' },
|
|
206
|
+
{ name: 'Product 2', photo: 'product2.jpg' }
|
|
207
|
+
]
|
|
208
|
+
};
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Result:**
|
|
212
|
+
```
|
|
213
|
+
A B
|
|
214
|
+
1 Product Photo
|
|
215
|
+
2 Product 1 🖼️
|
|
216
|
+
3 Product 2 🖼️
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
| Template (Before) | Rendered (After) |
|
|
220
|
+
|:------------------|:-----------------|
|
|
221
|
+
| `${contract.contractCode}` | `CTR-2024-001` |
|
|
222
|
+
| `${exportData.LRR.mothOrYear}` | `2024-01` |
|
|
223
|
+
| `${contract.contractTitle}` | `Construction Project A` |
|
|
224
|
+
|
|
225
|
+
### Compile Rules Configuration
|
|
226
|
+
|
|
227
|
+
Configure rendering rules in a rule sheet (e.g., `export.metadata.config`) with the following syntax:
|
|
228
|
+
|
|
229
|
+
**⚠️ Important Rule:**
|
|
230
|
+
- **Duplicate rules within the same sheet are invalid and may cause compilation errors**
|
|
231
|
+
- Each rule type must have unique configurations within the same sheet
|
|
232
|
+
|
|
233
|
+
| Rule Type | Syntax | Description |
|
|
234
|
+
|:----------|:-------|:------------|
|
|
235
|
+
| **alias** | `alias: @#key => use aliasKey: @# => @#` | Alias for field mapping |
|
|
236
|
+
| **rowCell** | `G-AP:12=compile GenCell(...)` | Row rule configuration |
|
|
237
|
+
| **mergeCell** | `G-AQ:13-17=sum(...)` | Merge cell calculation |
|
|
238
|
+
| **cell** | `D-7=@#[@D.MY]` | Single cell value assignment |
|
|
239
|
+
|
|
240
|
+
#### Alias Rules
|
|
241
|
+
|
|
242
|
+
Define abbreviations for variable names or variable expression values. Multiple alias configurations are supported.
|
|
243
|
+
|
|
244
|
+
**Syntax:** `alias abbreviation=originalVariable/originalExpression`
|
|
245
|
+
|
|
246
|
+
**Rules:**
|
|
247
|
+
- Alias abbreviations must be unique within the same sheet
|
|
248
|
+
- Aliases can be referenced using `@aliasName` in expressions
|
|
249
|
+
|
|
250
|
+
**Examples:**
|
|
251
|
+
|
|
252
|
+
| Alias Configuration | Description |
|
|
253
|
+
|:--------------------|:------------|
|
|
254
|
+
| `T=template` | Map `T` to `template` |
|
|
255
|
+
| `LLR=exportData.LRR` | Map `LLR` to `exportData.LRR` |
|
|
256
|
+
|
|
257
|
+
**Usage in Expressions:**
|
|
258
|
+
|
|
259
|
+
```
|
|
260
|
+
Before: ${exportData.LRR.value}
|
|
261
|
+
After: ${@LLR.value}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### RowCell Rules
|
|
265
|
+
|
|
266
|
+
Configure row rules to assign values to cell ranges. Multiple rowCell configurations are supported.
|
|
267
|
+
|
|
268
|
+
**Syntax:** `columnStartNum-columnEndNum:rowNum=valueExpression`
|
|
269
|
+
|
|
270
|
+
**Range Format:**
|
|
271
|
+
- `columnStartNum-columnEndNum:rowNum`
|
|
272
|
+
- Example: `G-AP:12` (columns G to AP, row 12)
|
|
273
|
+
|
|
274
|
+
**Value Expression:**
|
|
275
|
+
- Typically uses `compile:GenCell` macro replacement or `compile:Macro` expansion
|
|
276
|
+
|
|
277
|
+
**Examples:**
|
|
278
|
+
|
|
279
|
+
| Rule | Description |
|
|
280
|
+
|:-----|:------------|
|
|
281
|
+
| `G-AP:12=compile GenCell(@#item,[compile Macro]#index@0)` | Assign generated values to row 12, columns G-AP |
|
|
282
|
+
| `A-Z:5=compile Macro(@#data,2,5,!!codeKey)` | Assign formatted cell value to row 5, columns A-Z |
|
|
283
|
+
|
|
284
|
+
#### MergeCell Rules
|
|
285
|
+
|
|
286
|
+
Merge cells and apply calculation functions. Multiple mergeCell configurations are supported.
|
|
287
|
+
|
|
288
|
+
**Syntax:** `columnStartNum-columnEndNum:rowStartNum-rowEndNum=functionExpression`
|
|
289
|
+
|
|
290
|
+
**Range Format:**
|
|
291
|
+
- `columnStartNum-columnEndNum:rowStartNum-rowEndNum`
|
|
292
|
+
- Example: `G-AQ:13-17` (columns G to AQ, rows 13 to 17)
|
|
293
|
+
|
|
294
|
+
**Function Expression:**
|
|
295
|
+
- Typically uses `sum` or `sub` functions with macro replacements
|
|
296
|
+
|
|
297
|
+
**Examples:**
|
|
298
|
+
|
|
299
|
+
| Rule | Description |
|
|
300
|
+
|:-----|:------------|
|
|
301
|
+
| `G-AQ:13-17=sum(@LT,[compile:Macro(exprArr,F,13,17,!!codeKey)],compile:Macro(index),0)` | Merge and calculate sum for rows 13-17 |
|
|
302
|
+
| `G-AQ:18-35=sub(@LT,[compile:Macro(exprArr,F,18,35,!!codeKey)],compile:Macro(index),0)` | Merge and calculate difference for rows 18-35 |
|
|
303
|
+
|
|
304
|
+
#### Cell Rules
|
|
305
|
+
|
|
306
|
+
Assign values to single cells.
|
|
307
|
+
|
|
308
|
+
**Syntax:** `columnNum:rowNum=valueExpression`
|
|
309
|
+
|
|
310
|
+
**Coordinate Format:**
|
|
311
|
+
- `columnNum:rowNum`
|
|
312
|
+
- Example: `D:7` (column D, row 7)
|
|
313
|
+
|
|
314
|
+
**Value Expression:**
|
|
315
|
+
- `compile:Macro` expansion
|
|
316
|
+
- Variable placeholder: `${variable}`
|
|
317
|
+
- Variable placeholder with alias: `${@alias}`
|
|
318
|
+
|
|
319
|
+
**Examples:**
|
|
320
|
+
|
|
321
|
+
| Rule | Description |
|
|
322
|
+
|:-----|:------------|
|
|
323
|
+
| `D:7=@#[@D.MY]` | Assign value from expression |
|
|
324
|
+
| `A:1=${contractCode}` | Assign from variable placeholder |
|
|
325
|
+
| `B:1=${@LLR.value}` | Assign from aliased variable |
|
|
326
|
+
|
|
327
|
+
#### Calculation Functions
|
|
328
|
+
|
|
329
|
+
**sum Function**
|
|
330
|
+
|
|
331
|
+
Calculate the sum of multiple values.
|
|
332
|
+
|
|
333
|
+
**Syntax:** `sum(valueRoot,[valueItems...],valueSuffix,defaultValue)`
|
|
334
|
+
|
|
335
|
+
**Parameters:**
|
|
336
|
+
- `valueRoot`: Common parent of all value expressions
|
|
337
|
+
- `valueItems`: Array of child value items
|
|
338
|
+
- `valueSuffix`: Suffix for each value
|
|
339
|
+
- `defaultValue`: Value to return when sum equals 0 (undefined will not return default)
|
|
340
|
+
|
|
341
|
+
**Example:**
|
|
342
|
+
```
|
|
343
|
+
sum(orders,[cat,food,game],1,0)
|
|
344
|
+
// Equivalent to: orders.cat.1 + orders.food.1 + orders.game.1
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
**sub Function**
|
|
348
|
+
|
|
349
|
+
Calculate the difference of multiple values.
|
|
350
|
+
|
|
351
|
+
**Syntax:** `sub(valueRoot,[valueItems...],valueSuffix,defaultValue)`
|
|
352
|
+
|
|
353
|
+
**Parameters:**
|
|
354
|
+
- `valueRoot`: Common parent of all value expressions
|
|
355
|
+
- `valueItems`: Array of child value items
|
|
356
|
+
- `valueSuffix`: Suffix for each value
|
|
357
|
+
- `defaultValue`: Value to return when difference equals 0 (undefined will not return default)
|
|
358
|
+
|
|
359
|
+
**Example:**
|
|
360
|
+
```
|
|
361
|
+
sub(orders,[money,food,game],1,0)
|
|
362
|
+
// Equivalent to: orders.money.1 - orders.food.1 - orders.game.1
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Macro Replacement Rules
|
|
366
|
+
|
|
367
|
+
The library supports powerful macro replacement functions for dynamic cell content generation:
|
|
368
|
+
|
|
369
|
+
#### GenCell Macro
|
|
370
|
+
|
|
371
|
+
Generate cell expressions by concatenating multiple parts:
|
|
372
|
+
|
|
373
|
+
| Syntax | Description | Example | Result |
|
|
374
|
+
|:-------|:------------|:--------|:--------|
|
|
375
|
+
| `compile:GenCell(expr1,expr2,...,exprN)` | Concatenate with default separator `·` | `GenCell(test,1,2)` | `test·1·2` |
|
|
376
|
+
| `compile:GenCell(expr1,expr2,...,exprN,"sep")` | Concatenate with custom separator | `GenCell(test,1,2,"_")` | `test_1_2` |
|
|
377
|
+
| `compile:GenCell(expr1,expr2,...,exprN,"")` | Concatenate without separator | `GenCell(test,1,2,"")` | `test12` |
|
|
378
|
+
|
|
379
|
+
#### Macro Expansion
|
|
380
|
+
|
|
381
|
+
##### Single Cell Macro
|
|
382
|
+
|
|
383
|
+
Expand to a single cell's value:
|
|
384
|
+
|
|
385
|
+
| Syntax | Description | Example |
|
|
386
|
+
|:-------|:------------|:--------|
|
|
387
|
+
| `compile:Macro(expr,columnNum,rowNum)` | Get value from cell at (columnNum, rowNum) | `Macro(data,2,5)` |
|
|
388
|
+
| `compile:Macro(expr,columnNum,rowNum,MacroFormatter)` | Get formatted value | `Macro(data,2,5,!!codeKey)` |
|
|
389
|
+
|
|
390
|
+
**Parameters:**
|
|
391
|
+
- `expr`: Base expression
|
|
392
|
+
- `columnNum`: Column number (1-indexed)
|
|
393
|
+
- `rowNum`: Row number (1-indexed)
|
|
394
|
+
- `MacroFormatter`: Optional formatter (see below)
|
|
395
|
+
|
|
396
|
+
##### Multiple Cells Macro
|
|
397
|
+
|
|
398
|
+
Expand to multiple cell values:
|
|
399
|
+
|
|
400
|
+
| Syntax | Description | Example |
|
|
401
|
+
|:-------|:------------|:--------|
|
|
402
|
+
| `compile:Macro(exprArr,columnNum,rowStartNum,rowEndNum)` | Get values from cell range | `Macro(data,1,1,5)` |
|
|
403
|
+
| `compile:Macro(exprArr,columnNum,rowStartNum,rowEndNum,MacroFormatter)` | Get formatted values | `Macro(data,1,1,5,!!number)` |
|
|
404
|
+
|
|
405
|
+
**Parameters:**
|
|
406
|
+
- `exprArr`: Base expression array
|
|
407
|
+
- `columnNum`: Column number (1-indexed)
|
|
408
|
+
- `rowStartNum`: Start row number (1-indexed)
|
|
409
|
+
- `rowEndNum`: End row number (1-indexed)
|
|
410
|
+
- `MacroFormatter`: Optional formatter
|
|
411
|
+
|
|
412
|
+
##### Index Macro
|
|
413
|
+
|
|
414
|
+
Generate iteration sequence starting from 1:
|
|
415
|
+
|
|
416
|
+
| Syntax | Description | Example Usage | Result |
|
|
417
|
+
|:-------|:------------|:--------------|:--------|
|
|
418
|
+
| `compile:Macro(index)` | Auto-increment index (1-based) | Row 1: `Macro(index)` | `1` |
|
|
419
|
+
| | | Row 2: `Macro(index)` | `2` |
|
|
420
|
+
| | | Row 3: `Macro(index)` | `3` |
|
|
421
|
+
|
|
422
|
+
#### Macro Formatters
|
|
423
|
+
|
|
424
|
+
Format macro output using special formatters starting with `!!`:
|
|
425
|
+
|
|
426
|
+
| Formatter | Description | Input | Output |
|
|
427
|
+
|:----------|:------------|:-------|:--------|
|
|
428
|
+
| `!!codeKey` | Convert special chars (`@-[]{}\/'.`) to `_`, remove extra `__`, trim leading/trailing `_`, convert to uppercase | `test..x` | `TEST_X` |
|
|
429
|
+
| | | `@data-value` | `DATA_VALUE` |
|
|
430
|
+
| | | `[item].name` | `ITEM_NAME` |
|
|
431
|
+
| `!!codeKeyAlias` | Same as `!!codeKey` but adds prefix (default `@`) | `test..x` | `@TEST_X` |
|
|
432
|
+
| | (with default prefix `@`) | `data.value` | `@DATA_VALUE` |
|
|
433
|
+
| `!!number` | Convert to decimal integer, supports `0x` hex prefix | `123` | `123` |
|
|
434
|
+
| | | `0xFF` | `255` |
|
|
435
|
+
| | | `abc` | `abc` (unchanged, NaN) |
|
|
436
|
+
|
|
437
|
+
**CodeKey Conversion Rules:**
|
|
438
|
+
- Special characters replaced: `@`, `-`, space, `[`, `]`, `{`, `}`, `\`, `/`, `'`, `.`
|
|
439
|
+
- Multiple consecutive `__` collapsed to single `_`
|
|
440
|
+
- Leading and trailing `_` removed
|
|
441
|
+
- Final result converted to uppercase
|
|
442
|
+
|
|
443
|
+
#### Macro Examples
|
|
444
|
+
|
|
445
|
+
**Example 1: Generate CodeKey with Row Cell**
|
|
446
|
+
|
|
447
|
+
```
|
|
448
|
+
Rule: G-AQ:117=compile GenCell(#LT[compile Macro]#err@F118[#codeKey],[compile Macro]#index@0)
|
|
449
|
+
Result: errValue·1, errValue·2, errValue·3, ...
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
**Example 2: Format Cell Value with CodeKey**
|
|
453
|
+
|
|
454
|
+
```
|
|
455
|
+
Rule: D-7=compile Macro(@#[@D.MY],5,7,!!codeKey)
|
|
456
|
+
If cell(5,7) = "project-alpha-2024"
|
|
457
|
+
Result: PROJECT_ALPHA_2024
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
**Example 3: Generate CodeKeyAlias**
|
|
461
|
+
|
|
462
|
+
```
|
|
463
|
+
Rule: cell F-10=compile Macro(@#key,3,10,!!codeKeyAlias)
|
|
464
|
+
If cell(3,10) = "test..data"
|
|
465
|
+
Result: @TEST_DATA
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
**Example 4: Number Conversion**
|
|
469
|
+
|
|
470
|
+
```
|
|
471
|
+
Rule: row-5=compile Macro(@#value,2,5,!!number)
|
|
472
|
+
If cell(2,5) = "42"
|
|
473
|
+
Result: 42
|
|
474
|
+
|
|
475
|
+
Rule: row-6=compile Macro(@#hex,4,6,!!number)
|
|
476
|
+
If cell(4,6) = "0x1A"
|
|
477
|
+
Result: 26
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
**Example 5: Iteration with Index**
|
|
481
|
+
|
|
482
|
+
```
|
|
483
|
+
Row 1: Code-${compile:Macro(index)} → Code-1
|
|
484
|
+
Row 2: Code-${compile:Macro(index)} → Code-2
|
|
485
|
+
Row 3: Code-${compile:Macro(index)} → Code-3
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
#### Complete Rule Configuration Example
|
|
489
|
+
|
|
490
|
+
A complete example of a rule sheet (`export.metadata.config`) with all rule types:
|
|
491
|
+
|
|
492
|
+
```
|
|
493
|
+
# Alias Rules (define shortcuts for long expressions)
|
|
494
|
+
T=template
|
|
495
|
+
LLR=exportData.LRR
|
|
496
|
+
CTR=contract.contractCode
|
|
497
|
+
|
|
498
|
+
# RowCell Rules (assign values to cell ranges)
|
|
499
|
+
G-AQ:12=compile GenCell(@#item,[compile Macro]#index@0)
|
|
500
|
+
A-Z:5=compile Macro(@#data,2,5,!!codeKey)
|
|
501
|
+
|
|
502
|
+
# MergeCell Rules (merge cells and apply calculations)
|
|
503
|
+
G-AQ:13-17=sum(@LT,[compile:Macro(exprArr,F,13,17,!!codeKey)],compile:Macro(index),0)
|
|
504
|
+
G-AQ:18-35=sub(@LT,[compile:Macro(exprArr,F,18,35,!!codeKey)],compile:Macro(index),0)
|
|
505
|
+
|
|
506
|
+
# Cell Rules (assign values to single cells)
|
|
507
|
+
D:7=@#[@D.MY]
|
|
508
|
+
A:1=${@CTR}
|
|
509
|
+
B:1=${@LLR.value}
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
**⚠️ Important Notes:**
|
|
513
|
+
- Each rule type (alias, rowCell, mergeCell, cell) can appear multiple times
|
|
514
|
+
- But **duplicate rules of the same type with the same configuration are invalid**
|
|
515
|
+
- Alias abbreviations must be unique within the sheet
|
|
516
|
+
- Row/column ranges must not overlap in conflicting ways
|
|
517
|
+
|
|
518
|
+
### Render Functions
|
|
519
|
+
|
|
520
|
+
Built-in and custom functions for data processing:
|
|
521
|
+
|
|
522
|
+
| Function | Syntax | Example |
|
|
523
|
+
|:---------|:-------|:--------|
|
|
524
|
+
| **sum** | `fn:sum(...values)` | `fn:sum(10, 20, 30)` => `60` |
|
|
525
|
+
| **sub** | `fn:sub(a, b)` | `fn:sub(100, 30)` => `70` |
|
|
526
|
+
| **Custom Function** | `fn:customName(...args)` | User-defined logic |
|
|
527
|
+
|
|
528
|
+
## Quick Start
|
|
529
|
+
|
|
530
|
+
### Basic Usage
|
|
531
|
+
|
|
532
|
+
```typescript
|
|
533
|
+
import { ZipXlsxTemplateApp } from '@vdhewei/xlsx-template-lib';
|
|
534
|
+
import * as fs from 'node:fs/promises';
|
|
535
|
+
|
|
536
|
+
// Load template from buffer
|
|
537
|
+
const templateBuffer = await fs.readFile('template.xlsx');
|
|
538
|
+
const app = new ZipXlsxTemplateApp(templateBuffer);
|
|
539
|
+
|
|
540
|
+
// Render with data
|
|
541
|
+
const data = {
|
|
542
|
+
contract: {
|
|
543
|
+
contractCode: 'CTR-2024-001',
|
|
544
|
+
contractTitle: 'Construction Project A'
|
|
545
|
+
},
|
|
546
|
+
exportData: {
|
|
547
|
+
LRR: {
|
|
548
|
+
mothOrYear: '2024-01'
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
|
|
553
|
+
await app.substituteAll(data);
|
|
554
|
+
|
|
555
|
+
// Generate output
|
|
556
|
+
const output = await app.generate();
|
|
557
|
+
await fs.writeFile('output.xlsx', output);
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### Using XlsxRender
|
|
561
|
+
|
|
562
|
+
```typescript
|
|
563
|
+
import { XlsxRender } from '@vdhewei/xlsx-template-lib';
|
|
564
|
+
|
|
565
|
+
const templateBuffer = await fs.readFile('template.xlsx');
|
|
566
|
+
const xlsx = await XlsxRender.create(templateBuffer);
|
|
567
|
+
|
|
568
|
+
// Render a specific sheet
|
|
569
|
+
await xlsx.render({
|
|
570
|
+
contract: { contractCode: 'CTR-001' }
|
|
571
|
+
}, 'Sheet1');
|
|
572
|
+
|
|
573
|
+
// Generate output
|
|
574
|
+
const buffer = await xlsx.generate();
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
### Compile and Render with Rules
|
|
578
|
+
|
|
579
|
+
```typescript
|
|
580
|
+
import {
|
|
581
|
+
ZipXlsxTemplateApp,
|
|
582
|
+
compileAll,
|
|
583
|
+
AddCommand
|
|
584
|
+
} from '@vdhewei/xlsx-template-lib';
|
|
585
|
+
|
|
586
|
+
// Add custom render function
|
|
587
|
+
AddCommand('sum', (obj, args) => {
|
|
588
|
+
return args.groups.reduce((acc, val) => acc + Number(val), 0);
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
// Process with compile options
|
|
592
|
+
const compileOpts = {
|
|
593
|
+
sheetName: 'export.metadata.config', // Rule configuration sheet
|
|
594
|
+
remove: true // Remove rule sheet after compile
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
const zipBuffer = await fs.readFile('template.xlsx');
|
|
598
|
+
const result = await ZipXlsxTemplateApp.compileTo(zipBuffer, {
|
|
599
|
+
checker: async (buf, opts, values, fileName) => {
|
|
600
|
+
// Custom validation logic
|
|
601
|
+
return buf;
|
|
602
|
+
},
|
|
603
|
+
options: compileOpts
|
|
604
|
+
}, renderData);
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
### CLI Tool
|
|
608
|
+
|
|
609
|
+
The CLI tool `xlsx-cli` provides command-line interface for quick Excel template processing.
|
|
610
|
+
|
|
611
|
+
#### Installation
|
|
612
|
+
|
|
613
|
+
```bash
|
|
614
|
+
npm install -g @vdhewei/xlsx-template-lib
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
Or use directly from `npx`:
|
|
618
|
+
|
|
619
|
+
```bash
|
|
620
|
+
npx @vdhewei/xlsx-template-lib <command> [options]
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
#### Commands
|
|
624
|
+
|
|
625
|
+
##### 1. Compile Command
|
|
626
|
+
|
|
627
|
+
Compile Excel files with rule configurations.
|
|
628
|
+
|
|
629
|
+
```bash
|
|
630
|
+
xlsx-cli compile <xlsx-file> [options]
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
**Arguments:**
|
|
634
|
+
- `<xlsx-file>` - Path to the Excel file
|
|
635
|
+
|
|
636
|
+
**Options:**
|
|
637
|
+
- `-s, --save <string>` - Save compiled file to specified directory (default: current directory)
|
|
638
|
+
- `-n, --sheet-name <string>` - Sheet name to compile (default: first sheet)
|
|
639
|
+
- `-r, --remove` - Remove configure rules sheet after compilation (default: false)
|
|
640
|
+
|
|
641
|
+
**Examples:**
|
|
642
|
+
|
|
643
|
+
```bash
|
|
644
|
+
# Basic compile with default settings
|
|
645
|
+
xlsx-cli compile template.xlsx
|
|
646
|
+
|
|
647
|
+
# Compile and save to specific location
|
|
648
|
+
xlsx-cli compile template.xlsx -s ./output/
|
|
649
|
+
|
|
650
|
+
# Compile specific sheet
|
|
651
|
+
xlsx-cli compile template.xlsx -n Sheet1
|
|
652
|
+
|
|
653
|
+
# Compile and remove config sheet
|
|
654
|
+
xlsx-cli compile template.xlsx -r
|
|
655
|
+
|
|
656
|
+
# Full example
|
|
657
|
+
xlsx-cli compile template.xlsx -s ./output/ -n Sheet1 -r
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
**Output:**
|
|
661
|
+
- Compiled Excel file saved as `<filename>_<timestamp>.xlsx`
|
|
662
|
+
- Success messages displayed in green
|
|
663
|
+
- Errors displayed in red with process exit code 1
|
|
664
|
+
|
|
665
|
+
##### 2. Render Command
|
|
666
|
+
|
|
667
|
+
Render Excel templates with data substitution.
|
|
668
|
+
|
|
669
|
+
```bash
|
|
670
|
+
xlsx-cli render <xlsx-file> [options]
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
**Arguments:**
|
|
674
|
+
- `<xlsx-file>` - Path to the Excel template file
|
|
675
|
+
|
|
676
|
+
**Options:**
|
|
677
|
+
- `-c, --compile` - Auto-compile rules before rendering (default: false)
|
|
678
|
+
- `-n, --sheet-name <string>` - Sheet name to render (default: first sheet)
|
|
679
|
+
- `-s, --save <string>` - Save rendered file to specified directory (default: current directory)
|
|
680
|
+
- `-d, --data <string>` - Render data source (JSON string, file path, or URL)
|
|
681
|
+
|
|
682
|
+
**Examples:**
|
|
683
|
+
|
|
684
|
+
```bash
|
|
685
|
+
# Basic render with empty data
|
|
686
|
+
xlsx-cli render template.xlsx
|
|
687
|
+
|
|
688
|
+
# Render with JSON data string
|
|
689
|
+
xlsx-cli render template.xlsx -d '{"name":"John","age":30}'
|
|
690
|
+
|
|
691
|
+
# Render with JSON file
|
|
692
|
+
xlsx-cli render template.xlsx -d ./data.json
|
|
693
|
+
|
|
694
|
+
# Render with remote JSON URL
|
|
695
|
+
xlsx-cli render template.xlsx -d 'https://api.example.com/data.json'
|
|
696
|
+
|
|
697
|
+
# Render with auto-compile
|
|
698
|
+
xlsx-cli render template.xlsx -c -d './data.json'
|
|
699
|
+
|
|
700
|
+
# Render specific sheet
|
|
701
|
+
xlsx-cli render template.xlsx -n Sheet1 -d './data.json'
|
|
702
|
+
|
|
703
|
+
# Full example
|
|
704
|
+
xlsx-cli render template.xlsx -c -n Sheet1 -s ./output/ -d './data.json'
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
**Data Sources:**
|
|
708
|
+
- **JSON String**: Direct JSON string enclosed in single quotes
|
|
709
|
+
- **Local File**: Path to `.json` file (relative or absolute)
|
|
710
|
+
- **Remote URL**: HTTP/HTTPS URL returning JSON
|
|
711
|
+
|
|
712
|
+
**Output:**
|
|
713
|
+
- Rendered Excel file saved as `<filename>_<timestamp>.xlsx`
|
|
714
|
+
- Validation checks for sheet existence
|
|
715
|
+
- Success/error messages with appropriate colors
|
|
716
|
+
|
|
717
|
+
##### 3. Rules Command
|
|
718
|
+
|
|
719
|
+
Add rule configurations to Excel files.
|
|
720
|
+
|
|
721
|
+
```bash
|
|
722
|
+
xlsx-cli rules <xlsx-file> [options]
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
**Arguments:**
|
|
726
|
+
- `<xlsx-file>` - Path to the Excel file
|
|
727
|
+
|
|
728
|
+
**Options:**
|
|
729
|
+
|
|
730
|
+
**Mode 1: Command Line Rules**
|
|
731
|
+
- `-t, --type <string>` - Rule type: `cell`, `alias`, `rowCell`, `mergeCell` (required when using -r)
|
|
732
|
+
- `-r, --rule <string>` - Rule expression string (can be specified multiple times)
|
|
733
|
+
|
|
734
|
+
**Mode 2: File Rules**
|
|
735
|
+
- `-f, --file <string>` - Read rules from file (format: `<type> ruleExpr` per line)
|
|
736
|
+
- Lines starting with `#` are treated as comments
|
|
737
|
+
- Empty lines are skipped
|
|
738
|
+
- Rule types: `cell`, `alias`, `rowCell`, `mergeCell`
|
|
739
|
+
|
|
740
|
+
**Common Options:**
|
|
741
|
+
- `-s, --save <string>` - Save compiled file to specified directory (default: current directory)
|
|
742
|
+
|
|
743
|
+
**Examples:**
|
|
744
|
+
|
|
745
|
+
**Single Rule (Command Line):**
|
|
746
|
+
```bash
|
|
747
|
+
# Add alias rule
|
|
748
|
+
xlsx-cli rules template.xlsx -t alias -r 'T=template'
|
|
749
|
+
|
|
750
|
+
# Add cell rule
|
|
751
|
+
xlsx-cli rules template.xlsx -t cell -r 'D:7=${@LLR.value}'
|
|
752
|
+
|
|
753
|
+
# Add rowCell rule
|
|
754
|
+
xlsx-cli rules template.xlsx -t rowCell -r 'G-AQ:12=compile GenCell(@#item,[compile Macro]#index@0)'
|
|
755
|
+
|
|
756
|
+
# Add mergeCell rule
|
|
757
|
+
xlsx-cli rules template.xlsx -t mergeCell -r 'G-AQ:13-17=sum(@LT,[compile:Macro(exprArr,F,13,17,!!codeKey)],compile:Macro(index),0)'
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
**Multiple Rules (Command Line):**
|
|
761
|
+
```bash
|
|
762
|
+
# Add multiple rules with same type
|
|
763
|
+
xlsx-cli rules template.xlsx -t cell -r 'D:7=${@LLR.value}' -r 'A:1=${@T}' -r 'B:1=${@LLR.value}'
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
**Rules from File:**
|
|
767
|
+
```bash
|
|
768
|
+
# Read rules from file
|
|
769
|
+
xlsx-cli rules template.xlsx -f rules.txt
|
|
770
|
+
|
|
771
|
+
# Create rules.txt file:
|
|
772
|
+
# This is a comment
|
|
773
|
+
alias T=template
|
|
774
|
+
alias LLR=exportData.LRR
|
|
775
|
+
cell D:7=${@T}
|
|
776
|
+
cell A:1=${@LLR.value}
|
|
777
|
+
rowCell G-AQ:12=compile GenCell(@#item,[compile Macro]#index@0)
|
|
778
|
+
mergeCell G-AQ:13-17=sum(@LT,[compile:Macro(exprArr,F,13,17,!!codeKey)],compile:Macro(index),0)
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
**Save to Specific Directory:**
|
|
782
|
+
```bash
|
|
783
|
+
xlsx-cli rules template.xlsx -f rules.txt -s ./output/
|
|
784
|
+
xlsx-cli rules template.xlsx -t cell -r 'D:7=${@LLR.value}' -s ./output/
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
**File Format (-f mode):**
|
|
788
|
+
```bash
|
|
789
|
+
# Format: <type> ruleExpr
|
|
790
|
+
# Comments start with #
|
|
791
|
+
# Valid types: cell, alias, rowCell, mergeCell
|
|
792
|
+
|
|
793
|
+
cell D:7=${@LLR.value}
|
|
794
|
+
alias T=template
|
|
795
|
+
rowCell G-AQ:12=compile GenCell(@#item,[compile Macro]#index@0)
|
|
796
|
+
mergeCell G-AQ:13-17=sum(@LT,[compile:Macro(exprArr,F,13,17,!!codeKey)],compile:Macro(index),0)
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
**Behavior:**
|
|
800
|
+
- Creates `export_metadata.config` sheet if not exists
|
|
801
|
+
- Adds rule with proper styling: bold + center alignment for type, center alignment for expression
|
|
802
|
+
- Auto-adjusts column widths based on content
|
|
803
|
+
- Each rule type (cell, alias, rowCell, mergeCell) supports up to 4 rules per row
|
|
804
|
+
- If more than 4 rules are added for same type, automatically creates a new row
|
|
805
|
+
- Outputs new file with timestamp
|
|
806
|
+
|
|
807
|
+
#### Common Features
|
|
808
|
+
|
|
809
|
+
**Environment Variables:**
|
|
810
|
+
- CLI automatically loads `.env` file from current directory if present
|
|
811
|
+
|
|
812
|
+
**File Path Resolution:**
|
|
813
|
+
- Supports absolute and relative paths
|
|
814
|
+
- Resolves paths relative to current working directory
|
|
815
|
+
- Validates file existence before processing
|
|
816
|
+
|
|
817
|
+
**Error Handling:**
|
|
818
|
+
- All errors displayed in red using chalk
|
|
819
|
+
- Non-zero exit code on errors
|
|
820
|
+
- Detailed error messages for debugging
|
|
821
|
+
|
|
822
|
+
**Cross-Platform Support:**
|
|
823
|
+
- Works on Windows, Linux, and macOS
|
|
824
|
+
- Uses platform-independent path handling
|
|
825
|
+
|
|
826
|
+
**Output Filename Format:**
|
|
827
|
+
- Default: `<input-filename>_<timestamp>.xlsx`
|
|
828
|
+
- Timestamp in milliseconds since epoch
|
|
829
|
+
- Preserves original file name
|
|
830
|
+
|
|
831
|
+
**Verbose Logging:**
|
|
832
|
+
- Gray informational messages for process steps
|
|
833
|
+
- Green success messages
|
|
834
|
+
- Red error messages
|
|
835
|
+
- Yellow warnings
|
|
836
|
+
|
|
837
|
+
## Advanced Features
|
|
838
|
+
|
|
839
|
+
### Custom Commands (Render Functions)
|
|
840
|
+
|
|
841
|
+
```typescript
|
|
842
|
+
import { AddCommand, generateCommandsXlsxTemplate } from '@vdhewei/xlsx-template-lib';
|
|
843
|
+
|
|
844
|
+
// Add custom command
|
|
845
|
+
AddCommand('multiply', (obj, args) => {
|
|
846
|
+
const values = args.groups.map(g => valueDotGet(obj, g));
|
|
847
|
+
return values.reduce((a, b) => a * b, 1);
|
|
848
|
+
});
|
|
849
|
+
|
|
850
|
+
// Generate template with custom commands
|
|
851
|
+
const buffer = await generateCommandsXlsxTemplate(data, options);
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
### Batch Processing
|
|
855
|
+
|
|
856
|
+
```typescript
|
|
857
|
+
// Process ZIP file containing multiple XLSX files
|
|
858
|
+
const zipBuffer = await fs.readFile('templates.zip');
|
|
859
|
+
const app = new ZipXlsxTemplateApp(zipBuffer);
|
|
860
|
+
|
|
861
|
+
const compileOpts = {
|
|
862
|
+
sheetName: 'export.metadata.config',
|
|
863
|
+
remove: true
|
|
864
|
+
};
|
|
865
|
+
|
|
866
|
+
const renderOpts = {
|
|
867
|
+
// Rendering options
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
await app.substituteAll(renderData, compileOpts, renderOpts);
|
|
871
|
+
const output = await app.generate();
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
## API Reference
|
|
875
|
+
|
|
876
|
+
### ZipXlsxTemplateApp
|
|
877
|
+
|
|
878
|
+
Main class for processing Excel files in ZIP archives.
|
|
879
|
+
|
|
880
|
+
| Method | Description |
|
|
881
|
+
|:-------|:------------|
|
|
882
|
+
| `constructor(data?: Buffer)` | Initialize with ZIP buffer |
|
|
883
|
+
| `loadZipBuffer(data: Buffer)` | Load ZIP buffer |
|
|
884
|
+
| `parse(data: Buffer)` | Parse ZIP and extract XLSX entries |
|
|
885
|
+
| `getEntries()` | Get all XLSX file entries |
|
|
886
|
+
| `substituteAll(renderData, compileOpts?, renderOpts?)` | Substitute all placeholders |
|
|
887
|
+
| `generate(options?)` | Generate output buffer |
|
|
888
|
+
| `static compileAll(files, renderData?, compileOpts?)` | Compile multiple files |
|
|
889
|
+
| `static compileTo(data, opts, values?)` | Compile XLSX in ZIP with custom checker |
|
|
890
|
+
|
|
891
|
+
### XlsxRender
|
|
892
|
+
|
|
893
|
+
Main class for rendering single Excel files.
|
|
894
|
+
|
|
895
|
+
| Method | Description |
|
|
896
|
+
|:-------|:------------|
|
|
897
|
+
| `static create(data: Buffer, option?)` | Create from buffer |
|
|
898
|
+
| `render(values: Object, sheetName: string)` | Render specific sheet |
|
|
899
|
+
| `getSheets()` | Get all sheet information |
|
|
900
|
+
| `generate(options?)` | Generate output buffer |
|
|
901
|
+
|
|
902
|
+
### Helper Functions
|
|
903
|
+
|
|
904
|
+
| Function | Description |
|
|
905
|
+
|:---------|:------------|
|
|
906
|
+
| `ExprResolver` | Expression resolver for complex expressions |
|
|
907
|
+
| `compileRuleSheetName` | Default rule sheet name |
|
|
908
|
+
| `generateXlsxTemplate` | Generate XLSX template |
|
|
909
|
+
| `generateCommandsXlsxTemplate` | Generate with custom commands |
|
|
910
|
+
| `AddCommand(name, fn)` | Add custom render function |
|
|
911
|
+
|
|
912
|
+
## Complete Example
|
|
913
|
+
|
|
914
|
+
### Template Structure
|
|
915
|
+
|
|
916
|
+
```
|
|
917
|
+
template.xlsx
|
|
918
|
+
├── Sheet1 (Data Sheet with placeholders)
|
|
919
|
+
│ ├── A1: ${contract.contractCode}
|
|
920
|
+
│ ├── B1: ${contract.contractTitle}
|
|
921
|
+
│ └── C1: ${exportData.LRR.mothOrYear}
|
|
922
|
+
└── export.metadata.config (Rule Configuration Sheet)
|
|
923
|
+
├── Row 1: alias @#key => use aliasKey: @# => @#
|
|
924
|
+
├── Row 2: mergeCell G-AQ(1-17)=sum(...)
|
|
925
|
+
└── Row 3: cell D-7=@#[@D.MY]
|
|
926
|
+
```
|
|
927
|
+
|
|
928
|
+
### Compile & Render Flow
|
|
929
|
+
|
|
930
|
+
| Step | Input | Output | Description |
|
|
931
|
+
|:-----|:------|:-------|:------------|
|
|
932
|
+
| 1. Load | `template.xlsx` Buffer | `ZipXlsxTemplateApp` | Load template file |
|
|
933
|
+
| 2. Compile | Rule Config Sheet | Compiled Rules | Parse mergeCell/cell/rowCell rules |
|
|
934
|
+
| 3. Substitute | Data Object | Rendered Sheets | Replace `${...}` placeholders |
|
|
935
|
+
| 4. Generate | - | `output.xlsx` Buffer | Final output file |
|
|
936
|
+
|
|
937
|
+
```typescript
|
|
938
|
+
import { ZipXlsxTemplateApp, AddCommand } from '@vdhewei/xlsx-template-lib';
|
|
939
|
+
import * as fs from 'node:fs/promises';
|
|
940
|
+
|
|
941
|
+
// Define custom function
|
|
942
|
+
AddCommand('calculateTotal', (obj, args) => {
|
|
943
|
+
const base = Number(args.root);
|
|
944
|
+
const multiplier = args.groups.length > 0 ? Number(args.groups[0]) : 1;
|
|
945
|
+
return base * multiplier;
|
|
946
|
+
});
|
|
947
|
+
|
|
948
|
+
// Main processing
|
|
949
|
+
async function processTemplate() {
|
|
950
|
+
const templateBuffer = await fs.readFile('template.xlsx');
|
|
951
|
+
|
|
952
|
+
const app = new ZipXlsxTemplateApp(templateBuffer);
|
|
953
|
+
|
|
954
|
+
const renderData = {
|
|
955
|
+
contract: {
|
|
956
|
+
contractCode: 'CTR-2024-001',
|
|
957
|
+
contractTitle: 'Monthly Return of Site Labour'
|
|
958
|
+
},
|
|
959
|
+
exportData: {
|
|
960
|
+
LRR: {
|
|
961
|
+
mothOrYear: '2024-01',
|
|
962
|
+
workCode: 'WC-001'
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
|
|
967
|
+
const compileOpts = {
|
|
968
|
+
sheetName: 'export.metadata.config',
|
|
969
|
+
remove: true // Remove rule sheet in output
|
|
970
|
+
};
|
|
971
|
+
|
|
972
|
+
await app.substituteAll(renderData, compileOpts);
|
|
973
|
+
|
|
974
|
+
const output = await app.generate();
|
|
975
|
+
await fs.writeFile('output.xlsx', output);
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
processTemplate();
|
|
979
|
+
```
|
|
980
|
+
|
|
981
|
+
## Note
|
|
982
|
+
|
|
983
|
+
- The `test_data` directory contains internal test templates and is for private use only
|
|
984
|
+
- Rule configuration sheet supports: `alias`, `mergeCell`, `cell`, `rowCell` rule types
|
|
985
|
+
- Custom functions can be registered via `AddCommand(name, handler)`
|
|
986
|
+
|
|
987
|
+
## License
|
|
988
|
+
|
|
989
|
+
MIT
|
|
990
|
+
|
|
991
|
+
## Author
|
|
992
|
+
|
|
993
|
+
VDHewei
|
|
994
|
+
|
|
995
|
+
## Repository
|
|
996
|
+
|
|
997
|
+
https://github.com/VDHewei/xlsx-template-lib
|
|
998
|
+
|
|
999
|
+
## Contributing
|
|
1000
|
+
|
|
1001
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
1002
|
+
|
|
1003
|
+
## Acknowledgments
|
|
1004
|
+
|
|
1005
|
+
This project was inspired by the excellent open-source project [xlsx-template](https://github.com/optilude/xlsx-template) by optilude.
|
|
1006
|
+
|
|
1007
|
+
**xlsx-template** provides a robust foundation for Excel template-based report generation with dynamic data substitution. Many concepts and design patterns from xlsx-template have influenced this library, including:
|
|
1008
|
+
|
|
1009
|
+
- Template-based Excel file generation
|
|
1010
|
+
- Placeholder substitution syntax
|
|
1011
|
+
- Array and table expansion
|
|
1012
|
+
- Image insertion and positioning
|
|
1013
|
+
- Cell formatting preservation
|
|
1014
|
+
|
|
1015
|
+
We extend our gratitude to the xlsx-template team and contributors for their valuable work in the open-source community.
|
|
1016
|
+
|
|
1017
|
+
**Original xlsx-template repository:** https://github.com/optilude/xlsx-template
|