forked from sheetjs/sheetjs
266 lines
13 KiB
JavaScript
266 lines
13 KiB
JavaScript
|
function write_num_cm(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
|
||
|
var idx = fmt.length - 1;
|
||
|
while(fmt.charCodeAt(idx-1) === 44) --idx;
|
||
|
return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
|
||
|
}
|
||
|
function write_num_exp(fmt/*:string*/, val/*:number*/)/*:string*/{
|
||
|
var o/*:string*/;
|
||
|
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
|
||
|
if(fmt.match(/^#+0.0E\+0$/)) {
|
||
|
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
|
||
|
var ee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E)%period;
|
||
|
if(ee < 0) ee += period;
|
||
|
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
|
||
|
if(o.indexOf("e") === -1) {
|
||
|
var fakee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E);
|
||
|
if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
|
||
|
else o += "E+" + (fakee - ee);
|
||
|
while(o.substr(0,2) === "0.") {
|
||
|
o = o.charAt(0) + o.substr(2,period) + "." + o.substr(2+period);
|
||
|
o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0.");
|
||
|
}
|
||
|
o = o.replace(/\+-/,"-");
|
||
|
}
|
||
|
o = o.replace(/^([+-]?)(\d*)\.(\d*)[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[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
|
||
|
if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
|
||
|
return o.replace("e","E");
|
||
|
}
|
||
|
var frac1 = /# (\?+)( ?)\/( ?)(\d+)/;
|
||
|
function write_num_f1(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:string*/ {
|
||
|
var den = parseInt(r[4],10), rr = Math.round(aval * den), base = Math.floor(rr/den);
|
||
|
var myn = (rr - base*den), myd = den;
|
||
|
return sign + (base === 0 ? "" : ""+base) + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad_(myn,r[1].length) + r[2] + "/" + r[3] + pad0(myd,r[4].length));
|
||
|
}
|
||
|
function write_num_f2(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:string*/ {
|
||
|
return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
|
||
|
}
|
||
|
var dec1 = /^#*0*\.(0+)/;
|
||
|
var closeparen = /\).*[0#]/;
|
||
|
var phone = /\(###\) ###\\?-####/;
|
||
|
function hashq(str/*:string*/)/*:string*/ {
|
||
|
var o = "", cc;
|
||
|
for(var i = 0; i != str.length; ++i) switch((cc=str.charCodeAt(i))) {
|
||
|
case 35: break;
|
||
|
case 63: o+= " "; break;
|
||
|
case 48: o+= "0"; break;
|
||
|
default: o+= String.fromCharCode(cc);
|
||
|
}
|
||
|
return o;
|
||
|
}
|
||
|
function rnd(val/*:number*/, d/*:number*/)/*:string*/ { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
|
||
|
function dec(val/*:number*/, d/*:number*/)/*:number*/ {
|
||
|
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||
|
return 0;
|
||
|
}
|
||
|
return Math.round((val-Math.floor(val))*Math.pow(10,d));
|
||
|
}
|
||
|
function carry(val/*:number*/, d/*:number*/)/*:number*/ {
|
||
|
if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
function flr(val/*:number*/)/*:string*/ { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); }
|
||
|
function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
|
||
|
if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
|
||
|
var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
|
||
|
if(val >= 0) return write_num_flt('n', ffmt, val);
|
||
|
return '(' + write_num_flt('n', ffmt, -val) + ')';
|
||
|
}
|
||
|
if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm(type, fmt, val);
|
||
|
if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val);
|
||
|
if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val);
|
||
|
if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt[1]==' '?2:1),val);
|
||
|
var o;
|
||
|
var r/*:?Array<string>*/, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
|
||
|
if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length);
|
||
|
if(fmt.match(/^[#?]+$/)) {
|
||
|
o = pad0r(val,0); if(o === "0") o = "";
|
||
|
return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
|
||
|
}
|
||
|
if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign);
|
||
|
if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
|
||
|
if((r = fmt.match(dec1))) {
|
||
|
// $FlowIgnore
|
||
|
o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", /*::(*/r/*::||[""])*/[1].length-$1.length); });
|
||
|
return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
|
||
|
}
|
||
|
fmt = fmt.replace(/^#+([0.])/, "$1");
|
||
|
if((r = fmt.match(/^(0*)\.(#*)$/))) {
|
||
|
return sign + rnd(aval, r[2].length).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
|
||
|
}
|
||
|
if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify(pad0r(aval,0));
|
||
|
if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
|
||
|
return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length);
|
||
|
}
|
||
|
if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
|
||
|
if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
|
||
|
o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val));
|
||
|
ri = 0;
|
||
|
return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==='0'?'0':"";}));
|
||
|
}
|
||
|
if(fmt.match(phone)) {
|
||
|
o = write_num_flt(type, "##########", val);
|
||
|
return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
|
||
|
}
|
||
|
var oa = "";
|
||
|
if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
|
||
|
ri = Math.min(/*::String(*/r[4]/*::)*/.length,7);
|
||
|
ff = frac(aval, Math.pow(10,ri)-1, false);
|
||
|
o = "" + sign;
|
||
|
oa = write_num("n", /*::String(*/r[1]/*::)*/, ff[1]);
|
||
|
if(oa[oa.length-1] == " ") oa = oa.substr(0,oa.length-1) + "0";
|
||
|
o += oa + /*::String(*/r[2]/*::)*/ + "/" + /*::String(*/r[3]/*::)*/;
|
||
|
oa = rpad_(ff[2],ri);
|
||
|
if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
|
||
|
o += oa;
|
||
|
return o;
|
||
|
}
|
||
|
if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
|
||
|
ri = Math.min(Math.max(r[1].length, r[4].length),7);
|
||
|
ff = frac(aval, Math.pow(10,ri)-1, true);
|
||
|
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
|
||
|
}
|
||
|
if((r = fmt.match(/^[#0?]+$/))) {
|
||
|
o = pad0r(val, 0);
|
||
|
if(fmt.length <= o.length) return o;
|
||
|
return hashq(fmt.substr(0,fmt.length-o.length)) + o;
|
||
|
}
|
||
|
if((r = fmt.match(/^([#0?]+)\.([#0]+)$/))) {
|
||
|
o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
|
||
|
ri = o.indexOf(".");
|
||
|
var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
|
||
|
return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
|
||
|
}
|
||
|
if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
|
||
|
ri = dec(val, r[1].length);
|
||
|
return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(flr(val)).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(ri,r[1].length);
|
||
|
}
|
||
|
switch(fmt) {
|
||
|
case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : "";
|
||
|
default:
|
||
|
}
|
||
|
throw new Error("unsupported format |" + fmt + "|");
|
||
|
}
|
||
|
function write_num_cm2(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
|
||
|
var idx = fmt.length - 1;
|
||
|
while(fmt.charCodeAt(idx-1) === 44) --idx;
|
||
|
return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
|
||
|
}
|
||
|
function write_num_pct2(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
|
||
|
var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
|
||
|
return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
|
||
|
}
|
||
|
function write_num_exp2(fmt/*:string*/, val/*:number*/)/*:string*/{
|
||
|
var o/*:string*/;
|
||
|
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
|
||
|
if(fmt.match(/^#+0.0E\+0$/)) {
|
||
|
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
|
||
|
var ee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E)%period;
|
||
|
if(ee < 0) ee += period;
|
||
|
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
|
||
|
if(!o.match(/[Ee]/)) {
|
||
|
var fakee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E);
|
||
|
if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
|
||
|
else o += "E+" + (fakee - ee);
|
||
|
o = o.replace(/\+-/,"-");
|
||
|
}
|
||
|
o = o.replace(/^([+-]?)(\d*)\.(\d*)[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[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
|
||
|
if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
|
||
|
return o.replace("e","E");
|
||
|
}
|
||
|
function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
|
||
|
if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
|
||
|
var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
|
||
|
if(val >= 0) return write_num_int('n', ffmt, val);
|
||
|
return '(' + write_num_int('n', ffmt, -val) + ')';
|
||
|
}
|
||
|
if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm2(type, fmt, val);
|
||
|
if(fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val);
|
||
|
if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val);
|
||
|
if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt[1]==' '?2:1),val);
|
||
|
var o;
|
||
|
var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
|
||
|
if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length);
|
||
|
if(fmt.match(/^[#?]+$/)) {
|
||
|
o = (""+val); if(val === 0) o = "";
|
||
|
return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
|
||
|
}
|
||
|
if((r = fmt.match(frac1))) return write_num_f2(r, aval, sign);
|
||
|
if(fmt.match(/^#+0+$/)) return sign + pad0(aval,fmt.length - fmt.indexOf("0"));
|
||
|
if((r = fmt.match(dec1))) {
|
||
|
/*:: if(!Array.isArray(r)) throw "unreachable"; */
|
||
|
// $FlowIgnore
|
||
|
o = (""+val).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]);
|
||
|
// $FlowIgnore
|
||
|
o = o.replace(/\.(\d*)$/,function($$, $1) {
|
||
|
/*:: if(!Array.isArray(r)) throw "unreachable"; */
|
||
|
// $FlowIgnore
|
||
|
return "." + $1 + fill("0", r[1].length-$1.length); });
|
||
|
// $FlowIgnore
|
||
|
return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
|
||
|
}
|
||
|
fmt = fmt.replace(/^#+([0.])/, "$1");
|
||
|
if((r = fmt.match(/^(0*)\.(#*)$/))) {
|
||
|
return sign + (""+aval).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
|
||
|
}
|
||
|
if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify((""+aval));
|
||
|
if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
|
||
|
return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify((""+val)) + "." + fill('0',r[1].length);
|
||
|
}
|
||
|
if((r = fmt.match(/^#,#*,#0/))) return write_num_int(type,fmt.replace(/^#,#*,/,""),val);
|
||
|
if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
|
||
|
o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val));
|
||
|
ri = 0;
|
||
|
return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==='0'?'0':"";}));
|
||
|
}
|
||
|
if(fmt.match(phone)) {
|
||
|
o = write_num_int(type, "##########", val);
|
||
|
return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
|
||
|
}
|
||
|
var oa = "";
|
||
|
if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
|
||
|
ri = Math.min(r[4].length,7);
|
||
|
ff = frac(aval, Math.pow(10,ri)-1, false);
|
||
|
o = "" + sign;
|
||
|
oa = write_num("n", r[1], ff[1]);
|
||
|
if(oa[oa.length-1] == " ") oa = oa.substr(0,oa.length-1) + "0";
|
||
|
o += oa + r[2] + "/" + r[3];
|
||
|
oa = rpad_(ff[2],ri);
|
||
|
if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
|
||
|
o += oa;
|
||
|
return o;
|
||
|
}
|
||
|
if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
|
||
|
ri = Math.min(Math.max(r[1].length, r[4].length),7);
|
||
|
ff = frac(aval, Math.pow(10,ri)-1, true);
|
||
|
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
|
||
|
}
|
||
|
if((r = fmt.match(/^[#0?]+$/))) {
|
||
|
o = "" + val;
|
||
|
if(fmt.length <= o.length) return o;
|
||
|
return hashq(fmt.substr(0,fmt.length-o.length)) + o;
|
||
|
}
|
||
|
if((r = fmt.match(/^([#0]+)\.([#0]+)$/))) {
|
||
|
o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
|
||
|
ri = o.indexOf(".");
|
||
|
var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
|
||
|
return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
|
||
|
}
|
||
|
if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
|
||
|
return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify(""+val).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(0,r[1].length);
|
||
|
}
|
||
|
switch(fmt) {
|
||
|
case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
|
||
|
default:
|
||
|
}
|
||
|
throw new Error("unsupported format |" + fmt + "|");
|
||
|
}
|
||
|
return function write_num(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
|
||
|
return (val|0) === val ? write_num_int(type, fmt, val) : write_num_flt(type, fmt, val);
|
||
|
};})();
|