forked from sheetjs/sheetjs
Compare commits
24 Commits
sankhavara
...
master
Author | SHA1 | Date | |
---|---|---|---|
0577bb7a45 | |||
b150dea21d | |||
e9cf1ad0fb | |||
5141222c24 | |||
51a8619000 | |||
e7e129e417 | |||
df48489211 | |||
050f66ce1b | |||
2f329b64e2 | |||
515d1c6f2e | |||
654d6f98c3 | |||
4ae4f0fad9 | |||
|
1ca49a50bd | ||
81b231d866 | |||
1491302aa4 | |||
bd5878e7c7 | |||
|
4dd092a076 | ||
|
04dc18e742 | ||
6a5be04e3d | |||
e90a61bf09 | |||
26cbfe37be | |||
df0e7b5f25 | |||
6c9010f9d1 | |||
0a6ddcaf44 |
6
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
6
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Issues and Questions
|
||||
url: https://git.sheetjs.com/sheetjs/sheetjs/issues
|
||||
about: Please report issues to the official code repository.
|
||||
|
1
.gitmodules
vendored
1
.gitmodules
vendored
@ -1,3 +1,4 @@
|
||||
[submodule "test_files"]
|
||||
path = test_files
|
||||
url = https://github.com/SheetJS/test_files
|
||||
ignore = dirty
|
||||
|
@ -58,11 +58,11 @@ make.cmd
|
||||
xlsworker.js
|
||||
shim.js
|
||||
test.js
|
||||
hotcross.mjs
|
||||
test.mjs
|
||||
test.ts
|
||||
test.mts
|
||||
testnocp.ts
|
||||
testbun.mjs
|
||||
.jscs.json
|
||||
.gitmodules
|
||||
.travis.yml
|
||||
|
@ -54,6 +54,7 @@ Rollup
|
||||
SessionStorage
|
||||
SQLite
|
||||
SystemJS
|
||||
Vite
|
||||
VueJS
|
||||
WebKit
|
||||
WebSQL
|
||||
|
30
CHANGELOG.md
30
CHANGELOG.md
@ -4,6 +4,36 @@ This log is intended to keep track of backwards-incompatible changes, including
|
||||
but not limited to API changes and file location changes. Minor behavioral
|
||||
changes may not be included if they are not expected to break existing code.
|
||||
|
||||
## v0.19.2
|
||||
|
||||
* XLSX proper decoding of hyperlinks (h/t @tw-yaxu)
|
||||
* XLSX ignore unexpected attributes in rich text (h/t @colin4)
|
||||
* `sheet_to_json` type fix (h/t @chsdwn)
|
||||
|
||||
## v0.19.1
|
||||
|
||||
* Fixed types issue in strict mode (h/t @younes-io)
|
||||
* Numbers 12.2 parsing skip ActivityStream.iwa
|
||||
|
||||
## v0.19.0
|
||||
|
||||
* XLSX export hyperlinks compatible with google sheets (h/t Evan Bovie)
|
||||
* NUMBERS export multiple sheets, full worksheet range
|
||||
* formalized `dense` mode
|
||||
|
||||
## v0.18.12
|
||||
|
||||
* `package.json` added types in `exports` structure
|
||||
* uncapped NUMBERS single-sheet single-table export
|
||||
* DBF export records using supported codepages
|
||||
|
||||
## v0.18.11
|
||||
|
||||
* Base64 input ignore data URI wrapper
|
||||
* Parse ZIP files that use ZIP64 extended information field
|
||||
* More precise handling of time-only values
|
||||
* Threaded Comment fallback text for older Excel
|
||||
|
||||
## v0.18.10
|
||||
|
||||
* `exports` field in package.json to satiate ViteJS and newer tooling
|
||||
|
6
Makefile
6
Makefile
@ -148,16 +148,16 @@ test.ts: test.mts
|
||||
node -pe 'var data = fs.readFileSync("'$<'", "utf8"); data.split("\n").map(function(l) { return l.replace(/^describe\((.*?)function\(\)/, "Deno.test($$1async function(t)").replace(/\b(?:it|describe)\((.*?)function\(\)/g, "await t.step($$1async function(t)").replace("assert.ok", "assert.assert"); }).join("\n")' > $@
|
||||
|
||||
.PHONY: test-bun
|
||||
test-bun: hotcross.mjs ## Run Bun test suite
|
||||
test-bun: testbun.mjs ## Run Bun test suite
|
||||
bun $<
|
||||
|
||||
.PHONY: test-deno
|
||||
test-deno: test.ts ## Run Deno test suite
|
||||
deno test --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $<
|
||||
deno test --check --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $<
|
||||
|
||||
.PHONY: test-denocp
|
||||
test-denocp: testnocp.ts ## Run Deno test suite (without codepage)
|
||||
deno test --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $<
|
||||
deno test --check --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $<
|
||||
|
||||
TESTFMT=$(patsubst %,test_%,$(FMT))
|
||||
.PHONY: $(TESTFMT)
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.18.10';
|
||||
XLSX.version = '0.19.2';
|
||||
|
@ -71,7 +71,7 @@ var bconcat = has_buf ? function(bufs) { return Buffer.concat(bufs.map(function(
|
||||
for(i = 0, maxlen = 0; i < bufs.length; maxlen += len, ++i) {
|
||||
len = bufs[i].length;
|
||||
if(bufs[i] instanceof Uint8Array) o.set(bufs[i], maxlen);
|
||||
else if(typeof bufs[i] == "string") { throw "wtf"; }
|
||||
else if(typeof bufs[i] == "string") o.set(new Uint8Array(s2a(bufs[i])), maxlen);
|
||||
else o.set(new Uint8Array(bufs[i]), maxlen);
|
||||
}
|
||||
return o;
|
||||
|
@ -306,7 +306,7 @@ sleuth_fat(difat_start, difat_sec_cnt, sectors, ssz, fat_addrs);
|
||||
/** Chains */
|
||||
var sector_list/*:SectorList*/ = make_sector_list(sectors, dir_start, fat_addrs, ssz);
|
||||
|
||||
sector_list[dir_start].name = "!Directory";
|
||||
if(dir_start < sector_list.length) sector_list[dir_start].name = "!Directory";
|
||||
if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
|
||||
sector_list[fat_addrs[0]].name = "!FAT";
|
||||
sector_list.fat_addrs = fat_addrs;
|
||||
@ -1500,9 +1500,9 @@ function write_zip(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes*/
|
||||
var namebuf = new_buf(fp.length);
|
||||
for(j = 0; j < fp.length; ++j) namebuf.write_shift(1, fp.charCodeAt(j) & 0x7F);
|
||||
namebuf = namebuf.slice(0, namebuf.l);
|
||||
crcs[fcnt] = CRC32.buf(/*::((*/fi.content/*::||[]):any)*/, 0);
|
||||
crcs[fcnt] = typeof fi.content == "string" ? CRC32.bstr(fi.content, 0) : CRC32.buf(/*::((*/fi.content/*::||[]):any)*/, 0);
|
||||
|
||||
var outbuf = fi.content/*::||[]*/;
|
||||
var outbuf = typeof fi.content == "string" ? s2a(fi.content) : fi.content/*::||[]*/;
|
||||
if(method == 8) outbuf = _deflateRawSync(outbuf);
|
||||
|
||||
/* local file header */
|
||||
|
@ -181,21 +181,29 @@ function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/)/*:any*/
|
||||
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
|
||||
for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i);
|
||||
size = 2 * val.length;
|
||||
} else if(f === 'sbcs') {
|
||||
} else if(f === 'sbcs' || f == 'cpstr') {
|
||||
if(typeof $cptable !== 'undefined' && current_ansi == 874) {
|
||||
/* TODO: use tables directly, don't encode */
|
||||
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
|
||||
for(i = 0; i != val.length; ++i) {
|
||||
var cppayload = $cptable.utils.encode(current_ansi, val.charAt(i));
|
||||
this[this.l + i] = cppayload[0];
|
||||
var cpp = $cptable.utils.encode(current_ansi, val.charAt(i));
|
||||
this[this.l + i] = cpp[0];
|
||||
}
|
||||
size = val.length;
|
||||
} else if(typeof $cptable !== 'undefined' && f == 'cpstr') {
|
||||
cpp = $cptable.utils.encode(current_codepage, val);
|
||||
/* replace null bytes with _ when relevant */
|
||||
if(cpp.length == val.length) for(i = 0; i < val.length; ++i) if(cpp[i] == 0 && val.charCodeAt(i) != 0) cpp[i] = 0x5F;
|
||||
if(cpp.length == 2 * val.length) for(i = 0; i < val.length; ++i) if(cpp[2*i] == 0 && cpp[2*i+1] == 0 && val.charCodeAt(i) != 0) cpp[2*i] = 0x5F;
|
||||
for(i = 0; i < cpp.length; ++i) this[this.l + i] = cpp[i];
|
||||
size = cpp.length;
|
||||
} else {
|
||||
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
|
||||
val = val.replace(/[^\x00-\x7F]/g, "_");
|
||||
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
|
||||
for(i = 0; i != val.length; ++i) this[this.l + i] = (val.charCodeAt(i) & 0xFF);
|
||||
size = val.length;
|
||||
}
|
||||
size = val.length;
|
||||
} else if(f === 'hex') {
|
||||
for(; i < t; ++i) {
|
||||
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
|
||||
|
@ -9,7 +9,6 @@ function fix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^([A-Z])/,"$
|
||||
function unfix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^\$([A-Z])/,"$1"); }
|
||||
|
||||
function split_cell(cstr/*:string*/)/*:Array<string>*/ { return cstr.replace(/(\$?[A-Z]*)(\$?\d*)/,"$1,$2").split(","); }
|
||||
//function decode_cell(cstr/*:string*/)/*:CellAddress*/ { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; }
|
||||
function decode_cell(cstr/*:string*/)/*:CellAddress*/ {
|
||||
var R = 0, C = 0;
|
||||
for(var i = 0; i < cstr.length; ++i) {
|
||||
@ -19,7 +18,6 @@ function decode_cell(cstr/*:string*/)/*:CellAddress*/ {
|
||||
}
|
||||
return { c: C - 1, r:R - 1 };
|
||||
}
|
||||
//function encode_cell(cell/*:CellAddress*/)/*:string*/ { return encode_col(cell.c) + encode_row(cell.r); }
|
||||
function encode_cell(cell/*:CellAddress*/)/*:string*/ {
|
||||
var col = cell.c + 1;
|
||||
var s="";
|
||||
@ -112,9 +110,10 @@ function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ {
|
||||
|
||||
function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
|
||||
var o = opts || {};
|
||||
var dense = _ws ? Array.isArray(_ws) : o.dense;
|
||||
var dense = _ws ? (_ws["!data"] != null) : o.dense;
|
||||
if(DENSE != null && dense == null) dense = DENSE;
|
||||
var ws/*:Worksheet*/ = _ws || (dense ? ([]/*:any*/) : ({}/*:any*/));
|
||||
var ws/*:Worksheet*/ = _ws || ({}/*:any*/);
|
||||
if(dense && !ws["!data"]) ws["!data"] = [];
|
||||
var _R = 0, _C = 0;
|
||||
if(ws && o.origin != null) {
|
||||
if(typeof o.origin == 'number') _R = o.origin;
|
||||
@ -133,13 +132,19 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
|
||||
range.e.r = Math.max(range.e.r, _range.e.r);
|
||||
if(_R == -1) range.e.r = _R = _range.e.r + 1;
|
||||
}
|
||||
var row = [];
|
||||
for(var R = 0; R != data.length; ++R) {
|
||||
if(!data[R]) continue;
|
||||
if(!Array.isArray(data[R])) throw new Error("aoa_to_sheet expects an array of arrays");
|
||||
var __R = _R + R, __Rstr = "" + (__R + 1);
|
||||
if(dense) {
|
||||
if(!ws["!data"][__R]) ws["!data"][__R] = [];
|
||||
row = ws["!data"][__R];
|
||||
}
|
||||
for(var C = 0; C != data[R].length; ++C) {
|
||||
if(typeof data[R][C] === 'undefined') continue;
|
||||
var cell/*:Cell*/ = ({v: data[R][C] }/*:any*/);
|
||||
var __R = _R + R, __C = _C + C;
|
||||
var __C = _C + C;
|
||||
if(range.s.r > __R) range.s.r = __R;
|
||||
if(range.s.c > __C) range.s.c = __C;
|
||||
if(range.e.r < __R) range.e.r = __R;
|
||||
@ -163,11 +168,10 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
|
||||
else cell.t = 's';
|
||||
}
|
||||
if(dense) {
|
||||
if(!ws[__R]) ws[__R] = [];
|
||||
if(ws[__R][__C] && ws[__R][__C].z) cell.z = ws[__R][__C].z;
|
||||
ws[__R][__C] = cell;
|
||||
if(row[__C] && row[__C].z) cell.z = row[__C].z;
|
||||
row[__C] = cell;
|
||||
} else {
|
||||
var cell_ref = encode_cell(({c:__C,r:__R}/*:any*/));
|
||||
var cell_ref = encode_col(__C) + __Rstr/*:any*/;
|
||||
if(ws[cell_ref] && ws[cell_ref].z) cell.z = ws[cell_ref].z;
|
||||
ws[cell_ref] = cell;
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ function parse_rels(data/*:?string*/, currentFilePath/*:string*/) {
|
||||
var y = parsexmltag(x);
|
||||
/* 9.3.2.2 OPC_Relationships */
|
||||
if (y[0] === '<Relationship') {
|
||||
var rel = {}; rel.Type = y.Type; rel.Target = y.Target; rel.Id = y.Id; if(y.TargetMode) rel.TargetMode = y.TargetMode;
|
||||
var rel = {}; rel.Type = y.Type; rel.Target = unescapexml(y.Target); rel.Id = y.Id; if(y.TargetMode) rel.TargetMode = y.TargetMode;
|
||||
var canonictarget = y.TargetMode === 'External' ? y.Target : resolve_path(y.Target, currentFilePath);
|
||||
rels[canonictarget] = rel;
|
||||
hash[y.Id] = rel;
|
||||
|
147
bits/40_harb.js
147
bits/40_harb.js
@ -1,4 +1,3 @@
|
||||
/* from js-harb (C) 2014-present SheetJS */
|
||||
var DBF_SUPPORTED_VERSIONS = [0x02, 0x03, 0x30, 0x31, 0x83, 0x8B, 0x8C, 0xF5];
|
||||
var DBF = /*#__PURE__*/(function() {
|
||||
var dbf_codepage_map = {
|
||||
@ -239,14 +238,14 @@ function dbf_to_workbook(buf, opts)/*:Workbook*/ {
|
||||
var o = sheet_to_workbook(dbf_to_sheet(buf, opts), opts);
|
||||
o.bookType = "dbf";
|
||||
return o;
|
||||
}
|
||||
catch(e) { if(opts && opts.WTF) throw e; }
|
||||
} catch(e) { if(opts && opts.WTF) throw e; }
|
||||
return ({SheetNames:[],Sheets:{}});
|
||||
}
|
||||
|
||||
var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 };
|
||||
function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
|
||||
var o = opts || {};
|
||||
var old_cp = current_codepage;
|
||||
if(+o.codepage >= 0) set_cp(+o.codepage);
|
||||
if(o.type == "string") throw new Error("Cannot write DBF to JS string");
|
||||
var ba = buf_array();
|
||||
@ -282,7 +281,8 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
|
||||
case 'object': _guess = col[j] instanceof Date ? 'D' : 'C'; break;
|
||||
default: _guess = 'C';
|
||||
}
|
||||
maxlen = Math.max(maxlen, String(col[j]).length);
|
||||
/* TODO: cache the values instead of encoding twice */
|
||||
maxlen = Math.max(maxlen, (typeof $cptable !== "undefined" && typeof col[j] == "string" ? $cptable.utils.encode(current_ansi, col[j]): String(col[j])).length);
|
||||
guess = guess && guess != _guess ? 'C' : _guess;
|
||||
//if(guess == 'C') break;
|
||||
}
|
||||
@ -308,11 +308,17 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
|
||||
h.write_shift(2, 296 + 32 * hcnt);
|
||||
h.write_shift(2, rlen);
|
||||
for(i=0; i < 4; ++i) h.write_shift(4, 0);
|
||||
h.write_shift(4, 0x00000000 | ((+dbf_reverse_map[/*::String(*/current_ansi/*::)*/] || 0x03)<<8));
|
||||
var cp = +dbf_reverse_map[/*::String(*/current_codepage/*::)*/] || 0x03;
|
||||
h.write_shift(4, 0x00000000 | (cp<<8));
|
||||
if(dbf_codepage_map[cp] != +o.codepage) {
|
||||
if(o.codepage) console.error("DBF Unsupported codepage " + current_codepage + ", using 1252");
|
||||
current_codepage = 1252;
|
||||
}
|
||||
|
||||
for(i = 0, j = 0; i < headers.length; ++i) {
|
||||
if(headers[i] == null) continue;
|
||||
var hf = ba.next(32);
|
||||
/* TODO: test how applications handle non-ASCII field names */
|
||||
var _f = (headers[i].slice(-10) + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00").slice(0, 11);
|
||||
hf.write_shift(1, _f, "sbcs");
|
||||
hf.write_shift(1, coltypes[i] == '?' ? 'C' : coltypes[i], "sbcs");
|
||||
@ -341,6 +347,7 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
|
||||
case 'N':
|
||||
var _n = "0";
|
||||
if(typeof data[i][j] == "number") _n = data[i][j].toFixed(coldecimals[j]||0);
|
||||
if(_n.length > colwidths[j]) _n = _n.slice(0, colwidths[j]); // addresses decimal > width
|
||||
for(hcnt=0; hcnt < colwidths[j]-_n.length; ++hcnt) rout.write_shift(1, 0x20);
|
||||
rout.write_shift(1, _n, "sbcs");
|
||||
break;
|
||||
@ -352,13 +359,16 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
|
||||
rout.write_shift(2, ("00"+data[i][j].getDate()).slice(-2), "sbcs");
|
||||
} break;
|
||||
case 'C':
|
||||
var _l = rout.l;
|
||||
var _s = String(data[i][j] != null ? data[i][j] : "").slice(0, colwidths[j]);
|
||||
rout.write_shift(1, _s, "sbcs");
|
||||
for(hcnt=0; hcnt < colwidths[j]-_s.length; ++hcnt) rout.write_shift(1, 0x20); break;
|
||||
rout.write_shift(1, _s, "cpstr");
|
||||
_l += colwidths[j] - rout.l;
|
||||
for(hcnt=0; hcnt < _l; ++hcnt) rout.write_shift(1, 0x20); break;
|
||||
}
|
||||
}
|
||||
// data
|
||||
}
|
||||
current_codepage = old_cp;
|
||||
ba.next(1).write_shift(1, 0x1A);
|
||||
return ba.end();
|
||||
}
|
||||
@ -569,7 +579,7 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
case 'b': o += cell.v ? "TRUE" : "FALSE"; break;
|
||||
case 'e': o += cell.w || cell.v; break;
|
||||
case 'd': o += '"' + (cell.w || cell.v) + '"'; break;
|
||||
case 's': o += '"' + cell.v.replace(/"/g,"").replace(/;/g, ";;") + '"'; break;
|
||||
case 's': o += '"' + (cell.v == null ? "" : String(cell.v)).replace(/"/g,"").replace(/;/g, ";;") + '"'; break;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
@ -598,9 +608,10 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
}
|
||||
|
||||
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/, wb/*:?WorkBook*/)/*:string*/ {
|
||||
/* TODO: codepage */
|
||||
var preamble/*:Array<string>*/ = ["ID;PSheetJS;N;E"], o/*:Array<string>*/ = [];
|
||||
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
|
||||
var dense = Array.isArray(ws);
|
||||
var dense = ws["!data"] != null;
|
||||
var RS = "\r\n";
|
||||
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
|
||||
@ -612,10 +623,10 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
preamble.push("B;Y" + (r.e.r - r.s.r + 1) + ";X" + (r.e.c - r.s.c + 1) + ";D" + [r.s.c,r.s.r,r.e.c,r.e.r].join(" "));
|
||||
preamble.push("O;L;D;B" + (d1904 ? ";V4" : "") + ";K47;G100 0.001");
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
if(dense && !ws["!data"][R]) continue;
|
||||
var p = [];
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var coord = encode_cell({r:R,c:C});
|
||||
cell = dense ? (ws[R]||[])[C]: ws[coord];
|
||||
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
|
||||
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
|
||||
p.push(write_ws_cell_sylk(cell, ws, R, C, opts)); // TODO: pass date1904 info
|
||||
}
|
||||
@ -683,62 +694,55 @@ var DIF = /*#__PURE__*/(function() {
|
||||
return o;
|
||||
}
|
||||
|
||||
var sheet_to_dif = /*#__PURE__*/(function() {
|
||||
var push_field = function pf(o/*:Array<string>*/, topic/*:string*/, v/*:number*/, n/*:number*/, s/*:string*/) {
|
||||
o.push(topic);
|
||||
o.push(v + "," + n);
|
||||
o.push('"' + s.replace(/"/g,'""') + '"');
|
||||
};
|
||||
var push_value = function po(o/*:Array<string>*/, type/*:number*/, v/*:any*/, s/*:string*/) {
|
||||
o.push(type + "," + v);
|
||||
o.push(type == 1 ? '"' + s.replace(/"/g,'""') + '"' : s);
|
||||
};
|
||||
return function sheet_to_dif(ws/*:Worksheet*//*::, opts:?any*/)/*:string*/ {
|
||||
var o/*:Array<string>*/ = [];
|
||||
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
|
||||
var dense = Array.isArray(ws);
|
||||
push_field(o, "TABLE", 0, 1, "sheetjs");
|
||||
push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,"");
|
||||
push_field(o, "TUPLES", 0, r.e.c - r.s.c + 1,"");
|
||||
push_field(o, "DATA", 0, 0,"");
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
push_value(o, -1, 0, "BOT");
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var coord = encode_cell({r:R,c:C});
|
||||
cell = dense ? (ws[R]||[])[C] : ws[coord];
|
||||
if(!cell) { push_value(o, 1, 0, ""); continue;}
|
||||
switch(cell.t) {
|
||||
case 'n':
|
||||
var val = DIF_XL ? cell.w : cell.v;
|
||||
if(!val && cell.v != null) val = cell.v;
|
||||
if(val == null) {
|
||||
if(DIF_XL && cell.f && !cell.F) push_value(o, 1, 0, "=" + cell.f);
|
||||
else push_value(o, 1, 0, "");
|
||||
}
|
||||
else push_value(o, 0, val, "V");
|
||||
break;
|
||||
case 'b':
|
||||
push_value(o, 0, cell.v ? 1 : 0, cell.v ? "TRUE" : "FALSE");
|
||||
break;
|
||||
case 's':
|
||||
push_value(o, 1, 0, (!DIF_XL || isNaN(cell.v)) ? cell.v : '="' + cell.v + '"');
|
||||
break;
|
||||
case 'd':
|
||||
if(!cell.w) cell.w = SSF_format(cell.z || table_fmt[14], datenum(parseDate(cell.v)));
|
||||
if(DIF_XL) push_value(o, 0, cell.w, "V");
|
||||
else push_value(o, 1, 0, cell.w);
|
||||
break;
|
||||
default: push_value(o, 1, 0, "");
|
||||
}
|
||||
function make_value(v/*:number*/, s/*:string*/)/*:string*/ { return "0," + String(v) + "\r\n" + s; }
|
||||
function make_value_str(s/*:string*/)/*:string*/ { return "1,0\r\n\"" + s.replace(/"/g,'""') + '"'; }
|
||||
function sheet_to_dif(ws/*:Worksheet*//*::, opts:?any*/)/*:string*/ {
|
||||
var _DIF_XL = DIF_XL;
|
||||
var r = safe_decode_range(ws['!ref']);
|
||||
var dense = ws["!data"] != null;
|
||||
var o/*:Array<string>*/ = [
|
||||
"TABLE\r\n0,1\r\n\"sheetjs\"\r\n",
|
||||
"VECTORS\r\n0," + (r.e.r - r.s.r + 1) + "\r\n\"\"\r\n",
|
||||
"TUPLES\r\n0," + (r.e.c - r.s.c + 1) + "\r\n\"\"\r\n",
|
||||
"DATA\r\n0,0\r\n\"\"\r\n"
|
||||
];
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
var row = dense ? ws["!data"][R] : [];
|
||||
var p = "-1,0\r\nBOT\r\n";
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var cell/*:Cell*/ = dense ? (row && row[C]) : ws[encode_cell({r:R,c:C})];
|
||||
if(cell == null) { p +=("1,0\r\n\"\"\r\n"); continue;}
|
||||
switch(cell.t) {
|
||||
case 'n':
|
||||
if(_DIF_XL) {
|
||||
if(cell.w != null) p +=("0," + cell.w + "\r\nV");
|
||||
else if(cell.v != null) p +=(make_value(cell.v, "V")); // TODO: should this call SSF_format?
|
||||
else if(cell.f != null && !cell.F) p +=(make_value_str("=" + cell.f));
|
||||
else p +=("1,0\r\n\"\"");
|
||||
} else {
|
||||
if(cell.v == null) p +=("1,0\r\n\"\"");
|
||||
else p +=(make_value(cell.v, "V"));
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
p +=(cell.v ? make_value(1, "TRUE") : make_value(0, "FALSE"));
|
||||
break;
|
||||
case 's':
|
||||
p +=(make_value_str((!_DIF_XL || isNaN(+cell.v)) ? cell.v : '="' + cell.v + '"'));
|
||||
break;
|
||||
case 'd':
|
||||
if(!cell.w) cell.w = SSF_format(cell.z || table_fmt[14], datenum(parseDate(cell.v)));
|
||||
if(_DIF_XL) p +=(make_value(cell.w, "V"));
|
||||
else p +=(make_value_str(cell.w));
|
||||
break;
|
||||
default: p +=("1,0\r\n\"\"");
|
||||
}
|
||||
p += "\r\n";
|
||||
}
|
||||
push_value(o, -1, 0, "EOD");
|
||||
var RS = "\r\n";
|
||||
var oo = o.join(RS);
|
||||
//while((oo.length & 0x7F) != 0) oo += "\0";
|
||||
return oo;
|
||||
};
|
||||
})();
|
||||
o.push(p);
|
||||
}
|
||||
return o.join("") + "-1,0\r\nEOD";
|
||||
}
|
||||
return {
|
||||
to_workbook: dif_to_workbook,
|
||||
to_sheet: dif_to_sheet,
|
||||
@ -801,11 +805,11 @@ var ETH = /*#__PURE__*/(function() {
|
||||
if(!ws || !ws['!ref']) return "";
|
||||
var o/*:Array<string>*/ = [], oo/*:Array<string>*/ = [], cell, coord = "";
|
||||
var r = decode_range(ws['!ref']);
|
||||
var dense = Array.isArray(ws);
|
||||
var dense = ws["!data"] != null;
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
coord = encode_cell({r:R,c:C});
|
||||
cell = dense ? (ws[R]||[])[C] : ws[coord];
|
||||
cell = dense ? (ws["!data"][R]||[])[C] : ws[coord];
|
||||
if(!cell || cell.v == null || cell.t === 'z') continue;
|
||||
oo = ["cell", coord, 't'];
|
||||
switch(cell.t) {
|
||||
@ -927,7 +931,8 @@ var PRN = /*#__PURE__*/(function() {
|
||||
var o = opts || {};
|
||||
var sep = "";
|
||||
if(DENSE != null && o.dense == null) o.dense = DENSE;
|
||||
var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/);
|
||||
var ws/*:Worksheet*/ = ({}/*:any*/);
|
||||
if(o.dense) ws["!data"] = [];
|
||||
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:0}}/*:any*/);
|
||||
|
||||
if(str.slice(0,4) == "sep=") {
|
||||
@ -973,7 +978,7 @@ var PRN = /*#__PURE__*/(function() {
|
||||
cell.v = s;
|
||||
}
|
||||
if(cell.t == 'z'){}
|
||||
else if(o.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = cell; }
|
||||
else if(o.dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = cell; }
|
||||
else ws[encode_cell({c:C,r:R})] = cell;
|
||||
start = end+1; startcc = str.charCodeAt(start);
|
||||
if(range.e.c < C) range.e.c = C;
|
||||
@ -1029,12 +1034,12 @@ var PRN = /*#__PURE__*/(function() {
|
||||
function sheet_to_prn(ws/*:Worksheet*//*::, opts:?any*/)/*:string*/ {
|
||||
var o/*:Array<string>*/ = [];
|
||||
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
|
||||
var dense = Array.isArray(ws);
|
||||
var dense = ws["!data"] != null;
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
var oo/*:Array<string>*/ = [];
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var coord = encode_cell({r:R,c:C});
|
||||
cell = dense ? (ws[R]||[])[C] : ws[coord];
|
||||
cell = dense ? (ws["!data"][R]||[])[C] : ws[coord];
|
||||
if(!cell || cell.v == null) { oo.push(" "); continue; }
|
||||
var w = (cell.w || (format_cell(cell), cell.w) || "").slice(0,10);
|
||||
while(w.length < 10) w += " ";
|
||||
|
@ -28,8 +28,9 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
if(!d) return d;
|
||||
var o = opts || {};
|
||||
if(DENSE != null && o.dense == null) o.dense = DENSE;
|
||||
var s/*:Worksheet*/ = ((o.dense ? [] : {})/*:any*/), n = "Sheet1", next_n = "", sidx = 0;
|
||||
var sheets = {}, snames = [], realnames = [];
|
||||
var s/*:Worksheet*/ = ({}/*:any*/), n = "Sheet1", next_n = "", sidx = 0;
|
||||
var sheets = {}, snames = [], realnames = [], sdata = [];
|
||||
if(o.dense) sdata = s["!data"] = [];
|
||||
|
||||
var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
|
||||
var sheetRows = o.sheetRows || 0;
|
||||
@ -74,13 +75,13 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
s["!ref"] = encode_range(refguess);
|
||||
sheets[n] = s;
|
||||
snames.push(n);
|
||||
s = (o.dense ? [] : {});
|
||||
s = ({}/*:any*/); if(o.dense) sdata = s["!data"] = [];
|
||||
refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
|
||||
sidx = val[3]; n = next_n || "Sheet" + (sidx + 1); next_n = "";
|
||||
}
|
||||
}
|
||||
|
||||
var tmpcell = o.dense ? (s[val[0].r]||[])[val[0].c] : s[encode_cell(val[0])];
|
||||
var tmpcell = o.dense ? (sdata[val[0].r]||[])[val[0].c] : s[encode_cell(val[0])];
|
||||
if(tmpcell) {
|
||||
tmpcell.t = val[1].t; tmpcell.v = val[1].v;
|
||||
if(val[1].z != null) tmpcell.z = val[1].z;
|
||||
@ -88,8 +89,8 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
break;
|
||||
}
|
||||
if(o.dense) {
|
||||
if(!s[val[0].r]) s[val[0].r] = [];
|
||||
s[val[0].r][val[0].c] = val[1];
|
||||
if(!sdata[val[0].r]) sdata[val[0].r] = [];
|
||||
sdata[val[0].r][val[0].c] = val[1];
|
||||
} else s[encode_cell(val[0])] = val[1];
|
||||
break;
|
||||
case 0x5405: o.works2 = true; break;
|
||||
@ -115,14 +116,14 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
s["!ref"] = encode_range(refguess);
|
||||
sheets[n] = s;
|
||||
snames.push(n);
|
||||
s = (o.dense ? [] : {});
|
||||
s = ({}/*:any*/); if(o.dense) sdata = s["!data"] = [];
|
||||
refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
|
||||
sidx = val[3]; n = "Sheet" + (sidx + 1);
|
||||
}
|
||||
if(sheetRows > 0 && val[0].r >= sheetRows) break;
|
||||
if(o.dense) {
|
||||
if(!s[val[0].r]) s[val[0].r] = [];
|
||||
s[val[0].r][val[0].c] = val[1];
|
||||
if(!sdata[val[0].r]) sdata[val[0].r] = [];
|
||||
sdata[val[0].r][val[0].c] = val[1];
|
||||
} else s[encode_cell(val[0])] = val[1];
|
||||
if(refguess.e.c < val[0].c) refguess.e.c = val[0].c;
|
||||
if(refguess.e.r < val[0].r) refguess.e.r = val[0].r;
|
||||
@ -157,18 +158,17 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
if(o.type == "string") throw new Error("Cannot write WK1 to JS string");
|
||||
var ba = buf_array();
|
||||
var range = safe_decode_range(ws["!ref"]);
|
||||
var dense = Array.isArray(ws);
|
||||
var dense = ws["!data"] != null;
|
||||
var cols = [];
|
||||
|
||||
write_biff_rec(ba, 0x00, write_BOF_WK1(0x0406));
|
||||
write_biff_rec(ba, 0x06, write_RANGE(range));
|
||||
var max_R = Math.min(range.e.r, 8191);
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
|
||||
for(var R = range.s.r; R <= max_R; ++R) {
|
||||
var rr = encode_row(R);
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) {
|
||||
if(R === range.s.r) cols[C] = encode_col(C);
|
||||
var ref = cols[C] + rr;
|
||||
var cell = dense ? (ws[R]||[])[C] : ws[ref];
|
||||
for(C = range.s.c; C <= range.e.c; ++C) {
|
||||
var cell = dense ? (ws["!data"][R]||[])[C] : ws[cols[C] + rr];
|
||||
if(!cell || cell.t == "z") continue;
|
||||
/* TODO: formula records */
|
||||
if(cell.t == "n") {
|
||||
@ -200,7 +200,7 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
var ws = wb.Sheets[wb.SheetNames[i]];
|
||||
if(!ws || !ws["!ref"]) continue;
|
||||
var range = safe_decode_range(ws["!ref"]);
|
||||
var dense = Array.isArray(ws);
|
||||
var dense = ws["!data"] != null;
|
||||
var cols = [];
|
||||
var max_R = Math.min(range.e.r, 8191);
|
||||
for(var R = range.s.r; R <= max_R; ++R) {
|
||||
@ -208,7 +208,7 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) {
|
||||
if(R === range.s.r) cols[C] = encode_col(C);
|
||||
var ref = cols[C] + rr;
|
||||
var cell = dense ? (ws[R]||[])[C] : ws[ref];
|
||||
var cell = dense ? (ws["!data"][R]||[])[C] : ws[ref];
|
||||
if(!cell || cell.t == "z") continue;
|
||||
/* TODO: FORMULA19 NUMBER18 records */
|
||||
if(cell.t == "n") {
|
||||
@ -919,7 +919,7 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
prep_blob(d, 0);
|
||||
var o = opts || {};
|
||||
if(DENSE != null && o.dense == null) o.dense = DENSE;
|
||||
var s/*:Worksheet*/ = ((o.dense ? [] : {})/*:any*/);
|
||||
var s/*:Worksheet*/ = ({}/*:any*/); if(o.dense) s["!data"] = [];
|
||||
var SST = [], sname = "", formulae = [];
|
||||
var range = {s:{r:-1,c:-1}, e:{r:-1,c:-1}};
|
||||
var cnt = 0, type = 0, C = 0, R = 0;
|
||||
@ -956,7 +956,7 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
|
||||
case 0x0601: { /* BOS */
|
||||
var sidx = p.read_shift(2);
|
||||
s = ((o.dense ? [] : {})/*:any*/);
|
||||
s = ({}/*:any*/); if(o.dense) s["!data"] = [];
|
||||
range.s.c = p.read_shift(2);
|
||||
range.e.c = p.read_shift(2);
|
||||
range.s.r = p.read_shift(4);
|
||||
@ -993,6 +993,7 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
R = p.read_shift(4), cnt = p.read_shift(4);
|
||||
if(range.s.r > R) range.s.r = R;
|
||||
if(range.e.r < R + cnt - 1) range.e.r = R + cnt - 1;
|
||||
var CC = encode_col(C);
|
||||
while(p.l < p.length) {
|
||||
var cell = { t: "z" };
|
||||
var flags = p.read_shift(1);
|
||||
@ -1015,10 +1016,10 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
default: throw "Unsupported delta for QPW cell type " + (flags & 0x1F);
|
||||
}
|
||||
if(!(!o.sheetStubs && cell.t == "z")) {
|
||||
if(Array.isArray(s)) {
|
||||
if(!s[R]) s[R] = [];
|
||||
s[R][C] = cell;
|
||||
} else s[encode_cell({r:R, c:C})] = cell;
|
||||
if(s["!data"] != null) {
|
||||
if(!s["!data"][R]) s["!data"][R] = [];
|
||||
s["!data"][R][C] = cell;
|
||||
} else s[CC + encode_row(R)] = cell;
|
||||
}
|
||||
++R; --cnt;
|
||||
while(mul-- > 0 && cnt >= 0) {
|
||||
@ -1034,10 +1035,10 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
default: throw "Cannot apply repeat for QPW cell type " + (flags & 0x1F);
|
||||
}
|
||||
if(!(!o.sheetStubs && cell.t == "z")) {
|
||||
if(Array.isArray(s)) {
|
||||
if(!s[R]) s[R] = [];
|
||||
s[R][C] = cell;
|
||||
} else s[encode_cell({r:R, c:C})] = cell;
|
||||
if(s["!data"] != null) {
|
||||
if(!s["!data"][R]) s["!data"][R] = [];
|
||||
s["!data"][R][C] = cell;
|
||||
} else s[CC + encode_row(R)] = cell;
|
||||
}
|
||||
++R; --cnt;
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ var rs_to_html = /*#__PURE__*/(function parse_rs_factory() {
|
||||
})();
|
||||
|
||||
/* 18.4.8 si CT_Rst */
|
||||
var sitregex = /<(?:\w+:)?t[^>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r>/;
|
||||
var sitregex = /<(?:\w+:)?t[^>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r\b[^>]*>/;
|
||||
var sirphregex = /<(?:\w+:)?rPh.*?>([\s\S]*?)<\/(?:\w+:)?rPh>/g;
|
||||
function parse_si(x, opts) {
|
||||
var html = opts ? opts.cellHTML : true;
|
||||
@ -229,6 +229,7 @@ function write_sst_xml(sst/*:SST*/, opts)/*:string*/ {
|
||||
else {
|
||||
sitag += "<t";
|
||||
if(!s.t) s.t = "";
|
||||
if(typeof s.t !== "string") s.t = String(s.t);
|
||||
if(s.t.match(straywsregex)) sitag += ' xml:space="preserve"';
|
||||
sitag += ">" + escapexml(s.t) + "</t>";
|
||||
}
|
||||
|
@ -13,14 +13,18 @@ function rtf_to_sheet(d, opts) {
|
||||
}
|
||||
function rtf_to_sheet_str(str, opts) {
|
||||
var o = opts || {};
|
||||
var ws = o.dense ? [] : {};
|
||||
var ws = {};
|
||||
var dense = o.dense;
|
||||
if (dense)
|
||||
ws["!data"] = [];
|
||||
var rows = str.match(/\\trowd[\s\S]*?\\row\b/g);
|
||||
if (!rows)
|
||||
throw new Error("RTF missing table");
|
||||
var range = { s: { c: 0, r: 0 }, e: { c: 0, r: rows.length - 1 } };
|
||||
var row = [];
|
||||
rows.forEach(function(rowtf, R) {
|
||||
if (Array.isArray(ws))
|
||||
ws[R] = [];
|
||||
if (dense)
|
||||
row = ws["!data"][R] = [];
|
||||
var rtfre = /\\[\w\-]+\b/g;
|
||||
var last_index = 0;
|
||||
var res;
|
||||
@ -46,8 +50,8 @@ function rtf_to_sheet_str(str, opts) {
|
||||
cell.w = cell.v;
|
||||
cell.v = fuzzynum(cell.v);
|
||||
}
|
||||
if (Array.isArray(ws))
|
||||
ws[R][C] = cell;
|
||||
if (dense)
|
||||
row[C] = cell;
|
||||
else
|
||||
ws[encode_cell({ r: R, c: C })] = cell;
|
||||
}
|
||||
@ -75,15 +79,17 @@ function sheet_to_rtf(ws, opts) {
|
||||
if (!ws["!ref"])
|
||||
return o[0] + "}";
|
||||
var r = safe_decode_range(ws["!ref"]), cell;
|
||||
var dense = Array.isArray(ws);
|
||||
var dense = ws["!data"] != null, row = [];
|
||||
for (var R = r.s.r; R <= r.e.r; ++R) {
|
||||
o.push("\\trowd\\trautofit1");
|
||||
for (var C = r.s.c; C <= r.e.c; ++C)
|
||||
o.push("\\cellx" + (C + 1));
|
||||
o.push("\\pard\\intbl");
|
||||
if (dense)
|
||||
row = ws["!data"][R] || [];
|
||||
for (C = r.s.c; C <= r.e.c; ++C) {
|
||||
var coord = encode_cell({ r: R, c: C });
|
||||
cell = dense ? (ws[R] || [])[C] : ws[coord];
|
||||
cell = dense ? row[C] : ws[coord];
|
||||
if (!cell || cell.v == null && (!cell.f || cell.F)) {
|
||||
o.push(" \\cell");
|
||||
continue;
|
||||
|
@ -71,7 +71,7 @@ function parse_xlmeta_xml(data, name, opts) {
|
||||
lastmeta.offsets.push(+y.i);
|
||||
break;
|
||||
default:
|
||||
if (!pass && opts.WTF)
|
||||
if (!pass && (opts == null ? void 0 : opts.WTF))
|
||||
throw new Error("unrecognized " + y[0] + " in metadata");
|
||||
}
|
||||
return x;
|
||||
|
@ -1,15 +1,15 @@
|
||||
function sheet_insert_comments(sheet, comments/*:Array<RawComment>*/, threaded/*:boolean*/, people/*:?Array<any>*/) {
|
||||
var dense = Array.isArray(sheet);
|
||||
function sheet_insert_comments(sheet/*:WorkSheet*/, comments/*:Array<RawComment>*/, threaded/*:boolean*/, people/*:?Array<any>*/) {
|
||||
var dense = sheet["!data"] != null;
|
||||
var cell/*:Cell*/;
|
||||
comments.forEach(function(comment) {
|
||||
var r = decode_cell(comment.ref);
|
||||
if(dense) {
|
||||
if(!sheet[r.r]) sheet[r.r] = [];
|
||||
cell = sheet[r.r][r.c];
|
||||
if(!sheet["!data"][r.r]) sheet["!data"][r.r] = [];
|
||||
cell = sheet["!data"][r.r][r.c];
|
||||
} else cell = sheet[comment.ref];
|
||||
if (!cell) {
|
||||
cell = ({t:"z"}/*:any*/);
|
||||
if(dense) sheet[r.r][r.c] = cell;
|
||||
if(dense) sheet["!data"][r.r][r.c] = cell;
|
||||
else sheet[comment.ref] = cell;
|
||||
var range = safe_decode_range(sheet["!ref"]||"BDWGO1000001:A1");
|
||||
if(range.s.r > r.r) range.s.r = r.r;
|
||||
@ -17,7 +17,7 @@ function sheet_insert_comments(sheet, comments/*:Array<RawComment>*/, threaded/*
|
||||
if(range.s.c > r.c) range.s.c = r.c;
|
||||
if(range.e.c < r.c) range.e.c = r.c;
|
||||
var encoded = encode_range(range);
|
||||
if (encoded !== sheet["!ref"]) sheet["!ref"] = encoded;
|
||||
sheet["!ref"] = encoded;
|
||||
}
|
||||
|
||||
if (!cell.c) cell.c = [];
|
||||
@ -35,4 +35,3 @@ function sheet_insert_comments(sheet, comments/*:Array<RawComment>*/, threaded/*
|
||||
cell.c.push(o);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -50,21 +50,27 @@ function write_comments_xml(data/*::, opts*/) {
|
||||
o.push("<commentList>");
|
||||
data.forEach(function(d) {
|
||||
/* 18.7.3 CT_Comment */
|
||||
var lastauthor = 0, ts = [];
|
||||
var lastauthor = 0, ts = [], tcnt = 0;
|
||||
if(d[1][0] && d[1][0].T && d[1][0].ID) lastauthor = iauthor.indexOf("tc=" + d[1][0].ID);
|
||||
else d[1].forEach(function(c) {
|
||||
d[1].forEach(function(c) {
|
||||
if(c.a) lastauthor = iauthor.indexOf(escapexml(c.a));
|
||||
ts.push(c.t||"");
|
||||
if(c.T) ++tcnt;
|
||||
ts.push(c.t == null ? "" : escapexml(c.t));
|
||||
});
|
||||
o.push('<comment ref="' + d[0] + '" authorId="' + lastauthor + '"><text>');
|
||||
if(ts.length <= 1) o.push(writetag("t", escapexml(ts[0]||"")));
|
||||
else {
|
||||
if(tcnt === 0) {
|
||||
d[1].forEach(function(c) {
|
||||
o.push('<comment ref="' + d[0] + '" authorId="' + iauthor.indexOf(escapexml(c.a)) + '"><text>');
|
||||
o.push(writetag("t", c.t == null ? "" : escapexml(c.t)));
|
||||
o.push('</text></comment>');
|
||||
});
|
||||
} else {
|
||||
/* based on Threaded Comments -> Comments projection */
|
||||
o.push('<comment ref="' + d[0] + '" authorId="' + lastauthor + '"><text>');
|
||||
var t = "Comment:\n " + (ts[0]) + "\n";
|
||||
for(var i = 1; i < ts.length; ++i) t += "Reply:\n " + ts[i] + "\n";
|
||||
o.push(writetag("t", escapexml(t)));
|
||||
o.push('</text></comment>');
|
||||
}
|
||||
o.push('</text></comment>');
|
||||
});
|
||||
o.push("</commentList>");
|
||||
if(o.length>2) { o[o.length] = ('</comments>'); o[1]=o[1].replace("/>",">"); }
|
||||
|
@ -20,7 +20,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
|
||||
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
|
||||
|
||||
/* 18.3.1.99 worksheet CT_Worksheet */
|
||||
var s = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
|
||||
var s = ({}/*:any*/); if(opts.dense) s["!data"] = [];
|
||||
var refguess/*:Range*/ = ({s: {r:2000000, c:2000000}, e: {r:0, c:0} }/*:any*/);
|
||||
|
||||
var data1 = "", data2 = "";
|
||||
@ -39,7 +39,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
|
||||
var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
|
||||
if(ridx > 0) {
|
||||
var ref = data1.slice(ridx,ridx+50).match(dimregex);
|
||||
if(ref) parse_ws_xml_dim(s, ref[1]);
|
||||
if(ref && !(opts && opts.nodim)) parse_ws_xml_dim(s, ref[1]);
|
||||
}
|
||||
|
||||
/* 18.3.1.88 sheetViews CT_SheetViews */
|
||||
@ -75,6 +75,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
|
||||
var margins = data2.match(marginregex);
|
||||
if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));
|
||||
|
||||
if(opts && opts.nodim) refguess.s.c = refguess.s.r = 0;
|
||||
if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
|
||||
if(opts.sheetRows > 0 && s["!ref"]) {
|
||||
var tmpref = safe_decode_range(s["!ref"]);
|
||||
@ -149,7 +150,7 @@ function write_ws_xml_protection(sp)/*:string*/ {
|
||||
}
|
||||
|
||||
function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
|
||||
var dense = Array.isArray(s);
|
||||
var dense = s["!data"] != null;
|
||||
for(var i = 0; i != data.length; ++i) {
|
||||
var val = parsexmltag(utf8read(data[i]), true);
|
||||
if(!val.ref) return;
|
||||
@ -165,11 +166,11 @@ function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
|
||||
if(val.tooltip) { val.Tooltip = val.tooltip; delete val.tooltip; }
|
||||
var rng = safe_decode_range(val.ref);
|
||||
for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
|
||||
var addr = encode_cell({c:C,r:R});
|
||||
var addr = encode_col(C) + encode_row(R);
|
||||
if(dense) {
|
||||
if(!s[R]) s[R] = [];
|
||||
if(!s[R][C]) s[R][C] = {t:"z",v:undefined};
|
||||
s[R][C].l = val;
|
||||
if(!s["!data"][R]) s["!data"][R] = [];
|
||||
if(!s["!data"][R][C]) s["!data"][R][C] = {t:"z",v:undefined};
|
||||
s["!data"][R][C].l = val;
|
||||
} else {
|
||||
if(!s[addr]) s[addr] = {t:"z",v:undefined};
|
||||
s[addr].l = val;
|
||||
@ -299,7 +300,10 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string
|
||||
var ff = cell.F && cell.F.slice(0, ref.length) == ref ? {t:"array", ref:cell.F} : null;
|
||||
v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : "");
|
||||
}
|
||||
if(cell.l) ws['!links'].push([ref, cell.l]);
|
||||
if(cell.l) {
|
||||
cell.l.display = escapexml(vv);
|
||||
ws['!links'].push([ref, cell.l]);
|
||||
}
|
||||
if(cell.D) o.cm = 1;
|
||||
return writextag('c', v, o);
|
||||
}
|
||||
@ -318,7 +322,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
|
||||
var do_format = Array.isArray(styles.CellXf), cf;
|
||||
var arrayf/*:Array<[Range, string]>*/ = [];
|
||||
var sharedf = [];
|
||||
var dense = Array.isArray(s);
|
||||
var dense = s["!data"] != null;
|
||||
var rows/*:Array<RowInfo>*/ = [], rowobj = {}, rowrite = false;
|
||||
var sheetStubs = !!opts.sheetStubs;
|
||||
for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
|
||||
@ -349,8 +353,10 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
|
||||
tag = parsexmltag(x.slice(rstarti,ri), true);
|
||||
tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
|
||||
if(opts.sheetRows && opts.sheetRows < tagr) continue;
|
||||
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
|
||||
if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
|
||||
if(!opts.nodim) {
|
||||
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
|
||||
if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
|
||||
}
|
||||
|
||||
if(opts && opts.cellStyles) {
|
||||
rowobj = {}; rowrite = false;
|
||||
@ -481,10 +487,16 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
|
||||
var cm = (opts.xlmeta.Cell||[])[+tag.cm-1];
|
||||
if(cm && cm.type == 'XLDAPR') p.D = true;
|
||||
}
|
||||
var _r;
|
||||
if(opts.nodim) {
|
||||
_r = decode_cell(tag.r);
|
||||
if(guess.s.r > _r.r) guess.s.r = _r.r;
|
||||
if(guess.e.r < _r.r) guess.e.r = _r.r;
|
||||
}
|
||||
if(dense) {
|
||||
var _r = decode_cell(tag.r);
|
||||
if(!s[_r.r]) s[_r.r] = [];
|
||||
s[_r.r][_r.c] = p;
|
||||
_r = decode_cell(tag.r);
|
||||
if(!s["!data"][_r.r]) s["!data"][_r.r] = [];
|
||||
s["!data"][_r.r][_r.c] = p;
|
||||
} else s[tag.r] = p;
|
||||
}
|
||||
}
|
||||
@ -493,7 +505,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
|
||||
|
||||
function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*//*::, rels*/)/*:string*/ {
|
||||
var o/*:Array<string>*/ = [], r/*:Array<string>*/ = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols/*:Array<string>*/ = [], R=0, C=0, rows = ws['!rows'];
|
||||
var dense = Array.isArray(ws);
|
||||
var dense = ws["!data"] != null;
|
||||
var params = ({r:rr}/*:any*/), row/*:RowInfo*/, height = -1;
|
||||
for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
|
||||
for(R = range.s.r; R <= range.e.r; ++R) {
|
||||
@ -501,7 +513,7 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
|
||||
rr = encode_row(R);
|
||||
for(C = range.s.c; C <= range.e.c; ++C) {
|
||||
ref = cols[C] + rr;
|
||||
var _cell = dense ? (ws[R]||[])[C]: ws[ref];
|
||||
var _cell = dense ? (ws["!data"][R]||[])[C]: ws[ref];
|
||||
if(_cell === undefined) continue;
|
||||
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
|
||||
}
|
||||
@ -609,6 +621,7 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
|
||||
}
|
||||
if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1));
|
||||
if(l[1].Tooltip) rel.tooltip = escapexml(l[1].Tooltip);
|
||||
rel.display = l[1].display;
|
||||
o[o.length] = writextag("hyperlink",null,rel);
|
||||
});
|
||||
o[o.length] = "</hyperlinks>";
|
||||
|
@ -41,12 +41,13 @@ function write_BrtRowHdr(R/*:number*/, range, ws) {
|
||||
o.l += 4;
|
||||
|
||||
var caddr = {r:R, c:0};
|
||||
var dense = ws["!data"] != null;
|
||||
for(var i = 0; i < 16; ++i) {
|
||||
if((range.s.c > ((i+1) << 10)) || (range.e.c < (i << 10))) continue;
|
||||
var first = -1, last = -1;
|
||||
for(var j = (i<<10); j < ((i+1)<<10); ++j) {
|
||||
caddr.c = j;
|
||||
var cell = Array.isArray(ws) ? (ws[caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)];
|
||||
var cell = dense ? (ws["!data"][caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)];
|
||||
if(cell) { if(first < 0) first = j; last = j; }
|
||||
}
|
||||
if(first < 0) continue;
|
||||
@ -258,9 +259,10 @@ function parse_BrtCellSt(data) {
|
||||
return [cell, value, 'str'];
|
||||
}
|
||||
function write_BrtCellSt(cell, ncell, o) {
|
||||
var data = cell.v == null ? "" : String(cell.v);
|
||||
if(o == null) o = new_buf(12 + 4 * cell.v.length);
|
||||
write_XLSBCell(ncell, o);
|
||||
write_XLWideString(cell.v, o);
|
||||
write_XLWideString(data, o);
|
||||
return o.length > o.l ? o.slice(0, o.l) : o;
|
||||
}
|
||||
function parse_BrtShortSt(data) {
|
||||
@ -269,9 +271,10 @@ function parse_BrtShortSt(data) {
|
||||
return [cell, value, 'str'];
|
||||
}
|
||||
function write_BrtShortSt(cell, ncell, o) {
|
||||
if(o == null) o = new_buf(8 + 4 * cell.v.length);
|
||||
var data = cell.v == null ? "" : String(cell.v);
|
||||
if(o == null) o = new_buf(8 + 4 * data.length);
|
||||
write_XLSBShortCell(ncell, o);
|
||||
write_XLWideString(cell.v, o);
|
||||
write_XLWideString(data, o);
|
||||
return o.length > o.l ? o.slice(0, o.l) : o;
|
||||
}
|
||||
|
||||
@ -508,7 +511,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
|
||||
var opts = _opts || {};
|
||||
if(!rels) rels = {'!id':{}};
|
||||
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
|
||||
var s/*:Worksheet*/ = (opts.dense ? [] : {});
|
||||
var s/*:Worksheet*/ = ({}); if(opts.dense) s["!data"] = [];
|
||||
|
||||
var ref;
|
||||
var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
|
||||
@ -584,7 +587,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
|
||||
}
|
||||
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
|
||||
C = val[0].c == -1 ? C + 1 : val[0].c;
|
||||
if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
|
||||
if(opts.dense) { if(!s["!data"][R]) s["!data"][R] = []; s["!data"][R][C] = p; }
|
||||
else s[encode_col(C) + rr] = p;
|
||||
if(opts.cellFormula) {
|
||||
af = false;
|
||||
@ -617,7 +620,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
|
||||
if(!opts.sheetStubs || pass) break;
|
||||
p = ({t:'z',v:void 0}/*:any*/);
|
||||
C = val[0].c == -1 ? C + 1 : val[0].c;
|
||||
if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
|
||||
if(opts.dense) { if(!s["!data"][R]) s["!data"][R] = []; s["!data"][R][C] = p; }
|
||||
else s[encode_col(C) + rr] = p;
|
||||
if(refguess.s.r > row.r) refguess.s.r = row.r;
|
||||
if(refguess.s.c > C) refguess.s.c = C;
|
||||
@ -648,11 +651,11 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
|
||||
}
|
||||
for(R=val.rfx.s.r;R<=val.rfx.e.r;++R) for(C=val.rfx.s.c;C<=val.rfx.e.c;++C) {
|
||||
if(opts.dense) {
|
||||
if(!s[R]) s[R] = [];
|
||||
if(!s[R][C]) s[R][C] = {t:'z',v:undefined};
|
||||
s[R][C].l = val;
|
||||
if(!s["!data"][R]) s["!data"][R] = [];
|
||||
if(!s["!data"][R][C]) s["!data"][R][C] = {t:'z',v:undefined};
|
||||
s["!data"][R][C].l = val;
|
||||
} else {
|
||||
addr = encode_cell({c:C,r:R});
|
||||
addr = encode_col(C) + encode_row(R);
|
||||
if(!s[addr]) s[addr] = {t:'z',v:undefined};
|
||||
s[addr].l = val;
|
||||
}
|
||||
@ -662,14 +665,14 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
|
||||
case 0x01AA: /* 'BrtArrFmla' */
|
||||
if(!opts.cellFormula) break;
|
||||
arrayf.push(val);
|
||||
cell = ((opts.dense ? s[R][C] : s[encode_col(C) + rr])/*:any*/);
|
||||
cell = ((opts.dense ? s["!data"][R][C] : s[encode_col(C) + rr])/*:any*/);
|
||||
cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
|
||||
cell.F = encode_range(val[0]);
|
||||
break;
|
||||
case 0x01AB: /* 'BrtShrFmla' */
|
||||
if(!opts.cellFormula) break;
|
||||
sharedf[encode_cell(val[0].s)] = val[1];
|
||||
cell = (opts.dense ? s[R][C] : s[encode_col(C) + rr]);
|
||||
cell = (opts.dense ? s["!data"][R][C] : s[encode_col(C) + rr]);
|
||||
cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
|
||||
break;
|
||||
|
||||
@ -824,7 +827,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
|
||||
switch(cell.t) {
|
||||
case 's': case 'str':
|
||||
if(opts.bookSST) {
|
||||
vv = get_sst_id(opts.Strings, (cell.v/*:any*/), opts.revStrings);
|
||||
vv = get_sst_id(opts.Strings, (cell.v == null ? "" : String(cell.v)/*:any*/), opts.revStrings);
|
||||
o.t = "s"; o.v = vv;
|
||||
if(last_seen) write_record(ba, 0x0012 /* BrtShortIsst */, write_BrtShortIsst(cell, o));
|
||||
else write_record(ba, 0x0007 /* BrtCellIsst */, write_BrtCellIsst(cell, o));
|
||||
@ -862,7 +865,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
|
||||
function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
|
||||
var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols/*:Array<string>*/ = [];
|
||||
write_record(ba, 0x0091 /* BrtBeginSheetData */);
|
||||
var dense = Array.isArray(ws);
|
||||
var dense = ws["!data"] != null;
|
||||
var cap = range.e.r;
|
||||
if(ws['!rows']) cap = Math.max(range.e.r, ws['!rows'].length - 1);
|
||||
for(var R = range.s.r; R <= cap; ++R) {
|
||||
@ -875,7 +878,7 @@ function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Work
|
||||
/* *16384CELL */
|
||||
if(R === range.s.r) cols[C] = encode_col(C);
|
||||
ref = cols[C] + rr;
|
||||
var cell = dense ? (ws[R]||[])[C] : ws[ref];
|
||||
var cell = dense ? (ws["!data"][R]||[])[C] : ws[ref];
|
||||
if(!cell) { last_seen = false; continue; }
|
||||
/* write cell */
|
||||
last_seen = write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen);
|
||||
|
@ -34,7 +34,10 @@ function parse_chart(data/*:?string*/, name/*:string*/, opts, rels, wb, csheet)
|
||||
refguess.e.c = C;
|
||||
col = encode_col(C);
|
||||
cache[0].forEach(function(n,i) {
|
||||
cs[col + encode_row(i)] = {t:'n', v:n, z:cache[1] };
|
||||
if(cs["!data"]) {
|
||||
if(!cs["!data"][i]) cs["!data"][i] = [];
|
||||
cs["!data"][i][C] = {t:'n', v:n, z:cache[1] };
|
||||
} else cs[col + encode_row(i)] = {t:'n', v:n, z:cache[1] };
|
||||
R = i;
|
||||
});
|
||||
if(refguess.e.r < R) refguess.e.r = R;
|
||||
|
@ -207,7 +207,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
|
||||
var Rn;
|
||||
var state = [], tmp;
|
||||
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
|
||||
var sheets = {}, sheetnames/*:Array<string>*/ = [], cursheet/*:Worksheet*/ = (opts.dense ? [] : {}), sheetname = "";
|
||||
var sheets = {}, sheetnames/*:Array<string>*/ = [], cursheet/*:Worksheet*/ = ({}), sheetname = ""; if(opts.dense) cursheet["!data"] = [];
|
||||
var cell = ({}/*:any*/), row = {};// eslint-disable-line no-unused-vars
|
||||
var dtag = xlml_parsexmltag('<Data ss:Type="String">'), didx = 0;
|
||||
var c = 0, r = 0;
|
||||
@ -240,8 +240,8 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
|
||||
if(comments.length > 0) cell.c = comments;
|
||||
if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== void 0) {
|
||||
if(opts.dense) {
|
||||
if(!cursheet[r]) cursheet[r] = [];
|
||||
cursheet[r][c] = cell;
|
||||
if(!cursheet["!data"][r]) cursheet["!data"][r] = [];
|
||||
cursheet["!data"][r][c] = cell;
|
||||
} else cursheet[encode_col(c) + encode_row(r)] = cell;
|
||||
}
|
||||
if(cell.HRef) {
|
||||
@ -261,8 +261,8 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
|
||||
for(var cmd = r; cmd <= rr; ++cmd) {
|
||||
if(cma > c || cmd > r) {
|
||||
if(opts.dense) {
|
||||
if(!cursheet[cmd]) cursheet[cmd] = [];
|
||||
cursheet[cmd][cma] = {t:'z'};
|
||||
if(!cursheet["!data"][cmd]) cursheet["!data"][cmd] = [];
|
||||
cursheet["!data"][cmd][cma] = {t:'z'};
|
||||
} else cursheet[encode_col(cma) + encode_row(cmd)] = {t:'z'};
|
||||
}
|
||||
}
|
||||
@ -321,7 +321,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
|
||||
state.push([Rn[3], false]);
|
||||
tmp = xlml_parsexmltag(Rn[0]);
|
||||
sheetname = unescapexml(tmp.Name);
|
||||
cursheet = (opts.dense ? [] : {});
|
||||
cursheet = ({}); if(opts.dense) cursheet["!data"] = [];
|
||||
merges = [];
|
||||
arrayf = [];
|
||||
rowinfo = [];
|
||||
@ -1177,7 +1177,7 @@ function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbo
|
||||
if(n.hidden) k['ss:Hidden']="1";
|
||||
o.push(writextag("Column",null,k));
|
||||
});
|
||||
var dense = Array.isArray(ws);
|
||||
var dense = ws["!data"] != null;
|
||||
for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
var row = [write_ws_xlml_row(R, (ws['!rows']||[])[R])];
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) {
|
||||
@ -1192,7 +1192,7 @@ function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbo
|
||||
}
|
||||
if(skip) continue;
|
||||
var addr = {r:R,c:C};
|
||||
var ref = encode_cell(addr), cell = dense ? (ws[R]||[])[C] : ws[ref];
|
||||
var ref = encode_col(C) + encode_row(R), cell = dense ? (ws["!data"][R]||[])[C] : ws[ref];
|
||||
row.push(write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr));
|
||||
}
|
||||
row.push("</Row>");
|
||||
|
@ -104,7 +104,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
var wb = ({opts:{}}/*:any*/);
|
||||
var Sheets = {};
|
||||
if(DENSE != null && options.dense == null) options.dense = DENSE;
|
||||
var out/*:Worksheet*/ = ((options.dense ? [] : {})/*:any*/);
|
||||
var out/*:Worksheet*/ = ({}/*:any*/); if(options.dense) out["!data"] = [];
|
||||
var Directory = {};
|
||||
var range/*:Range*/ = ({}/*:any*/);
|
||||
var last_formula = null;
|
||||
@ -157,8 +157,8 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
}
|
||||
{
|
||||
if(options.dense) {
|
||||
if(!out[cell.r]) out[cell.r] = [];
|
||||
out[cell.r][cell.c] = line;
|
||||
if(!out["!data"][cell.r]) out["!data"][cell.r] = [];
|
||||
out["!data"][cell.r][cell.c] = line;
|
||||
} else out[last_cell] = line;
|
||||
}
|
||||
};
|
||||
@ -324,7 +324,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
Workbook.Sheets.push(wsprops);
|
||||
}
|
||||
if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out;
|
||||
out = ((options.dense ? [] : {})/*:any*/);
|
||||
out = ({}/*:any*/); if(options.dense) out["!data"] = [];
|
||||
} break;
|
||||
case 0x0009: case 0x0209: case 0x0409: case 0x0809 /* BOF */: {
|
||||
if(opts.biff === 8) opts.biff = {
|
||||
@ -344,7 +344,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(val.BIFFVer == 0 && val.dt == 0x1000) { opts.biff = 5; seen_codepage = true; set_cp(opts.codepage = 28591); }
|
||||
if(opts.biff == 8 && val.BIFFVer == 0 && val.dt == 16) opts.biff = 2;
|
||||
if(file_depth++) break;
|
||||
out = ((options.dense ? [] : {})/*:any*/);
|
||||
out = ({}/*:any*/); if(options.dense) out["!data"] = [];
|
||||
|
||||
if(opts.biff < 8 && !seen_codepage) { seen_codepage = true; set_cp(opts.codepage = options.codepage || 1252); }
|
||||
|
||||
@ -367,7 +367,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
wsprops = {Hidden:(Directory[s]||{hs:0}).hs, name:cur_sheet };
|
||||
} break;
|
||||
case 0x0203 /* Number */: case 0x0003 /* BIFF2NUM */: case 0x0002 /* BIFF2INT */: {
|
||||
if(out["!type"] == "chart") if(options.dense ? (out[val.r]||[])[val.c]: out[encode_cell({c:val.c, r:val.r})]) ++val.c;
|
||||
if(out["!type"] == "chart") if(options.dense ? (out["!data"][val.r]||[])[val.c]: out[encode_col(val.c) + encode_row(val.r)]) ++val.c;
|
||||
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe]||{}, v:val.val, t:'n'}/*:any*/);
|
||||
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
@ -404,7 +404,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F;
|
||||
else temp_val.F = ((options.dense ? (out["!data"][_fr]||[])[_fc]: out[_fe]) || {}).F;
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
@ -429,7 +429,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
case 0x0021: case 0x0221 /* Array */: {
|
||||
arrayf.push(val);
|
||||
var _arraystart = encode_cell(val[0].s);
|
||||
cc = options.dense ? (out[val[0].s.r]||[])[val[0].s.c] : out[_arraystart];
|
||||
cc = options.dense ? (out["!data"][val[0].s.r]||[])[val[0].s.c] : out[_arraystart];
|
||||
if(options.cellFormula && cc) {
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
if(!_arraystart || !cc) break;
|
||||
@ -443,7 +443,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
/* TODO: capture range */
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
sharedf[encode_cell(last_formula.cell)]= val[0];
|
||||
cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
|
||||
cc = options.dense ? (out["!data"][last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
|
||||
(cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
}
|
||||
} break;
|
||||
@ -508,25 +508,25 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
case 0x01b8 /* HLink */: {
|
||||
for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
|
||||
for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
|
||||
cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
|
||||
cc = options.dense ? (out["!data"][rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
|
||||
if(cc) cc.l = val[1];
|
||||
}
|
||||
} break;
|
||||
case 0x0800 /* HLinkTooltip */: {
|
||||
for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
|
||||
for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
|
||||
cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
|
||||
cc = options.dense ? (out["!data"][rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
|
||||
if(cc && cc.l) cc.l.Tooltip = val[1];
|
||||
}
|
||||
} break;
|
||||
case 0x001c /* Note */: {
|
||||
if(opts.biff <= 5 && opts.biff >= 2) break; /* TODO: BIFF5 */
|
||||
cc = options.dense ? (out[val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
|
||||
cc = options.dense ? (out["!data"][val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
|
||||
var noteobj = objects[val[2]];
|
||||
if(!cc) {
|
||||
if(options.dense) {
|
||||
if(!out[val[0].r]) out[val[0].r] = [];
|
||||
cc = out[val[0].r][val[0].c] = ({t:"z"}/*:any*/);
|
||||
if(!out["!data"][val[0].r]) out["!data"][val[0].r] = [];
|
||||
cc = out["!data"][val[0].r][val[0].c] = ({t:"z"}/*:any*/);
|
||||
} else {
|
||||
cc = out[encode_cell(val[0])] = ({t:"z"}/*:any*/);
|
||||
}
|
||||
|
@ -68,27 +68,27 @@ function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n
|
||||
case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
|
||||
/* TODO: codepage, sst */
|
||||
case 's': case 'str':
|
||||
write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, (cell.v||"").slice(0,255)));
|
||||
write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v == null ? "" : String(cell.v).slice(0,255)));
|
||||
return;
|
||||
}
|
||||
write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
|
||||
}
|
||||
|
||||
function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
|
||||
var dense = Array.isArray(ws);
|
||||
var dense = ws["!data"] != null;
|
||||
var range = safe_decode_range(ws['!ref'] || "A1"), ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
|
||||
if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
|
||||
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
|
||||
range.e.c = Math.min(range.e.c, 0xFF);
|
||||
range.e.r = Math.min(range.e.c, 0x3FFF);
|
||||
ref = encode_range(range);
|
||||
}
|
||||
var row = [];
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
|
||||
for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
if(dense) row = ws["!data"][R] || [];
|
||||
rr = encode_row(R);
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) {
|
||||
if(R === range.s.r) cols[C] = encode_col(C);
|
||||
ref = cols[C] + rr;
|
||||
var cell = dense ? (ws[R]||[])[C] : ws[ref];
|
||||
for(C = range.s.c; C <= range.e.c; ++C) {
|
||||
var cell = dense ? row[C] : ws[cols[C] + rr];
|
||||
if(!cell) continue;
|
||||
/* write cell */
|
||||
write_ws_biff2_cell(ba, cell, R, C, opts);
|
||||
@ -99,7 +99,6 @@ function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/
|
||||
/* Based on test files */
|
||||
function write_biff2_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
|
||||
var o = opts || {};
|
||||
if(DENSE != null && o.dense == null) o.dense = DENSE;
|
||||
var ba = buf_array();
|
||||
var idx = 0;
|
||||
for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i;
|
||||
@ -192,9 +191,9 @@ function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n
|
||||
/* TODO: codepage, sst */
|
||||
case 's': case 'str':
|
||||
if(opts.bookSST) {
|
||||
var isst = get_sst_id(opts.Strings, cell.v, opts.revStrings);
|
||||
var isst = get_sst_id(opts.Strings, cell.v == null ? "" : String(cell.v), opts.revStrings);
|
||||
write_biff_rec(ba, 0x00fd /* LabelSst */, write_LabelSst(R, C, isst, os, opts));
|
||||
} else write_biff_rec(ba, 0x0204 /* Label */, write_Label(R, C, (cell.v||"").slice(0,255), os, opts));
|
||||
} else write_biff_rec(ba, 0x0204 /* Label */, write_Label(R, C, (cell.v == null ? "" : String(cell.v)).slice(0,255), os, opts));
|
||||
break;
|
||||
default:
|
||||
write_biff_rec(ba, 0x0201 /* Blank */, write_XLSCell(R, C, os));
|
||||
@ -207,7 +206,7 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
|
||||
var _WB/*:WBWBProps*/ = ((wb||{}).Workbook||{}/*:any*/);
|
||||
var _sheet/*:WBWSProp*/ = ((_WB.Sheets||[])[idx]||{}/*:any*/);
|
||||
var dense = Array.isArray(ws);
|
||||
var dense = ws["!data"] != null;
|
||||
var b8 = opts.biff == 8;
|
||||
var ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
|
||||
var range = safe_decode_range(ws['!ref'] || "A1");
|
||||
@ -243,12 +242,14 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
|
||||
if(b8) ws['!links'] = [];
|
||||
var comments = [];
|
||||
var row = [];
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
|
||||
for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
if(dense) row = ws["!data"][R] || [];
|
||||
rr = encode_row(R);
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) {
|
||||
if(R === range.s.r) cols[C] = encode_col(C);
|
||||
for(C = range.s.c; C <= range.e.c; ++C) {
|
||||
ref = cols[C] + rr;
|
||||
var cell = dense ? (ws[R]||[])[C] : ws[ref];
|
||||
var cell = dense ? row[C] : ws[ref];
|
||||
if(!cell) continue;
|
||||
/* write cell */
|
||||
write_ws_biff8_cell(ba, cell, R, C, opts);
|
||||
|
@ -1,8 +1,8 @@
|
||||
/* note: browser DOM element cannot see mso- style attrs, must parse */
|
||||
function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ {
|
||||
var opts = _opts || {};
|
||||
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
|
||||
var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
|
||||
var dense = (opts.dense != null) ? opts.dense : DENSE;
|
||||
var ws/*:Worksheet*/ = ({}/*:any*/); if(dense) ws["!data"] = [];
|
||||
str = str.replace(/<!--.*?-->/g, "");
|
||||
var mtch/*:any*/ = str.match(/<table/i);
|
||||
if(!mtch) throw new Error("Invalid HTML: could not find <table>");
|
||||
@ -48,7 +48,7 @@ function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ {
|
||||
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
|
||||
o.z = opts.dateNF || table_fmt[14];
|
||||
}
|
||||
if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; }
|
||||
if(dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = o; }
|
||||
else ws[encode_cell({r:R, c:C})] = o;
|
||||
C += CS;
|
||||
}
|
||||
@ -61,6 +61,7 @@ function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HT
|
||||
var M/*:Array<Range>*/ = (ws['!merges'] ||[]);
|
||||
var oo/*:Array<string>*/ = [];
|
||||
var sp = ({}/*:any*/);
|
||||
var dense = ws["!data"] != null;
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var RS = 0, CS = 0;
|
||||
for(var j = 0; j < M.length; ++j) {
|
||||
@ -70,8 +71,8 @@ function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HT
|
||||
RS = M[j].e.r - M[j].s.r + 1; CS = M[j].e.c - M[j].s.c + 1; break;
|
||||
}
|
||||
if(RS < 0) continue;
|
||||
var coord = encode_cell({r:R,c:C});
|
||||
var cell = o.dense ? (ws[R]||[])[C] : ws[coord];
|
||||
var coord = encode_col(C) + encode_row(R);
|
||||
var cell = dense ? (ws["!data"][R]||[])[C] : ws[coord];
|
||||
/* TODO: html entities */
|
||||
var w = (cell && cell.v != null) && (cell.h || escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || "";
|
||||
sp = ({}/*:any*/);
|
||||
@ -119,7 +120,6 @@ function sheet_to_html(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*//*, wb:?Workboo
|
||||
var footer = o.footer != null ? o.footer : HTML_END;
|
||||
var out/*:Array<string>*/ = [header];
|
||||
var r = decode_range(ws['!ref']);
|
||||
o.dense = Array.isArray(ws);
|
||||
out.push(make_html_preamble(ws, r, o));
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
|
||||
out.push("</table>" + footer);
|
||||
@ -134,7 +134,7 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
|
||||
}
|
||||
|
||||
var opts = _opts || {};
|
||||
if(DENSE != null) opts.dense = DENSE;
|
||||
var dense = ws["!data"] != null;
|
||||
var or_R = 0, or_C = 0;
|
||||
if(opts.origin != null) {
|
||||
if(typeof opts.origin == 'number') or_R = opts.origin;
|
||||
@ -199,7 +199,7 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
|
||||
l = Aelts[Aelti].getAttribute("href"); if(l.charAt(0) != "#") break;
|
||||
}
|
||||
if(l && l.charAt(0) != "#" && l.slice(0, 11).toLowerCase() != 'javascript:') o.l = ({ Target: l });
|
||||
if(opts.dense) { if(!ws[R + or_R]) ws[R + or_R] = []; ws[R + or_R][C + or_C] = o; }
|
||||
if(dense) { if(!ws["!data"][R + or_R]) ws["!data"][R + or_R] = []; ws["!data"][R + or_R][C + or_C] = o; }
|
||||
else ws[encode_cell({c:C + or_C, r:R + or_R})] = o;
|
||||
if(range.e.c < C + or_C) range.e.c = C + or_C;
|
||||
C += CS;
|
||||
@ -215,7 +215,7 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
|
||||
|
||||
function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
|
||||
var opts = _opts || {};
|
||||
var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
|
||||
var ws/*:Worksheet*/ = ({}/*:any*/); if(opts.dense) ws["!data"] = [];
|
||||
return sheet_add_dom(ws, table, _opts);
|
||||
}
|
||||
|
||||
|
@ -245,7 +245,7 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
var sheetag/*:: = {name:"", '名称':""}*/;
|
||||
var rowtag/*:: = {'行号':""}*/;
|
||||
var Sheets = {}, SheetNames/*:Array<string>*/ = [];
|
||||
var ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
|
||||
var ws = ({}/*:any*/); if(opts.dense) ws["!data"] = [];
|
||||
var Rn, q/*:: :any = ({t:"", v:null, z:null, w:"",c:[],}:any)*/;
|
||||
var ctag = ({value:""}/*:any*/);
|
||||
var textp = "", textpidx = 0, textptag/*:: = {}*/;
|
||||
@ -289,7 +289,7 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
sheetag = parsexmltag(Rn[0], false);
|
||||
R = C = -1;
|
||||
range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0;
|
||||
ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/); merges = [];
|
||||
ws = ({}/*:any*/); if(opts.dense) ws["!data"] = []; merges = [];
|
||||
rowinfo = [];
|
||||
intable = true;
|
||||
}
|
||||
@ -309,7 +309,7 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
case 'covered-table-cell': // 9.1.5 <table:covered-table-cell>
|
||||
if(Rn[1] !== '/') ++C;
|
||||
if(opts.sheetStubs) {
|
||||
if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = {t:'z'}; }
|
||||
if(opts.dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = {t:'z'}; }
|
||||
else ws[encode_cell({r:R,c:C})] = {t:'z'};
|
||||
}
|
||||
textp = ""; textR = [];
|
||||
@ -325,10 +325,10 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
if((ctag['数据类型'] || ctag['value-type']) == "string") {
|
||||
q.t = "s"; q.v = unescapexml(ctag['string-value'] || "");
|
||||
if(opts.dense) {
|
||||
if(!ws[R]) ws[R] = [];
|
||||
ws[R][C] = q;
|
||||
if(!ws["!data"][R]) ws["!data"][R] = [];
|
||||
ws["!data"][R][C] = q;
|
||||
} else {
|
||||
ws[encode_cell({r:R,c:C})] = q;
|
||||
ws[encode_col(C) + encode_row(R)] = q;
|
||||
}
|
||||
}
|
||||
C+= colpeat-1;
|
||||
@ -405,9 +405,9 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
for(var rpt = 0; rpt < rowpeat; ++rpt) {
|
||||
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
|
||||
if(opts.dense) {
|
||||
if(!ws[R + rpt]) ws[R + rpt] = [];
|
||||
ws[R + rpt][C] = rpt == 0 ? q : dup(q);
|
||||
while(--colpeat > 0) ws[R + rpt][C + colpeat] = dup(q);
|
||||
if(!ws["!data"][R + rpt]) ws["!data"][R + rpt] = [];
|
||||
ws["!data"][R + rpt][C] = rpt == 0 ? q : dup(q);
|
||||
while(--colpeat > 0) ws["!data"][R + rpt][C + colpeat] = dup(q);
|
||||
} else {
|
||||
ws[encode_cell({r:R + rpt,c:C})] = q;
|
||||
while(--colpeat > 0) ws[encode_cell({r:R + rpt,c:C + colpeat})] = dup(q);
|
||||
|
@ -211,7 +211,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
|
||||
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="ta1">\n');
|
||||
var R=0,C=0, range = decode_range(ws['!ref']||"A1");
|
||||
var marr/*:Array<Range>*/ = ws['!merges'] || [], mi = 0;
|
||||
var dense = Array.isArray(ws);
|
||||
var dense = ws["!data"] != null;
|
||||
if(ws["!cols"]) {
|
||||
for(C = 0; C <= range.e.c; ++C) o.push(' <table:table-column' + (ws["!cols"][C] ? ' table:style-name="co' + ws["!cols"][C].ods + '"' : '') + '></table:table-column>\n');
|
||||
}
|
||||
@ -237,7 +237,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
|
||||
break;
|
||||
}
|
||||
if(skip) { o.push(covered_cell_xml); continue; }
|
||||
var ref = encode_cell({r:R, c:C}), cell = dense ? (ws[R]||[])[C]: ws[ref];
|
||||
var ref = encode_cell({r:R, c:C}), cell = dense ? (ws["!data"][R]||[])[C]: ws[ref];
|
||||
if(cell && cell.f) {
|
||||
ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f));
|
||||
if(cell.F) {
|
||||
@ -347,9 +347,10 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
|
||||
var nfi = 69;
|
||||
wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
|
||||
if(!ws) return;
|
||||
var dense = (ws["!data"] != null);
|
||||
var range = decode_range(ws["!ref"]);
|
||||
for(var R = 0; R <= range.e.r; ++R) for(var C = 0; C <= range.e.c; ++C) {
|
||||
var c = Array.isArray(ws) ? (ws[R]||[])[C] : ws[encode_cell({r:R,c:C})];
|
||||
var c = dense ? (ws["!data"][R]||[])[C] : ws[encode_cell({r:R,c:C})];
|
||||
if(!c || !c.z || c.z.toLowerCase() == "general") continue;
|
||||
if(!nfs[c.z]) {
|
||||
var out = write_number_format_ods(c.z, "N" + nfi);
|
||||
|
1483
bits/83_numbers.js
1483
bits/83_numbers.js
File diff suppressed because it is too large
Load Diff
@ -36,12 +36,12 @@ function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/
|
||||
sheets[sheet] = _ws;
|
||||
|
||||
/* scan rels for comments and threaded comments */
|
||||
var tcomments = [];
|
||||
var comments = [], tcomments = [];
|
||||
if(sheetRels && sheetRels[sheet]) keys(sheetRels[sheet]).forEach(function(n) {
|
||||
var dfile = "";
|
||||
if(sheetRels[sheet][n].Type == RELS.CMNT) {
|
||||
dfile = resolve_path(sheetRels[sheet][n].Target, path);
|
||||
var comments = parse_cmnt(getzipdata(zip, dfile, true), dfile, opts);
|
||||
comments = parse_cmnt(getzipdata(zip, dfile, true), dfile, opts);
|
||||
if(!comments || !comments.length) return;
|
||||
sheet_insert_comments(_ws, comments, false);
|
||||
}
|
||||
|
@ -101,7 +101,8 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
|
||||
/* TODO: something more intelligent with themes */
|
||||
|
||||
f = "xl/theme/theme1.xml";
|
||||
zip_add_file(zip, f, write_theme(wb.Themes, opts));
|
||||
var ww = write_theme(wb.Themes, opts);
|
||||
zip_add_file(zip, f, ww);
|
||||
ct.themes.push(f);
|
||||
add_rels(opts.wbrels, -1, "theme/theme1.xml", RELS.THEME);
|
||||
|
||||
|
@ -4,17 +4,17 @@ type MJRObject = {
|
||||
isempty: boolean;
|
||||
};
|
||||
*/
|
||||
function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, header/*:number*/, hdr/*:Array<any>*/, dense/*:boolean*/, o/*:Sheet2JSONOpts*/)/*:MJRObject*/ {
|
||||
function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, header/*:number*/, hdr/*:Array<any>*/, o/*:Sheet2JSONOpts*/)/*:MJRObject*/ {
|
||||
var rr = encode_row(R);
|
||||
var defval = o.defval, raw = o.raw || !Object.prototype.hasOwnProperty.call(o, "raw");
|
||||
var isempty = true;
|
||||
var isempty = true, dense = (sheet["!data"] != null);
|
||||
var row/*:any*/ = (header === 1) ? [] : {};
|
||||
if(header !== 1) {
|
||||
if(Object.defineProperty) try { Object.defineProperty(row, '__rowNum__', {value:R, enumerable:false}); } catch(e) { row.__rowNum__ = R; }
|
||||
else row.__rowNum__ = R;
|
||||
}
|
||||
if(!dense || sheet[R]) for (var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var val = dense ? sheet[R][C] : sheet[cols[C] + rr];
|
||||
if(!dense || sheet["!data"][R]) for (var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var val = dense ? (sheet["!data"][R]||[])[C] : sheet[cols[C] + rr];
|
||||
if(val === undefined || val.t === undefined) {
|
||||
if(defval === undefined) continue;
|
||||
if(hdr[C] != null) { row[hdr[C]] = defval; }
|
||||
@ -63,16 +63,16 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) {
|
||||
var cols/*:Array<string>*/ = [];
|
||||
var out/*:Array<any>*/ = [];
|
||||
var outi = 0, counter = 0;
|
||||
var dense = Array.isArray(sheet);
|
||||
var dense = sheet["!data"] != null;
|
||||
var R = r.s.r, C = 0;
|
||||
var header_cnt = {};
|
||||
if(dense && !sheet[R]) sheet[R] = [];
|
||||
if(dense && !sheet["!data"][R]) sheet["!data"][R] = [];
|
||||
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
|
||||
var rowinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!rows"] || [];
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
if(((colinfo[C]||{}).hidden)) continue;
|
||||
cols[C] = encode_col(C);
|
||||
val = dense ? sheet[R][C] : sheet[cols[C] + rr];
|
||||
val = dense ? sheet["!data"][R][C] : sheet[cols[C] + rr];
|
||||
switch(header) {
|
||||
case 1: hdr[C] = C - r.s.c; break;
|
||||
case 2: hdr[C] = cols[C]; break;
|
||||
@ -91,7 +91,7 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) {
|
||||
}
|
||||
for (R = r.s.r + offset; R <= r.e.r; ++R) {
|
||||
if ((rowinfo[R]||{}).hidden) continue;
|
||||
var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o);
|
||||
var row = make_json_row(sheet, r, R, cols, header, hdr, o);
|
||||
if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) out[outi++] = row.row;
|
||||
}
|
||||
out.length = outi;
|
||||
@ -102,9 +102,11 @@ var qreg = /"/g;
|
||||
function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, fs/*:number*/, rs/*:number*/, FS/*:string*/, o/*:Sheet2CSVOpts*/)/*:?string*/ {
|
||||
var isempty = true;
|
||||
var row/*:Array<string>*/ = [], txt = "", rr = encode_row(R);
|
||||
var dense = sheet["!data"] != null;
|
||||
var datarow = dense && sheet["!data"][R] || [];
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
if (!cols[C]) continue;
|
||||
var val = o.dense ? (sheet[R]||[])[C]: sheet[cols[C] + rr];
|
||||
var val = dense ? datarow[C]: sheet[cols[C] + rr];
|
||||
if(val == null) txt = "";
|
||||
else if(val.v != null) {
|
||||
isempty = false;
|
||||
@ -131,7 +133,6 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ {
|
||||
var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
|
||||
var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
|
||||
var row = "", cols/*:Array<string>*/ = [];
|
||||
o.dense = Array.isArray(sheet);
|
||||
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
|
||||
var rowinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!rows"] || [];
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
|
||||
@ -143,7 +144,6 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ {
|
||||
if(o.strip) row = row.replace(endregex,"");
|
||||
if(row || (o.blankrows !== false)) out.push((w++ ? RS : "") + row);
|
||||
}
|
||||
delete o.dense;
|
||||
return out.join("");
|
||||
}
|
||||
|
||||
@ -160,13 +160,13 @@ function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
|
||||
if(sheet == null || sheet["!ref"] == null) return [];
|
||||
var r = safe_decode_range(sheet['!ref']), rr = "", cols/*:Array<string>*/ = [], C;
|
||||
var cmds/*:Array<string>*/ = [];
|
||||
var dense = Array.isArray(sheet);
|
||||
var dense = sheet["!data"] != null;
|
||||
for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C);
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
rr = encode_row(R);
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
y = cols[C] + rr;
|
||||
x = dense ? (sheet[R]||[])[C] : sheet[y];
|
||||
x = dense ? (sheet["!data"][R]||[])[C] : sheet[y];
|
||||
val = "";
|
||||
if(x === undefined) continue;
|
||||
else if(x.F != null) {
|
||||
@ -191,10 +191,11 @@ function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
|
||||
|
||||
function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet*/ {
|
||||
var o = opts || {};
|
||||
var dense = _ws ? Array.isArray(_ws) : o.dense;
|
||||
var dense = _ws ? (_ws["!data"] != null) : o.dense;
|
||||
if(DENSE != null && dense == null) dense = DENSE;
|
||||
var offset = +!o.skipHeader;
|
||||
var ws/*:Worksheet*/ = _ws || (dense ? ([]/*:any*/) : ({}/*:any*/));
|
||||
var ws/*:Worksheet*/ = _ws || ({});
|
||||
if(!_ws && dense) ws["!data"] = [];
|
||||
var _R = 0, _C = 0;
|
||||
if(ws && o.origin != null) {
|
||||
if(typeof o.origin == 'number') _R = o.origin;
|
||||
@ -213,19 +214,20 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
|
||||
if(_R == -1) { _R = 0; range.e.r = js.length - 1 + offset; }
|
||||
}
|
||||
var hdr/*:Array<string>*/ = o.header || [], C = 0;
|
||||
|
||||
var ROW = [];
|
||||
js.forEach(function (JS, R/*:number*/) {
|
||||
if(!ws[_R + R + offset]) ws[_R + R + offset] = [];
|
||||
var ROW = ws[_R + R + offset];
|
||||
if(dense && !ws["!data"][_R + R + offset]) ws["!data"][_R + R + offset] = [];
|
||||
if(dense) ROW = ws["!data"][_R + R + offset];
|
||||
keys(JS).forEach(function(k) {
|
||||
if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k;
|
||||
var v = JS[k];
|
||||
var t = 'z';
|
||||
var z = "";
|
||||
var ref = dense ? "" : encode_cell({c:_C + C,r:_R + R + offset});
|
||||
var ref = dense ? "" : (encode_col(_C + C) + encode_row(_R + R + offset));
|
||||
var cell/*:Cell*/ = dense ? ROW[_C + C] : ws[ref];
|
||||
if(v && typeof v === 'object' && !(v instanceof Date)){
|
||||
ws[ref] = v;
|
||||
if(dense) ROW[_C + C] = v;
|
||||
else ws[ref] = v;
|
||||
} else {
|
||||
if(typeof v == 'number') t = 'n';
|
||||
else if(typeof v == 'boolean') t = 'b';
|
||||
@ -239,8 +241,7 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
|
||||
if(!cell) {
|
||||
if(!dense) ws[ref] = cell = ({t:t, v:v}/*:any*/);
|
||||
else ROW[_C + C] = cell = ({t:t, v:v}/*:any*/);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
cell.t = t; cell.v = v;
|
||||
delete cell.w; delete cell.R;
|
||||
if(z) cell.z = z;
|
||||
@ -251,9 +252,9 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
|
||||
});
|
||||
range.e.c = Math.max(range.e.c, _C + hdr.length - 1);
|
||||
var __R = encode_row(_R);
|
||||
if(dense && !ws[_R]) ws[_R] = [];
|
||||
if(dense && !ws["!data"][_R]) ws["!data"][_R] = [];
|
||||
if(offset) for(C = 0; C < hdr.length; ++C) {
|
||||
if(dense) ws[_R][C + _C] = {t:'s', v:hdr[C]};
|
||||
if(dense) ws["!data"][_R][C + _C] = {t:'s', v:hdr[C]};
|
||||
else ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]};
|
||||
}
|
||||
ws['!ref'] = encode_range(range);
|
||||
@ -265,18 +266,17 @@ function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ { return sheet_add
|
||||
function ws_get_cell_stub(ws/*:Worksheet*/, R, C/*:?number*/)/*:Cell*/ {
|
||||
/* A1 cell address */
|
||||
if(typeof R == "string") {
|
||||
/* dense */
|
||||
if(Array.isArray(ws)) {
|
||||
if(ws["!data"] != null) {
|
||||
var RC = decode_cell(R);
|
||||
if(!ws[RC.r]) ws[RC.r] = [];
|
||||
return ws[RC.r][RC.c] || (ws[RC.r][RC.c] = {t:'z'});
|
||||
if(!ws["!data"][RC.r]) ws["!data"][RC.r] = [];
|
||||
return ws["!data"][RC.r][RC.c] || (ws["!data"][RC.r][RC.c] = {t:'z'});
|
||||
}
|
||||
return ws[R] || (ws[R] = {t:'z'});
|
||||
}
|
||||
/* cell address object */
|
||||
if(typeof R != "number") return ws_get_cell_stub(ws, encode_cell(R));
|
||||
/* R and C are 0-based indices */
|
||||
return ws_get_cell_stub(ws, encode_cell({r:R,c:C||0}));
|
||||
return ws_get_cell_stub(ws, encode_col(C||0) + encode_row(R));
|
||||
}
|
||||
|
||||
/* find sheet index for given name / validate index */
|
||||
|
@ -10,7 +10,6 @@ function write_csv_stream(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
|
||||
var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
|
||||
var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
|
||||
var row/*:?string*/ = "", cols/*:Array<string>*/ = [];
|
||||
o.dense = Array.isArray(sheet);
|
||||
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
|
||||
var rowinfo/*:Array<RowInfo>*/ = o.skipHidden && sheet["!rows"] || [];
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
|
||||
@ -40,7 +39,6 @@ function write_html_stream(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*/) {
|
||||
var footer = o.footer != null ? o.footer : HTML_END;
|
||||
stream.push(header);
|
||||
var r = decode_range(ws['!ref']);
|
||||
o.dense = Array.isArray(ws);
|
||||
stream.push(make_html_preamble(ws, r, o));
|
||||
var R = r.s.r;
|
||||
var end = false;
|
||||
@ -78,16 +76,16 @@ function write_json_stream(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
|
||||
var rr = encode_row(r.s.r);
|
||||
var cols/*:Array<string>*/ = [];
|
||||
var counter = 0;
|
||||
var dense = Array.isArray(sheet);
|
||||
var dense = sheet["!data"] != null;
|
||||
var R = r.s.r, C = 0;
|
||||
var header_cnt = {};
|
||||
if(dense && !sheet[R]) sheet[R] = [];
|
||||
if(dense && !sheet["!data"][R]) sheet["!data"][R] = [];
|
||||
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
|
||||
var rowinfo/*:Array<RowInfo>*/ = o.skipHidden && sheet["!rows"] || [];
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
if(((colinfo[C]||{}).hidden)) continue;
|
||||
cols[C] = encode_col(C);
|
||||
val = dense ? sheet[R][C] : sheet[cols[C] + rr];
|
||||
val = dense ? sheet["!data"][R][C] : sheet[cols[C] + rr];
|
||||
switch(header) {
|
||||
case 1: hdr[C] = C - r.s.c; break;
|
||||
case 2: hdr[C] = cols[C]; break;
|
||||
@ -108,7 +106,7 @@ function write_json_stream(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
|
||||
stream._read = function() {
|
||||
while(R <= r.e.r) {
|
||||
if ((rowinfo[R-1]||{}).hidden) continue;
|
||||
var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o);
|
||||
var row = make_json_row(sheet, r, R, cols, header, hdr, o);
|
||||
++R;
|
||||
if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) {
|
||||
stream.push(row.row);
|
||||
|
@ -7,6 +7,6 @@ The ecosystem demos were grouped by type in the new demo site:
|
||||
|
||||
- [Nuxt Content](https://docs.sheetjs.com/docs/demos/content#nuxtjs) is now part of "Content and Site Generation"
|
||||
- [The new iOS app demo](https://docs.sheetjs.com/docs/demos/mobile#quasar) uses the Quasar Framework in a VueJS + Vite project to generate a native iOS app.
|
||||
- [`vue3-table-lite` reading, modifying, and writing files](https://docs.sheetjs.com/docs/demo/grid#vue3-table-lite) is now part of "Data Grids and UI"
|
||||
- [`vue3-table-lite` reading, modifying, and writing files](https://docs.sheetjs.com/docs/demos/grid#vue3-table-lite) is now part of "Data Grids and UI"
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
||||
|
39
dist/cpexcel.d.ts
generated
vendored
Normal file
39
dist/cpexcel.d.ts
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
/* codepage.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
// TypeScript Version: 2.2
|
||||
|
||||
/** Codepage index type (integer or string representation) */
|
||||
export type CP$Index = number | string;
|
||||
|
||||
/* Individual codepage converter */
|
||||
export interface CP$Conv {
|
||||
enc: {[n: string]: number; };
|
||||
dec: {[n: number]: string; };
|
||||
}
|
||||
|
||||
/** Encode input type (string, array of characters, Buffer) */
|
||||
export type CP$String = string | string[] | Uint8Array;
|
||||
|
||||
/** Encode output / decode input type */
|
||||
export type CP$Data = string | number[] | Uint8Array;
|
||||
|
||||
/** General utilities */
|
||||
export interface CP$Utils {
|
||||
decode(cp: CP$Index, data: CP$Data): string;
|
||||
encode(cp: CP$Index, data: CP$String, opts?: any): CP$Data;
|
||||
hascp(n: number): boolean;
|
||||
magic: {[cp: string]: string};
|
||||
}
|
||||
|
||||
/* note: TS cannot export top-level indexer, hence default workaround */
|
||||
export interface CP$Module {
|
||||
/** Version string */
|
||||
version: string;
|
||||
|
||||
/** Utility Functions */
|
||||
utils: CP$Utils;
|
||||
|
||||
/** Codepage Converters */
|
||||
[cp: number]: CP$Conv;
|
||||
}
|
||||
export const cptable: CP$Module;
|
||||
export default cptable;
|
31
dist/xlsx.core.min.js
generated
vendored
31
dist/xlsx.core.min.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.core.min.map
generated
vendored
2
dist/xlsx.core.min.map
generated
vendored
File diff suppressed because one or more lines are too long
2124
dist/xlsx.extendscript.js
generated
vendored
2124
dist/xlsx.extendscript.js
generated
vendored
File diff suppressed because it is too large
Load Diff
34
dist/xlsx.full.min.js
generated
vendored
34
dist/xlsx.full.min.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.full.min.map
generated
vendored
2
dist/xlsx.full.min.map
generated
vendored
File diff suppressed because one or more lines are too long
18
dist/xlsx.mini.min.js
generated
vendored
18
dist/xlsx.mini.min.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.mini.min.map
generated
vendored
2
dist/xlsx.mini.min.map
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.zahl.js
generated
vendored
2
dist/xlsx.zahl.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.zahl.mjs
generated
vendored
2
dist/xlsx.zahl.mjs
generated
vendored
File diff suppressed because one or more lines are too long
4
dist/zahl.d.ts
generated
vendored
Normal file
4
dist/zahl.d.ts
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/* zahl.d.ts (C) 2022-present SheetJS */
|
||||
// TypeScript Version: 2.2
|
||||
declare const XLSX_ZAHL_PAYLOAD: string;
|
||||
export default XLSX_ZAHL_PAYLOAD;
|
BIN
formats.png
BIN
formats.png
Binary file not shown.
Before Width: | Height: | Size: 204 KiB |
BIN
legend.png
BIN
legend.png
Binary file not shown.
Before Width: | Height: | Size: 33 KiB |
6
modules/.gitignore
vendored
6
modules/.gitignore
vendored
@ -1,9 +1,3 @@
|
||||
test_files
|
||||
*.node.js
|
||||
*.[Pp][Rr][Oo][Tt][Oo]
|
||||
*.[Ii][Ww][Aa]
|
||||
*.[Jj][Pp][Gg]
|
||||
*.[Pp][Ll][Ii][Ss][Tt]
|
||||
DocumentIdentifier
|
||||
xlsx.zahl.*
|
||||
src/numbers.ts
|
||||
|
@ -13,14 +13,18 @@ function rtf_to_sheet(d, opts) {
|
||||
}
|
||||
function rtf_to_sheet_str(str, opts) {
|
||||
var o = opts || {};
|
||||
var ws = o.dense ? [] : {};
|
||||
var ws = {};
|
||||
var dense = o.dense;
|
||||
if (dense)
|
||||
ws["!data"] = [];
|
||||
var rows = str.match(/\\trowd[\s\S]*?\\row\b/g);
|
||||
if (!rows)
|
||||
throw new Error("RTF missing table");
|
||||
var range = { s: { c: 0, r: 0 }, e: { c: 0, r: rows.length - 1 } };
|
||||
var row = [];
|
||||
rows.forEach(function(rowtf, R) {
|
||||
if (Array.isArray(ws))
|
||||
ws[R] = [];
|
||||
if (dense)
|
||||
row = ws["!data"][R] = [];
|
||||
var rtfre = /\\[\w\-]+\b/g;
|
||||
var last_index = 0;
|
||||
var res;
|
||||
@ -46,8 +50,8 @@ function rtf_to_sheet_str(str, opts) {
|
||||
cell.w = cell.v;
|
||||
cell.v = fuzzynum(cell.v);
|
||||
}
|
||||
if (Array.isArray(ws))
|
||||
ws[R][C] = cell;
|
||||
if (dense)
|
||||
row[C] = cell;
|
||||
else
|
||||
ws[encode_cell({ r: R, c: C })] = cell;
|
||||
}
|
||||
@ -75,15 +79,17 @@ function sheet_to_rtf(ws, opts) {
|
||||
if (!ws["!ref"])
|
||||
return o[0] + "}";
|
||||
var r = safe_decode_range(ws["!ref"]), cell;
|
||||
var dense = Array.isArray(ws);
|
||||
var dense = ws["!data"] != null, row = [];
|
||||
for (var R = r.s.r; R <= r.e.r; ++R) {
|
||||
o.push("\\trowd\\trautofit1");
|
||||
for (var C = r.s.c; C <= r.e.c; ++C)
|
||||
o.push("\\cellx" + (C + 1));
|
||||
o.push("\\pard\\intbl");
|
||||
if (dense)
|
||||
row = ws["!data"][R] || [];
|
||||
for (C = r.s.c; C <= r.e.c; ++C) {
|
||||
var coord = encode_cell({ r: R, c: C });
|
||||
cell = dense ? (ws[R] || [])[C] : ws[coord];
|
||||
cell = dense ? row[C] : ws[coord];
|
||||
if (!cell || cell.v == null && (!cell.f || cell.F)) {
|
||||
o.push(" \\cell");
|
||||
continue;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { WorkBook, WorkSheet, Range, CellObject } from '../';
|
||||
import { WorkBook, WorkSheet, Range, CellObject, DenseSheet, SparseSheet } from '../';
|
||||
import type { utils } from "../";
|
||||
|
||||
declare var encode_cell: typeof utils.encode_cell;
|
||||
@ -26,13 +26,16 @@ function rtf_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
|
||||
function rtf_to_sheet_str(str: string, opts)/*:Worksheet*/ {
|
||||
var o = opts || {};
|
||||
// ESBuild issue 2375
|
||||
var ws: WorkSheet = o.dense ? [] : ({}/*:any*/);
|
||||
var ws: WorkSheet = {} as WorkSheet;
|
||||
var dense = o.dense;
|
||||
if(dense) ws["!data"] = [];
|
||||
|
||||
var rows = str.match(/\\trowd[\s\S]*?\\row\b/g);
|
||||
if(!rows) throw new Error("RTF missing table");
|
||||
var range: Range = {s: {c:0, r:0}, e: {c:0, r:rows.length - 1}};
|
||||
var row: CellObject[] = [];
|
||||
rows.forEach(function(rowtf, R) {
|
||||
if(Array.isArray(ws)) ws[R] = [];
|
||||
if(dense) row = (ws as DenseSheet)["!data"][R] = [] as CellObject[];
|
||||
var rtfre = /\\[\w\-]+\b/g;
|
||||
var last_index = 0;
|
||||
var res;
|
||||
@ -51,8 +54,8 @@ function rtf_to_sheet_str(str: string, opts)/*:Worksheet*/ {
|
||||
if(cell.v == "TRUE" || cell.v == "FALSE") { cell.v = cell.v == "TRUE"; cell.t = "b"; }
|
||||
else if(!isNaN(fuzzynum(cell.v as string))) { cell.t = 'n'; if(o.cellText !== false) cell.w = cell.v as string; cell.v = fuzzynum(cell.v as string); }
|
||||
|
||||
if(Array.isArray(ws)) ws[R][C] = cell;
|
||||
else ws[encode_cell({r:R, c:C})] = cell;
|
||||
if(dense) row[C] = cell;
|
||||
else (ws as SparseSheet)[encode_cell({r:R, c:C})] = cell;
|
||||
}
|
||||
payload = [];
|
||||
break;
|
||||
@ -79,14 +82,15 @@ function sheet_to_rtf(ws: WorkSheet, opts): string {
|
||||
var o: string[] = ["{\\rtf1\\ansi"];
|
||||
if(!ws["!ref"]) return o[0] + "}";
|
||||
var r = safe_decode_range(ws['!ref']), cell: CellObject;
|
||||
var dense = Array.isArray(ws);
|
||||
var dense = ws["!data"] != null, row: CellObject[] = [];
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
o.push("\\trowd\\trautofit1");
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) o.push("\\cellx" + (C+1));
|
||||
o.push("\\pard\\intbl");
|
||||
if(dense) row = (ws as DenseSheet)["!data"][R] || ([] as CellObject[])
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
var coord = encode_cell({r:R,c:C});
|
||||
cell = dense ? (ws[R]||[])[C]: ws[coord];
|
||||
cell = dense ? row[C] : (ws as SparseSheet)[coord];
|
||||
if(!cell || cell.v == null && (!cell.f || cell.F)) { o.push(" \\cell"); continue; }
|
||||
o.push(" " + (cell.w || (format_cell(cell), cell.w) || "").replace(/[\r\n]/g, "\\par "));
|
||||
o.push("\\cell");
|
||||
@ -95,4 +99,3 @@ function sheet_to_rtf(ws: WorkSheet, opts): string {
|
||||
}
|
||||
return o.join("") + "}";
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ function write_BrtBeginEsmdb(cnt: number, cm: boolean): RawData {
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.34 Metadata */
|
||||
function parse_xlmeta_bin(data, name: string, _opts?: ParseXLMetaOptions): XLMeta {
|
||||
function parse_xlmeta_bin(data: RawData, name: string, _opts?: ParseXLMetaOptions): XLMeta {
|
||||
var out: XLMeta = { Types: [], Cell: [], Value: [] };
|
||||
var opts = _opts || {};
|
||||
var state: number[] = [];
|
||||
|
@ -71,7 +71,7 @@ function parse_xlmeta_xml(data, name, opts) {
|
||||
lastmeta.offsets.push(+y.i);
|
||||
break;
|
||||
default:
|
||||
if (!pass && opts.WTF)
|
||||
if (!pass && (opts == null ? void 0 : opts.WTF))
|
||||
throw new Error("unrecognized " + y[0] + " in metadata");
|
||||
}
|
||||
return x;
|
||||
|
@ -63,7 +63,7 @@ function parse_xlmeta_xml(data: string, name: string, opts?: ParseXLMetaOptions)
|
||||
lastmeta.offsets.push(+y.i);
|
||||
break;
|
||||
|
||||
default: if(!pass && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in metadata');
|
||||
default: if(!pass && opts?.WTF) throw new Error('unrecognized ' + y[0] + ' in metadata');
|
||||
}
|
||||
return x;
|
||||
});
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -2,24 +2,28 @@ LIBFILES=src/types.ts
|
||||
#LIBFILES=$(wildcard src/*.ts)
|
||||
TSFILES=$(wildcard *.ts)
|
||||
ENTRIES=$(subst .ts,.js,$(TSFILES))
|
||||
CC=esbuild@0.14.14
|
||||
|
||||
BAREJS=04_base64.js 45_rtf.js 51_xlsxmeta.js 51_xlsbmeta.js 59_vba.js 64_ftab.js 83_numbers.js
|
||||
|
||||
.PHONY: all
|
||||
all: $(ENTRIES) xlsx.zahl.js
|
||||
all: bits xlsx.zahl.js
|
||||
|
||||
xlsx.zahl.js: test.numbers reframe.node.js
|
||||
.PHONY: bits
|
||||
bits: $(ENTRIES)
|
||||
|
||||
xlsx.zahl.js: test.numbers
|
||||
bash -c ./reframe.sh
|
||||
|
||||
$(BAREJS): %.js: %.ts $(LIBFILES)
|
||||
npx esbuild@0.14.14 $< --outfile=$@ --platform=browser --target=es5
|
||||
npx $(CC) $< --outfile=$@ --platform=browser --target=es5
|
||||
|
||||
%.node.js: %.node.ts $(LIBFILES) src/numbers.ts
|
||||
npx esbuild@0.14.14 $< --bundle --external:xlsx --outfile=$@ --platform=node
|
||||
npx $(CC) $< --bundle --external:xlsx --outfile=$@ --platform=node
|
||||
sed -i '' 's/ts-node/node/g' $@ || sed -i'' 's/ts-node/node/g' $@ || { echo "sed failed"; exit 1; }
|
||||
|
||||
%.js: %.ts $(LIBFILES)
|
||||
npx esbuild@0.14.14 $< --bundle --outfile=$@ --platform=browser --format=iife --global-name=$* --target=es5
|
||||
npx $(CC) $< --bundle --outfile=$@ --platform=browser --format=iife --global-name=$* --target=es5
|
||||
|
||||
src/numbers.ts: 83_numbers.ts
|
||||
cat $< | sed 's/^\/\/<<//g' > $@
|
||||
|
@ -1,631 +0,0 @@
|
||||
/*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
import { decompress_iwa_file, compress_iwa_file, u8concat, parse_iwa_file, write_iwa_file, varint_to_i32, parse_shallow, write_shallow, u8str, stru8, IWAArchiveInfo, parse_TSP_Reference, write_varint49, u8contains, u8_to_dataview, write_new_storage } from "./src/numbers";
|
||||
import { read, writeFile, utils, find, CFB$Entry, CFB$Container } from 'cfb';
|
||||
|
||||
var f = process.argv[2]; var o = process.argv[3];
|
||||
var cfb = read(f, {type: "file"});
|
||||
|
||||
var nuevo = utils.cfb_new();
|
||||
|
||||
interface DependentInfo {
|
||||
deps: number[];
|
||||
location: string;
|
||||
type: number;
|
||||
}
|
||||
var dependents: {[x:number]: DependentInfo} = {};
|
||||
var indices: number[] = [];
|
||||
|
||||
/* First Pass: reframe, clean up junk, collect message space */
|
||||
cfb.FileIndex.map((fi, idx): [CFB$Entry, string] => ([fi, cfb.FullPaths[idx]])).forEach(row => {
|
||||
var fi = row[0], fp = row[1];
|
||||
/* blank all plist files */
|
||||
if(fi.name.match(/\.plist/)) {
|
||||
console.error(`Blanking plist ${fi.name}`);
|
||||
fi.content = new Uint8Array([
|
||||
0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, 0xd0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0a
|
||||
]);
|
||||
utils.cfb_add(nuevo, row[1], fi.content);
|
||||
return;
|
||||
}
|
||||
|
||||
if(fi.type != 2) return;
|
||||
|
||||
/* Remove other metadata */
|
||||
if(!fi.name.match(/\.iwa/)) {
|
||||
if(fi.name.match(/Sh33tJ5/)) return;
|
||||
console.error(`Removing file ${fi.name}`);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reframe .iwa files */
|
||||
var old_content = fi.content;
|
||||
var raw1 = decompress_iwa_file(old_content as Uint8Array);
|
||||
var new_content = compress_iwa_file(raw1);
|
||||
var raw2 = decompress_iwa_file(new_content);
|
||||
for(var i = 0; i < raw1.length; ++i) if(raw1[i] != raw2[i]) throw new Error(`${fi.name} did not properly roundtrip`);
|
||||
|
||||
var x = parse_iwa_file(raw2);
|
||||
x.forEach(ia => {
|
||||
ia.messages.forEach(m => {
|
||||
delete m.meta[2];
|
||||
delete m.meta[4];
|
||||
delete m.meta[5]; // extremely slow open if deleted
|
||||
for(var j = 6; j < m.meta.length; ++j) delete m.meta[j];
|
||||
});
|
||||
});
|
||||
|
||||
x.forEach(packet => {
|
||||
indices.push(packet.id);
|
||||
dependents[packet.id] = { deps: [], location: fp, type: varint_to_i32(packet.messages[0].meta[1][0].data) };
|
||||
});
|
||||
|
||||
var y = write_iwa_file(x);
|
||||
for(var i = 0; i < raw1.length; ++i) if(y[i] != raw1[i]) { console.log(fi.name, i, raw1[i], y[i]); break; }
|
||||
|
||||
var raw3 = compress_iwa_file(y);
|
||||
fi.content = raw3; fi.size = fi.content.length;
|
||||
// utils.cfb_add(nuevo, row[1], fi.content);
|
||||
});
|
||||
|
||||
indices.sort((x,y) => x-y);
|
||||
var indices_varint: Array<[number, Uint8Array]> = indices.filter(x => x > 1).map(x => [x, write_varint49(x)] );
|
||||
|
||||
/* Second pass: build dependency map */
|
||||
cfb.FileIndex.map((fi, idx): [CFB$Entry, string] => ([fi, cfb.FullPaths[idx]])).forEach(row => {
|
||||
var fi = row[0], fp = row[1];
|
||||
if(!fi?.name?.match(/\.iwa/)) return;
|
||||
var x = parse_iwa_file(decompress_iwa_file(fi.content as Uint8Array));
|
||||
|
||||
x.forEach(ia => {
|
||||
ia.messages.forEach(m => {
|
||||
indices_varint.forEach(([i, vi]) => {
|
||||
if(ia.messages.some(mess => varint_to_i32(mess.meta[1][0].data) != 11006 && u8contains(mess.data, vi))) {
|
||||
dependents[i].deps.push(ia.id);
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var deletables = [];
|
||||
function delete_message(id: number, cfb: CFB$Container) {
|
||||
var dep = dependents[id];
|
||||
if(dep?.deps?.length > 0) return console.error(`Message ${id} has dependents ${dep.deps}`);
|
||||
|
||||
//delete dependents[id];
|
||||
indices = indices.filter(x => x != id);
|
||||
|
||||
/* TODO: this really should be a forward map */
|
||||
indices.map(i => dependents[i]).filter(x => x).forEach(dep => {
|
||||
dep.deps = dep.deps.filter(x => x != id);
|
||||
});
|
||||
if(deletables.indexOf(id) == -1) deletables.push(id);
|
||||
}
|
||||
|
||||
function gc(cfb: CFB$Container) {
|
||||
deletables.forEach(id => {
|
||||
var dep = dependents[id];
|
||||
var entry = find(cfb, dep.location);
|
||||
var x = parse_iwa_file(decompress_iwa_file(entry.content as Uint8Array));
|
||||
|
||||
/* remove packet */
|
||||
console.log(`Removing packet ${id} ${dependents[id]?.type || "NaN"}`);
|
||||
for(var xi = 0; xi < x.length; ++xi) {
|
||||
var packet = x[xi];
|
||||
if(packet.id == id) { x.splice(xi,1); --xi; }
|
||||
}
|
||||
|
||||
delete dependents[id];
|
||||
|
||||
entry.content = compress_iwa_file(write_iwa_file(x));
|
||||
entry.size = entry.content.length;
|
||||
});
|
||||
deletables = [];
|
||||
|
||||
}
|
||||
|
||||
function delete_ref(dmeta: ReturnType<typeof parse_shallow>, j: number, me: number) {
|
||||
if(!dmeta) return;
|
||||
if(dmeta[j]) dmeta[j].forEach(pi => {
|
||||
var target = parse_TSP_Reference(pi.data);
|
||||
dependents[target].deps = dependents[target].deps.filter(x => x != me);
|
||||
if(dependents[target].deps.length == 0) delete_message(target, cfb);
|
||||
});
|
||||
delete dmeta[j];
|
||||
}
|
||||
|
||||
function shake() {
|
||||
var done = false;
|
||||
while(!done) {
|
||||
done = true;
|
||||
cfb.FileIndex.map((fi, idx): [CFB$Entry, string] => ([fi, cfb.FullPaths[idx]])).forEach(row => {
|
||||
var fi = row[0], fp = row[1];
|
||||
if(fi.name.match(/\.plist/)) return;
|
||||
if(!fi.name.match(/\.iwa/)) return;
|
||||
var old_content = fi.content;
|
||||
var raw1 = decompress_iwa_file(old_content as Uint8Array);
|
||||
var x = parse_iwa_file(raw1);
|
||||
|
||||
(()=>{
|
||||
for(var i = 0; i < x.length; ++i) {
|
||||
var w = x[i];
|
||||
var type = varint_to_i32(w.messages[0].meta[1][0].data);
|
||||
if(w.id > 10000 && (!dependents[w.id] || !dependents[w.id]?.deps?.length)) {
|
||||
console.log(`Deleting orphan ${fp} ${w.id}`);
|
||||
delete_message(w.id, cfb);
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
var y = write_iwa_file(x);
|
||||
var raw3 = compress_iwa_file(y);
|
||||
//fi.content = raw3;
|
||||
});
|
||||
gc(cfb);
|
||||
}
|
||||
}
|
||||
|
||||
/* Third pass: trim messages */
|
||||
cfb.FileIndex.map((fi, idx): [CFB$Entry, string] => ([fi, cfb.FullPaths[idx]])).forEach(row => {
|
||||
var fi = row[0], fp = row[1];
|
||||
if(!fi?.name?.match(/\.iwa/)) return;
|
||||
var x = parse_iwa_file(decompress_iwa_file(fi.content as Uint8Array));
|
||||
|
||||
trim(x, fi);
|
||||
|
||||
var y = write_iwa_file(x);
|
||||
var raw3 = compress_iwa_file(y);
|
||||
fi.content = raw3;
|
||||
});
|
||||
gc(cfb);
|
||||
|
||||
shake();
|
||||
|
||||
function mutate_row(tri: ReturnType<typeof parse_shallow>) {
|
||||
if(!tri[6]?.[0] || !tri[7]?.[0]) throw "Mutation only works on post-BNC storages!";
|
||||
var wide_offsets = tri[8]?.[0]?.data && varint_to_i32(tri[8][0].data) > 0 || false;
|
||||
var width = wide_offsets ? 4 : 1;
|
||||
var dv = u8_to_dataview(tri[7][0].data);
|
||||
var old_sz = 0, sz = 0;
|
||||
for(var i = 0; i < tri[7][0].data.length / 2; ++i) {
|
||||
sz = dv.getUint16(i*2, true);
|
||||
if(sz < 65535) old_sz = sz;
|
||||
if(old_sz) break;
|
||||
}
|
||||
if(!old_sz) old_sz = sz = tri[6][0].data.length;
|
||||
var start = 0,
|
||||
preamble = tri[6][0].data.slice(0, start),
|
||||
intramble = tri[6][0].data.slice(start, old_sz * width),
|
||||
postamble = tri[6][0].data.slice(old_sz * width);
|
||||
var sst = []; sst[69] = "SheetJS";
|
||||
//intramble = write_new_storage({t:"n", v:12345}, sst);
|
||||
//intramble = write_new_storage({t:"b", v:false}, sst);
|
||||
intramble = write_new_storage({t:"s", v:"SheetJS"}, sst);
|
||||
tri[6][0].data = u8concat([preamble, intramble, postamble]);
|
||||
var delta = intramble.length / width - old_sz;
|
||||
for(var i = 0; i < tri[7][0].data.length / 2; ++i) {
|
||||
sz = dv.getUint16(i*2, true);
|
||||
if(sz < 65535 && sz > start) dv.setUint16(i*2, sz + delta, true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find first sheet -> first table -> add "SheetJS" to data store and set cell A1 */
|
||||
(function() {
|
||||
var entry = find(cfb, dependents[1].location);
|
||||
var x = parse_iwa_file(decompress_iwa_file(entry.content as Uint8Array));
|
||||
var docroot: IWAArchiveInfo;
|
||||
for(var xi = 0; xi < x.length; ++xi) {
|
||||
var packet = x[xi];
|
||||
if(packet.id == 1) docroot = packet;
|
||||
}
|
||||
var sheetrootref = parse_TSP_Reference(parse_shallow(docroot.messages[0].data)[1][0].data);
|
||||
|
||||
entry = find(cfb, dependents[sheetrootref].location);
|
||||
x = parse_iwa_file(decompress_iwa_file(entry.content as Uint8Array));
|
||||
for(xi = 0; xi < x.length; ++xi) {
|
||||
var packet = x[xi];
|
||||
if(packet.id == sheetrootref) docroot = packet;
|
||||
}
|
||||
sheetrootref = parse_TSP_Reference(parse_shallow(docroot.messages[0].data)[2][0].data);
|
||||
|
||||
entry = find(cfb, dependents[sheetrootref].location);
|
||||
x = parse_iwa_file(decompress_iwa_file(entry.content as Uint8Array));
|
||||
for(xi = 0; xi < x.length; ++xi) {
|
||||
var packet = x[xi];
|
||||
if(packet.id == sheetrootref) docroot = packet;
|
||||
}
|
||||
sheetrootref = parse_TSP_Reference(parse_shallow(docroot.messages[0].data)[2][0].data);
|
||||
|
||||
entry = find(cfb, dependents[sheetrootref].location);
|
||||
x = parse_iwa_file(decompress_iwa_file(entry.content as Uint8Array));
|
||||
for(xi = 0; xi < x.length; ++xi) {
|
||||
var packet = x[xi];
|
||||
if(packet.id == sheetrootref) docroot = packet;
|
||||
}
|
||||
|
||||
var pb = parse_shallow(docroot.messages[0].data);
|
||||
{
|
||||
var store = parse_shallow(pb[4][0].data);
|
||||
{
|
||||
/* ref to string table */
|
||||
var sstref = parse_TSP_Reference(store[4][0].data);
|
||||
(() => {
|
||||
var sentry = find(cfb, dependents[sstref].location);
|
||||
var sx = parse_iwa_file(decompress_iwa_file(sentry.content as Uint8Array));
|
||||
var sstroot: IWAArchiveInfo;
|
||||
for(var sxi = 0; sxi < sx.length; ++sxi) {
|
||||
var packet = sx[sxi];
|
||||
if(packet.id == sstref) sstroot = packet;
|
||||
}
|
||||
|
||||
var sstdata = parse_shallow(sstroot.messages[0].data);
|
||||
{
|
||||
if(!sstdata[3]) sstdata[3] = [];
|
||||
var newsst: ReturnType<typeof parse_shallow> = [];
|
||||
newsst[1] = [ { type: 0, data: write_varint49(69) } ];
|
||||
newsst[2] = [ { type: 0, data: write_varint49(1) } ];
|
||||
newsst[3] = [ { type: 2, data: stru8("SheetJS") } ];
|
||||
sstdata[3].push({type: 2, data: write_shallow(newsst)});
|
||||
}
|
||||
sstroot.messages[0].data = write_shallow(sstdata);
|
||||
|
||||
var sy = write_iwa_file(sx);
|
||||
var raw3 = compress_iwa_file(sy);
|
||||
sentry.content = raw3; sentry.size = sentry.content.length;
|
||||
})();
|
||||
|
||||
var tile = parse_shallow(store[3][0].data); // TileStorage
|
||||
{
|
||||
var t = tile[1][0];
|
||||
delete tile[2];
|
||||
var tl = parse_shallow(t.data); // first Tile
|
||||
{
|
||||
var tileref = parse_TSP_Reference(tl[2][0].data);
|
||||
(() => {
|
||||
var tentry = find(cfb, dependents[tileref].location);
|
||||
var tx = parse_iwa_file(decompress_iwa_file(tentry.content as Uint8Array));
|
||||
var tileroot: IWAArchiveInfo;
|
||||
for(var sxi = 0; sxi < tx.length; ++sxi) {
|
||||
var packet = tx[sxi];
|
||||
if(packet.id == tileref) tileroot = packet;
|
||||
}
|
||||
|
||||
// .TST.Tile
|
||||
var tiledata = parse_shallow(tileroot.messages[0].data);
|
||||
{
|
||||
tiledata[5].forEach((row, R) => {
|
||||
var tilerow = parse_shallow(row.data);
|
||||
if(R == 0) mutate_row(tilerow);
|
||||
row.data = write_shallow(tilerow);
|
||||
})
|
||||
}
|
||||
tileroot.messages[0].data = write_shallow(tiledata);
|
||||
|
||||
var ty = write_iwa_file(tx);
|
||||
var raw3 = compress_iwa_file(ty);
|
||||
tentry.content = raw3; tentry.size = tentry.content.length;
|
||||
//throw dependents[tileref];
|
||||
})();
|
||||
}
|
||||
t.data = write_shallow(tl);
|
||||
}
|
||||
store[3][0].data = write_shallow(tile);
|
||||
}
|
||||
pb[4][0].data = write_shallow(store);
|
||||
}
|
||||
docroot.messages[0].data = write_shallow(pb);
|
||||
|
||||
var y = write_iwa_file(x);
|
||||
var raw3 = compress_iwa_file(y);
|
||||
entry.content = raw3; entry.size = entry.content.length;
|
||||
})();
|
||||
|
||||
//console.log(indices.map(i => [i, dependents[i]]).filter(([i, dep]) => dep?.deps && (dep.deps.length == 0 || dep.deps.length == 1 && dep.deps[0] == 1)));
|
||||
|
||||
/* Last pass: fix metadata and commit to new file */
|
||||
cfb.FileIndex.map((fi, idx): [CFB$Entry, string] => ([fi, cfb.FullPaths[idx]])).forEach(row => {
|
||||
var fi = row[0], fp = row[1];
|
||||
if(!fi?.name?.match(/\.iwa/)) return;
|
||||
var x = parse_iwa_file(decompress_iwa_file(fi.content as Uint8Array));
|
||||
|
||||
if(fi.name.match(/^Metadata.iwa$/)) {
|
||||
x.forEach((w: IWAArchiveInfo) => {
|
||||
var type = varint_to_i32(w.messages[0].meta[1][0].data);
|
||||
if(type != 11006) return;
|
||||
var package_metadata = parse_shallow(w.messages[0].data);
|
||||
[3,11].forEach(x => {
|
||||
if(!package_metadata[x]) return;
|
||||
for(var pmj = 0; pmj < package_metadata[x].length; ++pmj) {
|
||||
var ci = package_metadata[x][pmj];
|
||||
var comp = parse_shallow(ci.data);
|
||||
var compid = varint_to_i32(comp[1][0].data);
|
||||
if(!dependents[compid]) {
|
||||
console.log(`Removing ${compid} (${u8str(comp[2][0].data)} -> ${comp[3]?.[0] && u8str(comp[3][0].data) || ""}) from metadata`);
|
||||
package_metadata[x].splice(pmj, 1);
|
||||
--pmj; continue;
|
||||
}
|
||||
[13, 14, 15].forEach(j => delete comp[j]);
|
||||
ci.data = write_shallow(comp);
|
||||
}
|
||||
});
|
||||
[2, 4, 6, 8, 9].forEach(j => delete package_metadata[j]);
|
||||
w.messages[0].data = write_shallow(package_metadata);
|
||||
});
|
||||
}
|
||||
|
||||
var y = write_iwa_file(x);
|
||||
var raw3 = compress_iwa_file(y);
|
||||
fi.content = raw3;
|
||||
if(x.length == 0) {
|
||||
console.log(`Deleting ${fi.name} (no messages)`);
|
||||
return;
|
||||
}
|
||||
if(fi.name.match(/^Metadata.iwa$/)) {
|
||||
console.error(`Reframing iwa ${fi.name} (${fi.size} -> ${fi.content.length})`);
|
||||
fi.size = fi.content.length;
|
||||
utils.cfb_add(nuevo, row[1], fi.content);
|
||||
} else {
|
||||
console.error(`Reframing iwa ${fi.name} (${fi.size} -> ${fi.content.length})`);
|
||||
fi.size = fi.content.length;
|
||||
utils.cfb_add(nuevo, row[1], fi.content);
|
||||
}
|
||||
});
|
||||
|
||||
writeFile(nuevo, o, { fileType: "zip", compression: true });
|
||||
|
||||
function process_root(dmeta: ReturnType<typeof parse_shallow>, id: number) {
|
||||
var tsa = parse_shallow(dmeta[8][0].data);
|
||||
{
|
||||
var tsk = parse_shallow(tsa[1][0].data);
|
||||
{
|
||||
[7, 8, 14].forEach(j => delete_ref(tsk, j, id)); // annotation_author_storage
|
||||
[4, 9, 10, 11, 12, 15, 16, 17].forEach(j => delete tsk[j]);
|
||||
}
|
||||
tsa[1][0].data = write_shallow(tsk);
|
||||
[5, 6, 7, 10, 11, 12, 13].forEach(j => delete_ref(tsa, j, 1));
|
||||
[3, 8, 9, 14, 15, 16].forEach(j => delete tsa[j]);
|
||||
}
|
||||
dmeta[8][0].data = write_shallow(tsa);
|
||||
}
|
||||
|
||||
function process_sheet(dmeta: ReturnType<typeof parse_shallow>, id: number) {
|
||||
[3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 20, 21, 23, 24].forEach(j => delete dmeta[j]);
|
||||
[15, 16, 17, 18, 19, 22].forEach(j => delete_ref(dmeta, j, id));
|
||||
}
|
||||
|
||||
function process_TST_TableInfoArchive(dmeta: ReturnType<typeof parse_shallow>, id: number) {
|
||||
[7, 8, 9, 10, 14, 16].forEach(j => delete dmeta[j]);
|
||||
[3, 4, 5, 6, 15, 17].forEach(j => delete_ref(dmeta, j, id));
|
||||
}
|
||||
|
||||
function process_TST_TableModelArchive(dmeta: ReturnType<typeof parse_shallow>, id: number) {
|
||||
[90, 91, 92].forEach(j => delete dmeta[j]);
|
||||
[34, 35, 38, 49].forEach(j => delete_ref(dmeta, j, id));
|
||||
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69].forEach(j => delete_ref(dmeta, j, id));
|
||||
[70].forEach(j => delete dmeta[j]);
|
||||
[71, 72, 73, 74, 75, 76, 77, 78, 79, 80].forEach(j => delete_ref(dmeta, j, id));
|
||||
[85, 86, 87, 88, 89].forEach(j => delete_ref(dmeta, j, id));
|
||||
var store = parse_shallow(dmeta[4][0].data);
|
||||
{ // .TST.DataStore
|
||||
[12, 13, 15, 16, 17, 18, 19, 20, 21, 22].forEach(j => delete_ref(store, j, id));
|
||||
var tiles = parse_shallow(store[3][0].data);
|
||||
{ // .TST.TileStorage
|
||||
//console.log(parse_TSP_Reference(parse_shallow(tiles[1][0].data)[2][0].data));
|
||||
}
|
||||
store[3][0].data = write_shallow(tiles);
|
||||
// 4 -> sst
|
||||
// 17 -> rsst
|
||||
}
|
||||
dmeta[4][0].data = write_shallow(store);
|
||||
}
|
||||
|
||||
function process_TN_ThemeArchive(dmeta: ReturnType<typeof parse_shallow>, id: number) {
|
||||
[2].forEach(j => delete_ref(dmeta, j, id));
|
||||
var tssta = parse_shallow(dmeta[1][0].data);
|
||||
{
|
||||
//Object.keys(tssta).filter(x => +x >= 100).forEach(j => delete tssta[j]);
|
||||
}
|
||||
dmeta[1][0].data = write_shallow(tssta);
|
||||
}
|
||||
|
||||
function process_TSS_StylesheetArchive(dmeta: ReturnType<typeof parse_shallow>, id: number) {
|
||||
[7, 8, 9, 10, 11, 12].forEach(j => {
|
||||
if(!dmeta[j]) return;
|
||||
var vstyle = parse_shallow(dmeta[j][0].data);
|
||||
delete_ref(vstyle, 1, id);
|
||||
if(vstyle[2]) vstyle[2].forEach(ised => {
|
||||
var ise = parse_shallow(ised.data);
|
||||
delete_ref(ise, 2, id);
|
||||
})
|
||||
if(vstyle[3]) vstyle[3].forEach(sced => {
|
||||
var sce = parse_shallow(sced.data);
|
||||
delete_ref(sce, 2, id);
|
||||
delete_ref(sce, 1, id);
|
||||
})
|
||||
delete dmeta[j];
|
||||
});
|
||||
dmeta[4] = [{data: write_varint49(0), type: 0}];
|
||||
[3].forEach(j => delete_ref(dmeta, j, id));
|
||||
dmeta[5]?.forEach(pi => {
|
||||
var sce = parse_shallow(pi.data);
|
||||
delete_ref(sce, 1, id);
|
||||
delete_ref(sce, 2, id);
|
||||
}); delete dmeta[5];
|
||||
var deleted_styles = [];
|
||||
if(dmeta[2]) for(var pij = 0; pij < dmeta[2].length; ++pij) {
|
||||
var ise = parse_shallow(dmeta[2][pij].data);
|
||||
var sname = u8str(ise[1][0].data);
|
||||
if(sname.match(/_\d*$/) || sname.match(/^(captions|chart|image|movie|stickyComment)/) || sname.match(/evel[2-5]|pivot|liststyle/) ) {
|
||||
var deletedid = parse_TSP_Reference(ise[2][0].data);
|
||||
console.log(`Deleting style ${sname} [${deletedid}]`);
|
||||
deleted_styles.push(deletedid);
|
||||
delete_ref(ise, 2, id);
|
||||
dmeta[2].splice(pij,1);
|
||||
--pij; continue;
|
||||
} else console.log(`Keeping style ${sname}`)
|
||||
}
|
||||
if(dmeta[1]) for(var sj = 0; sj < dmeta[1].length; ++sj) {
|
||||
var dsid = parse_TSP_Reference(dmeta[1][sj].data);
|
||||
if(deleted_styles.indexOf(dsid) > -1) {
|
||||
//console.log(`Really deleting style ${dsid}`);
|
||||
dependents[dsid].deps = dependents[dsid].deps.filter(x => x != id);
|
||||
if(dependents[dsid].deps.length == 0) delete_message(dsid, cfb);
|
||||
dmeta[1].splice(sj, 1); --sj; continue;
|
||||
}
|
||||
}
|
||||
[6].forEach(j => delete dmeta[j]);
|
||||
}
|
||||
|
||||
function process_TSCE_CalculationEngineArchive(dmeta: ReturnType<typeof parse_shallow>, id: number) {
|
||||
[3, 12, 14, 15].forEach(j => delete_ref(dmeta, j, id));
|
||||
[1, 4, 5, 6, 7, 9, 10, 11, 13, 16, 17, 18].forEach(i => delete dmeta[i]);
|
||||
var dta = parse_shallow(dmeta[2][0].data);
|
||||
delete dta[5]; delete dta[2]; delete dta[4];
|
||||
delete dta[1]; delete dta[3]; delete_ref(dta, 6, id);
|
||||
dmeta[2][0].data = write_shallow(dta);
|
||||
}
|
||||
|
||||
function trim(x: IWAArchiveInfo[], fi: CFB$Entry) {
|
||||
for(var i = 0; i < x.length; ++i) {
|
||||
var w = x[i];
|
||||
var type = varint_to_i32(w.messages[0].meta[1][0].data);
|
||||
var dmeta = parse_shallow(w.messages[0].data);
|
||||
|
||||
switch(type) {
|
||||
case 222: // .TSK.CustomFormatListArchive
|
||||
case 601: // .TSA.FunctionBrowserStateArchive
|
||||
x.splice(i, 1); --i; continue;
|
||||
case 3047: break; // .TSD.GuideStorageArchive
|
||||
case 205: {
|
||||
} break; // .TSK.TreeNode
|
||||
|
||||
case 1: { // .TN.DocumentArchive
|
||||
process_root(dmeta, w.id);
|
||||
} break;
|
||||
case 2: { // .TN.SheetArchive
|
||||
process_sheet(dmeta, w.id);
|
||||
} break;
|
||||
case 6000: { // .TST.TableInfoArchive
|
||||
process_TST_TableInfoArchive(dmeta, w.id);
|
||||
} break;
|
||||
case 6001: { // .TST.TableModelArchive
|
||||
process_TST_TableModelArchive(dmeta, w.id)
|
||||
} break;
|
||||
case 401: { // .TSS.StylesheetArchive
|
||||
process_TSS_StylesheetArchive(dmeta, w.id);
|
||||
break;
|
||||
}
|
||||
case 11011: { // .TSP.DocumentMetadata
|
||||
[1, 3].forEach(i => delete dmeta[i]);
|
||||
} break;
|
||||
case 6002: {
|
||||
//process_TST_Tile(dmeta, w.id);
|
||||
} break; // .TST.Tile
|
||||
case 6005: break; // .TST.TableDataList
|
||||
case 6006: break; // .TST.HeaderStorageBucket
|
||||
case 2001: break; // .TSWP.StorageArchive
|
||||
case 12009: process_TN_ThemeArchive(dmeta, w.id); break; // .TN.ThemeArchive
|
||||
|
||||
case 3097: break; // .TSD.StandinCaptionArchive
|
||||
case 4000: process_TSCE_CalculationEngineArchive(dmeta, w.id); break; // .TSCE.CalculationEngineArchive
|
||||
case 4003: break; // .TSCE.NamedReferenceManagerArchive
|
||||
case 4004: break; // .TSCE.TrackedReferenceStoreArchive
|
||||
case 4008: { // .TSCE.FormulaOwnerDependenciesArchive
|
||||
[11].forEach(j => delete_ref(dmeta, j, w.id));
|
||||
[3].forEach(i => delete dmeta[i]);
|
||||
} break;
|
||||
case 4009: { // .TSCE.CellRecordTileArchive
|
||||
delete dmeta[4];
|
||||
} break;
|
||||
case 6267: { // .TST.ColumnRowUIDMapArchive
|
||||
// console.log("CRUIDMA", dmeta[1]?.[0], dmeta[2]?.[0], dmeta[3]?.[0]);
|
||||
//[1,2,3,4,5,6].forEach(j => delete dmeta[j]); break;
|
||||
} break;
|
||||
case 6366: break; // .TST.HeaderNameMgrArchive
|
||||
case 6204: break; // .TST.HiddenStateFormulaOwnerArchive
|
||||
case 6220: break; // .TST.FilterSetArchive
|
||||
case 6305: break; // .TST.StrokeSidecarArchive
|
||||
case 6316: break; // .TST.SummaryModelArchive
|
||||
case 6317: break; // .TST.SummaryCellVendorArchive
|
||||
case 6318: break; // .TST.CategoryOrderArchive
|
||||
case 6372: break; // .TST.CategoryOwnerRefArchive
|
||||
case 6373: break; // .TST.GroupByArchive
|
||||
case 2043: [2,3,4].forEach(j => delete dmeta[j]); break; // .TSWP.NumberAttachmentArchive
|
||||
|
||||
case 5020: // .TSCH.ChartStylePreset
|
||||
//[1,2,3,4,5,6].forEach(j => delete_ref(dmeta, j, w.id)); // some part of this is required to auto-save
|
||||
Object.keys(dmeta).filter(x => +x >= 10000).forEach(j => delete dmeta[j]);
|
||||
break;
|
||||
case 5022: // .TSCH.ChartStyleArchive
|
||||
case 5024: // .TSCH.LegendStyleArchive
|
||||
case 5026: // .TSCH.ChartAxisStyleArchive
|
||||
case 5028: // .TSCH.ChartSeriesStyleArchive
|
||||
case 5030: // .TSCH.ReferenceLineStyleArchive
|
||||
Object.keys(dmeta).filter(x => +x >= 10000).forEach(j => delete dmeta[j]);
|
||||
break;
|
||||
case 2021: break;
|
||||
case 2022: [10,11,12].forEach(j => delete dmeta[j]); break; // .TSWP.ParagraphStyleArchive
|
||||
case 2023: [10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25].forEach(j => delete dmeta[j]); break; // .TSWP.ListStyleArchive
|
||||
case 3016: [10,11].forEach(j => delete dmeta[j]); break; // .TSD.MediaStyleArchive
|
||||
case 2025: /* [10,11].forEach(j => delete dmeta[j]); */ break; // .TSWP.ShapeStyleArchive
|
||||
case 6003: /* [10,11].forEach(j => delete dmeta[j]); */ break; // .TST.TableStyleArchive
|
||||
case 6004: /* [10,11].forEach(j => delete dmeta[j]); */ break; // .TST.CellStyleArchive
|
||||
case 10024: [10,11,12].forEach(j => delete dmeta[j]); break; // .TN.DropCapStyleArchive
|
||||
case 12050: /* [2,3].forEach(j => delete dmeta[j]); */ break; // .TN.SheetStyleArchive
|
||||
case 3045: break; // .TSD.CanvasSelectionArchive
|
||||
|
||||
case 6008: {
|
||||
[1].forEach(j => delete dmeta[j]);
|
||||
[2].forEach(j => delete_ref(dmeta, j, w.id));
|
||||
// deleting 3 -> -[TSWPLayoutManager initWithStorage:owner:] /Library/Caches/com.apple.xbs/Sources/iWorkDependenciesMacOS/iWorkDependenciesMacOS-7032.0.145/shared/text/TSWPLayoutManager.mm:82 Cannot initialize with a nil storage.
|
||||
} break; // .TST.TableStylePresetArchive
|
||||
|
||||
case 6247: {
|
||||
[ 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 ].forEach(j => delete_ref(dmeta, j, w.id));
|
||||
} break; // .TST.TableStyleNetworkArchive
|
||||
|
||||
case 210: { // .TSK.ViewStateArchive
|
||||
[2, 3].forEach(i => delete dmeta[i]);
|
||||
} break;
|
||||
case 12026: { // .TN.UIStateArchive
|
||||
delete dmeta[13];
|
||||
} break;
|
||||
|
||||
case 219: delete dmeta[1]; break; // .DocumentSelectionArchive
|
||||
|
||||
case 12028: break; // .TN.SheetSelectionArchive
|
||||
case 3061: { // .TSD.DrawableSelectionArchive
|
||||
[3].forEach(j => delete_ref(dmeta, j, w.id));
|
||||
} break;
|
||||
case 3091: { // .TSD.FreehandDrawingToolkitUIState
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15].forEach(i => delete dmeta[i]);
|
||||
} break;
|
||||
|
||||
/* Metadata.iwa */
|
||||
case 11006: { // .TSP.PackageMetadata
|
||||
[10].forEach(j => delete_ref(dmeta, j, w.id));
|
||||
} break;
|
||||
case 11014: // .TSP.DataMetadata
|
||||
[1].forEach(j => delete dmeta[j]);
|
||||
break;
|
||||
case 11015: // .TSP.DataMetadataMap
|
||||
dmeta?.[1]?.forEach((r, idx) => {
|
||||
var ddmeta = parse_shallow(r.data);
|
||||
[2].forEach(j => delete_ref(ddmeta, j, w.id));
|
||||
});
|
||||
delete dmeta[1];
|
||||
dmeta.length = 0;
|
||||
break;
|
||||
|
||||
/* AnnotationAuthorStorage.iwa */
|
||||
case 213: break; // TSK.AnnotationAuthorStorageArchive
|
||||
|
||||
default:
|
||||
console.log("!!", fi.name, type, w.id, w.messages.length);
|
||||
}
|
||||
w.messages[0].data = write_shallow(dmeta);
|
||||
}
|
||||
}
|
@ -2,9 +2,8 @@
|
||||
set -eo pipefail
|
||||
INF=${1:-test.numbers}
|
||||
OUTF=${2:-reframed.numbers}
|
||||
make reframe.node.js
|
||||
node reframe.node.js "$INF" "$OUTF"
|
||||
chmod a+w "$OUTF"
|
||||
cp "$INF" "$OUTF"
|
||||
chmod a-w "$OUTF"
|
||||
sleep 0.1
|
||||
# open "$OUTF"
|
||||
unzip -l "$OUTF"
|
||||
|
Binary file not shown.
41
package.json
41
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xlsx",
|
||||
"version": "0.18.10",
|
||||
"version": "0.19.2",
|
||||
"author": "sheetjs",
|
||||
"description": "SheetJS Spreadsheet data parser and writer",
|
||||
"keywords": [
|
||||
@ -28,22 +28,47 @@
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./xlsx.mjs",
|
||||
"require": "./xlsx.js"
|
||||
"require": "./xlsx.js",
|
||||
"types": "./types/index.d.ts"
|
||||
},
|
||||
"./xlsx.mjs": {
|
||||
"import": "./xlsx.mjs"
|
||||
"import": "./xlsx.mjs",
|
||||
"types": "./types/index.d.ts"
|
||||
},
|
||||
"./xlsx.js": {
|
||||
"require": "./xlsx.js",
|
||||
"types": "./types/index.d.ts"
|
||||
},
|
||||
"./dist/xlsx.zahl": {
|
||||
"import": "./dist/xlsx.zahl.mjs",
|
||||
"require": "./dist/xlsx.zahl.js"
|
||||
"require": "./dist/xlsx.zahl.js",
|
||||
"types": "./dist/zahl.d.ts"
|
||||
},
|
||||
"./dist/xlsx.zahl.mjs": {
|
||||
"import": "./dist/xlsx.zahl.mjs",
|
||||
"types": "./dist/zahl.d.ts"
|
||||
},
|
||||
"./dist/xlsx.zahl.js": {
|
||||
"require": "./dist/xlsx.zahl.js",
|
||||
"types": "./dist/zahl.d.ts"
|
||||
},
|
||||
"./dist/cpexcel": {
|
||||
"import": "./dist/cpexcel.full.mjs",
|
||||
"require": "./dist/cpexcel.js"
|
||||
"require": "./dist/cpexcel.js",
|
||||
"types": "./dist/cpexcel.d.ts"
|
||||
},
|
||||
"./dist/cpexcel.js": {
|
||||
"require": "./dist/cpexcel.js",
|
||||
"types": "./dist/cpexcel.d.ts"
|
||||
},
|
||||
"./dist/cpexcel.full": {
|
||||
"import": "./dist/cpexcel.full.mjs",
|
||||
"require": "./dist/cpexcel.js"
|
||||
"require": "./dist/cpexcel.js",
|
||||
"types": "./dist/cpexcel.d.ts"
|
||||
},
|
||||
"./dist/cpexcel.full.mjs": {
|
||||
"import": "./dist/cpexcel.full.mjs",
|
||||
"types": "./dist/cpexcel.d.ts"
|
||||
}
|
||||
},
|
||||
"browser": {
|
||||
@ -84,7 +109,7 @@
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/SheetJS/sheetjs.git"
|
||||
"url": "https://git.sheetjs.com/SheetJS/sheetjs"
|
||||
},
|
||||
"scripts": {
|
||||
"pretest": "npm run lint",
|
||||
@ -113,7 +138,7 @@
|
||||
},
|
||||
"homepage": "https://sheetjs.com/",
|
||||
"bugs": {
|
||||
"url": "https://github.com/SheetJS/sheetjs/issues"
|
||||
"url": "https://git.sheetjs.com/SheetJS/sheetjs/issues"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
|
610
packages/otorp/otorp.ts
Executable file
610
packages/otorp/otorp.ts
Executable file
@ -0,0 +1,610 @@
|
||||
#!/usr/bin/env -S deno run -A
|
||||
/*! otorp (C) 2021-present SheetJS -- http://sheetjs.com */
|
||||
import { resolve } from "https://deno.land/std@0.171.0/path/mod.ts";
|
||||
import { TerminalSpinner } from "https://deno.land/x/spinners/mod.ts";
|
||||
|
||||
// #region util.ts
|
||||
|
||||
var u8_to_dataview = (array: Uint8Array): DataView => new DataView(array.buffer, array.byteOffset, array.byteLength);
|
||||
|
||||
var u8str = (u8: Uint8Array): string => new TextDecoder().decode(u8);
|
||||
|
||||
var u8concat = (u8a: Uint8Array[]): Uint8Array => {
|
||||
var len = u8a.reduce((acc: number, x: Uint8Array) => acc + x.length, 0);
|
||||
var out = new Uint8Array(len);
|
||||
var off = 0;
|
||||
u8a.forEach(u8 => { out.set(u8, off); off += u8.length; });
|
||||
return out;
|
||||
};
|
||||
|
||||
var indent = (str: string, depth: number /* = 1 */): string => str.split(/\n/g).map(x => x && " ".repeat(depth) + x).join("\n");
|
||||
|
||||
function u8indexOf(u8: Uint8Array, data: string | number | Uint8Array, byteOffset?: number): number {
|
||||
//if(Buffer.isBuffer(u8)) return u8.indexOf(data, byteOffset);
|
||||
if(typeof data == "number") return u8.indexOf(data, byteOffset);
|
||||
var l = byteOffset;
|
||||
if(typeof data == "string") {
|
||||
outs: while((l = u8.indexOf(data.charCodeAt(0), l)) > -1) {
|
||||
++l;
|
||||
for(var j = 1; j < data.length; ++j) if(u8[l+j-1] != data.charCodeAt(j)) continue outs;
|
||||
return l - 1;
|
||||
}
|
||||
} else {
|
||||
outb: while((l = u8.indexOf(data[0], l)) > -1) {
|
||||
++l;
|
||||
for(var j = 1; j < data.length; ++j) if(u8[l+j-1] != data[j]) continue outb;
|
||||
return l - 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region proto.ts
|
||||
|
||||
type Ptr = [number];
|
||||
|
||||
/** Parse an integer from the varint that can be exactly stored in a double */
|
||||
function parse_varint49(buf: Uint8Array, ptr?: Ptr): number {
|
||||
var l = ptr ? ptr[0] : 0;
|
||||
var usz = buf[l] & 0x7F;
|
||||
varint: if(buf[l++] >= 0x80) {
|
||||
usz |= (buf[l] & 0x7F) << 7; if(buf[l++] < 0x80) break varint;
|
||||
usz |= (buf[l] & 0x7F) << 14; if(buf[l++] < 0x80) break varint;
|
||||
usz |= (buf[l] & 0x7F) << 21; if(buf[l++] < 0x80) break varint;
|
||||
usz += (buf[l] & 0x7F) * Math.pow(2, 28); ++l; if(buf[l++] < 0x80) break varint;
|
||||
usz += (buf[l] & 0x7F) * Math.pow(2, 35); ++l; if(buf[l++] < 0x80) break varint;
|
||||
usz += (buf[l] & 0x7F) * Math.pow(2, 42); ++l; if(buf[l++] < 0x80) break varint;
|
||||
}
|
||||
if(ptr) ptr[0] = l;
|
||||
return usz;
|
||||
}
|
||||
|
||||
function write_varint49(v: number): Uint8Array {
|
||||
var usz = new Uint8Array(7);
|
||||
usz[0] = (v & 0x7F);
|
||||
var L = 1;
|
||||
sz: if(v > 0x7F) {
|
||||
usz[L-1] |= 0x80; usz[L] = (v >> 7) & 0x7F; ++L;
|
||||
if(v <= 0x3FFF) break sz;
|
||||
usz[L-1] |= 0x80; usz[L] = (v >> 14) & 0x7F; ++L;
|
||||
if(v <= 0x1FFFFF) break sz;
|
||||
usz[L-1] |= 0x80; usz[L] = (v >> 21) & 0x7F; ++L;
|
||||
if(v <= 0xFFFFFFF) break sz;
|
||||
usz[L-1] |= 0x80; usz[L] = ((v/0x100) >>> 21) & 0x7F; ++L;
|
||||
if(v <= 0x7FFFFFFFF) break sz;
|
||||
usz[L-1] |= 0x80; usz[L] = ((v/0x10000) >>> 21) & 0x7F; ++L;
|
||||
if(v <= 0x3FFFFFFFFFF) break sz;
|
||||
usz[L-1] |= 0x80; usz[L] = ((v/0x1000000) >>> 21) & 0x7F; ++L;
|
||||
}
|
||||
return usz.slice(0, L);
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
interface ProtoItem {
|
||||
offset?: number;
|
||||
data: Uint8Array;
|
||||
type: number;
|
||||
}
|
||||
type ProtoField = Array<ProtoItem>
|
||||
type ProtoMessage = Array<ProtoField>;
|
||||
|
||||
/** Shallow parse of a message */
|
||||
function parse_shallow(buf: Uint8Array): ProtoMessage {
|
||||
var out: ProtoMessage = [], ptr: Ptr = [0];
|
||||
while(ptr[0] < buf.length) {
|
||||
var off = ptr[0];
|
||||
var num = parse_varint49(buf, ptr);
|
||||
var type = num & 0x07; num = Math.floor(num / 8);
|
||||
var len = 0;
|
||||
var res: Uint8Array;
|
||||
if(num == 0) break;
|
||||
switch(type) {
|
||||
case 0: {
|
||||
var l = ptr[0];
|
||||
while(buf[ptr[0]++] >= 0x80);
|
||||
res = buf.slice(l, ptr[0]);
|
||||
} break;
|
||||
case 5: len = 4; res = buf.slice(ptr[0], ptr[0] + len); ptr[0] += len; break;
|
||||
case 1: len = 8; res = buf.slice(ptr[0], ptr[0] + len); ptr[0] += len; break;
|
||||
case 2: len = parse_varint49(buf, ptr); res = buf.slice(ptr[0], ptr[0] + len); ptr[0] += len; break;
|
||||
case 3: // Start group
|
||||
case 4: // End group
|
||||
default: throw new Error(`PB Type ${type} for Field ${num} at offset ${off}`);
|
||||
}
|
||||
var v: ProtoItem = { offset: off, data: res, type };
|
||||
if(out[num] == null) out[num] = [v];
|
||||
else out[num].push(v);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Serialize a shallow parse */
|
||||
function write_shallow(proto: ProtoMessage): Uint8Array {
|
||||
var out: Uint8Array[] = [];
|
||||
proto.forEach((field, idx) => {
|
||||
field.forEach(item => {
|
||||
out.push(write_varint49(idx * 8 + item.type));
|
||||
out.push(item.data);
|
||||
});
|
||||
});
|
||||
return u8concat(out);
|
||||
}
|
||||
|
||||
function mappa<U>(data: ProtoField, cb:(_:Uint8Array) => U): U[] {
|
||||
if(!data) return [];
|
||||
return data.map((d) => { try {
|
||||
return cb(d.data);
|
||||
} catch(e) {
|
||||
var m = e.message?.match(/at offset (\d+)/);
|
||||
if(m) e.message = e.message.replace(/at offset (\d+)/, "at offset " + (+m[1] + (d.offset||0)));
|
||||
throw e;
|
||||
}});
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region descriptor.ts
|
||||
|
||||
var TYPES = [
|
||||
"error",
|
||||
"double",
|
||||
"float",
|
||||
"int64",
|
||||
"uint64",
|
||||
"int32",
|
||||
"fixed64",
|
||||
"fixed32",
|
||||
"bool",
|
||||
"string",
|
||||
"group",
|
||||
"message",
|
||||
"bytes",
|
||||
"uint32",
|
||||
"enum",
|
||||
"sfixed32",
|
||||
"sfixed64",
|
||||
"sint32",
|
||||
"sint64"
|
||||
];
|
||||
|
||||
|
||||
interface FileOptions {
|
||||
javaPackage?: string;
|
||||
javaOuterClassname?: string;
|
||||
javaMultipleFiles?: string;
|
||||
goPackage?: string;
|
||||
}
|
||||
function parse_FileOptions(buf: Uint8Array): FileOptions {
|
||||
var data = parse_shallow(buf);
|
||||
var out: FileOptions = {};
|
||||
if(data[1]?.[0]) out.javaPackage = u8str(data[1][0].data);
|
||||
if(data[8]?.[0]) out.javaOuterClassname = u8str(data[8][0].data);
|
||||
if(data[11]?.[0]) out.goPackage = u8str(data[11][0].data);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
interface EnumValue {
|
||||
name?: string;
|
||||
number?: number;
|
||||
}
|
||||
function parse_EnumValue(buf: Uint8Array): EnumValue {
|
||||
var data = parse_shallow(buf);
|
||||
var out: EnumValue = {};
|
||||
if(data[1]?.[0]) out.name = u8str(data[1][0].data);
|
||||
if(data[2]?.[0]) out.number = varint_to_i32(data[2][0].data);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
interface Enum {
|
||||
name?: string;
|
||||
value?: EnumValue[];
|
||||
}
|
||||
function parse_Enum(buf: Uint8Array): Enum {
|
||||
var data = parse_shallow(buf);
|
||||
var out: Enum = {};
|
||||
if(data[1]?.[0]) out.name = u8str(data[1][0].data);
|
||||
out.value = mappa(data[2], parse_EnumValue);
|
||||
return out;
|
||||
}
|
||||
var write_Enum = (en: Enum): string => {
|
||||
var out = [`enum ${en.name} {`];
|
||||
en.value?.forEach(({name, number}) => out.push(` ${name} = ${number};`));
|
||||
return out.concat(`}`).join("\n");
|
||||
};
|
||||
|
||||
|
||||
interface FieldOptions {
|
||||
packed?: boolean;
|
||||
deprecated?: boolean;
|
||||
}
|
||||
function parse_FieldOptions(buf: Uint8Array): FieldOptions {
|
||||
var data = parse_shallow(buf);
|
||||
var out: FieldOptions = {};
|
||||
if(data[2]?.[0]) out.packed = !!data[2][0].data;
|
||||
if(data[3]?.[0]) out.deprecated = !!data[3][0].data;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
interface Field {
|
||||
name?: string;
|
||||
extendee?: string;
|
||||
number?: number;
|
||||
label?: number;
|
||||
type?: number;
|
||||
typeName?: string;
|
||||
defaultValue?: string;
|
||||
options?: FieldOptions;
|
||||
}
|
||||
function parse_Field(buf: Uint8Array): Field {
|
||||
var data = parse_shallow(buf);
|
||||
var out: Field = {};
|
||||
if(data[1]?.[0]) out.name = u8str(data[1][0].data);
|
||||
if(data[2]?.[0]) out.extendee = u8str(data[2][0].data);
|
||||
if(data[3]?.[0]) out.number = varint_to_i32(data[3][0].data);
|
||||
if(data[4]?.[0]) out.label = varint_to_i32(data[4][0].data);
|
||||
if(data[5]?.[0]) out.type = varint_to_i32(data[5][0].data);
|
||||
if(data[6]?.[0]) out.typeName = u8str(data[6][0].data);
|
||||
if(data[7]?.[0]) out.defaultValue = u8str(data[7][0].data);
|
||||
if(data[8]?.[0]) out.options = parse_FieldOptions(data[8][0].data);
|
||||
return out;
|
||||
}
|
||||
function write_Field(field: Field): string {
|
||||
var out = [];
|
||||
var label = ["", "optional ", "required ", "repeated "][field.label||0] || "";
|
||||
var type = field.typeName || TYPES[field.type||69] || "s5s";
|
||||
var opts = [];
|
||||
if(field.defaultValue) opts.push(`default = ${field.defaultValue}`);
|
||||
if(field.options?.packed) opts.push(`packed = true`);
|
||||
if(field.options?.deprecated) opts.push(`deprecated = true`);
|
||||
var os = opts.length ? ` [${opts.join(", ")}]`: "";
|
||||
out.push(`${label}${type} ${field.name} = ${field.number}${os};`);
|
||||
return out.length ? indent(out.join("\n"), 1) : "";
|
||||
}
|
||||
|
||||
|
||||
function write_extensions(ext: Field[], xtra = false, coalesce = true): string {
|
||||
var res: string[] = [];
|
||||
var xt: Array<[string, Array<Field>]> = [];
|
||||
ext.forEach(ext => {
|
||||
if(!ext.extendee) return;
|
||||
var row = coalesce ?
|
||||
xt.find(x => x[0] == ext.extendee) :
|
||||
(xt[xt.length - 1]?.[0] == ext.extendee ? xt[xt.length - 1]: null);
|
||||
if(row) row[1].push(ext);
|
||||
else xt.push([ext.extendee, [ext]]);
|
||||
});
|
||||
xt.forEach(extrow => {
|
||||
var out = [`extend ${extrow[0]} {`];
|
||||
extrow[1].forEach(ext => out.push(write_Field(ext)));
|
||||
res.push(out.concat(`}`).join("\n") + (xtra ? "\n" : ""));
|
||||
});
|
||||
return res.join("\n");
|
||||
}
|
||||
|
||||
|
||||
interface ExtensionRange { start?: number; end?: number; }
|
||||
interface MessageType {
|
||||
name?: string;
|
||||
nestedType?: MessageType[];
|
||||
enumType?: Enum[];
|
||||
field?: Field[];
|
||||
extension?: Field[];
|
||||
extensionRange?: ExtensionRange[];
|
||||
}
|
||||
function parse_mtype(buf: Uint8Array): MessageType {
|
||||
var data = parse_shallow(buf);
|
||||
var out: MessageType = {};
|
||||
if(data[1]?.[0]) out.name = u8str(data[1][0].data);
|
||||
if(data[2]?.length >= 1) out.field = mappa(data[2], parse_Field);
|
||||
if(data[3]?.length >= 1) out.nestedType = mappa(data[3], parse_mtype);
|
||||
if(data[4]?.length >= 1) out.enumType = mappa(data[4], parse_Enum);
|
||||
if(data[6]?.length >= 1) out.extension = mappa(data[6], parse_Field);
|
||||
if(data[5]?.length >= 1) out.extensionRange = data[5].map(d => {
|
||||
var data = parse_shallow(d.data);
|
||||
var out: ExtensionRange = {};
|
||||
if(data[1]?.[0]) out.start = varint_to_i32(data[1][0].data);
|
||||
if(data[2]?.[0]) out.end = varint_to_i32(data[2][0].data);
|
||||
return out;
|
||||
});
|
||||
return out;
|
||||
}
|
||||
var write_mtype = (message: MessageType): string => {
|
||||
var out = [ `message ${message.name} {` ];
|
||||
message.nestedType?.forEach(m => out.push(indent(write_mtype(m), 1)));
|
||||
message.enumType?.forEach(en => out.push(indent(write_Enum(en), 1)));
|
||||
message.field?.forEach(field => out.push(write_Field(field)));
|
||||
if(message.extensionRange) message.extensionRange.forEach(er => out.push(` extensions ${er.start} to ${(er.end||0) - 1};`));
|
||||
if(message.extension?.length) out.push(indent(write_extensions(message.extension), 1));
|
||||
return out.concat(`}`).join("\n");
|
||||
};
|
||||
|
||||
|
||||
interface Descriptor {
|
||||
name?: string;
|
||||
package?: string;
|
||||
dependency?: string[];
|
||||
messageType?: MessageType[];
|
||||
enumType?: Enum[];
|
||||
extension?: Field[];
|
||||
options?: FileOptions;
|
||||
}
|
||||
function parse_FileDescriptor(buf: Uint8Array): Descriptor {
|
||||
var data = parse_shallow(buf);
|
||||
var out: Descriptor = {};
|
||||
if(data[1]?.[0]) out.name = u8str(data[1][0].data);
|
||||
if(data[2]?.[0]) out.package = u8str(data[2][0].data);
|
||||
if(data[3]?.[0]) out.dependency = data[3].map(x => u8str(x.data));
|
||||
|
||||
if(data[4]?.length >= 1) out.messageType = mappa(data[4], parse_mtype);
|
||||
if(data[5]?.length >= 1) out.enumType = mappa(data[5], parse_Enum);
|
||||
if(data[7]?.length >= 1) out.extension = mappa(data[7], parse_Field);
|
||||
|
||||
if(data[8]?.[0]) out.options = parse_FileOptions(data[8][0].data);
|
||||
|
||||
return out;
|
||||
}
|
||||
var write_FileDescriptor = (pb: Descriptor): string => {
|
||||
var out = [
|
||||
'syntax = "proto2";',
|
||||
''
|
||||
];
|
||||
if(pb.dependency) pb.dependency.forEach((n: string) => { if(n) out.push(`import "${n}";`); });
|
||||
if(pb.package) out.push(`package ${pb.package};\n`);
|
||||
if(pb.options) {
|
||||
var o = out.length;
|
||||
|
||||
if(pb.options.javaPackage) out.push(`option java_package = "${pb.options.javaPackage}";`);
|
||||
if(pb.options.javaOuterClassname?.replace(/\W/g, "")) out.push(`option java_outer_classname = "${pb.options.javaOuterClassname}";`);
|
||||
if(pb.options.javaMultipleFiles) out.push(`option java_multiple_files = true;`);
|
||||
if(pb.options.goPackage) out.push(`option go_package = "${pb.options.goPackage}";`);
|
||||
|
||||
if(out.length > o) out.push('');
|
||||
}
|
||||
|
||||
pb.enumType?.forEach(en => { if(en.name) out.push(write_Enum(en) + "\n"); });
|
||||
pb.messageType?.forEach(m => { if(m.name) { var o = write_mtype(m); if(o) out.push(o + "\n"); }});
|
||||
|
||||
if(pb.extension?.length) {
|
||||
var e = write_extensions(pb.extension, true, false);
|
||||
if(e) out.push(e);
|
||||
}
|
||||
return out.join("\n") + "\n";
|
||||
};
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region macho.ts
|
||||
|
||||
interface MachOEntry {
|
||||
type: number;
|
||||
subtype: number;
|
||||
offset: number;
|
||||
size: number;
|
||||
align?: number;
|
||||
data: Uint8Array;
|
||||
}
|
||||
var parse_fat = (buf: Uint8Array): MachOEntry[] => {
|
||||
var dv = u8_to_dataview(buf);
|
||||
if(dv.getUint32(0, false) !== 0xCAFEBABE) throw new Error("Unsupported file");
|
||||
var nfat_arch = dv.getUint32(4, false);
|
||||
var out: MachOEntry[] = [];
|
||||
for(var i = 0; i < nfat_arch; ++i) {
|
||||
var start = i * 20 + 8;
|
||||
|
||||
var cputype = dv.getUint32(start, false);
|
||||
var cpusubtype = dv.getUint32(start+4, false);
|
||||
var offset = dv.getUint32(start+8, false);
|
||||
var size = dv.getUint32(start+12, false);
|
||||
var align = dv.getUint32(start+16, false);
|
||||
|
||||
out.push({
|
||||
type: cputype,
|
||||
subtype: cpusubtype,
|
||||
offset,
|
||||
size,
|
||||
align,
|
||||
data: buf.slice(offset, offset + size)
|
||||
});
|
||||
}
|
||||
return out;
|
||||
};
|
||||
var parse_macho = (buf: Uint8Array): MachOEntry[] => {
|
||||
var dv = u8_to_dataview(buf);
|
||||
var magic = dv.getUint32(0, false);
|
||||
switch(magic) {
|
||||
// fat binary (x86_64 / aarch64)
|
||||
case 0xCAFEBABE: return parse_fat(buf);
|
||||
// x86_64
|
||||
case 0xCFFAEDFE: return [{
|
||||
type: dv.getUint32(4, false),
|
||||
subtype: dv.getUint32(8, false),
|
||||
offset: 0,
|
||||
size: buf.length,
|
||||
data: buf
|
||||
}];
|
||||
}
|
||||
throw new Error("Unsupported file");
|
||||
};
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region otorp.ts
|
||||
|
||||
interface OtorpEntry {
|
||||
name: string;
|
||||
proto: string;
|
||||
}
|
||||
|
||||
/** Find and stringify all relevant protobuf defs */
|
||||
function otorp(buf: Uint8Array, builtins = false): OtorpEntry[] {
|
||||
var res = proto_offsets(buf);
|
||||
var registry: {[key: string]: Descriptor} = {};
|
||||
var names: Set<string> = new Set();
|
||||
var out: OtorpEntry[] = [];
|
||||
|
||||
res.forEach((r, i) => {
|
||||
if(!builtins && r[1].startsWith("google/protobuf/")) return;
|
||||
var b = buf.slice(r[0], i < res.length - 1 ? res[i+1][0] : buf.length);
|
||||
var pb = parse_FileDescriptorProto(b/*, r[1]*/);
|
||||
names.add(r[1]);
|
||||
registry[r[1]] = pb;
|
||||
});
|
||||
|
||||
names.forEach(name => {
|
||||
/* ensure partial ordering by dependencies */
|
||||
names.delete(name);
|
||||
var pb = registry[name];
|
||||
var doit = (pb.dependency||[]).every((d: string) => !names.has(d));
|
||||
if(!doit) { names.add(name); return; }
|
||||
|
||||
var dups = res.filter(r => r[1] == name);
|
||||
if(dups.length == 1) return out.push({ name, proto: write_FileDescriptor(pb) });
|
||||
|
||||
/* in a fat binary, compare the defs for x86_64/aarch64 */
|
||||
var pbs = dups.map(r => {
|
||||
var i = res.indexOf(r);
|
||||
var b = buf.slice(r[0], i < res.length - 1 ? res[i+1][0] : buf.length);
|
||||
var pb = parse_FileDescriptorProto(b/*, r[1]*/);
|
||||
return write_FileDescriptor(pb);
|
||||
});
|
||||
for(var l = 1; l < pbs.length; ++l) if(pbs[l] != pbs[0]) throw new Error(`Conflicting definitions for ${name} at offsets 0x${dups[0][0].toString(16)} and 0x${dups[l][0].toString(16)}`);
|
||||
return out.push({ name, proto: pbs[0] });
|
||||
});
|
||||
|
||||
return out;
|
||||
}
|
||||
export default otorp;
|
||||
|
||||
/** Determine if an address is being referenced */
|
||||
var is_referenced = (buf: Uint8Array, pos: number): boolean => {
|
||||
var dv = u8_to_dataview(buf);
|
||||
|
||||
/* Search for LEA reference (x86) */
|
||||
for(var leaddr = 0; leaddr > -1 && leaddr < pos; leaddr = u8indexOf(buf, 0x8D, leaddr + 1))
|
||||
if(dv.getUint32(leaddr + 2, true) == pos - leaddr - 6) return true;
|
||||
|
||||
/* Search for absolute reference to address */
|
||||
try {
|
||||
var headers = parse_macho(buf);
|
||||
for(var i = 0; i < headers.length; ++i) {
|
||||
if(pos < headers[i].offset || pos > headers[i].offset + headers[i].size) continue;
|
||||
var b = headers[i].data;
|
||||
var p = pos - headers[i].offset;
|
||||
var ref = new Uint8Array([0,0,0,0,0,0,0,0]);
|
||||
var dv = u8_to_dataview(ref);
|
||||
dv.setUint32(0, p, true);
|
||||
if(u8indexOf(b, ref, 0) > 0) return true;
|
||||
ref[4] = 0x01;
|
||||
if(u8indexOf(b, ref, 0) > 0) return true;
|
||||
ref[4] = 0x00; ref[6] = 0x10;
|
||||
if(u8indexOf(b, ref, 0) > 0) return true;
|
||||
}
|
||||
} catch(e) {throw e}
|
||||
return false;
|
||||
};
|
||||
|
||||
type OffsetList = Array<[number, string, number, number]>;
|
||||
/** Generate a list of potential starting points */
|
||||
var proto_offsets = (buf: Uint8Array): OffsetList => {
|
||||
var meta = parse_macho(buf);
|
||||
var out: OffsetList = [];
|
||||
var off = 0;
|
||||
/* note: this loop only works for names < 128 chars */
|
||||
search: while((off = u8indexOf(buf, ".proto", off + 1)) > -1) {
|
||||
var pos = off;
|
||||
off += 6;
|
||||
while(off - pos < 256 && buf[pos] != off - pos - 1) {
|
||||
if(buf[pos] > 0x7F || buf[pos] < 0x20) continue search;
|
||||
--pos;
|
||||
}
|
||||
if(off - pos > 250) continue;
|
||||
var name = u8str(buf.slice(pos + 1, off));
|
||||
if(buf[--pos] != 0x0A) continue;
|
||||
if(!is_referenced(buf, pos)) { console.error(`Reference to ${name} at ${pos} not found`); continue; }
|
||||
var bin = meta.find(m => m.offset <= pos && m.offset + m.size >= pos);
|
||||
out.push([pos, name, bin?.type || -1, bin?.subtype || -1]);
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
/** Parse a descriptor that starts with the first byte of the supplied buffer */
|
||||
var parse_FileDescriptorProto = (buf: Uint8Array): Descriptor => {
|
||||
var l = buf.length;
|
||||
while(l > 0) try {
|
||||
var b = buf.slice(0,l);
|
||||
var o = parse_FileDescriptor(b);
|
||||
return o;
|
||||
} catch(e) {
|
||||
var m = e.message.match(/at offset (\d+)/);
|
||||
if(m && parseInt(m[1], 10) < buf.length) l = parseInt(m[1], 10) - 1;
|
||||
else --l;
|
||||
}
|
||||
throw new RangeError("no protobuf message in range");
|
||||
};
|
||||
|
||||
|
||||
// #endregion
|
||||
|
||||
let spin: TerminalSpinner;
|
||||
const width = Deno.consoleSize().columns;
|
||||
function process(inf: string, outf: string) {
|
||||
const fi = Deno.statSync(inf);
|
||||
if(fi.isDirectory) for(let info of Deno.readDirSync(inf)) {
|
||||
if(spin) spin.set(inf.length > width - 4 ? "…" + inf.slice(-(width-4)) : inf);
|
||||
process(inf + (inf.slice(-1) == "/" ? "" : "/") + info.name, outf);
|
||||
}
|
||||
try {
|
||||
const buf: Uint8Array = Deno.readFileSync(inf);
|
||||
var dv = u8_to_dataview(buf);
|
||||
var magic = dv.getUint32(0, false);
|
||||
if(![0xCAFEBABE, 0xCFFAEDFE].includes(magic)) return;
|
||||
|
||||
otorp(buf).forEach(({name, proto}) => {
|
||||
if(!outf) return console.log(proto);
|
||||
var pth = resolve(outf || "./", name.replace(/[/]/g, "$"));
|
||||
try {
|
||||
const str = Deno.readTextFileSync(pth);
|
||||
if(str == proto) return;
|
||||
throw `${pth} definition diverges!`;
|
||||
} catch(e) { if(typeof e == "string") throw e; }
|
||||
console.error(`writing ${name} to ${pth}`);
|
||||
Deno.writeTextFileSync(pth, proto);
|
||||
});
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
function doit() {
|
||||
const [ inf, outf ] = Deno.args;
|
||||
if(!inf || inf == "-h" || inf == "--help") {
|
||||
console.log(`usage: otorp.ts <path/to/bin> [output/folder]
|
||||
|
||||
if no output folder specified, log all discovered defs
|
||||
if output folder specified, attempt to write defs in the folder
|
||||
|
||||
$ otorp.ts /Applications/Numbers.app out/ # search all files
|
||||
$ otorp.ts /Applications/Numbers.app/Contents/MacOS/Numbers # search one file
|
||||
`);
|
||||
Deno.exit(1);
|
||||
}
|
||||
if(Deno.statSync(inf).isDirectory) (spin = new TerminalSpinner("")).start();
|
||||
if(outf) try { Deno.mkdirSync(outf, { recursive: true }); } catch(e) {}
|
||||
process(inf, outf);
|
||||
if(spin) spin.stop();
|
||||
}
|
||||
doit();
|
54
test.js
54
test.js
@ -13,10 +13,8 @@ declare var before:(test:EmptyFunc)=>void;
|
||||
declare var afterEach:(test:EmptyFunc)=>void;
|
||||
declare var cptable: any;
|
||||
*/
|
||||
var X, XLSX_ZAHL;
|
||||
var modp = './';
|
||||
var X = require("./"), XLSX_ZAHL = require("./dist/xlsx.zahl");
|
||||
var fs = require('fs'), assert = require('assert');
|
||||
describe('source',function(){it('should load',function(){X=require(modp);});});
|
||||
var DIF_XL = true;
|
||||
|
||||
var browser = typeof document !== 'undefined';
|
||||
@ -56,6 +54,8 @@ if(!browser) {
|
||||
for(var _fileAi = 0; _fileAi < _fileA.length; ++_fileAi) if(test_file(_fileA[_fileAi])) fileA.push(_fileA[_fileAi]);
|
||||
}
|
||||
|
||||
var can_write_numbers = typeof Array.prototype.findIndex == "function" && typeof Uint8Array !== "undefined" && typeof Uint8Array.prototype.indexOf == "function";
|
||||
|
||||
/* Excel enforces 31 character sheet limit, although technical file limit is 255 */
|
||||
function fixsheetname(x/*:string*/)/*:string*/ { return x.substr(0,31); }
|
||||
|
||||
@ -396,11 +396,6 @@ function check_comments(wb) {
|
||||
|
||||
describe('parse options', function() {
|
||||
var html_cell_types = ['s'];
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
describe('cell', function() {
|
||||
it('XLSX should generate HTML by default', function() {
|
||||
var wb = X.read(fs.readFileSync(paths.cstxlsx), {type:TYPE});
|
||||
@ -748,7 +743,6 @@ describe('output formats', function() {
|
||||
["prn", false, true]
|
||||
];
|
||||
function RT(T) {
|
||||
if(!X) X = require(modp);
|
||||
fmts.forEach(function(fmt) {
|
||||
var wb = X.utils.book_new();
|
||||
X.utils.book_append_sheet(wb, X.utils.aoa_to_sheet([['R',"\u2603"],["\u0BEE",2]]), "Sheet1");
|
||||
@ -927,7 +921,6 @@ describe('parse features', function() {
|
||||
|
||||
describe('comments', function() {
|
||||
if(fs.existsSync(paths.swcxlsx)) it('should have comment as part of cell properties', function(){
|
||||
X = require(modp);
|
||||
var sheet = 'Sheet1';
|
||||
var wb1=X.read(fs.readFileSync(paths.swcxlsx), {type:TYPE});
|
||||
var wb2=X.read(fs.readFileSync(paths.swcxlsb), {type:TYPE});
|
||||
@ -1032,7 +1025,6 @@ describe('parse features', function() {
|
||||
describe('column properties', function() {
|
||||
var wbs = [], wbs_no_slk = [];
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
wbs = CWPaths.map(function(n) { return X.read(fs.readFileSync(n), {type:TYPE, cellStyles:true}); });
|
||||
wbs_no_slk = wbs.slice(0, 5);
|
||||
});
|
||||
@ -1075,7 +1067,6 @@ describe('parse features', function() {
|
||||
var wbs = [], ols = [];
|
||||
var ol = fs.existsSync(paths.olxls);
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
wbs = RHPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, cellStyles:true}); });
|
||||
/* */
|
||||
if(!ol) return;
|
||||
@ -1121,7 +1112,6 @@ describe('parse features', function() {
|
||||
describe('merge cells',function() {
|
||||
var wbs=[];
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
wbs = MCPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE}); });
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
@ -1140,7 +1130,6 @@ describe('parse features', function() {
|
||||
describe('should find hyperlinks', function() {
|
||||
var wb1, wb2;
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
wb1 = HLPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:true}); });
|
||||
wb2 = ILPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:true}); });
|
||||
});
|
||||
@ -1452,7 +1441,7 @@ describe('parse features', function() {
|
||||
// TODO: keep in sync with BookType, support other formats
|
||||
"xlsx"/*, "xlsm" */, "xlsb"/* xls / xla / biff# */, "xlml", "ods", "fods"/*, "csv", "txt", */, "sylk", "html", "dif", "rtf"/*, "prn", "eth"*/, "dbf", "numbers"
|
||||
].forEach(function(r) {
|
||||
if(!XLSX_ZAHL) XLSX_ZAHL=require("./dist/xlsx.zahl");
|
||||
if(r == "numbers" && !can_write_numbers) return;
|
||||
var ws = X.utils.aoa_to_sheet([ ["a", "b", "c"], [1, 2, 3] ]);
|
||||
var wb = X.utils.book_new(); X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
var data = X.write(wb, {type: TYPE, bookType: r, WTF: true, numbers:XLSX_ZAHL });
|
||||
@ -1480,7 +1469,6 @@ describe('write features', function() {
|
||||
};
|
||||
var ws;
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
ws = X.utils.aoa_to_sheet([["a","b","c"],[1,2,3]]);
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
@ -1558,6 +1546,22 @@ describe('write features', function() {
|
||||
assert.equal(Name.Ref, "Sheet1!$A$1:$C$3");
|
||||
assert.equal(wb2.Workbook.Names.length, wb3.Workbook.Names.length);
|
||||
}); });
|
||||
it('should handle non-string values for "s" cells', function() {[
|
||||
"xlsx", "xlsb", "xls", "biff5", "biff2", "xlml", "numbers", "ods", "fods", "wk3", "csv", "txt", "sylk", "html", "dif", "dbf", "wk1", "rtf", "prn"
|
||||
].forEach(function(fmt) {
|
||||
if(fmt == "numbers" && !can_write_numbers) return;
|
||||
var ws = X.utils.aoa_to_sheet([
|
||||
["String", "123"],
|
||||
["Number", 123],
|
||||
["Boolean", true],
|
||||
["Date", new Date()],
|
||||
], { cellDates: true });
|
||||
ws["B2"].t = ws["B3"].t = ws["B4"].t = "s"
|
||||
var wb = X.utils.book_new();
|
||||
X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
X.write(wb, {type: TYPE, bookType: fmt, bookSST: false, numbers:XLSX_ZAHL});
|
||||
X.write(wb, {type: TYPE, bookType: fmt, bookSST: true, numbers:XLSX_ZAHL});
|
||||
}); });
|
||||
});
|
||||
|
||||
function seq(end/*:number*/, start/*:?number*/)/*:Array<number>*/ {
|
||||
@ -1594,9 +1598,6 @@ function parseDate(str/*:string|Date*/)/*:Date*/ {
|
||||
var fixdate = browser ? parseDate("2014-02-19T14:30:00.000Z") : new Date("2014-02-19T14:30Z");
|
||||
|
||||
describe('roundtrip features', function() {
|
||||
var bef = (function() { X = require(modp); XLSX_ZAHL=require("./dist/xlsx.zahl"); });
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
describe('should preserve core properties', function() { [
|
||||
['xls', paths.cpxls],
|
||||
['xlml', paths.cpxml],
|
||||
@ -1627,6 +1628,7 @@ describe('roundtrip features', function() {
|
||||
|
||||
describe('should preserve merge cells', function() {
|
||||
["xlsx", "xlsb", "xlml", "ods", "biff8", "numbers"].forEach(function(f) { it(f, function() {
|
||||
if(f == "numbers" && !can_write_numbers) return;
|
||||
var wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE});
|
||||
var wb2 = X.read(X.write(wb1,{bookType:f,type:'binary',numbers:XLSX_ZAHL}),{type:'binary'});
|
||||
var m1 = wb1.Sheets["Merge"]['!merges'].map(X.utils.encode_range);
|
||||
@ -2225,7 +2227,7 @@ describe('CSV', function() {
|
||||
assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]);
|
||||
}
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
var B1 = get_cell(ws, "B1"); console.log(B1); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15);
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
@ -2363,7 +2365,7 @@ describe('numbers', function() {
|
||||
assert.equal(get_cell(ws, "B11").v, true);
|
||||
assert.equal(get_cell(ws, "B13").v, 50);
|
||||
});
|
||||
it('should cap cols at 1000 (ALL)', function() {
|
||||
if(can_write_numbers) it('should cap cols at 1000 (ALL)', function() {
|
||||
var aoa = [[1], [], []]; aoa[1][999] = 2; aoa[2][1000] = 3;
|
||||
var ws1 = X.utils.aoa_to_sheet(aoa);
|
||||
var wb1 = X.utils.book_new(); X.utils.book_append_sheet(wb1, ws1, "Sheet1");
|
||||
@ -2399,6 +2401,16 @@ describe('dbf', function() {
|
||||
["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
].forEach(function(r) { assert.equal(get_cell(ws, r[0])[r[1]], r[2]); });
|
||||
});
|
||||
if(!browser || typeof cptable !== 'undefined') it("Ś╫êëτ⌡ś and Š╫ěéτ⌡š", function() {
|
||||
[ [620, "Ś╫êëτ⌡ś"], [895, "Š╫ěéτ⌡š"] ].forEach(function(r) {
|
||||
var book = X.utils.book_new();
|
||||
var sheet = X.utils.aoa_to_sheet([["ASCII", "encoded"], ["Test", r[1]]]);
|
||||
X.utils.book_append_sheet(book, sheet, "sheet1");
|
||||
var data = X.write(book, {type: TYPE, bookType: "dbf", codepage:r[0]});
|
||||
var wb = X.read(data, {type: TYPE});
|
||||
assert.equal(wb.Sheets.Sheet1.B2.v, r[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
var JSDOM = null;
|
||||
// $FlowIgnore
|
||||
|
20
test.mjs
generated
20
test.mjs
generated
@ -58,6 +58,8 @@ if(!browser) {
|
||||
for(var _fileAi = 0; _fileAi < _fileA.length; ++_fileAi) if(test_file(_fileA[_fileAi])) fileA.push(_fileA[_fileAi]);
|
||||
}
|
||||
|
||||
var can_write_numbers = typeof Set !== "undefined" && typeof Array.prototype.findIndex == "function" && typeof Uint8Array !== "undefined" && typeof Uint8Array.prototype.indexOf == "function";
|
||||
|
||||
/* Excel enforces 31 character sheet limit, although technical file limit is 255 */
|
||||
function fixsheetname(x/*:string*/)/*:string*/ { return x.substr(0,31); }
|
||||
|
||||
@ -1443,6 +1445,7 @@ describe('parse features', function() {
|
||||
// TODO: keep in sync with BookType, support other formats
|
||||
"xlsx"/*, "xlsm" */, "xlsb"/* xls / xla / biff# */, "xlml", "ods", "fods"/*, "csv", "txt", */, "sylk", "html", "dif", "rtf"/*, "prn", "eth"*/, "dbf", "numbers"
|
||||
].forEach(function(r) {
|
||||
if(r == "numbers" && !can_write_numbers) return;
|
||||
var ws = X.utils.aoa_to_sheet([ ["a", "b", "c"], [1, 2, 3] ]);
|
||||
var wb = X.utils.book_new(); X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
var data = X.write(wb, {type: TYPE, bookType: r, WTF: true, numbers:XLSX_ZAHL });
|
||||
@ -1613,6 +1616,7 @@ describe('roundtrip features', function() {
|
||||
|
||||
describe('should preserve merge cells', function() {
|
||||
["xlsx", "xlsb", "xlml", "ods", "biff8", "numbers"].forEach(function(f) { it(f, function() {
|
||||
if(f == "numbers" && !can_write_numbers) return;
|
||||
var wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE});
|
||||
var wb2 = X.read(X.write(wb1,{bookType:f,type:'binary',numbers:XLSX_ZAHL}),{type:'binary'});
|
||||
var m1 = wb1.Sheets["Merge"]['!merges'].map(X.utils.encode_range);
|
||||
@ -2204,14 +2208,14 @@ describe('CSV', function() {
|
||||
["3a", "3 a", "3 a-1"],
|
||||
["3b", "3 b", "3 b-1"],
|
||||
["3p", "3 P", "3 p-1"]
|
||||
]
|
||||
];
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]);
|
||||
assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]);
|
||||
}
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
var B1 = get_cell(ws, "B1"); console.log(B1); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15);
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
@ -2349,7 +2353,7 @@ describe('numbers', function() {
|
||||
assert.equal(get_cell(ws, "B11").v, true);
|
||||
assert.equal(get_cell(ws, "B13").v, 50);
|
||||
});
|
||||
it('should cap cols at 1000 (ALL)', function() {
|
||||
if(can_write_numbers) it('should cap cols at 1000 (ALL)', function() {
|
||||
var aoa = [[1], [], []]; aoa[1][999] = 2; aoa[2][1000] = 3;
|
||||
var ws1 = X.utils.aoa_to_sheet(aoa);
|
||||
var wb1 = X.utils.book_new(); X.utils.book_append_sheet(wb1, ws1, "Sheet1");
|
||||
@ -2385,6 +2389,16 @@ describe('dbf', function() {
|
||||
["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
].forEach(function(r) { assert.equal(get_cell(ws, r[0])[r[1]], r[2]); });
|
||||
});
|
||||
if(!browser || typeof cptable !== 'undefined') it("Ś╫êëτ⌡ś and Š╫ěéτ⌡š", function() {
|
||||
[ [620, "Ś╫êëτ⌡ś"], [895, "Š╫ěéτ⌡š"] ].forEach(function(r) {
|
||||
var book = X.utils.book_new();
|
||||
var sheet = X.utils.aoa_to_sheet([["ASCII", "encoded"], ["Test", r[1]]]);
|
||||
X.utils.book_append_sheet(book, sheet, "sheet1");
|
||||
var data = X.write(book, {type: TYPE, bookType: "dbf", codepage:r[0]});
|
||||
var wb = X.read(data, {type: TYPE});
|
||||
assert.equal(wb.Sheets.Sheet1.B2.v, r[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
import { JSDOM } from 'jsdom';
|
||||
var domtest = true;
|
||||
|
20
test.mts
20
test.mts
@ -78,6 +78,8 @@ if(!browser) {
|
||||
for(var _fileAi = 0; _fileAi < _fileA.length; ++_fileAi) if(test_file(_fileA[_fileAi])) fileA.push(_fileA[_fileAi]);
|
||||
}
|
||||
|
||||
var can_write_numbers = typeof Set !== "undefined" && typeof Array.prototype.findIndex == "function" && typeof Uint8Array !== "undefined" && typeof Uint8Array.prototype.indexOf == "function";
|
||||
|
||||
/* Excel enforces 31 character sheet limit, although technical file limit is 255 */
|
||||
function fixsheetname(x: string): string { return x.substr(0,31); }
|
||||
|
||||
@ -1408,6 +1410,7 @@ describe('parse features', function() {
|
||||
// TODO: keep in sync with BookType, support other formats
|
||||
"xlsx"/*, "xlsm" */, "xlsb"/* xls / xla / biff# */, "xlml", "ods", "fods"/*, "csv", "txt", */, "sylk", "html", "dif", "rtf"/*, "prn", "eth"*/, "dbf", "numbers"
|
||||
] as X.BookType[]).forEach(function(r: X.BookType) {
|
||||
if(r == "numbers" && !can_write_numbers) return;
|
||||
var ws = X.utils.aoa_to_sheet([ ["a", "b", "c"], [1, 2, 3] ]);
|
||||
var wb = X.utils.book_new(); X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
var data = X.write(wb, {type: TYPE, bookType: r, WTF: true, numbers:XLSX_ZAHL });
|
||||
@ -1573,6 +1576,7 @@ describe('roundtrip features', function() {
|
||||
|
||||
describe('should preserve merge cells', function() {
|
||||
var mcf = ["xlsx", "xlsb", "xlml", "ods", "biff8", "numbers"] as Array<X.BookType>; for(let mci = 0; mci < mcf.length; ++mci) { let f = mcf[mci]; it(f, function() {
|
||||
if(f == "numbers" && !can_write_numbers) return;
|
||||
var wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE});
|
||||
var wb2 = X.read(X.write(wb1,{bookType:f,type:'binary',numbers:XLSX_ZAHL}),{type:'binary'});
|
||||
var m1 = wb1.Sheets["Merge"]?.['!merges']?.map(X.utils.encode_range);
|
||||
@ -2160,14 +2164,14 @@ describe('CSV', function() {
|
||||
["3a", "3 a", "3 a-1"],
|
||||
["3b", "3 b", "3 b-1"],
|
||||
["3p", "3 P", "3 p-1"],
|
||||
]
|
||||
];
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]);
|
||||
assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]);
|
||||
}
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
var B1 = get_cell(ws, "B1"); console.log(B1); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15);
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
@ -2295,7 +2299,7 @@ describe('numbers', function() {
|
||||
assert.equal(get_cell(ws, "B11").v, true);
|
||||
assert.equal(get_cell(ws, "B13").v, 50);
|
||||
});
|
||||
it('should cap cols at 1000 (ALL)', function() {
|
||||
if(can_write_numbers) it('should cap cols at 1000 (ALL)', function() {
|
||||
var aoa = [[1], [], []]; aoa[1][999] = 2; aoa[2][1000] = 3;
|
||||
var ws1 = X.utils.aoa_to_sheet(aoa);
|
||||
var wb1 = X.utils.book_new(); X.utils.book_append_sheet(wb1, ws1, "Sheet1");
|
||||
@ -2326,6 +2330,16 @@ describe('dbf', function() {
|
||||
["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
] as Array<[string, string, any]>).forEach(function(r) { assert.equal(get_cell(ws, r[0])[r[1]], r[2]); });
|
||||
});
|
||||
it("Ś╫êëτ⌡ś and Š╫ěéτ⌡š", function() {
|
||||
([ [620, "Ś╫êëτ⌡ś"], [895, "Š╫ěéτ⌡š"] ] as Array<[number,string]>).forEach(function(r) {
|
||||
var book = X.utils.book_new();
|
||||
var sheet = X.utils.aoa_to_sheet([["ASCII", "encoded"], ["Test", r[1]]]);
|
||||
X.utils.book_append_sheet(book, sheet, "sheet1");
|
||||
var data = X.write(book, {type: TYPE, bookType: "dbf", codepage:r[0]});
|
||||
var wb = X.read(data, {type: TYPE});
|
||||
assert.equal(wb.Sheets.Sheet1.B2.v, r[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
import { JSDOM } from 'jsdom';
|
||||
var domtest = false; // error: Error: Not implemented: isContext
|
||||
|
20
test.ts
20
test.ts
@ -78,6 +78,8 @@ if(!browser) {
|
||||
for(var _fileAi = 0; _fileAi < _fileA.length; ++_fileAi) if(test_file(_fileA[_fileAi])) fileA.push(_fileA[_fileAi]);
|
||||
}
|
||||
|
||||
var can_write_numbers = typeof Set !== "undefined" && typeof Array.prototype.findIndex == "function" && typeof Uint8Array !== "undefined" && typeof Uint8Array.prototype.indexOf == "function";
|
||||
|
||||
/* Excel enforces 31 character sheet limit, although technical file limit is 255 */
|
||||
function fixsheetname(x: string): string { return x.substr(0,31); }
|
||||
|
||||
@ -1408,6 +1410,7 @@ Deno.test('parse features', async function(t) {
|
||||
// TODO: keep in sync with BookType, support other formats
|
||||
"xlsx"/*, "xlsm" */, "xlsb"/* xls / xla / biff# */, "xlml", "ods", "fods"/*, "csv", "txt", */, "sylk", "html", "dif", "rtf"/*, "prn", "eth"*/, "dbf", "numbers"
|
||||
] as X.BookType[]).forEach(function(r: X.BookType) {
|
||||
if(r == "numbers" && !can_write_numbers) return;
|
||||
var ws = X.utils.aoa_to_sheet([ ["a", "b", "c"], [1, 2, 3] ]);
|
||||
var wb = X.utils.book_new(); X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
var data = X.write(wb, {type: TYPE, bookType: r, WTF: true, numbers:XLSX_ZAHL });
|
||||
@ -1573,6 +1576,7 @@ Deno.test('roundtrip features', async function(t) {
|
||||
|
||||
await t.step('should preserve merge cells', async function(t) {
|
||||
var mcf = ["xlsx", "xlsb", "xlml", "ods", "biff8", "numbers"] as Array<X.BookType>; for(let mci = 0; mci < mcf.length; ++mci) { let f = mcf[mci]; await t.step(f, async function(t) {
|
||||
if(f == "numbers" && !can_write_numbers) return;
|
||||
var wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE});
|
||||
var wb2 = X.read(X.write(wb1,{bookType:f,type:'binary',numbers:XLSX_ZAHL}),{type:'binary'});
|
||||
var m1 = wb1.Sheets["Merge"]?.['!merges']?.map(X.utils.encode_range);
|
||||
@ -2160,14 +2164,14 @@ Deno.test('CSV', async function(t) {
|
||||
["3a", "3 a", "3 a-1"],
|
||||
["3b", "3 b", "3 b-1"],
|
||||
["3p", "3 P", "3 p-1"],
|
||||
]
|
||||
];
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]);
|
||||
assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]);
|
||||
}
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
var B1 = get_cell(ws, "B1"); console.log(B1); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15);
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
@ -2295,7 +2299,7 @@ Deno.test('numbers', async function(t) {
|
||||
assert.equal(get_cell(ws, "B11").v, true);
|
||||
assert.equal(get_cell(ws, "B13").v, 50);
|
||||
});
|
||||
await t.step('should cap cols at 1000 (ALL)', async function(t) {
|
||||
if(can_write_numbers) await t.step('should cap cols at 1000 (ALL)', async function(t) {
|
||||
var aoa = [[1], [], []]; aoa[1][999] = 2; aoa[2][1000] = 3;
|
||||
var ws1 = X.utils.aoa_to_sheet(aoa);
|
||||
var wb1 = X.utils.book_new(); X.utils.book_append_sheet(wb1, ws1, "Sheet1");
|
||||
@ -2326,6 +2330,16 @@ Deno.test('dbf', async function(t) {
|
||||
["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
] as Array<[string, string, any]>).forEach(function(r) { assert.equal(get_cell(ws, r[0])[r[1]], r[2]); });
|
||||
});
|
||||
await t.step("Ś╫êëτ⌡ś and Š╫ěéτ⌡š", async function(t) {
|
||||
([ [620, "Ś╫êëτ⌡ś"], [895, "Š╫ěéτ⌡š"] ] as Array<[number,string]>).forEach(function(r) {
|
||||
var book = X.utils.book_new();
|
||||
var sheet = X.utils.aoa_to_sheet([["ASCII", "encoded"], ["Test", r[1]]]);
|
||||
X.utils.book_append_sheet(book, sheet, "sheet1");
|
||||
var data = X.write(book, {type: TYPE, bookType: "dbf", codepage:r[0]});
|
||||
var wb = X.read(data, {type: TYPE});
|
||||
assert.equal(wb.Sheets.Sheet1.B2.v, r[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
import { JSDOM } from 'jsdom';
|
||||
var domtest = false; // error: Error: Not implemented: isContext
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit f91c73f99ccb7919b7992e720f9ba7a730071770
|
||||
Subproject commit 1ea05a3eee0a746c102dea42e729b31e4ebfca35
|
7
hotcross.mjs → testbun.mjs
generated
7
hotcross.mjs → testbun.mjs
generated
@ -5,13 +5,6 @@ var it = function(m,cb){console.log(" ".repeat(pdizzle) + m); ++pdizzle; if(cb)
|
||||
it.skip = function(m,cb){};
|
||||
var before = function(cb){if(cb) cb();};
|
||||
var afterEach = function(cb){if(cb) cb();};
|
||||
try {
|
||||
new Buffer(925).copy(new Buffer(3072), 2048, 0, 925);
|
||||
} catch(e) {
|
||||
Buffer.prototype.copy = function(dst, dstStart, srcStart, srcEnd) {
|
||||
for(var j = srcStart; j < srcEnd; ++j) dst[j + dstStart] = this[j + srcStart];
|
||||
};
|
||||
}
|
||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
/* vim: set ts=2: */
|
||||
/*jshint mocha:true */
|
20
testnocp.ts
20
testnocp.ts
@ -77,6 +77,8 @@ if(!browser) {
|
||||
for(var _fileAi = 0; _fileAi < _fileA.length; ++_fileAi) if(test_file(_fileA[_fileAi])) fileA.push(_fileA[_fileAi]);
|
||||
}
|
||||
|
||||
var can_write_numbers = typeof Set !== "undefined" && typeof Array.prototype.findIndex == "function" && typeof Uint8Array !== "undefined" && typeof Uint8Array.prototype.indexOf == "function";
|
||||
|
||||
/* Excel enforces 31 character sheet limit, although technical file limit is 255 */
|
||||
function fixsheetname(x: string): string { return x.substr(0,31); }
|
||||
|
||||
@ -1407,6 +1409,7 @@ Deno.test('parse features', async function(t) {
|
||||
// TODO: keep in sync with BookType, support other formats
|
||||
"xlsx"/*, "xlsm" */, "xlsb"/* xls / xla / biff# */, "xlml", "ods", "fods"/*, "csv", "txt", */, "sylk", "html", "dif", "rtf"/*, "prn", "eth"*/, "dbf", "numbers"
|
||||
] as X.BookType[]).forEach(function(r: X.BookType) {
|
||||
if(r == "numbers" && !can_write_numbers) return;
|
||||
var ws = X.utils.aoa_to_sheet([ ["a", "b", "c"], [1, 2, 3] ]);
|
||||
var wb = X.utils.book_new(); X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
var data = X.write(wb, {type: TYPE, bookType: r, WTF: true, numbers:XLSX_ZAHL });
|
||||
@ -1572,6 +1575,7 @@ Deno.test('roundtrip features', async function(t) {
|
||||
|
||||
await t.step('should preserve merge cells', async function(t) {
|
||||
var mcf = ["xlsx", "xlsb", "xlml", "ods", "biff8", "numbers"] as Array<X.BookType>; for(let mci = 0; mci < mcf.length; ++mci) { let f = mcf[mci]; await t.step(f, async function(t) {
|
||||
if(f == "numbers" && !can_write_numbers) return;
|
||||
var wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE});
|
||||
var wb2 = X.read(X.write(wb1,{bookType:f,type:'binary',numbers:XLSX_ZAHL}),{type:'binary'});
|
||||
var m1 = wb1.Sheets["Merge"]?.['!merges']?.map(X.utils.encode_range);
|
||||
@ -2159,14 +2163,14 @@ Deno.test('CSV', async function(t) {
|
||||
["3a", "3 a", "3 a-1"],
|
||||
["3b", "3 b", "3 b-1"],
|
||||
["3p", "3 P", "3 p-1"],
|
||||
]
|
||||
];
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]);
|
||||
assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]);
|
||||
}
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
var B1 = get_cell(ws, "B1"); console.log(B1); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15);
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
@ -2294,7 +2298,7 @@ Deno.test('numbers', async function(t) {
|
||||
assert.equal(get_cell(ws, "B11").v, true);
|
||||
assert.equal(get_cell(ws, "B13").v, 50);
|
||||
});
|
||||
await t.step('should cap cols at 1000 (ALL)', async function(t) {
|
||||
if(can_write_numbers) await t.step('should cap cols at 1000 (ALL)', async function(t) {
|
||||
var aoa = [[1], [], []]; aoa[1][999] = 2; aoa[2][1000] = 3;
|
||||
var ws1 = X.utils.aoa_to_sheet(aoa);
|
||||
var wb1 = X.utils.book_new(); X.utils.book_append_sheet(wb1, ws1, "Sheet1");
|
||||
@ -2325,6 +2329,16 @@ Deno.test('dbf', async function(t) {
|
||||
["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
] as Array<[string, string, any]>).forEach(function(r) { assert.equal(get_cell(ws, r[0])[r[1]], r[2]); });
|
||||
});
|
||||
if(false) await t.step("Ś╫êëτ⌡ś and Š╫ěéτ⌡š", async function(t) {
|
||||
([ [620, "Ś╫êëτ⌡ś"], [895, "Š╫ěéτ⌡š"] ] as Array<[number,string]>).forEach(function(r) {
|
||||
var book = X.utils.book_new();
|
||||
var sheet = X.utils.aoa_to_sheet([["ASCII", "encoded"], ["Test", r[1]]]);
|
||||
X.utils.book_append_sheet(book, sheet, "sheet1");
|
||||
var data = X.write(book, {type: TYPE, bookType: "dbf", codepage:r[0]});
|
||||
var wb = X.read(data, {type: TYPE});
|
||||
assert.equal(wb.Sheets.Sheet1.B2.v, r[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
import { JSDOM } from 'jsdom';
|
||||
var domtest = false; // error: Error: Not implemented: isContext
|
||||
|
59
tests/core.js
generated
59
tests/core.js
generated
@ -13,10 +13,8 @@ declare var before:(test:EmptyFunc)=>void;
|
||||
declare var afterEach:(test:EmptyFunc)=>void;
|
||||
declare var cptable: any;
|
||||
*/
|
||||
var X, XLSX_ZAHL = XLSX_ZAHL_PAYLOAD;
|
||||
var modp = './';
|
||||
var X = require("./"), XLSX_ZAHL = require("./dist/xlsx.zahl");
|
||||
var fs = require('fs'), assert = require('assert');
|
||||
describe('source',function(){it('should load',function(){X=require(modp);});});
|
||||
var DIF_XL = true;
|
||||
|
||||
var browser = typeof document !== 'undefined';
|
||||
@ -27,7 +25,7 @@ var Buffer_from = /*::(*/function(){}/*:: :any)*/;
|
||||
|
||||
if(typeof Buffer !== 'undefined') {
|
||||
var nbfs = !Buffer.from;
|
||||
if(!nbfs) try { Buffer.from("foo", "utf8"); } catch(e) { nbfs = true; }
|
||||
if(!nbfs) try { Buffer.from("foo", "utf-8"); } catch(e) { nbfs = true; }
|
||||
Buffer_from = nbfs ? function(buf, enc) { return (enc) ? new Buffer(buf, enc) : new Buffer(buf); } : Buffer.from.bind(Buffer);
|
||||
// $FlowIgnore
|
||||
if(!Buffer.alloc) Buffer.alloc = function(n) { return new Buffer(n); };
|
||||
@ -56,6 +54,8 @@ if(!browser) {
|
||||
for(var _fileAi = 0; _fileAi < _fileA.length; ++_fileAi) if(test_file(_fileA[_fileAi])) fileA.push(_fileA[_fileAi]);
|
||||
}
|
||||
|
||||
var can_write_numbers = typeof Array.prototype.findIndex == "function" && typeof Uint8Array !== "undefined" && typeof Uint8Array.prototype.indexOf == "function";
|
||||
|
||||
/* Excel enforces 31 character sheet limit, although technical file limit is 255 */
|
||||
function fixsheetname(x/*:string*/)/*:string*/ { return x.substr(0,31); }
|
||||
|
||||
@ -396,11 +396,6 @@ function check_comments(wb) {
|
||||
|
||||
describe('parse options', function() {
|
||||
var html_cell_types = ['s'];
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
describe('cell', function() {
|
||||
it('XLSX should generate HTML by default', function() {
|
||||
var wb = X.read(fs.readFileSync(paths.cstxlsx), {type:TYPE});
|
||||
@ -748,7 +743,6 @@ describe('output formats', function() {
|
||||
["prn", false, true]
|
||||
];
|
||||
function RT(T) {
|
||||
if(!X) X = require(modp);
|
||||
fmts.forEach(function(fmt) {
|
||||
var wb = X.utils.book_new();
|
||||
X.utils.book_append_sheet(wb, X.utils.aoa_to_sheet([['R',"\u2603"],["\u0BEE",2]]), "Sheet1");
|
||||
@ -927,7 +921,6 @@ describe('parse features', function() {
|
||||
|
||||
describe('comments', function() {
|
||||
if(fs.existsSync(paths.swcxlsx)) it('should have comment as part of cell properties', function(){
|
||||
X = require(modp);
|
||||
var sheet = 'Sheet1';
|
||||
var wb1=X.read(fs.readFileSync(paths.swcxlsx), {type:TYPE});
|
||||
var wb2=X.read(fs.readFileSync(paths.swcxlsb), {type:TYPE});
|
||||
@ -1032,7 +1025,6 @@ describe('parse features', function() {
|
||||
describe('column properties', function() {
|
||||
var wbs = [], wbs_no_slk = [];
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
wbs = CWPaths.map(function(n) { return X.read(fs.readFileSync(n), {type:TYPE, cellStyles:true}); });
|
||||
wbs_no_slk = wbs.slice(0, 5);
|
||||
});
|
||||
@ -1075,7 +1067,6 @@ describe('parse features', function() {
|
||||
var wbs = [], ols = [];
|
||||
var ol = fs.existsSync(paths.olxls);
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
wbs = RHPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, cellStyles:true}); });
|
||||
/* */
|
||||
if(!ol) return;
|
||||
@ -1121,7 +1112,6 @@ describe('parse features', function() {
|
||||
describe('merge cells',function() {
|
||||
var wbs=[];
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
wbs = MCPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE}); });
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
@ -1140,7 +1130,6 @@ describe('parse features', function() {
|
||||
describe('should find hyperlinks', function() {
|
||||
var wb1, wb2;
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
wb1 = HLPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:true}); });
|
||||
wb2 = ILPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:true}); });
|
||||
});
|
||||
@ -1452,6 +1441,7 @@ describe('parse features', function() {
|
||||
// TODO: keep in sync with BookType, support other formats
|
||||
"xlsx"/*, "xlsm" */, "xlsb"/* xls / xla / biff# */, "xlml", "ods", "fods"/*, "csv", "txt", */, "sylk", "html", "dif", "rtf"/*, "prn", "eth"*/, "dbf", "numbers"
|
||||
].forEach(function(r) {
|
||||
if(r == "numbers" && !can_write_numbers) return;
|
||||
var ws = X.utils.aoa_to_sheet([ ["a", "b", "c"], [1, 2, 3] ]);
|
||||
var wb = X.utils.book_new(); X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
var data = X.write(wb, {type: TYPE, bookType: r, WTF: true, numbers:XLSX_ZAHL });
|
||||
@ -1479,7 +1469,6 @@ describe('write features', function() {
|
||||
};
|
||||
var ws;
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
ws = X.utils.aoa_to_sheet([["a","b","c"],[1,2,3]]);
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
@ -1557,6 +1546,22 @@ describe('write features', function() {
|
||||
assert.equal(Name.Ref, "Sheet1!$A$1:$C$3");
|
||||
assert.equal(wb2.Workbook.Names.length, wb3.Workbook.Names.length);
|
||||
}); });
|
||||
it('should handle non-string values for "s" cells', function() {[
|
||||
"xlsx", "xlsb", "xls", "biff5", "biff2", "xlml", "numbers", "ods", "fods", "wk3", "csv", "txt", "sylk", "html", "dif", "dbf", "wk1", "rtf", "prn"
|
||||
].forEach(function(fmt) {
|
||||
if(fmt == "numbers" && !can_write_numbers) return;
|
||||
var ws = X.utils.aoa_to_sheet([
|
||||
["String", "123"],
|
||||
["Number", 123],
|
||||
["Boolean", true],
|
||||
["Date", new Date()],
|
||||
], { cellDates: true });
|
||||
ws["B2"].t = ws["B3"].t = ws["B4"].t = "s"
|
||||
var wb = X.utils.book_new();
|
||||
X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
X.write(wb, {type: TYPE, bookType: fmt, bookSST: false, numbers:XLSX_ZAHL});
|
||||
X.write(wb, {type: TYPE, bookType: fmt, bookSST: true, numbers:XLSX_ZAHL});
|
||||
}); });
|
||||
});
|
||||
|
||||
function seq(end/*:number*/, start/*:?number*/)/*:Array<number>*/ {
|
||||
@ -1593,9 +1598,6 @@ function parseDate(str/*:string|Date*/)/*:Date*/ {
|
||||
var fixdate = browser ? parseDate("2014-02-19T14:30:00.000Z") : new Date("2014-02-19T14:30Z");
|
||||
|
||||
describe('roundtrip features', function() {
|
||||
var bef = (function() { X = require(modp); XLSX_ZAHL=require("./dist/xlsx.zahl"); });
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
describe('should preserve core properties', function() { [
|
||||
['xls', paths.cpxls],
|
||||
['xlml', paths.cpxml],
|
||||
@ -1626,6 +1628,7 @@ describe('roundtrip features', function() {
|
||||
|
||||
describe('should preserve merge cells', function() {
|
||||
["xlsx", "xlsb", "xlml", "ods", "biff8", "numbers"].forEach(function(f) { it(f, function() {
|
||||
if(f == "numbers" && !can_write_numbers) return;
|
||||
var wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE});
|
||||
var wb2 = X.read(X.write(wb1,{bookType:f,type:'binary',numbers:XLSX_ZAHL}),{type:'binary'});
|
||||
var m1 = wb1.Sheets["Merge"]['!merges'].map(X.utils.encode_range);
|
||||
@ -2124,7 +2127,7 @@ function plaintext_test(wb, raw) {
|
||||
var sheet = wb.Sheets[wb.SheetNames[0]];
|
||||
plaintext_val.forEach(function(x) {
|
||||
var cell = get_cell(sheet, x[0]);
|
||||
var tcval = x[2+(!!raw ? 1 : 0)];
|
||||
var tcval = x[2+(raw ? 1 : 0)];
|
||||
var type = raw ? 's' : x[1];
|
||||
if(x.length == 1) { if(cell) { assert.equal(cell.t, 'z'); assert.ok(!cell.v); } return; }
|
||||
assert.equal(cell.v, tcval); assert.equal(cell.t, type);
|
||||
@ -2217,14 +2220,14 @@ describe('CSV', function() {
|
||||
["3a", "3 a", "3 a-1"],
|
||||
["3b", "3 b", "3 b-1"],
|
||||
["3p", "3 P", "3 p-1"]
|
||||
]
|
||||
];
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]);
|
||||
assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]);
|
||||
}
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
var B1 = get_cell(ws, "B1"); console.log(B1); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15);
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
@ -2362,7 +2365,7 @@ describe('numbers', function() {
|
||||
assert.equal(get_cell(ws, "B11").v, true);
|
||||
assert.equal(get_cell(ws, "B13").v, 50);
|
||||
});
|
||||
it('should cap cols at 1000 (ALL)', function() {
|
||||
if(can_write_numbers) it('should cap cols at 1000 (ALL)', function() {
|
||||
var aoa = [[1], [], []]; aoa[1][999] = 2; aoa[2][1000] = 3;
|
||||
var ws1 = X.utils.aoa_to_sheet(aoa);
|
||||
var wb1 = X.utils.book_new(); X.utils.book_append_sheet(wb1, ws1, "Sheet1");
|
||||
@ -2398,6 +2401,16 @@ describe('dbf', function() {
|
||||
["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
].forEach(function(r) { assert.equal(get_cell(ws, r[0])[r[1]], r[2]); });
|
||||
});
|
||||
if(!browser || typeof cptable !== 'undefined') it("Ś╫êëτ⌡ś and Š╫ěéτ⌡š", function() {
|
||||
[ [620, "Ś╫êëτ⌡ś"], [895, "Š╫ěéτ⌡š"] ].forEach(function(r) {
|
||||
var book = X.utils.book_new();
|
||||
var sheet = X.utils.aoa_to_sheet([["ASCII", "encoded"], ["Test", r[1]]]);
|
||||
X.utils.book_append_sheet(book, sheet, "sheet1");
|
||||
var data = X.write(book, {type: TYPE, bookType: "dbf", codepage:r[0]});
|
||||
var wb = X.read(data, {type: TYPE});
|
||||
assert.equal(wb.Sheets.Sheet1.B2.v, r[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
var JSDOM = null;
|
||||
// $FlowIgnore
|
||||
|
79
types/index.d.ts
vendored
79
types/index.d.ts
vendored
@ -144,7 +144,15 @@ export interface ParsingOptions extends CommonOptions {
|
||||
/** Input data encoding */
|
||||
type?: 'base64' | 'binary' | 'buffer' | 'file' | 'array' | 'string';
|
||||
|
||||
/** Default codepage */
|
||||
/**
|
||||
* Default codepage for legacy files
|
||||
*
|
||||
* This requires encoding support to be loaded. It is automatically loaded
|
||||
* in `xlsx.full.min.js` and in CommonJS / Extendscript, but an extra step
|
||||
* is required in React / Angular / Webpack ESM deployments.
|
||||
*
|
||||
* Check the relevant guide https://docs.sheetjs.com/docs/getting-started/
|
||||
*/
|
||||
codepage?: number;
|
||||
|
||||
/**
|
||||
@ -213,6 +221,9 @@ export interface ParsingOptions extends CommonOptions {
|
||||
/** If true, plaintext parsing will not parse values */
|
||||
raw?: boolean;
|
||||
|
||||
/** If true, ignore "dimensions" records and guess range using every cell */
|
||||
nodim?: boolean;
|
||||
|
||||
/** If true, preserve _xlfn. prefixes in formula function names */
|
||||
xlfn?: boolean;
|
||||
|
||||
@ -261,6 +272,17 @@ export interface WritingOptions extends CommonOptions, SheetOption {
|
||||
/** Override workbook properties on save */
|
||||
Props?: Properties;
|
||||
|
||||
/**
|
||||
* Desired codepage for legacy file formats
|
||||
*
|
||||
* This requires encoding support to be loaded. It is automatically loaded
|
||||
* in `xlsx.full.min.js` and in CommonJS / Extendscript, but an extra step
|
||||
* is required in React / Angular / Webpack / ESM deployments.
|
||||
*
|
||||
* Check the relevant guide https://docs.sheetjs.com/docs/getting-started/
|
||||
*/
|
||||
codepage?: number;
|
||||
|
||||
/** Base64 encoding of NUMBERS base for exports */
|
||||
numbers?: string;
|
||||
}
|
||||
@ -517,20 +539,52 @@ export type SheetKeys = string | MarginInfo | SheetType;
|
||||
/** General object representing a Sheet (worksheet or chartsheet) */
|
||||
export interface Sheet {
|
||||
/**
|
||||
* Indexing with a cell address string maps to a cell object
|
||||
* Sparse-mode store cells with keys corresponding to A1-style address
|
||||
* Dense-mode store cells in the '!data' key
|
||||
* Special keys start with '!'
|
||||
*/
|
||||
[cell: string]: CellObject | SheetKeys | any;
|
||||
[cell: string]: CellObject | CellObject[][] | SheetKeys | any;
|
||||
|
||||
/**
|
||||
* Dense-mode worksheets store data in an array of arrays
|
||||
*
|
||||
* Cells are accessed with sheet['!data'][R][C] (where R and C are 0-indexed)
|
||||
*/
|
||||
'!data'?: CellObject[][];
|
||||
|
||||
/** Sheet type */
|
||||
'!type'?: SheetType;
|
||||
|
||||
/** Sheet Range */
|
||||
/** Sheet Range (A1-style) */
|
||||
'!ref'?: string;
|
||||
|
||||
/** Page Margins */
|
||||
'!margins'?: MarginInfo;
|
||||
}
|
||||
/** General object representing a dense Sheet (worksheet or chartsheet) */
|
||||
export interface DenseSheet extends Sheet {
|
||||
/**
|
||||
* Special keys start with '!'
|
||||
* Dense-mode worksheets store data in the '!data' key
|
||||
*/
|
||||
[cell: string]: CellObject[][] | SheetKeys | any;
|
||||
|
||||
/**
|
||||
* Dense-mode worksheets store data in an array of arrays
|
||||
*
|
||||
* Cells are accessed with sheet['!data'][R][C] (where R and C are 0-indexed)
|
||||
*/
|
||||
'!data': CellObject[][];
|
||||
}
|
||||
/** General object representing a sparse Sheet (worksheet or chartsheet) */
|
||||
export interface SparseSheet extends Sheet {
|
||||
/**
|
||||
* Sparse-mode store cells with keys corresponding to A1-style address
|
||||
* Cells are accessed with sheet[addr]
|
||||
*/
|
||||
'!data': never;
|
||||
}
|
||||
|
||||
|
||||
/** AutoFilter properties */
|
||||
export interface AutoFilterInfo {
|
||||
@ -563,6 +617,15 @@ export interface WorkSheet extends Sheet {
|
||||
/** AutoFilter info */
|
||||
'!autofilter'?: AutoFilterInfo;
|
||||
}
|
||||
/** Dense Worksheet Object */
|
||||
export interface DenseWorkSheet extends DenseSheet {
|
||||
/**
|
||||
* Dense-mode worksheets store data in an array of arrays
|
||||
*
|
||||
* Cells are accessed with sheet['!data'][R][C] (where R and C are 0-indexed)
|
||||
*/
|
||||
'!data': CellObject[][];
|
||||
}
|
||||
|
||||
/**
|
||||
* Worksheet Object with CellObject type
|
||||
@ -740,7 +803,7 @@ export interface AOA2SheetOpts extends CommonOptions, DateNFOption {
|
||||
|
||||
export interface SheetAOAOpts extends AOA2SheetOpts, OriginOption {}
|
||||
|
||||
export interface JSON2SheetOpts extends CommonOptions, DateNFOption {
|
||||
export interface JSON2SheetOpts extends CommonOptions, DateNFOption, OriginOption {
|
||||
/** Use specified column order */
|
||||
header?: string[];
|
||||
|
||||
@ -748,8 +811,6 @@ export interface JSON2SheetOpts extends CommonOptions, DateNFOption {
|
||||
skipHeader?: boolean;
|
||||
}
|
||||
|
||||
export interface SheetJSONOpts extends JSON2SheetOpts, OriginOption {}
|
||||
|
||||
export interface Table2SheetOpts extends CommonOptions, DateNFOption, OriginOption, SheetOption {
|
||||
/** If true, plaintext parsing will not parse values */
|
||||
raw?: boolean;
|
||||
@ -870,8 +931,8 @@ export interface XLSX$Utils {
|
||||
sheet_add_aoa(ws: WorkSheet, data: any[][], opts?: SheetAOAOpts): WorkSheet;
|
||||
|
||||
/** Add an array of JS objects to a worksheet */
|
||||
sheet_add_json(ws: WorkSheet, data: any[], opts?: SheetJSONOpts): WorkSheet;
|
||||
sheet_add_json<T>(ws: WorkSheet, data: T[], opts?: SheetJSONOpts): WorkSheet;
|
||||
sheet_add_json(ws: WorkSheet, data: any[], opts?: JSON2SheetOpts): WorkSheet;
|
||||
sheet_add_json<T>(ws: WorkSheet, data: T[], opts?: JSON2SheetOpts): WorkSheet;
|
||||
|
||||
|
||||
consts: XLSX$Consts;
|
||||
|
2093
xlsx.flow.js
2093
xlsx.flow.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
449
xlsx.mini.js
449
xlsx.mini.js
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user