xls-codec 4.14.0 → 4.15.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 +37 -19
- package/dist/biff/record-writer.cjs +18 -0
- package/dist/biff/record-writer.d.cts +7 -1
- package/dist/biff/record-writer.d.ts +7 -1
- package/dist/biff/record-writer.js +18 -1
- package/dist/container.cjs +9 -1
- package/dist/container.d.cts +2 -0
- package/dist/container.d.ts +2 -0
- package/dist/container.js +9 -1
- package/dist/content.cjs +6 -5
- package/dist/content.js +6 -5
- package/dist/drawing/escher-constants.cjs +6 -0
- package/dist/drawing/escher-constants.d.cts +5 -1
- package/dist/drawing/escher-constants.d.ts +5 -1
- package/dist/drawing/escher-constants.js +5 -1
- package/dist/drawing/escher-writer.cjs +107 -0
- package/dist/drawing/escher-writer.d.cts +32 -0
- package/dist/drawing/escher-writer.d.ts +32 -0
- package/dist/drawing/escher-writer.js +105 -0
- package/dist/drawing/md4.cjs +146 -0
- package/dist/drawing/md4.d.cts +7 -0
- package/dist/drawing/md4.d.ts +7 -0
- package/dist/drawing/md4.js +145 -0
- package/dist/drawing-writer-Blm_NUSZ.d.cts +19 -0
- package/dist/drawing-writer-Blm_NUSZ.d.ts +19 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/workbook/comments.cjs +26 -0
- package/dist/workbook/comments.d.cts +7 -1
- package/dist/workbook/comments.d.ts +7 -1
- package/dist/workbook/comments.js +26 -1
- package/dist/workbook/conditional-format-write.cjs +307 -18
- package/dist/workbook/conditional-format-write.js +307 -18
- package/dist/workbook/drawing-writer.cjs +253 -0
- package/dist/workbook/drawing-writer.d.cts +2 -0
- package/dist/workbook/drawing-writer.d.ts +2 -0
- package/dist/workbook/drawing-writer.js +252 -0
- package/dist/workbook/drawing.cjs +24 -3
- package/dist/workbook/drawing.d.cts +2 -0
- package/dist/workbook/drawing.d.ts +2 -0
- package/dist/workbook/drawing.js +25 -4
- package/dist/workbook/embedded-object.cjs +43 -0
- package/dist/workbook/embedded-object.d.cts +8 -0
- package/dist/workbook/embedded-object.d.ts +8 -0
- package/dist/workbook/embedded-object.js +41 -0
- package/dist/workbook/globals-writer.cjs +1 -0
- package/dist/workbook/globals-writer.d.cts +2 -0
- package/dist/workbook/globals-writer.d.ts +2 -0
- package/dist/workbook/globals-writer.js +2 -1
- package/dist/workbook/sheet-writer.cjs +4 -3
- package/dist/workbook/sheet-writer.d.cts +3 -2
- package/dist/workbook/sheet-writer.d.ts +3 -2
- package/dist/workbook/sheet-writer.js +4 -3
- package/dist/write.cjs +17 -7
- package/dist/write.js +17 -7
- package/package.json +1 -1
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import "../biff/record-types.js";
|
|
2
|
+
import { DEFAULT_COLUMN_WIDTH_CHARS, columnWidthToPoints } from "../units.js";
|
|
3
|
+
import { RecordBuilder } from "../biff/builder.js";
|
|
4
|
+
import { BiffWriteError } from "../biff/write-errors.js";
|
|
5
|
+
import { writeRecord, writeRecordChain } from "../biff/record-writer.js";
|
|
6
|
+
import { writeXLUnicodeStringNoCch } from "../biff/string-writer.js";
|
|
7
|
+
import { writeEmbeddedObjectPackage } from "./embedded-object.js";
|
|
8
|
+
import { writeDrawingGroupBytes, writeSheetDrawingBytes } from "../drawing/escher-writer.js";
|
|
9
|
+
//#region src/workbook/drawing-writer.ts
|
|
10
|
+
/** The sheet-grid geometry an anchor resolves against and inverts into, the write-side mirror of workbook/drawing.ts's own SheetGridGeometry: declared column widths/row heights with the same Excel "Normal" defaults beneath, so a shape written from a given placement reads back at the identical placement. Derived from the same constants (units.ts) the reader's own geometry uses, so the two cannot disagree about what an undeclared cell sizes. */
|
|
11
|
+
var WriterGridGeometry = class {
|
|
12
|
+
columnWidths = /* @__PURE__ */ new Map();
|
|
13
|
+
rowHeights = /* @__PURE__ */ new Map();
|
|
14
|
+
defaultColumnWidthPt = columnWidthToPoints(DEFAULT_COLUMN_WIDTH_CHARS * 256);
|
|
15
|
+
constructor(sheet) {
|
|
16
|
+
for (const column of sheet.columns) if (column.widthPt !== void 0) this.columnWidths.set(column.index, column.widthPt);
|
|
17
|
+
for (const row of sheet.rows) if (row.heightPt !== void 0) this.rowHeights.set(row.index, row.heightPt);
|
|
18
|
+
}
|
|
19
|
+
columnWidthPt(index) {
|
|
20
|
+
return this.columnWidths.get(index) ?? this.defaultColumnWidthPt;
|
|
21
|
+
}
|
|
22
|
+
rowHeightPt(index) {
|
|
23
|
+
return this.rowHeights.get(index) ?? 15;
|
|
24
|
+
}
|
|
25
|
+
/** The absolute x of a column's own left edge -- the cumulative width of every column before it, the identical accumulation the reader's own geometry walks back down. */
|
|
26
|
+
xPt(column) {
|
|
27
|
+
let x = 0;
|
|
28
|
+
for (let index = 0; index < column; index += 1) x += this.columnWidthPt(index);
|
|
29
|
+
return x;
|
|
30
|
+
}
|
|
31
|
+
yPt(row) {
|
|
32
|
+
let y = 0;
|
|
33
|
+
for (let index = 0; index < row; index += 1) y += this.rowHeightPt(index);
|
|
34
|
+
return y;
|
|
35
|
+
}
|
|
36
|
+
/** Locates an absolute x as a column plus a 1/1024ths-of-that-column fraction, the pair OfficeArtClientAnchorSheet's own left/right corners state. A point beyond the grid's own last column clamps to that column's far edge: the grid has no column 256 to name, and a shape whose extent runs that far past the grid loses only the overflow, where refusing the workbook would lose the cells too -- the same trade a print range past the grid already draws (print-names.ts's clampToGrid). */
|
|
37
|
+
locateX(x) {
|
|
38
|
+
let left = 0;
|
|
39
|
+
for (let column = 0; column < 255; column += 1) {
|
|
40
|
+
const width = this.columnWidthPt(column);
|
|
41
|
+
if (x < left + width) return {
|
|
42
|
+
column,
|
|
43
|
+
fraction: Math.min(1023, Math.round((x - left) / width * 1024))
|
|
44
|
+
};
|
|
45
|
+
left += width;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
column: 255,
|
|
49
|
+
fraction: 1023
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** The row-axis counterpart: a row plus a 1/256ths-of-that-row fraction, clamped to the grid's own last row. */
|
|
53
|
+
locateY(y) {
|
|
54
|
+
let top = 0;
|
|
55
|
+
for (let row = 0; row < 65535; row += 1) {
|
|
56
|
+
const height = this.rowHeightPt(row);
|
|
57
|
+
if (y < top + height) return {
|
|
58
|
+
row,
|
|
59
|
+
fraction: Math.min(255, Math.round((y - top) / height * 256))
|
|
60
|
+
};
|
|
61
|
+
top += height;
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
row: 65535,
|
|
65
|
+
fraction: 255
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
function placementOfImage(image, geometry) {
|
|
70
|
+
if (image.anchorRow > 65535 || image.anchorColumn > 255) throw new BiffWriteError(`a sheet image anchored at row ${image.anchorRow}, column ${image.anchorColumn} is outside BIFF8's own grid (rows 0-65535, columns 0-255); a .xls workbook cannot address the cell it names`);
|
|
71
|
+
return {
|
|
72
|
+
startXPt: geometry.xPt(image.anchorColumn) + image.offsetXPt,
|
|
73
|
+
startYPt: geometry.yPt(image.anchorRow) + image.offsetYPt,
|
|
74
|
+
widthPt: image.widthPt,
|
|
75
|
+
heightPt: image.heightPt
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function placementOfEmbedded(embedded, geometry) {
|
|
79
|
+
return {
|
|
80
|
+
startXPt: embedded.anchorColumn !== void 0 && embedded.offsetXPt !== void 0 ? geometry.xPt(embedded.anchorColumn) + embedded.offsetXPt : embedded.frame.xPt,
|
|
81
|
+
startYPt: embedded.anchorRow !== void 0 && embedded.offsetYPt !== void 0 ? geometry.yPt(embedded.anchorRow) + embedded.offsetYPt : embedded.frame.yPt,
|
|
82
|
+
widthPt: embedded.frame.widthPt,
|
|
83
|
+
heightPt: embedded.frame.heightPt
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/** Inverts a placement into the OfficeArtClientAnchorSheet corner pair the reader's own resolveAnchorPlacement turns back into that placement: each corner resolved to its containing cell and a 1/1024ths (columns) or 1/256ths (rows) fraction within it. */
|
|
87
|
+
function anchorOf(placement, geometry) {
|
|
88
|
+
const start = geometry.locateX(placement.startXPt);
|
|
89
|
+
const end = geometry.locateX(placement.startXPt + placement.widthPt);
|
|
90
|
+
const top = geometry.locateY(placement.startYPt);
|
|
91
|
+
const bottom = geometry.locateY(placement.startYPt + placement.heightPt);
|
|
92
|
+
return {
|
|
93
|
+
colL: start.column,
|
|
94
|
+
dxL: start.fraction,
|
|
95
|
+
rwT: top.row,
|
|
96
|
+
dyT: top.fraction,
|
|
97
|
+
colR: end.column,
|
|
98
|
+
dxR: end.fraction,
|
|
99
|
+
rwB: bottom.row,
|
|
100
|
+
dyB: bottom.fraction
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/** [MS-XLS] 2.5.213's own ot table: the Picture type both a plain image and an embedded OLE object carry -- an OLE object IS hosted through the picture machinery (its FtPictFmla naming the Embedding Storage its data lives in), which is exactly how the Embedding Storage page itself states the pairing ("cmo.ot equal to 8, pictFlags.fPrstm equal to 0, and pictFlags.fDde equal to 0"). */
|
|
104
|
+
const OBJECT_TYPE_PICTURE = 8;
|
|
105
|
+
/** FtCmo ([MS-XLS] 2.5.92, 22 bytes): ft 0x15, cb 0x12, the object type and id, then grbit and three unused dwords all written zero -- the identical shape comment-writer.ts writes for a Note, restated here with the object type as a parameter rather than shared across the two direction modules. */
|
|
106
|
+
function writeFtCmo(ot, id) {
|
|
107
|
+
return new RecordBuilder().u16(21).u16(18).u16(ot).u16(id).u16(0).u32(0).u32(0).u32(0).build();
|
|
108
|
+
}
|
|
109
|
+
/** FtCf ([MS-XLS] 2.5.142, https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/fc5bb3ce-8e35-4393-b22f-9cf54062a3a4): the clipboard format of the picture this object shows. 0xFFFF names "an unspecified format that is neither an enhanced metafile nor a bitmap" -- honest for a shape whose visible rendering is the blip the Escher layer itself carries and for an OLE object this writer has no preview metafile for. */
|
|
110
|
+
function writeFtCf() {
|
|
111
|
+
return new RecordBuilder().u16(7).u16(2).u16(65535).build();
|
|
112
|
+
}
|
|
113
|
+
/** FtPioGrbit ([MS-XLS] 2.5.151, https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/8eee0b3d-9d27-4294-85fc-a66ae8a361c9): a plain picture states fAutoPict (aspect preserved across views); an OLE embedding states no bits at all -- fPrstm and fDde stay clear, the pair the Embedding Storage page requires for storage-based object data. */
|
|
114
|
+
function writeFtPioGrbit(autoPict) {
|
|
115
|
+
return new RecordBuilder().u16(8).u16(2).u16(autoPict ? 1 : 0).build();
|
|
116
|
+
}
|
|
117
|
+
/** The PtgTbl token byte an embedded object's ObjectParsedFormula carries ([MS-XLS] 2.5.198.92: ptg 0x02, class none) -- the spelling that tells a reader this picture's data lives in an Embedding Storage rather than a linked range. */
|
|
118
|
+
const PTG_TBL = 2;
|
|
119
|
+
/** The class name stated in an embedding's PictFmlaEmbedInfo: "Package" is what a genuine OLE Package embed carries, so a real OLE-aware consumer that cannot decode this package's own JSON payload still sees a recognisable, accurate class rather than an invented one -- the identical choice rtf-codec's own ObjectHeader makes for the same payload shape. */
|
|
120
|
+
const EMBED_CLASS_NAME = "Package";
|
|
121
|
+
/** FtPictFmla ([MS-XLS] 2.5.150, https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/00f89d32-67b0-408e-9eaf-f4fecbddb089) for an embedded OLE object: the ObjFmla (cbFmla counting the ObjectParsedFormula, the PictFmlaEmbedInfo, and the padding -- even, per [MS-XLS] 2.5.187's own cbFmla rule), then lPosInCtlStm, the storage id the Embedding Storage's own MBD name is the eight-hex-digit spelling of. The ObjectParsedFormula is the one shape [MS-XLS] pins for an embedding: cce 5, rgce one PtgTbl followed by four undefined bytes. */
|
|
122
|
+
function writeFtPictFmla(storageId) {
|
|
123
|
+
const formula = new RecordBuilder().u16(5).u32(0).u8(PTG_TBL).bytes(/* @__PURE__ */ new Uint8Array(4)).build();
|
|
124
|
+
const className = writeXLUnicodeStringNoCch(EMBED_CLASS_NAME);
|
|
125
|
+
const embedInfo = new RecordBuilder().u8(3).u8(className.length - 1).u8(0).bytes(className).build();
|
|
126
|
+
const fmlaBytes = new RecordBuilder().bytes(formula).bytes(embedInfo).build();
|
|
127
|
+
const data = new RecordBuilder().u16(fmlaBytes.length).bytes(fmlaBytes).u32(storageId).build();
|
|
128
|
+
return new RecordBuilder().u16(9).u16(data.length).bytes(data).build();
|
|
129
|
+
}
|
|
130
|
+
/** The trailing four reserved bytes every Obj not naming a list-box/dropdown object carries ([MS-XLS] 2.4.181's own reserved field: MUST be 0) -- the ftEnd marker a real sub-record walk terminates on. */
|
|
131
|
+
const OBJ_RESERVED_END = /* @__PURE__ */ new Uint8Array(4);
|
|
132
|
+
/** One picture shape's Obj record: FtCmo (ot Picture), FtCf, FtPioGrbit, and the trailing reserved field. No FtPictFmla -- the image's bytes live in the workbook's Blip Store, which the shape's own pib property names, leaving the Obj record itself nothing to locate. */
|
|
133
|
+
function writePictureObjRecord(objectId) {
|
|
134
|
+
return writeRecord(93, new RecordBuilder().bytes(writeFtCmo(OBJECT_TYPE_PICTURE, objectId)).bytes(writeFtCf()).bytes(writeFtPioGrbit(true)).bytes(OBJ_RESERVED_END).build());
|
|
135
|
+
}
|
|
136
|
+
/** One embedded OLE object's Obj record: FtCmo (ot Picture), FtCf, FtPioGrbit (no bits -- storage-based, per the Embedding Storage page's own fPrstm/fDde requirement), the FtPictFmla naming the storage, and the trailing reserved field. */
|
|
137
|
+
function writeEmbeddedObjRecord(objectId, storageId) {
|
|
138
|
+
return writeRecord(93, new RecordBuilder().bytes(writeFtCmo(OBJECT_TYPE_PICTURE, objectId)).bytes(writeFtCf()).bytes(writeFtPioGrbit(false)).bytes(writeFtPictFmla(storageId)).bytes(OBJ_RESERVED_END).build());
|
|
139
|
+
}
|
|
140
|
+
/** Base64's own character set, decoded by hand rather than through atob's DOM-string round trip -- mirroring drawing/blips.ts's own hand-written encoder, which exists for the identical reason: byte-exact, allocation-predictable, and identical in Node and a Workers isolate. */
|
|
141
|
+
function bytesFromBase64(base64) {
|
|
142
|
+
const values = (/* @__PURE__ */ new Int8Array(256)).fill(-1);
|
|
143
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("").forEach((char, index) => {
|
|
144
|
+
values[char.charCodeAt(0)] = index;
|
|
145
|
+
});
|
|
146
|
+
const padding = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0;
|
|
147
|
+
const out = new Uint8Array(base64.length / 4 * 3 - padding);
|
|
148
|
+
let buffer = 0;
|
|
149
|
+
let bits = 0;
|
|
150
|
+
let outIndex = 0;
|
|
151
|
+
for (const char of base64) {
|
|
152
|
+
const value = values[char.charCodeAt(0)];
|
|
153
|
+
if (value === void 0 || value < 0) continue;
|
|
154
|
+
buffer = buffer << 6 | value;
|
|
155
|
+
bits += 6;
|
|
156
|
+
if (bits >= 8) {
|
|
157
|
+
bits -= 8;
|
|
158
|
+
out[outIndex] = buffer >> bits & 255;
|
|
159
|
+
outIndex += 1;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
function buildDrawingWritePlan(sheets) {
|
|
165
|
+
const blips = [];
|
|
166
|
+
const blipIndexByBase64 = /* @__PURE__ */ new Map();
|
|
167
|
+
const resolveBlip = (image) => {
|
|
168
|
+
if (image.format !== "png" && image.format !== "jpeg") throw new BiffWriteError(`xls-codec cannot write a sheet image of format "${image.format}": [MS-ODRAW]'s own MSOBLIPTYPE enumeration has no member for it, so no Blip Store entry can carry it`);
|
|
169
|
+
const existing = blipIndexByBase64.get(image.base64);
|
|
170
|
+
if (existing !== void 0) {
|
|
171
|
+
const blip = blips[existing - 1];
|
|
172
|
+
if (blip === void 0) throw new BiffWriteError("internal error: a blip index resolved that the workbook-wide image scan never assigned");
|
|
173
|
+
blip.referenceCount += 1;
|
|
174
|
+
return existing;
|
|
175
|
+
}
|
|
176
|
+
const index = blips.length + 1;
|
|
177
|
+
blipIndexByBase64.set(image.base64, index);
|
|
178
|
+
blips.push({
|
|
179
|
+
format: image.format,
|
|
180
|
+
fileBytes: bytesFromBase64(image.base64),
|
|
181
|
+
referenceCount: 1
|
|
182
|
+
});
|
|
183
|
+
return index;
|
|
184
|
+
};
|
|
185
|
+
let nextStorageId = 1;
|
|
186
|
+
const storageIdOf = () => {
|
|
187
|
+
const id = nextStorageId;
|
|
188
|
+
nextStorageId += 1;
|
|
189
|
+
return id;
|
|
190
|
+
};
|
|
191
|
+
let nextSpid = 1024;
|
|
192
|
+
let nextDrawingId = 1;
|
|
193
|
+
const drawingBlocks = [];
|
|
194
|
+
const sheetDrawings = [];
|
|
195
|
+
const embeddingStreams = [];
|
|
196
|
+
for (const sheet of sheets) {
|
|
197
|
+
const geometry = new WriterGridGeometry(sheet);
|
|
198
|
+
const entries = [];
|
|
199
|
+
const objRecords = [];
|
|
200
|
+
let nextObjectId = sheet.cells.filter((cell) => cell.comment !== void 0).length + 1;
|
|
201
|
+
for (const image of sheet.images) {
|
|
202
|
+
entries.push({
|
|
203
|
+
anchor: anchorOf(placementOfImage(image, geometry), geometry),
|
|
204
|
+
blipIndex: resolveBlip(image),
|
|
205
|
+
oleShape: false
|
|
206
|
+
});
|
|
207
|
+
objRecords.push(writePictureObjRecord(nextObjectId));
|
|
208
|
+
nextObjectId += 1;
|
|
209
|
+
}
|
|
210
|
+
for (const embedded of sheet.embeddedObjects ?? []) {
|
|
211
|
+
if (embedded.objectKind === "chart") throw new BiffWriteError("xls-codec cannot write a 'chart' embedded object: embedding one means writing a genuine BIFF8 chart substream -- the whole [MS-XLS] chart grammar its series data links drive -- which is a chart engine of its own rather than a container for the flattened series table the schema carries");
|
|
212
|
+
const storageId = storageIdOf();
|
|
213
|
+
entries.push({
|
|
214
|
+
anchor: anchorOf(placementOfEmbedded(embedded, geometry), geometry),
|
|
215
|
+
blipIndex: void 0,
|
|
216
|
+
oleShape: true
|
|
217
|
+
});
|
|
218
|
+
objRecords.push(writeEmbeddedObjRecord(nextObjectId, storageId));
|
|
219
|
+
nextObjectId += 1;
|
|
220
|
+
embeddingStreams.push({
|
|
221
|
+
path: `MBD${storageId.toString(16).toUpperCase().padStart(8, "0")}/Package`,
|
|
222
|
+
bytes: writeEmbeddedObjectPackage(embedded)
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
if (entries.length === 0) {
|
|
226
|
+
sheetDrawings.push({
|
|
227
|
+
msoDrawingRecords: [],
|
|
228
|
+
objRecords: []
|
|
229
|
+
});
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
const escherBytes = writeSheetDrawingBytes(nextDrawingId, nextSpid, entries);
|
|
233
|
+
drawingBlocks.push({
|
|
234
|
+
drawingId: nextDrawingId,
|
|
235
|
+
lastSpid: nextSpid + entries.length,
|
|
236
|
+
shapeCount: entries.length + 1
|
|
237
|
+
});
|
|
238
|
+
nextDrawingId += 1;
|
|
239
|
+
nextSpid += entries.length + 1;
|
|
240
|
+
sheetDrawings.push({
|
|
241
|
+
msoDrawingRecords: writeRecordChain(236, escherBytes),
|
|
242
|
+
objRecords
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
drawingGroupBytes: drawingBlocks.length > 0 ? writeDrawingGroupBytes(blips, drawingBlocks) : void 0,
|
|
247
|
+
sheetDrawings,
|
|
248
|
+
embeddingStreams
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
//#endregion
|
|
252
|
+
export { buildDrawingWritePlan };
|
|
@@ -6,6 +6,7 @@ const require_drawing_bytes = require("../drawing/bytes.cjs");
|
|
|
6
6
|
const require_workbook_comments = require("./comments.cjs");
|
|
7
7
|
const require_drawing_shapes = require("../drawing/shapes.cjs");
|
|
8
8
|
const require_workbook_chart = require("./chart.cjs");
|
|
9
|
+
const require_workbook_embedded_object = require("./embedded-object.cjs");
|
|
9
10
|
let document_schema_js = require("document-schema.js");
|
|
10
11
|
//#region src/workbook/drawing.ts
|
|
11
12
|
/** [MS-XLS] "FtCmo" ot enumeration, the values this reader routes on. */
|
|
@@ -69,8 +70,7 @@ function readSheetDrawing(worksheetRecords, context) {
|
|
|
69
70
|
const record = worksheetRecords[index];
|
|
70
71
|
if (record === void 0) continue;
|
|
71
72
|
if (record.type === 236) {
|
|
72
|
-
|
|
73
|
-
if (block !== void 0) drawingChunks.push(block);
|
|
73
|
+
drawingChunks.push(...record.blocks);
|
|
74
74
|
continue;
|
|
75
75
|
}
|
|
76
76
|
if (record.type === 93) {
|
|
@@ -79,7 +79,8 @@ function readSheetDrawing(worksheetRecords, context) {
|
|
|
79
79
|
objEntries.push({
|
|
80
80
|
ot,
|
|
81
81
|
offset: record.offset,
|
|
82
|
-
nextOffset
|
|
82
|
+
nextOffset,
|
|
83
|
+
group: record
|
|
83
84
|
});
|
|
84
85
|
}
|
|
85
86
|
}
|
|
@@ -98,6 +99,11 @@ function readSheetDrawing(worksheetRecords, context) {
|
|
|
98
99
|
const obj = objEntries[index];
|
|
99
100
|
if (shape === void 0 || obj === void 0 || obj.ot === OBJECT_TYPE_NOTE) continue;
|
|
100
101
|
if (obj.ot === OBJECT_TYPE_PICTURE || shape.shapeType === 75) {
|
|
102
|
+
const embedded = embeddedObjectFromObjRecord(obj.group, shape, context, geometry);
|
|
103
|
+
if (embedded !== void 0) {
|
|
104
|
+
embeddedObjects.push(embedded);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
101
107
|
const image = imageFromShape(shape, context, geometry);
|
|
102
108
|
if (image !== void 0) images.push(image);
|
|
103
109
|
continue;
|
|
@@ -115,6 +121,21 @@ function readSheetDrawing(worksheetRecords, context) {
|
|
|
115
121
|
embeddedObjects
|
|
116
122
|
};
|
|
117
123
|
}
|
|
124
|
+
/** A Picture-type Obj record whose FtPictFmla names an Embedding Storage this workbook's own outer compound file carries: resolved through readEmbeddedObjectPackage rather than the plain Blip Store path imageFromShape covers, since an OLE-embedded object's data lives in that storage's own Package stream instead of a pib reference into the workbook-wide Blip Store. Undefined for a plain picture (no FtPictFmla at all), an FtPictFmla naming a storage id this workbook's container did not report, or a storage whose Package stream is not this codec's own payload (readEmbeddedObjectPackage's own foreign-payload degrade) -- each falls through to imageFromShape instead. */
|
|
125
|
+
function embeddedObjectFromObjRecord(objGroup, shape, context, geometry) {
|
|
126
|
+
const storageId = require_workbook_comments.readObjPictFmlaStorageId(objGroup);
|
|
127
|
+
if (storageId === void 0) return;
|
|
128
|
+
const packageBytes = context.embeddingStreams.get(storageId);
|
|
129
|
+
if (packageBytes === void 0) return;
|
|
130
|
+
const placement = resolveAnchorPlacement(shape.anchor, geometry);
|
|
131
|
+
if (placement.widthPt <= 0 || placement.heightPt <= 0) return;
|
|
132
|
+
return require_workbook_embedded_object.readEmbeddedObjectPackage(packageBytes, {
|
|
133
|
+
xPt: placement.xPt,
|
|
134
|
+
yPt: placement.yPt,
|
|
135
|
+
widthPt: placement.widthPt,
|
|
136
|
+
heightPt: placement.heightPt
|
|
137
|
+
});
|
|
138
|
+
}
|
|
118
139
|
function imageFromShape(shape, context, geometry) {
|
|
119
140
|
if (shape.blipIndex === void 0) return;
|
|
120
141
|
const blip = context.blipStore.get(shape.blipIndex);
|
|
@@ -18,6 +18,8 @@ interface SheetDrawingContext {
|
|
|
18
18
|
readonly metadata: LayoutMetadata;
|
|
19
19
|
/** Every substream the workbook stream carries -- searched for the chart substream a Chart-type Obj record's own nested BOF...EOF produced (splitSubstreams reports it as its own entry, positioned by byte offset rather than nested inside the worksheet's own `records`; see biff/substreams.ts's own top comment for why). */
|
|
20
20
|
readonly allSubstreams: readonly Substream[];
|
|
21
|
+
/** Every "MBD<hex>/Package" Embedding Storage the outer compound file carries, keyed by the storage id a Picture-type Obj record's own FtPictFmla names (container.ts's own readWorkbookStreams) -- resolved here for a Picture Obj record whose data lives in an OLE embedding rather than the workbook-wide Blip Store. */
|
|
22
|
+
readonly embeddingStreams: ReadonlyMap<number, Uint8Array<ArrayBuffer>>;
|
|
21
23
|
}
|
|
22
24
|
/** Reads one worksheet's own drawing content: every MsoDrawing record's bytes concatenated into one Escher stream (drawing/shapes.ts), each of its real top-level shapes paired 1:1, in document order, with the non-Note Obj records the same substream carries. */
|
|
23
25
|
declare function readSheetDrawing(worksheetRecords: readonly RecordGroup[], context: SheetDrawingContext): SheetDrawing;
|
|
@@ -18,6 +18,8 @@ interface SheetDrawingContext {
|
|
|
18
18
|
readonly metadata: LayoutMetadata;
|
|
19
19
|
/** Every substream the workbook stream carries -- searched for the chart substream a Chart-type Obj record's own nested BOF...EOF produced (splitSubstreams reports it as its own entry, positioned by byte offset rather than nested inside the worksheet's own `records`; see biff/substreams.ts's own top comment for why). */
|
|
20
20
|
readonly allSubstreams: readonly Substream[];
|
|
21
|
+
/** Every "MBD<hex>/Package" Embedding Storage the outer compound file carries, keyed by the storage id a Picture-type Obj record's own FtPictFmla names (container.ts's own readWorkbookStreams) -- resolved here for a Picture Obj record whose data lives in an OLE embedding rather than the workbook-wide Blip Store. */
|
|
22
|
+
readonly embeddingStreams: ReadonlyMap<number, Uint8Array<ArrayBuffer>>;
|
|
21
23
|
}
|
|
22
24
|
/** Reads one worksheet's own drawing content: every MsoDrawing record's bytes concatenated into one Escher stream (drawing/shapes.ts), each of its real top-level shapes paired 1:1, in document order, with the non-Note Obj records the same substream carries. */
|
|
23
25
|
declare function readSheetDrawing(worksheetRecords: readonly RecordGroup[], context: SheetDrawingContext): SheetDrawing;
|
package/dist/workbook/drawing.js
CHANGED
|
@@ -2,9 +2,10 @@ import "../biff/record-types.js";
|
|
|
2
2
|
import { DEFAULT_COLUMN_WIDTH_CHARS, columnWidthToPoints } from "../units.js";
|
|
3
3
|
import "../drawing/escher-constants.js";
|
|
4
4
|
import { concatBytes } from "../drawing/bytes.js";
|
|
5
|
-
import { readObjTypeAndId } from "./comments.js";
|
|
5
|
+
import { readObjPictFmlaStorageId, readObjTypeAndId } from "./comments.js";
|
|
6
6
|
import { readSheetShapes } from "../drawing/shapes.js";
|
|
7
7
|
import { readChartSeries } from "./chart.js";
|
|
8
|
+
import { readEmbeddedObjectPackage } from "./embedded-object.js";
|
|
8
9
|
import { PAGE_SIZE_LETTER } from "document-schema.js";
|
|
9
10
|
//#region src/workbook/drawing.ts
|
|
10
11
|
/** [MS-XLS] "FtCmo" ot enumeration, the values this reader routes on. */
|
|
@@ -68,8 +69,7 @@ function readSheetDrawing(worksheetRecords, context) {
|
|
|
68
69
|
const record = worksheetRecords[index];
|
|
69
70
|
if (record === void 0) continue;
|
|
70
71
|
if (record.type === 236) {
|
|
71
|
-
|
|
72
|
-
if (block !== void 0) drawingChunks.push(block);
|
|
72
|
+
drawingChunks.push(...record.blocks);
|
|
73
73
|
continue;
|
|
74
74
|
}
|
|
75
75
|
if (record.type === 93) {
|
|
@@ -78,7 +78,8 @@ function readSheetDrawing(worksheetRecords, context) {
|
|
|
78
78
|
objEntries.push({
|
|
79
79
|
ot,
|
|
80
80
|
offset: record.offset,
|
|
81
|
-
nextOffset
|
|
81
|
+
nextOffset,
|
|
82
|
+
group: record
|
|
82
83
|
});
|
|
83
84
|
}
|
|
84
85
|
}
|
|
@@ -97,6 +98,11 @@ function readSheetDrawing(worksheetRecords, context) {
|
|
|
97
98
|
const obj = objEntries[index];
|
|
98
99
|
if (shape === void 0 || obj === void 0 || obj.ot === OBJECT_TYPE_NOTE) continue;
|
|
99
100
|
if (obj.ot === OBJECT_TYPE_PICTURE || shape.shapeType === 75) {
|
|
101
|
+
const embedded = embeddedObjectFromObjRecord(obj.group, shape, context, geometry);
|
|
102
|
+
if (embedded !== void 0) {
|
|
103
|
+
embeddedObjects.push(embedded);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
100
106
|
const image = imageFromShape(shape, context, geometry);
|
|
101
107
|
if (image !== void 0) images.push(image);
|
|
102
108
|
continue;
|
|
@@ -114,6 +120,21 @@ function readSheetDrawing(worksheetRecords, context) {
|
|
|
114
120
|
embeddedObjects
|
|
115
121
|
};
|
|
116
122
|
}
|
|
123
|
+
/** A Picture-type Obj record whose FtPictFmla names an Embedding Storage this workbook's own outer compound file carries: resolved through readEmbeddedObjectPackage rather than the plain Blip Store path imageFromShape covers, since an OLE-embedded object's data lives in that storage's own Package stream instead of a pib reference into the workbook-wide Blip Store. Undefined for a plain picture (no FtPictFmla at all), an FtPictFmla naming a storage id this workbook's container did not report, or a storage whose Package stream is not this codec's own payload (readEmbeddedObjectPackage's own foreign-payload degrade) -- each falls through to imageFromShape instead. */
|
|
124
|
+
function embeddedObjectFromObjRecord(objGroup, shape, context, geometry) {
|
|
125
|
+
const storageId = readObjPictFmlaStorageId(objGroup);
|
|
126
|
+
if (storageId === void 0) return;
|
|
127
|
+
const packageBytes = context.embeddingStreams.get(storageId);
|
|
128
|
+
if (packageBytes === void 0) return;
|
|
129
|
+
const placement = resolveAnchorPlacement(shape.anchor, geometry);
|
|
130
|
+
if (placement.widthPt <= 0 || placement.heightPt <= 0) return;
|
|
131
|
+
return readEmbeddedObjectPackage(packageBytes, {
|
|
132
|
+
xPt: placement.xPt,
|
|
133
|
+
yPt: placement.yPt,
|
|
134
|
+
widthPt: placement.widthPt,
|
|
135
|
+
heightPt: placement.heightPt
|
|
136
|
+
});
|
|
137
|
+
}
|
|
117
138
|
function imageFromShape(shape, context, geometry) {
|
|
118
139
|
if (shape.blipIndex === void 0) return;
|
|
119
140
|
const blip = context.blipStore.get(shape.blipIndex);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let archive_codec = require("archive-codec");
|
|
3
|
+
let document_schema_js = require("document-schema.js");
|
|
4
|
+
//#region src/workbook/embedded-object.ts
|
|
5
|
+
const PACKAGE_LABEL = "xls-codec-embedded-object.json";
|
|
6
|
+
function payloadOf(embedded) {
|
|
7
|
+
return {
|
|
8
|
+
objectKind: embedded.objectKind,
|
|
9
|
+
document: embedded.document,
|
|
10
|
+
source: embedded.source
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** The Package stream bytes for one embedded object: this package's own JSON serialisation of the object's kind, document, and residue, wrapped in the [MS-OLEDS] packaging. */
|
|
14
|
+
function writeEmbeddedObjectPackage(embedded) {
|
|
15
|
+
const fileBytes = new TextEncoder().encode(JSON.stringify(payloadOf(embedded)));
|
|
16
|
+
return (0, archive_codec.writeOlePackage)({
|
|
17
|
+
label: PACKAGE_LABEL,
|
|
18
|
+
sourcePath: "",
|
|
19
|
+
tempPath: "",
|
|
20
|
+
fileBytes
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/** The inverse of writeEmbeddedObjectPackage: recovers a ContentEmbeddedObject's kind, document, and residue when the Package stream bytes are this package's own payload, or undefined for anything else -- a real OLE object's packaged bytes included -- rather than throwing, since one unreadable embedding must not fail the whole sheet's drawing read. `frame` is the placement the caller derived from the embedding's own Escher anchor: the payload deliberately carries no placement of its own (see payloadOf above), and the full ContentEmbeddedObjectSchema validation needs a frame to accept, so the anchor-derived one is merged in before the parse -- the anchor stays the single authority for where the object sits. */
|
|
24
|
+
function readEmbeddedObjectPackage(packageBytes, frame) {
|
|
25
|
+
try {
|
|
26
|
+
const olePackage = (0, archive_codec.readOlePackage)(packageBytes);
|
|
27
|
+
if (olePackage.label !== PACKAGE_LABEL) return;
|
|
28
|
+
const text = new TextDecoder("utf-8").decode(olePackage.fileBytes);
|
|
29
|
+
const parsed = JSON.parse(text);
|
|
30
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || !("objectKind" in parsed) || !("document" in parsed)) return;
|
|
31
|
+
const result = document_schema_js.ContentEmbeddedObjectSchema.safeParse({
|
|
32
|
+
...parsed,
|
|
33
|
+
frame
|
|
34
|
+
});
|
|
35
|
+
if (!result.success) return;
|
|
36
|
+
return result.data;
|
|
37
|
+
} catch {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
exports.readEmbeddedObjectPackage = readEmbeddedObjectPackage;
|
|
43
|
+
exports.writeEmbeddedObjectPackage = writeEmbeddedObjectPackage;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ContentEmbeddedObject } from "document-schema.js";
|
|
2
|
+
//#region src/workbook/embedded-object.d.ts
|
|
3
|
+
/** The Package stream bytes for one embedded object: this package's own JSON serialisation of the object's kind, document, and residue, wrapped in the [MS-OLEDS] packaging. */
|
|
4
|
+
declare function writeEmbeddedObjectPackage(embedded: ContentEmbeddedObject): Uint8Array<ArrayBuffer>;
|
|
5
|
+
/** The inverse of writeEmbeddedObjectPackage: recovers a ContentEmbeddedObject's kind, document, and residue when the Package stream bytes are this package's own payload, or undefined for anything else -- a real OLE object's packaged bytes included -- rather than throwing, since one unreadable embedding must not fail the whole sheet's drawing read. `frame` is the placement the caller derived from the embedding's own Escher anchor: the payload deliberately carries no placement of its own (see payloadOf above), and the full ContentEmbeddedObjectSchema validation needs a frame to accept, so the anchor-derived one is merged in before the parse -- the anchor stays the single authority for where the object sits. */
|
|
6
|
+
declare function readEmbeddedObjectPackage(packageBytes: Uint8Array<ArrayBuffer>, frame: ContentEmbeddedObject["frame"]): ContentEmbeddedObject | undefined;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { readEmbeddedObjectPackage, writeEmbeddedObjectPackage };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ContentEmbeddedObject } from "document-schema.js";
|
|
2
|
+
//#region src/workbook/embedded-object.d.ts
|
|
3
|
+
/** The Package stream bytes for one embedded object: this package's own JSON serialisation of the object's kind, document, and residue, wrapped in the [MS-OLEDS] packaging. */
|
|
4
|
+
declare function writeEmbeddedObjectPackage(embedded: ContentEmbeddedObject): Uint8Array<ArrayBuffer>;
|
|
5
|
+
/** The inverse of writeEmbeddedObjectPackage: recovers a ContentEmbeddedObject's kind, document, and residue when the Package stream bytes are this package's own payload, or undefined for anything else -- a real OLE object's packaged bytes included -- rather than throwing, since one unreadable embedding must not fail the whole sheet's drawing read. `frame` is the placement the caller derived from the embedding's own Escher anchor: the payload deliberately carries no placement of its own (see payloadOf above), and the full ContentEmbeddedObjectSchema validation needs a frame to accept, so the anchor-derived one is merged in before the parse -- the anchor stays the single authority for where the object sits. */
|
|
6
|
+
declare function readEmbeddedObjectPackage(packageBytes: Uint8Array<ArrayBuffer>, frame: ContentEmbeddedObject["frame"]): ContentEmbeddedObject | undefined;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { readEmbeddedObjectPackage, writeEmbeddedObjectPackage };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { readOlePackage, writeOlePackage } from "archive-codec";
|
|
2
|
+
import { ContentEmbeddedObjectSchema } from "document-schema.js";
|
|
3
|
+
//#region src/workbook/embedded-object.ts
|
|
4
|
+
const PACKAGE_LABEL = "xls-codec-embedded-object.json";
|
|
5
|
+
function payloadOf(embedded) {
|
|
6
|
+
return {
|
|
7
|
+
objectKind: embedded.objectKind,
|
|
8
|
+
document: embedded.document,
|
|
9
|
+
source: embedded.source
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/** The Package stream bytes for one embedded object: this package's own JSON serialisation of the object's kind, document, and residue, wrapped in the [MS-OLEDS] packaging. */
|
|
13
|
+
function writeEmbeddedObjectPackage(embedded) {
|
|
14
|
+
const fileBytes = new TextEncoder().encode(JSON.stringify(payloadOf(embedded)));
|
|
15
|
+
return writeOlePackage({
|
|
16
|
+
label: PACKAGE_LABEL,
|
|
17
|
+
sourcePath: "",
|
|
18
|
+
tempPath: "",
|
|
19
|
+
fileBytes
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/** The inverse of writeEmbeddedObjectPackage: recovers a ContentEmbeddedObject's kind, document, and residue when the Package stream bytes are this package's own payload, or undefined for anything else -- a real OLE object's packaged bytes included -- rather than throwing, since one unreadable embedding must not fail the whole sheet's drawing read. `frame` is the placement the caller derived from the embedding's own Escher anchor: the payload deliberately carries no placement of its own (see payloadOf above), and the full ContentEmbeddedObjectSchema validation needs a frame to accept, so the anchor-derived one is merged in before the parse -- the anchor stays the single authority for where the object sits. */
|
|
23
|
+
function readEmbeddedObjectPackage(packageBytes, frame) {
|
|
24
|
+
try {
|
|
25
|
+
const olePackage = readOlePackage(packageBytes);
|
|
26
|
+
if (olePackage.label !== PACKAGE_LABEL) return;
|
|
27
|
+
const text = new TextDecoder("utf-8").decode(olePackage.fileBytes);
|
|
28
|
+
const parsed = JSON.parse(text);
|
|
29
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || !("objectKind" in parsed) || !("document" in parsed)) return;
|
|
30
|
+
const result = ContentEmbeddedObjectSchema.safeParse({
|
|
31
|
+
...parsed,
|
|
32
|
+
frame
|
|
33
|
+
});
|
|
34
|
+
if (!result.success) return;
|
|
35
|
+
return result.data;
|
|
36
|
+
} catch {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { readEmbeddedObjectPackage, writeEmbeddedObjectPackage };
|
|
@@ -110,6 +110,7 @@ function buildWorkbookGlobals(plan) {
|
|
|
110
110
|
for (const record of require_workbook_print_names.writePrintNameRecords(plan.printNames)) push(record);
|
|
111
111
|
for (const record of require_workbook_defined_names.writeDefinedNameRecords(plan.definedNames)) push(record);
|
|
112
112
|
}
|
|
113
|
+
if (plan.drawingGroupBytes !== void 0) for (const record of require_biff_record_writer.writeRecordChain(235, plan.drawingGroupBytes)) push(record);
|
|
113
114
|
if (plan.sharedStrings.length > 0) push(writeSstRecord(plan.sharedStrings, plan.sharedStringTotalCount));
|
|
114
115
|
push(require_biff_record_writer.writeRecord(10, /* @__PURE__ */ new Uint8Array(0)));
|
|
115
116
|
return {
|
|
@@ -35,6 +35,8 @@ interface WorkbookGlobalsPlan {
|
|
|
35
35
|
readonly printNames: readonly PrintNamePlanEntry[];
|
|
36
36
|
/** The document-level defined names the workbook declares, one Lbl record each, from workbook/defined-names.ts's own compile of the document's names array. */
|
|
37
37
|
readonly definedNames: readonly DefinedNamePlanEntry[];
|
|
38
|
+
/** The workbook-wide Escher drawing group ([MS-ODRAW] OfficeArtDggContainer, drawing/escher-writer.ts's own writeDrawingGroupBytes) -- the FDGGBlock plus the Blip Store every sheet's picture shapes share -- or undefined when no sheet in the workbook carries an image or embedded object, in which case no MsoDrawingGroup record is written at all. */
|
|
39
|
+
readonly drawingGroupBytes?: Uint8Array<ArrayBuffer>;
|
|
38
40
|
}
|
|
39
41
|
interface WorkbookGlobalsBuild {
|
|
40
42
|
readonly bytes: Uint8Array<ArrayBuffer>;
|
|
@@ -35,6 +35,8 @@ interface WorkbookGlobalsPlan {
|
|
|
35
35
|
readonly printNames: readonly PrintNamePlanEntry[];
|
|
36
36
|
/** The document-level defined names the workbook declares, one Lbl record each, from workbook/defined-names.ts's own compile of the document's names array. */
|
|
37
37
|
readonly definedNames: readonly DefinedNamePlanEntry[];
|
|
38
|
+
/** The workbook-wide Escher drawing group ([MS-ODRAW] OfficeArtDggContainer, drawing/escher-writer.ts's own writeDrawingGroupBytes) -- the FDGGBlock plus the Blip Store every sheet's picture shapes share -- or undefined when no sheet in the workbook carries an image or embedded object, in which case no MsoDrawingGroup record is written at all. */
|
|
39
|
+
readonly drawingGroupBytes?: Uint8Array<ArrayBuffer>;
|
|
38
40
|
}
|
|
39
41
|
interface WorkbookGlobalsBuild {
|
|
40
42
|
readonly bytes: Uint8Array<ArrayBuffer>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RECORD_BOF } from "../biff/record-types.js";
|
|
2
2
|
import { RecordBuilder } from "../biff/builder.js";
|
|
3
|
-
import { concatRecords, writeRecord } from "../biff/record-writer.js";
|
|
3
|
+
import { concatRecords, writeRecord, writeRecordChain } from "../biff/record-writer.js";
|
|
4
4
|
import { writeFontRecord } from "../biff/font.js";
|
|
5
5
|
import { writeRichExtendedString, writeShortXLUnicodeString } from "../biff/string-writer.js";
|
|
6
6
|
import { writeDefinedNameRecords } from "./defined-names.js";
|
|
@@ -109,6 +109,7 @@ function buildWorkbookGlobals(plan) {
|
|
|
109
109
|
for (const record of writePrintNameRecords(plan.printNames)) push(record);
|
|
110
110
|
for (const record of writeDefinedNameRecords(plan.definedNames)) push(record);
|
|
111
111
|
}
|
|
112
|
+
if (plan.drawingGroupBytes !== void 0) for (const record of writeRecordChain(235, plan.drawingGroupBytes)) push(record);
|
|
112
113
|
if (plan.sharedStrings.length > 0) push(writeSstRecord(plan.sharedStrings, plan.sharedStringTotalCount));
|
|
113
114
|
push(writeRecord(10, /* @__PURE__ */ new Uint8Array(0)));
|
|
114
115
|
return {
|
|
@@ -289,8 +289,8 @@ function writeFormulaRecords(cell, xfIndex) {
|
|
|
289
289
|
function writeCellRecords(cell, xfIndex, ctx) {
|
|
290
290
|
return cell.formula !== void 0 ? writeFormulaRecords(cell, xfIndex) : [writeCellValueRecord(cell, xfIndex, ctx)];
|
|
291
291
|
}
|
|
292
|
-
/** Builds one worksheet's own substream: BOF, the print-settings records, Dimensions, ColInfo per column, Row + value-cell records per populated or declared row (in ascending row then column order), MergeCells if the sheet declares any, comment records for cells carrying one, EOF. */
|
|
293
|
-
function buildWorksheetSubstream(sheet, ctx) {
|
|
292
|
+
/** Builds one worksheet's own substream: BOF, the print-settings records, Dimensions, ColInfo per column, Row + value-cell records per populated or declared row (in ascending row then column order), MergeCells if the sheet declares any, comment records for cells carrying one, the sheet's own MsoDrawing/Obj records for images and embedded objects, EOF. */
|
|
293
|
+
function buildWorksheetSubstream(sheet, ctx, drawing) {
|
|
294
294
|
for (const cell of sheet.cells) checkedCellPosition(cell);
|
|
295
295
|
const writtenCells = sheet.cells.filter(require_written_cells.writesCellRecord);
|
|
296
296
|
const cellsByRow = /* @__PURE__ */ new Map();
|
|
@@ -320,8 +320,9 @@ function buildWorksheetSubstream(sheet, ctx) {
|
|
|
320
320
|
if (merges.length > 0) pieces.push(writeMergeCellsRecord(merges));
|
|
321
321
|
const commentedCells = sheet.cells.filter((cell) => cell.comment !== void 0);
|
|
322
322
|
if (commentedCells.length > 0) pieces.push(...require_workbook_comment_writer.writeSheetComments(commentedCells));
|
|
323
|
-
pieces.push(...
|
|
323
|
+
pieces.push(...drawing.msoDrawingRecords, ...drawing.objRecords);
|
|
324
324
|
pieces.push(...require_workbook_conditional_format_write.writeSheetConditionalFormats(sheet, ctx.icvOf));
|
|
325
|
+
pieces.push(...require_workbook_data_validation_write.writeSheetDataValidations(sheet));
|
|
325
326
|
pieces.push(require_biff_record_writer.writeRecord(10, /* @__PURE__ */ new Uint8Array(0)));
|
|
326
327
|
return require_biff_record_writer.concatRecords(...pieces);
|
|
327
328
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { n as SheetDrawingWrite } from "../drawing-writer-Blm_NUSZ.cjs";
|
|
1
2
|
import { Color, ContentSheet, ContentSheetCell } from "document-schema.js";
|
|
2
3
|
//#region src/workbook/sheet-writer.d.ts
|
|
3
4
|
interface SheetWriteContext {
|
|
@@ -8,7 +9,7 @@ interface SheetWriteContext {
|
|
|
8
9
|
/** The shared string table index for a string cell's own text; every string a sheet writes must already be registered in the workbook-wide table before this is called. */
|
|
9
10
|
sstIndexFor(text: string): number;
|
|
10
11
|
}
|
|
11
|
-
/** Builds one worksheet's own substream: BOF, the print-settings records, Dimensions, ColInfo per column, Row + value-cell records per populated or declared row (in ascending row then column order), MergeCells if the sheet declares any, comment records for cells carrying one, EOF. */
|
|
12
|
-
declare function buildWorksheetSubstream(sheet: ContentSheet, ctx: SheetWriteContext): Uint8Array<ArrayBuffer>;
|
|
12
|
+
/** Builds one worksheet's own substream: BOF, the print-settings records, Dimensions, ColInfo per column, Row + value-cell records per populated or declared row (in ascending row then column order), MergeCells if the sheet declares any, comment records for cells carrying one, the sheet's own MsoDrawing/Obj records for images and embedded objects, EOF. */
|
|
13
|
+
declare function buildWorksheetSubstream(sheet: ContentSheet, ctx: SheetWriteContext, drawing: SheetDrawingWrite): Uint8Array<ArrayBuffer>;
|
|
13
14
|
//#endregion
|
|
14
15
|
export { SheetWriteContext, buildWorksheetSubstream };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { n as SheetDrawingWrite } from "../drawing-writer-Blm_NUSZ.js";
|
|
1
2
|
import { Color, ContentSheet, ContentSheetCell } from "document-schema.js";
|
|
2
3
|
//#region src/workbook/sheet-writer.d.ts
|
|
3
4
|
interface SheetWriteContext {
|
|
@@ -8,7 +9,7 @@ interface SheetWriteContext {
|
|
|
8
9
|
/** The shared string table index for a string cell's own text; every string a sheet writes must already be registered in the workbook-wide table before this is called. */
|
|
9
10
|
sstIndexFor(text: string): number;
|
|
10
11
|
}
|
|
11
|
-
/** Builds one worksheet's own substream: BOF, the print-settings records, Dimensions, ColInfo per column, Row + value-cell records per populated or declared row (in ascending row then column order), MergeCells if the sheet declares any, comment records for cells carrying one, EOF. */
|
|
12
|
-
declare function buildWorksheetSubstream(sheet: ContentSheet, ctx: SheetWriteContext): Uint8Array<ArrayBuffer>;
|
|
12
|
+
/** Builds one worksheet's own substream: BOF, the print-settings records, Dimensions, ColInfo per column, Row + value-cell records per populated or declared row (in ascending row then column order), MergeCells if the sheet declares any, comment records for cells carrying one, the sheet's own MsoDrawing/Obj records for images and embedded objects, EOF. */
|
|
13
|
+
declare function buildWorksheetSubstream(sheet: ContentSheet, ctx: SheetWriteContext, drawing: SheetDrawingWrite): Uint8Array<ArrayBuffer>;
|
|
13
14
|
//#endregion
|
|
14
15
|
export { SheetWriteContext, buildWorksheetSubstream };
|
|
@@ -288,8 +288,8 @@ function writeFormulaRecords(cell, xfIndex) {
|
|
|
288
288
|
function writeCellRecords(cell, xfIndex, ctx) {
|
|
289
289
|
return cell.formula !== void 0 ? writeFormulaRecords(cell, xfIndex) : [writeCellValueRecord(cell, xfIndex, ctx)];
|
|
290
290
|
}
|
|
291
|
-
/** Builds one worksheet's own substream: BOF, the print-settings records, Dimensions, ColInfo per column, Row + value-cell records per populated or declared row (in ascending row then column order), MergeCells if the sheet declares any, comment records for cells carrying one, EOF. */
|
|
292
|
-
function buildWorksheetSubstream(sheet, ctx) {
|
|
291
|
+
/** Builds one worksheet's own substream: BOF, the print-settings records, Dimensions, ColInfo per column, Row + value-cell records per populated or declared row (in ascending row then column order), MergeCells if the sheet declares any, comment records for cells carrying one, the sheet's own MsoDrawing/Obj records for images and embedded objects, EOF. */
|
|
292
|
+
function buildWorksheetSubstream(sheet, ctx, drawing) {
|
|
293
293
|
for (const cell of sheet.cells) checkedCellPosition(cell);
|
|
294
294
|
const writtenCells = sheet.cells.filter(writesCellRecord);
|
|
295
295
|
const cellsByRow = /* @__PURE__ */ new Map();
|
|
@@ -319,8 +319,9 @@ function buildWorksheetSubstream(sheet, ctx) {
|
|
|
319
319
|
if (merges.length > 0) pieces.push(writeMergeCellsRecord(merges));
|
|
320
320
|
const commentedCells = sheet.cells.filter((cell) => cell.comment !== void 0);
|
|
321
321
|
if (commentedCells.length > 0) pieces.push(...writeSheetComments(commentedCells));
|
|
322
|
-
pieces.push(...
|
|
322
|
+
pieces.push(...drawing.msoDrawingRecords, ...drawing.objRecords);
|
|
323
323
|
pieces.push(...writeSheetConditionalFormats(sheet, ctx.icvOf));
|
|
324
|
+
pieces.push(...writeSheetDataValidations(sheet));
|
|
324
325
|
pieces.push(writeRecord(10, /* @__PURE__ */ new Uint8Array(0)));
|
|
325
326
|
return concatRecords(...pieces);
|
|
326
327
|
}
|