forked from sheetjs/sheetjs
Miscellaneous format fixes
- SSF update to address extendscript issue (fixes #608 h/t @mjdb3d) - XLSX cellDates set date format (fixes #647 h/t @psalmody) - ODS add stub stylesheet for Excel (fixes #649 h/t @WaqasJaved1) - CSV with UTF8 BOM (fixes #650 h/t @charlesread) - DIF/CSV fuzzy date speculation - SYLK parse RC formulae - CSF utils for manipulating workbooks
This commit is contained in:
parent
a8736580a5
commit
7b4bafba49
@ -101,7 +101,7 @@ function frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/
|
||||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
}
|
||||
function general_fmt_int(v/*:number*/, opts/*:?any*/)/*:string*/ { return ""+v; }
|
||||
function general_fmt_int(v/*:number*/)/*:string*/ { return ""+v; }
|
||||
SSF._general_int = general_fmt_int;
|
||||
var general_fmt_num = (function make_general_fmt_num() {
|
||||
var gnr1 = /\.(\d*[1-9])0+$/, gnr2 = /\.0*$/, gnr4 = /\.(\d*[1-9])0+/, gnr5 = /\.0*[Ee]/, gnr6 = /(E[+-])(\d)$/;
|
||||
@ -121,11 +121,9 @@ function gfn4(o) {
|
||||
return o;
|
||||
}
|
||||
function gfn5(o) {
|
||||
//for(var i = 0; i != o.length; ++i) if(o.charCodeAt(i) === 46) return o.replace(gnr2,"").replace(gnr1,".$1");
|
||||
//return o;
|
||||
return o.indexOf(".") > -1 ? o.replace(gnr2,"").replace(gnr1,".$1") : o;
|
||||
}
|
||||
return function general_fmt_num(v/*:number*/, opts/*:?any*/)/*:string*/ {
|
||||
return function general_fmt_num(v/*:number*/)/*:string*/ {
|
||||
var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
|
||||
if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
|
||||
else if(Math.abs(V) <= 9) o = gfn2(v);
|
||||
@ -134,18 +132,18 @@ return function general_fmt_num(v/*:number*/, opts/*:?any*/)/*:string*/ {
|
||||
return gfn5(gfn4(o));
|
||||
};})();
|
||||
SSF._general_num = general_fmt_num;
|
||||
function general_fmt(v/*:any*/, opts/*:?any*/) {
|
||||
function general_fmt(v/*:any*/) {
|
||||
switch(typeof v) {
|
||||
case 'string': return v;
|
||||
case 'boolean': return v ? "TRUE" : "FALSE";
|
||||
case 'number': return (v|0) === v ? general_fmt_int(v, opts) : general_fmt_num(v, opts);
|
||||
case 'number': return (v|0) === v ? general_fmt_int(v/*, opts*/) : general_fmt_num(v/*, opts*/);
|
||||
case 'undefined': return "";
|
||||
case 'object': if(v == null) return "";
|
||||
}
|
||||
throw new Error("unsupported value in General format: " + v);
|
||||
}
|
||||
SSF._general = general_fmt;
|
||||
function fix_hijri(date, o) { return 0; }
|
||||
function fix_hijri(/*date, o*/) { return 0; }
|
||||
function parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
|
||||
if(v > 2958465 || v < 0) return null;
|
||||
var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
|
||||
@ -526,8 +524,7 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
|
||||
case "##,###":
|
||||
case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
|
||||
default:
|
||||
if(fmt.slice(-3) == ".00") return write_num_int(type, fmt.slice(0,-3), val) + ".00";
|
||||
if(fmt.slice(-2) == ".0") return write_num_int(type, fmt.slice(0,-2), val) + ".0";
|
||||
if(fmt.match(/\.[0#?]*$/)) return write_num_int(type, fmt.slice(0,fmt.lastIndexOf(".")), val) + hashq(fmt.slice(fmt.lastIndexOf(".")));
|
||||
}
|
||||
throw new Error("unsupported format |" + fmt + "|");
|
||||
}
|
||||
@ -536,8 +533,8 @@ return function write_num(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:str
|
||||
};})();
|
||||
function split_fmt(fmt/*:string*/)/*:Array<string>*/ {
|
||||
var out/*:Array<string>*/ = [];
|
||||
var in_str = false, cc;
|
||||
for(var i = 0, j = 0; i < fmt.length; ++i) switch((cc=fmt.charCodeAt(i))) {
|
||||
var in_str = false/*, cc*/;
|
||||
for(var i = 0, j = 0; i < fmt.length; ++i) switch((/*cc=*/fmt.charCodeAt(i))) {
|
||||
case 34: /* '"' */
|
||||
in_str = !in_str; break;
|
||||
case 95: case 42: case 92: /* '_' '*' '\\' */
|
||||
@ -553,11 +550,11 @@ function split_fmt(fmt/*:string*/)/*:Array<string>*/ {
|
||||
SSF._split = split_fmt;
|
||||
var abstime = /\[[HhMmSs]*\]/;
|
||||
function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
|
||||
var i = 0, cc = 0, c = "", o = "";
|
||||
var i = 0, /*cc = 0,*/ c = "", o = "";
|
||||
while(i < fmt.length) {
|
||||
switch((c = fmt.charAt(i))) {
|
||||
case 'G': if(isgeneral(fmt, i)) i+= 6; i++; break;
|
||||
case '"': for(;(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) ++i; ++i; break;
|
||||
case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) ++i; ++i; break;
|
||||
case '\\': i+=2; break;
|
||||
case '_': i+=2; break;
|
||||
case '@': ++i; break;
|
||||
@ -579,13 +576,13 @@ function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
|
||||
case '.':
|
||||
/* falls through */
|
||||
case '0': case '#':
|
||||
while(i < fmt.length && ("0#?.,E+-%".indexOf(c=fmt.charAt(++i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1)){}
|
||||
while(i < fmt.length && ("0#?.,E+-%".indexOf(c=fmt.charAt(++i)) > -1 || (c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1))){/* empty */}
|
||||
break;
|
||||
case '?': while(fmt.charAt(++i) === c){} break;
|
||||
case '?': while(fmt.charAt(++i) === c){/* empty */} break;
|
||||
case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break;
|
||||
case '(': case ')': ++i; break;
|
||||
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
||||
while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){} break;
|
||||
while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){/* empty */} break;
|
||||
case ' ': ++i; break;
|
||||
default: ++i; break;
|
||||
}
|
||||
@ -655,7 +652,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
}
|
||||
/* falls through */
|
||||
case '0': case '#':
|
||||
o = c; while(++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && i < fmt.length - 2 && "0#".indexOf(fmt.charAt(i+2))>-1) o += c;
|
||||
o = c; while((++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1) || (c=='\\' && fmt.charAt(i+1) == "-" && i < fmt.length - 2 && "0#".indexOf(fmt.charAt(i+2))>-1)) o += c;
|
||||
out[out.length] = {t:'n', v:o}; break;
|
||||
case '?':
|
||||
o = c; while(fmt.charAt(++i) === c) o+=c;
|
||||
@ -717,9 +714,9 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
jj = i+1;
|
||||
while(out[jj] != null && (
|
||||
(c=out[jj].t) === "?" || c === "D" ||
|
||||
(c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/') ||
|
||||
out[i].t === '(' && (c === ' ' || c === 'n' || c === ')') ||
|
||||
c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?')
|
||||
((c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/')) ||
|
||||
(out[i].t === '(' && (c === ' ' || c === 'n' || c === ')')) ||
|
||||
(c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?'))
|
||||
)) {
|
||||
out[i].v += out[jj].v;
|
||||
out[jj] = {v:"", t:";"}; ++jj;
|
||||
@ -773,7 +770,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
|
||||
jj = ostr.indexOf(".")+1;
|
||||
for(i=decpt; i<out.length; ++i) {
|
||||
if(out[i] == null || 'n?('.indexOf(out[i].t) === -1 && i !== decpt ) continue;
|
||||
if(out[i] == null || ('n?('.indexOf(out[i].t) === -1 && i !== decpt)) continue;
|
||||
j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0;
|
||||
vv = out[i].v.substr(0,j);
|
||||
for(; j<out[i].v.length; ++j) {
|
||||
|
@ -104,3 +104,16 @@ function dup(o/*:any*/)/*:any*/ {
|
||||
}
|
||||
|
||||
function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; }
|
||||
|
||||
/* TODO: stress test */
|
||||
function fuzzydate(s/*:string*/)/*:Date*/ {
|
||||
var o = new Date(s), n = new Date(NaN);
|
||||
var y = o.getYear(), m = o.getMonth(), d = o.getDate();
|
||||
if(isNaN(d)) return n;
|
||||
if(y < 0 || y > 8099) return n;
|
||||
if((m > 0 || d > 1) && y != 101) return o;
|
||||
if(s.toLowerCase().match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) return o;
|
||||
if(!s.match(/[a-zA-Z]/)) return o;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -89,11 +89,12 @@ function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
|
||||
for(var C = 0; C != data[R].length; ++C) {
|
||||
if(typeof data[R][C] === 'undefined') continue;
|
||||
var cell/*:Cell*/ = ({v: data[R][C] }/*:any*/);
|
||||
if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
|
||||
if(range.s.r > R) range.s.r = R;
|
||||
if(range.s.c > C) range.s.c = C;
|
||||
if(range.e.r < R) range.e.r = R;
|
||||
if(range.e.c < C) range.e.c = C;
|
||||
if(cell.v === null) { if(!o.cellStubs) continue; cell.t = 'z'; }
|
||||
if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.cellStubs) continue; else cell.t = 'z'; }
|
||||
else if(typeof cell.v === 'number') cell.t = 'n';
|
||||
else if(typeof cell.v === 'boolean') cell.t = 'b';
|
||||
else if(cell.v instanceof Date) {
|
||||
|
@ -55,3 +55,11 @@ function write_rdf(rdf, opts) {
|
||||
o.push('</rdf:RDF>');
|
||||
return o.join("");
|
||||
}
|
||||
/* TODO: pull properties */
|
||||
var write_meta_ods/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
var payload = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
|
||||
return function wmo(wb, opts) {
|
||||
return payload;
|
||||
};
|
||||
})();
|
||||
|
||||
|
@ -160,7 +160,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
|
||||
case 'T':
|
||||
var day = dd.read_shift(4), ms = dd.read_shift(4);
|
||||
throw new Error(day + " | " + ms);
|
||||
//out[R][C] = new Date(); // FIXME!!!
|
||||
//out[R][C] = new Date(); // TODO
|
||||
//break;
|
||||
case 'Y': out[R][C] = dd.read(4,'i')/1e4; break;
|
||||
case '0':
|
||||
@ -210,7 +210,9 @@ var SYLK = (function() {
|
||||
var Mval = 0, j;
|
||||
for (; ri !== records.length; ++ri) {
|
||||
Mval = 0;
|
||||
var rstr=records[ri].trim(), record=rstr.split(";"), RT=record[0], val;
|
||||
var rstr=records[ri].trim();
|
||||
var record=rstr.replace(/;;/g, "\u0001").split(";").map(function(x) { return x.replace(/\u0001/g, ";"); });
|
||||
var RT=record[0], val;
|
||||
if(rstr.length > 0) switch(RT) {
|
||||
case 'ID': break; /* header */
|
||||
case 'E': break; /* EOF */
|
||||
@ -240,17 +242,19 @@ var SYLK = (function() {
|
||||
next_cell_format = null;
|
||||
break;
|
||||
case 'E':
|
||||
/* formula = record[rj].substr(1); */
|
||||
break; /* TODO: formula */
|
||||
formula = rc_to_a1(record[rj].substr(1), {r:R,c:C});
|
||||
arr[R][C] = [arr[R][C], formula];
|
||||
break;
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
} break;
|
||||
case 'F':
|
||||
var F_seen = 0;
|
||||
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
|
||||
case 'X': C = parseInt(record[rj].substr(1))-1; break;
|
||||
case 'X': C = parseInt(record[rj].substr(1))-1; ++F_seen; break;
|
||||
case 'Y':
|
||||
R = parseInt(record[rj].substr(1))-1; C = 0;
|
||||
R = parseInt(record[rj].substr(1))-1; /*C = 0;*/
|
||||
for(j = arr.length; j <= R; ++j) arr[j] = [];
|
||||
break;
|
||||
++F_seen; break;
|
||||
case 'M': Mval = parseInt(record[rj].substr(1)) / 20; break;
|
||||
case 'F': break; /* ??? */
|
||||
case 'P':
|
||||
@ -265,14 +269,19 @@ var SYLK = (function() {
|
||||
Mval = parseInt(cw[2], 10);
|
||||
colinfo[j-1] = Mval == 0 ? {hidden:true}: {wch:Mval}; process_col(colinfo[j-1]);
|
||||
} break;
|
||||
case 'R':
|
||||
case 'C': /* default column format */
|
||||
C = parseInt(record[rj].substr(1))-1;
|
||||
if(!colinfo[C]) colinfo[C] = {};
|
||||
break;
|
||||
case 'R': /* row properties */
|
||||
R = parseInt(record[rj].substr(1))-1;
|
||||
rowinfo[R] = {};
|
||||
if(!rowinfo[R]) rowinfo[R] = {};
|
||||
if(Mval > 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); }
|
||||
else if(Mval == 0) rowinfo[R].hidden = true;
|
||||
break;
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
} break;
|
||||
}
|
||||
if(F_seen < 2) next_cell_format = null; break;
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
}
|
||||
}
|
||||
@ -387,7 +396,7 @@ var DIF = (function() {
|
||||
if(data === 'TRUE') arr[R][C] = true;
|
||||
else if(data === 'FALSE') arr[R][C] = false;
|
||||
else if(+value == +value) arr[R][C] = +value;
|
||||
else if(!isNaN(new Date(value).getDate())) arr[R][C] = parseDate(value);
|
||||
else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value);
|
||||
else arr[R][C] = value;
|
||||
++C; break;
|
||||
case 1:
|
||||
@ -519,7 +528,7 @@ var PRN = (function() {
|
||||
else if(s == "TRUE") { cell.t = 'b'; cell.v = true; }
|
||||
else if(s == "FALSE") { cell.t = 'b'; cell.v = false; }
|
||||
else if(!isNaN(v = +s)) { cell.t = 'n'; cell.w = s; cell.v = v; }
|
||||
else if(!isNaN(new Date(s).getDate())) { cell.t = 'd'; cell.v = parseDate(s); }
|
||||
else if(!isNaN(fuzzydate(s).getDate())) { cell.t = 'd'; cell.v = parseDate(s); }
|
||||
else {
|
||||
cell.t = 's';
|
||||
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
|
||||
@ -550,13 +559,16 @@ var PRN = (function() {
|
||||
}
|
||||
|
||||
function prn_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
|
||||
var str = "", bytes = firstbyte(d, opts);
|
||||
switch(opts.type) {
|
||||
case 'base64': return prn_to_sheet_str(Base64.decode(d), opts);
|
||||
case 'binary': return prn_to_sheet_str(d, opts);
|
||||
case 'buffer': return prn_to_sheet_str(d.toString('binary'), opts);
|
||||
case 'array': return prn_to_sheet_str(cc2str(d), opts);
|
||||
case 'base64': str = Base64.decode(d); break;
|
||||
case 'binary': str = d; break;
|
||||
case 'buffer': str = d.toString('binary'); break;
|
||||
case 'array': str = cc2str(d); break;
|
||||
default: throw new Error("Unrecognized type " + opts.type);
|
||||
}
|
||||
throw new Error("Unrecognized type " + opts.type);
|
||||
if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str);
|
||||
return prn_to_sheet_str(str, opts);
|
||||
}
|
||||
|
||||
function prn_to_workbook(str/*:string*/, opts)/*:Workbook*/ { return sheet_to_workbook(prn_to_sheet(str, opts), opts); }
|
||||
|
@ -198,8 +198,8 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
else {
|
||||
cell.t = 'n';
|
||||
vv = ''+(cell.v = datenum(parseDate(cell.v)));
|
||||
if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
|
||||
}
|
||||
if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
|
||||
break;
|
||||
default: vv = cell.v; break;
|
||||
}
|
||||
@ -312,8 +312,10 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
||||
}
|
||||
|
||||
if(tag.t == null && p.v === undefined) {
|
||||
if(!opts.sheetStubs) continue;
|
||||
p.t = "z";
|
||||
if(p.f || p.F) {
|
||||
p.v = 0; p.t = "n";
|
||||
} else if(!opts.sheetStubs) continue;
|
||||
else p.t = "z";
|
||||
}
|
||||
else p.t = tag.t || "n";
|
||||
if(guess.s.c > idx) guess.s.c = idx;
|
||||
|
@ -99,11 +99,20 @@ function parse_wb_defaults(wb) {
|
||||
_ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904, 'date1904');
|
||||
}
|
||||
|
||||
var badchars = "][*?\/\\".split("");
|
||||
function check_ws_name(n/*:string*/, safe/*:boolean*/)/*:boolean*/ {
|
||||
if(n.length > 31) { if(safe) return false; throw new Error("Sheet names cannot exceed 31 chars"); }
|
||||
var _good = true;
|
||||
badchars.forEach(function(c) {
|
||||
if(n.indexOf(c) == -1) return;
|
||||
if(!safe) throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
|
||||
_good = false;
|
||||
});
|
||||
return _good;
|
||||
}
|
||||
function check_wb_names(N) {
|
||||
var badchars = "][*?\/\\".split("");
|
||||
N.forEach(function(n,i) {
|
||||
badchars.forEach(function(c) { if(n.indexOf(c) > -1) throw new Error("Sheet name cannot contain : \\ / ? * [ ]"); });
|
||||
if(n.length > 31) throw new Error("Sheet names cannot exceed 31 chars");
|
||||
check_ws_name(n);
|
||||
for(var j = 0; j < i; ++j) if(n == N[j]) throw new Error("Duplicate Sheet Name: " + n);
|
||||
});
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
opts.enc = val;
|
||||
if(opts.WTF) console.error(val);
|
||||
if(!options.password) throw new Error("File is password-protected");
|
||||
if(val.Type !== 0) throw new Error("Encryption scheme unsupported");
|
||||
if(val.valid == null) throw new Error("Encryption scheme unsupported");
|
||||
if(!val.valid) throw new Error("Password is incorrect");
|
||||
break;
|
||||
case 'WriteAccess': opts.lastuser = val; break;
|
||||
@ -236,7 +236,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
case 'Template': break; // TODO
|
||||
case 'RefreshAll': wb.opts.RefreshAll = val; break;
|
||||
case 'BookBool': break; // TODO
|
||||
case 'UsesELFs': /* if(val) console.error("Unsupported ELFs"); */ break;
|
||||
case 'UsesELFs': break;
|
||||
case 'MTRSettings': break;
|
||||
case 'CalcCount': wb.opts.CalcCount = val; break;
|
||||
case 'CalcDelta': wb.opts.CalcDelta = val; break;
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* OpenDocument */
|
||||
var parse_content_xml = (function() {
|
||||
|
||||
var parse_text_p = function(text, tag) {
|
||||
@ -437,3 +438,16 @@ var parse_content_xml = (function() {
|
||||
return out;
|
||||
};
|
||||
})();
|
||||
|
||||
function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
|
||||
opts = opts || ({}/*:any*/);
|
||||
var ods = !!safegetzipfile(zip, 'objectdata');
|
||||
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
|
||||
var content = getzipstr(zip, 'content.xml');
|
||||
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
|
||||
return parse_content_xml(ods ? content : utf8read(content), opts);
|
||||
}
|
||||
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) {
|
||||
return parse_content_xml(data, opts);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,11 @@
|
||||
var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
/* OpenDocument */
|
||||
var write_styles_ods/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
var payload = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><office:document-styles xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style: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:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" office:version="1.2"></office:document-styles>';
|
||||
return function wso(wb, opts) {
|
||||
return payload;
|
||||
};
|
||||
})();
|
||||
var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
var null_cell_xml = ' <table:table-cell />\n';
|
||||
var covered_cell_xml = ' <table:covered-table-cell/>\n';
|
||||
var write_ws = function(ws, wb, i/*:number*/, opts)/*:string*/ {
|
||||
@ -61,7 +68,7 @@ var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
//case 'e':
|
||||
default: o.push(null_cell_xml); continue;
|
||||
}
|
||||
o.push(writextag('table:table-cell', writextag('text:p', textp, {}), ct));
|
||||
o.push(' ' + writextag('table:table-cell', writextag('text:p', textp, {}), ct) + '\n');
|
||||
}
|
||||
o.push(' </table:table-row>\n');
|
||||
}
|
||||
@ -143,3 +150,48 @@ var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
return o.join("");
|
||||
};
|
||||
})();
|
||||
|
||||
function write_ods(wb/*:any*/, opts/*:any*/) {
|
||||
if(opts.bookType == "fods") return write_content_ods(wb, opts);
|
||||
|
||||
/*:: if(!jszip) throw new Error("JSZip is not available"); */
|
||||
var zip = new jszip();
|
||||
var f = "";
|
||||
|
||||
var manifest/*:Array<Array<string> >*/ = [];
|
||||
var rdf = [];
|
||||
|
||||
/* 3:3.3 and 2:2.2.4 */
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_ods(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "ContentFile"]);
|
||||
|
||||
/* TODO: these are hard-coded styles to satiate excel */
|
||||
f = "styles.xml";
|
||||
zip.file(f, write_styles_ods(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "StylesFile"]);
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
f = "manifest.rdf";
|
||||
zip.file(f, write_rdf(rdf, opts));
|
||||
manifest.push([f, "application/rdf+xml"]);
|
||||
|
||||
/* TODO: this is hard-coded to satiate excel */
|
||||
f = "meta.xml";
|
||||
zip.file(f, write_meta_ods(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "MetadataFile"]);
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
f = "META-INF/manifest.xml";
|
||||
zip.file(f, write_manifest(manifest, opts));
|
||||
|
||||
return zip;
|
||||
}
|
||||
|
||||
|
@ -1,44 +0,0 @@
|
||||
/* Part 3: Packages */
|
||||
function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
|
||||
opts = opts || ({}/*:any*/);
|
||||
var ods = !!safegetzipfile(zip, 'objectdata');
|
||||
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
|
||||
var content = getzipstr(zip, 'content.xml');
|
||||
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
|
||||
return parse_content_xml(ods ? content : utf8read(content), opts);
|
||||
}
|
||||
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) {
|
||||
return parse_content_xml(data, opts);
|
||||
}
|
||||
|
||||
function write_ods(wb/*:any*/, opts/*:any*/) {
|
||||
if(opts.bookType == "fods") return write_content_xml(wb, opts);
|
||||
|
||||
/*:: if(!jszip) throw new Error("JSZip is not available"); */
|
||||
var zip = new jszip();
|
||||
var f = "";
|
||||
|
||||
var manifest/*:Array<Array<string> >*/ = [];
|
||||
var rdf = [];
|
||||
|
||||
/* 3:3.3 and 2:2.2.4 */
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "ContentFile"]);
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
f = "manifest.rdf";
|
||||
zip.file(f, write_rdf(rdf, opts));
|
||||
manifest.push([f, "application/rdf+xml"]);
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
f = "META-INF/manifest.xml";
|
||||
zip.file(f, write_manifest(manifest, opts));
|
||||
|
||||
return zip;
|
||||
}
|
@ -52,7 +52,7 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
|
||||
case 0x49: if(n[1] == 0x44) return SYLK.to_workbook(d, o); break;
|
||||
case 0x54: if(n[1] == 0x41 && n[2] == 0x42 && n[3] == 0x4C) return DIF.to_workbook(d, o); break;
|
||||
case 0x50: if(n[1] == 0x4B && n[2] < 0x20 && n[3] < 0x20) return read_zip(d, o); break;
|
||||
case 0xEF: return parse_xlml(d, o);
|
||||
case 0xEF: return n[3] == 0x3C ? parse_xlml(d, o) : PRN.to_workbook(d,o);
|
||||
case 0xFF: if(n[1] == 0xFE){ return read_utf16(d, o); } break;
|
||||
case 0x00: if(n[1] == 0x00 && n[2] >= 0x02 && n[3] == 0x00) return WK_.to_workbook(d, o); break;
|
||||
case 0x03: case 0x83: case 0x8B: return DBF.to_workbook(d, o);
|
||||
|
@ -21,7 +21,7 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/){
|
||||
var outi = 0, counter = 0;
|
||||
var dense = Array.isArray(sheet);
|
||||
var R = r.s.r, C = 0, CC = 0;
|
||||
if(!sheet[R]) sheet[R] = [];
|
||||
if(dense && !sheet[R]) sheet[R] = [];
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
cols[C] = encode_col(C);
|
||||
val = dense ? sheet[R][C] : sheet[cols[C] + rr];
|
||||
@ -189,3 +189,4 @@ var utils = {
|
||||
sheet_to_formulae: sheet_to_formulae,
|
||||
sheet_to_row_object_array: sheet_to_json
|
||||
};
|
||||
|
||||
|
103
bits/95_api.js
Normal file
103
bits/95_api.js
Normal file
@ -0,0 +1,103 @@
|
||||
(function(utils) {
|
||||
utils.consts = utils.consts || {};
|
||||
function add_consts(R) { R.forEach(function(a){ utils.consts[a[0]] = a[1]; }); }
|
||||
|
||||
function get_default(x, y, z) { return x[y] != null ? x[y] : (x[y] = z); }
|
||||
|
||||
/* get cell, creating a stub if necessary */
|
||||
function ws_get_cell_stub(ws/*:Worksheet*/, R, C/*:?number*/)/*:Cell*/ {
|
||||
/* A1 cell address */
|
||||
if(typeof R == "string") return ws[R] || (ws[R] = {t:'z'});
|
||||
/* cell address object */
|
||||
if(typeof R != "number") return ws_get_cell_stub(ws, encode_cell(R));
|
||||
/* R and C are 0-based indices */
|
||||
return ws_get_cell_stub(ws, encode_cell({r:R,c:C}));
|
||||
}
|
||||
|
||||
/* find sheet index for given name / validate index */
|
||||
function wb_sheet_idx(wb/*:Workbook*/, sh/*:number|string*/) {
|
||||
if(typeof sh == "number") {
|
||||
if(sh >= 0 && wb.SheetNames.length > sh) return sh;
|
||||
throw new Error("Cannot find sheet # " + sh);
|
||||
} else if(typeof sh == "string") {
|
||||
var idx = wb.SheetNames.indexOf(sh);
|
||||
if(idx > -1) return idx;
|
||||
throw new Error("Cannot find sheet name |" + sh + "|");
|
||||
} else throw new Error("Cannot find sheet |" + sh + "|");
|
||||
}
|
||||
|
||||
/* simple blank workbook object */
|
||||
utils.book_new = function()/*:Workbook*/ {
|
||||
return { SheetNames: [], Sheets: {} };
|
||||
};
|
||||
|
||||
/* add a worksheet to the end of a given workbook */
|
||||
utils.book_append_sheet = function(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/) {
|
||||
if(!name) for(var i = 1; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf("Sheet" + i) == -1) break;
|
||||
check_ws_name(name);
|
||||
if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!");
|
||||
|
||||
wb.SheetNames.push(name);
|
||||
wb.Sheets[name] = ws;
|
||||
};
|
||||
|
||||
/* set sheet visibility (visible/hidden/very hidden) */
|
||||
utils.book_set_sheet_visibility = function(wb/*:Workbook*/, sh/*:number|string*/, vis/*:number*/) {
|
||||
get_default(wb,"Workbook",{});
|
||||
get_default(wb.Workbook,"Sheets",[]);
|
||||
|
||||
var idx = wb_sheet_idx(wb, sh);
|
||||
get_default(wb.Workbook.Sheets,idx, {});
|
||||
|
||||
switch(vis) {
|
||||
case 0: case 1: case 2: break;
|
||||
default: throw new Error("Bad sheet visibility setting " + vis);
|
||||
}
|
||||
wb.Workbook.Sheets[idx].Hidden = vis;
|
||||
};
|
||||
add_consts([
|
||||
["SHEET_VISIBLE", 0],
|
||||
["SHEET_HIDDEN", 1],
|
||||
["SHEET_VERY_HIDDEN", 2]
|
||||
]);
|
||||
|
||||
/* set number format */
|
||||
utils.cell_set_number_format = function(cell/*:Cell*/, fmt/*:string|number*/) {
|
||||
cell.z = fmt;
|
||||
return cell;
|
||||
};
|
||||
|
||||
/* set cell hyperlink */
|
||||
utils.cell_set_hyperlink = function(cell/*:Cell*/, target/*:string*/, tooltip/*:?string*/) {
|
||||
if(!target) {
|
||||
delete cell.l;
|
||||
} else {
|
||||
cell.l = { Target: target };
|
||||
if(tooltip) cell.l.Tooltip = tooltip;
|
||||
}
|
||||
return cell;
|
||||
};
|
||||
|
||||
/* add to cell comments */
|
||||
utils.cell_add_comment = function(cell/*:Cell*/, text/*:string*/, author/*:?string*/) {
|
||||
if(!cell.c) cell.c = [];
|
||||
cell.c.push({t:text, a:author||"SheetJS"});
|
||||
};
|
||||
|
||||
/* set array formula and flush related cells */
|
||||
utils.sheet_set_array_formula = function(ws/*:Worksheet*/, range, formula/*:string*/) {
|
||||
var rng = typeof range != "string" ? range : safe_decode_range(range);
|
||||
var rngstr = typeof range == "string" ? range : encode_range(range);
|
||||
for(var R = rng.s.r; R <= rng.e.r; ++R) for(var C = rng.s.c; C <= rng.e.c; ++C) {
|
||||
var cell = ws_get_cell_stub(ws, R, C);
|
||||
cell.t = 'n';
|
||||
cell.F = rngstr;
|
||||
delete cell.v;
|
||||
if(R == rng.s.r && C == rng.s.c) cell.f = formula;
|
||||
}
|
||||
return ws;
|
||||
}
|
||||
|
||||
return utils;
|
||||
})(utils);
|
||||
|
@ -60,3 +60,4 @@ if(has_buf && typeof require != 'undefined') (function() {
|
||||
to_csv: write_csv_stream
|
||||
};
|
||||
})();
|
||||
|
||||
|
@ -26,8 +26,8 @@ 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
|
||||
# yes-csv
|
||||
number_format_entities .xls .xlsb .xlsx .xml
|
||||
pivot_table_named_range .xls .xlsb .xlsx .xml
|
||||
pivot_table_test .xls .xlsb .xlsm
|
||||
rich_text_stress .xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml
|
||||
|
37
test.js
37
test.js
@ -548,16 +548,19 @@ describe('input formats', function() {
|
||||
X.read(fs.readFileSync(paths.cstxlsb, 'binary'), {type: 'binary'});
|
||||
X.read(fs.readFileSync(paths.cstxls, 'binary'), {type: 'binary'});
|
||||
X.read(fs.readFileSync(paths.cstxml, 'binary'), {type: 'binary'});
|
||||
X.read(fs.readFileSync(paths.cstods, 'binary'), {type: 'binary'});
|
||||
});
|
||||
it('should read base64 strings', function() {
|
||||
X.read(fs.readFileSync(paths.cstxls, 'base64'), {type: 'base64'});
|
||||
X.read(fs.readFileSync(paths.cstxml, 'base64'), {type: 'base64'});
|
||||
X.read(fs.readFileSync(paths.cstods, 'base64'), {type: 'base64'});
|
||||
X.read(fs.readFileSync(paths.cstxlsx, 'base64'), {type: 'base64'});
|
||||
X.read(fs.readFileSync(paths.cstxlsb, 'base64'), {type: 'base64'});
|
||||
});
|
||||
it('should read buffers', function() {
|
||||
X.read(fs.readFileSync(paths.cstxls), {type: 'buffer'});
|
||||
X.read(fs.readFileSync(paths.cstxml), {type: 'buffer'});
|
||||
X.read(fs.readFileSync(paths.cstods), {type: 'buffer'});
|
||||
X.read(fs.readFileSync(paths.cstxlsx), {type: 'buffer'});
|
||||
X.read(fs.readFileSync(paths.cstxlsb), {type: 'buffer'});
|
||||
});
|
||||
@ -571,12 +574,14 @@ describe('input formats', function() {
|
||||
it('should throw if format is unknown', function() {
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cstxls), {type: 'dafuq'}); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cstxml), {type: 'dafuq'}); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cstods), {type: 'dafuq'}); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cstxlsx), {type: 'dafuq'}); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cstxlsb), {type: 'dafuq'}); });
|
||||
});
|
||||
it('should infer buffer type', function() {
|
||||
X.read(fs.readFileSync(paths.cstxls));
|
||||
X.read(fs.readFileSync(paths.cstxml));
|
||||
X.read(fs.readFileSync(paths.cstods));
|
||||
X.read(fs.readFileSync(paths.cstxlsx));
|
||||
X.read(fs.readFileSync(paths.cstxlsb));
|
||||
});
|
||||
@ -809,8 +814,9 @@ describe('parse features', function() {
|
||||
var wb2 = X.readFile(paths.fstxlsb, opts);
|
||||
var wb3 = X.readFile(paths.fstxls, opts);
|
||||
var wb4 = X.readFile(paths.fstxml, opts);
|
||||
var wb5 = X.readFile(paths.fstods, opts);
|
||||
/* TODO */
|
||||
[wb1, wb2 /*, wb3, wb4 */].forEach(function(wb) {
|
||||
[wb1, wb2 /*, wb3, wb4, wb5 */].forEach(function(wb) {
|
||||
assert.equal(wb.Sheets.Text["!fullref"],"A1:F49");
|
||||
assert.equal(wb.Sheets.Text["!ref"],"A1:F10");
|
||||
});
|
||||
@ -821,8 +827,9 @@ describe('parse features', function() {
|
||||
var wb2 = X.readFile(paths.cstxlsb, opts);
|
||||
var wb3 = X.readFile(paths.cstxls, opts);
|
||||
var wb4 = X.readFile(paths.cstxml, opts);
|
||||
var wb5 = X.readFile(paths.cstods, opts);
|
||||
/* TODO */
|
||||
[wb1, wb2 /*, wb3, wb4 */].forEach(function(wb) {
|
||||
[wb1, wb2 /*, wb3, wb4, wb5 */].forEach(function(wb) {
|
||||
assert.equal(wb.Sheets.Sheet7["!fullref"],"A1:N34");
|
||||
assert.equal(wb.Sheets.Sheet7["!ref"],"A1");
|
||||
});
|
||||
@ -1408,8 +1415,12 @@ describe('roundtrip features', function() {
|
||||
});
|
||||
});
|
||||
|
||||
function password_file(x){return x.match(/^password.*\.xls$/); }
|
||||
var password_files = fs.readdirSync('test_files').filter(password_file);
|
||||
//function password_file(x){return x.match(/^password.*\.xls$/); }
|
||||
//var password_files = fs.readdirSync('test_files').filter(password_file);
|
||||
var password_files = [
|
||||
//"password_2002_40_972000.xls",
|
||||
"password_2002_40_xor.xls"
|
||||
];
|
||||
describe('invalid files', function() {
|
||||
describe('parse', function() { [
|
||||
['password', 'apachepoi_password.xls'],
|
||||
@ -1765,10 +1776,20 @@ describe('encryption', function() {
|
||||
password_files.forEach(function(x) {
|
||||
describe(x, function() {
|
||||
it('should throw with no password', function() {assert.throws(function() { X.readFile(dir + x); }); });
|
||||
it('should throw with wrong password', function() {assert.throws(function() { X.readFile(dir + x, {password:'passwor',WTF:opts.WTF}); }); });
|
||||
it.skip('should recognize correct password', function() {
|
||||
try { X.readFile(dir + x, {password:'password',WTF:opts.WTF}); }
|
||||
catch(e) { if(e.message == "Password is incorrect") throw e; }
|
||||
it('should throw with wrong password', function() {
|
||||
try {
|
||||
X.readFile(dir + x, {password:'passwor',WTF:opts.WTF});
|
||||
throw new Error("incorrect password was accepted");
|
||||
} catch(e) {
|
||||
if(e.message != "Password is incorrect") throw e;
|
||||
}
|
||||
});
|
||||
it('should recognize correct password', function() {
|
||||
try {
|
||||
X.readFile(dir + x, {password:'password',WTF:opts.WTF});
|
||||
} catch(e) {
|
||||
if(e.message == "Password is incorrect") throw e;
|
||||
}
|
||||
});
|
||||
it.skip('should decrypt file', function() {
|
||||
var wb = X.readFile(dir + x, {password:'password',WTF:opts.WTF});
|
||||
|
@ -28,7 +28,7 @@ var wsrows = [
|
||||
{hpx: 24},
|
||||
{hidden:true}, // hide row
|
||||
{hidden:false}
|
||||
]
|
||||
];
|
||||
|
||||
console.log("Sheet Name: " + ws_name);
|
||||
console.log("Data: "); for(var i=0; i!=data.length; ++i) console.log(data[i]);
|
||||
@ -40,27 +40,39 @@ console.log("Columns :"); for(i=0; i!=wscols.length;++i) console.log(wscols[i]);
|
||||
if(typeof XLSX === "undefined") { try { XLSX = require('./'); } catch(e) { XLSX = require('../'); } }
|
||||
|
||||
/* blank workbook constructor */
|
||||
/*
|
||||
var wb = { SheetNames: [], Sheets: {} };
|
||||
*/
|
||||
var wb = XLSX.utils.book_new();
|
||||
|
||||
/* convert an array of arrays in JS to a CSF spreadsheet */
|
||||
var ws = XLSX.utils.aoa_to_sheet(data, {cellDates:true});
|
||||
|
||||
/* TEST: add worksheet to workbook */
|
||||
/*
|
||||
wb.SheetNames.push(ws_name);
|
||||
wb.Sheets[ws_name] = ws;
|
||||
*/
|
||||
XLSX.utils.book_append_sheet(wb, ws, ws_name);
|
||||
|
||||
/* 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"};
|
||||
*/
|
||||
XLSX.utils.sheet_set_array_formula(ws, 'D1:D1', "SUM(A1:C1*A1:C1)");
|
||||
|
||||
/* 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"};
|
||||
*/
|
||||
XLSX.utils.sheet_set_array_formula(ws, 'E1:E4', "TRANSPOSE(A1:D1)");
|
||||
ws["!ref"] = "A1:E6";
|
||||
|
||||
/* TEST: column props */
|
||||
@ -70,25 +82,40 @@ ws['!cols'] = wscols;
|
||||
ws['!rows'] = wsrows;
|
||||
|
||||
/* TEST: hyperlink note: Excel does not automatically style hyperlinks */
|
||||
/*
|
||||
ws['A3'].l = { Target: "http://sheetjs.com", Tooltip: "Visit us <SheetJS.com!>" };
|
||||
*/
|
||||
XLSX.utils.cell_set_hyperlink(ws['A3'], "http://sheetjs.com", "Visit us <SheetJS.com!>" );
|
||||
|
||||
/* TEST: built-in format */
|
||||
/*
|
||||
ws['B1'].z = "0%"; // Format Code 9
|
||||
*/
|
||||
XLSX.utils.cell_set_number_format(ws['B1'], "0%");
|
||||
|
||||
/* TEST: custom format */
|
||||
var custfmt = "\"This is \"\\ 0.0";
|
||||
/*
|
||||
ws['C2'].z = custfmt;
|
||||
*/
|
||||
XLSX.utils.cell_set_number_format(ws['C2'], custfmt);
|
||||
|
||||
/* TEST: page margins */
|
||||
ws['!margins'] = { left:1.0, right:1.0, top:1.0, bottom:1.0, header:0.5, footer:0.5 };
|
||||
|
||||
console.log("JSON Data:");console.log(XLSX.utils.sheet_to_json(ws, {header:1}));
|
||||
console.log("JSON Data:");
|
||||
console.log(XLSX.utils.sheet_to_json(ws, {header:1}));
|
||||
|
||||
/* TEST: hidden sheets */
|
||||
/*
|
||||
wb.SheetNames.push("Hidden");
|
||||
wb.Sheets["Hidden"] = XLSX.utils.aoa_to_sheet(["Hidden".split(""), [1,2,3]]);
|
||||
wb.Workbook = {Sheets:[]};
|
||||
wb.Workbook.Sheets[1] = {Hidden:1};
|
||||
*/
|
||||
var data_2 = ["Hidden".split(""), [1,2,3]];
|
||||
XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet(data_2), "Hidden");
|
||||
XLSX.utils.book_set_sheet_visibility(wb, "Hidden", XLSX.utils.consts.SHEET_HIDDEN);
|
||||
|
||||
/* TEST: properties */
|
||||
wb.Props = {
|
||||
@ -102,11 +129,14 @@ wb.Props = {
|
||||
Comments: "Nothing to say here",
|
||||
LastAuthor: "Not SheetJS",
|
||||
CreatedDate: new Date(2017,1,19)
|
||||
}
|
||||
};
|
||||
|
||||
/* TEST: comments */
|
||||
/*
|
||||
ws['A4'].c = [];
|
||||
ws['A4'].c.push({a:"SheetJS",t:"I'm a little comment, short and stout!\n\nWell, Stout may be the wrong word"});
|
||||
*/
|
||||
XLSX.utils.cell_add_comment(ws['A4'], "I'm a little comment, short and stout!\n\nWell, Stout may be the wrong word", "SheetJS");
|
||||
|
||||
/* TEST: sheet protection */
|
||||
ws['!protect'] = {
|
||||
@ -119,7 +149,7 @@ ws['!protect'] = {
|
||||
scenarios:1
|
||||
};
|
||||
|
||||
console.log("Worksheet Model:")
|
||||
console.log("Worksheet Model:");
|
||||
console.log(ws);
|
||||
|
||||
[
|
||||
|
359
xlsx.flow.js
359
xlsx.flow.js
@ -218,7 +218,7 @@ function frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/
|
||||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
}
|
||||
function general_fmt_int(v/*:number*/, opts/*:?any*/)/*:string*/ { return ""+v; }
|
||||
function general_fmt_int(v/*:number*/)/*:string*/ { return ""+v; }
|
||||
SSF._general_int = general_fmt_int;
|
||||
var general_fmt_num = (function make_general_fmt_num() {
|
||||
var gnr1 = /\.(\d*[1-9])0+$/, gnr2 = /\.0*$/, gnr4 = /\.(\d*[1-9])0+/, gnr5 = /\.0*[Ee]/, gnr6 = /(E[+-])(\d)$/;
|
||||
@ -238,11 +238,9 @@ function gfn4(o) {
|
||||
return o;
|
||||
}
|
||||
function gfn5(o) {
|
||||
//for(var i = 0; i != o.length; ++i) if(o.charCodeAt(i) === 46) return o.replace(gnr2,"").replace(gnr1,".$1");
|
||||
//return o;
|
||||
return o.indexOf(".") > -1 ? o.replace(gnr2,"").replace(gnr1,".$1") : o;
|
||||
}
|
||||
return function general_fmt_num(v/*:number*/, opts/*:?any*/)/*:string*/ {
|
||||
return function general_fmt_num(v/*:number*/)/*:string*/ {
|
||||
var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
|
||||
if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
|
||||
else if(Math.abs(V) <= 9) o = gfn2(v);
|
||||
@ -251,18 +249,18 @@ return function general_fmt_num(v/*:number*/, opts/*:?any*/)/*:string*/ {
|
||||
return gfn5(gfn4(o));
|
||||
};})();
|
||||
SSF._general_num = general_fmt_num;
|
||||
function general_fmt(v/*:any*/, opts/*:?any*/) {
|
||||
function general_fmt(v/*:any*/) {
|
||||
switch(typeof v) {
|
||||
case 'string': return v;
|
||||
case 'boolean': return v ? "TRUE" : "FALSE";
|
||||
case 'number': return (v|0) === v ? general_fmt_int(v, opts) : general_fmt_num(v, opts);
|
||||
case 'number': return (v|0) === v ? general_fmt_int(v/*, opts*/) : general_fmt_num(v/*, opts*/);
|
||||
case 'undefined': return "";
|
||||
case 'object': if(v == null) return "";
|
||||
}
|
||||
throw new Error("unsupported value in General format: " + v);
|
||||
}
|
||||
SSF._general = general_fmt;
|
||||
function fix_hijri(date, o) { return 0; }
|
||||
function fix_hijri(/*date, o*/) { return 0; }
|
||||
function parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
|
||||
if(v > 2958465 || v < 0) return null;
|
||||
var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
|
||||
@ -643,8 +641,7 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
|
||||
case "##,###":
|
||||
case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
|
||||
default:
|
||||
if(fmt.slice(-3) == ".00") return write_num_int(type, fmt.slice(0,-3), val) + ".00";
|
||||
if(fmt.slice(-2) == ".0") return write_num_int(type, fmt.slice(0,-2), val) + ".0";
|
||||
if(fmt.match(/\.[0#?]*$/)) return write_num_int(type, fmt.slice(0,fmt.lastIndexOf(".")), val) + hashq(fmt.slice(fmt.lastIndexOf(".")));
|
||||
}
|
||||
throw new Error("unsupported format |" + fmt + "|");
|
||||
}
|
||||
@ -653,8 +650,8 @@ return function write_num(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:str
|
||||
};})();
|
||||
function split_fmt(fmt/*:string*/)/*:Array<string>*/ {
|
||||
var out/*:Array<string>*/ = [];
|
||||
var in_str = false, cc;
|
||||
for(var i = 0, j = 0; i < fmt.length; ++i) switch((cc=fmt.charCodeAt(i))) {
|
||||
var in_str = false/*, cc*/;
|
||||
for(var i = 0, j = 0; i < fmt.length; ++i) switch((/*cc=*/fmt.charCodeAt(i))) {
|
||||
case 34: /* '"' */
|
||||
in_str = !in_str; break;
|
||||
case 95: case 42: case 92: /* '_' '*' '\\' */
|
||||
@ -670,11 +667,11 @@ function split_fmt(fmt/*:string*/)/*:Array<string>*/ {
|
||||
SSF._split = split_fmt;
|
||||
var abstime = /\[[HhMmSs]*\]/;
|
||||
function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
|
||||
var i = 0, cc = 0, c = "", o = "";
|
||||
var i = 0, /*cc = 0,*/ c = "", o = "";
|
||||
while(i < fmt.length) {
|
||||
switch((c = fmt.charAt(i))) {
|
||||
case 'G': if(isgeneral(fmt, i)) i+= 6; i++; break;
|
||||
case '"': for(;(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) ++i; ++i; break;
|
||||
case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) ++i; ++i; break;
|
||||
case '\\': i+=2; break;
|
||||
case '_': i+=2; break;
|
||||
case '@': ++i; break;
|
||||
@ -696,13 +693,13 @@ function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
|
||||
case '.':
|
||||
/* falls through */
|
||||
case '0': case '#':
|
||||
while(i < fmt.length && ("0#?.,E+-%".indexOf(c=fmt.charAt(++i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1)){}
|
||||
while(i < fmt.length && ("0#?.,E+-%".indexOf(c=fmt.charAt(++i)) > -1 || (c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1))){/* empty */}
|
||||
break;
|
||||
case '?': while(fmt.charAt(++i) === c){} break;
|
||||
case '?': while(fmt.charAt(++i) === c){/* empty */} break;
|
||||
case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break;
|
||||
case '(': case ')': ++i; break;
|
||||
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
||||
while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){} break;
|
||||
while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){/* empty */} break;
|
||||
case ' ': ++i; break;
|
||||
default: ++i; break;
|
||||
}
|
||||
@ -772,7 +769,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
}
|
||||
/* falls through */
|
||||
case '0': case '#':
|
||||
o = c; while(++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && i < fmt.length - 2 && "0#".indexOf(fmt.charAt(i+2))>-1) o += c;
|
||||
o = c; while((++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1) || (c=='\\' && fmt.charAt(i+1) == "-" && i < fmt.length - 2 && "0#".indexOf(fmt.charAt(i+2))>-1)) o += c;
|
||||
out[out.length] = {t:'n', v:o}; break;
|
||||
case '?':
|
||||
o = c; while(fmt.charAt(++i) === c) o+=c;
|
||||
@ -834,9 +831,9 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
jj = i+1;
|
||||
while(out[jj] != null && (
|
||||
(c=out[jj].t) === "?" || c === "D" ||
|
||||
(c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/') ||
|
||||
out[i].t === '(' && (c === ' ' || c === 'n' || c === ')') ||
|
||||
c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?')
|
||||
((c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/')) ||
|
||||
(out[i].t === '(' && (c === ' ' || c === 'n' || c === ')')) ||
|
||||
(c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?'))
|
||||
)) {
|
||||
out[i].v += out[jj].v;
|
||||
out[jj] = {v:"", t:";"}; ++jj;
|
||||
@ -890,7 +887,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
|
||||
jj = ostr.indexOf(".")+1;
|
||||
for(i=decpt; i<out.length; ++i) {
|
||||
if(out[i] == null || 'n?('.indexOf(out[i].t) === -1 && i !== decpt ) continue;
|
||||
if(out[i] == null || ('n?('.indexOf(out[i].t) === -1 && i !== decpt)) continue;
|
||||
j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0;
|
||||
vv = out[i].v.substr(0,j);
|
||||
for(; j<out[i].v.length; ++j) {
|
||||
@ -1513,6 +1510,19 @@ function dup(o/*:any*/)/*:any*/ {
|
||||
}
|
||||
|
||||
function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; }
|
||||
|
||||
/* TODO: stress test */
|
||||
function fuzzydate(s/*:string*/)/*:Date*/ {
|
||||
var o = new Date(s), n = new Date(NaN);
|
||||
var y = o.getYear(), m = o.getMonth(), d = o.getDate();
|
||||
if(isNaN(d)) return n;
|
||||
if(y < 0 || y > 8099) return n;
|
||||
if((m > 0 || d > 1) && y != 101) return o;
|
||||
if(s.toLowerCase().match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) return o;
|
||||
if(!s.match(/[a-zA-Z]/)) return o;
|
||||
return n;
|
||||
}
|
||||
|
||||
function getdatastr(data)/*:?string*/ {
|
||||
if(!data) return null;
|
||||
if(data.data) return debom(data.data);
|
||||
@ -2237,11 +2247,12 @@ function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
|
||||
for(var C = 0; C != data[R].length; ++C) {
|
||||
if(typeof data[R][C] === 'undefined') continue;
|
||||
var cell/*:Cell*/ = ({v: data[R][C] }/*:any*/);
|
||||
if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
|
||||
if(range.s.r > R) range.s.r = R;
|
||||
if(range.s.c > C) range.s.c = C;
|
||||
if(range.e.r < R) range.e.r = R;
|
||||
if(range.e.c < C) range.e.c = C;
|
||||
if(cell.v === null) { if(!o.cellStubs) continue; cell.t = 'z'; }
|
||||
if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.cellStubs) continue; else cell.t = 'z'; }
|
||||
else if(typeof cell.v === 'number') cell.t = 'n';
|
||||
else if(typeof cell.v === 'boolean') cell.t = 'b';
|
||||
else if(cell.v instanceof Date) {
|
||||
@ -3221,6 +3232,14 @@ function write_rdf(rdf, opts) {
|
||||
o.push('</rdf:RDF>');
|
||||
return o.join("");
|
||||
}
|
||||
/* TODO: pull properties */
|
||||
var write_meta_ods/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
var payload = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
|
||||
return function wmo(wb, opts) {
|
||||
return payload;
|
||||
};
|
||||
})();
|
||||
|
||||
/* ECMA-376 Part II 11.1 Core Properties Part */
|
||||
/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
|
||||
var CORE_PROPS/*:Array<Array<string> >*/ = [
|
||||
@ -5278,7 +5297,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
|
||||
case 'T':
|
||||
var day = dd.read_shift(4), ms = dd.read_shift(4);
|
||||
throw new Error(day + " | " + ms);
|
||||
//out[R][C] = new Date(); // FIXME!!!
|
||||
//out[R][C] = new Date(); // TODO
|
||||
//break;
|
||||
case 'Y': out[R][C] = dd.read(4,'i')/1e4; break;
|
||||
case '0':
|
||||
@ -5328,7 +5347,9 @@ var SYLK = (function() {
|
||||
var Mval = 0, j;
|
||||
for (; ri !== records.length; ++ri) {
|
||||
Mval = 0;
|
||||
var rstr=records[ri].trim(), record=rstr.split(";"), RT=record[0], val;
|
||||
var rstr=records[ri].trim();
|
||||
var record=rstr.replace(/;;/g, "\u0001").split(";").map(function(x) { return x.replace(/\u0001/g, ";"); });
|
||||
var RT=record[0], val;
|
||||
if(rstr.length > 0) switch(RT) {
|
||||
case 'ID': break; /* header */
|
||||
case 'E': break; /* EOF */
|
||||
@ -5358,17 +5379,19 @@ var SYLK = (function() {
|
||||
next_cell_format = null;
|
||||
break;
|
||||
case 'E':
|
||||
/* formula = record[rj].substr(1); */
|
||||
break; /* TODO: formula */
|
||||
formula = rc_to_a1(record[rj].substr(1), {r:R,c:C});
|
||||
arr[R][C] = [arr[R][C], formula];
|
||||
break;
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
} break;
|
||||
case 'F':
|
||||
var F_seen = 0;
|
||||
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
|
||||
case 'X': C = parseInt(record[rj].substr(1))-1; break;
|
||||
case 'X': C = parseInt(record[rj].substr(1))-1; ++F_seen; break;
|
||||
case 'Y':
|
||||
R = parseInt(record[rj].substr(1))-1; C = 0;
|
||||
R = parseInt(record[rj].substr(1))-1; /*C = 0;*/
|
||||
for(j = arr.length; j <= R; ++j) arr[j] = [];
|
||||
break;
|
||||
++F_seen; break;
|
||||
case 'M': Mval = parseInt(record[rj].substr(1)) / 20; break;
|
||||
case 'F': break; /* ??? */
|
||||
case 'P':
|
||||
@ -5383,14 +5406,19 @@ var SYLK = (function() {
|
||||
Mval = parseInt(cw[2], 10);
|
||||
colinfo[j-1] = Mval == 0 ? {hidden:true}: {wch:Mval}; process_col(colinfo[j-1]);
|
||||
} break;
|
||||
case 'R':
|
||||
case 'C': /* default column format */
|
||||
C = parseInt(record[rj].substr(1))-1;
|
||||
if(!colinfo[C]) colinfo[C] = {};
|
||||
break;
|
||||
case 'R': /* row properties */
|
||||
R = parseInt(record[rj].substr(1))-1;
|
||||
rowinfo[R] = {};
|
||||
if(!rowinfo[R]) rowinfo[R] = {};
|
||||
if(Mval > 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); }
|
||||
else if(Mval == 0) rowinfo[R].hidden = true;
|
||||
break;
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
} break;
|
||||
}
|
||||
if(F_seen < 2) next_cell_format = null; break;
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
}
|
||||
}
|
||||
@ -5505,7 +5533,7 @@ var DIF = (function() {
|
||||
if(data === 'TRUE') arr[R][C] = true;
|
||||
else if(data === 'FALSE') arr[R][C] = false;
|
||||
else if(+value == +value) arr[R][C] = +value;
|
||||
else if(!isNaN(new Date(value).getDate())) arr[R][C] = parseDate(value);
|
||||
else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value);
|
||||
else arr[R][C] = value;
|
||||
++C; break;
|
||||
case 1:
|
||||
@ -5637,7 +5665,7 @@ var PRN = (function() {
|
||||
else if(s == "TRUE") { cell.t = 'b'; cell.v = true; }
|
||||
else if(s == "FALSE") { cell.t = 'b'; cell.v = false; }
|
||||
else if(!isNaN(v = +s)) { cell.t = 'n'; cell.w = s; cell.v = v; }
|
||||
else if(!isNaN(new Date(s).getDate())) { cell.t = 'd'; cell.v = parseDate(s); }
|
||||
else if(!isNaN(fuzzydate(s).getDate())) { cell.t = 'd'; cell.v = parseDate(s); }
|
||||
else {
|
||||
cell.t = 's';
|
||||
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
|
||||
@ -5668,13 +5696,16 @@ var PRN = (function() {
|
||||
}
|
||||
|
||||
function prn_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
|
||||
var str = "", bytes = firstbyte(d, opts);
|
||||
switch(opts.type) {
|
||||
case 'base64': return prn_to_sheet_str(Base64.decode(d), opts);
|
||||
case 'binary': return prn_to_sheet_str(d, opts);
|
||||
case 'buffer': return prn_to_sheet_str(d.toString('binary'), opts);
|
||||
case 'array': return prn_to_sheet_str(cc2str(d), opts);
|
||||
case 'base64': str = Base64.decode(d); break;
|
||||
case 'binary': str = d; break;
|
||||
case 'buffer': str = d.toString('binary'); break;
|
||||
case 'array': str = cc2str(d); break;
|
||||
default: throw new Error("Unrecognized type " + opts.type);
|
||||
}
|
||||
throw new Error("Unrecognized type " + opts.type);
|
||||
if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str);
|
||||
return prn_to_sheet_str(str, opts);
|
||||
}
|
||||
|
||||
function prn_to_workbook(str/*:string*/, opts)/*:Workbook*/ { return sheet_to_workbook(prn_to_sheet(str, opts), opts); }
|
||||
@ -10788,8 +10819,8 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
else {
|
||||
cell.t = 'n';
|
||||
vv = ''+(cell.v = datenum(parseDate(cell.v)));
|
||||
if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
|
||||
}
|
||||
if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
|
||||
break;
|
||||
default: vv = cell.v; break;
|
||||
}
|
||||
@ -10902,8 +10933,10 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
||||
}
|
||||
|
||||
if(tag.t == null && p.v === undefined) {
|
||||
if(!opts.sheetStubs) continue;
|
||||
p.t = "z";
|
||||
if(p.f || p.F) {
|
||||
p.v = 0; p.t = "n";
|
||||
} else if(!opts.sheetStubs) continue;
|
||||
else p.t = "z";
|
||||
}
|
||||
else p.t = tag.t || "n";
|
||||
if(guess.s.c > idx) guess.s.c = idx;
|
||||
@ -12152,11 +12185,20 @@ function parse_wb_defaults(wb) {
|
||||
_ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904, 'date1904');
|
||||
}
|
||||
|
||||
var badchars = "][*?\/\\".split("");
|
||||
function check_ws_name(n/*:string*/, safe/*:boolean*/)/*:boolean*/ {
|
||||
if(n.length > 31) { if(safe) return false; throw new Error("Sheet names cannot exceed 31 chars"); }
|
||||
var _good = true;
|
||||
badchars.forEach(function(c) {
|
||||
if(n.indexOf(c) == -1) return;
|
||||
if(!safe) throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
|
||||
_good = false;
|
||||
});
|
||||
return _good;
|
||||
}
|
||||
function check_wb_names(N) {
|
||||
var badchars = "][*?\/\\".split("");
|
||||
N.forEach(function(n,i) {
|
||||
badchars.forEach(function(c) { if(n.indexOf(c) > -1) throw new Error("Sheet name cannot contain : \\ / ? * [ ]"); });
|
||||
if(n.length > 31) throw new Error("Sheet names cannot exceed 31 chars");
|
||||
check_ws_name(n);
|
||||
for(var j = 0; j < i; ++j) if(n == N[j]) throw new Error("Duplicate Sheet Name: " + n);
|
||||
});
|
||||
}
|
||||
@ -14009,7 +14051,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
opts.enc = val;
|
||||
if(opts.WTF) console.error(val);
|
||||
if(!options.password) throw new Error("File is password-protected");
|
||||
if(val.Type !== 0) throw new Error("Encryption scheme unsupported");
|
||||
if(val.valid == null) throw new Error("Encryption scheme unsupported");
|
||||
if(!val.valid) throw new Error("Password is incorrect");
|
||||
break;
|
||||
case 'WriteAccess': opts.lastuser = val; break;
|
||||
@ -14026,7 +14068,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
case 'Template': break; // TODO
|
||||
case 'RefreshAll': wb.opts.RefreshAll = val; break;
|
||||
case 'BookBool': break; // TODO
|
||||
case 'UsesELFs': /* if(val) console.error("Unsupported ELFs"); */ break;
|
||||
case 'UsesELFs': break;
|
||||
case 'MTRSettings': break;
|
||||
case 'CalcCount': wb.opts.CalcCount = val; break;
|
||||
case 'CalcDelta': wb.opts.CalcDelta = val; break;
|
||||
@ -16117,6 +16159,7 @@ function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
|
||||
function table_to_book(table/*:HTMLElement*/, opts/*:?any*/)/*:Workbook*/ {
|
||||
return sheet_to_workbook(parse_dom_table(table, opts), opts);
|
||||
}
|
||||
/* OpenDocument */
|
||||
var parse_content_xml = (function() {
|
||||
|
||||
var parse_text_p = function(text, tag) {
|
||||
@ -16556,7 +16599,27 @@ var parse_content_xml = (function() {
|
||||
return out;
|
||||
};
|
||||
})();
|
||||
var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
|
||||
function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
|
||||
opts = opts || ({}/*:any*/);
|
||||
var ods = !!safegetzipfile(zip, 'objectdata');
|
||||
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
|
||||
var content = getzipstr(zip, 'content.xml');
|
||||
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
|
||||
return parse_content_xml(ods ? content : utf8read(content), opts);
|
||||
}
|
||||
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) {
|
||||
return parse_content_xml(data, opts);
|
||||
}
|
||||
|
||||
/* OpenDocument */
|
||||
var write_styles_ods/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
var payload = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><office:document-styles xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style: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:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" office:version="1.2"></office:document-styles>';
|
||||
return function wso(wb, opts) {
|
||||
return payload;
|
||||
};
|
||||
})();
|
||||
var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
var null_cell_xml = ' <table:table-cell />\n';
|
||||
var covered_cell_xml = ' <table:covered-table-cell/>\n';
|
||||
var write_ws = function(ws, wb, i/*:number*/, opts)/*:string*/ {
|
||||
@ -16619,7 +16682,7 @@ var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
//case 'e':
|
||||
default: o.push(null_cell_xml); continue;
|
||||
}
|
||||
o.push(writextag('table:table-cell', writextag('text:p', textp, {}), ct));
|
||||
o.push(' ' + writextag('table:table-cell', writextag('text:p', textp, {}), ct) + '\n');
|
||||
}
|
||||
o.push(' </table:table-row>\n');
|
||||
}
|
||||
@ -16701,6 +16764,51 @@ var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
return o.join("");
|
||||
};
|
||||
})();
|
||||
|
||||
function write_ods(wb/*:any*/, opts/*:any*/) {
|
||||
if(opts.bookType == "fods") return write_content_ods(wb, opts);
|
||||
|
||||
/*:: if(!jszip) throw new Error("JSZip is not available"); */
|
||||
var zip = new jszip();
|
||||
var f = "";
|
||||
|
||||
var manifest/*:Array<Array<string> >*/ = [];
|
||||
var rdf = [];
|
||||
|
||||
/* 3:3.3 and 2:2.2.4 */
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_ods(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "ContentFile"]);
|
||||
|
||||
/* TODO: these are hard-coded styles to satiate excel */
|
||||
f = "styles.xml";
|
||||
zip.file(f, write_styles_ods(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "StylesFile"]);
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
f = "manifest.rdf";
|
||||
zip.file(f, write_rdf(rdf, opts));
|
||||
manifest.push([f, "application/rdf+xml"]);
|
||||
|
||||
/* TODO: this is hard-coded to satiate excel */
|
||||
f = "meta.xml";
|
||||
zip.file(f, write_meta_ods(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "MetadataFile"]);
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
f = "META-INF/manifest.xml";
|
||||
zip.file(f, write_manifest(manifest, opts));
|
||||
|
||||
return zip;
|
||||
}
|
||||
|
||||
/* actual implementation elsewhere, wrappers are for read/write */
|
||||
function write_obj_str(factory/*:WriteObjStrFactory*/) {
|
||||
return function write_str(wb/*:Workbook*/, o/*:WriteOpts*/)/*:string*/ {
|
||||
@ -16717,50 +16825,6 @@ var write_slk_str = write_obj_str(SYLK);
|
||||
var write_dif_str = write_obj_str(DIF);
|
||||
var write_prn_str = write_obj_str(PRN);
|
||||
var write_txt_str = write_obj_str({from_sheet:sheet_to_txt});
|
||||
/* Part 3: Packages */
|
||||
function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
|
||||
opts = opts || ({}/*:any*/);
|
||||
var ods = !!safegetzipfile(zip, 'objectdata');
|
||||
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
|
||||
var content = getzipstr(zip, 'content.xml');
|
||||
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
|
||||
return parse_content_xml(ods ? content : utf8read(content), opts);
|
||||
}
|
||||
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) {
|
||||
return parse_content_xml(data, opts);
|
||||
}
|
||||
|
||||
function write_ods(wb/*:any*/, opts/*:any*/) {
|
||||
if(opts.bookType == "fods") return write_content_xml(wb, opts);
|
||||
|
||||
/*:: if(!jszip) throw new Error("JSZip is not available"); */
|
||||
var zip = new jszip();
|
||||
var f = "";
|
||||
|
||||
var manifest/*:Array<Array<string> >*/ = [];
|
||||
var rdf = [];
|
||||
|
||||
/* 3:3.3 and 2:2.2.4 */
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "ContentFile"]);
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
f = "manifest.rdf";
|
||||
zip.file(f, write_rdf(rdf, opts));
|
||||
manifest.push([f, "application/rdf+xml"]);
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
f = "META-INF/manifest.xml";
|
||||
zip.file(f, write_manifest(manifest, opts));
|
||||
|
||||
return zip;
|
||||
}
|
||||
function fix_opts_func(defaults/*:Array<Array<any> >*/)/*:{(o:any):void}*/ {
|
||||
return function fix_opts(opts) {
|
||||
for(var i = 0; i != defaults.length; ++i) {
|
||||
@ -17199,7 +17263,7 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
|
||||
case 0x49: if(n[1] == 0x44) return SYLK.to_workbook(d, o); break;
|
||||
case 0x54: if(n[1] == 0x41 && n[2] == 0x42 && n[3] == 0x4C) return DIF.to_workbook(d, o); break;
|
||||
case 0x50: if(n[1] == 0x4B && n[2] < 0x20 && n[3] < 0x20) return read_zip(d, o); break;
|
||||
case 0xEF: return parse_xlml(d, o);
|
||||
case 0xEF: return n[3] == 0x3C ? parse_xlml(d, o) : PRN.to_workbook(d,o);
|
||||
case 0xFF: if(n[1] == 0xFE){ return read_utf16(d, o); } break;
|
||||
case 0x00: if(n[1] == 0x00 && n[2] >= 0x02 && n[3] == 0x00) return WK_.to_workbook(d, o); break;
|
||||
case 0x03: case 0x83: case 0x8B: return DBF.to_workbook(d, o);
|
||||
@ -17353,7 +17417,7 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/){
|
||||
var outi = 0, counter = 0;
|
||||
var dense = Array.isArray(sheet);
|
||||
var R = r.s.r, C = 0, CC = 0;
|
||||
if(!sheet[R]) sheet[R] = [];
|
||||
if(dense && !sheet[R]) sheet[R] = [];
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
cols[C] = encode_col(C);
|
||||
val = dense ? sheet[R][C] : sheet[cols[C] + rr];
|
||||
@ -17521,6 +17585,110 @@ var utils = {
|
||||
sheet_to_formulae: sheet_to_formulae,
|
||||
sheet_to_row_object_array: sheet_to_json
|
||||
};
|
||||
|
||||
(function(utils) {
|
||||
utils.consts = utils.consts || {};
|
||||
function add_consts(R) { R.forEach(function(a){ utils.consts[a[0]] = a[1]; }); }
|
||||
|
||||
function get_default(x, y, z) { return x[y] != null ? x[y] : (x[y] = z); }
|
||||
|
||||
/* get cell, creating a stub if necessary */
|
||||
function ws_get_cell_stub(ws/*:Worksheet*/, R, C/*:?number*/)/*:Cell*/ {
|
||||
/* A1 cell address */
|
||||
if(typeof R == "string") return ws[R] || (ws[R] = {t:'z'});
|
||||
/* cell address object */
|
||||
if(typeof R != "number") return ws_get_cell_stub(ws, encode_cell(R));
|
||||
/* R and C are 0-based indices */
|
||||
return ws_get_cell_stub(ws, encode_cell({r:R,c:C}));
|
||||
}
|
||||
|
||||
/* find sheet index for given name / validate index */
|
||||
function wb_sheet_idx(wb/*:Workbook*/, sh/*:number|string*/) {
|
||||
if(typeof sh == "number") {
|
||||
if(sh >= 0 && wb.SheetNames.length > sh) return sh;
|
||||
throw new Error("Cannot find sheet # " + sh);
|
||||
} else if(typeof sh == "string") {
|
||||
var idx = wb.SheetNames.indexOf(sh);
|
||||
if(idx > -1) return idx;
|
||||
throw new Error("Cannot find sheet name |" + sh + "|");
|
||||
} else throw new Error("Cannot find sheet |" + sh + "|");
|
||||
}
|
||||
|
||||
/* simple blank workbook object */
|
||||
utils.book_new = function()/*:Workbook*/ {
|
||||
return { SheetNames: [], Sheets: {} };
|
||||
};
|
||||
|
||||
/* add a worksheet to the end of a given workbook */
|
||||
utils.book_append_sheet = function(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/) {
|
||||
if(!name) for(var i = 1; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf("Sheet" + i) == -1) break;
|
||||
check_ws_name(name);
|
||||
if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!");
|
||||
|
||||
wb.SheetNames.push(name);
|
||||
wb.Sheets[name] = ws;
|
||||
};
|
||||
|
||||
/* set sheet visibility (visible/hidden/very hidden) */
|
||||
utils.book_set_sheet_visibility = function(wb/*:Workbook*/, sh/*:number|string*/, vis/*:number*/) {
|
||||
get_default(wb,"Workbook",{});
|
||||
get_default(wb.Workbook,"Sheets",[]);
|
||||
|
||||
var idx = wb_sheet_idx(wb, sh);
|
||||
get_default(wb.Workbook.Sheets,idx, {});
|
||||
|
||||
switch(vis) {
|
||||
case 0: case 1: case 2: break;
|
||||
default: throw new Error("Bad sheet visibility setting " + vis);
|
||||
}
|
||||
wb.Workbook.Sheets[idx].Hidden = vis;
|
||||
};
|
||||
add_consts([
|
||||
["SHEET_VISIBLE", 0],
|
||||
["SHEET_HIDDEN", 1],
|
||||
["SHEET_VERY_HIDDEN", 2]
|
||||
]);
|
||||
|
||||
/* set number format */
|
||||
utils.cell_set_number_format = function(cell/*:Cell*/, fmt/*:string|number*/) {
|
||||
cell.z = fmt;
|
||||
return cell;
|
||||
};
|
||||
|
||||
/* set cell hyperlink */
|
||||
utils.cell_set_hyperlink = function(cell/*:Cell*/, target/*:string*/, tooltip/*:?string*/) {
|
||||
if(!target) {
|
||||
delete cell.l;
|
||||
} else {
|
||||
cell.l = { Target: target };
|
||||
if(tooltip) cell.l.Tooltip = tooltip;
|
||||
}
|
||||
return cell;
|
||||
};
|
||||
|
||||
/* add to cell comments */
|
||||
utils.cell_add_comment = function(cell/*:Cell*/, text/*:string*/, author/*:?string*/) {
|
||||
if(!cell.c) cell.c = [];
|
||||
cell.c.push({t:text, a:author||"SheetJS"});
|
||||
};
|
||||
|
||||
/* set array formula and flush related cells */
|
||||
utils.sheet_set_array_formula = function(ws/*:Worksheet*/, range, formula/*:string*/) {
|
||||
var rng = typeof range != "string" ? range : safe_decode_range(range);
|
||||
var rngstr = typeof range == "string" ? range : encode_range(range);
|
||||
for(var R = rng.s.r; R <= rng.e.r; ++R) for(var C = rng.s.c; C <= rng.e.c; ++C) {
|
||||
var cell = ws_get_cell_stub(ws, R, C);
|
||||
cell.t = 'n';
|
||||
cell.F = rngstr;
|
||||
delete cell.v;
|
||||
if(R == rng.s.r && C == rng.s.c) cell.f = formula;
|
||||
}
|
||||
return ws;
|
||||
}
|
||||
|
||||
return utils;
|
||||
})(utils);
|
||||
|
||||
if(has_buf && typeof require != 'undefined') (function() {
|
||||
var Readable = require('stream').Readable;
|
||||
|
||||
@ -17583,6 +17751,7 @@ if(has_buf && typeof require != 'undefined') (function() {
|
||||
to_csv: write_csv_stream
|
||||
};
|
||||
})();
|
||||
|
||||
XLSX.parse_xlscfb = parse_xlscfb;
|
||||
XLSX.parse_ods = parse_ods;
|
||||
XLSX.parse_fods = parse_fods;
|
||||
|
357
xlsx.js
357
xlsx.js
@ -198,7 +198,7 @@ function frac(x, D, mixed) {
|
||||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
}
|
||||
function general_fmt_int(v, opts) { return ""+v; }
|
||||
function general_fmt_int(v) { return ""+v; }
|
||||
SSF._general_int = general_fmt_int;
|
||||
var general_fmt_num = (function make_general_fmt_num() {
|
||||
var gnr1 = /\.(\d*[1-9])0+$/, gnr2 = /\.0*$/, gnr4 = /\.(\d*[1-9])0+/, gnr5 = /\.0*[Ee]/, gnr6 = /(E[+-])(\d)$/;
|
||||
@ -218,11 +218,9 @@ function gfn4(o) {
|
||||
return o;
|
||||
}
|
||||
function gfn5(o) {
|
||||
//for(var i = 0; i != o.length; ++i) if(o.charCodeAt(i) === 46) return o.replace(gnr2,"").replace(gnr1,".$1");
|
||||
//return o;
|
||||
return o.indexOf(".") > -1 ? o.replace(gnr2,"").replace(gnr1,".$1") : o;
|
||||
}
|
||||
return function general_fmt_num(v, opts) {
|
||||
return function general_fmt_num(v) {
|
||||
var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
|
||||
if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
|
||||
else if(Math.abs(V) <= 9) o = gfn2(v);
|
||||
@ -231,18 +229,18 @@ return function general_fmt_num(v, opts) {
|
||||
return gfn5(gfn4(o));
|
||||
};})();
|
||||
SSF._general_num = general_fmt_num;
|
||||
function general_fmt(v, opts) {
|
||||
function general_fmt(v) {
|
||||
switch(typeof v) {
|
||||
case 'string': return v;
|
||||
case 'boolean': return v ? "TRUE" : "FALSE";
|
||||
case 'number': return (v|0) === v ? general_fmt_int(v, opts) : general_fmt_num(v, opts);
|
||||
case 'number': return (v|0) === v ? general_fmt_int(v/*, opts*/) : general_fmt_num(v/*, opts*/);
|
||||
case 'undefined': return "";
|
||||
case 'object': if(v == null) return "";
|
||||
}
|
||||
throw new Error("unsupported value in General format: " + v);
|
||||
}
|
||||
SSF._general = general_fmt;
|
||||
function fix_hijri(date, o) { return 0; }
|
||||
function fix_hijri(/*date, o*/) { return 0; }
|
||||
function parse_date_code(v,opts,b2) {
|
||||
if(v > 2958465 || v < 0) return null;
|
||||
var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
|
||||
@ -620,8 +618,7 @@ return "." + $1 + fill("0", r[1].length-$1.length); });
|
||||
case "##,###":
|
||||
case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
|
||||
default:
|
||||
if(fmt.slice(-3) == ".00") return write_num_int(type, fmt.slice(0,-3), val) + ".00";
|
||||
if(fmt.slice(-2) == ".0") return write_num_int(type, fmt.slice(0,-2), val) + ".0";
|
||||
if(fmt.match(/\.[0#?]*$/)) return write_num_int(type, fmt.slice(0,fmt.lastIndexOf(".")), val) + hashq(fmt.slice(fmt.lastIndexOf(".")));
|
||||
}
|
||||
throw new Error("unsupported format |" + fmt + "|");
|
||||
}
|
||||
@ -630,8 +627,8 @@ return function write_num(type, fmt, val) {
|
||||
};})();
|
||||
function split_fmt(fmt) {
|
||||
var out = [];
|
||||
var in_str = false, cc;
|
||||
for(var i = 0, j = 0; i < fmt.length; ++i) switch((cc=fmt.charCodeAt(i))) {
|
||||
var in_str = false/*, cc*/;
|
||||
for(var i = 0, j = 0; i < fmt.length; ++i) switch((/*cc=*/fmt.charCodeAt(i))) {
|
||||
case 34: /* '"' */
|
||||
in_str = !in_str; break;
|
||||
case 95: case 42: case 92: /* '_' '*' '\\' */
|
||||
@ -647,11 +644,11 @@ function split_fmt(fmt) {
|
||||
SSF._split = split_fmt;
|
||||
var abstime = /\[[HhMmSs]*\]/;
|
||||
function fmt_is_date(fmt) {
|
||||
var i = 0, cc = 0, c = "", o = "";
|
||||
var i = 0, /*cc = 0,*/ c = "", o = "";
|
||||
while(i < fmt.length) {
|
||||
switch((c = fmt.charAt(i))) {
|
||||
case 'G': if(isgeneral(fmt, i)) i+= 6; i++; break;
|
||||
case '"': for(;(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) ++i; ++i; break;
|
||||
case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) ++i; ++i; break;
|
||||
case '\\': i+=2; break;
|
||||
case '_': i+=2; break;
|
||||
case '@': ++i; break;
|
||||
@ -673,13 +670,13 @@ function fmt_is_date(fmt) {
|
||||
case '.':
|
||||
/* falls through */
|
||||
case '0': case '#':
|
||||
while(i < fmt.length && ("0#?.,E+-%".indexOf(c=fmt.charAt(++i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1)){}
|
||||
while(i < fmt.length && ("0#?.,E+-%".indexOf(c=fmt.charAt(++i)) > -1 || (c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1))){/* empty */}
|
||||
break;
|
||||
case '?': while(fmt.charAt(++i) === c){} break;
|
||||
case '?': while(fmt.charAt(++i) === c){/* empty */} break;
|
||||
case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break;
|
||||
case '(': case ')': ++i; break;
|
||||
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
||||
while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){} break;
|
||||
while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){/* empty */} break;
|
||||
case ' ': ++i; break;
|
||||
default: ++i; break;
|
||||
}
|
||||
@ -749,7 +746,7 @@ function eval_fmt(fmt, v, opts, flen) {
|
||||
}
|
||||
/* falls through */
|
||||
case '0': case '#':
|
||||
o = c; while(++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && i < fmt.length - 2 && "0#".indexOf(fmt.charAt(i+2))>-1) o += c;
|
||||
o = c; while((++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1) || (c=='\\' && fmt.charAt(i+1) == "-" && i < fmt.length - 2 && "0#".indexOf(fmt.charAt(i+2))>-1)) o += c;
|
||||
out[out.length] = {t:'n', v:o}; break;
|
||||
case '?':
|
||||
o = c; while(fmt.charAt(++i) === c) o+=c;
|
||||
@ -808,9 +805,9 @@ out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
|
||||
jj = i+1;
|
||||
while(out[jj] != null && (
|
||||
(c=out[jj].t) === "?" || c === "D" ||
|
||||
(c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/') ||
|
||||
out[i].t === '(' && (c === ' ' || c === 'n' || c === ')') ||
|
||||
c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?')
|
||||
((c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/')) ||
|
||||
(out[i].t === '(' && (c === ' ' || c === 'n' || c === ')')) ||
|
||||
(c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?'))
|
||||
)) {
|
||||
out[i].v += out[jj].v;
|
||||
out[jj] = {v:"", t:";"}; ++jj;
|
||||
@ -864,7 +861,7 @@ out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
|
||||
if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
|
||||
jj = ostr.indexOf(".")+1;
|
||||
for(i=decpt; i<out.length; ++i) {
|
||||
if(out[i] == null || 'n?('.indexOf(out[i].t) === -1 && i !== decpt ) continue;
|
||||
if(out[i] == null || ('n?('.indexOf(out[i].t) === -1 && i !== decpt)) continue;
|
||||
j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0;
|
||||
vv = out[i].v.substr(0,j);
|
||||
for(; j<out[i].v.length; ++j) {
|
||||
@ -1463,6 +1460,19 @@ function dup(o) {
|
||||
}
|
||||
|
||||
function fill(c,l) { var o = ""; while(o.length < l) o+=c; return o; }
|
||||
|
||||
/* TODO: stress test */
|
||||
function fuzzydate(s) {
|
||||
var o = new Date(s), n = new Date(NaN);
|
||||
var y = o.getYear(), m = o.getMonth(), d = o.getDate();
|
||||
if(isNaN(d)) return n;
|
||||
if(y < 0 || y > 8099) return n;
|
||||
if((m > 0 || d > 1) && y != 101) return o;
|
||||
if(s.toLowerCase().match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) return o;
|
||||
if(!s.match(/[a-zA-Z]/)) return o;
|
||||
return n;
|
||||
}
|
||||
|
||||
function getdatastr(data) {
|
||||
if(!data) return null;
|
||||
if(data.data) return debom(data.data);
|
||||
@ -2178,11 +2188,12 @@ function aoa_to_sheet(data, opts) {
|
||||
for(var C = 0; C != data[R].length; ++C) {
|
||||
if(typeof data[R][C] === 'undefined') continue;
|
||||
var cell = ({v: data[R][C] });
|
||||
if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
|
||||
if(range.s.r > R) range.s.r = R;
|
||||
if(range.s.c > C) range.s.c = C;
|
||||
if(range.e.r < R) range.e.r = R;
|
||||
if(range.e.c < C) range.e.c = C;
|
||||
if(cell.v === null) { if(!o.cellStubs) continue; cell.t = 'z'; }
|
||||
if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.cellStubs) continue; else cell.t = 'z'; }
|
||||
else if(typeof cell.v === 'number') cell.t = 'n';
|
||||
else if(typeof cell.v === 'boolean') cell.t = 'b';
|
||||
else if(cell.v instanceof Date) {
|
||||
@ -3162,6 +3173,14 @@ function write_rdf(rdf, opts) {
|
||||
o.push('</rdf:RDF>');
|
||||
return o.join("");
|
||||
}
|
||||
/* TODO: pull properties */
|
||||
var write_meta_ods = (function() {
|
||||
var payload = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
|
||||
return function wmo(wb, opts) {
|
||||
return payload;
|
||||
};
|
||||
})();
|
||||
|
||||
/* ECMA-376 Part II 11.1 Core Properties Part */
|
||||
/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
|
||||
var CORE_PROPS = [
|
||||
@ -5217,7 +5236,7 @@ function dbf_to_aoa(buf, opts) {
|
||||
case 'T':
|
||||
var day = dd.read_shift(4), ms = dd.read_shift(4);
|
||||
throw new Error(day + " | " + ms);
|
||||
//out[R][C] = new Date(); // FIXME!!!
|
||||
//out[R][C] = new Date(); // TODO
|
||||
//break;
|
||||
case 'Y': out[R][C] = dd.read(4,'i')/1e4; break;
|
||||
case '0':
|
||||
@ -5267,7 +5286,9 @@ var SYLK = (function() {
|
||||
var Mval = 0, j;
|
||||
for (; ri !== records.length; ++ri) {
|
||||
Mval = 0;
|
||||
var rstr=records[ri].trim(), record=rstr.split(";"), RT=record[0], val;
|
||||
var rstr=records[ri].trim();
|
||||
var record=rstr.replace(/;;/g, "\u0001").split(";").map(function(x) { return x.replace(/\u0001/g, ";"); });
|
||||
var RT=record[0], val;
|
||||
if(rstr.length > 0) switch(RT) {
|
||||
case 'ID': break; /* header */
|
||||
case 'E': break; /* EOF */
|
||||
@ -5297,17 +5318,19 @@ var SYLK = (function() {
|
||||
next_cell_format = null;
|
||||
break;
|
||||
case 'E':
|
||||
/* formula = record[rj].substr(1); */
|
||||
break; /* TODO: formula */
|
||||
formula = rc_to_a1(record[rj].substr(1), {r:R,c:C});
|
||||
arr[R][C] = [arr[R][C], formula];
|
||||
break;
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
} break;
|
||||
case 'F':
|
||||
var F_seen = 0;
|
||||
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
|
||||
case 'X': C = parseInt(record[rj].substr(1))-1; break;
|
||||
case 'X': C = parseInt(record[rj].substr(1))-1; ++F_seen; break;
|
||||
case 'Y':
|
||||
R = parseInt(record[rj].substr(1))-1; C = 0;
|
||||
R = parseInt(record[rj].substr(1))-1; /*C = 0;*/
|
||||
for(j = arr.length; j <= R; ++j) arr[j] = [];
|
||||
break;
|
||||
++F_seen; break;
|
||||
case 'M': Mval = parseInt(record[rj].substr(1)) / 20; break;
|
||||
case 'F': break; /* ??? */
|
||||
case 'P':
|
||||
@ -5322,14 +5345,19 @@ var SYLK = (function() {
|
||||
Mval = parseInt(cw[2], 10);
|
||||
colinfo[j-1] = Mval == 0 ? {hidden:true}: {wch:Mval}; process_col(colinfo[j-1]);
|
||||
} break;
|
||||
case 'R':
|
||||
case 'C': /* default column format */
|
||||
C = parseInt(record[rj].substr(1))-1;
|
||||
if(!colinfo[C]) colinfo[C] = {};
|
||||
break;
|
||||
case 'R': /* row properties */
|
||||
R = parseInt(record[rj].substr(1))-1;
|
||||
rowinfo[R] = {};
|
||||
if(!rowinfo[R]) rowinfo[R] = {};
|
||||
if(Mval > 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); }
|
||||
else if(Mval == 0) rowinfo[R].hidden = true;
|
||||
break;
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
} break;
|
||||
}
|
||||
if(F_seen < 2) next_cell_format = null; break;
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
}
|
||||
}
|
||||
@ -5444,7 +5472,7 @@ var DIF = (function() {
|
||||
if(data === 'TRUE') arr[R][C] = true;
|
||||
else if(data === 'FALSE') arr[R][C] = false;
|
||||
else if(+value == +value) arr[R][C] = +value;
|
||||
else if(!isNaN(new Date(value).getDate())) arr[R][C] = parseDate(value);
|
||||
else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value);
|
||||
else arr[R][C] = value;
|
||||
++C; break;
|
||||
case 1:
|
||||
@ -5576,7 +5604,7 @@ var PRN = (function() {
|
||||
else if(s == "TRUE") { cell.t = 'b'; cell.v = true; }
|
||||
else if(s == "FALSE") { cell.t = 'b'; cell.v = false; }
|
||||
else if(!isNaN(v = +s)) { cell.t = 'n'; cell.w = s; cell.v = v; }
|
||||
else if(!isNaN(new Date(s).getDate())) { cell.t = 'd'; cell.v = parseDate(s); }
|
||||
else if(!isNaN(fuzzydate(s).getDate())) { cell.t = 'd'; cell.v = parseDate(s); }
|
||||
else {
|
||||
cell.t = 's';
|
||||
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
|
||||
@ -5607,13 +5635,16 @@ var PRN = (function() {
|
||||
}
|
||||
|
||||
function prn_to_sheet(d, opts) {
|
||||
var str = "", bytes = firstbyte(d, opts);
|
||||
switch(opts.type) {
|
||||
case 'base64': return prn_to_sheet_str(Base64.decode(d), opts);
|
||||
case 'binary': return prn_to_sheet_str(d, opts);
|
||||
case 'buffer': return prn_to_sheet_str(d.toString('binary'), opts);
|
||||
case 'array': return prn_to_sheet_str(cc2str(d), opts);
|
||||
case 'base64': str = Base64.decode(d); break;
|
||||
case 'binary': str = d; break;
|
||||
case 'buffer': str = d.toString('binary'); break;
|
||||
case 'array': str = cc2str(d); break;
|
||||
default: throw new Error("Unrecognized type " + opts.type);
|
||||
}
|
||||
throw new Error("Unrecognized type " + opts.type);
|
||||
if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str);
|
||||
return prn_to_sheet_str(str, opts);
|
||||
}
|
||||
|
||||
function prn_to_workbook(str, opts) { return sheet_to_workbook(prn_to_sheet(str, opts), opts); }
|
||||
@ -10726,8 +10757,8 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
else {
|
||||
cell.t = 'n';
|
||||
vv = ''+(cell.v = datenum(parseDate(cell.v)));
|
||||
if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
|
||||
}
|
||||
if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
|
||||
break;
|
||||
default: vv = cell.v; break;
|
||||
}
|
||||
@ -10840,8 +10871,10 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
||||
}
|
||||
|
||||
if(tag.t == null && p.v === undefined) {
|
||||
if(!opts.sheetStubs) continue;
|
||||
p.t = "z";
|
||||
if(p.f || p.F) {
|
||||
p.v = 0; p.t = "n";
|
||||
} else if(!opts.sheetStubs) continue;
|
||||
else p.t = "z";
|
||||
}
|
||||
else p.t = tag.t || "n";
|
||||
if(guess.s.c > idx) guess.s.c = idx;
|
||||
@ -12090,11 +12123,20 @@ function parse_wb_defaults(wb) {
|
||||
_ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904, 'date1904');
|
||||
}
|
||||
|
||||
var badchars = "][*?\/\\".split("");
|
||||
function check_ws_name(n, safe) {
|
||||
if(n.length > 31) { if(safe) return false; throw new Error("Sheet names cannot exceed 31 chars"); }
|
||||
var _good = true;
|
||||
badchars.forEach(function(c) {
|
||||
if(n.indexOf(c) == -1) return;
|
||||
if(!safe) throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
|
||||
_good = false;
|
||||
});
|
||||
return _good;
|
||||
}
|
||||
function check_wb_names(N) {
|
||||
var badchars = "][*?\/\\".split("");
|
||||
N.forEach(function(n,i) {
|
||||
badchars.forEach(function(c) { if(n.indexOf(c) > -1) throw new Error("Sheet name cannot contain : \\ / ? * [ ]"); });
|
||||
if(n.length > 31) throw new Error("Sheet names cannot exceed 31 chars");
|
||||
check_ws_name(n);
|
||||
for(var j = 0; j < i; ++j) if(n == N[j]) throw new Error("Duplicate Sheet Name: " + n);
|
||||
});
|
||||
}
|
||||
@ -13943,7 +13985,7 @@ function parse_workbook(blob, options) {
|
||||
opts.enc = val;
|
||||
if(opts.WTF) console.error(val);
|
||||
if(!options.password) throw new Error("File is password-protected");
|
||||
if(val.Type !== 0) throw new Error("Encryption scheme unsupported");
|
||||
if(val.valid == null) throw new Error("Encryption scheme unsupported");
|
||||
if(!val.valid) throw new Error("Password is incorrect");
|
||||
break;
|
||||
case 'WriteAccess': opts.lastuser = val; break;
|
||||
@ -13960,7 +14002,7 @@ function parse_workbook(blob, options) {
|
||||
case 'Template': break; // TODO
|
||||
case 'RefreshAll': wb.opts.RefreshAll = val; break;
|
||||
case 'BookBool': break; // TODO
|
||||
case 'UsesELFs': /* if(val) console.error("Unsupported ELFs"); */ break;
|
||||
case 'UsesELFs': break;
|
||||
case 'MTRSettings': break;
|
||||
case 'CalcCount': wb.opts.CalcCount = val; break;
|
||||
case 'CalcDelta': wb.opts.CalcDelta = val; break;
|
||||
@ -16051,6 +16093,7 @@ function parse_dom_table(table, _opts) {
|
||||
function table_to_book(table, opts) {
|
||||
return sheet_to_workbook(parse_dom_table(table, opts), opts);
|
||||
}
|
||||
/* OpenDocument */
|
||||
var parse_content_xml = (function() {
|
||||
|
||||
var parse_text_p = function(text, tag) {
|
||||
@ -16490,7 +16533,27 @@ var parse_content_xml = (function() {
|
||||
return out;
|
||||
};
|
||||
})();
|
||||
var write_content_xml = (function() {
|
||||
|
||||
function parse_ods(zip, opts) {
|
||||
opts = opts || ({});
|
||||
var ods = !!safegetzipfile(zip, 'objectdata');
|
||||
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
|
||||
var content = getzipstr(zip, 'content.xml');
|
||||
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
|
||||
return parse_content_xml(ods ? content : utf8read(content), opts);
|
||||
}
|
||||
function parse_fods(data, opts) {
|
||||
return parse_content_xml(data, opts);
|
||||
}
|
||||
|
||||
/* OpenDocument */
|
||||
var write_styles_ods = (function() {
|
||||
var payload = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><office:document-styles xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style: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:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" office:version="1.2"></office:document-styles>';
|
||||
return function wso(wb, opts) {
|
||||
return payload;
|
||||
};
|
||||
})();
|
||||
var write_content_ods = (function() {
|
||||
var null_cell_xml = ' <table:table-cell />\n';
|
||||
var covered_cell_xml = ' <table:covered-table-cell/>\n';
|
||||
var write_ws = function(ws, wb, i, opts) {
|
||||
@ -16553,7 +16616,7 @@ var write_content_xml = (function() {
|
||||
//case 'e':
|
||||
default: o.push(null_cell_xml); continue;
|
||||
}
|
||||
o.push(writextag('table:table-cell', writextag('text:p', textp, {}), ct));
|
||||
o.push(' ' + writextag('table:table-cell', writextag('text:p', textp, {}), ct) + '\n');
|
||||
}
|
||||
o.push(' </table:table-row>\n');
|
||||
}
|
||||
@ -16635,6 +16698,50 @@ var write_content_xml = (function() {
|
||||
return o.join("");
|
||||
};
|
||||
})();
|
||||
|
||||
function write_ods(wb, opts) {
|
||||
if(opts.bookType == "fods") return write_content_ods(wb, opts);
|
||||
|
||||
var zip = new jszip();
|
||||
var f = "";
|
||||
|
||||
var manifest = [];
|
||||
var rdf = [];
|
||||
|
||||
/* 3:3.3 and 2:2.2.4 */
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_ods(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "ContentFile"]);
|
||||
|
||||
/* TODO: these are hard-coded styles to satiate excel */
|
||||
f = "styles.xml";
|
||||
zip.file(f, write_styles_ods(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "StylesFile"]);
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
f = "manifest.rdf";
|
||||
zip.file(f, write_rdf(rdf, opts));
|
||||
manifest.push([f, "application/rdf+xml"]);
|
||||
|
||||
/* TODO: this is hard-coded to satiate excel */
|
||||
f = "meta.xml";
|
||||
zip.file(f, write_meta_ods(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "MetadataFile"]);
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
f = "META-INF/manifest.xml";
|
||||
zip.file(f, write_manifest(manifest, opts));
|
||||
|
||||
return zip;
|
||||
}
|
||||
|
||||
/* actual implementation elsewhere, wrappers are for read/write */
|
||||
function write_obj_str(factory) {
|
||||
return function write_str(wb, o) {
|
||||
@ -16651,49 +16758,6 @@ var write_slk_str = write_obj_str(SYLK);
|
||||
var write_dif_str = write_obj_str(DIF);
|
||||
var write_prn_str = write_obj_str(PRN);
|
||||
var write_txt_str = write_obj_str({from_sheet:sheet_to_txt});
|
||||
/* Part 3: Packages */
|
||||
function parse_ods(zip, opts) {
|
||||
opts = opts || ({});
|
||||
var ods = !!safegetzipfile(zip, 'objectdata');
|
||||
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
|
||||
var content = getzipstr(zip, 'content.xml');
|
||||
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
|
||||
return parse_content_xml(ods ? content : utf8read(content), opts);
|
||||
}
|
||||
function parse_fods(data, opts) {
|
||||
return parse_content_xml(data, opts);
|
||||
}
|
||||
|
||||
function write_ods(wb, opts) {
|
||||
if(opts.bookType == "fods") return write_content_xml(wb, opts);
|
||||
|
||||
var zip = new jszip();
|
||||
var f = "";
|
||||
|
||||
var manifest = [];
|
||||
var rdf = [];
|
||||
|
||||
/* 3:3.3 and 2:2.2.4 */
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "ContentFile"]);
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
f = "manifest.rdf";
|
||||
zip.file(f, write_rdf(rdf, opts));
|
||||
manifest.push([f, "application/rdf+xml"]);
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
f = "META-INF/manifest.xml";
|
||||
zip.file(f, write_manifest(manifest, opts));
|
||||
|
||||
return zip;
|
||||
}
|
||||
function fix_opts_func(defaults) {
|
||||
return function fix_opts(opts) {
|
||||
for(var i = 0; i != defaults.length; ++i) {
|
||||
@ -17129,7 +17193,7 @@ function readSync(data, opts) {
|
||||
case 0x49: if(n[1] == 0x44) return SYLK.to_workbook(d, o); break;
|
||||
case 0x54: if(n[1] == 0x41 && n[2] == 0x42 && n[3] == 0x4C) return DIF.to_workbook(d, o); break;
|
||||
case 0x50: if(n[1] == 0x4B && n[2] < 0x20 && n[3] < 0x20) return read_zip(d, o); break;
|
||||
case 0xEF: return parse_xlml(d, o);
|
||||
case 0xEF: return n[3] == 0x3C ? parse_xlml(d, o) : PRN.to_workbook(d,o);
|
||||
case 0xFF: if(n[1] == 0xFE){ return read_utf16(d, o); } break;
|
||||
case 0x00: if(n[1] == 0x00 && n[2] >= 0x02 && n[3] == 0x00) return WK_.to_workbook(d, o); break;
|
||||
case 0x03: case 0x83: case 0x8B: return DBF.to_workbook(d, o);
|
||||
@ -17283,7 +17347,7 @@ function sheet_to_json(sheet, opts){
|
||||
var outi = 0, counter = 0;
|
||||
var dense = Array.isArray(sheet);
|
||||
var R = r.s.r, C = 0, CC = 0;
|
||||
if(!sheet[R]) sheet[R] = [];
|
||||
if(dense && !sheet[R]) sheet[R] = [];
|
||||
for(C = r.s.c; C <= r.e.c; ++C) {
|
||||
cols[C] = encode_col(C);
|
||||
val = dense ? sheet[R][C] : sheet[cols[C] + rr];
|
||||
@ -17451,6 +17515,110 @@ var utils = {
|
||||
sheet_to_formulae: sheet_to_formulae,
|
||||
sheet_to_row_object_array: sheet_to_json
|
||||
};
|
||||
|
||||
(function(utils) {
|
||||
utils.consts = utils.consts || {};
|
||||
function add_consts(R) { R.forEach(function(a){ utils.consts[a[0]] = a[1]; }); }
|
||||
|
||||
function get_default(x, y, z) { return x[y] != null ? x[y] : (x[y] = z); }
|
||||
|
||||
/* get cell, creating a stub if necessary */
|
||||
function ws_get_cell_stub(ws, R, C) {
|
||||
/* A1 cell address */
|
||||
if(typeof R == "string") return ws[R] || (ws[R] = {t:'z'});
|
||||
/* cell address object */
|
||||
if(typeof R != "number") return ws_get_cell_stub(ws, encode_cell(R));
|
||||
/* R and C are 0-based indices */
|
||||
return ws_get_cell_stub(ws, encode_cell({r:R,c:C}));
|
||||
}
|
||||
|
||||
/* find sheet index for given name / validate index */
|
||||
function wb_sheet_idx(wb, sh) {
|
||||
if(typeof sh == "number") {
|
||||
if(sh >= 0 && wb.SheetNames.length > sh) return sh;
|
||||
throw new Error("Cannot find sheet # " + sh);
|
||||
} else if(typeof sh == "string") {
|
||||
var idx = wb.SheetNames.indexOf(sh);
|
||||
if(idx > -1) return idx;
|
||||
throw new Error("Cannot find sheet name |" + sh + "|");
|
||||
} else throw new Error("Cannot find sheet |" + sh + "|");
|
||||
}
|
||||
|
||||
/* simple blank workbook object */
|
||||
utils.book_new = function() {
|
||||
return { SheetNames: [], Sheets: {} };
|
||||
};
|
||||
|
||||
/* add a worksheet to the end of a given workbook */
|
||||
utils.book_append_sheet = function(wb, ws, name) {
|
||||
if(!name) for(var i = 1; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf("Sheet" + i) == -1) break;
|
||||
check_ws_name(name);
|
||||
if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!");
|
||||
|
||||
wb.SheetNames.push(name);
|
||||
wb.Sheets[name] = ws;
|
||||
};
|
||||
|
||||
/* set sheet visibility (visible/hidden/very hidden) */
|
||||
utils.book_set_sheet_visibility = function(wb, sh, vis) {
|
||||
get_default(wb,"Workbook",{});
|
||||
get_default(wb.Workbook,"Sheets",[]);
|
||||
|
||||
var idx = wb_sheet_idx(wb, sh);
|
||||
get_default(wb.Workbook.Sheets,idx, {});
|
||||
|
||||
switch(vis) {
|
||||
case 0: case 1: case 2: break;
|
||||
default: throw new Error("Bad sheet visibility setting " + vis);
|
||||
}
|
||||
wb.Workbook.Sheets[idx].Hidden = vis;
|
||||
};
|
||||
add_consts([
|
||||
["SHEET_VISIBLE", 0],
|
||||
["SHEET_HIDDEN", 1],
|
||||
["SHEET_VERY_HIDDEN", 2]
|
||||
]);
|
||||
|
||||
/* set number format */
|
||||
utils.cell_set_number_format = function(cell, fmt) {
|
||||
cell.z = fmt;
|
||||
return cell;
|
||||
};
|
||||
|
||||
/* set cell hyperlink */
|
||||
utils.cell_set_hyperlink = function(cell, target, tooltip) {
|
||||
if(!target) {
|
||||
delete cell.l;
|
||||
} else {
|
||||
cell.l = { Target: target };
|
||||
if(tooltip) cell.l.Tooltip = tooltip;
|
||||
}
|
||||
return cell;
|
||||
};
|
||||
|
||||
/* add to cell comments */
|
||||
utils.cell_add_comment = function(cell, text, author) {
|
||||
if(!cell.c) cell.c = [];
|
||||
cell.c.push({t:text, a:author||"SheetJS"});
|
||||
};
|
||||
|
||||
/* set array formula and flush related cells */
|
||||
utils.sheet_set_array_formula = function(ws, range, formula) {
|
||||
var rng = typeof range != "string" ? range : safe_decode_range(range);
|
||||
var rngstr = typeof range == "string" ? range : encode_range(range);
|
||||
for(var R = rng.s.r; R <= rng.e.r; ++R) for(var C = rng.s.c; C <= rng.e.c; ++C) {
|
||||
var cell = ws_get_cell_stub(ws, R, C);
|
||||
cell.t = 'n';
|
||||
cell.F = rngstr;
|
||||
delete cell.v;
|
||||
if(R == rng.s.r && C == rng.s.c) cell.f = formula;
|
||||
}
|
||||
return ws;
|
||||
}
|
||||
|
||||
return utils;
|
||||
})(utils);
|
||||
|
||||
if(has_buf && typeof require != 'undefined') (function() {
|
||||
var Readable = require('stream').Readable;
|
||||
|
||||
@ -17513,6 +17681,7 @@ if(has_buf && typeof require != 'undefined') (function() {
|
||||
to_csv: write_csv_stream
|
||||
};
|
||||
})();
|
||||
|
||||
XLSX.parse_xlscfb = parse_xlscfb;
|
||||
XLSX.parse_ods = parse_ods;
|
||||
XLSX.parse_fods = parse_fods;
|
||||
|
Loading…
Reference in New Issue
Block a user