forked from sheetjs/sheetjs
		
	version bump 0.5.15: converging tests
- test script normalized - proper handling of empty sheet ranges - xlsb sheetStubs and calcchain parsing - jshint passes - updated SSF to 0.6.2
This commit is contained in:
		
							parent
							
								
									d462e18846
								
							
						
					
					
						commit
						56b10f3616
					
				| @ -6,7 +6,7 @@ var _strrev = function(x) { return String(x).split("").reverse().join("");}; | ||||
| function fill(c,l) { return new Array(l+1).join(c); } | ||||
| function pad(v,d,c){var t=String(v);return t.length>=d?t:(fill(c||0,d-t.length)+t);} | ||||
| function rpad(v,d,c){var t=String(v);return t.length>=d?t:(t+fill(c||0,d-t.length));} | ||||
| SSF.version = '0.6.1'; | ||||
| SSF.version = '0.6.2'; | ||||
| /* Options */ | ||||
| var opts_fmt = {}; | ||||
| function fixopts(o){for(var y in opts_fmt) if(o[y]===undefined) o[y]=opts_fmt[y];} | ||||
| @ -121,7 +121,7 @@ var parse_date_code = function parse_date_code(v,opts) { | ||||
| 	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(out.u > .999) { | ||||
| 	if(out.u > 0.999) { | ||||
| 		out.u = 0; | ||||
| 		if(++time == 86400) { time = 0; ++date; } | ||||
| 	} | ||||
| @ -202,13 +202,13 @@ var write_date = function(type, fmt, val) { | ||||
| /*jshint +W086 */ | ||||
| var commaify = function(s) { return _strrev(_strrev(s).replace(/.../g,"$&,")).replace(/^,/,""); }; | ||||
| var write_num = function(type, fmt, val) { | ||||
| 	if(type === '(') { | ||||
| 	if(type === '(' && !fmt.match(/\).*[0#]/)) { | ||||
| 		var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,""); | ||||
| 		if(val >= 0) return write_num('n', ffmt, val); | ||||
| 		return '(' + write_num('n', ffmt, -val) + ')'; | ||||
| 	} | ||||
| 	var mul = 0, o; | ||||
| 	fmt = fmt.replace(/%/g,function(x) { mul++; return ""; }); | ||||
| 	fmt = fmt.replace(/%/g,function() { mul++; return ""; }); | ||||
| 	if(mul !== 0) return write_num(type, fmt, val * Math.pow(10,2*mul)) + fill("%",mul); | ||||
| 	fmt = fmt.replace(/(\.0+)(,+)$/g,function($$,$1,$2) { mul=$2.length; return $1; }); | ||||
| 	if(mul !== 0) return write_num(type, fmt, val / Math.pow(10,3*mul)); | ||||
| @ -261,6 +261,18 @@ var write_num = function(type, fmt, val) { | ||||
| 		return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(rr,r[1].length,0); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^#,#*,#0/))) return write_num(type,fmt.replace(/^#,#*,/,""),val); | ||||
| 	if((r = fmt.match(/^([0#]+)-([0#]+)$/))) { | ||||
| 		ff = write_num(type, fmt.replace(/-/,""), val); | ||||
| 		return ff.substr(0,ff.length - r[2].length) + "-" + ff.substr(ff.length-r[2].length); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^([0#]+)-([0#]+)-([0#]+)$/))) { | ||||
| 		ff = write_num(type, fmt.replace(/-/g,""), val); | ||||
| 		return ff.substr(0,ff.length - r[2].length - r[3].length) + "-" + ff.substr(ff.length-r[2].length - r[3].length, r[2].length) + "-" + ff.substr(ff.length-r[3].length); | ||||
| 	} | ||||
| 	if(fmt == "(###) ###-####") { | ||||
| 		ff = write_num(type, "##########", val); | ||||
| 		return "(" + ff.substr(0,3) + ") " + ff.substr(3, 3) + "-" + ff.substr(6); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^([?]+)([ ]?)\/([ ]?)([?]+)/))) { | ||||
| 		rr = Math.min(Math.max(r[1].length, r[4].length),7); | ||||
| 		ff = frac(aval, Math.pow(10,rr)-1, false); | ||||
| @ -385,12 +397,12 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 	switch(bt) { | ||||
| 		case 0: break; | ||||
| 		case 1: | ||||
| 			if(dt.u >= .5) { dt.u = 0; ++dt.S; } | ||||
| 			if(dt.u >= 0.5) { dt.u = 0; ++dt.S; } | ||||
| 			if(dt.S >= 60) { dt.S = 0; ++dt.M; } | ||||
| 			if(dt.M >= 60) { dt.M = 0; ++dt.H; } | ||||
| 			break; | ||||
| 		case 2: | ||||
| 			if(dt.u >= .5) { dt.u = 0; ++dt.S; } | ||||
| 			if(dt.u >= 0.5) { dt.u = 0; ++dt.S; } | ||||
| 			if(dt.S >= 60) { dt.S = 0; ++dt.M; } | ||||
| 			break; | ||||
| 	} | ||||
| @ -403,7 +415,7 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 				out[i].t = 't'; break; | ||||
| 			case 'n': case '(': case '?': | ||||
| 				var jj = i+1; | ||||
| 				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 == '/' || '$€'.indexOf(out[jj].v) > -1 || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) { | ||||
| 				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 == '(' && (")n ".indexOf(out[jj].t) > -1) || out[jj].t == 't' && (out[jj].v == '/' || '$€'.indexOf(out[jj].v) > -1 || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) { | ||||
| 					out[i].v += out[jj].v; | ||||
| 					delete out[jj]; ++jj; | ||||
| 				} | ||||
| @ -429,7 +441,27 @@ function choose_fmt(fmt, v, o) { | ||||
| 		default: throw "cannot find right format for |" + fmt + "|"; | ||||
| 	} | ||||
| 	if(typeof v !== "number") return [fmt.length, fmt[3]]; | ||||
| 	return [l, v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2]]; | ||||
| 	var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2]; | ||||
| 	if(fmt[0].match(/\[[=<>]/) || fmt[1].match(/\[[=<>]/)) { | ||||
| 		var chk = function(v, rr, out) { | ||||
| 			if(!rr) return null; | ||||
| 			var found = false; | ||||
| 			var thresh = Number(rr[2]); | ||||
| 			switch(rr[1]) { | ||||
| 				case "=":  if(v == thresh) found = true; break; | ||||
| 				case ">":  if(v >  thresh) found = true; break; | ||||
| 				case "<":  if(v <  thresh) found = true; break; | ||||
| 				case "<>": if(v != thresh) found = true; break; | ||||
| 				case ">=": if(v >= thresh) found = true; break; | ||||
| 				case "<=": if(v <= thresh) found = true; break; | ||||
| 			} | ||||
| 			return found ? out : null; | ||||
| 		}; | ||||
| 		var m1 = fmt[0].match(/\[([=<>]*)([-]?\d+)\]/); | ||||
| 		var m2 = fmt[1].match(/\[([=<>]*)([-]?\d+)\]/); | ||||
| 		return chk(v, m1, [l, fmt[0]]) || chk(v, m2, [l, fmt[1]]) || [l, fmt[m1&&m2?2:1]]; | ||||
| 	} | ||||
| 	return [l, ff]; | ||||
| } | ||||
| var format = function format(fmt,v,o) { | ||||
| 	fixopts(o = (o||{})); | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| XLSX.version = '0.5.14'; | ||||
| XLSX.version = '0.5.15'; | ||||
|  | ||||
| @ -100,7 +100,7 @@ function parse_BrtColor(data, length) { | ||||
| 	var d = read(1); | ||||
| 	out.fValidRGB = d & 1; | ||||
| 	out.xColorType = d >>> 1; | ||||
| 	out.index = read(1) | ||||
| 	out.index = read(1); | ||||
| 	out.nTintAndShade = read(2, 'i'); | ||||
| 	out.bRed   = read(1); | ||||
| 	out.bGreen = read(1); | ||||
|  | ||||
| @ -6,7 +6,8 @@ var parse_BrtBeginSst = function(data, length) { | ||||
| /* [MS-XLSB] 2.1.7.45 Shared Strings */ | ||||
| var parse_sst_bin = function(data, opts) { | ||||
| 	var s = []; | ||||
| 	recordhopper(data, function(val, R) { | ||||
| 	var pass = false; | ||||
| 	recordhopper(data, function(val, R, RT) { | ||||
| 		switch(R.n) { | ||||
| 			case 'BrtBeginSst': s.Count = val[0]; s.Unique = val[1]; break; | ||||
| 			case 'BrtSSTItem': s.push(val); break; | ||||
|  | ||||
| @ -14,7 +14,7 @@ var ct2type = { | ||||
| 	"application/vnd.ms-excel.sharedStrings": "strs", /*XLSB*/ | ||||
| 
 | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains", /*XLS[XM]*/ | ||||
| 	//"application/vnd.ms-excel.calcChain": "calcchains", /*XLSB*/
 | ||||
| 	"application/vnd.ms-excel.calcChain": "calcchains", /*XLSB*/ | ||||
| 
 | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": "comments", /*XLS[XM]*/ | ||||
| 	"application/vnd.ms-excel.comments": "comments", /*XLSB*/ | ||||
| @ -107,23 +107,6 @@ function parseCustomProps(data) { | ||||
| 	return p; | ||||
| } | ||||
| 
 | ||||
| /* 18.6 Calculation Chain */ | ||||
| function parseDeps(data) { | ||||
| 	var d = []; | ||||
| 	var l = 0, i = 1; | ||||
| 	(data.match(/<[^>]*>/g)||[]).forEach(function(x) { | ||||
| 		var y = parsexmltag(x); | ||||
| 		switch(y[0]) { | ||||
| 			case '<?xml': break; | ||||
| 			/* 18.6.2  calcChain CT_CalcChain 1 */ | ||||
| 			case '<calcChain': case '<calcChain>': case '</calcChain>': break; | ||||
| 			/* 18.6.1  c CT_CalcCell 1 */ | ||||
| 			case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break; | ||||
| 		} | ||||
| 	}); | ||||
| 	return d; | ||||
| } | ||||
| 
 | ||||
| var ctext = {}; | ||||
| function parseCT(data) { | ||||
| 	if(!data || !data.match) return data; | ||||
							
								
								
									
										17
									
								
								bits/61_ccxml.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										17
									
								
								bits/61_ccxml.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| /* 18.6 Calculation Chain */ | ||||
| function parse_cc_xml(data, opts) { | ||||
| 	var d = []; | ||||
| 	var l = 0, i = 1; | ||||
| 	(data.match(/<[^>]*>/g)||[]).forEach(function(x) { | ||||
| 		var y = parsexmltag(x); | ||||
| 		switch(y[0]) { | ||||
| 			case '<?xml': break; | ||||
| 			/* 18.6.2  calcChain CT_CalcChain 1 */ | ||||
| 			case '<calcChain': case '<calcChain>': case '</calcChain>': break; | ||||
| 			/* 18.6.1  c CT_CalcCell 1 */ | ||||
| 			case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break; | ||||
| 		} | ||||
| 	}); | ||||
| 	return d; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										28
									
								
								bits/62_ccbin.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										28
									
								
								bits/62_ccbin.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| /* [MS-XLSB] 2.6.4.1 */ | ||||
| var parse_BrtCalcChainItem$ = function(data, length) { | ||||
| 	var out = {}; | ||||
| 	out.i = data.read_shift(4); | ||||
| 	var cell = {}; | ||||
| 	cell.r = data.read_shift(4); | ||||
| 	cell.c = data.read_shift(4); | ||||
| 	out.r = encode_cell(cell); | ||||
| 	var flags = data.read_shift(1); | ||||
| 	if(flags & 0x2) out.l = '1'; | ||||
| 	if(flags & 0x8) out.a = '1'; | ||||
| 	return out; | ||||
| }; | ||||
| 
 | ||||
| /* 18.6 Calculation Chain */ | ||||
| function parse_cc_bin(data, opts) { | ||||
| 	var out = []; | ||||
| 	var pass = false; | ||||
| 	recordhopper(data, function(val, R, RT) { | ||||
| 		switch(R.n) { | ||||
| 			case 'BrtCalcChainItem$': out.push(val); break; | ||||
| 			case 'BrtBeginCalcChain$': break; | ||||
| 			case 'BrtEndCalcChain$': break; | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n); | ||||
| 		} | ||||
| 	}); | ||||
| 	return out; | ||||
| } | ||||
| @ -23,7 +23,7 @@ function insertCommentsIntoSheet(sheetName, sheet, comments) { | ||||
| 		if (!cell) { | ||||
| 			cell = {}; | ||||
| 			sheet[comment.ref] = cell; | ||||
| 			var range = decode_range(sheet["!ref"]); | ||||
| 			var range = decode_range(sheet["!ref"]||"BDWGO1000001:A1"); | ||||
| 			var thisCell = decode_cell(comment.ref); | ||||
| 			if(range.s.r > thisCell.r) range.s.r = thisCell.r; | ||||
| 			if(range.e.r < thisCell.r) range.e.r = thisCell.r; | ||||
|  | ||||
| @ -88,8 +88,8 @@ function parse_ws_xml(data, opts) { | ||||
| 			s[cell.r] = p; | ||||
| 		}); | ||||
| 	}); | ||||
| 	if(!s["!ref"]) s["!ref"] = encode_range(refguess); | ||||
| 	if(opts.sheetRows) { | ||||
| 	if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess); | ||||
| 	if(opts.sheetRows && s["!ref"]) { | ||||
| 		var tmpref = decode_range(s["!ref"]); | ||||
| 		if(opts.sheetRows < +tmpref.e.r) { | ||||
| 			tmpref.e.r = opts.sheetRows - 1; | ||||
|  | ||||
| @ -20,7 +20,10 @@ var parse_BrtWsProp = function(data, length) { | ||||
| }; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.303 BrtCellBlank */ | ||||
| var parse_BrtCellBlank = parsenoop; | ||||
| var parse_BrtCellBlank = function(data, length) { | ||||
| 	var cell = parse_Cell(data); | ||||
| 	return [cell]; | ||||
| }; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.304 BrtCellBool */ | ||||
| var parse_BrtCellBool = function(data, length) { | ||||
| @ -170,7 +173,14 @@ var parse_ws_bin = function(data, opts) { | ||||
| 				if(refguess.e.c < val[0].c) refguess.e.c = val[0].c; | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'BrtCellBlank': break; // (blank cell)
 | ||||
| 			case 'BrtCellBlank': if(!opts.sheetStubs) break; | ||||
| 				p = {t:'str',v:undefined}; | ||||
| 				s[encode_cell({c:val[0].c,r:row.r})] = p; | ||||
| 				if(refguess.s.r > row.r) refguess.s.r = row.r; | ||||
| 				if(refguess.s.c > val[0].c) refguess.s.c = val[0].c; | ||||
| 				if(refguess.e.r < row.r) refguess.e.r = row.r; | ||||
| 				if(refguess.e.c < val[0].c) refguess.e.c = val[0].c; | ||||
| 				break; | ||||
| 
 | ||||
| 			/* Merge Cells */ | ||||
| 			case 'BrtBeginMergeCells': break; | ||||
| @ -281,8 +291,8 @@ var parse_ws_bin = function(data, opts) { | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + R.n); | ||||
| 		} | ||||
| 	}, opts); | ||||
| 	s["!ref"] = encode_range(ref); | ||||
| 	if(opts.sheetRows) { | ||||
| 	if(!s["!ref"] && ref) s["!ref"] = encode_range(ref); | ||||
| 	if(opts.sheetRows && s["!ref"]) { | ||||
| 		var tmpref = decode_range(s["!ref"]); | ||||
| 		if(opts.sheetRows < +tmpref.e.r) { | ||||
| 			tmpref.e.r = opts.sheetRows - 1; | ||||
|  | ||||
| @ -17,3 +17,7 @@ function parse_sst(data, name, opts) { | ||||
| function parse_cmnt(data, name, opts) { | ||||
| 	return name.substr(-4)===".bin" ? parse_comments_bin(data, opts) : parse_comments_xml(data, opts); | ||||
| } | ||||
| 
 | ||||
| function parse_cc(data, name, opts) { | ||||
| 	return name.substr(-4)===".bin" ? parse_cc_bin(data, opts) : parse_cc_xml(data, opts); | ||||
| } | ||||
|  | ||||
| @ -54,6 +54,7 @@ var RecordEnum = { | ||||
| 	0x003B: { n:"BrtStr", f:parsenoop }, | ||||
| 	0x003C: { n:"BrtColInfo", f:parsenoop }, | ||||
| 	0x003E: { n:"BrtCellRString", f:parsenoop }, | ||||
| 	0x003F: { n:"BrtCalcChainItem$", f:parse_BrtCalcChainItem$ }, | ||||
| 	0x0040: { n:"BrtDVal", f:parsenoop }, | ||||
| 	0x0041: { n:"BrtSxvcellNum", f:parsenoop }, | ||||
| 	0x0042: { n:"BrtSxvcellStr", f:parsenoop }, | ||||
| @ -456,6 +457,8 @@ var RecordEnum = { | ||||
| 	0x020D: { n:"BrtVolErr", f:parsenoop }, | ||||
| 	0x020E: { n:"BrtVolStr", f:parsenoop }, | ||||
| 	0x020F: { n:"BrtVolBool", f:parsenoop }, | ||||
| 	0x0210: { n:"BrtBeginCalcChain$", f:parsenoop }, | ||||
| 	0x0211: { n:"BrtEndCalcChain$", f:parsenoop }, | ||||
| 	0x0212: { n:"BrtBeginSortState", f:parsenoop }, | ||||
| 	0x0213: { n:"BrtEndSortState", f:parsenoop }, | ||||
| 	0x0214: { n:"BrtBeginSortCond", f:parsenoop }, | ||||
|  | ||||
| @ -50,7 +50,7 @@ function parseZip(zip, opts) { | ||||
| 	sheets = {}; | ||||
| 
 | ||||
| 	var deps = {}; | ||||
| 	if(opts.bookDeps && dir.calcchain) deps=parseDeps(getzipdata(zip, dir.calcchain.replace(/^\//,''))); | ||||
| 	if(opts.bookDeps && dir.calcchain) deps=parse_cc(getzipdata(zip, dir.calcchain.replace(/^\//,'')),dir.calcchain,opts); | ||||
| 
 | ||||
| 	var i=0; | ||||
| 	var sheetRels = {}; | ||||
|  | ||||
							
								
								
									
										152
									
								
								dist/xlsx.js
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										152
									
								
								dist/xlsx.js
									
									
									
									
										vendored
									
									
								
							| @ -9,7 +9,7 @@ var _strrev = function(x) { return String(x).split("").reverse().join("");}; | ||||
| function fill(c,l) { return new Array(l+1).join(c); } | ||||
| function pad(v,d,c){var t=String(v);return t.length>=d?t:(fill(c||0,d-t.length)+t);} | ||||
| function rpad(v,d,c){var t=String(v);return t.length>=d?t:(t+fill(c||0,d-t.length));} | ||||
| SSF.version = '0.6.1'; | ||||
| SSF.version = '0.6.2'; | ||||
| /* Options */ | ||||
| var opts_fmt = {}; | ||||
| function fixopts(o){for(var y in opts_fmt) if(o[y]===undefined) o[y]=opts_fmt[y];} | ||||
| @ -124,7 +124,7 @@ var parse_date_code = function parse_date_code(v,opts) { | ||||
| 	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(out.u > .999) { | ||||
| 	if(out.u > 0.999) { | ||||
| 		out.u = 0; | ||||
| 		if(++time == 86400) { time = 0; ++date; } | ||||
| 	} | ||||
| @ -205,13 +205,13 @@ var write_date = function(type, fmt, val) { | ||||
| /*jshint +W086 */ | ||||
| var commaify = function(s) { return _strrev(_strrev(s).replace(/.../g,"$&,")).replace(/^,/,""); }; | ||||
| var write_num = function(type, fmt, val) { | ||||
| 	if(type === '(') { | ||||
| 	if(type === '(' && !fmt.match(/\).*[0#]/)) { | ||||
| 		var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,""); | ||||
| 		if(val >= 0) return write_num('n', ffmt, val); | ||||
| 		return '(' + write_num('n', ffmt, -val) + ')'; | ||||
| 	} | ||||
| 	var mul = 0, o; | ||||
| 	fmt = fmt.replace(/%/g,function(x) { mul++; return ""; }); | ||||
| 	fmt = fmt.replace(/%/g,function() { mul++; return ""; }); | ||||
| 	if(mul !== 0) return write_num(type, fmt, val * Math.pow(10,2*mul)) + fill("%",mul); | ||||
| 	fmt = fmt.replace(/(\.0+)(,+)$/g,function($$,$1,$2) { mul=$2.length; return $1; }); | ||||
| 	if(mul !== 0) return write_num(type, fmt, val / Math.pow(10,3*mul)); | ||||
| @ -264,6 +264,18 @@ var write_num = function(type, fmt, val) { | ||||
| 		return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(rr,r[1].length,0); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^#,#*,#0/))) return write_num(type,fmt.replace(/^#,#*,/,""),val); | ||||
| 	if((r = fmt.match(/^([0#]+)-([0#]+)$/))) { | ||||
| 		ff = write_num(type, fmt.replace(/-/,""), val); | ||||
| 		return ff.substr(0,ff.length - r[2].length) + "-" + ff.substr(ff.length-r[2].length); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^([0#]+)-([0#]+)-([0#]+)$/))) { | ||||
| 		ff = write_num(type, fmt.replace(/-/g,""), val); | ||||
| 		return ff.substr(0,ff.length - r[2].length - r[3].length) + "-" + ff.substr(ff.length-r[2].length - r[3].length, r[2].length) + "-" + ff.substr(ff.length-r[3].length); | ||||
| 	} | ||||
| 	if(fmt == "(###) ###-####") { | ||||
| 		ff = write_num(type, "##########", val); | ||||
| 		return "(" + ff.substr(0,3) + ") " + ff.substr(3, 3) + "-" + ff.substr(6); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^([?]+)([ ]?)\/([ ]?)([?]+)/))) { | ||||
| 		rr = Math.min(Math.max(r[1].length, r[4].length),7); | ||||
| 		ff = frac(aval, Math.pow(10,rr)-1, false); | ||||
| @ -388,12 +400,12 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 	switch(bt) { | ||||
| 		case 0: break; | ||||
| 		case 1: | ||||
| 			if(dt.u >= .5) { dt.u = 0; ++dt.S; } | ||||
| 			if(dt.u >= 0.5) { dt.u = 0; ++dt.S; } | ||||
| 			if(dt.S >= 60) { dt.S = 0; ++dt.M; } | ||||
| 			if(dt.M >= 60) { dt.M = 0; ++dt.H; } | ||||
| 			break; | ||||
| 		case 2: | ||||
| 			if(dt.u >= .5) { dt.u = 0; ++dt.S; } | ||||
| 			if(dt.u >= 0.5) { dt.u = 0; ++dt.S; } | ||||
| 			if(dt.S >= 60) { dt.S = 0; ++dt.M; } | ||||
| 			break; | ||||
| 	} | ||||
| @ -406,7 +418,7 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 				out[i].t = 't'; break; | ||||
| 			case 'n': case '(': case '?': | ||||
| 				var jj = i+1; | ||||
| 				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 == '/' || '$€'.indexOf(out[jj].v) > -1 || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) { | ||||
| 				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 == '(' && (")n ".indexOf(out[jj].t) > -1) || out[jj].t == 't' && (out[jj].v == '/' || '$€'.indexOf(out[jj].v) > -1 || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) { | ||||
| 					out[i].v += out[jj].v; | ||||
| 					delete out[jj]; ++jj; | ||||
| 				} | ||||
| @ -432,7 +444,27 @@ function choose_fmt(fmt, v, o) { | ||||
| 		default: throw "cannot find right format for |" + fmt + "|"; | ||||
| 	} | ||||
| 	if(typeof v !== "number") return [fmt.length, fmt[3]]; | ||||
| 	return [l, v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2]]; | ||||
| 	var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2]; | ||||
| 	if(fmt[0].match(/\[[=<>]/) || fmt[1].match(/\[[=<>]/)) { | ||||
| 		var chk = function(v, rr, out) { | ||||
| 			if(!rr) return null; | ||||
| 			var found = false; | ||||
| 			var thresh = Number(rr[2]); | ||||
| 			switch(rr[1]) { | ||||
| 				case "=":  if(v == thresh) found = true; break; | ||||
| 				case ">":  if(v >  thresh) found = true; break; | ||||
| 				case "<":  if(v <  thresh) found = true; break; | ||||
| 				case "<>": if(v != thresh) found = true; break; | ||||
| 				case ">=": if(v >= thresh) found = true; break; | ||||
| 				case "<=": if(v <= thresh) found = true; break; | ||||
| 			} | ||||
| 			return found ? out : null; | ||||
| 		}; | ||||
| 		var m1 = fmt[0].match(/\[([=<>]*)([-]?\d+)\]/); | ||||
| 		var m2 = fmt[1].match(/\[([=<>]*)([-]?\d+)\]/); | ||||
| 		return chk(v, m1, [l, fmt[0]]) || chk(v, m2, [l, fmt[1]]) || [l, fmt[m1&&m2?2:1]]; | ||||
| 	} | ||||
| 	return [l, ff]; | ||||
| } | ||||
| var format = function format(fmt,v,o) { | ||||
| 	fixopts(o = (o||{})); | ||||
| @ -455,7 +487,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.5.14'; | ||||
| XLSX.version = '0.5.15'; | ||||
| var current_codepage, current_cptable, cptable; | ||||
| if(typeof module !== "undefined" && typeof require !== 'undefined') { | ||||
| 	if(typeof cptable === 'undefined') cptable = require('codepage'); | ||||
| @ -774,7 +806,7 @@ function parse_BrtColor(data, length) { | ||||
| 	var d = read(1); | ||||
| 	out.fValidRGB = d & 1; | ||||
| 	out.xColorType = d >>> 1; | ||||
| 	out.index = read(1) | ||||
| 	out.index = read(1); | ||||
| 	out.nTintAndShade = read(2, 'i'); | ||||
| 	out.bRed   = read(1); | ||||
| 	out.bGreen = read(1); | ||||
| @ -946,7 +978,8 @@ var parse_BrtBeginSst = function(data, length) { | ||||
| /* [MS-XLSB] 2.1.7.45 Shared Strings */ | ||||
| var parse_sst_bin = function(data, opts) { | ||||
| 	var s = []; | ||||
| 	recordhopper(data, function(val, R) { | ||||
| 	var pass = false; | ||||
| 	recordhopper(data, function(val, R, RT) { | ||||
| 		switch(R.n) { | ||||
| 			case 'BrtBeginSst': s.Count = val[0]; s.Unique = val[1]; break; | ||||
| 			case 'BrtSSTItem': s.push(val); break; | ||||
| @ -1161,7 +1194,7 @@ var ct2type = { | ||||
| 	"application/vnd.ms-excel.sharedStrings": "strs", /*XLSB*/ | ||||
| 
 | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains", /*XLS[XM]*/ | ||||
| 	//"application/vnd.ms-excel.calcChain": "calcchains", /*XLSB*/
 | ||||
| 	"application/vnd.ms-excel.calcChain": "calcchains", /*XLSB*/ | ||||
| 
 | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": "comments", /*XLS[XM]*/ | ||||
| 	"application/vnd.ms-excel.comments": "comments", /*XLSB*/ | ||||
| @ -1254,23 +1287,6 @@ function parseCustomProps(data) { | ||||
| 	return p; | ||||
| } | ||||
| 
 | ||||
| /* 18.6 Calculation Chain */ | ||||
| function parseDeps(data) { | ||||
| 	var d = []; | ||||
| 	var l = 0, i = 1; | ||||
| 	(data.match(/<[^>]*>/g)||[]).forEach(function(x) { | ||||
| 		var y = parsexmltag(x); | ||||
| 		switch(y[0]) { | ||||
| 			case '<?xml': break; | ||||
| 			/* 18.6.2  calcChain CT_CalcChain 1 */ | ||||
| 			case '<calcChain': case '<calcChain>': case '</calcChain>': break; | ||||
| 			/* 18.6.1  c CT_CalcCell 1 */ | ||||
| 			case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break; | ||||
| 		} | ||||
| 	}); | ||||
| 	return d; | ||||
| } | ||||
| 
 | ||||
| var ctext = {}; | ||||
| function parseCT(data) { | ||||
| 	if(!data || !data.match) return data; | ||||
| @ -1335,6 +1351,51 @@ function parseRels(data, currentFilePath) { | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* 18.6 Calculation Chain */ | ||||
| function parse_cc_xml(data, opts) { | ||||
| 	var d = []; | ||||
| 	var l = 0, i = 1; | ||||
| 	(data.match(/<[^>]*>/g)||[]).forEach(function(x) { | ||||
| 		var y = parsexmltag(x); | ||||
| 		switch(y[0]) { | ||||
| 			case '<?xml': break; | ||||
| 			/* 18.6.2  calcChain CT_CalcChain 1 */ | ||||
| 			case '<calcChain': case '<calcChain>': case '</calcChain>': break; | ||||
| 			/* 18.6.1  c CT_CalcCell 1 */ | ||||
| 			case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break; | ||||
| 		} | ||||
| 	}); | ||||
| 	return d; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.6.4.1 */ | ||||
| var parse_BrtCalcChainItem$ = function(data, length) { | ||||
| 	var out = {}; | ||||
| 	out.i = data.read_shift(4); | ||||
| 	var cell = {}; | ||||
| 	cell.r = data.read_shift(4); | ||||
| 	cell.c = data.read_shift(4); | ||||
| 	out.r = encode_cell(cell); | ||||
| 	var flags = data.read_shift(1); | ||||
| 	if(flags & 0x2) out.l = '1'; | ||||
| 	if(flags & 0x8) out.a = '1'; | ||||
| 	return out; | ||||
| }; | ||||
| 
 | ||||
| /* 18.6 Calculation Chain */ | ||||
| function parse_cc_bin(data, opts) { | ||||
| 	var out = []; | ||||
| 	var pass = false; | ||||
| 	recordhopper(data, function(val, R, RT) { | ||||
| 		switch(R.n) { | ||||
| 			case 'BrtCalcChainItem$': out.push(val); break; | ||||
| 			case 'BrtBeginCalcChain$': break; | ||||
| 			case 'BrtEndCalcChain$': break; | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n); | ||||
| 		} | ||||
| 	}); | ||||
| 	return out; | ||||
| } | ||||
| /* 18.7.3 CT_Comment */ | ||||
| function parse_comments_xml(data, opts) { | ||||
| 	if(data.match(/<comments *\/>/)) return []; | ||||
| @ -1429,7 +1490,7 @@ function insertCommentsIntoSheet(sheetName, sheet, comments) { | ||||
| 		if (!cell) { | ||||
| 			cell = {}; | ||||
| 			sheet[comment.ref] = cell; | ||||
| 			var range = decode_range(sheet["!ref"]); | ||||
| 			var range = decode_range(sheet["!ref"]||"BDWGO1000001:A1"); | ||||
| 			var thisCell = decode_cell(comment.ref); | ||||
| 			if(range.s.r > thisCell.r) range.s.r = thisCell.r; | ||||
| 			if(range.e.r < thisCell.r) range.e.r = thisCell.r; | ||||
| @ -1544,8 +1605,8 @@ function parse_ws_xml(data, opts) { | ||||
| 			s[cell.r] = p; | ||||
| 		}); | ||||
| 	}); | ||||
| 	if(!s["!ref"]) s["!ref"] = encode_range(refguess); | ||||
| 	if(opts.sheetRows) { | ||||
| 	if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess); | ||||
| 	if(opts.sheetRows && s["!ref"]) { | ||||
| 		var tmpref = decode_range(s["!ref"]); | ||||
| 		if(opts.sheetRows < +tmpref.e.r) { | ||||
| 			tmpref.e.r = opts.sheetRows - 1; | ||||
| @ -1583,7 +1644,10 @@ var parse_BrtWsProp = function(data, length) { | ||||
| }; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.303 BrtCellBlank */ | ||||
| var parse_BrtCellBlank = parsenoop; | ||||
| var parse_BrtCellBlank = function(data, length) { | ||||
| 	var cell = parse_Cell(data); | ||||
| 	return [cell]; | ||||
| }; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.304 BrtCellBool */ | ||||
| var parse_BrtCellBool = function(data, length) { | ||||
| @ -1733,7 +1797,14 @@ var parse_ws_bin = function(data, opts) { | ||||
| 				if(refguess.e.c < val[0].c) refguess.e.c = val[0].c; | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'BrtCellBlank': break; // (blank cell)
 | ||||
| 			case 'BrtCellBlank': if(!opts.sheetStubs) break; | ||||
| 				p = {t:'str',v:undefined}; | ||||
| 				s[encode_cell({c:val[0].c,r:row.r})] = p; | ||||
| 				if(refguess.s.r > row.r) refguess.s.r = row.r; | ||||
| 				if(refguess.s.c > val[0].c) refguess.s.c = val[0].c; | ||||
| 				if(refguess.e.r < row.r) refguess.e.r = row.r; | ||||
| 				if(refguess.e.c < val[0].c) refguess.e.c = val[0].c; | ||||
| 				break; | ||||
| 
 | ||||
| 			/* Merge Cells */ | ||||
| 			case 'BrtBeginMergeCells': break; | ||||
| @ -1844,8 +1915,8 @@ var parse_ws_bin = function(data, opts) { | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + R.n); | ||||
| 		} | ||||
| 	}, opts); | ||||
| 	s["!ref"] = encode_range(ref); | ||||
| 	if(opts.sheetRows) { | ||||
| 	if(!s["!ref"] && ref) s["!ref"] = encode_range(ref); | ||||
| 	if(opts.sheetRows && s["!ref"]) { | ||||
| 		var tmpref = decode_range(s["!ref"]); | ||||
| 		if(opts.sheetRows < +tmpref.e.r) { | ||||
| 			tmpref.e.r = opts.sheetRows - 1; | ||||
| @ -2151,6 +2222,10 @@ function parse_sst(data, name, opts) { | ||||
| function parse_cmnt(data, name, opts) { | ||||
| 	return name.substr(-4)===".bin" ? parse_comments_bin(data, opts) : parse_comments_xml(data, opts); | ||||
| } | ||||
| 
 | ||||
| function parse_cc(data, name, opts) { | ||||
| 	return name.substr(-4)===".bin" ? parse_cc_bin(data, opts) : parse_cc_xml(data, opts); | ||||
| } | ||||
| /* [MS-XLSB] 2.3 Record Enumeration */ | ||||
| var RecordEnum = { | ||||
| 	0x0000: { n:"BrtRowHdr", f:parse_BrtRowHdr }, | ||||
| @ -2207,6 +2282,7 @@ var RecordEnum = { | ||||
| 	0x003B: { n:"BrtStr", f:parsenoop }, | ||||
| 	0x003C: { n:"BrtColInfo", f:parsenoop }, | ||||
| 	0x003E: { n:"BrtCellRString", f:parsenoop }, | ||||
| 	0x003F: { n:"BrtCalcChainItem$", f:parse_BrtCalcChainItem$ }, | ||||
| 	0x0040: { n:"BrtDVal", f:parsenoop }, | ||||
| 	0x0041: { n:"BrtSxvcellNum", f:parsenoop }, | ||||
| 	0x0042: { n:"BrtSxvcellStr", f:parsenoop }, | ||||
| @ -2609,6 +2685,8 @@ var RecordEnum = { | ||||
| 	0x020D: { n:"BrtVolErr", f:parsenoop }, | ||||
| 	0x020E: { n:"BrtVolStr", f:parsenoop }, | ||||
| 	0x020F: { n:"BrtVolBool", f:parsenoop }, | ||||
| 	0x0210: { n:"BrtBeginCalcChain$", f:parsenoop }, | ||||
| 	0x0211: { n:"BrtEndCalcChain$", f:parsenoop }, | ||||
| 	0x0212: { n:"BrtBeginSortState", f:parsenoop }, | ||||
| 	0x0213: { n:"BrtEndSortState", f:parsenoop }, | ||||
| 	0x0214: { n:"BrtBeginSortCond", f:parsenoop }, | ||||
| @ -3043,7 +3121,7 @@ function parseZip(zip, opts) { | ||||
| 	sheets = {}; | ||||
| 
 | ||||
| 	var deps = {}; | ||||
| 	if(opts.bookDeps && dir.calcchain) deps=parseDeps(getzipdata(zip, dir.calcchain.replace(/^\//,''))); | ||||
| 	if(opts.bookDeps && dir.calcchain) deps=parse_cc(getzipdata(zip, dir.calcchain.replace(/^\//,'')),dir.calcchain,opts); | ||||
| 
 | ||||
| 	var i=0; | ||||
| 	var sheetRels = {}; | ||||
|  | ||||
							
								
								
									
										6
									
								
								dist/xlsx.min.js
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										6
									
								
								dist/xlsx.min.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/xlsx.min.map
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								dist/xlsx.min.map
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -1,6 +1,6 @@ | ||||
| { | ||||
| 	"name": "xlsx", | ||||
| 	"version": "0.5.14", | ||||
| 	"version": "0.5.15", | ||||
| 	"author": "sheetjs", | ||||
| 	"description": "XLSB / XLSX / XLSM (Excel 2007+ Spreadsheet) parser", | ||||
| 	"keywords": [ "xlsx", "xlsb", "xlsm", "office", "excel", "spreadsheet" ], | ||||
| @ -9,7 +9,7 @@ | ||||
| 	}, | ||||
| 	"main": "./xlsx", | ||||
| 	"dependencies": { | ||||
| 		"ssf":"~0.6.1", | ||||
| 		"ssf":"~0.6.2", | ||||
| 		"codepage":"", | ||||
| 		"cfb":"", | ||||
| 		"jszip":"~2.1.0", | ||||
|  | ||||
							
								
								
									
										220
									
								
								test.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										220
									
								
								test.js
									
									
									
									
									
								
							| @ -1,7 +1,7 @@ | ||||
| /* vim: set ts=2: */ | ||||
| var XLSX; | ||||
| var X; | ||||
| var fs = require('fs'), assert = require('assert'); | ||||
| describe('source',function(){it('should load',function(){XLSX=require('./');});}); | ||||
| describe('source',function(){it('should load',function(){X=require('./');});}); | ||||
| 
 | ||||
| var opts = {}; | ||||
| if(process.env.WTF) opts.WTF = true; | ||||
| @ -19,6 +19,26 @@ function normalizecsv(x) { return x.replace(/\t/g,",").replace(/#{255}/g,"").rep | ||||
| 
 | ||||
| var dir = "./test_files/"; | ||||
| 
 | ||||
| var paths = { | ||||
| 	cp1:  dir + 'custom_properties.xlsx', | ||||
| 	cp2:  dir + 'custom_properties.xlsb', | ||||
| 	cst1: dir + 'comments_stress_test.xlsx', | ||||
| 	cst2: dir + 'comments_stress_test.xlsb', | ||||
| 	fst1: dir + 'formula_stress_test.xlsx', | ||||
| 	fst2: dir + 'formula_stress_test.xlsb', | ||||
| 	fstb: dir + 'formula_stress_test.xlsb', | ||||
| 	lon1: dir + 'LONumbers.xlsx', | ||||
| 	mc1:  dir + 'merge_cells.xlsx', | ||||
| 	mc2:  dir + 'merge_cells.xlsb', | ||||
| 	nf1:  dir + 'number_format.xlsm', | ||||
| 	nf2:  dir + 'number_format.xlsb', | ||||
| 	swc1: dir + 'apachepoi_SimpleWithComments.xlsx', | ||||
| 	swc2: dir + '2013/apachepoi_SimpleWithComments.xlsx.xlsb' | ||||
| }; | ||||
| 
 | ||||
| var N1 = 'XLSX'; | ||||
| var N2 = 'XLSB'; | ||||
| 
 | ||||
| function parsetest(x, wb) { | ||||
| 	describe(x + ' should have all bits', function() { | ||||
| 		var sname = dir + '2011/' + x + '.sheetnames'; | ||||
| @ -34,21 +54,21 @@ function parsetest(x, wb) { | ||||
| 	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]); | ||||
| 				var csv = X.utils.make_csv(wb.Sheets[ws]); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| 	describe(x + ' should generate JSON', function() { | ||||
| 		wb.SheetNames.forEach(function(ws, i) { | ||||
| 			it('#' + i + ' (' + ws + ')', function() { | ||||
| 				var json = XLSX.utils.sheet_to_row_object_array(wb.Sheets[ws]); | ||||
| 				var json = X.utils.sheet_to_row_object_array(wb.Sheets[ws]); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| 	describe(x + ' should generate formulae', function() { | ||||
| 		wb.SheetNames.forEach(function(ws, i) { | ||||
| 			it('#' + i + ' (' + ws + ')', function() { | ||||
| 				var json = XLSX.utils.get_formulae(wb.Sheets[ws]); | ||||
| 				var json = X.utils.get_formulae(wb.Sheets[ws]); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| @ -63,7 +83,7 @@ function parsetest(x, wb) { | ||||
| 			} | ||||
| 			it('#' + i + ' (' + ws + ')', fs.existsSync(name) ? function() { | ||||
| 				var file = fs.readFileSync(name, 'utf-8'); | ||||
| 				var csv = XLSX.utils.make_csv(wb.Sheets[ws]); | ||||
| 				var csv = X.utils.make_csv(wb.Sheets[ws]); | ||||
| 				assert.equal(normalizecsv(csv), normalizecsv(file), "CSV badness"); | ||||
| 			} : null); | ||||
| 		}); | ||||
| @ -71,7 +91,7 @@ function parsetest(x, wb) { | ||||
| 	if(!fs.existsSync(dir + '2013/' + x + '.xlsb')) return; | ||||
| 	describe(x + '.xlsb from 2013', function() { | ||||
| 		it('should parse', function() { | ||||
| 			var xlsb = XLSX.readFile(dir + '2013/' + x + '.xlsb', opts); | ||||
| 			var wb = X.readFile(dir + '2013/' + x + '.xlsb', opts); | ||||
| 		}); | ||||
| 	}); | ||||
| } | ||||
| @ -79,7 +99,7 @@ function parsetest(x, wb) { | ||||
| describe('should parse test files', function() { | ||||
| 	files.forEach(function(x) { | ||||
| 		it(x, x.substr(-8) == ".pending" ? null : function() { | ||||
| 			var wb = XLSX.readFile(dir + x, opts); | ||||
| 			var wb = X.readFile(dir + x, opts); | ||||
| 			parsetest(x, wb); | ||||
| 		}); | ||||
| 	}); | ||||
| @ -88,11 +108,11 @@ describe('should parse test files', function() { | ||||
| describe('options', function() { | ||||
| 	var html_cell_types = ['s']; | ||||
| 	before(function() { | ||||
| 		XLSX = require('./'); | ||||
| 		X = require('./'); | ||||
| 	}); | ||||
| 	describe('cell', function() { | ||||
| 		it('should generate HTML by default', function() { | ||||
| 			var wb = XLSX.readFile(dir + 'comments_stress_test.xlsx'); | ||||
| 			var wb = X.readFile(paths.cst1); | ||||
| 			var ws = wb.Sheets.Sheet1; | ||||
| 			Object.keys(ws).forEach(function(addr) { | ||||
| 				if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return; | ||||
| @ -100,7 +120,7 @@ describe('options', function() { | ||||
| 			}); | ||||
| 		}); | ||||
| 		it('should not generate HTML when requested', function() { | ||||
| 			var wb = XLSX.readFile(dir+'comments_stress_test.xlsx', {cellHTML:false}); | ||||
| 			var wb = X.readFile(paths.cst1, {cellHTML:false}); | ||||
| 			var ws = wb.Sheets.Sheet1; | ||||
| 			Object.keys(ws).forEach(function(addr) { | ||||
| 				if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return; | ||||
| @ -108,7 +128,7 @@ describe('options', function() { | ||||
| 			}); | ||||
| 		}); | ||||
| 		it('should generate formulae by default', function() { | ||||
| 			var wb = XLSX.readFile(dir + 'formula_stress_test.xlsb'); | ||||
| 			var wb = X.readFile(paths.fstb); | ||||
| 			var found = false; | ||||
| 			wb.SheetNames.forEach(function(s) { | ||||
| 				var ws = wb.Sheets[s]; | ||||
| @ -120,7 +140,7 @@ describe('options', function() { | ||||
| 			assert(found); | ||||
| 		}); | ||||
| 		it('should not generate formulae when requested', function() { | ||||
| 			var wb =XLSX.readFile(dir+'formula_stress_test.xlsb',{cellFormula:false}); | ||||
| 			var wb =X.readFile(paths.fstb,{cellFormula:false}); | ||||
| 			wb.SheetNames.forEach(function(s) { | ||||
| 				var ws = wb.Sheets[s]; | ||||
| 				Object.keys(ws).forEach(function(addr) { | ||||
| @ -130,7 +150,7 @@ describe('options', function() { | ||||
| 			}); | ||||
| 		}); | ||||
| 		it('should not generate number formats by default', function() { | ||||
| 			var wb = XLSX.readFile(dir+'number_format.xlsm'); | ||||
| 			var wb = X.readFile(paths.nf1); | ||||
| 			wb.SheetNames.forEach(function(s) { | ||||
| 				var ws = wb.Sheets[s]; | ||||
| 				Object.keys(ws).forEach(function(addr) { | ||||
| @ -140,7 +160,7 @@ describe('options', function() { | ||||
| 			}); | ||||
| 		}); | ||||
| 		it('should generate number formats when requested', function() { | ||||
| 			var wb = XLSX.readFile(dir+'number_format.xlsm', {cellNF: true}); | ||||
| 			var wb = X.readFile(paths.nf1, {cellNF: true}); | ||||
| 			wb.SheetNames.forEach(function(s) { | ||||
| 				var ws = wb.Sheets[s]; | ||||
| 				Object.keys(ws).forEach(function(addr) { | ||||
| @ -152,16 +172,16 @@ describe('options', function() { | ||||
| 	}); | ||||
| 	describe('sheet', function() { | ||||
| 		it('should not generate sheet stubs by default', function() { | ||||
| 			var wb = XLSX.readFile(dir+'merge_cells.xlsx'); | ||||
| 			var wb = X.readFile(paths.mc1); | ||||
| 			assert.throws(function() { wb.Sheets.Merge.A2.v; }); | ||||
| 			wb = XLSX.readFile(dir+'merge_cells.xlsb'); | ||||
| 			wb = X.readFile(paths.mc2); | ||||
| 			assert.throws(function() { wb.Sheets.Merge.A2.v; }); | ||||
| 		}); | ||||
| 		it('should generate sheet stubs when requested', function() { | ||||
| 			var wb = XLSX.readFile(dir+'merge_cells.xlsx', {sheetStubs:true}); | ||||
| 			var wb = X.readFile(paths.mc1, {sheetStubs:true}); | ||||
| 			assert(typeof wb.Sheets.Merge.A2.t !== 'undefined'); | ||||
| 			wb = X.readFile(paths.mc2, {sheetStubs:true}); | ||||
| 			assert(typeof wb.Sheets.Merge.A2.t !== 'undefined'); | ||||
| 			wb = XLSX.readFile(dir+'merge_cells.xlsb', {sheetStubs:true}); | ||||
| 			assert.throws(function() { wb.Sheets.Merge.A2.v; }); | ||||
| 		}); | ||||
| 		function checkcells(wb, A46, B26, C16, D2) { | ||||
| 			assert((typeof wb.Sheets.Text.A46 !== 'undefined') == A46); | ||||
| @ -170,98 +190,105 @@ describe('options', function() { | ||||
| 			assert((typeof wb.Sheets.Text.D2  !== 'undefined') == D2); | ||||
| 		} | ||||
| 		it('should read all cells by default', function() { | ||||
| 			var wb = XLSX.readFile(dir+'formula_stress_test.xlsb'); | ||||
| 			var wb = X.readFile(paths.fst1); | ||||
| 			checkcells(wb, true, true, true, true); | ||||
| 			wb = XLSX.readFile(dir+'formula_stress_test.xlsx'); | ||||
| 			wb = X.readFile(paths.fst2); | ||||
| 			checkcells(wb, true, true, true, true); | ||||
| 		}); | ||||
| 		it('sheetRows n=20', function() { | ||||
| 			var wb = XLSX.readFile(dir+'formula_stress_test.xlsx', {sheetRows:20}); | ||||
| 			var wb = X.readFile(paths.fst1, {sheetRows:20}); | ||||
| 			checkcells(wb, false, false, true, true); | ||||
| 			wb = XLSX.readFile(dir+'formula_stress_test.xlsb', {sheetRows:20}); | ||||
| 			wb = X.readFile(paths.fst2, {sheetRows:20}); | ||||
| 			checkcells(wb, false, false, true, true); | ||||
| 		}); | ||||
| 		it('sheetRows n=10', function() { | ||||
| 			var wb = XLSX.readFile(dir+'formula_stress_test.xlsb', {sheetRows:10}); | ||||
| 			var wb = X.readFile(paths.fst1, {sheetRows:10}); | ||||
| 			checkcells(wb, false, false, false, true); | ||||
| 			wb = XLSX.readFile(dir+'formula_stress_test.xlsx', {sheetRows:10}); | ||||
| 			wb = X.readFile(paths.fst2, {sheetRows:10}); | ||||
| 			checkcells(wb, false, false, false, true); | ||||
| 		}); | ||||
| 	}); | ||||
| 	describe('book', function() { | ||||
| 		it('bookSheets should not generate sheets', function() { | ||||
| 			var wb = XLSX.readFile(dir+'merge_cells.xlsx', {bookSheets:true}); | ||||
| 			var wb = X.readFile(paths.mc1, {bookSheets:true}); | ||||
| 			assert(typeof wb.Sheets === 'undefined'); | ||||
| 			var wb = X.readFile(paths.mc2, {bookSheets:true}); | ||||
| 			assert(typeof wb.Sheets === 'undefined'); | ||||
| 		}); | ||||
| 		it('bookProps should not generate sheets', function() { | ||||
| 			var wb = XLSX.readFile(dir+'number_format.xlsb', {bookProps:true}); | ||||
| 			var wb = X.readFile(paths.nf1, {bookProps:true}); | ||||
| 			assert(typeof wb.Sheets === 'undefined'); | ||||
| 			wb = X.readFile(paths.nf2, {bookProps:true}); | ||||
| 			assert(typeof wb.Sheets === 'undefined'); | ||||
| 		}); | ||||
| 		it('bookProps && bookSheets should not generate sheets', function() { | ||||
| 			var wb = XLSX.readFile(dir+'LONumbers.xlsx', {bookProps:true, bookSheets:true}); | ||||
| 			var wb = X.readFile(paths.lon1, {bookProps:true, bookSheets:true}); | ||||
| 			assert(typeof wb.Sheets === 'undefined'); | ||||
| 		}); | ||||
| 		it('should not generate deps by default', function() { | ||||
| 			var wb = XLSX.readFile(dir+'formula_stress_test.xlsx'); | ||||
| 			var wb = X.readFile(paths.fst1); | ||||
| 			assert(typeof wb.Deps === 'undefined' || !(wb.Deps.length>0)); | ||||
| 			wb = X.readFile(paths.fst2); | ||||
| 			assert(typeof wb.Deps === 'undefined' || !(wb.Deps.length>0)); | ||||
| 		}); | ||||
| 		it('bookDeps should generate deps', function() { | ||||
| 			var wb = XLSX.readFile(dir+'formula_stress_test.xlsx', {bookDeps:true}); | ||||
| 			var wb = X.readFile(paths.fst1, {bookDeps:true}); | ||||
| 			assert(typeof wb.Deps !== 'undefined' && wb.Deps.length > 0); | ||||
| 			wb = X.readFile(paths.fst2, {bookDeps:true}); | ||||
| 			assert(typeof wb.Deps !== 'undefined' && wb.Deps.length > 0); | ||||
| 		}); | ||||
| 		it('should not generate files or keys by default', function() { | ||||
| 			var wb = XLSX.readFile(dir+'formula_stress_test.xlsx'); | ||||
| 			assert(typeof wb.files === 'undefined'); | ||||
| 			assert(typeof wb.keys === 'undefined'); | ||||
| 			wb = XLSX.readFile(dir+'formula_stress_test.xlsb'); | ||||
| 			assert(typeof wb.files === 'undefined'); | ||||
| 			assert(typeof wb.keys === 'undefined'); | ||||
| 		var ckf = function(wb, fields, exists) { fields.forEach(function(f) { | ||||
| 			assert((typeof wb[f] !== 'undefined') == exists); | ||||
| 		}); }; | ||||
| 		it('should not generate book files by default', function() { | ||||
| 			var wb = X.readFile(paths.fst1); | ||||
| 			ckf(wb, ['files', 'keys'], false); | ||||
| 			wb = X.readFile(paths.fst2); | ||||
| 			ckf(wb, ['files', 'keys'], false); | ||||
| 		}); | ||||
| 		it('bookFiles should generate files and keys', function() { | ||||
| 			var wb = XLSX.readFile(dir+'formula_stress_test.xlsx', {bookFiles:true}); | ||||
| 			assert(typeof wb.files !== 'undefined'); | ||||
| 			assert(typeof wb.keys !== 'undefined'); | ||||
| 			wb = XLSX.readFile(dir+'formula_stress_test.xlsb', {bookFiles:true}); | ||||
| 			assert(typeof wb.files !== 'undefined'); | ||||
| 			assert(typeof wb.keys !== 'undefined'); | ||||
| 		it('bookFiles should generate book files', function() { | ||||
| 			var wb = X.readFile(paths.fst1, {bookFiles:true}); | ||||
| 			ckf(wb, ['files', 'keys'], true); | ||||
| 			wb = X.readFile(paths.fst2, {bookFiles:true}); | ||||
| 			ckf(wb, ['files', 'keys'], true); | ||||
| 		}); | ||||
| 	}); | ||||
| }); | ||||
| 
 | ||||
| describe('input formats', function() { | ||||
| 	it('should read binary strings', function() { | ||||
| 		XLSX.read(fs.readFileSync(dir+'comments_stress_test.xlsb', 'binary'), {type: 'binary'}); | ||||
| 		XLSX.read(fs.readFileSync(dir+'comments_stress_test.xlsx', 'binary'), {type: 'binary'}); | ||||
| 		X.read(fs.readFileSync(paths.cst1, 'binary'), {type: 'binary'}); | ||||
| 		X.read(fs.readFileSync(paths.cst2, 'binary'), {type: 'binary'}); | ||||
| 	}); | ||||
| 	it('should read base64 strings', function() { | ||||
| 		XLSX.read(fs.readFileSync(dir+'comments_stress_test.xlsb', 'base64'), {type: 'base64'}); | ||||
| 		XLSX.read(fs.readFileSync(dir+'comments_stress_test.xlsx', 'base64'), {type: 'base64'}); | ||||
| 		X.read(fs.readFileSync(paths.cst1, 'base64'), {type: 'base64'}); | ||||
| 		X.read(fs.readFileSync(paths.cst2, 'base64'), {type: 'base64'}); | ||||
| 	}); | ||||
| }); | ||||
| 
 | ||||
| describe('features', function() { | ||||
| 	it('should have comment as part of cell properties', function(){ | ||||
| 		var XLSX = require('./'); | ||||
| 		var X = require('./'); | ||||
| 		var sheet = 'Sheet1'; | ||||
| 		var wbxlsx=XLSX.readFile(dir+'apachepoi_SimpleWithComments.xlsx'); | ||||
| 		var wbxlsb=XLSX.readFile(dir+'2013/apachepoi_SimpleWithComments.xlsx.xlsb'); | ||||
| 		var wb1=X.readFile(paths.swc1); | ||||
| 		var wb2=X.readFile(paths.swc2); | ||||
| 
 | ||||
| 		[wbxlsx,wbxlsb].map(function(wb) { return wb.Sheets[sheet]; }).forEach(function(ws, i) { | ||||
| 		[wb1,wb2].map(function(wb) { return wb.Sheets[sheet]; }).forEach(function(ws, i) { | ||||
| 			assert.equal(ws.B1.c.length, 1,"must have 1 comment"); | ||||
| 			assert.equal(ws.B1.c[0].a, "Yegor Kozlov","must have the same author"); | ||||
| 			if(i > 0) return; | ||||
| 			assert.equal(ws.B1.c[0].t.replace(/\r\n/g,"\n"), "Yegor Kozlov:\nfirst cell", "must have the concatenated texts"); | ||||
| 			if(i > 0) return; | ||||
| 			assert.equal(ws.B1.c[0].r, '<r><rPr><b/><sz val="8"/><color indexed="81"/><rFont val="Tahoma"/></rPr><t>Yegor Kozlov:</t></r><r><rPr><sz val="8"/><color indexed="81"/><rFont val="Tahoma"/></rPr><t xml:space="preserve">\r\nfirst cell</t></r>', "must have the rich text representation"); | ||||
| 			assert.equal(ws.B1.c[0].h, '<span style="font-weight: bold;">Yegor Kozlov:</span><span style=""><br/>first cell</span>', "must have the html representation"); | ||||
| 		}); | ||||
| 	}); | ||||
| 
 | ||||
| 	describe('should parse core properties and custom properties', function() { | ||||
| 		var wbxlsx, wbxlsb; | ||||
| 		var wb1, wb2; | ||||
| 		before(function() { | ||||
| 			XLSX = require('./'); | ||||
| 			wbxlsx = XLSX.readFile(dir+'custom_properties.xlsx'); | ||||
| 			wbxlsb = XLSX.readFile(dir+'custom_properties.xlsb'); | ||||
| 			X = require('./'); | ||||
| 			wb1 = X.readFile(paths.cp1); | ||||
| 			wb2 = X.readFile(paths.cp2); | ||||
| 		}); | ||||
| 
 | ||||
| 		function coreprop(wb) { | ||||
| @ -275,50 +302,35 @@ describe('features', function() { | ||||
| 			assert.equal(wb.Custprops.Counter, -3.14); | ||||
| 		} | ||||
| 
 | ||||
| 		it('XLSX should parse core properties', function() { coreprop(wbxlsx); }); | ||||
| 		it('XLSB should parse core properties', function() { coreprop(wbxlsb); }); | ||||
| 
 | ||||
| 		it('XLSX should parse custom properties', function() { custprop(wbxlsx); }); | ||||
| 		it('XLSB should parse custom properties', function() { custprop(wbxlsb); }); | ||||
| 	}); | ||||
| 
 | ||||
| 	describe('should parse cells with date type (XLSX/XLSM)', function() { | ||||
| 		var wb, ws; | ||||
| 		before(function() { | ||||
| 			XLSX = require('./'); | ||||
| 			wb = XLSX.readFile(dir+'xlsx-stream-d-date-cell.xlsx'); | ||||
| 			var sheetName = 'Sheet1'; | ||||
| 			ws = wb.Sheets[sheetName]; | ||||
| 		}); | ||||
| 		it('Must have read the date', function() { | ||||
| 			var sheet = XLSX.utils.sheet_to_row_object_array(ws); | ||||
| 			assert.equal(sheet[3]['てすと'], '2/14/14'); | ||||
| 		}); | ||||
| 		it(N1 + ' should parse core properties', function() { coreprop(wb1); }); | ||||
| 		it(N2 + ' should parse core properties', function() { coreprop(wb2); }); | ||||
| 		it(N1 + ' should parse custom properties', function() { custprop(wb1); }); | ||||
| 		it(N2 + ' should parse custom properties', function() { custprop(wb2); }); | ||||
| 	}); | ||||
| 
 | ||||
| 	describe('sheetRows', function() { | ||||
| 		it('should use original range if not set', function() { | ||||
| 			var opts = {}; | ||||
| 			var wbxlsb = XLSX.readFile(dir+'formula_stress_test.xlsb', opts); | ||||
| 			var wbxlsx = XLSX.readFile(dir+'formula_stress_test.xlsx', opts); | ||||
| 			[wbxlsx, wbxlsb].forEach(function(wb) { | ||||
| 			var wb1 = X.readFile(paths.fst1, opts); | ||||
| 			var wb2 = X.readFile(paths.fst2, opts); | ||||
| 			[wb1, wb2].forEach(function(wb) { | ||||
| 				assert.equal(wb.Sheets.Text["!ref"],"A1:F49"); | ||||
| 			}); | ||||
| 		}); | ||||
| 		it('should adjust range if set', function() { | ||||
| 			var opts = {sheetRows:10}; | ||||
| 			var wbxlsb = XLSX.readFile(dir+'formula_stress_test.xlsb', opts); | ||||
| 			var wbxlsx = XLSX.readFile(dir+'formula_stress_test.xlsx', opts); | ||||
| 			[wbxlsx, wbxlsb].forEach(function(wb) { | ||||
| 			var wb1 = X.readFile(paths.fst1, opts); | ||||
| 			var wb2 = X.readFile(paths.fst2, opts); | ||||
| 			[wb1, wb2].forEach(function(wb) { | ||||
| 				assert.equal(wb.Sheets.Text["!fullref"],"A1:F49"); | ||||
| 				assert.equal(wb.Sheets.Text["!ref"],"A1:F10"); | ||||
| 			}); | ||||
| 		}); | ||||
| 		it('should not generate comment cells', function() { | ||||
| 			var opts = {sheetRows:10}; | ||||
| 			var wbxlsb = XLSX.readFile(dir+'comments_stress_test.xlsb', opts); | ||||
| 			var wbxlsx = XLSX.readFile(dir+'comments_stress_test.xlsx', opts); | ||||
| 			[wbxlsx, wbxlsb].forEach(function(wb) { | ||||
| 			var wb1 = X.readFile(paths.cst1, opts); | ||||
| 			var wb2 = X.readFile(paths.cst2, opts); | ||||
| 			[wb1, wb2].forEach(function(wb) { | ||||
| 				assert.equal(wb.Sheets.Sheet7["!fullref"],"A1:N34"); | ||||
| 				assert.equal(wb.Sheets.Sheet7["!ref"],"A1:A1"); | ||||
| 			}); | ||||
| @ -326,32 +338,46 @@ describe('features', function() { | ||||
| 	}); | ||||
| 
 | ||||
| 	describe('merge cells',function() { | ||||
| 		var wbxls, wbxml; | ||||
| 		var wb1, wb2; | ||||
| 		before(function() { | ||||
| 			XLS = require('./'); | ||||
| 			wbxlsx = XLS.readFile(dir+'merge_cells.xlsx'); | ||||
| 			wbxlsb = XLS.readFile(dir+'merge_cells.xlsb'); | ||||
| 			X = require('./'); | ||||
| 			wb1 = X.readFile(paths.mc1); | ||||
| 			wb2 = X.readFile(paths.mc2); | ||||
| 		}); | ||||
| 		it('should have !merges', function() { | ||||
| 			assert(wbxlsb.Sheets.Merge['!merges']); | ||||
| 			assert(wbxlsx.Sheets.Merge['!merges']); | ||||
| 			var m = [wbxlsx,wbxlsb].map(function(x) { return x.Sheets.Merge['!merges'].map(function(y) { return XLS.utils.encode_range(y); });}); | ||||
| 			assert(wb1.Sheets.Merge['!merges']); | ||||
| 			assert(wb2.Sheets.Merge['!merges']); | ||||
| 			var m = [wb1, wb2].map(function(x) { return x.Sheets.Merge['!merges'].map(function(y) { return X.utils.encode_range(y); });}); | ||||
| 			assert.deepEqual(m[0].sort(),m[1].sort()); | ||||
| 		}); | ||||
| 	}); | ||||
| 
 | ||||
| 	describe('should parse cells with date type (XLSX/XLSM)', function() { | ||||
| 		var wb, ws; | ||||
| 		before(function() { | ||||
| 			X = require('./'); | ||||
| 			wb = X.readFile(dir+'xlsx-stream-d-date-cell.xlsx'); | ||||
| 			var sheetName = 'Sheet1'; | ||||
| 			ws = wb.Sheets[sheetName]; | ||||
| 		}); | ||||
| 		it('Must have read the date', function() { | ||||
| 			var sheet = X.utils.sheet_to_row_object_array(ws); | ||||
| 			assert.equal(sheet[3]['てすと'], '2/14/14'); | ||||
| 		}); | ||||
| 	}); | ||||
| }); | ||||
| 
 | ||||
| describe('invalid files', function() { | ||||
| 	it('should fail on passwords', function() { | ||||
| 		assert.throws(function() { XLSX.readFile(dir + 'excel-reader-xlsx_error03.xlsx'); }); | ||||
| 		assert.throws(function() { X.readFile(dir + 'excel-reader-xlsx_error03.xlsx'); }); | ||||
| 	}); | ||||
| 	it('should fail on XLS files', function() { | ||||
| 		assert.throws(function() { XLSX.readFile(dir + 'roo_type_excel.xlsx'); }); | ||||
| 		assert.throws(function() { X.readFile(dir + 'roo_type_excel.xlsx'); }); | ||||
| 	}); | ||||
| 	it('should fail on ODS files', function() { | ||||
| 		assert.throws(function() { XLSX.readFile(dir + 'roo_type_openoffice.xlsx');}); | ||||
| 		assert.throws(function() { X.readFile(dir + 'roo_type_openoffice.xlsx');}); | ||||
| 	}); | ||||
| 	it('should fail on DOC files', function() { | ||||
| 		assert.throws(function() { XLSX.readFile(dir + 'word_doc.doc');}); | ||||
| 		assert.throws(function() { X.readFile(dir + 'word_doc.doc');}); | ||||
| 	}); | ||||
| }); | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| AutoFilter.xlsb | ||||
| BlankSheetTypes.xlsb | ||||
| NumberFormatCondition.xlsb | ||||
| RkNumber.xlsb | ||||
| comments_stress_test.xlsb | ||||
| custom_properties.xlsb | ||||
| @ -256,6 +257,7 @@ xlrd_text_bar.xlsx | ||||
| xlsx-stream-d-date-cell.xlsx | ||||
| חישוב_נקודות_זיכוי.xlsx | ||||
| BlankSheetTypes.xlsm | ||||
| NumberFormatCondition.xlsm | ||||
| apachepoi_45431.xlsm | ||||
| apachepoi_47026.xlsm | ||||
| apachepoi_47089.xlsm | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| Subproject commit a056111d30799597f1b92dc1197f04a1f86cad78 | ||||
| Subproject commit 59e556bf07effb3fe3b39f3291ca9f860f322208 | ||||
							
								
								
									
										152
									
								
								xlsx.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										152
									
								
								xlsx.js
									
									
									
									
									
								
							| @ -9,7 +9,7 @@ var _strrev = function(x) { return String(x).split("").reverse().join("");}; | ||||
| function fill(c,l) { return new Array(l+1).join(c); } | ||||
| function pad(v,d,c){var t=String(v);return t.length>=d?t:(fill(c||0,d-t.length)+t);} | ||||
| function rpad(v,d,c){var t=String(v);return t.length>=d?t:(t+fill(c||0,d-t.length));} | ||||
| SSF.version = '0.6.1'; | ||||
| SSF.version = '0.6.2'; | ||||
| /* Options */ | ||||
| var opts_fmt = {}; | ||||
| function fixopts(o){for(var y in opts_fmt) if(o[y]===undefined) o[y]=opts_fmt[y];} | ||||
| @ -124,7 +124,7 @@ var parse_date_code = function parse_date_code(v,opts) { | ||||
| 	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(out.u > .999) { | ||||
| 	if(out.u > 0.999) { | ||||
| 		out.u = 0; | ||||
| 		if(++time == 86400) { time = 0; ++date; } | ||||
| 	} | ||||
| @ -205,13 +205,13 @@ var write_date = function(type, fmt, val) { | ||||
| /*jshint +W086 */ | ||||
| var commaify = function(s) { return _strrev(_strrev(s).replace(/.../g,"$&,")).replace(/^,/,""); }; | ||||
| var write_num = function(type, fmt, val) { | ||||
| 	if(type === '(') { | ||||
| 	if(type === '(' && !fmt.match(/\).*[0#]/)) { | ||||
| 		var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,""); | ||||
| 		if(val >= 0) return write_num('n', ffmt, val); | ||||
| 		return '(' + write_num('n', ffmt, -val) + ')'; | ||||
| 	} | ||||
| 	var mul = 0, o; | ||||
| 	fmt = fmt.replace(/%/g,function(x) { mul++; return ""; }); | ||||
| 	fmt = fmt.replace(/%/g,function() { mul++; return ""; }); | ||||
| 	if(mul !== 0) return write_num(type, fmt, val * Math.pow(10,2*mul)) + fill("%",mul); | ||||
| 	fmt = fmt.replace(/(\.0+)(,+)$/g,function($$,$1,$2) { mul=$2.length; return $1; }); | ||||
| 	if(mul !== 0) return write_num(type, fmt, val / Math.pow(10,3*mul)); | ||||
| @ -264,6 +264,18 @@ var write_num = function(type, fmt, val) { | ||||
| 		return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(rr,r[1].length,0); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^#,#*,#0/))) return write_num(type,fmt.replace(/^#,#*,/,""),val); | ||||
| 	if((r = fmt.match(/^([0#]+)-([0#]+)$/))) { | ||||
| 		ff = write_num(type, fmt.replace(/-/,""), val); | ||||
| 		return ff.substr(0,ff.length - r[2].length) + "-" + ff.substr(ff.length-r[2].length); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^([0#]+)-([0#]+)-([0#]+)$/))) { | ||||
| 		ff = write_num(type, fmt.replace(/-/g,""), val); | ||||
| 		return ff.substr(0,ff.length - r[2].length - r[3].length) + "-" + ff.substr(ff.length-r[2].length - r[3].length, r[2].length) + "-" + ff.substr(ff.length-r[3].length); | ||||
| 	} | ||||
| 	if(fmt == "(###) ###-####") { | ||||
| 		ff = write_num(type, "##########", val); | ||||
| 		return "(" + ff.substr(0,3) + ") " + ff.substr(3, 3) + "-" + ff.substr(6); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^([?]+)([ ]?)\/([ ]?)([?]+)/))) { | ||||
| 		rr = Math.min(Math.max(r[1].length, r[4].length),7); | ||||
| 		ff = frac(aval, Math.pow(10,rr)-1, false); | ||||
| @ -388,12 +400,12 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 	switch(bt) { | ||||
| 		case 0: break; | ||||
| 		case 1: | ||||
| 			if(dt.u >= .5) { dt.u = 0; ++dt.S; } | ||||
| 			if(dt.u >= 0.5) { dt.u = 0; ++dt.S; } | ||||
| 			if(dt.S >= 60) { dt.S = 0; ++dt.M; } | ||||
| 			if(dt.M >= 60) { dt.M = 0; ++dt.H; } | ||||
| 			break; | ||||
| 		case 2: | ||||
| 			if(dt.u >= .5) { dt.u = 0; ++dt.S; } | ||||
| 			if(dt.u >= 0.5) { dt.u = 0; ++dt.S; } | ||||
| 			if(dt.S >= 60) { dt.S = 0; ++dt.M; } | ||||
| 			break; | ||||
| 	} | ||||
| @ -406,7 +418,7 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 				out[i].t = 't'; break; | ||||
| 			case 'n': case '(': case '?': | ||||
| 				var jj = i+1; | ||||
| 				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 == '/' || '$€'.indexOf(out[jj].v) > -1 || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) { | ||||
| 				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 == '(' && (")n ".indexOf(out[jj].t) > -1) || out[jj].t == 't' && (out[jj].v == '/' || '$€'.indexOf(out[jj].v) > -1 || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) { | ||||
| 					out[i].v += out[jj].v; | ||||
| 					delete out[jj]; ++jj; | ||||
| 				} | ||||
| @ -432,7 +444,27 @@ function choose_fmt(fmt, v, o) { | ||||
| 		default: throw "cannot find right format for |" + fmt + "|"; | ||||
| 	} | ||||
| 	if(typeof v !== "number") return [fmt.length, fmt[3]]; | ||||
| 	return [l, v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2]]; | ||||
| 	var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2]; | ||||
| 	if(fmt[0].match(/\[[=<>]/) || fmt[1].match(/\[[=<>]/)) { | ||||
| 		var chk = function(v, rr, out) { | ||||
| 			if(!rr) return null; | ||||
| 			var found = false; | ||||
| 			var thresh = Number(rr[2]); | ||||
| 			switch(rr[1]) { | ||||
| 				case "=":  if(v == thresh) found = true; break; | ||||
| 				case ">":  if(v >  thresh) found = true; break; | ||||
| 				case "<":  if(v <  thresh) found = true; break; | ||||
| 				case "<>": if(v != thresh) found = true; break; | ||||
| 				case ">=": if(v >= thresh) found = true; break; | ||||
| 				case "<=": if(v <= thresh) found = true; break; | ||||
| 			} | ||||
| 			return found ? out : null; | ||||
| 		}; | ||||
| 		var m1 = fmt[0].match(/\[([=<>]*)([-]?\d+)\]/); | ||||
| 		var m2 = fmt[1].match(/\[([=<>]*)([-]?\d+)\]/); | ||||
| 		return chk(v, m1, [l, fmt[0]]) || chk(v, m2, [l, fmt[1]]) || [l, fmt[m1&&m2?2:1]]; | ||||
| 	} | ||||
| 	return [l, ff]; | ||||
| } | ||||
| var format = function format(fmt,v,o) { | ||||
| 	fixopts(o = (o||{})); | ||||
| @ -455,7 +487,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.5.14'; | ||||
| XLSX.version = '0.5.15'; | ||||
| var current_codepage, current_cptable, cptable; | ||||
| if(typeof module !== "undefined" && typeof require !== 'undefined') { | ||||
| 	if(typeof cptable === 'undefined') cptable = require('codepage'); | ||||
| @ -774,7 +806,7 @@ function parse_BrtColor(data, length) { | ||||
| 	var d = read(1); | ||||
| 	out.fValidRGB = d & 1; | ||||
| 	out.xColorType = d >>> 1; | ||||
| 	out.index = read(1) | ||||
| 	out.index = read(1); | ||||
| 	out.nTintAndShade = read(2, 'i'); | ||||
| 	out.bRed   = read(1); | ||||
| 	out.bGreen = read(1); | ||||
| @ -946,7 +978,8 @@ var parse_BrtBeginSst = function(data, length) { | ||||
| /* [MS-XLSB] 2.1.7.45 Shared Strings */ | ||||
| var parse_sst_bin = function(data, opts) { | ||||
| 	var s = []; | ||||
| 	recordhopper(data, function(val, R) { | ||||
| 	var pass = false; | ||||
| 	recordhopper(data, function(val, R, RT) { | ||||
| 		switch(R.n) { | ||||
| 			case 'BrtBeginSst': s.Count = val[0]; s.Unique = val[1]; break; | ||||
| 			case 'BrtSSTItem': s.push(val); break; | ||||
| @ -1161,7 +1194,7 @@ var ct2type = { | ||||
| 	"application/vnd.ms-excel.sharedStrings": "strs", /*XLSB*/ | ||||
| 
 | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains", /*XLS[XM]*/ | ||||
| 	//"application/vnd.ms-excel.calcChain": "calcchains", /*XLSB*/
 | ||||
| 	"application/vnd.ms-excel.calcChain": "calcchains", /*XLSB*/ | ||||
| 
 | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": "comments", /*XLS[XM]*/ | ||||
| 	"application/vnd.ms-excel.comments": "comments", /*XLSB*/ | ||||
| @ -1254,23 +1287,6 @@ function parseCustomProps(data) { | ||||
| 	return p; | ||||
| } | ||||
| 
 | ||||
| /* 18.6 Calculation Chain */ | ||||
| function parseDeps(data) { | ||||
| 	var d = []; | ||||
| 	var l = 0, i = 1; | ||||
| 	(data.match(/<[^>]*>/g)||[]).forEach(function(x) { | ||||
| 		var y = parsexmltag(x); | ||||
| 		switch(y[0]) { | ||||
| 			case '<?xml': break; | ||||
| 			/* 18.6.2  calcChain CT_CalcChain 1 */ | ||||
| 			case '<calcChain': case '<calcChain>': case '</calcChain>': break; | ||||
| 			/* 18.6.1  c CT_CalcCell 1 */ | ||||
| 			case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break; | ||||
| 		} | ||||
| 	}); | ||||
| 	return d; | ||||
| } | ||||
| 
 | ||||
| var ctext = {}; | ||||
| function parseCT(data) { | ||||
| 	if(!data || !data.match) return data; | ||||
| @ -1335,6 +1351,51 @@ function parseRels(data, currentFilePath) { | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* 18.6 Calculation Chain */ | ||||
| function parse_cc_xml(data, opts) { | ||||
| 	var d = []; | ||||
| 	var l = 0, i = 1; | ||||
| 	(data.match(/<[^>]*>/g)||[]).forEach(function(x) { | ||||
| 		var y = parsexmltag(x); | ||||
| 		switch(y[0]) { | ||||
| 			case '<?xml': break; | ||||
| 			/* 18.6.2  calcChain CT_CalcChain 1 */ | ||||
| 			case '<calcChain': case '<calcChain>': case '</calcChain>': break; | ||||
| 			/* 18.6.1  c CT_CalcCell 1 */ | ||||
| 			case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break; | ||||
| 		} | ||||
| 	}); | ||||
| 	return d; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.6.4.1 */ | ||||
| var parse_BrtCalcChainItem$ = function(data, length) { | ||||
| 	var out = {}; | ||||
| 	out.i = data.read_shift(4); | ||||
| 	var cell = {}; | ||||
| 	cell.r = data.read_shift(4); | ||||
| 	cell.c = data.read_shift(4); | ||||
| 	out.r = encode_cell(cell); | ||||
| 	var flags = data.read_shift(1); | ||||
| 	if(flags & 0x2) out.l = '1'; | ||||
| 	if(flags & 0x8) out.a = '1'; | ||||
| 	return out; | ||||
| }; | ||||
| 
 | ||||
| /* 18.6 Calculation Chain */ | ||||
| function parse_cc_bin(data, opts) { | ||||
| 	var out = []; | ||||
| 	var pass = false; | ||||
| 	recordhopper(data, function(val, R, RT) { | ||||
| 		switch(R.n) { | ||||
| 			case 'BrtCalcChainItem$': out.push(val); break; | ||||
| 			case 'BrtBeginCalcChain$': break; | ||||
| 			case 'BrtEndCalcChain$': break; | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n); | ||||
| 		} | ||||
| 	}); | ||||
| 	return out; | ||||
| } | ||||
| /* 18.7.3 CT_Comment */ | ||||
| function parse_comments_xml(data, opts) { | ||||
| 	if(data.match(/<comments *\/>/)) return []; | ||||
| @ -1429,7 +1490,7 @@ function insertCommentsIntoSheet(sheetName, sheet, comments) { | ||||
| 		if (!cell) { | ||||
| 			cell = {}; | ||||
| 			sheet[comment.ref] = cell; | ||||
| 			var range = decode_range(sheet["!ref"]); | ||||
| 			var range = decode_range(sheet["!ref"]||"BDWGO1000001:A1"); | ||||
| 			var thisCell = decode_cell(comment.ref); | ||||
| 			if(range.s.r > thisCell.r) range.s.r = thisCell.r; | ||||
| 			if(range.e.r < thisCell.r) range.e.r = thisCell.r; | ||||
| @ -1544,8 +1605,8 @@ function parse_ws_xml(data, opts) { | ||||
| 			s[cell.r] = p; | ||||
| 		}); | ||||
| 	}); | ||||
| 	if(!s["!ref"]) s["!ref"] = encode_range(refguess); | ||||
| 	if(opts.sheetRows) { | ||||
| 	if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess); | ||||
| 	if(opts.sheetRows && s["!ref"]) { | ||||
| 		var tmpref = decode_range(s["!ref"]); | ||||
| 		if(opts.sheetRows < +tmpref.e.r) { | ||||
| 			tmpref.e.r = opts.sheetRows - 1; | ||||
| @ -1583,7 +1644,10 @@ var parse_BrtWsProp = function(data, length) { | ||||
| }; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.303 BrtCellBlank */ | ||||
| var parse_BrtCellBlank = parsenoop; | ||||
| var parse_BrtCellBlank = function(data, length) { | ||||
| 	var cell = parse_Cell(data); | ||||
| 	return [cell]; | ||||
| }; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.304 BrtCellBool */ | ||||
| var parse_BrtCellBool = function(data, length) { | ||||
| @ -1733,7 +1797,14 @@ var parse_ws_bin = function(data, opts) { | ||||
| 				if(refguess.e.c < val[0].c) refguess.e.c = val[0].c; | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'BrtCellBlank': break; // (blank cell)
 | ||||
| 			case 'BrtCellBlank': if(!opts.sheetStubs) break; | ||||
| 				p = {t:'str',v:undefined}; | ||||
| 				s[encode_cell({c:val[0].c,r:row.r})] = p; | ||||
| 				if(refguess.s.r > row.r) refguess.s.r = row.r; | ||||
| 				if(refguess.s.c > val[0].c) refguess.s.c = val[0].c; | ||||
| 				if(refguess.e.r < row.r) refguess.e.r = row.r; | ||||
| 				if(refguess.e.c < val[0].c) refguess.e.c = val[0].c; | ||||
| 				break; | ||||
| 
 | ||||
| 			/* Merge Cells */ | ||||
| 			case 'BrtBeginMergeCells': break; | ||||
| @ -1844,8 +1915,8 @@ var parse_ws_bin = function(data, opts) { | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + R.n); | ||||
| 		} | ||||
| 	}, opts); | ||||
| 	s["!ref"] = encode_range(ref); | ||||
| 	if(opts.sheetRows) { | ||||
| 	if(!s["!ref"] && ref) s["!ref"] = encode_range(ref); | ||||
| 	if(opts.sheetRows && s["!ref"]) { | ||||
| 		var tmpref = decode_range(s["!ref"]); | ||||
| 		if(opts.sheetRows < +tmpref.e.r) { | ||||
| 			tmpref.e.r = opts.sheetRows - 1; | ||||
| @ -2151,6 +2222,10 @@ function parse_sst(data, name, opts) { | ||||
| function parse_cmnt(data, name, opts) { | ||||
| 	return name.substr(-4)===".bin" ? parse_comments_bin(data, opts) : parse_comments_xml(data, opts); | ||||
| } | ||||
| 
 | ||||
| function parse_cc(data, name, opts) { | ||||
| 	return name.substr(-4)===".bin" ? parse_cc_bin(data, opts) : parse_cc_xml(data, opts); | ||||
| } | ||||
| /* [MS-XLSB] 2.3 Record Enumeration */ | ||||
| var RecordEnum = { | ||||
| 	0x0000: { n:"BrtRowHdr", f:parse_BrtRowHdr }, | ||||
| @ -2207,6 +2282,7 @@ var RecordEnum = { | ||||
| 	0x003B: { n:"BrtStr", f:parsenoop }, | ||||
| 	0x003C: { n:"BrtColInfo", f:parsenoop }, | ||||
| 	0x003E: { n:"BrtCellRString", f:parsenoop }, | ||||
| 	0x003F: { n:"BrtCalcChainItem$", f:parse_BrtCalcChainItem$ }, | ||||
| 	0x0040: { n:"BrtDVal", f:parsenoop }, | ||||
| 	0x0041: { n:"BrtSxvcellNum", f:parsenoop }, | ||||
| 	0x0042: { n:"BrtSxvcellStr", f:parsenoop }, | ||||
| @ -2609,6 +2685,8 @@ var RecordEnum = { | ||||
| 	0x020D: { n:"BrtVolErr", f:parsenoop }, | ||||
| 	0x020E: { n:"BrtVolStr", f:parsenoop }, | ||||
| 	0x020F: { n:"BrtVolBool", f:parsenoop }, | ||||
| 	0x0210: { n:"BrtBeginCalcChain$", f:parsenoop }, | ||||
| 	0x0211: { n:"BrtEndCalcChain$", f:parsenoop }, | ||||
| 	0x0212: { n:"BrtBeginSortState", f:parsenoop }, | ||||
| 	0x0213: { n:"BrtEndSortState", f:parsenoop }, | ||||
| 	0x0214: { n:"BrtBeginSortCond", f:parsenoop }, | ||||
| @ -3043,7 +3121,7 @@ function parseZip(zip, opts) { | ||||
| 	sheets = {}; | ||||
| 
 | ||||
| 	var deps = {}; | ||||
| 	if(opts.bookDeps && dir.calcchain) deps=parseDeps(getzipdata(zip, dir.calcchain.replace(/^\//,''))); | ||||
| 	if(opts.bookDeps && dir.calcchain) deps=parse_cc(getzipdata(zip, dir.calcchain.replace(/^\//,'')),dir.calcchain,opts); | ||||
| 
 | ||||
| 	var i=0; | ||||
| 	var sheetRels = {}; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user