Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

124 changed files with 14912 additions and 25956 deletions

6
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View 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.

4
.gitignore vendored
View File

@ -23,16 +23,14 @@ tmp
*.[xX][mM][lL]
*.[xX][lL][mM][lL]
*.[uU][oO][sS]
*.[wW][kKqQbB][sS1234567890]
*.[wW][kKqQbB][S1234567890]
*.[qQ][pP][wW]
*.[fF][mM][3tT]
*.[bB][iI][fF][fF][23458]
*.[rR][tT][fF]
*.[eE][tT]
*.[eE][tT][hH]
*.[nN][uU][mM][bB][eE][rR][sS]
*.[mM][oO][dD]
*.[dD][tT][aA]
*.123
*.htm
*.html

View File

@ -11,7 +11,6 @@ node_modules
*.jsx
_book
book.json
v8.log
tmp
*.[tT][xX][tT]
*.[cC][sS][vV]
@ -20,7 +19,6 @@ tmp
*.[pP][mM][dD]*
*.[pP][dD][fF]
*.[sS][lL][kK]
*.[sS][yY][lL][kK]
*.socialcalc
*.[xX][lL][sSwWcCaAtTmMrR]
*.[xX][lL][sSaAtT][xXmMbB]
@ -34,7 +32,6 @@ tmp
*.[fF][mM][3tT]
*.[bB][iI][fF][fF][23458]
*.[rR][tT][fF]
*.[eE][tT]
*.[eE][tT][hH]
*.[nN][uU][mM][bB][eE][rR][sS]
*.[mM][oO][dD]

View File

@ -4,28 +4,6 @@ This log is intended to keep track of backwards-incompatible changes, including
but not limited to API changes and file location changes. Minor behavioral
changes may not be included if they are not expected to break existing code.
## v0.20.2
* Reworked parsing methods to avoid slow regexes (CVE-2024-22363)
* HTML properly encode data-v attribute
* SYLK read and write error cells
## v0.20.1
* `init` use packaged test files to work around GitHub breaking changes
* SSF date code rounding to 15 decimal digits (h/t @davidtamaki)
* `sheet_to_json` force UTC interpretation for formatted strings (h/t @Blanay)
* QPW extract result of string formula
* XLSX parse non-compliant merge cell expressions
* NUMBERS correctly handle rows omitted from official exports
* DBF parse empty logical field (h/t @Roman91)
* `dense` option added to types
* package.json add mini and core scripts to export map (h/t @stof)
## v0.20.0
* Use UTC interpretation of Date objects for date cells (potentially breaking)
* API functions support UTC and local time value interpretations
* Export `NaN` values to `#NUM!` and infinite values to `#DIV/0!`
## v0.19.3

View File

@ -4,17 +4,17 @@ The SheetJS Libraries should be free and clear to use in your projects. In
order to maintain that, every contributor must be vigilant.
There have been many projects in the past that have been very lax regarding
licensing. We are of the opinion that those are ticking timebombs and that no
commercial product should depend on them.
licensing, and we are of the opinion that those are ticking timebombs and that
no commercial product should depend on them.
# Required Reading
These are pretty short reads and emphasize the importance of proper licensing:
- https://github.com/jazzband/tablib/issues/114 (discussion of other tools)
- https://github.com/kennethreitz/tablib/issues/114 (discussion of other tools)
- https://web.archive.org/web/20120615223756/http://www.codinghorror.com/blog/2007/04/pick-a-license-any-license.html
- http://www.codinghorror.com/blog/2007/04/pick-a-license-any-license.html
# Raising Issues
@ -30,9 +30,10 @@ inbox is self-hosted.
# Opening Pull Requests
[Squash commits](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History)
before opening a pull request, If the pull request addresses documentation or
demos, add `[ci skip]` in the body or title of the commit message to skip tests.
Before opening a pull request, [squash all commits into
one](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History). If the pull
request addresses documentation or demos, add `[ci skip]` in the body or title
of your commit message to skip Travis checks.
# Pre-Contribution Checklist
@ -56,8 +57,8 @@ issue. If it is a particularly high-priority issue, please drop an email to
Keep these in mind as you work:
- Your contributions are your original work. Take note of any resources you
consult in the process. Be extra careful not to use unlicensed code on the
Internet or code generated by a large language model or other AI tool.
consult in the process (and be extra careful not to use unlicensed code on
the internet.
- You are working on your own time. Unless they explicitly grant permission,
your employer may be the ultimate owner of your IP

View File

@ -67,9 +67,10 @@ clean-data:
.PHONY: init
init: ## Initial setup for development
rm -rf test_files
if [ ! -e test_files.zip ]; then curl -LO https://test-files.sheetjs.com/test_files.zip; fi
unzip test_files.zip
git submodule init
git submodule update
#git submodule foreach git pull origin master
git submodule foreach make all
mkdir -p tmp
DISTHDR=misc/suppress_export.js
@ -106,13 +107,13 @@ dist-deps: ## Copy dependencies for distribution
.PHONY: aux
aux: $(AUXTARGETS)
BYTEFILEC=dist/xlsx.{full,core,mini}.min.js xlsx.mjs
BYTEFILER=dist/xlsx.extendscript.js
BYTEFILEC=dist/xlsx.{full,core,mini}.min.js
BYTEFILER=dist/xlsx.extendscript.js xlsx.mjs
.PHONY: bytes
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 -y esbuild@0.14.14 --bundle misc/import.js | wc -c)"
@npx printj "%-30s %10d" "treeshake" "$$(npx esbuild@0.14.14 --bundle misc/import.js | wc -c)"
.PHONY: git
@ -140,10 +141,6 @@ test mocha: test.js ## Run test suite
#* To run tests for one format, make test_<fmt>
#* To run the core test suite, make test_misc
.PHONY: testdot
testdot: test.js ## Run test suite using dot reporter
mocha -R dot -t 30000
.PHONY: test-esm
test-esm: test.mjs ## Run Node ESM test suite
npx -y mocha@9 -R spec -t 30000 $<
@ -168,11 +165,6 @@ TESTFMT=$(patsubst %,test_%,$(FMT))
$(TESTFMT): test_%:
FMTS=$* make test
TESTFMT=$(patsubst %,testdot_%,$(FMT))
.PHONY: $(TESTFMT)
$(TESTFMT): testdot_%:
FMTS=$* make testdot
TESTESMFMT=$(patsubst %,test-esm_%,$(FMT))
.PHONY: $(TESTESMFMT)
$(TESTESMFMT): test-esm_%:
@ -254,7 +246,8 @@ misc/coverage.html: $(TARGET) test.js
coveralls: ## Coverage Test + Send to coveralls.io
mocha --require blanket --reporter mocha-lcov-reporter -t 30000 | node ./node_modules/coveralls/bin/coveralls.js
MDLINT=README.md
DEMOMDS=$(sort $(wildcard demos/*/README.md))
MDLINT=$(DEMOMDS) README.md demos/README.md
.PHONY: mdlint
mdlint: $(MDLINT) ## Check markdown documents
./node_modules/.bin/alex $^

View File

@ -9,30 +9,29 @@ 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!
[![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)
## Documentation
- [API and Usage Documentation](https://docs.sheetjs.com)
- [Downloadable Scripts and Modules](https://cdn.sheetjs.com)
## Constellation
## Related Projects
- <https://oss.sheetjs.com/notes/>: File Format Notes
- [`ssf`](packages/ssf): Format data using ECMA-376 spreadsheet format codes
- [`xlsx-cli`](packages/xlsx-cli): NodeJS command-line tool for processing files
- [`xlsx-cli`](packages/xlsx-cli/): NodeJS command-line tool for processing files
- [`cfb`](https://git.sheetjs.com/SheetJS/js-cfb): Container (OLE/ZIP) file
processing library
- [`test_files`](https://github.com/SheetJS/test_files): Sample spreadsheets
- [`codepage`](https://git.sheetjs.com/SheetJS/js-codepage): Legacy text
encodings for XLS and other legacy spreadsheet formats
- [`cfb`](https://git.sheetjs.com/SheetJS/js-cfb): Container (OLE/ZIP) format library
- [`dta`](packages/dta): Stata DTA file processor
- [`test_files`](https://github.com/sheetjs/test_files): Test files and various
plaintext baselines.
- [`codepage`](https://git.sheetjs.com/SheetJS/js-codepage): Legacy text encodings
## License

View File

@ -1,6 +1,6 @@
/*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*exported XLSX */
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false, Set:false, Float32Array:false */
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */
var XLSX = {};
function make_xlsx_lib(XLSX){

View File

@ -1 +1 @@
XLSX.version = '0.20.2';
XLSX.version = '0.19.3';

View File

@ -6,26 +6,26 @@ var $cptable;
var VALID_ANSI = [ 874, 932, 936, 949, 950, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 10000 ];
/* ECMA-376 Part I 18.4.1 charset to codepage mapping */
var CS2CP = ({
0: 1252, /* ANSI */
1: 65001, /* DEFAULT */
2: 65001, /* SYMBOL */
77: 10000, /* MAC */
128: 932, /* SHIFTJIS */
129: 949, /* HANGUL */
130: 1361, /* JOHAB */
134: 936, /* GB2312 */
136: 950, /* CHINESEBIG5 */
161: 1253, /* GREEK */
162: 1254, /* TURKISH */
163: 1258, /* VIETNAMESE */
177: 1255, /* HEBREW */
178: 1256, /* ARABIC */
186: 1257, /* BALTIC */
204: 1251, /* RUSSIAN */
222: 874, /* THAI */
238: 1250, /* EASTEUROPE */
255: 1252, /* OEM */
69: 6969 /* MISC */
/*::[*/0/*::]*/: 1252, /* ANSI */
/*::[*/1/*::]*/: 65001, /* DEFAULT */
/*::[*/2/*::]*/: 65001, /* SYMBOL */
/*::[*/77/*::]*/: 10000, /* MAC */
/*::[*/128/*::]*/: 932, /* SHIFTJIS */
/*::[*/129/*::]*/: 949, /* HANGUL */
/*::[*/130/*::]*/: 1361, /* JOHAB */
/*::[*/134/*::]*/: 936, /* GB2312 */
/*::[*/136/*::]*/: 950, /* CHINESEBIG5 */
/*::[*/161/*::]*/: 1253, /* GREEK */
/*::[*/162/*::]*/: 1254, /* TURKISH */
/*::[*/163/*::]*/: 1258, /* VIETNAMESE */
/*::[*/177/*::]*/: 1255, /* HEBREW */
/*::[*/178/*::]*/: 1256, /* ARABIC */
/*::[*/186/*::]*/: 1257, /* BALTIC */
/*::[*/204/*::]*/: 1251, /* RUSSIAN */
/*::[*/222/*::]*/: 874, /* THAI */
/*::[*/238/*::]*/: 1250, /* EASTEUROPE */
/*::[*/255/*::]*/: 1252, /* OEM */
/*::[*/69/*::]*/: 6969 /* MISC */
}/*:any*/);
var set_ansi = function(cp/*:number*/) { if(VALID_ANSI.indexOf(cp) == -1) return; current_ansi = CS2CP[0] = cp; };

View File

@ -45,35 +45,10 @@ function Base64_encode_pass(input) {
}
return o;
}
function Base64_encode_arr(input) {
var o = "";
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
for (var i = 0; i < input.length; ) {
c1 = input[i++];
e1 = c1 >> 2;
c2 = input[i++];
e2 = (c1 & 3) << 4 | c2 >> 4;
c3 = input[i++];
e3 = (c2 & 15) << 2 | c3 >> 6;
e4 = c3 & 63;
if (isNaN(c2)) {
e3 = e4 = 64;
} else if (isNaN(c3)) {
e4 = 64;
}
o += Base64_map.charAt(e1) + Base64_map.charAt(e2) + Base64_map.charAt(e3) + Base64_map.charAt(e4);
}
return o;
}
function Base64_decode(input) {
var o = "";
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
if (input.slice(0, 5) == "data:") {
var i = input.slice(0, 1024).indexOf(";base64,");
if (i > -1)
input = input.slice(i + 8);
}
input = input.replace(/[^\w\+\/\=]/g, "");
input = input.replace(/^data:([^\/]+\/[^\/]+)?;base64\,/, "").replace(/[^\w\+\/\=]/g, "");
for (var i = 0; i < input.length; ) {
e1 = Base64_map.indexOf(input.charAt(i++));
e2 = Base64_map.indexOf(input.charAt(i++));

View File

@ -173,20 +173,8 @@ function SSF_frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number
var q = Math.floor(sgn * P/Q);
return [q, sgn*P - q*Q, Q];
}
function SSF_normalize_xl_unsafe(v/*:number*/)/*:number*/ {
var s = v.toPrecision(16);
if(s.indexOf("e") > -1) {
var m = s.slice(0, s.indexOf("e"));
m = m.indexOf(".") > -1 ? m.slice(0, (m.slice(0,2) == "0." ? 17 : 16)) : (m.slice(0,15) + fill("0", m.length - 15));
return m + s.slice(s.indexOf("e"));
}
var n = s.indexOf(".") > -1 ? s.slice(0, (s.slice(0,2) == "0." ? 17 : 16)) : (s.slice(0,15) + fill("0", s.length - 15));
return Number(n);
}
function SSF_parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
if(v > 2958465 || v < 0) return null;
v = SSF_normalize_xl_unsafe(v);
var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
var dout=[];
var out={D:date, T:time, u:86400*(v-date)-time,y:0,m:0,d:0,H:0,M:0,S:0,q:0};
@ -215,6 +203,15 @@ function SSF_parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
out.q = dow;
return out;
}
var SSFbasedate = /*#__PURE__*/new Date(1899, 11, 31, 0, 0, 0);
var SSFdnthresh = /*#__PURE__*/SSFbasedate.getTime();
var SSFbase1904 = /*#__PURE__*/new Date(1900, 2, 1, 0, 0, 0);
function datenum_local(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
var epoch = /*#__PURE__*/v.getTime();
if(date1904) epoch -= 1461*24*60*60*1000;
else if(v >= SSFbase1904) epoch += 24*60*60*1000;
return (epoch - (SSFdnthresh + (/*#__PURE__*/v.getTimezoneOffset() - /*#__PURE__*/SSFbasedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
}
/* ECMA-376 18.8.30 numFmt*/
/* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
/* exponent >= -9 and <= 9 */
@ -272,7 +269,7 @@ function SSF_general(v/*:any*/, opts/*:any*/) {
case 'undefined': return "";
case 'object':
if(v == null) return "";
if(v instanceof Date) return SSF_format(14, datenum(v, opts && opts.date1904), opts);
if(v instanceof Date) return SSF_format(14, datenum_local(v, opts && opts.date1904), opts);
}
throw new Error("unsupported value in General format: " + v);
}
@ -340,7 +337,7 @@ function SSF_write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*
switch(fmt) {
case '[h]': case '[hh]': out = val.D*24+val.H; break;
case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+(ss0 == 0 ? Math.round(val.S+val.u) : val.S); break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
default: throw 'bad abstime format: ' + fmt;
} outl = fmt.length === 3 ? 1 : 2; break;
case 101: /* 'e' era */
@ -408,7 +405,7 @@ function write_num_f2(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:s
return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
}
var dec1 = /^#*0*\.([0#]+)/;
var closeparen = /\)[^)]*[0#]/;
var closeparen = /\).*[0#]/;
var phone = /\(###\) ###\\?-####/;
function hashq(str/*:string*/)/*:string*/ {
var o = "", cc;
@ -788,11 +785,10 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
switch(out[i].t) {
case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
case 's':
if((ssm=out[i].v.match(/\.0+$/))) { ss0=Math.max(ss0,ssm[0].length-1); bt = 4;}
if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
if(bt < 3) bt = 3;
/* falls through */
case 'd': case 'y': case 'e': lst=out[i].t; break;
case 'M': lst=out[i].t; if(bt < 2) bt = 2; break;
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
case 'X': /*if(out[i].v === "B2");*/
break;
@ -802,29 +798,19 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
}
}
/* time rounding depends on presence of minute / second / usec fields */
var _dt;
switch(bt) {
case 0: break;
case 1:
case 2:
case 3:
/*::if(!dt) break;*/
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
if(dt.H >= 24) { dt.H = 0; ++dt.D; _dt = SSF_parse_date_code(dt.D); _dt.u = dt.u; _dt.S = dt.S; _dt.M = dt.M; _dt.H = dt.H; dt = _dt; }
break;
case 4:
switch(ss0) {
case 1: dt.u = Math.round(dt.u * 10)/10; break;
case 2: dt.u = Math.round(dt.u * 100)/100; break;
case 3: dt.u = Math.round(dt.u * 1000)/1000; break;
}
if(dt.u >= 1) { dt.u = 0; ++dt.S; }
case 2:
/*::if(!dt) break;*/
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
if(dt.H >= 24) { dt.H = 0; ++dt.D; _dt = SSF_parse_date_code(dt.D); _dt.u = dt.u; _dt.S = dt.S; _dt.M = dt.M; _dt.H = dt.H; dt = _dt; }
break;
}
@ -940,8 +926,6 @@ function choose_fmt(f/*:string*/, v/*:any*/) {
if(l<4 && lat>-1) --l;
if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
/* NOTE: most spreadsheet software do not support NaN or infinities */
if(typeof v === "number" && !isFinite(v)) v = 0;
switch(fmt.length) {
case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
@ -973,13 +957,11 @@ function SSF_format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
break;
}
if(SSF_isgeneral(sfmt,0)) return SSF_general(v, o);
if(v instanceof Date) v = datenum(v, o.date1904);
if(v instanceof Date) v = datenum_local(v, o.date1904);
var f = choose_fmt(sfmt, v);
if(SSF_isgeneral(f[1])) return SSF_general(v, o);
if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
else if(v === "" || v == null) return "";
else if(isNaN(v) && f[1].indexOf("0") > -1) return "#VALUE!";
else if(!isFinite(v) && f[1].indexOf("0") > -1) return "#DIV/0!";
return eval_fmt(f[1], v, o, f[0]);
}
function SSF_load(fmt/*:string*/, idx/*:?number*/)/*:number*/ {

View File

@ -43,7 +43,6 @@ var dateNFregex = /[dD]+|[mM]+|[yYeE]+|[Hh]+|[Ss]+/g;
function dateNF_regex(dateNF/*:string|number*/)/*:RegExp*/ {
var fmt = typeof dateNF == "number" ? table_fmt[dateNF] : dateNF;
fmt = fmt.replace(dateNFregex, "(\\d+)");
dateNFregex.lastIndex = 0;
return new RegExp("^" + fmt + "$");
}
function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/*:string*/ {
@ -56,7 +55,6 @@ function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/
case 'm': if(H >= 0) M = v; else m = v; break;
}
});
dateNFregex.lastIndex = 0;
if(S >= 0 && M == -1 && m >= 0) { M = m; m = -1; }
var datestr = (("" + (Y>=0?Y: new Date().getFullYear())).slice(-4) + "-" + ("00" + (m>=1?m:1)).slice(-2) + "-" + ("00" + (d>=1?d:1)).slice(-2));
if(datestr.length == 7) datestr = "0" + datestr;

View File

@ -769,9 +769,9 @@ function _write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes|strin
file = cfb.FileIndex[i];
if(i === 0) file.start = file.size ? file.start - 1 : ENDOFCHAIN;
var _nm/*:string*/ = (i === 0 && _opts.root) || file.name;
if(_nm.length > 31) {
console.error("Name " + _nm + " will be truncated to " + _nm.slice(0,31));
_nm = _nm.slice(0, 31);
if(_nm.length > 32) {
console.error("Name " + _nm + " will be truncated to " + _nm.slice(0,32));
_nm = _nm.slice(0, 32);
}
flen = 2*(_nm.length+1);
o.write_shift(64, _nm, "utf16le");
@ -1683,7 +1683,7 @@ function parse_mime(cfb/*:CFBContainer*/, data/*:Array<string>*/, root/*:string*
for(;di < 10; ++di) {
var line = data[di];
if(!line || line.match(/^\s*$/)) break;
var m = line.match(/^([^:]*?):\s*([^\s].*)$/);
var m = line.match(/^(.*?):\s*([^\s].*)$/);
if(m) switch(m[1].toLowerCase()) {
case "content-location": fname = m[2].trim(); break;
case "content-type": ctype = m[2].trim(); break;

View File

@ -35,7 +35,7 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
/*:: declare var chrome: any; */
if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
return chrome.downloads.download({ url: url, filename: fname, saveAs: true });
return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
}
var a = document.createElement("a");
if(a.download != null) {
@ -45,10 +45,6 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
return url;
}
} else if(typeof URL !== 'undefined' && !URL.createObjectURL && typeof chrome === 'object') {
/* manifest v3 extensions -- no URL.createObjectURL */
var b64 = "data:application/octet-stream;base64," + Base64_encode_arr(new Uint8Array(blobify(data)));
return chrome.downloads.download({ url: b64, filename: fname, saveAs: true });
}
}
// $FlowIgnore
@ -57,7 +53,7 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
var out = File(fname); out.open("w"); out.encoding = "binary";
if(Array.isArray(payload)) payload = a2s(payload);
out.write(payload); out.close(); return payload;
} catch(e) { if(!e.message || e.message.indexOf("onstruct") == -1) throw e; }
} catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; }
throw new Error("cannot save file " + fname);
}
@ -71,6 +67,6 @@ function read_binary(path/*:string*/) {
var infile = File(path); infile.open("r"); infile.encoding = "binary";
var data = infile.read(); infile.close();
return data;
} catch(e) { if(!e.message || e.message.indexOf("onstruct") == -1) throw e; }
} catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; }
throw new Error("Cannot access file " + path);
}

View File

@ -31,19 +31,22 @@ function evert_arr(obj/*:any*/)/*:EvertArrType*/ {
return o;
}
var dnthresh = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
var basedate = /*#__PURE__*/new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
var epoch = /*#__PURE__*/v.getTime();
var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
if(date1904) { res -= 1462; return res < -1402 ? res - 1 : res; }
return res < 60 ? res - 1 : res;
if(date1904) epoch -= 1462*24*60*60*1000;
var dnthresh = /*#__PURE__*/basedate.getTime() + (/*#__PURE__*/v.getTimezoneOffset() - /*#__PURE__*/basedate.getTimezoneOffset()) * 60000;
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
}
function numdate(v/*:number*/)/*:Date|number*/ {
if(v >= 60 && v < 61) return v;
var refdate = /*#__PURE__*/new Date();
var dnthresh = /*#__PURE__*/basedate.getTime() + (/*#__PURE__*/refdate.getTimezoneOffset() - /*#__PURE__*/basedate.getTimezoneOffset()) * 60000;
var refoffset = /*#__PURE__*/refdate.getTimezoneOffset();
function numdate(v/*:number*/)/*:Date*/ {
var out = new Date();
out.setTime((v>60 ? v : (v+1)) * 24 * 60 * 60 * 1000 + dnthresh);
out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh);
if (out.getTimezoneOffset() !== refoffset) {
out.setTime(out.getTime() + (out.getTimezoneOffset() - refoffset) * 60000);
}
return out;
}
@ -74,22 +77,28 @@ function parse_isodur(s) {
return sec;
}
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]], sans "Z"
/* parses a date string as a UTC date */
function parseDate(str/*:string*/, date1904/*:boolean*/)/*:Date*/ {
if(str instanceof Date) return str;
var m = str.match(pdre1);
if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
m = str.match(pdre2);
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
/* TODO: 1900-02-29T00:00:00.000 should return a flag to treat as a date code (affects xlml) */
m = str.match(pdre3);
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt((m[7] + "0000").slice(1,4), 10))||0)));
var good_pd_date_1 = /*#__PURE__*/new Date('2017-02-19T19:06:09.000Z');
var good_pd_date = /*#__PURE__*/isNaN(/*#__PURE__*/good_pd_date_1.getFullYear()) ? /*#__PURE__*/new Date('2/19/17') : good_pd_date_1;
var good_pd = /*#__PURE__*/good_pd_date.getFullYear() == 2017;
/* parses a date as a local date */
function parseDate(str/*:string|Date*/, fixdate/*:?number*/)/*:Date*/ {
var d = new Date(str);
return d;
if(good_pd) {
/*:: if(fixdate == null) fixdate = 0; */
if(fixdate > 0) d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
else if(fixdate < 0) d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000);
return d;
}
if(str instanceof Date) return str;
if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
var s = d.getFullYear();
if(str.indexOf("" + s) > -1) return d;
d.setFullYear(d.getFullYear() + 100); return d;
}
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000);
return out;
}
function cc2str(arr/*:Array<number>*/, debomit)/*:string*/ {
@ -120,18 +129,8 @@ function cc2str(arr/*:Array<number>*/, debomit)/*:string*/ {
return new TextDecoder("latin1").decode(arr).replace(/[€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ]/g, function(c) { return rev[c] || c; });
} catch(e) {}
var o = [], i = 0;
// this cascade is for the browsers and runtimes of antiquity (and for modern runtimes that lack TextEncoder)
try {
for(i = 0; i < arr.length - 65536; i+=65536) o.push(String.fromCharCode.apply(0, arr.slice(i, i + 65536)));
o.push(String.fromCharCode.apply(0, arr.slice(i)));
} catch(e) { try {
for(; i < arr.length - 16384; i+=16384) o.push(String.fromCharCode.apply(0, arr.slice(i, i + 16384)));
o.push(String.fromCharCode.apply(0, arr.slice(i)));
} catch(e) {
for(; i != arr.length; ++i) o.push(String.fromCharCode(arr[i]));
}
}
var o = [];
for(var i = 0; i != arr.length; ++i) o.push(String.fromCharCode(arr[i]));
return o.join("");
}
@ -154,56 +153,39 @@ function fuzzynum(s/*:string*/)/*:number*/ {
var wt = 1;
var ss = s.replace(/([\d]),([\d])/g,"$1$2").replace(/[$]/g,"").replace(/[%]/g, function() { wt *= 100; return "";});
if(!isNaN(v = Number(ss))) return v / wt;
ss = ss.replace(/[(]([^()]*)[)]/,function($$, $1) { wt = -wt; return $1;});
ss = ss.replace(/[(](.*)[)]/,function($$, $1) { wt = -wt; return $1;});
if(!isNaN(v = Number(ss))) return v / wt;
return v;
}
/* NOTE: Chrome rejects bare times like 1:23 PM */
var FDRE1 = /^(0?\d|1[0-2])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))\s+([ap])m?$/;
var FDRE2 = /^([01]?\d|2[0-3])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))$/;
var FDISO = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)(\.\d+)?[Z]?$/; // YYYY-mm-dd(T or space)HH:MM:SS[.UUU][Z]
/* TODO: 1904 adjustment */
var utc_append_works = new Date("6/9/69 00:00 UTC").valueOf() == -17798400000;
function fuzzytime1(M) /*:Date*/ {
if(!M[2]) return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0));
if(M[3]) {
if(M[4]) return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000));
else return new Date(Date.UTC(1899,11,31,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000));
}
else if(M[5]) return new Date(Date.UTC(1899,11,31, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0));
else return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0));
}
function fuzzytime2(M) /*:Date*/ {
if(!M[2]) return new Date(Date.UTC(1899,11,31,+M[1], 0, 0, 0));
if(M[3]) {
if(M[4]) return new Date(Date.UTC(1899,11,31,+M[1], +M[2], +M[4], parseFloat(M[3])*1000));
else return new Date(Date.UTC(1899,11,31,0, +M[1], +M[2], parseFloat(M[3])*1000));
}
else if(M[5]) return new Date(Date.UTC(1899,11,31, +M[1], +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0));
else return new Date(Date.UTC(1899,11,31,+M[1], +M[2], 0, 0));
/* TODO: 1904 adjustment, keep in sync with base date */
if(!M[2]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0);
if(M[3]) {
if(M[4]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000);
else return new Date(1899,11,30,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000);
}
else if(M[5]) return new Date(1899,11,30, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0);
else return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0);
}
var lower_months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'];
function fuzzydate(s/*:string*/)/*:Date*/ {
// See issue 2863 -- this is technically not supported in Excel but is otherwise useful
if(FDISO.test(s)) return s.indexOf("Z") == -1 ? local_to_utc(new Date(s)) : new Date(s);
var lower = s.toLowerCase();
var lnos = lower.replace(/\s+/g, " ").trim();
var M = lnos.match(FDRE1);
if(M) return fuzzytime1(M);
M = lnos.match(FDRE2);
if(M) return fuzzytime2(M);
M = lnos.match(pdre3);
if(M) return new Date(Date.UTC(+M[1], +M[2]-1, +M[3], +M[4], +M[5], ((M[6] && parseInt(M[6].slice(1), 10))|| 0), ((M[7] && parseInt((M[7] + "0000").slice(1,4), 10))||0)));
var o = new Date(utc_append_works && s.indexOf("UTC") == -1 ? s + " UTC": s), n = new Date(NaN);
var o = new Date(s), n = new Date(NaN);
var y = o.getYear(), m = o.getMonth(), d = o.getDate();
if(isNaN(d)) return n;
if(lower.match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) {
lower = lower.replace(/[^a-z]/g,"").replace(/([^a-z]|^)[ap]m?([^a-z]|$)/,"");
if(lower.length > 3 && lower_months.indexOf(lower) == -1) return n;
} else if(lower.replace(/[ap]m?/, "").match(/[a-z]/)) return n;
if(y < 0 || y > 8099 || s.match(/[^-0-9:,\/\\\ ]/)) return n;
if(y < 0 || y > 8099 || s.match(/[^-0-9:,\/\\]/)) return n;
return o;
}
@ -216,165 +198,3 @@ var split_regex = /*#__PURE__*/(function() {
return o;
};
})();
function utc_to_local(utc) {
return new Date(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate(), utc.getUTCHours(), utc.getUTCMinutes(), utc.getUTCSeconds(), utc.getUTCMilliseconds());
}
function local_to_utc(local) {
return new Date(Date.UTC(local.getFullYear(), local.getMonth(), local.getDate(), local.getHours(), local.getMinutes(), local.getSeconds(), local.getMilliseconds()));
}
function remove_doctype(str) {
var preamble = str.slice(0, 1024);
var si = preamble.indexOf("<!DOCTYPE");
if(si == -1) return str;
var m = str.match(/<[\w]/);
if(!m) return str;
return str.slice(0, si) + str.slice(m.index);
}
/* str.match(/<!--[\s\S]*?-->/g) --> str_match_ng(str, "<!--", "-->") */
function str_match_ng(str, s, e) {
var out = [];
var si = str.indexOf(s);
while(si > -1) {
var ei = str.indexOf(e, si + s.length);
if(ei == -1) break;
out.push(str.slice(si, ei + e.length));
si = str.indexOf(s, ei + e.length);
}
return out.length > 0 ? out : null;
}
/* str.replace(/<!--[\s\S]*?-->/g, "") --> str_remove_ng(str, "<!--", "-->") */
function str_remove_ng(str, s, e) {
var out = [], last = 0;
var si = str.indexOf(s);
if(si == -1) return str;
while(si > -1) {
out.push(str.slice(last, si));
var ei = str.indexOf(e, si + s.length);
if(ei == -1) break;
if((si = str.indexOf(s, (last = ei + e.length))) == -1) out.push(str.slice(last));
}
return out.join("");
}
/* str.match(/<tag\b[^>]*?>([\s\S]*?)</tag>/) --> str_match_xml(str, "tag") */
var xml_boundary = { " ": 1, "\t": 1, "\r": 1, "\n": 1, ">": 1 };
function str_match_xml(str, tag) {
var si = str.indexOf('<' + tag), w = tag.length + 1, L = str.length;
while(si >= 0 && si <= L - w && !xml_boundary[str.charAt(si + w)]) si = str.indexOf('<' + tag, si+1);
if(si === -1) return null;
var sf = str.indexOf(">", si + tag.length);
if(sf === -1) return null;
var et = "</" + tag + ">";
var ei = str.indexOf(et, sf);
if(ei == -1) return null;
return [str.slice(si, ei + et.length), str.slice(sf + 1, ei)];
}
/* str.match(/<(?:\w+:)?tag\b[^<>]*?>([\s\S]*?)<\/(?:\w+:)?tag>/) --> str_match_xml(str, "tag") */
var str_match_xml_ns = /*#__PURE__*/(function() {
var str_match_xml_ns_cache = {};
return function str_match_xml_ns(str, tag) {
var res = str_match_xml_ns_cache[tag];
if(!res) str_match_xml_ns_cache[tag] = res = [
new RegExp('<(?:\\w+:)?'+tag+'\\b[^<>]*>', "g"),
new RegExp('</(?:\\w+:)?'+tag+'>', "g")
];
res[0].lastIndex = res[1].lastIndex = 0;
var m = res[0].exec(str);
if(!m) return null;
var si = m.index;
var sf = res[0].lastIndex;
res[1].lastIndex = res[0].lastIndex;
m = res[1].exec(str);
if(!m) return null;
var ei = m.index;
var ef = res[1].lastIndex;
return [str.slice(si, ef), str.slice(sf, ei)];
};
})();
/* str.match(/<(?:\w+:)?tag\b[^<>]*?>([\s\S]*?)<\/(?:\w+:)?tag>/g) --> str_match_xml_ns_g(str, "tag") */
var str_match_xml_ns_g = /*#__PURE__*/(function() {
var str_match_xml_ns_cache = {};
return function str_match_xml_ns(str, tag) {
var out = [];
var res = str_match_xml_ns_cache[tag];
if(!res) str_match_xml_ns_cache[tag] = res = [
new RegExp('<(?:\\w+:)?'+tag+'\\b[^<>]*>', "g"),
new RegExp('</(?:\\w+:)?'+tag+'>', "g")
];
res[0].lastIndex = res[1].lastIndex = 0;
var m;
while((m = res[0].exec(str))) {
var si = m.index;
res[1].lastIndex = res[0].lastIndex;
m = res[1].exec(str);
if(!m) return null;
var ef = res[1].lastIndex;
out.push(str.slice(si, ef));
res[0].lastIndex = res[1].lastIndex;
}
return out.length == 0 ? null : out;
};
})();
var str_remove_xml_ns_g = /*#__PURE__*/(function() {
var str_remove_xml_ns_cache = {};
return function str_remove_xml_ns_g(str, tag) {
var out = [];
var res = str_remove_xml_ns_cache[tag];
if(!res) str_remove_xml_ns_cache[tag] = res = [
new RegExp('<(?:\\w+:)?'+tag+'\\b[^<>]*>', "g"),
new RegExp('</(?:\\w+:)?'+tag+'>', "g")
];
res[0].lastIndex = res[1].lastIndex = 0;
var m;
var si = 0, ef = 0;
while((m = res[0].exec(str))) {
si = m.index;
out.push(str.slice(ef, si));
ef = si;
res[1].lastIndex = res[0].lastIndex;
m = res[1].exec(str);
if(!m) return null;
ef = res[1].lastIndex;
res[0].lastIndex = res[1].lastIndex;
}
out.push(str.slice(ef));
return out.length == 0 ? "" : out.join("");
};
})();
/* str.match(/<(?:\w+:)?tag\b[^>]*?>([\s\S]*?)<\/(?:\w+:)?tag>/gi) --> str_match_xml_ns_ig(str, "tag") */
var str_match_xml_ig = /*#__PURE__*/(function() {
var str_match_xml_ns_cache = {};
return function str_match_xml_ns(str, tag) {
var out = [];
var res = str_match_xml_ns_cache[tag];
if(!res) str_match_xml_ns_cache[tag] = res = [
new RegExp('<'+tag+'\\b[^<>]*>', "ig"),
new RegExp('</'+tag+'>', "ig")
];
res[0].lastIndex = res[1].lastIndex = 0;
var m;
while((m = res[0].exec(str))) {
var si = m.index;
res[1].lastIndex = res[0].lastIndex;
m = res[1].exec(str);
if(!m) return null;
var ef = res[1].lastIndex;
out.push(str.slice(si, ef));
res[0].lastIndex = res[1].lastIndex;
}
return out.length == 0 ? null : out;
};
})();

View File

@ -1,6 +1,6 @@
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
var attregexg=/\s([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex1=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?<>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'"<>\s=]+))*\s*[\/\?]?>/mg, tagregex2 = /<[^<>]*>/g;
var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex1=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s*[\/\?]?>/mg, tagregex2 = /<[^>]*>/g;
var tagregex = /*#__PURE__*/XML_HEADER.match(tagregex1) ? tagregex1 : tagregex2;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*/)/*:any*/ {
@ -11,7 +11,7 @@ function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*
if(eq === tag.length) return z;
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1;
if(m) for(i = 0; i != m.length; ++i) {
cc = m[i].slice(1);
cc = m[i];
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
q = cc.slice(0,c).trim();
while(cc.charCodeAt(c+1) == 32) ++c;
@ -161,6 +161,16 @@ var utf8write/*:StringConv*/ = has_buf ? function(data) { return Buffer_from(dat
return out.join("");
};
// matches <foo>...</foo> extracts content
var matchtag = /*#__PURE__*/(function() {
var mtcache/*:{[k:string]:RegExp}*/ = ({}/*:any*/);
return function matchtag(f/*:string*/,g/*:?string*/)/*:RegExp*/ {
var t = f+"|"+(g||"");
if(mtcache[t]) return mtcache[t];
return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([\\s\\S]*?)</(?:\\w+:)?'+f+'>',((g||"")/*:any*/)));
};
})();
var htmldecode/*:{(s:string):string}*/ = /*#__PURE__*/(function() {
var entities/*:Array<[RegExp, string]>*/ = [
['nbsp', ' '], ['middot', '·'],
@ -171,25 +181,30 @@ var htmldecode/*:{(s:string):string}*/ = /*#__PURE__*/(function() {
// Remove new lines and spaces from start of content
.replace(/^[\t\n\r ]+/, "")
// Remove new lines and spaces from end of content
.replace(/(^|[^\t\n\r ])[\t\n\r ]+$/,"$1")
.replace(/[\t\n\r ]+$/,"")
// Added line which removes any white space characters after and before html tags
.replace(/>\s+/g,">").replace(/\b\s+</g,"<")
.replace(/>\s+/g,">").replace(/\s+</g,"<")
// Replace remaining new lines and spaces with space
.replace(/[\t\n\r ]+/g, " ")
// Replace <br> tags with new lines
.replace(/<\s*[bB][rR]\s*\/?>/g,"\n")
// Strip HTML elements
.replace(/<[^<>]*>/g,"");
.replace(/<[^>]*>/g,"");
for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]);
return o;
};
})();
var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^<"'>]*)>([\s\S]*)</;
var vtregex = /*#__PURE__*/(function(){ var vt_cache = {};
return function vt_regex(bt) {
if(vt_cache[bt] !== undefined) return vt_cache[bt];
return (vt_cache[bt] = new RegExp("<(?:vt:)?" + bt + ">([\\s\\S]*?)</(?:vt:)?" + bt + ">", 'g') );
};})();
var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^>]*)>([\s\S]*)</;
function parseVector(data/*:string*/, opts)/*:Array<{v:string,t:string}>*/ {
var h = parsexmltag(data);
var matches/*:Array<string>*/ = str_match_xml_ns_g(data, h.baseType)||[];
var matches/*:Array<string>*/ = data.match(vtregex(h.baseType))||[];
var res/*:Array<any>*/ = [];
if(matches.length != h.size) {
if(opts.WTF) throw new Error("unexpected vector length " + matches.length + " != " + h.size);
@ -230,8 +245,9 @@ function xlml_normalize(d)/*:string*/ {
if(typeof Uint8Array !== 'undefined' && d instanceof Uint8Array) return utf8read(a2s(ab2a(d)));
throw new Error("Bad input format: expected Buffer or string");
}
/* UOS uses CJK in tags, ODS uses invalid XML */
var xlmlregex = /<([\/]?)([^\s?><!\/:"]*:|)([^\s?<>:\/"]+)(?:\s+[^<>=?"'\s]+="[^"]*?")*\s*[\/]?>/mg;
/* UOS uses CJK in tags */
var xlmlregex = /<(\/?)([^\s?><!\/:]*:|)([^\s?<>:\/]+)(?:[\s?:\/](?:[^>=]|="[^"]*?")*)?>/mg;
//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
var XMLNS = ({
CORE_PROPS: 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties',

View File

@ -108,13 +108,6 @@ function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ {
return { SheetNames: [n], Sheets: sheets };
}
function sheet_new(opts) {
var out = {};
var o = opts || {};
if(o.dense) out["!data"] = [];
return out;
}
function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
var o = opts || {};
var dense = _ws ? (_ws["!data"] != null) : o.dense;
@ -128,19 +121,18 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
_R = _origin.r; _C = _origin.c;
}
if(!ws["!ref"]) ws["!ref"] = "A1:A1";
}
var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/);
if(ws["!ref"]){
if(ws['!ref']) {
var _range = safe_decode_range(ws['!ref']);
range.s.c = _range.s.c;
range.s.r = _range.s.r;
range.e.c = Math.max(range.e.c, _range.e.c);
range.e.r = Math.max(range.e.r, _range.e.r);
if(_R == -1) range.e.r = _R = (ws["!ref"] ? _range.e.r + 1 : 0);
} else {
range.s.c = range.e.c = range.s.r = range.e.r = 0;
if(_R == -1) range.e.r = _R = _range.e.r + 1;
}
var row = [], seen = false;
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");
@ -157,7 +149,6 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
if(range.s.c > __C) range.s.c = __C;
if(range.e.r < __R) range.e.r = __R;
if(range.e.c < __C) range.e.c = __C;
seen = true;
if(data[R][C] && typeof data[R][C] === 'object' && !Array.isArray(data[R][C]) && !(data[R][C] instanceof Date)) cell = data[R][C];
else {
if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
@ -167,15 +158,10 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
else if(!o.sheetStubs) continue;
else cell.t = 'z';
}
else if(typeof cell.v === 'number') {
if(isFinite(cell.v)) cell.t = 'n';
else if(isNaN(cell.v)) { cell.t = 'e'; cell.v = 0x0F; /* #VALUE! */ }
else { cell.t = 'e'; cell.v = 0x07; /*# DIV/0 */ }
}
else if(typeof cell.v === 'number') cell.t = 'n';
else if(typeof cell.v === 'boolean') cell.t = 'b';
else if(cell.v instanceof Date) {
cell.z = o.dateNF || table_fmt[14];
if(!o.UTC) cell.v = local_to_utc(cell.v);
if(o.cellDates) { cell.t = 'd'; cell.w = SSF_format(cell.z, datenum(cell.v, o.date1904)); }
else { cell.t = 'n'; cell.v = datenum(cell.v, o.date1904); cell.w = SSF_format(cell.z, cell.v); }
}
@ -191,7 +177,8 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
}
}
}
if(seen && range.s.c < 10400000) ws['!ref'] = encode_range(range);
if(range.s.c < 10000000) ws['!ref'] = encode_range(range);
return ws;
}
function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { return sheet_add_aoa(null, data, opts); }

View File

@ -44,118 +44,118 @@ var VT_CUSTOM = [VT_STRING, VT_USTR];
/* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */
var DocSummaryPIDDSI = {
0x01: { n: 'CodePage', t: VT_I2 },
0x02: { n: 'Category', t: VT_STRING },
0x03: { n: 'PresentationFormat', t: VT_STRING },
0x04: { n: 'ByteCount', t: VT_I4 },
0x05: { n: 'LineCount', t: VT_I4 },
0x06: { n: 'ParagraphCount', t: VT_I4 },
0x07: { n: 'SlideCount', t: VT_I4 },
0x08: { n: 'NoteCount', t: VT_I4 },
0x09: { n: 'HiddenCount', t: VT_I4 },
0x0a: { n: 'MultimediaClipCount', t: VT_I4 },
0x0b: { n: 'ScaleCrop', t: VT_BOOL },
0x0c: { n: 'HeadingPairs', t: VT_VECTOR_VARIANT /* VT_VECTOR | VT_VARIANT */ },
0x0d: { n: 'TitlesOfParts', t: VT_VECTOR_LPSTR /* VT_VECTOR | VT_LPSTR */ },
0x0e: { n: 'Manager', t: VT_STRING },
0x0f: { n: 'Company', t: VT_STRING },
0x10: { n: 'LinksUpToDate', t: VT_BOOL },
0x11: { n: 'CharacterCount', t: VT_I4 },
0x13: { n: 'SharedDoc', t: VT_BOOL },
0x16: { n: 'HyperlinksChanged', t: VT_BOOL },
0x17: { n: 'AppVersion', t: VT_I4, p: 'version' },
0x18: { n: 'DigSig', t: VT_BLOB },
0x1A: { n: 'ContentType', t: VT_STRING },
0x1B: { n: 'ContentStatus', t: VT_STRING },
0x1C: { n: 'Language', t: VT_STRING },
0x1D: { n: 'Version', t: VT_STRING },
0xFF: {},
/*::[*/0x01/*::]*/: { n: 'CodePage', t: VT_I2 },
/*::[*/0x02/*::]*/: { n: 'Category', t: VT_STRING },
/*::[*/0x03/*::]*/: { n: 'PresentationFormat', t: VT_STRING },
/*::[*/0x04/*::]*/: { n: 'ByteCount', t: VT_I4 },
/*::[*/0x05/*::]*/: { n: 'LineCount', t: VT_I4 },
/*::[*/0x06/*::]*/: { n: 'ParagraphCount', t: VT_I4 },
/*::[*/0x07/*::]*/: { n: 'SlideCount', t: VT_I4 },
/*::[*/0x08/*::]*/: { n: 'NoteCount', t: VT_I4 },
/*::[*/0x09/*::]*/: { n: 'HiddenCount', t: VT_I4 },
/*::[*/0x0a/*::]*/: { n: 'MultimediaClipCount', t: VT_I4 },
/*::[*/0x0b/*::]*/: { n: 'ScaleCrop', t: VT_BOOL },
/*::[*/0x0c/*::]*/: { n: 'HeadingPairs', t: VT_VECTOR_VARIANT /* VT_VECTOR | VT_VARIANT */ },
/*::[*/0x0d/*::]*/: { n: 'TitlesOfParts', t: VT_VECTOR_LPSTR /* VT_VECTOR | VT_LPSTR */ },
/*::[*/0x0e/*::]*/: { n: 'Manager', t: VT_STRING },
/*::[*/0x0f/*::]*/: { n: 'Company', t: VT_STRING },
/*::[*/0x10/*::]*/: { n: 'LinksUpToDate', t: VT_BOOL },
/*::[*/0x11/*::]*/: { n: 'CharacterCount', t: VT_I4 },
/*::[*/0x13/*::]*/: { n: 'SharedDoc', t: VT_BOOL },
/*::[*/0x16/*::]*/: { n: 'HyperlinksChanged', t: VT_BOOL },
/*::[*/0x17/*::]*/: { n: 'AppVersion', t: VT_I4, p: 'version' },
/*::[*/0x18/*::]*/: { n: 'DigSig', t: VT_BLOB },
/*::[*/0x1A/*::]*/: { n: 'ContentType', t: VT_STRING },
/*::[*/0x1B/*::]*/: { n: 'ContentStatus', t: VT_STRING },
/*::[*/0x1C/*::]*/: { n: 'Language', t: VT_STRING },
/*::[*/0x1D/*::]*/: { n: 'Version', t: VT_STRING },
/*::[*/0xFF/*::]*/: {},
/* [MS-OLEPS] 2.18 */
0x80000000: { n: 'Locale', t: VT_UI4 },
0x80000003: { n: 'Behavior', t: VT_UI4 },
0x72627262: {}
/*::[*/0x80000000/*::]*/: { n: 'Locale', t: VT_UI4 },
/*::[*/0x80000003/*::]*/: { n: 'Behavior', t: VT_UI4 },
/*::[*/0x72627262/*::]*/: {}
};
/* [MS-OSHARED] 2.3.3.2.1.1 Summary Information Property Set PIDSI */
var SummaryPIDSI = {
0x01: { n: 'CodePage', t: VT_I2 },
0x02: { n: 'Title', t: VT_STRING },
0x03: { n: 'Subject', t: VT_STRING },
0x04: { n: 'Author', t: VT_STRING },
0x05: { n: 'Keywords', t: VT_STRING },
0x06: { n: 'Comments', t: VT_STRING },
0x07: { n: 'Template', t: VT_STRING },
0x08: { n: 'LastAuthor', t: VT_STRING },
0x09: { n: 'RevNumber', t: VT_STRING },
0x0A: { n: 'EditTime', t: VT_FILETIME },
0x0B: { n: 'LastPrinted', t: VT_FILETIME },
0x0C: { n: 'CreatedDate', t: VT_FILETIME },
0x0D: { n: 'ModifiedDate', t: VT_FILETIME },
0x0E: { n: 'PageCount', t: VT_I4 },
0x0F: { n: 'WordCount', t: VT_I4 },
0x10: { n: 'CharCount', t: VT_I4 },
0x11: { n: 'Thumbnail', t: VT_CF },
0x12: { n: 'Application', t: VT_STRING },
0x13: { n: 'DocSecurity', t: VT_I4 },
0xFF: {},
/*::[*/0x01/*::]*/: { n: 'CodePage', t: VT_I2 },
/*::[*/0x02/*::]*/: { n: 'Title', t: VT_STRING },
/*::[*/0x03/*::]*/: { n: 'Subject', t: VT_STRING },
/*::[*/0x04/*::]*/: { n: 'Author', t: VT_STRING },
/*::[*/0x05/*::]*/: { n: 'Keywords', t: VT_STRING },
/*::[*/0x06/*::]*/: { n: 'Comments', t: VT_STRING },
/*::[*/0x07/*::]*/: { n: 'Template', t: VT_STRING },
/*::[*/0x08/*::]*/: { n: 'LastAuthor', t: VT_STRING },
/*::[*/0x09/*::]*/: { n: 'RevNumber', t: VT_STRING },
/*::[*/0x0A/*::]*/: { n: 'EditTime', t: VT_FILETIME },
/*::[*/0x0B/*::]*/: { n: 'LastPrinted', t: VT_FILETIME },
/*::[*/0x0C/*::]*/: { n: 'CreatedDate', t: VT_FILETIME },
/*::[*/0x0D/*::]*/: { n: 'ModifiedDate', t: VT_FILETIME },
/*::[*/0x0E/*::]*/: { n: 'PageCount', t: VT_I4 },
/*::[*/0x0F/*::]*/: { n: 'WordCount', t: VT_I4 },
/*::[*/0x10/*::]*/: { n: 'CharCount', t: VT_I4 },
/*::[*/0x11/*::]*/: { n: 'Thumbnail', t: VT_CF },
/*::[*/0x12/*::]*/: { n: 'Application', t: VT_STRING },
/*::[*/0x13/*::]*/: { n: 'DocSecurity', t: VT_I4 },
/*::[*/0xFF/*::]*/: {},
/* [MS-OLEPS] 2.18 */
0x80000000: { n: 'Locale', t: VT_UI4 },
0x80000003: { n: 'Behavior', t: VT_UI4 },
0x72627262: {}
/*::[*/0x80000000/*::]*/: { n: 'Locale', t: VT_UI4 },
/*::[*/0x80000003/*::]*/: { n: 'Behavior', t: VT_UI4 },
/*::[*/0x72627262/*::]*/: {}
};
/* [MS-XLS] 2.4.63 Country/Region codes */
var CountryEnum = {
0x0001: "US", // United States
0x0002: "CA", // Canada
0x0003: "", // Latin America (except Brazil)
0x0007: "RU", // Russia
0x0014: "EG", // Egypt
0x001E: "GR", // Greece
0x001F: "NL", // Netherlands
0x0020: "BE", // Belgium
0x0021: "FR", // France
0x0022: "ES", // Spain
0x0024: "HU", // Hungary
0x0027: "IT", // Italy
0x0029: "CH", // Switzerland
0x002B: "AT", // Austria
0x002C: "GB", // United Kingdom
0x002D: "DK", // Denmark
0x002E: "SE", // Sweden
0x002F: "NO", // Norway
0x0030: "PL", // Poland
0x0031: "DE", // Germany
0x0034: "MX", // Mexico
0x0037: "BR", // Brazil
0x003d: "AU", // Australia
0x0040: "NZ", // New Zealand
0x0042: "TH", // Thailand
0x0051: "JP", // Japan
0x0052: "KR", // Korea
0x0054: "VN", // Viet Nam
0x0056: "CN", // China
0x005A: "TR", // Turkey
0x0069: "JS", // Ramastan
0x00D5: "DZ", // Algeria
0x00D8: "MA", // Morocco
0x00DA: "LY", // Libya
0x015F: "PT", // Portugal
0x0162: "IS", // Iceland
0x0166: "FI", // Finland
0x01A4: "CZ", // Czech Republic
0x0376: "TW", // Taiwan
0x03C1: "LB", // Lebanon
0x03C2: "JO", // Jordan
0x03C3: "SY", // Syria
0x03C4: "IQ", // Iraq
0x03C5: "KW", // Kuwait
0x03C6: "SA", // Saudi Arabia
0x03CB: "AE", // United Arab Emirates
0x03CC: "IL", // Israel
0x03CE: "QA", // Qatar
0x03D5: "IR", // Iran
0xFFFF: "US" // United States
/*::[*/0x0001/*::]*/: "US", // United States
/*::[*/0x0002/*::]*/: "CA", // Canada
/*::[*/0x0003/*::]*/: "", // Latin America (except Brazil)
/*::[*/0x0007/*::]*/: "RU", // Russia
/*::[*/0x0014/*::]*/: "EG", // Egypt
/*::[*/0x001E/*::]*/: "GR", // Greece
/*::[*/0x001F/*::]*/: "NL", // Netherlands
/*::[*/0x0020/*::]*/: "BE", // Belgium
/*::[*/0x0021/*::]*/: "FR", // France
/*::[*/0x0022/*::]*/: "ES", // Spain
/*::[*/0x0024/*::]*/: "HU", // Hungary
/*::[*/0x0027/*::]*/: "IT", // Italy
/*::[*/0x0029/*::]*/: "CH", // Switzerland
/*::[*/0x002B/*::]*/: "AT", // Austria
/*::[*/0x002C/*::]*/: "GB", // United Kingdom
/*::[*/0x002D/*::]*/: "DK", // Denmark
/*::[*/0x002E/*::]*/: "SE", // Sweden
/*::[*/0x002F/*::]*/: "NO", // Norway
/*::[*/0x0030/*::]*/: "PL", // Poland
/*::[*/0x0031/*::]*/: "DE", // Germany
/*::[*/0x0034/*::]*/: "MX", // Mexico
/*::[*/0x0037/*::]*/: "BR", // Brazil
/*::[*/0x003d/*::]*/: "AU", // Australia
/*::[*/0x0040/*::]*/: "NZ", // New Zealand
/*::[*/0x0042/*::]*/: "TH", // Thailand
/*::[*/0x0051/*::]*/: "JP", // Japan
/*::[*/0x0052/*::]*/: "KR", // Korea
/*::[*/0x0054/*::]*/: "VN", // Viet Nam
/*::[*/0x0056/*::]*/: "CN", // China
/*::[*/0x005A/*::]*/: "TR", // Turkey
/*::[*/0x0069/*::]*/: "JS", // Ramastan
/*::[*/0x00D5/*::]*/: "DZ", // Algeria
/*::[*/0x00D8/*::]*/: "MA", // Morocco
/*::[*/0x00DA/*::]*/: "LY", // Libya
/*::[*/0x015F/*::]*/: "PT", // Portugal
/*::[*/0x0162/*::]*/: "IS", // Iceland
/*::[*/0x0166/*::]*/: "FI", // Finland
/*::[*/0x01A4/*::]*/: "CZ", // Czech Republic
/*::[*/0x0376/*::]*/: "TW", // Taiwan
/*::[*/0x03C1/*::]*/: "LB", // Lebanon
/*::[*/0x03C2/*::]*/: "JO", // Jordan
/*::[*/0x03C3/*::]*/: "SY", // Syria
/*::[*/0x03C4/*::]*/: "IQ", // Iraq
/*::[*/0x03C5/*::]*/: "KW", // Kuwait
/*::[*/0x03C6/*::]*/: "SA", // Saudi Arabia
/*::[*/0x03CB/*::]*/: "AE", // United Arab Emirates
/*::[*/0x03CC/*::]*/: "IL", // Israel
/*::[*/0x03CE/*::]*/: "QA", // Qatar
/*::[*/0x03D5/*::]*/: "IR", // Iran
/*::[*/0xFFFF/*::]*/: "US" // United States
};
/* [MS-XLS] 2.5.127 */
@ -281,15 +281,15 @@ var XLSIcv = /*#__PURE__*/dup(_XLSIcv);
/* [MS-XLSB] 2.5.97.2 */
var BErr = {
0x00: "#NULL!",
0x07: "#DIV/0!",
0x0F: "#VALUE!",
0x17: "#REF!",
0x1D: "#NAME?",
0x24: "#NUM!",
0x2A: "#N/A",
0x2B: "#GETTING_DATA",
0xFF: "#WTF?"
/*::[*/0x00/*::]*/: "#NULL!",
/*::[*/0x07/*::]*/: "#DIV/0!",
/*::[*/0x0F/*::]*/: "#VALUE!",
/*::[*/0x17/*::]*/: "#REF!",
/*::[*/0x1D/*::]*/: "#NAME?",
/*::[*/0x24/*::]*/: "#NUM!",
/*::[*/0x2A/*::]*/: "#N/A",
/*::[*/0x2B/*::]*/: "#GETTING_DATA",
/*::[*/0xFF/*::]*/: "#WTF?"
};
//var RBErr = evert_num(BErr);
var RBErr = {

View File

@ -18,12 +18,22 @@ var CORE_PROPS/*:Array<Array<string> >*/ = [
["dcterms:modified", "ModifiedDate", 'date']
];
var CORE_PROPS_REGEX/*:Array<RegExp>*/ = /*#__PURE__*/(function() {
var r = new Array(CORE_PROPS.length);
for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i];
var g = "(?:"+ f[0].slice(0,f[0].indexOf(":")) +":)"+ f[0].slice(f[0].indexOf(":")+1);
r[i] = new RegExp("<" + g + "[^>]*>([\\s\\S]*?)<\/" + g + ">");
}
return r;
})();
function parse_core_props(data) {
var p = {};
data = utf8read(data);
for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i], cur = str_match_xml(data, f[0]);
var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
if(cur != null && cur.length > 0) p[f[1]] = unescapexml(cur[1]);
if(f[2] === 'date' && p[f[1]]) p[f[1]] = parseDate(p[f[1]]);
}

View File

@ -71,12 +71,12 @@ function parse_ext_props(data, p, opts) {
data = utf8read(data);
EXT_PROPS.forEach(function(f) {
var xml = (str_match_xml_ns(data, f[0])||[])[1];
var xml = (data.match(matchtag(f[0]))||[])[1];
switch(f[2]) {
case "string": if(xml) p[f[1]] = unescapexml(xml); break;
case "bool": p[f[1]] = xml === "true"; break;
case "raw":
var cur = str_match_xml(data, f[0]);
var cur = data.match(new RegExp("<" + f[0] + "[^>]*>([\\s\\S]*?)<\/" + f[0] + ">"));
if(cur && cur.length > 0) q[f[1]] = cur[1];
break;
}

View File

@ -1,5 +1,5 @@
/* 15.2.12.2 Custom File Properties Part */
var custregex = /<[^<>]+>[^<]*/g;
var custregex = /<[^>]+>[^<]*/g;
function parse_cust_props(data/*:string*/, opts) {
var p = {}, name = "";
var m = data.match(custregex);

View File

@ -233,8 +233,8 @@ function parse_PropertySet(blob, PIDSI) {
/* [MS-OSHARED] 2.3.3.2.3.1.2 + PROPVARIANT */
switch(blob[blob.l]) {
case 0x41 /*VT_BLOB*/: blob.l += 4; val = parse_BLOB(blob); break;
case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/(^|[^\u0000])\u0000+$/,"$1"); break;
case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break;
case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break;
case 0x03 /*VT_I4*/: blob.l += 4; val = blob.read_shift(4, 'i'); break;
case 0x13 /*VT_UI4*/: blob.l += 4; val = blob.read_shift(4); break;
case 0x05 /*VT_R8*/: blob.l += 4; val = blob.read_shift(8, 'f'); break;

View File

@ -1,20 +1,9 @@
/* [MS-XLS] 2.5.19 */
function parse_XLSCell(blob, length, opts)/*:Cell*/ {
function parse_XLSCell(blob/*::, length*/)/*:Cell*/ {
var rw = blob.read_shift(2); // 0-indexed
var col = blob.read_shift(2);
var ret = ({r:rw, c:col, ixfe:0}/*:any*/);
if(opts && opts.biff == 2 || length == 7) {
/* TODO: pass back flags */
var flags = blob.read_shift(1);
ret.ixfe = flags & 0x3F;
blob.l += 2;
/*
var ifntifmt = blob.read_shift(1);
var ifmt = ifntifmt & 0x3f, ifnt = ifntifmt >> 6;
var flags3 = blob.read_shift(1);
*/
} else ret.ixfe = blob.read_shift(2);
return ret;
var ixfe = blob.read_shift(2);
return ({r:rw, c:col, ixfe:ixfe}/*:any*/);
}
function write_XLSCell(R/*:number*/, C/*:number*/, ixfe/*:?number*/, o) {
if(!o) o = new_buf(6);
@ -122,25 +111,25 @@ function parse_FtCf(blob) {
/* [MS-XLS] 2.5.140 - 2.5.154 and friends */
function parse_FtSkip(blob) { blob.l += 2; blob.l += blob.read_shift(2); }
var FtTab = {
0x00: parse_FtSkip, /* FtEnd */
0x04: parse_FtSkip, /* FtMacro */
0x05: parse_FtSkip, /* FtButton */
0x06: parse_FtSkip, /* FtGmo */
0x07: parse_FtCf, /* FtCf */
0x08: parse_FtSkip, /* FtPioGrbit */
0x09: parse_FtSkip, /* FtPictFmla */
0x0A: parse_FtSkip, /* FtCbls */
0x0B: parse_FtSkip, /* FtRbo */
0x0C: parse_FtSkip, /* FtSbs */
0x0D: parse_FtNts, /* FtNts */
0x0E: parse_FtSkip, /* FtSbsFmla */
0x0F: parse_FtSkip, /* FtGboData */
0x10: parse_FtSkip, /* FtEdoData */
0x11: parse_FtSkip, /* FtRboData */
0x12: parse_FtSkip, /* FtCblsData */
0x13: parse_FtSkip, /* FtLbsData */
0x14: parse_FtSkip, /* FtCblsFmla */
0x15: parse_FtCmo
/*::[*/0x00/*::]*/: parse_FtSkip, /* FtEnd */
/*::[*/0x04/*::]*/: parse_FtSkip, /* FtMacro */
/*::[*/0x05/*::]*/: parse_FtSkip, /* FtButton */
/*::[*/0x06/*::]*/: parse_FtSkip, /* FtGmo */
/*::[*/0x07/*::]*/: parse_FtCf, /* FtCf */
/*::[*/0x08/*::]*/: parse_FtSkip, /* FtPioGrbit */
/*::[*/0x09/*::]*/: parse_FtSkip, /* FtPictFmla */
/*::[*/0x0A/*::]*/: parse_FtSkip, /* FtCbls */
/*::[*/0x0B/*::]*/: parse_FtSkip, /* FtRbo */
/*::[*/0x0C/*::]*/: parse_FtSkip, /* FtSbs */
/*::[*/0x0D/*::]*/: parse_FtNts, /* FtNts */
/*::[*/0x0E/*::]*/: parse_FtSkip, /* FtSbsFmla */
/*::[*/0x0F/*::]*/: parse_FtSkip, /* FtGboData */
/*::[*/0x10/*::]*/: parse_FtSkip, /* FtEdoData */
/*::[*/0x11/*::]*/: parse_FtSkip, /* FtRboData */
/*::[*/0x12/*::]*/: parse_FtSkip, /* FtCblsData */
/*::[*/0x13/*::]*/: parse_FtSkip, /* FtLbsData */
/*::[*/0x14/*::]*/: parse_FtSkip, /* FtCblsFmla */
/*::[*/0x15/*::]*/: parse_FtCmo
};
function parse_FtArray(blob, length/*::, ot*/) {
var tgt = blob.l + length;
@ -239,12 +228,6 @@ function parse_WsBool(blob, length, opts) {
/* [MS-XLS] 2.4.28 */
function parse_BoundSheet8(blob, length, opts) {
var name = "";
if(opts.biff == 4) {
name = parse_ShortXLUnicodeString(blob, 0, opts);
if(name.length === 0) name = "Sheet1";
return { name:name };
}
var pos = blob.read_shift(4);
var hidden = blob.read_shift(1) & 0x03;
var dt = blob.read_shift(1);
@ -254,7 +237,7 @@ function parse_BoundSheet8(blob, length, opts) {
case 2: dt = 'Chartsheet'; break;
case 6: dt = 'VBAModule'; break;
}
name = parse_ShortXLUnicodeString(blob, 0, opts);
var name = parse_ShortXLUnicodeString(blob, 0, opts);
if(name.length === 0) name = "Sheet1";
return { pos:pos, hs:hidden, dt:dt, name:name };
}
@ -425,8 +408,8 @@ function write_Font(data, opts) {
}
/* [MS-XLS] 2.4.149 */
function parse_LabelSst(blob, length, opts) {
var cell = parse_XLSCell(blob, length, opts);
function parse_LabelSst(blob) {
var cell = parse_XLSCell(blob);
cell.isst = blob.read_shift(4);
return cell;
}
@ -441,7 +424,8 @@ function write_LabelSst(R/*:number*/, C/*:number*/, v/*:number*/, os/*:number*/
function parse_Label(blob, length, opts) {
if(opts.biffguess && opts.biff == 2) opts.biff = 5;
var target = blob.l + length;
var cell = parse_XLSCell(blob, length, opts);
var cell = parse_XLSCell(blob, 6);
if(opts.biff == 2) blob.l++;
var str = parse_XLUnicodeString(blob, target - blob.l, opts);
cell.val = str;
return cell;
@ -475,19 +459,6 @@ function write_Format(i/*:number*/, f/*:string*/, opts, o) {
return out;
}
var parse_BIFF2Format = parse_XLUnicodeString2;
function write_BIFF2Format(f/*:string*/) {
var o = new_buf(1 + f.length);
o.write_shift(1, f.length);
o.write_shift(f.length, f, "sbcs");
return o;
}
function write_BIFF4Format(f/*:string*/) {
var o = new_buf(3 + f.length);
o.l += 2;
o.write_shift(1, f.length);
o.write_shift(f.length, f, "sbcs");
return o;
}
/* [MS-XLS] 2.4.90 */
function parse_Dimensions(blob, length, opts) {
@ -611,44 +582,6 @@ function write_XF(data, ixfeP, opts, o) {
o.write_shift(2, 0);
return o;
}
function parse_BIFF2XF(blob/*::, length, opts*/) {
var o = {};
o.ifnt = blob.read_shift(1); blob.l++; o.flags = blob.read_shift(1);
o.numFmtId = o.flags & 0x3F; o.flags>>=6;
o.fStyle = 0;
o.data = {}; // TODO
return o;
}
function write_BIFF2XF(xf) {
var o = new_buf(4);
o.l+=2;
o.write_shift(1, xf.numFmtId);
o.l++;
return o;
}
function write_BIFF3XF(xf) {
var o = new_buf(12);
o.l++;
o.write_shift(1, xf.numFmtId);
o.l += 10;
return o;
}
/* TODO: check other fields */
var write_BIFF4XF = write_BIFF3XF;
function parse_BIFF3XF(blob/*::, length, opts*/) {
var o = {};
o.ifnt = blob.read_shift(1); o.numFmtId = blob.read_shift(1); o.flags = blob.read_shift(2);
o.fStyle = (o.flags >> 2) & 0x01;
o.data = {}; // TODO
return o;
}
function parse_BIFF4XF(blob/*::, length, opts*/) {
var o = {};
o.ifnt = blob.read_shift(1); o.numFmtId = blob.read_shift(1); o.flags = blob.read_shift(2);
o.fStyle = (o.flags >> 2) & 0x01;
o.data = {}; // TODO
return o;
}
/* [MS-XLS] 2.4.134 */
function parse_Guts(blob) {
@ -669,7 +602,8 @@ function write_Guts(guts/*:Array<number>*/) {
/* [MS-XLS] 2.4.24 */
function parse_BoolErr(blob, length, opts) {
var cell = parse_XLSCell(blob, 6, opts);
var cell = parse_XLSCell(blob, 6);
if(opts.biff == 2 || length == 9) ++blob.l;
var val = parse_Bes(blob, 2);
cell.val = val;
cell.t = (val === true || val === false) ? 'b' : 'e';
@ -685,7 +619,7 @@ function write_BoolErr(R/*:number*/, C/*:number*/, v, os/*:number*/, opts, t/*:s
/* [MS-XLS] 2.4.180 Number */
function parse_Number(blob, length, opts) {
if(opts.biffguess && opts.biff == 2) opts.biff = 5;
var cell = parse_XLSCell(blob, 6, opts);
var cell = parse_XLSCell(blob, 6);
var xnum = parse_Xnum(blob, 8);
cell.val = xnum;
return cell;
@ -818,34 +752,21 @@ function parse_MTRSettings(blob) {
return [fMTREnabled, fUserSetThreadCount, cUserThreadCount];
}
/* [MS-XLS] 2.5.186 */
/* [MS-XLS] 2.5.186 TODO: BIFF5 */
function parse_NoteSh(blob, length, opts) {
if(opts.biff < 8) return;
var row = blob.read_shift(2), col = blob.read_shift(2);
var flags = blob.read_shift(2), idObj = blob.read_shift(2);
var stAuthor = parse_XLUnicodeString2(blob, 0, opts);
if(opts.biff < 8) blob.read_shift(1);
return [{r:row,c:col}, stAuthor, idObj, flags];
}
/* [MS-XLS] 2.4.179 */
function parse_Note(blob, length, opts) {
if(opts && (opts.biff < 8)) {
var row = blob.read_shift(2), col = blob.read_shift(2);
if(row == 0xFFFF || row == -1) return; // TODO: test continuation
var cch = blob.read_shift(2);
var cmnt = blob.read_shift(Math.min(cch,2048), 'cpstr');
return [{r:row, c:col}, cmnt];
}
/* TODO: Support revisions */
return parse_NoteSh(blob, length, opts);
}
function write_NOTE_BIFF2(text/*:string*/, R/*:number*/, C/*:number*/, len/*?:number*/) {
var o = new_buf(6 + (len || text.length));
o.write_shift(2, R);
o.write_shift(2, C);
o.write_shift(2, len || text.length);
o.write_shift(text.length, text, "sbcs");
return o;
}
/* [MS-XLS] 2.4.168 */
function parse_MergeCells(blob, length)/*:Array<Range>*/ {
@ -1095,50 +1016,43 @@ function parse_ImData(blob) {
return o;
}
function write_BIFF2Cell(out, r/*:number*/, c/*:number*/, ixfe/*:number*/, ifmt/*:number*/) {
if(!out) out = new_buf(7);
out.write_shift(2, r);
out.write_shift(2, c);
out.write_shift(1, ixfe||0/* & 0x3F */);
out.write_shift(1, ifmt||0/* & 0x3F */);
out.write_shift(1, 0);
return out;
}
/* BIFF2_??? where ??? is the name from [XLS] */
function parse_BIFF2STR(blob, length, opts) {
if(opts.biffguess && opts.biff == 5) opts.biff = 2;
var cell = parse_XLSCell(blob, 7, opts);
var cell = parse_XLSCell(blob, 6);
++blob.l;
var str = parse_XLUnicodeString2(blob, length-7, opts);
cell.t = 'str';
cell.val = str;
return cell;
}
function parse_BIFF2NUM(blob, length, opts) {
var cell = parse_XLSCell(blob, 7, opts);
function parse_BIFF2NUM(blob/*::, length*/) {
var cell = parse_XLSCell(blob, 6);
++blob.l;
var num = parse_Xnum(blob, 8);
cell.t = 'n';
cell.val = num;
return cell;
}
function write_BIFF2NUM(r/*:number*/, c/*:number*/, val/*:number*/, ixfe, ifmt) {
function write_BIFF2NUM(r/*:number*/, c/*:number*/, val/*:number*/) {
var out = new_buf(15);
write_BIFF2Cell(out, r, c, ixfe||0, ifmt||0);
write_BIFF2Cell(out, r, c);
out.write_shift(8, val, 'f');
return out;
}
function parse_BIFF2INT(blob, length, opts) {
var cell = parse_XLSCell(blob, 7, opts);
function parse_BIFF2INT(blob) {
var cell = parse_XLSCell(blob, 6);
++blob.l;
var num = blob.read_shift(2);
cell.t = 'n';
cell.val = num;
return cell;
}
function write_BIFF2INT(r/*:number*/, c/*:number*/, val/*:number*/, ixfe/*:number*/, ifmt/*:number*/) {
function write_BIFF2INT(r/*:number*/, c/*:number*/, val/*:number*/) {
var out = new_buf(9);
write_BIFF2Cell(out, r, c, ixfe||0, ifmt||0);
write_BIFF2Cell(out, r, c);
out.write_shift(2, val);
return out;
}
@ -1149,16 +1063,6 @@ function parse_BIFF2STRING(blob) {
return blob.read_shift(cch, 'sbcs-cont');
}
function parse_BIFF2BOOLERR(blob, length, opts) {
var bestart = blob.l + 7;
var cell = parse_XLSCell(blob, 6, opts);
blob.l = bestart;
var val = parse_Bes(blob, 2);
cell.val = val;
cell.t = (val === true || val === false) ? 'b' : 'e';
return cell;
}
/* TODO: convert to BIFF8 font struct */
function parse_BIFF2FONTXTRA(blob, length) {
blob.l += 6; // unknown
@ -1172,7 +1076,7 @@ function parse_BIFF2FONTXTRA(blob, length) {
/* TODO: parse rich text runs */
function parse_RString(blob, length, opts) {
var end = blob.l + length;
var cell = parse_XLSCell(blob, 6, opts);
var cell = parse_XLSCell(blob, 6);
var cch = blob.read_shift(2);
var str = parse_XLUnicodeStringNoCch(blob, cch, opts);
blob.l = end;
@ -1180,10 +1084,3 @@ function parse_RString(blob, length, opts) {
cell.val = str;
return cell;
}
function parse_BIFF4SheetInfo(blob/*::, length, opts*/) {
var flags = blob.read_shift(4);
var cch = blob.read_shift(1), name = blob.read_shift(cch, "sbcs");
if(name.length === 0) name = "Sheet1";
return { flags: flags, name:name };
}

View File

@ -2,60 +2,60 @@ var DBF_SUPPORTED_VERSIONS = [0x02, 0x03, 0x30, 0x31, 0x83, 0x8B, 0x8C, 0xF5];
var DBF = /*#__PURE__*/(function() {
var dbf_codepage_map = {
/* Code Pages Supported by Visual FoxPro */
0x01: 437, 0x02: 850,
0x03: 1252, 0x04: 10000,
0x64: 852, 0x65: 866,
0x66: 865, 0x67: 861,
0x68: 895, 0x69: 620,
0x6A: 737, 0x6B: 857,
0x78: 950, 0x79: 949,
0x7A: 936, 0x7B: 932,
0x7C: 874, 0x7D: 1255,
0x7E: 1256, 0x96: 10007,
0x97: 10029, 0x98: 10006,
0xC8: 1250, 0xC9: 1251,
0xCA: 1254, 0xCB: 1253,
/*::[*/0x01/*::]*/: 437, /*::[*/0x02/*::]*/: 850,
/*::[*/0x03/*::]*/: 1252, /*::[*/0x04/*::]*/: 10000,
/*::[*/0x64/*::]*/: 852, /*::[*/0x65/*::]*/: 866,
/*::[*/0x66/*::]*/: 865, /*::[*/0x67/*::]*/: 861,
/*::[*/0x68/*::]*/: 895, /*::[*/0x69/*::]*/: 620,
/*::[*/0x6A/*::]*/: 737, /*::[*/0x6B/*::]*/: 857,
/*::[*/0x78/*::]*/: 950, /*::[*/0x79/*::]*/: 949,
/*::[*/0x7A/*::]*/: 936, /*::[*/0x7B/*::]*/: 932,
/*::[*/0x7C/*::]*/: 874, /*::[*/0x7D/*::]*/: 1255,
/*::[*/0x7E/*::]*/: 1256, /*::[*/0x96/*::]*/: 10007,
/*::[*/0x97/*::]*/: 10029, /*::[*/0x98/*::]*/: 10006,
/*::[*/0xC8/*::]*/: 1250, /*::[*/0xC9/*::]*/: 1251,
/*::[*/0xCA/*::]*/: 1254, /*::[*/0xCB/*::]*/: 1253,
/* shapefile DBF extension */
0x00: 20127, 0x08: 865,
0x09: 437, 0x0A: 850,
0x0B: 437, 0x0D: 437,
0x0E: 850, 0x0F: 437,
0x10: 850, 0x11: 437,
0x12: 850, 0x13: 932,
0x14: 850, 0x15: 437,
0x16: 850, 0x17: 865,
0x18: 437, 0x19: 437,
0x1A: 850, 0x1B: 437,
0x1C: 863, 0x1D: 850,
0x1F: 852, 0x22: 852,
0x23: 852, 0x24: 860,
0x25: 850, 0x26: 866,
0x37: 850, 0x40: 852,
0x4D: 936, 0x4E: 949,
0x4F: 950, 0x50: 874,
0x57: 1252, 0x58: 1252,
0x59: 1252, 0x6C: 863,
0x86: 737, 0x87: 852,
0x88: 857, 0xCC: 1257,
/*::[*/0x00/*::]*/: 20127, /*::[*/0x08/*::]*/: 865,
/*::[*/0x09/*::]*/: 437, /*::[*/0x0A/*::]*/: 850,
/*::[*/0x0B/*::]*/: 437, /*::[*/0x0D/*::]*/: 437,
/*::[*/0x0E/*::]*/: 850, /*::[*/0x0F/*::]*/: 437,
/*::[*/0x10/*::]*/: 850, /*::[*/0x11/*::]*/: 437,
/*::[*/0x12/*::]*/: 850, /*::[*/0x13/*::]*/: 932,
/*::[*/0x14/*::]*/: 850, /*::[*/0x15/*::]*/: 437,
/*::[*/0x16/*::]*/: 850, /*::[*/0x17/*::]*/: 865,
/*::[*/0x18/*::]*/: 437, /*::[*/0x19/*::]*/: 437,
/*::[*/0x1A/*::]*/: 850, /*::[*/0x1B/*::]*/: 437,
/*::[*/0x1C/*::]*/: 863, /*::[*/0x1D/*::]*/: 850,
/*::[*/0x1F/*::]*/: 852, /*::[*/0x22/*::]*/: 852,
/*::[*/0x23/*::]*/: 852, /*::[*/0x24/*::]*/: 860,
/*::[*/0x25/*::]*/: 850, /*::[*/0x26/*::]*/: 866,
/*::[*/0x37/*::]*/: 850, /*::[*/0x40/*::]*/: 852,
/*::[*/0x4D/*::]*/: 936, /*::[*/0x4E/*::]*/: 949,
/*::[*/0x4F/*::]*/: 950, /*::[*/0x50/*::]*/: 874,
/*::[*/0x57/*::]*/: 1252, /*::[*/0x58/*::]*/: 1252,
/*::[*/0x59/*::]*/: 1252, /*::[*/0x6C/*::]*/: 863,
/*::[*/0x86/*::]*/: 737, /*::[*/0x87/*::]*/: 852,
/*::[*/0x88/*::]*/: 857, /*::[*/0xCC/*::]*/: 1257,
0xFF: 16969
/*::[*/0xFF/*::]*/: 16969
};
var dbf_reverse_map = evert({
0x01: 437, 0x02: 850,
0x03: 1252, 0x04: 10000,
0x64: 852, 0x65: 866,
0x66: 865, 0x67: 861,
0x68: 895, 0x69: 620,
0x6A: 737, 0x6B: 857,
0x78: 950, 0x79: 949,
0x7A: 936, 0x7B: 932,
0x7C: 874, 0x7D: 1255,
0x7E: 1256, 0x96: 10007,
0x97: 10029, 0x98: 10006,
0xC8: 1250, 0xC9: 1251,
0xCA: 1254, 0xCB: 1253,
0x00: 20127
/*::[*/0x01/*::]*/: 437, /*::[*/0x02/*::]*/: 850,
/*::[*/0x03/*::]*/: 1252, /*::[*/0x04/*::]*/: 10000,
/*::[*/0x64/*::]*/: 852, /*::[*/0x65/*::]*/: 866,
/*::[*/0x66/*::]*/: 865, /*::[*/0x67/*::]*/: 861,
/*::[*/0x68/*::]*/: 895, /*::[*/0x69/*::]*/: 620,
/*::[*/0x6A/*::]*/: 737, /*::[*/0x6B/*::]*/: 857,
/*::[*/0x78/*::]*/: 950, /*::[*/0x79/*::]*/: 949,
/*::[*/0x7A/*::]*/: 936, /*::[*/0x7B/*::]*/: 932,
/*::[*/0x7C/*::]*/: 874, /*::[*/0x7D/*::]*/: 1255,
/*::[*/0x7E/*::]*/: 1256, /*::[*/0x96/*::]*/: 10007,
/*::[*/0x97/*::]*/: 10029, /*::[*/0x98/*::]*/: 10006,
/*::[*/0xC8/*::]*/: 1250, /*::[*/0xC9/*::]*/: 1251,
/*::[*/0xCA/*::]*/: 1254, /*::[*/0xCB/*::]*/: 1253,
/*::[*/0x00/*::]*/: 20127
});
/* TODO: find an actual specification */
function dbf_to_aoa(buf, opts)/*:AOA*/ {
@ -118,7 +118,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
var ww = l7 ? 32 : 11;
while(d.l < hend && d[d.l] != 0x0d) {
field = ({}/*:any*/);
field.name = (typeof $cptable !== "undefined" ? $cptable.utils.decode(current_cp, d.slice(d.l, d.l+ww)) : a2s(d.slice(d.l, d.l + ww))).replace(/[\u0000\r\n][\S\s]*$/g,"");
field.name = (typeof $cptable !== "undefined" ? $cptable.utils.decode(current_cp, d.slice(d.l, d.l+ww)) : a2s(d.slice(d.l, d.l + ww))).replace(/[\u0000\r\n].*$/g,"");
d.l += ww;
field.type = String.fromCharCode(d.read_shift(1));
if(ft != 0x02 && !l7) field.offset = d.read_shift(4);
@ -176,13 +176,10 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
switch(fields[C].type) {
case 'C':
// NOTE: it is conventional to write ' / / ' for empty dates
if(s.trim().length) out[R][C] = s.replace(/([^\s])\s+$/,"$1");
if(s.trim().length) out[R][C] = s.replace(/\s+$/,"");
break;
case 'D':
if(s.length === 8) {
out[R][C] = new Date(Date.UTC(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8), 0, 0, 0, 0));
if(!(opts && opts.UTC)) { out[R][C] = utc_to_local(out[R][C]); }
}
if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8));
else out[R][C] = s;
break;
case 'F': out[R][C] = parseFloat(s.trim()); break;
@ -190,7 +187,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
case 'L': switch(s.trim().toUpperCase()) {
case 'Y': case 'T': out[R][C] = true; break;
case 'N': case 'F': out[R][C] = false; break;
case '': case '\x00': case '?': break;
case '': case '?': break;
default: throw new Error("DBF Unrecognized L:|" + s + "|");
} break;
case 'M': /* TODO: handle memo files */
@ -205,12 +202,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
// NOTE: dBASE specs appear to be incorrect
out[R][C] = new Date(dd.read_shift(-8, 'f') - 0x388317533400);
break;
case 'T': {
var hi = dd.read_shift(4), lo = dd.read_shift(4);
if(hi == 0 && lo == 0) break;
out[R][C] = new Date((hi - 0x253D8C) * 0x5265C00 + lo);
if(!(opts && opts.UTC)) out[R][C] = utc_to_local(out[R][C]);
} break;
case 'T': out[R][C] = new Date((dd.read_shift(4) - 0x253D8C) * 0x5265C00 + dd.read_shift(4)); break;
case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4 + (dd.read_shift(4, 'i')/1e4)*Math.pow(2,32); break;
case 'O': out[R][C] = -dd.read_shift(-8, 'f'); break;
case 'B': if(vfp && fields[C].len == 8) { out[R][C] = dd.read_shift(8,'f'); break; }
@ -252,7 +244,6 @@ function dbf_to_workbook(buf, opts)/*:Workbook*/ {
var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 };
function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
if(!ws["!ref"]) throw new Error("Cannot export empty sheet to DBF");
var o = opts || {};
var old_cp = current_codepage;
if(+o.codepage >= 0) set_cp(+o.codepage);
@ -404,21 +395,16 @@ var SYLK = /*#__PURE__*/(function() {
KC:'Ç', Kc:'ç', q:'æ', z:'œ', a:'Æ', j:'Œ',
DN:209, Dn:241, Hy:255,
S:169, c:170, R:174, "B ":180,
0:176, 1:177, 2:178,
3:179, 5:181, 6:182,
7:183, Q:185, k:186, b:208, i:216, l:222, s:240, y:248,
/*::[*/0/*::]*/:176, /*::[*/1/*::]*/:177, /*::[*/2/*::]*/:178,
/*::[*/3/*::]*/:179, /*::[*/5/*::]*/:181, /*::[*/6/*::]*/:182,
/*::[*/7/*::]*/:183, Q:185, k:186, b:208, i:216, l:222, s:240, y:248,
"!":161, '"':162, "#":163, "(":164, "%":165, "'":167, "H ":168,
"+":171, ";":187, "<":188, "=":189, ">":190, "?":191, "{":223
}/*:any*/);
var sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1").replace("{", "\\{") + "|\\|)", "gm");
try {
sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1") + "|\\|)", "gm");
} catch(e) {}
var sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1") + "|\\|)", "gm");
var sylk_char_fn = function(_, $1){ var o = sylk_escapes[$1]; return typeof o == "number" ? _getansi(o) : o; };
var decode_sylk_char = function($$, $1, $2) { var newcc = (($1.charCodeAt(0) - 0x20)<<4) | ($2.charCodeAt(0) - 0x30); return newcc == 59 ? $$ : _getansi(newcc); };
sylk_escapes["|"] = 254;
/* TODO: evert the escape map */
var encode_sylk_str = function($$) { return $$.replace(/\n/g, "\x1b :").replace(/\r/g, "\x1b ="); };
/* https://oss.sheetjs.com/notes/sylk/ for more details */
function sylk_to_aoa(d/*:RawData*/, opts)/*:[AOA, Worksheet]*/ {
switch(opts.type) {
@ -471,9 +457,8 @@ var SYLK = /*#__PURE__*/(function() {
// case 'NU': // ??
case 'C': /* cell */
var C_seen_K = false, C_seen_X = false, C_seen_S = false, C_seen_E = false, _R = -1, _C = -1, formula = "", cell_t = "z";
var cmnt = "";
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
case 'A': cmnt = record[rj].slice(1); break; // TODO: comment
case 'A': break; // TODO: comment
case 'X': C = parseInt(record[rj].slice(1), 10)-1; C_seen_X = true; break;
case 'Y':
R = parseInt(record[rj].slice(1), 10)-1; if(!C_seen_X) C = 0;
@ -483,12 +468,12 @@ var SYLK = /*#__PURE__*/(function() {
val = record[rj].slice(1);
if(val.charAt(0) === '"') { val = val.slice(1,val.length - 1); cell_t = "s"; }
else if(val === 'TRUE' || val === 'FALSE') { val = val === 'TRUE'; cell_t = "b"; }
else if(val.charAt(0) == "#" && RBErr[val] != null) { cell_t = "e"; val = RBErr[val]; }
else if(!isNaN(fuzzynum(val))) {
val = fuzzynum(val); cell_t = "n";
if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) {
val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : val); cell_t = typeof val == "number" ? "n" : "d";
}
if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) { val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : val); cell_t = "d"; }
} else if(!isNaN(fuzzydate(val).getDate())) {
val = parseDate(val); cell_t = "d";
if(!opts.cellDates) { cell_t = "n"; val = datenum(val, wb.Workbook.WBProps.date1904); }
}
if(typeof $cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = $cptable.utils.decode(opts.codepage, val);
C_seen_K = true;
@ -524,10 +509,6 @@ var SYLK = /*#__PURE__*/(function() {
if(!arr[R][C]) arr[R][C] = { t: 'n', f: formula };
else arr[R][C].f = formula;
}
if(cmnt) {
if(!arr[R][C]) arr[R][C] = { t: 'z' };
arr[R][C].c = [{a:"SheetJSYLK", t: cmnt}];
}
break;
case 'F': /* Format */
var F_seen = 0;
@ -589,27 +570,20 @@ var SYLK = /*#__PURE__*/(function() {
return outwb;
}
function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/)/*:string*/ {
function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*//*::, opts*/)/*:string*/ {
var o = "C;Y" + (R+1) + ";X" + (C+1) + ";K";
switch(cell.t) {
case 'n':
o += (cell.v||0);
if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break;
case 'b': o += cell.v ? "TRUE" : "FALSE"; break;
case 'e': o += cell.w || BErr[cell.v] || cell.v; break;
case 'd': o += datenum(parseDate(cell.v, date1904), date1904); break;
case 'e': o += cell.w || cell.v; break;
case 'd': o += '"' + (cell.w || cell.v) + '"'; break;
case 's': o += '"' + (cell.v == null ? "" : String(cell.v)).replace(/"/g,"").replace(/;/g, ";;") + '"'; break;
}
return o;
}
function write_ws_cmnt_sylk(cmnt/*:Comment*/, R/*:number*/, C/*:number*/)/*:string*/ {
var o = "C;Y" + (R+1) + ";X" + (C+1) + ";A";
/* TODO: max length? */
o += encode_sylk_str(cmnt.map(function(c) { return c.t; }).join(""));
return o;
}
function write_ws_cols_sylk(out, cols) {
cols.forEach(function(col, i) {
var rec = "F;W" + (i+1) + " " + (i+1) + " ";
@ -634,52 +608,30 @@ var SYLK = /*#__PURE__*/(function() {
}
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/, wb/*:?WorkBook*/)/*:string*/ {
if(!opts) opts = {}; opts._formats = ["General"];
/* TODO: codepage */
var preamble/*:Array<string>*/ = ["ID;PSheetJS;N;E"], o/*:Array<string>*/ = [];
var r = safe_decode_range(ws['!ref']||"A1"), cell/*:Cell*/;
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = ws["!data"] != null;
var RS = "\r\n";
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
var _lastfmt = "General";
preamble.push("P;PGeneral");
/* Excel has been inconsistent in comment placement */
var R = r.s.r, C = r.s.c, p = [];
if(ws["!ref"]) for(R = r.s.r; R <= r.e.r; ++R) {
if(dense && !ws["!data"][R]) continue;
p = [];
for(C = r.s.c; C <= r.e.c; ++C) {
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
if(!cell || !cell.c) continue;
p.push(write_ws_cmnt_sylk(cell.c, R, C));
}
if(p.length) o.push(p.join(RS));
}
if(ws["!ref"]) for(R = r.s.r; R <= r.e.r; ++R) {
if(dense && !ws["!data"][R]) continue;
p = [];
for(C = r.s.c; C <= r.e.c; ++C) {
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
if((cell.z||(cell.t == "d" ? table_fmt[14] : "General")) != _lastfmt) {
var ifmt = opts._formats.indexOf(cell.z);
if(ifmt == -1) { opts._formats.push(cell.z); ifmt = opts._formats.length - 1; preamble.push("P;P" + cell.z.replace(/;/g, ";;")); }
p.push("F;P" + ifmt + ";Y" + (R+1) + ";X" + (C+1));
}
p.push(write_ws_cell_sylk(cell, ws, R, C, opts, d1904));
}
o.push(p.join(RS));
}
preamble.push("F;P0;DG0G8;M255");
if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
if(ws["!ref"]) 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("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");
delete opts._formats;
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) {
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
}
o.push(p.join(RS));
}
return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
}
@ -719,10 +671,7 @@ var DIF = /*#__PURE__*/(function() {
if(data === 'TRUE') arr[R][C] = true;
else if(data === 'FALSE') arr[R][C] = false;
else if(!isNaN(fuzzynum(value))) arr[R][C] = fuzzynum(value);
else if(!isNaN(fuzzydate(value).getDate())) {
arr[R][C] = parseDate(value);
if(!(opts && opts.UTC)) { arr[R][C] = utc_to_local(arr[R][C]); }
}
else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value);
else arr[R][C] = value;
++C; break;
case 1:
@ -749,7 +698,6 @@ var DIF = /*#__PURE__*/(function() {
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;
if(!ws["!ref"]) throw new Error("Cannot export empty sheet to DIF");
var r = safe_decode_range(ws['!ref']);
var dense = ws["!data"] != null;
var o/*:Array<string>*/ = [
@ -941,18 +889,18 @@ var PRN = /*#__PURE__*/(function() {
// List of accepted CSV separators
var guess_seps = {
0x2C: ',',
0x09: "\t",
0x3B: ';',
0x7C: '|'
/*::[*/0x2C/*::]*/: ',',
/*::[*/0x09/*::]*/: "\t",
/*::[*/0x3B/*::]*/: ';',
/*::[*/0x7C/*::]*/: '|'
};
// CSV separator weights to be used in case of equal numbers
var guess_sep_weights = {
0x2C: 3,
0x09: 2,
0x3B: 1,
0x7C: 0
/*::[*/0x2C/*::]*/: 3,
/*::[*/0x09/*::]*/: 2,
/*::[*/0x3B/*::]*/: 1,
/*::[*/0x7C/*::]*/: 0
};
function guess_sep(str) {
@ -1004,28 +952,26 @@ var PRN = /*#__PURE__*/(function() {
var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0);
var _re/*:?RegExp*/ = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
function finish_cell() {
/* TODO: fuzzy parsers should pass back assumed number format */
var s = str.slice(start, end); if(s.slice(-1) == "\r") s = s.slice(0, -1);
var cell = ({}/*:any*/);
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
if(o.cellText !== false) cell.w = s;
if(s.length === 0) cell.t = 'z';
else if(o.raw) { cell.t = 's'; cell.v = s; }
else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; }
else if(s.charCodeAt(0) == 0x3D) {
if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); }
else if(fuzzyfmla(s)) { cell.t = 's'; cell.f = s.slice(1); cell.v = s; }
else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.slice(1); }
else { cell.t = 's'; cell.v = s; } }
else if(s == "TRUE") { cell.t = 'b'; cell.v = true; }
else if(s == "FALSE") { cell.t = 'b'; cell.v = false; }
else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; cell.v = v; }
else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; if(o.cellText !== false) cell.w = s; cell.v = v; }
else if(!isNaN((v = fuzzydate(s)).getDate()) || _re && s.match(_re)) {
cell.z = o.dateNF || table_fmt[14];
if(_re && s.match(_re)){ var news=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); v = parseDate(news); if(o && o.UTC === false) v = utc_to_local(v); }
else if(o && o.UTC === false) v = utc_to_local(v);
else if(o.cellText !== false && o.dateNF) cell.w = SSF_format(cell.z, v);
var k = 0;
if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; v = parseDate(s, k); }
if(o.cellDates) { cell.t = 'd'; cell.v = v; }
else { cell.t = 'n'; cell.v = datenum(v); }
if(o.cellText !== false) cell.w = SSF_format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v);
if(!o.cellNF) delete cell.z;
} else {
cell.t = 's';
@ -1087,7 +1033,6 @@ var PRN = /*#__PURE__*/(function() {
function sheet_to_prn(ws/*:Worksheet*//*::, opts:?any*/)/*:string*/ {
var o/*:Array<string>*/ = [];
if(!ws["!ref"]) return "";
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = ws["!data"] != null;
for(var R = r.s.r; R <= r.e.r; ++R) {
@ -1121,7 +1066,7 @@ function read_wb_ID(d, opts) {
return out;
} catch(e) {
o.WTF = OLD_WTF;
if((e.message.indexOf("SYLK bad record ID") == -1) && OLD_WTF) throw e;
if(!e.message.match(/SYLK bad record ID/) && OLD_WTF) throw e;
return PRN.to_workbook(d, opts);
}
}

View File

@ -24,22 +24,6 @@ var WK_ = /*#__PURE__*/(function() {
throw "Unsupported type " + opts.type;
}
/* NOTE: this list intentionally starts at 1 */
var LOTUS_DATE_FMTS = [
"mmmm",
"dd-mmm-yyyy",
"dd-mmm",
"mmm-yyyy",
"@", // "text"?
"mm/dd",
"hh:mm:ss AM/PM", // 7
"hh:mm AM/PM",
"mm/dd/yyyy",
"mm/dd",
"hh:mm:ss",
"hh:mm" // 12
];
function lotus_to_workbook_buf(d, opts)/*:Workbook*/ {
if(!d) return d;
var o = opts || {};
@ -50,7 +34,6 @@ var WK_ = /*#__PURE__*/(function() {
var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
var sheetRows = o.sheetRows || 0;
var lastcell = {};
if(d[4] == 0x51 && d[5] == 0x50 && d[6] == 0x57) return qpw_to_workbook_buf(d, opts);
if(d[2] == 0x00) {
@ -82,9 +65,9 @@ var WK_ = /*#__PURE__*/(function() {
case 0x0E: /* NUMBER */
case 0x10: /* FORMULA */
/* TODO: actual translation of the format code */
if((val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) {
val[1].z = o.dateNF || LOTUS_DATE_FMTS[(val[2] & 0x0F)-1] || table_fmt[14];
if(o.cellDates) { val[1].v = numdate(val[1].v); val[1].t = typeof val[1].v == "number" ? 'n' : 'd'; }
if(RT == 0x0E && (val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) {
val[1].z = o.dateNF || table_fmt[14];
if(o.cellDates) { val[1].t = 'd'; val[1].v = numdate(val[1].v); }
}
if(o.qpro) {
@ -103,25 +86,15 @@ var WK_ = /*#__PURE__*/(function() {
tmpcell.t = val[1].t; tmpcell.v = val[1].v;
if(val[1].z != null) tmpcell.z = val[1].z;
if(val[1].f != null) tmpcell.f = val[1].f;
lastcell = tmpcell;
break;
}
if(o.dense) {
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];
lastcell = val[1];
break;
case 0x5405: o.works2 = true; break;
case 0x5402: {
/* TODO: enumerate all extended number formats */
if(val == 0x14a1) {
lastcell.z = "hh:mm:ss";
if(o.cellDates && lastcell.t == "n") {
lastcell.v = numdate(lastcell.v); lastcell.t = typeof lastcell.v == "number" ? 'n' : 'd';
}
}
} break;
default:
}}, o);
} else if(d[2] == 0x1A || d[2] == 0x0E) {
o.Enum = WK3Enum;
@ -184,7 +157,6 @@ var WK_ = /*#__PURE__*/(function() {
if(+o.codepage >= 0) set_cp(+o.codepage);
if(o.type == "string") throw new Error("Cannot write WK1 to JS string");
var ba = buf_array();
if(!ws["!ref"]) throw new Error("Cannot export empty sheet to WK1");
var range = safe_decode_range(ws["!ref"]);
var dense = ws["!data"] != null;
var cols = [];
@ -199,17 +171,10 @@ var WK_ = /*#__PURE__*/(function() {
var cell = dense ? (ws["!data"][R]||[])[C] : ws[cols[C] + rr];
if(!cell || cell.t == "z") continue;
/* TODO: formula records */
switch(cell.t) {
case "n":
if((cell.v|0)==cell.v && cell.v >= -32768 && cell.v <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, cell));
else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, cell));
break;
case "d":
var dc = datenum(cell.v);
if((dc|0)==dc && dc >= -32768 && dc <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, {t:"n", v:dc, z:cell.z || table_fmt[14]}));
else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, {t:"n", v:dc, z:cell.z || table_fmt[14]}));
break;
default:
if(cell.t == "n") {
if((cell.v|0)==cell.v && cell.v >= -32768 && cell.v <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, cell.v));
else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, cell.v));
} else {
var str = format_cell(cell);
write_biff_rec(ba, 0x0F, write_LABEL(R, C, str.slice(0, 239)));
}
@ -343,18 +308,11 @@ var WK_ = /*#__PURE__*/(function() {
return o;
}
function get_wk1_fmt(cell)/*:number*/ {
/* TODO: some fuzzy matching on the number format */
if(cell.z && fmt_is_date(cell.z)) {
return 0xf0 | (LOTUS_DATE_FMTS.indexOf(cell.z) + 1 || 2);
}
return 0xFF;
}
function parse_LABEL(blob, length, opts) {
var tgt = blob.l + length;
var o = parse_cell(blob, length, opts);
o[1].t = 's';
if((opts.vers & 0xFFFE) == 0x5120) { // WQ1 / WQ2
if(opts.vers == 0x5120) {
blob.l++;
var len = blob.read_shift(1);
o[1].v = blob.read_shift(len, 'utf8');
@ -396,12 +354,12 @@ var WK_ = /*#__PURE__*/(function() {
o[1].v = blob.read_shift(2, 'i');
return o;
}
function write_INTEGER(R, C, cell) {
function write_INTEGER(R, C, v) {
var o = new_buf(7);
o.write_shift(1, get_wk1_fmt(cell));
o.write_shift(1, 0xFF);
o.write_shift(2, C);
o.write_shift(2, R);
o.write_shift(2, cell.v, 'i');
o.write_shift(2, v, 'i');
return o;
}
@ -410,12 +368,12 @@ var WK_ = /*#__PURE__*/(function() {
o[1].v = blob.read_shift(8, 'f');
return o;
}
function write_NUMBER(R, C, cell) {
function write_NUMBER(R, C, v) {
var o = new_buf(13);
o.write_shift(1, get_wk1_fmt(cell));
o.write_shift(1, 0xFF);
o.write_shift(2, C);
o.write_shift(2, R);
o.write_shift(8, cell.v, 'f');
o.write_shift(8, v, 'f');
return o;
}
@ -468,7 +426,7 @@ var WK_ = /*#__PURE__*/(function() {
0x33: ["FALSE", 0],
0x34: ["TRUE", 0],
0x35: ["RAND", 0],
0x36: ["DATE", 3],
// 0x36 DATE
// 0x37 NOW
// 0x38 PMT
// 0x39 PV
@ -478,7 +436,7 @@ var WK_ = /*#__PURE__*/(function() {
// 0x3D MONTH
// 0x3E YEAR
0x3F: ["ROUND", 2],
0x40: ["TIME", 3],
// 0x40 TIME
// 0x41 HOUR
// 0x42 MINUTE
// 0x43 SECOND
@ -763,240 +721,199 @@ var WK_ = /*#__PURE__*/(function() {
}
var WK1Enum = {
0x0000: { n:"BOF", f:parseuint16 },
0x0001: { n:"EOF" },
0x0002: { n:"CALCMODE" },
0x0003: { n:"CALCORDER" },
0x0004: { n:"SPLIT" },
0x0005: { n:"SYNC" },
0x0006: { n:"RANGE", f:parse_RANGE },
0x0007: { n:"WINDOW1" },
0x0008: { n:"COLW1" },
0x0009: { n:"WINTWO" },
0x000A: { n:"COLW2" },
0x000B: { n:"NAME" },
0x000C: { n:"BLANK" },
0x000D: { n:"INTEGER", f:parse_INTEGER },
0x000E: { n:"NUMBER", f:parse_NUMBER },
0x000F: { n:"LABEL", f:parse_LABEL },
0x0010: { n:"FORMULA", f:parse_FORMULA },
0x0018: { n:"TABLE" },
0x0019: { n:"ORANGE" },
0x001A: { n:"PRANGE" },
0x001B: { n:"SRANGE" },
0x001C: { n:"FRANGE" },
0x001D: { n:"KRANGE1" },
0x0020: { n:"HRANGE" },
0x0023: { n:"KRANGE2" },
0x0024: { n:"PROTEC" },
0x0025: { n:"FOOTER" },
0x0026: { n:"HEADER" },
0x0027: { n:"SETUP" },
0x0028: { n:"MARGINS" },
0x0029: { n:"LABELFMT" },
0x002A: { n:"TITLES" },
0x002B: { n:"SHEETJS" },
0x002D: { n:"GRAPH" },
0x002E: { n:"NGRAPH" },
0x002F: { n:"CALCCOUNT" },
0x0030: { n:"UNFORMATTED" },
0x0031: { n:"CURSORW12" },
0x0032: { n:"WINDOW" },
0x0033: { n:"STRING", f:parse_STRING },
0x0037: { n:"PASSWORD" },
0x0038: { n:"LOCKED" },
0x003C: { n:"QUERY" },
0x003D: { n:"QUERYNAME" },
0x003E: { n:"PRINT" },
0x003F: { n:"PRINTNAME" },
0x0040: { n:"GRAPH2" },
0x0041: { n:"GRAPHNAME" },
0x0042: { n:"ZOOM" },
0x0043: { n:"SYMSPLIT" },
0x0044: { n:"NSROWS" },
0x0045: { n:"NSCOLS" },
0x0046: { n:"RULER" },
0x0047: { n:"NNAME" },
0x0048: { n:"ACOMM" },
0x0049: { n:"AMACRO" },
0x004A: { n:"PARSE" },
// 0x0064
0x0066: { n:"PRANGES??" },
0x0067: { n:"RRANGES??" },
0x0068: { n:"FNAME??" },
0x0069: { n:"MRANGES??" },
// 0x0096
// 0x0099
// 0x009A
// 0x009B
// 0x009C
// 0x00C0
// 0x00C7
// 0x00C9
0x00CC: { n:"SHEETNAMECS", f:parse_SHEETNAMECS },
// 0x00CD
0x00DE: { n:"SHEETNAMELP", f:parse_SHEETNAMELP },
0x00FF: { n:"BOF", f:parseuint16 },
0x5402: { n:"WKSNF", f:parseuint16 },
0xFFFF: { n:"" }
/*::[*/0x0000/*::]*/: { n:"BOF", f:parseuint16 },
/*::[*/0x0001/*::]*/: { n:"EOF" },
/*::[*/0x0002/*::]*/: { n:"CALCMODE" },
/*::[*/0x0003/*::]*/: { n:"CALCORDER" },
/*::[*/0x0004/*::]*/: { n:"SPLIT" },
/*::[*/0x0005/*::]*/: { n:"SYNC" },
/*::[*/0x0006/*::]*/: { n:"RANGE", f:parse_RANGE },
/*::[*/0x0007/*::]*/: { n:"WINDOW1" },
/*::[*/0x0008/*::]*/: { n:"COLW1" },
/*::[*/0x0009/*::]*/: { n:"WINTWO" },
/*::[*/0x000A/*::]*/: { n:"COLW2" },
/*::[*/0x000B/*::]*/: { n:"NAME" },
/*::[*/0x000C/*::]*/: { n:"BLANK" },
/*::[*/0x000D/*::]*/: { n:"INTEGER", f:parse_INTEGER },
/*::[*/0x000E/*::]*/: { n:"NUMBER", f:parse_NUMBER },
/*::[*/0x000F/*::]*/: { n:"LABEL", f:parse_LABEL },
/*::[*/0x0010/*::]*/: { n:"FORMULA", f:parse_FORMULA },
/*::[*/0x0018/*::]*/: { n:"TABLE" },
/*::[*/0x0019/*::]*/: { n:"ORANGE" },
/*::[*/0x001A/*::]*/: { n:"PRANGE" },
/*::[*/0x001B/*::]*/: { n:"SRANGE" },
/*::[*/0x001C/*::]*/: { n:"FRANGE" },
/*::[*/0x001D/*::]*/: { n:"KRANGE1" },
/*::[*/0x0020/*::]*/: { n:"HRANGE" },
/*::[*/0x0023/*::]*/: { n:"KRANGE2" },
/*::[*/0x0024/*::]*/: { n:"PROTEC" },
/*::[*/0x0025/*::]*/: { n:"FOOTER" },
/*::[*/0x0026/*::]*/: { n:"HEADER" },
/*::[*/0x0027/*::]*/: { n:"SETUP" },
/*::[*/0x0028/*::]*/: { n:"MARGINS" },
/*::[*/0x0029/*::]*/: { n:"LABELFMT" },
/*::[*/0x002A/*::]*/: { n:"TITLES" },
/*::[*/0x002B/*::]*/: { n:"SHEETJS" },
/*::[*/0x002D/*::]*/: { n:"GRAPH" },
/*::[*/0x002E/*::]*/: { n:"NGRAPH" },
/*::[*/0x002F/*::]*/: { n:"CALCCOUNT" },
/*::[*/0x0030/*::]*/: { n:"UNFORMATTED" },
/*::[*/0x0031/*::]*/: { n:"CURSORW12" },
/*::[*/0x0032/*::]*/: { n:"WINDOW" },
/*::[*/0x0033/*::]*/: { n:"STRING", f:parse_STRING },
/*::[*/0x0037/*::]*/: { n:"PASSWORD" },
/*::[*/0x0038/*::]*/: { n:"LOCKED" },
/*::[*/0x003C/*::]*/: { n:"QUERY" },
/*::[*/0x003D/*::]*/: { n:"QUERYNAME" },
/*::[*/0x003E/*::]*/: { n:"PRINT" },
/*::[*/0x003F/*::]*/: { n:"PRINTNAME" },
/*::[*/0x0040/*::]*/: { n:"GRAPH2" },
/*::[*/0x0041/*::]*/: { n:"GRAPHNAME" },
/*::[*/0x0042/*::]*/: { n:"ZOOM" },
/*::[*/0x0043/*::]*/: { n:"SYMSPLIT" },
/*::[*/0x0044/*::]*/: { n:"NSROWS" },
/*::[*/0x0045/*::]*/: { n:"NSCOLS" },
/*::[*/0x0046/*::]*/: { n:"RULER" },
/*::[*/0x0047/*::]*/: { n:"NNAME" },
/*::[*/0x0048/*::]*/: { n:"ACOMM" },
/*::[*/0x0049/*::]*/: { n:"AMACRO" },
/*::[*/0x004A/*::]*/: { n:"PARSE" },
/*::[*/0x0066/*::]*/: { n:"PRANGES??" },
/*::[*/0x0067/*::]*/: { n:"RRANGES??" },
/*::[*/0x0068/*::]*/: { n:"FNAME??" },
/*::[*/0x0069/*::]*/: { n:"MRANGES??" },
/*::[*/0x00CC/*::]*/: { n:"SHEETNAMECS", f:parse_SHEETNAMECS },
/*::[*/0x00DE/*::]*/: { n:"SHEETNAMELP", f:parse_SHEETNAMELP },
/*::[*/0x00FF/*::]*/: { n:"BOF", f:parseuint16 },
/*::[*/0xFFFF/*::]*/: { n:"" }
};
var WK3Enum = {
0x0000: { n:"BOF" },
0x0001: { n:"EOF" },
0x0002: { n:"PASSWORD" },
0x0003: { n:"CALCSET" },
0x0004: { n:"WINDOWSET" },
0x0005: { n:"SHEETCELLPTR" },
0x0006: { n:"SHEETLAYOUT" },
0x0007: { n:"COLUMNWIDTH" },
0x0008: { n:"HIDDENCOLUMN" },
0x0009: { n:"USERRANGE" },
0x000A: { n:"SYSTEMRANGE" },
0x000B: { n:"ZEROFORCE" },
0x000C: { n:"SORTKEYDIR" },
0x000D: { n:"FILESEAL" },
0x000E: { n:"DATAFILLNUMS" },
0x000F: { n:"PRINTMAIN" },
0x0010: { n:"PRINTSTRING" },
0x0011: { n:"GRAPHMAIN" },
0x0012: { n:"GRAPHSTRING" },
0x0013: { n:"??" },
0x0014: { n:"ERRCELL" },
0x0015: { n:"NACELL" },
0x0016: { n:"LABEL16", f:parse_LABEL_16},
0x0017: { n:"NUMBER17", f:parse_NUMBER_17 },
0x0018: { n:"NUMBER18", f:parse_NUMBER_18 },
0x0019: { n:"FORMULA19", f:parse_FORMULA_19},
0x001A: { n:"FORMULA1A" },
0x001B: { n:"XFORMAT", f:parse_XFORMAT },
0x001C: { n:"DTLABELMISC" },
0x001D: { n:"DTLABELCELL" },
0x001E: { n:"GRAPHWINDOW" },
0x001F: { n:"CPA" },
0x0020: { n:"LPLAUTO" },
0x0021: { n:"QUERY" },
0x0022: { n:"HIDDENSHEET" },
0x0023: { n:"??" },
0x0025: { n:"NUMBER25", f:parse_NUMBER_25 },
0x0026: { n:"??" },
0x0027: { n:"NUMBER27", f:parse_NUMBER_27 },
0x0028: { n:"FORMULA28", f:parse_FORMULA_28 },
0x008E: { n:"??" },
0x0093: { n:"??" },
0x0096: { n:"??" },
0x0097: { n:"??" },
0x0098: { n:"??" },
0x0099: { n:"??" },
0x009A: { n:"??" },
0x009B: { n:"??" },
0x009C: { n:"??" },
0x00A3: { n:"??" },
0x00AE: { n:"??" },
0x00AF: { n:"??" },
0x00B0: { n:"??" },
0x00B1: { n:"??" },
0x00B8: { n:"??" },
0x00B9: { n:"??" },
0x00BA: { n:"??" },
0x00BB: { n:"??" },
0x00BC: { n:"??" },
0x00C3: { n:"??" },
0x00C9: { n:"??" },
0x00CC: { n:"SHEETNAMECS", f:parse_SHEETNAMECS },
0x00CD: { n:"??" },
0x00CE: { n:"??" },
0x00CF: { n:"??" },
0x00D0: { n:"??" },
0x0100: { n:"??" },
0x0103: { n:"??" },
0x0104: { n:"??" },
0x0105: { n:"??" },
0x0106: { n:"??" },
0x0107: { n:"??" },
0x0109: { n:"??" },
0x010A: { n:"??" },
0x010B: { n:"??" },
0x010C: { n:"??" },
0x010E: { n:"??" },
0x010F: { n:"??" },
0x0180: { n:"??" },
0x0185: { n:"??" },
0x0186: { n:"??" },
0x0189: { n:"??" },
0x018C: { n:"??" },
0x0200: { n:"??" },
0x0202: { n:"??" },
0x0201: { n:"??" },
0x0204: { n:"??" },
0x0205: { n:"??" },
0x0280: { n:"??" },
0x0281: { n:"??" },
0x0282: { n:"??" },
0x0283: { n:"??" },
0x0284: { n:"??" },
0x0285: { n:"??" },
0x0286: { n:"??" },
0x0287: { n:"??" },
0x0288: { n:"??" },
0x0292: { n:"??" },
0x0293: { n:"??" },
0x0294: { n:"??" },
0x0295: { n:"??" },
0x0296: { n:"??" },
0x0299: { n:"??" },
0x029A: { n:"??" },
0x0300: { n:"??" },
0x0304: { n:"??" },
0x0601: { n:"SHEETINFOQP", f:parse_SHEETINFOQP },
0x0640: { n:"??" },
0x0642: { n:"??" },
0x0701: { n:"??" },
0x0702: { n:"??" },
0x0703: { n:"??" },
0x0704: { n:"??" },
0x0780: { n:"??" },
0x0800: { n:"??" },
0x0801: { n:"??" },
0x0804: { n:"??" },
0x0A80: { n:"??" },
0x2AF6: { n:"??" },
0x3231: { n:"??" },
0x6E49: { n:"??" },
0x6F44: { n:"??" },
0xFFFF: { n:"" }
/*::[*/0x0000/*::]*/: { n:"BOF" },
/*::[*/0x0001/*::]*/: { n:"EOF" },
/*::[*/0x0002/*::]*/: { n:"PASSWORD" },
/*::[*/0x0003/*::]*/: { n:"CALCSET" },
/*::[*/0x0004/*::]*/: { n:"WINDOWSET" },
/*::[*/0x0005/*::]*/: { n:"SHEETCELLPTR" },
/*::[*/0x0006/*::]*/: { n:"SHEETLAYOUT" },
/*::[*/0x0007/*::]*/: { n:"COLUMNWIDTH" },
/*::[*/0x0008/*::]*/: { n:"HIDDENCOLUMN" },
/*::[*/0x0009/*::]*/: { n:"USERRANGE" },
/*::[*/0x000A/*::]*/: { n:"SYSTEMRANGE" },
/*::[*/0x000B/*::]*/: { n:"ZEROFORCE" },
/*::[*/0x000C/*::]*/: { n:"SORTKEYDIR" },
/*::[*/0x000D/*::]*/: { n:"FILESEAL" },
/*::[*/0x000E/*::]*/: { n:"DATAFILLNUMS" },
/*::[*/0x000F/*::]*/: { n:"PRINTMAIN" },
/*::[*/0x0010/*::]*/: { n:"PRINTSTRING" },
/*::[*/0x0011/*::]*/: { n:"GRAPHMAIN" },
/*::[*/0x0012/*::]*/: { n:"GRAPHSTRING" },
/*::[*/0x0013/*::]*/: { n:"??" },
/*::[*/0x0014/*::]*/: { n:"ERRCELL" },
/*::[*/0x0015/*::]*/: { n:"NACELL" },
/*::[*/0x0016/*::]*/: { n:"LABEL16", f:parse_LABEL_16},
/*::[*/0x0017/*::]*/: { n:"NUMBER17", f:parse_NUMBER_17 },
/*::[*/0x0018/*::]*/: { n:"NUMBER18", f:parse_NUMBER_18 },
/*::[*/0x0019/*::]*/: { n:"FORMULA19", f:parse_FORMULA_19},
/*::[*/0x001A/*::]*/: { n:"FORMULA1A" },
/*::[*/0x001B/*::]*/: { n:"XFORMAT", f:parse_XFORMAT },
/*::[*/0x001C/*::]*/: { n:"DTLABELMISC" },
/*::[*/0x001D/*::]*/: { n:"DTLABELCELL" },
/*::[*/0x001E/*::]*/: { n:"GRAPHWINDOW" },
/*::[*/0x001F/*::]*/: { n:"CPA" },
/*::[*/0x0020/*::]*/: { n:"LPLAUTO" },
/*::[*/0x0021/*::]*/: { n:"QUERY" },
/*::[*/0x0022/*::]*/: { n:"HIDDENSHEET" },
/*::[*/0x0023/*::]*/: { n:"??" },
/*::[*/0x0025/*::]*/: { n:"NUMBER25", f:parse_NUMBER_25 },
/*::[*/0x0026/*::]*/: { n:"??" },
/*::[*/0x0027/*::]*/: { n:"NUMBER27", f:parse_NUMBER_27 },
/*::[*/0x0028/*::]*/: { n:"FORMULA28", f:parse_FORMULA_28 },
/*::[*/0x008E/*::]*/: { n:"??" },
/*::[*/0x0093/*::]*/: { n:"??" },
/*::[*/0x0096/*::]*/: { n:"??" },
/*::[*/0x0097/*::]*/: { n:"??" },
/*::[*/0x0098/*::]*/: { n:"??" },
/*::[*/0x0099/*::]*/: { n:"??" },
/*::[*/0x009A/*::]*/: { n:"??" },
/*::[*/0x009B/*::]*/: { n:"??" },
/*::[*/0x009C/*::]*/: { n:"??" },
/*::[*/0x00A3/*::]*/: { n:"??" },
/*::[*/0x00AE/*::]*/: { n:"??" },
/*::[*/0x00AF/*::]*/: { n:"??" },
/*::[*/0x00B0/*::]*/: { n:"??" },
/*::[*/0x00B1/*::]*/: { n:"??" },
/*::[*/0x00B8/*::]*/: { n:"??" },
/*::[*/0x00B9/*::]*/: { n:"??" },
/*::[*/0x00BA/*::]*/: { n:"??" },
/*::[*/0x00BB/*::]*/: { n:"??" },
/*::[*/0x00BC/*::]*/: { n:"??" },
/*::[*/0x00C3/*::]*/: { n:"??" },
/*::[*/0x00C9/*::]*/: { n:"??" },
/*::[*/0x00CC/*::]*/: { n:"SHEETNAMECS", f:parse_SHEETNAMECS },
/*::[*/0x00CD/*::]*/: { n:"??" },
/*::[*/0x00CE/*::]*/: { n:"??" },
/*::[*/0x00CF/*::]*/: { n:"??" },
/*::[*/0x00D0/*::]*/: { n:"??" },
/*::[*/0x0100/*::]*/: { n:"??" },
/*::[*/0x0103/*::]*/: { n:"??" },
/*::[*/0x0104/*::]*/: { n:"??" },
/*::[*/0x0105/*::]*/: { n:"??" },
/*::[*/0x0106/*::]*/: { n:"??" },
/*::[*/0x0107/*::]*/: { n:"??" },
/*::[*/0x0109/*::]*/: { n:"??" },
/*::[*/0x010A/*::]*/: { n:"??" },
/*::[*/0x010B/*::]*/: { n:"??" },
/*::[*/0x010C/*::]*/: { n:"??" },
/*::[*/0x010E/*::]*/: { n:"??" },
/*::[*/0x010F/*::]*/: { n:"??" },
/*::[*/0x0180/*::]*/: { n:"??" },
/*::[*/0x0185/*::]*/: { n:"??" },
/*::[*/0x0186/*::]*/: { n:"??" },
/*::[*/0x0189/*::]*/: { n:"??" },
/*::[*/0x018C/*::]*/: { n:"??" },
/*::[*/0x0200/*::]*/: { n:"??" },
/*::[*/0x0202/*::]*/: { n:"??" },
/*::[*/0x0201/*::]*/: { n:"??" },
/*::[*/0x0204/*::]*/: { n:"??" },
/*::[*/0x0205/*::]*/: { n:"??" },
/*::[*/0x0280/*::]*/: { n:"??" },
/*::[*/0x0281/*::]*/: { n:"??" },
/*::[*/0x0282/*::]*/: { n:"??" },
/*::[*/0x0283/*::]*/: { n:"??" },
/*::[*/0x0284/*::]*/: { n:"??" },
/*::[*/0x0285/*::]*/: { n:"??" },
/*::[*/0x0286/*::]*/: { n:"??" },
/*::[*/0x0287/*::]*/: { n:"??" },
/*::[*/0x0288/*::]*/: { n:"??" },
/*::[*/0x0292/*::]*/: { n:"??" },
/*::[*/0x0293/*::]*/: { n:"??" },
/*::[*/0x0294/*::]*/: { n:"??" },
/*::[*/0x0295/*::]*/: { n:"??" },
/*::[*/0x0296/*::]*/: { n:"??" },
/*::[*/0x0299/*::]*/: { n:"??" },
/*::[*/0x029A/*::]*/: { n:"??" },
/*::[*/0x0300/*::]*/: { n:"??" },
/*::[*/0x0304/*::]*/: { n:"??" },
/*::[*/0x0601/*::]*/: { n:"SHEETINFOQP", f:parse_SHEETINFOQP },
/*::[*/0x0640/*::]*/: { n:"??" },
/*::[*/0x0642/*::]*/: { n:"??" },
/*::[*/0x0701/*::]*/: { n:"??" },
/*::[*/0x0702/*::]*/: { n:"??" },
/*::[*/0x0703/*::]*/: { n:"??" },
/*::[*/0x0704/*::]*/: { n:"??" },
/*::[*/0x0780/*::]*/: { n:"??" },
/*::[*/0x0800/*::]*/: { n:"??" },
/*::[*/0x0801/*::]*/: { n:"??" },
/*::[*/0x0804/*::]*/: { n:"??" },
/*::[*/0x0A80/*::]*/: { n:"??" },
/*::[*/0x2AF6/*::]*/: { n:"??" },
/*::[*/0x3231/*::]*/: { n:"??" },
/*::[*/0x6E49/*::]*/: { n:"??" },
/*::[*/0x6F44/*::]*/: { n:"??" },
/*::[*/0xFFFF/*::]*/: { n:"" }
};
/* TODO: fill out and verify this table across QP versions */
var QPWNFTable = {
0x05: "dd-mmm-yy",
0x06: "dd-mmm",
0x07: "mmm-yy",
0x08: "mm/dd/yy", // Long Date Intl
0x0A: "hh:mm:ss AM/PM",
0x0B: "hh:mm AM/PM",
0x0E: "dd-mmm-yyyy",
0x0F: "mmm-yyyy",
/* It is suspected that the the low nybble specifies decimal places */
0x0022: "0.00",
0x0032: "0.00;[Red]0.00",
0x0042: "0.00;\(0.00\)",
0x0052: "0.00;[Red]\(0.00\)",
0x00A2: '"$"#,##0.00;\\("$"#,##0.00\\)',
0x0120: '0%',
0x0130: '0E+00',
0x0140: '# ?/?'
};
function parse_qpw_str(p) {
var cch = p.read_shift(2);
var flags = p.read_shift(1);
/* TODO: find examples with nonzero flags */
if(flags != 0) throw "unsupported QPW string type " + flags.toString(16);
return p.read_shift(cch, "sbcs-cont");
}
/* QPW uses a different set of record types */
function qpw_to_workbook_buf(d, opts)/*:Workbook*/ {
prep_blob(d, 0);
@ -1007,7 +924,6 @@ var WK_ = /*#__PURE__*/(function() {
var range = {s:{r:-1,c:-1}, e:{r:-1,c:-1}};
var cnt = 0, type = 0, C = 0, R = 0;
var wb = { SheetNames: [], Sheets: {} };
var FMTS = [];
outer: while(d.l < d.length) {
var RT = d.read_shift(2), length = d.read_shift(2);
var p = d.slice(d.l, d.l + length);
@ -1018,22 +934,6 @@ var WK_ = /*#__PURE__*/(function() {
break;
case 0x02: /* EOF */ break outer;
case 0x08: /* NF */ break; // TODO: this is tied to custom number formats
case 0x0A: /* FORMATS */ {
var fcnt = p.read_shift(4);
var step = ((p.length - p.l)/ fcnt)|0;
for(var ifmt = 0; ifmt < fcnt; ++ifmt) {
var end = p.l + step;
var fmt = {};
p.l += 2;
fmt.numFmtId = p.read_shift(2);
if(QPWNFTable[fmt.numFmtId]) fmt.z = QPWNFTable[fmt.numFmtId];
p.l = end;
FMTS.push(fmt);
}
} break;
/* TODO: The behavior here should be consistent with Numbers: QP Notebook ~ .TN.SheetArchive, QP Sheet ~ .TST.TableModelArchive */
case 0x0401: /* BON */ break;
case 0x0402: /* EON */ /* TODO: backfill missing sheets based on BON cnt */ break;
@ -1096,25 +996,18 @@ var WK_ = /*#__PURE__*/(function() {
var CC = encode_col(C);
while(p.l < p.length) {
var cell = { t: "z" };
var flags = p.read_shift(1), fmtidx = -1;
if(flags & 0x80) fmtidx = p.read_shift(2);
var flags = p.read_shift(1);
if(flags & 0x80) p.l += 2;
var mul = (flags & 0x40) ? p.read_shift(2) - 1: 0;
switch(flags & 0x1F) {
case 0: break;
case 1: break;
case 2: cell = { t: "n", v: p.read_shift(2) }; break;
case 3: cell = { t: "n", v: p.read_shift(2, 'i') }; break;
case 4: cell = { t: "n", v: parse_RkNumber(p) }; break;
case 5: cell = { t: "n", v: p.read_shift(8, 'f') }; break;
case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break;
case 8:
cell = { t: "n", v: p.read_shift(8, 'f') };
p.l += 2; /* cell.f = formulae[p.read_shift(4)]; */ p.l += 4;
if(isNaN(cell.v)) cell = { t: "e", v: 0x0F }; // #VALUE!
break;
case 8: cell = { t: "n", v: p.read_shift(8, 'f') }; p.l += 2; /* cell.f = formulae[p.read_shift(4)]; */ p.l += 4; break;
default: throw "Unrecognized QPW cell type " + (flags & 0x1F);
}
if(fmtidx != -1 && (FMTS[fmtidx - 1]||{}).z) cell.z = FMTS[fmtidx-1].z;
var delta = 0;
if(flags & 0x20) switch(flags & 0x1F) {
case 2: delta = p.read_shift(2); break;
@ -1123,14 +1016,10 @@ var WK_ = /*#__PURE__*/(function() {
default: throw "Unsupported delta for QPW cell type " + (flags & 0x1F);
}
if(!(!o.sheetStubs && cell.t == "z")) {
var newcell = dup(cell);
if(cell.t == "n" && cell.z && fmt_is_date(cell.z) && o.cellDates) {
newcell.v = numdate(cell.v); newcell.t = typeof newcell.v == "number" ? 'n' : 'd';
}
if(s["!data"] != null) {
if(!s["!data"][R]) s["!data"][R] = [];
s["!data"][R][C] = newcell;
} else s[CC + encode_row(R)] = newcell;
s["!data"][R][C] = cell;
} else s[CC + encode_row(R)] = cell;
}
++R; --cnt;
while(mul-- > 0 && cnt >= 0) {
@ -1145,7 +1034,6 @@ var WK_ = /*#__PURE__*/(function() {
case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break;
default: throw "Cannot apply repeat for QPW cell type " + (flags & 0x1F);
}
if(fmtidx != -1);
if(!(!o.sheetStubs && cell.t == "z")) {
if(s["!data"] != null) {
if(!s["!data"][R]) s["!data"][R] = [];
@ -1157,17 +1045,6 @@ var WK_ = /*#__PURE__*/(function() {
}
} break;
case 0x0C02: { /* String (result of string formula expression) */
C = p.read_shift(2);
R = p.read_shift(4);
var str = parse_qpw_str(p);
/* TODO: QP10 record has an additional unknown character after the string */
if(s["!data"] != null) {
if(!s["!data"][R]) s["!data"][R] = [];
s["!data"][R][C] = { t:"s", v:str };
} else s[encode_col(C) + encode_row(R)] = { t:"s", v:str };
} break;
default: break;
}
d.l += length;

View File

@ -4,7 +4,7 @@ function parse_rpr(rpr) {
var pass = false;
if(m) for(;i!=m.length; ++i) {
var y = parsexmltag(m[i]);
switch(y[0].replace(/<\w*:/g,"<")) {
switch(y[0].replace(/\w*:/g,"")) {
/* 18.8.12 condense CT_BooleanProperty */
/* ** not required . */
case '<condense': break;
@ -107,14 +107,15 @@ function parse_rpr(rpr) {
}
var parse_rs = /*#__PURE__*/(function() {
var tregex = matchtag("t"), rpregex = matchtag("rPr");
/* 18.4.4 r CT_RElt */
function parse_r(r) {
/* 18.4.12 t ST_Xstring */
var t = str_match_xml_ns(r, "t")/*, cp = 65001*/;
var t = r.match(tregex)/*, cp = 65001*/;
if(!t) return {t:"s", v:""};
var o/*:Cell*/ = ({t:'s', v:unescapexml(t[1])}/*:any*/);
var rpr = str_match_xml_ns(r, "rPr");
var rpr = r.match(rpregex);
if(rpr) o.s = parse_rpr(rpr[1]);
return o;
}
@ -167,7 +168,8 @@ var rs_to_html = /*#__PURE__*/(function parse_rs_factory() {
})();
/* 18.4.8 si CT_Rst */
var sitregex = /<(?:\w+:)?t\b[^<>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r\b[^<>]*>/;
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;
var z = {};
@ -183,7 +185,7 @@ function parse_si(x, opts) {
/* 18.4.4 r CT_RElt (Rich Text Run) */
else if((/*y = */x.match(sirregex))) {
z.r = utf8read(x);
z.t = unescapexml(utf8read((str_remove_xml_ns_g(x, "rPh").match(sitregex)||[]).join("").replace(tagregex,"")), true);
z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")), true);
if(html) z.h = rs_to_html(parse_rs(z.r));
}
/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
@ -192,20 +194,21 @@ function parse_si(x, opts) {
}
/* 18.4 Shared String Table */
var sstr0 = /<(?:\w+:)?sst([^>]*)>([\s\S]*)<\/(?:\w+:)?sst>/;
var sstr1 = /<(?:\w+:)?(?:si|sstItem)>/g;
var sstr2 = /<\/(?:\w+:)?(?:si|sstItem)>/;
function parse_sst_xml(data/*:string*/, opts)/*:SST*/ {
var s/*:SST*/ = ([]/*:any*/), ss = "";
if(!data) return s;
/* 18.4.9 sst CT_Sst */
var sst = str_match_xml_ns(data, "sst");
var sst = data.match(sstr0);
if(sst) {
ss = sst[1].replace(sstr1,"").split(sstr2);
ss = sst[2].replace(sstr1,"").split(sstr2);
for(var i = 0; i != ss.length; ++i) {
var o = parse_si(ss[i].trim(), opts);
if(o != null) s[s.length] = o;
}
sst = parsexmltag(sst[0].slice(0, sst[0].indexOf(">"))); s.Count = sst.count; s.Unique = sst.uniqueCount;
sst = parsexmltag(sst[1]); s.Count = sst.count; s.Unique = sst.uniqueCount;
}
return s;
}

View File

@ -17,7 +17,7 @@ function rtf_to_sheet_str(str, opts) {
var dense = o.dense;
if (dense)
ws["!data"] = [];
var rows = str_match_ng(str, "\\trowd", "\\row");
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 } };

View File

@ -3,7 +3,7 @@ function parse_borders(t, styles, themes, opts) {
styles.Borders = [];
var border = {};
var pass = false;
(t.match(tagregex)||[]).forEach(function(x) {
(t[0].match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<borders': case '<borders>': case '</borders>': break;
@ -78,7 +78,7 @@ function parse_fills(t, styles, themes, opts) {
styles.Fills = [];
var fill = {};
var pass = false;
(t.match(tagregex)||[]).forEach(function(x) {
(t[0].match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<fills': case '<fills>': case '</fills>': break;
@ -144,7 +144,7 @@ function parse_fonts(t, styles, themes, opts) {
styles.Fonts = [];
var font = {};
var pass = false;
(t.match(tagregex)||[]).forEach(function(x) {
(t[0].match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<fonts': case '<fonts>': case '</fonts>': break;
@ -264,7 +264,7 @@ function parse_numFmts(t, styles, opts) {
styles.NumberFmt = [];
var k/*Array<number>*/ = (keys(table_fmt)/*:any*/);
for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = table_fmt[k[i]];
var m = t.match(tagregex);
var m = t[0].match(tagregex);
if(!m) return;
for(i=0; i < m.length; ++i) {
var y = parsexmltag(m[i]);
@ -305,13 +305,13 @@ function parse_cellXfs(t, styles, opts) {
styles.CellXf = [];
var xf;
var pass = false;
(t.match(tagregex)||[]).forEach(function(x) {
(t[0].match(tagregex)||[]).forEach(function(x) {
var y = parsexmltag(x), i = 0;
switch(strip_ns(y[0])) {
case '<cellXfs': case '<cellXfs>': case '<cellXfs/>': case '</cellXfs>': break;
/* 18.8.45 xf CT_Xf */
case '<xf': case '<xf/>': case '<xf>':
case '<xf': case '<xf/>':
xf = y;
delete xf[0];
for(i = 0; i < cellXF_uint.length; ++i) if(xf[cellXF_uint[i]])
@ -325,7 +325,7 @@ function parse_cellXfs(t, styles, opts) {
case '</xf>': break;
/* 18.8.1 alignment CT_CellAlignment */
case '<alignment': case '<alignment/>': case '<alignment>':
case '<alignment': case '<alignment/>':
var alignment = {};
if(y.vertical) alignment.vertical = y.vertical;
if(y.horizontal) alignment.horizontal = y.horizontal;
@ -337,12 +337,12 @@ function parse_cellXfs(t, styles, opts) {
case '</alignment>': break;
/* 18.8.33 protection CT_CellProtection */
case '<protection': case '<protection>':
case '<protection':
break;
case '</protection>': case '<protection/>': break;
/* note: sometimes mc:AlternateContent appears bare */
case '<AlternateContent': case '<AlternateContent>': pass = true; break;
case '<AlternateContent': pass = true; break;
case '</AlternateContent>': pass = false; break;
/* 18.2.10 extLst CT_ExtensionList ? */
@ -370,31 +370,36 @@ function write_cellXfs(cellXfs)/*:string*/ {
/* 18.8 Styles CT_Stylesheet*/
var parse_sty_xml= /*#__PURE__*/(function make_pstyx() {
var numFmtRegex = /<(?:\w+:)?numFmts([^>]*)>[\S\s]*?<\/(?:\w+:)?numFmts>/;
var cellXfRegex = /<(?:\w+:)?cellXfs([^>]*)>[\S\s]*?<\/(?:\w+:)?cellXfs>/;
var fillsRegex = /<(?:\w+:)?fills([^>]*)>[\S\s]*?<\/(?:\w+:)?fills>/;
var fontsRegex = /<(?:\w+:)?fonts([^>]*)>[\S\s]*?<\/(?:\w+:)?fonts>/;
var bordersRegex = /<(?:\w+:)?borders([^>]*)>[\S\s]*?<\/(?:\w+:)?borders>/;
return function parse_sty_xml(data, themes, opts) {
var styles = {};
if(!data) return styles;
data = remove_doctype(str_remove_ng(data, "<!--", "-->"));
data = data.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
/* 18.8.39 styleSheet CT_Stylesheet */
var t;
/* 18.8.31 numFmts CT_NumFmts ? */
if((t=str_match_xml_ns(data, "numFmts"))) parse_numFmts(t[0], styles, opts);
if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts);
/* 18.8.23 fonts CT_Fonts ? */
if((t=str_match_xml_ns(data, "fonts"))) parse_fonts(t[0], styles, themes, opts);
if((t=data.match(fontsRegex))) parse_fonts(t, styles, themes, opts);
/* 18.8.21 fills CT_Fills ? */
if((t=str_match_xml_ns(data, "fills"))) parse_fills(t[0], styles, themes, opts);
if((t=data.match(fillsRegex))) parse_fills(t, styles, themes, opts);
/* 18.8.5 borders CT_Borders ? */
if((t=str_match_xml_ns(data, "borders"))) parse_borders(t[0], styles, themes, opts);
if((t=data.match(bordersRegex))) parse_borders(t, styles, themes, opts);
/* 18.8.9 cellStyleXfs CT_CellStyleXfs ? */
/* 18.8.8 cellStyles CT_CellStyles ? */
/* 18.8.10 cellXfs CT_CellXfs ? */
if((t=str_match_xml_ns(data, "cellXfs"))) parse_cellXfs(t[0], styles, opts);
if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts);
/* 18.8.15 dxfs CT_Dxfs ? */
/* 18.8.42 tableStyles CT_TableStyles ? */

View File

@ -18,12 +18,10 @@ function parse_clrScheme(t, themes, opts) {
/* 20.1.2.3.32 srgbClr CT_SRgbColor */
case '<a:srgbClr':
color.rgb = y.val; break;
case '</a:srgbClr>': break;
/* 20.1.2.3.33 sysClr CT_SystemColor */
case '<a:sysClr':
color.rgb = y.lastClr; break;
case '</a:sysClr>': break;
/* 20.1.4.1.1 accent1 (Accent 1) */
/* 20.1.4.1.2 accent2 (Accent 2) */
@ -37,10 +35,8 @@ function parse_clrScheme(t, themes, opts) {
/* 20.1.4.1.19 hlink (Hyperlink) */
/* 20.1.4.1.22 lt1 (Light 1) */
/* 20.1.4.1.23 lt2 (Light 2) */
case '</a:dk1>':
case '</a:lt1>':
case '<a:dk1>':
case '<a:lt1>':
case '<a:dk1>': case '</a:dk1>':
case '<a:lt1>': case '</a:lt1>':
case '<a:dk2>': case '</a:dk2>':
case '<a:lt2>': case '</a:lt2>':
case '<a:accent1>': case '</a:accent1>':
@ -70,25 +66,31 @@ function parse_fontScheme(/*::t, themes, opts*/) { }
/* 20.1.4.1.15 fmtScheme CT_StyleMatrix */
function parse_fmtScheme(/*::t, themes, opts*/) { }
var clrsregex = /<a:clrScheme([^>]*)>[\s\S]*<\/a:clrScheme>/;
var fntsregex = /<a:fontScheme([^>]*)>[\s\S]*<\/a:fontScheme>/;
var fmtsregex = /<a:fmtScheme([^>]*)>[\s\S]*<\/a:fmtScheme>/;
/* 20.1.6.10 themeElements CT_BaseStyles */
function parse_themeElements(data, themes, opts) {
themes.themeElements = {};
var t;
/* clrScheme CT_ColorScheme */
if(!(t=str_match_xml(data, "a:clrScheme"))) throw new Error('clrScheme not found in themeElements');
parse_clrScheme(t, themes, opts);
/* fontScheme CT_FontScheme */
if(!(t=str_match_xml(data, "a:fontScheme"))) throw new Error('fontScheme not found in themeElements');
parse_fontScheme(t, themes, opts);
/* fmtScheme CT_StyleMatrix */
if(!(t=str_match_xml(data, "a:fmtScheme"))) throw new Error('fmtScheme not found in themeElements');
parse_fmtScheme(t, themes, opts);
[
/* clrScheme CT_ColorScheme */
['clrScheme', clrsregex, parse_clrScheme],
/* fontScheme CT_FontScheme */
['fontScheme', fntsregex, parse_fontScheme],
/* fmtScheme CT_StyleMatrix */
['fmtScheme', fmtsregex, parse_fmtScheme]
].forEach(function(m) {
if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements');
m[2](t, themes, opts);
});
}
var themeltregex = /<a:themeElements([^>]*)>[\s\S]*<\/a:themeElements>/;
/* 14.2.7 Theme Part */
function parse_theme_xml(data/*:string*/, opts) {
/* 20.1.6.9 theme CT_OfficeStyleSheet */
@ -98,7 +100,7 @@ function parse_theme_xml(data/*:string*/, opts) {
var themes = {};
/* themeElements CT_BaseStyles */
if(!(t=str_match_xml(data, "a:themeElements"))) throw new Error('themeElements not found in theme');
if(!(t=data.match(themeltregex))) throw new Error('themeElements not found in theme');
parse_themeElements(t[0], themes, opts);
themes.raw = data;
return themes;

View File

@ -13,7 +13,7 @@ function parse_drawing(data, rels/*:any*/) {
the actual type is based on the URI of the graphicData
TODO: handle embedded charts and other types of graphics
*/
var id = (data.match(/<c:chart [^<>]*r:id="([^<>"]*)"/)||["",""])[1];
var id = (data.match(/<c:chart [^>]*r:id="([^"]*)"/)||["",""])[1];
return rels['!id'][id].Target;
}

View File

@ -1,42 +1,5 @@
/* L.5.5.2 SpreadsheetML Comments + VML Schema */
function parse_vml(data/*:string*/, sheet, comments) {
var cidx = 0;
(str_match_xml_ns_g(data, "shape")||[]).forEach(function(m) {
var type = "";
var hidden = true;
var aidx = -1;
var R = -1, C = -1;
m.replace(tagregex, function(x/*:string*/, idx/*:number*/) {
var y = parsexmltag(x);
switch(strip_ns(y[0])) {
case '<ClientData': if(y.ObjectType) type = y.ObjectType; break;
case '<Visible': case '<Visible/>': hidden = false; break;
case '<Row': case '<Row>': aidx = idx + x.length; break;
case '</Row>': R = +m.slice(aidx, idx).trim(); break;
case '<Column': case '<Column>': aidx = idx + x.length; break;
case '</Column>': C = +m.slice(aidx, idx).trim(); break;
}
return "";
});
switch(type) {
case 'Note':
var cell = ws_get_cell_stub(sheet, ((R>=0 && C>=0) ? encode_cell({r:R,c:C}) : comments[cidx].ref));
if(cell.c) {
cell.c.hidden = hidden;
}
++cidx;
break;
}
});
}
/* comment boxes */
function write_vml(rId/*:number*/, comments, ws) {
function write_vml(rId/*:number*/, comments) {
var csize = [21600, 21600];
/* L.5.2.1.2 Path Attribute */
var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(",");
@ -58,7 +21,7 @@ function write_vml(rId/*:number*/, comments, ws) {
return o.join("");
}
function write_vml_comment(x, _shapeid, ws)/*:string*/ {
function write_vml_comment(x, _shapeid)/*:string*/ {
var c = decode_cell(x[0]);
var fillopts = /*::(*/{'color2':"#BEFF82", 'type':"gradient"}/*:: :any)*/;
if(fillopts.type == "gradient") fillopts.angle = "-180";

View File

@ -4,22 +4,22 @@ function parse_comments_xml(data/*:string*/, opts)/*:Array<RawComment>*/ {
if(data.match(/<(?:\w+:)?comments *\/>/)) return [];
var authors/*:Array<string>*/ = [];
var commentList/*:Array<RawComment>*/ = [];
var authtag = str_match_xml_ns(data, "authors");
var authtag = data.match(/<(?:\w+:)?authors>([\s\S]*)<\/(?:\w+:)?authors>/);
if(authtag && authtag[1]) authtag[1].split(/<\/\w*:?author>/).forEach(function(x) {
if(x === "" || x.trim() === "") return;
var a = x.match(/<(?:\w+:)?author[^<>]*>(.*)/);
var a = x.match(/<(?:\w+:)?author[^>]*>(.*)/);
if(a) authors.push(a[1]);
});
var cmnttag = str_match_xml_ns(data, "commentList");
var cmnttag = data.match(/<(?:\w+:)?commentList>([\s\S]*)<\/(?:\w+:)?commentList>/);
if(cmnttag && cmnttag[1]) cmnttag[1].split(/<\/\w*:?comment>/).forEach(function(x) {
if(x === "" || x.trim() === "") return;
var cm = x.match(/<(?:\w+:)?comment[^<>]*>/);
var cm = x.match(/<(?:\w+:)?comment[^>]*>/);
if(!cm) return;
var y = parsexmltag(cm[0]);
var comment/*:RawComment*/ = ({ author: y.authorId && authors[y.authorId] || "sheetjsghost", ref: y.ref, guid: y.guid }/*:any*/);
var cell = decode_cell(y.ref);
if(opts.sheetRows && opts.sheetRows <= cell.r) return;
var textMatch = str_match_xml_ns(x, "text");
var textMatch = x.match(/<(?:\w+:)?text>([\s\S]*)<\/(?:\w+:)?text>/);
var rt = !!textMatch && !!textMatch[1] && parse_si(textMatch[1]) || {r:"",t:"",h:""};
comment.r = rt.r;
if(rt.r == "<t></t>") rt.t = rt.h = "";
@ -64,7 +64,6 @@ function write_comments_xml(data/*::, opts*/) {
o.push('</text></comment>');
});
} else {
if(d[1][0] && d[1][0].T && d[1][0].ID) lastauthor = iauthor.indexOf("tc=" + d[1][0].ID);
/* based on Threaded Comments -> Comments projection */
o.push('<comment ref="' + d[0] + '" authorId="' + lastauthor + '"><text>');
var t = "Comment:\n " + (ts[0]) + "\n";

View File

@ -74,10 +74,6 @@ function write_comments_bin(data/*::, opts*/) {
if(iauthor.indexOf(c.a) > -1) return;
iauthor.push(c.a.slice(0,54));
write_record(ba, 0x0278 /* BrtCommentAuthor */, write_BrtCommentAuthor(c.a));
if(c.T && c.ID && iauthor.indexOf("tc=" + c.ID) == -1) {
iauthor.push("tc=" + c.ID);
write_record(ba, 0x0278 /* BrtCommentAuthor */, write_BrtCommentAuthor("tc=" + c.ID));
}
});
});
write_record(ba, 0x0277 /* BrtEndCommentAuthors */);
@ -85,11 +81,7 @@ function write_comments_bin(data/*::, opts*/) {
write_record(ba, 0x0279 /* BrtBeginCommentList */);
data.forEach(function(comment) {
comment[1].forEach(function(c) {
var _ia = -1;
if(c.ID) _ia = iauthor.indexOf("tc=" + c.ID);
if(_ia == -1 && comment[1][0].T && comment[1][0].ID) _ia = iauthor.indexOf("tc=" + comment[1][0].ID);
if(_ia == -1) _ia = iauthor.indexOf(c.a);
c.iauthor = _ia;
c.iauthor = iauthor.indexOf(c.a);
var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])};
write_record(ba, 0x027B /* BrtBeginComment */, write_BrtBeginComment([range, c]));
if(c.t && c.t.length > 0) write_record(ba, 0x027D /* BrtCommentText */, write_BrtCommentText(c));

View File

@ -13,7 +13,7 @@ function fill_vba_xls(cfb, vba) {
vba.FullPaths.forEach(function(p, i) {
if (i == 0)
return;
var newpath = p.replace(/^[\/]*[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
var newpath = p.replace(/[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
if (newpath.slice(-1) !== "/")
CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content);
});

View File

@ -23,10 +23,7 @@ var rc_to_a1 = /*#__PURE__*/(function(){
};
})();
var crefregex = /(^|[^._A-Z0-9])(\$?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])(\$?)(\d{1,7})(?![_.\(A-Za-z0-9])/g;
try {
crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)(10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})(?![_.\(A-Za-z0-9])/g;
}catch(e){}
var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)(10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})(?![_.\(A-Za-z0-9])/g;
var a1_to_rc = /*#__PURE__*/(function(){
return function a1_to_rc(fstr/*:string*/, base/*:CellAddress*/) {
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) {

View File

@ -495,112 +495,112 @@ function parse_PtgAttrNoop(blob/*::, length, opts*/) {
/* [MS-XLS] 2.5.198.25 ; [MS-XLSB] 2.5.97.16 */
var PtgTypes = {
0x01: { n:'PtgExp', f:parse_PtgExp },
0x02: { n:'PtgTbl', f:parse_PtgTbl },
0x03: { n:'PtgAdd', f:parseread1 },
0x04: { n:'PtgSub', f:parseread1 },
0x05: { n:'PtgMul', f:parseread1 },
0x06: { n:'PtgDiv', f:parseread1 },
0x07: { n:'PtgPower', f:parseread1 },
0x08: { n:'PtgConcat', f:parseread1 },
0x09: { n:'PtgLt', f:parseread1 },
0x0A: { n:'PtgLe', f:parseread1 },
0x0B: { n:'PtgEq', f:parseread1 },
0x0C: { n:'PtgGe', f:parseread1 },
0x0D: { n:'PtgGt', f:parseread1 },
0x0E: { n:'PtgNe', f:parseread1 },
0x0F: { n:'PtgIsect', f:parseread1 },
0x10: { n:'PtgUnion', f:parseread1 },
0x11: { n:'PtgRange', f:parseread1 },
0x12: { n:'PtgUplus', f:parseread1 },
0x13: { n:'PtgUminus', f:parseread1 },
0x14: { n:'PtgPercent', f:parseread1 },
0x15: { n:'PtgParen', f:parseread1 },
0x16: { n:'PtgMissArg', f:parseread1 },
0x17: { n:'PtgStr', f:parse_PtgStr },
0x1A: { n:'PtgSheet', f:parse_PtgSheet },
0x1B: { n:'PtgEndSheet', f:parse_PtgEndSheet },
0x1C: { n:'PtgErr', f:parse_PtgErr },
0x1D: { n:'PtgBool', f:parse_PtgBool },
0x1E: { n:'PtgInt', f:parse_PtgInt },
0x1F: { n:'PtgNum', f:parse_PtgNum },
0x20: { n:'PtgArray', f:parse_PtgArray },
0x21: { n:'PtgFunc', f:parse_PtgFunc },
0x22: { n:'PtgFuncVar', f:parse_PtgFuncVar },
0x23: { n:'PtgName', f:parse_PtgName },
0x24: { n:'PtgRef', f:parse_PtgRef },
0x25: { n:'PtgArea', f:parse_PtgArea },
0x26: { n:'PtgMemArea', f:parse_PtgMemArea },
0x27: { n:'PtgMemErr', f:parse_PtgMemErr },
0x28: { n:'PtgMemNoMem', f:parse_PtgMemNoMem },
0x29: { n:'PtgMemFunc', f:parse_PtgMemFunc },
0x2A: { n:'PtgRefErr', f:parse_PtgRefErr },
0x2B: { n:'PtgAreaErr', f:parse_PtgAreaErr },
0x2C: { n:'PtgRefN', f:parse_PtgRefN },
0x2D: { n:'PtgAreaN', f:parse_PtgAreaN },
0x2E: { n:'PtgMemAreaN', f:parse_PtgMemAreaN },
0x2F: { n:'PtgMemNoMemN', f:parse_PtgMemNoMemN },
0x39: { n:'PtgNameX', f:parse_PtgNameX },
0x3A: { n:'PtgRef3d', f:parse_PtgRef3d },
0x3B: { n:'PtgArea3d', f:parse_PtgArea3d },
0x3C: { n:'PtgRefErr3d', f:parse_PtgRefErr3d },
0x3D: { n:'PtgAreaErr3d', f:parse_PtgAreaErr3d },
0xFF: {}
/*::[*/0x01/*::]*/: { n:'PtgExp', f:parse_PtgExp },
/*::[*/0x02/*::]*/: { n:'PtgTbl', f:parse_PtgTbl },
/*::[*/0x03/*::]*/: { n:'PtgAdd', f:parseread1 },
/*::[*/0x04/*::]*/: { n:'PtgSub', f:parseread1 },
/*::[*/0x05/*::]*/: { n:'PtgMul', f:parseread1 },
/*::[*/0x06/*::]*/: { n:'PtgDiv', f:parseread1 },
/*::[*/0x07/*::]*/: { n:'PtgPower', f:parseread1 },
/*::[*/0x08/*::]*/: { n:'PtgConcat', f:parseread1 },
/*::[*/0x09/*::]*/: { n:'PtgLt', f:parseread1 },
/*::[*/0x0A/*::]*/: { n:'PtgLe', f:parseread1 },
/*::[*/0x0B/*::]*/: { n:'PtgEq', f:parseread1 },
/*::[*/0x0C/*::]*/: { n:'PtgGe', f:parseread1 },
/*::[*/0x0D/*::]*/: { n:'PtgGt', f:parseread1 },
/*::[*/0x0E/*::]*/: { n:'PtgNe', f:parseread1 },
/*::[*/0x0F/*::]*/: { n:'PtgIsect', f:parseread1 },
/*::[*/0x10/*::]*/: { n:'PtgUnion', f:parseread1 },
/*::[*/0x11/*::]*/: { n:'PtgRange', f:parseread1 },
/*::[*/0x12/*::]*/: { n:'PtgUplus', f:parseread1 },
/*::[*/0x13/*::]*/: { n:'PtgUminus', f:parseread1 },
/*::[*/0x14/*::]*/: { n:'PtgPercent', f:parseread1 },
/*::[*/0x15/*::]*/: { n:'PtgParen', f:parseread1 },
/*::[*/0x16/*::]*/: { n:'PtgMissArg', f:parseread1 },
/*::[*/0x17/*::]*/: { n:'PtgStr', f:parse_PtgStr },
/*::[*/0x1A/*::]*/: { n:'PtgSheet', f:parse_PtgSheet },
/*::[*/0x1B/*::]*/: { n:'PtgEndSheet', f:parse_PtgEndSheet },
/*::[*/0x1C/*::]*/: { n:'PtgErr', f:parse_PtgErr },
/*::[*/0x1D/*::]*/: { n:'PtgBool', f:parse_PtgBool },
/*::[*/0x1E/*::]*/: { n:'PtgInt', f:parse_PtgInt },
/*::[*/0x1F/*::]*/: { n:'PtgNum', f:parse_PtgNum },
/*::[*/0x20/*::]*/: { n:'PtgArray', f:parse_PtgArray },
/*::[*/0x21/*::]*/: { n:'PtgFunc', f:parse_PtgFunc },
/*::[*/0x22/*::]*/: { n:'PtgFuncVar', f:parse_PtgFuncVar },
/*::[*/0x23/*::]*/: { n:'PtgName', f:parse_PtgName },
/*::[*/0x24/*::]*/: { n:'PtgRef', f:parse_PtgRef },
/*::[*/0x25/*::]*/: { n:'PtgArea', f:parse_PtgArea },
/*::[*/0x26/*::]*/: { n:'PtgMemArea', f:parse_PtgMemArea },
/*::[*/0x27/*::]*/: { n:'PtgMemErr', f:parse_PtgMemErr },
/*::[*/0x28/*::]*/: { n:'PtgMemNoMem', f:parse_PtgMemNoMem },
/*::[*/0x29/*::]*/: { n:'PtgMemFunc', f:parse_PtgMemFunc },
/*::[*/0x2A/*::]*/: { n:'PtgRefErr', f:parse_PtgRefErr },
/*::[*/0x2B/*::]*/: { n:'PtgAreaErr', f:parse_PtgAreaErr },
/*::[*/0x2C/*::]*/: { n:'PtgRefN', f:parse_PtgRefN },
/*::[*/0x2D/*::]*/: { n:'PtgAreaN', f:parse_PtgAreaN },
/*::[*/0x2E/*::]*/: { n:'PtgMemAreaN', f:parse_PtgMemAreaN },
/*::[*/0x2F/*::]*/: { n:'PtgMemNoMemN', f:parse_PtgMemNoMemN },
/*::[*/0x39/*::]*/: { n:'PtgNameX', f:parse_PtgNameX },
/*::[*/0x3A/*::]*/: { n:'PtgRef3d', f:parse_PtgRef3d },
/*::[*/0x3B/*::]*/: { n:'PtgArea3d', f:parse_PtgArea3d },
/*::[*/0x3C/*::]*/: { n:'PtgRefErr3d', f:parse_PtgRefErr3d },
/*::[*/0x3D/*::]*/: { n:'PtgAreaErr3d', f:parse_PtgAreaErr3d },
/*::[*/0xFF/*::]*/: {}
};
/* These are duplicated in the PtgTypes table */
var PtgDupes = {
0x40: 0x20, 0x60: 0x20,
0x41: 0x21, 0x61: 0x21,
0x42: 0x22, 0x62: 0x22,
0x43: 0x23, 0x63: 0x23,
0x44: 0x24, 0x64: 0x24,
0x45: 0x25, 0x65: 0x25,
0x46: 0x26, 0x66: 0x26,
0x47: 0x27, 0x67: 0x27,
0x48: 0x28, 0x68: 0x28,
0x49: 0x29, 0x69: 0x29,
0x4A: 0x2A, 0x6A: 0x2A,
0x4B: 0x2B, 0x6B: 0x2B,
0x4C: 0x2C, 0x6C: 0x2C,
0x4D: 0x2D, 0x6D: 0x2D,
0x4E: 0x2E, 0x6E: 0x2E,
0x4F: 0x2F, 0x6F: 0x2F,
0x58: 0x22, 0x78: 0x22,
0x59: 0x39, 0x79: 0x39,
0x5A: 0x3A, 0x7A: 0x3A,
0x5B: 0x3B, 0x7B: 0x3B,
0x5C: 0x3C, 0x7C: 0x3C,
0x5D: 0x3D, 0x7D: 0x3D
/*::[*/0x40/*::]*/: 0x20, /*::[*/0x60/*::]*/: 0x20,
/*::[*/0x41/*::]*/: 0x21, /*::[*/0x61/*::]*/: 0x21,
/*::[*/0x42/*::]*/: 0x22, /*::[*/0x62/*::]*/: 0x22,
/*::[*/0x43/*::]*/: 0x23, /*::[*/0x63/*::]*/: 0x23,
/*::[*/0x44/*::]*/: 0x24, /*::[*/0x64/*::]*/: 0x24,
/*::[*/0x45/*::]*/: 0x25, /*::[*/0x65/*::]*/: 0x25,
/*::[*/0x46/*::]*/: 0x26, /*::[*/0x66/*::]*/: 0x26,
/*::[*/0x47/*::]*/: 0x27, /*::[*/0x67/*::]*/: 0x27,
/*::[*/0x48/*::]*/: 0x28, /*::[*/0x68/*::]*/: 0x28,
/*::[*/0x49/*::]*/: 0x29, /*::[*/0x69/*::]*/: 0x29,
/*::[*/0x4A/*::]*/: 0x2A, /*::[*/0x6A/*::]*/: 0x2A,
/*::[*/0x4B/*::]*/: 0x2B, /*::[*/0x6B/*::]*/: 0x2B,
/*::[*/0x4C/*::]*/: 0x2C, /*::[*/0x6C/*::]*/: 0x2C,
/*::[*/0x4D/*::]*/: 0x2D, /*::[*/0x6D/*::]*/: 0x2D,
/*::[*/0x4E/*::]*/: 0x2E, /*::[*/0x6E/*::]*/: 0x2E,
/*::[*/0x4F/*::]*/: 0x2F, /*::[*/0x6F/*::]*/: 0x2F,
/*::[*/0x58/*::]*/: 0x22, /*::[*/0x78/*::]*/: 0x22,
/*::[*/0x59/*::]*/: 0x39, /*::[*/0x79/*::]*/: 0x39,
/*::[*/0x5A/*::]*/: 0x3A, /*::[*/0x7A/*::]*/: 0x3A,
/*::[*/0x5B/*::]*/: 0x3B, /*::[*/0x7B/*::]*/: 0x3B,
/*::[*/0x5C/*::]*/: 0x3C, /*::[*/0x7C/*::]*/: 0x3C,
/*::[*/0x5D/*::]*/: 0x3D, /*::[*/0x7D/*::]*/: 0x3D
};
var Ptg18 = {
0x01: { n:'PtgElfLel', f:parse_PtgElfLel },
0x02: { n:'PtgElfRw', f:parse_PtgElfRw },
0x03: { n:'PtgElfCol', f:parse_PtgElfCol },
0x06: { n:'PtgElfRwV', f:parse_PtgElfRwV },
0x07: { n:'PtgElfColV', f:parse_PtgElfColV },
0x0A: { n:'PtgElfRadical', f:parse_PtgElfRadical },
0x0B: { n:'PtgElfRadicalS', f:parse_PtgElfRadicalS },
0x0D: { n:'PtgElfColS', f:parse_PtgElfColS },
0x0F: { n:'PtgElfColSV', f:parse_PtgElfColSV },
0x10: { n:'PtgElfRadicalLel', f:parse_PtgElfRadicalLel },
0x19: { n:'PtgList', f:parse_PtgList },
0x1D: { n:'PtgSxName', f:parse_PtgSxName },
0xFF: {}
/*::[*/0x01/*::]*/: { n:'PtgElfLel', f:parse_PtgElfLel },
/*::[*/0x02/*::]*/: { n:'PtgElfRw', f:parse_PtgElfRw },
/*::[*/0x03/*::]*/: { n:'PtgElfCol', f:parse_PtgElfCol },
/*::[*/0x06/*::]*/: { n:'PtgElfRwV', f:parse_PtgElfRwV },
/*::[*/0x07/*::]*/: { n:'PtgElfColV', f:parse_PtgElfColV },
/*::[*/0x0A/*::]*/: { n:'PtgElfRadical', f:parse_PtgElfRadical },
/*::[*/0x0B/*::]*/: { n:'PtgElfRadicalS', f:parse_PtgElfRadicalS },
/*::[*/0x0D/*::]*/: { n:'PtgElfColS', f:parse_PtgElfColS },
/*::[*/0x0F/*::]*/: { n:'PtgElfColSV', f:parse_PtgElfColSV },
/*::[*/0x10/*::]*/: { n:'PtgElfRadicalLel', f:parse_PtgElfRadicalLel },
/*::[*/0x19/*::]*/: { n:'PtgList', f:parse_PtgList },
/*::[*/0x1D/*::]*/: { n:'PtgSxName', f:parse_PtgSxName },
/*::[*/0xFF/*::]*/: {}
};
var Ptg19 = {
0x00: { n:'PtgAttrNoop', f:parse_PtgAttrNoop },
0x01: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
0x02: { n:'PtgAttrIf', f:parse_PtgAttrIf },
0x04: { n:'PtgAttrChoose', f:parse_PtgAttrChoose },
0x08: { n:'PtgAttrGoto', f:parse_PtgAttrGoto },
0x10: { n:'PtgAttrSum', f:parse_PtgAttrSum },
0x20: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
0x21: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
0x40: { n:'PtgAttrSpace', f:parse_PtgAttrSpace },
0x41: { n:'PtgAttrSpaceSemi', f:parse_PtgAttrSpaceSemi },
0x80: { n:'PtgAttrIfError', f:parse_PtgAttrIfError },
0xFF: {}
/*::[*/0x00/*::]*/: { n:'PtgAttrNoop', f:parse_PtgAttrNoop },
/*::[*/0x01/*::]*/: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
/*::[*/0x02/*::]*/: { n:'PtgAttrIf', f:parse_PtgAttrIf },
/*::[*/0x04/*::]*/: { n:'PtgAttrChoose', f:parse_PtgAttrChoose },
/*::[*/0x08/*::]*/: { n:'PtgAttrGoto', f:parse_PtgAttrGoto },
/*::[*/0x10/*::]*/: { n:'PtgAttrSum', f:parse_PtgAttrSum },
/*::[*/0x20/*::]*/: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
/*::[*/0x21/*::]*/: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
/*::[*/0x40/*::]*/: { n:'PtgAttrSpace', f:parse_PtgAttrSpace },
/*::[*/0x41/*::]*/: { n:'PtgAttrSpaceSemi', f:parse_PtgAttrSpaceSemi },
/*::[*/0x80/*::]*/: { n:'PtgAttrIfError', f:parse_PtgAttrIfError },
/*::[*/0xFF/*::]*/: {}
};
/* [MS-XLS] 2.5.198.103 ; [MS-XLSB] 2.5.97.87 */

View File

@ -68,7 +68,8 @@ function write_FormulaValue(value) {
/* [MS-XLS] 2.4.127 TODO */
function parse_Formula(blob, length, opts) {
var end = blob.l + length;
var cell = parse_XLSCell(blob, 6, opts);
var cell = parse_XLSCell(blob, 6);
if(opts.biff == 2) ++blob.l;
var val = parse_FormulaValue(blob,8);
var flags = blob.read_shift(1);
if(opts.biff != 2) {
@ -262,7 +263,7 @@ function write_XLSBFormulaRangeWS(_str, wb) {
var sname = _str.slice(0, lastbang);
_str = _str.slice(lastbang+1);
if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
var parts = _str.split(":");
var parts = _str.split(":"); str = parts[0];
var out = new_buf(27);
out.write_shift(4, 19);

View File

@ -31,6 +31,6 @@ function ods_to_csf_3D(r/*:string*/)/*:[string, string]*/ {
}
function csf_to_ods_3D(r/*:string*/)/*:string*/ {
return r.replace(/!/,".").replace(/:/, ":.");
return r.replace(/!/,".");
}

View File

@ -81,7 +81,7 @@ function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) {
return len;
}
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles, date1904) {
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) {
try {
if(opts.cellNF) p.z = table_fmt[fmtid];
} catch(e) { if(opts.WTF) throw e; }
@ -96,14 +96,14 @@ function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, the
else p.w = SSF_general_num(p.v);
}
else if(p.t === 'd') {
var dd = datenum(p.v, !!date1904);
var dd = datenum(p.v);
if((dd|0) === dd) p.w = dd.toString(10);
else p.w = SSF_general_num(dd);
}
else if(p.v === undefined) return "";
else p.w = SSF_general(p.v,_ssfopts);
}
else if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v, !!date1904),_ssfopts);
else if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v),_ssfopts);
else p.w = SSF_format(fmtid,p.v,_ssfopts);
} catch(e) { if(opts.WTF) throw e; }
if(!opts.cellStyles) return;

View File

@ -2,13 +2,16 @@ function parse_ws_xml_dim(ws/*:Worksheet*/, s/*:string*/) {
var d = safe_decode_range(s);
if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d);
}
var mergecregex = /<(?:\w+:)?mergeCell ref=["'][A-Z0-9:]+['"]\s*[\/]?>/g;
var hlinkregex = /<(?:\w+:)?hyperlink [^<>]*>/mg;
var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*[\/]?>/g;
var sheetdataregex = /<(?:\w+:)?sheetData[^>]*>([\s\S]*)<\/(?:\w+:)?sheetData>/;
var hlinkregex = /<(?:\w:)?hyperlink [^>]*>/mg;
var dimregex = /"(\w*:\w*)"/;
var colregex = /<(?:\w+:)?col\b[^<>]*[\/]?>/g;
var afregex = /<(?:\w+:)?autoFilter[^>]*/g;
var marginregex= /<(?:\w+:)?pageMargins[^<>]*\/>/g;
var sheetprregex = /<(?:\w+:)?sheetPr\b[^<>]*?\/>/;
var colregex = /<(?:\w:)?col\b[^>]*[\/]?>/g;
var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g;
var sheetprregex = /<(?:\w:)?sheetPr\b(?:[^>a-z][^>]*)?\/>/;
var sheetprregex2= /<(?:\w:)?sheetPr[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetPr)>/;
var svsregex = /<(?:\w:)?sheetViews[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetViews)>/;
/* 18.3 Worksheets */
function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ {
@ -21,7 +24,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
var refguess/*:Range*/ = ({s: {r:2000000, c:2000000}, e: {r:0, c:0} }/*:any*/);
var data1 = "", data2 = "";
var mtch/*:?any*/ = str_match_xml_ns(data, "sheetData");
var mtch/*:?any*/ = data.match(sheetdataregex);
if(mtch) {
data1 = data.slice(0, mtch.index);
data2 = data.slice(mtch.index + mtch[0].length);
@ -30,7 +33,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
/* 18.3.1.82 sheetPr CT_SheetPr */
var sheetPr = data1.match(sheetprregex);
if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
else if((sheetPr = str_match_xml_ns(data1, "sheetPr"))) parse_ws_xml_sheetpr2(sheetPr[0], sheetPr[1]||"", s, wb, idx, styles, themes);
else if((sheetPr = data1.match(sheetprregex2))) parse_ws_xml_sheetpr2(sheetPr[0], sheetPr[1]||"", s, wb, idx, styles, themes);
/* 18.3.1.35 dimension CT_SheetDimension */
var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
@ -40,7 +43,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
}
/* 18.3.1.88 sheetViews CT_SheetViews */
var svs = str_match_xml_ns(data1, "sheetViews");
var svs = data1.match(svsregex);
if(svs && svs[1]) parse_ws_xml_sheetviews(svs[1], wb);
/* 18.3.1.17 cols CT_Cols */
@ -52,7 +55,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
}
/* 18.3.1.80 sheetData CT_SheetData ? */
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles, wb);
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
/* 18.3.1.2 autoFilter CT_AutoFilter */
var afilter = data2.match(afregex);
@ -72,10 +75,6 @@ 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]));
/* legacyDrawing */
var m;
if((m = data2.match(/legacyDrawing r:id="(.*?)"/))) s['!legrel'] = m[1];
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"]) {
@ -92,7 +91,6 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
}
if(columns.length > 0) s["!cols"] = columns;
if(merges.length > 0) s["!merges"] = merges;
if(rels['!id'][s['!legrel']]) s['!legdrawel'] = rels['!id'][s['!legrel']];
return s;
}
@ -239,7 +237,7 @@ function write_ws_xml_autofilter(data, ws, wb, idx)/*:string*/ {
/* 18.3.1.88 sheetViews CT_SheetViews */
/* 18.3.1.87 sheetView CT_SheetView */
var sviewregex = /<(?:\w:)?sheetView(?:[^<>a-z][^<>]*)?\/?>/g;
var sviewregex = /<(?:\w:)?sheetView(?:[^>a-z][^>]*)?\/?>/g;
function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) {
if(!wb.Views) wb.Views = [{}];
(data.match(sviewregex)||[]).forEach(function(r/*:string*/, i/*:number*/) {
@ -259,7 +257,7 @@ function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
return writextag("sheetViews", writextag("sheetView", null, sview), {});
}
function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb, date1904)/*:string*/ {
function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string*/ {
if(cell.c) ws['!comments'].push([ref, cell.c]);
if((cell.v === undefined || cell.t === "z" && !(opts||{}).sheetStubs) && typeof cell.f !== "string" && typeof cell.z == "undefined") return "";
var vv = "";
@ -272,14 +270,11 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb, date1904)/*:st
else vv = ''+cell.v; break;
case 'e': vv = BErr[cell.v]; break;
case 'd':
if(opts && opts.cellDates) {
var _vv = parseDate(cell.v, date1904);
vv = _vv.toISOString();
if(_vv.getUTCFullYear() < 1900) vv = vv.slice(vv.indexOf("T") + 1).replace("Z","");
} else {
if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
else {
cell = dup(cell);
cell.t = 'n';
vv = ''+(cell.v = datenum(parseDate(cell.v, date1904), date1904));
vv = ''+(cell.v = datenum(parseDate(cell.v)));
}
if(typeof cell.z === 'undefined') cell.z = table_fmt[14];
break;
@ -318,10 +313,11 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb, date1904)/*:st
var parse_ws_xml_data = /*#__PURE__*/(function() {
var cellregex = /<(?:\w+:)?c[ \/>]/, rowregex = /<\/(?:\w+:)?row>/;
var rregex = /r=["']([^"']*)["']/;
var rregex = /r=["']([^"']*)["']/, isregex = /<(?:\w+:)?is>([\S\s]*?)<\/(?:\w+:)?is>/;
var refregex = /ref=["']([^"']*)["']/;
var match_v = matchtag("v"), match_f = matchtag("f");
return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles, wb) {
return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles) {
var ri = 0, x = "", cells/*:Array<string>*/ = [], cref/*:?Array<string>*/ = [], idx=0, i=0, cc=0, d="", p/*:any*/;
var tag, tagr = 0, tagc = 0;
var sstr, ftag;
@ -332,7 +328,6 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
var dense = s["!data"] != null;
var rows/*:Array<RowInfo>*/ = [], rowobj = {}, rowrite = false;
var sheetStubs = !!opts.sheetStubs;
var date1904 = !!((wb||{}).WBProps||{}).date1904;
for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
x = marr[mt].trim();
var xlen = x.length;
@ -398,31 +393,23 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
d = x.slice(i);
p = ({t:""}/*:any*/);
if((cref=str_match_xml_ns(d, "v"))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
if(opts.cellFormula) {
if((cref=str_match_xml_ns(d, "f"))!= null /*:: && cref != null*/) {
if(cref[1] == "") {
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
// TODO: parse formula
ftag = parsexmltag(cref[0]);
if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
}
} else {
/* TODO: match against XLSXFutureFunctions */
p.f=unescapexml(utf8read(cref[1]), true);
if(!opts.xlfn) p.f = _xlfn(p.f);
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
p.F = (d.match(refregex)||[])[1];
if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
} else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
// TODO: parse formula
ftag = parsexmltag(cref[0]);
var ___f = unescapexml(utf8read(cref[1]));
if(!opts.xlfn) ___f = _xlfn(___f);
sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
}
if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') {
/* TODO: match against XLSXFutureFunctions */
p.f=unescapexml(utf8read(cref[1]), true);
if(!opts.xlfn) p.f = _xlfn(p.f);
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
p.F = (d.match(refregex)||[])[1];
if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
} else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
// TODO: parse formula
ftag = parsexmltag(cref[0]);
var ___f = unescapexml(utf8read(cref[1]));
if(!opts.xlfn) ___f = _xlfn(___f);
sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
}
} else if((cref=d.match(/<f[^<>]*\/>/))) {
} else if((cref=d.match(/<f[^>]*\/>/))) {
ftag = parsexmltag(cref[0]);
if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
}
@ -468,7 +455,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
if(opts.cellHTML) p.h = escapehtml(p.v);
break;
case 'inlineStr':
cref = str_match_xml_ns(d, "is");
cref = d.match(isregex);
p.t = 's';
if(cref != null && (sstr = parse_si(cref[1]))) {
p.v = sstr.t;
@ -477,8 +464,8 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
break;
case 'b': p.v = parsexmlbool(p.v); break;
case 'd':
if(opts.cellDates) p.v = parseDate(p.v, date1904);
else { p.v = datenum(parseDate(p.v, date1904), date1904); p.t = 'n'; }
if(opts.cellDates) p.v = parseDate(p.v, 1);
else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; }
break;
/* error string in .w, number in .v */
case 'e':
@ -497,8 +484,8 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
}
}
}
safe_format(p, fmtid, fillid, opts, themes, styles, date1904);
if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.v = numdate(p.v + (date1904 ? 1462 : 0)); p.t = typeof p.v == "number" ? 'n' : 'd'; }
safe_format(p, fmtid, fillid, opts, themes, styles);
if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.t = 'd'; p.v = numdate(p.v); }
if(tag.cm && opts.xlmeta) {
var cm = (opts.xlmeta.Cell||[])[+tag.cm-1];
if(cm && cm.type == 'XLDAPR') p.D = true;
@ -523,7 +510,6 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
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 = ws["!data"] != null;
var params = ({r:rr}/*:any*/), row/*:RowInfo*/, height = -1;
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
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) {
r = [];
@ -532,7 +518,7 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
ref = cols[C] + rr;
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, date1904)) != null) r.push(cell);
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
}
if(r.length > 0 || (rows && rows[R])) {
params = ({r:rr}/*:any*/);
@ -633,7 +619,7 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
if(!l[1].Target) return;
rel = ({"ref":l[0]}/*:any*/);
if(l[1].Target.charAt(0) != "#") {
rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#[\s\S]*$/, ""), RELS.HLINK);
rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), RELS.HLINK);
rel["r:id"] = "rId"+rId;
}
if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1));

View File

@ -542,7 +542,6 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
XLSBRecordEnum[0x0010] = { n:"BrtShortReal", f:parse_BrtShortReal };
var cm, vm;
var date1904 = 1462 * +!!((wb||{}).WBProps||{}).date1904;
recordhopper(data, function ws_parse(val, RR, RT) {
if(end) return;
@ -586,7 +585,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 'str': p.t = 's'; p.v = val[1]; break;
case 'is': p.t = 's'; p.v = val[1].t; break;
}
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles, date1904>0);
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["!data"][R]) s["!data"][R] = []; s["!data"][R][C] = p; }
else s[encode_col(C) + rr] = p;
@ -607,7 +606,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
if(refguess.e.r < row.r) refguess.e.r = row.r;
if(refguess.e.c < C) refguess.e.c = C;
if(opts.cellDates && cf && p.t == 'n' && fmt_is_date(table_fmt[cf.numFmtId])) {
var _d = SSF_parse_date_code(p.v + date1904); if(_d) { p.t = 'd'; p.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
var _d = SSF_parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
}
if(cm) {
if(cm.type == 'XLDAPR') p.D = true;
@ -687,10 +686,6 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
}
break;
case 0x0227: /* 'BrtLegacyDrawing' */
if(val) s["!legrel"] = val;
break;
case 0x00A1: /* 'BrtBeginAFilter' */
s['!autofilter'] = { ref:encode_range(val) };
break;
@ -747,6 +742,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x0499: /* 'BrtFilter14' */
case 0x00A9: /* 'BrtIconFilter' */
case 0x049D: /* 'BrtIconFilter14' */
case 0x0227: /* 'BrtLegacyDrawing' */
case 0x0228: /* 'BrtLegacyDrawingHF' */
case 0x0295: /* 'BrtListPart' */
case 0x027F: /* 'BrtOleObject' */
@ -805,12 +801,11 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
if(merges.length > 0) s["!merges"] = merges;
if(colinfo.length > 0) s["!cols"] = colinfo;
if(rowinfo.length > 0) s["!rows"] = rowinfo;
if(rels['!id'][s['!legrel']]) s['!legdrawel'] = rels['!id'][s['!legrel']];
return s;
}
/* TODO: something useful -- this is a stub */
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/, date1904/*:boolean*/)/*:boolean*/ {
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/)/*:boolean*/ {
var o/*:any*/ = ({r:R, c:C}/*:any*/);
if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
if(cell.v === undefined) return false;
@ -820,7 +815,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
case 'd': // no BrtCellDate :(
cell = dup(cell);
cell.z = cell.z || table_fmt[14];
cell.v = datenum(parseDate(cell.v, date1904), date1904); cell.t = 'n';
cell.v = datenum(parseDate(cell.v)); cell.t = 'n';
break;
/* falls through */
case 'n': case 'e': vv = ''+cell.v; break;
@ -873,9 +868,8 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
return true;
}
function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols/*:Array<string>*/ = [];
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
write_record(ba, 0x0091 /* BrtBeginSheetData */);
var dense = ws["!data"] != null;
var cap = range.e.r;
@ -893,7 +887,7 @@ function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbo
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, date1904);
last_seen = write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen);
}
}
write_record(ba, 0x0092 /* BrtEndSheetData */);
@ -924,7 +918,7 @@ function write_HLINKS(ba, ws/*:Worksheet*/, rels) {
/* *BrtHLink */
ws['!links'].forEach(function(l) {
if(!l[1].Target) return;
var rId = add_rels(rels, -1, l[1].Target.replace(/#[\s\S]*$/, ""), RELS.HLINK);
var rId = add_rels(rels, -1, l[1].Target.replace(/#.*$/, ""), RELS.HLINK);
write_record(ba, 0x01EE /* BrtHLink */, write_BrtHLink(l, rId));
});
delete ws['!links'];

View File

@ -4,16 +4,16 @@ function parse_Cache(data/*:string*/)/*:[Array<number|string>, string, ?string]*
var f;
/* 21.2.2.150 pt CT_NumVal */
(data.match(/<c:pt idx="(\d*)"[^<>\/]*><c:v>([^<])<\/c:v><\/c:pt>/mg)||[]).forEach(function(pt) {
var q = pt.match(/<c:pt idx="(\d*)"[^<>\/]*><c:v>([^<]*)<\/c:v><\/c:pt>/);
(data.match(/<c:pt idx="(\d*)">(.*?)<\/c:pt>/mg)||[]).forEach(function(pt) {
var q = pt.match(/<c:pt idx="(\d*?)"><c:v>(.*)<\/c:v><\/c:pt>/);
if(!q) return;
col[+q[1]] = num ? +q[2] : q[2];
});
/* 21.2.2.71 formatCode CT_Xstring */
var nf = unescapexml((str_match_xml(data, "c:formatCode") || ["","General"])[1]);
var nf = unescapexml((data.match(/<c:formatCode>([\s\S]*?)<\/c:formatCode>/) || ["","General"])[1]);
(str_match_ng(data, "<c:f>", "</c:f>")||[]).forEach(function(F) { f = F.replace(/<[^<>]*>/g,""); });
(data.match(/<c:f>(.*?)<\/c:f>/mg)||[]).forEach(function(F) { f = F.replace(/<.*?>/g,""); });
return [col, nf, f];
}
@ -28,7 +28,7 @@ function parse_chart(data/*:?string*/, name/*:string*/, opts, rels, wb, csheet)
var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
/* 21.2.2.120 numCache CT_NumData */
(str_match_ng(data, "<c:numCache>", "</c:numCache>")||[]).forEach(function(nc) {
(data.match(/<c:numCache>[\s\S]*?<\/c:numCache>/gm)||[]).forEach(function(nc) {
var cache = parse_Cache(nc);
refguess.s.r = refguess.s.c = 0;
refguess.e.c = C;

View File

@ -69,14 +69,8 @@ function parse_BrtName(data, length, opts) {
data.l += 1; //var chKey = data.read_shift(1);
var itab = data.read_shift(4);
var name = parse_XLNameWideString(data);
var formula;
var comment = "";
try {
formula = parse_XLSBNameParsedFormula(data, 0, opts);
try {
comment = parse_XLNullableWideString(data);
} catch(e){}
} catch(e) { console.error("Could not parse defined name " + name); }
var formula = parse_XLSBNameParsedFormula(data, 0, opts);
var comment = parse_XLNullableWideString(data);
if(flags & 0x20) name = "_xlnm." + name;
//if(0 /* fProc */) {
// unusedstring1: XLNullableWideString
@ -147,7 +141,7 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
case 0x0027: /* 'BrtName' */
if(val.Sheet != null) opts.SID = val.Sheet;
val.Ref = val.Ptg ? stringify_formula(val.Ptg, null, null, supbooks, opts) : "#REF!";
val.Ref = stringify_formula(val.Ptg, null, null, supbooks, opts);
delete opts.SID;
delete val.Ptg;
Names.push(val);

View File

@ -1,5 +1,5 @@
var attregexg2=/\b((?:\w+:)?[\w]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
var attregex2=/\b((?:\w+:)?[\w]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;
var attregexg2=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
var attregex2=/([\w:]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;
function xlml_parsexmltag(tag/*:string*/, skip_root/*:?boolean*/) {
var words = tag.split(/\s+/);
var z/*:any*/ = ([]/*:any*/); if(!skip_root) z[0] = words[0];
@ -40,10 +40,10 @@ function xlml_parsexmltagobj(tag/*:string*/) {
/* map from xlml named formats to SSF TODO: localize */
var XLMLFormatMap/*: {[string]:string}*/;
function xlml_format(format, value, date1904)/*:string*/ {
function xlml_format(format, value)/*:string*/ {
var fmt = XLMLFormatMap[format] || unescapexml(format);
if(fmt === "General") return SSF_general(value);
return SSF_format(fmt, value, {date1904: !!date1904});
return SSF_format(fmt, value);
}
function xlml_set_custprop(Custprops, key, cp, val/*:string*/) {
@ -59,7 +59,7 @@ function xlml_set_custprop(Custprops, key, cp, val/*:string*/) {
Custprops[unescapexml(key)] = oval;
}
function safe_format_xlml(cell/*:Cell*/, nf, o, date1904) {
function safe_format_xlml(cell/*:Cell*/, nf, o) {
if(cell.t === 'z') return;
if(!o || o.cellText !== false) try {
if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
@ -70,13 +70,13 @@ function safe_format_xlml(cell/*:Cell*/, nf, o, date1904) {
}
else cell.w = SSF_general(cell.v);
}
else cell.w = xlml_format(nf||"General", cell.v, date1904);
else cell.w = xlml_format(nf||"General", cell.v);
} catch(e) { if(o.WTF) throw e; }
try {
var z = XLMLFormatMap[nf]||nf||"General";
if(o.cellNF) cell.z = z;
if(o.cellDates && cell.t == 'n' && fmt_is_date(z)) {
var _d = SSF_parse_date_code(cell.v + (date1904 ? 1462 : 0)); if(_d) { cell.t = 'd'; cell.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
var _d = SSF_parse_date_code(cell.v); if(_d) { cell.t = 'd'; cell.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
}
} catch(e) { if(o.WTF) throw e; }
}
@ -92,18 +92,17 @@ function process_style_xlml(styles, stag, opts) {
}
/* TODO: there must exist some form of OSP-blessed spec */
function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o, date1904) {
function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o) {
var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
var interiors = [];
var i = 0;
if(sid === undefined && row) sid = row.StyleID;
if(sid === undefined && csty) sid = csty.StyleID;
while(styles[sid] !== undefined) {
var ssid = styles[sid];
if(ssid.nf) nf = ssid.nf;
if(ssid.Interior) interiors.push(ssid.Interior);
if(!ssid.Parent) break;
sid = ssid.Parent;
if(styles[sid].nf) nf = styles[sid].nf;
if(styles[sid].Interior) interiors.push(styles[sid].Interior);
if(!styles[sid].Parent) break;
sid = styles[sid].Parent;
}
switch(data.Type) {
case 'Boolean':
@ -112,12 +111,13 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
break;
case 'String':
cell.t = 's'; cell.r = xlml_fixstr(unescapexml(xml));
cell.v = (xml.indexOf("<") > -1 ? unescapexml(ss||xml).replace(/<[^<>]*>/g, "") : cell.r); // todo: BR etc
cell.v = (xml.indexOf("<") > -1 ? unescapexml(ss||xml).replace(/<.*?>/g, "") : cell.r); // todo: BR etc
break;
case 'DateTime':
if(xml.slice(-1) != "Z") xml += "Z";
cell.v = datenum(parseDate(xml, date1904), date1904);
cell.v = (parseDate(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
if(cell.v !== cell.v) cell.v = unescapexml(xml);
else if(cell.v<60) cell.v = cell.v -1;
if(!nf || nf == "General") nf = "yyyy-mm-dd";
/* falls through */
case 'Number':
@ -130,7 +130,7 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
else { cell.t = 's'; cell.v = xlml_fixstr(ss||xml); }
break;
}
safe_format_xlml(cell, nf, o, date1904);
safe_format_xlml(cell, nf, o);
if(o.cellFormula !== false) {
if(cell.Formula) {
var fstr = unescapexml(cell.Formula);
@ -222,7 +222,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
var rowinfo/*:Array<RowInfo>*/ = [], rowobj = {}, cc = 0, rr = 0;
var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false} }/*:any*/), wsprops = {};
xlmlregex.lastIndex = 0;
str = str_remove_ng(str, "<!--", "-->");
str = str.replace(/<!--([\s\S]*?)-->/mg,"");
var raw_Rn3 = "";
while((Rn = xlmlregex.exec(str))) switch((Rn[3] = (raw_Rn3 = Rn[3]).toLowerCase())) {
case 'data' /*case 'Data'*/:
@ -232,7 +232,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
break;
}
if(state[state.length-1][1]) break;
if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]==/*"Comment"*/"comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts, Workbook.WBProps.date1904);
if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]==/*"Comment"*/"comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts);
else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; }
break;
case 'cell' /*case 'Cell'*/:
@ -443,7 +443,6 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
} else {
state.push([Rn[3], false]);
tmp = xlml_parsexmltag(Rn[0]);
if(!parsexmlbool(tmp["ShowAlways"]||"0")) comments.hidden = true;
comment = ({a:tmp.Author}/*:any*/);
}
break;
@ -535,9 +534,6 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
/*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
Workbook.WBProps.date1904 = true;
break;
case 'hidehorizontalscrollbar' /*case 'HideHorizontalScrollBar'*/: break;
case 'hideverticalscrollbar' /*case 'HideVerticalScrollBar'*/: break;
case 'hideworkbooktabs' /*case 'HideWorkbookTabs'*/: break;
case 'windowheight' /*case 'WindowHeight'*/: break;
case 'windowwidth' /*case 'WindowWidth'*/: break;
case 'windowtopx' /*case 'WindowTopX'*/: break;
@ -1106,15 +1102,11 @@ function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workb
return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x});
}
function write_ws_xlml_comment(comments/*:Array<any>*/)/*:string*/ {
/* TODO: test multiple comments */
return comments.map(function(c) {
// TODO: formatted text
var t = xlml_unfixstr(c.t||"");
var d =writextag("ss:Data", t, {"xmlns":"http://www.w3.org/TR/REC-html40"});
var p = {};
if(c.a) p["ss:Author"] = c.a;
if(!comments.hidden) p["ss:ShowAlways"] = "1";
return writextag("Comment", d, p);
return writextag("Comment", d, {"ss:Author":c.a});
}).join("");
}
function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, addr)/*:string*/{

View File

@ -77,7 +77,7 @@ function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
var fmtid = 0;
try {
fmtid = p.z || p.XF.numFmtId || 0;
if(opts.cellNF && p.z == null) p.z = table_fmt[fmtid];
if(opts.cellNF) p.z = table_fmt[fmtid];
} catch(e) { if(opts.WTF) throw e; }
if(!opts || opts.cellText !== false) try {
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
@ -91,7 +91,7 @@ function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
else p.w = SSF_format(fmtid,p.v, {date1904:!!date1904, dateNF: opts && opts.dateNF});
} catch(e) { if(opts.WTF) throw e; }
if(opts.cellDates && fmtid && p.t == 'n' && fmt_is_date(table_fmt[fmtid] || String(fmtid))) {
var _d = SSF_parse_date_code(p.v + (date1904 ? 1462 : 0)); if(_d) { p.t = 'd'; p.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
var _d = SSF_parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
}
}
@ -119,13 +119,12 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
var XFs = []; /* XF records */
var palette/*:Array<[number, number, number]>*/ = [];
var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false}, Views:[{}] }/*:any*/), wsprops = {};
var biff4w = false;
var get_rgb = function getrgb(icv/*:number*/)/*:[number, number, number]*/ {
if(icv < 8) return XLSIcv[icv];
if(icv < 64) return palette[icv-8] || XLSIcv[icv];
return XLSIcv[icv];
};
var process_cell_style = function pcs(line/*:any*/, options) {
var process_cell_style = function pcs(cell, line/*:any*/, options) {
var xfd = line.XF.data;
if(!xfd || !xfd.patternType || !options || !options.cellStyles) return;
line.s = ({}/*:any*/);
@ -135,9 +134,9 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; }
};
var addcell = function addcell(cell/*:any*/, line/*:any*/, options/*:any*/) {
if(!biff4w && file_depth > 1) return;
if(file_depth > 1) return;
if(options.sheetRows && cell.r >= options.sheetRows) return;
if(options.cellStyles && line.XF && line.XF.data) process_cell_style(line, options);
if(options.cellStyles && line.XF && line.XF.data) process_cell_style(cell, line, options);
delete line.ixfe; delete line.XF;
lastcell = cell;
last_cell = encode_cell(cell);
@ -266,7 +265,6 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
if(!val.fBelow) (out["!outline"] || (out["!outline"] = {})).above = true;
if(!val.fRight) (out["!outline"] || (out["!outline"] = {})).left = true;
break; // TODO
case 0x0043: /* BIFF2XF */ case 0x0243: /* BIFF3XF */ case 0x0443: /* BIFF4XF */
case 0x00e0 /* XF */:
XFs.push(val); break;
case 0x01ae /* SupBook */:
@ -301,11 +299,11 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
case 0x0012 /* Protect */: out["!protect"] = val; break; /* for sheet or book */
case 0x0013 /* Password */: if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
case 0x0085 /* BoundSheet8 */: {
Directory[opts.biff == 4 ? opts.snames.length : val.pos] = val;
Directory[val.pos] = val;
opts.snames.push(val.name);
} break;
case 0x000a /* EOF */: {
if(--file_depth ? !biff4w : biff4w) break;
if(--file_depth) break;
if(range.e) {
if(range.e.r > 0 && range.e.c > 0) {
range.e.r--; range.e.c--;
@ -330,29 +328,27 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
} break;
case 0x0009: case 0x0209: case 0x0409: case 0x0809 /* BOF */: {
if(opts.biff === 8) opts.biff = {
0x0009: 2,
0x0209: 3,
0x0409: 4
/*::[*/0x0009/*::]*/:2,
/*::[*/0x0209/*::]*/:3,
/*::[*/0x0409/*::]*/:4
}[RecordType] || {
0x0200: 2,
0x0300: 3,
0x0400: 4,
0x0500: 5,
0x0600: 8,
0x0002: 2,
0x0007: 2
/*::[*/0x0200/*::]*/:2,
/*::[*/0x0300/*::]*/:3,
/*::[*/0x0400/*::]*/:4,
/*::[*/0x0500/*::]*/:5,
/*::[*/0x0600/*::]*/:8,
/*::[*/0x0002/*::]*/:2,
/*::[*/0x0007/*::]*/:2
}[val.BIFFVer] || 8;
opts.biffguess = val.BIFFVer == 0;
if(val.BIFFVer == 0 && val.dt == 0x1000) { opts.biff = 5; seen_codepage = true; set_cp(opts.codepage = 28591); }
if(opts.biff == 4 && val.dt & 0x100) biff4w = true;
if(opts.biff == 8 && val.BIFFVer == 0 && val.dt == 16) opts.biff = 2;
if(file_depth++ && !biff4w) break;
if(file_depth++) break;
out = ({}/*:any*/); if(options.dense) out["!data"] = [];
if(opts.biff < 8 && !seen_codepage) { seen_codepage = true; set_cp(opts.codepage = options.codepage || 1252); }
if(opts.biff == 4 && biff4w) {
cur_sheet = (Directory[opts.snames.indexOf(cur_sheet)+1] || {name:""}).name;
} else if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) {
if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) {
if(cur_sheet === "") cur_sheet = "Sheet1";
range = {s:{r:0,c:0},e:{r:0,c:0}};
/* fake BoundSheet8 */
@ -373,19 +369,19 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
case 0x0203 /* Number */: case 0x0003 /* BIFF2NUM */: case 0x0002 /* BIFF2INT */: {
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 = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
case 0x0005: case 0x0205 /* BoolErr */: {
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
case 0x027e /* RK */: {
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
@ -393,7 +389,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
for(var j = val.c; j <= val.C; ++j) {
var ixfe = val.rkrec[j-val.c][0];
temp_val= ({ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:j, r:val.r}, temp_val, options);
}
@ -411,7 +407,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
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 = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell(val.cell, temp_val, options);
last_formula = val;
@ -424,7 +420,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
if(options.cellFormula) {
temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
}
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell(last_formula.cell, temp_val, options);
last_formula = null;
@ -455,13 +451,13 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
temp_val=make_cell(sst[val.isst].t, val.ixfe, 's');
if(sst[val.isst].h) temp_val.h = sst[val.isst].h;
temp_val.XF = XFs[temp_val.ixfe];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
break;
case 0x0201 /* Blank */: if(options.sheetStubs) {
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
} break;
@ -469,7 +465,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
for(var _j = val.c; _j <= val.C; ++_j) {
var _ixfe = val.ixfe[_j-val.c];
temp_val= ({ixfe:_ixfe, XF:XFs[_ixfe], t:'z'}/*:any*/);
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:_j, r:val.r}, temp_val, options);
}
@ -478,7 +474,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
case 0x0204 /* Label */: case 0x0004 /* BIFF2STR */:
temp_val=make_cell(val.val, val.ixfe, 's');
temp_val.XF = XFs[temp_val.ixfe];
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
safe_format_xf(temp_val, options, wb.opts.Date1904);
addcell({c:val.c, r:val.r}, temp_val, options);
break;
@ -490,7 +486,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
sst = val;
} break;
case 0x041e /* Format */: { /* val = [id, fmt] */
if(opts.biff >= 3 && opts.biff <= 4) {
if(opts.biff == 4) {
BIFF2FmtTable[BIFF2Fmt++] = val[1];
for(var b4idx = 0; b4idx < BIFF2Fmt + 163; ++b4idx) if(table_fmt[b4idx] == val[1]) break;
if(b4idx >= 163) SSF__load(val[1], BIFF2Fmt + 163);
@ -524,8 +520,9 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
}
} break;
case 0x001c /* Note */: {
/* TODO: comment continuation (row == -1 / 0xFFFF) */
if(opts.biff <= 5 && opts.biff >= 2) break; /* TODO: BIFF5 */
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["!data"][val[0].r]) out["!data"][val[0].r] = [];
@ -539,12 +536,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
range.s.c = Math.min(range.s.c, val[0].c);
}
if(!cc.c) cc.c = [];
if(opts.biff <= 5 && opts.biff >= 2) cmnt = {a:"SheetJ5", t:val[1]};
else {
var noteobj = objects[val[2]];
cmnt = {a:val[1],t:noteobj.TxO.t};
if(val[3] != null && !(val[3] & 0x02)) cc.c.hidden = true;
}
cmnt = {a:val[1],t:noteobj.TxO.t};
cc.c.push(cmnt);
} break;
case 0x087d /* XFExt */: update_xfext(XFs[val.ixfe], val.ext); break;

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,15 @@ function write_biff_continue(ba/*:BufArray*/, type/*:number*/, payload, length/*
}
}
function write_BIFF2Cell(out, r/*:number*/, c/*:number*/) {
if(!out) out = new_buf(7);
out.write_shift(2, r);
out.write_shift(2, c);
out.write_shift(2, 0);
out.write_shift(1, 0);
return out;
}
function write_BIFF2BERR(r/*:number*/, c/*:number*/, val, t/*:?string*/) {
var out = new_buf(9);
write_BIFF2Cell(out, r, c);
@ -47,69 +56,37 @@ function write_BIFF2LABEL(r/*:number*/, c/*:number*/, val) {
return out.l < out.length ? out.slice(0, out.l) : out;
}
function write_comments_biff2(ba/*:BufArray*/, comments/*:Array<[Comment[], number, number]>*/) {
comments.forEach(function(data) {
var text = data[0].map(function(cc) { return cc.t; }).join("");
// TODO: should '\n' be translated to '\r' to correct for Excel 5.0 bug when exporting to BIFF2/3 ?
if(text.length <= 2048) return write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text, data[1], data[2]));
write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text.slice(0, 2048), data[1], data[2], text.length));
for(var i = 2048; i < text.length; i += 2048)
write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text.slice(i, Math.min(i+2048, text.length)), -1, -1, Math.min(2048, text.length - i)));
});
}
/* TODO: BIFF3/4 use different records -- see comments*/
function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/) {
var ifmt = 0;
if(cell.z != null) {
ifmt = opts._BIFF2FmtTable.indexOf(cell.z);
if(ifmt == -1) { opts._BIFF2FmtTable.push(cell.z); ifmt = opts._BIFF2FmtTable.length - 1; }
}
var ixfe = 0;
if(cell.z != null) {
for(; ixfe < opts.cellXfs.length; ++ixfe) if(opts.cellXfs[ixfe].numFmtId == ifmt) break;
if(ixfe == opts.cellXfs.length) opts.cellXfs.push({numFmtId: ifmt});
}
function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*//*::, opts*/) {
if(cell.v != null) switch(cell.t) {
case 'd': case 'n':
var v = cell.t == 'd' ? datenum(parseDate(cell.v, date1904), date1904) : cell.v;
if(opts.biff == 2 && (v == (v|0)) && (v >= 0) && (v < 65536))
// 0x027E (RK) in BIFF3/4
write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v, ixfe, ifmt));
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))
// 0x0205 in BIFF3/4
write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x24, "e")); // #NUM!
else if(!isFinite(v))
// 0x0205 in BIFF3/4
write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x07, "e")); // #DIV/0!
else
// 0x0203 in BIFF3/4
write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v, ixfe, ifmt));
write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v));
return;
case 'b': case 'e':
// 0x0205 in BIFF3/4
write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); 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':
// 0x0204 in BIFF3/4
write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v == null ? "" : String(cell.v).slice(0,255)));
return;
}
// 0x0201 in BIFF3/4
write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
}
function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
var dense = ws["!data"] != null;
var range = safe_decode_range(ws['!ref'] || "A1"), rr = "", cols/*:Array<string>*/ = [];
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);
}
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
var row = [], comments = [];
/* TODO: 0x0000 / 0x0200 dimensions? */
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] || [];
@ -118,300 +95,26 @@ function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts,
var cell = dense ? row[C] : ws[cols[C] + rr];
if(!cell) continue;
/* write cell */
write_ws_biff2_cell(ba, cell, R, C, opts, date1904);
if(cell.c) comments.push([cell.c, R, C]);
write_ws_biff2_cell(ba, cell, R, C, opts);
}
}
/* ... 0x12 0x19 0x13 (Password) */
write_comments_biff2(ba, comments);
/* 0x3d (Window1) ... */
}
/* Based on test files */
function write_biff2_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
var o = opts || {};
var ba = buf_array();
var idx = 0;
for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i;
if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
write_biff_rec(ba, (o.biff == 4 ? 0x0409 : (o.biff == 3 ? 0x0209 : 0x0009)), write_BOF(wb, 0x10, o));
if(((wb.Workbook||{}).WBProps||{}).date1904) write_biff_rec(ba, 0x0022, writebool(true));
o.cellXfs = [{numFmtId: 0}];
o._BIFF2FmtTable/*:Array<string>*/ = ["General"]; o._Fonts = [];
var body = buf_array();
write_ws_biff2(body, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
o._BIFF2FmtTable.forEach(function(f) {
if(o.biff <= 3) write_biff_rec(ba, 0x001E, write_BIFF2Format(f));
else write_biff_rec(ba, 0x041E, write_BIFF4Format(f));
});
o.cellXfs.forEach(function(xf) {
switch(o.biff) {
case 2: write_biff_rec(ba, 0x0043, write_BIFF2XF(xf)); break;
case 3: write_biff_rec(ba, 0x0243, write_BIFF3XF(xf)); break;
case 4: write_biff_rec(ba, 0x0443, write_BIFF4XF(xf)); break;
}
});
delete o._BIFF2FmtTable; delete o.cellXfs; delete o._Fonts;
ba.push(body.end());
/* ... */
write_ws_biff2(ba, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
/* ... */
write_biff_rec(ba, 0x000A);
return ba.end();
}
var b8oid = 1, b8ocnts/*:Array<[number, number, number]>*/ = [];
function write_MsoDrawingGroup() {
var buf = new_buf(82 + 8 * b8ocnts.length);
/* [MS-ODRAW] 2.2.12 OfficeArtDggContainer */
buf.write_shift(2, 0x0F);
buf.write_shift(2, 0xF000);
buf.write_shift(4, 74 + 8 * b8ocnts.length);
/* 2.2.48 OfficeArtFDGGBlock */
{
buf.write_shift(2, 0);
buf.write_shift(2, 0xF006);
buf.write_shift(4, 16 + 8 * b8ocnts.length);
/* 2.2.47 OfficeArtFDGG */
{
buf.write_shift(4, b8oid);
buf.write_shift(4, b8ocnts.length+1);
var acc = 0; for(var i = 0; i < b8ocnts.length; ++i) acc += (b8ocnts[i] && b8ocnts[i][1] || 0); buf.write_shift(4, acc);
buf.write_shift(4, b8ocnts.length);
}
/* 2.2.46 OfficeArtIDCL + */
b8ocnts.forEach(function(b8) {
buf.write_shift(4, b8[0]);
buf.write_shift(4, b8[2]);
});
}
/* 2.2.9 OfficeArtFOPT */
{
buf.write_shift(2, 0x33); // 0x03 | (3 << 4)
buf.write_shift(2, 0xF00B);
buf.write_shift(4, 0x12); // 3 * 6
/* 2.3.21.15 Text Boolean Properties */
buf.write_shift(2, 0xBF); buf.write_shift(4, 0x00080008);
/* 2.3.7.2 fillColor */
buf.write_shift(2, 0x0181); buf.write_shift(4, 0x08000041);
/* 2.3.8.1 lineColor */
buf.write_shift(2, 0x01C0); buf.write_shift(4, 0x08000040);
}
/* 2.2.45 OfficeArtSplitMenuColorContainer */
{
buf.write_shift(2, 0x40);
buf.write_shift(2, 0xF11E);
buf.write_shift(4, 16);
buf.write_shift(4, 0x0800000D);
buf.write_shift(4, 0x0800000C);
buf.write_shift(4, 0x08000017);
buf.write_shift(4, 0x100000F7);
}
return buf;
}
function write_comments_biff8(ba/*:BufArray*/, comments/*:Array<[Comment[], number, number]>*/) {
var notes/*:Array<RawData>*/ = [], sz = 0, pl = buf_array(), baseid = b8oid;
var _oasc;
comments.forEach(function(c, ci) {
var author = "";
var text = c[0].map(function(t) { if(t.a && !author) author = t.a; return t.t; }).join("");
++b8oid;
/* 2.2.14 OfficeArtSpContainer */
{
var oasc = new_buf(0x96);
oasc.write_shift(2, 0x0F);
oasc.write_shift(2, 0xF004);
oasc.write_shift(4, 0x96);
/* 2.2.40 OfficeArtFSP */
{
oasc.write_shift(2, 0xca2); // 0x02 | (0xca << 4)
oasc.write_shift(2, 0xF00A);
oasc.write_shift(4, 8);
oasc.write_shift(4, b8oid);
oasc.write_shift(4, 0xA00);
}
/* 2.2.9 OfficeArtFOPT */
{
oasc.write_shift(2, 0xE3); // 0x03 | (14 << 4)
oasc.write_shift(2, 0xF00B);
oasc.write_shift(4, 0x54); // 14 * 6
/* 2.3.21.1 ITxid */
oasc.write_shift(2, 0x80); oasc.write_shift(4, 0);
/* 2.3.21.12 txdir */
oasc.write_shift(2, 0x8B); oasc.write_shift(4, 0x02);
/* 2.3.21.15 Text Boolean Properties */
oasc.write_shift(2, 0xBF); oasc.write_shift(4, 0x00080008);
/* 2.3.6.30 cxk */
oasc.write_shift(2, 0x0158); oasc.l += 4;
/* 2.3.7.2 fillColor */
oasc.write_shift(2, 0x0181); oasc.write_shift(4, 0x08000050);
/* 2.3.7.4 fillBackColor */
oasc.write_shift(2, 0x0183); oasc.write_shift(4, 0x08000050);
/* 2.3.7.6 fillCrMod */
oasc.write_shift(2, 0x0185); oasc.write_shift(4, 0x100000F4);
/* 2.3.7.43 Fill Style Boolean Properties */
oasc.write_shift(2, 0x01BF); oasc.write_shift(4, 0x00100010);
/* 2.3.8.1 lineColor */
oasc.write_shift(2, 0x01C0); oasc.write_shift(4, 0x08000051);
/* 2.3.8.4 lineCrMod */
oasc.write_shift(2, 0x01C3); oasc.write_shift(4, 0x100000F4);
/* 2.3.13.2 shadowColor */
oasc.write_shift(2, 0x0201); oasc.write_shift(4, 0x08000051);
/* 2.3.13.4 shadowCrMod */
oasc.write_shift(2, 0x0203); oasc.write_shift(4, 0x100000F4);
/* 2.3.13.23 Shadow Style Boolean Properties */
oasc.write_shift(2, 0x023F); oasc.write_shift(4, 0x00030001);
/* 2.3.4.44 Group Shape Boolean Properties */
oasc.write_shift(2, 0x03BF); oasc.write_shift(4, 0x00020000 | (c[0].hidden ? 2 : 0));
}
/* [MS-XLS] 2.5.193 OfficeArtClientAnchorSheet */
{
oasc.l += 2;
oasc.write_shift(2, 0xF010);
oasc.write_shift(4, 0x12);
oasc.write_shift(2, 0x3); // do not move or size with cells
oasc.write_shift(2, c[2] + 2); oasc.l += 2;
oasc.write_shift(2, c[1] + 1); oasc.l += 2;
oasc.write_shift(2, c[2] + 4); oasc.l += 2;
oasc.write_shift(2, c[1] + 5); oasc.l += 2;
}
/* [MS-XLS] 2.5.194 OfficeArtClientData */
{
oasc.l += 2;
oasc.write_shift(2, 0xF011);
oasc.l += 4;
}
oasc.l = 0x96;
if(ci == 0) /* write_biff_rec(pl, 0x003C, oasc); */ _oasc = oasc;
else write_biff_rec(pl, 0x00EC, oasc);
}
sz += 0x96;
/* [MS-XLS] 2.4.181 Obj */
{
var obj = new_buf(52); // 22 + 26 + 4
/* [MS-XLS] 2.5.143 FtCmo */
obj.write_shift(2, 0x15);
obj.write_shift(2, 0x12);
obj.write_shift(2, 0x19);
obj.write_shift(2, b8oid);
obj.write_shift(2, 0);
obj.l = 22;
/* [MS-XLS] 2.5.149 FtNts */
obj.write_shift(2, 0x0D);
obj.write_shift(2, 0x16);
obj.write_shift(4, 0x62726272);
obj.write_shift(4, 0x95374305);
obj.write_shift(4, 0x80301328);
obj.write_shift(4, 0x69696904 + b8oid*256);
obj.write_shift(2,0);
obj.write_shift(4,0);
// reserved
obj.l += 4;
write_biff_rec(pl, 0x005D, obj);
}
/* [MS-XLS] 2.5.195 OfficeArtClientTextbox */
{
var oact = new_buf(8);
oact.l += 2;
oact.write_shift(2, 0xF00D);
oact.l += 4;
write_biff_rec(pl, 0x00EC, oact);
}
sz += 8;
/* [MS-XLS] 2.4.329 TxO */
{
var txo = new_buf(18);
txo.write_shift(2, 0x12);
txo.l += 8;
txo.write_shift(2, text.length);
txo.write_shift(2, 0x10);
txo.l += 4;
write_biff_rec(pl, 0x01b6, txo);
/* text continue record TODO: switch to wide strings */
{
var cont = new_buf(1 + text.length);
cont.write_shift(1, 0);
cont.write_shift(text.length, text, "sbcs");
write_biff_rec(pl, 0x003C, cont);
}
/* formatting continue records */
{
var conf = new_buf(0x10);
conf.l += 8;
conf.write_shift(2, text.length);
conf.l += 6;
write_biff_rec(pl, 0x003C, conf);
}
}
/* 2.4.179 Note */
{
var notesh = new_buf(12 + author.length);
notesh.write_shift(2, c[1]);
notesh.write_shift(2, c[2]);
notesh.write_shift(2, 0 | (c[0].hidden ? 0 : 2));
notesh.write_shift(2, b8oid);
notesh.write_shift(2, author.length);
notesh.write_shift(1, 0);
notesh.write_shift(author.length, author, "sbcs");
notesh.l ++;
notes.push(notesh);
}
});
/* [MS-ODRAW] 2.2.13 OfficeArtDgContainer */
{
var hdr = new_buf(80);
hdr.write_shift(2, 0x0F);
hdr.write_shift(2, 0xF002);
hdr.write_shift(4, sz + hdr.length - 8);
/* [MS-ODRAW] 2.2.49 OfficeArtFDG */
{
hdr.write_shift(2, 0x10);
hdr.write_shift(2, 0xF008);
hdr.write_shift(4, 0x08);
hdr.write_shift(4, comments.length + 1);
hdr.write_shift(4, b8oid);
}
/* [MS-ODRAW] 2.2.16 OfficeArtSpgrContainer */
{
hdr.write_shift(2, 0x0f);
hdr.write_shift(2, 0xF003);
hdr.write_shift(4, sz + 0x30);
/* [MS-ODRAW] 2.2.14 OfficeArtSpContainer */
{
hdr.write_shift(2, 0x0f);
hdr.write_shift(2, 0xF004);
hdr.write_shift(4, 0x28);
/* [MS-ODRAW] 2.2.38 OfficeArtFSPGR */
{
hdr.write_shift(2, 0x01);
hdr.write_shift(2, 0xF009);
hdr.write_shift(4, 0x10);
hdr.l += 16;
}
/* [MS-ODRAW] 2.2.40 OfficeArtFSP */
{
hdr.write_shift(2, 0x02);
hdr.write_shift(2, 0xF00A);
hdr.write_shift(4, 0x08);
hdr.write_shift(4, baseid);
hdr.write_shift(4, 0x05);
}
}
}
write_biff_rec(ba, 0x00EC, /* hdr */ _oasc ? bconcat([hdr, _oasc]) : hdr);
}
ba.push(pl.end());
notes.forEach(function(n) { write_biff_rec(ba, 0x001C, n); });
b8ocnts.push([baseid, comments.length + 1, b8oid]);
++b8oid;
}
function write_FONTS_biff8(ba, data, opts) {
write_biff_rec(ba, 0x0031 /* Font */, write_Font({
sz:12,
@ -473,7 +176,7 @@ function write_ws_cols_biff8(ba, cols) {
});
}
function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/) {
function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) {
var os = 16 + get_cell_style(opts.cellXfs, cell, opts);
if(cell.v == null && !cell.bf) {
write_biff_rec(ba, 0x0201 /* Blank */, write_XLSCell(R, C, os));
@ -482,7 +185,7 @@ function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n
if(cell.bf) write_biff_rec(ba, 0x0006 /* Formula */, write_Formula(cell, R, C, opts, os));
else switch(cell.t) {
case 'd': case 'n':
var v = cell.t == 'd' ? datenum(parseDate(cell.v, date1904), date1904) : cell.v;
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 */
@ -543,11 +246,10 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
write_biff_rec(ba, 0x0200 /* Dimensions */, write_Dimensions(range, opts));
/* ... */
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
if(b8) ws['!links'] = [];
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
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);
@ -556,14 +258,14 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
var cell = dense ? row[C] : ws[ref];
if(!cell) continue;
/* write cell */
write_ws_biff8_cell(ba, cell, R, C, opts, date1904);
write_ws_biff8_cell(ba, cell, R, C, opts);
if(b8 && cell.l) ws['!links'].push([ref, cell.l]);
if(cell.c) comments.push([cell.c, R, C]);
if(b8 && cell.c) comments.push([ref, cell.c]);
}
}
var cname/*:string*/ = _sheet.CodeName || _sheet.name || s;
/* ... */
if(b8) write_comments_biff8(ba, comments); else write_comments_biff2(ba, comments);
// if(b8) comments.forEach(function(comment) { write_biff_rec(ba, 0x001c /* Note */, write_NoteSh(comment)); });
/* ... */
if(b8) write_biff_rec(ba, 0x023e /* Window2 */, write_Window2((_WB.Views||[])[0]));
/* ... */
@ -633,10 +335,8 @@ function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) {
var C = buf_array();
/* METADATA [MTRSettings] [ForceFullCalculation] */
if(b8) write_biff_rec(C, 0x008C /* Country */, write_Country());
/* *SUPBOOK *LBL *RTD [RecalcId] *HFPicture */
/* *SUPBOOK *LBL *RTD [RecalcId] *HFPicture *MSODRAWINGGROUP */
/* BIFF8: MsoDrawingGroup [*Continue] */
if(b8 && b8ocnts.length) write_biff_rec(C, 0x00EB /* MsoDrawingGroup */, write_MsoDrawingGroup());
/* BIFF8: [SST *Continue] ExtSST */
if(b8 && opts.Strings) write_biff_continue(C, 0x00FC /* SST */, write_SST(opts.Strings, opts));
@ -679,7 +379,6 @@ function write_biff8_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
o.ssf = wb.SSF;
}
b8oid = 1; b8ocnts = [];
o.Strings = /*::((*/[]/*:: :any):SST)*/; o.Strings.Count = 0; o.Strings.Unique = 0;
fix_write_opts(o);

View File

@ -3,12 +3,12 @@ function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ {
var opts = _opts || {};
var dense = (opts.dense != null) ? opts.dense : DENSE;
var ws/*:Worksheet*/ = ({}/*:any*/); if(dense) ws["!data"] = [];
str = str_remove_ng(str, "<!--", "-->");
str = str.replace(/<!--.*?-->/g, "");
var mtch/*:any*/ = str.match(/<table/i);
if(!mtch) throw new Error("Invalid HTML: could not find <table>");
var mtch2/*:any*/ = str.match(/<\/table/i);
var i/*:number*/ = mtch.index, j/*:number*/ = mtch2 && mtch2.index || str.length;
var rows = split_regex(str.slice(i, j), /(:?<tr[^<>]*>)/i, "<tr>");
var rows = split_regex(str.slice(i, j), /(:?<tr[^>]*>)/i, "<tr>");
var R = -1, C = 0, RS = 0, CS = 0;
var range/*:Range*/ = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
var merges/*:Array<Range>*/ = [];
@ -45,11 +45,9 @@ function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ {
else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)};
else if(!isNaN(fuzzydate(m).getDate())) {
o = ({t:'d', v:parseDate(m)}/*:any*/);
if(opts.UTC === false) o.v = utc_to_local(o.v);
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
o.z = opts.dateNF || table_fmt[14];
}
if(o.cellText !== false) o.w = m;
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;
@ -83,8 +81,7 @@ function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HT
if(o.editable) w = '<span contenteditable="true">' + w + '</span>';
else if(cell) {
sp["data-t"] = cell && cell.t || 'z';
// note: data-v is unaffected by the timezone interpretation
if(cell.v != null) sp["data-v"] = escapehtml(cell.v instanceof Date ? cell.v.toISOString() : cell.v);
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="' + escapehtml(cell.l.Target) +'">' + w + '</a>';
}
@ -99,7 +96,7 @@ var HTML_BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export
var HTML_END = '</body></html>';
function html_to_workbook(str/*:string*/, opts)/*:Workbook*/ {
var mtch = str_match_xml_ig(str, "table");
var mtch = str.match(/<table[\s\S]*?>[\s\S]*?<\/table>/gi);
if(!mtch || mtch.length == 0) throw new Error("Invalid HTML: could not find <table>");
if(mtch.length == 1) {
var w = sheet_to_workbook(html_to_sheet(mtch[0], opts), opts);
@ -122,9 +119,9 @@ function sheet_to_html(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*//*, wb:?Workboo
var header = o.header != null ? o.header : HTML_BEGIN;
var footer = o.footer != null ? o.footer : HTML_END;
var out/*:Array<string>*/ = [header];
var r = decode_range(ws['!ref'] || "A1");
var r = decode_range(ws['!ref']);
out.push(make_html_preamble(ws, r, o));
if(ws["!ref"]) for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, 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);
return out.join("");
}
@ -190,7 +187,6 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
else if(!isNaN(fuzzydate(v).getDate())) {
o = ({t:'d', v:parseDate(v)}/*:any*/);
if(opts.UTC) o.v = local_to_utc(o.v);
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
o.z = opts.dateNF || table_fmt[14];
}

View File

@ -5,9 +5,9 @@ function parse_text_p(text/*:string*//*::, tag*/)/*:Array<any>*/ {
.replace(/[\t\r\n]/g, " ").trim().replace(/ +/g, " ")
.replace(/<text:s\/>/g," ")
.replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); })
.replace(/<text:tab[^<>]*\/>/g,"\t")
.replace(/<text:tab[^>]*\/>/g,"\t")
.replace(/<text:line-break\/>/g,"\n");
var v = unescapexml(fixed.replace(/<[^<>]*>/g,""));
var v = unescapexml(fixed.replace(/<[^>]*>/g,""));
return [v];
}
@ -17,10 +17,10 @@ function parse_ods_styles(d/*:string*/, _opts, _nfm) {
var number_format_map = _nfm || {};
var str = xlml_normalize(d);
xlmlregex.lastIndex = 0;
str = remove_doctype(str_remove_ng(str, "<!--", "-->"));
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
var Rn, NFtag, NF = "", tNF = "", y, etpos = 0, tidx = -1, infmt = false, payload = "";
while((Rn = xlmlregex.exec(str))) {
switch((Rn[3]=Rn[3].replace(/_[\s\S]*$/,""))) {
switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
/* Number Format Definitions */
case 'number-style': // <number:number-style> 16.29.2
case 'currency-style': // <number:currency-style> 16.29.8
@ -248,8 +248,8 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
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/*:: = {}*/, oldtextp = "", oldtextpidx = 0;
var textR = [], oldtextR = [];
var textp = "", textpidx = 0, textptag/*:: = {}*/;
var textR = [];
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
var row_ol = 0;
var number_format_map = _nfm || {}, styles = {};
@ -263,9 +263,10 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
var creator = "", creatoridx = 0;
var isstub = false, intable = false;
var i = 0;
var baddate = 0;
xlmlregex.lastIndex = 0;
str = remove_doctype(str_remove_ng(str, "<!--", "-->"));
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_[\s\S]*$/,""))) {
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
case 'table': case '工作表': // 9.1.2 <table:table>
if(Rn[1]==='/') {
@ -333,7 +334,7 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
C+= colpeat-1;
} else if(Rn[1]!=='/') {
++C;
textp = oldtextp = ""; textpidx = oldtextpidx = 0; textR = []; oldtextR = [];
textp = ""; textpidx = 0; textR = [];
colpeat = 1;
var rptR = rowpeat ? R + rowpeat - 1 : R;
if(C > range.e.c) range.e.c = C;
@ -369,23 +370,19 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
/* 19.675.2 table:number-columns-repeated */
if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10);
/* 19.385 office:value-type TODO: verify ODS and UOS */
/* 19.385 office:value-type */
switch(q.t) {
case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']) || (+ctag['boolean-value'] >= 1); break;
case 'float': q.t = 'n'; q.v = parseFloat(ctag.value);
if(opts.cellDates && q.z && fmt_is_date(q.z)) { q.v = numdate(q.v + (WB.WBProps.date1904 ? 1462 : 0)); q.t = typeof q.v == "number" ? 'n' : 'd'; }
break;
case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value'], WB.WBProps.date1904);
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904); }
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']);
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904) - baddate; }
if(!q.z) q.z = 'm/d/yy'; break;
/* NOTE: for `time`, Excel ODS export incorrectly uses durations relative to 1900 epoch even if 1904 is specified */
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400;
if(opts.cellDates) { q.v = numdate(q.v); q.t = typeof q.v == "number" ? 'n' : 'd'; }
if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); }
if(!q.z) q.z = 'HH:MM:SS'; break;
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']);
break;
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
default:
if(q.t === 'string' || q.t === 'text' || !q.t) {
q.t = 's';
@ -446,17 +443,10 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
if(textR.length) /*::(*/comment/*:: :any)*/.R = textR;
comment.a = creator;
comments.push(comment);
textp = oldtextp; textpidx = oldtextpidx; textR = oldtextR;
}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
state.push([Rn[3], false]);
var annotag = parsexmltag(Rn[0], true);
/* office:display TODO: check if there is a global override */
if(!(annotag["display"] && parsexmlbool(annotag["display"]))) comments.hidden = true;
oldtextp = textp; oldtextpidx = textpidx; oldtextR = textR;
textp = ""; textpidx = 0; textR = [];
}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);}
creator = ""; creatoridx = 0;
textp = ""; textpidx = 0; textR = [];
break;
case 'creator': // 4.3.2.7 <dc:creator>
@ -582,7 +572,9 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
case 'null-date': // 9.4.2 <table:null-date>
tag = parsexmltag(Rn[0], false);
switch(tag["date-value"]) {
case "1904-01-01": WB.WBProps.date1904 = true; break;
case "1904-01-01": WB.WBProps.date1904 = true;
/* falls through */
case "1900-01-01": baddate = 0;
}
break;
@ -636,13 +628,10 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
case 'help-message': break; // 9.4.6 <table:
case 'error-message': break; // 9.4.7 <table:
case 'database-ranges': break; // 9.4.14 <table:database-ranges>
/* 9.5 Filters */
case 'filter': break; // 9.5.2 <table:filter>
case 'filter-and': break; // 9.5.3 <table:filter-and>
case 'filter-or': break; // 9.5.4 <table:filter-or>
case 'filter-condition': break; // 9.5.5 <table:filter-condition>
case 'filter-set-item': break; // 9.5.6 <table:filter-condition>
case 'list-level-style-bullet': break; // 16.31 <text:
case 'list-level-style-number': break; // 16.32 <text:

View File

@ -67,7 +67,7 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
if((t=nf.match(/# (\?+)\/(\d+)/))) { payload += writextag("number:fraction", null, {"number:min-integer-digits":0, "number:min-numerator-digits": t[1].length, "number:denominator-value": +t[2]}); break j; }
/* percentages */
if((t=nf.match(/\b(\d+)(|\.\d+)%/))) { type = "percentage"; payload += writextag("number:number", null, {"number:decimal-places": t[2] && t.length - 1 || 0, "number:min-decimal-places": t[2] && t.length - 1 || 0, "number:min-integer-digits": t[1].length }) + "<number:text>%</number:text>"; break j; }
if((t=nf.match(/(\d+)(|\.\d+)%/))) { type = "percentage"; payload += writextag("number:number", null, {"number:decimal-places": t[2] && t.length - 1 || 0, "number:min-decimal-places": t[2] && t.length - 1 || 0, "number:min-integer-digits": t[1].length }) + "<number:text>%</number:text>"; break j; }
/* datetime */
var has_time = false;
@ -99,9 +99,7 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
break;
case '\\': c = nf[++i];
payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
case '/': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
default: console.error("unrecognized character " + c + " in ODF format " + nf);
}
if(!has_time) break j;
@ -128,7 +126,7 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
break;
case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
case '/': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
case "a":
if(nf.slice(i, i+3).toLowerCase() == "a/p") { payload += '<number:am-pm/>'; i += 2; break; } // Note: ODF does not support A/P
if(nf.slice(i, i+5).toLowerCase() == "am/pm") { payload += '<number:am-pm/>'; i += 4; break; }
@ -184,34 +182,30 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
}
function write_names_ods(Names, SheetNames, idx) {
//var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
var scoped = []; for(var namei = 0; namei < Names.length; ++namei) {
var name = Names[namei];
if(!name) continue;
if(name.Sheet == (idx == -1 ? null : idx)) scoped.push(name);
}
var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
if(!scoped.length) return "";
return " <table:named-expressions>\n" + scoped.map(function(name) {
var odsref = (idx == -1 ? "$" : "") + csf_to_ods_3D(name.Ref);
var odsref = csf_to_ods_3D(name.Ref);
return " " + writextag("table:named-range", null, {
"table:name": name.Name,
"table:cell-range-address": odsref,
"table:base-cell-address": odsref.replace(/[\.][^\.]*$/, ".$A$1")
"table:base-cell-address": odsref.replace(/[\.]?[^\.]*$/, ".$A$1")
});
}).join("\n") + "\n </table:named-expressions>\n";
}
var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function() {
/* 6.1.2 White Space Characters */
var write_text_p = function(text/*:string*/, span)/*:string*/ {
var write_text_p = function(text/*:string*/)/*:string*/ {
return escapexml(text)
.replace(/ +/g, function($$){return '<text:s text:c="'+$$.length+'"/>';})
.replace(/\t/g, "<text:tab/>")
.replace(/\n/g, span ? "<text:line-break/>": "</text:p><text:p>")
.replace(/\n/g, "</text:p><text:p>")
.replace(/^ /, "<text:s/>").replace(/ $/, "<text:s/>");
};
var null_cell_xml = ' <table:table-cell />\n';
var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts, nfs, date1904)/*:string*/ {
var covered_cell_xml = ' <table:covered-table-cell/>\n';
var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts, nfs)/*:string*/ {
/* Section 9 Tables */
var o/*:Array<string>*/ = [];
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="ta1">\n');
@ -242,7 +236,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
ct['table:number-rows-spanned'] = (marr[mi].e.r - marr[mi].s.r + 1);
break;
}
if(skip) { o.push(' <table:covered-table-cell/>\n'); continue; }
if(skip) { o.push(covered_cell_xml); continue; }
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));
@ -271,13 +265,13 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
ct['office:value-type'] = "string";
break;
case 'd':
textp = (cell.w||(parseDate(cell.v, date1904).toISOString()));
textp = (cell.w||(parseDate(cell.v).toISOString()));
ct['office:value-type'] = "date";
ct['office:date-value'] = (parseDate(cell.v, date1904).toISOString());
ct['office:date-value'] = (parseDate(cell.v).toISOString());
ct['table:style-name'] = "ce1";
break;
//case 'e': // TODO: translate to ODS errors
default: o.push(null_cell_xml); continue; // TODO: empty cell with comments
//case 'e':
default: o.push(null_cell_xml); continue;
}
var text_p = write_text_p(textp);
if(cell.l && cell.l.Target) {
@ -288,17 +282,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
text_p = writextag('text:a', text_p, {'xlink:href': _tgt.replace(/&/g, "&amp;")});
}
if(nfs[cell.z]) ct["table:style-name"] = "ce" + nfs[cell.z].slice(1);
var payload = writextag('text:p', text_p, {});
if(cell.c) {
var acreator = "", apayload = "", aprops = {};
for(var ci = 0; ci < cell.c.length; ++ci) {
if(!acreator && cell.c[ci].a) acreator = cell.c[ci].a;
apayload += "<text:p>" + write_text_p(cell.c[ci].t) + "</text:p>";
}
if(!cell.c.hidden) aprops["office:display"] = true;
payload = writextag('office:annotation', apayload, aprops) + payload;
}
o.push(' ' + writextag('table:table-cell', payload, ct) + '\n');
o.push(' ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n');
}
o.push(' </table:table-row>\n');
}
@ -364,7 +348,6 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
if(!ws) return;
var dense = (ws["!data"] != null);
if(!ws["!ref"]) return;
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 = dense ? (ws["!data"][R]||[])[C] : ws[encode_cell({r:R,c:C})];
@ -436,7 +419,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
if(opts.bookType == "fods") {
o.push('<office:document' + attr + fods + '>\n');
o.push(write_meta_ods().replace(/<office:document-meta[^<>]*?>/, "").replace(/<\/office:document-meta>/, "") + "\n");
o.push(write_meta_ods().replace(/<office:document-meta.*?>/, "").replace(/<\/office:document-meta>/, "") + "\n");
// TODO: settings (equiv of settings.xml for ODS)
} else o.push('<office:document-content' + attr + '>\n');
// o.push(' <office:scripts/>\n');
@ -444,7 +427,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
o.push(' <office:body>\n');
o.push(' <office:spreadsheet>\n');
if(((wb.Workbook||{}).WBProps||{}).date1904) o.push(' <table:calculation-settings table:case-sensitive="false" table:search-criteria-must-apply-to-whole-cell="true" table:use-wildcards="true" table:use-regular-expressions="false" table:automatic-find-labels="false">\n <table:null-date table:date-value="1904-01-01"/>\n </table:calculation-settings>\n');
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs, ((wb.Workbook||{}).WBProps||{}).date1904));
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs));
if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1));
o.push(' </office:spreadsheet>\n');
o.push(' </office:body>\n');

File diff suppressed because it is too large Load Diff

View File

@ -13,13 +13,6 @@ function safe_parse_wbrels(wbrels, sheets) {
return !wbrels || wbrels.length === 0 ? null : wbrels;
}
function parse_sheet_legacy_drawing(sheet, type, zip, path, idx, opts, wb, comments) {
if(!sheet || !sheet['!legdrawel']) return;
var dfile = resolve_path(sheet['!legdrawel'].Target, path);
var draw = getzipstr(zip, dfile, true);
if(draw) parse_vml(utf8read(draw), sheet, comments||[]);
}
function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/*:number*/, sheetRels, sheets, stype/*:string*/, opts, wb, themes, styles) {
try {
sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
@ -58,7 +51,6 @@ function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/
}
});
if(tcomments && tcomments.length) sheet_insert_comments(_ws, tcomments, true, opts.people || []);
parse_sheet_legacy_drawing(_ws, stype, zip, path, idx, opts, wb, comments);
} catch(e) { if(opts.WTF) throw e; }
}
@ -204,7 +196,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
if(wbrels && wbrels[i]) {
path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
if(!safegetzipfile(zip, path)) path = wbrels[i][1];
if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/[\S\s]*$/,"") + wbrels[i][1];
if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/.*$/,"") + wbrels[i][1];
stype = wbrels[i][2];
} else {
path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
@ -257,7 +249,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,strip_front_slash(dir.vba[0]),true);
else if(dir.defaults && dir.defaults.bin === CT_VBA) out.vbaraw = getzipdata(zip, 'xl/vbaProject.bin',true);
}
// TODO: pass back content types metadata for xlsm/xlsx resolution
// TODO: pass back content types metdata for xlsm/xlsx resolution
out.bookType = xlsb ? "xlsb" : "xlsx";
return out;
}

View File

@ -51,9 +51,6 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
add_rels(opts.rels, 4, f, RELS.CUST_PROPS);
}
var people = ["SheetJ5"];
opts.tcid = 0;
for(rId=1;rId <= wb.SheetNames.length; ++rId) {
var wsrels = {'!id':{}};
var ws = wb.Sheets[wb.SheetNames[rId-1]];
@ -73,17 +70,6 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
var need_vml = false;
var cf = "";
if(comments && comments.length > 0) {
var needtc = false;
comments.forEach(function(carr) {
carr[1].forEach(function(c) { if(c.T == true) needtc = true; });
});
if(needtc) {
cf = "xl/threadedComments/threadedComment" + rId + ".xml";
zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts));
ct.threadedcomments.push(cf);
add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + ".xml", RELS.TCMNT);
}
cf = "xl/comments" + rId + "." + wbext;
zip_add_file(zip, cf, write_comments_bin(comments, opts));
ct.comments.push(cf);
@ -139,13 +125,6 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
ct.metadata.push(f);
add_rels(opts.wbrels, -1, "metadata." + wbext, RELS.XLMETA);
if(people.length > 1) {
f = "xl/persons/person.xml";
zip_add_file(zip, f, write_people_xml(people, opts));
ct.people.push(f);
add_rels(opts.wbrels, -1, "persons/person.xml", RELS.PEOPLE);
}
zip_add_file(zip, "[Content_Types].xml", write_ct(ct, opts));
zip_add_file(zip, '_rels/.rels', write_rels(opts.rels));
zip_add_file(zip, 'xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));

View File

@ -15,7 +15,7 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
}
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 == null || val.t === undefined) {
if(val === undefined || val.t === undefined) {
if(defval === undefined) continue;
if(hdr[C] != null) { row[hdr[C]] = defval; }
continue;
@ -24,12 +24,7 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
switch(val.t){
case 'z': if(v == null) break; continue;
case 'e': v = (v == 0 ? null : void 0); break;
case 's': case 'b':
case 'n': if(!val.z || !fmt_is_date(val.z)) break;
v = numdate(v); // TODO: date1904 setting should also be stored in worksheet object
if(typeof v == "number") break;
/* falls through */
case 'd': if(!(o && (o.UTC||(o.raw === false)))) v = utc_to_local(new Date(v)); break;
case 's': case 'd': case 'b': case 'n': break;
default: throw new Error('unrecognized type ' + val.t);
}
if(hdr[C] != null) {
@ -39,7 +34,7 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
else if(raw && v === null) row[hdr[C]] = null;
else continue;
} else {
row[hdr[C]] = (val.t === 'n' && typeof o.rawNumbers === 'boolean' ? o.rawNumbers : raw) ? v : format_cell(val, v, o);
row[hdr[C]] = raw && (val.t !== "n" || (val.t === "n" && o.rawNumbers !== false)) ? v : format_cell(val,v,o);
}
if(v != null) isempty = false;
}
@ -125,7 +120,6 @@ function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Arr
/* NOTE: Excel CSV does not support array formulae */
row.push(txt);
}
if(o.strip) while(row[row.length - 1] === "") --row.length;
if(o.blankrows === false && isempty) return null;
return row.join(FS);
}
@ -137,6 +131,7 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ {
var r = safe_decode_range(sheet["!ref"]);
var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
var row = "", cols/*:Array<string>*/ = [];
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
var rowinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!rows"] || [];
@ -146,6 +141,7 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ {
if ((rowinfo[R]||{}).hidden) continue;
row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o);
if(row == null) { continue; }
if(o.strip) row = row.replace(endregex,"");
if(row || (o.blankrows !== false)) out.push((w++ ? RS : "") + row);
}
return out.join("");
@ -238,7 +234,6 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
else if(typeof v == 'string') t = 's';
else if(v instanceof Date) {
t = 'd';
if(!o.UTC) v = local_to_utc(v);
if(!o.cellDates) { t = 'n'; v = datenum(v); }
z = (cell != null && cell.z && fmt_is_date(cell.z)) ? cell.z : (o.dateNF || table_fmt[14]);
}
@ -296,11 +291,9 @@ function wb_sheet_idx(wb/*:Workbook*/, sh/*:number|string*/) {
} else throw new Error("Cannot find sheet |" + sh + "|");
}
/* simple blank or single-sheet workbook object */
function book_new(ws/*:?Worksheet*/, wsname/*:?string*/)/*:Workbook*/ {
var wb = { SheetNames: [], Sheets: {} };
if(ws) book_append_sheet(wb, ws, wsname || "Sheet1");
return wb;
/* simple blank workbook object */
function book_new()/*:Workbook*/ {
return { SheetNames: [], Sheets: {} };
}
/* add a worksheet to the end of a given workbook */
@ -308,10 +301,10 @@ function book_append_sheet(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/,
var i = 1;
if(!name) for(; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break;
if(!name || wb.SheetNames.length >= 0xFFFF) throw new Error("Too many worksheets");
if(roll && wb.SheetNames.indexOf(name) >= 0 && name.length < 32) {
var m = name.match(/\d+$/); // at this point, name length is capped at 32
i = m && +m[0] || 0;
var root = m && name.slice(0, m.index) || name;
if(roll && wb.SheetNames.indexOf(name) >= 0) {
var m = name.match(/(^.*?)(\d+)$/);
i = m && +m[2] || 0;
var root = m && m[1] || name;
for(++i; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf(name = root + i) == -1) break;
}
check_ws_name(name);

View File

@ -9,7 +9,6 @@ var utils/*:any*/ = {
decode_cell: decode_cell,
decode_range: decode_range,
format_cell: format_cell,
sheet_new: sheet_new,
sheet_add_aoa: sheet_add_aoa,
sheet_add_json: sheet_add_json,
sheet_add_dom: sheet_add_dom,

View File

@ -8,6 +8,7 @@ function write_csv_stream(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
var r = safe_decode_range(sheet["!ref"]);
var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
var row/*:?string*/ = "", cols/*:Array<string>*/ = [];
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
var rowinfo/*:Array<RowInfo>*/ = o.skipHidden && sheet["!rows"] || [];
@ -21,6 +22,7 @@ function write_csv_stream(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
if ((rowinfo[R-1]||{}).hidden) continue;
row = make_csv_row(sheet, r, R-1, cols, fs, rs, FS, o);
if(row != null) {
if(o.strip) row = row.replace(endregex,"");
if(row || (o.blankrows !== false)) return stream.push((w++ ? RS : "") + row);
}
}

32
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

File diff suppressed because one or more lines are too long

6464
dist/xlsx.extendscript.js generated vendored

File diff suppressed because it is too large Load Diff

35
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

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

View File

@ -45,35 +45,10 @@ function Base64_encode_pass(input) {
}
return o;
}
function Base64_encode_arr(input) {
var o = "";
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
for (var i = 0; i < input.length; ) {
c1 = input[i++];
e1 = c1 >> 2;
c2 = input[i++];
e2 = (c1 & 3) << 4 | c2 >> 4;
c3 = input[i++];
e3 = (c2 & 15) << 2 | c3 >> 6;
e4 = c3 & 63;
if (isNaN(c2)) {
e3 = e4 = 64;
} else if (isNaN(c3)) {
e4 = 64;
}
o += Base64_map.charAt(e1) + Base64_map.charAt(e2) + Base64_map.charAt(e3) + Base64_map.charAt(e4);
}
return o;
}
function Base64_decode(input) {
var o = "";
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
if (input.slice(0, 5) == "data:") {
var i = input.slice(0, 1024).indexOf(";base64,");
if (i > -1)
input = input.slice(i + 8);
}
input = input.replace(/[^\w\+\/\=]/g, "");
input = input.replace(/^data:([^\/]+\/[^\/]+)?;base64\,/, "").replace(/[^\w\+\/\=]/g, "");
for (var i = 0; i < input.length; ) {
e1 = Base64_map.indexOf(input.charAt(i++));
e2 = Base64_map.indexOf(input.charAt(i++));

View File

@ -37,33 +37,11 @@ function Base64_encode_pass(input: string): string {
}
return o;
}
function Base64_encode_arr(input: Uint8Array|number[]): string {
var o = "";
var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0;
for(var i = 0; i < input.length; ) {
c1 = input[i++];
e1 = (c1 >> 2);
c2 = input[i++];
e2 = ((c1 & 3) << 4) | (c2 >> 4);
c3 = input[i++];
e3 = ((c2 & 15) << 2) | (c3 >> 6);
e4 = (c3 & 63);
if (isNaN(c2)) { e3 = e4 = 64; }
else if (isNaN(c3)) { e4 = 64; }
o += Base64_map.charAt(e1) + Base64_map.charAt(e2) + Base64_map.charAt(e3) + Base64_map.charAt(e4);
}
return o;
}
function Base64_decode(input: string): string {
var o = "";
var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0;
if(input.slice(0,5) == "data:") {
var i = input.slice(0, 1024).indexOf(";base64,");
if(i > -1) input = input.slice(i+8);
}
input = input.replace(/[^\w\+\/\=]/g, "");
input = input.replace(/^data:([^\/]+\/[^\/]+)?;base64\,/,'')
.replace(/[^\w\+\/\=]/g, "")
for(var i = 0; i < input.length;) {
e1 = Base64_map.indexOf(input.charAt(i++));
e2 = Base64_map.indexOf(input.charAt(i++));

View File

@ -17,7 +17,7 @@ function rtf_to_sheet_str(str, opts) {
var dense = o.dense;
if (dense)
ws["!data"] = [];
var rows = str_match_ng(str, "\\trowd", "\\row");
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 } };

View File

@ -31,7 +31,7 @@ function rtf_to_sheet_str(str: string, opts: ParsingOptions): WorkSheet {
var dense = o.dense;
if(dense) ws["!data"] = [];
var rows = str_match_ng(str, "\\trowd", "\\row");
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[] = [];

View File

@ -13,7 +13,7 @@ function fill_vba_xls(cfb, vba) {
vba.FullPaths.forEach(function(p, i) {
if (i == 0)
return;
var newpath = p.replace(/^[\/]*[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
var newpath = p.replace(/[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
if (newpath.slice(-1) !== "/")
CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content);
});

View File

@ -16,7 +16,7 @@ function make_vba_xls(cfb: CFBModule.CFB$Container) {
function fill_vba_xls(cfb: CFBModule.CFB$Container, vba: CFBModule.CFB$Container): void {
vba.FullPaths.forEach(function(p, i) {
if(i == 0) return;
var newpath = p.replace(/^[\/]*[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
var newpath = p.replace(/[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
if(newpath.slice(-1) !== "/") CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content);
});
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "xlsx",
"version": "0.20.2",
"version": "0.19.3",
"author": "sheetjs",
"description": "SheetJS Spreadsheet data parser and writer",
"keywords": [
@ -39,36 +39,6 @@
"require": "./xlsx.js",
"types": "./types/index.d.ts"
},
"./dist/xlsx.core.min": {
"import": "./dist/xlsx.core.min.js",
"require": "./dist/xlsx.core.min.js",
"types": "./types/index.d.ts"
},
"./dist/xlsx.core.min.js": {
"import": "./dist/xlsx.core.min.js",
"require": "./dist/xlsx.core.min.js",
"types": "./types/index.d.ts"
},
"./dist/xlsx.full.min": {
"import": "./dist/xlsx.full.min.js",
"require": "./dist/xlsx.full.min.js",
"types": "./types/index.d.ts"
},
"./dist/xlsx.full.min.js": {
"import": "./dist/xlsx.full.min.js",
"require": "./dist/xlsx.full.min.js",
"types": "./types/index.d.ts"
},
"./dist/xlsx.mini.min": {
"import": "./dist/xlsx.mini.min.js",
"require": "./dist/xlsx.mini.min.js",
"types": "./types/index.d.ts"
},
"./dist/xlsx.mini.min.js": {
"import": "./dist/xlsx.mini.min.js",
"require": "./dist/xlsx.mini.min.js",
"types": "./types/index.d.ts"
},
"./dist/xlsx.zahl": {
"import": "./dist/xlsx.zahl.mjs",
"require": "./dist/xlsx.zahl.js",
@ -167,12 +137,6 @@
]
},
"homepage": "https://sheetjs.com/",
"files": [
"CHANGELOG.md", "LICENSE", "README.md", "bower.json", "package.json", "xlsx.js", "xlsx.mjs", "xlsxworker.js",
"bin/xlsx.njs",
"dist/LICENSE", "dist/*.mjs", "dist/*.js", "dist/*.map", "dist/*.d.ts",
"types/index.d.ts", "types/tsconfig.json"
],
"bugs": {
"url": "https://git.sheetjs.com/SheetJS/sheetjs/issues"
},

View File

@ -1,26 +0,0 @@
{
"env": { "shared-node-browser":true },
"globals": {},
"parserOptions": {
"ecmaVersion": 6
},
"plugins": [ "html", "json" ],
"extends": "eslint:recommended",
"rules": {
"comma-style": [ 2, "last" ],
"comma-dangle": [ 2, "never" ],
"curly": 0,
"no-bitwise": 0,
"no-cond-assign": 1,
"no-console": 0,
"no-control-regex": 0,
"no-unused-vars": 1,
"no-empty": 0,
"no-trailing-spaces": 2,
"no-use-before-define": [ 1, {
"functions":false, "classes":true, "variables":false
}],
"no-useless-escape": 0,
"semi": [ 2, "always" ]
}
}

View File

@ -1 +0,0 @@
misc/

View File

@ -1,35 +0,0 @@
.PHONY: build
build: node browser types
.PHONY: clean
clean:
rm dist/dta.*
## Types
.PHONY: types
types: dta.ts
tsc -d --emitDeclarationOnly --declarationDir types $<
mv types/dta.d.ts types/index.d.ts
## NodeJS target
.PHONY: node
node: dist/dta.js
dist/dta.js: dta.ts
npx esbuild@0.14.14 $< --bundle --outfile=$@ --platform=node
.PHONY: test-node
test-node: dist/dta.js test.js
npx mocha@2.5.3 test.js
## Browser target
.PHONY: browser
browser: dist/dta.min.js
dist/dta.min.js: dta.ts
npx esbuild@0.14.14 $< --bundle --outfile=$@ --minify --sourcemap --global-name=DTA
dist/dta.mjs: dta.ts
npx esbuild@0.14.14 $< --bundle --outfile=$@ --minify --sourcemap --format=esm

View File

@ -1,69 +0,0 @@
# DTA Data File Codec
Codec for reading Stata .DTA files and generating CSF workbook objects
compatible with the [SheetJS](https://sheetjs.com) library constellation.
DTA datasets can support millions of observations and over 32767 variables.
The codec will truncate data to 1048576 observations and 16384 variables.
<https://docs.sheetjs.com/docs/constellation/dta> includes a live demo.
## Installation
Using NodeJS package manager:
```bash
npm install --save https://cdn.sheetjs.com/dta-0.0.2/dta-0.0.2.tgz
```
The standalone script is also hosted on the SheetJS CDN:
```html
<script src="https://cdn.sheetjs.com/dta-0.0.2/package/dist/dta.min.js"></script>
```
## Usage
The `parse` method accepts a `Uint8Array` representing the file data. It returns
a ["Common Spreadsheet Format"](https://docs.sheetjs.com/docs/csf/) workbook
object.
The `set_utils` method accepts a `utils` object from SheetJS CE or a SheetJS
Pro build. `parse` will use methods from the `utils` object.
### NodeJS
```js
const XLSX = require("xlsx"), DTA = require("dta");
DTA.set_utils(XLSX.utils);
const wb = DTA.parse(fs.readFileSync("auto.dta"));
```
### Browser
`dist/dta.min.js` is a standalone build designed to be added with `<script>`.
```html
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
<script src="dist/dta.min.js"></script>
<div id="out"></div>
<script>
DTA.set_utils(XLSX.utils);
(async() => {
/* fetch file */
const data = await (await fetch("test.dta")).arrayBuffer();
/* parse */
const wb = DTA.parse(new Uint8Array(data));
/* wb is a SheetJS workbook object */
const html = XLSX.utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]);
out.innerHTML = html;
})();
</script>
```
`dist/dta.mjs` is a ECMAScript Module build designed to be used with bundlers:
```js
import * as DTA from 'dta';
```

View File

@ -1,19 +0,0 @@
#!/usr/bin/env node
/* eslint-env node, es6 */
const DTA = require("../");
const XLSX = (() => {
try {
const XLSX = require("xlsx");
DTA.set_utils(XLSX.utils);
return XLSX;
} catch(e) {
throw new Error("Must install the SheetJS file processing library! See https://docs.sheetjs.com/docs/getting-started/installation/nodejs for more details");
}
})();
const fs = require("fs");
const buf = fs.readFileSync(process.argv[2]);
const wb = DTA.parse(buf);
// translate stub cells to single blanks
//wb.Sheets[wb.SheetNames[0]]["!data"].forEach(row => row.forEach(cell => {if(cell.t == "z") {cell.t = "s"; cell.v = " ";}}));
console.log(XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]));

View File

@ -1,688 +0,0 @@
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __reExport = (target, module2, copyDefault, desc) => {
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
for (let key of __getOwnPropNames(module2))
if (!__hasOwnProp.call(target, key) && (copyDefault || key !== "default"))
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
}
return target;
};
var __toCommonJS = /* @__PURE__ */ ((cache) => {
return (module2, temp) => {
return cache && cache.get(module2) || (temp = __reExport(__markAsModule({}), module2, 1), cache && cache.set(module2, temp), temp);
};
})(typeof WeakMap !== "undefined" ? /* @__PURE__ */ new WeakMap() : 0);
// dta.ts
var dta_exports = {};
__export(dta_exports, {
parse: () => parse,
set_utils: () => set_utils,
version: () => version
});
var version = "0.0.2";
var _utils;
function set_utils(utils) {
_utils = utils;
}
function u8_to_str(u8) {
return new TextDecoder().decode(u8);
}
function u8_to_latin1(u8) {
return new TextDecoder("latin1").decode(u8);
}
function format_number_dta(value, format, t) {
if (value < 0) {
const res = format_number_dta(-value, format, t);
res.w = "-" + res.w;
return res;
}
const o = { t: "n", v: value };
switch (t) {
case 251:
case 98:
case 65530:
format = "%8.0g";
break;
case 252:
case 105:
case 65529:
format = "%8.0g";
break;
case 253:
case 108:
case 65528:
format = "%12.0g";
break;
case 254:
case 102:
case 65527:
format = "%9.0g";
break;
case 255:
case 100:
case 65526:
format = "%10.0g";
break;
default:
throw t;
}
try {
let w = +(format.match(/%(\d+)/) || [])[1] || 8;
let k = 0;
if (value < 1)
++k;
if (value < 0.1)
++k;
if (value < 0.01)
++k;
if (value < 1e-3)
++k;
const e = value.toExponential();
const exp = e.indexOf("e") == -1 ? 0 : +e.slice(e.indexOf("e") + 1);
let h = w - 2 - exp;
if (h < 0)
h = 0;
var m = format.match(/%\d+\.(\d+)/);
if (m && +m[1])
h = +m[1];
o.w = (Math.round(value * 10 ** h) / 10 ** h).toFixed(h).replace(/^([-]?)0\./, "$1.");
o.w = o.w.slice(0, w + k);
if (o.w.indexOf(".") > -1)
o.w = o.w.replace(/0+$/, "");
o.w = o.w.replace(/\.$/, "");
if (o.w == "")
o.w = "0";
} catch (e) {
}
return o;
}
function u8_to_dataview(array) {
return new DataView(array.buffer, array.byteOffset, array.byteLength);
}
function valid_inc(p, n) {
if (u8_to_str(p.raw.slice(p.ptr, p.ptr + n.length)) != n)
return false;
p.ptr += n.length;
return true;
}
function read_f64(p, LE) {
p.ptr += 8;
const d = p.dv.getFloat64(p.ptr - 8, LE);
return d > 8988e304 ? null : d;
}
function read_f32(p, LE) {
p.ptr += 4;
const d = p.dv.getFloat32(p.ptr - 4, LE);
return d > 1701e35 ? null : d;
}
function read_u32(p, LE) {
p.ptr += 4;
return p.dv.getUint32(p.ptr - 4, LE);
}
function read_i32(p, LE) {
p.ptr += 4;
const u = p.dv.getInt32(p.ptr - 4, LE);
return u > 2147483620 ? null : u;
}
function read_u16(p, LE) {
p.ptr += 2;
return p.dv.getUint16(p.ptr - 2, LE);
}
function read_i16(p, LE) {
p.ptr += 2;
const u = p.dv.getInt16(p.ptr - 2, LE);
return u > 32740 ? null : u;
}
function read_u8(p) {
return p.raw[p.ptr++];
}
function read_i8(p) {
let u = p.raw[p.ptr++];
u = u < 128 ? u : u - 256;
return u > 100 ? null : u;
}
var SUPPORTED_VERSIONS_TAGGED = [
"117",
"118",
"119",
"120",
"121"
];
var SUPPORTED_VERSIONS_LEGACY = [
102,
103,
104,
105,
108,
110,
111,
112,
113,
114,
115
];
function parse_tagged(raw) {
const err = "Not a DTA file";
const d = {
ptr: 0,
raw,
dv: u8_to_dataview(raw)
};
let vers = 118;
let LE = true;
let nvar = 0, nobs = 0, nobs_lo = 0, nobs_hi = 0;
let label = "", timestamp = "";
const var_types = [];
const var_names = [];
const formats = [];
if (!valid_inc(d, "<stata_dta>"))
throw err;
{
if (!valid_inc(d, "<header>"))
throw err;
{
if (!valid_inc(d, "<release>"))
throw err;
const res = u8_to_latin1(d.raw.slice(d.ptr, d.ptr + 3));
d.ptr += 3;
if (!valid_inc(d, "</release>"))
throw err;
if (SUPPORTED_VERSIONS_TAGGED.indexOf(res) == -1)
throw `Unsupported DTA ${res} file`;
vers = +res;
}
{
if (!valid_inc(d, "<byteorder>"))
throw err;
const res = u8_to_latin1(d.raw.slice(d.ptr, d.ptr + 3));
d.ptr += 3;
if (!valid_inc(d, "</byteorder>"))
throw err;
switch (res) {
case "MSF":
LE = false;
break;
case "LSF":
LE = true;
break;
default:
throw `Unsupported byteorder ${res}`;
}
}
{
if (!valid_inc(d, "<K>"))
throw err;
nvar = vers === 119 || vers >= 121 ? read_u32(d, LE) : read_u16(d, LE);
if (!valid_inc(d, "</K>"))
throw err;
}
{
if (!valid_inc(d, "<N>"))
throw err;
if (vers == 117)
nobs = nobs_lo = read_u32(d, LE);
else {
const lo = read_u32(d, LE), hi = read_u32(d, LE);
nobs = LE ? (nobs_lo = lo) + (nobs_hi = hi) * Math.pow(2, 32) : (nobs_lo = hi) + (nobs_hi = lo) * Math.pow(2, 32);
}
if (nobs > 1e6)
console.error(`More than 1 million observations -- extra rows will be dropped`);
if (!valid_inc(d, "</N>"))
throw err;
}
{
if (!valid_inc(d, "<label>"))
throw err;
const w = vers >= 118 ? 2 : 1;
const strlen = w == 1 ? read_u8(d) : read_u16(d, LE);
if (strlen > 0)
label = u8_to_str(d.raw.slice(d.ptr, d.ptr + w));
d.ptr += strlen;
if (!valid_inc(d, "</label>"))
throw err;
}
{
if (!valid_inc(d, "<timestamp>"))
throw err;
const strlen = read_u8(d);
timestamp = u8_to_latin1(d.raw.slice(d.ptr, d.ptr + strlen));
d.ptr += strlen;
if (!valid_inc(d, "</timestamp>"))
throw err;
}
if (!valid_inc(d, "</header>"))
throw err;
}
{
if (!valid_inc(d, "<map>"))
throw err;
d.ptr += 8 * 14;
if (!valid_inc(d, "</map>"))
throw err;
}
let stride = 0;
{
if (!valid_inc(d, "<variable_types>"))
throw err;
for (var i = 0; i < nvar; ++i) {
const type = read_u16(d, LE);
var_types.push(type);
if (type >= 1 && type <= 2045)
stride += type;
else
switch (type) {
case 32768:
stride += 8;
break;
case 65525:
stride += 0;
break;
case 65526:
stride += 8;
break;
case 65527:
stride += 4;
break;
case 65528:
stride += 4;
break;
case 65529:
stride += 2;
break;
case 65530:
stride += 1;
break;
default:
throw `Unsupported field type ${type}`;
}
}
if (!valid_inc(d, "</variable_types>"))
throw err;
}
{
if (!valid_inc(d, "<varnames>"))
throw err;
const w = vers >= 118 ? 129 : 33;
for (let i2 = 0; i2 < nvar; ++i2) {
const name = u8_to_str(d.raw.slice(d.ptr, d.ptr + w));
d.ptr += w;
var_names.push(name.replace(/\x00[\s\S]*/, ""));
}
if (!valid_inc(d, "</varnames>"))
throw err;
}
{
if (!valid_inc(d, "<sortlist>"))
throw err;
d.ptr += (2 * nvar + 2) * (vers == 119 || vers == 121 ? 2 : 1);
if (!valid_inc(d, "</sortlist>"))
throw err;
}
{
if (!valid_inc(d, "<formats>"))
throw err;
const w = vers >= 118 ? 57 : 49;
for (let i2 = 0; i2 < nvar; ++i2) {
const name = u8_to_str(d.raw.slice(d.ptr, d.ptr + w));
d.ptr += w;
formats.push(name.replace(/\x00[\s\S]*/, ""));
}
if (!valid_inc(d, "</formats>"))
throw err;
}
const value_label_names = [];
{
if (!valid_inc(d, "<value_label_names>"))
throw err;
const w = vers >= 118 ? 129 : 33;
for (let i2 = 0; i2 < nvar; ++i2, d.ptr += w)
value_label_names[i2] = u8_to_latin1(d.raw.slice(d.ptr, d.ptr + w)).replace(/\x00.*$/, "");
if (!valid_inc(d, "</value_label_names>"))
throw err;
}
{
if (!valid_inc(d, "<variable_labels>"))
throw err;
const w = vers >= 118 ? 321 : 81;
d.ptr += w * nvar;
if (!valid_inc(d, "</variable_labels>"))
throw err;
}
{
if (!valid_inc(d, "<characteristics>"))
throw err;
while (valid_inc(d, "<ch>")) {
const len = read_u32(d, LE);
d.ptr += len;
if (!valid_inc(d, "</ch>"))
throw err;
}
if (!valid_inc(d, "</characteristics>"))
throw err;
}
const ws = _utils.aoa_to_sheet([var_names], { dense: true });
var ptrs = [];
{
if (!valid_inc(d, "<data>"))
throw err;
for (let R = 0; R < nobs; ++R) {
const row = [];
for (let C = 0; C < nvar; ++C) {
let t = var_types[C];
if (t >= 1 && t <= 2045) {
let s = u8_to_str(d.raw.slice(d.ptr, d.ptr + t));
s = s.replace(/\x00[\s\S]*/, "");
row[C] = s;
d.ptr += t;
} else
switch (t) {
case 65525:
d.ptr += 0;
break;
case 65530:
row[C] = read_i8(d);
break;
case 65529:
row[C] = read_i16(d, LE);
break;
case 65528:
row[C] = read_i32(d, LE);
break;
case 65527:
row[C] = read_f32(d, LE);
break;
case 65526:
row[C] = read_f64(d, LE);
break;
case 32768:
{
row[C] = "##SheetJStrL##";
ptrs.push([R + 1, C, d.raw.slice(d.ptr, d.ptr + 8)]);
d.ptr += 8;
}
break;
default:
throw `Unsupported field type ${t} for ${var_names[C]}`;
}
if (typeof row[C] == "number" && formats[C])
row[C] = format_number_dta(row[C], formats[C], t);
}
_utils.sheet_add_aoa(ws, [row], { origin: -1, sheetStubs: true });
}
if (!valid_inc(d, "</data>"))
throw err;
}
{
if (!valid_inc(d, "<strls>"))
throw err;
const strl_tbl = [];
while (d.raw[d.ptr] == 71) {
if (!valid_inc(d, "GSO"))
throw err;
const v = read_u32(d, LE);
let o = 0;
if (vers == 117)
o = read_u32(d, LE);
else {
const lo = read_u32(d, LE), hi = read_u32(d, LE);
o = LE ? lo + hi * Math.pow(2, 32) : hi + lo * Math.pow(2, 32);
if (o > 1e6)
console.error(`More than 1 million observations -- data will be dropped`);
}
const t = read_u8(d);
const len = read_u32(d, LE);
if (!strl_tbl[o])
strl_tbl[o] = [];
let str = "";
if (t == 129) {
str = new TextDecoder(vers >= 118 ? "utf8" : "latin1").decode(d.raw.slice(d.ptr, d.ptr + len));
d.ptr += len;
} else {
str = new TextDecoder(vers >= 118 ? "utf8" : "latin1").decode(d.raw.slice(d.ptr, d.ptr + len)).replace(/\x00$/, "");
d.ptr += len;
}
strl_tbl[o][v] = str;
}
if (!valid_inc(d, "</strls>"))
throw err;
ptrs.forEach(([R, C, buf]) => {
const dv = u8_to_dataview(buf);
let v = 0, o = 0;
switch (vers) {
case 117:
{
v = dv.getUint32(0, LE);
o = dv.getUint32(4, LE);
}
break;
case 118:
case 120:
{
v = dv.getUint16(0, LE);
const o1 = dv.getUint16(2, LE), o2 = dv.getUint32(4, LE);
o = LE ? o1 + o2 * 65536 : o2 + o1 * 2 ** 32;
}
break;
case 119:
case 121: {
const v1 = dv.getUint16(0, LE), v2 = buf[2];
v = LE ? v1 + (v2 << 16) : v2 + (v1 << 8);
const o1 = buf[3], o2 = dv.getUint32(4, LE);
o = LE ? o1 + o2 * 256 : o2 + o1 * 2 ** 32;
}
}
ws["!data"][R][C].v = strl_tbl[o][v];
});
}
{
const w = vers >= 118 ? 129 : 33;
if (!valid_inc(d, "<value_labels>"))
throw err;
while (valid_inc(d, "<lbl>")) {
let len = read_u32(d, LE);
const labname = u8_to_latin1(d.raw.slice(d.ptr, d.ptr + w)).replace(/\x00.*$/, "");
d.ptr += w;
d.ptr += 3;
const labels = [];
{
const n = read_u32(d, LE);
const txtlen = read_u32(d, LE);
const off = [], val = [];
for (let i2 = 0; i2 < n; ++i2)
off.push(read_u32(d, LE));
for (let i2 = 0; i2 < n; ++i2)
val.push(read_u32(d, LE));
const str = u8_to_str(d.raw.slice(d.ptr, d.ptr + txtlen));
d.ptr += txtlen;
for (let i2 = 0; i2 < n; ++i2)
labels[val[i2]] = str.slice(off[i2], str.indexOf("\0", off[i2]));
}
const C = value_label_names.indexOf(labname);
if (C == -1)
throw new Error(`unexpected value label |${labname}|`);
for (let R = 1; R < ws["!data"].length; ++R) {
const cell = ws["!data"][R][C];
cell.t = "s";
cell.v = cell.w = labels[cell.v || 0];
}
if (!valid_inc(d, "</lbl>"))
throw err;
}
if (!valid_inc(d, "</value_labels>"))
throw err;
}
if (!valid_inc(d, "</stata_dta>"))
throw err;
const wb = _utils.book_new();
_utils.book_append_sheet(wb, ws, "Sheet1");
wb.bookType = "dta";
return wb;
}
function parse_legacy(raw) {
let vers = raw[0];
if (SUPPORTED_VERSIONS_LEGACY.indexOf(vers) == -1)
throw new Error("Not a DTA file");
const d = {
ptr: 1,
raw,
dv: u8_to_dataview(raw)
};
let LE = true;
let nvar = 0, nobs = 0;
let label = "", timestamp = "";
const var_types = [];
const var_names = [];
const formats = [];
{
const byteorder = read_u8(d);
switch (byteorder) {
case 1:
LE = false;
break;
case 2:
LE = true;
break;
default:
throw `DTA ${vers} Unexpected byteorder ${byteorder}`;
}
let byte = read_u8(d);
if (byte != 1)
throw `DTA ${vers} Unexpected filetype ${byte}`;
d.ptr++;
nvar = read_u16(d, LE);
nobs = read_u32(d, LE);
d.ptr += vers >= 108 ? 81 : vers >= 103 ? 32 : 30;
if (vers >= 105)
d.ptr += 18;
}
const value_label_names = [];
{
let C = 0;
for (C = 0; C < nvar; ++C)
var_types.push(read_u8(d));
const w = vers >= 110 ? 33 : 9;
for (C = 0; C < nvar; ++C) {
var_names.push(u8_to_str(d.raw.slice(d.ptr, d.ptr + w)).replace(/\x00[\s\S]*$/, ""));
d.ptr += w;
}
d.ptr += 2 * (nvar + 1);
const fw = vers >= 114 ? 49 : vers >= 105 ? 12 : 7;
for (C = 0; C < nvar; ++C) {
formats.push(u8_to_str(d.raw.slice(d.ptr, d.ptr + fw)).replace(/\x00[\s\S]*$/, ""));
d.ptr += fw;
}
const lw = vers >= 110 ? 33 : 9;
for (let i = 0; i < nvar; ++i, d.ptr += lw)
value_label_names[i] = u8_to_latin1(d.raw.slice(d.ptr, d.ptr + lw)).replace(/\x00.*$/, "");
}
d.ptr += (vers >= 106 ? 81 : 32) * nvar;
if (vers >= 105)
while (d.ptr < d.raw.length) {
const dt = read_u8(d), len = (vers >= 110 ? read_u32 : read_u16)(d, LE);
if (dt == 0 && len == 0)
break;
d.ptr += len;
}
const ws = _utils.aoa_to_sheet([var_names], { dense: true });
for (let R = 0; R < nobs; ++R) {
const row = [];
for (let C = 0; C < nvar; ++C) {
let t = var_types[C];
if ((vers == 111 || vers >= 113) && t >= 1 && t <= 244) {
let s = u8_to_str(d.raw.slice(d.ptr, d.ptr + t));
s = s.replace(/\x00[\s\S]*/, "");
row[C] = s;
d.ptr += t;
} else if ((vers == 112 || vers <= 110) && t >= 128) {
let s = u8_to_str(d.raw.slice(d.ptr, d.ptr + t - 127));
s = s.replace(/\x00[\s\S]*/, "");
row[C] = s;
d.ptr += t - 127;
} else
switch (t) {
case 251:
case 98:
row[C] = read_i8(d);
break;
case 252:
case 105:
row[C] = read_i16(d, LE);
break;
case 253:
case 108:
row[C] = read_i32(d, LE);
break;
case 254:
case 102:
row[C] = read_f32(d, LE);
break;
case 255:
case 100:
row[C] = read_f64(d, LE);
break;
default:
throw `Unsupported field type ${t} for ${var_names[C]}`;
}
if (typeof row[C] == "number" && formats[C])
row[C] = format_number_dta(row[C], formats[C], t);
}
_utils.sheet_add_aoa(ws, [row], { origin: -1, sheetStubs: true });
}
if (vers >= 115)
while (d.ptr < d.raw.length) {
const w = 33;
let len = read_u32(d, LE);
const labname = u8_to_latin1(d.raw.slice(d.ptr, d.ptr + w)).replace(/\x00.*$/, "");
d.ptr += w;
d.ptr += 3;
const labels = [];
{
const n = read_u32(d, LE);
const txtlen = read_u32(d, LE);
const off = [], val = [];
for (let i = 0; i < n; ++i)
off.push(read_u32(d, LE));
for (let i = 0; i < n; ++i)
val.push(read_u32(d, LE));
const str = u8_to_latin1(d.raw.slice(d.ptr, d.ptr + txtlen));
d.ptr += txtlen;
for (let i = 0; i < n; ++i)
labels[val[i]] = str.slice(off[i], str.indexOf("\0", off[i]));
}
const C = value_label_names.indexOf(labname);
if (C == -1)
throw new Error(`unexpected value label |${labname}|`);
for (let R = 1; R < ws["!data"].length; ++R) {
const cell = ws["!data"][R][C];
cell.t = "s";
cell.v = cell.w = labels[cell.v || 0];
}
}
const wb = _utils.book_new();
_utils.book_append_sheet(wb, ws, "Sheet1");
wb.bookType = "dta";
return wb;
}
function parse(data) {
if (data[0] >= 102 && data[0] <= 115)
return parse_legacy(data);
if (data[0] === 60)
return parse_tagged(data);
throw new Error("Not a DTA file");
}
module.exports = __toCommonJS(dta_exports);
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
parse,
set_utils,
version
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
packages/dta/dist/dta.mjs generated vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,629 +0,0 @@
import { CellObject, DenseWorkSheet, WorkBook, type utils } from 'xlsx';
export { parse, set_utils, version };
const version = "0.0.2";
let _utils: typeof utils;
/** Set internal instance of `utils`
*
* Usage:
*
* ```js
* const XLSX = require("xlsx");
* const DTA = require("dta");
* DTA.set_utils(XLSX.utils);
* ```
*
* @param utils utils object
*/
function set_utils(utils: any): void {
_utils = utils;
}
function u8_to_str(u8: Uint8Array): string {
return new TextDecoder().decode(u8);
}
/* sadly the web zealots decided to abandon binary strings */
function u8_to_latin1(u8: Uint8Array): string {
return new TextDecoder("latin1").decode(u8);
}
/* TODO: generalize and map to SSF */
function format_number_dta(value: number, format: string, t: number): CellObject {
if(value < 0) { const res = format_number_dta(-value, format, t); res.w = "-" + res.w; return res; }
const o: CellObject = { t: "n", v: value };
/* NOTE: The Stata CSV exporter appears to ignore the column formats, instead using these defaults */
switch(t) {
case 251: case 0x62: case 65530: format = "%8.0g"; break; // byte
case 252: case 0x69: case 65529: format = "%8.0g"; break; // int
case 253: case 0x6c: case 65528: format = "%12.0g"; break; // long
case 254: case 0x66: case 65527: format = "%9.0g"; break; // float
case 255: case 0x64: case 65526: format = "%10.0g"; break; // double
default: throw t;
}
try {
let w = +((format.match(/%(\d+)/)||[])[1]) || 8;
let k = 0;
if(value < 1) ++k;
if(value < 0.1) ++k;
if(value < 0.01) ++k;
if(value < 0.001) ++k;
const e = value.toExponential();
const exp = e.indexOf("e") == -1 ? 0 : +e.slice(e.indexOf("e")+1);
let h = w - 2 - exp;
if(h < 0) h = 0;
var m = format.match(/%\d+\.(\d+)/);
if(m && +m[1]) h = +m[1];
o.w = (Math.round(value * 10**(h))/10**(h)).toFixed(h).replace(/^([-]?)0\./,"$1.");
o.w = o.w.slice(0, w + k);
if(o.w.indexOf(".") > -1) o.w = o.w.replace(/0+$/,"");
o.w = o.w.replace(/\.$/,"");
if(o.w == "") o.w = "0";
} catch(e) {}
return o;
}
interface Payload {
/** Offset */
ptr: number;
/** Raw data */
raw: Uint8Array;
/** DataView */
dv: DataView;
}
function u8_to_dataview(array: Uint8Array): DataView { return new DataView(array.buffer, array.byteOffset, array.byteLength); }
function valid_inc(p: Payload, n: string): boolean {
if(u8_to_str(p.raw.slice(p.ptr, p.ptr + n.length)) != n) return false;
p.ptr += n.length;
return true;
}
function read_f64(p: Payload, LE: boolean): number | null {
p.ptr += 8;
const d = p.dv.getFloat64(p.ptr - 8, LE);
return d > 8.988e+307 ? null : d;
}
function read_f32(p: Payload, LE: boolean): number | null {
p.ptr += 4;
const d = p.dv.getFloat32(p.ptr - 4, LE);
return d > 1.701e+38 ? null : d;
}
function read_u32(p: Payload, LE: boolean) {
p.ptr += 4;
return p.dv.getUint32(p.ptr - 4, LE);
}
function read_i32(p: Payload, LE: boolean): number | null {
p.ptr += 4;
const u = p.dv.getInt32(p.ptr - 4, LE);
return u > 0x7fffffe4 ? null : u;
}
function read_u16(p: Payload, LE: boolean) {
p.ptr += 2;
return p.dv.getUint16(p.ptr - 2, LE);
}
function read_i16(p: Payload, LE: boolean): number | null {
p.ptr += 2;
const u = p.dv.getInt16(p.ptr - 2, LE);
return u > 32740 ? null : u;
}
function read_u8(p: Payload) {
return p.raw[p.ptr++];
}
function read_i8(p: Payload): number | null {
let u = p.raw[p.ptr++];
u = u < 128 ? u : u - 256;
return u > 100 ? null : u;
}
/* the annotations are from `dtaversion` */
const SUPPORTED_VERSIONS_TAGGED = [
"117", // stata 13
"118", // stata 14-18
"119", // stata 15-18 (> 32767 variables)
"120", // stata 18 (<= 32767, with aliases)
"121", // stata 18 (> 32767, with aliases)
];
const SUPPORTED_VERSIONS_LEGACY = [
102, // stata 1
103, // stata 2/3
104, // stata 4
105, // stata 5
108, // stata 6
110, // stata 7
111, // stata 7
112, // stata 8/9
113, // stata 8/9
114, // stata 10/11
115, // stata 12
];
function parse_tagged(raw: Uint8Array): WorkBook {
const err = ("Not a DTA file");
const d: Payload = {
ptr: 0,
raw,
dv: u8_to_dataview(raw)
};
let vers: number = 118;
let LE: boolean = true;
let nvar: number = 0, nobs: number = 0, nobs_lo = 0, nobs_hi = 0;
let label: string = "", timestamp: string = "";
const var_types: number[] = [];
const var_names: string[] = [];
const formats: string[] = [];
/* 5. Dataset format definition */
if(!valid_inc(d, "<stata_dta>")) throw err;
/* 5.1 Header <header> */
{
if(!valid_inc(d, "<header>")) throw err;
/* <release> */
{
if(!valid_inc(d, "<release>")) throw err;
/* NOTE: this assumes the version is 3 characters wide */
const res = u8_to_latin1(d.raw.slice(d.ptr, d.ptr+3));
d.ptr += 3;
if(!valid_inc(d, "</release>")) throw err;
if(SUPPORTED_VERSIONS_TAGGED.indexOf(res) == -1) throw (`Unsupported DTA ${res} file`);
vers = +res;
}
/* <byteorder> */
{
if(!valid_inc(d, "<byteorder>")) throw err;
/* NOTE: this assumes the byte order is 3 characters wide */
const res = u8_to_latin1(d.raw.slice(d.ptr, d.ptr+3));
d.ptr += 3;
if(!valid_inc(d, "</byteorder>")) throw err;
switch(res) {
case "MSF": LE = false; break;
case "LSF": LE = true; break;
default: throw (`Unsupported byteorder ${res}`);
}
}
/* <K> */
{
if(!valid_inc(d, "<K>")) throw err;
nvar = (vers === 119 || vers >= 121) ? read_u32(d, LE) : read_u16(d, LE);
if(!valid_inc(d, "</K>")) throw err;
}
/* <N> */
{
if(!valid_inc(d, "<N>")) throw err;
if(vers == 117) nobs = nobs_lo = read_u32(d, LE);
else {
const lo = read_u32(d, LE), hi = read_u32(d, LE);
nobs = LE ? ((nobs_lo = lo) + (nobs_hi = hi) * Math.pow(2,32)) : ((nobs_lo = hi) + (nobs_hi = lo) * Math.pow(2,32));
}
if(nobs > 1e6) console.error(`More than 1 million observations -- extra rows will be dropped`);
if(!valid_inc(d, "</N>")) throw err;
}
/* <label> */
{
if(!valid_inc(d, "<label>")) throw err;
const w = vers >= 118 ? 2 : 1;
const strlen = w == 1 ? read_u8(d) : read_u16(d, LE);
if(strlen > 0) label = u8_to_str(d.raw.slice(d.ptr, d.ptr + w));
d.ptr += strlen;
if(!valid_inc(d, "</label>")) throw err;
}
/* <timestamp> */
{
if(!valid_inc(d, "<timestamp>")) throw err;
const strlen = read_u8(d);
timestamp = u8_to_latin1(d.raw.slice(d.ptr, d.ptr + strlen));
d.ptr += strlen;
if(!valid_inc(d, "</timestamp>")) throw err;
}
if(!valid_inc(d, "</header>")) throw err;
}
/* 5.2 Map <map> */
{
/* TODO: validate map? */
if(!valid_inc(d, "<map>")) throw err;
/* 14 8-byte offsets for:
<stata_data>
<map>
<variable_types>
<varnames>
<sortlist>
<formats>
<value_label_names>
<variable_labels>
<characteristics>
<data>
<strls>
<value_labels>
</stata_data>
EOF
*/
d.ptr += 8 * 14;
if(!valid_inc(d, "</map>")) throw err;
}
let stride = 0;
/* 5.3 Variable types <variable_types> */
{
if(!valid_inc(d, "<variable_types>")) throw err;
for(var i = 0; i < nvar; ++i) {
const type = read_u16(d, LE);
var_types.push(type);
if(type >= 1 && type <= 2045) stride += type;
else switch(type) {
case 32768: stride += 8; break;
case 65525: stride += 0; break; // alias
case 65526: stride += 8; break;
case 65527: stride += 4; break;
case 65528: stride += 4; break;
case 65529: stride += 2; break;
case 65530: stride += 1; break;
default: throw (`Unsupported field type ${type}`);
}
}
if(!valid_inc(d, "</variable_types>")) throw err;
}
/* 5.4 Variable names <varnames> */
{
if(!valid_inc(d, "<varnames>")) throw err;
const w = vers >= 118 ? 129 : 33;
for(let i = 0; i < nvar; ++i) {
const name = u8_to_str(d.raw.slice(d.ptr, d.ptr + w));
d.ptr += w;
var_names.push(name.replace(/\x00[\s\S]*/,""));
}
if(!valid_inc(d, "</varnames>")) throw err;
}
/* 5.5 Sort order of observations <sortlist> */
{
/* TODO: check sort list? */
if(!valid_inc(d, "<sortlist>")) throw err;
d.ptr += (2 * nvar + 2) * ((vers == 119 || vers == 121) ? 2 : 1);
if(!valid_inc(d, "</sortlist>")) throw err;
}
/* 5.6 Display formats <formats> */
{
if(!valid_inc(d, "<formats>")) throw err;
const w = vers >= 118 ? 57 : 49;
for(let i = 0; i < nvar; ++i) {
const name = u8_to_str(d.raw.slice(d.ptr, d.ptr + w));
d.ptr += w;
formats.push(name.replace(/\x00[\s\S]*/,""));
}
if(!valid_inc(d, "</formats>")) throw err;
}
const value_label_names: string[] = [];
/* TODO: <value_label_names> */
{
if(!valid_inc(d, "<value_label_names>")) throw err;
const w = vers >= 118 ? 129 : 33;
for(let i = 0; i < nvar; ++i, d.ptr += w) value_label_names[i] = u8_to_latin1(d.raw.slice(d.ptr, d.ptr + w)).replace(/\x00.*$/,"");
if(!valid_inc(d, "</value_label_names>")) throw err;
}
/* TODO: <variable_labels> */
{
if(!valid_inc(d, "<variable_labels>")) throw err;
const w = vers >= 118 ? 321 : 81;
d.ptr += w * nvar;
if(!valid_inc(d, "</variable_labels>")) throw err;
}
/* 5.9 Characteristics <characteristics> */
{
if(!valid_inc(d, "<characteristics>")) throw err;
while(valid_inc(d, "<ch>")) {
const len = read_u32(d, LE);
d.ptr += len;
if(!valid_inc(d, "</ch>")) throw err;
}
if(!valid_inc(d, "</characteristics>")) throw err;
}
const ws: DenseWorkSheet = (_utils.aoa_to_sheet([var_names], {dense: true} as any) as DenseWorkSheet);
var ptrs: Array<[number, number, Uint8Array]> = []
/* 5.10 Data <data> */
{
if(!valid_inc(d, "<data>")) throw err;
for(let R = 0; R < nobs; ++R) {
const row: any[] = [];
for(let C = 0; C < nvar; ++C) {
let t = var_types[C];
// TODO: formats, dta_12{0,1} aliases?
if(t >= 1 && t <= 2045) {
/* NOTE: dta_117 restricts strf to ASCII */
let s = u8_to_str(d.raw.slice(d.ptr, d.ptr + t));
s = s.replace(/\x00[\s\S]*/,"");
row[C] = s;
d.ptr += t;
} else switch(t) {
case 65525: d.ptr += 0; break; // alias
case 65530: row[C] = read_i8(d); break; // byte
case 65529: row[C] = read_i16(d, LE); break; // int
case 65528: row[C] = read_i32(d, LE); break; // long
case 65527: row[C] = read_f32(d, LE); break; // float
case 65526: row[C] = read_f64(d, LE); break; // double
case 32768: {
row[C] = "##SheetJStrL##";
ptrs.push([R+1,C, d.raw.slice(d.ptr, d.ptr + 8)]);
d.ptr += 8;
} break;
default: throw (`Unsupported field type ${t} for ${var_names[C]}`);
}
if(typeof row[C] == "number" && formats[C]) row[C] = format_number_dta(row[C], formats[C], t);
}
_utils.sheet_add_aoa(ws, [row], {origin: -1, sheetStubs: true});
}
if(!valid_inc(d, "</data>")) throw err;
}
/* 5.11 StrLs <strls> */
{
if(!valid_inc(d, "<strls>")) throw err;
const strl_tbl: string[][] = [];
while(d.raw[d.ptr] == 71 /* G */) {
if(!valid_inc(d, "GSO")) throw err;
const v = read_u32(d, LE);
let o = 0;
if(vers == 117) o = read_u32(d, LE);
else {
const lo = read_u32(d, LE), hi = read_u32(d, LE);
o = LE ? (lo + hi * Math.pow(2,32)) : (hi + lo * Math.pow(2,32));
if(o > 1e6) console.error(`More than 1 million observations -- data will be dropped`);
}
const t = read_u8(d);
const len = read_u32(d, LE);
if(!strl_tbl[o]) strl_tbl[o] = [];
let str = "";
if(t == 129) {
// TODO: dta_117 codepage
str = new TextDecoder(vers >= 118 ? "utf8" : "latin1").decode(d.raw.slice(d.ptr, d.ptr + len));
d.ptr += len;
} else {
str = new TextDecoder(vers >= 118 ? "utf8" : "latin1").decode(d.raw.slice(d.ptr, d.ptr + len)).replace(/\x00$/,"");
d.ptr += len;
}
strl_tbl[o][v] = str;
}
if(!valid_inc(d, "</strls>")) throw err;
ptrs.forEach(([R,C,buf]) => {
const dv = u8_to_dataview(buf);
let v = 0, o = 0;
switch(vers) {
case 117: { // v(4) o(4)
v = dv.getUint32(0, LE);
o = dv.getUint32(4, LE);
} break;
case 118: case 120: { // v(2) o(6)
v = dv.getUint16(0, LE);
const o1 = dv.getUint16(2, LE), o2 = dv.getUint32(4, LE);
o = LE ? o1 + o2 * 65536 : o2 + o1 * (2**32);
} break;
case 119: case 121: { // v(3) o(5)
const v1 = dv.getUint16(0, LE), v2 = buf[2];
v = LE ? v1 + (v2 << 16) : v2 + (v1 << 8);
const o1 = buf[3], o2 = dv.getUint32(4, LE);
o = LE ? o1 + o2 * 256 : o2 + o1 * (2**32);
}
}
ws["!data"][R][C].v = strl_tbl[o][v];
});
}
/* 5.12 Value labels <value_labels> */
{
const w = vers >= 118 ? 129 : 33;
if(!valid_inc(d, "<value_labels>")) throw err;
while(valid_inc(d, "<lbl>")) {
let len = read_u32(d, LE);
const labname = u8_to_latin1(d.raw.slice(d.ptr, d.ptr + w)).replace(/\x00.*$/,"");
d.ptr += w;
d.ptr += 3; // padding
const labels: string[] = [];
{
const n = read_u32(d, LE);
const txtlen = read_u32(d, LE);
const off: number[] = [], val: number[] = [];
for(let i = 0; i < n; ++i) off.push(read_u32(d, LE));
for(let i = 0; i < n; ++i) val.push(read_u32(d, LE));
const str = u8_to_str(d.raw.slice(d.ptr, d.ptr + txtlen));
d.ptr += txtlen;
for(let i = 0; i < n; ++i) labels[val[i]] = str.slice(off[i], str.indexOf("\x00", off[i]));
}
const C = value_label_names.indexOf(labname);
if(C == -1) throw new Error(`unexpected value label |${labname}|`);
for(let R = 1; R < ws["!data"].length; ++R) {
const cell = ws["!data"][R][C];
cell.t = "s"; cell.v = cell.w = labels[(cell.v as number)||0];
}
//d.ptr += len; // value_label_table
if(!valid_inc(d, "</lbl>")) throw err;
}
if(!valid_inc(d, "</value_labels>")) throw err;
}
if(!valid_inc(d, "</stata_dta>")) throw err;
const wb = _utils.book_new();
_utils.book_append_sheet(wb, ws, "Sheet1");
wb.bookType = "dta" as any;
return wb;
}
function parse_legacy(raw: Uint8Array): WorkBook {
let vers: number = raw[0];
if(SUPPORTED_VERSIONS_LEGACY.indexOf(vers) == -1) throw new Error("Not a DTA file");
const d: Payload = {
ptr: 1,
raw,
dv: u8_to_dataview(raw)
};
let LE: boolean = true;
let nvar: number = 0, nobs: number = 0;
let label: string = "", timestamp: string = "";
const var_types: number[] = [];
const var_names: string[] = [];
const formats: string[] = [];
/* 5.1 Header */
{
const byteorder = read_u8(d);
switch(byteorder) {
case 1: LE = false; break;
case 2: LE = true; break;
default: throw (`DTA ${vers} Unexpected byteorder ${byteorder}`);
}
let byte = read_u8(d);
if(byte != 1) throw (`DTA ${vers} Unexpected filetype ${byte}`);
// NOTE: dta_105 technically supports filetype 2
d.ptr++; // "unused"
nvar = read_u16(d, LE);
nobs = read_u32(d, LE);
d.ptr += (vers >= 108 ? 81 : vers >= 103 ? 32 : 30); // TODO: data_label
if(vers >= 105) d.ptr += 18; // TODO: time_stamp
}
/* 5.2 Descriptors */
const value_label_names: string[] = [];
{
let C = 0;
// typlist
for(C = 0; C < nvar; ++C) var_types.push(read_u8(d));
// varlist
const w = vers >= 110 ? 33 : 9;
for(C = 0; C < nvar; ++C) {
var_names.push(u8_to_str(d.raw.slice(d.ptr, d.ptr + w)).replace(/\x00[\s\S]*$/,""));
d.ptr += w;
}
// srtlist
d.ptr += 2*(nvar + 1);
// fmtlist
const fw = (vers >= 114 ? 49 : vers >= 105 ? 12 : 7);
for(C = 0; C < nvar; ++C) {
formats.push(u8_to_str(d.raw.slice(d.ptr, d.ptr + fw)).replace(/\x00[\s\S]*$/,""));
d.ptr += fw;
}
// lbllist
const lw = vers >= 110 ? 33 : 9;
for(let i = 0; i < nvar; ++i, d.ptr += lw) value_label_names[i] = u8_to_latin1(d.raw.slice(d.ptr, d.ptr + lw)).replace(/\x00.*$/,"");
}
/* 5.3 Variable labels */
// TODO: should these names be used in the worksheet?
d.ptr += (vers >= 106 ? 81 : 32) * nvar;
/* 5.4 Expansion fields */
if(vers >= 105) while(d.ptr < d.raw.length) {
const dt = read_u8(d), len = (vers >= 110 ? read_u32 : read_u16)(d, LE);
if(dt == 0 && len == 0) break;
d.ptr += len;
}
const ws: DenseWorkSheet = (_utils.aoa_to_sheet([var_names], {dense: true} as any) as DenseWorkSheet);
/* 5.5 Data */
for(let R = 0; R < nobs; ++R) {
const row: any[] = [];
for(let C = 0; C < nvar; ++C) {
let t = var_types[C];
// TODO: data type processing
if((vers == 111 || vers >= 113) && t >= 1 && t <= 244) {
/* NOTE: dta_117 restricts strf to ASCII */
let s = u8_to_str(d.raw.slice(d.ptr, d.ptr + t));
s = s.replace(/\x00[\s\S]*/,"");
row[C] = s;
d.ptr += t;
} else if((vers == 112 || vers <= 110) && t >= 0x80) {
/* NOTE: dta_105 restricts strf to ASCII */
let s = u8_to_str(d.raw.slice(d.ptr, d.ptr + t - 0x7F));
s = s.replace(/\x00[\s\S]*/,"");
row[C] = s;
d.ptr += t - 0x7F;
} else switch(t) {
case 251: case 0x62: row[C] = read_i8(d); break; // byte
case 252: case 0x69: row[C] = read_i16(d, LE); break; // int
case 253: case 0x6c: row[C] = read_i32(d, LE); break; // long
case 254: case 0x66: row[C] = read_f32(d, LE); break; // float
case 255: case 0x64: row[C] = read_f64(d, LE); break; // double
default: throw (`Unsupported field type ${t} for ${var_names[C]}`);
}
if(typeof row[C] == "number" && formats[C]) row[C] = format_number_dta(row[C], formats[C], t);
}
_utils.sheet_add_aoa(ws, [row], {origin: -1, sheetStubs: true});
}
/* 5.6 Value labels */
// TODO: < 115
if(vers >= 115) while(d.ptr < d.raw.length) {
const w = 33;
let len = read_u32(d, LE);
const labname = u8_to_latin1(d.raw.slice(d.ptr, d.ptr + w)).replace(/\x00.*$/,"");
d.ptr += w;
d.ptr += 3; // padding
const labels: string[] = [];
{
const n = read_u32(d, LE);
const txtlen = read_u32(d, LE);
const off: number[] = [], val: number[] = [];
for(let i = 0; i < n; ++i) off.push(read_u32(d, LE));
for(let i = 0; i < n; ++i) val.push(read_u32(d, LE));
const str = u8_to_latin1(d.raw.slice(d.ptr, d.ptr + txtlen));
d.ptr += txtlen;
for(let i = 0; i < n; ++i) labels[val[i]] = str.slice(off[i], str.indexOf("\x00", off[i]));
}
const C = value_label_names.indexOf(labname);
if(C == -1) throw new Error(`unexpected value label |${labname}|`);
for(let R = 1; R < ws["!data"].length; ++R) {
const cell = ws["!data"][R][C];
cell.t = "s"; cell.v = cell.w = labels[(cell.v as number)||0];
}
}
const wb: WorkBook = _utils.book_new();
_utils.book_append_sheet(wb, ws, "Sheet1");
wb.bookType = "dta" as any;
return wb;
}
/** Parse DTA file
*
* NOTE: In NodeJS, `Buffer` extends `Uint8Array`
*
* @param {Uint8Array} data File data
*/
function parse(data: Uint8Array): WorkBook {
if(data[0] >= 102 && data[0] <= 115) return parse_legacy(data);
if(data[0] === 60) return parse_tagged(data);
throw new Error("Not a DTA file");
}

View File

@ -1,39 +0,0 @@
{
"name": "dta",
"version": "0.0.2",
"author": "sheetjs",
"description": "Stata .dta codecs for SheetJS Common Spreadsheet Format",
"bin": {
"dta2csv": "./bin/dta2csv.njs"
},
"main": "dist/dta.js",
"module": "dist/dta.mjs",
"types": "types",
"files": [
"bin/",
"dist/",
"types/"
],
"repository": {
"type": "git",
"url": "https://git.sheetjs.com/SheetJS/sheetjs",
"directory": "packages/dta"
},
"scripts": {
"test": "make test",
"build": "make",
"lint": "make fullint",
"dtslint": "dtslint types"
},
"homepage": "https://sheetjs.com/",
"bugs": {
"url": "https://git.sheetjs.com/SheetJS/sheetjs/issues"
},
"license": "Apache-2.0",
"engines": {
"node": ">=12.0"
},
"devDependencies": {
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.1/xlsx-0.20.1.tgz"
}
}

View File

@ -1,32 +0,0 @@
/* eslint-env mocha, node, es6 */
const fs = require("fs"), assert = require("assert");
const DTA = require("./");
const XLSX = require("xlsx");
DTA.set_utils(XLSX.utils);
const test_folders = [
"test_files"
];
for(let tF of test_folders) describe(tF, () => {
const test_files = fs.readdirSync(tF);
for(let tf of test_files) {
if(tf.endsWith("csv")) it(`${tf.replace(".csv", "")} [CSV]`, () => {
const buf = fs.readFileSync(`${tF}/${tf.replace(".csv", "")}`);
const wb = DTA.parse(buf);
assert(wb.SheetNames.length > 0);
/* stata will represent unspecified values as single spaces */
//wb.Sheets[wb.SheetNames[0]]["!data"].forEach(row => row.forEach(cell => {if(cell.t == "z") {cell.t = "s"; cell.v = " ";}}));
const csvstr = XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]);
const baseline = fs.readFileSync(`${tF}/${tf}`, "utf8").replace(/[\r\n]+/g,"\n");
assert.equal(csvstr.trim(), baseline.trim());
});
if(!tf.endsWith("dta")) continue;
it(tf, () => {
const buf = fs.readFileSync(`${tF}/${tf}`);
const wb = DTA.parse(buf);
assert(wb.SheetNames.length > 0);
});
}
});

View File

@ -1,23 +0,0 @@
import { WorkBook } from 'xlsx';
export { parse, set_utils, version };
declare const version = "0.0.2";
/** Set internal instance of `utils`
*
* Usage:
*
* ```js
* const XLSX = require("xlsx");
* const DTA = require("dta");
* DTA.set_utils(XLSX.utils);
* ```
*
* @param utils utils object
*/
declare function set_utils(utils: any): void;
/** Parse DTA file
*
* NOTE: In NodeJS, `Buffer` extends `Uint8Array`
*
* @param {Uint8Array} data File data
*/
declare function parse(data: Uint8Array): WorkBook;

View File

@ -59,7 +59,7 @@ ctest: ## Build browser test fixtures
.PHONY: ctestserv
ctestserv: ## Start a test server on port 8000
@cd ctest && python -mSimpleHTTPServer || python3 -mhttp.server || npx -y http-server -p 8000 .
@cd ctest && python -mSimpleHTTPServer
## Code Checking

View File

@ -8,14 +8,16 @@ features like international support as well as dedicated support.
## Installation
With [npm](https://www.npmjs.org/package/ssf):
```bash
$ npm install https://cdn.sheetjs.com/ssf-0.11.3/ssf-0.11.3.tgz
$ npm install ssf
```
In the browser:
```html
<script src="https://cdn.sheetjs.com/ssf-0.11.3/ssf.js"></script>
<script src="ssf.js"></script>
```
The browser exposes a variable `SSF`
@ -105,3 +107,13 @@ granted by the Apache 2.0 license are reserved by the Original Author.
## Badges
[![Sauce Test Status](https://saucelabs.com/browser-matrix/ssfjs.svg)](https://saucelabs.com/u/ssfjs)
[![Build Status](https://travis-ci.org/SheetJS/ssf.svg?branch=master)](https://travis-ci.org/SheetJS/ssf)
[![Coverage Status](http://img.shields.io/coveralls/SheetJS/ssf/master.svg)](https://coveralls.io/r/SheetJS/ssf?branch=master)
[![NPM Downloads](https://img.shields.io/npm/dt/ssf.svg)](https://npmjs.org/package/ssf)
[![Dependencies Status](https://david-dm.org/sheetjs/ssf/status.svg)](https://david-dm.org/sheetjs/ssf)
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/ssf?pixel)](https://github.com/SheetJS/ssf)

View File

@ -1 +1 @@
SSF.version = '0.11.3';
SSF.version = '0.11.2';

View File

@ -5,6 +5,6 @@ function pad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v;return t.length>=d?t
function rpad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);}
function pad0r1(v/*:any*/,d/*:number*/)/*:string*/{var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;}
function pad0r2(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
var p2_32 = /*#__PURE__*/Math.pow(2,32);
var p2_32 = Math.pow(2,32);
function pad0r(v/*:any*/,d/*:number*/)/*:string*/{if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); }
function isgeneral(s/*:string*/, i/*:?number*/)/*:boolean*/ { i = i || 0; return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; }

View File

@ -1,5 +1,4 @@
function init_table(t/*:any*/) {
if(!t) t = {};
t[0]= 'General';
t[1]= '0';
t[2]= '0.00';
@ -29,7 +28,6 @@ function init_table(t/*:any*/) {
t[48]= '##0.0E+0';
t[49]= '@';
t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "';
return t;
}
var table_fmt = {};

View File

@ -1,20 +0,0 @@
function normalize_xl_unsafe(v/*:number*/)/*:number*/ {
if(v == 0) return 0;
var s = v.toPrecision(17);
if(s.indexOf("e") > -1) {
var m = s.slice(0, s.indexOf("e"));
if(m.indexOf(".") > -1) {
var tail = m.charAt(0) + m.slice(2, 17);
m = m.slice(0, 16);
if(tail.length == 16) {
m = String(Math.round(Number(tail.slice(0,15) + "." + tail.slice(15))));
if(m.length == 16) m = m.slice(0,2) + "." + m.slice(2);
else m = m.charAt(0) + "." + m.slice(1);
}
}
else m = m.slice(0,15) + fill("0", m.length - 15);
return Number(m + s.slice(s.indexOf("e")));
}
var n = s.indexOf(".") > -1 ? s.slice(0, (s.slice(0,2) == "0." ? 17 : 16)) : (s.slice(0,15) + fill("0", s.length - 15));
return Number(n);
}

View File

@ -54,7 +54,7 @@ function write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*:str
switch(fmt) {
case '[h]': case '[hh]': out = val.D*24+val.H; break;
case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+(ss0 == 0 ? Math.round(val.S+val.u) : val.S); break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
default: throw 'bad abstime format: ' + fmt;
} outl = fmt.length === 3 ? 1 : 2; break;
case 101: /* 'e' era */

View File

@ -39,7 +39,7 @@ function write_num_f2(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:s
return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
}
var dec1 = /^#*0*\.([0#]+)/;
var closeparen = /\)[^)]*[0#]/;
var closeparen = /\).*[0#]/;
var phone = /\(###\) ###\\?-####/;
function hashq(str/*:string*/)/*:string*/ {
var o = "", cc;

View File

@ -1,5 +1,4 @@
function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
if(typeof v == "number") v = normalize_xl_unsafe(v);
var out = [], o = "", i = 0, c = "", lst='t', dt, j, cc;
var hr='H';
/* Tokenize */
@ -86,11 +85,10 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
switch(out[i].t) {
case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
case 's':
if((ssm=out[i].v.match(/\.0+$/))) { ss0=Math.max(ss0,ssm[0].length-1); bt = 4;}
if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
if(bt < 3) bt = 3;
/* falls through */
case 'd': case 'y': case 'e': lst=out[i].t; break;
case 'M': lst=out[i].t; if(bt < 2) bt = 2; break;
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
case 'X': /*if(out[i].v === "B2");*/
break;
@ -100,29 +98,19 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
}
}
/* time rounding depends on presence of minute / second / usec fields */
var _dt;
switch(bt) {
case 0: break;
case 1:
case 2:
case 3:
/*::if(!dt) break;*/
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
if(dt.H >= 24) { dt.H = 0; ++dt.D; _dt = parse_date_code(dt.D); _dt.u = dt.u; _dt.S = dt.S; _dt.M = dt.M; _dt.H = dt.H; dt = _dt; }
break;
case 4:
switch(ss0) {
case 1: dt.u = Math.round(dt.u * 10)/10; break;
case 2: dt.u = Math.round(dt.u * 100)/100; break;
case 3: dt.u = Math.round(dt.u * 1000)/1000; break;
}
if(dt.u >= 1) { dt.u = 0; ++dt.S; }
case 2:
/*::if(!dt) break;*/
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
if(dt.H >= 24) { dt.H = 0; ++dt.D; _dt = parse_date_code(dt.D); _dt.u = dt.u; _dt.S = dt.S; _dt.M = dt.M; _dt.H = dt.H; dt = _dt; }
break;
}

View File

@ -4,8 +4,6 @@ function choose_fmt(f/*:string*/, v/*:any*/) {
if(l<4 && lat>-1) --l;
if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
/* NOTE: most spreadsheet software do not support NaN or infinities */
if(typeof v === "number" && !isFinite(v)) v = 0;
switch(fmt.length) {
case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
@ -42,7 +40,5 @@ function format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
if(isgeneral(f[1])) return general_fmt(v, o);
if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
else if(v === "" || v == null) return "";
else if(isNaN(v) && f[1].indexOf("0") > -1) return "#VALUE!";
else if(!isFinite(v) && f[1].indexOf("0") > -1) return "#DIV/0!";
return eval_fmt(f[1], v, o, f[0]);
}

View File

@ -1,6 +1,6 @@
{
"name": "ssf",
"version": "0.11.3",
"version": "0.11.2",
"author": "sheetjs",
"description": "Format data using ECMA-376 spreadsheet Format Codes",
"keywords": [
@ -19,12 +19,11 @@
"blanket": "~1.2.3",
"dtslint": "^0.1.2",
"mocha": "~2.5.3",
"typescript": "2.2.0",
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz"
"typescript": "2.2.0"
},
"repository": {
"type": "git",
"url": "https://git.sheetjs.com/SheetJS/sheetjs",
"url": "git://github.com/SheetJS/sheetjs.git",
"directory": "packages/ssf"
},
"scripts": {
@ -49,9 +48,9 @@
"holes"
]
},
"homepage": "https://sheetjs.com/",
"homepage": "http://sheetjs.com/",
"bugs": {
"url": "https://git.sheetjs.com/SheetJS/sheetjs/issues"
"url": "https://github.com/SheetJS/sheetjs/issues"
},
"license": "Apache-2.0",
"engines": {

View File

@ -3,8 +3,8 @@
/*jshint -W041 */
/*:: declare var DO_NOT_EXPORT_SSF: any; */
var SSF/*:SSFModule*/ = ({}/*:any*/);
function make_ssf(SSF/*:SSFModule*/){
SSF.version = '0.11.3';
var make_ssf = function make_ssf(SSF/*:SSFModule*/){
SSF.version = '0.11.2';
function _strrev(x/*:string*/)/*:string*/ { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; }
function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; }
function pad0(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
@ -12,7 +12,7 @@ function pad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v;return t.length>=d?t
function rpad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);}
function pad0r1(v/*:any*/,d/*:number*/)/*:string*/{var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;}
function pad0r2(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
var p2_32 = /*#__PURE__*/Math.pow(2,32);
var p2_32 = Math.pow(2,32);
function pad0r(v/*:any*/,d/*:number*/)/*:string*/{if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); }
function isgeneral(s/*:string*/, i/*:?number*/)/*:boolean*/ { i = i || 0; return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; }
/*::
@ -42,7 +42,6 @@ var months/*:Array<Array<string> >*/ = [
['D', 'Dec', 'December']
];
function init_table(t/*:any*/) {
if(!t) t = {};
t[0]= 'General';
t[1]= '0';
t[2]= '0.00';
@ -72,7 +71,6 @@ function init_table(t/*:any*/) {
t[48]= '##0.0E+0';
t[49]= '@';
t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "';
return t;
}
var table_fmt = {};
@ -143,26 +141,6 @@ var default_str = {
44: '_("$"* #,##0.00_);_("$"* \\(#,##0.00\\);_("$"* "-"??_);_(@_)'
};
function normalize_xl_unsafe(v/*:number*/)/*:number*/ {
if(v == 0) return 0;
var s = v.toPrecision(17);
if(s.indexOf("e") > -1) {
var m = s.slice(0, s.indexOf("e"));
if(m.indexOf(".") > -1) {
var tail = m.charAt(0) + m.slice(2, 17);
m = m.slice(0, 16);
if(tail.length == 16) {
m = String(Math.round(Number(tail.slice(0,15) + "." + tail.slice(15))));
if(m.length == 16) m = m.slice(0,2) + "." + m.slice(2);
else m = m.charAt(0) + "." + m.slice(1);
}
}
else m = m.slice(0,15) + fill("0", m.length - 15);
return Number(m + s.slice(s.indexOf("e")));
}
var n = s.indexOf(".") > -1 ? s.slice(0, (s.slice(0,2) == "0." ? 17 : 16)) : (s.slice(0,15) + fill("0", s.length - 15));
return Number(n);
}
function frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
var sgn = x < 0 ? -1 : 1;
var B = x * sgn;
@ -223,6 +201,10 @@ function datenum_local(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
else if(v >= base1904) epoch += 24*60*60*1000;
return (epoch - (dnthresh + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
}
/* The longest 32-bit integer text is "-4294967296", exactly 11 chars */
function general_fmt_int(v/*:number*/)/*:string*/ { return v.toString(10); }
SSF._general_int = general_fmt_int;
/* ECMA-376 18.8.30 numFmt*/
/* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
var general_fmt_num = (function make_general_fmt_num() {
@ -275,7 +257,6 @@ SSF._general_num = general_fmt_num;
- "up to 11 characters" displayed for numbers
- Default date format (code 14) used for Dates
The longest 32-bit integer text is "-2147483648", exactly 11 chars
TODO: technically the display depends on the width of the cell
*/
function general_fmt(v/*:any*/, opts/*:any*/) {
@ -355,7 +336,7 @@ function write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*:str
switch(fmt) {
case '[h]': case '[hh]': out = val.D*24+val.H; break;
case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+(ss0 == 0 ? Math.round(val.S+val.u) : val.S); break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
default: throw 'bad abstime format: ' + fmt;
} outl = fmt.length === 3 ? 1 : 2; break;
case 101: /* 'e' era */
@ -419,7 +400,7 @@ function write_num_f2(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:s
return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
}
var dec1 = /^#*0*\.([0#]+)/;
var closeparen = /\)[^)]*[0#]/;
var closeparen = /\).*[0#]/;
var phone = /\(###\) ###\\?-####/;
function hashq(str/*:string*/)/*:string*/ {
var o = "", cc;
@ -713,7 +694,6 @@ function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
}
SSF.is_date = fmt_is_date;
function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
if(typeof v == "number") v = normalize_xl_unsafe(v);
var out = [], o = "", i = 0, c = "", lst='t', dt, j, cc;
var hr='H';
/* Tokenize */
@ -800,11 +780,10 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
switch(out[i].t) {
case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
case 's':
if((ssm=out[i].v.match(/\.0+$/))) { ss0=Math.max(ss0,ssm[0].length-1); bt = 4;}
if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
if(bt < 3) bt = 3;
/* falls through */
case 'd': case 'y': case 'e': lst=out[i].t; break;
case 'M': lst=out[i].t; if(bt < 2) bt = 2; break;
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
case 'X': /*if(out[i].v === "B2");*/
break;
@ -814,29 +793,19 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
}
}
/* time rounding depends on presence of minute / second / usec fields */
var _dt;
switch(bt) {
case 0: break;
case 1:
case 2:
case 3:
/*::if(!dt) break;*/
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
if(dt.H >= 24) { dt.H = 0; ++dt.D; _dt = parse_date_code(dt.D); _dt.u = dt.u; _dt.S = dt.S; _dt.M = dt.M; _dt.H = dt.H; dt = _dt; }
break;
case 4:
switch(ss0) {
case 1: dt.u = Math.round(dt.u * 10)/10; break;
case 2: dt.u = Math.round(dt.u * 100)/100; break;
case 3: dt.u = Math.round(dt.u * 1000)/1000; break;
}
if(dt.u >= 1) { dt.u = 0; ++dt.S; }
case 2:
/*::if(!dt) break;*/
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
if(dt.H >= 24) { dt.H = 0; ++dt.D; _dt = parse_date_code(dt.D); _dt.u = dt.u; _dt.S = dt.S; _dt.M = dt.M; _dt.H = dt.H; dt = _dt; }
break;
}
@ -953,8 +922,6 @@ function choose_fmt(f/*:string*/, v/*:any*/) {
if(l<4 && lat>-1) --l;
if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
/* NOTE: most spreadsheet software do not support NaN or infinities */
if(typeof v === "number" && !isFinite(v)) v = 0;
switch(fmt.length) {
case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
@ -991,8 +958,6 @@ function format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
if(isgeneral(f[1])) return general_fmt(v, o);
if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
else if(v === "" || v == null) return "";
else if(isNaN(v) && f[1].indexOf("0") > -1) return "#VALUE!";
else if(!isFinite(v) && f[1].indexOf("0") > -1) return "#DIV/0!";
return eval_fmt(f[1], v, o, f[0]);
}
function load_entry(fmt/*:string*/, idx/*:?number*/)/*:number*/ {
@ -1020,8 +985,7 @@ SSF.load_table = function load_table(tbl/*:SSFTable*/)/*:void*/ {
};
SSF.init_table = init_table;
SSF.format = format;
SSF.choose_format = choose_fmt;
}
};
make_ssf(SSF);
/*global module */
if(typeof module !== 'undefined' && typeof DO_NOT_EXPORT_SSF === 'undefined') module.exports = SSF;

View File

@ -2,8 +2,8 @@
/* vim: set ts=2: */
/*jshint -W041 */
var SSF = ({});
function make_ssf(SSF){
SSF.version = '0.11.3';
var make_ssf = function make_ssf(SSF){
SSF.version = '0.11.2';
function _strrev(x) { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; }
function fill(c,l) { var o = ""; while(o.length < l) o+=c; return o; }
function pad0(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
@ -38,7 +38,6 @@ var months = [
['D', 'Dec', 'December']
];
function init_table(t) {
if(!t) t = {};
t[0]= 'General';
t[1]= '0';
t[2]= '0.00';
@ -68,7 +67,6 @@ function init_table(t) {
t[48]= '##0.0E+0';
t[49]= '@';
t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "';
return t;
}
var table_fmt = {};
@ -139,26 +137,6 @@ var default_str = {
44: '_("$"* #,##0.00_);_("$"* \\(#,##0.00\\);_("$"* "-"??_);_(@_)'
};
function normalize_xl_unsafe(v) {
if(v == 0) return 0;
var s = v.toPrecision(17);
if(s.indexOf("e") > -1) {
var m = s.slice(0, s.indexOf("e"));
if(m.indexOf(".") > -1) {
var tail = m.charAt(0) + m.slice(2, 17);
m = m.slice(0, 16);
if(tail.length == 16) {
m = String(Math.round(Number(tail.slice(0,15) + "." + tail.slice(15))));
if(m.length == 16) m = m.slice(0,2) + "." + m.slice(2);
else m = m.charAt(0) + "." + m.slice(1);
}
}
else m = m.slice(0,15) + fill("0", m.length - 15);
return Number(m + s.slice(s.indexOf("e")));
}
var n = s.indexOf(".") > -1 ? s.slice(0, (s.slice(0,2) == "0." ? 17 : 16)) : (s.slice(0,15) + fill("0", s.length - 15));
return Number(n);
}
function frac(x, D, mixed) {
var sgn = x < 0 ? -1 : 1;
var B = x * sgn;
@ -219,6 +197,10 @@ function datenum_local(v, date1904) {
else if(v >= base1904) epoch += 24*60*60*1000;
return (epoch - (dnthresh + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
}
/* The longest 32-bit integer text is "-4294967296", exactly 11 chars */
function general_fmt_int(v) { return v.toString(10); }
SSF._general_int = general_fmt_int;
/* ECMA-376 18.8.30 numFmt*/
/* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
var general_fmt_num = (function make_general_fmt_num() {
@ -271,7 +253,6 @@ SSF._general_num = general_fmt_num;
- "up to 11 characters" displayed for numbers
- Default date format (code 14) used for Dates
The longest 32-bit integer text is "-2147483648", exactly 11 chars
TODO: technically the display depends on the width of the cell
*/
function general_fmt(v, opts) {
@ -350,7 +331,7 @@ if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100;
switch(fmt) {
case '[h]': case '[hh]': out = val.D*24+val.H; break;
case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+(ss0 == 0 ? Math.round(val.S+val.u) : val.S); break;
case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
default: throw 'bad abstime format: ' + fmt;
} outl = fmt.length === 3 ? 1 : 2; break;
case 101: /* 'e' era */
@ -414,7 +395,7 @@ function write_num_f2(r, aval, sign) {
return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
}
var dec1 = /^#*0*\.([0#]+)/;
var closeparen = /\)[^)]*[0#]/;
var closeparen = /\).*[0#]/;
var phone = /\(###\) ###\\?-####/;
function hashq(str) {
var o = "", cc;
@ -706,7 +687,6 @@ function fmt_is_date(fmt) {
}
SSF.is_date = fmt_is_date;
function eval_fmt(fmt, v, opts, flen) {
if(typeof v == "number") v = normalize_xl_unsafe(v);
var out = [], o = "", i = 0, c = "", lst='t', dt, j, cc;
var hr='H';
/* Tokenize */
@ -793,11 +773,10 @@ function eval_fmt(fmt, v, opts, flen) {
switch(out[i].t) {
case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
case 's':
if((ssm=out[i].v.match(/\.0+$/))) { ss0=Math.max(ss0,ssm[0].length-1); bt = 4;}
if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
if(bt < 3) bt = 3;
/* falls through */
case 'd': case 'y': case 'e': lst=out[i].t; break;
case 'M': lst=out[i].t; if(bt < 2) bt = 2; break;
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
case 'X': /*if(out[i].v === "B2");*/
break;
@ -807,29 +786,17 @@ function eval_fmt(fmt, v, opts, flen) {
if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
}
}
/* time rounding depends on presence of minute / second / usec fields */
var _dt;
switch(bt) {
case 0: break;
case 1:
case 2:
case 3:
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
if(dt.H >= 24) { dt.H = 0; ++dt.D; _dt = parse_date_code(dt.D); _dt.u = dt.u; _dt.S = dt.S; _dt.M = dt.M; _dt.H = dt.H; dt = _dt; }
break;
case 4:
switch(ss0) {
case 1: dt.u = Math.round(dt.u * 10)/10; break;
case 2: dt.u = Math.round(dt.u * 100)/100; break;
case 3: dt.u = Math.round(dt.u * 1000)/1000; break;
}
if(dt.u >= 1) { dt.u = 0; ++dt.S; }
case 2:
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
if(dt.H >= 24) { dt.H = 0; ++dt.D; _dt = parse_date_code(dt.D); _dt.u = dt.u; _dt.S = dt.S; _dt.M = dt.M; _dt.H = dt.H; dt = _dt; }
break;
}
@ -945,8 +912,6 @@ function choose_fmt(f, v) {
if(l<4 && lat>-1) --l;
if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
/* NOTE: most spreadsheet software do not support NaN or infinities */
if(typeof v === "number" && !isFinite(v)) v = 0;
switch(fmt.length) {
case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
@ -983,8 +948,6 @@ function format(fmt,v,o) {
if(isgeneral(f[1])) return general_fmt(v, o);
if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
else if(v === "" || v == null) return "";
else if(isNaN(v) && f[1].indexOf("0") > -1) return "#VALUE!";
else if(!isFinite(v) && f[1].indexOf("0") > -1) return "#DIV/0!";
return eval_fmt(f[1], v, o, f[0]);
}
function load_entry(fmt, idx) {
@ -1008,8 +971,7 @@ SSF.load_table = function load_table(tbl) {
};
SSF.init_table = init_table;
SSF.format = format;
SSF.choose_format = choose_fmt;
}
};
make_ssf(SSF);
/*global module */
if(typeof module !== 'undefined' && typeof DO_NOT_EXPORT_SSF === 'undefined') module.exports = SSF;

Some files were not shown because too many files have changed in this diff Show More