1
forked from sheetjs/sheetjs

SYLK error cells read/write (fixes )

This commit is contained in:
SheetJS 2024-01-10 04:54:10 -05:00
parent 29d46c07a8
commit d4d4ff3da2
13 changed files with 246 additions and 32 deletions

@ -4,6 +4,10 @@ This log is intended to keep track of backwards-incompatible changes, including
but not limited to API changes and file location changes. Minor behavioral but not limited to API changes and file location changes. Minor behavioral
changes may not be included if they are not expected to break existing code. changes may not be included if they are not expected to break existing code.
## v0.20.2
* SYLK read and write error cells
## v0.20.1 ## v0.20.1
* `init` use packaged test files to work around GitHub breaking changes * `init` use packaged test files to work around GitHub breaking changes

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

@ -769,9 +769,9 @@ function _write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes|strin
file = cfb.FileIndex[i]; file = cfb.FileIndex[i];
if(i === 0) file.start = file.size ? file.start - 1 : ENDOFCHAIN; if(i === 0) file.start = file.size ? file.start - 1 : ENDOFCHAIN;
var _nm/*:string*/ = (i === 0 && _opts.root) || file.name; var _nm/*:string*/ = (i === 0 && _opts.root) || file.name;
if(_nm.length > 32) { if(_nm.length > 31) {
console.error("Name " + _nm + " will be truncated to " + _nm.slice(0,32)); console.error("Name " + _nm + " will be truncated to " + _nm.slice(0,31));
_nm = _nm.slice(0, 32); _nm = _nm.slice(0, 31);
} }
flen = 2*(_nm.length+1); flen = 2*(_nm.length+1);
o.write_shift(64, _nm, "utf16le"); o.write_shift(64, _nm, "utf16le");

@ -483,6 +483,7 @@ var SYLK = /*#__PURE__*/(function() {
val = record[rj].slice(1); val = record[rj].slice(1);
if(val.charAt(0) === '"') { val = val.slice(1,val.length - 1); cell_t = "s"; } if(val.charAt(0) === '"') { val = val.slice(1,val.length - 1); cell_t = "s"; }
else if(val === 'TRUE' || val === 'FALSE') { val = val === 'TRUE'; cell_t = "b"; } else if(val === 'TRUE' || val === 'FALSE') { val = val === 'TRUE'; cell_t = "b"; }
else if(val.charAt(0) == "#" && RBErr[val] != null) { cell_t = "e"; val = RBErr[val]; }
else if(!isNaN(fuzzynum(val))) { else if(!isNaN(fuzzynum(val))) {
val = fuzzynum(val); cell_t = "n"; val = fuzzynum(val); cell_t = "n";
if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) { if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) {
@ -595,7 +596,7 @@ var SYLK = /*#__PURE__*/(function() {
o += (cell.v||0); o += (cell.v||0);
if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break; if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break;
case 'b': o += cell.v ? "TRUE" : "FALSE"; break; case 'b': o += cell.v ? "TRUE" : "FALSE"; break;
case 'e': o += cell.w || cell.v; break; case 'e': o += cell.w || BErr[cell.v] || cell.v; break;
case 'd': o += datenum(parseDate(cell.v, date1904), date1904); break; case 'd': o += datenum(parseDate(cell.v, date1904), date1904); break;
case 's': o += '"' + (cell.v == null ? "" : String(cell.v)).replace(/"/g,"").replace(/;/g, ";;") + '"'; break; case 's': o += '"' + (cell.v == null ? "" : String(cell.v)).replace(/"/g,"").replace(/;/g, ";;") + '"'; break;
} }

@ -18,10 +18,12 @@ function parse_clrScheme(t, themes, opts) {
/* 20.1.2.3.32 srgbClr CT_SRgbColor */ /* 20.1.2.3.32 srgbClr CT_SRgbColor */
case '<a:srgbClr': case '<a:srgbClr':
color.rgb = y.val; break; color.rgb = y.val; break;
case '</a:srgbClr>': break;
/* 20.1.2.3.33 sysClr CT_SystemColor */ /* 20.1.2.3.33 sysClr CT_SystemColor */
case '<a:sysClr': case '<a:sysClr':
color.rgb = y.lastClr; break; color.rgb = y.lastClr; break;
case '</a:sysClr>': break;
/* 20.1.4.1.1 accent1 (Accent 1) */ /* 20.1.4.1.1 accent1 (Accent 1) */
/* 20.1.4.1.2 accent2 (Accent 2) */ /* 20.1.4.1.2 accent2 (Accent 2) */
@ -35,8 +37,10 @@ function parse_clrScheme(t, themes, opts) {
/* 20.1.4.1.19 hlink (Hyperlink) */ /* 20.1.4.1.19 hlink (Hyperlink) */
/* 20.1.4.1.22 lt1 (Light 1) */ /* 20.1.4.1.22 lt1 (Light 1) */
/* 20.1.4.1.23 lt2 (Light 2) */ /* 20.1.4.1.23 lt2 (Light 2) */
case '<a:dk1>': case '</a:dk1>': case '</a:dk1>':
case '<a:lt1>': case '</a:lt1>': case '</a:lt1>':
case '<a:dk1>':
case '<a:lt1>':
case '<a:dk2>': case '</a:dk2>': case '<a:dk2>': case '</a:dk2>':
case '<a:lt2>': case '</a:lt2>': case '<a:lt2>': case '</a:lt2>':
case '<a:accent1>': case '</a:accent1>': case '<a:accent1>': case '</a:accent1>':

@ -99,10 +99,11 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
if(sid === undefined && row) sid = row.StyleID; if(sid === undefined && row) sid = row.StyleID;
if(sid === undefined && csty) sid = csty.StyleID; if(sid === undefined && csty) sid = csty.StyleID;
while(styles[sid] !== undefined) { while(styles[sid] !== undefined) {
if(styles[sid].nf) nf = styles[sid].nf; var ssid = styles[sid];
if(styles[sid].Interior) interiors.push(styles[sid].Interior); if(ssid.nf) nf = ssid.nf;
if(!styles[sid].Parent) break; if(ssid.Interior) interiors.push(ssid.Interior);
sid = styles[sid].Parent; if(!ssid.Parent) break;
sid = ssid.Parent;
} }
switch(data.Type) { switch(data.Type) {
case 'Boolean': case 'Boolean':

@ -125,7 +125,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
if(icv < 64) return palette[icv-8] || XLSIcv[icv]; if(icv < 64) return palette[icv-8] || XLSIcv[icv];
return XLSIcv[icv]; return XLSIcv[icv];
}; };
var process_cell_style = function pcs(cell, line/*:any*/, options) { var process_cell_style = function pcs(line/*:any*/, options) {
var xfd = line.XF.data; var xfd = line.XF.data;
if(!xfd || !xfd.patternType || !options || !options.cellStyles) return; if(!xfd || !xfd.patternType || !options || !options.cellStyles) return;
line.s = ({}/*:any*/); line.s = ({}/*:any*/);
@ -137,7 +137,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
var addcell = function addcell(cell/*:any*/, line/*:any*/, options/*:any*/) { var addcell = function addcell(cell/*:any*/, line/*:any*/, options/*:any*/) {
if(!biff4w && file_depth > 1) return; if(!biff4w && file_depth > 1) return;
if(options.sheetRows && cell.r >= options.sheetRows) return; if(options.sheetRows && cell.r >= options.sheetRows) return;
if(options.cellStyles && line.XF && line.XF.data) process_cell_style(cell, line, options); if(options.cellStyles && line.XF && line.XF.data) process_cell_style(line, options);
delete line.ixfe; delete line.XF; delete line.ixfe; delete line.XF;
lastcell = cell; lastcell = cell;
last_cell = encode_cell(cell); last_cell = encode_cell(cell);

@ -31,7 +31,7 @@ function write_biff_continue(ba/*:BufArray*/, type/*:number*/, payload, length/*
} }
} }
function write_BIFF2BERR(r/*:number*/, c/*:number*/, val, t/*:string*/) { function write_BIFF2BERR(r/*:number*/, c/*:number*/, val, t/*:?string*/) {
var out = new_buf(9); var out = new_buf(9);
write_BIFF2Cell(out, r, c); write_BIFF2Cell(out, r, c);
write_Bes(val, t || 'b', out); write_Bes(val, t || 'b', out);
@ -101,7 +101,7 @@ function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n
function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) { function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
var dense = ws["!data"] != null; var dense = ws["!data"] != null;
var range = safe_decode_range(ws['!ref'] || "A1"), ref/*:string*/, rr = "", cols/*:Array<string>*/ = []; var range = safe_decode_range(ws['!ref'] || "A1"), rr = "", cols/*:Array<string>*/ = [];
if(range.e.c > 0xFF || range.e.r > 0x3FFF) { if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384"); if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF); range.e.c = Math.min(range.e.c, 0xFF);
@ -545,9 +545,9 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904; var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
if(b8) ws['!links'] = []; if(b8) ws['!links'] = [];
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
var comments = []; var comments = [];
var row = []; var row = [];
for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
for(var R = range.s.r; R <= range.e.r; ++R) { for(var R = range.s.r; R <= range.e.r; ++R) {
if(dense) row = ws["!data"][R] || []; if(dense) row = ws["!data"][R] || [];
rr = encode_row(R); rr = encode_row(R);

@ -202,11 +202,11 @@ function write_names_ods(Names, SheetNames, idx) {
} }
var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function() { var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function() {
/* 6.1.2 White Space Characters */ /* 6.1.2 White Space Characters */
var write_text_p = function(text/*:string*/)/*:string*/ { var write_text_p = function(text/*:string*/, span)/*:string*/ {
return escapexml(text) return escapexml(text)
.replace(/ +/g, function($$){return '<text:s text:c="'+$$.length+'"/>';}) .replace(/ +/g, function($$){return '<text:s text:c="'+$$.length+'"/>';})
.replace(/\t/g, "<text:tab/>") .replace(/\t/g, "<text:tab/>")
.replace(/\n/g, "</text:p><text:p>") .replace(/\n/g, span ? "<text:line-break/>": "</text:p><text:p>")
.replace(/^ /, "<text:s/>").replace(/ $/, "<text:s/>"); .replace(/^ /, "<text:s/>").replace(/ $/, "<text:s/>");
}; };

@ -257,7 +257,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,strip_front_slash(dir.vba[0]),true); if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,strip_front_slash(dir.vba[0]),true);
else if(dir.defaults && dir.defaults.bin === CT_VBA) out.vbaraw = getzipdata(zip, 'xl/vbaProject.bin',true); else if(dir.defaults && dir.defaults.bin === CT_VBA) out.vbaraw = getzipdata(zip, 'xl/vbaProject.bin',true);
} }
// TODO: pass back content types metdata for xlsm/xlsx resolution // TODO: pass back content types metadata for xlsm/xlsx resolution
out.bookType = xlsb ? "xlsb" : "xlsx"; out.bookType = xlsb ? "xlsb" : "xlsx";
return out; return out;
} }

@ -52,7 +52,7 @@ const wb = DTA.parse(fs.readFileSync("auto.dta"));
DTA.set_utils(XLSX.utils); DTA.set_utils(XLSX.utils);
(async() => { (async() => {
/* fetch file */ /* fetch file */
const data = await (await fetch("test.dta")).arrayBuffer(); const data = await (await fetch("test.dta")).arrayBuffer();
/* parse */ /* parse */
const wb = DTA.parse(new Uint8Array(data)); const wb = DTA.parse(new Uint8Array(data));
/* wb is a SheetJS workbook object */ /* wb is a SheetJS workbook object */

125
test.js

@ -367,13 +367,13 @@ if(!browser) describe('should parse test files', function() {
}); });
function get_cell(ws/*:Worksheet*/, addr/*:string*/) { function get_cell(ws/*:Worksheet*/, addr/*:string*/) {
if(!Array.isArray(ws)) return ws[addr]; if(!ws["!data"]) return ws[addr];
var a = X.utils.decode_cell(addr); var a = X.utils.decode_cell(addr);
return (ws[a.r]||[])[a.c]; return (ws["!data"][a.r]||[])[a.c];
} }
function each_cell(ws, f) { function each_cell(ws, f) {
if(Array.isArray(ws)) ws.forEach(function(row) { if(row) row.forEach(f); }); if(ws["!data"]) ws["!data"].forEach(function(row) { if(row) row.forEach(f); });
else Object.keys(ws).forEach(function(addr) { if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return; f(ws[addr]); }); else Object.keys(ws).forEach(function(addr) { if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return; f(ws[addr]); });
} }
@ -1023,10 +1023,14 @@ describe('parse features', function() {
}); });
describe('column properties', function() { describe('column properties', function() {
var wbs = [], wbs_no_slk = []; var wbs = [], wbs_no_slk = [], ols = [];
var ol = fs.existsSync(paths.olxls);
var bef = (function() { var bef = (function() {
wbs = CWPaths.map(function(n) { return X.read(fs.readFileSync(n), {type:TYPE, cellStyles:true}); }); wbs = CWPaths.map(function(n) { return X.read(fs.readFileSync(n), {type:TYPE, cellStyles:true}); });
wbs_no_slk = wbs.slice(0, 5); wbs_no_slk = wbs.slice(0, 5);
/* */
if(!ol) return;
ols = OLPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, cellStyles:true}); });
}); });
if(typeof before != 'undefined') before(bef); if(typeof before != 'undefined') before(bef);
else it('before', bef); else it('before', bef);
@ -1061,6 +1065,22 @@ describe('parse features', function() {
assert.equal(x[7].wpx, 101); assert.equal(x[7].wpx, 101);
}); });
}); });
it('should have correct outline levels', function() {
ols.map(function(x) { return x.Sheets["Sheet1"]; }).forEach(function(ws) {
var cols = ws['!cols'];
if(!cols) return; // TODO: ODS!!!
for(var i = 0; i < 29; ++i) {
var cell = get_cell(ws, X.utils.encode_col(i) + "1");
var lvl = (cols[i]||{}).level||0;
if(!cell || cell.t == 's') assert.equal(lvl, 0);
else if(cell.t == 'n') {
if(cell.v === 0) assert.equal(lvl, 0);
else assert.equal(lvl, cell.v);
}
}
assert.equal(cols[29].level, 7);
});
});
}); });
describe('row properties', function() { describe('row properties', function() {
@ -2476,10 +2496,12 @@ describe('dbf', function() {
it(wbs[1][0], function() { it(wbs[1][0], function() {
var wsfalse = wbsfalse[1][1].Sheets["Sheet1"]; var wsfalse = wbsfalse[1][1].Sheets["Sheet1"];
[ [
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45], ["C2", "v", 12.345], ["D2", "v", 1234.1], ["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45],
["C2", "v", 12.345], ["D2", "v", 1234.1],
["E2", "v", 6260], ["E2", "w", "19170219"], ["E2", "v", 6260], ["E2", "w", "19170219"],
["F2", "v", 6260], ["F2", "w", "19170219"], ["F2", "v", 6260], ["F2", "w", "19170219"],
["G2", "v", 1231.4], ["H2", "v", 123234], ["I2", "v", true], ["L2", "v", "SheetJS"] ["G2", "v", 1231.4], ["H2", "v", 123234],
["I2", "v", true], ["L2", "v", "SheetJS"]
].forEach(function(r) { ].forEach(function(r) {
assert.equal(get_cell(wsfalse, r[0])[r[1]], r[2]); assert.equal(get_cell(wsfalse, r[0])[r[1]], r[2]);
}); });
@ -2703,6 +2725,97 @@ describe('rtf', function() {
}); });
}); });
describe('dense mode', function() {
it('sheet_new', function() {
var sp = X.utils.sheet_new(); assert.ok(!sp["!data"]);
sp = X.utils.sheet_new({}); assert.ok(!sp["!data"]);
sp = X.utils.sheet_new({dense: false}); assert.ok(!sp["!data"]);
sp = X.utils.sheet_new({dense: true}); assert.ok(!!sp["!data"]);
});
it('read', function() {
ILPaths.forEach(function(p) {
var wb = X.read(fs.readFileSync(p), {type: TYPE, WTF: true});
var ws = wb.Sheets[wb.SheetNames[0]];
assert.equal(ws["A1"].v, "Link to Sheet2");
assert.ok(!ws["!data"]);
wb = X.read(fs.readFileSync(p), {type: TYPE, WTF: true, dense: true});
ws = wb.Sheets[wb.SheetNames[0]];
assert.ok(!ws["A1"]);
assert.equal(ws["!data"][0][0].v, "Link to Sheet2");
});
if(!browser) artifax.forEach(function(p) {
var wb = X.read(fs.readFileSync(p), {type: TYPE, WTF: true});
var ws = wb.Sheets[wb.SheetNames[0]];
assert.ok(ws["A1"]);
assert.ok(!ws["!data"]);
wb = X.read(fs.readFileSync(p), {type: TYPE, WTF: true, dense: true});
ws = wb.Sheets[wb.SheetNames[0]];
assert.ok(!ws["A1"]);
assert.ok(ws["!data"][0][0]);
});
});
it('aoa_to_sheet', function() {
var aoa = [["SheetJS"],[5433795]];
var sp = X.utils.aoa_to_sheet(aoa); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa, {}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa, {dense: false}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
var ds = X.utils.aoa_to_sheet(aoa, {dense: true}); assert.equal(ds["!data"][1][0].v, 5433795); assert.ok(!ds["A2"]);
});
it('json_to_sheet', function() {
var json = [{"SheetJS": 5433795}];
var sp = X.utils.json_to_sheet(json); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.json_to_sheet(json, {}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.json_to_sheet(json, {dense: false}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
var ds = X.utils.json_to_sheet(json, {dense: true}); assert.equal(ds["!data"][1][0].v, 5433795); assert.ok(!ds["A2"]);
});
it('sheet_add_aoa', function() {
var aoa = [["SheetJS"]];
var sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_aoa(sp, [[5433795]], {origin:-1}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_aoa(sp, [[5433795]], {origin:-1, dense: true}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
var ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1}); assert.equal(ds["!data"][1][0].v, 5433795); assert.ok(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1, dense: true}); assert.equal(ds["!data"][1][0].v, 5433795); assert.ok(!ds["A2"]);
});
it('sheet_add_json', function() {
var aoa = [["SheetJS"]];
var sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_json(sp, [{X:5433795}], {origin:-1, skipHeader:1}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_json(sp, [{X:5433795}], {origin:-1, skipHeader: 1, dense: true}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
var ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: 1}); assert.equal(ds["!data"][1][0].v, 5433795); assert.ok(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: 1, dense: true}); assert.equal(ds["!data"][1][0].v, 5433795); assert.ok(!ds["A2"]);
});
ofmt.forEach(function(f) { it('write ' + f, function() {
var aoa = [["SheetJS"],[5433795]];
var wb = X.utils.book_new(X.utils.aoa_to_sheet(aoa));
var newwb = X.read(X.write(wb, {type:"binary", bookType:f}), {type:"binary"});
assert.equal(get_cell(newwb.Sheets["Sheet1"], "A1").v, "SheetJS");
assert.equal(get_cell(newwb.Sheets["Sheet1"], "A2").v, 5433795);
}); });
it('sheet_to_formulae', function() {
var w = ['xlsx', paths.fstxlsx];
var wb1 = X.read(fs.readFileSync(w[1]), {type:TYPE, cellFormula:true, WTF:true, dense: false});
var wb2 = X.read(fs.readFileSync(w[1]), {type:TYPE, cellFormula:true, WTF:true, dense: true});
wb1.SheetNames.forEach(function(n) {
assert.equal(
X.utils.sheet_to_formulae(wb1.Sheets[n]).sort().join("\n"),
X.utils.sheet_to_formulae(wb2.Sheets[n]).sort().join("\n")
);
});
});
it('sheet_to_csv', function() {
var w = ['xlsx', paths.fstxlsx];
var wb1 = X.read(fs.readFileSync(w[1]), {type:TYPE, cellFormula:true, WTF:true, dense: false});
var wb2 = X.read(fs.readFileSync(w[1]), {type:TYPE, cellFormula:true, WTF:true, dense: true});
wb1.SheetNames.forEach(function(n) {
assert.equal(
X.utils.sheet_to_csv(wb1.Sheets[n]),
X.utils.sheet_to_csv(wb2.Sheets[n])
);
});
});
});
describe('corner cases', function() { describe('corner cases', function() {
it('output functions', function() { it('output functions', function() {
var ws = X.utils.aoa_to_sheet([ var ws = X.utils.aoa_to_sheet([

103
tests/core.js generated

@ -367,13 +367,13 @@ if(!browser) describe('should parse test files', function() {
}); });
function get_cell(ws/*:Worksheet*/, addr/*:string*/) { function get_cell(ws/*:Worksheet*/, addr/*:string*/) {
if(!Array.isArray(ws)) return ws[addr]; if(!ws["!data"]) return ws[addr];
var a = X.utils.decode_cell(addr); var a = X.utils.decode_cell(addr);
return (ws[a.r]||[])[a.c]; return (ws["!data"][a.r]||[])[a.c];
} }
function each_cell(ws, f) { function each_cell(ws, f) {
if(Array.isArray(ws)) ws.forEach(function(row) { if(row) row.forEach(f); }); if(ws["!data"]) ws["!data"].forEach(function(row) { if(row) row.forEach(f); });
else Object.keys(ws).forEach(function(addr) { if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return; f(ws[addr]); }); else Object.keys(ws).forEach(function(addr) { if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return; f(ws[addr]); });
} }
@ -1023,10 +1023,14 @@ describe('parse features', function() {
}); });
describe('column properties', function() { describe('column properties', function() {
var wbs = [], wbs_no_slk = []; var wbs = [], wbs_no_slk = [], ols = [];
var ol = fs.existsSync(paths.olxls);
var bef = (function() { var bef = (function() {
wbs = CWPaths.map(function(n) { return X.read(fs.readFileSync(n), {type:TYPE, cellStyles:true}); }); wbs = CWPaths.map(function(n) { return X.read(fs.readFileSync(n), {type:TYPE, cellStyles:true}); });
wbs_no_slk = wbs.slice(0, 5); wbs_no_slk = wbs.slice(0, 5);
/* */
if(!ol) return;
ols = OLPaths.map(function(p) { return X.read(fs.readFileSync(p), {type:TYPE, cellStyles:true}); });
}); });
if(typeof before != 'undefined') before(bef); if(typeof before != 'undefined') before(bef);
else it('before', bef); else it('before', bef);
@ -1061,6 +1065,22 @@ describe('parse features', function() {
assert.equal(x[7].wpx, 101); assert.equal(x[7].wpx, 101);
}); });
}); });
it('should have correct outline levels', function() {
ols.map(function(x) { return x.Sheets["Sheet1"]; }).forEach(function(ws) {
var cols = ws['!cols'];
if(!cols) return; // TODO: ODS!!!
for(var i = 0; i < 29; ++i) {
var cell = get_cell(ws, X.utils.encode_col(i) + "1");
var lvl = (cols[i]||{}).level||0;
if(!cell || cell.t == 's') assert.equal(lvl, 0);
else if(cell.t == 'n') {
if(cell.v === 0) assert.equal(lvl, 0);
else assert.equal(lvl, cell.v);
}
}
assert.equal(cols[29].level, 7);
});
});
}); });
describe('row properties', function() { describe('row properties', function() {
@ -2476,10 +2496,12 @@ describe('dbf', function() {
it(wbs[1][0], function() { it(wbs[1][0], function() {
var wsfalse = wbsfalse[1][1].Sheets["Sheet1"]; var wsfalse = wbsfalse[1][1].Sheets["Sheet1"];
[ [
["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45], ["C2", "v", 12.345], ["D2", "v", 1234.1], ["A1", "v", "CHAR10"], ["A2", "v", "test1"], ["B2", "v", 123.45],
["C2", "v", 12.345], ["D2", "v", 1234.1],
["E2", "v", 6260], ["E2", "w", "19170219"], ["E2", "v", 6260], ["E2", "w", "19170219"],
["F2", "v", 6260], ["F2", "w", "19170219"], ["F2", "v", 6260], ["F2", "w", "19170219"],
["G2", "v", 1231.4], ["H2", "v", 123234], ["I2", "v", true], ["L2", "v", "SheetJS"] ["G2", "v", 1231.4], ["H2", "v", 123234],
["I2", "v", true], ["L2", "v", "SheetJS"]
].forEach(function(r) { ].forEach(function(r) {
assert.equal(get_cell(wsfalse, r[0])[r[1]], r[2]); assert.equal(get_cell(wsfalse, r[0])[r[1]], r[2]);
}); });
@ -2703,6 +2725,75 @@ describe('rtf', function() {
}); });
}); });
describe('dense mode', function() {
it('sheet_new', function() {
var sp = X.utils.sheet_new(); assert.ok(!sp["!data"]);
sp = X.utils.sheet_new({}); assert.ok(!sp["!data"]);
sp = X.utils.sheet_new({dense: false}); assert.ok(!sp["!data"]);
sp = X.utils.sheet_new({dense: true}); assert.ok(!!sp["!data"]);
});
it('read', function() {
ILPaths.forEach(function(p) {
var wb = X.read(fs.readFileSync(p), {type: TYPE, WTF: true});
var ws = wb.Sheets[wb.SheetNames[0]];
assert.equal(ws["A1"].v, "Link to Sheet2");
assert.ok(!ws["!data"]);
wb = X.read(fs.readFileSync(p), {type: TYPE, WTF: true, dense: true});
ws = wb.Sheets[wb.SheetNames[0]];
assert.ok(!ws["A1"]);
assert.equal(ws["!data"][0][0].v, "Link to Sheet2");
});
if(!browser) artifax.forEach(function(p) {
var wb = X.read(fs.readFileSync(p), {type: TYPE, WTF: true});
var ws = wb.Sheets[wb.SheetNames[0]];
assert.ok(ws["A1"]);
assert.ok(!ws["!data"]);
wb = X.read(fs.readFileSync(p), {type: TYPE, WTF: true, dense: true});
ws = wb.Sheets[wb.SheetNames[0]];
assert.ok(!ws["A1"]);
assert.ok(ws["!data"][0][0]);
});
});
it('aoa_to_sheet', function() {
var aoa = [["SheetJS"],[5433795]];
var sp = X.utils.aoa_to_sheet(aoa); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa, {}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa, {dense: false}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
var ds = X.utils.aoa_to_sheet(aoa, {dense: true}); assert.equal(ds["!data"][1][0].v, 5433795); assert.ok(!ds["A2"]);
});
it('json_to_sheet', function() {
var json = [{"SheetJS": 5433795}];
var sp = X.utils.json_to_sheet(json); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.json_to_sheet(json, {}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.json_to_sheet(json, {dense: false}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
var ds = X.utils.json_to_sheet(json, {dense: true}); assert.equal(ds["!data"][1][0].v, 5433795); assert.ok(!ds["A2"]);
});
it('sheet_add_aoa', function() {
var aoa = [["SheetJS"]];
var sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_aoa(sp, [[5433795]], {origin:-1}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_aoa(sp, [[5433795]], {origin:-1, dense: true}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
var ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1}); assert.equal(ds["!data"][1][0].v, 5433795); assert.ok(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_aoa(ds, [[5433795]], {origin:-1, dense: true}); assert.equal(ds["!data"][1][0].v, 5433795); assert.ok(!ds["A2"]);
});
it('sheet_add_json', function() {
var aoa = [["SheetJS"]];
var sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_json(sp, [{X:5433795}], {origin:-1, skipHeader:1}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
sp = X.utils.aoa_to_sheet(aoa); X.utils.sheet_add_json(sp, [{X:5433795}], {origin:-1, skipHeader: 1, dense: true}); assert.equal(sp["A2"].v, 5433795); assert.ok(!sp["!data"]);
var ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: 1}); assert.equal(ds["!data"][1][0].v, 5433795); assert.ok(!ds["A2"]);
ds = X.utils.aoa_to_sheet(aoa, {dense: true}); X.utils.sheet_add_json(ds, [{X:5433795}], {origin:-1, skipHeader: 1, dense: true}); assert.equal(ds["!data"][1][0].v, 5433795); assert.ok(!ds["A2"]);
});
ofmt.forEach(function(f) { it('write ' + f, function() {
var aoa = [["SheetJS"],[5433795]];
var wb = X.utils.book_new(X.utils.aoa_to_sheet(aoa));
var newwb = X.read(X.write(wb, {type:"binary", bookType:f}), {type:"binary"});
assert.equal(get_cell(newwb.Sheets["Sheet1"], "A1").v, "SheetJS");
assert.equal(get_cell(newwb.Sheets["Sheet1"], "A2").v, 5433795);
}); });
;});
describe('corner cases', function() { describe('corner cases', function() {
it('output functions', function() { it('output functions', function() {
var ws = X.utils.aoa_to_sheet([ var ws = X.utils.aoa_to_sheet([