forked from sheetjs/sheetjs
roundtrip 1904 date setting
This commit is contained in:
parent
83ddb4c120
commit
4cc0412154
4
.github/workflows/deno.yml
vendored
4
.github/workflows/deno.yml
vendored
@ -20,7 +20,7 @@ jobs:
|
||||
- run: sudo chmod a+x /usr/bin/rooster
|
||||
- run: make init
|
||||
- run: 'cd test_files; make all; cd -'
|
||||
- run: deno test --allow-env --allow-read --allow-write test.ts
|
||||
- run: deno test --allow-env --allow-read --allow-write --config misc/test.deno.jsonc test.ts
|
||||
# full test
|
||||
full:
|
||||
runs-on: ubuntu-latest
|
||||
@ -36,4 +36,4 @@ jobs:
|
||||
- run: sudo chmod a+x /usr/bin/rooster
|
||||
- run: make init
|
||||
- run: 'cd test_files; make all; cd -'
|
||||
- run: deno test --allow-env --allow-read --allow-write test.ts
|
||||
- run: deno test --allow-env --allow-read --allow-write --config misc/test.deno.jsonc test.ts
|
||||
|
5
Makefile
5
Makefile
@ -141,9 +141,12 @@ test mocha: test.js ## Run test suite
|
||||
test-esm: test.mjs ## Run Node ESM test suite
|
||||
npx -y mocha@9 -R spec -t 30000 $<
|
||||
|
||||
test.ts: test.mts
|
||||
node -pe 'var data = fs.readFileSync("'$<'", "utf8"); data.split("\n").map(function(l) { return l.replace(/^describe\((.*?)function\(\)/, "Deno.test($$1async function(t)").replace(/\b(?:it|describe)\((.*?)function\(\)/g, "await t.step($$1async function(t)").replace("assert.ok", "assert.assert"); }).join("\n")' > $@
|
||||
|
||||
.PHONY: test-deno
|
||||
test-deno: test.ts ## Run Deno test suite
|
||||
deno test --allow-env --allow-read --allow-write $<
|
||||
deno test --allow-env --allow-read --allow-write --config misc/test.deno.jsonc $<
|
||||
|
||||
#* To run tests for one format, make test_<fmt>
|
||||
#* To run the core test suite, make test_misc
|
||||
|
@ -12,7 +12,9 @@ port calculations to web apps; automate common spreadsheet tasks, and much more!
|
||||
![License](https://img.shields.io/github/license/SheetJS/sheetjs)
|
||||
[![Build Status](https://img.shields.io/github/workflow/status/sheetjs/sheetjs/Tests:%20node.js)](https://github.com/SheetJS/sheetjs/actions)
|
||||
[![Snyk Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/SheetJS/sheetjs)](https://snyk.io/test/github/SheetJS/sheetjs)
|
||||
[![npm Downloads](https://img.shields.io/npm/dm/xlsx.svg)](https://npmjs.org/package/xlsx)
|
||||
[![npm Downloads](https://img.shields.io/npm/dm/xlsx.svg)](https://cdn.sheetjs.com/)
|
||||
[![GitHub Repo stars](https://img.shields.io/github/stars/SheetJS/sheetjs?style=social)](https://github.com/SheetJS/sheetjs)
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/sheetjs?pixel)](https://github.com/SheetJS/sheetjs)
|
||||
|
||||
[![Build Status](https://saucelabs.com/browser-matrix/sheetjs.svg)](https://saucelabs.com/u/sheetjs)
|
||||
@ -25,13 +27,13 @@ port calculations to web apps; automate common spreadsheet tasks, and much more!
|
||||
|
||||
## Related Projects
|
||||
|
||||
- <https://oss.sheetjs.com/notes/> file format notes
|
||||
- <https://oss.sheetjs.com/notes/>: File Format Notes
|
||||
|
||||
- [`ssf`](packages/ssf): Format data using ECMA-376 spreadsheet format codes
|
||||
|
||||
- [`xlsx-cli`](packages/xlsx-cli/): NodeJS command-line tool for processing files
|
||||
|
||||
- [`test_files`](https://github.com/SheetJS/test_files): test files repo
|
||||
- [`test_files`](https://github.com/SheetJS/test_files): Sample spreadsheets
|
||||
|
||||
- [`cfb`](https://github.com/SheetJS/js-cfb): Container (OLE/ZIP) format library
|
||||
|
||||
|
@ -157,8 +157,8 @@ 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.cellDates) { cell.t = 'd'; cell.w = SSF_format(cell.z, datenum(cell.v)); }
|
||||
else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF_format(cell.z, 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); }
|
||||
}
|
||||
else cell.t = 's';
|
||||
}
|
||||
|
@ -440,7 +440,7 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
wb.Workbook.Names.push(nn);
|
||||
} break;
|
||||
case 'C': /* cell */
|
||||
var C_seen_K = false, C_seen_X = false, C_seen_S = false, C_seen_E = false, _R = -1, _C = -1;
|
||||
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";
|
||||
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
|
||||
case 'A': break; // TODO: comment
|
||||
case 'X': C = parseInt(record[rj].slice(1), 10)-1; C_seen_X = true; break;
|
||||
@ -450,26 +450,24 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
break;
|
||||
case 'K':
|
||||
val = record[rj].slice(1);
|
||||
if(val.charAt(0) === '"') val = val.slice(1,val.length - 1);
|
||||
else if(val === 'TRUE') val = true;
|
||||
else if(val === 'FALSE') val = false;
|
||||
if(val.charAt(0) === '"') { val = val.slice(1,val.length - 1); cell_t = "s"; }
|
||||
else if(val === 'TRUE' || val === 'FALSE') { val = val === 'TRUE'; cell_t = "b"; }
|
||||
else if(!isNaN(fuzzynum(val))) {
|
||||
val = fuzzynum(val);
|
||||
if(next_cell_format !== null && fmt_is_date(next_cell_format)) val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : 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);
|
||||
val = parseDate(val); cell_t = "d";
|
||||
if(!opts.cellDates) { cell_t = "n"; val = datenum(val, wb.Workbook.WBProps.date1904); }
|
||||
}
|
||||
if(typeof $cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = $cptable.utils.decode(opts.codepage, val);
|
||||
C_seen_K = true;
|
||||
break;
|
||||
case 'E':
|
||||
C_seen_E = true;
|
||||
var formula = rc_to_a1(record[rj].slice(1), {r:R,c:C});
|
||||
arr[R][C] = [arr[R][C], formula];
|
||||
formula = rc_to_a1(record[rj].slice(1), {r:R,c:C});
|
||||
break;
|
||||
case 'S':
|
||||
C_seen_S = true;
|
||||
arr[R][C] = [arr[R][C], "S5S"];
|
||||
break;
|
||||
case 'G': break; // unknown
|
||||
case 'R': _R = parseInt(record[rj].slice(1), 10)-1; break;
|
||||
@ -477,15 +475,21 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
}
|
||||
if(C_seen_K) {
|
||||
if(arr[R][C] && arr[R][C].length == 2) arr[R][C][0] = val;
|
||||
else arr[R][C] = val;
|
||||
if(!arr[R][C]) arr[R][C] = { t: cell_t, v: val };
|
||||
else { arr[R][C].t = cell_t; arr[R][C].v = val; }
|
||||
if(next_cell_format) arr[R][C].z = next_cell_format;
|
||||
if(opts.cellText !== false && next_cell_format) arr[R][C].w = SSF_format(arr[R][C].z, arr[R][C].v, { date1904: wb.Workbook.WBProps.date1904 });
|
||||
next_cell_format = null;
|
||||
}
|
||||
if(C_seen_S) {
|
||||
if(C_seen_E) throw new Error("SYLK shared formula cannot have own formula");
|
||||
var shrbase = _R > -1 && arr[_R][_C];
|
||||
if(!shrbase || !shrbase[1]) throw new Error("SYLK shared formula cannot find base");
|
||||
arr[R][C][1] = shift_formula_str(shrbase[1], {r: R - _R, c: C - _C});
|
||||
formula = shift_formula_str(shrbase[1], {r: R - _R, c: C - _C});
|
||||
}
|
||||
if(formula) {
|
||||
if(!arr[R][C]) arr[R][C] = { t: 'n', f: formula };
|
||||
else arr[R][C].f = formula;
|
||||
}
|
||||
break;
|
||||
case 'F': /* Format */
|
||||
@ -537,7 +541,8 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
function sylk_to_workbook(d/*:RawData*/, opts)/*:Workbook*/ {
|
||||
var aoasht = sylk_to_aoa(d, opts);
|
||||
var aoa = aoasht[0], ws = aoasht[1], wb = aoasht[2];
|
||||
var o = aoa_to_sheet(aoa, opts);
|
||||
var _opts = dup(opts); _opts.date1904 = (((wb||{}).Workbook || {}).WBProps || {}).date1904;
|
||||
var o = aoa_to_sheet(aoa, _opts);
|
||||
keys(ws).forEach(function(k) { o[k] = ws[k]; });
|
||||
var outwb = sheet_to_workbook(o, opts);
|
||||
keys(wb).forEach(function(k) { outwb[k] = wb[k]; });
|
||||
@ -581,11 +586,12 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
});
|
||||
}
|
||||
|
||||
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
|
||||
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/, wb/*:?WorkBook*/)/*:string*/ {
|
||||
var preamble/*:Array<string>*/ = ["ID;PSheetJS;N;E"], o/*:Array<string>*/ = [];
|
||||
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
|
||||
var dense = Array.isArray(ws);
|
||||
var RS = "\r\n";
|
||||
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
|
||||
preamble.push("P;PGeneral");
|
||||
preamble.push("F;P0;DG0G8;M255");
|
||||
@ -593,12 +599,13 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
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) {
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var coord = encode_cell({r:R,c:C});
|
||||
cell = dense ? (ws[R]||[])[C]: ws[coord];
|
||||
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
|
||||
o.push(write_ws_cell_sylk(cell, ws, R, C, opts));
|
||||
o.push(write_ws_cell_sylk(cell, ws, R, C, opts)); // TODO: pass date1904 info
|
||||
}
|
||||
}
|
||||
return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
|
||||
|
@ -45,6 +45,7 @@ function write_BrtWbProp(data/*:?WBProps*/, o) {
|
||||
var flags = 0;
|
||||
if(data) {
|
||||
/* TODO: mirror parse_BrtWbProp fields */
|
||||
if(data.date1904) flags |= 0x01;
|
||||
if(data.filterPrivacy) flags |= 0x08;
|
||||
}
|
||||
o.write_shift(4, flags);
|
||||
|
@ -942,9 +942,10 @@ function write_props_xlml(wb/*:Workbook*/, opts)/*:string*/ {
|
||||
return o.join("");
|
||||
}
|
||||
/* TODO */
|
||||
function write_wb_xlml(/*::wb, opts*/)/*:string*/ {
|
||||
function write_wb_xlml(wb/*::, opts*/)/*:string*/ {
|
||||
/* OfficeDocumentSettings */
|
||||
/* ExcelWorkbook */
|
||||
if((((wb||{}).Workbook||{}).WBProps||{}).date1904) return '<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"><Date1904/></ExcelWorkbook>';
|
||||
return "";
|
||||
}
|
||||
/* TODO */
|
||||
|
@ -49,13 +49,14 @@ function parse_content_xml(d/*:string*/, _opts)/*:Workbook*/ {
|
||||
var merges/*:Array<Range>*/ = [], mrange = {}, mR = 0, mC = 0;
|
||||
var rowinfo/*:Array<RowInfo>*/ = [], rowpeat = 1, colpeat = 1;
|
||||
var arrayf/*:Array<[Range, string]>*/ = [];
|
||||
var WB = {Names:[]};
|
||||
var WB = {Names:[], WBProps:{}};
|
||||
var atag = ({}/*:any*/);
|
||||
var _Ref/*:[string, string]*/ = ["", ""];
|
||||
var comments/*:Array<Comment>*/ = [], comment/*:Comment*/ = ({}/*:any*/);
|
||||
var creator = "", creatoridx = 0;
|
||||
var isstub = false, intable = false;
|
||||
var i = 0;
|
||||
var baddate = 1;
|
||||
xlmlregex.lastIndex = 0;
|
||||
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
|
||||
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
|
||||
@ -167,7 +168,7 @@ function parse_content_xml(d/*:string*/, _opts)/*:Workbook*/ {
|
||||
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); }
|
||||
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904) - baddate; }
|
||||
q.z = 'm/d/yy'; break;
|
||||
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400;
|
||||
if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); }
|
||||
@ -368,7 +369,14 @@ function parse_content_xml(d/*:string*/, _opts)/*:Workbook*/ {
|
||||
case 'table-header-columns': break; // 9.1.11 <table:table-header-columns>
|
||||
case 'table-columns': break; // 9.1.12 <table:table-columns>
|
||||
|
||||
case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
|
||||
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;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'graphic-properties': break; // 17.21 <style:graphic-properties>
|
||||
case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
|
||||
|
@ -255,6 +255,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
|
||||
write_automatic_styles_ods(o, wb);
|
||||
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));
|
||||
if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1));
|
||||
o.push(' </office:spreadsheet>\n');
|
||||
|
@ -134,7 +134,7 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
|
||||
case 'xml':
|
||||
case 'xlml': return write_string_type(write_xlml(wb, o), o);
|
||||
case 'slk':
|
||||
case 'sylk': return write_string_type(SYLK.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
|
||||
case 'sylk': return write_string_type(SYLK.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb), o);
|
||||
case 'htm':
|
||||
case 'html': return write_string_type(sheet_to_html(wb.Sheets[wb.SheetNames[idx]], o), o);
|
||||
case 'txt': return write_stxt_type(sheet_to_txt(wb.Sheets[wb.SheetNames[idx]], o), o);
|
||||
|
@ -45,6 +45,7 @@ can be installed with Bash on Windows or with `cygwin`.
|
||||
- [`Chrome / Chromium extensions`](chrome/)
|
||||
- [`Google Sheets API`](https://docs.sheetjs.com/docs/getting-started/demos/gsheet)
|
||||
- [`Adobe Apps`](https://docs.sheetjs.com/docs/getting-started/demos/extendscript)
|
||||
- [`Excel JavaScript API`](https://docs.sheetjs.com/docs/getting-started/demos/excel)
|
||||
- [`Headless Browsers`](headless/)
|
||||
- [`canvas-datagrid`](datagrid/)
|
||||
- [`x-spreadsheet`](xspreadsheet/)
|
||||
|
5
misc/import_map.json
Normal file
5
misc/import_map.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"imports": {
|
||||
"jsdom": "https://esm.sh/jsdom"
|
||||
}
|
||||
}
|
11
misc/test.deno.jsonc
Normal file
11
misc/test.deno.jsonc
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"deno.ns",
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"dom.asynciterable"
|
||||
]
|
||||
},
|
||||
"importMap": "./import_map.json"
|
||||
}
|
336
test.mjs
generated
336
test.mjs
generated
@ -342,7 +342,7 @@ function parsetest(x/*:string*/, wb/*:Workbook*/, full/*:boolean*/, ext/*:?strin
|
||||
|
||||
var wbtable = {};
|
||||
|
||||
(browser ? describe.skip : describe)('should parse test files', function() {
|
||||
if(!browser) describe('should parse test files', function() {
|
||||
files.forEach(function(x) {
|
||||
if(x.slice(-8) == ".pending" || !fs.existsSync(dir + x)) return;
|
||||
it(x, function() {
|
||||
@ -383,13 +383,13 @@ function each_sheet(wb, f) { wb.SheetNames.forEach(function(n, i) { f(wb.Sheets[
|
||||
|
||||
/* comments_stress_test family */
|
||||
function check_comments(wb) {
|
||||
var ws0 = wb.Sheets.Sheet2;
|
||||
var ws0 = wb.Sheets["Sheet2"];
|
||||
assert.equal(get_cell(ws0,"A1").c[0].a, 'Author');
|
||||
assert.equal(get_cell(ws0,"A1").c[0].t, 'Author:\nGod thinks this is good');
|
||||
assert.equal(get_cell(ws0,"C1").c[0].a, 'Author');
|
||||
assert.equal(get_cell(ws0,"C1").c[0].t, 'I really hope that xlsx decides not to use magic like rPr');
|
||||
|
||||
var ws3 = wb.Sheets.Sheet4;
|
||||
var ws3 = wb.Sheets["Sheet4"];
|
||||
assert.equal(get_cell(ws3,"B1").c[0].a, 'Author');
|
||||
assert.equal(get_cell(ws3,"B1").c[0].t, 'The next comment is empty');
|
||||
assert.equal(get_cell(ws3,"B2").c[0].a, 'Author');
|
||||
@ -401,14 +401,14 @@ describe('parse options', function() {
|
||||
describe('cell', function() {
|
||||
it('XLSX should generate HTML by default', function() {
|
||||
var wb = X.read(fs.readFileSync(paths.cstxlsx), {type:TYPE});
|
||||
var ws = wb.Sheets.Sheet1;
|
||||
var ws = wb.Sheets["Sheet1"];
|
||||
each_cell(ws, function(cell) {
|
||||
assert.ok(html_cell_types.indexOf(cell.t) === -1 || cell.h);
|
||||
});
|
||||
});
|
||||
it('XLSX should not generate HTML when requested', function() {
|
||||
var wb = X.read(fs.readFileSync(paths.cstxlsx), {type:TYPE, cellHTML:false});
|
||||
var ws = wb.Sheets.Sheet1;
|
||||
var ws = wb.Sheets["Sheet1"];
|
||||
each_cell(ws, function(cell) {
|
||||
assert.ok(typeof cell.h === 'undefined');
|
||||
});
|
||||
@ -483,7 +483,7 @@ describe('parse options', function() {
|
||||
});
|
||||
it('should not generate cell styles by default', function() {
|
||||
CSSPaths.forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE, WTF:1});
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE, WTF:true});
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
each_cell(ws, function(cell) {
|
||||
@ -513,7 +513,7 @@ describe('parse options', function() {
|
||||
});
|
||||
it('should generate cell dates when requested', function() {
|
||||
DTPaths.forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE, cellDates: true, WTF:1});
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE, cellDates: true, WTF:true});
|
||||
var found = false;
|
||||
each_sheet(wb, function(ws/*::, i*/) { /*:: void i; */each_cell(ws, function(cell) {
|
||||
if(cell.t === 'd') return (found = true);
|
||||
@ -529,9 +529,9 @@ describe('parse options', function() {
|
||||
var str = X.write(wb, {bookType: "xlsx", type: "binary"});
|
||||
var wb2 = X.read(str, {type: "binary"});
|
||||
/*jshint -W069 */
|
||||
assert.equal(wb2.Sheets.Sheet1["A1"].f, "IFS(2>3,1,3>2,2)");
|
||||
assert.equal(wb2.Sheets["Sheet1"]["A1"].f, "IFS(2>3,1,3>2,2)");
|
||||
var wb3 = X.read(str, {type: "binary", xlfn: true});
|
||||
assert.equal(wb3.Sheets.Sheet1["A1"].f, "_xlfn.IFS(2>3,1,3>2,2)");
|
||||
assert.equal(wb3.Sheets["Sheet1"]["A1"].f, "_xlfn.IFS(2>3,1,3>2,2)");
|
||||
/*jshint +W069 */
|
||||
});
|
||||
});
|
||||
@ -539,27 +539,27 @@ describe('parse options', function() {
|
||||
it('should not generate sheet stubs by default', function() {
|
||||
MCPaths.forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE});
|
||||
assert.throws(function() { return get_cell(wb.Sheets.Merge, "A2").v; });
|
||||
assert.throws(function() { return get_cell(wb.Sheets["Merge"], "A2").v; });
|
||||
});
|
||||
});
|
||||
it('should generate sheet stubs when requested', function() {
|
||||
MCPaths.forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE, sheetStubs:true});
|
||||
assert.ok(get_cell(wb.Sheets.Merge, "A2").t == 'z');
|
||||
assert.ok(get_cell(wb.Sheets["Merge"], "A2").t == 'z');
|
||||
});
|
||||
});
|
||||
it('should handle stub cells', function() {
|
||||
MCPaths.forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE, sheetStubs:true});
|
||||
X.utils.sheet_to_csv(wb.Sheets.Merge);
|
||||
X.utils.sheet_to_json(wb.Sheets.Merge);
|
||||
X.utils.sheet_to_formulae(wb.Sheets.Merge);
|
||||
X.utils.sheet_to_csv(wb.Sheets["Merge"]);
|
||||
X.utils.sheet_to_json(wb.Sheets["Merge"]);
|
||||
X.utils.sheet_to_formulae(wb.Sheets["Merge"]);
|
||||
ofmt.forEach(function(f) { if(f != "dbf") X.write(wb, {type:TYPE, bookType:f}); });
|
||||
});
|
||||
});
|
||||
function checkcells(wb, A46, B26, C16, D2) {
|
||||
[ ["A46", A46], ["B26", B26], ["C16", C16], ["D2", D2] ].forEach(function(r) {
|
||||
assert.ok((typeof get_cell(wb.Sheets.Text, r[0]) !== 'undefined') == r[1]);
|
||||
assert.ok((typeof get_cell(wb.Sheets["Text"], r[0]) !== 'undefined') == r[1]);
|
||||
});
|
||||
}
|
||||
it('should read all cells by default', function() { FSTPaths.forEach(function(p) {
|
||||
@ -581,35 +581,35 @@ describe('parse options', function() {
|
||||
assert.ok(ws['!ref'] === "A1:B3");
|
||||
var wb = X.utils.book_new();
|
||||
X.utils.book_append_sheet(wb, ws, "Sheet1");
|
||||
var bs = X.write(wb, { bookType: fmt, type: ot, WTF: 1 });
|
||||
var bs = X.write(wb, { bookType: fmt, type: ot, WTF:true });
|
||||
|
||||
var wb0 = X.read(bs, { type: ot, WTF: 1 });
|
||||
var ws0 = wb0.Sheets.Sheet1;
|
||||
var wb0 = X.read(bs, { type: ot, WTF:true });
|
||||
var ws0 = wb0.Sheets["Sheet1"];
|
||||
assert.equal(ws0['!ref'], "A1:B3");
|
||||
assert.equal(get_cell(ws0, "A1").v, 1);
|
||||
assert.equal(get_cell(ws0, "A1").v, fmt == "dbf" ? "1" : 1);
|
||||
assert.equal(get_cell(ws0, "B2").v, 4);
|
||||
assert.equal(get_cell(ws0, "A3").v, 5);
|
||||
|
||||
var wb1 = X.read(bs, { type: ot, sheetRows: 1 });
|
||||
var ws1 = wb1.Sheets.Sheet1;
|
||||
var ws1 = wb1.Sheets["Sheet1"];
|
||||
assert.equal(ws1['!ref'], "A1:B1");
|
||||
assert.equal(get_cell(ws1, "A1").v, 1);
|
||||
assert.equal(get_cell(ws1, "A1").v, fmt == "dbf" ? "1" : 1);
|
||||
assert.ok(!get_cell(ws1, "B2"));
|
||||
assert.ok(!get_cell(ws1, "A3"));
|
||||
if(ws1['!fullref']) assert.equal(ws1['!fullref'], "A1:B3");
|
||||
|
||||
var wb2 = X.read(bs, { type: ot, sheetRows: 2 });
|
||||
var ws2 = wb2.Sheets.Sheet1;
|
||||
var ws2 = wb2.Sheets["Sheet1"];
|
||||
assert.equal(ws2['!ref'], "A1:B2");
|
||||
assert.equal(get_cell(ws2, "A1").v, 1);
|
||||
assert.equal(get_cell(ws2, "A1").v, fmt == "dbf" ? "1" : 1);
|
||||
assert.equal(get_cell(ws2, "B2").v, 4);
|
||||
assert.ok(!get_cell(ws2, "A3"));
|
||||
if(ws2['!fullref']) assert.equal(ws2['!fullref'], "A1:B3");
|
||||
|
||||
var wb3 = X.read(bs, { type: ot, sheetRows: 3 });
|
||||
var ws3 = wb3.Sheets.Sheet1;
|
||||
var ws3 = wb3.Sheets["Sheet1"];
|
||||
assert.equal(ws3['!ref'], "A1:B3");
|
||||
assert.equal(get_cell(ws3, "A1").v, 1);
|
||||
assert.equal(get_cell(ws3, "A1").v, fmt == "dbf" ? "1" : 1);
|
||||
assert.equal(get_cell(ws3, "B2").v, 4);
|
||||
assert.equal(get_cell(ws3, "A3").v, 5);
|
||||
if(ws3['!fullref']) assert.equal(ws3['!fullref'], "A1:B3");
|
||||
@ -685,13 +685,13 @@ describe('input formats', function() {
|
||||
it('should read base64 strings', function() { artifax.forEach(function(p) {
|
||||
X.read(fs.readFileSync(p, 'base64'), {type: 'base64'});
|
||||
}); });
|
||||
(typeof Uint8Array !== 'undefined' ? it : it.skip)('should read array', function() { artifax.forEach(function(p) {
|
||||
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'});
|
||||
}); });
|
||||
((browser || typeof Buffer === 'undefined') ? it.skip : it)('should read Buffers', function() { artifax.forEach(function(p) {
|
||||
X.read(fs.readFileSync(p), {type: 'buffer'});
|
||||
}); });
|
||||
(typeof Uint8Array !== 'undefined' ? it : it.skip)('should read ArrayBuffer / Uint8Array', function() { artifax.forEach(function(p) {
|
||||
if(typeof Uint8Array !== 'undefined') it('should read ArrayBuffer / Uint8Array', function() { artifax.forEach(function(p) {
|
||||
var payload = fs.readFileSync(p, browser ? 'buffer' : null);
|
||||
var ab = new ArrayBuffer(payload.length), vu = new Uint8Array(ab);
|
||||
for(var i = 0; i < payload.length; ++i) vu[i] = payload[i];
|
||||
@ -731,9 +731,9 @@ describe('output formats', function() {
|
||||
fmts.forEach(function(fmt) {
|
||||
var wb = X.utils.book_new();
|
||||
X.utils.book_append_sheet(wb, X.utils.aoa_to_sheet([['R',"\u2603"],["\u0BEE",2]]), "Sheet1");
|
||||
if(T == 'string' && !fmt[2]) return assert.throws(function() {X.write(wb, {type: T, bookType:fmt[0], WTF:1});});
|
||||
var out = X.write(wb, {type: T, bookType:fmt[0], WTF:1});
|
||||
var nwb = X.read(out, {type: T, PRN: fmt[0] == 'prn', WTF:1});
|
||||
if(T == 'string' && !fmt[2]) return assert.throws(function() {X.write(wb, {type: T, bookType:fmt[0], WTF:true});});
|
||||
var out = X.write(wb, {type: T, bookType:fmt[0], WTF:true});
|
||||
var nwb = X.read(out, {type: T, PRN: fmt[0] == 'prn', WTF:true});
|
||||
var nws = nwb.Sheets[nwb.SheetNames[0]];
|
||||
assert.equal(get_cell(nws, "B2").v, 2);
|
||||
assert.equal(get_cell(nws, "A1").v, "R");
|
||||
@ -930,7 +930,7 @@ describe('parse features', function() {
|
||||
].forEach(function(m) { it(m[0] + ' stress test', function() {
|
||||
var wb = X.read(fs.readFileSync(m[1]), {type:TYPE});
|
||||
check_comments(wb);
|
||||
var ws0 = wb.Sheets.Sheet2;
|
||||
var ws0 = wb.Sheets["Sheet2"];
|
||||
assert.equal(get_cell(ws0,"A1").c[0].a, 'Author');
|
||||
assert.equal(get_cell(ws0,"A1").c[0].t, 'Author:\nGod thinks this is good');
|
||||
assert.equal(get_cell(ws0,"C1").c[0].a, 'Author');
|
||||
@ -942,10 +942,10 @@ describe('parse features', function() {
|
||||
var wbs=[];
|
||||
var bef = (function() {
|
||||
wbs = [
|
||||
X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE, WTF:1}),
|
||||
X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE, WTF:1}),
|
||||
X.read(fs.readFileSync(paths.cpxls), {type:TYPE, WTF:1}),
|
||||
X.read(fs.readFileSync(paths.cpxml), {type:TYPE, WTF:1})
|
||||
X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE, WTF:true}),
|
||||
X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE, WTF:true}),
|
||||
X.read(fs.readFileSync(paths.cpxls), {type:TYPE, WTF:true}),
|
||||
X.read(fs.readFileSync(paths.cpxml), {type:TYPE, WTF:true})
|
||||
];
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
@ -984,7 +984,7 @@ describe('parse features', function() {
|
||||
it('should use original range if not set', function() {
|
||||
var opts = {type:TYPE};
|
||||
FSTPaths.map(function(p) { return X.read(fs.readFileSync(p), opts); }).forEach(function(wb) {
|
||||
assert.equal(wb.Sheets.Text["!ref"],"A1:F49");
|
||||
assert.equal(wb.Sheets["Text"]["!ref"],"A1:F49");
|
||||
});
|
||||
});
|
||||
it('should adjust range if set', function() {
|
||||
@ -992,8 +992,8 @@ describe('parse features', function() {
|
||||
var wbs = FSTPaths.map(function(p) { return X.read(fs.readFileSync(p), opts); });
|
||||
/* TODO: XLS, XML, ODS */
|
||||
wbs.slice(0,2).forEach(function(wb) {
|
||||
assert.equal(wb.Sheets.Text["!fullref"],"A1:F49");
|
||||
assert.equal(wb.Sheets.Text["!ref"],"A1:F10");
|
||||
assert.equal(wb.Sheets["Text"]["!fullref"],"A1:F49");
|
||||
assert.equal(wb.Sheets["Text"]["!ref"],"A1:F10");
|
||||
});
|
||||
});
|
||||
it('should not generate comment cells', function() {
|
||||
@ -1001,8 +1001,8 @@ describe('parse features', function() {
|
||||
var wbs = CSTPaths.map(function(p) { return X.read(fs.readFileSync(p), opts); });
|
||||
/* TODO: XLS, XML, ODS */
|
||||
wbs.slice(0,2).forEach(function(wb) {
|
||||
assert.equal(wb.Sheets.Sheet7["!fullref"],"A1:N34");
|
||||
assert.equal(wb.Sheets.Sheet7["!ref"],"A1");
|
||||
assert.equal(wb.Sheets["Sheet7"]["!fullref"],"A1:N34");
|
||||
assert.equal(wb.Sheets["Sheet7"]["!ref"],"A1");
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1016,16 +1016,16 @@ describe('parse features', function() {
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
it('should have "!cols"', function() {
|
||||
wbs.forEach(function(wb) { assert.ok(wb.Sheets.Sheet1['!cols']); });
|
||||
wbs.forEach(function(wb) { assert.ok(wb.Sheets["Sheet1"]['!cols']); });
|
||||
});
|
||||
it('should have correct widths', function() {
|
||||
/* SYLK rounds wch so skip non-integral */
|
||||
wbs_no_slk.map(function(x) { return x.Sheets.Sheet1['!cols']; }).forEach(function(x) {
|
||||
wbs_no_slk.map(function(x) { return x.Sheets["Sheet1"]['!cols']; }).forEach(function(x) {
|
||||
assert.equal(x[1].width, 0.1640625);
|
||||
assert.equal(x[2].width, 16.6640625);
|
||||
assert.equal(x[3].width, 1.6640625);
|
||||
});
|
||||
wbs.map(function(x) { return x.Sheets.Sheet1['!cols']; }).forEach(function(x) {
|
||||
wbs.map(function(x) { return x.Sheets["Sheet1"]['!cols']; }).forEach(function(x) {
|
||||
assert.equal(x[4].width, 4.83203125);
|
||||
assert.equal(x[5].width, 8.83203125);
|
||||
assert.equal(x[6].width, 12.83203125);
|
||||
@ -1034,12 +1034,12 @@ describe('parse features', function() {
|
||||
});
|
||||
it('should have correct pixels', function() {
|
||||
/* SYLK rounds wch so skip non-integral */
|
||||
wbs_no_slk.map(function(x) { return x.Sheets.Sheet1['!cols']; }).forEach(function(x) {
|
||||
wbs_no_slk.map(function(x) { return x.Sheets["Sheet1"]['!cols']; }).forEach(function(x) {
|
||||
assert.equal(x[1].wpx, 1);
|
||||
assert.equal(x[2].wpx, 100);
|
||||
assert.equal(x[3].wpx, 10);
|
||||
});
|
||||
wbs.map(function(x) { return x.Sheets.Sheet1['!cols']; }).forEach(function(x) {
|
||||
wbs.map(function(x) { return x.Sheets["Sheet1"]['!cols']; }).forEach(function(x) {
|
||||
assert.equal(x[4].wpx, 29);
|
||||
assert.equal(x[5].wpx, 53);
|
||||
assert.equal(x[6].wpx, 77);
|
||||
@ -1060,25 +1060,25 @@ describe('parse features', function() {
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
it('should have "!rows"', function() {
|
||||
wbs.forEach(function(wb) { assert.ok(wb.Sheets.Sheet1['!rows']); });
|
||||
wbs.forEach(function(wb) { assert.ok(wb.Sheets["Sheet1"]['!rows']); });
|
||||
});
|
||||
it('should have correct points', function() {
|
||||
wbs.map(function(x) { return x.Sheets.Sheet1['!rows']; }).forEach(function(x) {
|
||||
wbs.map(function(x) { return x.Sheets["Sheet1"]['!rows']; }).forEach(function(x) {
|
||||
assert.equal(x[1].hpt, 1);
|
||||
assert.equal(x[2].hpt, 10);
|
||||
assert.equal(x[3].hpt, 100);
|
||||
});
|
||||
});
|
||||
it('should have correct pixels', function() {
|
||||
wbs.map(function(x) { return x.Sheets.Sheet1['!rows']; }).forEach(function(x) {
|
||||
wbs.map(function(x) { return x.Sheets["Sheet1"]['!rows']; }).forEach(function(x) {
|
||||
/* note: at 96 PPI hpt == hpx */
|
||||
assert.equal(x[1].hpx, 1);
|
||||
assert.equal(x[2].hpx, 10);
|
||||
assert.equal(x[3].hpx, 100);
|
||||
});
|
||||
});
|
||||
(ol ? it : it.skip)('should have correct outline levels', function() {
|
||||
ols.map(function(x) { return x.Sheets.Sheet1; }).forEach(function(ws) {
|
||||
it('should have correct outline levels', function() {
|
||||
ols.map(function(x) { return x.Sheets["Sheet1"]; }).forEach(function(ws) {
|
||||
var rows = ws['!rows'];
|
||||
for(var i = 0; i < 29; ++i) {
|
||||
var cell = get_cell(ws, "A" + X.utils.encode_row(i));
|
||||
@ -1103,9 +1103,9 @@ describe('parse features', function() {
|
||||
else it('before', bef);
|
||||
it('should have !merges', function() {
|
||||
wbs.forEach(function(wb) {
|
||||
assert.ok(wb.Sheets.Merge['!merges']);
|
||||
assert.ok(wb.Sheets["Merge"]['!merges']);
|
||||
});
|
||||
var m = wbs.map(function(x) { return x.Sheets.Merge['!merges'].map(function(y) { return X.utils.encode_range(y); });});
|
||||
var m = wbs.map(function(x) { return x.Sheets["Merge"]['!merges'].map(function(y) { return X.utils.encode_range(y); });});
|
||||
m.slice(1).forEach(function(x) {
|
||||
assert.deepEqual(m[0].sort(),x.sort());
|
||||
});
|
||||
@ -1115,17 +1115,17 @@ describe('parse features', function() {
|
||||
describe('should find hyperlinks', function() {
|
||||
var wb1, wb2;
|
||||
var bef = (function() {
|
||||
wb1 = HLPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:1}); });
|
||||
wb2 = ILPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:1}); });
|
||||
wb1 = HLPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:true}); });
|
||||
wb2 = ILPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:true}); });
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
|
||||
['xlsx', 'xlsb', 'xls', 'xml'].forEach(function(x, i) {
|
||||
it(x + " external", function() { hlink1(wb1[i].Sheets.Sheet1); });
|
||||
it(x + " external", function() { hlink1(wb1[i].Sheets["Sheet1"]); });
|
||||
});
|
||||
['xlsx', 'xlsb', 'xls', 'xml', 'ods'].forEach(function(x, i) {
|
||||
it(x + " internal", function() { hlink2(wb2[i].Sheets.Sheet1); });
|
||||
it(x + " internal", function() { hlink2(wb2[i].Sheets["Sheet1"]); });
|
||||
});
|
||||
});
|
||||
|
||||
@ -1275,10 +1275,10 @@ describe('parse features', function() {
|
||||
else it('before', bef);
|
||||
['xlsx'].forEach(function(m) { it(m, function() {
|
||||
var wb2 = X.read(X.write(wb, {bookType:m, type:TYPE}),{type:TYPE, cellHTML:true});
|
||||
assert.equal(get_cell(wb2.Sheets.Sheet1, "A2").h, "&");
|
||||
assert.equal(get_cell(wb2.Sheets.Sheet1, "B2").h, "<");
|
||||
assert.equal(get_cell(wb2.Sheets.Sheet1, "C2").h, ">");
|
||||
var h = get_cell(wb2.Sheets.Sheet1, "D2").h;
|
||||
assert.equal(get_cell(wb2.Sheets["Sheet1"], "A2").h, "&");
|
||||
assert.equal(get_cell(wb2.Sheets["Sheet1"], "B2").h, "<");
|
||||
assert.equal(get_cell(wb2.Sheets["Sheet1"], "C2").h, ">");
|
||||
var h = get_cell(wb2.Sheets["Sheet1"], "D2").h;
|
||||
assert.ok(h == "
" || h == "<br/>");
|
||||
}); });
|
||||
});
|
||||
@ -1287,7 +1287,7 @@ describe('parse features', function() {
|
||||
var wbs=[];
|
||||
var bef = (function() {
|
||||
if(!fs.existsSync(paths.pmxls)) return;
|
||||
wbs = PMPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:1}); });
|
||||
wbs = PMPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, WTF:true}); });
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
@ -1306,8 +1306,8 @@ describe('parse features', function() {
|
||||
describe('should correctly handle styles', function() {
|
||||
var wsxls, wsxlsx, rn, rn2;
|
||||
var bef = (function() {
|
||||
wsxls=X.read(fs.readFileSync(paths.cssxls), {type:TYPE,cellStyles:true,WTF:1}).Sheets.Sheet1;
|
||||
wsxlsx=X.read(fs.readFileSync(paths.cssxlsx), {type:TYPE,cellStyles:true,WTF:1}).Sheets.Sheet1;
|
||||
wsxls=X.read(fs.readFileSync(paths.cssxls), {type:TYPE,cellStyles:true,WTF:true}).Sheets["Sheet1"];
|
||||
wsxlsx=X.read(fs.readFileSync(paths.cssxlsx), {type:TYPE,cellStyles:true,WTF:true}).Sheets["Sheet1"];
|
||||
rn = function(range) {
|
||||
var r = X.utils.decode_range(range);
|
||||
var out = [];
|
||||
@ -1395,12 +1395,36 @@ describe('parse features', function() {
|
||||
assert.equal(data[4][1], '456.00');
|
||||
assert.equal(data[5][1], '7,890');
|
||||
}); }); });
|
||||
|
||||
it('date system', function() {[
|
||||
"biff5", "ods", "slk", "xls", "xlsb", "xlsx", "xml"
|
||||
].forEach(function(ext) {
|
||||
// TODO: verify actual date values
|
||||
var wb0 = X.read(fs.readFileSync("./test_files/1904/1900." + ext), {type: TYPE, cellNF: true});
|
||||
assert.ok(!wb0.Workbook || !wb0.Workbook.WBProps || !wb0.Workbook.WBProps.date1904);
|
||||
assert.equal(X.utils.sheet_to_csv(wb0.Sheets[wb0.SheetNames[0]]), [
|
||||
"1,1900-01-01,1900-01-01,1900-01-01",
|
||||
"11,1900-01-11,1900-01-11,1900-01-11",
|
||||
"111,1900-04-20,1900-04-20,1900-04-20",
|
||||
"1111,1903-01-15,1903-01-15,1903-01-15",
|
||||
"11111,1930-06-02,1930-06-02,1930-06-02"
|
||||
].join("\n"));
|
||||
|
||||
var wb4 = X.read(fs.readFileSync("./test_files/1904/1904." + ext), {type: TYPE, cellNF: true});
|
||||
assert.ok(wb4.Workbook.WBProps.date1904);
|
||||
assert.equal(X.utils.sheet_to_csv(wb4.Sheets[wb4.SheetNames[0]]), [
|
||||
"1,1904-01-02,1904-01-02,1904-01-02",
|
||||
"11,1904-01-12,1904-01-12,1904-01-12",
|
||||
"111,1904-04-21,1904-04-21,1904-04-21",
|
||||
"1111,1907-01-16,1907-01-16,1907-01-16",
|
||||
"11111,1934-06-03,1934-06-03,1934-06-03"
|
||||
].join("\n"));
|
||||
}); });
|
||||
});
|
||||
|
||||
describe('write features', function() {
|
||||
describe('props', function() {
|
||||
describe('core', function() {
|
||||
var ws;
|
||||
var baseprops = {
|
||||
Category: "Newspaper",
|
||||
ContentStatus: "Published",
|
||||
@ -1416,6 +1440,7 @@ describe('write features', function() {
|
||||
Subject: "Superman",
|
||||
Title: "Man of Steel"
|
||||
};
|
||||
var ws;
|
||||
var bef = (function() {
|
||||
ws = X.utils.aoa_to_sheet([["a","b","c"],[1,2,3]]);
|
||||
});
|
||||
@ -1452,17 +1477,17 @@ describe('write features', function() {
|
||||
["xlsb", "XFD1048576"]
|
||||
].forEach(function(r) { it(r[0], function() {
|
||||
var C = X.utils.decode_cell(r[1]);
|
||||
var wopts = {bookType:r[0], type:'binary', WTF:1};
|
||||
var wopts = {bookType:r[0], type:'binary', WTF:true};
|
||||
var wb = { SheetNames: ["Sheet1"], Sheets: { Sheet1: {} } };
|
||||
|
||||
wb.Sheets.Sheet1['!ref'] = "A1:" + X.utils.encode_cell({r:0, c:C.c});
|
||||
wb.Sheets["Sheet1"]['!ref'] = "A1:" + X.utils.encode_cell({r:0, c:C.c});
|
||||
X.write(wb, wopts);
|
||||
wb.Sheets.Sheet1['!ref'] = "A" + X.utils.encode_row(C.r - 5) + ":" + X.utils.encode_cell({r:C.r, c:0});
|
||||
wb.Sheets["Sheet1"]['!ref'] = "A" + X.utils.encode_row(C.r - 5) + ":" + X.utils.encode_cell({r:C.r, c:0});
|
||||
X.write(wb, wopts);
|
||||
|
||||
wb.Sheets.Sheet1['!ref'] = "A1:" + X.utils.encode_cell({r:0, c:C.c+1});
|
||||
wb.Sheets["Sheet1"]['!ref'] = "A1:" + X.utils.encode_cell({r:0, c:C.c+1});
|
||||
assert.throws(function() { X.write(wb, wopts); });
|
||||
wb.Sheets.Sheet1['!ref'] = "A" + X.utils.encode_row(C.r - 5) + ":" + X.utils.encode_cell({r:C.r+1, c:0});
|
||||
wb.Sheets["Sheet1"]['!ref'] = "A" + X.utils.encode_row(C.r - 5) + ":" + X.utils.encode_cell({r:C.r+1, c:0});
|
||||
assert.throws(function() { X.write(wb, wopts); });
|
||||
}); }); });
|
||||
it('single worksheet formats', function() {
|
||||
@ -1485,8 +1510,8 @@ describe('write features', function() {
|
||||
((wb2.Workbook||{}).Names || []).forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == 0) Name = dn; });
|
||||
assert.ok(!!Name, "Could not find _xlnm._FilterDatabases name WR");
|
||||
assert.equal(Name.Ref, "Sheet1!$A$1:$C$2");
|
||||
X.utils.sheet_add_aoa(wb2.Sheets.Sheet1, [[4,5,6]], { origin: -1 });
|
||||
wb2.Sheets.Sheet1["!autofilter"].ref = wb2.Sheets.Sheet1["!ref"];
|
||||
X.utils.sheet_add_aoa(wb2.Sheets["Sheet1"], [[4,5,6]], { origin: -1 });
|
||||
wb2.Sheets["Sheet1"]["!autofilter"].ref = wb2.Sheets["Sheet1"]["!ref"];
|
||||
var wb3 = X.read(X.write(wb2, {bookType:fmt, type:TYPE}), {type:TYPE});
|
||||
Name = void 0;
|
||||
((wb3.Workbook||{}).Names || []).forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == 0) Name = dn; });
|
||||
@ -1562,8 +1587,8 @@ describe('roundtrip features', function() {
|
||||
["xlsx", "xlsb", "xlml", "ods", "biff8", "numbers"].forEach(function(f) { it(f, function() {
|
||||
var wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE});
|
||||
var wb2 = X.read(X.write(wb1,{bookType:f,type:'binary',numbers:XLSX_ZAHL}),{type:'binary'});
|
||||
var m1 = wb1.Sheets.Merge['!merges'].map(X.utils.encode_range);
|
||||
var m2 = wb2.Sheets.Merge['!merges'].map(X.utils.encode_range);
|
||||
var m1 = wb1.Sheets["Merge"]['!merges'].map(X.utils.encode_range);
|
||||
var m2 = wb2.Sheets["Merge"]['!merges'].map(X.utils.encode_range);
|
||||
assert.equal(m1.length, m2.length);
|
||||
for(var i = 0; i < m1.length; ++i) assert.ok(m1.indexOf(m2[i]) > -1);
|
||||
}); });
|
||||
@ -1595,13 +1620,13 @@ describe('roundtrip features', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('should preserve formulae', function() { [
|
||||
describe('should preserve formulae', function() { var ff = [
|
||||
['xlml', paths.fstxml],
|
||||
['xlsx', paths.fstxlsx],
|
||||
['ods', paths.fstods]
|
||||
].forEach(function(w) { it(w[0], function() {
|
||||
var wb1 = X.read(fs.readFileSync(w[1]), {type:TYPE, cellFormula:true, WTF:1});
|
||||
var wb2 = X.read(X.write(wb1, {bookType:w[0], type:TYPE}), {cellFormula:true, type:TYPE, WTF:1});
|
||||
]; ff.forEach(function(w) { it(w[0], function() {
|
||||
var wb1 = X.read(fs.readFileSync(w[1]), {type:TYPE, cellFormula:true, WTF:true});
|
||||
var wb2 = X.read(X.write(wb1, {bookType:w[0], type:TYPE}), {cellFormula:true, type:TYPE, WTF:true});
|
||||
wb1.SheetNames.forEach(function(n) {
|
||||
assert.equal(
|
||||
X.utils.sheet_to_formulae(wb1.Sheets[n]).sort().join("\n"),
|
||||
@ -1613,17 +1638,17 @@ describe('roundtrip features', function() {
|
||||
describe('should preserve dynamic array formulae', function() { [
|
||||
['xlsx', paths.m19xlsx]
|
||||
].forEach(function(w) { it(w[0], function() {
|
||||
var wb1 = X.read(fs.readFileSync(w[1]), {xlfn: true, type:TYPE, cellFormula:true, WTF:1});
|
||||
var wb2 = X.read(X.write(wb1, {bookType:w[0], type:TYPE}), {cellFormula:true, xlfn: true, type:TYPE, WTF:1});
|
||||
assert.equal(!!get_cell(wb2.Sheets.Sheet1, "B3").D, true);
|
||||
assert.equal(!!get_cell(wb2.Sheets.Sheet1, "B13").D, true);
|
||||
assert.equal(!!get_cell(wb2.Sheets.Sheet1, "C13").D, true);
|
||||
var wb1 = X.read(fs.readFileSync(w[1]), {xlfn: true, type:TYPE, cellFormula:true, WTF:true});
|
||||
var wb2 = X.read(X.write(wb1, {bookType:w[0], type:TYPE}), {cellFormula:true, xlfn: true, type:TYPE, WTF:true});
|
||||
assert.equal(!!get_cell(wb2.Sheets["Sheet1"], "B3").D, true);
|
||||
assert.equal(!!get_cell(wb2.Sheets["Sheet1"], "B13").D, true);
|
||||
assert.equal(!!get_cell(wb2.Sheets["Sheet1"], "C13").D, true);
|
||||
|
||||
get_cell(wb2.Sheets.Sheet1, "B3").D = false;
|
||||
var wb3 = X.read(X.write(wb2, {bookType:w[0], type:TYPE}), {cellFormula:true, xlfn: true, type:TYPE, WTF:1});
|
||||
assert.equal(!!get_cell(wb3.Sheets.Sheet1, "B3").D, false);
|
||||
assert.equal(!!get_cell(wb3.Sheets.Sheet1, "B13").D, true);
|
||||
assert.equal(!!get_cell(wb3.Sheets.Sheet1, "C13").D, true);
|
||||
get_cell(wb2.Sheets["Sheet1"], "B3").D = false;
|
||||
var wb3 = X.read(X.write(wb2, {bookType:w[0], type:TYPE}), {cellFormula:true, xlfn: true, type:TYPE, WTF:true});
|
||||
assert.equal(!!get_cell(wb3.Sheets["Sheet1"], "B3").D, false);
|
||||
assert.equal(!!get_cell(wb3.Sheets["Sheet1"], "B13").D, true);
|
||||
assert.equal(!!get_cell(wb3.Sheets["Sheet1"], "C13").D, true);
|
||||
}); }); });
|
||||
|
||||
describe('should preserve hyperlink', function() { [
|
||||
@ -1638,12 +1663,12 @@ describe('roundtrip features', function() {
|
||||
['ods', paths.ilods, false]
|
||||
].forEach(function(w) { it(w[0]+" "+(w[2]?"ex":"in")+ "ternal", function() {
|
||||
var wb = X.read(fs.readFileSync(w[1]), {type:TYPE, WTF:opts.WTF});
|
||||
var hlink = (w[2] ? hlink1 : hlink2); hlink(wb.Sheets.Sheet1);
|
||||
var hlink = (w[2] ? hlink1 : hlink2); hlink(wb.Sheets["Sheet1"]);
|
||||
wb = X.read(X.write(wb, {bookType:w[0], type:TYPE, WTF:opts.WTF}), {type:TYPE, WTF:opts.WTF});
|
||||
hlink(wb.Sheets.Sheet1);
|
||||
hlink(wb.Sheets["Sheet1"]);
|
||||
}); }); });
|
||||
|
||||
(fs.existsSync(paths.pmxlsx) ? describe : describe.skip)('should preserve page margins', function() {[
|
||||
describe('should preserve page margins', function() {[
|
||||
['xlml', paths.pmxml],
|
||||
['xlsx', paths.pmxlsx],
|
||||
['xlsb', paths.pmxlsb]
|
||||
@ -1691,7 +1716,7 @@ describe('roundtrip features', function() {
|
||||
ws1['!cols'] = [{wch:9},{wpx:100},{width:80},{hidden:true}];
|
||||
var wb1 = {SheetNames:["Sheet1"], Sheets:{Sheet1:ws1}};
|
||||
var wb2 = X.read(X.write(wb1, {bookType:w, type:TYPE}), {type:TYPE, cellStyles:true});
|
||||
var ws2 = wb2.Sheets.Sheet1;
|
||||
var ws2 = wb2.Sheets["Sheet1"];
|
||||
assert.equal(ws2['!cols'][3].hidden, true);
|
||||
assert.equal(ws2['!cols'][0].wch, 9);
|
||||
if(w == 'slk') return;
|
||||
@ -1711,7 +1736,7 @@ describe('roundtrip features', function() {
|
||||
for(var i = 0; i <= 7; ++i) ws1['!rows'].push({level:i});
|
||||
var wb1 = {SheetNames:["Sheet1"], Sheets:{Sheet1:ws1}};
|
||||
var wb2 = X.read(X.write(wb1, {bookType:w, type:TYPE, cellStyles:true}), {type:TYPE, cellStyles:true});
|
||||
var ws2 = wb2.Sheets.Sheet1;
|
||||
var ws2 = wb2.Sheets["Sheet1"];
|
||||
assert.equal(ws2['!rows'][0].hpx, 12);
|
||||
assert.equal(ws2['!rows'][1].hpt, 24);
|
||||
assert.equal(ws2['!rows'][2].hpx, 48);
|
||||
@ -1767,6 +1792,7 @@ describe('roundtrip features', function() {
|
||||
assert.equal(wb2.Sheets[wb2.SheetNames[i]]['!autofilter'].ref,"A1:E22");
|
||||
}
|
||||
}); });
|
||||
|
||||
});
|
||||
|
||||
//function password_file(x){return x.match(/^password.*\.xls$/); }
|
||||
@ -2002,7 +2028,7 @@ describe('json output', function() {
|
||||
seq(8).forEach(function(n) {
|
||||
var opts = {};
|
||||
if(n & 1) opts.header = 1;
|
||||
if(n & 2) opts.raw = 1;
|
||||
if(n & 2) opts.raw = true;
|
||||
if(n & 4) opts.defval = null;
|
||||
var J = X.utils.sheet_to_json(ws, opts);
|
||||
for(var i = 0; i < 3; ++i) {
|
||||
@ -2015,7 +2041,7 @@ describe('json output', function() {
|
||||
|
||||
|
||||
var codes = [["あ 1", "\u00E3\u0081\u0082 1"]];
|
||||
var plaintext_val = [
|
||||
var plaintext_val = ([
|
||||
["A1", 'n', -0.08, "-0.08"],
|
||||
["B1", 'n', 4001, "4,001"],
|
||||
["C1", 's', "あ 1", "あ 1"],
|
||||
@ -2025,12 +2051,12 @@ var plaintext_val = [
|
||||
["D3", 'b', false, "FALSE"],
|
||||
["B3", 's', " ", " "],
|
||||
["A3"]
|
||||
];
|
||||
]);
|
||||
function plaintext_test(wb, raw) {
|
||||
var sheet = wb.Sheets[wb.SheetNames[0]];
|
||||
plaintext_val.forEach(function(x) {
|
||||
var cell = get_cell(sheet, x[0]);
|
||||
var tcval = x[2+!!raw];
|
||||
var tcval = x[2+(!!raw ? 1 : 0)];
|
||||
var type = raw ? 's' : x[1];
|
||||
if(x.length == 1) { if(cell) { assert.equal(cell.t, 'z'); assert.ok(!cell.v); } return; }
|
||||
assert.equal(cell.v, tcval); assert.equal(cell.t, type);
|
||||
@ -2055,14 +2081,14 @@ describe('CSV', function() {
|
||||
var b = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\n,,,\nbaz,,qux,\n";
|
||||
it('should generate date numbers by default', function() {
|
||||
var opts = {type:"binary"};
|
||||
var cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3");
|
||||
var cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.w, '2/19/14');
|
||||
assert.equal(cell.t, 'n');
|
||||
assert.ok(typeof cell.v == "number");
|
||||
});
|
||||
it('should generate dates when requested', function() {
|
||||
var opts = {type:"binary", cellDates:true};
|
||||
var cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3");
|
||||
var cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.w, '2/19/14');
|
||||
assert.equal(cell.t, 'd');
|
||||
assert.ok(cell.v instanceof Date || typeof cell.v == "string");
|
||||
@ -2070,29 +2096,29 @@ describe('CSV', function() {
|
||||
|
||||
it('should use US date code 14 by default', function() {
|
||||
var opts = ({type:"binary"}/*:any*/);
|
||||
var cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3");
|
||||
var cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.w, '2/19/14');
|
||||
opts.cellDates = true;
|
||||
cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3");
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.w, '2/19/14');
|
||||
});
|
||||
it('should honor dateNF override', function() {
|
||||
var opts = ({type:"binary", dateNF:"YYYY-MM-DD"}/*:any*/);
|
||||
var cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3");
|
||||
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');
|
||||
opts.cellDates = true; opts.dateNF = "YY-MM-DD";
|
||||
cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3");
|
||||
cell = get_cell(X.read(b, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.w, '14-02-19');
|
||||
});
|
||||
it('should interpret dateNF', function() {
|
||||
var bb = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/3/14,0.3\n,,,\nbaz,,qux,\n";
|
||||
var opts = {type:"binary", cellDates:true, dateNF:'m/d/yy'};
|
||||
var cell = get_cell(X.read(bb, opts).Sheets.Sheet1, "C3");
|
||||
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'};
|
||||
cell = get_cell(X.read(bb, opts).Sheets.Sheet1, "C3");
|
||||
cell = get_cell(X.read(bb, opts).Sheets["Sheet1"], "C3");
|
||||
assert.equal(cell.v.getMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
});
|
||||
@ -2100,7 +2126,7 @@ describe('CSV', function() {
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(csv_str, {type:"string", raw:true}), true); });
|
||||
it('should handle formulae', function() {
|
||||
var bb = '=,=1+1,="100"';
|
||||
var sheet = X.read(bb, {type:"binary"}).Sheets.Sheet1;
|
||||
var sheet = X.read(bb, {type:"binary"}).Sheets["Sheet1"];
|
||||
assert.equal(get_cell(sheet, "A1").t, 's');
|
||||
assert.equal(get_cell(sheet, "A1").v, '=');
|
||||
assert.equal(get_cell(sheet, "B1").f, '1+1');
|
||||
@ -2109,12 +2135,12 @@ describe('CSV', function() {
|
||||
});
|
||||
it('should interpret CRLF newlines', function() {
|
||||
var wb = X.read("sep=&\r\n1&2&3\r\n4&5&6", {type: "string"});
|
||||
assert.equal(wb.Sheets.Sheet1["!ref"], "A1:C2");
|
||||
assert.equal(wb.Sheets["Sheet1"]["!ref"], "A1:C2");
|
||||
});
|
||||
if(!browser || typeof cptable !== 'undefined') it('should honor codepage for binary strings', function() {
|
||||
var data = "abc,def\nghi,j\xD3l";
|
||||
[[1251, 'У'],[1252, 'Ó'], [1253, 'Σ'], [1254, 'Ó'], [1255, '׃'], [1256, 'س'], [10000, '”']].forEach(function(m) {
|
||||
var ws = X.read(data, {type:"binary", codepage:m[0]}).Sheets.Sheet1;
|
||||
var ws = X.read(data, {type:"binary", codepage:m[0]}).Sheets["Sheet1"];
|
||||
assert.equal(get_cell(ws, "B2").v, "j" + m[1] + "l");
|
||||
});
|
||||
});
|
||||
@ -2164,9 +2190,9 @@ describe('CSV', function() {
|
||||
var data = ["1,a", "2,b", "3,c"];
|
||||
[ "\r", "\n", "\r\n" ].forEach(function(RS) {
|
||||
var wb = X.read(data.join(RS), {type:'binary'});
|
||||
assert.equal(get_cell(wb.Sheets.Sheet1, "A1").v, 1);
|
||||
assert.equal(get_cell(wb.Sheets.Sheet1, "B3").v, "c");
|
||||
assert.equal(wb.Sheets.Sheet1['!ref'], "A1:B3");
|
||||
assert.equal(get_cell(wb.Sheets["Sheet1"], "A1").v, 1);
|
||||
assert.equal(get_cell(wb.Sheets["Sheet1"], "B3").v, "c");
|
||||
assert.equal(wb.Sheets["Sheet1"]['!ref'], "A1:B3");
|
||||
});
|
||||
});
|
||||
it('should handle skipHidden for rows if requested', function() {
|
||||
@ -2210,32 +2236,33 @@ describe('sylk', function() {
|
||||
describe('input', function(){
|
||||
it('codepage', cpavail ? function() {
|
||||
var str = "ID;PWXL;N;E\r\nC;X1;Y1;K\"a – b\"\r\nE", A1 = "a – b";
|
||||
assert.equal(get_cell(X.read(str, {type:"string"}).Sheets.Sheet1, "A1").v, A1);
|
||||
assert.equal(get_cell(X.read(str.replace(/–/, "\x96"), {type:"binary", codepage:1252}).Sheets.Sheet1, "A1").v, A1);
|
||||
assert.equal(get_cell(X.read(str, {type:"string"}).Sheets["Sheet1"], "A1").v, A1);
|
||||
assert.equal(get_cell(X.read(str.replace(/–/, "\x96"), {type:"binary", codepage:1252}).Sheets["Sheet1"], "A1").v, A1);
|
||||
if(typeof Buffer !== 'undefined' && !browser) {
|
||||
assert.equal(get_cell(X.read(Buffer_from(str), {type:"buffer", codepage:65001}).Sheets.Sheet1, "A1").v, A1);
|
||||
assert.equal(get_cell(X.read(Buffer_from(str.replace(/–/, "\x96"), "binary"), {type:"buffer", codepage:1252}).Sheets.Sheet1, "A1").v, A1);
|
||||
assert.equal(get_cell(X.read(Buffer_from(str), {type:"buffer", codepage:65001}).Sheets["Sheet1"], "A1").v, A1);
|
||||
assert.equal(get_cell(X.read(Buffer_from(str.replace(/–/, "\x96"), "binary"), {type:"buffer", codepage:1252}).Sheets["Sheet1"], "A1").v, A1);
|
||||
}
|
||||
} : null);
|
||||
});
|
||||
describe('date system', function() {
|
||||
function make_slk(d1904) { return "ID;PSheetJS\nP;Pd\\/m\\/yy\nP;Pd\\/m\\/yyyy\n" + (d1904 != null ? "O;D;V" + d1904 : "") + "\nF;P0;FG0G;X1;Y1\nC;K1\nE"; }
|
||||
it('should default to 1900', function() {
|
||||
assert.equal(get_cell(X.read(make_slk(), {type: "binary"}).Sheets.Sheet1, "A1").v, 1);
|
||||
assert.ok(get_cell(X.read(make_slk(), {type: "binary", cellDates: true}).Sheets.Sheet1, "A1").v.getFullYear() < 1902);
|
||||
assert.equal(get_cell(X.read(make_slk(5), {type: "binary"}).Sheets.Sheet1, "A1").v, 1);
|
||||
assert.ok(get_cell(X.read(make_slk(5), {type: "binary", cellDates: true}).Sheets.Sheet1, "A1").v.getFullYear() < 1902);
|
||||
assert.equal(get_cell(X.read(make_slk(), {type: "binary"}).Sheets["Sheet1"], "A1").v, 1);
|
||||
assert.ok(get_cell(X.read(make_slk(), {type: "binary", cellDates: true}).Sheets["Sheet1"], "A1").v.getFullYear() < 1902);
|
||||
assert.equal(get_cell(X.read(make_slk(5), {type: "binary"}).Sheets["Sheet1"], "A1").v, 1);
|
||||
assert.ok(get_cell(X.read(make_slk(5), {type: "binary", cellDates: true}).Sheets["Sheet1"], "A1").v.getFullYear() < 1902);
|
||||
});
|
||||
it('should use 1904 when specified', function() {
|
||||
assert.ok(get_cell(X.read(make_slk(1), {type: "binary", cellDates: true}).Sheets.Sheet1, "A1").v.getFullYear() > 1902);
|
||||
assert.ok(get_cell(X.read(make_slk(4), {type: "binary", cellDates: true}).Sheets.Sheet1, "A1").v.getFullYear() > 1902);
|
||||
assert.ok(get_cell(X.read(make_slk(1), {type: "binary", cellDates: true}).Sheets["Sheet1"], "A1").v.getFullYear() > 1902);
|
||||
assert.ok(get_cell(X.read(make_slk(4), {type: "binary", cellDates: true}).Sheets["Sheet1"], "A1").v.getFullYear() > 1902);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
(typeof Uint8Array !== "undefined" ? describe : describe.skip)('numbers', function() {
|
||||
if(typeof Uint8Array !== "undefined")
|
||||
describe('numbers', function() {
|
||||
it('should parse files from Numbers 6.x', function() {
|
||||
var wb = X.read(fs.readFileSync(dir + 'numbers/types_61.numbers'), {type:TYPE, WTF:1});
|
||||
var wb = X.read(fs.readFileSync(dir + 'numbers/types_61.numbers'), {type:TYPE, WTF:true});
|
||||
var ws = wb.Sheets["Sheet 1"];
|
||||
assert.equal(get_cell(ws, "A1").v, "Sheet");
|
||||
assert.equal(get_cell(ws, "B1").v, "JS");
|
||||
@ -2248,14 +2275,14 @@ describe('sylk', function() {
|
||||
var ws1 = X.utils.aoa_to_sheet(aoa);
|
||||
var wb1 = X.utils.book_new(); X.utils.book_append_sheet(wb1, ws1, "Sheet1");
|
||||
var wb2 = X.read(X.write(wb1,{bookType:"numbers",type:'binary',numbers:XLSX_ZAHL}),{type:'binary'});
|
||||
var ws2 = wb2.Sheets.Sheet1;
|
||||
var ws2 = wb2.Sheets["Sheet1"];
|
||||
assert.equal(ws2["!ref"], "A1:ALL3");
|
||||
assert.equal(get_cell(ws2, "A1").v, 1);
|
||||
assert.equal(get_cell(ws2, "ALL2").v, 2);
|
||||
});
|
||||
});
|
||||
|
||||
if(fs.existsSync(dir + 'dbf/d11.dbf')) describe('dbf', function() {
|
||||
describe('dbf', function() {
|
||||
var wbs/*:Array<any>*/ = ([
|
||||
['d11', dir + 'dbf/d11.dbf'],
|
||||
['vfp3', dir + 'dbf/vfp3.dbf']
|
||||
@ -2266,7 +2293,7 @@ if(fs.existsSync(dir + 'dbf/d11.dbf')) describe('dbf', function() {
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
it(wbs[1][0], function() {
|
||||
var ws = wbs[1][1].Sheets.Sheet1;
|
||||
var ws = wbs[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"],
|
||||
@ -2306,7 +2333,7 @@ describe('HTML', function() {
|
||||
it('should handle newlines correctly', function() {
|
||||
var table = "<table><tr><td>foo<br/>bar</td><td>baz</td></tr></table>";
|
||||
var wb = X.read(table, {type:"string"});
|
||||
assert.equal(get_cell(wb.Sheets.Sheet1, "A1").v, "foo\nbar");
|
||||
assert.equal(get_cell(wb.Sheets["Sheet1"], "A1").v, "foo\nbar");
|
||||
});
|
||||
it('should generate multi-sheet workbooks', function() {
|
||||
var table = "";
|
||||
@ -2321,7 +2348,7 @@ describe('HTML', function() {
|
||||
}
|
||||
});
|
||||
});
|
||||
(domtest ? describe : describe.skip)('input DOM', function() {
|
||||
if(domtest) describe('input DOM', function() {
|
||||
it('should interpret values by default', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str)), false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str), {raw:true}), true); });
|
||||
it('should handle newlines correctly', function() {
|
||||
@ -2388,15 +2415,15 @@ describe('HTML', function() {
|
||||
}
|
||||
var html = "<table><tr><td t=\"s\">1234567890</td><td>1234567890</td></tr></table>";
|
||||
it('HTML string', function() {
|
||||
var ws = X.read(html, {type:'string'}).Sheets.Sheet1; chk(ws);
|
||||
chk(X.read(X.utils.sheet_to_html(ws), {type:'string'}).Sheets.Sheet1);
|
||||
var ws = X.read(html, {type:'string'}).Sheets["Sheet1"]; chk(ws);
|
||||
chk(X.read(X.utils.sheet_to_html(ws), {type:'string'}).Sheets["Sheet1"]);
|
||||
});
|
||||
if(domtest) it('DOM', function() { chk(X.utils.table_to_sheet(get_dom_element(html))); });
|
||||
});
|
||||
describe('TH/THEAD/TBODY/TFOOT elements', function() {
|
||||
var html = "<table><thead><tr><th>A</th><th>B</th></tr></thead><tbody><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></tbody><tfoot><tr><th>4</th><th>6</th></tr></tfoot></table>";
|
||||
it('HTML string', function() {
|
||||
var ws = X.read(html, {type:'string'}).Sheets.Sheet1;
|
||||
var ws = X.read(html, {type:'string'}).Sheets["Sheet1"];
|
||||
assert.equal(X.utils.sheet_to_csv(ws), "A,B\n1,2\n3,4\n4,6");
|
||||
});
|
||||
if(domtest) it('DOM', function() {
|
||||
@ -2408,13 +2435,13 @@ describe('HTML', function() {
|
||||
var html = "<table><tr><td>abc</td><td><b> </b></td><td>def</td></tr></table>";
|
||||
var expectedCellCount = 3;
|
||||
it('HTML string', function() {
|
||||
var ws = X.read(html, {type:'string'}).Sheets.Sheet1;
|
||||
var range = X.utils.decode_range(ws['!ref']);
|
||||
var ws = X.read(html, {type:'string'}).Sheets["Sheet1"];
|
||||
var range = X.utils.decode_range(ws['!ref']||"A1");
|
||||
assert.equal(range.e.c,expectedCellCount - 1);
|
||||
});
|
||||
if(domtest) it('DOM', function() {
|
||||
var ws = X.utils.table_to_sheet(get_dom_element(html));
|
||||
var range = X.utils.decode_range(ws['!ref']);
|
||||
var range = X.utils.decode_range(ws['!ref']||"A1");
|
||||
assert.equal(range.e.c, expectedCellCount - 1);
|
||||
});
|
||||
});
|
||||
@ -2529,22 +2556,22 @@ describe('corner cases', function() {
|
||||
});
|
||||
});
|
||||
if(fs.existsSync(dir + 'wtf_path.xlsx')) it('OPC oddities', function() {
|
||||
X.read(fs.readFileSync(dir + 'wtf_path.xlsx'), {WTF:1, type:TYPE});
|
||||
X.read(fs.readFileSync(dir + 'wtf_path.xlsb'), {WTF:1, type:TYPE});
|
||||
X.read(fs.readFileSync(dir + 'wtf_path.xlsx'), {WTF:true, type:TYPE});
|
||||
X.read(fs.readFileSync(dir + 'wtf_path.xlsb'), {WTF:true, type:TYPE});
|
||||
});
|
||||
it("should quote unicode sheet names in formulae", function() {
|
||||
var wb = X.read(fs.readFileSync(dir + "cross-sheet_formula_names.xlsb"), {WTF:1, type:TYPE});
|
||||
assert.equal(wb.Sheets.Sheet1.A1.f, "'a-b'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A2.f, "'a#b'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A3.f, "'a^b'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A4.f, "'a%b'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A5.f, "'a\u066ab'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A6.f, "'☃️'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A7.f, "'\ud83c\udf63'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A8.f, "'a!!b'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A9.f, "'a$b'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A10.f, "'a!b'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A11.f, "'a b'!A1");
|
||||
var wb = X.read(fs.readFileSync(dir + "cross-sheet_formula_names.xlsb"), {WTF:true, type:TYPE});
|
||||
assert.equal(wb.Sheets["Sheet1"].A1.f, "'a-b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A2.f, "'a#b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A3.f, "'a^b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A4.f, "'a%b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A5.f, "'a\u066ab'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A6.f, "'☃️'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A7.f, "'\ud83c\udf63'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A8.f, "'a!!b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A9.f, "'a$b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A10.f, "'a!b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A11.f, "'a b'!A1");
|
||||
});
|
||||
it.skip('should parse CSV date values with preceding space', function() {
|
||||
function check_ws(ws, dNF) {
|
||||
@ -2559,12 +2586,12 @@ describe('corner cases', function() {
|
||||
var ws1 = X.read(
|
||||
'7,2018-03-24',
|
||||
{cellDates: cD, dateNF: dNF, type:'string'}
|
||||
).Sheets.Sheet1;
|
||||
).Sheets["Sheet1"];
|
||||
check_ws(ws1, dNF);
|
||||
var ws2 = X.read(
|
||||
'7, 2018-03-24',
|
||||
{cellDates: cD, dateNF: dNF, type:'string'}
|
||||
).Sheets.Sheet1;
|
||||
).Sheets["Sheet1"];
|
||||
check_ws(ws2, dNF);
|
||||
});
|
||||
});
|
||||
@ -2702,7 +2729,7 @@ describe('encryption', function() {
|
||||
if(e.message == "Password is incorrect") throw e;
|
||||
}
|
||||
});
|
||||
it.skip('should decrypt file', function() {
|
||||
if(false) it('should decrypt file', function() {
|
||||
/*var wb = */X.read(fs.readFileSync(dir + x), {type:TYPE,password:'password',WTF:opts.WTF});
|
||||
});
|
||||
});
|
||||
@ -2737,19 +2764,18 @@ mft.forEach(function(x) {
|
||||
cmparr(ss.map(function(s) { return (s['!merges']||[]).map(function(y) { return X.utils.encode_range(y); }).sort(); }));
|
||||
});
|
||||
});
|
||||
it('should have the same CSV', csv ? function() {
|
||||
if(csv) it('should have the same CSV', function() {
|
||||
cmparr(f.map(function(x) { return x.SheetNames; }));
|
||||
f[0].SheetNames.forEach(function(name) {
|
||||
cmparr(f.map(function(x) { return X.utils.sheet_to_csv(x.Sheets[name]); }));
|
||||
});
|
||||
} : null);
|
||||
it('should have the same formulae', formulae ? function() {
|
||||
});
|
||||
if(formulae) it('should have the same formulae', function() {
|
||||
cmparr(f.map(function(x) { return x.SheetNames; }));
|
||||
f[0].SheetNames.forEach(function(name) {
|
||||
cmparr(f.map(function(x) { return X.utils.sheet_to_formulae(x.Sheets[name]).sort(); }));
|
||||
});
|
||||
} : null);
|
||||
|
||||
});
|
||||
});
|
||||
else x.split(/\s+/).forEach(function(w) { switch(w) {
|
||||
case "no-csv": csv = false; break;
|
||||
|
288
test.ts
288
test.ts
@ -28,22 +28,22 @@ var DIF_XL = true;
|
||||
type BSEncoding = 'utf-8' | 'binary' | 'base64';
|
||||
type BFEncoding = 'buffer';
|
||||
type ShEncoding = BSEncoding | BFEncoding;
|
||||
|
||||
function readFileSync2(x: string): Uint8Array;
|
||||
function readFileSync2(x: string, e: BSEncoding): string;
|
||||
function readFileSync2(x: string, e: BFEncoding): Uint8Array;
|
||||
function readFileSync2(x: string, e: ShEncoding): Uint8Array | string {
|
||||
const u8 = Deno.readFileSync(x);
|
||||
switch(e) {
|
||||
case 'utf-8': return new TextDecoder().decode(u8);
|
||||
case 'base64': return base64_.encode(u8);
|
||||
case 'buffer': return u8;
|
||||
case 'binary': return Array.from({length: u8.length}, (_,i) => String.fromCharCode(u8[i])).join("");
|
||||
}
|
||||
throw new Error(`unsupported encoding ${e}`)
|
||||
function readFileSync2(x: string, e?: ShEncoding): Uint8Array | string {
|
||||
const u8 = Deno.readFileSync(x);
|
||||
if(!e) return u8;
|
||||
switch(e) {
|
||||
case 'utf-8': return new TextDecoder().decode(u8);
|
||||
case 'base64': return base64_.encode(u8);
|
||||
case 'buffer': return u8;
|
||||
case 'binary': return Array.from({length: u8.length}, (_,i) => String.fromCharCode(u8[i])).join("");
|
||||
}
|
||||
throw new Error(`unsupported encoding ${e}`)
|
||||
}
|
||||
var fs = {
|
||||
readFileSync: (x: string) => Deno.readFileSync(x),
|
||||
readFileSync2,
|
||||
readFileSync: readFileSync2,
|
||||
existsSync: (x: string): boolean => { try { Deno.readFileSync(x); } catch(e) { return false; } return true; },
|
||||
readdirSync: (x: string) => ([...Deno.readDirSync(x)].filter(x => x.isFile).map(x => x.name))
|
||||
};
|
||||
@ -72,9 +72,9 @@ function test_file(x: string){ return ex.indexOf(x.slice(-5))>=0||exp.indexOf(x.
|
||||
|
||||
var files: string[] = [], fileA: string[] = [];
|
||||
if(!browser) {
|
||||
var _files = fs.existsSync('tests.lst') ? fs.readFileSync2('tests.lst', 'utf-8').split("\n").map(function(x) { return x.trim(); }) : fs.readdirSync('test_files');
|
||||
var _files = fs.existsSync('tests.lst') ? fs.readFileSync('tests.lst', 'utf-8').split("\n").map(function(x) { return x.trim(); }) : fs.readdirSync('test_files');
|
||||
for(var _filesi = 0; _filesi < _files.length; ++_filesi) if(test_file(_files[_filesi])) files.push(_files[_filesi]);
|
||||
var _fileA = fs.existsSync('tests/testA.lst') ? fs.readFileSync2('tests/testA.lst', 'utf-8').split("\n").map(function(x) { return x.trim(); }) : [];
|
||||
var _fileA = fs.existsSync('tests/testA.lst') ? fs.readFileSync('tests/testA.lst', 'utf-8').split("\n").map(function(x) { return x.trim(); }) : [];
|
||||
for(var _fileAi = 0; _fileAi < _fileA.length; ++_fileAi) if(test_file(_fileA[_fileAi])) fileA.push(_fileA[_fileAi]);
|
||||
}
|
||||
|
||||
@ -269,7 +269,7 @@ async function parsetest(x: string, wb: X.WorkBook, full: boolean, ext: string,
|
||||
wb.SheetNames.forEach(function(y) { assert.assert(wb.Sheets[y], 'bad sheet ' + y); });
|
||||
});
|
||||
if(fs.existsSync(sname)) await t.step('should have the right sheet names', async function(t) {
|
||||
var file = fs.readFileSync2(sname, 'utf-8').replace(/\r/g,"");
|
||||
var file = fs.readFileSync(sname, 'utf-8').replace(/\r/g,"");
|
||||
var names = wb.SheetNames.map(fixsheetname).join("\n") + "\n";
|
||||
if(file.length && !x.match(/artifacts/)) assert.equal(names, file);
|
||||
});
|
||||
@ -317,7 +317,7 @@ async function parsetest(x: string, wb: X.WorkBook, full: boolean, ext: string,
|
||||
for(var i = 0; i < wb.SheetNames.length; ++i) { var ws = wb.SheetNames[i];
|
||||
var name = getfile(dir, x, i, ".csv");
|
||||
if(fs.existsSync(name)) await t.step('#' + i + ' (' + ws + ')', async function(t) {
|
||||
var file = fs.readFileSync2(name, 'utf-8');
|
||||
var file = fs.readFileSync(name, 'utf-8');
|
||||
var csv = X.utils.sheet_to_csv(wb.Sheets[ws]);
|
||||
assert.equal(fixcsv(csv), fixcsv(file), "CSV badness");
|
||||
});
|
||||
@ -327,14 +327,14 @@ async function parsetest(x: string, wb: X.WorkBook, full: boolean, ext: string,
|
||||
for(var i = 0; i < wb.SheetNames.length; ++i) { var ws = wb.SheetNames[i];
|
||||
var rawjson = getfile(dir, x, i, ".rawjson");
|
||||
if(fs.existsSync(rawjson)) await t.step('#' + i + ' (' + ws + ')', async function(t) {
|
||||
var file = fs.readFileSync2(rawjson, 'utf-8');
|
||||
var file = fs.readFileSync(rawjson, 'utf-8');
|
||||
var json: Array<any> = X.utils.sheet_to_json(wb.Sheets[ws],{raw:true});
|
||||
assert.equal(JSON.stringify(json), fixjson(file), "JSON badness");
|
||||
});
|
||||
|
||||
var jsonf = getfile(dir, x, i, ".json");
|
||||
if(fs.existsSync(jsonf)) await t.step('#' + i + ' (' + ws + ')', async function(t) {
|
||||
var file = fs.readFileSync2(jsonf, 'utf-8');
|
||||
var file = fs.readFileSync(jsonf, 'utf-8');
|
||||
var json: Array<any> = X.utils.sheet_to_json(wb.Sheets[ws], {raw:false});
|
||||
assert.equal(JSON.stringify(json), fixjson(file), "JSON badness");
|
||||
});
|
||||
@ -400,13 +400,13 @@ function each_sheet(wb: X.WorkBook, f: (ws: X.WorkSheet, i: number)=>any) { wb.S
|
||||
|
||||
/* comments_stress_test family */
|
||||
function check_comments(wb: X.WorkBook) {
|
||||
var ws0 = wb.Sheets.Sheet2;
|
||||
var ws0 = wb.Sheets["Sheet2"];
|
||||
assert.equal(get_cell(ws0,"A1").c[0].a, 'Author');
|
||||
assert.equal(get_cell(ws0,"A1").c[0].t, 'Author:\nGod thinks this is good');
|
||||
assert.equal(get_cell(ws0,"C1").c[0].a, 'Author');
|
||||
assert.equal(get_cell(ws0,"C1").c[0].t, 'I really hope that xlsx decides not to use magic like rPr');
|
||||
|
||||
var ws3 = wb.Sheets.Sheet4;
|
||||
var ws3 = wb.Sheets["Sheet4"];
|
||||
assert.equal(get_cell(ws3,"B1").c[0].a, 'Author');
|
||||
assert.equal(get_cell(ws3,"B1").c[0].t, 'The next comment is empty');
|
||||
assert.equal(get_cell(ws3,"B2").c[0].a, 'Author');
|
||||
@ -556,27 +556,27 @@ Deno.test('parse options', async function(t) {
|
||||
await t.step('should not generate sheet stubs by default', async function(t) {
|
||||
MCPaths.forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE});
|
||||
assert.throws(function() { return get_cell(wb.Sheets.Merge, "A2").v; });
|
||||
assert.throws(function() { return get_cell(wb.Sheets["Merge"], "A2").v; });
|
||||
});
|
||||
});
|
||||
await t.step('should generate sheet stubs when requested', async function(t) {
|
||||
MCPaths.forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE, sheetStubs:true});
|
||||
assert.assert(get_cell(wb.Sheets.Merge, "A2").t == 'z');
|
||||
assert.assert(get_cell(wb.Sheets["Merge"], "A2").t == 'z');
|
||||
});
|
||||
});
|
||||
await t.step('should handle stub cells', async function(t) {
|
||||
MCPaths.forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE, sheetStubs:true});
|
||||
X.utils.sheet_to_csv(wb.Sheets.Merge);
|
||||
X.utils.sheet_to_json(wb.Sheets.Merge);
|
||||
X.utils.sheet_to_formulae(wb.Sheets.Merge);
|
||||
X.utils.sheet_to_csv(wb.Sheets["Merge"]);
|
||||
X.utils.sheet_to_json(wb.Sheets["Merge"]);
|
||||
X.utils.sheet_to_formulae(wb.Sheets["Merge"]);
|
||||
ofmt.forEach(function(f) { if(f != "dbf") X.write(wb, {type:TYPE, bookType:f}); });
|
||||
});
|
||||
});
|
||||
function checkcells(wb: X.WorkBook, A46: boolean, B26: boolean, C16: boolean, D2: boolean) {
|
||||
([ ["A46", A46], ["B26", B26], ["C16", C16], ["D2", D2] ] as Array<[string, boolean]>).forEach(function(r: [string, boolean]) {
|
||||
assert.assert((typeof get_cell(wb.Sheets.Text, r[0]) !== 'undefined') == r[1]);
|
||||
assert.assert((typeof get_cell(wb.Sheets["Text"], r[0]) !== 'undefined') == r[1]);
|
||||
});
|
||||
}
|
||||
await t.step('should read all cells by default', async function(t) { FSTPaths.forEach(function(p) {
|
||||
@ -697,19 +697,19 @@ Deno.test('parse options', async function(t) {
|
||||
|
||||
Deno.test('input formats', async function(t) {
|
||||
await t.step('should read binary strings', async function(t) { artifax.forEach(function(p) {
|
||||
X.read(fs.readFileSync2(p, 'binary'), {type: 'binary'});
|
||||
X.read(fs.readFileSync(p, 'binary'), {type: 'binary'});
|
||||
}); });
|
||||
await t.step('should read base64 strings', async function(t) { artifax.forEach(function(p) {
|
||||
X.read(fs.readFileSync2(p, 'base64'), {type: 'base64'});
|
||||
X.read(fs.readFileSync(p, 'base64'), {type: 'base64'});
|
||||
}); });
|
||||
await t.step('should read array', async function(t) { artifax.forEach(function(p) {
|
||||
X.read(fs.readFileSync2(p, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
|
||||
if(typeof Uint8Array !== 'undefined') await t.step('should read array', async function(t) { artifax.forEach(function(p) {
|
||||
X.read(fs.readFileSync(p, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
|
||||
}); });
|
||||
await t.step('should read Buffers', async function(t) { artifax.forEach(function(p) {
|
||||
X.read(fs.readFileSync(p), {type: 'buffer'});
|
||||
}); });
|
||||
await t.step('should read ArrayBuffer / Uint8Array', async function(t) { artifax.forEach(function(p) {
|
||||
var payload: any = fs.readFileSync2(p, "buffer");
|
||||
if(typeof Uint8Array !== 'undefined') await t.step('should read ArrayBuffer / Uint8Array', async function(t) { artifax.forEach(function(p) {
|
||||
var payload: any = fs.readFileSync(p, "buffer");
|
||||
var ab = new ArrayBuffer(payload.length), vu = new Uint8Array(ab);
|
||||
for(var i = 0; i < payload.length; ++i) vu[i] = payload[i];
|
||||
X.read(ab, {type: 'array'});
|
||||
@ -894,7 +894,7 @@ function check_margin(margins: X.MarginInfo, exp: number[]) {
|
||||
|
||||
Deno.test('parse features', async function(t) {
|
||||
await t.step('sheet visibility', async function(t) {
|
||||
var wbs = SVPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE}); });
|
||||
var wbs = SVPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE}); });
|
||||
await t.step('should detect visible sheets', async function(t) {
|
||||
wbs.forEach(function(wb) {
|
||||
assert.assert(!wb?.Workbook?.Sheets?.[0]?.Hidden);
|
||||
@ -940,7 +940,7 @@ Deno.test('parse features', async function(t) {
|
||||
]; for(var ststi = 0; ststi < stst.length; ++ststi) { let m = stst[ststi]; await t.step(m[0] + ' stress test', async function(t) {
|
||||
var wb = X.read(fs.readFileSync(m[1]), {type:TYPE});
|
||||
check_comments(wb);
|
||||
var ws0 = wb.Sheets.Sheet2;
|
||||
var ws0 = wb.Sheets["Sheet2"];
|
||||
assert.equal(get_cell(ws0,"A1").c[0].a, 'Author');
|
||||
assert.equal(get_cell(ws0,"A1").c[0].t, 'Author:\nGod thinks this is good');
|
||||
assert.equal(get_cell(ws0,"C1").c[0].a, 'Author');
|
||||
@ -989,7 +989,7 @@ Deno.test('parse features', async function(t) {
|
||||
await t.step('should use original range if not set', async function(t) {
|
||||
var opts = {type:TYPE};
|
||||
FSTPaths.map(function(p) { return X.read(fs.readFileSync(p), opts); }).forEach(function(wb) {
|
||||
assert.equal(wb.Sheets.Text["!ref"],"A1:F49");
|
||||
assert.equal(wb.Sheets["Text"]["!ref"],"A1:F49");
|
||||
});
|
||||
});
|
||||
await t.step('should adjust range if set', async function(t) {
|
||||
@ -997,8 +997,8 @@ Deno.test('parse features', async function(t) {
|
||||
var wbs = FSTPaths.map(function(p) { return X.read(fs.readFileSync(p), opts); });
|
||||
/* TODO: XLS, XML, ODS */
|
||||
wbs.slice(0,2).forEach(function(wb) {
|
||||
assert.equal(wb.Sheets.Text["!fullref"],"A1:F49");
|
||||
assert.equal(wb.Sheets.Text["!ref"],"A1:F10");
|
||||
assert.equal(wb.Sheets["Text"]["!fullref"],"A1:F49");
|
||||
assert.equal(wb.Sheets["Text"]["!ref"],"A1:F10");
|
||||
});
|
||||
});
|
||||
await t.step('should not generate comment cells', async function(t) {
|
||||
@ -1006,8 +1006,8 @@ Deno.test('parse features', async function(t) {
|
||||
var wbs = CSTPaths.map(function(p) { return X.read(fs.readFileSync(p), opts); });
|
||||
/* TODO: XLS, XML, ODS */
|
||||
wbs.slice(0,2).forEach(function(wb) {
|
||||
assert.equal(wb.Sheets.Sheet7["!fullref"],"A1:N34");
|
||||
assert.equal(wb.Sheets.Sheet7["!ref"],"A1");
|
||||
assert.equal(wb.Sheets["Sheet7"]["!fullref"],"A1:N34");
|
||||
assert.equal(wb.Sheets["Sheet7"]["!ref"],"A1");
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1092,9 +1092,9 @@ Deno.test('parse features', async function(t) {
|
||||
var wbs = MCPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE}); });
|
||||
await t.step('should have !merges', async function(t) {
|
||||
wbs.forEach(function(wb) {
|
||||
assert.assert(wb.Sheets.Merge['!merges']);
|
||||
assert.assert(wb.Sheets["Merge"]['!merges']);
|
||||
});
|
||||
var m = wbs.map(function(x) { return x.Sheets.Merge?.['!merges']?.map(function(y) { return X.utils.encode_range(y); });});
|
||||
var m = wbs.map(function(x) { return x.Sheets["Merge"]?.['!merges']?.map(function(y) { return X.utils.encode_range(y); });});
|
||||
m?.slice(1)?.forEach(function(x) {
|
||||
assert.deepEqual(m?.[0]?.sort(),x?.sort());
|
||||
});
|
||||
@ -1360,6 +1360,31 @@ Deno.test('parse features', async function(t) {
|
||||
assert.equal(data[4][1], '456.00');
|
||||
assert.equal(data[5][1], '7,890');
|
||||
}); } });
|
||||
|
||||
await t.step('date system', async function(t) {[
|
||||
"biff5", "ods", "slk", "xls", "xlsb", "xlsx", "xml"
|
||||
].forEach(function(ext) {
|
||||
// TODO: verify actual date values
|
||||
var wb0 = X.read(fs.readFileSync("./test_files/1904/1900." + ext), {type: TYPE, cellNF: true});
|
||||
assert.assert(!(wb0?.Workbook?.WBProps?.date1904));
|
||||
assert.equal(X.utils.sheet_to_csv(wb0.Sheets[wb0.SheetNames[0]]), [
|
||||
"1,1900-01-01,1900-01-01,1900-01-01",
|
||||
"11,1900-01-11,1900-01-11,1900-01-11",
|
||||
"111,1900-04-20,1900-04-20,1900-04-20",
|
||||
"1111,1903-01-15,1903-01-15,1903-01-15",
|
||||
"11111,1930-06-02,1930-06-02,1930-06-02"
|
||||
].join("\n"));
|
||||
|
||||
var wb4 = X.read(fs.readFileSync("./test_files/1904/1904." + ext), {type: TYPE, cellNF: true});
|
||||
assert.assert(wb4?.Workbook?.WBProps?.date1904);
|
||||
assert.equal(X.utils.sheet_to_csv(wb4.Sheets[wb4.SheetNames[0]]), [
|
||||
"1,1904-01-02,1904-01-02,1904-01-02",
|
||||
"11,1904-01-12,1904-01-12,1904-01-12",
|
||||
"111,1904-04-21,1904-04-21,1904-04-21",
|
||||
"1111,1907-01-16,1907-01-16,1907-01-16",
|
||||
"11111,1934-06-03,1934-06-03,1934-06-03"
|
||||
].join("\n"));
|
||||
}); });
|
||||
});
|
||||
|
||||
Deno.test('write features', async function(t) {
|
||||
@ -1433,7 +1458,7 @@ Deno.test('write features', async function(t) {
|
||||
assert.equal(X.write(wb, {type:"string", bookType:"csv", sheet:"Sheet2"}), "5,6\n7,8");
|
||||
assert.throws(function() { X.write(wb, {type:"string", bookType:"csv", sheet:"Sheet3"}); });
|
||||
});
|
||||
await t.step('should create/update autofilter defined name on write', async function() {([
|
||||
await t.step('should create/update autofilter defined name on write', async function(t) {([
|
||||
"xlsx", "xlsb", /* "xls", */ "xlml" /*, "ods" */
|
||||
] as Array<X.BookType>).forEach(function(fmt) {
|
||||
var wb = X.utils.book_new();
|
||||
@ -1445,8 +1470,8 @@ Deno.test('write features', async function(t) {
|
||||
((wb2.Workbook||{}).Names || []).forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == 0) Name = dn; });
|
||||
assert.assert(!!Name, "Could not find _xlnm._FilterDatabases name WR");
|
||||
assert.equal(Name.Ref, "Sheet1!$A$1:$C$2");
|
||||
X.utils.sheet_add_aoa(wb2.Sheets.Sheet1, [[4,5,6]], { origin: -1 });
|
||||
(wb2.Sheets.Sheet1["!autofilter"] as any).ref = wb2.Sheets.Sheet1["!ref"];
|
||||
X.utils.sheet_add_aoa(wb2.Sheets["Sheet1"], [[4,5,6]], { origin: -1 });
|
||||
(wb2.Sheets["Sheet1"]["!autofilter"] as any).ref = wb2.Sheets["Sheet1"]["!ref"];
|
||||
var wb3 = X.read(X.write(wb2, {bookType:fmt, type:TYPE}), {type:TYPE});
|
||||
Name = (null as any);
|
||||
((wb3.Workbook||{}).Names || []).forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == 0) Name = dn; });
|
||||
@ -1522,8 +1547,8 @@ Deno.test('roundtrip features', async function(t) {
|
||||
var mcf = ["xlsx", "xlsb", "xlml", "ods", "biff8", "numbers"] as Array<X.BookType>; for(let mci = 0; mci < mcf.length; ++mci) { let f = mcf[mci]; await t.step(f, async function(t) {
|
||||
var wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE});
|
||||
var wb2 = X.read(X.write(wb1,{bookType:f,type:'binary',numbers:XLSX_ZAHL}),{type:'binary'});
|
||||
var m1 = wb1.Sheets.Merge?.['!merges']?.map(X.utils.encode_range);
|
||||
var m2 = wb2.Sheets.Merge?.['!merges']?.map(X.utils.encode_range);
|
||||
var m1 = wb1.Sheets["Merge"]?.['!merges']?.map(X.utils.encode_range);
|
||||
var m2 = wb2.Sheets["Merge"]?.['!merges']?.map(X.utils.encode_range);
|
||||
assert.equal(m1?.length, m2?.length);
|
||||
if(m1 && m2) for(var i = 0; i < m1?.length; ++i) assert.assert(m1?.indexOf(m2?.[i]) > -1);
|
||||
}); }
|
||||
@ -1572,18 +1597,18 @@ Deno.test('roundtrip features', async function(t) {
|
||||
|
||||
await t.step('should preserve dynamic array formulae', async function(t) { var m19 = [
|
||||
['xlsx', paths.m19xlsx]
|
||||
]; for(var h1 = 0; h1 < m19.length; ++h1) { var w = m19[h1]; await t.step(w[0], async function (t) {
|
||||
]; for(var h1 = 0; h1 < m19.length; ++h1) { var w = m19[h1]; await t.step(w[0], async function(t) {
|
||||
var wb1 = X.read(fs.readFileSync(w[1]), {xlfn: true, type:TYPE, cellFormula:true, WTF:true});
|
||||
var wb2 = X.read(X.write(wb1, {bookType:w[0], type:TYPE}), {cellFormula:true, xlfn: true, type:TYPE, WTF:true});
|
||||
assert.equal(!!get_cell(wb2.Sheets.Sheet1, "B3").D, true);
|
||||
assert.equal(!!get_cell(wb2.Sheets.Sheet1, "B13").D, true);
|
||||
assert.equal(!!get_cell(wb2.Sheets.Sheet1, "C13").D, true);
|
||||
assert.equal(!!get_cell(wb2.Sheets["Sheet1"], "B3").D, true);
|
||||
assert.equal(!!get_cell(wb2.Sheets["Sheet1"], "B13").D, true);
|
||||
assert.equal(!!get_cell(wb2.Sheets["Sheet1"], "C13").D, true);
|
||||
|
||||
get_cell(wb2.Sheets.Sheet1, "B3").D = false;
|
||||
get_cell(wb2.Sheets["Sheet1"], "B3").D = false;
|
||||
var wb3 = X.read(X.write(wb2, {bookType:w[0], type:TYPE}), {cellFormula:true, xlfn: true, type:TYPE, WTF:true});
|
||||
assert.equal(!!get_cell(wb3.Sheets.Sheet1, "B3").D, false);
|
||||
assert.equal(!!get_cell(wb3.Sheets.Sheet1, "B13").D, true);
|
||||
assert.equal(!!get_cell(wb3.Sheets.Sheet1, "C13").D, true);
|
||||
assert.equal(!!get_cell(wb3.Sheets["Sheet1"], "B3").D, false);
|
||||
assert.equal(!!get_cell(wb3.Sheets["Sheet1"], "B13").D, true);
|
||||
assert.equal(!!get_cell(wb3.Sheets["Sheet1"], "C13").D, true);
|
||||
}); } });
|
||||
|
||||
await t.step('should preserve hyperlink', async function(t) { var hl = [
|
||||
@ -1684,7 +1709,7 @@ Deno.test('roundtrip features', async function(t) {
|
||||
await t.step('should preserve cell comments', async function(t) { var cc = [
|
||||
['xlsx', paths.cstxlsx],
|
||||
['xlsb', paths.cstxlsb],
|
||||
//['xls', paths.cstxlsx],
|
||||
//['xls', paths.cstxls],
|
||||
['xlml', paths.cstxml]
|
||||
//['ods', paths.cstods]
|
||||
]; for(var cci = 0; cci < cc.length; ++cci) { let w = cc[cci];
|
||||
@ -1711,7 +1736,7 @@ Deno.test('roundtrip features', async function(t) {
|
||||
});
|
||||
});
|
||||
|
||||
await t.step('should preserve autofilter settings', async function() {[
|
||||
await t.step('should preserve autofilter settings', async function(t) {[
|
||||
['xlsx', paths.afxlsx],
|
||||
['xlsb', paths.afxlsb],
|
||||
// TODO:
|
||||
@ -1727,6 +1752,7 @@ Deno.test('roundtrip features', async function(t) {
|
||||
assert.equal((wb2.Sheets[wb2.SheetNames[i]]['!autofilter'] as any).ref,"A1:E22");
|
||||
}
|
||||
}); });
|
||||
|
||||
});
|
||||
|
||||
//function password_file(x){return x.match(/^password.*\.xls$/); }
|
||||
@ -1742,8 +1768,8 @@ Deno.test('invalid files', async function(t) {
|
||||
['passwords', 'apachepoi_xor-encryption-abc.xls'],
|
||||
['DOC files', 'word_doc.doc']
|
||||
]; for(var f1 = 0; f1 < fl.length; ++f1) { let w = fl[f1]; await t.step('should fail on ' + w[0], async function(t) {
|
||||
assert.throws(function() { X.read(fs.readFileSync2(dir + w[1], 'binary'), {type:'binary'}); });
|
||||
assert.throws(function() { X.read(fs.readFileSync2(dir + w[1], 'base64'), {type:'base64'}); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(dir + w[1], 'binary'), {type:'binary'}); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(dir + w[1], 'base64'), {type:'base64'}); });
|
||||
}); } });
|
||||
await t.step('write', async function(t) {
|
||||
await t.step('should pass -> XLSX', async function(t) { FSTPaths.forEach(function(p) {
|
||||
@ -2159,12 +2185,12 @@ Deno.test('sylk', async function(t) {
|
||||
assert.equal(get_cell(X.read(str, {type:"string"}).Sheets["Sheet1"], "A1").v, A1);
|
||||
assert.equal(get_cell(X.read(str.replace(/–/, "\x96"), {type:"binary", codepage:1252}).Sheets["Sheet1"], "A1").v, A1);
|
||||
if(true) {
|
||||
assert.equal(get_cell(X.read(Buffer_from(str), {type:"buffer", codepage:65001}).Sheets.Sheet1, "A1").v, A1);
|
||||
assert.equal(get_cell(X.read(Buffer_from(str.replace(/–/, "\x96"), "binary"), {type:"buffer", codepage:1252}).Sheets.Sheet1, "A1").v, A1);
|
||||
assert.equal(get_cell(X.read(Buffer_from(str), {type:"buffer", codepage:65001}).Sheets["Sheet1"], "A1").v, A1);
|
||||
assert.equal(get_cell(X.read(Buffer_from(str.replace(/–/, "\x96"), "binary"), {type:"buffer", codepage:1252}).Sheets["Sheet1"], "A1").v, A1);
|
||||
}
|
||||
});
|
||||
});
|
||||
await t.step('date system', async function(t){
|
||||
await t.step('date system', async function(t) {
|
||||
function make_slk(d1904?: number) { return "ID;PSheetJS\nP;Pd\\/m\\/yy\nP;Pd\\/m\\/yyyy\n" + (d1904 != null ? "O;D;V" + d1904 : "") + "\nF;P0;FG0G;X1;Y1\nC;K1\nE"; }
|
||||
await t.step('should default to 1900', async function(t) {
|
||||
assert.equal(get_cell(X.read(make_slk(), {type: "binary"}).Sheets["Sheet1"], "A1").v, 1);
|
||||
@ -2179,6 +2205,7 @@ Deno.test('sylk', async function(t) {
|
||||
});
|
||||
});
|
||||
|
||||
if(typeof Uint8Array !== "undefined")
|
||||
Deno.test('numbers', async function(t) {
|
||||
await t.step('should parse files from Numbers 6.x', async function(t) {
|
||||
var wb = X.read(fs.readFileSync(dir + 'numbers/types_61.numbers'), {type:TYPE, WTF:true});
|
||||
@ -2194,20 +2221,20 @@ Deno.test('numbers', async function(t) {
|
||||
var ws1 = X.utils.aoa_to_sheet(aoa);
|
||||
var wb1 = X.utils.book_new(); X.utils.book_append_sheet(wb1, ws1, "Sheet1");
|
||||
var wb2 = X.read(X.write(wb1,{bookType:"numbers",type:'binary',numbers:XLSX_ZAHL}),{type:'binary'});
|
||||
var ws2 = wb2.Sheets.Sheet1;
|
||||
var ws2 = wb2.Sheets["Sheet1"];
|
||||
assert.equal(ws2["!ref"], "A1:ALL3");
|
||||
assert.equal(get_cell(ws2, "A1").v, 1);
|
||||
assert.equal(get_cell(ws2, "ALL2").v, 2);
|
||||
});
|
||||
});
|
||||
|
||||
if(fs.existsSync(dir + 'dbf/d11.dbf')) Deno.test('dbf', async function(t) {
|
||||
Deno.test('dbf', async function(t) {
|
||||
var wbs: Array<[string, X.WorkBook]> = ([
|
||||
['d11', dir + 'dbf/d11.dbf'],
|
||||
['vfp3', dir + 'dbf/vfp3.dbf']
|
||||
]).map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), {type:TYPE})]; });
|
||||
await t.step(wbs[1][0], async function(t) {
|
||||
var ws = wbs[1][1].Sheets.Sheet1;
|
||||
var ws = wbs[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"],
|
||||
@ -2216,6 +2243,21 @@ if(fs.existsSync(dir + 'dbf/d11.dbf')) Deno.test('dbf', async function(t) {
|
||||
] as Array<[string, string, any]>).forEach(function(r) { assert.equal(get_cell(ws, r[0])[r[1]], r[2]); });
|
||||
});
|
||||
});
|
||||
import { JSDOM } from 'jsdom';
|
||||
var domtest = false; // error: Error: Not implemented: isContext
|
||||
var inserted_dom_elements = [];
|
||||
|
||||
function get_dom_element(html: string) {
|
||||
if(browser) {
|
||||
var domelt = document.createElement('div');
|
||||
domelt.innerHTML = html;
|
||||
if(document.body) document.body.appendChild(domelt);
|
||||
inserted_dom_elements.push(domelt);
|
||||
return domelt.children[0];
|
||||
}
|
||||
if(!JSDOM) throw new Error("Browser test fail");
|
||||
return new JSDOM(html).window.document.body.children[0];
|
||||
}
|
||||
|
||||
Deno.test('HTML', async function(t) {
|
||||
await t.step('input string', async function(t) {
|
||||
@ -2225,7 +2267,7 @@ Deno.test('HTML', async function(t) {
|
||||
await t.step('should handle newlines correctly', async function(t) {
|
||||
var table = "<table><tr><td>foo<br/>bar</td><td>baz</td></tr></table>";
|
||||
var wb = X.read(table, {type:"string"});
|
||||
assert.equal(get_cell(wb.Sheets.Sheet1, "A1").v, "foo\nbar");
|
||||
assert.equal(get_cell(wb.Sheets["Sheet1"], "A1").v, "foo\nbar");
|
||||
});
|
||||
await t.step('should generate multi-sheet workbooks', async function(t) {
|
||||
var table = "";
|
||||
@ -2240,6 +2282,64 @@ Deno.test('HTML', async function(t) {
|
||||
}
|
||||
});
|
||||
});
|
||||
if(domtest) await t.step('input DOM', async function(t) {
|
||||
await t.step('should interpret values by default', async function(t) { plaintext_test(X.utils.table_to_book(get_dom_element(html_str)), false); });
|
||||
await t.step('should generate strings if raw option is passed', async function(t) { plaintext_test(X.utils.table_to_book(get_dom_element(html_str), {raw:true}), true); });
|
||||
await t.step('should handle newlines correctly', async function(t) {
|
||||
var table = get_dom_element("<table><tr><td>foo<br/>bar</td><td>baz</td></tr></table>");
|
||||
var ws = X.utils.table_to_sheet(table);
|
||||
assert.equal(get_cell(ws, "A1").v, "foo\nbar");
|
||||
});
|
||||
await t.step('should trim whitespace', async function(t) {
|
||||
if(get_dom_element("foo <br> bar").innerHTML != "foo <br> bar") return;
|
||||
var table = get_dom_element("<table><tr><td> foo <br/> bar </td><td> baz qux </td></tr></table>");
|
||||
var ws = X.utils.table_to_sheet(table);
|
||||
assert.equal(get_cell(ws, "A1").v.replace(/\n/g, "|"), "foo | bar");
|
||||
assert.equal(get_cell(ws, "B1").v, "baz qux");
|
||||
});
|
||||
});
|
||||
if(domtest) await t.step('should handle entities', async function(t) {
|
||||
var html = "<table><tr><td>A&B</td><td>A·B</td></tr></table>";
|
||||
var ws = X.utils.table_to_sheet(get_dom_element(html));
|
||||
assert.equal(get_cell(ws, "A1").v, "A&B");
|
||||
assert.equal(get_cell(ws, "B1").v, "A·B");
|
||||
});
|
||||
if(domtest) await t.step('should honor sheetRows', async function(t) {
|
||||
var html = X.utils.sheet_to_html(X.utils.aoa_to_sheet([[1,2],[3,4],[5,6]]));
|
||||
// $FlowIgnore
|
||||
html = /<body[^>]*>([\s\S]*)<\/body>/i.exec(html)?.[1] || "";
|
||||
var ws = X.utils.table_to_sheet(get_dom_element(html));
|
||||
assert.equal(ws['!ref'], "A1:B3");
|
||||
ws = X.utils.table_to_sheet(get_dom_element(html), {sheetRows:1});
|
||||
assert.equal(ws['!ref'], "A1:B1");
|
||||
assert.equal(ws['!fullref'], "A1:B3");
|
||||
ws = X.utils.table_to_sheet(get_dom_element(html), {sheetRows:2});
|
||||
assert.equal(ws['!ref'], "A1:B2");
|
||||
assert.equal(ws['!fullref'], "A1:B3");
|
||||
});
|
||||
if(domtest) await t.step('should hide hidden rows', async function(t) {
|
||||
var html = "<table><tr style='display: none;'><td>Foo</td></tr><tr><td style='display: none;'>Bar</td></tr><tr class='hidden'><td>Baz</td></tr></table><style>.hidden {display: none}</style>";
|
||||
var ws = X.utils.table_to_sheet(get_dom_element(html));
|
||||
var expected_rows = [];
|
||||
expected_rows[0] = expected_rows[2] = {hidden: true};
|
||||
assert.equal(ws['!ref'], "A1:A3");
|
||||
try {
|
||||
assert.deepEqual(ws['!rows'], expected_rows);
|
||||
} catch(e) {
|
||||
expected_rows[1] = {};
|
||||
assert.deepEqual(ws['!rows'], expected_rows);
|
||||
}
|
||||
assert.equal(get_cell(ws, "A1").v, "Foo");
|
||||
assert.equal(get_cell(ws, "A2").v, "Bar");
|
||||
assert.equal(get_cell(ws, "A3").v, "Baz");
|
||||
});
|
||||
if(domtest) await t.step('should ignore hidden rows and cells when the `display` option is on', async function(t) {
|
||||
var html = "<table><tr style='display: none;'><td>1</td><td>2</td><td>3</td></tr><tr><td class='hidden'>Foo</td><td>Bar</td><td style='display: none;'>Baz</td></tr></table><style>.hidden {display: none}</style>";
|
||||
var ws = X.utils.table_to_sheet(get_dom_element(html), {display: true});
|
||||
assert.equal(ws['!ref'], "A1");
|
||||
assert.assert(ws.hasOwnProperty('!rows') == false || !ws["!rows"]?.[0] || !ws["!rows"]?.[0]?.hidden);
|
||||
assert.equal(get_cell(ws, "A1").v, "Bar");
|
||||
});
|
||||
await t.step('type override', async function(t) {
|
||||
function chk(ws: X.WorkSheet) {
|
||||
assert.equal(get_cell(ws, "A1").t, "s");
|
||||
@ -2249,25 +2349,35 @@ Deno.test('HTML', async function(t) {
|
||||
}
|
||||
var html = "<table><tr><td t=\"s\">1234567890</td><td>1234567890</td></tr></table>";
|
||||
await t.step('HTML string', async function(t) {
|
||||
var ws = X.read(html, {type:'string'}).Sheets.Sheet1; chk(ws);
|
||||
chk(X.read(X.utils.sheet_to_html(ws), {type:'string'}).Sheets.Sheet1);
|
||||
var ws = X.read(html, {type:'string'}).Sheets["Sheet1"]; chk(ws);
|
||||
chk(X.read(X.utils.sheet_to_html(ws), {type:'string'}).Sheets["Sheet1"]);
|
||||
});
|
||||
if(domtest) await t.step('DOM', async function(t) { chk(X.utils.table_to_sheet(get_dom_element(html))); });
|
||||
});
|
||||
await t.step('TH/THEAD/TBODY/TFOOT elements', async function(t) {
|
||||
var html = "<table><thead><tr><th>A</th><th>B</th></tr></thead><tbody><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></tbody><tfoot><tr><th>4</th><th>6</th></tr></tfoot></table>";
|
||||
await t.step('HTML string', async function(t) {
|
||||
var ws = X.read(html, {type:'string'}).Sheets.Sheet1;
|
||||
var ws = X.read(html, {type:'string'}).Sheets["Sheet1"];
|
||||
assert.equal(X.utils.sheet_to_csv(ws), "A,B\n1,2\n3,4\n4,6");
|
||||
});
|
||||
if(domtest) await t.step('DOM', async function(t) {
|
||||
var ws = X.utils.table_to_sheet(get_dom_element(html));
|
||||
assert.equal(X.utils.sheet_to_csv(ws), "A,B\n1,2\n3,4\n4,6");
|
||||
});
|
||||
});
|
||||
await t.step('empty cell containing html element should increment cell index', async function(t) {
|
||||
var html = "<table><tr><td>abc</td><td><b> </b></td><td>def</td></tr></table>";
|
||||
var expectedCellCount = 3;
|
||||
await t.step('HTML string', async function() {
|
||||
var ws = X.read(html, {type:'string'}).Sheets.Sheet1;
|
||||
await t.step('HTML string', async function(t) {
|
||||
var ws = X.read(html, {type:'string'}).Sheets["Sheet1"];
|
||||
var range = X.utils.decode_range(ws['!ref']||"A1");
|
||||
assert.equal(range.e.c,expectedCellCount - 1);
|
||||
});
|
||||
if(domtest) await t.step('DOM', async function(t) {
|
||||
var ws = X.utils.table_to_sheet(get_dom_element(html));
|
||||
var range = X.utils.decode_range(ws['!ref']||"A1");
|
||||
assert.equal(range.e.c, expectedCellCount - 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -2346,7 +2456,7 @@ Deno.test('corner cases', async function(t) {
|
||||
});
|
||||
if(typeof JSON !== 'undefined') await t.step('SSF oddities', async function(t) {
|
||||
// $FlowIgnore
|
||||
var ssfdata: Array<any> = JSON.parse(fs.readFileSync2('./misc/ssf.json', 'utf-8'));
|
||||
var ssfdata: Array<any> = JSON.parse(fs.readFileSync('./misc/ssf.json', 'utf-8'));
|
||||
var cb = function(d: any, j: any) { return function() { return X.SSF.format(d[0], d[j][0]); }; };
|
||||
ssfdata.forEach(function(d) {
|
||||
for(var j=1;j<d.length;++j) {
|
||||
@ -2381,17 +2491,17 @@ Deno.test('corner cases', async function(t) {
|
||||
});
|
||||
await t.step("should quote unicode sheet names in formulae", async function(t) {
|
||||
var wb = X.read(fs.readFileSync(dir + "cross-sheet_formula_names.xlsb"), {WTF:true, type:TYPE});
|
||||
assert.equal(wb.Sheets.Sheet1.A1.f, "'a-b'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A2.f, "'a#b'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A3.f, "'a^b'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A4.f, "'a%b'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A5.f, "'a\u066ab'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A6.f, "'☃️'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A7.f, "'\ud83c\udf63'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A8.f, "'a!!b'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A9.f, "'a$b'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A10.f, "'a!b'!A1");
|
||||
assert.equal(wb.Sheets.Sheet1.A11.f, "'a b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A1.f, "'a-b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A2.f, "'a#b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A3.f, "'a^b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A4.f, "'a%b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A5.f, "'a\u066ab'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A6.f, "'☃️'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A7.f, "'\ud83c\udf63'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A8.f, "'a!!b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A9.f, "'a$b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A10.f, "'a!b'!A1");
|
||||
assert.equal(wb.Sheets["Sheet1"].A11.f, "'a b'!A1");
|
||||
});
|
||||
if(false) await t.step('should parse CSV date values with preceding space', async function(t) {
|
||||
function check_ws(ws: X.WorkSheet, dNF?: any) {
|
||||
@ -2406,12 +2516,12 @@ Deno.test('corner cases', async function(t) {
|
||||
var ws1 = X.read(
|
||||
'7,2018-03-24',
|
||||
{cellDates: cD, dateNF: dNF, type:'string'}
|
||||
).Sheets.Sheet1;
|
||||
).Sheets["Sheet1"];
|
||||
check_ws(ws1, dNF);
|
||||
var ws2 = X.read(
|
||||
'7, 2018-03-24',
|
||||
{cellDates: cD, dateNF: dNF, type:'string'}
|
||||
).Sheets.Sheet1;
|
||||
).Sheets["Sheet1"];
|
||||
check_ws(ws2, dNF);
|
||||
});
|
||||
});
|
||||
@ -2549,16 +2659,17 @@ Deno.test('encryption', async function(t) {
|
||||
if(e.message == "Password is incorrect") throw e;
|
||||
}
|
||||
});
|
||||
//it.skip('should decrypt file', async function(t) {
|
||||
// /*var wb = */X.read(fs.readFileSync(dir + x), {type:TYPE,password:'password',WTF:opts.WTF});
|
||||
//});
|
||||
if(false) await t.step('should decrypt file', async function(t) {
|
||||
/*var wb = */X.read(fs.readFileSync(dir + x), {type:TYPE,password:'password',WTF:opts.WTF});
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
if(!browser || typeof cptable !== 'undefined')
|
||||
Deno.test('multiformat tests', async function(t) {
|
||||
var mfopts = opts;
|
||||
var mft = fs.readFileSync2('multiformat.lst','utf-8').replace(/\r/g,"").split("\n").map(function(x) { return x.trim(); });
|
||||
var mft = fs.readFileSync('multiformat.lst','utf-8').replace(/\r/g,"").split("\n").map(function(x) { return x.trim(); });
|
||||
var csv = true, formulae = false;
|
||||
for(var mfti = 0; mfti < mft.length; ++mfti) { var x = mft[mfti];
|
||||
if(x.charAt(0)!="#") await t.step('MFT ' + x, async function(t) {
|
||||
@ -2603,3 +2714,4 @@ for(var mfti = 0; mfti < mft.length; ++mfti) { var x = mft[mfti];
|
||||
case "yes-formula": formulae = true; break;
|
||||
}});
|
||||
} });
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 50158c2288492df6f6eb4037568023a3de3e0ef9
|
||||
Subproject commit 02324c31f26195b3b5c15c38ca46fe6d22c9ac1c
|
@ -1,4 +1,5 @@
|
||||
var assert = function(bool) { if(!bool) { throw new Error("failed assert"); } };
|
||||
assert.ok = function(bool) { if(!bool) { throw new Error("failed assert"); } };
|
||||
assert.deepEqualArray = function(x,y) {
|
||||
if(x.length != y.length) throw new Error("Length mismatch: " + x.length + " != " + y.length);
|
||||
for(var i = 0; i < x.length; ++i) assert.deepEqual(x[i], y[i]);
|
||||
|
64
xlsx.flow.js
64
xlsx.flow.js
@ -4372,8 +4372,8 @@ 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.cellDates) { cell.t = 'd'; cell.w = SSF_format(cell.z, datenum(cell.v)); }
|
||||
else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF_format(cell.z, 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); }
|
||||
}
|
||||
else cell.t = 's';
|
||||
}
|
||||
@ -8026,7 +8026,7 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
wb.Workbook.Names.push(nn);
|
||||
} break;
|
||||
case 'C': /* cell */
|
||||
var C_seen_K = false, C_seen_X = false, C_seen_S = false, C_seen_E = false, _R = -1, _C = -1;
|
||||
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";
|
||||
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
|
||||
case 'A': break; // TODO: comment
|
||||
case 'X': C = parseInt(record[rj].slice(1), 10)-1; C_seen_X = true; break;
|
||||
@ -8036,26 +8036,24 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
break;
|
||||
case 'K':
|
||||
val = record[rj].slice(1);
|
||||
if(val.charAt(0) === '"') val = val.slice(1,val.length - 1);
|
||||
else if(val === 'TRUE') val = true;
|
||||
else if(val === 'FALSE') val = false;
|
||||
if(val.charAt(0) === '"') { val = val.slice(1,val.length - 1); cell_t = "s"; }
|
||||
else if(val === 'TRUE' || val === 'FALSE') { val = val === 'TRUE'; cell_t = "b"; }
|
||||
else if(!isNaN(fuzzynum(val))) {
|
||||
val = fuzzynum(val);
|
||||
if(next_cell_format !== null && fmt_is_date(next_cell_format)) val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : 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);
|
||||
val = parseDate(val); cell_t = "d";
|
||||
if(!opts.cellDates) { cell_t = "n"; val = datenum(val, wb.Workbook.WBProps.date1904); }
|
||||
}
|
||||
if(typeof $cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = $cptable.utils.decode(opts.codepage, val);
|
||||
C_seen_K = true;
|
||||
break;
|
||||
case 'E':
|
||||
C_seen_E = true;
|
||||
var formula = rc_to_a1(record[rj].slice(1), {r:R,c:C});
|
||||
arr[R][C] = [arr[R][C], formula];
|
||||
formula = rc_to_a1(record[rj].slice(1), {r:R,c:C});
|
||||
break;
|
||||
case 'S':
|
||||
C_seen_S = true;
|
||||
arr[R][C] = [arr[R][C], "S5S"];
|
||||
break;
|
||||
case 'G': break; // unknown
|
||||
case 'R': _R = parseInt(record[rj].slice(1), 10)-1; break;
|
||||
@ -8063,15 +8061,21 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
}
|
||||
if(C_seen_K) {
|
||||
if(arr[R][C] && arr[R][C].length == 2) arr[R][C][0] = val;
|
||||
else arr[R][C] = val;
|
||||
if(!arr[R][C]) arr[R][C] = { t: cell_t, v: val };
|
||||
else { arr[R][C].t = cell_t; arr[R][C].v = val; }
|
||||
if(next_cell_format) arr[R][C].z = next_cell_format;
|
||||
if(opts.cellText !== false && next_cell_format) arr[R][C].w = SSF_format(arr[R][C].z, arr[R][C].v, { date1904: wb.Workbook.WBProps.date1904 });
|
||||
next_cell_format = null;
|
||||
}
|
||||
if(C_seen_S) {
|
||||
if(C_seen_E) throw new Error("SYLK shared formula cannot have own formula");
|
||||
var shrbase = _R > -1 && arr[_R][_C];
|
||||
if(!shrbase || !shrbase[1]) throw new Error("SYLK shared formula cannot find base");
|
||||
arr[R][C][1] = shift_formula_str(shrbase[1], {r: R - _R, c: C - _C});
|
||||
formula = shift_formula_str(shrbase[1], {r: R - _R, c: C - _C});
|
||||
}
|
||||
if(formula) {
|
||||
if(!arr[R][C]) arr[R][C] = { t: 'n', f: formula };
|
||||
else arr[R][C].f = formula;
|
||||
}
|
||||
break;
|
||||
case 'F': /* Format */
|
||||
@ -8123,7 +8127,8 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
function sylk_to_workbook(d/*:RawData*/, opts)/*:Workbook*/ {
|
||||
var aoasht = sylk_to_aoa(d, opts);
|
||||
var aoa = aoasht[0], ws = aoasht[1], wb = aoasht[2];
|
||||
var o = aoa_to_sheet(aoa, opts);
|
||||
var _opts = dup(opts); _opts.date1904 = (((wb||{}).Workbook || {}).WBProps || {}).date1904;
|
||||
var o = aoa_to_sheet(aoa, _opts);
|
||||
keys(ws).forEach(function(k) { o[k] = ws[k]; });
|
||||
var outwb = sheet_to_workbook(o, opts);
|
||||
keys(wb).forEach(function(k) { outwb[k] = wb[k]; });
|
||||
@ -8167,11 +8172,12 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
});
|
||||
}
|
||||
|
||||
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
|
||||
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/, wb/*:?WorkBook*/)/*:string*/ {
|
||||
var preamble/*:Array<string>*/ = ["ID;PSheetJS;N;E"], o/*:Array<string>*/ = [];
|
||||
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
|
||||
var dense = Array.isArray(ws);
|
||||
var RS = "\r\n";
|
||||
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
|
||||
preamble.push("P;PGeneral");
|
||||
preamble.push("F;P0;DG0G8;M255");
|
||||
@ -8179,12 +8185,13 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
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) {
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var coord = encode_cell({r:R,c:C});
|
||||
cell = dense ? (ws[R]||[])[C]: ws[coord];
|
||||
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
|
||||
o.push(write_ws_cell_sylk(cell, ws, R, C, opts));
|
||||
o.push(write_ws_cell_sylk(cell, ws, R, C, opts)); // TODO: pass date1904 info
|
||||
}
|
||||
}
|
||||
return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
|
||||
@ -17405,6 +17412,7 @@ function write_BrtWbProp(data/*:?WBProps*/, o) {
|
||||
var flags = 0;
|
||||
if(data) {
|
||||
/* TODO: mirror parse_BrtWbProp fields */
|
||||
if(data.date1904) flags |= 0x01;
|
||||
if(data.filterPrivacy) flags |= 0x08;
|
||||
}
|
||||
o.write_shift(4, flags);
|
||||
@ -18711,9 +18719,10 @@ function write_props_xlml(wb/*:Workbook*/, opts)/*:string*/ {
|
||||
return o.join("");
|
||||
}
|
||||
/* TODO */
|
||||
function write_wb_xlml(/*::wb, opts*/)/*:string*/ {
|
||||
function write_wb_xlml(wb/*::, opts*/)/*:string*/ {
|
||||
/* OfficeDocumentSettings */
|
||||
/* ExcelWorkbook */
|
||||
if((((wb||{}).Workbook||{}).WBProps||{}).date1904) return '<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"><Date1904/></ExcelWorkbook>';
|
||||
return "";
|
||||
}
|
||||
/* TODO */
|
||||
@ -21766,13 +21775,14 @@ function parse_content_xml(d/*:string*/, _opts)/*:Workbook*/ {
|
||||
var merges/*:Array<Range>*/ = [], mrange = {}, mR = 0, mC = 0;
|
||||
var rowinfo/*:Array<RowInfo>*/ = [], rowpeat = 1, colpeat = 1;
|
||||
var arrayf/*:Array<[Range, string]>*/ = [];
|
||||
var WB = {Names:[]};
|
||||
var WB = {Names:[], WBProps:{}};
|
||||
var atag = ({}/*:any*/);
|
||||
var _Ref/*:[string, string]*/ = ["", ""];
|
||||
var comments/*:Array<Comment>*/ = [], comment/*:Comment*/ = ({}/*:any*/);
|
||||
var creator = "", creatoridx = 0;
|
||||
var isstub = false, intable = false;
|
||||
var i = 0;
|
||||
var baddate = 1;
|
||||
xlmlregex.lastIndex = 0;
|
||||
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
|
||||
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
|
||||
@ -21884,7 +21894,7 @@ function parse_content_xml(d/*:string*/, _opts)/*:Workbook*/ {
|
||||
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); }
|
||||
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904) - baddate; }
|
||||
q.z = 'm/d/yy'; break;
|
||||
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400;
|
||||
if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); }
|
||||
@ -22085,7 +22095,14 @@ function parse_content_xml(d/*:string*/, _opts)/*:Workbook*/ {
|
||||
case 'table-header-columns': break; // 9.1.11 <table:table-header-columns>
|
||||
case 'table-columns': break; // 9.1.12 <table:table-columns>
|
||||
|
||||
case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
|
||||
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;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'graphic-properties': break; // 17.21 <style:graphic-properties>
|
||||
case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
|
||||
@ -22540,6 +22557,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
|
||||
write_automatic_styles_ods(o, wb);
|
||||
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));
|
||||
if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1));
|
||||
o.push(' </office:spreadsheet>\n');
|
||||
@ -24664,7 +24682,7 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
|
||||
case 'xml':
|
||||
case 'xlml': return write_string_type(write_xlml(wb, o), o);
|
||||
case 'slk':
|
||||
case 'sylk': return write_string_type(SYLK.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
|
||||
case 'sylk': return write_string_type(SYLK.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb), o);
|
||||
case 'htm':
|
||||
case 'html': return write_string_type(sheet_to_html(wb.Sheets[wb.SheetNames[idx]], o), o);
|
||||
case 'txt': return write_stxt_type(sheet_to_txt(wb.Sheets[wb.SheetNames[idx]], o), o);
|
||||
|
64
xlsx.js
generated
64
xlsx.js
generated
@ -4287,8 +4287,8 @@ 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.cellDates) { cell.t = 'd'; cell.w = SSF_format(cell.z, datenum(cell.v)); }
|
||||
else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF_format(cell.z, 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); }
|
||||
}
|
||||
else cell.t = 's';
|
||||
}
|
||||
@ -7936,7 +7936,7 @@ var SYLK = (function() {
|
||||
wb.Workbook.Names.push(nn);
|
||||
} break;
|
||||
case 'C': /* cell */
|
||||
var C_seen_K = false, C_seen_X = false, C_seen_S = false, C_seen_E = false, _R = -1, _C = -1;
|
||||
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";
|
||||
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
|
||||
case 'A': break; // TODO: comment
|
||||
case 'X': C = parseInt(record[rj].slice(1), 10)-1; C_seen_X = true; break;
|
||||
@ -7946,26 +7946,24 @@ var SYLK = (function() {
|
||||
break;
|
||||
case 'K':
|
||||
val = record[rj].slice(1);
|
||||
if(val.charAt(0) === '"') val = val.slice(1,val.length - 1);
|
||||
else if(val === 'TRUE') val = true;
|
||||
else if(val === 'FALSE') val = false;
|
||||
if(val.charAt(0) === '"') { val = val.slice(1,val.length - 1); cell_t = "s"; }
|
||||
else if(val === 'TRUE' || val === 'FALSE') { val = val === 'TRUE'; cell_t = "b"; }
|
||||
else if(!isNaN(fuzzynum(val))) {
|
||||
val = fuzzynum(val);
|
||||
if(next_cell_format !== null && fmt_is_date(next_cell_format)) val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : 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);
|
||||
val = parseDate(val); cell_t = "d";
|
||||
if(!opts.cellDates) { cell_t = "n"; val = datenum(val, wb.Workbook.WBProps.date1904); }
|
||||
}
|
||||
if(typeof $cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = $cptable.utils.decode(opts.codepage, val);
|
||||
C_seen_K = true;
|
||||
break;
|
||||
case 'E':
|
||||
C_seen_E = true;
|
||||
var formula = rc_to_a1(record[rj].slice(1), {r:R,c:C});
|
||||
arr[R][C] = [arr[R][C], formula];
|
||||
formula = rc_to_a1(record[rj].slice(1), {r:R,c:C});
|
||||
break;
|
||||
case 'S':
|
||||
C_seen_S = true;
|
||||
arr[R][C] = [arr[R][C], "S5S"];
|
||||
break;
|
||||
case 'G': break; // unknown
|
||||
case 'R': _R = parseInt(record[rj].slice(1), 10)-1; break;
|
||||
@ -7973,15 +7971,21 @@ var SYLK = (function() {
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
}
|
||||
if(C_seen_K) {
|
||||
if(arr[R][C] && arr[R][C].length == 2) arr[R][C][0] = val;
|
||||
else arr[R][C] = val;
|
||||
if(!arr[R][C]) arr[R][C] = { t: cell_t, v: val };
|
||||
else { arr[R][C].t = cell_t; arr[R][C].v = val; }
|
||||
if(next_cell_format) arr[R][C].z = next_cell_format;
|
||||
if(opts.cellText !== false && next_cell_format) arr[R][C].w = SSF_format(arr[R][C].z, arr[R][C].v, { date1904: wb.Workbook.WBProps.date1904 });
|
||||
next_cell_format = null;
|
||||
}
|
||||
if(C_seen_S) {
|
||||
if(C_seen_E) throw new Error("SYLK shared formula cannot have own formula");
|
||||
var shrbase = _R > -1 && arr[_R][_C];
|
||||
if(!shrbase || !shrbase[1]) throw new Error("SYLK shared formula cannot find base");
|
||||
arr[R][C][1] = shift_formula_str(shrbase[1], {r: R - _R, c: C - _C});
|
||||
formula = shift_formula_str(shrbase[1], {r: R - _R, c: C - _C});
|
||||
}
|
||||
if(formula) {
|
||||
if(!arr[R][C]) arr[R][C] = { t: 'n', f: formula };
|
||||
else arr[R][C].f = formula;
|
||||
}
|
||||
break;
|
||||
case 'F': /* Format */
|
||||
@ -8033,7 +8037,8 @@ var SYLK = (function() {
|
||||
function sylk_to_workbook(d, opts) {
|
||||
var aoasht = sylk_to_aoa(d, opts);
|
||||
var aoa = aoasht[0], ws = aoasht[1], wb = aoasht[2];
|
||||
var o = aoa_to_sheet(aoa, opts);
|
||||
var _opts = dup(opts); _opts.date1904 = (((wb||{}).Workbook || {}).WBProps || {}).date1904;
|
||||
var o = aoa_to_sheet(aoa, _opts);
|
||||
keys(ws).forEach(function(k) { o[k] = ws[k]; });
|
||||
var outwb = sheet_to_workbook(o, opts);
|
||||
keys(wb).forEach(function(k) { outwb[k] = wb[k]; });
|
||||
@ -8077,11 +8082,12 @@ var SYLK = (function() {
|
||||
});
|
||||
}
|
||||
|
||||
function sheet_to_sylk(ws, opts) {
|
||||
function sheet_to_sylk(ws, opts, wb) {
|
||||
var preamble = ["ID;PSheetJS;N;E"], o = [];
|
||||
var r = safe_decode_range(ws['!ref']), cell;
|
||||
var dense = Array.isArray(ws);
|
||||
var RS = "\r\n";
|
||||
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
|
||||
preamble.push("P;PGeneral");
|
||||
preamble.push("F;P0;DG0G8;M255");
|
||||
@ -8089,12 +8095,13 @@ var SYLK = (function() {
|
||||
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) {
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var coord = encode_cell({r:R,c:C});
|
||||
cell = dense ? (ws[R]||[])[C]: ws[coord];
|
||||
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
|
||||
o.push(write_ws_cell_sylk(cell, ws, R, C, opts));
|
||||
o.push(write_ws_cell_sylk(cell, ws, R, C, opts)); // TODO: pass date1904 info
|
||||
}
|
||||
}
|
||||
return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
|
||||
@ -17308,6 +17315,7 @@ function write_BrtWbProp(data, o) {
|
||||
var flags = 0;
|
||||
if(data) {
|
||||
/* TODO: mirror parse_BrtWbProp fields */
|
||||
if(data.date1904) flags |= 0x01;
|
||||
if(data.filterPrivacy) flags |= 0x08;
|
||||
}
|
||||
o.write_shift(4, flags);
|
||||
@ -18609,9 +18617,10 @@ function write_props_xlml(wb, opts) {
|
||||
return o.join("");
|
||||
}
|
||||
/* TODO */
|
||||
function write_wb_xlml() {
|
||||
function write_wb_xlml(wb) {
|
||||
/* OfficeDocumentSettings */
|
||||
/* ExcelWorkbook */
|
||||
if((((wb||{}).Workbook||{}).WBProps||{}).date1904) return '<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"><Date1904/></ExcelWorkbook>';
|
||||
return "";
|
||||
}
|
||||
/* TODO */
|
||||
@ -21656,13 +21665,14 @@ function parse_content_xml(d, _opts) {
|
||||
var merges = [], mrange = {}, mR = 0, mC = 0;
|
||||
var rowinfo = [], rowpeat = 1, colpeat = 1;
|
||||
var arrayf = [];
|
||||
var WB = {Names:[]};
|
||||
var WB = {Names:[], WBProps:{}};
|
||||
var atag = ({});
|
||||
var _Ref = ["", ""];
|
||||
var comments = [], comment = ({});
|
||||
var creator = "", creatoridx = 0;
|
||||
var isstub = false, intable = false;
|
||||
var i = 0;
|
||||
var baddate = 1;
|
||||
xlmlregex.lastIndex = 0;
|
||||
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
|
||||
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
|
||||
@ -21774,7 +21784,7 @@ function parse_content_xml(d, _opts) {
|
||||
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); }
|
||||
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904) - baddate; }
|
||||
q.z = 'm/d/yy'; break;
|
||||
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400;
|
||||
if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); }
|
||||
@ -21975,7 +21985,14 @@ function parse_content_xml(d, _opts) {
|
||||
case 'table-header-columns': break; // 9.1.11 <table:table-header-columns>
|
||||
case 'table-columns': break; // 9.1.12 <table:table-columns>
|
||||
|
||||
case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
|
||||
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;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'graphic-properties': break; // 17.21 <style:graphic-properties>
|
||||
case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
|
||||
@ -22430,6 +22447,7 @@ var write_content_ods = /* @__PURE__ */(function() {
|
||||
write_automatic_styles_ods(o, wb);
|
||||
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));
|
||||
if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1));
|
||||
o.push(' </office:spreadsheet>\n');
|
||||
@ -24549,7 +24567,7 @@ function writeSync(wb, opts) {
|
||||
case 'xml':
|
||||
case 'xlml': return write_string_type(write_xlml(wb, o), o);
|
||||
case 'slk':
|
||||
case 'sylk': return write_string_type(SYLK.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
|
||||
case 'sylk': return write_string_type(SYLK.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb), o);
|
||||
case 'htm':
|
||||
case 'html': return write_string_type(sheet_to_html(wb.Sheets[wb.SheetNames[idx]], o), o);
|
||||
case 'txt': return write_stxt_type(sheet_to_txt(wb.Sheets[wb.SheetNames[idx]], o), o);
|
||||
|
64
xlsx.mjs
generated
64
xlsx.mjs
generated
@ -4367,8 +4367,8 @@ 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.cellDates) { cell.t = 'd'; cell.w = SSF_format(cell.z, datenum(cell.v)); }
|
||||
else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF_format(cell.z, 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); }
|
||||
}
|
||||
else cell.t = 's';
|
||||
}
|
||||
@ -8021,7 +8021,7 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
wb.Workbook.Names.push(nn);
|
||||
} break;
|
||||
case 'C': /* cell */
|
||||
var C_seen_K = false, C_seen_X = false, C_seen_S = false, C_seen_E = false, _R = -1, _C = -1;
|
||||
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";
|
||||
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
|
||||
case 'A': break; // TODO: comment
|
||||
case 'X': C = parseInt(record[rj].slice(1), 10)-1; C_seen_X = true; break;
|
||||
@ -8031,26 +8031,24 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
break;
|
||||
case 'K':
|
||||
val = record[rj].slice(1);
|
||||
if(val.charAt(0) === '"') val = val.slice(1,val.length - 1);
|
||||
else if(val === 'TRUE') val = true;
|
||||
else if(val === 'FALSE') val = false;
|
||||
if(val.charAt(0) === '"') { val = val.slice(1,val.length - 1); cell_t = "s"; }
|
||||
else if(val === 'TRUE' || val === 'FALSE') { val = val === 'TRUE'; cell_t = "b"; }
|
||||
else if(!isNaN(fuzzynum(val))) {
|
||||
val = fuzzynum(val);
|
||||
if(next_cell_format !== null && fmt_is_date(next_cell_format)) val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : 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);
|
||||
val = parseDate(val); cell_t = "d";
|
||||
if(!opts.cellDates) { cell_t = "n"; val = datenum(val, wb.Workbook.WBProps.date1904); }
|
||||
}
|
||||
if(typeof $cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = $cptable.utils.decode(opts.codepage, val);
|
||||
C_seen_K = true;
|
||||
break;
|
||||
case 'E':
|
||||
C_seen_E = true;
|
||||
var formula = rc_to_a1(record[rj].slice(1), {r:R,c:C});
|
||||
arr[R][C] = [arr[R][C], formula];
|
||||
formula = rc_to_a1(record[rj].slice(1), {r:R,c:C});
|
||||
break;
|
||||
case 'S':
|
||||
C_seen_S = true;
|
||||
arr[R][C] = [arr[R][C], "S5S"];
|
||||
break;
|
||||
case 'G': break; // unknown
|
||||
case 'R': _R = parseInt(record[rj].slice(1), 10)-1; break;
|
||||
@ -8058,15 +8056,21 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
}
|
||||
if(C_seen_K) {
|
||||
if(arr[R][C] && arr[R][C].length == 2) arr[R][C][0] = val;
|
||||
else arr[R][C] = val;
|
||||
if(!arr[R][C]) arr[R][C] = { t: cell_t, v: val };
|
||||
else { arr[R][C].t = cell_t; arr[R][C].v = val; }
|
||||
if(next_cell_format) arr[R][C].z = next_cell_format;
|
||||
if(opts.cellText !== false && next_cell_format) arr[R][C].w = SSF_format(arr[R][C].z, arr[R][C].v, { date1904: wb.Workbook.WBProps.date1904 });
|
||||
next_cell_format = null;
|
||||
}
|
||||
if(C_seen_S) {
|
||||
if(C_seen_E) throw new Error("SYLK shared formula cannot have own formula");
|
||||
var shrbase = _R > -1 && arr[_R][_C];
|
||||
if(!shrbase || !shrbase[1]) throw new Error("SYLK shared formula cannot find base");
|
||||
arr[R][C][1] = shift_formula_str(shrbase[1], {r: R - _R, c: C - _C});
|
||||
formula = shift_formula_str(shrbase[1], {r: R - _R, c: C - _C});
|
||||
}
|
||||
if(formula) {
|
||||
if(!arr[R][C]) arr[R][C] = { t: 'n', f: formula };
|
||||
else arr[R][C].f = formula;
|
||||
}
|
||||
break;
|
||||
case 'F': /* Format */
|
||||
@ -8118,7 +8122,8 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
function sylk_to_workbook(d/*:RawData*/, opts)/*:Workbook*/ {
|
||||
var aoasht = sylk_to_aoa(d, opts);
|
||||
var aoa = aoasht[0], ws = aoasht[1], wb = aoasht[2];
|
||||
var o = aoa_to_sheet(aoa, opts);
|
||||
var _opts = dup(opts); _opts.date1904 = (((wb||{}).Workbook || {}).WBProps || {}).date1904;
|
||||
var o = aoa_to_sheet(aoa, _opts);
|
||||
keys(ws).forEach(function(k) { o[k] = ws[k]; });
|
||||
var outwb = sheet_to_workbook(o, opts);
|
||||
keys(wb).forEach(function(k) { outwb[k] = wb[k]; });
|
||||
@ -8162,11 +8167,12 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
});
|
||||
}
|
||||
|
||||
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
|
||||
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/, wb/*:?WorkBook*/)/*:string*/ {
|
||||
var preamble/*:Array<string>*/ = ["ID;PSheetJS;N;E"], o/*:Array<string>*/ = [];
|
||||
var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
|
||||
var dense = Array.isArray(ws);
|
||||
var RS = "\r\n";
|
||||
var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
|
||||
|
||||
preamble.push("P;PGeneral");
|
||||
preamble.push("F;P0;DG0G8;M255");
|
||||
@ -8174,12 +8180,13 @@ var SYLK = /*#__PURE__*/(function() {
|
||||
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) {
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var coord = encode_cell({r:R,c:C});
|
||||
cell = dense ? (ws[R]||[])[C]: ws[coord];
|
||||
if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
|
||||
o.push(write_ws_cell_sylk(cell, ws, R, C, opts));
|
||||
o.push(write_ws_cell_sylk(cell, ws, R, C, opts)); // TODO: pass date1904 info
|
||||
}
|
||||
}
|
||||
return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
|
||||
@ -17400,6 +17407,7 @@ function write_BrtWbProp(data/*:?WBProps*/, o) {
|
||||
var flags = 0;
|
||||
if(data) {
|
||||
/* TODO: mirror parse_BrtWbProp fields */
|
||||
if(data.date1904) flags |= 0x01;
|
||||
if(data.filterPrivacy) flags |= 0x08;
|
||||
}
|
||||
o.write_shift(4, flags);
|
||||
@ -18706,9 +18714,10 @@ function write_props_xlml(wb/*:Workbook*/, opts)/*:string*/ {
|
||||
return o.join("");
|
||||
}
|
||||
/* TODO */
|
||||
function write_wb_xlml(/*::wb, opts*/)/*:string*/ {
|
||||
function write_wb_xlml(wb/*::, opts*/)/*:string*/ {
|
||||
/* OfficeDocumentSettings */
|
||||
/* ExcelWorkbook */
|
||||
if((((wb||{}).Workbook||{}).WBProps||{}).date1904) return '<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"><Date1904/></ExcelWorkbook>';
|
||||
return "";
|
||||
}
|
||||
/* TODO */
|
||||
@ -21761,13 +21770,14 @@ function parse_content_xml(d/*:string*/, _opts)/*:Workbook*/ {
|
||||
var merges/*:Array<Range>*/ = [], mrange = {}, mR = 0, mC = 0;
|
||||
var rowinfo/*:Array<RowInfo>*/ = [], rowpeat = 1, colpeat = 1;
|
||||
var arrayf/*:Array<[Range, string]>*/ = [];
|
||||
var WB = {Names:[]};
|
||||
var WB = {Names:[], WBProps:{}};
|
||||
var atag = ({}/*:any*/);
|
||||
var _Ref/*:[string, string]*/ = ["", ""];
|
||||
var comments/*:Array<Comment>*/ = [], comment/*:Comment*/ = ({}/*:any*/);
|
||||
var creator = "", creatoridx = 0;
|
||||
var isstub = false, intable = false;
|
||||
var i = 0;
|
||||
var baddate = 1;
|
||||
xlmlregex.lastIndex = 0;
|
||||
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
|
||||
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
|
||||
@ -21879,7 +21889,7 @@ function parse_content_xml(d/*:string*/, _opts)/*:Workbook*/ {
|
||||
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); }
|
||||
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904) - baddate; }
|
||||
q.z = 'm/d/yy'; break;
|
||||
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400;
|
||||
if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); }
|
||||
@ -22080,7 +22090,14 @@ function parse_content_xml(d/*:string*/, _opts)/*:Workbook*/ {
|
||||
case 'table-header-columns': break; // 9.1.11 <table:table-header-columns>
|
||||
case 'table-columns': break; // 9.1.12 <table:table-columns>
|
||||
|
||||
case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
|
||||
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;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'graphic-properties': break; // 17.21 <style:graphic-properties>
|
||||
case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
|
||||
@ -22535,6 +22552,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
|
||||
write_automatic_styles_ods(o, wb);
|
||||
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));
|
||||
if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1));
|
||||
o.push(' </office:spreadsheet>\n');
|
||||
@ -24659,7 +24677,7 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
|
||||
case 'xml':
|
||||
case 'xlml': return write_string_type(write_xlml(wb, o), o);
|
||||
case 'slk':
|
||||
case 'sylk': return write_string_type(SYLK.from_sheet(wb.Sheets[wb.SheetNames[idx]], o), o);
|
||||
case 'sylk': return write_string_type(SYLK.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb), o);
|
||||
case 'htm':
|
||||
case 'html': return write_string_type(sheet_to_html(wb.Sheets[wb.SheetNames[idx]], o), o);
|
||||
case 'txt': return write_stxt_type(sheet_to_txt(wb.Sheets[wb.SheetNames[idx]], o), o);
|
||||
|
Loading…
Reference in New Issue
Block a user