forked from sheetjs/sheetjs
		
	version bump 0.5.14: XLSB comments
- SSF updated to 0.6.1 (h/t @notatestuser) - more tests and related XLSB records - XLSB plaintext comment and author - preliminary work for XLSB formats
This commit is contained in:
		
							parent
							
								
									37cc0006f2
								
							
						
					
					
						commit
						d462e18846
					
				| @ -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.5.9'; | ||||
| SSF.version = '0.6.1'; | ||||
| /* Options */ | ||||
| var opts_fmt = {}; | ||||
| function fixopts(o){for(var y in opts_fmt) if(o[y]===undefined) o[y]=opts_fmt[y];} | ||||
| @ -121,6 +121,10 @@ 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) { | ||||
| 		out.u = 0; | ||||
| 		if(++time == 86400) { time = 0; ++date; } | ||||
| 	} | ||||
| 	if(date === 60) {dout = [1900,2,29]; dow=3;} | ||||
| 	else if(date === 0) {dout = [1900,1,0]; dow=6;} | ||||
| 	else { | ||||
| @ -143,7 +147,7 @@ SSF.parse_date_code = parse_date_code; | ||||
| /*jshint -W086 */ | ||||
| var write_date = function(type, fmt, val) { | ||||
| 	if(val < 0) return ""; | ||||
| 	var o; | ||||
| 	var o, ss; | ||||
| 	switch(type) { | ||||
| 		case 'y': switch(fmt) { /* year */ | ||||
| 			case 'y': case 'yy': return pad(val.y % 100,2); | ||||
| @ -178,11 +182,11 @@ var write_date = function(type, fmt, val) { | ||||
| 			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': ss=Math.round(val.S+val.u); return ss >= 60 ? 0 : ss; | ||||
| 			case 'ss': ss=Math.round(val.S+val.u); if(ss>=60) ss=0; return pad(ss,2); | ||||
| 			case 'ss.0': ss=Math.round(10*(val.S+val.u)); if(ss>=600) ss = 0; o = pad(ss,3); return o.substr(0,2)+"." + o.substr(2); | ||||
| 			case 'ss.00': ss=Math.round(100*(val.S+val.u)); if(ss>=6000) ss = 0; o = pad(ss,4); return o.substr(0,2)+"." + o.substr(2); | ||||
| 			case 'ss.000': ss=Math.round(1000*(val.S+val.u)); if(ss>=60000) ss = 0; o = pad(ss,5); return o.substr(0,2)+"." + o.substr(2); | ||||
| 			default: throw 'bad second format: ' + fmt; | ||||
| 		} | ||||
| 		case 'Z': switch(fmt) { | ||||
| @ -206,6 +210,8 @@ var write_num = function(type, fmt, val) { | ||||
| 	var mul = 0, o; | ||||
| 	fmt = fmt.replace(/%/g,function(x) { 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)); | ||||
| 	if(fmt.indexOf("E") > -1) { | ||||
| 		var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1; | ||||
| 		if(fmt.match(/^#+0.0E\+0$/)) { | ||||
| @ -239,11 +245,12 @@ var write_num = function(type, fmt, val) { | ||||
| 	if(fmt.match(/^#+0+$/)) fmt = fmt.replace(/#/g,""); | ||||
| 	if(fmt.match(/^00+$/)) return (val<0?"-":"")+pad(Math.round(aval),fmt.length); | ||||
| 	if(fmt.match(/^[#?]+$/)) return String(Math.round(val)).replace(/^0$/,""); | ||||
| 	if((r = fmt.match(/^#*0+\.(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); }); | ||||
| 		rr = String(o/Math.pow(10,r[1].length)).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.([0-9]*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); }); | ||||
| 		return fmt.match(/0\./) ? rr : rr.replace(/^0\./,"."); | ||||
| 	} | ||||
| 	fmt = fmt.replace(/^#+0/, "0"); | ||||
| 	fmt = fmt.replace(/^#+([0.])/, "$1"); | ||||
| 	if((r = fmt.match(/^(0*)\.(#*)$/))) { | ||||
| 		o = Math.round(aval*Math.pow(10,r[2].length)); | ||||
| 		return sign + String(o / Math.pow(10,r[2].length)).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^([-]?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":"."); | ||||
| @ -253,15 +260,23 @@ var write_num = function(type, fmt, val) { | ||||
| 		rr = Math.round((val-Math.floor(val))*Math.pow(10,r[1].length)); | ||||
| 		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(/^([?]+)([ ]?)\/([ ]?)([?]+)/))) { | ||||
| 		rr = Math.min(Math.max(r[1].length, r[4].length),7); | ||||
| 		ff = frac(aval, Math.pow(10,rr)-1, false); | ||||
| 		return sign + (ff[0]||(ff[1] ? "" : "0")) + (ff[1] ? pad(ff[1],rr," ") + r[2] + "/" + r[3] + rpad(ff[2],rr," "): fill(" ", 2*rr+1 + r[2].length + r[3].length)); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^# ([?]+)([ ]?)\/([ ]?)([?]+)/))) { | ||||
| 		rr = Math.min(Math.max(r[1].length, r[4].length),7); | ||||
| 		ff = frac(aval, Math.pow(10,rr)-1, true); | ||||
| 		return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],rr," ") + r[2] + "/" + r[3] + rpad(ff[2],rr," "): fill(" ", 2*rr+1 + r[2].length + r[3].length)); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^00,000\.([#0]*0)$/))) { | ||||
| 		rr = val == Math.floor(val) ? 0 : Math.round((val-Math.floor(val))*Math.pow(10,r[1].length)); | ||||
| 		return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad(0,3-$$.length) : "") + $$; }) + "." + pad(rr,r[1].length,0); | ||||
| 	} | ||||
| 	switch(fmt) { | ||||
| 		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 : ""; | ||||
| 		default: | ||||
| 	} | ||||
| @ -306,7 +321,7 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 			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': | ||||
| 			case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g': | ||||
| 				if(v < 0) return ""; | ||||
| 				if(!dt) dt = parse_date_code(v, opts); | ||||
| 				if(!dt) return ""; | ||||
| @ -341,7 +356,7 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 			case '?': | ||||
| 				o = fmt[i]; while(fmt[++i] === c) o+=c; | ||||
| 				q={t:c, v:o}; out.push(q); lst = c; break; | ||||
| 			case '*': ++i; if(fmt[i] == ' ') ++i; break; // **
 | ||||
| 			case '*': ++i; if(fmt[i] == ' ' || fmt[i] == '*') ++i; break; // **
 | ||||
| 			case '(': case ')': out.push({t:(flen===1?'t':c),v:c}); ++i; break; | ||||
| 			case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': | ||||
| 				o = fmt[i]; while("0123456789".indexOf(fmt[++i]) > -1) o+=fmt[i]; | ||||
| @ -353,22 +368,38 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 				out.push({t:'t', v:c}); ++i; break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* walk backwards */ | ||||
| 	var bt = 0; | ||||
| 	for(i=out.length-1, lst='t'; i >= 0; --i) { | ||||
| 		switch(out[i].t) { | ||||
| 			case 'h': case 'H': out[i].t = hr; lst='h'; break; | ||||
| 			case 'd': case 'y': case 's': case 'M': case 'e': lst=out[i].t; break; | ||||
| 			case 'm': if(lst === 's') out[i].t = 'M'; break; | ||||
| 			case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break; | ||||
| 			case 's': if(bt < 3) bt = 3; | ||||
| 			/* falls through */ | ||||
| 			case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break; | ||||
| 			case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break; | ||||
| 			case 'Z': | ||||
| 				if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1; | ||||
| 				if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2; | ||||
| 				if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	switch(bt) { | ||||
| 		case 0: break; | ||||
| 		case 1: | ||||
| 			if(dt.u >= .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.S >= 60) { dt.S = 0; ++dt.M; } | ||||
| 			break; | ||||
| 	} | ||||
| 	/* replace fields */ | ||||
| 	for(i=0; i < out.length; ++i) { | ||||
| 		switch(out[i].t) { | ||||
| 			case 't': case 'T': case ' ': case 'D': break; | ||||
| 			case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'Z': | ||||
| 				out[i].v = write_date(out[i].t, out[i].v, dt); | ||||
| 				out[i].v = write_date(out[i].t, out[i].v, dt, bt); | ||||
| 				out[i].t = 't'; break; | ||||
| 			case 'n': case '(': case '?': | ||||
| 				var jj = i+1; | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| XLSX.version = '0.5.13'; | ||||
| XLSX.version = '0.5.14'; | ||||
|  | ||||
| @ -20,6 +20,7 @@ var parse_RichStr = function(data, length) { | ||||
| 		/* TODO: formatted string */ | ||||
| 		var dwSizeStrRun = data.read_shift(4); | ||||
| 		for(var i = 0; i != dwSizeStrRun; ++i) rgsStrRun.push(parse_StrRun(data)); | ||||
| 		z.r = JSON.stringify(rgsStrRun); | ||||
| 	} | ||||
| 	if(fExtStr) { | ||||
| 		/* TODO: phonetic string */ | ||||
| @ -92,3 +93,32 @@ var BErr = { | ||||
| }; | ||||
| var RBErr = evert(BErr); | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.321 BrtColor */ | ||||
| function parse_BrtColor(data, length) { | ||||
| 	var read = data.read_shift.bind(data); | ||||
| 	var out = {}; | ||||
| 	var d = read(1); | ||||
| 	out.fValidRGB = d & 1; | ||||
| 	out.xColorType = d >>> 1; | ||||
| 	out.index = read(1) | ||||
| 	out.nTintAndShade = read(2, 'i'); | ||||
| 	out.bRed   = read(1); | ||||
| 	out.bGreen = read(1); | ||||
| 	out.bBlue  = read(1); | ||||
| 	out.bAlpha = read(1); | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB 2.5.52 */ | ||||
| function parse_FontFlags(data, length) { | ||||
| 	var d = data.read_shift(1); | ||||
| 	data.l++; | ||||
| 	var out = { | ||||
| 		fItalic: d & 0x2, | ||||
| 		fStrikeout: d & 0x8, | ||||
| 		fOutline: d & 0x10, | ||||
| 		fShadow: d & 0x20, | ||||
| 		fCondense: d & 0x40, | ||||
| 		fExtend: d & 0x80, | ||||
| 	}; | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| @ -5,6 +5,34 @@ function parse_BrtFmt(data, length) { | ||||
| 	return [ifmt, stFmtCode]; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.653 BrtFont TODO */ | ||||
| function parse_BrtFont(data, length) { | ||||
| 	var read = data.read_shift.bind(data); | ||||
| 	var out = {flags:{}}; | ||||
| 	out.dyHeight = read(2); | ||||
| 	out.grbit = parse_FontFlags(data, 2); | ||||
| 	out.bls = read(2); | ||||
| 	out.sss = read(2); | ||||
| 	out.uls = read(1); | ||||
| 	out.bFamily = read(1); | ||||
| 	out.bCharSet = read(1); | ||||
| 	data.l++; | ||||
| 	out.brtColor = parse_BrtColor(data, 8); | ||||
| 	out.bFontScheme = read(1); | ||||
| 	out.name = parse_XLWideString(data, length - 21); | ||||
| 
 | ||||
| 	out.flags.Bold = out.bls === 0x02BC; | ||||
| 	out.flags.Italic = out.grbit.fItalic; | ||||
| 	out.flags.Strikeout = out.grbit.fStrikeout; | ||||
| 	out.flags.Outline = out.grbit.fOutline; | ||||
| 	out.flags.Shadow = out.grbit.fShadow; | ||||
| 	out.flags.Condense = out.grbit.fCondense; | ||||
| 	out.flags.Extend = out.grbit.fExtend; | ||||
| 	out.flags.Sub = out.sss & 0x2; | ||||
| 	out.flags.Sup = out.sss & 0x1; | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.816 BrtXF */ | ||||
| function parse_BrtXF(data, length) { | ||||
| 	var ixfeParent = data.read_shift(2); | ||||
|  | ||||
| @ -16,11 +16,13 @@ var ct2type = { | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains", /*XLS[XM]*/ | ||||
| 	//"application/vnd.ms-excel.calcChain": "calcchains", /*XLSB*/
 | ||||
| 
 | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": "comments", /*XLS[XM]*/ | ||||
| 	"application/vnd.ms-excel.comments": "comments", /*XLSB*/ | ||||
| 
 | ||||
| 	"application/vnd.openxmlformats-package.core-properties+xml": "coreprops", | ||||
| 	"application/vnd.openxmlformats-officedocument.extended-properties+xml": "extprops", | ||||
| 	"application/vnd.openxmlformats-officedocument.custom-properties+xml": "custprops", | ||||
| 	"application/vnd.openxmlformats-officedocument.theme+xml":"themes", | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": "comments", | ||||
| 	"foo": "bar" | ||||
| }; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										25
									
								
								bits/63_cmntxml.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										25
									
								
								bits/63_cmntxml.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| /* 18.7.3 CT_Comment */ | ||||
| function parse_comments_xml(data, opts) { | ||||
| 	if(data.match(/<comments *\/>/)) return []; | ||||
| 	var authors = []; | ||||
| 	var commentList = []; | ||||
| 	data.match(/<authors>([^\u2603]*)<\/authors>/m)[1].split('</author>').forEach(function(x) { | ||||
| 		if(x === "" || x.trim() === "") return; | ||||
| 		authors.push(x.match(/<author[^>]*>(.*)/)[1]); | ||||
| 	}); | ||||
| 	data.match(/<commentList>([^\u2603]*)<\/commentList>/m)[1].split('</comment>').forEach(function(x, index) { | ||||
| 		if(x === "" || x.trim() === "") return; | ||||
| 		var y = parsexmltag(x.match(/<comment[^>]*>/)[0]); | ||||
| 		var comment = { author: y.authorId && authors[y.authorId] ? authors[y.authorId] : undefined, ref: y.ref, guid: y.guid }; | ||||
| 		var cell = decode_cell(y.ref); | ||||
| 		if(opts.sheetRows && opts.sheetRows <= cell.r) return; | ||||
| 		var textMatch = x.match(/<text>([^\u2603]*)<\/text>/m); | ||||
| 		if (!textMatch || !textMatch[1]) return; // a comment may contain an empty text tag.
 | ||||
| 		var rt = parse_si(textMatch[1]); | ||||
| 		comment.r = rt.r; | ||||
| 		comment.t = rt.t; | ||||
| 		if(opts.cellHTML) comment.h = rt.h; | ||||
| 		commentList.push(comment); | ||||
| 	}); | ||||
| 	return commentList; | ||||
| } | ||||
							
								
								
									
										44
									
								
								bits/64_cmntbin.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										44
									
								
								bits/64_cmntbin.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | ||||
| /* [MS-XLSB] 2.4.28 BrtBeginComment */ | ||||
| var parse_BrtBeginComment = function(data, length) { | ||||
| 	var out = {}; | ||||
| 	out.iauthor = data.read_shift(4); | ||||
| 	var rfx = parse_UncheckedRfX(data, 16); | ||||
| 	out.rfx = rfx.s; | ||||
| 	out.ref = encode_cell(rfx.s); | ||||
| 	data.l += 16; /*var guid = parse_GUID(data); */ | ||||
| 	return out; | ||||
| }; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.324 BrtCommentAuthor */ | ||||
| var parse_BrtCommentAuthor = parse_XLWideString; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.325 BrtCommentText */ | ||||
| var parse_BrtCommentText = parse_RichStr; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.8 Comments */ | ||||
| function parse_comments_bin(data, opts) { | ||||
| 	var out = []; | ||||
| 	var authors = []; | ||||
| 	var c = {}; | ||||
| 	var pass = false; | ||||
| 	recordhopper(data, function(val, R, RT) { | ||||
| 		switch(R.n) { | ||||
| 			case 'BrtCommentAuthor': authors.push(val); break; | ||||
| 			case 'BrtBeginComment': c = val; break; | ||||
| 			case 'BrtCommentText': c.t = val.t; c.h = val.h; c.r = val.r; break; | ||||
| 			case 'BrtEndComment': | ||||
| 				c.author = authors[c.iauthor]; | ||||
| 				delete c.iauthor; | ||||
| 				if(opts.sheetRows && opts.sheetRows <= c.rfx.r) break; | ||||
| 				delete c.rfx; out.push(c); break; | ||||
| 			case 'BrtBeginComments': break; | ||||
| 			case 'BrtEndComments': break; | ||||
| 			case 'BrtBeginCommentAuthors': break; | ||||
| 			case 'BrtEndCommentAuthors': break; | ||||
| 			case 'BrtBeginCommentList': break; | ||||
| 			case 'BrtEndCommentList': break; | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n); | ||||
| 		} | ||||
| 	}); | ||||
| 	return out; | ||||
| } | ||||
| @ -1,33 +1,8 @@ | ||||
| /* 18.7.3 CT_Comment */ | ||||
| function parse_comments_xml(data, opts) { | ||||
| 	if(data.match(/<comments *\/>/)) return []; | ||||
| 	var authors = []; | ||||
| 	var commentList = []; | ||||
| 	data.match(/<authors>([^\u2603]*)<\/authors>/m)[1].split('</author>').forEach(function(x) { | ||||
| 		if(x === "" || x.trim() === "") return; | ||||
| 		authors.push(x.match(/<author[^>]*>(.*)/)[1]); | ||||
| 	}); | ||||
| 	data.match(/<commentList>([^\u2603]*)<\/commentList>/m)[1].split('</comment>').forEach(function(x, index) { | ||||
| 		if(x === "" || x.trim() === "") return; | ||||
| 		var y = parsexmltag(x.match(/<comment[^>]*>/)[0]); | ||||
| 		var comment = { author: y.authorId && authors[y.authorId] ? authors[y.authorId] : undefined, ref: y.ref, guid: y.guid }; | ||||
| 		var cell = decode_cell(y.ref); | ||||
| 		if(opts.sheetRows && opts.sheetRows <= cell.r) return; | ||||
| 		var textMatch = x.match(/<text>([^\u2603]*)<\/text>/m); | ||||
| 		if (!textMatch || !textMatch[1]) return; // a comment may contain an empty text tag.
 | ||||
| 		var rt = parse_si(textMatch[1]); | ||||
| 		comment.r = rt.r; | ||||
| 		comment.t = rt.t; | ||||
| 		if(opts.cellHTML) comment.h = rt.h; | ||||
| 		commentList.push(comment); | ||||
| 	}); | ||||
| 	return commentList; | ||||
| } | ||||
| 
 | ||||
| function parse_comments(zip, dirComments, sheets, sheetRels, opts) { | ||||
| 	for(var i = 0; i != dirComments.length; ++i) { | ||||
| 		var canonicalpath=dirComments[i]; | ||||
| 		var comments=parse_comments_xml(getzipdata(zip, canonicalpath.replace(/^\//,''), true), opts); | ||||
| 		var comments=parse_cmnt(getzipdata(zip, canonicalpath.replace(/^\//,''), true), canonicalpath, opts); | ||||
| 		if(!comments || !comments.length) continue; | ||||
| 		// find the sheets targeted by these comments
 | ||||
| 		var sheetNames = Object.keys(sheets); | ||||
|  | ||||
| @ -208,6 +208,7 @@ var parse_ws_bin = function(data, opts) { | ||||
| 			case 'BrtHLink': break; // TODO
 | ||||
| 			case 'BrtDrawing': break; // TODO
 | ||||
| 			case 'BrtLegacyDrawing': break; // TODO
 | ||||
| 			case 'BrtLegacyDrawingHF': break; // TODO
 | ||||
| 			case 'BrtPhoneticInfo': break; // TODO
 | ||||
| 			case 'BrtBeginHeaderFooter': break; // TODO
 | ||||
| 			case 'BrtEndHeaderFooter': break; // TODO
 | ||||
| @ -239,6 +240,11 @@ var parse_ws_bin = function(data, opts) { | ||||
| 			case 'BrtDVal': break; // TODO
 | ||||
| 			case 'BrtEndDVals': break; // TODO
 | ||||
| 			case 'BrtRangeProtection': break; // TODO
 | ||||
| 			case 'BrtBeginDCon': break; // TODO
 | ||||
| 			case 'BrtEndDCon': break; // TODO
 | ||||
| 			case 'BrtBeginDRefs': break; | ||||
| 			case 'BrtDRef': break; | ||||
| 			case 'BrtEndDRefs': break; | ||||
| 
 | ||||
| 			/* ActiveX */ | ||||
| 			case 'BrtBeginActiveXControls': break; | ||||
| @ -259,6 +265,19 @@ var parse_ws_bin = function(data, opts) { | ||||
| 			case 'BrtCustomFilter': break; | ||||
| 			case 'BrtEndCustomFilters': break; | ||||
| 
 | ||||
| 			/* Cell Watch */ | ||||
| 			case 'BrtBeginCellWatches': break; | ||||
| 			case 'BrtCellWatch': break; | ||||
| 			case 'BrtEndCellWatches': break; | ||||
| 
 | ||||
| 			/* Table */ | ||||
| 			case 'BrtTable': break; | ||||
| 
 | ||||
| 			/* Ignore Cell Errors */ | ||||
| 			case 'BrtBeginCellIgnoreECs': break; | ||||
| 			case 'BrtCellIgnoreEC': break; | ||||
| 			case 'BrtEndCellIgnoreECs': break; | ||||
| 
 | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + R.n); | ||||
| 		} | ||||
| 	}, opts); | ||||
|  | ||||
| @ -46,6 +46,7 @@ var parse_wb_bin = function(data, opts) { | ||||
| 			case 'BrtEndPivotCacheIDs': break; | ||||
| 			case 'BrtWebOpt': break; | ||||
| 			case 'BrtFileRecover': break; | ||||
| 			case 'BrtFileSharing': break; | ||||
| 			/*case 'BrtBeginWebPubItems': break; | ||||
| 			case 'BrtBeginWebPubItem': break; | ||||
| 			case 'BrtEndWebPubItem': break; | ||||
|  | ||||
| @ -13,3 +13,7 @@ function parse_sty(data, name, opts) { | ||||
| function parse_sst(data, name, opts) { | ||||
| 	return name.substr(-4)===".bin" ? parse_sst_bin(data, opts) : parse_sst_xml(data, opts); | ||||
| } | ||||
| 
 | ||||
| function parse_cmnt(data, name, opts) { | ||||
| 	return name.substr(-4)===".bin" ? parse_comments_bin(data, opts) : parse_comments_xml(data, opts); | ||||
| } | ||||
|  | ||||
| @ -35,7 +35,7 @@ var RecordEnum = { | ||||
| 	0x0027: { n:"BrtName", f:parsenoop }, | ||||
| 	0x0028: { n:"BrtIndexRowBlock", f:parsenoop }, | ||||
| 	0x002A: { n:"BrtIndexBlock", f:parsenoop }, | ||||
| 	0x002B: { n:"BrtFont", f:parsenoop }, | ||||
| 	0x002B: { n:"BrtFont", f:parse_BrtFont }, | ||||
| 	0x002C: { n:"BrtFmt", f:parse_BrtFmt }, | ||||
| 	0x002D: { n:"BrtFill", f:parsenoop }, | ||||
| 	0x002E: { n:"BrtBorder", f:parsenoop }, | ||||
| @ -543,12 +543,12 @@ var RecordEnum = { | ||||
| 	0x0275: { n:"BrtEndComments", f:parsenoop }, | ||||
| 	0x0276: { n:"BrtBeginCommentAuthors", f:parsenoop }, | ||||
| 	0x0277: { n:"BrtEndCommentAuthors", f:parsenoop }, | ||||
| 	0x0278: { n:"BrtCommentAuthor", f:parsenoop }, | ||||
| 	0x0278: { n:"BrtCommentAuthor", f:parse_BrtCommentAuthor }, | ||||
| 	0x0279: { n:"BrtBeginCommentList", f:parsenoop }, | ||||
| 	0x027A: { n:"BrtEndCommentList", f:parsenoop }, | ||||
| 	0x027B: { n:"BrtBeginComment", f:parsenoop }, | ||||
| 	0x027B: { n:"BrtBeginComment", f:parse_BrtBeginComment}, | ||||
| 	0x027C: { n:"BrtEndComment", f:parsenoop }, | ||||
| 	0x027D: { n:"BrtCommentText", f:parsenoop }, | ||||
| 	0x027D: { n:"BrtCommentText", f:parse_BrtCommentText }, | ||||
| 	0x027E: { n:"BrtBeginOleObjects", f:parsenoop }, | ||||
| 	0x027F: { n:"BrtOleObject", f:parsenoop }, | ||||
| 	0x0280: { n:"BrtEndOleObjects", f:parsenoop }, | ||||
|  | ||||
							
								
								
									
										215
									
								
								dist/xlsx.js
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										215
									
								
								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.5.9'; | ||||
| SSF.version = '0.6.1'; | ||||
| /* Options */ | ||||
| var opts_fmt = {}; | ||||
| function fixopts(o){for(var y in opts_fmt) if(o[y]===undefined) o[y]=opts_fmt[y];} | ||||
| @ -124,6 +124,10 @@ 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) { | ||||
| 		out.u = 0; | ||||
| 		if(++time == 86400) { time = 0; ++date; } | ||||
| 	} | ||||
| 	if(date === 60) {dout = [1900,2,29]; dow=3;} | ||||
| 	else if(date === 0) {dout = [1900,1,0]; dow=6;} | ||||
| 	else { | ||||
| @ -146,7 +150,7 @@ SSF.parse_date_code = parse_date_code; | ||||
| /*jshint -W086 */ | ||||
| var write_date = function(type, fmt, val) { | ||||
| 	if(val < 0) return ""; | ||||
| 	var o; | ||||
| 	var o, ss; | ||||
| 	switch(type) { | ||||
| 		case 'y': switch(fmt) { /* year */ | ||||
| 			case 'y': case 'yy': return pad(val.y % 100,2); | ||||
| @ -181,11 +185,11 @@ var write_date = function(type, fmt, val) { | ||||
| 			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': ss=Math.round(val.S+val.u); return ss >= 60 ? 0 : ss; | ||||
| 			case 'ss': ss=Math.round(val.S+val.u); if(ss>=60) ss=0; return pad(ss,2); | ||||
| 			case 'ss.0': ss=Math.round(10*(val.S+val.u)); if(ss>=600) ss = 0; o = pad(ss,3); return o.substr(0,2)+"." + o.substr(2); | ||||
| 			case 'ss.00': ss=Math.round(100*(val.S+val.u)); if(ss>=6000) ss = 0; o = pad(ss,4); return o.substr(0,2)+"." + o.substr(2); | ||||
| 			case 'ss.000': ss=Math.round(1000*(val.S+val.u)); if(ss>=60000) ss = 0; o = pad(ss,5); return o.substr(0,2)+"." + o.substr(2); | ||||
| 			default: throw 'bad second format: ' + fmt; | ||||
| 		} | ||||
| 		case 'Z': switch(fmt) { | ||||
| @ -209,6 +213,8 @@ var write_num = function(type, fmt, val) { | ||||
| 	var mul = 0, o; | ||||
| 	fmt = fmt.replace(/%/g,function(x) { 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)); | ||||
| 	if(fmt.indexOf("E") > -1) { | ||||
| 		var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1; | ||||
| 		if(fmt.match(/^#+0.0E\+0$/)) { | ||||
| @ -242,11 +248,12 @@ var write_num = function(type, fmt, val) { | ||||
| 	if(fmt.match(/^#+0+$/)) fmt = fmt.replace(/#/g,""); | ||||
| 	if(fmt.match(/^00+$/)) return (val<0?"-":"")+pad(Math.round(aval),fmt.length); | ||||
| 	if(fmt.match(/^[#?]+$/)) return String(Math.round(val)).replace(/^0$/,""); | ||||
| 	if((r = fmt.match(/^#*0+\.(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); }); | ||||
| 		rr = String(o/Math.pow(10,r[1].length)).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.([0-9]*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); }); | ||||
| 		return fmt.match(/0\./) ? rr : rr.replace(/^0\./,"."); | ||||
| 	} | ||||
| 	fmt = fmt.replace(/^#+0/, "0"); | ||||
| 	fmt = fmt.replace(/^#+([0.])/, "$1"); | ||||
| 	if((r = fmt.match(/^(0*)\.(#*)$/))) { | ||||
| 		o = Math.round(aval*Math.pow(10,r[2].length)); | ||||
| 		return sign + String(o / Math.pow(10,r[2].length)).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^([-]?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":"."); | ||||
| @ -256,15 +263,23 @@ var write_num = function(type, fmt, val) { | ||||
| 		rr = Math.round((val-Math.floor(val))*Math.pow(10,r[1].length)); | ||||
| 		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(/^([?]+)([ ]?)\/([ ]?)([?]+)/))) { | ||||
| 		rr = Math.min(Math.max(r[1].length, r[4].length),7); | ||||
| 		ff = frac(aval, Math.pow(10,rr)-1, false); | ||||
| 		return sign + (ff[0]||(ff[1] ? "" : "0")) + (ff[1] ? pad(ff[1],rr," ") + r[2] + "/" + r[3] + rpad(ff[2],rr," "): fill(" ", 2*rr+1 + r[2].length + r[3].length)); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^# ([?]+)([ ]?)\/([ ]?)([?]+)/))) { | ||||
| 		rr = Math.min(Math.max(r[1].length, r[4].length),7); | ||||
| 		ff = frac(aval, Math.pow(10,rr)-1, true); | ||||
| 		return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],rr," ") + r[2] + "/" + r[3] + rpad(ff[2],rr," "): fill(" ", 2*rr+1 + r[2].length + r[3].length)); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^00,000\.([#0]*0)$/))) { | ||||
| 		rr = val == Math.floor(val) ? 0 : Math.round((val-Math.floor(val))*Math.pow(10,r[1].length)); | ||||
| 		return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad(0,3-$$.length) : "") + $$; }) + "." + pad(rr,r[1].length,0); | ||||
| 	} | ||||
| 	switch(fmt) { | ||||
| 		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 : ""; | ||||
| 		default: | ||||
| 	} | ||||
| @ -309,7 +324,7 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 			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': | ||||
| 			case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g': | ||||
| 				if(v < 0) return ""; | ||||
| 				if(!dt) dt = parse_date_code(v, opts); | ||||
| 				if(!dt) return ""; | ||||
| @ -344,7 +359,7 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 			case '?': | ||||
| 				o = fmt[i]; while(fmt[++i] === c) o+=c; | ||||
| 				q={t:c, v:o}; out.push(q); lst = c; break; | ||||
| 			case '*': ++i; if(fmt[i] == ' ') ++i; break; // **
 | ||||
| 			case '*': ++i; if(fmt[i] == ' ' || fmt[i] == '*') ++i; break; // **
 | ||||
| 			case '(': case ')': out.push({t:(flen===1?'t':c),v:c}); ++i; break; | ||||
| 			case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': | ||||
| 				o = fmt[i]; while("0123456789".indexOf(fmt[++i]) > -1) o+=fmt[i]; | ||||
| @ -356,22 +371,38 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 				out.push({t:'t', v:c}); ++i; break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* walk backwards */ | ||||
| 	var bt = 0; | ||||
| 	for(i=out.length-1, lst='t'; i >= 0; --i) { | ||||
| 		switch(out[i].t) { | ||||
| 			case 'h': case 'H': out[i].t = hr; lst='h'; break; | ||||
| 			case 'd': case 'y': case 's': case 'M': case 'e': lst=out[i].t; break; | ||||
| 			case 'm': if(lst === 's') out[i].t = 'M'; break; | ||||
| 			case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break; | ||||
| 			case 's': if(bt < 3) bt = 3; | ||||
| 			/* falls through */ | ||||
| 			case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break; | ||||
| 			case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break; | ||||
| 			case 'Z': | ||||
| 				if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1; | ||||
| 				if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2; | ||||
| 				if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	switch(bt) { | ||||
| 		case 0: break; | ||||
| 		case 1: | ||||
| 			if(dt.u >= .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.S >= 60) { dt.S = 0; ++dt.M; } | ||||
| 			break; | ||||
| 	} | ||||
| 	/* replace fields */ | ||||
| 	for(i=0; i < out.length; ++i) { | ||||
| 		switch(out[i].t) { | ||||
| 			case 't': case 'T': case ' ': case 'D': break; | ||||
| 			case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'Z': | ||||
| 				out[i].v = write_date(out[i].t, out[i].v, dt); | ||||
| 				out[i].v = write_date(out[i].t, out[i].v, dt, bt); | ||||
| 				out[i].t = 't'; break; | ||||
| 			case 'n': case '(': case '?': | ||||
| 				var jj = i+1; | ||||
| @ -424,7 +455,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.13'; | ||||
| XLSX.version = '0.5.14'; | ||||
| var current_codepage, current_cptable, cptable; | ||||
| if(typeof module !== "undefined" && typeof require !== 'undefined') { | ||||
| 	if(typeof cptable === 'undefined') cptable = require('codepage'); | ||||
| @ -663,6 +694,7 @@ var parse_RichStr = function(data, length) { | ||||
| 		/* TODO: formatted string */ | ||||
| 		var dwSizeStrRun = data.read_shift(4); | ||||
| 		for(var i = 0; i != dwSizeStrRun; ++i) rgsStrRun.push(parse_StrRun(data)); | ||||
| 		z.r = JSON.stringify(rgsStrRun); | ||||
| 	} | ||||
| 	if(fExtStr) { | ||||
| 		/* TODO: phonetic string */ | ||||
| @ -735,6 +767,35 @@ var BErr = { | ||||
| }; | ||||
| var RBErr = evert(BErr); | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.321 BrtColor */ | ||||
| function parse_BrtColor(data, length) { | ||||
| 	var read = data.read_shift.bind(data); | ||||
| 	var out = {}; | ||||
| 	var d = read(1); | ||||
| 	out.fValidRGB = d & 1; | ||||
| 	out.xColorType = d >>> 1; | ||||
| 	out.index = read(1) | ||||
| 	out.nTintAndShade = read(2, 'i'); | ||||
| 	out.bRed   = read(1); | ||||
| 	out.bGreen = read(1); | ||||
| 	out.bBlue  = read(1); | ||||
| 	out.bAlpha = read(1); | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB 2.5.52 */ | ||||
| function parse_FontFlags(data, length) { | ||||
| 	var d = data.read_shift(1); | ||||
| 	data.l++; | ||||
| 	var out = { | ||||
| 		fItalic: d & 0x2, | ||||
| 		fStrikeout: d & 0x8, | ||||
| 		fOutline: d & 0x10, | ||||
| 		fShadow: d & 0x20, | ||||
| 		fCondense: d & 0x40, | ||||
| 		fExtend: d & 0x80, | ||||
| 	}; | ||||
| 	return out; | ||||
| } | ||||
| /* Parse a list of <r> tags */ | ||||
| var parse_rs = (function() { | ||||
| 	var tregex = matchtag("t"), rpregex = matchtag("rPr"); | ||||
| @ -974,6 +1035,34 @@ function parse_BrtFmt(data, length) { | ||||
| 	return [ifmt, stFmtCode]; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.653 BrtFont TODO */ | ||||
| function parse_BrtFont(data, length) { | ||||
| 	var read = data.read_shift.bind(data); | ||||
| 	var out = {flags:{}}; | ||||
| 	out.dyHeight = read(2); | ||||
| 	out.grbit = parse_FontFlags(data, 2); | ||||
| 	out.bls = read(2); | ||||
| 	out.sss = read(2); | ||||
| 	out.uls = read(1); | ||||
| 	out.bFamily = read(1); | ||||
| 	out.bCharSet = read(1); | ||||
| 	data.l++; | ||||
| 	out.brtColor = parse_BrtColor(data, 8); | ||||
| 	out.bFontScheme = read(1); | ||||
| 	out.name = parse_XLWideString(data, length - 21); | ||||
| 
 | ||||
| 	out.flags.Bold = out.bls === 0x02BC; | ||||
| 	out.flags.Italic = out.grbit.fItalic; | ||||
| 	out.flags.Strikeout = out.grbit.fStrikeout; | ||||
| 	out.flags.Outline = out.grbit.fOutline; | ||||
| 	out.flags.Shadow = out.grbit.fShadow; | ||||
| 	out.flags.Condense = out.grbit.fCondense; | ||||
| 	out.flags.Extend = out.grbit.fExtend; | ||||
| 	out.flags.Sub = out.sss & 0x2; | ||||
| 	out.flags.Sup = out.sss & 0x1; | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.816 BrtXF */ | ||||
| function parse_BrtXF(data, length) { | ||||
| 	var ixfeParent = data.read_shift(2); | ||||
| @ -1074,11 +1163,13 @@ var ct2type = { | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains", /*XLS[XM]*/ | ||||
| 	//"application/vnd.ms-excel.calcChain": "calcchains", /*XLSB*/
 | ||||
| 
 | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": "comments", /*XLS[XM]*/ | ||||
| 	"application/vnd.ms-excel.comments": "comments", /*XLSB*/ | ||||
| 
 | ||||
| 	"application/vnd.openxmlformats-package.core-properties+xml": "coreprops", | ||||
| 	"application/vnd.openxmlformats-officedocument.extended-properties+xml": "extprops", | ||||
| 	"application/vnd.openxmlformats-officedocument.custom-properties+xml": "custprops", | ||||
| 	"application/vnd.openxmlformats-officedocument.theme+xml":"themes", | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": "comments", | ||||
| 	"foo": "bar" | ||||
| }; | ||||
| 
 | ||||
| @ -1269,11 +1360,55 @@ function parse_comments_xml(data, opts) { | ||||
| 	}); | ||||
| 	return commentList; | ||||
| } | ||||
| /* [MS-XLSB] 2.4.28 BrtBeginComment */ | ||||
| var parse_BrtBeginComment = function(data, length) { | ||||
| 	var out = {}; | ||||
| 	out.iauthor = data.read_shift(4); | ||||
| 	var rfx = parse_UncheckedRfX(data, 16); | ||||
| 	out.rfx = rfx.s; | ||||
| 	out.ref = encode_cell(rfx.s); | ||||
| 	data.l += 16; /*var guid = parse_GUID(data); */ | ||||
| 	return out; | ||||
| }; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.324 BrtCommentAuthor */ | ||||
| var parse_BrtCommentAuthor = parse_XLWideString; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.325 BrtCommentText */ | ||||
| var parse_BrtCommentText = parse_RichStr; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.8 Comments */ | ||||
| function parse_comments_bin(data, opts) { | ||||
| 	var out = []; | ||||
| 	var authors = []; | ||||
| 	var c = {}; | ||||
| 	var pass = false; | ||||
| 	recordhopper(data, function(val, R, RT) { | ||||
| 		switch(R.n) { | ||||
| 			case 'BrtCommentAuthor': authors.push(val); break; | ||||
| 			case 'BrtBeginComment': c = val; break; | ||||
| 			case 'BrtCommentText': c.t = val.t; c.h = val.h; c.r = val.r; break; | ||||
| 			case 'BrtEndComment': | ||||
| 				c.author = authors[c.iauthor]; | ||||
| 				delete c.iauthor; | ||||
| 				if(opts.sheetRows && opts.sheetRows <= c.rfx.r) break; | ||||
| 				delete c.rfx; out.push(c); break; | ||||
| 			case 'BrtBeginComments': break; | ||||
| 			case 'BrtEndComments': break; | ||||
| 			case 'BrtBeginCommentAuthors': break; | ||||
| 			case 'BrtEndCommentAuthors': break; | ||||
| 			case 'BrtBeginCommentList': break; | ||||
| 			case 'BrtEndCommentList': break; | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n); | ||||
| 		} | ||||
| 	}); | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| function parse_comments(zip, dirComments, sheets, sheetRels, opts) { | ||||
| 	for(var i = 0; i != dirComments.length; ++i) { | ||||
| 		var canonicalpath=dirComments[i]; | ||||
| 		var comments=parse_comments_xml(getzipdata(zip, canonicalpath.replace(/^\//,''), true), opts); | ||||
| 		var comments=parse_cmnt(getzipdata(zip, canonicalpath.replace(/^\//,''), true), canonicalpath, opts); | ||||
| 		if(!comments || !comments.length) continue; | ||||
| 		// find the sheets targeted by these comments
 | ||||
| 		var sheetNames = Object.keys(sheets); | ||||
| @ -1636,6 +1771,7 @@ var parse_ws_bin = function(data, opts) { | ||||
| 			case 'BrtHLink': break; // TODO
 | ||||
| 			case 'BrtDrawing': break; // TODO
 | ||||
| 			case 'BrtLegacyDrawing': break; // TODO
 | ||||
| 			case 'BrtLegacyDrawingHF': break; // TODO
 | ||||
| 			case 'BrtPhoneticInfo': break; // TODO
 | ||||
| 			case 'BrtBeginHeaderFooter': break; // TODO
 | ||||
| 			case 'BrtEndHeaderFooter': break; // TODO
 | ||||
| @ -1667,6 +1803,11 @@ var parse_ws_bin = function(data, opts) { | ||||
| 			case 'BrtDVal': break; // TODO
 | ||||
| 			case 'BrtEndDVals': break; // TODO
 | ||||
| 			case 'BrtRangeProtection': break; // TODO
 | ||||
| 			case 'BrtBeginDCon': break; // TODO
 | ||||
| 			case 'BrtEndDCon': break; // TODO
 | ||||
| 			case 'BrtBeginDRefs': break; | ||||
| 			case 'BrtDRef': break; | ||||
| 			case 'BrtEndDRefs': break; | ||||
| 
 | ||||
| 			/* ActiveX */ | ||||
| 			case 'BrtBeginActiveXControls': break; | ||||
| @ -1687,6 +1828,19 @@ var parse_ws_bin = function(data, opts) { | ||||
| 			case 'BrtCustomFilter': break; | ||||
| 			case 'BrtEndCustomFilters': break; | ||||
| 
 | ||||
| 			/* Cell Watch */ | ||||
| 			case 'BrtBeginCellWatches': break; | ||||
| 			case 'BrtCellWatch': break; | ||||
| 			case 'BrtEndCellWatches': break; | ||||
| 
 | ||||
| 			/* Table */ | ||||
| 			case 'BrtTable': break; | ||||
| 
 | ||||
| 			/* Ignore Cell Errors */ | ||||
| 			case 'BrtBeginCellIgnoreECs': break; | ||||
| 			case 'BrtCellIgnoreEC': break; | ||||
| 			case 'BrtEndCellIgnoreECs': break; | ||||
| 
 | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + R.n); | ||||
| 		} | ||||
| 	}, opts); | ||||
| @ -1955,6 +2109,7 @@ var parse_wb_bin = function(data, opts) { | ||||
| 			case 'BrtEndPivotCacheIDs': break; | ||||
| 			case 'BrtWebOpt': break; | ||||
| 			case 'BrtFileRecover': break; | ||||
| 			case 'BrtFileSharing': break; | ||||
| 			/*case 'BrtBeginWebPubItems': break; | ||||
| 			case 'BrtBeginWebPubItem': break; | ||||
| 			case 'BrtEndWebPubItem': break; | ||||
| @ -1992,6 +2147,10 @@ function parse_sty(data, name, opts) { | ||||
| function parse_sst(data, name, opts) { | ||||
| 	return name.substr(-4)===".bin" ? parse_sst_bin(data, opts) : parse_sst_xml(data, opts); | ||||
| } | ||||
| 
 | ||||
| function parse_cmnt(data, name, opts) { | ||||
| 	return name.substr(-4)===".bin" ? parse_comments_bin(data, opts) : parse_comments_xml(data, opts); | ||||
| } | ||||
| /* [MS-XLSB] 2.3 Record Enumeration */ | ||||
| var RecordEnum = { | ||||
| 	0x0000: { n:"BrtRowHdr", f:parse_BrtRowHdr }, | ||||
| @ -2029,7 +2188,7 @@ var RecordEnum = { | ||||
| 	0x0027: { n:"BrtName", f:parsenoop }, | ||||
| 	0x0028: { n:"BrtIndexRowBlock", f:parsenoop }, | ||||
| 	0x002A: { n:"BrtIndexBlock", f:parsenoop }, | ||||
| 	0x002B: { n:"BrtFont", f:parsenoop }, | ||||
| 	0x002B: { n:"BrtFont", f:parse_BrtFont }, | ||||
| 	0x002C: { n:"BrtFmt", f:parse_BrtFmt }, | ||||
| 	0x002D: { n:"BrtFill", f:parsenoop }, | ||||
| 	0x002E: { n:"BrtBorder", f:parsenoop }, | ||||
| @ -2537,12 +2696,12 @@ var RecordEnum = { | ||||
| 	0x0275: { n:"BrtEndComments", f:parsenoop }, | ||||
| 	0x0276: { n:"BrtBeginCommentAuthors", f:parsenoop }, | ||||
| 	0x0277: { n:"BrtEndCommentAuthors", f:parsenoop }, | ||||
| 	0x0278: { n:"BrtCommentAuthor", f:parsenoop }, | ||||
| 	0x0278: { n:"BrtCommentAuthor", f:parse_BrtCommentAuthor }, | ||||
| 	0x0279: { n:"BrtBeginCommentList", f:parsenoop }, | ||||
| 	0x027A: { n:"BrtEndCommentList", f:parsenoop }, | ||||
| 	0x027B: { n:"BrtBeginComment", f:parsenoop }, | ||||
| 	0x027B: { n:"BrtBeginComment", f:parse_BrtBeginComment}, | ||||
| 	0x027C: { n:"BrtEndComment", f:parsenoop }, | ||||
| 	0x027D: { n:"BrtCommentText", f:parsenoop }, | ||||
| 	0x027D: { n:"BrtCommentText", f:parse_BrtCommentText }, | ||||
| 	0x027E: { n:"BrtBeginOleObjects", f:parsenoop }, | ||||
| 	0x027F: { n:"BrtOleObject", f:parsenoop }, | ||||
| 	0x0280: { n:"BrtEndOleObjects", f:parsenoop }, | ||||
|  | ||||
							
								
								
									
										4
									
								
								dist/xlsx.min.js
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										4
									
								
								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.13", | ||||
| 	"version": "0.5.14", | ||||
| 	"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.5.9", | ||||
| 		"ssf":"~0.6.1", | ||||
| 		"codepage":"", | ||||
| 		"cfb":"", | ||||
| 		"jszip":"~2.1.0", | ||||
|  | ||||
							
								
								
									
										136
									
								
								test.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										136
									
								
								test.js
									
									
									
									
									
								
							| @ -154,46 +154,38 @@ describe('options', function() { | ||||
| 		it('should not generate sheet stubs by default', function() { | ||||
| 			var wb = XLSX.readFile(dir+'merge_cells.xlsx'); | ||||
| 			assert.throws(function() { wb.Sheets.Merge.A2.v; }); | ||||
| 			wb = XLSX.readFile(dir+'merge_cells.xlsb'); | ||||
| 			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}); | ||||
| 			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); | ||||
| 			assert((typeof wb.Sheets.Text.B26 !== 'undefined') == B26); | ||||
| 			assert((typeof wb.Sheets.Text.C16 !== 'undefined') == C16); | ||||
| 			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'); | ||||
| 			assert(typeof wb.Sheets.Text.A46 !== 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.B26 !== 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.C16 !== 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.D2 !== 'undefined'); | ||||
| 			checkcells(wb, true, true, true, true); | ||||
| 			wb = XLSX.readFile(dir+'formula_stress_test.xlsx'); | ||||
| 			assert(typeof wb.Sheets.Text.A46 !== 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.B26 !== 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.C16 !== 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.D2 !== 'undefined'); | ||||
| 			checkcells(wb, true, true, true, true); | ||||
| 		}); | ||||
| 		it('sheetRows n=20', function() { | ||||
| 			var wb = XLSX.readFile(dir+'formula_stress_test.xlsx', {sheetRows:20}); | ||||
| 			assert(typeof wb.Sheets.Text.A46 === 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.B26 === 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.C16 !== 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.D2 !== 'undefined'); | ||||
| 			checkcells(wb, false, false, true, true); | ||||
| 			wb = XLSX.readFile(dir+'formula_stress_test.xlsb', {sheetRows:20}); | ||||
| 			assert(typeof wb.Sheets.Text.A46 === 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.B26 === 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.C16 !== 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.D2 !== 'undefined'); | ||||
| 			checkcells(wb, false, false, true, true); | ||||
| 		}); | ||||
| 		it('sheetRows n=10', function() { | ||||
| 			var wb = XLSX.readFile(dir+'formula_stress_test.xlsb', {sheetRows:10}); | ||||
| 			assert(typeof wb.Sheets.Text.A46 === 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.B26 === 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.C16 === 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.D2 !== 'undefined'); | ||||
| 			checkcells(wb, false, false, false, true); | ||||
| 			wb = XLSX.readFile(dir+'formula_stress_test.xlsx', {sheetRows:10}); | ||||
| 			assert(typeof wb.Sheets.Text.A46 === 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.B26 === 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.C16 === 'undefined'); | ||||
| 			assert(typeof wb.Sheets.Text.D2 !== 'undefined'); | ||||
| 			checkcells(wb, false, false, false, true); | ||||
| 		}); | ||||
| 	}); | ||||
| 	describe('book', function() { | ||||
| @ -248,42 +240,49 @@ describe('input formats', function() { | ||||
| }); | ||||
| 
 | ||||
| describe('features', function() { | ||||
| 	describe('should have comment as part of cell properties', function(){ | ||||
| 		var ws; | ||||
| 		before(function() { | ||||
| 			XLSX = require('./'); | ||||
| 			var wb = XLSX.readFile(dir+'apachepoi_SimpleWithComments.xlsx'); | ||||
| 			var sheetName = 'Sheet1'; | ||||
| 			ws = wb.Sheets[sheetName]; | ||||
| 		}); | ||||
| 		it('Parse comments.xml and insert into cell',function(){ | ||||
| 	it('should have comment as part of cell properties', function(){ | ||||
| 		var XLSX = require('./'); | ||||
| 		var sheet = 'Sheet1'; | ||||
| 		var wbxlsx=XLSX.readFile(dir+'apachepoi_SimpleWithComments.xlsx'); | ||||
| 		var wbxlsb=XLSX.readFile(dir+'2013/apachepoi_SimpleWithComments.xlsx.xlsb'); | ||||
| 
 | ||||
| 		[wbxlsx,wbxlsb].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].t, "Yegor Kozlov:\r\nfirst cell", "must have the concatenated texts"); | ||||
| 			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"); | ||||
| 			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].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"); | ||||
| 			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 wb; | ||||
| 		var wbxlsx, wbxlsb; | ||||
| 		before(function() { | ||||
| 			XLSX = require('./'); | ||||
| 			wb = XLSX.readFile(dir+'custom_properties.xlsx'); | ||||
| 			wbxlsx = XLSX.readFile(dir+'custom_properties.xlsx'); | ||||
| 			wbxlsb = XLSX.readFile(dir+'custom_properties.xlsb'); | ||||
| 		}); | ||||
| 		it('Must have read the core properties', function() { | ||||
| 
 | ||||
| 		function coreprop(wb) { | ||||
| 			assert.equal(wb.Props.Company, 'Vector Inc'); | ||||
| 			assert.equal(wb.Props.Creator, 'Pony Foo'); | ||||
| 		}); | ||||
| 		it('Must have read the custom properties', function() { | ||||
| 		} | ||||
| 		function custprop(wb) { | ||||
| 			assert.equal(wb.Custprops['I am a boolean'], true); | ||||
| 			assert.equal(wb.Custprops['Date completed'], '1967-03-09T16:30:00Z'); | ||||
| 			assert.equal(wb.Custprops.Status, 2); | ||||
| 			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/XLSB)', function() { | ||||
| 	describe('should parse cells with date type (XLSX/XLSM)', function() { | ||||
| 		var wb, ws; | ||||
| 		before(function() { | ||||
| 			XLSX = require('./'); | ||||
| @ -299,26 +298,30 @@ describe('features', function() { | ||||
| 
 | ||||
| 	describe('sheetRows', function() { | ||||
| 		it('should use original range if not set', function() { | ||||
| 			var wb = XLSX.readFile(dir+'formula_stress_test.xlsb'); | ||||
| 			assert.equal(wb.Sheets.Text["!ref"],"A1:F49"); | ||||
| 			wb = XLSX.readFile(dir+'formula_stress_test.xlsx'); | ||||
| 			assert.equal(wb.Sheets.Text["!ref"],"A1:F49"); | ||||
| 			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) { | ||||
| 				assert.equal(wb.Sheets.Text["!ref"],"A1:F49"); | ||||
| 			}); | ||||
| 		}); | ||||
| 		it('should adjust range if set', function() { | ||||
| 			var wb = XLSX.readFile(dir+'formula_stress_test.xlsx', {sheetRows:10}); | ||||
| 			assert.equal(wb.Sheets.Text["!fullref"],"A1:F49"); | ||||
| 			assert.equal(wb.Sheets.Text["!ref"],"A1:F10"); | ||||
| 			wb = XLSX.readFile(dir+'formula_stress_test.xlsb', {sheetRows:10}); | ||||
| 			assert.equal(wb.Sheets.Text["!fullref"],"A1:F49"); | ||||
| 			assert.equal(wb.Sheets.Text["!ref"],"A1:F10"); | ||||
| 			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) { | ||||
| 				assert.equal(wb.Sheets.Text["!fullref"],"A1:F49"); | ||||
| 				assert.equal(wb.Sheets.Text["!ref"],"A1:F10"); | ||||
| 			}); | ||||
| 		}); | ||||
| 		it('should not generate comment cells', function() { | ||||
| 			var wb = XLSX.readFile(dir+'comments_stress_test.xlsx', {sheetRows:10}); | ||||
| 			assert.equal(wb.Sheets.Sheet7["!fullref"],"A1:N34"); | ||||
| 			assert.equal(wb.Sheets.Sheet7["!ref"],"A1:A1"); | ||||
| 			wb = XLSX.readFile(dir+'comments_stress_test.xlsb', {sheetRows:10}); | ||||
| 			assert.equal(wb.Sheets.Sheet7["!fullref"],"A1:N34"); | ||||
| 			assert.equal(wb.Sheets.Sheet7["!ref"],"A1:A1"); | ||||
| 			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) { | ||||
| 				assert.equal(wb.Sheets.Sheet7["!fullref"],"A1:N34"); | ||||
| 				assert.equal(wb.Sheets.Sheet7["!ref"],"A1:A1"); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| 
 | ||||
| @ -337,3 +340,18 @@ describe('features', function() { | ||||
| 		}); | ||||
| 	}); | ||||
| }); | ||||
| 
 | ||||
| describe('invalid files', function() { | ||||
| 	it('should fail on passwords', function() { | ||||
| 		assert.throws(function() { XLSX.readFile(dir + 'excel-reader-xlsx_error03.xlsx'); }); | ||||
| 	}); | ||||
| 	it('should fail on XLS files', function() { | ||||
| 		assert.throws(function() { XLSX.readFile(dir + 'roo_type_excel.xlsx'); }); | ||||
| 	}); | ||||
| 	it('should fail on ODS files', function() { | ||||
| 		assert.throws(function() { XLSX.readFile(dir + 'roo_type_openoffice.xlsx');}); | ||||
| 	}); | ||||
| 	it('should fail on DOC files', function() { | ||||
| 		assert.throws(function() { XLSX.readFile(dir + 'word_doc.doc');}); | ||||
| 	}); | ||||
| }); | ||||
|  | ||||
							
								
								
									
										16
									
								
								tests.lst
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										16
									
								
								tests.lst
									
									
									
									
									
								
							| @ -1,4 +1,5 @@ | ||||
| AutoFilter.xlsb | ||||
| BlankSheetTypes.xlsb | ||||
| RkNumber.xlsb | ||||
| comments_stress_test.xlsb | ||||
| custom_properties.xlsb | ||||
| @ -7,10 +8,22 @@ large_strings.xlsb | ||||
| merge_cells.xlsb | ||||
| named_ranges_2011.xlsb | ||||
| number_format.xlsb | ||||
| pivot_table_named_range.xlsb | ||||
| pivot_table_test.xlsb | ||||
| rich_text_stress.xlsb | ||||
| time_stress_test_1.xlsb | ||||
| xlsx-stream-d-date-cell.xlsb | ||||
| 2013/apachepoi_29982.xls.xlsb | ||||
| 2013/apachepoi_43251.xls.xlsb | ||||
| 2013/apachepoi_44593.xls.xlsb | ||||
| 2013/apachepoi_44643.xls.xlsb | ||||
| 2013/apachepoi_44958.xls.xlsb | ||||
| 2013/apachepoi_46136-NoWarnings.xls.xlsb | ||||
| 2013/apachepoi_48968.xls.xlsb | ||||
| 2013/apachepoi_50939.xls.xlsb | ||||
| 2013/apachepoi_54016.xls.xlsb | ||||
| 2013/apachepoi_ReadOnlyRecommended.xls.xlsb | ||||
| 2013/apachepoi_testArraysAndTables.xls.xlsb | ||||
| AutoFilter.xlsx | ||||
| LONumbers-2010.xlsx | ||||
| LONumbers-2011.xlsx | ||||
| @ -191,6 +204,7 @@ openpyxl_r_date_1904.xlsx | ||||
| openpyxl_r_formulae.xlsx | ||||
| openpyxl_r_null_archive.xlsx.pending | ||||
| openpyxl_r_null_file.xlsx.pending | ||||
| pivot_table_named_range.xlsx | ||||
| rich_text_stress.xlsx | ||||
| roo_1900_base.xlsx | ||||
| roo_1904_base.xlsx | ||||
| @ -208,6 +222,7 @@ roo_formula.xlsx | ||||
| roo_formula_string_error.xlsx | ||||
| roo_link.xlsx | ||||
| roo_named_cells.xlsx | ||||
| roo_numbers-export.xlsx | ||||
| roo_numbers1.xlsx | ||||
| roo_numeric-link.xlsx | ||||
| roo_only_one_sheet.xlsx | ||||
| @ -240,6 +255,7 @@ xlrd_test_comments_gdocs.xlsx | ||||
| xlrd_text_bar.xlsx | ||||
| xlsx-stream-d-date-cell.xlsx | ||||
| חישוב_נקודות_זיכוי.xlsx | ||||
| BlankSheetTypes.xlsm | ||||
| apachepoi_45431.xlsm | ||||
| apachepoi_47026.xlsm | ||||
| apachepoi_47089.xlsm | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| Subproject commit 95f6e5509f22f8f8f757a342a3906dc3b6835cc4 | ||||
| Subproject commit a056111d30799597f1b92dc1197f04a1f86cad78 | ||||
							
								
								
									
										215
									
								
								xlsx.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										215
									
								
								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.5.9'; | ||||
| SSF.version = '0.6.1'; | ||||
| /* Options */ | ||||
| var opts_fmt = {}; | ||||
| function fixopts(o){for(var y in opts_fmt) if(o[y]===undefined) o[y]=opts_fmt[y];} | ||||
| @ -124,6 +124,10 @@ 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) { | ||||
| 		out.u = 0; | ||||
| 		if(++time == 86400) { time = 0; ++date; } | ||||
| 	} | ||||
| 	if(date === 60) {dout = [1900,2,29]; dow=3;} | ||||
| 	else if(date === 0) {dout = [1900,1,0]; dow=6;} | ||||
| 	else { | ||||
| @ -146,7 +150,7 @@ SSF.parse_date_code = parse_date_code; | ||||
| /*jshint -W086 */ | ||||
| var write_date = function(type, fmt, val) { | ||||
| 	if(val < 0) return ""; | ||||
| 	var o; | ||||
| 	var o, ss; | ||||
| 	switch(type) { | ||||
| 		case 'y': switch(fmt) { /* year */ | ||||
| 			case 'y': case 'yy': return pad(val.y % 100,2); | ||||
| @ -181,11 +185,11 @@ var write_date = function(type, fmt, val) { | ||||
| 			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': ss=Math.round(val.S+val.u); return ss >= 60 ? 0 : ss; | ||||
| 			case 'ss': ss=Math.round(val.S+val.u); if(ss>=60) ss=0; return pad(ss,2); | ||||
| 			case 'ss.0': ss=Math.round(10*(val.S+val.u)); if(ss>=600) ss = 0; o = pad(ss,3); return o.substr(0,2)+"." + o.substr(2); | ||||
| 			case 'ss.00': ss=Math.round(100*(val.S+val.u)); if(ss>=6000) ss = 0; o = pad(ss,4); return o.substr(0,2)+"." + o.substr(2); | ||||
| 			case 'ss.000': ss=Math.round(1000*(val.S+val.u)); if(ss>=60000) ss = 0; o = pad(ss,5); return o.substr(0,2)+"." + o.substr(2); | ||||
| 			default: throw 'bad second format: ' + fmt; | ||||
| 		} | ||||
| 		case 'Z': switch(fmt) { | ||||
| @ -209,6 +213,8 @@ var write_num = function(type, fmt, val) { | ||||
| 	var mul = 0, o; | ||||
| 	fmt = fmt.replace(/%/g,function(x) { 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)); | ||||
| 	if(fmt.indexOf("E") > -1) { | ||||
| 		var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1; | ||||
| 		if(fmt.match(/^#+0.0E\+0$/)) { | ||||
| @ -242,11 +248,12 @@ var write_num = function(type, fmt, val) { | ||||
| 	if(fmt.match(/^#+0+$/)) fmt = fmt.replace(/#/g,""); | ||||
| 	if(fmt.match(/^00+$/)) return (val<0?"-":"")+pad(Math.round(aval),fmt.length); | ||||
| 	if(fmt.match(/^[#?]+$/)) return String(Math.round(val)).replace(/^0$/,""); | ||||
| 	if((r = fmt.match(/^#*0+\.(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); }); | ||||
| 		rr = String(o/Math.pow(10,r[1].length)).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.([0-9]*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); }); | ||||
| 		return fmt.match(/0\./) ? rr : rr.replace(/^0\./,"."); | ||||
| 	} | ||||
| 	fmt = fmt.replace(/^#+0/, "0"); | ||||
| 	fmt = fmt.replace(/^#+([0.])/, "$1"); | ||||
| 	if((r = fmt.match(/^(0*)\.(#*)$/))) { | ||||
| 		o = Math.round(aval*Math.pow(10,r[2].length)); | ||||
| 		return sign + String(o / Math.pow(10,r[2].length)).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^([-]?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":"."); | ||||
| @ -256,15 +263,23 @@ var write_num = function(type, fmt, val) { | ||||
| 		rr = Math.round((val-Math.floor(val))*Math.pow(10,r[1].length)); | ||||
| 		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(/^([?]+)([ ]?)\/([ ]?)([?]+)/))) { | ||||
| 		rr = Math.min(Math.max(r[1].length, r[4].length),7); | ||||
| 		ff = frac(aval, Math.pow(10,rr)-1, false); | ||||
| 		return sign + (ff[0]||(ff[1] ? "" : "0")) + (ff[1] ? pad(ff[1],rr," ") + r[2] + "/" + r[3] + rpad(ff[2],rr," "): fill(" ", 2*rr+1 + r[2].length + r[3].length)); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^# ([?]+)([ ]?)\/([ ]?)([?]+)/))) { | ||||
| 		rr = Math.min(Math.max(r[1].length, r[4].length),7); | ||||
| 		ff = frac(aval, Math.pow(10,rr)-1, true); | ||||
| 		return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],rr," ") + r[2] + "/" + r[3] + rpad(ff[2],rr," "): fill(" ", 2*rr+1 + r[2].length + r[3].length)); | ||||
| 	} | ||||
| 	if((r = fmt.match(/^00,000\.([#0]*0)$/))) { | ||||
| 		rr = val == Math.floor(val) ? 0 : Math.round((val-Math.floor(val))*Math.pow(10,r[1].length)); | ||||
| 		return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad(0,3-$$.length) : "") + $$; }) + "." + pad(rr,r[1].length,0); | ||||
| 	} | ||||
| 	switch(fmt) { | ||||
| 		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 : ""; | ||||
| 		default: | ||||
| 	} | ||||
| @ -309,7 +324,7 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 			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': | ||||
| 			case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g': | ||||
| 				if(v < 0) return ""; | ||||
| 				if(!dt) dt = parse_date_code(v, opts); | ||||
| 				if(!dt) return ""; | ||||
| @ -344,7 +359,7 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 			case '?': | ||||
| 				o = fmt[i]; while(fmt[++i] === c) o+=c; | ||||
| 				q={t:c, v:o}; out.push(q); lst = c; break; | ||||
| 			case '*': ++i; if(fmt[i] == ' ') ++i; break; // **
 | ||||
| 			case '*': ++i; if(fmt[i] == ' ' || fmt[i] == '*') ++i; break; // **
 | ||||
| 			case '(': case ')': out.push({t:(flen===1?'t':c),v:c}); ++i; break; | ||||
| 			case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': | ||||
| 				o = fmt[i]; while("0123456789".indexOf(fmt[++i]) > -1) o+=fmt[i]; | ||||
| @ -356,22 +371,38 @@ function eval_fmt(fmt, v, opts, flen) { | ||||
| 				out.push({t:'t', v:c}); ++i; break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* walk backwards */ | ||||
| 	var bt = 0; | ||||
| 	for(i=out.length-1, lst='t'; i >= 0; --i) { | ||||
| 		switch(out[i].t) { | ||||
| 			case 'h': case 'H': out[i].t = hr; lst='h'; break; | ||||
| 			case 'd': case 'y': case 's': case 'M': case 'e': lst=out[i].t; break; | ||||
| 			case 'm': if(lst === 's') out[i].t = 'M'; break; | ||||
| 			case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break; | ||||
| 			case 's': if(bt < 3) bt = 3; | ||||
| 			/* falls through */ | ||||
| 			case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break; | ||||
| 			case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break; | ||||
| 			case 'Z': | ||||
| 				if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1; | ||||
| 				if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2; | ||||
| 				if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	switch(bt) { | ||||
| 		case 0: break; | ||||
| 		case 1: | ||||
| 			if(dt.u >= .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.S >= 60) { dt.S = 0; ++dt.M; } | ||||
| 			break; | ||||
| 	} | ||||
| 	/* replace fields */ | ||||
| 	for(i=0; i < out.length; ++i) { | ||||
| 		switch(out[i].t) { | ||||
| 			case 't': case 'T': case ' ': case 'D': break; | ||||
| 			case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'Z': | ||||
| 				out[i].v = write_date(out[i].t, out[i].v, dt); | ||||
| 				out[i].v = write_date(out[i].t, out[i].v, dt, bt); | ||||
| 				out[i].t = 't'; break; | ||||
| 			case 'n': case '(': case '?': | ||||
| 				var jj = i+1; | ||||
| @ -424,7 +455,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.13'; | ||||
| XLSX.version = '0.5.14'; | ||||
| var current_codepage, current_cptable, cptable; | ||||
| if(typeof module !== "undefined" && typeof require !== 'undefined') { | ||||
| 	if(typeof cptable === 'undefined') cptable = require('codepage'); | ||||
| @ -663,6 +694,7 @@ var parse_RichStr = function(data, length) { | ||||
| 		/* TODO: formatted string */ | ||||
| 		var dwSizeStrRun = data.read_shift(4); | ||||
| 		for(var i = 0; i != dwSizeStrRun; ++i) rgsStrRun.push(parse_StrRun(data)); | ||||
| 		z.r = JSON.stringify(rgsStrRun); | ||||
| 	} | ||||
| 	if(fExtStr) { | ||||
| 		/* TODO: phonetic string */ | ||||
| @ -735,6 +767,35 @@ var BErr = { | ||||
| }; | ||||
| var RBErr = evert(BErr); | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.321 BrtColor */ | ||||
| function parse_BrtColor(data, length) { | ||||
| 	var read = data.read_shift.bind(data); | ||||
| 	var out = {}; | ||||
| 	var d = read(1); | ||||
| 	out.fValidRGB = d & 1; | ||||
| 	out.xColorType = d >>> 1; | ||||
| 	out.index = read(1) | ||||
| 	out.nTintAndShade = read(2, 'i'); | ||||
| 	out.bRed   = read(1); | ||||
| 	out.bGreen = read(1); | ||||
| 	out.bBlue  = read(1); | ||||
| 	out.bAlpha = read(1); | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB 2.5.52 */ | ||||
| function parse_FontFlags(data, length) { | ||||
| 	var d = data.read_shift(1); | ||||
| 	data.l++; | ||||
| 	var out = { | ||||
| 		fItalic: d & 0x2, | ||||
| 		fStrikeout: d & 0x8, | ||||
| 		fOutline: d & 0x10, | ||||
| 		fShadow: d & 0x20, | ||||
| 		fCondense: d & 0x40, | ||||
| 		fExtend: d & 0x80, | ||||
| 	}; | ||||
| 	return out; | ||||
| } | ||||
| /* Parse a list of <r> tags */ | ||||
| var parse_rs = (function() { | ||||
| 	var tregex = matchtag("t"), rpregex = matchtag("rPr"); | ||||
| @ -974,6 +1035,34 @@ function parse_BrtFmt(data, length) { | ||||
| 	return [ifmt, stFmtCode]; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.653 BrtFont TODO */ | ||||
| function parse_BrtFont(data, length) { | ||||
| 	var read = data.read_shift.bind(data); | ||||
| 	var out = {flags:{}}; | ||||
| 	out.dyHeight = read(2); | ||||
| 	out.grbit = parse_FontFlags(data, 2); | ||||
| 	out.bls = read(2); | ||||
| 	out.sss = read(2); | ||||
| 	out.uls = read(1); | ||||
| 	out.bFamily = read(1); | ||||
| 	out.bCharSet = read(1); | ||||
| 	data.l++; | ||||
| 	out.brtColor = parse_BrtColor(data, 8); | ||||
| 	out.bFontScheme = read(1); | ||||
| 	out.name = parse_XLWideString(data, length - 21); | ||||
| 
 | ||||
| 	out.flags.Bold = out.bls === 0x02BC; | ||||
| 	out.flags.Italic = out.grbit.fItalic; | ||||
| 	out.flags.Strikeout = out.grbit.fStrikeout; | ||||
| 	out.flags.Outline = out.grbit.fOutline; | ||||
| 	out.flags.Shadow = out.grbit.fShadow; | ||||
| 	out.flags.Condense = out.grbit.fCondense; | ||||
| 	out.flags.Extend = out.grbit.fExtend; | ||||
| 	out.flags.Sub = out.sss & 0x2; | ||||
| 	out.flags.Sup = out.sss & 0x1; | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.816 BrtXF */ | ||||
| function parse_BrtXF(data, length) { | ||||
| 	var ixfeParent = data.read_shift(2); | ||||
| @ -1074,11 +1163,13 @@ var ct2type = { | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains", /*XLS[XM]*/ | ||||
| 	//"application/vnd.ms-excel.calcChain": "calcchains", /*XLSB*/
 | ||||
| 
 | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": "comments", /*XLS[XM]*/ | ||||
| 	"application/vnd.ms-excel.comments": "comments", /*XLSB*/ | ||||
| 
 | ||||
| 	"application/vnd.openxmlformats-package.core-properties+xml": "coreprops", | ||||
| 	"application/vnd.openxmlformats-officedocument.extended-properties+xml": "extprops", | ||||
| 	"application/vnd.openxmlformats-officedocument.custom-properties+xml": "custprops", | ||||
| 	"application/vnd.openxmlformats-officedocument.theme+xml":"themes", | ||||
| 	"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": "comments", | ||||
| 	"foo": "bar" | ||||
| }; | ||||
| 
 | ||||
| @ -1269,11 +1360,55 @@ function parse_comments_xml(data, opts) { | ||||
| 	}); | ||||
| 	return commentList; | ||||
| } | ||||
| /* [MS-XLSB] 2.4.28 BrtBeginComment */ | ||||
| var parse_BrtBeginComment = function(data, length) { | ||||
| 	var out = {}; | ||||
| 	out.iauthor = data.read_shift(4); | ||||
| 	var rfx = parse_UncheckedRfX(data, 16); | ||||
| 	out.rfx = rfx.s; | ||||
| 	out.ref = encode_cell(rfx.s); | ||||
| 	data.l += 16; /*var guid = parse_GUID(data); */ | ||||
| 	return out; | ||||
| }; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.324 BrtCommentAuthor */ | ||||
| var parse_BrtCommentAuthor = parse_XLWideString; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.4.325 BrtCommentText */ | ||||
| var parse_BrtCommentText = parse_RichStr; | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.8 Comments */ | ||||
| function parse_comments_bin(data, opts) { | ||||
| 	var out = []; | ||||
| 	var authors = []; | ||||
| 	var c = {}; | ||||
| 	var pass = false; | ||||
| 	recordhopper(data, function(val, R, RT) { | ||||
| 		switch(R.n) { | ||||
| 			case 'BrtCommentAuthor': authors.push(val); break; | ||||
| 			case 'BrtBeginComment': c = val; break; | ||||
| 			case 'BrtCommentText': c.t = val.t; c.h = val.h; c.r = val.r; break; | ||||
| 			case 'BrtEndComment': | ||||
| 				c.author = authors[c.iauthor]; | ||||
| 				delete c.iauthor; | ||||
| 				if(opts.sheetRows && opts.sheetRows <= c.rfx.r) break; | ||||
| 				delete c.rfx; out.push(c); break; | ||||
| 			case 'BrtBeginComments': break; | ||||
| 			case 'BrtEndComments': break; | ||||
| 			case 'BrtBeginCommentAuthors': break; | ||||
| 			case 'BrtEndCommentAuthors': break; | ||||
| 			case 'BrtBeginCommentList': break; | ||||
| 			case 'BrtEndCommentList': break; | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n); | ||||
| 		} | ||||
| 	}); | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| function parse_comments(zip, dirComments, sheets, sheetRels, opts) { | ||||
| 	for(var i = 0; i != dirComments.length; ++i) { | ||||
| 		var canonicalpath=dirComments[i]; | ||||
| 		var comments=parse_comments_xml(getzipdata(zip, canonicalpath.replace(/^\//,''), true), opts); | ||||
| 		var comments=parse_cmnt(getzipdata(zip, canonicalpath.replace(/^\//,''), true), canonicalpath, opts); | ||||
| 		if(!comments || !comments.length) continue; | ||||
| 		// find the sheets targeted by these comments
 | ||||
| 		var sheetNames = Object.keys(sheets); | ||||
| @ -1636,6 +1771,7 @@ var parse_ws_bin = function(data, opts) { | ||||
| 			case 'BrtHLink': break; // TODO
 | ||||
| 			case 'BrtDrawing': break; // TODO
 | ||||
| 			case 'BrtLegacyDrawing': break; // TODO
 | ||||
| 			case 'BrtLegacyDrawingHF': break; // TODO
 | ||||
| 			case 'BrtPhoneticInfo': break; // TODO
 | ||||
| 			case 'BrtBeginHeaderFooter': break; // TODO
 | ||||
| 			case 'BrtEndHeaderFooter': break; // TODO
 | ||||
| @ -1667,6 +1803,11 @@ var parse_ws_bin = function(data, opts) { | ||||
| 			case 'BrtDVal': break; // TODO
 | ||||
| 			case 'BrtEndDVals': break; // TODO
 | ||||
| 			case 'BrtRangeProtection': break; // TODO
 | ||||
| 			case 'BrtBeginDCon': break; // TODO
 | ||||
| 			case 'BrtEndDCon': break; // TODO
 | ||||
| 			case 'BrtBeginDRefs': break; | ||||
| 			case 'BrtDRef': break; | ||||
| 			case 'BrtEndDRefs': break; | ||||
| 
 | ||||
| 			/* ActiveX */ | ||||
| 			case 'BrtBeginActiveXControls': break; | ||||
| @ -1687,6 +1828,19 @@ var parse_ws_bin = function(data, opts) { | ||||
| 			case 'BrtCustomFilter': break; | ||||
| 			case 'BrtEndCustomFilters': break; | ||||
| 
 | ||||
| 			/* Cell Watch */ | ||||
| 			case 'BrtBeginCellWatches': break; | ||||
| 			case 'BrtCellWatch': break; | ||||
| 			case 'BrtEndCellWatches': break; | ||||
| 
 | ||||
| 			/* Table */ | ||||
| 			case 'BrtTable': break; | ||||
| 
 | ||||
| 			/* Ignore Cell Errors */ | ||||
| 			case 'BrtBeginCellIgnoreECs': break; | ||||
| 			case 'BrtCellIgnoreEC': break; | ||||
| 			case 'BrtEndCellIgnoreECs': break; | ||||
| 
 | ||||
| 			default: if(!pass || opts.WTF) throw new Error("Unexpected record " + R.n); | ||||
| 		} | ||||
| 	}, opts); | ||||
| @ -1955,6 +2109,7 @@ var parse_wb_bin = function(data, opts) { | ||||
| 			case 'BrtEndPivotCacheIDs': break; | ||||
| 			case 'BrtWebOpt': break; | ||||
| 			case 'BrtFileRecover': break; | ||||
| 			case 'BrtFileSharing': break; | ||||
| 			/*case 'BrtBeginWebPubItems': break; | ||||
| 			case 'BrtBeginWebPubItem': break; | ||||
| 			case 'BrtEndWebPubItem': break; | ||||
| @ -1992,6 +2147,10 @@ function parse_sty(data, name, opts) { | ||||
| function parse_sst(data, name, opts) { | ||||
| 	return name.substr(-4)===".bin" ? parse_sst_bin(data, opts) : parse_sst_xml(data, opts); | ||||
| } | ||||
| 
 | ||||
| function parse_cmnt(data, name, opts) { | ||||
| 	return name.substr(-4)===".bin" ? parse_comments_bin(data, opts) : parse_comments_xml(data, opts); | ||||
| } | ||||
| /* [MS-XLSB] 2.3 Record Enumeration */ | ||||
| var RecordEnum = { | ||||
| 	0x0000: { n:"BrtRowHdr", f:parse_BrtRowHdr }, | ||||
| @ -2029,7 +2188,7 @@ var RecordEnum = { | ||||
| 	0x0027: { n:"BrtName", f:parsenoop }, | ||||
| 	0x0028: { n:"BrtIndexRowBlock", f:parsenoop }, | ||||
| 	0x002A: { n:"BrtIndexBlock", f:parsenoop }, | ||||
| 	0x002B: { n:"BrtFont", f:parsenoop }, | ||||
| 	0x002B: { n:"BrtFont", f:parse_BrtFont }, | ||||
| 	0x002C: { n:"BrtFmt", f:parse_BrtFmt }, | ||||
| 	0x002D: { n:"BrtFill", f:parsenoop }, | ||||
| 	0x002E: { n:"BrtBorder", f:parsenoop }, | ||||
| @ -2537,12 +2696,12 @@ var RecordEnum = { | ||||
| 	0x0275: { n:"BrtEndComments", f:parsenoop }, | ||||
| 	0x0276: { n:"BrtBeginCommentAuthors", f:parsenoop }, | ||||
| 	0x0277: { n:"BrtEndCommentAuthors", f:parsenoop }, | ||||
| 	0x0278: { n:"BrtCommentAuthor", f:parsenoop }, | ||||
| 	0x0278: { n:"BrtCommentAuthor", f:parse_BrtCommentAuthor }, | ||||
| 	0x0279: { n:"BrtBeginCommentList", f:parsenoop }, | ||||
| 	0x027A: { n:"BrtEndCommentList", f:parsenoop }, | ||||
| 	0x027B: { n:"BrtBeginComment", f:parsenoop }, | ||||
| 	0x027B: { n:"BrtBeginComment", f:parse_BrtBeginComment}, | ||||
| 	0x027C: { n:"BrtEndComment", f:parsenoop }, | ||||
| 	0x027D: { n:"BrtCommentText", f:parsenoop }, | ||||
| 	0x027D: { n:"BrtCommentText", f:parse_BrtCommentText }, | ||||
| 	0x027E: { n:"BrtBeginOleObjects", f:parsenoop }, | ||||
| 	0x027F: { n:"BrtOleObject", f:parsenoop }, | ||||
| 	0x0280: { n:"BrtEndOleObjects", f:parsenoop }, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user