forked from sheetjs/sheetjs
version bump 0.3.8: more formatting
- updated SSF to 0.5.3 tests without baselines now try to generate CSV output
This commit is contained in:
parent
dd0a649c95
commit
a1ccaf511d
@ -1,19 +1,30 @@
|
||||
#!/usr/bin/env node
|
||||
/* xlsx.js (C) 2013 SheetJS -- http://sheetjs.com */
|
||||
/* xlsx.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
|
||||
var n = "xlsx";
|
||||
/* vim: set ts=2: */
|
||||
var XLSX = require('../');
|
||||
var X = require('../');
|
||||
var fs = require('fs'), program = require('commander');
|
||||
program
|
||||
.version('0.3.1')
|
||||
.version(X.version)
|
||||
.usage('[options] <file> [sheetname]')
|
||||
.option('-f, --file <file>', 'use specified workbook')
|
||||
.option('-s, --sheet <sheet>', 'print specified sheet (default first sheet)')
|
||||
.option('-l, --list-sheets', 'list sheet names and exit')
|
||||
.option('-F, --formulae', 'print formulae')
|
||||
.option('-S, --formulae', 'print formulae')
|
||||
.option('-j, --json', 'emit formatted JSON rather than CSV (all fields text)')
|
||||
.option('-J, --raw-js', 'emit raw JS object rather than CSV (raw numbers)')
|
||||
.option('-F, --field-sep <sep>', 'CSV field separator', ",")
|
||||
.option('-R, --row-sep <sep>', 'CSV row separator', "\n")
|
||||
.option('--dev', 'development mode')
|
||||
.option('--read', 'read but do not print out contents')
|
||||
.option('-q, --quiet', 'quiet mode')
|
||||
.parse(process.argv);
|
||||
.option('-q, --quiet', 'quiet mode');
|
||||
|
||||
program.on('--help', function() {
|
||||
console.log(' Support email: dev@sheetjs.com');
|
||||
console.log(' Web Demo: http://oss.sheetjs.com/js-'+n+'/');
|
||||
});
|
||||
|
||||
program.parse(process.argv);
|
||||
|
||||
var filename, sheetname = '';
|
||||
if(program.args[0]) {
|
||||
@ -24,23 +35,23 @@ if(program.sheet) sheetname = program.sheet;
|
||||
if(program.file) filename = program.file;
|
||||
|
||||
if(!filename) {
|
||||
console.error("xlsx2csv: must specify a filename");
|
||||
console.error(n + "2csv: must specify a filename");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if(!fs.existsSync(filename)) {
|
||||
console.error("xlsx2csv: " + filename + ": No such file or directory");
|
||||
console.error(n + "2csv: " + filename + ": No such file or directory");
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
if(program.dev) XLSX.verbose = 2;
|
||||
if(program.dev) X.verbose = 2;
|
||||
|
||||
var wb;
|
||||
if(program.dev) wb = XLSX.readFile(filename);
|
||||
if(program.dev) wb = X.readFile(filename);
|
||||
else try {
|
||||
wb = XLSX.readFile(filename);
|
||||
wb = X.readFile(filename);
|
||||
} catch(e) {
|
||||
var msg = (program.quiet) ? "" : "xlsx2csv: error parsing ";
|
||||
var msg = (program.quiet) ? "" : n + "2csv: error parsing ";
|
||||
msg += filename + ": " + e;
|
||||
console.error(msg);
|
||||
process.exit(3);
|
||||
@ -60,10 +71,12 @@ try {
|
||||
ws = wb.Sheets[target_sheet];
|
||||
if(!ws) throw "Sheet " + target_sheet + " cannot be found";
|
||||
} catch(e) {
|
||||
console.error("xlsx2csv: error parsing "+filename+" "+target_sheet+": " + e);
|
||||
console.error(n + "2csv: error parsing "+filename+" "+target_sheet+": " + e);
|
||||
process.exit(4);
|
||||
}
|
||||
|
||||
if(!program.quiet) console.error(target_sheet);
|
||||
if(program.formulae) console.log(XLSX.utils.get_formulae(ws).join("\n"));
|
||||
else console.log(XLSX.utils.make_csv(ws));
|
||||
if(program.formulae) console.log(X.utils.get_formulae(ws).join("\n"));
|
||||
else if(program.json) console.log(JSON.stringify(X.utils.sheet_to_row_object_array(ws)));
|
||||
else if(program.rawJs) console.log(JSON.stringify(X.utils.sheet_to_row_object_array(ws,{raw:true})));
|
||||
else console.log(X.utils.make_csv(ws, {FS:program.fieldSep, RS:program.rowSep}));
|
||||
|
194
bits/10_ssf.js
194
bits/10_ssf.js
@ -1,11 +1,12 @@
|
||||
/* Spreadsheet Format -- jump to XLSX for the XLSX code */
|
||||
/* ssf.js (C) 2013 SheetJS -- http://sheetjs.com */
|
||||
/* ssf.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
|
||||
var SSF = {};
|
||||
var make_ssf = function(SSF){
|
||||
var _strrev = function(x) { return String(x).split("").reverse().join("");};
|
||||
function fill(c,l) { return new Array(l+1).join(c); }
|
||||
function pad(v,d,c){var t=String(v);return t.length>=d?t:(fill(c||0,d-t.length)+t);}
|
||||
function rpad(v,d,c){var t=String(v);return t.length>=d?t:(t+fill(c||0,d-t.length));}
|
||||
SSF.version = '0.5.3';
|
||||
/* Options */
|
||||
var opts_fmt = {};
|
||||
function fixopts(o){for(var y in opts_fmt) if(o[y]===undefined) o[y]=opts_fmt[y];}
|
||||
@ -14,7 +15,7 @@ opts_fmt.date1904 = 0;
|
||||
opts_fmt.output = "";
|
||||
opts_fmt.mode = "";
|
||||
var table_fmt = {
|
||||
0: 'General',
|
||||
0: 'General',
|
||||
1: '0',
|
||||
2: '0.00',
|
||||
3: '#,##0',
|
||||
@ -41,7 +42,9 @@ var table_fmt = {
|
||||
46: '[h]:mm:ss',
|
||||
47: 'mmss.0',
|
||||
48: '##0.0E+0',
|
||||
49: '@'
|
||||
49: '@',
|
||||
56: '"上午/下午 "hh"時"mm"分"ss"秒 "',
|
||||
65535: 'General'
|
||||
};
|
||||
var days = [
|
||||
['Sun', 'Sunday'],
|
||||
@ -71,12 +74,12 @@ var frac = function frac(x, D, mixed) {
|
||||
var B = x * sgn;
|
||||
var P_2 = 0, P_1 = 1, P = 0;
|
||||
var Q_2 = 1, Q_1 = 0, Q = 0;
|
||||
var A = Math.floor(B);
|
||||
var A = Math.floor(B);
|
||||
while(Q_1 < D) {
|
||||
A = Math.floor(B);
|
||||
A = Math.floor(B);
|
||||
P = A * P_1 + P_2;
|
||||
Q = A * Q_1 + Q_2;
|
||||
if((B - A) < 0.0000000005) break;
|
||||
if((B - A) < 0.0000000005) break;
|
||||
B = 1 / (B - A);
|
||||
P_2 = P_1; P_1 = P;
|
||||
Q_2 = Q_1; Q_1 = Q;
|
||||
@ -84,7 +87,7 @@ var frac = function frac(x, D, mixed) {
|
||||
if(Q > D) { Q = Q_1; P = P_1; }
|
||||
if(Q > D) { Q = Q_2; P = P_2; }
|
||||
if(!mixed) return [0, sgn * P, Q];
|
||||
if(Q===0) throw "Unexpected state: "+P+" "+P_1+" "+P_2+" "+Q+" "+Q_1+" "+Q_2;
|
||||
if(Q===0) throw "Unexpected state: "+P+" "+P_1+" "+P_2+" "+Q+" "+Q_1+" "+Q_2;
|
||||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
};
|
||||
@ -114,10 +117,10 @@ var general_fmt = function(v) {
|
||||
};
|
||||
SSF._general = general_fmt;
|
||||
var parse_date_code = function parse_date_code(v,opts) {
|
||||
var date = Math.floor(v), time = Math.floor(86400 * (v - date)+1e-6), dow=0;
|
||||
var date = Math.floor(v), time = Math.floor(86400 * (v - date)+1e-6), dow=0;
|
||||
var dout=[], out={D:date, T:time, u:86400*(v-date)-time}; fixopts(opts = (opts||{}));
|
||||
if(opts.date1904) date += 1462;
|
||||
if(date > 2958465) return null;
|
||||
if(date > 2958465) return null;
|
||||
if(date === 60) {dout = [1900,2,29]; dow=3;}
|
||||
else if(date === 0) {dout = [1900,1,0]; dow=6;}
|
||||
else {
|
||||
@ -127,7 +130,7 @@ var parse_date_code = function parse_date_code(v,opts) {
|
||||
d.setDate(d.getDate() + date - 1);
|
||||
dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
|
||||
dow = d.getDay();
|
||||
if(/* opts.mode === 'excel' && */ date < 60) dow = (dow + 6) % 7;
|
||||
if(/* opts.mode === 'excel' && */ date < 60) dow = (dow + 6) % 7;
|
||||
}
|
||||
out.y = dout[0]; out.m = dout[1]; out.d = dout[2];
|
||||
out.S = time % 60; time = Math.floor(time / 60);
|
||||
@ -140,13 +143,13 @@ SSF.parse_date_code = parse_date_code;
|
||||
/*jshint -W086 */
|
||||
var write_date = function(type, fmt, val) {
|
||||
if(val < 0) return "";
|
||||
var o;
|
||||
var o;
|
||||
switch(type) {
|
||||
case 'y': switch(fmt) { /* year */
|
||||
case 'y': case 'yy': return pad(val.y % 100,2);
|
||||
case 'yyy': case 'yyyy': return pad(val.y % 10000,4);
|
||||
default: throw 'bad year format: ' + fmt;
|
||||
}
|
||||
case 'yyy': case 'yyyy': return pad(val.y % 10000,4);
|
||||
default: throw 'bad year format: ' + fmt;
|
||||
}
|
||||
case 'm': switch(fmt) { /* month */
|
||||
case 'm': return val.m;
|
||||
case 'mm': return pad(val.m,2);
|
||||
@ -154,46 +157,45 @@ var write_date = function(type, fmt, val) {
|
||||
case 'mmmm': return months[val.m-1][2];
|
||||
case 'mmmmm': return months[val.m-1][0];
|
||||
default: throw 'bad month format: ' + fmt;
|
||||
}
|
||||
}
|
||||
case 'd': switch(fmt) { /* day */
|
||||
case 'd': return val.d;
|
||||
case 'dd': return pad(val.d,2);
|
||||
case 'ddd': return days[val.q][0];
|
||||
case 'dddd': return days[val.q][1];
|
||||
default: throw 'bad day format: ' + fmt;
|
||||
}
|
||||
}
|
||||
case 'h': switch(fmt) { /* 12-hour */
|
||||
case 'h': return 1+(val.H+11)%12;
|
||||
case 'hh': return pad(1+(val.H+11)%12, 2);
|
||||
default: throw 'bad hour format: ' + fmt;
|
||||
}
|
||||
}
|
||||
case 'H': switch(fmt) { /* 24-hour */
|
||||
case 'h': return val.H;
|
||||
case 'hh': return pad(val.H, 2);
|
||||
default: throw 'bad hour format: ' + fmt;
|
||||
}
|
||||
}
|
||||
case 'M': switch(fmt) { /* minutes */
|
||||
case 'm': return val.M;
|
||||
case 'mm': return pad(val.M, 2);
|
||||
default: throw 'bad minute format: ' + fmt;
|
||||
}
|
||||
}
|
||||
case 's': switch(fmt) { /* seconds */
|
||||
case 's': return Math.round(val.S+val.u);
|
||||
case 'ss': return pad(Math.round(val.S+val.u), 2);
|
||||
case 'ss.0': o = pad(Math.round(10*(val.S+val.u)),3); return o.substr(0,2)+"." + o.substr(2);
|
||||
case 'ss.00': o = pad(Math.round(100*(val.S+val.u)),4); return o.substr(0,2)+"." + o.substr(2);
|
||||
case 'ss.000': o = pad(Math.round(1000*(val.S+val.u)),5); return o.substr(0,2)+"." + o.substr(2);
|
||||
case 's': return Math.round(val.S+val.u);
|
||||
case 'ss': return pad(Math.round(val.S+val.u), 2);
|
||||
case 'ss.0': o = pad(Math.round(10*(val.S+val.u)),3); return o.substr(0,2)+"." + o.substr(2);
|
||||
case 'ss.00': o = pad(Math.round(100*(val.S+val.u)),4); return o.substr(0,2)+"." + o.substr(2);
|
||||
case 'ss.000': o = pad(Math.round(1000*(val.S+val.u)),5); return o.substr(0,2)+"." + o.substr(2);
|
||||
default: throw 'bad second format: ' + fmt;
|
||||
}
|
||||
}
|
||||
case 'Z': switch(fmt) {
|
||||
case '[h]': case '[hh]': o = val.D*24+val.H; break;
|
||||
case '[m]': case '[mm]': o = (val.D*24+val.H)*60+val.M; break;
|
||||
case '[s]': case '[ss]': o = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
|
||||
case '[h]': case '[hh]': o = val.D*24+val.H; break;
|
||||
case '[m]': case '[mm]': o = (val.D*24+val.H)*60+val.M; break;
|
||||
case '[s]': case '[ss]': o = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
|
||||
default: throw 'bad abstime format: ' + fmt;
|
||||
} return fmt.length === 3 ? o : pad(o, 2);
|
||||
} return fmt.length === 3 ? o : pad(o, 2);
|
||||
/* TODO: handle the ECMA spec format ee -> yy */
|
||||
case 'e': { return val.y; } break;
|
||||
case 'A': return (val.h>=12 ? 'P' : 'A') + fmt.substr(1);
|
||||
default: throw 'bad format type ' + type + ' in ' + fmt;
|
||||
}
|
||||
};
|
||||
@ -210,48 +212,54 @@ var write_num = function(type, fmt, val) {
|
||||
if(mul !== 0) return write_num(type, fmt, val * Math.pow(10,2*mul)) + fill("%",mul);
|
||||
if(fmt.indexOf("E") > -1) {
|
||||
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
|
||||
//if(fmt.match(/^#+0\.0E\+0$/))
|
||||
if(fmt == '##0.0E+0') {
|
||||
var period = fmt.length - 5;
|
||||
var ee = (Number(val.toExponential(0).substr(2+(val<0))))%period;
|
||||
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
|
||||
if(!o.match(/[Ee]/)) {
|
||||
var fakee = (Number(val.toExponential(0).substr(2+(val<0))));
|
||||
if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
|
||||
else throw "missing E |" + o;
|
||||
}
|
||||
o = o.replace(/^([+-]?)([0-9]*)\.([0-9]*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
|
||||
var period = fmt.length - 5;
|
||||
var ee = (Number(val.toExponential(0).substr(2+(val<0))))%period;
|
||||
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
|
||||
if(!o.match(/[Ee]/)) {
|
||||
var fakee = (Number(val.toExponential(0).substr(2+(val<0))));
|
||||
if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
|
||||
else throw "missing E |" + o;
|
||||
}
|
||||
o = o.replace(/^([+-]?)([0-9]*)\.([0-9]*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
|
||||
} else o = val.toExponential(idx);
|
||||
if(fmt.match(/E\+00$/) && o.match(/e[+-][0-9]$/)) o = o.substr(0,o.length-1) + "0" + o[o.length-1];
|
||||
if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
|
||||
return o.replace("e","E");
|
||||
}
|
||||
if(fmt[0] === "$") return "$"+write_num(type,fmt.substr(fmt[1]==' '?2:1),val);
|
||||
if(fmt[0] === "$") return "$"+write_num(type,fmt.substr(fmt[1]==' '?2:1),val);
|
||||
var r, ff, aval = val < 0 ? -val : val, sign = val < 0 ? "-" : "";
|
||||
if((r = fmt.match(/# (\?+) \/ (\d+)/))) {
|
||||
var den = Number(r[2]), rnd = Math.round(aval * den), base = Math.floor(rnd/den);
|
||||
if((r = fmt.match(/# (\?+)([ ]?)\/([ ]?)(\d+)/))) {
|
||||
var den = Number(r[4]), rnd = Math.round(aval * den), base = Math.floor(rnd/den);
|
||||
var myn = (rnd - base*den), myd = den;
|
||||
return sign + (base?base:"") + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[2].length) : pad(myn,r[1].length," ") + "/" + pad(myd,r[2].length));
|
||||
return sign + (base?base:"") + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad(myn,r[1].length," ") + r[2] + "/" + r[3] + pad(myd,r[4].length));
|
||||
}
|
||||
if(fmt.match(/^00+$/)) return (val<0?"-":"")+pad(Math.round(aval),fmt.length);
|
||||
if(fmt.match(/^[#?]+$/)) return String(Math.round(val)).replace(/^0$/,"");
|
||||
if(r = fmt.match(/^#*0+\.(0+)/)) {
|
||||
o = Math.round(val * Math.pow(10,r[1].length));
|
||||
return String(o/Math.pow(10,r[1].length)).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.([0-9]*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
|
||||
}
|
||||
if(r = fmt.match(/^# ([?]+)([ ]?)\/([ ]?)([?]+)/)) {
|
||||
var rr = Math.min(Math.max(r[1].length, r[4].length),7);
|
||||
ff = frac(aval, Math.pow(10,rr)-1, true);
|
||||
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],rr," ") + r[2] + "/" + r[3] + rpad(ff[2],rr," "): fill(" ", 2*rr+1 + r[2].length + r[3].length));
|
||||
}
|
||||
if(fmt.match(/^00*$/)) return (val<0?"-":"")+pad(Math.round(aval),fmt.length);
|
||||
if(fmt.match(/^####*$/)) return Math.round(val);
|
||||
switch(fmt) {
|
||||
case "0": return Math.round(val);
|
||||
case "0.0": o = Math.round(val*10);
|
||||
return String(o/10).replace(/^([^\.]+)$/,"$1.0").replace(/\.$/,".0");
|
||||
case "0.00": o = Math.round(val*100);
|
||||
return String(o/100).replace(/^([^\.]+)$/,"$1.00").replace(/\.$/,".00").replace(/\.([0-9])$/,".$1"+"0");
|
||||
case "0.000": o = Math.round(val*1000);
|
||||
return String(o/1000).replace(/^([^\.]+)$/,"$1.000").replace(/\.$/,".000").replace(/\.([0-9])$/,".$1"+"00").replace(/\.([0-9][0-9])$/,".$1"+"0");
|
||||
case "#.##": o = Math.round(val*100);
|
||||
return String(o/100).replace(/^([^\.]+)$/,"$1.").replace(/^0\.$/,".");
|
||||
case "#,###": var x = commaify(String(Math.round(aval))); return x !== "0" ? sign + x : "";
|
||||
case "0": case "#0": return Math.round(val);
|
||||
case "#.##": o = Math.round(val*100);
|
||||
return String(o/100).replace(/^([^\.]+)$/,"$1.").replace(/^0\.$/,".");
|
||||
case "#,###": var x = commaify(String(Math.round(aval))); return x !== "0" ? sign + x : "";
|
||||
case "#,##0": return sign + commaify(String(Math.round(aval)));
|
||||
case "#,##0.0": r = Math.round((val-Math.floor(val))*10); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + r;
|
||||
case "#,##0.00": r = Math.round((val-Math.floor(val))*100); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + (r < 10 ? "0"+r:r);
|
||||
case "# ? / ?": ff = frac(aval, 9, true); return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] === 0 ? " " : ff[1] + "/" + ff[2]);
|
||||
case "# ?? / ??": ff = frac(aval, 99, true); return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],2," ") + "/" + rpad(ff[2],2," ") : " ");
|
||||
case "# ??? / ???": ff = frac(aval, 999, true); return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],3," ") + "/" + rpad(ff[2],3," ") : " ");
|
||||
case "#,##0.0": r = Math.round((val-Math.floor(val))*10); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,1,"0");
|
||||
case "#,##0.00": r = Math.round((val-Math.floor(val))*100); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,2,"0");
|
||||
case "#,##0.000": r = Math.round((val-Math.floor(val))*1000); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,3,0);
|
||||
case "#,##0.0000": r = Math.round((val-Math.floor(val))*10000); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,4,0);
|
||||
case "#,##0.00000": r = Math.round((val-Math.floor(val))*Math.pow(10,5)); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,5,0);
|
||||
case "#,##0.000000": r = Math.round((val-Math.floor(val))*Math.pow(10,6)); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,6,0);
|
||||
case "#,##0.0000000": r = Math.round((val-Math.floor(val))*Math.pow(10,7)); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,7,0);
|
||||
case "#,##0.00000000": r = Math.round((val-Math.floor(val))*Math.pow(10,8)); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,8,0);
|
||||
case "#,##0.000000000": r = Math.round((val-Math.floor(val))*Math.pow(10,9)); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,9,0);
|
||||
default:
|
||||
}
|
||||
throw new Error("unsupported format |" + fmt + "|");
|
||||
@ -279,10 +287,10 @@ function eval_fmt(fmt, v, opts, flen) {
|
||||
/* Tokenize */
|
||||
while(i < fmt.length) {
|
||||
switch((c = fmt[i])) {
|
||||
case 'G': /* General */
|
||||
if(fmt.substr(i, i+6).toLowerCase() !== "general")
|
||||
throw 'unrecognized character ' + fmt[i] + ' in ' + fmt;
|
||||
out.push({t:'G',v:'General'}); i+=7; break;
|
||||
case 'G': /* General */
|
||||
if(fmt.substr(i, i+6).toLowerCase() !== "general")
|
||||
throw 'unrecognized character ' + fmt[i] + ' in ' + fmt;
|
||||
out.push({t:'G',v:'General'}); i+=7; break;
|
||||
case '"': /* Literal text */
|
||||
for(o="";fmt[++i] !== '"' && i < fmt.length;) o += fmt[i];
|
||||
out.push({t:'t', v:o}); ++i; break;
|
||||
@ -292,35 +300,35 @@ function eval_fmt(fmt, v, opts, flen) {
|
||||
case '@': /* Text Placeholder */
|
||||
out.push({t:'T', v:v}); ++i; break;
|
||||
/* Dates */
|
||||
case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
|
||||
c = c.toLowerCase();
|
||||
/* falls through */
|
||||
case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
|
||||
c = c.toLowerCase();
|
||||
/* falls through */
|
||||
case 'm': case 'd': case 'y': case 'h': case 's': case 'e':
|
||||
if(v < 0) return "";
|
||||
if(!dt) dt = parse_date_code(v, opts);
|
||||
if(!dt) return "";
|
||||
o = fmt[i]; while((fmt[++i]||"").toLowerCase() === c) o+=c;
|
||||
if(!dt) return "";
|
||||
o = fmt[i]; while((fmt[++i]||"").toLowerCase() === c) o+=c;
|
||||
if(c === 's' && fmt[i] === '.' && fmt[i+1] === '0') { o+='.'; while(fmt[++i] === '0') o+= '0'; }
|
||||
if(c === 'm' && lst.toLowerCase() === 'h') c = 'M'; /* m = minute */
|
||||
if(c === 'h') c = hr;
|
||||
o = o.toLowerCase();
|
||||
o = o.toLowerCase();
|
||||
q={t:c, v:o}; out.push(q); lst = c; break;
|
||||
case 'A':
|
||||
if(!dt) dt = parse_date_code(v, opts);
|
||||
if(!dt) return "";
|
||||
if(!dt) return "";
|
||||
q={t:c,v:"A"};
|
||||
if(fmt.substr(i, 3) === "A/P") {q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;}
|
||||
else if(fmt.substr(i,5) === "AM/PM") { q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; }
|
||||
else { q.t = "t"; i++; }
|
||||
else { q.t = "t"; i++; }
|
||||
out.push(q); lst = c; break;
|
||||
case '[': /* TODO: Fix this -- ignore all conditionals and formatting */
|
||||
o = c;
|
||||
while(fmt[i++] !== ']') o += fmt[i];
|
||||
if(o.match(/\[[HhMmSs]*\]/)) {
|
||||
if(!dt) dt = parse_date_code(v, opts);
|
||||
if(!dt) return "";
|
||||
out.push({t:'Z', v:o.toLowerCase()});
|
||||
} else { o=""; }
|
||||
if(o.match(/\[[HhMmSs]*\]/)) {
|
||||
if(!dt) dt = parse_date_code(v, opts);
|
||||
if(!dt) return "";
|
||||
out.push({t:'Z', v:o.toLowerCase()});
|
||||
} else { o=""; }
|
||||
break;
|
||||
/* Numbers */
|
||||
case '0': case '#':
|
||||
@ -336,7 +344,7 @@ function eval_fmt(fmt, v, opts, flen) {
|
||||
out.push({t:'D', v:o}); break;
|
||||
case ' ': out.push({t:c,v:c}); ++i; break;
|
||||
default:
|
||||
if("$-+/():!^&'~{}<>=".indexOf(c) === -1)
|
||||
if(",$-+/():!^&'~{}<>=".indexOf(c) === -1)
|
||||
throw 'unrecognized character ' + fmt[i] + ' in ' + fmt;
|
||||
out.push({t:'t', v:c}); ++i; break;
|
||||
}
|
||||
@ -358,30 +366,30 @@ function eval_fmt(fmt, v, opts, flen) {
|
||||
case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'A': case 'e': case 'Z':
|
||||
out[i].v = write_date(out[i].t, out[i].v, dt);
|
||||
out[i].t = 't'; break;
|
||||
case 'n': case '(':
|
||||
case 'n': case '(': case '?':
|
||||
var jj = i+1;
|
||||
while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (out[jj].t == " " && (out[jj+1]||{}).t === "?" ) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || out[jj].v == '$' || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) {
|
||||
if(out[jj].v!==' ') out[i].v += ' ' + out[jj].v;
|
||||
while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (" t".indexOf(out[jj].t) > -1 && "?t".indexOf((out[jj+1]||{}).t)>-1 && (out[jj+1].t == '?' || out[jj+1].v == '/')) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || out[jj].v == '$' || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) {
|
||||
out[i].v += out[jj].v;
|
||||
delete out[jj]; ++jj;
|
||||
}
|
||||
out[i].v = write_num(out[i].t, out[i].v, v);
|
||||
out[i].t = 't';
|
||||
i = jj-1; break;
|
||||
case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
|
||||
default: throw "unrecognized type " + out[i].t;
|
||||
i = jj-1; break;
|
||||
case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
|
||||
default: console.error(out); throw "unrecognized type " + out[i].t;
|
||||
}
|
||||
}
|
||||
return out.map(function(x){return x.v;}).join("");
|
||||
}
|
||||
SSF._eval = eval_fmt;
|
||||
function choose_fmt(fmt, v, o) {
|
||||
if(typeof fmt === 'number') fmt = ((o&&o.table) ? o.table : table_fmt)[fmt];
|
||||
if(typeof fmt === 'number') fmt = ((o&&o.table) ? o.table : table_fmt)[fmt];
|
||||
if(typeof fmt === "string") fmt = split_fmt(fmt);
|
||||
var l = fmt.length;
|
||||
switch(fmt.length) {
|
||||
case 1: fmt = fmt[0].indexOf("@")>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
|
||||
case 2: fmt = fmt[1].indexOf("@")>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
|
||||
case 3: fmt = fmt[2].indexOf("@")>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
|
||||
case 1: fmt = fmt[0].indexOf("@")>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
|
||||
case 2: fmt = fmt[1].indexOf("@")>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
|
||||
case 3: fmt = fmt[2].indexOf("@")>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
|
||||
case 4: break;
|
||||
default: throw "cannot find right format for |" + fmt + "|";
|
||||
}
|
||||
@ -390,11 +398,11 @@ function choose_fmt(fmt, v, o) {
|
||||
}
|
||||
var format = function format(fmt,v,o) {
|
||||
fixopts(o = (o||{}));
|
||||
if(typeof fmt === "string" && fmt.toLowerCase() === "general") return general_fmt(v, o);
|
||||
if(typeof fmt === 'number') fmt = (o.table || table_fmt)[fmt];
|
||||
if(typeof fmt === "string" && fmt.toLowerCase() === "general") return general_fmt(v, o);
|
||||
if(typeof fmt === 'number') fmt = (o.table || table_fmt)[fmt];
|
||||
var f = choose_fmt(fmt, v, o);
|
||||
if(f[1].toLowerCase() === "general") return general_fmt(v,o);
|
||||
if(v === true) v = "TRUE"; if(v === false) v = "FALSE";
|
||||
if(f[1].toLowerCase() === "general") return general_fmt(v,o);
|
||||
if(v === true) v = "TRUE"; if(v === false) v = "FALSE";
|
||||
return eval_fmt(f[1], v, o, f[0]);
|
||||
};
|
||||
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.3.7';
|
||||
XLSX.version = '0.3.8';
|
||||
|
106
bits/90_utils.js
106
bits/90_utils.js
@ -10,60 +10,50 @@ function split_cell(cstr) { return cstr.replace(/(\$?[A-Z]*)(\$?[0-9]*)/,"$1,$2"
|
||||
function decode_cell(cstr) { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; }
|
||||
function decode_range(range) { var x =range.split(":").map(decode_cell); return {s:x[0],e:x[x.length-1]}; }
|
||||
function encode_range(range) { return encode_cell(range.s) + ":" + encode_cell(range.e); }
|
||||
/**
|
||||
* Convert a sheet into an array of objects where the column headers are keys.
|
||||
**/
|
||||
function sheet_to_row_object_array(sheet){
|
||||
var val, rowObject, range, columnHeaders, emptyRow, C;
|
||||
var outSheet = [];
|
||||
if (sheet["!ref"]) {
|
||||
range = decode_range(sheet["!ref"]);
|
||||
|
||||
columnHeaders = {};
|
||||
for (C = range.s.c; C <= range.e.c; ++C) {
|
||||
val = sheet[encode_cell({
|
||||
c: C,
|
||||
r: range.s.r
|
||||
})];
|
||||
if(val){
|
||||
switch(val.t) {
|
||||
case 's': case 'str': columnHeaders[C] = val.v; break;
|
||||
case 'n': columnHeaders[C] = val.v; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var R = range.s.r + 1; R <= range.e.r; ++R) {
|
||||
emptyRow = true;
|
||||
//Row number is recorded in the prototype
|
||||
//so that it doesn't appear when stringified.
|
||||
rowObject = Object.create({ __rowNum__ : R });
|
||||
for (C = range.s.c; C <= range.e.c; ++C) {
|
||||
val = sheet[encode_cell({
|
||||
c: C,
|
||||
r: R
|
||||
})];
|
||||
if(val !== undefined) switch(val.t){
|
||||
case 's': case 'str': case 'b': case 'n':
|
||||
if(val.v !== undefined) {
|
||||
rowObject[columnHeaders[C]] = val.v;
|
||||
emptyRow = false;
|
||||
}
|
||||
break;
|
||||
case 'e': break; /* throw */
|
||||
default: throw 'unrecognized type ' + val.t;
|
||||
}
|
||||
}
|
||||
if(!emptyRow) {
|
||||
outSheet.push(rowObject);
|
||||
function sheet_to_row_object_array(sheet, opts){
|
||||
var val, row, r, hdr = {}, isempty, R, C, v;
|
||||
var out = [];
|
||||
opts = opts || {};
|
||||
if(!sheet["!ref"]) return out;
|
||||
r = XLSX.utils.decode_range(sheet["!ref"]);
|
||||
for(R=r.s.r, C = r.s.c; C <= r.e.c; ++C) {
|
||||
val = sheet[encode_cell({c:C,r:R})];
|
||||
if(val){
|
||||
switch(val.t) {
|
||||
case 's': case 'str': hdr[C] = val.v; break;
|
||||
case 'n': hdr[C] = val.v; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return outSheet;
|
||||
|
||||
for (R = r.s.r + 1; R <= r.e.r; ++R) {
|
||||
isempty = true;
|
||||
/* row index available as __rowNum__ */
|
||||
row = Object.create({ __rowNum__ : R });
|
||||
for (C = r.s.c; C <= r.e.c; ++C) {
|
||||
val = sheet[encode_cell({c: C,r: R})];
|
||||
if(!val) continue;
|
||||
v = (val || {}).v;
|
||||
switch(val.t){
|
||||
case 's': case 'str': case 'b': case 'n':
|
||||
if(val.v !== undefined) {
|
||||
row[hdr[C]] = val.v;
|
||||
isempty = false;
|
||||
}
|
||||
break;
|
||||
case 'e': break; /* throw */
|
||||
default: throw 'unrecognized type ' + val.t;
|
||||
}
|
||||
}
|
||||
if(!isempty) out.push(row);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function sheet_to_csv(sheet) {
|
||||
function sheet_to_csv(sheet, opts) {
|
||||
var stringify = function stringify(val) {
|
||||
if(!val.t) return "";
|
||||
switch(val.t){
|
||||
case 'n': return String(val.v);
|
||||
case 's': case 'str':
|
||||
@ -74,17 +64,19 @@ function sheet_to_csv(sheet) {
|
||||
default: throw 'unrecognized type ' + val.t;
|
||||
}
|
||||
};
|
||||
var out = "";
|
||||
if(sheet["!ref"]) {
|
||||
var r = XLSX.utils.decode_range(sheet["!ref"]);
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
var row = [];
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var val = sheet[XLSX.utils.encode_cell({c:C,r:R})];
|
||||
row.push(val ? stringify(val).replace(/\\r\\n/g,"\n").replace(/\\t/g,"\t").replace(/\\\\/g,"\\").replace("\\\"","\"\"") : "");
|
||||
}
|
||||
out += row.join(",") + "\n";
|
||||
var out = "", txt = "";
|
||||
opts = opts || {};
|
||||
if(!sheet["!ref"]) return out;
|
||||
var r = XLSX.utils.decode_range(sheet["!ref"]);
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
var row = [];
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var val = sheet[XLSX.utils.encode_cell({c:C,r:R})];
|
||||
if(!val) { row.push(""); continue; }
|
||||
txt = stringify(val);
|
||||
row.push(String(txt).replace(/\\r\\n/g,"\n").replace(/\\t/g,"\t").replace(/\\\\/g,"\\").replace("\\\"","\"\""));
|
||||
}
|
||||
out += row.join(opts.FS||",") + (opts.RS||"\n");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
19
index.html
19
index.html
@ -32,17 +32,18 @@
|
||||
<script src="jszip.js"></script>
|
||||
<script src="xlsx.js"></script>
|
||||
<script>
|
||||
var rABS = typeof FileReader !== "undefined" && typeof FileReader.prototype !== "undefined" && typeof FileReader.prototype.readAsBinaryString !== "undefined";
|
||||
function xlsxworker(data, cb) {
|
||||
var worker = new Worker('./xlsxworker.js');
|
||||
worker.onmessage = function(e) {
|
||||
switch(e.data.t) {
|
||||
case 'ready': break;
|
||||
case 'e': console.error(e.data.d);
|
||||
case 'e': console.error(e.data.d); break;
|
||||
case 'xlsx': cb(JSON.parse(e.data.d)); break;
|
||||
}
|
||||
};
|
||||
var arr = btoa(String.fromCharCode.apply(null, new Uint8Array(data)));
|
||||
worker.postMessage(arr);
|
||||
var arr = rABS ? data : btoa(String.fromCharCode.apply(null, new Uint8Array(data)));
|
||||
worker.postMessage({d:arr,b:rABS});
|
||||
}
|
||||
|
||||
function get_radio_value( radioName ) {
|
||||
@ -127,14 +128,18 @@ function handleDrop(e) {
|
||||
if(typeof Worker !== 'undefined') {
|
||||
xlsxworker(data, process_wb);
|
||||
} else {
|
||||
//var wb = XLSX.read(data, {type: 'binary'});
|
||||
var wb;
|
||||
if(rABS) {
|
||||
wb = XLSX.read(data, {type: 'binary'});
|
||||
} else {
|
||||
var arr = String.fromCharCode.apply(null, new Uint8Array(data));
|
||||
var wb = XLSX.read(btoa(arr), {type: 'base64'});
|
||||
wb = XLSX.read(btoa(arr), {type: 'base64'});
|
||||
}
|
||||
process_wb(wb);
|
||||
}
|
||||
};
|
||||
//reader.readAsBinaryString(f);
|
||||
reader.readAsArrayBuffer(f);
|
||||
if(rABS) reader.readAsBinaryString(f);
|
||||
else reader.readAsArrayBuffer(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xlsx",
|
||||
"version": "0.3.7",
|
||||
"version": "0.3.8",
|
||||
"author": "sheetjs",
|
||||
"description": "(one day) a full-featured XLSX parser and writer. For now, primitive parser",
|
||||
"keywords": [ "xlsx", "office", "excel", "spreadsheet" ],
|
||||
|
14
test.js
14
test.js
@ -1,10 +1,13 @@
|
||||
/* vim: set ts=2: */
|
||||
var XLSX;
|
||||
var fs = require('fs'), assert = require('assert');
|
||||
describe('source', function() { it('should load', function() { XLSX = require('./'); }); });
|
||||
describe('source',function(){ it('should load', function(){ XLSX = require('./'); });});
|
||||
|
||||
var files = (fs.existsSync('tests.lst') ? fs.readFileSync('tests.lst', 'utf-8').split("\n") : fs.readdirSync('test_files')).filter(function(x){return x.substr(-5)==".xlsx" || x.substr(-13)==".xlsx.pending"});
|
||||
|
||||
/* Excel enforces 31 character sheet limit, although technical file limit is 255 */
|
||||
function fixsheetname(x) { return x.substr(0,31); }
|
||||
|
||||
function normalizecsv(x) { return x.replace(/\t/g,",").replace(/#{255}/g,"").replace(/"/g,"").replace(/[\n\r]+/g,"\n").replace(/\n*$/,""); }
|
||||
|
||||
function parsetest(x, wb) {
|
||||
@ -15,10 +18,17 @@ function parsetest(x, wb) {
|
||||
});
|
||||
it('should have the right sheet names', fs.existsSync(sname) ? function() {
|
||||
var file = fs.readFileSync(sname, 'utf-8');
|
||||
var names = wb.SheetNames.join("\n") + "\n";
|
||||
var names = wb.SheetNames.map(fixsheetname).join("\n") + "\n";
|
||||
assert.equal(names, file);
|
||||
} : null);
|
||||
});
|
||||
describe(x + ' should generate CSV', function() {
|
||||
wb.SheetNames.forEach(function(ws, i) {
|
||||
it('#' + i + ' (' + ws + ')', function() {
|
||||
var csv = XLSX.utils.make_csv(wb.Sheets[ws]);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe(x + ' should generate correct output', function() {
|
||||
wb.SheetNames.forEach(function(ws, i) {
|
||||
var name = ('./test_files/' + x + '.' + i + '.csv');
|
||||
|
302
xlsx.js
302
xlsx.js
@ -2,13 +2,14 @@
|
||||
/* vim: set ts=2: */
|
||||
/*jshint eqnull:true */
|
||||
/* Spreadsheet Format -- jump to XLSX for the XLSX code */
|
||||
/* ssf.js (C) 2013 SheetJS -- http://sheetjs.com */
|
||||
/* ssf.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
|
||||
var SSF = {};
|
||||
var make_ssf = function(SSF){
|
||||
var _strrev = function(x) { return String(x).split("").reverse().join("");};
|
||||
function fill(c,l) { return new Array(l+1).join(c); }
|
||||
function pad(v,d,c){var t=String(v);return t.length>=d?t:(fill(c||0,d-t.length)+t);}
|
||||
function rpad(v,d,c){var t=String(v);return t.length>=d?t:(t+fill(c||0,d-t.length));}
|
||||
SSF.version = '0.5.3';
|
||||
/* Options */
|
||||
var opts_fmt = {};
|
||||
function fixopts(o){for(var y in opts_fmt) if(o[y]===undefined) o[y]=opts_fmt[y];}
|
||||
@ -17,7 +18,7 @@ opts_fmt.date1904 = 0;
|
||||
opts_fmt.output = "";
|
||||
opts_fmt.mode = "";
|
||||
var table_fmt = {
|
||||
0: 'General',
|
||||
0: 'General',
|
||||
1: '0',
|
||||
2: '0.00',
|
||||
3: '#,##0',
|
||||
@ -44,7 +45,9 @@ var table_fmt = {
|
||||
46: '[h]:mm:ss',
|
||||
47: 'mmss.0',
|
||||
48: '##0.0E+0',
|
||||
49: '@'
|
||||
49: '@',
|
||||
56: '"上午/下午 "hh"時"mm"分"ss"秒 "',
|
||||
65535: 'General'
|
||||
};
|
||||
var days = [
|
||||
['Sun', 'Sunday'],
|
||||
@ -74,12 +77,12 @@ var frac = function frac(x, D, mixed) {
|
||||
var B = x * sgn;
|
||||
var P_2 = 0, P_1 = 1, P = 0;
|
||||
var Q_2 = 1, Q_1 = 0, Q = 0;
|
||||
var A = Math.floor(B);
|
||||
var A = Math.floor(B);
|
||||
while(Q_1 < D) {
|
||||
A = Math.floor(B);
|
||||
A = Math.floor(B);
|
||||
P = A * P_1 + P_2;
|
||||
Q = A * Q_1 + Q_2;
|
||||
if((B - A) < 0.0000000005) break;
|
||||
if((B - A) < 0.0000000005) break;
|
||||
B = 1 / (B - A);
|
||||
P_2 = P_1; P_1 = P;
|
||||
Q_2 = Q_1; Q_1 = Q;
|
||||
@ -87,7 +90,7 @@ var frac = function frac(x, D, mixed) {
|
||||
if(Q > D) { Q = Q_1; P = P_1; }
|
||||
if(Q > D) { Q = Q_2; P = P_2; }
|
||||
if(!mixed) return [0, sgn * P, Q];
|
||||
if(Q===0) throw "Unexpected state: "+P+" "+P_1+" "+P_2+" "+Q+" "+Q_1+" "+Q_2;
|
||||
if(Q===0) throw "Unexpected state: "+P+" "+P_1+" "+P_2+" "+Q+" "+Q_1+" "+Q_2;
|
||||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
};
|
||||
@ -117,10 +120,10 @@ var general_fmt = function(v) {
|
||||
};
|
||||
SSF._general = general_fmt;
|
||||
var parse_date_code = function parse_date_code(v,opts) {
|
||||
var date = Math.floor(v), time = Math.floor(86400 * (v - date)+1e-6), dow=0;
|
||||
var date = Math.floor(v), time = Math.floor(86400 * (v - date)+1e-6), dow=0;
|
||||
var dout=[], out={D:date, T:time, u:86400*(v-date)-time}; fixopts(opts = (opts||{}));
|
||||
if(opts.date1904) date += 1462;
|
||||
if(date > 2958465) return null;
|
||||
if(date > 2958465) return null;
|
||||
if(date === 60) {dout = [1900,2,29]; dow=3;}
|
||||
else if(date === 0) {dout = [1900,1,0]; dow=6;}
|
||||
else {
|
||||
@ -130,7 +133,7 @@ var parse_date_code = function parse_date_code(v,opts) {
|
||||
d.setDate(d.getDate() + date - 1);
|
||||
dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
|
||||
dow = d.getDay();
|
||||
if(/* opts.mode === 'excel' && */ date < 60) dow = (dow + 6) % 7;
|
||||
if(/* opts.mode === 'excel' && */ date < 60) dow = (dow + 6) % 7;
|
||||
}
|
||||
out.y = dout[0]; out.m = dout[1]; out.d = dout[2];
|
||||
out.S = time % 60; time = Math.floor(time / 60);
|
||||
@ -143,13 +146,13 @@ SSF.parse_date_code = parse_date_code;
|
||||
/*jshint -W086 */
|
||||
var write_date = function(type, fmt, val) {
|
||||
if(val < 0) return "";
|
||||
var o;
|
||||
var o;
|
||||
switch(type) {
|
||||
case 'y': switch(fmt) { /* year */
|
||||
case 'y': case 'yy': return pad(val.y % 100,2);
|
||||
case 'yyy': case 'yyyy': return pad(val.y % 10000,4);
|
||||
default: throw 'bad year format: ' + fmt;
|
||||
}
|
||||
case 'yyy': case 'yyyy': return pad(val.y % 10000,4);
|
||||
default: throw 'bad year format: ' + fmt;
|
||||
}
|
||||
case 'm': switch(fmt) { /* month */
|
||||
case 'm': return val.m;
|
||||
case 'mm': return pad(val.m,2);
|
||||
@ -157,46 +160,45 @@ var write_date = function(type, fmt, val) {
|
||||
case 'mmmm': return months[val.m-1][2];
|
||||
case 'mmmmm': return months[val.m-1][0];
|
||||
default: throw 'bad month format: ' + fmt;
|
||||
}
|
||||
}
|
||||
case 'd': switch(fmt) { /* day */
|
||||
case 'd': return val.d;
|
||||
case 'dd': return pad(val.d,2);
|
||||
case 'ddd': return days[val.q][0];
|
||||
case 'dddd': return days[val.q][1];
|
||||
default: throw 'bad day format: ' + fmt;
|
||||
}
|
||||
}
|
||||
case 'h': switch(fmt) { /* 12-hour */
|
||||
case 'h': return 1+(val.H+11)%12;
|
||||
case 'hh': return pad(1+(val.H+11)%12, 2);
|
||||
default: throw 'bad hour format: ' + fmt;
|
||||
}
|
||||
}
|
||||
case 'H': switch(fmt) { /* 24-hour */
|
||||
case 'h': return val.H;
|
||||
case 'hh': return pad(val.H, 2);
|
||||
default: throw 'bad hour format: ' + fmt;
|
||||
}
|
||||
}
|
||||
case 'M': switch(fmt) { /* minutes */
|
||||
case 'm': return val.M;
|
||||
case 'mm': return pad(val.M, 2);
|
||||
default: throw 'bad minute format: ' + fmt;
|
||||
}
|
||||
}
|
||||
case 's': switch(fmt) { /* seconds */
|
||||
case 's': return Math.round(val.S+val.u);
|
||||
case 'ss': return pad(Math.round(val.S+val.u), 2);
|
||||
case 'ss.0': o = pad(Math.round(10*(val.S+val.u)),3); return o.substr(0,2)+"." + o.substr(2);
|
||||
case 'ss.00': o = pad(Math.round(100*(val.S+val.u)),4); return o.substr(0,2)+"." + o.substr(2);
|
||||
case 'ss.000': o = pad(Math.round(1000*(val.S+val.u)),5); return o.substr(0,2)+"." + o.substr(2);
|
||||
case 's': return Math.round(val.S+val.u);
|
||||
case 'ss': return pad(Math.round(val.S+val.u), 2);
|
||||
case 'ss.0': o = pad(Math.round(10*(val.S+val.u)),3); return o.substr(0,2)+"." + o.substr(2);
|
||||
case 'ss.00': o = pad(Math.round(100*(val.S+val.u)),4); return o.substr(0,2)+"." + o.substr(2);
|
||||
case 'ss.000': o = pad(Math.round(1000*(val.S+val.u)),5); return o.substr(0,2)+"." + o.substr(2);
|
||||
default: throw 'bad second format: ' + fmt;
|
||||
}
|
||||
}
|
||||
case 'Z': switch(fmt) {
|
||||
case '[h]': case '[hh]': o = val.D*24+val.H; break;
|
||||
case '[m]': case '[mm]': o = (val.D*24+val.H)*60+val.M; break;
|
||||
case '[s]': case '[ss]': o = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
|
||||
case '[h]': case '[hh]': o = val.D*24+val.H; break;
|
||||
case '[m]': case '[mm]': o = (val.D*24+val.H)*60+val.M; break;
|
||||
case '[s]': case '[ss]': o = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
|
||||
default: throw 'bad abstime format: ' + fmt;
|
||||
} return fmt.length === 3 ? o : pad(o, 2);
|
||||
} return fmt.length === 3 ? o : pad(o, 2);
|
||||
/* TODO: handle the ECMA spec format ee -> yy */
|
||||
case 'e': { return val.y; } break;
|
||||
case 'A': return (val.h>=12 ? 'P' : 'A') + fmt.substr(1);
|
||||
default: throw 'bad format type ' + type + ' in ' + fmt;
|
||||
}
|
||||
};
|
||||
@ -213,48 +215,54 @@ var write_num = function(type, fmt, val) {
|
||||
if(mul !== 0) return write_num(type, fmt, val * Math.pow(10,2*mul)) + fill("%",mul);
|
||||
if(fmt.indexOf("E") > -1) {
|
||||
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
|
||||
//if(fmt.match(/^#+0\.0E\+0$/))
|
||||
if(fmt == '##0.0E+0') {
|
||||
var period = fmt.length - 5;
|
||||
var ee = (Number(val.toExponential(0).substr(2+(val<0))))%period;
|
||||
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
|
||||
if(!o.match(/[Ee]/)) {
|
||||
var fakee = (Number(val.toExponential(0).substr(2+(val<0))));
|
||||
if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
|
||||
else throw "missing E |" + o;
|
||||
}
|
||||
o = o.replace(/^([+-]?)([0-9]*)\.([0-9]*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
|
||||
var period = fmt.length - 5;
|
||||
var ee = (Number(val.toExponential(0).substr(2+(val<0))))%period;
|
||||
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
|
||||
if(!o.match(/[Ee]/)) {
|
||||
var fakee = (Number(val.toExponential(0).substr(2+(val<0))));
|
||||
if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
|
||||
else throw "missing E |" + o;
|
||||
}
|
||||
o = o.replace(/^([+-]?)([0-9]*)\.([0-9]*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
|
||||
} else o = val.toExponential(idx);
|
||||
if(fmt.match(/E\+00$/) && o.match(/e[+-][0-9]$/)) o = o.substr(0,o.length-1) + "0" + o[o.length-1];
|
||||
if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
|
||||
return o.replace("e","E");
|
||||
}
|
||||
if(fmt[0] === "$") return "$"+write_num(type,fmt.substr(fmt[1]==' '?2:1),val);
|
||||
if(fmt[0] === "$") return "$"+write_num(type,fmt.substr(fmt[1]==' '?2:1),val);
|
||||
var r, ff, aval = val < 0 ? -val : val, sign = val < 0 ? "-" : "";
|
||||
if((r = fmt.match(/# (\?+) \/ (\d+)/))) {
|
||||
var den = Number(r[2]), rnd = Math.round(aval * den), base = Math.floor(rnd/den);
|
||||
if((r = fmt.match(/# (\?+)([ ]?)\/([ ]?)(\d+)/))) {
|
||||
var den = Number(r[4]), rnd = Math.round(aval * den), base = Math.floor(rnd/den);
|
||||
var myn = (rnd - base*den), myd = den;
|
||||
return sign + (base?base:"") + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[2].length) : pad(myn,r[1].length," ") + "/" + pad(myd,r[2].length));
|
||||
return sign + (base?base:"") + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad(myn,r[1].length," ") + r[2] + "/" + r[3] + pad(myd,r[4].length));
|
||||
}
|
||||
if(fmt.match(/^00+$/)) return (val<0?"-":"")+pad(Math.round(aval),fmt.length);
|
||||
if(fmt.match(/^[#?]+$/)) return String(Math.round(val)).replace(/^0$/,"");
|
||||
if(r = fmt.match(/^#*0+\.(0+)/)) {
|
||||
o = Math.round(val * Math.pow(10,r[1].length));
|
||||
return String(o/Math.pow(10,r[1].length)).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.([0-9]*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
|
||||
}
|
||||
if(r = fmt.match(/^# ([?]+)([ ]?)\/([ ]?)([?]+)/)) {
|
||||
var rr = Math.min(Math.max(r[1].length, r[4].length),7);
|
||||
ff = frac(aval, Math.pow(10,rr)-1, true);
|
||||
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],rr," ") + r[2] + "/" + r[3] + rpad(ff[2],rr," "): fill(" ", 2*rr+1 + r[2].length + r[3].length));
|
||||
}
|
||||
if(fmt.match(/^00*$/)) return (val<0?"-":"")+pad(Math.round(aval),fmt.length);
|
||||
if(fmt.match(/^####*$/)) return Math.round(val);
|
||||
switch(fmt) {
|
||||
case "0": return Math.round(val);
|
||||
case "0.0": o = Math.round(val*10);
|
||||
return String(o/10).replace(/^([^\.]+)$/,"$1.0").replace(/\.$/,".0");
|
||||
case "0.00": o = Math.round(val*100);
|
||||
return String(o/100).replace(/^([^\.]+)$/,"$1.00").replace(/\.$/,".00").replace(/\.([0-9])$/,".$1"+"0");
|
||||
case "0.000": o = Math.round(val*1000);
|
||||
return String(o/1000).replace(/^([^\.]+)$/,"$1.000").replace(/\.$/,".000").replace(/\.([0-9])$/,".$1"+"00").replace(/\.([0-9][0-9])$/,".$1"+"0");
|
||||
case "#.##": o = Math.round(val*100);
|
||||
return String(o/100).replace(/^([^\.]+)$/,"$1.").replace(/^0\.$/,".");
|
||||
case "#,###": var x = commaify(String(Math.round(aval))); return x !== "0" ? sign + x : "";
|
||||
case "0": case "#0": return Math.round(val);
|
||||
case "#.##": o = Math.round(val*100);
|
||||
return String(o/100).replace(/^([^\.]+)$/,"$1.").replace(/^0\.$/,".");
|
||||
case "#,###": var x = commaify(String(Math.round(aval))); return x !== "0" ? sign + x : "";
|
||||
case "#,##0": return sign + commaify(String(Math.round(aval)));
|
||||
case "#,##0.0": r = Math.round((val-Math.floor(val))*10); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + r;
|
||||
case "#,##0.00": r = Math.round((val-Math.floor(val))*100); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + (r < 10 ? "0"+r:r);
|
||||
case "# ? / ?": ff = frac(aval, 9, true); return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] === 0 ? " " : ff[1] + "/" + ff[2]);
|
||||
case "# ?? / ??": ff = frac(aval, 99, true); return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],2," ") + "/" + rpad(ff[2],2," ") : " ");
|
||||
case "# ??? / ???": ff = frac(aval, 999, true); return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],3," ") + "/" + rpad(ff[2],3," ") : " ");
|
||||
case "#,##0.0": r = Math.round((val-Math.floor(val))*10); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,1,"0");
|
||||
case "#,##0.00": r = Math.round((val-Math.floor(val))*100); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,2,"0");
|
||||
case "#,##0.000": r = Math.round((val-Math.floor(val))*1000); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,3,0);
|
||||
case "#,##0.0000": r = Math.round((val-Math.floor(val))*10000); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,4,0);
|
||||
case "#,##0.00000": r = Math.round((val-Math.floor(val))*Math.pow(10,5)); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,5,0);
|
||||
case "#,##0.000000": r = Math.round((val-Math.floor(val))*Math.pow(10,6)); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,6,0);
|
||||
case "#,##0.0000000": r = Math.round((val-Math.floor(val))*Math.pow(10,7)); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,7,0);
|
||||
case "#,##0.00000000": r = Math.round((val-Math.floor(val))*Math.pow(10,8)); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,8,0);
|
||||
case "#,##0.000000000": r = Math.round((val-Math.floor(val))*Math.pow(10,9)); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(r,9,0);
|
||||
default:
|
||||
}
|
||||
throw new Error("unsupported format |" + fmt + "|");
|
||||
@ -282,10 +290,10 @@ function eval_fmt(fmt, v, opts, flen) {
|
||||
/* Tokenize */
|
||||
while(i < fmt.length) {
|
||||
switch((c = fmt[i])) {
|
||||
case 'G': /* General */
|
||||
if(fmt.substr(i, i+6).toLowerCase() !== "general")
|
||||
throw 'unrecognized character ' + fmt[i] + ' in ' + fmt;
|
||||
out.push({t:'G',v:'General'}); i+=7; break;
|
||||
case 'G': /* General */
|
||||
if(fmt.substr(i, i+6).toLowerCase() !== "general")
|
||||
throw 'unrecognized character ' + fmt[i] + ' in ' + fmt;
|
||||
out.push({t:'G',v:'General'}); i+=7; break;
|
||||
case '"': /* Literal text */
|
||||
for(o="";fmt[++i] !== '"' && i < fmt.length;) o += fmt[i];
|
||||
out.push({t:'t', v:o}); ++i; break;
|
||||
@ -295,35 +303,35 @@ function eval_fmt(fmt, v, opts, flen) {
|
||||
case '@': /* Text Placeholder */
|
||||
out.push({t:'T', v:v}); ++i; break;
|
||||
/* Dates */
|
||||
case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
|
||||
c = c.toLowerCase();
|
||||
/* falls through */
|
||||
case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
|
||||
c = c.toLowerCase();
|
||||
/* falls through */
|
||||
case 'm': case 'd': case 'y': case 'h': case 's': case 'e':
|
||||
if(v < 0) return "";
|
||||
if(!dt) dt = parse_date_code(v, opts);
|
||||
if(!dt) return "";
|
||||
o = fmt[i]; while((fmt[++i]||"").toLowerCase() === c) o+=c;
|
||||
if(!dt) return "";
|
||||
o = fmt[i]; while((fmt[++i]||"").toLowerCase() === c) o+=c;
|
||||
if(c === 's' && fmt[i] === '.' && fmt[i+1] === '0') { o+='.'; while(fmt[++i] === '0') o+= '0'; }
|
||||
if(c === 'm' && lst.toLowerCase() === 'h') c = 'M'; /* m = minute */
|
||||
if(c === 'h') c = hr;
|
||||
o = o.toLowerCase();
|
||||
o = o.toLowerCase();
|
||||
q={t:c, v:o}; out.push(q); lst = c; break;
|
||||
case 'A':
|
||||
if(!dt) dt = parse_date_code(v, opts);
|
||||
if(!dt) return "";
|
||||
if(!dt) return "";
|
||||
q={t:c,v:"A"};
|
||||
if(fmt.substr(i, 3) === "A/P") {q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;}
|
||||
else if(fmt.substr(i,5) === "AM/PM") { q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; }
|
||||
else { q.t = "t"; i++; }
|
||||
else { q.t = "t"; i++; }
|
||||
out.push(q); lst = c; break;
|
||||
case '[': /* TODO: Fix this -- ignore all conditionals and formatting */
|
||||
o = c;
|
||||
while(fmt[i++] !== ']') o += fmt[i];
|
||||
if(o.match(/\[[HhMmSs]*\]/)) {
|
||||
if(!dt) dt = parse_date_code(v, opts);
|
||||
if(!dt) return "";
|
||||
out.push({t:'Z', v:o.toLowerCase()});
|
||||
} else { o=""; }
|
||||
if(o.match(/\[[HhMmSs]*\]/)) {
|
||||
if(!dt) dt = parse_date_code(v, opts);
|
||||
if(!dt) return "";
|
||||
out.push({t:'Z', v:o.toLowerCase()});
|
||||
} else { o=""; }
|
||||
break;
|
||||
/* Numbers */
|
||||
case '0': case '#':
|
||||
@ -339,7 +347,7 @@ function eval_fmt(fmt, v, opts, flen) {
|
||||
out.push({t:'D', v:o}); break;
|
||||
case ' ': out.push({t:c,v:c}); ++i; break;
|
||||
default:
|
||||
if("$-+/():!^&'~{}<>=".indexOf(c) === -1)
|
||||
if(",$-+/():!^&'~{}<>=".indexOf(c) === -1)
|
||||
throw 'unrecognized character ' + fmt[i] + ' in ' + fmt;
|
||||
out.push({t:'t', v:c}); ++i; break;
|
||||
}
|
||||
@ -361,30 +369,30 @@ function eval_fmt(fmt, v, opts, flen) {
|
||||
case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'A': case 'e': case 'Z':
|
||||
out[i].v = write_date(out[i].t, out[i].v, dt);
|
||||
out[i].t = 't'; break;
|
||||
case 'n': case '(':
|
||||
case 'n': case '(': case '?':
|
||||
var jj = i+1;
|
||||
while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (out[jj].t == " " && (out[jj+1]||{}).t === "?" ) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || out[jj].v == '$' || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) {
|
||||
if(out[jj].v!==' ') out[i].v += ' ' + out[jj].v;
|
||||
while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (" t".indexOf(out[jj].t) > -1 && "?t".indexOf((out[jj+1]||{}).t)>-1 && (out[jj+1].t == '?' || out[jj+1].v == '/')) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || out[jj].v == '$' || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) {
|
||||
out[i].v += out[jj].v;
|
||||
delete out[jj]; ++jj;
|
||||
}
|
||||
out[i].v = write_num(out[i].t, out[i].v, v);
|
||||
out[i].t = 't';
|
||||
i = jj-1; break;
|
||||
case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
|
||||
default: throw "unrecognized type " + out[i].t;
|
||||
i = jj-1; break;
|
||||
case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
|
||||
default: console.error(out); throw "unrecognized type " + out[i].t;
|
||||
}
|
||||
}
|
||||
return out.map(function(x){return x.v;}).join("");
|
||||
}
|
||||
SSF._eval = eval_fmt;
|
||||
function choose_fmt(fmt, v, o) {
|
||||
if(typeof fmt === 'number') fmt = ((o&&o.table) ? o.table : table_fmt)[fmt];
|
||||
if(typeof fmt === 'number') fmt = ((o&&o.table) ? o.table : table_fmt)[fmt];
|
||||
if(typeof fmt === "string") fmt = split_fmt(fmt);
|
||||
var l = fmt.length;
|
||||
switch(fmt.length) {
|
||||
case 1: fmt = fmt[0].indexOf("@")>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
|
||||
case 2: fmt = fmt[1].indexOf("@")>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
|
||||
case 3: fmt = fmt[2].indexOf("@")>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
|
||||
case 1: fmt = fmt[0].indexOf("@")>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
|
||||
case 2: fmt = fmt[1].indexOf("@")>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
|
||||
case 3: fmt = fmt[2].indexOf("@")>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
|
||||
case 4: break;
|
||||
default: throw "cannot find right format for |" + fmt + "|";
|
||||
}
|
||||
@ -393,11 +401,11 @@ function choose_fmt(fmt, v, o) {
|
||||
}
|
||||
var format = function format(fmt,v,o) {
|
||||
fixopts(o = (o||{}));
|
||||
if(typeof fmt === "string" && fmt.toLowerCase() === "general") return general_fmt(v, o);
|
||||
if(typeof fmt === 'number') fmt = (o.table || table_fmt)[fmt];
|
||||
if(typeof fmt === "string" && fmt.toLowerCase() === "general") return general_fmt(v, o);
|
||||
if(typeof fmt === 'number') fmt = (o.table || table_fmt)[fmt];
|
||||
var f = choose_fmt(fmt, v, o);
|
||||
if(f[1].toLowerCase() === "general") return general_fmt(v,o);
|
||||
if(v === true) v = "TRUE"; if(v === false) v = "FALSE";
|
||||
if(f[1].toLowerCase() === "general") return general_fmt(v,o);
|
||||
if(v === true) v = "TRUE"; if(v === false) v = "FALSE";
|
||||
return eval_fmt(f[1], v, o, f[0]);
|
||||
};
|
||||
|
||||
@ -411,7 +419,7 @@ SSF.load_table = function(tbl) { for(var i=0; i!=0x0188; ++i) if(tbl[i]) SSF.loa
|
||||
make_ssf(SSF);
|
||||
var XLSX = {};
|
||||
(function(XLSX){
|
||||
XLSX.version = '0.3.7';
|
||||
XLSX.version = '0.3.8';
|
||||
function parsexmltag(tag) {
|
||||
var words = tag.split(/\s+/);
|
||||
var z = {'0': words[0]};
|
||||
@ -1291,60 +1299,50 @@ function split_cell(cstr) { return cstr.replace(/(\$?[A-Z]*)(\$?[0-9]*)/,"$1,$2"
|
||||
function decode_cell(cstr) { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; }
|
||||
function decode_range(range) { var x =range.split(":").map(decode_cell); return {s:x[0],e:x[x.length-1]}; }
|
||||
function encode_range(range) { return encode_cell(range.s) + ":" + encode_cell(range.e); }
|
||||
/**
|
||||
* Convert a sheet into an array of objects where the column headers are keys.
|
||||
**/
|
||||
function sheet_to_row_object_array(sheet){
|
||||
var val, rowObject, range, columnHeaders, emptyRow, C;
|
||||
var outSheet = [];
|
||||
if (sheet["!ref"]) {
|
||||
range = decode_range(sheet["!ref"]);
|
||||
|
||||
columnHeaders = {};
|
||||
for (C = range.s.c; C <= range.e.c; ++C) {
|
||||
val = sheet[encode_cell({
|
||||
c: C,
|
||||
r: range.s.r
|
||||
})];
|
||||
if(val){
|
||||
switch(val.t) {
|
||||
case 's': case 'str': columnHeaders[C] = val.v; break;
|
||||
case 'n': columnHeaders[C] = val.v; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var R = range.s.r + 1; R <= range.e.r; ++R) {
|
||||
emptyRow = true;
|
||||
//Row number is recorded in the prototype
|
||||
//so that it doesn't appear when stringified.
|
||||
rowObject = Object.create({ __rowNum__ : R });
|
||||
for (C = range.s.c; C <= range.e.c; ++C) {
|
||||
val = sheet[encode_cell({
|
||||
c: C,
|
||||
r: R
|
||||
})];
|
||||
if(val !== undefined) switch(val.t){
|
||||
case 's': case 'str': case 'b': case 'n':
|
||||
if(val.v !== undefined) {
|
||||
rowObject[columnHeaders[C]] = val.v;
|
||||
emptyRow = false;
|
||||
}
|
||||
break;
|
||||
case 'e': break; /* throw */
|
||||
default: throw 'unrecognized type ' + val.t;
|
||||
}
|
||||
}
|
||||
if(!emptyRow) {
|
||||
outSheet.push(rowObject);
|
||||
function sheet_to_row_object_array(sheet, opts){
|
||||
var val, row, r, hdr = {}, isempty, R, C, v;
|
||||
var out = [];
|
||||
opts = opts || {};
|
||||
if(!sheet["!ref"]) return out;
|
||||
r = XLSX.utils.decode_range(sheet["!ref"]);
|
||||
for(R=r.s.r, C = r.s.c; C <= r.e.c; ++C) {
|
||||
val = sheet[encode_cell({c:C,r:R})];
|
||||
if(val){
|
||||
switch(val.t) {
|
||||
case 's': case 'str': hdr[C] = val.v; break;
|
||||
case 'n': hdr[C] = val.v; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return outSheet;
|
||||
|
||||
for (R = r.s.r + 1; R <= r.e.r; ++R) {
|
||||
isempty = true;
|
||||
/* row index available as __rowNum__ */
|
||||
row = Object.create({ __rowNum__ : R });
|
||||
for (C = r.s.c; C <= r.e.c; ++C) {
|
||||
val = sheet[encode_cell({c: C,r: R})];
|
||||
if(!val) continue;
|
||||
v = (val || {}).v;
|
||||
switch(val.t){
|
||||
case 's': case 'str': case 'b': case 'n':
|
||||
if(val.v !== undefined) {
|
||||
row[hdr[C]] = val.v;
|
||||
isempty = false;
|
||||
}
|
||||
break;
|
||||
case 'e': break; /* throw */
|
||||
default: throw 'unrecognized type ' + val.t;
|
||||
}
|
||||
}
|
||||
if(!isempty) out.push(row);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function sheet_to_csv(sheet) {
|
||||
function sheet_to_csv(sheet, opts) {
|
||||
var stringify = function stringify(val) {
|
||||
if(!val.t) return "";
|
||||
switch(val.t){
|
||||
case 'n': return String(val.v);
|
||||
case 's': case 'str':
|
||||
@ -1355,17 +1353,19 @@ function sheet_to_csv(sheet) {
|
||||
default: throw 'unrecognized type ' + val.t;
|
||||
}
|
||||
};
|
||||
var out = "";
|
||||
if(sheet["!ref"]) {
|
||||
var r = XLSX.utils.decode_range(sheet["!ref"]);
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
var row = [];
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var val = sheet[XLSX.utils.encode_cell({c:C,r:R})];
|
||||
row.push(val ? stringify(val).replace(/\\r\\n/g,"\n").replace(/\\t/g,"\t").replace(/\\\\/g,"\\").replace("\\\"","\"\"") : "");
|
||||
}
|
||||
out += row.join(",") + "\n";
|
||||
var out = "", txt = "";
|
||||
opts = opts || {};
|
||||
if(!sheet["!ref"]) return out;
|
||||
var r = XLSX.utils.decode_range(sheet["!ref"]);
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
var row = [];
|
||||
for(var C = r.s.c; C <= r.e.c; ++C) {
|
||||
var val = sheet[XLSX.utils.encode_cell({c:C,r:R})];
|
||||
if(!val) { row.push(""); continue; }
|
||||
txt = stringify(val);
|
||||
row.push(String(txt).replace(/\\r\\n/g,"\n").replace(/\\t/g,"\t").replace(/\\\\/g,"\\").replace("\\\"","\"\""));
|
||||
}
|
||||
out += row.join(opts.FS||",") + (opts.RS||"\n");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user