version bump 0.7.6: IE compatibility
- jscs linting to check for trailing comma issues (h/t @altkatz) - IE: phased out lazy string indexing in favor of charCodeAt - XLSX: replaced certain operations in hot functions with faster alternatives - updated SSF to 0.7.1 - improved coverage in tests
This commit is contained in:
parent
a96b723cda
commit
44b55c5c56
|
@ -1,3 +1,4 @@
|
|||
node_modules
|
||||
misc/coverage.html
|
||||
tmp
|
||||
*.xlsx
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"requireCommaBeforeLineBreak": true,
|
||||
"disallowTrailingWhitespace": true,
|
||||
"disallowTrailingComma": true
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- "0.11"
|
||||
- "0.10"
|
||||
- "0.8"
|
||||
before_install:
|
||||
|
|
13
Makefile
13
Makefile
|
@ -13,7 +13,11 @@ bits/01_version.js: package.json
|
|||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm $(TARGET)
|
||||
rm -f $(TARGET)
|
||||
|
||||
.PHONY: clean-data
|
||||
clean-data:
|
||||
rm -f *.xlsx *.xlsm *.xlsb *.xls *.xml
|
||||
|
||||
.PHONY: init
|
||||
init:
|
||||
|
@ -37,6 +41,13 @@ $(TESTFMT): test_%:
|
|||
.PHONY: lint
|
||||
lint: $(TARGET)
|
||||
jshint --show-non-errors $(TARGET)
|
||||
jscs $(TARGET)
|
||||
|
||||
.PHONY: test-osx
|
||||
test-osx:
|
||||
node tests/write.js
|
||||
open -a Numbers sheetjs.xlsx
|
||||
open -a "Microsoft Excel" sheetjs.xlsx
|
||||
|
||||
.PHONY: cov cov-spin
|
||||
cov: misc/coverage.html
|
||||
|
|
|
@ -1 +1 @@
|
|||
XLSX.version = '0.7.5';
|
||||
XLSX.version = '0.7.6';
|
||||
|
|
|
@ -13,7 +13,7 @@ if(typeof cptable !== 'undefined') _getchar = function(x) {
|
|||
return cptable.utils.decode(current_codepage, [x%256,x>>8])[0];
|
||||
};
|
||||
|
||||
function char_codes(data) { return data.split("").map(function(x) { return x.charCodeAt(0); }); }
|
||||
function char_codes(data) { var o = []; for(var i = 0; i != data.length; ++i) o[i] = data.charCodeAt(i); return o; }
|
||||
function debom_xml(data) {
|
||||
if(typeof cptable !== 'undefined') {
|
||||
if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.substr(2))); }
|
||||
|
|
|
@ -5,7 +5,7 @@ var _strrev = function(x) { return String(x).split("").reverse().join("");};
|
|||
function fill(c,l) { return new Array(l+1).join(c); }
|
||||
function pad(v,d,c){var t=String(v);return t.length>=d?t:(fill(c||0,d-t.length)+t);}
|
||||
function rpad(v,d,c){var t=String(v);return t.length>=d?t:(t+fill(c||0,d-t.length));}
|
||||
SSF.version = '0.7.0';
|
||||
SSF.version = '0.7.1';
|
||||
/* Options */
|
||||
var opts_fmt = {
|
||||
date1904:0,
|
||||
|
@ -252,7 +252,10 @@ var write_num = function(type, fmt, val) {
|
|||
}
|
||||
if(fmt.match(/^#+0+$/)) fmt = fmt.replace(/#/g,"");
|
||||
if(fmt.match(/^00+$/)) return (val<0?"-":"")+pad(Math.round(aval),fmt.length);
|
||||
if(fmt.match(/^[#?]+$/)) return String(Math.round(val)).replace(/^0$/,"");
|
||||
if(fmt.match(/^[#?]+$/)) {
|
||||
o = String(Math.round(val)).replace(/^0$/,"");
|
||||
return o.length > fmt.length ? o : fmt.substr(0,fmt.length-o.length).replace(/#/g,"").replace(/[?]/g," ") + o;
|
||||
}
|
||||
if((r = fmt.match(/^#*0*\.(0+)/))) {
|
||||
o = Math.round(val * Math.pow(10,r[1].length));
|
||||
rr = String(o/Math.pow(10,r[1].length)).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.([0-9]*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
|
||||
|
@ -278,20 +281,32 @@ var write_num = function(type, fmt, val) {
|
|||
ff = write_num(type, "##########", val);
|
||||
return "(" + ff.substr(0,3) + ") " + ff.substr(3, 3) + "-" + ff.substr(6);
|
||||
}
|
||||
if((r = fmt.match(/^([?]+)([ ]?)\/([ ]?)([?]+)/))) {
|
||||
rr = Math.min(Math.max(r[1].length, r[4].length),7);
|
||||
var oa = "";
|
||||
if((r = fmt.match(/^([#0?]+)([ ]?)\/([ ]?)([#0?]+)/))) {
|
||||
o="";
|
||||
rr = Math.min(r[4].length,7);
|
||||
ff = frac(aval, Math.pow(10,rr)-1, false);
|
||||
return sign + (ff[0]||(ff[1] ? "" : "0")) + (ff[1] ? pad(ff[1],rr," ") + r[2] + "/" + r[3] + rpad(ff[2],rr," "): fill(" ", 2*rr+1 + r[2].length + r[3].length));
|
||||
o += sign;
|
||||
oa = write_num("n", r[1], ff[1]);
|
||||
if(oa[oa.length-1] == " ") oa = oa.substr(0,oa.length-1) + "0";
|
||||
o += oa;
|
||||
o += r[2];
|
||||
o += "/";
|
||||
o += r[3];
|
||||
oa = rpad(ff[2],rr," ");
|
||||
if(oa.length < r[4].length) oa = r[4].substr(r[4].length-oa.length).replace(/[?]/g," ").replace(/#/g,"") + oa;
|
||||
o += oa;
|
||||
return o;
|
||||
}
|
||||
if((r = fmt.match(/^# ([?]+)([ ]?)\/([ ]?)([?]+)/))) {
|
||||
if((r = fmt.match(/^# ([#0?]+)([ ]?)\/([ ]?)([#0?]+)/))) {
|
||||
rr = Math.min(Math.max(r[1].length, r[4].length),7);
|
||||
ff = frac(aval, Math.pow(10,rr)-1, true);
|
||||
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],rr," ") + r[2] + "/" + r[3] + rpad(ff[2],rr," "): fill(" ", 2*rr+1 + r[2].length + r[3].length));
|
||||
}
|
||||
if((r = fmt.match(/^[#0]+$/))) {
|
||||
if((r = fmt.match(/^[#0?]+$/))) {
|
||||
o = "" + Math.round(val);
|
||||
if(fmt.length <= o.length) return o;
|
||||
return fmt.substr(0,fmt.length - o.length).replace(/#/g,"") + o;
|
||||
return fmt.substr(0,fmt.length-o.length).replace(/#/g,"").replace(/\?/g," ") + o;
|
||||
}
|
||||
if((r = fmt.match(/^([#0]+)\.([#0]+)$/))) {
|
||||
o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
|
||||
|
@ -507,7 +522,9 @@ function eval_fmt(fmt, v, opts, flen) {
|
|||
out[i].v = write_num(out[i].t, out[i].v, (flen >1 && v < 0 && i>0 && out[i-1].v == "-" ? -v:v));
|
||||
out[i].t = 't';
|
||||
}
|
||||
return out.map(function(x){return x.v;}).join("");
|
||||
var retval = "";
|
||||
for(i=0; i != out.length; ++i) if(out[i]) retval += out[i].v;
|
||||
return retval;
|
||||
}
|
||||
SSF._eval = eval_fmt;
|
||||
function choose_fmt(fmt, v, o) {
|
||||
|
|
|
@ -2,9 +2,9 @@ var _chr = function(c) { return String.fromCharCode(c); };
|
|||
var _ord = function(c) { return c.charCodeAt(0); };
|
||||
var attregexg=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
|
||||
var attregex=/([\w:]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;
|
||||
function parsexmltag(tag) {
|
||||
function parsexmltag(tag, skip_root) {
|
||||
var words = tag.split(/\s+/);
|
||||
var z = {'0': words[0]};
|
||||
var z = []; if(!skip_root) z[0] = words[0];
|
||||
if(words.length === 1) return z;
|
||||
var m = tag.match(attregexg), y, j, w, i;
|
||||
if(m) for(i = 0; i != m.length; ++i) {
|
||||
|
|
|
@ -140,7 +140,7 @@ var parse_si = function(x, opts) {
|
|||
if(!x) return null;
|
||||
var y;
|
||||
/* 18.4.12 t ST_Xstring (Plaintext String) */
|
||||
if(x[1] === 't') {
|
||||
if(x.charCodeAt(1) === 116) {
|
||||
z.t = utf8read(unescapexml(x.substr(x.indexOf(">")+1).split(/<\/t>/)[0]));
|
||||
z.r = x;
|
||||
if(html) z.h = z.t;
|
||||
|
|
|
@ -20,23 +20,23 @@ function parse_fills(t, opts) {
|
|||
/* 18.8.3 bgColor CT_Color */
|
||||
case '<bgColor':
|
||||
if(!fill.bgColor) fill.bgColor = {};
|
||||
if(y.indexed) fill.bgColor.indexed = parseInt(y.indexed);
|
||||
if(y.theme) fill.bgColor.theme = parseInt(y.theme);
|
||||
if(y.indexed) fill.bgColor.indexed = Number(y.indexed);
|
||||
if(y.theme) fill.bgColor.theme = Number(y.theme);
|
||||
if(y.tint) fill.bgColor.tint = Number(y.tint);
|
||||
/* Excel uses ARGB strings */
|
||||
if(y.rgb) fill.bgColor.rgb = y.rgb.substring(y.rgb.length - 6);
|
||||
break;
|
||||
case '</bgColor>': break;
|
||||
case '<bgColor/>': case '</bgColor>': break;
|
||||
|
||||
/* 18.8.19 fgColor CT_Color */
|
||||
case '<fgColor':
|
||||
if(!fill.fgColor) fill.fgColor = {};
|
||||
if(y.theme) fill.fgColor.theme = parseInt(y.theme);
|
||||
if(y.theme) fill.fgColor.theme = Number(y.theme);
|
||||
if(y.tint) fill.fgColor.tint = Number(y.tint);
|
||||
/* Excel uses ARGB strings */
|
||||
if(y.rgb) fill.fgColor.rgb = y.rgb.substring(y.rgb.length - 6);
|
||||
break;
|
||||
case '</fgColor>': break;
|
||||
case '<bgColor/>': case '</fgColor>': break;
|
||||
|
||||
default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in fills';
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ function parse_clrScheme(t, opts) {
|
|||
|
||||
/* 14.2.7 Theme Part */
|
||||
function parse_theme_xml(data, opts) {
|
||||
if(!data || data.length === 0) return themes;
|
||||
themes.themeElements = {};
|
||||
|
||||
var t;
|
||||
|
|
144
bits/67_wsxml.js
144
bits/67_wsxml.js
|
@ -22,20 +22,7 @@ function parse_ws_xml(data, opts, rels) {
|
|||
if(opts.cellStyles && data.match(/<\/cols>/)) {
|
||||
/* 18.3.1.13 col CT_Col */
|
||||
var cols = data.match(/<col[^>]*\/>/g);
|
||||
var seencol = false;
|
||||
for(var coli = 0; coli != cols.length; ++coli) {
|
||||
var coll = parsexmltag(cols[coli]);
|
||||
delete coll[0];
|
||||
var colm=Number(coll.min)-1, colM=Number(coll.max)-1;
|
||||
delete coll.min, coll.max;
|
||||
if(!seencol && coll.width) { seencol = true; find_mdw(+coll.width, coll); }
|
||||
if(coll.width) {
|
||||
coll.wpx = width2px(+coll.width);
|
||||
coll.wch = px2char(coll.wpx);
|
||||
coll.MDW = MDW;
|
||||
}
|
||||
while(colm <= colM) columns[colm++] = coll;
|
||||
}
|
||||
parse_ws_xml_cols(columns, cols);
|
||||
}
|
||||
|
||||
var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} };
|
||||
|
@ -46,23 +33,34 @@ function parse_ws_xml(data, opts, rels) {
|
|||
mtch=data.match(/<(?:\w+:)?sheetData>([^\u2603]*)<\/(?:\w+:)?sheetData>/m);
|
||||
if(mtch) for(var marr = mtch[1].split(/<\/(?:\w+:)?row>/), mt = 0; mt != marr.length; ++mt) {
|
||||
x = marr[mt];
|
||||
if(x === "" || x.trim() === "") continue;
|
||||
if(x.length === 0 || x.trim().length === 0) continue;
|
||||
|
||||
/* 18.3.1.73 row CT_Row */
|
||||
var row = parsexmltag(x.match(/<(?:\w+:)?row[^>]*>/)[0]);
|
||||
for(var ri = 0; ri != x.length; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
|
||||
var row = parsexmltag(x.substr(0,ri));
|
||||
if(opts.sheetRows && opts.sheetRows < +row.r) continue;
|
||||
if(refguess.s.r > row.r - 1) refguess.s.r = row.r - 1;
|
||||
if(refguess.e.r < row.r - 1) refguess.e.r = row.r - 1;
|
||||
|
||||
/* 18.3.1.4 c CT_Cell */
|
||||
var cells = x.substr(x.indexOf('>')+1).split(/<(?:\w+:)?c /);
|
||||
var cells = x.substr(ri).split(/<(?:\w+:)?c /);
|
||||
for(var ix = 0, c=cells[0]; ix != cells.length; ++ix) {
|
||||
c = cells[ix];
|
||||
if(c === "" || c.trim() === "") continue;
|
||||
var cref = c.match(/r=["']([^"']*)["']/), idx = ix;
|
||||
if(c.length === 0 || c.trim().length === 0) continue;
|
||||
var cref = c.match(/r=["']([^"']*)["']/), idx = ix, i=0, cc=0, a1="";
|
||||
c = "<c " + c;
|
||||
if(cref && cref.length == 2) idx = decode_cell(cref[1]).c;
|
||||
var cell = parsexmltag((c.match(/<c[^>]*>/)||[c])[0]); delete cell[0];
|
||||
var d = c.substr(c.indexOf('>')+1);
|
||||
if(cref && cref.length == 2) {
|
||||
idx = 0; a1=cref[1];
|
||||
for(i=0; i != a1.length; ++i) {
|
||||
if((cc=a1.charCodeAt(i)-64) < 1 || cc > 26) break;
|
||||
idx = 26*idx + cc;
|
||||
}
|
||||
--idx;
|
||||
}
|
||||
|
||||
for(var ci = 0; ci != c.length; ++ci) if(c.charCodeAt(ci) === 62) break; ++ci;
|
||||
var cell = parsexmltag(c.substr(0,ci), true);
|
||||
var d = c.substr(ci);
|
||||
var p = {};
|
||||
|
||||
var x=d.match(match_v);if(x)p.v=unescapexml(x[1]);
|
||||
|
@ -73,7 +71,7 @@ function parse_ws_xml(data, opts, rels) {
|
|||
if(!opts.sheetStubs) continue;
|
||||
p.t = "str"; p.v = undefined;
|
||||
}
|
||||
else p.t = (cell.t ? cell.t : "n"); // default is "n" in schema
|
||||
else p.t = cell.t || "n";
|
||||
if(refguess.s.c > idx) refguess.s.c = idx;
|
||||
if(refguess.e.c < idx) refguess.e.c = idx;
|
||||
/* 18.18.11 t ST_CellType */
|
||||
|
@ -91,7 +89,7 @@ function parse_ws_xml(data, opts, rels) {
|
|||
is = is ? parse_si(is[1]) : {t:"",r:""};
|
||||
p.t = 'str'; p.v = is.t;
|
||||
break; // inline string
|
||||
case 'b': if(typeof p.v !== 'boolean') p.v = parsexmlbool(p.v); break;
|
||||
case 'b': p.v = parsexmlbool(p.v); break;
|
||||
case 'd':
|
||||
p.v = datenum(p.v);
|
||||
p.t = 'n';
|
||||
|
@ -113,22 +111,7 @@ function parse_ws_xml(data, opts, rels) {
|
|||
}
|
||||
|
||||
/* 18.3.1.48 hyperlinks CT_Hyperlinks */
|
||||
if(data.match(/<\/hyperlinks>/)) data.match(/<hyperlink[^>]*\/>/g).forEach(function(h) {
|
||||
var val = parsexmltag(h); delete val[0];
|
||||
if(!val.ref) return;
|
||||
var rel = rels['!id'][val.id];
|
||||
if(rel) {
|
||||
val.Target = rel.Target;
|
||||
if(val.location) val.Target += "#"+val.location;
|
||||
val.Rel = rel;
|
||||
}
|
||||
var rng = 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:"str",v:undefined};
|
||||
s[addr].l = val;
|
||||
}
|
||||
});
|
||||
if(data.match(/<\/hyperlinks>/)) parse_ws_xml_hlinks(s, data.match(/<hyperlink[^>]*\/>/g), rels);
|
||||
|
||||
if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
|
||||
if(opts.sheetRows && s["!ref"]) {
|
||||
|
@ -149,10 +132,56 @@ function parse_ws_xml(data, opts, rels) {
|
|||
}
|
||||
|
||||
|
||||
var WS_XML_ROOT = writextag('worksheet', null, {
|
||||
'xmlns': XMLNS.main[0],
|
||||
'xmlns:r': XMLNS.r
|
||||
});
|
||||
var parse_ws_xml_hlinks = function(s, data, rels) {
|
||||
data.forEach(function(h) {
|
||||
var val = parsexmltag(h, true);
|
||||
if(!val.ref) return;
|
||||
var rel = rels['!id'][val.id];
|
||||
if(rel) {
|
||||
val.Target = rel.Target;
|
||||
if(val.location) val.Target += "#"+val.location;
|
||||
val.Rel = rel;
|
||||
}
|
||||
var rng = 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:"str",v:undefined};
|
||||
s[addr].l = val;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var parse_ws_xml_cols = function(columns, cols) {
|
||||
var seencol = false;
|
||||
for(var coli = 0; coli != cols.length; ++coli) {
|
||||
var coll = parsexmltag(cols[coli], true);
|
||||
var colm=Number(coll.min)-1, colM=Number(coll.max)-1;
|
||||
delete coll.min; delete coll.max;
|
||||
if(!seencol && coll.width) { seencol = true; find_mdw(+coll.width, coll); }
|
||||
if(coll.width) {
|
||||
coll.wpx = width2px(+coll.width);
|
||||
coll.wch = px2char(coll.wpx);
|
||||
coll.MDW = MDW;
|
||||
}
|
||||
while(colm <= colM) columns[colm++] = coll;
|
||||
}
|
||||
};
|
||||
|
||||
var write_ws_xml_cols = function(ws, cols) {
|
||||
var o = ["<cols>"], col, width;
|
||||
for(var i = 0; i != cols.length; ++i) {
|
||||
if(!(col = cols[i])) continue;
|
||||
var p = {min:i+1,max:i+1};
|
||||
/* wch (chars), wpx (pixels) */
|
||||
width = -1;
|
||||
if(col.wpx) width = px2char(col.wpx);
|
||||
else if(col.wch) width = col.wch;
|
||||
if(width > -1) { p.width = char2width(width); p.customWidth= 1; }
|
||||
o.push(writextag('col', null, p));
|
||||
}
|
||||
o.push("</cols>");
|
||||
return o.join("");
|
||||
};
|
||||
|
||||
var write_ws_xml_cell = function(cell, ref, ws, opts, idx, wb) {
|
||||
var vv = cell.v; if(cell.t == 'b') vv = cell.v ? "1" : "0";
|
||||
|
@ -162,12 +191,12 @@ var write_ws_xml_cell = function(cell, ref, ws, opts, idx, wb) {
|
|||
/* TODO: cell style */
|
||||
if(typeof cell.v === 'undefined') return "";
|
||||
switch(cell.t) {
|
||||
case 's': case 'str': {
|
||||
case 's': case 'str':
|
||||
if(opts.bookSST) {
|
||||
v = writextag('v', String(get_sst_id(opts.Strings, cell.v)));
|
||||
o.t = "s"; return writextag('c', v, o);
|
||||
} else { o.t = "str"; return writextag('c', v, o); }
|
||||
} break;
|
||||
}
|
||||
o.t = "str"; return writextag('c', v, o);
|
||||
case 'n': delete o.t; return writextag('c', v, o);
|
||||
case 'b': o.t = "b"; return writextag('c', v, o);
|
||||
case 'e': o.t = "e"; return writextag('c', v, o);
|
||||
|
@ -188,28 +217,17 @@ var write_ws_xml_data = function(ws, opts, idx, wb) {
|
|||
return o.join("");
|
||||
};
|
||||
|
||||
var write_ws_cols = function(ws, cols) {
|
||||
var o = ["<cols>"], col, width;
|
||||
for(var i = 0; i != cols.length; ++i) {
|
||||
if(!(col = cols[i])) continue;
|
||||
var p = {min:i+1,max:i+1};
|
||||
/* wch (chars), wpx (pixels) */
|
||||
width = -1;
|
||||
if(col.wpx) width = px2char(col.wpx);
|
||||
else if(col.wch) width = col.wch;
|
||||
if(width > -1) { p.width = char2width(width); p.customWidth= 1; }
|
||||
o.push(writextag('col', null, p));
|
||||
}
|
||||
o.push("</cols>");
|
||||
return o.join("");
|
||||
};
|
||||
var WS_XML_ROOT = writextag('worksheet', null, {
|
||||
'xmlns': XMLNS.main[0],
|
||||
'xmlns:r': XMLNS.r
|
||||
});
|
||||
|
||||
var write_ws_xml = function(idx, opts, wb) {
|
||||
var o = [], s = wb.SheetNames[idx], ws = wb.Sheets[s] || {}, sidx = 0, rdata = "";
|
||||
o.push(XML_HEADER);
|
||||
o.push(WS_XML_ROOT);
|
||||
o.push(writextag('dimension', null, {'ref': ws['!ref'] || 'A1'}));
|
||||
if((ws['!cols']||[]).length > 0) o.push(write_ws_cols(ws, ws['!cols']));
|
||||
if((ws['!cols']||[]).length > 0) o.push(write_ws_xml_cols(ws, ws['!cols']));
|
||||
sidx = o.length;
|
||||
o.push(writextag('sheetData', null));
|
||||
if(ws['!ref']) rdata = write_ws_xml_data(ws, opts, idx, wb);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/* 18.2 Workbook */
|
||||
function parse_wb_xml(data) {
|
||||
function parse_wb_xml(data, opts) {
|
||||
var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
|
||||
var pass = false, xmlns = "xmlns";
|
||||
data.match(/<[^>]*>/g).forEach(function(x) {
|
||||
var y = parsexmltag(x);
|
||||
switch(y[0].replace(/<\w+:/,"<")) {
|
||||
switch(y[0].replace(/<(\/?)\w+:/,"<$1")) {
|
||||
case '<?xml': break;
|
||||
|
||||
/* 18.2.27 workbook CT_Workbook 1 */
|
||||
|
@ -26,6 +26,7 @@ function parse_wb_xml(data) {
|
|||
case '<workbookPr/>': delete y[0]; wb.WBProps = y; break;
|
||||
|
||||
/* 18.2.29 workbookProtection CT_WorkbookProtection ? */
|
||||
case '<workbookProtection': break;
|
||||
case '<workbookProtection/>': break;
|
||||
|
||||
/* 18.2.1 bookViews CT_BookViews ? */
|
||||
|
@ -44,13 +45,13 @@ function parse_wb_xml(data) {
|
|||
case '<functionGroup': break;
|
||||
|
||||
/* 18.2.9 externalReferences CT_ExternalReferences ? */
|
||||
case '<externalReferences': case '</externalReferences>': break;
|
||||
case '<externalReferences': case '</externalReferences>': case '<externalReferences>': break;
|
||||
/* 18.2.8 externalReference CT_ExternalReference + */
|
||||
case '<externalReference': break;
|
||||
|
||||
/* 18.2.6 definedNames CT_DefinedNames ? */
|
||||
case '<definedNames/>': break;
|
||||
case '<definedNames>': pass=true; break;
|
||||
case '<definedNames>': case '<definedNames': pass=true; break;
|
||||
case '</definedNames>': pass=false; break;
|
||||
/* 18.2.5 definedName CT_DefinedName + */
|
||||
case '<definedName': case '<definedName/>': case '</definedName>': break;
|
||||
|
@ -98,9 +99,11 @@ function parse_wb_xml(data) {
|
|||
case '</ext>': pass=false; break;
|
||||
|
||||
/* Others */
|
||||
case '<mx:ArchID': break;
|
||||
case '<mc:AlternateContent': pass=true; break;
|
||||
case '</mc:AlternateContent>': pass=false; break;
|
||||
case '<ArchID': break;
|
||||
case '<AlternateContent': pass=true; break;
|
||||
case '</AlternateContent>': pass=false; break;
|
||||
|
||||
default: if(!pass && opts.WTF) throw 'unrecognized ' + y[0] + ' in workbook';
|
||||
}
|
||||
});
|
||||
if(XMLNS.main.indexOf(wb.xmlns) === -1) throw new Error("Unknown Namespace: " + wb.xmlns);
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
function safe_parse_wbrels(wbrels, sheets) {
|
||||
if(!wbrels) return 0;
|
||||
try {
|
||||
wbrels = sheets.map(function(w) { return [w.name, wbrels['!id'][w.id].Target]; });
|
||||
} catch(e) { return null; }
|
||||
return !wbrels || wbrels.length === 0 ? null : wbrels;
|
||||
}
|
||||
|
||||
function safe_parse_ws(zip, path, relsPath, sheet, sheetRels, sheets, opts) {
|
||||
try {
|
||||
sheetRels[sheet]=parse_rels(getzipdata(zip, relsPath, true), path);
|
||||
sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet]);
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
}
|
||||
|
||||
function parse_zip(zip, opts) {
|
||||
make_ssf(SSF);
|
||||
opts = opts || {};
|
||||
|
@ -28,7 +43,7 @@ function parse_zip(zip, opts) {
|
|||
if(dir.style) styles = parse_sty(getzipdata(zip, dir.style.replace(/^\//,'')),dir.style, opts);
|
||||
|
||||
themes = {};
|
||||
if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipdata(zip, dir.themes[0].replace(/^\//,'')),dir.themes[0], opts);
|
||||
if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipdata(zip, dir.themes[0].replace(/^\//,''), true),dir.themes[0], opts);
|
||||
}
|
||||
|
||||
var wb = parse_wb(getzipdata(zip, dir.workbooks[0].replace(/^\//,'')), dir.workbooks[0], opts);
|
||||
|
@ -80,23 +95,17 @@ function parse_zip(zip, opts) {
|
|||
var wbext = xlsb ? "bin" : "xml";
|
||||
var wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
|
||||
var wbrels = parse_rels(getzipdata(zip, wbrelsfile, true), wbrelsfile);
|
||||
if(wbrels) try {
|
||||
wbrels = wb.Sheets.map(function(w) { return [w.name, wbrels['!id'][w.id].Target]; });
|
||||
} catch(e) { wbrels = null; }
|
||||
if(wbrels && wbrels.length === 0) wbrels = null;
|
||||
if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
|
||||
/* Numbers iOS hack */
|
||||
var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
|
||||
for(i = 0; i != props.Worksheets; ++i) {
|
||||
try {
|
||||
if(wbrels) path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
|
||||
else {
|
||||
path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
|
||||
path = path.replace(/sheet0\./,"sheet.");
|
||||
}
|
||||
relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
|
||||
sheetRels[props.SheetNames[i]]=parse_rels(getzipdata(zip, relsPath, true), path);
|
||||
sheets[props.SheetNames[i]]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[props.SheetNames[i]]);
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
if(wbrels) path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
|
||||
else {
|
||||
path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
|
||||
path = path.replace(/sheet0\./,"sheet.");
|
||||
}
|
||||
relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
|
||||
safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts);
|
||||
}
|
||||
|
||||
if(dir.comments) parse_comments(zip, dir.comments, sheets, sheetRels, opts);
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -2,7 +2,7 @@
|
|||
/* vim: set ts=2: */
|
||||
var XLSX = {};
|
||||
(function(XLSX){
|
||||
XLSX.version = '0.7.5';
|
||||
XLSX.version = '0.7.6';
|
||||
var current_codepage = 1252, current_cptable;
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
|
||||
if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel');
|
||||
|
@ -18,7 +18,7 @@ if(typeof cptable !== 'undefined') _getchar = function(x) {
|
|||
return cptable.utils.decode(current_codepage, [x%256,x>>8])[0];
|
||||
};
|
||||
|
||||
function char_codes(data) { return data.split("").map(function(x) { return x.charCodeAt(0); }); }
|
||||
function char_codes(data) { var o = []; for(var i = 0; i != data.length; ++i) o[i] = data.charCodeAt(i); return o; }
|
||||
function debom_xml(data) {
|
||||
if(typeof cptable !== 'undefined') {
|
||||
if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.substr(2))); }
|
||||
|
@ -32,7 +32,7 @@ var _strrev = function(x) { return String(x).split("").reverse().join("");};
|
|||
function fill(c,l) { return new Array(l+1).join(c); }
|
||||
function pad(v,d,c){var t=String(v);return t.length>=d?t:(fill(c||0,d-t.length)+t);}
|
||||
function rpad(v,d,c){var t=String(v);return t.length>=d?t:(t+fill(c||0,d-t.length));}
|
||||
SSF.version = '0.7.0';
|
||||
SSF.version = '0.7.1';
|
||||
/* Options */
|
||||
var opts_fmt = {
|
||||
date1904:0,
|
||||
|
@ -279,7 +279,10 @@ var write_num = function(type, fmt, val) {
|
|||
}
|
||||
if(fmt.match(/^#+0+$/)) fmt = fmt.replace(/#/g,"");
|
||||
if(fmt.match(/^00+$/)) return (val<0?"-":"")+pad(Math.round(aval),fmt.length);
|
||||
if(fmt.match(/^[#?]+$/)) return String(Math.round(val)).replace(/^0$/,"");
|
||||
if(fmt.match(/^[#?]+$/)) {
|
||||
o = String(Math.round(val)).replace(/^0$/,"");
|
||||
return o.length > fmt.length ? o : fmt.substr(0,fmt.length-o.length).replace(/#/g,"").replace(/[?]/g," ") + o;
|
||||
}
|
||||
if((r = fmt.match(/^#*0*\.(0+)/))) {
|
||||
o = Math.round(val * Math.pow(10,r[1].length));
|
||||
rr = String(o/Math.pow(10,r[1].length)).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.([0-9]*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
|
||||
|
@ -305,20 +308,32 @@ var write_num = function(type, fmt, val) {
|
|||
ff = write_num(type, "##########", val);
|
||||
return "(" + ff.substr(0,3) + ") " + ff.substr(3, 3) + "-" + ff.substr(6);
|
||||
}
|
||||
if((r = fmt.match(/^([?]+)([ ]?)\/([ ]?)([?]+)/))) {
|
||||
rr = Math.min(Math.max(r[1].length, r[4].length),7);
|
||||
var oa = "";
|
||||
if((r = fmt.match(/^([#0?]+)([ ]?)\/([ ]?)([#0?]+)/))) {
|
||||
o="";
|
||||
rr = Math.min(r[4].length,7);
|
||||
ff = frac(aval, Math.pow(10,rr)-1, false);
|
||||
return sign + (ff[0]||(ff[1] ? "" : "0")) + (ff[1] ? pad(ff[1],rr," ") + r[2] + "/" + r[3] + rpad(ff[2],rr," "): fill(" ", 2*rr+1 + r[2].length + r[3].length));
|
||||
o += sign;
|
||||
oa = write_num("n", r[1], ff[1]);
|
||||
if(oa[oa.length-1] == " ") oa = oa.substr(0,oa.length-1) + "0";
|
||||
o += oa;
|
||||
o += r[2];
|
||||
o += "/";
|
||||
o += r[3];
|
||||
oa = rpad(ff[2],rr," ");
|
||||
if(oa.length < r[4].length) oa = r[4].substr(r[4].length-oa.length).replace(/[?]/g," ").replace(/#/g,"") + oa;
|
||||
o += oa;
|
||||
return o;
|
||||
}
|
||||
if((r = fmt.match(/^# ([?]+)([ ]?)\/([ ]?)([?]+)/))) {
|
||||
if((r = fmt.match(/^# ([#0?]+)([ ]?)\/([ ]?)([#0?]+)/))) {
|
||||
rr = Math.min(Math.max(r[1].length, r[4].length),7);
|
||||
ff = frac(aval, Math.pow(10,rr)-1, true);
|
||||
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],rr," ") + r[2] + "/" + r[3] + rpad(ff[2],rr," "): fill(" ", 2*rr+1 + r[2].length + r[3].length));
|
||||
}
|
||||
if((r = fmt.match(/^[#0]+$/))) {
|
||||
if((r = fmt.match(/^[#0?]+$/))) {
|
||||
o = "" + Math.round(val);
|
||||
if(fmt.length <= o.length) return o;
|
||||
return fmt.substr(0,fmt.length - o.length).replace(/#/g,"") + o;
|
||||
return fmt.substr(0,fmt.length-o.length).replace(/#/g,"").replace(/\?/g," ") + o;
|
||||
}
|
||||
if((r = fmt.match(/^([#0]+)\.([#0]+)$/))) {
|
||||
o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
|
||||
|
@ -534,7 +549,9 @@ function eval_fmt(fmt, v, opts, flen) {
|
|||
out[i].v = write_num(out[i].t, out[i].v, (flen >1 && v < 0 && i>0 && out[i-1].v == "-" ? -v:v));
|
||||
out[i].t = 't';
|
||||
}
|
||||
return out.map(function(x){return x.v;}).join("");
|
||||
var retval = "";
|
||||
for(i=0; i != out.length; ++i) if(out[i]) retval += out[i].v;
|
||||
return retval;
|
||||
}
|
||||
SSF._eval = eval_fmt;
|
||||
function choose_fmt(fmt, v, o) {
|
||||
|
@ -651,9 +668,9 @@ var _chr = function(c) { return String.fromCharCode(c); };
|
|||
var _ord = function(c) { return c.charCodeAt(0); };
|
||||
var attregexg=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
|
||||
var attregex=/([\w:]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;
|
||||
function parsexmltag(tag) {
|
||||
function parsexmltag(tag, skip_root) {
|
||||
var words = tag.split(/\s+/);
|
||||
var z = {'0': words[0]};
|
||||
var z = []; if(!skip_root) z[0] = words[0];
|
||||
if(words.length === 1) return z;
|
||||
var m = tag.match(attregexg), y, j, w, i;
|
||||
if(m) for(i = 0; i != m.length; ++i) {
|
||||
|
@ -1475,7 +1492,7 @@ var EXT_PROPS = [
|
|||
["LinksUpToDate", "LinksUpToDate", "bool"],
|
||||
["ScaleCrop", "ScaleCrop", "bool"],
|
||||
["HeadingPairs", "HeadingPairs", "raw"],
|
||||
["TitlesOfParts", "TitlesOfParts", "raw"],
|
||||
["TitlesOfParts", "TitlesOfParts", "raw"]
|
||||
];
|
||||
|
||||
XMLNS.EXT_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
|
||||
|
@ -1750,7 +1767,7 @@ var parse_si = function(x, opts) {
|
|||
if(!x) return null;
|
||||
var y;
|
||||
/* 18.4.12 t ST_Xstring (Plaintext String) */
|
||||
if(x[1] === 't') {
|
||||
if(x.charCodeAt(1) === 116) {
|
||||
z.t = utf8read(unescapexml(x.substr(x.indexOf(">")+1).split(/<\/t>/)[0]));
|
||||
z.r = x;
|
||||
if(html) z.h = z.t;
|
||||
|
@ -1917,23 +1934,23 @@ function parse_fills(t, opts) {
|
|||
/* 18.8.3 bgColor CT_Color */
|
||||
case '<bgColor':
|
||||
if(!fill.bgColor) fill.bgColor = {};
|
||||
if(y.indexed) fill.bgColor.indexed = parseInt(y.indexed);
|
||||
if(y.theme) fill.bgColor.theme = parseInt(y.theme);
|
||||
if(y.indexed) fill.bgColor.indexed = Number(y.indexed);
|
||||
if(y.theme) fill.bgColor.theme = Number(y.theme);
|
||||
if(y.tint) fill.bgColor.tint = Number(y.tint);
|
||||
/* Excel uses ARGB strings */
|
||||
if(y.rgb) fill.bgColor.rgb = y.rgb.substring(y.rgb.length - 6);
|
||||
break;
|
||||
case '</bgColor>': break;
|
||||
case '<bgColor/>': case '</bgColor>': break;
|
||||
|
||||
/* 18.8.19 fgColor CT_Color */
|
||||
case '<fgColor':
|
||||
if(!fill.fgColor) fill.fgColor = {};
|
||||
if(y.theme) fill.fgColor.theme = parseInt(y.theme);
|
||||
if(y.theme) fill.fgColor.theme = Number(y.theme);
|
||||
if(y.tint) fill.fgColor.tint = Number(y.tint);
|
||||
/* Excel uses ARGB strings */
|
||||
if(y.rgb) fill.fgColor.rgb = y.rgb.substring(y.rgb.length - 6);
|
||||
break;
|
||||
case '</fgColor>': break;
|
||||
case '<bgColor/>': case '</fgColor>': break;
|
||||
|
||||
default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in fills';
|
||||
}
|
||||
|
@ -2243,6 +2260,7 @@ function parse_clrScheme(t, opts) {
|
|||
|
||||
/* 14.2.7 Theme Part */
|
||||
function parse_theme_xml(data, opts) {
|
||||
if(!data || data.length === 0) return themes;
|
||||
themes.themeElements = {};
|
||||
|
||||
var t;
|
||||
|
@ -2487,20 +2505,7 @@ function parse_ws_xml(data, opts, rels) {
|
|||
if(opts.cellStyles && data.match(/<\/cols>/)) {
|
||||
/* 18.3.1.13 col CT_Col */
|
||||
var cols = data.match(/<col[^>]*\/>/g);
|
||||
var seencol = false;
|
||||
for(var coli = 0; coli != cols.length; ++coli) {
|
||||
var coll = parsexmltag(cols[coli]);
|
||||
delete coll[0];
|
||||
var colm=Number(coll.min)-1, colM=Number(coll.max)-1;
|
||||
delete coll.min, coll.max;
|
||||
if(!seencol && coll.width) { seencol = true; find_mdw(+coll.width, coll); }
|
||||
if(coll.width) {
|
||||
coll.wpx = width2px(+coll.width);
|
||||
coll.wch = px2char(coll.wpx);
|
||||
coll.MDW = MDW;
|
||||
}
|
||||
while(colm <= colM) columns[colm++] = coll;
|
||||
}
|
||||
parse_ws_xml_cols(columns, cols);
|
||||
}
|
||||
|
||||
var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} };
|
||||
|
@ -2511,23 +2516,34 @@ function parse_ws_xml(data, opts, rels) {
|
|||
mtch=data.match(/<(?:\w+:)?sheetData>([^\u2603]*)<\/(?:\w+:)?sheetData>/m);
|
||||
if(mtch) for(var marr = mtch[1].split(/<\/(?:\w+:)?row>/), mt = 0; mt != marr.length; ++mt) {
|
||||
x = marr[mt];
|
||||
if(x === "" || x.trim() === "") continue;
|
||||
if(x.length === 0 || x.trim().length === 0) continue;
|
||||
|
||||
/* 18.3.1.73 row CT_Row */
|
||||
var row = parsexmltag(x.match(/<(?:\w+:)?row[^>]*>/)[0]);
|
||||
for(var ri = 0; ri != x.length; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
|
||||
var row = parsexmltag(x.substr(0,ri));
|
||||
if(opts.sheetRows && opts.sheetRows < +row.r) continue;
|
||||
if(refguess.s.r > row.r - 1) refguess.s.r = row.r - 1;
|
||||
if(refguess.e.r < row.r - 1) refguess.e.r = row.r - 1;
|
||||
|
||||
/* 18.3.1.4 c CT_Cell */
|
||||
var cells = x.substr(x.indexOf('>')+1).split(/<(?:\w+:)?c /);
|
||||
var cells = x.substr(ri).split(/<(?:\w+:)?c /);
|
||||
for(var ix = 0, c=cells[0]; ix != cells.length; ++ix) {
|
||||
c = cells[ix];
|
||||
if(c === "" || c.trim() === "") continue;
|
||||
var cref = c.match(/r=["']([^"']*)["']/), idx = ix;
|
||||
if(c.length === 0 || c.trim().length === 0) continue;
|
||||
var cref = c.match(/r=["']([^"']*)["']/), idx = ix, i=0, cc=0, a1="";
|
||||
c = "<c " + c;
|
||||
if(cref && cref.length == 2) idx = decode_cell(cref[1]).c;
|
||||
var cell = parsexmltag((c.match(/<c[^>]*>/)||[c])[0]); delete cell[0];
|
||||
var d = c.substr(c.indexOf('>')+1);
|
||||
if(cref && cref.length == 2) {
|
||||
idx = 0; a1=cref[1];
|
||||
for(i=0; i != a1.length; ++i) {
|
||||
if((cc=a1.charCodeAt(i)-64) < 1 || cc > 26) break;
|
||||
idx = 26*idx + cc;
|
||||
}
|
||||
--idx;
|
||||
}
|
||||
|
||||
for(var ci = 0; ci != c.length; ++ci) if(c.charCodeAt(ci) === 62) break; ++ci;
|
||||
var cell = parsexmltag(c.substr(0,ci), true);
|
||||
var d = c.substr(ci);
|
||||
var p = {};
|
||||
|
||||
var x=d.match(match_v);if(x)p.v=unescapexml(x[1]);
|
||||
|
@ -2538,7 +2554,7 @@ function parse_ws_xml(data, opts, rels) {
|
|||
if(!opts.sheetStubs) continue;
|
||||
p.t = "str"; p.v = undefined;
|
||||
}
|
||||
else p.t = (cell.t ? cell.t : "n"); // default is "n" in schema
|
||||
else p.t = cell.t || "n";
|
||||
if(refguess.s.c > idx) refguess.s.c = idx;
|
||||
if(refguess.e.c < idx) refguess.e.c = idx;
|
||||
/* 18.18.11 t ST_CellType */
|
||||
|
@ -2556,7 +2572,7 @@ function parse_ws_xml(data, opts, rels) {
|
|||
is = is ? parse_si(is[1]) : {t:"",r:""};
|
||||
p.t = 'str'; p.v = is.t;
|
||||
break; // inline string
|
||||
case 'b': if(typeof p.v !== 'boolean') p.v = parsexmlbool(p.v); break;
|
||||
case 'b': p.v = parsexmlbool(p.v); break;
|
||||
case 'd':
|
||||
p.v = datenum(p.v);
|
||||
p.t = 'n';
|
||||
|
@ -2578,22 +2594,7 @@ function parse_ws_xml(data, opts, rels) {
|
|||
}
|
||||
|
||||
/* 18.3.1.48 hyperlinks CT_Hyperlinks */
|
||||
if(data.match(/<\/hyperlinks>/)) data.match(/<hyperlink[^>]*\/>/g).forEach(function(h) {
|
||||
var val = parsexmltag(h); delete val[0];
|
||||
if(!val.ref) return;
|
||||
var rel = rels['!id'][val.id];
|
||||
if(rel) {
|
||||
val.Target = rel.Target;
|
||||
if(val.location) val.Target += "#"+val.location;
|
||||
val.Rel = rel;
|
||||
}
|
||||
var rng = 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:"str",v:undefined};
|
||||
s[addr].l = val;
|
||||
}
|
||||
});
|
||||
if(data.match(/<\/hyperlinks>/)) parse_ws_xml_hlinks(s, data.match(/<hyperlink[^>]*\/>/g), rels);
|
||||
|
||||
if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
|
||||
if(opts.sheetRows && s["!ref"]) {
|
||||
|
@ -2614,10 +2615,56 @@ function parse_ws_xml(data, opts, rels) {
|
|||
}
|
||||
|
||||
|
||||
var WS_XML_ROOT = writextag('worksheet', null, {
|
||||
'xmlns': XMLNS.main[0],
|
||||
'xmlns:r': XMLNS.r
|
||||
});
|
||||
var parse_ws_xml_hlinks = function(s, data, rels) {
|
||||
data.forEach(function(h) {
|
||||
var val = parsexmltag(h, true);
|
||||
if(!val.ref) return;
|
||||
var rel = rels['!id'][val.id];
|
||||
if(rel) {
|
||||
val.Target = rel.Target;
|
||||
if(val.location) val.Target += "#"+val.location;
|
||||
val.Rel = rel;
|
||||
}
|
||||
var rng = 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:"str",v:undefined};
|
||||
s[addr].l = val;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var parse_ws_xml_cols = function(columns, cols) {
|
||||
var seencol = false;
|
||||
for(var coli = 0; coli != cols.length; ++coli) {
|
||||
var coll = parsexmltag(cols[coli], true);
|
||||
var colm=Number(coll.min)-1, colM=Number(coll.max)-1;
|
||||
delete coll.min; delete coll.max;
|
||||
if(!seencol && coll.width) { seencol = true; find_mdw(+coll.width, coll); }
|
||||
if(coll.width) {
|
||||
coll.wpx = width2px(+coll.width);
|
||||
coll.wch = px2char(coll.wpx);
|
||||
coll.MDW = MDW;
|
||||
}
|
||||
while(colm <= colM) columns[colm++] = coll;
|
||||
}
|
||||
};
|
||||
|
||||
var write_ws_xml_cols = function(ws, cols) {
|
||||
var o = ["<cols>"], col, width;
|
||||
for(var i = 0; i != cols.length; ++i) {
|
||||
if(!(col = cols[i])) continue;
|
||||
var p = {min:i+1,max:i+1};
|
||||
/* wch (chars), wpx (pixels) */
|
||||
width = -1;
|
||||
if(col.wpx) width = px2char(col.wpx);
|
||||
else if(col.wch) width = col.wch;
|
||||
if(width > -1) { p.width = char2width(width); p.customWidth= 1; }
|
||||
o.push(writextag('col', null, p));
|
||||
}
|
||||
o.push("</cols>");
|
||||
return o.join("");
|
||||
};
|
||||
|
||||
var write_ws_xml_cell = function(cell, ref, ws, opts, idx, wb) {
|
||||
var vv = cell.v; if(cell.t == 'b') vv = cell.v ? "1" : "0";
|
||||
|
@ -2627,12 +2674,12 @@ var write_ws_xml_cell = function(cell, ref, ws, opts, idx, wb) {
|
|||
/* TODO: cell style */
|
||||
if(typeof cell.v === 'undefined') return "";
|
||||
switch(cell.t) {
|
||||
case 's': case 'str': {
|
||||
case 's': case 'str':
|
||||
if(opts.bookSST) {
|
||||
v = writextag('v', String(get_sst_id(opts.Strings, cell.v)));
|
||||
o.t = "s"; return writextag('c', v, o);
|
||||
} else { o.t = "str"; return writextag('c', v, o); }
|
||||
} break;
|
||||
}
|
||||
o.t = "str"; return writextag('c', v, o);
|
||||
case 'n': delete o.t; return writextag('c', v, o);
|
||||
case 'b': o.t = "b"; return writextag('c', v, o);
|
||||
case 'e': o.t = "e"; return writextag('c', v, o);
|
||||
|
@ -2653,28 +2700,17 @@ var write_ws_xml_data = function(ws, opts, idx, wb) {
|
|||
return o.join("");
|
||||
};
|
||||
|
||||
var write_ws_cols = function(ws, cols) {
|
||||
var o = ["<cols>"], col, width;
|
||||
for(var i = 0; i != cols.length; ++i) {
|
||||
if(!(col = cols[i])) continue;
|
||||
var p = {min:i+1,max:i+1};
|
||||
/* wch (chars), wpx (pixels) */
|
||||
width = -1;
|
||||
if(col.wpx) width = px2char(col.wpx);
|
||||
else if(col.wch) width = col.wch;
|
||||
if(width > -1) { p.width = char2width(width); p.customWidth= 1; }
|
||||
o.push(writextag('col', null, p));
|
||||
}
|
||||
o.push("</cols>");
|
||||
return o.join("");
|
||||
};
|
||||
var WS_XML_ROOT = writextag('worksheet', null, {
|
||||
'xmlns': XMLNS.main[0],
|
||||
'xmlns:r': XMLNS.r
|
||||
});
|
||||
|
||||
var write_ws_xml = function(idx, opts, wb) {
|
||||
var o = [], s = wb.SheetNames[idx], ws = wb.Sheets[s] || {}, sidx = 0, rdata = "";
|
||||
o.push(XML_HEADER);
|
||||
o.push(WS_XML_ROOT);
|
||||
o.push(writextag('dimension', null, {'ref': ws['!ref'] || 'A1'}));
|
||||
if((ws['!cols']||[]).length > 0) o.push(write_ws_cols(ws, ws['!cols']));
|
||||
if((ws['!cols']||[]).length > 0) o.push(write_ws_xml_cols(ws, ws['!cols']));
|
||||
sidx = o.length;
|
||||
o.push(writextag('sheetData', null));
|
||||
if(ws['!ref']) rdata = write_ws_xml_data(ws, opts, idx, wb);
|
||||
|
@ -3154,12 +3190,12 @@ var CustomWBViewDef = {
|
|||
yWindow: '0'
|
||||
};
|
||||
/* 18.2 Workbook */
|
||||
function parse_wb_xml(data) {
|
||||
function parse_wb_xml(data, opts) {
|
||||
var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
|
||||
var pass = false, xmlns = "xmlns";
|
||||
data.match(/<[^>]*>/g).forEach(function(x) {
|
||||
var y = parsexmltag(x);
|
||||
switch(y[0].replace(/<\w+:/,"<")) {
|
||||
switch(y[0].replace(/<(\/?)\w+:/,"<$1")) {
|
||||
case '<?xml': break;
|
||||
|
||||
/* 18.2.27 workbook CT_Workbook 1 */
|
||||
|
@ -3181,6 +3217,7 @@ function parse_wb_xml(data) {
|
|||
case '<workbookPr/>': delete y[0]; wb.WBProps = y; break;
|
||||
|
||||
/* 18.2.29 workbookProtection CT_WorkbookProtection ? */
|
||||
case '<workbookProtection': break;
|
||||
case '<workbookProtection/>': break;
|
||||
|
||||
/* 18.2.1 bookViews CT_BookViews ? */
|
||||
|
@ -3199,13 +3236,13 @@ function parse_wb_xml(data) {
|
|||
case '<functionGroup': break;
|
||||
|
||||
/* 18.2.9 externalReferences CT_ExternalReferences ? */
|
||||
case '<externalReferences': case '</externalReferences>': break;
|
||||
case '<externalReferences': case '</externalReferences>': case '<externalReferences>': break;
|
||||
/* 18.2.8 externalReference CT_ExternalReference + */
|
||||
case '<externalReference': break;
|
||||
|
||||
/* 18.2.6 definedNames CT_DefinedNames ? */
|
||||
case '<definedNames/>': break;
|
||||
case '<definedNames>': pass=true; break;
|
||||
case '<definedNames>': case '<definedNames': pass=true; break;
|
||||
case '</definedNames>': pass=false; break;
|
||||
/* 18.2.5 definedName CT_DefinedName + */
|
||||
case '<definedName': case '<definedName/>': case '</definedName>': break;
|
||||
|
@ -3253,9 +3290,11 @@ function parse_wb_xml(data) {
|
|||
case '</ext>': pass=false; break;
|
||||
|
||||
/* Others */
|
||||
case '<mx:ArchID': break;
|
||||
case '<mc:AlternateContent': pass=true; break;
|
||||
case '</mc:AlternateContent>': pass=false; break;
|
||||
case '<ArchID': break;
|
||||
case '<AlternateContent': pass=true; break;
|
||||
case '</AlternateContent>': pass=false; break;
|
||||
|
||||
default: if(!pass && opts.WTF) throw 'unrecognized ' + y[0] + ' in workbook';
|
||||
}
|
||||
});
|
||||
if(XMLNS.main.indexOf(wb.xmlns) === -1) throw new Error("Unknown Namespace: " + wb.xmlns);
|
||||
|
@ -4392,6 +4431,21 @@ var fix_write_opts = fix_opts([
|
|||
|
||||
['WTF', false] /* WTF mode (throws errors) */
|
||||
]);
|
||||
function safe_parse_wbrels(wbrels, sheets) {
|
||||
if(!wbrels) return 0;
|
||||
try {
|
||||
wbrels = sheets.map(function(w) { return [w.name, wbrels['!id'][w.id].Target]; });
|
||||
} catch(e) { return null; }
|
||||
return !wbrels || wbrels.length === 0 ? null : wbrels;
|
||||
}
|
||||
|
||||
function safe_parse_ws(zip, path, relsPath, sheet, sheetRels, sheets, opts) {
|
||||
try {
|
||||
sheetRels[sheet]=parse_rels(getzipdata(zip, relsPath, true), path);
|
||||
sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet]);
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
}
|
||||
|
||||
function parse_zip(zip, opts) {
|
||||
make_ssf(SSF);
|
||||
opts = opts || {};
|
||||
|
@ -4422,7 +4476,7 @@ function parse_zip(zip, opts) {
|
|||
if(dir.style) styles = parse_sty(getzipdata(zip, dir.style.replace(/^\//,'')),dir.style, opts);
|
||||
|
||||
themes = {};
|
||||
if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipdata(zip, dir.themes[0].replace(/^\//,'')),dir.themes[0], opts);
|
||||
if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipdata(zip, dir.themes[0].replace(/^\//,''), true),dir.themes[0], opts);
|
||||
}
|
||||
|
||||
var wb = parse_wb(getzipdata(zip, dir.workbooks[0].replace(/^\//,'')), dir.workbooks[0], opts);
|
||||
|
@ -4474,23 +4528,17 @@ function parse_zip(zip, opts) {
|
|||
var wbext = xlsb ? "bin" : "xml";
|
||||
var wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
|
||||
var wbrels = parse_rels(getzipdata(zip, wbrelsfile, true), wbrelsfile);
|
||||
if(wbrels) try {
|
||||
wbrels = wb.Sheets.map(function(w) { return [w.name, wbrels['!id'][w.id].Target]; });
|
||||
} catch(e) { wbrels = null; }
|
||||
if(wbrels && wbrels.length === 0) wbrels = null;
|
||||
if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
|
||||
/* Numbers iOS hack */
|
||||
var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
|
||||
for(i = 0; i != props.Worksheets; ++i) {
|
||||
try {
|
||||
if(wbrels) path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
|
||||
else {
|
||||
path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
|
||||
path = path.replace(/sheet0\./,"sheet.");
|
||||
}
|
||||
relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
|
||||
sheetRels[props.SheetNames[i]]=parse_rels(getzipdata(zip, relsPath, true), path);
|
||||
sheets[props.SheetNames[i]]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[props.SheetNames[i]]);
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
if(wbrels) path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
|
||||
else {
|
||||
path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
|
||||
path = path.replace(/sheet0\./,"sheet.");
|
||||
}
|
||||
relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
|
||||
safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts);
|
||||
}
|
||||
|
||||
if(dir.comments) parse_comments(zip, dir.comments, sheets, sheetRels, opts);
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -33,6 +33,7 @@
|
|||
<br />
|
||||
<!-- uncomment the next line here and in xlsxworker.js for encoding support -->
|
||||
<!--<script src="dist/cpexcel.js"></script>-->
|
||||
<script src="shim.js"></script>
|
||||
<script src="jszip.js"></script>
|
||||
<script src="xlsx.js"></script>
|
||||
<script>
|
||||
|
@ -106,6 +107,7 @@ function to_formulae(workbook) {
|
|||
|
||||
var tarea = document.getElementById('b64data');
|
||||
function b64it() {
|
||||
if(typeof console !== 'undefined') console.log("onload", new Date());
|
||||
var wb = XLSX.read(tarea.value, {type: 'base64'});
|
||||
process_wb(wb);
|
||||
}
|
||||
|
@ -124,6 +126,7 @@ function process_wb(wb) {
|
|||
}
|
||||
if(out.innerText === undefined) out.textContent = output;
|
||||
else out.innerText = output;
|
||||
if(typeof console !== 'undefined') console.log("output", new Date());
|
||||
}
|
||||
|
||||
var drop = document.getElementById('drop');
|
||||
|
@ -136,6 +139,7 @@ function handleDrop(e) {
|
|||
var reader = new FileReader();
|
||||
var name = f.name;
|
||||
reader.onload = function(e) {
|
||||
if(typeof console !== 'undefined') console.log("onload", new Date());
|
||||
var data = e.target.result;
|
||||
if(typeof Worker !== 'undefined') {
|
||||
xlsxworker(data, process_wb);
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
[
|
||||
["\"foo\";\"bar\";\"baz\";\"qux\"",
|
||||
[1, "foo"], [-1, "bar"], [0, "baz"], ["sheetjs", "qux"]
|
||||
],
|
||||
["\"foo\";\"bar\";\"baz\"",
|
||||
[1, "foo"], [-1, "bar"], [0, "baz"], ["sheetjs", "sheetjs"]
|
||||
],
|
||||
["\"foo\";\"bar\";@",
|
||||
[ |