forked from sheetjs/sheetjs
Formula write support
- XLSX/XLML/ODS/CSV formula write - XLS Array/Formula record parsing - ODS to/from CSF formula conversion - XLML parse negative dates - formula multiformat and roundtrip tests - update SSF Closes issues: - closes #549 h/t @omershelef - closes #306 h/t @akaustel - closes #300 h/t @wawanopoulos - closes #152 h/t @florf - closes #103 h/t @christocracy - closes #112 h/t @johnyesberg - closes #307 h/t @alexanderknapstein
This commit is contained in:
parent
ea1873e572
commit
5a3774e36e
@ -484,7 +484,7 @@ will not be generated; the parser `sheetStubs` option must be set to `true`.
|
||||
### Formulae
|
||||
|
||||
The A1-style formula string is stored in the `f` field. Even though different
|
||||
file formats store the formulae in different ways, the formats are converted.
|
||||
file formats store the formulae in different ways, the formats are translated.
|
||||
|
||||
Shared formulae are decompressed and each cell has the correct formula.
|
||||
|
||||
|
@ -310,7 +310,18 @@ function hashq(str/*:string*/)/*:string*/ {
|
||||
return o;
|
||||
}
|
||||
function rnd(val/*:number*/, d/*:number*/)/*:string*/ { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
|
||||
function dec(val/*:number*/, d/*:number*/)/*:number*/ { return Math.round((val-Math.floor(val))*Math.pow(10,d)); }
|
||||
function dec(val/*:number*/, d/*:number*/)/*:number*/ {
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 0;
|
||||
}
|
||||
return Math.round((val-Math.floor(val))*Math.pow(10,d));
|
||||
}
|
||||
function carry(val/*:number*/, d/*:number*/)/*:number*/ {
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
function flr(val/*:number*/)/*:string*/ { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); }
|
||||
function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
|
||||
if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
|
||||
@ -332,8 +343,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
|
||||
if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign);
|
||||
if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
|
||||
if((r = fmt.match(dec1))) {
|
||||
// $FlowIgnore
|
||||
o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
|
||||
o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", /*::(*/r/*::||[""])*/[1].length-$1.length); });
|
||||
return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
|
||||
}
|
||||
fmt = fmt.replace(/^#+([0.])/, "$1");
|
||||
@ -342,7 +352,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
|
||||
}
|
||||
if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify(pad0r(aval,0));
|
||||
if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
|
||||
return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val))) + "." + pad0(dec(val, r[1].length),r[1].length);
|
||||
return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length);
|
||||
}
|
||||
if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
|
||||
if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
|
||||
|
@ -6,6 +6,16 @@ function ods_to_csf_formula(f/*:string*/)/*:string*/ {
|
||||
f = f.substr(1);
|
||||
if(f.charCodeAt(0) == 61) f = f.substr(1);
|
||||
}
|
||||
f = f.replace(/COM\.MICROSOFT\./g, "");
|
||||
/* Part 3 Section 5.8 References */
|
||||
return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, "");
|
||||
f = f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, function($$, $1) { return $1.replace(/\./g,""); });
|
||||
/* TODO: something other than this */
|
||||
f = f.replace(/\[.(#[A-Z]*[?!])\]/g, "$1");
|
||||
return f.replace(/[;~]/g,",").replace(/\|/g,";");
|
||||
}
|
||||
|
||||
function csf_to_ods_formula(f/*:string*/)/*:string*/ {
|
||||
var o = "of:=" + f.replace(crefregex, "$1[.$2$3$4$5]").replace(/\]:\[/g,":");
|
||||
/* TODO: something other than this */
|
||||
return o.replace(/;/g, "|").replace(/,/g,";");
|
||||
}
|
||||
|
@ -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 || cell.t === 'z') return "";
|
||||
if(cell.v === undefined && cell.f === undefined || cell.t === 'z') return "";
|
||||
var vv = "";
|
||||
var oldt = cell.t, oldv = cell.v;
|
||||
switch(cell.t) {
|
||||
@ -152,7 +152,7 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
case 'd': o.t = "d"; break;
|
||||
case 'b': o.t = "b"; break;
|
||||
case 'e': o.t = "e"; break;
|
||||
default:
|
||||
default: if(cell.v == null) { delete cell.t; break; }
|
||||
if(opts.bookSST) {
|
||||
v = writetag('v', ''+get_sst_id(opts.Strings, cell.v));
|
||||
o.t = "s"; break;
|
||||
@ -160,6 +160,10 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
o.t = "str"; break;
|
||||
}
|
||||
if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; }
|
||||
if(cell.f) {
|
||||
var ff = cell.F && cell.F.substr(0, ref.length) == ref ? {t:"array", ref:cell.F} : null;
|
||||
v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : "");
|
||||
}
|
||||
return writextag('c', v, o);
|
||||
}
|
||||
|
||||
@ -215,7 +219,8 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
|
||||
if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
|
||||
if(opts.cellFormula) {
|
||||
if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') {
|
||||
p.f=unescapexml(utf8read(cref[1]));
|
||||
/* TODO: match against XLSXFutureFunctions */
|
||||
p.f=unescapexml(utf8read(cref[1])).replace(/_xlfn\./,"");
|
||||
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
|
||||
p.F = (d.match(refregex)||[])[1];
|
||||
if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
|
||||
|
@ -108,7 +108,7 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
|
||||
case 'DateTime':
|
||||
cell.v = (Date.parse(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
|
||||
if(cell.v !== cell.v) cell.v = unescapexml(xml);
|
||||
else if(cell.v >= 1 && cell.v<60) cell.v = cell.v -1;
|
||||
else if(cell.v<60) cell.v = cell.v -1;
|
||||
if(!nf || nf == "General") nf = "yyyy-mm-dd";
|
||||
/* falls through */
|
||||
case 'Number':
|
||||
@ -250,6 +250,7 @@ function parse_xlml_xml(d, opts)/*:Workbook*/ {
|
||||
sheetname = unescapexml(tmp.Name);
|
||||
cursheet = {};
|
||||
mergecells = [];
|
||||
arrayf = [];
|
||||
}
|
||||
break;
|
||||
case 'Table':
|
||||
@ -759,10 +760,14 @@ function write_sty_xlml(wb, opts)/*:string*/ {
|
||||
}
|
||||
/* TODO */
|
||||
function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
|
||||
if(!cell || cell.v === undefined) return "<Cell></Cell>";
|
||||
if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>";
|
||||
|
||||
var attr = {};
|
||||
if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr));
|
||||
if(cell.F && cell.F.substr(0, ref.length) == ref) {
|
||||
var end = decode_cell(cell.F.substr(ref.length + 1));
|
||||
attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]");
|
||||
}
|
||||
|
||||
if(ws['!merges']) {
|
||||
var marr = ws['!merges'];
|
||||
@ -780,9 +785,9 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
|
||||
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
|
||||
case 'e': t = 'Error'; p = BErr[cell.v]; break;
|
||||
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); break;
|
||||
case 's': t = 'String'; p = escapexml(cell.v||""); break;
|
||||
case 's': t = 'String'; p = escapexml(cell.v||""); break;
|
||||
}
|
||||
var m = '<Data ss:Type="' + t + '">' + p + '</Data>';
|
||||
var m = '<Data ss:Type="' + t + '">' + (cell.v != null ? p : "") + '</Data>';
|
||||
|
||||
return writextag("Cell", m, attr);
|
||||
}
|
||||
|
@ -122,6 +122,19 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1;
|
||||
if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1;
|
||||
}
|
||||
if(options.cellFormula && line.f) {
|
||||
for(var afi = 0; afi < array_formulae.length; ++afi) {
|
||||
if(array_formulae[afi][0].s.c > cell.c) continue;
|
||||
if(array_formulae[afi][0].s.r > cell.r) continue;
|
||||
if(array_formulae[afi][0].e.c < cell.c) continue;
|
||||
if(array_formulae[afi][0].e.r < cell.r) continue;
|
||||
line.F = encode_range(array_formulae[afi][0]);
|
||||
if(array_formulae[afi][0].s.c != cell.c) delete line.f;
|
||||
if(array_formulae[afi][0].s.r != cell.r) delete line.f;
|
||||
if(line.f) line.f = "" + stringify_formula(array_formulae[afi][1], range, cell, supbooks, opts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(options.sheetRows && lastcell.r >= options.sheetRows) cell_valid = false;
|
||||
else out[last_cell] = line;
|
||||
};
|
||||
@ -274,7 +287,9 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
else cur_sheet = (Directory[s] || {name:""}).name;
|
||||
mergecells = [];
|
||||
objects = [];
|
||||
array_formulae = []; opts.arrayf = array_formulae;
|
||||
} break;
|
||||
|
||||
case 'Number': case 'BIFF2NUM': case 'BIFF2INT': {
|
||||
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:'n'};
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
@ -299,44 +314,43 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
}
|
||||
} break;
|
||||
case 'Formula': {
|
||||
switch(val.val) {
|
||||
case 'String': last_formula = val; break;
|
||||
case 'Array Formula': throw "Array Formula unsupported";
|
||||
default:
|
||||
temp_val = ({v:val.val, ixfe:val.cell.ixfe, t:val.tt}/*:any*/);
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) {
|
||||
var _f = val.formula;
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = (out[_fe] || {}).F;
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(val.cell, temp_val, options);
|
||||
last_formula = val;
|
||||
if(val.val == 'String') { last_formula = val; break; }
|
||||
temp_val = ({v:val.val, ixfe:val.cell.ixfe, t:val.tt}/*:any*/);
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) {
|
||||
var _f = val.formula;
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = (out[_fe] || {}).F;
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(val.cell, temp_val, options);
|
||||
last_formula = val;
|
||||
} break;
|
||||
case 'String': {
|
||||
if(last_formula) {
|
||||
if(last_formula) { /* technically always true */
|
||||
last_formula.val = val;
|
||||
temp_val = ({v:last_formula.val, ixfe:last_formula.cell.ixfe, t:'s'}/*:any*/);
|
||||
temp_val = ({v:val, ixfe:last_formula.cell.ixfe, t:'s'}/*:any*/);
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
if(options.cellFormula) {
|
||||
temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
}
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(last_formula.cell, temp_val, options);
|
||||
last_formula = null;
|
||||
}
|
||||
} else throw new Error("String record expects Formula");
|
||||
} break;
|
||||
case 'Array': {
|
||||
array_formulae.push(val);
|
||||
if(options.cellFormula && out[last_cell]) {
|
||||
var _arraystart = encode_cell(val[0].s);
|
||||
if(options.cellFormula && out[_arraystart]) {
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
if(!last_cell || !out[last_cell]) break; /* technically unreachable */
|
||||
out[last_cell].f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
out[last_cell].F = encode_range(val[0]);
|
||||
if(!_arraystart || !out[_arraystart]) break;
|
||||
out[_arraystart].f = ""+stringify_formula(val[1], range, val[0], supbooks, opts);
|
||||
out[_arraystart].F = encode_range(val[0]);
|
||||
}
|
||||
} break;
|
||||
case 'ShrFmla': {
|
||||
@ -375,6 +389,7 @@ 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 'Dimensions': {
|
||||
if(file_depth === 1) range = val; /* TODO: stack */
|
||||
} break;
|
||||
|
@ -57,20 +57,20 @@ function write_BIFF2LABEL(r, c, val) {
|
||||
}
|
||||
|
||||
function write_ws_biff_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) {
|
||||
switch(cell.t) {
|
||||
if(cell.v != null) switch(cell.t) {
|
||||
case 'n':
|
||||
if((cell.v == (cell.v|0)) && (cell.v >= 0) && (cell.v < 65536))
|
||||
write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, cell.v));
|
||||
else
|
||||
write_biff_rec(ba, 0x0003, write_BIFF2NUMBER(R,C, cell.v));
|
||||
break;
|
||||
case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); break;
|
||||
return;
|
||||
case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
|
||||
/* TODO: codepage, sst */
|
||||
case 's': case 'str':
|
||||
write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v));
|
||||
break;
|
||||
default: write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
|
||||
return;
|
||||
}
|
||||
write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
|
||||
}
|
||||
|
||||
function write_biff_ws(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
|
@ -78,6 +78,7 @@ var parse_content_xml = (function() {
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:""*/}/*:any*/);
|
||||
if(opts.cellFormula) {
|
||||
if(ctag.formula) ctag.formula = unescapexml(ctag.formula);
|
||||
if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
|
||||
mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
|
||||
mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
|
||||
|
@ -27,11 +27,22 @@ var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
}
|
||||
if(skip) { o.push(covered_cell_xml); continue; }
|
||||
var ref = encode_cell({r:R, c:C}), cell = ws[ref];
|
||||
var fmla = "";
|
||||
if(cell && cell.f) {
|
||||
fmla = ' table:formula="' + escapexml(csf_to_ods_formula(cell.f)) + '"';
|
||||
if(cell.F) {
|
||||
if(cell.F.substr(0, ref.length) == ref) {
|
||||
var _Fref = decode_range(cell.F);
|
||||
fmla += ' table:number-matrix-columns-spanned="' + (_Fref.e.c - _Fref.s.c + 1)+ '"';
|
||||
fmla += ' table:number-matrix-rows-spanned="' + (_Fref.e.r - _Fref.s.r + 1) + '"';
|
||||
} else fmla = "";
|
||||
}
|
||||
}
|
||||
if(cell) switch(cell.t) {
|
||||
case 'b': o.push(cell_begin + mxml + vt + '"boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '">' + p_begin + (cell.v ? 'TRUE' : 'FALSE') + p_end + cell_end); break;
|
||||
case 'n': o.push(cell_begin + mxml + vt + '"float" office:value="' + cell.v + '">' + p_begin + (cell.w||cell.v) + p_end + cell_end); break;
|
||||
case 's': case 'str': o.push(cell_begin + mxml + vt + '"string">' + p_begin + escapexml(cell.v) + p_end + cell_end); break;
|
||||
case 'd': o.push(cell_begin + mxml + vt + '"date" office:date-value="' + (new Date(cell.v).toISOString()) + '">' + p_begin + (cell.w||(new Date(cell.v).toISOString())) + p_end + cell_end); break;
|
||||
case 'b': o.push(cell_begin + mxml + vt + '"boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"' + fmla + '>' + p_begin + (cell.v ? 'TRUE' : 'FALSE') + p_end + cell_end); break;
|
||||
case 'n': o.push(cell_begin + mxml + vt + '"float" office:value="' + cell.v + '"' + fmla + '>' + p_begin + (cell.w||cell.v) + p_end + cell_end); break;
|
||||
case 's': case 'str': o.push(cell_begin + mxml + vt + '"string"' + fmla + '>' + p_begin + escapexml(cell.v) + p_end + cell_end); break;
|
||||
case 'd': o.push(cell_begin + mxml + vt + '"date" office:date-value="' + (new Date(cell.v).toISOString()) + '"' + fmla + '>' + p_begin + (cell.w||(new Date(cell.v).toISOString())) + p_end + cell_end); break;
|
||||
//case 'e':
|
||||
default: o.push(null_cell_xml);
|
||||
} else o.push(null_cell_xml);
|
||||
@ -46,7 +57,7 @@ var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
var o = [XML_HEADER];
|
||||
/* 3.1.3.2 */
|
||||
if(opts.bookType == "fods") o.push('<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">');
|
||||
else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
|
||||
else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2">\n'); // TODO
|
||||
o.push(' <office:body>\n');
|
||||
o.push(' <office:spreadsheet>\n');
|
||||
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts));
|
||||
|
@ -156,9 +156,15 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
|
||||
rr = encode_row(R);
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
val = sheet[cols[C] + rr];
|
||||
txt = val !== undefined ? ''+format_cell(val) : "";
|
||||
for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {
|
||||
txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
|
||||
if(val == null) txt = "";
|
||||
else if(val.v != null) {
|
||||
txt = ''+format_cell(val);
|
||||
for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {
|
||||
txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
|
||||
} else if(val.f != null && !val.F) {
|
||||
txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"';
|
||||
} else txt = "";
|
||||
/* NOTE: Excel CSV does not support array formulae */
|
||||
row += (C === r.s.c ? "" : FS) + txt;
|
||||
}
|
||||
out += row + RS;
|
||||
|
@ -10,13 +10,19 @@ cell_style_simple .xls .xlsb .xlsx .xml
|
||||
comments_stress_test .xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml
|
||||
# yes-csv
|
||||
custom_properties .xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml
|
||||
# no-formula (defined names)
|
||||
defined_names_simple .xls .xlsb .xlsx .xml
|
||||
#formula_stress_test .xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml
|
||||
# yes-formula
|
||||
# no-csv (randbetween) note: ODS does not support many XLSX functions
|
||||
formula_stress_test .xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml
|
||||
# yes-csv
|
||||
formulae_test_simple .xls .xlsb .xlsx .xml
|
||||
hyperlink_stress_test_2011 .xls .xlsb .xlsx .xml
|
||||
#large_strings .xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml
|
||||
merge_cells .xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml
|
||||
# no-formula (defined names)
|
||||
named_ranges_2011 .xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml
|
||||
# yes-formula
|
||||
# no-csv (macro serialization in xml)
|
||||
number_format .xls .xlsb .xlsm .xls.xml .xlsb.xml .xlsm.xml
|
||||
number_format_entities .xls .xlsb .xlsx .xml
|
||||
|
34
test.js
34
test.js
@ -838,9 +838,7 @@ function seq(end, start) {
|
||||
}
|
||||
|
||||
describe('roundtrip features', function() {
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
});
|
||||
var bef = (function() { X = require(modp); });
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
describe('should parse core properties and custom properties', function() {
|
||||
@ -907,14 +905,18 @@ describe('roundtrip features', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('xls to xlsx conversions', function() { [
|
||||
['XLS', 'formula_stress_test.xls'],
|
||||
['XML', 'formula_stress_test.xls.xml']
|
||||
describe('should preserve formulae', function() { [
|
||||
['xlml', paths.fstxml],
|
||||
['xlsx', paths.fstxlsx],
|
||||
['ods', paths.fstods]
|
||||
].forEach(function(w) {
|
||||
it('should be able to write ' + w[0] + ' files', function() {
|
||||
var xls = X.readFile('./test_files/' + w[1], {cellNF:true});
|
||||
X.writeFile(xls, './tmp/' + w[1] + '.xlsx', {bookSST:true});
|
||||
X.writeFile(xls, './tmp/' + w[1] + '.xlsb', {bookSST:true});
|
||||
it(w[0], function() {
|
||||
var wb1 = X.readFile(w[1], {cellFormula:true});
|
||||
if(w[0] == 'ods') X.writeFile(wb1, "./tmp/_.ods", {bookType:"ods"});
|
||||
var wb2 = X.read(X.write(wb1, {bookType:w[0], type:"buffer"}), {cellFormula:true, type:"buffer"});
|
||||
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") );
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1209,7 +1211,7 @@ describe('encryption', function() {
|
||||
describe('multiformat tests', function() {
|
||||
var mfopts = opts;
|
||||
var mft = fs.readFileSync('multiformat.lst','utf-8').split("\n");
|
||||
var csv = true;
|
||||
var csv = true, formulae = false;
|
||||
mft.forEach(function(x) {
|
||||
if(x[0]!="#") describe('MFT ' + x, function() {
|
||||
var fil = {}, f = [], r = x.split(/\s+/);
|
||||
@ -1239,10 +1241,20 @@ mft.forEach(function(x) {
|
||||
cmparr(f.map(function(x) { return X.utils.sheet_to_csv(x.Sheets[name]); }));
|
||||
});
|
||||
} : null);
|
||||
it('should have the same formulae', formulae ? function() {
|
||||
cmparr(f.map(function(x) { return x.SheetNames; }));
|
||||
var names = f[0].SheetNames;
|
||||
names.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;
|
||||
case "yes-csv": csv = true; break;
|
||||
case "no-formula": formulae = false; break;
|
||||
case "yes-formula": formulae = true; break;
|
||||
}});
|
||||
});
|
||||
});
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 8ab3308622f83ac47a0ee584d61e11357b01f925
|
||||
Subproject commit e0b7060b10ef972ad48869faa4efffd089e1a428
|
245
tests.lst
245
tests.lst
@ -29,17 +29,6 @@ sushi.xlsb
|
||||
text_and_numbers.xlsb
|
||||
time_stress_test_1.xlsb.pending
|
||||
xlsx-stream-d-date-cell.xlsb
|
||||
2013/apachepoi_29982.xls.xlsb
|
||||
2013/apachepoi_43251.xls.xlsb
|
||||
2013/apachepoi_44593.xls.xlsb ## xlsb loop timeout
|
||||
2013/apachepoi_44643.xls.xlsb
|
||||
2013/apachepoi_44958.xls.xlsb
|
||||
2013/apachepoi_46136-NoWarnings.xls.xlsb
|
||||
2013/apachepoi_48968.xls.xlsb
|
||||
2013/apachepoi_50939.xls.xlsb
|
||||
2013/apachepoi_54016.xls.xlsb
|
||||
2013/apachepoi_ReadOnlyRecommended.xls.xlsb
|
||||
2013/apachepoi_testArraysAndTables.xls.xlsb
|
||||
AutoFilter.xlsx
|
||||
ErrorTypes.xlsx
|
||||
LONumbers-2010.xlsx
|
||||
@ -199,6 +188,7 @@ apachepoi_DataTableCities.xlsx
|
||||
apachepoi_DataValidationEvaluations.xlsx
|
||||
apachepoi_DataValidations-49244.xlsx
|
||||
# apachepoi_DateFormatTests.xlsx # xlml
|
||||
apachepoi_DateFormatTests.xlsx.xlsx
|
||||
apachepoi_ElapsedFormatTests.xlsx
|
||||
apachepoi_ExcelTables.xlsx
|
||||
apachepoi_ForShifting.xlsx
|
||||
@ -249,6 +239,7 @@ apachepoi_WithTwoCharts.xlsx
|
||||
apachepoi_WithVariousData.xlsx
|
||||
apachepoi_XSSFSheet.copyRows.xlsx
|
||||
apachepoi_atp.xlsx
|
||||
apachepoi_bug60858.xlsx
|
||||
apachepoi_chartTitle_noTitle.xlsx
|
||||
apachepoi_chartTitle_withTitle.xlsx
|
||||
apachepoi_chart_sheet.xlsx.pending
|
||||
@ -362,6 +353,8 @@ openpyxl_r_null_file.xlsx.pending
|
||||
phonetic_text.xlsx
|
||||
pivot_table_named_range.xlsx
|
||||
rich_text_stress.xlsx
|
||||
roo-xls_numbers1.xlsx
|
||||
roo-xls_type_excel.xlsx
|
||||
roo_1900_base.xlsx
|
||||
roo_1904_base.xlsx
|
||||
roo_Bibelbund.xlsx
|
||||
@ -404,6 +397,44 @@ roo_whitespace.xlsx
|
||||
roo_x000D.xlsx
|
||||
roo_zero-padded-number.xlsx
|
||||
smart_tags_2007.xlsx
|
||||
spout-xlsx_attack_billion_laughs.xlsx
|
||||
spout-xlsx_attack_quadratic_blowup.xlsx
|
||||
# spout-xlsx_file_corrupted.xlsx
|
||||
spout-xlsx_file_with_no_sheets_in_workbook_xml.xlsx
|
||||
# spout-xlsx_file_with_sheet_xml_not_matching_content_types.xlsx
|
||||
spout-xlsx_one_sheet_with_inline_strings.xlsx
|
||||
spout-xlsx_one_sheet_with_invalid_xml_characters.xlsx
|
||||
spout-xlsx_one_sheet_with_shared_multiline_strings.xlsx
|
||||
spout-xlsx_one_sheet_with_shared_strings.xlsx
|
||||
spout-xlsx_one_sheet_with_shared_strings_containing_text_and_hyperlink_in_same_cell.xlsx
|
||||
spout-xlsx_one_sheet_with_shared_strings_missing_unique_count.xlsx
|
||||
spout-xlsx_one_sheet_with_shared_strings_missing_unique_count_and_count.xlsx
|
||||
spout-xlsx_sheet_with_all_cell_types.xlsx
|
||||
spout-xlsx_sheet_with_custom_date_formats_and_no_apply_number_format.xlsx
|
||||
spout-xlsx_sheet_with_dates_and_times.xlsx
|
||||
spout-xlsx_sheet_with_different_numeric_value_dates.xlsx
|
||||
spout-xlsx_sheet_with_different_numeric_value_times.xlsx
|
||||
spout-xlsx_sheet_with_dimensions_and_empty_cells.xlsx
|
||||
spout-xlsx_sheet_with_empty_cells.xlsx
|
||||
spout-xlsx_sheet_with_empty_rows_and_missing_row_index.xlsx
|
||||
spout-xlsx_sheet_with_empty_shared_string.xlsx
|
||||
spout-xlsx_sheet_with_formulas.xlsx
|
||||
spout-xlsx_sheet_with_lots_of_shared_strings.xlsx
|
||||
spout-xlsx_sheet_with_missing_cell_reference.xlsx
|
||||
spout-xlsx_sheet_with_no_cells.xlsx
|
||||
spout-xlsx_sheet_with_no_shared_strings_file.xlsx
|
||||
spout-xlsx_sheet_with_prefixed_xml_files.xlsx
|
||||
spout-xlsx_sheet_with_preserve_space_shared_strings.xlsx
|
||||
spout-xlsx_sheet_with_pronunciation.xlsx
|
||||
spout-xlsx_sheet_with_same_numeric_value_date_formatted_differently.xlsx
|
||||
spout-xlsx_sheet_with_untrimmed_inline_strings.xlsx
|
||||
spout-xlsx_sheet_with_zeros_in_row.xlsx
|
||||
spout-xlsx_sheet_without_dimensions_and_empty_cells.xlsx
|
||||
spout-xlsx_sheet_without_dimensions_but_spans_and_empty_cells.xlsx
|
||||
spout-xlsx_two_sheets_with_custom_names.xlsx
|
||||
spout-xlsx_two_sheets_with_inline_strings.xlsx
|
||||
spout-xlsx_two_sheets_with_shared_strings.xlsx
|
||||
spout-xlsx_two_sheets_with_sheets_definition_in_reverse_order.xlsx
|
||||
spreadsheet-parsexlsx_Test.xlsx
|
||||
spreadsheet-parsexlsx_bug-10.xlsx
|
||||
spreadsheet-parsexlsx_bug-11.xlsx
|
||||
@ -426,7 +457,7 @@ spreadsheet-parsexlsx_bug-5.xlsx
|
||||
spreadsheet-parsexlsx_bug-57.xlsx
|
||||
spreadsheet-parsexlsx_bug-6-2.xlsx
|
||||
spreadsheet-parsexlsx_bug-6.xlsx
|
||||
spreadsheet-parsexlsx_bug-61.xlsx
|
||||
# spreadsheet-parsexlsx_bug-61.xlsx
|
||||
spreadsheet-parsexlsx_bug-7.xlsx
|
||||
spreadsheet-parsexlsx_bug-8.xlsx
|
||||
spreadsheet-parsexlsx_bug-lock.xlsx
|
||||
@ -469,9 +500,9 @@ hyperlink_no_rels.xlsm
|
||||
number_format.xlsm
|
||||
number_format_russian.xlsm
|
||||
numfmt_1_russian.xlsm
|
||||
openpyxl_r_vba+comments.xlsm
|
||||
openpyxl_r_vba-comments-saved.xlsm
|
||||
openpyxl_r_vba-test.xlsm
|
||||
# openpyxl_r_vba+comments.xlsm
|
||||
# openpyxl_r_vba-comments-saved.xlsm
|
||||
# openpyxl_r_vba-test.xlsm
|
||||
# pivot_table_test.xlsm # xlml
|
||||
roo_1900_base.xlsm
|
||||
roo_1904_base.xlsm
|
||||
@ -507,6 +538,8 @@ formula_stress_test.ods
|
||||
merge_cells.ods
|
||||
number_format.ods
|
||||
rich_text_stress.ods
|
||||
roo-xls_numbers1.ods
|
||||
roo-xls_type_excel.ods
|
||||
roo_Bibelbund.ods
|
||||
roo_Bibelbund1.ods
|
||||
roo_advanced_header.ods
|
||||
@ -534,6 +567,32 @@ roo_time-test.ods
|
||||
roo_type_excel.ods
|
||||
roo_type_excelx.ods
|
||||
roo_whitespace.ods
|
||||
spout-ods_attack_billion_laughs.ods
|
||||
spout-ods_attack_quadratic_blowup.ods
|
||||
# spout-ods_file_corrupted.ods
|
||||
spout-ods_file_generated_by_excel_2010_windows.ods
|
||||
spout-ods_file_generated_by_excel_office_online.ods
|
||||
spout-ods_file_generated_by_libre_office.ods
|
||||
spout-ods_one_sheet_with_strings.ods
|
||||
spout-ods_sheet_with_all_cell_types.ods
|
||||
spout-ods_sheet_with_dates_and_times.ods
|
||||
spout-ods_sheet_with_empty_cells.ods
|
||||
spout-ods_sheet_with_empty_rows.ods
|
||||
spout-ods_sheet_with_formulas.ods
|
||||
spout-ods_sheet_with_hyperlinks.ods
|
||||
spout-ods_sheet_with_inline_font_formatting.ods
|
||||
spout-ods_sheet_with_invalid_date_time.ods.pending
|
||||
spout-ods_sheet_with_multiline_string.ods
|
||||
spout-ods_sheet_with_no_cells.ods
|
||||
spout-ods_sheet_with_number_columns_repeated.ods
|
||||
spout-ods_sheet_with_number_rows_repeated.ods
|
||||
spout-ods_sheet_with_only_one_cell.ods
|
||||
spout-ods_sheet_with_undefined_value_type.ods
|
||||
spout-ods_sheet_with_untrimmed_strings.ods
|
||||
spout-ods_sheet_with_various_spaces.ods
|
||||
spout-ods_sheet_with_zeros_in_row.ods
|
||||
spout-ods_two_sheets_with_custom_names.ods
|
||||
spout-ods_two_sheets_with_strings.ods
|
||||
sushi.ods
|
||||
biff5/NumberFormatCondition.xls
|
||||
biff5/RkNumber.xls
|
||||
@ -612,6 +671,7 @@ apachepoi_33082.xls
|
||||
apachepoi_34775.xls
|
||||
apachepoi_35564.xls
|
||||
apachepoi_35565.xls
|
||||
# apachepoi_35897-type4.xls ## password
|
||||
apachepoi_36947.xls
|
||||
apachepoi_37376.xls
|
||||
apachepoi_37630.xls
|
||||
@ -649,6 +709,7 @@ apachepoi_44840.xls
|
||||
apachepoi_44861.xls
|
||||
apachepoi_44891.xls
|
||||
apachepoi_44958.xls
|
||||
apachepoi_44958_1.xls
|
||||
apachepoi_45129.xls
|
||||
apachepoi_45290.xls
|
||||
apachepoi_45322.xls
|
||||
@ -659,6 +720,7 @@ apachepoi_45538_classic_Footer.xls
|
||||
apachepoi_45538_classic_Header.xls
|
||||
apachepoi_45538_form_Footer.xls
|
||||
apachepoi_45538_form_Header.xls
|
||||
apachepoi_45565.xls
|
||||
apachepoi_45672.xls
|
||||
apachepoi_45720.xls
|
||||
apachepoi_45761.xls
|
||||
@ -669,12 +731,14 @@ apachepoi_46137.xls
|
||||
apachepoi_46250.xls
|
||||
apachepoi_46368.xls
|
||||
apachepoi_46445.xls
|
||||
apachepoi_46515.xls
|
||||
apachepoi_46670_http.xls
|
||||
apachepoi_46670_local.xls
|
||||
apachepoi_46670_ref_airline.xls
|
||||
apachepoi_46904.xls
|
||||
apachepoi_47034.xls
|
||||
apachepoi_47154.xls
|
||||
apachepoi_47245_test.xls
|
||||
apachepoi_47251.xls
|
||||
apachepoi_47251_1.xls
|
||||
apachepoi_47701.xls
|
||||
@ -690,6 +754,7 @@ apachepoi_49096.xls
|
||||
apachepoi_49185.xls
|
||||
apachepoi_49219.xls
|
||||
apachepoi_49237.xls
|
||||
apachepoi_49423.xls
|
||||
apachepoi_49524.xls
|
||||
apachepoi_49529.xls
|
||||
apachepoi_49581.xls
|
||||
@ -717,6 +782,7 @@ apachepoi_51832.xls.pending
|
||||
apachepoi_52527.xls
|
||||
apachepoi_52575_main.xls
|
||||
apachepoi_52575_source.xls
|
||||
apachepoi_53109.xls
|
||||
apachepoi_53404.xls
|
||||
apachepoi_53433.xls
|
||||
apachepoi_53446.xls
|
||||
@ -730,24 +796,44 @@ apachepoi_54206.xls
|
||||
apachepoi_54500.xls
|
||||
apachepoi_54686_fraction_formats.xls
|
||||
apachepoi_55341_CellStyleBorder.xls
|
||||
apachepoi_55668.xls
|
||||
apachepoi_55906-MultiSheetRefs.xls
|
||||
apachepoi_55982.xls
|
||||
apachepoi_56325.xls
|
||||
apachepoi_56325a.xls
|
||||
apachepoi_56450.xls
|
||||
apachepoi_56482.xls
|
||||
apachepoi_56563a.xls
|
||||
apachepoi_56563b.xls
|
||||
apachepoi_56737.xls
|
||||
apachepoi_57003-FixedFunctionTestCaseData.xls
|
||||
apachepoi_57074.xls
|
||||
apachepoi_57163.xls
|
||||
apachepoi_57231_MixedGasReport.xls.pending
|
||||
apachepoi_57456.xls.pending
|
||||
apachepoi_57798.xls
|
||||
apachepoi_57925.xls
|
||||
apachepoi_59074.xls
|
||||
apachepoi_59264.xls
|
||||
apachepoi_59830.xls
|
||||
apachepoi_59858.xls
|
||||
apachepoi_60273.xls
|
||||
# apachepoi_60284.xls
|
||||
apachepoi_AbnormalSharedFormulaFlag.xls
|
||||
apachepoi_AreaErrPtg.xls
|
||||
apachepoi_BOOK_in_capitals.xls
|
||||
apachepoi_Basic_Expense_Template_2011.xls
|
||||
apachepoi_CodeFunctionTestCaseData.xls
|
||||
apachepoi_ColumnStyle1dp.xls
|
||||
apachepoi_ColumnStyle1dpColoured.xls
|
||||
apachepoi_ColumnStyleNone.xls
|
||||
apachepoi_ComplexFunctionTestCaseData.xls
|
||||
apachepoi_ConditionalFormattingSamples.xls
|
||||
apachepoi_ContinueRecordProblem.xls
|
||||
apachepoi_DBCSHeader.xls
|
||||
apachepoi_DBCSSheetName.xls
|
||||
apachepoi_DGet.xls
|
||||
apachepoi_DStar.xls
|
||||
apachepoi_DateFormats.xls
|
||||
apachepoi_DeltaFunctionTestCaseData.xls
|
||||
apachepoi_DrawingAndComments.xls
|
||||
@ -758,6 +844,7 @@ apachepoi_ErrPtg.xls
|
||||
apachepoi_FactDoubleFunctionTestCaseData.xls
|
||||
apachepoi_ForShifting.xls
|
||||
apachepoi_FormatChoiceTests.xls
|
||||
apachepoi_FormatKM.xls
|
||||
apachepoi_Formatting.xls
|
||||
apachepoi_FormulaEvalTestData.xls
|
||||
apachepoi_FormulaRefs.xls
|
||||
@ -775,6 +862,7 @@ apachepoi_IrrNpvTestCaseData.xls
|
||||
apachepoi_MRExtraLines.xls
|
||||
apachepoi_MatchFunctionTestCaseData.xls
|
||||
apachepoi_MissingBits.xls
|
||||
apachepoi_NewStyleConditionalFormattings.xls
|
||||
apachepoi_NoGutsRecords.xls
|
||||
apachepoi_OddStyleRecord.xls
|
||||
apachepoi_PercentPtg.xls
|
||||
@ -791,7 +879,9 @@ apachepoi_SheetWithDrawing.xls
|
||||
apachepoi_ShrinkToFit.xls
|
||||
apachepoi_Simple.xls
|
||||
apachepoi_SimpleChart.xls
|
||||
apachepoi_SimpleMacro.xls
|
||||
apachepoi_SimpleMultiCell.xls
|
||||
apachepoi_SimpleScatterChart.xls
|
||||
apachepoi_SimpleWithAutofilter.xls
|
||||
apachepoi_SimpleWithChoose.xls
|
||||
apachepoi_SimpleWithColours.xls
|
||||
@ -811,6 +901,7 @@ apachepoi_StringContinueRecords.xls
|
||||
apachepoi_StringFormulas.xls
|
||||
apachepoi_SubtotalsNested.xls
|
||||
apachepoi_TestRandBetween.xls
|
||||
apachepoi_Themes2.xls
|
||||
apachepoi_TwoSheetsNoneHidden.xls
|
||||
apachepoi_TwoSheetsOneHidden.xls
|
||||
# apachepoi_UncalcedRecord.xls # xlml
|
||||
@ -831,10 +922,13 @@ apachepoi_WithTwoHyperLinks.xls
|
||||
apachepoi_WrongFormulaRecordType.xls
|
||||
apachepoi_XRefCalc.xls
|
||||
apachepoi_XRefCalcData.xls
|
||||
apachepoi_ar.org.apsme.www_Form%20Inscripcion%20Curso%20NO%20Socios.xls
|
||||
apachepoi_at.gv.land-oberoesterreich.www_cps_rde_xbcr_SID-4A1B954F-5C07F98E_ooe_stat_download_bp10.xls
|
||||
apachepoi_atp.xls
|
||||
apachepoi_blankworkbook.xls
|
||||
apachepoi_bug_42794.xls
|
||||
apachepoi_colwidth.xls
|
||||
apachepoi_com.aida-tour.www_SPO_files_maldives%20august%20october.xls
|
||||
apachepoi_comments.xls
|
||||
apachepoi_countblankExamples.xls
|
||||
apachepoi_countifExamples.xls
|
||||
@ -861,24 +955,32 @@ apachepoi_excel_with_embeded.xls
|
||||
apachepoi_excelant.xls.pending
|
||||
apachepoi_externalFunctionExample.xls
|
||||
# apachepoi_finance.xls # xlml
|
||||
apachepoi_florida_data.ashx.xls
|
||||
apachepoi_intercept.xls
|
||||
apachepoi_mirrTest.xls
|
||||
apachepoi_missingFuncs44675.xls
|
||||
apachepoi_mortgage-calculation.xls
|
||||
apachepoi_multibookFormulaA.xls
|
||||
apachepoi_multibookFormulaB.xls
|
||||
apachepoi_named-cell-in-formula-test.xls
|
||||
apachepoi_named-cell-test.xls
|
||||
apachepoi_namedinput.xls
|
||||
apachepoi_noHeaderFooter47244.xls
|
||||
apachepoi_ole2-embedding.xls
|
||||
apachepoi_overlapSharedFormula.xls
|
||||
apachepoi_password.xls.pending
|
||||
apachepoi_rank.xls
|
||||
apachepoi_resize_compare.xls
|
||||
apachepoi_rk.xls
|
||||
apachepoi_shared_formulas.xls
|
||||
apachepoi_sumifformula.xls
|
||||
# apachepoi_sumifs.xls # xlml
|
||||
apachepoi_templateExcelWithAutofilter.xls
|
||||
apachepoi_testArraysAndTables.xls
|
||||
apachepoi_testEXCEL_3.xls
|
||||
apachepoi_testEXCEL_4.xls
|
||||
apachepoi_testEXCEL_5.xls
|
||||
apachepoi_testEXCEL_95.xls
|
||||
apachepoi_testNames.xls
|
||||
apachepoi_testRRaC.xls
|
||||
apachepoi_testRVA.xls
|
||||
@ -1091,40 +1193,41 @@ pyExcelerator_mini-mini.xls
|
||||
pyExcelerator_mini.xls
|
||||
pyExcelerator_oo14.xls
|
||||
rich_text_stress.xls
|
||||
roo_1900_base.xls
|
||||
roo_1904_base.xls
|
||||
roo_Bibelbund.xls
|
||||
roo_bad_excel_date.xls
|
||||
roo_bbu.xls
|
||||
roo_boolean.xls
|
||||
roo_borders.xls
|
||||
roo_bug-row-column-fixnum-float.xls
|
||||
roo_comments.xls
|
||||
roo_datetime.xls
|
||||
roo_datetime_floatconv.xls
|
||||
roo_emptysheets.xls
|
||||
roo_false_encoding.xls
|
||||
roo_formula.xls
|
||||
roo_formula_parse_error.xls
|
||||
roo_link.xls
|
||||
roo_matrix.xls
|
||||
roo_named_cells.xls
|
||||
roo_numbers1.xls
|
||||
roo_only_one_sheet.xls
|
||||
roo_paragraph.xls
|
||||
roo_prova.xls
|
||||
roo_simple_spreadsheet.xls
|
||||
roo_simple_spreadsheet_from_italo.xls
|
||||
roo_style.xls
|
||||
roo_time-test.xls
|
||||
roo_type_excelx.xls
|
||||
roo_type_openoffice.xls
|
||||
roo-xls_1900_base.xls
|
||||
roo-xls_1904_base.xls
|
||||
roo-xls_Bibelbund.xls
|
||||
roo-xls_bad_excel_date.xls
|
||||
roo-xls_bbu.xls
|
||||
roo-xls_boolean.xls
|
||||
roo-xls_borders.xls
|
||||
roo-xls_bug-row-column-fixnum-float.xls
|
||||
roo-xls_comments.xls
|
||||
roo-xls_datetime.xls
|
||||
roo-xls_datetime_floatconv.xls
|
||||
roo-xls_emptysheets.xls
|
||||
roo-xls_false_encoding.xls
|
||||
roo-xls_formula.xls
|
||||
roo-xls_formula_parse_error.xls
|
||||
roo-xls_link.xls
|
||||
roo-xls_matrix.xls
|
||||
roo-xls_named_cells.xls
|
||||
roo-xls_numbers1.xls
|
||||
roo-xls_only_one_sheet.xls
|
||||
roo-xls_paragraph.xls
|
||||
roo-xls_prova.xls
|
||||
roo-xls_simple_spreadsheet.xls
|
||||
roo-xls_simple_spreadsheet_from_italo.xls
|
||||
roo-xls_style.xls
|
||||
roo-xls_time-test.xls
|
||||
roo-xls_type_excelx.xls
|
||||
roo-xls_type_openoffice.xls
|
||||
roo_whitespace.xls
|
||||
smart_tags_2007.xls
|
||||
sushi.xls
|
||||
text_and_numbers.xls
|
||||
write.xls
|
||||
xlrd_Formate.xls
|
||||
# xlrd_biff4_no_format_no_window2.xls
|
||||
xlrd_formula_test_names.xls
|
||||
xlrd_formula_test_sjmachin.xls
|
||||
xlrd_issue20.xls
|
||||
@ -1135,7 +1238,6 @@ xlrd_xf_class.xls
|
||||
xlsx-stream-d-date-cell.xls
|
||||
AutoFilter.xml
|
||||
BlankSheetTypes.xml
|
||||
ErrorTypes.xml
|
||||
LONumbers-2010.xls.xml
|
||||
LONumbers-2010.xlsx.xml
|
||||
LONumbers-2011.xls.xml
|
||||
@ -1145,6 +1247,7 @@ NumberFormatCondition.xml
|
||||
RkNumber.xls.xml
|
||||
RkNumber.xlsb.xml
|
||||
RkNumber.xlsx.xml
|
||||
apachepoi_SampleSS.xml
|
||||
calendar_stress_test.xml.pending
|
||||
cell_style_simple.xml
|
||||
comments_stress_test.xls.xml
|
||||
@ -1197,26 +1300,28 @@ protect_stress_test_xml.xml
|
||||
rich_text_stress.xls.xml
|
||||
rich_text_stress.xlsb.xml
|
||||
rich_text_stress.xlsx.xml
|
||||
roo_Bibelbund.xml
|
||||
roo_bbu.xml
|
||||
roo_boolean.xml
|
||||
roo_borders.xml
|
||||
roo_bug-row-column-fixnum-float.xml
|
||||
roo_datetime.xml
|
||||
roo_datetime_floatconv.xml
|
||||
roo_emptysheets.xml
|
||||
roo_excel2003.xml
|
||||
roo_false_encoding.xml
|
||||
roo_formula.xml
|
||||
roo_formula_parse_error.xml
|
||||
roo_numbers1.xml
|
||||
roo_only_one_sheet.xml
|
||||
roo_paragraph.xml
|
||||
roo_simple_spreadsheet.xml
|
||||
roo_simple_spreadsheet_from_italo.xml
|
||||
roo_style.xml
|
||||
roo_time-test.xml
|
||||
roo_whitespace.xml
|
||||
roo-xls_Bibelbund.xml
|
||||
roo-xls_bbu.xml
|
||||
roo-xls_boolean.xml
|
||||
roo-xls_borders.xml
|
||||
roo-xls_bug-row-column-fixnum-float.xml
|
||||
roo-xls_datetime.xml
|
||||
roo-xls_datetime_floatconv.xml
|
||||
roo-xls_emptysheets.xml
|
||||
roo-xls_excel2003.xml
|
||||
roo-xls_excel2003_namespace.xml
|
||||
roo-xls_false_encoding.xml
|
||||
roo-xls_formula.xml
|
||||
roo-xls_formula_parse_error.xml
|
||||
roo-xls_numbers1.xml
|
||||
roo-xls_only_one_sheet.xml
|
||||
roo-xls_paragraph.xml
|
||||
roo-xls_simple_spreadsheet.xml
|
||||
roo-xls_simple_spreadsheet_from_italo.xml
|
||||
roo-xls_style.xml
|
||||
roo-xls_time-test.xml
|
||||
roo-xls_whitespace.xml
|
||||
# roo_sheet1.xml
|
||||
smart_tags_2007.xml
|
||||
sushi.xml
|
||||
text_and_numbers.xml
|
||||
@ -1229,3 +1334,15 @@ xlsx-stream-d-date-cell.xlsx.xml
|
||||
2011/apachepoi_styles.xlsx.xml
|
||||
2011/openpyxl_r_conditional-formatting.xlsx.xls
|
||||
2011/roo_file_item_error.xlsx.xml
|
||||
2013/apachepoi_29982.xls.xlsb
|
||||
2013/apachepoi_43251.xls.xlsb
|
||||
2013/apachepoi_44593.xls.xlsb ## xlsb loop timeout
|
||||
2013/apachepoi_44643.xls.xlsb
|
||||
2013/apachepoi_44958.xls.xlsb
|
||||
2013/apachepoi_46136-NoWarnings.xls.xlsb
|
||||
2013/apachepoi_48968.xls.xlsb
|
||||
2013/apachepoi_50939.xls.xlsb
|
||||
2013/apachepoi_54016.xls.xlsb
|
||||
2013/apachepoi_ReadOnlyRecommended.xls.xlsb
|
||||
2013/apachepoi_testArraysAndTables.xls.xlsb
|
||||
|
||||
|
@ -79,14 +79,32 @@ var ws = sheet_from_array_of_arrays(data);
|
||||
wb.SheetNames.push(ws_name);
|
||||
wb.Sheets[ws_name] = ws;
|
||||
|
||||
/* TEST: simple formula */
|
||||
ws['C1'].f = "A1+B1";
|
||||
ws['C2'] = {t:'n', f:"A1+B1"};
|
||||
|
||||
/* TEST: single-cell array formula */
|
||||
ws['D1'] = {t:'n', f:"SUM(A1:C1*A1:C1)", F:"D1:D1"};
|
||||
|
||||
/* TEST: multi-cell array formula */
|
||||
ws['E1'] = {t:'n', f:"TRANSPOSE(A1:D1)", F:"E1:E4"};
|
||||
ws['E2'] = {t:'n', F:"E1:E4"};
|
||||
ws['E3'] = {t:'n', F:"E1:E4"};
|
||||
ws['E4'] = {t:'n', F:"E1:E4"};
|
||||
ws["!ref"] = "A1:E4";
|
||||
|
||||
/* TEST: column widths */
|
||||
ws['!cols'] = wscols;
|
||||
|
||||
console.log("JSON Data: "); console.log(XLSX.utils.sheet_to_json(ws, {header:1}));
|
||||
|
||||
|
||||
/* write file */
|
||||
XLSX.writeFile(wb, 'sheetjs.xlsx');
|
||||
XLSX.writeFile(wb, 'sheetjs.xlsx', {bookSST:true});
|
||||
XLSX.writeFile(wb, 'sheetjs.xlsm');
|
||||
XLSX.writeFile(wb, 'sheetjs.xlsb');
|
||||
XLSX.writeFile(wb, 'sheetjs.xls', {bookType:'biff2'});
|
||||
XLSX.writeFile(wb, 'sheetjs.xlsb'); // no formula
|
||||
XLSX.writeFile(wb, 'sheetjs.xls', {bookType:'biff2'}); // no formula
|
||||
XLSX.writeFile(wb, 'sheetjs.xml.xls', {bookType:'xlml'});
|
||||
XLSX.writeFile(wb, 'sheetjs.ods');
|
||||
XLSX.writeFile(wb, 'sheetjs.fods');
|
||||
XLSX.writeFile(wb, 'sheetjs.csv');
|
||||
@ -96,6 +114,7 @@ XLSX.readFile('sheetjs.xlsx');
|
||||
XLSX.readFile('sheetjs.xlsm');
|
||||
XLSX.readFile('sheetjs.xlsb');
|
||||
XLSX.readFile('sheetjs.xls');
|
||||
XLSX.readFile('sheetjs.xml.xls');
|
||||
XLSX.readFile('sheetjs.ods');
|
||||
XLSX.readFile('sheetjs.fods');
|
||||
//XLSX.readFile('sheetjs.csv');
|
||||
|
165
xlsx.flow.js
165
xlsx.flow.js
@ -422,7 +422,18 @@ function hashq(str/*:string*/)/*:string*/ {
|
||||
return o;
|
||||
}
|
||||
function rnd(val/*:number*/, d/*:number*/)/*:string*/ { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
|
||||
function dec(val/*:number*/, d/*:number*/)/*:number*/ { return Math.round((val-Math.floor(val))*Math.pow(10,d)); }
|
||||
function dec(val/*:number*/, d/*:number*/)/*:number*/ {
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 0;
|
||||
}
|
||||
return Math.round((val-Math.floor(val))*Math.pow(10,d));
|
||||
}
|
||||
function carry(val/*:number*/, d/*:number*/)/*:number*/ {
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
function flr(val/*:number*/)/*:string*/ { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); }
|
||||
function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
|
||||
if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
|
||||
@ -444,8 +455,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
|
||||
if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign);
|
||||
if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
|
||||
if((r = fmt.match(dec1))) {
|
||||
// $FlowIgnore
|
||||
o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
|
||||
o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", /*::(*/r/*::||[""])*/[1].length-$1.length); });
|
||||
return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
|
||||
}
|
||||
fmt = fmt.replace(/^#+([0.])/, "$1");
|
||||
@ -454,7 +464,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
|
||||
}
|
||||
if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify(pad0r(aval,0));
|
||||
if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
|
||||
return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val))) + "." + pad0(dec(val, r[1].length),r[1].length);
|
||||
return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length);
|
||||
}
|
||||
if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
|
||||
if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
|
||||
@ -8201,8 +8211,18 @@ function ods_to_csf_formula(f/*:string*/)/*:string*/ {
|
||||
f = f.substr(1);
|
||||
if(f.charCodeAt(0) == 61) f = f.substr(1);
|
||||
}
|
||||
f = f.replace(/COM\.MICROSOFT\./g, "");
|
||||
/* Part 3 Section 5.8 References */
|
||||
return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, "");
|
||||
f = f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, function($$, $1) { return $1.replace(/\./g,""); });
|
||||
/* TODO: something other than this */
|
||||
f = f.replace(/\[.(#[A-Z]*[?!])\]/g, "$1");
|
||||
return f.replace(/[;~]/g,",").replace(/\|/g,";");
|
||||
}
|
||||
|
||||
function csf_to_ods_formula(f/*:string*/)/*:string*/ {
|
||||
var o = "of:=" + f.replace(crefregex, "$1[.$2$3$4$5]").replace(/\]:\[/g,":");
|
||||
/* TODO: something other than this */
|
||||
return o.replace(/;/g, "|").replace(/,/g,";");
|
||||
}
|
||||
var strs = {}; // shared strings
|
||||
var _ssfopts = {}; // spreadsheet formatting options
|
||||
@ -8390,7 +8410,7 @@ function write_ws_xml_cols(ws, cols)/*:string*/ {
|
||||
}
|
||||
|
||||
function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
if(cell.v === undefined || cell.t === 'z') return "";
|
||||
if(cell.v === undefined && cell.f === undefined || cell.t === 'z') return "";
|
||||
var vv = "";
|
||||
var oldt = cell.t, oldv = cell.v;
|
||||
switch(cell.t) {
|
||||
@ -8416,7 +8436,7 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
case 'd': o.t = "d"; break;
|
||||
case 'b': o.t = "b"; break;
|
||||
case 'e': o.t = "e"; break;
|
||||
default:
|
||||
default: if(cell.v == null) { delete cell.t; break; }
|
||||
if(opts.bookSST) {
|
||||
v = writetag('v', ''+get_sst_id(opts.Strings, cell.v));
|
||||
o.t = "s"; break;
|
||||
@ -8424,6 +8444,10 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
o.t = "str"; break;
|
||||
}
|
||||
if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; }
|
||||
if(cell.f) {
|
||||
var ff = cell.F && cell.F.substr(0, ref.length) == ref ? {t:"array", ref:cell.F} : null;
|
||||
v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : "");
|
||||
}
|
||||
return writextag('c', v, o);
|
||||
}
|
||||
|
||||
@ -8479,7 +8503,8 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
|
||||
if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
|
||||
if(opts.cellFormula) {
|
||||
if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') {
|
||||
p.f=unescapexml(utf8read(cref[1]));
|
||||
/* TODO: match against XLSXFutureFunctions */
|
||||
p.f=unescapexml(utf8read(cref[1])).replace(/_xlfn\./,"");
|
||||
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
|
||||
p.F = (d.match(refregex)||[])[1];
|
||||
if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
|
||||
@ -9842,7 +9867,7 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
|
||||
case 'DateTime':
|
||||
cell.v = (Date.parse(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
|
||||
if(cell.v !== cell.v) cell.v = unescapexml(xml);
|
||||
else if(cell.v >= 1 && cell.v<60) cell.v = cell.v -1;
|
||||
else if(cell.v<60) cell.v = cell.v -1;
|
||||
if(!nf || nf == "General") nf = "yyyy-mm-dd";
|
||||
/* falls through */
|
||||
case 'Number':
|
||||
@ -9984,6 +10009,7 @@ function parse_xlml_xml(d, opts)/*:Workbook*/ {
|
||||
sheetname = unescapexml(tmp.Name);
|
||||
cursheet = {};
|
||||
mergecells = [];
|
||||
arrayf = [];
|
||||
}
|
||||
break;
|
||||
case 'Table':
|
||||
@ -10493,10 +10519,14 @@ function write_sty_xlml(wb, opts)/*:string*/ {
|
||||
}
|
||||
/* TODO */
|
||||
function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
|
||||
if(!cell || cell.v === undefined) return "<Cell></Cell>";
|
||||
if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>";
|
||||
|
||||
var attr = {};
|
||||
if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr));
|
||||
if(cell.F && cell.F.substr(0, ref.length) == ref) {
|
||||
var end = decode_cell(cell.F.substr(ref.length + 1));
|
||||
attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]");
|
||||
}
|
||||
|
||||
if(ws['!merges']) {
|
||||
var marr = ws['!merges'];
|
||||
@ -10514,9 +10544,9 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
|
||||
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
|
||||
case 'e': t = 'Error'; p = BErr[cell.v]; break;
|
||||
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); break;
|
||||
case 's': t = 'String'; p = escapexml(cell.v||""); break;
|
||||
case 's': t = 'String'; p = escapexml(cell.v||""); break;
|
||||
}
|
||||
var m = '<Data ss:Type="' + t + '">' + p + '</Data>';
|
||||
var m = '<Data ss:Type="' + t + '">' + (cell.v != null ? p : "") + '</Data>';
|
||||
|
||||
return writextag("Cell", m, attr);
|
||||
}
|
||||
@ -10699,6 +10729,19 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1;
|
||||
if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1;
|
||||
}
|
||||
if(options.cellFormula && line.f) {
|
||||
for(var afi = 0; afi < array_formulae.length; ++afi) {
|
||||
if(array_formulae[afi][0].s.c > cell.c) continue;
|
||||
if(array_formulae[afi][0].s.r > cell.r) continue;
|
||||
if(array_formulae[afi][0].e.c < cell.c) continue;
|
||||
if(array_formulae[afi][0].e.r < cell.r) continue;
|
||||
line.F = encode_range(array_formulae[afi][0]);
|
||||
if(array_formulae[afi][0].s.c != cell.c) delete line.f;
|
||||
if(array_formulae[afi][0].s.r != cell.r) delete line.f;
|
||||
if(line.f) line.f = "" + stringify_formula(array_formulae[afi][1], range, cell, supbooks, opts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(options.sheetRows && lastcell.r >= options.sheetRows) cell_valid = false;
|
||||
else out[last_cell] = line;
|
||||
};
|
||||
@ -10851,7 +10894,9 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
else cur_sheet = (Directory[s] || {name:""}).name;
|
||||
mergecells = [];
|
||||
objects = [];
|
||||
array_formulae = []; opts.arrayf = array_formulae;
|
||||
} break;
|
||||
|
||||
case 'Number': case 'BIFF2NUM': case 'BIFF2INT': {
|
||||
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:'n'};
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
@ -10876,44 +10921,43 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
}
|
||||
} break;
|
||||
case 'Formula': {
|
||||
switch(val.val) {
|
||||
case 'String': last_formula = val; break;
|
||||
case 'Array Formula': throw "Array Formula unsupported";
|
||||
default:
|
||||
temp_val = ({v:val.val, ixfe:val.cell.ixfe, t:val.tt}/*:any*/);
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) {
|
||||
var _f = val.formula;
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = (out[_fe] || {}).F;
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(val.cell, temp_val, options);
|
||||
last_formula = val;
|
||||
if(val.val == 'String') { last_formula = val; break; }
|
||||
temp_val = ({v:val.val, ixfe:val.cell.ixfe, t:val.tt}/*:any*/);
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) {
|
||||
var _f = val.formula;
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = (out[_fe] || {}).F;
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(val.cell, temp_val, options);
|
||||
last_formula = val;
|
||||
} break;
|
||||
case 'String': {
|
||||
if(last_formula) {
|
||||
if(last_formula) { /* technically always true */
|
||||
last_formula.val = val;
|
||||
temp_val = ({v:last_formula.val, ixfe:last_formula.cell.ixfe, t:'s'}/*:any*/);
|
||||
temp_val = ({v:val, ixfe:last_formula.cell.ixfe, t:'s'}/*:any*/);
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
if(options.cellFormula) {
|
||||
temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
}
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(last_formula.cell, temp_val, options);
|
||||
last_formula = null;
|
||||
}
|
||||
} else throw new Error("String record expects Formula");
|
||||
} break;
|
||||
case 'Array': {
|
||||
array_formulae.push(val);
|
||||
if(options.cellFormula && out[last_cell]) {
|
||||
var _arraystart = encode_cell(val[0].s);
|
||||
if(options.cellFormula && out[_arraystart]) {
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
if(!last_cell || !out[last_cell]) break; /* technically unreachable */
|
||||
out[last_cell].f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
out[last_cell].F = encode_range(val[0]);
|
||||
if(!_arraystart || !out[_arraystart]) break;
|
||||
out[_arraystart].f = ""+stringify_formula(val[1], range, val[0], supbooks, opts);
|
||||
out[_arraystart].F = encode_range(val[0]);
|
||||
}
|
||||
} break;
|
||||
case 'ShrFmla': {
|
||||
@ -10952,6 +10996,7 @@ 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 'Dimensions': {
|
||||
if(file_depth === 1) range = val; /* TODO: stack */
|
||||
} break;
|
||||
@ -12602,20 +12647,20 @@ function write_BIFF2LABEL(r, c, val) {
|
||||
}
|
||||
|
||||
function write_ws_biff_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) {
|
||||
switch(cell.t) {
|
||||
if(cell.v != null) switch(cell.t) {
|
||||
case 'n':
|
||||
if((cell.v == (cell.v|0)) && (cell.v >= 0) && (cell.v < 65536))
|
||||
write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, cell.v));
|
||||
else
|
||||
write_biff_rec(ba, 0x0003, write_BIFF2NUMBER(R,C, cell.v));
|
||||
break;
|
||||
case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); break;
|
||||
return;
|
||||
case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
|
||||
/* TODO: codepage, sst */
|
||||
case 's': case 'str':
|
||||
write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v));
|
||||
break;
|
||||
default: write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
|
||||
return;
|
||||
}
|
||||
write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
|
||||
}
|
||||
|
||||
function write_biff_ws(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
@ -12761,6 +12806,7 @@ var parse_content_xml = (function() {
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:""*/}/*:any*/);
|
||||
if(opts.cellFormula) {
|
||||
if(ctag.formula) ctag.formula = unescapexml(ctag.formula);
|
||||
if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
|
||||
mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
|
||||
mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
|
||||
@ -13108,11 +13154,22 @@ var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
}
|
||||
if(skip) { o.push(covered_cell_xml); continue; }
|
||||
var ref = encode_cell({r:R, c:C}), cell = ws[ref];
|
||||
var fmla = "";
|
||||
if(cell && cell.f) {
|
||||
fmla = ' table:formula="' + escapexml(csf_to_ods_formula(cell.f)) + '"';
|
||||
if(cell.F) {
|
||||
if(cell.F.substr(0, ref.length) == ref) {
|
||||
var _Fref = decode_range(cell.F);
|
||||
fmla += ' table:number-matrix-columns-spanned="' + (_Fref.e.c - _Fref.s.c + 1)+ '"';
|
||||
fmla += ' table:number-matrix-rows-spanned="' + (_Fref.e.r - _Fref.s.r + 1) + '"';
|
||||
} else fmla = "";
|
||||
}
|
||||
}
|
||||
if(cell) switch(cell.t) {
|
||||
case 'b': o.push(cell_begin + mxml + vt + '"boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '">' + p_begin + (cell.v ? 'TRUE' : 'FALSE') + p_end + cell_end); break;
|
||||
case 'n': o.push(cell_begin + mxml + vt + '"float" office:value="' + cell.v + '">' + p_begin + (cell.w||cell.v) + p_end + cell_end); break;
|
||||
case 's': case 'str': o.push(cell_begin + mxml + vt + '"string">' + p_begin + escapexml(cell.v) + p_end + cell_end); break;
|
||||
case 'd': o.push(cell_begin + mxml + vt + '"date" office:date-value="' + (new Date(cell.v).toISOString()) + '">' + p_begin + (cell.w||(new Date(cell.v).toISOString())) + p_end + cell_end); break;
|
||||
case 'b': o.push(cell_begin + mxml + vt + '"boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"' + fmla + '>' + p_begin + (cell.v ? 'TRUE' : 'FALSE') + p_end + cell_end); break;
|
||||
case 'n': o.push(cell_begin + mxml + vt + '"float" office:value="' + cell.v + '"' + fmla + '>' + p_begin + (cell.w||cell.v) + p_end + cell_end); break;
|
||||
case 's': case 'str': o.push(cell_begin + mxml + vt + '"string"' + fmla + '>' + p_begin + escapexml(cell.v) + p_end + cell_end); break;
|
||||
case 'd': o.push(cell_begin + mxml + vt + '"date" office:date-value="' + (new Date(cell.v).toISOString()) + '"' + fmla + '>' + p_begin + (cell.w||(new Date(cell.v).toISOString())) + p_end + cell_end); break;
|
||||
//case 'e':
|
||||
default: o.push(null_cell_xml);
|
||||
} else o.push(null_cell_xml);
|
||||
@ -13127,7 +13184,7 @@ var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
var o = [XML_HEADER];
|
||||
/* 3.1.3.2 */
|
||||
if(opts.bookType == "fods") o.push('<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">');
|
||||
else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
|
||||
else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2">\n'); // TODO
|
||||
o.push(' <office:body>\n');
|
||||
o.push(' <office:spreadsheet>\n');
|
||||
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts));
|
||||
@ -13749,9 +13806,15 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
|
||||
rr = encode_row(R);
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
val = sheet[cols[C] + rr];
|
||||
txt = val !== undefined ? ''+format_cell(val) : "";
|
||||
for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {
|
||||
txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
|
||||
if(val == null) txt = "";
|
||||
else if(val.v != null) {
|
||||
txt = ''+format_cell(val);
|
||||
for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {
|
||||
txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
|
||||
} else if(val.f != null && !val.F) {
|
||||
txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"';
|
||||
} else txt = "";
|
||||
/* NOTE: Excel CSV does not support array formulae */
|
||||
row += (C === r.s.c ? "" : FS) + txt;
|
||||
}
|
||||
out += row + RS;
|
||||
|
163
xlsx.js
163
xlsx.js
@ -403,7 +403,18 @@ function hashq(str) {
|
||||
return o;
|
||||
}
|
||||
function rnd(val, d) { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
|
||||
function dec(val, d) { return Math.round((val-Math.floor(val))*Math.pow(10,d)); }
|
||||
function dec(val, d) {
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 0;
|
||||
}
|
||||
return Math.round((val-Math.floor(val))*Math.pow(10,d));
|
||||
}
|
||||
function carry(val, d) {
|
||||
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
function flr(val) { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); }
|
||||
function write_num_flt(type, fmt, val) {
|
||||
if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
|
||||
@ -425,7 +436,6 @@ function write_num_flt(type, fmt, val) {
|
||||
if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign);
|
||||
if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
|
||||
if((r = fmt.match(dec1))) {
|
||||
// $FlowIgnore
|
||||
o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
|
||||
return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
|
||||
}
|
||||
@ -435,7 +445,7 @@ function write_num_flt(type, fmt, val) {
|
||||
}
|
||||
if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify(pad0r(aval,0));
|
||||
if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
|
||||
return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val))) + "." + pad0(dec(val, r[1].length),r[1].length);
|
||||
return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length);
|
||||
}
|
||||
if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
|
||||
if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
|
||||
@ -8148,8 +8158,18 @@ function ods_to_csf_formula(f) {
|
||||
f = f.substr(1);
|
||||
if(f.charCodeAt(0) == 61) f = f.substr(1);
|
||||
}
|
||||
f = f.replace(/COM\.MICROSOFT\./g, "");
|
||||
/* Part 3 Section 5.8 References */
|
||||
return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, "");
|
||||
f = f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, function($$, $1) { return $1.replace(/\./g,""); });
|
||||
/* TODO: something other than this */
|
||||
f = f.replace(/\[.(#[A-Z]*[?!])\]/g, "$1");
|
||||
return f.replace(/[;~]/g,",").replace(/\|/g,";");
|
||||
}
|
||||
|
||||
function csf_to_ods_formula(f) {
|
||||
var o = "of:=" + f.replace(crefregex, "$1[.$2$3$4$5]").replace(/\]:\[/g,":");
|
||||
/* TODO: something other than this */
|
||||
return o.replace(/;/g, "|").replace(/,/g,";");
|
||||
}
|
||||
var strs = {}; // shared strings
|
||||
var _ssfopts = {}; // spreadsheet formatting options
|
||||
@ -8337,7 +8357,7 @@ function write_ws_xml_cols(ws, cols) {
|
||||
}
|
||||
|
||||
function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
if(cell.v === undefined || cell.t === 'z') return "";
|
||||
if(cell.v === undefined && cell.f === undefined || cell.t === 'z') return "";
|
||||
var vv = "";
|
||||
var oldt = cell.t, oldv = cell.v;
|
||||
switch(cell.t) {
|
||||
@ -8363,7 +8383,7 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
case 'd': o.t = "d"; break;
|
||||
case 'b': o.t = "b"; break;
|
||||
case 'e': o.t = "e"; break;
|
||||
default:
|
||||
default: if(cell.v == null) { delete cell.t; break; }
|
||||
if(opts.bookSST) {
|
||||
v = writetag('v', ''+get_sst_id(opts.Strings, cell.v));
|
||||
o.t = "s"; break;
|
||||
@ -8371,6 +8391,10 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
o.t = "str"; break;
|
||||
}
|
||||
if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; }
|
||||
if(cell.f) {
|
||||
var ff = cell.F && cell.F.substr(0, ref.length) == ref ? {t:"array", ref:cell.F} : null;
|
||||
v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : "");
|
||||
}
|
||||
return writextag('c', v, o);
|
||||
}
|
||||
|
||||
@ -8426,7 +8450,8 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
|
||||
if((cref=d.match(match_v))!= null && cref[1] !== '') p.v=unescapexml(cref[1]);
|
||||
if(opts.cellFormula) {
|
||||
if((cref=d.match(match_f))!= null && cref[1] !== '') {
|
||||
p.f=unescapexml(utf8read(cref[1]));
|
||||
/* TODO: match against XLSXFutureFunctions */
|
||||
p.f=unescapexml(utf8read(cref[1])).replace(/_xlfn\./,"");
|
||||
if(cref[0].indexOf('t="array"') > -1) {
|
||||
p.F = (d.match(refregex)||[])[1];
|
||||
if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
|
||||
@ -9787,7 +9812,7 @@ function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, arrayf, o
|
||||
case 'DateTime':
|
||||
cell.v = (Date.parse(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
|
||||
if(cell.v !== cell.v) cell.v = unescapexml(xml);
|
||||
else if(cell.v >= 1 && cell.v<60) cell.v = cell.v -1;
|
||||
else if(cell.v<60) cell.v = cell.v -1;
|
||||
if(!nf || nf == "General") nf = "yyyy-mm-dd";
|
||||
/* falls through */
|
||||
case 'Number':
|
||||
@ -9928,6 +9953,7 @@ for(var cma = c; cma <= cc; ++cma) {
|
||||
sheetname = unescapexml(tmp.Name);
|
||||
cursheet = {};
|
||||
mergecells = [];
|
||||
arrayf = [];
|
||||
}
|
||||
break;
|
||||
case 'Table':
|
||||
@ -10436,10 +10462,14 @@ function write_sty_xlml(wb, opts) {
|
||||
}
|
||||
/* TODO */
|
||||
function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){
|
||||
if(!cell || cell.v === undefined) return "<Cell></Cell>";
|
||||
if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>";
|
||||
|
||||
var attr = {};
|
||||
if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr));
|
||||
if(cell.F && cell.F.substr(0, ref.length) == ref) {
|
||||
var end = decode_cell(cell.F.substr(ref.length + 1));
|
||||
attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]");
|
||||
}
|
||||
|
||||
if(ws['!merges']) {
|
||||
var marr = ws['!merges'];
|
||||
@ -10457,9 +10487,9 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){
|
||||
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
|
||||
case 'e': t = 'Error'; p = BErr[cell.v]; break;
|
||||
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); break;
|
||||
case 's': t = 'String'; p = escapexml(cell.v||""); break;
|
||||
case 's': t = 'String'; p = escapexml(cell.v||""); break;
|
||||
}
|
||||
var m = '<Data ss:Type="' + t + '">' + p + '</Data>';
|
||||
var m = '<Data ss:Type="' + t + '">' + (cell.v != null ? p : "") + '</Data>';
|
||||
|
||||
return writextag("Cell", m, attr);
|
||||
}
|
||||
@ -10642,6 +10672,19 @@ function parse_workbook(blob, options) {
|
||||
if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1;
|
||||
if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1;
|
||||
}
|
||||
if(options.cellFormula && line.f) {
|
||||
for(var afi = 0; afi < array_formulae.length; ++afi) {
|
||||
if(array_formulae[afi][0].s.c > cell.c) continue;
|
||||
if(array_formulae[afi][0].s.r > cell.r) continue;
|
||||
if(array_formulae[afi][0].e.c < cell.c) continue;
|
||||
if(array_formulae[afi][0].e.r < cell.r) continue;
|
||||
line.F = encode_range(array_formulae[afi][0]);
|
||||
if(array_formulae[afi][0].s.c != cell.c) delete line.f;
|
||||
if(array_formulae[afi][0].s.r != cell.r) delete line.f;
|
||||
if(line.f) line.f = "" + stringify_formula(array_formulae[afi][1], range, cell, supbooks, opts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(options.sheetRows && lastcell.r >= options.sheetRows) cell_valid = false;
|
||||
else out[last_cell] = line;
|
||||
};
|
||||
@ -10794,7 +10837,9 @@ function parse_workbook(blob, options) {
|
||||
else cur_sheet = (Directory[s] || {name:""}).name;
|
||||
mergecells = [];
|
||||
objects = [];
|
||||
array_formulae = []; opts.arrayf = array_formulae;
|
||||
} break;
|
||||
|
||||
case 'Number': case 'BIFF2NUM': case 'BIFF2INT': {
|
||||
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:'n'};
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
@ -10819,44 +10864,43 @@ function parse_workbook(blob, options) {
|
||||
}
|
||||
} break;
|
||||
case 'Formula': {
|
||||
switch(val.val) {
|
||||
case 'String': last_formula = val; break;
|
||||
case 'Array Formula': throw "Array Formula unsupported";
|
||||
default:
|
||||
temp_val = ({v:val.val, ixfe:val.cell.ixfe, t:val.tt});
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) {
|
||||
var _f = val.formula;
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = (out[_fe] || {}).F;
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(val.cell, temp_val, options);
|
||||
last_formula = val;
|
||||
if(val.val == 'String') { last_formula = val; break; }
|
||||
temp_val = ({v:val.val, ixfe:val.cell.ixfe, t:val.tt});
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) {
|
||||
var _f = val.formula;
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = (out[_fe] || {}).F;
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(val.cell, temp_val, options);
|
||||
last_formula = val;
|
||||
} break;
|
||||
case 'String': {
|
||||
if(last_formula) {
|
||||
if(last_formula) { /* technically always true */
|
||||
last_formula.val = val;
|
||||
temp_val = ({v:last_formula.val, ixfe:last_formula.cell.ixfe, t:'s'});
|
||||
temp_val = ({v:val, ixfe:last_formula.cell.ixfe, t:'s'});
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
if(options.cellFormula) {
|
||||
temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
}
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(last_formula.cell, temp_val, options);
|
||||
last_formula = null;
|
||||
}
|
||||
} else throw new Error("String record expects Formula");
|
||||
} break;
|
||||
case 'Array': {
|
||||
array_formulae.push(val);
|
||||
if(options.cellFormula && out[last_cell]) {
|
||||
var _arraystart = encode_cell(val[0].s);
|
||||
if(options.cellFormula && out[_arraystart]) {
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
if(!last_cell || !out[last_cell]) break; /* technically unreachable */
|
||||
out[last_cell].f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
out[last_cell].F = encode_range(val[0]);
|
||||
if(!_arraystart || !out[_arraystart]) break;
|
||||
out[_arraystart].f = ""+stringify_formula(val[1], range, val[0], supbooks, opts);
|
||||
out[_arraystart].F = encode_range(val[0]);
|
||||
}
|
||||
} break;
|
||||
case 'ShrFmla': {
|
||||
@ -10895,6 +10939,7 @@ 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 'Dimensions': {
|
||||
if(file_depth === 1) range = val; /* TODO: stack */
|
||||
} break;
|
||||
@ -12545,20 +12590,20 @@ function write_BIFF2LABEL(r, c, val) {
|
||||
}
|
||||
|
||||
function write_ws_biff_cell(ba, cell, R, C, opts) {
|
||||
switch(cell.t) {
|
||||
if(cell.v != null) switch(cell.t) {
|
||||
case 'n':
|
||||
if((cell.v == (cell.v|0)) && (cell.v >= 0) && (cell.v < 65536))
|
||||
write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, cell.v));
|
||||
else
|
||||
write_biff_rec(ba, 0x0003, write_BIFF2NUMBER(R,C, cell.v));
|
||||
break;
|
||||
case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); break;
|
||||
return;
|
||||
case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
|
||||
/* TODO: codepage, sst */
|
||||
case 's': case 'str':
|
||||
write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v));
|
||||
break;
|
||||
default: write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
|
||||
return;
|
||||
}
|
||||
write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
|
||||
}
|
||||
|
||||
function write_biff_ws(ba, ws, idx, opts, wb) {
|
||||
@ -12704,6 +12749,7 @@ var parse_content_xml = (function() {
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null});
|
||||
if(opts.cellFormula) {
|
||||
if(ctag.formula) ctag.formula = unescapexml(ctag.formula);
|
||||
if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
|
||||
mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
|
||||
mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
|
||||
@ -13051,11 +13097,22 @@ var write_content_xml = (function() {
|
||||
}
|
||||
if(skip) { o.push(covered_cell_xml); continue; }
|
||||
var ref = encode_cell({r:R, c:C}), cell = ws[ref];
|
||||
var fmla = "";
|
||||
if(cell && cell.f) {
|
||||
fmla = ' table:formula="' + escapexml(csf_to_ods_formula(cell.f)) + '"';
|
||||
if(cell.F) {
|
||||
if(cell.F.substr(0, ref.length) == ref) {
|
||||
var _Fref = decode_range(cell.F);
|
||||
fmla += ' table:number-matrix-columns-spanned="' + (_Fref.e.c - _Fref.s.c + 1)+ '"';
|
||||
fmla += ' table:number-matrix-rows-spanned="' + (_Fref.e.r - _Fref.s.r + 1) + '"';
|
||||
} else fmla = "";
|
||||
}
|
||||
}
|
||||
if(cell) switch(cell.t) {
|
||||
case 'b': o.push(cell_begin + mxml + vt + '"boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '">' + p_begin + (cell.v ? 'TRUE' : 'FALSE') + p_end + cell_end); break;
|
||||
case 'n': o.push(cell_begin + mxml + vt + '"float" office:value="' + cell.v + '">' + p_begin + (cell.w||cell.v) + p_end + cell_end); break;
|
||||
case 's': case 'str': o.push(cell_begin + mxml + vt + '"string">' + p_begin + escapexml(cell.v) + p_end + cell_end); break;
|
||||
case 'd': o.push(cell_begin + mxml + vt + '"date" office:date-value="' + (new Date(cell.v).toISOString()) + '">' + p_begin + (cell.w||(new Date(cell.v).toISOString())) + p_end + cell_end); break;
|
||||
case 'b': o.push(cell_begin + mxml + vt + '"boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"' + fmla + '>' + p_begin + (cell.v ? 'TRUE' : 'FALSE') + p_end + cell_end); break;
|
||||
case 'n': o.push(cell_begin + mxml + vt + '"float" office:value="' + cell.v + '"' + fmla + '>' + p_begin + (cell.w||cell.v) + p_end + cell_end); break;
|
||||
case 's': case 'str': o.push(cell_begin + mxml + vt + '"string"' + fmla + '>' + p_begin + escapexml(cell.v) + p_end + cell_end); break;
|
||||
case 'd': o.push(cell_begin + mxml + vt + '"date" office:date-value="' + (new Date(cell.v).toISOString()) + '"' + fmla + '>' + p_begin + (cell.w||(new Date(cell.v).toISOString())) + p_end + cell_end); break;
|
||||
//case 'e':
|
||||
default: o.push(null_cell_xml);
|
||||
} else o.push(null_cell_xml);
|
||||
@ -13070,7 +13127,7 @@ var write_content_xml = (function() {
|
||||
var o = [XML_HEADER];
|
||||
/* 3.1.3.2 */
|
||||
if(opts.bookType == "fods") o.push('<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">');
|
||||
else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
|
||||
else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2">\n'); // TODO
|
||||
o.push(' <office:body>\n');
|
||||
o.push(' <office:spreadsheet>\n');
|
||||
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts));
|
||||
@ -13684,9 +13741,15 @@ function sheet_to_csv(sheet, opts) {
|
||||
rr = encode_row(R);
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
val = sheet[cols[C] + rr];
|
||||
txt = val !== undefined ? ''+format_cell(val) : "";
|
||||
for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {
|
||||
txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
|
||||
if(val == null) txt = "";
|
||||
else if(val.v != null) {
|
||||
txt = ''+format_cell(val);
|
||||
for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {
|
||||
txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
|
||||
} else if(val.f != null && !val.F) {
|
||||
txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"';
|
||||
} else txt = "";
|
||||
/* NOTE: Excel CSV does not support array formulae */
|
||||
row += (C === r.s.c ? "" : FS) + txt;
|
||||
}
|
||||
out += row + RS;
|
||||
|
Loading…
Reference in New Issue
Block a user