forked from sheetjs/sheetjs
unify stub cells with type z
- fixes #382 h/t @jugaltheshah @pimpelsang - fixes #333 h/t @xushuheng0623 @abhishek1234321 @mateuszkrzeszowiec - fixes #79 h/t @volodymyrl @elad
This commit is contained in:
parent
05185e13f2
commit
d3eaa62d45
@ -8,6 +8,7 @@ changes may not be included if they are not expected to break existing code.
|
||||
## Unreleased
|
||||
|
||||
* XLML property names are more closely mapped to the XLSX equivalent
|
||||
* Stub cells are now cell type `z`
|
||||
|
||||
## 0.9.2 (2017-03-13)
|
||||
|
||||
|
@ -477,6 +477,10 @@ dates in the local timezone. js-xlsx does not correct for this error.
|
||||
Type `s` is the String type. `v` should be explicitly stored as a string to
|
||||
avoid possible confusion.
|
||||
|
||||
Type `z` represents blank stub cells. These do not have any data or type, and
|
||||
are not processed by any of the core library functions. By default these cells
|
||||
will not be generated; the parser `cellStubs` option must be set to `true`.
|
||||
|
||||
### Formulae
|
||||
|
||||
The A1-style formula string is stored in the `f` field. Even though different
|
||||
@ -549,7 +553,7 @@ The exported `read` and `readFile` functions accept an options argument:
|
||||
| cellNF | false | Save number format string to the .z field |
|
||||
| cellStyles | false | Save style/theme info to the .s field |
|
||||
| cellDates | false | Store dates as type `d` (default is `n`) ** |
|
||||
| sheetStubs | false | Create cell objects for stub cells |
|
||||
| sheetStubs | false | Create cell objects of type `z` for stub cells |
|
||||
| sheetRows | 0 | If >0, read the first `sheetRows` rows ** |
|
||||
| bookDeps | false | If true, parse calculation chains |
|
||||
| bookFiles | false | If true, add raw files to book object ** |
|
||||
|
@ -315,6 +315,17 @@ function parse_MulRk(blob, length) {
|
||||
if(rkrecs.length != lastcol - col + 1) throw "MulRK length mismatch";
|
||||
return {r:rw, c:col, C:lastcol, rkrec:rkrecs};
|
||||
}
|
||||
/* 2.4.174 */
|
||||
function parse_MulBlank(blob, length) {
|
||||
var target = blob.l + length - 2;
|
||||
var rw = blob.read_shift(2), col = blob.read_shift(2);
|
||||
var ixfes = [];
|
||||
while(blob.l < target) ixfes.push(blob.read_shift(2));
|
||||
if(blob.l !== target) throw "MulBlank read error";
|
||||
var lastcol = blob.read_shift(2);
|
||||
if(ixfes.length != lastcol - col + 1) throw "MulBlank length mismatch";
|
||||
return {r:rw, c:col, C:lastcol, ixfe:ixfes};
|
||||
}
|
||||
|
||||
/* 2.5.20 2.5.249 TODO: interpret values here */
|
||||
function parse_CellStyleXF(blob, length, style) {
|
||||
@ -711,7 +722,6 @@ var parse_SXLI = parsenoop;
|
||||
var parse_SXPI = parsenoop;
|
||||
var parse_DocRoute = parsenoop;
|
||||
var parse_RecipName = parsenoop;
|
||||
var parse_MulBlank = parsenoop;
|
||||
var parse_SXDI = parsenoop;
|
||||
var parse_SXDB = parsenoop;
|
||||
var parse_SXFDB = parsenoop;
|
||||
|
@ -23,6 +23,7 @@ function get_cell_style(styles, cell, opts) {
|
||||
}
|
||||
|
||||
function safe_format(p, fmtid, fillid, opts) {
|
||||
if(p.t === 'z') return;
|
||||
if(p.t === 'd' && typeof p.v === 'string') p.v = new Date(p.v);
|
||||
try {
|
||||
if(p.t === 'e') p.w = p.w || BErr[p.v];
|
||||
|
@ -87,7 +87,7 @@ function parse_ws_xml_hlinks(s, data, rels) {
|
||||
var rng = safe_decode_range(val.ref);
|
||||
for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
|
||||
var addr = encode_cell({c:C,r:R});
|
||||
if(!s[addr]) s[addr] = {t:"stub",v:undefined};
|
||||
if(!s[addr]) s[addr] = {t:"z",v:undefined};
|
||||
s[addr].l = val;
|
||||
}
|
||||
}
|
||||
@ -126,7 +126,7 @@ function write_ws_xml_cols(ws, cols)/*:string*/ {
|
||||
}
|
||||
|
||||
function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
if(cell.v === undefined) return "";
|
||||
if(cell.v === undefined || cell.t === 'z') return "";
|
||||
var vv = "";
|
||||
var oldt = cell.t, oldv = cell.v;
|
||||
switch(cell.t) {
|
||||
@ -239,7 +239,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
|
||||
/* SCHEMA IS ACTUALLY INCORRECT HERE. IF A CELL HAS NO T, EMIT "" */
|
||||
if(tag.t === undefined && p.v === undefined) {
|
||||
if(!opts.sheetStubs) continue;
|
||||
p.t = "stub";
|
||||
p.t = "z";
|
||||
}
|
||||
else p.t = tag.t || "n";
|
||||
if(guess.s.c > idx) guess.s.c = idx;
|
||||
@ -251,7 +251,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
|
||||
sstr = strs[parseInt(p.v, 10)];
|
||||
if(typeof p.v == 'undefined') {
|
||||
if(!opts.sheetStubs) continue;
|
||||
p.t = "stub";
|
||||
p.t = 'z';
|
||||
}
|
||||
p.v = sstr.t;
|
||||
p.r = sstr.r;
|
||||
|
@ -324,7 +324,7 @@ function parse_ws_bin(data, opts, rels, wb)/*:Worksheet*/ {
|
||||
break;
|
||||
|
||||
case 'BrtCellBlank': if(!opts.sheetStubs) break;
|
||||
p = ({t:'s',v:undefined}/*:any*/);
|
||||
p = ({t:'z',v:undefined}/*:any*/);
|
||||
s[encode_col(C=val[0].c) + rr] = p;
|
||||
if(refguess.s.r > row.r) refguess.s.r = row.r;
|
||||
if(refguess.s.c > C) refguess.s.c = C;
|
||||
|
@ -58,6 +58,7 @@ function xlml_set_custprop(Custprops, Rn, cp, val/*:string*/) {
|
||||
}
|
||||
|
||||
function safe_format_xlml(cell/*:Cell*/, nf, o) {
|
||||
if(cell.t === 'z') return;
|
||||
try {
|
||||
if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
|
||||
else if(nf === "General") {
|
||||
@ -200,8 +201,17 @@ function parse_xlml_xml(d, opts)/*:Workbook*/ {
|
||||
var rr = r + (parseInt(cell.MergeDown,10)|0);
|
||||
mergecells.push({s:{c:c,r:r},e:{c:cc,r:rr}});
|
||||
}
|
||||
++c;
|
||||
if(cell.MergeAcross) c += +cell.MergeAcross;
|
||||
if(!opts.sheetStubs) { if(cell.MergeAcross) c = cc + 1; else ++c; }
|
||||
else if(cell.MergeAcross || cell.MergeDown) {
|
||||
/*:: if(!cc) cc = 0; if(!rr) rr = 0; */
|
||||
for(var cma = c; cma <= cc; ++cma) {
|
||||
for(var cmd = r; cmd <= rr; ++cmd) {
|
||||
if(cma > c || cmd > r) cursheet[encode_col(cma) + encode_row(cmd)] = {t:'z'};
|
||||
}
|
||||
}
|
||||
c = cc + 1;
|
||||
}
|
||||
else ++c;
|
||||
} else {
|
||||
cell = xlml_parsexmltagobj(Rn[0]);
|
||||
if(cell.Index) c = +cell.Index - 1;
|
||||
@ -756,6 +766,7 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
|
||||
|
||||
var t = "", p = "";
|
||||
switch(cell.t) {
|
||||
case 'z': return "";
|
||||
case 'n': t = 'Number'; p = String(cell.v); break;
|
||||
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
|
||||
case 'e': t = 'Error'; p = BErr[cell.v]; break;
|
||||
|
@ -53,6 +53,7 @@ function slurp(R, blob, length/*:number*/, opts) {
|
||||
}
|
||||
|
||||
function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
|
||||
if(p.t === 'z') return;
|
||||
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
|
||||
if(!p.XF) return;
|
||||
try {
|
||||
@ -354,6 +355,19 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
break;
|
||||
case 'Blank': if(options.sheetStubs) {
|
||||
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'};
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
} break;
|
||||
case 'MulBlank': if(options.sheetStubs) {
|
||||
for(var _j = val.c; _j <= val.C; ++_j) {
|
||||
var _ixfe = val.ixfe[_j-val.c];
|
||||
temp_val= {ixfe:_ixfe, XF:XFs[_ixfe], t:'z'};
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:_j, r:val.r}, temp_val, options);
|
||||
}
|
||||
} break;
|
||||
case 'RString':
|
||||
case 'Label': case 'BIFF2STR':
|
||||
temp_val=make_cell(val.val, val.ixfe, 's');
|
||||
@ -420,7 +434,6 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
case 'ColInfo': break; // TODO
|
||||
case 'Row': break; // TODO
|
||||
case 'DBCell': break; // TODO
|
||||
case 'MulBlank': break; // TODO
|
||||
case 'EntExU2': break; // TODO
|
||||
case 'SxView': break; // TODO
|
||||
case 'Sxvd': break; // TODO
|
||||
@ -435,7 +448,6 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
case 'Feat': break;
|
||||
case 'FeatHdr': case 'FeatHdr11': break;
|
||||
case 'Feature11': case 'Feature12': case 'List12': break;
|
||||
case 'Blank': break;
|
||||
case 'Country': country = val; break;
|
||||
case 'RecalcId': break;
|
||||
case 'DefaultRowHeight': case 'DxGCol': break; // TODO: htmlify
|
||||
|
@ -58,8 +58,10 @@ var parse_content_xml = (function() {
|
||||
rowtag = parsexmltag(Rn[0], false);
|
||||
if(rowtag['行号']) R = rowtag['行号'] - 1; else ++R;
|
||||
C = -1; break;
|
||||
case 'covered-table-cell': // 9.1.5 table:covered-table-cell
|
||||
++C; break; /* stub */
|
||||
case 'covered-table-cell': // 9.1.5 <table:covered-table-cell>
|
||||
++C;
|
||||
if(opts.sheetStubs) ws[encode_cell({r:R,c:C})] = {t:'z'};
|
||||
break; /* stub */
|
||||
case 'table-cell': case '数据':
|
||||
if(Rn[0].charAt(Rn[0].length-2) === '/') {
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
@ -121,7 +123,7 @@ var parse_content_xml = (function() {
|
||||
isstub = textpidx == 0;
|
||||
}
|
||||
if(textp) q.w = textp;
|
||||
if(!isstub || opts.cellStubs) {
|
||||
if(!isstub || opts.sheetStubs) {
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[encode_cell({r:R,c:++C})] = dup(q);
|
||||
|
@ -66,7 +66,7 @@ function safe_format_cell(cell/*:Cell*/, v/*:any*/) {
|
||||
}
|
||||
|
||||
function format_cell(cell/*:Cell*/, v/*:any*/) {
|
||||
if(cell == null || cell.t == null) return "";
|
||||
if(cell == null || cell.t == null || cell.t == 'z') return "";
|
||||
if(cell.w !== undefined) return cell.w;
|
||||
if(v === undefined) return safe_format_cell(cell, cell.v);
|
||||
return safe_format_cell(cell, v);
|
||||
@ -121,6 +121,7 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/){
|
||||
if(val === undefined || val.t === undefined) continue;
|
||||
v = val.v;
|
||||
switch(val.t){
|
||||
case 'z': continue;
|
||||
case 'e': continue;
|
||||
case 's': break;
|
||||
case 'b': case 'n': break;
|
||||
@ -187,6 +188,7 @@ function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
|
||||
if(y.indexOf(":") == -1) y = y + ":" + y;
|
||||
}
|
||||
if(x.f != null) val = x.f;
|
||||
else if(x.t == 'z') continue;
|
||||
else if(x.t == 'n' && x.v != null) val = "" + x.v;
|
||||
else if(x.t == 'b') val = x.v ? "TRUE" : "FALSE";
|
||||
else if(x.w !== undefined) val = "'" + x.w;
|
||||
|
14
test.js
14
test.js
@ -346,10 +346,18 @@ describe('parse options', function() {
|
||||
});
|
||||
});
|
||||
it('should generate sheet stubs when requested', function() {
|
||||
/* TODO: ODS/XLS/XML */
|
||||
[paths.mcxlsx, paths.mcxlsb /*, paths.mcods, paths.mcxls, paths.mcxml*/].forEach(function(p) {
|
||||
[paths.mcxlsx, paths.mcxlsb, paths.mcods, paths.mcxls, paths.mcxml].forEach(function(p) {
|
||||
var wb = X.readFile(p, {sheetStubs:true});
|
||||
assert(typeof wb.Sheets.Merge.A2.t !== 'undefined');
|
||||
assert(wb.Sheets.Merge.A2.t == 'z');
|
||||
});
|
||||
});
|
||||
it('should handle stub cells', function() {
|
||||
[paths.mcxlsx, paths.mcxlsb, paths.mcods, paths.mcxls, paths.mcxml].forEach(function(p) {
|
||||
var wb = X.readFile(p, {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);
|
||||
ofmt.forEach(function(f) { X.write(wb, {type:"binary", bookType:f}); });
|
||||
});
|
||||
});
|
||||
function checkcells(wb, A46, B26, C16, D2) {
|
||||
|
66
xlsx.flow.js
66
xlsx.flow.js
@ -3852,6 +3852,17 @@ function parse_MulRk(blob, length) {
|
||||
if(rkrecs.length != lastcol - col + 1) throw "MulRK length mismatch";
|
||||
return {r:rw, c:col, C:lastcol, rkrec:rkrecs};
|
||||
}
|
||||
/* 2.4.174 */
|
||||
function parse_MulBlank(blob, length) {
|
||||
var target = blob.l + length - 2;
|
||||
var rw = blob.read_shift(2), col = blob.read_shift(2);
|
||||
var ixfes = [];
|
||||
while(blob.l < target) ixfes.push(blob.read_shift(2));
|
||||
if(blob.l !== target) throw "MulBlank read error";
|
||||
var lastcol = blob.read_shift(2);
|
||||
if(ixfes.length != lastcol - col + 1) throw "MulBlank length mismatch";
|
||||
return {r:rw, c:col, C:lastcol, ixfe:ixfes};
|
||||
}
|
||||
|
||||
/* 2.5.20 2.5.249 TODO: interpret values here */
|
||||
function parse_CellStyleXF(blob, length, style) {
|
||||
@ -4248,7 +4259,6 @@ var parse_SXLI = parsenoop;
|
||||
var parse_SXPI = parsenoop;
|
||||
var parse_DocRoute = parsenoop;
|
||||
var parse_RecipName = parsenoop;
|
||||
var parse_MulBlank = parsenoop;
|
||||
var parse_SXDI = parsenoop;
|
||||
var parse_SXDB = parsenoop;
|
||||
var parse_SXFDB = parsenoop;
|
||||
@ -8219,6 +8229,7 @@ function get_cell_style(styles, cell, opts) {
|
||||
}
|
||||
|
||||
function safe_format(p, fmtid, fillid, opts) {
|
||||
if(p.t === 'z') return;
|
||||
if(p.t === 'd' && typeof p.v === 'string') p.v = new Date(p.v);
|
||||
try {
|
||||
if(p.t === 'e') p.w = p.w || BErr[p.v];
|
||||
@ -8340,7 +8351,7 @@ function parse_ws_xml_hlinks(s, data, rels) {
|
||||
var rng = safe_decode_range(val.ref);
|
||||
for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
|
||||
var addr = encode_cell({c:C,r:R});
|
||||
if(!s[addr]) s[addr] = {t:"stub",v:undefined};
|
||||
if(!s[addr]) s[addr] = {t:"z",v:undefined};
|
||||
s[addr].l = val;
|
||||
}
|
||||
}
|
||||
@ -8379,7 +8390,7 @@ function write_ws_xml_cols(ws, cols)/*:string*/ {
|
||||
}
|
||||
|
||||
function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
if(cell.v === undefined) return "";
|
||||
if(cell.v === undefined || cell.t === 'z') return "";
|
||||
var vv = "";
|
||||
var oldt = cell.t, oldv = cell.v;
|
||||
switch(cell.t) {
|
||||
@ -8492,7 +8503,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
|
||||
/* SCHEMA IS ACTUALLY INCORRECT HERE. IF A CELL HAS NO T, EMIT "" */
|
||||
if(tag.t === undefined && p.v === undefined) {
|
||||
if(!opts.sheetStubs) continue;
|
||||
p.t = "stub";
|
||||
p.t = "z";
|
||||
}
|
||||
else p.t = tag.t || "n";
|
||||
if(guess.s.c > idx) guess.s.c = idx;
|
||||
@ -8504,7 +8515,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
|
||||
sstr = strs[parseInt(p.v, 10)];
|
||||
if(typeof p.v == 'undefined') {
|
||||
if(!opts.sheetStubs) continue;
|
||||
p.t = "stub";
|
||||
p.t = 'z';
|
||||
}
|
||||
p.v = sstr.t;
|
||||
p.r = sstr.r;
|
||||
@ -8910,7 +8921,7 @@ function parse_ws_bin(data, opts, rels, wb)/*:Worksheet*/ {
|
||||
break;
|
||||
|
||||
case 'BrtCellBlank': if(!opts.sheetStubs) break;
|
||||
p = ({t:'s',v:undefined}/*:any*/);
|
||||
p = ({t:'z',v:undefined}/*:any*/);
|
||||
s[encode_col(C=val[0].c) + rr] = p;
|
||||
if(refguess.s.r > row.r) refguess.s.r = row.r;
|
||||
if(refguess.s.c > C) refguess.s.c = C;
|
||||
@ -9767,6 +9778,7 @@ function xlml_set_custprop(Custprops, Rn, cp, val/*:string*/) {
|
||||
}
|
||||
|
||||
function safe_format_xlml(cell/*:Cell*/, nf, o) {
|
||||
if(cell.t === 'z') return;
|
||||
try {
|
||||
if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
|
||||
else if(nf === "General") {
|
||||
@ -9909,8 +9921,17 @@ function parse_xlml_xml(d, opts)/*:Workbook*/ {
|
||||
var rr = r + (parseInt(cell.MergeDown,10)|0);
|
||||
mergecells.push({s:{c:c,r:r},e:{c:cc,r:rr}});
|
||||
}
|
||||
++c;
|
||||
if(cell.MergeAcross) c += +cell.MergeAcross;
|
||||
if(!opts.sheetStubs) { if(cell.MergeAcross) c = cc + 1; else ++c; }
|
||||
else if(cell.MergeAcross || cell.MergeDown) {
|
||||
/*:: if(!cc) cc = 0; if(!rr) rr = 0; */
|
||||
for(var cma = c; cma <= cc; ++cma) {
|
||||
for(var cmd = r; cmd <= rr; ++cmd) {
|
||||
if(cma > c || cmd > r) cursheet[encode_col(cma) + encode_row(cmd)] = {t:'z'};
|
||||
}
|
||||
}
|
||||
c = cc + 1;
|
||||
}
|
||||
else ++c;
|
||||
} else {
|
||||
cell = xlml_parsexmltagobj(Rn[0]);
|
||||
if(cell.Index) c = +cell.Index - 1;
|
||||
@ -10465,6 +10486,7 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
|
||||
|
||||
var t = "", p = "";
|
||||
switch(cell.t) {
|
||||
case 'z': return "";
|
||||
case 'n': t = 'Number'; p = String(cell.v); break;
|
||||
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
|
||||
case 'e': t = 'Error'; p = BErr[cell.v]; break;
|
||||
@ -10574,6 +10596,7 @@ function slurp(R, blob, length/*:number*/, opts) {
|
||||
}
|
||||
|
||||
function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
|
||||
if(p.t === 'z') return;
|
||||
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
|
||||
if(!p.XF) return;
|
||||
try {
|
||||
@ -10875,6 +10898,19 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
break;
|
||||
case 'Blank': if(options.sheetStubs) {
|
||||
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'};
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
} break;
|
||||
case 'MulBlank': if(options.sheetStubs) {
|
||||
for(var _j = val.c; _j <= val.C; ++_j) {
|
||||
var _ixfe = val.ixfe[_j-val.c];
|
||||
temp_val= {ixfe:_ixfe, XF:XFs[_ixfe], t:'z'};
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:_j, r:val.r}, temp_val, options);
|
||||
}
|
||||
} break;
|
||||
case 'RString':
|
||||
case 'Label': case 'BIFF2STR':
|
||||
temp_val=make_cell(val.val, val.ixfe, 's');
|
||||
@ -10941,7 +10977,6 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
case 'ColInfo': break; // TODO
|
||||
case 'Row': break; // TODO
|
||||
case 'DBCell': break; // TODO
|
||||
case 'MulBlank': break; // TODO
|
||||
case 'EntExU2': break; // TODO
|
||||
case 'SxView': break; // TODO
|
||||
case 'Sxvd': break; // TODO
|
||||
@ -10956,7 +10991,6 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
case 'Feat': break;
|
||||
case 'FeatHdr': case 'FeatHdr11': break;
|
||||
case 'Feature11': case 'Feature12': case 'List12': break;
|
||||
case 'Blank': break;
|
||||
case 'Country': country = val; break;
|
||||
case 'RecalcId': break;
|
||||
case 'DefaultRowHeight': case 'DxGCol': break; // TODO: htmlify
|
||||
@ -12673,8 +12707,10 @@ var parse_content_xml = (function() {
|
||||
rowtag = parsexmltag(Rn[0], false);
|
||||
if(rowtag['行号']) R = rowtag['行号'] - 1; else ++R;
|
||||
C = -1; break;
|
||||
case 'covered-table-cell': // 9.1.5 table:covered-table-cell
|
||||
++C; break; /* stub */
|
||||
case 'covered-table-cell': // 9.1.5 <table:covered-table-cell>
|
||||
++C;
|
||||
if(opts.sheetStubs) ws[encode_cell({r:R,c:C})] = {t:'z'};
|
||||
break; /* stub */
|
||||
case 'table-cell': case '数据':
|
||||
if(Rn[0].charAt(Rn[0].length-2) === '/') {
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
@ -12736,7 +12772,7 @@ var parse_content_xml = (function() {
|
||||
isstub = textpidx == 0;
|
||||
}
|
||||
if(textp) q.w = textp;
|
||||
if(!isstub || opts.cellStubs) {
|
||||
if(!isstub || opts.sheetStubs) {
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[encode_cell({r:R,c:++C})] = dup(q);
|
||||
@ -13571,7 +13607,7 @@ function safe_format_cell(cell/*:Cell*/, v/*:any*/) {
|
||||
}
|
||||
|
||||
function format_cell(cell/*:Cell*/, v/*:any*/) {
|
||||
if(cell == null || cell.t == null) return "";
|
||||
if(cell == null || cell.t == null || cell.t == 'z') return "";
|
||||
if(cell.w !== undefined) return cell.w;
|
||||
if(v === undefined) return safe_format_cell(cell, cell.v);
|
||||
return safe_format_cell(cell, v);
|
||||
@ -13626,6 +13662,7 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/){
|
||||
if(val === undefined || val.t === undefined) continue;
|
||||
v = val.v;
|
||||
switch(val.t){
|
||||
case 'z': continue;
|
||||
case 'e': continue;
|
||||
case 's': break;
|
||||
case 'b': case 'n': break;
|
||||
@ -13692,6 +13729,7 @@ function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
|
||||
if(y.indexOf(":") == -1) y = y + ":" + y;
|
||||
}
|
||||
if(x.f != null) val = x.f;
|
||||
else if(x.t == 'z') continue;
|
||||
else if(x.t == 'n' && x.v != null) val = "" + x.v;
|
||||
else if(x.t == 'b') val = x.v ? "TRUE" : "FALSE";
|
||||
else if(x.w !== undefined) val = "'" + x.w;
|
||||
|
65
xlsx.js
65
xlsx.js
@ -3800,6 +3800,17 @@ function parse_MulRk(blob, length) {
|
||||
if(rkrecs.length != lastcol - col + 1) throw "MulRK length mismatch";
|
||||
return {r:rw, c:col, C:lastcol, rkrec:rkrecs};
|
||||
}
|
||||
/* 2.4.174 */
|
||||
function parse_MulBlank(blob, length) {
|
||||
var target = blob.l + length - 2;
|
||||
var rw = blob.read_shift(2), col = blob.read_shift(2);
|
||||
var ixfes = [];
|
||||
while(blob.l < target) ixfes.push(blob.read_shift(2));
|
||||
if(blob.l !== target) throw "MulBlank read error";
|
||||
var lastcol = blob.read_shift(2);
|
||||
if(ixfes.length != lastcol - col + 1) throw "MulBlank length mismatch";
|
||||
return {r:rw, c:col, C:lastcol, ixfe:ixfes};
|
||||
}
|
||||
|
||||
/* 2.5.20 2.5.249 TODO: interpret values here */
|
||||
function parse_CellStyleXF(blob, length, style) {
|
||||
@ -4196,7 +4207,6 @@ var parse_SXLI = parsenoop;
|
||||
var parse_SXPI = parsenoop;
|
||||
var parse_DocRoute = parsenoop;
|
||||
var parse_RecipName = parsenoop;
|
||||
var parse_MulBlank = parsenoop;
|
||||
var parse_SXDI = parsenoop;
|
||||
var parse_SXDB = parsenoop;
|
||||
var parse_SXFDB = parsenoop;
|
||||
@ -8166,6 +8176,7 @@ function get_cell_style(styles, cell, opts) {
|
||||
}
|
||||
|
||||
function safe_format(p, fmtid, fillid, opts) {
|
||||
if(p.t === 'z') return;
|
||||
if(p.t === 'd' && typeof p.v === 'string') p.v = new Date(p.v);
|
||||
try {
|
||||
if(p.t === 'e') p.w = p.w || BErr[p.v];
|
||||
@ -8287,7 +8298,7 @@ function parse_ws_xml_hlinks(s, data, rels) {
|
||||
var rng = safe_decode_range(val.ref);
|
||||
for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
|
||||
var addr = encode_cell({c:C,r:R});
|
||||
if(!s[addr]) s[addr] = {t:"stub",v:undefined};
|
||||
if(!s[addr]) s[addr] = {t:"z",v:undefined};
|
||||
s[addr].l = val;
|
||||
}
|
||||
}
|
||||
@ -8326,7 +8337,7 @@ function write_ws_xml_cols(ws, cols) {
|
||||
}
|
||||
|
||||
function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
if(cell.v === undefined) return "";
|
||||
if(cell.v === undefined || cell.t === 'z') return "";
|
||||
var vv = "";
|
||||
var oldt = cell.t, oldv = cell.v;
|
||||
switch(cell.t) {
|
||||
@ -8439,7 +8450,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
|
||||
/* SCHEMA IS ACTUALLY INCORRECT HERE. IF A CELL HAS NO T, EMIT "" */
|
||||
if(tag.t === undefined && p.v === undefined) {
|
||||
if(!opts.sheetStubs) continue;
|
||||
p.t = "stub";
|
||||
p.t = "z";
|
||||
}
|
||||
else p.t = tag.t || "n";
|
||||
if(guess.s.c > idx) guess.s.c = idx;
|
||||
@ -8451,7 +8462,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
|
||||
sstr = strs[parseInt(p.v, 10)];
|
||||
if(typeof p.v == 'undefined') {
|
||||
if(!opts.sheetStubs) continue;
|
||||
p.t = "stub";
|
||||
p.t = 'z';
|
||||
}
|
||||
p.v = sstr.t;
|
||||
p.r = sstr.r;
|
||||
@ -8857,7 +8868,7 @@ function parse_ws_bin(data, opts, rels, wb) {
|
||||
break;
|
||||
|
||||
case 'BrtCellBlank': if(!opts.sheetStubs) break;
|
||||
p = ({t:'s',v:undefined});
|
||||
p = ({t:'z',v:undefined});
|
||||
s[encode_col(C=val[0].c) + rr] = p;
|
||||
if(refguess.s.r > row.r) refguess.s.r = row.r;
|
||||
if(refguess.s.c > C) refguess.s.c = C;
|
||||
@ -9712,6 +9723,7 @@ function xlml_set_custprop(Custprops, Rn, cp, val) {
|
||||
}
|
||||
|
||||
function safe_format_xlml(cell, nf, o) {
|
||||
if(cell.t === 'z') return;
|
||||
try {
|
||||
if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
|
||||
else if(nf === "General") {
|
||||
@ -9854,8 +9866,16 @@ function parse_xlml_xml(d, opts) {
|
||||
var rr = r + (parseInt(cell.MergeDown,10)|0);
|
||||
mergecells.push({s:{c:c,r:r},e:{c:cc,r:rr}});
|
||||
}
|
||||
++c;
|
||||
if(cell.MergeAcross) c += +cell.MergeAcross;
|
||||
if(!opts.sheetStubs) { if(cell.MergeAcross) c = cc + 1; else ++c; }
|
||||
else if(cell.MergeAcross || cell.MergeDown) {
|
||||
for(var cma = c; cma <= cc; ++cma) {
|
||||
for(var cmd = r; cmd <= rr; ++cmd) {
|
||||
if(cma > c || cmd > r) cursheet[encode_col(cma) + encode_row(cmd)] = {t:'z'};
|
||||
}
|
||||
}
|
||||
c = cc + 1;
|
||||
}
|
||||
else ++c;
|
||||
} else {
|
||||
cell = xlml_parsexmltagobj(Rn[0]);
|
||||
if(cell.Index) c = +cell.Index - 1;
|
||||
@ -10409,6 +10429,7 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){
|
||||
|
||||
var t = "", p = "";
|
||||
switch(cell.t) {
|
||||
case 'z': return "";
|
||||
case 'n': t = 'Number'; p = String(cell.v); break;
|
||||
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
|
||||
case 'e': t = 'Error'; p = BErr[cell.v]; break;
|
||||
@ -10518,6 +10539,7 @@ function slurp(R, blob, length, opts) {
|
||||
}
|
||||
|
||||
function safe_format_xf(p, opts, date1904) {
|
||||
if(p.t === 'z') return;
|
||||
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
|
||||
if(!p.XF) return;
|
||||
try {
|
||||
@ -10819,6 +10841,19 @@ function parse_workbook(blob, options) {
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
break;
|
||||
case 'Blank': if(options.sheetStubs) {
|
||||
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'};
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
} break;
|
||||
case 'MulBlank': if(options.sheetStubs) {
|
||||
for(var _j = val.c; _j <= val.C; ++_j) {
|
||||
var _ixfe = val.ixfe[_j-val.c];
|
||||
temp_val= {ixfe:_ixfe, XF:XFs[_ixfe], t:'z'};
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:_j, r:val.r}, temp_val, options);
|
||||
}
|
||||
} break;
|
||||
case 'RString':
|
||||
case 'Label': case 'BIFF2STR':
|
||||
temp_val=make_cell(val.val, val.ixfe, 's');
|
||||
@ -10885,7 +10920,6 @@ function parse_workbook(blob, options) {
|
||||
case 'ColInfo': break; // TODO
|
||||
case 'Row': break; // TODO
|
||||
case 'DBCell': break; // TODO
|
||||
case 'MulBlank': break; // TODO
|
||||
case 'EntExU2': break; // TODO
|
||||
case 'SxView': break; // TODO
|
||||
case 'Sxvd': break; // TODO
|
||||
@ -10900,7 +10934,6 @@ function parse_workbook(blob, options) {
|
||||
case 'Feat': break;
|
||||
case 'FeatHdr': case 'FeatHdr11': break;
|
||||
case 'Feature11': case 'Feature12': case 'List12': break;
|
||||
case 'Blank': break;
|
||||
case 'Country': country = val; break;
|
||||
case 'RecalcId': break;
|
||||
case 'DefaultRowHeight': case 'DxGCol': break; // TODO: htmlify
|
||||
@ -12617,8 +12650,10 @@ var parse_content_xml = (function() {
|
||||
rowtag = parsexmltag(Rn[0], false);
|
||||
if(rowtag['行号']) R = rowtag['行号'] - 1; else ++R;
|
||||
C = -1; break;
|
||||
case 'covered-table-cell': // 9.1.5 table:covered-table-cell
|
||||
++C; break; /* stub */
|
||||
case 'covered-table-cell': // 9.1.5 <table:covered-table-cell>
|
||||
++C;
|
||||
if(opts.sheetStubs) ws[encode_cell({r:R,c:C})] = {t:'z'};
|
||||
break; /* stub */
|
||||
case 'table-cell': case '数据':
|
||||
if(Rn[0].charAt(Rn[0].length-2) === '/') {
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
@ -12680,7 +12715,7 @@ var parse_content_xml = (function() {
|
||||
isstub = textpidx == 0;
|
||||
}
|
||||
if(textp) q.w = textp;
|
||||
if(!isstub || opts.cellStubs) {
|
||||
if(!isstub || opts.sheetStubs) {
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[encode_cell({r:R,c:++C})] = dup(q);
|
||||
@ -13507,7 +13542,7 @@ function safe_format_cell(cell, v) {
|
||||
}
|
||||
|
||||
function format_cell(cell, v) {
|
||||
if(cell == null || cell.t == null) return "";
|
||||
if(cell == null || cell.t == null || cell.t == 'z') return "";
|
||||
if(cell.w !== undefined) return cell.w;
|
||||
if(v === undefined) return safe_format_cell(cell, cell.v);
|
||||
return safe_format_cell(cell, v);
|
||||
@ -13562,6 +13597,7 @@ function sheet_to_json(sheet, opts){
|
||||
if(val === undefined || val.t === undefined) continue;
|
||||
v = val.v;
|
||||
switch(val.t){
|
||||
case 'z': continue;
|
||||
case 'e': continue;
|
||||
case 's': break;
|
||||
case 'b': case 'n': break;
|
||||
@ -13628,6 +13664,7 @@ function sheet_to_formulae(sheet) {
|
||||
if(y.indexOf(":") == -1) y = y + ":" + y;
|
||||
}
|
||||
if(x.f != null) val = x.f;
|
||||
else if(x.t == 'z') continue;
|
||||
else if(x.t == 'n' && x.v != null) val = "" + x.v;
|
||||
else if(x.t == 'b') val = x.v ? "TRUE" : "FALSE";
|
||||
else if(x.w !== undefined) val = "'" + x.w;
|
||||
|
Loading…
Reference in New Issue
Block a user