Merge branch 'master' into types
This commit is contained in:
commit
c9b78b6563
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -4,6 +4,18 @@ 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.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)
|
||||
|
|
7
Makefile
7
Makefile
|
@ -67,10 +67,9 @@ clean-data:
|
|||
|
||||
.PHONY: init
|
||||
init: ## Initial setup for development
|
||||
git submodule init
|
||||
git submodule update
|
||||
#git submodule foreach git pull origin master
|
||||
git submodule foreach make all
|
||||
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
|
||||
mkdir -p tmp
|
||||
|
||||
DISTHDR=misc/suppress_export.js
|
||||
|
|
19
README.md
19
README.md
|
@ -9,29 +9,30 @@ 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)
|
||||
|
||||
## Related Projects
|
||||
## Constellation
|
||||
|
||||
- <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
|
||||
|
||||
- [`test_files`](https://github.com/SheetJS/test_files): Sample spreadsheets
|
||||
- [`cfb`](https://git.sheetjs.com/SheetJS/js-cfb): Container (OLE/ZIP) file
|
||||
processing library
|
||||
|
||||
- [`cfb`](https://git.sheetjs.com/SheetJS/js-cfb): Container (OLE/ZIP) format library
|
||||
- [`codepage`](https://git.sheetjs.com/SheetJS/js-codepage): Legacy text
|
||||
encodings for XLS and other legacy spreadsheet formats
|
||||
|
||||
- [`codepage`](https://git.sheetjs.com/SheetJS/js-codepage): Legacy text encodings
|
||||
- [`dta`](packages/dta): Stata DTA file processor
|
||||
|
||||
- [`test_files`](https://github.com/sheetjs/test_files): Test files and various
|
||||
plaintext baselines.
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
XLSX.version = '0.20.0';
|
||||
XLSX.version = '0.20.1';
|
||||
|
|
|
@ -29,7 +29,7 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
|
|||
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)) v = utc_to_local(v); break;
|
||||
case 'd': if(!(o && (o.UTC||(o.raw === false)))) v = utc_to_local(new Date(v)); break;
|
||||
default: throw new Error('unrecognized type ' + val.t);
|
||||
}
|
||||
if(hdr[C] != null) {
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -160,7 +160,7 @@ var DO_NOT_EXPORT_CODEPAGE = true;
|
|||
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false, Float32Array:false */
|
||||
var XLSX = {};
|
||||
function make_xlsx_lib(XLSX){
|
||||
XLSX.version = '0.20.0';
|
||||
XLSX.version = '0.20.1';
|
||||
var current_codepage = 1200, current_ansi = 1252;
|
||||
/*global cptable:true, window */
|
||||
var $cptable;
|
||||
|
@ -620,8 +620,20 @@ function SSF_frac(x, D, mixed) {
|
|||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
}
|
||||
function SSF_normalize_xl_unsafe(v) {
|
||||
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,opts,b2) {
|
||||
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};
|
||||
|
@ -774,7 +786,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+Math.round(val.S+val.u); 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;
|
||||
default: throw 'bad abstime format: ' + fmt;
|
||||
} outl = fmt.length === 3 ? 1 : 2; break;
|
||||
case 101: /* 'e' era */
|
||||
|
@ -1220,10 +1232,11 @@ 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);
|
||||
if((ssm=out[i].v.match(/\.0+$/))) { ss0=Math.max(ss0,ssm[0].length-1); bt = 4;}
|
||||
if(bt < 3) bt = 3;
|
||||
/* falls through */
|
||||
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
|
||||
case 'd': case 'y': case 'e': lst=out[i].t; break;
|
||||
case 'M': lst=out[i].t; if(bt < 2) bt = 2; break;
|
||||
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
|
||||
case 'X': /*if(out[i].v === "B2");*/
|
||||
break;
|
||||
|
@ -1233,17 +1246,29 @@ 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:
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
case 2:
|
||||
case 3:
|
||||
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 2:
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
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; }
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -4503,6 +4528,13 @@ function sheet_to_workbook(sheet, opts) {
|
|||
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, data, opts) {
|
||||
var o = opts || {};
|
||||
var dense = _ws ? (_ws["!data"] != null) : o.dense;
|
||||
|
@ -8059,7 +8091,7 @@ var fields = [], field = ({});
|
|||
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 '?': break;
|
||||
case '': case '\x00': case '?': break;
|
||||
default: throw new Error("DBF Unrecognized L:|" + s + "|");
|
||||
} break;
|
||||
case 'M': /* TODO: handle memo files */
|
||||
|
@ -8121,6 +8153,7 @@ function dbf_to_workbook(buf, opts) {
|
|||
|
||||
var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 };
|
||||
function sheet_to_dbf(ws, opts) {
|
||||
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);
|
||||
|
@ -8278,7 +8311,10 @@ var SYLK = (function() {
|
|||
"!":161, '"':162, "#":163, "(":164, "%":165, "'":167, "H ":168,
|
||||
"+":171, ";":187, "<":188, "=":189, ">":190, "?":191, "{":223
|
||||
});
|
||||
var sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1") + "|\\|)", "gm");
|
||||
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_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;
|
||||
|
@ -8501,7 +8537,7 @@ var SYLK = (function() {
|
|||
if(!opts) opts = {}; opts._formats = ["General"];
|
||||
/* TODO: codepage */
|
||||
var preamble = ["ID;PSheetJS;N;E"], o = [];
|
||||
var r = safe_decode_range(ws['!ref']), cell;
|
||||
var r = safe_decode_range(ws['!ref']||"A1"), cell;
|
||||
var dense = ws["!data"] != null;
|
||||
var RS = "\r\n";
|
||||
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
|
@ -8510,7 +8546,7 @@ var SYLK = (function() {
|
|||
preamble.push("P;PGeneral");
|
||||
/* Excel has been inconsistent in comment placement */
|
||||
var R = r.s.r, C = r.s.c, p = [];
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
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) {
|
||||
|
@ -8520,7 +8556,7 @@ var SYLK = (function() {
|
|||
}
|
||||
if(p.length) o.push(p.join(RS));
|
||||
}
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
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) {
|
||||
|
@ -8540,7 +8576,7 @@ var SYLK = (function() {
|
|||
if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
|
||||
if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
|
||||
|
||||
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(" "));
|
||||
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("O;L;D;B" + (d1904 ? ";V4" : "") + ";K47;G100 0.001");
|
||||
|
||||
delete opts._formats;
|
||||
|
@ -8613,6 +8649,7 @@ var DIF = (function() {
|
|||
function make_value_str(s) { return "1,0\r\n\"" + s.replace(/"/g,'""') + '"'; }
|
||||
function sheet_to_dif(ws) {
|
||||
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 = [
|
||||
|
@ -8950,6 +8987,7 @@ var PRN = (function() {
|
|||
|
||||
function sheet_to_prn(ws) {
|
||||
var o = [];
|
||||
if(!ws["!ref"]) return "";
|
||||
var r = safe_decode_range(ws['!ref']), cell;
|
||||
var dense = ws["!data"] != null;
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
|
@ -9174,6 +9212,7 @@ var WK_ = (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 = [];
|
||||
|
@ -9967,13 +10006,25 @@ var WK_ = (function() {
|
|||
0x0E: "dd-mmm-yyyy",
|
||||
0x0F: "mmm-yyyy",
|
||||
|
||||
0x22: "0.00",
|
||||
0x32: "0.00;[Red]0.00",
|
||||
0x42: "0.00;\(0.00\)",
|
||||
0x52: "0.00;[Red]\(0.00\)",
|
||||
|
||||
162: '"$"#,##0;\\("$"#,##0\\)' // slightly different from SSF 5
|
||||
/* 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) {
|
||||
prep_blob(d, 0);
|
||||
|
@ -10084,7 +10135,11 @@ var WK_ = (function() {
|
|||
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; 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;
|
||||
default: throw "Unrecognized QPW cell type " + (flags & 0x1F);
|
||||
}
|
||||
if(fmtidx != -1 && (FMTS[fmtidx - 1]||{}).z) cell.z = FMTS[fmtidx-1].z;
|
||||
|
@ -10130,6 +10185,17 @@ var WK_ = (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;
|
||||
|
@ -11281,7 +11347,7 @@ function parse_cellXfs(t, styles, opts) {
|
|||
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]])
|
||||
|
@ -11295,7 +11361,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;
|
||||
|
@ -11307,12 +11373,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': pass = true; break;
|
||||
case '<AlternateContent': case '<AlternateContent>': pass = true; break;
|
||||
case '</AlternateContent>': pass = false; break;
|
||||
|
||||
/* 18.2.10 extLst CT_ExtensionList ? */
|
||||
|
@ -12951,7 +13017,10 @@ var rc_to_a1 = (function(){
|
|||
};
|
||||
})();
|
||||
|
||||
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 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 a1_to_rc = (function(){
|
||||
return function a1_to_rc(fstr, base) {
|
||||
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
|
||||
|
@ -15664,7 +15733,7 @@ function parse_ws_xml_dim(ws, s) {
|
|||
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 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*)"/;
|
||||
|
@ -22507,9 +22576,9 @@ function sheet_to_html(ws, opts/*, wb:?Workbook*/) {
|
|||
var header = o.header != null ? o.header : HTML_BEGIN;
|
||||
var footer = o.footer != null ? o.footer : HTML_END;
|
||||
var out = [header];
|
||||
var r = decode_range(ws['!ref']);
|
||||
var r = decode_range(ws['!ref'] || "A1");
|
||||
out.push(make_html_preamble(ws, r, o));
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
|
||||
if(ws["!ref"]) 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("");
|
||||
}
|
||||
|
@ -23268,10 +23337,13 @@ function parse_content_xml(d, _opts, _nfm) {
|
|||
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:
|
||||
|
@ -23788,6 +23860,7 @@ var write_content_ods = /* @__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})];
|
||||
|
@ -25039,7 +25112,7 @@ function s5s_to_iwa_comment(s5s) {
|
|||
return out;
|
||||
}
|
||||
function parse_TST_TableModelArchive(M, root, ws, opts) {
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
||||
var pb = parse_shallow(root.data);
|
||||
var range = { s: { r: 0, c: 0 }, e: { r: 0, c: 0 } };
|
||||
range.e.r = (varint_to_i32(pb[6][0].data) >>> 0) - 1;
|
||||
|
@ -25068,7 +25141,17 @@ function parse_TST_TableModelArchive(M, root, ws, opts) {
|
|||
lut.nfmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[22][0].data)][0]);
|
||||
var tile = parse_shallow(store[3][0].data);
|
||||
var _R = 0;
|
||||
tile[1].forEach(function(t) {
|
||||
if (!((_h = store[9]) == null ? void 0 : _h[0]))
|
||||
throw "NUMBERS file missing row tree";
|
||||
var rtt = parse_shallow(store[9][0].data)[1].map(function(p) {
|
||||
return parse_shallow(p.data);
|
||||
});
|
||||
rtt.forEach(function(kv) {
|
||||
_R = varint_to_i32(kv[1][0].data);
|
||||
var tidx = varint_to_i32(kv[2][0].data);
|
||||
var t = tile[1][tidx];
|
||||
if (!t)
|
||||
throw "NUMBERS missing tile " + tidx;
|
||||
var tl = parse_shallow(t.data);
|
||||
var ref2 = M[parse_TSP_Reference(tl[2][0].data)][0];
|
||||
var mtype2 = varint_to_i32(ref2.meta[1][0].data);
|
||||
|
@ -25091,12 +25174,12 @@ function parse_TST_TableModelArchive(M, root, ws, opts) {
|
|||
});
|
||||
_R += _tile.nrows;
|
||||
});
|
||||
if ((_h = store[13]) == null ? void 0 : _h[0]) {
|
||||
if ((_i = store[13]) == null ? void 0 : _i[0]) {
|
||||
var ref = M[parse_TSP_Reference(store[13][0].data)][0];
|
||||
var mtype = varint_to_i32(ref.meta[1][0].data);
|
||||
if (mtype != 6144)
|
||||
throw new Error("Expected merge type 6144, found ".concat(mtype));
|
||||
ws["!merges"] = (_i = parse_shallow(ref.data)) == null ? void 0 : _i[1].map(function(pi) {
|
||||
ws["!merges"] = (_j = parse_shallow(ref.data)) == null ? void 0 : _j[1].map(function(pi) {
|
||||
var merge = parse_shallow(pi.data);
|
||||
var origin = u8_to_dataview(parse_shallow(merge[1][0].data)[1][0].data), size = u8_to_dataview(parse_shallow(merge[2][0].data)[1][0].data);
|
||||
return {
|
||||
|
@ -25758,6 +25841,8 @@ function write_numbers_ws(cfb, deps, ws, wsname, sheetidx, rootref) {
|
|||
}
|
||||
var USE_WIDE_ROWS = true;
|
||||
function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) {
|
||||
if (!ws["!ref"])
|
||||
throw new Error("Cannot export empty sheet to NUMBERS");
|
||||
var range = decode_range(ws["!ref"]);
|
||||
range.s.r = range.s.c = 0;
|
||||
var trunc = false;
|
||||
|
@ -27192,7 +27277,7 @@ function make_json_row(sheet, r, R, cols, header, hdr, o) {
|
|||
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)) v = utc_to_local(v); break;
|
||||
case 'd': if(!(o && (o.UTC||(o.raw === false)))) v = utc_to_local(new Date(v)); break;
|
||||
default: throw new Error('unrecognized type ' + val.t);
|
||||
}
|
||||
if(hdr[C] != null) {
|
||||
|
@ -27202,7 +27287,7 @@ function make_json_row(sheet, r, R, cols, header, hdr, o) {
|
|||
else if(raw && v === null) row[hdr[C]] = null;
|
||||
else continue;
|
||||
} else {
|
||||
row[hdr[C]] = raw && (val.t !== "n" || (val.t === "n" && o.rawNumbers !== false)) ? v : format_cell(val,v,o);
|
||||
row[hdr[C]] = (val.t === 'n' && typeof o.rawNumbers === 'boolean' ? o.rawNumbers : raw) ? v : format_cell(val, v, o);
|
||||
}
|
||||
if(v != null) isempty = false;
|
||||
}
|
||||
|
@ -27460,9 +27545,11 @@ function wb_sheet_idx(wb, sh) {
|
|||
} else throw new Error("Cannot find sheet |" + sh + "|");
|
||||
}
|
||||
|
||||
/* simple blank workbook object */
|
||||
function book_new() {
|
||||
return { SheetNames: [], Sheets: {} };
|
||||
/* simple blank or single-sheet workbook object */
|
||||
function book_new(ws, wsname) {
|
||||
var wb = { SheetNames: [], Sheets: {} };
|
||||
if(ws) book_append_sheet(wb, ws, wsname || "Sheet1");
|
||||
return wb;
|
||||
}
|
||||
|
||||
/* add a worksheet to the end of a given workbook */
|
||||
|
@ -27559,6 +27646,7 @@ var utils = {
|
|||
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,
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "xlsx",
|
||||
"version": "0.20.0+csv",
|
||||
"version": "0.20.1",
|
||||
"author": "sheetjs",
|
||||
"description": "SheetJS Spreadsheet data parser and writer",
|
||||
"keywords": [
|
||||
|
@ -167,6 +167,12 @@
|
|||
]
|
||||
},
|
||||
"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"
|
||||
},
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
misc/
|
|
@ -1,5 +1,15 @@
|
|||
.PHONY: build
|
||||
build: node browser
|
||||
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
|
||||
|
||||
|
|
|
@ -6,4 +6,58 @@ 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.
|
||||
<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.1/dta-0.0.1.tgz
|
||||
```
|
||||
|
||||
The standalone script is also hosted on the SheetJS CDN:
|
||||
|
||||
```html
|
||||
<script src="https://cdn.sheetjs.com/dta-0.0.1/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>
|
||||
```
|
|
@ -15,5 +15,5 @@ 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 = " ";}}));
|
||||
//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]]));
|
|
@ -25,41 +25,95 @@ var __toCommonJS = /* @__PURE__ */ ((cache) => {
|
|||
var dta_exports = {};
|
||||
__export(dta_exports, {
|
||||
parse: () => parse,
|
||||
set_utils: () => set_utils
|
||||
set_utils: () => set_utils,
|
||||
version: () => version
|
||||
});
|
||||
var version = "0.0.1";
|
||||
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 (p.str.slice(p.ptr, p.ptr + n.length) != n)
|
||||
if (u8_to_str(p.raw.slice(p.ptr, p.ptr + n.length)) != n)
|
||||
return false;
|
||||
p.ptr += n.length;
|
||||
return true;
|
||||
}
|
||||
function skip_end(p, n) {
|
||||
const idx = p.str.indexOf(n, p.ptr);
|
||||
if (idx == -1)
|
||||
throw new Error(`Expected ${n} after offset ${p.ptr}`);
|
||||
p.ptr = idx + n.length;
|
||||
}
|
||||
function slice_end(p, n) {
|
||||
const idx = p.str.indexOf(n, p.ptr);
|
||||
if (idx == -1)
|
||||
throw new Error(`Expected ${n} after offset ${p.ptr}`);
|
||||
const raw = p.raw.slice(p.ptr, idx);
|
||||
const res = {
|
||||
ptr: 0,
|
||||
raw,
|
||||
str: p.str.slice(p.ptr, idx),
|
||||
dv: u8_to_dataview(raw)
|
||||
};
|
||||
p.ptr = idx + n.length;
|
||||
return res;
|
||||
}
|
||||
function read_f64(p, LE) {
|
||||
p.ptr += 8;
|
||||
const d = p.dv.getFloat64(p.ptr - 8, LE);
|
||||
|
@ -98,15 +152,29 @@ function read_i8(p) {
|
|||
}
|
||||
var SUPPORTED_VERSIONS_TAGGED = [
|
||||
"117",
|
||||
"118"
|
||||
"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 str = new TextDecoder("latin1").decode(raw);
|
||||
const d = {
|
||||
ptr: 0,
|
||||
raw,
|
||||
str,
|
||||
dv: u8_to_dataview(raw)
|
||||
};
|
||||
let vers = 118;
|
||||
|
@ -124,16 +192,22 @@ function parse_tagged(raw) {
|
|||
{
|
||||
if (!valid_inc(d, "<release>"))
|
||||
throw err;
|
||||
const res = slice_end(d, "</release>");
|
||||
if (SUPPORTED_VERSIONS_TAGGED.indexOf(res.str) == -1)
|
||||
throw `Unsupported DTA ${res.str} file`;
|
||||
vers = +res.str;
|
||||
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 = slice_end(d, "</byteorder>");
|
||||
switch (res.str) {
|
||||
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;
|
||||
|
@ -141,48 +215,49 @@ function parse_tagged(raw) {
|
|||
LE = true;
|
||||
break;
|
||||
default:
|
||||
throw `Unsupported byteorder ${res.str}`;
|
||||
throw `Unsupported byteorder ${res}`;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (!valid_inc(d, "<K>"))
|
||||
throw err;
|
||||
const res = slice_end(d, "</K>");
|
||||
nvar = read_u16(res, LE);
|
||||
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;
|
||||
const res = slice_end(d, "</N>");
|
||||
if (vers == 117)
|
||||
nobs = nobs_lo = read_u32(res, LE);
|
||||
nobs = nobs_lo = read_u32(d, LE);
|
||||
else {
|
||||
const lo = read_u32(res, LE), hi = read_u32(res, LE);
|
||||
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 res = slice_end(d, "</label>");
|
||||
const w = vers >= 118 ? 2 : 1;
|
||||
const strlen = w == 1 ? read_u8(res) : read_u16(res, LE);
|
||||
if (strlen + w != res.str.length)
|
||||
throw `Expected string length ${strlen} but actual length was ${res.str.length - w}`;
|
||||
const strlen = w == 1 ? read_u8(d) : read_u16(d, LE);
|
||||
if (strlen > 0)
|
||||
label = new TextDecoder().decode(res.raw.slice(w));
|
||||
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 res = slice_end(d, "</timestamp>");
|
||||
const strlen = read_u8(res);
|
||||
if (strlen + 1 != res.str.length)
|
||||
throw `Expected string length ${strlen} but actual length was ${res.str.length - 1}`;
|
||||
if (strlen > 0)
|
||||
timestamp = res.str.slice(1);
|
||||
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;
|
||||
|
@ -190,17 +265,16 @@ function parse_tagged(raw) {
|
|||
{
|
||||
if (!valid_inc(d, "<map>"))
|
||||
throw err;
|
||||
skip_end(d, "</map>");
|
||||
d.ptr += 8 * 14;
|
||||
if (!valid_inc(d, "</map>"))
|
||||
throw err;
|
||||
}
|
||||
let stride = 0;
|
||||
{
|
||||
if (!valid_inc(d, "<variable_types>"))
|
||||
throw err;
|
||||
const res = slice_end(d, "</variable_types>");
|
||||
if (res.raw.length != 2 * nvar)
|
||||
throw `Expected variable_types length ${nvar * 2}, found ${res.raw.length}`;
|
||||
while (res.ptr < res.raw.length) {
|
||||
const type = read_u16(res, LE);
|
||||
for (var i = 0; i < nvar; ++i) {
|
||||
const type = read_u16(d, LE);
|
||||
var_types.push(type);
|
||||
if (type >= 1 && type <= 2045)
|
||||
stride += type;
|
||||
|
@ -209,6 +283,9 @@ function parse_tagged(raw) {
|
|||
case 32768:
|
||||
stride += 8;
|
||||
break;
|
||||
case 65525:
|
||||
stride += 0;
|
||||
break;
|
||||
case 65526:
|
||||
stride += 8;
|
||||
break;
|
||||
|
@ -228,57 +305,62 @@ function parse_tagged(raw) {
|
|||
throw `Unsupported field type ${type}`;
|
||||
}
|
||||
}
|
||||
if (!valid_inc(d, "</variable_types>"))
|
||||
throw err;
|
||||
}
|
||||
{
|
||||
if (!valid_inc(d, "<varnames>"))
|
||||
throw err;
|
||||
const res = slice_end(d, "</varnames>");
|
||||
const w = vers >= 118 ? 129 : 33;
|
||||
if (res.raw.length != w * nvar)
|
||||
throw `Expected variable_types length ${nvar * w}, found ${res.raw.length}`;
|
||||
while (res.ptr < res.raw.length) {
|
||||
const name = new TextDecoder().decode(res.raw.slice(res.ptr, res.ptr + w));
|
||||
res.ptr += w;
|
||||
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;
|
||||
const res = slice_end(d, "</sortlist>");
|
||||
if (res.raw.length != 2 * nvar + 2)
|
||||
throw `Expected sortlist length ${nvar * 2 + 2}, found ${res.raw.length}`;
|
||||
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 res = slice_end(d, "</formats>");
|
||||
const w = vers >= 118 ? 57 : 49;
|
||||
if (res.raw.length != w * nvar)
|
||||
throw `Expected formats length ${nvar * w}, found ${res.raw.length}`;
|
||||
while (res.ptr < res.raw.length) {
|
||||
const name = new TextDecoder().decode(res.raw.slice(res.ptr, res.ptr + w));
|
||||
res.ptr += w;
|
||||
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;
|
||||
const res = slice_end(d, "</value_label_names>");
|
||||
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;
|
||||
const res = slice_end(d, "</variable_labels>");
|
||||
d.ptr += w * nvar;
|
||||
if (!valid_inc(d, "</variable_labels>"))
|
||||
throw err;
|
||||
}
|
||||
{
|
||||
if (!valid_inc(d, "<characteristics>"))
|
||||
throw err;
|
||||
while (d.str.slice(d.ptr, d.ptr + 4) == "<ch>") {
|
||||
d.ptr += 4;
|
||||
while (valid_inc(d, "<ch>")) {
|
||||
const len = read_u32(d, LE);
|
||||
d.ptr += len;
|
||||
if (!valid_inc(d, "</ch>"))
|
||||
|
@ -297,26 +379,29 @@ function parse_tagged(raw) {
|
|||
for (let C = 0; C < nvar; ++C) {
|
||||
let t = var_types[C];
|
||||
if (t >= 1 && t <= 2045) {
|
||||
let s = new TextDecoder().decode(d.raw.slice(d.ptr, d.ptr + t));
|
||||
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 65526:
|
||||
row[C] = read_f64(d, LE);
|
||||
case 65525:
|
||||
d.ptr += 0;
|
||||
break;
|
||||
case 65527:
|
||||
row[C] = read_f32(d, LE);
|
||||
break;
|
||||
case 65528:
|
||||
row[C] = read_i32(d, LE);
|
||||
case 65530:
|
||||
row[C] = read_i8(d);
|
||||
break;
|
||||
case 65529:
|
||||
row[C] = read_i16(d, LE);
|
||||
break;
|
||||
case 65530:
|
||||
row[C] = read_i8(d);
|
||||
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:
|
||||
{
|
||||
|
@ -328,6 +413,8 @@ function parse_tagged(raw) {
|
|||
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 });
|
||||
}
|
||||
|
@ -355,15 +442,15 @@ function parse_tagged(raw) {
|
|||
const len = read_u32(d, LE);
|
||||
if (!strl_tbl[o])
|
||||
strl_tbl[o] = [];
|
||||
let str2 = "";
|
||||
let str = "";
|
||||
if (t == 129) {
|
||||
str2 = new TextDecoder("latin1").decode(d.raw.slice(d.ptr, d.ptr + len));
|
||||
str = new TextDecoder(vers >= 118 ? "utf8" : "latin1").decode(d.raw.slice(d.ptr, d.ptr + len));
|
||||
d.ptr += len;
|
||||
} else {
|
||||
str2 = new TextDecoder("latin1").decode(d.raw.slice(d.ptr, d.ptr + len)).replace(/\x00$/, "");
|
||||
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] = str2;
|
||||
strl_tbl[o][v] = str;
|
||||
}
|
||||
if (!valid_inc(d, "</strls>"))
|
||||
throw err;
|
||||
|
@ -397,9 +484,41 @@ function parse_tagged(raw) {
|
|||
});
|
||||
}
|
||||
{
|
||||
const w = vers >= 118 ? 129 : 33;
|
||||
if (!valid_inc(d, "<value_labels>"))
|
||||
throw err;
|
||||
const res = slice_end(d, "</value_labels>");
|
||||
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;
|
||||
|
@ -409,27 +528,11 @@ function parse_tagged(raw) {
|
|||
}
|
||||
function parse_legacy(raw) {
|
||||
let vers = raw[0];
|
||||
switch (vers) {
|
||||
case 102:
|
||||
case 112:
|
||||
throw `Unsupported DTA ${vers} file`;
|
||||
case 103:
|
||||
case 104:
|
||||
case 105:
|
||||
case 108:
|
||||
case 110:
|
||||
case 111:
|
||||
case 113:
|
||||
case 114:
|
||||
case 115:
|
||||
break;
|
||||
default:
|
||||
throw new Error("Not a DTA file");
|
||||
}
|
||||
if (SUPPORTED_VERSIONS_LEGACY.indexOf(vers) == -1)
|
||||
throw new Error("Not a DTA file");
|
||||
const d = {
|
||||
ptr: 1,
|
||||
raw,
|
||||
str: "",
|
||||
dv: u8_to_dataview(raw)
|
||||
};
|
||||
let LE = true;
|
||||
|
@ -456,31 +559,34 @@ function parse_legacy(raw) {
|
|||
d.ptr++;
|
||||
nvar = read_u16(d, LE);
|
||||
nobs = read_u32(d, LE);
|
||||
d.ptr += vers >= 108 ? 81 : 32;
|
||||
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(new TextDecoder().decode(d.raw.slice(d.ptr, d.ptr + w)).replace(/\x00[\s\S]*$/, ""));
|
||||
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(new TextDecoder().decode(d.raw.slice(d.ptr, d.ptr + fw)).replace(/\x00[\s\S]*$/, ""));
|
||||
formats.push(u8_to_str(d.raw.slice(d.ptr, d.ptr + fw)).replace(/\x00[\s\S]*$/, ""));
|
||||
d.ptr += fw;
|
||||
}
|
||||
d.ptr += (vers >= 110 ? 33 : 9) * nvar;
|
||||
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 >= 111 ? read_u32 : read_u16)(d, LE);
|
||||
const dt = read_u8(d), len = (vers >= 110 ? read_u32 : read_u16)(d, LE);
|
||||
if (dt == 0 && len == 0)
|
||||
break;
|
||||
d.ptr += len;
|
||||
|
@ -490,11 +596,16 @@ function parse_legacy(raw) {
|
|||
const row = [];
|
||||
for (let C = 0; C < nvar; ++C) {
|
||||
let t = var_types[C];
|
||||
if (vers >= 111 && t >= 1 && t <= 244) {
|
||||
let s = new TextDecoder().decode(d.raw.slice(d.ptr, d.ptr + t));
|
||||
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:
|
||||
|
@ -520,9 +631,41 @@ function parse_legacy(raw) {
|
|||
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");
|
||||
return wb;
|
||||
|
@ -538,5 +681,6 @@ module.exports = __toCommonJS(dta_exports);
|
|||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
parse,
|
||||
set_utils
|
||||
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
|
@ -1,5 +1,7 @@
|
|||
import { DenseWorkSheet, WorkBook, type utils } from 'xlsx';
|
||||
export { parse, set_utils };
|
||||
import { CellObject, DenseWorkSheet, WorkBook, type utils } from 'xlsx';
|
||||
export { parse, set_utils, version };
|
||||
|
||||
const version = "0.0.1";
|
||||
|
||||
let _utils: typeof utils;
|
||||
/** Set internal instance of `utils`
|
||||
|
@ -18,6 +20,51 @@ 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;
|
||||
|
@ -25,39 +72,17 @@ interface Payload {
|
|||
/** Raw data */
|
||||
raw: Uint8Array;
|
||||
|
||||
/** Latin-1 encoded */
|
||||
str: string;
|
||||
|
||||
/** 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(p.str.slice(p.ptr, p.ptr + n.length) != n) return false;
|
||||
if(u8_to_str(p.raw.slice(p.ptr, p.ptr + n.length)) != n) return false;
|
||||
p.ptr += n.length;
|
||||
return true;
|
||||
}
|
||||
|
||||
function skip_end(p: Payload, n: string): void {
|
||||
const idx = p.str.indexOf(n, p.ptr);
|
||||
if(idx == -1) throw new Error(`Expected ${n} after offset ${p.ptr}`);
|
||||
p.ptr = idx + n.length;
|
||||
}
|
||||
function slice_end(p: Payload, n: string): Payload {
|
||||
const idx = p.str.indexOf(n, p.ptr);
|
||||
if(idx == -1) throw new Error(`Expected ${n} after offset ${p.ptr}`);
|
||||
const raw = p.raw.slice(p.ptr, idx);
|
||||
const res = {
|
||||
ptr: 0,
|
||||
raw,
|
||||
str: p.str.slice(p.ptr, idx),
|
||||
dv: u8_to_dataview(raw)
|
||||
};
|
||||
p.ptr = idx + n.length;
|
||||
return res;
|
||||
}
|
||||
|
||||
function read_f64(p: Payload, LE: boolean): number | null {
|
||||
p.ptr += 8;
|
||||
const d = p.dv.getFloat64(p.ptr - 8, LE);
|
||||
|
@ -96,23 +121,34 @@ function read_i8(p: Payload): number | null {
|
|||
return u > 100 ? null : u;
|
||||
}
|
||||
|
||||
/* the annotations are from `dtaversion` */
|
||||
const SUPPORTED_VERSIONS_TAGGED = [
|
||||
"117", // stata 13
|
||||
"118", // stata 14-18
|
||||
// "119", // stata 15/16/17/18 (> 32767 variables)
|
||||
// "120", // stata 18 (<= 32767, with aliases)
|
||||
// "121", // stata 18 (> 32767, with aliases)
|
||||
"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");
|
||||
/* sadly the web zealots decided to abandon binary strings */
|
||||
const str = new TextDecoder('latin1').decode(raw);
|
||||
|
||||
const d: Payload = {
|
||||
ptr: 0,
|
||||
raw,
|
||||
str,
|
||||
dv: u8_to_dataview(raw)
|
||||
}
|
||||
|
||||
|
@ -134,58 +170,64 @@ function parse_tagged(raw: Uint8Array): WorkBook {
|
|||
/* <release> */
|
||||
{
|
||||
if(!valid_inc(d, "<release>")) throw err;
|
||||
const res = slice_end(d, "</release>");
|
||||
if(SUPPORTED_VERSIONS_TAGGED.indexOf(res.str) == -1) throw (`Unsupported DTA ${res.str} file`);
|
||||
vers = +res.str;
|
||||
/* 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;
|
||||
const res = slice_end(d, "</byteorder>");
|
||||
switch(res.str) {
|
||||
/* 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.str}`);
|
||||
default: throw (`Unsupported byteorder ${res}`);
|
||||
}
|
||||
}
|
||||
|
||||
/* <K> */
|
||||
{
|
||||
if(!valid_inc(d, "<K>")) throw err;
|
||||
const res = slice_end(d, "</K>");
|
||||
nvar = read_u16(res, LE);
|
||||
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;
|
||||
const res = slice_end(d, "</N>");
|
||||
if(vers == 117) nobs = nobs_lo = read_u32(res, LE);
|
||||
if(vers == 117) nobs = nobs_lo = read_u32(d, LE);
|
||||
else {
|
||||
const lo = read_u32(res, LE), hi = read_u32(res, LE);
|
||||
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 res = slice_end(d, "</label>");
|
||||
const w = vers >= 118 ? 2 : 1;
|
||||
const strlen = w == 1 ? read_u8(res) : read_u16(res, LE);
|
||||
if(strlen + w != res.str.length) throw (`Expected string length ${strlen} but actual length was ${res.str.length - w}`);
|
||||
if(strlen > 0) label = new TextDecoder().decode(res.raw.slice(w));
|
||||
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 res = slice_end(d, "</timestamp>");
|
||||
const strlen = read_u8(res);
|
||||
if(strlen + 1 != res.str.length) throw (`Expected string length ${strlen} but actual length was ${res.str.length - 1}`);
|
||||
if(strlen > 0) timestamp = res.str.slice(1);
|
||||
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;
|
||||
|
@ -211,21 +253,21 @@ function parse_tagged(raw: Uint8Array): WorkBook {
|
|||
</stata_data>
|
||||
EOF
|
||||
*/
|
||||
skip_end(d, "</map>");
|
||||
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;
|
||||
const res = slice_end(d, "</variable_types>");
|
||||
if(res.raw.length != 2 * nvar) throw (`Expected variable_types length ${nvar * 2}, found ${res.raw.length}`);
|
||||
while(res.ptr < res.raw.length) {
|
||||
const type = read_u16(res, LE);
|
||||
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;
|
||||
|
@ -234,61 +276,62 @@ function parse_tagged(raw: Uint8Array): WorkBook {
|
|||
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 res = slice_end(d, "</varnames>");
|
||||
const w = vers >= 118 ? 129 : 33;
|
||||
if(res.raw.length != w * nvar) throw (`Expected variable_types length ${nvar * w}, found ${res.raw.length}`);
|
||||
while(res.ptr < res.raw.length) {
|
||||
const name = new TextDecoder().decode(res.raw.slice(res.ptr, res.ptr + w));
|
||||
res.ptr += w;
|
||||
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;
|
||||
const res = slice_end(d, "</sortlist>");
|
||||
if(res.raw.length != 2 * nvar + 2) throw (`Expected sortlist length ${nvar * 2 + 2}, found ${res.raw.length}`);
|
||||
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 res = slice_end(d, "</formats>");
|
||||
const w = vers >= 118 ? 57 : 49;
|
||||
if(res.raw.length != w * nvar) throw (`Expected formats length ${nvar * w}, found ${res.raw.length}`);
|
||||
while(res.ptr < res.raw.length) {
|
||||
const name = new TextDecoder().decode(res.raw.slice(res.ptr, res.ptr + w));
|
||||
res.ptr += w;
|
||||
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;
|
||||
const res = slice_end(d, "</value_label_names>");
|
||||
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;
|
||||
const res = slice_end(d, "</variable_labels>");
|
||||
d.ptr += w * nvar;
|
||||
if(!valid_inc(d, "</variable_labels>")) throw err;
|
||||
}
|
||||
|
||||
/* 5.9 Characteristics <characteristics> */
|
||||
{
|
||||
if(!valid_inc(d, "<characteristics>")) throw err;
|
||||
while(d.str.slice(d.ptr, d.ptr + 4) == "<ch>") {
|
||||
d.ptr += 4;
|
||||
while(valid_inc(d, "<ch>")) {
|
||||
const len = read_u32(d, LE);
|
||||
d.ptr += len;
|
||||
if(!valid_inc(d, "</ch>")) throw err;
|
||||
|
@ -296,7 +339,7 @@ function parse_tagged(raw: Uint8Array): WorkBook {
|
|||
if(!valid_inc(d, "</characteristics>")) throw err;
|
||||
}
|
||||
|
||||
const ws: DenseWorkSheet = (_utils.aoa_to_sheet([var_names], {dense: true}) as DenseWorkSheet);
|
||||
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> */
|
||||
|
@ -309,16 +352,17 @@ function parse_tagged(raw: Uint8Array): WorkBook {
|
|||
// TODO: formats, dta_12{0,1} aliases?
|
||||
if(t >= 1 && t <= 2045) {
|
||||
/* NOTE: dta_117 restricts strf to ASCII */
|
||||
let s = new TextDecoder().decode(d.raw.slice(d.ptr, d.ptr + t));
|
||||
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 65526: row[C] = read_f64(d, LE); break;
|
||||
case 65527: row[C] = read_f32(d, LE); break;
|
||||
case 65528: row[C] = read_i32(d, LE); break;
|
||||
case 65529: row[C] = read_i16(d, LE); break;
|
||||
case 65530: row[C] = read_i8(d); break;
|
||||
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)]);
|
||||
|
@ -326,6 +370,7 @@ function parse_tagged(raw: Uint8Array): WorkBook {
|
|||
} 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});
|
||||
}
|
||||
|
@ -352,11 +397,11 @@ function parse_tagged(raw: Uint8Array): WorkBook {
|
|||
if(!strl_tbl[o]) strl_tbl[o] = [];
|
||||
let str = "";
|
||||
if(t == 129) {
|
||||
// TODO: codepage
|
||||
str = new TextDecoder("latin1").decode(d.raw.slice(d.ptr, d.ptr + len));
|
||||
// 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("latin1").decode(d.raw.slice(d.ptr, d.ptr + len)).replace(/\x00$/,"");
|
||||
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;
|
||||
|
@ -391,12 +436,37 @@ function parse_tagged(raw: Uint8Array): WorkBook {
|
|||
|
||||
/* 5.12 Value labels <value_labels> */
|
||||
{
|
||||
const w = vers >= 118 ? 129 : 33;
|
||||
if(!valid_inc(d, "<value_labels>")) throw err;
|
||||
const res = slice_end(d, "</value_labels>");
|
||||
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");
|
||||
return wb;
|
||||
|
@ -404,29 +474,11 @@ function parse_tagged(raw: Uint8Array): WorkBook {
|
|||
|
||||
function parse_legacy(raw: Uint8Array): WorkBook {
|
||||
let vers: number = raw[0];
|
||||
switch(vers) {
|
||||
case 102: // stata 1
|
||||
case 112: // stata 8/9
|
||||
throw (`Unsupported DTA ${vers} file`);
|
||||
|
||||
case 103: // stata 2/3
|
||||
case 104: // stata 4
|
||||
case 105: // stata 5
|
||||
case 108: // stata 6
|
||||
case 110: // stata 7
|
||||
case 111: // stata 7
|
||||
case 113: // stata 8/9
|
||||
case 114: // stata 10/11
|
||||
case 115: // stata 12
|
||||
break;
|
||||
|
||||
default: throw new Error("Not a DTA file");
|
||||
}
|
||||
if(SUPPORTED_VERSIONS_LEGACY.indexOf(vers) == -1) throw new Error("Not a DTA file");
|
||||
|
||||
const d: Payload = {
|
||||
ptr: 1,
|
||||
raw,
|
||||
str:"",
|
||||
dv: u8_to_dataview(raw)
|
||||
}
|
||||
|
||||
|
@ -453,11 +505,12 @@ function parse_legacy(raw: Uint8Array): WorkBook {
|
|||
d.ptr++; // "unused"
|
||||
nvar = read_u16(d, LE);
|
||||
nobs = read_u32(d, LE);
|
||||
d.ptr += (vers >= 108 ? 81 : 32); // TODO: data_label
|
||||
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;
|
||||
|
||||
|
@ -467,7 +520,7 @@ function parse_legacy(raw: Uint8Array): WorkBook {
|
|||
// varlist
|
||||
const w = vers >= 110 ? 33 : 9;
|
||||
for(C = 0; C < nvar; ++C) {
|
||||
var_names.push(new TextDecoder().decode(d.raw.slice(d.ptr, d.ptr + w)).replace(/\x00[\s\S]*$/,""));
|
||||
var_names.push(u8_to_str(d.raw.slice(d.ptr, d.ptr + w)).replace(/\x00[\s\S]*$/,""));
|
||||
d.ptr += w;
|
||||
}
|
||||
|
||||
|
@ -477,12 +530,12 @@ function parse_legacy(raw: Uint8Array): WorkBook {
|
|||
// fmtlist
|
||||
const fw = (vers >= 114 ? 49 : vers >= 105 ? 12 : 7);
|
||||
for(C = 0; C < nvar; ++C) {
|
||||
formats.push(new TextDecoder().decode(d.raw.slice(d.ptr, d.ptr + fw)).replace(/\x00[\s\S]*$/,""));
|
||||
formats.push(u8_to_str(d.raw.slice(d.ptr, d.ptr + fw)).replace(/\x00[\s\S]*$/,""));
|
||||
d.ptr += fw;
|
||||
}
|
||||
|
||||
// lbllist
|
||||
d.ptr += (vers >= 110 ? 33 : 9) * nvar;
|
||||
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 */
|
||||
|
@ -491,12 +544,12 @@ function parse_legacy(raw: Uint8Array): WorkBook {
|
|||
|
||||
/* 5.4 Expansion fields */
|
||||
if(vers >= 105) while(d.ptr < d.raw.length) {
|
||||
const dt = read_u8(d), len = (vers >= 111 ? read_u32 : read_u16)(d, LE);
|
||||
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 DenseWorkSheet);
|
||||
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) {
|
||||
|
@ -504,12 +557,18 @@ function parse_legacy(raw: Uint8Array): WorkBook {
|
|||
for(let C = 0; C < nvar; ++C) {
|
||||
let t = var_types[C];
|
||||
// TODO: data type processing
|
||||
if(vers >= 111 && t >= 1 && t <= 244) {
|
||||
if((vers == 111 || vers >= 113) && t >= 1 && t <= 244) {
|
||||
/* NOTE: dta_117 restricts strf to ASCII */
|
||||
let s = new TextDecoder().decode(d.raw.slice(d.ptr, d.ptr + t));
|
||||
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
|
||||
|
@ -518,12 +577,38 @@ function parse_legacy(raw: Uint8Array): WorkBook {
|
|||
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 */
|
||||
// EOF or 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");
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
"main": "dist/dta.js",
|
||||
"types": "types",
|
||||
"files": [
|
||||
"dist/"
|
||||
"bin/",
|
||||
"dist/",
|
||||
"types/"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
@ -16,7 +16,7 @@ for(let tF of test_folders) describe(tF, () => {
|
|||
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 = " ";}}));
|
||||
//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());
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import type { WorkBook } from "xlsx";
|
||||
|
||||
import { WorkBook } from 'xlsx';
|
||||
export { parse, set_utils, version };
|
||||
declare const version = "0.0.1";
|
||||
/** Set internal instance of `utils`
|
||||
*
|
||||
* Usage:
|
||||
|
@ -12,12 +13,11 @@ import type { WorkBook } from "xlsx";
|
|||
*
|
||||
* @param utils utils object
|
||||
*/
|
||||
export function set_utils(utils: any): void;
|
||||
|
||||
declare function set_utils(utils: any): void;
|
||||
/** Parse DTA file
|
||||
*
|
||||
* NOTE: In NodeJS, `Buffer` extends `Uint8Array`
|
||||
*
|
||||
* @param {Uint8Array} data File data
|
||||
*/
|
||||
export function parse(data: Uint8Array): WorkBook
|
||||
declare function parse(data: Uint8Array): WorkBook;
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
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);
|
||||
}
|
|
@ -1,17 +1,5 @@
|
|||
function 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 parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
|
||||
if(v > 2958465 || v < 0) return null;
|
||||
v = 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};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
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 */
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
"blanket": "~1.2.3",
|
||||
"dtslint": "^0.1.2",
|
||||
"mocha": "~2.5.3",
|
||||
"typescript": "2.2.0"
|
||||
"typescript": "2.2.0",
|
||||
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.0/xlsx-0.20.0.tgz"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
@ -141,6 +141,26 @@ 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;
|
||||
|
@ -161,20 +181,8 @@ function frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/
|
|||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
}
|
||||
function 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 parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
|
||||
if(v > 2958465 || v < 0) return null;
|
||||
v = 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};
|
||||
|
@ -703,6 +711,7 @@ 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 */
|
||||
|
|
|
@ -137,6 +137,26 @@ 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;
|
||||
|
@ -157,20 +177,8 @@ function frac(x, D, mixed) {
|
|||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
}
|
||||
function normalize_xl_unsafe(v) {
|
||||
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 parse_date_code(v,opts,b2) {
|
||||
if(v > 2958465 || v < 0) return null;
|
||||
v = 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};
|
||||
|
@ -696,6 +704,7 @@ 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 */
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/* vim: set ts=2: */
|
||||
/*jshint loopfunc:true, mocha:true, node:true */
|
||||
/*eslint-env node, mocha */
|
||||
var XLSX = require("xlsx"), SSF = require("../");
|
||||
|
||||
describe('rounding', function() {
|
||||
|
||||
it('number', function() {
|
||||
var wb = XLSX.readFile("./test/rounding.xlsx", {cellNF: true, dense: true});
|
||||
var data = wb.Sheets.number["!data"];
|
||||
data.slice(1).forEach(function(r,R) {
|
||||
var val = data[R+1][0].v;
|
||||
var raw = parseFloat(data[R+1][1].v);
|
||||
r.slice(2).forEach(function(cell, C) {
|
||||
var fmt = data[0][C+2].v;
|
||||
var w = SSF.format(fmt, val);
|
||||
if(w != cell.v) throw ([R, C, val, fmt, cell.v, w].join("|"));
|
||||
var W = SSF.format(fmt, raw);
|
||||
if(W != cell.v) throw ([R, C, val, fmt, cell.v, W, "!!"].join("|"));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('date', function() {
|
||||
var wb = XLSX.readFile("./test/rounding.xlsx", {cellNF: true, dense: true});
|
||||
var data = wb.Sheets.date["!data"];
|
||||
data.slice(1).forEach(function(r,R) {
|
||||
var val = data[R+1][0].v;
|
||||
r.slice(1).forEach(function(cell, C) {
|
||||
var fmt = data[0][C+1].v;
|
||||
if(fmt == 'yyyy-mm-dd [hh]:mm:ss') return; // Format broken in excel 2007 - present
|
||||
var w = SSF.format(fmt, val);
|
||||
if(w != cell.v) throw([R, C, val, fmt, cell.v, w].join("|"));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
Binary file not shown.
|
@ -5,6 +5,6 @@ var fs = require('fs'), assert = require('assert');
|
|||
var is_date = JSON.parse(fs.readFileSync('./test/is_date.json','utf8'));
|
||||
describe('utilities', function() {
|
||||
it('correctly determines if formats are dates', function() {
|
||||
is_date.forEach(function(d) { assert.equal(SSF.is_date(d[0]), d[1], d[0]); });
|
||||
is_date.forEach(function(d) { assert.equal(SSF.is_date(d[0]), d[1], d[0]); });
|
||||
});
|
||||
});
|
||||
|
|
9
test.js
9
test.js
|
@ -2128,6 +2128,15 @@ describe('json output', function() {
|
|||
}
|
||||
});
|
||||
});
|
||||
it('should force UTC in formatted strings', function() {
|
||||
var ws = { "!ref": "A1", "A1": { t: 'd', v: new Date(Date.UTC(2002, 11, 24, 0, 0, 0, 0)) } };
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: true, raw: false, dateNF: 'd"/"m"/"yyyy'})[0][0], "24/12/2002");
|
||||
delete ws.A1.w;
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: false, raw: false, dateNF: 'd"/"m"/"yyyy'})[0][0], "24/12/2002");
|
||||
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: true, raw: true, dateNF: 'd"/"m"/"yyyy'})[0][0].valueOf(), 1040688000000);
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: false, raw: true, dateNF: 'd"/"m"/"yyyy'})[0][0].valueOf(), 1040688000000 + new Date("2002-12-24T00:00:00.000Z").getTimezoneOffset()*60000);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -1406,13 +1406,16 @@ describe('parse features', function() {
|
|||
].forEach(function(m) { it(m[0], function() {
|
||||
var wb = X.read(fs.readFileSync(m[1]), {type: TYPE, cellDates: true});
|
||||
var ws = wb.Sheets[wb.SheetNames[0]];
|
||||
var data = X.utils.sheet_to_json(ws, { header: 1, raw: true, rawNumbers: false });
|
||||
assert.ok(data[0][1] instanceof Date);
|
||||
assert.ok(data[1][1] instanceof Date);
|
||||
assert.equal(data[2][1], '$123.00');
|
||||
assert.equal(data[3][1], '98.76%');
|
||||
assert.equal(data[4][1], '456.00');
|
||||
assert.equal(data[5][1], '7,890');
|
||||
var data1 = X.utils.sheet_to_json(ws, { header: 1, raw: true, rawNumbers: false });
|
||||
var data2 = X.utils.sheet_to_json(ws, { header: 1, raw: false, rawNumbers: true });
|
||||
assert.ok(data1[0][1] instanceof Date);
|
||||
assert.ok(data1[1][1] instanceof Date);
|
||||
assert.equal(data1[2][1], '$123.00');
|
||||
assert.equal(data1[3][1], '98.76%');
|
||||
assert.equal(data1[4][1], '456.00');
|
||||
assert.equal(data1[5][1], '7,890');
|
||||
assert.equal(data2[0][1], '7/23/2020');
|
||||
assert.equal(data2[5][1], 7890);
|
||||
}); }); });
|
||||
|
||||
it('date system', function() {[
|
||||
|
@ -1558,7 +1561,7 @@ describe('write features', function() {
|
|||
["String", "123"],
|
||||
["Number", 123],
|
||||
["Boolean", true],
|
||||
["Date", new Date()],
|
||||
["Date", new Date()]
|
||||
], { cellDates: true });
|
||||
ws["B2"].t = ws["B3"].t = ws["B4"].t = "s"
|
||||
var wb = X.utils.book_new();
|
||||
|
@ -2129,6 +2132,15 @@ describe('json output', function() {
|
|||
}
|
||||
});
|
||||
});
|
||||
it('should force UTC in formatted strings', function() {
|
||||
var ws = { "!ref": "A1", "A1": { t: 'd', v: new Date(Date.UTC(2002, 11, 24, 0, 0, 0, 0)) } };
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: true, raw: false, dateNF: 'd"/"m"/"yyyy'})[0][0], "24/12/2002");
|
||||
delete ws.A1.w;
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: false, raw: false, dateNF: 'd"/"m"/"yyyy'})[0][0], "24/12/2002");
|
||||
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: true, raw: true, dateNF: 'd"/"m"/"yyyy'})[0][0].valueOf(), 1040688000000);
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: false, raw: true, dateNF: 'd"/"m"/"yyyy'})[0][0].valueOf(), 1040688000000 + new Date("2002-12-24T00:00:00.000Z").getTimezoneOffset()*60000);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
@ -2478,7 +2490,7 @@ describe('dbf', function() {
|
|||
var wstrue = wbstrue[1][1].Sheets["Sheet1"];
|
||||
[
|
||||
["E2", "v", Date.UTC(1917,1,19,0,0,0,0)], ["E2", "w", "19170219"],
|
||||
["F2", "v", Date.UTC(1917,1,19,0,0,0,0)], ["F2", "w", "19170219"],
|
||||
["F2", "v", Date.UTC(1917,1,19,0,0,0,0)], ["F2", "w", "19170219"]
|
||||
].forEach(function(r) {
|
||||
assert.equal(get_cell(wstrue, r[0])[r[1]].valueOf(), r[2].valueOf());
|
||||
});
|
||||
|
|
28
test.mts
28
test.mts
|
@ -1367,17 +1367,20 @@ describe('parse features', function() {
|
|||
});
|
||||
|
||||
describe('data types formats', function() {var dtf = [
|
||||
['xlsx', paths.dtfxlsx],
|
||||
['xlsx', paths.dtfxlsx]
|
||||
]; for(var j = 0; j < dtf.length; ++j) { var m = dtf[j]; it(m[0], function() {
|
||||
var wb = X.read(fs.readFileSync(m[1]), {type: TYPE, cellDates: true});
|
||||
var ws = wb.Sheets[wb.SheetNames[0]];
|
||||
var data = X.utils.sheet_to_json<any>(ws, { header: 1, raw: true, rawNumbers: false });
|
||||
assert.ok(data[0][1] instanceof Date);
|
||||
assert.ok(data[1][1] instanceof Date);
|
||||
assert.equal(data[2][1], '$123.00');
|
||||
assert.equal(data[3][1], '98.76%');
|
||||
assert.equal(data[4][1], '456.00');
|
||||
assert.equal(data[5][1], '7,890');
|
||||
var data1 = X.utils.sheet_to_json<any>(ws, { header: 1, raw: true, rawNumbers: false });
|
||||
var data2 = X.utils.sheet_to_json<any>(ws, { header: 1, raw: false, rawNumbers: true });
|
||||
assert.ok(data1[0][1] instanceof Date);
|
||||
assert.ok(data1[1][1] instanceof Date);
|
||||
assert.equal(data1[2][1], '$123.00');
|
||||
assert.equal(data1[3][1], '98.76%');
|
||||
assert.equal(data1[4][1], '456.00');
|
||||
assert.equal(data1[5][1], '7,890');
|
||||
assert.equal(data2[0][1], '7/23/2020');
|
||||
assert.equal(data2[5][1], 7890);
|
||||
}); } });
|
||||
|
||||
it('date system', function() {[
|
||||
|
@ -2085,6 +2088,15 @@ describe('json output', function() {
|
|||
}
|
||||
});
|
||||
});
|
||||
it('should force UTC in formatted strings', function() {
|
||||
var ws: X.WorkSheet = { "!ref": "A1", "A1": { t: 'd', v: new Date(Date.UTC(2002, 11, 24, 0, 0, 0, 0)) } };
|
||||
assert.equal(X.utils.sheet_to_json<string[]>(ws, {header: 1, UTC: true, raw: false, dateNF: 'd"/"m"/"yyyy'})[0][0], "24/12/2002");
|
||||
delete ws.A1.w;
|
||||
assert.equal(X.utils.sheet_to_json<string[]>(ws, {header: 1, UTC: false, raw: false, dateNF: 'd"/"m"/"yyyy'})[0][0], "24/12/2002");
|
||||
|
||||
assert.equal(X.utils.sheet_to_json<number[]>(ws, {header: 1, UTC: true, raw: true, dateNF: 'd"/"m"/"yyyy'})[0][0].valueOf(), 1040688000000);
|
||||
assert.equal(X.utils.sheet_to_json<number[]>(ws, {header: 1, UTC: false, raw: true, dateNF: 'd"/"m"/"yyyy'})[0][0].valueOf(), 1040688000000 + new Date("2002-12-24T00:00:00.000Z").getTimezoneOffset()*60000);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
#!/bin/bash
|
||||
set -euxo pipefail
|
||||
TZONES=(America/New_York Europe/London Asia/Seoul America/Los_Angeles Europe/Berlin Asia/Kolkata Asia/Shanghai America/Cancun America/Anchorage America/Barbados Asia/Tokyo America/Cayman Pacific/Honolulu America/Mexico_City Asia/Hong_Kong Europe/Paris Atlantic/Azores)
|
||||
|
||||
if [ -e datetest.js ]; then
|
||||
sudo n 20;
|
||||
for TZ in ${TZONES[@]}; do
|
||||
echo "$TZ"
|
||||
env TZ="$TZ" mocha -R dot datetest.js
|
||||
done
|
||||
fi
|
||||
|
||||
# min test
|
||||
for n in 20 10 0.8 0.10 0.12 4 6 8 12 14 16 18; do
|
||||
sudo n $n
|
||||
env WTF=1 make testdot_misc
|
||||
for TZ in ${TZONES[@]}; do
|
||||
sudo n $n
|
||||
env WTF=1 TZ="$TZ" make testdot_misc
|
||||
done
|
||||
done
|
||||
|
||||
# full test
|
||||
for n in 20 10 0.12; do
|
||||
for TZ in America/New_York Asia/Seoul Asia/Kolkata Europe/Paris; do
|
||||
sudo n $n
|
||||
env WTF=1 TZ="$TZ" make testdot
|
||||
done
|
||||
done
|
||||
|
||||
# bun
|
||||
for TZ in ${TZONES[@]}; do
|
||||
echo "$TZ";
|
||||
env TZ="$TZ" WTF=1 make test-bun_misc;
|
||||
done
|
||||
|
||||
# deno
|
||||
for TZ in ${TZONES[@]}; do
|
||||
echo "$TZ";
|
||||
env TZ="$TZ" WTF=1 make test-deno_misc;
|
||||
env TZ="$TZ" WTF=1 make test-denocp_misc;
|
||||
done
|
||||
|
||||
|
28
test.ts
28
test.ts
|
@ -1367,17 +1367,20 @@ Deno.test('parse features', async function(t) {
|
|||
});
|
||||
|
||||
await t.step('data types formats', async function(t) {var dtf = [
|
||||
['xlsx', paths.dtfxlsx],
|
||||
['xlsx', paths.dtfxlsx]
|
||||
]; for(var j = 0; j < dtf.length; ++j) { var m = dtf[j]; await t.step(m[0], async function(t) {
|
||||
var wb = X.read(fs.readFileSync(m[1]), {type: TYPE, cellDates: true});
|
||||
var ws = wb.Sheets[wb.SheetNames[0]];
|
||||
var data = X.utils.sheet_to_json<any>(ws, { header: 1, raw: true, rawNumbers: false });
|
||||
assert.assert(data[0][1] instanceof Date);
|
||||
assert.assert(data[1][1] instanceof Date);
|
||||
assert.equal(data[2][1], '$123.00');
|
||||
assert.equal(data[3][1], '98.76%');
|
||||
assert.equal(data[4][1], '456.00');
|
||||
assert.equal(data[5][1], '7,890');
|
||||
var data1 = X.utils.sheet_to_json<any>(ws, { header: 1, raw: true, rawNumbers: false });
|
||||
var data2 = X.utils.sheet_to_json<any>(ws, { header: 1, raw: false, rawNumbers: true });
|
||||
assert.assert(data1[0][1] instanceof Date);
|
||||
assert.assert(data1[1][1] instanceof Date);
|
||||
assert.equal(data1[2][1], '$123.00');
|
||||
assert.equal(data1[3][1], '98.76%');
|
||||
assert.equal(data1[4][1], '456.00');
|
||||
assert.equal(data1[5][1], '7,890');
|
||||
assert.equal(data2[0][1], '7/23/2020');
|
||||
assert.equal(data2[5][1], 7890);
|
||||
}); } });
|
||||
|
||||
await t.step('date system', async function(t) {[
|
||||
|
@ -2085,6 +2088,15 @@ Deno.test('json output', async function(t) {
|
|||
}
|
||||
});
|
||||
});
|
||||
await t.step('should force UTC in formatted strings', async function(t) {
|
||||
var ws: X.WorkSheet = { "!ref": "A1", "A1": { t: 'd', v: new Date(Date.UTC(2002, 11, 24, 0, 0, 0, 0)) } };
|
||||
assert.equal(X.utils.sheet_to_json<string[]>(ws, {header: 1, UTC: true, raw: false, dateNF: 'd"/"m"/"yyyy'})[0][0], "24/12/2002");
|
||||
delete ws.A1.w;
|
||||
assert.equal(X.utils.sheet_to_json<string[]>(ws, {header: 1, UTC: false, raw: false, dateNF: 'd"/"m"/"yyyy'})[0][0], "24/12/2002");
|
||||
|
||||
assert.equal(X.utils.sheet_to_json<number[]>(ws, {header: 1, UTC: true, raw: true, dateNF: 'd"/"m"/"yyyy'})[0][0].valueOf(), 1040688000000);
|
||||
assert.equal(X.utils.sheet_to_json<number[]>(ws, {header: 1, UTC: false, raw: true, dateNF: 'd"/"m"/"yyyy'})[0][0].valueOf(), 1040688000000 + new Date("2002-12-24T00:00:00.000Z").getTimezoneOffset()*60000);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -65,6 +65,8 @@ if(!browser) {
|
|||
for(var _fileAi = 0; _fileAi < _fileA.length; ++_fileAi) if(test_file(_fileA[_fileAi])) fileA.push(_fileA[_fileAi]);
|
||||
}
|
||||
|
||||
var can_write_numbers = typeof Set !== "undefined" && typeof Array.prototype.findIndex == "function" && typeof Uint8Array !== "undefined" && typeof Uint8Array.prototype.indexOf == "function";
|
||||
|
||||
/* Excel enforces 31 character sheet limit, although technical file limit is 255 */
|
||||
function fixsheetname(x/*:string*/)/*:string*/ { return x.substr(0,31); }
|
||||
|
||||
|
@ -581,7 +583,7 @@ describe('parse options', function() {
|
|||
it('sheetRows n=10', function() { FSTPaths.forEach(function(p) {
|
||||
checkcells(X.read(fs.readFileSync(p), {type:TYPE, sheetRows:10}), false, false, false, true);
|
||||
}); });
|
||||
if(false) it('sheetRows n=1', function() { ofmt.forEach(function(fmt) {
|
||||
it('sheetRows n=1', function() { ofmt.forEach(function(fmt) {
|
||||
[TYPE, "buffer", "buffer", "array"].forEach(function(ot) {
|
||||
var data = [[1,2],[3,4],[5,6]];
|
||||
var ws = X.utils.aoa_to_sheet(data);
|
||||
|
@ -676,7 +678,7 @@ describe('parse options', function() {
|
|||
it('should not generate VBA by default', function() { NFPaths.forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE}); assert.ok(typeof wb.vbaraw === 'undefined');
|
||||
}); });
|
||||
if(false) it('bookVBA should generate vbaraw', function() { NFVBA.forEach(function(p) {
|
||||
it('bookVBA should generate vbaraw', function() { NFVBA.forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p),{type: TYPE, bookVBA: true});
|
||||
assert.ok(wb.vbaraw);
|
||||
var cfb = X.CFB.read(wb.vbaraw, {type: 'array'});
|
||||
|
@ -714,7 +716,7 @@ describe('input formats', function() {
|
|||
((browser || typeof Buffer === 'undefined') ? it.skip : it)('should read Buffers', function() { artifax.forEach(function(p) {
|
||||
X.read(fs.readFileSync(p), {type: 'buffer'});
|
||||
}); });
|
||||
if(false) if(typeof Uint8Array !== 'undefined') it('should read ArrayBuffer / Uint8Array', function() { artifax.forEach(function(p) {
|
||||
if(typeof Uint8Array !== 'undefined') it('should read ArrayBuffer / Uint8Array', function() { artifax.forEach(function(p) {
|
||||
var payload = fs.readFileSync(p, browser ? 'buffer' : null);
|
||||
var ab = new ArrayBuffer(payload.length), vu = new Uint8Array(ab);
|
||||
for(var i = 0; i < payload.length; ++i) vu[i] = payload[i];
|
||||
|
@ -726,13 +728,13 @@ describe('input formats', function() {
|
|||
}); });
|
||||
|
||||
var T = browser ? 'base64' : 'buffer';
|
||||
if(false) it('should default to "' + T + '" type', function() { artifax.forEach(function(p) {
|
||||
it('should default to "' + T + '" type', function() { artifax.forEach(function(p) {
|
||||
X.read(fs.readFileSync.apply(fs, browser ? [p, 'base64'] : [p]));
|
||||
}); });
|
||||
if(!browser) it('should read files', function() { artifax.forEach(function(p) { X.readFile(p); }); });
|
||||
});
|
||||
|
||||
if(false) describe('output formats', function() {
|
||||
describe('output formats', function() {
|
||||
var fmts = [
|
||||
/* fmt unicode str */
|
||||
["xlsx", true, false],
|
||||
|
@ -962,7 +964,7 @@ describe('parse features', function() {
|
|||
}); });
|
||||
});
|
||||
|
||||
if(false) describe('should parse core properties and custom properties', function() {
|
||||
describe('should parse core properties and custom properties', function() {
|
||||
var wbs=[];
|
||||
var bef = (function() {
|
||||
wbs = [
|
||||
|
@ -1031,7 +1033,7 @@ describe('parse features', function() {
|
|||
});
|
||||
});
|
||||
|
||||
if(false) describe('column properties', function() {
|
||||
describe('column properties', function() {
|
||||
var wbs = [], wbs_no_slk = [];
|
||||
var bef = (function() {
|
||||
wbs = CWPaths.map(function(n) { return X.read(fs.readFileSync(n), {type:TYPE, cellStyles:true}); });
|
||||
|
@ -1072,7 +1074,7 @@ describe('parse features', function() {
|
|||
});
|
||||
});
|
||||
|
||||
if(false) describe('row properties', function() {
|
||||
describe('row properties', function() {
|
||||
var wbs = [], ols = [];
|
||||
var ol = fs.existsSync(paths.olxls);
|
||||
var bef = (function() {
|
||||
|
@ -1145,15 +1147,15 @@ describe('parse features', function() {
|
|||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
|
||||
['xlsx', 'xlsb', /* 'xls', 'xml'*/].forEach(function(x, i) {
|
||||
['xlsx', 'xlsb', 'xls', 'xml'].forEach(function(x, i) {
|
||||
it(x + " external", function() { hlink1(wb1[i].Sheets["Sheet1"]); });
|
||||
});
|
||||
['xlsx', 'xlsb', /* 'xls', 'xml', 'ods'*/].forEach(function(x, i) {
|
||||
['xlsx', 'xlsb', 'xls', 'xml', 'ods'].forEach(function(x, i) {
|
||||
it(x + " internal", function() { hlink2(wb2[i].Sheets["Sheet1"]); });
|
||||
});
|
||||
});
|
||||
|
||||
if(false) describe('should parse cells with date type (XLSX/XLSM)', function() {
|
||||
describe('should parse cells with date type (XLSX/XLSM)', function() {
|
||||
it('Must have read the date', function() {
|
||||
var wb, ws;
|
||||
var sheetName = 'Sheet1';
|
||||
|
@ -1220,7 +1222,7 @@ describe('parse features', function() {
|
|||
assert.equal(names[i].Ref, "Sheet1!$A$2");
|
||||
}); }); });
|
||||
|
||||
if(false) describe('defined names unicode', function() {[
|
||||
describe('defined names unicode', function() {[
|
||||
/* desc path RT */
|
||||
['xlsx', paths.dnuxlsx, true],
|
||||
['xlsb', paths.dnuxlsb, true],
|
||||
|
@ -1254,7 +1256,7 @@ describe('parse features', function() {
|
|||
}); });
|
||||
}); }); });
|
||||
|
||||
if(false) describe('workbook codename unicode', function() {
|
||||
describe('workbook codename unicode', function() {
|
||||
var ws, wb;
|
||||
var bef = (function() {
|
||||
wb = X.utils.book_new();
|
||||
|
@ -1307,7 +1309,7 @@ describe('parse features', function() {
|
|||
}); });
|
||||
});
|
||||
|
||||
if(false) describe('page margins', function() {
|
||||
describe('page margins', function() {
|
||||
var wbs=[];
|
||||
var bef = (function() {
|
||||
if(!fs.existsSync(paths.pmxls)) return;
|
||||
|
@ -1407,20 +1409,23 @@ describe('parse features', function() {
|
|||
});
|
||||
|
||||
describe('data types formats', function() {[
|
||||
['xlsx', paths.dtfxlsx],
|
||||
['xlsx', paths.dtfxlsx]
|
||||
].forEach(function(m) { it(m[0], function() {
|
||||
var wb = X.read(fs.readFileSync(m[1]), {type: TYPE, cellDates: true});
|
||||
var ws = wb.Sheets[wb.SheetNames[0]];
|
||||
var data = X.utils.sheet_to_json(ws, { header: 1, raw: true, rawNumbers: false });
|
||||
assert.ok(data[0][1] instanceof Date);
|
||||
assert.ok(data[1][1] instanceof Date);
|
||||
assert.equal(data[2][1], '$123.00');
|
||||
assert.equal(data[3][1], '98.76%');
|
||||
assert.equal(data[4][1], '456.00');
|
||||
assert.equal(data[5][1], '7,890');
|
||||
var data1 = X.utils.sheet_to_json(ws, { header: 1, raw: true, rawNumbers: false });
|
||||
var data2 = X.utils.sheet_to_json(ws, { header: 1, raw: false, rawNumbers: true });
|
||||
assert.ok(data1[0][1] instanceof Date);
|
||||
assert.ok(data1[1][1] instanceof Date);
|
||||
assert.equal(data1[2][1], '$123.00');
|
||||
assert.equal(data1[3][1], '98.76%');
|
||||
assert.equal(data1[4][1], '456.00');
|
||||
assert.equal(data1[5][1], '7,890');
|
||||
assert.equal(data2[0][1], '7/23/2020');
|
||||
assert.equal(data2[5][1], 7890);
|
||||
}); }); });
|
||||
|
||||
if(false) it('date system', function() {[
|
||||
it('date system', function() {[
|
||||
"biff5", "ods", "slk", "xls", "xlsb", "xlsx", "xml"
|
||||
].forEach(function(ext) {
|
||||
// TODO: verify actual date values
|
||||
|
@ -1445,18 +1450,18 @@ describe('parse features', function() {
|
|||
].join("\n"));
|
||||
}); });
|
||||
|
||||
if(false) it('bookType metadata', function() {
|
||||
it('bookType metadata', function() {
|
||||
[
|
||||
// TODO: keep in sync with BookType, support other formats
|
||||
"xlsx"/*, "xlsm" */, "xlsb"/* xls / xla / biff# */, "xlml", "ods", "fods"/*, "csv", "txt", */, "sylk", "html", "dif", "rtf"/*, "prn", "eth"*/, "dbf", "numbers"
|
||||
].forEach(function(r) {
|
||||
if(r == "numbers" && !can_write_numbers) return;
|
||||
var ws = X.utils.aoa_to_sheet([ ["a", "b", "c"], [1, 2, 3] ]);
|
||||
var wb = X.utils.book_new(); X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
var data = X.write(wb, {type: TYPE, bookType: r, WTF: true, numbers:XLSX_ZAHL });
|
||||
assert.equal(X.read(data, {type: TYPE, WTF: true}).bookType, r);
|
||||
}); });
|
||||
});
|
||||
console.log(`${fails} FAILED ${passes} PASSED`); process.exit(fails > 0);
|
||||
|
||||
describe('write features', function() {
|
||||
describe('props', function() {
|
||||
|
@ -1563,7 +1568,7 @@ describe('write features', function() {
|
|||
["String", "123"],
|
||||
["Number", 123],
|
||||
["Boolean", true],
|
||||
["Date", new Date()],
|
||||
["Date", new Date()]
|
||||
], { cellDates: true });
|
||||
ws["B2"].t = ws["B3"].t = ws["B4"].t = "s"
|
||||
var wb = X.utils.book_new();
|
||||
|
@ -1608,7 +1613,7 @@ function parseDate(str/*:string*/, date1904/*:boolean*/)/*:Date*/ {
|
|||
|
||||
var fixdate = browser ? parseDate("2014-02-19T14:30:00.000Z") : new Date("2014-02-19T14:30Z");
|
||||
|
||||
describe('roundtrip features', function() {
|
||||
if(false) describe('roundtrip features', function() {
|
||||
describe('should preserve core properties', function() { [
|
||||
['xls', paths.cpxls],
|
||||
['xlml', paths.cpxml],
|
||||
|
@ -1639,6 +1644,7 @@ describe('roundtrip features', function() {
|
|||
|
||||
describe('should preserve merge cells', function() {
|
||||
["xlsx", "xlsb", "xlml", "ods", "biff8", "numbers"].forEach(function(f) { it(f, function() {
|
||||
if(f == "numbers" && !can_write_numbers) return;
|
||||
var wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE});
|
||||
var wb2 = X.read(X.write(wb1,{bookType:f,type:'binary',numbers:XLSX_ZAHL}),{type:'binary'});
|
||||
var m1 = wb1.Sheets["Merge"]['!merges'].map(X.utils.encode_range);
|
||||
|
@ -1882,7 +1888,7 @@ var password_files = [
|
|||
"password_2002_40_xor.xls"
|
||||
];
|
||||
describe('invalid files', function() {
|
||||
describe('parse', function() { [
|
||||
if(false) describe('parse', function() { [
|
||||
['KEY files', 'numbers/Untitled.key'],
|
||||
['PAGES files', 'numbers/Untitled.pages'],
|
||||
['password', 'apachepoi_password.xls'],
|
||||
|
@ -2133,6 +2139,15 @@ describe('json output', function() {
|
|||
}
|
||||
});
|
||||
});
|
||||
it('should force UTC in formatted strings', function() {
|
||||
var ws = { "!ref": "A1", "A1": { t: 'd', v: new Date(Date.UTC(2002, 11, 24, 0, 0, 0, 0)) } };
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: true, raw: false, dateNF: 'd"/"m"/"yyyy'})[0][0], "24/12/2002");
|
||||
delete ws.A1.w;
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: false, raw: false, dateNF: 'd"/"m"/"yyyy'})[0][0], "24/12/2002");
|
||||
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: true, raw: true, dateNF: 'd"/"m"/"yyyy'})[0][0].valueOf(), 1040688000000);
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: false, raw: true, dateNF: 'd"/"m"/"yyyy'})[0][0].valueOf(), 1040688000000 + new Date("2002-12-24T00:00:00.000Z").getTimezoneOffset()*60000);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
@ -2172,6 +2187,9 @@ var html_bstr = make_html_str(1), html_str = make_html_str(0);
|
|||
var csv_bstr = make_csv_str(1), csv_str = make_csv_str(0);
|
||||
|
||||
|
||||
// WTF=1 make test-bun_misc in bun 1.0.15 reached this point
|
||||
console.log(`${fails} FAILED ${passes} PASSED`); process.exit(+!!(fails > 0));
|
||||
|
||||
describe('CSV', function() {
|
||||
describe('input', function(){
|
||||
var b = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\n,,,\nbaz,,qux,\n";
|
||||
|
@ -2297,6 +2315,23 @@ describe('CSV', function() {
|
|||
B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal(B1.v * 24, 3);
|
||||
B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal(B3.v * 24, 15);
|
||||
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]);
|
||||
assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]);
|
||||
}
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
B1 = get_cell(ws, "B1"); assert.equal(B1.t, "d"); assert.equal(B1.v.getUTCHours(), 3);
|
||||
B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getUTCHours(), 15);
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]);
|
||||
assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]);
|
||||
}
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal(B1.v * 24, 3);
|
||||
B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal(B3.v * 24, 15);
|
||||
|
||||
});
|
||||
});
|
||||
describe('output', function(){
|
||||
|
@ -2424,7 +2459,7 @@ describe('numbers', function() {
|
|||
assert.equal(get_cell(ws, "B11").v, true);
|
||||
assert.equal(get_cell(ws, "B13").v, 50);
|
||||
});
|
||||
it('should cap cols at 1000 (ALL)', function() {
|
||||
if(can_write_numbers) it('should cap cols at 1000 (ALL)', function() {
|
||||
var aoa = [[1], [], []]; aoa[1][999] = 2; aoa[2][1000] = 3;
|
||||
var ws1 = X.utils.aoa_to_sheet(aoa);
|
||||
var wb1 = X.utils.book_new(); X.utils.book_append_sheet(wb1, ws1, "Sheet1");
|
||||
|
|
28
testnocp.ts
28
testnocp.ts
|
@ -1366,17 +1366,20 @@ Deno.test('parse features', async function(t) {
|
|||
});
|
||||
|
||||
await t.step('data types formats', async function(t) {var dtf = [
|
||||
['xlsx', paths.dtfxlsx],
|
||||
['xlsx', paths.dtfxlsx]
|
||||
]; for(var j = 0; j < dtf.length; ++j) { var m = dtf[j]; await t.step(m[0], async function(t) {
|
||||
var wb = X.read(fs.readFileSync(m[1]), {type: TYPE, cellDates: true});
|
||||
var ws = wb.Sheets[wb.SheetNames[0]];
|
||||
var data = X.utils.sheet_to_json<any>(ws, { header: 1, raw: true, rawNumbers: false });
|
||||
assert.assert(data[0][1] instanceof Date);
|
||||
assert.assert(data[1][1] instanceof Date);
|
||||
assert.equal(data[2][1], '$123.00');
|
||||
assert.equal(data[3][1], '98.76%');
|
||||
assert.equal(data[4][1], '456.00');
|
||||
assert.equal(data[5][1], '7,890');
|
||||
var data1 = X.utils.sheet_to_json<any>(ws, { header: 1, raw: true, rawNumbers: false });
|
||||
var data2 = X.utils.sheet_to_json<any>(ws, { header: 1, raw: false, rawNumbers: true });
|
||||
assert.assert(data1[0][1] instanceof Date);
|
||||
assert.assert(data1[1][1] instanceof Date);
|
||||
assert.equal(data1[2][1], '$123.00');
|
||||
assert.equal(data1[3][1], '98.76%');
|
||||
assert.equal(data1[4][1], '456.00');
|
||||
assert.equal(data1[5][1], '7,890');
|
||||
assert.equal(data2[0][1], '7/23/2020');
|
||||
assert.equal(data2[5][1], 7890);
|
||||
}); } });
|
||||
|
||||
await t.step('date system', async function(t) {[
|
||||
|
@ -2084,6 +2087,15 @@ Deno.test('json output', async function(t) {
|
|||
}
|
||||
});
|
||||
});
|
||||
await t.step('should force UTC in formatted strings', async function(t) {
|
||||
var ws: X.WorkSheet = { "!ref": "A1", "A1": { t: 'd', v: new Date(Date.UTC(2002, 11, 24, 0, 0, 0, 0)) } };
|
||||
assert.equal(X.utils.sheet_to_json<string[]>(ws, {header: 1, UTC: true, raw: false, dateNF: 'd"/"m"/"yyyy'})[0][0], "24/12/2002");
|
||||
delete ws.A1.w;
|
||||
assert.equal(X.utils.sheet_to_json<string[]>(ws, {header: 1, UTC: false, raw: false, dateNF: 'd"/"m"/"yyyy'})[0][0], "24/12/2002");
|
||||
|
||||
assert.equal(X.utils.sheet_to_json<number[]>(ws, {header: 1, UTC: true, raw: true, dateNF: 'd"/"m"/"yyyy'})[0][0].valueOf(), 1040688000000);
|
||||
assert.equal(X.utils.sheet_to_json<number[]>(ws, {header: 1, UTC: false, raw: true, dateNF: 'd"/"m"/"yyyy'})[0][0].valueOf(), 1040688000000 + new Date("2002-12-24T00:00:00.000Z").getTimezoneOffset()*60000);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -1402,13 +1402,16 @@ describe('parse features', function() {
|
|||
].forEach(function(m) { it(m[0], function() {
|
||||
var wb = X.read(fs.readFileSync(m[1]), {type: TYPE, cellDates: true});
|
||||
var ws = wb.Sheets[wb.SheetNames[0]];
|
||||
var data = X.utils.sheet_to_json(ws, { header: 1, raw: true, rawNumbers: false });
|
||||
assert.ok(data[0][1] instanceof Date);
|
||||
assert.ok(data[1][1] instanceof Date);
|
||||
assert.equal(data[2][1], '$123.00');
|
||||
assert.equal(data[3][1], '98.76%');
|
||||
assert.equal(data[4][1], '456.00');
|
||||
assert.equal(data[5][1], '7,890');
|
||||
var data1 = X.utils.sheet_to_json(ws, { header: 1, raw: true, rawNumbers: false });
|
||||
var data2 = X.utils.sheet_to_json(ws, { header: 1, raw: false, rawNumbers: true });
|
||||
assert.ok(data1[0][1] instanceof Date);
|
||||
assert.ok(data1[1][1] instanceof Date);
|
||||
assert.equal(data1[2][1], '$123.00');
|
||||
assert.equal(data1[3][1], '98.76%');
|
||||
assert.equal(data1[4][1], '456.00');
|
||||
assert.equal(data1[5][1], '7,890');
|
||||
assert.equal(data2[0][1], '7/23/2020');
|
||||
assert.equal(data2[5][1], 7890);
|
||||
}); }); });
|
||||
|
||||
it('date system', function() {[
|
||||
|
@ -2125,6 +2128,15 @@ describe('json output', function() {
|
|||
}
|
||||
});
|
||||
});
|
||||
it('should force UTC in formatted strings', function() {
|
||||
var ws = { "!ref": "A1", "A1": { t: 'd', v: new Date(Date.UTC(2002, 11, 24, 0, 0, 0, 0)) } };
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: true, raw: false, dateNF: 'd"/"m"/"yyyy'})[0][0], "24/12/2002");
|
||||
delete ws.A1.w;
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: false, raw: false, dateNF: 'd"/"m"/"yyyy'})[0][0], "24/12/2002");
|
||||
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: true, raw: true, dateNF: 'd"/"m"/"yyyy'})[0][0].valueOf(), 1040688000000);
|
||||
assert.equal(X.utils.sheet_to_json(ws, {header: 1, UTC: false, raw: true, dateNF: 'd"/"m"/"yyyy'})[0][0].valueOf(), 1040688000000 + new Date("2002-12-24T00:00:00.000Z").getTimezoneOffset()*60000);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
|
162
xlsx.flow.js
162
xlsx.flow.js
|
@ -4,7 +4,7 @@
|
|||
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false, Float32Array:false */
|
||||
var XLSX = {};
|
||||
function make_xlsx_lib(XLSX){
|
||||
XLSX.version = '0.20.0';
|
||||
XLSX.version = '0.20.1';
|
||||
var current_codepage = 1200, current_ansi = 1252;
|
||||
/*:: declare var cptable:any; */
|
||||
/*global cptable:true, window */
|
||||
|
@ -484,8 +484,20 @@ 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};
|
||||
|
@ -639,7 +651,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+Math.round(val.S+val.u); 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;
|
||||
default: throw 'bad abstime format: ' + fmt;
|
||||
} outl = fmt.length === 3 ? 1 : 2; break;
|
||||
case 101: /* 'e' era */
|
||||
|
@ -1087,10 +1099,11 @@ 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);
|
||||
if((ssm=out[i].v.match(/\.0+$/))) { ss0=Math.max(ss0,ssm[0].length-1); bt = 4;}
|
||||
if(bt < 3) bt = 3;
|
||||
/* falls through */
|
||||
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
|
||||
case 'd': case 'y': case 'e': lst=out[i].t; break;
|
||||
case 'M': lst=out[i].t; if(bt < 2) bt = 2; break;
|
||||
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
|
||||
case 'X': /*if(out[i].v === "B2");*/
|
||||
break;
|
||||
|
@ -1100,19 +1113,29 @@ 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:
|
||||
/*::if(!dt) break;*/
|
||||
case 2:
|
||||
case 3:
|
||||
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 2:
|
||||
/*::if(!dt) break;*/
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
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; }
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -4431,6 +4454,13 @@ 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;
|
||||
|
@ -7992,7 +8022,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 '?': break;
|
||||
case '': case '\x00': case '?': break;
|
||||
default: throw new Error("DBF Unrecognized L:|" + s + "|");
|
||||
} break;
|
||||
case 'M': /* TODO: handle memo files */
|
||||
|
@ -8054,6 +8084,7 @@ 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);
|
||||
|
@ -8211,7 +8242,10 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
"!":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") + "|\\|)", "gm");
|
||||
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_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;
|
||||
|
@ -8434,7 +8468,7 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
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']), cell/*:Cell*/;
|
||||
var r = safe_decode_range(ws['!ref']||"A1"), cell/*:Cell*/;
|
||||
var dense = ws["!data"] != null;
|
||||
var RS = "\r\n";
|
||||
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
|
@ -8443,7 +8477,7 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
preamble.push("P;PGeneral");
|
||||
/* Excel has been inconsistent in comment placement */
|
||||
var R = r.s.r, C = r.s.c, p = [];
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
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) {
|
||||
|
@ -8453,7 +8487,7 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
}
|
||||
if(p.length) o.push(p.join(RS));
|
||||
}
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
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) {
|
||||
|
@ -8473,7 +8507,7 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
|
||||
if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
|
||||
|
||||
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(" "));
|
||||
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("O;L;D;B" + (d1904 ? ";V4" : "") + ";K47;G100 0.001");
|
||||
|
||||
delete opts._formats;
|
||||
|
@ -8546,6 +8580,7 @@ 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>*/ = [
|
||||
|
@ -8883,6 +8918,7 @@ 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) {
|
||||
|
@ -9107,6 +9143,7 @@ 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 = [];
|
||||
|
@ -9900,13 +9937,25 @@ var WK_ = /*#__PURE__*/(function() {
|
|||
/*::[*/0x0E/*::*/: "dd-mmm-yyyy",
|
||||
/*::[*/0x0F/*::*/: "mmm-yyyy",
|
||||
|
||||
/*::[*/0x22/*::*/: "0.00",
|
||||
/*::[*/0x32/*::*/: "0.00;[Red]0.00",
|
||||
/*::[*/0x42/*::*/: "0.00;\(0.00\)",
|
||||
/*::[*/0x52/*::*/: "0.00;[Red]\(0.00\)",
|
||||
|
||||
/*::[*/162/*::*/: '"$"#,##0;\\("$"#,##0\\)' // slightly different from SSF 5
|
||||
/* 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);
|
||||
|
@ -10017,7 +10066,11 @@ var WK_ = /*#__PURE__*/(function() {
|
|||
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; 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;
|
||||
default: throw "Unrecognized QPW cell type " + (flags & 0x1F);
|
||||
}
|
||||
if(fmtidx != -1 && (FMTS[fmtidx - 1]||{}).z) cell.z = FMTS[fmtidx-1].z;
|
||||
|
@ -10063,6 +10116,17 @@ 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;
|
||||
|
@ -11215,7 +11279,7 @@ function parse_cellXfs(t, styles, opts) {
|
|||
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]])
|
||||
|
@ -11229,7 +11293,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;
|
||||
|
@ -11241,12 +11305,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': pass = true; break;
|
||||
case '<AlternateContent': case '<AlternateContent>': pass = true; break;
|
||||
case '</AlternateContent>': pass = false; break;
|
||||
|
||||
/* 18.2.10 extLst CT_ExtensionList ? */
|
||||
|
@ -12887,7 +12951,10 @@ 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])([$]?)(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 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 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) {
|
||||
|
@ -15601,7 +15668,7 @@ 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 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*)"/;
|
||||
|
@ -22460,9 +22527,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']);
|
||||
var r = decode_range(ws['!ref'] || "A1");
|
||||
out.push(make_html_preamble(ws, r, o));
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
|
||||
if(ws["!ref"]) 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("");
|
||||
}
|
||||
|
@ -23221,10 +23288,13 @@ 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:
|
||||
|
@ -23741,6 +23811,7 @@ 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})];
|
||||
|
@ -24992,7 +25063,7 @@ function s5s_to_iwa_comment(s5s) {
|
|||
return out;
|
||||
}
|
||||
function parse_TST_TableModelArchive(M, root, ws, opts) {
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
||||
var pb = parse_shallow(root.data);
|
||||
var range = { s: { r: 0, c: 0 }, e: { r: 0, c: 0 } };
|
||||
range.e.r = (varint_to_i32(pb[6][0].data) >>> 0) - 1;
|
||||
|
@ -25021,7 +25092,17 @@ function parse_TST_TableModelArchive(M, root, ws, opts) {
|
|||
lut.nfmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[22][0].data)][0]);
|
||||
var tile = parse_shallow(store[3][0].data);
|
||||
var _R = 0;
|
||||
tile[1].forEach(function(t) {
|
||||
if (!((_h = store[9]) == null ? void 0 : _h[0]))
|
||||
throw "NUMBERS file missing row tree";
|
||||
var rtt = parse_shallow(store[9][0].data)[1].map(function(p) {
|
||||
return parse_shallow(p.data);
|
||||
});
|
||||
rtt.forEach(function(kv) {
|
||||
_R = varint_to_i32(kv[1][0].data);
|
||||
var tidx = varint_to_i32(kv[2][0].data);
|
||||
var t = tile[1][tidx];
|
||||
if (!t)
|
||||
throw "NUMBERS missing tile " + tidx;
|
||||
var tl = parse_shallow(t.data);
|
||||
var ref2 = M[parse_TSP_Reference(tl[2][0].data)][0];
|
||||
var mtype2 = varint_to_i32(ref2.meta[1][0].data);
|
||||
|
@ -25044,12 +25125,12 @@ function parse_TST_TableModelArchive(M, root, ws, opts) {
|
|||
});
|
||||
_R += _tile.nrows;
|
||||
});
|
||||
if ((_h = store[13]) == null ? void 0 : _h[0]) {
|
||||
if ((_i = store[13]) == null ? void 0 : _i[0]) {
|
||||
var ref = M[parse_TSP_Reference(store[13][0].data)][0];
|
||||
var mtype = varint_to_i32(ref.meta[1][0].data);
|
||||
if (mtype != 6144)
|
||||
throw new Error("Expected merge type 6144, found ".concat(mtype));
|
||||
ws["!merges"] = (_i = parse_shallow(ref.data)) == null ? void 0 : _i[1].map(function(pi) {
|
||||
ws["!merges"] = (_j = parse_shallow(ref.data)) == null ? void 0 : _j[1].map(function(pi) {
|
||||
var merge = parse_shallow(pi.data);
|
||||
var origin = u8_to_dataview(parse_shallow(merge[1][0].data)[1][0].data), size = u8_to_dataview(parse_shallow(merge[2][0].data)[1][0].data);
|
||||
return {
|
||||
|
@ -25711,6 +25792,8 @@ function write_numbers_ws(cfb, deps, ws, wsname, sheetidx, rootref) {
|
|||
}
|
||||
var USE_WIDE_ROWS = true;
|
||||
function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) {
|
||||
if (!ws["!ref"])
|
||||
throw new Error("Cannot export empty sheet to NUMBERS");
|
||||
var range = decode_range(ws["!ref"]);
|
||||
range.s.r = range.s.c = 0;
|
||||
var trunc = false;
|
||||
|
@ -27156,7 +27239,7 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
|
|||
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)) v = utc_to_local(v); break;
|
||||
case 'd': if(!(o && (o.UTC||(o.raw === false)))) v = utc_to_local(new Date(v)); break;
|
||||
default: throw new Error('unrecognized type ' + val.t);
|
||||
}
|
||||
if(hdr[C] != null) {
|
||||
|
@ -27166,7 +27249,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]] = raw && (val.t !== "n" || (val.t === "n" && o.rawNumbers !== false)) ? v : format_cell(val,v,o);
|
||||
row[hdr[C]] = (val.t === 'n' && typeof o.rawNumbers === 'boolean' ? o.rawNumbers : raw) ? v : format_cell(val, v, o);
|
||||
}
|
||||
if(v != null) isempty = false;
|
||||
}
|
||||
|
@ -27424,9 +27507,11 @@ function wb_sheet_idx(wb/*:Workbook*/, sh/*:number|string*/) {
|
|||
} else throw new Error("Cannot find sheet |" + sh + "|");
|
||||
}
|
||||
|
||||
/* simple blank workbook object */
|
||||
function book_new()/*:Workbook*/ {
|
||||
return { SheetNames: [], Sheets: {} };
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* add a worksheet to the end of a given workbook */
|
||||
|
@ -27523,6 +27608,7 @@ 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,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false, Float32Array:false */
|
||||
var XLSX = {};
|
||||
function make_xlsx_lib(XLSX){
|
||||
XLSX.version = '0.20.0';
|
||||
XLSX.version = '0.20.1';
|
||||
var current_codepage = 1200, current_ansi = 1252;
|
||||
/*global cptable:true, window */
|
||||
var $cptable;
|
||||
|
@ -464,8 +464,20 @@ function SSF_frac(x, D, mixed) {
|
|||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
}
|
||||
function SSF_normalize_xl_unsafe(v) {
|
||||
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,opts,b2) {
|
||||
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};
|
||||
|
@ -618,7 +630,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+Math.round(val.S+val.u); 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;
|
||||
default: throw 'bad abstime format: ' + fmt;
|
||||
} outl = fmt.length === 3 ? 1 : 2; break;
|
||||
case 101: /* 'e' era */
|
||||
|
@ -1064,10 +1076,11 @@ 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);
|
||||
if((ssm=out[i].v.match(/\.0+$/))) { ss0=Math.max(ss0,ssm[0].length-1); bt = 4;}
|
||||
if(bt < 3) bt = 3;
|
||||
/* falls through */
|
||||
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
|
||||
case 'd': case 'y': case 'e': lst=out[i].t; break;
|
||||
case 'M': lst=out[i].t; if(bt < 2) bt = 2; break;
|
||||
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
|
||||
case 'X': /*if(out[i].v === "B2");*/
|
||||
break;
|
||||
|
@ -1077,17 +1090,29 @@ 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:
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
case 2:
|
||||
case 3:
|
||||
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 2:
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
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; }
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -4347,6 +4372,13 @@ function sheet_to_workbook(sheet, opts) {
|
|||
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, data, opts) {
|
||||
var o = opts || {};
|
||||
var dense = _ws ? (_ws["!data"] != null) : o.dense;
|
||||
|
@ -7903,7 +7935,7 @@ var fields = [], field = ({});
|
|||
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 '?': break;
|
||||
case '': case '\x00': case '?': break;
|
||||
default: throw new Error("DBF Unrecognized L:|" + s + "|");
|
||||
} break;
|
||||
case 'M': /* TODO: handle memo files */
|
||||
|
@ -7965,6 +7997,7 @@ function dbf_to_workbook(buf, opts) {
|
|||
|
||||
var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 };
|
||||
function sheet_to_dbf(ws, opts) {
|
||||
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);
|
||||
|
@ -8122,7 +8155,10 @@ var SYLK = (function() {
|
|||
"!":161, '"':162, "#":163, "(":164, "%":165, "'":167, "H ":168,
|
||||
"+":171, ";":187, "<":188, "=":189, ">":190, "?":191, "{":223
|
||||
});
|
||||
var sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1") + "|\\|)", "gm");
|
||||
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_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;
|
||||
|
@ -8345,7 +8381,7 @@ var SYLK = (function() {
|
|||
if(!opts) opts = {}; opts._formats = ["General"];
|
||||
/* TODO: codepage */
|
||||
var preamble = ["ID;PSheetJS;N;E"], o = [];
|
||||
var r = safe_decode_range(ws['!ref']), cell;
|
||||
var r = safe_decode_range(ws['!ref']||"A1"), cell;
|
||||
var dense = ws["!data"] != null;
|
||||
var RS = "\r\n";
|
||||
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
|
@ -8354,7 +8390,7 @@ var SYLK = (function() {
|
|||
preamble.push("P;PGeneral");
|
||||
/* Excel has been inconsistent in comment placement */
|
||||
var R = r.s.r, C = r.s.c, p = [];
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
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) {
|
||||
|
@ -8364,7 +8400,7 @@ var SYLK = (function() {
|
|||
}
|
||||
if(p.length) o.push(p.join(RS));
|
||||
}
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
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) {
|
||||
|
@ -8384,7 +8420,7 @@ var SYLK = (function() {
|
|||
if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
|
||||
if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
|
||||
|
||||
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(" "));
|
||||
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("O;L;D;B" + (d1904 ? ";V4" : "") + ";K47;G100 0.001");
|
||||
|
||||
delete opts._formats;
|
||||
|
@ -8457,6 +8493,7 @@ var DIF = (function() {
|
|||
function make_value_str(s) { return "1,0\r\n\"" + s.replace(/"/g,'""') + '"'; }
|
||||
function sheet_to_dif(ws) {
|
||||
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 = [
|
||||
|
@ -8794,6 +8831,7 @@ var PRN = (function() {
|
|||
|
||||
function sheet_to_prn(ws) {
|
||||
var o = [];
|
||||
if(!ws["!ref"]) return "";
|
||||
var r = safe_decode_range(ws['!ref']), cell;
|
||||
var dense = ws["!data"] != null;
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
|
@ -9018,6 +9056,7 @@ var WK_ = (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 = [];
|
||||
|
@ -9811,13 +9850,25 @@ var WK_ = (function() {
|
|||
0x0E: "dd-mmm-yyyy",
|
||||
0x0F: "mmm-yyyy",
|
||||
|
||||
0x22: "0.00",
|
||||
0x32: "0.00;[Red]0.00",
|
||||
0x42: "0.00;\(0.00\)",
|
||||
0x52: "0.00;[Red]\(0.00\)",
|
||||
|
||||
162: '"$"#,##0;\\("$"#,##0\\)' // slightly different from SSF 5
|
||||
/* 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) {
|
||||
prep_blob(d, 0);
|
||||
|
@ -9928,7 +9979,11 @@ var WK_ = (function() {
|
|||
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; 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;
|
||||
default: throw "Unrecognized QPW cell type " + (flags & 0x1F);
|
||||
}
|
||||
if(fmtidx != -1 && (FMTS[fmtidx - 1]||{}).z) cell.z = FMTS[fmtidx-1].z;
|
||||
|
@ -9974,6 +10029,17 @@ var WK_ = (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;
|
||||
|
@ -11125,7 +11191,7 @@ function parse_cellXfs(t, styles, opts) {
|
|||
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]])
|
||||
|
@ -11139,7 +11205,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;
|
||||
|
@ -11151,12 +11217,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': pass = true; break;
|
||||
case '<AlternateContent': case '<AlternateContent>': pass = true; break;
|
||||
case '</AlternateContent>': pass = false; break;
|
||||
|
||||
/* 18.2.10 extLst CT_ExtensionList ? */
|
||||
|
@ -12795,7 +12861,10 @@ var rc_to_a1 = (function(){
|
|||
};
|
||||
})();
|
||||
|
||||
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 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 a1_to_rc = (function(){
|
||||
return function a1_to_rc(fstr, base) {
|
||||
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
|
||||
|
@ -15508,7 +15577,7 @@ function parse_ws_xml_dim(ws, s) {
|
|||
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 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*)"/;
|
||||
|
@ -22351,9 +22420,9 @@ function sheet_to_html(ws, opts/*, wb:?Workbook*/) {
|
|||
var header = o.header != null ? o.header : HTML_BEGIN;
|
||||
var footer = o.footer != null ? o.footer : HTML_END;
|
||||
var out = [header];
|
||||
var r = decode_range(ws['!ref']);
|
||||
var r = decode_range(ws['!ref'] || "A1");
|
||||
out.push(make_html_preamble(ws, r, o));
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
|
||||
if(ws["!ref"]) 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("");
|
||||
}
|
||||
|
@ -23112,10 +23181,13 @@ function parse_content_xml(d, _opts, _nfm) {
|
|||
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:
|
||||
|
@ -23632,6 +23704,7 @@ var write_content_ods = /* @__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})];
|
||||
|
@ -24883,7 +24956,7 @@ function s5s_to_iwa_comment(s5s) {
|
|||
return out;
|
||||
}
|
||||
function parse_TST_TableModelArchive(M, root, ws, opts) {
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
||||
var pb = parse_shallow(root.data);
|
||||
var range = { s: { r: 0, c: 0 }, e: { r: 0, c: 0 } };
|
||||
range.e.r = (varint_to_i32(pb[6][0].data) >>> 0) - 1;
|
||||
|
@ -24912,7 +24985,17 @@ function parse_TST_TableModelArchive(M, root, ws, opts) {
|
|||
lut.nfmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[22][0].data)][0]);
|
||||
var tile = parse_shallow(store[3][0].data);
|
||||
var _R = 0;
|
||||
tile[1].forEach(function(t) {
|
||||
if (!((_h = store[9]) == null ? void 0 : _h[0]))
|
||||
throw "NUMBERS file missing row tree";
|
||||
var rtt = parse_shallow(store[9][0].data)[1].map(function(p) {
|
||||
return parse_shallow(p.data);
|
||||
});
|
||||
rtt.forEach(function(kv) {
|
||||
_R = varint_to_i32(kv[1][0].data);
|
||||
var tidx = varint_to_i32(kv[2][0].data);
|
||||
var t = tile[1][tidx];
|
||||
if (!t)
|
||||
throw "NUMBERS missing tile " + tidx;
|
||||
var tl = parse_shallow(t.data);
|
||||
var ref2 = M[parse_TSP_Reference(tl[2][0].data)][0];
|
||||
var mtype2 = varint_to_i32(ref2.meta[1][0].data);
|
||||
|
@ -24935,12 +25018,12 @@ function parse_TST_TableModelArchive(M, root, ws, opts) {
|
|||
});
|
||||
_R += _tile.nrows;
|
||||
});
|
||||
if ((_h = store[13]) == null ? void 0 : _h[0]) {
|
||||
if ((_i = store[13]) == null ? void 0 : _i[0]) {
|
||||
var ref = M[parse_TSP_Reference(store[13][0].data)][0];
|
||||
var mtype = varint_to_i32(ref.meta[1][0].data);
|
||||
if (mtype != 6144)
|
||||
throw new Error("Expected merge type 6144, found ".concat(mtype));
|
||||
ws["!merges"] = (_i = parse_shallow(ref.data)) == null ? void 0 : _i[1].map(function(pi) {
|
||||
ws["!merges"] = (_j = parse_shallow(ref.data)) == null ? void 0 : _j[1].map(function(pi) {
|
||||
var merge = parse_shallow(pi.data);
|
||||
var origin = u8_to_dataview(parse_shallow(merge[1][0].data)[1][0].data), size = u8_to_dataview(parse_shallow(merge[2][0].data)[1][0].data);
|
||||
return {
|
||||
|
@ -25602,6 +25685,8 @@ function write_numbers_ws(cfb, deps, ws, wsname, sheetidx, rootref) {
|
|||
}
|
||||
var USE_WIDE_ROWS = true;
|
||||
function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) {
|
||||
if (!ws["!ref"])
|
||||
throw new Error("Cannot export empty sheet to NUMBERS");
|
||||
var range = decode_range(ws["!ref"]);
|
||||
range.s.r = range.s.c = 0;
|
||||
var trunc = false;
|
||||
|
@ -27036,7 +27121,7 @@ function make_json_row(sheet, r, R, cols, header, hdr, o) {
|
|||
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)) v = utc_to_local(v); break;
|
||||
case 'd': if(!(o && (o.UTC||(o.raw === false)))) v = utc_to_local(new Date(v)); break;
|
||||
default: throw new Error('unrecognized type ' + val.t);
|
||||
}
|
||||
if(hdr[C] != null) {
|
||||
|
@ -27046,7 +27131,7 @@ function make_json_row(sheet, r, R, cols, header, hdr, o) {
|
|||
else if(raw && v === null) row[hdr[C]] = null;
|
||||
else continue;
|
||||
} else {
|
||||
row[hdr[C]] = raw && (val.t !== "n" || (val.t === "n" && o.rawNumbers !== false)) ? v : format_cell(val,v,o);
|
||||
row[hdr[C]] = (val.t === 'n' && typeof o.rawNumbers === 'boolean' ? o.rawNumbers : raw) ? v : format_cell(val, v, o);
|
||||
}
|
||||
if(v != null) isempty = false;
|
||||
}
|
||||
|
@ -27304,9 +27389,11 @@ function wb_sheet_idx(wb, sh) {
|
|||
} else throw new Error("Cannot find sheet |" + sh + "|");
|
||||
}
|
||||
|
||||
/* simple blank workbook object */
|
||||
function book_new() {
|
||||
return { SheetNames: [], Sheets: {} };
|
||||
/* simple blank or single-sheet workbook object */
|
||||
function book_new(ws, wsname) {
|
||||
var wb = { SheetNames: [], Sheets: {} };
|
||||
if(ws) book_append_sheet(wb, ws, wsname || "Sheet1");
|
||||
return wb;
|
||||
}
|
||||
|
||||
/* add a worksheet to the end of a given workbook */
|
||||
|
@ -27403,6 +27490,7 @@ var utils = {
|
|||
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,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false, Float32Array:false */
|
||||
var XLSX = {};
|
||||
function make_xlsx_lib(XLSX){
|
||||
XLSX.version = '0.20.0';
|
||||
XLSX.version = '0.20.1';
|
||||
var current_codepage = 1200, current_ansi = 1252;
|
||||
/*:: declare var cptable:any; */
|
||||
/*global cptable:true, window */
|
||||
|
@ -484,8 +484,20 @@ 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};
|
||||
|
@ -639,7 +651,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+Math.round(val.S+val.u); 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;
|
||||
default: throw 'bad abstime format: ' + fmt;
|
||||
} outl = fmt.length === 3 ? 1 : 2; break;
|
||||
case 101: /* 'e' era */
|
||||
|
@ -1087,10 +1099,11 @@ 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);
|
||||
if((ssm=out[i].v.match(/\.0+$/))) { ss0=Math.max(ss0,ssm[0].length-1); bt = 4;}
|
||||
if(bt < 3) bt = 3;
|
||||
/* falls through */
|
||||
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
|
||||
case 'd': case 'y': case 'e': lst=out[i].t; break;
|
||||
case 'M': lst=out[i].t; if(bt < 2) bt = 2; break;
|
||||
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
|
||||
case 'X': /*if(out[i].v === "B2");*/
|
||||
break;
|
||||
|
@ -1100,19 +1113,29 @@ 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:
|
||||
/*::if(!dt) break;*/
|
||||
case 2:
|
||||
case 3:
|
||||
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 2:
|
||||
/*::if(!dt) break;*/
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
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; }
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -4427,6 +4450,13 @@ 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;
|
||||
|
@ -5759,7 +5789,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 '?': break;
|
||||
case '': case '\x00': case '?': break;
|
||||
default: throw new Error("DBF Unrecognized L:|" + s + "|");
|
||||
} break;
|
||||
case 'M': /* TODO: handle memo files */
|
||||
|
@ -5821,6 +5851,7 @@ 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);
|
||||
|
@ -5978,7 +6009,10 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
"!":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") + "|\\|)", "gm");
|
||||
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_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;
|
||||
|
@ -6201,7 +6235,7 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
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']), cell/*:Cell*/;
|
||||
var r = safe_decode_range(ws['!ref']||"A1"), cell/*:Cell*/;
|
||||
var dense = ws["!data"] != null;
|
||||
var RS = "\r\n";
|
||||
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
|
@ -6210,7 +6244,7 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
preamble.push("P;PGeneral");
|
||||
/* Excel has been inconsistent in comment placement */
|
||||
var R = r.s.r, C = r.s.c, p = [];
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
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) {
|
||||
|
@ -6220,7 +6254,7 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
}
|
||||
if(p.length) o.push(p.join(RS));
|
||||
}
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
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) {
|
||||
|
@ -6240,7 +6274,7 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
|
||||
if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
|
||||
|
||||
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(" "));
|
||||
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("O;L;D;B" + (d1904 ? ";V4" : "") + ";K47;G100 0.001");
|
||||
|
||||
delete opts._formats;
|
||||
|
@ -6313,6 +6347,7 @@ 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>*/ = [
|
||||
|
@ -6650,6 +6685,7 @@ 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) {
|
||||
|
@ -7360,7 +7396,7 @@ function parse_cellXfs(t, styles, opts) {
|
|||
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]])
|
||||
|
@ -7374,7 +7410,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;
|
||||
|
@ -7386,12 +7422,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': pass = true; break;
|
||||
case '<AlternateContent': case '<AlternateContent>': pass = true; break;
|
||||
case '</AlternateContent>': pass = false; break;
|
||||
|
||||
/* 18.2.10 extLst CT_ExtensionList ? */
|
||||
|
@ -8281,7 +8317,10 @@ 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])([$]?)(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 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 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) {
|
||||
|
@ -8484,7 +8523,7 @@ 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 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*)"/;
|
||||
|
@ -9828,9 +9867,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']);
|
||||
var r = decode_range(ws['!ref'] || "A1");
|
||||
out.push(make_html_preamble(ws, r, o));
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
|
||||
if(ws["!ref"]) 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("");
|
||||
}
|
||||
|
@ -10589,10 +10628,13 @@ 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:
|
||||
|
@ -11109,6 +11151,7 @@ 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})];
|
||||
|
@ -12272,7 +12315,7 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
|
|||
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)) v = utc_to_local(v); break;
|
||||
case 'd': if(!(o && (o.UTC||(o.raw === false)))) v = utc_to_local(new Date(v)); break;
|
||||
default: throw new Error('unrecognized type ' + val.t);
|
||||
}
|
||||
if(hdr[C] != null) {
|
||||
|
@ -12282,7 +12325,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]] = raw && (val.t !== "n" || (val.t === "n" && o.rawNumbers !== false)) ? v : format_cell(val,v,o);
|
||||
row[hdr[C]] = (val.t === 'n' && typeof o.rawNumbers === 'boolean' ? o.rawNumbers : raw) ? v : format_cell(val, v, o);
|
||||
}
|
||||
if(v != null) isempty = false;
|
||||
}
|
||||
|
@ -12540,9 +12583,11 @@ function wb_sheet_idx(wb/*:Workbook*/, sh/*:number|string*/) {
|
|||
} else throw new Error("Cannot find sheet |" + sh + "|");
|
||||
}
|
||||
|
||||
/* simple blank workbook object */
|
||||
function book_new()/*:Workbook*/ {
|
||||
return { SheetNames: [], Sheets: {} };
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* add a worksheet to the end of a given workbook */
|
||||
|
@ -12639,6 +12684,7 @@ 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,
|
||||
|
|
100
xlsx.mini.js
100
xlsx.mini.js
|
@ -4,7 +4,7 @@
|
|||
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false, Float32Array:false */
|
||||
var XLSX = {};
|
||||
function make_xlsx_lib(XLSX){
|
||||
XLSX.version = '0.20.0';
|
||||
XLSX.version = '0.20.1';
|
||||
var current_codepage = 1200, current_ansi = 1252;
|
||||
/*global cptable:true, window */
|
||||
var $cptable;
|
||||
|
@ -464,8 +464,20 @@ function SSF_frac(x, D, mixed) {
|
|||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
}
|
||||
function SSF_normalize_xl_unsafe(v) {
|
||||
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,opts,b2) {
|
||||
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};
|
||||
|
@ -618,7 +630,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+Math.round(val.S+val.u); 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;
|
||||
default: throw 'bad abstime format: ' + fmt;
|
||||
} outl = fmt.length === 3 ? 1 : 2; break;
|
||||
case 101: /* 'e' era */
|
||||
|
@ -1064,10 +1076,11 @@ 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);
|
||||
if((ssm=out[i].v.match(/\.0+$/))) { ss0=Math.max(ss0,ssm[0].length-1); bt = 4;}
|
||||
if(bt < 3) bt = 3;
|
||||
/* falls through */
|
||||
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
|
||||
case 'd': case 'y': case 'e': lst=out[i].t; break;
|
||||
case 'M': lst=out[i].t; if(bt < 2) bt = 2; break;
|
||||
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
|
||||
case 'X': /*if(out[i].v === "B2");*/
|
||||
break;
|
||||
|
@ -1077,17 +1090,29 @@ 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:
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
case 2:
|
||||
case 3:
|
||||
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 2:
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
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; }
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -4343,6 +4368,13 @@ function sheet_to_workbook(sheet, opts) {
|
|||
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, data, opts) {
|
||||
var o = opts || {};
|
||||
var dense = _ws ? (_ws["!data"] != null) : o.dense;
|
||||
|
@ -5674,7 +5706,7 @@ var fields = [], field = ({});
|
|||
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 '?': break;
|
||||
case '': case '\x00': case '?': break;
|
||||
default: throw new Error("DBF Unrecognized L:|" + s + "|");
|
||||
} break;
|
||||
case 'M': /* TODO: handle memo files */
|
||||
|
@ -5736,6 +5768,7 @@ function dbf_to_workbook(buf, opts) {
|
|||
|
||||
var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 };
|
||||
function sheet_to_dbf(ws, opts) {
|
||||
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);
|
||||
|
@ -5893,7 +5926,10 @@ var SYLK = (function() {
|
|||
"!":161, '"':162, "#":163, "(":164, "%":165, "'":167, "H ":168,
|
||||
"+":171, ";":187, "<":188, "=":189, ">":190, "?":191, "{":223
|
||||
});
|
||||
var sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1") + "|\\|)", "gm");
|
||||
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_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;
|
||||
|
@ -6116,7 +6152,7 @@ var SYLK = (function() {
|
|||
if(!opts) opts = {}; opts._formats = ["General"];
|
||||
/* TODO: codepage */
|
||||
var preamble = ["ID;PSheetJS;N;E"], o = [];
|
||||
var r = safe_decode_range(ws['!ref']), cell;
|
||||
var r = safe_decode_range(ws['!ref']||"A1"), cell;
|
||||
var dense = ws["!data"] != null;
|
||||
var RS = "\r\n";
|
||||
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
|
@ -6125,7 +6161,7 @@ var SYLK = (function() {
|
|||
preamble.push("P;PGeneral");
|
||||
/* Excel has been inconsistent in comment placement */
|
||||
var R = r.s.r, C = r.s.c, p = [];
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
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) {
|
||||
|
@ -6135,7 +6171,7 @@ var SYLK = (function() {
|
|||
}
|
||||
if(p.length) o.push(p.join(RS));
|
||||
}
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
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) {
|
||||
|
@ -6155,7 +6191,7 @@ var SYLK = (function() {
|
|||
if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
|
||||
if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
|
||||
|
||||
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(" "));
|
||||
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("O;L;D;B" + (d1904 ? ";V4" : "") + ";K47;G100 0.001");
|
||||
|
||||
delete opts._formats;
|
||||
|
@ -6228,6 +6264,7 @@ var DIF = (function() {
|
|||
function make_value_str(s) { return "1,0\r\n\"" + s.replace(/"/g,'""') + '"'; }
|
||||
function sheet_to_dif(ws) {
|
||||
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 = [
|
||||
|
@ -6565,6 +6602,7 @@ var PRN = (function() {
|
|||
|
||||
function sheet_to_prn(ws) {
|
||||
var o = [];
|
||||
if(!ws["!ref"]) return "";
|
||||
var r = safe_decode_range(ws['!ref']), cell;
|
||||
var dense = ws["!data"] != null;
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
|
@ -7275,7 +7313,7 @@ function parse_cellXfs(t, styles, opts) {
|
|||
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]])
|
||||
|
@ -7289,7 +7327,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;
|
||||
|
@ -7301,12 +7339,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': pass = true; break;
|
||||
case '<AlternateContent': case '<AlternateContent>': pass = true; break;
|
||||
case '</AlternateContent>': pass = false; break;
|
||||
|
||||
/* 18.2.10 extLst CT_ExtensionList ? */
|
||||
|
@ -8196,7 +8234,10 @@ var rc_to_a1 = (function(){
|
|||
};
|
||||
})();
|
||||
|
||||
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 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 a1_to_rc = (function(){
|
||||
return function a1_to_rc(fstr, base) {
|
||||
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
|
||||
|
@ -8399,7 +8440,7 @@ function parse_ws_xml_dim(ws, s) {
|
|||
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 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*)"/;
|
||||
|
@ -9741,9 +9782,9 @@ function sheet_to_html(ws, opts/*, wb:?Workbook*/) {
|
|||
var header = o.header != null ? o.header : HTML_BEGIN;
|
||||
var footer = o.footer != null ? o.footer : HTML_END;
|
||||
var out = [header];
|
||||
var r = decode_range(ws['!ref']);
|
||||
var r = decode_range(ws['!ref'] || "A1");
|
||||
out.push(make_html_preamble(ws, r, o));
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
|
||||
if(ws["!ref"]) 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("");
|
||||
}
|
||||
|
@ -10502,10 +10543,13 @@ function parse_content_xml(d, _opts, _nfm) {
|
|||
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:
|
||||
|
@ -11022,6 +11066,7 @@ var write_content_ods = /* @__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})];
|
||||
|
@ -12174,7 +12219,7 @@ function make_json_row(sheet, r, R, cols, header, hdr, o) {
|
|||
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)) v = utc_to_local(v); break;
|
||||
case 'd': if(!(o && (o.UTC||(o.raw === false)))) v = utc_to_local(new Date(v)); break;
|
||||
default: throw new Error('unrecognized type ' + val.t);
|
||||
}
|
||||
if(hdr[C] != null) {
|
||||
|
@ -12184,7 +12229,7 @@ function make_json_row(sheet, r, R, cols, header, hdr, o) {
|
|||
else if(raw && v === null) row[hdr[C]] = null;
|
||||
else continue;
|
||||
} else {
|
||||
row[hdr[C]] = raw && (val.t !== "n" || (val.t === "n" && o.rawNumbers !== false)) ? v : format_cell(val,v,o);
|
||||
row[hdr[C]] = (val.t === 'n' && typeof o.rawNumbers === 'boolean' ? o.rawNumbers : raw) ? v : format_cell(val, v, o);
|
||||
}
|
||||
if(v != null) isempty = false;
|
||||
}
|
||||
|
@ -12442,9 +12487,11 @@ function wb_sheet_idx(wb, sh) {
|
|||
} else throw new Error("Cannot find sheet |" + sh + "|");
|
||||
}
|
||||
|
||||
/* simple blank workbook object */
|
||||
function book_new() {
|
||||
return { SheetNames: [], Sheets: {} };
|
||||
/* simple blank or single-sheet workbook object */
|
||||
function book_new(ws, wsname) {
|
||||
var wb = { SheetNames: [], Sheets: {} };
|
||||
if(ws) book_append_sheet(wb, ws, wsname || "Sheet1");
|
||||
return wb;
|
||||
}
|
||||
|
||||
/* add a worksheet to the end of a given workbook */
|
||||
|
@ -12541,6 +12588,7 @@ var utils = {
|
|||
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,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*exported XLSX */
|
||||
/*global process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */
|
||||
var XLSX = {};
|
||||
XLSX.version = '0.20.0';
|
||||
XLSX.version = '0.20.1';
|
||||
var current_codepage = 1200, current_ansi = 1252;
|
||||
/*:: declare var cptable:any; */
|
||||
/*global cptable:true, window */
|
||||
|
@ -483,8 +483,20 @@ 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};
|
||||
|
@ -638,7 +650,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+Math.round(val.S+val.u); 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;
|
||||
default: throw 'bad abstime format: ' + fmt;
|
||||
} outl = fmt.length === 3 ? 1 : 2; break;
|
||||
case 101: /* 'e' era */
|
||||
|
@ -1086,10 +1098,11 @@ 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);
|
||||
if((ssm=out[i].v.match(/\.0+$/))) { ss0=Math.max(ss0,ssm[0].length-1); bt = 4;}
|
||||
if(bt < 3) bt = 3;
|
||||
/* falls through */
|
||||
case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
|
||||
case 'd': case 'y': case 'e': lst=out[i].t; break;
|
||||
case 'M': lst=out[i].t; if(bt < 2) bt = 2; break;
|
||||
case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
|
||||
case 'X': /*if(out[i].v === "B2");*/
|
||||
break;
|
||||
|
@ -1099,19 +1112,29 @@ 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:
|
||||
/*::if(!dt) break;*/
|
||||
case 2:
|
||||
case 3:
|
||||
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 2:
|
||||
/*::if(!dt) break;*/
|
||||
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
|
||||
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; }
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -4426,6 +4449,13 @@ 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;
|
||||
|
@ -7987,7 +8017,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 '?': break;
|
||||
case '': case '\x00': case '?': break;
|
||||
default: throw new Error("DBF Unrecognized L:|" + s + "|");
|
||||
} break;
|
||||
case 'M': /* TODO: handle memo files */
|
||||
|
@ -8049,6 +8079,7 @@ 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);
|
||||
|
@ -8206,7 +8237,10 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
"!":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") + "|\\|)", "gm");
|
||||
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_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;
|
||||
|
@ -8429,7 +8463,7 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
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']), cell/*:Cell*/;
|
||||
var r = safe_decode_range(ws['!ref']||"A1"), cell/*:Cell*/;
|
||||
var dense = ws["!data"] != null;
|
||||
var RS = "\r\n";
|
||||
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
|
@ -8438,7 +8472,7 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
preamble.push("P;PGeneral");
|
||||
/* Excel has been inconsistent in comment placement */
|
||||
var R = r.s.r, C = r.s.c, p = [];
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
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) {
|
||||
|
@ -8448,7 +8482,7 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
}
|
||||
if(p.length) o.push(p.join(RS));
|
||||
}
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
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) {
|
||||
|
@ -8468,7 +8502,7 @@ var SYLK = /*#__PURE__*/(function() {
|
|||
if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
|
||||
if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
|
||||
|
||||
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(" "));
|
||||
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("O;L;D;B" + (d1904 ? ";V4" : "") + ";K47;G100 0.001");
|
||||
|
||||
delete opts._formats;
|
||||
|
@ -8541,6 +8575,7 @@ 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>*/ = [
|
||||
|
@ -8878,6 +8913,7 @@ 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) {
|
||||
|
@ -9102,6 +9138,7 @@ 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 = [];
|
||||
|
@ -9895,13 +9932,25 @@ var WK_ = /*#__PURE__*/(function() {
|
|||
/*::[*/0x0E/*::*/: "dd-mmm-yyyy",
|
||||
/*::[*/0x0F/*::*/: "mmm-yyyy",
|
||||
|
||||
/*::[*/0x22/*::*/: "0.00",
|
||||
/*::[*/0x32/*::*/: "0.00;[Red]0.00",
|
||||
/*::[*/0x42/*::*/: "0.00;\(0.00\)",
|
||||
/*::[*/0x52/*::*/: "0.00;[Red]\(0.00\)",
|
||||
|
||||
/*::[*/162/*::*/: '"$"#,##0;\\("$"#,##0\\)' // slightly different from SSF 5
|
||||
/* 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);
|
||||
|
@ -10012,7 +10061,11 @@ var WK_ = /*#__PURE__*/(function() {
|
|||
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; 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;
|
||||
default: throw "Unrecognized QPW cell type " + (flags & 0x1F);
|
||||
}
|
||||
if(fmtidx != -1 && (FMTS[fmtidx - 1]||{}).z) cell.z = FMTS[fmtidx-1].z;
|
||||
|
@ -10058,6 +10111,17 @@ 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;
|
||||
|
@ -11210,7 +11274,7 @@ function parse_cellXfs(t, styles, opts) {
|
|||
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]])
|
||||
|
@ -11224,7 +11288,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;
|
||||
|
@ -11236,12 +11300,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': pass = true; break;
|
||||
case '<AlternateContent': case '<AlternateContent>': pass = true; break;
|
||||
case '</AlternateContent>': pass = false; break;
|
||||
|
||||
/* 18.2.10 extLst CT_ExtensionList ? */
|
||||
|
@ -12882,7 +12946,10 @@ 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])([$]?)(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 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 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) {
|
||||
|
@ -15596,7 +15663,7 @@ 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 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*)"/;
|
||||
|
@ -22455,9 +22522,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']);
|
||||
var r = decode_range(ws['!ref'] || "A1");
|
||||
out.push(make_html_preamble(ws, r, o));
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
|
||||
if(ws["!ref"]) 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("");
|
||||
}
|
||||
|
@ -23216,10 +23283,13 @@ 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:
|
||||
|
@ -23736,6 +23806,7 @@ 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})];
|
||||
|
@ -24987,7 +25058,7 @@ function s5s_to_iwa_comment(s5s) {
|
|||
return out;
|
||||
}
|
||||
function parse_TST_TableModelArchive(M, root, ws, opts) {
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
||||
var pb = parse_shallow(root.data);
|
||||
var range = { s: { r: 0, c: 0 }, e: { r: 0, c: 0 } };
|
||||
range.e.r = (varint_to_i32(pb[6][0].data) >>> 0) - 1;
|
||||
|
@ -25016,7 +25087,17 @@ function parse_TST_TableModelArchive(M, root, ws, opts) {
|
|||
lut.nfmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[22][0].data)][0]);
|
||||
var tile = parse_shallow(store[3][0].data);
|
||||
var _R = 0;
|
||||
tile[1].forEach(function(t) {
|
||||
if (!((_h = store[9]) == null ? void 0 : _h[0]))
|
||||
throw "NUMBERS file missing row tree";
|
||||
var rtt = parse_shallow(store[9][0].data)[1].map(function(p) {
|
||||
return parse_shallow(p.data);
|
||||
});
|
||||
rtt.forEach(function(kv) {
|
||||
_R = varint_to_i32(kv[1][0].data);
|
||||
var tidx = varint_to_i32(kv[2][0].data);
|
||||
var t = tile[1][tidx];
|
||||
if (!t)
|
||||
throw "NUMBERS missing tile " + tidx;
|
||||
var tl = parse_shallow(t.data);
|
||||
var ref2 = M[parse_TSP_Reference(tl[2][0].data)][0];
|
||||
var mtype2 = varint_to_i32(ref2.meta[1][0].data);
|
||||
|
@ -25039,12 +25120,12 @@ function parse_TST_TableModelArchive(M, root, ws, opts) {
|
|||
});
|
||||
_R += _tile.nrows;
|
||||
});
|
||||
if ((_h = store[13]) == null ? void 0 : _h[0]) {
|
||||
if ((_i = store[13]) == null ? void 0 : _i[0]) {
|
||||
var ref = M[parse_TSP_Reference(store[13][0].data)][0];
|
||||
var mtype = varint_to_i32(ref.meta[1][0].data);
|
||||
if (mtype != 6144)
|
||||
throw new Error("Expected merge type 6144, found ".concat(mtype));
|
||||
ws["!merges"] = (_i = parse_shallow(ref.data)) == null ? void 0 : _i[1].map(function(pi) {
|
||||
ws["!merges"] = (_j = parse_shallow(ref.data)) == null ? void 0 : _j[1].map(function(pi) {
|
||||
var merge = parse_shallow(pi.data);
|
||||
var origin = u8_to_dataview(parse_shallow(merge[1][0].data)[1][0].data), size = u8_to_dataview(parse_shallow(merge[2][0].data)[1][0].data);
|
||||
return {
|
||||
|
@ -25706,6 +25787,8 @@ function write_numbers_ws(cfb, deps, ws, wsname, sheetidx, rootref) {
|
|||
}
|
||||
var USE_WIDE_ROWS = true;
|
||||
function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) {
|
||||
if (!ws["!ref"])
|
||||
throw new Error("Cannot export empty sheet to NUMBERS");
|
||||
var range = decode_range(ws["!ref"]);
|
||||
range.s.r = range.s.c = 0;
|
||||
var trunc = false;
|
||||
|
@ -27151,7 +27234,7 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
|
|||
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)) v = utc_to_local(v); break;
|
||||
case 'd': if(!(o && (o.UTC||(o.raw === false)))) v = utc_to_local(new Date(v)); break;
|
||||
default: throw new Error('unrecognized type ' + val.t);
|
||||
}
|
||||
if(hdr[C] != null) {
|
||||
|
@ -27161,7 +27244,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]] = raw && (val.t !== "n" || (val.t === "n" && o.rawNumbers !== false)) ? v : format_cell(val,v,o);
|
||||
row[hdr[C]] = (val.t === 'n' && typeof o.rawNumbers === 'boolean' ? o.rawNumbers : raw) ? v : format_cell(val, v, o);
|
||||
}
|
||||
if(v != null) isempty = false;
|
||||
}
|
||||
|
@ -27419,9 +27502,11 @@ function wb_sheet_idx(wb/*:Workbook*/, sh/*:number|string*/) {
|
|||
} else throw new Error("Cannot find sheet |" + sh + "|");
|
||||
}
|
||||
|
||||
/* simple blank workbook object */
|
||||
function book_new()/*:Workbook*/ {
|
||||
return { SheetNames: [], Sheets: {} };
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* add a worksheet to the end of a given workbook */
|
||||
|
@ -27518,6 +27603,7 @@ 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,
|
||||
|
|
Loading…
Reference in New Issue