to-spreadsheet 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +168 -1
- package/lib/generate-excel.d.ts +14 -2
- package/lib/generate-excel.js +17 -12
- package/lib/index.d.ts +11 -20
- package/lib/index.js +64 -30
- package/lib/read-csv.d.ts +6 -0
- package/lib/read-csv.js +80 -0
- package/lib/read-excel.d.ts +23 -0
- package/lib/read-excel.js +265 -0
- package/lib/types.d.ts +34 -0
- package/lib/types.js +44 -0
- package/lib/util.d.ts +7 -2
- package/lib/util.js +44 -11
- package/lib/xl/styles.xml.js +29 -9
- package/lib/xl/worksheets/sheet.xml.js +5 -5
- package/package.json +13 -10
package/README.md
CHANGED
|
@@ -40,6 +40,55 @@ generateExcel(sampleData); // <-- by default generate XLSX for node
|
|
|
40
40
|
generateExcel(sampleData, EnvironmentType.BROWSER); // <-- for browser
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
# Reading / Importing
|
|
44
|
+
|
|
45
|
+
`to-spreadsheet` can also read spreadsheets back into plain JavaScript values. The
|
|
46
|
+
reader works in **both Node.js and the browser** and covers `.xlsx` (OOXML) files —
|
|
47
|
+
those produced by this library as well as ordinary files from Excel and other tools —
|
|
48
|
+
plus CSV text.
|
|
49
|
+
|
|
50
|
+
## Reading an `.xlsx` file
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { readExcel } from 'to-spreadsheet/lib/index';
|
|
54
|
+
|
|
55
|
+
// Node.js: pass a file path, a Buffer, or a Uint8Array/ArrayBuffer
|
|
56
|
+
const workbook = await readExcel('./report.xlsx');
|
|
57
|
+
|
|
58
|
+
// Browser: pass a File/Blob (e.g. from <input type="file">) or an ArrayBuffer
|
|
59
|
+
// const workbook = await readExcel(file);
|
|
60
|
+
|
|
61
|
+
workbook.sheets.forEach((sheet) => {
|
|
62
|
+
console.log(sheet.title); // sheet (tab) name
|
|
63
|
+
console.log(sheet.rows); // ReadCellValue[][] — a dense grid, gaps are null
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Each cell comes back as a `string`, `number`, `boolean`, `Date` (for date-formatted
|
|
68
|
+
cells) or `null` (empty). Date conversion can be disabled to get the raw Excel serial:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
const workbook = await readExcel('./report.xlsx', { cellDates: false });
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Formula cells are surfaced on an optional parallel `sheet.formulas` grid (the formula
|
|
75
|
+
text without the leading `=`), present only when a sheet contains at least one formula.
|
|
76
|
+
|
|
77
|
+
## Parsing CSV
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { parseCsv } from 'to-spreadsheet/lib/index';
|
|
81
|
+
|
|
82
|
+
const rows = parseCsv('name,age\nalice,30\n"bob, jr.",25');
|
|
83
|
+
// [["name","age"], ["alice","30"], ["bob, jr.","25"]]
|
|
84
|
+
|
|
85
|
+
// custom delimiter
|
|
86
|
+
const tsv = parseCsv(tabText, { delimiter: '\t' });
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`parseCsv` follows RFC 4180: quoted fields, escaped quotes (`""`), embedded commas and
|
|
90
|
+
newlines, `\r\n`/`\n` line endings, and a leading UTF-8 BOM are all handled.
|
|
91
|
+
|
|
43
92
|
# Cell Features
|
|
44
93
|
|
|
45
94
|
## Dates
|
|
@@ -145,7 +194,7 @@ const data = [
|
|
|
145
194
|
- [x] Cell borders
|
|
146
195
|
- [x] Cell styling (background colors, foreground colors, dates)
|
|
147
196
|
- [x] Date cells with proper Excel formatting
|
|
148
|
-
- [
|
|
197
|
+
- [x] Cell alignment (horizontal and vertical)
|
|
149
198
|
- [ ] Sheet styling
|
|
150
199
|
|
|
151
200
|
## Cell Borders
|
|
@@ -290,3 +339,121 @@ Colors should be specified in hex format:
|
|
|
290
339
|
- `#000000` - Black
|
|
291
340
|
- `#FFFFFF` - White
|
|
292
341
|
- `#CCCCCC` - Light gray
|
|
342
|
+
|
|
343
|
+
## Cell Alignment
|
|
344
|
+
|
|
345
|
+
You can align cell content both horizontally and vertically:
|
|
346
|
+
|
|
347
|
+
### Basic Alignment Usage
|
|
348
|
+
|
|
349
|
+
```ts
|
|
350
|
+
import {
|
|
351
|
+
generateExcel,
|
|
352
|
+
createHorizontallyAlignedCell,
|
|
353
|
+
createVerticallyAlignedCell,
|
|
354
|
+
createAlignedCell,
|
|
355
|
+
createCenteredCell,
|
|
356
|
+
HorizontalAlignment,
|
|
357
|
+
VerticalAlignment
|
|
358
|
+
} from 'to-spreadsheet/lib/index';
|
|
359
|
+
|
|
360
|
+
const data = [
|
|
361
|
+
{
|
|
362
|
+
title: 'AlignmentDemo',
|
|
363
|
+
content: [
|
|
364
|
+
[
|
|
365
|
+
'Feature',
|
|
366
|
+
'Horizontal',
|
|
367
|
+
'Vertical',
|
|
368
|
+
'Both'
|
|
369
|
+
],
|
|
370
|
+
[
|
|
371
|
+
'Left Align',
|
|
372
|
+
createHorizontallyAlignedCell('Left Text', HorizontalAlignment.left),
|
|
373
|
+
createVerticallyAlignedCell('Top Text', VerticalAlignment.top),
|
|
374
|
+
createAlignedCell('Top-Left', HorizontalAlignment.left, VerticalAlignment.top)
|
|
375
|
+
],
|
|
376
|
+
[
|
|
377
|
+
'Center Align',
|
|
378
|
+
createHorizontallyAlignedCell('Center Text', HorizontalAlignment.center),
|
|
379
|
+
createVerticallyAlignedCell('Center Text', VerticalAlignment.center),
|
|
380
|
+
createCenteredCell('Full Center')
|
|
381
|
+
],
|
|
382
|
+
[
|
|
383
|
+
'Right Align',
|
|
384
|
+
createHorizontallyAlignedCell('Right Text', HorizontalAlignment.right),
|
|
385
|
+
createVerticallyAlignedCell('Bottom Text', VerticalAlignment.bottom),
|
|
386
|
+
createAlignedCell('Bottom-Right', HorizontalAlignment.right, VerticalAlignment.bottom)
|
|
387
|
+
]
|
|
388
|
+
]
|
|
389
|
+
}
|
|
390
|
+
];
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Horizontal Alignment Options
|
|
394
|
+
|
|
395
|
+
- `HorizontalAlignment.general` - General alignment (Excel default)
|
|
396
|
+
- `HorizontalAlignment.left` - Left alignment
|
|
397
|
+
- `HorizontalAlignment.center` - Center alignment
|
|
398
|
+
- `HorizontalAlignment.right` - Right alignment
|
|
399
|
+
- `HorizontalAlignment.fill` - Fill alignment
|
|
400
|
+
- `HorizontalAlignment.justify` - Justify alignment
|
|
401
|
+
- `HorizontalAlignment.centerContinuous` - Center across selection
|
|
402
|
+
- `HorizontalAlignment.distributed` - Distributed alignment
|
|
403
|
+
|
|
404
|
+
### Vertical Alignment Options
|
|
405
|
+
|
|
406
|
+
- `VerticalAlignment.top` - Top alignment
|
|
407
|
+
- `VerticalAlignment.center` - Center alignment
|
|
408
|
+
- `VerticalAlignment.bottom` - Bottom alignment
|
|
409
|
+
- `VerticalAlignment.justify` - Justify alignment
|
|
410
|
+
- `VerticalAlignment.distributed` - Distributed alignment
|
|
411
|
+
|
|
412
|
+
### Alignment Helper Functions
|
|
413
|
+
|
|
414
|
+
- `createHorizontallyAlignedCell(value, alignment)` - Creates cell with horizontal alignment
|
|
415
|
+
- `createVerticallyAlignedCell(value, alignment)` - Creates cell with vertical alignment
|
|
416
|
+
- `createAlignedCell(value, horizontal, vertical)` - Creates cell with both alignments
|
|
417
|
+
- `createCenteredCell(value)` - Creates center-aligned cell (convenience function)
|
|
418
|
+
|
|
419
|
+
### Combined with Other Features
|
|
420
|
+
|
|
421
|
+
Alignment works seamlessly with all other styling features:
|
|
422
|
+
|
|
423
|
+
```ts
|
|
424
|
+
import {
|
|
425
|
+
createStyledCell,
|
|
426
|
+
HorizontalAlignment,
|
|
427
|
+
VerticalAlignment,
|
|
428
|
+
createAllBorders,
|
|
429
|
+
BorderStyle
|
|
430
|
+
} from 'to-spreadsheet/lib/index';
|
|
431
|
+
|
|
432
|
+
const data = [
|
|
433
|
+
{
|
|
434
|
+
title: 'ComplexStyling',
|
|
435
|
+
content: [
|
|
436
|
+
[
|
|
437
|
+
// Full styling with alignment, colors, and borders
|
|
438
|
+
createStyledCell('Complete Style', {
|
|
439
|
+
horizontalAlignment: HorizontalAlignment.center,
|
|
440
|
+
verticalAlignment: VerticalAlignment.center,
|
|
441
|
+
backgroundColor: '#CCFFCC',
|
|
442
|
+
foregroundColor: '#FF0000',
|
|
443
|
+
border: createAllBorders(BorderStyle.thick, '#000000')
|
|
444
|
+
}),
|
|
445
|
+
|
|
446
|
+
// Aligned date cell
|
|
447
|
+
createDateCell(new Date(), {
|
|
448
|
+
horizontalAlignment: HorizontalAlignment.right,
|
|
449
|
+
verticalAlignment: VerticalAlignment.center,
|
|
450
|
+
backgroundColor: '#FFFFCC'
|
|
451
|
+
}),
|
|
452
|
+
|
|
453
|
+
// Simple centered text
|
|
454
|
+
createCenteredCell('Centered')
|
|
455
|
+
]
|
|
456
|
+
]
|
|
457
|
+
}
|
|
458
|
+
];
|
|
459
|
+
```
|
package/lib/generate-excel.d.ts
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
|
-
import { IPage } from "./index";
|
|
1
|
+
import { IPage, IWorkbook } from "./index";
|
|
2
|
+
declare const generateTree: (workbook: IWorkbook) => {
|
|
3
|
+
"[Content_Types].xml": string;
|
|
4
|
+
"_rels/.rels": string;
|
|
5
|
+
"docProps/app.xml": string;
|
|
6
|
+
"docProps/core.xml": string;
|
|
7
|
+
"xl/_rels/workbook.xml.rels": string;
|
|
8
|
+
"xl/sharedStrings.xml": string;
|
|
9
|
+
"xl/styles.xml": string;
|
|
10
|
+
"xl/theme/theme1.xml": string;
|
|
11
|
+
"xl/workbook.xml": string;
|
|
12
|
+
};
|
|
2
13
|
declare enum EnvironmentType {
|
|
3
14
|
NODE = 0,
|
|
4
15
|
BROWSER = 1
|
|
5
16
|
}
|
|
17
|
+
declare const buildWorkbook: (dump: IPage[]) => IWorkbook;
|
|
6
18
|
declare const generateExcel: (dump: IPage[], environmentType?: EnvironmentType) => Promise<void>;
|
|
7
|
-
export { generateExcel, EnvironmentType };
|
|
19
|
+
export { generateExcel, EnvironmentType, buildWorkbook, generateTree };
|
package/lib/generate-excel.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EnvironmentType = exports.generateExcel = void 0;
|
|
3
|
+
exports.generateTree = exports.buildWorkbook = exports.EnvironmentType = exports.generateExcel = void 0;
|
|
4
4
|
const content_types_xml_1 = require("./content-types.xml");
|
|
5
5
|
const _rels_1 = require("./_rels/.rels");
|
|
6
6
|
const app_xml_1 = require("./docProps/app.xml");
|
|
@@ -11,7 +11,7 @@ const styles_xml_1 = require("./xl/styles.xml");
|
|
|
11
11
|
const theme1_xml_1 = require("./xl/theme/theme1.xml");
|
|
12
12
|
const workbook_xml_1 = require("./xl/workbook.xml");
|
|
13
13
|
const sheet_xml_1 = require("./xl/worksheets/sheet.xml");
|
|
14
|
-
const
|
|
14
|
+
const types_1 = require("./types");
|
|
15
15
|
const util_1 = require("./util");
|
|
16
16
|
const generateTree = (workbook) => {
|
|
17
17
|
const styleMap = new Map();
|
|
@@ -20,7 +20,7 @@ const generateTree = (workbook) => {
|
|
|
20
20
|
workbook.sheets.forEach(sheet => {
|
|
21
21
|
sheet.rows.forEach(row => {
|
|
22
22
|
row.cells.forEach(cell => {
|
|
23
|
-
if (cell.type ===
|
|
23
|
+
if (cell.type === types_1.ICellType.date) {
|
|
24
24
|
hasDateCells = true;
|
|
25
25
|
}
|
|
26
26
|
if ('style' in cell && cell.style) {
|
|
@@ -32,41 +32,42 @@ const generateTree = (workbook) => {
|
|
|
32
32
|
});
|
|
33
33
|
return Object.assign({ "[Content_Types].xml": (0, content_types_xml_1.generateContentTypesXml)(workbook), "_rels/.rels": (0, _rels_1.generateRels)(), "docProps/app.xml": (0, app_xml_1.generateAppXml)(workbook), "docProps/core.xml": (0, core_xml_1.generateCoreXml)({}), "xl/_rels/workbook.xml.rels": (0, workbook_xml_rels_1.generateWorkBookXmlRels)(workbook), "xl/sharedStrings.xml": (0, sharedStrings_xml_1.generateSharedStrings)(workbook), "xl/styles.xml": (0, styles_xml_1.generateStyleXml)(styleMap, hasDateCells), "xl/theme/theme1.xml": (0, theme1_xml_1.generateTheme1)(), "xl/workbook.xml": (0, workbook_xml_1.generateWorkBookXml)(workbook) }, workbook.sheets.reduce((acc, sheet, idx) => (Object.assign(Object.assign({}, acc), { [`xl/worksheets/sheet${idx + 1}.xml`]: (0, sheet_xml_1.generateSheetXml)(sheet, styleMap, hasDateCells) })), {}));
|
|
34
34
|
};
|
|
35
|
+
exports.generateTree = generateTree;
|
|
35
36
|
var EnvironmentType;
|
|
36
37
|
(function (EnvironmentType) {
|
|
37
38
|
EnvironmentType[EnvironmentType["NODE"] = 0] = "NODE";
|
|
38
39
|
EnvironmentType[EnvironmentType["BROWSER"] = 1] = "BROWSER";
|
|
39
40
|
})(EnvironmentType || (EnvironmentType = {}));
|
|
40
41
|
exports.EnvironmentType = EnvironmentType;
|
|
41
|
-
const
|
|
42
|
+
const buildWorkbook = (dump) => {
|
|
42
43
|
const strings = [];
|
|
43
44
|
const sheets = dump.map(({ title, content }) => {
|
|
44
45
|
const rows = content.map(row => {
|
|
45
46
|
const cells = [];
|
|
46
47
|
row.forEach(content => {
|
|
47
48
|
if (typeof content === 'number') {
|
|
48
|
-
cells.push({ type:
|
|
49
|
+
cells.push({ type: types_1.ICellType.number, value: content });
|
|
49
50
|
}
|
|
50
51
|
else if (typeof content === 'string') {
|
|
51
|
-
const type =
|
|
52
|
+
const type = types_1.ICellType.string;
|
|
52
53
|
let value = strings.indexOf(content);
|
|
53
54
|
if (value === -1) {
|
|
54
55
|
strings.push(content);
|
|
55
56
|
value = strings.length - 1;
|
|
56
57
|
}
|
|
57
|
-
cells.push({ type:
|
|
58
|
+
cells.push({ type: types_1.ICellType.string, value });
|
|
58
59
|
}
|
|
59
60
|
else if (content instanceof util_1.SkipCell) {
|
|
60
61
|
for (let i = 0; i < content.getSkipCell(); i++) {
|
|
61
|
-
cells.push({ type:
|
|
62
|
+
cells.push({ type: types_1.ICellType.skip, value: undefined });
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
else if (content instanceof util_1.Equation) {
|
|
65
|
-
cells.push({ type:
|
|
66
|
+
cells.push({ type: types_1.ICellType.equation, value: content });
|
|
66
67
|
}
|
|
67
68
|
else if (content && typeof content === 'object' && 'type' in content) {
|
|
68
69
|
const cell = content;
|
|
69
|
-
if (cell.type ===
|
|
70
|
+
if (cell.type === types_1.ICellType.string && typeof cell.value === 'string') {
|
|
70
71
|
let stringIndex = strings.indexOf(cell.value);
|
|
71
72
|
if (stringIndex === -1) {
|
|
72
73
|
strings.push(cell.value);
|
|
@@ -79,18 +80,22 @@ const generateExcel = (dump, environmentType = EnvironmentType.NODE) => {
|
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
else {
|
|
82
|
-
cells.push({ type:
|
|
83
|
+
cells.push({ type: types_1.ICellType.skip });
|
|
83
84
|
}
|
|
84
85
|
});
|
|
85
86
|
return { cells };
|
|
86
87
|
});
|
|
87
88
|
return { title, rows };
|
|
88
89
|
});
|
|
89
|
-
|
|
90
|
+
return {
|
|
90
91
|
sheets,
|
|
91
92
|
strings,
|
|
92
93
|
filename: "tem.xlsx"
|
|
93
94
|
};
|
|
95
|
+
};
|
|
96
|
+
exports.buildWorkbook = buildWorkbook;
|
|
97
|
+
const generateExcel = (dump, environmentType = EnvironmentType.NODE) => {
|
|
98
|
+
const workbook = buildWorkbook(dump);
|
|
94
99
|
if (environmentType === EnvironmentType.BROWSER) {
|
|
95
100
|
return generateExcelWorkbookBrowser(workbook);
|
|
96
101
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,21 +1,8 @@
|
|
|
1
1
|
import { generateExcel, EnvironmentType } from "./generate-excel";
|
|
2
|
-
import { SkipCell, skipCell, Equation, writeEquation, createBorder, createAllBorders, createTopBorder, createBottomBorder, createLeftBorder, createRightBorder, createStyledCell, createBorderedCell, createDateCell, createBorderedDateCell, createBackgroundCell, createForegroundCell, createColoredCell, createBackgroundDateCell } from "./util";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
date = "d",
|
|
7
|
-
skip = "skip",
|
|
8
|
-
equation = "equation"
|
|
9
|
-
}
|
|
10
|
-
declare enum BorderStyle {
|
|
11
|
-
none = "none",
|
|
12
|
-
thin = "thin",
|
|
13
|
-
medium = "medium",
|
|
14
|
-
thick = "thick",
|
|
15
|
-
double = "double",
|
|
16
|
-
dotted = "dotted",
|
|
17
|
-
dashed = "dashed"
|
|
18
|
-
}
|
|
2
|
+
import { SkipCell, skipCell, Equation, writeEquation, createBorder, createAllBorders, createTopBorder, createBottomBorder, createLeftBorder, createRightBorder, createStyledCell, createBorderedCell, createDateCell, createBorderedDateCell, createBackgroundCell, createForegroundCell, createColoredCell, createBackgroundDateCell, createHorizontallyAlignedCell, createVerticallyAlignedCell, createAlignedCell, createCenteredCell } from "./util";
|
|
3
|
+
import { readExcel, ReadCellValue, IReadSheet, IReadWorkbook, IReadOptions, ReadExcelInput } from "./read-excel";
|
|
4
|
+
import { parseCsv, ICsvOptions } from "./read-csv";
|
|
5
|
+
import { ICellType, BorderStyle, HorizontalAlignment, VerticalAlignment } from "./types";
|
|
19
6
|
interface IBorder {
|
|
20
7
|
top?: BorderStyle;
|
|
21
8
|
right?: BorderStyle;
|
|
@@ -27,6 +14,8 @@ interface ICellStyle {
|
|
|
27
14
|
border?: IBorder;
|
|
28
15
|
backgroundColor?: string;
|
|
29
16
|
foregroundColor?: string;
|
|
17
|
+
horizontalAlignment?: HorizontalAlignment;
|
|
18
|
+
verticalAlignment?: VerticalAlignment;
|
|
30
19
|
}
|
|
31
20
|
interface ICellString {
|
|
32
21
|
type: ICellType.string;
|
|
@@ -51,7 +40,7 @@ interface ICellDate {
|
|
|
51
40
|
value: Date;
|
|
52
41
|
style?: ICellStyle;
|
|
53
42
|
}
|
|
54
|
-
|
|
43
|
+
type ICell = ICellString | ICellNumber | ICellDate | ICellSkip | ICellEquation;
|
|
55
44
|
interface IRows {
|
|
56
45
|
cells: ICell[];
|
|
57
46
|
}
|
|
@@ -68,7 +57,8 @@ interface IPage {
|
|
|
68
57
|
title: string;
|
|
69
58
|
content: (string | number | undefined | SkipCell | Equation | ICell)[][];
|
|
70
59
|
}
|
|
71
|
-
export { ICell, ISheet, IWorkbook, IRows, ICellType, IPage, BorderStyle, IBorder, ICellStyle, ICellDate };
|
|
60
|
+
export { ICell, ISheet, IWorkbook, IRows, ICellType, IPage, BorderStyle, IBorder, ICellStyle, ICellDate, HorizontalAlignment, VerticalAlignment };
|
|
61
|
+
export { ReadCellValue, IReadSheet, IReadWorkbook, IReadOptions, ReadExcelInput, ICsvOptions };
|
|
72
62
|
declare const sampleData: ({
|
|
73
63
|
title: string;
|
|
74
64
|
content: (string[] | (number | Equation)[])[];
|
|
@@ -82,4 +72,5 @@ declare const sampleData: ({
|
|
|
82
72
|
title: string;
|
|
83
73
|
content: (string | number | ICell)[][];
|
|
84
74
|
})[];
|
|
85
|
-
export { generateExcel, sampleData, EnvironmentType, skipCell, writeEquation, createBorder, createAllBorders, createTopBorder, createBottomBorder, createLeftBorder, createRightBorder, createStyledCell, createBorderedCell, createDateCell, createBorderedDateCell, createBackgroundCell, createForegroundCell, createColoredCell, createBackgroundDateCell };
|
|
75
|
+
export { generateExcel, sampleData, EnvironmentType, skipCell, writeEquation, createBorder, createAllBorders, createTopBorder, createBottomBorder, createLeftBorder, createRightBorder, createStyledCell, createBorderedCell, createDateCell, createBorderedDateCell, createBackgroundCell, createForegroundCell, createColoredCell, createBackgroundDateCell, createHorizontallyAlignedCell, createVerticallyAlignedCell, createAlignedCell, createCenteredCell };
|
|
76
|
+
export { readExcel, parseCsv };
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createBackgroundDateCell = exports.createColoredCell = exports.createForegroundCell = exports.createBackgroundCell = exports.createBorderedDateCell = exports.createDateCell = exports.createBorderedCell = exports.createStyledCell = exports.createRightBorder = exports.createLeftBorder = exports.createBottomBorder = exports.createTopBorder = exports.createAllBorders = exports.createBorder = exports.writeEquation = exports.skipCell = exports.EnvironmentType = exports.sampleData = exports.generateExcel = exports.BorderStyle = exports.ICellType = void 0;
|
|
3
|
+
exports.parseCsv = exports.readExcel = exports.createCenteredCell = exports.createAlignedCell = exports.createVerticallyAlignedCell = exports.createHorizontallyAlignedCell = exports.createBackgroundDateCell = exports.createColoredCell = exports.createForegroundCell = exports.createBackgroundCell = exports.createBorderedDateCell = exports.createDateCell = exports.createBorderedCell = exports.createStyledCell = exports.createRightBorder = exports.createLeftBorder = exports.createBottomBorder = exports.createTopBorder = exports.createAllBorders = exports.createBorder = exports.writeEquation = exports.skipCell = exports.EnvironmentType = exports.sampleData = exports.generateExcel = exports.VerticalAlignment = exports.HorizontalAlignment = exports.BorderStyle = exports.ICellType = void 0;
|
|
4
4
|
const generate_excel_1 = require("./generate-excel");
|
|
5
5
|
Object.defineProperty(exports, "generateExcel", { enumerable: true, get: function () { return generate_excel_1.generateExcel; } });
|
|
6
6
|
Object.defineProperty(exports, "EnvironmentType", { enumerable: true, get: function () { return generate_excel_1.EnvironmentType; } });
|
|
@@ -21,26 +21,19 @@ Object.defineProperty(exports, "createBackgroundCell", { enumerable: true, get:
|
|
|
21
21
|
Object.defineProperty(exports, "createForegroundCell", { enumerable: true, get: function () { return util_1.createForegroundCell; } });
|
|
22
22
|
Object.defineProperty(exports, "createColoredCell", { enumerable: true, get: function () { return util_1.createColoredCell; } });
|
|
23
23
|
Object.defineProperty(exports, "createBackgroundDateCell", { enumerable: true, get: function () { return util_1.createBackgroundDateCell; } });
|
|
24
|
-
|
|
25
|
-
(function (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
(function (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
BorderStyle["medium"] = "medium";
|
|
38
|
-
BorderStyle["thick"] = "thick";
|
|
39
|
-
BorderStyle["double"] = "double";
|
|
40
|
-
BorderStyle["dotted"] = "dotted";
|
|
41
|
-
BorderStyle["dashed"] = "dashed";
|
|
42
|
-
})(BorderStyle || (BorderStyle = {}));
|
|
43
|
-
exports.BorderStyle = BorderStyle;
|
|
24
|
+
Object.defineProperty(exports, "createHorizontallyAlignedCell", { enumerable: true, get: function () { return util_1.createHorizontallyAlignedCell; } });
|
|
25
|
+
Object.defineProperty(exports, "createVerticallyAlignedCell", { enumerable: true, get: function () { return util_1.createVerticallyAlignedCell; } });
|
|
26
|
+
Object.defineProperty(exports, "createAlignedCell", { enumerable: true, get: function () { return util_1.createAlignedCell; } });
|
|
27
|
+
Object.defineProperty(exports, "createCenteredCell", { enumerable: true, get: function () { return util_1.createCenteredCell; } });
|
|
28
|
+
const read_excel_1 = require("./read-excel");
|
|
29
|
+
Object.defineProperty(exports, "readExcel", { enumerable: true, get: function () { return read_excel_1.readExcel; } });
|
|
30
|
+
const read_csv_1 = require("./read-csv");
|
|
31
|
+
Object.defineProperty(exports, "parseCsv", { enumerable: true, get: function () { return read_csv_1.parseCsv; } });
|
|
32
|
+
const types_1 = require("./types");
|
|
33
|
+
Object.defineProperty(exports, "ICellType", { enumerable: true, get: function () { return types_1.ICellType; } });
|
|
34
|
+
Object.defineProperty(exports, "BorderStyle", { enumerable: true, get: function () { return types_1.BorderStyle; } });
|
|
35
|
+
Object.defineProperty(exports, "HorizontalAlignment", { enumerable: true, get: function () { return types_1.HorizontalAlignment; } });
|
|
36
|
+
Object.defineProperty(exports, "VerticalAlignment", { enumerable: true, get: function () { return types_1.VerticalAlignment; } });
|
|
44
37
|
const sampleData = [
|
|
45
38
|
{
|
|
46
39
|
title: 'Maifee1', content: [
|
|
@@ -57,9 +50,9 @@ const sampleData = [
|
|
|
57
50
|
title: 'BorderDemo',
|
|
58
51
|
content: [
|
|
59
52
|
[
|
|
60
|
-
(0, util_1.createBorderedCell)('Product', (0, util_1.createAllBorders)(BorderStyle.thick, '#000000')),
|
|
61
|
-
(0, util_1.createBorderedCell)('Price', (0, util_1.createAllBorders)(BorderStyle.thick, '#000000')),
|
|
62
|
-
(0, util_1.createBorderedCell)('Total', (0, util_1.createAllBorders)(BorderStyle.thick, '#000000'))
|
|
53
|
+
(0, util_1.createBorderedCell)('Product', (0, util_1.createAllBorders)(types_1.BorderStyle.thick, '#000000')),
|
|
54
|
+
(0, util_1.createBorderedCell)('Price', (0, util_1.createAllBorders)(types_1.BorderStyle.thick, '#000000')),
|
|
55
|
+
(0, util_1.createBorderedCell)('Total', (0, util_1.createAllBorders)(types_1.BorderStyle.thick, '#000000'))
|
|
63
56
|
],
|
|
64
57
|
[
|
|
65
58
|
(0, util_1.createBorderedCell)('Apple', (0, util_1.createLeftBorder)()),
|
|
@@ -69,8 +62,8 @@ const sampleData = [
|
|
|
69
62
|
[
|
|
70
63
|
(0, util_1.createStyledCell)('Custom', {
|
|
71
64
|
border: {
|
|
72
|
-
left: BorderStyle.double,
|
|
73
|
-
bottom: BorderStyle.thin,
|
|
65
|
+
left: types_1.BorderStyle.double,
|
|
66
|
+
bottom: types_1.BorderStyle.thin,
|
|
74
67
|
color: '#0000FF'
|
|
75
68
|
}
|
|
76
69
|
}),
|
|
@@ -90,7 +83,7 @@ const sampleData = [
|
|
|
90
83
|
[
|
|
91
84
|
'Project Start',
|
|
92
85
|
(0, util_1.createDateCell)(new Date('2024-01-01')),
|
|
93
|
-
(0, util_1.createBorderedDateCell)(new Date('2024-01-15'), (0, util_1.createAllBorders)(BorderStyle.thin, '#000000'))
|
|
86
|
+
(0, util_1.createBorderedDateCell)(new Date('2024-01-15'), (0, util_1.createAllBorders)(types_1.BorderStyle.thin, '#000000'))
|
|
94
87
|
],
|
|
95
88
|
[
|
|
96
89
|
'Milestone 1',
|
|
@@ -101,8 +94,8 @@ const sampleData = [
|
|
|
101
94
|
'Custom Date Style',
|
|
102
95
|
(0, util_1.createDateCell)(new Date('2024-06-15'), {
|
|
103
96
|
border: {
|
|
104
|
-
top: BorderStyle.thick,
|
|
105
|
-
bottom: BorderStyle.double,
|
|
97
|
+
top: types_1.BorderStyle.thick,
|
|
98
|
+
bottom: types_1.BorderStyle.double,
|
|
106
99
|
color: '#FF0000'
|
|
107
100
|
}
|
|
108
101
|
}),
|
|
@@ -145,12 +138,53 @@ const sampleData = [
|
|
|
145
138
|
(0, util_1.createStyledCell)('Complex', {
|
|
146
139
|
backgroundColor: '#FFFFCC',
|
|
147
140
|
foregroundColor: '#0000FF',
|
|
148
|
-
border: (0, util_1.createAllBorders)(BorderStyle.thick, '#000000')
|
|
141
|
+
border: (0, util_1.createAllBorders)(types_1.BorderStyle.thick, '#000000')
|
|
149
142
|
}),
|
|
150
143
|
'Plain text',
|
|
151
144
|
42
|
|
152
145
|
]
|
|
153
146
|
]
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
title: 'AlignmentDemo',
|
|
150
|
+
content: [
|
|
151
|
+
[
|
|
152
|
+
'Feature',
|
|
153
|
+
'Horizontal Alignment',
|
|
154
|
+
'Vertical Alignment',
|
|
155
|
+
'Both Alignments'
|
|
156
|
+
],
|
|
157
|
+
[
|
|
158
|
+
'Left Align',
|
|
159
|
+
(0, util_1.createHorizontallyAlignedCell)('Left Text', types_1.HorizontalAlignment.left),
|
|
160
|
+
(0, util_1.createVerticallyAlignedCell)('Top Text', types_1.VerticalAlignment.top),
|
|
161
|
+
(0, util_1.createAlignedCell)('Top-Left', types_1.HorizontalAlignment.left, types_1.VerticalAlignment.top)
|
|
162
|
+
],
|
|
163
|
+
[
|
|
164
|
+
'Center Align',
|
|
165
|
+
(0, util_1.createHorizontallyAlignedCell)('Center Text', types_1.HorizontalAlignment.center),
|
|
166
|
+
(0, util_1.createVerticallyAlignedCell)('Center Text', types_1.VerticalAlignment.center),
|
|
167
|
+
(0, util_1.createCenteredCell)('Full Center')
|
|
168
|
+
],
|
|
169
|
+
[
|
|
170
|
+
'Right Align',
|
|
171
|
+
(0, util_1.createHorizontallyAlignedCell)('Right Text', types_1.HorizontalAlignment.right),
|
|
172
|
+
(0, util_1.createVerticallyAlignedCell)('Bottom Text', types_1.VerticalAlignment.bottom),
|
|
173
|
+
(0, util_1.createAlignedCell)('Bottom-Right', types_1.HorizontalAlignment.right, types_1.VerticalAlignment.bottom)
|
|
174
|
+
],
|
|
175
|
+
[
|
|
176
|
+
'Complex Style',
|
|
177
|
+
(0, util_1.createStyledCell)('All Features', {
|
|
178
|
+
horizontalAlignment: types_1.HorizontalAlignment.center,
|
|
179
|
+
verticalAlignment: types_1.VerticalAlignment.center,
|
|
180
|
+
backgroundColor: '#CCFFCC',
|
|
181
|
+
foregroundColor: '#FF0000',
|
|
182
|
+
border: (0, util_1.createAllBorders)(types_1.BorderStyle.thick, '#000000')
|
|
183
|
+
}),
|
|
184
|
+
(0, util_1.createAlignedCell)(new Date(), types_1.HorizontalAlignment.right, types_1.VerticalAlignment.center),
|
|
185
|
+
(0, util_1.createCenteredCell)(42)
|
|
186
|
+
]
|
|
187
|
+
]
|
|
154
188
|
}
|
|
155
189
|
];
|
|
156
190
|
exports.sampleData = sampleData;
|
package/lib/read-csv.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseCsv = void 0;
|
|
4
|
+
const parseCsv = (text, options = {}) => {
|
|
5
|
+
var _a;
|
|
6
|
+
const delimiter = (_a = options.delimiter) !== null && _a !== void 0 ? _a : ",";
|
|
7
|
+
const skipEmptyTrailingRow = options.skipEmptyTrailingRow !== false;
|
|
8
|
+
const delim = delimiter.charAt(0);
|
|
9
|
+
if (text.charCodeAt(0) === 0xfeff)
|
|
10
|
+
text = text.slice(1);
|
|
11
|
+
const rows = [];
|
|
12
|
+
let row = [];
|
|
13
|
+
let field = "";
|
|
14
|
+
let inQuotes = false;
|
|
15
|
+
let i = 0;
|
|
16
|
+
const length = text.length;
|
|
17
|
+
const endField = () => {
|
|
18
|
+
row.push(field);
|
|
19
|
+
field = "";
|
|
20
|
+
};
|
|
21
|
+
const endRow = () => {
|
|
22
|
+
endField();
|
|
23
|
+
rows.push(row);
|
|
24
|
+
row = [];
|
|
25
|
+
};
|
|
26
|
+
while (i < length) {
|
|
27
|
+
const char = text[i];
|
|
28
|
+
if (inQuotes) {
|
|
29
|
+
if (char === '"') {
|
|
30
|
+
if (text[i + 1] === '"') {
|
|
31
|
+
field += '"';
|
|
32
|
+
i += 2;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
inQuotes = false;
|
|
36
|
+
i++;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
field += char;
|
|
40
|
+
i++;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (char === '"') {
|
|
44
|
+
inQuotes = true;
|
|
45
|
+
i++;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (char === delim) {
|
|
49
|
+
endField();
|
|
50
|
+
i++;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (char === "\n") {
|
|
54
|
+
endRow();
|
|
55
|
+
i++;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (char === "\r") {
|
|
59
|
+
endRow();
|
|
60
|
+
if (text[i + 1] === "\n")
|
|
61
|
+
i += 2;
|
|
62
|
+
else
|
|
63
|
+
i++;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
field += char;
|
|
67
|
+
i++;
|
|
68
|
+
}
|
|
69
|
+
if (field.length > 0 || row.length > 0) {
|
|
70
|
+
endRow();
|
|
71
|
+
}
|
|
72
|
+
if (skipEmptyTrailingRow &&
|
|
73
|
+
rows.length > 0 &&
|
|
74
|
+
rows[rows.length - 1].length === 1 &&
|
|
75
|
+
rows[rows.length - 1][0] === "") {
|
|
76
|
+
rows.pop();
|
|
77
|
+
}
|
|
78
|
+
return rows;
|
|
79
|
+
};
|
|
80
|
+
exports.parseCsv = parseCsv;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
type ReadCellValue = string | number | boolean | Date | null;
|
|
3
|
+
interface IReadSheet {
|
|
4
|
+
title: string;
|
|
5
|
+
rows: ReadCellValue[][];
|
|
6
|
+
formulas?: (string | null)[][];
|
|
7
|
+
}
|
|
8
|
+
interface IReadWorkbook {
|
|
9
|
+
sheets: IReadSheet[];
|
|
10
|
+
}
|
|
11
|
+
interface IReadOptions {
|
|
12
|
+
cellDates?: boolean;
|
|
13
|
+
}
|
|
14
|
+
type ReadExcelInput = string | Uint8Array | ArrayBuffer | Blob;
|
|
15
|
+
declare const columnLettersToIndex: (letters: string) => number;
|
|
16
|
+
declare const excelSerialToDate: (serial: number) => Date;
|
|
17
|
+
declare const parseSharedStrings: (sharedStringsXml: string | undefined) => string[];
|
|
18
|
+
declare const parseWorksheet: (sheetXml: string, sharedStrings: string[], dateStyleFlags: boolean[], cellDates: boolean) => {
|
|
19
|
+
rows: ReadCellValue[][];
|
|
20
|
+
formulas?: (string | null)[][] | undefined;
|
|
21
|
+
};
|
|
22
|
+
declare const readExcel: (input: ReadExcelInput, options?: IReadOptions) => Promise<IReadWorkbook>;
|
|
23
|
+
export { readExcel, ReadCellValue, IReadSheet, IReadWorkbook, IReadOptions, ReadExcelInput, columnLettersToIndex, excelSerialToDate, parseSharedStrings, parseWorksheet, };
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.parseWorksheet = exports.parseSharedStrings = exports.excelSerialToDate = exports.columnLettersToIndex = exports.readExcel = void 0;
|
|
13
|
+
const decodeXml = (text) => text
|
|
14
|
+
.replace(/&#x([0-9a-fA-F]+);/g, (_, hex) => String.fromCodePoint(parseInt(hex, 16)))
|
|
15
|
+
.replace(/&#(\d+);/g, (_, dec) => String.fromCodePoint(parseInt(dec, 10)))
|
|
16
|
+
.replace(/</g, "<")
|
|
17
|
+
.replace(/>/g, ">")
|
|
18
|
+
.replace(/"/g, '"')
|
|
19
|
+
.replace(/'/g, "'")
|
|
20
|
+
.replace(/&/g, "&");
|
|
21
|
+
const getAttr = (attrs, name) => {
|
|
22
|
+
const match = attrs.match(new RegExp(`\\b${name}\\s*=\\s*"([^"]*)"|\\b${name}\\s*=\\s*'([^']*)'`));
|
|
23
|
+
if (!match)
|
|
24
|
+
return undefined;
|
|
25
|
+
return decodeXml(match[1] !== undefined ? match[1] : match[2]);
|
|
26
|
+
};
|
|
27
|
+
const columnLettersToIndex = (letters) => {
|
|
28
|
+
let index = 0;
|
|
29
|
+
for (let i = 0; i < letters.length; i++) {
|
|
30
|
+
index = index * 26 + (letters.charCodeAt(i) - 64);
|
|
31
|
+
}
|
|
32
|
+
return index - 1;
|
|
33
|
+
};
|
|
34
|
+
exports.columnLettersToIndex = columnLettersToIndex;
|
|
35
|
+
const excelSerialToDate = (serial) => {
|
|
36
|
+
const excelEpoch = new Date(1900, 0, 1);
|
|
37
|
+
const offset = serial >= 60 ? 2 : 1;
|
|
38
|
+
const millis = excelEpoch.getTime() + (serial - offset) * 24 * 60 * 60 * 1000;
|
|
39
|
+
return new Date(millis);
|
|
40
|
+
};
|
|
41
|
+
exports.excelSerialToDate = excelSerialToDate;
|
|
42
|
+
const BUILTIN_DATE_FORMAT_IDS = new Set([
|
|
43
|
+
14, 15, 16, 17, 18, 19, 20, 21, 22, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
|
|
44
|
+
45, 46, 47, 50, 51, 52, 53, 54, 55, 56, 57, 58,
|
|
45
|
+
]);
|
|
46
|
+
const isDateFormatCode = (code) => {
|
|
47
|
+
const stripped = code
|
|
48
|
+
.replace(/\[[^\]]*\]/g, "")
|
|
49
|
+
.replace(/"[^"]*"/g, "")
|
|
50
|
+
.replace(/\\./g, "");
|
|
51
|
+
return /[yYdDhHsS]/.test(stripped) || /\bmm?m?m?\b/.test(stripped) && /[yYdDhH]/.test(code);
|
|
52
|
+
};
|
|
53
|
+
const parseDateStyleFlags = (stylesXml) => {
|
|
54
|
+
if (!stylesXml)
|
|
55
|
+
return [];
|
|
56
|
+
const dateNumFmtIds = new Set(BUILTIN_DATE_FORMAT_IDS);
|
|
57
|
+
const numFmtRe = /<numFmt\b([^>]*)\/?>/g;
|
|
58
|
+
let numFmtMatch;
|
|
59
|
+
while ((numFmtMatch = numFmtRe.exec(stylesXml)) !== null) {
|
|
60
|
+
const id = Number(getAttr(numFmtMatch[1], "numFmtId"));
|
|
61
|
+
const code = getAttr(numFmtMatch[1], "formatCode");
|
|
62
|
+
if (!Number.isNaN(id) && code && isDateFormatCode(code)) {
|
|
63
|
+
dateNumFmtIds.add(id);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const cellXfsBlock = stylesXml.match(/<cellXfs\b[^>]*>([\s\S]*?)<\/cellXfs>/);
|
|
67
|
+
if (!cellXfsBlock)
|
|
68
|
+
return [];
|
|
69
|
+
const flags = [];
|
|
70
|
+
const xfRe = /<xf\b([^>]*?)(?:\/>|>[\s\S]*?<\/xf>)/g;
|
|
71
|
+
let xfMatch;
|
|
72
|
+
while ((xfMatch = xfRe.exec(cellXfsBlock[1])) !== null) {
|
|
73
|
+
const numFmtId = Number(getAttr(xfMatch[1], "numFmtId"));
|
|
74
|
+
flags.push(!Number.isNaN(numFmtId) && dateNumFmtIds.has(numFmtId));
|
|
75
|
+
}
|
|
76
|
+
return flags;
|
|
77
|
+
};
|
|
78
|
+
const parseSharedStrings = (sharedStringsXml) => {
|
|
79
|
+
if (!sharedStringsXml)
|
|
80
|
+
return [];
|
|
81
|
+
const strings = [];
|
|
82
|
+
const siRe = /<si\b[^>]*>([\s\S]*?)<\/si>|<si\b[^>]*\/>/g;
|
|
83
|
+
let siMatch;
|
|
84
|
+
while ((siMatch = siRe.exec(sharedStringsXml)) !== null) {
|
|
85
|
+
const inner = siMatch[1] || "";
|
|
86
|
+
let text = "";
|
|
87
|
+
const tRe = /<t\b[^>]*>([\s\S]*?)<\/t>|<t\b[^>]*\/>/g;
|
|
88
|
+
let tMatch;
|
|
89
|
+
while ((tMatch = tRe.exec(inner)) !== null) {
|
|
90
|
+
text += decodeXml(tMatch[1] || "");
|
|
91
|
+
}
|
|
92
|
+
strings.push(text);
|
|
93
|
+
}
|
|
94
|
+
return strings;
|
|
95
|
+
};
|
|
96
|
+
exports.parseSharedStrings = parseSharedStrings;
|
|
97
|
+
const parseWorkbookRels = (relsXml) => {
|
|
98
|
+
const map = new Map();
|
|
99
|
+
if (!relsXml)
|
|
100
|
+
return map;
|
|
101
|
+
const relRe = /<Relationship\b([^>]*)\/?>/g;
|
|
102
|
+
let match;
|
|
103
|
+
while ((match = relRe.exec(relsXml)) !== null) {
|
|
104
|
+
const id = getAttr(match[1], "Id");
|
|
105
|
+
let target = getAttr(match[1], "Target");
|
|
106
|
+
if (!id || !target)
|
|
107
|
+
continue;
|
|
108
|
+
target = target.replace(/^\//, "").replace(/^xl\//, "");
|
|
109
|
+
map.set(id, `xl/${target}`);
|
|
110
|
+
}
|
|
111
|
+
return map;
|
|
112
|
+
};
|
|
113
|
+
const parseWorkbookSheets = (workbookXml) => {
|
|
114
|
+
var _a, _b;
|
|
115
|
+
if (!workbookXml)
|
|
116
|
+
return [];
|
|
117
|
+
const sheets = [];
|
|
118
|
+
const sheetRe = /<sheet\b([^>]*)\/?>/g;
|
|
119
|
+
let match;
|
|
120
|
+
while ((match = sheetRe.exec(workbookXml)) !== null) {
|
|
121
|
+
const name = (_a = getAttr(match[1], "name")) !== null && _a !== void 0 ? _a : `Sheet${sheets.length + 1}`;
|
|
122
|
+
const rId = (_b = getAttr(match[1], "r:id")) !== null && _b !== void 0 ? _b : getAttr(match[1], "id");
|
|
123
|
+
sheets.push({ name, rId });
|
|
124
|
+
}
|
|
125
|
+
return sheets;
|
|
126
|
+
};
|
|
127
|
+
const parseWorksheet = (sheetXml, sharedStrings, dateStyleFlags, cellDates) => {
|
|
128
|
+
var _a;
|
|
129
|
+
const rows = [];
|
|
130
|
+
const formulas = [];
|
|
131
|
+
let sawFormula = false;
|
|
132
|
+
const rowRe = /<row\b([^>]*)>([\s\S]*?)<\/row>/g;
|
|
133
|
+
let rowMatch;
|
|
134
|
+
let sequentialRowIndex = -1;
|
|
135
|
+
while ((rowMatch = rowRe.exec(sheetXml)) !== null) {
|
|
136
|
+
sequentialRowIndex++;
|
|
137
|
+
const rAttr = getAttr(rowMatch[1], "r");
|
|
138
|
+
const rowIndex = rAttr ? Number(rAttr) - 1 : sequentialRowIndex;
|
|
139
|
+
const rowInner = rowMatch[2];
|
|
140
|
+
const rowValues = [];
|
|
141
|
+
const rowFormulas = [];
|
|
142
|
+
let sequentialColIndex = -1;
|
|
143
|
+
const cellRe = /<c\b([^>]*?)(?:\/>|>([\s\S]*?)<\/c>)/g;
|
|
144
|
+
let cellMatch;
|
|
145
|
+
while ((cellMatch = cellRe.exec(rowInner)) !== null) {
|
|
146
|
+
sequentialColIndex++;
|
|
147
|
+
const attrs = cellMatch[1];
|
|
148
|
+
const inner = cellMatch[2] || "";
|
|
149
|
+
const ref = getAttr(attrs, "r");
|
|
150
|
+
const colLetters = ref ? ref.replace(/[0-9]/g, "") : "";
|
|
151
|
+
const colIndex = colLetters ? columnLettersToIndex(colLetters) : sequentialColIndex;
|
|
152
|
+
const type = getAttr(attrs, "t") || "n";
|
|
153
|
+
const styleIndex = Number(getAttr(attrs, "s") || "0");
|
|
154
|
+
const fMatch = inner.match(/<f\b[^>]*>([\s\S]*?)<\/f>|<f\b[^>]*\/>/);
|
|
155
|
+
const formula = fMatch ? decodeXml(fMatch[1] || "") : null;
|
|
156
|
+
if (formula)
|
|
157
|
+
sawFormula = true;
|
|
158
|
+
const vMatch = inner.match(/<v\b[^>]*>([\s\S]*?)<\/v>/);
|
|
159
|
+
const rawValue = vMatch ? decodeXml(vMatch[1]) : undefined;
|
|
160
|
+
let value = null;
|
|
161
|
+
if (type === "s") {
|
|
162
|
+
const idx = Number(rawValue);
|
|
163
|
+
value = Number.isNaN(idx) ? "" : (_a = sharedStrings[idx]) !== null && _a !== void 0 ? _a : "";
|
|
164
|
+
}
|
|
165
|
+
else if (type === "inlineStr") {
|
|
166
|
+
const isMatch = inner.match(/<is\b[^>]*>([\s\S]*?)<\/is>/);
|
|
167
|
+
let text = "";
|
|
168
|
+
if (isMatch) {
|
|
169
|
+
const tRe = /<t\b[^>]*>([\s\S]*?)<\/t>/g;
|
|
170
|
+
let tMatch;
|
|
171
|
+
while ((tMatch = tRe.exec(isMatch[1])) !== null)
|
|
172
|
+
text += decodeXml(tMatch[1]);
|
|
173
|
+
}
|
|
174
|
+
value = text;
|
|
175
|
+
}
|
|
176
|
+
else if (type === "str") {
|
|
177
|
+
value = rawValue !== null && rawValue !== void 0 ? rawValue : (formula !== null && formula !== void 0 ? formula : "");
|
|
178
|
+
}
|
|
179
|
+
else if (type === "b") {
|
|
180
|
+
value = rawValue === "1" || rawValue === "true";
|
|
181
|
+
}
|
|
182
|
+
else if (type === "e") {
|
|
183
|
+
value = rawValue !== null && rawValue !== void 0 ? rawValue : null;
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
if (rawValue === undefined || rawValue === "") {
|
|
187
|
+
value = formula !== null ? formula : null;
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
const num = Number(rawValue);
|
|
191
|
+
if (Number.isNaN(num)) {
|
|
192
|
+
value = rawValue;
|
|
193
|
+
}
|
|
194
|
+
else if (cellDates && dateStyleFlags[styleIndex]) {
|
|
195
|
+
value = excelSerialToDate(num);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
value = num;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
rowValues[colIndex] = value;
|
|
203
|
+
rowFormulas[colIndex] = formula;
|
|
204
|
+
}
|
|
205
|
+
rows[rowIndex] = rowValues;
|
|
206
|
+
formulas[rowIndex] = rowFormulas;
|
|
207
|
+
}
|
|
208
|
+
const width = rows.reduce((max, row) => Math.max(max, row ? row.length : 0), 0);
|
|
209
|
+
for (let r = 0; r < rows.length; r++) {
|
|
210
|
+
if (!rows[r])
|
|
211
|
+
rows[r] = [];
|
|
212
|
+
for (let c = 0; c < width; c++) {
|
|
213
|
+
if (rows[r][c] === undefined)
|
|
214
|
+
rows[r][c] = null;
|
|
215
|
+
if (!formulas[r])
|
|
216
|
+
formulas[r] = [];
|
|
217
|
+
if (formulas[r][c] === undefined)
|
|
218
|
+
formulas[r][c] = null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return sawFormula ? { rows, formulas } : { rows };
|
|
222
|
+
};
|
|
223
|
+
exports.parseWorksheet = parseWorksheet;
|
|
224
|
+
const toZipInput = (input) => __awaiter(void 0, void 0, void 0, function* () {
|
|
225
|
+
if (typeof input === "string") {
|
|
226
|
+
const fs = require("fs");
|
|
227
|
+
return fs.readFileSync(input);
|
|
228
|
+
}
|
|
229
|
+
return input;
|
|
230
|
+
});
|
|
231
|
+
const readExcel = (input, options = {}) => __awaiter(void 0, void 0, void 0, function* () {
|
|
232
|
+
const cellDates = options.cellDates !== false;
|
|
233
|
+
const JSZip = require("jszip");
|
|
234
|
+
const zip = yield JSZip.loadAsync(yield toZipInput(input));
|
|
235
|
+
const readPart = (path) => __awaiter(void 0, void 0, void 0, function* () {
|
|
236
|
+
const file = zip.file(path);
|
|
237
|
+
return file ? yield file.async("string") : undefined;
|
|
238
|
+
});
|
|
239
|
+
const [workbookXml, relsXml, sharedStringsXml, stylesXml] = yield Promise.all([
|
|
240
|
+
readPart("xl/workbook.xml"),
|
|
241
|
+
readPart("xl/_rels/workbook.xml.rels"),
|
|
242
|
+
readPart("xl/sharedStrings.xml"),
|
|
243
|
+
readPart("xl/styles.xml"),
|
|
244
|
+
]);
|
|
245
|
+
const sharedStrings = parseSharedStrings(sharedStringsXml);
|
|
246
|
+
const dateStyleFlags = parseDateStyleFlags(stylesXml);
|
|
247
|
+
const rels = parseWorkbookRels(relsXml);
|
|
248
|
+
const sheetRefs = parseWorkbookSheets(workbookXml);
|
|
249
|
+
const sheets = [];
|
|
250
|
+
for (let i = 0; i < sheetRefs.length; i++) {
|
|
251
|
+
const ref = sheetRefs[i];
|
|
252
|
+
let path = ref.rId ? rels.get(ref.rId) : undefined;
|
|
253
|
+
if (!path || !zip.file(path))
|
|
254
|
+
path = `xl/worksheets/sheet${i + 1}.xml`;
|
|
255
|
+
const sheetXml = yield readPart(path);
|
|
256
|
+
if (sheetXml === undefined) {
|
|
257
|
+
sheets.push({ title: ref.name, rows: [] });
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
const parsed = parseWorksheet(sheetXml, sharedStrings, dateStyleFlags, cellDates);
|
|
261
|
+
sheets.push(Object.assign({ title: ref.name }, parsed));
|
|
262
|
+
}
|
|
263
|
+
return { sheets };
|
|
264
|
+
});
|
|
265
|
+
exports.readExcel = readExcel;
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
declare enum ICellType {
|
|
2
|
+
string = "s",
|
|
3
|
+
number = "n",
|
|
4
|
+
date = "d",
|
|
5
|
+
skip = "skip",
|
|
6
|
+
equation = "equation"
|
|
7
|
+
}
|
|
8
|
+
declare enum BorderStyle {
|
|
9
|
+
none = "none",
|
|
10
|
+
thin = "thin",
|
|
11
|
+
medium = "medium",
|
|
12
|
+
thick = "thick",
|
|
13
|
+
double = "double",
|
|
14
|
+
dotted = "dotted",
|
|
15
|
+
dashed = "dashed"
|
|
16
|
+
}
|
|
17
|
+
declare enum HorizontalAlignment {
|
|
18
|
+
general = "general",
|
|
19
|
+
left = "left",
|
|
20
|
+
center = "center",
|
|
21
|
+
right = "right",
|
|
22
|
+
fill = "fill",
|
|
23
|
+
justify = "justify",
|
|
24
|
+
centerContinuous = "centerContinuous",
|
|
25
|
+
distributed = "distributed"
|
|
26
|
+
}
|
|
27
|
+
declare enum VerticalAlignment {
|
|
28
|
+
top = "top",
|
|
29
|
+
center = "center",
|
|
30
|
+
bottom = "bottom",
|
|
31
|
+
justify = "justify",
|
|
32
|
+
distributed = "distributed"
|
|
33
|
+
}
|
|
34
|
+
export { ICellType, BorderStyle, HorizontalAlignment, VerticalAlignment };
|
package/lib/types.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VerticalAlignment = exports.HorizontalAlignment = exports.BorderStyle = exports.ICellType = void 0;
|
|
4
|
+
var ICellType;
|
|
5
|
+
(function (ICellType) {
|
|
6
|
+
ICellType["string"] = "s";
|
|
7
|
+
ICellType["number"] = "n";
|
|
8
|
+
ICellType["date"] = "d";
|
|
9
|
+
ICellType["skip"] = "skip";
|
|
10
|
+
ICellType["equation"] = "equation";
|
|
11
|
+
})(ICellType || (ICellType = {}));
|
|
12
|
+
exports.ICellType = ICellType;
|
|
13
|
+
var BorderStyle;
|
|
14
|
+
(function (BorderStyle) {
|
|
15
|
+
BorderStyle["none"] = "none";
|
|
16
|
+
BorderStyle["thin"] = "thin";
|
|
17
|
+
BorderStyle["medium"] = "medium";
|
|
18
|
+
BorderStyle["thick"] = "thick";
|
|
19
|
+
BorderStyle["double"] = "double";
|
|
20
|
+
BorderStyle["dotted"] = "dotted";
|
|
21
|
+
BorderStyle["dashed"] = "dashed";
|
|
22
|
+
})(BorderStyle || (BorderStyle = {}));
|
|
23
|
+
exports.BorderStyle = BorderStyle;
|
|
24
|
+
var HorizontalAlignment;
|
|
25
|
+
(function (HorizontalAlignment) {
|
|
26
|
+
HorizontalAlignment["general"] = "general";
|
|
27
|
+
HorizontalAlignment["left"] = "left";
|
|
28
|
+
HorizontalAlignment["center"] = "center";
|
|
29
|
+
HorizontalAlignment["right"] = "right";
|
|
30
|
+
HorizontalAlignment["fill"] = "fill";
|
|
31
|
+
HorizontalAlignment["justify"] = "justify";
|
|
32
|
+
HorizontalAlignment["centerContinuous"] = "centerContinuous";
|
|
33
|
+
HorizontalAlignment["distributed"] = "distributed";
|
|
34
|
+
})(HorizontalAlignment || (HorizontalAlignment = {}));
|
|
35
|
+
exports.HorizontalAlignment = HorizontalAlignment;
|
|
36
|
+
var VerticalAlignment;
|
|
37
|
+
(function (VerticalAlignment) {
|
|
38
|
+
VerticalAlignment["top"] = "top";
|
|
39
|
+
VerticalAlignment["center"] = "center";
|
|
40
|
+
VerticalAlignment["bottom"] = "bottom";
|
|
41
|
+
VerticalAlignment["justify"] = "justify";
|
|
42
|
+
VerticalAlignment["distributed"] = "distributed";
|
|
43
|
+
})(VerticalAlignment || (VerticalAlignment = {}));
|
|
44
|
+
exports.VerticalAlignment = VerticalAlignment;
|
package/lib/util.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { IRows, IBorder,
|
|
1
|
+
import { IRows, IBorder, ICellStyle, ICell } from ".";
|
|
2
|
+
import { BorderStyle, HorizontalAlignment, VerticalAlignment } from "./types";
|
|
2
3
|
declare const indexToVbIndex: (index: number) => number;
|
|
3
4
|
declare const indexToVbRelationIndex: (index: number) => number;
|
|
4
5
|
declare const indexToRowIndex: (index: number) => string;
|
|
@@ -33,4 +34,8 @@ declare const createBackgroundCell: (value: string | number, backgroundColor: st
|
|
|
33
34
|
declare const createForegroundCell: (value: string | number, foregroundColor: string) => ICell;
|
|
34
35
|
declare const createColoredCell: (value: string | number, backgroundColor: string, foregroundColor: string) => ICell;
|
|
35
36
|
declare const createBackgroundDateCell: (date: Date, backgroundColor: string) => ICell;
|
|
36
|
-
|
|
37
|
+
declare const createHorizontallyAlignedCell: (value: string | number | Date, alignment: HorizontalAlignment) => ICell;
|
|
38
|
+
declare const createVerticallyAlignedCell: (value: string | number | Date, alignment: VerticalAlignment) => ICell;
|
|
39
|
+
declare const createAlignedCell: (value: string | number | Date, horizontal: HorizontalAlignment, vertical: VerticalAlignment) => ICell;
|
|
40
|
+
declare const createCenteredCell: (value: string | number | Date) => ICell;
|
|
41
|
+
export { indexToVbIndex, indexToVbRelationIndex, indexToRowIndex, rowColumnToVbPosition, calculateExtant, SkipCell, skipCell, Equation, writeEquation, createBorder, createAllBorders, createTopBorder, createBottomBorder, createLeftBorder, createRightBorder, getBorderKey, getStyleKey, createStyledCell, createBorderedCell, dateToExcelSerial, createDateCell, createBorderedDateCell, createBackgroundCell, createForegroundCell, createColoredCell, createBackgroundDateCell, createHorizontallyAlignedCell, createVerticallyAlignedCell, createAlignedCell, createCenteredCell };
|
package/lib/util.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createBackgroundDateCell = exports.createColoredCell = exports.createForegroundCell = exports.createBackgroundCell = exports.createBorderedDateCell = exports.createDateCell = exports.dateToExcelSerial = exports.createBorderedCell = exports.createStyledCell = exports.getStyleKey = exports.getBorderKey = exports.createRightBorder = exports.createLeftBorder = exports.createBottomBorder = exports.createTopBorder = exports.createAllBorders = exports.createBorder = exports.writeEquation = exports.Equation = exports.skipCell = exports.SkipCell = exports.calculateExtant = exports.rowColumnToVbPosition = exports.indexToRowIndex = exports.indexToVbRelationIndex = exports.indexToVbIndex = void 0;
|
|
4
|
-
const
|
|
3
|
+
exports.createCenteredCell = exports.createAlignedCell = exports.createVerticallyAlignedCell = exports.createHorizontallyAlignedCell = exports.createBackgroundDateCell = exports.createColoredCell = exports.createForegroundCell = exports.createBackgroundCell = exports.createBorderedDateCell = exports.createDateCell = exports.dateToExcelSerial = exports.createBorderedCell = exports.createStyledCell = exports.getStyleKey = exports.getBorderKey = exports.createRightBorder = exports.createLeftBorder = exports.createBottomBorder = exports.createTopBorder = exports.createAllBorders = exports.createBorder = exports.writeEquation = exports.Equation = exports.skipCell = exports.SkipCell = exports.calculateExtant = exports.rowColumnToVbPosition = exports.indexToRowIndex = exports.indexToVbRelationIndex = exports.indexToVbIndex = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
5
|
const indexToVbIndex = (index) => index + 1;
|
|
6
6
|
exports.indexToVbIndex = indexToVbIndex;
|
|
7
7
|
const indexToVbRelationIndex = (index) => indexToVbIndex(index) + 2;
|
|
@@ -41,7 +41,7 @@ const writeEquation = (equation) => new Equation(equation);
|
|
|
41
41
|
exports.writeEquation = writeEquation;
|
|
42
42
|
const createBorder = (border) => border;
|
|
43
43
|
exports.createBorder = createBorder;
|
|
44
|
-
const createAllBorders = (style =
|
|
44
|
+
const createAllBorders = (style = types_1.BorderStyle.thin, color = "#000000") => ({
|
|
45
45
|
top: style,
|
|
46
46
|
right: style,
|
|
47
47
|
bottom: style,
|
|
@@ -49,22 +49,22 @@ const createAllBorders = (style = _1.BorderStyle.thin, color = "#000000") => ({
|
|
|
49
49
|
color
|
|
50
50
|
});
|
|
51
51
|
exports.createAllBorders = createAllBorders;
|
|
52
|
-
const createTopBorder = (style =
|
|
52
|
+
const createTopBorder = (style = types_1.BorderStyle.thin, color = "#000000") => ({
|
|
53
53
|
top: style,
|
|
54
54
|
color
|
|
55
55
|
});
|
|
56
56
|
exports.createTopBorder = createTopBorder;
|
|
57
|
-
const createBottomBorder = (style =
|
|
57
|
+
const createBottomBorder = (style = types_1.BorderStyle.thin, color = "#000000") => ({
|
|
58
58
|
bottom: style,
|
|
59
59
|
color
|
|
60
60
|
});
|
|
61
61
|
exports.createBottomBorder = createBottomBorder;
|
|
62
|
-
const createLeftBorder = (style =
|
|
62
|
+
const createLeftBorder = (style = types_1.BorderStyle.thin, color = "#000000") => ({
|
|
63
63
|
left: style,
|
|
64
64
|
color
|
|
65
65
|
});
|
|
66
66
|
exports.createLeftBorder = createLeftBorder;
|
|
67
|
-
const createRightBorder = (style =
|
|
67
|
+
const createRightBorder = (style = types_1.BorderStyle.thin, color = "#000000") => ({
|
|
68
68
|
right: style,
|
|
69
69
|
color
|
|
70
70
|
});
|
|
@@ -88,7 +88,9 @@ const getStyleKey = (style) => {
|
|
|
88
88
|
const parts = [
|
|
89
89
|
getBorderKey(style.border),
|
|
90
90
|
style.backgroundColor || "no-bg",
|
|
91
|
-
style.foregroundColor || "no-fg"
|
|
91
|
+
style.foregroundColor || "no-fg",
|
|
92
|
+
style.horizontalAlignment || "no-halign",
|
|
93
|
+
style.verticalAlignment || "no-valign"
|
|
92
94
|
];
|
|
93
95
|
return parts.join("|");
|
|
94
96
|
};
|
|
@@ -96,14 +98,14 @@ exports.getStyleKey = getStyleKey;
|
|
|
96
98
|
const createStyledCell = (value, style) => {
|
|
97
99
|
if (typeof value === 'string') {
|
|
98
100
|
return {
|
|
99
|
-
type:
|
|
101
|
+
type: types_1.ICellType.string,
|
|
100
102
|
value: value,
|
|
101
103
|
style
|
|
102
104
|
};
|
|
103
105
|
}
|
|
104
106
|
else {
|
|
105
107
|
return {
|
|
106
|
-
type:
|
|
108
|
+
type: types_1.ICellType.number,
|
|
107
109
|
value,
|
|
108
110
|
style
|
|
109
111
|
};
|
|
@@ -123,7 +125,7 @@ const dateToExcelSerial = (date) => {
|
|
|
123
125
|
exports.dateToExcelSerial = dateToExcelSerial;
|
|
124
126
|
const createDateCell = (date, style) => {
|
|
125
127
|
return {
|
|
126
|
-
type:
|
|
128
|
+
type: types_1.ICellType.date,
|
|
127
129
|
value: date,
|
|
128
130
|
style
|
|
129
131
|
};
|
|
@@ -149,3 +151,34 @@ const createBackgroundDateCell = (date, backgroundColor) => {
|
|
|
149
151
|
return createDateCell(date, { backgroundColor });
|
|
150
152
|
};
|
|
151
153
|
exports.createBackgroundDateCell = createBackgroundDateCell;
|
|
154
|
+
const createHorizontallyAlignedCell = (value, alignment) => {
|
|
155
|
+
if (value instanceof Date) {
|
|
156
|
+
return createDateCell(value, { horizontalAlignment: alignment });
|
|
157
|
+
}
|
|
158
|
+
return createStyledCell(value, { horizontalAlignment: alignment });
|
|
159
|
+
};
|
|
160
|
+
exports.createHorizontallyAlignedCell = createHorizontallyAlignedCell;
|
|
161
|
+
const createVerticallyAlignedCell = (value, alignment) => {
|
|
162
|
+
if (value instanceof Date) {
|
|
163
|
+
return createDateCell(value, { verticalAlignment: alignment });
|
|
164
|
+
}
|
|
165
|
+
return createStyledCell(value, { verticalAlignment: alignment });
|
|
166
|
+
};
|
|
167
|
+
exports.createVerticallyAlignedCell = createVerticallyAlignedCell;
|
|
168
|
+
const createAlignedCell = (value, horizontal, vertical) => {
|
|
169
|
+
if (value instanceof Date) {
|
|
170
|
+
return createDateCell(value, {
|
|
171
|
+
horizontalAlignment: horizontal,
|
|
172
|
+
verticalAlignment: vertical
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
return createStyledCell(value, {
|
|
176
|
+
horizontalAlignment: horizontal,
|
|
177
|
+
verticalAlignment: vertical
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
exports.createAlignedCell = createAlignedCell;
|
|
181
|
+
const createCenteredCell = (value) => {
|
|
182
|
+
return createAlignedCell(value, types_1.HorizontalAlignment.center, types_1.VerticalAlignment.center);
|
|
183
|
+
};
|
|
184
|
+
exports.createCenteredCell = createCenteredCell;
|
package/lib/xl/styles.xml.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateStyleXml = void 0;
|
|
4
|
-
const
|
|
4
|
+
const types_1 = require("../types");
|
|
5
5
|
const generateBorderXml = (border) => {
|
|
6
6
|
const getColorXml = (color) => color ? `<color rgb="${color.replace('#', 'FF')}" />` : '';
|
|
7
7
|
const getBorderSideXml = (side, color) => {
|
|
8
|
-
if (!side || side ===
|
|
8
|
+
if (!side || side === types_1.BorderStyle.none) {
|
|
9
9
|
return '<left />';
|
|
10
10
|
}
|
|
11
11
|
return `<left style="${side}">${getColorXml(color)}</left>`;
|
|
12
12
|
};
|
|
13
|
-
const leftXml = !border.left || border.left ===
|
|
13
|
+
const leftXml = !border.left || border.left === types_1.BorderStyle.none
|
|
14
14
|
? '<left />'
|
|
15
15
|
: `<left style="${border.left}">${getColorXml(border.color)}</left>`;
|
|
16
|
-
const rightXml = !border.right || border.right ===
|
|
16
|
+
const rightXml = !border.right || border.right === types_1.BorderStyle.none
|
|
17
17
|
? '<right />'
|
|
18
18
|
: `<right style="${border.right}">${getColorXml(border.color)}</right>`;
|
|
19
|
-
const topXml = !border.top || border.top ===
|
|
19
|
+
const topXml = !border.top || border.top === types_1.BorderStyle.none
|
|
20
20
|
? '<top />'
|
|
21
21
|
: `<top style="${border.top}">${getColorXml(border.color)}</top>`;
|
|
22
|
-
const bottomXml = !border.bottom || border.bottom ===
|
|
22
|
+
const bottomXml = !border.bottom || border.bottom === types_1.BorderStyle.none
|
|
23
23
|
? '<bottom />'
|
|
24
24
|
: `<bottom style="${border.bottom}">${getColorXml(border.color)}</bottom>`;
|
|
25
25
|
return `
|
|
@@ -59,6 +59,20 @@ const generateFillXml = (color) => {
|
|
|
59
59
|
</patternFill>
|
|
60
60
|
</fill>`;
|
|
61
61
|
};
|
|
62
|
+
const generateAlignmentXml = (style) => {
|
|
63
|
+
const hasAlignment = style.horizontalAlignment || style.verticalAlignment;
|
|
64
|
+
if (!hasAlignment) {
|
|
65
|
+
return '';
|
|
66
|
+
}
|
|
67
|
+
let alignmentAttrs = '';
|
|
68
|
+
if (style.horizontalAlignment) {
|
|
69
|
+
alignmentAttrs += ` horizontal="${style.horizontalAlignment}"`;
|
|
70
|
+
}
|
|
71
|
+
if (style.verticalAlignment) {
|
|
72
|
+
alignmentAttrs += ` vertical="${style.verticalAlignment}"`;
|
|
73
|
+
}
|
|
74
|
+
return `<alignment${alignmentAttrs} />`;
|
|
75
|
+
};
|
|
62
76
|
const generateStyleXml = (styleMap, hasDateCells = false) => {
|
|
63
77
|
const styles = Array.from(styleMap.values());
|
|
64
78
|
const styleCount = styles.length;
|
|
@@ -98,14 +112,18 @@ const generateStyleXml = (styleMap, hasDateCells = false) => {
|
|
|
98
112
|
const borderIndex = Array.from(uniqueBorders.keys()).indexOf(JSON.stringify(style.border || {}));
|
|
99
113
|
const fontIndex = Array.from(uniqueFonts.keys()).indexOf(style.foregroundColor || "default");
|
|
100
114
|
const fillIndex = Array.from(uniqueFills.keys()).indexOf(style.backgroundColor || "none");
|
|
101
|
-
|
|
115
|
+
const alignmentXml = generateAlignmentXml(style);
|
|
116
|
+
const applyAlignment = style.horizontalAlignment || style.verticalAlignment ? ' applyAlignment="1"' : '';
|
|
117
|
+
return `<xf numFmtId="0" fontId="${fontIndex}" fillId="${fillIndex}" borderId="${borderIndex}" xfId="0"${applyAlignment}>${alignmentXml}</xf>`;
|
|
102
118
|
}).join('\n ');
|
|
103
119
|
cellXfsXml += '\n ';
|
|
104
120
|
cellXfsXml += styles.map((style, index) => {
|
|
105
121
|
const borderIndex = Array.from(uniqueBorders.keys()).indexOf(JSON.stringify(style.border || {}));
|
|
106
122
|
const fontIndex = Array.from(uniqueFonts.keys()).indexOf(style.foregroundColor || "default");
|
|
107
123
|
const fillIndex = Array.from(uniqueFills.keys()).indexOf(style.backgroundColor || "none");
|
|
108
|
-
|
|
124
|
+
const alignmentXml = generateAlignmentXml(style);
|
|
125
|
+
const applyAlignment = style.horizontalAlignment || style.verticalAlignment ? ' applyAlignment="1"' : '';
|
|
126
|
+
return `<xf numFmtId="164" fontId="${fontIndex}" fillId="${fillIndex}" borderId="${borderIndex}" xfId="0"${applyAlignment}>${alignmentXml}</xf>`;
|
|
109
127
|
}).join('\n ');
|
|
110
128
|
cellXfsCount = styleCount * 2;
|
|
111
129
|
}
|
|
@@ -114,7 +132,9 @@ const generateStyleXml = (styleMap, hasDateCells = false) => {
|
|
|
114
132
|
const borderIndex = Array.from(uniqueBorders.keys()).indexOf(JSON.stringify(style.border || {}));
|
|
115
133
|
const fontIndex = Array.from(uniqueFonts.keys()).indexOf(style.foregroundColor || "default");
|
|
116
134
|
const fillIndex = Array.from(uniqueFills.keys()).indexOf(style.backgroundColor || "none");
|
|
117
|
-
|
|
135
|
+
const alignmentXml = generateAlignmentXml(style);
|
|
136
|
+
const applyAlignment = style.horizontalAlignment || style.verticalAlignment ? ' applyAlignment="1"' : '';
|
|
137
|
+
return `<xf numFmtId="0" fontId="${fontIndex}" fillId="${fillIndex}" borderId="${borderIndex}" xfId="0"${applyAlignment}>${alignmentXml}</xf>`;
|
|
118
138
|
}).join('\n ');
|
|
119
139
|
}
|
|
120
140
|
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateSheetXml = void 0;
|
|
4
|
-
const
|
|
4
|
+
const types_1 = require("../../types");
|
|
5
5
|
const util_1 = require("../../util");
|
|
6
6
|
const generateSheetXml = (sheet, styleMap, hasDateCells = false) => {
|
|
7
7
|
const styleToIndex = new Map();
|
|
@@ -29,11 +29,11 @@ const generateSheetXml = (sheet, styleMap, hasDateCells = false) => {
|
|
|
29
29
|
rowContent += `<row r="${(0, util_1.indexToVbIndex)(rowIndex)}">\n`;
|
|
30
30
|
row.cells.forEach((cell, cellIndex) => {
|
|
31
31
|
const cellType = cell.type;
|
|
32
|
-
if (cellType !==
|
|
32
|
+
if (cellType !== types_1.ICellType.skip) {
|
|
33
33
|
const cellPosition = (0, util_1.rowColumnToVbPosition)(cellIndex, rowIndex);
|
|
34
34
|
const cellValue = cell.value || '';
|
|
35
35
|
let styleIndex = 0;
|
|
36
|
-
let isDateCell = cell.type ===
|
|
36
|
+
let isDateCell = cell.type === types_1.ICellType.date;
|
|
37
37
|
if ('style' in cell && cell.style) {
|
|
38
38
|
const styleKey = (0, util_1.getStyleKey)(cell.style);
|
|
39
39
|
const baseStyleIndex = styleToIndex.get(styleKey) || 0;
|
|
@@ -47,13 +47,13 @@ const generateSheetXml = (sheet, styleMap, hasDateCells = false) => {
|
|
|
47
47
|
else if (isDateCell && hasDateCells) {
|
|
48
48
|
styleIndex = styleMap.size;
|
|
49
49
|
}
|
|
50
|
-
if (cell.type ===
|
|
50
|
+
if (cell.type === types_1.ICellType.equation) {
|
|
51
51
|
rowContent += `
|
|
52
52
|
<c r="${cellPosition}" t="n" s="${styleIndex}">
|
|
53
53
|
<f aca="false">${cell.value.getEquation()}</f>
|
|
54
54
|
</c>\n`;
|
|
55
55
|
}
|
|
56
|
-
else if (cell.type ===
|
|
56
|
+
else if (cell.type === types_1.ICellType.date) {
|
|
57
57
|
const excelDateValue = (0, util_1.dateToExcelSerial)(cell.value);
|
|
58
58
|
rowContent += `
|
|
59
59
|
<c r="${cellPosition}" t="n" s="${styleIndex}">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "to-spreadsheet",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "npm package to create spreadsheet in node environment and in browser",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"excel",
|
|
@@ -30,11 +30,6 @@
|
|
|
30
30
|
],
|
|
31
31
|
"main": "lib/index.js",
|
|
32
32
|
"types": "lib/index.d.ts",
|
|
33
|
-
"scripts": {
|
|
34
|
-
"prepare": "npm run build",
|
|
35
|
-
"build": "tsc",
|
|
36
|
-
"test:compile": "npx ts-node src/index.ts"
|
|
37
|
-
},
|
|
38
33
|
"repository": {
|
|
39
34
|
"type": "git",
|
|
40
35
|
"url": "git+https://github.com/maifeeulasad/to-spreadsheet.git"
|
|
@@ -49,7 +44,7 @@
|
|
|
49
44
|
},
|
|
50
45
|
"homepage": "https://github.com/maifeeulasad/to-spreadsheet#readme",
|
|
51
46
|
"dependencies": {
|
|
52
|
-
"archiver": "^
|
|
47
|
+
"archiver": "^7.0.1",
|
|
53
48
|
"file-saver": "^2.0.5",
|
|
54
49
|
"jszip": "^3.10.1"
|
|
55
50
|
},
|
|
@@ -59,10 +54,18 @@
|
|
|
59
54
|
"LICENSE"
|
|
60
55
|
],
|
|
61
56
|
"devDependencies": {
|
|
62
|
-
"@
|
|
57
|
+
"@tsconfig/node16": "1.0.4",
|
|
58
|
+
"@types/archiver": "^6.0.4",
|
|
63
59
|
"@types/file-saver": "^2.0.5",
|
|
64
60
|
"@types/node": "^17.0.35",
|
|
65
61
|
"ts-node": "^10.8.0",
|
|
66
|
-
"typescript": "^4.7.2"
|
|
62
|
+
"typescript": "^4.7.2",
|
|
63
|
+
"vitest": "^2.1.9"
|
|
64
|
+
},
|
|
65
|
+
"scripts": {
|
|
66
|
+
"build": "tsc",
|
|
67
|
+
"test:compile": "npx ts-node src/index.ts",
|
|
68
|
+
"test": "vitest run",
|
|
69
|
+
"test:watch": "vitest"
|
|
67
70
|
}
|
|
68
|
-
}
|
|
71
|
+
}
|