wpd-codec 3.1.1 → 3.2.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 +30 -26
- package/dist/bytes/view.cjs +5 -0
- package/dist/bytes/view.d.cts +2 -1
- package/dist/bytes/view.d.ts +2 -1
- package/dist/bytes/view.js +5 -1
- package/dist/container/prefix.cjs +15 -0
- package/dist/container/prefix.d.cts +3 -1
- package/dist/container/prefix.d.ts +3 -1
- package/dist/container/prefix.js +14 -1
- package/dist/{diagnostics-CR0pXOyb.d.cts → diagnostics-Dtb2uPw4.d.cts} +5 -0
- package/dist/{diagnostics-CR0pXOyb.d.ts → diagnostics-Dtb2uPw4.d.ts} +5 -0
- package/dist/diagnostics.cjs +6 -1
- package/dist/diagnostics.d.cts +1 -1
- package/dist/diagnostics.d.ts +1 -1
- package/dist/diagnostics.js +6 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/read.cjs +213 -48
- package/dist/read.d.cts +1 -1
- package/dist/read.d.ts +1 -1
- package/dist/read.js +215 -50
- package/dist/stream/box.cjs +122 -0
- package/dist/stream/box.d.cts +20 -0
- package/dist/stream/box.d.ts +20 -0
- package/dist/stream/box.js +117 -0
- package/dist/stream/formula.cjs +286 -0
- package/dist/stream/formula.d.cts +4 -0
- package/dist/stream/formula.d.ts +4 -0
- package/dist/stream/formula.js +285 -0
- package/dist/stream/style.cjs +19 -0
- package/dist/stream/style.d.cts +3 -1
- package/dist/stream/style.d.ts +3 -1
- package/dist/stream/style.js +18 -1
- package/dist/stream/table.cjs +2 -1
- package/dist/stream/table.d.cts +2 -1
- package/dist/stream/table.d.ts +2 -1
- package/dist/stream/table.js +2 -2
- package/package.json +3 -3
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { uint16At } from "../bytes/view.js";
|
|
2
|
+
import { pointsFromWpu } from "./units.js";
|
|
3
|
+
//#region src/stream/box.ts
|
|
4
|
+
const OVERRIDE_BIT_POSITION = 14;
|
|
5
|
+
const OVERRIDE_BIT_CONTENT = 13;
|
|
6
|
+
const OVERRIDE_BIT_HTML = 7;
|
|
7
|
+
const OVERRIDE_FLAGS_OFFSET = 18;
|
|
8
|
+
const FIRST_OVERRIDE_BLOCK_OFFSET = 20;
|
|
9
|
+
function walkOverrideBlocks(nonDeletable) {
|
|
10
|
+
if (nonDeletable.length < FIRST_OVERRIDE_BLOCK_OFFSET) return;
|
|
11
|
+
const flags = uint16At(nonDeletable, OVERRIDE_FLAGS_OFFSET);
|
|
12
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
13
|
+
let cursor = FIRST_OVERRIDE_BLOCK_OFFSET;
|
|
14
|
+
for (let bit = 15; bit >= 5; bit -= 1) {
|
|
15
|
+
if ((flags & 1 << bit) === 0) continue;
|
|
16
|
+
if (bit === OVERRIDE_BIT_HTML) continue;
|
|
17
|
+
if (cursor + 2 > nonDeletable.length) return;
|
|
18
|
+
const size = uint16At(nonDeletable, cursor);
|
|
19
|
+
cursor += 2;
|
|
20
|
+
if (cursor + size > nonDeletable.length) return;
|
|
21
|
+
blocks.set(bit, nonDeletable.subarray(cursor, cursor + size));
|
|
22
|
+
cursor += size;
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
flags,
|
|
26
|
+
blocks
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function readContentType(contentBlock) {
|
|
30
|
+
if (contentBlock.length < 2) return;
|
|
31
|
+
const flags = uint16At(contentBlock, 0);
|
|
32
|
+
let cursor = 2;
|
|
33
|
+
if ((flags & 32768) !== 0) {
|
|
34
|
+
if (cursor + 2 > contentBlock.length) return;
|
|
35
|
+
cursor += 2;
|
|
36
|
+
}
|
|
37
|
+
if ((flags & 16384) === 0) return;
|
|
38
|
+
return contentBlock[cursor];
|
|
39
|
+
}
|
|
40
|
+
function readPositionOverride(positionBlock) {
|
|
41
|
+
if (positionBlock.length < 2) return;
|
|
42
|
+
const flags = uint16At(positionBlock, 0);
|
|
43
|
+
let cursor = 2;
|
|
44
|
+
let widthWpu;
|
|
45
|
+
let heightWpu;
|
|
46
|
+
let xWpu;
|
|
47
|
+
let yWpu;
|
|
48
|
+
const need = (bytes) => cursor + bytes <= positionBlock.length;
|
|
49
|
+
if ((flags & 32768) !== 0) {
|
|
50
|
+
if (!need(2)) return void 0;
|
|
51
|
+
cursor += 2;
|
|
52
|
+
}
|
|
53
|
+
if ((flags & 16384) !== 0) {
|
|
54
|
+
if (!need(2)) return void 0;
|
|
55
|
+
cursor += 2;
|
|
56
|
+
}
|
|
57
|
+
if ((flags & 8192) !== 0) {
|
|
58
|
+
if (!need(5)) return void 0;
|
|
59
|
+
const horizontalFlags = positionBlock[cursor];
|
|
60
|
+
const offset = uint16At(positionBlock, cursor + 1);
|
|
61
|
+
if (horizontalFlags !== void 0 && (horizontalFlags & 3) === 0) xWpu = offset;
|
|
62
|
+
cursor += 5;
|
|
63
|
+
}
|
|
64
|
+
if ((flags & 4096) !== 0) {
|
|
65
|
+
if (!need(3)) return void 0;
|
|
66
|
+
const verticalFlags = positionBlock[cursor];
|
|
67
|
+
const offset = uint16At(positionBlock, cursor + 1);
|
|
68
|
+
if (verticalFlags !== void 0 && (verticalFlags & 3) === 0) yWpu = offset;
|
|
69
|
+
cursor += 3;
|
|
70
|
+
}
|
|
71
|
+
if ((flags & 2048) !== 0) {
|
|
72
|
+
if (!need(3)) return void 0;
|
|
73
|
+
widthWpu = uint16At(positionBlock, cursor + 1);
|
|
74
|
+
cursor += 3;
|
|
75
|
+
}
|
|
76
|
+
if ((flags & 1024) !== 0) {
|
|
77
|
+
if (!need(3)) return void 0;
|
|
78
|
+
heightWpu = uint16At(positionBlock, cursor + 1);
|
|
79
|
+
cursor += 3;
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
widthWpu,
|
|
83
|
+
heightWpu,
|
|
84
|
+
xWpu,
|
|
85
|
+
yWpu
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const BOX_CONTENT_TYPE_TEXT = 1;
|
|
89
|
+
const BOX_CONTENT_TYPE_LINKED_TEXT = 2;
|
|
90
|
+
const BOX_CONTENT_TYPE_IMAGE = 3;
|
|
91
|
+
const BOX_CONTENT_TYPE_EQUATION = 4;
|
|
92
|
+
function readBoxContent(nonDeletable, prefixIds) {
|
|
93
|
+
const walk = walkOverrideBlocks(nonDeletable);
|
|
94
|
+
if (walk === void 0) return;
|
|
95
|
+
const { flags, blocks } = walk;
|
|
96
|
+
const contentBlock = blocks.get(OVERRIDE_BIT_CONTENT);
|
|
97
|
+
if (contentBlock === void 0) return;
|
|
98
|
+
const contentType = readContentType(contentBlock);
|
|
99
|
+
if (contentType === void 0) return;
|
|
100
|
+
const contentPrefixId = prefixIds[1 + ((flags & 32768) !== 0 ? 1 : 0)];
|
|
101
|
+
if (contentPrefixId === void 0) return;
|
|
102
|
+
const positionBlock = blocks.get(OVERRIDE_BIT_POSITION);
|
|
103
|
+
const position = positionBlock === void 0 ? void 0 : readPositionOverride(positionBlock);
|
|
104
|
+
return {
|
|
105
|
+
contentType,
|
|
106
|
+
contentPrefixId,
|
|
107
|
+
frame: position?.widthWpu === void 0 || position.heightWpu === void 0 ? void 0 : {
|
|
108
|
+
xPt: pointsFromWpu(position.xWpu ?? 0),
|
|
109
|
+
yPt: pointsFromWpu(position.yWpu ?? 0),
|
|
110
|
+
widthPt: pointsFromWpu(position.widthWpu),
|
|
111
|
+
heightPt: pointsFromWpu(position.heightWpu),
|
|
112
|
+
positionResolved: position.xWpu !== void 0 && position.yWpu !== void 0
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//#endregion
|
|
117
|
+
export { BOX_CONTENT_TYPE_EQUATION, BOX_CONTENT_TYPE_IMAGE, BOX_CONTENT_TYPE_LINKED_TEXT, BOX_CONTENT_TYPE_TEXT, readBoxContent };
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_bytes_view = require("../bytes/view.cjs");
|
|
3
|
+
const require_stream_characters = require("./characters.cjs");
|
|
4
|
+
//#region src/stream/formula.ts
|
|
5
|
+
const GROUP1_FUNCTIONS = /* @__PURE__ */ new Map([
|
|
6
|
+
[1, "MINUS"],
|
|
7
|
+
[2, "ABS"],
|
|
8
|
+
[3, "INT"],
|
|
9
|
+
[4, "SIGN"],
|
|
10
|
+
[5, "NOT"],
|
|
11
|
+
[6, "TRUE"],
|
|
12
|
+
[7, "FALSE"],
|
|
13
|
+
[8, "AND"],
|
|
14
|
+
[9, "OR"],
|
|
15
|
+
[10, "AVE"],
|
|
16
|
+
[11, "COUNT"],
|
|
17
|
+
[12, "MIN"],
|
|
18
|
+
[13, "MAX"],
|
|
19
|
+
[14, "NA"],
|
|
20
|
+
[15, "ISNA"],
|
|
21
|
+
[16, "TIME"],
|
|
22
|
+
[17, "DATE"],
|
|
23
|
+
[18, "FACT"],
|
|
24
|
+
[19, "ROW"],
|
|
25
|
+
[20, "COLUMN"]
|
|
26
|
+
]);
|
|
27
|
+
const GROUP2_FUNCTIONS = /* @__PURE__ */ new Map([
|
|
28
|
+
[1, "POWER"],
|
|
29
|
+
[2, "LN"],
|
|
30
|
+
[3, "LOG"],
|
|
31
|
+
[4, "SQRT"],
|
|
32
|
+
[5, "PI"],
|
|
33
|
+
[6, "EXP"],
|
|
34
|
+
[7, "SIN"],
|
|
35
|
+
[8, "COS"],
|
|
36
|
+
[9, "TAN"],
|
|
37
|
+
[10, "MOD"],
|
|
38
|
+
[11, "ASIN"],
|
|
39
|
+
[12, "ACOS"],
|
|
40
|
+
[13, "ATAN"],
|
|
41
|
+
[14, "TERM"],
|
|
42
|
+
[15, "PV"],
|
|
43
|
+
[16, "PMT"],
|
|
44
|
+
[17, "FV"],
|
|
45
|
+
[18, "NPV"],
|
|
46
|
+
[19, "LOOKUP"],
|
|
47
|
+
[20, "INDEX"],
|
|
48
|
+
[21, "ROUND"],
|
|
49
|
+
[22, "STDEV"],
|
|
50
|
+
[23, "CONCEDE"],
|
|
51
|
+
[24, "MID"],
|
|
52
|
+
[25, "LENGTH"],
|
|
53
|
+
[26, "VALUE"],
|
|
54
|
+
[27, "TEXT"],
|
|
55
|
+
[28, "MDY"],
|
|
56
|
+
[29, "MONTH"],
|
|
57
|
+
[30, "DAY"],
|
|
58
|
+
[31, "YEAR"],
|
|
59
|
+
[32, "DATETEXT"],
|
|
60
|
+
[33, "DATEVALUE"],
|
|
61
|
+
[34, "VAR"],
|
|
62
|
+
[35, "RANDOM"],
|
|
63
|
+
[36, "CURRENCY"],
|
|
64
|
+
[37, "ITERATION"],
|
|
65
|
+
[38, "ISVALUE"],
|
|
66
|
+
[39, "ISTEXT"],
|
|
67
|
+
[40, "REPLACE"],
|
|
68
|
+
[41, "RADIANS"],
|
|
69
|
+
[42, "CELL"],
|
|
70
|
+
[43, "SUBTRACT"],
|
|
71
|
+
[44, "IRR"],
|
|
72
|
+
[45, "FIND"],
|
|
73
|
+
[46, "LEFT"],
|
|
74
|
+
[47, "RIGHT"],
|
|
75
|
+
[48, "UPPER"],
|
|
76
|
+
[49, "LOWER"],
|
|
77
|
+
[50, "PROPER"],
|
|
78
|
+
[51, "CHAR"],
|
|
79
|
+
[52, "CODE"],
|
|
80
|
+
[53, "TRIM"],
|
|
81
|
+
[54, "REPEAT"],
|
|
82
|
+
[55, "BLOCK"],
|
|
83
|
+
[56, "CURSOR"],
|
|
84
|
+
[57, "DDB"],
|
|
85
|
+
[58, "SLN"],
|
|
86
|
+
[59, "SYD"],
|
|
87
|
+
[60, "RATE"],
|
|
88
|
+
[61, "STATUS"],
|
|
89
|
+
[62, "FOREACH"],
|
|
90
|
+
[63, "DEGREES"],
|
|
91
|
+
[64, "HOUR"],
|
|
92
|
+
[65, "MINUTE"],
|
|
93
|
+
[66, "SECOND"],
|
|
94
|
+
[67, "HMS"],
|
|
95
|
+
[68, "TIMETEXT"],
|
|
96
|
+
[69, "TIMEVALUE"],
|
|
97
|
+
[70, "PRODUCT"],
|
|
98
|
+
[71, "QUOTIENT"],
|
|
99
|
+
[72, "VARP"],
|
|
100
|
+
[73, "STDEVP"],
|
|
101
|
+
[74, "ATAN2"],
|
|
102
|
+
[75, "MATCH"],
|
|
103
|
+
[76, "MATCH2"],
|
|
104
|
+
[77, "LOOKUP2"],
|
|
105
|
+
[78, "LINK"],
|
|
106
|
+
[79, "ISERR"],
|
|
107
|
+
[80, "ISERR2"],
|
|
108
|
+
[81, "CHOOSE"]
|
|
109
|
+
]);
|
|
110
|
+
const COMPARE_OPERATORS = /* @__PURE__ */ new Map([
|
|
111
|
+
[1, "="],
|
|
112
|
+
[2, "<>"],
|
|
113
|
+
[3, ">"],
|
|
114
|
+
[4, ">="],
|
|
115
|
+
[5, "<"],
|
|
116
|
+
[6, "<="]
|
|
117
|
+
]);
|
|
118
|
+
const SYMBOL_CODES = /* @__PURE__ */ new Map([
|
|
119
|
+
[1, "+"],
|
|
120
|
+
[2, "-"],
|
|
121
|
+
[3, "*"],
|
|
122
|
+
[4, "/"],
|
|
123
|
+
[5, "-"],
|
|
124
|
+
[6, "%"],
|
|
125
|
+
[7, "SUM"],
|
|
126
|
+
[11, "^"],
|
|
127
|
+
[15, "%"],
|
|
128
|
+
[16, "!"],
|
|
129
|
+
[17, "&"],
|
|
130
|
+
[18, "|"],
|
|
131
|
+
[19, "^^"],
|
|
132
|
+
[20, "IF"],
|
|
133
|
+
[22, ","],
|
|
134
|
+
[23, "("],
|
|
135
|
+
[24, ")"],
|
|
136
|
+
[29, "!="],
|
|
137
|
+
[35, "0"],
|
|
138
|
+
[36, "{"],
|
|
139
|
+
[37, "}"],
|
|
140
|
+
[38, "!"],
|
|
141
|
+
[39, "<"],
|
|
142
|
+
[40, ">"]
|
|
143
|
+
]);
|
|
144
|
+
function columnLetters(column) {
|
|
145
|
+
let value = column;
|
|
146
|
+
let letters = "";
|
|
147
|
+
do {
|
|
148
|
+
letters = String.fromCharCode(65 + value % 26) + letters;
|
|
149
|
+
value = Math.floor(value / 26) - 1;
|
|
150
|
+
} while (value >= 0);
|
|
151
|
+
return letters;
|
|
152
|
+
}
|
|
153
|
+
function cellReferenceText(row, column, absoluteColumn, absoluteRow) {
|
|
154
|
+
if (row < 0 || column < 0) return;
|
|
155
|
+
return `${`${absoluteColumn ? "$" : ""}${columnLetters(column)}`}${`${absoluteRow ? "$" : ""}${row + 1}`}`;
|
|
156
|
+
}
|
|
157
|
+
function readLengthPrefixedWordString(cursor) {
|
|
158
|
+
if (cursor.offset + 2 > cursor.bytes.length) return;
|
|
159
|
+
const length = require_bytes_view.uint16At(cursor.bytes, cursor.offset);
|
|
160
|
+
cursor.offset += 2;
|
|
161
|
+
const { text, wordsRead } = require_stream_characters.decodeWordString(cursor.bytes, cursor.offset, length);
|
|
162
|
+
if (wordsRead < length) return;
|
|
163
|
+
cursor.offset += length * 2;
|
|
164
|
+
return text;
|
|
165
|
+
}
|
|
166
|
+
function readLengthPrefixedByteString(cursor) {
|
|
167
|
+
if (cursor.offset + 2 > cursor.bytes.length) return;
|
|
168
|
+
const length = require_bytes_view.uint16At(cursor.bytes, cursor.offset);
|
|
169
|
+
cursor.offset += 2;
|
|
170
|
+
if (cursor.offset + length > cursor.bytes.length) return;
|
|
171
|
+
const slice = cursor.bytes.subarray(cursor.offset, cursor.offset + length);
|
|
172
|
+
cursor.offset += length;
|
|
173
|
+
return Array.from(slice, (byte) => String.fromCharCode(byte)).join("");
|
|
174
|
+
}
|
|
175
|
+
function readCellNumber(cursor) {
|
|
176
|
+
if (cursor.offset + 4 > cursor.bytes.length) return;
|
|
177
|
+
const row = require_bytes_view.int16At(cursor.bytes, cursor.offset);
|
|
178
|
+
const column = require_bytes_view.int16At(cursor.bytes, cursor.offset + 2);
|
|
179
|
+
cursor.offset += 4;
|
|
180
|
+
return {
|
|
181
|
+
row,
|
|
182
|
+
column
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function readToken(cursor) {
|
|
186
|
+
const code = cursor.bytes[cursor.offset];
|
|
187
|
+
if (code === void 0) return;
|
|
188
|
+
cursor.offset += 1;
|
|
189
|
+
const symbol = SYMBOL_CODES.get(code);
|
|
190
|
+
if (symbol !== void 0) return symbol;
|
|
191
|
+
switch (code) {
|
|
192
|
+
case 8:
|
|
193
|
+
case 9:
|
|
194
|
+
case 10:
|
|
195
|
+
case 26: {
|
|
196
|
+
const text = readLengthPrefixedWordString(cursor);
|
|
197
|
+
if (text === void 0) return;
|
|
198
|
+
return code === 9 ? `"${text}"` : text;
|
|
199
|
+
}
|
|
200
|
+
case 12: {
|
|
201
|
+
const functionNumber = cursor.bytes[cursor.offset];
|
|
202
|
+
cursor.offset += 1;
|
|
203
|
+
return functionNumber === void 0 ? void 0 : GROUP1_FUNCTIONS.get(functionNumber);
|
|
204
|
+
}
|
|
205
|
+
case 13: {
|
|
206
|
+
const functionNumber = cursor.bytes[cursor.offset];
|
|
207
|
+
cursor.offset += 1;
|
|
208
|
+
return functionNumber === void 0 ? void 0 : GROUP2_FUNCTIONS.get(functionNumber);
|
|
209
|
+
}
|
|
210
|
+
case 21: {
|
|
211
|
+
const functionNumber = cursor.bytes[cursor.offset];
|
|
212
|
+
cursor.offset += 1;
|
|
213
|
+
return functionNumber === void 0 ? void 0 : COMPARE_OPERATORS.get(functionNumber);
|
|
214
|
+
}
|
|
215
|
+
case 25: {
|
|
216
|
+
if (cursor.offset + 2 > cursor.bytes.length) return;
|
|
217
|
+
const count = require_bytes_view.uint16At(cursor.bytes, cursor.offset);
|
|
218
|
+
cursor.offset += 2;
|
|
219
|
+
return " ".repeat(count);
|
|
220
|
+
}
|
|
221
|
+
case 27: {
|
|
222
|
+
const cell = readCellNumber(cursor);
|
|
223
|
+
return cell === void 0 ? void 0 : cellReferenceText(cell.row, cell.column, false, false);
|
|
224
|
+
}
|
|
225
|
+
case 28: {
|
|
226
|
+
const start = readCellNumber(cursor);
|
|
227
|
+
const end = start === void 0 ? void 0 : readCellNumber(cursor);
|
|
228
|
+
if (start === void 0 || end === void 0) return;
|
|
229
|
+
const startText = cellReferenceText(start.row, start.column, false, false);
|
|
230
|
+
const endText = cellReferenceText(end.row, end.column, false, false);
|
|
231
|
+
return startText === void 0 || endText === void 0 ? void 0 : `${startText}:${endText}`;
|
|
232
|
+
}
|
|
233
|
+
case 30: {
|
|
234
|
+
if (cursor.offset + 8 > cursor.bytes.length) return;
|
|
235
|
+
const value = new DataView(cursor.bytes.buffer, cursor.bytes.byteOffset + cursor.offset, 8).getFloat64(0, true);
|
|
236
|
+
cursor.offset += 8;
|
|
237
|
+
return readLengthPrefixedByteString(cursor) === void 0 ? void 0 : String(value);
|
|
238
|
+
}
|
|
239
|
+
case 31: {
|
|
240
|
+
if (cursor.offset + 2 > cursor.bytes.length) return;
|
|
241
|
+
const argumentNumber = require_bytes_view.uint16At(cursor.bytes, cursor.offset);
|
|
242
|
+
cursor.offset += 2;
|
|
243
|
+
return `ARG${argumentNumber}`;
|
|
244
|
+
}
|
|
245
|
+
case 32: return readLengthPrefixedWordString(cursor);
|
|
246
|
+
case 41:
|
|
247
|
+
case 42:
|
|
248
|
+
cursor.offset += 2;
|
|
249
|
+
return "";
|
|
250
|
+
case 43:
|
|
251
|
+
cursor.offset += 2;
|
|
252
|
+
return "";
|
|
253
|
+
case 44: return "";
|
|
254
|
+
default:
|
|
255
|
+
if (code >= 48 && code <= 63) {
|
|
256
|
+
const flags = code - 48;
|
|
257
|
+
const start = readCellNumber(cursor);
|
|
258
|
+
const end = start === void 0 ? void 0 : readCellNumber(cursor);
|
|
259
|
+
if (start === void 0 || end === void 0) return;
|
|
260
|
+
const startText = cellReferenceText(start.row, start.column, (flags & 4) !== 0, (flags & 8) !== 0);
|
|
261
|
+
const endText = cellReferenceText(end.row, end.column, (flags & 1) !== 0, (flags & 2) !== 0);
|
|
262
|
+
return startText === void 0 || endText === void 0 ? void 0 : `${startText}:${endText}`;
|
|
263
|
+
}
|
|
264
|
+
if (code >= 64 && code <= 67) {
|
|
265
|
+
const flags = code - 64;
|
|
266
|
+
const cell = readCellNumber(cursor);
|
|
267
|
+
return cell === void 0 ? void 0 : cellReferenceText(cell.row, cell.column, (flags & 1) !== 0, (flags & 2) !== 0);
|
|
268
|
+
}
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function readTableFormula(bytes) {
|
|
273
|
+
const cursor = {
|
|
274
|
+
bytes,
|
|
275
|
+
offset: 0
|
|
276
|
+
};
|
|
277
|
+
let text = "";
|
|
278
|
+
while (cursor.offset < bytes.length) {
|
|
279
|
+
const token = readToken(cursor);
|
|
280
|
+
if (token === void 0) return;
|
|
281
|
+
text += token;
|
|
282
|
+
}
|
|
283
|
+
return text;
|
|
284
|
+
}
|
|
285
|
+
//#endregion
|
|
286
|
+
exports.readTableFormula = readTableFormula;
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { int16At, uint16At } from "../bytes/view.js";
|
|
2
|
+
import { decodeWordString } from "./characters.js";
|
|
3
|
+
//#region src/stream/formula.ts
|
|
4
|
+
const GROUP1_FUNCTIONS = /* @__PURE__ */ new Map([
|
|
5
|
+
[1, "MINUS"],
|
|
6
|
+
[2, "ABS"],
|
|
7
|
+
[3, "INT"],
|
|
8
|
+
[4, "SIGN"],
|
|
9
|
+
[5, "NOT"],
|
|
10
|
+
[6, "TRUE"],
|
|
11
|
+
[7, "FALSE"],
|
|
12
|
+
[8, "AND"],
|
|
13
|
+
[9, "OR"],
|
|
14
|
+
[10, "AVE"],
|
|
15
|
+
[11, "COUNT"],
|
|
16
|
+
[12, "MIN"],
|
|
17
|
+
[13, "MAX"],
|
|
18
|
+
[14, "NA"],
|
|
19
|
+
[15, "ISNA"],
|
|
20
|
+
[16, "TIME"],
|
|
21
|
+
[17, "DATE"],
|
|
22
|
+
[18, "FACT"],
|
|
23
|
+
[19, "ROW"],
|
|
24
|
+
[20, "COLUMN"]
|
|
25
|
+
]);
|
|
26
|
+
const GROUP2_FUNCTIONS = /* @__PURE__ */ new Map([
|
|
27
|
+
[1, "POWER"],
|
|
28
|
+
[2, "LN"],
|
|
29
|
+
[3, "LOG"],
|
|
30
|
+
[4, "SQRT"],
|
|
31
|
+
[5, "PI"],
|
|
32
|
+
[6, "EXP"],
|
|
33
|
+
[7, "SIN"],
|
|
34
|
+
[8, "COS"],
|
|
35
|
+
[9, "TAN"],
|
|
36
|
+
[10, "MOD"],
|
|
37
|
+
[11, "ASIN"],
|
|
38
|
+
[12, "ACOS"],
|
|
39
|
+
[13, "ATAN"],
|
|
40
|
+
[14, "TERM"],
|
|
41
|
+
[15, "PV"],
|
|
42
|
+
[16, "PMT"],
|
|
43
|
+
[17, "FV"],
|
|
44
|
+
[18, "NPV"],
|
|
45
|
+
[19, "LOOKUP"],
|
|
46
|
+
[20, "INDEX"],
|
|
47
|
+
[21, "ROUND"],
|
|
48
|
+
[22, "STDEV"],
|
|
49
|
+
[23, "CONCEDE"],
|
|
50
|
+
[24, "MID"],
|
|
51
|
+
[25, "LENGTH"],
|
|
52
|
+
[26, "VALUE"],
|
|
53
|
+
[27, "TEXT"],
|
|
54
|
+
[28, "MDY"],
|
|
55
|
+
[29, "MONTH"],
|
|
56
|
+
[30, "DAY"],
|
|
57
|
+
[31, "YEAR"],
|
|
58
|
+
[32, "DATETEXT"],
|
|
59
|
+
[33, "DATEVALUE"],
|
|
60
|
+
[34, "VAR"],
|
|
61
|
+
[35, "RANDOM"],
|
|
62
|
+
[36, "CURRENCY"],
|
|
63
|
+
[37, "ITERATION"],
|
|
64
|
+
[38, "ISVALUE"],
|
|
65
|
+
[39, "ISTEXT"],
|
|
66
|
+
[40, "REPLACE"],
|
|
67
|
+
[41, "RADIANS"],
|
|
68
|
+
[42, "CELL"],
|
|
69
|
+
[43, "SUBTRACT"],
|
|
70
|
+
[44, "IRR"],
|
|
71
|
+
[45, "FIND"],
|
|
72
|
+
[46, "LEFT"],
|
|
73
|
+
[47, "RIGHT"],
|
|
74
|
+
[48, "UPPER"],
|
|
75
|
+
[49, "LOWER"],
|
|
76
|
+
[50, "PROPER"],
|
|
77
|
+
[51, "CHAR"],
|
|
78
|
+
[52, "CODE"],
|
|
79
|
+
[53, "TRIM"],
|
|
80
|
+
[54, "REPEAT"],
|
|
81
|
+
[55, "BLOCK"],
|
|
82
|
+
[56, "CURSOR"],
|
|
83
|
+
[57, "DDB"],
|
|
84
|
+
[58, "SLN"],
|
|
85
|
+
[59, "SYD"],
|
|
86
|
+
[60, "RATE"],
|
|
87
|
+
[61, "STATUS"],
|
|
88
|
+
[62, "FOREACH"],
|
|
89
|
+
[63, "DEGREES"],
|
|
90
|
+
[64, "HOUR"],
|
|
91
|
+
[65, "MINUTE"],
|
|
92
|
+
[66, "SECOND"],
|
|
93
|
+
[67, "HMS"],
|
|
94
|
+
[68, "TIMETEXT"],
|
|
95
|
+
[69, "TIMEVALUE"],
|
|
96
|
+
[70, "PRODUCT"],
|
|
97
|
+
[71, "QUOTIENT"],
|
|
98
|
+
[72, "VARP"],
|
|
99
|
+
[73, "STDEVP"],
|
|
100
|
+
[74, "ATAN2"],
|
|
101
|
+
[75, "MATCH"],
|
|
102
|
+
[76, "MATCH2"],
|
|
103
|
+
[77, "LOOKUP2"],
|
|
104
|
+
[78, "LINK"],
|
|
105
|
+
[79, "ISERR"],
|
|
106
|
+
[80, "ISERR2"],
|
|
107
|
+
[81, "CHOOSE"]
|
|
108
|
+
]);
|
|
109
|
+
const COMPARE_OPERATORS = /* @__PURE__ */ new Map([
|
|
110
|
+
[1, "="],
|
|
111
|
+
[2, "<>"],
|
|
112
|
+
[3, ">"],
|
|
113
|
+
[4, ">="],
|
|
114
|
+
[5, "<"],
|
|
115
|
+
[6, "<="]
|
|
116
|
+
]);
|
|
117
|
+
const SYMBOL_CODES = /* @__PURE__ */ new Map([
|
|
118
|
+
[1, "+"],
|
|
119
|
+
[2, "-"],
|
|
120
|
+
[3, "*"],
|
|
121
|
+
[4, "/"],
|
|
122
|
+
[5, "-"],
|
|
123
|
+
[6, "%"],
|
|
124
|
+
[7, "SUM"],
|
|
125
|
+
[11, "^"],
|
|
126
|
+
[15, "%"],
|
|
127
|
+
[16, "!"],
|
|
128
|
+
[17, "&"],
|
|
129
|
+
[18, "|"],
|
|
130
|
+
[19, "^^"],
|
|
131
|
+
[20, "IF"],
|
|
132
|
+
[22, ","],
|
|
133
|
+
[23, "("],
|
|
134
|
+
[24, ")"],
|
|
135
|
+
[29, "!="],
|
|
136
|
+
[35, "0"],
|
|
137
|
+
[36, "{"],
|
|
138
|
+
[37, "}"],
|
|
139
|
+
[38, "!"],
|
|
140
|
+
[39, "<"],
|
|
141
|
+
[40, ">"]
|
|
142
|
+
]);
|
|
143
|
+
function columnLetters(column) {
|
|
144
|
+
let value = column;
|
|
145
|
+
let letters = "";
|
|
146
|
+
do {
|
|
147
|
+
letters = String.fromCharCode(65 + value % 26) + letters;
|
|
148
|
+
value = Math.floor(value / 26) - 1;
|
|
149
|
+
} while (value >= 0);
|
|
150
|
+
return letters;
|
|
151
|
+
}
|
|
152
|
+
function cellReferenceText(row, column, absoluteColumn, absoluteRow) {
|
|
153
|
+
if (row < 0 || column < 0) return;
|
|
154
|
+
return `${`${absoluteColumn ? "$" : ""}${columnLetters(column)}`}${`${absoluteRow ? "$" : ""}${row + 1}`}`;
|
|
155
|
+
}
|
|
156
|
+
function readLengthPrefixedWordString(cursor) {
|
|
157
|
+
if (cursor.offset + 2 > cursor.bytes.length) return;
|
|
158
|
+
const length = uint16At(cursor.bytes, cursor.offset);
|
|
159
|
+
cursor.offset += 2;
|
|
160
|
+
const { text, wordsRead } = decodeWordString(cursor.bytes, cursor.offset, length);
|
|
161
|
+
if (wordsRead < length) return;
|
|
162
|
+
cursor.offset += length * 2;
|
|
163
|
+
return text;
|
|
164
|
+
}
|
|
165
|
+
function readLengthPrefixedByteString(cursor) {
|
|
166
|
+
if (cursor.offset + 2 > cursor.bytes.length) return;
|
|
167
|
+
const length = uint16At(cursor.bytes, cursor.offset);
|
|
168
|
+
cursor.offset += 2;
|
|
169
|
+
if (cursor.offset + length > cursor.bytes.length) return;
|
|
170
|
+
const slice = cursor.bytes.subarray(cursor.offset, cursor.offset + length);
|
|
171
|
+
cursor.offset += length;
|
|
172
|
+
return Array.from(slice, (byte) => String.fromCharCode(byte)).join("");
|
|
173
|
+
}
|
|
174
|
+
function readCellNumber(cursor) {
|
|
175
|
+
if (cursor.offset + 4 > cursor.bytes.length) return;
|
|
176
|
+
const row = int16At(cursor.bytes, cursor.offset);
|
|
177
|
+
const column = int16At(cursor.bytes, cursor.offset + 2);
|
|
178
|
+
cursor.offset += 4;
|
|
179
|
+
return {
|
|
180
|
+
row,
|
|
181
|
+
column
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function readToken(cursor) {
|
|
185
|
+
const code = cursor.bytes[cursor.offset];
|
|
186
|
+
if (code === void 0) return;
|
|
187
|
+
cursor.offset += 1;
|
|
188
|
+
const symbol = SYMBOL_CODES.get(code);
|
|
189
|
+
if (symbol !== void 0) return symbol;
|
|
190
|
+
switch (code) {
|
|
191
|
+
case 8:
|
|
192
|
+
case 9:
|
|
193
|
+
case 10:
|
|
194
|
+
case 26: {
|
|
195
|
+
const text = readLengthPrefixedWordString(cursor);
|
|
196
|
+
if (text === void 0) return;
|
|
197
|
+
return code === 9 ? `"${text}"` : text;
|
|
198
|
+
}
|
|
199
|
+
case 12: {
|
|
200
|
+
const functionNumber = cursor.bytes[cursor.offset];
|
|
201
|
+
cursor.offset += 1;
|
|
202
|
+
return functionNumber === void 0 ? void 0 : GROUP1_FUNCTIONS.get(functionNumber);
|
|
203
|
+
}
|
|
204
|
+
case 13: {
|
|
205
|
+
const functionNumber = cursor.bytes[cursor.offset];
|
|
206
|
+
cursor.offset += 1;
|
|
207
|
+
return functionNumber === void 0 ? void 0 : GROUP2_FUNCTIONS.get(functionNumber);
|
|
208
|
+
}
|
|
209
|
+
case 21: {
|
|
210
|
+
const functionNumber = cursor.bytes[cursor.offset];
|
|
211
|
+
cursor.offset += 1;
|
|
212
|
+
return functionNumber === void 0 ? void 0 : COMPARE_OPERATORS.get(functionNumber);
|
|
213
|
+
}
|
|
214
|
+
case 25: {
|
|
215
|
+
if (cursor.offset + 2 > cursor.bytes.length) return;
|
|
216
|
+
const count = uint16At(cursor.bytes, cursor.offset);
|
|
217
|
+
cursor.offset += 2;
|
|
218
|
+
return " ".repeat(count);
|
|
219
|
+
}
|
|
220
|
+
case 27: {
|
|
221
|
+
const cell = readCellNumber(cursor);
|
|
222
|
+
return cell === void 0 ? void 0 : cellReferenceText(cell.row, cell.column, false, false);
|
|
223
|
+
}
|
|
224
|
+
case 28: {
|
|
225
|
+
const start = readCellNumber(cursor);
|
|
226
|
+
const end = start === void 0 ? void 0 : readCellNumber(cursor);
|
|
227
|
+
if (start === void 0 || end === void 0) return;
|
|
228
|
+
const startText = cellReferenceText(start.row, start.column, false, false);
|
|
229
|
+
const endText = cellReferenceText(end.row, end.column, false, false);
|
|
230
|
+
return startText === void 0 || endText === void 0 ? void 0 : `${startText}:${endText}`;
|
|
231
|
+
}
|
|
232
|
+
case 30: {
|
|
233
|
+
if (cursor.offset + 8 > cursor.bytes.length) return;
|
|
234
|
+
const value = new DataView(cursor.bytes.buffer, cursor.bytes.byteOffset + cursor.offset, 8).getFloat64(0, true);
|
|
235
|
+
cursor.offset += 8;
|
|
236
|
+
return readLengthPrefixedByteString(cursor) === void 0 ? void 0 : String(value);
|
|
237
|
+
}
|
|
238
|
+
case 31: {
|
|
239
|
+
if (cursor.offset + 2 > cursor.bytes.length) return;
|
|
240
|
+
const argumentNumber = uint16At(cursor.bytes, cursor.offset);
|
|
241
|
+
cursor.offset += 2;
|
|
242
|
+
return `ARG${argumentNumber}`;
|
|
243
|
+
}
|
|
244
|
+
case 32: return readLengthPrefixedWordString(cursor);
|
|
245
|
+
case 41:
|
|
246
|
+
case 42:
|
|
247
|
+
cursor.offset += 2;
|
|
248
|
+
return "";
|
|
249
|
+
case 43:
|
|
250
|
+
cursor.offset += 2;
|
|
251
|
+
return "";
|
|
252
|
+
case 44: return "";
|
|
253
|
+
default:
|
|
254
|
+
if (code >= 48 && code <= 63) {
|
|
255
|
+
const flags = code - 48;
|
|
256
|
+
const start = readCellNumber(cursor);
|
|
257
|
+
const end = start === void 0 ? void 0 : readCellNumber(cursor);
|
|
258
|
+
if (start === void 0 || end === void 0) return;
|
|
259
|
+
const startText = cellReferenceText(start.row, start.column, (flags & 4) !== 0, (flags & 8) !== 0);
|
|
260
|
+
const endText = cellReferenceText(end.row, end.column, (flags & 1) !== 0, (flags & 2) !== 0);
|
|
261
|
+
return startText === void 0 || endText === void 0 ? void 0 : `${startText}:${endText}`;
|
|
262
|
+
}
|
|
263
|
+
if (code >= 64 && code <= 67) {
|
|
264
|
+
const flags = code - 64;
|
|
265
|
+
const cell = readCellNumber(cursor);
|
|
266
|
+
return cell === void 0 ? void 0 : cellReferenceText(cell.row, cell.column, (flags & 1) !== 0, (flags & 2) !== 0);
|
|
267
|
+
}
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function readTableFormula(bytes) {
|
|
272
|
+
const cursor = {
|
|
273
|
+
bytes,
|
|
274
|
+
offset: 0
|
|
275
|
+
};
|
|
276
|
+
let text = "";
|
|
277
|
+
while (cursor.offset < bytes.length) {
|
|
278
|
+
const token = readToken(cursor);
|
|
279
|
+
if (token === void 0) return;
|
|
280
|
+
text += token;
|
|
281
|
+
}
|
|
282
|
+
return text;
|
|
283
|
+
}
|
|
284
|
+
//#endregion
|
|
285
|
+
export { readTableFormula };
|