From d3a480750bd479791e0c0d4bc16dcf764980b423 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Sat, 13 May 2023 01:17:15 -0400 Subject: [PATCH] NUMBERS read/write external links --- Makefile | 3 +- bits/83_numbers.js | 433 +++++++++++++++++++++++++++++++++------- modules/83_numbers.js | 433 +++++++++++++++++++++++++++++++++------- modules/83_numbers.ts | 412 ++++++++++++++++++++++++++++++-------- xlsx.mjs | 455 +++++++++++++++++++++++++++++++++++------- 5 files changed, 1443 insertions(+), 293 deletions(-) diff --git a/Makefile b/Makefile index 0bf7d9c..ae9fb07 100644 --- a/Makefile +++ b/Makefile @@ -246,8 +246,7 @@ misc/coverage.html: $(TARGET) test.js coveralls: ## Coverage Test + Send to coveralls.io mocha --require blanket --reporter mocha-lcov-reporter -t 30000 | node ./node_modules/coveralls/bin/coveralls.js -DEMOMDS=$(sort $(wildcard demos/*/README.md)) -MDLINT=$(DEMOMDS) README.md demos/README.md +MDLINT=README.md .PHONY: mdlint mdlint: $(MDLINT) ## Check markdown documents ./node_modules/.bin/alex $^ diff --git a/bits/83_numbers.js b/bits/83_numbers.js index 63a51b6..731d47a 100644 --- a/bits/83_numbers.js +++ b/bits/83_numbers.js @@ -146,19 +146,18 @@ function write_packed_varints(nums) { } function varint_to_i32(buf) { var l = 0, i32 = buf[l] & 127; - varint: - if (buf[l++] >= 128) { - i32 |= (buf[l] & 127) << 7; - if (buf[l++] < 128) - break varint; - i32 |= (buf[l] & 127) << 14; - if (buf[l++] < 128) - break varint; - i32 |= (buf[l] & 127) << 21; - if (buf[l++] < 128) - break varint; - i32 |= (buf[l] & 127) << 28; - } + if (buf[l++] < 128) + return i32; + i32 |= (buf[l] & 127) << 7; + if (buf[l++] < 128) + return i32; + i32 |= (buf[l] & 127) << 14; + if (buf[l++] < 128) + return i32; + i32 |= (buf[l] & 127) << 21; + if (buf[l++] < 128) + return i32; + i32 |= (buf[l] & 15) << 28; return i32; } function varint_to_u64(buf) { @@ -451,7 +450,7 @@ function compress_iwa_file(buf) { return u8concat(out); } var numbers_lut_new = function() { - return { sst: [], rsst: [], ofmt: [], nfmt: [] }; + return { sst: [], rsst: [], ofmt: [], nfmt: [], fmla: [], ferr: [] }; }; function numbers_format_cell(cell, t, flags, ofmt, nfmt) { var _a, _b, _c, _d; @@ -627,9 +626,12 @@ function parse_old_storage(buf, lut, v) { break; case 9: { - if (ridx > -1) - ret = { t: "s", v: lut.rsst[ridx] }; - else + if (ridx > -1) { + var rts = lut.rsst[ridx]; + ret = { t: "s", v: rts.v }; + if (rts.l) + ret.l = { Target: rts.l }; + } else throw new Error("Unsupported cell type ".concat(buf[subarray](0, 4))); } break; @@ -647,7 +649,7 @@ function parse_new_storage(buf, lut) { var flags = dv.getUint32(4, true); var fields = dv.getUint32(8, true); var doff = 12; - var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1); + var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1), eidx = -1, fidx = -1; if (fields & 1) { d128 = readDecimal128LE(buf, doff); doff += 16; @@ -668,6 +670,16 @@ function parse_new_storage(buf, lut) { ridx = dv.getUint32(doff, true); doff += 4; } + doff += popcnt(fields & 480) * 4; + if (fields & 512) { + fidx = dv.getUint32(doff, true); + doff += 4; + } + doff += popcnt(fields & 1024) * 4; + if (fields & 2048) { + eidx = dv.getUint32(doff, true); + doff += 4; + } var ret; var t = buf[1]; switch (t) { @@ -692,7 +704,15 @@ function parse_new_storage(buf, lut) { ret = { t: "e", v: 0 }; break; case 9: - ret = { t: "s", v: lut.rsst[ridx] }; + { + if (ridx > -1) { + var rts = lut.rsst[ridx]; + ret = { t: "s", v: rts.v }; + if (rts.l) + ret.l = { Target: rts.l }; + } else + throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(fields & 31, " : ").concat(buf[subarray](0, 4))); + } break; case 10: ret = { t: "n", v: d128 }; @@ -700,7 +720,7 @@ function parse_new_storage(buf, lut) { default: throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(fields & 31, " : ").concat(buf[subarray](0, 4))); } - doff += popcnt(fields & 8160) * 4; + doff += popcnt(fields & 4096) * 4; if (fields & 516096) { if (zidx == -1) zidx = dv.getUint32(doff, true); @@ -712,7 +732,7 @@ function parse_new_storage(buf, lut) { ret.v /= 86400; return ret; } -function write_new_storage(cell, sst) { +function write_new_storage(cell, sst, rsst) { var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, flags = 0; out[0] = 5; switch (cell.t) { @@ -729,14 +749,29 @@ function write_new_storage(cell, sst) { l += 8; break; case "s": - var s = cell.v == null ? "" : String(cell.v); - var isst = sst.indexOf(s); - if (isst == -1) - sst[isst = sst.length] = s; - out[1] = 3; - dv.setUint32(l, isst, true); - flags |= 8; - l += 4; + { + var s = cell.v == null ? "" : String(cell.v); + if (cell.l) { + var irsst = rsst.findIndex(function(v) { + var _a; + return v.v == s && v.l == ((_a = cell.l) == null ? void 0 : _a.Target); + }); + if (irsst == -1) + rsst[irsst = rsst.length] = { v: s, l: cell.l.Target }; + out[1] = 9; + dv.setUint32(l, irsst, true); + flags |= 16; + l += 4; + } else { + var isst = sst.indexOf(s); + if (isst == -1) + sst[isst = sst.length] = s; + out[1] = 3; + dv.setUint32(l, isst, true); + flags |= 8; + l += 4; + } + } break; default: throw "unsupported cell type " + cell.t; @@ -744,31 +779,46 @@ function write_new_storage(cell, sst) { dv.setUint32(8, flags, true); return out[subarray](0, l); } -function write_old_storage(cell, sst) { +function write_old_storage(cell, sst, rsst) { var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, flags = 0; out[0] = 4; switch (cell.t) { case "n": - out[2] = 2; + out[1] = 2; dv.setFloat64(l, cell.v, true); flags |= 32; l += 8; break; case "b": - out[2] = 6; + out[1] = 6; dv.setFloat64(l, cell.v ? 1 : 0, true); flags |= 32; l += 8; break; case "s": - var s = cell.v == null ? "" : String(cell.v); - var isst = sst.indexOf(s); - if (isst == -1) - sst[isst = sst.length] = s; - out[2] = 3; - dv.setUint32(l, isst, true); - flags |= 16; - l += 4; + { + var s = cell.v == null ? "" : String(cell.v); + if (cell.l) { + var irsst = rsst.findIndex(function(v) { + var _a; + return v.v == s && v.l == ((_a = cell.l) == null ? void 0 : _a.Target); + }); + if (irsst == -1) + rsst[irsst = rsst.length] = { v: s, l: cell.l.Target }; + out[1] = 9; + dv.setUint32(l, irsst, true); + flags |= 512; + l += 4; + } else { + var isst = sst.indexOf(s); + if (isst == -1) + sst[isst = sst.length] = s; + out[1] = 3; + dv.setUint32(l, isst, true); + flags |= 16; + l += 4; + } + } break; default: throw "unsupported cell type " + cell.t; @@ -822,6 +872,7 @@ function parse_TST_TableDataList(M, root) { var entries = pb[3]; var data = []; (entries || []).forEach(function(entry) { + var _a, _b; var le = parse_shallow(entry.data); if (!le[1]) return; @@ -839,14 +890,43 @@ function parse_TST_TableDataList(M, root) { if (mtype != 2001) throw new Error("2000 unexpected reference to ".concat(mtype)); var tswpsa = parse_shallow(rtpref.data); - data[key] = tswpsa[3].map(function(x) { + var richtext = { v: tswpsa[3].map(function(x) { return u8str(x.data); - }).join(""); + }).join("") }; + data[key] = richtext; + sfields: + if ((_a = tswpsa == null ? void 0 : tswpsa[11]) == null ? void 0 : _a[0]) { + var smartfields = (_b = parse_shallow(tswpsa[11][0].data)) == null ? void 0 : _b[1]; + if (!smartfields) + break sfields; + smartfields.forEach(function(sf) { + var _a2, _b2, _c; + var attr = parse_shallow(sf.data); + if ((_a2 = attr[2]) == null ? void 0 : _a2[0]) { + var obj = M[parse_TSP_Reference((_b2 = attr[2]) == null ? void 0 : _b2[0].data)][0]; + var objtype = varint_to_i32(obj.meta[1][0].data); + switch (objtype) { + case 2032: + var hlink = parse_shallow(obj.data); + if (((_c = hlink == null ? void 0 : hlink[2]) == null ? void 0 : _c[0]) && !richtext.l) + richtext.l = u8str(hlink[2][0].data); + break; + case 2039: + break; + default: + console.log("unrecognized ObjectAttribute type ".concat(objtype)); + } + } + }); + } } break; case 2: data[key] = parse_shallow(le[6][0].data); break; + case 3: + data[key] = parse_shallow(le[5][0].data); + break; default: throw type; } @@ -913,7 +993,7 @@ function parse_TST_Tile(M, root) { }; } function parse_TST_TableModelArchive(M, root, ws) { - var _a, _b, _c, _d, _e, _f; + var _a, _b, _c, _d, _e, _f, _g, _h; var pb = parse_shallow(root.data); var range = { s: { r: 0, c: 0 }, e: { r: 0, c: 0 } }; range.e.r = (varint_to_i32(pb[6][0].data) >>> 0) - 1; @@ -928,11 +1008,15 @@ function parse_TST_TableModelArchive(M, root, ws) { var lut = numbers_lut_new(); if ((_a = store[4]) == null ? void 0 : _a[0]) lut.sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); - if ((_b = store[11]) == null ? void 0 : _b[0]) + if ((_b = store[6]) == null ? void 0 : _b[0]) + lut.fmla = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[6][0].data)][0]); + if ((_c = store[11]) == null ? void 0 : _c[0]) lut.ofmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[11][0].data)][0]); - if ((_c = store[17]) == null ? void 0 : _c[0]) + if ((_d = store[12]) == null ? void 0 : _d[0]) + lut.ferr = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[12][0].data)][0]); + if ((_e = store[17]) == null ? void 0 : _e[0]) lut.rsst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]); - if ((_d = store[22]) == null ? void 0 : _d[0]) + if ((_f = store[22]) == null ? void 0 : _f[0]) lut.nfmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[22][0].data)][0]); var tile = parse_shallow(store[3][0].data); var _R = 0; @@ -959,12 +1043,12 @@ function parse_TST_TableModelArchive(M, root, ws) { }); _R += _tile.nrows; }); - if ((_e = store[13]) == null ? void 0 : _e[0]) { + if ((_g = store[13]) == null ? void 0 : _g[0]) { var ref = M[parse_TSP_Reference(store[13][0].data)][0]; var mtype = varint_to_i32(ref.meta[1][0].data); if (mtype != 6144) throw new Error("Expected merge type 6144, found ".concat(mtype)); - ws["!merges"] = (_f = parse_shallow(ref.data)) == null ? void 0 : _f[1].map(function(pi) { + ws["!merges"] = (_h = parse_shallow(ref.data)) == null ? void 0 : _h[1].map(function(pi) { var merge = parse_shallow(pi.data); var origin = u8_to_dataview(parse_shallow(merge[1][0].data)[1][0].data), size = u8_to_dataview(parse_shallow(merge[2][0].data)[1][0].data); return { @@ -1079,7 +1163,7 @@ function parse_numbers_iwa(cfb, opts) { throw new Error("Cannot find Document root"); return parse_TN_DocumentArchive(M, docroot, opts); } -function write_TST_TileRowInfo(data, SST, wide) { +function write_TST_TileRowInfo(data, SST, RSST, wide) { var _a, _b; var tri = [ [], @@ -1113,7 +1197,7 @@ function write_TST_TileRowInfo(data, SST, wide) { var _dv = u8_to_dataview(tri[4][0].data), _last_offset = 0, _cell_storage = []; var width = wide ? 4 : 1; for (var C = 0; C < data.length; ++C) { - if (data[C] == null) { + if (data[C] == null || data[C].t == "z" || data[C].t == "e") { dv.setUint16(C * 2, 65535, true); _dv.setUint16(C * 2, 65535); continue; @@ -1121,25 +1205,23 @@ function write_TST_TileRowInfo(data, SST, wide) { dv.setUint16(C * 2, last_offset / width, true); _dv.setUint16(C * 2, _last_offset / width, true); var celload, _celload; - switch (typeof data[C]) { - case "string": - celload = write_new_storage({ t: "s", v: data[C] }, SST); - _celload = write_old_storage({ t: "s", v: data[C] }, SST); - break; - case "number": - celload = write_new_storage({ t: "n", v: data[C] }, SST); - _celload = write_old_storage({ t: "n", v: data[C] }, SST); - break; - case "boolean": - celload = write_new_storage({ t: "b", v: data[C] }, SST); - _celload = write_old_storage({ t: "b", v: data[C] }, SST); - break; - default: - if (data[C] instanceof Date) { - celload = write_new_storage({ t: "s", v: data[C].toISOString() }, SST); - _celload = write_old_storage({ t: "s", v: data[C].toISOString() }, SST); + switch (data[C].t) { + case "d": + if (data[C].v instanceof Date) { + celload = write_new_storage({ t: "s", v: data[C].v.toISOString() }, SST, RSST); + _celload = write_old_storage({ t: "s", v: data[C].v.toISOString() }, SST, RSST); break; } + celload = write_new_storage(data[C], SST, RSST); + _celload = write_old_storage(data[C], SST, RSST); + break; + case "s": + case "n": + case "b": + celload = write_new_storage(data[C], SST, RSST); + _celload = write_old_storage(data[C], SST, RSST); + break; + default: throw new Error("Unsupported value " + data[C]); } cell_storage.push(celload); @@ -1260,6 +1342,38 @@ function numbers_iwa_find(cfb, deps, id) { }); return ainfo; } +function numbers_add_msg(cfb, type, msg, path, deps, id) { + if (!id) + id = get_unique_msgid({ deps: [], location: "", type: type }, deps); + var loc = "".concat(path, "-").concat(id, ".iwa"); + deps[id].location = "Root Entry" + loc; + CFB.utils.cfb_add(cfb, loc, compress_iwa_file(write_iwa_file([{ + id: id, + messages: [write_iwam(type, write_shallow(msg))] + }]))); + var newloc = loc.replace(/^[\/]/, "").replace(/^Index\//, "").replace(/\.iwa$/, ""); + numbers_iwa_doit(cfb, deps, 2, function(ai) { + var mlist = parse_shallow(ai.messages[0].data); + mlist[3].push({ type: 2, data: write_shallow([ + [], + [{ type: 0, data: write_varint49(id) }], + [{ type: 2, data: stru8(newloc.replace(/-.*$/, "")) }], + [{ type: 2, data: stru8(newloc) }], + [{ type: 2, data: new Uint8Array([2, 0, 0]) }], + [{ type: 2, data: new Uint8Array([2, 0, 0]) }], + [], + [], + [], + [], + [{ type: 0, data: write_varint49(0) }], + [], + [{ type: 0, data: write_varint49(0) }] + ]) }); + mlist[1] = [{ type: 0, data: write_varint49(Math.max(id + 1, varint_to_i32(mlist[1][0].data))) }]; + ai.messages[0].data = write_shallow(mlist); + }); + return id; +} function numbers_add_ws(cfb, deps, wsidx) { var sheetref = -1, newsheetref = -1; var remap = {}; @@ -1362,7 +1476,7 @@ function numbers_add_ws(cfb, deps, wsidx) { numbers_iwa_doit(cfb, deps, tmaref, function(tmaroot, arch) { var _a, _b; var tma = parse_shallow(tmaroot.messages[0].data); - var uuid = u8str(tma[1][0].data), new_uuid = uuid.replace(/-[A-Z0-9]*/, "-".concat(wsidx.toString(16).padStart(4, "0"))); + var uuid = u8str(tma[1][0].data), new_uuid = uuid.replace(/-[A-Z0-9]*/, "-".concat(("0000" + wsidx.toString(16)).slice(-4))); tma[1][0].data = stru8(new_uuid); [12, 13, 29, 31, 32, 33, 39, 44, 47, 81, 82, 84].forEach(function(n) { return delete tma[n]; @@ -1648,8 +1762,27 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) { } if (trunc) console.error("Truncating to ".concat(encode_range(range))); - var data = sheet_to_json(ws, { range: range, header: 1 }); + var data = []; + if (ws["!data"]) + data = ws["!data"]; + else { + var colstr = []; + for (var _C = 0; _C <= range.e.c; ++_C) + colstr[_C] = encode_col(_C); + for (var R_ = 0; R_ <= range.e.r; ++R_) { + data[R_] = []; + var _R = "" + (R_ + 1); + for (_C = 0; _C <= range.e.c; ++_C) { + var _cell = ws[colstr[_C] + _R]; + if (!_cell) + continue; + data[R_][_C] = _cell; + } + } + } + sheet_to_json(ws, { range: range, header: 1 }); var SST = ["~Sh33tJ5~"]; + var RSST = [{ v: "~54ee77S~", l: "https://sheetjs.com/" }]; var loc = deps[tmaref].location; loc = loc.replace(/^Root Entry\//, ""); loc = loc.replace(/^Index\//, "").replace(/\.iwa$/, ""); @@ -1747,7 +1880,7 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) { [{ type: 0, data: write_varint49(USE_WIDE_ROWS ? 1 : 0) }] ]; for (var R = tidx * tstride; R <= Math.min(range.e.r, (tidx + 1) * tstride - 1); ++R) { - var tilerow = write_TST_TileRowInfo(data[R], SST, USE_WIDE_ROWS); + var tilerow = write_TST_TileRowInfo(data[R], SST, RSST, USE_WIDE_ROWS); tilerow[1][0].data = write_varint49(R - tidx * tstride); tiledata[5].push({ data: write_shallow(tilerow), type: 2 }); } @@ -1884,6 +2017,166 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) { } sstroot.messages[0].data = write_shallow(sstdata); }); + var rsstref = parse_TSP_Reference(store[17][0].data); + numbers_iwa_doit(cfb, deps, rsstref, function(rsstroot) { + var rsstdata = parse_shallow(rsstroot.messages[0].data); + rsstdata[3] = []; + var style_indices = [ + 904980, + 903835, + 903815, + 903845 + ]; + RSST.forEach(function(rsst, i) { + if (i == 0) + return; + var tswpsa = [ + [], + [{ type: 0, data: new Uint8Array([5]) }], + [], + [{ type: 2, data: stru8(rsst.v) }] + ]; + tswpsa[10] = [{ type: 0, data: new Uint8Array([1]) }]; + tswpsa[19] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 18, 2, 101, 110]) }]; + tswpsa[5] = [{ type: 2, data: new Uint8Array([10, 8, 8, 0, 18, 4, 8, 155, 149, 55]) }]; + tswpsa[2] = [{ type: 2, data: new Uint8Array([8, 148, 158, 55]) }]; + tswpsa[6] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 16, 0, 24, 0]) }]; + tswpsa[7] = [{ type: 2, data: new Uint8Array([10, 8, 8, 0, 18, 4, 8, 135, 149, 55]) }]; + tswpsa[8] = [{ type: 2, data: new Uint8Array([10, 8, 8, 0, 18, 4, 8, 165, 149, 55]) }]; + tswpsa[14] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 16, 0, 24, 0]) }]; + tswpsa[24] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 16, 0, 24, 0]) }]; + var tswpsaid = get_unique_msgid({ deps: [], location: "", type: 2001 }, deps); + var tswpsarefs = []; + if (rsst.l) { + var newhlinkid = numbers_add_msg(cfb, 2032, [ + [], + [], + [{ type: 2, data: stru8(rsst.l) }] + ], "/Index/Tables/DataList", deps); + tswpsa[11] = []; + var smartfield = [[], []]; + if (!smartfield[1]) + smartfield[1] = []; + smartfield[1].push({ type: 2, data: write_shallow([ + [], + [{ type: 0, data: write_varint49(0) }], + [{ type: 2, data: write_TSP_Reference(newhlinkid) }] + ]) }); + tswpsa[11][0] = { type: 2, data: write_shallow(smartfield) }; + tswpsarefs.push(newhlinkid); + } + numbers_add_msg(cfb, 2001, tswpsa, "/Index/Tables/DataList", deps, tswpsaid); + numbers_iwa_doit(cfb, deps, tswpsaid, function(iwa) { + style_indices.forEach(function(ref) { + return numbers_add_oref(iwa, ref); + }); + tswpsarefs.forEach(function(ref) { + return numbers_add_oref(iwa, ref); + }); + }); + var rtpaid = numbers_add_msg(cfb, 6218, [ + [], + [{ type: 2, data: write_TSP_Reference(tswpsaid) }], + [], + [{ type: 2, data: new Uint8Array([13, 255, 255, 255, 0, 18, 10, 16, 255, 255, 1, 24, 255, 255, 255, 255, 7]) }] + ], "/Index/Tables/DataList", deps); + numbers_iwa_doit(cfb, deps, rtpaid, function(iwa) { + return numbers_add_oref(iwa, tswpsaid); + }); + rsstdata[3].push({ type: 2, data: write_shallow([ + [], + [{ type: 0, data: write_varint49(i) }], + [{ type: 0, data: write_varint49(1) }], + [], + [], + [], + [], + [], + [], + [{ type: 2, data: write_TSP_Reference(rtpaid) }] + ]) }); + numbers_add_oref(rsstroot, rtpaid); + numbers_iwa_doit(cfb, deps, 2, function(ai) { + var mlist = parse_shallow(ai.messages[0].data); + var loc2 = deps[rsstref].location.replace(/^Root Entry\//, "").replace(/^Index\//, "").replace(/\.iwa$/, ""); + var parentidx = mlist[3].findIndex(function(m) { + var _a, _b; + var mm = parse_shallow(m.data); + if ((_a = mm[3]) == null ? void 0 : _a[0]) + return u8str(mm[3][0].data) == loc2; + if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc2) + return true; + return false; + }); + var parent = parse_shallow(mlist[3][parentidx].data); + if (!parent[6]) + parent[6] = []; + parent[6].push({ + type: 2, + data: write_shallow([ + [], + [{ type: 0, data: write_varint49(rtpaid) }] + ]) + }); + mlist[3][parentidx].data = write_shallow(parent); + loc2 = deps[rtpaid].location.replace(/^Root Entry\//, "").replace(/^Index\//, "").replace(/\.iwa$/, ""); + parentidx = mlist[3].findIndex(function(m) { + var _a, _b; + var mm = parse_shallow(m.data); + if ((_a = mm[3]) == null ? void 0 : _a[0]) + return u8str(mm[3][0].data) == loc2; + if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc2) + return true; + return false; + }); + parent = parse_shallow(mlist[3][parentidx].data); + if (!parent[6]) + parent[6] = []; + parent[6].push({ + type: 2, + data: write_shallow([ + [], + [{ type: 0, data: write_varint49(tswpsaid) }] + ]) + }); + mlist[3][parentidx].data = write_shallow(parent); + loc2 = deps[tswpsaid].location.replace(/^Root Entry\//, "").replace(/^Index\//, "").replace(/\.iwa$/, ""); + parentidx = mlist[3].findIndex(function(m) { + var _a, _b; + var mm = parse_shallow(m.data); + if ((_a = mm[3]) == null ? void 0 : _a[0]) + return u8str(mm[3][0].data) == loc2; + if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc2) + return true; + return false; + }); + parent = parse_shallow(mlist[3][parentidx].data); + if (!parent[6]) + parent[6] = []; + tswpsarefs.forEach(function(id) { + return parent[6].push({ + type: 2, + data: write_shallow([ + [], + [{ type: 0, data: write_varint49(id) }] + ]) + }); + }); + style_indices.forEach(function(n) { + return parent[6].push({ + type: 2, + data: write_shallow([ + [], + [{ type: 0, data: write_varint49(n) }] + ]) + }); + }); + mlist[3][parentidx].data = write_shallow(parent); + ai.messages[0].data = write_shallow(mlist); + }); + }); + rsstroot.messages[0].data = write_shallow(rsstdata); + }); } pb[4][0].data = write_shallow(store); } diff --git a/modules/83_numbers.js b/modules/83_numbers.js index 63a51b6..731d47a 100644 --- a/modules/83_numbers.js +++ b/modules/83_numbers.js @@ -146,19 +146,18 @@ function write_packed_varints(nums) { } function varint_to_i32(buf) { var l = 0, i32 = buf[l] & 127; - varint: - if (buf[l++] >= 128) { - i32 |= (buf[l] & 127) << 7; - if (buf[l++] < 128) - break varint; - i32 |= (buf[l] & 127) << 14; - if (buf[l++] < 128) - break varint; - i32 |= (buf[l] & 127) << 21; - if (buf[l++] < 128) - break varint; - i32 |= (buf[l] & 127) << 28; - } + if (buf[l++] < 128) + return i32; + i32 |= (buf[l] & 127) << 7; + if (buf[l++] < 128) + return i32; + i32 |= (buf[l] & 127) << 14; + if (buf[l++] < 128) + return i32; + i32 |= (buf[l] & 127) << 21; + if (buf[l++] < 128) + return i32; + i32 |= (buf[l] & 15) << 28; return i32; } function varint_to_u64(buf) { @@ -451,7 +450,7 @@ function compress_iwa_file(buf) { return u8concat(out); } var numbers_lut_new = function() { - return { sst: [], rsst: [], ofmt: [], nfmt: [] }; + return { sst: [], rsst: [], ofmt: [], nfmt: [], fmla: [], ferr: [] }; }; function numbers_format_cell(cell, t, flags, ofmt, nfmt) { var _a, _b, _c, _d; @@ -627,9 +626,12 @@ function parse_old_storage(buf, lut, v) { break; case 9: { - if (ridx > -1) - ret = { t: "s", v: lut.rsst[ridx] }; - else + if (ridx > -1) { + var rts = lut.rsst[ridx]; + ret = { t: "s", v: rts.v }; + if (rts.l) + ret.l = { Target: rts.l }; + } else throw new Error("Unsupported cell type ".concat(buf[subarray](0, 4))); } break; @@ -647,7 +649,7 @@ function parse_new_storage(buf, lut) { var flags = dv.getUint32(4, true); var fields = dv.getUint32(8, true); var doff = 12; - var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1); + var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1), eidx = -1, fidx = -1; if (fields & 1) { d128 = readDecimal128LE(buf, doff); doff += 16; @@ -668,6 +670,16 @@ function parse_new_storage(buf, lut) { ridx = dv.getUint32(doff, true); doff += 4; } + doff += popcnt(fields & 480) * 4; + if (fields & 512) { + fidx = dv.getUint32(doff, true); + doff += 4; + } + doff += popcnt(fields & 1024) * 4; + if (fields & 2048) { + eidx = dv.getUint32(doff, true); + doff += 4; + } var ret; var t = buf[1]; switch (t) { @@ -692,7 +704,15 @@ function parse_new_storage(buf, lut) { ret = { t: "e", v: 0 }; break; case 9: - ret = { t: "s", v: lut.rsst[ridx] }; + { + if (ridx > -1) { + var rts = lut.rsst[ridx]; + ret = { t: "s", v: rts.v }; + if (rts.l) + ret.l = { Target: rts.l }; + } else + throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(fields & 31, " : ").concat(buf[subarray](0, 4))); + } break; case 10: ret = { t: "n", v: d128 }; @@ -700,7 +720,7 @@ function parse_new_storage(buf, lut) { default: throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(fields & 31, " : ").concat(buf[subarray](0, 4))); } - doff += popcnt(fields & 8160) * 4; + doff += popcnt(fields & 4096) * 4; if (fields & 516096) { if (zidx == -1) zidx = dv.getUint32(doff, true); @@ -712,7 +732,7 @@ function parse_new_storage(buf, lut) { ret.v /= 86400; return ret; } -function write_new_storage(cell, sst) { +function write_new_storage(cell, sst, rsst) { var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, flags = 0; out[0] = 5; switch (cell.t) { @@ -729,14 +749,29 @@ function write_new_storage(cell, sst) { l += 8; break; case "s": - var s = cell.v == null ? "" : String(cell.v); - var isst = sst.indexOf(s); - if (isst == -1) - sst[isst = sst.length] = s; - out[1] = 3; - dv.setUint32(l, isst, true); - flags |= 8; - l += 4; + { + var s = cell.v == null ? "" : String(cell.v); + if (cell.l) { + var irsst = rsst.findIndex(function(v) { + var _a; + return v.v == s && v.l == ((_a = cell.l) == null ? void 0 : _a.Target); + }); + if (irsst == -1) + rsst[irsst = rsst.length] = { v: s, l: cell.l.Target }; + out[1] = 9; + dv.setUint32(l, irsst, true); + flags |= 16; + l += 4; + } else { + var isst = sst.indexOf(s); + if (isst == -1) + sst[isst = sst.length] = s; + out[1] = 3; + dv.setUint32(l, isst, true); + flags |= 8; + l += 4; + } + } break; default: throw "unsupported cell type " + cell.t; @@ -744,31 +779,46 @@ function write_new_storage(cell, sst) { dv.setUint32(8, flags, true); return out[subarray](0, l); } -function write_old_storage(cell, sst) { +function write_old_storage(cell, sst, rsst) { var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, flags = 0; out[0] = 4; switch (cell.t) { case "n": - out[2] = 2; + out[1] = 2; dv.setFloat64(l, cell.v, true); flags |= 32; l += 8; break; case "b": - out[2] = 6; + out[1] = 6; dv.setFloat64(l, cell.v ? 1 : 0, true); flags |= 32; l += 8; break; case "s": - var s = cell.v == null ? "" : String(cell.v); - var isst = sst.indexOf(s); - if (isst == -1) - sst[isst = sst.length] = s; - out[2] = 3; - dv.setUint32(l, isst, true); - flags |= 16; - l += 4; + { + var s = cell.v == null ? "" : String(cell.v); + if (cell.l) { + var irsst = rsst.findIndex(function(v) { + var _a; + return v.v == s && v.l == ((_a = cell.l) == null ? void 0 : _a.Target); + }); + if (irsst == -1) + rsst[irsst = rsst.length] = { v: s, l: cell.l.Target }; + out[1] = 9; + dv.setUint32(l, irsst, true); + flags |= 512; + l += 4; + } else { + var isst = sst.indexOf(s); + if (isst == -1) + sst[isst = sst.length] = s; + out[1] = 3; + dv.setUint32(l, isst, true); + flags |= 16; + l += 4; + } + } break; default: throw "unsupported cell type " + cell.t; @@ -822,6 +872,7 @@ function parse_TST_TableDataList(M, root) { var entries = pb[3]; var data = []; (entries || []).forEach(function(entry) { + var _a, _b; var le = parse_shallow(entry.data); if (!le[1]) return; @@ -839,14 +890,43 @@ function parse_TST_TableDataList(M, root) { if (mtype != 2001) throw new Error("2000 unexpected reference to ".concat(mtype)); var tswpsa = parse_shallow(rtpref.data); - data[key] = tswpsa[3].map(function(x) { + var richtext = { v: tswpsa[3].map(function(x) { return u8str(x.data); - }).join(""); + }).join("") }; + data[key] = richtext; + sfields: + if ((_a = tswpsa == null ? void 0 : tswpsa[11]) == null ? void 0 : _a[0]) { + var smartfields = (_b = parse_shallow(tswpsa[11][0].data)) == null ? void 0 : _b[1]; + if (!smartfields) + break sfields; + smartfields.forEach(function(sf) { + var _a2, _b2, _c; + var attr = parse_shallow(sf.data); + if ((_a2 = attr[2]) == null ? void 0 : _a2[0]) { + var obj = M[parse_TSP_Reference((_b2 = attr[2]) == null ? void 0 : _b2[0].data)][0]; + var objtype = varint_to_i32(obj.meta[1][0].data); + switch (objtype) { + case 2032: + var hlink = parse_shallow(obj.data); + if (((_c = hlink == null ? void 0 : hlink[2]) == null ? void 0 : _c[0]) && !richtext.l) + richtext.l = u8str(hlink[2][0].data); + break; + case 2039: + break; + default: + console.log("unrecognized ObjectAttribute type ".concat(objtype)); + } + } + }); + } } break; case 2: data[key] = parse_shallow(le[6][0].data); break; + case 3: + data[key] = parse_shallow(le[5][0].data); + break; default: throw type; } @@ -913,7 +993,7 @@ function parse_TST_Tile(M, root) { }; } function parse_TST_TableModelArchive(M, root, ws) { - var _a, _b, _c, _d, _e, _f; + var _a, _b, _c, _d, _e, _f, _g, _h; var pb = parse_shallow(root.data); var range = { s: { r: 0, c: 0 }, e: { r: 0, c: 0 } }; range.e.r = (varint_to_i32(pb[6][0].data) >>> 0) - 1; @@ -928,11 +1008,15 @@ function parse_TST_TableModelArchive(M, root, ws) { var lut = numbers_lut_new(); if ((_a = store[4]) == null ? void 0 : _a[0]) lut.sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); - if ((_b = store[11]) == null ? void 0 : _b[0]) + if ((_b = store[6]) == null ? void 0 : _b[0]) + lut.fmla = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[6][0].data)][0]); + if ((_c = store[11]) == null ? void 0 : _c[0]) lut.ofmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[11][0].data)][0]); - if ((_c = store[17]) == null ? void 0 : _c[0]) + if ((_d = store[12]) == null ? void 0 : _d[0]) + lut.ferr = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[12][0].data)][0]); + if ((_e = store[17]) == null ? void 0 : _e[0]) lut.rsst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]); - if ((_d = store[22]) == null ? void 0 : _d[0]) + if ((_f = store[22]) == null ? void 0 : _f[0]) lut.nfmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[22][0].data)][0]); var tile = parse_shallow(store[3][0].data); var _R = 0; @@ -959,12 +1043,12 @@ function parse_TST_TableModelArchive(M, root, ws) { }); _R += _tile.nrows; }); - if ((_e = store[13]) == null ? void 0 : _e[0]) { + if ((_g = store[13]) == null ? void 0 : _g[0]) { var ref = M[parse_TSP_Reference(store[13][0].data)][0]; var mtype = varint_to_i32(ref.meta[1][0].data); if (mtype != 6144) throw new Error("Expected merge type 6144, found ".concat(mtype)); - ws["!merges"] = (_f = parse_shallow(ref.data)) == null ? void 0 : _f[1].map(function(pi) { + ws["!merges"] = (_h = parse_shallow(ref.data)) == null ? void 0 : _h[1].map(function(pi) { var merge = parse_shallow(pi.data); var origin = u8_to_dataview(parse_shallow(merge[1][0].data)[1][0].data), size = u8_to_dataview(parse_shallow(merge[2][0].data)[1][0].data); return { @@ -1079,7 +1163,7 @@ function parse_numbers_iwa(cfb, opts) { throw new Error("Cannot find Document root"); return parse_TN_DocumentArchive(M, docroot, opts); } -function write_TST_TileRowInfo(data, SST, wide) { +function write_TST_TileRowInfo(data, SST, RSST, wide) { var _a, _b; var tri = [ [], @@ -1113,7 +1197,7 @@ function write_TST_TileRowInfo(data, SST, wide) { var _dv = u8_to_dataview(tri[4][0].data), _last_offset = 0, _cell_storage = []; var width = wide ? 4 : 1; for (var C = 0; C < data.length; ++C) { - if (data[C] == null) { + if (data[C] == null || data[C].t == "z" || data[C].t == "e") { dv.setUint16(C * 2, 65535, true); _dv.setUint16(C * 2, 65535); continue; @@ -1121,25 +1205,23 @@ function write_TST_TileRowInfo(data, SST, wide) { dv.setUint16(C * 2, last_offset / width, true); _dv.setUint16(C * 2, _last_offset / width, true); var celload, _celload; - switch (typeof data[C]) { - case "string": - celload = write_new_storage({ t: "s", v: data[C] }, SST); - _celload = write_old_storage({ t: "s", v: data[C] }, SST); - break; - case "number": - celload = write_new_storage({ t: "n", v: data[C] }, SST); - _celload = write_old_storage({ t: "n", v: data[C] }, SST); - break; - case "boolean": - celload = write_new_storage({ t: "b", v: data[C] }, SST); - _celload = write_old_storage({ t: "b", v: data[C] }, SST); - break; - default: - if (data[C] instanceof Date) { - celload = write_new_storage({ t: "s", v: data[C].toISOString() }, SST); - _celload = write_old_storage({ t: "s", v: data[C].toISOString() }, SST); + switch (data[C].t) { + case "d": + if (data[C].v instanceof Date) { + celload = write_new_storage({ t: "s", v: data[C].v.toISOString() }, SST, RSST); + _celload = write_old_storage({ t: "s", v: data[C].v.toISOString() }, SST, RSST); break; } + celload = write_new_storage(data[C], SST, RSST); + _celload = write_old_storage(data[C], SST, RSST); + break; + case "s": + case "n": + case "b": + celload = write_new_storage(data[C], SST, RSST); + _celload = write_old_storage(data[C], SST, RSST); + break; + default: throw new Error("Unsupported value " + data[C]); } cell_storage.push(celload); @@ -1260,6 +1342,38 @@ function numbers_iwa_find(cfb, deps, id) { }); return ainfo; } +function numbers_add_msg(cfb, type, msg, path, deps, id) { + if (!id) + id = get_unique_msgid({ deps: [], location: "", type: type }, deps); + var loc = "".concat(path, "-").concat(id, ".iwa"); + deps[id].location = "Root Entry" + loc; + CFB.utils.cfb_add(cfb, loc, compress_iwa_file(write_iwa_file([{ + id: id, + messages: [write_iwam(type, write_shallow(msg))] + }]))); + var newloc = loc.replace(/^[\/]/, "").replace(/^Index\//, "").replace(/\.iwa$/, ""); + numbers_iwa_doit(cfb, deps, 2, function(ai) { + var mlist = parse_shallow(ai.messages[0].data); + mlist[3].push({ type: 2, data: write_shallow([ + [], + [{ type: 0, data: write_varint49(id) }], + [{ type: 2, data: stru8(newloc.replace(/-.*$/, "")) }], + [{ type: 2, data: stru8(newloc) }], + [{ type: 2, data: new Uint8Array([2, 0, 0]) }], + [{ type: 2, data: new Uint8Array([2, 0, 0]) }], + [], + [], + [], + [], + [{ type: 0, data: write_varint49(0) }], + [], + [{ type: 0, data: write_varint49(0) }] + ]) }); + mlist[1] = [{ type: 0, data: write_varint49(Math.max(id + 1, varint_to_i32(mlist[1][0].data))) }]; + ai.messages[0].data = write_shallow(mlist); + }); + return id; +} function numbers_add_ws(cfb, deps, wsidx) { var sheetref = -1, newsheetref = -1; var remap = {}; @@ -1362,7 +1476,7 @@ function numbers_add_ws(cfb, deps, wsidx) { numbers_iwa_doit(cfb, deps, tmaref, function(tmaroot, arch) { var _a, _b; var tma = parse_shallow(tmaroot.messages[0].data); - var uuid = u8str(tma[1][0].data), new_uuid = uuid.replace(/-[A-Z0-9]*/, "-".concat(wsidx.toString(16).padStart(4, "0"))); + var uuid = u8str(tma[1][0].data), new_uuid = uuid.replace(/-[A-Z0-9]*/, "-".concat(("0000" + wsidx.toString(16)).slice(-4))); tma[1][0].data = stru8(new_uuid); [12, 13, 29, 31, 32, 33, 39, 44, 47, 81, 82, 84].forEach(function(n) { return delete tma[n]; @@ -1648,8 +1762,27 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) { } if (trunc) console.error("Truncating to ".concat(encode_range(range))); - var data = sheet_to_json(ws, { range: range, header: 1 }); + var data = []; + if (ws["!data"]) + data = ws["!data"]; + else { + var colstr = []; + for (var _C = 0; _C <= range.e.c; ++_C) + colstr[_C] = encode_col(_C); + for (var R_ = 0; R_ <= range.e.r; ++R_) { + data[R_] = []; + var _R = "" + (R_ + 1); + for (_C = 0; _C <= range.e.c; ++_C) { + var _cell = ws[colstr[_C] + _R]; + if (!_cell) + continue; + data[R_][_C] = _cell; + } + } + } + sheet_to_json(ws, { range: range, header: 1 }); var SST = ["~Sh33tJ5~"]; + var RSST = [{ v: "~54ee77S~", l: "https://sheetjs.com/" }]; var loc = deps[tmaref].location; loc = loc.replace(/^Root Entry\//, ""); loc = loc.replace(/^Index\//, "").replace(/\.iwa$/, ""); @@ -1747,7 +1880,7 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) { [{ type: 0, data: write_varint49(USE_WIDE_ROWS ? 1 : 0) }] ]; for (var R = tidx * tstride; R <= Math.min(range.e.r, (tidx + 1) * tstride - 1); ++R) { - var tilerow = write_TST_TileRowInfo(data[R], SST, USE_WIDE_ROWS); + var tilerow = write_TST_TileRowInfo(data[R], SST, RSST, USE_WIDE_ROWS); tilerow[1][0].data = write_varint49(R - tidx * tstride); tiledata[5].push({ data: write_shallow(tilerow), type: 2 }); } @@ -1884,6 +2017,166 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) { } sstroot.messages[0].data = write_shallow(sstdata); }); + var rsstref = parse_TSP_Reference(store[17][0].data); + numbers_iwa_doit(cfb, deps, rsstref, function(rsstroot) { + var rsstdata = parse_shallow(rsstroot.messages[0].data); + rsstdata[3] = []; + var style_indices = [ + 904980, + 903835, + 903815, + 903845 + ]; + RSST.forEach(function(rsst, i) { + if (i == 0) + return; + var tswpsa = [ + [], + [{ type: 0, data: new Uint8Array([5]) }], + [], + [{ type: 2, data: stru8(rsst.v) }] + ]; + tswpsa[10] = [{ type: 0, data: new Uint8Array([1]) }]; + tswpsa[19] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 18, 2, 101, 110]) }]; + tswpsa[5] = [{ type: 2, data: new Uint8Array([10, 8, 8, 0, 18, 4, 8, 155, 149, 55]) }]; + tswpsa[2] = [{ type: 2, data: new Uint8Array([8, 148, 158, 55]) }]; + tswpsa[6] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 16, 0, 24, 0]) }]; + tswpsa[7] = [{ type: 2, data: new Uint8Array([10, 8, 8, 0, 18, 4, 8, 135, 149, 55]) }]; + tswpsa[8] = [{ type: 2, data: new Uint8Array([10, 8, 8, 0, 18, 4, 8, 165, 149, 55]) }]; + tswpsa[14] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 16, 0, 24, 0]) }]; + tswpsa[24] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 16, 0, 24, 0]) }]; + var tswpsaid = get_unique_msgid({ deps: [], location: "", type: 2001 }, deps); + var tswpsarefs = []; + if (rsst.l) { + var newhlinkid = numbers_add_msg(cfb, 2032, [ + [], + [], + [{ type: 2, data: stru8(rsst.l) }] + ], "/Index/Tables/DataList", deps); + tswpsa[11] = []; + var smartfield = [[], []]; + if (!smartfield[1]) + smartfield[1] = []; + smartfield[1].push({ type: 2, data: write_shallow([ + [], + [{ type: 0, data: write_varint49(0) }], + [{ type: 2, data: write_TSP_Reference(newhlinkid) }] + ]) }); + tswpsa[11][0] = { type: 2, data: write_shallow(smartfield) }; + tswpsarefs.push(newhlinkid); + } + numbers_add_msg(cfb, 2001, tswpsa, "/Index/Tables/DataList", deps, tswpsaid); + numbers_iwa_doit(cfb, deps, tswpsaid, function(iwa) { + style_indices.forEach(function(ref) { + return numbers_add_oref(iwa, ref); + }); + tswpsarefs.forEach(function(ref) { + return numbers_add_oref(iwa, ref); + }); + }); + var rtpaid = numbers_add_msg(cfb, 6218, [ + [], + [{ type: 2, data: write_TSP_Reference(tswpsaid) }], + [], + [{ type: 2, data: new Uint8Array([13, 255, 255, 255, 0, 18, 10, 16, 255, 255, 1, 24, 255, 255, 255, 255, 7]) }] + ], "/Index/Tables/DataList", deps); + numbers_iwa_doit(cfb, deps, rtpaid, function(iwa) { + return numbers_add_oref(iwa, tswpsaid); + }); + rsstdata[3].push({ type: 2, data: write_shallow([ + [], + [{ type: 0, data: write_varint49(i) }], + [{ type: 0, data: write_varint49(1) }], + [], + [], + [], + [], + [], + [], + [{ type: 2, data: write_TSP_Reference(rtpaid) }] + ]) }); + numbers_add_oref(rsstroot, rtpaid); + numbers_iwa_doit(cfb, deps, 2, function(ai) { + var mlist = parse_shallow(ai.messages[0].data); + var loc2 = deps[rsstref].location.replace(/^Root Entry\//, "").replace(/^Index\//, "").replace(/\.iwa$/, ""); + var parentidx = mlist[3].findIndex(function(m) { + var _a, _b; + var mm = parse_shallow(m.data); + if ((_a = mm[3]) == null ? void 0 : _a[0]) + return u8str(mm[3][0].data) == loc2; + if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc2) + return true; + return false; + }); + var parent = parse_shallow(mlist[3][parentidx].data); + if (!parent[6]) + parent[6] = []; + parent[6].push({ + type: 2, + data: write_shallow([ + [], + [{ type: 0, data: write_varint49(rtpaid) }] + ]) + }); + mlist[3][parentidx].data = write_shallow(parent); + loc2 = deps[rtpaid].location.replace(/^Root Entry\//, "").replace(/^Index\//, "").replace(/\.iwa$/, ""); + parentidx = mlist[3].findIndex(function(m) { + var _a, _b; + var mm = parse_shallow(m.data); + if ((_a = mm[3]) == null ? void 0 : _a[0]) + return u8str(mm[3][0].data) == loc2; + if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc2) + return true; + return false; + }); + parent = parse_shallow(mlist[3][parentidx].data); + if (!parent[6]) + parent[6] = []; + parent[6].push({ + type: 2, + data: write_shallow([ + [], + [{ type: 0, data: write_varint49(tswpsaid) }] + ]) + }); + mlist[3][parentidx].data = write_shallow(parent); + loc2 = deps[tswpsaid].location.replace(/^Root Entry\//, "").replace(/^Index\//, "").replace(/\.iwa$/, ""); + parentidx = mlist[3].findIndex(function(m) { + var _a, _b; + var mm = parse_shallow(m.data); + if ((_a = mm[3]) == null ? void 0 : _a[0]) + return u8str(mm[3][0].data) == loc2; + if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc2) + return true; + return false; + }); + parent = parse_shallow(mlist[3][parentidx].data); + if (!parent[6]) + parent[6] = []; + tswpsarefs.forEach(function(id) { + return parent[6].push({ + type: 2, + data: write_shallow([ + [], + [{ type: 0, data: write_varint49(id) }] + ]) + }); + }); + style_indices.forEach(function(n) { + return parent[6].push({ + type: 2, + data: write_shallow([ + [], + [{ type: 0, data: write_varint49(n) }] + ]) + }); + }); + mlist[3][parentidx].data = write_shallow(parent); + ai.messages[0].data = write_shallow(mlist); + }); + }); + rsstroot.messages[0].data = write_shallow(rsstdata); + }); } pb[4][0].data = write_shallow(store); } diff --git a/modules/83_numbers.ts b/modules/83_numbers.ts index d260418..43c8bca 100644 --- a/modules/83_numbers.ts +++ b/modules/83_numbers.ts @@ -134,14 +134,12 @@ function write_packed_varints(nums: number[]): Uint8Array { /** Parse a 32-bit signed integer from the raw varint */ function varint_to_i32(buf: Uint8Array): number { - var l = 0, i32 = buf[l] & 0x7F; - varint: if(buf[l++] >= 0x80) { - i32 |= (buf[l] & 0x7F) << 7; if(buf[l++] < 0x80) break varint; - i32 |= (buf[l] & 0x7F) << 14; if(buf[l++] < 0x80) break varint; - i32 |= (buf[l] & 0x7F) << 21; if(buf[l++] < 0x80) break varint; - i32 |= (buf[l] & 0x7F) << 28; - } - return i32; + var l = 0, + i32 = (buf[l] & 0x7F) ; if(buf[l++] < 0x80) return i32; + i32 |= (buf[l] & 0x7F) << 7; if(buf[l++] < 0x80) return i32; + i32 |= (buf[l] & 0x7F) << 14; if(buf[l++] < 0x80) return i32; + i32 |= (buf[l] & 0x7F) << 21; if(buf[l++] < 0x80) return i32; + i32 |= (buf[l] & 0x0F) << 28; return i32; } /** Parse a 64-bit unsigned integer as a pair */ function varint_to_u64(buf: Uint8Array): [number, number] { @@ -382,18 +380,31 @@ function compress_iwa_file(buf: Uint8Array): Uint8Array { } //< ({ sst: [], rsst: [], ofmt: [], nfmt: [] }); +var numbers_lut_new = (): DataLUT => ({ sst: [], rsst: [], ofmt: [], nfmt: [], fmla: [], ferr: [] }); function numbers_format_cell(cell: CellObject, t: number, flags: number, ofmt: ProtoMessage, nfmt: ProtoMessage): void { var ctype = t & 0xFF, ver = t >> 8; @@ -499,8 +510,11 @@ function parse_old_storage(buf: Uint8Array, lut: DataLUT, v: 0|1|2|3|4): CellObj case 7: ret = { t: "n", v: ieee }; break; // duration in seconds case 8: ret = { t: "e", v: 0}; break; // "formula error" TODO: enumerate and map errors to csf equivalents case 9: { // "rich text" - if(ridx > -1) ret = { t: "s", v: lut.rsst[ridx] }; - else throw new Error(`Unsupported cell type ${buf[subarray](0,4)}`); + if(ridx > -1) { + var rts = lut.rsst[ridx]; + ret = { t: "s", v: rts.v }; + if(rts.l) ret.l = { Target: rts.l }; + } else throw new Error(`Unsupported cell type ${buf[subarray](0,4)}`); } break; default: throw new Error(`Unsupported cell type ${buf[subarray](0,4)}`); } @@ -518,7 +532,7 @@ function parse_new_storage(buf: Uint8Array, lut: DataLUT): CellObject | void { var fields = dv.getUint32(8, true); var doff = 12; - var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1); + var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1), eidx = -1, fidx = -1; // 0x00001F data if(fields & 0x000001) { d128 = readDecimal128LE(buf, doff); doff += 16; } @@ -527,6 +541,14 @@ function parse_new_storage(buf: Uint8Array, lut: DataLUT): CellObject | void { if(fields & 0x000008) { sidx = dv.getUint32(doff, true); doff += 4; } if(fields & 0x000010) { ridx = dv.getUint32(doff, true); doff += 4; } + // 0x0001E0 styling + doff += popcnt(fields & 0x0001E0) * 4; + + // 0x000E00 formula + if(fields & 0x000200) { fidx = dv.getUint32(doff, true); doff += 4; } + doff += popcnt(fields & 0x000400) * 4; + if(fields & 0x000800) { eidx = dv.getUint32(doff, true); doff += 4; } + var ret: CellObject; var t = buf[1]; switch(t) { @@ -537,17 +559,19 @@ function parse_new_storage(buf: Uint8Array, lut: DataLUT): CellObject | void { case 6: ret = { t: "b", v: ieee > 0 }; break; // boolean case 7: ret = { t: "n", v: ieee }; break; // duration in "s", fixed later case 8: ret = { t: "e", v: 0 }; break; // "formula error" TODO: enumerate and map errors to csf equivalents - case 9: ret = { t: "s", v: lut.rsst[ridx] }; break;// "rich text" + case 9: { + if(ridx > -1) { + var rts = lut.rsst[ridx]; + ret = { t: "s", v: rts.v }; + if(rts.l) ret.l = { Target: rts.l }; + } else throw new Error(`Unsupported cell type ${buf[1]} : ${fields & 0x1F} : ${buf[subarray](0,4)}`); + } break; // "rich text" case 10: ret = { t: "n", v: d128 }; break; // currency default: throw new Error(`Unsupported cell type ${buf[1]} : ${fields & 0x1F} : ${buf[subarray](0,4)}`); } - // 0x0001E0 styling - - // 0x000E00 formula - // 0x001000 something related to cell format - doff += popcnt(fields & 0x001FE0) * 4; + doff += popcnt(fields & 0x001000) * 4; /* TODO: stress test if a cell can have multiple sub-type formats */ // 0x07E000 formats @@ -562,34 +586,48 @@ function parse_new_storage(buf: Uint8Array, lut: DataLUT): CellObject | void { } /** Write a cell "new storage" (version 5) */ -function write_new_storage(cell: CellObject, sst: string[]): Uint8Array { +function write_new_storage(cell: CellObject, sst: string[], rsst: RichText[]): Uint8Array { var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, flags = 0; out[0] = 5; switch(cell.t) { case "n": out[1] = 2; writeDecimal128LE(out, l, cell.v as number); flags |= 1; l += 16; break; case "b": out[1] = 6; dv.setFloat64(l, cell.v ? 1 : 0, true); flags |= 2; l += 8; break; - case "s": + case "s": { var s = cell.v == null ? "" : String(cell.v); - var isst = sst.indexOf(s); - if(isst == -1) sst[isst = sst.length] = s; - out[1] = 3; dv.setUint32(l, isst, true); flags |= 8; l += 4; break; + if(cell.l) { + var irsst = rsst.findIndex(v => v.v == s && v.l == cell.l?.Target); + if(irsst == -1) rsst[irsst = rsst.length] = { v: s , l: cell.l.Target }; + out[1] = 9; dv.setUint32(l, irsst, true); flags |= 0x10; l += 4; + } else { + var isst = sst.indexOf(s); + if(isst == -1) sst[isst = sst.length] = s; + out[1] = 3; dv.setUint32(l, isst, true); flags |= 8; l += 4; + } + } break; default: throw "unsupported cell type " + cell.t; } dv.setUint32(8, flags, true); return out[subarray](0, l); } /** Write a cell "old storage" (version 4) */ -function write_old_storage(cell: CellObject, sst: string[]): Uint8Array { +function write_old_storage(cell: CellObject, sst: string[], rsst: RichText[]): Uint8Array { var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, flags = 0; out[0] = 4; switch(cell.t) { - case "n": out[2] = 2; dv.setFloat64(l, cell.v as number, true); flags |= 0x20; l += 8; break; - case "b": out[2] = 6; dv.setFloat64(l, cell.v ? 1 : 0, true); flags |= 0x20; l += 8; break; - case "s": + case "n": out[1] = 2; dv.setFloat64(l, cell.v as number, true); flags |= 0x20; l += 8; break; + case "b": out[1] = 6; dv.setFloat64(l, cell.v ? 1 : 0, true); flags |= 0x20; l += 8; break; + case "s": { var s = cell.v == null ? "" : String(cell.v); - var isst = sst.indexOf(s); - if(isst == -1) sst[isst = sst.length] = s; - out[2] = 3; dv.setUint32(l, isst, true); flags |= 0x10; l += 4; break; + if(cell.l) { + var irsst = rsst.findIndex(v => v.v == s && v.l == cell.l?.Target); + if(irsst == -1) rsst[irsst = rsst.length] = { v: s, l: cell.l.Target }; + out[1] = 9; dv.setUint32(l, irsst, true); flags |= 0x200; l += 4; + } else { + var isst = sst.indexOf(s); + if(isst == -1) sst[isst = sst.length] = s; + out[1] = 3; dv.setUint32(l, isst, true); flags |= 0x10; l += 4; + } + } break; default: throw "unsupported cell type " + cell.t; } dv.setUint32(8, flags, true); @@ -657,7 +695,7 @@ function parse_TST_TableDataList(M: MessageSpace, root: IWAMessage): any[] { switch(type) { case 1: data[key] = u8str(le[3][0].data); break; case 8: { - // .TSP.RichTextPayloadArchive + // .TST.RichTextPayloadArchive var rt = M[parse_TSP_Reference(le[9][0].data)][0]; var rtp = parse_shallow(rt.data); @@ -667,9 +705,37 @@ function parse_TST_TableDataList(M: MessageSpace, root: IWAMessage): any[] { if(mtype != 2001) throw new Error(`2000 unexpected reference to ${mtype}`); var tswpsa = parse_shallow(rtpref.data); - data[key] = tswpsa[3].map(x => u8str(x.data)).join(""); + var richtext: RichText = { v: tswpsa[3].map(x => u8str(x.data)).join("") }; + data[key] = richtext; + + /* NOTE: NUMBERS rich text styling is spiritually similar to XLS */ + sfields: if(tswpsa?.[11]?.[0]) { + // .TSWP.ObjectAttributeTable + var smartfields = parse_shallow(tswpsa[11][0].data)?.[1]; + if(!smartfields) break sfields; + smartfields.forEach(sf => { + // .TSWP.ObjectAttributeTable.ObjectAttribute + var attr = parse_shallow(sf.data); + if(attr[2]?.[0]) { + var obj = M[parse_TSP_Reference(attr[2]?.[0].data)][0]; + var objtype = varint_to_i32(obj.meta[1][0].data); + switch(objtype) { + case 2032: // .TSWP.HyperlinkFieldArchive + var hlink = parse_shallow(obj.data); + /* TODO: once run-level links are supported, fix this cell assignment */ + if(hlink?.[2]?.[0] && !richtext.l) richtext.l = u8str(hlink[2][0].data); + break; + case 2039: // .TSWP.UnsupportedHyperlinkFieldArchive + /* TODO: "Sheet" internal links */ + break; + default: console.log(`unrecognized ObjectAttribute type ${objtype}`); + } + } + }); + } } break; case 2: data[key] = parse_shallow(le[6][0].data); break; + case 3: data[key] = parse_shallow(le[5][0].data); break; default: throw type; } }); @@ -751,8 +817,10 @@ function parse_TST_TableModelArchive(M: MessageSpace, root: IWAMessage, ws: Work // .TST.DataStore var store = parse_shallow(pb[4][0].data); var lut: DataLUT = numbers_lut_new(); - if(store[4]?.[0]) lut.sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); + if(store[4]?.[0]) lut.sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); + if(store[6]?.[0]) lut.fmla = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[6][0].data)][0]); if(store[11]?.[0]) lut.ofmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[11][0].data)][0]); + if(store[12]?.[0]) lut.ferr = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[12][0].data)][0]); if(store[17]?.[0]) lut.rsst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]); if(store[22]?.[0]) lut.nfmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[22][0].data)][0]); @@ -905,7 +973,7 @@ interface DependentInfo { type: number; } /** Write .TST.TileRowInfo */ -function write_TST_TileRowInfo(data: any[], SST: string[], wide: boolean): ProtoMessage { +function write_TST_TileRowInfo(data: CellObject[], SST: string[], RSST: RichText[], wide: boolean): ProtoMessage { var tri: ProtoMessage = [ [], [ { type: 0, data: write_varint49(0) }], @@ -937,30 +1005,27 @@ function write_TST_TileRowInfo(data: any[], SST: string[], wide: boolean): Proto var _dv = u8_to_dataview(tri[4][0].data), _last_offset = 0, _cell_storage: Uint8Array[] = []; var width = wide ? 4 : 1; for(var C = 0; C < data.length; ++C) { - if(data[C] == null) { dv.setUint16(C*2, 0xFFFF, true); _dv.setUint16(C*2, 0xFFFF); continue; } + if(data[C] == null || data[C].t == "z" || data[C].t == "e") { dv.setUint16(C*2, 0xFFFF, true); _dv.setUint16(C*2, 0xFFFF); continue; } dv.setUint16(C*2, last_offset / width, true); /*if(!wide)*/ _dv.setUint16(C*2, _last_offset / width, true); var celload: Uint8Array, _celload: Uint8Array; - switch(typeof data[C]) { - case "string": - celload = write_new_storage({t: "s", v: data[C]}, SST); - /*if(!wide)*/ _celload = write_old_storage({t: "s", v: data[C]}, SST); - break; - case "number": - celload = write_new_storage({t: "n", v: data[C]}, SST); - /*if(!wide)*/ _celload = write_old_storage({t: "n", v: data[C]}, SST); - break; - case "boolean": - celload = write_new_storage({t: "b", v: data[C]}, SST); - /*if(!wide)*/ _celload = write_old_storage({t: "b", v: data[C]}, SST); - break; - default: + switch(data[C].t) { + case "d": // TODO: write the actual date code - if(data[C] instanceof Date) { - celload = write_new_storage({t: "s", v: (data[C] as Date).toISOString()}, SST); - /*if(!wide)*/ _celload = write_old_storage({t: "s", v: (data[C] as Date).toISOString()}, SST); + if(data[C].v instanceof Date) { + celload = write_new_storage({t: "s", v: (data[C].v as Date).toISOString()}, SST, RSST); + /*if(!wide)*/ _celload = write_old_storage({t: "s", v: (data[C].v as Date).toISOString()}, SST, RSST); break; } + /* TODO: can esbuild preserve falls through comments ? */ + celload = write_new_storage(data[C], SST, RSST); + /*if(!wide)*/ _celload = write_old_storage(data[C], SST, RSST); + break; + case "s": case "n": case "b": + celload = write_new_storage(data[C], SST, RSST); + /*if(!wide)*/ _celload = write_old_storage(data[C], SST, RSST); + break; + default: throw new Error("Unsupported value " + data[C]); } cell_storage.push(celload); last_offset += celload.length; @@ -1034,7 +1099,6 @@ function build_numbers_deps(cfb: CFB$Container): Dependents { }); }); }); - return dependents; } @@ -1083,6 +1147,36 @@ function numbers_iwa_find(cfb: CFB$Container, deps: Dependents, id: number) { return ainfo; } +function numbers_add_msg(cfb: CFB$Container, type: number, msg: ProtoMessage, path: string, deps: Dependents, id?: number): number { + if(!id) id = get_unique_msgid({ deps: [], location: "", type }, deps); + var loc = `${path}-${id}.iwa`; + deps[id].location = "Root Entry" + loc; + CFB.utils.cfb_add(cfb, loc, compress_iwa_file(write_iwa_file([{ + id, + messages: [ write_iwam(type, write_shallow(msg)) ] + }]))); + var newloc = loc.replace(/^[\/]/, "").replace(/^Index\//, "").replace(/\.iwa$/,""); + numbers_iwa_doit(cfb, deps, 2, ai => { + var mlist = parse_shallow(ai.messages[0].data); + + mlist[3].push({type: 2, data: write_shallow([ [], + [{type: 0, data: write_varint49(id as number)}], + [{type: 2, data: stru8(newloc.replace(/-.*$/, "")) }], + [{type: 2, data: stru8(newloc)}], + [{type: 2, data: new Uint8Array([2, 0, 0])}], + [{type: 2, data: new Uint8Array([2, 0, 0])}], + [], [], [], [], + [{type: 0, data: write_varint49(0)}], + [], + [{type: 0, data: write_varint49(0 /* TODO: save_token */)}], + ])}); + mlist[1] = [{type: 0, data: write_varint49(Math.max((id as number) + 1, varint_to_i32(mlist[1][0].data) ))}]; + + ai.messages[0].data = write_shallow(mlist); + }) + return id; +} + /** Deep copy of the essential parts of a worksheet */ function numbers_add_ws(cfb: CFB$Container, deps: Dependents, wsidx: number) { var sheetref = -1, newsheetref = -1; @@ -1204,7 +1298,7 @@ function numbers_add_ws(cfb: CFB$Container, deps: Dependents, wsidx: number) { numbers_iwa_doit(cfb, deps, tmaref, (tmaroot: IWAArchiveInfo, arch: IWAArchiveInfo[]) => { /* TODO: formulae currently break due to missing CE details */ var tma = parse_shallow(tmaroot.messages[0].data); - var uuid = u8str(tma[1][0].data), new_uuid = uuid.replace(/-[A-Z0-9]*/, `-${wsidx.toString(16).padStart(4, "0")}`); + var uuid = u8str(tma[1][0].data), new_uuid = uuid.replace(/-[A-Z0-9]*/, `-${("0000" + wsidx.toString(16)).slice(-4)}`); tma[1][0].data = stru8(new_uuid); /* NOTE: These lists should be revisited every time the template is changed */ @@ -1271,7 +1365,7 @@ function numbers_add_ws(cfb: CFB$Container, deps: Dependents, wsidx: number) { newloc = newloc.replace(/^Root Entry\//,""); // NOTE: the Root Entry prefix is an artifact of the CFB container library newloc = newloc.replace(/^Index\//, "").replace(/\.iwa$/,""); - numbers_iwa_doit(cfb, deps, 2, (ai => { + numbers_iwa_doit(cfb, deps, 2, ai => { var mlist = parse_shallow(ai.messages[0].data); mlist[3].push({type: 2, data: write_shallow([ [], @@ -1309,7 +1403,7 @@ function numbers_add_ws(cfb: CFB$Container, deps: Dependents, wsidx: number) { mlist[3][parentidx].data = write_shallow(parent); ai.messages[0].data = write_shallow(mlist); - })); + }); } store[n][0].data = write_TSP_Reference(newref); }); @@ -1338,8 +1432,7 @@ function numbers_add_ws(cfb: CFB$Container, deps: Dependents, wsidx: number) { numbers_iwa_doit(cfb, deps, 2, (ai => { var mlist = parse_shallow(ai.messages[0].data); - mlist[3].push({type: 2, data: write_shallow([ - [], + mlist[3].push({type: 2, data: write_shallow([ [], [{type: 0, data: write_varint49(newref)}], [{type: 2, data: stru8(newloc.replace(/-.*$/, "")) }], [{type: 2, data: stru8(newloc)}], @@ -1402,8 +1495,7 @@ function numbers_add_ws(cfb: CFB$Container, deps: Dependents, wsidx: number) { numbers_iwa_doit(cfb, deps, 2, (ai => { var mlist = parse_shallow(ai.messages[0].data); - mlist[3].push({type: 2, data: write_shallow([ - [], + mlist[3].push({type: 2, data: write_shallow([ [], [{type: 0, data: write_varint49(newtileref)}], [{type: 2, data: stru8("Tables/Tile") }], [{type: 2, data: stru8(`Tables/Tile-${newtileref}`)}], @@ -1491,8 +1583,23 @@ function write_numbers_tma(cfb: CFB$Container, deps: Dependents, ws: WorkSheet, if(trunc) console.error(`Truncating to ${encode_range(range)}`); /* preprocess data and build up shared string table */ - var data = sheet_to_json(ws, { range, header: 1 }); - var SST = ["~Sh33tJ5~"]; + var data: CellObject[][] = []; + if(ws["!data"]) data = ws["!data"]; + else { + var colstr: string[] = []; + for(var _C = 0; _C <= range.e.c; ++_C) colstr[_C] = encode_col(_C); + for(var R_ = 0; R_ <= range.e.r; ++R_) { + data[R_] = []; + var _R = "" + (R_+1); + for(_C = 0; _C <= range.e.c; ++_C) { + var _cell = ws[colstr[_C] + _R]; + if(!_cell) continue; + data[R_][_C] = _cell; + } + } + } sheet_to_json(ws, { range, header: 1 }); + var SST: string[] = ["~Sh33tJ5~"]; + var RSST: RichText[] = [{v:"~54ee77S~", l: "https://sheetjs.com/"}]; /* identifier for finding the TableModelArchive in the archive */ var loc = deps[tmaref].location; @@ -1600,8 +1707,7 @@ function write_numbers_tma(cfb: CFB$Container, deps: Dependents, ws: WorkSheet, deps[newtileid].location = `Root Entry/Index/Tables/Tile-${newtileid}.iwa`; /* create new tile */ - var tiledata: ProtoMessage = [ - [], + var tiledata: ProtoMessage = [ [], [{type: 0, data: write_varint49(0 /*range.e.c + 1*/)}], [{type: 0, data: write_varint49(Math.min(range.e.r + 1, (tidx + 1) * tstride))}], [{type: 0, data: write_varint49(0/*cnt*/)}], @@ -1612,14 +1718,13 @@ function write_numbers_tma(cfb: CFB$Container, deps: Dependents, ws: WorkSheet, [{type: 0, data: write_varint49(USE_WIDE_ROWS ? 1 : 0)}] ]; for(var R = tidx * tstride; R <= Math.min(range.e.r, (tidx + 1) * tstride - 1); ++R) { - var tilerow = write_TST_TileRowInfo(data[R], SST, USE_WIDE_ROWS); + var tilerow = write_TST_TileRowInfo(data[R], SST, RSST, USE_WIDE_ROWS); tilerow[1][0].data = write_varint49(R - tidx * tstride); tiledata[5].push({data: write_shallow(tilerow), type: 2}); } /* add to tiles */ - tilestore[1].push({type: 2, data: write_shallow([ - [], + tilestore[1].push({type: 2, data: write_shallow([ [], [{type: 0, data: write_varint49(tidx)}], [{type: 2, data: write_TSP_Reference(newtileid)}] ])}); @@ -1635,19 +1740,15 @@ function write_numbers_tma(cfb: CFB$Container, deps: Dependents, ws: WorkSheet, /* update metadata -- TODO: can this have an id other than 2? */ numbers_iwa_doit(cfb, deps, 2, (ai => { var mlist = parse_shallow(ai.messages[0].data); - mlist[3].push({type: 2, data: write_shallow([ - [], + mlist[3].push({type: 2, data: write_shallow([ [], [{type: 0, data: write_varint49(newtileid)}], [{type: 2, data: stru8("Tables/Tile") }], [{type: 2, data: stru8(`Tables/Tile-${newtileid}`)}], [{type: 2, data: new Uint8Array([2, 0, 0])}], [{type: 2, data: new Uint8Array([2, 0, 0])}], - [], - [], - [], - [], + [], [], [], [], // skip fields 6-9 [{type: 0, data: write_varint49(0)}], - [], + [], // skip field 11 [{type: 0, data: write_varint49(save_token)}], ])}); mlist[1] = [{type: 0, data: write_varint49(Math.max(newtileid + 1, varint_to_i32(mlist[1][0].data) ))}]; @@ -1663,8 +1764,7 @@ function write_numbers_tma(cfb: CFB$Container, deps: Dependents, ws: WorkSheet, if(!parent[6]) parent[6] = []; parent[6].push({ type: 2, - data: write_shallow([ - [], + data: write_shallow([ [], [{type: 0, data: write_varint49(newtileid) }] ]) }); @@ -1677,8 +1777,7 @@ function write_numbers_tma(cfb: CFB$Container, deps: Dependents, ws: WorkSheet, numbers_add_oref(tmaroot, newtileid); /* add to row rbtree */ - rbtree[1].push({type: 2, data: write_shallow([ - [], + rbtree[1].push({type: 2, data: write_shallow([ [], [{ type: 0, data: write_varint49(tidx*tstride) }], [{ type: 0, data: write_varint49(tidx) }] ])}); @@ -1758,6 +1857,161 @@ function write_numbers_tma(cfb: CFB$Container, deps: Dependents, ws: WorkSheet, sstroot.messages[0].data = write_shallow(sstdata); }); + /* rebuild rich shared string table */ + var rsstref = parse_TSP_Reference(store[17][0].data); + numbers_iwa_doit(cfb, deps, rsstref, (rsstroot) => { + var rsstdata = parse_shallow(rsstroot.messages[0].data); + /* TODO: remove unused children */ + rsstdata[3] = []; + + /* TODO: this must be in sync with zahl */ + var style_indices = [ + 904980, // hardcoded stylesheet + 903835, // paragraph style + 903815, // list style + 903845 // character style + ]; + + RSST.forEach((rsst, i) => { + if(i == 0) return; + + /* create .TSWP.StorageArchive (2001) */ + var tswpsa: ProtoMessage = [ [], + [ { type: 0, data: new Uint8Array([5]) }], // .TSWP.StorageArchive.KindType CELL = 5 + [], + [ { type: 2, data: stru8(rsst.v) }] + ]; + tswpsa[10] = [ { type: 0, data: new Uint8Array([1]) } ]; + tswpsa[19] = [ { type: 2, data: new Uint8Array([10, 6, 8, 0, 18, 2, 101, 110])}]; // "en" + + // Even though field 5 `table_para_style` is "optional", Numbers 13 crashes without a clear error message if this is not included + tswpsa[5] = [ { type: 2, data: new Uint8Array([0x0a, 0x08, 0x08, 0x00, 0x12, 0x04, 0x08, 0x9b, 0x95, 0x37])}]; + + // At least Numbers tells you the file is corrupt if some of these fields are missing + tswpsa[2] = [ { type: 2, data: new Uint8Array([8, 148, 158, 55])}]; // msg 904980 TODO: verify in the zahl build script + tswpsa[6] = [ { type: 2, data: new Uint8Array([0x0a, 0x06, 0x08, 0x00, 0x10, 0x00, 0x18, 0x00])}]; + tswpsa[7] = [ { type: 2, data: new Uint8Array([0x0a, 0x08, 0x08, 0x00, 0x12, 0x04, 0x08, 0x87, 0x95, 0x37])}]; + tswpsa[8] = [ { type: 2, data: new Uint8Array([10, 8, 8, 0, 18, 4, 8, 165, 149, 55])}]; // TODO: revisit with mixed links + tswpsa[14] = [ { type: 2, data: new Uint8Array([0x0a, 0x06, 0x08, 0x00, 0x10, 0x00, 0x18, 0x00])}]; + tswpsa[24] = [ { type: 2, data: new Uint8Array([0x0a, 0x06, 0x08, 0x00, 0x10, 0x00, 0x18, 0x00])}]; + + var tswpsaid = get_unique_msgid({ deps: [], location: "", type: 2001 }, deps); + var tswpsarefs: number[] = []; + + /* add hyperlink if specified */ + if(rsst.l) { + /* create .TSWP.HyperlinkFieldArchive (2032) */ + var newhlinkid = numbers_add_msg(cfb, 2032, [ [], + [], + [ { type: 2, data: stru8(rsst.l) } ] + ], "/Index/Tables/DataList", deps); + /* add to smart field table */ + tswpsa[11] = []; + var smartfield: ProtoMessage = [[], []]; + if(!smartfield[1]) smartfield[1] = []; + + /* TODO: note that this applies one link to the entire text */ + smartfield[1].push({ type: 2, data: write_shallow([ [], + [ { type: 0, data: write_varint49(0) }], + [ { type: 2, data: write_TSP_Reference(newhlinkid) }] + ]) }); + tswpsa[11][0] = { type: 2, data: write_shallow(smartfield) }; + tswpsarefs.push(newhlinkid); + } + + /* add .TSWP.StorageArchive and object references */ + numbers_add_msg(cfb, 2001, tswpsa, "/Index/Tables/DataList", deps, tswpsaid); + numbers_iwa_doit(cfb, deps, tswpsaid, iwa => { + style_indices.forEach(ref => numbers_add_oref(iwa, ref)); + tswpsarefs.forEach(ref => numbers_add_oref(iwa, ref)); + }); + + /* create .TST.RichTextPayloadArchive (6218) */ + var rtpaid = numbers_add_msg(cfb, 6218, [ [], + [ { type: 2, data: write_TSP_Reference(tswpsaid) }], + [], + [{ type: 2, data: new Uint8Array([ 13, 255, 255, 255, 0, 18, 10, 16, 255, 255, 1, 24, 255, 255, 255, 255, 7 ]) }], + ], "/Index/Tables/DataList", deps); + numbers_iwa_doit(cfb, deps, rtpaid, iwa => numbers_add_oref(iwa, tswpsaid)); + + /* add to rsst */ + rsstdata[3].push({type: 2, data: write_shallow([ [], + [ { type: 0, data: write_varint49(i) } ], + [ { type: 0, data: write_varint49(1) } ], + [], [], [], [], [], [], // skip fields 3-8 + [ { type: 2, data: write_TSP_Reference(rtpaid) } ] + ])}); + numbers_add_oref(rsstroot, rtpaid); + + /* try to wire up other missing deps */ + numbers_iwa_doit(cfb, deps, 2, ai => { + var mlist = parse_shallow(ai.messages[0].data); + + /* rsst -> rich text payload */ + var loc = deps[rsstref].location.replace(/^Root Entry\//,"").replace(/^Index\//, "").replace(/\.iwa$/,""); + var parentidx = mlist[3].findIndex(m => { + var mm = parse_shallow(m.data); + if(mm[3]?.[0]) return u8str(mm[3][0].data) == loc; + if(mm[2]?.[0] && u8str(mm[2][0].data) == loc) return true; + return false; + }); + var parent = parse_shallow(mlist[3][parentidx].data); + if(!parent[6]) parent[6] = []; + parent[6].push({ + type: 2, + data: write_shallow([ [], + [{type: 0, data: write_varint49(rtpaid) }] + ]) + }); + mlist[3][parentidx].data = write_shallow(parent); + + /* rich text payload -> storage archive */ + loc = deps[rtpaid].location.replace(/^Root Entry\//,"").replace(/^Index\//, "").replace(/\.iwa$/,""); + parentidx = mlist[3].findIndex(m => { + var mm = parse_shallow(m.data); + if(mm[3]?.[0]) return u8str(mm[3][0].data) == loc; + if(mm[2]?.[0] && u8str(mm[2][0].data) == loc) return true; + return false; + }); + parent = parse_shallow(mlist[3][parentidx].data); + if(!parent[6]) parent[6] = []; + parent[6].push({ + type: 2, + data: write_shallow([ [], + [{type: 0, data: write_varint49(tswpsaid) }] + ]) + }); + mlist[3][parentidx].data = write_shallow(parent); + + /* storage archive -> smart fields */ + loc = deps[tswpsaid].location.replace(/^Root Entry\//,"").replace(/^Index\//, "").replace(/\.iwa$/,""); + parentidx = mlist[3].findIndex(m => { + var mm = parse_shallow(m.data); + if(mm[3]?.[0]) return u8str(mm[3][0].data) == loc; + if(mm[2]?.[0] && u8str(mm[2][0].data) == loc) return true; + return false; + }); + parent = parse_shallow(mlist[3][parentidx].data); + if(!parent[6]) parent[6] = []; + tswpsarefs.forEach(id => parent[6].push({ + type: 2, + data: write_shallow([ [], + [{type: 0, data: write_varint49(id) }] + ]) + })); + style_indices.forEach(n => parent[6].push({ + type: 2, + data: write_shallow([ [], + [{type: 0, data: write_varint49(n) }] + ]) + })); + mlist[3][parentidx].data = write_shallow(parent); + + ai.messages[0].data = write_shallow(mlist); + }); + }); + rsstroot.messages[0].data = write_shallow(rsstdata); + }); } pb[4][0].data = write_shallow(store); } diff --git a/xlsx.mjs b/xlsx.mjs index 56fbe7e..6f05313 100644 --- a/xlsx.mjs +++ b/xlsx.mjs @@ -15524,7 +15524,10 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string var oldt = cell.t, oldv = cell.v; if(cell.t !== "z") switch(cell.t) { case 'b': vv = cell.v ? "1" : "0"; break; - case 'n': vv = ''+cell.v; break; + case 'n': + if(isNaN(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x24]; } // #NUM! + else if(!isFinite(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x07]; } // #DIV/0! + else vv = ''+cell.v; break; case 'e': vv = BErr[cell.v]; break; case 'd': if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString(); @@ -16770,6 +16773,12 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) { if(last_seen) write_record(ba, 0x000D /* BrtShortRk */, write_BrtShortRk(cell, o)); else write_record(ba, 0x0002 /* BrtCellRk */, write_BrtCellRk(cell, o)); + } else if(isNaN(cell.v)) { + if(last_seen) write_record(ba, 0x000E /* BrtShortError */, write_BrtShortError({t:"e", v: 0x24}, o)); // #NUM! + else write_record(ba, 0x0003 /* BrtCellError */, write_BrtCellError({t:"e", v: 0x24}, o)); // #NUM! + } else if(!isFinite(cell.v)) { + if(last_seen) write_record(ba, 0x000E /* BrtShortError */, write_BrtShortError({t:"e", v: 0x07}, o)); // #DIV/0! + else write_record(ba, 0x0003 /* BrtCellError */, write_BrtCellError({t:"e", v: 0x07}, o)); // #DIV/0! } else { if(last_seen) write_record(ba, 0x0010 /* BrtShortReal */, write_BrtShortReal(cell, o)); else write_record(ba, 0x0005 /* BrtCellReal */, write_BrtCellReal(cell, o)); @@ -21301,6 +21310,10 @@ function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v; if((v == (v|0)) && (v >= 0) && (v < 65536)) write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v)); + else if(isNaN(v)) + write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x24, "e")); // #NUM! + else if(!isFinite(v)) + write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x07, "e")); // #DIV/0! else write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v)); return; @@ -21421,8 +21434,10 @@ function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n else switch(cell.t) { case 'd': case 'n': var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v; + if(isNaN(v)) write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, 0x24, os, opts, "e")); // #NUM! + else if(!isFinite(v)) write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, 0x07, os, opts, "e")); // #DIV/0! /* TODO: emit RK as appropriate */ - write_biff_rec(ba, 0x0203 /* Number */, write_Number(R, C, v, os, opts)); + else write_biff_rec(ba, 0x0203 /* Number */, write_Number(R, C, v, os, opts)); break; case 'b': case 'e': write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, cell.v, os, opts, cell.t)); @@ -22483,6 +22498,9 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ { if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) { var ptp = parse_text_p(str.slice(textpidx,Rn.index), textptag); textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0]; + } else if(Rn[0].slice(-2) == "/>") { + /* TODO: is self-closing 文本串 valid? */ + textp += "\n"; } else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; } break; // case 's': break; // @@ -23296,19 +23314,18 @@ function write_packed_varints(nums) { } function varint_to_i32(buf) { var l = 0, i32 = buf[l] & 127; - varint: - if (buf[l++] >= 128) { - i32 |= (buf[l] & 127) << 7; - if (buf[l++] < 128) - break varint; - i32 |= (buf[l] & 127) << 14; - if (buf[l++] < 128) - break varint; - i32 |= (buf[l] & 127) << 21; - if (buf[l++] < 128) - break varint; - i32 |= (buf[l] & 127) << 28; - } + if (buf[l++] < 128) + return i32; + i32 |= (buf[l] & 127) << 7; + if (buf[l++] < 128) + return i32; + i32 |= (buf[l] & 127) << 14; + if (buf[l++] < 128) + return i32; + i32 |= (buf[l] & 127) << 21; + if (buf[l++] < 128) + return i32; + i32 |= (buf[l] & 15) << 28; return i32; } function varint_to_u64(buf) { @@ -23601,7 +23618,7 @@ function compress_iwa_file(buf) { return u8concat(out); } var numbers_lut_new = function() { - return { sst: [], rsst: [], ofmt: [], nfmt: [] }; + return { sst: [], rsst: [], ofmt: [], nfmt: [], fmla: [], ferr: [] }; }; function numbers_format_cell(cell, t, flags, ofmt, nfmt) { var _a, _b, _c, _d; @@ -23777,9 +23794,12 @@ function parse_old_storage(buf, lut, v) { break; case 9: { - if (ridx > -1) - ret = { t: "s", v: lut.rsst[ridx] }; - else + if (ridx > -1) { + var rts = lut.rsst[ridx]; + ret = { t: "s", v: rts.v }; + if (rts.l) + ret.l = { Target: rts.l }; + } else throw new Error("Unsupported cell type ".concat(buf[subarray](0, 4))); } break; @@ -23797,7 +23817,7 @@ function parse_new_storage(buf, lut) { var flags = dv.getUint32(4, true); var fields = dv.getUint32(8, true); var doff = 12; - var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1); + var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1), eidx = -1, fidx = -1; if (fields & 1) { d128 = readDecimal128LE(buf, doff); doff += 16; @@ -23818,6 +23838,16 @@ function parse_new_storage(buf, lut) { ridx = dv.getUint32(doff, true); doff += 4; } + doff += popcnt(fields & 480) * 4; + if (fields & 512) { + fidx = dv.getUint32(doff, true); + doff += 4; + } + doff += popcnt(fields & 1024) * 4; + if (fields & 2048) { + eidx = dv.getUint32(doff, true); + doff += 4; + } var ret; var t = buf[1]; switch (t) { @@ -23842,7 +23872,15 @@ function parse_new_storage(buf, lut) { ret = { t: "e", v: 0 }; break; case 9: - ret = { t: "s", v: lut.rsst[ridx] }; + { + if (ridx > -1) { + var rts = lut.rsst[ridx]; + ret = { t: "s", v: rts.v }; + if (rts.l) + ret.l = { Target: rts.l }; + } else + throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(fields & 31, " : ").concat(buf[subarray](0, 4))); + } break; case 10: ret = { t: "n", v: d128 }; @@ -23850,7 +23888,7 @@ function parse_new_storage(buf, lut) { default: throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(fields & 31, " : ").concat(buf[subarray](0, 4))); } - doff += popcnt(fields & 8160) * 4; + doff += popcnt(fields & 4096) * 4; if (fields & 516096) { if (zidx == -1) zidx = dv.getUint32(doff, true); @@ -23862,7 +23900,7 @@ function parse_new_storage(buf, lut) { ret.v /= 86400; return ret; } -function write_new_storage(cell, sst) { +function write_new_storage(cell, sst, rsst) { var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, flags = 0; out[0] = 5; switch (cell.t) { @@ -23879,14 +23917,29 @@ function write_new_storage(cell, sst) { l += 8; break; case "s": - var s = cell.v == null ? "" : String(cell.v); - var isst = sst.indexOf(s); - if (isst == -1) - sst[isst = sst.length] = s; - out[1] = 3; - dv.setUint32(l, isst, true); - flags |= 8; - l += 4; + { + var s = cell.v == null ? "" : String(cell.v); + if (cell.l) { + var irsst = rsst.findIndex(function(v) { + var _a; + return v.v == s && v.l == ((_a = cell.l) == null ? void 0 : _a.Target); + }); + if (irsst == -1) + rsst[irsst = rsst.length] = { v: s, l: cell.l.Target }; + out[1] = 9; + dv.setUint32(l, irsst, true); + flags |= 16; + l += 4; + } else { + var isst = sst.indexOf(s); + if (isst == -1) + sst[isst = sst.length] = s; + out[1] = 3; + dv.setUint32(l, isst, true); + flags |= 8; + l += 4; + } + } break; default: throw "unsupported cell type " + cell.t; @@ -23894,31 +23947,46 @@ function write_new_storage(cell, sst) { dv.setUint32(8, flags, true); return out[subarray](0, l); } -function write_old_storage(cell, sst) { +function write_old_storage(cell, sst, rsst) { var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, flags = 0; out[0] = 4; switch (cell.t) { case "n": - out[2] = 2; + out[1] = 2; dv.setFloat64(l, cell.v, true); flags |= 32; l += 8; break; case "b": - out[2] = 6; + out[1] = 6; dv.setFloat64(l, cell.v ? 1 : 0, true); flags |= 32; l += 8; break; case "s": - var s = cell.v == null ? "" : String(cell.v); - var isst = sst.indexOf(s); - if (isst == -1) - sst[isst = sst.length] = s; - out[2] = 3; - dv.setUint32(l, isst, true); - flags |= 16; - l += 4; + { + var s = cell.v == null ? "" : String(cell.v); + if (cell.l) { + var irsst = rsst.findIndex(function(v) { + var _a; + return v.v == s && v.l == ((_a = cell.l) == null ? void 0 : _a.Target); + }); + if (irsst == -1) + rsst[irsst = rsst.length] = { v: s, l: cell.l.Target }; + out[1] = 9; + dv.setUint32(l, irsst, true); + flags |= 512; + l += 4; + } else { + var isst = sst.indexOf(s); + if (isst == -1) + sst[isst = sst.length] = s; + out[1] = 3; + dv.setUint32(l, isst, true); + flags |= 16; + l += 4; + } + } break; default: throw "unsupported cell type " + cell.t; @@ -23972,6 +24040,7 @@ function parse_TST_TableDataList(M, root) { var entries = pb[3]; var data = []; (entries || []).forEach(function(entry) { + var _a, _b; var le = parse_shallow(entry.data); if (!le[1]) return; @@ -23989,14 +24058,43 @@ function parse_TST_TableDataList(M, root) { if (mtype != 2001) throw new Error("2000 unexpected reference to ".concat(mtype)); var tswpsa = parse_shallow(rtpref.data); - data[key] = tswpsa[3].map(function(x) { + var richtext = { v: tswpsa[3].map(function(x) { return u8str(x.data); - }).join(""); + }).join("") }; + data[key] = richtext; + sfields: + if ((_a = tswpsa == null ? void 0 : tswpsa[11]) == null ? void 0 : _a[0]) { + var smartfields = (_b = parse_shallow(tswpsa[11][0].data)) == null ? void 0 : _b[1]; + if (!smartfields) + break sfields; + smartfields.forEach(function(sf) { + var _a2, _b2, _c; + var attr = parse_shallow(sf.data); + if ((_a2 = attr[2]) == null ? void 0 : _a2[0]) { + var obj = M[parse_TSP_Reference((_b2 = attr[2]) == null ? void 0 : _b2[0].data)][0]; + var objtype = varint_to_i32(obj.meta[1][0].data); + switch (objtype) { + case 2032: + var hlink = parse_shallow(obj.data); + if (((_c = hlink == null ? void 0 : hlink[2]) == null ? void 0 : _c[0]) && !richtext.l) + richtext.l = u8str(hlink[2][0].data); + break; + case 2039: + break; + default: + console.log("unrecognized ObjectAttribute type ".concat(objtype)); + } + } + }); + } } break; case 2: data[key] = parse_shallow(le[6][0].data); break; + case 3: + data[key] = parse_shallow(le[5][0].data); + break; default: throw type; } @@ -24063,7 +24161,7 @@ function parse_TST_Tile(M, root) { }; } function parse_TST_TableModelArchive(M, root, ws) { - var _a, _b, _c, _d, _e, _f; + var _a, _b, _c, _d, _e, _f, _g, _h; var pb = parse_shallow(root.data); var range = { s: { r: 0, c: 0 }, e: { r: 0, c: 0 } }; range.e.r = (varint_to_i32(pb[6][0].data) >>> 0) - 1; @@ -24078,11 +24176,15 @@ function parse_TST_TableModelArchive(M, root, ws) { var lut = numbers_lut_new(); if ((_a = store[4]) == null ? void 0 : _a[0]) lut.sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]); - if ((_b = store[11]) == null ? void 0 : _b[0]) + if ((_b = store[6]) == null ? void 0 : _b[0]) + lut.fmla = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[6][0].data)][0]); + if ((_c = store[11]) == null ? void 0 : _c[0]) lut.ofmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[11][0].data)][0]); - if ((_c = store[17]) == null ? void 0 : _c[0]) + if ((_d = store[12]) == null ? void 0 : _d[0]) + lut.ferr = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[12][0].data)][0]); + if ((_e = store[17]) == null ? void 0 : _e[0]) lut.rsst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]); - if ((_d = store[22]) == null ? void 0 : _d[0]) + if ((_f = store[22]) == null ? void 0 : _f[0]) lut.nfmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[22][0].data)][0]); var tile = parse_shallow(store[3][0].data); var _R = 0; @@ -24109,12 +24211,12 @@ function parse_TST_TableModelArchive(M, root, ws) { }); _R += _tile.nrows; }); - if ((_e = store[13]) == null ? void 0 : _e[0]) { + if ((_g = store[13]) == null ? void 0 : _g[0]) { var ref = M[parse_TSP_Reference(store[13][0].data)][0]; var mtype = varint_to_i32(ref.meta[1][0].data); if (mtype != 6144) throw new Error("Expected merge type 6144, found ".concat(mtype)); - ws["!merges"] = (_f = parse_shallow(ref.data)) == null ? void 0 : _f[1].map(function(pi) { + ws["!merges"] = (_h = parse_shallow(ref.data)) == null ? void 0 : _h[1].map(function(pi) { var merge = parse_shallow(pi.data); var origin = u8_to_dataview(parse_shallow(merge[1][0].data)[1][0].data), size = u8_to_dataview(parse_shallow(merge[2][0].data)[1][0].data); return { @@ -24229,7 +24331,7 @@ function parse_numbers_iwa(cfb, opts) { throw new Error("Cannot find Document root"); return parse_TN_DocumentArchive(M, docroot, opts); } -function write_TST_TileRowInfo(data, SST, wide) { +function write_TST_TileRowInfo(data, SST, RSST, wide) { var _a, _b; var tri = [ [], @@ -24263,7 +24365,7 @@ function write_TST_TileRowInfo(data, SST, wide) { var _dv = u8_to_dataview(tri[4][0].data), _last_offset = 0, _cell_storage = []; var width = wide ? 4 : 1; for (var C = 0; C < data.length; ++C) { - if (data[C] == null) { + if (data[C] == null || data[C].t == "z" || data[C].t == "e") { dv.setUint16(C * 2, 65535, true); _dv.setUint16(C * 2, 65535); continue; @@ -24271,25 +24373,23 @@ function write_TST_TileRowInfo(data, SST, wide) { dv.setUint16(C * 2, last_offset / width, true); _dv.setUint16(C * 2, _last_offset / width, true); var celload, _celload; - switch (typeof data[C]) { - case "string": - celload = write_new_storage({ t: "s", v: data[C] }, SST); - _celload = write_old_storage({ t: "s", v: data[C] }, SST); - break; - case "number": - celload = write_new_storage({ t: "n", v: data[C] }, SST); - _celload = write_old_storage({ t: "n", v: data[C] }, SST); - break; - case "boolean": - celload = write_new_storage({ t: "b", v: data[C] }, SST); - _celload = write_old_storage({ t: "b", v: data[C] }, SST); - break; - default: - if (data[C] instanceof Date) { - celload = write_new_storage({ t: "s", v: data[C].toISOString() }, SST); - _celload = write_old_storage({ t: "s", v: data[C].toISOString() }, SST); + switch (data[C].t) { + case "d": + if (data[C].v instanceof Date) { + celload = write_new_storage({ t: "s", v: data[C].v.toISOString() }, SST, RSST); + _celload = write_old_storage({ t: "s", v: data[C].v.toISOString() }, SST, RSST); break; } + celload = write_new_storage(data[C], SST, RSST); + _celload = write_old_storage(data[C], SST, RSST); + break; + case "s": + case "n": + case "b": + celload = write_new_storage(data[C], SST, RSST); + _celload = write_old_storage(data[C], SST, RSST); + break; + default: throw new Error("Unsupported value " + data[C]); } cell_storage.push(celload); @@ -24410,6 +24510,38 @@ function numbers_iwa_find(cfb, deps, id) { }); return ainfo; } +function numbers_add_msg(cfb, type, msg, path, deps, id) { + if (!id) + id = get_unique_msgid({ deps: [], location: "", type: type }, deps); + var loc = "".concat(path, "-").concat(id, ".iwa"); + deps[id].location = "Root Entry" + loc; + CFB.utils.cfb_add(cfb, loc, compress_iwa_file(write_iwa_file([{ + id: id, + messages: [write_iwam(type, write_shallow(msg))] + }]))); + var newloc = loc.replace(/^[\/]/, "").replace(/^Index\//, "").replace(/\.iwa$/, ""); + numbers_iwa_doit(cfb, deps, 2, function(ai) { + var mlist = parse_shallow(ai.messages[0].data); + mlist[3].push({ type: 2, data: write_shallow([ + [], + [{ type: 0, data: write_varint49(id) }], + [{ type: 2, data: stru8(newloc.replace(/-.*$/, "")) }], + [{ type: 2, data: stru8(newloc) }], + [{ type: 2, data: new Uint8Array([2, 0, 0]) }], + [{ type: 2, data: new Uint8Array([2, 0, 0]) }], + [], + [], + [], + [], + [{ type: 0, data: write_varint49(0) }], + [], + [{ type: 0, data: write_varint49(0) }] + ]) }); + mlist[1] = [{ type: 0, data: write_varint49(Math.max(id + 1, varint_to_i32(mlist[1][0].data))) }]; + ai.messages[0].data = write_shallow(mlist); + }); + return id; +} function numbers_add_ws(cfb, deps, wsidx) { var sheetref = -1, newsheetref = -1; var remap = {}; @@ -24512,7 +24644,7 @@ function numbers_add_ws(cfb, deps, wsidx) { numbers_iwa_doit(cfb, deps, tmaref, function(tmaroot, arch) { var _a, _b; var tma = parse_shallow(tmaroot.messages[0].data); - var uuid = u8str(tma[1][0].data), new_uuid = uuid.replace(/-[A-Z0-9]*/, "-".concat(wsidx.toString(16).padStart(4, "0"))); + var uuid = u8str(tma[1][0].data), new_uuid = uuid.replace(/-[A-Z0-9]*/, "-".concat(("0000" + wsidx.toString(16)).slice(-4))); tma[1][0].data = stru8(new_uuid); [12, 13, 29, 31, 32, 33, 39, 44, 47, 81, 82, 84].forEach(function(n) { return delete tma[n]; @@ -24798,8 +24930,27 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) { } if (trunc) console.error("Truncating to ".concat(encode_range(range))); - var data = sheet_to_json(ws, { range: range, header: 1 }); + var data = []; + if (ws["!data"]) + data = ws["!data"]; + else { + var colstr = []; + for (var _C = 0; _C <= range.e.c; ++_C) + colstr[_C] = encode_col(_C); + for (var R_ = 0; R_ <= range.e.r; ++R_) { + data[R_] = []; + var _R = "" + (R_ + 1); + for (_C = 0; _C <= range.e.c; ++_C) { + var _cell = ws[colstr[_C] + _R]; + if (!_cell) + continue; + data[R_][_C] = _cell; + } + } + } + sheet_to_json(ws, { range: range, header: 1 }); var SST = ["~Sh33tJ5~"]; + var RSST = [{ v: "~54ee77S~", l: "https://sheetjs.com/" }]; var loc = deps[tmaref].location; loc = loc.replace(/^Root Entry\//, ""); loc = loc.replace(/^Index\//, "").replace(/\.iwa$/, ""); @@ -24897,7 +25048,7 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) { [{ type: 0, data: write_varint49(USE_WIDE_ROWS ? 1 : 0) }] ]; for (var R = tidx * tstride; R <= Math.min(range.e.r, (tidx + 1) * tstride - 1); ++R) { - var tilerow = write_TST_TileRowInfo(data[R], SST, USE_WIDE_ROWS); + var tilerow = write_TST_TileRowInfo(data[R], SST, RSST, USE_WIDE_ROWS); tilerow[1][0].data = write_varint49(R - tidx * tstride); tiledata[5].push({ data: write_shallow(tilerow), type: 2 }); } @@ -25034,6 +25185,166 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) { } sstroot.messages[0].data = write_shallow(sstdata); }); + var rsstref = parse_TSP_Reference(store[17][0].data); + numbers_iwa_doit(cfb, deps, rsstref, function(rsstroot) { + var rsstdata = parse_shallow(rsstroot.messages[0].data); + rsstdata[3] = []; + var style_indices = [ + 904980, + 903835, + 903815, + 903845 + ]; + RSST.forEach(function(rsst, i) { + if (i == 0) + return; + var tswpsa = [ + [], + [{ type: 0, data: new Uint8Array([5]) }], + [], + [{ type: 2, data: stru8(rsst.v) }] + ]; + tswpsa[10] = [{ type: 0, data: new Uint8Array([1]) }]; + tswpsa[19] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 18, 2, 101, 110]) }]; + tswpsa[5] = [{ type: 2, data: new Uint8Array([10, 8, 8, 0, 18, 4, 8, 155, 149, 55]) }]; + tswpsa[2] = [{ type: 2, data: new Uint8Array([8, 148, 158, 55]) }]; + tswpsa[6] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 16, 0, 24, 0]) }]; + tswpsa[7] = [{ type: 2, data: new Uint8Array([10, 8, 8, 0, 18, 4, 8, 135, 149, 55]) }]; + tswpsa[8] = [{ type: 2, data: new Uint8Array([10, 8, 8, 0, 18, 4, 8, 165, 149, 55]) }]; + tswpsa[14] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 16, 0, 24, 0]) }]; + tswpsa[24] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 16, 0, 24, 0]) }]; + var tswpsaid = get_unique_msgid({ deps: [], location: "", type: 2001 }, deps); + var tswpsarefs = []; + if (rsst.l) { + var newhlinkid = numbers_add_msg(cfb, 2032, [ + [], + [], + [{ type: 2, data: stru8(rsst.l) }] + ], "/Index/Tables/DataList", deps); + tswpsa[11] = []; + var smartfield = [[], []]; + if (!smartfield[1]) + smartfield[1] = []; + smartfield[1].push({ type: 2, data: write_shallow([ + [], + [{ type: 0, data: write_varint49(0) }], + [{ type: 2, data: write_TSP_Reference(newhlinkid) }] + ]) }); + tswpsa[11][0] = { type: 2, data: write_shallow(smartfield) }; + tswpsarefs.push(newhlinkid); + } + numbers_add_msg(cfb, 2001, tswpsa, "/Index/Tables/DataList", deps, tswpsaid); + numbers_iwa_doit(cfb, deps, tswpsaid, function(iwa) { + style_indices.forEach(function(ref) { + return numbers_add_oref(iwa, ref); + }); + tswpsarefs.forEach(function(ref) { + return numbers_add_oref(iwa, ref); + }); + }); + var rtpaid = numbers_add_msg(cfb, 6218, [ + [], + [{ type: 2, data: write_TSP_Reference(tswpsaid) }], + [], + [{ type: 2, data: new Uint8Array([13, 255, 255, 255, 0, 18, 10, 16, 255, 255, 1, 24, 255, 255, 255, 255, 7]) }] + ], "/Index/Tables/DataList", deps); + numbers_iwa_doit(cfb, deps, rtpaid, function(iwa) { + return numbers_add_oref(iwa, tswpsaid); + }); + rsstdata[3].push({ type: 2, data: write_shallow([ + [], + [{ type: 0, data: write_varint49(i) }], + [{ type: 0, data: write_varint49(1) }], + [], + [], + [], + [], + [], + [], + [{ type: 2, data: write_TSP_Reference(rtpaid) }] + ]) }); + numbers_add_oref(rsstroot, rtpaid); + numbers_iwa_doit(cfb, deps, 2, function(ai) { + var mlist = parse_shallow(ai.messages[0].data); + var loc2 = deps[rsstref].location.replace(/^Root Entry\//, "").replace(/^Index\//, "").replace(/\.iwa$/, ""); + var parentidx = mlist[3].findIndex(function(m) { + var _a, _b; + var mm = parse_shallow(m.data); + if ((_a = mm[3]) == null ? void 0 : _a[0]) + return u8str(mm[3][0].data) == loc2; + if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc2) + return true; + return false; + }); + var parent = parse_shallow(mlist[3][parentidx].data); + if (!parent[6]) + parent[6] = []; + parent[6].push({ + type: 2, + data: write_shallow([ + [], + [{ type: 0, data: write_varint49(rtpaid) }] + ]) + }); + mlist[3][parentidx].data = write_shallow(parent); + loc2 = deps[rtpaid].location.replace(/^Root Entry\//, "").replace(/^Index\//, "").replace(/\.iwa$/, ""); + parentidx = mlist[3].findIndex(function(m) { + var _a, _b; + var mm = parse_shallow(m.data); + if ((_a = mm[3]) == null ? void 0 : _a[0]) + return u8str(mm[3][0].data) == loc2; + if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc2) + return true; + return false; + }); + parent = parse_shallow(mlist[3][parentidx].data); + if (!parent[6]) + parent[6] = []; + parent[6].push({ + type: 2, + data: write_shallow([ + [], + [{ type: 0, data: write_varint49(tswpsaid) }] + ]) + }); + mlist[3][parentidx].data = write_shallow(parent); + loc2 = deps[tswpsaid].location.replace(/^Root Entry\//, "").replace(/^Index\//, "").replace(/\.iwa$/, ""); + parentidx = mlist[3].findIndex(function(m) { + var _a, _b; + var mm = parse_shallow(m.data); + if ((_a = mm[3]) == null ? void 0 : _a[0]) + return u8str(mm[3][0].data) == loc2; + if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc2) + return true; + return false; + }); + parent = parse_shallow(mlist[3][parentidx].data); + if (!parent[6]) + parent[6] = []; + tswpsarefs.forEach(function(id) { + return parent[6].push({ + type: 2, + data: write_shallow([ + [], + [{ type: 0, data: write_varint49(id) }] + ]) + }); + }); + style_indices.forEach(function(n) { + return parent[6].push({ + type: 2, + data: write_shallow([ + [], + [{ type: 0, data: write_varint49(n) }] + ]) + }); + }); + mlist[3][parentidx].data = write_shallow(parent); + ai.messages[0].data = write_shallow(mlist); + }); + }); + rsstroot.messages[0].data = write_shallow(rsstdata); + }); } pb[4][0].data = write_shallow(store); }