@js-ak/excel-toolbox 1.8.3 → 1.9.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/build/cjs/lib/template/template-fs.js +2 -1
- package/build/cjs/lib/template/template-memory.js +2 -1
- package/build/cjs/lib/template/utils/column-letter-to-index.js +15 -0
- package/build/cjs/lib/template/utils/index.js +1 -1
- package/build/cjs/lib/template/utils/prepare-row-to-cells.js +2 -2
- package/build/cjs/lib/template/utils/validate-worksheet-xml.js +19 -9
- package/build/cjs/lib/utils/index.js +2 -0
- package/build/cjs/lib/utils/trim-and-join-multiline.js +32 -0
- package/build/cjs/lib/workbook-builder/default/border.js +18 -0
- package/build/cjs/lib/workbook-builder/default/cell-xf.js +15 -0
- package/build/cjs/lib/workbook-builder/default/fill.js +18 -0
- package/build/cjs/lib/workbook-builder/default/font.js +19 -0
- package/build/cjs/lib/workbook-builder/default/index.js +21 -0
- package/build/cjs/lib/workbook-builder/default/sheet-name.js +10 -0
- package/build/cjs/lib/workbook-builder/index.js +18 -0
- package/build/cjs/lib/workbook-builder/merge-cells/add.js +72 -0
- package/build/cjs/lib/workbook-builder/merge-cells/helpers/index.js +18 -0
- package/build/cjs/lib/workbook-builder/merge-cells/helpers/ranges-equal.js +17 -0
- package/build/cjs/lib/workbook-builder/merge-cells/helpers/ranges-intersect.js +17 -0
- package/build/cjs/lib/workbook-builder/merge-cells/index.js +18 -0
- package/build/cjs/lib/workbook-builder/merge-cells/remove.js +60 -0
- package/build/cjs/lib/workbook-builder/shared-string-ref/add.js +24 -0
- package/build/cjs/lib/workbook-builder/shared-string-ref/index.js +19 -0
- package/build/cjs/lib/workbook-builder/shared-string-ref/remove-all-from-sheet.js +66 -0
- package/build/cjs/lib/workbook-builder/shared-string-ref/remove.js +66 -0
- package/build/cjs/lib/workbook-builder/style-ref/add-or-get.js +94 -0
- package/build/cjs/lib/workbook-builder/style-ref/helpers/add-num-fmt.js +25 -0
- package/build/cjs/lib/workbook-builder/style-ref/helpers/border-to-xml.js +49 -0
- package/build/cjs/lib/workbook-builder/style-ref/helpers/fill-to-xml.js +51 -0
- package/build/cjs/lib/workbook-builder/style-ref/helpers/font-to-xml.js +112 -0
- package/build/cjs/lib/workbook-builder/style-ref/helpers/index.js +21 -0
- package/build/cjs/lib/workbook-builder/style-ref/helpers/reindex-style-map-after-removal.js +30 -0
- package/build/cjs/lib/workbook-builder/style-ref/index.js +19 -0
- package/build/cjs/lib/workbook-builder/style-ref/remove-all-from-sheet.js +26 -0
- package/build/cjs/lib/workbook-builder/style-ref/remove.js +52 -0
- package/build/cjs/lib/workbook-builder/types/app-xml-options.js +2 -0
- package/build/cjs/lib/workbook-builder/types/border-style.js +2 -0
- package/build/cjs/lib/workbook-builder/types/cell-data.js +2 -0
- package/build/cjs/lib/workbook-builder/types/cell-style.js +2 -0
- package/build/cjs/lib/workbook-builder/types/cell-type.js +2 -0
- package/build/cjs/lib/workbook-builder/types/cell-value.js +2 -0
- package/build/cjs/lib/workbook-builder/types/cell-xf.js +2 -0
- package/build/cjs/lib/workbook-builder/types/index.js +27 -0
- package/build/cjs/lib/workbook-builder/types/merge-cell.js +2 -0
- package/build/cjs/lib/workbook-builder/types/row-data.js +2 -0
- package/build/cjs/lib/workbook-builder/types/sheet-data.js +2 -0
- package/build/cjs/lib/workbook-builder/types/xml-node.js +2 -0
- package/build/cjs/lib/workbook-builder/utils/build-app-xml.js +51 -0
- package/build/cjs/lib/workbook-builder/utils/build-cell-children.js +59 -0
- package/build/cjs/lib/workbook-builder/utils/build-content-types-xml.js +42 -0
- package/build/cjs/lib/workbook-builder/utils/build-core-xml.js +27 -0
- package/build/cjs/lib/workbook-builder/utils/build-rels-xml.js +19 -0
- package/build/cjs/lib/workbook-builder/utils/build-shared-strings-xml.js +39 -0
- package/build/cjs/lib/workbook-builder/utils/build-styles-xml.js +178 -0
- package/build/cjs/lib/workbook-builder/utils/build-theme-xml.js +609 -0
- package/build/cjs/lib/workbook-builder/utils/build-workbook-rels-xml.js +58 -0
- package/build/cjs/lib/workbook-builder/utils/build-workbook-xml.js +26 -0
- package/build/cjs/lib/workbook-builder/utils/build-worksheet-xml.js +66 -0
- package/build/cjs/lib/workbook-builder/utils/build-xml.js +72 -0
- package/build/cjs/lib/workbook-builder/utils/constants.js +55 -0
- package/build/cjs/lib/workbook-builder/utils/date-to-excel-serial.js +16 -0
- package/build/cjs/lib/workbook-builder/utils/index.js +34 -0
- package/build/cjs/lib/workbook-builder/utils/initialize-files.js +40 -0
- package/build/cjs/lib/workbook-builder/utils/sheet.js +144 -0
- package/build/cjs/lib/workbook-builder/utils/write-shared-strings-xml.js +49 -0
- package/build/cjs/lib/workbook-builder/utils/write-styles-xml.js +196 -0
- package/build/cjs/lib/workbook-builder/utils/write-worksheet-xml.js +209 -0
- package/build/cjs/lib/workbook-builder/utils/write-xml.js +37 -0
- package/build/cjs/lib/workbook-builder/workbook-builder.js +414 -0
- package/build/esm/lib/template/template-fs.js +2 -1
- package/build/esm/lib/template/template-memory.js +2 -1
- package/build/esm/lib/template/utils/column-letter-to-index.js +12 -0
- package/build/esm/lib/template/utils/index.js +1 -1
- package/build/esm/lib/template/utils/prepare-row-to-cells.js +1 -1
- package/build/esm/lib/template/utils/validate-worksheet-xml.js +19 -9
- package/build/esm/lib/utils/index.js +2 -0
- package/build/esm/lib/utils/trim-and-join-multiline.js +29 -0
- package/build/esm/lib/workbook-builder/default/border.js +14 -0
- package/build/esm/lib/workbook-builder/default/cell-xf.js +11 -0
- package/build/esm/lib/workbook-builder/default/fill.js +14 -0
- package/build/esm/lib/workbook-builder/default/font.js +15 -0
- package/build/esm/lib/workbook-builder/default/index.js +5 -0
- package/build/esm/lib/workbook-builder/default/sheet-name.js +6 -0
- package/build/esm/lib/workbook-builder/index.js +2 -0
- package/build/esm/lib/workbook-builder/merge-cells/add.js +36 -0
- package/build/esm/lib/workbook-builder/merge-cells/helpers/index.js +2 -0
- package/build/esm/lib/workbook-builder/merge-cells/helpers/ranges-equal.js +14 -0
- package/build/esm/lib/workbook-builder/merge-cells/helpers/ranges-intersect.js +14 -0
- package/build/esm/lib/workbook-builder/merge-cells/index.js +2 -0
- package/build/esm/lib/workbook-builder/merge-cells/remove.js +24 -0
- package/build/esm/lib/workbook-builder/shared-string-ref/add.js +21 -0
- package/build/esm/lib/workbook-builder/shared-string-ref/index.js +3 -0
- package/build/esm/lib/workbook-builder/shared-string-ref/remove-all-from-sheet.js +63 -0
- package/build/esm/lib/workbook-builder/shared-string-ref/remove.js +63 -0
- package/build/esm/lib/workbook-builder/style-ref/add-or-get.js +58 -0
- package/build/esm/lib/workbook-builder/style-ref/helpers/add-num-fmt.js +21 -0
- package/build/esm/lib/workbook-builder/style-ref/helpers/border-to-xml.js +45 -0
- package/build/esm/lib/workbook-builder/style-ref/helpers/fill-to-xml.js +47 -0
- package/build/esm/lib/workbook-builder/style-ref/helpers/font-to-xml.js +75 -0
- package/build/esm/lib/workbook-builder/style-ref/helpers/index.js +5 -0
- package/build/esm/lib/workbook-builder/style-ref/helpers/reindex-style-map-after-removal.js +26 -0
- package/build/esm/lib/workbook-builder/style-ref/index.js +3 -0
- package/build/esm/lib/workbook-builder/style-ref/remove-all-from-sheet.js +23 -0
- package/build/esm/lib/workbook-builder/style-ref/remove.js +49 -0
- package/build/esm/lib/workbook-builder/types/app-xml-options.js +1 -0
- package/build/esm/lib/workbook-builder/types/border-style.js +1 -0
- package/build/esm/lib/workbook-builder/types/cell-data.js +1 -0
- package/build/esm/lib/workbook-builder/types/cell-style.js +1 -0
- package/build/esm/lib/workbook-builder/types/cell-type.js +1 -0
- package/build/esm/lib/workbook-builder/types/cell-value.js +1 -0
- package/build/esm/lib/workbook-builder/types/cell-xf.js +1 -0
- package/build/esm/lib/workbook-builder/types/index.js +11 -0
- package/build/esm/lib/workbook-builder/types/merge-cell.js +1 -0
- package/build/esm/lib/workbook-builder/types/row-data.js +1 -0
- package/build/esm/lib/workbook-builder/types/sheet-data.js +1 -0
- package/build/esm/lib/workbook-builder/types/xml-node.js +1 -0
- package/build/esm/lib/workbook-builder/utils/build-app-xml.js +48 -0
- package/build/esm/lib/workbook-builder/utils/build-cell-children.js +56 -0
- package/build/esm/lib/workbook-builder/utils/build-content-types-xml.js +39 -0
- package/build/esm/lib/workbook-builder/utils/build-core-xml.js +24 -0
- package/build/esm/lib/workbook-builder/utils/build-rels-xml.js +16 -0
- package/build/esm/lib/workbook-builder/utils/build-shared-strings-xml.js +36 -0
- package/build/esm/lib/workbook-builder/utils/build-styles-xml.js +142 -0
- package/build/esm/lib/workbook-builder/utils/build-theme-xml.js +606 -0
- package/build/esm/lib/workbook-builder/utils/build-workbook-rels-xml.js +55 -0
- package/build/esm/lib/workbook-builder/utils/build-workbook-xml.js +23 -0
- package/build/esm/lib/workbook-builder/utils/build-worksheet-xml.js +63 -0
- package/build/esm/lib/workbook-builder/utils/build-xml.js +69 -0
- package/build/esm/lib/workbook-builder/utils/constants.js +52 -0
- package/build/esm/lib/workbook-builder/utils/date-to-excel-serial.js +13 -0
- package/build/esm/lib/workbook-builder/utils/index.js +18 -0
- package/build/esm/lib/workbook-builder/utils/initialize-files.js +36 -0
- package/build/esm/lib/workbook-builder/utils/sheet.js +141 -0
- package/build/esm/lib/workbook-builder/utils/write-shared-strings-xml.js +43 -0
- package/build/esm/lib/workbook-builder/utils/write-styles-xml.js +157 -0
- package/build/esm/lib/workbook-builder/utils/write-worksheet-xml.js +203 -0
- package/build/esm/lib/workbook-builder/utils/write-xml.js +34 -0
- package/build/esm/lib/workbook-builder/workbook-builder.js +374 -0
- package/build/types/lib/template/utils/column-letter-to-index.d.ts +1 -0
- package/build/types/lib/template/utils/index.d.ts +1 -1
- package/build/types/lib/utils/index.d.ts +2 -0
- package/build/types/lib/utils/trim-and-join-multiline.d.ts +23 -0
- package/build/types/lib/workbook-builder/default/border.d.ts +7 -0
- package/build/types/lib/workbook-builder/default/cell-xf.d.ts +7 -0
- package/build/types/lib/workbook-builder/default/fill.d.ts +7 -0
- package/build/types/lib/workbook-builder/default/font.d.ts +21 -0
- package/build/types/lib/workbook-builder/default/index.d.ts +5 -0
- package/build/types/lib/workbook-builder/default/sheet-name.d.ts +6 -0
- package/build/types/lib/workbook-builder/index.d.ts +2 -0
- package/build/types/lib/workbook-builder/merge-cells/add.d.ts +15 -0
- package/build/types/lib/workbook-builder/merge-cells/helpers/index.d.ts +2 -0
- package/build/types/lib/workbook-builder/merge-cells/helpers/ranges-equal.d.ts +10 -0
- package/build/types/lib/workbook-builder/merge-cells/helpers/ranges-intersect.d.ts +10 -0
- package/build/types/lib/workbook-builder/merge-cells/index.d.ts +2 -0
- package/build/types/lib/workbook-builder/merge-cells/remove.d.ts +15 -0
- package/build/types/lib/workbook-builder/shared-string-ref/add.d.ts +13 -0
- package/build/types/lib/workbook-builder/shared-string-ref/index.d.ts +3 -0
- package/build/types/lib/workbook-builder/shared-string-ref/remove-all-from-sheet.d.ts +10 -0
- package/build/types/lib/workbook-builder/shared-string-ref/remove.d.ts +13 -0
- package/build/types/lib/workbook-builder/style-ref/add-or-get.d.ts +16 -0
- package/build/types/lib/workbook-builder/style-ref/helpers/add-num-fmt.d.ts +17 -0
- package/build/types/lib/workbook-builder/style-ref/helpers/border-to-xml.d.ts +16 -0
- package/build/types/lib/workbook-builder/style-ref/helpers/fill-to-xml.d.ts +17 -0
- package/build/types/lib/workbook-builder/style-ref/helpers/font-to-xml.d.ts +18 -0
- package/build/types/lib/workbook-builder/style-ref/helpers/index.d.ts +5 -0
- package/build/types/lib/workbook-builder/style-ref/helpers/reindex-style-map-after-removal.d.ts +15 -0
- package/build/types/lib/workbook-builder/style-ref/index.d.ts +3 -0
- package/build/types/lib/workbook-builder/style-ref/remove-all-from-sheet.d.ts +4 -0
- package/build/types/lib/workbook-builder/style-ref/remove.d.ts +18 -0
- package/build/types/lib/workbook-builder/types/app-xml-options.d.ts +9 -0
- package/build/types/lib/workbook-builder/types/border-style.d.ts +5 -0
- package/build/types/lib/workbook-builder/types/cell-data.d.ts +10 -0
- package/build/types/lib/workbook-builder/types/cell-style.d.ts +32 -0
- package/build/types/lib/workbook-builder/types/cell-type.d.ts +11 -0
- package/build/types/lib/workbook-builder/types/cell-value.d.ts +2 -0
- package/build/types/lib/workbook-builder/types/cell-xf.d.ts +13 -0
- package/build/types/lib/workbook-builder/types/index.d.ts +11 -0
- package/build/types/lib/workbook-builder/types/merge-cell.d.ts +6 -0
- package/build/types/lib/workbook-builder/types/row-data.d.ts +5 -0
- package/build/types/lib/workbook-builder/types/sheet-data.d.ts +13 -0
- package/build/types/lib/workbook-builder/types/xml-node.d.ts +11 -0
- package/build/types/lib/workbook-builder/utils/build-app-xml.d.ts +2 -0
- package/build/types/lib/workbook-builder/utils/build-cell-children.d.ts +9 -0
- package/build/types/lib/workbook-builder/utils/build-content-types-xml.d.ts +1 -0
- package/build/types/lib/workbook-builder/utils/build-core-xml.d.ts +1 -0
- package/build/types/lib/workbook-builder/utils/build-rels-xml.d.ts +1 -0
- package/build/types/lib/workbook-builder/utils/build-shared-strings-xml.d.ts +10 -0
- package/build/types/lib/workbook-builder/utils/build-styles-xml.d.ts +23 -0
- package/build/types/lib/workbook-builder/utils/build-theme-xml.d.ts +1 -0
- package/build/types/lib/workbook-builder/utils/build-workbook-rels-xml.d.ts +9 -0
- package/build/types/lib/workbook-builder/utils/build-workbook-xml.d.ts +3 -0
- package/build/types/lib/workbook-builder/utils/build-worksheet-xml.d.ts +2 -0
- package/build/types/lib/workbook-builder/utils/build-xml.d.ts +50 -0
- package/build/types/lib/workbook-builder/utils/constants.d.ts +47 -0
- package/build/types/lib/workbook-builder/utils/date-to-excel-serial.d.ts +9 -0
- package/build/types/lib/workbook-builder/utils/index.d.ts +18 -0
- package/build/types/lib/workbook-builder/utils/initialize-files.d.ts +13 -0
- package/build/types/lib/workbook-builder/utils/sheet.d.ts +21 -0
- package/build/types/lib/workbook-builder/utils/write-shared-strings-xml.d.ts +11 -0
- package/build/types/lib/workbook-builder/utils/write-styles-xml.d.ts +24 -0
- package/build/types/lib/workbook-builder/utils/write-worksheet-xml.d.ts +14 -0
- package/build/types/lib/workbook-builder/utils/write-xml.d.ts +3 -0
- package/build/types/lib/workbook-builder/workbook-builder.d.ts +110 -0
- package/package.json +1 -1
- /package/build/cjs/lib/{template/utils → utils}/escape-xml.js +0 -0
- /package/build/esm/lib/{template/utils → utils}/escape-xml.js +0 -0
- /package/build/types/lib/{template/utils → utils}/escape-xml.d.ts +0 -0
@@ -0,0 +1,196 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15
|
+
}) : function(o, v) {
|
16
|
+
o["default"] = v;
|
17
|
+
});
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
19
|
+
var ownKeys = function(o) {
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
21
|
+
var ar = [];
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
23
|
+
return ar;
|
24
|
+
};
|
25
|
+
return ownKeys(o);
|
26
|
+
};
|
27
|
+
return function (mod) {
|
28
|
+
if (mod && mod.__esModule) return mod;
|
29
|
+
var result = {};
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
31
|
+
__setModuleDefault(result, mod);
|
32
|
+
return result;
|
33
|
+
};
|
34
|
+
})();
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
37
|
+
};
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
39
|
+
exports.writeStylesXml = writeStylesXml;
|
40
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
41
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
42
|
+
const node_path_1 = __importDefault(require("node:path"));
|
43
|
+
const Default = __importStar(require("../default/index.js"));
|
44
|
+
const constants_js_1 = require("./constants.js");
|
45
|
+
const write_xml_js_1 = require("./write-xml.js");
|
46
|
+
/**
|
47
|
+
* Writes the `styles.xml` part to a file at the given destination using a write stream.
|
48
|
+
* Falls back to default font/fill/border collections when none are provided.
|
49
|
+
*
|
50
|
+
* @param destination - Absolute or relative file path to write
|
51
|
+
* @param data - Style collections used to construct the stylesheet
|
52
|
+
* @param data.borders - Array of border XmlNodes
|
53
|
+
* @param data.cellXfs - Array of cell format records
|
54
|
+
* @param data.fills - Array of fill XmlNodes
|
55
|
+
* @param data.fonts - Array of font XmlNodes
|
56
|
+
* @param data.numFmts - Array of custom number formats (formatCode and id)
|
57
|
+
* @returns Promise that resolves when the write stream finishes
|
58
|
+
*/
|
59
|
+
async function writeStylesXml(destination, data) {
|
60
|
+
// Ensure destination folder exists
|
61
|
+
await promises_1.default.mkdir(node_path_1.default.dirname(destination), { recursive: true });
|
62
|
+
const stream = node_fs_1.default.createWriteStream(destination, { encoding: "utf-8" });
|
63
|
+
try {
|
64
|
+
const { borders = [], cellXfs = [], fills = [], fonts = [], numFmts = [], } = data || {};
|
65
|
+
const children = [];
|
66
|
+
if (numFmts.length) {
|
67
|
+
children.push({
|
68
|
+
attrs: { count: String(numFmts.length) },
|
69
|
+
children: numFmts.map(nf => ({
|
70
|
+
attrs: {
|
71
|
+
formatCode: nf.formatCode,
|
72
|
+
numFmtId: String(nf.id),
|
73
|
+
},
|
74
|
+
tag: "numFmt",
|
75
|
+
})),
|
76
|
+
tag: "numFmts",
|
77
|
+
});
|
78
|
+
}
|
79
|
+
if (fonts.length) {
|
80
|
+
children.push({
|
81
|
+
attrs: { count: String(fonts.length) },
|
82
|
+
children: fonts,
|
83
|
+
tag: "fonts",
|
84
|
+
});
|
85
|
+
}
|
86
|
+
else {
|
87
|
+
children.push({
|
88
|
+
attrs: { count: "1" },
|
89
|
+
children: [Default.font()],
|
90
|
+
tag: "fonts",
|
91
|
+
});
|
92
|
+
}
|
93
|
+
if (fills.length) {
|
94
|
+
children.push({
|
95
|
+
attrs: { count: String(fills.length) },
|
96
|
+
children: fills,
|
97
|
+
tag: "fills",
|
98
|
+
});
|
99
|
+
}
|
100
|
+
else {
|
101
|
+
children.push({
|
102
|
+
attrs: { count: "1" },
|
103
|
+
children: [Default.fill()],
|
104
|
+
tag: "fills",
|
105
|
+
});
|
106
|
+
}
|
107
|
+
if (borders.length) {
|
108
|
+
children.push({
|
109
|
+
attrs: { count: String(borders.length) },
|
110
|
+
children: borders,
|
111
|
+
tag: "borders",
|
112
|
+
});
|
113
|
+
}
|
114
|
+
else {
|
115
|
+
children.push({
|
116
|
+
attrs: { count: "1" },
|
117
|
+
children: [Default.border()],
|
118
|
+
tag: "borders",
|
119
|
+
});
|
120
|
+
}
|
121
|
+
children.push({
|
122
|
+
attrs: { count: "1" },
|
123
|
+
children: [{
|
124
|
+
attrs: { borderId: "0", fillId: "0", fontId: "0", numFmtId: "0" },
|
125
|
+
tag: "xf",
|
126
|
+
}],
|
127
|
+
tag: "cellStyleXfs",
|
128
|
+
});
|
129
|
+
if (cellXfs.length) {
|
130
|
+
children.push({
|
131
|
+
attrs: { count: String(cellXfs.length) },
|
132
|
+
children: cellXfs.map((xf, i) => {
|
133
|
+
const isBaseXf = i === 0;
|
134
|
+
const hasAlignment = !!xf.alignment;
|
135
|
+
const xfChildren = [];
|
136
|
+
if (hasAlignment) {
|
137
|
+
xfChildren.push({
|
138
|
+
attrs: {
|
139
|
+
...(xf.alignment?.horizontal ? { horizontal: xf.alignment.horizontal } : {}),
|
140
|
+
...(xf.alignment?.vertical ? { vertical: xf.alignment.vertical } : {}),
|
141
|
+
...(xf.alignment?.wrapText ? { wrapText: "1" } : {}),
|
142
|
+
...(xf.alignment?.indent !== undefined ? { indent: String(xf.alignment.indent) } : {}),
|
143
|
+
},
|
144
|
+
tag: "alignment",
|
145
|
+
});
|
146
|
+
}
|
147
|
+
return {
|
148
|
+
attrs: {
|
149
|
+
...(isBaseXf
|
150
|
+
? {}
|
151
|
+
: {
|
152
|
+
applyBorder: "1",
|
153
|
+
applyFill: "1",
|
154
|
+
applyFont: "1",
|
155
|
+
applyNumberFormat: xf.numFmtId ? "1" : "0",
|
156
|
+
}),
|
157
|
+
...(hasAlignment ? { applyAlignment: "1" } : {}),
|
158
|
+
borderId: String(xf.borderId),
|
159
|
+
fillId: String(xf.fillId),
|
160
|
+
fontId: String(xf.fontId),
|
161
|
+
numFmtId: String(xf.numFmtId ?? 0),
|
162
|
+
xfId: "0",
|
163
|
+
},
|
164
|
+
children: xfChildren,
|
165
|
+
tag: "xf",
|
166
|
+
};
|
167
|
+
}),
|
168
|
+
tag: "cellXfs",
|
169
|
+
});
|
170
|
+
}
|
171
|
+
else {
|
172
|
+
// Base style without fill
|
173
|
+
children.push({
|
174
|
+
attrs: { count: "1" },
|
175
|
+
children: [
|
176
|
+
{ attrs: { borderId: "0", fillId: "0", fontId: "0", numFmtId: "0", xfId: "0" }, tag: "xf" },
|
177
|
+
],
|
178
|
+
tag: "cellXfs",
|
179
|
+
});
|
180
|
+
}
|
181
|
+
// XML declaration
|
182
|
+
stream.write(constants_js_1.XML_DECLARATION + "\n");
|
183
|
+
await (0, write_xml_js_1.writeXml)({
|
184
|
+
attrs: { xmlns: constants_js_1.XML_NAMESPACES.SPREADSHEET_ML },
|
185
|
+
children,
|
186
|
+
tag: "styleSheet",
|
187
|
+
}, stream);
|
188
|
+
}
|
189
|
+
finally {
|
190
|
+
stream.end();
|
191
|
+
}
|
192
|
+
return new Promise((resolve, reject) => {
|
193
|
+
stream.on("error", reject);
|
194
|
+
stream.on("finish", resolve);
|
195
|
+
});
|
196
|
+
}
|
@@ -0,0 +1,209 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.writeWorksheetXml = writeWorksheetXml;
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
8
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
10
|
+
const node_readline_1 = __importDefault(require("node:readline"));
|
11
|
+
const constants_js_1 = require("./constants.js");
|
12
|
+
const column_index_to_letter_js_1 = require("../../template/utils/column-index-to-letter.js");
|
13
|
+
const column_letter_to_index_js_1 = require("../../template/utils/column-letter-to-index.js");
|
14
|
+
/**
|
15
|
+
* Writes a worksheet XML file to the given destination using a streaming approach.
|
16
|
+
*
|
17
|
+
* - Streams rows and cells to minimize memory usage
|
18
|
+
* - Tracks the worksheet dimension (min/max rows/cols) while streaming
|
19
|
+
* - Updates the <dimension> ref at the end by rewriting the file in a buffered pass
|
20
|
+
*
|
21
|
+
* @param destination - Absolute or relative file path for the worksheet XML
|
22
|
+
* @param rows - Map of rowIndex -> RowData with cells
|
23
|
+
* @param merges - Merge ranges to append after <sheetData>
|
24
|
+
* @returns Promise that resolves when the file is fully written and dimension updated
|
25
|
+
*/
|
26
|
+
async function writeWorksheetXml(destination, rows = new Map(), merges = []) {
|
27
|
+
// ensure folder exists
|
28
|
+
await promises_1.default.mkdir(node_path_1.default.dirname(destination), { recursive: true });
|
29
|
+
const stream = node_fs_1.default.createWriteStream(destination, { encoding: "utf-8" });
|
30
|
+
// Track dimension incrementally while streaming
|
31
|
+
let minRow = Number.POSITIVE_INFINITY;
|
32
|
+
let maxRow = 0;
|
33
|
+
let minCol = Number.POSITIVE_INFINITY;
|
34
|
+
let maxCol = 0;
|
35
|
+
try {
|
36
|
+
// header
|
37
|
+
stream.write(constants_js_1.XML_DECLARATION + "\n");
|
38
|
+
stream.write(`<worksheet xmlns="${constants_js_1.XML_NAMESPACES.SPREADSHEET_ML}" xmlns:r="${constants_js_1.XML_NAMESPACES.OFFICE_DOCUMENT}">\n`);
|
39
|
+
// dimension
|
40
|
+
stream.write(" <dimension ref=\"A1:A1\"/>\n");
|
41
|
+
// sheetViews
|
42
|
+
stream.write(" <sheetViews>\n");
|
43
|
+
stream.write(" <sheetView workbookViewId=\"0\"/>\n");
|
44
|
+
stream.write(" </sheetViews>\n");
|
45
|
+
// sheetFormatPr
|
46
|
+
stream.write(" <sheetFormatPr defaultRowHeight=\"15\"/>\n");
|
47
|
+
// sheetData start
|
48
|
+
stream.write(" <sheetData>\n");
|
49
|
+
// rows (stream, without accumulation)
|
50
|
+
const typeSetSkipping = new Set(["n"]);
|
51
|
+
let processedRows = 0;
|
52
|
+
for (const [rowNumber, row] of rows) {
|
53
|
+
if (row.cells.size > 0) {
|
54
|
+
if (rowNumber < minRow)
|
55
|
+
minRow = rowNumber;
|
56
|
+
if (rowNumber > maxRow)
|
57
|
+
maxRow = rowNumber;
|
58
|
+
}
|
59
|
+
// Build the row string
|
60
|
+
const rowStart = ` <row r="${rowNumber}">\n`;
|
61
|
+
const rowEnd = " </row>\n";
|
62
|
+
// write to stream with backpressure control
|
63
|
+
if (!stream.write(rowStart)) {
|
64
|
+
await new Promise(resolve => stream.once("drain", () => resolve()));
|
65
|
+
}
|
66
|
+
// if you need to stream cells, you can do so as well:
|
67
|
+
for (const [colNumber, cellData] of row.cells) {
|
68
|
+
const colIndex = (0, column_letter_to_index_js_1.columnLetterToIndex)(colNumber) - 1;
|
69
|
+
if (colIndex < minCol)
|
70
|
+
minCol = colIndex;
|
71
|
+
if (colIndex > maxCol)
|
72
|
+
maxCol = colIndex;
|
73
|
+
const attrT = cellData.type && typeSetSkipping.has(cellData.type)
|
74
|
+
? ""
|
75
|
+
: ` t="${cellData.type}"`;
|
76
|
+
const attrS = cellData.style?.index
|
77
|
+
? ` s="${cellData.style?.index}"`
|
78
|
+
: "";
|
79
|
+
let cellXml = "";
|
80
|
+
if (cellData.isFormula) {
|
81
|
+
cellXml = ` <c r="${colNumber}${rowNumber}"${attrS}${attrT}><f>${cellData.value}</f></c>\n`;
|
82
|
+
}
|
83
|
+
else {
|
84
|
+
switch (cellData.type) {
|
85
|
+
case "b": {
|
86
|
+
cellXml = ` <c r="${colNumber}${rowNumber}"${attrS}${attrT}><v>${cellData.value ? "1" : "0"}</v></c>\n`;
|
87
|
+
break;
|
88
|
+
}
|
89
|
+
case "inlineStr": {
|
90
|
+
cellXml = ` <c r="${colNumber}${rowNumber}"${attrS}${attrT}><is><t>${cellData.value}</t></is></c>\n`;
|
91
|
+
break;
|
92
|
+
}
|
93
|
+
default: {
|
94
|
+
cellXml = ` <c r="${colNumber}${rowNumber}"${attrS}${attrT}><v>${cellData.value}</v></c>\n`;
|
95
|
+
break;
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}
|
99
|
+
stream.write(cellXml);
|
100
|
+
// if (!stream.write(cellXml)) {
|
101
|
+
// await new Promise<void>(resolve => stream.once("drain", () => resolve()));
|
102
|
+
// }
|
103
|
+
}
|
104
|
+
if (!stream.write(rowEnd)) {
|
105
|
+
await new Promise(resolve => stream.once("drain", () => resolve()));
|
106
|
+
}
|
107
|
+
// Unload the event loop every 100 rows
|
108
|
+
processedRows++;
|
109
|
+
if (processedRows % 100 === 0) {
|
110
|
+
await new Promise(resolve => setImmediate(resolve));
|
111
|
+
}
|
112
|
+
// Unload the event loop every 100 rows
|
113
|
+
// rows.delete(rowNumber);
|
114
|
+
}
|
115
|
+
// sheetData end
|
116
|
+
stream.write(" </sheetData>\n");
|
117
|
+
// mergeCells
|
118
|
+
if (merges.length > 0) {
|
119
|
+
stream.write(` <mergeCells count="${merges.length}">\n`);
|
120
|
+
for (const merge of merges) {
|
121
|
+
if (merge.startCol < minCol)
|
122
|
+
minCol = merge.startCol;
|
123
|
+
if (merge.endCol > maxCol)
|
124
|
+
maxCol = merge.endCol;
|
125
|
+
if (merge.startRow < minRow)
|
126
|
+
minRow = merge.startRow;
|
127
|
+
if (merge.endRow > maxRow)
|
128
|
+
maxRow = merge.endRow;
|
129
|
+
const ref = `${(0, column_index_to_letter_js_1.columnIndexToLetter)(merge.startCol)}${merge.startRow}:${(0, column_index_to_letter_js_1.columnIndexToLetter)(merge.endCol)}${merge.endRow}`;
|
130
|
+
stream.write(` <mergeCell ref="${ref}"/>\n`);
|
131
|
+
}
|
132
|
+
stream.write(" </mergeCells>\n");
|
133
|
+
}
|
134
|
+
// close worksheet
|
135
|
+
stream.write("</worksheet>\n");
|
136
|
+
}
|
137
|
+
finally {
|
138
|
+
stream.end();
|
139
|
+
}
|
140
|
+
let finalDimensionRef = "A1:A1";
|
141
|
+
if (Number.isFinite(minCol) && Number.isFinite(minRow) && maxCol >= 0 && maxRow > 0) {
|
142
|
+
finalDimensionRef = `${(0, column_index_to_letter_js_1.columnIndexToLetter)(minCol)}${minRow}:${(0, column_index_to_letter_js_1.columnIndexToLetter)(maxCol)}${maxRow}`;
|
143
|
+
}
|
144
|
+
await new Promise((resolve, reject) => {
|
145
|
+
stream.on("error", reject);
|
146
|
+
stream.on("finish", resolve);
|
147
|
+
});
|
148
|
+
await updateWorksheetDimensionInFile(destination, finalDimensionRef);
|
149
|
+
return;
|
150
|
+
}
|
151
|
+
// async function updateWorksheetDimensionInFile(destination: string, dimensionRef: string): Promise<void> {
|
152
|
+
// const tempPath = `${destination}.tmp`;
|
153
|
+
// const readStream = fs.createReadStream(destination, { encoding: "utf-8" });
|
154
|
+
// const rl = readline.createInterface({ crlfDelay: Infinity, input: readStream });
|
155
|
+
// const writeStream = fs.createWriteStream(tempPath, { encoding: "utf-8" });
|
156
|
+
// let updated = false;
|
157
|
+
// const rlClosed = new Promise<void>(resolve => rl.once("close", resolve));
|
158
|
+
// for await (const line of rl) {
|
159
|
+
// let outLine = line;
|
160
|
+
// if (!updated && line.includes("<dimension")) {
|
161
|
+
// outLine = line.replace(/(<dimension[^>]*ref=")[^"]*("[^>]*\/>)/, `$1${dimensionRef}$2`);
|
162
|
+
// updated = true;
|
163
|
+
// }
|
164
|
+
// if (!writeStream.write(outLine + "\n")) {
|
165
|
+
// await new Promise<void>(resolve => writeStream.once("drain", resolve));
|
166
|
+
// }
|
167
|
+
// }
|
168
|
+
// await rlClosed;
|
169
|
+
// writeStream.end();
|
170
|
+
// await new Promise<void>(resolve => writeStream.once("finish", resolve));
|
171
|
+
// await fsPromises.rename(tempPath, destination);
|
172
|
+
// }
|
173
|
+
/**
|
174
|
+
* Updates the <dimension> ref attribute in an existing worksheet XML file.
|
175
|
+
* Performs a buffered line-by-line rewrite to a temporary file, then renames it in place.
|
176
|
+
*
|
177
|
+
* @param destination - Path to the worksheet XML file to update
|
178
|
+
* @param dimensionRef - Final dimension reference, e.g., "A1:C25"
|
179
|
+
*/
|
180
|
+
async function updateWorksheetDimensionInFile(destination, dimensionRef) {
|
181
|
+
const tempPath = `${destination}.tmp`;
|
182
|
+
const readStream = node_fs_1.default.createReadStream(destination, { encoding: "utf-8" });
|
183
|
+
const rl = node_readline_1.default.createInterface({ crlfDelay: Infinity, input: readStream });
|
184
|
+
const writeStream = node_fs_1.default.createWriteStream(tempPath, { encoding: "utf-8" });
|
185
|
+
let updated = false;
|
186
|
+
let buffer = "";
|
187
|
+
const BUFFER_SIZE = 64 * 1024; // 64 KB
|
188
|
+
for await (const line of rl) {
|
189
|
+
let outLine = line;
|
190
|
+
if (!updated && line.includes("<dimension")) {
|
191
|
+
outLine = line.replace(/(<dimension[^>]*ref=")[^"]*("[^>]*\/>)/, `$1${dimensionRef}$2`);
|
192
|
+
updated = true;
|
193
|
+
}
|
194
|
+
buffer += outLine + "\n";
|
195
|
+
if (buffer.length >= BUFFER_SIZE) {
|
196
|
+
if (!writeStream.write(buffer)) {
|
197
|
+
await new Promise(resolve => writeStream.once("drain", resolve));
|
198
|
+
}
|
199
|
+
buffer = "";
|
200
|
+
}
|
201
|
+
}
|
202
|
+
// Write remaining buffer
|
203
|
+
if (buffer)
|
204
|
+
writeStream.write(buffer);
|
205
|
+
// Close streams
|
206
|
+
await new Promise(resolve => writeStream.end(resolve));
|
207
|
+
// Replace original file
|
208
|
+
await promises_1.default.rename(tempPath, destination);
|
209
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.writeXml = writeXml;
|
4
|
+
async function writeXml(node, stream, level = 0, chunkSize = 100) {
|
5
|
+
const { attrs = {}, children = [], tag } = node;
|
6
|
+
const attrStr = Object.entries(attrs)
|
7
|
+
.filter(([, v]) => v !== undefined && v !== null)
|
8
|
+
.map(([k, v]) => ` ${k}="${v}"`)
|
9
|
+
.join("");
|
10
|
+
const gap = " ".repeat(level);
|
11
|
+
// No children → self-closing tag
|
12
|
+
if (!children.length) {
|
13
|
+
stream.write(`${gap}<${tag}${attrStr}/>\n`);
|
14
|
+
return;
|
15
|
+
}
|
16
|
+
// Single text child → inline formatting
|
17
|
+
if (children.length === 1 && typeof children[0] === "string" && !children[0].includes("<")) {
|
18
|
+
stream.write(`${gap}<${tag}${attrStr}>${children[0]}</${tag}>\n`);
|
19
|
+
return;
|
20
|
+
}
|
21
|
+
// Has children → recursive streaming
|
22
|
+
stream.write(`${gap}<${tag}${attrStr}>\n`);
|
23
|
+
let processed = 0;
|
24
|
+
for (const c of children) {
|
25
|
+
if (typeof c === "string") {
|
26
|
+
stream.write(`${" ".repeat(level + 1)}${c}\n`);
|
27
|
+
}
|
28
|
+
else {
|
29
|
+
await writeXml(c, stream, level + 1, chunkSize);
|
30
|
+
}
|
31
|
+
processed++;
|
32
|
+
if (processed % chunkSize === 0) {
|
33
|
+
await new Promise(resolve => setImmediate(resolve));
|
34
|
+
}
|
35
|
+
}
|
36
|
+
stream.write(`${gap}</${tag}>\n`);
|
37
|
+
}
|