forked from sheetjs/sheetjs
version bump 0.20.0
This commit is contained in:
parent
36c5b7c0f5
commit
955543147d
.gitignore.npmignoreCHANGELOG.mdMakefile
bits
00_header.js01_version.js10_ssf.js11_ssfutils.js20_jsutils.js27_csfutils.js39_xlsbiff.js40_harb.js41_lotus.js55_vml.js63_fbin.js65_fods.js66_wscommon.js67_wsxml.js68_wsbin.js75_xlml.js76_xls.js77_parsetab.js78_writebiff.js79_html.js80_parseods.js81_writeods.js83_numbers.js90_utils.js
dist
xlsx.core.min.jsxlsx.core.min.mapxlsx.extendscript.jsxlsx.full.min.jsxlsx.full.min.mapxlsx.mini.min.jsxlsx.mini.min.map
modules
package.jsontest.jstest.mjstest.mtstest.tstestbun.mjstestnocp.tstests
types
xlsx.flow.jsxlsx.jsxlsx.mini.flow.jsxlsx.mini.jsxlsx.mjs
1
.gitignore
vendored
1
.gitignore
vendored
@ -28,6 +28,7 @@ tmp
|
||||
*.[fF][mM][3tT]
|
||||
*.[bB][iI][fF][fF][23458]
|
||||
*.[rR][tT][fF]
|
||||
*.[eE][tT]
|
||||
*.[eE][tT][hH]
|
||||
*.[nN][uU][mM][bB][eE][rR][sS]
|
||||
*.[mM][oO][dD]
|
||||
|
@ -11,6 +11,7 @@ node_modules
|
||||
*.jsx
|
||||
_book
|
||||
book.json
|
||||
v8.log
|
||||
tmp
|
||||
*.[tT][xX][tT]
|
||||
*.[cC][sS][vV]
|
||||
@ -19,6 +20,7 @@ tmp
|
||||
*.[pP][mM][dD]*
|
||||
*.[pP][dD][fF]
|
||||
*.[sS][lL][kK]
|
||||
*.[sS][yY][lL][kK]
|
||||
*.socialcalc
|
||||
*.[xX][lL][sSwWcCaAtTmMrR]
|
||||
*.[xX][lL][sSaAtT][xXmMbB]
|
||||
@ -32,6 +34,7 @@ tmp
|
||||
*.[fF][mM][3tT]
|
||||
*.[bB][iI][fF][fF][23458]
|
||||
*.[rR][tT][fF]
|
||||
*.[eE][tT]
|
||||
*.[eE][tT][hH]
|
||||
*.[nN][uU][mM][bB][eE][rR][sS]
|
||||
*.[mM][oO][dD]
|
||||
|
@ -4,6 +4,10 @@ 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.0
|
||||
|
||||
* Use UTC interpretation of Date objects for date cells (potentially breaking)
|
||||
* API functions support UTC and local time value interpretations
|
||||
* Export `NaN` values to `#NUM!` and infinite values to `#DIV/0!`
|
||||
|
||||
## v0.19.3
|
||||
|
15
Makefile
15
Makefile
@ -107,13 +107,13 @@ dist-deps: ## Copy dependencies for distribution
|
||||
.PHONY: aux
|
||||
aux: $(AUXTARGETS)
|
||||
|
||||
BYTEFILEC=dist/xlsx.{full,core,mini}.min.js
|
||||
BYTEFILER=dist/xlsx.extendscript.js xlsx.mjs
|
||||
BYTEFILEC=dist/xlsx.{full,core,mini}.min.js xlsx.mjs
|
||||
BYTEFILER=dist/xlsx.extendscript.js
|
||||
.PHONY: bytes
|
||||
bytes: ## Display minified and gzipped file sizes
|
||||
@for i in $(BYTEFILEC); do npx printj "%-30s %7d %10d" $$i $$(wc -c < $$i) $$(gzip --best --stdout $$i | wc -c); done
|
||||
@for i in $(BYTEFILER); do npx printj "%-30s %7d" $$i $$(wc -c < $$i); done
|
||||
@npx printj "%-30s %10d" "treeshake" "$$(npx esbuild@0.14.14 --bundle misc/import.js | wc -c)"
|
||||
@npx printj "%-30s %10d" "treeshake" "$$(npx -y esbuild@0.14.14 --bundle misc/import.js | wc -c)"
|
||||
|
||||
|
||||
.PHONY: git
|
||||
@ -141,6 +141,10 @@ test mocha: test.js ## Run test suite
|
||||
#* To run tests for one format, make test_<fmt>
|
||||
#* To run the core test suite, make test_misc
|
||||
|
||||
.PHONY: testdot
|
||||
testdot: test.js ## Run test suite using dot reporter
|
||||
mocha -R dot -t 30000
|
||||
|
||||
.PHONY: test-esm
|
||||
test-esm: test.mjs ## Run Node ESM test suite
|
||||
npx -y mocha@9 -R spec -t 30000 $<
|
||||
@ -165,6 +169,11 @@ TESTFMT=$(patsubst %,test_%,$(FMT))
|
||||
$(TESTFMT): test_%:
|
||||
FMTS=$* make test
|
||||
|
||||
TESTFMT=$(patsubst %,testdot_%,$(FMT))
|
||||
.PHONY: $(TESTFMT)
|
||||
$(TESTFMT): testdot_%:
|
||||
FMTS=$* make testdot
|
||||
|
||||
TESTESMFMT=$(patsubst %,test-esm_%,$(FMT))
|
||||
.PHONY: $(TESTESMFMT)
|
||||
$(TESTESMFMT): test-esm_%:
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
/* vim: set ts=2: */
|
||||
/*exported XLSX */
|
||||
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */
|
||||
/*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){
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.19.3';
|
||||
XLSX.version = '0.20.0';
|
||||
|
@ -203,15 +203,6 @@ function SSF_parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
|
||||
out.q = dow;
|
||||
return out;
|
||||
}
|
||||
var SSFbasedate = /*#__PURE__*/new Date(1899, 11, 31, 0, 0, 0);
|
||||
var SSFdnthresh = /*#__PURE__*/SSFbasedate.getTime();
|
||||
var SSFbase1904 = /*#__PURE__*/new Date(1900, 2, 1, 0, 0, 0);
|
||||
function datenum_local(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
|
||||
var epoch = /*#__PURE__*/v.getTime();
|
||||
if(date1904) epoch -= 1461*24*60*60*1000;
|
||||
else if(v >= SSFbase1904) epoch += 24*60*60*1000;
|
||||
return (epoch - (SSFdnthresh + (/*#__PURE__*/v.getTimezoneOffset() - /*#__PURE__*/SSFbasedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
|
||||
}
|
||||
/* ECMA-376 18.8.30 numFmt*/
|
||||
/* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
|
||||
/* exponent >= -9 and <= 9 */
|
||||
@ -269,7 +260,7 @@ function SSF_general(v/*:any*/, opts/*:any*/) {
|
||||
case 'undefined': return "";
|
||||
case 'object':
|
||||
if(v == null) return "";
|
||||
if(v instanceof Date) return SSF_format(14, datenum_local(v, opts && opts.date1904), opts);
|
||||
if(v instanceof Date) return SSF_format(14, datenum(v, opts && opts.date1904), opts);
|
||||
}
|
||||
throw new Error("unsupported value in General format: " + v);
|
||||
}
|
||||
@ -957,7 +948,7 @@ function SSF_format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
|
||||
break;
|
||||
}
|
||||
if(SSF_isgeneral(sfmt,0)) return SSF_general(v, o);
|
||||
if(v instanceof Date) v = datenum_local(v, o.date1904);
|
||||
if(v instanceof Date) v = datenum(v, o.date1904);
|
||||
var f = choose_fmt(sfmt, v);
|
||||
if(SSF_isgeneral(f[1])) return SSF_general(v, o);
|
||||
if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
|
||||
|
@ -43,6 +43,7 @@ var dateNFregex = /[dD]+|[mM]+|[yYeE]+|[Hh]+|[Ss]+/g;
|
||||
function dateNF_regex(dateNF/*:string|number*/)/*:RegExp*/ {
|
||||
var fmt = typeof dateNF == "number" ? table_fmt[dateNF] : dateNF;
|
||||
fmt = fmt.replace(dateNFregex, "(\\d+)");
|
||||
dateNFregex.lastIndex = 0;
|
||||
return new RegExp("^" + fmt + "$");
|
||||
}
|
||||
function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/*:string*/ {
|
||||
@ -55,6 +56,7 @@ function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/
|
||||
case 'm': if(H >= 0) M = v; else m = v; break;
|
||||
}
|
||||
});
|
||||
dateNFregex.lastIndex = 0;
|
||||
if(S >= 0 && M == -1 && m >= 0) { M = m; m = -1; }
|
||||
var datestr = (("" + (Y>=0?Y: new Date().getFullYear())).slice(-4) + "-" + ("00" + (m>=1?m:1)).slice(-2) + "-" + ("00" + (d>=1?d:1)).slice(-2));
|
||||
if(datestr.length == 7) datestr = "0" + datestr;
|
||||
|
@ -31,22 +31,19 @@ function evert_arr(obj/*:any*/)/*:EvertArrType*/ {
|
||||
return o;
|
||||
}
|
||||
|
||||
var basedate = /*#__PURE__*/new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
|
||||
var dnthresh = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
|
||||
var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
|
||||
var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
|
||||
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
|
||||
var epoch = /*#__PURE__*/v.getTime();
|
||||
if(date1904) epoch -= 1462*24*60*60*1000;
|
||||
var dnthresh = /*#__PURE__*/basedate.getTime() + (/*#__PURE__*/v.getTimezoneOffset() - /*#__PURE__*/basedate.getTimezoneOffset()) * 60000;
|
||||
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
if(date1904) { res -= 1462; return res < -1402 ? res - 1 : res; }
|
||||
return res < 60 ? res - 1 : res;
|
||||
}
|
||||
var refdate = /*#__PURE__*/new Date();
|
||||
var dnthresh = /*#__PURE__*/basedate.getTime() + (/*#__PURE__*/refdate.getTimezoneOffset() - /*#__PURE__*/basedate.getTimezoneOffset()) * 60000;
|
||||
var refoffset = /*#__PURE__*/refdate.getTimezoneOffset();
|
||||
function numdate(v/*:number*/)/*:Date*/ {
|
||||
function numdate(v/*:number*/)/*:Date|number*/ {
|
||||
if(v >= 60 && v < 61) return v;
|
||||
var out = new Date();
|
||||
out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh);
|
||||
if (out.getTimezoneOffset() !== refoffset) {
|
||||
out.setTime(out.getTime() + (out.getTimezoneOffset() - refoffset) * 60000);
|
||||
}
|
||||
out.setTime((v>60 ? v : (v+1)) * 24 * 60 * 60 * 1000 + dnthresh);
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -77,28 +74,22 @@ function parse_isodur(s) {
|
||||
return sec;
|
||||
}
|
||||
|
||||
var good_pd_date_1 = /*#__PURE__*/new Date('2017-02-19T19:06:09.000Z');
|
||||
var good_pd_date = /*#__PURE__*/isNaN(/*#__PURE__*/good_pd_date_1.getFullYear()) ? /*#__PURE__*/new Date('2/19/17') : good_pd_date_1;
|
||||
var good_pd = /*#__PURE__*/good_pd_date.getFullYear() == 2017;
|
||||
/* parses a date as a local date */
|
||||
function parseDate(str/*:string|Date*/, fixdate/*:?number*/)/*:Date*/ {
|
||||
var d = new Date(str);
|
||||
if(good_pd) {
|
||||
/*:: if(fixdate == null) fixdate = 0; */
|
||||
if(fixdate > 0) d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
|
||||
else if(fixdate < 0) d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000);
|
||||
return d;
|
||||
}
|
||||
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
|
||||
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
|
||||
var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
|
||||
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]], sans "Z"
|
||||
/* parses a date string as a UTC date */
|
||||
function parseDate(str/*:string*/, date1904/*:boolean*/)/*:Date*/ {
|
||||
if(str instanceof Date) return str;
|
||||
if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
|
||||
var s = d.getFullYear();
|
||||
if(str.indexOf("" + s) > -1) return d;
|
||||
d.setFullYear(d.getFullYear() + 100); return d;
|
||||
}
|
||||
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
|
||||
var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
|
||||
if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000);
|
||||
return out;
|
||||
var m = str.match(pdre1);
|
||||
if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
|
||||
m = str.match(pdre2);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
|
||||
/* TODO: 1900-02-29T00:00:00.000 should return a flag to treat as a date code (affects xlml) */
|
||||
m = str.match(pdre3);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt(m[7].slice(1), 10))||0)));
|
||||
var d = new Date(str);
|
||||
return d;
|
||||
}
|
||||
|
||||
function cc2str(arr/*:Array<number>*/, debomit)/*:string*/ {
|
||||
@ -170,32 +161,49 @@ function fuzzynum(s/*:string*/)/*:number*/ {
|
||||
|
||||
/* NOTE: Chrome rejects bare times like 1:23 PM */
|
||||
var FDRE1 = /^(0?\d|1[0-2])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))\s+([ap])m?$/;
|
||||
var FDRE2 = /^([01]?\d|2[0-3])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))$/;
|
||||
var FDISO = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)(\.\d+)?[Z]?$/; // YYYY-mm-dd(T or space)HH:MM:SS[.UUU][Z]
|
||||
|
||||
/* TODO: 1904 adjustment */
|
||||
var utc_append_works = new Date("6/9/69 00:00 UTC").valueOf() == -17798400000;
|
||||
function fuzzytime1(M) /*:Date*/ {
|
||||
/* TODO: 1904 adjustment, keep in sync with base date */
|
||||
if(!M[2]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0);
|
||||
if(!M[2]) return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0));
|
||||
if(M[3]) {
|
||||
if(M[4]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000);
|
||||
else return new Date(1899,11,30,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000);
|
||||
if(M[4]) return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000));
|
||||
else return new Date(Date.UTC(1899,11,31,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000));
|
||||
}
|
||||
else if(M[5]) return new Date(1899,11,30, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0);
|
||||
else return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0);
|
||||
else if(M[5]) return new Date(Date.UTC(1899,11,31, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0));
|
||||
else return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0));
|
||||
}
|
||||
function fuzzytime2(M) /*:Date*/ {
|
||||
if(!M[2]) return new Date(Date.UTC(1899,11,31,+M[1], 0, 0, 0));
|
||||
if(M[3]) {
|
||||
if(M[4]) return new Date(Date.UTC(1899,11,31,+M[1], +M[2], +M[4], parseFloat(M[3])*1000));
|
||||
else return new Date(Date.UTC(1899,11,31,0, +M[1], +M[2], parseFloat(M[3])*1000));
|
||||
}
|
||||
else if(M[5]) return new Date(Date.UTC(1899,11,31, +M[1], +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0));
|
||||
else return new Date(Date.UTC(1899,11,31,+M[1], +M[2], 0, 0));
|
||||
}
|
||||
var lower_months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'];
|
||||
function fuzzydate(s/*:string*/)/*:Date*/ {
|
||||
// See issue 2863 -- this is technically not supported in Excel but is otherwise useful
|
||||
if(FDISO.test(s)) return s.indexOf("Z") == -1 ? local_to_utc(new Date(s)) : new Date(s);
|
||||
var lower = s.toLowerCase();
|
||||
var lnos = lower.replace(/\s+/g, " ").trim();
|
||||
var M = lnos.match(FDRE1);
|
||||
if(M) return fuzzytime1(M);
|
||||
|
||||
var o = new Date(s), n = new Date(NaN);
|
||||
M = lnos.match(FDRE2);
|
||||
if(M) return fuzzytime2(M);
|
||||
M = lnos.match(pdre3);
|
||||
if(M) return new Date(Date.UTC(+M[1], +M[2]-1, +M[3], +M[4], +M[5], ((M[6] && parseInt(M[6].slice(1), 10))|| 0), ((M[7] && parseInt(M[7].slice(1), 10))||0)));
|
||||
var o = new Date(utc_append_works && s.indexOf("UTC") == -1 ? s + " UTC": s), n = new Date(NaN);
|
||||
var y = o.getYear(), m = o.getMonth(), d = o.getDate();
|
||||
if(isNaN(d)) return n;
|
||||
if(lower.match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) {
|
||||
lower = lower.replace(/[^a-z]/g,"").replace(/([^a-z]|^)[ap]m?([^a-z]|$)/,"");
|
||||
if(lower.length > 3 && lower_months.indexOf(lower) == -1) return n;
|
||||
} else if(lower.replace(/[ap]m?/, "").match(/[a-z]/)) return n;
|
||||
if(y < 0 || y > 8099 || s.match(/[^-0-9:,\/\\]/)) return n;
|
||||
if(y < 0 || y > 8099 || s.match(/[^-0-9:,\/\\\ ]/)) return n;
|
||||
return o;
|
||||
}
|
||||
|
||||
@ -208,3 +216,10 @@ var split_regex = /*#__PURE__*/(function() {
|
||||
return o;
|
||||
};
|
||||
})();
|
||||
|
||||
function utc_to_local(utc) {
|
||||
return new Date(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate(), utc.getUTCHours(), utc.getUTCMinutes(), utc.getUTCSeconds(), utc.getUTCMilliseconds());
|
||||
}
|
||||
function local_to_utc(local) {
|
||||
return new Date(Date.UTC(local.getFullYear(), local.getMonth(), local.getDate(), local.getHours(), local.getMinutes(), local.getSeconds(), local.getMilliseconds()));
|
||||
}
|
||||
|
@ -162,6 +162,7 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
|
||||
else if(typeof cell.v === 'boolean') cell.t = 'b';
|
||||
else if(cell.v instanceof Date) {
|
||||
cell.z = o.dateNF || table_fmt[14];
|
||||
if(!o.UTC) cell.v = local_to_utc(cell.v);
|
||||
if(o.cellDates) { cell.t = 'd'; cell.w = SSF_format(cell.z, datenum(cell.v, o.date1904)); }
|
||||
else { cell.t = 'n'; cell.v = datenum(cell.v, o.date1904); cell.w = SSF_format(cell.z, cell.v); }
|
||||
}
|
||||
|
@ -1,9 +1,20 @@
|
||||
/* [MS-XLS] 2.5.19 */
|
||||
function parse_XLSCell(blob/*::, length*/)/*:Cell*/ {
|
||||
function parse_XLSCell(blob, length, opts)/*:Cell*/ {
|
||||
var rw = blob.read_shift(2); // 0-indexed
|
||||
var col = blob.read_shift(2);
|
||||
var ixfe = blob.read_shift(2);
|
||||
return ({r:rw, c:col, ixfe:ixfe}/*:any*/);
|
||||
var ret = ({r:rw, c:col, ixfe:0}/*:any*/);
|
||||
if(opts && opts.biff == 2 || length == 7) {
|
||||
/* TODO: pass back flags */
|
||||
var flags = blob.read_shift(1);
|
||||
ret.ixfe = flags & 0x3F;
|
||||
blob.l += 2;
|
||||
/*
|
||||
var ifntifmt = blob.read_shift(1);
|
||||
var ifmt = ifntifmt & 0x3f, ifnt = ifntifmt >> 6;
|
||||
var flags3 = blob.read_shift(1);
|
||||
*/
|
||||
} else ret.ixfe = blob.read_shift(2);
|
||||
return ret;
|
||||
}
|
||||
function write_XLSCell(R/*:number*/, C/*:number*/, ixfe/*:?number*/, o) {
|
||||
if(!o) o = new_buf(6);
|
||||
@ -228,6 +239,12 @@ function parse_WsBool(blob, length, opts) {
|
||||
|
||||
/* [MS-XLS] 2.4.28 */
|
||||
function parse_BoundSheet8(blob, length, opts) {
|
||||
var name = "";
|
||||
if(opts.biff == 4) {
|
||||
name = parse_ShortXLUnicodeString(blob, 0, opts);
|
||||
if(name.length === 0) name = "Sheet1";
|
||||
return { name:name };
|
||||
}
|
||||
var pos = blob.read_shift(4);
|
||||
var hidden = blob.read_shift(1) & 0x03;
|
||||
var dt = blob.read_shift(1);
|
||||
@ -237,7 +254,7 @@ function parse_BoundSheet8(blob, length, opts) {
|
||||
case 2: dt = 'Chartsheet'; break;
|
||||
case 6: dt = 'VBAModule'; break;
|
||||
}
|
||||
var name = parse_ShortXLUnicodeString(blob, 0, opts);
|
||||
name = parse_ShortXLUnicodeString(blob, 0, opts);
|
||||
if(name.length === 0) name = "Sheet1";
|
||||
return { pos:pos, hs:hidden, dt:dt, name:name };
|
||||
}
|
||||
@ -408,8 +425,8 @@ function write_Font(data, opts) {
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.4.149 */
|
||||
function parse_LabelSst(blob) {
|
||||
var cell = parse_XLSCell(blob);
|
||||
function parse_LabelSst(blob, length, opts) {
|
||||
var cell = parse_XLSCell(blob, length, opts);
|
||||
cell.isst = blob.read_shift(4);
|
||||
return cell;
|
||||
}
|
||||
@ -424,8 +441,7 @@ function write_LabelSst(R/*:number*/, C/*:number*/, v/*:number*/, os/*:number*/
|
||||
function parse_Label(blob, length, opts) {
|
||||
if(opts.biffguess && opts.biff == 2) opts.biff = 5;
|
||||
var target = blob.l + length;
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
if(opts.biff == 2) blob.l++;
|
||||
var cell = parse_XLSCell(blob, length, opts);
|
||||
var str = parse_XLUnicodeString(blob, target - blob.l, opts);
|
||||
cell.val = str;
|
||||
return cell;
|
||||
@ -459,6 +475,19 @@ function write_Format(i/*:number*/, f/*:string*/, opts, o) {
|
||||
return out;
|
||||
}
|
||||
var parse_BIFF2Format = parse_XLUnicodeString2;
|
||||
function write_BIFF2Format(f/*:string*/) {
|
||||
var o = new_buf(1 + f.length);
|
||||
o.write_shift(1, f.length);
|
||||
o.write_shift(f.length, f, "sbcs");
|
||||
return o;
|
||||
}
|
||||
function write_BIFF4Format(f/*:string*/) {
|
||||
var o = new_buf(3 + f.length);
|
||||
o.l += 2;
|
||||
o.write_shift(1, f.length);
|
||||
o.write_shift(f.length, f, "sbcs");
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.4.90 */
|
||||
function parse_Dimensions(blob, length, opts) {
|
||||
@ -582,6 +611,44 @@ function write_XF(data, ixfeP, opts, o) {
|
||||
o.write_shift(2, 0);
|
||||
return o;
|
||||
}
|
||||
function parse_BIFF2XF(blob/*::, length, opts*/) {
|
||||
var o = {};
|
||||
o.ifnt = blob.read_shift(1); blob.l++; o.flags = blob.read_shift(1);
|
||||
o.numFmtId = o.flags & 0x3F; o.flags>>=6;
|
||||
o.fStyle = 0;
|
||||
o.data = {}; // TODO
|
||||
return o;
|
||||
}
|
||||
function write_BIFF2XF(xf) {
|
||||
var o = new_buf(4);
|
||||
o.l+=2;
|
||||
o.write_shift(1, xf.numFmtId);
|
||||
o.l++;
|
||||
return o;
|
||||
}
|
||||
function write_BIFF3XF(xf) {
|
||||
var o = new_buf(12);
|
||||
o.l++;
|
||||
o.write_shift(1, xf.numFmtId);
|
||||
o.l += 10;
|
||||
return o;
|
||||
}
|
||||
/* TODO: check other fields */
|
||||
var write_BIFF4XF = write_BIFF3XF;
|
||||
function parse_BIFF3XF(blob/*::, length, opts*/) {
|
||||
var o = {};
|
||||
o.ifnt = blob.read_shift(1); o.numFmtId = blob.read_shift(1); o.flags = blob.read_shift(2);
|
||||
o.fStyle = (o.flags >> 2) & 0x01;
|
||||
o.data = {}; // TODO
|
||||
return o;
|
||||
}
|
||||
function parse_BIFF4XF(blob/*::, length, opts*/) {
|
||||
var o = {};
|
||||
o.ifnt = blob.read_shift(1); o.numFmtId = blob.read_shift(1); o.flags = blob.read_shift(2);
|
||||
o.fStyle = (o.flags >> 2) & 0x01;
|
||||
o.data = {}; // TODO
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.4.134 */
|
||||
function parse_Guts(blob) {
|
||||
@ -602,8 +669,7 @@ function write_Guts(guts/*:Array<number>*/) {
|
||||
|
||||
/* [MS-XLS] 2.4.24 */
|
||||
function parse_BoolErr(blob, length, opts) {
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
if(opts.biff == 2 || length == 9) ++blob.l;
|
||||
var cell = parse_XLSCell(blob, 6, opts);
|
||||
var val = parse_Bes(blob, 2);
|
||||
cell.val = val;
|
||||
cell.t = (val === true || val === false) ? 'b' : 'e';
|
||||
@ -619,7 +685,7 @@ function write_BoolErr(R/*:number*/, C/*:number*/, v, os/*:number*/, opts, t/*:s
|
||||
/* [MS-XLS] 2.4.180 Number */
|
||||
function parse_Number(blob, length, opts) {
|
||||
if(opts.biffguess && opts.biff == 2) opts.biff = 5;
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
var cell = parse_XLSCell(blob, 6, opts);
|
||||
var xnum = parse_Xnum(blob, 8);
|
||||
cell.val = xnum;
|
||||
return cell;
|
||||
@ -1029,43 +1095,50 @@ function parse_ImData(blob) {
|
||||
return o;
|
||||
}
|
||||
|
||||
function write_BIFF2Cell(out, r/*:number*/, c/*:number*/, ixfe/*:number*/, ifmt/*:number*/) {
|
||||
if(!out) out = new_buf(7);
|
||||
out.write_shift(2, r);
|
||||
out.write_shift(2, c);
|
||||
out.write_shift(1, ixfe||0/* & 0x3F */);
|
||||
out.write_shift(1, ifmt||0/* & 0x3F */);
|
||||
out.write_shift(1, 0);
|
||||
return out;
|
||||
}
|
||||
|
||||
/* BIFF2_??? where ??? is the name from [XLS] */
|
||||
function parse_BIFF2STR(blob, length, opts) {
|
||||
if(opts.biffguess && opts.biff == 5) opts.biff = 2;
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
++blob.l;
|
||||
var cell = parse_XLSCell(blob, 7, opts);
|
||||
var str = parse_XLUnicodeString2(blob, length-7, opts);
|
||||
cell.t = 'str';
|
||||
cell.val = str;
|
||||
return cell;
|
||||
}
|
||||
|
||||
function parse_BIFF2NUM(blob/*::, length*/) {
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
++blob.l;
|
||||
function parse_BIFF2NUM(blob, length, opts) {
|
||||
var cell = parse_XLSCell(blob, 7, opts);
|
||||
var num = parse_Xnum(blob, 8);
|
||||
cell.t = 'n';
|
||||
cell.val = num;
|
||||
return cell;
|
||||
}
|
||||
function write_BIFF2NUM(r/*:number*/, c/*:number*/, val/*:number*/) {
|
||||
function write_BIFF2NUM(r/*:number*/, c/*:number*/, val/*:number*/, ixfe, ifmt) {
|
||||
var out = new_buf(15);
|
||||
write_BIFF2Cell(out, r, c);
|
||||
write_BIFF2Cell(out, r, c, ixfe||0, ifmt||0);
|
||||
out.write_shift(8, val, 'f');
|
||||
return out;
|
||||
}
|
||||
|
||||
function parse_BIFF2INT(blob) {
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
++blob.l;
|
||||
function parse_BIFF2INT(blob, length, opts) {
|
||||
var cell = parse_XLSCell(blob, 7, opts);
|
||||
var num = blob.read_shift(2);
|
||||
cell.t = 'n';
|
||||
cell.val = num;
|
||||
return cell;
|
||||
}
|
||||
function write_BIFF2INT(r/*:number*/, c/*:number*/, val/*:number*/) {
|
||||
function write_BIFF2INT(r/*:number*/, c/*:number*/, val/*:number*/, ixfe/*:number*/, ifmt/*:number*/) {
|
||||
var out = new_buf(9);
|
||||
write_BIFF2Cell(out, r, c);
|
||||
write_BIFF2Cell(out, r, c, ixfe||0, ifmt||0);
|
||||
out.write_shift(2, val);
|
||||
return out;
|
||||
}
|
||||
@ -1076,6 +1149,16 @@ function parse_BIFF2STRING(blob) {
|
||||
return blob.read_shift(cch, 'sbcs-cont');
|
||||
}
|
||||
|
||||
function parse_BIFF2BOOLERR(blob, length, opts) {
|
||||
var bestart = blob.l + 7;
|
||||
var cell = parse_XLSCell(blob, 6, opts);
|
||||
blob.l = bestart;
|
||||
var val = parse_Bes(blob, 2);
|
||||
cell.val = val;
|
||||
cell.t = (val === true || val === false) ? 'b' : 'e';
|
||||
return cell;
|
||||
}
|
||||
|
||||
/* TODO: convert to BIFF8 font struct */
|
||||
function parse_BIFF2FONTXTRA(blob, length) {
|
||||
blob.l += 6; // unknown
|
||||
@ -1089,7 +1172,7 @@ function parse_BIFF2FONTXTRA(blob, length) {
|
||||
/* TODO: parse rich text runs */
|
||||
function parse_RString(blob, length, opts) {
|
||||
var end = blob.l + length;
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
var cell = parse_XLSCell(blob, 6, opts);
|
||||
var cch = blob.read_shift(2);
|
||||
var str = parse_XLUnicodeStringNoCch(blob, cch, opts);
|
||||
blob.l = end;
|
||||
@ -1097,3 +1180,10 @@ function parse_RString(blob, length, opts) {
|
||||
cell.val = str;
|
||||
return cell;
|
||||
}
|
||||
|
||||
function parse_BIFF4SheetInfo(blob/*::, length, opts*/) {
|
||||
var flags = blob.read_shift(4);
|
||||
var cch = blob.read_shift(1), name = blob.read_shift(cch, "sbcs");
|
||||
if(name.length === 0) name = "Sheet1";
|
||||
return { flags: flags, name:name };
|
||||
}
|
@ -179,7 +179,10 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
|
||||
if(s.trim().length) out[R][C] = s.replace(/\s+$/,"");
|
||||
break;
|
||||
case 'D':
|
||||
if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8));
|
||||
if(s.length === 8) {
|
||||
out[R][C] = new Date(Date.UTC(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8), 0, 0, 0, 0));
|
||||
if(!(opts && opts.UTC)) { out[R][C] = utc_to_local(out[R][C]); }
|
||||
}
|
||||
else out[R][C] = s;
|
||||
break;
|
||||
case 'F': out[R][C] = parseFloat(s.trim()); break;
|
||||
@ -202,7 +205,12 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
|
||||
// NOTE: dBASE specs appear to be incorrect
|
||||
out[R][C] = new Date(dd.read_shift(-8, 'f') - 0x388317533400);
|
||||
break;
|
||||
case 'T': out[R][C] = new Date((dd.read_shift(4) - 0x253D8C) * 0x5265C00 + dd.read_shift(4)); break;
|
||||
case 'T': {
|
||||
var hi = dd.read_shift(4), lo = dd.read_shift(4);
|
||||
if(hi == 0 && lo == 0) break;
|
||||
out[R][C] = new Date((hi - 0x253D8C) * 0x5265C00 + lo);
|
||||
if(!(opts && opts.UTC)) out[R][C] = utc_to_local(out[R][C]);
|
||||
} break;
|
||||
case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4 + (dd.read_shift(4, 'i')/1e4)*Math.pow(2,32); break;
|
||||
case 'O': out[R][C] = -dd.read_shift(-8, 'f'); break;
|
||||
case 'B': if(vfp && fields[C].len == 8) { out[R][C] = dd.read_shift(8,'f'); break; }
|
||||
@ -473,10 +481,9 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
else if(val === 'TRUE' || val === 'FALSE') { val = val === 'TRUE'; cell_t = "b"; }
|
||||
else if(!isNaN(fuzzynum(val))) {
|
||||
val = fuzzynum(val); cell_t = "n";
|
||||
if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) { val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : val); cell_t = "d"; }
|
||||
} else if(!isNaN(fuzzydate(val).getDate())) {
|
||||
val = parseDate(val); cell_t = "d";
|
||||
if(!opts.cellDates) { cell_t = "n"; val = datenum(val, wb.Workbook.WBProps.date1904); }
|
||||
if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) {
|
||||
val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : val); cell_t = typeof val == "number" ? "n" : "d";
|
||||
}
|
||||
}
|
||||
if(typeof $cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = $cptable.utils.decode(opts.codepage, val);
|
||||
C_seen_K = true;
|
||||
@ -577,7 +584,7 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
return outwb;
|
||||
}
|
||||
|
||||
function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*//*::, opts*/)/*:string*/ {
|
||||
function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/)/*:string*/ {
|
||||
var o = "C;Y" + (R+1) + ";X" + (C+1) + ";K";
|
||||
switch(cell.t) {
|
||||
case 'n':
|
||||
@ -585,7 +592,7 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break;
|
||||
case 'b': o += cell.v ? "TRUE" : "FALSE"; break;
|
||||
case 'e': o += cell.w || cell.v; break;
|
||||
case 'd': o += '"' + (cell.w || cell.v) + '"'; break;
|
||||
case 'd': o += datenum(parseDate(cell.v, date1904), date1904); break;
|
||||
case 's': o += '"' + (cell.v == null ? "" : String(cell.v)).replace(/"/g,"").replace(/;/g, ";;") + '"'; break;
|
||||
}
|
||||
return o;
|
||||
@ -622,6 +629,7 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
}
|
||||
|
||||
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/, wb/*:?WorkBook*/)/*:string*/ {
|
||||
if(!opts) opts = {}; opts._formats = ["General"];
|
||||
/* TODO: codepage */
|
||||
var preamble/*:Array<string>*/ = ["ID;PSheetJS;N;E"], o/*:Array<string>*/ = [];
|
||||
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
|
||||
@ -629,34 +637,44 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
var RS = "\r\n";
|
||||
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
|
||||
var _lastfmt = "General";
|
||||
preamble.push("P;PGeneral");
|
||||
/* Excel has been inconsistent in comment placement */
|
||||
var R = r.s.r, C = r.s.c, p = [];
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
if(dense && !ws["!data"][R]) continue;
|
||||
p = [];
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
|
||||
if(!cell || !cell.c) continue;
|
||||
p.push(write_ws_cmnt_sylk(cell.c, R, C));
|
||||
}
|
||||
if(p.length) o.push(p.join(RS));
|
||||
}
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
if(dense && !ws["!data"][R]) continue;
|
||||
p = [];
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
|
||||
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
|
||||
if((cell.z||(cell.t == "d" ? table_fmt[14] : "General")) != _lastfmt) {
|
||||
var ifmt = opts._formats.indexOf(cell.z);
|
||||
if(ifmt == -1) { opts._formats.push(cell.z); ifmt = opts._formats.length - 1; preamble.push("P;P" + cell.z.replace(/;/g, ";;")); }
|
||||
p.push("F;P" + ifmt + ";Y" + (R+1) + ";X" + (C+1));
|
||||
}
|
||||
p.push(write_ws_cell_sylk(cell, ws, R, C, opts, d1904));
|
||||
}
|
||||
o.push(p.join(RS));
|
||||
}
|
||||
|
||||
preamble.push("F;P0;DG0G8;M255");
|
||||
if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
|
||||
if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
|
||||
|
||||
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");
|
||||
/* Excel has been inconsistent in comment placement, */
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
if(dense && !ws["!data"][R]) continue;
|
||||
var p = [];
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
|
||||
if(!cell || !cell.c) continue;
|
||||
p.push(write_ws_cmnt_sylk(cell.c, R, C)); // TODO: pass date1904 info
|
||||
}
|
||||
o.push(p.join(RS));
|
||||
}
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
if(dense && !ws["!data"][R]) continue;
|
||||
var p = [];
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
|
||||
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
|
||||
p.push(write_ws_cell_sylk(cell, ws, R, C, opts)); // TODO: pass date1904 info
|
||||
}
|
||||
o.push(p.join(RS));
|
||||
}
|
||||
|
||||
delete opts._formats;
|
||||
return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
|
||||
}
|
||||
|
||||
@ -696,7 +714,10 @@ var DIF = /*#__PURE__*/(function() {
|
||||
if(data === 'TRUE') arr[R][C] = true;
|
||||
else if(data === 'FALSE') arr[R][C] = false;
|
||||
else if(!isNaN(fuzzynum(value))) arr[R][C] = fuzzynum(value);
|
||||
else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value);
|
||||
else if(!isNaN(fuzzydate(value).getDate())) {
|
||||
arr[R][C] = parseDate(value);
|
||||
if(!(opts && opts.UTC)) { arr[R][C] = utc_to_local(arr[R][C]); }
|
||||
}
|
||||
else arr[R][C] = value;
|
||||
++C; break;
|
||||
case 1:
|
||||
@ -977,9 +998,11 @@ var PRN = /*#__PURE__*/(function() {
|
||||
var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0);
|
||||
var _re/*:?RegExp*/ = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
|
||||
function finish_cell() {
|
||||
/* TODO: fuzzy parsers should pass back assumed number format */
|
||||
var s = str.slice(start, end); if(s.slice(-1) == "\r") s = s.slice(0, -1);
|
||||
var cell = ({}/*:any*/);
|
||||
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
|
||||
if(o.cellText !== false) cell.w = s;
|
||||
if(s.length === 0) cell.t = 'z';
|
||||
else if(o.raw) { cell.t = 's'; cell.v = s; }
|
||||
else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; }
|
||||
@ -989,14 +1012,14 @@ var PRN = /*#__PURE__*/(function() {
|
||||
else { cell.t = 's'; cell.v = s; } }
|
||||
else if(s == "TRUE") { cell.t = 'b'; cell.v = true; }
|
||||
else if(s == "FALSE") { cell.t = 'b'; cell.v = false; }
|
||||
else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; if(o.cellText !== false) cell.w = s; cell.v = v; }
|
||||
else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; cell.v = v; }
|
||||
else if(!isNaN((v = fuzzydate(s)).getDate()) || _re && s.match(_re)) {
|
||||
cell.z = o.dateNF || table_fmt[14];
|
||||
var k = 0;
|
||||
if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; v = parseDate(s, k); }
|
||||
if(_re && s.match(_re)){ var news=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); v = parseDate(news); if(o && o.UTC === false) v = utc_to_local(v); }
|
||||
else if(o && o.UTC === false) v = utc_to_local(v);
|
||||
else if(o.cellText !== false && o.dateNF) cell.w = SSF_format(cell.z, v);
|
||||
if(o.cellDates) { cell.t = 'd'; cell.v = v; }
|
||||
else { cell.t = 'n'; cell.v = datenum(v); }
|
||||
if(o.cellText !== false) cell.w = SSF_format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v);
|
||||
if(!o.cellNF) delete cell.z;
|
||||
} else {
|
||||
cell.t = 's';
|
||||
|
137
bits/41_lotus.js
137
bits/41_lotus.js
@ -24,6 +24,22 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
throw "Unsupported type " + opts.type;
|
||||
}
|
||||
|
||||
/* NOTE: this list intentionally starts at 1 */
|
||||
var LOTUS_DATE_FMTS = [
|
||||
"mmmm",
|
||||
"dd-mmm-yyyy",
|
||||
"dd-mmm",
|
||||
"mmm-yyyy",
|
||||
"@", // "text"?
|
||||
"mm/dd",
|
||||
"hh:mm:ss AM/PM", // 7
|
||||
"hh:mm AM/PM",
|
||||
"mm/dd/yyyy",
|
||||
"mm/dd",
|
||||
"hh:mm:ss",
|
||||
"hh:mm" // 12
|
||||
];
|
||||
|
||||
function lotus_to_workbook_buf(d, opts)/*:Workbook*/ {
|
||||
if(!d) return d;
|
||||
var o = opts || {};
|
||||
@ -34,6 +50,7 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
|
||||
var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
|
||||
var sheetRows = o.sheetRows || 0;
|
||||
var lastcell = {};
|
||||
|
||||
if(d[4] == 0x51 && d[5] == 0x50 && d[6] == 0x57) return qpw_to_workbook_buf(d, opts);
|
||||
if(d[2] == 0x00) {
|
||||
@ -65,9 +82,9 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
case 0x0E: /* NUMBER */
|
||||
case 0x10: /* FORMULA */
|
||||
/* TODO: actual translation of the format code */
|
||||
if(RT == 0x0E && (val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) {
|
||||
val[1].z = o.dateNF || table_fmt[14];
|
||||
if(o.cellDates) { val[1].t = 'd'; val[1].v = numdate(val[1].v); }
|
||||
if((val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) {
|
||||
val[1].z = o.dateNF || LOTUS_DATE_FMTS[(val[2] & 0x0F)-1] || table_fmt[14];
|
||||
if(o.cellDates) { val[1].v = numdate(val[1].v); val[1].t = typeof val[1].v == "number" ? 'n' : 'd'; }
|
||||
}
|
||||
|
||||
if(o.qpro) {
|
||||
@ -86,15 +103,25 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
tmpcell.t = val[1].t; tmpcell.v = val[1].v;
|
||||
if(val[1].z != null) tmpcell.z = val[1].z;
|
||||
if(val[1].f != null) tmpcell.f = val[1].f;
|
||||
lastcell = tmpcell;
|
||||
break;
|
||||
}
|
||||
if(o.dense) {
|
||||
if(!sdata[val[0].r]) sdata[val[0].r] = [];
|
||||
sdata[val[0].r][val[0].c] = val[1];
|
||||
} else s[encode_cell(val[0])] = val[1];
|
||||
lastcell = val[1];
|
||||
break;
|
||||
case 0x5405: o.works2 = true; break;
|
||||
default:
|
||||
case 0x5402: {
|
||||
/* TODO: enumerate all extended number formats */
|
||||
if(val == 0x14a1) {
|
||||
lastcell.z = "hh:mm:ss";
|
||||
if(o.cellDates && lastcell.t == "n") {
|
||||
lastcell.v = numdate(lastcell.v); lastcell.t = typeof lastcell.v == "number" ? 'n' : 'd';
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}}, o);
|
||||
} else if(d[2] == 0x1A || d[2] == 0x0E) {
|
||||
o.Enum = WK3Enum;
|
||||
@ -171,10 +198,17 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
var cell = dense ? (ws["!data"][R]||[])[C] : ws[cols[C] + rr];
|
||||
if(!cell || cell.t == "z") continue;
|
||||
/* TODO: formula records */
|
||||
if(cell.t == "n") {
|
||||
if((cell.v|0)==cell.v && cell.v >= -32768 && cell.v <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, cell.v));
|
||||
else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, cell.v));
|
||||
} else {
|
||||
switch(cell.t) {
|
||||
case "n":
|
||||
if((cell.v|0)==cell.v && cell.v >= -32768 && cell.v <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, cell));
|
||||
else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, cell));
|
||||
break;
|
||||
case "d":
|
||||
var dc = datenum(cell.v);
|
||||
if((dc|0)==dc && dc >= -32768 && dc <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, {t:"n", v:dc, z:cell.z || table_fmt[14]}));
|
||||
else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, {t:"n", v:dc, z:cell.z || table_fmt[14]}));
|
||||
break;
|
||||
default:
|
||||
var str = format_cell(cell);
|
||||
write_biff_rec(ba, 0x0F, write_LABEL(R, C, str.slice(0, 239)));
|
||||
}
|
||||
@ -308,11 +342,18 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
return o;
|
||||
}
|
||||
|
||||
function get_wk1_fmt(cell)/*:number*/ {
|
||||
/* TODO: some fuzzy matching on the number format */
|
||||
if(cell.z && fmt_is_date(cell.z)) {
|
||||
return 0xf0 | (LOTUS_DATE_FMTS.indexOf(cell.z) + 1 || 2);
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
function parse_LABEL(blob, length, opts) {
|
||||
var tgt = blob.l + length;
|
||||
var o = parse_cell(blob, length, opts);
|
||||
o[1].t = 's';
|
||||
if(opts.vers == 0x5120) {
|
||||
if((opts.vers & 0xFFFE) == 0x5120) { // WQ1 / WQ2
|
||||
blob.l++;
|
||||
var len = blob.read_shift(1);
|
||||
o[1].v = blob.read_shift(len, 'utf8');
|
||||
@ -354,12 +395,12 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
o[1].v = blob.read_shift(2, 'i');
|
||||
return o;
|
||||
}
|
||||
function write_INTEGER(R, C, v) {
|
||||
function write_INTEGER(R, C, cell) {
|
||||
var o = new_buf(7);
|
||||
o.write_shift(1, 0xFF);
|
||||
o.write_shift(1, get_wk1_fmt(cell));
|
||||
o.write_shift(2, C);
|
||||
o.write_shift(2, R);
|
||||
o.write_shift(2, v, 'i');
|
||||
o.write_shift(2, cell.v, 'i');
|
||||
return o;
|
||||
}
|
||||
|
||||
@ -368,12 +409,12 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
o[1].v = blob.read_shift(8, 'f');
|
||||
return o;
|
||||
}
|
||||
function write_NUMBER(R, C, v) {
|
||||
function write_NUMBER(R, C, cell) {
|
||||
var o = new_buf(13);
|
||||
o.write_shift(1, 0xFF);
|
||||
o.write_shift(1, get_wk1_fmt(cell));
|
||||
o.write_shift(2, C);
|
||||
o.write_shift(2, R);
|
||||
o.write_shift(8, v, 'f');
|
||||
o.write_shift(8, cell.v, 'f');
|
||||
return o;
|
||||
}
|
||||
|
||||
@ -426,7 +467,7 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
0x33: ["FALSE", 0],
|
||||
0x34: ["TRUE", 0],
|
||||
0x35: ["RAND", 0],
|
||||
// 0x36 DATE
|
||||
0x36: ["DATE", 3],
|
||||
// 0x37 NOW
|
||||
// 0x38 PMT
|
||||
// 0x39 PV
|
||||
@ -436,7 +477,7 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
// 0x3D MONTH
|
||||
// 0x3E YEAR
|
||||
0x3F: ["ROUND", 2],
|
||||
// 0x40 TIME
|
||||
0x40: ["TIME", 3],
|
||||
// 0x41 HOUR
|
||||
// 0x42 MINUTE
|
||||
// 0x43 SECOND
|
||||
@ -778,13 +819,24 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
/*::[*/0x0048/*::]*/: { n:"ACOMM" },
|
||||
/*::[*/0x0049/*::]*/: { n:"AMACRO" },
|
||||
/*::[*/0x004A/*::]*/: { n:"PARSE" },
|
||||
// 0x0064
|
||||
/*::[*/0x0066/*::]*/: { n:"PRANGES??" },
|
||||
/*::[*/0x0067/*::]*/: { n:"RRANGES??" },
|
||||
/*::[*/0x0068/*::]*/: { n:"FNAME??" },
|
||||
/*::[*/0x0069/*::]*/: { n:"MRANGES??" },
|
||||
// 0x0096
|
||||
// 0x0099
|
||||
// 0x009A
|
||||
// 0x009B
|
||||
// 0x009C
|
||||
// 0x00C0
|
||||
// 0x00C7
|
||||
// 0x00C9
|
||||
/*::[*/0x00CC/*::]*/: { n:"SHEETNAMECS", f:parse_SHEETNAMECS },
|
||||
// 0x00CD
|
||||
/*::[*/0x00DE/*::]*/: { n:"SHEETNAMELP", f:parse_SHEETNAMELP },
|
||||
/*::[*/0x00FF/*::]*/: { n:"BOF", f:parseuint16 },
|
||||
/*::[*/0x5402/*::]*/: { n:"WKSNF", f:parseuint16 },
|
||||
/*::[*/0xFFFF/*::]*/: { n:"" }
|
||||
};
|
||||
|
||||
@ -914,6 +966,24 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
/*::[*/0xFFFF/*::]*/: { n:"" }
|
||||
};
|
||||
|
||||
/* TODO: fill out and verify this table across QP versions */
|
||||
var QPWNFTable = {
|
||||
/*::[*/0x05/*::*/: "dd-mmm-yy",
|
||||
/*::[*/0x06/*::*/: "dd-mmm",
|
||||
/*::[*/0x07/*::*/: "mmm-yy",
|
||||
/*::[*/0x08/*::*/: "mm/dd/yy", // Long Date Intl
|
||||
/*::[*/0x0A/*::*/: "hh:mm:ss AM/PM",
|
||||
/*::[*/0x0B/*::*/: "hh:mm AM/PM",
|
||||
/*::[*/0x0E/*::*/: "dd-mmm-yyyy",
|
||||
/*::[*/0x0F/*::*/: "mmm-yyyy",
|
||||
|
||||
/*::[*/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
|
||||
};
|
||||
/* QPW uses a different set of record types */
|
||||
function qpw_to_workbook_buf(d, opts)/*:Workbook*/ {
|
||||
prep_blob(d, 0);
|
||||
@ -924,6 +994,7 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
var range = {s:{r:-1,c:-1}, e:{r:-1,c:-1}};
|
||||
var cnt = 0, type = 0, C = 0, R = 0;
|
||||
var wb = { SheetNames: [], Sheets: {} };
|
||||
var FMTS = [];
|
||||
outer: while(d.l < d.length) {
|
||||
var RT = d.read_shift(2), length = d.read_shift(2);
|
||||
var p = d.slice(d.l, d.l + length);
|
||||
@ -934,6 +1005,22 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
break;
|
||||
case 0x02: /* EOF */ break outer;
|
||||
|
||||
case 0x08: /* NF */ break; // TODO: this is tied to custom number formats
|
||||
|
||||
case 0x0A: /* FORMATS */ {
|
||||
var fcnt = p.read_shift(4);
|
||||
var step = ((p.length - p.l)/ fcnt)|0;
|
||||
for(var ifmt = 0; ifmt < fcnt; ++ifmt) {
|
||||
var end = p.l + step;
|
||||
var fmt = {};
|
||||
p.l += 2;
|
||||
fmt.numFmtId = p.read_shift(2);
|
||||
if(QPWNFTable[fmt.numFmtId]) fmt.z = QPWNFTable[fmt.numFmtId];
|
||||
p.l = end;
|
||||
FMTS.push(fmt);
|
||||
}
|
||||
} break;
|
||||
|
||||
/* TODO: The behavior here should be consistent with Numbers: QP Notebook ~ .TN.SheetArchive, QP Sheet ~ .TST.TableModelArchive */
|
||||
case 0x0401: /* BON */ break;
|
||||
case 0x0402: /* EON */ /* TODO: backfill missing sheets based on BON cnt */ break;
|
||||
@ -996,18 +1083,21 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
var CC = encode_col(C);
|
||||
while(p.l < p.length) {
|
||||
var cell = { t: "z" };
|
||||
var flags = p.read_shift(1);
|
||||
if(flags & 0x80) p.l += 2;
|
||||
var flags = p.read_shift(1), fmtidx = -1;
|
||||
if(flags & 0x80) fmtidx = p.read_shift(2);
|
||||
var mul = (flags & 0x40) ? p.read_shift(2) - 1: 0;
|
||||
switch(flags & 0x1F) {
|
||||
case 0: break;
|
||||
case 1: break;
|
||||
case 2: cell = { t: "n", v: p.read_shift(2) }; break;
|
||||
case 3: cell = { t: "n", v: p.read_shift(2, 'i') }; break;
|
||||
case 4: cell = { t: "n", v: parse_RkNumber(p) }; break;
|
||||
case 5: cell = { t: "n", v: p.read_shift(8, 'f') }; break;
|
||||
case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break;
|
||||
case 8: cell = { t: "n", v: p.read_shift(8, 'f') }; p.l += 2; /* cell.f = formulae[p.read_shift(4)]; */ p.l += 4; break;
|
||||
default: throw "Unrecognized QPW cell type " + (flags & 0x1F);
|
||||
}
|
||||
if(fmtidx != -1 && (FMTS[fmtidx - 1]||{}).z) cell.z = FMTS[fmtidx-1].z;
|
||||
var delta = 0;
|
||||
if(flags & 0x20) switch(flags & 0x1F) {
|
||||
case 2: delta = p.read_shift(2); break;
|
||||
@ -1016,10 +1106,14 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
default: throw "Unsupported delta for QPW cell type " + (flags & 0x1F);
|
||||
}
|
||||
if(!(!o.sheetStubs && cell.t == "z")) {
|
||||
var newcell = dup(cell);
|
||||
if(cell.t == "n" && cell.z && fmt_is_date(cell.z) && o.cellDates) {
|
||||
newcell.v = numdate(cell.v); newcell.t = typeof newcell.v == "number" ? 'n' : 'd';
|
||||
}
|
||||
if(s["!data"] != null) {
|
||||
if(!s["!data"][R]) s["!data"][R] = [];
|
||||
s["!data"][R][C] = cell;
|
||||
} else s[CC + encode_row(R)] = cell;
|
||||
s["!data"][R][C] = newcell;
|
||||
} else s[CC + encode_row(R)] = newcell;
|
||||
}
|
||||
++R; --cnt;
|
||||
while(mul-- > 0 && cnt >= 0) {
|
||||
@ -1034,6 +1128,7 @@ var WK_ = /*#__PURE__*/(function() {
|
||||
case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break;
|
||||
default: throw "Cannot apply repeat for QPW cell type " + (flags & 0x1F);
|
||||
}
|
||||
if(fmtidx != -1);
|
||||
if(!(!o.sheetStubs && cell.t == "z")) {
|
||||
if(s["!data"] != null) {
|
||||
if(!s["!data"][R]) s["!data"][R] = [];
|
||||
|
@ -5,6 +5,7 @@ function parse_vml(data/*:string*/, sheet, comments) {
|
||||
(data.match(shapevmlregex)||[]).forEach(function(m) {
|
||||
var type = "";
|
||||
var hidden = true;
|
||||
var aidx = -1;
|
||||
var R = -1, C = -1;
|
||||
m.replace(tagregex, function(x/*:string*/, idx/*:number*/) {
|
||||
var y = parsexmltag(x);
|
||||
|
@ -68,8 +68,7 @@ function write_FormulaValue(value) {
|
||||
/* [MS-XLS] 2.4.127 TODO */
|
||||
function parse_Formula(blob, length, opts) {
|
||||
var end = blob.l + length;
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
if(opts.biff == 2) ++blob.l;
|
||||
var cell = parse_XLSCell(blob, 6, opts);
|
||||
var val = parse_FormulaValue(blob,8);
|
||||
var flags = blob.read_shift(1);
|
||||
if(opts.biff != 2) {
|
||||
@ -263,7 +262,7 @@ function write_XLSBFormulaRangeWS(_str, wb) {
|
||||
var sname = _str.slice(0, lastbang);
|
||||
_str = _str.slice(lastbang+1);
|
||||
if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
|
||||
var parts = _str.split(":"); str = parts[0];
|
||||
var parts = _str.split(":");
|
||||
|
||||
var out = new_buf(27);
|
||||
out.write_shift(4, 19);
|
||||
|
@ -31,6 +31,6 @@ function ods_to_csf_3D(r/*:string*/)/*:[string, string]*/ {
|
||||
}
|
||||
|
||||
function csf_to_ods_3D(r/*:string*/)/*:string*/ {
|
||||
return r.replace(/!/,".");
|
||||
return r.replace(/!/,".").replace(/:/, ":.");
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) {
|
||||
return len;
|
||||
}
|
||||
|
||||
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) {
|
||||
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles, date1904) {
|
||||
try {
|
||||
if(opts.cellNF) p.z = table_fmt[fmtid];
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
@ -96,14 +96,14 @@ function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, the
|
||||
else p.w = SSF_general_num(p.v);
|
||||
}
|
||||
else if(p.t === 'd') {
|
||||
var dd = datenum(p.v);
|
||||
var dd = datenum(p.v, !!date1904);
|
||||
if((dd|0) === dd) p.w = dd.toString(10);
|
||||
else p.w = SSF_general_num(dd);
|
||||
}
|
||||
else if(p.v === undefined) return "";
|
||||
else p.w = SSF_general(p.v,_ssfopts);
|
||||
}
|
||||
else if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v),_ssfopts);
|
||||
else if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v, !!date1904),_ssfopts);
|
||||
else p.w = SSF_format(fmtid,p.v,_ssfopts);
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
if(!opts.cellStyles) return;
|
||||
|
@ -55,7 +55,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
|
||||
}
|
||||
|
||||
/* 18.3.1.80 sheetData CT_SheetData ? */
|
||||
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
|
||||
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles, wb);
|
||||
|
||||
/* 18.3.1.2 autoFilter CT_AutoFilter */
|
||||
var afilter = data2.match(afregex);
|
||||
@ -76,6 +76,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
|
||||
if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));
|
||||
|
||||
/* legacyDrawing */
|
||||
var m;
|
||||
if((m = data2.match(/legacyDrawing r:id="(.*?)"/))) s['!legrel'] = m[1];
|
||||
|
||||
if(opts && opts.nodim) refguess.s.c = refguess.s.r = 0;
|
||||
@ -261,7 +262,7 @@ function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
|
||||
return writextag("sheetViews", writextag("sheetView", null, sview), {});
|
||||
}
|
||||
|
||||
function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string*/ {
|
||||
function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb, date1904)/*:string*/ {
|
||||
if(cell.c) ws['!comments'].push([ref, cell.c]);
|
||||
if((cell.v === undefined || cell.t === "z" && !(opts||{}).sheetStubs) && typeof cell.f !== "string" && typeof cell.z == "undefined") return "";
|
||||
var vv = "";
|
||||
@ -274,11 +275,14 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string
|
||||
else vv = ''+cell.v; break;
|
||||
case 'e': vv = BErr[cell.v]; break;
|
||||
case 'd':
|
||||
if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
|
||||
else {
|
||||
if(opts && opts.cellDates) {
|
||||
var _vv = parseDate(cell.v, date1904);
|
||||
vv = _vv.toISOString();
|
||||
if(_vv.getUTCFullYear() < 1900) vv = vv.slice(vv.indexOf("T") + 1).replace("Z","");
|
||||
} else {
|
||||
cell = dup(cell);
|
||||
cell.t = 'n';
|
||||
vv = ''+(cell.v = datenum(parseDate(cell.v)));
|
||||
vv = ''+(cell.v = datenum(parseDate(cell.v, date1904), date1904));
|
||||
}
|
||||
if(typeof cell.z === 'undefined') cell.z = table_fmt[14];
|
||||
break;
|
||||
@ -321,7 +325,7 @@ var parse_ws_xml_data = /*#__PURE__*/(function() {
|
||||
var refregex = /ref=["']([^"']*)["']/;
|
||||
var match_v = matchtag("v"), match_f = matchtag("f");
|
||||
|
||||
return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles) {
|
||||
return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles, wb) {
|
||||
var ri = 0, x = "", cells/*:Array<string>*/ = [], cref/*:?Array<string>*/ = [], idx=0, i=0, cc=0, d="", p/*:any*/;
|
||||
var tag, tagr = 0, tagc = 0;
|
||||
var sstr, ftag;
|
||||
@ -332,6 +336,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
|
||||
var dense = s["!data"] != null;
|
||||
var rows/*:Array<RowInfo>*/ = [], rowobj = {}, rowrite = false;
|
||||
var sheetStubs = !!opts.sheetStubs;
|
||||
var date1904 = !!((wb||{}).WBProps||{}).date1904;
|
||||
for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
|
||||
x = marr[mt].trim();
|
||||
var xlen = x.length;
|
||||
@ -476,8 +481,8 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
|
||||
break;
|
||||
case 'b': p.v = parsexmlbool(p.v); break;
|
||||
case 'd':
|
||||
if(opts.cellDates) p.v = parseDate(p.v, 1);
|
||||
else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; }
|
||||
if(opts.cellDates) p.v = parseDate(p.v, date1904);
|
||||
else { p.v = datenum(parseDate(p.v, date1904), date1904); p.t = 'n'; }
|
||||
break;
|
||||
/* error string in .w, number in .v */
|
||||
case 'e':
|
||||
@ -496,8 +501,8 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
|
||||
}
|
||||
}
|
||||
}
|
||||
safe_format(p, fmtid, fillid, opts, themes, styles);
|
||||
if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.t = 'd'; p.v = numdate(p.v); }
|
||||
safe_format(p, fmtid, fillid, opts, themes, styles, date1904);
|
||||
if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.v = numdate(p.v + (date1904 ? 1462 : 0)); p.t = typeof p.v == "number" ? 'n' : 'd'; }
|
||||
if(tag.cm && opts.xlmeta) {
|
||||
var cm = (opts.xlmeta.Cell||[])[+tag.cm-1];
|
||||
if(cm && cm.type == 'XLDAPR') p.D = true;
|
||||
@ -522,6 +527,7 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
|
||||
var o/*:Array<string>*/ = [], r/*:Array<string>*/ = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols/*:Array<string>*/ = [], R=0, C=0, rows = ws['!rows'];
|
||||
var dense = ws["!data"] != null;
|
||||
var params = ({r:rr}/*:any*/), row/*:RowInfo*/, height = -1;
|
||||
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
|
||||
for(R = range.s.r; R <= range.e.r; ++R) {
|
||||
r = [];
|
||||
@ -530,7 +536,7 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
|
||||
ref = cols[C] + rr;
|
||||
var _cell = dense ? (ws["!data"][R]||[])[C]: ws[ref];
|
||||
if(_cell === undefined) continue;
|
||||
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
|
||||
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb, date1904)) != null) r.push(cell);
|
||||
}
|
||||
if(r.length > 0 || (rows && rows[R])) {
|
||||
params = ({r:rr}/*:any*/);
|
||||
|
@ -542,6 +542,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
|
||||
XLSBRecordEnum[0x0010] = { n:"BrtShortReal", f:parse_BrtShortReal };
|
||||
|
||||
var cm, vm;
|
||||
var date1904 = 1462 * +!!((wb||{}).WBProps||{}).date1904;
|
||||
|
||||
recordhopper(data, function ws_parse(val, RR, RT) {
|
||||
if(end) return;
|
||||
@ -585,7 +586,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
|
||||
case 'str': p.t = 's'; p.v = val[1]; break;
|
||||
case 'is': p.t = 's'; p.v = val[1].t; break;
|
||||
}
|
||||
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
|
||||
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles, date1904>0);
|
||||
C = val[0].c == -1 ? C + 1 : val[0].c;
|
||||
if(opts.dense) { if(!s["!data"][R]) s["!data"][R] = []; s["!data"][R][C] = p; }
|
||||
else s[encode_col(C) + rr] = p;
|
||||
@ -606,7 +607,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
|
||||
if(refguess.e.r < row.r) refguess.e.r = row.r;
|
||||
if(refguess.e.c < C) refguess.e.c = C;
|
||||
if(opts.cellDates && cf && p.t == 'n' && fmt_is_date(table_fmt[cf.numFmtId])) {
|
||||
var _d = SSF_parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
|
||||
var _d = SSF_parse_date_code(p.v + date1904); if(_d) { p.t = 'd'; p.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
|
||||
}
|
||||
if(cm) {
|
||||
if(cm.type == 'XLDAPR') p.D = true;
|
||||
@ -809,7 +810,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
|
||||
}
|
||||
|
||||
/* TODO: something useful -- this is a stub */
|
||||
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/)/*:boolean*/ {
|
||||
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/, date1904/*:boolean*/)/*:boolean*/ {
|
||||
var o/*:any*/ = ({r:R, c:C}/*:any*/);
|
||||
if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
|
||||
if(cell.v === undefined) return false;
|
||||
@ -819,7 +820,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
|
||||
case 'd': // no BrtCellDate :(
|
||||
cell = dup(cell);
|
||||
cell.z = cell.z || table_fmt[14];
|
||||
cell.v = datenum(parseDate(cell.v)); cell.t = 'n';
|
||||
cell.v = datenum(parseDate(cell.v, date1904), date1904); cell.t = 'n';
|
||||
break;
|
||||
/* falls through */
|
||||
case 'n': case 'e': vv = ''+cell.v; break;
|
||||
@ -872,8 +873,9 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
|
||||
return true;
|
||||
}
|
||||
|
||||
function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
|
||||
function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols/*:Array<string>*/ = [];
|
||||
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
write_record(ba, 0x0091 /* BrtBeginSheetData */);
|
||||
var dense = ws["!data"] != null;
|
||||
var cap = range.e.r;
|
||||
@ -891,7 +893,7 @@ function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Work
|
||||
var cell = dense ? (ws["!data"][R]||[])[C] : ws[ref];
|
||||
if(!cell) { last_seen = false; continue; }
|
||||
/* write cell */
|
||||
last_seen = write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen);
|
||||
last_seen = write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen, date1904);
|
||||
}
|
||||
}
|
||||
write_record(ba, 0x0092 /* BrtEndSheetData */);
|
||||
|
@ -40,10 +40,10 @@ function xlml_parsexmltagobj(tag/*:string*/) {
|
||||
/* map from xlml named formats to SSF TODO: localize */
|
||||
var XLMLFormatMap/*: {[string]:string}*/;
|
||||
|
||||
function xlml_format(format, value)/*:string*/ {
|
||||
function xlml_format(format, value, date1904)/*:string*/ {
|
||||
var fmt = XLMLFormatMap[format] || unescapexml(format);
|
||||
if(fmt === "General") return SSF_general(value);
|
||||
return SSF_format(fmt, value);
|
||||
return SSF_format(fmt, value, {date1904: !!date1904});
|
||||
}
|
||||
|
||||
function xlml_set_custprop(Custprops, key, cp, val/*:string*/) {
|
||||
@ -59,7 +59,7 @@ function xlml_set_custprop(Custprops, key, cp, val/*:string*/) {
|
||||
Custprops[unescapexml(key)] = oval;
|
||||
}
|
||||
|
||||
function safe_format_xlml(cell/*:Cell*/, nf, o) {
|
||||
function safe_format_xlml(cell/*:Cell*/, nf, o, date1904) {
|
||||
if(cell.t === 'z') return;
|
||||
if(!o || o.cellText !== false) try {
|
||||
if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
|
||||
@ -70,13 +70,13 @@ function safe_format_xlml(cell/*:Cell*/, nf, o) {
|
||||
}
|
||||
else cell.w = SSF_general(cell.v);
|
||||
}
|
||||
else cell.w = xlml_format(nf||"General", cell.v);
|
||||
else cell.w = xlml_format(nf||"General", cell.v, date1904);
|
||||
} catch(e) { if(o.WTF) throw e; }
|
||||
try {
|
||||
var z = XLMLFormatMap[nf]||nf||"General";
|
||||
if(o.cellNF) cell.z = z;
|
||||
if(o.cellDates && cell.t == 'n' && fmt_is_date(z)) {
|
||||
var _d = SSF_parse_date_code(cell.v); if(_d) { cell.t = 'd'; cell.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
|
||||
var _d = SSF_parse_date_code(cell.v + (date1904 ? 1462 : 0)); if(_d) { cell.t = 'd'; cell.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
|
||||
}
|
||||
} catch(e) { if(o.WTF) throw e; }
|
||||
}
|
||||
@ -92,7 +92,7 @@ function process_style_xlml(styles, stag, opts) {
|
||||
}
|
||||
|
||||
/* TODO: there must exist some form of OSP-blessed spec */
|
||||
function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o) {
|
||||
function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o, date1904) {
|
||||
var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
|
||||
var interiors = [];
|
||||
var i = 0;
|
||||
@ -115,9 +115,8 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
|
||||
break;
|
||||
case 'DateTime':
|
||||
if(xml.slice(-1) != "Z") xml += "Z";
|
||||
cell.v = (parseDate(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
|
||||
cell.v = datenum(parseDate(xml, date1904), date1904);
|
||||
if(cell.v !== cell.v) cell.v = unescapexml(xml);
|
||||
else if(cell.v<60) cell.v = cell.v -1;
|
||||
if(!nf || nf == "General") nf = "yyyy-mm-dd";
|
||||
/* falls through */
|
||||
case 'Number':
|
||||
@ -130,7 +129,7 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
|
||||
else { cell.t = 's'; cell.v = xlml_fixstr(ss||xml); }
|
||||
break;
|
||||
}
|
||||
safe_format_xlml(cell, nf, o);
|
||||
safe_format_xlml(cell, nf, o, date1904);
|
||||
if(o.cellFormula !== false) {
|
||||
if(cell.Formula) {
|
||||
var fstr = unescapexml(cell.Formula);
|
||||
@ -232,7 +231,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
|
||||
break;
|
||||
}
|
||||
if(state[state.length-1][1]) break;
|
||||
if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]==/*"Comment"*/"comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts);
|
||||
if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]==/*"Comment"*/"comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts, Workbook.WBProps.date1904);
|
||||
else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; }
|
||||
break;
|
||||
case 'cell' /*case 'Cell'*/:
|
||||
|
@ -77,7 +77,7 @@ function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
|
||||
var fmtid = 0;
|
||||
try {
|
||||
fmtid = p.z || p.XF.numFmtId || 0;
|
||||
if(opts.cellNF) p.z = table_fmt[fmtid];
|
||||
if(opts.cellNF && p.z == null) p.z = table_fmt[fmtid];
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
if(!opts || opts.cellText !== false) try {
|
||||
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
|
||||
@ -91,7 +91,7 @@ function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
|
||||
else p.w = SSF_format(fmtid,p.v, {date1904:!!date1904, dateNF: opts && opts.dateNF});
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
if(opts.cellDates && fmtid && p.t == 'n' && fmt_is_date(table_fmt[fmtid] || String(fmtid))) {
|
||||
var _d = SSF_parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
|
||||
var _d = SSF_parse_date_code(p.v + (date1904 ? 1462 : 0)); if(_d) { p.t = 'd'; p.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,6 +119,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
var XFs = []; /* XF records */
|
||||
var palette/*:Array<[number, number, number]>*/ = [];
|
||||
var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false}, Views:[{}] }/*:any*/), wsprops = {};
|
||||
var biff4w = false;
|
||||
var get_rgb = function getrgb(icv/*:number*/)/*:[number, number, number]*/ {
|
||||
if(icv < 8) return XLSIcv[icv];
|
||||
if(icv < 64) return palette[icv-8] || XLSIcv[icv];
|
||||
@ -134,7 +135,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; }
|
||||
};
|
||||
var addcell = function addcell(cell/*:any*/, line/*:any*/, options/*:any*/) {
|
||||
if(file_depth > 1) return;
|
||||
if(!biff4w && file_depth > 1) return;
|
||||
if(options.sheetRows && cell.r >= options.sheetRows) return;
|
||||
if(options.cellStyles && line.XF && line.XF.data) process_cell_style(cell, line, options);
|
||||
delete line.ixfe; delete line.XF;
|
||||
@ -265,6 +266,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(!val.fBelow) (out["!outline"] || (out["!outline"] = {})).above = true;
|
||||
if(!val.fRight) (out["!outline"] || (out["!outline"] = {})).left = true;
|
||||
break; // TODO
|
||||
case 0x0043: /* BIFF2XF */ case 0x0243: /* BIFF3XF */ case 0x0443: /* BIFF4XF */
|
||||
case 0x00e0 /* XF */:
|
||||
XFs.push(val); break;
|
||||
case 0x01ae /* SupBook */:
|
||||
@ -299,11 +301,11 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
case 0x0012 /* Protect */: out["!protect"] = val; break; /* for sheet or book */
|
||||
case 0x0013 /* Password */: if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
|
||||
case 0x0085 /* BoundSheet8 */: {
|
||||
Directory[val.pos] = val;
|
||||
Directory[opts.biff == 4 ? opts.snames.length : val.pos] = val;
|
||||
opts.snames.push(val.name);
|
||||
} break;
|
||||
case 0x000a /* EOF */: {
|
||||
if(--file_depth) break;
|
||||
if(--file_depth ? !biff4w : biff4w) break;
|
||||
if(range.e) {
|
||||
if(range.e.r > 0 && range.e.c > 0) {
|
||||
range.e.r--; range.e.c--;
|
||||
@ -342,13 +344,15 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
}[val.BIFFVer] || 8;
|
||||
opts.biffguess = val.BIFFVer == 0;
|
||||
if(val.BIFFVer == 0 && val.dt == 0x1000) { opts.biff = 5; seen_codepage = true; set_cp(opts.codepage = 28591); }
|
||||
if(opts.biff == 4 && val.dt & 0x100) biff4w = true;
|
||||
if(opts.biff == 8 && val.BIFFVer == 0 && val.dt == 16) opts.biff = 2;
|
||||
if(file_depth++) break;
|
||||
if(file_depth++ && !biff4w) break;
|
||||
out = ({}/*:any*/); if(options.dense) out["!data"] = [];
|
||||
|
||||
if(opts.biff < 8 && !seen_codepage) { seen_codepage = true; set_cp(opts.codepage = options.codepage || 1252); }
|
||||
|
||||
if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) {
|
||||
if(opts.biff == 4 && biff4w) {
|
||||
cur_sheet = (Directory[opts.snames.indexOf(cur_sheet)+1] || {name:""}).name;
|
||||
} else if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) {
|
||||
if(cur_sheet === "") cur_sheet = "Sheet1";
|
||||
range = {s:{r:0,c:0},e:{r:0,c:0}};
|
||||
/* fake BoundSheet8 */
|
||||
@ -369,19 +373,19 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
case 0x0203 /* Number */: case 0x0003 /* BIFF2NUM */: case 0x0002 /* BIFF2INT */: {
|
||||
if(out["!type"] == "chart") if(options.dense ? (out["!data"][val.r]||[])[val.c]: out[encode_col(val.c) + encode_row(val.r)]) ++val.c;
|
||||
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe]||{}, v:val.val, t:'n'}/*:any*/);
|
||||
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
} break;
|
||||
case 0x0005: case 0x0205 /* BoolErr */: {
|
||||
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t}/*:any*/);
|
||||
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
} break;
|
||||
case 0x027e /* RK */: {
|
||||
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'}/*:any*/);
|
||||
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
} break;
|
||||
@ -389,7 +393,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
for(var j = val.c; j <= val.C; ++j) {
|
||||
var ixfe = val.rkrec[j-val.c][0];
|
||||
temp_val= ({ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'}/*:any*/);
|
||||
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:j, r:val.r}, temp_val, options);
|
||||
}
|
||||
@ -407,7 +411,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
else temp_val.F = ((options.dense ? (out["!data"][_fr]||[])[_fc]: out[_fe]) || {}).F;
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(val.cell, temp_val, options);
|
||||
last_formula = val;
|
||||
@ -420,7 +424,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(options.cellFormula) {
|
||||
temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
}
|
||||
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(last_formula.cell, temp_val, options);
|
||||
last_formula = null;
|
||||
@ -451,13 +455,13 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
temp_val=make_cell(sst[val.isst].t, val.ixfe, 's');
|
||||
if(sst[val.isst].h) temp_val.h = sst[val.isst].h;
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
break;
|
||||
case 0x0201 /* Blank */: if(options.sheetStubs) {
|
||||
temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'}/*:any*/);
|
||||
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
} break;
|
||||
@ -465,7 +469,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
for(var _j = val.c; _j <= val.C; ++_j) {
|
||||
var _ixfe = val.ixfe[_j-val.c];
|
||||
temp_val= ({ixfe:_ixfe, XF:XFs[_ixfe], t:'z'}/*:any*/);
|
||||
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:_j, r:val.r}, temp_val, options);
|
||||
}
|
||||
@ -474,7 +478,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
case 0x0204 /* Label */: case 0x0004 /* BIFF2STR */:
|
||||
temp_val=make_cell(val.val, val.ixfe, 's');
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
break;
|
||||
@ -486,7 +490,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
sst = val;
|
||||
} break;
|
||||
case 0x041e /* Format */: { /* val = [id, fmt] */
|
||||
if(opts.biff == 4) {
|
||||
if(opts.biff >= 3 && opts.biff <= 4) {
|
||||
BIFF2FmtTable[BIFF2Fmt++] = val[1];
|
||||
for(var b4idx = 0; b4idx < BIFF2Fmt + 163; ++b4idx) if(table_fmt[b4idx] == val[1]) break;
|
||||
if(b4idx >= 163) SSF__load(val[1], BIFF2Fmt + 163);
|
||||
|
@ -1221,7 +1221,7 @@ var XLSRecordEnum = {
|
||||
/*::[*/0x0002/*::]*/: { /* n:"BIFF2INT", */ f:parse_BIFF2INT },
|
||||
/*::[*/0x0003/*::]*/: { /* n:"BIFF2NUM", */ f:parse_BIFF2NUM },
|
||||
/*::[*/0x0004/*::]*/: { /* n:"BIFF2STR", */ f:parse_BIFF2STR },
|
||||
/*::[*/0x0005/*::]*/: { /* n:"BoolErr", */ f:parse_BoolErr },
|
||||
/*::[*/0x0005/*::]*/: { /* n:"BIFF2BOOLERR", */ f:parse_BIFF2BOOLERR },
|
||||
/*::[*/0x0007/*::]*/: { /* n:"String", */ f:parse_BIFF2STRING },
|
||||
/*::[*/0x0008/*::]*/: { /* n:"BIFF2ROW", */ },
|
||||
/*::[*/0x0009/*::]*/: { /* n:"BOF", */ f:parse_BOF },
|
||||
@ -1260,7 +1260,7 @@ var XLSRecordEnum = {
|
||||
|
||||
/* - - - */
|
||||
/*::[*/0x0034/*::]*/: { /* n:"DDEObjName", */ },
|
||||
/*::[*/0x0043/*::]*/: { /* n:"BIFF2XF", */ },
|
||||
/*::[*/0x0043/*::]*/: { /* n:"BIFF2XF", */ f:parse_BIFF2XF },
|
||||
/*::[*/0x0044/*::]*/: { /* n:"BIFF2XFINDEX", */ f:parseuint16 },
|
||||
/*::[*/0x0045/*::]*/: { /* n:"BIFF2FONTCLR", */ },
|
||||
/*::[*/0x0056/*::]*/: { /* n:"BIFF4FMTCNT", */ }, /* 16-bit cnt, similar to BIFF2 */
|
||||
@ -1272,7 +1272,7 @@ var XLSRecordEnum = {
|
||||
// 0x8A
|
||||
// 0x8B LH: alternate menu key flag (BIFF3/4)
|
||||
// 0x8E
|
||||
// 0x8F
|
||||
/*::[*/0x008F/*::]*/: { /* n:"BIFF4SheetInfo", */ f:parse_BIFF4SheetInfo },
|
||||
/*::[*/0x0091/*::]*/: { /* n:"Sub", */ },
|
||||
// 0x93 STYLE
|
||||
/*::[*/0x0094/*::]*/: { /* n:"LHRecord", */ },
|
||||
@ -1298,10 +1298,10 @@ var XLSRecordEnum = {
|
||||
/*::[*/0x0218/*::]*/: { /* n:"Lbl", */ f:parse_Lbl },
|
||||
/*::[*/0x0223/*::]*/: { /* n:"ExternName", */ f:parse_ExternName },
|
||||
/*::[*/0x0231/*::]*/: { /* n:"Font", */ },
|
||||
/*::[*/0x0243/*::]*/: { /* n:"BIFF3XF", */ },
|
||||
/*::[*/0x0243/*::]*/: { /* n:"BIFF3XF", */ f:parse_BIFF3XF },
|
||||
/*::[*/0x0406/*::]*/: { /* n:"Formula", */ f:parse_Formula },
|
||||
/*::[*/0x0409/*::]*/: { /* n:"BOF", */ f:parse_BOF },
|
||||
/*::[*/0x0443/*::]*/: { /* n:"BIFF4XF", */ },
|
||||
/*::[*/0x0443/*::]*/: { /* n:"BIFF4XF", */ f:parse_BIFF4XF },
|
||||
/*::[*/0x086d/*::]*/: { /* n:"FeatInfo", */ },
|
||||
/*::[*/0x0873/*::]*/: { /* n:"FeatInfo11", */ },
|
||||
/*::[*/0x0881/*::]*/: { /* n:"SXAddl12", */ },
|
||||
|
@ -31,16 +31,7 @@ function write_biff_continue(ba/*:BufArray*/, type/*:number*/, payload, length/*
|
||||
}
|
||||
}
|
||||
|
||||
function write_BIFF2Cell(out, r/*:number*/, c/*:number*/) {
|
||||
if(!out) out = new_buf(7);
|
||||
out.write_shift(2, r);
|
||||
out.write_shift(2, c);
|
||||
out.write_shift(2, 0);
|
||||
out.write_shift(1, 0);
|
||||
return out;
|
||||
}
|
||||
|
||||
function write_BIFF2BERR(r/*:number*/, c/*:number*/, val, t/*:?string*/) {
|
||||
function write_BIFF2BERR(r/*:number*/, c/*:number*/, val, t/*:string*/) {
|
||||
var out = new_buf(9);
|
||||
write_BIFF2Cell(out, r, c);
|
||||
write_Bes(val, t || 'b', out);
|
||||
@ -67,29 +58,48 @@ function write_comments_biff2(ba/*:BufArray*/, comments/*:Array<[Comment[], numb
|
||||
});
|
||||
}
|
||||
|
||||
function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*//*::, opts*/) {
|
||||
/* TODO: BIFF3/4 use different records -- see comments*/
|
||||
function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/) {
|
||||
var ifmt = 0;
|
||||
if(cell.z != null) {
|
||||
ifmt = opts._BIFF2FmtTable.indexOf(cell.z);
|
||||
if(ifmt == -1) { opts._BIFF2FmtTable.push(cell.z); ifmt = opts._BIFF2FmtTable.length - 1; }
|
||||
}
|
||||
var ixfe = 0;
|
||||
if(cell.z != null) {
|
||||
for(; ixfe < opts.cellXfs.length; ++ixfe) if(opts.cellXfs[ixfe].numFmtId == ifmt) break;
|
||||
if(ixfe == opts.cellXfs.length) opts.cellXfs.push({numFmtId: ifmt});
|
||||
}
|
||||
if(cell.v != null) switch(cell.t) {
|
||||
case 'd': case 'n':
|
||||
var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
|
||||
if((v == (v|0)) && (v >= 0) && (v < 65536))
|
||||
write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v));
|
||||
var v = cell.t == 'd' ? datenum(parseDate(cell.v, date1904), date1904) : cell.v;
|
||||
if(opts.biff == 2 && (v == (v|0)) && (v >= 0) && (v < 65536))
|
||||
// 0x027E (RK) in BIFF3/4
|
||||
write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v, ixfe, ifmt));
|
||||
else if(isNaN(v))
|
||||
// 0x0205 in BIFF3/4
|
||||
write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x24, "e")); // #NUM!
|
||||
else if(!isFinite(v))
|
||||
// 0x0205 in BIFF3/4
|
||||
write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x07, "e")); // #DIV/0!
|
||||
else
|
||||
write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v));
|
||||
// 0x0203 in BIFF3/4
|
||||
write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v, ixfe, ifmt));
|
||||
return;
|
||||
case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
|
||||
case 'b': case 'e':
|
||||
// 0x0205 in BIFF3/4
|
||||
write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
|
||||
/* TODO: codepage, sst */
|
||||
case 's': case 'str':
|
||||
// 0x0204 in BIFF3/4
|
||||
write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v == null ? "" : String(cell.v).slice(0,255)));
|
||||
return;
|
||||
}
|
||||
// 0x0201 in BIFF3/4
|
||||
write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
|
||||
}
|
||||
|
||||
function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
|
||||
function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
var dense = ws["!data"] != null;
|
||||
var range = safe_decode_range(ws['!ref'] || "A1"), ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
|
||||
if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
|
||||
@ -97,7 +107,9 @@ function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/
|
||||
range.e.c = Math.min(range.e.c, 0xFF);
|
||||
range.e.r = Math.min(range.e.c, 0x3FFF);
|
||||
}
|
||||
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
var row = [], comments = [];
|
||||
/* TODO: 0x0000 / 0x0200 dimensions? */
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
|
||||
for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
if(dense) row = ws["!data"][R] || [];
|
||||
@ -106,7 +118,7 @@ function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/
|
||||
var cell = dense ? row[C] : ws[cols[C] + rr];
|
||||
if(!cell) continue;
|
||||
/* write cell */
|
||||
write_ws_biff2_cell(ba, cell, R, C, opts);
|
||||
write_ws_biff2_cell(ba, cell, R, C, opts, date1904);
|
||||
if(cell.c) comments.push([cell.c, R, C]);
|
||||
}
|
||||
}
|
||||
@ -119,14 +131,32 @@ function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/
|
||||
/* Based on test files */
|
||||
function write_biff2_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
|
||||
var o = opts || {};
|
||||
|
||||
var ba = buf_array();
|
||||
var idx = 0;
|
||||
for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i;
|
||||
if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
|
||||
write_biff_rec(ba, (o.biff == 4 ? 0x0409 : (o.biff == 3 ? 0x0209 : 0x0009)), write_BOF(wb, 0x10, o));
|
||||
/* ... */
|
||||
write_ws_biff2(ba, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
|
||||
/* ... */
|
||||
if(((wb.Workbook||{}).WBProps||{}).date1904) write_biff_rec(ba, 0x0022, writebool(true));
|
||||
o.cellXfs = [{numFmtId: 0}];
|
||||
o._BIFF2FmtTable/*:Array<string>*/ = ["General"]; o._Fonts = [];
|
||||
var body = buf_array();
|
||||
write_ws_biff2(body, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
|
||||
|
||||
o._BIFF2FmtTable.forEach(function(f) {
|
||||
if(o.biff <= 3) write_biff_rec(ba, 0x001E, write_BIFF2Format(f));
|
||||
else write_biff_rec(ba, 0x041E, write_BIFF4Format(f));
|
||||
});
|
||||
o.cellXfs.forEach(function(xf) {
|
||||
switch(o.biff) {
|
||||
case 2: write_biff_rec(ba, 0x0043, write_BIFF2XF(xf)); break;
|
||||
case 3: write_biff_rec(ba, 0x0243, write_BIFF3XF(xf)); break;
|
||||
case 4: write_biff_rec(ba, 0x0443, write_BIFF4XF(xf)); break;
|
||||
}
|
||||
});
|
||||
delete o._BIFF2FmtTable; delete o.cellXfs; delete o._Fonts;
|
||||
|
||||
ba.push(body.end());
|
||||
write_biff_rec(ba, 0x000A);
|
||||
return ba.end();
|
||||
}
|
||||
@ -147,7 +177,7 @@ function write_MsoDrawingGroup() {
|
||||
{
|
||||
buf.write_shift(4, b8oid);
|
||||
buf.write_shift(4, b8ocnts.length+1);
|
||||
buf.write_shift(4, b8ocnts.reduce(function(acc,x) { return acc+x[1]; }, 0));
|
||||
var acc = 0; for(var i = 0; i < b8ocnts.length; ++i) acc += (b8ocnts[i] && b8ocnts[i][1] || 0); buf.write_shift(4, acc);
|
||||
buf.write_shift(4, b8ocnts.length);
|
||||
}
|
||||
/* 2.2.46 OfficeArtIDCL + */
|
||||
@ -185,7 +215,7 @@ function write_comments_biff8(ba/*:BufArray*/, comments/*:Array<[Comment[], numb
|
||||
var _oasc;
|
||||
comments.forEach(function(c, ci) {
|
||||
var author = "";
|
||||
var text = c[0].map(function(t) { if(t.a && !author) author = t.a; return t.t }).join("");
|
||||
var text = c[0].map(function(t) { if(t.a && !author) author = t.a; return t.t; }).join("");
|
||||
++b8oid;
|
||||
|
||||
/* 2.2.14 OfficeArtSpContainer */
|
||||
@ -336,7 +366,7 @@ function write_comments_biff8(ba/*:BufArray*/, comments/*:Array<[Comment[], numb
|
||||
/* [MS-ODRAW] 2.2.13 OfficeArtDgContainer */
|
||||
{
|
||||
var hdr = new_buf(80);
|
||||
hdr.write_shift(2, 0x0F)
|
||||
hdr.write_shift(2, 0x0F);
|
||||
hdr.write_shift(2, 0xF002);
|
||||
hdr.write_shift(4, sz + hdr.length - 8);
|
||||
/* [MS-ODRAW] 2.2.49 OfficeArtFDG */
|
||||
@ -443,7 +473,7 @@ function write_ws_cols_biff8(ba, cols) {
|
||||
});
|
||||
}
|
||||
|
||||
function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) {
|
||||
function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/) {
|
||||
var os = 16 + get_cell_style(opts.cellXfs, cell, opts);
|
||||
if(cell.v == null && !cell.bf) {
|
||||
write_biff_rec(ba, 0x0201 /* Blank */, write_XLSCell(R, C, os));
|
||||
@ -452,7 +482,7 @@ function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n
|
||||
if(cell.bf) write_biff_rec(ba, 0x0006 /* Formula */, write_Formula(cell, R, C, opts, os));
|
||||
else switch(cell.t) {
|
||||
case 'd': case 'n':
|
||||
var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
|
||||
var v = cell.t == 'd' ? datenum(parseDate(cell.v, date1904), date1904) : cell.v;
|
||||
if(isNaN(v)) write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, 0x24, os, opts, "e")); // #NUM!
|
||||
else if(!isFinite(v)) write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, 0x07, os, opts, "e")); // #DIV/0!
|
||||
/* TODO: emit RK as appropriate */
|
||||
@ -513,6 +543,7 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
write_biff_rec(ba, 0x0200 /* Dimensions */, write_Dimensions(range, opts));
|
||||
/* ... */
|
||||
|
||||
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
if(b8) ws['!links'] = [];
|
||||
var comments = [];
|
||||
var row = [];
|
||||
@ -525,7 +556,7 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
var cell = dense ? row[C] : ws[ref];
|
||||
if(!cell) continue;
|
||||
/* write cell */
|
||||
write_ws_biff8_cell(ba, cell, R, C, opts);
|
||||
write_ws_biff8_cell(ba, cell, R, C, opts, date1904);
|
||||
if(b8 && cell.l) ws['!links'].push([ref, cell.l]);
|
||||
if(cell.c) comments.push([cell.c, R, C]);
|
||||
}
|
||||
|
@ -45,9 +45,11 @@ function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ {
|
||||
else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)};
|
||||
else if(!isNaN(fuzzydate(m).getDate())) {
|
||||
o = ({t:'d', v:parseDate(m)}/*:any*/);
|
||||
if(opts.UTC === false) o.v = utc_to_local(o.v);
|
||||
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
|
||||
o.z = opts.dateNF || table_fmt[14];
|
||||
}
|
||||
if(o.cellText !== false) o.w = m;
|
||||
if(dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = o; }
|
||||
else ws[encode_cell({r:R, c:C})] = o;
|
||||
C += CS;
|
||||
@ -81,7 +83,8 @@ function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HT
|
||||
if(o.editable) w = '<span contenteditable="true">' + w + '</span>';
|
||||
else if(cell) {
|
||||
sp["data-t"] = cell && cell.t || 'z';
|
||||
if(cell.v != null) sp["data-v"] = cell.v;
|
||||
// note: data-v is unaffected by the timezone interpretation
|
||||
if(cell.v != null) sp["data-v"] = cell.v instanceof Date ? cell.v.toISOString() : cell.v;
|
||||
if(cell.z != null) sp["data-z"] = cell.z;
|
||||
if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + escapehtml(cell.l.Target) +'">' + w + '</a>';
|
||||
}
|
||||
@ -187,6 +190,7 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
|
||||
else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
|
||||
else if(!isNaN(fuzzydate(v).getDate())) {
|
||||
o = ({t:'d', v:parseDate(v)}/*:any*/);
|
||||
if(opts.UTC) o.v = local_to_utc(o.v);
|
||||
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
|
||||
o.z = opts.dateNF || table_fmt[14];
|
||||
}
|
||||
|
@ -263,7 +263,6 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
var creator = "", creatoridx = 0;
|
||||
var isstub = false, intable = false;
|
||||
var i = 0;
|
||||
var baddate = 0;
|
||||
xlmlregex.lastIndex = 0;
|
||||
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
|
||||
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
|
||||
@ -370,19 +369,23 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
/* 19.675.2 table:number-columns-repeated */
|
||||
if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10);
|
||||
|
||||
/* 19.385 office:value-type */
|
||||
/* 19.385 office:value-type TODO: verify ODS and UOS */
|
||||
switch(q.t) {
|
||||
case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']) || (+ctag['boolean-value'] >= 1); break;
|
||||
case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break;
|
||||
case 'float': q.t = 'n'; q.v = parseFloat(ctag.value);
|
||||
if(opts.cellDates && q.z && fmt_is_date(q.z)) { q.v = numdate(q.v + (WB.WBProps.date1904 ? 1462 : 0)); q.t = typeof q.v == "number" ? 'n' : 'd'; }
|
||||
break;
|
||||
case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break;
|
||||
case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break;
|
||||
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']);
|
||||
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904) - baddate; }
|
||||
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value'], WB.WBProps.date1904);
|
||||
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904); }
|
||||
if(!q.z) q.z = 'm/d/yy'; break;
|
||||
/* NOTE: for `time`, Excel ODS export incorrectly uses durations relative to 1900 epoch even if 1904 is specified */
|
||||
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400;
|
||||
if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); }
|
||||
if(opts.cellDates) { q.v = numdate(q.v); q.t = typeof q.v == "number" ? 'n' : 'd'; }
|
||||
if(!q.z) q.z = 'HH:MM:SS'; break;
|
||||
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
|
||||
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']);
|
||||
break;
|
||||
default:
|
||||
if(q.t === 'string' || q.t === 'text' || !q.t) {
|
||||
q.t = 's';
|
||||
@ -579,9 +582,7 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
case 'null-date': // 9.4.2 <table:null-date>
|
||||
tag = parsexmltag(Rn[0], false);
|
||||
switch(tag["date-value"]) {
|
||||
case "1904-01-01": WB.WBProps.date1904 = true;
|
||||
/* falls through */
|
||||
case "1900-01-01": baddate = 0;
|
||||
case "1904-01-01": WB.WBProps.date1904 = true; break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -99,7 +99,9 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
|
||||
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
|
||||
payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
|
||||
break;
|
||||
case '/': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
case '\\': c = nf[++i];
|
||||
payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
default: console.error("unrecognized character " + c + " in ODF format " + nf);
|
||||
}
|
||||
if(!has_time) break j;
|
||||
@ -126,7 +128,7 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
|
||||
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
|
||||
payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
|
||||
break;
|
||||
case '/': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
case "a":
|
||||
if(nf.slice(i, i+3).toLowerCase() == "a/p") { payload += '<number:am-pm/>'; i += 2; break; } // Note: ODF does not support A/P
|
||||
if(nf.slice(i, i+5).toLowerCase() == "am/pm") { payload += '<number:am-pm/>'; i += 4; break; }
|
||||
@ -182,10 +184,15 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
|
||||
}
|
||||
|
||||
function write_names_ods(Names, SheetNames, idx) {
|
||||
var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
|
||||
//var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
|
||||
var scoped = []; for(var namei = 0; namei < Names.length; ++namei) {
|
||||
var name = Names[namei];
|
||||
if(!name) continue;
|
||||
if(name.Sheet == (idx == -1 ? null : idx)) scoped.push(name);
|
||||
}
|
||||
if(!scoped.length) return "";
|
||||
return " <table:named-expressions>\n" + scoped.map(function(name) {
|
||||
var odsref = csf_to_ods_3D(name.Ref);
|
||||
var odsref = (idx == -1 ? "$" : "") + csf_to_ods_3D(name.Ref);
|
||||
return " " + writextag("table:named-range", null, {
|
||||
"table:name": name.Name,
|
||||
"table:cell-range-address": odsref,
|
||||
@ -204,7 +211,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
|
||||
};
|
||||
|
||||
var null_cell_xml = ' <table:table-cell />\n';
|
||||
var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts, nfs)/*:string*/ {
|
||||
var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts, nfs, date1904)/*:string*/ {
|
||||
/* Section 9 Tables */
|
||||
var o/*:Array<string>*/ = [];
|
||||
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="ta1">\n');
|
||||
@ -264,9 +271,9 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
|
||||
ct['office:value-type'] = "string";
|
||||
break;
|
||||
case 'd':
|
||||
textp = (cell.w||(parseDate(cell.v).toISOString()));
|
||||
textp = (cell.w||(parseDate(cell.v, date1904).toISOString()));
|
||||
ct['office:value-type'] = "date";
|
||||
ct['office:date-value'] = (parseDate(cell.v).toISOString());
|
||||
ct['office:date-value'] = (parseDate(cell.v, date1904).toISOString());
|
||||
ct['table:style-name'] = "ce1";
|
||||
break;
|
||||
//case 'e': // TODO: translate to ODS errors
|
||||
@ -436,7 +443,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
|
||||
o.push(' <office:body>\n');
|
||||
o.push(' <office:spreadsheet>\n');
|
||||
if(((wb.Workbook||{}).WBProps||{}).date1904) o.push(' <table:calculation-settings table:case-sensitive="false" table:search-criteria-must-apply-to-whole-cell="true" table:use-wildcards="true" table:use-regular-expressions="false" table:automatic-find-labels="false">\n <table:null-date table:date-value="1904-01-01"/>\n </table:calculation-settings>\n');
|
||||
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs));
|
||||
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs, ((wb.Workbook||{}).WBProps||{}).date1904));
|
||||
if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1));
|
||||
o.push(' </office:spreadsheet>\n');
|
||||
o.push(' </office:body>\n');
|
||||
|
@ -566,10 +566,10 @@ function numbers_format_cell(cell, t, flags, ofmt, nfmt) {
|
||||
cell.w = cell.w.replace(/:(\d\d\d)$/, ".$1");
|
||||
}
|
||||
}
|
||||
function parse_old_storage(buf, lut, v) {
|
||||
function parse_old_storage(buf, lut, v, opts) {
|
||||
var dv = u8_to_dataview(buf);
|
||||
var flags = dv.getUint32(4, true);
|
||||
var ridx = -1, sidx = -1, zidx = -1, ieee = NaN, dt = new Date(2001, 0, 1);
|
||||
var ridx = -1, sidx = -1, zidx = -1, ieee = NaN, dc = 0, dt = new Date(Date.UTC(2001, 0, 1));
|
||||
var doff = v > 1 ? 12 : 8;
|
||||
if (flags & 2) {
|
||||
zidx = dv.getUint32(doff, true);
|
||||
@ -590,7 +590,7 @@ function parse_old_storage(buf, lut, v) {
|
||||
doff += 8;
|
||||
}
|
||||
if (flags & 64) {
|
||||
dt.setTime(dt.getTime() + dv.getFloat64(doff, true) * 1e3);
|
||||
dt.setTime(dt.getTime() + (dc = dv.getFloat64(doff, true)) * 1e3);
|
||||
doff += 8;
|
||||
}
|
||||
if (v > 1) {
|
||||
@ -613,7 +613,12 @@ function parse_old_storage(buf, lut, v) {
|
||||
ret = { t: "s", v: lut.sst[sidx] };
|
||||
break;
|
||||
case 5:
|
||||
{
|
||||
if (opts == null ? void 0 : opts.cellDates)
|
||||
ret = { t: "d", v: dt };
|
||||
else
|
||||
ret = { t: "n", v: dc / 86400 + 35430, z: table_fmt[14] };
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
ret = { t: "b", v: ieee > 0 };
|
||||
@ -644,12 +649,12 @@ function parse_old_storage(buf, lut, v) {
|
||||
ret.v /= 86400;
|
||||
return ret;
|
||||
}
|
||||
function parse_new_storage(buf, lut) {
|
||||
function parse_new_storage(buf, lut, opts) {
|
||||
var dv = u8_to_dataview(buf);
|
||||
var flags = dv.getUint32(4, true);
|
||||
var fields = dv.getUint32(8, true);
|
||||
var doff = 12;
|
||||
var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1), eidx = -1, fidx = -1;
|
||||
var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dc = 0, dt = new Date(Date.UTC(2001, 0, 1)), eidx = -1, fidx = -1;
|
||||
if (fields & 1) {
|
||||
d128 = readDecimal128LE(buf, doff);
|
||||
doff += 16;
|
||||
@ -659,7 +664,7 @@ function parse_new_storage(buf, lut) {
|
||||
doff += 8;
|
||||
}
|
||||
if (fields & 4) {
|
||||
dt.setTime(dt.getTime() + dv.getFloat64(doff, true) * 1e3);
|
||||
dt.setTime(dt.getTime() + (dc = dv.getFloat64(doff, true)) * 1e3);
|
||||
doff += 8;
|
||||
}
|
||||
if (fields & 8) {
|
||||
@ -693,7 +698,12 @@ function parse_new_storage(buf, lut) {
|
||||
ret = { t: "s", v: lut.sst[sidx] };
|
||||
break;
|
||||
case 5:
|
||||
{
|
||||
if (opts == null ? void 0 : opts.cellDates)
|
||||
ret = { t: "d", v: dt };
|
||||
else
|
||||
ret = { t: "n", v: dc / 86400 + 35430, z: table_fmt[14] };
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
ret = { t: "b", v: ieee > 0 };
|
||||
@ -744,10 +754,18 @@ function write_new_storage(cell, lut) {
|
||||
out[0] = 5;
|
||||
switch (cell.t) {
|
||||
case "n":
|
||||
if (cell.z && fmt_is_date(cell.z)) {
|
||||
out[1] = 5;
|
||||
dv.setFloat64(l, (numdate(cell.v + 1462).getTime() - Date.UTC(2001, 0, 1)) / 1e3, true);
|
||||
fields |= 4;
|
||||
l += 8;
|
||||
break;
|
||||
} else {
|
||||
out[1] = 2;
|
||||
writeDecimal128LE(out, l, cell.v);
|
||||
fields |= 1;
|
||||
l += 16;
|
||||
}
|
||||
break;
|
||||
case "b":
|
||||
out[1] = 6;
|
||||
@ -780,6 +798,12 @@ function write_new_storage(cell, lut) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "d":
|
||||
out[1] = 5;
|
||||
dv.setFloat64(l, (cell.v.getTime() - Date.UTC(2001, 0, 1)) / 1e3, true);
|
||||
fields |= 4;
|
||||
l += 8;
|
||||
break;
|
||||
case "z":
|
||||
out[1] = 0;
|
||||
break;
|
||||
@ -796,7 +820,7 @@ function write_new_storage(cell, lut) {
|
||||
return out[subarray](0, l);
|
||||
}
|
||||
function write_old_storage(cell, lut) {
|
||||
var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, fields = 0;
|
||||
var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, fields = 0, s = "";
|
||||
out[0] = 4;
|
||||
switch (cell.t) {
|
||||
case "n":
|
||||
@ -805,7 +829,7 @@ function write_old_storage(cell, lut) {
|
||||
break;
|
||||
case "s":
|
||||
{
|
||||
var s = cell.v == null ? "" : String(cell.v);
|
||||
s = cell.v == null ? "" : String(cell.v);
|
||||
if (cell.l) {
|
||||
var irsst = lut.rsst.findIndex(function(v) {
|
||||
var _a;
|
||||
@ -821,6 +845,10 @@ function write_old_storage(cell, lut) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "d":
|
||||
break;
|
||||
case "e":
|
||||
break;
|
||||
case "z":
|
||||
break;
|
||||
default:
|
||||
@ -846,7 +874,7 @@ function write_old_storage(cell, lut) {
|
||||
break;
|
||||
case "s":
|
||||
{
|
||||
var s = cell.v == null ? "" : String(cell.v);
|
||||
s = cell.v == null ? "" : String(cell.v);
|
||||
if (cell.l) {
|
||||
} else {
|
||||
var isst = lut.sst.indexOf(s);
|
||||
@ -859,6 +887,12 @@ function write_old_storage(cell, lut) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "d":
|
||||
out[1] = 5;
|
||||
dv.setFloat64(l, (cell.v.getTime() - Date.UTC(2001, 0, 1)) / 1e3, true);
|
||||
fields |= 64;
|
||||
l += 8;
|
||||
break;
|
||||
case "z":
|
||||
out[1] = 0;
|
||||
break;
|
||||
@ -868,16 +902,16 @@ function write_old_storage(cell, lut) {
|
||||
dv.setUint32(8, fields, true);
|
||||
return out[subarray](0, l);
|
||||
}
|
||||
function parse_cell_storage(buf, lut) {
|
||||
function parse_cell_storage(buf, lut, opts) {
|
||||
switch (buf[0]) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
return parse_old_storage(buf, lut, buf[0]);
|
||||
return parse_old_storage(buf, lut, buf[0], opts);
|
||||
case 5:
|
||||
return parse_new_storage(buf, lut);
|
||||
return parse_new_storage(buf, lut, opts);
|
||||
default:
|
||||
throw new Error("Unsupported payload version ".concat(buf[0]));
|
||||
}
|
||||
@ -1082,7 +1116,7 @@ function s5s_to_iwa_comment(s5s) {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
function parse_TST_TableModelArchive(M, root, ws) {
|
||||
function parse_TST_TableModelArchive(M, root, ws, opts) {
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
||||
var pb = parse_shallow(root.data);
|
||||
var range = { s: { r: 0, c: 0 }, e: { r: 0, c: 0 } };
|
||||
@ -1121,7 +1155,7 @@ function parse_TST_TableModelArchive(M, root, ws) {
|
||||
var _tile = parse_TST_Tile(M, ref2);
|
||||
_tile.data.forEach(function(row, R) {
|
||||
row.forEach(function(buf, C) {
|
||||
var res = parse_cell_storage(buf, lut);
|
||||
var res = parse_cell_storage(buf, lut, opts);
|
||||
if (res) {
|
||||
if (dense) {
|
||||
if (!dws["!data"][_R + R])
|
||||
@ -1162,7 +1196,7 @@ function parse_TST_TableInfoArchive(M, root, opts) {
|
||||
var mtype = varint_to_i32(tableref[0].meta[1][0].data);
|
||||
if (mtype != 6001)
|
||||
throw new Error("6000 unexpected reference to ".concat(mtype));
|
||||
parse_TST_TableModelArchive(M, tableref[0], out);
|
||||
parse_TST_TableModelArchive(M, tableref[0], out, opts);
|
||||
return out;
|
||||
}
|
||||
function parse_TN_SheetArchive(M, root, opts) {
|
||||
@ -1185,6 +1219,7 @@ function parse_TN_SheetArchive(M, root, opts) {
|
||||
function parse_TN_DocumentArchive(M, root, opts) {
|
||||
var _a;
|
||||
var out = book_new();
|
||||
out.Workbook = { WBProps: { date1904: true } };
|
||||
var pb = parse_shallow(root.data);
|
||||
if ((_a = pb[2]) == null ? void 0 : _a[0])
|
||||
throw new Error("Keynote presentations are not supported");
|
||||
@ -1300,8 +1335,8 @@ function write_TST_TileRowInfo(data, lut, wide) {
|
||||
switch (data[C].t) {
|
||||
case "d":
|
||||
if (data[C].v instanceof Date) {
|
||||
celload = write_new_storage({ t: "s", v: data[C].v.toISOString() }, lut);
|
||||
_celload = write_old_storage({ t: "s", v: data[C].v.toISOString() }, lut);
|
||||
celload = write_new_storage(data[C], lut);
|
||||
_celload = write_old_storage(data[C], lut);
|
||||
break;
|
||||
}
|
||||
celload = write_new_storage(data[C], lut);
|
||||
|
@ -24,7 +24,12 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
|
||||
switch(val.t){
|
||||
case 'z': if(v == null) break; continue;
|
||||
case 'e': v = (v == 0 ? null : void 0); break;
|
||||
case 's': case 'd': case 'b': case 'n': break;
|
||||
case 's': case 'b':
|
||||
case 'n': if(!val.z || !fmt_is_date(val.z)) break;
|
||||
v = numdate(v); // TODO: date1904 setting should also be stored in worksheet object
|
||||
if(typeof v == "number") break;
|
||||
/* falls through */
|
||||
case 'd': if(!(o && o.UTC)) v = utc_to_local(v); break;
|
||||
default: throw new Error('unrecognized type ' + val.t);
|
||||
}
|
||||
if(hdr[C] != null) {
|
||||
@ -234,6 +239,7 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
|
||||
else if(typeof v == 'string') t = 's';
|
||||
else if(v instanceof Date) {
|
||||
t = 'd';
|
||||
if(!o.UTC) v = local_to_utc(v);
|
||||
if(!o.cellDates) { t = 'n'; v = datenum(v); }
|
||||
z = (cell != null && cell.z && fmt_is_date(cell.z)) ? cell.z : (o.dateNF || table_fmt[14]);
|
||||
}
|
||||
|
32
dist/xlsx.core.min.js
generated
vendored
32
dist/xlsx.core.min.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.core.min.map
generated
vendored
2
dist/xlsx.core.min.map
generated
vendored
File diff suppressed because one or more lines are too long
2209
dist/xlsx.extendscript.js
generated
vendored
2209
dist/xlsx.extendscript.js
generated
vendored
File diff suppressed because it is too large
Load Diff
35
dist/xlsx.full.min.js
generated
vendored
35
dist/xlsx.full.min.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.full.min.map
generated
vendored
2
dist/xlsx.full.min.map
generated
vendored
File diff suppressed because one or more lines are too long
18
dist/xlsx.mini.min.js
generated
vendored
18
dist/xlsx.mini.min.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.mini.min.map
generated
vendored
2
dist/xlsx.mini.min.map
generated
vendored
File diff suppressed because one or more lines are too long
@ -566,10 +566,10 @@ function numbers_format_cell(cell, t, flags, ofmt, nfmt) {
|
||||
cell.w = cell.w.replace(/:(\d\d\d)$/, ".$1");
|
||||
}
|
||||
}
|
||||
function parse_old_storage(buf, lut, v) {
|
||||
function parse_old_storage(buf, lut, v, opts) {
|
||||
var dv = u8_to_dataview(buf);
|
||||
var flags = dv.getUint32(4, true);
|
||||
var ridx = -1, sidx = -1, zidx = -1, ieee = NaN, dt = new Date(2001, 0, 1);
|
||||
var ridx = -1, sidx = -1, zidx = -1, ieee = NaN, dc = 0, dt = new Date(Date.UTC(2001, 0, 1));
|
||||
var doff = v > 1 ? 12 : 8;
|
||||
if (flags & 2) {
|
||||
zidx = dv.getUint32(doff, true);
|
||||
@ -590,7 +590,7 @@ function parse_old_storage(buf, lut, v) {
|
||||
doff += 8;
|
||||
}
|
||||
if (flags & 64) {
|
||||
dt.setTime(dt.getTime() + dv.getFloat64(doff, true) * 1e3);
|
||||
dt.setTime(dt.getTime() + (dc = dv.getFloat64(doff, true)) * 1e3);
|
||||
doff += 8;
|
||||
}
|
||||
if (v > 1) {
|
||||
@ -613,7 +613,12 @@ function parse_old_storage(buf, lut, v) {
|
||||
ret = { t: "s", v: lut.sst[sidx] };
|
||||
break;
|
||||
case 5:
|
||||
{
|
||||
if (opts == null ? void 0 : opts.cellDates)
|
||||
ret = { t: "d", v: dt };
|
||||
else
|
||||
ret = { t: "n", v: dc / 86400 + 35430, z: table_fmt[14] };
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
ret = { t: "b", v: ieee > 0 };
|
||||
@ -644,12 +649,12 @@ function parse_old_storage(buf, lut, v) {
|
||||
ret.v /= 86400;
|
||||
return ret;
|
||||
}
|
||||
function parse_new_storage(buf, lut) {
|
||||
function parse_new_storage(buf, lut, opts) {
|
||||
var dv = u8_to_dataview(buf);
|
||||
var flags = dv.getUint32(4, true);
|
||||
var fields = dv.getUint32(8, true);
|
||||
var doff = 12;
|
||||
var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1), eidx = -1, fidx = -1;
|
||||
var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dc = 0, dt = new Date(Date.UTC(2001, 0, 1)), eidx = -1, fidx = -1;
|
||||
if (fields & 1) {
|
||||
d128 = readDecimal128LE(buf, doff);
|
||||
doff += 16;
|
||||
@ -659,7 +664,7 @@ function parse_new_storage(buf, lut) {
|
||||
doff += 8;
|
||||
}
|
||||
if (fields & 4) {
|
||||
dt.setTime(dt.getTime() + dv.getFloat64(doff, true) * 1e3);
|
||||
dt.setTime(dt.getTime() + (dc = dv.getFloat64(doff, true)) * 1e3);
|
||||
doff += 8;
|
||||
}
|
||||
if (fields & 8) {
|
||||
@ -693,7 +698,12 @@ function parse_new_storage(buf, lut) {
|
||||
ret = { t: "s", v: lut.sst[sidx] };
|
||||
break;
|
||||
case 5:
|
||||
{
|
||||
if (opts == null ? void 0 : opts.cellDates)
|
||||
ret = { t: "d", v: dt };
|
||||
else
|
||||
ret = { t: "n", v: dc / 86400 + 35430, z: table_fmt[14] };
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
ret = { t: "b", v: ieee > 0 };
|
||||
@ -744,10 +754,18 @@ function write_new_storage(cell, lut) {
|
||||
out[0] = 5;
|
||||
switch (cell.t) {
|
||||
case "n":
|
||||
if (cell.z && fmt_is_date(cell.z)) {
|
||||
out[1] = 5;
|
||||
dv.setFloat64(l, (numdate(cell.v + 1462).getTime() - Date.UTC(2001, 0, 1)) / 1e3, true);
|
||||
fields |= 4;
|
||||
l += 8;
|
||||
break;
|
||||
} else {
|
||||
out[1] = 2;
|
||||
writeDecimal128LE(out, l, cell.v);
|
||||
fields |= 1;
|
||||
l += 16;
|
||||
}
|
||||
break;
|
||||
case "b":
|
||||
out[1] = 6;
|
||||
@ -780,6 +798,12 @@ function write_new_storage(cell, lut) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "d":
|
||||
out[1] = 5;
|
||||
dv.setFloat64(l, (cell.v.getTime() - Date.UTC(2001, 0, 1)) / 1e3, true);
|
||||
fields |= 4;
|
||||
l += 8;
|
||||
break;
|
||||
case "z":
|
||||
out[1] = 0;
|
||||
break;
|
||||
@ -796,7 +820,7 @@ function write_new_storage(cell, lut) {
|
||||
return out[subarray](0, l);
|
||||
}
|
||||
function write_old_storage(cell, lut) {
|
||||
var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, fields = 0;
|
||||
var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, fields = 0, s = "";
|
||||
out[0] = 4;
|
||||
switch (cell.t) {
|
||||
case "n":
|
||||
@ -805,7 +829,7 @@ function write_old_storage(cell, lut) {
|
||||
break;
|
||||
case "s":
|
||||
{
|
||||
var s = cell.v == null ? "" : String(cell.v);
|
||||
s = cell.v == null ? "" : String(cell.v);
|
||||
if (cell.l) {
|
||||
var irsst = lut.rsst.findIndex(function(v) {
|
||||
var _a;
|
||||
@ -821,6 +845,10 @@ function write_old_storage(cell, lut) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "d":
|
||||
break;
|
||||
case "e":
|
||||
break;
|
||||
case "z":
|
||||
break;
|
||||
default:
|
||||
@ -846,7 +874,7 @@ function write_old_storage(cell, lut) {
|
||||
break;
|
||||
case "s":
|
||||
{
|
||||
var s = cell.v == null ? "" : String(cell.v);
|
||||
s = cell.v == null ? "" : String(cell.v);
|
||||
if (cell.l) {
|
||||
} else {
|
||||
var isst = lut.sst.indexOf(s);
|
||||
@ -859,6 +887,12 @@ function write_old_storage(cell, lut) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "d":
|
||||
out[1] = 5;
|
||||
dv.setFloat64(l, (cell.v.getTime() - Date.UTC(2001, 0, 1)) / 1e3, true);
|
||||
fields |= 64;
|
||||
l += 8;
|
||||
break;
|
||||
case "z":
|
||||
out[1] = 0;
|
||||
break;
|
||||
@ -868,16 +902,16 @@ function write_old_storage(cell, lut) {
|
||||
dv.setUint32(8, fields, true);
|
||||
return out[subarray](0, l);
|
||||
}
|
||||
function parse_cell_storage(buf, lut) {
|
||||
function parse_cell_storage(buf, lut, opts) {
|
||||
switch (buf[0]) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
return parse_old_storage(buf, lut, buf[0]);
|
||||
return parse_old_storage(buf, lut, buf[0], opts);
|
||||
case 5:
|
||||
return parse_new_storage(buf, lut);
|
||||
return parse_new_storage(buf, lut, opts);
|
||||
default:
|
||||
throw new Error("Unsupported payload version ".concat(buf[0]));
|
||||
}
|
||||
@ -1082,7 +1116,7 @@ function s5s_to_iwa_comment(s5s) {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
function parse_TST_TableModelArchive(M, root, ws) {
|
||||
function parse_TST_TableModelArchive(M, root, ws, opts) {
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
||||
var pb = parse_shallow(root.data);
|
||||
var range = { s: { r: 0, c: 0 }, e: { r: 0, c: 0 } };
|
||||
@ -1121,7 +1155,7 @@ function parse_TST_TableModelArchive(M, root, ws) {
|
||||
var _tile = parse_TST_Tile(M, ref2);
|
||||
_tile.data.forEach(function(row, R) {
|
||||
row.forEach(function(buf, C) {
|
||||
var res = parse_cell_storage(buf, lut);
|
||||
var res = parse_cell_storage(buf, lut, opts);
|
||||
if (res) {
|
||||
if (dense) {
|
||||
if (!dws["!data"][_R + R])
|
||||
@ -1162,7 +1196,7 @@ function parse_TST_TableInfoArchive(M, root, opts) {
|
||||
var mtype = varint_to_i32(tableref[0].meta[1][0].data);
|
||||
if (mtype != 6001)
|
||||
throw new Error("6000 unexpected reference to ".concat(mtype));
|
||||
parse_TST_TableModelArchive(M, tableref[0], out);
|
||||
parse_TST_TableModelArchive(M, tableref[0], out, opts);
|
||||
return out;
|
||||
}
|
||||
function parse_TN_SheetArchive(M, root, opts) {
|
||||
@ -1185,6 +1219,7 @@ function parse_TN_SheetArchive(M, root, opts) {
|
||||
function parse_TN_DocumentArchive(M, root, opts) {
|
||||
var _a;
|
||||
var out = book_new();
|
||||
out.Workbook = { WBProps: { date1904: true } };
|
||||
var pb = parse_shallow(root.data);
|
||||
if ((_a = pb[2]) == null ? void 0 : _a[0])
|
||||
throw new Error("Keynote presentations are not supported");
|
||||
@ -1300,8 +1335,8 @@ function write_TST_TileRowInfo(data, lut, wide) {
|
||||
switch (data[C].t) {
|
||||
case "d":
|
||||
if (data[C].v instanceof Date) {
|
||||
celload = write_new_storage({ t: "s", v: data[C].v.toISOString() }, lut);
|
||||
_celload = write_old_storage({ t: "s", v: data[C].v.toISOString() }, lut);
|
||||
celload = write_new_storage(data[C], lut);
|
||||
_celload = write_old_storage(data[C], lut);
|
||||
break;
|
||||
}
|
||||
celload = write_new_storage(data[C], lut);
|
||||
|
@ -4,7 +4,7 @@
|
||||
/* these are type imports and do not show up in the generated JS */
|
||||
import { CFB$Container, CFB$Entry } from 'cfb';
|
||||
import { WorkBook, WorkSheet, Range, CellObject, ParsingOptions, WritingOptions, DenseWorkSheet, Comments } from '../';
|
||||
import type { utils } from "../";
|
||||
import type { utils, NumberFormat } from "../";
|
||||
|
||||
declare var encode_col: typeof utils.encode_col;
|
||||
declare var encode_row: typeof utils.encode_row;
|
||||
@ -12,6 +12,9 @@ declare var encode_range: typeof utils.encode_range;
|
||||
declare var book_new: typeof utils.book_new;
|
||||
declare var book_append_sheet: typeof utils.book_append_sheet;
|
||||
declare var decode_range: typeof utils.decode_range;
|
||||
declare var numdate: (num: number) => Date;
|
||||
declare var table_fmt: {[nf: number]: string};
|
||||
declare function fmt_is_date(fmt: NumberFormat): boolean;
|
||||
import * as _CFB from 'cfb';
|
||||
declare var CFB: typeof _CFB;
|
||||
//<<import { utils } from "../../";
|
||||
@ -487,11 +490,11 @@ function numbers_format_cell(cell: CellObject, t: number, flags: number, ofmt: P
|
||||
}
|
||||
|
||||
/** Parse "old storage" (version 0..4) */
|
||||
function parse_old_storage(buf: Uint8Array, lut: DataLUT, v: 0|1|2|3|4): CellObject | void {
|
||||
function parse_old_storage(buf: Uint8Array, lut: DataLUT, v: 0|1|2|3|4, opts?: ParsingOptions): CellObject | void {
|
||||
var dv = u8_to_dataview(buf);
|
||||
var flags = dv.getUint32(4, true);
|
||||
|
||||
var ridx = -1, sidx = -1, zidx = -1, ieee = NaN, dt = new Date(2001, 0, 1);
|
||||
var ridx = -1, sidx = -1, zidx = -1, ieee = NaN, dc = 0, dt = new Date(Date.UTC(2001, 0, 1));
|
||||
var doff = (v > 1 ? 12 : 8);
|
||||
if(flags & 0x0002) { zidx = dv.getUint32(doff, true); doff += 4;}
|
||||
doff += popcnt(flags & (v > 1 ? 0x0D8C : 0x018C)) * 4;
|
||||
@ -500,7 +503,7 @@ function parse_old_storage(buf: Uint8Array, lut: DataLUT, v: 0|1|2|3|4): CellObj
|
||||
doff += popcnt(flags & (v > 1 ? 0x3000 : 0x1000)) * 4;
|
||||
if(flags & 0x0010) { sidx = dv.getUint32(doff, true); doff += 4; }
|
||||
if(flags & 0x0020) { ieee = dv.getFloat64(doff, true); doff += 8; }
|
||||
if(flags & 0x0040) { dt.setTime(dt.getTime() + dv.getFloat64(doff, true) * 1000); doff += 8; }
|
||||
if(flags & 0x0040) { dt.setTime(dt.getTime() + (dc = dv.getFloat64(doff, true)) * 1000); doff += 8; }
|
||||
|
||||
if(v > 1) {
|
||||
flags = dv.getUint32(8, true) >>> 16;
|
||||
@ -514,7 +517,10 @@ function parse_old_storage(buf: Uint8Array, lut: DataLUT, v: 0|1|2|3|4): CellObj
|
||||
case 0: return void 0; // return { t: "z" }; // blank?
|
||||
case 2: ret = { t: "n", v: ieee }; break; // number
|
||||
case 3: ret = { t: "s", v: lut.sst[sidx] }; break; // string
|
||||
case 5: ret = { t: "d", v: dt }; break; // date-time
|
||||
case 5: { // date-time
|
||||
if(opts?.cellDates) ret = { t: "d", v: dt };
|
||||
else ret = ({ t: "n", v: dc/(86400)+35430, z: table_fmt[14]});
|
||||
} break;
|
||||
case 6: ret = { t: "b", v: ieee > 0 }; break; // boolean
|
||||
case 7: ret = { t: "n", v: ieee }; break; // duration in seconds
|
||||
case 8: ret = { t: "e", v: 0}; break; // "formula error" TODO: enumerate and map errors to csf equivalents
|
||||
@ -534,19 +540,19 @@ function parse_old_storage(buf: Uint8Array, lut: DataLUT, v: 0|1|2|3|4): CellObj
|
||||
}
|
||||
|
||||
/** Parse "new storage" (version 5) */
|
||||
function parse_new_storage(buf: Uint8Array, lut: DataLUT): CellObject | void {
|
||||
function parse_new_storage(buf: Uint8Array, lut: DataLUT, opts?: ParsingOptions): CellObject | void {
|
||||
var dv = u8_to_dataview(buf);
|
||||
// TODO: bytes 2:3 appear to be unused?
|
||||
var flags = dv.getUint32(4, true);
|
||||
var fields = dv.getUint32(8, true);
|
||||
var doff = 12;
|
||||
|
||||
var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1), eidx = -1, fidx = -1;
|
||||
var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dc = 0, dt = new Date(Date.UTC(2001, 0, 1)), eidx = -1, fidx = -1;
|
||||
|
||||
// 0x00001F data
|
||||
if(fields & 0x000001) { d128 = readDecimal128LE(buf, doff); doff += 16; }
|
||||
if(fields & 0x000002) { ieee = dv.getFloat64(doff, true); doff += 8; }
|
||||
if(fields & 0x000004) { dt.setTime(dt.getTime() + dv.getFloat64(doff, true) * 1000); doff += 8; }
|
||||
if(fields & 0x000004) { dt.setTime(dt.getTime() + (dc = dv.getFloat64(doff, true)) * 1000); doff += 8; }
|
||||
if(fields & 0x000008) { sidx = dv.getUint32(doff, true); doff += 4; }
|
||||
if(fields & 0x000010) { ridx = dv.getUint32(doff, true); doff += 4; }
|
||||
|
||||
@ -564,7 +570,10 @@ function parse_new_storage(buf: Uint8Array, lut: DataLUT): CellObject | void {
|
||||
case 0: ret = { t: "z" }; break;
|
||||
case 2: ret = { t: "n", v: d128 }; break; // number
|
||||
case 3: ret = { t: "s", v: lut.sst[sidx] }; break; // string
|
||||
case 5: ret = { t: "d", v: dt }; break; // date-time
|
||||
case 5: { // date-time
|
||||
if(opts?.cellDates) ret = { t: "d", v: dt };
|
||||
else ret = ({ t: "n", v: dc/(86400)+35430, z: table_fmt[14]});
|
||||
} break;
|
||||
case 6: ret = { t: "b", v: ieee > 0 }; break; // boolean
|
||||
case 7: ret = { t: "n", v: ieee }; break; // duration in "s", fixed later
|
||||
case 8: ret = { t: "e", v: 0 }; break; // "formula error" TODO: enumerate and map errors to csf equivalents
|
||||
@ -603,7 +612,11 @@ function write_new_storage(cell: CellObject, lut: DataLUT): Uint8Array {
|
||||
var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, fields = 0;
|
||||
out[0] = 5;
|
||||
switch(cell.t) {
|
||||
case "n": out[1] = 2; writeDecimal128LE(out, l, cell.v as number); fields |= 1; l += 16; break;
|
||||
case "n": if(cell.z && fmt_is_date(cell.z)) {
|
||||
out[1] = 5; dv.setFloat64(l, ((numdate((cell.v as number) + 1462)).getTime() - Date.UTC(2001, 0, 1))/1000, true); fields |= 4; l += 8; break
|
||||
} else {
|
||||
out[1] = 2; writeDecimal128LE(out, l, cell.v as number); fields |= 1; l += 16;
|
||||
} break
|
||||
case "b": out[1] = 6; dv.setFloat64(l, cell.v ? 1 : 0, true); fields |= 2; l += 8; break;
|
||||
case "s": {
|
||||
var s = cell.v == null ? "" : String(cell.v);
|
||||
@ -617,6 +630,8 @@ function write_new_storage(cell: CellObject, lut: DataLUT): Uint8Array {
|
||||
out[1] = 3; dv.setUint32(l, isst, true); fields |= 8; l += 4;
|
||||
}
|
||||
} break;
|
||||
case "d": out[1] = 5; dv.setFloat64(l, ((cell.v as Date).getTime() - Date.UTC(2001, 0, 1))/1000, true); fields |= 4; l += 8; break;
|
||||
|
||||
case "z": out[1] = 0; break;
|
||||
default: throw "unsupported cell type " + cell.t;
|
||||
}
|
||||
@ -629,20 +644,22 @@ function write_new_storage(cell: CellObject, lut: DataLUT): Uint8Array {
|
||||
}
|
||||
/** Write a cell "old storage" (version 4) */
|
||||
function write_old_storage(cell: CellObject, lut: DataLUT): Uint8Array {
|
||||
var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, fields = 0;
|
||||
var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, fields = 0, s = "";
|
||||
out[0] = 4;
|
||||
/* note: rich text appears *before* comments */
|
||||
switch(cell.t) {
|
||||
case "n": break;
|
||||
case "b": break;
|
||||
case "s": {
|
||||
var s = cell.v == null ? "" : String(cell.v);
|
||||
s = cell.v == null ? "" : String(cell.v);
|
||||
if(cell.l) {
|
||||
var irsst = lut.rsst.findIndex(v => v.v == s && v.l == cell.l?.Target);
|
||||
if(irsst == -1) lut.rsst[irsst = lut.rsst.length] = { v: s, l: cell.l.Target };
|
||||
out[1] = 9; dv.setUint32(l, irsst, true); fields |= 0x200; l += 4;
|
||||
} else { }
|
||||
} break;
|
||||
case "d": break;
|
||||
case "e": break;
|
||||
case "z": break;
|
||||
default: throw "unsupported cell type " + cell.t;
|
||||
}
|
||||
@ -654,13 +671,14 @@ function write_old_storage(cell: CellObject, lut: DataLUT): Uint8Array {
|
||||
case "n": out[1] = 2; dv.setFloat64(l, cell.v as number, true); fields |= 0x20; l += 8; break;
|
||||
case "b": out[1] = 6; dv.setFloat64(l, cell.v ? 1 : 0, true); fields |= 0x20; l += 8; break;
|
||||
case "s": {
|
||||
var s = cell.v == null ? "" : String(cell.v);
|
||||
s = cell.v == null ? "" : String(cell.v);
|
||||
if(cell.l) { } else {
|
||||
var isst = lut.sst.indexOf(s);
|
||||
if(isst == -1) lut.sst[isst = lut.sst.length] = s;
|
||||
out[1] = 3; dv.setUint32(l, isst, true); fields |= 0x10; l += 4;
|
||||
}
|
||||
} break;
|
||||
case "d": out[1] = 5; dv.setFloat64(l, ((cell.v as Date).getTime() - Date.UTC(2001, 0, 1))/1000, true); fields |= 0x40; l += 8; break;
|
||||
case "z": out[1] = 0; break;
|
||||
default: throw "unsupported cell type " + cell.t;
|
||||
}
|
||||
@ -668,11 +686,11 @@ function write_old_storage(cell: CellObject, lut: DataLUT): Uint8Array {
|
||||
return out[subarray](0, l);
|
||||
}
|
||||
//<<export { write_new_storage, write_old_storage };
|
||||
function parse_cell_storage(buf: Uint8Array, lut: DataLUT): CellObject | void {
|
||||
function parse_cell_storage(buf: Uint8Array, lut: DataLUT, opts?: ParsingOptions): CellObject | void {
|
||||
switch(buf[0]) {
|
||||
case 0: case 1:
|
||||
case 2: case 3: case 4: return parse_old_storage(buf, lut, buf[0]);
|
||||
case 5: return parse_new_storage(buf, lut);
|
||||
case 2: case 3: case 4: return parse_old_storage(buf, lut, buf[0], opts);
|
||||
case 5: return parse_new_storage(buf, lut, opts);
|
||||
default: throw new Error(`Unsupported payload version ${buf[0]}`);
|
||||
}
|
||||
}
|
||||
@ -885,7 +903,7 @@ function s5s_to_iwa_comment(s5s: Comments): IWAComment {
|
||||
}
|
||||
|
||||
/** Parse .TST.TableModelArchive (6001) */
|
||||
function parse_TST_TableModelArchive(M: MessageSpace, root: IWAMessage, ws: WorkSheet) {
|
||||
function parse_TST_TableModelArchive(M: MessageSpace, root: IWAMessage, ws: WorkSheet, opts?: ParsingOptions) {
|
||||
var pb = parse_shallow(root.data);
|
||||
var range: Range = { s: {r:0, c:0}, e: {r:0, c:0} };
|
||||
range.e.r = (varint_to_i32(pb[6][0].data) >>> 0) - 1;
|
||||
@ -918,7 +936,7 @@ function parse_TST_TableModelArchive(M: MessageSpace, root: IWAMessage, ws: Work
|
||||
var _tile = parse_TST_Tile(M, ref);
|
||||
_tile.data.forEach((row, R) => {
|
||||
row.forEach((buf, C) => {
|
||||
var res = parse_cell_storage(buf, lut);
|
||||
var res = parse_cell_storage(buf, lut, opts);
|
||||
if(res) {
|
||||
if(dense) {
|
||||
if(!dws["!data"][_R + R]) dws["!data"][_R + R] = [];
|
||||
@ -959,7 +977,7 @@ function parse_TST_TableInfoArchive(M: MessageSpace, root: IWAMessage, opts?: Pa
|
||||
var tableref = M[parse_TSP_Reference(pb[2][0].data)];
|
||||
var mtype = varint_to_i32(tableref[0].meta[1][0].data);
|
||||
if(mtype != 6001) throw new Error(`6000 unexpected reference to ${mtype}`);
|
||||
parse_TST_TableModelArchive(M, tableref[0], out);
|
||||
parse_TST_TableModelArchive(M, tableref[0], out, opts);
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -987,6 +1005,7 @@ function parse_TN_SheetArchive(M: MessageSpace, root: IWAMessage, opts?: Parsing
|
||||
/** Parse .TN.DocumentArchive */
|
||||
function parse_TN_DocumentArchive(M: MessageSpace, root: IWAMessage, opts?: ParsingOptions): WorkBook {
|
||||
var out = book_new();
|
||||
out.Workbook = { WBProps: { date1904: true } };
|
||||
var pb = parse_shallow(root.data);
|
||||
if(pb[2]?.[0]) throw new Error("Keynote presentations are not supported");
|
||||
|
||||
@ -1093,10 +1112,9 @@ function write_TST_TileRowInfo(data: CellObject[], lut: DataLUT, wide: boolean):
|
||||
var celload: Uint8Array, _celload: Uint8Array;
|
||||
switch(data[C].t) {
|
||||
case "d":
|
||||
// TODO: write the actual date code
|
||||
if(data[C].v instanceof Date) {
|
||||
celload = write_new_storage({t: "s", v: (data[C].v as Date).toISOString()}, lut);
|
||||
/*if(!wide)*/ _celload = write_old_storage({t: "s", v: (data[C].v as Date).toISOString()}, lut);
|
||||
celload = write_new_storage(data[C], lut);
|
||||
/*if(!wide)*/ _celload = write_old_storage(data[C], lut);
|
||||
break;
|
||||
}
|
||||
/* TODO: can esbuild preserve falls through comments ? */
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xlsx",
|
||||
"version": "0.19.3",
|
||||
"version": "0.20.0",
|
||||
"author": "sheetjs",
|
||||
"description": "SheetJS Spreadsheet data parser and writer",
|
||||
"keywords": [
|
||||
|
129
test.js
129
test.js
@ -1554,7 +1554,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();
|
||||
@ -1571,28 +1571,30 @@ function seq(end/*:number*/, start/*:?number*/)/*:Array<number>*/ {
|
||||
return o;
|
||||
}
|
||||
|
||||
var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
|
||||
var dnthresh = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
|
||||
var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
|
||||
var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
|
||||
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
|
||||
var epoch = v.getTime();
|
||||
if(date1904) epoch -= 1462*24*60*60*1000;
|
||||
var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
|
||||
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
var epoch = /*#__PURE__*/v.getTime();
|
||||
var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
if(date1904) return res - 1462;
|
||||
return res < 60 ? res - 1 : res;
|
||||
}
|
||||
var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
|
||||
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2017-02-19T19:06:09');
|
||||
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
|
||||
var good_pd = good_pd_date.getFullYear() == 2017;
|
||||
function parseDate(str/*:string|Date*/)/*:Date*/ {
|
||||
var d = new Date(str);
|
||||
if(good_pd) return d;
|
||||
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
|
||||
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
|
||||
var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
|
||||
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]] sans "Z"
|
||||
/* parses a date string as a UTC date */
|
||||
function parseDate(str/*:string*/, date1904/*:boolean*/)/*:Date*/ {
|
||||
if(str instanceof Date) return str;
|
||||
if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
|
||||
var s = d.getFullYear();
|
||||
if(str.indexOf("" + s) > -1) return d;
|
||||
d.setFullYear(d.getFullYear() + 100); return d;
|
||||
}
|
||||
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
|
||||
return new Date(Date.UTC(+n[0], +n[1] - 1, +n[2], +n[3], +n[4], +n[5]));
|
||||
var m = str.match(pdre1);
|
||||
if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
|
||||
m = str.match(pdre2);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
|
||||
m = str.match(pdre3);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt(m[7].slice(1), 10))||0)));
|
||||
var d = new Date(str);
|
||||
return d;
|
||||
}
|
||||
|
||||
var fixdate = browser ? parseDate("2014-02-19T14:30:00.000Z") : new Date("2014-02-19T14:30Z");
|
||||
@ -1816,7 +1818,7 @@ describe('roundtrip features', function() {
|
||||
];
|
||||
var o = X.utils.sheet_to_json(X.utils.json_to_sheet(data, {cellDates:true}));
|
||||
data.forEach(function(row, i) {
|
||||
Object.keys(row).forEach(function(k) { assert.equal(row[k], o[i][k]); });
|
||||
Object.keys(row).forEach(function(k) { assert.equal(row[k].valueOf(), o[i][k].valueOf()); });
|
||||
});
|
||||
});
|
||||
|
||||
@ -2189,7 +2191,15 @@ describe('CSV', function() {
|
||||
assert.equal(cell.w, '2/19/14');
|
||||
});
|
||||
it('should honor dateNF override', function() {
|
||||
var opts = ({type:"binary", dateNF:"YYYY-MM-DD"}/*:any*/);
|
||||
var opts = ({type:"binary", dateNF:"YYYY-MM-DD", cellNF: true}/*:any*/);
|
||||
var cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
/* NOTE: IE interprets 2-digit years as 19xx */
|
||||
assert.ok(cell.w == '2014-02-19' || cell.w == '1914-02-19' || cell.w == "2/19/14");
|
||||
assert.equal(cell.z, "YYYY-MM-DD");
|
||||
opts.cellDates = true; opts.dateNF = "YY-MM-DD";
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
assert.ok(cell.w == '14-02-19' || cell.w == "2/19/14");
|
||||
var opts = ({type:"binary", dateNF:"YYYY-MM-DD", UTC: true}/*:any*/);
|
||||
var cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
/* NOTE: IE interprets 2-digit years as 19xx */
|
||||
assert.ok(cell.w == '2014-02-19' || cell.w == '1914-02-19');
|
||||
@ -2203,10 +2213,18 @@ describe('CSV', function() {
|
||||
var cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 1);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts = {type:"binary", cellDates:true, dateNF:'d/m/yy'};
|
||||
opts.dateNF = 'd/m/yy';
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts = {type:"binary", cellDates:true, dateNF:'m/d/yy', UTC: true};
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getUTCMonth(), 1);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts.dateNF = 'd/m/yy';
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getUTCMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
});
|
||||
it('should interpret values by default', function() { plaintext_test(X.read(csv_bstr, {type:"binary"}), false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(csv_str, {type:"string", raw:true}), true); });
|
||||
@ -2236,7 +2254,8 @@ describe('CSV', function() {
|
||||
["3b", "3 b", "3 b-1"],
|
||||
["3p", "3 P", "3 p-1"]
|
||||
];
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1;
|
||||
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true, UTC: 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]);
|
||||
@ -2244,14 +2263,46 @@ describe('CSV', function() {
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15);
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false, UTC: 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");
|
||||
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true, UTC: 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, UTC: 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, "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");
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal(B1.v * 24, 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal(B3.v * 24, 15);
|
||||
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);
|
||||
|
||||
});
|
||||
});
|
||||
@ -2402,19 +2453,31 @@ describe('dbf', function() {
|
||||
['d11', dir + 'dbf/d11.dbf'],
|
||||
['vfp3', dir + 'dbf/vfp3.dbf']
|
||||
]/*:any*/);
|
||||
var wbsfalse = ([]);
|
||||
var wbstrue = ([]);
|
||||
var bef = (function() {
|
||||
wbs = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), {type:TYPE})]; });
|
||||
wbsfalse = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), { type:TYPE, cellDates: false })]; });
|
||||
wbstrue = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), { type:TYPE, cellDates: true })]; });
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
it(wbs[1][0], function() {
|
||||
var ws = wbs[1][1].Sheets["Sheet1"];
|
||||
var wsfalse = wbsfalse[1][1].Sheets["Sheet1"];
|
||||
[
|
||||
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45],
|
||||
["C2", "v", 12.345], ["D2", "v", 1234.1], ["E2", "w", "19170219"],
|
||||
/* [F2", "w", "19170219"], */ ["G2", "v", 1231.4], ["H2", "v", 123234],
|
||||
["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
].forEach(function(r) { assert.equal(get_cell(ws, r[0])[r[1]], r[2]); });
|
||||
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45], ["C2", "v", 12.345], ["D2", "v", 1234.1],
|
||||
["E2", "v", 6260], ["E2", "w", "19170219"],
|
||||
["F2", "v", 6260], ["F2", "w", "19170219"],
|
||||
["G2", "v", 1231.4], ["H2", "v", 123234], ["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
].forEach(function(r) {
|
||||
assert.equal(get_cell(wsfalse, r[0])[r[1]], r[2]);
|
||||
});
|
||||
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"]
|
||||
].forEach(function(r) {
|
||||
assert.equal(get_cell(wstrue, r[0])[r[1]].valueOf(), r[2].valueOf());
|
||||
});
|
||||
});
|
||||
if(!browser || typeof cptable !== 'undefined') it("Ś╫êëτ⌡ś and Š╫ěéτ⌡š", function() {
|
||||
[ [620, "Ś╫êëτ⌡ś"], [895, "Š╫ěéτ⌡š"] ].forEach(function(r) {
|
||||
|
158
test.mjs
generated
158
test.mjs
generated
@ -1550,6 +1550,22 @@ describe('write features', function() {
|
||||
assert.equal(Name.Ref, "Sheet1!$A$1:$C$3");
|
||||
assert.equal(wb2.Workbook.Names.length, wb3.Workbook.Names.length);
|
||||
}); });
|
||||
it('should handle non-string values for "s" cells', function() {[
|
||||
"xlsx", "xlsb", "xls", "biff5", "biff2", "xlml", "numbers", "ods", "fods", "wk3", "csv", "txt", "sylk", "html", "dif", "dbf", "wk1", "rtf", "prn"
|
||||
].forEach(function(fmt) {
|
||||
if(fmt == "numbers" && !can_write_numbers) return;
|
||||
var ws = X.utils.aoa_to_sheet([
|
||||
["String", "123"],
|
||||
["Number", 123],
|
||||
["Boolean", true],
|
||||
["Date", new Date()],
|
||||
], { cellDates: true });
|
||||
ws["B2"].t = ws["B3"].t = ws["B4"].t = "s"
|
||||
var wb = X.utils.book_new();
|
||||
X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
X.write(wb, {type: TYPE, bookType: fmt, bookSST: false, numbers:XLSX_ZAHL});
|
||||
X.write(wb, {type: TYPE, bookType: fmt, bookSST: true, numbers:XLSX_ZAHL});
|
||||
}); });
|
||||
});
|
||||
|
||||
function seq(end/*:number*/, start/*:?number*/)/*:Array<number>*/ {
|
||||
@ -1559,28 +1575,30 @@ function seq(end/*:number*/, start/*:?number*/)/*:Array<number>*/ {
|
||||
return o;
|
||||
}
|
||||
|
||||
var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
|
||||
var dnthresh = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
|
||||
var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
|
||||
var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
|
||||
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
|
||||
var epoch = v.getTime();
|
||||
if(date1904) epoch -= 1462*24*60*60*1000;
|
||||
var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
|
||||
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
var epoch = /*#__PURE__*/v.getTime();
|
||||
var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
if(date1904) return res - 1462;
|
||||
return res < 60 ? res - 1 : res;
|
||||
}
|
||||
var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
|
||||
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2017-02-19T19:06:09');
|
||||
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
|
||||
var good_pd = good_pd_date.getFullYear() == 2017;
|
||||
function parseDate(str/*:string|Date*/)/*:Date*/ {
|
||||
var d = new Date(str);
|
||||
if(good_pd) return d;
|
||||
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
|
||||
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
|
||||
var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
|
||||
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]] sans "Z"
|
||||
/* parses a date string as a UTC date */
|
||||
function parseDate(str/*:string*/, date1904/*:boolean*/)/*:Date*/ {
|
||||
if(str instanceof Date) return str;
|
||||
if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
|
||||
var s = d.getFullYear();
|
||||
if(str.indexOf("" + s) > -1) return d;
|
||||
d.setFullYear(d.getFullYear() + 100); return d;
|
||||
}
|
||||
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
|
||||
return new Date(Date.UTC(+n[0], +n[1] - 1, +n[2], +n[3], +n[4], +n[5]));
|
||||
var m = str.match(pdre1);
|
||||
if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
|
||||
m = str.match(pdre2);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
|
||||
m = str.match(pdre3);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt(m[7].slice(1), 10))||0)));
|
||||
var d = new Date(str);
|
||||
return d;
|
||||
}
|
||||
|
||||
var fixdate = browser ? parseDate("2014-02-19T14:30:00.000Z") : new Date("2014-02-19T14:30Z");
|
||||
@ -1804,7 +1822,7 @@ describe('roundtrip features', function() {
|
||||
];
|
||||
var o = X.utils.sheet_to_json(X.utils.json_to_sheet(data, {cellDates:true}));
|
||||
data.forEach(function(row, i) {
|
||||
Object.keys(row).forEach(function(k) { assert.equal(row[k], o[i][k]); });
|
||||
Object.keys(row).forEach(function(k) { assert.equal(row[k].valueOf(), o[i][k].valueOf()); });
|
||||
});
|
||||
});
|
||||
|
||||
@ -1891,6 +1909,21 @@ describe('invalid files', function() {
|
||||
wb.SheetNames.push(wb.SheetNames[0]);
|
||||
assert.throws(function() { X.write(wb, {type:'binary'}); });
|
||||
});
|
||||
it('should fail if sheet name is not valid', function() {
|
||||
var names = [
|
||||
"", // cannot be blank
|
||||
"abcdefghijklmnopqrstuvwxyz1234567890", // cannot exceed 31 chars
|
||||
"'sheetjs", "sheetjs'", // cannot start or end with apostrophe
|
||||
"History", // cannot be History
|
||||
"Sheet:JS", "Sheet]JS", "Sheet[JS", "Sheet*JS", // bad characters
|
||||
"Sheet?JS", "Sheet\\JS", "Sheet\/JS"
|
||||
];
|
||||
names.forEach(function(n) { assert.throws(function() {
|
||||
var wb = { SheetNames: [n], Sheets: {} };
|
||||
wb.Sheets[n] = X.utils.aoa_to_sheet([["SheetJS"]]);
|
||||
X.write(wb, {type:"binary", bookType:"xlsx"});
|
||||
}); });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -2162,7 +2195,15 @@ describe('CSV', function() {
|
||||
assert.equal(cell.w, '2/19/14');
|
||||
});
|
||||
it('should honor dateNF override', function() {
|
||||
var opts = ({type:"binary", dateNF:"YYYY-MM-DD"}/*:any*/);
|
||||
var opts = ({type:"binary", dateNF:"YYYY-MM-DD", cellNF: true}/*:any*/);
|
||||
var cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
/* NOTE: IE interprets 2-digit years as 19xx */
|
||||
assert.ok(cell.w == '2014-02-19' || cell.w == '1914-02-19' || cell.w == "2/19/14");
|
||||
assert.equal(cell.z, "YYYY-MM-DD");
|
||||
opts.cellDates = true; opts.dateNF = "YY-MM-DD";
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
assert.ok(cell.w == '14-02-19' || cell.w == "2/19/14");
|
||||
var opts = ({type:"binary", dateNF:"YYYY-MM-DD", UTC: true}/*:any*/);
|
||||
var cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
/* NOTE: IE interprets 2-digit years as 19xx */
|
||||
assert.ok(cell.w == '2014-02-19' || cell.w == '1914-02-19');
|
||||
@ -2176,10 +2217,18 @@ describe('CSV', function() {
|
||||
var cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 1);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts = {type:"binary", cellDates:true, dateNF:'d/m/yy'};
|
||||
opts.dateNF = 'd/m/yy';
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts = {type:"binary", cellDates:true, dateNF:'m/d/yy', UTC: true};
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getUTCMonth(), 1);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts.dateNF = 'd/m/yy';
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getUTCMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
});
|
||||
it('should interpret values by default', function() { plaintext_test(X.read(csv_bstr, {type:"binary"}), false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(csv_str, {type:"string", raw:true}), true); });
|
||||
@ -2209,7 +2258,8 @@ describe('CSV', function() {
|
||||
["3b", "3 b", "3 b-1"],
|
||||
["3p", "3 P", "3 p-1"]
|
||||
];
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1;
|
||||
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true, UTC: 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]);
|
||||
@ -2217,14 +2267,46 @@ describe('CSV', function() {
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15);
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false, UTC: 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");
|
||||
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true, UTC: 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, UTC: 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, "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");
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal(B1.v * 24, 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal(B3.v * 24, 15);
|
||||
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);
|
||||
|
||||
});
|
||||
});
|
||||
@ -2375,19 +2457,31 @@ describe('dbf', function() {
|
||||
['d11', dir + 'dbf/d11.dbf'],
|
||||
['vfp3', dir + 'dbf/vfp3.dbf']
|
||||
]/*:any*/);
|
||||
var wbsfalse = ([]);
|
||||
var wbstrue = ([]);
|
||||
var bef = (function() {
|
||||
wbs = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), {type:TYPE})]; });
|
||||
wbsfalse = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), { type:TYPE, cellDates: false })]; });
|
||||
wbstrue = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), { type:TYPE, cellDates: true })]; });
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
it(wbs[1][0], function() {
|
||||
var ws = wbs[1][1].Sheets["Sheet1"];
|
||||
var wsfalse = wbsfalse[1][1].Sheets["Sheet1"];
|
||||
[
|
||||
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45],
|
||||
["C2", "v", 12.345], ["D2", "v", 1234.1], ["E2", "w", "19170219"],
|
||||
/* [F2", "w", "19170219"], */ ["G2", "v", 1231.4], ["H2", "v", 123234],
|
||||
["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
].forEach(function(r) { assert.equal(get_cell(ws, r[0])[r[1]], r[2]); });
|
||||
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45], ["C2", "v", 12.345], ["D2", "v", 1234.1],
|
||||
["E2", "v", 6260], ["E2", "w", "19170219"],
|
||||
["F2", "v", 6260], ["F2", "w", "19170219"],
|
||||
["G2", "v", 1231.4], ["H2", "v", 123234], ["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
].forEach(function(r) {
|
||||
assert.equal(get_cell(wsfalse, r[0])[r[1]], r[2]);
|
||||
});
|
||||
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"],
|
||||
].forEach(function(r) {
|
||||
assert.equal(get_cell(wstrue, r[0])[r[1]].valueOf(), r[2].valueOf());
|
||||
});
|
||||
});
|
||||
if(!browser || typeof cptable !== 'undefined') it("Ś╫êëτ⌡ś and Š╫ěéτ⌡š", function() {
|
||||
[ [620, "Ś╫êëτ⌡ś"], [895, "Š╫ěéτ⌡š"] ].forEach(function(r) {
|
||||
|
163
test.mts
163
test.mts
@ -1006,7 +1006,7 @@ describe('parse features', function() {
|
||||
|
||||
describe('sheetRows', function() {
|
||||
it('should use original range if not set', function() {
|
||||
var opts = {type:TYPE};
|
||||
var opts: X.ParsingOptions = {type:TYPE};
|
||||
FSTPaths.map(function(p) { return X.read(fs.readFileSync(p), opts); }).forEach(function(wb) {
|
||||
assert.equal(wb.Sheets["Text"]["!ref"],"A1:F49");
|
||||
});
|
||||
@ -1510,6 +1510,22 @@ describe('write features', function() {
|
||||
assert.equal(Name.Ref, "Sheet1!$A$1:$C$3");
|
||||
assert.equal(((wb2.Workbook as any).Names as any).length, ((wb3.Workbook as any).Names as any).length);
|
||||
}); });
|
||||
it('should handle non-string values for "s" cells', function() {([
|
||||
"xlsx", "xlsb", "xls", "biff5", "biff2", "xlml", "numbers", "ods", "fods", "wk3", "csv", "txt", "sylk", "html", "dif", "dbf", "wk1", "rtf", "prn"
|
||||
] as Array<X.BookType>).forEach(function(fmt) {
|
||||
if(fmt == "numbers" && !can_write_numbers) return;
|
||||
var ws = X.utils.aoa_to_sheet([
|
||||
["String", "123"],
|
||||
["Number", 123],
|
||||
["Boolean", true],
|
||||
["Date", new Date()],
|
||||
], { cellDates: true });
|
||||
ws["B2"].t = ws["B3"].t = ws["B4"].t = "s"
|
||||
var wb = X.utils.book_new();
|
||||
X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
X.write(wb, {type: TYPE, bookType: fmt, bookSST: false, numbers:XLSX_ZAHL});
|
||||
X.write(wb, {type: TYPE, bookType: fmt, bookSST: true, numbers:XLSX_ZAHL});
|
||||
}); });
|
||||
});
|
||||
|
||||
function seq(end: number, start?: number): Array<number> {
|
||||
@ -1519,28 +1535,30 @@ function seq(end: number, start?: number): Array<number> {
|
||||
return o;
|
||||
}
|
||||
|
||||
var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
|
||||
var dnthresh = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
|
||||
var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
|
||||
var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
|
||||
function datenum(v: Date, date1904?: boolean): number {
|
||||
var epoch = v.getTime();
|
||||
if(date1904) epoch -= 1462*24*60*60*1000;
|
||||
var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
|
||||
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
var epoch = /*#__PURE__*/v.getTime();
|
||||
var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
if(date1904) return res - 1462;
|
||||
return res < 60 ? res - 1 : res;
|
||||
}
|
||||
var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
|
||||
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2017-02-19T19:06:09');
|
||||
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
|
||||
var good_pd = good_pd_date.getFullYear() == 2017;
|
||||
function parseDate(str: string|Date): Date {
|
||||
var d = new Date(str);
|
||||
if(good_pd) return d;
|
||||
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
|
||||
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
|
||||
var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
|
||||
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]] sans "Z"
|
||||
/* parses a date string as a UTC date */
|
||||
function parseDate(str: string|Date, date1904?: boolean): Date {
|
||||
if(str instanceof Date) return str;
|
||||
if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
|
||||
var s = d.getFullYear();
|
||||
if(str.indexOf("" + s) > -1) return d;
|
||||
d.setFullYear(d.getFullYear() + 100); return d;
|
||||
}
|
||||
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
|
||||
return new Date(Date.UTC(+n[0], +n[1] - 1, +n[2], +n[3], +n[4], +n[5]));
|
||||
var m = str.match(pdre1);
|
||||
if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
|
||||
m = str.match(pdre2);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
|
||||
m = str.match(pdre3);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt(m[7].slice(1), 10))||0)));
|
||||
var d = new Date(str);
|
||||
return d;
|
||||
}
|
||||
|
||||
var fixdate = browser ? parseDate("2014-02-19T14:30:00.000Z") : new Date("2014-02-19T14:30Z");
|
||||
@ -1851,6 +1869,21 @@ describe('invalid files', function() {
|
||||
wb.SheetNames.push(wb.SheetNames[0]);
|
||||
assert.throws(function() { X.write(wb, {type:'binary'}); });
|
||||
});
|
||||
it('should fail if sheet name is not valid', function() {
|
||||
var names = [
|
||||
"", // cannot be blank
|
||||
"abcdefghijklmnopqrstuvwxyz1234567890", // cannot exceed 31 chars
|
||||
"'sheetjs", "sheetjs'", // cannot start or end with apostrophe
|
||||
"History", // cannot be History
|
||||
"Sheet:JS", "Sheet]JS", "Sheet[JS", "Sheet*JS", // bad characters
|
||||
"Sheet?JS", "Sheet\\JS", "Sheet\/JS"
|
||||
];
|
||||
names.forEach(function(n) { assert.throws(function() {
|
||||
var wb: X.WorkBook = { SheetNames: [n], Sheets: {} };
|
||||
wb.Sheets[n] = X.utils.aoa_to_sheet([["SheetJS"]]);
|
||||
X.write(wb, {type:"binary", bookType:"xlsx"});
|
||||
}); });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -2118,9 +2151,17 @@ describe('CSV', function() {
|
||||
assert.equal(cell.w, '2/19/14');
|
||||
});
|
||||
it('should honor dateNF override', function() {
|
||||
var opts: X.ParsingOptions = ({type:"binary", dateNF:"YYYY-MM-DD"});
|
||||
var opts: X.ParsingOptions = ({type:"binary", dateNF:"YYYY-MM-DD", cellNF: true});
|
||||
var cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
/* NOTE: IE interprets 2-digit years as 19xx */
|
||||
assert.ok(cell.w == '2014-02-19' || cell.w == '1914-02-19' || cell.w == "2/19/14");
|
||||
assert.equal(cell.z, "YYYY-MM-DD");
|
||||
opts.cellDates = true; opts.dateNF = "YY-MM-DD";
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
assert.ok(cell.w == '14-02-19' || cell.w == "2/19/14");
|
||||
opts = ({type:"binary", dateNF:"YYYY-MM-DD", UTC: true}/*:any*/);
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
/* NOTE: IE interprets 2-digit years as 19xx */
|
||||
assert.ok(cell.w == '2014-02-19' || cell.w == '1914-02-19');
|
||||
opts.cellDates = true; opts.dateNF = "YY-MM-DD";
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
@ -2132,10 +2173,18 @@ describe('CSV', function() {
|
||||
var cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 1);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts = {type:"binary", cellDates:true, dateNF:'d/m/yy'};
|
||||
opts.dateNF = 'd/m/yy';
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts = {type:"binary", cellDates:true, dateNF:'m/d/yy', UTC: true};
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getUTCMonth(), 1);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts.dateNF = 'd/m/yy';
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getUTCMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
});
|
||||
it('should interpret values by default', function() { plaintext_test(X.read(csv_bstr, {type:"binary"}), false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(csv_str, {type:"string", raw:true}), true); });
|
||||
@ -2163,9 +2212,10 @@ describe('CSV', function() {
|
||||
var aoa = [
|
||||
["3a", "3 a", "3 a-1"],
|
||||
["3b", "3 b", "3 b-1"],
|
||||
["3p", "3 P", "3 p-1"],
|
||||
["3p", "3 P", "3 p-1"]
|
||||
];
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1;
|
||||
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true, UTC: 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]);
|
||||
@ -2173,14 +2223,46 @@ describe('CSV', function() {
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15);
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false, UTC: 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");
|
||||
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true, UTC: 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, UTC: 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, "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");
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal(B1.v * 24, 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal(B3.v * 24, 15);
|
||||
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);
|
||||
|
||||
});
|
||||
});
|
||||
@ -2317,18 +2399,31 @@ describe('numbers', function() {
|
||||
});
|
||||
|
||||
describe('dbf', function() {
|
||||
var wbs: Array<[string, X.WorkBook]> = ([
|
||||
var wbs: Array<[string, string]> = ([
|
||||
['d11', dir + 'dbf/d11.dbf'],
|
||||
['vfp3', dir + 'dbf/vfp3.dbf']
|
||||
]).map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), {type:TYPE})]; });
|
||||
]);
|
||||
var wbsfalse: Array<[string, X.WorkBook]> = ([]);
|
||||
var wbstrue: Array<[string, X.WorkBook]> = ([]);
|
||||
wbsfalse = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), { type:TYPE, cellDates: false })]; });
|
||||
wbstrue = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), { type:TYPE, cellDates: true })]; });
|
||||
it(wbs[1][0], function() {
|
||||
var ws = wbs[1][1].Sheets["Sheet1"];
|
||||
var wsfalse = wbsfalse[1][1].Sheets["Sheet1"];
|
||||
([
|
||||
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45],
|
||||
["C2", "v", 12.345], ["D2", "v", 1234.1], ["E2", "w", "19170219"],
|
||||
/* [F2", "w", "19170219"], */ ["G2", "v", 1231.4], ["H2", "v", 123234],
|
||||
["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
] as Array<[string, string, any]>).forEach(function(r) { assert.equal(get_cell(ws, r[0])[r[1]], r[2]); });
|
||||
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45], ["C2", "v", 12.345], ["D2", "v", 1234.1],
|
||||
["E2", "v", 6260], ["E2", "w", "19170219"],
|
||||
["F2", "v", 6260], ["F2", "w", "19170219"],
|
||||
["G2", "v", 1231.4], ["H2", "v", 123234], ["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
] as Array<[string, string, any]>).forEach(function(r) {
|
||||
assert.equal(get_cell(wsfalse, r[0])[r[1]], r[2]);
|
||||
});
|
||||
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"],
|
||||
] as Array<[string, string, any]>).forEach(function(r) {
|
||||
assert.equal(get_cell(wstrue, r[0])[r[1]].valueOf(), r[2].valueOf());
|
||||
});
|
||||
});
|
||||
it("Ś╫êëτ⌡ś and Š╫ěéτ⌡š", function() {
|
||||
([ [620, "Ś╫êëτ⌡ś"], [895, "Š╫ěéτ⌡š"] ] as Array<[number,string]>).forEach(function(r) {
|
||||
|
163
test.ts
163
test.ts
@ -1006,7 +1006,7 @@ Deno.test('parse features', async function(t) {
|
||||
|
||||
await t.step('sheetRows', async function(t) {
|
||||
await t.step('should use original range if not set', async function(t) {
|
||||
var opts = {type:TYPE};
|
||||
var opts: X.ParsingOptions = {type:TYPE};
|
||||
FSTPaths.map(function(p) { return X.read(fs.readFileSync(p), opts); }).forEach(function(wb) {
|
||||
assert.equal(wb.Sheets["Text"]["!ref"],"A1:F49");
|
||||
});
|
||||
@ -1510,6 +1510,22 @@ Deno.test('write features', async function(t) {
|
||||
assert.equal(Name.Ref, "Sheet1!$A$1:$C$3");
|
||||
assert.equal(((wb2.Workbook as any).Names as any).length, ((wb3.Workbook as any).Names as any).length);
|
||||
}); });
|
||||
await t.step('should handle non-string values for "s" cells', async function(t) {([
|
||||
"xlsx", "xlsb", "xls", "biff5", "biff2", "xlml", "numbers", "ods", "fods", "wk3", "csv", "txt", "sylk", "html", "dif", "dbf", "wk1", "rtf", "prn"
|
||||
] as Array<X.BookType>).forEach(function(fmt) {
|
||||
if(fmt == "numbers" && !can_write_numbers) return;
|
||||
var ws = X.utils.aoa_to_sheet([
|
||||
["String", "123"],
|
||||
["Number", 123],
|
||||
["Boolean", true],
|
||||
["Date", new Date()],
|
||||
], { cellDates: true });
|
||||
ws["B2"].t = ws["B3"].t = ws["B4"].t = "s"
|
||||
var wb = X.utils.book_new();
|
||||
X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
X.write(wb, {type: TYPE, bookType: fmt, bookSST: false, numbers:XLSX_ZAHL});
|
||||
X.write(wb, {type: TYPE, bookType: fmt, bookSST: true, numbers:XLSX_ZAHL});
|
||||
}); });
|
||||
});
|
||||
|
||||
function seq(end: number, start?: number): Array<number> {
|
||||
@ -1519,28 +1535,30 @@ function seq(end: number, start?: number): Array<number> {
|
||||
return o;
|
||||
}
|
||||
|
||||
var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
|
||||
var dnthresh = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
|
||||
var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
|
||||
var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
|
||||
function datenum(v: Date, date1904?: boolean): number {
|
||||
var epoch = v.getTime();
|
||||
if(date1904) epoch -= 1462*24*60*60*1000;
|
||||
var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
|
||||
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
var epoch = /*#__PURE__*/v.getTime();
|
||||
var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
if(date1904) return res - 1462;
|
||||
return res < 60 ? res - 1 : res;
|
||||
}
|
||||
var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
|
||||
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2017-02-19T19:06:09');
|
||||
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
|
||||
var good_pd = good_pd_date.getFullYear() == 2017;
|
||||
function parseDate(str: string|Date): Date {
|
||||
var d = new Date(str);
|
||||
if(good_pd) return d;
|
||||
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
|
||||
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
|
||||
var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
|
||||
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]] sans "Z"
|
||||
/* parses a date string as a UTC date */
|
||||
function parseDate(str: string|Date, date1904?: boolean): Date {
|
||||
if(str instanceof Date) return str;
|
||||
if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
|
||||
var s = d.getFullYear();
|
||||
if(str.indexOf("" + s) > -1) return d;
|
||||
d.setFullYear(d.getFullYear() + 100); return d;
|
||||
}
|
||||
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
|
||||
return new Date(Date.UTC(+n[0], +n[1] - 1, +n[2], +n[3], +n[4], +n[5]));
|
||||
var m = str.match(pdre1);
|
||||
if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
|
||||
m = str.match(pdre2);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
|
||||
m = str.match(pdre3);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt(m[7].slice(1), 10))||0)));
|
||||
var d = new Date(str);
|
||||
return d;
|
||||
}
|
||||
|
||||
var fixdate = browser ? parseDate("2014-02-19T14:30:00.000Z") : new Date("2014-02-19T14:30Z");
|
||||
@ -1851,6 +1869,21 @@ Deno.test('invalid files', async function(t) {
|
||||
wb.SheetNames.push(wb.SheetNames[0]);
|
||||
assert.throws(function() { X.write(wb, {type:'binary'}); });
|
||||
});
|
||||
await t.step('should fail if sheet name is not valid', async function(t) {
|
||||
var names = [
|
||||
"", // cannot be blank
|
||||
"abcdefghijklmnopqrstuvwxyz1234567890", // cannot exceed 31 chars
|
||||
"'sheetjs", "sheetjs'", // cannot start or end with apostrophe
|
||||
"History", // cannot be History
|
||||
"Sheet:JS", "Sheet]JS", "Sheet[JS", "Sheet*JS", // bad characters
|
||||
"Sheet?JS", "Sheet\\JS", "Sheet\/JS"
|
||||
];
|
||||
names.forEach(function(n) { assert.throws(function() {
|
||||
var wb: X.WorkBook = { SheetNames: [n], Sheets: {} };
|
||||
wb.Sheets[n] = X.utils.aoa_to_sheet([["SheetJS"]]);
|
||||
X.write(wb, {type:"binary", bookType:"xlsx"});
|
||||
}); });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -2118,9 +2151,17 @@ Deno.test('CSV', async function(t) {
|
||||
assert.equal(cell.w, '2/19/14');
|
||||
});
|
||||
await t.step('should honor dateNF override', async function(t) {
|
||||
var opts: X.ParsingOptions = ({type:"binary", dateNF:"YYYY-MM-DD"});
|
||||
var opts: X.ParsingOptions = ({type:"binary", dateNF:"YYYY-MM-DD", cellNF: true});
|
||||
var cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
/* NOTE: IE interprets 2-digit years as 19xx */
|
||||
assert.assert(cell.w == '2014-02-19' || cell.w == '1914-02-19' || cell.w == "2/19/14");
|
||||
assert.equal(cell.z, "YYYY-MM-DD");
|
||||
opts.cellDates = true; opts.dateNF = "YY-MM-DD";
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
assert.assert(cell.w == '14-02-19' || cell.w == "2/19/14");
|
||||
opts = ({type:"binary", dateNF:"YYYY-MM-DD", UTC: true}/*:any*/);
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
/* NOTE: IE interprets 2-digit years as 19xx */
|
||||
assert.assert(cell.w == '2014-02-19' || cell.w == '1914-02-19');
|
||||
opts.cellDates = true; opts.dateNF = "YY-MM-DD";
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
@ -2132,10 +2173,18 @@ Deno.test('CSV', async function(t) {
|
||||
var cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 1);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts = {type:"binary", cellDates:true, dateNF:'d/m/yy'};
|
||||
opts.dateNF = 'd/m/yy';
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts = {type:"binary", cellDates:true, dateNF:'m/d/yy', UTC: true};
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getUTCMonth(), 1);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts.dateNF = 'd/m/yy';
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getUTCMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
});
|
||||
await t.step('should interpret values by default', async function(t) { plaintext_test(X.read(csv_bstr, {type:"binary"}), false); });
|
||||
await t.step('should generate strings if raw option is passed', async function(t) { plaintext_test(X.read(csv_str, {type:"string", raw:true}), true); });
|
||||
@ -2163,9 +2212,10 @@ Deno.test('CSV', async function(t) {
|
||||
var aoa = [
|
||||
["3a", "3 a", "3 a-1"],
|
||||
["3b", "3 b", "3 b-1"],
|
||||
["3p", "3 P", "3 p-1"],
|
||||
["3p", "3 P", "3 p-1"]
|
||||
];
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1;
|
||||
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true, UTC: 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]);
|
||||
@ -2173,14 +2223,46 @@ Deno.test('CSV', async function(t) {
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15);
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false, UTC: 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");
|
||||
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true, UTC: 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, UTC: 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, "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");
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal(B1.v * 24, 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal(B3.v * 24, 15);
|
||||
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);
|
||||
|
||||
});
|
||||
});
|
||||
@ -2317,18 +2399,31 @@ Deno.test('numbers', async function(t) {
|
||||
});
|
||||
|
||||
Deno.test('dbf', async function(t) {
|
||||
var wbs: Array<[string, X.WorkBook]> = ([
|
||||
var wbs: Array<[string, string]> = ([
|
||||
['d11', dir + 'dbf/d11.dbf'],
|
||||
['vfp3', dir + 'dbf/vfp3.dbf']
|
||||
]).map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), {type:TYPE})]; });
|
||||
]);
|
||||
var wbsfalse: Array<[string, X.WorkBook]> = ([]);
|
||||
var wbstrue: Array<[string, X.WorkBook]> = ([]);
|
||||
wbsfalse = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), { type:TYPE, cellDates: false })]; });
|
||||
wbstrue = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), { type:TYPE, cellDates: true })]; });
|
||||
await t.step(wbs[1][0], async function(t) {
|
||||
var ws = wbs[1][1].Sheets["Sheet1"];
|
||||
var wsfalse = wbsfalse[1][1].Sheets["Sheet1"];
|
||||
([
|
||||
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45],
|
||||
["C2", "v", 12.345], ["D2", "v", 1234.1], ["E2", "w", "19170219"],
|
||||
/* [F2", "w", "19170219"], */ ["G2", "v", 1231.4], ["H2", "v", 123234],
|
||||
["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
] as Array<[string, string, any]>).forEach(function(r) { assert.equal(get_cell(ws, r[0])[r[1]], r[2]); });
|
||||
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45], ["C2", "v", 12.345], ["D2", "v", 1234.1],
|
||||
["E2", "v", 6260], ["E2", "w", "19170219"],
|
||||
["F2", "v", 6260], ["F2", "w", "19170219"],
|
||||
["G2", "v", 1231.4], ["H2", "v", 123234], ["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
] as Array<[string, string, any]>).forEach(function(r) {
|
||||
assert.equal(get_cell(wsfalse, r[0])[r[1]], r[2]);
|
||||
});
|
||||
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"],
|
||||
] as Array<[string, string, any]>).forEach(function(r) {
|
||||
assert.equal(get_cell(wstrue, r[0])[r[1]].valueOf(), r[2].valueOf());
|
||||
});
|
||||
});
|
||||
await t.step("Ś╫êëτ⌡ś and Š╫ěéτ⌡š", async function(t) {
|
||||
([ [620, "Ś╫êëτ⌡ś"], [895, "Š╫ěéτ⌡š"] ] as Array<[number,string]>).forEach(function(r) {
|
||||
|
183
testbun.mjs
generated
183
testbun.mjs
generated
@ -684,6 +684,7 @@ describe('parse options', function() {
|
||||
}); });
|
||||
});
|
||||
});
|
||||
|
||||
describe('input formats', function() {
|
||||
if(false) it('should read binary strings', function() { artifax.forEach(function(p) {
|
||||
X.read(fs.readFileSync(p, 'binary'), {type: 'binary'});
|
||||
@ -691,6 +692,22 @@ describe('input formats', function() {
|
||||
if(false) it('should read base64 strings', function() { artifax.forEach(function(p) {
|
||||
X.read(fs.readFileSync(p, 'base64'), {type: 'base64'});
|
||||
}); });
|
||||
it('handles base64 within data URI scheme (gh-2762)', function() {
|
||||
var data = 'TmFtZXMNCkhhZmV6DQpTYW0NCg==';
|
||||
|
||||
var wb0 = X.read(data, { type: 'base64' }); // raw base64 string
|
||||
var wb1 = X.read('data:;base64,' + data, { type: 'base64' }); // data URI, no media type
|
||||
var wb2 = X.read('data:text/csv;base64,' + data, { type: 'base64' }); // data URI, CSV type
|
||||
var wb3 = X.read('data:application/vnd.ms-excel;base64,' + data, { type: 'base64' }); // data URI, Excel
|
||||
|
||||
[wb0, wb1, wb2, wb3].forEach(function(wb) {
|
||||
var ws = wb.Sheets.Sheet1;
|
||||
assert.equal(ws["!ref"], "A1:A3");
|
||||
assert.equal(get_cell(ws, "A1").v, "Names");
|
||||
assert.equal(get_cell(ws, "A2").v, "Hafez");
|
||||
assert.equal(get_cell(ws, "A3").v, "Sam");
|
||||
});
|
||||
});
|
||||
if(false) if(typeof Uint8Array !== 'undefined') it('should read array', function() { artifax.forEach(function(p) {
|
||||
X.read(fs.readFileSync(p, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
|
||||
}); });
|
||||
@ -1538,6 +1555,22 @@ describe('write features', function() {
|
||||
assert.equal(Name.Ref, "Sheet1!$A$1:$C$3");
|
||||
assert.equal(wb2.Workbook.Names.length, wb3.Workbook.Names.length);
|
||||
}); });
|
||||
it('should handle non-string values for "s" cells', function() {[
|
||||
"xlsx", "xlsb", "xls", "biff5", "biff2", "xlml", "numbers", "ods", "fods", "wk3", "csv", "txt", "sylk", "html", "dif", "dbf", "wk1", "rtf", "prn"
|
||||
].forEach(function(fmt) {
|
||||
if(fmt == "numbers" && !can_write_numbers) return;
|
||||
var ws = X.utils.aoa_to_sheet([
|
||||
["String", "123"],
|
||||
["Number", 123],
|
||||
["Boolean", true],
|
||||
["Date", new Date()],
|
||||
], { cellDates: true });
|
||||
ws["B2"].t = ws["B3"].t = ws["B4"].t = "s"
|
||||
var wb = X.utils.book_new();
|
||||
X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
X.write(wb, {type: TYPE, bookType: fmt, bookSST: false, numbers:XLSX_ZAHL});
|
||||
X.write(wb, {type: TYPE, bookType: fmt, bookSST: true, numbers:XLSX_ZAHL});
|
||||
}); });
|
||||
});
|
||||
|
||||
function seq(end/*:number*/, start/*:?number*/)/*:Array<number>*/ {
|
||||
@ -1547,28 +1580,30 @@ function seq(end/*:number*/, start/*:?number*/)/*:Array<number>*/ {
|
||||
return o;
|
||||
}
|
||||
|
||||
var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
|
||||
var dnthresh = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
|
||||
var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
|
||||
var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
|
||||
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
|
||||
var epoch = v.getTime();
|
||||
if(date1904) epoch -= 1462*24*60*60*1000;
|
||||
var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
|
||||
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
var epoch = /*#__PURE__*/v.getTime();
|
||||
var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
if(date1904) return res - 1462;
|
||||
return res < 60 ? res - 1 : res;
|
||||
}
|
||||
var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
|
||||
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2017-02-19T19:06:09');
|
||||
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
|
||||
var good_pd = good_pd_date.getFullYear() == 2017;
|
||||
function parseDate(str/*:string|Date*/)/*:Date*/ {
|
||||
var d = new Date(str);
|
||||
if(good_pd) return d;
|
||||
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
|
||||
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
|
||||
var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
|
||||
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]] sans "Z"
|
||||
/* parses a date string as a UTC date */
|
||||
function parseDate(str/*:string*/, date1904/*:boolean*/)/*:Date*/ {
|
||||
if(str instanceof Date) return str;
|
||||
if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
|
||||
var s = d.getFullYear();
|
||||
if(str.indexOf("" + s) > -1) return d;
|
||||
d.setFullYear(d.getFullYear() + 100); return d;
|
||||
}
|
||||
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
|
||||
return new Date(Date.UTC(+n[0], +n[1] - 1, +n[2], +n[3], +n[4], +n[5]));
|
||||
var m = str.match(pdre1);
|
||||
if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
|
||||
m = str.match(pdre2);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
|
||||
m = str.match(pdre3);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt(m[7].slice(1), 10))||0)));
|
||||
var d = new Date(str);
|
||||
return d;
|
||||
}
|
||||
|
||||
var fixdate = browser ? parseDate("2014-02-19T14:30:00.000Z") : new Date("2014-02-19T14:30Z");
|
||||
@ -1791,7 +1826,7 @@ describe('roundtrip features', function() {
|
||||
];
|
||||
var o = X.utils.sheet_to_json(X.utils.json_to_sheet(data, {cellDates:true}));
|
||||
data.forEach(function(row, i) {
|
||||
Object.keys(row).forEach(function(k) { assert.equal(row[k], o[i][k]); });
|
||||
Object.keys(row).forEach(function(k) { assert.equal(row[k].valueOf(), o[i][k].valueOf()); });
|
||||
});
|
||||
});
|
||||
|
||||
@ -1878,6 +1913,21 @@ describe('invalid files', function() {
|
||||
wb.SheetNames.push(wb.SheetNames[0]);
|
||||
assert.throws(function() { X.write(wb, {type:'binary'}); });
|
||||
});
|
||||
it('should fail if sheet name is not valid', function() {
|
||||
var names = [
|
||||
"", // cannot be blank
|
||||
"abcdefghijklmnopqrstuvwxyz1234567890", // cannot exceed 31 chars
|
||||
"'sheetjs", "sheetjs'", // cannot start or end with apostrophe
|
||||
"History", // cannot be History
|
||||
"Sheet:JS", "Sheet]JS", "Sheet[JS", "Sheet*JS", // bad characters
|
||||
"Sheet?JS", "Sheet\\JS", "Sheet\/JS"
|
||||
];
|
||||
names.forEach(function(n) { assert.throws(function() {
|
||||
var wb = { SheetNames: [n], Sheets: {} };
|
||||
wb.Sheets[n] = X.utils.aoa_to_sheet([["SheetJS"]]);
|
||||
X.write(wb, {type:"binary", bookType:"xlsx"});
|
||||
}); });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -2149,7 +2199,15 @@ describe('CSV', function() {
|
||||
assert.equal(cell.w, '2/19/14');
|
||||
});
|
||||
it('should honor dateNF override', function() {
|
||||
var opts = ({type:"buffer", dateNF:"YYYY-MM-DD"}/*:any*/);
|
||||
var opts = ({type:"buffer", dateNF:"YYYY-MM-DD", cellNF: true}/*:any*/);
|
||||
var cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
/* NOTE: IE interprets 2-digit years as 19xx */
|
||||
assert.ok(cell.w == '2014-02-19' || cell.w == '1914-02-19' || cell.w == "2/19/14");
|
||||
assert.equal(cell.z, "YYYY-MM-DD");
|
||||
opts.cellDates = true; opts.dateNF = "YY-MM-DD";
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
assert.ok(cell.w == '14-02-19' || cell.w == "2/19/14");
|
||||
var opts = ({type:"buffer", dateNF:"YYYY-MM-DD", UTC: true}/*:any*/);
|
||||
var cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
/* NOTE: IE interprets 2-digit years as 19xx */
|
||||
assert.ok(cell.w == '2014-02-19' || cell.w == '1914-02-19');
|
||||
@ -2163,10 +2221,18 @@ describe('CSV', function() {
|
||||
var cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 1);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts = {type:"buffer", cellDates:true, dateNF:'d/m/yy'};
|
||||
opts.dateNF = 'd/m/yy';
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts = {type:"buffer", cellDates:true, dateNF:'m/d/yy', UTC: true};
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getUTCMonth(), 1);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts.dateNF = 'd/m/yy';
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getUTCMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
});
|
||||
it('should interpret values by default', function() { plaintext_test(X.read(csv_bstr, {type:"buffer"}), false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(csv_str, {type:"string", raw:true}), true); });
|
||||
@ -2190,6 +2256,48 @@ describe('CSV', function() {
|
||||
assert.equal(get_cell(ws, "B2").v, "j" + m[1] + "l");
|
||||
});
|
||||
});
|
||||
it('should parse date-less meridien time values', function() {
|
||||
var aoa = [
|
||||
["3a", "3 a", "3 a-1"],
|
||||
["3b", "3 b", "3 b-1"],
|
||||
["3p", "3 P", "3 p-1"]
|
||||
];
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]);
|
||||
assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]);
|
||||
}
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15);
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false}).Sheets.Sheet1;
|
||||
for(var R = 0; R < 3; ++R) {
|
||||
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");
|
||||
/* this particular case is not well-defined */
|
||||
//var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal((24 + Math.round(B1.v * 24)) % 24, Math.round(3 + 24 + new Date(1899,11,31,0,0,0,0).getTimezoneOffset()/60) % 24);
|
||||
//var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal((24 + Math.round(B3.v * 24)) % 24, Math.round(15 + 24 + new Date(1899,11,31,0,0,0,0).getTimezoneOffset()/60) % 24);
|
||||
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true, UTC: 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, UTC: 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, "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(){
|
||||
var data, ws;
|
||||
@ -2338,19 +2446,36 @@ describe('dbf', function() {
|
||||
['d11', dir + 'dbf/d11.dbf'],
|
||||
['vfp3', dir + 'dbf/vfp3.dbf']
|
||||
]/*:any*/);
|
||||
var wbstrue = ([]);
|
||||
var wbsfalse = ([]);
|
||||
var bef = (function() {
|
||||
wbs = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), {type:TYPE})]; });
|
||||
wbsfalse = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), { type:TYPE, UTC: false })]; });
|
||||
wbstrue = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), { type:TYPE, UTC: true })]; });
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
it(wbs[1][0], function() {
|
||||
var ws = wbs[1][1].Sheets["Sheet1"];
|
||||
var wstrue = wbstrue[1][1].Sheets["Sheet1"];
|
||||
var wsfalse = wbsfalse[1][1].Sheets["Sheet1"];
|
||||
[
|
||||
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45],
|
||||
["C2", "v", 12.345], ["D2", "v", 1234.1], ["E2", "w", "19170219"],
|
||||
/* [F2", "w", "19170219"], */ ["G2", "v", 1231.4], ["H2", "v", 123234],
|
||||
["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
].forEach(function(r) { assert.equal(get_cell(ws, r[0])[r[1]], r[2]); });
|
||||
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45], ["C2", "v", 12.345], ["D2", "v", 1234.1],
|
||||
["E2", "w", "19170219", (new Date(1917,1,19).getTimezoneOffset() > 0 ? "19170218" : "19170219")],
|
||||
["F2", "w", "19170219", (new Date(1917,1,19).getTimezoneOffset() > 0 ? "19170218" : "19170219")],
|
||||
["G2", "v", 1231.4], ["H2", "v", 123234], ["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
].forEach(function(r) {
|
||||
assert.equal(get_cell(wstrue, r[0])[r[1]], r[2]);
|
||||
assert.equal(get_cell(wsfalse, r[0])[r[1]], r[3] || r[2]);
|
||||
});
|
||||
});
|
||||
if(!browser || typeof cptable !== 'undefined') it("Ś╫êëτ⌡ś and Š╫ěéτ⌡š", function() {
|
||||
[ [620, "Ś╫êëτ⌡ś"], [895, "Š╫ěéτ⌡š"] ].forEach(function(r) {
|
||||
var book = X.utils.book_new();
|
||||
var sheet = X.utils.aoa_to_sheet([["ASCII", "encoded"], ["Test", r[1]]]);
|
||||
X.utils.book_append_sheet(book, sheet, "sheet1");
|
||||
var data = X.write(book, {type: TYPE, bookType: "dbf", codepage:r[0]});
|
||||
var wb = X.read(data, {type: TYPE});
|
||||
assert.equal(wb.Sheets.Sheet1.B2.v, r[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
//import { JSDOM } from 'jsdom';
|
||||
|
163
testnocp.ts
163
testnocp.ts
@ -1005,7 +1005,7 @@ Deno.test('parse features', async function(t) {
|
||||
|
||||
await t.step('sheetRows', async function(t) {
|
||||
await t.step('should use original range if not set', async function(t) {
|
||||
var opts = {type:TYPE};
|
||||
var opts: X.ParsingOptions = {type:TYPE};
|
||||
FSTPaths.map(function(p) { return X.read(fs.readFileSync(p), opts); }).forEach(function(wb) {
|
||||
assert.equal(wb.Sheets["Text"]["!ref"],"A1:F49");
|
||||
});
|
||||
@ -1509,6 +1509,22 @@ Deno.test('write features', async function(t) {
|
||||
assert.equal(Name.Ref, "Sheet1!$A$1:$C$3");
|
||||
assert.equal(((wb2.Workbook as any).Names as any).length, ((wb3.Workbook as any).Names as any).length);
|
||||
}); });
|
||||
await t.step('should handle non-string values for "s" cells', async function(t) {([
|
||||
"xlsx", "xlsb", "xls", "biff5", "biff2", "xlml", "numbers", "ods", "fods", "wk3", "csv", "txt", "sylk", "html", "dif", "dbf", "wk1", "rtf", "prn"
|
||||
] as Array<X.BookType>).forEach(function(fmt) {
|
||||
if(fmt == "numbers" && !can_write_numbers) return;
|
||||
var ws = X.utils.aoa_to_sheet([
|
||||
["String", "123"],
|
||||
["Number", 123],
|
||||
["Boolean", true],
|
||||
["Date", new Date()],
|
||||
], { cellDates: true });
|
||||
ws["B2"].t = ws["B3"].t = ws["B4"].t = "s"
|
||||
var wb = X.utils.book_new();
|
||||
X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
X.write(wb, {type: TYPE, bookType: fmt, bookSST: false, numbers:XLSX_ZAHL});
|
||||
X.write(wb, {type: TYPE, bookType: fmt, bookSST: true, numbers:XLSX_ZAHL});
|
||||
}); });
|
||||
});
|
||||
|
||||
function seq(end: number, start?: number): Array<number> {
|
||||
@ -1518,28 +1534,30 @@ function seq(end: number, start?: number): Array<number> {
|
||||
return o;
|
||||
}
|
||||
|
||||
var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
|
||||
var dnthresh = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
|
||||
var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
|
||||
var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
|
||||
function datenum(v: Date, date1904?: boolean): number {
|
||||
var epoch = v.getTime();
|
||||
if(date1904) epoch -= 1462*24*60*60*1000;
|
||||
var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
|
||||
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
var epoch = /*#__PURE__*/v.getTime();
|
||||
var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
if(date1904) return res - 1462;
|
||||
return res < 60 ? res - 1 : res;
|
||||
}
|
||||
var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
|
||||
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2017-02-19T19:06:09');
|
||||
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
|
||||
var good_pd = good_pd_date.getFullYear() == 2017;
|
||||
function parseDate(str: string|Date): Date {
|
||||
var d = new Date(str);
|
||||
if(good_pd) return d;
|
||||
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
|
||||
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
|
||||
var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
|
||||
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]] sans "Z"
|
||||
/* parses a date string as a UTC date */
|
||||
function parseDate(str: string|Date, date1904?: boolean): Date {
|
||||
if(str instanceof Date) return str;
|
||||
if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
|
||||
var s = d.getFullYear();
|
||||
if(str.indexOf("" + s) > -1) return d;
|
||||
d.setFullYear(d.getFullYear() + 100); return d;
|
||||
}
|
||||
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
|
||||
return new Date(Date.UTC(+n[0], +n[1] - 1, +n[2], +n[3], +n[4], +n[5]));
|
||||
var m = str.match(pdre1);
|
||||
if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
|
||||
m = str.match(pdre2);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
|
||||
m = str.match(pdre3);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt(m[7].slice(1), 10))||0)));
|
||||
var d = new Date(str);
|
||||
return d;
|
||||
}
|
||||
|
||||
var fixdate = browser ? parseDate("2014-02-19T14:30:00.000Z") : new Date("2014-02-19T14:30Z");
|
||||
@ -1850,6 +1868,21 @@ Deno.test('invalid files', async function(t) {
|
||||
wb.SheetNames.push(wb.SheetNames[0]);
|
||||
assert.throws(function() { X.write(wb, {type:'binary'}); });
|
||||
});
|
||||
await t.step('should fail if sheet name is not valid', async function(t) {
|
||||
var names = [
|
||||
"", // cannot be blank
|
||||
"abcdefghijklmnopqrstuvwxyz1234567890", // cannot exceed 31 chars
|
||||
"'sheetjs", "sheetjs'", // cannot start or end with apostrophe
|
||||
"History", // cannot be History
|
||||
"Sheet:JS", "Sheet]JS", "Sheet[JS", "Sheet*JS", // bad characters
|
||||
"Sheet?JS", "Sheet\\JS", "Sheet\/JS"
|
||||
];
|
||||
names.forEach(function(n) { assert.throws(function() {
|
||||
var wb: X.WorkBook = { SheetNames: [n], Sheets: {} };
|
||||
wb.Sheets[n] = X.utils.aoa_to_sheet([["SheetJS"]]);
|
||||
X.write(wb, {type:"binary", bookType:"xlsx"});
|
||||
}); });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -2117,9 +2150,17 @@ Deno.test('CSV', async function(t) {
|
||||
assert.equal(cell.w, '2/19/14');
|
||||
});
|
||||
await t.step('should honor dateNF override', async function(t) {
|
||||
var opts: X.ParsingOptions = ({type:"binary", dateNF:"YYYY-MM-DD"});
|
||||
var opts: X.ParsingOptions = ({type:"binary", dateNF:"YYYY-MM-DD", cellNF: true});
|
||||
var cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
/* NOTE: IE interprets 2-digit years as 19xx */
|
||||
assert.assert(cell.w == '2014-02-19' || cell.w == '1914-02-19' || cell.w == "2/19/14");
|
||||
assert.equal(cell.z, "YYYY-MM-DD");
|
||||
opts.cellDates = true; opts.dateNF = "YY-MM-DD";
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
assert.assert(cell.w == '14-02-19' || cell.w == "2/19/14");
|
||||
opts = ({type:"binary", dateNF:"YYYY-MM-DD", UTC: true}/*:any*/);
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
/* NOTE: IE interprets 2-digit years as 19xx */
|
||||
assert.assert(cell.w == '2014-02-19' || cell.w == '1914-02-19');
|
||||
opts.cellDates = true; opts.dateNF = "YY-MM-DD";
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
@ -2131,10 +2172,18 @@ Deno.test('CSV', async function(t) {
|
||||
var cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 1);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts = {type:"binary", cellDates:true, dateNF:'d/m/yy'};
|
||||
opts.dateNF = 'd/m/yy';
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts = {type:"binary", cellDates:true, dateNF:'m/d/yy', UTC: true};
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getUTCMonth(), 1);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts.dateNF = 'd/m/yy';
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getUTCMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
});
|
||||
await t.step('should interpret values by default', async function(t) { plaintext_test(X.read(csv_bstr, {type:"binary"}), false); });
|
||||
await t.step('should generate strings if raw option is passed', async function(t) { plaintext_test(X.read(csv_str, {type:"string", raw:true}), true); });
|
||||
@ -2162,9 +2211,10 @@ Deno.test('CSV', async function(t) {
|
||||
var aoa = [
|
||||
["3a", "3 a", "3 a-1"],
|
||||
["3b", "3 b", "3 b-1"],
|
||||
["3p", "3 P", "3 p-1"],
|
||||
["3p", "3 P", "3 p-1"]
|
||||
];
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1;
|
||||
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true, UTC: 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]);
|
||||
@ -2172,14 +2222,46 @@ Deno.test('CSV', async function(t) {
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15);
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false, UTC: 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");
|
||||
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true, UTC: 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, UTC: 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, "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");
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal(B1.v * 24, 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal(B3.v * 24, 15);
|
||||
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);
|
||||
|
||||
});
|
||||
});
|
||||
@ -2316,18 +2398,31 @@ Deno.test('numbers', async function(t) {
|
||||
});
|
||||
|
||||
Deno.test('dbf', async function(t) {
|
||||
var wbs: Array<[string, X.WorkBook]> = ([
|
||||
var wbs: Array<[string, string]> = ([
|
||||
['d11', dir + 'dbf/d11.dbf'],
|
||||
['vfp3', dir + 'dbf/vfp3.dbf']
|
||||
]).map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), {type:TYPE})]; });
|
||||
]);
|
||||
var wbsfalse: Array<[string, X.WorkBook]> = ([]);
|
||||
var wbstrue: Array<[string, X.WorkBook]> = ([]);
|
||||
wbsfalse = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), { type:TYPE, cellDates: false })]; });
|
||||
wbstrue = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), { type:TYPE, cellDates: true })]; });
|
||||
await t.step(wbs[1][0], async function(t) {
|
||||
var ws = wbs[1][1].Sheets["Sheet1"];
|
||||
var wsfalse = wbsfalse[1][1].Sheets["Sheet1"];
|
||||
([
|
||||
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45],
|
||||
["C2", "v", 12.345], ["D2", "v", 1234.1], ["E2", "w", "19170219"],
|
||||
/* [F2", "w", "19170219"], */ ["G2", "v", 1231.4], ["H2", "v", 123234],
|
||||
["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
] as Array<[string, string, any]>).forEach(function(r) { assert.equal(get_cell(ws, r[0])[r[1]], r[2]); });
|
||||
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45], ["C2", "v", 12.345], ["D2", "v", 1234.1],
|
||||
["E2", "v", 6260], ["E2", "w", "19170219"],
|
||||
["F2", "v", 6260], ["F2", "w", "19170219"],
|
||||
["G2", "v", 1231.4], ["H2", "v", 123234], ["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
] as Array<[string, string, any]>).forEach(function(r) {
|
||||
assert.equal(get_cell(wsfalse, r[0])[r[1]], r[2]);
|
||||
});
|
||||
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"],
|
||||
] as Array<[string, string, any]>).forEach(function(r) {
|
||||
assert.equal(get_cell(wstrue, r[0])[r[1]].valueOf(), r[2].valueOf());
|
||||
});
|
||||
});
|
||||
if(false) await t.step("Ś╫êëτ⌡ś and Š╫ěéτ⌡š", async function(t) {
|
||||
([ [620, "Ś╫êëτ⌡ś"], [895, "Š╫ěéτ⌡š"] ] as Array<[number,string]>).forEach(function(r) {
|
||||
|
129
tests/core.js
generated
129
tests/core.js
generated
@ -1554,7 +1554,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();
|
||||
@ -1571,28 +1571,30 @@ function seq(end/*:number*/, start/*:?number*/)/*:Array<number>*/ {
|
||||
return o;
|
||||
}
|
||||
|
||||
var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
|
||||
var dnthresh = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
|
||||
var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
|
||||
var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
|
||||
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
|
||||
var epoch = v.getTime();
|
||||
if(date1904) epoch -= 1462*24*60*60*1000;
|
||||
var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
|
||||
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
var epoch = /*#__PURE__*/v.getTime();
|
||||
var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
if(date1904) return res - 1462;
|
||||
return res < 60 ? res - 1 : res;
|
||||
}
|
||||
var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
|
||||
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2017-02-19T19:06:09');
|
||||
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
|
||||
var good_pd = good_pd_date.getFullYear() == 2017;
|
||||
function parseDate(str/*:string|Date*/)/*:Date*/ {
|
||||
var d = new Date(str);
|
||||
if(good_pd) return d;
|
||||
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
|
||||
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
|
||||
var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
|
||||
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]] sans "Z"
|
||||
/* parses a date string as a UTC date */
|
||||
function parseDate(str/*:string*/, date1904/*:boolean*/)/*:Date*/ {
|
||||
if(str instanceof Date) return str;
|
||||
if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
|
||||
var s = d.getFullYear();
|
||||
if(str.indexOf("" + s) > -1) return d;
|
||||
d.setFullYear(d.getFullYear() + 100); return d;
|
||||
}
|
||||
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
|
||||
return new Date(Date.UTC(+n[0], +n[1] - 1, +n[2], +n[3], +n[4], +n[5]));
|
||||
var m = str.match(pdre1);
|
||||
if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
|
||||
m = str.match(pdre2);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
|
||||
m = str.match(pdre3);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt(m[7].slice(1), 10))||0)));
|
||||
var d = new Date(str);
|
||||
return d;
|
||||
}
|
||||
|
||||
var fixdate = browser ? parseDate("2014-02-19T14:30:00.000Z") : new Date("2014-02-19T14:30Z");
|
||||
@ -1816,7 +1818,7 @@ describe('roundtrip features', function() {
|
||||
];
|
||||
var o = X.utils.sheet_to_json(X.utils.json_to_sheet(data, {cellDates:true}));
|
||||
data.forEach(function(row, i) {
|
||||
Object.keys(row).forEach(function(k) { assert.equal(row[k], o[i][k]); });
|
||||
Object.keys(row).forEach(function(k) { assert.equal(row[k].valueOf(), o[i][k].valueOf()); });
|
||||
});
|
||||
});
|
||||
|
||||
@ -2189,7 +2191,15 @@ describe('CSV', function() {
|
||||
assert.equal(cell.w, '2/19/14');
|
||||
});
|
||||
it('should honor dateNF override', function() {
|
||||
var opts = ({type:"binary", dateNF:"YYYY-MM-DD"}/*:any*/);
|
||||
var opts = ({type:"binary", dateNF:"YYYY-MM-DD", cellNF: true}/*:any*/);
|
||||
var cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
/* NOTE: IE interprets 2-digit years as 19xx */
|
||||
assert.ok(cell.w == '2014-02-19' || cell.w == '1914-02-19' || cell.w == "2/19/14");
|
||||
assert.equal(cell.z, "YYYY-MM-DD");
|
||||
opts.cellDates = true; opts.dateNF = "YY-MM-DD";
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
assert.ok(cell.w == '14-02-19' || cell.w == "2/19/14");
|
||||
var opts = ({type:"binary", dateNF:"YYYY-MM-DD", UTC: true}/*:any*/);
|
||||
var cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
/* NOTE: IE interprets 2-digit years as 19xx */
|
||||
assert.ok(cell.w == '2014-02-19' || cell.w == '1914-02-19');
|
||||
@ -2203,10 +2213,18 @@ describe('CSV', function() {
|
||||
var cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 1);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts = {type:"binary", cellDates:true, dateNF:'d/m/yy'};
|
||||
opts.dateNF = 'd/m/yy';
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts = {type:"binary", cellDates:true, dateNF:'m/d/yy', UTC: true};
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getUTCMonth(), 1);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
opts.dateNF = 'd/m/yy';
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getUTCMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
});
|
||||
it('should interpret values by default', function() { plaintext_test(X.read(csv_bstr, {type:"binary"}), false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(csv_str, {type:"string", raw:true}), true); });
|
||||
@ -2236,7 +2254,8 @@ describe('CSV', function() {
|
||||
["3b", "3 b", "3 b-1"],
|
||||
["3p", "3 P", "3 p-1"]
|
||||
];
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1;
|
||||
|
||||
var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true, UTC: 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]);
|
||||
@ -2244,14 +2263,46 @@ describe('CSV', function() {
|
||||
assert.equal(get_cell(ws, "B2").v, "3 b");
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15);
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false, UTC: 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");
|
||||
|
||||
ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true, UTC: 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, UTC: 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, "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");
|
||||
var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal(B1.v * 24, 3);
|
||||
var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal(B3.v * 24, 15);
|
||||
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);
|
||||
|
||||
});
|
||||
});
|
||||
@ -2402,19 +2453,31 @@ describe('dbf', function() {
|
||||
['d11', dir + 'dbf/d11.dbf'],
|
||||
['vfp3', dir + 'dbf/vfp3.dbf']
|
||||
]/*:any*/);
|
||||
var wbsfalse = ([]);
|
||||
var wbstrue = ([]);
|
||||
var bef = (function() {
|
||||
wbs = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), {type:TYPE})]; });
|
||||
wbsfalse = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), { type:TYPE, cellDates: false })]; });
|
||||
wbstrue = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), { type:TYPE, cellDates: true })]; });
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
it(wbs[1][0], function() {
|
||||
var ws = wbs[1][1].Sheets["Sheet1"];
|
||||
var wsfalse = wbsfalse[1][1].Sheets["Sheet1"];
|
||||
[
|
||||
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45],
|
||||
["C2", "v", 12.345], ["D2", "v", 1234.1], ["E2", "w", "19170219"],
|
||||
/* [F2", "w", "19170219"], */ ["G2", "v", 1231.4], ["H2", "v", 123234],
|
||||
["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
].forEach(function(r) { assert.equal(get_cell(ws, r[0])[r[1]], r[2]); });
|
||||
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45], ["C2", "v", 12.345], ["D2", "v", 1234.1],
|
||||
["E2", "v", 6260], ["E2", "w", "19170219"],
|
||||
["F2", "v", 6260], ["F2", "w", "19170219"],
|
||||
["G2", "v", 1231.4], ["H2", "v", 123234], ["I2", "v", true], ["L2", "v", "SheetJS"]
|
||||
].forEach(function(r) {
|
||||
assert.equal(get_cell(wsfalse, r[0])[r[1]], r[2]);
|
||||
});
|
||||
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"]
|
||||
].forEach(function(r) {
|
||||
assert.equal(get_cell(wstrue, r[0])[r[1]].valueOf(), r[2].valueOf());
|
||||
});
|
||||
});
|
||||
if(!browser || typeof cptable !== 'undefined') it("Ś╫êëτ⌡ś and Š╫ěéτ⌡š", function() {
|
||||
[ [620, "Ś╫êëτ⌡ś"], [895, "Š╫ěéτ⌡š"] ].forEach(function(r) {
|
||||
|
59
types/index.d.ts
vendored
59
types/index.d.ts
vendored
@ -139,8 +139,20 @@ export interface DateNFOption {
|
||||
dateNF?: NumberFormat;
|
||||
}
|
||||
|
||||
export interface UTCOption {
|
||||
/**
|
||||
* For plaintext formats, interpret ambiguous datetimes in UTC
|
||||
* If explicitly set to `false`, dates will be parsed in local time.
|
||||
*
|
||||
* The `true` option is consistent with spreadsheet application export.
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
UTC?: boolean;
|
||||
}
|
||||
|
||||
/** Options for read and readFile */
|
||||
export interface ParsingOptions extends CommonOptions {
|
||||
export interface ParsingOptions extends UTCOption, CommonOptions {
|
||||
/** Input data encoding */
|
||||
type?: 'base64' | 'binary' | 'buffer' | 'file' | 'array' | 'string';
|
||||
|
||||
@ -294,6 +306,12 @@ export interface WritingOptions extends CommonOptions {
|
||||
* If this option is omitted, the first worksheet will be exported.
|
||||
*/
|
||||
sheet?: string | number;
|
||||
|
||||
/** Field Separator ("delimiter") for CSV / Text output */
|
||||
FS?: string;
|
||||
|
||||
/** Record Separator ("row separator") for CSV / Text output */
|
||||
RS?: string;
|
||||
}
|
||||
|
||||
/** Workbook Object */
|
||||
@ -803,9 +821,27 @@ export interface Sheet2JSONOpts extends DateNFOption {
|
||||
|
||||
/** if true, return raw numbers; if false, return formatted numbers */
|
||||
rawNumbers?: boolean;
|
||||
|
||||
/**
|
||||
* If true, return dates whose UTC interpretation is correct
|
||||
* By default, return dates whose local interpretation is correct
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
UTC?: boolean;
|
||||
}
|
||||
|
||||
export interface AOA2SheetOpts extends CommonOptions, DateNFOption {
|
||||
export interface UTCDateOption {
|
||||
/**
|
||||
* If true, dates are interpreted using the UTC methods
|
||||
* By default, dates are interpreted in the local timezone
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
UTC?: boolean;
|
||||
}
|
||||
|
||||
export interface AOA2SheetOpts extends CommonOptions, UTCDateOption, DateNFOption {
|
||||
/**
|
||||
* Create cell objects for stub cells
|
||||
* @default false
|
||||
@ -815,7 +851,7 @@ export interface AOA2SheetOpts extends CommonOptions, DateNFOption {
|
||||
|
||||
export interface SheetAOAOpts extends AOA2SheetOpts, OriginOption {}
|
||||
|
||||
export interface JSON2SheetOpts extends CommonOptions, DateNFOption, OriginOption {
|
||||
export interface JSON2SheetOpts extends CommonOptions, UTCDateOption, DateNFOption, OriginOption {
|
||||
/** Use specified column order */
|
||||
header?: string[];
|
||||
|
||||
@ -841,6 +877,14 @@ export interface Table2SheetOpts extends CommonOptions, DateNFOption, OriginOpti
|
||||
* @default "Sheet1"
|
||||
*/
|
||||
sheet?: string;
|
||||
|
||||
/**
|
||||
* If true, interpret date strings as if they are UTC.
|
||||
* By default, date strings are interpreted in the local timezone.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
UTC?: boolean;
|
||||
}
|
||||
|
||||
export interface Table2BookOpts extends Table2SheetOpts {
|
||||
@ -887,15 +931,6 @@ export interface XLSX$Utils {
|
||||
/** Generates a list of the formulae (with value fallbacks) */
|
||||
sheet_to_formulae(worksheet: WorkSheet): string[];
|
||||
|
||||
/** Generates DIF */
|
||||
sheet_to_dif(worksheet: WorkSheet, options?: Sheet2HTMLOpts): string;
|
||||
|
||||
/** Generates SYLK (Symbolic Link) */
|
||||
sheet_to_slk(worksheet: WorkSheet, options?: Sheet2HTMLOpts): string;
|
||||
|
||||
/** Generates ETH */
|
||||
sheet_to_eth(worksheet: WorkSheet, options?: Sheet2HTMLOpts): string;
|
||||
|
||||
/* --- Cell Address Utilities --- */
|
||||
|
||||
/** Converts 0-indexed cell address to A1 form */
|
||||
|
@ -21,9 +21,6 @@ interface Tester {
|
||||
const jsonvalues: Tester[] = XLSX.utils.sheet_to_json<Tester>(firstworksheet);
|
||||
const csv: string = XLSX.utils.sheet_to_csv(firstworksheet);
|
||||
const txt: string = XLSX.utils.sheet_to_txt(firstworksheet);
|
||||
const dif: string = XLSX.utils.sheet_to_dif(firstworksheet);
|
||||
const slk: string = XLSX.utils.sheet_to_slk(firstworksheet);
|
||||
const eth: string = XLSX.utils.sheet_to_eth(firstworksheet);
|
||||
const formulae: string[] = XLSX.utils.sheet_to_formulae(firstworksheet);
|
||||
const aoa: any[][] = XLSX.utils.sheet_to_json<any[]>(firstworksheet, {raw:true, header:1});
|
||||
|
||||
|
2214
xlsx.flow.js
2214
xlsx.flow.js
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,10 @@
|
||||
/*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
/* vim: set ts=2: */
|
||||
/*exported XLSX */
|
||||
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */
|
||||
/*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.19.3';
|
||||
XLSX.version = '0.20.0';
|
||||
var current_codepage = 1200, current_ansi = 1252;
|
||||
/*:: declare var cptable:any; */
|
||||
/*global cptable:true, window */
|
||||
@ -135,6 +135,26 @@ function Base64_encode_pass(input) {
|
||||
}
|
||||
return o;
|
||||
}
|
||||
function Base64_encode_arr(input) {
|
||||
var o = "";
|
||||
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
|
||||
for (var i = 0; i < input.length; ) {
|
||||
c1 = input[i++];
|
||||
e1 = c1 >> 2;
|
||||
c2 = input[i++];
|
||||
e2 = (c1 & 3) << 4 | c2 >> 4;
|
||||
c3 = input[i++];
|
||||
e3 = (c2 & 15) << 2 | c3 >> 6;
|
||||
e4 = c3 & 63;
|
||||
if (isNaN(c2)) {
|
||||
e3 = e4 = 64;
|
||||
} else if (isNaN(c3)) {
|
||||
e4 = 64;
|
||||
}
|
||||
o += Base64_map.charAt(e1) + Base64_map.charAt(e2) + Base64_map.charAt(e3) + Base64_map.charAt(e4);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
function Base64_decode(input) {
|
||||
var o = "";
|
||||
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
|
||||
@ -494,15 +514,6 @@ function SSF_parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
|
||||
out.q = dow;
|
||||
return out;
|
||||
}
|
||||
var SSFbasedate = /*#__PURE__*/new Date(1899, 11, 31, 0, 0, 0);
|
||||
var SSFdnthresh = /*#__PURE__*/SSFbasedate.getTime();
|
||||
var SSFbase1904 = /*#__PURE__*/new Date(1900, 2, 1, 0, 0, 0);
|
||||
function datenum_local(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
|
||||
var epoch = /*#__PURE__*/v.getTime();
|
||||
if(date1904) epoch -= 1461*24*60*60*1000;
|
||||
else if(v >= SSFbase1904) epoch += 24*60*60*1000;
|
||||
return (epoch - (SSFdnthresh + (/*#__PURE__*/v.getTimezoneOffset() - /*#__PURE__*/SSFbasedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
|
||||
}
|
||||
/* ECMA-376 18.8.30 numFmt*/
|
||||
/* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
|
||||
/* exponent >= -9 and <= 9 */
|
||||
@ -560,7 +571,7 @@ function SSF_general(v/*:any*/, opts/*:any*/) {
|
||||
case 'undefined': return "";
|
||||
case 'object':
|
||||
if(v == null) return "";
|
||||
if(v instanceof Date) return SSF_format(14, datenum_local(v, opts && opts.date1904), opts);
|
||||
if(v instanceof Date) return SSF_format(14, datenum(v, opts && opts.date1904), opts);
|
||||
}
|
||||
throw new Error("unsupported value in General format: " + v);
|
||||
}
|
||||
@ -1248,7 +1259,7 @@ function SSF_format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
|
||||
break;
|
||||
}
|
||||
if(SSF_isgeneral(sfmt,0)) return SSF_general(v, o);
|
||||
if(v instanceof Date) v = datenum_local(v, o.date1904);
|
||||
if(v instanceof Date) v = datenum(v, o.date1904);
|
||||
var f = choose_fmt(sfmt, v);
|
||||
if(SSF_isgeneral(f[1])) return SSF_general(v, o);
|
||||
if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
|
||||
@ -1335,6 +1346,7 @@ var dateNFregex = /[dD]+|[mM]+|[yYeE]+|[Hh]+|[Ss]+/g;
|
||||
function dateNF_regex(dateNF/*:string|number*/)/*:RegExp*/ {
|
||||
var fmt = typeof dateNF == "number" ? table_fmt[dateNF] : dateNF;
|
||||
fmt = fmt.replace(dateNFregex, "(\\d+)");
|
||||
dateNFregex.lastIndex = 0;
|
||||
return new RegExp("^" + fmt + "$");
|
||||
}
|
||||
function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/*:string*/ {
|
||||
@ -1347,6 +1359,7 @@ function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/
|
||||
case 'm': if(H >= 0) M = v; else m = v; break;
|
||||
}
|
||||
});
|
||||
dateNFregex.lastIndex = 0;
|
||||
if(S >= 0 && M == -1 && m >= 0) { M = m; m = -1; }
|
||||
var datestr = (("" + (Y>=0?Y: new Date().getFullYear())).slice(-4) + "-" + ("00" + (m>=1?m:1)).slice(-2) + "-" + ("00" + (d>=1?d:1)).slice(-2));
|
||||
if(datestr.length == 7) datestr = "0" + datestr;
|
||||
@ -3274,7 +3287,7 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
|
||||
/*:: declare var chrome: any; */
|
||||
if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
|
||||
if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
|
||||
return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
|
||||
return chrome.downloads.download({ url: url, filename: fname, saveAs: true });
|
||||
}
|
||||
var a = document.createElement("a");
|
||||
if(a.download != null) {
|
||||
@ -3284,6 +3297,10 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
|
||||
if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
|
||||
return url;
|
||||
}
|
||||
} else if(typeof URL !== 'undefined' && !URL.createObjectURL && typeof chrome === 'object') {
|
||||
/* manifest v3 extensions -- no URL.createObjectURL */
|
||||
var b64 = "data:application/octet-stream;base64," + Base64_encode_arr(new Uint8Array(blobify(data)));
|
||||
return chrome.downloads.download({ url: b64, filename: fname, saveAs: true });
|
||||
}
|
||||
}
|
||||
// $FlowIgnore
|
||||
@ -3342,22 +3359,19 @@ function evert_arr(obj/*:any*/)/*:EvertArrType*/ {
|
||||
return o;
|
||||
}
|
||||
|
||||
var basedate = /*#__PURE__*/new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
|
||||
var dnthresh = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
|
||||
var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
|
||||
var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
|
||||
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
|
||||
var epoch = /*#__PURE__*/v.getTime();
|
||||
if(date1904) epoch -= 1462*24*60*60*1000;
|
||||
var dnthresh = /*#__PURE__*/basedate.getTime() + (/*#__PURE__*/v.getTimezoneOffset() - /*#__PURE__*/basedate.getTimezoneOffset()) * 60000;
|
||||
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
if(date1904) { res -= 1462; return res < -1402 ? res - 1 : res; }
|
||||
return res < 60 ? res - 1 : res;
|
||||
}
|
||||
var refdate = /*#__PURE__*/new Date();
|
||||
var dnthresh = /*#__PURE__*/basedate.getTime() + (/*#__PURE__*/refdate.getTimezoneOffset() - /*#__PURE__*/basedate.getTimezoneOffset()) * 60000;
|
||||
var refoffset = /*#__PURE__*/refdate.getTimezoneOffset();
|
||||
function numdate(v/*:number*/)/*:Date*/ {
|
||||
function numdate(v/*:number*/)/*:Date|number*/ {
|
||||
if(v >= 60 && v < 61) return v;
|
||||
var out = new Date();
|
||||
out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh);
|
||||
if (out.getTimezoneOffset() !== refoffset) {
|
||||
out.setTime(out.getTime() + (out.getTimezoneOffset() - refoffset) * 60000);
|
||||
}
|
||||
out.setTime((v>60 ? v : (v+1)) * 24 * 60 * 60 * 1000 + dnthresh);
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -3388,28 +3402,22 @@ function parse_isodur(s) {
|
||||
return sec;
|
||||
}
|
||||
|
||||
var good_pd_date_1 = /*#__PURE__*/new Date('2017-02-19T19:06:09.000Z');
|
||||
var good_pd_date = /*#__PURE__*/isNaN(/*#__PURE__*/good_pd_date_1.getFullYear()) ? /*#__PURE__*/new Date('2/19/17') : good_pd_date_1;
|
||||
var good_pd = /*#__PURE__*/good_pd_date.getFullYear() == 2017;
|
||||
/* parses a date as a local date */
|
||||
function parseDate(str/*:string|Date*/, fixdate/*:?number*/)/*:Date*/ {
|
||||
var d = new Date(str);
|
||||
if(good_pd) {
|
||||
/*:: if(fixdate == null) fixdate = 0; */
|
||||
if(fixdate > 0) d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
|
||||
else if(fixdate < 0) d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000);
|
||||
return d;
|
||||
}
|
||||
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
|
||||
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
|
||||
var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
|
||||
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]], sans "Z"
|
||||
/* parses a date string as a UTC date */
|
||||
function parseDate(str/*:string*/, date1904/*:boolean*/)/*:Date*/ {
|
||||
if(str instanceof Date) return str;
|
||||
if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
|
||||
var s = d.getFullYear();
|
||||
if(str.indexOf("" + s) > -1) return d;
|
||||
d.setFullYear(d.getFullYear() + 100); return d;
|
||||
}
|
||||
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
|
||||
var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
|
||||
if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000);
|
||||
return out;
|
||||
var m = str.match(pdre1);
|
||||
if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
|
||||
m = str.match(pdre2);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
|
||||
/* TODO: 1900-02-29T00:00:00.000 should return a flag to treat as a date code (affects xlml) */
|
||||
m = str.match(pdre3);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt(m[7].slice(1), 10))||0)));
|
||||
var d = new Date(str);
|
||||
return d;
|
||||
}
|
||||
|
||||
function cc2str(arr/*:Array<number>*/, debomit)/*:string*/ {
|
||||
@ -3440,8 +3448,18 @@ function cc2str(arr/*:Array<number>*/, debomit)/*:string*/ {
|
||||
return new TextDecoder("latin1").decode(arr).replace(/[€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ]/g, function(c) { return rev[c] || c; });
|
||||
} catch(e) {}
|
||||
|
||||
var o = [];
|
||||
for(var i = 0; i != arr.length; ++i) o.push(String.fromCharCode(arr[i]));
|
||||
var o = [], i = 0;
|
||||
// this cascade is for the browsers and runtimes of antiquity (and for modern runtimes that lack TextEncoder)
|
||||
try {
|
||||
for(i = 0; i < arr.length - 65536; i+=65536) o.push(String.fromCharCode.apply(0, arr.slice(i, i + 65536)));
|
||||
o.push(String.fromCharCode.apply(0, arr.slice(i)));
|
||||
} catch(e) { try {
|
||||
for(; i < arr.length - 16384; i+=16384) o.push(String.fromCharCode.apply(0, arr.slice(i, i + 16384)));
|
||||
o.push(String.fromCharCode.apply(0, arr.slice(i)));
|
||||
} catch(e) {
|
||||
for(; i != arr.length; ++i) o.push(String.fromCharCode(arr[i]));
|
||||
}
|
||||
}
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
@ -3471,32 +3489,49 @@ function fuzzynum(s/*:string*/)/*:number*/ {
|
||||
|
||||
/* NOTE: Chrome rejects bare times like 1:23 PM */
|
||||
var FDRE1 = /^(0?\d|1[0-2])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))\s+([ap])m?$/;
|
||||
var FDRE2 = /^([01]?\d|2[0-3])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))$/;
|
||||
var FDISO = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)(\.\d+)?[Z]?$/; // YYYY-mm-dd(T or space)HH:MM:SS[.UUU][Z]
|
||||
|
||||
/* TODO: 1904 adjustment */
|
||||
var utc_append_works = new Date("6/9/69 00:00 UTC").valueOf() == -17798400000;
|
||||
function fuzzytime1(M) /*:Date*/ {
|
||||
/* TODO: 1904 adjustment, keep in sync with base date */
|
||||
if(!M[2]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0);
|
||||
if(!M[2]) return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0));
|
||||
if(M[3]) {
|
||||
if(M[4]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000);
|
||||
else return new Date(1899,11,30,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000);
|
||||
if(M[4]) return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000));
|
||||
else return new Date(Date.UTC(1899,11,31,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000));
|
||||
}
|
||||
else if(M[5]) return new Date(1899,11,30, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0);
|
||||
else return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0);
|
||||
else if(M[5]) return new Date(Date.UTC(1899,11,31, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0));
|
||||
else return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0));
|
||||
}
|
||||
function fuzzytime2(M) /*:Date*/ {
|
||||
if(!M[2]) return new Date(Date.UTC(1899,11,31,+M[1], 0, 0, 0));
|
||||
if(M[3]) {
|
||||
if(M[4]) return new Date(Date.UTC(1899,11,31,+M[1], +M[2], +M[4], parseFloat(M[3])*1000));
|
||||
else return new Date(Date.UTC(1899,11,31,0, +M[1], +M[2], parseFloat(M[3])*1000));
|
||||
}
|
||||
else if(M[5]) return new Date(Date.UTC(1899,11,31, +M[1], +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0));
|
||||
else return new Date(Date.UTC(1899,11,31,+M[1], +M[2], 0, 0));
|
||||
}
|
||||
var lower_months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'];
|
||||
function fuzzydate(s/*:string*/)/*:Date*/ {
|
||||
// See issue 2863 -- this is technically not supported in Excel but is otherwise useful
|
||||
if(FDISO.test(s)) return s.indexOf("Z") == -1 ? local_to_utc(new Date(s)) : new Date(s);
|
||||
var lower = s.toLowerCase();
|
||||
var lnos = lower.replace(/\s+/g, " ").trim();
|
||||
var M = lnos.match(FDRE1);
|
||||
if(M) return fuzzytime1(M);
|
||||
|
||||
var o = new Date(s), n = new Date(NaN);
|
||||
M = lnos.match(FDRE2);
|
||||
if(M) return fuzzytime2(M);
|
||||
M = lnos.match(pdre3);
|
||||
if(M) return new Date(Date.UTC(+M[1], +M[2]-1, +M[3], +M[4], +M[5], ((M[6] && parseInt(M[6].slice(1), 10))|| 0), ((M[7] && parseInt(M[7].slice(1), 10))||0)));
|
||||
var o = new Date(utc_append_works && s.indexOf("UTC") == -1 ? s + " UTC": s), n = new Date(NaN);
|
||||
var y = o.getYear(), m = o.getMonth(), d = o.getDate();
|
||||
if(isNaN(d)) return n;
|
||||
if(lower.match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) {
|
||||
lower = lower.replace(/[^a-z]/g,"").replace(/([^a-z]|^)[ap]m?([^a-z]|$)/,"");
|
||||
if(lower.length > 3 && lower_months.indexOf(lower) == -1) return n;
|
||||
} else if(lower.replace(/[ap]m?/, "").match(/[a-z]/)) return n;
|
||||
if(y < 0 || y > 8099 || s.match(/[^-0-9:,\/\\]/)) return n;
|
||||
if(y < 0 || y > 8099 || s.match(/[^-0-9:,\/\\\ ]/)) return n;
|
||||
return o;
|
||||
}
|
||||
|
||||
@ -3509,6 +3544,13 @@ var split_regex = /*#__PURE__*/(function() {
|
||||
return o;
|
||||
};
|
||||
})();
|
||||
|
||||
function utc_to_local(utc) {
|
||||
return new Date(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate(), utc.getUTCHours(), utc.getUTCMinutes(), utc.getUTCSeconds(), utc.getUTCMilliseconds());
|
||||
}
|
||||
function local_to_utc(local) {
|
||||
return new Date(Date.UTC(local.getFullYear(), local.getMonth(), local.getDate(), local.getHours(), local.getMinutes(), local.getSeconds(), local.getMilliseconds()));
|
||||
}
|
||||
function getdatastr(data)/*:?string*/ {
|
||||
if(!data) return null;
|
||||
if(data.content && data.type) return cc2str(data.content, true);
|
||||
@ -4439,6 +4481,7 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
|
||||
else if(typeof cell.v === 'boolean') cell.t = 'b';
|
||||
else if(cell.v instanceof Date) {
|
||||
cell.z = o.dateNF || table_fmt[14];
|
||||
if(!o.UTC) cell.v = local_to_utc(cell.v);
|
||||
if(o.cellDates) { cell.t = 'd'; cell.w = SSF_format(cell.z, datenum(cell.v, o.date1904)); }
|
||||
else { cell.t = 'n'; cell.v = datenum(cell.v, o.date1904); cell.w = SSF_format(cell.z, cell.v); }
|
||||
}
|
||||
@ -5705,7 +5748,10 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
|
||||
if(s.trim().length) out[R][C] = s.replace(/\s+$/,"");
|
||||
break;
|
||||
case 'D':
|
||||
if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8));
|
||||
if(s.length === 8) {
|
||||
out[R][C] = new Date(Date.UTC(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8), 0, 0, 0, 0));
|
||||
if(!(opts && opts.UTC)) { out[R][C] = utc_to_local(out[R][C]); }
|
||||
}
|
||||
else out[R][C] = s;
|
||||
break;
|
||||
case 'F': out[R][C] = parseFloat(s.trim()); break;
|
||||
@ -5728,7 +5774,12 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
|
||||
// NOTE: dBASE specs appear to be incorrect
|
||||
out[R][C] = new Date(dd.read_shift(-8, 'f') - 0x388317533400);
|
||||
break;
|
||||
case 'T': out[R][C] = new Date((dd.read_shift(4) - 0x253D8C) * 0x5265C00 + dd.read_shift(4)); break;
|
||||
case 'T': {
|
||||
var hi = dd.read_shift(4), lo = dd.read_shift(4);
|
||||
if(hi == 0 && lo == 0) break;
|
||||
out[R][C] = new Date((hi - 0x253D8C) * 0x5265C00 + lo);
|
||||
if(!(opts && opts.UTC)) out[R][C] = utc_to_local(out[R][C]);
|
||||
} break;
|
||||
case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4 + (dd.read_shift(4, 'i')/1e4)*Math.pow(2,32); break;
|
||||
case 'O': out[R][C] = -dd.read_shift(-8, 'f'); break;
|
||||
case 'B': if(vfp && fields[C].len == 8) { out[R][C] = dd.read_shift(8,'f'); break; }
|
||||
@ -5931,6 +5982,8 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
var sylk_char_fn = function(_, $1){ var o = sylk_escapes[$1]; return typeof o == "number" ? _getansi(o) : o; };
|
||||
var decode_sylk_char = function($$, $1, $2) { var newcc = (($1.charCodeAt(0) - 0x20)<<4) | ($2.charCodeAt(0) - 0x30); return newcc == 59 ? $$ : _getansi(newcc); };
|
||||
sylk_escapes["|"] = 254;
|
||||
/* TODO: evert the escape map */
|
||||
var encode_sylk_str = function($$) { return $$.replace(/\n/g, "\x1b :").replace(/\r/g, "\x1b ="); };
|
||||
/* https://oss.sheetjs.com/notes/sylk/ for more details */
|
||||
function sylk_to_aoa(d/*:RawData*/, opts)/*:[AOA, Worksheet]*/ {
|
||||
switch(opts.type) {
|
||||
@ -5983,8 +6036,9 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
// case 'NU': // ??
|
||||
case 'C': /* cell */
|
||||
var C_seen_K = false, C_seen_X = false, C_seen_S = false, C_seen_E = false, _R = -1, _C = -1, formula = "", cell_t = "z";
|
||||
var cmnt = "";
|
||||
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
|
||||
case 'A': break; // TODO: comment
|
||||
case 'A': cmnt = record[rj].slice(1); break; // TODO: comment
|
||||
case 'X': C = parseInt(record[rj].slice(1), 10)-1; C_seen_X = true; break;
|
||||
case 'Y':
|
||||
R = parseInt(record[rj].slice(1), 10)-1; if(!C_seen_X) C = 0;
|
||||
@ -5996,10 +6050,9 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
else if(val === 'TRUE' || val === 'FALSE') { val = val === 'TRUE'; cell_t = "b"; }
|
||||
else if(!isNaN(fuzzynum(val))) {
|
||||
val = fuzzynum(val); cell_t = "n";
|
||||
if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) { val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : val); cell_t = "d"; }
|
||||
} else if(!isNaN(fuzzydate(val).getDate())) {
|
||||
val = parseDate(val); cell_t = "d";
|
||||
if(!opts.cellDates) { cell_t = "n"; val = datenum(val, wb.Workbook.WBProps.date1904); }
|
||||
if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) {
|
||||
val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : val); cell_t = typeof val == "number" ? "n" : "d";
|
||||
}
|
||||
}
|
||||
if(typeof $cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = $cptable.utils.decode(opts.codepage, val);
|
||||
C_seen_K = true;
|
||||
@ -6035,6 +6088,10 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
if(!arr[R][C]) arr[R][C] = { t: 'n', f: formula };
|
||||
else arr[R][C].f = formula;
|
||||
}
|
||||
if(cmnt) {
|
||||
if(!arr[R][C]) arr[R][C] = { t: 'z' };
|
||||
arr[R][C].c = [{a:"SheetJSYLK", t: cmnt}];
|
||||
}
|
||||
break;
|
||||
case 'F': /* Format */
|
||||
var F_seen = 0;
|
||||
@ -6096,7 +6153,7 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
return outwb;
|
||||
}
|
||||
|
||||
function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*//*::, opts*/)/*:string*/ {
|
||||
function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/)/*:string*/ {
|
||||
var o = "C;Y" + (R+1) + ";X" + (C+1) + ";K";
|
||||
switch(cell.t) {
|
||||
case 'n':
|
||||
@ -6104,12 +6161,19 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break;
|
||||
case 'b': o += cell.v ? "TRUE" : "FALSE"; break;
|
||||
case 'e': o += cell.w || cell.v; break;
|
||||
case 'd': o += '"' + (cell.w || cell.v) + '"'; break;
|
||||
case 'd': o += datenum(parseDate(cell.v, date1904), date1904); break;
|
||||
case 's': o += '"' + (cell.v == null ? "" : String(cell.v)).replace(/"/g,"").replace(/;/g, ";;") + '"'; break;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
function write_ws_cmnt_sylk(cmnt/*:Comment*/, R/*:number*/, C/*:number*/)/*:string*/ {
|
||||
var o = "C;Y" + (R+1) + ";X" + (C+1) + ";A";
|
||||
/* TODO: max length? */
|
||||
o += encode_sylk_str(cmnt.map(function(c) { return c.t; }).join(""));
|
||||
return o;
|
||||
}
|
||||
|
||||
function write_ws_cols_sylk(out, cols) {
|
||||
cols.forEach(function(col, i) {
|
||||
var rec = "F;W" + (i+1) + " " + (i+1) + " ";
|
||||
@ -6134,6 +6198,7 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
}
|
||||
|
||||
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/, wb/*:?WorkBook*/)/*:string*/ {
|
||||
if(!opts) opts = {}; opts._formats = ["General"];
|
||||
/* TODO: codepage */
|
||||
var preamble/*:Array<string>*/ = ["ID;PSheetJS;N;E"], o/*:Array<string>*/ = [];
|
||||
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
|
||||
@ -6141,23 +6206,44 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
var RS = "\r\n";
|
||||
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
|
||||
var _lastfmt = "General";
|
||||
preamble.push("P;PGeneral");
|
||||
/* Excel has been inconsistent in comment placement */
|
||||
var R = r.s.r, C = r.s.c, p = [];
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
if(dense && !ws["!data"][R]) continue;
|
||||
p = [];
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
|
||||
if(!cell || !cell.c) continue;
|
||||
p.push(write_ws_cmnt_sylk(cell.c, R, C));
|
||||
}
|
||||
if(p.length) o.push(p.join(RS));
|
||||
}
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
if(dense && !ws["!data"][R]) continue;
|
||||
p = [];
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
|
||||
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
|
||||
if((cell.z||(cell.t == "d" ? table_fmt[14] : "General")) != _lastfmt) {
|
||||
var ifmt = opts._formats.indexOf(cell.z);
|
||||
if(ifmt == -1) { opts._formats.push(cell.z); ifmt = opts._formats.length - 1; preamble.push("P;P" + cell.z.replace(/;/g, ";;")); }
|
||||
p.push("F;P" + ifmt + ";Y" + (R+1) + ";X" + (C+1));
|
||||
}
|
||||
p.push(write_ws_cell_sylk(cell, ws, R, C, opts, d1904));
|
||||
}
|
||||
o.push(p.join(RS));
|
||||
}
|
||||
|
||||
preamble.push("F;P0;DG0G8;M255");
|
||||
if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
|
||||
if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
|
||||
|
||||
preamble.push("B;Y" + (r.e.r - r.s.r + 1) + ";X" + (r.e.c - r.s.c + 1) + ";D" + [r.s.c,r.s.r,r.e.c,r.e.r].join(" "));
|
||||
preamble.push("O;L;D;B" + (d1904 ? ";V4" : "") + ";K47;G100 0.001");
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
if(dense && !ws["!data"][R]) continue;
|
||||
var p = [];
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
|
||||
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
|
||||
p.push(write_ws_cell_sylk(cell, ws, R, C, opts)); // TODO: pass date1904 info
|
||||
}
|
||||
o.push(p.join(RS));
|
||||
}
|
||||
|
||||
delete opts._formats;
|
||||
return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
|
||||
}
|
||||
|
||||
@ -6197,7 +6283,10 @@ var DIF = /*#__PURE__*/(function() {
|
||||
if(data === 'TRUE') arr[R][C] = true;
|
||||
else if(data === 'FALSE') arr[R][C] = false;
|
||||
else if(!isNaN(fuzzynum(value))) arr[R][C] = fuzzynum(value);
|
||||
else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value);
|
||||
else if(!isNaN(fuzzydate(value).getDate())) {
|
||||
arr[R][C] = parseDate(value);
|
||||
if(!(opts && opts.UTC)) { arr[R][C] = utc_to_local(arr[R][C]); }
|
||||
}
|
||||
else arr[R][C] = value;
|
||||
++C; break;
|
||||
case 1:
|
||||
@ -6478,9 +6567,11 @@ var PRN = /*#__PURE__*/(function() {
|
||||
var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0);
|
||||
var _re/*:?RegExp*/ = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
|
||||
function finish_cell() {
|
||||
/* TODO: fuzzy parsers should pass back assumed number format */
|
||||
var s = str.slice(start, end); if(s.slice(-1) == "\r") s = s.slice(0, -1);
|
||||
var cell = ({}/*:any*/);
|
||||
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
|
||||
if(o.cellText !== false) cell.w = s;
|
||||
if(s.length === 0) cell.t = 'z';
|
||||
else if(o.raw) { cell.t = 's'; cell.v = s; }
|
||||
else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; }
|
||||
@ -6490,14 +6581,14 @@ var PRN = /*#__PURE__*/(function() {
|
||||
else { cell.t = 's'; cell.v = s; } }
|
||||
else if(s == "TRUE") { cell.t = 'b'; cell.v = true; }
|
||||
else if(s == "FALSE") { cell.t = 'b'; cell.v = false; }
|
||||
else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; if(o.cellText !== false) cell.w = s; cell.v = v; }
|
||||
else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; cell.v = v; }
|
||||
else if(!isNaN((v = fuzzydate(s)).getDate()) || _re && s.match(_re)) {
|
||||
cell.z = o.dateNF || table_fmt[14];
|
||||
var k = 0;
|
||||
if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; v = parseDate(s, k); }
|
||||
if(_re && s.match(_re)){ var news=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); v = parseDate(news); if(o && o.UTC === false) v = utc_to_local(v); }
|
||||
else if(o && o.UTC === false) v = utc_to_local(v);
|
||||
else if(o.cellText !== false && o.dateNF) cell.w = SSF_format(cell.z, v);
|
||||
if(o.cellDates) { cell.t = 'd'; cell.v = v; }
|
||||
else { cell.t = 'n'; cell.v = datenum(v); }
|
||||
if(o.cellText !== false) cell.w = SSF_format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v);
|
||||
if(!o.cellNF) delete cell.z;
|
||||
} else {
|
||||
cell.t = 's';
|
||||
@ -7821,7 +7912,45 @@ function parse_drawing(data, rels/*:any*/) {
|
||||
}
|
||||
|
||||
/* L.5.5.2 SpreadsheetML Comments + VML Schema */
|
||||
function write_vml(rId/*:number*/, comments) {
|
||||
var shapevmlregex = /<(?:\w+:)?shape(?:[^\w][^>]*)?>([\s\S]*?)<\/(?:\w+:)?shape>/g;
|
||||
function parse_vml(data/*:string*/, sheet, comments) {
|
||||
var cidx = 0;
|
||||
(data.match(shapevmlregex)||[]).forEach(function(m) {
|
||||
var type = "";
|
||||
var hidden = true;
|
||||
var aidx = -1;
|
||||
var R = -1, C = -1;
|
||||
m.replace(tagregex, function(x/*:string*/, idx/*:number*/) {
|
||||
var y = parsexmltag(x);
|
||||
switch(strip_ns(y[0])) {
|
||||
case '<ClientData': if(y.ObjectType) type = y.ObjectType; break;
|
||||
|
||||
case '<Visible': case '<Visible/>': hidden = false; break;
|
||||
|
||||
case '<Row': case '<Row>': aidx = idx + x.length; break;
|
||||
case '</Row>': R = +m.slice(aidx, idx).trim(); break;
|
||||
|
||||
case '<Column': case '<Column>': aidx = idx + x.length; break;
|
||||
case '</Column>': C = +m.slice(aidx, idx).trim(); break;
|
||||
}
|
||||
return "";
|
||||
});
|
||||
switch(type) {
|
||||
case 'Note':
|
||||
var cell = ws_get_cell_stub(sheet, ((R>=0 && C>=0) ? encode_cell({r:R,c:C}) : comments[cidx].ref));
|
||||
if(cell.c) {
|
||||
cell.c.hidden = hidden;
|
||||
}
|
||||
++cidx;
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* comment boxes */
|
||||
function write_vml(rId/*:number*/, comments, ws) {
|
||||
var csize = [21600, 21600];
|
||||
/* L.5.2.1.2 Path Attribute */
|
||||
var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(",");
|
||||
@ -7843,7 +7972,7 @@ function write_vml(rId/*:number*/, comments) {
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
function write_vml_comment(x, _shapeid)/*:string*/ {
|
||||
function write_vml_comment(x, _shapeid, ws)/*:string*/ {
|
||||
var c = decode_cell(x[0]);
|
||||
var fillopts = /*::(*/{'color2':"#BEFF82", 'type':"gradient"}/*:: :any)*/;
|
||||
if(fillopts.type == "gradient") fillopts.angle = "-180";
|
||||
@ -7981,6 +8110,7 @@ function write_comments_xml(data/*::, opts*/) {
|
||||
o.push('</text></comment>');
|
||||
});
|
||||
} else {
|
||||
if(d[1][0] && d[1][0].T && d[1][0].ID) lastauthor = iauthor.indexOf("tc=" + d[1][0].ID);
|
||||
/* based on Threaded Comments -> Comments projection */
|
||||
o.push('<comment ref="' + d[0] + '" authorId="' + lastauthor + '"><text>');
|
||||
var t = "Comment:\n " + (ts[0]) + "\n";
|
||||
@ -8219,7 +8349,7 @@ function ods_to_csf_3D(r/*:string*/)/*:[string, string]*/ {
|
||||
}
|
||||
|
||||
function csf_to_ods_3D(r/*:string*/)/*:string*/ {
|
||||
return r.replace(/!/,".");
|
||||
return r.replace(/!/,".").replace(/:/, ":.");
|
||||
}
|
||||
|
||||
var strs = {}; // shared strings
|
||||
@ -8305,7 +8435,7 @@ function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) {
|
||||
return len;
|
||||
}
|
||||
|
||||
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) {
|
||||
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles, date1904) {
|
||||
try {
|
||||
if(opts.cellNF) p.z = table_fmt[fmtid];
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
@ -8320,14 +8450,14 @@ function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, the
|
||||
else p.w = SSF_general_num(p.v);
|
||||
}
|
||||
else if(p.t === 'd') {
|
||||
var dd = datenum(p.v);
|
||||
var dd = datenum(p.v, !!date1904);
|
||||
if((dd|0) === dd) p.w = dd.toString(10);
|
||||
else p.w = SSF_general_num(dd);
|
||||
}
|
||||
else if(p.v === undefined) return "";
|
||||
else p.w = SSF_general(p.v,_ssfopts);
|
||||
}
|
||||
else if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v),_ssfopts);
|
||||
else if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v, !!date1904),_ssfopts);
|
||||
else p.w = SSF_format(fmtid,p.v,_ssfopts);
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
if(!opts.cellStyles) return;
|
||||
@ -8407,7 +8537,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
|
||||
}
|
||||
|
||||
/* 18.3.1.80 sheetData CT_SheetData ? */
|
||||
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
|
||||
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles, wb);
|
||||
|
||||
/* 18.3.1.2 autoFilter CT_AutoFilter */
|
||||
var afilter = data2.match(afregex);
|
||||
@ -8427,6 +8557,10 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
|
||||
var margins = data2.match(marginregex);
|
||||
if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));
|
||||
|
||||
/* legacyDrawing */
|
||||
var m;
|
||||
if((m = data2.match(/legacyDrawing r:id="(.*?)"/))) s['!legrel'] = m[1];
|
||||
|
||||
if(opts && opts.nodim) refguess.s.c = refguess.s.r = 0;
|
||||
if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
|
||||
if(opts.sheetRows > 0 && s["!ref"]) {
|
||||
@ -8443,6 +8577,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
|
||||
}
|
||||
if(columns.length > 0) s["!cols"] = columns;
|
||||
if(merges.length > 0) s["!merges"] = merges;
|
||||
if(rels['!id'][s['!legrel']]) s['!legdrawel'] = rels['!id'][s['!legrel']];
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -8609,21 +8744,27 @@ function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
|
||||
return writextag("sheetViews", writextag("sheetView", null, sview), {});
|
||||
}
|
||||
|
||||
function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string*/ {
|
||||
function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb, date1904)/*:string*/ {
|
||||
if(cell.c) ws['!comments'].push([ref, cell.c]);
|
||||
if((cell.v === undefined || cell.t === "z" && !(opts||{}).sheetStubs) && typeof cell.f !== "string" && typeof cell.z == "undefined") return "";
|
||||
var vv = "";
|
||||
var oldt = cell.t, oldv = cell.v;
|
||||
if(cell.t !== "z") switch(cell.t) {
|
||||
case 'b': vv = cell.v ? "1" : "0"; break;
|
||||
case 'n': vv = ''+cell.v; break;
|
||||
case 'n':
|
||||
if(isNaN(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x24]; } // #NUM!
|
||||
else if(!isFinite(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x07]; } // #DIV/0!
|
||||
else vv = ''+cell.v; break;
|
||||
case 'e': vv = BErr[cell.v]; break;
|
||||
case 'd':
|
||||
if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
|
||||
else {
|
||||
if(opts && opts.cellDates) {
|
||||
var _vv = parseDate(cell.v, date1904);
|
||||
vv = _vv.toISOString();
|
||||
if(_vv.getUTCFullYear() < 1900) vv = vv.slice(vv.indexOf("T") + 1).replace("Z","");
|
||||
} else {
|
||||
cell = dup(cell);
|
||||
cell.t = 'n';
|
||||
vv = ''+(cell.v = datenum(parseDate(cell.v)));
|
||||
vv = ''+(cell.v = datenum(parseDate(cell.v, date1904), date1904));
|
||||
}
|
||||
if(typeof cell.z === 'undefined') cell.z = table_fmt[14];
|
||||
break;
|
||||
@ -8666,7 +8807,7 @@ var parse_ws_xml_data = /*#__PURE__*/(function() {
|
||||
var refregex = /ref=["']([^"']*)["']/;
|
||||
var match_v = matchtag("v"), match_f = matchtag("f");
|
||||
|
||||
return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles) {
|
||||
return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles, wb) {
|
||||
var ri = 0, x = "", cells/*:Array<string>*/ = [], cref/*:?Array<string>*/ = [], idx=0, i=0, cc=0, d="", p/*:any*/;
|
||||
var tag, tagr = 0, tagc = 0;
|
||||
var sstr, ftag;
|
||||
@ -8677,6 +8818,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
|
||||
var dense = s["!data"] != null;
|
||||
var rows/*:Array<RowInfo>*/ = [], rowobj = {}, rowrite = false;
|
||||
var sheetStubs = !!opts.sheetStubs;
|
||||
var date1904 = !!((wb||{}).WBProps||{}).date1904;
|
||||
for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
|
||||
x = marr[mt].trim();
|
||||
var xlen = x.length;
|
||||
@ -8744,7 +8886,14 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
|
||||
|
||||
if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
|
||||
if(opts.cellFormula) {
|
||||
if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') {
|
||||
if((cref=d.match(match_f))!= null /*:: && cref != null*/) {
|
||||
if(cref[1] == "") {
|
||||
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
|
||||
// TODO: parse formula
|
||||
ftag = parsexmltag(cref[0]);
|
||||
if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
|
||||
}
|
||||
} else {
|
||||
/* TODO: match against XLSXFutureFunctions */
|
||||
p.f=unescapexml(utf8read(cref[1]), true);
|
||||
if(!opts.xlfn) p.f = _xlfn(p.f);
|
||||
@ -8758,6 +8907,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
|
||||
if(!opts.xlfn) ___f = _xlfn(___f);
|
||||
sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
|
||||
}
|
||||
}
|
||||
} else if((cref=d.match(/<f[^>]*\/>/))) {
|
||||
ftag = parsexmltag(cref[0]);
|
||||
if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
|
||||
@ -8813,8 +8963,8 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
|
||||
break;
|
||||
case 'b': p.v = parsexmlbool(p.v); break;
|
||||
case 'd':
|
||||
if(opts.cellDates) p.v = parseDate(p.v, 1);
|
||||
else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; }
|
||||
if(opts.cellDates) p.v = parseDate(p.v, date1904);
|
||||
else { p.v = datenum(parseDate(p.v, date1904), date1904); p.t = 'n'; }
|
||||
break;
|
||||
/* error string in .w, number in .v */
|
||||
case 'e':
|
||||
@ -8833,8 +8983,8 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
|
||||
}
|
||||
}
|
||||
}
|
||||
safe_format(p, fmtid, fillid, opts, themes, styles);
|
||||
if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.t = 'd'; p.v = numdate(p.v); }
|
||||
safe_format(p, fmtid, fillid, opts, themes, styles, date1904);
|
||||
if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.v = numdate(p.v + (date1904 ? 1462 : 0)); p.t = typeof p.v == "number" ? 'n' : 'd'; }
|
||||
if(tag.cm && opts.xlmeta) {
|
||||
var cm = (opts.xlmeta.Cell||[])[+tag.cm-1];
|
||||
if(cm && cm.type == 'XLDAPR') p.D = true;
|
||||
@ -8859,6 +9009,7 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
|
||||
var o/*:Array<string>*/ = [], r/*:Array<string>*/ = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols/*:Array<string>*/ = [], R=0, C=0, rows = ws['!rows'];
|
||||
var dense = ws["!data"] != null;
|
||||
var params = ({r:rr}/*:any*/), row/*:RowInfo*/, height = -1;
|
||||
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
|
||||
for(R = range.s.r; R <= range.e.r; ++R) {
|
||||
r = [];
|
||||
@ -8867,7 +9018,7 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
|
||||
ref = cols[C] + rr;
|
||||
var _cell = dense ? (ws["!data"][R]||[])[C]: ws[ref];
|
||||
if(_cell === undefined) continue;
|
||||
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
|
||||
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb, date1904)) != null) r.push(cell);
|
||||
}
|
||||
if(r.length > 0 || (rows && rows[R])) {
|
||||
params = ({r:rr}/*:any*/);
|
||||
@ -9600,9 +9751,11 @@ function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ {
|
||||
else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)};
|
||||
else if(!isNaN(fuzzydate(m).getDate())) {
|
||||
o = ({t:'d', v:parseDate(m)}/*:any*/);
|
||||
if(opts.UTC === false) o.v = utc_to_local(o.v);
|
||||
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
|
||||
o.z = opts.dateNF || table_fmt[14];
|
||||
}
|
||||
if(o.cellText !== false) o.w = m;
|
||||
if(dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = o; }
|
||||
else ws[encode_cell({r:R, c:C})] = o;
|
||||
C += CS;
|
||||
@ -9636,7 +9789,8 @@ function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HT
|
||||
if(o.editable) w = '<span contenteditable="true">' + w + '</span>';
|
||||
else if(cell) {
|
||||
sp["data-t"] = cell && cell.t || 'z';
|
||||
if(cell.v != null) sp["data-v"] = cell.v;
|
||||
// note: data-v is unaffected by the timezone interpretation
|
||||
if(cell.v != null) sp["data-v"] = cell.v instanceof Date ? cell.v.toISOString() : cell.v;
|
||||
if(cell.z != null) sp["data-z"] = cell.z;
|
||||
if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + escapehtml(cell.l.Target) +'">' + w + '</a>';
|
||||
}
|
||||
@ -9742,6 +9896,7 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
|
||||
else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
|
||||
else if(!isNaN(fuzzydate(v).getDate())) {
|
||||
o = ({t:'d', v:parseDate(v)}/*:any*/);
|
||||
if(opts.UTC) o.v = local_to_utc(o.v);
|
||||
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
|
||||
o.z = opts.dateNF || table_fmt[14];
|
||||
}
|
||||
@ -10046,8 +10201,8 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
var ws = ({}/*:any*/); if(opts.dense) ws["!data"] = [];
|
||||
var Rn, q/*:: :any = ({t:"", v:null, z:null, w:"",c:[],}:any)*/;
|
||||
var ctag = ({value:""}/*:any*/);
|
||||
var textp = "", textpidx = 0, textptag/*:: = {}*/;
|
||||
var textR = [];
|
||||
var textp = "", textpidx = 0, textptag/*:: = {}*/, oldtextp = "", oldtextpidx = 0;
|
||||
var textR = [], oldtextR = [];
|
||||
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
|
||||
var row_ol = 0;
|
||||
var number_format_map = _nfm || {}, styles = {};
|
||||
@ -10061,7 +10216,6 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
var creator = "", creatoridx = 0;
|
||||
var isstub = false, intable = false;
|
||||
var i = 0;
|
||||
var baddate = 0;
|
||||
xlmlregex.lastIndex = 0;
|
||||
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
|
||||
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
|
||||
@ -10132,7 +10286,7 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
C+= colpeat-1;
|
||||
} else if(Rn[1]!=='/') {
|
||||
++C;
|
||||
textp = ""; textpidx = 0; textR = [];
|
||||
textp = oldtextp = ""; textpidx = oldtextpidx = 0; textR = []; oldtextR = [];
|
||||
colpeat = 1;
|
||||
var rptR = rowpeat ? R + rowpeat - 1 : R;
|
||||
if(C > range.e.c) range.e.c = C;
|
||||
@ -10168,19 +10322,23 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
/* 19.675.2 table:number-columns-repeated */
|
||||
if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10);
|
||||
|
||||
/* 19.385 office:value-type */
|
||||
/* 19.385 office:value-type TODO: verify ODS and UOS */
|
||||
switch(q.t) {
|
||||
case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']) || (+ctag['boolean-value'] >= 1); break;
|
||||
case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break;
|
||||
case 'float': q.t = 'n'; q.v = parseFloat(ctag.value);
|
||||
if(opts.cellDates && q.z && fmt_is_date(q.z)) { q.v = numdate(q.v + (WB.WBProps.date1904 ? 1462 : 0)); q.t = typeof q.v == "number" ? 'n' : 'd'; }
|
||||
break;
|
||||
case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break;
|
||||
case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break;
|
||||
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']);
|
||||
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904) - baddate; }
|
||||
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value'], WB.WBProps.date1904);
|
||||
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904); }
|
||||
if(!q.z) q.z = 'm/d/yy'; break;
|
||||
/* NOTE: for `time`, Excel ODS export incorrectly uses durations relative to 1900 epoch even if 1904 is specified */
|
||||
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400;
|
||||
if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); }
|
||||
if(opts.cellDates) { q.v = numdate(q.v); q.t = typeof q.v == "number" ? 'n' : 'd'; }
|
||||
if(!q.z) q.z = 'HH:MM:SS'; break;
|
||||
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
|
||||
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']);
|
||||
break;
|
||||
default:
|
||||
if(q.t === 'string' || q.t === 'text' || !q.t) {
|
||||
q.t = 's';
|
||||
@ -10241,10 +10399,17 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
if(textR.length) /*::(*/comment/*:: :any)*/.R = textR;
|
||||
comment.a = creator;
|
||||
comments.push(comment);
|
||||
textp = oldtextp; textpidx = oldtextpidx; textR = oldtextR;
|
||||
}
|
||||
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);}
|
||||
creator = ""; creatoridx = 0;
|
||||
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
|
||||
state.push([Rn[3], false]);
|
||||
var annotag = parsexmltag(Rn[0], true);
|
||||
/* office:display TODO: check if there is a global override */
|
||||
if(!(annotag["display"] && parsexmlbool(annotag["display"]))) comments.hidden = true;
|
||||
oldtextp = textp; oldtextpidx = textpidx; oldtextR = textR;
|
||||
textp = ""; textpidx = 0; textR = [];
|
||||
}
|
||||
creator = ""; creatoridx = 0;
|
||||
break;
|
||||
|
||||
case 'creator': // 4.3.2.7 <dc:creator>
|
||||
@ -10370,9 +10535,7 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
case 'null-date': // 9.4.2 <table:null-date>
|
||||
tag = parsexmltag(Rn[0], false);
|
||||
switch(tag["date-value"]) {
|
||||
case "1904-01-01": WB.WBProps.date1904 = true;
|
||||
/* falls through */
|
||||
case "1900-01-01": baddate = 0;
|
||||
case "1904-01-01": WB.WBProps.date1904 = true; break;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -10394,6 +10557,9 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
|
||||
if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) {
|
||||
var ptp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
|
||||
textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0];
|
||||
} else if(Rn[0].slice(-2) == "/>") {
|
||||
/* TODO: is self-closing 文本串 valid? */
|
||||
textp += "\n";
|
||||
} else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
|
||||
break; // <text:p>
|
||||
case 's': break; // <text:s>
|
||||
@ -10678,7 +10844,9 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
|
||||
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
|
||||
payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
|
||||
break;
|
||||
case '/': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
case '\\': c = nf[++i];
|
||||
payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
default: console.error("unrecognized character " + c + " in ODF format " + nf);
|
||||
}
|
||||
if(!has_time) break j;
|
||||
@ -10705,7 +10873,7 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
|
||||
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
|
||||
payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
|
||||
break;
|
||||
case '/': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
case "a":
|
||||
if(nf.slice(i, i+3).toLowerCase() == "a/p") { payload += '<number:am-pm/>'; i += 2; break; } // Note: ODF does not support A/P
|
||||
if(nf.slice(i, i+5).toLowerCase() == "am/pm") { payload += '<number:am-pm/>'; i += 4; break; }
|
||||
@ -10761,10 +10929,15 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
|
||||
}
|
||||
|
||||
function write_names_ods(Names, SheetNames, idx) {
|
||||
var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
|
||||
//var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
|
||||
var scoped = []; for(var namei = 0; namei < Names.length; ++namei) {
|
||||
var name = Names[namei];
|
||||
if(!name) continue;
|
||||
if(name.Sheet == (idx == -1 ? null : idx)) scoped.push(name);
|
||||
}
|
||||
if(!scoped.length) return "";
|
||||
return " <table:named-expressions>\n" + scoped.map(function(name) {
|
||||
var odsref = csf_to_ods_3D(name.Ref);
|
||||
var odsref = (idx == -1 ? "$" : "") + csf_to_ods_3D(name.Ref);
|
||||
return " " + writextag("table:named-range", null, {
|
||||
"table:name": name.Name,
|
||||
"table:cell-range-address": odsref,
|
||||
@ -10783,8 +10956,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
|
||||
};
|
||||
|
||||
var null_cell_xml = ' <table:table-cell />\n';
|
||||
var covered_cell_xml = ' <table:covered-table-cell/>\n';
|
||||
var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts, nfs)/*:string*/ {
|
||||
var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts, nfs, date1904)/*:string*/ {
|
||||
/* Section 9 Tables */
|
||||
var o/*:Array<string>*/ = [];
|
||||
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="ta1">\n');
|
||||
@ -10815,7 +10987,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
|
||||
ct['table:number-rows-spanned'] = (marr[mi].e.r - marr[mi].s.r + 1);
|
||||
break;
|
||||
}
|
||||
if(skip) { o.push(covered_cell_xml); continue; }
|
||||
if(skip) { o.push(' <table:covered-table-cell/>\n'); continue; }
|
||||
var ref = encode_cell({r:R, c:C}), cell = dense ? (ws["!data"][R]||[])[C]: ws[ref];
|
||||
if(cell && cell.f) {
|
||||
ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f));
|
||||
@ -10844,13 +11016,13 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
|
||||
ct['office:value-type'] = "string";
|
||||
break;
|
||||
case 'd':
|
||||
textp = (cell.w||(parseDate(cell.v).toISOString()));
|
||||
textp = (cell.w||(parseDate(cell.v, date1904).toISOString()));
|
||||
ct['office:value-type'] = "date";
|
||||
ct['office:date-value'] = (parseDate(cell.v).toISOString());
|
||||
ct['office:date-value'] = (parseDate(cell.v, date1904).toISOString());
|
||||
ct['table:style-name'] = "ce1";
|
||||
break;
|
||||
//case 'e':
|
||||
default: o.push(null_cell_xml); continue;
|
||||
//case 'e': // TODO: translate to ODS errors
|
||||
default: o.push(null_cell_xml); continue; // TODO: empty cell with comments
|
||||
}
|
||||
var text_p = write_text_p(textp);
|
||||
if(cell.l && cell.l.Target) {
|
||||
@ -10861,7 +11033,17 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
|
||||
text_p = writextag('text:a', text_p, {'xlink:href': _tgt.replace(/&/g, "&")});
|
||||
}
|
||||
if(nfs[cell.z]) ct["table:style-name"] = "ce" + nfs[cell.z].slice(1);
|
||||
o.push(' ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n');
|
||||
var payload = writextag('text:p', text_p, {});
|
||||
if(cell.c) {
|
||||
var acreator = "", apayload = "", aprops = {};
|
||||
for(var ci = 0; ci < cell.c.length; ++ci) {
|
||||
if(!acreator && cell.c[ci].a) acreator = cell.c[ci].a;
|
||||
apayload += "<text:p>" + write_text_p(cell.c[ci].t) + "</text:p>";
|
||||
}
|
||||
if(!cell.c.hidden) aprops["office:display"] = true;
|
||||
payload = writextag('office:annotation', apayload, aprops) + payload;
|
||||
}
|
||||
o.push(' ' + writextag('table:table-cell', payload, ct) + '\n');
|
||||
}
|
||||
o.push(' </table:table-row>\n');
|
||||
}
|
||||
@ -11006,7 +11188,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
|
||||
o.push(' <office:body>\n');
|
||||
o.push(' <office:spreadsheet>\n');
|
||||
if(((wb.Workbook||{}).WBProps||{}).date1904) o.push(' <table:calculation-settings table:case-sensitive="false" table:search-criteria-must-apply-to-whole-cell="true" table:use-wildcards="true" table:use-regular-expressions="false" table:automatic-find-labels="false">\n <table:null-date table:date-value="1904-01-01"/>\n </table:calculation-settings>\n');
|
||||
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs));
|
||||
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs, ((wb.Workbook||{}).WBProps||{}).date1904));
|
||||
if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1));
|
||||
o.push(' </office:spreadsheet>\n');
|
||||
o.push(' </office:body>\n');
|
||||
@ -11120,6 +11302,13 @@ function safe_parse_wbrels(wbrels, sheets) {
|
||||
return !wbrels || wbrels.length === 0 ? null : wbrels;
|
||||
}
|
||||
|
||||
function parse_sheet_legacy_drawing(sheet, type, zip, path, idx, opts, wb, comments) {
|
||||
if(!sheet || !sheet['!legdrawel']) return;
|
||||
var dfile = resolve_path(sheet['!legdrawel'].Target, path);
|
||||
var draw = getzipstr(zip, dfile, true);
|
||||
if(draw) parse_vml(utf8read(draw), sheet, comments||[]);
|
||||
}
|
||||
|
||||
function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/*:number*/, sheetRels, sheets, stype/*:string*/, opts, wb, themes, styles) {
|
||||
try {
|
||||
sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
|
||||
@ -11158,6 +11347,7 @@ function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/
|
||||
}
|
||||
});
|
||||
if(tcomments && tcomments.length) sheet_insert_comments(_ws, tcomments, true, opts.people || []);
|
||||
parse_sheet_legacy_drawing(_ws, stype, zip, path, idx, opts, wb, comments);
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
}
|
||||
|
||||
@ -11460,6 +11650,9 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
|
||||
add_rels(opts.rels, 4, f, RELS.CUST_PROPS);
|
||||
}
|
||||
|
||||
var people = ["SheetJ5"];
|
||||
opts.tcid = 0;
|
||||
|
||||
for(rId=1;rId <= wb.SheetNames.length; ++rId) {
|
||||
var wsrels = {'!id':{}};
|
||||
var ws = wb.Sheets[wb.SheetNames[rId-1]];
|
||||
@ -11479,6 +11672,17 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
|
||||
var need_vml = false;
|
||||
var cf = "";
|
||||
if(comments && comments.length > 0) {
|
||||
var needtc = false;
|
||||
comments.forEach(function(carr) {
|
||||
carr[1].forEach(function(c) { if(c.T == true) needtc = true; });
|
||||
});
|
||||
if(needtc) {
|
||||
cf = "xl/threadedComments/threadedComment" + rId + ".xml";
|
||||
zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts));
|
||||
ct.threadedcomments.push(cf);
|
||||
add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + ".xml", RELS.TCMNT);
|
||||
}
|
||||
|
||||
cf = "xl/comments" + rId + "." + wbext;
|
||||
zip_add_file(zip, cf, write_comments_bin(comments, opts));
|
||||
ct.comments.push(cf);
|
||||
@ -11534,6 +11738,13 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
|
||||
ct.metadata.push(f);
|
||||
add_rels(opts.wbrels, -1, "metadata." + wbext, RELS.XLMETA);
|
||||
|
||||
if(people.length > 1) {
|
||||
f = "xl/persons/person.xml";
|
||||
zip_add_file(zip, f, write_people_xml(people, opts));
|
||||
ct.people.push(f);
|
||||
add_rels(opts.wbrels, -1, "persons/person.xml", RELS.PEOPLE);
|
||||
}
|
||||
|
||||
zip_add_file(zip, "[Content_Types].xml", write_ct(ct, opts));
|
||||
zip_add_file(zip, '_rels/.rels', write_rels(opts.rels));
|
||||
zip_add_file(zip, 'xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));
|
||||
@ -12047,7 +12258,7 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
|
||||
}
|
||||
if(!dense || sheet["!data"][R]) for (var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var val = dense ? (sheet["!data"][R]||[])[C] : sheet[cols[C] + rr];
|
||||
if(val === undefined || val.t === undefined) {
|
||||
if(val == null || val.t === undefined) {
|
||||
if(defval === undefined) continue;
|
||||
if(hdr[C] != null) { row[hdr[C]] = defval; }
|
||||
continue;
|
||||
@ -12056,7 +12267,12 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
|
||||
switch(val.t){
|
||||
case 'z': if(v == null) break; continue;
|
||||
case 'e': v = (v == 0 ? null : void 0); break;
|
||||
case 's': case 'd': case 'b': case 'n': break;
|
||||
case 's': case 'b':
|
||||
case 'n': if(!val.z || !fmt_is_date(val.z)) break;
|
||||
v = numdate(v); // TODO: date1904 setting should also be stored in worksheet object
|
||||
if(typeof v == "number") break;
|
||||
/* falls through */
|
||||
case 'd': if(!(o && o.UTC)) v = utc_to_local(v); break;
|
||||
default: throw new Error('unrecognized type ' + val.t);
|
||||
}
|
||||
if(hdr[C] != null) {
|
||||
@ -12266,6 +12482,7 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
|
||||
else if(typeof v == 'string') t = 's';
|
||||
else if(v instanceof Date) {
|
||||
t = 'd';
|
||||
if(!o.UTC) v = local_to_utc(v);
|
||||
if(!o.cellDates) { t = 'n'; v = datenum(v); }
|
||||
z = (cell != null && cell.z && fmt_is_date(cell.z)) ? cell.z : (o.dateNF || table_fmt[14]);
|
||||
}
|
||||
|
478
xlsx.mini.js
478
xlsx.mini.js
@ -1,10 +1,10 @@
|
||||
/*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
/* vim: set ts=2: */
|
||||
/*exported XLSX */
|
||||
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */
|
||||
/*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.19.3';
|
||||
XLSX.version = '0.20.0';
|
||||
var current_codepage = 1200, current_ansi = 1252;
|
||||
/*global cptable:true, window */
|
||||
var $cptable;
|
||||
@ -134,6 +134,26 @@ function Base64_encode_pass(input) {
|
||||
}
|
||||
return o;
|
||||
}
|
||||
function Base64_encode_arr(input) {
|
||||
var o = "";
|
||||
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
|
||||
for (var i = 0; i < input.length; ) {
|
||||
c1 = input[i++];
|
||||
e1 = c1 >> 2;
|
||||
c2 = input[i++];
|
||||
e2 = (c1 & 3) << 4 | c2 >> 4;
|
||||
c3 = input[i++];
|
||||
e3 = (c2 & 15) << 2 | c3 >> 6;
|
||||
e4 = c3 & 63;
|
||||
if (isNaN(c2)) {
|
||||
e3 = e4 = 64;
|
||||
} else if (isNaN(c3)) {
|
||||
e4 = 64;
|
||||
}
|
||||
o += Base64_map.charAt(e1) + Base64_map.charAt(e2) + Base64_map.charAt(e3) + Base64_map.charAt(e4);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
function Base64_decode(input) {
|
||||
var o = "";
|
||||
var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
|
||||
@ -474,15 +494,6 @@ function SSF_parse_date_code(v,opts,b2) {
|
||||
out.q = dow;
|
||||
return out;
|
||||
}
|
||||
var SSFbasedate = new Date(1899, 11, 31, 0, 0, 0);
|
||||
var SSFdnthresh = SSFbasedate.getTime();
|
||||
var SSFbase1904 = new Date(1900, 2, 1, 0, 0, 0);
|
||||
function datenum_local(v, date1904) {
|
||||
var epoch = v.getTime();
|
||||
if(date1904) epoch -= 1461*24*60*60*1000;
|
||||
else if(v >= SSFbase1904) epoch += 24*60*60*1000;
|
||||
return (epoch - (SSFdnthresh + (v.getTimezoneOffset() - SSFbasedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
|
||||
}
|
||||
/* ECMA-376 18.8.30 numFmt*/
|
||||
/* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
|
||||
/* exponent >= -9 and <= 9 */
|
||||
@ -540,7 +551,7 @@ function SSF_general(v, opts) {
|
||||
case 'undefined': return "";
|
||||
case 'object':
|
||||
if(v == null) return "";
|
||||
if(v instanceof Date) return SSF_format(14, datenum_local(v, opts && opts.date1904), opts);
|
||||
if(v instanceof Date) return SSF_format(14, datenum(v, opts && opts.date1904), opts);
|
||||
}
|
||||
throw new Error("unsupported value in General format: " + v);
|
||||
}
|
||||
@ -1222,7 +1233,7 @@ function SSF_format(fmt,v,o) {
|
||||
break;
|
||||
}
|
||||
if(SSF_isgeneral(sfmt,0)) return SSF_general(v, o);
|
||||
if(v instanceof Date) v = datenum_local(v, o.date1904);
|
||||
if(v instanceof Date) v = datenum(v, o.date1904);
|
||||
var f = choose_fmt(sfmt, v);
|
||||
if(SSF_isgeneral(f[1])) return SSF_general(v, o);
|
||||
if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
|
||||
@ -1305,6 +1316,7 @@ var dateNFregex = /[dD]+|[mM]+|[yYeE]+|[Hh]+|[Ss]+/g;
|
||||
function dateNF_regex(dateNF) {
|
||||
var fmt = typeof dateNF == "number" ? table_fmt[dateNF] : dateNF;
|
||||
fmt = fmt.replace(dateNFregex, "(\\d+)");
|
||||
dateNFregex.lastIndex = 0;
|
||||
return new RegExp("^" + fmt + "$");
|
||||
}
|
||||
function dateNF_fix(str, dateNF, match) {
|
||||
@ -1317,6 +1329,7 @@ function dateNF_fix(str, dateNF, match) {
|
||||
case 'm': if(H >= 0) M = v; else m = v; break;
|
||||
}
|
||||
});
|
||||
dateNFregex.lastIndex = 0;
|
||||
if(S >= 0 && M == -1 && m >= 0) { M = m; m = -1; }
|
||||
var datestr = (("" + (Y>=0?Y: new Date().getFullYear())).slice(-4) + "-" + ("00" + (m>=1?m:1)).slice(-2) + "-" + ("00" + (d>=1?d:1)).slice(-2));
|
||||
if(datestr.length == 7) datestr = "0" + datestr;
|
||||
@ -3202,7 +3215,7 @@ if(typeof saveAs !== 'undefined') return saveAs(blob, fname);
|
||||
var url = URL.createObjectURL(blob);
|
||||
if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
|
||||
if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
|
||||
return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
|
||||
return chrome.downloads.download({ url: url, filename: fname, saveAs: true });
|
||||
}
|
||||
var a = document.createElement("a");
|
||||
if(a.download != null) {
|
||||
@ -3211,6 +3224,10 @@ document.body.removeChild(a);
|
||||
if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
|
||||
return url;
|
||||
}
|
||||
} else if(typeof URL !== 'undefined' && !URL.createObjectURL && typeof chrome === 'object') {
|
||||
/* manifest v3 extensions -- no URL.createObjectURL */
|
||||
var b64 = "data:application/octet-stream;base64," + Base64_encode_arr(new Uint8Array(blobify(data)));
|
||||
return chrome.downloads.download({ url: b64, filename: fname, saveAs: true });
|
||||
}
|
||||
}
|
||||
// $FlowIgnore
|
||||
@ -3269,22 +3286,19 @@ function evert_arr(obj) {
|
||||
return o;
|
||||
}
|
||||
|
||||
var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
|
||||
var dnthresh = Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
|
||||
var dnthresh1 = Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
|
||||
var dnthresh2 = Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
|
||||
function datenum(v, date1904) {
|
||||
var epoch = v.getTime();
|
||||
if(date1904) epoch -= 1462*24*60*60*1000;
|
||||
var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
|
||||
return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
|
||||
if(date1904) { res -= 1462; return res < -1402 ? res - 1 : res; }
|
||||
return res < 60 ? res - 1 : res;
|
||||
}
|
||||
var refdate = new Date();
|
||||
var dnthresh = basedate.getTime() + (refdate.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
|
||||
var refoffset = refdate.getTimezoneOffset();
|
||||
function numdate(v) {
|
||||
if(v >= 60 && v < 61) return v;
|
||||
var out = new Date();
|
||||
out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh);
|
||||
if (out.getTimezoneOffset() !== refoffset) {
|
||||
out.setTime(out.getTime() + (out.getTimezoneOffset() - refoffset) * 60000);
|
||||
}
|
||||
out.setTime((v>60 ? v : (v+1)) * 24 * 60 * 60 * 1000 + dnthresh);
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -3315,27 +3329,22 @@ function parse_isodur(s) {
|
||||
return sec;
|
||||
}
|
||||
|
||||
var good_pd_date_1 = new Date('2017-02-19T19:06:09.000Z');
|
||||
var good_pd_date = isNaN(good_pd_date_1.getFullYear()) ? new Date('2/19/17') : good_pd_date_1;
|
||||
var good_pd = good_pd_date.getFullYear() == 2017;
|
||||
/* parses a date as a local date */
|
||||
function parseDate(str, fixdate) {
|
||||
var d = new Date(str);
|
||||
if(good_pd) {
|
||||
if(fixdate > 0) d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
|
||||
else if(fixdate < 0) d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000);
|
||||
return d;
|
||||
}
|
||||
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
|
||||
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
|
||||
var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
|
||||
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]], sans "Z"
|
||||
/* parses a date string as a UTC date */
|
||||
function parseDate(str, date1904) {
|
||||
if(str instanceof Date) return str;
|
||||
if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
|
||||
var s = d.getFullYear();
|
||||
if(str.indexOf("" + s) > -1) return d;
|
||||
d.setFullYear(d.getFullYear() + 100); return d;
|
||||
}
|
||||
var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
|
||||
var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
|
||||
if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000);
|
||||
return out;
|
||||
var m = str.match(pdre1);
|
||||
if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
|
||||
m = str.match(pdre2);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
|
||||
/* TODO: 1900-02-29T00:00:00.000 should return a flag to treat as a date code (affects xlml) */
|
||||
m = str.match(pdre3);
|
||||
if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt(m[7].slice(1), 10))||0)));
|
||||
var d = new Date(str);
|
||||
return d;
|
||||
}
|
||||
|
||||
function cc2str(arr, debomit) {
|
||||
@ -3366,8 +3375,18 @@ function cc2str(arr, debomit) {
|
||||
return new TextDecoder("latin1").decode(arr).replace(/[€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ]/g, function(c) { return rev[c] || c; });
|
||||
} catch(e) {}
|
||||
|
||||
var o = [];
|
||||
for(var i = 0; i != arr.length; ++i) o.push(String.fromCharCode(arr[i]));
|
||||
var o = [], i = 0;
|
||||
// this cascade is for the browsers and runtimes of antiquity (and for modern runtimes that lack TextEncoder)
|
||||
try {
|
||||
for(i = 0; i < arr.length - 65536; i+=65536) o.push(String.fromCharCode.apply(0, arr.slice(i, i + 65536)));
|
||||
o.push(String.fromCharCode.apply(0, arr.slice(i)));
|
||||
} catch(e) { try {
|
||||
for(; i < arr.length - 16384; i+=16384) o.push(String.fromCharCode.apply(0, arr.slice(i, i + 16384)));
|
||||
o.push(String.fromCharCode.apply(0, arr.slice(i)));
|
||||
} catch(e) {
|
||||
for(; i != arr.length; ++i) o.push(String.fromCharCode(arr[i]));
|
||||
}
|
||||
}
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
@ -3397,32 +3416,49 @@ function fuzzynum(s) {
|
||||
|
||||
/* NOTE: Chrome rejects bare times like 1:23 PM */
|
||||
var FDRE1 = /^(0?\d|1[0-2])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))\s+([ap])m?$/;
|
||||
var FDRE2 = /^([01]?\d|2[0-3])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))$/;
|
||||
var FDISO = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)(\.\d+)?[Z]?$/; // YYYY-mm-dd(T or space)HH:MM:SS[.UUU][Z]
|
||||
|
||||
/* TODO: 1904 adjustment */
|
||||
var utc_append_works = new Date("6/9/69 00:00 UTC").valueOf() == -17798400000;
|
||||
function fuzzytime1(M) {
|
||||
/* TODO: 1904 adjustment, keep in sync with base date */
|
||||
if(!M[2]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0);
|
||||
if(!M[2]) return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0));
|
||||
if(M[3]) {
|
||||
if(M[4]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000);
|
||||
else return new Date(1899,11,30,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000);
|
||||
if(M[4]) return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000));
|
||||
else return new Date(Date.UTC(1899,11,31,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000));
|
||||
}
|
||||
else if(M[5]) return new Date(1899,11,30, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0);
|
||||
else return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0);
|
||||
else if(M[5]) return new Date(Date.UTC(1899,11,31, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0));
|
||||
else return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0));
|
||||
}
|
||||
function fuzzytime2(M) {
|
||||
if(!M[2]) return new Date(Date.UTC(1899,11,31,+M[1], 0, 0, 0));
|
||||
if(M[3]) {
|
||||
if(M[4]) return new Date(Date.UTC(1899,11,31,+M[1], +M[2], +M[4], parseFloat(M[3])*1000));
|
||||
else return new Date(Date.UTC(1899,11,31,0, +M[1], +M[2], parseFloat(M[3])*1000));
|
||||
}
|
||||
else if(M[5]) return new Date(Date.UTC(1899,11,31, +M[1], +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0));
|
||||
else return new Date(Date.UTC(1899,11,31,+M[1], +M[2], 0, 0));
|
||||
}
|
||||
var lower_months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'];
|
||||
function fuzzydate(s) {
|
||||
// See issue 2863 -- this is technically not supported in Excel but is otherwise useful
|
||||
if(FDISO.test(s)) return s.indexOf("Z") == -1 ? local_to_utc(new Date(s)) : new Date(s);
|
||||
var lower = s.toLowerCase();
|
||||
var lnos = lower.replace(/\s+/g, " ").trim();
|
||||
var M = lnos.match(FDRE1);
|
||||
if(M) return fuzzytime1(M);
|
||||
|
||||
var o = new Date(s), n = new Date(NaN);
|
||||
M = lnos.match(FDRE2);
|
||||
if(M) return fuzzytime2(M);
|
||||
M = lnos.match(pdre3);
|
||||
if(M) return new Date(Date.UTC(+M[1], +M[2]-1, +M[3], +M[4], +M[5], ((M[6] && parseInt(M[6].slice(1), 10))|| 0), ((M[7] && parseInt(M[7].slice(1), 10))||0)));
|
||||
var o = new Date(utc_append_works && s.indexOf("UTC") == -1 ? s + " UTC": s), n = new Date(NaN);
|
||||
var y = o.getYear(), m = o.getMonth(), d = o.getDate();
|
||||
if(isNaN(d)) return n;
|
||||
if(lower.match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) {
|
||||
lower = lower.replace(/[^a-z]/g,"").replace(/([^a-z]|^)[ap]m?([^a-z]|$)/,"");
|
||||
if(lower.length > 3 && lower_months.indexOf(lower) == -1) return n;
|
||||
} else if(lower.replace(/[ap]m?/, "").match(/[a-z]/)) return n;
|
||||
if(y < 0 || y > 8099 || s.match(/[^-0-9:,\/\\]/)) return n;
|
||||
if(y < 0 || y > 8099 || s.match(/[^-0-9:,\/\\\ ]/)) return n;
|
||||
return o;
|
||||
}
|
||||
|
||||
@ -3435,6 +3471,13 @@ var split_regex = (function() {
|
||||
return o;
|
||||
};
|
||||
})();
|
||||
|
||||
function utc_to_local(utc) {
|
||||
return new Date(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate(), utc.getUTCHours(), utc.getUTCMinutes(), utc.getUTCSeconds(), utc.getUTCMilliseconds());
|
||||
}
|
||||
function local_to_utc(local) {
|
||||
return new Date(Date.UTC(local.getFullYear(), local.getMonth(), local.getDate(), local.getHours(), local.getMinutes(), local.getSeconds(), local.getMilliseconds()));
|
||||
}
|
||||
function getdatastr(data) {
|
||||
if(!data) return null;
|
||||
if(data.content && data.type) return cc2str(data.content, true);
|
||||
@ -4354,6 +4397,7 @@ function sheet_add_aoa(_ws, data, opts) {
|
||||
else if(typeof cell.v === 'boolean') cell.t = 'b';
|
||||
else if(cell.v instanceof Date) {
|
||||
cell.z = o.dateNF || table_fmt[14];
|
||||
if(!o.UTC) cell.v = local_to_utc(cell.v);
|
||||
if(o.cellDates) { cell.t = 'd'; cell.w = SSF_format(cell.z, datenum(cell.v, o.date1904)); }
|
||||
else { cell.t = 'n'; cell.v = datenum(cell.v, o.date1904); cell.w = SSF_format(cell.z, cell.v); }
|
||||
}
|
||||
@ -5619,7 +5663,10 @@ var fields = [], field = ({});
|
||||
if(s.trim().length) out[R][C] = s.replace(/\s+$/,"");
|
||||
break;
|
||||
case 'D':
|
||||
if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8));
|
||||
if(s.length === 8) {
|
||||
out[R][C] = new Date(Date.UTC(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8), 0, 0, 0, 0));
|
||||
if(!(opts && opts.UTC)) { out[R][C] = utc_to_local(out[R][C]); }
|
||||
}
|
||||
else out[R][C] = s;
|
||||
break;
|
||||
case 'F': out[R][C] = parseFloat(s.trim()); break;
|
||||
@ -5642,7 +5689,12 @@ var fields = [], field = ({});
|
||||
// NOTE: dBASE specs appear to be incorrect
|
||||
out[R][C] = new Date(dd.read_shift(-8, 'f') - 0x388317533400);
|
||||
break;
|
||||
case 'T': out[R][C] = new Date((dd.read_shift(4) - 0x253D8C) * 0x5265C00 + dd.read_shift(4)); break;
|
||||
case 'T': {
|
||||
var hi = dd.read_shift(4), lo = dd.read_shift(4);
|
||||
if(hi == 0 && lo == 0) break;
|
||||
out[R][C] = new Date((hi - 0x253D8C) * 0x5265C00 + lo);
|
||||
if(!(opts && opts.UTC)) out[R][C] = utc_to_local(out[R][C]);
|
||||
} break;
|
||||
case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4 + (dd.read_shift(4, 'i')/1e4)*Math.pow(2,32); break;
|
||||
case 'O': out[R][C] = -dd.read_shift(-8, 'f'); break;
|
||||
case 'B': if(vfp && fields[C].len == 8) { out[R][C] = dd.read_shift(8,'f'); break; }
|
||||
@ -5845,6 +5897,8 @@ var SYLK = (function() {
|
||||
var sylk_char_fn = function(_, $1){ var o = sylk_escapes[$1]; return typeof o == "number" ? _getansi(o) : o; };
|
||||
var decode_sylk_char = function($$, $1, $2) { var newcc = (($1.charCodeAt(0) - 0x20)<<4) | ($2.charCodeAt(0) - 0x30); return newcc == 59 ? $$ : _getansi(newcc); };
|
||||
sylk_escapes["|"] = 254;
|
||||
/* TODO: evert the escape map */
|
||||
var encode_sylk_str = function($$) { return $$.replace(/\n/g, "\x1b :").replace(/\r/g, "\x1b ="); };
|
||||
/* https://oss.sheetjs.com/notes/sylk/ for more details */
|
||||
function sylk_to_aoa(d, opts) {
|
||||
switch(opts.type) {
|
||||
@ -5897,8 +5951,9 @@ var SYLK = (function() {
|
||||
// case 'NU': // ??
|
||||
case 'C': /* cell */
|
||||
var C_seen_K = false, C_seen_X = false, C_seen_S = false, C_seen_E = false, _R = -1, _C = -1, formula = "", cell_t = "z";
|
||||
var cmnt = "";
|
||||
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
|
||||
case 'A': break; // TODO: comment
|
||||
case 'A': cmnt = record[rj].slice(1); break; // TODO: comment
|
||||
case 'X': C = parseInt(record[rj].slice(1), 10)-1; C_seen_X = true; break;
|
||||
case 'Y':
|
||||
R = parseInt(record[rj].slice(1), 10)-1; if(!C_seen_X) C = 0;
|
||||
@ -5910,10 +5965,9 @@ var SYLK = (function() {
|
||||
else if(val === 'TRUE' || val === 'FALSE') { val = val === 'TRUE'; cell_t = "b"; }
|
||||
else if(!isNaN(fuzzynum(val))) {
|
||||
val = fuzzynum(val); cell_t = "n";
|
||||
if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) { val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : val); cell_t = "d"; }
|
||||
} else if(!isNaN(fuzzydate(val).getDate())) {
|
||||
val = parseDate(val); cell_t = "d";
|
||||
if(!opts.cellDates) { cell_t = "n"; val = datenum(val, wb.Workbook.WBProps.date1904); }
|
||||
if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) {
|
||||
val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : val); cell_t = typeof val == "number" ? "n" : "d";
|
||||
}
|
||||
}
|
||||
if(typeof $cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = $cptable.utils.decode(opts.codepage, val);
|
||||
C_seen_K = true;
|
||||
@ -5949,6 +6003,10 @@ var SYLK = (function() {
|
||||
if(!arr[R][C]) arr[R][C] = { t: 'n', f: formula };
|
||||
else arr[R][C].f = formula;
|
||||
}
|
||||
if(cmnt) {
|
||||
if(!arr[R][C]) arr[R][C] = { t: 'z' };
|
||||
arr[R][C].c = [{a:"SheetJSYLK", t: cmnt}];
|
||||
}
|
||||
break;
|
||||
case 'F': /* Format */
|
||||
var F_seen = 0;
|
||||
@ -6010,7 +6068,7 @@ var SYLK = (function() {
|
||||
return outwb;
|
||||
}
|
||||
|
||||
function write_ws_cell_sylk(cell, ws, R, C) {
|
||||
function write_ws_cell_sylk(cell, ws, R, C, opts, date1904) {
|
||||
var o = "C;Y" + (R+1) + ";X" + (C+1) + ";K";
|
||||
switch(cell.t) {
|
||||
case 'n':
|
||||
@ -6018,12 +6076,19 @@ var SYLK = (function() {
|
||||
if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break;
|
||||
case 'b': o += cell.v ? "TRUE" : "FALSE"; break;
|
||||
case 'e': o += cell.w || cell.v; break;
|
||||
case 'd': o += '"' + (cell.w || cell.v) + '"'; break;
|
||||
case 'd': o += datenum(parseDate(cell.v, date1904), date1904); break;
|
||||
case 's': o += '"' + (cell.v == null ? "" : String(cell.v)).replace(/"/g,"").replace(/;/g, ";;") + '"'; break;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
function write_ws_cmnt_sylk(cmnt, R, C) {
|
||||
var o = "C;Y" + (R+1) + ";X" + (C+1) + ";A";
|
||||
/* TODO: max length? */
|
||||
o += encode_sylk_str(cmnt.map(function(c) { return c.t; }).join(""));
|
||||
return o;
|
||||
}
|
||||
|
||||
function write_ws_cols_sylk(out, cols) {
|
||||
cols.forEach(function(col, i) {
|
||||
var rec = "F;W" + (i+1) + " " + (i+1) + " ";
|
||||
@ -6048,6 +6113,7 @@ var SYLK = (function() {
|
||||
}
|
||||
|
||||
function sheet_to_sylk(ws, opts, wb) {
|
||||
if(!opts) opts = {}; opts._formats = ["General"];
|
||||
/* TODO: codepage */
|
||||
var preamble = ["ID;PSheetJS;N;E"], o = [];
|
||||
var r = safe_decode_range(ws['!ref']), cell;
|
||||
@ -6055,23 +6121,44 @@ var SYLK = (function() {
|
||||
var RS = "\r\n";
|
||||
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
|
||||
var _lastfmt = "General";
|
||||
preamble.push("P;PGeneral");
|
||||
/* Excel has been inconsistent in comment placement */
|
||||
var R = r.s.r, C = r.s.c, p = [];
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
if(dense && !ws["!data"][R]) continue;
|
||||
p = [];
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
|
||||
if(!cell || !cell.c) continue;
|
||||
p.push(write_ws_cmnt_sylk(cell.c, R, C));
|
||||
}
|
||||
if(p.length) o.push(p.join(RS));
|
||||
}
|
||||
for(R = r.s.r; R <= r.e.r; ++R) {
|
||||
if(dense && !ws["!data"][R]) continue;
|
||||
p = [];
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
|
||||
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
|
||||
if((cell.z||(cell.t == "d" ? table_fmt[14] : "General")) != _lastfmt) {
|
||||
var ifmt = opts._formats.indexOf(cell.z);
|
||||
if(ifmt == -1) { opts._formats.push(cell.z); ifmt = opts._formats.length - 1; preamble.push("P;P" + cell.z.replace(/;/g, ";;")); }
|
||||
p.push("F;P" + ifmt + ";Y" + (R+1) + ";X" + (C+1));
|
||||
}
|
||||
p.push(write_ws_cell_sylk(cell, ws, R, C, opts, d1904));
|
||||
}
|
||||
o.push(p.join(RS));
|
||||
}
|
||||
|
||||
preamble.push("F;P0;DG0G8;M255");
|
||||
if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
|
||||
if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
|
||||
|
||||
preamble.push("B;Y" + (r.e.r - r.s.r + 1) + ";X" + (r.e.c - r.s.c + 1) + ";D" + [r.s.c,r.s.r,r.e.c,r.e.r].join(" "));
|
||||
preamble.push("O;L;D;B" + (d1904 ? ";V4" : "") + ";K47;G100 0.001");
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
if(dense && !ws["!data"][R]) continue;
|
||||
var p = [];
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
|
||||
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
|
||||
p.push(write_ws_cell_sylk(cell, ws, R, C, opts)); // TODO: pass date1904 info
|
||||
}
|
||||
o.push(p.join(RS));
|
||||
}
|
||||
|
||||
delete opts._formats;
|
||||
return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
|
||||
}
|
||||
|
||||
@ -6111,7 +6198,10 @@ var DIF = (function() {
|
||||
if(data === 'TRUE') arr[R][C] = true;
|
||||
else if(data === 'FALSE') arr[R][C] = false;
|
||||
else if(!isNaN(fuzzynum(value))) arr[R][C] = fuzzynum(value);
|
||||
else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value);
|
||||
else if(!isNaN(fuzzydate(value).getDate())) {
|
||||
arr[R][C] = parseDate(value);
|
||||
if(!(opts && opts.UTC)) { arr[R][C] = utc_to_local(arr[R][C]); }
|
||||
}
|
||||
else arr[R][C] = value;
|
||||
++C; break;
|
||||
case 1:
|
||||
@ -6392,9 +6482,11 @@ var PRN = (function() {
|
||||
var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0);
|
||||
var _re = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
|
||||
function finish_cell() {
|
||||
/* TODO: fuzzy parsers should pass back assumed number format */
|
||||
var s = str.slice(start, end); if(s.slice(-1) == "\r") s = s.slice(0, -1);
|
||||
var cell = ({});
|
||||
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
|
||||
if(o.cellText !== false) cell.w = s;
|
||||
if(s.length === 0) cell.t = 'z';
|
||||
else if(o.raw) { cell.t = 's'; cell.v = s; }
|
||||
else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; }
|
||||
@ -6404,14 +6496,14 @@ var PRN = (function() {
|
||||
else { cell.t = 's'; cell.v = s; } }
|
||||
else if(s == "TRUE") { cell.t = 'b'; cell.v = true; }
|
||||
else if(s == "FALSE") { cell.t = 'b'; cell.v = false; }
|
||||
else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; if(o.cellText !== false) cell.w = s; cell.v = v; }
|
||||
else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; cell.v = v; }
|
||||
else if(!isNaN((v = fuzzydate(s)).getDate()) || _re && s.match(_re)) {
|
||||
cell.z = o.dateNF || table_fmt[14];
|
||||
var k = 0;
|
||||
if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; v = parseDate(s, k); }
|
||||
if(_re && s.match(_re)){ var news=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); v = parseDate(news); if(o && o.UTC === false) v = utc_to_local(v); }
|
||||
else if(o && o.UTC === false) v = utc_to_local(v);
|
||||
else if(o.cellText !== false && o.dateNF) cell.w = SSF_format(cell.z, v);
|
||||
if(o.cellDates) { cell.t = 'd'; cell.v = v; }
|
||||
else { cell.t = 'n'; cell.v = datenum(v); }
|
||||
if(o.cellText !== false) cell.w = SSF_format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v);
|
||||
if(!o.cellNF) delete cell.z;
|
||||
} else {
|
||||
cell.t = 's';
|
||||
@ -7735,7 +7827,45 @@ function parse_drawing(data, rels) {
|
||||
}
|
||||
|
||||
/* L.5.5.2 SpreadsheetML Comments + VML Schema */
|
||||
function write_vml(rId, comments) {
|
||||
var shapevmlregex = /<(?:\w+:)?shape(?:[^\w][^>]*)?>([\s\S]*?)<\/(?:\w+:)?shape>/g;
|
||||
function parse_vml(data, sheet, comments) {
|
||||
var cidx = 0;
|
||||
(data.match(shapevmlregex)||[]).forEach(function(m) {
|
||||
var type = "";
|
||||
var hidden = true;
|
||||
var aidx = -1;
|
||||
var R = -1, C = -1;
|
||||
m.replace(tagregex, function(x, idx) {
|
||||
var y = parsexmltag(x);
|
||||
switch(strip_ns(y[0])) {
|
||||
case '<ClientData': if(y.ObjectType) type = y.ObjectType; break;
|
||||
|
||||
case '<Visible': case '<Visible/>': hidden = false; break;
|
||||
|
||||
case '<Row': case '<Row>': aidx = idx + x.length; break;
|
||||
case '</Row>': R = +m.slice(aidx, idx).trim(); break;
|
||||
|
||||
case '<Column': case '<Column>': aidx = idx + x.length; break;
|
||||
case '</Column>': C = +m.slice(aidx, idx).trim(); break;
|
||||
}
|
||||
return "";
|
||||
});
|
||||
switch(type) {
|
||||
case 'Note':
|
||||
var cell = ws_get_cell_stub(sheet, ((R>=0 && C>=0) ? encode_cell({r:R,c:C}) : comments[cidx].ref));
|
||||
if(cell.c) {
|
||||
cell.c.hidden = hidden;
|
||||
}
|
||||
++cidx;
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* comment boxes */
|
||||
function write_vml(rId, comments, ws) {
|
||||
var csize = [21600, 21600];
|
||||
/* L.5.2.1.2 Path Attribute */
|
||||
var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(",");
|
||||
@ -7757,7 +7887,7 @@ function write_vml(rId, comments) {
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
function write_vml_comment(x, _shapeid) {
|
||||
function write_vml_comment(x, _shapeid, ws) {
|
||||
var c = decode_cell(x[0]);
|
||||
var fillopts = {'color2':"#BEFF82", 'type':"gradient"};
|
||||
if(fillopts.type == "gradient") fillopts.angle = "-180";
|
||||
@ -7895,6 +8025,7 @@ function write_comments_xml(data) {
|
||||
o.push('</text></comment>');
|
||||
});
|
||||
} else {
|
||||
if(d[1][0] && d[1][0].T && d[1][0].ID) lastauthor = iauthor.indexOf("tc=" + d[1][0].ID);
|
||||
/* based on Threaded Comments -> Comments projection */
|
||||
o.push('<comment ref="' + d[0] + '" authorId="' + lastauthor + '"><text>');
|
||||
var t = "Comment:\n " + (ts[0]) + "\n";
|
||||
@ -8133,7 +8264,7 @@ function ods_to_csf_3D(r) {
|
||||
}
|
||||
|
||||
function csf_to_ods_3D(r) {
|
||||
return r.replace(/!/,".");
|
||||
return r.replace(/!/,".").replace(/:/, ":.");
|
||||
}
|
||||
|
||||
var strs = {}; // shared strings
|
||||
@ -8219,7 +8350,7 @@ function get_cell_style(styles, cell, opts) {
|
||||
return len;
|
||||
}
|
||||
|
||||
function safe_format(p, fmtid, fillid, opts, themes, styles) {
|
||||
function safe_format(p, fmtid, fillid, opts, themes, styles, date1904) {
|
||||
try {
|
||||
if(opts.cellNF) p.z = table_fmt[fmtid];
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
@ -8234,14 +8365,14 @@ function safe_format(p, fmtid, fillid, opts, themes, styles) {
|
||||
else p.w = SSF_general_num(p.v);
|
||||
}
|
||||
else if(p.t === 'd') {
|
||||
var dd = datenum(p.v);
|
||||
var dd = datenum(p.v, !!date1904);
|
||||
if((dd|0) === dd) p.w = dd.toString(10);
|
||||
else p.w = SSF_general_num(dd);
|
||||
}
|
||||
else if(p.v === undefined) return "";
|
||||
else p.w = SSF_general(p.v,_ssfopts);
|
||||
}
|
||||
else if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v),_ssfopts);
|
||||
else if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v, !!date1904),_ssfopts);
|
||||
else p.w = SSF_format(fmtid,p.v,_ssfopts);
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
if(!opts.cellStyles) return;
|
||||
@ -8321,7 +8452,7 @@ function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) {
|
||||
}
|
||||
|
||||
/* 18.3.1.80 sheetData CT_SheetData ? */
|
||||
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
|
||||
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles, wb);
|
||||
|
||||
/* 18.3.1.2 autoFilter CT_AutoFilter */
|
||||
var afilter = data2.match(afregex);
|
||||
@ -8341,6 +8472,10 @@ function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) {
|
||||
var margins = data2.match(marginregex);
|
||||
if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));
|
||||
|
||||
/* legacyDrawing */
|
||||
var m;
|
||||
if((m = data2.match(/legacyDrawing r:id="(.*?)"/))) s['!legrel'] = m[1];
|
||||
|
||||
if(opts && opts.nodim) refguess.s.c = refguess.s.r = 0;
|
||||
if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
|
||||
if(opts.sheetRows > 0 && s["!ref"]) {
|
||||
@ -8357,6 +8492,7 @@ function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) {
|
||||
}
|
||||
if(columns.length > 0) s["!cols"] = columns;
|
||||
if(merges.length > 0) s["!merges"] = merges;
|
||||
if(rels['!id'][s['!legrel']]) s['!legdrawel'] = rels['!id'][s['!legrel']];
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -8523,21 +8659,27 @@ function write_ws_xml_sheetviews(ws, opts, idx, wb) {
|
||||
return writextag("sheetViews", writextag("sheetView", null, sview), {});
|
||||
}
|
||||
|
||||
function write_ws_xml_cell(cell, ref, ws, opts) {
|
||||
function write_ws_xml_cell(cell, ref, ws, opts, idx, wb, date1904) {
|
||||
if(cell.c) ws['!comments'].push([ref, cell.c]);
|
||||
if((cell.v === undefined || cell.t === "z" && !(opts||{}).sheetStubs) && typeof cell.f !== "string" && typeof cell.z == "undefined") return "";
|
||||
var vv = "";
|
||||
var oldt = cell.t, oldv = cell.v;
|
||||
if(cell.t !== "z") switch(cell.t) {
|
||||
case 'b': vv = cell.v ? "1" : "0"; break;
|
||||
case 'n': vv = ''+cell.v; break;
|
||||
case 'n':
|
||||
if(isNaN(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x24]; } // #NUM!
|
||||
else if(!isFinite(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x07]; } // #DIV/0!
|
||||
else vv = ''+cell.v; break;
|
||||
case 'e': vv = BErr[cell.v]; break;
|
||||
case 'd':
|
||||
if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
|
||||
else {
|
||||
if(opts && opts.cellDates) {
|
||||
var _vv = parseDate(cell.v, date1904);
|
||||
vv = _vv.toISOString();
|
||||
if(_vv.getUTCFullYear() < 1900) vv = vv.slice(vv.indexOf("T") + 1).replace("Z","");
|
||||
} else {
|
||||
cell = dup(cell);
|
||||
cell.t = 'n';
|
||||
vv = ''+(cell.v = datenum(parseDate(cell.v)));
|
||||
vv = ''+(cell.v = datenum(parseDate(cell.v, date1904), date1904));
|
||||
}
|
||||
if(typeof cell.z === 'undefined') cell.z = table_fmt[14];
|
||||
break;
|
||||
@ -8580,7 +8722,7 @@ var parse_ws_xml_data = (function() {
|
||||
var refregex = /ref=["']([^"']*)["']/;
|
||||
var match_v = matchtag("v"), match_f = matchtag("f");
|
||||
|
||||
return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
||||
return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles, wb) {
|
||||
var ri = 0, x = "", cells = [], cref = [], idx=0, i=0, cc=0, d="", p;
|
||||
var tag, tagr = 0, tagc = 0;
|
||||
var sstr, ftag;
|
||||
@ -8591,6 +8733,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
||||
var dense = s["!data"] != null;
|
||||
var rows = [], rowobj = {}, rowrite = false;
|
||||
var sheetStubs = !!opts.sheetStubs;
|
||||
var date1904 = !!((wb||{}).WBProps||{}).date1904;
|
||||
for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
|
||||
x = marr[mt].trim();
|
||||
var xlen = x.length;
|
||||
@ -8658,7 +8801,14 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
||||
|
||||
if((cref=d.match(match_v))!= null && cref[1] !== '') p.v=unescapexml(cref[1]);
|
||||
if(opts.cellFormula) {
|
||||
if((cref=d.match(match_f))!= null && cref[1] !== '') {
|
||||
if((cref=d.match(match_f))!= null ) {
|
||||
if(cref[1] == "") {
|
||||
if(cref[0].indexOf('t="shared"') > -1) {
|
||||
// TODO: parse formula
|
||||
ftag = parsexmltag(cref[0]);
|
||||
if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
|
||||
}
|
||||
} else {
|
||||
/* TODO: match against XLSXFutureFunctions */
|
||||
p.f=unescapexml(utf8read(cref[1]), true);
|
||||
if(!opts.xlfn) p.f = _xlfn(p.f);
|
||||
@ -8672,6 +8822,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
||||
if(!opts.xlfn) ___f = _xlfn(___f);
|
||||
sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
|
||||
}
|
||||
}
|
||||
} else if((cref=d.match(/<f[^>]*\/>/))) {
|
||||
ftag = parsexmltag(cref[0]);
|
||||
if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
|
||||
@ -8727,8 +8878,8 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
||||
break;
|
||||
case 'b': p.v = parsexmlbool(p.v); break;
|
||||
case 'd':
|
||||
if(opts.cellDates) p.v = parseDate(p.v, 1);
|
||||
else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; }
|
||||
if(opts.cellDates) p.v = parseDate(p.v, date1904);
|
||||
else { p.v = datenum(parseDate(p.v, date1904), date1904); p.t = 'n'; }
|
||||
break;
|
||||
/* error string in .w, number in .v */
|
||||
case 'e':
|
||||
@ -8747,8 +8898,8 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
||||
}
|
||||
}
|
||||
}
|
||||
safe_format(p, fmtid, fillid, opts, themes, styles);
|
||||
if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.t = 'd'; p.v = numdate(p.v); }
|
||||
safe_format(p, fmtid, fillid, opts, themes, styles, date1904);
|
||||
if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.v = numdate(p.v + (date1904 ? 1462 : 0)); p.t = typeof p.v == "number" ? 'n' : 'd'; }
|
||||
if(tag.cm && opts.xlmeta) {
|
||||
var cm = (opts.xlmeta.Cell||[])[+tag.cm-1];
|
||||
if(cm && cm.type == 'XLDAPR') p.D = true;
|
||||
@ -8773,6 +8924,7 @@ function write_ws_xml_data(ws, opts, idx, wb) {
|
||||
var o = [], r = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols = [], R=0, C=0, rows = ws['!rows'];
|
||||
var dense = ws["!data"] != null;
|
||||
var params = ({r:rr}), row, height = -1;
|
||||
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
|
||||
for(R = range.s.r; R <= range.e.r; ++R) {
|
||||
r = [];
|
||||
@ -8781,7 +8933,7 @@ function write_ws_xml_data(ws, opts, idx, wb) {
|
||||
ref = cols[C] + rr;
|
||||
var _cell = dense ? (ws["!data"][R]||[])[C]: ws[ref];
|
||||
if(_cell === undefined) continue;
|
||||
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
|
||||
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb, date1904)) != null) r.push(cell);
|
||||
}
|
||||
if(r.length > 0 || (rows && rows[R])) {
|
||||
params = ({r:rr});
|
||||
@ -9512,9 +9664,11 @@ function html_to_sheet(str, _opts) {
|
||||
else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)};
|
||||
else if(!isNaN(fuzzydate(m).getDate())) {
|
||||
o = ({t:'d', v:parseDate(m)});
|
||||
if(opts.UTC === false) o.v = utc_to_local(o.v);
|
||||
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)});
|
||||
o.z = opts.dateNF || table_fmt[14];
|
||||
}
|
||||
if(o.cellText !== false) o.w = m;
|
||||
if(dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = o; }
|
||||
else ws[encode_cell({r:R, c:C})] = o;
|
||||
C += CS;
|
||||
@ -9548,7 +9702,8 @@ function make_html_row(ws, r, R, o) {
|
||||
if(o.editable) w = '<span contenteditable="true">' + w + '</span>';
|
||||
else if(cell) {
|
||||
sp["data-t"] = cell && cell.t || 'z';
|
||||
if(cell.v != null) sp["data-v"] = cell.v;
|
||||
// note: data-v is unaffected by the timezone interpretation
|
||||
if(cell.v != null) sp["data-v"] = cell.v instanceof Date ? cell.v.toISOString() : cell.v;
|
||||
if(cell.z != null) sp["data-z"] = cell.z;
|
||||
if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + escapehtml(cell.l.Target) +'">' + w + '</a>';
|
||||
}
|
||||
@ -9654,6 +9809,7 @@ function sheet_add_dom(ws, table, _opts) {
|
||||
else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
|
||||
else if(!isNaN(fuzzydate(v).getDate())) {
|
||||
o = ({t:'d', v:parseDate(v)});
|
||||
if(opts.UTC) o.v = local_to_utc(o.v);
|
||||
if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)});
|
||||
o.z = opts.dateNF || table_fmt[14];
|
||||
}
|
||||
@ -9958,8 +10114,8 @@ function parse_content_xml(d, _opts, _nfm) {
|
||||
var ws = ({}); if(opts.dense) ws["!data"] = [];
|
||||
var Rn, q;
|
||||
var ctag = ({value:""});
|
||||
var textp = "", textpidx = 0, textptag;
|
||||
var textR = [];
|
||||
var textp = "", textpidx = 0, textptag, oldtextp = "", oldtextpidx = 0;
|
||||
var textR = [], oldtextR = [];
|
||||
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
|
||||
var row_ol = 0;
|
||||
var number_format_map = _nfm || {}, styles = {};
|
||||
@ -9973,7 +10129,6 @@ function parse_content_xml(d, _opts, _nfm) {
|
||||
var creator = "", creatoridx = 0;
|
||||
var isstub = false, intable = false;
|
||||
var i = 0;
|
||||
var baddate = 0;
|
||||
xlmlregex.lastIndex = 0;
|
||||
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
|
||||
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
|
||||
@ -10044,7 +10199,7 @@ function parse_content_xml(d, _opts, _nfm) {
|
||||
C+= colpeat-1;
|
||||
} else if(Rn[1]!=='/') {
|
||||
++C;
|
||||
textp = ""; textpidx = 0; textR = [];
|
||||
textp = oldtextp = ""; textpidx = oldtextpidx = 0; textR = []; oldtextR = [];
|
||||
colpeat = 1;
|
||||
var rptR = rowpeat ? R + rowpeat - 1 : R;
|
||||
if(C > range.e.c) range.e.c = C;
|
||||
@ -10080,19 +10235,23 @@ function parse_content_xml(d, _opts, _nfm) {
|
||||
/* 19.675.2 table:number-columns-repeated */
|
||||
if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10);
|
||||
|
||||
/* 19.385 office:value-type */
|
||||
/* 19.385 office:value-type TODO: verify ODS and UOS */
|
||||
switch(q.t) {
|
||||
case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']) || (+ctag['boolean-value'] >= 1); break;
|
||||
case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break;
|
||||
case 'float': q.t = 'n'; q.v = parseFloat(ctag.value);
|
||||
if(opts.cellDates && q.z && fmt_is_date(q.z)) { q.v = numdate(q.v + (WB.WBProps.date1904 ? 1462 : 0)); q.t = typeof q.v == "number" ? 'n' : 'd'; }
|
||||
break;
|
||||
case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break;
|
||||
case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break;
|
||||
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']);
|
||||
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904) - baddate; }
|
||||
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value'], WB.WBProps.date1904);
|
||||
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904); }
|
||||
if(!q.z) q.z = 'm/d/yy'; break;
|
||||
/* NOTE: for `time`, Excel ODS export incorrectly uses durations relative to 1900 epoch even if 1904 is specified */
|
||||
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400;
|
||||
if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); }
|
||||
if(opts.cellDates) { q.v = numdate(q.v); q.t = typeof q.v == "number" ? 'n' : 'd'; }
|
||||
if(!q.z) q.z = 'HH:MM:SS'; break;
|
||||
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
|
||||
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']);
|
||||
break;
|
||||
default:
|
||||
if(q.t === 'string' || q.t === 'text' || !q.t) {
|
||||
q.t = 's';
|
||||
@ -10153,10 +10312,17 @@ function parse_content_xml(d, _opts, _nfm) {
|
||||
if(textR.length) comment.R = textR;
|
||||
comment.a = creator;
|
||||
comments.push(comment);
|
||||
textp = oldtextp; textpidx = oldtextpidx; textR = oldtextR;
|
||||
}
|
||||
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);}
|
||||
creator = ""; creatoridx = 0;
|
||||
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
|
||||
state.push([Rn[3], false]);
|
||||
var annotag = parsexmltag(Rn[0], true);
|
||||
/* office:display TODO: check if there is a global override */
|
||||
if(!(annotag["display"] && parsexmlbool(annotag["display"]))) comments.hidden = true;
|
||||
oldtextp = textp; oldtextpidx = textpidx; oldtextR = textR;
|
||||
textp = ""; textpidx = 0; textR = [];
|
||||
}
|
||||
creator = ""; creatoridx = 0;
|
||||
break;
|
||||
|
||||
case 'creator': // 4.3.2.7 <dc:creator>
|
||||
@ -10282,9 +10448,7 @@ function parse_content_xml(d, _opts, _nfm) {
|
||||
case 'null-date': // 9.4.2 <table:null-date>
|
||||
tag = parsexmltag(Rn[0], false);
|
||||
switch(tag["date-value"]) {
|
||||
case "1904-01-01": WB.WBProps.date1904 = true;
|
||||
/* falls through */
|
||||
case "1900-01-01": baddate = 0;
|
||||
case "1904-01-01": WB.WBProps.date1904 = true; break;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -10306,6 +10470,9 @@ function parse_content_xml(d, _opts, _nfm) {
|
||||
if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) {
|
||||
var ptp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
|
||||
textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0];
|
||||
} else if(Rn[0].slice(-2) == "/>") {
|
||||
/* TODO: is self-closing 文本串 valid? */
|
||||
textp += "\n";
|
||||
} else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
|
||||
break; // <text:p>
|
||||
case 's': break; // <text:s>
|
||||
@ -10590,7 +10757,9 @@ function write_number_format_ods(nf, nfidx) {
|
||||
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
|
||||
payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
|
||||
break;
|
||||
case '/': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
case '\\': c = nf[++i];
|
||||
payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
default: console.error("unrecognized character " + c + " in ODF format " + nf);
|
||||
}
|
||||
if(!has_time) break j;
|
||||
@ -10617,7 +10786,7 @@ function write_number_format_ods(nf, nfidx) {
|
||||
while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
|
||||
payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
|
||||
break;
|
||||
case '/': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
|
||||
case "a":
|
||||
if(nf.slice(i, i+3).toLowerCase() == "a/p") { payload += '<number:am-pm/>'; i += 2; break; } // Note: ODF does not support A/P
|
||||
if(nf.slice(i, i+5).toLowerCase() == "am/pm") { payload += '<number:am-pm/>'; i += 4; break; }
|
||||
@ -10673,10 +10842,15 @@ function write_number_format_ods(nf, nfidx) {
|
||||
}
|
||||
|
||||
function write_names_ods(Names, SheetNames, idx) {
|
||||
var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
|
||||
//var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
|
||||
var scoped = []; for(var namei = 0; namei < Names.length; ++namei) {
|
||||
var name = Names[namei];
|
||||
if(!name) continue;
|
||||
if(name.Sheet == (idx == -1 ? null : idx)) scoped.push(name);
|
||||
}
|
||||
if(!scoped.length) return "";
|
||||
return " <table:named-expressions>\n" + scoped.map(function(name) {
|
||||
var odsref = csf_to_ods_3D(name.Ref);
|
||||
var odsref = (idx == -1 ? "$" : "") + csf_to_ods_3D(name.Ref);
|
||||
return " " + writextag("table:named-range", null, {
|
||||
"table:name": name.Name,
|
||||
"table:cell-range-address": odsref,
|
||||
@ -10695,8 +10869,7 @@ var write_content_ods = /* @__PURE__ */(function() {
|
||||
};
|
||||
|
||||
var null_cell_xml = ' <table:table-cell />\n';
|
||||
var covered_cell_xml = ' <table:covered-table-cell/>\n';
|
||||
var write_ws = function(ws, wb, i, opts, nfs) {
|
||||
var write_ws = function(ws, wb, i, opts, nfs, date1904) {
|
||||
/* Section 9 Tables */
|
||||
var o = [];
|
||||
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="ta1">\n');
|
||||
@ -10727,7 +10900,7 @@ var write_content_ods = /* @__PURE__ */(function() {
|
||||
ct['table:number-rows-spanned'] = (marr[mi].e.r - marr[mi].s.r + 1);
|
||||
break;
|
||||
}
|
||||
if(skip) { o.push(covered_cell_xml); continue; }
|
||||
if(skip) { o.push(' <table:covered-table-cell/>\n'); continue; }
|
||||
var ref = encode_cell({r:R, c:C}), cell = dense ? (ws["!data"][R]||[])[C]: ws[ref];
|
||||
if(cell && cell.f) {
|
||||
ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f));
|
||||
@ -10756,13 +10929,13 @@ var write_content_ods = /* @__PURE__ */(function() {
|
||||
ct['office:value-type'] = "string";
|
||||
break;
|
||||
case 'd':
|
||||
textp = (cell.w||(parseDate(cell.v).toISOString()));
|
||||
textp = (cell.w||(parseDate(cell.v, date1904).toISOString()));
|
||||
ct['office:value-type'] = "date";
|
||||
ct['office:date-value'] = (parseDate(cell.v).toISOString());
|
||||
ct['office:date-value'] = (parseDate(cell.v, date1904).toISOString());
|
||||
ct['table:style-name'] = "ce1";
|
||||
break;
|
||||
//case 'e':
|
||||
default: o.push(null_cell_xml); continue;
|
||||
//case 'e': // TODO: translate to ODS errors
|
||||
default: o.push(null_cell_xml); continue; // TODO: empty cell with comments
|
||||
}
|
||||
var text_p = write_text_p(textp);
|
||||
if(cell.l && cell.l.Target) {
|
||||
@ -10773,7 +10946,17 @@ var write_content_ods = /* @__PURE__ */(function() {
|
||||
text_p = writextag('text:a', text_p, {'xlink:href': _tgt.replace(/&/g, "&")});
|
||||
}
|
||||
if(nfs[cell.z]) ct["table:style-name"] = "ce" + nfs[cell.z].slice(1);
|
||||
o.push(' ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n');
|
||||
var payload = writextag('text:p', text_p, {});
|
||||
if(cell.c) {
|
||||
var acreator = "", apayload = "", aprops = {};
|
||||
for(var ci = 0; ci < cell.c.length; ++ci) {
|
||||
if(!acreator && cell.c[ci].a) acreator = cell.c[ci].a;
|
||||
apayload += "<text:p>" + write_text_p(cell.c[ci].t) + "</text:p>";
|
||||
}
|
||||
if(!cell.c.hidden) aprops["office:display"] = true;
|
||||
payload = writextag('office:annotation', apayload, aprops) + payload;
|
||||
}
|
||||
o.push(' ' + writextag('table:table-cell', payload, ct) + '\n');
|
||||
}
|
||||
o.push(' </table:table-row>\n');
|
||||
}
|
||||
@ -10918,7 +11101,7 @@ var write_content_ods = /* @__PURE__ */(function() {
|
||||
o.push(' <office:body>\n');
|
||||
o.push(' <office:spreadsheet>\n');
|
||||
if(((wb.Workbook||{}).WBProps||{}).date1904) o.push(' <table:calculation-settings table:case-sensitive="false" table:search-criteria-must-apply-to-whole-cell="true" table:use-wildcards="true" table:use-regular-expressions="false" table:automatic-find-labels="false">\n <table:null-date table:date-value="1904-01-01"/>\n </table:calculation-settings>\n');
|
||||
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs));
|
||||
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs, ((wb.Workbook||{}).WBProps||{}).date1904));
|
||||
if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1));
|
||||
o.push(' </office:spreadsheet>\n');
|
||||
o.push(' </office:body>\n');
|
||||
@ -11032,6 +11215,13 @@ function safe_parse_wbrels(wbrels, sheets) {
|
||||
return !wbrels || wbrels.length === 0 ? null : wbrels;
|
||||
}
|
||||
|
||||
function parse_sheet_legacy_drawing(sheet, type, zip, path, idx, opts, wb, comments) {
|
||||
if(!sheet || !sheet['!legdrawel']) return;
|
||||
var dfile = resolve_path(sheet['!legdrawel'].Target, path);
|
||||
var draw = getzipstr(zip, dfile, true);
|
||||
if(draw) parse_vml(utf8read(draw), sheet, comments||[]);
|
||||
}
|
||||
|
||||
function safe_parse_sheet(zip, path, relsPath, sheet, idx, sheetRels, sheets, stype, opts, wb, themes, styles) {
|
||||
try {
|
||||
sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
|
||||
@ -11070,6 +11260,7 @@ function safe_parse_sheet(zip, path, relsPath, sheet, idx, sheetRels, sheets, st
|
||||
}
|
||||
});
|
||||
if(tcomments && tcomments.length) sheet_insert_comments(_ws, tcomments, true, opts.people || []);
|
||||
parse_sheet_legacy_drawing(_ws, stype, zip, path, idx, opts, wb, comments);
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
}
|
||||
|
||||
@ -11369,6 +11560,9 @@ f = "docProps/app.xml";
|
||||
add_rels(opts.rels, 4, f, RELS.CUST_PROPS);
|
||||
}
|
||||
|
||||
var people = ["SheetJ5"];
|
||||
opts.tcid = 0;
|
||||
|
||||
for(rId=1;rId <= wb.SheetNames.length; ++rId) {
|
||||
var wsrels = {'!id':{}};
|
||||
var ws = wb.Sheets[wb.SheetNames[rId-1]];
|
||||
@ -11388,6 +11582,17 @@ f = "docProps/app.xml";
|
||||
var need_vml = false;
|
||||
var cf = "";
|
||||
if(comments && comments.length > 0) {
|
||||
var needtc = false;
|
||||
comments.forEach(function(carr) {
|
||||
carr[1].forEach(function(c) { if(c.T == true) needtc = true; });
|
||||
});
|
||||
if(needtc) {
|
||||
cf = "xl/threadedComments/threadedComment" + rId + ".xml";
|
||||
zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts));
|
||||
ct.threadedcomments.push(cf);
|
||||
add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + ".xml", RELS.TCMNT);
|
||||
}
|
||||
|
||||
cf = "xl/comments" + rId + "." + wbext;
|
||||
zip_add_file(zip, cf, write_comments_bin(comments, opts));
|
||||
ct.comments.push(cf);
|
||||
@ -11443,6 +11648,13 @@ f = "docProps/app.xml";
|
||||
ct.metadata.push(f);
|
||||
add_rels(opts.wbrels, -1, "metadata." + wbext, RELS.XLMETA);
|
||||
|
||||
if(people.length > 1) {
|
||||
f = "xl/persons/person.xml";
|
||||
zip_add_file(zip, f, write_people_xml(people, opts));
|
||||
ct.people.push(f);
|
||||
add_rels(opts.wbrels, -1, "persons/person.xml", RELS.PEOPLE);
|
||||
}
|
||||
|
||||
zip_add_file(zip, "[Content_Types].xml", write_ct(ct, opts));
|
||||
zip_add_file(zip, '_rels/.rels', write_rels(opts.rels));
|
||||
zip_add_file(zip, 'xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));
|
||||
@ -11948,7 +12160,7 @@ function make_json_row(sheet, r, R, cols, header, hdr, o) {
|
||||
}
|
||||
if(!dense || sheet["!data"][R]) for (var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var val = dense ? (sheet["!data"][R]||[])[C] : sheet[cols[C] + rr];
|
||||
if(val === undefined || val.t === undefined) {
|
||||
if(val == null || val.t === undefined) {
|
||||
if(defval === undefined) continue;
|
||||
if(hdr[C] != null) { row[hdr[C]] = defval; }
|
||||
continue;
|
||||
@ -11957,7 +12169,12 @@ function make_json_row(sheet, r, R, cols, header, hdr, o) {
|
||||
switch(val.t){
|
||||
case 'z': if(v == null) break; continue;
|
||||
case 'e': v = (v == 0 ? null : void 0); break;
|
||||
case 's': case 'd': case 'b': case 'n': break;
|
||||
case 's': case 'b':
|
||||
case 'n': if(!val.z || !fmt_is_date(val.z)) break;
|
||||
v = numdate(v); // TODO: date1904 setting should also be stored in worksheet object
|
||||
if(typeof v == "number") break;
|
||||
/* falls through */
|
||||
case 'd': if(!(o && o.UTC)) v = utc_to_local(v); break;
|
||||
default: throw new Error('unrecognized type ' + val.t);
|
||||
}
|
||||
if(hdr[C] != null) {
|
||||
@ -12167,6 +12384,7 @@ function sheet_add_json(_ws, js, opts) {
|
||||
else if(typeof v == 'string') t = 's';
|
||||
else if(v instanceof Date) {
|
||||
t = 'd';
|
||||
if(!o.UTC) v = local_to_utc(v);
|
||||
if(!o.cellDates) { t = 'n'; v = datenum(v); }
|
||||
z = (cell != null && cell.z && fmt_is_date(cell.z)) ? cell.z : (o.dateNF || table_fmt[14]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user