forked from sheetjs/sheetjs
Compare commits
32 Commits
sankhavara
...
master
Author | SHA1 | Date | |
---|---|---|---|
5b33acfaf4 | |||
b68eaed726 | |||
333e4e40f9 | |||
af8e3d9171 | |||
|
dca90c8024 | ||
c06a32043f | |||
ffbea71bc2 | |||
16dd8a6eae | |||
0577bb7a45 | |||
b150dea21d | |||
e9cf1ad0fb | |||
5141222c24 | |||
51a8619000 | |||
e7e129e417 | |||
df48489211 | |||
050f66ce1b | |||
2f329b64e2 | |||
515d1c6f2e | |||
654d6f98c3 | |||
4ae4f0fad9 | |||
|
1ca49a50bd | ||
81b231d866 | |||
1491302aa4 | |||
bd5878e7c7 | |||
|
4dd092a076 | ||
|
04dc18e742 | ||
6a5be04e3d | |||
e90a61bf09 | |||
26cbfe37be | |||
df0e7b5f25 | |||
6c9010f9d1 | |||
0a6ddcaf44 |
@ -11,6 +11,7 @@
|
||||
"comma-dangle": [ 2, "never" ],
|
||||
"curly": 0,
|
||||
"no-bitwise": 0,
|
||||
"no-cond-assign": 1,
|
||||
"no-console": 0,
|
||||
"no-control-regex": 0,
|
||||
"no-unused-vars": 1,
|
||||
|
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
.gitignore
vendored
1
.gitignore
vendored
@ -14,6 +14,7 @@ tmp
|
||||
*.[pP][mM][dD]*
|
||||
*.[pP][dD][fF]
|
||||
*.[sS][lL][kK]
|
||||
*.[sS][yY][lL][kK]
|
||||
*.socialcalc
|
||||
*.[xX][lL][sSwWcCaAtTmMrR]
|
||||
*.[xX][lL][sSaAtT][xXmMbB]
|
||||
|
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
|
||||
|
40
CHANGELOG.md
40
CHANGELOG.md
@ -4,6 +4,44 @@ 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.
|
||||
|
||||
* Export `NaN` values to `#NUM!` and infinite values to `#DIV/0!`
|
||||
|
||||
## v0.19.3
|
||||
|
||||
* XLSX Ensure comment address is valid (h/t @slonser)
|
||||
* Enforce Excel worksheet name restrictions
|
||||
* Fixed "Prototype Pollution" vulnerability (CVE-2023-30533)
|
||||
|
||||
## 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
|
||||
@ -21,7 +59,7 @@ changes may not be included if they are not expected to break existing code.
|
||||
## v0.18.8
|
||||
|
||||
* Plaintext parsing of dateless meridien time values (`1:23:45 PM`)
|
||||
* Legacy format (SYLK / WK# / Multiplan) minutiae
|
||||
* Legacy format (SYLK / WK# / Multiplan) minutiae
|
||||
|
||||
## v0.18.7
|
||||
|
||||
|
7
Makefile
7
Makefile
@ -113,6 +113,7 @@ BYTEFILER=dist/xlsx.extendscript.js xlsx.mjs
|
||||
bytes: ## Display minified and gzipped file sizes
|
||||
@for i in $(BYTEFILEC); do npx printj "%-30s %7d %10d" $$i $$(wc -c < $$i) $$(gzip --best --stdout $$i | wc -c); done
|
||||
@for i in $(BYTEFILER); do npx printj "%-30s %7d" $$i $$(wc -c < $$i); done
|
||||
@npx printj "%-30s %10d" "treeshake" "$$(npx esbuild@0.14.14 --bundle misc/import.js | wc -c)"
|
||||
|
||||
|
||||
.PHONY: git
|
||||
@ -148,16 +149,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)
|
||||
|
12
README.md
12
README.md
@ -9,13 +9,7 @@ Edit complex templates with ease; let out your inner Picasso with styling; make
|
||||
custom sheets with images/graphs/PivotTables; evaluate formula expressions and
|
||||
port calculations to web apps; automate common spreadsheet tasks, and much more!
|
||||
|
||||
[![License](https://img.shields.io/github/license/SheetJS/sheetjs)](https://github.com/SheetJS/sheetjs/blob/master/LICENSE)
|
||||
[![Build Status](https://img.shields.io/github/workflow/status/sheetjs/sheetjs/Tests:%20node.js)](https://github.com/SheetJS/sheetjs/actions)
|
||||
[![Snyk Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/SheetJS/sheetjs)](https://snyk.io/test/github/SheetJS/sheetjs)
|
||||
[![npm Downloads](https://img.shields.io/npm/dm/xlsx.svg)](https://cdn.sheetjs.com/)
|
||||
[![GitHub Repo stars](https://img.shields.io/github/stars/SheetJS/sheetjs?style=social)](https://github.com/SheetJS/sheetjs)
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/sheetjs?pixel)](https://github.com/SheetJS/sheetjs)
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/sheetjs?pixel)](https://git.sheetjs.com/SheetJS/sheetjs)
|
||||
|
||||
[![Build Status](https://saucelabs.com/browser-matrix/sheetjs.svg)](https://saucelabs.com/u/sheetjs)
|
||||
|
||||
@ -35,9 +29,9 @@ port calculations to web apps; automate common spreadsheet tasks, and much more!
|
||||
|
||||
- [`test_files`](https://github.com/SheetJS/test_files): Sample spreadsheets
|
||||
|
||||
- [`cfb`](https://github.com/SheetJS/js-cfb): Container (OLE/ZIP) format library
|
||||
- [`cfb`](https://git.sheetjs.com/SheetJS/js-cfb): Container (OLE/ZIP) format library
|
||||
|
||||
- [`codepage`](https://github.com/SheetJS/js-codepage): Legacy text encodings
|
||||
- [`codepage`](https://git.sheetjs.com/SheetJS/js-codepage): Legacy text encodings
|
||||
|
||||
## License
|
||||
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.18.10';
|
||||
XLSX.version = '0.19.3';
|
||||
|
@ -41,6 +41,11 @@ function utf16leread(data/*:string*/)/*:string*/ {
|
||||
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i) + (data.charCodeAt(2*i+1)<<8));
|
||||
return o.join("");
|
||||
}
|
||||
function utf16lereadu(data/*:Uint8Array*/)/*:string*/ {
|
||||
var o/*:Array<string>*/ = [];
|
||||
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data[2*i] + (data[2*i+1]<<8));
|
||||
return o.join("");
|
||||
}
|
||||
function utf16beread(data/*:string*/)/*:string*/ {
|
||||
var o/*:Array<string>*/ = [];
|
||||
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i+1) + (data.charCodeAt(2*i)<<8));
|
||||
|
@ -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;
|
||||
|
@ -73,7 +73,7 @@ function slice_by_16_tables(T) {
|
||||
for(c = 256 + n; c < 4096; c += 256) v = table[c] = (v >>> 8) ^ T[v & 0xFF];
|
||||
}
|
||||
var out = [];
|
||||
for(n = 1; n != 16; ++n) out[n - 1] = typeof Int32Array !== 'undefined' ? table.subarray(n * 256, n * 256 + 256) : table.slice(n * 256, n * 256 + 256);
|
||||
for(n = 1; n != 16; ++n) out[n - 1] = typeof Int32Array !== 'undefined' && typeof table.subarray == "function" ? table.subarray(n * 256, n * 256 + 256) : table.slice(n * 256, n * 256 + 256);
|
||||
return out;
|
||||
}
|
||||
var TT = slice_by_16_tables(T0);
|
||||
@ -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;
|
||||
|
@ -1,62 +1,61 @@
|
||||
/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
|
||||
function parse_manifest(d, opts) {
|
||||
var str = xlml_normalize(d);
|
||||
var Rn;
|
||||
var FEtag;
|
||||
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
|
||||
case 'manifest': break; // 4.2 <manifest:manifest>
|
||||
case 'file-entry': // 4.3 <manifest:file-entry>
|
||||
FEtag = parsexmltag(Rn[0], false);
|
||||
if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet");
|
||||
break;
|
||||
case 'encryption-data': // 4.4 <manifest:encryption-data>
|
||||
case 'algorithm': // 4.5 <manifest:algorithm>
|
||||
case 'start-key-generation': // 4.6 <manifest:start-key-generation>
|
||||
case 'key-derivation': // 4.7 <manifest:key-derivation>
|
||||
throw new Error("Unsupported ODS Encryption");
|
||||
default: if(opts && opts.WTF) throw Rn;
|
||||
}
|
||||
var str = xlml_normalize(d);
|
||||
var Rn;
|
||||
var FEtag;
|
||||
while (Rn = xlmlregex.exec(str))
|
||||
switch (Rn[3]) {
|
||||
case "manifest":
|
||||
break;
|
||||
case "file-entry":
|
||||
FEtag = parsexmltag(Rn[0], false);
|
||||
if (FEtag.path == "/" && FEtag.type !== CT_ODS)
|
||||
throw new Error("This OpenDocument is not a spreadsheet");
|
||||
break;
|
||||
case "encryption-data":
|
||||
case "algorithm":
|
||||
case "start-key-generation":
|
||||
case "key-derivation":
|
||||
throw new Error("Unsupported ODS Encryption");
|
||||
default:
|
||||
if (opts && opts.WTF)
|
||||
throw Rn;
|
||||
}
|
||||
}
|
||||
|
||||
function write_manifest(manifest/*:Array<Array<string> >*/)/*:string*/ {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
|
||||
o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
|
||||
for(var i = 0; i < manifest.length; ++i) o.push(' <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
|
||||
o.push('</manifest:manifest>');
|
||||
return o.join("");
|
||||
function write_manifest(manifest) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
|
||||
o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
|
||||
for (var i = 0; i < manifest.length; ++i)
|
||||
o.push(' <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
|
||||
o.push("</manifest:manifest>");
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
function write_rdf_type(file/*:string*/, res/*:string*/, tag/*:?string*/) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + file + '">\n',
|
||||
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
function write_rdf_type(file, res, tag) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + file + '">\n',
|
||||
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + "#" + res + '"/>\n',
|
||||
" </rdf:Description>\n"
|
||||
].join("");
|
||||
}
|
||||
function write_rdf_has(base/*:string*/, file/*:string*/) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + base + '">\n',
|
||||
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
function write_rdf_has(base, file) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + base + '">\n',
|
||||
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
|
||||
" </rdf:Description>\n"
|
||||
].join("");
|
||||
}
|
||||
function write_rdf(rdf) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
|
||||
for(var i = 0; i != rdf.length; ++i) {
|
||||
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
|
||||
o.push(write_rdf_has("",rdf[i][0]));
|
||||
}
|
||||
o.push(write_rdf_type("","Document", "pkg"));
|
||||
o.push('</rdf:RDF>');
|
||||
return o.join("");
|
||||
var o = [XML_HEADER];
|
||||
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
|
||||
for (var i = 0; i != rdf.length; ++i) {
|
||||
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
|
||||
o.push(write_rdf_has("", rdf[i][0]));
|
||||
}
|
||||
o.push(write_rdf_type("", "Document", "pkg"));
|
||||
o.push("</rdf:RDF>");
|
||||
return o.join("");
|
||||
}
|
||||
/* TODO: pull properties */
|
||||
function write_meta_ods(/*:: wb: Workbook, opts: any*/)/*:string*/ {
|
||||
return '<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
|
||||
function write_meta_ods(wb, opts) {
|
||||
return '<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>SheetJS ' + XLSX.version + "</meta:generator></office:meta></office:document-meta>";
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ function parse_FtArray(blob, length/*::, ot*/) {
|
||||
var ft = blob.read_shift(2);
|
||||
blob.l-=2;
|
||||
try {
|
||||
fts.push(FtTab[ft](blob, tgt - blob.l));
|
||||
fts[ft] = FtTab[ft](blob, tgt - blob.l);
|
||||
} catch(e) { blob.l = tgt; return fts; }
|
||||
}
|
||||
if(blob.l != tgt) blob.l = tgt; //throw new Error("bad Object Ft-sequence");
|
||||
@ -696,9 +696,11 @@ function parse_Lbl(blob, length, opts) {
|
||||
};
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.4.106 TODO: verify filename encoding */
|
||||
/* [MS-XLS] 2.4.106 TODO: legacy record filename encoding */
|
||||
function parse_ExternSheet(blob, length, opts) {
|
||||
if(opts.biff < 8) return parse_BIFF5ExternSheet(blob, length, opts);
|
||||
/* see issue 2907 */
|
||||
if(!(opts.biff > 8) && (length == blob[blob.l] + (blob[blob.l+1] == 0x03 ? 1 : 0) + 1)) return parse_BIFF5ExternSheet(blob, length, opts);
|
||||
var o = [], target = blob.l + length, len = blob.read_shift(opts.biff > 8 ? 4 : 2);
|
||||
while(len-- !== 0) o.push(parse_XTI(blob, opts.biff > 8 ? 12 : 6, opts));
|
||||
// [iSupBook, itabFirst, itabLast];
|
||||
|
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,16 @@
|
||||
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(r.r < 0 || r.c < 0) return;
|
||||
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 +18,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 +36,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;
|
||||
@ -263,7 +264,10 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string
|
||||
var oldt = cell.t, oldv = cell.v;
|
||||
if(cell.t !== "z") switch(cell.t) {
|
||||
case 'b': vv = cell.v ? "1" : "0"; break;
|
||||
case 'n': vv = ''+cell.v; break;
|
||||
case 'n':
|
||||
if(isNaN(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x24]; } // #NUM!
|
||||
else if(!isFinite(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x07]; } // #DIV/0!
|
||||
else vv = ''+cell.v; break;
|
||||
case 'e': vv = BErr[cell.v]; break;
|
||||
case 'd':
|
||||
if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
|
||||
@ -299,7 +303,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 +325,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 +356,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 +490,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 +508,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 +516,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 +624,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));
|
||||
@ -839,6 +842,12 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
|
||||
if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) {
|
||||
if(last_seen) write_record(ba, 0x000D /* BrtShortRk */, write_BrtShortRk(cell, o));
|
||||
else write_record(ba, 0x0002 /* BrtCellRk */, write_BrtCellRk(cell, o));
|
||||
} else if(isNaN(cell.v)) {
|
||||
if(last_seen) write_record(ba, 0x000E /* BrtShortError */, write_BrtShortError({t:"e", v: 0x24}, o)); // #NUM!
|
||||
else write_record(ba, 0x0003 /* BrtCellError */, write_BrtCellError({t:"e", v: 0x24}, o)); // #NUM!
|
||||
} else if(!isFinite(cell.v)) {
|
||||
if(last_seen) write_record(ba, 0x000E /* BrtShortError */, write_BrtShortError({t:"e", v: 0x07}, o)); // #DIV/0!
|
||||
else write_record(ba, 0x0003 /* BrtCellError */, write_BrtCellError({t:"e", v: 0x07}, o)); // #DIV/0!
|
||||
} else {
|
||||
if(last_seen) write_record(ba, 0x0010 /* BrtShortReal */, write_BrtShortReal(cell, o));
|
||||
else write_record(ba, 0x0005 /* BrtCellReal */, write_BrtCellReal(cell, o));
|
||||
@ -862,7 +871,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 +884,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;
|
||||
|
@ -115,14 +115,17 @@ function safe1904(wb/*:Workbook*/)/*:string*/ {
|
||||
|
||||
var badchars = /*#__PURE__*/":][*?\/\\".split("");
|
||||
function check_ws_name(n/*:string*/, safe/*:?boolean*/)/*:boolean*/ {
|
||||
if(n.length > 31) { if(safe) return false; throw new Error("Sheet names cannot exceed 31 chars"); }
|
||||
var _good = true;
|
||||
badchars.forEach(function(c) {
|
||||
if(n.indexOf(c) == -1) return;
|
||||
if(!safe) throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
|
||||
_good = false;
|
||||
});
|
||||
return _good;
|
||||
try {
|
||||
if(n == "") throw new Error("Sheet name cannot be blank");
|
||||
if(n.length > 31) throw new Error("Sheet name cannot exceed 31 chars");
|
||||
if(n.charCodeAt(0) == 0x27 || n.charCodeAt(n.length - 1) == 0x27) throw new Error("Sheet name cannot start or end with apostrophe (')");
|
||||
if(n.toLowerCase() == "history") throw new Error("Sheet name cannot be 'History'");
|
||||
badchars.forEach(function(c) {
|
||||
if(n.indexOf(c) == -1) return;
|
||||
throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
|
||||
});
|
||||
} catch(e) { if(safe) return false; throw e; }
|
||||
return true;
|
||||
}
|
||||
function check_wb_names(N, S, codes) {
|
||||
N.forEach(function(n,i) {
|
||||
|
@ -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*/);
|
||||
}
|
||||
|
@ -62,33 +62,37 @@ function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n
|
||||
var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
|
||||
if((v == (v|0)) && (v >= 0) && (v < 65536))
|
||||
write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v));
|
||||
else if(isNaN(v))
|
||||
write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x24, "e")); // #NUM!
|
||||
else if(!isFinite(v))
|
||||
write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x07, "e")); // #DIV/0!
|
||||
else
|
||||
write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v));
|
||||
return;
|
||||
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 +103,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;
|
||||
@ -183,8 +186,10 @@ function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n
|
||||
else switch(cell.t) {
|
||||
case 'd': case 'n':
|
||||
var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
|
||||
if(isNaN(v)) write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, 0x24, os, opts, "e")); // #NUM!
|
||||
else if(!isFinite(v)) write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, 0x07, os, opts, "e")); // #DIV/0!
|
||||
/* TODO: emit RK as appropriate */
|
||||
write_biff_rec(ba, 0x0203 /* Number */, write_Number(R, C, v, os, opts));
|
||||
else write_biff_rec(ba, 0x0203 /* Number */, write_Number(R, C, v, os, opts));
|
||||
break;
|
||||
case 'b': case 'e':
|
||||
write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, cell.v, os, opts, cell.t));
|
||||
@ -192,9 +197,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 +212,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 +248,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*/);
|
||||
@ -82,7 +83,7 @@ function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HT
|
||||
sp["data-t"] = cell && cell.t || 'z';
|
||||
if(cell.v != null) sp["data-v"] = cell.v;
|
||||
if(cell.z != null) sp["data-z"] = cell.z;
|
||||
if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + cell.l.Target +'">' + w + '</a>';
|
||||
if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + escapehtml(cell.l.Target) +'">' + w + '</a>';
|
||||
}
|
||||
sp.id = (o.id || "sjs") + "-" + coord;
|
||||
oo.push(writextag('td', w, sp));
|
||||
@ -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);
|
||||
@ -596,6 +596,9 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) {
|
||||
var ptp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
|
||||
textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0];
|
||||
} else if(Rn[0].slice(-2) == "/>") {
|
||||
/* TODO: is self-closing 文本串 valid? */
|
||||
textp += "\n";
|
||||
} else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
|
||||
break; // <text:p>
|
||||
case 's': break; // <text:s>
|
||||
|
@ -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);
|
||||
|
||||
|
@ -50,7 +50,13 @@ function read_plaintext_raw(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
|
||||
function read_utf16(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
|
||||
var d = data;
|
||||
if(o.type == 'base64') d = Base64_decode(d);
|
||||
d = typeof $cptable !== "undefined" ? $cptable.utils.decode(1200, d.slice(2), 'str') : utf16leread(d.slice(2));
|
||||
if(typeof ArrayBuffer !== "undefined" && data instanceof ArrayBuffer) d = new Uint8Array(data);
|
||||
d = typeof $cptable !== "undefined" ? $cptable.utils.decode(1200, d.slice(2), 'str') : (
|
||||
(has_buf && Buffer.isBuffer(data)) ? data.slice(2).toString("utf16le") :
|
||||
(typeof Uint8Array !== "undefined" && d instanceof Uint8Array) ? (
|
||||
typeof TextDecoder !== "undefined" ? new TextDecoder("utf-16le").decode(d.slice(2)) : utf16lereadu(d.slice(2))
|
||||
) : utf16leread(d.slice(2))
|
||||
);
|
||||
o.type = "binary";
|
||||
return read_plaintext(d, o);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -10,6 +10,8 @@ XLSX.writeFileAsync = writeFileAsync;
|
||||
XLSX.utils = utils;
|
||||
XLSX.writeXLSX = writeSyncXLSX;
|
||||
XLSX.writeFileXLSX = writeFileSyncXLSX;
|
||||
XLSX.set_fs = set_fs;
|
||||
XLSX.set_cptable = set_cptable;
|
||||
XLSX.SSF = SSF;
|
||||
if(typeof __stream !== "undefined") XLSX.stream = __stream;
|
||||
if(typeof CFB !== "undefined") XLSX.CFB = CFB;
|
||||
|
@ -1,78 +0,0 @@
|
||||
# Demos
|
||||
|
||||
These demos are intended to demonstrate how to load this library in various
|
||||
ecosystems. The library is designed to be used in the web browser and in node
|
||||
contexts, using dynamic feature tests to pull in features when necessary. This
|
||||
works extremely well in common use cases: script tag insertion and node require.
|
||||
|
||||
Systems like webpack try to be clever by performing simple static analysis to
|
||||
pull in code. However, they do not support dynamic type tests, breaking
|
||||
compatibility with traditional scripts. Configuration is required. The demos
|
||||
cover basic configuration steps for various systems and should "just work".
|
||||
|
||||
Mobile app and other larger demos do not include the full build structure. The
|
||||
demos have `Makefile` scripts that show how to reproduce the full projects. The
|
||||
scripts have been tested against iOS and OSX. For Windows platforms, GNU make
|
||||
can be installed with Bash on Windows or with `cygwin`.
|
||||
|
||||
### Included Demos
|
||||
|
||||
**JavaScript APIs**
|
||||
- [`XMLHttpRequest and fetch`](https://docs.sheetjs.com/docs/demos/network)
|
||||
- [`Clipboard Data`](https://docs.sheetjs.com/docs/demos/clipboard)
|
||||
- [`Typed Arrays for Machine Learning`](https://docs.sheetjs.com/docs/demos/ml)
|
||||
- [`LocalStorage and SessionStorage`](https://docs.sheetjs.com/docs/demos/database#localstorage-and-sessionstorage)
|
||||
- [`Web SQL Database`](https://docs.sheetjs.com/docs/demos/database#websql)
|
||||
- [`IndexedDB`](https://docs.sheetjs.com/docs/demos/database#indexeddb)
|
||||
|
||||
**Frameworks**
|
||||
- [`Angular 2+ and Ionic`](https://docs.sheetjs.com/docs/demos/angular)
|
||||
- [`React`](https://docs.sheetjs.com/docs/demos/react)
|
||||
- [`VueJS`](https://docs.sheetjs.com/docs/demos/vue)
|
||||
- [`Angular.JS`](https://docs.sheetjs.com/docs/demos/legacy#angularjs)
|
||||
- [`Knockout`](https://docs.sheetjs.com/docs/demos/legacy#knockoutjs)
|
||||
|
||||
**Front-End UI Components**
|
||||
- [`canvas-datagrid`](https://docs.sheetjs.com/docs/demos/grid#canvas-datagrid)
|
||||
- [`x-spreadsheet`](https://docs.sheetjs.com/docs/demos/grid#x-spreadsheet)
|
||||
- [`react-data-grid`](https://docs.sheetjs.com/docs/demos/grid#react-data-grid)
|
||||
- [`vue3-table-lite`](https://docs.sheetjs.com/docs/demos/grid#vue3-table-lite)
|
||||
- [`angular-ui-grid`](https://docs.sheetjs.com/docs/demos/grid#angular-ui-grid)
|
||||
|
||||
**Platforms and Integrations**
|
||||
- [`Command-Line Tools`](https://docs.sheetjs.com/docs/demos/cli)
|
||||
- [`iOS and Android Mobile Applications`](https://docs.sheetjs.com/docs/demos/mobile)
|
||||
- [`NodeJS Server-Side Processing`](https://docs.sheetjs.com/docs/demos/server#nodejs)
|
||||
- [`Content Management and Static Sites`](https://docs.sheetjs.com/docs/demos/content)
|
||||
- [`Electron`](https://docs.sheetjs.com/docs/demos/desktop#electron)
|
||||
- [`NW.js`](https://docs.sheetjs.com/docs/demos/desktop#nwjs)
|
||||
- [`Tauri`](https://docs.sheetjs.com/docs/demos/desktop#tauri)
|
||||
- [`Chrome and Chromium Extensions`](https://docs.sheetjs.com/docs/demos/chromium)
|
||||
- [`Google Sheets API`](https://docs.sheetjs.com/docs/demos/gsheet)
|
||||
- [`ExtendScript for Adobe Apps`](https://docs.sheetjs.com/docs/demos/extendscript)
|
||||
- [`NetSuite SuiteScript`](https://docs.sheetjs.com/docs/demos/netsuite)
|
||||
- [`SalesForce Lightning Web Components`](https://docs.sheetjs.com/docs/demos/salesforce)
|
||||
- [`Excel JavaScript API`](https://docs.sheetjs.com/docs/demos/excel)
|
||||
- [`Headless Automation`](https://docs.sheetjs.com/docs/demos/headless)
|
||||
- [`Other JavaScript Engines`](https://docs.sheetjs.com/docs/demos/engines)
|
||||
- [`Azure Functions and Storage`](https://docs.sheetjs.com/docs/demos/azure)
|
||||
- [`Amazon Web Services`](https://docs.sheetjs.com/docs/demos/aws)
|
||||
- [`Databases and Structured Data Stores`](https://docs.sheetjs.com/docs/demos/database)
|
||||
- [`NoSQL and Unstructured Data Stores`](https://docs.sheetjs.com/docs/demos/nosql)
|
||||
- [`Legacy Internet Explorer`](https://docs.sheetjs.com/docs/demos/legacy#internet-explorer)
|
||||
|
||||
**Bundlers and Tooling**
|
||||
- [`browserify`](https://docs.sheetjs.com/docs/demos/bundler#browserify)
|
||||
- [`bun`](https://docs.sheetjs.com/docs/demos/bundler#bun)
|
||||
- [`esbuild`](https://docs.sheetjs.com/docs/demos/bundler#esbuild)
|
||||
- [`parcel`](https://docs.sheetjs.com/docs/demos/bundler#parcel)
|
||||
- [`requirejs`](https://docs.sheetjs.com/docs/demos/bundler#requirejs)
|
||||
- [`rollup`](https://docs.sheetjs.com/docs/demos/bundler#rollup)
|
||||
- [`snowpack`](https://docs.sheetjs.com/docs/demos/bundler#snowpack)
|
||||
- [`swc`](https://docs.sheetjs.com/docs/demos/bundler#swc)
|
||||
- [`systemjs`](https://docs.sheetjs.com/docs/demos/bundler#systemjs)
|
||||
- [`vite`](https://docs.sheetjs.com/docs/demos/bundler#vite)
|
||||
- [`webpack`](https://docs.sheetjs.com/docs/demos/bundler#webpack)
|
||||
- [`wmr`](https://docs.sheetjs.com/docs/demos/bundler#wmr)
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,7 +0,0 @@
|
||||
# Other JS Engines and Deployments
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/engines)
|
||||
includes more detailed instructions and more JS engines.
|
||||
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,10 +0,0 @@
|
||||
# AngularJS
|
||||
|
||||
The content has been reorganized;
|
||||
|
||||
- [The "Legacy Frameworks" section](https://docs.sheetjs.com/docs/demos/legacy#angularjs)
|
||||
covers the AngularJS basics.
|
||||
- [The "Angular UI Grid" section](https://docs.sheetjs.com/docs/demos/legacy#angularjs)
|
||||
covers the integration with Angular UI Grid.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,11 +0,0 @@
|
||||
# Angular 2+
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/angular) has an updated
|
||||
exposition for legacy and modern deployments alike.
|
||||
|
||||
The ecosystem demos were grouped by type in the new demo site:
|
||||
|
||||
- [NativeScript](https://docs.sheetjs.com/docs/demos/mobile#nativescript) is now part of "iOS and Android Apps"
|
||||
- [Ionic](https://docs.sheetjs.com/docs/demos/mobile#ionic) is now part of "iOS and Android Apps"
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,6 +0,0 @@
|
||||
# Typed Arrays and Math
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/ml) includes
|
||||
interactive examples as well as strategies for CSV and JS Array interchange.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,6 +0,0 @@
|
||||
# Browserify
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/bundler#browserify)
|
||||
includes a more concise example.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,6 +0,0 @@
|
||||
# Chrome and Chromium
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/chromium)
|
||||
includes more up-to-date details.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,11 +0,0 @@
|
||||
# Databases
|
||||
|
||||
This demo has been split up for clarity:
|
||||
|
||||
- <https://docs.sheetjs.com/docs/demos/database> covers SQL and
|
||||
structured data (including CRUD operations)
|
||||
|
||||
- https://docs.sheetjs.com/docs/demos/nosql covers unstructured
|
||||
data including "NoSQL" data stores.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,7 +0,0 @@
|
||||
# canvas-datagrid
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/grid#canvas-datagrid)
|
||||
includes a live example and improved explanations.
|
||||
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,13 +0,0 @@
|
||||
# Deno
|
||||
|
||||
Deno is a runtime capable of running JS code including this library.
|
||||
|
||||
Demos have been integrated in the [documentation](https://docs.sheetjs.com) :
|
||||
|
||||
- <https://docs.sheetjs.com/docs/installation/deno> installation
|
||||
- <https://docs.sheetjs.com/docs/example> writing JS data to a spreadsheet
|
||||
- <https://docs.sheetjs.com/docs/solutions/input> input strategies
|
||||
- <https://docs.sheetjs.com/docs/solutions/output> output strategies
|
||||
- <https://docs.sheetjs.com/docs/demos/cli#deno> `deno compile`
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,6 +0,0 @@
|
||||
# Electron
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/desktop#electron)
|
||||
includes an improved example and detailed explanations.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,7 +0,0 @@
|
||||
# Adobe ExtendScript
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/extendscript)
|
||||
has a more focused Photoshop example as well as notes about other extensibility
|
||||
frameworks shipping with newer versions of Creative Cloud apps.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,9 +0,0 @@
|
||||
# "Serverless" Functions
|
||||
|
||||
Cloud services are covered in separate demos:
|
||||
|
||||
- [AWS](https://docs.sheetjs.com/docs/demos/aws)
|
||||
- [Azure](https://docs.sheetjs.com/docs/demos/azure)
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
||||
|
@ -1,9 +0,0 @@
|
||||
# Google Sheets API
|
||||
|
||||
The old demo used a deprecated version of the Google Sheets API to export data
|
||||
from Google Sheets Documents.
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/gsheet) uses
|
||||
the new Google Sheets API to read and write data.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,8 +0,0 @@
|
||||
# Headless Browsers
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/headless)
|
||||
has a more focused table export example as well as a demo script for Chromium
|
||||
automation with Puppeteer and multi-browser automation with Playwright.
|
||||
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,7 +0,0 @@
|
||||
# Knockout
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/legacy#knockoutjs)
|
||||
includes a live example and improved explanations.
|
||||
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,8 +0,0 @@
|
||||
# Meteor
|
||||
|
||||
This demo originally covered Meteor's package manager and other nuances. At the
|
||||
time the demo was written, Meteor had its own ecosystem that clashed with the
|
||||
burgeoning NodeJS package ecosystem. Eventually, Meteor added proper support
|
||||
for NodeJS modules. New projects should follow the instructions for packages.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,6 +0,0 @@
|
||||
# NW.js
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/desktop#nwjs)
|
||||
includes an improved example and detailed explanations.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,6 +0,0 @@
|
||||
# Internet Explorer
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/legacy#internet-explorer)
|
||||
includes a live example and easier integration bundle.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,6 +0,0 @@
|
||||
# Parcel
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/bundler#parcel)
|
||||
includes a more concise example.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,12 +0,0 @@
|
||||
# React
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/react) has an updated
|
||||
exposition for legacy and modern deployments alike.
|
||||
|
||||
The ecosystem demos were grouped by type in the new demo site:
|
||||
|
||||
- [server-rendered React components with `next.js`](https://docs.sheetjs.com/docs/demos/content#nextjs) is now part of "Content and Site Generation"
|
||||
- [`react-native` deployment for iOS and android](https://docs.sheetjs.com/docs/demos/mobile#react-native) is now part of "iOS and Android Apps"
|
||||
- [`react-data-grid` reading, modifying, and writing files](https://docs.sheetjs.com/docs/demo/grid#react-data-grid) 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)
|
@ -1,7 +0,0 @@
|
||||
# RequireJS
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/bundler#requirejs)
|
||||
includes a live example and improved explanations.
|
||||
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,7 +0,0 @@
|
||||
# Rollup
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/bundler#rollup)
|
||||
includes a simple example and improved explanations.
|
||||
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,11 +0,0 @@
|
||||
# NodeJS Server Deployments
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/server) has a more focused
|
||||
discussion with examples for popular JS server-side frameworks.
|
||||
|
||||
Cloud services are covered in separate demos:
|
||||
|
||||
- [AWS](https://docs.sheetjs.com/docs/demos/aws)
|
||||
- [Azure](https://docs.sheetjs.com/docs/demos/azure)
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,6 +0,0 @@
|
||||
# SystemJS Demos
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/bundler#systemjs)
|
||||
includes a live example and improved explanations.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,9 +0,0 @@
|
||||
# TypeScript
|
||||
|
||||
This demo originally covered direct use of the `tsc` TypeScript compiler. At
|
||||
the time when the demo was first written, TypeScript 2.2 had a module system
|
||||
that was incompatible with the pure JS ecosystem. Since then, various
|
||||
language improvements and compiler changes have obviated this demo. Uses of
|
||||
TypeScript are scattered throughout other demos.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,12 +0,0 @@
|
||||
# VueJS
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/vue) has an updated
|
||||
exposition for legacy and modern deployments alike.
|
||||
|
||||
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"
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,6 +0,0 @@
|
||||
# Webpack
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/bundler#webpack)
|
||||
reflects the new default behavior to use the ESM build.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,7 +0,0 @@
|
||||
# XMLHttpRequest and fetch
|
||||
|
||||
[The new demo](https://docs.sheetjs.com/docs/demos/network)
|
||||
includes interactive demos and improved explanations.
|
||||
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,18 +0,0 @@
|
||||
# x-spreadsheet
|
||||
|
||||
The `sheet_to_json` utility function generates output arrays suitable for use
|
||||
with other JS libraries such as data grids for previewing data. With a familiar
|
||||
UI, [`x-spreadsheet`](https://myliang.github.io/x-spreadsheet/) is an excellent
|
||||
choice for developers looking for a modern editor.
|
||||
|
||||
[The new docs](https://docs.sheetjs.com/docs/demos/grid/#x-spreadsheet)
|
||||
include more detail and examples.
|
||||
|
||||
The original demo is available at <https://docs.sheetjs.com/xspreadsheet/>
|
||||
|
||||
A hosted version of the `xlsxspread.js` script is available on the SheetJS CDN:
|
||||
|
||||
- <https://cdn.sheetjs.com/xspreadsheet/xlsxspread.js> original script
|
||||
- <https://cdn.sheetjs.com/xspreadsheet/xlsxspread.min.js> minified
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
@ -1,133 +0,0 @@
|
||||
/*! xlsxspread.js (C) SheetJS LLC -- https://sheetjs.com/ */
|
||||
/* eslint-env browser */
|
||||
/*global XLSX */
|
||||
/*exported stox, xtos */
|
||||
console.log("The latest version of the xlsxspread.js script is at https://cdn.sheetjs.com/xspreadsheet/xlsxspread.js !")
|
||||
|
||||
/**
|
||||
* Converts data from SheetJS to x-spreadsheet
|
||||
*
|
||||
* @param {Object} wb SheetJS workbook object
|
||||
*
|
||||
* @returns {Object[]} An x-spreadsheet data
|
||||
*/
|
||||
function stox(wb) {
|
||||
var out = [];
|
||||
wb.SheetNames.forEach(function (name) {
|
||||
var o = { name: name, rows: {} };
|
||||
var ws = wb.Sheets[name];
|
||||
if(!ws || !ws["!ref"]) return;
|
||||
var range = XLSX.utils.decode_range(ws['!ref']);
|
||||
// sheet_to_json will lost empty row and col at begin as default
|
||||
range.s = { r: 0, c: 0 };
|
||||
var aoa = XLSX.utils.sheet_to_json(ws, {
|
||||
raw: false,
|
||||
header: 1,
|
||||
range: range
|
||||
});
|
||||
|
||||
aoa.forEach(function (r, i) {
|
||||
var cells = {};
|
||||
r.forEach(function (c, j) {
|
||||
cells[j] = { text: c };
|
||||
|
||||
var cellRef = XLSX.utils.encode_cell({ r: i, c: j });
|
||||
|
||||
if ( ws[cellRef] != null && ws[cellRef].f != null) {
|
||||
cells[j].text = "=" + ws[cellRef].f;
|
||||
}
|
||||
});
|
||||
o.rows[i] = { cells: cells };
|
||||
});
|
||||
|
||||
o.merges = [];
|
||||
(ws["!merges"]||[]).forEach(function (merge, i) {
|
||||
//Needed to support merged cells with empty content
|
||||
if (o.rows[merge.s.r] == null) {
|
||||
o.rows[merge.s.r] = { cells: {} };
|
||||
}
|
||||
if (o.rows[merge.s.r].cells[merge.s.c] == null) {
|
||||
o.rows[merge.s.r].cells[merge.s.c] = {};
|
||||
}
|
||||
|
||||
o.rows[merge.s.r].cells[merge.s.c].merge = [
|
||||
merge.e.r - merge.s.r,
|
||||
merge.e.c - merge.s.c
|
||||
];
|
||||
|
||||
o.merges[i] = XLSX.utils.encode_range(merge);
|
||||
});
|
||||
|
||||
out.push(o);
|
||||
});
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts data from x-spreadsheet to SheetJS
|
||||
*
|
||||
* @param {Object[]} sdata An x-spreadsheet data object
|
||||
*
|
||||
* @returns {Object} A SheetJS workbook object
|
||||
*/
|
||||
function xtos(sdata) {
|
||||
var out = XLSX.utils.book_new();
|
||||
sdata.forEach(function (xws) {
|
||||
var ws = {};
|
||||
var rowobj = xws.rows;
|
||||
var minCoord = { r: 0, c: 0 }, maxCoord = { r: 0, c: 0 };
|
||||
for (var ri = 0; ri < rowobj.len; ++ri) {
|
||||
var row = rowobj[ri];
|
||||
if (!row) continue;
|
||||
|
||||
Object.keys(row.cells).forEach(function (k) {
|
||||
var idx = +k;
|
||||
if (isNaN(idx)) return;
|
||||
|
||||
var lastRef = XLSX.utils.encode_cell({ r: ri, c: idx });
|
||||
if (ri > maxCoord.r) maxCoord.r = ri;
|
||||
if (idx > maxCoord.c) maxCoord.c = idx;
|
||||
|
||||
var cellText = row.cells[k].text, type = "s";
|
||||
if (!cellText) {
|
||||
cellText = "";
|
||||
type = "z";
|
||||
} else if (!isNaN(Number(cellText))) {
|
||||
cellText = Number(cellText);
|
||||
type = "n";
|
||||
} else if (cellText.toLowerCase() === "true" || cellText.toLowerCase() === "false") {
|
||||
cellText = Boolean(cellText);
|
||||
type = "b";
|
||||
}
|
||||
|
||||
ws[lastRef] = { v: cellText, t: type };
|
||||
|
||||
if (type == "s" && cellText[0] == "=") {
|
||||
ws[lastRef].f = cellText.slice(1);
|
||||
}
|
||||
|
||||
if (row.cells[k].merge != null) {
|
||||
if (ws["!merges"] == null) ws["!merges"] = [];
|
||||
|
||||
ws["!merges"].push({
|
||||
s: { r: ri, c: idx },
|
||||
e: {
|
||||
r: ri + row.cells[k].merge[0],
|
||||
c: idx + row.cells[k].merge[1]
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
ws["!ref"] = minCoord ? XLSX.utils.encode_range({
|
||||
s: minCoord,
|
||||
e: maxCoord
|
||||
}) : "A1";
|
||||
|
||||
XLSX.utils.book_append_sheet(out, ws, xws.name);
|
||||
});
|
||||
|
||||
return out;
|
||||
}
|
||||
|
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
2268
dist/xlsx.extendscript.js
generated
vendored
2268
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 |
1
misc/import.js
Normal file
1
misc/import.js
Normal file
@ -0,0 +1 @@
|
||||
export { version } from "../";
|
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
|
||||
|
61
modules/32_odmanrdf.js
Normal file
61
modules/32_odmanrdf.js
Normal file
@ -0,0 +1,61 @@
|
||||
var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
|
||||
function parse_manifest(d, opts) {
|
||||
var str = xlml_normalize(d);
|
||||
var Rn;
|
||||
var FEtag;
|
||||
while (Rn = xlmlregex.exec(str))
|
||||
switch (Rn[3]) {
|
||||
case "manifest":
|
||||
break;
|
||||
case "file-entry":
|
||||
FEtag = parsexmltag(Rn[0], false);
|
||||
if (FEtag.path == "/" && FEtag.type !== CT_ODS)
|
||||
throw new Error("This OpenDocument is not a spreadsheet");
|
||||
break;
|
||||
case "encryption-data":
|
||||
case "algorithm":
|
||||
case "start-key-generation":
|
||||
case "key-derivation":
|
||||
throw new Error("Unsupported ODS Encryption");
|
||||
default:
|
||||
if (opts && opts.WTF)
|
||||
throw Rn;
|
||||
}
|
||||
}
|
||||
function write_manifest(manifest) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
|
||||
o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
|
||||
for (var i = 0; i < manifest.length; ++i)
|
||||
o.push(' <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
|
||||
o.push("</manifest:manifest>");
|
||||
return o.join("");
|
||||
}
|
||||
function write_rdf_type(file, res, tag) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + file + '">\n',
|
||||
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + "#" + res + '"/>\n',
|
||||
" </rdf:Description>\n"
|
||||
].join("");
|
||||
}
|
||||
function write_rdf_has(base, file) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + base + '">\n',
|
||||
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
|
||||
" </rdf:Description>\n"
|
||||
].join("");
|
||||
}
|
||||
function write_rdf(rdf) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
|
||||
for (var i = 0; i != rdf.length; ++i) {
|
||||
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
|
||||
o.push(write_rdf_has("", rdf[i][0]));
|
||||
}
|
||||
o.push(write_rdf_type("", "Document", "pkg"));
|
||||
o.push("</rdf:RDF>");
|
||||
return o.join("");
|
||||
}
|
||||
function write_meta_ods(wb, opts) {
|
||||
return '<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>SheetJS ' + XLSX.version + "</meta:generator></office:meta></office:document-meta>";
|
||||
}
|
73
modules/32_odmanrdf.ts
Normal file
73
modules/32_odmanrdf.ts
Normal file
@ -0,0 +1,73 @@
|
||||
/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
|
||||
|
||||
import { WorkBook, ParsingOptions } from '../';
|
||||
import * as _XLSX from '../';
|
||||
declare var XLSX: typeof _XLSX;
|
||||
|
||||
type RawData = any;
|
||||
declare var XML_HEADER: string;
|
||||
declare var xlmlregex: RegExp;
|
||||
declare function parsexmltag(tag: string, skip_root?: boolean, skip_LC?: boolean): any;
|
||||
declare function xlml_normalize(d: RawData): string;
|
||||
type RDF = [string, string][];
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
|
||||
function parse_manifest(d: RawData, opts?: ParsingOptions) {
|
||||
var str = xlml_normalize(d);
|
||||
var Rn: RegExpExecArray | null;
|
||||
var FEtag;
|
||||
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
|
||||
case 'manifest': break; // 4.2 <manifest:manifest>
|
||||
case 'file-entry': // 4.3 <manifest:file-entry>
|
||||
FEtag = parsexmltag(Rn[0], false);
|
||||
if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet");
|
||||
break;
|
||||
case 'encryption-data': // 4.4 <manifest:encryption-data>
|
||||
case 'algorithm': // 4.5 <manifest:algorithm>
|
||||
case 'start-key-generation': // 4.6 <manifest:start-key-generation>
|
||||
case 'key-derivation': // 4.7 <manifest:key-derivation>
|
||||
throw new Error("Unsupported ODS Encryption");
|
||||
default: if(opts && opts.WTF) throw Rn;
|
||||
}
|
||||
}
|
||||
|
||||
function write_manifest(manifest: RDF): string {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
|
||||
o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
|
||||
for(var i = 0; i < manifest.length; ++i) o.push(' <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
|
||||
o.push('</manifest:manifest>');
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
function write_rdf_type(file: string, res: string, tag?: string): string {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + file + '">\n',
|
||||
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf_has(base: string, file: string): string {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + base + '">\n',
|
||||
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf(rdf: RDF): string {
|
||||
var o: string[] = [XML_HEADER];
|
||||
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
|
||||
for(var i = 0; i != rdf.length; ++i) {
|
||||
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
|
||||
o.push(write_rdf_has("",rdf[i][0]));
|
||||
}
|
||||
o.push(write_rdf_type("","Document", "pkg"));
|
||||
o.push('</rdf:RDF>');
|
||||
return o.join("");
|
||||
}
|
||||
/* TODO: pull properties */
|
||||
function write_meta_ods(wb?: WorkBook, opts?: any): string {
|
||||
return '<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
|
||||
}
|
@ -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,5 +1,6 @@
|
||||
import { WorkBook, WorkSheet, Range, CellObject } from '../';
|
||||
import { WorkBook, WorkSheet, Range, CellObject, DenseSheet, SparseSheet, ParsingOptions, WritingOptions } from '../';
|
||||
import type { utils } from "../";
|
||||
type RawData = any;
|
||||
|
||||
declare var encode_cell: typeof utils.encode_cell;
|
||||
declare var encode_range: typeof utils.encode_range;
|
||||
@ -12,7 +13,7 @@ declare var has_buf: boolean;
|
||||
declare function Base64_decode(s: string): string;
|
||||
declare function fuzzynum(s: string): number;
|
||||
|
||||
function rtf_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
|
||||
function rtf_to_sheet(d: RawData, opts: ParsingOptions): WorkSheet {
|
||||
switch(opts.type) {
|
||||
case 'base64': return rtf_to_sheet_str(Base64_decode(d), opts);
|
||||
case 'binary': return rtf_to_sheet_str(d, opts);
|
||||
@ -23,16 +24,19 @@ function rtf_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
|
||||
}
|
||||
|
||||
/* TODO: this is a stub */
|
||||
function rtf_to_sheet_str(str: string, opts)/*:Worksheet*/ {
|
||||
function rtf_to_sheet_str(str: string, opts: ParsingOptions): 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 +55,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;
|
||||
@ -68,25 +72,26 @@ function rtf_to_sheet_str(str: string, opts)/*:Worksheet*/ {
|
||||
return ws;
|
||||
}
|
||||
|
||||
function rtf_to_workbook(d/*:RawData*/, opts): WorkBook {
|
||||
function rtf_to_workbook(d: RawData, opts: ParsingOptions): WorkBook {
|
||||
var wb: WorkBook = sheet_to_workbook(rtf_to_sheet(d, opts), opts);
|
||||
wb.bookType = "rtf";
|
||||
return wb;
|
||||
}
|
||||
|
||||
/* TODO: this is a stub */
|
||||
function sheet_to_rtf(ws: WorkSheet, opts): string {
|
||||
function sheet_to_rtf(ws: WorkSheet, opts: WritingOptions): 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 +100,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,32 @@ 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
|
||||
BAREJS=04_base64.js 32_odmanrdf.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: lint
|
||||
lint: $(filter-out $(wildcard *.node.ts),$(TSFILES))
|
||||
tsc --strict --noEmit $^
|
||||
|
||||
.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,13 +2,13 @@
|
||||
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"
|
||||
if [ -e "$OUTF" ]; then chmod a+w "$OUTF"; fi
|
||||
cp "$INF" "$OUTF"
|
||||
chmod a-w "$OUTF"
|
||||
sleep 0.1
|
||||
# open "$OUTF"
|
||||
unzip -l "$OUTF"
|
||||
base64 "$OUTF" | tr -d '\n' > xlsx.zahl.js
|
||||
(base64 "$OUTF" || base64 -i "$OUTF") | tr -d '\n' > xlsx.zahl.js
|
||||
sed -i.bak 's/^/var XLSX_ZAHL_PAYLOAD = "/g;s/$/";\n/g' xlsx.zahl.js
|
||||
cp xlsx.zahl.js xlsx.zahl.mjs
|
||||
cat >> xlsx.zahl.js <<EOF
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user