xlsx.flow.js 656.4 KB
Newer Older
S
SheetJS 已提交
1 2 3
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*jshint -W041 */
S
SheetJS 已提交
4
/*jshint funcscope:true, eqnull:true, loopfunc:true */
5
/*exported XLSX */
S
SheetJS 已提交
6
/*global global, exports, module, require:false, process:false, Buffer:false */
S
SheetJS 已提交
7 8
var XLSX = {};
(function make_xlsx(XLSX){
9
XLSX.version = '0.11.2';
S
SheetJS 已提交
10
var current_codepage = 1200;
S
SheetJS 已提交
11
/*:: declare var cptable:any; */
S
SheetJS 已提交
12
/*global cptable:true */
S
SheetJS 已提交
13
if(typeof module !== "undefined" && typeof require !== 'undefined') {
S
SheetJS 已提交
14
	if(typeof cptable === 'undefined') global.cptable = require('./dist/cpexcel.js');
S
SheetJS 已提交
15 16 17 18 19
}
function reset_cp() { set_cp(1200); }
var set_cp = function(cp) { current_codepage = cp; };

function char_codes(data) { var o = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; }
S
SheetJS 已提交
20 21 22 23 24 25 26 27 28 29 30 31

function utf16leread(data/*:string*/)/*:string*/ {
	var o = [];
	for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i) + (data.charCodeAt(2*i+1)<<8));
	return o.join("");
}
function utf16beread(data/*:string*/)/*:string*/ {
	var o = [];
	for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i+1) + (data.charCodeAt(2*i)<<8));
	return o.join("");
}

S
SheetJS 已提交
32 33
var debom = function(data/*:string*/)/*:string*/ {
	var c1 = data.charCodeAt(0), c2 = data.charCodeAt(1);
S
SheetJS 已提交
34 35
	if(c1 == 0xFF && c2 == 0xFE) return utf16leread(data.substr(2));
	if(c1 == 0xFE && c2 == 0xFF) return utf16beread(data.substr(2));
S
SheetJS 已提交
36 37 38
	if(c1 == 0xFEFF) return data.substr(1);
	return data;
};
S
SheetJS 已提交
39 40 41

var _getchar = function _gc1(x) { return String.fromCharCode(x); };
if(typeof cptable !== 'undefined') {
S
SheetJS 已提交
42
	set_cp = function(cp) { current_codepage = cp; };
S
SheetJS 已提交
43
	debom = function(data) {
S
SheetJS 已提交
44 45 46 47 48 49 50 51
		if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.substr(2))); }
		return data;
	};
	_getchar = function _gc2(x) {
		if(current_codepage === 1200) return String.fromCharCode(x);
		return cptable.utils.decode(current_codepage, [x&255,x>>8])[0];
	};
}
52
var DENSE = null;
S
SheetJS 已提交
53
var DIF_XL = true;
S
SheetJS 已提交
54 55 56
var Base64 = (function make_b64(){
	var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
	return {
S
SheetJS 已提交
57
		encode: function(input/*:string*/)/*:string*/ {
S
SheetJS 已提交
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
			var o = "";
			var c1, c2, c3, e1, e2, e3, e4;
			for(var i = 0; i < input.length; ) {
				c1 = input.charCodeAt(i++);
				c2 = input.charCodeAt(i++);
				c3 = input.charCodeAt(i++);
				e1 = c1 >> 2;
				e2 = (c1 & 3) << 4 | c2 >> 4;
				e3 = (c2 & 15) << 2 | c3 >> 6;
				e4 = c3 & 63;
				if (isNaN(c2)) { e3 = e4 = 64; }
				else if (isNaN(c3)) { e4 = 64; }
				o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4);
			}
			return o;
		},
S
SheetJS 已提交
74
		decode: function b64_decode(input/*:string*/)/*:string*/ {
S
SheetJS 已提交
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
			var o = "";
			var c1, c2, c3;
			var e1, e2, e3, e4;
			input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
			for(var i = 0; i < input.length;) {
				e1 = map.indexOf(input.charAt(i++));
				e2 = map.indexOf(input.charAt(i++));
				e3 = map.indexOf(input.charAt(i++));
				e4 = map.indexOf(input.charAt(i++));
				c1 = e1 << 2 | e2 >> 4;
				c2 = (e2 & 15) << 4 | e3 >> 2;
				c3 = (e3 & 3) << 6 | e4;
				o += String.fromCharCode(c1);
				if (e3 != 64) { o += String.fromCharCode(c2); }
				if (e4 != 64) { o += String.fromCharCode(c3); }
			}
			return o;
		}
	};
})();
S
SheetJS 已提交
95
var has_buf = (typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && process.versions.node);
S
SheetJS 已提交
96

S
SheetJS 已提交
97
function new_raw_buf(len/*:number*/) {
S
SheetJS 已提交
98
	/* jshint -W056 */
S
SheetJS 已提交
99
	// $FlowIgnore
S
SheetJS 已提交
100 101 102 103
	return new (has_buf ? Buffer : Array)(len);
	/* jshint +W056 */
}

S
SheetJS 已提交
104
function s2a(s/*:string*/) {
S
SheetJS 已提交
105 106 107 108 109 110 111 112 113 114
	if(has_buf) return new Buffer(s, "binary");
	return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; });
}

var bconcat = function(bufs) { return [].concat.apply([], bufs); };

var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/;
/*::
declare type Block = any;
declare type BufArray = {
S
SheetJS 已提交
115
	newblk(sz:number):Block;
S
SheetJS 已提交
116 117 118 119
	next(sz:number):Block;
	end():any;
	push(buf:Block):void;
};
S
SheetJS 已提交
120

121
type RecordHopperCB = {(d:any, Rn:string, RT:number):?boolean;};
S
SheetJS 已提交
122 123 124 125 126 127

type EvertType = {[string]:string};
type EvertNumType = {[string]:number};
type EvertArrType = {[string]:Array<string>};

type StringConv = {(string):string};
S
TXT/PRN  
SheetJS 已提交
128

S
SheetJS 已提交
129
type WriteObjStrFactory = {from_sheet(ws:Worksheet, o:any, wb:?Workbook):string};
S
SheetJS 已提交
130
*/
S
SheetJS 已提交
131
/* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */
S
SheetJS 已提交
132
/*jshint -W041 */
S
SheetJS 已提交
133 134 135
var SSF/*:SSFModule*/ = ({}/*:any*/);
var make_ssf = function make_ssf(SSF/*:SSFModule*/){
SSF.version = '0.10.0';
S
SheetJS 已提交
136 137 138 139 140 141 142
function _strrev(x/*:string*/)/*:string*/ { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; }
function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; }
function pad0(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
function pad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v;return t.length>=d?t:fill(' ',d-t.length)+t;}
function rpad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);}
function pad0r1(v/*:any*/,d/*:number*/)/*:string*/{var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;}
function pad0r2(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
S
SheetJS 已提交
143
var p2_32 = Math.pow(2,32);
S
SheetJS 已提交
144 145
function pad0r(v/*:any*/,d/*:number*/)/*:string*/{if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); }
function isgeneral(s/*:string*/, i/*:?number*/)/*:boolean*/ { i = i || 0; return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; }
S
SheetJS 已提交
146 147 148
/*::
type SSF_write_num = {(type:string, fmt:string, val:number):string};
*/
S
SheetJS 已提交
149
var days/*:Array<Array<string> >*/ = [
S
SheetJS 已提交
150 151 152 153 154 155 156 157
	['Sun', 'Sunday'],
	['Mon', 'Monday'],
	['Tue', 'Tuesday'],
	['Wed', 'Wednesday'],
	['Thu', 'Thursday'],
	['Fri', 'Friday'],
	['Sat', 'Saturday']
];
S
SheetJS 已提交
158
var months/*:Array<Array<string> >*/ = [
S
SheetJS 已提交
159 160 161 162 163 164 165 166 167 168 169 170 171
	['J', 'Jan', 'January'],
	['F', 'Feb', 'February'],
	['M', 'Mar', 'March'],
	['A', 'Apr', 'April'],
	['M', 'May', 'May'],
	['J', 'Jun', 'June'],
	['J', 'Jul', 'July'],
	['A', 'Aug', 'August'],
	['S', 'Sep', 'September'],
	['O', 'Oct', 'October'],
	['N', 'Nov', 'November'],
	['D', 'Dec', 'December']
];
S
SheetJS 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
function init_table(t/*:any*/) {
	t[0]=  'General';
	t[1]=  '0';
	t[2]=  '0.00';
	t[3]=  '#,##0';
	t[4]=  '#,##0.00';
	t[9]=  '0%';
	t[10]= '0.00%';
	t[11]= '0.00E+00';
	t[12]= '# ?/?';
	t[13]= '# ??/??';
	t[14]= 'm/d/yy';
	t[15]= 'd-mmm-yy';
	t[16]= 'd-mmm';
	t[17]= 'mmm-yy';
	t[18]= 'h:mm AM/PM';
	t[19]= 'h:mm:ss AM/PM';
	t[20]= 'h:mm';
	t[21]= 'h:mm:ss';
	t[22]= 'm/d/yy h:mm';
	t[37]= '#,##0 ;(#,##0)';
	t[38]= '#,##0 ;[Red](#,##0)';
	t[39]= '#,##0.00;(#,##0.00)';
	t[40]= '#,##0.00;[Red](#,##0.00)';
	t[45]= 'mm:ss';
	t[46]= '[h]:mm:ss';
	t[47]= 'mmss.0';
	t[48]= '##0.0E+0';
	t[49]= '@';
	t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "';
	t[65535]= 'General';
}

var table_fmt = {};
init_table(table_fmt);
function frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
S
SheetJS 已提交
208 209 210 211 212 213 214 215 216
	var sgn = x < 0 ? -1 : 1;
	var B = x * sgn;
	var P_2 = 0, P_1 = 1, P = 0;
	var Q_2 = 1, Q_1 = 0, Q = 0;
	var A = Math.floor(B);
	while(Q_1 < D) {
		A = Math.floor(B);
		P = A * P_1 + P_2;
		Q = A * Q_1 + Q_2;
S
SheetJS 已提交
217
		if((B - A) < 0.00000005) break;
S
SheetJS 已提交
218 219 220 221
		B = 1 / (B - A);
		P_2 = P_1; P_1 = P;
		Q_2 = Q_1; Q_1 = Q;
	}
S
SheetJS 已提交
222
	if(Q > D) { if(Q_1 > D) { Q = Q_2; P = P_2; } else { Q = Q_1; P = P_1; } }
S
SheetJS 已提交
223 224 225 226
	if(!mixed) return [0, sgn * P, Q];
	var q = Math.floor(sgn * P/Q);
	return [q, sgn*P - q*Q, Q];
}
S
SheetJS 已提交
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
function parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
	if(v > 2958465 || v < 0) return null;
	var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
	var dout=[];
	var out={D:date, T:time, u:86400*(v-date)-time,y:0,m:0,d:0,H:0,M:0,S:0,q:0};
	if(Math.abs(out.u) < 1e-6) out.u = 0;
	if(opts && opts.date1904) date += 1462;
	if(out.u > 0.9999) {
		out.u = 0;
		if(++time == 86400) { out.T = time = 0; ++date; ++out.D; }
	}
	if(date === 60) {dout = b2 ? [1317,10,29] : [1900,2,29]; dow=3;}
	else if(date === 0) {dout = b2 ? [1317,8,29] : [1900,1,0]; dow=6;}
	else {
		if(date > 60) --date;
		/* 1 = Jan 1 1900 in Gregorian */
		var d = new Date(1900, 0, 1);
		d.setDate(d.getDate() + date - 1);
		dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
		dow = d.getDay();
		if(date < 60) dow = (dow + 6) % 7;
		if(b2) dow = fix_hijri(d, dout);
	}
	out.y = dout[0]; out.m = dout[1]; out.d = dout[2];
	out.S = time % 60; time = Math.floor(time / 60);
	out.M = time % 60; time = Math.floor(time / 60);
	out.H = time;
	out.q = dow;
	return out;
}
SSF.parse_date_code = parse_date_code;
var basedate = new Date(1899, 11, 31, 0, 0, 0);
var dnthresh = basedate.getTime();
var base1904 = new Date(1900, 2, 1, 0, 0, 0);
function datenum_local(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
	var epoch = v.getTime();
	if(date1904) epoch -= 1461*24*60*60*1000;
	else if(v >= base1904) epoch += 24*60*60*1000;
	return (epoch - (dnthresh + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
}
function general_fmt_int(v/*:number*/)/*:string*/ { return v.toString(10); }
S
SheetJS 已提交
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
SSF._general_int = general_fmt_int;
var general_fmt_num = (function make_general_fmt_num() {
var gnr1 = /\.(\d*[1-9])0+$/, gnr2 = /\.0*$/, gnr4 = /\.(\d*[1-9])0+/, gnr5 = /\.0*[Ee]/, gnr6 = /(E[+-])(\d)$/;
function gfn2(v) {
	var w = (v<0?12:11);
	var o = gfn5(v.toFixed(12)); if(o.length <= w) return o;
	o = v.toPrecision(10); if(o.length <= w) return o;
	return v.toExponential(5);
}
function gfn3(v) {
	var o = v.toFixed(11).replace(gnr1,".$1");
	if(o.length > (v<0?12:11)) o = v.toPrecision(6);
	return o;
}
function gfn4(o) {
	for(var i = 0; i != o.length; ++i) if((o.charCodeAt(i) | 0x20) === 101) return o.replace(gnr4,".$1").replace(gnr5,"E").replace("e","E").replace(gnr6,"$10$2");
	return o;
}
function gfn5(o) {
	return o.indexOf(".") > -1 ? o.replace(gnr2,"").replace(gnr1,".$1") : o;
}
S
SheetJS 已提交
289
return function general_fmt_num(v/*:number*/)/*:string*/ {
S
SheetJS 已提交
290 291 292 293 294 295 296 297
	var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
	if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
	else if(Math.abs(V) <= 9) o = gfn2(v);
	else if(V === 10) o = v.toFixed(10).substr(0,12);
	else o = gfn3(v);
	return gfn5(gfn4(o));
};})();
SSF._general_num = general_fmt_num;
S
SheetJS 已提交
298
function general_fmt(v/*:any*/, opts/*:any*/) {
S
SheetJS 已提交
299 300 301
	switch(typeof v) {
		case 'string': return v;
		case 'boolean': return v ? "TRUE" : "FALSE";
S
SheetJS 已提交
302
		case 'number': return (v|0) === v ? general_fmt_int(v) : general_fmt_num(v);
S
SheetJS 已提交
303
		case 'undefined': return "";
S
SheetJS 已提交
304 305 306
		case 'object':
			if(v == null) return "";
			if(v instanceof Date) return format(14, datenum_local(v, opts && opts.date1904), opts);
S
SheetJS 已提交
307 308 309 310
	}
	throw new Error("unsupported value in General format: " + v);
}
SSF._general = general_fmt;
S
SheetJS 已提交
311
function fix_hijri(/*::date, o*/) { return 0; }
S
SheetJS 已提交
312
/*jshint -W086 */
S
SheetJS 已提交
313
function write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*:string*/ {
S
SheetJS 已提交
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
	var o="", ss=0, tt=0, y = val.y, out, outl = 0;
	switch(type) {
		case 98: /* 'b' buddhist year */
			y = val.y + 543;
			/* falls through */
		case 121: /* 'y' year */
		switch(fmt.length) {
			case 1: case 2: out = y % 100; outl = 2; break;
			default: out = y % 10000; outl = 4; break;
		} break;
		case 109: /* 'm' month */
		switch(fmt.length) {
			case 1: case 2: out = val.m; outl = fmt.length; break;
			case 3: return months[val.m-1][1];
			case 5: return months[val.m-1][0];
			default: return months[val.m-1][2];
		} break;
		case 100: /* 'd' day */
		switch(fmt.length) {
			case 1: case 2: out = val.d; outl = fmt.length; break;
			case 3: return days[val.q][0];
			default: return days[val.q][1];
		} break;
		case 104: /* 'h' 12-hour */
		switch(fmt.length) {
			case 1: case 2: out = 1+(val.H+11)%12; outl = fmt.length; break;
			default: throw 'bad hour format: ' + fmt;
		} break;
		case 72: /* 'H' 24-hour */
		switch(fmt.length) {
			case 1: case 2: out = val.H; outl = fmt.length; break;
			default: throw 'bad hour format: ' + fmt;
		} break;
		case 77: /* 'M' minutes */
		switch(fmt.length) {
			case 1: case 2: out = val.M; outl = fmt.length; break;
			default: throw 'bad minute format: ' + fmt;
		} break;
		case 115: /* 's' seconds */
S
SheetJS 已提交
353 354 355 356 357 358 359 360 361 362 363
			if(fmt != 's' && fmt != 'ss' && fmt != '.0' && fmt != '.00' && fmt != '.000') throw 'bad second format: ' + fmt;
			if(val.u === 0 && (fmt == "s" || fmt == "ss")) return pad0(val.S, fmt.length);
			/*::if(!ss0) ss0 = 0; */
			if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100;
			else tt = ss0 === 1 ? 10 : 1;
			ss = Math.round((tt)*(val.S + val.u));
			if(ss >= 60*tt) ss = 0;
			if(fmt === 's') return ss === 0 ? "0" : ""+ss/tt;
			o = pad0(ss,2 + ss0);
			if(fmt === 'ss') return o.substr(0,2);
			return "." + o.substr(2,fmt.length-1);
S
SheetJS 已提交
364 365 366 367 368 369 370 371 372 373 374 375 376
		case 90: /* 'Z' absolute time */
		switch(fmt) {
			case '[h]': case '[hh]': out = val.D*24+val.H; break;
			case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
			case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
			default: throw 'bad abstime format: ' + fmt;
		} outl = fmt.length === 3 ? 1 : 2; break;
		case 101: /* 'e' era */
			out = y; outl = 1;
	}
	if(outl > 0) return pad0(out, outl); else return "";
}
/*jshint +W086 */
S
SheetJS 已提交
377
function commaify(s/*:string*/)/*:string*/ {
S
SheetJS 已提交
378 379 380 381
	var w = 3;
	if(s.length <= w) return s;
	var j = (s.length % w), o = s.substr(0,j);
	for(; j!=s.length; j+=w) o+=(o.length > 0 ? "," : "") + s.substr(j,w);
S
SheetJS 已提交
382 383
	return o;
}
S
SheetJS 已提交
384
var write_num/*:SSF_write_num*/ = (function make_write_num(){
S
SheetJS 已提交
385
var pct1 = /%/g;
S
SheetJS 已提交
386
function write_num_pct(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
S
SheetJS 已提交
387 388 389
	var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
	return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
}
S
SheetJS 已提交
390
function write_num_cm(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
S
SheetJS 已提交
391 392 393 394
	var idx = fmt.length - 1;
	while(fmt.charCodeAt(idx-1) === 44) --idx;
	return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
}
S
SheetJS 已提交
395 396
function write_num_exp(fmt/*:string*/, val/*:number*/)/*:string*/{
	var o/*:string*/;
S
SheetJS 已提交
397 398
	var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
	if(fmt.match(/^#+0.0E\+0$/)) {
S
SheetJS 已提交
399 400
		if(val == 0) return "0.0E+0";
		else if(val < 0) return "-" + write_num_exp(fmt, -val);
S
SheetJS 已提交
401
		var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
S
SheetJS 已提交
402
		var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
S
SheetJS 已提交
403 404 405
		if(ee < 0) ee += period;
		o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
		if(o.indexOf("e") === -1) {
S
SheetJS 已提交
406
			var fakee = Math.floor(Math.log(val)*Math.LOG10E);
S
SheetJS 已提交
407
			if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
S
SheetJS 已提交
408 409
			else o += "E+" + (fakee - ee);
			while(o.substr(0,2) === "0.") {
S
SheetJS 已提交
410
				o = o.charAt(0) + o.substr(2,period) + "." + o.substr(2+period);
S
SheetJS 已提交
411 412 413 414 415 416
				o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0.");
			}
			o = o.replace(/\+-/,"-");
		}
		o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
	} else o = val.toExponential(idx);
S
SheetJS 已提交
417
	if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
S
SheetJS 已提交
418 419 420 421
	if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
	return o.replace("e","E");
}
var frac1 = /# (\?+)( ?)\/( ?)(\d+)/;
S
SheetJS 已提交
422 423
function write_num_f1(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:string*/ {
	var den = parseInt(r[4],10), rr = Math.round(aval * den), base = Math.floor(rr/den);
S
SheetJS 已提交
424 425 426
	var myn = (rr - base*den), myd = den;
	return sign + (base === 0 ? "" : ""+base) + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad_(myn,r[1].length) + r[2] + "/" + r[3] + pad0(myd,r[4].length));
}
S
SheetJS 已提交
427
function write_num_f2(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:string*/ {
S
SheetJS 已提交
428 429
	return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
}
V
Valters Valdersteins 已提交
430
var dec1 = /^#*0*\.([0#]+)/;
S
SheetJS 已提交
431 432
var closeparen = /\).*[0#]/;
var phone = /\(###\) ###\\?-####/;
S
SheetJS 已提交
433
function hashq(str/*:string*/)/*:string*/ {
S
SheetJS 已提交
434 435 436 437 438 439 440 441 442
	var o = "", cc;
	for(var i = 0; i != str.length; ++i) switch((cc=str.charCodeAt(i))) {
		case 35: break;
		case 63: o+= " "; break;
		case 48: o+= "0"; break;
		default: o+= String.fromCharCode(cc);
	}
	return o;
}
S
SheetJS 已提交
443
function rnd(val/*:number*/, d/*:number*/)/*:string*/ { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
S
SheetJS 已提交
444 445 446 447 448 449 450 451 452 453 454 455
function dec(val/*:number*/, d/*:number*/)/*:number*/ {
	if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
		return 0;
	}
	return Math.round((val-Math.floor(val))*Math.pow(10,d));
}
function carry(val/*:number*/, d/*:number*/)/*:number*/ {
	if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
		return 1;
	}
	return 0;
}
S
SheetJS 已提交
456 457
function flr(val/*:number*/)/*:string*/ { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); }
function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
S
SheetJS 已提交
458 459 460 461 462 463 464 465
	if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
		var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
		if(val >= 0) return write_num_flt('n', ffmt, val);
		return '(' + write_num_flt('n', ffmt, -val) + ')';
	}
	if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm(type, fmt, val);
	if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val);
	if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val);
S
SheetJS 已提交
466
	if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
S
SheetJS 已提交
467 468
	var o;
	var r/*:?Array<string>*/, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
S
SheetJS 已提交
469 470 471 472 473
	if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length);
	if(fmt.match(/^[#?]+$/)) {
		o = pad0r(val,0); if(o === "0") o = "";
		return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
	}
S
SheetJS 已提交
474 475 476
	if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign);
	if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
	if((r = fmt.match(dec1))) {
V
Valters Valdersteins 已提交
477
		o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1])).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", hashq(/*::(*/r/*::||[""])*/[1]).length-$1.length); });
S
SheetJS 已提交
478 479 480
		return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
	}
	fmt = fmt.replace(/^#+([0.])/, "$1");
S
SheetJS 已提交
481
	if((r = fmt.match(/^(0*)\.(#*)$/))) {
S
SheetJS 已提交
482 483
		return sign + rnd(aval, r[2].length).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
	}
S
SheetJS 已提交
484
	if((r = fmt.match(/^#{1,3},##0(\.?)$/))) return sign + commaify(pad0r(aval,0));
S
SheetJS 已提交
485
	if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
S
SheetJS 已提交
486
		return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length);
S
SheetJS 已提交
487
	}
S
SheetJS 已提交
488 489
	if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
	if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
S
SheetJS 已提交
490 491
		o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val));
		ri = 0;
S
SheetJS 已提交
492
		return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";}));
S
SheetJS 已提交
493
	}
S
SheetJS 已提交
494
	if(fmt.match(phone)) {
S
SheetJS 已提交
495 496 497 498
		o = write_num_flt(type, "##########", val);
		return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
	}
	var oa = "";
S
SheetJS 已提交
499 500
	if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
		ri = Math.min(/*::String(*/r[4]/*::)*/.length,7);
S
SheetJS 已提交
501 502
		ff = frac(aval, Math.pow(10,ri)-1, false);
		o = "" + sign;
S
SheetJS 已提交
503
		oa = write_num("n", /*::String(*/r[1]/*::)*/, ff[1]);
S
SheetJS 已提交
504
		if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
S
SheetJS 已提交
505
		o += oa + /*::String(*/r[2]/*::)*/ + "/" + /*::String(*/r[3]/*::)*/;
S
SheetJS 已提交
506 507 508 509 510
		oa = rpad_(ff[2],ri);
		if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
		o += oa;
		return o;
	}
S
SheetJS 已提交
511
	if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
S
SheetJS 已提交
512 513 514 515
		ri = Math.min(Math.max(r[1].length, r[4].length),7);
		ff = frac(aval, Math.pow(10,ri)-1, true);
		return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
	}
S
SheetJS 已提交
516
	if((r = fmt.match(/^[#0?]+$/))) {
S
SheetJS 已提交
517 518 519 520
		o = pad0r(val, 0);
		if(fmt.length <= o.length) return o;
		return hashq(fmt.substr(0,fmt.length-o.length)) + o;
	}
S
SheetJS 已提交
521
	if((r = fmt.match(/^([#0?]+)\.([#0]+)$/))) {
S
SheetJS 已提交
522 523 524 525 526
		o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
		ri = o.indexOf(".");
		var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
		return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
	}
S
SheetJS 已提交
527
	if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
S
SheetJS 已提交
528 529 530 531
		ri = dec(val, r[1].length);
		return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(flr(val)).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(ri,r[1].length);
	}
	switch(fmt) {
S
SheetJS 已提交
532 533 534
		case "###,##0.00": return write_num_flt(type, "#,##0.00", val);
		case "###,###":
		case "##,###":
S
SheetJS 已提交
535
		case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : "";
S
SheetJS 已提交
536 537
		case "###,###.00": return write_num_flt(type, "###,##0.00",val).replace(/^0\./,".");
		case "#,###.00": return write_num_flt(type, "#,##0.00",val).replace(/^0\./,".");
S
SheetJS 已提交
538 539 540 541
		default:
	}
	throw new Error("unsupported format |" + fmt + "|");
}
S
SheetJS 已提交
542
function write_num_cm2(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
S
SheetJS 已提交
543 544 545 546
	var idx = fmt.length - 1;
	while(fmt.charCodeAt(idx-1) === 44) --idx;
	return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
}
S
SheetJS 已提交
547
function write_num_pct2(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
S
SheetJS 已提交
548 549 550
	var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
	return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
}
S
SheetJS 已提交
551 552
function write_num_exp2(fmt/*:string*/, val/*:number*/)/*:string*/{
	var o/*:string*/;
S
SheetJS 已提交
553 554
	var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
	if(fmt.match(/^#+0.0E\+0$/)) {
S
SheetJS 已提交
555 556
		if(val == 0) return "0.0E+0";
		else if(val < 0) return "-" + write_num_exp2(fmt, -val);
S
SheetJS 已提交
557
		var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
S
SheetJS 已提交
558
		var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
S
SheetJS 已提交
559 560 561
		if(ee < 0) ee += period;
		o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
		if(!o.match(/[Ee]/)) {
S
SheetJS 已提交
562
			var fakee = Math.floor(Math.log(val)*Math.LOG10E);
S
SheetJS 已提交
563
			if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
S
SheetJS 已提交
564 565 566 567 568
			else o += "E+" + (fakee - ee);
			o = o.replace(/\+-/,"-");
		}
		o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
	} else o = val.toExponential(idx);
S
SheetJS 已提交
569
	if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
S
SheetJS 已提交
570 571 572
	if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
	return o.replace("e","E");
}
S
SheetJS 已提交
573
function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
S
SheetJS 已提交
574 575 576 577 578 579 580 581
	if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
		var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
		if(val >= 0) return write_num_int('n', ffmt, val);
		return '(' + write_num_int('n', ffmt, -val) + ')';
	}
	if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm2(type, fmt, val);
	if(fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val);
	if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val);
S
SheetJS 已提交
582
	if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
S
SheetJS 已提交
583
	var o;
S
SheetJS 已提交
584
	var r/*:?Array<string>*/, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
S
SheetJS 已提交
585 586 587 588 589
	if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length);
	if(fmt.match(/^[#?]+$/)) {
		o = (""+val); if(val === 0) o = "";
		return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
	}
S
SheetJS 已提交
590 591 592
	if((r = fmt.match(frac1))) return write_num_f2(r, aval, sign);
	if(fmt.match(/^#+0+$/)) return sign + pad0(aval,fmt.length - fmt.indexOf("0"));
	if((r = fmt.match(dec1))) {
S
SheetJS 已提交
593
		/*:: if(!Array.isArray(r)) throw new Error("unreachable"); */
V
Valters Valdersteins 已提交
594
		o = (""+val).replace(/^([^\.]+)$/,"$1."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1]));
S
SheetJS 已提交
595
		o = o.replace(/\.(\d*)$/,function($$, $1) {
S
SheetJS 已提交
596
		/*:: if(!Array.isArray(r)) throw new Error("unreachable"); */
V
Valters Valdersteins 已提交
597
			return "." + $1 + fill("0", hashq(r[1]).length-$1.length); });
S
SheetJS 已提交
598 599 600
		return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
	}
	fmt = fmt.replace(/^#+([0.])/, "$1");
S
SheetJS 已提交
601
	if((r = fmt.match(/^(0*)\.(#*)$/))) {
S
SheetJS 已提交
602 603
		return sign + (""+aval).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
	}
S
SheetJS 已提交
604
	if((r = fmt.match(/^#{1,3},##0(\.?)$/))) return sign + commaify((""+aval));
S
SheetJS 已提交
605
	if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
S
SheetJS 已提交
606 607
		return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify((""+val)) + "." + fill('0',r[1].length);
	}
S
SheetJS 已提交
608 609
	if((r = fmt.match(/^#,#*,#0/))) return write_num_int(type,fmt.replace(/^#,#*,/,""),val);
	if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
S
SheetJS 已提交
610 611
		o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val));
		ri = 0;
S
SheetJS 已提交
612
		return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";}));
S
SheetJS 已提交
613
	}
S
SheetJS 已提交
614
	if(fmt.match(phone)) {
S
SheetJS 已提交
615 616 617 618
		o = write_num_int(type, "##########", val);
		return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
	}
	var oa = "";
S
SheetJS 已提交
619
	if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
S
SheetJS 已提交
620
		ri = Math.min(/*::String(*/r[4]/*::)*/.length,7);
S
SheetJS 已提交
621 622
		ff = frac(aval, Math.pow(10,ri)-1, false);
		o = "" + sign;
S
SheetJS 已提交
623
		oa = write_num("n", /*::String(*/r[1]/*::)*/, ff[1]);
S
SheetJS 已提交
624
		if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
S
SheetJS 已提交
625
		o += oa + /*::String(*/r[2]/*::)*/ + "/" + /*::String(*/r[3]/*::)*/;
S
SheetJS 已提交
626 627 628 629 630
		oa = rpad_(ff[2],ri);
		if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
		o += oa;
		return o;
	}
S
SheetJS 已提交
631
	if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
S
SheetJS 已提交
632 633 634 635
		ri = Math.min(Math.max(r[1].length, r[4].length),7);
		ff = frac(aval, Math.pow(10,ri)-1, true);
		return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
	}
S
SheetJS 已提交
636
	if((r = fmt.match(/^[#0?]+$/))) {
S
SheetJS 已提交
637 638 639 640
		o = "" + val;
		if(fmt.length <= o.length) return o;
		return hashq(fmt.substr(0,fmt.length-o.length)) + o;
	}
S
SheetJS 已提交
641
	if((r = fmt.match(/^([#0]+)\.([#0]+)$/))) {
S
SheetJS 已提交
642 643 644 645 646
		o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
		ri = o.indexOf(".");
		var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
		return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
	}
S
SheetJS 已提交
647
	if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
S
SheetJS 已提交
648 649 650
		return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify(""+val).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(0,r[1].length);
	}
	switch(fmt) {
S
SheetJS 已提交
651 652
		case "###,###":
		case "##,###":
S
SheetJS 已提交
653 654
		case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
		default:
S
SheetJS 已提交
655
			if(fmt.match(/\.[0#?]*$/)) return write_num_int(type, fmt.slice(0,fmt.lastIndexOf(".")), val) + hashq(fmt.slice(fmt.lastIndexOf(".")));
S
SheetJS 已提交
656 657 658
	}
	throw new Error("unsupported format |" + fmt + "|");
}
S
SheetJS 已提交
659
return function write_num(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
S
SheetJS 已提交
660 661
	return (val|0) === val ? write_num_int(type, fmt, val) : write_num_flt(type, fmt, val);
};})();
S
SheetJS 已提交
662 663
function split_fmt(fmt/*:string*/)/*:Array<string>*/ {
	var out/*:Array<string>*/ = [];
S
SheetJS 已提交
664 665
	var in_str = false/*, cc*/;
	for(var i = 0, j = 0; i < fmt.length; ++i) switch((/*cc=*/fmt.charCodeAt(i))) {
S
SheetJS 已提交
666 667 668 669 670 671 672 673 674 675 676 677 678 679
		case 34: /* '"' */
			in_str = !in_str; break;
		case 95: case 42: case 92: /* '_' '*' '\\' */
			++i; break;
		case 59: /* ';' */
			out[out.length] = fmt.substr(j,i-j);
			j = i+1;
	}
	out[out.length] = fmt.substr(j);
	if(in_str === true) throw new Error("Format |" + fmt + "| unterminated string ");
	return out;
}
SSF._split = split_fmt;
var abstime = /\[[HhMmSs]*\]/;
S
SheetJS 已提交
680
function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
S
SheetJS 已提交
681
	var i = 0, /*cc = 0,*/ c = "", o = "";
S
SheetJS 已提交
682 683 684
	while(i < fmt.length) {
		switch((c = fmt.charAt(i))) {
			case 'G': if(isgeneral(fmt, i)) i+= 6; i++; break;
S
SheetJS 已提交
685
			case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) ++i; ++i; break;
S
SheetJS 已提交
686 687 688 689 690 691 692 693 694
			case '\\': i+=2; break;
			case '_': i+=2; break;
			case '@': ++i; break;
			case 'B': case 'b':
				if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") return true;
				/* falls through */
			case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
				/* falls through */
			case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g': return true;
V
Valters Valdersteins 已提交
695 696 697
			case 'A': case 'a':
				if(fmt.substr(i, 3).toUpperCase() === "A/P") return true;
				if(fmt.substr(i, 5).toUpperCase() === "AM/PM") return true;
S
SheetJS 已提交
698 699 700 701 702 703 704 705 706
				++i; break;
			case '[':
				o = c;
				while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
				if(o.match(abstime)) return true;
				break;
			case '.':
				/* falls through */
			case '0': case '#':
S
SheetJS 已提交
707
				while(i < fmt.length && ("0#?.,E+-%".indexOf(c=fmt.charAt(++i)) > -1 || (c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1))){/* empty */}
S
SheetJS 已提交
708
				break;
S
SheetJS 已提交
709
			case '?': while(fmt.charAt(++i) === c){/* empty */} break;
S
SheetJS 已提交
710 711 712
			case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break;
			case '(': case ')': ++i; break;
			case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
S
SheetJS 已提交
713
				while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){/* empty */} break;
S
SheetJS 已提交
714 715 716 717 718 719 720
			case ' ': ++i; break;
			default: ++i; break;
		}
	}
	return false;
}
SSF.is_date = fmt_is_date;
S
SheetJS 已提交
721
function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
S
SheetJS 已提交
722
	var out = [], o = "", i = 0, c = "", lst='t', dt, j, cc;
S
SheetJS 已提交
723 724 725
	var hr='H';
	/* Tokenize */
	while(i < fmt.length) {
S
SheetJS 已提交
726
		switch((c = fmt.charAt(i))) {
S
SheetJS 已提交
727 728 729 730 731 732
			case 'G': /* General */
				if(!isgeneral(fmt, i)) throw new Error('unrecognized character ' + c + ' in ' +fmt);
				out[out.length] = {t:'G', v:'General'}; i+=7; break;
			case '"': /* Literal text */
				for(o="";(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) o += String.fromCharCode(cc);
				out[out.length] = {t:'t', v:o}; ++i; break;
S
SheetJS 已提交
733
			case '\\': var w = fmt.charAt(++i), t = (w === "(" || w === ")") ? w : 't';
S
SheetJS 已提交
734 735 736 737 738
				out[out.length] = {t:t, v:w}; ++i; break;
			case '_': out[out.length] = {t:'t', v:" "}; i+=2; break;
			case '@': /* Text Placeholder */
				out[out.length] = {t:'T', v:v}; ++i; break;
			case 'B': case 'b':
S
SheetJS 已提交
739 740
				if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") {
					if(dt==null) { dt=parse_date_code(v, opts, fmt.charAt(i+1) === "2"); if(dt==null) return ""; }
S
SheetJS 已提交
741 742 743 744 745 746 747 748 749
					out[out.length] = {t:'X', v:fmt.substr(i,2)}; lst = c; i+=2; break;
				}
				/* falls through */
			case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
				c = c.toLowerCase();
				/* falls through */
			case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g':
				if(v < 0) return "";
				if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
S
SheetJS 已提交
750
				o = c; while(++i < fmt.length && fmt.charAt(i).toLowerCase() === c) o+=c;
S
SheetJS 已提交
751
				if(c === 'm' && lst.toLowerCase() === 'h') c = 'M';
S
SheetJS 已提交
752 753
				if(c === 'h') c = hr;
				out[out.length] = {t:c, v:o}; lst = c; break;
V
Valters Valdersteins 已提交
754
			case 'A': case 'a':
S
SheetJS 已提交
755
				var q={t:c, v:c};
S
SheetJS 已提交
756
				if(dt==null) dt=parse_date_code(v, opts);
V
Valters Valdersteins 已提交
757 758
				if(fmt.substr(i, 3).toUpperCase() === "A/P") { if(dt!=null) q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;}
				else if(fmt.substr(i,5).toUpperCase() === "AM/PM") { if(dt!=null) q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; }
S
SheetJS 已提交
759 760 761 762 763
				else { q.t = "t"; ++i; }
				if(dt==null && q.t === 'T') return "";
				out[out.length] = q; lst = c; break;
			case '[':
				o = c;
S
SheetJS 已提交
764 765
				while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
				if(o.slice(-1) !== ']') throw 'unterminated "[" block: |' + o + '|';
S
SheetJS 已提交
766 767 768
				if(o.match(abstime)) {
					if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
					out[out.length] = {t:'Z', v:o.toLowerCase()};
S
SheetJS 已提交
769
					lst = o.charAt(1);
S
SheetJS 已提交
770 771 772 773
				} else if(o.indexOf("$") > -1) {
					o = (o.match(/\$([^-\[\]]*)/)||[])[1]||"$";
					if(!fmt_is_date(fmt)) out[out.length] = {t:'t',v:o};
				}
S
SheetJS 已提交
774 775 776 777
				break;
			/* Numbers */
			case '.':
				if(dt != null) {
S
SheetJS 已提交
778
					o = c; while(++i < fmt.length && (c=fmt.charAt(i)) === "0") o += c;
S
SheetJS 已提交
779 780 781 782
					out[out.length] = {t:'s', v:o}; break;
				}
				/* falls through */
			case '0': case '#':
S
SheetJS 已提交
783
				o = c; while((++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1) || (c=='\\' && fmt.charAt(i+1) == "-" && i < fmt.length - 2 && "0#".indexOf(fmt.charAt(i+2))>-1)) o += c;
S
SheetJS 已提交
784 785
				out[out.length] = {t:'n', v:o}; break;
			case '?':
S
SheetJS 已提交
786
				o = c; while(fmt.charAt(++i) === c) o+=c;
S
SheetJS 已提交
787
				out[out.length] = {t:c, v:o}; lst = c; break;
S
SheetJS 已提交
788
			case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break; // **
S
SheetJS 已提交
789 790
			case '(': case ')': out[out.length] = {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':
S
SheetJS 已提交
791
				o = c; while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1) o+=fmt.charAt(i);
S
SheetJS 已提交
792 793 794
				out[out.length] = {t:'D', v:o}; break;
			case ' ': out[out.length] = {t:c, v:c}; ++i; break;
			default:
V
Valters Valdersteins 已提交
795
				if(",$-+/():!^&'~{}<>=€acfijklopqrtuvwxzP".indexOf(c) === -1) throw new Error('unrecognized character ' + c + ' in ' + fmt);
S
SheetJS 已提交
796 797 798 799 800 801 802 803 804 805 806 807 808
				out[out.length] = {t:'t', v:c}; ++i; break;
		}
	}
	var bt = 0, ss0 = 0, ssm;
	for(i=out.length-1, lst='t'; i >= 0; --i) {
		switch(out[i].t) {
			case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
			case 's':
				if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
				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;
S
SheetJS 已提交
809
			case 'X': /*if(out[i].v === "B2");*/
S
SheetJS 已提交
810 811 812 813 814 815 816 817 818 819
				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:
S
SheetJS 已提交
820
			/*::if(!dt) break;*/
S
SheetJS 已提交
821 822 823 824 825
			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:
S
SheetJS 已提交
826
			/*::if(!dt) break;*/
S
SheetJS 已提交
827 828 829 830 831 832 833 834 835
			if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
			if(dt.S >=  60) { dt.S = 0; ++dt.M; }
			break;
	}
	/* replace fields */
	var nstr = "", jj;
	for(i=0; i < out.length; ++i) {
		switch(out[i].t) {
			case 't': case 'T': case ' ': case 'D': break;
S
SheetJS 已提交
836
			case 'X': out[i].v = ""; out[i].t = ";"; break;
S
SheetJS 已提交
837
			case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'b': case 'Z':
S
SheetJS 已提交
838
				/*::if(!dt) throw "unreachable"; */
S
SheetJS 已提交
839 840 841 842 843 844
				out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
				out[i].t = 't'; break;
			case 'n': case '(': case '?':
				jj = i+1;
				while(out[jj] != null && (
					(c=out[jj].t) === "?" || c === "D" ||
S
SheetJS 已提交
845 846 847
					((c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/')) ||
					(out[i].t === '(' && (c === ' ' || c === 'n' || c === ')')) ||
					(c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?'))
S
SheetJS 已提交
848 849
				)) {
					out[i].v += out[jj].v;
S
SheetJS 已提交
850
					out[jj] = {v:"", t:";"}; ++jj;
S
SheetJS 已提交
851 852 853 854 855 856 857 858
				}
				nstr += out[i].v;
				i = jj-1; break;
			case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
		}
	}
	var vv = "", myv, ostr;
	if(nstr.length > 0) {
S
SheetJS 已提交
859 860 861 862 863 864 865 866 867 868 869
		if(nstr.charCodeAt(0) == 40) /* '(' */ {
			myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v);
			ostr = write_num('(', nstr, myv);
		} else {
			myv = (v<0 && flen > 1 ? -v : v);
			ostr = write_num('n', nstr, myv);
			if(myv < 0 && out[0] && out[0].t == 't') {
				ostr = ostr.substr(1);
				out[0].v = "-" + out[0].v;
			}
		}
S
SheetJS 已提交
870 871
		jj=ostr.length-1;
		var decpt = out.length;
S
SheetJS 已提交
872
		for(i=0; i < out.length; ++i) if(out[i] != null && out[i].t != 't' && out[i].v.indexOf(".") > -1) { decpt = i; break; }
S
SheetJS 已提交
873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891
		var lasti=out.length;
		if(decpt === out.length && ostr.indexOf("E") === -1) {
			for(i=out.length-1; i>= 0;--i) {
				if(out[i] == null || 'n?('.indexOf(out[i].t) === -1) continue;
				if(jj>=out[i].v.length-1) { jj -= out[i].v.length; out[i].v = ostr.substr(jj+1, out[i].v.length); }
				else if(jj < 0) out[i].v = "";
				else { out[i].v = ostr.substr(0, jj+1); jj = -1; }
				out[i].t = 't';
				lasti = i;
			}
			if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
		}
		else if(decpt !== out.length && ostr.indexOf("E") === -1) {
			jj = ostr.indexOf(".")-1;
			for(i=decpt; i>= 0; --i) {
				if(out[i] == null || 'n?('.indexOf(out[i].t) === -1) continue;
				j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1;
				vv = out[i].v.substr(j+1);
				for(; j>=0; --j) {
S
SheetJS 已提交
892
					if(jj>=0 && (out[i].v.charAt(j) === "0" || out[i].v.charAt(j) === "#")) vv = ostr.charAt(jj--) + vv;
S
SheetJS 已提交
893 894 895 896 897 898 899 900
				}
				out[i].v = vv;
				out[i].t = 't';
				lasti = i;
			}
			if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
			jj = ostr.indexOf(".")+1;
			for(i=decpt; i<out.length; ++i) {
S
SheetJS 已提交
901
				if(out[i] == null || ('n?('.indexOf(out[i].t) === -1 && i !== decpt)) continue;
S
SheetJS 已提交
902 903 904
				j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0;
				vv = out[i].v.substr(0,j);
				for(; j<out[i].v.length; ++j) {
S
SheetJS 已提交
905
					if(jj<ostr.length) vv += ostr.charAt(jj++);
S
SheetJS 已提交
906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937
				}
				out[i].v = vv;
				out[i].t = 't';
				lasti = i;
			}
		}
	}
	for(i=0; i<out.length; ++i) if(out[i] != null && 'n(?'.indexOf(out[i].t)>-1) {
		myv = (flen >1 && v < 0 && i>0 && out[i-1].v === "-" ? -v:v);
		out[i].v = write_num(out[i].t, out[i].v, myv);
		out[i].t = 't';
	}
	var retval = "";
	for(i=0; i !== out.length; ++i) if(out[i] != null) retval += out[i].v;
	return retval;
}
SSF._eval = eval_fmt;
var cfregex = /\[[=<>]/;
var cfregex2 = /\[([=<>]*)(-?\d+\.?\d*)\]/;
function chkcond(v, rr) {
	if(rr == null) return false;
	var thresh = parseFloat(rr[2]);
	switch(rr[1]) {
		case "=":  if(v == thresh) return true; break;
		case ">":  if(v >  thresh) return true; break;
		case "<":  if(v <  thresh) return true; break;
		case "<>": if(v != thresh) return true; break;
		case ">=": if(v >= thresh) return true; break;
		case "<=": if(v <= thresh) return true; break;
	}
	return false;
}
S
SheetJS 已提交
938
function choose_fmt(f/*:string*/, v/*:any*/) {
S
SheetJS 已提交
939 940 941
	var fmt = split_fmt(f);
	var l = fmt.length, lat = fmt[l-1].indexOf("@");
	if(l<4 && lat>-1) --l;
S
SheetJS 已提交
942
	if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
S
SheetJS 已提交
943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958
	if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
	switch(fmt.length) {
		case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
		case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
		case 3: fmt = lat>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
		case 4: break;
	}
	var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2];
	if(fmt[0].indexOf("[") === -1 && fmt[1].indexOf("[") === -1) return [l, ff];
	if(fmt[0].match(cfregex) != null || fmt[1].match(cfregex) != null) {
		var m1 = fmt[0].match(cfregex2);
		var m2 = fmt[1].match(cfregex2);
		return chkcond(v, m1) ? [l, fmt[0]] : chkcond(v, m2) ? [l, fmt[1]] : [l, fmt[m1 != null && m2 != null ? 2 : 1]];
	}
	return [l, ff];
}
S
SheetJS 已提交
959
function format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
S
SheetJS 已提交
960
	if(o == null) o = {};
S
SheetJS 已提交
961 962
	var sfmt = "";
	switch(typeof fmt) {
S
SheetJS 已提交
963 964 965 966 967 968 969 970
		case "string":
			if(fmt == "m/d/yy" && o.dateNF) sfmt = o.dateNF;
			else sfmt = fmt;
			break;
		case "number":
			if(fmt == 14 && o.dateNF) sfmt = o.dateNF;
			else sfmt = (o.table != null ? (o.table/*:any*/) : table_fmt)[fmt];
			break;
S
SheetJS 已提交
971 972
	}
	if(isgeneral(sfmt,0)) return general_fmt(v, o);
S
SheetJS 已提交
973
	if(v instanceof Date) v = datenum_local(v, o.date1904);
S
SheetJS 已提交
974 975 976 977 978 979
	var f = choose_fmt(sfmt, v);
	if(isgeneral(f[1])) return general_fmt(v, o);
	if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
	else if(v === "" || v == null) return "";
	return eval_fmt(f[1], v, o, f[0]);
}
S
SheetJS 已提交
980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996
function load_entry(fmt/*:string*/, idx/*:?number*/)/*:number*/ {
	if(typeof idx != 'number') {
		idx = +idx || -1;
/*::if(typeof idx != 'number') return 0x188; */
		for(var i = 0; i < 0x0188; ++i) {
/*::if(typeof idx != 'number') return 0x188; */
			if(table_fmt[i] == undefined) { if(idx < 0) idx = i; continue; }
			if(table_fmt[i] == fmt) { idx = i; break; }
		}
/*::if(typeof idx != 'number') return 0x188; */
		if(idx < 0) idx = 0x187;
	}
/*::if(typeof idx != 'number') return 0x188; */
	table_fmt[idx] = fmt;
	return idx;
}
SSF.load = load_entry;
S
SheetJS 已提交
997
SSF._table = table_fmt;
S
SheetJS 已提交
998 999 1000 1001 1002
SSF.get_table = function get_table()/*:SSFTable*/ { return table_fmt; };
SSF.load_table = function load_table(tbl/*:SSFTable*/)/*:void*/ {
	for(var i=0; i!=0x0188; ++i)
		if(tbl[i] !== undefined) load_entry(tbl[i], i);
};
S
SheetJS 已提交
1003
SSF.init_table = init_table;
S
SheetJS 已提交
1004
SSF.format = format;
S
SheetJS 已提交
1005 1006 1007
};
make_ssf(SSF);
/* map from xlml named formats to SSF TODO: localize */
S
SheetJS 已提交
1008
var XLMLFormatMap/*{[string]:string}*/ = ({
S
SheetJS 已提交
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
	"General Number": "General",
	"General Date": SSF._table[22],
	"Long Date": "dddd, mmmm dd, yyyy",
	"Medium Date": SSF._table[15],
	"Short Date": SSF._table[14],
	"Long Time": SSF._table[19],
	"Medium Time": SSF._table[18],
	"Short Time": SSF._table[20],
	"Currency": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
	"Fixed": SSF._table[2],
	"Standard": SSF._table[4],
	"Percent": SSF._table[10],
	"Scientific": SSF._table[11],
	"Yes/No": '"Yes";"Yes";"No";@',
	"True/False": '"True";"True";"False";@',
	"On/Off": '"Yes";"Yes";"No";@'
S
SheetJS 已提交
1025
}/*:any*/);
S
SheetJS 已提交
1026

S
SheetJS 已提交
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
/* dateNF parse TODO: move to SSF */
var dateNFregex = /[dD]+|[mM]+|[yYeE]+|[Hh]+|[Ss]+/g;
function dateNF_regex(dateNF/*:string|number*/)/*:RegExp*/ {
	var fmt = typeof dateNF == "number" ? SSF._table[dateNF] : dateNF;
	fmt = fmt.replace(dateNFregex, "(\\d+)");
	return new RegExp("^" + fmt + "$");
}
function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/*:string*/ {
	var Y = -1, m = -1, d = -1, H = -1, M = -1, S = -1;
	(dateNF.match(dateNFregex)||[]).forEach(function(n, i) {
		var v = parseInt(match[i+1], 10);
		switch(n.toLowerCase().charAt(0)) {
			case 'y': Y = v; break; case 'd': d = v; break;
			case 'h': H = v; break; case 's': S = v; break;
			case 'm': if(H >= 0) M = v; else m = v; break;
		}
	});
	if(S >= 0 && M == -1 && m >= 0) { M = m; m = -1; }
	var datestr = (("" + (Y>=0?Y: new Date().getFullYear())).slice(-4) + "-" + ("00" + (m>=1?m:1)).slice(-2) + "-" + ("00" + (d>=1?d:1)).slice(-2));
	if(datestr.length == 7) datestr = "0" + datestr;
	if(datestr.length == 8) datestr = "20" + datestr;
	var timestr = (("00" + (H>=0?H:0)).slice(-2) + ":" + ("00" + (M>=0?M:0)).slice(-2) + ":" + ("00" + (S>=0?S:0)).slice(-2));
	if(H == -1 && M == -1 && S == -1) return datestr;
	if(Y == -1 && m == -1 && d == -1) return timestr;
	return datestr + "T" + timestr;
}

S
SheetJS 已提交
1054
var DO_NOT_EXPORT_CFB = true;
S
SheetJS 已提交
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
/*::
declare var Base64:any;
declare var ReadShift:any;
declare var CheckField:any;
declare var prep_blob:any;
declare var __readUInt32LE:any;
declare var __readInt32LE:any;
declare var __toBuffer:any;
declare var __utf16le:any;
declare var bconcat:any;
declare var s2a:any;
declare var chr0:any;
declare var chr1:any;
*/
/* cfb.js (C) 2013-present SheetJS -- http://sheetjs.com */
S
SheetJS 已提交
1070 1071 1072
/* vim: set ts=2: */
/*jshint eqnull:true */

S
SheetJS 已提交
1073
/*::
S
SheetJS 已提交
1074 1075 1076 1077 1078 1079
declare var DO_NOT_EXPORT_CFB:?boolean;
type SectorEntry = {
	name?:string;
	nodes?:Array<number>;
	data:RawBytes;
};
S
SheetJS 已提交
1080
type SectorList = {
S
SheetJS 已提交
1081
	[k:string|number]:SectorEntry;
S
SheetJS 已提交
1082
	name:?string;
S
SheetJS 已提交
1083
	fat_addrs:Array<number>;
S
SheetJS 已提交
1084 1085
	ssz:number;
}
S
SheetJS 已提交
1086
type CFBFiles = {[n:string]:CFBEntry};
S
SheetJS 已提交
1087
*/
S
SheetJS 已提交
1088 1089
/* [MS-CFB] v20130118 */
var CFB = (function _CFB(){
S
SheetJS 已提交
1090
var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
S
SheetJS 已提交
1091
exports.version = '0.12.1';
S
SheetJS 已提交
1092
function parse(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/ {
S
SheetJS 已提交
1093 1094 1095 1096 1097 1098 1099 1100
var mver = 3; // major version
var ssz = 512; // sector size
var nmfs = 0; // number of mini FAT sectors
var ndfs = 0; // number of DIFAT sectors
var dir_start = 0; // first directory sector location
var minifat_start = 0; // first mini FAT sector location
var difat_start = 0; // first mini FAT sector location

S
SheetJS 已提交
1101
var fat_addrs/*:Array<number>*/ = []; // locations of FAT sectors
S
SheetJS 已提交
1102 1103

/* [MS-CFB] 2.2 Compound File Header */
S
SheetJS 已提交
1104
var blob/*:CFBlob*/ = /*::(*/file.slice(0,512)/*:: :any)*/;
S
SheetJS 已提交
1105 1106 1107 1108 1109 1110 1111
prep_blob(blob, 0);

/* major version */
var mv = check_get_mver(blob);
mver = mv[0];
switch(mver) {
	case 3: ssz = 512; break; case 4: ssz = 4096; break;
S
SheetJS 已提交
1112
	default: throw new Error("Major Version: Expected 3 or 4 saw " + mver);
S
SheetJS 已提交
1113 1114 1115
}

/* reprocess header */
S
SheetJS 已提交
1116
if(ssz !== 512) { blob = /*::(*/file.slice(0,ssz)/*:: :any)*/; prep_blob(blob, 28 /* blob.l */); }
S
SheetJS 已提交
1117
/* Save header for final object */
S
SheetJS 已提交
1118
var header/*:RawBytes*/ = file.slice(0,ssz);
S
SheetJS 已提交
1119 1120 1121 1122

check_shifts(blob, mver);

// Number of Directory Sectors
S
SheetJS 已提交
1123
var nds/*:number*/ = blob.read_shift(4, 'i');
S
SheetJS 已提交
1124
if(mver === 3 && nds !== 0) throw new Error('# Directory Sectors: Expected 0 saw ' + nds);
S
SheetJS 已提交
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151

// Number of FAT Sectors
//var nfs = blob.read_shift(4, 'i');
blob.l += 4;

// First Directory Sector Location
dir_start = blob.read_shift(4, 'i');

// Transaction Signature
blob.l += 4;

// Mini Stream Cutoff Size
blob.chk('00100000', 'Mini Stream Cutoff Size: ');

// First Mini FAT Sector Location
minifat_start = blob.read_shift(4, 'i');

// Number of Mini FAT Sectors
nmfs = blob.read_shift(4, 'i');

// First DIFAT sector location
difat_start = blob.read_shift(4, 'i');

// Number of DIFAT Sectors
ndfs = blob.read_shift(4, 'i');

// Grab FAT Sector Locations
S
SheetJS 已提交
1152
for(var q = -1, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */
S
SheetJS 已提交
1153 1154 1155 1156 1157 1158
	q = blob.read_shift(4, 'i');
	if(q<0) break;
	fat_addrs[j] = q;
}

/** Break the file up into sectors */
S
SheetJS 已提交
1159
var sectors/*:Array<RawBytes>*/ = sectorify(file, ssz);
S
SheetJS 已提交
1160 1161 1162 1163

sleuth_fat(difat_start, ndfs, sectors, ssz, fat_addrs);

/** Chains */
S
SheetJS 已提交
1164
var sector_list/*:SectorList*/ = make_sector_list(sectors, dir_start, fat_addrs, ssz);
S
SheetJS 已提交
1165 1166 1167 1168 1169 1170 1171 1172

sector_list[dir_start].name = "!Directory";
if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
sector_list[fat_addrs[0]].name = "!FAT";
sector_list.fat_addrs = fat_addrs;
sector_list.ssz = ssz;

/* [MS-CFB] 2.6.1 Compound File Directory Entry */
S
SheetJS 已提交
1173
var files/*:CFBFiles*/ = {}, Paths/*:Array<string>*/ = [], FileIndex/*:CFBFileIndex*/ = [], FullPaths/*:Array<string>*/ = [], FullPathDir = {};
S
SheetJS 已提交
1174 1175 1176 1177
read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex);

build_full_paths(FileIndex, FullPathDir, FullPaths, Paths);

S
SheetJS 已提交
1178
var root_name/*:string*/ = Paths.shift();
S
SheetJS 已提交
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192

/* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */
var find_path = make_find_path(FullPaths, Paths, FileIndex, files, root_name);

return {
	raw: {header: header, sectors: sectors},
	FileIndex: FileIndex,
	FullPaths: FullPaths,
	FullPathDir: FullPathDir,
	find: find_path
};
} // parse

/* [MS-CFB] 2.2 Compound File Header -- read up to major version */
S
SheetJS 已提交
1193
function check_get_mver(blob/*:CFBlob*/)/*:[number, number]*/ {
S
SheetJS 已提交
1194 1195 1196 1197 1198 1199 1200
	// header signature 8
	blob.chk(HEADER_SIGNATURE, 'Header Signature: ');

	// clsid 16
	blob.chk(HEADER_CLSID, 'CLSID: ');

	// minor version 2
S
SheetJS 已提交
1201
	var mver/*:number*/ = blob.read_shift(2, 'u');
S
SheetJS 已提交
1202 1203 1204

	return [blob.read_shift(2,'u'), mver];
}
S
SheetJS 已提交
1205
function check_shifts(blob/*:CFBlob*/, mver/*:number*/)/*:void*/ {
S
SheetJS 已提交
1206 1207 1208
	var shift = 0x09;

	// Byte Order
S
SheetJS 已提交
1209 1210
	//blob.chk('feff', 'Byte Order: '); // note: some writers put 0xffff
	blob.l += 2;
S
SheetJS 已提交
1211 1212 1213

	// Sector Shift
	switch((shift = blob.read_shift(2))) {
S
SheetJS 已提交
1214 1215 1216
		case 0x09: if(mver != 3) throw new Error('Sector Shift: Expected 9 saw ' + shift); break;
		case 0x0c: if(mver != 4) throw new Error('Sector Shift: Expected 12 saw ' + shift); break;
		default: throw new Error('Sector Shift: Expected 9 or 12 saw ' + shift);
S
SheetJS 已提交
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226
	}

	// Mini Sector Shift
	blob.chk('0600', 'Mini Sector Shift: ');

	// Reserved
	blob.chk('000000000000', 'Reserved: ');
}

/** Break the file up into sectors */
S
SheetJS 已提交
1227
function sectorify(file/*:RawBytes*/, ssz/*:number*/)/*:Array<RawBytes>*/ {
S
SheetJS 已提交
1228
	var nsectors = Math.ceil(file.length/ssz)-1;
S
SheetJS 已提交
1229
	var sectors/*:Array<RawBytes>*/ = [];
S
SheetJS 已提交
1230 1231 1232 1233 1234 1235
	for(var i=1; i < nsectors; ++i) sectors[i-1] = file.slice(i*ssz,(i+1)*ssz);
	sectors[nsectors-1] = file.slice(nsectors*ssz);
	return sectors;
}

/* [MS-CFB] 2.6.4 Red-Black Tree */
S
SheetJS 已提交
1236
function build_full_paths(FI/*:CFBFileIndex*/, FPD/*:CFBFullPathDir*/, FP/*:Array<string>*/, Paths/*:Array<string>*/)/*:void*/ {
S
SheetJS 已提交
1237
	var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length;
S
SheetJS 已提交
1238
	var dad/*:Array<number>*/ = [], q/*:Array<number>*/ = [];
S
SheetJS 已提交
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261

	for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; }

	for(; j < q.length; ++j) {
		i = q[j];
		L = FI[i].L; R = FI[i].R; C = FI[i].C;
		if(dad[i] === i) {
			if(L !== -1 /*NOSTREAM*/ && dad[L] !== L) dad[i] = dad[L];
			if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
		}
		if(C !== -1 /*NOSTREAM*/) dad[C] = i;
		if(L !== -1) { dad[L] = dad[i]; q.push(L); }
		if(R !== -1) { dad[R] = dad[i]; q.push(R); }
	}
	for(i=1; i !== pl; ++i) if(dad[i] === i) {
		if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
		else if(L !== -1 && dad[L] !== L) dad[i] = dad[L];
	}

	for(i=1; i < pl; ++i) {
		if(FI[i].type === 0 /* unknown */) continue;
		j = dad[i];
		if(j === 0) FP[i] = FP[0] + "/" + FP[i];
S
SheetJS 已提交
1262
		else while(j !== 0 && j !== dad[j]) {
S
SheetJS 已提交
1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276
			FP[i] = FP[j] + "/" + FP[i];
			j = dad[j];
		}
		dad[i] = 0;
	}

	FP[0] += "/";
	for(i=1; i < pl; ++i) {
		if(FI[i].type !== 2 /* stream */) FP[i] += "/";
		FPD[FP[i]] = FI[i];
	}
}

/* [MS-CFB] 2.6.4 */
S
SheetJS 已提交
1277 1278 1279
function make_find_path(FullPaths/*:Array<string>*/, Paths/*:Array<string>*/, FileIndex/*:CFBFileIndex*/, files/*:CFBFiles*/, root_name/*:string*/)/*:CFBFindPath*/ {
	var UCFullPaths/*:Array<string>*/ = [];
	var UCPaths/*:Array<string>*/ = [], i = 0;
S
SheetJS 已提交
1280 1281
	for(i = 0; i < FullPaths.length; ++i) UCFullPaths[i] = FullPaths[i].toUpperCase().replace(chr0,'').replace(chr1,'!');
	for(i = 0; i < Paths.length; ++i) UCPaths[i] = Paths[i].toUpperCase().replace(chr0,'').replace(chr1,'!');
S
SheetJS 已提交
1282 1283
	return function find_path(path/*:string*/)/*:?CFBEntry*/ {
		var k/*:boolean*/ = false;
S
SheetJS 已提交
1284 1285
		if(path.charCodeAt(0) === 47 /* "/" */) { k=true; path = root_name + path; }
		else k = path.indexOf("/") !== -1;
S
SheetJS 已提交
1286 1287
		var UCPath/*:string*/ = path.toUpperCase().replace(chr0,'').replace(chr1,'!');
		var w/*:number*/ = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath);
S
SheetJS 已提交
1288 1289 1290 1291 1292 1293 1294
		if(w === -1) return null;
		return k === true ? FileIndex[w] : files[Paths[w]];
	};
}

/** Chase down the rest of the DIFAT chain to build a comprehensive list
    DIFAT chains by storing the next sector number as the last 32 bytes */
S
SheetJS 已提交
1295 1296
function sleuth_fat(idx/*:number*/, cnt/*:number*/, sectors/*:Array<RawBytes>*/, ssz/*:number*/, fat_addrs)/*:void*/ {
	var q/*:number*/ = ENDOFCHAIN;
S
SheetJS 已提交
1297
	if(idx === ENDOFCHAIN) {
S
SheetJS 已提交
1298
		if(cnt !== 0) throw new Error("DIFAT chain shorter than expected");
S
SheetJS 已提交
1299 1300
	} else if(idx !== -1 /*FREESECT*/) {
		var sector = sectors[idx], m = (ssz>>>2)-1;
S
SheetJS 已提交
1301
		if(!sector) return;
S
SheetJS 已提交
1302 1303 1304 1305 1306 1307 1308 1309 1310
		for(var i = 0; i < m; ++i) {
			if((q = __readInt32LE(sector,i*4)) === ENDOFCHAIN) break;
			fat_addrs.push(q);
		}
		sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs);
	}
}

/** Follow the linked list of sectors for a given starting point */
S
SheetJS 已提交
1311
function get_sector_list(sectors/*:Array<RawBytes>*/, start/*:number*/, fat_addrs/*:Array<number>*/, ssz/*:number*/, chkd/*:?Array<boolean>*/)/*:SectorEntry*/ {
S
SheetJS 已提交
1312
	var sl = sectors.length;
S
SheetJS 已提交
1313 1314 1315
	var buf/*:Array<number>*/ = [], buf_chain/*:Array<any>*/ = [];
	if(!chkd) chkd = [];
	var modulus = ssz - 1, j = 0, jj = 0;
S
SheetJS 已提交
1316 1317 1318 1319 1320 1321
	for(j=start; j>=0;) {
		chkd[j] = true;
		buf[buf.length] = j;
		buf_chain.push(sectors[j]);
		var addr = fat_addrs[Math.floor(j*4/ssz)];
		jj = ((j*4) & modulus);
S
SheetJS 已提交
1322
		if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz);
S
SheetJS 已提交
1323
		if(!sectors[addr]) break;
S
SheetJS 已提交
1324 1325 1326 1327 1328 1329
		j = __readInt32LE(sectors[addr], jj);
	}
	return {nodes: buf, data:__toBuffer([buf_chain])};
}

/** Chase down the sector linked lists */
S
SheetJS 已提交
1330 1331 1332 1333
function make_sector_list(sectors/*:Array<RawBytes>*/, dir_start/*:number*/, fat_addrs/*:Array<number>*/, ssz/*:number*/)/*:SectorList*/ {
	var sl = sectors.length, sector_list/*:SectorList*/ = ([]/*:any*/);
	var chkd/*:Array<boolean>*/ = [], buf/*:Array<number>*/ = [], buf_chain/*:Array<RawBytes>*/ = [];
	var modulus = ssz - 1, i=0, j=0, k=0, jj=0;
S
SheetJS 已提交
1334
	for(i=0; i < sl; ++i) {
S
SheetJS 已提交
1335
		buf = ([]/*:Array<number>*/);
S
SheetJS 已提交
1336
		k = (i + dir_start); if(k >= sl) k-=sl;
S
SheetJS 已提交
1337
		if(chkd[k]) continue;
S
SheetJS 已提交
1338 1339 1340 1341 1342
		buf_chain = [];
		for(j=k; j>=0;) {
			chkd[j] = true;
			buf[buf.length] = j;
			buf_chain.push(sectors[j]);
S
SheetJS 已提交
1343
			var addr/*:number*/ = fat_addrs[Math.floor(j*4/ssz)];
S
SheetJS 已提交
1344
			jj = ((j*4) & modulus);
S
SheetJS 已提交
1345
			if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz);
S
SheetJS 已提交
1346
			if(!sectors[addr]) break;
S
SheetJS 已提交
1347 1348
			j = __readInt32LE(sectors[addr], jj);
		}
S
SheetJS 已提交
1349
		sector_list[k] = ({nodes: buf, data:__toBuffer([buf_chain])}/*:SectorEntry*/);
S
SheetJS 已提交
1350 1351 1352 1353 1354
	}
	return sector_list;
}

/* [MS-CFB] 2.6.1 Compound File Directory Entry */
S
SheetJS 已提交
1355
function read_directory(dir_start/*:number*/, sector_list/*:SectorList*/, sectors/*:Array<RawBytes>*/, Paths/*:Array<string>*/, nmfs, files, FileIndex) {
S
SheetJS 已提交
1356 1357
	var minifat_store = 0, pl = (Paths.length?2:0);
	var sector = sector_list[dir_start].data;
S
SheetJS 已提交
1358
	var i = 0, namelen = 0, name;
S
SheetJS 已提交
1359
	for(; i < sector.length; i+= 128) {
S
SheetJS 已提交
1360
		var blob/*:CFBlob*/ = /*::(*/sector.slice(i, i+128)/*:: :any)*/;
S
SheetJS 已提交
1361 1362 1363 1364
		prep_blob(blob, 64);
		namelen = blob.read_shift(2);
		name = __utf16le(blob,0,namelen-pl);
		Paths.push(name);
S
SheetJS 已提交
1365
		var o/*:CFBEntry*/ = ({
S
SheetJS 已提交
1366 1367 1368 1369 1370 1371 1372
			name:  name,
			type:  blob.read_shift(1),
			color: blob.read_shift(1),
			L:     blob.read_shift(4, 'i'),
			R:     blob.read_shift(4, 'i'),
			C:     blob.read_shift(4, 'i'),
			clsid: blob.read_shift(16),
S
SheetJS 已提交
1373 1374 1375 1376 1377 1378 1379 1380
			state: blob.read_shift(4, 'i'),
			start: 0,
			size: 0
		});
		var ctime/*:number*/ = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2);
		if(ctime !== 0) o.ct = read_date(blob, blob.l-8);
		var mtime/*:number*/ = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2);
		if(mtime !== 0) o.mt = read_date(blob, blob.l-8);
S
SheetJS 已提交
1381 1382
		o.start = blob.read_shift(4, 'i');
		o.size = blob.read_shift(4, 'i');
S
SheetJS 已提交
1383
		if(o.size < 0 && o.start < 0) { o.size = o.type = 0; o.start = ENDOFCHAIN; o.name = ""; }
S
SheetJS 已提交
1384 1385 1386 1387 1388 1389 1390 1391
		if(o.type === 5) { /* root */
			minifat_store = o.start;
			if(nmfs > 0 && minifat_store !== ENDOFCHAIN) sector_list[minifat_store].name = "!StreamData";
			/*minifat_size = o.size;*/
		} else if(o.size >= 4096 /* MSCSZ */) {
			o.storage = 'fat';
			if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz);
			sector_list[o.start].name = o.name;
S
SheetJS 已提交
1392
			o.content = (sector_list[o.start].data.slice(0,o.size)/*:any*/);
S
SheetJS 已提交
1393 1394 1395
			prep_blob(o.content, 0);
		} else {
			o.storage = 'minifat';
S
SheetJS 已提交
1396
			if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) {
S
SheetJS 已提交
1397
				o.content = (sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size)/*:any*/);
S
SheetJS 已提交
1398 1399 1400 1401 1402 1403 1404 1405
				prep_blob(o.content, 0);
			}
		}
		files[name] = o;
		FileIndex.push(o);
	}
}

S
SheetJS 已提交
1406
function read_date(blob/*:RawBytes|CFBlob*/, offset/*:number*/)/*:Date*/ {
S
SheetJS 已提交
1407 1408 1409
	return new Date(( ( (__readUInt32LE(blob,offset+4)/1e7)*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7 ) - 11644473600)*1000);
}

S
SheetJS 已提交
1410 1411 1412
var fs/*:: = require('fs'); */;
function readFileSync(filename/*:string*/, options/*:CFBReadOpts*/) {
	if(fs == null) fs = require('fs');
S
SheetJS 已提交
1413 1414 1415
	return parse(fs.readFileSync(filename), options);
}

S
SheetJS 已提交
1416 1417 1418 1419 1420
function readSync(blob/*:RawBytes|string*/, options/*:CFBReadOpts*/) {
	switch(options && options.type || "base64") {
		case "file": /*:: if(typeof blob !== 'string') throw "Must pass a filename when type='file'"; */return readFileSync(blob, options);
		case "base64": /*:: if(typeof blob !== 'string') throw "Must pass a base64-encoded binary string when type='file'"; */return parse(s2a(Base64.decode(blob)), options);
		case "binary": /*:: if(typeof blob !== 'string') throw "Must pass a binary string when type='file'"; */return parse(s2a(blob), options);
S
SheetJS 已提交
1421
	}
S
SheetJS 已提交
1422
	return parse(/*::typeof blob == 'string' ? new Buffer(blob, 'utf-8') : */blob, options);
S
SheetJS 已提交
1423 1424
}

S
SheetJS 已提交
1425 1426 1427
function find(cfb/*:CFBContainer*/, path/*:string*/)/*:?CFBEntry*/ {
	return cfb.find(path);
}
S
SheetJS 已提交
1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452
/** CFB Constants */
var MSSZ = 64; /* Mini Sector Size = 1<<6 */
//var MSCSZ = 4096; /* Mini Stream Cutoff Size */
/* 2.1 Compound File Sector Numbers and Types */
var ENDOFCHAIN = -2;
/* 2.2 Compound File Header */
var HEADER_SIGNATURE = 'd0cf11e0a1b11ae1';
var HEADER_CLSID = '00000000000000000000000000000000';
var consts = {
	/* 2.1 Compund File Sector Numbers and Types */
	MAXREGSECT: -6,
	DIFSECT: -4,
	FATSECT: -3,
	ENDOFCHAIN: ENDOFCHAIN,
	FREESECT: -1,
	/* 2.2 Compound File Header */
	HEADER_SIGNATURE: HEADER_SIGNATURE,
	HEADER_MINOR_VERSION: '3e00',
	MAXREGSID: -6,
	NOSTREAM: -1,
	HEADER_CLSID: HEADER_CLSID,
	/* 2.6.1 Compound File Directory Entry */
	EntryTypes: ['unknown','storage','stream','lockbytes','property','root']
};

S
SheetJS 已提交
1453
exports.find = find;
S
SheetJS 已提交
1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469
exports.read = readSync;
exports.parse = parse;
exports.utils = {
	ReadShift: ReadShift,
	CheckField: CheckField,
	prep_blob: prep_blob,
	bconcat: bconcat,
	consts: consts
};

return exports;
})();

if(typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO_NOT_EXPORT_CFB === 'undefined') { module.exports = CFB; }
function isval(x/*:?any*/)/*:boolean*/ { return x !== undefined && x !== null; }

S
SheetJS 已提交
1470
function keys(o/*:any*/)/*:Array<any>*/ { return Object.keys(o); }
S
SheetJS 已提交
1471

S
SheetJS 已提交
1472 1473
function evert_key(obj/*:any*/, key/*:string*/)/*:EvertType*/ {
	var o = ([]/*:any*/), K = keys(obj);
S
SheetJS 已提交
1474 1475 1476 1477
	for(var i = 0; i !== K.length; ++i) o[obj[K[i]][key]] = K[i];
	return o;
}

S
SheetJS 已提交
1478 1479
function evert(obj/*:any*/)/*:EvertType*/ {
	var o = ([]/*:any*/), K = keys(obj);
S
SheetJS 已提交
1480 1481 1482 1483
	for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = K[i];
	return o;
}

S
SheetJS 已提交
1484 1485
function evert_num(obj/*:any*/)/*:EvertNumType*/ {
	var o = ([]/*:any*/), K = keys(obj);
S
SheetJS 已提交
1486 1487 1488 1489
	for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = parseInt(K[i],10);
	return o;
}

S
SheetJS 已提交
1490 1491
function evert_arr(obj/*:any*/)/*:EvertArrType*/ {
	var o/*:EvertArrType*/ = ([]/*:any*/), K = keys(obj);
S
SheetJS 已提交
1492 1493 1494 1495 1496 1497 1498
	for(var i = 0; i !== K.length; ++i) {
		if(o[obj[K[i]]] == null) o[obj[K[i]]] = [];
		o[obj[K[i]]].push(K[i]);
	}
	return o;
}

S
SheetJS 已提交
1499 1500
var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
var dnthresh = basedate.getTime() + (new Date().getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
S
SheetJS 已提交
1501 1502
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
	var epoch = v.getTime();
S
SheetJS 已提交
1503
	if(date1904) epoch -= 1462*24*60*60*1000;
S
SheetJS 已提交
1504
	return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
S
SheetJS 已提交
1505
}
S
SheetJS 已提交
1506
function numdate(v/*:number*/)/*:Date*/ {
S
SheetJS 已提交
1507 1508 1509
	var out = new Date();
	out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh);
	return out;
S
SheetJS 已提交
1510
}
S
SheetJS 已提交
1511

1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538
/* ISO 8601 Duration */
function parse_isodur(s) {
	var sec = 0, mt = 0, time = false;
	var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
	if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
	for(var i = 1; i != m.length; ++i) {
		if(!m[i]) continue;
		mt = 1;
		if(i > 3) time = true;
		switch(m[i].substr(m[i].length-1)) {
			case 'Y':
				throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1));
			case 'D': mt *= 24;
				/* falls through */
			case 'H': mt *= 60;
				/* falls through */
			case 'M':
				if(!time) throw new Error("Unsupported ISO Duration Field: M");
				else mt *= 60;
				/* falls through */
			case 'S': break;
		}
		sec += mt * parseInt(m[i], 10);
	}
	return sec;
}

S
SheetJS 已提交
1539
var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
1540
if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
S
SheetJS 已提交
1541
var good_pd = good_pd_date.getFullYear() == 2017;
1542
/* parses a date as a local date */
S
SheetJS 已提交
1543
function parseDate(str/*:string|Date*/, fixdate/*:?number*/)/*:Date*/ {
1544
	var d = new Date(str);
S
SheetJS 已提交
1545 1546 1547 1548 1549 1550
	if(good_pd) {
		/*:: if(fixdate == null) fixdate = 0; */
		if(fixdate > 0) d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
		else if(fixdate < 0) d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000);
		return d;
	}
S
SheetJS 已提交
1551
	if(str instanceof Date) return str;
1552 1553 1554 1555 1556
	if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
		var s = d.getFullYear();
		if(str.indexOf("" + s) > -1) return d;
		d.setFullYear(d.getFullYear() + 100); return d;
	}
S
SheetJS 已提交
1557
	var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
1558 1559 1560
	var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
	if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000);
	return out;
S
SheetJS 已提交
1561 1562
}

S
SheetJS 已提交
1563 1564 1565 1566 1567 1568
function cc2str(arr/*:Array<number>*/)/*:string*/ {
	var o = "";
	for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
	return o;
}

1569 1570 1571 1572 1573 1574
function str2cc(str) {
	var o = [];
	for(var i = 0; i != str.length; ++i) o.push(str.charCodeAt(i));
	return o;
}

S
SheetJS 已提交
1575
function dup(o/*:any*/)/*:any*/ {
S
SheetJS 已提交
1576
	if(typeof JSON != 'undefined' && !Array.isArray(o)) return JSON.parse(JSON.stringify(o));
1577
	if(typeof o != 'object' || o == null) return o;
S
SheetJS 已提交
1578 1579 1580 1581 1582 1583
	var out = {};
	for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]);
	return out;
}

function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; }
S
SheetJS 已提交
1584 1585

/* TODO: stress test */
S
SheetJS 已提交
1586 1587 1588
function fuzzynum(s/*:string*/)/*:number*/ {
	var v/*:number*/ = Number(s);
	if(!isNaN(v)) return v;
1589 1590 1591 1592 1593
	var wt = 1;
	var ss = s.replace(/([\d]),([\d])/g,"$1$2").replace(/[$]/g,"").replace(/[%]/g, function() { wt *= 100; return "";});
	if(!isNaN(v = Number(ss))) return v / wt;
	ss = ss.replace(/[(](.*)[)]/,function($$, $1) { wt = -wt; return $1;});
	if(!isNaN(v = Number(ss))) return v / wt;
S
SheetJS 已提交
1594 1595
	return v;
}
S
SheetJS 已提交
1596 1597 1598 1599 1600 1601 1602
function fuzzydate(s/*:string*/)/*:Date*/ {
	var o = new Date(s), n = new Date(NaN);
	var y = o.getYear(), m = o.getMonth(), d = o.getDate();
	if(isNaN(d)) return n;
	if(y < 0 || y > 8099) return n;
	if((m > 0 || d > 1) && y != 101) return o;
	if(s.toLowerCase().match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) return o;
1603
	if(s.match(/[^-0-9:,\/\\]/)) return o;
S
SheetJS 已提交
1604 1605 1606
	return n;
}

1607 1608 1609 1610 1611 1612 1613
var safe_split_regex = "abacaba".split(/(:?b)/i).length == 5;
function split_regex(str/*:string*/, re, def/*:string*/)/*:Array<string>*/ {
	if(safe_split_regex || typeof re == "string") return str.split(re);
	var p = str.split(re), o = [p[0]];
	for(var i = 1; i < p.length; ++i) { o.push(def); o.push(p[i]); }
	return o;
}
S
SheetJS 已提交
1614
function getdatastr(data)/*:?string*/ {
S
SheetJS 已提交
1615
	if(!data) return null;
S
SheetJS 已提交
1616 1617 1618 1619
	if(data.data) return debom(data.data);
	if(data.asNodeBuffer && has_buf) return debom(data.asNodeBuffer().toString('binary'));
	if(data.asBinary) return debom(data.asBinary());
	if(data._data && data._data.getContent) return debom(cc2str(Array.prototype.slice.call(data._data.getContent(),0)));
S
SheetJS 已提交
1620 1621 1622
	return null;
}

S
SheetJS 已提交
1623 1624 1625 1626
function getdatabin(data) {
	if(!data) return null;
	if(data.data) return char_codes(data.data);
	if(data.asNodeBuffer && has_buf) return data.asNodeBuffer();
1627 1628 1629 1630 1631
	if(data._data && data._data.getContent) {
		var o = data._data.getContent();
		if(typeof o == "string") return str2cc(o);
		return Array.prototype.slice.call(o);
	}
S
SheetJS 已提交
1632 1633 1634
	return null;
}

1635
function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getdatabin(data) : getdatastr(data); }
S
SheetJS 已提交
1636

S
SheetJS 已提交
1637
/* Part 2 Section 10.1.2 "Mapping Content Types" Names are case-insensitive */
1638
/* OASIS does not comment on filename case sensitivity */
S
SheetJS 已提交
1639
function safegetzipfile(zip, file/*:string*/) {
S
SheetJS 已提交
1640 1641 1642 1643 1644 1645
	var k = keys(zip.files);
	var f = file.toLowerCase(), g = f.replace(/\//g,'\\');
	for(var i=0; i<k.length; ++i) {
		var n = k[i].toLowerCase();
		if(f == n || g == n) return zip.files[k[i]];
	}
S
SheetJS 已提交
1646 1647 1648
	return null;
}

S
SheetJS 已提交
1649
function getzipfile(zip, file/*:string*/) {
S
SheetJS 已提交
1650 1651 1652 1653 1654
	var o = safegetzipfile(zip, file);
	if(o == null) throw new Error("Cannot find file " + file + " in zip");
	return o;
}

S
SheetJS 已提交
1655
function getzipdata(zip, file/*:string*/, safe/*:?boolean*/) {
S
SheetJS 已提交
1656 1657 1658 1659 1660
	if(!safe) return getdata(getzipfile(zip, file));
	if(!file) return null;
	try { return getzipdata(zip, file); } catch(e) { return null; }
}

S
SheetJS 已提交
1661 1662 1663 1664 1665 1666
function getzipstr(zip, file/*:string*/, safe/*:?boolean*/)/*:?string*/ {
	if(!safe) return getdatastr(getzipfile(zip, file));
	if(!file) return null;
	try { return getzipstr(zip, file); } catch(e) { return null; }
}

S
SheetJS 已提交
1667
var _fs, jszip;
S
SheetJS 已提交
1668
/*:: declare var JSZip:any; */
S
SheetJS 已提交
1669
/*global JSZip:true */
S
SheetJS 已提交
1670 1671 1672
if(typeof JSZip !== 'undefined') jszip = JSZip;
if (typeof exports !== 'undefined') {
	if (typeof module !== 'undefined' && module.exports) {
S
SheetJS 已提交
1673
		if(typeof jszip === 'undefined') jszip = require('./jszip.js');
S
SheetJS 已提交
1674
		try { _fs = require('fs'); } catch(e) { }
S
SheetJS 已提交
1675 1676
	}
}
1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688

function resolve_path(path/*:string*/, base/*:string*/)/*:string*/ {
	var result = base.split('/');
	if(base.slice(-1) != "/") result.pop(); // folder path
	var target = path.split('/');
	while (target.length !== 0) {
		var step = target.shift();
		if (step === '..') result.pop();
		else if (step !== '.') result.push(step);
	}
	return result.join('/');
}
S
SheetJS 已提交
1689
var attregexg=/([^"\s?>\/]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
1690
var tagregex=/<[\/\?]?[a-zA-Z0-9:]+(?:\s+[^"\s?>\/]+=(?:"[^"]*"|'[^']*'|[^'">\s]+))*\s?[\/\?]?>/g;
S
SheetJS 已提交
1691
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
S
SheetJS 已提交
1692
function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/)/*:any*/ {
S
SheetJS 已提交
1693
	var z = ({}/*:any*/);
S
SheetJS 已提交
1694 1695 1696 1697
	var eq = 0, c = 0;
	for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
	if(!skip_root) z[0] = tag.substr(0, eq);
	if(eq === tag.length) return z;
S
SheetJS 已提交
1698
	var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1;
S
SheetJS 已提交
1699 1700 1701
	if(m) for(i = 0; i != m.length; ++i) {
		cc = m[i];
		for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
S
SheetJS 已提交
1702 1703 1704
		q = cc.substr(0,c);
		quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0;
		v = cc.substring(c+1+quot, cc.length-quot);
S
SheetJS 已提交
1705
		for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
1706
		if(j===q.length) {
1707
			if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_")); // from ods
1708 1709 1710 1711
			z[q] = v;
		}
		else {
			var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1);
1712
			if(z[k] && q.substr(j-3,3) == "ext") continue; // from ods
1713 1714
			z[k] = v;
		}
S
SheetJS 已提交
1715 1716 1717
	}
	return z;
}
S
SheetJS 已提交
1718
function strip_ns(x/*:string*/)/*:string*/ { return x.replace(nsregex2, "<$1"); }
S
SheetJS 已提交
1719 1720 1721 1722 1723 1724 1725 1726 1727

var encodings = {
	'&quot;': '"',
	'&apos;': "'",
	'&gt;': '>',
	'&lt;': '<',
	'&amp;': '&'
};
var rencoding = evert(encodings);
S
SheetJS 已提交
1728
//var rencstr = "&<>'\"".split("");
S
SheetJS 已提交
1729 1730

// TODO: CP remap (need to read file version to determine OS)
S
SheetJS 已提交
1731
var unescapexml/*:StringConv*/ = (function() {
1732
	/* 22.4.2.4 bstr (Basic String) */
1733
	var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/g, coderegex = /_x([\da-fA-F]{4})_/g;
S
SheetJS 已提交
1734
	return function unescapexml(text/*:string*/)/*:string*/ {
1735 1736 1737 1738
		var s = text + '', i = s.indexOf("<![CDATA[");
		if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
		var j = s.indexOf("]]>");
		return unescapexml(s.slice(0, i)) + s.slice(i+9,j) + unescapexml(s.slice(j+3));
S
SheetJS 已提交
1739 1740 1741 1742
	};
})();

var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
1743
function escapexml(text/*:string*/, xml/*:?boolean*/)/*:string*/{
S
SheetJS 已提交
1744
	var s = text + '';
1745
	return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";});
S
SheetJS 已提交
1746
}
S
SheetJS 已提交
1747
function escapexmltag(text/*:string*/)/*:string*/{ return escapexml(text).replace(/ /g,"_x0020_"); }
S
SheetJS 已提交
1748

S
SheetJS 已提交
1749
var htmlcharegex = /[\u0000-\u001f]/g;
1750 1751
function escapehtml(text){
	var s = text + '';
S
SheetJS 已提交
1752
	return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; });
1753 1754
}

S
SheetJS 已提交
1755
/* TODO: handle codepages */
S
SheetJS 已提交
1756
var xlml_fixstr/*:StringConv*/ = (function() {
S
SheetJS 已提交
1757
	var entregex = /&#(\d+);/g;
S
SheetJS 已提交
1758 1759
	function entrepl($$/*:string*/,$1/*:string*/)/*:string*/ { return String.fromCharCode(parseInt($1,10)); }
	return function xlml_fixstr(str/*:string*/)/*:string*/ { return str.replace(entregex,entrepl); };
S
SheetJS 已提交
1760
})();
S
SheetJS 已提交
1761 1762 1763
var xlml_unfixstr/*:StringConv*/ = (function() {
	return function xlml_unfixstr(str/*:string*/)/*:string*/ { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); };
})();
S
SheetJS 已提交
1764

S
SheetJS 已提交
1765
function parsexmlbool(value/*:any*/, tag/*:?string*/)/*:boolean*/ {
S
SheetJS 已提交
1766
	switch(value) {
S
SheetJS 已提交
1767
		case 1: case true: case '1': case 'true': case 'TRUE': return true;
S
SheetJS 已提交
1768 1769 1770 1771 1772
		/* case '0': case 'false': case 'FALSE':*/
		default: return false;
	}
}

S
SheetJS 已提交
1773
var utf8read/*:StringConv*/ = function utf8reada(orig) {
S
SheetJS 已提交
1774 1775 1776 1777 1778
	var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
	while (i < orig.length) {
		c = orig.charCodeAt(i++);
		if (c < 128) { out += String.fromCharCode(c); continue; }
		d = orig.charCodeAt(i++);
S
SheetJS 已提交
1779
		if (c>191 && c<224) { f = ((c & 31) << 6); f |= (d & 63); out += String.fromCharCode(f); continue; }
S
SheetJS 已提交
1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805
		e = orig.charCodeAt(i++);
		if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; }
		f = orig.charCodeAt(i++);
		w = (((c & 7) << 18) | ((d & 63) << 12) | ((e & 63) << 6) | (f & 63))-65536;
		out += String.fromCharCode(0xD800 + ((w>>>10)&1023));
		out += String.fromCharCode(0xDC00 + (w&1023));
	}
	return out;
};


if(has_buf) {
	var utf8readb = function utf8readb(data) {
		var out = new Buffer(2*data.length), w, i, j = 1, k = 0, ww=0, c;
		for(i = 0; i < data.length; i+=j) {
			j = 1;
			if((c=data.charCodeAt(i)) < 128) w = c;
			else if(c < 224) { w = (c&31)*64+(data.charCodeAt(i+1)&63); j=2; }
			else if(c < 240) { w=(c&15)*4096+(data.charCodeAt(i+1)&63)*64+(data.charCodeAt(i+2)&63); j=3; }
			else { j = 4;
				w = (c & 7)*262144+(data.charCodeAt(i+1)&63)*4096+(data.charCodeAt(i+2)&63)*64+(data.charCodeAt(i+3)&63);
				w -= 65536; ww = 0xD800 + ((w>>>10)&1023); w = 0xDC00 + (w&1023);
			}
			if(ww !== 0) { out[k++] = ww&255; out[k++] = ww>>>8; ww = 0; }
			out[k++] = w%256; out[k++] = w>>>8;
		}
S
SheetJS 已提交
1806
		return out.slice(0,k).toString('ucs2');
S
SheetJS 已提交
1807 1808 1809
	};
	var corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3";
	if(utf8read(corpus) == utf8readb(corpus)) utf8read = utf8readb;
S
SheetJS 已提交
1810
	// $FlowIgnore
S
SheetJS 已提交
1811 1812 1813 1814 1815 1816
	var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
	if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
}

// matches <foo>...</foo> extracts content
var matchtag = (function() {
S
SheetJS 已提交
1817 1818
	var mtcache/*:{[k:string]:RegExp}*/ = ({}/*:any*/);
	return function matchtag(f,g/*:?string*/)/*:RegExp*/ {
S
SheetJS 已提交
1819
		var t = f+"|"+(g||"");
S
SheetJS 已提交
1820
		if(mtcache[t]) return mtcache[t];
S
SheetJS 已提交
1821
		return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([\\s\\S]*?)</(?:\\w+:)?'+f+'>',((g||"")/*:any*/)));
S
SheetJS 已提交
1822 1823 1824 1825 1826 1827
	};
})();

var vtregex = (function(){ var vt_cache = {};
	return function vt_regex(bt) {
		if(vt_cache[bt] !== undefined) return vt_cache[bt];
1828
		return (vt_cache[bt] = new RegExp("<(?:vt:)?" + bt + ">([\\s\\S]*?)</(?:vt:)?" + bt + ">", 'g') );
S
SheetJS 已提交
1829
};})();
1830
var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^>]*)>([\s\S]*)</;
1831
function parseVector(data, opts) {
S
SheetJS 已提交
1832 1833 1834 1835
	var h = parsexmltag(data);

	var matches = data.match(vtregex(h.baseType))||[];
	var res = [];
1836 1837 1838 1839
	if(matches.length != h.size) {
		if(opts.WTF) throw new Error("unexpected vector length " + matches.length + " != " + h.size);
		return res;
	}
S
SheetJS 已提交
1840 1841
	matches.forEach(function(x) {
		var v = x.replace(vtvregex,"").match(vtmregex);
O
OliverZ 已提交
1842
		res.push({v:utf8read(v[2]), t:v[1]});
S
SheetJS 已提交
1843 1844 1845 1846 1847 1848 1849
	});
	return res;
}

var wtregex = /(^\s|\s$|\n)/;
function writetag(f,g) {return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>';}

S
SheetJS 已提交
1850 1851
function wxt_helper(h)/*:string*/ { return keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join(""); }
function writextag(f,g,h) { return '<' + f + (isval(h) /*:: && h */? wxt_helper(h) : "") + (isval(g) /*:: && g */? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';}
S
SheetJS 已提交
1852

S
SheetJS 已提交
1853
function write_w3cdtf(d/*:Date*/, t/*:?boolean*/)/*:string*/ { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } return ""; }
S
SheetJS 已提交
1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865

function write_vt(s) {
	switch(typeof s) {
		case 'string': return writextag('vt:lpwstr', s);
		case 'number': return writextag((s|0)==s?'vt:i4':'vt:r8', String(s));
		case 'boolean': return writextag('vt:bool',s?'true':'false');
	}
	if(s instanceof Date) return writextag('vt:filetime', write_w3cdtf(s));
	throw new Error("Unable to serialize " + s);
}

var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
S
SheetJS 已提交
1866
var XMLNS = ({
S
SheetJS 已提交
1867 1868 1869 1870 1871 1872 1873 1874 1875
	'dc': 'http://purl.org/dc/elements/1.1/',
	'dcterms': 'http://purl.org/dc/terms/',
	'dcmitype': 'http://purl.org/dc/dcmitype/',
	'mx': 'http://schemas.microsoft.com/office/mac/excel/2008/main',
	'r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
	'sjs': 'http://schemas.openxmlformats.org/package/2006/sheetjs/core-properties',
	'vt': 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes',
	'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
	'xsd': 'http://www.w3.org/2001/XMLSchema'
S
SheetJS 已提交
1876
}/*:any*/);
S
SheetJS 已提交
1877 1878 1879 1880 1881 1882 1883 1884

XMLNS.main = [
	'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
	'http://purl.oclc.org/ooxml/spreadsheetml/main',
	'http://schemas.microsoft.com/office/excel/2006/main',
	'http://schemas.microsoft.com/office/excel/2006/2'
];

S
SheetJS 已提交
1885 1886 1887 1888 1889
var XLMLNS = ({
	'o':    'urn:schemas-microsoft-com:office:office',
	'x':    'urn:schemas-microsoft-com:office:excel',
	'ss':   'urn:schemas-microsoft-com:office:spreadsheet',
	'dt':   'uuid:C2F41010-65B3-11d1-A29F-00AA00C14882',
S
SheetJS 已提交
1890 1891
	'mv':   'http://macVmlSchemaUri',
	'v':    'urn:schemas-microsoft-com:vml',
S
SheetJS 已提交
1892 1893
	'html': 'http://www.w3.org/TR/REC-html40'
}/*:any*/);
S
SheetJS 已提交
1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917
function read_double_le(b, idx/*:number*/)/*:number*/ {
	var s = 1 - 2 * (b[idx + 7] >>> 7);
	var e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 0x0f);
	var m = (b[idx+6]&0x0f);
	for(var i = 5; i >= 0; --i) m = m * 256 + b[idx + i];
	if(e == 0x7ff) return m == 0 ? s * Infinity : NaN;
	if(e == 0) e = -1022;
	else { e -= 1023; m += Math.pow(2,52); }
	return s * Math.pow(2, e - 52) * m;
}

function write_double_le(b, v/*:number*/, idx/*:number*/) {
	var bs = ((v < 0 || 1/v == -Infinity) ? 1 : 0) << 7, e = 0, m = 0;
	var av = bs ? -v : v;
	if(!isFinite(av)) { e = 0x7ff; m = isNaN(v) ? 0x6969 : 0; }
	else {
		e = Math.floor(Math.log(av) * Math.LOG2E);
		m = v * Math.pow(2, 52 - e);
		if(e <= -1023 && (!isFinite(m) || m < Math.pow(2,52))) { e = -1022; }
		else { m -= Math.pow(2,52); e+=1023; }
	}
	for(var i = 0; i <= 5; ++i, m/=256) b[idx + i] = m & 0xff;
	b[idx + 6] = ((e & 0x0f) << 4) | m & 0xf;
	b[idx + 7] = (e >> 4) | bs;
S
SheetJS 已提交
1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931
}

var __toBuffer, ___toBuffer;
__toBuffer = ___toBuffer = function toBuffer_(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; };
var __utf16le, ___utf16le;
__utf16le = ___utf16le = function utf16le_(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join(""); };
var __hexlify, ___hexlify;
__hexlify = ___hexlify = function hexlify_(b,s,l) { return b.slice(s,(s+l)).map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); };
var __utf8, ___utf8;
__utf8 = ___utf8 = function(b,s,e) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
var __lpstr, ___lpstr;
__lpstr = ___lpstr = function lpstr_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var __lpwstr, ___lpwstr;
__lpwstr = ___lpwstr = function lpwstr_(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
S
SheetJS 已提交
1932 1933 1934 1935
var __lpp4, ___lpp4;
__lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
var __8lpp4, ___8lpp4;
__8lpp4 = ___8lpp4 = function lpp4_8(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
S
SheetJS 已提交
1936
var __double, ___double;
S
SheetJS 已提交
1937
__double = ___double = function(b, idx) { return read_double_le(b, idx);};
S
SheetJS 已提交
1938 1939

var is_buf = function is_buf_a(a) { return Array.isArray(a); };
S
SheetJS 已提交
1940
if(has_buf/*:: && typeof Buffer != 'undefined'*/) {
S
SheetJS 已提交
1941 1942 1943 1944
	__utf16le = function utf16le_b(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e); };
	__hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
	__lpstr = function lpstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
	__lpwstr = function lpwstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
S
SheetJS 已提交
1945 1946
	__lpp4 = function lpp4_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);};
	__8lpp4 = function lpp4_8b(b,i) { if(!Buffer.isBuffer(b)) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);};
S
SheetJS 已提交
1947
	__utf8 = function utf8_b(b, s,e) { return b.toString('utf8',s,e); };
S
SheetJS 已提交
1948 1949
	__toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);};
	bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); };
S
SheetJS 已提交
1950
	__double = function double_(b,i) { if(Buffer.isBuffer(b)/*::&& b instanceof Buffer*/) return b.readDoubleLE(i); return ___double(b,i); };
S
SheetJS 已提交
1951 1952 1953 1954 1955 1956 1957 1958 1959
	is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); };
}

/* from js-xls */
if(typeof cptable !== 'undefined') {
	__utf16le = function(b,s,e) { return cptable.utils.decode(1200, b.slice(s,e)); };
	__utf8 = function(b,s,e) { return cptable.utils.decode(65001, b.slice(s,e)); };
	__lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";};
	__lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";};
S
SheetJS 已提交
1960 1961
	__lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";};
	__8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";};
S
SheetJS 已提交
1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972
}

var __readUInt8 = function(b, idx) { return b[idx]; };
var __readUInt16LE = function(b, idx) { return b[idx+1]*(1<<8)+b[idx]; };
var __readInt16LE = function(b, idx) { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; };
var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };

var ___unhexlify = function(s) { return s.match(/../g).map(function(x) { return parseInt(x,16);}); };
var __unhexlify = typeof Buffer !== "undefined" ? function(s) { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;

S
SheetJS 已提交
1973
function ReadShift(size/*:number*/, t/*:?string*/) {
S
SheetJS 已提交
1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985
	var o="", oI, oR, oo=[], w, vv, i, loc;
	switch(t) {
		case 'dbcs':
			loc = this.l;
			if(has_buf && Buffer.isBuffer(this)) o = this.slice(this.l, this.l+2*size).toString("utf16le");
			else for(i = 0; i != size; ++i) { o+=String.fromCharCode(__readUInt16LE(this, loc)); loc+=2; }
			size *= 2;
			break;

		case 'utf8': o = __utf8(this, this.l, this.l + size); break;
		case 'utf16le': size *= 2; o = __utf16le(this, this.l, this.l + size); break;

1986 1987 1988
		case 'wstr':
			if(typeof cptable !== 'undefined') o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l+2*size));
			else return ReadShift.call(this, size, 'dbcs');
S
SheetJS 已提交
1989
			size = 2 * size; break;
S
SheetJS 已提交
1990

S
SheetJS 已提交
1991 1992 1993 1994
		/* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */
		case 'lpstr': o = __lpstr(this, this.l); size = 5 + o.length; break;
		/* [MS-OLEDS] 2.1.5 LengthPrefixedUnicodeString */
		case 'lpwstr': o = __lpwstr(this, this.l); size = 5 + o.length; if(o[o.length-1] == '\u0000') size += 2; break;
S
SheetJS 已提交
1995 1996 1997 1998
		/* [MS-OFFCRYPTO] 2.1.2 Length-Prefixed Padded Unicode String (UNICODE-LP-P4) */
		case 'lpp4': size = 4 +  __readUInt32LE(this, this.l); o = __lpp4(this, this.l); if(size & 0x02) size += 2; break;
		/* [MS-OFFCRYPTO] 2.1.3 Length-Prefixed UTF-8 String (UTF-8-LP-P4) */
		case '8lpp4': size = 4 +  __readUInt32LE(this, this.l); o = __8lpp4(this, this.l); if(size & 0x03) size += 4 - (size & 0x03); break;
S
SheetJS 已提交
1999 2000 2001 2002

		case 'cstr': size = 0; o = "";
			while((w=__readUInt8(this, this.l + size++))!==0) oo.push(_getchar(w));
			o = oo.join(""); break;
S
SheetJS 已提交
2003
		case '_wstr': size = 0; o = "";
S
SheetJS 已提交
2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037
			while((w=__readUInt16LE(this,this.l +size))!==0){oo.push(_getchar(w));size+=2;}
			size+=2; o = oo.join(""); break;

		/* sbcs and dbcs support continue records in the SST way TODO codepages */
		case 'dbcs-cont': o = ""; loc = this.l;
			for(i = 0; i != size; ++i) {
				if(this.lens && this.lens.indexOf(loc) !== -1) {
					w = __readUInt8(this, loc);
					this.l = loc + 1;
					vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont');
					return oo.join("") + vv;
				}
				oo.push(_getchar(__readUInt16LE(this, loc)));
				loc+=2;
			} o = oo.join(""); size *= 2; break;

		case 'sbcs-cont': o = ""; loc = this.l;
			for(i = 0; i != size; ++i) {
				if(this.lens && this.lens.indexOf(loc) !== -1) {
					w = __readUInt8(this, loc);
					this.l = loc + 1;
					vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont');
					return oo.join("") + vv;
				}
				oo.push(_getchar(__readUInt8(this, loc)));
				loc+=1;
			} o = oo.join(""); break;

		default:
	switch(size) {
		case 1: oI = __readUInt8(this, this.l); this.l++; return oI;
		case 2: oI = (t === 'i' ? __readInt16LE : __readUInt16LE)(this, this.l); this.l += 2; return oI;
		case 4:
			if(t === 'i' || (this[this.l+3] & 0x80)===0) { oI = __readInt32LE(this, this.l); this.l += 4; return oI; }
S
SheetJS 已提交
2038
			else { oR = __readUInt32LE(this, this.l); this.l += 4; } return oR;
S
SheetJS 已提交
2039 2040 2041 2042 2043 2044 2045
		case 8: if(t === 'f') { oR = __double(this, this.l); this.l += 8; return oR; }
		/* falls through */
		case 16: o = __hexlify(this, this.l, size); break;
	}}
	this.l+=size; return o;
}

S
SheetJS 已提交
2046 2047 2048 2049
var __writeUInt16LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); };
var __writeUInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); b[idx+2] = ((val >>> 16) & 0xFF); b[idx+3] = ((val >>> 24) & 0xFF); };
var __writeInt32LE  = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); };

S
SheetJS 已提交
2050 2051
function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/) {
	var size = 0, i = 0;
S
SheetJS 已提交
2052
	if(f === 'dbcs') {
S
SheetJS 已提交
2053
		/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
S
SheetJS 已提交
2054
		for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i);
S
SheetJS 已提交
2055
		size = 2 * val.length;
S
SheetJS 已提交
2056
	} else if(f === 'sbcs') {
S
SheetJS 已提交
2057
		/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
S
SheetJS 已提交
2058 2059
		for(i = 0; i != val.length; ++i) this[this.l + i] = val.charCodeAt(i) & 0xFF;
		size = val.length;
S
SheetJS 已提交
2060
	} else /*:: if(typeof val === 'number') */ switch(t) {
S
SheetJS 已提交
2061 2062 2063 2064 2065
		case  1: size = 1; this[this.l] = val&0xFF; break;
		case  2: size = 2; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; break;
		case  3: size = 3; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; val >>>= 8; this[this.l+2] = val&0xFF; break;
		case  4: size = 4; __writeUInt32LE(this, val, this.l); break;
		case  8: size = 8; if(f === 'f') { write_double_le(this, val, this.l); break; }
S
SheetJS 已提交
2066 2067
		/* falls through */
		case 16: break;
S
SheetJS 已提交
2068
		case -4: size = 4; __writeInt32LE(this, val, this.l); break;
S
SheetJS 已提交
2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086
	}
	this.l += size; return this;
}

function CheckField(hexstr, fld) {
	var m = __hexlify(this,this.l,hexstr.length>>1);
	if(m !== hexstr) throw fld + 'Expected ' + hexstr + ' saw ' + m;
	this.l += hexstr.length>>1;
}

function prep_blob(blob, pos/*:number*/) {
	blob.l = pos;
	blob.read_shift = ReadShift;
	blob.chk = CheckField;
	blob.write_shift = WriteShift;
}

function parsenoop(blob, length/*:number*/) { blob.l += length; }
S
SheetJS 已提交
2087
function parsenooplog(blob, length/*:number*/) { if(typeof console != 'undefined') console.log(blob.slice(blob.l, blob.l + length)); blob.l += length; }
S
SheetJS 已提交
2088 2089 2090

function writenoop(blob, length/*:number*/) { blob.l += length; }

S
SheetJS 已提交
2091
function new_buf(sz/*:number*/)/*:Block*/ {
S
SheetJS 已提交
2092 2093 2094 2095 2096 2097
	var o = new_raw_buf(sz);
	prep_blob(o, 0);
	return o;
}

/* [MS-XLSB] 2.1.4 Record */
S
SheetJS 已提交
2098 2099
function recordhopper(data, cb/*:RecordHopperCB*/, opts/*:?any*/) {
	if(!data) return;
S
SheetJS 已提交
2100 2101
	var tmpbyte, cntbyte, length;
	prep_blob(data, data.l || 0);
2102 2103 2104
	var L = data.length, RT = 0, tgt = 0;
	while(data.l < L) {
		RT = data.read_shift(1);
S
SheetJS 已提交
2105 2106 2107 2108 2109
		if(RT & 0x80) RT = (RT & 0x7F) + ((data.read_shift(1) & 0x7F)<<7);
		var R = XLSBRecordEnum[RT] || XLSBRecordEnum[0xFFFF];
		tmpbyte = data.read_shift(1);
		length = tmpbyte & 0x7F;
		for(cntbyte = 1; cntbyte <4 && (tmpbyte & 0x80); ++cntbyte) length += ((tmpbyte = data.read_shift(1)) & 0x7F)<<(7*cntbyte);
2110
		tgt = data.l + length;
S
SheetJS 已提交
2111
		var d = R.f(data, length, opts);
S
SheetJS 已提交
2112
		data.l = tgt;
2113
		if(cb(d, R.n, RT)) return;
S
SheetJS 已提交
2114 2115 2116 2117
	}
}

/* control buffer usage for fixed-length buffers */
S
SheetJS 已提交
2118
function buf_array()/*:BufArray*/ {
S
SheetJS 已提交
2119 2120
	var bufs = [], blksz = 2048;
	var newblk = function ba_newblk(sz) {
S
SheetJS 已提交
2121
		var o/*:Block*/ = (new_buf(sz)/*:any*/);
S
SheetJS 已提交
2122 2123 2124 2125 2126 2127 2128
		prep_blob(o, 0);
		return o;
	};

	var curbuf = newblk(blksz);

	var endbuf = function ba_endbuf() {
S
SheetJS 已提交
2129
		if(!curbuf) return;
S
SheetJS 已提交
2130 2131 2132 2133 2134 2135
		if(curbuf.length > curbuf.l) curbuf = curbuf.slice(0, curbuf.l);
		if(curbuf.length > 0) bufs.push(curbuf);
		curbuf = null;
	};

	var next = function ba_next(sz) {
S
SheetJS 已提交
2136
		if(curbuf && sz < curbuf.length - curbuf.l) return curbuf;
S
SheetJS 已提交
2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147
		endbuf();
		return (curbuf = newblk(Math.max(sz+1, blksz)));
	};

	var end = function ba_end() {
		endbuf();
		return __toBuffer([bufs]);
	};

	var push = function ba_push(buf) { endbuf(); curbuf = buf; next(blksz); };

S
SheetJS 已提交
2148
	return ({ next:next, push:push, end:end, _bufs:bufs }/*:any*/);
S
SheetJS 已提交
2149 2150 2151
}

function write_record(ba/*:BufArray*/, type/*:string*/, payload, length/*:?number*/) {
S
SheetJS 已提交
2152 2153
	var t/*:number*/ = Number(evert_RE[type]), l;
	if(isNaN(t)) return; // TODO: throw something here?
S
SheetJS 已提交
2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169
	if(!length) length = XLSBRecordEnum[t].p || (payload||[]).length || 0;
	l = 1 + (t >= 0x80 ? 1 : 0) + 1 + length;
	if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l;
	var o = ba.next(l);
	if(t <= 0x7F) o.write_shift(1, t);
	else {
		o.write_shift(1, (t & 0x7F) + 0x80);
		o.write_shift(1, (t >> 7));
	}
	for(var i = 0; i != 4; ++i) {
		if(length >= 0x80) { o.write_shift(1, (length & 0x7F)+0x80); length >>= 7; }
		else { o.write_shift(1, length); break; }
	}
	if(/*:: length != null &&*/length > 0 && is_buf(payload)) ba.push(payload);
}
/* XLS ranges enforced */
S
SheetJS 已提交
2170
function shift_cell_xls(cell/*:CellAddress*/, tgt/*:any*/, opts/*:?any*/)/*:CellAddress*/ {
S
SheetJS 已提交
2171
	var out = dup(cell);
S
SheetJS 已提交
2172
	if(tgt.s) {
S
SheetJS 已提交
2173 2174
		if(out.cRel) out.c += tgt.s.c;
		if(out.rRel) out.r += tgt.s.r;
S
SheetJS 已提交
2175
	} else {
S
SheetJS 已提交
2176 2177
		out.c += tgt.c;
		out.r += tgt.r;
S
SheetJS 已提交
2178
	}
S
SheetJS 已提交
2179 2180 2181 2182 2183
	if(!opts || opts.biff < 12) {
		while(out.c >= 0x100) out.c -= 0x100;
		while(out.r >= 0x10000) out.r -= 0x10000;
	}
	return out;
S
SheetJS 已提交
2184 2185
}

S
SheetJS 已提交
2186 2187 2188 2189 2190
function shift_range_xls(cell, range, opts) {
	var out = dup(cell);
	out.s = shift_cell_xls(out.s, range.s, opts);
	out.e = shift_cell_xls(out.e, range.s, opts);
	return out;
S
SheetJS 已提交
2191 2192
}

S
SheetJS 已提交
2193
function encode_cell_xls(c/*:CellAddress*/)/*:string*/ {
S
SheetJS 已提交
2194 2195 2196 2197 2198 2199
	var s = encode_cell(c);
	if(c.cRel === 0) s = fix_col(s);
	if(c.rRel === 0) s = fix_row(s);
	return s;
}

S
SheetJS 已提交
2200 2201
function encode_range_xls(r, opts)/*:string*/ {
	if(r.s.r == 0 && !r.s.rRel) {
S
SheetJS 已提交
2202
		if(r.e.r == (opts.biff >= 12 ? 0xFFFFF : 0xFFFF) && !r.e.rRel) {
S
SheetJS 已提交
2203 2204 2205 2206
			return (r.s.cRel ? "" : "$") + encode_col(r.s.c) + ":" + (r.e.cRel ? "" : "$") + encode_col(r.e.c);
		}
	}
	if(r.s.c == 0 && !r.s.cRel) {
S
SheetJS 已提交
2207
		if(r.e.c == (opts.biff >= 12 ? 0xFFFF : 0xFF) && !r.e.cRel) {
S
SheetJS 已提交
2208 2209 2210
			return (r.s.rRel ? "" : "$") + encode_row(r.s.r) + ":" + (r.e.rRel ? "" : "$") + encode_row(r.e.r);
		}
	}
S
SheetJS 已提交
2211 2212
	return encode_cell_xls(r.s) + ":" + encode_cell_xls(r.e);
}
S
SheetJS 已提交
2213
var OFFCRYPTO = {};
S
SheetJS 已提交
2214

S
SheetJS 已提交
2215 2216 2217 2218
var make_offcrypto = function(O, _crypto) {
	var crypto;
	if(typeof _crypto !== 'undefined') crypto = _crypto;
	else if(typeof require !== 'undefined') {
S
SheetJS 已提交
2219
		try { crypto = require('crypto'); }
S
SheetJS 已提交
2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230
		catch(e) { crypto = null; }
	}

	O.rc4 = function(key, data) {
		var S = new Array(256);
		var c = 0, i = 0, j = 0, t = 0;
		for(i = 0; i != 256; ++i) S[i] = i;
		for(i = 0; i != 256; ++i) {
			j = (j + S[i] + (key[i%key.length]).charCodeAt(0))&255;
			t = S[i]; S[i] = S[j]; S[j] = t;
		}
S
SheetJS 已提交
2231 2232
		// $FlowIgnore
		i = j = 0; var out = Buffer(data.length);
S
SheetJS 已提交
2233 2234 2235 2236 2237 2238 2239 2240 2241
		for(c = 0; c != data.length; ++c) {
			i = (i + 1)&255;
			j = (j + S[i])%256;
			t = S[i]; S[i] = S[j]; S[j] = t;
			out[c] = (data[c] ^ S[(S[i]+S[j])&255]);
		}
		return out;
	};

S
SheetJS 已提交
2242 2243 2244 2245
	O.md5 = function(hex) {
		if(!crypto) throw new Error("Unsupported crypto");
		return crypto.createHash('md5').update(hex).digest('hex');
	};
S
SheetJS 已提交
2246
};
S
SheetJS 已提交
2247
/*:: declare var crypto:any; */
S
SheetJS 已提交
2248
/*global crypto:true */
S
SheetJS 已提交
2249 2250
make_offcrypto(OFFCRYPTO, typeof crypto !== "undefined" ? crypto : undefined);

S
SheetJS 已提交
2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315
function decode_row(rowstr/*:string*/)/*:number*/ { return parseInt(unfix_row(rowstr),10) - 1; }
function encode_row(row/*:number*/)/*:string*/ { return "" + (row + 1); }
function fix_row(cstr/*:string*/)/*:string*/ { return cstr.replace(/([A-Z]|^)(\d+)$/,"$1$$$2"); }
function unfix_row(cstr/*:string*/)/*:string*/ { return cstr.replace(/\$(\d+)$/,"$1"); }

function decode_col(colstr/*:string*/)/*:number*/ { var c = unfix_col(colstr), d = 0, i = 0; for(; i !== c.length; ++i) d = 26*d + c.charCodeAt(i) - 64; return d - 1; }
function encode_col(col/*:number*/)/*:string*/ { var s=""; for(++col; col; col=Math.floor((col-1)/26)) s = String.fromCharCode(((col-1)%26) + 65) + s; return s; }
function fix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^([A-Z])/,"$$$1"); }
function unfix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^\$([A-Z])/,"$1"); }

function split_cell(cstr/*:string*/)/*:Array<string>*/ { return cstr.replace(/(\$?[A-Z]*)(\$?\d*)/,"$1,$2").split(","); }
function decode_cell(cstr/*:string*/)/*:CellAddress*/ { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; }
function encode_cell(cell/*:CellAddress*/)/*:string*/ { return encode_col(cell.c) + encode_row(cell.r); }
function fix_cell(cstr/*:string*/)/*:string*/ { return fix_col(fix_row(cstr)); }
function unfix_cell(cstr/*:string*/)/*:string*/ { return unfix_col(unfix_row(cstr)); }
function decode_range(range/*:string*/)/*:Range*/ { var x =range.split(":").map(decode_cell); return {s:x[0],e:x[x.length-1]}; }
/*# if only one arg, it is assumed to be a Range.  If 2 args, both are cell addresses */
function encode_range(cs/*:CellAddrSpec|Range*/,ce/*:?CellAddrSpec*/)/*:string*/ {
	if(typeof ce === 'undefined' || typeof ce === 'number') {
/*:: if(!(cs instanceof Range)) throw "unreachable"; */
		return encode_range(cs.s, cs.e);
	}
/*:: if((cs instanceof Range)) throw "unreachable"; */
	if(typeof cs !== 'string') cs = encode_cell((cs/*:any*/));
	if(typeof ce !== 'string') ce = encode_cell((ce/*:any*/));
/*:: if(typeof cs !== 'string') throw "unreachable"; */
/*:: if(typeof ce !== 'string') throw "unreachable"; */
	return cs == ce ? cs : cs + ":" + ce;
}

function safe_decode_range(range/*:string*/)/*:Range*/ {
	var o = {s:{c:0,r:0},e:{c:0,r:0}};
	var idx = 0, i = 0, cc = 0;
	var len = range.length;
	for(idx = 0; i < len; ++i) {
		if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
		idx = 26*idx + cc;
	}
	o.s.c = --idx;

	for(idx = 0; i < len; ++i) {
		if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
		idx = 10*idx + cc;
	}
	o.s.r = --idx;

	if(i === len || range.charCodeAt(++i) === 58) { o.e.c=o.s.c; o.e.r=o.s.r; return o; }

	for(idx = 0; i != len; ++i) {
		if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
		idx = 26*idx + cc;
	}
	o.e.c = --idx;

	for(idx = 0; i != len; ++i) {
		if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
		idx = 10*idx + cc;
	}
	o.e.r = --idx;
	return o;
}

function safe_format_cell(cell/*:Cell*/, v/*:any*/) {
	var q = (cell.t == 'd' && v instanceof Date);
	if(cell.z != null) try { return (cell.w = SSF.format(cell.z, q ? datenum(v) : v)); } catch(e) { }
S
SheetJS 已提交
2316
	try { return (cell.w = SSF.format((cell.XF||{}).numFmtId||(q ? 14 : 0),  q ? datenum(v) : v)); } catch(e) { return ''+v; }
S
SheetJS 已提交
2317 2318 2319 2320 2321 2322
}

function format_cell(cell/*:Cell*/, v/*:any*/, o/*:any*/) {
	if(cell == null || cell.t == null || cell.t == 'z') return "";
	if(cell.w !== undefined) return cell.w;
	if(cell.t == 'd' && !cell.z && o && o.dateNF) cell.z = o.dateNF;
S
SheetJS 已提交
2323 2324
	if(v == undefined) return safe_format_cell(cell, cell.v);
	return safe_format_cell(cell, v);
S
SheetJS 已提交
2325 2326
}

S
SheetJS 已提交
2327 2328 2329 2330 2331 2332 2333 2334
function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ {
	var n = opts && opts.sheet ? opts.sheet : "Sheet1";
	var sheets = {}; sheets[n] = sheet;
	return { SheetNames: [n], Sheets: sheets };
}

function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
	var o = opts || {};
2335
	if(DENSE != null && o.dense == null) o.dense = DENSE;
S
SheetJS 已提交
2336
	var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/);
S
SheetJS 已提交
2337 2338 2339 2340 2341
	var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/);
	for(var R = 0; R != data.length; ++R) {
		for(var C = 0; C != data[R].length; ++C) {
			if(typeof data[R][C] === 'undefined') continue;
			var cell/*:Cell*/ = ({v: data[R][C] }/*:any*/);
S
SheetJS 已提交
2342
			if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
S
SheetJS 已提交
2343 2344 2345 2346
			if(range.s.r > R) range.s.r = R;
			if(range.s.c > C) range.s.c = C;
			if(range.e.r < R) range.e.r = R;
			if(range.e.c < C) range.e.c = C;
S
SheetJS 已提交
2347
			if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.cellStubs) continue; else cell.t = 'z'; }
S
SheetJS 已提交
2348 2349 2350 2351
			else if(typeof cell.v === 'number') cell.t = 'n';
			else if(typeof cell.v === 'boolean') cell.t = 'b';
			else if(cell.v instanceof Date) {
				cell.z = o.dateNF || SSF._table[14];
S
TXT/PRN  
SheetJS 已提交
2352 2353
				if(o.cellDates) { cell.t = 'd'; cell.w = SSF.format(cell.z, datenum(cell.v)); }
				else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); }
S
SheetJS 已提交
2354 2355
			}
			else cell.t = 's';
S
SheetJS 已提交
2356 2357 2358 2359 2360 2361 2362
			if(o.dense) {
				if(!ws[R]) ws[R] = [];
				ws[R][C] = cell;
			} else {
				var cell_ref = encode_cell(({c:C,r:R}/*:any*/));
				ws[cell_ref] = cell;
			}
S
SheetJS 已提交
2363 2364 2365 2366 2367 2368
		}
	}
	if(range.s.c < 10000000) ws['!ref'] = encode_range(range);
	return ws;
}

S
SheetJS 已提交
2369 2370 2371 2372 2373 2374 2375
function write_UInt32LE(x/*:number*/, o) {
	if(!o) o = new_buf(4);
	o.write_shift(4, x);
	return o;
}

/* [MS-XLSB] 2.5.168 */
2376
function parse_XLWideString(data/*::, length*/)/*:string*/ {
S
SheetJS 已提交
2377 2378 2379 2380 2381 2382 2383 2384 2385
	var cchCharacters = data.read_shift(4);
	return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, 'dbcs');
}
function write_XLWideString(data/*:string*/, o) {
	var _null = false; if(o == null) { _null = true; o = new_buf(4+2*data.length); }
	o.write_shift(4, data.length);
	if(data.length > 0) o.write_shift(0, data, 'dbcs');
	return _null ? o.slice(0, o.l) : o;
}
S
SheetJS 已提交
2386 2387

/* [MS-XLSB] 2.5.143 */
S
SheetJS 已提交
2388
function parse_StrRun(data, length/*:?number*/) {
S
SheetJS 已提交
2389 2390
	return { ich: data.read_shift(2), ifnt: data.read_shift(2) };
}
S
SheetJS 已提交
2391 2392 2393 2394 2395 2396
function write_StrRun(run, o) {
	if(!o) o = new_buf(4);
	o.write_shift(2, run.ich || 0);
	o.write_shift(2, run.ifnt || 0);
	return o;
}
S
SheetJS 已提交
2397 2398

/* [MS-XLSB] 2.1.7.121 */
S
SheetJS 已提交
2399
function parse_RichStr(data, length/*:number*/)/*:XLString*/ {
S
SheetJS 已提交
2400 2401 2402 2403
	var start = data.l;
	var flags = data.read_shift(1);
	var str = parse_XLWideString(data);
	var rgsStrRun = [];
S
SheetJS 已提交
2404
	var z = ({ t: str, h: str }/*:any*/);
S
SheetJS 已提交
2405 2406 2407 2408 2409 2410
	if((flags & 1) !== 0) { /* fRichStr */
		/* TODO: formatted string */
		var dwSizeStrRun = data.read_shift(4);
		for(var i = 0; i != dwSizeStrRun; ++i) rgsStrRun.push(parse_StrRun(data));
		z.r = rgsStrRun;
	}
S
SheetJS 已提交
2411
	else z.r = [{ich:0, ifnt:0}];
S
SheetJS 已提交
2412 2413 2414
	//if((flags & 2) !== 0) { /* fExtStr */
	//	/* TODO: phonetic string */
	//}
S
SheetJS 已提交
2415 2416 2417
	data.l = start + length;
	return z;
}
S
SheetJS 已提交
2418
function write_RichStr(str/*:XLString*/, o/*:?Block*/)/*:Block*/ {
S
SheetJS 已提交
2419
	/* TODO: formatted string */
S
SheetJS 已提交
2420
	var _null = false; if(o == null) { _null = true; o = new_buf(15+4*str.t.length); }
S
SheetJS 已提交
2421 2422
	o.write_shift(1,0);
	write_XLWideString(str.t, o);
S
SheetJS 已提交
2423
	return _null ? o.slice(0, o.l) : o;
S
SheetJS 已提交
2424
}
S
SheetJS 已提交
2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435
/* [MS-XLSB] 2.4.325 BrtCommentText (RichStr w/1 run) */
var parse_BrtCommentText = parse_RichStr;
function write_BrtCommentText(str/*:XLString*/, o/*:?Block*/)/*:Block*/ {
	/* TODO: formatted string */
	var _null = false; if(o == null) { _null = true; o = new_buf(23+4*str.t.length); }
	o.write_shift(1,1);
	write_XLWideString(str.t, o);
	o.write_shift(4,1);
	write_StrRun({ich:0,ifnt:0}, o);
	return _null ? o.slice(0, o.l) : o;
}
S
SheetJS 已提交
2436 2437

/* [MS-XLSB] 2.5.9 */
S
SheetJS 已提交
2438
function parse_XLSBCell(data)/*:any*/ {
S
SheetJS 已提交
2439 2440 2441 2442 2443 2444
	var col = data.read_shift(4);
	var iStyleRef = data.read_shift(2);
	iStyleRef += data.read_shift(1) <<16;
	var fPhShow = data.read_shift(1);
	return { c:col, iStyleRef: iStyleRef };
}
S
SheetJS 已提交
2445
function write_XLSBCell(cell/*:any*/, o/*:?Block*/) {
S
SheetJS 已提交
2446 2447
	if(o == null) o = new_buf(8);
	o.write_shift(-4, cell.c);
S
SheetJS 已提交
2448
	o.write_shift(3, cell.iStyleRef || cell.s);
S
SheetJS 已提交
2449 2450 2451 2452 2453 2454
	o.write_shift(1, 0); /* fPhShow */
	return o;
}


/* [MS-XLSB] 2.5.21 */
S
SheetJS 已提交
2455 2456
var parse_XLSBCodeName = parse_XLWideString;
var write_XLSBCodeName = write_XLWideString;
S
SheetJS 已提交
2457 2458

/* [MS-XLSB] 2.5.166 */
2459
function parse_XLNullableWideString(data/*::, length*/)/*:string*/ {
S
SheetJS 已提交
2460 2461 2462
	var cchCharacters = data.read_shift(4);
	return cchCharacters === 0 || cchCharacters === 0xFFFFFFFF ? "" : data.read_shift(cchCharacters, 'dbcs');
}
S
SheetJS 已提交
2463
function write_XLNullableWideString(data/*:string*/, o) {
S
SheetJS 已提交
2464
	var _null = false; if(o == null) { _null = true; o = new_buf(127); }
S
SheetJS 已提交
2465 2466
	o.write_shift(4, data.length > 0 ? data.length : 0xFFFFFFFF);
	if(data.length > 0) o.write_shift(0, data, 'dbcs');
S
SheetJS 已提交
2467
	return _null ? o.slice(0, o.l) : o;
S
SheetJS 已提交
2468 2469
}

S
SheetJS 已提交
2470 2471 2472 2473
/* [MS-XLSB] 2.5.165 */
var parse_XLNameWideString = parse_XLWideString;
var write_XLNameWideString = write_XLWideString;

S
SheetJS 已提交
2474 2475 2476 2477 2478 2479 2480
/* [MS-XLSB] 2.5.114 */
var parse_RelID = parse_XLNullableWideString;
var write_RelID = write_XLNullableWideString;


/* [MS-XLSB] 2.5.122 */
/* [MS-XLS] 2.5.217 */
S
SheetJS 已提交
2481
function parse_RkNumber(data)/*:number*/ {
S
SheetJS 已提交
2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498
	var b = data.slice(data.l, data.l+4);
	var fX100 = b[0] & 1, fInt = b[0] & 2;
	data.l+=4;
	b[0] &= 0xFC; // b[0] &= ~3;
	var RK = fInt === 0 ? __double([0,0,0,0,b[0],b[1],b[2],b[3]],0) : __readInt32LE(b,0)>>2;
	return fX100 ? RK/100 : RK;
}
function write_RkNumber(data/*:number*/, o) {
	if(o == null) o = new_buf(4);
	var fX100 = 0, fInt = 0, d100 = data * 100;
	if(data == (data | 0) && data >= -(1<<29) && data < (1 << 29)) { fInt = 1; }
	else if(d100 == (d100 | 0) && d100 >= -(1<<29) && d100 < (1 << 29)) { fInt = 1; fX100 = 1; }
	if(fInt) o.write_shift(-4, ((fX100 ? d100 : data) << 2) + (fX100 + 2));
	else throw new Error("unsupported RkNumber " + data); // TODO
}


S
SheetJS 已提交
2499
/* [MS-XLSB] 2.5.117 RfX */
2500
function parse_RfX(data /*::, length*/)/*:Range*/ {
S
SheetJS 已提交
2501
	var cell/*:Range*/ = ({s: {}, e: {}}/*:any*/);
S
SheetJS 已提交
2502 2503 2504 2505 2506 2507 2508
	cell.s.r = data.read_shift(4);
	cell.e.r = data.read_shift(4);
	cell.s.c = data.read_shift(4);
	cell.e.c = data.read_shift(4);
	return cell;
}

S
SheetJS 已提交
2509
function write_RfX(r/*:Range*/, o) {
S
SheetJS 已提交
2510 2511 2512 2513 2514 2515 2516 2517
	if(!o) o = new_buf(16);
	o.write_shift(4, r.s.r);
	o.write_shift(4, r.e.r);
	o.write_shift(4, r.s.c);
	o.write_shift(4, r.e.c);
	return o;
}

S
SheetJS 已提交
2518 2519 2520 2521
/* [MS-XLSB] 2.5.153 UncheckedRfX */
var parse_UncheckedRfX = parse_RfX;
var write_UncheckedRfX = write_RfX;

S
SheetJS 已提交
2522 2523 2524
/* [MS-XLSB] 2.5.171 */
/* [MS-XLS] 2.5.342 */
/* TODO: error checking, NaN and Infinity values are not valid Xnum */
S
SheetJS 已提交
2525
function parse_Xnum(data, length/*:?number*/) { return data.read_shift(8, 'f'); }
S
SheetJS 已提交
2526 2527 2528 2529
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); }

/* [MS-XLSB] 2.5.198.2 */
var BErr = {
S
SheetJS 已提交
2530 2531 2532 2533 2534 2535 2536 2537 2538
	/*::[*/0x00/*::]*/: "#NULL!",
	/*::[*/0x07/*::]*/: "#DIV/0!",
	/*::[*/0x0F/*::]*/: "#VALUE!",
	/*::[*/0x17/*::]*/: "#REF!",
	/*::[*/0x1D/*::]*/: "#NAME?",
	/*::[*/0x24/*::]*/: "#NUM!",
	/*::[*/0x2A/*::]*/: "#N/A",
	/*::[*/0x2B/*::]*/: "#GETTING_DATA",
	/*::[*/0xFF/*::]*/: "#WTF?"
S
SheetJS 已提交
2539 2540 2541 2542
};
var RBErr = evert_num(BErr);

/* [MS-XLSB] 2.4.321 BrtColor */
S
SheetJS 已提交
2543
function parse_BrtColor(data, length/*:number*/) {
S
SheetJS 已提交
2544 2545
	var out = {};
	var d = data.read_shift(1);
S
SheetJS 已提交
2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562

	var fValidRGB = d & 1;
	var xColorType = d >>> 1;

	var index = data.read_shift(1);
	var nTS = data.read_shift(2, 'i');
	var bR = data.read_shift(1);
	var bG = data.read_shift(1);
	var bB = data.read_shift(1);
	var bAlpha = data.read_shift(1);

	switch(xColorType) {
		case 0: out.auto = 1; break;
		case 1:
			out.index = index;
			var icv = XLSIcv[index];
			/* automatic pseudo index 81 */
S
SheetJS 已提交
2563
			if(icv) out.rgb = rgb2Hex(icv);
S
SheetJS 已提交
2564 2565 2566
			break;
		case 2:
			/* if(!fValidRGB) throw new Error("invalid"); */
S
SheetJS 已提交
2567
			out.rgb = rgb2Hex([bR, bG, bB]);
S
SheetJS 已提交
2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603
			break;
		case 3: out.theme = index; break;
	}
	if(nTS != 0) out.tint = nTS > 0 ? nTS / 32767 : nTS / 32768;

	return out;
}
function write_BrtColor(color, o) {
	if(!o) o = new_buf(8);
	if(!color||color.auto) { o.write_shift(4, 0); o.write_shift(4, 0); return o; }
	if(color.index) {
		o.write_shift(1, 0x02);
		o.write_shift(1, color.index);
	} else if(color.theme) {
		o.write_shift(1, 0x06);
		o.write_shift(1, color.theme);
	} else {
		o.write_shift(1, 0x05);
		o.write_shift(1, 0);
	}
	var nTS = color.tint || 0;
	if(nTS > 0) nTS *= 32767;
	else if(nTS < 0) nTS *= 32768;
	o.write_shift(2, nTS);
	if(!color.rgb) {
		o.write_shift(2, 0);
		o.write_shift(1, 0);
		o.write_shift(1, 0);
	} else {
		var rgb = (color.rgb || 'FFFFFF');
		o.write_shift(1, parseInt(rgb.substr(0,2),16));
		o.write_shift(1, parseInt(rgb.substr(2,2),16));
		o.write_shift(1, parseInt(rgb.substr(4,2),16));
		o.write_shift(1, 0xFF);
	}
	return o;
S
SheetJS 已提交
2604 2605 2606
}

/* [MS-XLSB] 2.5.52 */
S
SheetJS 已提交
2607
function parse_FontFlags(data, length/*:number*/, opts) {
S
SheetJS 已提交
2608 2609 2610
	var d = data.read_shift(1);
	data.l++;
	var out = {
S
SheetJS 已提交
2611 2612 2613 2614
		/* fBold: d & 0x01 */
		fItalic: d & 0x02,
		/* fUnderline: d & 0x04 */
		fStrikeout: d & 0x08,
S
SheetJS 已提交
2615 2616 2617 2618 2619 2620 2621
		fOutline: d & 0x10,
		fShadow: d & 0x20,
		fCondense: d & 0x40,
		fExtend: d & 0x80
	};
	return out;
}
S
SheetJS 已提交
2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635
function write_FontFlags(font, o) {
	if(!o) o = new_buf(2);
	var grbit =
		(font.italic   ? 0x02 : 0) |
		(font.strike   ? 0x08 : 0) |
		(font.outline  ? 0x10 : 0) |
		(font.shadow   ? 0x20 : 0) |
		(font.condense ? 0x40 : 0) |
		(font.extend   ? 0x80 : 0);
	o.write_shift(1, grbit);
	o.write_shift(1, 0);
	return o;
}

S
SheetJS 已提交
2636 2637
/* [MS-OLEPS] 2.2 PropertyType */
{
S
SheetJS 已提交
2638 2639
	//var VT_EMPTY    = 0x0000;
	//var VT_NULL     = 0x0001;
S
SheetJS 已提交
2640 2641
	var VT_I2       = 0x0002;
	var VT_I4       = 0x0003;
S
SheetJS 已提交
2642 2643 2644 2645 2646 2647
	//var VT_R4       = 0x0004;
	//var VT_R8       = 0x0005;
	//var VT_CY       = 0x0006;
	//var VT_DATE     = 0x0007;
	//var VT_BSTR     = 0x0008;
	//var VT_ERROR    = 0x000A;
S
SheetJS 已提交
2648 2649
	var VT_BOOL     = 0x000B;
	var VT_VARIANT  = 0x000C;
S
SheetJS 已提交
2650 2651 2652 2653
	//var VT_DECIMAL  = 0x000E;
	//var VT_I1       = 0x0010;
	//var VT_UI1      = 0x0011;
	//var VT_UI2      = 0x0012;
S
SheetJS 已提交
2654
	var VT_UI4      = 0x0013;
S
SheetJS 已提交
2655
	//var VT_I8       = 0x0014;
S
SheetJS 已提交
2656
	var VT_UI8      = 0x0015;
S
SheetJS 已提交
2657 2658
	//var VT_INT      = 0x0016;
	//var VT_UINT     = 0x0017;
S
SheetJS 已提交
2659
	var VT_LPSTR    = 0x001E;
S
SheetJS 已提交
2660
	//var VT_LPWSTR   = 0x001F;
S
SheetJS 已提交
2661
	var VT_FILETIME = 0x0040;
S
SheetJS 已提交
2662 2663 2664 2665 2666 2667
	//var VT_BLOB     = 0x0041;
	//var VT_STREAM   = 0x0042;
	//var VT_STORAGE  = 0x0043;
	//var VT_STREAMED_Object  = 0x0044;
	//var VT_STORED_Object    = 0x0045;
	//var VT_BLOB_Object      = 0x0046;
S
SheetJS 已提交
2668
	var VT_CF       = 0x0047;
S
SheetJS 已提交
2669 2670
	//var VT_CLSID    = 0x0048;
	//var VT_VERSIONED_STREAM = 0x0049;
S
SheetJS 已提交
2671
	var VT_VECTOR   = 0x1000;
S
SheetJS 已提交
2672
	//var VT_ARRAY    = 0x2000;
S
SheetJS 已提交
2673 2674 2675 2676 2677 2678 2679 2680

	var VT_STRING   = 0x0050; // 2.3.3.1.11 VtString
	var VT_USTR     = 0x0051; // 2.3.3.1.12 VtUnalignedString
	var VT_CUSTOM   = [VT_STRING, VT_USTR];
}

/* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */
var DocSummaryPIDDSI = {
S
SheetJS 已提交
2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705
	/*::[*/0x01/*::]*/: { n: 'CodePage', t: VT_I2 },
	/*::[*/0x02/*::]*/: { n: 'Category', t: VT_STRING },
	/*::[*/0x03/*::]*/: { n: 'PresentationFormat', t: VT_STRING },
	/*::[*/0x04/*::]*/: { n: 'ByteCount', t: VT_I4 },
	/*::[*/0x05/*::]*/: { n: 'LineCount', t: VT_I4 },
	/*::[*/0x06/*::]*/: { n: 'ParagraphCount', t: VT_I4 },
	/*::[*/0x07/*::]*/: { n: 'SlideCount', t: VT_I4 },
	/*::[*/0x08/*::]*/: { n: 'NoteCount', t: VT_I4 },
	/*::[*/0x09/*::]*/: { n: 'HiddenCount', t: VT_I4 },
	/*::[*/0x0a/*::]*/: { n: 'MultimediaClipCount', t: VT_I4 },
	/*::[*/0x0b/*::]*/: { n: 'Scale', t: VT_BOOL },
	/*::[*/0x0c/*::]*/: { n: 'HeadingPair', t: VT_VECTOR | VT_VARIANT },
	/*::[*/0x0d/*::]*/: { n: 'DocParts', t: VT_VECTOR | VT_LPSTR },
	/*::[*/0x0e/*::]*/: { n: 'Manager', t: VT_STRING },
	/*::[*/0x0f/*::]*/: { n: 'Company', t: VT_STRING },
	/*::[*/0x10/*::]*/: { n: 'LinksDirty', t: VT_BOOL },
	/*::[*/0x11/*::]*/: { n: 'CharacterCount', t: VT_I4 },
	/*::[*/0x13/*::]*/: { n: 'SharedDoc', t: VT_BOOL },
	/*::[*/0x16/*::]*/: { n: 'HLinksChanged', t: VT_BOOL },
	/*::[*/0x17/*::]*/: { n: 'AppVersion', t: VT_I4, p: 'version' },
	/*::[*/0x1A/*::]*/: { n: 'ContentType', t: VT_STRING },
	/*::[*/0x1B/*::]*/: { n: 'ContentStatus', t: VT_STRING },
	/*::[*/0x1C/*::]*/: { n: 'Language', t: VT_STRING },
	/*::[*/0x1D/*::]*/: { n: 'Version', t: VT_STRING },
	/*::[*/0xFF/*::]*/: {}
S
SheetJS 已提交
2706 2707 2708 2709
};

/* [MS-OSHARED] 2.3.3.2.1.1 Summary Information Property Set PIDSI */
var SummaryPIDSI = {
S
SheetJS 已提交
2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729
	/*::[*/0x01/*::]*/: { n: 'CodePage', t: VT_I2 },
	/*::[*/0x02/*::]*/: { n: 'Title', t: VT_STRING },
	/*::[*/0x03/*::]*/: { n: 'Subject', t: VT_STRING },
	/*::[*/0x04/*::]*/: { n: 'Author', t: VT_STRING },
	/*::[*/0x05/*::]*/: { n: 'Keywords', t: VT_STRING },
	/*::[*/0x06/*::]*/: { n: 'Comments', t: VT_STRING },
	/*::[*/0x07/*::]*/: { n: 'Template', t: VT_STRING },
	/*::[*/0x08/*::]*/: { n: 'LastAuthor', t: VT_STRING },
	/*::[*/0x09/*::]*/: { n: 'RevNumber', t: VT_STRING },
	/*::[*/0x0A/*::]*/: { n: 'EditTime', t: VT_FILETIME },
	/*::[*/0x0B/*::]*/: { n: 'LastPrinted', t: VT_FILETIME },
	/*::[*/0x0C/*::]*/: { n: 'CreatedDate', t: VT_FILETIME },
	/*::[*/0x0D/*::]*/: { n: 'ModifiedDate', t: VT_FILETIME },
	/*::[*/0x0E/*::]*/: { n: 'PageCount', t: VT_I4 },
	/*::[*/0x0F/*::]*/: { n: 'WordCount', t: VT_I4 },
	/*::[*/0x10/*::]*/: { n: 'CharCount', t: VT_I4 },
	/*::[*/0x11/*::]*/: { n: 'Thumbnail', t: VT_CF },
	/*::[*/0x12/*::]*/: { n: 'ApplicationName', t: VT_LPSTR },
	/*::[*/0x13/*::]*/: { n: 'DocumentSecurity', t: VT_I4 },
	/*::[*/0xFF/*::]*/: {}
S
SheetJS 已提交
2730 2731 2732 2733
};

/* [MS-OLEPS] 2.18 */
var SpecialProperties = {
S
SheetJS 已提交
2734 2735 2736
	/*::[*/0x80000000/*::]*/: { n: 'Locale', t: VT_UI4 },
	/*::[*/0x80000003/*::]*/: { n: 'Behavior', t: VT_UI4 },
	/*::[*/0x72627262/*::]*/: {}
S
SheetJS 已提交
2737 2738 2739 2740 2741 2742 2743 2744 2745
};

(function() {
	for(var y in SpecialProperties) if(SpecialProperties.hasOwnProperty(y))
	DocSummaryPIDDSI[y] = SummaryPIDSI[y] = SpecialProperties[y];
})();

/* [MS-XLS] 2.4.63 Country/Region codes */
var CountryEnum = {
S
SheetJS 已提交
2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795
	/*::[*/0x0001/*::]*/: "US", // United States
	/*::[*/0x0002/*::]*/: "CA", // Canada
	/*::[*/0x0003/*::]*/: "", // Latin America (except Brazil)
	/*::[*/0x0007/*::]*/: "RU", // Russia
	/*::[*/0x0014/*::]*/: "EG", // Egypt
	/*::[*/0x001E/*::]*/: "GR", // Greece
	/*::[*/0x001F/*::]*/: "NL", // Netherlands
	/*::[*/0x0020/*::]*/: "BE", // Belgium
	/*::[*/0x0021/*::]*/: "FR", // France
	/*::[*/0x0022/*::]*/: "ES", // Spain
	/*::[*/0x0024/*::]*/: "HU", // Hungary
	/*::[*/0x0027/*::]*/: "IT", // Italy
	/*::[*/0x0029/*::]*/: "CH", // Switzerland
	/*::[*/0x002B/*::]*/: "AT", // Austria
	/*::[*/0x002C/*::]*/: "GB", // United Kingdom
	/*::[*/0x002D/*::]*/: "DK", // Denmark
	/*::[*/0x002E/*::]*/: "SE", // Sweden
	/*::[*/0x002F/*::]*/: "NO", // Norway
	/*::[*/0x0030/*::]*/: "PL", // Poland
	/*::[*/0x0031/*::]*/: "DE", // Germany
	/*::[*/0x0034/*::]*/: "MX", // Mexico
	/*::[*/0x0037/*::]*/: "BR", // Brazil
	/*::[*/0x003d/*::]*/: "AU", // Australia
	/*::[*/0x0040/*::]*/: "NZ", // New Zealand
	/*::[*/0x0042/*::]*/: "TH", // Thailand
	/*::[*/0x0051/*::]*/: "JP", // Japan
	/*::[*/0x0052/*::]*/: "KR", // Korea
	/*::[*/0x0054/*::]*/: "VN", // Viet Nam
	/*::[*/0x0056/*::]*/: "CN", // China
	/*::[*/0x005A/*::]*/: "TR", // Turkey
	/*::[*/0x0069/*::]*/: "JS", // Ramastan
	/*::[*/0x00D5/*::]*/: "DZ", // Algeria
	/*::[*/0x00D8/*::]*/: "MA", // Morocco
	/*::[*/0x00DA/*::]*/: "LY", // Libya
	/*::[*/0x015F/*::]*/: "PT", // Portugal
	/*::[*/0x0162/*::]*/: "IS", // Iceland
	/*::[*/0x0166/*::]*/: "FI", // Finland
	/*::[*/0x01A4/*::]*/: "CZ", // Czech Republic
	/*::[*/0x0376/*::]*/: "TW", // Taiwan
	/*::[*/0x03C1/*::]*/: "LB", // Lebanon
	/*::[*/0x03C2/*::]*/: "JO", // Jordan
	/*::[*/0x03C3/*::]*/: "SY", // Syria
	/*::[*/0x03C4/*::]*/: "IQ", // Iraq
	/*::[*/0x03C5/*::]*/: "KW", // Kuwait
	/*::[*/0x03C6/*::]*/: "SA", // Saudi Arabia
	/*::[*/0x03CB/*::]*/: "AE", // United Arab Emirates
	/*::[*/0x03CC/*::]*/: "IL", // Israel
	/*::[*/0x03CE/*::]*/: "QA", // Qatar
	/*::[*/0x03D5/*::]*/: "IR", // Iran
	/*::[*/0xFFFF/*::]*/: "US"  // United States
S
SheetJS 已提交
2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823
};

/* [MS-XLS] 2.5.127 */
var XLSFillPattern = [
	null,
	'solid',
	'mediumGray',
	'darkGray',
	'lightGray',
	'darkHorizontal',
	'darkVertical',
	'darkDown',
	'darkUp',
	'darkGrid',
	'darkTrellis',
	'lightHorizontal',
	'lightVertical',
	'lightDown',
	'lightUp',
	'lightGrid',
	'lightTrellis',
	'gray125',
	'gray0625'
];

function rgbify(arr) { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); }

/* [MS-XLS] 2.5.161 */
S
SheetJS 已提交
2824
/* [MS-XLSB] 2.5.75 */
S
SheetJS 已提交
2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835
var XLSIcv = rgbify([
	/* Color Constants */
	0x000000,
	0xFFFFFF,
	0xFF0000,
	0x00FF00,
	0x0000FF,
	0xFFFF00,
	0xFF00FF,
	0x00FFFF,

S
SheetJS 已提交
2836
	/* Overridable Defaults */
S
SheetJS 已提交
2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896
	0x000000,
	0xFFFFFF,
	0xFF0000,
	0x00FF00,
	0x0000FF,
	0xFFFF00,
	0xFF00FF,
	0x00FFFF,

	0x800000,
	0x008000,
	0x000080,
	0x808000,
	0x800080,
	0x008080,
	0xC0C0C0,
	0x808080,
	0x9999FF,
	0x993366,
	0xFFFFCC,
	0xCCFFFF,
	0x660066,
	0xFF8080,
	0x0066CC,
	0xCCCCFF,

	0x000080,
	0xFF00FF,
	0xFFFF00,
	0x00FFFF,
	0x800080,
	0x800000,
	0x008080,
	0x0000FF,
	0x00CCFF,
	0xCCFFFF,
	0xCCFFCC,
	0xFFFF99,
	0x99CCFF,
	0xFF99CC,
	0xCC99FF,
	0xFFCC99,

	0x3366FF,
	0x33CCCC,
	0x99CC00,
	0xFFCC00,
	0xFF9900,
	0xFF6600,
	0x666699,
	0x969696,
	0x003366,
	0x339966,
	0x003300,
	0x333300,
	0x993300,
	0x993366,
	0x333399,
	0x333333,

S
SheetJS 已提交
2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915
	/* Other entries to appease BIFF8/12 */
	0xFFFFFF, /* 0x40 icvForeground ?? */
	0x000000, /* 0x41 icvBackground ?? */
	0x000000, /* 0x42 icvFrame ?? */
	0x000000, /* 0x43 icv3D ?? */
	0x000000, /* 0x44 icv3DText ?? */
	0x000000, /* 0x45 icv3DHilite ?? */
	0x000000, /* 0x46 icv3DShadow ?? */
	0x000000, /* 0x47 icvHilite ?? */
	0x000000, /* 0x48 icvCtlText ?? */
	0x000000, /* 0x49 icvCtlScrl ?? */
	0x000000, /* 0x4A icvCtlInv ?? */
	0x000000, /* 0x4B icvCtlBody ?? */
	0x000000, /* 0x4C icvCtlFrame ?? */
	0x000000, /* 0x4D icvCtlFore ?? */
	0x000000, /* 0x4E icvCtlBack ?? */
	0x000000, /* 0x4F icvCtlNeutral */
	0x000000, /* 0x50 icvInfoBk ?? */
	0x000000 /* 0x51 icvInfoText ?? */
S
SheetJS 已提交
2916 2917 2918 2919 2920 2921 2922
]);

/* Parts enumerated in OPC spec, MS-XLSB and MS-XLSX */
/* 12.3 Part Summary <SpreadsheetML> */
/* 14.2 Part Summary <DrawingML> */
/* [MS-XLSX] 2.1 Part Enumerations */
/* [MS-XLSB] 2.1.7 Part Enumeration */
S
SheetJS 已提交
2923
var ct2type/*{[string]:string}*/ = ({
S
SheetJS 已提交
2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940
	/* Workbook */
	"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": "workbooks",

	/* Worksheet */
	"application/vnd.ms-excel.binIndexWs": "TODO", /* Binary Index */

	/* Macrosheet */
	"application/vnd.ms-excel.intlmacrosheet": "TODO",
	"application/vnd.ms-excel.binIndexMs": "TODO", /* Binary Index */

	/* File Properties */
	"application/vnd.openxmlformats-package.core-properties+xml": "coreprops",
	"application/vnd.openxmlformats-officedocument.custom-properties+xml": "custprops",
	"application/vnd.openxmlformats-officedocument.extended-properties+xml": "extprops",

	/* Custom Data Properties */
	"application/vnd.openxmlformats-officedocument.customXmlProperties+xml": "TODO",
2941
	"application/vnd.openxmlformats-officedocument.spreadsheetml.customProperty": "TODO",
S
SheetJS 已提交
2942 2943 2944 2945 2946

	/* PivotTable */
	"application/vnd.ms-excel.pivotTable": "TODO",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml": "TODO",

S
SheetJS 已提交
2947 2948 2949 2950 2951 2952
	/* Chart Colors */
	"application/vnd.ms-office.chartcolorstyle+xml": "TODO",

	/* Chart Style */
	"application/vnd.ms-office.chartstyle+xml": "TODO",

S
SheetJS 已提交
2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971
	/* Calculation Chain */
	"application/vnd.ms-excel.calcChain": "calcchains",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains",

	/* Printer Settings */
	"application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings": "TODO",

	/* ActiveX */
	"application/vnd.ms-office.activeX": "TODO",
	"application/vnd.ms-office.activeX+xml": "TODO",

	/* Custom Toolbars */
	"application/vnd.ms-excel.attachedToolbars": "TODO",

	/* External Data Connections */
	"application/vnd.ms-excel.connections": "TODO",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml": "TODO",

	/* External Links */
S
SheetJS 已提交
2972 2973
	"application/vnd.ms-excel.externalLink": "links",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml": "links",
S
SheetJS 已提交
2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016

	/* Metadata */
	"application/vnd.ms-excel.sheetMetadata": "TODO",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml": "TODO",

	/* PivotCache */
	"application/vnd.ms-excel.pivotCacheDefinition": "TODO",
	"application/vnd.ms-excel.pivotCacheRecords": "TODO",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml": "TODO",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml": "TODO",

	/* Query Table */
	"application/vnd.ms-excel.queryTable": "TODO",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml": "TODO",

	/* Shared Workbook */
	"application/vnd.ms-excel.userNames": "TODO",
	"application/vnd.ms-excel.revisionHeaders": "TODO",
	"application/vnd.ms-excel.revisionLog": "TODO",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml": "TODO",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml": "TODO",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml": "TODO",

	/* Single Cell Table */
	"application/vnd.ms-excel.tableSingleCells": "TODO",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml": "TODO",

	/* Slicer */
	"application/vnd.ms-excel.slicer": "TODO",
	"application/vnd.ms-excel.slicerCache": "TODO",
	"application/vnd.ms-excel.slicer+xml": "TODO",
	"application/vnd.ms-excel.slicerCache+xml": "TODO",

	/* Sort Map */
	"application/vnd.ms-excel.wsSortMap": "TODO",

	/* Table */
	"application/vnd.ms-excel.table": "TODO",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml": "TODO",

	/* Themes */
	"application/vnd.openxmlformats-officedocument.theme+xml": "themes",

3017 3018 3019
	/* Theme Override */
	"application/vnd.openxmlformats-officedocument.themeOverride+xml": "TODO",

S
SheetJS 已提交
3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041
	/* Timeline */
	"application/vnd.ms-excel.Timeline+xml": "TODO", /* verify */
	"application/vnd.ms-excel.TimelineCache+xml": "TODO", /* verify */

	/* VBA */
	"application/vnd.ms-office.vbaProject": "vba",
	"application/vnd.ms-office.vbaProjectSignature": "vba",

	/* Volatile Dependencies */
	"application/vnd.ms-office.volatileDependencies": "TODO",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml": "TODO",

	/* Control Properties */
	"application/vnd.ms-excel.controlproperties+xml": "TODO",

	/* Data Model */
	"application/vnd.openxmlformats-officedocument.model+data": "TODO",

	/* Survey */
	"application/vnd.ms-excel.Survey+xml": "TODO",

	/* Drawing */
S
SheetJS 已提交
3042
	"application/vnd.openxmlformats-officedocument.drawing+xml": "drawings",
S
SheetJS 已提交
3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055
	"application/vnd.openxmlformats-officedocument.drawingml.chart+xml": "TODO",
	"application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml": "TODO",
	"application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml": "TODO",
	"application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml": "TODO",
	"application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml": "TODO",
	"application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml": "TODO",

	/* VML */
	"application/vnd.openxmlformats-officedocument.vmlDrawing": "TODO",

	"application/vnd.openxmlformats-package.relationships+xml": "rels",
	"application/vnd.openxmlformats-officedocument.oleObject": "TODO",

3056 3057 3058
	/* Image */
	"image/png": "TODO",

S
SheetJS 已提交
3059
	"sheet": "js"
S
SheetJS 已提交
3060
}/*:any*/);
S
SheetJS 已提交
3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073

var CT_LIST = (function(){
	var o = {
		workbooks: {
			xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
			xlsm: "application/vnd.ms-excel.sheet.macroEnabled.main+xml",
			xlsb: "application/vnd.ms-excel.sheet.binary.macroEnabled.main",
			xltx: "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
		},
		strs: { /* Shared Strings */
			xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
			xlsb: "application/vnd.ms-excel.sharedStrings"
		},
S
SheetJS 已提交
3074 3075 3076 3077
		comments: { /* Comments */
			xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
			xlsb: "application/vnd.ms-excel.comments"
		},
3078
		sheets: { /* Worksheet */
S
SheetJS 已提交
3079 3080 3081
			xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
			xlsb: "application/vnd.ms-excel.worksheet"
		},
3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094
		charts: { /* Chartsheet */
			xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml",
			xlsb: "application/vnd.ms-excel.chartsheet"
		},
		dialogs: { /* Dialogsheet */
			xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml",
			xlsb: "application/vnd.ms-excel.dialogsheet"
		},
		macros: { /* Macrosheet (Excel 4.0 Macros) */
			xlsx: "application/vnd.ms-excel.macrosheet+xml",
			xlsb: "application/vnd.ms-excel.macrosheet"
		},
		styles: { /* Styles */
S
SheetJS 已提交
3095 3096 3097 3098 3099 3100 3101 3102 3103
			xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
			xlsb: "application/vnd.ms-excel.styles"
		}
	};
	keys(o).forEach(function(k) { if(!o[k].xlsm) o[k].xlsm = o[k].xlsx; });
	keys(o).forEach(function(k){ keys(o[k]).forEach(function(v) { ct2type[o[k][v]] = k; }); });
	return o;
})();

S
SheetJS 已提交
3104
var type2ct/*{[string]:Array<string>}*/ = evert_arr(ct2type);
S
SheetJS 已提交
3105 3106 3107

XMLNS.CT = 'http://schemas.openxmlformats.org/package/2006/content-types';

S
SheetJS 已提交
3108 3109
function new_ct()/*:any*/ {
	return ({
S
SheetJS 已提交
3110
		workbooks:[], sheets:[], charts:[], dialogs:[], macros:[],
S
SheetJS 已提交
3111
		rels:[], strs:[], comments:[], links:[],
3112
		coreprops:[], extprops:[], custprops:[], themes:[], styles:[],
S
SheetJS 已提交
3113
		calcchains:[], vba: [], drawings: [],
3114
		TODO:[], xmlns: "" }/*:any*/);
S
SheetJS 已提交
3115 3116 3117 3118
}

function parse_ct(data/*:?string*/, opts) {
	var ct = new_ct();
S
SheetJS 已提交
3119 3120
	if(!data || !data.match) return ct;
	var ctext = {};
S
SheetJS 已提交
3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149
	(data.match(tagregex)||[]).forEach(function(x) {
		var y = parsexmltag(x);
		switch(y[0].replace(nsregex,"<")) {
			case '<?xml': break;
			case '<Types': ct.xmlns = y['xmlns' + (y[0].match(/<(\w+):/)||["",""])[1] ]; break;
			case '<Default': ctext[y.Extension] = y.ContentType; break;
			case '<Override':
				if(ct[ct2type[y.ContentType]] !== undefined) ct[ct2type[y.ContentType]].push(y.PartName);
				break;
		}
	});
	if(ct.xmlns !== XMLNS.CT) throw new Error("Unknown Namespace: " + ct.xmlns);
	ct.calcchain = ct.calcchains.length > 0 ? ct.calcchains[0] : "";
	ct.sst = ct.strs.length > 0 ? ct.strs[0] : "";
	ct.style = ct.styles.length > 0 ? ct.styles[0] : "";
	ct.defaults = ctext;
	delete ct.calcchains;
	return ct;
}

var CTYPE_XML_ROOT = writextag('Types', null, {
	'xmlns': XMLNS.CT,
	'xmlns:xsd': XMLNS.xsd,
	'xmlns:xsi': XMLNS.xsi
});

var CTYPE_DEFAULTS = [
	['xml', 'application/xml'],
	['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
S
SheetJS 已提交
3150
	['vml', 'application/vnd.openxmlformats-officedocument.vmlDrawing'],
S
SheetJS 已提交
3151 3152 3153 3154 3155 3156 3157 3158 3159
	/* from test files */
	['bmp', 'image/bmp'],
	['png', 'image/png'],
	['gif', 'image/gif'],
	['emf', 'image/x-emf'],
	['wmf', 'image/x-wmf'],
	['jpg', 'image/jpeg'], ['jpeg', 'image/jpeg'],
	['tif', 'image/tiff'], ['tiff', 'image/tiff'],
	['pdf', 'application/pdf'],
S
SheetJS 已提交
3160 3161 3162 3163 3164
	['rels', type2ct.rels[0]]
].map(function(x) {
	return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
});

S
SheetJS 已提交
3165 3166
function write_ct(ct, opts)/*:string*/ {
	var o/*:Array<string>*/ = [], v;
S
SheetJS 已提交
3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179
	o[o.length] = (XML_HEADER);
	o[o.length] = (CTYPE_XML_ROOT);
	o = o.concat(CTYPE_DEFAULTS);
	var f1 = function(w) {
		if(ct[w] && ct[w].length > 0) {
			v = ct[w][0];
			o[o.length] = (writextag('Override', null, {
				'PartName': (v[0] == '/' ? "":"/") + v,
				'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
			}));
		}
	};
	var f2 = function(w) {
S
SheetJS 已提交
3180
		(ct[w]||[]).forEach(function(v) {
S
SheetJS 已提交
3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196
			o[o.length] = (writextag('Override', null, {
				'PartName': (v[0] == '/' ? "":"/") + v,
				'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
			}));
		});
	};
	var f3 = function(t) {
		(ct[t]||[]).forEach(function(v) {
			o[o.length] = (writextag('Override', null, {
				'PartName': (v[0] == '/' ? "":"/") + v,
				'ContentType': type2ct[t][0]
			}));
		});
	};
	f1('workbooks');
	f2('sheets');
S
SheetJS 已提交
3197
	f2('charts');
S
SheetJS 已提交
3198 3199 3200
	f3('themes');
	['strs', 'styles'].forEach(f1);
	['coreprops', 'extprops', 'custprops'].forEach(f3);
S
SheetJS 已提交
3201
	f3('vba');
S
SheetJS 已提交
3202 3203
	f3('comments');
	f3('drawings');
S
SheetJS 已提交
3204 3205 3206
	if(o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
	return o.join("");
}
3207
/* 9.3 Relationships */
S
SheetJS 已提交
3208
var RELS = ({
S
SheetJS 已提交
3209
	WB: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
S
SheetJS 已提交
3210
	SHEET: "http://sheetjs.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
S
SheetJS 已提交
3211
	HLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
S
SheetJS 已提交
3212
	VML: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing",
S
SheetJS 已提交
3213
	VBA: "http://schemas.microsoft.com/office/2006/relationships/vbaProject"
S
SheetJS 已提交
3214
}/*:any*/);
S
SheetJS 已提交
3215

3216 3217 3218
/* 9.3.3 Representing Relationships */
function get_rels_path(file/*:string*/)/*:string*/ {
	var n = file.lastIndexOf("/");
S
SheetJS 已提交
3219
	return file.substr(0,n+1) + '_rels/' + file.substr(n+1) + ".rels";
3220 3221
}

S
SheetJS 已提交
3222
function parse_rels(data/*:?string*/, currentFilePath/*:string*/) {
S
SheetJS 已提交
3223 3224 3225 3226 3227 3228 3229
	if (!data) return data;
	if (currentFilePath.charAt(0) !== '/') {
		currentFilePath = '/'+currentFilePath;
	}
	var rels = {};
	var hash = {};

S
SheetJS 已提交
3230
	(data.match(tagregex)||[]).forEach(function(x) {
S
SheetJS 已提交
3231 3232 3233 3234
		var y = parsexmltag(x);
		/* 9.3.2.2 OPC_Relationships */
		if (y[0] === '<Relationship') {
			var rel = {}; rel.Type = y.Type; rel.Target = y.Target; rel.Id = y.Id; rel.TargetMode = y.TargetMode;
3235
			var canonictarget = y.TargetMode === 'External' ? y.Target : resolve_path(y.Target, currentFilePath);
S
SheetJS 已提交
3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251
			rels[canonictarget] = rel;
			hash[y.Id] = rel;
		}
	});
	rels["!id"] = hash;
	return rels;
}

XMLNS.RELS = 'http://schemas.openxmlformats.org/package/2006/relationships';

var RELS_ROOT = writextag('Relationships', null, {
	//'xmlns:ns0': XMLNS.RELS,
	'xmlns': XMLNS.RELS
});

/* TODO */
S
SheetJS 已提交
3252
function write_rels(rels)/*:string*/ {
S
SheetJS 已提交
3253 3254 3255
	var o = [XML_HEADER, RELS_ROOT];
	keys(rels['!id']).forEach(function(rid) {
		o[o.length] = (writextag('Relationship', null, rels['!id'][rid]));
S
SheetJS 已提交
3256 3257 3258 3259
	});
	if(o.length>2){ o[o.length] = ('</Relationships>'); o[1]=o[1].replace("/>",">"); }
	return o.join("");
}
S
SheetJS 已提交
3260 3261 3262 3263

function add_rels(rels, rId, f, type, relobj)/*:number*/ {
	if(!relobj) relobj = {};
	if(!rels['!id']) rels['!id'] = {};
S
SheetJS 已提交
3264
	if(rId < 0) for(rId = 1; rels['!id']['rId' + rId]; ++rId){/* empty */}
S
SheetJS 已提交
3265 3266 3267 3268 3269 3270 3271 3272 3273
	relobj.Id = 'rId' + rId;
	relobj.Type = type;
	relobj.Target = f;
	if(relobj.Type == RELS.HLINK) relobj.TargetMode = "External";
	if(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId);
	rels['!id'][relobj.Id] = relobj;
	rels[('/' + relobj.Target).replace("//","/")] = relobj;
	return rId;
}
3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330
/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
/* Part 3 Section 4 Manifest File */
var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
function parse_manifest(d, opts) {
	var str = xlml_normalize(d);
	var Rn;
	var FEtag;
	while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
		case 'manifest': break; // 4.2 <manifest:manifest>
		case 'file-entry': // 4.3 <manifest:file-entry>
			FEtag = parsexmltag(Rn[0], false);
			if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet");
			break;
		case 'encryption-data': // 4.4 <manifest:encryption-data>
		case 'algorithm': // 4.5 <manifest:algorithm>
		case 'start-key-generation': // 4.6 <manifest:start-key-generation>
		case 'key-derivation': // 4.7 <manifest:key-derivation>
			throw new Error("Unsupported ODS Encryption");
		default: if(opts && opts.WTF) throw Rn;
	}
}

function write_manifest(manifest/*:Array<Array<string> >*/, opts)/*:string*/ {
	var o = [XML_HEADER];
	o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
	o.push('  <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
	for(var i = 0; i < manifest.length; ++i) o.push('  <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
	o.push('</manifest:manifest>');
	return o.join("");
}

/* Part 3 Section 6 Metadata Manifest File */
function write_rdf_type(file/*:string*/, res/*:string*/, tag/*:?string*/) {
	return [
		'  <rdf:Description rdf:about="' + file + '">\n',
		'    <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
		'  </rdf:Description>\n'
	].join("");
}
function write_rdf_has(base/*:string*/, file/*:string*/) {
	return [
		'  <rdf:Description rdf:about="' + base + '">\n',
		'    <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
		'  </rdf:Description>\n'
	].join("");
}
function write_rdf(rdf, opts) {
	var o = [XML_HEADER];
	o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
	for(var i = 0; i != rdf.length; ++i) {
		o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
		o.push(write_rdf_has("",rdf[i][0]));
	}
	o.push(write_rdf_type("","Document", "pkg"));
	o.push('</rdf:RDF>');
	return o.join("");
}
S
SheetJS 已提交
3331 3332 3333 3334 3335 3336 3337 3338
/* TODO: pull properties */
var write_meta_ods/*:{(wb:any, opts:any):string}*/ = (function() {
	var payload = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
	return function wmo(wb, opts) {
		return payload;
	};
})();

S
SheetJS 已提交
3339 3340
/* ECMA-376 Part II 11.1 Core Properties Part */
/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
S
SheetJS 已提交
3341
var CORE_PROPS/*:Array<Array<string> >*/ = [
S
SheetJS 已提交
3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361
	["cp:category", "Category"],
	["cp:contentStatus", "ContentStatus"],
	["cp:keywords", "Keywords"],
	["cp:lastModifiedBy", "LastAuthor"],
	["cp:lastPrinted", "LastPrinted"],
	["cp:revision", "RevNumber"],
	["cp:version", "Version"],
	["dc:creator", "Author"],
	["dc:description", "Comments"],
	["dc:identifier", "Identifier"],
	["dc:language", "Language"],
	["dc:subject", "Subject"],
	["dc:title", "Title"],
	["dcterms:created", "CreatedDate", 'date'],
	["dcterms:modified", "ModifiedDate", 'date']
];

XMLNS.CORE_PROPS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
RELS.CORE_PROPS  = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';

S
SheetJS 已提交
3362
var CORE_PROPS_REGEX/*:Array<RegExp>*/ = (function() {
S
SheetJS 已提交
3363 3364 3365 3366
	var r = new Array(CORE_PROPS.length);
	for(var i = 0; i < CORE_PROPS.length; ++i) {
		var f = CORE_PROPS[i];
		var g = "(?:"+ f[0].substr(0,f[0].indexOf(":")) +":)"+ f[0].substr(f[0].indexOf(":")+1);
3367
		r[i] = new RegExp("<" + g + "[^>]*>([\\s\\S]*?)<\/" + g + ">");
S
SheetJS 已提交
3368 3369 3370 3371 3372 3373 3374 3375 3376 3377
	}
	return r;
})();

function parse_core_props(data) {
	var p = {};

	for(var i = 0; i < CORE_PROPS.length; ++i) {
		var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
		if(cur != null && cur.length > 0) p[f[1]] = cur[1];
S
SheetJS 已提交
3378
		if(f[2] === 'date' && p[f[1]]) p[f[1]] = parseDate(p[f[1]]);
S
SheetJS 已提交
3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398
	}

	return p;
}

var CORE_PROPS_XML_ROOT = writextag('cp:coreProperties', null, {
	//'xmlns': XMLNS.CORE_PROPS,
	'xmlns:cp': XMLNS.CORE_PROPS,
	'xmlns:dc': XMLNS.dc,
	'xmlns:dcterms': XMLNS.dcterms,
	'xmlns:dcmitype': XMLNS.dcmitype,
	'xmlns:xsi': XMLNS.xsi
});

function cp_doit(f, g, h, o, p) {
	if(p[f] != null || g == null || g === "") return;
	p[f] = g;
	o[o.length] = (h ? writextag(f,g,h) : writetag(f,g));
}

S
SheetJS 已提交
3399 3400
function write_core_props(cp, _opts) {
	var opts = _opts || {};
S
SheetJS 已提交
3401
	var o = [XML_HEADER, CORE_PROPS_XML_ROOT], p = {};
S
SheetJS 已提交
3402
	if(!cp && !opts.Props) return o.join("");
S
SheetJS 已提交
3403

S
SheetJS 已提交
3404 3405 3406 3407
	if(cp) {
		if(cp.CreatedDate != null) cp_doit("dcterms:created", typeof cp.CreatedDate === "string" ? cp.CreatedDate : write_w3cdtf(cp.CreatedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
		if(cp.ModifiedDate != null) cp_doit("dcterms:modified", typeof cp.ModifiedDate === "string" ? cp.ModifiedDate : write_w3cdtf(cp.ModifiedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
	}
S
SheetJS 已提交
3408

S
SheetJS 已提交
3409 3410 3411 3412 3413 3414 3415 3416
	for(var i = 0; i != CORE_PROPS.length; ++i) {
		var f = CORE_PROPS[i];
		var v = opts.Props && opts.Props[f[1]] != null ? opts.Props[f[1]] : cp ? cp[f[1]] : null;
		if(v === true) v = "1";
		else if(v === false) v = "0";
		else if(typeof v == "number") v = String(v);
		if(v != null) cp_doit(f[0], v, null, o, p);
	}
S
SheetJS 已提交
3417 3418 3419 3420 3421
	if(o.length>2){ o[o.length] = ('</cp:coreProperties>'); o[1]=o[1].replace("/>",">"); }
	return o.join("");
}
/* 15.2.12.3 Extended File Properties Part */
/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
S
SheetJS 已提交
3422
var EXT_PROPS/*:Array<Array<string> >*/ = [
S
SheetJS 已提交
3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438
	["Application", "Application", "string"],
	["AppVersion", "AppVersion", "string"],
	["Company", "Company", "string"],
	["DocSecurity", "DocSecurity", "string"],
	["Manager", "Manager", "string"],
	["HyperlinksChanged", "HyperlinksChanged", "bool"],
	["SharedDoc", "SharedDoc", "bool"],
	["LinksUpToDate", "LinksUpToDate", "bool"],
	["ScaleCrop", "ScaleCrop", "bool"],
	["HeadingPairs", "HeadingPairs", "raw"],
	["TitlesOfParts", "TitlesOfParts", "raw"]
];

XMLNS.EXT_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
RELS.EXT_PROPS  = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';

3439
function parse_ext_props(data, p, opts) {
S
SheetJS 已提交
3440 3441 3442 3443 3444 3445 3446
	var q = {}; if(!p) p = {};

	EXT_PROPS.forEach(function(f) {
		switch(f[2]) {
			case "string": p[f[1]] = (data.match(matchtag(f[0]))||[])[1]; break;
			case "bool": p[f[1]] = (data.match(matchtag(f[0]))||[])[1] === "true"; break;
			case "raw":
3447
				var cur = data.match(new RegExp("<" + f[0] + "[^>]*>([\\s\\S]*?)<\/" + f[0] + ">"));
S
SheetJS 已提交
3448 3449 3450 3451 3452 3453
				if(cur && cur.length > 0) q[f[1]] = cur[1];
				break;
		}
	});

	if(q.HeadingPairs && q.TitlesOfParts) {
3454 3455
		var v = parseVector(q.HeadingPairs, opts);
		var parts = parseVector(q.TitlesOfParts, opts).map(function (x) { return x.v; });
3456
		var idx = 0, len = 0;
3457
		if(parts.length > 0) for(var i = 0; i !== v.length; i += 2) {
S
SheetJS 已提交
3458
			len = +(v[i+1].v);
S
SheetJS 已提交
3459
			switch(v[i].v) {
3460
				case "Worksheets":
O
OliverZ 已提交
3461 3462
				case "工作表":
				case "Листы":
S
SheetJS 已提交
3463
				case "أوراق العمل":
O
OliverZ 已提交
3464 3465 3466 3467 3468 3469 3470 3471
				case "ワークシート":
				case "גליונות עבודה":
				case "Arbeitsblätter":
				case "Çalışma Sayfaları":
				case "Feuilles de calcul":
				case "Fogli di lavoro":
				case "Folhas de cálculo":
				case "Planilhas":
3472
				case "Regneark":
O
OliverZ 已提交
3473
				case "Werkbladen":
3474 3475 3476
					p.Worksheets = len;
					p.SheetNames = parts.slice(idx, idx + len);
					break;
O
OliverZ 已提交
3477

3478
				case "Named Ranges":
S
SheetJS 已提交
3479
				case "名前付き一覧":
O
OliverZ 已提交
3480
				case "Benannte Bereiche":
3481
				case "Navngivne områder":
3482 3483 3484
					p.NamedRanges = len;
					p.DefinedNames = parts.slice(idx, idx + len);
					break;
O
OliverZ 已提交
3485

3486 3487 3488 3489 3490
				case "Charts":
				case "Diagramme":
					p.Chartsheets = len;
					p.ChartNames = parts.slice(idx, idx + len);
					break;
S
SheetJS 已提交
3491
			}
3492
			idx += len;
S
SheetJS 已提交
3493 3494
		}
	}
S
SheetJS 已提交
3495

S
SheetJS 已提交
3496 3497 3498 3499 3500 3501 3502 3503
	return p;
}

var EXT_PROPS_XML_ROOT = writextag('Properties', null, {
	'xmlns': XMLNS.EXT_PROPS,
	'xmlns:vt': XMLNS.vt
});

S
SheetJS 已提交
3504
function write_ext_props(cp, opts)/*:string*/ {
S
SheetJS 已提交
3505 3506 3507 3508 3509 3510 3511 3512 3513 3514
	var o = [], p = {}, W = writextag;
	if(!cp) cp = {};
	cp.Application = "SheetJS";
	o[o.length] = (XML_HEADER);
	o[o.length] = (EXT_PROPS_XML_ROOT);

	EXT_PROPS.forEach(function(f) {
		if(cp[f[1]] === undefined) return;
		var v;
		switch(f[2]) {
S
SheetJS 已提交
3515
			case 'string': v = String(cp[f[1]]); break;
S
SheetJS 已提交
3516 3517 3518 3519 3520 3521 3522
			case 'bool': v = cp[f[1]] ? 'true' : 'false'; break;
		}
		if(v !== undefined) o[o.length] = (W(f[0], v));
	});

	/* TODO: HeadingPairs, TitlesOfParts */
	o[o.length] = (W('HeadingPairs', W('vt:vector', W('vt:variant', '<vt:lpstr>Worksheets</vt:lpstr>')+W('vt:variant', W('vt:i4', String(cp.Worksheets))), {size:2, baseType:"variant"})));
S
SheetJS 已提交
3523
	o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + escapexml(s) + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
S
SheetJS 已提交
3524 3525 3526 3527 3528 3529 3530 3531
	if(o.length>2){ o[o.length] = ('</Properties>'); o[1]=o[1].replace("/>",">"); }
	return o.join("");
}
/* 15.2.12.2 Custom File Properties Part */
XMLNS.CUST_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
RELS.CUST_PROPS  = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties';

var custregex = /<[^>]+>[^<]*/g;
S
SheetJS 已提交
3532 3533
function parse_cust_props(data/*:string*/, opts) {
	var p = {}, name = "";
S
SheetJS 已提交
3534 3535 3536 3537 3538
	var m = data.match(custregex);
	if(m) for(var i = 0; i != m.length; ++i) {
		var x = m[i], y = parsexmltag(x);
		switch(y[0]) {
			case '<?xml': break;
S
SheetJS 已提交
3539
			case '<Properties': break;
S
SheetJS 已提交
3540 3541 3542 3543 3544 3545 3546
			case '<property': name = y.name; break;
			case '</property>': name = null; break;
			default: if (x.indexOf('<vt:') === 0) {
				var toks = x.split('>');
				var type = toks[0].substring(4), text = toks[1];
				/* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */
				switch(type) {
S
SheetJS 已提交
3547
					case 'lpstr': case 'bstr': case 'lpwstr':
S
SheetJS 已提交
3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559
						p[name] = unescapexml(text);
						break;
					case 'bool':
						p[name] = parsexmlbool(text, '<vt:bool>');
						break;
					case 'i1': case 'i2': case 'i4': case 'i8': case 'int': case 'uint':
						p[name] = parseInt(text, 10);
						break;
					case 'r4': case 'r8': case 'decimal':
						p[name] = parseFloat(text);
						break;
					case 'filetime': case 'date':
S
SheetJS 已提交
3560
						p[name] = parseDate(text);
S
SheetJS 已提交
3561 3562 3563 3564 3565
						break;
					case 'cy': case 'error':
						p[name] = unescapexml(text);
						break;
					default:
S
SheetJS 已提交
3566
						if(type.slice(-1) == '/') break;
S
SheetJS 已提交
3567 3568
						if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks);
				}
S
SheetJS 已提交
3569
			} else if(x.substr(0,2) === "</") {/* empty */
S
SheetJS 已提交
3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580
			} else if(opts.WTF) throw new Error(x);
		}
	}
	return p;
}

var CUST_PROPS_XML_ROOT = writextag('Properties', null, {
	'xmlns': XMLNS.CUST_PROPS,
	'xmlns:vt': XMLNS.vt
});

S
SheetJS 已提交
3581
function write_cust_props(cp, opts)/*:string*/ {
S
SheetJS 已提交
3582 3583 3584 3585
	var o = [XML_HEADER, CUST_PROPS_XML_ROOT];
	if(!cp) return o.join("");
	var pid = 1;
	keys(cp).forEach(function custprop(k) { ++pid;
S
SheetJS 已提交
3586
		// $FlowIgnore
S
SheetJS 已提交
3587 3588 3589 3590 3591 3592 3593 3594 3595
		o[o.length] = (writextag('property', write_vt(cp[k]), {
			'fmtid': '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}',
			'pid': pid,
			'name': k
		}));
	});
	if(o.length>2){ o[o.length] = '</Properties>'; o[1]=o[1].replace("/>",">"); }
	return o.join("");
}
S
SheetJS 已提交
3596 3597
/* Common Name -> XLML Name */
var XLMLDocPropsMap = {
S
SheetJS 已提交
3598 3599 3600
	Title: 'Title',
	Subject: 'Subject',
	Author: 'Author',
S
SheetJS 已提交
3601
	Keywords: 'Keywords',
S
SheetJS 已提交
3602
	Comments: 'Description',
S
SheetJS 已提交
3603 3604
	LastAuthor: 'LastAuthor',
	RevNumber: 'Revision',
S
SheetJS 已提交
3605 3606 3607
	Application: 'AppName',
	/* TotalTime: 'TotalTime', */
	LastPrinted: 'LastPrinted',
S
SheetJS 已提交
3608 3609
	CreatedDate: 'Created',
	ModifiedDate: 'LastSaved',
S
SheetJS 已提交
3610 3611 3612 3613 3614
	/* Pages */
	/* Words */
	/* Characters */
	Category: 'Category',
	/* PresentationFormat */
S
SheetJS 已提交
3615
	Manager: 'Manager',
S
SheetJS 已提交
3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627
	Company: 'Company',
	/* Guid */
	/* HyperlinkBase */
	/* Bytes */
	/* Lines */
	/* Paragraphs */
	/* CharactersWithSpaces */
	AppVersion: 'Version',

	ContentStatus: 'ContentStatus', /* NOTE: missing from schema */
	Identifier: 'Identifier', /* NOTE: missing from schema */
	Language: 'Language' /* NOTE: missing from schema */
S
SheetJS 已提交
3628 3629 3630
};
var evert_XLMLDPM = evert(XLMLDocPropsMap);

S
SheetJS 已提交
3631
function xlml_set_prop(Props, tag/*:string*/, val) {
S
SheetJS 已提交
3632
	tag = evert_XLMLDPM[tag] || tag;
S
SheetJS 已提交
3633 3634 3635
	Props[tag] = val;
}

S
SheetJS 已提交
3636
function xlml_write_docprops(Props, opts) {
S
SheetJS 已提交
3637
	var o = [];
S
SheetJS 已提交
3638 3639 3640 3641 3642
	keys(XLMLDocPropsMap).map(function(m) {
		for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i];
		for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i];
		throw m;
	}).forEach(function(p) {
S
SheetJS 已提交
3643 3644
		if(Props[p[1]] == null) return;
		var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]];
S
SheetJS 已提交
3645
		switch(p[2]) {
S
SheetJS 已提交
3646
			case 'date': m = new Date(m).toISOString().replace(/\.\d*Z/,"Z"); break;
S
SheetJS 已提交
3647
		}
S
SheetJS 已提交
3648
		if(typeof m == 'number') m = String(m);
S
SheetJS 已提交
3649
		else if(m === true || m === false) { m = m ? "1" : "0"; }
S
SheetJS 已提交
3650
		else if(m instanceof Date) m = new Date(m).toISOString().replace(/\.\d*Z/,"");
S
SheetJS 已提交
3651
		o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m));
S
SheetJS 已提交
3652
	});
S
SheetJS 已提交
3653
	return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o });
S
SheetJS 已提交
3654
}
S
SheetJS 已提交
3655 3656
function xlml_write_custprops(Props, Custprops, opts) {
	var BLACKLIST = ["Worksheets","SheetNames"];
S
SheetJS 已提交
3657 3658 3659 3660 3661
	var T = 'CustomDocumentProperties';
	var o = [];
	if(Props) keys(Props).forEach(function(k) {
		/*:: if(!Props) return; */
		if(!Props.hasOwnProperty(k)) return;
S
SheetJS 已提交
3662 3663 3664 3665
		for(var i = 0; i < CORE_PROPS.length; ++i) if(k == CORE_PROPS[i][1]) return;
		for(i = 0; i < EXT_PROPS.length; ++i) if(k == EXT_PROPS[i][1]) return;
		for(i = 0; i < BLACKLIST.length; ++i) if(k == BLACKLIST[i]) return;

S
SheetJS 已提交
3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685
		var m = Props[k];
		var t = "string";
		if(typeof m == 'number') { t = "float"; m = String(m); }
		else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
		else m = String(m);
		o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
	});
	if(Custprops) keys(Custprops).forEach(function(k) {
		/*:: if(!Custprops) return; */
		if(!Custprops.hasOwnProperty(k)) return;
		var m = Custprops[k];
		var t = "string";
		if(typeof m == 'number') { t = "float"; m = String(m); }
		else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
		else if(m instanceof Date) { t = "dateTime.tz"; m = m.toISOString(); }
		else m = String(m);
		o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
	});
	return '<' + T + ' xmlns="' + XLMLNS.o + '">' + o.join("") + '</' + T + '>';
}
S
SheetJS 已提交
3686 3687 3688 3689 3690 3691 3692 3693 3694
/* [MS-DTYP] 2.3.3 FILETIME */
/* [MS-OLEDS] 2.1.3 FILETIME (Packet Version) */
/* [MS-OLEPS] 2.8 FILETIME (Packet Version) */
function parse_FILETIME(blob) {
	var dwLowDateTime = blob.read_shift(4), dwHighDateTime = blob.read_shift(4);
	return new Date(((dwHighDateTime/1e7*Math.pow(2,32) + dwLowDateTime/1e7) - 11644473600)*1000).toISOString().replace(/\.000/,"");
}

/* [MS-OSHARED] 2.3.3.1.4 Lpstr */
S
SheetJS 已提交
3695
function parse_lpstr(blob, type, pad/*:?number*/) {
S
SheetJS 已提交
3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715
	var str = blob.read_shift(0, 'lpstr');
	if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3;
	return str;
}

/* [MS-OSHARED] 2.3.3.1.6 Lpwstr */
function parse_lpwstr(blob, type, pad) {
	var str = blob.read_shift(0, 'lpwstr');
	if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3;
	return str;
}


/* [MS-OSHARED] 2.3.3.1.11 VtString */
/* [MS-OSHARED] 2.3.3.1.12 VtUnalignedString */
function parse_VtStringBase(blob, stringType, pad) {
	if(stringType === 0x1F /*VT_LPWSTR*/) return parse_lpwstr(blob);
	return parse_lpstr(blob, stringType, pad);
}

S
SheetJS 已提交
3716 3717
function parse_VtString(blob, t/*:number*/, pad/*:?boolean*/) { return parse_VtStringBase(blob, t, pad === false ? 0: 4); }
function parse_VtUnalignedString(blob, t/*:number*/) { if(!t) throw new Error("VtUnalignedString must have positive length"); return parse_VtStringBase(blob, t, 0); }
S
SheetJS 已提交
3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755

/* [MS-OSHARED] 2.3.3.1.9 VtVecUnalignedLpstrValue */
function parse_VtVecUnalignedLpstrValue(blob) {
	var length = blob.read_shift(4);
	var ret = [];
	for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr');
	return ret;
}

/* [MS-OSHARED] 2.3.3.1.10 VtVecUnalignedLpstr */
function parse_VtVecUnalignedLpstr(blob) {
	return parse_VtVecUnalignedLpstrValue(blob);
}

/* [MS-OSHARED] 2.3.3.1.13 VtHeadingPair */
function parse_VtHeadingPair(blob) {
	var headingString = parse_TypedPropertyValue(blob, VT_USTR);
	var headerParts = parse_TypedPropertyValue(blob, VT_I4);
	return [headingString, headerParts];
}

/* [MS-OSHARED] 2.3.3.1.14 VtVecHeadingPairValue */
function parse_VtVecHeadingPairValue(blob) {
	var cElements = blob.read_shift(4);
	var out = [];
	for(var i = 0; i != cElements / 2; ++i) out.push(parse_VtHeadingPair(blob));
	return out;
}

/* [MS-OSHARED] 2.3.3.1.15 VtVecHeadingPair */
function parse_VtVecHeadingPair(blob) {
	// NOTE: When invoked, wType & padding were already consumed
	return parse_VtVecHeadingPairValue(blob);
}

/* [MS-OLEPS] 2.18.1 Dictionary (uses 2.17, 2.16) */
function parse_dictionary(blob,CodePage) {
	var cnt = blob.read_shift(4);
S
SheetJS 已提交
3756
	var dict/*:{[number]:string}*/ = ({}/*:any*/);
S
SheetJS 已提交
3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769
	for(var j = 0; j != cnt; ++j) {
		var pid = blob.read_shift(4);
		var len = blob.read_shift(4);
		dict[pid] = blob.read_shift(len, (CodePage === 0x4B0 ?'utf16le':'utf8')).replace(chr0,'').replace(chr1,'!');
	}
	if(blob.l & 3) blob.l = (blob.l>>2+1)<<2;
	return dict;
}

/* [MS-OLEPS] 2.9 BLOB */
function parse_BLOB(blob) {
	var size = blob.read_shift(4);
	var bytes = blob.slice(blob.l,blob.l+size);
S
SheetJS 已提交
3770
	if((size & 3) > 0) blob.l += (4 - (size & 3)) & 3;
S
SheetJS 已提交
3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795
	return bytes;
}

/* [MS-OLEPS] 2.11 ClipboardData */
function parse_ClipboardData(blob) {
	// TODO
	var o = {};
	o.Size = blob.read_shift(4);
	//o.Format = blob.read_shift(4);
	blob.l += o.Size;
	return o;
}

/* [MS-OLEPS] 2.14 Vector and Array Property Types */
function parse_VtVector(blob, cb) {
	/* [MS-OLEPS] 2.14.2 VectorHeader */
/*	var Length = blob.read_shift(4);
	var o = [];
	for(var i = 0; i != Length; ++i) {
		o.push(cb(blob));
	}
	return o;*/
}

/* [MS-OLEPS] 2.15 TypedPropertyValue */
3796
function parse_TypedPropertyValue(blob, type/*:number*/, _opts) {
S
SheetJS 已提交
3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810
	var t = blob.read_shift(2), ret, opts = _opts||{};
	blob.l += 2;
	if(type !== VT_VARIANT)
	if(t !== type && VT_CUSTOM.indexOf(type)===-1) throw new Error('Expected type ' + type + ' saw ' + t);
	switch(type === VT_VARIANT ? t : type) {
		case 0x02 /*VT_I2*/: ret = blob.read_shift(2, 'i'); if(!opts.raw) blob.l += 2; return ret;
		case 0x03 /*VT_I4*/: ret = blob.read_shift(4, 'i'); return ret;
		case 0x0B /*VT_BOOL*/: return blob.read_shift(4) !== 0x0;
		case 0x13 /*VT_UI4*/: ret = blob.read_shift(4); return ret;
		case 0x1E /*VT_LPSTR*/: return parse_lpstr(blob, t, 4).replace(chr0,'');
		case 0x1F /*VT_LPWSTR*/: return parse_lpwstr(blob);
		case 0x40 /*VT_FILETIME*/: return parse_FILETIME(blob);
		case 0x41 /*VT_BLOB*/: return parse_BLOB(blob);
		case 0x47 /*VT_CF*/: return parse_ClipboardData(blob);
S
SheetJS 已提交
3811
		case 0x50 /*VT_STRING*/: return parse_VtString(blob, t, !opts.raw).replace(chr0,'');
3812
		case 0x51 /*VT_USTR*/: return parse_VtUnalignedString(blob, t/*, 4*/).replace(chr0,'');
S
SheetJS 已提交
3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836
		case 0x100C /*VT_VECTOR|VT_VARIANT*/: return parse_VtVecHeadingPair(blob);
		case 0x101E /*VT_LPSTR*/: return parse_VtVecUnalignedLpstr(blob);
		default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + t);
	}
}
/* [MS-OLEPS] 2.14.2 VectorHeader */
/*function parse_VTVectorVariant(blob) {
	var Length = blob.read_shift(4);

	if(Length & 1 !== 0) throw new Error("VectorHeader Length=" + Length + " must be even");
	var o = [];
	for(var i = 0; i != Length; ++i) {
		o.push(parse_TypedPropertyValue(blob, VT_VARIANT));
	}
	return o;
}*/

/* [MS-OLEPS] 2.20 PropertySet */
function parse_PropertySet(blob, PIDSI) {
	var start_addr = blob.l;
	var size = blob.read_shift(4);
	var NumProps = blob.read_shift(4);
	var Props = [], i = 0;
	var CodePage = 0;
S
SheetJS 已提交
3837
	var Dictionary = -1, DictObj/*:{[number]:string}*/ = ({}/*:any*/);
S
SheetJS 已提交
3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861
	for(i = 0; i != NumProps; ++i) {
		var PropID = blob.read_shift(4);
		var Offset = blob.read_shift(4);
		Props[i] = [PropID, Offset + start_addr];
	}
	var PropH = {};
	for(i = 0; i != NumProps; ++i) {
		if(blob.l !== Props[i][1]) {
			var fail = true;
			if(i>0 && PIDSI) switch(PIDSI[Props[i-1][0]].t) {
				case 0x02 /*VT_I2*/: if(blob.l +2 === Props[i][1]) { blob.l+=2; fail = false; } break;
				case 0x50 /*VT_STRING*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
				case 0x100C /*VT_VECTOR|VT_VARIANT*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
			}
			if(!PIDSI && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; }
			if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i);
		}
		if(PIDSI) {
			var piddsi = PIDSI[Props[i][0]];
			PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true});
			if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + String(PropH[piddsi.n] & 0xFFFF);
			if(piddsi.n == "CodePage") switch(PropH[piddsi.n]) {
				case 0: PropH[piddsi.n] = 1252;
					/* falls through */
S
SheetJS 已提交
3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880
				case 874:
				case 932:
				case 936:
				case 949:
				case 950:
				case 1250:
				case 1251:
				case 1253:
				case 1254:
				case 1255:
				case 1256:
				case 1257:
				case 1258:
				case 10000:
				case 1200:
				case 1201:
				case 1252:
				case 65000: case -536:
				case 65001: case -535:
S
SheetJS 已提交
3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908
					set_cp(CodePage = PropH[piddsi.n]); break;
				default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
			}
		} else {
			if(Props[i][0] === 0x1) {
				CodePage = PropH.CodePage = parse_TypedPropertyValue(blob, VT_I2);
				set_cp(CodePage);
				if(Dictionary !== -1) {
					var oldpos = blob.l;
					blob.l = Props[Dictionary][1];
					DictObj = parse_dictionary(blob,CodePage);
					blob.l = oldpos;
				}
			} else if(Props[i][0] === 0) {
				if(CodePage === 0) { Dictionary = i; blob.l = Props[i+1][1]; continue; }
				DictObj = parse_dictionary(blob,CodePage);
			} else {
				var name = DictObj[Props[i][0]];
				var val;
				/* [MS-OSHARED] 2.3.3.2.3.1.2 + PROPVARIANT */
				switch(blob[blob.l]) {
					case 0x41 /*VT_BLOB*/: blob.l += 4; val = parse_BLOB(blob); break;
					case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]); break;
					case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]); break;
					case 0x03 /*VT_I4*/: blob.l += 4; val = blob.read_shift(4, 'i'); break;
					case 0x13 /*VT_UI4*/: blob.l += 4; val = blob.read_shift(4); break;
					case 0x05 /*VT_R8*/: blob.l += 4; val = blob.read_shift(8, 'f'); break;
					case 0x0B /*VT_BOOL*/: blob.l += 4; val = parsebool(blob, 4); break;
S
SheetJS 已提交
3909
					case 0x40 /*VT_FILETIME*/: blob.l += 4; val = parseDate(parse_FILETIME(blob)); break;
S
SheetJS 已提交
3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924
					default: throw new Error("unparsed value: " + blob[blob.l]);
				}
				PropH[name] = val;
			}
		}
	}
	blob.l = start_addr + size; /* step ahead to skip padding */
	return PropH;
}

/* [MS-OLEPS] 2.21 PropertySetStream */
function parse_PropertySetStream(file, PIDSI) {
	var blob = file.content;
	prep_blob(blob, 0);

S
SheetJS 已提交
3925
	var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;
S
SheetJS 已提交
3926 3927 3928 3929 3930 3931
	blob.chk('feff', 'Byte Order: ');

	var vers = blob.read_shift(2); // TODO: check version
	var SystemIdentifier = blob.read_shift(4);
	blob.chk(CFB.utils.consts.HEADER_CLSID, 'CLSID: ');
	NumSets = blob.read_shift(4);
3932
	if(NumSets !== 1 && NumSets !== 2) throw new Error("Unrecognized #Sets: " + NumSets);
S
SheetJS 已提交
3933 3934
	FMTID0 = blob.read_shift(16); Offset0 = blob.read_shift(4);

3935
	if(NumSets === 1 && Offset0 !== blob.l) throw new Error("Length mismatch: " + Offset0 + " !== " + blob.l);
S
SheetJS 已提交
3936 3937 3938
	else if(NumSets === 2) { FMTID1 = blob.read_shift(16); Offset1 = blob.read_shift(4); }
	var PSet0 = parse_PropertySet(blob, PIDSI);

S
SheetJS 已提交
3939
	var rval = ({ SystemIdentifier: SystemIdentifier }/*:any*/);
S
SheetJS 已提交
3940 3941 3942 3943 3944
	for(var y in PSet0) rval[y] = PSet0[y];
	//rval.blob = blob;
	rval.FMTID = FMTID0;
	//rval.PSet0 = PSet0;
	if(NumSets === 1) return rval;
S
SheetJS 已提交
3945
	if(blob.l !== Offset1) throw new Error("Length mismatch 2: " + blob.l + " !== " + Offset1);
S
SheetJS 已提交
3946
	var PSet1;
S
SheetJS 已提交
3947
	try { PSet1 = parse_PropertySet(blob, null); } catch(e) {/* empty */}
S
SheetJS 已提交
3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964
	for(y in PSet1) rval[y] = PSet1[y];
	rval.FMTID = [FMTID0, FMTID1]; // TODO: verify FMTID0/1
	return rval;
}


function parsenoop2(blob, length) { blob.read_shift(length); return null; }

function parslurp(blob, length, cb) {
	var arr = [], target = blob.l + length;
	while(blob.l < target) arr.push(cb(blob, target - blob.l));
	if(target !== blob.l) throw new Error("Slurp error");
	return arr;
}

function parsebool(blob, length) { return blob.read_shift(length) === 0x1; }

3965 3966
function parseuint16(blob/*::, length:?number, opts:?any*/) { return blob.read_shift(2, 'u'); }
function parseuint16a(blob, length/*:: :?number, opts:?any*/) { return parslurp(blob,length,parseuint16);}
S
SheetJS 已提交
3967 3968 3969 3970 3971 3972 3973

/* --- 2.5 Structures --- */

/* [MS-XLS] 2.5.14 Boolean */
var parse_Boolean = parsebool;

/* [MS-XLS] 2.5.10 Bes (boolean or error) */
3974
function parse_Bes(blob/*::, length*/) {
S
SheetJS 已提交
3975 3976 3977 3978 3979 3980
	var v = blob.read_shift(1), t = blob.read_shift(1);
	return t === 0x01 ? v : v === 0x01;
}

/* [MS-XLS] 2.5.240 ShortXLUnicodeString */
function parse_ShortXLUnicodeString(blob, length, opts) {
S
SheetJS 已提交
3981
	var cch = blob.read_shift(opts && opts.biff >= 12 ? 2 : 1);
S
SheetJS 已提交
3982 3983 3984
	var width = 1, encoding = 'sbcs-cont';
	var cp = current_codepage;
	if(opts && opts.biff >= 8) current_codepage = 1200;
S
SheetJS 已提交
3985
	if(!opts || opts.biff == 8 ) {
S
SheetJS 已提交
3986 3987
		var fHighByte = blob.read_shift(1);
		if(fHighByte) { width = 2; encoding = 'dbcs-cont'; }
S
SheetJS 已提交
3988 3989
	} else if(opts.biff == 12) {
		width = 2; encoding = 'wstr';
S
SheetJS 已提交
3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002
	}
	var o = cch ? blob.read_shift(cch, encoding) : "";
	current_codepage = cp;
	return o;
}

/* 2.5.293 XLUnicodeRichExtendedString */
function parse_XLUnicodeRichExtendedString(blob) {
	var cp = current_codepage;
	current_codepage = 1200;
	var cch = blob.read_shift(2), flags = blob.read_shift(1);
	var fHighByte = flags & 0x1, fExtSt = flags & 0x4, fRichSt = flags & 0x8;
	var width = 1 + (flags & 0x1); // 0x0 -> utf8, 0x1 -> dbcs
S
SheetJS 已提交
4003
	var cRun = 0, cbExtRst;
S
SheetJS 已提交
4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019
	var z = {};
	if(fRichSt) cRun = blob.read_shift(2);
	if(fExtSt) cbExtRst = blob.read_shift(4);
	var encoding = (flags & 0x1) ? 'dbcs-cont' : 'sbcs-cont';
	var msg = cch === 0 ? "" : blob.read_shift(cch, encoding);
	if(fRichSt) blob.l += 4 * cRun; //TODO: parse this
	if(fExtSt) blob.l += cbExtRst; //TODO: parse this
	z.t = msg;
	if(!fRichSt) { z.raw = "<t>" + z.t + "</t>"; z.r = z.t; }
	current_codepage = cp;
	return z;
}

/* 2.5.296 XLUnicodeStringNoCch */
function parse_XLUnicodeStringNoCch(blob, cch, opts) {
	var retval;
S
SheetJS 已提交
4020 4021 4022 4023
	if(opts) {
		if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'sbcs-cont');
		if(opts.biff >= 12) return blob.read_shift(cch, 'dbcs-cont');
	}
S
SheetJS 已提交
4024 4025 4026 4027 4028 4029 4030 4031
	var fHighByte = blob.read_shift(1);
	if(fHighByte===0) { retval = blob.read_shift(cch, 'sbcs-cont'); }
	else { retval = blob.read_shift(cch, 'dbcs-cont'); }
	return retval;
}

/* 2.5.294 XLUnicodeString */
function parse_XLUnicodeString(blob, length, opts) {
S
SheetJS 已提交
4032
	var cch = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
S
SheetJS 已提交
4033 4034 4035 4036 4037
	if(cch === 0) { blob.l++; return ""; }
	return parse_XLUnicodeStringNoCch(blob, cch, opts);
}
/* BIFF5 override */
function parse_XLUnicodeString2(blob, length, opts) {
S
SheetJS 已提交
4038
	if(opts.biff > 5) return parse_XLUnicodeString(blob, length, opts);
S
SheetJS 已提交
4039 4040 4041 4042 4043 4044
	var cch = blob.read_shift(1);
	if(cch === 0) { blob.l++; return ""; }
	return blob.read_shift(cch, 'sbcs-cont');
}

/* [MS-XLS] 2.5.61 ControlInfo */
S
SheetJS 已提交
4045 4046 4047 4048 4049 4050 4051
function parse_ControlInfo(blob, length, opts) {
	var flags = blob.read_shift(1);
	blob.l++;
	var accel = blob.read_shift(2);
	blob.l += 2;
	return [flags, accel];
}
S
SheetJS 已提交
4052 4053

/* [MS-OSHARED] 2.3.7.6 URLMoniker TODO: flags */
4054
var parse_URLMoniker = function(blob/*::, length, opts*/) {
S
SheetJS 已提交
4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088
	var len = blob.read_shift(4), start = blob.l;
	var extra = false;
	if(len > 24) {
		/* look ahead */
		blob.l += len - 24;
		if(blob.read_shift(16) === "795881f43b1d7f48af2c825dc4852763") extra = true;
		blob.l = start;
	}
	var url = blob.read_shift((extra?len-24:len)>>1, 'utf16le').replace(chr0,"");
	if(extra) blob.l += 24;
	return url;
};

/* [MS-OSHARED] 2.3.7.8 FileMoniker TODO: all fields */
var parse_FileMoniker = function(blob, length) {
	var cAnti = blob.read_shift(2);
	var ansiLength = blob.read_shift(4);
	var ansiPath = blob.read_shift(ansiLength, 'cstr');
	var endServer = blob.read_shift(2);
	var versionNumber = blob.read_shift(2);
	var cbUnicodePathSize = blob.read_shift(4);
	if(cbUnicodePathSize === 0) return ansiPath.replace(/\\/g,"/");
	var cbUnicodePathBytes = blob.read_shift(4);
	var usKeyValue = blob.read_shift(2);
	var unicodePath = blob.read_shift(cbUnicodePathBytes>>1, 'utf16le').replace(chr0,"");
	return unicodePath;
};

/* [MS-OSHARED] 2.3.7.2 HyperlinkMoniker TODO: all the monikers */
var parse_HyperlinkMoniker = function(blob, length) {
	var clsid = blob.read_shift(16); length -= 16;
	switch(clsid) {
		case "e0c9ea79f9bace118c8200aa004ba90b": return parse_URLMoniker(blob, length);
		case "0303000000000000c000000000000046": return parse_FileMoniker(blob, length);
4089
		default: throw new Error("Unsupported Moniker " + clsid);
S
SheetJS 已提交
4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113
	}
};

/* [MS-OSHARED] 2.3.7.9 HyperlinkString */
var parse_HyperlinkString = function(blob, length) {
	var len = blob.read_shift(4);
	var o = blob.read_shift(len, 'utf16le').replace(chr0, "");
	return o;
};

/* [MS-OSHARED] 2.3.7.1 Hyperlink Object TODO: unify params with XLSX */
var parse_Hyperlink = function(blob, length) {
	var end = blob.l + length;
	var sVer = blob.read_shift(4);
	if(sVer !== 2) throw new Error("Unrecognized streamVersion: " + sVer);
	var flags = blob.read_shift(2);
	blob.l += 2;
	var displayName, targetFrameName, moniker, oleMoniker, location, guid, fileTime;
	if(flags & 0x0010) displayName = parse_HyperlinkString(blob, end - blob.l);
	if(flags & 0x0080) targetFrameName = parse_HyperlinkString(blob, end - blob.l);
	if((flags & 0x0101) === 0x0101) moniker = parse_HyperlinkString(blob, end - blob.l);
	if((flags & 0x0101) === 0x0001) oleMoniker = parse_HyperlinkMoniker(blob, end - blob.l);
	if(flags & 0x0008) location = parse_HyperlinkString(blob, end - blob.l);
	if(flags & 0x0020) guid = blob.read_shift(16);
S
SheetJS 已提交
4114
	if(flags & 0x0040) fileTime = parse_FILETIME(blob/*, 8*/);
S
SheetJS 已提交
4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130
	blob.l = end;
	var target = (targetFrameName||moniker||oleMoniker);
	if(location) target+="#"+location;
	return {Target: target};
};

/* 2.5.178 LongRGBA */
function parse_LongRGBA(blob, length) { var r = blob.read_shift(1), g = blob.read_shift(1), b = blob.read_shift(1), a = blob.read_shift(1); return [r,g,b,a]; }

/* 2.5.177 LongRGB */
function parse_LongRGB(blob, length) { var x = parse_LongRGBA(blob, length); x[3] = 0; return x; }


/* --- MS-XLS --- */

/* 2.5.19 */
S
SheetJS 已提交
4131
function parse_XLSCell(blob, length)/*:Cell*/ {
S
SheetJS 已提交
4132 4133 4134
	var rw = blob.read_shift(2); // 0-indexed
	var col = blob.read_shift(2);
	var ixfe = blob.read_shift(2);
S
SheetJS 已提交
4135
	return ({r:rw, c:col, ixfe:ixfe}/*:any*/);
S
SheetJS 已提交
4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150
}

/* 2.5.134 */
function parse_frtHeader(blob) {
	var rt = blob.read_shift(2);
	var flags = blob.read_shift(2); // TODO: parse these flags
	blob.l += 8;
	return {type: rt, flags: flags};
}



function parse_OptXLUnicodeString(blob, length, opts) { return length === 0 ? "" : parse_XLUnicodeString2(blob, length, opts); }

/* 2.5.158 */
S
SheetJS 已提交
4151
//var HIDEOBJENUM = ['SHOWALL', 'SHOWPLACEHOLDER', 'HIDEALL'];
S
SheetJS 已提交
4152 4153 4154
var parse_HideObjEnum = parseuint16;

/* 2.5.344 */
S
SheetJS 已提交
4155 4156 4157
function parse_XTI(blob, length, opts) {
	var w = opts.biff > 8 ? 4 : 2;
	var iSupBook = blob.read_shift(w), itabFirst = blob.read_shift(w,'i'), itabLast = blob.read_shift(w,'i');
S
SheetJS 已提交
4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168
	return [iSupBook, itabFirst, itabLast];
}

/* 2.5.218 */
function parse_RkRec(blob, length) {
	var ixfe = blob.read_shift(2);
	var RK = parse_RkNumber(blob);
	return [ixfe, RK];
}

/* 2.5.1 */
S
SheetJS 已提交
4169
function parse_AddinUdf(blob, length, opts) {
S
SheetJS 已提交
4170 4171
	blob.l += 4; length -= 4;
	var l = blob.l + length;
S
SheetJS 已提交
4172
	var udfName = parse_ShortXLUnicodeString(blob, length, opts);
S
SheetJS 已提交
4173 4174
	var cb = blob.read_shift(2);
	l -= blob.l;
4175
	if(cb !== l) throw new Error("Malformed AddinUdf: padding = " + l + " != " + cb);
S
SheetJS 已提交
4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229
	blob.l += cb;
	return udfName;
}

/* 2.5.209 TODO: Check sizes */
function parse_Ref8U(blob, length) {
	var rwFirst = blob.read_shift(2);
	var rwLast = blob.read_shift(2);
	var colFirst = blob.read_shift(2);
	var colLast = blob.read_shift(2);
	return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}};
}

/* 2.5.211 */
function parse_RefU(blob, length) {
	var rwFirst = blob.read_shift(2);
	var rwLast = blob.read_shift(2);
	var colFirst = blob.read_shift(1);
	var colLast = blob.read_shift(1);
	return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}};
}

/* 2.5.207 */
var parse_Ref = parse_RefU;

/* 2.5.143 */
function parse_FtCmo(blob, length) {
	blob.l += 4;
	var ot = blob.read_shift(2);
	var id = blob.read_shift(2);
	var flags = blob.read_shift(2);
	blob.l+=12;
	return [id, ot, flags];
}

/* 2.5.149 */
function parse_FtNts(blob, length) {
	var out = {};
	blob.l += 4;
	blob.l += 16; // GUID TODO
	out.fSharedNote = blob.read_shift(2);
	blob.l += 4;
	return out;
}

/* 2.5.142 */
function parse_FtCf(blob, length) {
	var out = {};
	blob.l += 4;
	blob.cf = blob.read_shift(2);
	return out;
}

/* 2.5.140 - 2.5.154 and friends */
S
SheetJS 已提交
4230
function parse_FtSkip(blob, length) { blob.l += 2; blob.l += blob.read_shift(2); }
S
SheetJS 已提交
4231
var FtTab = {
S
SheetJS 已提交
4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250
	/*::[*/0x00/*::]*/: parse_FtSkip,      /* FtEnd */
	/*::[*/0x04/*::]*/: parse_FtSkip,      /* FtMacro */
	/*::[*/0x05/*::]*/: parse_FtSkip,      /* FtButton */
	/*::[*/0x06/*::]*/: parse_FtSkip,      /* FtGmo */
	/*::[*/0x07/*::]*/: parse_FtCf,        /* FtCf */
	/*::[*/0x08/*::]*/: parse_FtSkip,      /* FtPioGrbit */
	/*::[*/0x09/*::]*/: parse_FtSkip,      /* FtPictFmla */
	/*::[*/0x0A/*::]*/: parse_FtSkip,      /* FtCbls */
	/*::[*/0x0B/*::]*/: parse_FtSkip,      /* FtRbo */
	/*::[*/0x0C/*::]*/: parse_FtSkip,      /* FtSbs */
	/*::[*/0x0D/*::]*/: parse_FtNts,       /* FtNts */
	/*::[*/0x0E/*::]*/: parse_FtSkip,      /* FtSbsFmla */
	/*::[*/0x0F/*::]*/: parse_FtSkip,      /* FtGboData */
	/*::[*/0x10/*::]*/: parse_FtSkip,      /* FtEdoData */
	/*::[*/0x11/*::]*/: parse_FtSkip,      /* FtRboData */
	/*::[*/0x12/*::]*/: parse_FtSkip,      /* FtCblsData */
	/*::[*/0x13/*::]*/: parse_FtSkip,      /* FtLbsData */
	/*::[*/0x14/*::]*/: parse_FtSkip,      /* FtCblsFmla */
	/*::[*/0x15/*::]*/: parse_FtCmo
S
SheetJS 已提交
4251 4252
};
function parse_FtArray(blob, length, ot) {
S
SheetJS 已提交
4253
	var tgt = blob.l + length;
S
SheetJS 已提交
4254
	var fts = [];
S
SheetJS 已提交
4255
	while(blob.l < tgt) {
S
SheetJS 已提交
4256 4257 4258
		var ft = blob.read_shift(2);
		blob.l-=2;
		try {
S
SheetJS 已提交
4259 4260
			fts.push(FtTab[ft](blob, tgt - blob.l));
		} catch(e) { blob.l = tgt; return fts; }
S
SheetJS 已提交
4261
	}
S
SheetJS 已提交
4262
	if(blob.l != tgt) blob.l = tgt; //throw new Error("bad Object Ft-sequence");
S
SheetJS 已提交
4263 4264 4265 4266 4267 4268 4269 4270 4271 4272
	return fts;
}

/* 2.5.129 */
var parse_FontIndex = parseuint16;

/* --- 2.4 Records --- */

/* 2.4.21 */
function parse_BOF(blob, length) {
4273
	var o = {BIFFVer:0, dt:0};
S
SheetJS 已提交
4274
	o.BIFFVer = blob.read_shift(2); length -= 2;
4275
	if(length >= 2) { o.dt = blob.read_shift(2); blob.l -= 2; }
S
SheetJS 已提交
4276 4277 4278 4279 4280
	switch(o.BIFFVer) {
		case 0x0600: /* BIFF8 */
		case 0x0500: /* BIFF5 */
		case 0x0002: case 0x0007: /* BIFF2 */
			break;
S
SheetJS 已提交
4281
		default: if(length > 6) throw new Error("Unexpected BIFF Ver " + o.BIFFVer);
S
SheetJS 已提交
4282
	}
4283

S
SheetJS 已提交
4284 4285 4286 4287 4288 4289 4290 4291 4292
	blob.read_shift(length);
	return o;
}


/* 2.4.146 */
function parse_InterfaceHdr(blob, length) {
	if(length === 0) return 0x04b0;
	var q;
S
SheetJS 已提交
4293
	if((q=blob.read_shift(2))!==0x04b0){/* empty */}
S
SheetJS 已提交
4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310
	return 0x04b0;
}


/* 2.4.349 */
function parse_WriteAccess(blob, length, opts) {
	if(opts.enc) { blob.l += length; return ""; }
	var l = blob.l;
	// TODO: make sure XLUnicodeString doesnt overrun
	var UserName = parse_XLUnicodeString(blob, 0, opts);
	blob.read_shift(length + l - blob.l);
	return UserName;
}

/* 2.4.28 */
function parse_BoundSheet8(blob, length, opts) {
	var pos = blob.read_shift(4);
S
SheetJS 已提交
4311
	var hidden = blob.read_shift(1) & 0x03;
S
SheetJS 已提交
4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324
	var dt = blob.read_shift(1);
	switch(dt) {
		case 0: dt = 'Worksheet'; break;
		case 1: dt = 'Macrosheet'; break;
		case 2: dt = 'Chartsheet'; break;
		case 6: dt = 'VBAModule'; break;
	}
	var name = parse_ShortXLUnicodeString(blob, 0, opts);
	if(name.length === 0) name = "Sheet1";
	return { pos:pos, hs:hidden, dt:dt, name:name };
}

/* 2.4.265 TODO */
S
SheetJS 已提交
4325
function parse_SST(blob, length)/*:SST*/ {
S
SheetJS 已提交
4326
	var end = blob.l + length;
S
SheetJS 已提交
4327 4328
	var cnt = blob.read_shift(4);
	var ucnt = blob.read_shift(4);
S
SheetJS 已提交
4329
	var strs/*:SST*/ = ([]/*:any*/);
S
SheetJS 已提交
4330
	for(var i = 0; i != ucnt && blob.l < end; ++i) {
S
SheetJS 已提交
4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345
		strs.push(parse_XLUnicodeRichExtendedString(blob));
	}
	strs.Count = cnt; strs.Unique = ucnt;
	return strs;
}

/* 2.4.107 */
function parse_ExtSST(blob, length) {
	var extsst = {};
	extsst.dsst = blob.read_shift(2);
	blob.l += length-2;
	return extsst;
}


S
SheetJS 已提交
4346
/* 2.4.221 TODO: check BIFF2-4 */
S
SheetJS 已提交
4347
function parse_Row(blob, length) {
S
SheetJS 已提交
4348 4349 4350 4351 4352 4353
	var z = ({}/*:any*/);
	z.r = blob.read_shift(2);
	z.c = blob.read_shift(2);
	z.cnt = blob.read_shift(2) - z.c;
	var miyRw = blob.read_shift(2);
	blob.l += 4; // reserved(2), unused(2)
S
SheetJS 已提交
4354
	var flags = blob.read_shift(1); // various flags
S
SheetJS 已提交
4355
	blob.l += 3; // reserved(8), ixfe(12), flags(4)
4356 4357
	if(flags & 0x07) z.level = flags & 0x07;
	// collapsed: flags & 0x10
S
SheetJS 已提交
4358 4359 4360
	if(flags & 0x20) z.hidden = true;
	if(flags & 0x40) z.hpt = miyRw / 20;
	return z;
S
SheetJS 已提交
4361 4362 4363 4364 4365 4366
}


/* 2.4.125 */
function parse_ForceFullCalculation(blob, length) {
	var header = parse_frtHeader(blob);
4367
	if(header.type != 0x08A3) throw new Error("Invalid Future Record " + header.type);
S
SheetJS 已提交
4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383
	var fullcalc = blob.read_shift(4);
	return fullcalc !== 0x0;
}


var parse_CompressPictures = parsenoop2; /* 2.4.55 Not interesting */



/* 2.4.215 rt */
function parse_RecalcId(blob, length) {
	blob.read_shift(2);
	return blob.read_shift(4);
}

/* 2.4.87 */
S
SheetJS 已提交
4384 4385 4386 4387 4388
function parse_DefaultRowHeight(blob, length, opts) {
	var f = 0;
	if(!(opts && opts.biff == 2)) {
		f = blob.read_shift(2);
	}
S
SheetJS 已提交
4389
	var miyRw = blob.read_shift(2);
S
SheetJS 已提交
4390 4391 4392 4393
	if((opts && opts.biff == 2)) {
		f = 1 - (miyRw >> 15); miyRw &= 0x7fff;
	}
	var fl = {Unsynced:f&1,DyZero:(f&2)>>1,ExAsc:(f&4)>>2,ExDsc:(f&8)>>3};
S
SheetJS 已提交
4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407
	return [fl, miyRw];
}

/* 2.4.345 TODO */
function parse_Window1(blob, length) {
	var xWn = blob.read_shift(2), yWn = blob.read_shift(2), dxWn = blob.read_shift(2), dyWn = blob.read_shift(2);
	var flags = blob.read_shift(2), iTabCur = blob.read_shift(2), iTabFirst = blob.read_shift(2);
	var ctabSel = blob.read_shift(2), wTabRatio = blob.read_shift(2);
	return { Pos: [xWn, yWn], Dim: [dxWn, dyWn], Flags: flags, CurTab: iTabCur,
		FirstTab: iTabFirst, Selected: ctabSel, TabRatio: wTabRatio };
}

/* 2.4.122 TODO */
function parse_Font(blob, length, opts) {
S
SheetJS 已提交
4408
	var o/*:any*/ = {
S
SheetJS 已提交
4409 4410 4411 4412 4413 4414 4415 4416 4417 4418
		dyHeight: blob.read_shift(2),
		fl: blob.read_shift(2)
	};
	switch(opts && opts.biff || 8) {
		case 2: break;
		case 3: case 4: blob.l += 2; break;
		default: blob.l += 10; break;
	}
	o.name = parse_ShortXLUnicodeString(blob, 0, opts);
	return o;
S
SheetJS 已提交
4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429
}

/* 2.4.149 */
function parse_LabelSst(blob, length) {
	var cell = parse_XLSCell(blob);
	cell.isst = blob.read_shift(4);
	return cell;
}

/* 2.4.148 */
function parse_Label(blob, length, opts) {
S
SheetJS 已提交
4430
	var target = blob.l + length;
S
SheetJS 已提交
4431
	var cell = parse_XLSCell(blob, 6);
S
SheetJS 已提交
4432 4433
	if(opts.biff == 2) blob.l++;
	var str = parse_XLUnicodeString(blob, target - blob.l, opts);
S
SheetJS 已提交
4434 4435 4436 4437 4438 4439
	cell.val = str;
	return cell;
}

/* 2.4.126 Number Formats */
function parse_Format(blob, length, opts) {
S
SheetJS 已提交
4440
	var numFmtId = blob.read_shift(2);
S
SheetJS 已提交
4441
	var fmtstr = parse_XLUnicodeString2(blob, 0, opts);
S
SheetJS 已提交
4442
	return [numFmtId, fmtstr];
S
SheetJS 已提交
4443
}
S
SheetJS 已提交
4444
var parse_BIFF2Format = parse_XLUnicodeString2;
S
SheetJS 已提交
4445 4446

/* 2.4.90 */
S
SheetJS 已提交
4447 4448 4449
function parse_Dimensions(blob, length, opts) {
	var end = blob.l + length;
	var w = opts.biff == 8 || !opts.biff ? 4 : 2;
S
SheetJS 已提交
4450 4451
	var r = blob.read_shift(w), R = blob.read_shift(w);
	var c = blob.read_shift(2), C = blob.read_shift(2);
S
SheetJS 已提交
4452
	blob.l = end;
S
SheetJS 已提交
4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468
	return {s: {r:r, c:c}, e: {r:R, c:C}};
}

/* 2.4.220 */
function parse_RK(blob, length) {
	var rw = blob.read_shift(2), col = blob.read_shift(2);
	var rkrec = parse_RkRec(blob);
	return {r:rw, c:col, ixfe:rkrec[0], rknum:rkrec[1]};
}

/* 2.4.175 */
function parse_MulRk(blob, length) {
	var target = blob.l + length - 2;
	var rw = blob.read_shift(2), col = blob.read_shift(2);
	var rkrecs = [];
	while(blob.l < target) rkrecs.push(parse_RkRec(blob));
4469
	if(blob.l !== target) throw new Error("MulRK read error");
S
SheetJS 已提交
4470
	var lastcol = blob.read_shift(2);
4471
	if(rkrecs.length != lastcol - col + 1) throw new Error("MulRK length mismatch");
S
SheetJS 已提交
4472 4473
	return {r:rw, c:col, C:lastcol, rkrec:rkrecs};
}
S
SheetJS 已提交
4474 4475 4476 4477 4478 4479
/* 2.4.174 */
function parse_MulBlank(blob, length) {
	var target = blob.l + length - 2;
	var rw = blob.read_shift(2), col = blob.read_shift(2);
	var ixfes = [];
	while(blob.l < target) ixfes.push(blob.read_shift(2));
4480
	if(blob.l !== target) throw new Error("MulBlank read error");
S
SheetJS 已提交
4481
	var lastcol = blob.read_shift(2);
4482
	if(ixfes.length != lastcol - col + 1) throw new Error("MulBlank length mismatch");
S
SheetJS 已提交
4483 4484
	return {r:rw, c:col, C:lastcol, ixfe:ixfes};
}
S
SheetJS 已提交
4485

S
SheetJS 已提交
4486
/* 2.5.20 2.5.249 TODO: interpret values here */
S
SheetJS 已提交
4487
function parse_CellStyleXF(blob, length, style, opts) {
S
SheetJS 已提交
4488 4489 4490 4491
	var o = {};
	var a = blob.read_shift(4), b = blob.read_shift(4);
	var c = blob.read_shift(4), d = blob.read_shift(2);
	o.patternType = XLSFillPattern[c >> 26];
S
SheetJS 已提交
4492

S
SheetJS 已提交
4493
	if(!opts.cellStyles) return o;
S
SheetJS 已提交
4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521
	o.alc = a & 0x07;
	o.fWrap = (a >> 3) & 0x01;
	o.alcV = (a >> 4) & 0x07;
	o.fJustLast = (a >> 7) & 0x01;
	o.trot = (a >> 8) & 0xFF;
	o.cIndent = (a >> 16) & 0x0F;
	o.fShrinkToFit = (a >> 20) & 0x01;
	o.iReadOrder = (a >> 22) & 0x02;
	o.fAtrNum = (a >> 26) & 0x01;
	o.fAtrFnt = (a >> 27) & 0x01;
	o.fAtrAlc = (a >> 28) & 0x01;
	o.fAtrBdr = (a >> 29) & 0x01;
	o.fAtrPat = (a >> 30) & 0x01;
	o.fAtrProt = (a >> 31) & 0x01;

	o.dgLeft = b & 0x0F;
	o.dgRight = (b >> 4) & 0x0F;
	o.dgTop = (b >> 8) & 0x0F;
	o.dgBottom = (b >> 12) & 0x0F;
	o.icvLeft = (b >> 16) & 0x7F;
	o.icvRight = (b >> 23) & 0x7F;
	o.grbitDiag = (b >> 30) & 0x03;

	o.icvTop = c & 0x7F;
	o.icvBottom = (c >> 7) & 0x7F;
	o.icvDiag = (c >> 14) & 0x7F;
	o.dgDiag = (c >> 21) & 0x0F;

S
SheetJS 已提交
4522 4523
	o.icvFore = d & 0x7F;
	o.icvBack = (d >> 7) & 0x7F;
S
SheetJS 已提交
4524
	o.fsxButton = (d >> 14) & 0x01;
S
SheetJS 已提交
4525 4526
	return o;
}
S
SheetJS 已提交
4527 4528
function parse_CellXF(blob, length, opts) {return parse_CellStyleXF(blob,length,0, opts);}
function parse_StyleXF(blob, length, opts) {return parse_CellStyleXF(blob,length,1, opts);}
S
SheetJS 已提交
4529 4530

/* 2.4.353 TODO: actually do this right */
S
SheetJS 已提交
4531
function parse_XF(blob, length, opts) {
S
SheetJS 已提交
4532
	var o = {};
S
SheetJS 已提交
4533
	o.ifnt = blob.read_shift(2); o.numFmtId = blob.read_shift(2); o.flags = blob.read_shift(2);
S
SheetJS 已提交
4534 4535
	o.fStyle = (o.flags >> 2) & 0x01;
	length -= 6;
S
SheetJS 已提交
4536
	o.data = parse_CellStyleXF(blob, length, o.fStyle, opts);
S
SheetJS 已提交
4537 4538 4539 4540 4541 4542 4543 4544 4545
	return o;
}

/* 2.4.134 */
function parse_Guts(blob, length) {
	blob.l += 4;
	var out = [blob.read_shift(2), blob.read_shift(2)];
	if(out[0] !== 0) out[0]--;
	if(out[1] !== 0) out[1]--;
4546
	if(out[0] > 7 || out[1] > 7) throw new Error("Bad Gutters: " + out.join("|"));
S
SheetJS 已提交
4547 4548 4549 4550
	return out;
}

/* 2.4.24 */
S
SheetJS 已提交
4551
function parse_BoolErr(blob, length, opts) {
S
SheetJS 已提交
4552
	var cell = parse_XLSCell(blob, 6);
S
SheetJS 已提交
4553
	if(opts.biff == 2) ++blob.l;
S
SheetJS 已提交
4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575
	var val = parse_Bes(blob, 2);
	cell.val = val;
	cell.t = (val === true || val === false) ? 'b' : 'e';
	return cell;
}

/* 2.4.180 Number */
function parse_Number(blob, length) {
	var cell = parse_XLSCell(blob, 6);
	var xnum = parse_Xnum(blob, 8);
	cell.val = xnum;
	return cell;
}

var parse_XLHeaderFooter = parse_OptXLUnicodeString; // TODO: parse 2.4.136

/* 2.4.271 */
function parse_SupBook(blob, length, opts) {
	var end = blob.l + length;
	var ctab = blob.read_shift(2);
	var cch = blob.read_shift(2);
	opts.sbcch = cch;
S
SheetJS 已提交
4576 4577 4578
	if(cch == 0x0401 || cch == 0x3A01) return [cch, ctab];
	if(cch < 0x01 || cch >0xff) throw new Error("Unexpected SupBook type: "+cch);
	var virtPath = parse_XLUnicodeStringNoCch(blob, cch);
S
SheetJS 已提交
4579 4580 4581
	/* TODO: 2.5.277 Virtual Path */
	var rgst = [];
	while(end > blob.l) rgst.push(parse_XLUnicodeString(blob));
S
SheetJS 已提交
4582 4583 4584 4585 4586 4587 4588
	return [cch, ctab, virtPath, rgst];
}

/* 2.4.105 TODO */
function parse_ExternName(blob, length, opts) {
	var flags = blob.read_shift(2);
	var body;
S
SheetJS 已提交
4589
	var o = ({
S
SheetJS 已提交
4590 4591 4592 4593 4594 4595 4596
		fBuiltIn: flags & 0x01,
		fWantAdvise: (flags >>> 1) & 0x01,
		fWantPict: (flags >>> 2) & 0x01,
		fOle: (flags >>> 3) & 0x01,
		fOleLink: (flags >>> 4) & 0x01,
		cf: (flags >>> 5) & 0x3FF,
		fIcon: flags >>> 15 & 0x01
S
SheetJS 已提交
4597
	}/*:any*/);
S
SheetJS 已提交
4598
	if(opts.sbcch === 0x3A01) body = parse_AddinUdf(blob, length-2, opts);
S
SheetJS 已提交
4599 4600
	//else throw new Error("unsupported SupBook cch: " + opts.sbcch);
	o.body = body || blob.read_shift(length-2);
S
SheetJS 已提交
4601
	if(typeof body === "string") o.Name = body;
S
SheetJS 已提交
4602 4603 4604 4605
	return o;
}

/* 2.4.150 TODO */
S
SheetJS 已提交
4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621
var XLSLblBuiltIn = [
	"_xlnm.Consolidate_Area",
	"_xlnm.Auto_Open",
	"_xlnm.Auto_Close",
	"_xlnm.Extract",
	"_xlnm.Database",
	"_xlnm.Criteria",
	"_xlnm.Print_Area",
	"_xlnm.Print_Titles",
	"_xlnm.Recorder",
	"_xlnm.Data_Form",
	"_xlnm.Auto_Activate",
	"_xlnm.Auto_Deactivate",
	"_xlnm.Sheet_Title",
	"_xlnm._FilterDatabase"
];
S
SheetJS 已提交
4622 4623 4624 4625 4626
function parse_Lbl(blob, length, opts) {
	var target = blob.l + length;
	var flags = blob.read_shift(2);
	var chKey = blob.read_shift(1);
	var cch = blob.read_shift(1);
S
SheetJS 已提交
4627
	var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
S
SheetJS 已提交
4628
	var itab = 0;
S
SheetJS 已提交
4629 4630
	if(!opts || opts.biff >= 5) {
		blob.l += 2;
S
SheetJS 已提交
4631
		itab = blob.read_shift(2);
S
SheetJS 已提交
4632 4633
		blob.l += 4;
	}
S
SheetJS 已提交
4634
	var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
S
SheetJS 已提交
4635
	if(flags & 0x20) name = XLSLblBuiltIn[name.charCodeAt(0)];
S
SheetJS 已提交
4636 4637
	var npflen = target - blob.l; if(opts && opts.biff == 2) --npflen;
	var rgce = target == blob.l || cce == 0 ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
S
SheetJS 已提交
4638 4639 4640
	return {
		chKey: chKey,
		Name: name,
S
SheetJS 已提交
4641
		itab: itab,
S
SheetJS 已提交
4642 4643 4644 4645
		rgce: rgce
	};
}

S
SheetJS 已提交
4646
/* 2.4.106 TODO: verify filename encoding */
S
SheetJS 已提交
4647
function parse_ExternSheet(blob, length, opts) {
S
SheetJS 已提交
4648 4649 4650
	if(opts.biff < 8) return parse_BIFF5ExternSheet(blob, length, opts);
	var o = [], target = blob.l + length, len = blob.read_shift(opts.biff > 8 ? 4 : 2);
	while(len-- !== 0) o.push(parse_XTI(blob, opts.biff > 8 ? 12 : 6, opts));
S
SheetJS 已提交
4651
		// [iSupBook, itabFirst, itabLast];
S
SheetJS 已提交
4652
	var oo = [];
S
SheetJS 已提交
4653 4654
	return o;
}
S
SheetJS 已提交
4655 4656 4657 4658 4659 4660
function parse_BIFF5ExternSheet(blob, length, opts) {
	if(blob[blob.l + 1] == 0x03) blob[blob.l]++;
	var o = parse_ShortXLUnicodeString(blob, length, opts);
	return o.charCodeAt(0) == 0x03 ? o.slice(1) : o;
}
var parse_ExternCount = parseuint16;
S
SheetJS 已提交
4661 4662 4663 4664 4665 4666 4667 4668 4669

/* 2.4.176 TODO: check older biff */
function parse_NameCmt(blob, length, opts) {
	if(opts.biff < 8) { blob.l += length; return; }
	var cchName = blob.read_shift(2);
	var cchComment = blob.read_shift(2);
	var name = parse_XLUnicodeStringNoCch(blob, cchName, opts);
	var comment = parse_XLUnicodeStringNoCch(blob, cchComment, opts);
	return [name, comment];
S
SheetJS 已提交
4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683
}

/* 2.4.260 */
function parse_ShrFmla(blob, length, opts) {
	var ref = parse_RefU(blob, 6);
	blob.l++;
	var cUse = blob.read_shift(1);
	length -= 8;
	return [parse_SharedParsedFormula(blob, length, opts), cUse];
}

/* 2.4.4 TODO */
function parse_Array(blob, length, opts) {
	var ref = parse_Ref(blob, 6);
S
SheetJS 已提交
4684 4685 4686 4687 4688 4689
	/* TODO: fAlwaysCalc */
	switch(opts.biff) {
		case 2: blob.l ++; length -= 7; break;
		case 3: case 4: blob.l += 2; length -= 8; break;
		default: blob.l += 6; length -= 12;
	}
S
SheetJS 已提交
4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725
	return [ref, parse_ArrayParsedFormula(blob, length, opts, ref)];
}

/* 2.4.173 */
function parse_MTRSettings(blob, length) {
	var fMTREnabled = blob.read_shift(4) !== 0x00;
	var fUserSetThreadCount = blob.read_shift(4) !== 0x00;
	var cUserThreadCount = blob.read_shift(4);
	return [fMTREnabled, fUserSetThreadCount, cUserThreadCount];
}

/* 2.5.186 TODO: BIFF5 */
function parse_NoteSh(blob, length, opts) {
	if(opts.biff < 8) return;
	var row = blob.read_shift(2), col = blob.read_shift(2);
	var flags = blob.read_shift(2), idObj = blob.read_shift(2);
	var stAuthor = parse_XLUnicodeString2(blob, 0, opts);
	if(opts.biff < 8) blob.read_shift(1);
	return [{r:row,c:col}, stAuthor, idObj, flags];
}

/* 2.4.179 */
function parse_Note(blob, length, opts) {
	/* TODO: Support revisions */
	return parse_NoteSh(blob, length, opts);
}

/* 2.4.168 */
function parse_MergeCells(blob, length) {
	var merges = [];
	var cmcs = blob.read_shift(2);
	while (cmcs--) merges.push(parse_Ref8U(blob,length));
	return merges;
}

/* 2.4.181 TODO: parse all the things! */
S
SheetJS 已提交
4726 4727
function parse_Obj(blob, length, opts) {
	if(opts && opts.biff < 8) return parse_BIFF5Obj(blob, length, opts);
S
SheetJS 已提交
4728 4729 4730 4731
	var cmo = parse_FtCmo(blob, 22); // id, ot, flags
	var fts = parse_FtArray(blob, length-22, cmo[1]);
	return { cmo: cmo, ft:fts };
}
S
SheetJS 已提交
4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768
/* from older spec */
var parse_BIFF5OT = [];
parse_BIFF5OT[0x08] = function(blob, length, opts) {
	var tgt = blob.l + length;
	blob.l += 10; // todo
	var cf = blob.read_shift(2);
	blob.l += 4;
	var cbPictFmla = blob.read_shift(2);
	blob.l += 2;
	var grbit = blob.read_shift(2);
	blob.l += 4;
	var cchName = blob.read_shift(1);
	blob.l += cchName; // TODO: stName
	blob.l = tgt; // TODO: fmla
	return { fmt:cf };
};

function parse_BIFF5Obj(blob, length, opts) {
	var cnt = blob.read_shift(4);
	var ot = blob.read_shift(2);
	var id = blob.read_shift(2);
	var grbit = blob.read_shift(2);
	var colL = blob.read_shift(2);
	var dxL = blob.read_shift(2);
	var rwT = blob.read_shift(2);
	var dyT = blob.read_shift(2);
	var colR = blob.read_shift(2);
	var dxR = blob.read_shift(2);
	var rwB = blob.read_shift(2);
	var dyB = blob.read_shift(2);
	var cbMacro = blob.read_shift(2);
	blob.l += 6;
	length -= 36;
	var fts = [];
	fts.push((parse_BIFF5OT[ot]||parsenoop)(blob, length, opts));
	return { cmo: [id, ot, grbit], ft:fts };
}
S
SheetJS 已提交
4769 4770 4771 4772

/* 2.4.329 TODO: parse properly */
function parse_TxO(blob, length, opts) {
	var s = blob.l;
S
SheetJS 已提交
4773
	var texts = "";
S
SheetJS 已提交
4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787
try {
	blob.l += 4;
	var ot = (opts.lastobj||{cmo:[0,0]}).cmo[1];
	var controlInfo;
	if([0,5,7,11,12,14].indexOf(ot) == -1) blob.l += 6;
	else controlInfo = parse_ControlInfo(blob, 6, opts);
	var cchText = blob.read_shift(2);
	var cbRuns = blob.read_shift(2);
	var ifntEmpty = parse_FontIndex(blob, 2);
	var len = blob.read_shift(2);
	blob.l += len;
	//var fmla = parse_ObjFmla(blob, s + length - blob.l);

	for(var i = 1; i < blob.lens.length-1; ++i) {
4788
		if(blob.l-s != blob.lens[i]) throw new Error("TxO: bad continue record");
S
SheetJS 已提交
4789 4790 4791 4792 4793 4794
		var hdr = blob[blob.l];
		var t = parse_XLUnicodeStringNoCch(blob, blob.lens[i+1]-blob.lens[i]-1);
		texts += t;
		if(texts.length >= (hdr ? cchText : 2*cchText)) break;
	}
	if(texts.length !== cchText && texts.length !== cchText*2) {
4795
		throw new Error("cchText: " + cchText + " != " + texts.length);
S
SheetJS 已提交
4796 4797 4798 4799 4800 4801 4802
	}

	blob.l = s + length;
	/* 2.5.272 TxORuns */
//	var rgTxoRuns = [];
//	for(var j = 0; j != cbRuns/8-1; ++j) blob.l += 8;
//	var cchText2 = blob.read_shift(2);
4803
//	if(cchText2 !== cchText) throw new Error("TxOLastRun mismatch: " + cchText2 + " " + cchText);
S
SheetJS 已提交
4804
//	blob.l += 6;
4805
//	if(s + length != blob.l) throw new Error("TxO " + (s + length) + ", at " + blob.l);
S
SheetJS 已提交
4806
	return { t: texts };
S
SheetJS 已提交
4807
} catch(e) { blob.l = s + length; return { t: texts }; }
S
SheetJS 已提交
4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860
}

/* 2.4.140 */
var parse_HLink = function(blob, length) {
	var ref = parse_Ref8U(blob, 8);
	blob.l += 16; /* CLSID */
	var hlink = parse_Hyperlink(blob, length-24);
	return [ref, hlink];
};

/* 2.4.141 */
var parse_HLinkTooltip = function(blob, length) {
	var end = blob.l + length;
	blob.read_shift(2);
	var ref = parse_Ref8U(blob, 8);
	var wzTooltip = blob.read_shift((length-10)/2, 'dbcs-cont');
	wzTooltip = wzTooltip.replace(chr0,"");
	return [ref, wzTooltip];
};

/* 2.4.63 */
function parse_Country(blob, length) {
	var o = [], d;
	d = blob.read_shift(2); o[0] = CountryEnum[d] || d;
	d = blob.read_shift(2); o[1] = CountryEnum[d] || d;
	return o;
}

/* 2.4.50 ClrtClient */
function parse_ClrtClient(blob, length) {
	var ccv = blob.read_shift(2);
	var o = [];
	while(ccv-->0) o.push(parse_LongRGB(blob, 8));
	return o;
}

/* 2.4.188 */
function parse_Palette(blob, length) {
	var ccv = blob.read_shift(2);
	var o = [];
	while(ccv-->0) o.push(parse_LongRGB(blob, 8));
	return o;
}

/* 2.4.354 */
function parse_XFCRC(blob, length) {
	blob.l += 2;
	var o = {cxfs:0, crc:0};
	o.cxfs = blob.read_shift(2);
	o.crc = blob.read_shift(4);
	return o;
}

S
SheetJS 已提交
4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874
/* 2.4.53 TODO: parse flags */
/* [MS-XLSB] 2.4.323 TODO: parse flags */
function parse_ColInfo(blob, length, opts) {
	if(!opts.cellStyles) return parsenoop(blob, length);
	var w = opts && opts.biff >= 12 ? 4 : 2;
	var colFirst = blob.read_shift(w);
	var colLast = blob.read_shift(w);
	var coldx = blob.read_shift(w);
	var ixfe = blob.read_shift(w);
	var flags = blob.read_shift(2);
	if(w == 2) blob.l += 2;
	return {s:colFirst, e:colLast, w:coldx, ixfe:ixfe, flags:flags};
}

S
SheetJS 已提交
4875 4876 4877 4878 4879 4880 4881 4882 4883 4884
/* 2.4.257 */
function parse_Setup(blob, length, opts) {
	var o = {};
	blob.l += 16;
	o.header = parse_Xnum(blob, 8);
	o.footer = parse_Xnum(blob, 8);
	blob.l += 2;
	return o;
}

4885 4886 4887 4888 4889 4890 4891 4892 4893
/* 2.4.261 */
function parse_ShtProps(blob, length, opts) {
	var def = {area:false};
	if(opts.biff != 5) { blob.l += length; return def; }
	var d = blob.read_shift(1); blob.l += 3;
	if((d & 0x10)) def.area = true;
	return def;
}

S
SheetJS 已提交
4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204
var parse_Style = parsenoop;
var parse_StyleExt = parsenoop;

var parse_Window2 = parsenoop;

var parse_Backup = parsebool; /* 2.4.14 */
var parse_Blank = parse_XLSCell; /* 2.4.20 Just the cell */
var parse_BottomMargin = parse_Xnum; /* 2.4.27 */
var parse_BuiltInFnGroupCount = parseuint16; /* 2.4.30 0x0E or 0x10 but excel 2011 generates 0x11? */
var parse_CalcCount = parseuint16; /* 2.4.31 #Iterations */
var parse_CalcDelta = parse_Xnum; /* 2.4.32 */
var parse_CalcIter = parsebool;  /* 2.4.33 1=iterative calc */
var parse_CalcMode = parseuint16; /* 2.4.34 0=manual, 1=auto (def), 2=table */
var parse_CalcPrecision = parsebool; /* 2.4.35 */
var parse_CalcRefMode = parsenoop2; /* 2.4.36 */
var parse_CalcSaveRecalc = parsebool; /* 2.4.37 */
var parse_CodePage = parseuint16; /* 2.4.52 */
var parse_Compat12 = parsebool; /* 2.4.54 true = no compatibility check */
var parse_Date1904 = parsebool; /* 2.4.77 - 1=1904,0=1900 */
var parse_DefColWidth = parseuint16; /* 2.4.89 */
var parse_DSF = parsenoop2; /* 2.4.94 -- MUST be ignored */
var parse_EntExU2 = parsenoop2; /* 2.4.102 -- Explicitly says to ignore */
var parse_EOF = parsenoop2; /* 2.4.103 */
var parse_Excel9File = parsenoop2; /* 2.4.104 -- Optional and unused */
var parse_FeatHdr = parsenoop2; /* 2.4.112 */
var parse_FontX = parseuint16; /* 2.4.123 */
var parse_Footer = parse_XLHeaderFooter; /* 2.4.124 */
var parse_GridSet = parseuint16; /* 2.4.132, =1 */
var parse_HCenter = parsebool; /* 2.4.135 sheet centered horizontal on print */
var parse_Header = parse_XLHeaderFooter; /* 2.4.136 */
var parse_HideObj = parse_HideObjEnum; /* 2.4.139 */
var parse_InterfaceEnd = parsenoop2; /* 2.4.145 -- noop */
var parse_LeftMargin = parse_Xnum; /* 2.4.151 */
var parse_Mms = parsenoop2; /* 2.4.169 -- Explicitly says to ignore */
var parse_ObjProtect = parsebool; /* 2.4.183 -- must be 1 if present */
var parse_Password = parseuint16; /* 2.4.191 */
var parse_PrintGrid = parsebool; /* 2.4.202 */
var parse_PrintRowCol = parsebool; /* 2.4.203 */
var parse_PrintSize = parseuint16; /* 2.4.204 0:3 */
var parse_Prot4Rev = parsebool; /* 2.4.205 */
var parse_Prot4RevPass = parseuint16; /* 2.4.206 */
var parse_Protect = parsebool; /* 2.4.207 */
var parse_RefreshAll = parsebool; /* 2.4.217 -- must be 0 if not template */
var parse_RightMargin = parse_Xnum; /* 2.4.219 */
var parse_RRTabId = parseuint16a; /* 2.4.241 */
var parse_ScenarioProtect = parsebool; /* 2.4.245 */
var parse_Scl = parseuint16a; /* 2.4.247 num, den */
var parse_String = parse_XLUnicodeString; /* 2.4.268 */
var parse_SxBool = parsebool; /* 2.4.274 */
var parse_TopMargin = parse_Xnum; /* 2.4.328 */
var parse_UsesELFs = parsebool; /* 2.4.337 -- should be 0 */
var parse_VCenter = parsebool; /* 2.4.342 */
var parse_WinProtect = parsebool; /* 2.4.347 */
var parse_WriteProtect = parsenoop; /* 2.4.350 empty record */


/* ---- */
var parse_VerticalPageBreaks = parsenoop;
var parse_HorizontalPageBreaks = parsenoop;
var parse_Selection = parsenoop;
var parse_Continue = parsenoop;
var parse_Pane = parsenoop;
var parse_Pls = parsenoop;
var parse_DCon = parsenoop;
var parse_DConRef = parsenoop;
var parse_DConName = parsenoop;
var parse_XCT = parsenoop;
var parse_CRN = parsenoop;
var parse_FileSharing = parsenoop;
var parse_Uncalced = parsenoop;
var parse_Template = parsenoop;
var parse_Intl = parsenoop;
var parse_WsBool = parsenoop;
var parse_Sort = parsenoop;
var parse_Sync = parsenoop;
var parse_LPr = parsenoop;
var parse_DxGCol = parsenoop;
var parse_FnGroupName = parsenoop;
var parse_FilterMode = parsenoop;
var parse_AutoFilterInfo = parsenoop;
var parse_AutoFilter = parsenoop;
var parse_ScenMan = parsenoop;
var parse_SCENARIO = parsenoop;
var parse_SxView = parsenoop;
var parse_Sxvd = parsenoop;
var parse_SXVI = parsenoop;
var parse_SxIvd = parsenoop;
var parse_SXLI = parsenoop;
var parse_SXPI = parsenoop;
var parse_DocRoute = parsenoop;
var parse_RecipName = parsenoop;
var parse_SXDI = parsenoop;
var parse_SXDB = parsenoop;
var parse_SXFDB = parsenoop;
var parse_SXDBB = parsenoop;
var parse_SXNum = parsenoop;
var parse_SxErr = parsenoop;
var parse_SXInt = parsenoop;
var parse_SXString = parsenoop;
var parse_SXDtr = parsenoop;
var parse_SxNil = parsenoop;
var parse_SXTbl = parsenoop;
var parse_SXTBRGIITM = parsenoop;
var parse_SxTbpg = parsenoop;
var parse_ObProj = parsenoop;
var parse_SXStreamID = parsenoop;
var parse_DBCell = parsenoop;
var parse_SXRng = parsenoop;
var parse_SxIsxoper = parsenoop;
var parse_BookBool = parsenoop;
var parse_DbOrParamQry = parsenoop;
var parse_OleObjectSize = parsenoop;
var parse_SXVS = parsenoop;
var parse_BkHim = parsenoop;
var parse_MsoDrawingGroup = parsenoop;
var parse_MsoDrawing = parsenoop;
var parse_MsoDrawingSelection = parsenoop;
var parse_PhoneticInfo = parsenoop;
var parse_SxRule = parsenoop;
var parse_SXEx = parsenoop;
var parse_SxFilt = parsenoop;
var parse_SxDXF = parsenoop;
var parse_SxItm = parsenoop;
var parse_SxName = parsenoop;
var parse_SxSelect = parsenoop;
var parse_SXPair = parsenoop;
var parse_SxFmla = parsenoop;
var parse_SxFormat = parsenoop;
var parse_SXVDEx = parsenoop;
var parse_SXFormula = parsenoop;
var parse_SXDBEx = parsenoop;
var parse_RRDInsDel = parsenoop;
var parse_RRDHead = parsenoop;
var parse_RRDChgCell = parsenoop;
var parse_RRDRenSheet = parsenoop;
var parse_RRSort = parsenoop;
var parse_RRDMove = parsenoop;
var parse_RRFormat = parsenoop;
var parse_RRAutoFmt = parsenoop;
var parse_RRInsertSh = parsenoop;
var parse_RRDMoveBegin = parsenoop;
var parse_RRDMoveEnd = parsenoop;
var parse_RRDInsDelBegin = parsenoop;
var parse_RRDInsDelEnd = parsenoop;
var parse_RRDConflict = parsenoop;
var parse_RRDDefName = parsenoop;
var parse_RRDRstEtxp = parsenoop;
var parse_LRng = parsenoop;
var parse_CUsr = parsenoop;
var parse_CbUsr = parsenoop;
var parse_UsrInfo = parsenoop;
var parse_UsrExcl = parsenoop;
var parse_FileLock = parsenoop;
var parse_RRDInfo = parsenoop;
var parse_BCUsrs = parsenoop;
var parse_UsrChk = parsenoop;
var parse_UserBView = parsenoop;
var parse_UserSViewBegin = parsenoop; // overloaded
var parse_UserSViewEnd = parsenoop;
var parse_RRDUserView = parsenoop;
var parse_Qsi = parsenoop;
var parse_CondFmt = parsenoop;
var parse_CF = parsenoop;
var parse_DVal = parsenoop;
var parse_DConBin = parsenoop;
var parse_Lel = parsenoop;
var parse_XLSCodeName = parse_XLUnicodeString;
var parse_SXFDBType = parsenoop;
var parse_ObNoMacros = parsenoop;
var parse_Dv = parsenoop;
var parse_Index = parsenoop;
var parse_Table = parsenoop;
var parse_BigName = parsenoop;
var parse_ContinueBigName = parsenoop;
var parse_WebPub = parsenoop;
var parse_QsiSXTag = parsenoop;
var parse_DBQueryExt = parsenoop;
var parse_ExtString = parsenoop;
var parse_TxtQry = parsenoop;
var parse_Qsir = parsenoop;
var parse_Qsif = parsenoop;
var parse_RRDTQSIF = parsenoop;
var parse_OleDbConn = parsenoop;
var parse_WOpt = parsenoop;
var parse_SXViewEx = parsenoop;
var parse_SXTH = parsenoop;
var parse_SXPIEx = parsenoop;
var parse_SXVDTEx = parsenoop;
var parse_SXViewEx9 = parsenoop;
var parse_ContinueFrt = parsenoop;
var parse_RealTimeData = parsenoop;
var parse_ChartFrtInfo = parsenoop;
var parse_FrtWrapper = parsenoop;
var parse_StartBlock = parsenoop;
var parse_EndBlock = parsenoop;
var parse_StartObject = parsenoop;
var parse_EndObject = parsenoop;
var parse_CatLab = parsenoop;
var parse_YMult = parsenoop;
var parse_SXViewLink = parsenoop;
var parse_PivotChartBits = parsenoop;
var parse_FrtFontList = parsenoop;
var parse_SheetExt = parsenoop;
var parse_BookExt = parsenoop;
var parse_SXAddl = parsenoop;
var parse_CrErr = parsenoop;
var parse_HFPicture = parsenoop;
var parse_Feat = parsenoop;
var parse_DataLabExt = parsenoop;
var parse_DataLabExtContents = parsenoop;
var parse_CellWatch = parsenoop;
var parse_FeatHdr11 = parsenoop;
var parse_Feature11 = parsenoop;
var parse_DropDownObjIds = parsenoop;
var parse_ContinueFrt11 = parsenoop;
var parse_DConn = parsenoop;
var parse_List12 = parsenoop;
var parse_Feature12 = parsenoop;
var parse_CondFmt12 = parsenoop;
var parse_CF12 = parsenoop;
var parse_CFEx = parsenoop;
var parse_AutoFilter12 = parsenoop;
var parse_ContinueFrt12 = parsenoop;
var parse_MDTInfo = parsenoop;
var parse_MDXStr = parsenoop;
var parse_MDXTuple = parsenoop;
var parse_MDXSet = parsenoop;
var parse_MDXProp = parsenoop;
var parse_MDXKPI = parsenoop;
var parse_MDB = parsenoop;
var parse_PLV = parsenoop;
var parse_DXF = parsenoop;
var parse_TableStyles = parsenoop;
var parse_TableStyle = parsenoop;
var parse_TableStyleElement = parsenoop;
var parse_NamePublish = parsenoop;
var parse_SortData = parsenoop;
var parse_GUIDTypeLib = parsenoop;
var parse_FnGrp12 = parsenoop;
var parse_NameFnGrp12 = parsenoop;
var parse_HeaderFooter = parsenoop;
var parse_CrtLayout12 = parsenoop;
var parse_CrtMlFrt = parsenoop;
var parse_CrtMlFrtContinue = parsenoop;
var parse_ShapePropsStream = parsenoop;
var parse_TextPropsStream = parsenoop;
var parse_RichTextStream = parsenoop;
var parse_CrtLayout12A = parsenoop;
var parse_Units = parsenoop;
var parse_Chart = parsenoop;
var parse_Series = parsenoop;
var parse_DataFormat = parsenoop;
var parse_LineFormat = parsenoop;
var parse_MarkerFormat = parsenoop;
var parse_AreaFormat = parsenoop;
var parse_PieFormat = parsenoop;
var parse_AttachedLabel = parsenoop;
var parse_SeriesText = parsenoop;
var parse_ChartFormat = parsenoop;
var parse_Legend = parsenoop;
var parse_SeriesList = parsenoop;
var parse_Bar = parsenoop;
var parse_Line = parsenoop;
var parse_Pie = parsenoop;
var parse_Area = parsenoop;
var parse_Scatter = parsenoop;
var parse_CrtLine = parsenoop;
var parse_Axis = parsenoop;
var parse_Tick = parsenoop;
var parse_ValueRange = parsenoop;
var parse_CatSerRange = parsenoop;
var parse_AxisLine = parsenoop;
var parse_CrtLink = parsenoop;
var parse_DefaultText = parsenoop;
var parse_Text = parsenoop;
var parse_ObjectLink = parsenoop;
var parse_Frame = parsenoop;
var parse_Begin = parsenoop;
var parse_End = parsenoop;
var parse_PlotArea = parsenoop;
var parse_Chart3d = parsenoop;
var parse_PicF = parsenoop;
var parse_DropBar = parsenoop;
var parse_Radar = parsenoop;
var parse_Surf = parsenoop;
var parse_RadarArea = parsenoop;
var parse_AxisParent = parsenoop;
var parse_LegendException = parsenoop;
var parse_SerToCrt = parsenoop;
var parse_AxesUsed = parsenoop;
var parse_SBaseRef = parsenoop;
var parse_SerParent = parsenoop;
var parse_SerAuxTrend = parsenoop;
var parse_IFmtRecord = parsenoop;
var parse_Pos = parsenoop;
var parse_AlRuns = parsenoop;
var parse_BRAI = parsenoop;
var parse_SerAuxErrBar = parsenoop;
var parse_SerFmt = parsenoop;
var parse_Chart3DBarShape = parsenoop;
var parse_Fbi = parsenoop;
var parse_BopPop = parsenoop;
var parse_AxcExt = parsenoop;
var parse_Dat = parsenoop;
var parse_PlotGrowth = parsenoop;
var parse_SIIndex = parsenoop;
var parse_GelFrame = parsenoop;
var parse_BopPopCustom = parsenoop;
var parse_Fbi2 = parsenoop;

/* --- Specific to versions before BIFF8 --- */
S
SheetJS 已提交
5205 5206 5207 5208 5209 5210 5211 5212 5213 5214
function parse_ImData(blob, length, opts) {
	var tgt = blob.l + length;
	var cf = blob.read_shift(2);
	var env = blob.read_shift(2);
	var lcb = blob.read_shift(4);
	var o = {fmt:cf, env:env, len:lcb, data:blob.slice(blob.l,blob.l+lcb)};
	blob.l += lcb;
	return o;
}

S
SheetJS 已提交
5215 5216 5217 5218 5219 5220 5221 5222 5223 5224
function parse_BIFF5String(blob) {
	var len = blob.read_shift(1);
	return blob.read_shift(len, 'sbcs-cont');
}

/* BIFF2_??? where ??? is the name from [XLS] */
function parse_BIFF2STR(blob, length, opts) {
	var cell = parse_XLSCell(blob, 6);
	++blob.l;
	var str = parse_XLUnicodeString2(blob, length-7, opts);
S
SheetJS 已提交
5225
	cell.t = 'str';
S
SheetJS 已提交
5226 5227 5228 5229 5230 5231 5232 5233
	cell.val = str;
	return cell;
}

function parse_BIFF2NUM(blob, length, opts) {
	var cell = parse_XLSCell(blob, 6);
	++blob.l;
	var num = parse_Xnum(blob, 8);
S
SheetJS 已提交
5234
	cell.t = 'n';
S
SheetJS 已提交
5235 5236 5237 5238
	cell.val = num;
	return cell;
}

S
SheetJS 已提交
5239 5240 5241 5242
function parse_BIFF2INT(blob, length) {
	var cell = parse_XLSCell(blob, 6);
	++blob.l;
	var num = blob.read_shift(2);
S
SheetJS 已提交
5243
	cell.t = 'n';
S
SheetJS 已提交
5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260
	cell.val = num;
	return cell;
}

function parse_BIFF2STRING(blob, length) {
	var cch = blob.read_shift(1);
	if(cch === 0) { blob.l++; return ""; }
	return blob.read_shift(cch, 'sbcs-cont');
}

/* TODO: convert to BIFF8 font struct */
function parse_BIFF2FONTXTRA(blob, length) {
	blob.l += 6; // unknown
	blob.l += 2; // font weight "bls"
	blob.l += 1; // charset
	blob.l += 3; // unknown
	blob.l += 1; // font family
S
SheetJS 已提交
5261
	blob.l += length - 13;
S
SheetJS 已提交
5262
}
S
SheetJS 已提交
5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274

/* TODO: parse rich text runs */
function parse_RString(blob, length, opts) {
	var end = blob.l + length;
	var cell = parse_XLSCell(blob, 6);
	var cch = blob.read_shift(2);
	var str = parse_XLUnicodeStringNoCch(blob, cch, opts);
	blob.l = end;
	cell.t = 'str';
	cell.val = str;
	return cell;
}
S
SheetJS 已提交
5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333
/* from js-harb (C) 2014-present  SheetJS */
var DBF = (function() {
var dbf_codepage_map = {
	/* Code Pages Supported by Visual FoxPro */
	/*::[*/0x01/*::]*/:   437,           /*::[*/0x02/*::]*/:   850,
	/*::[*/0x03/*::]*/:  1252,           /*::[*/0x04/*::]*/: 10000,
	/*::[*/0x64/*::]*/:   852,           /*::[*/0x65/*::]*/:   866,
	/*::[*/0x66/*::]*/:   865,           /*::[*/0x67/*::]*/:   861,
	/*::[*/0x68/*::]*/:   895,           /*::[*/0x69/*::]*/:   620,
	/*::[*/0x6A/*::]*/:   737,           /*::[*/0x6B/*::]*/:   857,
	/*::[*/0x78/*::]*/:   950,           /*::[*/0x79/*::]*/:   949,
	/*::[*/0x7A/*::]*/:   936,           /*::[*/0x7B/*::]*/:   932,
	/*::[*/0x7C/*::]*/:   874,           /*::[*/0x7D/*::]*/:  1255,
	/*::[*/0x7E/*::]*/:  1256,           /*::[*/0x96/*::]*/: 10007,
	/*::[*/0x97/*::]*/: 10029,           /*::[*/0x98/*::]*/: 10006,
	/*::[*/0xC8/*::]*/:  1250,           /*::[*/0xC9/*::]*/:  1251,
	/*::[*/0xCA/*::]*/:  1254,           /*::[*/0xCB/*::]*/:  1253,

	/* shapefile DBF extension */
	/*::[*/0x00/*::]*/: 20127,           /*::[*/0x08/*::]*/:   865,
	/*::[*/0x09/*::]*/:   437,           /*::[*/0x0A/*::]*/:   850,
	/*::[*/0x0B/*::]*/:   437,           /*::[*/0x0D/*::]*/:   437,
	/*::[*/0x0E/*::]*/:   850,           /*::[*/0x0F/*::]*/:   437,
	/*::[*/0x10/*::]*/:   850,           /*::[*/0x11/*::]*/:   437,
	/*::[*/0x12/*::]*/:   850,           /*::[*/0x13/*::]*/:   932,
	/*::[*/0x14/*::]*/:   850,           /*::[*/0x15/*::]*/:   437,
	/*::[*/0x16/*::]*/:   850,           /*::[*/0x17/*::]*/:   865,
	/*::[*/0x18/*::]*/:   437,           /*::[*/0x19/*::]*/:   437,
	/*::[*/0x1A/*::]*/:   850,           /*::[*/0x1B/*::]*/:   437,
	/*::[*/0x1C/*::]*/:   863,           /*::[*/0x1D/*::]*/:   850,
	/*::[*/0x1F/*::]*/:   852,           /*::[*/0x22/*::]*/:   852,
	/*::[*/0x23/*::]*/:   852,           /*::[*/0x24/*::]*/:   860,
	/*::[*/0x25/*::]*/:   850,           /*::[*/0x26/*::]*/:   866,
	/*::[*/0x37/*::]*/:   850,           /*::[*/0x40/*::]*/:   852,
	/*::[*/0x4D/*::]*/:   936,           /*::[*/0x4E/*::]*/:   949,
	/*::[*/0x4F/*::]*/:   950,           /*::[*/0x50/*::]*/:   874,
	/*::[*/0x57/*::]*/:  1252,           /*::[*/0x58/*::]*/:  1252,
	/*::[*/0x59/*::]*/:  1252,

	/*::[*/0xFF/*::]*/: 16969
};

/* TODO: find an actual specification */
function dbf_to_aoa(buf, opts)/*:AOA*/ {
	var out/*:AOA*/ = [];
	/* TODO: browser based */
	var d/*:Block*/ = (new_raw_buf(1)/*:any*/);
	switch(opts.type) {
		case 'base64': d = s2a(Base64.decode(buf)); break;
		case 'binary': d = s2a(buf); break;
		case 'buffer':
		case 'array': d = buf; break;
	}
	prep_blob(d, 0);
	/* header */
	var ft = d.read_shift(1);
	var memo = false;
	var vfp = false;
	switch(ft) {
S
TXT/PRN  
SheetJS 已提交
5334
		case 0x02: case 0x03: break;
S
SheetJS 已提交
5335 5336 5337 5338 5339
		case 0x30: vfp = true; memo = true; break;
		case 0x31: vfp = true; break;
		case 0x83: memo = true; break;
		case 0x8B: memo = true; break;
		case 0xF5: memo = true; break;
S
SheetJS 已提交
5340
		default: throw new Error("DBF Unsupported Version: " + ft.toString(16));
S
SheetJS 已提交
5341
	}
S
TXT/PRN  
SheetJS 已提交
5342 5343 5344 5345 5346
	var filedate = new Date(), nrow = 0, fpos = 0;
	if(ft == 0x02) nrow = d.read_shift(2);
	filedate = new Date(d.read_shift(1) + 1900, d.read_shift(1) - 1, d.read_shift(1));
	if(ft != 0x02) nrow = d.read_shift(4);
	if(ft != 0x02) fpos = d.read_shift(2);
S
SheetJS 已提交
5347 5348
	var rlen = d.read_shift(2);

S
TXT/PRN  
SheetJS 已提交
5349 5350 5351 5352
	var flags = 0, current_cp = 1252;
	if(ft != 0x02) {
	d.l+=16;
	flags = d.read_shift(1);
S
SheetJS 已提交
5353 5354 5355 5356 5357 5358 5359
	//if(memo && ((flags & 0x02) === 0)) throw new Error("DBF Flags " + flags.toString(16) + " ft " + ft.toString(16));

	/* codepage present in FoxPro */
	if(d[d.l] !== 0) current_cp = dbf_codepage_map[d[d.l]];
	d.l+=1;

	d.l+=2;
S
TXT/PRN  
SheetJS 已提交
5360
	}
S
SheetJS 已提交
5361 5362
	var fields = [], field = {};
	var hend = fpos - 10 - (vfp ? 264 : 0);
S
TXT/PRN  
SheetJS 已提交
5363
	while(ft == 0x02 ? d.l < d.length && d[d.l] != 0x0d: d.l < hend) {
S
SheetJS 已提交
5364 5365 5366 5367
		field = {};
		field.name = cptable.utils.decode(current_cp, d.slice(d.l, d.l+10)).replace(/[\u0000\r\n].*$/g,"");
		d.l += 11;
		field.type = String.fromCharCode(d.read_shift(1));
S
TXT/PRN  
SheetJS 已提交
5368
		if(ft != 0x02) field.offset = d.read_shift(4);
S
SheetJS 已提交
5369
		field.len = d.read_shift(1);
S
TXT/PRN  
SheetJS 已提交
5370
		if(ft == 0x02) field.offset = d.read_shift(2);
S
SheetJS 已提交
5371 5372
		field.dec = d.read_shift(1);
		if(field.name.length) fields.push(field);
S
TXT/PRN  
SheetJS 已提交
5373
		if(ft != 0x02) d.l += 14;
S
SheetJS 已提交
5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394
		switch(field.type) {
			// case 'B': break; // Binary
			case 'C': break; // character
			case 'D': break; // date
			case 'F': break; // floating point
			// case 'G': break; // General
			case 'I': break; // long
			case 'L': break; // boolean
			case 'M': break; // memo
			case 'N': break; // number
			// case 'O': break; // double
			// case 'P': break; // Picture
			case 'T': break; // datetime
			case 'Y': break; // currency
			case '0': break; // null ?
			case '+': break; // autoincrement
			case '@': break; // timestamp
			default: throw new Error('Unknown Field Type: ' + field.type);
		}
	}
	if(d[d.l] !== 0x0D) d.l = fpos-1;
S
TXT/PRN  
SheetJS 已提交
5395 5396 5397 5398 5399
	else if(ft == 0x02) d.l = 0x209;
	if(ft != 0x02) {
		if(d.read_shift(1) !== 0x0D) throw new Error("DBF Terminator not found " + d.l + " " + d[d.l]);
		d.l = fpos;
	}
S
SheetJS 已提交
5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436
	/* data */
	var R = 0, C = 0;
	out[0] = [];
	for(C = 0; C != fields.length; ++C) out[0][C] = fields[C].name;
	while(nrow-- > 0) {
		if(d[d.l] === 0x2A) { d.l+=rlen; continue; }
		++d.l;
		out[++R] = []; C = 0;
		for(C = 0; C != fields.length; ++C) {
			var dd = d.slice(d.l, d.l+fields[C].len); d.l+=fields[C].len;
			prep_blob(dd, 0);
			var s = cptable.utils.decode(current_cp, dd);
			switch(fields[C].type) {
				case 'C':
					out[R][C] = cptable.utils.decode(current_cp, dd);
					out[R][C] = out[R][C].trim();
					break;
				case 'D':
					if(s.length === 8) out[R][C] = new Date(+s.substr(0,4), +s.substr(4,2)-1, +s.substr(6,2));
					else out[R][C] = s;
					break;
				case 'F': out[R][C] = parseFloat(s.trim()); break;
				case 'I': out[R][C] = dd.read_shift(4, 'i'); break;
				case 'L': switch(s.toUpperCase()) {
					case 'Y': case 'T': out[R][C] = true; break;
					case 'N': case 'F': out[R][C] = false; break;
					case ' ': case '?': out[R][C] = false; break; /* NOTE: technically unitialized */
					default: throw new Error("DBF Unrecognized L:|" + s + "|");
					} break;
				case 'M': /* TODO: handle memo files */
					if(!memo) throw new Error("DBF Unexpected MEMO for type " + ft.toString(16));
					out[R][C] = "##MEMO##" + dd.read_shift(4);
					break;
				case 'N': out[R][C] = +s.replace(/\u0000/g,"").trim(); break;
				case 'T':
					var day = dd.read_shift(4), ms = dd.read_shift(4);
					throw new Error(day + " | " + ms);
S
SheetJS 已提交
5437
					//out[R][C] = new Date(); // TODO
S
SheetJS 已提交
5438 5439 5440 5441 5442 5443 5444 5445 5446
					//break;
				case 'Y': out[R][C] = dd.read(4,'i')/1e4; break;
				case '0':
					if(fields[C].name === '_NullFlags') break;
					/* falls through */
				default: throw new Error("DBF Unsupported data type " + fields[C].type);
			}
		}
	}
S
TXT/PRN  
SheetJS 已提交
5447
	if(ft != 0x02) if(d.l < d.length && d[d.l++] != 0x1A) throw new Error("DBF EOF Marker missing " + (d.l-1) + " of " + d.length + " " + d[d.l-1].toString(16));
S
SheetJS 已提交
5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466
	return out;
}

function dbf_to_sheet(buf, opts)/*:Worksheet*/ {
	var o = opts || {};
	if(!o.dateNF) o.dateNF = "yyyymmdd";
	return aoa_to_sheet(dbf_to_aoa(buf, o), o);
}

function dbf_to_workbook(buf, opts)/*:Workbook*/ {
	try { return sheet_to_workbook(dbf_to_sheet(buf, opts), opts); }
	catch(e) { if(opts && opts.WTF) throw e; }
	return ({SheetNames:[],Sheets:{}});
}
	return {
		to_workbook: dbf_to_workbook,
		to_sheet: dbf_to_sheet
	};
})();
S
SheetJS 已提交
5467 5468 5469

var SYLK = (function() {
	/* TODO: find an actual specification */
S
SheetJS 已提交
5470
	function sylk_to_aoa(d/*:RawData*/, opts)/*:[AOA, Worksheet]*/ {
S
SheetJS 已提交
5471 5472 5473 5474 5475 5476 5477 5478
		switch(opts.type) {
			case 'base64': return sylk_to_aoa_str(Base64.decode(d), opts);
			case 'binary': return sylk_to_aoa_str(d, opts);
			case 'buffer': return sylk_to_aoa_str(d.toString('binary'), opts);
			case 'array': return sylk_to_aoa_str(cc2str(d), opts);
		}
		throw new Error("Unrecognized type " + opts.type);
	}
S
SheetJS 已提交
5479
	function sylk_to_aoa_str(str/*:string*/, opts)/*:[AOA, Worksheet]*/ {
S
SheetJS 已提交
5480 5481 5482
		var records = str.split(/[\n\r]+/), R = -1, C = -1, ri = 0, rj = 0, arr = [];
		var formats = [];
		var next_cell_format = null;
S
SheetJS 已提交
5483 5484
		var sht = {}, rowinfo = [], colinfo = [], cw = [];
		var Mval = 0, j;
S
SheetJS 已提交
5485
		for (; ri !== records.length; ++ri) {
S
SheetJS 已提交
5486
			Mval = 0;
S
SheetJS 已提交
5487 5488 5489
			var rstr=records[ri].trim();
			var record=rstr.replace(/;;/g, "\u0001").split(";").map(function(x) { return x.replace(/\u0001/g, ";"); });
			var RT=record[0], val;
S
SheetJS 已提交
5490 5491 5492 5493 5494 5495 5496 5497
			if(rstr.length > 0) switch(RT) {
			case 'ID': break; /* header */
			case 'E': break; /* EOF */
			case 'B': break; /* dimensions */
			case 'O': break; /* options? */
			case 'P':
				if(record[1].charAt(0) == 'P')
					formats.push(rstr.substr(3).replace(/;;/g, ";"));
S
SheetJS 已提交
5498
				break;
S
SheetJS 已提交
5499 5500 5501
			case 'C':
			for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
				case 'X': C = parseInt(record[rj].substr(1))-1; break;
S
SheetJS 已提交
5502 5503
				case 'Y':
					R = parseInt(record[rj].substr(1))-1; C = 0;
S
SheetJS 已提交
5504
					for(j = arr.length; j <= R; ++j) arr[j] = [];
S
SheetJS 已提交
5505 5506 5507 5508 5509 5510
					break;
				case 'K':
					val = record[rj].substr(1);
					if(val.charAt(0) === '"') val = val.substr(1,val.length - 2);
					else if(val === 'TRUE') val = true;
					else if(val === 'FALSE') val = false;
S
SheetJS 已提交
5511 5512
					else if(!isNaN(fuzzynum(val))) {
						val = fuzzynum(val);
S
SheetJS 已提交
5513
						if(next_cell_format !== null && SSF.is_date(next_cell_format)) val = numdate(val);
5514 5515
					} else if(!isNaN(fuzzydate(val).getDate())) {
						val = parseDate(val);
S
SheetJS 已提交
5516 5517 5518 5519
					}
					arr[R][C] = val;
					next_cell_format = null;
					break;
S
SheetJS 已提交
5520
				case 'E':
S
SheetJS 已提交
5521
					var formula = rc_to_a1(record[rj].substr(1), {r:R,c:C});
S
SheetJS 已提交
5522 5523
					arr[R][C] = [arr[R][C], formula];
					break;
S
SheetJS 已提交
5524 5525 5526
				default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
			} break;
			case 'F':
S
SheetJS 已提交
5527
			var F_seen = 0;
S
SheetJS 已提交
5528
			for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
S
SheetJS 已提交
5529
				case 'X': C = parseInt(record[rj].substr(1))-1; ++F_seen; break;
S
SheetJS 已提交
5530
				case 'Y':
S
SheetJS 已提交
5531
					R = parseInt(record[rj].substr(1))-1; /*C = 0;*/
S
SheetJS 已提交
5532
					for(j = arr.length; j <= R; ++j) arr[j] = [];
5533
					break;
S
SheetJS 已提交
5534 5535
				case 'M': Mval = parseInt(record[rj].substr(1)) / 20; break;
				case 'F': break; /* ??? */
S
SheetJS 已提交
5536 5537
				case 'P':
					next_cell_format = formats[parseInt(record[rj].substr(1))];
S
SheetJS 已提交
5538
					break;
S
SheetJS 已提交
5539 5540 5541
				case 'S': break; /* cell style */
				case 'D': break; /* column */
				case 'N': break; /* font */
S
SheetJS 已提交
5542 5543 5544 5545 5546 5547
				case 'W':
					cw = record[rj].substr(1).split(" ");
					for(j = parseInt(cw[0], 10); j <= parseInt(cw[1], 10); ++j) {
						Mval = parseInt(cw[2], 10);
						colinfo[j-1] = Mval == 0 ? {hidden:true}: {wch:Mval}; process_col(colinfo[j-1]);
					} break;
S
SheetJS 已提交
5548 5549 5550 5551 5552
				case 'C': /* default column format */
					C = parseInt(record[rj].substr(1))-1;
					if(!colinfo[C]) colinfo[C] = {};
					break;
				case 'R': /* row properties */
S
SheetJS 已提交
5553
					R = parseInt(record[rj].substr(1))-1;
S
SheetJS 已提交
5554
					if(!rowinfo[R]) rowinfo[R] = {};
S
SheetJS 已提交
5555 5556
					if(Mval > 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); }
					else if(Mval == 0) rowinfo[R].hidden = true;
S
SheetJS 已提交
5557 5558
					break;
				default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
S
SheetJS 已提交
5559
			}
5560
			if(F_seen < 1) next_cell_format = null; break;
S
SheetJS 已提交
5561
			default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
S
SheetJS 已提交
5562 5563
			}
		}
S
SheetJS 已提交
5564 5565
		if(rowinfo.length > 0) sht['!rows'] = rowinfo;
		if(colinfo.length > 0) sht['!cols'] = colinfo;
S
SheetJS 已提交
5566
		return [arr, sht];
S
SheetJS 已提交
5567 5568
	}

5569 5570
	function sylk_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
		var aoasht = sylk_to_aoa(d, opts);
S
SheetJS 已提交
5571
		var aoa = aoasht[0], ws = aoasht[1];
S
SheetJS 已提交
5572 5573 5574 5575
		var o = aoa_to_sheet(aoa, opts);
		keys(ws).forEach(function(k) { o[k] = ws[k]; });
		return o;
	}
S
SheetJS 已提交
5576

5577
	function sylk_to_workbook(d/*:RawData*/, opts)/*:Workbook*/ { return sheet_to_workbook(sylk_to_sheet(d, opts), opts); }
S
SheetJS 已提交
5578 5579 5580 5581

	function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*/, opts)/*:string*/ {
		var o = "C;Y" + (R+1) + ";X" + (C+1) + ";K";
		switch(cell.t) {
S
SheetJS 已提交
5582 5583 5584
			case 'n':
				o += (cell.v||0);
				if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break;
S
SheetJS 已提交
5585 5586 5587 5588 5589 5590 5591 5592
			case 'b': o += cell.v ? "TRUE" : "FALSE"; break;
			case 'e': o += cell.w || cell.v; break;
			case 'd': o += '"' + (cell.w || cell.v) + '"'; break;
			case 's': o += '"' + cell.v.replace(/"/g,"") + '"'; break;
		}
		return o;
	}

S
SheetJS 已提交
5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605
	function write_ws_cols_sylk(out, cols) {
		cols.forEach(function(col, i) {
			var rec = "F;W" + (i+1) + " " + (i+1) + " ";
			if(col.hidden) rec += "0";
			else {
				if(typeof col.width == 'number') col.wpx = width2px(col.width);
				if(typeof col.wpx == 'number') col.wch = px2char(col.wpx);
				if(typeof col.wch == 'number') rec += Math.round(col.wch);
			}
			if(rec.charAt(rec.length - 1) != " ") out.push(rec);
		});
	}

S
SheetJS 已提交
5606
	function write_ws_rows_sylk(out/*:Array<string>*/, rows/*:Array<RowInfo>*/) {
S
SheetJS 已提交
5607 5608 5609 5610 5611 5612 5613 5614 5615
		rows.forEach(function(row, i) {
			var rec = "F;";
			if(row.hidden) rec += "M0;";
			else if(row.hpt) rec += "M" + 20 * row.hpt + ";";
			else if(row.hpx) rec += "M" + 20 * px2pt(row.hpx) + ";";
			if(rec.length > 2) out.push(rec + "R" + (i+1));
		});
	}

S
SheetJS 已提交
5616 5617 5618
	function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
		var preamble/*:Array<string>*/ = ["ID;PWXL;N;E"], o/*:Array<string>*/ = [];
		var r = decode_range(ws['!ref']), cell/*:Cell*/;
S
SheetJS 已提交
5619
		var dense = Array.isArray(ws);
S
SheetJS 已提交
5620 5621 5622 5623 5624 5625 5626
		var RS = "\r\n";

		preamble.push("P;PGeneral");
		preamble.push("F;P0;DG0G8;M255");
		if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
		if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);

S
SheetJS 已提交
5627
		preamble.push("B;Y" + (r.e.r - r.s.r + 1) + ";X" + (r.e.c - r.s.c + 1) + ";D" + [r.s.c,r.s.r,r.e.c,r.e.r].join(" "));
S
SheetJS 已提交
5628 5629 5630
		for(var R = r.s.r; R <= r.e.r; ++R) {
			for(var C = r.s.c; C <= r.e.c; ++C) {
				var coord = encode_cell({r:R,c:C});
S
SheetJS 已提交
5631
				cell = dense ? (ws[R]||[])[C]: ws[coord];
S
SheetJS 已提交
5632
				if(!cell || cell.v == null && (!cell.f || cell.F)) continue;
S
SheetJS 已提交
5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672
				o.push(write_ws_cell_sylk(cell, ws, R, C, opts));
			}
		}
		return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
	}

	return {
		to_workbook: sylk_to_workbook,
		to_sheet: sylk_to_sheet,
		from_sheet: sheet_to_sylk
	};
})();

var DIF = (function() {
	function dif_to_aoa(d/*:RawData*/, opts)/*:AOA*/ {
		switch(opts.type) {
			case 'base64': return dif_to_aoa_str(Base64.decode(d), opts);
			case 'binary': return dif_to_aoa_str(d, opts);
			case 'buffer': return dif_to_aoa_str(d.toString('binary'), opts);
			case 'array': return dif_to_aoa_str(cc2str(d), opts);
		}
		throw new Error("Unrecognized type " + opts.type);
	}
	function dif_to_aoa_str(str/*:string*/, opts)/*:AOA*/ {
		var records = str.split('\n'), R = -1, C = -1, ri = 0, arr = [];
		for (; ri !== records.length; ++ri) {
			if (records[ri].trim() === 'BOT') { arr[++R] = []; C = 0; continue; }
			if (R < 0) continue;
			var metadata = records[ri].trim().split(",");
			var type = metadata[0], value = metadata[1];
			++ri;
			var data = records[ri].trim();
			switch (+type) {
				case -1:
					if (data === 'BOT') { arr[++R] = []; C = 0; continue; }
					else if (data !== 'EOD') throw new Error("Unrecognized DIF special command " + data);
					break;
				case 0:
					if(data === 'TRUE') arr[R][C] = true;
					else if(data === 'FALSE') arr[R][C] = false;
S
SheetJS 已提交
5673
					else if(!isNaN(fuzzynum(value))) arr[R][C] = fuzzynum(value);
S
SheetJS 已提交
5674
					else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value);
S
SheetJS 已提交
5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695
					else arr[R][C] = value;
					++C; break;
				case 1:
					data = data.substr(1,data.length-2);
					arr[R][C++] = data !== '' ? data : null;
					break;
			}
			if (data === 'EOD') break;
		}
		return arr;
	}

	function dif_to_sheet(str/*:string*/, opts)/*:Worksheet*/ { return aoa_to_sheet(dif_to_aoa(str, opts), opts); }
	function dif_to_workbook(str/*:string*/, opts)/*:Workbook*/ { return sheet_to_workbook(dif_to_sheet(str, opts), opts); }

	var sheet_to_dif = (function() {
		var push_field = function pf(o/*:Array<string>*/, topic/*:string*/, v/*:number*/, n/*:number*/, s/*:string*/) {
			o.push(topic);
			o.push(v + "," + n);
			o.push('"' + s.replace(/"/g,'""') + '"');
		};
S
SheetJS 已提交
5696
		var push_value = function po(o/*:Array<string>*/, type/*:number*/, v/*:any*/, s/*:string*/) {
S
SheetJS 已提交
5697 5698 5699 5700 5701 5702
			o.push(type + "," + v);
			o.push(type == 1 ? '"' + s.replace(/"/g,'""') + '"' : s);
		};
		return function sheet_to_dif(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
			var o/*:Array<string>*/ = [];
			var r = decode_range(ws['!ref']), cell/*:Cell*/;
S
SheetJS 已提交
5703
			var dense = Array.isArray(ws);
S
SheetJS 已提交
5704 5705 5706 5707 5708 5709 5710 5711
			push_field(o, "TABLE", 0, 1, "sheetjs");
			push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,"");
			push_field(o, "TUPLES", 0, r.e.c - r.s.c + 1,"");
			push_field(o, "DATA", 0, 0,"");
			for(var R = r.s.r; R <= r.e.r; ++R) {
				push_value(o, -1, 0, "BOT");
				for(var C = r.s.c; C <= r.e.c; ++C) {
					var coord = encode_cell({r:R,c:C});
S
SheetJS 已提交
5712
					cell = dense ? (ws[R]||[])[C] : ws[coord];
S
SheetJS 已提交
5713
					if(!cell) { push_value(o, 1, 0, ""); continue;}
S
SheetJS 已提交
5714
					switch(cell.t) {
S
SheetJS 已提交
5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734
						case 'n':
							var val = DIF_XL ? cell.w : cell.v;
							if(!val && cell.v != null) val = cell.v;
							if(val == null) {
								if(DIF_XL && cell.f && !cell.F) push_value(o, 1, 0, "=" + cell.f);
								else push_value(o, 1, 0, "");
							}
							else push_value(o, 0, val, "V");
							break;
						case 'b':
							push_value(o, 0, cell.v ? 1 : 0, cell.v ? "TRUE" : "FALSE");
							break;
						case 's':
							push_value(o, 1, 0, (!DIF_XL || isNaN(cell.v)) ? cell.v : '="' + cell.v + '"');
							break;
						case 'd':
							if(!cell.w) cell.w = SSF.format(cell.z || SSF._table[14], datenum(parseDate(cell.v)));
							if(DIF_XL) push_value(o, 0, cell.w, "V");
							else push_value(o, 1, 0, cell.w);
							break;
S
SheetJS 已提交
5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751
						default: push_value(o, 1, 0, "");
					}
				}
			}
			push_value(o, -1, 0, "EOD");
			var RS = "\r\n";
			var oo = o.join(RS);
			//while((oo.length & 0x7F) != 0) oo += "\0";
			return oo;
		};
	})();
	return {
		to_workbook: dif_to_workbook,
		to_sheet: dif_to_sheet,
		from_sheet: sheet_to_dif
	};
})();
S
SheetJS 已提交
5752 5753

var PRN = (function() {
S
SheetJS 已提交
5754 5755 5756
	function set_text_arr(data/*:string*/, arr/*:AOA*/, R/*:number*/, C/*:number*/, o/*:any*/) {
		if(o.raw) arr[R][C] = data;
		else if(data === 'TRUE') arr[R][C] = true;
S
SheetJS 已提交
5757
		else if(data === 'FALSE') arr[R][C] = false;
S
SheetJS 已提交
5758
		else if(data === ""){/* empty */}
S
SheetJS 已提交
5759
		else if(!isNaN(fuzzynum(data))) arr[R][C] = fuzzynum(data);
5760
		else if(!isNaN(fuzzydate(data).getDate())) arr[R][C] = parseDate(data);
S
TXT/PRN  
SheetJS 已提交
5761
		else arr[R][C] = data;
S
SheetJS 已提交
5762 5763 5764
	}

	function prn_to_aoa_str(f/*:string*/, opts)/*:AOA*/ {
S
SheetJS 已提交
5765
		var o = opts || {};
S
SheetJS 已提交
5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781
		var arr/*:AOA*/ = ([]/*:any*/);
		if(!f || f.length === 0) return arr;
		var lines = f.split(/[\r\n]/);
		var L = lines.length - 1;
		while(L >= 0 && lines[L].length === 0) --L;
		var start = 10, idx = 0;
		var R = 0;
		for(; R <= L; ++R) {
			idx = lines[R].indexOf(" ");
			if(idx == -1) idx = lines[R].length; else idx++;
			start = Math.max(start, idx);
		}
		for(R = 0; R <= L; ++R) {
			arr[R] = [];
			/* TODO: confirm that widths are always 10 */
			var C = 0;
S
SheetJS 已提交
5782
			set_text_arr(lines[R].slice(0, start).trim(), arr, R, C, o);
S
SheetJS 已提交
5783
			for(C = 1; C <= (lines[R].length - start)/10 + 1; ++C)
S
SheetJS 已提交
5784
				set_text_arr(lines[R].slice(start+(C-1)*10,start+C*10).trim(),arr,R,C,o);
S
SheetJS 已提交
5785 5786 5787 5788
		}
		return arr;
	}

S
SheetJS 已提交
5789
	function dsv_to_sheet_str(str/*:string*/, opts)/*:Worksheet*/ {
S
SheetJS 已提交
5790
		var o = opts || {};
S
SheetJS 已提交
5791
		var sep = "";
5792
		if(DENSE != null && o.dense == null) o.dense = DENSE;
S
SheetJS 已提交
5793
		var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/);
S
SheetJS 已提交
5794 5795 5796 5797
		var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:0}}/*:any*/);

		/* known sep */
		if(str.substr(0,4) == "sep=" && str.charCodeAt(5) == 10) { sep = str.charAt(4); str = str.substr(6); }
S
SheetJS 已提交
5798
		else if(str.substr(0,1024).indexOf("\t") == -1) sep = ","; else sep = "\t";
S
SheetJS 已提交
5799 5800
		var R = 0, C = 0, v = 0;
		var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0;
S
SheetJS 已提交
5801
		str = str.replace(/\r\n/mg, "\n");
S
SheetJS 已提交
5802
		var _re/*:?RegExp*/ = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
S
SheetJS 已提交
5803
		function finish_cell() {
S
SheetJS 已提交
5804
			var s = str.slice(start, end);
S
SheetJS 已提交
5805
			var cell = ({}/*:any*/);
5806 5807
			if(o.raw) { cell.t = 's'; cell.v = s; }
			else if(s.charCodeAt(0) == 0x3D) { cell.t = 'n'; cell.f = s.substr(1); }
S
SheetJS 已提交
5808 5809
			else if(s == "TRUE") { cell.t = 'b'; cell.v = true; }
			else if(s == "FALSE") { cell.t = 'b'; cell.v = false; }
S
SheetJS 已提交
5810
			else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; cell.w = s; cell.v = v; }
S
SheetJS 已提交
5811
			else if(!isNaN(fuzzydate(s).getDate()) || _re && s.match(_re)) {
S
SheetJS 已提交
5812
				cell.z = o.dateNF || SSF._table[14];
S
SheetJS 已提交
5813 5814 5815 5816
				var k = 0;
				if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; }
				if(o.cellDates) { cell.t = 'd'; cell.v = parseDate(s, k); }
				else { cell.t = 'n'; cell.v = datenum(parseDate(s, k)); }
S
SheetJS 已提交
5817 5818
				cell.w = SSF.format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v);
			} else {
S
SheetJS 已提交
5819 5820 5821 5822
				cell.t = 's';
				if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
				cell.v = s;
			}
S
SheetJS 已提交
5823 5824
			if(o.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = cell; }
			else ws[encode_cell({c:C,r:R})] = cell;
S
SheetJS 已提交
5825 5826 5827
			start = end+1;
			if(range.e.c < C) range.e.c = C;
			if(range.e.r < R) range.e.r = R;
S
SheetJS 已提交
5828 5829 5830
			if(cc == sepcc) ++C; else { C = 0; ++R; }
		}
		for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) {
S
SheetJS 已提交
5831
			case 0x22: instr = !instr; break;
S
SheetJS 已提交
5832
			case sepcc: case 0x0a: case 0x0d: if(!instr) finish_cell(); break;
S
SheetJS 已提交
5833 5834
			default: break;
		}
S
SheetJS 已提交
5835
		if(end - start > 0) finish_cell();
S
SheetJS 已提交
5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847

		ws['!ref'] = encode_range(range);
		return ws;
	}

	function prn_to_sheet_str(str/*:string*/, opts)/*:Worksheet*/ {
		if(str.substr(0,4) == "sep=") return dsv_to_sheet_str(str, opts);
		if(str.indexOf("\t") >= 0 || str.indexOf(",") >= 0) return dsv_to_sheet_str(str, opts);
		return aoa_to_sheet(prn_to_aoa_str(str, opts), opts);
	}

	function prn_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
S
SheetJS 已提交
5848
		var str = "", bytes = firstbyte(d, opts);
S
SheetJS 已提交
5849
		switch(opts.type) {
S
SheetJS 已提交
5850 5851 5852 5853 5854
			case 'base64': str = Base64.decode(d); break;
			case 'binary': str = d; break;
			case 'buffer': str = d.toString('binary'); break;
			case 'array': str = cc2str(d); break;
			default: throw new Error("Unrecognized type " + opts.type);
S
SheetJS 已提交
5855
		}
S
SheetJS 已提交
5856 5857
		if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str);
		return prn_to_sheet_str(str, opts);
S
SheetJS 已提交
5858
	}
S
SheetJS 已提交
5859

5860
	function prn_to_workbook(d/*:RawData*/, opts)/*:Workbook*/ { return sheet_to_workbook(prn_to_sheet(d, opts), opts); }
S
SheetJS 已提交
5861

S
TXT/PRN  
SheetJS 已提交
5862 5863 5864
	function sheet_to_prn(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
		var o/*:Array<string>*/ = [];
		var r = decode_range(ws['!ref']), cell/*:Cell*/;
S
SheetJS 已提交
5865
		var dense = Array.isArray(ws);
S
TXT/PRN  
SheetJS 已提交
5866 5867 5868 5869
		for(var R = r.s.r; R <= r.e.r; ++R) {
			var oo = [];
			for(var C = r.s.c; C <= r.e.c; ++C) {
				var coord = encode_cell({r:R,c:C});
S
SheetJS 已提交
5870 5871
				cell = dense ? (ws[R]||[])[C] : ws[coord];
				if(!cell || cell.v == null) { oo.push("          "); continue; }
S
TXT/PRN  
SheetJS 已提交
5872 5873 5874 5875 5876 5877 5878 5879 5880
				var w = (cell.w || (format_cell(cell), cell.w) || "").substr(0,10);
				while(w.length < 10) w += " ";
				oo.push(w + (C == 0 ? " " : ""));
			}
			o.push(oo.join(""));
		}
		return o.join("\n");
	}

S
SheetJS 已提交
5881 5882
	return {
		to_workbook: prn_to_workbook,
S
TXT/PRN  
SheetJS 已提交
5883 5884
		to_sheet: prn_to_sheet,
		from_sheet: sheet_to_prn
S
SheetJS 已提交
5885 5886 5887
	};
})();

5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900
/* Excel defaults to SYLK but warns if data is not valid */
function read_wb_ID(d, opts) {
	var o = opts || {}, OLD_WTF = !!o.WTF; o.WTF = true;
	try {
		var out = SYLK.to_workbook(d, o);
		o.WTF = OLD_WTF;
		return out;
	} catch(e) {
		o.WTF = OLD_WTF;
		if(!e.message.match(/SYLK bad record ID/) && OLD_WTF) throw e;
		return PRN.to_workbook(d, opts);
	}
}
S
SheetJS 已提交
5901

S
SheetJS 已提交
5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913
var WK_ = (function() {
	function lotushopper(data, cb/*:RecordHopperCB*/, opts/*:any*/) {
		if(!data) return;
		prep_blob(data, data.l || 0);
		var Enum = opts.Enum || WK1Enum;
		while(data.l < data.length) {
			var RT = data.read_shift(2);
			var R = Enum[RT] || Enum[0xFF];
			var length = data.read_shift(2);
			var tgt = data.l + length;
			var d = R.f(data, length, opts);
			data.l = tgt;
5914
			if(cb(d, R.n, RT)) return;
S
SheetJS 已提交
5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930
		}
	}

	function lotus_to_workbook(d/*:RawData*/, opts) {
		switch(opts.type) {
			case 'base64': return lotus_to_workbook_buf(s2a(Base64.decode(d)), opts);
			case 'binary': return lotus_to_workbook_buf(s2a(d), opts);
			case 'buffer':
			case 'array': return lotus_to_workbook_buf(d, opts);
		}
		throw "Unsupported type " + opts.type;
	}

	function lotus_to_workbook_buf(d,opts)/*:Workbook*/ {
		if(!d) return d;
		var o = opts || {};
5931
		if(DENSE != null && o.dense == null) o.dense = DENSE;
S
SheetJS 已提交
5932
		var s/*:Worksheet*/ = ((o.dense ? [] : {})/*:any*/), n = "Sheet1", sidx = 0;
S
SheetJS 已提交
5933 5934 5935 5936 5937 5938 5939 5940
		var sheets = {}, snames = [n];

		var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };

		if(d[2] == 0x02) o.Enum = WK1Enum;
		else if(d[2] == 0x1a) o.Enum = WK3Enum;
		else if(d[2] == 0x0e) { o.Enum = WK3Enum; o.qpro = true; d.l = 0; }
		else throw new Error("Unrecognized LOTUS BOF " + d[2]);
5941
		lotushopper(d, function(val, Rn, RT) {
S
SheetJS 已提交
5942 5943 5944 5945 5946 5947 5948
			if(d[2] == 0x02) switch(RT) {
				case 0x00:
					o.vers = val;
					if(val >= 0x1000) o.qpro = true;
					break;
				case 0x06: refguess = val; break; /* RANGE */
				case 0x0F: /* LABEL */
S
SheetJS 已提交
5949
					if(!o.qpro) val[1].v = val[1].v.substr(1);
S
SheetJS 已提交
5950 5951 5952 5953 5954
					/* falls through */
				case 0x0D: /* INTEGER */
				case 0x0E: /* NUMBER */
				case 0x10: /* FORMULA */
				case 0x33: /* STRING */
5955 5956 5957 5958 5959
					/* TODO: actual translation of the format code */
					if(RT == 0x0E && (val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) {
						val[1].z = o.dateNF || SSF._table[14];
						if(o.cellDates) { val[1].t = 'd'; val[1].v = numdate(val[1].v); }
					}
S
SheetJS 已提交
5960 5961 5962 5963
					if(o.dense) {
						if(!s[val[0].r]) s[val[0].r] = [];
						s[val[0].r][val[0].c] = val[1];
					} else s[encode_cell(val[0])] = val[1];
S
SheetJS 已提交
5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977
					break;
			} else switch(RT) {
				case 0x16: /* LABEL16 */
					val[1].v = val[1].v.substr(1);
					/* falls through */
				case 0x17: /* NUMBER17 */
				case 0x18: /* NUMBER18 */
				case 0x19: /* FORMULA19 */
				case 0x25: /* NUMBER25 */
				case 0x27: /* NUMBER27 */
				case 0x28: /* FORMULA28 */
					if(val[3] > sidx) {
						s["!ref"] = encode_range(refguess);
						sheets[n] = s;
S
SheetJS 已提交
5978
						s = (o.dense ? [] : {});
S
SheetJS 已提交
5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131
						refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
						sidx = val[3]; n = "Sheet" + (sidx + 1);
						snames.push(n);
					}
					s[encode_cell(val[0])] = val[1];
					if(refguess.e.c < val[0].c) refguess.e.c = val[0].c;
					if(refguess.e.r < val[0].r) refguess.e.r = val[0].r;
					break;
				default: break;
			}
		}, o);

		s["!ref"] = encode_range(refguess);
		sheets[n] = s;
		return { SheetNames: snames, Sheets:sheets };
	}

	function parse_RANGE(blob, length) {
		var o = {s:{c:0,r:0},e:{c:0,r:0}};
		o.s.c = blob.read_shift(2);
		o.s.r = blob.read_shift(2);
		o.e.c = blob.read_shift(2);
		o.e.r = blob.read_shift(2);
		if(o.s.c == 0xFFFF) o.s.c = o.e.c = o.s.r = o.e.r = 0;
		return o;
	}

	function parse_cell(blob, length, opts) {
		var o = [{c:0,r:0}, {t:'n',v:0}, 0];
		if(opts.qpro && opts.vers != 0x5120) {
			o[0].c = blob.read_shift(1);
			blob.l++;
			o[0].r = blob.read_shift(2);
			blob.l+=2;
		} else {
			o[2] = blob.read_shift(1);
			o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2);
		}
		return o;
	}

	function parse_LABEL(blob, length, opts) {
		var tgt = blob.l + length;
		var o = parse_cell(blob, length, opts);
		o[1].t = 's';
		if(opts.vers == 0x5120) {
			blob.l++;
			var len = blob.read_shift(1);
			o[1].v = blob.read_shift(len, 'utf8');
			return o;
		}
		if(opts.qpro) blob.l++;
		o[1].v = blob.read_shift(tgt - blob.l, 'cstr');
		return o;
	}

	function parse_INTEGER(blob, length, opts) {
		var o = parse_cell(blob, length, opts);
		o[1].v = blob.read_shift(2, 'i');
		return o;
	}

	function parse_NUMBER(blob, length, opts) {
		var o = parse_cell(blob, length, opts);
		o[1].v = blob.read_shift(8, 'f');
		return o;
	}

	function parse_FORMULA(blob, length, opts) {
		var tgt = blob.l + length;
		var o = parse_cell(blob, length, opts);
		/* TODO: formula */
		o[1].v = blob.read_shift(8, 'f');
		if(opts.qpro) blob.l = tgt;
		else {
			var flen = blob.read_shift(2);
			blob.l += flen;
		}
		return o;
	}

	function parse_cell_3(blob, length) {
		var o = [{c:0,r:0}, {t:'n',v:0}, 0];
		o[0].r = blob.read_shift(2); o[3] = blob[blob.l++]; o[0].c = blob[blob.l++];
		return o;
	}

	function parse_LABEL_16(blob, length) {
		var o = parse_cell_3(blob, length);
		o[1].t = 's';
		o[1].v = blob.read_shift(length - 4, 'cstr');
		return o;
	}

	function parse_NUMBER_18(blob, length) {
		var o = parse_cell_3(blob, length);
		o[1].v = blob.read_shift(2);
		var v = o[1].v >> 1;
		/* TODO: figure out all of the corner cases */
		if(o[1].v & 0x1) {
			switch(v & 0x07) {
				case 1: v = (v >> 3) * 500; break;
				case 2: v = (v >> 3) / 20; break;
				case 4: v = (v >> 3) / 2000; break;
				case 6: v = (v >> 3) / 16; break;
				case 7: v = (v >> 3) / 64; break;
				default: throw "unknown NUMBER_18 encoding " + (v & 0x07);
			}
		}
		o[1].v = v;
		return o;
	}

	function parse_NUMBER_17(blob, length) {
		var o = parse_cell_3(blob, length);
		var v1 = blob.read_shift(4);
		var v2 = blob.read_shift(4);
		var e = blob.read_shift(2);
		if(e == 0xFFFF) { o[1].v = 0; return o; }
		var s = e & 0x8000; e = (e&0x7FFF) - 16446;
		o[1].v = ((e > 0 ? (v2 << e) : (v2 >>> -e)) + (e > -32 ? (v1 << (e + 32)) : (v1 >>> -(e + 32))));
		return o;
	}

	function parse_FORMULA_19(blob, length) {
		var o = parse_NUMBER_17(blob, 14);
		blob.l += length - 14; /* TODO: formula */
		return o;
	}

	function parse_NUMBER_25(blob, length) {
		var o = parse_cell_3(blob, length);
		var v1 = blob.read_shift(4);
		o[1].v = v1 >> 6;
		return o;
	}

	function parse_NUMBER_27(blob, length) {
		var o = parse_cell_3(blob, length);
		var v1 = blob.read_shift(8,'f');
		o[1].v = v1;
		return o;
	}

	function parse_FORMULA_28(blob, length) {
		var o = parse_NUMBER_27(blob, 14);
		blob.l += length - 10; /* TODO: formula */
		return o;
	}

	var WK1Enum = {
		/*::[*/0x0000/*::]*/: { n:"BOF", f:parseuint16 },
		/*::[*/0x0001/*::]*/: { n:"EOF", f:parsenoop },
6132
		/*::[*/0x0002/*::]*/: { n:"CALCMODE", f:parsenoop },
S
SheetJS 已提交
6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228
		/*::[*/0x0003/*::]*/: { n:"CALCORDER", f:parsenoop },
		/*::[*/0x0004/*::]*/: { n:"SPLIT", f:parsenoop },
		/*::[*/0x0005/*::]*/: { n:"SYNC", f:parsenoop },
		/*::[*/0x0006/*::]*/: { n:"RANGE", f:parse_RANGE },
		/*::[*/0x0007/*::]*/: { n:"WINDOW1", f:parsenoop },
		/*::[*/0x0008/*::]*/: { n:"COLW1", f:parsenoop },
		/*::[*/0x0009/*::]*/: { n:"WINTWO", f:parsenoop },
		/*::[*/0x000A/*::]*/: { n:"COLW2", f:parsenoop },
		/*::[*/0x000B/*::]*/: { n:"NAME", f:parsenoop },
		/*::[*/0x000C/*::]*/: { n:"BLANK", f:parsenoop },
		/*::[*/0x000D/*::]*/: { n:"INTEGER", f:parse_INTEGER },
		/*::[*/0x000E/*::]*/: { n:"NUMBER", f:parse_NUMBER },
		/*::[*/0x000F/*::]*/: { n:"LABEL", f:parse_LABEL },
		/*::[*/0x0010/*::]*/: { n:"FORMULA", f:parse_FORMULA },
		/*::[*/0x0018/*::]*/: { n:"TABLE", f:parsenoop },
		/*::[*/0x0019/*::]*/: { n:"ORANGE", f:parsenoop },
		/*::[*/0x001A/*::]*/: { n:"PRANGE", f:parsenoop },
		/*::[*/0x001B/*::]*/: { n:"SRANGE", f:parsenoop },
		/*::[*/0x001C/*::]*/: { n:"FRANGE", f:parsenoop },
		/*::[*/0x001D/*::]*/: { n:"KRANGE1", f:parsenoop },
		/*::[*/0x0020/*::]*/: { n:"HRANGE", f:parsenoop },
		/*::[*/0x0023/*::]*/: { n:"KRANGE2", f:parsenoop },
		/*::[*/0x0024/*::]*/: { n:"PROTEC", f:parsenoop },
		/*::[*/0x0025/*::]*/: { n:"FOOTER", f:parsenoop },
		/*::[*/0x0026/*::]*/: { n:"HEADER", f:parsenoop },
		/*::[*/0x0027/*::]*/: { n:"SETUP", f:parsenoop },
		/*::[*/0x0028/*::]*/: { n:"MARGINS", f:parsenoop },
		/*::[*/0x0029/*::]*/: { n:"LABELFMT", f:parsenoop },
		/*::[*/0x002A/*::]*/: { n:"TITLES", f:parsenoop },
		/*::[*/0x002B/*::]*/: { n:"SHEETJS", f:parsenoop },
		/*::[*/0x002D/*::]*/: { n:"GRAPH", f:parsenoop },
		/*::[*/0x002E/*::]*/: { n:"NGRAPH", f:parsenoop },
		/*::[*/0x002F/*::]*/: { n:"CALCCOUNT", f:parsenoop },
		/*::[*/0x0030/*::]*/: { n:"UNFORMATTED", f:parsenoop },
		/*::[*/0x0031/*::]*/: { n:"CURSORW12", f:parsenoop },
		/*::[*/0x0032/*::]*/: { n:"WINDOW", f:parsenoop },
		/*::[*/0x0033/*::]*/: { n:"STRING", f:parse_LABEL },
		/*::[*/0x0037/*::]*/: { n:"PASSWORD", f:parsenoop },
		/*::[*/0x0038/*::]*/: { n:"LOCKED", f:parsenoop },
		/*::[*/0x003C/*::]*/: { n:"QUERY", f:parsenoop },
		/*::[*/0x003D/*::]*/: { n:"QUERYNAME", f:parsenoop },
		/*::[*/0x003E/*::]*/: { n:"PRINT", f:parsenoop },
		/*::[*/0x003F/*::]*/: { n:"PRINTNAME", f:parsenoop },
		/*::[*/0x0040/*::]*/: { n:"GRAPH2", f:parsenoop },
		/*::[*/0x0041/*::]*/: { n:"GRAPHNAME", f:parsenoop },
		/*::[*/0x0042/*::]*/: { n:"ZOOM", f:parsenoop },
		/*::[*/0x0043/*::]*/: { n:"SYMSPLIT", f:parsenoop },
		/*::[*/0x0044/*::]*/: { n:"NSROWS", f:parsenoop },
		/*::[*/0x0045/*::]*/: { n:"NSCOLS", f:parsenoop },
		/*::[*/0x0046/*::]*/: { n:"RULER", f:parsenoop },
		/*::[*/0x0047/*::]*/: { n:"NNAME", f:parsenoop },
		/*::[*/0x0048/*::]*/: { n:"ACOMM", f:parsenoop },
		/*::[*/0x0049/*::]*/: { n:"AMACRO", f:parsenoop },
		/*::[*/0x004A/*::]*/: { n:"PARSE", f:parsenoop },
		/*::[*/0x00FF/*::]*/: { n:"", f:parsenoop }
	};

	var WK3Enum = {
		/*::[*/0x0000/*::]*/: { n:"BOF", f:parsenoop },
		/*::[*/0x0001/*::]*/: { n:"EOF", f:parsenoop },
		/*::[*/0x0003/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x0004/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x0005/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x0006/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x0007/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x0009/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x000a/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x000b/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x000c/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x000e/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x000f/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x0010/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x0011/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x0012/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x0013/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x0015/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x0016/*::]*/: { n:"LABEL16", f:parse_LABEL_16},
		/*::[*/0x0017/*::]*/: { n:"NUMBER17", f:parse_NUMBER_17 },
		/*::[*/0x0018/*::]*/: { n:"NUMBER18", f:parse_NUMBER_18 },
		/*::[*/0x0019/*::]*/: { n:"FORMULA19", f:parse_FORMULA_19},
		/*::[*/0x001a/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x001b/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x001c/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x001d/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x001e/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x001f/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x0021/*::]*/: { n:"??", f:parsenoop },
		/*::[*/0x0025/*::]*/: { n:"NUMBER25", f:parse_NUMBER_25 },
		/*::[*/0x0027/*::]*/: { n:"NUMBER27", f:parse_NUMBER_27 },
		/*::[*/0x0028/*::]*/: { n:"FORMULA28", f:parse_FORMULA_28 },
		/*::[*/0x00FF/*::]*/: { n:"", f:parsenoop }
	};
	return {
		to_workbook: lotus_to_workbook
	};
})();
S
SheetJS 已提交
6229
/* 18.4.1 charset to codepage mapping */
S
SheetJS 已提交
6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251
var CS2CP = ({
	/*::[*/0/*::]*/:    1252, /* ANSI */
	/*::[*/1/*::]*/:   65001, /* DEFAULT */
	/*::[*/2/*::]*/:   65001, /* SYMBOL */
	/*::[*/77/*::]*/:  10000, /* MAC */
	/*::[*/128/*::]*/:   932, /* SHIFTJIS */
	/*::[*/129/*::]*/:   949, /* HANGUL */
	/*::[*/130/*::]*/:  1361, /* JOHAB */
	/*::[*/134/*::]*/:   936, /* GB2312 */
	/*::[*/136/*::]*/:   950, /* CHINESEBIG5 */
	/*::[*/161/*::]*/:  1253, /* GREEK */
	/*::[*/162/*::]*/:  1254, /* TURKISH */
	/*::[*/163/*::]*/:  1258, /* VIETNAMESE */
	/*::[*/177/*::]*/:  1255, /* HEBREW */
	/*::[*/178/*::]*/:  1256, /* ARABIC */
	/*::[*/186/*::]*/:  1257, /* BALTIC */
	/*::[*/204/*::]*/:  1251, /* RUSSIAN */
	/*::[*/222/*::]*/:   874, /* THAI */
	/*::[*/238/*::]*/:  1250, /* EASTEUROPE */
	/*::[*/255/*::]*/:  1252, /* OEM */
	/*::[*/69/*::]*/:   6969  /* MISC */
}/*:any*/);
S
SheetJS 已提交
6252 6253 6254

/* Parse a list of <r> tags */
var parse_rs = (function parse_rs_factory() {
S
SheetJS 已提交
6255
	var tregex = matchtag("t"), rpregex = matchtag("rPr"), rregex = /<(?:\w+:)?r>/g, rend = /<\/(?:\w+:)?r>/, nlregex = /\r\n/g;
S
SheetJS 已提交
6256 6257
	/* 18.4.7 rPr CT_RPrElt */
	var parse_rpr = function parse_rpr(rpr, intro, outro) {
S
SheetJS 已提交
6258
		var font = {}, cp = 65001, align = "";
S
SheetJS 已提交
6259 6260 6261
		var m = rpr.match(tagregex), i = 0;
		if(m) for(;i!=m.length; ++i) {
			var y = parsexmltag(m[i]);
S
SheetJS 已提交
6262
			switch(y[0].replace(/\w*:/g,"")) {
S
SheetJS 已提交
6263 6264 6265 6266 6267 6268 6269 6270 6271
				/* 18.8.12 condense CT_BooleanProperty */
				/* ** not required . */
				case '<condense': break;
				/* 18.8.17 extend CT_BooleanProperty */
				/* ** not required . */
				case '<extend': break;
				/* 18.8.36 shadow CT_BooleanProperty */
				/* ** not required . */
				case '<shadow':
S
SheetJS 已提交
6272
					if(!y.val) break;
S
SheetJS 已提交
6273
					/* falls through */
6274
				case '<shadow>':
S
SheetJS 已提交
6275 6276
				case '<shadow/>': font.shadow = 1; break;
				case '</shadow>': break;
S
SheetJS 已提交
6277 6278 6279 6280 6281 6282 6283 6284 6285

				/* 18.4.1 charset CT_IntProperty TODO */
				case '<charset':
					if(y.val == '1') break;
					cp = CS2CP[parseInt(y.val, 10)];
					break;

				/* 18.4.2 outline CT_BooleanProperty TODO */
				case '<outline':
S
SheetJS 已提交
6286
					if(!y.val) break;
S
SheetJS 已提交
6287
					/* falls through */
6288
				case '<outline>':
S
SheetJS 已提交
6289 6290
				case '<outline/>': font.outline = 1; break;
				case '</outline>': break;
S
SheetJS 已提交
6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301

				/* 18.4.5 rFont CT_FontName */
				case '<rFont': font.name = y.val; break;

				/* 18.4.11 sz CT_FontSize */
				case '<sz': font.sz = y.val; break;

				/* 18.4.10 strike CT_BooleanProperty */
				case '<strike':
					if(!y.val) break;
					/* falls through */
6302
				case '<strike>':
S
SheetJS 已提交
6303 6304 6305 6306 6307
				case '<strike/>': font.strike = 1; break;
				case '</strike>': break;

				/* 18.4.13 u CT_UnderlineProperty */
				case '<u':
S
SheetJS 已提交
6308 6309 6310 6311 6312 6313
					if(!y.val) break;
					switch(y.val) {
						case 'double': font.uval = "double"; break;
						case 'singleAccounting': font.uval = "single-accounting"; break;
						case 'doubleAccounting': font.uval = "double-accounting"; break;
					}
S
SheetJS 已提交
6314
					/* falls through */
6315
				case '<u>':
S
SheetJS 已提交
6316 6317 6318 6319 6320
				case '<u/>': font.u = 1; break;
				case '</u>': break;

				/* 18.8.2 b */
				case '<b':
S
SheetJS 已提交
6321
					if(y.val == '0') break;
S
SheetJS 已提交
6322
					/* falls through */
6323
				case '<b>':
S
SheetJS 已提交
6324 6325 6326 6327 6328
				case '<b/>': font.b = 1; break;
				case '</b>': break;

				/* 18.8.26 i */
				case '<i':
S
SheetJS 已提交
6329
					if(y.val == '0') break;
S
SheetJS 已提交
6330
					/* falls through */
6331
				case '<i>':
S
SheetJS 已提交
6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343
				case '<i/>': font.i = 1; break;
				case '</i>': break;

				/* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */
				case '<color':
					if(y.rgb) font.color = y.rgb.substr(2,6);
					break;

				/* 18.8.18 family ST_FontFamily */
				case '<family': font.family = y.val; break;

				/* 18.4.14 vertAlign CT_VerticalAlignFontProperty TODO */
S
SheetJS 已提交
6344
				case '<vertAlign': align = y.val; break;
S
SheetJS 已提交
6345 6346 6347 6348 6349 6350 6351 6352 6353

				/* 18.8.35 scheme CT_FontScheme TODO */
				case '<scheme': break;

				default:
					if(y[0].charCodeAt(1) !== 47) throw 'Unrecognized rich format ' + y[0];
			}
		}
		var style = [];
S
SheetJS 已提交
6354 6355 6356 6357 6358 6359

		if(font.u) style.push("text-decoration: underline;");
		if(font.uval) style.push("text-underline-style:" + font.uval + ";");
		if(font.sz) style.push("font-size:" + font.sz + ";");
		if(font.outline) style.push("text-effect: outline;");
		if(font.shadow) style.push("text-shadow: auto;");
S
SheetJS 已提交
6360
		intro.push('<span style="' + style.join("") + '">');
S
SheetJS 已提交
6361 6362 6363 6364 6365 6366 6367 6368 6369

		if(font.b) { intro.push("<b>"); outro.push("</b>"); }
		if(font.i) { intro.push("<i>"); outro.push("</i>"); }
		if(font.strike) { intro.push("<s>"); outro.push("</s>"); }

		if(align == "superscript") align = "sup";
		else if(align == "subscript") align = "sub";
		if(align != "") { intro.push("<" + align + ">"); outro.push("</" + align + ">"); }

S
SheetJS 已提交
6370 6371 6372 6373 6374 6375 6376 6377 6378
		outro.push("</span>");
		return cp;
	};

	/* 18.4.4 r CT_RElt */
	function parse_r(r) {
		var terms = [[],"",[]];
		/* 18.4.12 t ST_Xstring */
		var t = r.match(tregex), cp = 65001;
S
SheetJS 已提交
6379
		if(!isval(t)/*:: || !t*/) return "";
S
SheetJS 已提交
6380 6381 6382
		terms[1] = t[1];

		var rpr = r.match(rpregex);
S
SheetJS 已提交
6383
		if(isval(rpr)/*:: && rpr*/) cp = parse_rpr(rpr[1], terms[0], terms[2]);
S
SheetJS 已提交
6384 6385 6386 6387 6388 6389 6390 6391 6392

		return terms[0].join("") + terms[1].replace(nlregex,'<br/>') + terms[2].join("");
	}
	return function parse_rs(rs) {
		return rs.replace(rregex,"").split(rend).map(parse_r).join("");
	};
})();

/* 18.4.8 si CT_Rst */
S
SheetJS 已提交
6393
var sitregex = /<(?:\w+:)?t[^>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r>/;
6394
var sirphregex = /<(?:\w+:)?rPh.*?>([\s\S]*?)<\/(?:\w+:)?rPh>/g;
S
SheetJS 已提交
6395 6396 6397 6398 6399 6400
function parse_si(x, opts) {
	var html = opts ? opts.cellHTML : true;
	var z = {};
	if(!x) return null;
	var y;
	/* 18.4.12 t ST_Xstring (Plaintext String) */
S
SheetJS 已提交
6401 6402
	// TODO: is whitespace actually valid here?
	if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) {
S
SheetJS 已提交
6403
		z.t = utf8read(unescapexml(x.substr(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]));
S
SheetJS 已提交
6404
		z.r = utf8read(x);
6405
		if(html) z.h = escapehtml(z.t);
S
SheetJS 已提交
6406 6407 6408
	}
	/* 18.4.4 r CT_RElt (Rich Text Run) */
	else if((y = x.match(sirregex))) {
S
SheetJS 已提交
6409
		z.r = utf8read(x);
6410
		z.t = utf8read(unescapexml((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")));
S
SheetJS 已提交
6411
		if(html) z.h = parse_rs(z.r);
S
SheetJS 已提交
6412 6413 6414 6415 6416 6417 6418
	}
	/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
	/* 18.4.6 rPh CT_PhoneticRun (TODO: needed for Asian support) */
	return z;
}

/* 18.4 Shared String Table */
S
SheetJS 已提交
6419 6420 6421 6422 6423 6424
var sstr0 = /<(?:\w+:)?sst([^>]*)>([\s\S]*)<\/(?:\w+:)?sst>/;
var sstr1 = /<(?:\w+:)?(?:si|sstItem)>/g;
var sstr2 = /<\/(?:\w+:)?(?:si|sstItem)>/;
function parse_sst_xml(data/*:string*/, opts)/*:SST*/ {
	var s/*:SST*/ = ([]/*:any*/), ss = "";
	if(!data) return s;
S
SheetJS 已提交
6425 6426
	/* 18.4.9 sst CT_Sst */
	var sst = data.match(sstr0);
S
SheetJS 已提交
6427
	if(isval(sst)/*:: && sst*/) {
S
SheetJS 已提交
6428 6429
		ss = sst[2].replace(sstr1,"").split(sstr2);
		for(var i = 0; i != ss.length; ++i) {
S
SheetJS 已提交
6430
			var o = parse_si(ss[i].trim(), opts);
S
SheetJS 已提交
6431 6432 6433 6434 6435 6436 6437 6438 6439
			if(o != null) s[s.length] = o;
		}
		sst = parsexmltag(sst[1]); s.Count = sst.count; s.Unique = sst.uniqueCount;
	}
	return s;
}

RELS.SST = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
var straywsregex = /^\s|\s$|[\t\n\r]/;
S
SheetJS 已提交
6440
function write_sst_xml(sst/*:SST*/, opts)/*:string*/ {
S
SheetJS 已提交
6441 6442 6443 6444 6445 6446 6447 6448
	if(!opts.bookSST) return "";
	var o = [XML_HEADER];
	o[o.length] = (writextag('sst', null, {
		xmlns: XMLNS.main[0],
		count: sst.Count,
		uniqueCount: sst.Unique
	}));
	for(var i = 0; i != sst.length; ++i) { if(sst[i] == null) continue;
S
SheetJS 已提交
6449
		var s/*:XLString*/ = sst[i];
S
SheetJS 已提交
6450 6451 6452 6453
		var sitag = "<si>";
		if(s.r) sitag += s.r;
		else {
			sitag += "<t";
6454
			if(!s.t) s.t = "";
S
SheetJS 已提交
6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469
			if(s.t.match(straywsregex)) sitag += ' xml:space="preserve"';
			sitag += ">" + escapexml(s.t) + "</t>";
		}
		sitag += "</si>";
		o[o.length] = (sitag);
	}
	if(o.length>2){ o[o.length] = ('</sst>'); o[1]=o[1].replace("/>",">"); }
	return o.join("");
}
/* [MS-XLSB] 2.4.219 BrtBeginSst */
function parse_BrtBeginSst(data, length) {
	return [data.read_shift(4), data.read_shift(4)];
}

/* [MS-XLSB] 2.1.7.45 Shared Strings */
S
SheetJS 已提交
6470 6471
function parse_sst_bin(data, opts)/*:SST*/ {
	var s/*:SST*/ = ([]/*:any*/);
S
SheetJS 已提交
6472
	var pass = false;
6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487
	recordhopper(data, function hopper_sst(val, R_n, RT) {
		switch(RT) {
			case 0x009F: /* 'BrtBeginSst' */
				s.Count = val[0]; s.Unique = val[1]; break;
			case 0x0013: /* 'BrtSSTItem' */
				s.push(val); break;
			case 0x00A0: /* 'BrtEndSst' */
				return true;

			case 0x0023: /* 'BrtFRTBegin' */
				pass = true; break;
			case 0x0024: /* 'BrtFRTEnd' */
				pass = false; break;

			default:
S
SheetJS 已提交
6488 6489
				if(R_n.indexOf("Begin") > 0){/* empty */}
				else if(R_n.indexOf("End") > 0){/* empty */}
6490
				if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
S
SheetJS 已提交
6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508
		}
	});
	return s;
}

function write_BrtBeginSst(sst, o) {
	if(!o) o = new_buf(8);
	o.write_shift(4, sst.Count);
	o.write_shift(4, sst.Unique);
	return o;
}

var write_BrtSSTItem = write_RichStr;

function write_sst_bin(sst, opts) {
	var ba = buf_array();
	write_record(ba, "BrtBeginSst", write_BrtBeginSst(sst));
	for(var i = 0; i < sst.length; ++i) write_record(ba, "BrtSSTItem", write_BrtSSTItem(sst[i]));
S
SheetJS 已提交
6509
	/* FRTSST */
S
SheetJS 已提交
6510 6511 6512
	write_record(ba, "BrtEndSst");
	return ba.end();
}
S
SheetJS 已提交
6513 6514 6515 6516 6517 6518
function _JS2ANSI(str/*:string*/)/*:Array<number>*/ {
	if(typeof cptable !== 'undefined') return cptable.utils.encode(1252, str);
	var o = [], oo = str.split("");
	for(var i = 0; i < oo.length; ++i) o[i] = oo[i].charCodeAt(0);
	return o;
}
S
SheetJS 已提交
6519 6520

/* [MS-OFFCRYPTO] 2.1.4 Version */
S
SheetJS 已提交
6521 6522
function parse_CRYPTOVersion(blob, length/*:?number*/) {
	var o/*:any*/ = {};
S
SheetJS 已提交
6523 6524
	o.Major = blob.read_shift(2);
	o.Minor = blob.read_shift(2);
S
SheetJS 已提交
6525 6526
	/*:: if(length == null) return o; */
	if(length >= 4) blob.l += length - 4;
S
SheetJS 已提交
6527 6528
	return o;
}
S
SheetJS 已提交
6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578

/* [MS-OFFCRYPTO] 2.1.5 DataSpaceVersionInfo */
function parse_DataSpaceVersionInfo(blob, length) {
	var o = {};
	o.id = blob.read_shift(0, 'lpp4');
	o.R = parse_CRYPTOVersion(blob, 4);
	o.U = parse_CRYPTOVersion(blob, 4);
	o.W = parse_CRYPTOVersion(blob, 4);
	return o;
}

/* [MS-OFFCRYPTO] 2.1.6.1 DataSpaceMapEntry Structure */
function parse_DataSpaceMapEntry(blob) {
	var len = blob.read_shift(4);
	var end = blob.l + len - 4;
	var o = {};
	var cnt = blob.read_shift(4);
	var comps = [];
	while(cnt-- > 0) {
		/* [MS-OFFCRYPTO] 2.1.6.2 DataSpaceReferenceComponent Structure */
		var rc = {};
		rc.t = blob.read_shift(4);
		rc.v = blob.read_shift(0, 'lpp4');
		comps.push(rc);
	}
	o.name = blob.read_shift(0, 'lpp4');
	o.comps = comps;
	return o;
}

/* [MS-OFFCRYPTO] 2.1.6 DataSpaceMap */
function parse_DataSpaceMap(blob, length) {
	var o = [];
	blob.l += 4; // must be 0x8
	var cnt = blob.read_shift(4);
	while(cnt-- > 0) o.push(parse_DataSpaceMapEntry(blob));
	return o;
}

/* [MS-OFFCRYPTO] 2.1.7 DataSpaceDefinition */
function parse_DataSpaceDefinition(blob, length) {
	var o = [];
	blob.l += 4; // must be 0x8
	var cnt = blob.read_shift(4);
	while(cnt-- > 0) o.push(blob.read_shift(0, 'lpp4'));
	return o;
}

/* [MS-OFFCRYPTO] 2.1.8 DataSpaceDefinition */
function parse_TransformInfoHeader(blob, length) {
S
SheetJS 已提交
6579
	var o = {};
S
SheetJS 已提交
6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590
	var len = blob.read_shift(4);
	var tgt = blob.l + len - 4;
	blob.l += 4; // must be 0x1
	o.id = blob.read_shift(0, 'lpp4');
	// tgt == len
	o.name = blob.read_shift(0, 'lpp4');
	o.R = parse_CRYPTOVersion(blob, 4);
	o.U = parse_CRYPTOVersion(blob, 4);
	o.W = parse_CRYPTOVersion(blob, 4);
	return o;
}
S
SheetJS 已提交
6591

S
SheetJS 已提交
6592 6593 6594 6595 6596 6597 6598 6599 6600 6601
function parse_Primary(blob, length) {
	/* [MS-OFFCRYPTO] 2.2.6 IRMDSTransformInfo */
	var hdr = parse_TransformInfoHeader(blob);
	/* [MS-OFFCRYPTO] 2.1.9 EncryptionTransformInfo */
	hdr.ename = blob.read_shift(0, '8lpp4');
	hdr.blksz = blob.read_shift(4);
	hdr.cmode = blob.read_shift(4);
	if(blob.read_shift(4) != 0x04) throw new Error("Bad !Primary record");
	return hdr;
}
S
SheetJS 已提交
6602

S
SheetJS 已提交
6603 6604 6605 6606 6607 6608
/* [MS-OFFCRYPTO] 2.3.2 Encryption Header */
function parse_EncryptionHeader(blob, length/*:number*/) {
	var tgt = blob.l + length;
	var o = {};
	o.Flags = (blob.read_shift(4) & 0x3F);
	blob.l += 4;
S
SheetJS 已提交
6609
	o.AlgID = blob.read_shift(4);
S
SheetJS 已提交
6610
	var valid = false;
S
SheetJS 已提交
6611
	switch(o.AlgID) {
S
SheetJS 已提交
6612 6613 6614
		case 0x660E: case 0x660F: case 0x6610: valid = (o.Flags == 0x24); break;
		case 0x6801: valid = (o.Flags == 0x04); break;
		case 0: valid = (o.Flags == 0x10 || o.Flags == 0x04 || o.Flags == 0x24); break;
S
SheetJS 已提交
6615 6616
		default: throw 'Unrecognized encryption algorithm: ' + o.AlgID;
	}
S
SheetJS 已提交
6617 6618 6619 6620 6621 6622 6623
	if(!valid) throw new Error("Encryption Flags/AlgID mismatch");
	o.AlgIDHash = blob.read_shift(4);
	o.KeySize = blob.read_shift(4);
	o.ProviderType = blob.read_shift(4);
	blob.l += 8;
	o.CSPName = blob.read_shift((tgt-blob.l)>>1, 'utf16le').slice(0,-1);
	blob.l = tgt;
S
SheetJS 已提交
6624 6625 6626 6627
	return o;
}

/* [MS-OFFCRYPTO] 2.3.3 Encryption Verifier */
S
SheetJS 已提交
6628
function parse_EncryptionVerifier(blob, length/*:number*/) {
S
SheetJS 已提交
6629 6630 6631 6632 6633 6634 6635 6636 6637 6638
	var o = {};
	blob.l += 4; // SaltSize must be 0x10
	o.Salt = blob.slice(blob.l, blob.l+16); blob.l += 16;
	o.Verifier = blob.slice(blob.l, blob.l+16); blob.l += 16;
	var sz = blob.read_shift(4);
	o.VerifierHash = blob.slice(blob.l, blob.l + sz); blob.l += sz;
	return o;
}

/* [MS-OFFCRYPTO] 2.3.4.* EncryptionInfo Stream */
S
SheetJS 已提交
6639
function parse_EncryptionInfo(blob, length/*:?number*/) {
S
SheetJS 已提交
6640 6641 6642 6643 6644 6645 6646
	var vers = parse_CRYPTOVersion(blob);
	switch(vers.Minor) {
		case 0x02: return parse_EncInfoStd(blob, vers);
		case 0x03: return parse_EncInfoExt(blob, vers);
		case 0x04: return parse_EncInfoAgl(blob, vers);
	}
	throw new Error("ECMA-376 Encryped file unrecognized Version: " + vers.Minor);
S
SheetJS 已提交
6647
}
S
SheetJS 已提交
6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666

/* [MS-OFFCRYPTO] 2.3.4.5  EncryptionInfo Stream (Standard Encryption) */
function parse_EncInfoStd(blob, vers) {
	var flags = blob.read_shift(4);
	if((flags & 0x3F) != 0x24) throw new Error("EncryptionInfo mismatch");
	var sz = blob.read_shift(4);
	var tgt = blob.l + sz;
	var hdr = parse_EncryptionHeader(blob, sz);
	var verifier = parse_EncryptionVerifier(blob, blob.length - blob.l);
	return { t:"Std", h:hdr, v:verifier };
}
/* [MS-OFFCRYPTO] 2.3.4.6  EncryptionInfo Stream (Extensible Encryption) */
function parse_EncInfoExt(blob, vers) { throw new Error("File is password-protected: ECMA-376 Extensible"); }
/* [MS-OFFCRYPTO] 2.3.4.10 EncryptionInfo Stream (Agile Encryption) */
function parse_EncInfoAgl(blob, vers) { throw new Error("File is password-protected: ECMA-376 Agile"); }




S
SheetJS 已提交
6667
/* [MS-OFFCRYPTO] 2.3.5.1 RC4 CryptoAPI Encryption Header */
S
SheetJS 已提交
6668
function parse_RC4CryptoHeader(blob, length/*:number*/) {
S
SheetJS 已提交
6669
	var o = {};
S
SheetJS 已提交
6670
	var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4); length -= 4;
S
SheetJS 已提交
6671 6672
	if(vers.Minor != 2) throw new Error('unrecognized minor version code: ' + vers.Minor);
	if(vers.Major > 4 || vers.Major < 2) throw new Error('unrecognized major version code: ' + vers.Major);
S
SheetJS 已提交
6673 6674 6675 6676 6677 6678 6679
	o.Flags = blob.read_shift(4); length -= 4;
	var sz = blob.read_shift(4); length -= 4;
	o.EncryptionHeader = parse_EncryptionHeader(blob, sz); length -= sz;
	o.EncryptionVerifier = parse_EncryptionVerifier(blob, length);
	return o;
}
/* [MS-OFFCRYPTO] 2.3.6.1 RC4 Encryption Header */
S
SheetJS 已提交
6680
function parse_RC4Header(blob, length/*:number*/) {
S
SheetJS 已提交
6681
	var o = {};
S
SheetJS 已提交
6682
	var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4); length -= 4;
S
SheetJS 已提交
6683 6684 6685 6686 6687 6688 6689 6690
	if(vers.Major != 1 || vers.Minor != 1) throw 'unrecognized version code ' + vers.Major + ' : ' + vers.Minor;
	o.Salt = blob.read_shift(16);
	o.EncryptedVerifier = blob.read_shift(16);
	o.EncryptedVerifierHash = blob.read_shift(16);
	return o;
}

/* [MS-OFFCRYPTO] 2.3.7.1 Binary Document Password Verifier Derivation */
S
SheetJS 已提交
6691
function crypto_CreatePasswordVerifier_Method1(Password/*:string*/) {
S
SheetJS 已提交
6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727
	var Verifier = 0x0000, PasswordArray;
	var PasswordDecoded = _JS2ANSI(Password);
	var len = PasswordDecoded.length + 1, i, PasswordByte;
	var Intermediate1, Intermediate2, Intermediate3;
	PasswordArray = new_raw_buf(len);
	PasswordArray[0] = PasswordDecoded.length;
	for(i = 1; i != len; ++i) PasswordArray[i] = PasswordDecoded[i-1];
	for(i = len-1; i >= 0; --i) {
		PasswordByte = PasswordArray[i];
		Intermediate1 = ((Verifier & 0x4000) === 0x0000) ? 0 : 1;
		Intermediate2 = (Verifier << 1) & 0x7FFF;
		Intermediate3 = Intermediate1 | Intermediate2;
		Verifier = Intermediate3 ^ PasswordByte;
	}
	return Verifier ^ 0xCE4B;
}

/* [MS-OFFCRYPTO] 2.3.7.2 Binary Document XOR Array Initialization */
var crypto_CreateXorArray_Method1 = (function() {
	var PadArray = [0xBB, 0xFF, 0xFF, 0xBA, 0xFF, 0xFF, 0xB9, 0x80, 0x00, 0xBE, 0x0F, 0x00, 0xBF, 0x0F, 0x00];
	var InitialCode = [0xE1F0, 0x1D0F, 0xCC9C, 0x84C0, 0x110C, 0x0E10, 0xF1CE, 0x313E, 0x1872, 0xE139, 0xD40F, 0x84F9, 0x280C, 0xA96A, 0x4EC3];
	var XorMatrix = [0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09, 0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF, 0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0, 0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40, 0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5, 0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A, 0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9, 0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0, 0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC, 0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10, 0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168, 0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C, 0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD, 0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC, 0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4];
	var Ror = function(Byte) { return ((Byte/2) | (Byte*128)) & 0xFF; };
	var XorRor = function(byte1, byte2) { return Ror(byte1 ^ byte2); };
	var CreateXorKey_Method1 = function(Password) {
		var XorKey = InitialCode[Password.length - 1];
		var CurrentElement = 0x68;
		for(var i = Password.length-1; i >= 0; --i) {
			var Char = Password[i];
			for(var j = 0; j != 7; ++j) {
				if(Char & 0x40) XorKey ^= XorMatrix[CurrentElement];
				Char *= 2; --CurrentElement;
			}
		}
		return XorKey;
	};
S
SheetJS 已提交
6728
	return function(password/*:string*/) {
S
SheetJS 已提交
6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767
		var Password = _JS2ANSI(password);
		var XorKey = CreateXorKey_Method1(Password);
		var Index = Password.length;
		var ObfuscationArray = new_raw_buf(16);
		for(var i = 0; i != 16; ++i) ObfuscationArray[i] = 0x00;
		var Temp, PasswordLastChar, PadIndex;
		if((Index & 1) === 1) {
			Temp = XorKey >> 8;
			ObfuscationArray[Index] = XorRor(PadArray[0], Temp);
			--Index;
			Temp = XorKey & 0xFF;
			PasswordLastChar = Password[Password.length - 1];
			ObfuscationArray[Index] = XorRor(PasswordLastChar, Temp);
		}
		while(Index > 0) {
			--Index;
			Temp = XorKey >> 8;
			ObfuscationArray[Index] = XorRor(Password[Index], Temp);
			--Index;
			Temp = XorKey & 0xFF;
			ObfuscationArray[Index] = XorRor(Password[Index], Temp);
		}
		Index = 15;
		PadIndex = 15 - Password.length;
		while(PadIndex > 0) {
			Temp = XorKey >> 8;
			ObfuscationArray[Index] = XorRor(PadArray[PadIndex], Temp);
			--Index;
			--PadIndex;
			Temp = XorKey & 0xFF;
			ObfuscationArray[Index] = XorRor(Password[Index], Temp);
			--Index;
			--PadIndex;
		}
		return ObfuscationArray;
	};
})();

/* [MS-OFFCRYPTO] 2.3.7.3 Binary Document XOR Data Transformation Method 1 */
S
SheetJS 已提交
6768
var crypto_DecryptData_Method1 = function(password/*:string*/, Data, XorArrayIndex, XorArray, O) {
S
SheetJS 已提交
6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782
	/* If XorArray is set, use it; if O is not set, make changes in-place */
	if(!O) O = Data;
	if(!XorArray) XorArray = crypto_CreateXorArray_Method1(password);
	var Index, Value;
	for(Index = 0; Index != Data.length; ++Index) {
		Value = Data[Index];
		Value ^= XorArray[XorArrayIndex];
		Value = ((Value>>5) | (Value<<3)) & 0xFF;
		O[Index] = Value;
		++XorArrayIndex;
	}
	return [O, XorArrayIndex, XorArray];
};

S
SheetJS 已提交
6783
var crypto_MakeXorDecryptor = function(password/*:string*/) {
S
SheetJS 已提交
6784 6785
	var XorArrayIndex = 0, XorArray = crypto_CreateXorArray_Method1(password);
	return function(Data) {
S
SheetJS 已提交
6786
		var O = crypto_DecryptData_Method1("", Data, XorArrayIndex, XorArray);
S
SheetJS 已提交
6787 6788 6789 6790 6791 6792 6793
		XorArrayIndex = O[1];
		return O[0];
	};
};

/* 2.5.343 */
function parse_XORObfuscation(blob, length, opts, out) {
S
SheetJS 已提交
6794
	var o = ({ key: parseuint16(blob), verificationBytes: parseuint16(blob) }/*:any*/);
S
SheetJS 已提交
6795 6796 6797 6798 6799 6800 6801
	if(opts.password) o.verifier = crypto_CreatePasswordVerifier_Method1(opts.password);
	out.valid = o.verificationBytes === o.verifier;
	if(out.valid) out.insitu_decrypt = crypto_MakeXorDecryptor(opts.password);
	return o;
}

/* 2.4.117 */
S
SheetJS 已提交
6802
function parse_FilePassHeader(blob, length/*:number*/, oo) {
S
SheetJS 已提交
6803 6804 6805 6806 6807
	var o = oo || {}; o.Info = blob.read_shift(2); blob.l -= 2;
	if(o.Info === 1) o.Data = parse_RC4Header(blob, length);
	else o.Data = parse_RC4CryptoHeader(blob, length);
	return o;
}
S
SheetJS 已提交
6808
function parse_FilePass(blob, length/*:number*/, opts) {
S
SheetJS 已提交
6809
	var o = ({ Type: opts.biff >= 8 ? blob.read_shift(2) : 0 }/*:any*/); /* wEncryptionType */
S
SheetJS 已提交
6810 6811 6812 6813 6814 6815
	if(o.Type) parse_FilePassHeader(blob, length-2, o);
	else parse_XORObfuscation(blob, length-2, opts, o);
	return o;
}


S
SheetJS 已提交
6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839
var RTF = (function() {
	function rtf_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
		switch(opts.type) {
			case 'base64': return rtf_to_sheet_str(Base64.decode(d), opts);
			case 'binary': return rtf_to_sheet_str(d, opts);
			case 'buffer': return rtf_to_sheet_str(d.toString('binary'), opts);
			case 'array':  return rtf_to_sheet_str(cc2str(d), opts);
		}
		throw new Error("Unrecognized type " + opts.type);
	}

	function rtf_to_sheet_str(str/*:string*/, opts)/*:Worksheet*/ {
		throw new Error("Unsupported RTF");
	}

	function rtf_to_workbook(d/*:RawData*/, opts)/*:Workbook*/ { return sheet_to_workbook(rtf_to_sheet(d, opts), opts); }
	function sheet_to_rtf() { throw new Error("Unsupported"); }

	return {
		to_workbook: rtf_to_workbook,
		to_sheet: rtf_to_sheet,
		from_sheet: sheet_to_rtf
	};
})();
S
SheetJS 已提交
6840 6841
function hex2RGB(h) {
	var o = h.substr(h[0]==="#"?1:0,6);
S
SheetJS 已提交
6842
	return [parseInt(o.substr(0,2),16),parseInt(o.substr(2,2),16),parseInt(o.substr(4,2),16)];
S
SheetJS 已提交
6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891
}
function rgb2Hex(rgb) {
	for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);
	return o.toString(16).toUpperCase().substr(1);
}

function rgb2HSL(rgb) {
	var R = rgb[0]/255, G = rgb[1]/255, B=rgb[2]/255;
	var M = Math.max(R, G, B), m = Math.min(R, G, B), C = M - m;
	if(C === 0) return [0, 0, R];

	var H6 = 0, S = 0, L2 = (M + m);
	S = C / (L2 > 1 ? 2 - L2 : L2);
	switch(M){
		case R: H6 = ((G - B) / C + 6)%6; break;
		case G: H6 = ((B - R) / C + 2); break;
		case B: H6 = ((R - G) / C + 4); break;
	}
	return [H6 / 6, S, L2 / 2];
}

function hsl2RGB(hsl){
	var H = hsl[0], S = hsl[1], L = hsl[2];
	var C = S * 2 * (L < 0.5 ? L : 1 - L), m = L - C/2;
	var rgb = [m,m,m], h6 = 6*H;

	var X;
	if(S !== 0) switch(h6|0) {
		case 0: case 6: X = C * h6; rgb[0] += C; rgb[1] += X; break;
		case 1: X = C * (2 - h6);   rgb[0] += X; rgb[1] += C; break;
		case 2: X = C * (h6 - 2);   rgb[1] += C; rgb[2] += X; break;
		case 3: X = C * (4 - h6);   rgb[1] += X; rgb[2] += C; break;
		case 4: X = C * (h6 - 4);   rgb[2] += C; rgb[0] += X; break;
		case 5: X = C * (6 - h6);   rgb[2] += X; rgb[0] += C; break;
	}
	for(var i = 0; i != 3; ++i) rgb[i] = Math.round(rgb[i]*255);
	return rgb;
}

/* 18.8.3 bgColor tint algorithm */
function rgb_tint(hex, tint) {
	if(tint === 0) return hex;
	var hsl = rgb2HSL(hex2RGB(hex));
	if (tint < 0) hsl[2] = hsl[2] * (1 + tint);
	else hsl[2] = 1 - (1 - hsl[2]) * (1 - tint);
	return rgb2Hex(hsl2RGB(hsl));
}

/* 18.3.1.13 width calculations */
S
SheetJS 已提交
6892
/* [MS-OI29500] 2.1.595 Column Width & Formatting */
S
SheetJS 已提交
6893
var DEF_MDW = 6, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
S
SheetJS 已提交
6894 6895 6896 6897 6898
function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); }
function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; }
function char2width(chr) { return (Math.round((chr * MDW + 5)/MDW*256))/256; }
function px2char_(px) { return (((px - 5)/MDW * 100 + 0.5))/100; }
function char2width_(chr) { return (((chr * MDW + 5)/MDW*256))/256; }
S
SheetJS 已提交
6899
function cycle_width(collw) { return char2width(px2char(width2px(collw))); }
S
SheetJS 已提交
6900 6901
/* XLSX/XLSB/XLS specify width in units of MDW */
function find_mdw_colw(collw) {
S
SheetJS 已提交
6902 6903
	var delta = Math.abs(collw - cycle_width(collw)), _MDW = MDW;
	if(delta > 0.005) for(MDW=MIN_MDW; MDW<MAX_MDW; ++MDW) if(Math.abs(collw - cycle_width(collw)) <= delta) { delta = Math.abs(collw - cycle_width(collw)); _MDW = MDW; }
S
SheetJS 已提交
6904 6905 6906 6907 6908 6909 6910 6911 6912 6913
	MDW = _MDW;
}
/* XLML specifies width in terms of pixels */
function find_mdw_wpx(wpx) {
	var delta = Infinity, guess = 0, _MDW = MIN_MDW;
	for(MDW=MIN_MDW; MDW<MAX_MDW; ++MDW) {
		guess = char2width_(px2char_(wpx))*256;
		guess = (guess) % 1;
		if(guess > 0.5) guess--;
		if(Math.abs(guess) < delta) { delta = Math.abs(guess); _MDW = MDW; }
S
SheetJS 已提交
6914
	}
S
SheetJS 已提交
6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926
	MDW = _MDW;
}

function process_col(coll/*:ColInfo*/) {
	if(coll.width) {
		coll.wpx = width2px(coll.width);
		coll.wch = px2char(coll.wpx);
		coll.MDW = MDW;
	} else if(coll.wpx) {
		coll.wch = px2char(coll.wpx);
		coll.width = char2width(coll.wch);
		coll.MDW = MDW;
S
SheetJS 已提交
6927 6928 6929 6930
	} else if(typeof coll.wch == 'number') {
		coll.width = char2width(coll.wch);
		coll.wpx = width2px(coll.width);
		coll.MDW = MDW;
S
SheetJS 已提交
6931 6932
	}
	if(coll.customWidth) delete coll.customWidth;
S
SheetJS 已提交
6933 6934
}

S
SheetJS 已提交
6935 6936 6937
var DEF_PPI = 96, PPI = DEF_PPI;
function px2pt(px) { return px * 96 / PPI; }
function pt2px(pt) { return pt * PPI / 96; }
P
Paul Ishenin 已提交
6938

S
SheetJS 已提交
6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957
/* [MS-EXSPXML3] 2.4.54 ST_enmPattern */
var XLMLPatternTypeMap = {
	"None": "none",
	"Solid": "solid",
	"Gray50": "mediumGray",
	"Gray75": "darkGray",
	"Gray25": "lightGray",
	"HorzStripe": "darkHorizontal",
	"VertStripe": "darkVertical",
	"ReverseDiagStripe": "darkDown",
	"DiagStripe": "darkUp",
	"DiagCross": "darkGrid",
	"ThickDiagCross": "darkTrellis",
	"ThinHorzStripe": "lightHorizontal",
	"ThinVertStripe": "lightVertical",
	"ThinReverseDiagStripe": "lightDown",
	"ThinHorzCross": "lightGrid"
};

P
Pieter Sheth-Voss 已提交
6958 6959 6960 6961 6962 6963 6964 6965 6966 6967
/* 18.8.5 borders CT_Borders */
function parse_borders(t, styles, themes, opts) {
	styles.Borders = [];
	var border = {}, sub_border = {};
	t[0].match(tagregex).forEach(function(x) {
		var y = parsexmltag(x);
		switch (y[0]) {
			case '<borders': case '<borders>': case '</borders>': break;

			/* 18.8.4 border CT_Border */
S
SheetJS 已提交
6968
			case '<border': case '<border>': case '<border/>':
P
Pieter Sheth-Voss 已提交
6969 6970 6971 6972 6973 6974 6975 6976
				border = {};
				if (y.diagonalUp) { border.diagonalUp = y.diagonalUp; }
				if (y.diagonalDown) { border.diagonalDown = y.diagonalDown; }
				styles.Borders.push(border);
				break;
			case '</border>': break;

			/* note: not in spec, appears to be CT_BorderPr */
6977 6978
			case '<left/>': break;
			case '<left': case '<left>': break;
P
Pieter Sheth-Voss 已提交
6979 6980 6981
			case '</left>': break;

			/* note: not in spec, appears to be CT_BorderPr */
6982 6983
			case '<right/>': break;
			case '<right': case '<right>': break;
P
Pieter Sheth-Voss 已提交
6984 6985 6986
			case '</right>': break;

			/* 18.8.43 top CT_BorderPr */
6987 6988
			case '<top/>': break;
			case '<top': case '<top>': break;
P
Pieter Sheth-Voss 已提交
6989 6990 6991
			case '</top>': break;

			/* 18.8.6 bottom CT_BorderPr */
6992 6993
			case '<bottom/>': break;
			case '<bottom': case '<bottom>': break;
P
Pieter Sheth-Voss 已提交
6994 6995 6996
			case '</bottom>': break;

			/* 18.8.13 diagonal CT_BorderPr */
6997
			case '<diagonal': case '<diagonal>': case '<diagonal/>': break;
P
Pieter Sheth-Voss 已提交
6998 6999 7000
			case '</diagonal>': break;

			/* 18.8.25 horizontal CT_BorderPr */
7001
			case '<horizontal': case '<horizontal>': case '<horizontal/>': break;
P
Pieter Sheth-Voss 已提交
7002 7003 7004
			case '</horizontal>': break;

			/* 18.8.44 vertical CT_BorderPr */
7005
			case '<vertical': case '<vertical>': case '<vertical/>': break;
P
Pieter Sheth-Voss 已提交
7006 7007 7008
			case '</vertical>': break;

			/* 18.8.37 start CT_BorderPr */
7009
			case '<start': case '<start>': case '<start/>': break;
P
Pieter Sheth-Voss 已提交
7010 7011 7012
			case '</start>': break;

			/* 18.8.16 end CT_BorderPr */
7013
			case '<end': case '<end>': case '<end/>': break;
P
Pieter Sheth-Voss 已提交
7014 7015 7016
			case '</end>': break;

			/* 18.8.? color CT_Color */
7017 7018
			case '<color': case '<color>': break;
			case '<color/>': case '</color>': break;
P
Pieter Sheth-Voss 已提交
7019 7020 7021 7022 7023 7024

			default: if(opts && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in borders');
		}
	});
}

S
SheetJS 已提交
7025
/* 18.8.21 fills CT_Fills */
P
Pieter Sheth-Voss 已提交
7026
function parse_fills(t, styles, themes, opts) {
S
SheetJS 已提交
7027 7028 7029 7030 7031 7032 7033 7034
	styles.Fills = [];
	var fill = {};
	t[0].match(tagregex).forEach(function(x) {
		var y = parsexmltag(x);
		switch(y[0]) {
			case '<fills': case '<fills>': case '</fills>': break;

			/* 18.8.20 fill CT_Fill */
S
SheetJS 已提交
7035 7036 7037
			case '<fill>': case '<fill': case '<fill/>':
				fill = {}; styles.Fills.push(fill); break;
			case '</fill>': break;
S
SheetJS 已提交
7038

P
Pieter Sheth-Voss 已提交
7039
			/* 18.8.24 gradientFill CT_GradientFill */
S
SheetJS 已提交
7040
			case '<gradientFill>': break;
S
SheetJS 已提交
7041
			case '<gradientFill':
S
SheetJS 已提交
7042
			case '</gradientFill>': styles.Fills.push(fill); fill = {}; break;
P
Pieter Sheth-Voss 已提交
7043

S
SheetJS 已提交
7044
			/* 18.8.32 patternFill CT_PatternFill */
P
Pieter Sheth-Voss 已提交
7045
			case '<patternFill': case '<patternFill>':
S
SheetJS 已提交
7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056
				if(y.patternType) fill.patternType = y.patternType;
				break;
			case '<patternFill/>': case '</patternFill>': break;

			/* 18.8.3 bgColor CT_Color */
			case '<bgColor':
				if(!fill.bgColor) fill.bgColor = {};
				if(y.indexed) fill.bgColor.indexed = parseInt(y.indexed, 10);
				if(y.theme) fill.bgColor.theme = parseInt(y.theme, 10);
				if(y.tint) fill.bgColor.tint = parseFloat(y.tint);
				/* Excel uses ARGB strings */
P
Pieter Sheth-Voss 已提交
7057
				if(y.rgb) fill.bgColor.rgb = y.rgb.slice(-6);
S
SheetJS 已提交
7058 7059 7060 7061 7062 7063 7064 7065 7066
				break;
			case '<bgColor/>': case '</bgColor>': break;

			/* 18.8.19 fgColor CT_Color */
			case '<fgColor':
				if(!fill.fgColor) fill.fgColor = {};
				if(y.theme) fill.fgColor.theme = parseInt(y.theme, 10);
				if(y.tint) fill.fgColor.tint = parseFloat(y.tint);
				/* Excel uses ARGB strings */
P
Pieter Sheth-Voss 已提交
7067
				if(y.rgb) fill.fgColor.rgb = y.rgb.slice(-6);
S
SheetJS 已提交
7068 7069 7070
				break;
			case '<fgColor/>': case '</fgColor>': break;

P
Pieter Sheth-Voss 已提交
7071 7072 7073 7074 7075 7076 7077 7078
			/* 18.8.38 stop CT_GradientStop */
			case '<stop': case '<stop/>': break;
			case '</stop>': break;

			/* 18.8.? color CT_Color */
			case '<color': case '<color/>': break;
			case '</color>': break;

S
SheetJS 已提交
7079
			default: if(opts && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fills');
S
SheetJS 已提交
7080 7081 7082 7083
		}
	});
}

P
Pieter Sheth-Voss 已提交
7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103
/* 18.8.23 fonts CT_Fonts */
function parse_fonts(t, styles, themes, opts) {
	styles.Fonts = [];
	var font = {};
	t[0].match(tagregex).forEach(function(x) {
		var y = parsexmltag(x);
		switch (y[0]) {
			case '<fonts': case '<fonts>': case '</fonts>': break;

			/* 18.8.22 font CT_Font */
			case '<font': case '<font>': break;
			case '</font>': case '<font/>':
				styles.Fonts.push(font);
				font = {};
				break;

			/* 18.8.29 name CT_FontName */
			case '<name': if(y.val) font.name = y.val; break;
			case '<name/>': case '</name>': break;

S
SheetJS 已提交
7104 7105 7106
			/* 18.8.2  b CT_BooleanProperty */
			case '<b': font.bold = y.val ? parsexmlbool(y.val) : 1; break;
			case '<b/>': font.bold = 1; break;
P
Pieter Sheth-Voss 已提交
7107 7108

			/* 18.8.26 i CT_BooleanProperty */
S
SheetJS 已提交
7109 7110
			case '<i': font.italic = y.val ? parsexmlbool(y.val) : 1; break;
			case '<i/>': font.italic = 1; break;
P
Pieter Sheth-Voss 已提交
7111 7112

			/* 18.4.13 u CT_UnderlineProperty */
S
SheetJS 已提交
7113 7114 7115 7116 7117 7118 7119 7120 7121
			case '<u':
				switch(y.val) {
					case "none": font.underline = 0x00; break;
					case "single": font.underline = 0x01; break;
					case "double": font.underline = 0x02; break;
					case "singleAccounting": font.underline = 0x21; break;
					case "doubleAccounting": font.underline = 0x22; break;
				} break;
			case '<u/>': font.underline = 1; break;
P
Pieter Sheth-Voss 已提交
7122 7123

			/* 18.4.10 strike CT_BooleanProperty */
S
SheetJS 已提交
7124 7125
			case '<strike': font.strike = y.val ? parsexmlbool(y.val) : 1; break;
			case '<strike/>': font.strike = 1; break;
P
Pieter Sheth-Voss 已提交
7126

S
SheetJS 已提交
7127 7128 7129
			/* 18.4.2  outline CT_BooleanProperty */
			case '<outline': font.outline = y.val ? parsexmlbool(y.val) : 1; break;
			case '<outline/>': font.outline = 1; break;
P
Pieter Sheth-Voss 已提交
7130 7131

			/* 18.8.36 shadow CT_BooleanProperty */
S
SheetJS 已提交
7132 7133 7134 7135 7136 7137 7138 7139 7140 7141
			case '<shadow': font.shadow = y.val ? parsexmlbool(y.val) : 1; break;
			case '<shadow/>': font.shadow = 1; break;

			/* 18.8.12 condense CT_BooleanProperty */
			case '<condense': font.condense = y.val ? parsexmlbool(y.val) : 1; break;
			case '<condense/>': font.condense = 1; break;

			/* 18.8.17 extend CT_BooleanProperty */
			case '<extend': font.extend = y.val ? parsexmlbool(y.val) : 1; break;
			case '<extend/>': font.extend = 1; break;
P
Pieter Sheth-Voss 已提交
7142 7143

			/* 18.4.11 sz CT_FontSize */
S
SheetJS 已提交
7144
			case '<sz': if(y.val) font.sz = +y.val; break;
P
Pieter Sheth-Voss 已提交
7145 7146 7147 7148 7149 7150 7151
			case '<sz/>': case '</sz>': break;

			/* 18.4.14 vertAlign CT_VerticalAlignFontProperty */
			case '<vertAlign': if(y.val) font.vertAlign = y.val; break;
			case '<vertAlign/>': case '</vertAlign>': break;

			/* 18.8.18 family CT_FontFamily */
S
SheetJS 已提交
7152
			case '<family': if(y.val) font.family = parseInt(y.val,10); break;
P
Pieter Sheth-Voss 已提交
7153 7154 7155 7156 7157 7158
			case '<family/>': case '</family>': break;

			/* 18.8.35 scheme CT_FontScheme */
			case '<scheme': if(y.val) font.scheme = y.val; break;
			case '<scheme/>': case '</scheme>': break;

S
SheetJS 已提交
7159
			/* 18.4.1 charset CT_IntProperty */
P
Pieter Sheth-Voss 已提交
7160 7161 7162 7163 7164
			case '<charset':
				if(y.val == '1') break;
				y.codepage = CS2CP[parseInt(y.val, 10)];
				break;

S
SheetJS 已提交
7165
			/* 18.?.? color CT_Color */
P
Pieter Sheth-Voss 已提交
7166 7167
			case '<color':
				if(!font.color) font.color = {};
S
SheetJS 已提交
7168 7169
				if(y.auto) font.color.auto = parsexmlbool(y.auto);

7170
				if(y.rgb) font.color.rgb = y.rgb.slice(-6);
S
SheetJS 已提交
7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184
				else if(y.indexed) {
					font.color.index = parseInt(y.indexed, 10);
					var icv = XLSIcv[font.color.index];
					if(font.color.index == 81) icv = XLSIcv[1];
					if(!icv) throw new Error(x);
					font.color.rgb = icv[0].toString(16) + icv[1].toString(16) + icv[2].toString(16);
				} else if(y.theme) {
					font.color.theme = parseInt(y.theme, 10);
					if(y.tint) font.color.tint = parseFloat(y.tint);
					if(y.theme && themes.themeElements && themes.themeElements.clrScheme) {
						font.color.rgb = rgb_tint(themes.themeElements.clrScheme[font.color.theme].rgb, font.color.tint || 0);
					}
				}

P
Pieter Sheth-Voss 已提交
7185 7186 7187 7188 7189 7190 7191 7192
				break;
			case '<color/>': case '</color>': break;

			default: if(opts && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fonts');
		}
	});
}

S
SheetJS 已提交
7193
/* 18.8.31 numFmts CT_NumFmts */
S
SheetJS 已提交
7194
function parse_numFmts(t, styles, opts) {
S
SheetJS 已提交
7195
	styles.NumberFmt = [];
S
SheetJS 已提交
7196
	var k/*Array<number>*/ = (keys(SSF._table)/*:any*/);
S
SheetJS 已提交
7197 7198
	for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
	var m = t[0].match(tagregex);
S
SheetJS 已提交
7199
	if(!m) return;
S
SheetJS 已提交
7200 7201 7202 7203 7204 7205
	for(i=0; i < m.length; ++i) {
		var y = parsexmltag(m[i]);
		switch(y[0]) {
			case '<numFmts': case '</numFmts>': case '<numFmts/>': case '<numFmts>': break;
			case '<numFmt': {
				var f=unescapexml(utf8read(y.formatCode)), j=parseInt(y.numFmtId,10);
7206 7207 7208 7209 7210 7211 7212 7213
				styles.NumberFmt[j] = f;
				if(j>0) {
					if(j > 0x188) {
						for(j = 0x188; j > 0x3c; --j) if(styles.NumberFmt[j] == null) break;
						styles.NumberFmt[j] = f;
					}
					SSF.load(f,j);
				}
S
SheetJS 已提交
7214
			} break;
S
SheetJS 已提交
7215
			case '</numFmt>': break;
S
SheetJS 已提交
7216
			default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in numFmts');
S
SheetJS 已提交
7217 7218 7219 7220
		}
	}
}

S
SheetJS 已提交
7221
function write_numFmts(NF/*:{[n:number|string]:string}*/, opts) {
S
SheetJS 已提交
7222
	var o = ["<numFmts>"];
S
SheetJS 已提交
7223
	[[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
P
Pieter Sheth-Voss 已提交
7224
		for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) o[o.length] = (writextag('numFmt',null,{numFmtId:i,formatCode:escapexml(NF[i])}));
S
SheetJS 已提交
7225 7226 7227 7228 7229 7230 7231 7232
	});
	if(o.length === 1) return "";
	o[o.length] = ("</numFmts>");
	o[0] = writextag('numFmts', null, { count:o.length-2 }).replace("/>", ">");
	return o.join("");
}

/* 18.8.10 cellXfs CT_CellXfs */
S
SheetJS 已提交
7233 7234
var cellXF_uint = [ "numFmtId", "fillId", "fontId", "borderId", "xfId" ];
var cellXF_bool = [ "applyAlignment", "applyBorder", "applyFill", "applyFont", "applyNumberFormat", "applyProtection", "pivotButton", "quotePrefix" ];
S
SheetJS 已提交
7235
function parse_cellXfs(t, styles, opts) {
S
SheetJS 已提交
7236
	styles.CellXf = [];
P
Pieter Sheth-Voss 已提交
7237
	var xf;
S
SheetJS 已提交
7238
	t[0].match(tagregex).forEach(function(x) {
S
SheetJS 已提交
7239
		var y = parsexmltag(x), i = 0;
S
SheetJS 已提交
7240 7241 7242 7243
		switch(y[0]) {
			case '<cellXfs': case '<cellXfs>': case '<cellXfs/>': case '</cellXfs>': break;

			/* 18.8.45 xf CT_Xf */
7244
			case '<xf': case '<xf/>':
P
Pieter Sheth-Voss 已提交
7245 7246
				xf = y;
				delete xf[0];
S
SheetJS 已提交
7247 7248 7249 7250
				for(i = 0; i < cellXF_uint.length; ++i) if(xf[cellXF_uint[i]])
					xf[cellXF_uint[i]] = parseInt(xf[cellXF_uint[i]], 10);
				for(i = 0; i < cellXF_bool.length; ++i) if(xf[cellXF_bool[i]])
					xf[cellXF_bool[i]] = parsexmlbool(xf[cellXF_bool[i]], "");
7251 7252 7253
				if(xf.numFmtId > 0x188) {
					for(i = 0x188; i > 0x3c; --i) if(styles.NumberFmt[xf.numFmtId] == styles.NumberFmt[i]) { xf.numFmtId = i; break; }
				}
P
Pieter Sheth-Voss 已提交
7254
				styles.CellXf.push(xf); break;
S
SheetJS 已提交
7255 7256 7257
			case '</xf>': break;

			/* 18.8.1 alignment CT_CellAlignment */
P
Pieter Sheth-Voss 已提交
7258 7259 7260 7261 7262 7263 7264 7265 7266 7267
			case '<alignment': case '<alignment/>':
				var alignment = {};
				if(y.vertical) alignment.vertical = y.vertical;
				if(y.horizontal) alignment.horizontal = y.horizontal;
				if(y.textRotation != null) alignment.textRotation = y.textRotation;
				if(y.indent) alignment.indent = y.indent;
				if(y.wrapText) alignment.wrapText = y.wrapText;
				xf.alignment = alignment;
				break;
			case '</alignment>': break;
S
SheetJS 已提交
7268 7269 7270 7271

			/* 18.8.33 protection CT_CellProtection */
			case '<protection': case '</protection>': case '<protection/>': break;

P
Pieter Sheth-Voss 已提交
7272
			/* 18.2.10 extLst CT_ExtensionList ? */
S
SheetJS 已提交
7273 7274
			case '<extLst': case '</extLst>': break;
			case '<ext': break;
7275
			default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in cellXfs');
S
SheetJS 已提交
7276 7277 7278 7279
		}
	});
}

S
SheetJS 已提交
7280
function write_cellXfs(cellXfs)/*:string*/ {
S
SheetJS 已提交
7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291
	var o = [];
	o[o.length] = (writextag('cellXfs',null));
	cellXfs.forEach(function(c) { o[o.length] = (writextag('xf', null, c)); });
	o[o.length] = ("</cellXfs>");
	if(o.length === 2) return "";
	o[0] = writextag('cellXfs',null, {count:o.length-2}).replace("/>",">");
	return o.join("");
}

/* 18.8 Styles CT_Stylesheet*/
var parse_sty_xml= (function make_pstyx() {
7292 7293 7294 7295 7296
var numFmtRegex = /<numFmts([^>]*)>[\S\s]*?<\/numFmts>/;
var cellXfRegex = /<cellXfs([^>]*)>[\S\s]*?<\/cellXfs>/;
var fillsRegex = /<fills([^>]*)>[\S\s]*?<\/fills>/;
var fontsRegex = /<fonts([^>]*)>[\S\s]*?<\/fonts>/;
var bordersRegex = /<borders([^>]*)>[\S\s]*?<\/borders>/;
S
SheetJS 已提交
7297

P
Pieter Sheth-Voss 已提交
7298
return function parse_sty_xml(data, themes, opts) {
S
SheetJS 已提交
7299
	var styles = {};
S
SheetJS 已提交
7300
	if(!data) return styles;
7301
	data = data.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
S
SheetJS 已提交
7302 7303 7304
	/* 18.8.39 styleSheet CT_Stylesheet */
	var t;

P
Pieter Sheth-Voss 已提交
7305
	/* 18.8.31 numFmts CT_NumFmts ? */
S
SheetJS 已提交
7306
	if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts);
S
SheetJS 已提交
7307

P
Pieter Sheth-Voss 已提交
7308 7309
	/* 18.8.23 fonts CT_Fonts ? */
	if((t=data.match(fontsRegex))) parse_fonts(t, styles, themes, opts);
S
SheetJS 已提交
7310

S
SheetJS 已提交
7311
	/* 18.8.21 fills CT_Fills ? */
P
Pieter Sheth-Voss 已提交
7312
	if((t=data.match(fillsRegex))) parse_fills(t, styles, themes, opts);
S
SheetJS 已提交
7313

S
SheetJS 已提交
7314
	/* 18.8.5  borders CT_Borders ? */
P
Pieter Sheth-Voss 已提交
7315
	if((t=data.match(bordersRegex))) parse_borders(t, styles, themes, opts);
S
SheetJS 已提交
7316

S
SheetJS 已提交
7317
	/* 18.8.9  cellStyleXfs CT_CellStyleXfs ? */
P
Pieter Sheth-Voss 已提交
7318 7319

	/* 18.8.10 cellXfs CT_CellXfs ? */
S
SheetJS 已提交
7320
	if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts);
S
SheetJS 已提交
7321

S
SheetJS 已提交
7322
	/* 18.8.8  cellStyles CT_CellStyles ? */
P
Pieter Sheth-Voss 已提交
7323 7324 7325 7326
	/* 18.8.15 dxfs CT_Dxfs ? */
	/* 18.8.42 tableStyles CT_TableStyles ? */
	/* 18.8.11 colors CT_Colors ? */
	/* 18.2.10 extLst CT_ExtensionList ? */
S
SheetJS 已提交
7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338

	return styles;
};
})();

var STYLES_XML_ROOT = writextag('styleSheet', null, {
	'xmlns': XMLNS.main[0],
	'xmlns:vt': XMLNS.vt
});

RELS.STY = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";

S
SheetJS 已提交
7339
function write_sty_xml(wb/*:Workbook*/, opts)/*:string*/ {
S
SheetJS 已提交
7340
	var o = [XML_HEADER, STYLES_XML_ROOT], w;
S
SheetJS 已提交
7341
	if(wb.SSF && (w = write_numFmts(wb.SSF)) != null) o[o.length] = w;
S
SheetJS 已提交
7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354
	o[o.length] = ('<fonts count="1"><font><sz val="12"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font></fonts>');
	o[o.length] = ('<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
	o[o.length] = ('<borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>');
	o[o.length] = ('<cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>');
	if((w = write_cellXfs(opts.cellXfs))) o[o.length] = (w);
	o[o.length] = ('<cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles>');
	o[o.length] = ('<dxfs count="0"/>');
	o[o.length] = ('<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleMedium4"/>');

	if(o.length>2){ o[o.length] = ('</styleSheet>'); o[1]=o[1].replace("/>",">"); }
	return o.join("");
}
/* [MS-XLSB] 2.4.651 BrtFmt */
S
SheetJS 已提交
7355
function parse_BrtFmt(data, length/*:number*/) {
S
SheetJS 已提交
7356
	var numFmtId = data.read_shift(2);
S
SheetJS 已提交
7357
	var stFmtCode = parse_XLWideString(data,length-2);
S
SheetJS 已提交
7358
	return [numFmtId, stFmtCode];
S
SheetJS 已提交
7359
}
S
SheetJS 已提交
7360 7361 7362 7363 7364 7365
function write_BrtFmt(i/*:number*/, f/*:string*/, o) {
	if(!o) o = new_buf(6 + 4 * f.length);
	o.write_shift(2, i);
	write_XLWideString(f, o);
	return o.length > o.l ? o.slice(0, o.l) : o;
}
S
SheetJS 已提交
7366 7367

/* [MS-XLSB] 2.4.653 BrtFont TODO */
S
SheetJS 已提交
7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398
function parse_BrtFont(data, length/*:number*/, opts) {
	var out = ({}/*:any*/);

	out.sz = data.read_shift(2) / 20;

	var grbit = parse_FontFlags(data, 2, opts);
	if(grbit.fCondense) out.condense = 1;
	if(grbit.fExtend) out.extend = 1;
	if(grbit.fShadow) out.shadow = 1;
	if(grbit.fOutline) out.outline = 1;
	if(grbit.fStrikeout) out.strike = 1;
	if(grbit.fItalic) out.italic = 1;

	var bls = data.read_shift(2);
	if(bls === 0x02BC) out.bold = 1;

	switch(data.read_shift(2)) {
		/* case 0: out.vertAlign = "baseline"; break; */
		case 1: out.vertAlign = "superscript"; break;
		case 2: out.vertAlign = "subscript"; break;
	}

	var underline = data.read_shift(1);
	if(underline != 0) out.underline = underline;

	var family = data.read_shift(1);
	if(family > 0) out.family = family;

	var bCharSet = data.read_shift(1);
	if(bCharSet > 0) out.charset = bCharSet;

S
SheetJS 已提交
7399
	data.l++;
S
SheetJS 已提交
7400 7401 7402 7403 7404 7405 7406 7407
	out.color = parse_BrtColor(data, 8);

	switch(data.read_shift(1)) {
		/* case 0: out.scheme = "none": break; */
		case 1: out.scheme = "major"; break;
		case 2: out.scheme = "minor"; break;
	}

S
SheetJS 已提交
7408 7409 7410 7411
	out.name = parse_XLWideString(data, length - 21);

	return out;
}
S
SheetJS 已提交
7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455
function write_BrtFont(font, o) {
	if(!o) o = new_buf(25+4*32);
	o.write_shift(2, font.sz * 20);
	write_FontFlags(font, o);
	o.write_shift(2, font.bold ? 0x02BC : 0x0190);
	var sss = 0;
	if(font.vertAlign == "superscript") sss = 1;
	else if(font.vertAlign == "subscript") sss = 2;
	o.write_shift(2, sss);
	o.write_shift(1, font.underline || 0);
	o.write_shift(1, font.family || 0);
	o.write_shift(1, font.charset || 0);
	o.write_shift(1, 0);
	write_BrtColor(font.color, o);
	var scheme = 0;
	if(font.scheme == "major") scheme = 1;
	if(font.scheme == "minor") scheme = 2;
	o.write_shift(1, scheme);
	write_XLWideString(font.name, o);
	return o.length > o.l ? o.slice(0, o.l) : o;
}

/* [MS-XLSB] 2.4.644 BrtFill */
var XLSBFillPTNames = [
	"none",
	"solid",
	"mediumGray",
	"darkGray",
	"lightGray",
	"darkHorizontal",
	"darkVertical",
	"darkDown",
	"darkUp",
	"darkGrid",
	"darkTrellis",
	"lightHorizontal",
	"lightVertical",
	"lightDown",
	"lightUp",
	"lightGrid",
	"lightTrellis",
	"gray125",
	"gray0625"
];
S
SheetJS 已提交
7456
var rev_XLSBFillPTNames/*:EvertNumType*/ = (evert(XLSBFillPTNames)/*:any*/);
S
SheetJS 已提交
7457
/* TODO: gradient fill representation */
S
SheetJS 已提交
7458
var parse_BrtFill = parsenoop;
S
SheetJS 已提交
7459 7460
function write_BrtFill(fill, o) {
	if(!o) o = new_buf(4*3 + 8*7 + 16*1);
S
SheetJS 已提交
7461
	var fls/*:number*/ = rev_XLSBFillPTNames[fill.patternType];
S
SheetJS 已提交
7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486
	if(fls == null) fls = 0x28;
	o.write_shift(4, fls);
	var j = 0;
	if(fls != 0x28) {
		/* TODO: custom FG Color */
		write_BrtColor({auto:1}, o);
		/* TODO: custom BG Color */
		write_BrtColor({auto:1}, o);

		for(; j < 12; ++j) o.write_shift(4, 0);
	} else {
		for(; j < 4; ++j) o.write_shift(4, 0);

		for(; j < 12; ++j) o.write_shift(4, 0); /* TODO */
		/* iGradientType */
		/* xnumDegree */
		/* xnumFillToLeft */
		/* xnumFillToRight */
		/* xnumFillToTop */
		/* xnumFillToBottom */
		/* cNumStop */
		/* xfillGradientStop */
	}
	return o.length > o.l ? o.slice(0, o.l) : o;
}
S
SheetJS 已提交
7487 7488

/* [MS-XLSB] 2.4.816 BrtXF */
S
SheetJS 已提交
7489
function parse_BrtXF(data, length/*:number*/) {
S
SheetJS 已提交
7490 7491 7492
	var ixfeParent = data.read_shift(2);
	var ifmt = data.read_shift(2);
	parsenoop(data, length-4);
S
SheetJS 已提交
7493
	return {ixfe:ixfeParent, numFmtId:ifmt };
S
SheetJS 已提交
7494
}
S
SheetJS 已提交
7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520
function write_BrtXF(data, ixfeP, o) {
	if(!o) o = new_buf(16);
	o.write_shift(2, ixfeP||0);
	o.write_shift(2, data.numFmtId||0);
	o.write_shift(2, 0); /* iFont */
	o.write_shift(2, 0); /* iFill */
	o.write_shift(2, 0); /* ixBorder */
	o.write_shift(1, 0); /* trot */
	o.write_shift(1, 0); /* indent */
	o.write_shift(1, 0); /* flags */
	o.write_shift(1, 0); /* flags */
	o.write_shift(1, 0); /* xfGrbitAtr */
	o.write_shift(1, 0);
	return o;
}

/* [MS-XLSB] 2.5.4 Blxf TODO */
function write_Blxf(data, o) {
	if(!o) o = new_buf(10);
	o.write_shift(1, 0); /* dg */
	o.write_shift(1, 0);
	o.write_shift(4, 0); /* color */
	o.write_shift(4, 0); /* color */
	return o;
}
/* [MS-XLSB] 2.4.299 BrtBorder TODO */
S
SheetJS 已提交
7521
var parse_BrtBorder = parsenoop;
S
SheetJS 已提交
7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551
function write_BrtBorder(border, o) {
	if(!o) o = new_buf(51);
	o.write_shift(1, 0); /* diagonal */
	write_Blxf(null, o); /* top */
	write_Blxf(null, o); /* bottom */
	write_Blxf(null, o); /* left */
	write_Blxf(null, o); /* right */
	write_Blxf(null, o); /* diag */
	return o.length > o.l ? o.slice(0, o.l) : o;
}

/* [MS-XLSB] 2.4.755 BrtStyle TODO */
function write_BrtStyle(style, o) {
	if(!o) o = new_buf(12+4*10);
	o.write_shift(4, style.xfId);
	o.write_shift(2, 1);
	o.write_shift(1, +style.builtinId);
	o.write_shift(1, 0); /* iLevel */
	write_XLNullableWideString(style.name || "", o);
	return o.length > o.l ? o.slice(0, o.l) : o;
}

/* [MS-XLSB] 2.4.269 BrtBeginTableStyles */
function write_BrtBeginTableStyles(cnt, defTableStyle, defPivotStyle) {
	var o = new_buf(4+256*2*4);
	o.write_shift(4, cnt);
	write_XLNullableWideString(defTableStyle, o);
	write_XLNullableWideString(defPivotStyle, o);
	return o.length > o.l ? o.slice(0, o.l) : o;
}
S
SheetJS 已提交
7552 7553

/* [MS-XLSB] 2.1.7.50 Styles */
P
Pieter Sheth-Voss 已提交
7554
function parse_sty_bin(data, themes, opts) {
S
SheetJS 已提交
7555
	var styles = {};
S
SheetJS 已提交
7556
	styles.NumberFmt = ([]/*:any*/);
S
SheetJS 已提交
7557 7558 7559
	for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y];

	styles.CellXf = [];
S
SheetJS 已提交
7560
	styles.Fonts = [];
S
SheetJS 已提交
7561
	var state = [];
S
SheetJS 已提交
7562
	var pass = false;
7563 7564 7565
	recordhopper(data, function hopper_sty(val, R_n, RT) {
		switch(RT) {
			case 0x002C: /* 'BrtFmt' */
S
SheetJS 已提交
7566 7567
				styles.NumberFmt[val[0]] = val[1]; SSF.load(val[1], val[0]);
				break;
S
SheetJS 已提交
7568 7569
			case 0x002B: /* 'BrtFont' */
				styles.Fonts.push(val);
S
SheetJS 已提交
7570 7571 7572
				if(val.color.theme != null && themes && themes.themeElements && themes.themeElements.clrScheme) {
					val.color.rgb = rgb_tint(themes.themeElements.clrScheme[val.color.theme].rgb, val.color.tint || 0);
				}
S
SheetJS 已提交
7573
				break;
7574 7575 7576 7577
			case 0x0401: /* 'BrtKnownFonts' */ break;
			case 0x002D: /* 'BrtFill' */ break;
			case 0x002E: /* 'BrtBorder' */ break;
			case 0x002F: /* 'BrtXF' */
S
SheetJS 已提交
7578
				if(state[state.length - 1] == "BrtBeginCellXFs") {
S
SheetJS 已提交
7579 7580
					styles.CellXf.push(val);
				}
7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603
				break;
			case 0x0030: /* 'BrtStyle' */
			case 0x01FB: /* 'BrtDXF' */
			case 0x023C: /* 'BrtMRUColor' */
			case 0x01DB: /* 'BrtIndexedColor': */
				break;

			case 0x0493: /* 'BrtDXF14' */
			case 0x0836: /* 'BrtDXF15' */
			case 0x046A: /* 'BrtSlicerStyleElement' */
			case 0x0200: /* 'BrtTableStyleElement' */
			case 0x082F: /* 'BrtTimelineStyleElement' */
			/* case 'BrtUid' */
				break;

			case 0x0023: /* 'BrtFRTBegin' */
				pass = true; break;
			case 0x0024: /* 'BrtFRTEnd' */
				pass = false; break;
			case 0x0025: /* 'BrtACBegin' */
				state.push(R_n); break;
			case 0x0026: /* 'BrtACEnd' */
				state.pop(); break;
S
SheetJS 已提交
7604 7605

			default:
7606 7607 7608
				if((R_n||"").indexOf("Begin") > 0) state.push(R_n);
				else if((R_n||"").indexOf("End") > 0) state.pop();
				else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
S
SheetJS 已提交
7609 7610 7611 7612 7613
		}
	});
	return styles;
}

S
SheetJS 已提交
7614
function write_FMTS_bin(ba, NF/*:?SSFTable*/) {
S
SheetJS 已提交
7615 7616
	if(!NF) return;
	var cnt = 0;
7617
	[[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
S
SheetJS 已提交
7618
		/*:: if(!NF) return; */
S
SheetJS 已提交
7619 7620 7621 7622 7623
		for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) ++cnt;
	});

	if(cnt == 0) return;
	write_record(ba, "BrtBeginFmts", write_UInt32LE(cnt));
7624
	[[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
S
SheetJS 已提交
7625
		/*:: if(!NF) return; */
S
SheetJS 已提交
7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721
		for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_record(ba, "BrtFmt", write_BrtFmt(i, NF[i]));
	});
	write_record(ba, "BrtEndFmts");
}

function write_FONTS_bin(ba, data) {
	var cnt = 1;

	if(cnt == 0) return;
	write_record(ba, "BrtBeginFonts", write_UInt32LE(cnt));
	write_record(ba, "BrtFont", write_BrtFont({
		sz:12,
		color: {theme:1},
		name: "Calibri",
		family: 2,
		scheme: "minor"
	}));
	/* 1*65491BrtFont [ACFONTS] */
	write_record(ba, "BrtEndFonts");
}

function write_FILLS_bin(ba, data) {
	var cnt = 2;

	if(cnt == 0) return;
	write_record(ba, "BrtBeginFills", write_UInt32LE(cnt));
	write_record(ba, "BrtFill", write_BrtFill({patternType:"none"}));
	write_record(ba, "BrtFill", write_BrtFill({patternType:"gray125"}));
	/* 1*65431BrtFill */
	write_record(ba, "BrtEndFills");
}

function write_BORDERS_bin(ba, data) {
	var cnt = 1;

	if(cnt == 0) return;
	write_record(ba, "BrtBeginBorders", write_UInt32LE(cnt));
	write_record(ba, "BrtBorder", write_BrtBorder({}));
	/* 1*65430BrtBorder */
	write_record(ba, "BrtEndBorders");
}

function write_CELLSTYLEXFS_bin(ba, data) {
	var cnt = 1;
	write_record(ba, "BrtBeginCellStyleXFs", write_UInt32LE(cnt));
	write_record(ba, "BrtXF", write_BrtXF({
		numFmtId:0,
		fontId:0,
		fillId:0,
		borderId:0
	}, 0xFFFF));
	/* 1*65430(BrtXF *FRT) */
	write_record(ba, "BrtEndCellStyleXFs");
}

function write_CELLXFS_bin(ba, data) {
	write_record(ba, "BrtBeginCellXFs", write_UInt32LE(data.length));
	data.forEach(function(c) { write_record(ba, "BrtXF", write_BrtXF(c,0)); });
	/* 1*65430(BrtXF *FRT) */
	write_record(ba, "BrtEndCellXFs");
}

function write_STYLES_bin(ba, data) {
	var cnt = 1;

	write_record(ba, "BrtBeginStyles", write_UInt32LE(1));
	write_record(ba, "BrtStyle", write_BrtStyle({
		xfId:0,
		builtinId:0,
		name:"Normal"
	}));
	/* 1*65430(BrtStyle *FRT) */
	write_record(ba, "BrtEndStyles");
}

function write_DXFS_bin(ba, data) {
	var cnt = 0;

	write_record(ba, "BrtBeginDXFs", write_UInt32LE(cnt));
	/* *2147483647(BrtDXF *FRT) */
	write_record(ba, "BrtEndDXFs");
}

function write_TABLESTYLES_bin(ba, data) {
	var cnt = 0;

	write_record(ba, "BrtBeginTableStyles", write_BrtBeginTableStyles(cnt, "TableStyleMedium9", "PivotStyleMedium4"));
	/* *TABLESTYLE */
	write_record(ba, "BrtEndTableStyles");
}

function write_COLORPALETTE_bin(ba, data) {
	return;
	/* BrtBeginColorPalette [INDEXEDCOLORS] [MRUCOLORS] BrtEndColorPalette */
}

S
SheetJS 已提交
7722
/* [MS-XLSB] 2.1.7.50 Styles */
S
SheetJS 已提交
7723
function write_sty_bin(wb, opts) {
S
SheetJS 已提交
7724 7725
	var ba = buf_array();
	write_record(ba, "BrtBeginStyleSheet");
S
SheetJS 已提交
7726 7727 7728 7729 7730 7731 7732 7733 7734 7735
	write_FMTS_bin(ba, wb.SSF);
	write_FONTS_bin(ba, wb);
	write_FILLS_bin(ba, wb);
	write_BORDERS_bin(ba, wb);
	write_CELLSTYLEXFS_bin(ba, wb);
	write_CELLXFS_bin(ba, opts.cellXfs);
	write_STYLES_bin(ba, wb);
	write_DXFS_bin(ba, wb);
	write_TABLESTYLES_bin(ba, wb);
	write_COLORPALETTE_bin(ba, wb);
S
SheetJS 已提交
7736 7737 7738 7739 7740 7741 7742
	/* FRTSTYLESHEET*/
	write_record(ba, "BrtEndStyleSheet");
	return ba.end();
}
RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";

/* 20.1.6.2 clrScheme CT_ColorScheme */
S
SheetJS 已提交
7743
function parse_clrScheme(t, themes, opts) {
S
SheetJS 已提交
7744 7745
	themes.themeElements.clrScheme = [];
	var color = {};
S
SheetJS 已提交
7746
	(t[0].match(tagregex)||[]).forEach(function(x) {
S
SheetJS 已提交
7747 7748
		var y = parsexmltag(x);
		switch(y[0]) {
S
SheetJS 已提交
7749
			/* 20.1.6.2 clrScheme (Color Scheme) CT_ColorScheme */
S
SheetJS 已提交
7750 7751 7752
			case '<a:clrScheme': case '</a:clrScheme>': break;

			/* 20.1.2.3.32 srgbClr CT_SRgbColor */
S
SheetJS 已提交
7753 7754
			case '<a:srgbClr':
				color.rgb = y.val; break;
S
SheetJS 已提交
7755 7756

			/* 20.1.2.3.33 sysClr CT_SystemColor */
S
SheetJS 已提交
7757 7758
			case '<a:sysClr':
				color.rgb = y.lastClr; break;
S
SheetJS 已提交
7759 7760 7761 7762 7763 7764 7765

			/* 20.1.4.1.1 accent1 (Accent 1) */
			/* 20.1.4.1.2 accent2 (Accent 2) */
			/* 20.1.4.1.3 accent3 (Accent 3) */
			/* 20.1.4.1.4 accent4 (Accent 4) */
			/* 20.1.4.1.5 accent5 (Accent 5) */
			/* 20.1.4.1.6 accent6 (Accent 6) */
S
SheetJS 已提交
7766 7767
			/* 20.1.4.1.9 dk1 (Dark 1) */
			/* 20.1.4.1.10 dk2 (Dark 2) */
S
SheetJS 已提交
7768
			/* 20.1.4.1.15 folHlink (Followed Hyperlink) */
S
SheetJS 已提交
7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783
			/* 20.1.4.1.19 hlink (Hyperlink) */
			/* 20.1.4.1.22 lt1 (Light 1) */
			/* 20.1.4.1.23 lt2 (Light 2) */
			case '<a:dk1>': case '</a:dk1>':
			case '<a:lt1>': case '</a:lt1>':
			case '<a:dk2>': case '</a:dk2>':
			case '<a:lt2>': case '</a:lt2>':
			case '<a:accent1>': case '</a:accent1>':
			case '<a:accent2>': case '</a:accent2>':
			case '<a:accent3>': case '</a:accent3>':
			case '<a:accent4>': case '</a:accent4>':
			case '<a:accent5>': case '</a:accent5>':
			case '<a:accent6>': case '</a:accent6>':
			case '<a:hlink>': case '</a:hlink>':
			case '<a:folHlink>': case '</a:folHlink>':
S
SheetJS 已提交
7784
				if (y[0].charAt(1) === '/') {
S
SheetJS 已提交
7785 7786 7787 7788 7789 7790 7791
					themes.themeElements.clrScheme.push(color);
					color = {};
				} else {
					color.name = y[0].substring(3, y[0].length - 1);
				}
				break;

S
SheetJS 已提交
7792
			default: if(opts && opts.WTF) throw new Error('Unrecognized ' + y[0] + ' in clrScheme');
S
SheetJS 已提交
7793 7794 7795 7796 7797
		}
	});
}

/* 20.1.4.1.18 fontScheme CT_FontScheme */
S
SheetJS 已提交
7798
function parse_fontScheme(t, themes, opts) { }
S
SheetJS 已提交
7799 7800

/* 20.1.4.1.15 fmtScheme CT_StyleMatrix */
S
SheetJS 已提交
7801
function parse_fmtScheme(t, themes, opts) { }
S
SheetJS 已提交
7802

S
SheetJS 已提交
7803 7804 7805
var clrsregex = /<a:clrScheme([^>]*)>[\s\S]*<\/a:clrScheme>/;
var fntsregex = /<a:fontScheme([^>]*)>[\s\S]*<\/a:fontScheme>/;
var fmtsregex = /<a:fmtScheme([^>]*)>[\s\S]*<\/a:fmtScheme>/;
S
SheetJS 已提交
7806 7807

/* 20.1.6.10 themeElements CT_BaseStyles */
S
SheetJS 已提交
7808
function parse_themeElements(data, themes, opts) {
S
SheetJS 已提交
7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820
	themes.themeElements = {};

	var t;

	[
		/* clrScheme CT_ColorScheme */
		['clrScheme', clrsregex, parse_clrScheme],
		/* fontScheme CT_FontScheme */
		['fontScheme', fntsregex, parse_fontScheme],
		/* fmtScheme CT_StyleMatrix */
		['fmtScheme', fmtsregex, parse_fmtScheme]
	].forEach(function(m) {
S
SheetJS 已提交
7821
		if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements');
S
SheetJS 已提交
7822
		m[2](t, themes, opts);
S
SheetJS 已提交
7823 7824 7825
	});
}

S
SheetJS 已提交
7826
var themeltregex = /<a:themeElements([^>]*)>[\s\S]*<\/a:themeElements>/;
S
SheetJS 已提交
7827 7828

/* 14.2.7 Theme Part */
S
SheetJS 已提交
7829
function parse_theme_xml(data/*:string*/, opts) {
S
SheetJS 已提交
7830
	/* 20.1.6.9 theme CT_OfficeStyleSheet */
S
SheetJS 已提交
7831
	if(!data || data.length === 0) return parse_theme_xml(write_theme());
S
SheetJS 已提交
7832 7833

	var t;
S
SheetJS 已提交
7834
	var themes = {};
S
SheetJS 已提交
7835 7836

	/* themeElements CT_BaseStyles */
7837
	if(!(t=data.match(themeltregex))) throw new Error('themeElements not found in theme');
S
SheetJS 已提交
7838
	parse_themeElements(t[0], themes, opts);
S
SheetJS 已提交
7839 7840 7841 7842

	return themes;
}

S
SheetJS 已提交
7843
function write_theme(Themes, opts)/*:string*/ {
S
SheetJS 已提交
7844
	if(opts && opts.themeXLSX) return opts.themeXLSX;
S
SheetJS 已提交
7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 7925 7926 7927 7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999
	var o = [XML_HEADER];
	o[o.length] = '<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">';
	o[o.length] =  '<a:themeElements>';

	o[o.length] =   '<a:clrScheme name="Office">';
	o[o.length] =    '<a:dk1><a:sysClr val="windowText" lastClr="000000"/></a:dk1>';
	o[o.length] =    '<a:lt1><a:sysClr val="window" lastClr="FFFFFF"/></a:lt1>';
	o[o.length] =    '<a:dk2><a:srgbClr val="1F497D"/></a:dk2>';
	o[o.length] =    '<a:lt2><a:srgbClr val="EEECE1"/></a:lt2>';
	o[o.length] =    '<a:accent1><a:srgbClr val="4F81BD"/></a:accent1>';
	o[o.length] =    '<a:accent2><a:srgbClr val="C0504D"/></a:accent2>';
	o[o.length] =    '<a:accent3><a:srgbClr val="9BBB59"/></a:accent3>';
	o[o.length] =    '<a:accent4><a:srgbClr val="8064A2"/></a:accent4>';
	o[o.length] =    '<a:accent5><a:srgbClr val="4BACC6"/></a:accent5>';
	o[o.length] =    '<a:accent6><a:srgbClr val="F79646"/></a:accent6>';
	o[o.length] =    '<a:hlink><a:srgbClr val="0000FF"/></a:hlink>';
	o[o.length] =    '<a:folHlink><a:srgbClr val="800080"/></a:folHlink>';
	o[o.length] =   '</a:clrScheme>';

	o[o.length] =   '<a:fontScheme name="Office">';
	o[o.length] =    '<a:majorFont>';
	o[o.length] =     '<a:latin typeface="Cambria"/>';
	o[o.length] =     '<a:ea typeface=""/>';
	o[o.length] =     '<a:cs typeface=""/>';
	o[o.length] =     '<a:font script="Jpan" typeface="MS Pゴシック"/>';
	o[o.length] =     '<a:font script="Hang" typeface="맑은 고딕"/>';
	o[o.length] =     '<a:font script="Hans" typeface="宋体"/>';
	o[o.length] =     '<a:font script="Hant" typeface="新細明體"/>';
	o[o.length] =     '<a:font script="Arab" typeface="Times New Roman"/>';
	o[o.length] =     '<a:font script="Hebr" typeface="Times New Roman"/>';
	o[o.length] =     '<a:font script="Thai" typeface="Tahoma"/>';
	o[o.length] =     '<a:font script="Ethi" typeface="Nyala"/>';
	o[o.length] =     '<a:font script="Beng" typeface="Vrinda"/>';
	o[o.length] =     '<a:font script="Gujr" typeface="Shruti"/>';
	o[o.length] =     '<a:font script="Khmr" typeface="MoolBoran"/>';
	o[o.length] =     '<a:font script="Knda" typeface="Tunga"/>';
	o[o.length] =     '<a:font script="Guru" typeface="Raavi"/>';
	o[o.length] =     '<a:font script="Cans" typeface="Euphemia"/>';
	o[o.length] =     '<a:font script="Cher" typeface="Plantagenet Cherokee"/>';
	o[o.length] =     '<a:font script="Yiii" typeface="Microsoft Yi Baiti"/>';
	o[o.length] =     '<a:font script="Tibt" typeface="Microsoft Himalaya"/>';
	o[o.length] =     '<a:font script="Thaa" typeface="MV Boli"/>';
	o[o.length] =     '<a:font script="Deva" typeface="Mangal"/>';
	o[o.length] =     '<a:font script="Telu" typeface="Gautami"/>';
	o[o.length] =     '<a:font script="Taml" typeface="Latha"/>';
	o[o.length] =     '<a:font script="Syrc" typeface="Estrangelo Edessa"/>';
	o[o.length] =     '<a:font script="Orya" typeface="Kalinga"/>';
	o[o.length] =     '<a:font script="Mlym" typeface="Kartika"/>';
	o[o.length] =     '<a:font script="Laoo" typeface="DokChampa"/>';
	o[o.length] =     '<a:font script="Sinh" typeface="Iskoola Pota"/>';
	o[o.length] =     '<a:font script="Mong" typeface="Mongolian Baiti"/>';
	o[o.length] =     '<a:font script="Viet" typeface="Times New Roman"/>';
	o[o.length] =     '<a:font script="Uigh" typeface="Microsoft Uighur"/>';
	o[o.length] =     '<a:font script="Geor" typeface="Sylfaen"/>';
	o[o.length] =    '</a:majorFont>';
	o[o.length] =    '<a:minorFont>';
	o[o.length] =     '<a:latin typeface="Calibri"/>';
	o[o.length] =     '<a:ea typeface=""/>';
	o[o.length] =     '<a:cs typeface=""/>';
	o[o.length] =     '<a:font script="Jpan" typeface="MS Pゴシック"/>';
	o[o.length] =     '<a:font script="Hang" typeface="맑은 고딕"/>';
	o[o.length] =     '<a:font script="Hans" typeface="宋体"/>';
	o[o.length] =     '<a:font script="Hant" typeface="新細明體"/>';
	o[o.length] =     '<a:font script="Arab" typeface="Arial"/>';
	o[o.length] =     '<a:font script="Hebr" typeface="Arial"/>';
	o[o.length] =     '<a:font script="Thai" typeface="Tahoma"/>';
	o[o.length] =     '<a:font script="Ethi" typeface="Nyala"/>';
	o[o.length] =     '<a:font script="Beng" typeface="Vrinda"/>';
	o[o.length] =     '<a:font script="Gujr" typeface="Shruti"/>';
	o[o.length] =     '<a:font script="Khmr" typeface="DaunPenh"/>';
	o[o.length] =     '<a:font script="Knda" typeface="Tunga"/>';
	o[o.length] =     '<a:font script="Guru" typeface="Raavi"/>';
	o[o.length] =     '<a:font script="Cans" typeface="Euphemia"/>';
	o[o.length] =     '<a:font script="Cher" typeface="Plantagenet Cherokee"/>';
	o[o.length] =     '<a:font script="Yiii" typeface="Microsoft Yi Baiti"/>';
	o[o.length] =     '<a:font script="Tibt" typeface="Microsoft Himalaya"/>';
	o[o.length] =     '<a:font script="Thaa" typeface="MV Boli"/>';
	o[o.length] =     '<a:font script="Deva" typeface="Mangal"/>';
	o[o.length] =     '<a:font script="Telu" typeface="Gautami"/>';
	o[o.length] =     '<a:font script="Taml" typeface="Latha"/>';
	o[o.length] =     '<a:font script="Syrc" typeface="Estrangelo Edessa"/>';
	o[o.length] =     '<a:font script="Orya" typeface="Kalinga"/>';
	o[o.length] =     '<a:font script="Mlym" typeface="Kartika"/>';
	o[o.length] =     '<a:font script="Laoo" typeface="DokChampa"/>';
	o[o.length] =     '<a:font script="Sinh" typeface="Iskoola Pota"/>';
	o[o.length] =     '<a:font script="Mong" typeface="Mongolian Baiti"/>';
	o[o.length] =     '<a:font script="Viet" typeface="Arial"/>';
	o[o.length] =     '<a:font script="Uigh" typeface="Microsoft Uighur"/>';
	o[o.length] =     '<a:font script="Geor" typeface="Sylfaen"/>';
	o[o.length] =    '</a:minorFont>';
	o[o.length] =   '</a:fontScheme>';

	o[o.length] =   '<a:fmtScheme name="Office">';
	o[o.length] =    '<a:fillStyleLst>';
	o[o.length] =     '<a:solidFill><a:schemeClr val="phClr"/></a:solidFill>';
	o[o.length] =     '<a:gradFill rotWithShape="1">';
	o[o.length] =      '<a:gsLst>';
	o[o.length] =       '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="50000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
	o[o.length] =       '<a:gs pos="35000"><a:schemeClr val="phClr"><a:tint val="37000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
	o[o.length] =       '<a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="15000"/><a:satMod val="350000"/></a:schemeClr></a:gs>';
	o[o.length] =      '</a:gsLst>';
	o[o.length] =      '<a:lin ang="16200000" scaled="1"/>';
	o[o.length] =     '</a:gradFill>';
	o[o.length] =     '<a:gradFill rotWithShape="1">';
	o[o.length] =      '<a:gsLst>';
	o[o.length] =       '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="100000"/><a:shade val="100000"/><a:satMod val="130000"/></a:schemeClr></a:gs>';
	o[o.length] =       '<a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="50000"/><a:shade val="100000"/><a:satMod val="350000"/></a:schemeClr></a:gs>';
	o[o.length] =      '</a:gsLst>';
	o[o.length] =      '<a:lin ang="16200000" scaled="0"/>';
	o[o.length] =     '</a:gradFill>';
	o[o.length] =    '</a:fillStyleLst>';
	o[o.length] =    '<a:lnStyleLst>';
	o[o.length] =     '<a:ln w="9525" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"><a:shade val="95000"/><a:satMod val="105000"/></a:schemeClr></a:solidFill><a:prstDash val="solid"/></a:ln>';
	o[o.length] =     '<a:ln w="25400" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/></a:ln>';
	o[o.length] =     '<a:ln w="38100" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/></a:ln>';
	o[o.length] =    '</a:lnStyleLst>';
	o[o.length] =    '<a:effectStyleLst>';
	o[o.length] =     '<a:effectStyle>';
	o[o.length] =      '<a:effectLst>';
	o[o.length] =       '<a:outerShdw blurRad="40000" dist="20000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="38000"/></a:srgbClr></a:outerShdw>';
	o[o.length] =      '</a:effectLst>';
	o[o.length] =     '</a:effectStyle>';
	o[o.length] =     '<a:effectStyle>';
	o[o.length] =      '<a:effectLst>';
	o[o.length] =       '<a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000"/></a:srgbClr></a:outerShdw>';
	o[o.length] =      '</a:effectLst>';
	o[o.length] =     '</a:effectStyle>';
	o[o.length] =     '<a:effectStyle>';
	o[o.length] =      '<a:effectLst>';
	o[o.length] =       '<a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000"/></a:srgbClr></a:outerShdw>';
	o[o.length] =      '</a:effectLst>';
	o[o.length] =      '<a:scene3d><a:camera prst="orthographicFront"><a:rot lat="0" lon="0" rev="0"/></a:camera><a:lightRig rig="threePt" dir="t"><a:rot lat="0" lon="0" rev="1200000"/></a:lightRig></a:scene3d>';
	o[o.length] =      '<a:sp3d><a:bevelT w="63500" h="25400"/></a:sp3d>';
	o[o.length] =     '</a:effectStyle>';
	o[o.length] =    '</a:effectStyleLst>';
	o[o.length] =    '<a:bgFillStyleLst>';
	o[o.length] =     '<a:solidFill><a:schemeClr val="phClr"/></a:solidFill>';
	o[o.length] =     '<a:gradFill rotWithShape="1">';
	o[o.length] =      '<a:gsLst>';
	o[o.length] =       '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="40000"/><a:satMod val="350000"/></a:schemeClr></a:gs>';
	o[o.length] =       '<a:gs pos="40000"><a:schemeClr val="phClr"><a:tint val="45000"/><a:shade val="99000"/><a:satMod val="350000"/></a:schemeClr></a:gs>';
	o[o.length] =       '<a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="20000"/><a:satMod val="255000"/></a:schemeClr></a:gs>';
	o[o.length] =      '</a:gsLst>';
	o[o.length] =      '<a:path path="circle"><a:fillToRect l="50000" t="-80000" r="50000" b="180000"/></a:path>';
	o[o.length] =     '</a:gradFill>';
	o[o.length] =     '<a:gradFill rotWithShape="1">';
	o[o.length] =      '<a:gsLst>';
	o[o.length] =       '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="80000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
	o[o.length] =       '<a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="30000"/><a:satMod val="200000"/></a:schemeClr></a:gs>';
	o[o.length] =      '</a:gsLst>';
	o[o.length] =      '<a:path path="circle"><a:fillToRect l="50000" t="50000" r="50000" b="50000"/></a:path>';
	o[o.length] =     '</a:gradFill>';
	o[o.length] =    '</a:bgFillStyleLst>';
	o[o.length] =   '</a:fmtScheme>';
	o[o.length] =  '</a:themeElements>';
S
SheetJS 已提交
8000

S
SheetJS 已提交
8001 8002 8003 8004 8005 8006
	o[o.length] =  '<a:objectDefaults>';
	o[o.length] =   '<a:spDef>';
	o[o.length] =    '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="1"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="3"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="2"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="lt1"/></a:fontRef></a:style>';
	o[o.length] =   '</a:spDef>';
	o[o.length] =   '<a:lnDef>';
	o[o.length] =    '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="2"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="0"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="1"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="tx1"/></a:fontRef></a:style>';
S
SheetJS 已提交
8007
	o[o.length] =   '</a:lnDef>';
S
SheetJS 已提交
8008 8009 8010 8011 8012
	o[o.length] =  '</a:objectDefaults>';
	o[o.length] =  '<a:extraClrSchemeLst/>';
	o[o.length] = '</a:theme>';
	return o.join("");
}
S
SheetJS 已提交
8013
/* [MS-XLS] 2.4.326 TODO: payload is a zip file */
S
SheetJS 已提交
8014
function parse_Theme(blob, length, opts) {
S
SheetJS 已提交
8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082
	var dwThemeVersion = blob.read_shift(4);
	if(dwThemeVersion === 124226) return;
	blob.l += length-4;
}

/* 2.5.49 */
function parse_ColorTheme(blob, length) { return blob.read_shift(4); }

/* 2.5.155 */
function parse_FullColorExt(blob, length) {
	var o = {};
	o.xclrType = blob.read_shift(2);
	o.nTintShade = blob.read_shift(2);
	switch(o.xclrType) {
		case 0: blob.l += 4; break;
		case 1: o.xclrValue = parse_IcvXF(blob, 4); break;
		case 2: o.xclrValue = parse_LongRGBA(blob, 4); break;
		case 3: o.xclrValue = parse_ColorTheme(blob, 4); break;
		case 4: blob.l += 4; break;
	}
	blob.l += 8;
	return o;
}

/* 2.5.164 TODO: read 7 bits*/
function parse_IcvXF(blob, length) {
	return parsenoop(blob, length);
}

/* 2.5.280 */
function parse_XFExtGradient(blob, length) {
	return parsenoop(blob, length);
}

/* 2.5.108 */
function parse_ExtProp(blob, length) {
	var extType = blob.read_shift(2);
	var cb = blob.read_shift(2);
	var o = [extType];
	switch(extType) {
		case 0x04: case 0x05: case 0x07: case 0x08:
		case 0x09: case 0x0A: case 0x0B: case 0x0D:
			o[1] = parse_FullColorExt(blob, cb); break;
		case 0x06: o[1] = parse_XFExtGradient(blob, cb); break;
		case 0x0E: case 0x0F: o[1] = blob.read_shift(cb === 5 ? 1 : 2); break;
		default: throw new Error("Unrecognized ExtProp type: " + extType + " " + cb);
	}
	return o;
}

/* 2.4.355 */
function parse_XFExt(blob, length) {
	var end = blob.l + length;
	blob.l += 2;
	var ixfe = blob.read_shift(2);
	blob.l += 2;
	var cexts = blob.read_shift(2);
	var ext = [];
	while(cexts-- > 0) ext.push(parse_ExtProp(blob, end-blob.l));
	return {ixfe:ixfe, ext:ext};
}

/* xf is an XF, see parse_XFExt for xfext */
function update_xfext(xf, xfext) {
	xfext.forEach(function(xfe) {
		switch(xfe[0]) { /* 2.5.108 extPropData */
			case 0x04: break; /* foreground color */
			case 0x05: break; /* background color */
S
SheetJS 已提交
8083 8084 8085 8086 8087 8088
			case 0x06: break; /* gradient fill */
			case 0x07: break; /* top cell border color */
			case 0x08: break; /* bottom cell border color */
			case 0x09: break; /* left cell border color */
			case 0x0a: break; /* right cell border color */
			case 0x0b: break; /* diagonal cell border color */
S
SheetJS 已提交
8089 8090
			case 0x0d: break; /* text color */
			case 0x0e: break; /* font scheme */
S
SheetJS 已提交
8091
			case 0x0f: break; /* indentation level */
S
SheetJS 已提交
8092 8093 8094 8095 8096 8097 8098
		}
	});
}

/* 18.6 Calculation Chain */
function parse_cc_xml(data, opts) {
	var d = [];
S
SheetJS 已提交
8099
	if(!data) return d;
S
SheetJS 已提交
8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132
	var l = 0, i = 1;
	(data.match(tagregex)||[]).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;
}

function write_cc_xml(data, opts) { }
/* [MS-XLSB] 2.6.4.1 */
function parse_BrtCalcChainItem$(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;
8133 8134 8135 8136 8137 8138
	recordhopper(data, function hopper_cc(val, R_n, RT) {
		switch(RT) {
			case 0x003F: /* 'BrtCalcChainItem$' */
				out.push(val); break;

			default:
S
SheetJS 已提交
8139 8140
				if((R_n||"").indexOf("Begin") > 0){/* empty */}
				else if((R_n||"").indexOf("End") > 0){/* empty */}
8141
				else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
S
SheetJS 已提交
8142 8143 8144 8145 8146 8147
		}
	});
	return out;
}

function write_cc_bin(data, opts) { }
S
SheetJS 已提交
8148 8149
RELS.IMG = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
RELS.DRAW = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing";
8150 8151 8152 8153 8154 8155 8156 8157 8158 8159
/* 20.5 DrawingML - SpreadsheetML Drawing */
function parse_drawing(data, rels/*:any*/) {
	if(!data) return "??";
	/*
	  Chartsheet Drawing:
	   - 20.5.2.35 wsDr CT_Drawing
	    - 20.5.2.1  absoluteAnchor CT_AbsoluteAnchor
	     - 20.5.2.16 graphicFrame CT_GraphicalObjectFrame
	      - 20.1.2.2.16 graphic CT_GraphicalObject
	       - 20.1.2.2.17 graphicData CT_GraphicalObjectData
S
SheetJS 已提交
8160 8161
          - chart reference
	   the actual type is based on the URI of the graphicData
8162 8163 8164 8165 8166 8167
		TODO: handle embedded charts and other types of graphics
	*/
	var id = (data.match(/<c:chart [^>]*r:id="([^"]*)"/)||["",""])[1];

	return rels['!id'][id].Target;
}
S
SheetJS 已提交
8168

S
SheetJS 已提交
8169 8170 8171 8172 8173 8174 8175 8176 8177 8178 8179 8180 8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204
/* L.5.5.2 SpreadsheetML Comments + VML Schema */
var _shapeid = 1024;
function write_comments_vml(rId, comments) {
	var csize = [21600, 21600];
	/* L.5.2.1.2 Path Attribute */
	var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(",");
	var o = [
		writextag("xml", null, { 'xmlns:v': XLMLNS.v, 'xmlns:o': XLMLNS.o, 'xmlns:x': XLMLNS.x, 'xmlns:mv': XLMLNS.mv }).replace(/\/>/,">"),
		writextag("o:shapelayout", writextag("o:idmap", null, {'v:ext':"edit", 'data':rId}), {'v:ext':"edit"}),
		writextag("v:shapetype", [
			writextag("v:stroke", null, {joinstyle:"miter"}),
			writextag("v:path", null, {gradientshapeok:"t", 'o:connecttype':"rect"})
		].join(""), {id:"_x0000_t202", 'o:spt':202, coordsize:csize.join(","),path:bbox})
	];
	while(_shapeid < rId * 1000) _shapeid += 1000;

	comments.map(function(x) { return decode_cell(x[0]); }).forEach(function(c,i) { o = o.concat([
	'<v:shape' + wxt_helper({
		id:'_x0000_s' + (++_shapeid),
		type:"#_x0000_t202",
		style:"position:absolute; margin-left:80pt;margin-top:5pt;width:104pt;height:64pt;z-index:10;visibility:hidden",
		fillcolor:"#ECFAD4",
		strokecolor:"#edeaa1"
	}) + '>',
		writextag('v:fill', writextag("o:fill", null, {type:"gradientUnscaled", 'v:ext':"view"}), {'color2':"#BEFF82", 'angle':"-180", 'type':"gradient"}),
		writextag("v:shadow", null, {on:"t", 'obscured':"t"}),
		writextag("v:path", null, {'o:connecttype':"none"}),
		'<v:textbox><div style="text-align:left"></div></v:textbox>',
		'<x:ClientData ObjectType="Note">',
			'<x:MoveWithCells/>',
			'<x:SizeWithCells/>',
			/* Part 4 19.4.2.3 Anchor (Anchor) */
			writetag('x:Anchor', [c.c, 0, c.r, 0, c.c+3, 100, c.r+5, 100].join(",")),
			writetag('x:AutoFill', "False"),
			writetag('x:Row', String(c.r)),
			writetag('x:Column', String(c.c)),
S
SheetJS 已提交
8205
			'<x:Visible/>',
S
SheetJS 已提交
8206 8207 8208 8209 8210 8211 8212 8213
		'</x:ClientData>',
	'</v:shape>'
	]); });
	o.push('</xml>');
	return o.join("");
}

RELS.CMNT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
S
SheetJS 已提交
8214 8215 8216 8217 8218 8219 8220 8221 8222 8223 8224 8225 8226 8227 8228 8229 8230 8231 8232 8233

function parse_comments(zip, dirComments, sheets, sheetRels, opts) {
	for(var i = 0; i != dirComments.length; ++i) {
		var canonicalpath=dirComments[i];
		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 = keys(sheets);
		for(var j = 0; j != sheetNames.length; ++j) {
			var sheetName = sheetNames[j];
			var rels = sheetRels[sheetName];
			if(rels) {
				var rel = rels[canonicalpath];
				if(rel) insertCommentsIntoSheet(sheetName, sheets[sheetName], comments);
			}
		}
	}
}

function insertCommentsIntoSheet(sheetName, sheet, comments) {
S
SheetJS 已提交
8234 8235
	var dense = Array.isArray(sheet);
	var cell, r;
S
SheetJS 已提交
8236
	comments.forEach(function(comment) {
S
SheetJS 已提交
8237 8238 8239 8240 8241
		if(dense) {
			r = decode_cell(comment.ref);
			if(!sheet[r.r]) sheet[r.r] = [];
			cell = sheet[r.r][r.c];
		} else cell = sheet[comment.ref];
S
SheetJS 已提交
8242 8243
		if (!cell) {
			cell = {};
S
SheetJS 已提交
8244 8245
			if(dense) sheet[r.r][r.c] = cell;
			else sheet[comment.ref] = cell;
S
SheetJS 已提交
8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256
			var range = safe_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;
			if(range.s.c > thisCell.c) range.s.c = thisCell.c;
			if(range.e.c < thisCell.c) range.e.c = thisCell.c;
			var encoded = encode_range(range);
			if (encoded !== sheet["!ref"]) sheet["!ref"] = encoded;
		}

		if (!cell.c) cell.c = [];
S
SheetJS 已提交
8257
		var o = ({a: comment.author, t: comment.t, r: comment.r}/*:any*/);
S
SheetJS 已提交
8258 8259 8260 8261 8262
		if(comment.h) o.h = comment.h;
		cell.c.push(o);
	});
}

S
SheetJS 已提交
8263
/* 18.7 Comments */
S
SheetJS 已提交
8264
function parse_comments_xml(data/*:string*/, opts)/*:Array<Comment>*/ {
S
SheetJS 已提交
8265
	/* 18.7.6 CT_Comments */
S
SheetJS 已提交
8266 8267 8268
	if(data.match(/<(?:\w+:)?comments *\/>/)) return [];
	var authors = [];
	var commentList = [];
S
SheetJS 已提交
8269
	var authtag = data.match(/<(?:\w+:)?authors>([\s\S]*)<\/(?:\w+:)?authors>/);
S
SheetJS 已提交
8270
	if(authtag && authtag[1]) authtag[1].split(/<\/\w*:?author>/).forEach(function(x) {
S
SheetJS 已提交
8271
		if(x === "" || x.trim() === "") return;
S
SheetJS 已提交
8272 8273
		var a = x.match(/<(?:\w+:)?author[^>]*>(.*)/);
		if(a) authors.push(a[1]);
S
SheetJS 已提交
8274
	});
S
SheetJS 已提交
8275
	var cmnttag = data.match(/<(?:\w+:)?commentList>([\s\S]*)<\/(?:\w+:)?commentList>/);
S
SheetJS 已提交
8276
	if(cmnttag && cmnttag[1]) cmnttag[1].split(/<\/\w*:?comment>/).forEach(function(x, index) {
S
SheetJS 已提交
8277
		if(x === "" || x.trim() === "") return;
S
SheetJS 已提交
8278 8279 8280
		var cm = x.match(/<(?:\w+:)?comment[^>]*>/);
		if(!cm) return;
		var y = parsexmltag(cm[0]);
S
SheetJS 已提交
8281
		var comment/*:Comment*/ = ({ author: y.authorId && authors[y.authorId] ? authors[y.authorId] : "sheetjsghost", ref: y.ref, guid: y.guid }/*:any*/);
S
SheetJS 已提交
8282 8283
		var cell = decode_cell(y.ref);
		if(opts.sheetRows && opts.sheetRows <= cell.r) return;
S
SheetJS 已提交
8284
		var textMatch = x.match(/<(?:\w+:)?text>([\s\S]*)<\/(?:\w+:)?text>/);
S
TXT/PRN  
SheetJS 已提交
8285
		var rt = !!textMatch && !!textMatch[1] && parse_si(textMatch[1]) || {r:"",t:"",h:""};
S
SheetJS 已提交
8286
		comment.r = rt.r;
S
TXT/PRN  
SheetJS 已提交
8287
		if(rt.r == "<t></t>") rt.t = rt.h = "";
S
SheetJS 已提交
8288
		comment.t = rt.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n");
S
SheetJS 已提交
8289 8290 8291 8292 8293 8294
		if(opts.cellHTML) comment.h = rt.h;
		commentList.push(comment);
	});
	return commentList;
}

S
SheetJS 已提交
8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313
var CMNT_XML_ROOT = writextag('comments', null, { 'xmlns': XMLNS.main[0] });
function write_comments_xml(data, opts) {
	var o = [XML_HEADER, CMNT_XML_ROOT];

	var iauthor = [];
	o.push("<authors>");
	data.map(function(x) { return x[1]; }).forEach(function(comment) {
		comment.map(function(x) { return escapexml(x.a); }).forEach(function(a) {
			if(iauthor.indexOf(a) > -1) return;
			iauthor.push(a);
			o.push("<author>" + a + "</author>");
		});
	});
	o.push("</authors>");
	o.push("<commentList>");
	data.forEach(function(d) {
		d[1].forEach(function(c) {
			/* 18.7.3 CT_Comment */
			o.push('<comment ref="' + d[0] + '" authorId="' + iauthor.indexOf(escapexml(c.a)) + '"><text>');
S
TXT/PRN  
SheetJS 已提交
8314
			o.push(writetag("t", c.t == null ? "" : c.t));
S
SheetJS 已提交
8315 8316 8317 8318 8319 8320 8321
			o.push('</text></comment>');
		});
	});
	o.push("</commentList>");
	if(o.length>2) { o[o.length] = ('</comments>'); o[1]=o[1].replace("/>",">"); }
	return o.join("");
}
S
SheetJS 已提交
8322
/* [MS-XLSB] 2.4.28 BrtBeginComment */
S
SheetJS 已提交
8323
function parse_BrtBeginComment(data, length/*:number*/) {
S
SheetJS 已提交
8324 8325 8326 8327 8328 8329 8330 8331
	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;
}
S
SheetJS 已提交
8332 8333 8334
function write_BrtBeginComment(data, o) {
	if(o == null) o = new_buf(36);
	o.write_shift(4, data[1].iauthor);
S
TXT/PRN  
SheetJS 已提交
8335
	write_UncheckedRfX((data[0]/*:any*/), o);
S
SheetJS 已提交
8336 8337 8338 8339 8340 8341
	o.write_shift(4, 0);
	o.write_shift(4, 0);
	o.write_shift(4, 0);
	o.write_shift(4, 0);
	return o;
}
S
SheetJS 已提交
8342 8343 8344

/* [MS-XLSB] 2.4.324 BrtCommentAuthor */
var parse_BrtCommentAuthor = parse_XLWideString;
S
SheetJS 已提交
8345
function write_BrtCommentAuthor(data) { return write_XLWideString(data.substr(0, 54)); }
S
SheetJS 已提交
8346 8347 8348 8349 8350 8351 8352

/* [MS-XLSB] 2.1.7.8 Comments */
function parse_comments_bin(data, opts) {
	var out = [];
	var authors = [];
	var c = {};
	var pass = false;
8353 8354 8355 8356 8357 8358 8359 8360 8361
	recordhopper(data, function hopper_cmnt(val, R_n, RT) {
		switch(RT) {
			case 0x0278: /* 'BrtCommentAuthor' */
				authors.push(val); break;
			case 0x027B: /* 'BrtBeginComment' */
				c = val; break;
			case 0x027D: /* 'BrtCommentText' */
				c.t = val.t; c.h = val.h; c.r = val.r; break;
			case 0x027C: /* 'BrtEndComment' */
S
SheetJS 已提交
8362 8363 8364
				c.author = authors[c.iauthor];
				delete c.iauthor;
				if(opts.sheetRows && opts.sheetRows <= c.rfx.r) break;
S
SheetJS 已提交
8365
				if(!c.t) c.t = "";
S
SheetJS 已提交
8366
				delete c.rfx; out.push(c); break;
S
SheetJS 已提交
8367

8368 8369 8370 8371 8372 8373 8374 8375 8376
			/* case 'BrtUid': */

			case 0x0023: /* 'BrtFRTBegin' */
				pass = true; break;
			case 0x0024: /* 'BrtFRTEnd' */
				pass = false; break;
			case 0x0025: /* 'BrtACBegin' */ break;
			case 0x0026: /* 'BrtACEnd' */ break;

S
SheetJS 已提交
8377 8378

			default:
S
SheetJS 已提交
8379 8380
				if((R_n||"").indexOf("Begin") > 0){/* empty */}
				else if((R_n||"").indexOf("End") > 0){/* empty */}
8381
				else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
S
SheetJS 已提交
8382 8383 8384 8385 8386
		}
	});
	return out;
}

S
SheetJS 已提交
8387 8388 8389 8390 8391 8392 8393 8394 8395 8396
function write_comments_bin(data, opts) {
	var ba = buf_array();
	var iauthor = [];
	write_record(ba, "BrtBeginComments");
	{ /* COMMENTAUTHORS */
		write_record(ba, "BrtBeginCommentAuthors");
		data.forEach(function(comment) {
			comment[1].forEach(function(c) {
				if(iauthor.indexOf(c.a) > -1) return;
				iauthor.push(c.a.substr(0,54));
S
SheetJS 已提交
8397
				write_record(ba, "BrtCommentAuthor", write_BrtCommentAuthor(c.a));
S
SheetJS 已提交
8398 8399 8400 8401 8402 8403 8404 8405 8406
			});
		});
		write_record(ba, "BrtEndCommentAuthors");
	}
	{ /* COMMENTLIST */
		write_record(ba, "BrtBeginCommentList");
		data.forEach(function(comment) {
			comment[1].forEach(function(c) {
				c.iauthor = iauthor.indexOf(c.a);
S
TXT/PRN  
SheetJS 已提交
8407
				var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])};
S
SheetJS 已提交
8408
				write_record(ba, "BrtBeginComment", write_BrtBeginComment([range, c]));
S
SheetJS 已提交
8409
				if(c.t && c.t.length > 0) write_record(ba, "BrtCommentText", write_BrtCommentText(c));
S
SheetJS 已提交
8410 8411 8412 8413 8414 8415 8416 8417 8418
				write_record(ba, "BrtEndComment");
				delete c.iauthor;
			});
		});
		write_record(ba, "BrtEndCommentList");
	}
	write_record(ba, "BrtEndComments");
	return ba.end();
}
S
SheetJS 已提交
8419 8420 8421 8422
RELS.DS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet";
RELS.MS = "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet";

/* macro and dialog sheet stubs */
8423 8424 8425 8426
function parse_ds_bin(data/*:any*/, opts, rels, wb, themes, styles)/*:Worksheet*/ { return {'!type':'dialog'}; }
function parse_ds_xml(data/*:any*/, opts, rels, wb, themes, styles)/*:Worksheet*/ { return {'!type':'dialog'}; }
function parse_ms_bin(data/*:any*/, opts, rels, wb, themes, styles)/*:Worksheet*/ { return {'!type':'macro'}; }
function parse_ms_xml(data/*:any*/, opts, rels, wb, themes, styles)/*:Worksheet*/ { return {'!type':'macro'}; }
S
SheetJS 已提交
8427 8428 8429
/* TODO: it will be useful to parse the function str */
var rc_to_a1 = (function(){
	var rcregex = /(^|[^A-Za-z])R(\[?)(-?\d+|)\]?C(\[?)(-?\d+|)\]?/g;
S
SheetJS 已提交
8430
	var rcbase/*:Cell*/ = ({r:0,c:0}/*:any*/);
S
SheetJS 已提交
8431 8432 8433
	function rcfunc($$,$1,$2,$3,$4,$5) {
		var R = $3.length>0?parseInt($3,10)|0:0, C = $5.length>0?parseInt($5,10)|0:0;
		if(C<0 && $4.length === 0) C=0;
S
SheetJS 已提交
8434 8435 8436 8437
		var cRel = false, rRel = false;
		if($4.length > 0 || $5.length == 0) cRel = true; if(cRel) C += rcbase.c; else --C;
		if($2.length > 0 || $3.length == 0) rRel = true; if(rRel) R += rcbase.r; else --R;
		return $1 + (cRel ? "" : "$") + encode_col(C) + (rRel ? "" : "$") + encode_row(R);
S
SheetJS 已提交
8438
	}
S
SheetJS 已提交
8439
	return function rc_to_a1(fstr/*:string*/, base/*:Cell*/)/*:string*/ {
S
SheetJS 已提交
8440 8441 8442 8443 8444
		rcbase = base;
		return fstr.replace(rcregex, rcfunc);
	};
})();

S
SheetJS 已提交
8445
var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)([1-9]\d{0,5}|10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6])(?![_.\(A-Za-z0-9])/g;
S
SheetJS 已提交
8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457
var a1_to_rc =(function(){
	return function a1_to_rc(fstr, base) {
		return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
			/* TODO: handle fixcol / fixrow */
			var c = decode_col($3) - base.c;
			var r = decode_row($5) - base.r;
			return $1 + "R" + (r == 0 ? "" : "[" + r + "]") + "C" + (c == 0 ? "" : "[" + c + "]");
		});
	};
})();

/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
S
SheetJS 已提交
8458
function shift_formula_str(f/*:string*/, delta/*:Cell*/)/*:string*/ {
S
SheetJS 已提交
8459
	return f.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
S
SheetJS 已提交
8460 8461 8462 8463 8464 8465 8466 8467 8468
		return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
	});
}

function shift_formula_xlsx(f/*:string*/, range/*:string*/, cell/*:string*/)/*:string*/ {
	var r = decode_range(range), s = r.s, c = decode_cell(cell);
	var delta = {r:c.r - s.r, c:c.c - s.c};
	return shift_formula_str(f, delta);
}
S
SheetJS 已提交
8469 8470 8471
/* --- formula references point to MS-XLS --- */
/* Small helpers */
function parseread(l) { return function(blob, length) { blob.l+=l; return; }; }
S
SheetJS 已提交
8472
function parseread1(blob) { blob.l+=1; return; }
S
SheetJS 已提交
8473 8474 8475 8476 8477

/* Rgce Helpers */

/* 2.5.51 */
function parse_ColRelU(blob, length) {
S
SheetJS 已提交
8478
	var c = blob.read_shift(length == 1 ? 1 : 2);
S
SheetJS 已提交
8479 8480 8481
	return [c & 0x3FFF, (c >> 14) & 1, (c >> 15) & 1];
}

S
SheetJS 已提交
8482 8483 8484 8485 8486 8487 8488 8489 8490
/* [MS-XLS] 2.5.198.105 */
/* [MS-XLSB] 2.5.97.89 */
function parse_RgceArea(blob, length, opts) {
	var w = 2;
	if(opts) {
		if(opts.biff >= 2 && opts.biff <= 5) return parse_RgceArea_BIFF2(blob, length, opts);
		else if(opts.biff == 12) w = 4;
	}
	var r=blob.read_shift(w), R=blob.read_shift(w);
S
SheetJS 已提交
8491 8492 8493 8494
	var c=parse_ColRelU(blob, 2);
	var C=parse_ColRelU(blob, 2);
	return { s:{r:r, c:c[0], cRel:c[1], rRel:c[2]}, e:{r:R, c:C[0], cRel:C[1], rRel:C[2]} };
}
S
SheetJS 已提交
8495
/* BIFF 2-5 encodes flags in the row field */
8496
function parse_RgceArea_BIFF2(blob/*::, length, opts*/) {
S
SheetJS 已提交
8497 8498 8499 8500 8501
	var r=parse_ColRelU(blob, 2), R=parse_ColRelU(blob, 2);
	var c=blob.read_shift(1);
	var C=blob.read_shift(1);
	return { s:{r:r[0], c:c, cRel:r[1], rRel:r[2]}, e:{r:R[0], c:C, cRel:R[1], rRel:R[2]} };
}
S
SheetJS 已提交
8502 8503

/* 2.5.198.105 TODO */
8504
function parse_RgceAreaRel(blob, length/*::, opts*/) {
S
SheetJS 已提交
8505
	var r=blob.read_shift(length == 12 ? 4 : 2), R=blob.read_shift(length == 12 ? 4 : 2);
S
SheetJS 已提交
8506 8507 8508 8509 8510 8511
	var c=parse_ColRelU(blob, 2);
	var C=parse_ColRelU(blob, 2);
	return { s:{r:r, c:c[0], cRel:c[1], rRel:c[2]}, e:{r:R, c:C[0], cRel:C[1], rRel:C[2]} };
}

/* 2.5.198.109 */
S
SheetJS 已提交
8512 8513 8514
function parse_RgceLoc(blob, length, opts) {
	if(opts && opts.biff >= 2 && opts.biff <= 5) return parse_RgceLoc_BIFF2(blob, length, opts);
	var r = blob.read_shift(opts && opts.biff == 12 ? 4 : 2);
S
SheetJS 已提交
8515 8516 8517
	var c = parse_ColRelU(blob, 2);
	return {r:r, c:c[0], cRel:c[1], rRel:c[2]};
}
S
SheetJS 已提交
8518 8519 8520 8521 8522
function parse_RgceLoc_BIFF2(blob, length, opts) {
	var r = parse_ColRelU(blob, 2);
	var c = blob.read_shift(1);
	return {r:r[0], c:c, cRel:r[1], rRel:r[2]};
}
S
SheetJS 已提交
8523

S
SheetJS 已提交
8524 8525 8526 8527 8528 8529
/* [MS-XLS] 2.5.198.111 TODO */
/* [MS-XLSB] 2.5.97.92 TODO */
function parse_RgceLocRel(blob, length, opts) {
	var biff = opts && opts.biff ? opts.biff : 8;
	if(biff >= 2 && biff <= 5) return parse_RgceLocRel_BIFF2(blob, length, opts);
	var r = blob.read_shift(biff >= 12 ? 4 : 2);
S
SheetJS 已提交
8530 8531 8532
	var cl = blob.read_shift(2);
	var cRel = (cl & 0x8000) >> 15, rRel = (cl & 0x4000) >> 14;
	cl &= 0x3FFF;
S
SheetJS 已提交
8533 8534
	if(rRel == 1) while(r > 0x7FFFF) r -= 0x100000;
	if(cRel == 1) while(cl > 0x1FFF) cl = cl - 0x4000;
S
SheetJS 已提交
8535 8536
	return {r:r,c:cl,cRel:cRel,rRel:rRel};
}
8537
function parse_RgceLocRel_BIFF2(blob, length/*::, opts*/) {
S
SheetJS 已提交
8538 8539 8540 8541 8542 8543 8544 8545
	var rl = blob.read_shift(2);
	var c = blob.read_shift(1);
	var rRel = (rl & 0x8000) >> 15, cRel = (rl & 0x4000) >> 14;
	rl &= 0x3FFF;
	if(rRel == 1 && rl >= 0x2000) rl = rl - 0x4000;
	if(cRel == 1 && c >= 0x80) c = c - 0x100;
	return {r:rl,c:c,cRel:cRel,rRel:rRel};
}
S
SheetJS 已提交
8546 8547 8548 8549

/* Ptg Tokens */

/* 2.5.198.27 */
S
SheetJS 已提交
8550
function parse_PtgArea(blob, length, opts) {
S
SheetJS 已提交
8551
	var type = (blob[blob.l++] & 0x60) >> 5;
S
SheetJS 已提交
8552
	var area = parse_RgceArea(blob, opts.biff >= 2 && opts.biff <= 5 ? 6 : 8, opts);
S
SheetJS 已提交
8553 8554 8555
	return [type, area];
}

S
SheetJS 已提交
8556 8557 8558
/* [MS-XLS] 2.5.198.28 */
/* [MS-XLSB] 2.5.97.19 */
function parse_PtgArea3d(blob, length, opts) {
S
SheetJS 已提交
8559
	var type = (blob[blob.l++] & 0x60) >> 5;
S
SheetJS 已提交
8560 8561 8562 8563 8564 8565 8566
	var ixti = blob.read_shift(2, 'i');
	var w = 8;
	if(opts) switch(opts.biff) {
		case 5: blob.l += 12; w = 6; break;
		case 12: w = 12; break;
	}
	var area = parse_RgceArea(blob, w, opts);
S
SheetJS 已提交
8567 8568 8569 8570
	return [type, ixti, area];
}

/* 2.5.198.29 */
S
SheetJS 已提交
8571
function parse_PtgAreaErr(blob, length, opts) {
S
SheetJS 已提交
8572
	var type = (blob[blob.l++] & 0x60) >> 5;
S
SheetJS 已提交
8573
	blob.l += opts && opts.biff > 8 ? 12 : 8;
S
SheetJS 已提交
8574 8575 8576
	return [type];
}
/* 2.5.198.30 */
S
SheetJS 已提交
8577
function parse_PtgAreaErr3d(blob, length, opts) {
S
SheetJS 已提交
8578 8579
	var type = (blob[blob.l++] & 0x60) >> 5;
	var ixti = blob.read_shift(2);
S
SheetJS 已提交
8580 8581 8582 8583 8584 8585
	var w = 8;
	if(opts) switch(opts.biff) {
		case 5: blob.l += 12; w = 6; break;
		case 12: w = 12; break;
	}
	blob.l += w;
S
SheetJS 已提交
8586 8587 8588 8589
	return [type, ixti];
}

/* 2.5.198.31 */
S
SheetJS 已提交
8590
function parse_PtgAreaN(blob, length, opts) {
S
SheetJS 已提交
8591
	var type = (blob[blob.l++] & 0x60) >> 5;
S
SheetJS 已提交
8592
	var area = parse_RgceAreaRel(blob, opts && opts.biff > 8 ? 12 : 8, opts);
S
SheetJS 已提交
8593 8594 8595
	return [type, area];
}

S
SheetJS 已提交
8596 8597 8598
/* [MS-XLS] 2.5.198.32 */
/* [MS-XLSB] 2.5.97.23 */
function parse_PtgArray(blob, length, opts) {
S
SheetJS 已提交
8599
	var type = (blob[blob.l++] & 0x60) >> 5;
S
SheetJS 已提交
8600
	blob.l += opts.biff == 2 ? 6 : opts.biff == 12 ? 14 : 7;
S
SheetJS 已提交
8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611 8612
	return [type];
}

/* 2.5.198.33 */
function parse_PtgAttrBaxcel(blob, length) {
	var bitSemi = blob[blob.l+1] & 0x01; /* 1 = volatile */
	var bitBaxcel = 1;
	blob.l += 4;
	return [bitSemi, bitBaxcel];
}

/* 2.5.198.34 */
S
SheetJS 已提交
8613
function parse_PtgAttrChoose(blob, length, opts) {
S
SheetJS 已提交
8614
	blob.l +=2;
S
SheetJS 已提交
8615
	var offset = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
S
SheetJS 已提交
8616 8617
	var o = [];
	/* offset is 1 less than the number of elements */
S
SheetJS 已提交
8618
	for(var i = 0; i <= offset; ++i) o.push(blob.read_shift(opts && opts.biff == 2 ? 1 : 2));
S
SheetJS 已提交
8619 8620 8621 8622
	return o;
}

/* 2.5.198.35 */
S
SheetJS 已提交
8623
function parse_PtgAttrGoto(blob, length, opts) {
S
SheetJS 已提交
8624 8625
	var bitGoto = (blob[blob.l+1] & 0xFF) ? 1 : 0;
	blob.l += 2;
S
SheetJS 已提交
8626
	return [bitGoto, blob.read_shift(opts && opts.biff == 2 ? 1 : 2)];
S
SheetJS 已提交
8627 8628 8629
}

/* 2.5.198.36 */
S
SheetJS 已提交
8630 8631 8632 8633 8634 8635 8636 8637
function parse_PtgAttrIf(blob, length, opts) {
	var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0;
	blob.l += 2;
	return [bitIf, blob.read_shift(opts && opts.biff == 2 ? 1 : 2)];
}

/* [MS-XLSB] 2.5.97.28 */
function parse_PtgAttrIfError(blob, length) {
S
SheetJS 已提交
8638 8639 8640 8641 8642 8643
	var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0;
	blob.l += 2;
	return [bitIf, blob.read_shift(2)];
}

/* 2.5.198.37 */
S
SheetJS 已提交
8644
function parse_PtgAttrSemi(blob, length, opts) {
S
SheetJS 已提交
8645
	var bitSemi = (blob[blob.l+1] & 0xFF) ? 1 : 0;
S
SheetJS 已提交
8646
	blob.l += opts && opts.biff == 2 ? 3 : 4;
S
SheetJS 已提交
8647 8648 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 8668
	return [bitSemi];
}

/* 2.5.198.40 (used by PtgAttrSpace and PtgAttrSpaceSemi) */
function parse_PtgAttrSpaceType(blob, length) {
	var type = blob.read_shift(1), cch = blob.read_shift(1);
	return [type, cch];
}

/* 2.5.198.38 */
function parse_PtgAttrSpace(blob, length) {
	blob.read_shift(2);
	return parse_PtgAttrSpaceType(blob, 2);
}

/* 2.5.198.39 */
function parse_PtgAttrSpaceSemi(blob, length) {
	blob.read_shift(2);
	return parse_PtgAttrSpaceType(blob, 2);
}

/* 2.5.198.84 TODO */
S
SheetJS 已提交
8669
function parse_PtgRef(blob, length, opts) {
S
SheetJS 已提交
8670 8671 8672
	var ptg = blob[blob.l] & 0x1F;
	var type = (blob[blob.l] & 0x60)>>5;
	blob.l += 1;
S
SheetJS 已提交
8673
	var loc = parse_RgceLoc(blob, 0, opts);
S
SheetJS 已提交
8674 8675 8676 8677
	return [type, loc];
}

/* 2.5.198.88 TODO */
S
SheetJS 已提交
8678
function parse_PtgRefN(blob, length, opts) {
S
SheetJS 已提交
8679 8680
	var type = (blob[blob.l] & 0x60)>>5;
	blob.l += 1;
S
SheetJS 已提交
8681
	var loc = parse_RgceLocRel(blob, 0, opts);
S
SheetJS 已提交
8682 8683 8684 8685
	return [type, loc];
}

/* 2.5.198.85 TODO */
S
SheetJS 已提交
8686
function parse_PtgRef3d(blob, length, opts) {
S
SheetJS 已提交
8687 8688 8689
	var type = (blob[blob.l] & 0x60)>>5;
	blob.l += 1;
	var ixti = blob.read_shift(2); // XtiIndex
S
SheetJS 已提交
8690
	var loc = parse_RgceLoc(blob, 0, opts); // TODO: or RgceLocRel
S
SheetJS 已提交
8691 8692 8693 8694 8695
	return [type, ixti, loc];
}


/* 2.5.198.62 TODO */
S
SheetJS 已提交
8696
function parse_PtgFunc(blob, length, opts) {
S
SheetJS 已提交
8697 8698 8699
	var ptg = blob[blob.l] & 0x1F;
	var type = (blob[blob.l] & 0x60)>>5;
	blob.l += 1;
S
SheetJS 已提交
8700 8701
	var iftab = blob.read_shift(opts && opts.biff <= 3 ? 1 : 2);
	return [FtabArgc[iftab], Ftab[iftab], type];
S
SheetJS 已提交
8702 8703
}
/* 2.5.198.63 TODO */
S
SheetJS 已提交
8704
function parse_PtgFuncVar(blob, length, opts) {
S
SheetJS 已提交
8705
	blob.l++;
S
SheetJS 已提交
8706
	var cparams = blob.read_shift(1), tab = opts && opts.biff <= 3 ? [0, blob.read_shift(1)]: parsetab(blob);
S
SheetJS 已提交
8707 8708 8709 8710 8711 8712 8713 8714
	return [cparams, (tab[0] === 0 ? Ftab : Cetab)[tab[1]]];
}

function parsetab(blob, length) {
	return [blob[blob.l+1]>>7, blob.read_shift(2) & 0x7FFF];
}

/* 2.5.198.41 */
S
SheetJS 已提交
8715 8716 8717 8718
function parse_PtgAttrSum(blob, length, opts) {
	blob.l += opts && opts.biff == 2 ? 3 : 4; return;
}

S
SheetJS 已提交
8719 8720 8721 8722
/* 2.5.198.43 */
var parse_PtgConcat = parseread1;

/* 2.5.198.58 */
S
SheetJS 已提交
8723
function parse_PtgExp(blob, length, opts) {
S
SheetJS 已提交
8724
	blob.l++;
S
SheetJS 已提交
8725
	if(opts && opts.biff == 12) return [blob.read_shift(4, 'i'), 0];
S
SheetJS 已提交
8726
	var row = blob.read_shift(2);
S
SheetJS 已提交
8727
	var col = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
S
SheetJS 已提交
8728 8729 8730 8731 8732 8733
	return [row, col];
}

/* 2.5.198.57 */
function parse_PtgErr(blob, length) { blob.l++; return BErr[blob.read_shift(1)]; }

S
SheetJS 已提交
8734
/* 2.5.198.66 */
S
SheetJS 已提交
8735 8736 8737 8738 8739 8740 8741 8742 8743
function parse_PtgInt(blob, length) { blob.l++; return blob.read_shift(2); }

/* 2.5.198.42 */
function parse_PtgBool(blob, length) { blob.l++; return blob.read_shift(1)!==0;}

/* 2.5.198.79 */
function parse_PtgNum(blob, length) { blob.l++; return parse_Xnum(blob, 8); }

/* 2.5.198.89 */
S
SheetJS 已提交
8744 8745 8746 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756
function parse_PtgStr(blob, length, opts) { blob.l++; return parse_ShortXLUnicodeString(blob, length-1, opts); }

/* [MS-XLS] 2.5.192.112 + 2.5.192.11{3,4,5,6,7} */
/* [MS-XLSB] 2.5.97.93 + 2.5.97.9{4,5,6,7} */
function parse_SerAr(blob, biff/*:number*/) {
	var val = [blob.read_shift(1)];
	if(biff == 12) switch(val[0]) {
		case 0x02: val[0] = 0x04; break; /* SerBool */
		case 0x04: val[0] = 0x10; break; /* SerErr */
		case 0x00: val[0] = 0x01; break; /* SerNum */
		case 0x01: val[0] = 0x02; break; /* SerStr */
	}
	switch(val[0]) {
S
SheetJS 已提交
8757 8758 8759 8760 8761 8762 8763 8764 8765 8766 8767 8768 8769 8770 8771 8772
		/* 2.5.192.113 */
		case 0x04: /* SerBool -- boolean */
			val[1] = parsebool(blob, 1) ? 'TRUE' : 'FALSE';
			blob.l += 7; break;
		/* 2.5.192.114 */
		case 0x10: /* SerErr -- error */
			val[1] = BErr[blob[blob.l]];
			blob.l += 8; break;
		/* 2.5.192.115 */
		case 0x00: /* SerNil -- honestly, I'm not sure how to reproduce this */
			blob.l += 8; break;
		/* 2.5.192.116 */
		case 0x01: /* SerNum -- Xnum */
			val[1] = parse_Xnum(blob, 8); break;
		/* 2.5.192.117 */
		case 0x02: /* SerStr -- XLUnicodeString (<256 chars) */
S
SheetJS 已提交
8773
			val[1] = parse_XLUnicodeString2(blob, 0, {biff:biff > 0 && biff < 8 ? 2 : biff}); break;
S
SheetJS 已提交
8774 8775 8776 8777 8778 8779 8780 8781 8782 8783 8784 8785 8786 8787
		// default: throw "Bad SerAr: " + val[0]; /* Unreachable */
	}
	return val;
}

/* 2.5.198.61 */
function parse_PtgExtraMem(blob, cce) {
	var count = blob.read_shift(2);
	var out = [];
	for(var i = 0; i != count; ++i) out.push(parse_Ref8U(blob, 8));
	return out;
}

/* 2.5.198.59 */
S
SheetJS 已提交
8788 8789 8790 8791 8792 8793 8794 8795 8796 8797
function parse_PtgExtraArray(blob, length, opts) {
	var rows = 0, cols = 0;
	if(opts.biff == 12) {
		rows = blob.read_shift(4); // DRw
		cols = blob.read_shift(4); // DCol
	} else {
		cols = 1 + blob.read_shift(1); //DColByteU
		rows = 1 + blob.read_shift(2); //DRw
	}
	if(opts.biff >= 2 && opts.biff < 8) { --rows; if(--cols == 0) cols = 0x100; }
S
SheetJS 已提交
8798 8799
	// $FlowIgnore
	for(var i = 0, o/*:Array<Array<any> >*/=[]; i != rows && (o[i] = []); ++i)
S
SheetJS 已提交
8800
		for(var j = 0; j != cols; ++j) o[i][j] = parse_SerAr(blob, opts.biff);
S
SheetJS 已提交
8801 8802 8803 8804
	return o;
}

/* 2.5.198.76 */
S
SheetJS 已提交
8805
function parse_PtgName(blob, length, opts) {
S
SheetJS 已提交
8806
	var type = (blob.read_shift(1) >>> 5) & 0x03;
S
SheetJS 已提交
8807 8808 8809 8810 8811 8812 8813
	var w = (!opts || (opts.biff >= 8)) ? 4 : 2;
	var nameindex = blob.read_shift(w);
	switch(opts.biff) {
		case 2: blob.l += 5; break;
		case 3: case 4: blob.l += 8; break;
		case 5: blob.l += 12; break;
	}
S
SheetJS 已提交
8814 8815 8816 8817
	return [type, 0, nameindex];
}

/* 2.5.198.77 */
S
SheetJS 已提交
8818 8819
function parse_PtgNameX(blob, length, opts) {
	if(opts.biff == 5) return parse_PtgNameX_BIFF5(blob, length, opts);
S
SheetJS 已提交
8820 8821 8822 8823 8824
	var type = (blob.read_shift(1) >>> 5) & 0x03;
	var ixti = blob.read_shift(2); // XtiIndex
	var nameindex = blob.read_shift(4);
	return [type, ixti, nameindex];
}
S
SheetJS 已提交
8825 8826 8827 8828 8829 8830 8831 8832
function parse_PtgNameX_BIFF5(blob, length, opts) {
	var type = (blob.read_shift(1) >>> 5) & 0x03;
	var ixti = blob.read_shift(2, 'i'); // XtiIndex
	blob.l += 8;
	var nameindex = blob.read_shift(2);
	blob.l += 12;
	return [type, ixti, nameindex];
}
S
SheetJS 已提交
8833 8834

/* 2.5.198.70 */
S
SheetJS 已提交
8835
function parse_PtgMemArea(blob, length, opts) {
S
SheetJS 已提交
8836
	var type = (blob.read_shift(1) >>> 5) & 0x03;
S
SheetJS 已提交
8837 8838
	blob.l += (opts && opts.biff == 2 ? 3 : 4);
	var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
S
SheetJS 已提交
8839 8840 8841 8842
	return [type, cce];
}

/* 2.5.198.72 */
S
SheetJS 已提交
8843
function parse_PtgMemFunc(blob, length, opts) {
S
SheetJS 已提交
8844
	var type = (blob.read_shift(1) >>> 5) & 0x03;
S
SheetJS 已提交
8845
	var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
S
SheetJS 已提交
8846 8847 8848 8849 8850
	return [type, cce];
}


/* 2.5.198.86 */
S
SheetJS 已提交
8851
function parse_PtgRefErr(blob, length, opts) {
S
SheetJS 已提交
8852 8853
	var type = (blob.read_shift(1) >>> 5) & 0x03;
	blob.l += 4;
S
SheetJS 已提交
8854
	if(opts.biff == 12) blob.l += 2;
S
SheetJS 已提交
8855 8856 8857
	return [type];
}

S
SheetJS 已提交
8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870
/* 2.5.198.87 */
function parse_PtgRefErr3d(blob, length, opts) {
	var type = (blob[blob.l++] & 0x60) >> 5;
	var ixti = blob.read_shift(2);
	var w = 4;
	if(opts) switch(opts.biff) {
		case 5: throw new Error("PtgRefErr3d -- 5"); // TODO: find test case
		case 12: w = 6; break;
	}
	blob.l += w;
	return [type, ixti];
}

S
SheetJS 已提交
8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918
/* 2.5.198.26 */
var parse_PtgAdd = parseread1;
/* 2.5.198.45 */
var parse_PtgDiv = parseread1;
/* 2.5.198.56 */
var parse_PtgEq = parseread1;
/* 2.5.198.64 */
var parse_PtgGe = parseread1;
/* 2.5.198.65 */
var parse_PtgGt = parseread1;
/* 2.5.198.67 */
var parse_PtgIsect = parseread1;
/* 2.5.198.68 */
var parse_PtgLe = parseread1;
/* 2.5.198.69 */
var parse_PtgLt = parseread1;
/* 2.5.198.74 */
var parse_PtgMissArg = parseread1;
/* 2.5.198.75 */
var parse_PtgMul = parseread1;
/* 2.5.198.78 */
var parse_PtgNe = parseread1;
/* 2.5.198.80 */
var parse_PtgParen = parseread1;
/* 2.5.198.81 */
var parse_PtgPercent = parseread1;
/* 2.5.198.82 */
var parse_PtgPower = parseread1;
/* 2.5.198.83 */
var parse_PtgRange = parseread1;
/* 2.5.198.90 */
var parse_PtgSub = parseread1;
/* 2.5.198.93 */
var parse_PtgUminus = parseread1;
/* 2.5.198.94 */
var parse_PtgUnion = parseread1;
/* 2.5.198.95 */
var parse_PtgUplus = parseread1;

/* 2.5.198.71 */
var parse_PtgMemErr = parsenoop;
/* 2.5.198.73 */
var parse_PtgMemNoMem = parsenoop;
/* 2.5.198.92 */
var parse_PtgTbl = parsenoop;

/* 2.5.198.25 */
var PtgTypes = {
S
SheetJS 已提交
8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965
	/*::[*/0x01/*::]*/: { n:'PtgExp', f:parse_PtgExp },
	/*::[*/0x02/*::]*/: { n:'PtgTbl', f:parse_PtgTbl },
	/*::[*/0x03/*::]*/: { n:'PtgAdd', f:parse_PtgAdd },
	/*::[*/0x04/*::]*/: { n:'PtgSub', f:parse_PtgSub },
	/*::[*/0x05/*::]*/: { n:'PtgMul', f:parse_PtgMul },
	/*::[*/0x06/*::]*/: { n:'PtgDiv', f:parse_PtgDiv },
	/*::[*/0x07/*::]*/: { n:'PtgPower', f:parse_PtgPower },
	/*::[*/0x08/*::]*/: { n:'PtgConcat', f:parse_PtgConcat },
	/*::[*/0x09/*::]*/: { n:'PtgLt', f:parse_PtgLt },
	/*::[*/0x0A/*::]*/: { n:'PtgLe', f:parse_PtgLe },
	/*::[*/0x0B/*::]*/: { n:'PtgEq', f:parse_PtgEq },
	/*::[*/0x0C/*::]*/: { n:'PtgGe', f:parse_PtgGe },
	/*::[*/0x0D/*::]*/: { n:'PtgGt', f:parse_PtgGt },
	/*::[*/0x0E/*::]*/: { n:'PtgNe', f:parse_PtgNe },
	/*::[*/0x0F/*::]*/: { n:'PtgIsect', f:parse_PtgIsect },
	/*::[*/0x10/*::]*/: { n:'PtgUnion', f:parse_PtgUnion },
	/*::[*/0x11/*::]*/: { n:'PtgRange', f:parse_PtgRange },
	/*::[*/0x12/*::]*/: { n:'PtgUplus', f:parse_PtgUplus },
	/*::[*/0x13/*::]*/: { n:'PtgUminus', f:parse_PtgUminus },
	/*::[*/0x14/*::]*/: { n:'PtgPercent', f:parse_PtgPercent },
	/*::[*/0x15/*::]*/: { n:'PtgParen', f:parse_PtgParen },
	/*::[*/0x16/*::]*/: { n:'PtgMissArg', f:parse_PtgMissArg },
	/*::[*/0x17/*::]*/: { n:'PtgStr', f:parse_PtgStr },
	/*::[*/0x1C/*::]*/: { n:'PtgErr', f:parse_PtgErr },
	/*::[*/0x1D/*::]*/: { n:'PtgBool', f:parse_PtgBool },
	/*::[*/0x1E/*::]*/: { n:'PtgInt', f:parse_PtgInt },
	/*::[*/0x1F/*::]*/: { n:'PtgNum', f:parse_PtgNum },
	/*::[*/0x20/*::]*/: { n:'PtgArray', f:parse_PtgArray },
	/*::[*/0x21/*::]*/: { n:'PtgFunc', f:parse_PtgFunc },
	/*::[*/0x22/*::]*/: { n:'PtgFuncVar', f:parse_PtgFuncVar },
	/*::[*/0x23/*::]*/: { n:'PtgName', f:parse_PtgName },
	/*::[*/0x24/*::]*/: { n:'PtgRef', f:parse_PtgRef },
	/*::[*/0x25/*::]*/: { n:'PtgArea', f:parse_PtgArea },
	/*::[*/0x26/*::]*/: { n:'PtgMemArea', f:parse_PtgMemArea },
	/*::[*/0x27/*::]*/: { n:'PtgMemErr', f:parse_PtgMemErr },
	/*::[*/0x28/*::]*/: { n:'PtgMemNoMem', f:parse_PtgMemNoMem },
	/*::[*/0x29/*::]*/: { n:'PtgMemFunc', f:parse_PtgMemFunc },
	/*::[*/0x2A/*::]*/: { n:'PtgRefErr', f:parse_PtgRefErr },
	/*::[*/0x2B/*::]*/: { n:'PtgAreaErr', f:parse_PtgAreaErr },
	/*::[*/0x2C/*::]*/: { n:'PtgRefN', f:parse_PtgRefN },
	/*::[*/0x2D/*::]*/: { n:'PtgAreaN', f:parse_PtgAreaN },
	/*::[*/0x39/*::]*/: { n:'PtgNameX', f:parse_PtgNameX },
	/*::[*/0x3A/*::]*/: { n:'PtgRef3d', f:parse_PtgRef3d },
	/*::[*/0x3B/*::]*/: { n:'PtgArea3d', f:parse_PtgArea3d },
	/*::[*/0x3C/*::]*/: { n:'PtgRefErr3d', f:parse_PtgRefErr3d },
	/*::[*/0x3D/*::]*/: { n:'PtgAreaErr3d', f:parse_PtgAreaErr3d },
	/*::[*/0xFF/*::]*/: {}
S
SheetJS 已提交
8966 8967 8968
};
/* These are duplicated in the PtgTypes table */
var PtgDupes = {
S
SheetJS 已提交
8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982 8983 8984 8985 8986 8987
	/*::[*/0x40/*::]*/: 0x20, /*::[*/0x60/*::]*/: 0x20,
	/*::[*/0x41/*::]*/: 0x21, /*::[*/0x61/*::]*/: 0x21,
	/*::[*/0x42/*::]*/: 0x22, /*::[*/0x62/*::]*/: 0x22,
	/*::[*/0x43/*::]*/: 0x23, /*::[*/0x63/*::]*/: 0x23,
	/*::[*/0x44/*::]*/: 0x24, /*::[*/0x64/*::]*/: 0x24,
	/*::[*/0x45/*::]*/: 0x25, /*::[*/0x65/*::]*/: 0x25,
	/*::[*/0x46/*::]*/: 0x26, /*::[*/0x66/*::]*/: 0x26,
	/*::[*/0x47/*::]*/: 0x27, /*::[*/0x67/*::]*/: 0x27,
	/*::[*/0x48/*::]*/: 0x28, /*::[*/0x68/*::]*/: 0x28,
	/*::[*/0x49/*::]*/: 0x29, /*::[*/0x69/*::]*/: 0x29,
	/*::[*/0x4A/*::]*/: 0x2A, /*::[*/0x6A/*::]*/: 0x2A,
	/*::[*/0x4B/*::]*/: 0x2B, /*::[*/0x6B/*::]*/: 0x2B,
	/*::[*/0x4C/*::]*/: 0x2C, /*::[*/0x6C/*::]*/: 0x2C,
	/*::[*/0x4D/*::]*/: 0x2D, /*::[*/0x6D/*::]*/: 0x2D,
	/*::[*/0x59/*::]*/: 0x39, /*::[*/0x79/*::]*/: 0x39,
	/*::[*/0x5A/*::]*/: 0x3A, /*::[*/0x7A/*::]*/: 0x3A,
	/*::[*/0x5B/*::]*/: 0x3B, /*::[*/0x7B/*::]*/: 0x3B,
	/*::[*/0x5C/*::]*/: 0x3C, /*::[*/0x7C/*::]*/: 0x3C,
	/*::[*/0x5D/*::]*/: 0x3D, /*::[*/0x7D/*::]*/: 0x3D
S
SheetJS 已提交
8988 8989 8990
};
(function(){for(var y in PtgDupes) PtgTypes[y] = PtgTypes[PtgDupes[y]];})();

S
SheetJS 已提交
8991 8992 8993 8994
var Ptg18 = {
//	/*::[*/0x19/*::]*/: { n:'PtgList', f:parse_PtgList }, // TODO
//	/*::[*/0x1D/*::]*/: { n:'PtgSxName', f:parse_PtgSxName }, // TODO
};
S
SheetJS 已提交
8995
var Ptg19 = {
S
SheetJS 已提交
8996 8997 8998 8999 9000 9001 9002 9003
	/*::[*/0x01/*::]*/: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
	/*::[*/0x02/*::]*/: { n:'PtgAttrIf', f:parse_PtgAttrIf },
	/*::[*/0x04/*::]*/: { n:'PtgAttrChoose', f:parse_PtgAttrChoose },
	/*::[*/0x08/*::]*/: { n:'PtgAttrGoto', f:parse_PtgAttrGoto },
	/*::[*/0x10/*::]*/: { n:'PtgAttrSum', f:parse_PtgAttrSum },
	/*::[*/0x20/*::]*/: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
	/*::[*/0x40/*::]*/: { n:'PtgAttrSpace', f:parse_PtgAttrSpace },
	/*::[*/0x41/*::]*/: { n:'PtgAttrSpaceSemi', f:parse_PtgAttrSpaceSemi },
S
SheetJS 已提交
9004
	/*::[*/0x80/*::]*/: { n:'PtgAttrIfError', f:parse_PtgAttrIfError },
S
SheetJS 已提交
9005
	/*::[*/0xFF/*::]*/: {}
S
SheetJS 已提交
9006 9007 9008 9009
};

/* 2.4.127 TODO */
function parse_Formula(blob, length, opts) {
S
SheetJS 已提交
9010
	var end = blob.l + length;
S
SheetJS 已提交
9011
	var cell = parse_XLSCell(blob, 6);
S
SheetJS 已提交
9012
	if(opts.biff == 2) ++blob.l;
S
SheetJS 已提交
9013 9014
	var val = parse_FormulaValue(blob,8);
	var flags = blob.read_shift(1);
S
SheetJS 已提交
9015 9016 9017 9018 9019 9020
	if(opts.biff != 2) {
		blob.read_shift(1);
		if(opts.biff >= 5) {
			var chn = blob.read_shift(4);
		}
	}
S
SheetJS 已提交
9021
	var cbf = parse_XLSCellParsedFormula(blob, end - blob.l, opts);
S
SheetJS 已提交
9022 9023 9024 9025
	return {cell:cell, val:val[0], formula:cbf, shared: (flags >> 3) & 1, tt:val[1]};
}

/* 2.5.133 TODO: how to emit empty strings? */
9026
function parse_FormulaValue(blob/*::, length*/) {
S
SheetJS 已提交
9027 9028 9029 9030 9031 9032 9033 9034
	var b;
	if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return [parse_Xnum(blob),'n'];
	switch(blob[blob.l]) {
		case 0x00: blob.l += 8; return ["String", 's'];
		case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return [b,'b'];
		case 0x02: b = blob[blob.l+2]; blob.l += 8; return [b,'e'];
		case 0x03: blob.l += 8; return ["",'s'];
	}
S
SheetJS 已提交
9035
	return [];
S
SheetJS 已提交
9036 9037 9038 9039
}

/* 2.5.198.103 */
function parse_RgbExtra(blob, length, rgce, opts) {
S
SheetJS 已提交
9040
	if(opts.biff < 8) return parsenoop(blob, length);
S
SheetJS 已提交
9041 9042 9043 9044 9045
	var target = blob.l + length;
	var o = [];
	for(var i = 0; i !== rgce.length; ++i) {
		switch(rgce[i][0]) {
			case 'PtgArray': /* PtgArray -> PtgExtraArray */
S
SheetJS 已提交
9046
				rgce[i][1] = parse_PtgExtraArray(blob, 0, opts);
S
SheetJS 已提交
9047 9048 9049 9050 9051 9052
				o.push(rgce[i][1]);
				break;
			case 'PtgMemArea': /* PtgMemArea -> PtgExtraMem */
				rgce[i][2] = parse_PtgExtraMem(blob, rgce[i][1]);
				o.push(rgce[i][2]);
				break;
S
SheetJS 已提交
9053 9054 9055 9056 9057
			case 'PtgExp': /* PtgExp -> PtgExtraCol */
				if(opts && opts.biff == 12) {
					rgce[i][1][1] = blob.read_shift(4);
					o.push(rgce[i][1]);
				} break;
S
SheetJS 已提交
9058 9059 9060 9061
			default: break;
		}
	}
	length = target - blob.l;
S
SheetJS 已提交
9062 9063
	/* note: this is technically an error but Excel disregards */
	//if(target !== blob.l && blob.l !== target - length) throw new Error(target + " != " + blob.l);
S
SheetJS 已提交
9064 9065 9066 9067 9068 9069 9070
	if(length !== 0) o.push(parsenoop(blob, length));
	return o;
}

/* 2.5.198.21 */
function parse_NameParsedFormula(blob, length, opts, cce) {
	var target = blob.l + length;
S
SheetJS 已提交
9071
	var rgce = parse_Rgce(blob, cce, opts);
S
SheetJS 已提交
9072 9073 9074 9075 9076 9077 9078
	var rgcb;
	if(target !== blob.l) rgcb = parse_RgbExtra(blob, target - blob.l, rgce, opts);
	return [rgce, rgcb];
}

/* 2.5.198.3 TODO */
function parse_XLSCellParsedFormula(blob, length, opts) {
S
SheetJS 已提交
9079 9080
	var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
	var rgcb, cce = blob.read_shift(len); // length of rgce
S
SheetJS 已提交
9081
	if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
S
SheetJS 已提交
9082 9083
	var rgce = parse_Rgce(blob, cce, opts);
	if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
S
SheetJS 已提交
9084 9085 9086 9087 9088 9089 9090
	return [rgce, rgcb];
}

/* 2.5.198.118 TODO */
function parse_SharedParsedFormula(blob, length, opts) {
	var target = blob.l + length;
	var rgcb, cce = blob.read_shift(2); // length of rgce
S
SheetJS 已提交
9091
	var rgce = parse_Rgce(blob, cce, opts);
S
SheetJS 已提交
9092 9093 9094 9095 9096 9097 9098
	if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
	if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
	return [rgce, rgcb];
}

/* 2.5.198.1 TODO */
function parse_ArrayParsedFormula(blob, length, opts, ref) {
S
SheetJS 已提交
9099 9100
	var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
	var rgcb, cce = blob.read_shift(len); // length of rgce
S
SheetJS 已提交
9101
	if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
S
SheetJS 已提交
9102 9103
	var rgce = parse_Rgce(blob, cce, opts);
	if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
S
SheetJS 已提交
9104 9105 9106 9107
	return [rgce, rgcb];
}

/* 2.5.198.104 */
S
SheetJS 已提交
9108
function parse_Rgce(blob, length, opts) {
S
SheetJS 已提交
9109 9110 9111 9112 9113 9114 9115 9116 9117 9118
	var target = blob.l + length;
	var R, id, ptgs = [];
	while(target != blob.l) {
		length = target - blob.l;
		id = blob[blob.l];
		R = PtgTypes[id];
		if(id === 0x18 || id === 0x19) {
			id = blob[blob.l + 1];
			R = (id === 0x18 ? Ptg18 : Ptg19)[id];
		}
S
SheetJS 已提交
9119 9120
		if(!R || !R.f) { /*ptgs.push*/(parsenoop(blob, length)); }
		// $FlowIgnore
S
SheetJS 已提交
9121
		else { ptgs.push([R.n, R.f(blob, length, opts)]); }
S
SheetJS 已提交
9122 9123 9124 9125
	}
	return ptgs;
}

S
SheetJS 已提交
9126 9127 9128 9129 9130 9131 9132 9133
function stringify_array(f) {
	var o = [];
	for(var i = 0; i < f.length; ++i) {
		var x = f[i], r = [];
		for(var j = 0; j < x.length; ++j) {
			var y = x[j];
			if(y) switch(y[0]) {
				// TODO: handle embedded quotes
S
SheetJS 已提交
9134 9135 9136
				case 0x02:
					/*:: if(typeof y[1] != 'string') throw "unreachable"; */
					r.push('"' + y[1].replace(/"/g,'""') + '"'); break;
S
SheetJS 已提交
9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160
				default: r.push(y[1]);
			} else r.push("");
		}
		o.push(r.join(","));
	}
	return o.join(";");
}

/* [MS-XLS] 2.2.2 TODO */
/* [MS-XLSB] 2.2.2 */
var PtgBinOp = {
	PtgAdd: "+",
	PtgConcat: "&",
	PtgDiv: "/",
	PtgEq: "=",
	PtgGe: ">=",
	PtgGt: ">",
	PtgLe: "<=",
	PtgLt: "<",
	PtgMul: "*",
	PtgNe: "<>",
	PtgPower: "^",
	PtgSub: "-"
};
S
SheetJS 已提交
9161 9162 9163 9164 9165 9166
function formula_quote_sheet_name(sname/*:string*/)/*:string*/ {
	if(!sname) return "";
	if(sname.indexOf(" ") > -1) return "'" + sname + "'";
	return sname;
}
function get_ixti_raw(supbooks, ixti/*:number*/, opts)/*:string*/ {
S
SheetJS 已提交
9167 9168
	return supbooks.SheetNames[ixti];
}
S
SheetJS 已提交
9169 9170 9171
function get_ixti(supbooks, ixti/*:number*/, opts)/*:string*/ {
	return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts));
}
S
SheetJS 已提交
9172
function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, opts) {
S
SheetJS 已提交
9173
	//console.log(formula);
S
SheetJS 已提交
9174
	var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}};
S
SheetJS 已提交
9175
	var stack/*:Array<string>*/ = [], e1, e2, type, c/*:CellAddress*/, ixti=0, nameidx=0, r, sname="";
S
SheetJS 已提交
9176
	if(!formula[0] || !formula[0][0]) return "";
S
SheetJS 已提交
9177
	var last_sp = -1, sp = "";
S
SheetJS 已提交
9178 9179 9180 9181 9182
	//console.log("--",cell,formula[0])
	for(var ff = 0, fflen = formula[0].length; ff < fflen; ++ff) {
		var f = formula[0][ff];
		//console.log("++",f, stack)
		switch(f[0]) {
S
SheetJS 已提交
9183 9184 9185 9186 9187 9188
			case 'PtgUminus': /* 2.5.198.93 */
				stack.push("-" + stack.pop()); break;
			case 'PtgUplus': /* 2.5.198.95 */
				stack.push("+" + stack.pop()); break;
			case 'PtgPercent': /* 2.5.198.81 */
				stack.push(stack.pop() + "%"); break;
S
SheetJS 已提交
9189

S
SheetJS 已提交
9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201
			case 'PtgAdd':    /* 2.5.198.26 */
			case 'PtgConcat': /* 2.5.198.43 */
			case 'PtgDiv':    /* 2.5.198.45 */
			case 'PtgEq':     /* 2.5.198.56 */
			case 'PtgGe':     /* 2.5.198.64 */
			case 'PtgGt':     /* 2.5.198.65 */
			case 'PtgLe':     /* 2.5.198.68 */
			case 'PtgLt':     /* 2.5.198.69 */
			case 'PtgMul':    /* 2.5.198.75 */
			case 'PtgNe':     /* 2.5.198.78 */
			case 'PtgPower':  /* 2.5.198.82 */
			case 'PtgSub':    /* 2.5.198.90 */
S
SheetJS 已提交
9202
				e1 = stack.pop(); e2 = stack.pop();
S
SheetJS 已提交
9203 9204
				if(last_sp >= 0) {
					switch(formula[0][last_sp][1][0]) {
S
SheetJS 已提交
9205 9206 9207 9208 9209 9210
						case 0:
							// $FlowIgnore
							sp = fill(" ", formula[0][last_sp][1][1]); break;
						case 1:
							// $FlowIgnore
							sp = fill("\r", formula[0][last_sp][1][1]); break;
S
SheetJS 已提交
9211 9212
						default:
							sp = "";
S
SheetJS 已提交
9213
							// $FlowIgnore
S
SheetJS 已提交
9214
							if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + formula[0][last_sp][1][0]);
S
SheetJS 已提交
9215 9216 9217 9218 9219
					}
					e2 = e2 + sp;
					last_sp = -1;
				}
				stack.push(e2+PtgBinOp[f[0]]+e1);
S
SheetJS 已提交
9220 9221
				break;

S
SheetJS 已提交
9222
			case 'PtgIsect': /* 2.5.198.67 */
S
SheetJS 已提交
9223 9224 9225
				e1 = stack.pop(); e2 = stack.pop();
				stack.push(e2+" "+e1);
				break;
S
SheetJS 已提交
9226
			case 'PtgUnion': /* 2.5.198.94 */
S
SheetJS 已提交
9227 9228 9229
				e1 = stack.pop(); e2 = stack.pop();
				stack.push(e2+","+e1);
				break;
S
SheetJS 已提交
9230
			case 'PtgRange': /* 2.5.198.83 */
S
SheetJS 已提交
9231 9232 9233
				e1 = stack.pop(); e2 = stack.pop();
				stack.push(e2+":"+e1);
				break;
S
SheetJS 已提交
9234

S
SheetJS 已提交
9235 9236 9237 9238 9239 9240 9241 9242
			case 'PtgAttrChoose': /* 2.5.198.34 */
				break;
			case 'PtgAttrGoto': /* 2.5.198.35 */
				break;
			case 'PtgAttrIf': /* 2.5.198.36 */
				break;
			case 'PtgAttrIfError': /* [MS-XLSB] 2.5.97.28 */
				break;
S
SheetJS 已提交
9243 9244


S
SheetJS 已提交
9245
			case 'PtgRef': /* 2.5.198.84 */
S
SheetJS 已提交
9246
				type = f[1][0]; c = shift_cell_xls((f[1][1]/*:any*/), _range, opts);
S
SheetJS 已提交
9247
				stack.push(encode_cell_xls(c));
S
SheetJS 已提交
9248
				break;
S
SheetJS 已提交
9249
			case 'PtgRefN': /* 2.5.198.88 */
S
SheetJS 已提交
9250
				type = f[1][0]; c = cell ? shift_cell_xls((f[1][1]/*:any*/), cell, opts) : (f[1][1]/*:any*/);
S
SheetJS 已提交
9251
				stack.push(encode_cell_xls(c));
S
SheetJS 已提交
9252
				break;
S
SheetJS 已提交
9253
			case 'PtgRef3d': /* 2.5.198.85 */
S
SheetJS 已提交
9254
				type = f[1][0]; ixti = /*::Number(*/f[1][1]/*::)*/; c = shift_cell_xls((f[1][2]/*:any*/), _range, opts);
S
SheetJS 已提交
9255
				sname = get_ixti(supbooks, ixti, opts);
S
SheetJS 已提交
9256
				var w = sname; /* IE9 fails on defined names */
S
SheetJS 已提交
9257
				stack.push(sname + "!" + encode_cell_xls(c));
S
SheetJS 已提交
9258 9259
				break;

S
SheetJS 已提交
9260 9261
			case 'PtgFunc': /* 2.5.198.62 */
			case 'PtgFuncVar': /* 2.5.198.63 */
S
SheetJS 已提交
9262
				//console.log(f[1]);
S
SheetJS 已提交
9263
				/* f[1] = [argc, func, type] */
S
SheetJS 已提交
9264
				var argc/*:number*/ = f[1][0], func/*:string*/ = f[1][1];
S
SheetJS 已提交
9265
				if(!argc) argc = 0;
S
SheetJS 已提交
9266
				var args = argc == 0 ? [] : stack.slice(-argc);
S
SheetJS 已提交
9267 9268 9269 9270 9271
				stack.length -= argc;
				if(func === 'User') func = args.shift();
				stack.push(func + "(" + args.join(",") + ")");
				break;

S
SheetJS 已提交
9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283
			case 'PtgBool': /* 2.5.198.42 */
				stack.push(f[1] ? "TRUE" : "FALSE"); break;
			case 'PtgInt': /* 2.5.198.66 */
				stack.push(/*::String(*/f[1]/*::)*/); break;
			case 'PtgNum': /* 2.5.198.79 TODO: precision? */
				stack.push(String(f[1])); break;
			case 'PtgStr': /* 2.5.198.89 */
				// $FlowIgnore
				stack.push('"' + f[1] + '"'); break;
			case 'PtgErr': /* 2.5.198.57 */
				stack.push(/*::String(*/f[1]/*::)*/); break;
			case 'PtgAreaN': /* 2.5.198.31 TODO */
S
SheetJS 已提交
9284
				type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts);
S
SheetJS 已提交
9285
				stack.push(encode_range_xls((r/*:any*/), opts));
S
SheetJS 已提交
9286
				break;
S
SheetJS 已提交
9287
			case 'PtgArea': /* 2.5.198.27 TODO: fixed points */
S
SheetJS 已提交
9288
				type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts);
S
SheetJS 已提交
9289
				stack.push(encode_range_xls((r/*:any*/), opts));
S
SheetJS 已提交
9290
				break;
S
SheetJS 已提交
9291
			case 'PtgArea3d': /* 2.5.198.28 TODO */
S
SheetJS 已提交
9292
				type = f[1][0]; ixti = /*::Number(*/f[1][1]/*::)*/; r = f[1][2];
S
SheetJS 已提交
9293
				sname = (supbooks && supbooks[1] ? supbooks[1][ixti+1] : "**MISSING**");
S
SheetJS 已提交
9294
				stack.push(sname + "!" + encode_range((r/*:any*/)));
S
SheetJS 已提交
9295
				break;
S
SheetJS 已提交
9296
			case 'PtgAttrSum': /* 2.5.198.41 */
S
SheetJS 已提交
9297 9298 9299
				stack.push("SUM(" + stack.pop() + ")");
				break;

S
SheetJS 已提交
9300 9301
			case 'PtgAttrSemi': /* 2.5.198.37 */
				break;
S
SheetJS 已提交
9302

S
SheetJS 已提交
9303
			case 'PtgName': /* 2.5.97.60 TODO: revisions */
S
SheetJS 已提交
9304
				/* f[1] = type, 0, nameindex */
S
SheetJS 已提交
9305
				nameidx = (f[1][2]/*:any*/);
S
SheetJS 已提交
9306
				var lbl = (supbooks.names||[])[nameidx-1] || (supbooks[0]||[])[nameidx];
S
SheetJS 已提交
9307
				var name = lbl ? lbl.Name : "SH33TJSERR7" + String(nameidx);
S
SheetJS 已提交
9308 9309 9310 9311
				if(name in XLSXFutureFunctions) name = XLSXFutureFunctions[name];
				stack.push(name);
				break;

S
SheetJS 已提交
9312
			case 'PtgNameX': /* 2.5.97.61 TODO: revisions */
S
SheetJS 已提交
9313
				/* f[1] = type, ixti, nameindex */
S
SheetJS 已提交
9314
				var bookidx/*:number*/ = (f[1][1]/*:any*/); nameidx = (f[1][2]/*:any*/); var externbook;
S
SheetJS 已提交
9315
				/* TODO: Properly handle missing values */
S
SheetJS 已提交
9316
				//console.log(bookidx, supbooks);
S
SheetJS 已提交
9317
				if(opts.biff <= 5) {
S
SheetJS 已提交
9318 9319 9320
					if(bookidx < 0) bookidx = -bookidx;
					if(supbooks[bookidx]) externbook = supbooks[bookidx][nameidx];
				} else {
S
SheetJS 已提交
9321 9322
					var pnxname = supbooks.SheetNames[bookidx];
					var o = "";
S
SheetJS 已提交
9323
					if(((supbooks[bookidx]||[])[0]||[])[0] == 0x3A01){/* empty */}
S
SheetJS 已提交
9324 9325 9326 9327 9328 9329 9330 9331
					else if(((supbooks[bookidx]||[])[0]||[])[0] == 0x0401){
						if(supbooks[bookidx][nameidx] && supbooks[bookidx][nameidx].itab > 0) {
							o = supbooks.SheetNames[supbooks[bookidx][nameidx].itab-1] + "!";
						}
					}
					else o = supbooks.SheetNames[nameidx-1]+ "!";
					if(supbooks[bookidx] && supbooks[bookidx][nameidx]) o += supbooks[bookidx][nameidx].Name;
					else if(supbooks[0] && supbooks[0][nameidx]) o += supbooks[0][nameidx].Name;
S
SheetJS 已提交
9332
					else o += "SH33TJSERRX";
S
SheetJS 已提交
9333 9334
					stack.push(o);
					break;
S
SheetJS 已提交
9335
				}
S
SheetJS 已提交
9336
				if(!externbook) externbook = {Name: "SH33TJSERRY"};
S
SheetJS 已提交
9337
				stack.push(externbook.Name);
S
SheetJS 已提交
9338 9339
				break;

S
SheetJS 已提交
9340
			case 'PtgParen': /* 2.5.198.80 */
S
SheetJS 已提交
9341 9342 9343 9344
				var lp = '(', rp = ')';
				if(last_sp >= 0) {
					sp = "";
					switch(formula[0][last_sp][1][0]) {
S
SheetJS 已提交
9345
						// $FlowIgnore
S
SheetJS 已提交
9346
						case 2: lp = fill(" ", formula[0][last_sp][1][1]) + lp; break;
S
SheetJS 已提交
9347
						// $FlowIgnore
S
SheetJS 已提交
9348
						case 3: lp = fill("\r", formula[0][last_sp][1][1]) + lp; break;
S
SheetJS 已提交
9349
						// $FlowIgnore
S
SheetJS 已提交
9350
						case 4: rp = fill(" ", formula[0][last_sp][1][1]) + rp; break;
S
SheetJS 已提交
9351
						// $FlowIgnore
S
SheetJS 已提交
9352
						case 5: rp = fill("\r", formula[0][last_sp][1][1]) + rp; break;
S
SheetJS 已提交
9353
						default:
S
SheetJS 已提交
9354
							// $FlowIgnore
S
SheetJS 已提交
9355
							if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + formula[0][last_sp][1][0]);
S
SheetJS 已提交
9356 9357 9358 9359
					}
					last_sp = -1;
				}
				stack.push(lp + stack.pop() + rp); break;
S
SheetJS 已提交
9360

S
SheetJS 已提交
9361 9362
			case 'PtgRefErr': /* 2.5.198.86 */
				stack.push('#REF!'); break;
S
SheetJS 已提交
9363

S
SheetJS 已提交
9364 9365
			case 'PtgRefErr3d': /* 2.5.198.87 */
				stack.push('#REF!'); break;
S
SheetJS 已提交
9366

S
SheetJS 已提交
9367
			case 'PtgExp': /* 2.5.198.58 TODO */
S
SheetJS 已提交
9368
				c = {c:f[1][1],r:f[1][0]};
S
SheetJS 已提交
9369
				var q = ({c: cell.c, r:cell.r}/*:any*/);
S
SheetJS 已提交
9370 9371 9372 9373 9374 9375 9376 9377 9378 9379 9380 9381
				if(supbooks.sharedf[encode_cell(c)]) {
					var parsedf = (supbooks.sharedf[encode_cell(c)]);
					stack.push(stringify_formula(parsedf, _range, q, supbooks, opts));
				}
				else {
					var fnd = false;
					for(e1=0;e1!=supbooks.arrayf.length; ++e1) {
						/* TODO: should be something like range_has */
						e2 = supbooks.arrayf[e1];
						if(c.c < e2[0].s.c || c.c > e2[0].e.c) continue;
						if(c.r < e2[0].s.r || c.r > e2[0].e.r) continue;
						stack.push(stringify_formula(e2[1], _range, q, supbooks, opts));
S
SheetJS 已提交
9382 9383
						fnd = true;
						break;
S
SheetJS 已提交
9384
					}
S
SheetJS 已提交
9385
					if(!fnd) stack.push(/*::String(*/f[1]/*::)*/);
S
SheetJS 已提交
9386 9387 9388
				}
				break;

S
SheetJS 已提交
9389
			case 'PtgArray': /* 2.5.198.32 TODO */
S
SheetJS 已提交
9390
				stack.push("{" + stringify_array(f[1]) + "}");
S
SheetJS 已提交
9391 9392
				break;

S
SheetJS 已提交
9393
			case 'PtgMemArea': /* 2.5.198.70 TODO: confirm this is a non-display */
S
SheetJS 已提交
9394 9395 9396
				//stack.push("(" + f[2].map(encode_range).join(",") + ")");
				break;

S
SheetJS 已提交
9397 9398
			case 'PtgAttrSpace': /* 2.5.198.38 */
			case 'PtgAttrSpaceSemi': /* 2.5.198.39 */
S
SheetJS 已提交
9399 9400
				last_sp = ff;
				break;
S
SheetJS 已提交
9401

S
SheetJS 已提交
9402 9403
			case 'PtgTbl': /* 2.5.198.92 TODO */
				break;
S
SheetJS 已提交
9404

S
SheetJS 已提交
9405 9406
			case 'PtgMemErr': /* 2.5.198.71 */
				break;
S
SheetJS 已提交
9407

S
SheetJS 已提交
9408
			case 'PtgMissArg': /* 2.5.198.74 */
S
SheetJS 已提交
9409 9410 9411
				stack.push("");
				break;

S
SheetJS 已提交
9412 9413
			case 'PtgAreaErr': /* 2.5.198.29 */
				stack.push("#REF!"); break;
S
SheetJS 已提交
9414

S
SheetJS 已提交
9415 9416
			case 'PtgAreaErr3d': /* 2.5.198.30 */
				stack.push("#REF!"); break;
S
SheetJS 已提交
9417

S
SheetJS 已提交
9418 9419
			case 'PtgMemFunc': /* 2.5.198.72 TODO */
				break;
S
SheetJS 已提交
9420

S
SheetJS 已提交
9421
			default: throw new Error('Unrecognized Formula Token: ' + String(f));
S
SheetJS 已提交
9422
		}
S
SheetJS 已提交
9423 9424 9425
		var PtgNonDisp = ['PtgAttrSpace', 'PtgAttrSpaceSemi', 'PtgAttrGoto'];
		if(last_sp >= 0 && PtgNonDisp.indexOf(formula[0][ff][0]) == -1) {
			f = formula[0][last_sp];
S
SheetJS 已提交
9426
			var _left = true;
S
SheetJS 已提交
9427
			switch(f[1][0]) {
S
SheetJS 已提交
9428 9429 9430
				/* note: some bad XLSB files omit the PtgParen */
				case 4: _left = false;
				/* falls through */
S
SheetJS 已提交
9431 9432 9433
				case 0:
					// $FlowIgnore
					sp = fill(" ", f[1][1]); break;
S
SheetJS 已提交
9434 9435
				case 5: _left = false;
				/* falls through */
S
SheetJS 已提交
9436 9437 9438
				case 1:
					// $FlowIgnore
					sp = fill("\r", f[1][1]); break;
S
SheetJS 已提交
9439 9440
				default:
					sp = "";
S
SheetJS 已提交
9441
					// $FlowIgnore
S
SheetJS 已提交
9442
					if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + f[1][0]);
S
SheetJS 已提交
9443
			}
S
SheetJS 已提交
9444
			stack.push((_left ? sp : "") + stack.pop() + (_left ? "" : sp));
S
SheetJS 已提交
9445 9446
			last_sp = -1;
		}
S
SheetJS 已提交
9447 9448 9449
		//console.log("::",f, stack)
	}
	//console.log("--",stack);
S
SheetJS 已提交
9450
	if(stack.length > 1 && opts.WTF) throw new Error("bad formula stack");
S
SheetJS 已提交
9451 9452 9453
	return stack[0];
}

S
SheetJS 已提交
9454 9455 9456
/* XLSB Parsed Formula records have the same shape */
function parse_XLSBParsedFormula(data, length, opts) {
	var end = data.l + length;
S
SheetJS 已提交
9457
	var cce = data.read_shift(4);
S
SheetJS 已提交
9458 9459 9460 9461
	var rgce = parse_Rgce(data, cce, opts);
	var cb = data.read_shift(4);
	var rgcb = cb > 0 ? parse_RgbExtra(data, cb, rgce, opts) : null;
	return [rgce, rgcb];
S
SheetJS 已提交
9462
}
S
SheetJS 已提交
9463 9464 9465 9466 9467 9468 9469 9470 9471

/* [MS-XLSB] 2.5.97.1 ArrayParsedFormula */
var parse_XLSBArrayParsedFormula = parse_XLSBParsedFormula;
/* [MS-XLSB] 2.5.97.4 CellParsedFormula */
var parse_XLSBCellParsedFormula = parse_XLSBParsedFormula;
/* [MS-XLSB] 2.5.97.12 NameParsedFormula */
var parse_XLSBNameParsedFormula = parse_XLSBParsedFormula;
/* [MS-XLSB] 2.5.97.98 SharedParsedFormula */
var parse_XLSBSharedParsedFormula = parse_XLSBParsedFormula;
S
SheetJS 已提交
9472 9473
/* [MS-XLS] 2.5.198.44 */
var PtgDataType = {
S
SheetJS 已提交
9474 9475 9476
	/*::[*/0x1/*::]*/: "REFERENCE", // reference to range
	/*::[*/0x2/*::]*/: "VALUE", // single value
	/*::[*/0x3/*::]*/: "ARRAY" // array of values
S
SheetJS 已提交
9477 9478 9479 9480
};

/* [MS-XLS] 2.5.198.4 */
var Cetab = {
S
SheetJS 已提交
9481 9482 9483 9484 9485 9486 9487 9488 9489 9490 9491 9492 9493 9494 9495 9496 9497 9498 9499 9500 9501 9502 9503 9504 9505 9506 9507 9508 9509 9510 9511 9512 9513 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 9528 9529 9530 9531 9532 9533 9534 9535 9536 9537 9538 9539 9540 9541 9542 9543 9544 9545 9546 9547 9548 9549 9550 9551 9552 9553 9554 9555 9556 9557 9558 9559 9560 9561 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 9576 9577 9578 9579 9580 9581 9582 9583 9584 9585 9586 9587 9588 9589 9590 9591 9592 9593 9594 9595 9596 9597 9598 9599 9600 9601 9602 9603 9604 9605 9606 9607 9608 9609 9610 9611 9612 9613 9614 9615 9616 9617 9618 9619 9620 9621 9622 9623 9624 9625 9626 9627 9628 9629 9630 9631 9632 9633 9634 9635 9636 9637 9638 9639 9640 9641 9642 9643 9644 9645 9646 9647 9648 9649 9650 9651 9652 9653 9654 9655 9656 9657 9658 9659 9660 9661 9662 9663 9664 9665 9666 9667 9668 9669 9670 9671 9672 9673 9674 9675 9676 9677 9678 9679 9680 9681 9682 9683 9684 9685 9686 9687 9688 9689 9690 9691 9692 9693 9694 9695 9696 9697 9698 9699 9700 9701 9702 9703 9704 9705 9706 9707 9708 9709 9710 9711 9712 9713 9714 9715 9716 9717 9718 9719 9720 9721 9722 9723 9724 9725 9726 9727 9728 9729 9730 9731 9732 9733 9734 9735 9736 9737 9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752 9753 9754 9755 9756 9757 9758 9759 9760 9761 9762 9763 9764 9765 9766 9767 9768 9769 9770 9771 9772 9773 9774 9775 9776 9777 9778 9779 9780 9781 9782 9783 9784 9785 9786 9787 9788 9789 9790 9791 9792 9793 9794 9795 9796 9797 9798 9799 9800 9801 9802 9803 9804 9805 9806 9807 9808 9809 9810 9811 9812 9813 9814 9815 9816 9817 9818 9819 9820 9821 9822 9823 9824 9825 9826 9827 9828 9829 9830 9831 9832 9833 9834 9835 9836 9837 9838 9839 9840 9841 9842 9843 9844 9845 9846 9847 9848 9849 9850 9851 9852 9853 9854 9855 9856 9857 9858 9859 9860 9861 9862 9863 9864 9865 9866 9867 9868 9869 9870 9871 9872 9873 9874 9875 9876
	/*::[*/0x0000/*::]*/: 'BEEP',
	/*::[*/0x0001/*::]*/: 'OPEN',
	/*::[*/0x0002/*::]*/: 'OPEN.LINKS',
	/*::[*/0x0003/*::]*/: 'CLOSE.ALL',
	/*::[*/0x0004/*::]*/: 'SAVE',
	/*::[*/0x0005/*::]*/: 'SAVE.AS',
	/*::[*/0x0006/*::]*/: 'FILE.DELETE',
	/*::[*/0x0007/*::]*/: 'PAGE.SETUP',
	/*::[*/0x0008/*::]*/: 'PRINT',
	/*::[*/0x0009/*::]*/: 'PRINTER.SETUP',
	/*::[*/0x000A/*::]*/: 'QUIT',
	/*::[*/0x000B/*::]*/: 'NEW.WINDOW',
	/*::[*/0x000C/*::]*/: 'ARRANGE.ALL',
	/*::[*/0x000D/*::]*/: 'WINDOW.SIZE',
	/*::[*/0x000E/*::]*/: 'WINDOW.MOVE',
	/*::[*/0x000F/*::]*/: 'FULL',
	/*::[*/0x0010/*::]*/: 'CLOSE',
	/*::[*/0x0011/*::]*/: 'RUN',
	/*::[*/0x0016/*::]*/: 'SET.PRINT.AREA',
	/*::[*/0x0017/*::]*/: 'SET.PRINT.TITLES',
	/*::[*/0x0018/*::]*/: 'SET.PAGE.BREAK',
	/*::[*/0x0019/*::]*/: 'REMOVE.PAGE.BREAK',
	/*::[*/0x001A/*::]*/: 'FONT',
	/*::[*/0x001B/*::]*/: 'DISPLAY',
	/*::[*/0x001C/*::]*/: 'PROTECT.DOCUMENT',
	/*::[*/0x001D/*::]*/: 'PRECISION',
	/*::[*/0x001E/*::]*/: 'A1.R1C1',
	/*::[*/0x001F/*::]*/: 'CALCULATE.NOW',
	/*::[*/0x0020/*::]*/: 'CALCULATION',
	/*::[*/0x0022/*::]*/: 'DATA.FIND',
	/*::[*/0x0023/*::]*/: 'EXTRACT',
	/*::[*/0x0024/*::]*/: 'DATA.DELETE',
	/*::[*/0x0025/*::]*/: 'SET.DATABASE',
	/*::[*/0x0026/*::]*/: 'SET.CRITERIA',
	/*::[*/0x0027/*::]*/: 'SORT',
	/*::[*/0x0028/*::]*/: 'DATA.SERIES',
	/*::[*/0x0029/*::]*/: 'TABLE',
	/*::[*/0x002A/*::]*/: 'FORMAT.NUMBER',
	/*::[*/0x002B/*::]*/: 'ALIGNMENT',
	/*::[*/0x002C/*::]*/: 'STYLE',
	/*::[*/0x002D/*::]*/: 'BORDER',
	/*::[*/0x002E/*::]*/: 'CELL.PROTECTION',
	/*::[*/0x002F/*::]*/: 'COLUMN.WIDTH',
	/*::[*/0x0030/*::]*/: 'UNDO',
	/*::[*/0x0031/*::]*/: 'CUT',
	/*::[*/0x0032/*::]*/: 'COPY',
	/*::[*/0x0033/*::]*/: 'PASTE',
	/*::[*/0x0034/*::]*/: 'CLEAR',
	/*::[*/0x0035/*::]*/: 'PASTE.SPECIAL',
	/*::[*/0x0036/*::]*/: 'EDIT.DELETE',
	/*::[*/0x0037/*::]*/: 'INSERT',
	/*::[*/0x0038/*::]*/: 'FILL.RIGHT',
	/*::[*/0x0039/*::]*/: 'FILL.DOWN',
	/*::[*/0x003D/*::]*/: 'DEFINE.NAME',
	/*::[*/0x003E/*::]*/: 'CREATE.NAMES',
	/*::[*/0x003F/*::]*/: 'FORMULA.GOTO',
	/*::[*/0x0040/*::]*/: 'FORMULA.FIND',
	/*::[*/0x0041/*::]*/: 'SELECT.LAST.CELL',
	/*::[*/0x0042/*::]*/: 'SHOW.ACTIVE.CELL',
	/*::[*/0x0043/*::]*/: 'GALLERY.AREA',
	/*::[*/0x0044/*::]*/: 'GALLERY.BAR',
	/*::[*/0x0045/*::]*/: 'GALLERY.COLUMN',
	/*::[*/0x0046/*::]*/: 'GALLERY.LINE',
	/*::[*/0x0047/*::]*/: 'GALLERY.PIE',
	/*::[*/0x0048/*::]*/: 'GALLERY.SCATTER',
	/*::[*/0x0049/*::]*/: 'COMBINATION',
	/*::[*/0x004A/*::]*/: 'PREFERRED',
	/*::[*/0x004B/*::]*/: 'ADD.OVERLAY',
	/*::[*/0x004C/*::]*/: 'GRIDLINES',
	/*::[*/0x004D/*::]*/: 'SET.PREFERRED',
	/*::[*/0x004E/*::]*/: 'AXES',
	/*::[*/0x004F/*::]*/: 'LEGEND',
	/*::[*/0x0050/*::]*/: 'ATTACH.TEXT',
	/*::[*/0x0051/*::]*/: 'ADD.ARROW',
	/*::[*/0x0052/*::]*/: 'SELECT.CHART',
	/*::[*/0x0053/*::]*/: 'SELECT.PLOT.AREA',
	/*::[*/0x0054/*::]*/: 'PATTERNS',
	/*::[*/0x0055/*::]*/: 'MAIN.CHART',
	/*::[*/0x0056/*::]*/: 'OVERLAY',
	/*::[*/0x0057/*::]*/: 'SCALE',
	/*::[*/0x0058/*::]*/: 'FORMAT.LEGEND',
	/*::[*/0x0059/*::]*/: 'FORMAT.TEXT',
	/*::[*/0x005A/*::]*/: 'EDIT.REPEAT',
	/*::[*/0x005B/*::]*/: 'PARSE',
	/*::[*/0x005C/*::]*/: 'JUSTIFY',
	/*::[*/0x005D/*::]*/: 'HIDE',
	/*::[*/0x005E/*::]*/: 'UNHIDE',
	/*::[*/0x005F/*::]*/: 'WORKSPACE',
	/*::[*/0x0060/*::]*/: 'FORMULA',
	/*::[*/0x0061/*::]*/: 'FORMULA.FILL',
	/*::[*/0x0062/*::]*/: 'FORMULA.ARRAY',
	/*::[*/0x0063/*::]*/: 'DATA.FIND.NEXT',
	/*::[*/0x0064/*::]*/: 'DATA.FIND.PREV',
	/*::[*/0x0065/*::]*/: 'FORMULA.FIND.NEXT',
	/*::[*/0x0066/*::]*/: 'FORMULA.FIND.PREV',
	/*::[*/0x0067/*::]*/: 'ACTIVATE',
	/*::[*/0x0068/*::]*/: 'ACTIVATE.NEXT',
	/*::[*/0x0069/*::]*/: 'ACTIVATE.PREV',
	/*::[*/0x006A/*::]*/: 'UNLOCKED.NEXT',
	/*::[*/0x006B/*::]*/: 'UNLOCKED.PREV',
	/*::[*/0x006C/*::]*/: 'COPY.PICTURE',
	/*::[*/0x006D/*::]*/: 'SELECT',
	/*::[*/0x006E/*::]*/: 'DELETE.NAME',
	/*::[*/0x006F/*::]*/: 'DELETE.FORMAT',
	/*::[*/0x0070/*::]*/: 'VLINE',
	/*::[*/0x0071/*::]*/: 'HLINE',
	/*::[*/0x0072/*::]*/: 'VPAGE',
	/*::[*/0x0073/*::]*/: 'HPAGE',
	/*::[*/0x0074/*::]*/: 'VSCROLL',
	/*::[*/0x0075/*::]*/: 'HSCROLL',
	/*::[*/0x0076/*::]*/: 'ALERT',
	/*::[*/0x0077/*::]*/: 'NEW',
	/*::[*/0x0078/*::]*/: 'CANCEL.COPY',
	/*::[*/0x0079/*::]*/: 'SHOW.CLIPBOARD',
	/*::[*/0x007A/*::]*/: 'MESSAGE',
	/*::[*/0x007C/*::]*/: 'PASTE.LINK',
	/*::[*/0x007D/*::]*/: 'APP.ACTIVATE',
	/*::[*/0x007E/*::]*/: 'DELETE.ARROW',
	/*::[*/0x007F/*::]*/: 'ROW.HEIGHT',
	/*::[*/0x0080/*::]*/: 'FORMAT.MOVE',
	/*::[*/0x0081/*::]*/: 'FORMAT.SIZE',
	/*::[*/0x0082/*::]*/: 'FORMULA.REPLACE',
	/*::[*/0x0083/*::]*/: 'SEND.KEYS',
	/*::[*/0x0084/*::]*/: 'SELECT.SPECIAL',
	/*::[*/0x0085/*::]*/: 'APPLY.NAMES',
	/*::[*/0x0086/*::]*/: 'REPLACE.FONT',
	/*::[*/0x0087/*::]*/: 'FREEZE.PANES',
	/*::[*/0x0088/*::]*/: 'SHOW.INFO',
	/*::[*/0x0089/*::]*/: 'SPLIT',
	/*::[*/0x008A/*::]*/: 'ON.WINDOW',
	/*::[*/0x008B/*::]*/: 'ON.DATA',
	/*::[*/0x008C/*::]*/: 'DISABLE.INPUT',
	/*::[*/0x008E/*::]*/: 'OUTLINE',
	/*::[*/0x008F/*::]*/: 'LIST.NAMES',
	/*::[*/0x0090/*::]*/: 'FILE.CLOSE',
	/*::[*/0x0091/*::]*/: 'SAVE.WORKBOOK',
	/*::[*/0x0092/*::]*/: 'DATA.FORM',
	/*::[*/0x0093/*::]*/: 'COPY.CHART',
	/*::[*/0x0094/*::]*/: 'ON.TIME',
	/*::[*/0x0095/*::]*/: 'WAIT',
	/*::[*/0x0096/*::]*/: 'FORMAT.FONT',
	/*::[*/0x0097/*::]*/: 'FILL.UP',
	/*::[*/0x0098/*::]*/: 'FILL.LEFT',
	/*::[*/0x0099/*::]*/: 'DELETE.OVERLAY',
	/*::[*/0x009B/*::]*/: 'SHORT.MENUS',
	/*::[*/0x009F/*::]*/: 'SET.UPDATE.STATUS',
	/*::[*/0x00A1/*::]*/: 'COLOR.PALETTE',
	/*::[*/0x00A2/*::]*/: 'DELETE.STYLE',
	/*::[*/0x00A3/*::]*/: 'WINDOW.RESTORE',
	/*::[*/0x00A4/*::]*/: 'WINDOW.MAXIMIZE',
	/*::[*/0x00A6/*::]*/: 'CHANGE.LINK',
	/*::[*/0x00A7/*::]*/: 'CALCULATE.DOCUMENT',
	/*::[*/0x00A8/*::]*/: 'ON.KEY',
	/*::[*/0x00A9/*::]*/: 'APP.RESTORE',
	/*::[*/0x00AA/*::]*/: 'APP.MOVE',
	/*::[*/0x00AB/*::]*/: 'APP.SIZE',
	/*::[*/0x00AC/*::]*/: 'APP.MINIMIZE',
	/*::[*/0x00AD/*::]*/: 'APP.MAXIMIZE',
	/*::[*/0x00AE/*::]*/: 'BRING.TO.FRONT',
	/*::[*/0x00AF/*::]*/: 'SEND.TO.BACK',
	/*::[*/0x00B9/*::]*/: 'MAIN.CHART.TYPE',
	/*::[*/0x00BA/*::]*/: 'OVERLAY.CHART.TYPE',
	/*::[*/0x00BB/*::]*/: 'SELECT.END',
	/*::[*/0x00BC/*::]*/: 'OPEN.MAIL',
	/*::[*/0x00BD/*::]*/: 'SEND.MAIL',
	/*::[*/0x00BE/*::]*/: 'STANDARD.FONT',
	/*::[*/0x00BF/*::]*/: 'CONSOLIDATE',
	/*::[*/0x00C0/*::]*/: 'SORT.SPECIAL',
	/*::[*/0x00C1/*::]*/: 'GALLERY.3D.AREA',
	/*::[*/0x00C2/*::]*/: 'GALLERY.3D.COLUMN',
	/*::[*/0x00C3/*::]*/: 'GALLERY.3D.LINE',
	/*::[*/0x00C4/*::]*/: 'GALLERY.3D.PIE',
	/*::[*/0x00C5/*::]*/: 'VIEW.3D',
	/*::[*/0x00C6/*::]*/: 'GOAL.SEEK',
	/*::[*/0x00C7/*::]*/: 'WORKGROUP',
	/*::[*/0x00C8/*::]*/: 'FILL.GROUP',
	/*::[*/0x00C9/*::]*/: 'UPDATE.LINK',
	/*::[*/0x00CA/*::]*/: 'PROMOTE',
	/*::[*/0x00CB/*::]*/: 'DEMOTE',
	/*::[*/0x00CC/*::]*/: 'SHOW.DETAIL',
	/*::[*/0x00CE/*::]*/: 'UNGROUP',
	/*::[*/0x00CF/*::]*/: 'OBJECT.PROPERTIES',
	/*::[*/0x00D0/*::]*/: 'SAVE.NEW.OBJECT',
	/*::[*/0x00D1/*::]*/: 'SHARE',
	/*::[*/0x00D2/*::]*/: 'SHARE.NAME',
	/*::[*/0x00D3/*::]*/: 'DUPLICATE',
	/*::[*/0x00D4/*::]*/: 'APPLY.STYLE',
	/*::[*/0x00D5/*::]*/: 'ASSIGN.TO.OBJECT',
	/*::[*/0x00D6/*::]*/: 'OBJECT.PROTECTION',
	/*::[*/0x00D7/*::]*/: 'HIDE.OBJECT',
	/*::[*/0x00D8/*::]*/: 'SET.EXTRACT',
	/*::[*/0x00D9/*::]*/: 'CREATE.PUBLISHER',
	/*::[*/0x00DA/*::]*/: 'SUBSCRIBE.TO',
	/*::[*/0x00DB/*::]*/: 'ATTRIBUTES',
	/*::[*/0x00DC/*::]*/: 'SHOW.TOOLBAR',
	/*::[*/0x00DE/*::]*/: 'PRINT.PREVIEW',
	/*::[*/0x00DF/*::]*/: 'EDIT.COLOR',
	/*::[*/0x00E0/*::]*/: 'SHOW.LEVELS',
	/*::[*/0x00E1/*::]*/: 'FORMAT.MAIN',
	/*::[*/0x00E2/*::]*/: 'FORMAT.OVERLAY',
	/*::[*/0x00E3/*::]*/: 'ON.RECALC',
	/*::[*/0x00E4/*::]*/: 'EDIT.SERIES',
	/*::[*/0x00E5/*::]*/: 'DEFINE.STYLE',
	/*::[*/0x00F0/*::]*/: 'LINE.PRINT',
	/*::[*/0x00F3/*::]*/: 'ENTER.DATA',
	/*::[*/0x00F9/*::]*/: 'GALLERY.RADAR',
	/*::[*/0x00FA/*::]*/: 'MERGE.STYLES',
	/*::[*/0x00FB/*::]*/: 'EDITION.OPTIONS',
	/*::[*/0x00FC/*::]*/: 'PASTE.PICTURE',
	/*::[*/0x00FD/*::]*/: 'PASTE.PICTURE.LINK',
	/*::[*/0x00FE/*::]*/: 'SPELLING',
	/*::[*/0x0100/*::]*/: 'ZOOM',
	/*::[*/0x0103/*::]*/: 'INSERT.OBJECT',
	/*::[*/0x0104/*::]*/: 'WINDOW.MINIMIZE',
	/*::[*/0x0109/*::]*/: 'SOUND.NOTE',
	/*::[*/0x010A/*::]*/: 'SOUND.PLAY',
	/*::[*/0x010B/*::]*/: 'FORMAT.SHAPE',
	/*::[*/0x010C/*::]*/: 'EXTEND.POLYGON',
	/*::[*/0x010D/*::]*/: 'FORMAT.AUTO',
	/*::[*/0x0110/*::]*/: 'GALLERY.3D.BAR',
	/*::[*/0x0111/*::]*/: 'GALLERY.3D.SURFACE',
	/*::[*/0x0112/*::]*/: 'FILL.AUTO',
	/*::[*/0x0114/*::]*/: 'CUSTOMIZE.TOOLBAR',
	/*::[*/0x0115/*::]*/: 'ADD.TOOL',
	/*::[*/0x0116/*::]*/: 'EDIT.OBJECT',
	/*::[*/0x0117/*::]*/: 'ON.DOUBLECLICK',
	/*::[*/0x0118/*::]*/: 'ON.ENTRY',
	/*::[*/0x0119/*::]*/: 'WORKBOOK.ADD',
	/*::[*/0x011A/*::]*/: 'WORKBOOK.MOVE',
	/*::[*/0x011B/*::]*/: 'WORKBOOK.COPY',
	/*::[*/0x011C/*::]*/: 'WORKBOOK.OPTIONS',
	/*::[*/0x011D/*::]*/: 'SAVE.WORKSPACE',
	/*::[*/0x0120/*::]*/: 'CHART.WIZARD',
	/*::[*/0x0121/*::]*/: 'DELETE.TOOL',
	/*::[*/0x0122/*::]*/: 'MOVE.TOOL',
	/*::[*/0x0123/*::]*/: 'WORKBOOK.SELECT',
	/*::[*/0x0124/*::]*/: 'WORKBOOK.ACTIVATE',
	/*::[*/0x0125/*::]*/: 'ASSIGN.TO.TOOL',
	/*::[*/0x0127/*::]*/: 'COPY.TOOL',
	/*::[*/0x0128/*::]*/: 'RESET.TOOL',
	/*::[*/0x0129/*::]*/: 'CONSTRAIN.NUMERIC',
	/*::[*/0x012A/*::]*/: 'PASTE.TOOL',
	/*::[*/0x012E/*::]*/: 'WORKBOOK.NEW',
	/*::[*/0x0131/*::]*/: 'SCENARIO.CELLS',
	/*::[*/0x0132/*::]*/: 'SCENARIO.DELETE',
	/*::[*/0x0133/*::]*/: 'SCENARIO.ADD',
	/*::[*/0x0134/*::]*/: 'SCENARIO.EDIT',
	/*::[*/0x0135/*::]*/: 'SCENARIO.SHOW',
	/*::[*/0x0136/*::]*/: 'SCENARIO.SHOW.NEXT',
	/*::[*/0x0137/*::]*/: 'SCENARIO.SUMMARY',
	/*::[*/0x0138/*::]*/: 'PIVOT.TABLE.WIZARD',
	/*::[*/0x0139/*::]*/: 'PIVOT.FIELD.PROPERTIES',
	/*::[*/0x013A/*::]*/: 'PIVOT.FIELD',
	/*::[*/0x013B/*::]*/: 'PIVOT.ITEM',
	/*::[*/0x013C/*::]*/: 'PIVOT.ADD.FIELDS',
	/*::[*/0x013E/*::]*/: 'OPTIONS.CALCULATION',
	/*::[*/0x013F/*::]*/: 'OPTIONS.EDIT',
	/*::[*/0x0140/*::]*/: 'OPTIONS.VIEW',
	/*::[*/0x0141/*::]*/: 'ADDIN.MANAGER',
	/*::[*/0x0142/*::]*/: 'MENU.EDITOR',
	/*::[*/0x0143/*::]*/: 'ATTACH.TOOLBARS',
	/*::[*/0x0144/*::]*/: 'VBAActivate',
	/*::[*/0x0145/*::]*/: 'OPTIONS.CHART',
	/*::[*/0x0148/*::]*/: 'VBA.INSERT.FILE',
	/*::[*/0x014A/*::]*/: 'VBA.PROCEDURE.DEFINITION',
	/*::[*/0x0150/*::]*/: 'ROUTING.SLIP',
	/*::[*/0x0152/*::]*/: 'ROUTE.DOCUMENT',
	/*::[*/0x0153/*::]*/: 'MAIL.LOGON',
	/*::[*/0x0156/*::]*/: 'INSERT.PICTURE',
	/*::[*/0x0157/*::]*/: 'EDIT.TOOL',
	/*::[*/0x0158/*::]*/: 'GALLERY.DOUGHNUT',
	/*::[*/0x015E/*::]*/: 'CHART.TREND',
	/*::[*/0x0160/*::]*/: 'PIVOT.ITEM.PROPERTIES',
	/*::[*/0x0162/*::]*/: 'WORKBOOK.INSERT',
	/*::[*/0x0163/*::]*/: 'OPTIONS.TRANSITION',
	/*::[*/0x0164/*::]*/: 'OPTIONS.GENERAL',
	/*::[*/0x0172/*::]*/: 'FILTER.ADVANCED',
	/*::[*/0x0175/*::]*/: 'MAIL.ADD.MAILER',
	/*::[*/0x0176/*::]*/: 'MAIL.DELETE.MAILER',
	/*::[*/0x0177/*::]*/: 'MAIL.REPLY',
	/*::[*/0x0178/*::]*/: 'MAIL.REPLY.ALL',
	/*::[*/0x0179/*::]*/: 'MAIL.FORWARD',
	/*::[*/0x017A/*::]*/: 'MAIL.NEXT.LETTER',
	/*::[*/0x017B/*::]*/: 'DATA.LABEL',
	/*::[*/0x017C/*::]*/: 'INSERT.TITLE',
	/*::[*/0x017D/*::]*/: 'FONT.PROPERTIES',
	/*::[*/0x017E/*::]*/: 'MACRO.OPTIONS',
	/*::[*/0x017F/*::]*/: 'WORKBOOK.HIDE',
	/*::[*/0x0180/*::]*/: 'WORKBOOK.UNHIDE',
	/*::[*/0x0181/*::]*/: 'WORKBOOK.DELETE',
	/*::[*/0x0182/*::]*/: 'WORKBOOK.NAME',
	/*::[*/0x0184/*::]*/: 'GALLERY.CUSTOM',
	/*::[*/0x0186/*::]*/: 'ADD.CHART.AUTOFORMAT',
	/*::[*/0x0187/*::]*/: 'DELETE.CHART.AUTOFORMAT',
	/*::[*/0x0188/*::]*/: 'CHART.ADD.DATA',
	/*::[*/0x0189/*::]*/: 'AUTO.OUTLINE',
	/*::[*/0x018A/*::]*/: 'TAB.ORDER',
	/*::[*/0x018B/*::]*/: 'SHOW.DIALOG',
	/*::[*/0x018C/*::]*/: 'SELECT.ALL',
	/*::[*/0x018D/*::]*/: 'UNGROUP.SHEETS',
	/*::[*/0x018E/*::]*/: 'SUBTOTAL.CREATE',
	/*::[*/0x018F/*::]*/: 'SUBTOTAL.REMOVE',
	/*::[*/0x0190/*::]*/: 'RENAME.OBJECT',
	/*::[*/0x019C/*::]*/: 'WORKBOOK.SCROLL',
	/*::[*/0x019D/*::]*/: 'WORKBOOK.NEXT',
	/*::[*/0x019E/*::]*/: 'WORKBOOK.PREV',
	/*::[*/0x019F/*::]*/: 'WORKBOOK.TAB.SPLIT',
	/*::[*/0x01A0/*::]*/: 'FULL.SCREEN',
	/*::[*/0x01A1/*::]*/: 'WORKBOOK.PROTECT',
	/*::[*/0x01A4/*::]*/: 'SCROLLBAR.PROPERTIES',
	/*::[*/0x01A5/*::]*/: 'PIVOT.SHOW.PAGES',
	/*::[*/0x01A6/*::]*/: 'TEXT.TO.COLUMNS',
	/*::[*/0x01A7/*::]*/: 'FORMAT.CHARTTYPE',
	/*::[*/0x01A8/*::]*/: 'LINK.FORMAT',
	/*::[*/0x01A9/*::]*/: 'TRACER.DISPLAY',
	/*::[*/0x01AE/*::]*/: 'TRACER.NAVIGATE',
	/*::[*/0x01AF/*::]*/: 'TRACER.CLEAR',
	/*::[*/0x01B0/*::]*/: 'TRACER.ERROR',
	/*::[*/0x01B1/*::]*/: 'PIVOT.FIELD.GROUP',
	/*::[*/0x01B2/*::]*/: 'PIVOT.FIELD.UNGROUP',
	/*::[*/0x01B3/*::]*/: 'CHECKBOX.PROPERTIES',
	/*::[*/0x01B4/*::]*/: 'LABEL.PROPERTIES',
	/*::[*/0x01B5/*::]*/: 'LISTBOX.PROPERTIES',
	/*::[*/0x01B6/*::]*/: 'EDITBOX.PROPERTIES',
	/*::[*/0x01B7/*::]*/: 'PIVOT.REFRESH',
	/*::[*/0x01B8/*::]*/: 'LINK.COMBO',
	/*::[*/0x01B9/*::]*/: 'OPEN.TEXT',
	/*::[*/0x01BA/*::]*/: 'HIDE.DIALOG',
	/*::[*/0x01BB/*::]*/: 'SET.DIALOG.FOCUS',
	/*::[*/0x01BC/*::]*/: 'ENABLE.OBJECT',
	/*::[*/0x01BD/*::]*/: 'PUSHBUTTON.PROPERTIES',
	/*::[*/0x01BE/*::]*/: 'SET.DIALOG.DEFAULT',
	/*::[*/0x01BF/*::]*/: 'FILTER',
	/*::[*/0x01C0/*::]*/: 'FILTER.SHOW.ALL',
	/*::[*/0x01C1/*::]*/: 'CLEAR.OUTLINE',
	/*::[*/0x01C2/*::]*/: 'FUNCTION.WIZARD',
	/*::[*/0x01C3/*::]*/: 'ADD.LIST.ITEM',
	/*::[*/0x01C4/*::]*/: 'SET.LIST.ITEM',
	/*::[*/0x01C5/*::]*/: 'REMOVE.LIST.ITEM',
	/*::[*/0x01C6/*::]*/: 'SELECT.LIST.ITEM',
	/*::[*/0x01C7/*::]*/: 'SET.CONTROL.VALUE',
	/*::[*/0x01C8/*::]*/: 'SAVE.COPY.AS',
	/*::[*/0x01CA/*::]*/: 'OPTIONS.LISTS.ADD',
	/*::[*/0x01CB/*::]*/: 'OPTIONS.LISTS.DELETE',
	/*::[*/0x01CC/*::]*/: 'SERIES.AXES',
	/*::[*/0x01CD/*::]*/: 'SERIES.X',
	/*::[*/0x01CE/*::]*/: 'SERIES.Y',
	/*::[*/0x01CF/*::]*/: 'ERRORBAR.X',
	/*::[*/0x01D0/*::]*/: 'ERRORBAR.Y',
	/*::[*/0x01D1/*::]*/: 'FORMAT.CHART',
	/*::[*/0x01D2/*::]*/: 'SERIES.ORDER',
	/*::[*/0x01D3/*::]*/: 'MAIL.LOGOFF',
	/*::[*/0x01D4/*::]*/: 'CLEAR.ROUTING.SLIP',
	/*::[*/0x01D5/*::]*/: 'APP.ACTIVATE.MICROSOFT',
	/*::[*/0x01D6/*::]*/: 'MAIL.EDIT.MAILER',
	/*::[*/0x01D7/*::]*/: 'ON.SHEET',
	/*::[*/0x01D8/*::]*/: 'STANDARD.WIDTH',
	/*::[*/0x01D9/*::]*/: 'SCENARIO.MERGE',
	/*::[*/0x01DA/*::]*/: 'SUMMARY.INFO',
	/*::[*/0x01DB/*::]*/: 'FIND.FILE',
	/*::[*/0x01DC/*::]*/: 'ACTIVE.CELL.FONT',
	/*::[*/0x01DD/*::]*/: 'ENABLE.TIPWIZARD',
	/*::[*/0x01DE/*::]*/: 'VBA.MAKE.ADDIN',
	/*::[*/0x01E0/*::]*/: 'INSERTDATATABLE',
	/*::[*/0x01E1/*::]*/: 'WORKGROUP.OPTIONS',
	/*::[*/0x01E2/*::]*/: 'MAIL.SEND.MAILER',
	/*::[*/0x01E5/*::]*/: 'AUTOCORRECT',
	/*::[*/0x01E9/*::]*/: 'POST.DOCUMENT',
	/*::[*/0x01EB/*::]*/: 'PICKLIST',
	/*::[*/0x01ED/*::]*/: 'VIEW.SHOW',
	/*::[*/0x01EE/*::]*/: 'VIEW.DEFINE',
	/*::[*/0x01EF/*::]*/: 'VIEW.DELETE',
	/*::[*/0x01FD/*::]*/: 'SHEET.BACKGROUND',
	/*::[*/0x01FE/*::]*/: 'INSERT.MAP.OBJECT',
	/*::[*/0x01FF/*::]*/: 'OPTIONS.MENONO',
	/*::[*/0x0205/*::]*/: 'MSOCHECKS',
	/*::[*/0x0206/*::]*/: 'NORMAL',
	/*::[*/0x0207/*::]*/: 'LAYOUT',
	/*::[*/0x0208/*::]*/: 'RM.PRINT.AREA',
	/*::[*/0x0209/*::]*/: 'CLEAR.PRINT.AREA',
	/*::[*/0x020A/*::]*/: 'ADD.PRINT.AREA',
	/*::[*/0x020B/*::]*/: 'MOVE.BRK',
	/*::[*/0x0221/*::]*/: 'HIDECURR.NOTE',
	/*::[*/0x0222/*::]*/: 'HIDEALL.NOTES',
	/*::[*/0x0223/*::]*/: 'DELETE.NOTE',
	/*::[*/0x0224/*::]*/: 'TRAVERSE.NOTES',
	/*::[*/0x0225/*::]*/: 'ACTIVATE.NOTES',
	/*::[*/0x026C/*::]*/: 'PROTECT.REVISIONS',
	/*::[*/0x026D/*::]*/: 'UNPROTECT.REVISIONS',
	/*::[*/0x0287/*::]*/: 'OPTIONS.ME',
	/*::[*/0x028D/*::]*/: 'WEB.PUBLISH',
	/*::[*/0x029B/*::]*/: 'NEWWEBQUERY',
	/*::[*/0x02A1/*::]*/: 'PIVOT.TABLE.CHART',
	/*::[*/0x02F1/*::]*/: 'OPTIONS.SAVE',
	/*::[*/0x02F3/*::]*/: 'OPTIONS.SPELL',
	/*::[*/0x0328/*::]*/: 'HIDEALL.INKANNOTS'
S
SheetJS 已提交
9877 9878 9879
};

/* [MS-XLS] 2.5.198.17 */
S
SheetJS 已提交
9880
/* [MS-XLSB] 2.5.97.10 */
S
SheetJS 已提交
9881
var Ftab = {
S
SheetJS 已提交
9882 9883 9884 9885 9886 9887 9888 9889 9890 9891 9892 9893 9894 9895 9896 9897 9898 9899 9900 9901 9902 9903 9904 9905 9906 9907 9908 9909 9910 9911 9912 9913 9914 9915 9916 9917 9918 9919 9920 9921 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950 9951 9952 9953 9954 9955 9956 9957 9958 9959 9960 9961 9962 9963 9964 9965 9966 9967 9968 9969 9970 9971 9972 9973 9974 9975 9976 9977 9978 9979 9980 9981 9982 9983 9984 9985 9986 9987 9988 9989 9990 9991 9992 9993 9994 9995 9996 9997 9998 9999 10000 10001 10002 10003 10004 10005 10006 10007 10008 10009 10010 10011 10012 10013 10014 10015 10016 10017 10018 10019 10020 10021 10022 10023 10024 10025 10026 10027 10028 10029 10030 10031 10032 10033 10034 10035 10036 10037 10038 10039 10040 10041 10042 10043 10044 10045 10046 10047 10048 10049 10050 10051 10052 10053 10054 10055 10056 10057 10058 10059 10060 10061 10062 10063 10064 10065 10066 10067 10068 10069 10070 10071 10072 10073 10074 10075 10076 10077 10078 10079 10080 10081 10082 10083 10084 10085 10086 10087 10088 10089 10090 10091 10092 10093 10094 10095 10096 10097 10098 10099 10100 10101 10102 10103 10104 10105 10106 10107 10108 10109 10110 10111 10112 10113 10114 10115 10116 10117 10118 10119 10120 10121 10122 10123 10124 10125 10126 10127 10128 10129 10130 10131 10132 10133 10134 10135 10136 10137 10138 10139 10140 10141 10142 10143 10144 10145 10146 10147 10148 10149 10150 10151 10152 10153 10154 10155 10156 10157 10158 10159 10160 10161 10162 10163 10164 10165 10166 10167 10168 10169 10170 10171 10172 10173 10174 10175 10176 10177 10178 10179 10180 10181 10182 10183 10184 10185 10186 10187 10188 10189 10190 10191 10192 10193 10194 10195 10196 10197 10198 10199 10200 10201 10202 10203 10204 10205 10206 10207 10208 10209 10210 10211 10212 10213 10214 10215 10216 10217 10218 10219 10220 10221 10222 10223 10224 10225 10226 10227 10228 10229 10230 10231 10232 10233 10234 10235 10236 10237 10238 10239 10240 10241 10242 10243 10244 10245 10246 10247 10248 10249 10250 10251 10252 10253
	/*::[*/0x0000/*::]*/: 'COUNT',
	/*::[*/0x0001/*::]*/: 'IF',
	/*::[*/0x0002/*::]*/: 'ISNA',
	/*::[*/0x0003/*::]*/: 'ISERROR',
	/*::[*/0x0004/*::]*/: 'SUM',
	/*::[*/0x0005/*::]*/: 'AVERAGE',
	/*::[*/0x0006/*::]*/: 'MIN',
	/*::[*/0x0007/*::]*/: 'MAX',
	/*::[*/0x0008/*::]*/: 'ROW',
	/*::[*/0x0009/*::]*/: 'COLUMN',
	/*::[*/0x000A/*::]*/: 'NA',
	/*::[*/0x000B/*::]*/: 'NPV',
	/*::[*/0x000C/*::]*/: 'STDEV',
	/*::[*/0x000D/*::]*/: 'DOLLAR',
	/*::[*/0x000E/*::]*/: 'FIXED',
	/*::[*/0x000F/*::]*/: 'SIN',
	/*::[*/0x0010/*::]*/: 'COS',
	/*::[*/0x0011/*::]*/: 'TAN',
	/*::[*/0x0012/*::]*/: 'ATAN',
	/*::[*/0x0013/*::]*/: 'PI',
	/*::[*/0x0014/*::]*/: 'SQRT',
	/*::[*/0x0015/*::]*/: 'EXP',
	/*::[*/0x0016/*::]*/: 'LN',
	/*::[*/0x0017/*::]*/: 'LOG10',
	/*::[*/0x0018/*::]*/: 'ABS',
	/*::[*/0x0019/*::]*/: 'INT',
	/*::[*/0x001A/*::]*/: 'SIGN',
	/*::[*/0x001B/*::]*/: 'ROUND',
	/*::[*/0x001C/*::]*/: 'LOOKUP',
	/*::[*/0x001D/*::]*/: 'INDEX',
	/*::[*/0x001E/*::]*/: 'REPT',
	/*::[*/0x001F/*::]*/: 'MID',
	/*::[*/0x0020/*::]*/: 'LEN',
	/*::[*/0x0021/*::]*/: 'VALUE',
	/*::[*/0x0022/*::]*/: 'TRUE',
	/*::[*/0x0023/*::]*/: 'FALSE',
	/*::[*/0x0024/*::]*/: 'AND',
	/*::[*/0x0025/*::]*/: 'OR',
	/*::[*/0x0026/*::]*/: 'NOT',
	/*::[*/0x0027/*::]*/: 'MOD',
	/*::[*/0x0028/*::]*/: 'DCOUNT',
	/*::[*/0x0029/*::]*/: 'DSUM',
	/*::[*/0x002A/*::]*/: 'DAVERAGE',
	/*::[*/0x002B/*::]*/: 'DMIN',
	/*::[*/0x002C/*::]*/: 'DMAX',
	/*::[*/0x002D/*::]*/: 'DSTDEV',
	/*::[*/0x002E/*::]*/: 'VAR',
	/*::[*/0x002F/*::]*/: 'DVAR',
	/*::[*/0x0030/*::]*/: 'TEXT',
	/*::[*/0x0031/*::]*/: 'LINEST',
	/*::[*/0x0032/*::]*/: 'TREND',
	/*::[*/0x0033/*::]*/: 'LOGEST',
	/*::[*/0x0034/*::]*/: 'GROWTH',
	/*::[*/0x0035/*::]*/: 'GOTO',
	/*::[*/0x0036/*::]*/: 'HALT',
	/*::[*/0x0037/*::]*/: 'RETURN',
	/*::[*/0x0038/*::]*/: 'PV',
	/*::[*/0x0039/*::]*/: 'FV',
	/*::[*/0x003A/*::]*/: 'NPER',
	/*::[*/0x003B/*::]*/: 'PMT',
	/*::[*/0x003C/*::]*/: 'RATE',
	/*::[*/0x003D/*::]*/: 'MIRR',
	/*::[*/0x003E/*::]*/: 'IRR',
	/*::[*/0x003F/*::]*/: 'RAND',
	/*::[*/0x0040/*::]*/: 'MATCH',
	/*::[*/0x0041/*::]*/: 'DATE',
	/*::[*/0x0042/*::]*/: 'TIME',
	/*::[*/0x0043/*::]*/: 'DAY',
	/*::[*/0x0044/*::]*/: 'MONTH',
	/*::[*/0x0045/*::]*/: 'YEAR',
	/*::[*/0x0046/*::]*/: 'WEEKDAY',
	/*::[*/0x0047/*::]*/: 'HOUR',
	/*::[*/0x0048/*::]*/: 'MINUTE',
	/*::[*/0x0049/*::]*/: 'SECOND',
	/*::[*/0x004A/*::]*/: 'NOW',
	/*::[*/0x004B/*::]*/: 'AREAS',
	/*::[*/0x004C/*::]*/: 'ROWS',
	/*::[*/0x004D/*::]*/: 'COLUMNS',
	/*::[*/0x004E/*::]*/: 'OFFSET',
	/*::[*/0x004F/*::]*/: 'ABSREF',
	/*::[*/0x0050/*::]*/: 'RELREF',
	/*::[*/0x0051/*::]*/: 'ARGUMENT',
	/*::[*/0x0052/*::]*/: 'SEARCH',
	/*::[*/0x0053/*::]*/: 'TRANSPOSE',
	/*::[*/0x0054/*::]*/: 'ERROR',
	/*::[*/0x0055/*::]*/: 'STEP',
	/*::[*/0x0056/*::]*/: 'TYPE',
	/*::[*/0x0057/*::]*/: 'ECHO',
	/*::[*/0x0058/*::]*/: 'SET.NAME',
	/*::[*/0x0059/*::]*/: 'CALLER',
	/*::[*/0x005A/*::]*/: 'DEREF',
	/*::[*/0x005B/*::]*/: 'WINDOWS',
	/*::[*/0x005C/*::]*/: 'SERIES',
	/*::[*/0x005D/*::]*/: 'DOCUMENTS',
	/*::[*/0x005E/*::]*/: 'ACTIVE.CELL',
	/*::[*/0x005F/*::]*/: 'SELECTION',
	/*::[*/0x0060/*::]*/: 'RESULT',
	/*::[*/0x0061/*::]*/: 'ATAN2',
	/*::[*/0x0062/*::]*/: 'ASIN',
	/*::[*/0x0063/*::]*/: 'ACOS',
	/*::[*/0x0064/*::]*/: 'CHOOSE',
	/*::[*/0x0065/*::]*/: 'HLOOKUP',
	/*::[*/0x0066/*::]*/: 'VLOOKUP',
	/*::[*/0x0067/*::]*/: 'LINKS',
	/*::[*/0x0068/*::]*/: 'INPUT',
	/*::[*/0x0069/*::]*/: 'ISREF',
	/*::[*/0x006A/*::]*/: 'GET.FORMULA',
	/*::[*/0x006B/*::]*/: 'GET.NAME',
	/*::[*/0x006C/*::]*/: 'SET.VALUE',
	/*::[*/0x006D/*::]*/: 'LOG',
	/*::[*/0x006E/*::]*/: 'EXEC',
	/*::[*/0x006F/*::]*/: 'CHAR',
	/*::[*/0x0070/*::]*/: 'LOWER',
	/*::[*/0x0071/*::]*/: 'UPPER',
	/*::[*/0x0072/*::]*/: 'PROPER',
	/*::[*/0x0073/*::]*/: 'LEFT',
	/*::[*/0x0074/*::]*/: 'RIGHT',
	/*::[*/0x0075/*::]*/: 'EXACT',
	/*::[*/0x0076/*::]*/: 'TRIM',
	/*::[*/0x0077/*::]*/: 'REPLACE',
	/*::[*/0x0078/*::]*/: 'SUBSTITUTE',
	/*::[*/0x0079/*::]*/: 'CODE',
	/*::[*/0x007A/*::]*/: 'NAMES',
	/*::[*/0x007B/*::]*/: 'DIRECTORY',
	/*::[*/0x007C/*::]*/: 'FIND',
	/*::[*/0x007D/*::]*/: 'CELL',
	/*::[*/0x007E/*::]*/: 'ISERR',
	/*::[*/0x007F/*::]*/: 'ISTEXT',
	/*::[*/0x0080/*::]*/: 'ISNUMBER',
	/*::[*/0x0081/*::]*/: 'ISBLANK',
	/*::[*/0x0082/*::]*/: 'T',
	/*::[*/0x0083/*::]*/: 'N',
	/*::[*/0x0084/*::]*/: 'FOPEN',
	/*::[*/0x0085/*::]*/: 'FCLOSE',
	/*::[*/0x0086/*::]*/: 'FSIZE',
	/*::[*/0x0087/*::]*/: 'FREADLN',
	/*::[*/0x0088/*::]*/: 'FREAD',
	/*::[*/0x0089/*::]*/: 'FWRITELN',
	/*::[*/0x008A/*::]*/: 'FWRITE',
	/*::[*/0x008B/*::]*/: 'FPOS',
	/*::[*/0x008C/*::]*/: 'DATEVALUE',
	/*::[*/0x008D/*::]*/: 'TIMEVALUE',
	/*::[*/0x008E/*::]*/: 'SLN',
	/*::[*/0x008F/*::]*/: 'SYD',
	/*::[*/0x0090/*::]*/: 'DDB',
	/*::[*/0x0091/*::]*/: 'GET.DEF',
	/*::[*/0x0092/*::]*/: 'REFTEXT',
	/*::[*/0x0093/*::]*/: 'TEXTREF',
	/*::[*/0x0094/*::]*/: 'INDIRECT',
	/*::[*/0x0095/*::]*/: 'REGISTER',
	/*::[*/0x0096/*::]*/: 'CALL',
	/*::[*/0x0097/*::]*/: 'ADD.BAR',
	/*::[*/0x0098/*::]*/: 'ADD.MENU',
	/*::[*/0x0099/*::]*/: 'ADD.COMMAND',
	/*::[*/0x009A/*::]*/: 'ENABLE.COMMAND',
	/*::[*/0x009B/*::]*/: 'CHECK.COMMAND',
	/*::[*/0x009C/*::]*/: 'RENAME.COMMAND',
	/*::[*/0x009D/*::]*/: 'SHOW.BAR',
	/*::[*/0x009E/*::]*/: 'DELETE.MENU',
	/*::[*/0x009F/*::]*/: 'DELETE.COMMAND',
	/*::[*/0x00A0/*::]*/: 'GET.CHART.ITEM',
	/*::[*/0x00A1/*::]*/: 'DIALOG.BOX',
	/*::[*/0x00A2/*::]*/: 'CLEAN',
	/*::[*/0x00A3/*::]*/: 'MDETERM',
	/*::[*/0x00A4/*::]*/: 'MINVERSE',
	/*::[*/0x00A5/*::]*/: 'MMULT',
	/*::[*/0x00A6/*::]*/: 'FILES',
	/*::[*/0x00A7/*::]*/: 'IPMT',
	/*::[*/0x00A8/*::]*/: 'PPMT',
	/*::[*/0x00A9/*::]*/: 'COUNTA',
	/*::[*/0x00AA/*::]*/: 'CANCEL.KEY',
	/*::[*/0x00AB/*::]*/: 'FOR',
	/*::[*/0x00AC/*::]*/: 'WHILE',
	/*::[*/0x00AD/*::]*/: 'BREAK',
	/*::[*/0x00AE/*::]*/: 'NEXT',
	/*::[*/0x00AF/*::]*/: 'INITIATE',
	/*::[*/0x00B0/*::]*/: 'REQUEST',
	/*::[*/0x00B1/*::]*/: 'POKE',
	/*::[*/0x00B2/*::]*/: 'EXECUTE',
	/*::[*/0x00B3/*::]*/: 'TERMINATE',
	/*::[*/0x00B4/*::]*/: 'RESTART',
	/*::[*/0x00B5/*::]*/: 'HELP',
	/*::[*/0x00B6/*::]*/: 'GET.BAR',
	/*::[*/0x00B7/*::]*/: 'PRODUCT',
	/*::[*/0x00B8/*::]*/: 'FACT',
	/*::[*/0x00B9/*::]*/: 'GET.CELL',
	/*::[*/0x00BA/*::]*/: 'GET.WORKSPACE',
	/*::[*/0x00BB/*::]*/: 'GET.WINDOW',
	/*::[*/0x00BC/*::]*/: 'GET.DOCUMENT',
	/*::[*/0x00BD/*::]*/: 'DPRODUCT',
	/*::[*/0x00BE/*::]*/: 'ISNONTEXT',
	/*::[*/0x00BF/*::]*/: 'GET.NOTE',
	/*::[*/0x00C0/*::]*/: 'NOTE',
	/*::[*/0x00C1/*::]*/: 'STDEVP',
	/*::[*/0x00C2/*::]*/: 'VARP',
	/*::[*/0x00C3/*::]*/: 'DSTDEVP',
	/*::[*/0x00C4/*::]*/: 'DVARP',
	/*::[*/0x00C5/*::]*/: 'TRUNC',
	/*::[*/0x00C6/*::]*/: 'ISLOGICAL',
	/*::[*/0x00C7/*::]*/: 'DCOUNTA',
	/*::[*/0x00C8/*::]*/: 'DELETE.BAR',
	/*::[*/0x00C9/*::]*/: 'UNREGISTER',
	/*::[*/0x00CC/*::]*/: 'USDOLLAR',
	/*::[*/0x00CD/*::]*/: 'FINDB',
	/*::[*/0x00CE/*::]*/: 'SEARCHB',
	/*::[*/0x00CF/*::]*/: 'REPLACEB',
	/*::[*/0x00D0/*::]*/: 'LEFTB',
	/*::[*/0x00D1/*::]*/: 'RIGHTB',
	/*::[*/0x00D2/*::]*/: 'MIDB',
	/*::[*/0x00D3/*::]*/: 'LENB',
	/*::[*/0x00D4/*::]*/: 'ROUNDUP',
	/*::[*/0x00D5/*::]*/: 'ROUNDDOWN',
	/*::[*/0x00D6/*::]*/: 'ASC',
	/*::[*/0x00D7/*::]*/: 'DBCS',
	/*::[*/0x00D8/*::]*/: 'RANK',
	/*::[*/0x00DB/*::]*/: 'ADDRESS',
	/*::[*/0x00DC/*::]*/: 'DAYS360',
	/*::[*/0x00DD/*::]*/: 'TODAY',
	/*::[*/0x00DE/*::]*/: 'VDB',
	/*::[*/0x00DF/*::]*/: 'ELSE',
	/*::[*/0x00E0/*::]*/: 'ELSE.IF',
	/*::[*/0x00E1/*::]*/: 'END.IF',
	/*::[*/0x00E2/*::]*/: 'FOR.CELL',
	/*::[*/0x00E3/*::]*/: 'MEDIAN',
	/*::[*/0x00E4/*::]*/: 'SUMPRODUCT',
	/*::[*/0x00E5/*::]*/: 'SINH',
	/*::[*/0x00E6/*::]*/: 'COSH',
	/*::[*/0x00E7/*::]*/: 'TANH',
	/*::[*/0x00E8/*::]*/: 'ASINH',
	/*::[*/0x00E9/*::]*/: 'ACOSH',
	/*::[*/0x00EA/*::]*/: 'ATANH',
	/*::[*/0x00EB/*::]*/: 'DGET',
	/*::[*/0x00EC/*::]*/: 'CREATE.OBJECT',
	/*::[*/0x00ED/*::]*/: 'VOLATILE',
	/*::[*/0x00EE/*::]*/: 'LAST.ERROR',
	/*::[*/0x00EF/*::]*/: 'CUSTOM.UNDO',
	/*::[*/0x00F0/*::]*/: 'CUSTOM.REPEAT',
	/*::[*/0x00F1/*::]*/: 'FORMULA.CONVERT',
	/*::[*/0x00F2/*::]*/: 'GET.LINK.INFO',
	/*::[*/0x00F3/*::]*/: 'TEXT.BOX',
	/*::[*/0x00F4/*::]*/: 'INFO',
	/*::[*/0x00F5/*::]*/: 'GROUP',
	/*::[*/0x00F6/*::]*/: 'GET.OBJECT',
	/*::[*/0x00F7/*::]*/: 'DB',
	/*::[*/0x00F8/*::]*/: 'PAUSE',
	/*::[*/0x00FB/*::]*/: 'RESUME',
	/*::[*/0x00FC/*::]*/: 'FREQUENCY',
	/*::[*/0x00FD/*::]*/: 'ADD.TOOLBAR',
	/*::[*/0x00FE/*::]*/: 'DELETE.TOOLBAR',
	/*::[*/0x00FF/*::]*/: 'User',
	/*::[*/0x0100/*::]*/: 'RESET.TOOLBAR',
	/*::[*/0x0101/*::]*/: 'EVALUATE',
	/*::[*/0x0102/*::]*/: 'GET.TOOLBAR',
	/*::[*/0x0103/*::]*/: 'GET.TOOL',
	/*::[*/0x0104/*::]*/: 'SPELLING.CHECK',
	/*::[*/0x0105/*::]*/: 'ERROR.TYPE',
	/*::[*/0x0106/*::]*/: 'APP.TITLE',
	/*::[*/0x0107/*::]*/: 'WINDOW.TITLE',
	/*::[*/0x0108/*::]*/: 'SAVE.TOOLBAR',
	/*::[*/0x0109/*::]*/: 'ENABLE.TOOL',
	/*::[*/0x010A/*::]*/: 'PRESS.TOOL',
	/*::[*/0x010B/*::]*/: 'REGISTER.ID',
	/*::[*/0x010C/*::]*/: 'GET.WORKBOOK',
	/*::[*/0x010D/*::]*/: 'AVEDEV',
	/*::[*/0x010E/*::]*/: 'BETADIST',
	/*::[*/0x010F/*::]*/: 'GAMMALN',
	/*::[*/0x0110/*::]*/: 'BETAINV',
	/*::[*/0x0111/*::]*/: 'BINOMDIST',
	/*::[*/0x0112/*::]*/: 'CHIDIST',
	/*::[*/0x0113/*::]*/: 'CHIINV',
	/*::[*/0x0114/*::]*/: 'COMBIN',
	/*::[*/0x0115/*::]*/: 'CONFIDENCE',
	/*::[*/0x0116/*::]*/: 'CRITBINOM',
	/*::[*/0x0117/*::]*/: 'EVEN',
	/*::[*/0x0118/*::]*/: 'EXPONDIST',
	/*::[*/0x0119/*::]*/: 'FDIST',
	/*::[*/0x011A/*::]*/: 'FINV',
	/*::[*/0x011B/*::]*/: 'FISHER',
	/*::[*/0x011C/*::]*/: 'FISHERINV',
	/*::[*/0x011D/*::]*/: 'FLOOR',
	/*::[*/0x011E/*::]*/: 'GAMMADIST',
	/*::[*/0x011F/*::]*/: 'GAMMAINV',
	/*::[*/0x0120/*::]*/: 'CEILING',
	/*::[*/0x0121/*::]*/: 'HYPGEOMDIST',
	/*::[*/0x0122/*::]*/: 'LOGNORMDIST',
	/*::[*/0x0123/*::]*/: 'LOGINV',
	/*::[*/0x0124/*::]*/: 'NEGBINOMDIST',
	/*::[*/0x0125/*::]*/: 'NORMDIST',
	/*::[*/0x0126/*::]*/: 'NORMSDIST',
	/*::[*/0x0127/*::]*/: 'NORMINV',
	/*::[*/0x0128/*::]*/: 'NORMSINV',
	/*::[*/0x0129/*::]*/: 'STANDARDIZE',
	/*::[*/0x012A/*::]*/: 'ODD',
	/*::[*/0x012B/*::]*/: 'PERMUT',
	/*::[*/0x012C/*::]*/: 'POISSON',
	/*::[*/0x012D/*::]*/: 'TDIST',
	/*::[*/0x012E/*::]*/: 'WEIBULL',
	/*::[*/0x012F/*::]*/: 'SUMXMY2',
	/*::[*/0x0130/*::]*/: 'SUMX2MY2',
	/*::[*/0x0131/*::]*/: 'SUMX2PY2',
	/*::[*/0x0132/*::]*/: 'CHITEST',
	/*::[*/0x0133/*::]*/: 'CORREL',
	/*::[*/0x0134/*::]*/: 'COVAR',
	/*::[*/0x0135/*::]*/: 'FORECAST',
	/*::[*/0x0136/*::]*/: 'FTEST',
	/*::[*/0x0137/*::]*/: 'INTERCEPT',
	/*::[*/0x0138/*::]*/: 'PEARSON',
	/*::[*/0x0139/*::]*/: 'RSQ',
	/*::[*/0x013A/*::]*/: 'STEYX',
	/*::[*/0x013B/*::]*/: 'SLOPE',
	/*::[*/0x013C/*::]*/: 'TTEST',
	/*::[*/0x013D/*::]*/: 'PROB',
	/*::[*/0x013E/*::]*/: 'DEVSQ',
	/*::[*/0x013F/*::]*/: 'GEOMEAN',
	/*::[*/0x0140/*::]*/: 'HARMEAN',
	/*::[*/0x0141/*::]*/: 'SUMSQ',
	/*::[*/0x0142/*::]*/: 'KURT',
	/*::[*/0x0143/*::]*/: 'SKEW',
	/*::[*/0x0144/*::]*/: 'ZTEST',
	/*::[*/0x0145/*::]*/: 'LARGE',
	/*::[*/0x0146/*::]*/: 'SMALL',
	/*::[*/0x0147/*::]*/: 'QUARTILE',
	/*::[*/0x0148/*::]*/: 'PERCENTILE',
	/*::[*/0x0149/*::]*/: 'PERCENTRANK',
	/*::[*/0x014A/*::]*/: 'MODE',
	/*::[*/0x014B/*::]*/: 'TRIMMEAN',
	/*::[*/0x014C/*::]*/: 'TINV',
	/*::[*/0x014E/*::]*/: 'MOVIE.COMMAND',
	/*::[*/0x014F/*::]*/: 'GET.MOVIE',
	/*::[*/0x0150/*::]*/: 'CONCATENATE',
	/*::[*/0x0151/*::]*/: 'POWER',
	/*::[*/0x0152/*::]*/: 'PIVOT.ADD.DATA',
	/*::[*/0x0153/*::]*/: 'GET.PIVOT.TABLE',
	/*::[*/0x0154/*::]*/: 'GET.PIVOT.FIELD',
	/*::[*/0x0155/*::]*/: 'GET.PIVOT.ITEM',
	/*::[*/0x0156/*::]*/: 'RADIANS',
	/*::[*/0x0157/*::]*/: 'DEGREES',
	/*::[*/0x0158/*::]*/: 'SUBTOTAL',
	/*::[*/0x0159/*::]*/: 'SUMIF',
	/*::[*/0x015A/*::]*/: 'COUNTIF',
	/*::[*/0x015B/*::]*/: 'COUNTBLANK',
	/*::[*/0x015C/*::]*/: 'SCENARIO.GET',
	/*::[*/0x015D/*::]*/: 'OPTIONS.LISTS.GET',
	/*::[*/0x015E/*::]*/: 'ISPMT',
	/*::[*/0x015F/*::]*/: 'DATEDIF',
	/*::[*/0x0160/*::]*/: 'DATESTRING',
	/*::[*/0x0161/*::]*/: 'NUMBERSTRING',
	/*::[*/0x0162/*::]*/: 'ROMAN',
	/*::[*/0x0163/*::]*/: 'OPEN.DIALOG',
	/*::[*/0x0164/*::]*/: 'SAVE.DIALOG',
	/*::[*/0x0165/*::]*/: 'VIEW.GET',
	/*::[*/0x0166/*::]*/: 'GETPIVOTDATA',
	/*::[*/0x0167/*::]*/: 'HYPERLINK',
	/*::[*/0x0168/*::]*/: 'PHONETIC',
	/*::[*/0x0169/*::]*/: 'AVERAGEA',
	/*::[*/0x016A/*::]*/: 'MAXA',
	/*::[*/0x016B/*::]*/: 'MINA',
	/*::[*/0x016C/*::]*/: 'STDEVPA',
	/*::[*/0x016D/*::]*/: 'VARPA',
	/*::[*/0x016E/*::]*/: 'STDEVA',
	/*::[*/0x016F/*::]*/: 'VARA',
	/*::[*/0x0170/*::]*/: 'BAHTTEXT',
	/*::[*/0x0171/*::]*/: 'THAIDAYOFWEEK',
	/*::[*/0x0172/*::]*/: 'THAIDIGIT',
	/*::[*/0x0173/*::]*/: 'THAIMONTHOFYEAR',
	/*::[*/0x0174/*::]*/: 'THAINUMSOUND',
	/*::[*/0x0175/*::]*/: 'THAINUMSTRING',
	/*::[*/0x0176/*::]*/: 'THAISTRINGLENGTH',
	/*::[*/0x0177/*::]*/: 'ISTHAIDIGIT',
	/*::[*/0x0178/*::]*/: 'ROUNDBAHTDOWN',
	/*::[*/0x0179/*::]*/: 'ROUNDBAHTUP',
	/*::[*/0x017A/*::]*/: 'THAIYEAR',
S
SheetJS 已提交
10254 10255 10256 10257 10258 10259 10260 10261 10262 10263 10264 10265 10266 10267 10268 10269 10270 10271 10272 10273 10274 10275 10276 10277 10278 10279 10280 10281 10282 10283 10284 10285 10286 10287 10288 10289 10290 10291 10292 10293 10294 10295 10296 10297 10298 10299 10300 10301 10302 10303 10304 10305 10306 10307 10308 10309 10310 10311 10312 10313 10314 10315 10316 10317 10318 10319 10320 10321 10322 10323 10324 10325 10326 10327 10328 10329 10330 10331 10332 10333 10334 10335 10336 10337 10338 10339 10340 10341 10342 10343
	/*::[*/0x017B/*::]*/: 'RTD',

	/*::[*/0x017C/*::]*/: 'CUBEVALUE',
	/*::[*/0x017D/*::]*/: 'CUBEMEMBER',
	/*::[*/0x017E/*::]*/: 'CUBEMEMBERPROPERTY',
	/*::[*/0x017F/*::]*/: 'CUBERANKEDMEMBER',
	/*::[*/0x0180/*::]*/: 'HEX2BIN',
	/*::[*/0x0181/*::]*/: 'HEX2DEC',
	/*::[*/0x0182/*::]*/: 'HEX2OCT',
	/*::[*/0x0183/*::]*/: 'DEC2BIN',
	/*::[*/0x0184/*::]*/: 'DEC2HEX',
	/*::[*/0x0185/*::]*/: 'DEC2OCT',
	/*::[*/0x0186/*::]*/: 'OCT2BIN',
	/*::[*/0x0187/*::]*/: 'OCT2HEX',
	/*::[*/0x0188/*::]*/: 'OCT2DEC',
	/*::[*/0x0189/*::]*/: 'BIN2DEC',
	/*::[*/0x018A/*::]*/: 'BIN2OCT',
	/*::[*/0x018B/*::]*/: 'BIN2HEX',
	/*::[*/0x018C/*::]*/: 'IMSUB',
	/*::[*/0x018D/*::]*/: 'IMDIV',
	/*::[*/0x018E/*::]*/: 'IMPOWER',
	/*::[*/0x018F/*::]*/: 'IMABS',
	/*::[*/0x0190/*::]*/: 'IMSQRT',
	/*::[*/0x0191/*::]*/: 'IMLN',
	/*::[*/0x0192/*::]*/: 'IMLOG2',
	/*::[*/0x0193/*::]*/: 'IMLOG10',
	/*::[*/0x0194/*::]*/: 'IMSIN',
	/*::[*/0x0195/*::]*/: 'IMCOS',
	/*::[*/0x0196/*::]*/: 'IMEXP',
	/*::[*/0x0197/*::]*/: 'IMARGUMENT',
	/*::[*/0x0198/*::]*/: 'IMCONJUGATE',
	/*::[*/0x0199/*::]*/: 'IMAGINARY',
	/*::[*/0x019A/*::]*/: 'IMREAL',
	/*::[*/0x019B/*::]*/: 'COMPLEX',
	/*::[*/0x019C/*::]*/: 'IMSUM',
	/*::[*/0x019D/*::]*/: 'IMPRODUCT',
	/*::[*/0x019E/*::]*/: 'SERIESSUM',
	/*::[*/0x019F/*::]*/: 'FACTDOUBLE',
	/*::[*/0x01A0/*::]*/: 'SQRTPI',
	/*::[*/0x01A1/*::]*/: 'QUOTIENT',
	/*::[*/0x01A2/*::]*/: 'DELTA',
	/*::[*/0x01A3/*::]*/: 'GESTEP',
	/*::[*/0x01A4/*::]*/: 'ISEVEN',
	/*::[*/0x01A5/*::]*/: 'ISODD',
	/*::[*/0x01A6/*::]*/: 'MROUND',
	/*::[*/0x01A7/*::]*/: 'ERF',
	/*::[*/0x01A8/*::]*/: 'ERFC',
	/*::[*/0x01A9/*::]*/: 'BESSELJ',
	/*::[*/0x01AA/*::]*/: 'BESSELK',
	/*::[*/0x01AB/*::]*/: 'BESSELY',
	/*::[*/0x01AC/*::]*/: 'BESSELI',
	/*::[*/0x01AD/*::]*/: 'XIRR',
	/*::[*/0x01AE/*::]*/: 'XNPV',
	/*::[*/0x01AF/*::]*/: 'PRICEMAT',
	/*::[*/0x01B0/*::]*/: 'YIELDMAT',
	/*::[*/0x01B1/*::]*/: 'INTRATE',
	/*::[*/0x01B2/*::]*/: 'RECEIVED',
	/*::[*/0x01B3/*::]*/: 'DISC',
	/*::[*/0x01B4/*::]*/: 'PRICEDISC',
	/*::[*/0x01B5/*::]*/: 'YIELDDISC',
	/*::[*/0x01B6/*::]*/: 'TBILLEQ',
	/*::[*/0x01B7/*::]*/: 'TBILLPRICE',
	/*::[*/0x01B8/*::]*/: 'TBILLYIELD',
	/*::[*/0x01B9/*::]*/: 'PRICE',
	/*::[*/0x01BA/*::]*/: 'YIELD',
	/*::[*/0x01BB/*::]*/: 'DOLLARDE',
	/*::[*/0x01BC/*::]*/: 'DOLLARFR',
	/*::[*/0x01BD/*::]*/: 'NOMINAL',
	/*::[*/0x01BE/*::]*/: 'EFFECT',
	/*::[*/0x01BF/*::]*/: 'CUMPRINC',
	/*::[*/0x01C0/*::]*/: 'CUMIPMT',
	/*::[*/0x01C1/*::]*/: 'EDATE',
	/*::[*/0x01C2/*::]*/: 'EOMONTH',
	/*::[*/0x01C3/*::]*/: 'YEARFRAC',
	/*::[*/0x01C4/*::]*/: 'COUPDAYBS',
	/*::[*/0x01C5/*::]*/: 'COUPDAYS',
	/*::[*/0x01C6/*::]*/: 'COUPDAYSNC',
	/*::[*/0x01C7/*::]*/: 'COUPNCD',
	/*::[*/0x01C8/*::]*/: 'COUPNUM',
	/*::[*/0x01C9/*::]*/: 'COUPPCD',
	/*::[*/0x01CA/*::]*/: 'DURATION',
	/*::[*/0x01CB/*::]*/: 'MDURATION',
	/*::[*/0x01CC/*::]*/: 'ODDLPRICE',
	/*::[*/0x01CD/*::]*/: 'ODDLYIELD',
	/*::[*/0x01CE/*::]*/: 'ODDFPRICE',
	/*::[*/0x01CF/*::]*/: 'ODDFYIELD',
	/*::[*/0x01D0/*::]*/: 'RANDBETWEEN',
	/*::[*/0x01D1/*::]*/: 'WEEKNUM',
	/*::[*/0x01D2/*::]*/: 'AMORDEGRC',
	/*::[*/0x01D3/*::]*/: 'AMORLINC',
S
SheetJS 已提交
10344 10345
	/*::[*/0x01D4/*::]*/: 'CONVERT',
	/*::[*/0x02D4/*::]*/: 'SHEETJS',
S
SheetJS 已提交
10346 10347 10348 10349 10350 10351 10352 10353 10354 10355 10356 10357 10358 10359 10360 10361
	/*::[*/0x01D5/*::]*/: 'ACCRINT',
	/*::[*/0x01D6/*::]*/: 'ACCRINTM',
	/*::[*/0x01D7/*::]*/: 'WORKDAY',
	/*::[*/0x01D8/*::]*/: 'NETWORKDAYS',
	/*::[*/0x01D9/*::]*/: 'GCD',
	/*::[*/0x01DA/*::]*/: 'MULTINOMIAL',
	/*::[*/0x01DB/*::]*/: 'LCM',
	/*::[*/0x01DC/*::]*/: 'FVSCHEDULE',
	/*::[*/0x01DD/*::]*/: 'CUBEKPIMEMBER',
	/*::[*/0x01DE/*::]*/: 'CUBESET',
	/*::[*/0x01DF/*::]*/: 'CUBESETCOUNT',
	/*::[*/0x01E0/*::]*/: 'IFERROR',
	/*::[*/0x01E1/*::]*/: 'COUNTIFS',
	/*::[*/0x01E2/*::]*/: 'SUMIFS',
	/*::[*/0x01E3/*::]*/: 'AVERAGEIF',
	/*::[*/0x01E4/*::]*/: 'AVERAGEIFS'
S
SheetJS 已提交
10362 10363
};
var FtabArgc = {
S
SheetJS 已提交
10364 10365 10366 10367 10368 10369
	/*::[*/0x0002/*::]*/: 1, /* ISNA */
	/*::[*/0x0003/*::]*/: 1, /* ISERROR */
	/*::[*/0x000F/*::]*/: 1, /* SIN */
	/*::[*/0x0010/*::]*/: 1, /* COS */
	/*::[*/0x0011/*::]*/: 1, /* TAN */
	/*::[*/0x0012/*::]*/: 1, /* ATAN */
S
SheetJS 已提交
10370
	/*::[*/0x0013/*::]*/: 0, /* PI */
S
SheetJS 已提交
10371 10372 10373 10374 10375 10376 10377 10378 10379 10380 10381 10382 10383 10384 10385 10386 10387 10388 10389 10390 10391 10392 10393 10394 10395 10396 10397 10398 10399
	/*::[*/0x0014/*::]*/: 1, /* SQRT */
	/*::[*/0x0015/*::]*/: 1, /* EXP */
	/*::[*/0x0016/*::]*/: 1, /* LN */
	/*::[*/0x0017/*::]*/: 1, /* LOG10 */
	/*::[*/0x0018/*::]*/: 1, /* ABS */
	/*::[*/0x0019/*::]*/: 1, /* INT */
	/*::[*/0x001A/*::]*/: 1, /* SIGN */
	/*::[*/0x001B/*::]*/: 2, /* ROUND */
	/*::[*/0x001E/*::]*/: 2, /* REPT */
	/*::[*/0x001F/*::]*/: 3, /* MID */
	/*::[*/0x0020/*::]*/: 1, /* LEN */
	/*::[*/0x0021/*::]*/: 1, /* VALUE */
	/*::[*/0x0026/*::]*/: 1, /* NOT */
	/*::[*/0x0027/*::]*/: 2, /* MOD */
	/*::[*/0x0028/*::]*/: 3, /* DCOUNT */
	/*::[*/0x0029/*::]*/: 3, /* DSUM */
	/*::[*/0x002A/*::]*/: 3, /* DAVERAGE */
	/*::[*/0x002B/*::]*/: 3, /* DMIN */
	/*::[*/0x002C/*::]*/: 3, /* DMAX */
	/*::[*/0x002D/*::]*/: 3, /* DSTDEV */
	/*::[*/0x002F/*::]*/: 3, /* DVAR */
	/*::[*/0x0030/*::]*/: 2, /* TEXT */
	/*::[*/0x0035/*::]*/: 1, /* GOTO */
	/*::[*/0x003D/*::]*/: 3, /* MIRR */
	/*::[*/0x0041/*::]*/: 3, /* DATE */
	/*::[*/0x0042/*::]*/: 3, /* TIME */
	/*::[*/0x0043/*::]*/: 1, /* DAY */
	/*::[*/0x0044/*::]*/: 1, /* MONTH */
	/*::[*/0x0045/*::]*/: 1, /* YEAR */
S
SheetJS 已提交
10400
	/*::[*/0x0046/*::]*/: 1, /* WEEKDAY */
S
SheetJS 已提交
10401 10402 10403 10404 10405 10406 10407 10408 10409
	/*::[*/0x0047/*::]*/: 1, /* HOUR */
	/*::[*/0x0048/*::]*/: 1, /* MINUTE */
	/*::[*/0x0049/*::]*/: 1, /* SECOND */
	/*::[*/0x004B/*::]*/: 1, /* AREAS */
	/*::[*/0x004C/*::]*/: 1, /* ROWS */
	/*::[*/0x004D/*::]*/: 1, /* COLUMNS */
	/*::[*/0x004F/*::]*/: 2, /* ABSREF */
	/*::[*/0x0050/*::]*/: 2, /* RELREF */
	/*::[*/0x0053/*::]*/: 1, /* TRANSPOSE */
S
SheetJS 已提交
10410
	/*::[*/0x0055/*::]*/: 0, /* STEP */
S
SheetJS 已提交
10411 10412 10413 10414 10415
	/*::[*/0x0056/*::]*/: 1, /* TYPE */
	/*::[*/0x005A/*::]*/: 1, /* DEREF */
	/*::[*/0x0061/*::]*/: 2, /* ATAN2 */
	/*::[*/0x0062/*::]*/: 1, /* ASIN */
	/*::[*/0x0063/*::]*/: 1, /* ACOS */
S
SheetJS 已提交
10416 10417
	/*::[*/0x0065/*::]*/: 3, /* HLOOKUP */
	/*::[*/0x0066/*::]*/: 3, /* VLOOKUP */
S
SheetJS 已提交
10418 10419 10420 10421 10422 10423 10424 10425 10426 10427 10428 10429 10430 10431 10432 10433 10434 10435 10436 10437 10438 10439 10440 10441 10442
	/*::[*/0x0069/*::]*/: 1, /* ISREF */
	/*::[*/0x006F/*::]*/: 1, /* CHAR */
	/*::[*/0x0070/*::]*/: 1, /* LOWER */
	/*::[*/0x0071/*::]*/: 1, /* UPPER */
	/*::[*/0x0072/*::]*/: 1, /* PROPER */
	/*::[*/0x0075/*::]*/: 2, /* EXACT */
	/*::[*/0x0076/*::]*/: 1, /* TRIM */
	/*::[*/0x0077/*::]*/: 4, /* REPLACE */
	/*::[*/0x0079/*::]*/: 1, /* CODE */
	/*::[*/0x007E/*::]*/: 1, /* ISERR */
	/*::[*/0x007F/*::]*/: 1, /* ISTEXT */
	/*::[*/0x0080/*::]*/: 1, /* ISNUMBER */
	/*::[*/0x0081/*::]*/: 1, /* ISBLANK */
	/*::[*/0x0082/*::]*/: 1, /* T */
	/*::[*/0x0083/*::]*/: 1, /* N */
	/*::[*/0x0085/*::]*/: 1, /* FCLOSE */
	/*::[*/0x0086/*::]*/: 1, /* FSIZE */
	/*::[*/0x0087/*::]*/: 1, /* FREADLN */
	/*::[*/0x0088/*::]*/: 2, /* FREAD */
	/*::[*/0x0089/*::]*/: 2, /* FWRITELN */
	/*::[*/0x008A/*::]*/: 2, /* FWRITE */
	/*::[*/0x008C/*::]*/: 1, /* DATEVALUE */
	/*::[*/0x008D/*::]*/: 1, /* TIMEVALUE */
	/*::[*/0x008E/*::]*/: 3, /* SLN */
	/*::[*/0x008F/*::]*/: 4, /* SYD */
S
SheetJS 已提交
10443
	/*::[*/0x0090/*::]*/: 4, /* DDB */
S
SheetJS 已提交
10444 10445 10446 10447 10448 10449 10450 10451 10452 10453 10454 10455 10456 10457 10458
	/*::[*/0x00A2/*::]*/: 1, /* CLEAN */
	/*::[*/0x00A3/*::]*/: 1, /* MDETERM */
	/*::[*/0x00A4/*::]*/: 1, /* MINVERSE */
	/*::[*/0x00A5/*::]*/: 2, /* MMULT */
	/*::[*/0x00AC/*::]*/: 1, /* WHILE */
	/*::[*/0x00AF/*::]*/: 2, /* INITIATE */
	/*::[*/0x00B0/*::]*/: 2, /* REQUEST */
	/*::[*/0x00B1/*::]*/: 3, /* POKE */
	/*::[*/0x00B2/*::]*/: 2, /* EXECUTE */
	/*::[*/0x00B3/*::]*/: 1, /* TERMINATE */
	/*::[*/0x00B8/*::]*/: 1, /* FACT */
	/*::[*/0x00BD/*::]*/: 3, /* DPRODUCT */
	/*::[*/0x00BE/*::]*/: 1, /* ISNONTEXT */
	/*::[*/0x00C3/*::]*/: 3, /* DSTDEVP */
	/*::[*/0x00C4/*::]*/: 3, /* DVARP */
S
SheetJS 已提交
10459
	/*::[*/0x00C5/*::]*/: 1, /* TRUNC */
S
SheetJS 已提交
10460 10461 10462 10463 10464 10465 10466 10467 10468 10469 10470 10471 10472 10473 10474 10475 10476 10477
	/*::[*/0x00C6/*::]*/: 1, /* ISLOGICAL */
	/*::[*/0x00C7/*::]*/: 3, /* DCOUNTA */
	/*::[*/0x00C9/*::]*/: 1, /* UNREGISTER */
	/*::[*/0x00CF/*::]*/: 4, /* REPLACEB */
	/*::[*/0x00D2/*::]*/: 3, /* MIDB */
	/*::[*/0x00D3/*::]*/: 1, /* LENB */
	/*::[*/0x00D4/*::]*/: 2, /* ROUNDUP */
	/*::[*/0x00D5/*::]*/: 2, /* ROUNDDOWN */
	/*::[*/0x00D6/*::]*/: 1, /* ASC */
	/*::[*/0x00D7/*::]*/: 1, /* DBCS */
	/*::[*/0x00E5/*::]*/: 1, /* SINH */
	/*::[*/0x00E6/*::]*/: 1, /* COSH */
	/*::[*/0x00E7/*::]*/: 1, /* TANH */
	/*::[*/0x00E8/*::]*/: 1, /* ASINH */
	/*::[*/0x00E9/*::]*/: 1, /* ACOSH */
	/*::[*/0x00EA/*::]*/: 1, /* ATANH */
	/*::[*/0x00EB/*::]*/: 3, /* DGET */
	/*::[*/0x00F4/*::]*/: 1, /* INFO */
S
SheetJS 已提交
10478
	/*::[*/0x00F7/*::]*/: 4, /* DB */
S
SheetJS 已提交
10479 10480 10481 10482 10483 10484 10485 10486 10487 10488 10489 10490 10491 10492 10493 10494 10495 10496 10497 10498 10499 10500 10501 10502 10503 10504 10505 10506 10507 10508 10509 10510 10511 10512 10513 10514 10515 10516 10517 10518 10519 10520 10521 10522 10523 10524 10525 10526 10527 10528 10529 10530 10531 10532 10533 10534 10535 10536 10537 10538 10539 10540 10541 10542 10543 10544 10545 10546 10547 10548 10549 10550 10551 10552 10553
	/*::[*/0x00FC/*::]*/: 2, /* FREQUENCY */
	/*::[*/0x0101/*::]*/: 1, /* EVALUATE */
	/*::[*/0x0105/*::]*/: 1, /* ERROR.TYPE */
	/*::[*/0x010F/*::]*/: 1, /* GAMMALN */
	/*::[*/0x0111/*::]*/: 4, /* BINOMDIST */
	/*::[*/0x0112/*::]*/: 2, /* CHIDIST */
	/*::[*/0x0113/*::]*/: 2, /* CHIINV */
	/*::[*/0x0114/*::]*/: 2, /* COMBIN */
	/*::[*/0x0115/*::]*/: 3, /* CONFIDENCE */
	/*::[*/0x0116/*::]*/: 3, /* CRITBINOM */
	/*::[*/0x0117/*::]*/: 1, /* EVEN */
	/*::[*/0x0118/*::]*/: 3, /* EXPONDIST */
	/*::[*/0x0119/*::]*/: 3, /* FDIST */
	/*::[*/0x011A/*::]*/: 3, /* FINV */
	/*::[*/0x011B/*::]*/: 1, /* FISHER */
	/*::[*/0x011C/*::]*/: 1, /* FISHERINV */
	/*::[*/0x011D/*::]*/: 2, /* FLOOR */
	/*::[*/0x011E/*::]*/: 4, /* GAMMADIST */
	/*::[*/0x011F/*::]*/: 3, /* GAMMAINV */
	/*::[*/0x0120/*::]*/: 2, /* CEILING */
	/*::[*/0x0121/*::]*/: 4, /* HYPGEOMDIST */
	/*::[*/0x0122/*::]*/: 3, /* LOGNORMDIST */
	/*::[*/0x0123/*::]*/: 3, /* LOGINV */
	/*::[*/0x0124/*::]*/: 3, /* NEGBINOMDIST */
	/*::[*/0x0125/*::]*/: 4, /* NORMDIST */
	/*::[*/0x0126/*::]*/: 1, /* NORMSDIST */
	/*::[*/0x0127/*::]*/: 3, /* NORMINV */
	/*::[*/0x0128/*::]*/: 1, /* NORMSINV */
	/*::[*/0x0129/*::]*/: 3, /* STANDARDIZE */
	/*::[*/0x012A/*::]*/: 1, /* ODD */
	/*::[*/0x012B/*::]*/: 2, /* PERMUT */
	/*::[*/0x012C/*::]*/: 3, /* POISSON */
	/*::[*/0x012D/*::]*/: 3, /* TDIST */
	/*::[*/0x012E/*::]*/: 4, /* WEIBULL */
	/*::[*/0x012F/*::]*/: 2, /* SUMXMY2 */
	/*::[*/0x0130/*::]*/: 2, /* SUMX2MY2 */
	/*::[*/0x0131/*::]*/: 2, /* SUMX2PY2 */
	/*::[*/0x0132/*::]*/: 2, /* CHITEST */
	/*::[*/0x0133/*::]*/: 2, /* CORREL */
	/*::[*/0x0134/*::]*/: 2, /* COVAR */
	/*::[*/0x0135/*::]*/: 3, /* FORECAST */
	/*::[*/0x0136/*::]*/: 2, /* FTEST */
	/*::[*/0x0137/*::]*/: 2, /* INTERCEPT */
	/*::[*/0x0138/*::]*/: 2, /* PEARSON */
	/*::[*/0x0139/*::]*/: 2, /* RSQ */
	/*::[*/0x013A/*::]*/: 2, /* STEYX */
	/*::[*/0x013B/*::]*/: 2, /* SLOPE */
	/*::[*/0x013C/*::]*/: 4, /* TTEST */
	/*::[*/0x0145/*::]*/: 2, /* LARGE */
	/*::[*/0x0146/*::]*/: 2, /* SMALL */
	/*::[*/0x0147/*::]*/: 2, /* QUARTILE */
	/*::[*/0x0148/*::]*/: 2, /* PERCENTILE */
	/*::[*/0x014B/*::]*/: 2, /* TRIMMEAN */
	/*::[*/0x014C/*::]*/: 2, /* TINV */
	/*::[*/0x0151/*::]*/: 2, /* POWER */
	/*::[*/0x0156/*::]*/: 1, /* RADIANS */
	/*::[*/0x0157/*::]*/: 1, /* DEGREES */
	/*::[*/0x015A/*::]*/: 2, /* COUNTIF */
	/*::[*/0x015B/*::]*/: 1, /* COUNTBLANK */
	/*::[*/0x015E/*::]*/: 4, /* ISPMT */
	/*::[*/0x015F/*::]*/: 3, /* DATEDIF */
	/*::[*/0x0160/*::]*/: 1, /* DATESTRING */
	/*::[*/0x0161/*::]*/: 2, /* NUMBERSTRING */
	/*::[*/0x0168/*::]*/: 1, /* PHONETIC */
	/*::[*/0x0170/*::]*/: 1, /* BAHTTEXT */
	/*::[*/0x0171/*::]*/: 1, /* THAIDAYOFWEEK */
	/*::[*/0x0172/*::]*/: 1, /* THAIDIGIT */
	/*::[*/0x0173/*::]*/: 1, /* THAIMONTHOFYEAR */
	/*::[*/0x0174/*::]*/: 1, /* THAINUMSOUND */
	/*::[*/0x0175/*::]*/: 1, /* THAINUMSTRING */
	/*::[*/0x0176/*::]*/: 1, /* THAISTRINGLENGTH */
	/*::[*/0x0177/*::]*/: 1, /* ISTHAIDIGIT */
	/*::[*/0x0178/*::]*/: 1, /* ROUNDBAHTDOWN */
	/*::[*/0x0179/*::]*/: 1, /* ROUNDBAHTUP */
	/*::[*/0x017A/*::]*/: 1, /* THAIYEAR */
S
SheetJS 已提交
10554 10555 10556 10557 10558 10559 10560 10561 10562 10563 10564 10565 10566 10567 10568 10569 10570 10571 10572 10573 10574
	/*::[*/0x017E/*::]*/: 3, /* CUBEMEMBERPROPERTY */
	/*::[*/0x0181/*::]*/: 1, /* HEX2DEC */
	/*::[*/0x0188/*::]*/: 1, /* OCT2DEC */
	/*::[*/0x0189/*::]*/: 1, /* BIN2DEC */
	/*::[*/0x018C/*::]*/: 2, /* IMSUB */
	/*::[*/0x018D/*::]*/: 2, /* IMDIV */
	/*::[*/0x018E/*::]*/: 2, /* IMPOWER */
	/*::[*/0x018F/*::]*/: 1, /* IMABS */
	/*::[*/0x0190/*::]*/: 1, /* IMSQRT */
	/*::[*/0x0191/*::]*/: 1, /* IMLN */
	/*::[*/0x0192/*::]*/: 1, /* IMLOG2 */
	/*::[*/0x0193/*::]*/: 1, /* IMLOG10 */
	/*::[*/0x0194/*::]*/: 1, /* IMSIN */
	/*::[*/0x0195/*::]*/: 1, /* IMCOS */
	/*::[*/0x0196/*::]*/: 1, /* IMEXP */
	/*::[*/0x0197/*::]*/: 1, /* IMARGUMENT */
	/*::[*/0x0198/*::]*/: 1, /* IMCONJUGATE */
	/*::[*/0x0199/*::]*/: 1, /* IMAGINARY */
	/*::[*/0x019A/*::]*/: 1, /* IMREAL */
	/*::[*/0x019E/*::]*/: 4, /* SERIESSUM */
	/*::[*/0x019F/*::]*/: 1, /* FACTDOUBLE */
S
SheetJS 已提交
10575
	/*::[*/0x01A0/*::]*/: 1, /* SQRTPI */
S
SheetJS 已提交
10576 10577 10578 10579 10580 10581 10582 10583 10584 10585 10586 10587 10588 10589 10590 10591 10592 10593 10594
	/*::[*/0x01A1/*::]*/: 2, /* QUOTIENT */
	/*::[*/0x01A4/*::]*/: 1, /* ISEVEN */
	/*::[*/0x01A5/*::]*/: 1, /* ISODD */
	/*::[*/0x01A6/*::]*/: 2, /* MROUND */
	/*::[*/0x01A8/*::]*/: 1, /* ERFC */
	/*::[*/0x01A9/*::]*/: 2, /* BESSELJ */
	/*::[*/0x01AA/*::]*/: 2, /* BESSELK */
	/*::[*/0x01AB/*::]*/: 2, /* BESSELY */
	/*::[*/0x01AC/*::]*/: 2, /* BESSELI */
	/*::[*/0x01AE/*::]*/: 3, /* XNPV */
	/*::[*/0x01B6/*::]*/: 3, /* TBILLEQ */
	/*::[*/0x01B7/*::]*/: 3, /* TBILLPRICE */
	/*::[*/0x01B8/*::]*/: 3, /* TBILLYIELD */
	/*::[*/0x01BB/*::]*/: 2, /* DOLLARDE */
	/*::[*/0x01BC/*::]*/: 2, /* DOLLARFR */
	/*::[*/0x01BD/*::]*/: 2, /* NOMINAL */
	/*::[*/0x01BE/*::]*/: 2, /* EFFECT */
	/*::[*/0x01BF/*::]*/: 6, /* CUMPRINC */
	/*::[*/0x01C0/*::]*/: 6, /* CUMIPMT */
S
SheetJS 已提交
10595 10596
	/*::[*/0x01C1/*::]*/: 2, /* EDATE */
	/*::[*/0x01C2/*::]*/: 2, /* EOMONTH */
S
SheetJS 已提交
10597 10598 10599 10600 10601
	/*::[*/0x01D0/*::]*/: 2, /* RANDBETWEEN */
	/*::[*/0x01D4/*::]*/: 3, /* CONVERT */
	/*::[*/0x01DC/*::]*/: 2, /* FVSCHEDULE */
	/*::[*/0x01DF/*::]*/: 1, /* CUBESETCOUNT */
	/*::[*/0x01E0/*::]*/: 2, /* IFERROR */
S
SheetJS 已提交
10602
	/*::[*/0xFFFF/*::]*/: 0
S
SheetJS 已提交
10603 10604
};
/* [MS-XLSX] 2.2.3 Functions */
S
SheetJS 已提交
10605
/* [MS-XLSB] 2.5.97.10 Ftab */
S
SheetJS 已提交
10606 10607 10608 10609 10610 10611 10612 10613 10614 10615 10616 10617 10618 10619 10620 10621 10622 10623 10624 10625 10626 10627 10628 10629 10630 10631 10632 10633 10634 10635 10636 10637 10638 10639 10640 10641 10642 10643 10644 10645 10646 10647 10648 10649 10650 10651 10652 10653 10654 10655 10656 10657 10658 10659 10660 10661 10662 10663 10664 10665 10666 10667 10668 10669 10670 10671 10672 10673 10674 10675 10676 10677 10678 10679 10680 10681 10682 10683 10684 10685 10686 10687 10688 10689 10690 10691 10692 10693 10694 10695 10696 10697 10698 10699 10700 10701 10702 10703 10704 10705 10706 10707 10708 10709 10710 10711 10712 10713 10714 10715 10716 10717 10718 10719 10720 10721 10722 10723 10724 10725 10726
var XLSXFutureFunctions = {
	"_xlfn.ACOT": "ACOT",
	"_xlfn.ACOTH": "ACOTH",
	"_xlfn.AGGREGATE": "AGGREGATE",
	"_xlfn.ARABIC": "ARABIC",
	"_xlfn.AVERAGEIF": "AVERAGEIF",
	"_xlfn.AVERAGEIFS": "AVERAGEIFS",
	"_xlfn.BASE": "BASE",
	"_xlfn.BETA.DIST": "BETA.DIST",
	"_xlfn.BETA.INV": "BETA.INV",
	"_xlfn.BINOM.DIST": "BINOM.DIST",
	"_xlfn.BINOM.DIST.RANGE": "BINOM.DIST.RANGE",
	"_xlfn.BINOM.INV": "BINOM.INV",
	"_xlfn.BITAND": "BITAND",
	"_xlfn.BITLSHIFT": "BITLSHIFT",
	"_xlfn.BITOR": "BITOR",
	"_xlfn.BITRSHIFT": "BITRSHIFT",
	"_xlfn.BITXOR": "BITXOR",
	"_xlfn.CEILING.MATH": "CEILING.MATH",
	"_xlfn.CEILING.PRECISE": "CEILING.PRECISE",
	"_xlfn.CHISQ.DIST": "CHISQ.DIST",
	"_xlfn.CHISQ.DIST.RT": "CHISQ.DIST.RT",
	"_xlfn.CHISQ.INV": "CHISQ.INV",
	"_xlfn.CHISQ.INV.RT": "CHISQ.INV.RT",
	"_xlfn.CHISQ.TEST": "CHISQ.TEST",
	"_xlfn.COMBINA": "COMBINA",
	"_xlfn.CONFIDENCE.NORM": "CONFIDENCE.NORM",
	"_xlfn.CONFIDENCE.T": "CONFIDENCE.T",
	"_xlfn.COT": "COT",
	"_xlfn.COTH": "COTH",
	"_xlfn.COUNTIFS": "COUNTIFS",
	"_xlfn.COVARIANCE.P": "COVARIANCE.P",
	"_xlfn.COVARIANCE.S": "COVARIANCE.S",
	"_xlfn.CSC": "CSC",
	"_xlfn.CSCH": "CSCH",
	"_xlfn.DAYS": "DAYS",
	"_xlfn.DECIMAL": "DECIMAL",
	"_xlfn.ECMA.CEILING": "ECMA.CEILING",
	"_xlfn.ERF.PRECISE": "ERF.PRECISE",
	"_xlfn.ERFC.PRECISE": "ERFC.PRECISE",
	"_xlfn.EXPON.DIST": "EXPON.DIST",
	"_xlfn.F.DIST": "F.DIST",
	"_xlfn.F.DIST.RT": "F.DIST.RT",
	"_xlfn.F.INV": "F.INV",
	"_xlfn.F.INV.RT": "F.INV.RT",
	"_xlfn.F.TEST": "F.TEST",
	"_xlfn.FILTERXML": "FILTERXML",
	"_xlfn.FLOOR.MATH": "FLOOR.MATH",
	"_xlfn.FLOOR.PRECISE": "FLOOR.PRECISE",
	"_xlfn.FORMULATEXT": "FORMULATEXT",
	"_xlfn.GAMMA": "GAMMA",
	"_xlfn.GAMMA.DIST": "GAMMA.DIST",
	"_xlfn.GAMMA.INV": "GAMMA.INV",
	"_xlfn.GAMMALN.PRECISE": "GAMMALN.PRECISE",
	"_xlfn.GAUSS": "GAUSS",
	"_xlfn.HYPGEOM.DIST": "HYPGEOM.DIST",
	"_xlfn.IFNA": "IFNA",
	"_xlfn.IFERROR": "IFERROR",
	"_xlfn.IMCOSH": "IMCOSH",
	"_xlfn.IMCOT": "IMCOT",
	"_xlfn.IMCSC": "IMCSC",
	"_xlfn.IMCSCH": "IMCSCH",
	"_xlfn.IMSEC": "IMSEC",
	"_xlfn.IMSECH": "IMSECH",
	"_xlfn.IMSINH": "IMSINH",
	"_xlfn.IMTAN": "IMTAN",
	"_xlfn.ISFORMULA": "ISFORMULA",
	"_xlfn.ISO.CEILING": "ISO.CEILING",
	"_xlfn.ISOWEEKNUM": "ISOWEEKNUM",
	"_xlfn.LOGNORM.DIST": "LOGNORM.DIST",
	"_xlfn.LOGNORM.INV": "LOGNORM.INV",
	"_xlfn.MODE.MULT": "MODE.MULT",
	"_xlfn.MODE.SNGL": "MODE.SNGL",
	"_xlfn.MUNIT": "MUNIT",
	"_xlfn.NEGBINOM.DIST": "NEGBINOM.DIST",
	"_xlfn.NETWORKDAYS.INTL": "NETWORKDAYS.INTL",
	"_xlfn.NIGBINOM": "NIGBINOM",
	"_xlfn.NORM.DIST": "NORM.DIST",
	"_xlfn.NORM.INV": "NORM.INV",
	"_xlfn.NORM.S.DIST": "NORM.S.DIST",
	"_xlfn.NORM.S.INV": "NORM.S.INV",
	"_xlfn.NUMBERVALUE": "NUMBERVALUE",
	"_xlfn.PDURATION": "PDURATION",
	"_xlfn.PERCENTILE.EXC": "PERCENTILE.EXC",
	"_xlfn.PERCENTILE.INC": "PERCENTILE.INC",
	"_xlfn.PERCENTRANK.EXC": "PERCENTRANK.EXC",
	"_xlfn.PERCENTRANK.INC": "PERCENTRANK.INC",
	"_xlfn.PERMUTATIONA": "PERMUTATIONA",
	"_xlfn.PHI": "PHI",
	"_xlfn.POISSON.DIST": "POISSON.DIST",
	"_xlfn.QUARTILE.EXC": "QUARTILE.EXC",
	"_xlfn.QUARTILE.INC": "QUARTILE.INC",
	"_xlfn.QUERYSTRING": "QUERYSTRING",
	"_xlfn.RANK.AVG": "RANK.AVG",
	"_xlfn.RANK.EQ": "RANK.EQ",
	"_xlfn.RRI": "RRI",
	"_xlfn.SEC": "SEC",
	"_xlfn.SECH": "SECH",
	"_xlfn.SHEET": "SHEET",
	"_xlfn.SHEETS": "SHEETS",
	"_xlfn.SKEW.P": "SKEW.P",
	"_xlfn.STDEV.P": "STDEV.P",
	"_xlfn.STDEV.S": "STDEV.S",
	"_xlfn.SUMIFS": "SUMIFS",
	"_xlfn.T.DIST": "T.DIST",
	"_xlfn.T.DIST.2T": "T.DIST.2T",
	"_xlfn.T.DIST.RT": "T.DIST.RT",
	"_xlfn.T.INV": "T.INV",
	"_xlfn.T.INV.2T": "T.INV.2T",
	"_xlfn.T.TEST": "T.TEST",
	"_xlfn.UNICHAR": "UNICHAR",
	"_xlfn.UNICODE": "UNICODE",
	"_xlfn.VAR.P": "VAR.P",
	"_xlfn.VAR.S": "VAR.S",
	"_xlfn.WEBSERVICE": "WEBSERVICE",
	"_xlfn.WEIBULL.DIST": "WEIBULL.DIST",
	"_xlfn.WORKDAY.INTL": "WORKDAY.INTL",
	"_xlfn.XOR": "XOR",
	"_xlfn.Z.TEST": "Z.TEST"
};

10727 10728 10729 10730 10731 10732 10733 10734
/* Part 3 TODO: actually parse formulae */
function ods_to_csf_formula(f/*:string*/)/*:string*/ {
	if(f.substr(0,3) == "of:") f = f.substr(3);
	/* 5.2 Basic Expressions */
	if(f.charCodeAt(0) == 61) {
		f = f.substr(1);
		if(f.charCodeAt(0) == 61) f = f.substr(1);
	}
S
SheetJS 已提交
10735
	f = f.replace(/COM\.MICROSOFT\./g, "");
10736
	/* Part 3 Section 5.8 References */
S
SheetJS 已提交
10737 10738 10739 10740 10741 10742 10743 10744 10745 10746
	f = f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, function($$, $1) { return $1.replace(/\./g,""); });
	/* TODO: something other than this */
	f = f.replace(/\[.(#[A-Z]*[?!])\]/g, "$1");
	return f.replace(/[;~]/g,",").replace(/\|/g,";");
}

function csf_to_ods_formula(f/*:string*/)/*:string*/ {
	var o = "of:=" + f.replace(crefregex, "$1[.$2$3$4$5]").replace(/\]:\[/g,":");
	/* TODO: something other than this */
	return o.replace(/;/g, "|").replace(/,/g,";");
10747
}
S
SheetJS 已提交
10748

S
SheetJS 已提交
10749
function ods_to_csf_range_3D(r/*:string*/)/*:[string, string]*/ {
S
SheetJS 已提交
10750 10751 10752 10753
	var a = r.split(":");
	var s = a[0].split(".")[0];
	return [s, a[0].split(".")[1] + ":" + a[1].split(".")[1]];
}
S
SheetJS 已提交
10754 10755 10756
var strs = {}; // shared strings
var _ssfopts = {}; // spreadsheet formatting options

10757 10758 10759 10760
RELS.WS = [
	"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
	"http://purl.oclc.org/ooxml/officeDocument/relationships/worksheet"
];
S
SheetJS 已提交
10761

S
SheetJS 已提交
10762
function get_sst_id(sst/*:SST*/, str/*:string*/)/*:number*/ {
S
SheetJS 已提交
10763 10764 10765 10766
	for(var i = 0, len = sst.length; i < len; ++i) if(sst[i].t === str) { sst.Count ++; return i; }
	sst[len] = {t:str}; sst.Count ++; sst.Unique ++; return len;
}

S
SheetJS 已提交
10767 10768 10769
function col_obj_w(C/*:number*/, col) {
	var p = ({min:C+1,max:C+1}/*:any*/);
	/* wch (chars), wpx (pixels) */
S
SheetJS 已提交
10770
	var wch = -1;
S
SheetJS 已提交
10771 10772
	if(col.MDW) MDW = col.MDW;
	if(col.width != null) p.customWidth = 1;
S
SheetJS 已提交
10773 10774 10775 10776 10777
	else if(col.wpx != null) wch = px2char(col.wpx);
	else if(col.wch != null) wch = col.wch;
	if(wch > -1) { p.width = char2width(wch); p.customWidth = 1; }
	else if(col.width != null) p.width = col.width;
	if(col.hidden) p.hidden = true;
S
SheetJS 已提交
10778 10779 10780
	return p;
}

S
SheetJS 已提交
10781
function default_margins(margins/*:Margins*/, mode/*:?string*/) {
S
SheetJS 已提交
10782 10783 10784 10785 10786 10787 10788 10789 10790 10791 10792
	if(!margins) return;
	var defs = [0.7, 0.7, 0.75, 0.75, 0.3, 0.3];
	if(mode == 'xlml') defs = [1, 1, 1, 1, 0.5, 0.5];
	if(margins.left   == null) margins.left   = defs[0];
	if(margins.right  == null) margins.right  = defs[1];
	if(margins.top    == null) margins.top    = defs[2];
	if(margins.bottom == null) margins.bottom = defs[3];
	if(margins.header == null) margins.header = defs[4];
	if(margins.footer == null) margins.footer = defs[5];
}

S
SheetJS 已提交
10793 10794
function get_cell_style(styles, cell, opts) {
	var z = opts.revssf[cell.z != null ? cell.z : "General"];
S
SheetJS 已提交
10795 10796 10797 10798 10799 10800 10801 10802 10803 10804
	var i = 0x3c, len = styles.length;
	if(z == null && opts.ssf) {
		for(; i < 0x188; ++i) if(opts.ssf[i] == null) {
			SSF.load(cell.z, i);
			opts.ssf[i] = cell.z;
			opts.revssf[cell.z] = z = i;
			break;
		}
	}
	for(i = 0; i != len; ++i) if(styles[i].numFmtId === z) return i;
S
SheetJS 已提交
10805 10806 10807 10808 10809 10810 10811 10812 10813 10814 10815
	styles[len] = {
		numFmtId:z,
		fontId:0,
		fillId:0,
		borderId:0,
		xfId:0,
		applyNumberFormat:1
	};
	return len;
}

S
SheetJS 已提交
10816
function safe_format(p, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) {
S
SheetJS 已提交
10817
	if(p.t === 'z') return;
S
SheetJS 已提交
10818
	if(p.t === 'd' && typeof p.v === 'string') p.v = parseDate(p.v);
S
SheetJS 已提交
10819
	try {
S
SheetJS 已提交
10820 10821 10822
		if(opts.cellNF) p.z = SSF._table[fmtid];
	} catch(e) { if(opts.WTF) throw e; }
	if(!opts || opts.cellText !== false) try {
S
SheetJS 已提交
10823 10824 10825
		if(p.t === 'e') p.w = p.w || BErr[p.v];
		else if(fmtid === 0) {
			if(p.t === 'n') {
S
SheetJS 已提交
10826 10827
				if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
				else p.w = SSF._general_num(p.v);
S
SheetJS 已提交
10828 10829 10830
			}
			else if(p.t === 'd') {
				var dd = datenum(p.v);
S
SheetJS 已提交
10831 10832
				if((dd|0) === dd) p.w = SSF._general_int(dd);
				else p.w = SSF._general_num(dd);
S
SheetJS 已提交
10833 10834 10835 10836 10837 10838 10839
			}
			else if(p.v === undefined) return "";
			else p.w = SSF._general(p.v,_ssfopts);
		}
		else if(p.t === 'd') p.w = SSF.format(fmtid,datenum(p.v),_ssfopts);
		else p.w = SSF.format(fmtid,p.v,_ssfopts);
	} catch(e) { if(opts.WTF) throw e; }
S
SheetJS 已提交
10840 10841
	if(!opts.cellStyles) return;
	if(fillid != null) try {
S
SheetJS 已提交
10842
		p.s = styles.Fills[fillid];
S
SheetJS 已提交
10843
		if (p.s.fgColor && p.s.fgColor.theme && !p.s.fgColor.rgb) {
S
SheetJS 已提交
10844 10845 10846 10847 10848 10849 10850
			p.s.fgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.fgColor.theme].rgb, p.s.fgColor.tint || 0);
			if(opts.WTF) p.s.fgColor.raw_rgb = themes.themeElements.clrScheme[p.s.fgColor.theme].rgb;
		}
		if (p.s.bgColor && p.s.bgColor.theme) {
			p.s.bgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.bgColor.theme].rgb, p.s.bgColor.tint || 0);
			if(opts.WTF) p.s.bgColor.raw_rgb = themes.themeElements.clrScheme[p.s.bgColor.theme].rgb;
		}
S
SheetJS 已提交
10851
	} catch(e) { if(opts.WTF && styles.Fills) throw e; }
S
SheetJS 已提交
10852 10853 10854 10855 10856
}
function parse_ws_xml_dim(ws, s) {
	var d = safe_decode_range(s);
	if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d);
}
S
SheetJS 已提交
10857
var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*[\/]?>/g;
S
SheetJS 已提交
10858
var sheetdataregex = /<(?:\w+:)?sheetData>([\s\S]*)<\/(?:\w+:)?sheetData>/;
10859
var hlinkregex = /<(?:\w:)?hyperlink [^>]*>/mg;
S
SheetJS 已提交
10860
var dimregex = /"(\w*:\w*)"/;
10861
var colregex = /<(?:\w:)?col[^>]*[\/]?>/g;
S
SheetJS 已提交
10862
var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
S
SheetJS 已提交
10863
var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g;
S
SheetJS 已提交
10864
/* 18.3 Worksheets */
S
SheetJS 已提交
10865
function parse_ws_xml(data/*:?string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
S
SheetJS 已提交
10866
	if(!data) return data;
10867
	if(DENSE != null && opts.dense == null) opts.dense = DENSE;
S
SheetJS 已提交
10868

S
SheetJS 已提交
10869
	/* 18.3.1.99 worksheet CT_Worksheet */
S
SheetJS 已提交
10870
	var s = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
S
SheetJS 已提交
10871 10872 10873
	var refguess/*:Range*/ = ({s: {r:2000000, c:2000000}, e: {r:0, c:0} }/*:any*/);

	var data1 = "", data2 = "";
S
SheetJS 已提交
10874
	var mtch/*:?any*/ = data.match(sheetdataregex);
S
SheetJS 已提交
10875 10876 10877 10878
	if(mtch) {
		data1 = data.substr(0, mtch.index);
		data2 = data.substr(mtch.index + mtch[0].length);
	} else data1 = data2 = data;
S
SheetJS 已提交
10879 10880

	/* 18.3.1.35 dimension CT_SheetDimension ? */
S
SheetJS 已提交
10881
	// $FlowIgnore
S
SheetJS 已提交
10882
	var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
S
SheetJS 已提交
10883
	if(ridx > 0) {
S
SheetJS 已提交
10884 10885
		var ref = data1.substr(ridx,50).match(dimregex);
		if(ref) parse_ws_xml_dim(s, ref[1]);
S
SheetJS 已提交
10886 10887 10888 10889
	}

	/* 18.3.1.17 cols CT_Cols */
	var columns = [];
S
SheetJS 已提交
10890
	if(opts.cellStyles) {
S
SheetJS 已提交
10891
		/* 18.3.1.13 col CT_Col */
S
SheetJS 已提交
10892
		var cols = data1.match(colregex);
S
SheetJS 已提交
10893
		if(cols) parse_ws_xml_cols(columns, cols);
S
SheetJS 已提交
10894 10895 10896
	}

	/* 18.3.1.80 sheetData CT_SheetData ? */
S
SheetJS 已提交
10897
	if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
S
SheetJS 已提交
10898

S
SheetJS 已提交
10899 10900 10901 10902 10903 10904 10905 10906 10907 10908
	/* 18.3.1.2  autoFilter CT_AutoFilter */
	var afilter = data2.match(afregex);
	if(afilter) s['!autofilter'] = parse_ws_xml_autofilter(afilter[0]);

	/* 18.3.1.55 mergeCells CT_MergeCells */
	var mergecells = [];
	var merges = data2.match(mergecregex);
	if(merges) for(ridx = 0; ridx != merges.length; ++ridx)
		mergecells[ridx] = safe_decode_range(merges[ridx].substr(merges[ridx].indexOf("\"")+1));

S
SheetJS 已提交
10909
	/* 18.3.1.48 hyperlinks CT_Hyperlinks */
S
SheetJS 已提交
10910
	var hlink = data2.match(hlinkregex);
S
SheetJS 已提交
10911
	if(hlink) parse_ws_xml_hlinks(s, hlink, rels);
S
SheetJS 已提交
10912

S
SheetJS 已提交
10913 10914 10915 10916
	/* 18.3.1.62 pageMargins CT_PageMargins */
	var margins = data2.match(marginregex);
	if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));

S
SheetJS 已提交
10917 10918 10919 10920 10921 10922 10923 10924 10925 10926 10927 10928 10929 10930
	if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
	if(opts.sheetRows > 0 && s["!ref"]) {
		var tmpref = safe_decode_range(s["!ref"]);
		if(opts.sheetRows < +tmpref.e.r) {
			tmpref.e.r = opts.sheetRows - 1;
			if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
			if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
			if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c;
			if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c;
			s["!fullref"] = s["!ref"];
			s["!ref"] = encode_range(tmpref);
		}
	}
	if(columns.length > 0) s["!cols"] = columns;
10931
	if(mergecells.length > 0) s["!merges"] = mergecells;
S
SheetJS 已提交
10932 10933 10934 10935 10936 10937 10938 10939 10940 10941
	return s;
}

function write_ws_xml_merges(merges) {
	if(merges.length == 0) return "";
	var o = '<mergeCells count="' + merges.length + '">';
	for(var i = 0; i != merges.length; ++i) o += '<mergeCell ref="' + encode_range(merges[i]) + '"/>';
	return o + '</mergeCells>';
}

M
Mior 已提交
10942 10943 10944 10945 10946 10947 10948 10949 10950 10951 10952 10953 10954 10955 10956 10957 10958 10959
/* 18.3.1.85 sheetPr CT_SheetProtection */
function write_ws_xml_protection(sp)/*:string*/ {
	// algorithmName, hashValue, saltValue, spinCountpassword
	var o = ({sheet:1}/*:any*/);
	var deffalse = ["objects", "scenarios", "selectLockedCells", "selectUnlockedCells"];
	var deftrue = [
		"formatColumns", "formatRows", "formatCells",
		"insertColumns", "insertRows", "insertHyperlinks",
		"deleteColumns", "deleteRows",
		"sort", "autoFilter", "pivotTables"
	];
	deffalse.forEach(function(n) { if(sp[n] != null && sp[n]) o[n] = "1"; });
	deftrue.forEach(function(n) { if(sp[n] != null && !sp[n]) o[n] = "0"; });
	/* TODO: algorithm */
	if(sp.password) o.password = crypto_CreatePasswordVerifier_Method1(sp.password).toString(16).toUpperCase();
	return writextag('sheetProtection', null, o);
}

S
SheetJS 已提交
10960
function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
S
SheetJS 已提交
10961
	var dense = Array.isArray(s);
S
SheetJS 已提交
10962
	for(var i = 0; i != data.length; ++i) {
S
SheetJS 已提交
10963
		var val = parsexmltag(utf8read(data[i]), true);
S
SheetJS 已提交
10964 10965 10966 10967 10968 10969 10970 10971 10972 10973 10974
		if(!val.ref) return;
		var rel = rels ? rels['!id'][val.id] : null;
		if(rel) {
			val.Target = rel.Target;
			if(val.location) val.Target += "#"+val.location;
			val.Rel = rel;
		} else {
			val.Target = val.location;
			rel = {Target: val.location, TargetMode: 'Internal'};
			val.Rel = rel;
		}
S
SheetJS 已提交
10975
		if(val.tooltip) { val.Tooltip = val.tooltip; delete val.tooltip; }
S
SheetJS 已提交
10976 10977 10978
		var rng = safe_decode_range(val.ref);
		for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
			var addr = encode_cell({c:C,r:R});
S
SheetJS 已提交
10979 10980 10981 10982 10983 10984 10985 10986
			if(dense) {
				if(!s[R]) s[R] = [];
				if(!s[R][C]) s[R][C] = {t:"z",v:undefined};
				s[R][C].l = val;
			} else {
				if(!s[addr]) s[addr] = {t:"z",v:undefined};
				s[addr].l = val;
			}
S
SheetJS 已提交
10987 10988 10989 10990
		}
	}
}

S
SheetJS 已提交
10991 10992 10993 10994 10995 10996 10997
function parse_ws_xml_margins(margin) {
	var o = {};
	["left", "right", "top", "bottom", "header", "footer"].forEach(function(k) {
		if(margin[k]) o[k] = parseFloat(margin[k]);
	});
	return o;
}
S
Siguza 已提交
10998 10999 11000 11001
function write_ws_xml_margins(margin) {
	default_margins(margin);
	return writextag('pageMargins', null, margin);
}
S
SheetJS 已提交
11002

S
SheetJS 已提交
11003 11004 11005 11006
function parse_ws_xml_cols(columns, cols) {
	var seencol = false;
	for(var coli = 0; coli != cols.length; ++coli) {
		var coll = parsexmltag(cols[coli], true);
S
SheetJS 已提交
11007
		if(coll.hidden) coll.hidden = parsexmlbool(coll.hidden);
S
SheetJS 已提交
11008
		var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
S
SheetJS 已提交
11009 11010 11011 11012
		delete coll.min; delete coll.max; coll.width = +coll.width;
		if(!seencol && coll.width) { seencol = true; find_mdw_colw(coll.width); }
		process_col(coll);
		while(colm <= colM) columns[colm++] = dup(coll);
S
SheetJS 已提交
11013 11014 11015
	}
}

S
SheetJS 已提交
11016
function write_ws_xml_cols(ws, cols)/*:string*/ {
S
SheetJS 已提交
11017 11018 11019
	var o = ["<cols>"], col, width;
	for(var i = 0; i != cols.length; ++i) {
		if(!(col = cols[i])) continue;
S
SheetJS 已提交
11020
		o[o.length] = (writextag('col', null, col_obj_w(i, col)));
S
SheetJS 已提交
11021 11022 11023 11024 11025
	}
	o[o.length] = "</cols>";
	return o.join("");
}

S
SheetJS 已提交
11026 11027 11028 11029 11030 11031 11032 11033
function parse_ws_xml_autofilter(data) {
	var o = { ref: (data.match(/ref="([^"]*)"/)||[])[1]};
	return o;
}
function write_ws_xml_autofilter(data)/*:string*/ {
	return writextag("autoFilter", null, {ref:data.ref});
}

S
SheetJS 已提交
11034 11035 11036 11037 11038 11039
/* 18.3.1.88 sheetViews CT_SheetViews */
/* 18.3.1.87 sheetView CT_SheetView */
function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
	return writextag("sheetViews", writextag("sheetView", null, {workbookViewId:"0"}), {});
}

S
SheetJS 已提交
11040
function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
S
SheetJS 已提交
11041
	if(cell.v === undefined && cell.f === undefined || cell.t === 'z') return "";
S
SheetJS 已提交
11042 11043 11044 11045 11046 11047 11048
	var vv = "";
	var oldt = cell.t, oldv = cell.v;
	switch(cell.t) {
		case 'b': vv = cell.v ? "1" : "0"; break;
		case 'n': vv = ''+cell.v; break;
		case 'e': vv = BErr[cell.v]; break;
		case 'd':
S
SheetJS 已提交
11049
			if(opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
S
SheetJS 已提交
11050 11051
			else {
				cell.t = 'n';
S
SheetJS 已提交
11052
				vv = ''+(cell.v = datenum(parseDate(cell.v)));
S
SheetJS 已提交
11053
			}
S
SheetJS 已提交
11054
			if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
S
SheetJS 已提交
11055 11056 11057
			break;
		default: vv = cell.v; break;
	}
S
SheetJS 已提交
11058
	var v = writetag('v', escapexml(vv)), o = ({r:ref}/*:any*/);
S
SheetJS 已提交
11059 11060 11061 11062 11063 11064 11065 11066
	/* TODO: cell style */
	var os = get_cell_style(opts.cellXfs, cell, opts);
	if(os !== 0) o.s = os;
	switch(cell.t) {
		case 'n': break;
		case 'd': o.t = "d"; break;
		case 'b': o.t = "b"; break;
		case 'e': o.t = "e"; break;
S
SheetJS 已提交
11067
		default: if(cell.v == null) { delete cell.t; break; }
S
SheetJS 已提交
11068 11069 11070 11071 11072 11073 11074
			if(opts.bookSST) {
				v = writetag('v', ''+get_sst_id(opts.Strings, cell.v));
				o.t = "s"; break;
			}
			o.t = "str"; break;
	}
	if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; }
S
SheetJS 已提交
11075 11076 11077 11078
	if(cell.f) {
		var ff = cell.F && cell.F.substr(0, ref.length) == ref ? {t:"array", ref:cell.F} : null;
		v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : "");
	}
S
SheetJS 已提交
11079
	if(cell.l) ws['!links'].push([ref, cell.l]);
S
SheetJS 已提交
11080
	if(cell.c) ws['!comments'].push([ref, cell.c]);
S
SheetJS 已提交
11081 11082 11083 11084 11085
	return writextag('c', v, o);
}

var parse_ws_xml_data = (function parse_ws_xml_data_factory() {
	var cellregex = /<(?:\w+:)?c[ >]/, rowregex = /<\/(?:\w+:)?row>/;
S
SheetJS 已提交
11086
	var rregex = /r=["']([^"']*)["']/, isregex = /<(?:\w+:)?is>([\S\s]*?)<\/(?:\w+:)?is>/;
S
SheetJS 已提交
11087
	var refregex = /ref=["']([^"']*)["']/;
S
SheetJS 已提交
11088 11089
	var match_v = matchtag("v"), match_f = matchtag("f");

S
SheetJS 已提交
11090
return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
S
SheetJS 已提交
11091
	var ri = 0, x = "", cells = [], cref = [], idx=0, i=0, cc=0, d="", p/*:any*/;
S
SheetJS 已提交
11092
	var tag, tagr = 0, tagc = 0;
S
SheetJS 已提交
11093
	var sstr, ftag;
11094 11095
	var fmtid = 0, fillid = 0;
	var do_format = Array.isArray(styles.CellXf), cf;
S
SheetJS 已提交
11096 11097
	var arrayf = [];
	var sharedf = [];
S
SheetJS 已提交
11098
	var dense = Array.isArray(s);
S
SheetJS 已提交
11099
	var rows = [], rowobj = {}, rowrite = false;
S
SheetJS 已提交
11100 11101 11102 11103 11104 11105 11106 11107
	for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
		x = marr[mt].trim();
		var xlen = x.length;
		if(xlen === 0) continue;

		/* 18.3.1.73 row CT_Row */
		for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
		tag = parsexmltag(x.substr(0,ri), true);
S
SheetJS 已提交
11108
		tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
S
SheetJS 已提交
11109 11110 11111 11112
		if(opts.sheetRows && opts.sheetRows < tagr) continue;
		if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
		if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;

S
SheetJS 已提交
11113 11114 11115 11116
		if(opts && opts.cellStyles) {
			rowobj = {}; rowrite = false;
			if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
			if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; }
11117
			if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
S
SheetJS 已提交
11118 11119 11120
			if(rowrite) rows[tagr-1] = rowobj;
		}

S
SheetJS 已提交
11121 11122
		/* 18.3.1.4 c CT_Cell */
		cells = x.substr(ri).split(cellregex);
11123
		for(ri = 0; ri != cells.length; ++ri) {
S
SheetJS 已提交
11124 11125 11126 11127
			x = cells[ri].trim();
			if(x.length === 0) continue;
			cref = x.match(rregex); idx = ri; i=0; cc=0;
			x = "<c " + (x.substr(0,1)=="<"?">":"") + x;
S
SheetJS 已提交
11128
			if(cref != null && cref.length === 2) {
S
SheetJS 已提交
11129 11130 11131 11132 11133 11134 11135 11136 11137 11138
				idx = 0; d=cref[1];
				for(i=0; i != d.length; ++i) {
					if((cc=d.charCodeAt(i)-64) < 1 || cc > 26) break;
					idx = 26*idx + cc;
				}
				--idx;
				tagc = idx;
			} else ++tagc;
			for(i = 0; i != x.length; ++i) if(x.charCodeAt(i) === 62) break; ++i;
			tag = parsexmltag(x.substr(0,i), true);
S
SheetJS 已提交
11139
			if(!tag.r) tag.r = encode_cell({r:tagr-1, c:tagc});
S
SheetJS 已提交
11140
			d = x.substr(i);
S
SheetJS 已提交
11141
			p = ({t:""}/*:any*/);
S
SheetJS 已提交
11142

S
SheetJS 已提交
11143 11144 11145
			if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
			if(opts.cellFormula) {
				if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') {
S
SheetJS 已提交
11146 11147
					/* TODO: match against XLSXFutureFunctions */
					p.f=unescapexml(utf8read(cref[1])).replace(/_xlfn\./,"");
S
SheetJS 已提交
11148 11149 11150 11151 11152 11153 11154 11155 11156 11157 11158 11159 11160 11161 11162 11163 11164 11165 11166
					if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
						p.F = (d.match(refregex)||[])[1];
						if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
					} else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
						// TODO: parse formula
						ftag = parsexmltag(cref[0]);
						sharedf[parseInt(ftag.si, 10)] = [ftag, unescapexml(utf8read(cref[1]))];
					}
				} else if((cref=d.match(/<f[^>]*\/>/))) {
					ftag = parsexmltag(cref[0]);
					if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][0].ref, tag.r);
				}
				/* TODO: factor out contains logic */
				var _tag = decode_cell(tag.r);
				for(i = 0; i < arrayf.length; ++i)
					if(_tag.r >= arrayf[i][0].s.r && _tag.r <= arrayf[i][0].e.r)
						if(_tag.c >= arrayf[i][0].s.c && _tag.c <= arrayf[i][0].e.c)
							p.F = arrayf[i][1];
			}
S
SheetJS 已提交
11167

S
SheetJS 已提交
11168
			if(tag.t == null && p.v === undefined) {
S
SheetJS 已提交
11169 11170 11171 11172
				if(p.f || p.F) {
					p.v = 0; p.t = "n";
				} else if(!opts.sheetStubs) continue;
				else p.t = "z";
S
SheetJS 已提交
11173 11174 11175 11176 11177 11178
			}
			else p.t = tag.t || "n";
			if(guess.s.c > idx) guess.s.c = idx;
			if(guess.e.c < idx) guess.e.c = idx;
			/* 18.18.11 t ST_CellType */
			switch(p.t) {
S
SheetJS 已提交
11179 11180 11181
				case 'n':
					p.v = parseFloat(p.v);
					break;
S
SheetJS 已提交
11182
				case 's':
11183 11184
					if(typeof p.v == 'undefined') {
						if(!opts.sheetStubs) continue;
S
SheetJS 已提交
11185
						p.t = 'z';
11186 11187 11188 11189 11190
					} else {
						sstr = strs[parseInt(p.v, 10)];
						p.v = sstr.t;
						p.r = sstr.r;
						if(opts.cellHTML) p.h = sstr.h;
11191
					}
S
SheetJS 已提交
11192 11193 11194 11195
					break;
				case 'str':
					p.t = "s";
					p.v = (p.v!=null) ? utf8read(p.v) : '';
11196
					if(opts.cellHTML) p.h = escapehtml(p.v);
S
SheetJS 已提交
11197 11198 11199 11200
					break;
				case 'inlineStr':
					cref = d.match(isregex);
					p.t = 's';
S
SheetJS 已提交
11201
					if(cref != null && (sstr = parse_si(cref[1]))) p.v = sstr.t; else p.v = "";
S
SheetJS 已提交
11202
					break;
S
SheetJS 已提交
11203 11204
				case 'b': p.v = parsexmlbool(p.v); break;
				case 'd':
S
SheetJS 已提交
11205 11206
					if(opts.cellDates) p.v = parseDate(p.v, 1);
					else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; }
S
SheetJS 已提交
11207
					break;
S
SheetJS 已提交
11208
				/* error string in .w, number in .v */
S
SheetJS 已提交
11209
				case 'e':
S
SheetJS 已提交
11210
					if(!opts || opts.cellText !== false) p.w = p.v;
S
SheetJS 已提交
11211
					p.v = RBErr[p.v]; break;
S
SheetJS 已提交
11212 11213 11214 11215 11216 11217 11218
			}
			/* formatting */
			fmtid = fillid = 0;
			if(do_format && tag.s !== undefined) {
				cf = styles.CellXf[tag.s];
				if(cf != null) {
					if(cf.numFmtId != null) fmtid = cf.numFmtId;
S
SheetJS 已提交
11219 11220 11221
					if(opts.cellStyles) {
						if(cf.fillId != null) fillid = cf.fillId;
					}
S
SheetJS 已提交
11222 11223
				}
			}
S
SheetJS 已提交
11224
			safe_format(p, fmtid, fillid, opts, themes, styles);
S
SheetJS 已提交
11225
			if(opts.cellDates && do_format && p.t == 'n' && SSF.is_date(SSF._table[fmtid])) { p.t = 'd'; p.v = numdate(p.v); }
S
SheetJS 已提交
11226 11227 11228 11229 11230
			if(dense) {
				var _r = decode_cell(tag.r);
				if(!s[_r.r]) s[_r.r] = [];
				s[_r.r][_r.c] = p;
			} else s[tag.r] = p;
S
SheetJS 已提交
11231 11232
		}
	}
S
SheetJS 已提交
11233
	if(rows.length > 0) s['!rows'] = rows;
S
SheetJS 已提交
11234 11235
}; })();

S
SheetJS 已提交
11236
function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/, rels)/*:string*/ {
P
Paul Ishenin 已提交
11237
	var o = [], r = [], range = safe_decode_range(ws['!ref']), cell, ref, rr = "", cols = [], R=0, C=0, rows = ws['!rows'];
S
SheetJS 已提交
11238
	var dense = Array.isArray(ws);
S
SheetJS 已提交
11239 11240 11241 11242 11243 11244
	for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
	for(R = range.s.r; R <= range.e.r; ++R) {
		r = [];
		rr = encode_row(R);
		for(C = range.s.c; C <= range.e.c; ++C) {
			ref = cols[C] + rr;
S
SheetJS 已提交
11245 11246 11247
			var _cell = dense ? (ws[R]||[])[C]: ws[ref];
			if(_cell === undefined) continue;
			if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
S
SheetJS 已提交
11248
		}
11249
		if(r.length > 0 || rows && rows[R]) {
S
SheetJS 已提交
11250
			var params = ({r:rr}/*:any*/);
P
Paul Ishenin 已提交
11251 11252 11253 11254 11255 11256 11257
			if(rows && rows[R]) {
				var row = rows[R];
				if(row.hidden) params.hidden = 1;
				var height = -1;
				if (row.hpx) height = px2pt(row.hpx);
				else if (row.hpt) height = row.hpt;
				if (height > -1) { params.ht = height; params.customHeight = 1; }
11258
				if (row.level) { params.outlineLevel = row.level; }
P
Paul Ishenin 已提交
11259 11260 11261
			}
			o[o.length] = (writextag('row', r.join(""), params));
		}
S
SheetJS 已提交
11262
	}
11263 11264
	if(rows) for(; R < rows.length; ++R) {
		if(rows && rows[R]) {
S
SheetJS 已提交
11265 11266
			params = ({r:R+1}/*:any*/);
			row = rows[R];
11267
			if(row.hidden) params.hidden = 1;
S
SheetJS 已提交
11268
			height = -1;
11269 11270 11271 11272 11273 11274 11275
			if (row.hpx) height = px2pt(row.hpx);
			else if (row.hpt) height = row.hpt;
			if (height > -1) { params.ht = height; params.customHeight = 1; }
			if (row.level) { params.outlineLevel = row.level; }
			o[o.length] = (writextag('row', "", params));
		}
	}
S
SheetJS 已提交
11276 11277 11278 11279 11280 11281 11282 11283
	return o.join("");
}

var WS_XML_ROOT = writextag('worksheet', null, {
	'xmlns': XMLNS.main[0],
	'xmlns:r': XMLNS.r
});

S
SheetJS 已提交
11284
function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
S
SheetJS 已提交
11285 11286 11287
	var o = [XML_HEADER, WS_XML_ROOT];
	var s = wb.SheetNames[idx], sidx = 0, rdata = "";
	var ws = wb.Sheets[s];
S
SheetJS 已提交
11288 11289
	if(ws == null) ws = {};
	var ref = ws['!ref']; if(ref == null) ref = 'A1';
S
SheetJS 已提交
11290
	if(!rels) rels = {};
S
SheetJS 已提交
11291
	ws['!comments'] = [];
S
SheetJS 已提交
11292
	ws['!drawing'] = [];
S
SheetJS 已提交
11293 11294

	o[o.length] = (writextag('sheetPr', null, {'codeName': escapexml(wb.SheetNames[idx])}));
S
SheetJS 已提交
11295

S
SheetJS 已提交
11296 11297
	o[o.length] = (writextag('dimension', null, {'ref': ref}));

S
SheetJS 已提交
11298
	o[o.length] = write_ws_xml_sheetviews(ws, opts, idx, wb);
S
SheetJS 已提交
11299

11300
	/* TODO: store in WB, process styles */
11301 11302 11303 11304 11305
	if(opts.sheetFormat) o[o.length] = (writextag('sheetFormatPr', null, {
		defaultRowHeight:opts.sheetFormat.defaultRowHeight||'16',
		baseColWidth:opts.sheetFormat.baseColWidth||'10',
		outlineLevelRow:opts.sheetFormat.outlineLevelRow||'7'
	}));
11306

S
SheetJS 已提交
11307 11308
	if(ws['!cols'] != null && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols']));

S
SheetJS 已提交
11309
	o[sidx = o.length] = '<sheetData/>';
S
SheetJS 已提交
11310
	ws['!links'] = [];
S
SheetJS 已提交
11311
	if(ws['!ref'] != null) {
S
SheetJS 已提交
11312
		rdata = write_ws_xml_data(ws, opts, idx, wb, rels);
S
SheetJS 已提交
11313 11314 11315 11316
		if(rdata.length > 0) o[o.length] = (rdata);
	}
	if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }

S
SheetJS 已提交
11317 11318
	/* sheetCalcPr */

M
Mior 已提交
11319 11320
	if(ws['!protect'] != null) o[o.length] = write_ws_xml_protection(ws['!protect']);

S
SheetJS 已提交
11321 11322 11323 11324 11325 11326 11327 11328 11329
	/* protectedRanges */
	/* scenarios */

	if(ws['!autofilter'] != null) o[o.length] = write_ws_xml_autofilter(ws['!autofilter']);

	/* sortState */
	/* dataConsolidate */
	/* customSheetViews */

S
SheetJS 已提交
11330
	if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
S
SheetJS 已提交
11331

S
SheetJS 已提交
11332 11333 11334 11335
	/* phoneticPr */
	/* conditionalFormatting */
	/* dataValidations */

S
SheetJS 已提交
11336
	var relc = -1, rel, rId = -1;
S
SheetJS 已提交
11337 11338 11339 11340
	if(ws['!links'].length > 0) {
		o[o.length] = "<hyperlinks>";
		ws['!links'].forEach(function(l) {
			if(!l[1].Target) return;
S
SheetJS 已提交
11341
			rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), RELS.HLINK);
S
SheetJS 已提交
11342 11343 11344 11345 11346 11347 11348
			rel = ({"ref":l[0], "r:id":"rId"+rId}/*:any*/);
			if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.substr(relc+1));
			if(l[1].Tooltip) rel.tooltip = escapexml(l[1].Tooltip);
			o[o.length] = writextag("hyperlink",null,rel);
		});
		o[o.length] = "</hyperlinks>";
	}
S
SheetJS 已提交
11349
	delete ws['!links'];
S
SheetJS 已提交
11350

S
SheetJS 已提交
11351
	/* printOptions */
S
SheetJS 已提交
11352
	if (ws['!margins'] != null) o[o.length] =  write_ws_xml_margins(ws['!margins']);
S
SheetJS 已提交
11353 11354
	/* pageSetup */

S
SheetJS 已提交
11355 11356 11357
	var hfidx = o.length;
	o[o.length] = "";

S
SheetJS 已提交
11358 11359 11360 11361 11362 11363 11364
	/* rowBreaks */
	/* colBreaks */
	/* customProperties */
	/* cellWatches */
	/* ignoredErrors */
	/* smartTags */

S
SheetJS 已提交
11365 11366 11367 11368 11369
	if(ws['!drawing'].length > 0) {
		rId = add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
		o[o.length] = writextag("drawing", null, {"r:id":"rId" + rId});
	}
	else delete ws['!drawing'];
S
SheetJS 已提交
11370

S
SheetJS 已提交
11371 11372 11373 11374 11375 11376
	if(ws['!comments'].length > 0) {
		rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML);
		o[o.length] = writextag("legacyDrawing", null, {"r:id":"rId" + rId});
		ws['!legacy'] = rId;
	}

S
SheetJS 已提交
11377 11378 11379 11380 11381 11382 11383 11384
	/* drawingHF */
	/* picture */
	/* oleObjects */
	/* controls */
	/* webPublishItems */
	/* tableParts */
	/* extList */

S
SheetJS 已提交
11385
	if(o.length>2) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
S
SheetJS 已提交
11386 11387 11388 11389 11390
	return o.join("");
}

/* [MS-XLSB] 2.4.718 BrtRowHdr */
function parse_BrtRowHdr(data, length) {
S
SheetJS 已提交
11391 11392
	var z = ({}/*:any*/);
	var tgt = data.l + length;
S
SheetJS 已提交
11393
	z.r = data.read_shift(4);
S
SheetJS 已提交
11394 11395 11396 11397 11398
	data.l += 4; // TODO: ixfe
	var miyRw = data.read_shift(2);
	data.l += 1; // TODO: top/bot padding
	var flags = data.read_shift(1);
	data.l = tgt;
11399
	if(flags & 0x07) z.level = flags & 0x07;
S
SheetJS 已提交
11400 11401
	if(flags & 0x10) z.hidden = true;
	if(flags & 0x20) z.hpt = miyRw / 20;
S
SheetJS 已提交
11402 11403 11404 11405
	return z;
}
function write_BrtRowHdr(R/*:number*/, range, ws) {
	var o = new_buf(17+8*16);
S
SheetJS 已提交
11406
	var row = (ws['!rows']||[])[R]||{};
S
SheetJS 已提交
11407 11408
	o.write_shift(4, R);

S
SheetJS 已提交
11409 11410 11411 11412 11413 11414 11415 11416 11417 11418
	o.write_shift(4, 0); /* TODO: ixfe */

	var miyRw = 0x0140;
	if(row.hpx) miyRw = px2pt(row.hpx) * 20;
	else if(row.hpt) miyRw = row.hpt * 20;
	o.write_shift(2, miyRw);

	o.write_shift(1, 0); /* top/bot padding */

	var flags = 0x0;
11419
	if(row.level) flags |= row.level;
S
SheetJS 已提交
11420 11421 11422 11423 11424
	if(row.hidden) flags |= 0x10;
	if(row.hpx || row.hpt) flags |= 0x20;
	o.write_shift(1, flags);

	o.write_shift(1, 0); /* phonetic guide */
S
SheetJS 已提交
11425 11426 11427 11428 11429 11430 11431 11432 11433 11434 11435

	/* [MS-XLSB] 2.5.8 BrtColSpan explains the mechanism */
	var ncolspan = 0, lcs = o.l;
	o.l += 4;

	var caddr = {r:R, c:0};
	for(var i = 0; i < 16; ++i) {
		if(range.s.c > ((i+1) << 10) || range.e.c < (i << 10)) continue;
		var first = -1, last = -1;
		for(var j = (i<<10); j < ((i+1)<<10); ++j) {
			caddr.c = j;
S
SheetJS 已提交
11436 11437
			var cell = Array.isArray(ws) ? (ws[caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)];
			if(cell) { if(first < 0) first = j; last = j; }
S
SheetJS 已提交
11438 11439 11440 11441 11442 11443 11444 11445 11446 11447 11448 11449 11450 11451 11452 11453
		}
		if(first < 0) continue;
		++ncolspan;
		o.write_shift(4, first);
		o.write_shift(4, last);
	}

	var l = o.l;
	o.l = lcs;
	o.write_shift(4, ncolspan);
	o.l = l;

	return o.length > o.l ? o.slice(0, o.l) : o;
}
function write_row_header(ba, ws, range, R) {
	var o = write_BrtRowHdr(R, range, ws);
11454
	if(o.length > 17 || (ws['!rows']||[])[R]) write_record(ba, 'BrtRowHdr', o);
S
SheetJS 已提交
11455 11456 11457 11458 11459 11460
}

/* [MS-XLSB] 2.4.812 BrtWsDim */
var parse_BrtWsDim = parse_UncheckedRfX;
var write_BrtWsDim = write_UncheckedRfX;

S
SheetJS 已提交
11461
/* [MS-XLSB] 2.4.813 BrtWsFmtInfo */
S
SheetJS 已提交
11462 11463
function parse_BrtWsFmtInfo(data, length) {
}
S
SheetJS 已提交
11464 11465
//function write_BrtWsFmtInfo(ws, o) { }

S
SheetJS 已提交
11466 11467 11468 11469 11470 11471 11472 11473
/* [MS-XLSB] 2.4.815 BrtWsProp */
function parse_BrtWsProp(data, length) {
	var z = {};
	/* TODO: pull flags */
	data.l += 19;
	z.name = parse_XLSBCodeName(data, length - 19);
	return z;
}
S
SheetJS 已提交
11474
function write_BrtWsProp(str, o) {
S
SheetJS 已提交
11475 11476 11477
	if(o == null) o = new_buf(84+4*str.length);
	for(var i = 0; i < 3; ++i) o.write_shift(1,0);
	write_BrtColor({auto:1}, o);
S
SheetJS 已提交
11478 11479 11480 11481 11482
	o.write_shift(-4,-1);
	o.write_shift(-4,-1);
	write_XLSBCodeName(str, o);
	return o.slice(0, o.l);
}
S
SheetJS 已提交
11483 11484 11485 11486 11487 11488 11489 11490 11491 11492 11493 11494 11495 11496 11497 11498 11499 11500 11501 11502 11503 11504 11505 11506 11507 11508 11509 11510 11511 11512 11513 11514 11515 11516 11517 11518 11519 11520 11521 11522 11523 11524 11525 11526 11527 11528 11529 11530 11531 11532 11533 11534 11535 11536 11537 11538 11539 11540 11541 11542 11543 11544 11545 11546 11547 11548 11549 11550 11551 11552 11553 11554 11555 11556 11557 11558 11559 11560 11561 11562 11563 11564 11565 11566 11567 11568 11569

/* [MS-XLSB] 2.4.303 BrtCellBlank */
function parse_BrtCellBlank(data, length) {
	var cell = parse_XLSBCell(data);
	return [cell];
}
function write_BrtCellBlank(cell, ncell, o) {
	if(o == null) o = new_buf(8);
	return write_XLSBCell(ncell, o);
}


/* [MS-XLSB] 2.4.304 BrtCellBool */
function parse_BrtCellBool(data, length) {
	var cell = parse_XLSBCell(data);
	var fBool = data.read_shift(1);
	return [cell, fBool, 'b'];
}
function write_BrtCellBool(cell, ncell, o) {
	if(o == null) o = new_buf(9);
	write_XLSBCell(ncell, o);
	o.write_shift(1, cell.v ? 1 : 0);
	return o;
}

/* [MS-XLSB] 2.4.305 BrtCellError */
function parse_BrtCellError(data, length) {
	var cell = parse_XLSBCell(data);
	var bError = data.read_shift(1);
	return [cell, bError, 'e'];
}

/* [MS-XLSB] 2.4.308 BrtCellIsst */
function parse_BrtCellIsst(data, length) {
	var cell = parse_XLSBCell(data);
	var isst = data.read_shift(4);
	return [cell, isst, 's'];
}
function write_BrtCellIsst(cell, ncell, o) {
	if(o == null) o = new_buf(12);
	write_XLSBCell(ncell, o);
	o.write_shift(4, ncell.v);
	return o;
}

/* [MS-XLSB] 2.4.310 BrtCellReal */
function parse_BrtCellReal(data, length) {
	var cell = parse_XLSBCell(data);
	var value = parse_Xnum(data);
	return [cell, value, 'n'];
}
function write_BrtCellReal(cell, ncell, o) {
	if(o == null) o = new_buf(16);
	write_XLSBCell(ncell, o);
	write_Xnum(cell.v, o);
	return o;
}

/* [MS-XLSB] 2.4.311 BrtCellRk */
function parse_BrtCellRk(data, length) {
	var cell = parse_XLSBCell(data);
	var value = parse_RkNumber(data);
	return [cell, value, 'n'];
}
function write_BrtCellRk(cell, ncell, o) {
	if(o == null) o = new_buf(12);
	write_XLSBCell(ncell, o);
	write_RkNumber(cell.v, o);
	return o;
}


/* [MS-XLSB] 2.4.314 BrtCellSt */
function parse_BrtCellSt(data, length) {
	var cell = parse_XLSBCell(data);
	var value = parse_XLWideString(data);
	return [cell, value, 'str'];
}
function write_BrtCellSt(cell, ncell, o) {
	if(o == null) o = new_buf(12 + 4 * cell.v.length);
	write_XLSBCell(ncell, o);
	write_XLWideString(cell.v, o);
	return o.length > o.l ? o.slice(0, o.l) : o;
}

/* [MS-XLSB] 2.4.647 BrtFmlaBool */
function parse_BrtFmlaBool(data, length, opts) {
S
SheetJS 已提交
11570
	var end = data.l + length;
S
SheetJS 已提交
11571
	var cell = parse_XLSBCell(data);
S
SheetJS 已提交
11572
	cell.r = opts['!row'];
S
SheetJS 已提交
11573 11574 11575
	var value = data.read_shift(1);
	var o = [cell, value, 'b'];
	if(opts.cellFormula) {
S
SheetJS 已提交
11576 11577 11578
		data.l += 2;
		var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
		o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
S
SheetJS 已提交
11579
	}
S
SheetJS 已提交
11580
	else data.l = end;
S
SheetJS 已提交
11581 11582 11583 11584 11585
	return o;
}

/* [MS-XLSB] 2.4.648 BrtFmlaError */
function parse_BrtFmlaError(data, length, opts) {
S
SheetJS 已提交
11586
	var end = data.l + length;
S
SheetJS 已提交
11587
	var cell = parse_XLSBCell(data);
S
SheetJS 已提交
11588
	cell.r = opts['!row'];
S
SheetJS 已提交
11589 11590 11591
	var value = data.read_shift(1);
	var o = [cell, value, 'e'];
	if(opts.cellFormula) {
S
SheetJS 已提交
11592 11593 11594
		data.l += 2;
		var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
		o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
S
SheetJS 已提交
11595
	}
S
SheetJS 已提交
11596
	else data.l = end;
S
SheetJS 已提交
11597 11598 11599 11600 11601
	return o;
}

/* [MS-XLSB] 2.4.649 BrtFmlaNum */
function parse_BrtFmlaNum(data, length, opts) {
S
SheetJS 已提交
11602
	var end = data.l + length;
S
SheetJS 已提交
11603
	var cell = parse_XLSBCell(data);
S
SheetJS 已提交
11604
	cell.r = opts['!row'];
S
SheetJS 已提交
11605 11606 11607
	var value = parse_Xnum(data);
	var o = [cell, value, 'n'];
	if(opts.cellFormula) {
S
SheetJS 已提交
11608 11609 11610
		data.l += 2;
		var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
		o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
S
SheetJS 已提交
11611
	}
S
SheetJS 已提交
11612
	else data.l = end;
S
SheetJS 已提交
11613 11614 11615 11616 11617
	return o;
}

/* [MS-XLSB] 2.4.650 BrtFmlaString */
function parse_BrtFmlaString(data, length, opts) {
S
SheetJS 已提交
11618
	var end = data.l + length;
S
SheetJS 已提交
11619
	var cell = parse_XLSBCell(data);
S
SheetJS 已提交
11620
	cell.r = opts['!row'];
S
SheetJS 已提交
11621 11622 11623
	var value = parse_XLWideString(data);
	var o = [cell, value, 'str'];
	if(opts.cellFormula) {
S
SheetJS 已提交
11624 11625 11626
		data.l += 2;
		var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
		o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
S
SheetJS 已提交
11627
	}
S
SheetJS 已提交
11628
	else data.l = end;
S
SheetJS 已提交
11629 11630 11631 11632 11633
	return o;
}

/* [MS-XLSB] 2.4.676 BrtMergeCell */
var parse_BrtMergeCell = parse_UncheckedRfX;
11634 11635 11636 11637 11638 11639 11640
var write_BrtMergeCell = write_UncheckedRfX;
/* [MS-XLSB] 2.4.108 BrtBeginMergeCells */
function write_BrtBeginMergeCells(cnt, o) {
	if(o == null) o = new_buf(4);
	o.write_shift(4, cnt);
	return o;
}
S
SheetJS 已提交
11641 11642 11643 11644 11645 11646 11647 11648 11649 11650

/* [MS-XLSB] 2.4.656 BrtHLink */
function parse_BrtHLink(data, length, opts) {
	var end = data.l + length;
	var rfx = parse_UncheckedRfX(data, 16);
	var relId = parse_XLNullableWideString(data);
	var loc = parse_XLWideString(data);
	var tooltip = parse_XLWideString(data);
	var display = parse_XLWideString(data);
	data.l = end;
S
SheetJS 已提交
11651
	return {rfx:rfx, relId:relId, loc:loc, Tooltip:tooltip, display:display};
S
SheetJS 已提交
11652
}
S
SheetJS 已提交
11653 11654 11655 11656 11657
function write_BrtHLink(l, rId, o) {
	if(o == null) o = new_buf(50+4*l[1].Target.length);
	write_UncheckedRfX({s:decode_cell(l[0]), e:decode_cell(l[0])}, o);
	write_RelID("rId" + rId, o);
	var locidx = l[1].Target.indexOf("#");
S
SheetJS 已提交
11658 11659
	var loc = locidx == -1 ? "" : l[1].Target.substr(locidx+1);
	write_XLWideString(loc || "", o);
S
SheetJS 已提交
11660 11661 11662 11663
	write_XLWideString(l[1].Tooltip || "", o);
	write_XLWideString("", o);
	return o.slice(0, o.l);
}
S
SheetJS 已提交
11664

S
SheetJS 已提交
11665 11666 11667 11668 11669
/* [MS-XLSB] 2.4.6 BrtArrFmla */
function parse_BrtArrFmla(data, length, opts) {
	var end = data.l + length;
	var rfx = parse_RfX(data, 16);
	var fAlwaysCalc = data.read_shift(1);
S
SheetJS 已提交
11670
	var o = [rfx]; o[2] = fAlwaysCalc;
S
SheetJS 已提交
11671 11672 11673 11674 11675 11676 11677 11678 11679 11680 11681
	if(opts.cellFormula) {
		var formula = parse_XLSBArrayParsedFormula(data, end - data.l, opts);
		o[1] = formula;
	} else data.l = end;
	return o;
}

/* [MS-XLSB] 2.4.742 BrtShrFmla */
function parse_BrtShrFmla(data, length, opts) {
	var end = data.l + length;
	var rfx = parse_UncheckedRfX(data, 16);
S
SheetJS 已提交
11682
	var o = [rfx];
S
SheetJS 已提交
11683 11684 11685 11686 11687 11688 11689 11690
	if(opts.cellFormula) {
		var formula = parse_XLSBSharedParsedFormula(data, end - data.l, opts);
		o[1] = formula;
		data.l = end;
	} else data.l = end;
	return o;
}

S
SheetJS 已提交
11691 11692 11693 11694 11695 11696 11697
/* [MS-XLSB] 2.4.323 BrtColInfo */
/* TODO: once XLS ColInfo is set, combine the functions */
function write_BrtColInfo(C/*:number*/, col, o) {
	if(o == null) o = new_buf(18);
	var p = col_obj_w(C, col);
	o.write_shift(-4, C);
	o.write_shift(-4, C);
S
SheetJS 已提交
11698
	o.write_shift(4, (p.width || 10) * 256);
S
SheetJS 已提交
11699
	o.write_shift(4, 0/*ixfe*/); // style
S
SheetJS 已提交
11700 11701 11702 11703
	var flags = 0;
	if(col.hidden) flags |= 0x01;
	if(typeof p.width == 'number') flags |= 0x02;
	o.write_shift(1, flags); // bit flag
S
SheetJS 已提交
11704 11705 11706 11707
	o.write_shift(1, 0); // bit flag
	return o;
}

S
SheetJS 已提交
11708 11709 11710 11711 11712 11713 11714 11715 11716 11717 11718 11719 11720 11721 11722 11723 11724 11725 11726 11727 11728 11729 11730
/* [MS-XLSB] 2.4.672 BrtMargins */
function parse_BrtMargins(data, length, opts) {
	return {
		left: parse_Xnum(data, 8),
		right: parse_Xnum(data, 8),
		top: parse_Xnum(data, 8),
		bottom: parse_Xnum(data, 8),
		header: parse_Xnum(data, 8),
		footer: parse_Xnum(data, 8)
	};
}
function write_BrtMargins(margins, o) {
	if(o == null) o = new_buf(6*8);
	default_margins(margins);
	write_Xnum(margins.left, o);
	write_Xnum(margins.right, o);
	write_Xnum(margins.top, o);
	write_Xnum(margins.bottom, o);
	write_Xnum(margins.header, o);
	write_Xnum(margins.footer, o);
	return o;
}

S
SheetJS 已提交
11731 11732 11733 11734 11735 11736 11737 11738 11739 11740 11741 11742 11743 11744 11745 11746 11747 11748
/* [MS-XLSB] 2.4.292 BrtBeginWsView */
function write_BrtBeginWsView(ws, o) {
	if(o == null) o = new_buf(30);
	o.write_shift(2, 924); // bit flag
	o.write_shift(4, 0);
	o.write_shift(4, 0); // view first row
	o.write_shift(4, 0); // view first col
	o.write_shift(1, 0); // gridline color ICV
	o.write_shift(1, 0);
	o.write_shift(2, 0);
	o.write_shift(2, 100); // zoom scale
	o.write_shift(2, 0);
	o.write_shift(2, 0);
	o.write_shift(2, 0);
	o.write_shift(4, 0); // workbook view id
	return o;
}

S
SheetJS 已提交
11749 11750 11751 11752 11753 11754 11755 11756 11757 11758 11759 11760 11761 11762 11763 11764 11765 11766 11767 11768 11769 11770
/* [MS-XLSB] 2.4.740 BrtSheetProtection */
function write_BrtSheetProtection(sp, o) {
	if(o == null) o = new_buf(16*4+2);
	o.write_shift(2, sp.password ? crypto_CreatePasswordVerifier_Method1(sp.password) : 0);
	o.write_shift(4, 1); // this record should not be written if no protection
	[
		["objects",             false], // fObjects
		["scenarios",           false], // fScenarios
		["formatCells",          true], // fFormatCells
		["formatColumns",        true], // fFormatColumns
		["formatRows",           true], // fFormatRows
		["insertColumns",        true], // fInsertColumns
		["insertRows",           true], // fInsertRows
		["insertHyperlinks",     true], // fInsertHyperlinks
		["deleteColumns",        true], // fDeleteColumns
		["deleteRows",           true], // fDeleteRows
		["selectLockedCells",   false], // fSelLockedCells
		["sort",                 true], // fSort
		["autoFilter",           true], // fAutoFilter
		["pivotTables",          true], // fPivotTables
		["selectUnlockedCells", false]  // fSelUnlockedCells
	].forEach(function(n) {
S
SheetJS 已提交
11771
		/*:: if(o == null) throw "unreachable"; */
S
SheetJS 已提交
11772 11773
		if(n[1]) o.write_shift(4, sp[n[0]] != null && !sp[n[0]] ? 1 : 0);
		else      o.write_shift(4, sp[n[0]] != null && sp[n[0]] ? 0 : 1);
S
SheetJS 已提交
11774 11775 11776 11777
	});
	return o;
}

S
SheetJS 已提交
11778
/* [MS-XLSB] 2.1.7.61 Worksheet */
S
SheetJS 已提交
11779
function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ {
S
SheetJS 已提交
11780
	if(!data) return data;
S
SheetJS 已提交
11781
	var opts = _opts || {};
S
SheetJS 已提交
11782
	if(!rels) rels = {'!id':{}};
11783
	if(DENSE != null && opts.dense == null) opts.dense = DENSE;
S
SheetJS 已提交
11784
	var s/*:Worksheet*/ = (opts.dense ? [] : {});
S
SheetJS 已提交
11785 11786 11787 11788 11789

	var ref;
	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };

	var pass = false, end = false;
S
SheetJS 已提交
11790
	var row, p, cf, R, C, addr, sstr, rr, cell/*:Cell*/;
S
SheetJS 已提交
11791
	var mergecells = [];
S
SheetJS 已提交
11792 11793 11794 11795 11796 11797 11798 11799 11800 11801
	opts.biff = 12;
	opts['!row'] = 0;

	var ai = 0, af = false;

	var array_formulae = [];
	var shared_formulae = {};
	var supbooks = ([[]]/*:any*/);
	supbooks.sharedf = shared_formulae;
	supbooks.arrayf = array_formulae;
S
SheetJS 已提交
11802
	supbooks.SheetNames = wb.SheetNames || wb.Sheets.map(function(x) { return x.name; });
S
SheetJS 已提交
11803
	opts.supbooks = supbooks;
S
SheetJS 已提交
11804
	for(var i = 0; i < wb.Names.length; ++i) supbooks[0][i+1] = wb.Names[i];
S
SheetJS 已提交
11805

S
SheetJS 已提交
11806 11807 11808 11809
	var colinfo = [], rowinfo = [];
	var defwidth = 0, defheight = 0; // twips / MDW respectively
	var seencol = false;

11810
	recordhopper(data, function ws_parse(val, R_n, RT) {
S
SheetJS 已提交
11811
		if(end) return;
11812 11813 11814 11815
		switch(RT) {
			case 0x0094: /* 'BrtWsDim' */
				ref = val; break;
			case 0x0000: /* 'BrtRowHdr' */
S
SheetJS 已提交
11816 11817
				row = val;
				if(opts.sheetRows && opts.sheetRows <= row.r) end=true;
S
SheetJS 已提交
11818
				rr = encode_row(R = row.r);
S
SheetJS 已提交
11819
				opts['!row'] = row.r;
11820
				if(val.hidden || val.hpt || val.level != null) {
S
SheetJS 已提交
11821 11822 11823
					if(val.hpt) val.hpx = pt2px(val.hpt);
					rowinfo[val.r] = val;
				}
S
SheetJS 已提交
11824 11825
				break;

11826 11827 11828 11829 11830 11831 11832 11833 11834 11835
			case 0x0002: /* 'BrtCellRk' */
			case 0x0003: /* 'BrtCellError' */
			case 0x0004: /* 'BrtCellBool' */
			case 0x0005: /* 'BrtCellReal' */
			case 0x0006: /* 'BrtCellSt' */
			case 0x0007: /* 'BrtCellIsst' */
			case 0x0008: /* 'BrtFmlaString' */
			case 0x0009: /* 'BrtFmlaNum' */
			case 0x000A: /* 'BrtFmlaBool' */
			case 0x000B: /* 'BrtFmlaError' */
S
SheetJS 已提交
11836
				p = ({t:val[2]}/*:any*/);
S
SheetJS 已提交
11837 11838 11839 11840
				switch(val[2]) {
					case 'n': p.v = val[1]; break;
					case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
					case 'b': p.v = val[1] ? true : false; break;
S
SheetJS 已提交
11841
					case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break;
S
SheetJS 已提交
11842 11843
					case 'str': p.t = 's'; p.v = utf8read(val[1]); break;
				}
S
SheetJS 已提交
11844
				if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
S
SheetJS 已提交
11845 11846 11847
				C = val[0].c;
				if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
				else s[encode_col(C) + rr] = p;
S
SheetJS 已提交
11848 11849 11850 11851 11852 11853 11854 11855 11856 11857 11858
				if(opts.cellFormula) {
					af = false;
					for(ai = 0; ai < array_formulae.length; ++ai) {
						var aii = array_formulae[ai];
						if(row.r >= aii[0].s.r && row.r <= aii[0].e.r)
							if(C >= aii[0].s.c && C <= aii[0].e.c) {
								p.F = encode_range(aii[0]); af = true;
							}
					}
					if(!af && val.length > 3) p.f = val[3];
				}
S
SheetJS 已提交
11859 11860 11861 11862
				if(refguess.s.r > row.r) refguess.s.r = row.r;
				if(refguess.s.c > C) refguess.s.c = C;
				if(refguess.e.r < row.r) refguess.e.r = row.r;
				if(refguess.e.c < C) refguess.e.c = C;
S
SheetJS 已提交
11863
				if(opts.cellDates && cf && p.t == 'n' && SSF.is_date(SSF._table[cf.numFmtId])) {
S
SheetJS 已提交
11864
					var _d = SSF.parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
S
SheetJS 已提交
11865
				}
S
SheetJS 已提交
11866 11867
				break;

11868
			case 0x0001: /* 'BrtCellBlank' */
S
SheetJS 已提交
11869
				if(!opts.sheetStubs || pass) break;
S
SheetJS 已提交
11870
				p = ({t:'z',v:undefined}/*:any*/);
S
SheetJS 已提交
11871 11872 11873
				C = val[0].c;
				if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
				else s[encode_col(C) + rr] = p;
S
SheetJS 已提交
11874 11875 11876 11877 11878 11879
				if(refguess.s.r > row.r) refguess.s.r = row.r;
				if(refguess.s.c > C) refguess.s.c = C;
				if(refguess.e.r < row.r) refguess.e.r = row.r;
				if(refguess.e.c < C) refguess.e.c = C;
				break;

11880 11881
			case 0x00B0: /* 'BrtMergeCell' */
				mergecells.push(val); break;
S
SheetJS 已提交
11882

11883
			case 0x01EE: /* 'BrtHLink' */
S
SheetJS 已提交
11884 11885 11886 11887 11888 11889 11890
				var rel = rels['!id'][val.relId];
				if(rel) {
					val.Target = rel.Target;
					if(val.loc) val.Target += "#"+val.loc;
					val.Rel = rel;
				}
				for(R=val.rfx.s.r;R<=val.rfx.e.r;++R) for(C=val.rfx.s.c;C<=val.rfx.e.c;++C) {
S
SheetJS 已提交
11891 11892 11893 11894 11895 11896 11897 11898 11899
					if(opts.dense) {
						if(!s[R]) s[R] = [];
						if(!s[R][C]) s[R][C] = {t:'z',v:undefined};
						s[R][C].l = val;
					} else {
						addr = encode_cell({c:C,r:R});
						if(!s[addr]) s[addr] = {t:'z',v:undefined};
						s[addr].l = val;
					}
S
SheetJS 已提交
11900 11901 11902
				}
				break;

11903
			case 0x01AA: /* 'BrtArrFmla' */
S
SheetJS 已提交
11904
				if(!opts.cellFormula) break;
S
SheetJS 已提交
11905
				array_formulae.push(val);
S
SheetJS 已提交
11906
				cell = ((opts.dense ? s[R][C] : s[encode_col(C) + rr])/*:any*/);
S
SheetJS 已提交
11907 11908
				cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
				cell.F = encode_range(val[0]);
S
SheetJS 已提交
11909
				break;
11910
			case 0x01AB: /* 'BrtShrFmla' */
S
SheetJS 已提交
11911
				if(!opts.cellFormula) break;
S
SheetJS 已提交
11912
				shared_formulae[encode_cell(val[0].s)] = val[1];
S
SheetJS 已提交
11913 11914
				cell = (opts.dense ? s[R][C] : s[encode_col(C) + rr]);
				cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
S
SheetJS 已提交
11915 11916
				break;

S
SheetJS 已提交
11917
			/* identical to 'ColInfo' in XLS */
11918
			case 0x003C: /* 'BrtColInfo' */
S
SheetJS 已提交
11919 11920
				if(!opts.cellStyles) break;
				while(val.e >= val.s) {
S
SheetJS 已提交
11921
					colinfo[val.e--] = { width: val.w/256, hidden: !!(val.flags & 0x01) };
S
SheetJS 已提交
11922 11923 11924
					if(!seencol) { seencol = true; find_mdw_colw(val.w/256); }
					process_col(colinfo[val.e+1]);
				}
S
SheetJS 已提交
11925
				break;
S
SheetJS 已提交
11926

S
SheetJS 已提交
11927 11928 11929 11930
			case 0x00A1: /* 'BrtBeginAFilter' */
				s['!autofilter'] = { ref:encode_range(val) };
				break;

S
SheetJS 已提交
11931 11932 11933 11934
			case 0x01DC: /* 'BrtMargins' */
				s['!margins'] = val;
				break;

S
SheetJS 已提交
11935
			case 0x01E5: /* 'BrtWsFmtInfo' */
S
SheetJS 已提交
11936
			/* case 'BrtUid' */
11937 11938 11939 11940 11941 11942 11943 11944 11945 11946 11947 11948 11949 11950 11951 11952 11953 11954 11955 11956 11957 11958 11959 11960 11961 11962 11963 11964 11965 11966 11967 11968 11969 11970 11971 11972 11973 11974 11975 11976 11977 11978 11979 11980 11981 11982 11983 11984 11985 11986 11987 11988 11989 11990 11991 11992 11993 11994 11995 11996 11997
			case 0x00AF: /* 'BrtAFilterDateGroupItem' */
			case 0x0284: /* 'BrtActiveX' */
			case 0x0271: /* 'BrtBigName' */
			case 0x0232: /* 'BrtBkHim' */
			case 0x018C: /* 'BrtBrk' */
			case 0x0458: /* 'BrtCFIcon' */
			case 0x047A: /* 'BrtCFRuleExt' */
			case 0x01D7: /* 'BrtCFVO' */
			case 0x041A: /* 'BrtCFVO14' */
			case 0x0289: /* 'BrtCellIgnoreEC' */
			case 0x0451: /* 'BrtCellIgnoreEC14' */
			case 0x0031: /* 'BrtCellMeta' */
			case 0x024D: /* 'BrtCellSmartTagProperty' */
			case 0x025F: /* 'BrtCellWatch' */
			case 0x0234: /* 'BrtColor' */
			case 0x041F: /* 'BrtColor14' */
			case 0x00A8: /* 'BrtColorFilter' */
			case 0x00AE: /* 'BrtCustomFilter' */
			case 0x049C: /* 'BrtCustomFilter14' */
			case 0x01F3: /* 'BrtDRef' */
			case 0x0040: /* 'BrtDVal' */
			case 0x041D: /* 'BrtDVal14' */
			case 0x0226: /* 'BrtDrawing' */
			case 0x00AB: /* 'BrtDynamicFilter' */
			case 0x00A7: /* 'BrtFilter' */
			case 0x0499: /* 'BrtFilter14' */
			case 0x00A9: /* 'BrtIconFilter' */
			case 0x049D: /* 'BrtIconFilter14' */
			case 0x0227: /* 'BrtLegacyDrawing' */
			case 0x0228: /* 'BrtLegacyDrawingHF' */
			case 0x0295: /* 'BrtListPart' */
			case 0x027F: /* 'BrtOleObject' */
			case 0x01DE: /* 'BrtPageSetup' */
			case 0x0097: /* 'BrtPane' */
			case 0x0219: /* 'BrtPhoneticInfo' */
			case 0x01DD: /* 'BrtPrintOptions' */
			case 0x0218: /* 'BrtRangeProtection' */
			case 0x044F: /* 'BrtRangeProtection14' */
			case 0x02A8: /* 'BrtRangeProtectionIso' */
			case 0x0450: /* 'BrtRangeProtectionIso14' */
			case 0x0400: /* 'BrtRwDescent' */
			case 0x0098: /* 'BrtSel' */
			case 0x0297: /* 'BrtSheetCalcProp' */
			case 0x0217: /* 'BrtSheetProtection' */
			case 0x02A6: /* 'BrtSheetProtectionIso' */
			case 0x01F8: /* 'BrtSlc' */
			case 0x0413: /* 'BrtSparkline' */
			case 0x01AC: /* 'BrtTable' */
			case 0x00AA: /* 'BrtTop10Filter' */
			case 0x0032: /* 'BrtValueMeta' */
			case 0x0816: /* 'BrtWebExtension' */
			case 0x0415: /* 'BrtWsFmtInfoEx14' */
			case 0x0093: /* 'BrtWsProp' */
				break;

			case 0x0023: /* 'BrtFRTBegin' */
				pass = true; break;
			case 0x0024: /* 'BrtFRTEnd' */
				pass = false; break;
			case 0x0025: /* 'BrtACBegin' */ break;
			case 0x0026: /* 'BrtACEnd' */ break;
S
SheetJS 已提交
11998

S
SheetJS 已提交
11999
			default:
S
SheetJS 已提交
12000 12001
				if((R_n||"").indexOf("Begin") > 0){/* empty */}
				else if((R_n||"").indexOf("End") > 0){/* empty */}
12002
				else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
S
SheetJS 已提交
12003 12004
		}
	}, opts);
S
SheetJS 已提交
12005 12006 12007 12008

	delete opts.supbooks;
	delete opts['!row'];

S
SheetJS 已提交
12009
	if(!s["!ref"] && (refguess.s.r < 2000000 || ref && (ref.e.r > 0 || ref.e.c > 0 || ref.s.r > 0 || ref.s.c > 0))) s["!ref"] = encode_range(ref || refguess);
S
SheetJS 已提交
12010 12011 12012 12013 12014 12015 12016 12017 12018 12019 12020 12021 12022
	if(opts.sheetRows && s["!ref"]) {
		var tmpref = safe_decode_range(s["!ref"]);
		if(opts.sheetRows < +tmpref.e.r) {
			tmpref.e.r = opts.sheetRows - 1;
			if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
			if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
			if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c;
			if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c;
			s["!fullref"] = s["!ref"];
			s["!ref"] = encode_range(tmpref);
		}
	}
	if(mergecells.length > 0) s["!merges"] = mergecells;
S
SheetJS 已提交
12023 12024
	if(colinfo.length > 0) s["!cols"] = colinfo;
	if(rowinfo.length > 0) s["!rows"] = rowinfo;
S
SheetJS 已提交
12025 12026 12027 12028
	return s;
}

/* TODO: something useful -- this is a stub */
S
SheetJS 已提交
12029
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/) {
S
SheetJS 已提交
12030
	if(cell.v === undefined) return "";
S
SheetJS 已提交
12031
	var vv = ""; var olddate = null;
S
SheetJS 已提交
12032 12033
	switch(cell.t) {
		case 'b': vv = cell.v ? "1" : "0"; break;
S
SheetJS 已提交
12034 12035 12036 12037 12038 12039
		case 'd': // no BrtCellDate :(
			cell.z = cell.z || SSF._table[14];
			olddate = cell.v;
			cell.v = datenum((cell.v/*:any*/)); cell.t = 'n';
			break;
		/* falls through */
S
SheetJS 已提交
12040 12041 12042
		case 'n': case 'e': vv = ''+cell.v; break;
		default: vv = cell.v; break;
	}
S
SheetJS 已提交
12043
	var o/*:any*/ = ({r:R, c:C}/*:any*/);
S
SheetJS 已提交
12044
	/* TODO: cell style */
S
SheetJS 已提交
12045
	o.s = get_cell_style(opts.cellXfs, cell, opts);
S
SheetJS 已提交
12046
	if(cell.l) ws['!links'].push([encode_cell(o), cell.l]);
S
SheetJS 已提交
12047
	if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
S
SheetJS 已提交
12048 12049 12050
	switch(cell.t) {
		case 's': case 'str':
			if(opts.bookSST) {
S
SheetJS 已提交
12051
				vv = get_sst_id(opts.Strings, (cell.v/*:any*/));
S
SheetJS 已提交
12052 12053 12054 12055 12056 12057 12058 12059 12060 12061 12062
				o.t = "s"; o.v = vv;
				write_record(ba, "BrtCellIsst", write_BrtCellIsst(cell, o));
			} else {
				o.t = "str";
				write_record(ba, "BrtCellSt", write_BrtCellSt(cell, o));
			}
			return;
		case 'n':
			/* TODO: determine threshold for Real vs RK */
			if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o));
			else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o));
S
SheetJS 已提交
12063
			if(olddate) { cell.t = 'd'; cell.v = olddate; }
S
SheetJS 已提交
12064 12065 12066 12067 12068 12069 12070 12071 12072 12073
			return;
		case 'b':
			o.t = "b";
			write_record(ba, "BrtCellBool", write_BrtCellBool(cell, o));
			return;
		case 'e': /* TODO: error */ o.t = "e"; break;
	}
	write_record(ba, "BrtCellBlank", write_BrtCellBlank(cell, o));
}

S
SheetJS 已提交
12074
function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
S
SheetJS 已提交
12075 12076
	var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = [];
	write_record(ba, 'BrtBeginSheetData');
S
SheetJS 已提交
12077
	var dense = Array.isArray(ws);
12078 12079 12080
	var cap = range.e.r;
	if(ws['!rows']) cap = Math.max(range.e.r, ws['!rows'].length - 1);
	for(var R = range.s.r; R <= cap; ++R) {
S
SheetJS 已提交
12081 12082 12083 12084
		rr = encode_row(R);
		/* [ACCELLTABLE] */
		/* BrtRowHdr */
		write_row_header(ba, ws, range, R);
12085
		if(R <= range.e.r) for(var C = range.s.c; C <= range.e.c; ++C) {
S
SheetJS 已提交
12086 12087 12088
			/* *16384CELL */
			if(R === range.s.r) cols[C] = encode_col(C);
			ref = cols[C] + rr;
S
SheetJS 已提交
12089 12090
			var cell = dense ? (ws[R]||[])[C] : ws[ref];
			if(!cell) continue;
S
SheetJS 已提交
12091
			/* write cell */
S
SheetJS 已提交
12092
			write_ws_bin_cell(ba, cell, R, C, opts, ws);
S
SheetJS 已提交
12093 12094 12095 12096 12097
		}
	}
	write_record(ba, 'BrtEndSheetData');
}

12098 12099 12100 12101 12102 12103 12104
function write_MERGECELLS(ba, ws/*:Worksheet*/) {
	if(!ws || !ws['!merges']) return;
	write_record(ba, 'BrtBeginMergeCells', write_BrtBeginMergeCells(ws['!merges'].length));
	ws['!merges'].forEach(function(m) { write_record(ba, 'BrtMergeCell', write_BrtMergeCell(m)); });
	write_record(ba, 'BrtEndMergeCells');
}

S
SheetJS 已提交
12105 12106 12107 12108 12109 12110 12111
function write_COLINFOS(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
	if(!ws || !ws['!cols']) return;
	write_record(ba, 'BrtBeginColInfos');
	ws['!cols'].forEach(function(m, i) { if(m) write_record(ba, 'BrtColInfo', write_BrtColInfo(i, m)); });
	write_record(ba, 'BrtEndColInfos');
}

S
SheetJS 已提交
12112 12113 12114 12115 12116 12117 12118 12119 12120
function write_HLINKS(ba, ws/*:Worksheet*/, rels) {
	/* *BrtHLink */
	ws['!links'].forEach(function(l) {
		if(!l[1].Target) return;
		var rId = add_rels(rels, -1, l[1].Target.replace(/#.*$/, ""), RELS.HLINK);
		write_record(ba, "BrtHLink", write_BrtHLink(l, rId));
	});
	delete ws['!links'];
}
S
SheetJS 已提交
12121 12122 12123 12124 12125 12126 12127 12128
function write_LEGACYDRAWING(ba, ws/*:Worksheet*/, idx/*:number*/, rels) {
	/* [BrtLegacyDrawing] */
	if(ws['!comments'].length > 0) {
		var rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML);
		write_record(ba, "BrtLegacyDrawing", write_RelID("rId" + rId));
		ws['!legacy'] = rId;
	}
}
S
SheetJS 已提交
12129

S
SheetJS 已提交
12130 12131 12132 12133 12134 12135 12136 12137 12138
function write_AUTOFILTER(ba, ws) {
	if(!ws['!autofilter']) return;
	write_record(ba, "BrtBeginAFilter", write_UncheckedRfX(decode_range(ws['!autofilter'].ref)));
	/* *FILTERCOLUMN */
	/* [SORTSTATE] */
	/* BrtEndAFilter */
	write_record(ba, "BrtEndAFilter");
}

S
SheetJS 已提交
12139 12140 12141 12142 12143 12144 12145 12146 12147 12148 12149 12150 12151 12152 12153
function write_WSVIEWS2(ba, ws) {
	write_record(ba, "BrtBeginWsViews");
	{ /* 1*WSVIEW2 */
		/* [ACUID] */
		write_record(ba, "BrtBeginWsView", write_BrtBeginWsView(ws));
		/* [BrtPane] */
		/* *4BrtSel */
		/* *4SXSELECT */
		/* *FRT */
		write_record(ba, "BrtEndWsView");
	}
	/* *FRT */
	write_record(ba, "BrtEndWsViews");
}

S
SheetJS 已提交
12154 12155 12156 12157 12158
function write_WSFMTINFO(ba, ws) {
	/* [ACWSFMTINFO] */
	//write_record(ba, "BrtWsFmtInfo", write_BrtWsFmtInfo(ws));
}

S
SheetJS 已提交
12159 12160 12161 12162 12163 12164
function write_SHEETPROTECT(ba, ws) {
	if(!ws['!protect']) return;
	/* [BrtSheetProtectionIso] */
	write_record(ba, "BrtSheetProtection", write_BrtSheetProtection(ws['!protect']));
}

S
SheetJS 已提交
12165
function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
S
SheetJS 已提交
12166 12167 12168
	var ba = buf_array();
	var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
	var r = safe_decode_range(ws['!ref'] || "A1");
S
SheetJS 已提交
12169
	ws['!links'] = [];
S
SheetJS 已提交
12170 12171
	/* passed back to write_zip and removed there */
	ws['!comments'] = [];
S
SheetJS 已提交
12172
	write_record(ba, "BrtBeginSheet");
S
SheetJS 已提交
12173
	write_record(ba, "BrtWsProp", write_BrtWsProp(s));
S
SheetJS 已提交
12174
	write_record(ba, "BrtWsDim", write_BrtWsDim(r));
S
SheetJS 已提交
12175
	write_WSVIEWS2(ba, ws);
S
SheetJS 已提交
12176
	write_WSFMTINFO(ba, ws);
S
SheetJS 已提交
12177
	write_COLINFOS(ba, ws, idx, opts, wb);
S
SheetJS 已提交
12178 12179
	write_CELLTABLE(ba, ws, idx, opts, wb);
	/* [BrtSheetCalcProp] */
S
SheetJS 已提交
12180
	write_SHEETPROTECT(ba, ws);
S
SheetJS 已提交
12181 12182
	/* *([BrtRangeProtectionIso] BrtRangeProtection) */
	/* [SCENMAN] */
S
SheetJS 已提交
12183
	write_AUTOFILTER(ba, ws);
S
SheetJS 已提交
12184 12185 12186
	/* [SORTSTATE] */
	/* [DCON] */
	/* [USERSHVIEWS] */
12187
	write_MERGECELLS(ba, ws);
S
SheetJS 已提交
12188 12189 12190
	/* [BrtPhoneticInfo] */
	/* *CONDITIONALFORMATTING */
	/* [DVALS] */
S
SheetJS 已提交
12191
	write_HLINKS(ba, ws, rels);
S
SheetJS 已提交
12192
	/* [BrtPrintOptions] */
S
SheetJS 已提交
12193
	if(ws['!margins']) write_record(ba, "BrtMargins", write_BrtMargins(ws['!margins']));
S
SheetJS 已提交
12194 12195 12196 12197 12198 12199 12200 12201 12202
	/* [BrtPageSetup] */
	/* [HEADERFOOTER] */
	/* [RWBRK] */
	/* [COLBRK] */
	/* *BrtBigName */
	/* [CELLWATCHES] */
	/* [IGNOREECS] */
	/* [SMARTTAGS] */
	/* [BrtDrawing] */
S
SheetJS 已提交
12203
	write_LEGACYDRAWING(ba, ws, idx, rels);
S
SheetJS 已提交
12204 12205 12206 12207 12208 12209 12210 12211 12212 12213
	/* [BrtLegacyDrawingHF] */
	/* [BrtBkHim] */
	/* [OLEOBJECTS] */
	/* [ACTIVEXCONTROLS] */
	/* [WEBPUBITEMS] */
	/* [LISTPARTS] */
	/* FRTWORKSHEET */
	write_record(ba, "BrtEndSheet");
	return ba.end();
}
12214 12215 12216 12217 12218 12219 12220 12221 12222 12223 12224
function parse_numCache(data) {
	var col = [];

	/* 21.2.2.150 pt CT_NumVal */
	(data.match(/<c:pt idx="(\d*)">(.*?)<\/c:pt>/mg)||[]).forEach(function(pt) {
		var q = pt.match(/<c:pt idx="(.*?)"><c:v>(.*)<\/c:v><\/c:pt>/);
		if(!q) return;
		col[+q[1]] = +q[2];
	});

	/* 21.2.2.71 formatCode CT_Xstring */
12225
	var nf = unescapexml((data.match(/<c:formatCode>([\s\S]*?)<\/c:formatCode>/) || ["","General"])[1]);
12226 12227 12228 12229 12230 12231 12232 12233 12234 12235 12236 12237 12238 12239

	return [col, nf];
}

/* 21.2 DrawingML - Charts */
function parse_chart(data, name/*:string*/, opts, rels, wb, csheet) {
	var cs = ((csheet || {"!type":"chart"})/*:any*/);
	if(!data) return csheet;
	/* 21.2.2.27 chart CT_Chart */

	var C = 0, R = 0, col = "A";
	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };

	/* 21.2.2.120 numCache CT_NumData */
12240
	(data.match(/<c:numCache>[\s\S]*?<\/c:numCache>/gm)||[]).forEach(function(nc) {
12241 12242 12243 12244 12245 12246 12247 12248 12249 12250 12251 12252 12253 12254 12255 12256
		var cache = parse_numCache(nc);
		refguess.s.r = refguess.s.c = 0;
		refguess.e.c = C;
		col = encode_col(C);
		cache[0].forEach(function(n,i) {
			cs[col + encode_row(i)] = {t:'n', v:n, z:cache[1] };
			R = i;
		});
		if(refguess.e.r < R) refguess.e.r = R;
		++C;
	});
	if(C > 0) cs["!ref"] = encode_range(refguess);
	return cs;
}
RELS.CS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet";

S
SheetJS 已提交
12257 12258 12259 12260 12261
var CS_XML_ROOT = writextag('chartsheet', null, {
	'xmlns': XMLNS.main[0],
	'xmlns:r': XMLNS.r
});

12262 12263 12264 12265 12266 12267 12268 12269 12270 12271 12272 12273 12274 12275
/* 18.3 Worksheets also covers Chartsheets */
function parse_cs_xml(data/*:?string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
	if(!data) return data;
	/* 18.3.1.12 chartsheet CT_ChartSheet */
	if(!rels) rels = {'!id':{}};
	var s = {'!type':"chart", '!chart':null, '!rel':""};
	var m;

	/* 18.3.1.36 drawing CT_Drawing */
	if((m = data.match(/drawing r:id="(.*?)"/))) s['!rel'] = m[1];

	if(rels['!id'][s['!rel']]) s['!chart'] = rels['!id'][s['!rel']];
	return s;
}
S
SheetJS 已提交
12276 12277 12278 12279 12280 12281 12282
function write_cs_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
	var o = [XML_HEADER, CS_XML_ROOT];
	o[o.length] = writextag("drawing", null, {"r:id": "rId1"});
	add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
	if(o.length>2) { o[o.length] = ('</chartsheet>'); o[1]=o[1].replace("/>",">"); }
	return o.join("");
}
12283 12284 12285 12286 12287 12288

/* [MS-XLSB] 2.1.7.7 Chart Sheet */
function parse_cs_bin(data, opts, rels, wb, themes, styles)/*:Worksheet*/ {
	if(!data) return data;
	if(!rels) rels = {'!id':{}};
	var s = {'!type':"chart", '!chart':null, '!rel':""};
S
SheetJS 已提交
12289
	var state = [];
12290
	var pass = false;
12291 12292 12293 12294 12295 12296 12297 12298 12299 12300 12301 12302 12303 12304 12305 12306 12307 12308 12309 12310 12311 12312 12313 12314 12315
	recordhopper(data, function cs_parse(val, R_n, RT) {
		switch(RT) {

			case 0x0226: /* 'BrtDrawing' */
				s['!rel'] = val; break;

			/* case 'BrtUid': */
			case 0x0232: /* 'BrtBkHim' */
			case 0x028C: /* 'BrtCsPageSetup' */
			case 0x028B: /* 'BrtCsProp' */
			case 0x029D: /* 'BrtCsProtection' */
			case 0x02A7: /* 'BrtCsProtectionIso' */
			case 0x0227: /* 'BrtLegacyDrawing' */
			case 0x0228: /* 'BrtLegacyDrawingHF' */
			case 0x01DC: /* 'BrtMargins' */
				break;

			case 0x0023: /* 'BrtFRTBegin' */
				pass = true; break;
			case 0x0024: /* 'BrtFRTEnd' */
				pass = false; break;
			case 0x0025: /* 'BrtACBegin' */
				state.push(R_n); break;
			case 0x0026: /* 'BrtACEnd' */
				state.pop(); break;
S
SheetJS 已提交
12316 12317

			default:
12318 12319 12320
				if((R_n||"").indexOf("Begin") > 0) state.push(R_n);
				else if((R_n||"").indexOf("End") > 0) state.pop();
				else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
12321 12322 12323 12324 12325 12326
		}
	}, opts);

	if(rels['!id'][s['!rel']]) s['!chart'] = rels['!id'][s['!rel']];
	return s;
}
S
SheetJS 已提交
12327 12328 12329 12330 12331 12332 12333 12334 12335 12336 12337 12338 12339 12340 12341 12342 12343 12344 12345
function write_cs_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
	var ba = buf_array();
	write_record(ba, "BrtBeginSheet");
	/* [BrtCsProp] */
	/* CSVIEWS */
	/* [[BrtCsProtectionIso] BrtCsProtection] */
	/* [USERCSVIEWS] */
	/* [BrtMargins] */
	/* [BrtCsPageSetup] */
	/* [HEADERFOOTER] */
	/* BrtDrawing */
	/* [BrtLegacyDrawing] */
	/* [BrtLegacyDrawingHF] */
	/* [BrtBkHim] */
	/* [WEBPUBITEMS] */
	/* FRTCHARTSHEET */
	write_record(ba, "BrtEndSheet");
	return ba.end();
}
S
SheetJS 已提交
12346 12347
/* 18.2.28 (CT_WorkbookProtection) Defaults */
var WBPropsDef = [
S
SheetJS 已提交
12348 12349 12350 12351 12352 12353 12354 12355 12356 12357 12358 12359 12360 12361 12362 12363 12364 12365
	['allowRefreshQuery',           false, "bool"],
	['autoCompressPictures',        true,  "bool"],
	['backupFile',                  false, "bool"],
	['checkCompatibility',          false, "bool"],
	['codeName',                    ''],
	['date1904',                    false, "bool"],
	['defaultThemeVersion',         0,      "int"],
	['filterPrivacy',               false, "bool"],
	['hidePivotFieldList',          false, "bool"],
	['promptedSolutions',           false, "bool"],
	['publishItems',                false, "bool"],
	['refreshAllConnections',       false, "bool"],
	['saveExternalLinkValues',      true,  "bool"],
	['showBorderUnselectedTables',  true,  "bool"],
	['showInkAnnotation',           true,  "bool"],
	['showObjects',                 'all'],
	['showPivotChartFilter',        false, "bool"],
	['updateLinks', 'userSet']
S
SheetJS 已提交
12366 12367 12368 12369
];

/* 18.2.30 (CT_BookView) Defaults */
var WBViewDef = [
S
SheetJS 已提交
12370 12371 12372 12373 12374 12375 12376 12377 12378
	['activeTab',                   0,      "int"],
	['autoFilterDateGrouping',      true,  "bool"],
	['firstSheet',                  0,      "int"],
	['minimized',                   false, "bool"],
	['showHorizontalScroll',        true,  "bool"],
	['showSheetTabs',               true,  "bool"],
	['showVerticalScroll',          true,  "bool"],
	['tabRatio',                    600,    "int"],
	['visibility',                  'visible']
S
SheetJS 已提交
12379 12380 12381 12382 12383
	//window{Height,Width}, {x,y}Window
];

/* 18.2.19 (CT_Sheet) Defaults */
var SheetDef = [
S
SheetJS 已提交
12384
	//['state', 'visible']
S
SheetJS 已提交
12385 12386 12387 12388 12389 12390 12391 12392 12393 12394 12395 12396 12397 12398 12399 12400 12401 12402 12403 12404 12405 12406 12407 12408 12409 12410 12411 12412 12413 12414 12415 12416 12417 12418 12419 12420 12421 12422 12423 12424 12425 12426
];

/* 18.2.2  (CT_CalcPr) Defaults */
var CalcPrDef = [
	['calcCompleted', 'true'],
	['calcMode', 'auto'],
	['calcOnSave', 'true'],
	['concurrentCalc', 'true'],
	['fullCalcOnLoad', 'false'],
	['fullPrecision', 'true'],
	['iterate', 'false'],
	['iterateCount', '100'],
	['iterateDelta', '0.001'],
	['refMode', 'A1']
];

/* 18.2.3 (CT_CustomWorkbookView) Defaults */
var CustomWBViewDef = [
	['autoUpdate', 'false'],
	['changesSavedWin', 'false'],
	['includeHiddenRowCol', 'true'],
	['includePrintSettings', 'true'],
	['maximized', 'false'],
	['minimized', 'false'],
	['onlySync', 'false'],
	['personalView', 'false'],
	['showComments', 'commIndicator'],
	['showFormulaBar', 'true'],
	['showHorizontalScroll', 'true'],
	['showObjects', 'all'],
	['showSheetTabs', 'true'],
	['showStatusbar', 'true'],
	['showVerticalScroll', 'true'],
	['tabRatio', '600'],
	['xWindow', '0'],
	['yWindow', '0']
];

function push_defaults_array(target, defaults) {
	for(var j = 0; j != target.length; ++j) { var w = target[j];
		for(var i=0; i != defaults.length; ++i) { var z = defaults[i];
			if(w[z[0]] == null) w[z[0]] = z[1];
S
SheetJS 已提交
12427 12428 12429 12430
			else switch(z[2]) {
			case "bool": if(typeof w[z[0]] == "string") w[z[0]] = parsexmlbool(w[z[0]], z[0]); break;
			case "int": if(typeof w[z[0]] == "string") w[z[0]] = parseInt(w[z[0]], 10); break;
			}
S
SheetJS 已提交
12431 12432 12433 12434 12435 12436
		}
	}
}
function push_defaults(target, defaults) {
	for(var i = 0; i != defaults.length; ++i) { var z = defaults[i];
		if(target[z[0]] == null) target[z[0]] = z[1];
S
SheetJS 已提交
12437 12438 12439 12440
		else switch(z[2]) {
			case "bool": if(typeof target[z[0]] == "string") target[z[0]] = parsexmlbool(target[z[0]], z[0]); break;
			case "int": if(typeof target[z[0]] == "string") target[z[0]] = parseInt(target[z[0]], 10); break;
		}
S
SheetJS 已提交
12441 12442 12443 12444 12445 12446 12447 12448 12449 12450 12451 12452
	}
}

function parse_wb_defaults(wb) {
	push_defaults(wb.WBProps, WBPropsDef);
	push_defaults(wb.CalcPr, CalcPrDef);

	push_defaults_array(wb.WBView, WBViewDef);
	push_defaults_array(wb.Sheets, SheetDef);

	_ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904, 'date1904');
}
S
SheetJS 已提交
12453

S
SheetJS 已提交
12454 12455 12456 12457 12458 12459 12460
function safe1904(wb/*:Workbook*/)/*:string*/ {
	/* TODO: store date1904 somewhere else */
	if(!wb.Workbook) return "false";
	if(!wb.Workbook.WBProps) return "false";
	return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false";
}

S
SheetJS 已提交
12461
var badchars = "][*?\/\\".split("");
S
SheetJS 已提交
12462
function check_ws_name(n/*:string*/, safe/*:?boolean*/)/*:boolean*/ {
S
SheetJS 已提交
12463 12464 12465 12466 12467 12468 12469 12470 12471
	if(n.length > 31) { if(safe) return false; throw new Error("Sheet names cannot exceed 31 chars"); }
	var _good = true;
	badchars.forEach(function(c) {
		if(n.indexOf(c) == -1) return;
		if(!safe) throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
		_good = false;
	});
	return _good;
}
S
TXT/PRN  
SheetJS 已提交
12472 12473
function check_wb_names(N) {
	N.forEach(function(n,i) {
S
SheetJS 已提交
12474
		check_ws_name(n);
S
TXT/PRN  
SheetJS 已提交
12475 12476 12477
		for(var j = 0; j < i; ++j) if(n == N[j]) throw new Error("Duplicate Sheet Name: " + n);
	});
}
S
SheetJS 已提交
12478 12479
function check_wb(wb) {
	if(!wb || !wb.SheetNames || !wb.Sheets) throw new Error("Invalid Workbook");
S
TXT/PRN  
SheetJS 已提交
12480 12481
	check_wb_names(wb.SheetNames);
	/* TODO: validate workbook */
S
SheetJS 已提交
12482
}
S
SheetJS 已提交
12483 12484
/* 18.2 Workbook */
var wbnsregex = /<\w+:workbook/;
S
SheetJS 已提交
12485
function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
S
SheetJS 已提交
12486
	if(!data) throw new Error("Could not find file");
S
SheetJS 已提交
12487
	var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, Names:[], xmlns: "" };
S
SheetJS 已提交
12488
	var pass = false, xmlns = "xmlns";
A
Alex Litskevich 已提交
12489 12490 12491
	var dname = {}, dnstart = 0;
	/*(data.match(tagregex)||[]).forEach */
	data.replace(tagregex, function xml_wb(x, idx) {
S
SheetJS 已提交
12492
		var y/*:any*/ = parsexmltag(x);
S
SheetJS 已提交
12493 12494 12495 12496 12497 12498 12499 12500 12501 12502 12503 12504
		switch(strip_ns(y[0])) {
			case '<?xml': break;

			/* 18.2.27 workbook CT_Workbook 1 */
			case '<workbook':
				if(x.match(wbnsregex)) xmlns = "xmlns" + x.match(/<(\w+):/)[1];
				wb.xmlns = y[xmlns];
				break;
			case '</workbook>': break;

			/* 18.2.13 fileVersion CT_FileVersion ? */
			case '<fileVersion': delete y[0]; wb.AppVersion = y; break;
S
SheetJS 已提交
12505
			case '<fileVersion/>': case '</fileVersion>': break;
S
SheetJS 已提交
12506 12507 12508 12509 12510

			/* 18.2.12 fileSharing CT_FileSharing ? */
			case '<fileSharing': case '<fileSharing/>': break;

			/* 18.2.28 workbookPr CT_WorkbookPr ? */
S
SheetJS 已提交
12511 12512 12513 12514 12515 12516 12517 12518 12519 12520 12521
			case '<workbookPr':
			case '<workbookPr/>':
				WBPropsDef.forEach(function(w) {
					if(y[w[0]] == null) return;
					switch(w[2]) {
						case "bool": wb.WBProps[w[0]] = parsexmlbool(y[w[0]], w[0]); break;
						case "int": wb.WBProps[w[0]] = parseInt(y[w[0]], 10); break;
						default: wb.WBProps[w[0]] = y[w[0]];
					}
				});
				break;
S
SheetJS 已提交
12522
			case '</workbookPr>': break;
S
SheetJS 已提交
12523 12524 12525 12526 12527 12528

			/* 18.2.29 workbookProtection CT_WorkbookProtection ? */
			case '<workbookProtection': break;
			case '<workbookProtection/>': break;

			/* 18.2.1  bookViews CT_BookViews ? */
S
SheetJS 已提交
12529
			case '<bookViews': case '<bookViews>': case '</bookViews>': break;
S
SheetJS 已提交
12530 12531
			/* 18.2.30   workbookView CT_BookView + */
			case '<workbookView': delete y[0]; wb.WBView.push(y); break;
S
SheetJS 已提交
12532
			case '</workbookView>': break;
S
SheetJS 已提交
12533 12534

			/* 18.2.20 sheets CT_Sheets 1 */
S
SheetJS 已提交
12535
			case '<sheets': case '<sheets>': case '</sheets>': break; // aggregate sheet
S
SheetJS 已提交
12536
			/* 18.2.19   sheet CT_Sheet + */
S
SheetJS 已提交
12537 12538 12539 12540 12541 12542 12543 12544 12545
			case '<sheet':
				switch(y.state) {
					case "hidden": y.Hidden = 1; break;
					case "veryHidden": y.Hidden = 2; break;
					default: y.Hidden = 0;
				}
				delete y.state;
				y.name = unescapexml(utf8read(y.name));
				delete y[0]; wb.Sheets.push(y); break;
S
SheetJS 已提交
12546
			case '</sheet>': break;
S
SheetJS 已提交
12547 12548 12549 12550 12551 12552 12553 12554 12555 12556 12557 12558 12559 12560 12561 12562

			/* 18.2.15 functionGroups CT_FunctionGroups ? */
			case '<functionGroups': case '<functionGroups/>': break;
			/* 18.2.14   functionGroup CT_FunctionGroup + */
			case '<functionGroup': break;

			/* 18.2.9  externalReferences CT_ExternalReferences ? */
			case '<externalReferences': case '</externalReferences>': case '<externalReferences>': break;
			/* 18.2.8    externalReference CT_ExternalReference + */
			case '<externalReference': break;

			/* 18.2.6  definedNames CT_DefinedNames ? */
			case '<definedNames/>': break;
			case '<definedNames>': case '<definedNames': pass=true; break;
			case '</definedNames>': pass=false; break;
			/* 18.2.5    definedName CT_DefinedName + */
A
Alex Litskevich 已提交
12563 12564 12565 12566
			case '<definedName': {
				dname = {};
				dname.Name = y.name;
				if(y.comment) dname.Comment = y.comment;
S
SheetJS 已提交
12567
				if(y.localSheetId) dname.Sheet = +y.localSheetId;
A
Alex Litskevich 已提交
12568 12569 12570 12571
				dnstart = idx + x.length;
			}	break;
			case '</definedName>': {
				dname.Ref = data.slice(dnstart, idx);
S
SheetJS 已提交
12572
				wb.Names.push(dname);
A
Alex Litskevich 已提交
12573 12574
			} break;
			case '<definedName/>': break;
S
SheetJS 已提交
12575 12576 12577 12578

			/* 18.2.2  calcPr CT_CalcPr ? */
			case '<calcPr': delete y[0]; wb.CalcPr = y; break;
			case '<calcPr/>': delete y[0]; wb.CalcPr = y; break;
S
SheetJS 已提交
12579
			case '</calcPr>': break;
S
SheetJS 已提交
12580 12581 12582 12583 12584 12585 12586 12587 12588 12589 12590 12591 12592 12593 12594 12595 12596 12597 12598 12599 12600 12601 12602 12603 12604 12605 12606 12607 12608 12609 12610 12611 12612 12613

			/* 18.2.16 oleSize CT_OleSize ? (ref required) */
			case '<oleSize': break;

			/* 18.2.4  customWorkbookViews CT_CustomWorkbookViews ? */
			case '<customWorkbookViews>': case '</customWorkbookViews>': case '<customWorkbookViews': break;
			/* 18.2.3    customWorkbookView CT_CustomWorkbookView + */
			case '<customWorkbookView': case '</customWorkbookView>': break;

			/* 18.2.18 pivotCaches CT_PivotCaches ? */
			case '<pivotCaches>': case '</pivotCaches>': case '<pivotCaches': break;
			/* 18.2.17 pivotCache CT_PivotCache ? */
			case '<pivotCache': break;

			/* 18.2.21 smartTagPr CT_SmartTagPr ? */
			case '<smartTagPr': case '<smartTagPr/>': break;

			/* 18.2.23 smartTagTypes CT_SmartTagTypes ? */
			case '<smartTagTypes': case '<smartTagTypes>': case '</smartTagTypes>': break;
			/* 18.2.22   smartTagType CT_SmartTagType ? */
			case '<smartTagType': break;

			/* 18.2.24 webPublishing CT_WebPublishing ? */
			case '<webPublishing': case '<webPublishing/>': break;

			/* 18.2.11 fileRecoveryPr CT_FileRecoveryPr ? */
			case '<fileRecoveryPr': case '<fileRecoveryPr/>': break;

			/* 18.2.26 webPublishObjects CT_WebPublishObjects ? */
			case '<webPublishObjects>': case '<webPublishObjects': case '</webPublishObjects>': break;
			/* 18.2.25 webPublishObject CT_WebPublishObject ? */
			case '<webPublishObject': break;

			/* 18.2.10 extLst CT_ExtensionList ? */
S
SheetJS 已提交
12614
			case '<extLst': case '<extLst>': case '</extLst>': case '<extLst/>': break;
S
SheetJS 已提交
12615 12616 12617 12618 12619 12620 12621 12622 12623
			/* 18.2.7    ext CT_Extension + */
			case '<ext': pass=true; break; //TODO: check with versions of excel
			case '</ext>': pass=false; break;

			/* Others */
			case '<ArchID': break;
			case '<AlternateContent': pass=true; break;
			case '</AlternateContent>': pass=false; break;

S
SheetJS 已提交
12624 12625 12626
			/* TODO */
			case '<revisionPtr': break;

S
SheetJS 已提交
12627
			default: if(!pass && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in workbook');
S
SheetJS 已提交
12628
		}
A
Alex Litskevich 已提交
12629
		return x;
S
SheetJS 已提交
12630 12631 12632 12633 12634 12635 12636 12637 12638 12639 12640 12641 12642 12643 12644
	});
	if(XMLNS.main.indexOf(wb.xmlns) === -1) throw new Error("Unknown Namespace: " + wb.xmlns);

	parse_wb_defaults(wb);

	return wb;
}

var WB_XML_ROOT = writextag('workbook', null, {
	'xmlns': XMLNS.main[0],
	//'xmlns:mx': XMLNS.mx,
	//'xmlns:s': XMLNS.main[0],
	'xmlns:r': XMLNS.r
});

S
SheetJS 已提交
12645
function write_wb_xml(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:string*/ {
S
SheetJS 已提交
12646 12647
	var o = [XML_HEADER];
	o[o.length] = WB_XML_ROOT;
S
SheetJS 已提交
12648

S
SheetJS 已提交
12649 12650
	var write_names = (wb.Workbook && (wb.Workbook.Names||[]).length > 0);

S
SheetJS 已提交
12651 12652 12653
	/* fileVersion */
	/* fileSharing */

S
SheetJS 已提交
12654 12655 12656 12657 12658 12659 12660 12661 12662 12663 12664
	var workbookPr/*:WBProps*/ = ({codeName:"ThisWorkbook"}/*:any*/);
	if(wb.Workbook && wb.Workbook.WBProps) {
		if(wb.Workbook.WBProps.codeName) workbookPr.codeName = wb.Workbook.WBProps.codeName;
		WBPropsDef.forEach(function(x) {
			/*:: if(!wb.Workbook || !wb.Workbook.WBProps) throw "unreachable"; */
			if((wb.Workbook.WBProps[x[0]]/*:any*/) == null) return;
			if((wb.Workbook.WBProps[x[0]]/*:any*/) == x[1]) return;
			workbookPr[x[0]] = (wb.Workbook.WBProps[x[0]]/*:any*/);
		});
	}
	o[o.length] = (writextag('workbookPr', null, workbookPr));
S
SheetJS 已提交
12665 12666 12667 12668

	/* workbookProtection */
	/* bookViews */

S
SheetJS 已提交
12669
	o[o.length] = "<sheets>";
S
SheetJS 已提交
12670 12671 12672 12673 12674 12675 12676 12677 12678 12679 12680
	var sheets = wb.Workbook && wb.Workbook.Sheets || [];
	for(var i = 0; i != wb.SheetNames.length; ++i) {
		var sht = ({name:escapexml(wb.SheetNames[i].substr(0,31))}/*:any*/);
		sht.sheetId = ""+(i+1);
		sht["r:id"] = "rId"+(i+1);
		if(sheets[i]) switch(sheets[i].Hidden) {
			case 1: sht.state = "hidden"; break;
			case 2: sht.state = "veryHidden"; break;
		}
		o[o.length] = (writextag('sheet',null,sht));
	}
S
SheetJS 已提交
12681
	o[o.length] = "</sheets>";
S
SheetJS 已提交
12682 12683 12684

	/* functionGroups */
	/* externalReferences */
S
SheetJS 已提交
12685

S
SheetJS 已提交
12686
	if(write_names) {
S
SheetJS 已提交
12687
		o[o.length] = "<definedNames>";
S
SheetJS 已提交
12688
		if(wb.Workbook && wb.Workbook.Names) wb.Workbook.Names.forEach(function(n) {
S
SheetJS 已提交
12689
			var d/*:any*/ = {name:n.Name};
S
SheetJS 已提交
12690 12691 12692 12693 12694 12695 12696 12697
			if(n.Comment) d.comment = n.Comment;
			if(n.Sheet != null) d.localSheetId = ""+n.Sheet;
			if(!n.Ref) return;
			o[o.length] = writextag('definedName', String(n.Ref), d);
		});
		o[o.length] = "</definedNames>";
	}

S
SheetJS 已提交
12698 12699 12700 12701 12702 12703 12704 12705 12706 12707 12708
	/* calcPr */
	/* oleSize */
	/* customWorkbookViews */
	/* pivotCaches */
	/* smartTagPr */
	/* smartTagTypes */
	/* webPublishing */
	/* fileRecoveryPr */
	/* webPublishObjects */
	/* extLst */

S
SheetJS 已提交
12709 12710 12711 12712
	if(o.length>2){ o[o.length] = '</workbook>'; o[1]=o[1].replace("/>",">"); }
	return o.join("");
}
/* [MS-XLSB] 2.4.301 BrtBundleSh */
S
SheetJS 已提交
12713
function parse_BrtBundleSh(data, length/*:number*/) {
S
SheetJS 已提交
12714
	var z = {};
S
SheetJS 已提交
12715
	z.Hidden = data.read_shift(4); //hsState ST_SheetState
S
SheetJS 已提交
12716 12717 12718 12719 12720 12721 12722
	z.iTabID = data.read_shift(4);
	z.strRelID = parse_RelID(data,length-8);
	z.name = parse_XLWideString(data);
	return z;
}
function write_BrtBundleSh(data, o) {
	if(!o) o = new_buf(127);
S
SheetJS 已提交
12723
	o.write_shift(4, data.Hidden);
S
SheetJS 已提交
12724 12725 12726 12727 12728 12729 12730
	o.write_shift(4, data.iTabID);
	write_RelID(data.strRelID, o);
	write_XLWideString(data.name.substr(0,31), o);
	return o.length > o.l ? o.slice(0, o.l) : o;
}

/* [MS-XLSB] 2.4.807 BrtWbProp */
S
SheetJS 已提交
12731 12732
function parse_BrtWbProp(data, length)/*:WBProps*/ {
	var o/*:WBProps*/ = ({}/*:any*/);
S
SheetJS 已提交
12733 12734
	var flags = data.read_shift(4);
	o.defaultThemeVersion = data.read_shift(4);
S
SheetJS 已提交
12735
	var strName = (length > 8) ? parse_XLWideString(data) : "";
S
SheetJS 已提交
12736 12737 12738 12739 12740 12741 12742 12743 12744 12745 12746 12747 12748 12749 12750 12751 12752
	if(strName.length > 0) o.codeName = strName;
	o.autoCompressPictures = !!(flags & 0x10000);
	o.backupFile = !!(flags & 0x40);
	o.checkCompatibility = !!(flags & 0x1000);
	o.date1904 = !!(flags & 0x01);
	o.filterPrivacy = !!(flags & 0x08);
	o.hidePivotFieldList = !!(flags & 0x400);
	o.promptedSolutions = !!(flags & 0x10);
	o.publishItems = !!(flags & 0x800);
	o.refreshAllConnections = !!(flags & 0x40000);
	o.saveExternalLinkValues = !!(flags & 0x80);
	o.showBorderUnselectedTables = !!(flags & 0x04);
	o.showInkAnnotation = !!(flags & 0x20);
	o.showObjects = ["all", "placeholders", "none"][(flags >> 13) & 0x03];
	o.showPivotChartFilter = !!(flags & 0x8000);
	o.updateLinks = ["userSet", "never", "always"][(flags >> 8) & 0x03];
	return o;
S
SheetJS 已提交
12753
}
S
SheetJS 已提交
12754
function write_BrtWbProp(data/*:?WBProps*/, o) {
S
SheetJS 已提交
12755
	if(!o) o = new_buf(72);
S
SheetJS 已提交
12756 12757 12758 12759 12760 12761
	var flags = 0;
	if(data) {
		/* TODO: mirror parse_BrtWbProp fields */
		if(data.filterPrivacy) flags |= 0x08;
	}
	o.write_shift(4, flags);
S
SheetJS 已提交
12762
	o.write_shift(4, 0);
S
SheetJS 已提交
12763 12764
	write_XLSBCodeName("ThisWorkbook", o);
	return o.slice(0, o.l);
S
SheetJS 已提交
12765 12766 12767 12768 12769 12770 12771 12772 12773 12774
}

function parse_BrtFRTArchID$(data, length) {
	var o = {};
	data.read_shift(4);
	o.ArchID = data.read_shift(4);
	data.l += length - 8;
	return o;
}

S
SheetJS 已提交
12775 12776 12777 12778 12779 12780 12781 12782 12783
/* [MS-XLSB] 2.4.680 BrtName */
function parse_BrtName(data, length, opts) {
	var end = data.l + length;
	var flags = data.read_shift(4);
	var chKey = data.read_shift(1);
	var itab = data.read_shift(4);
	var name = parse_XLNameWideString(data);
	var formula = parse_XLSBNameParsedFormula(data, 0, opts);
	var comment = parse_XLNullableWideString(data);
S
SheetJS 已提交
12784
	//if(0 /* fProc */) {
S
SheetJS 已提交
12785 12786 12787 12788
		// unusedstring1: XLNullableWideString
		// description: XLNullableWideString
		// helpTopic: XLNullableWideString
		// unusedstring2: XLNullableWideString
S
SheetJS 已提交
12789
	//}
S
SheetJS 已提交
12790
	data.l = end;
S
SheetJS 已提交
12791 12792 12793
	var out = ({Name:name, Ptg:formula, Comment:comment}/*:any*/);
	if(itab < 0xFFFFFFF) out.Sheet = itab;
	return out;
S
SheetJS 已提交
12794 12795
}

S
SheetJS 已提交
12796
/* [MS-XLSB] 2.1.7.60 Workbook */
S
SheetJS 已提交
12797
function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
S
SheetJS 已提交
12798 12799 12800
	var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
	var pass = false, z;

S
SheetJS 已提交
12801 12802 12803
	if(!opts) opts = {};
	opts.biff = 12;

S
SheetJS 已提交
12804
	var Names = [];
S
SheetJS 已提交
12805
	var supbooks = ([]/*:any*/);
S
SheetJS 已提交
12806
	supbooks.SheetNames = [];
S
SheetJS 已提交
12807

12808 12809 12810
	recordhopper(data, function hopper_wb(val, R_n, RT) {
		switch(RT) {
			case 0x009C: /* 'BrtBundleSh' */
S
SheetJS 已提交
12811
				supbooks.SheetNames.push(val.name);
12812
				wb.Sheets.push(val); break;
S
SheetJS 已提交
12813

S
SheetJS 已提交
12814 12815 12816
			case 0x0099: /* 'BrtWbProp' */
				wb.WBProps = val; break;

12817
			case 0x0027: /* 'BrtName' */
S
SheetJS 已提交
12818 12819 12820
				val.Ref = stringify_formula(val.Ptg, null, null, supbooks, opts);
				delete val.Ptg;
				Names.push(val);
S
SheetJS 已提交
12821
				break;
12822 12823
			case 0x040C: /* 'BrtNameExt' */ break;

S
SheetJS 已提交
12824 12825 12826 12827 12828 12829 12830
			case 0x0165: /* 'BrtSupSelf' */
			case 0x0166: /* 'BrtSupSame' */
			case 0x0163: /* 'BrtSupBookSrc' */
			case 0x029B: /* 'BrtSupAddin' */
			case 0x016A: /* 'BrtExternSheet' */
			case 0x0169: /* 'BrtPlaceholderName' */
				break;
S
SheetJS 已提交
12831

S
SheetJS 已提交
12832 12833 12834
			/* case 'BrtModelTimeGroupingCalcCol' */
			/* case 'BrtRevisionPtr' */
			/* case 'BrtUid' */
12835 12836 12837 12838 12839 12840 12841 12842 12843 12844 12845 12846 12847 12848 12849 12850 12851 12852 12853 12854 12855 12856 12857 12858 12859 12860 12861 12862 12863 12864 12865 12866 12867 12868 12869 12870
			case 0x0817: /* 'BrtAbsPath15' */
			case 0x0216: /* 'BrtBookProtection' */
			case 0x02A5: /* 'BrtBookProtectionIso' */
			case 0x009E: /* 'BrtBookView' */
			case 0x009D: /* 'BrtCalcProp' */
			case 0x0262: /* 'BrtCrashRecErr' */
			case 0x0802: /* 'BrtDecoupledPivotCacheID' */
			case 0x009B: /* 'BrtFileRecover' */
			case 0x0224: /* 'BrtFileSharing' */
			case 0x02A4: /* 'BrtFileSharingIso' */
			case 0x0080: /* 'BrtFileVersion' */
			case 0x0299: /* 'BrtFnGroup' */
			case 0x0850: /* 'BrtModelRelationship' */
			case 0x084D: /* 'BrtModelTable' */
			case 0x0225: /* 'BrtOleSize' */
			case 0x0805: /* 'BrtPivotTableRef' */
			case 0x0254: /* 'BrtSmartTagType' */
			case 0x081C: /* 'BrtTableSlicerCacheID' */
			case 0x081B: /* 'BrtTableSlicerCacheIDs' */
			case 0x0822: /* 'BrtTimelineCachePivotCacheID' */
			case 0x018D: /* 'BrtUserBookView' */
			case 0x009A: /* 'BrtWbFactoid' */
			case 0x045D: /* 'BrtWbProp14' */
			case 0x0229: /* 'BrtWebOpt' */
			case 0x082B: /* 'BrtWorkBookPr15' */
				break;

			case 0x0023: /* 'BrtFRTBegin' */
				pass = true; break;
			case 0x0024: /* 'BrtFRTEnd' */
				pass = false; break;
			case 0x0025: /* 'BrtACBegin' */ break;
			case 0x0026: /* 'BrtACEnd' */ break;

			case 0x0010: /* 'BrtFRTArchID$' */ break;

S
SheetJS 已提交
12871
			default:
S
SheetJS 已提交
12872 12873
				if((R_n||"").indexOf("Begin") > 0){/* empty */}
				else if((R_n||"").indexOf("End") > 0){/* empty */}
12874
				else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
S
SheetJS 已提交
12875
		}
S
SheetJS 已提交
12876
	}, opts);
S
SheetJS 已提交
12877 12878 12879

	parse_wb_defaults(wb);

S
SheetJS 已提交
12880
	// $FlowIgnore
S
SheetJS 已提交
12881 12882
	wb.Names = Names;

S
SheetJS 已提交
12883 12884 12885 12886 12887 12888 12889
	return wb;
}

/* [MS-XLSB] 2.1.7.60 Workbook */
function write_BUNDLESHS(ba, wb, opts) {
	write_record(ba, "BrtBeginBundleShs");
	for(var idx = 0; idx != wb.SheetNames.length; ++idx) {
S
SheetJS 已提交
12890 12891
		var viz = wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx] && wb.Workbook.Sheets[idx].Hidden || 0;
		var d = { Hidden: viz, iTabID: idx+1, strRelID: 'rId' + (idx+1), name: wb.SheetNames[idx] };
S
SheetJS 已提交
12892 12893 12894 12895 12896 12897 12898 12899 12900 12901 12902 12903 12904 12905 12906 12907 12908
		write_record(ba, "BrtBundleSh", write_BrtBundleSh(d));
	}
	write_record(ba, "BrtEndBundleShs");
}

/* [MS-XLSB] 2.4.643 BrtFileVersion */
function write_BrtFileVersion(data, o) {
	if(!o) o = new_buf(127);
	for(var i = 0; i != 4; ++i) o.write_shift(4, 0);
	write_XLWideString("SheetJS", o);
	write_XLWideString(XLSX.version, o);
	write_XLWideString(XLSX.version, o);
	write_XLWideString("7262", o);
	o.length = o.l;
	return o.length > o.l ? o.slice(0, o.l) : o;
}

S
SheetJS 已提交
12909 12910 12911 12912 12913 12914 12915 12916 12917 12918 12919 12920 12921 12922 12923
/* [MS-XLSB] 2.4.298 BrtBookView */
function write_BrtBookView(idx, o) {
	if(!o) o = new_buf(29);
	o.write_shift(-4, 0);
	o.write_shift(-4, 460);
	o.write_shift(4,  28800);
	o.write_shift(4,  17600);
	o.write_shift(4,  500);
	o.write_shift(4,  idx);
	o.write_shift(4,  idx);
	var flags = 0x78;
	o.write_shift(1,  flags);
	return o.length > o.l ? o.slice(0, o.l) : o;
}

S
SheetJS 已提交
12924 12925
/* [MS-XLSB] 2.1.7.60 Workbook */
function write_BOOKVIEWS(ba, wb, opts) {
S
SheetJS 已提交
12926 12927 12928 12929 12930 12931 12932 12933 12934
	/* required if hidden tab appears before visible tab */
	if(!wb.Workbook || !wb.Workbook.Sheets) return;
	var sheets = wb.Workbook.Sheets;
	var i = 0, vistab = -1, hidden = -1;
	for(; i < sheets.length; ++i) {
		if(!sheets[i] || !sheets[i].Hidden && vistab == -1) vistab = i;
		else if(sheets[i].Hidden == 1 && hidden == -1) hidden = i;
	}
	if(hidden > vistab) return;
S
SheetJS 已提交
12935
	write_record(ba, "BrtBeginBookViews");
S
SheetJS 已提交
12936
	write_record(ba, "BrtBookView", write_BrtBookView(vistab));
S
SheetJS 已提交
12937 12938 12939 12940 12941 12942 12943 12944 12945 12946 12947 12948 12949 12950 12951 12952 12953 12954 12955 12956 12957 12958 12959 12960 12961 12962 12963 12964 12965 12966
	/* 1*(BrtBookView *FRT) */
	write_record(ba, "BrtEndBookViews");
}

/* [MS-XLSB] 2.4.302 BrtCalcProp */
function write_BrtCalcProp(data, o) {
	if(!o) o = new_buf(26);
	o.write_shift(4,0); /* force recalc */
	o.write_shift(4,1);
	o.write_shift(4,0);
	write_Xnum(0, o);
	o.write_shift(-4, 1023);
	o.write_shift(1, 0x33);
	o.write_shift(1, 0x00);
	return o;
}

/* [MS-XLSB] 2.4.640 BrtFileRecover */
function write_BrtFileRecover(data, o) {
	if(!o) o = new_buf(1);
	o.write_shift(1,0);
	return o;
}

/* [MS-XLSB] 2.1.7.60 Workbook */
function write_wb_bin(wb, opts) {
	var ba = buf_array();
	write_record(ba, "BrtBeginBook");
	write_record(ba, "BrtFileVersion", write_BrtFileVersion());
	/* [[BrtFileSharingIso] BrtFileSharing] */
S
SheetJS 已提交
12967
	write_record(ba, "BrtWbProp", write_BrtWbProp(wb.Workbook && wb.Workbook.WBProps || null));
S
SheetJS 已提交
12968 12969
	/* [ACABSPATH] */
	/* [[BrtBookProtectionIso] BrtBookProtection] */
S
SheetJS 已提交
12970
	write_BOOKVIEWS(ba, wb, opts);
S
SheetJS 已提交
12971 12972 12973 12974
	write_BUNDLESHS(ba, wb, opts);
	/* [FNGROUP] */
	/* [EXTERNALS] */
	/* *BrtName */
S
SheetJS 已提交
12975
	/* write_record(ba, "BrtCalcProp", write_BrtCalcProp()); */
S
SheetJS 已提交
12976 12977 12978 12979 12980 12981
	/* [BrtOleSize] */
	/* *(BrtUserBookView *FRT) */
	/* [PIVOTCACHEIDS] */
	/* [BrtWbFactoid] */
	/* [SMARTTAGTYPES] */
	/* [BrtWebOpt] */
S
SheetJS 已提交
12982
	/* write_record(ba, "BrtFileRecover", write_BrtFileRecover()); */
S
SheetJS 已提交
12983 12984 12985 12986 12987 12988 12989
	/* [WEBPUBITEMS] */
	/* [CRERRS] */
	/* FRTWORKBOOK */
	write_record(ba, "BrtEndBook");

	return ba.end();
}
S
SheetJS 已提交
12990
function parse_wb(data, name/*:string*/, opts)/*:WorkbookFile*/ {
12991
	if(name.slice(-4)===".bin") return parse_wb_bin((data/*:any*/), opts);
S
SheetJS 已提交
12992
	return parse_wb_xml((data/*:any*/), opts);
S
SheetJS 已提交
12993 12994
}

S
SheetJS 已提交
12995 12996 12997
function parse_ws(data, name/*:string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
	if(name.slice(-4)===".bin") return parse_ws_bin((data/*:any*/), opts, rels, wb, themes, styles);
	return parse_ws_xml((data/*:any*/), opts, rels, wb, themes, styles);
S
SheetJS 已提交
12998 12999
}

13000 13001 13002 13003 13004
function parse_cs(data, name/*:string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
	if(name.slice(-4)===".bin") return parse_cs_bin((data/*:any*/), opts, rels, wb, themes, styles);
	return parse_cs_xml((data/*:any*/), opts, rels, wb, themes, styles);
}

S
SheetJS 已提交
13005 13006 13007 13008 13009 13010 13011 13012 13013 13014
function parse_ms(data, name/*:string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
	if(name.slice(-4)===".bin") return parse_ms_bin((data/*:any*/), opts, rels, wb, themes, styles);
	return parse_ms_xml((data/*:any*/), opts, rels, wb, themes, styles);
}

function parse_ds(data, name/*:string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
	if(name.slice(-4)===".bin") return parse_ds_bin((data/*:any*/), opts, rels, wb, themes, styles);
	return parse_ds_xml((data/*:any*/), opts, rels, wb, themes, styles);
}

P
Pieter Sheth-Voss 已提交
13015 13016 13017
function parse_sty(data, name/*:string*/, themes, opts) {
	if(name.slice(-4)===".bin") return parse_sty_bin((data/*:any*/), themes, opts);
	return parse_sty_xml((data/*:any*/), themes, opts);
S
SheetJS 已提交
13018 13019
}

S
SheetJS 已提交
13020
function parse_theme(data/*:string*/, name/*:string*/, opts) {
S
SheetJS 已提交
13021 13022 13023
	return parse_theme_xml(data, opts);
}

S
SheetJS 已提交
13024
function parse_sst(data, name/*:string*/, opts)/*:SST*/ {
13025
	if(name.slice(-4)===".bin") return parse_sst_bin((data/*:any*/), opts);
S
SheetJS 已提交
13026
	return parse_sst_xml((data/*:any*/), opts);
S
SheetJS 已提交
13027 13028
}

S
SheetJS 已提交
13029
function parse_cmnt(data, name/*:string*/, opts) {
13030
	if(name.slice(-4)===".bin") return parse_comments_bin((data/*:any*/), opts);
S
SheetJS 已提交
13031
	return parse_comments_xml((data/*:any*/), opts);
S
SheetJS 已提交
13032 13033
}

S
SheetJS 已提交
13034
function parse_cc(data, name/*:string*/, opts) {
13035
	if(name.slice(-4)===".bin") return parse_cc_bin((data/*:any*/), opts);
S
SheetJS 已提交
13036
	return parse_cc_xml((data/*:any*/), opts);
S
SheetJS 已提交
13037 13038
}

S
SheetJS 已提交
13039
function write_wb(wb, name/*:string*/, opts) {
13040
	return (name.slice(-4)===".bin" ? write_wb_bin : write_wb_xml)(wb, opts);
S
SheetJS 已提交
13041 13042
}

S
SheetJS 已提交
13043
function write_ws(data/*:number*/, name/*:string*/, opts, wb/*:Workbook*/, rels) {
S
SheetJS 已提交
13044
	return (name.slice(-4)===".bin" ? write_ws_bin : write_ws_xml)(data, opts, wb, rels);
S
SheetJS 已提交
13045 13046
}

S
SheetJS 已提交
13047 13048 13049 13050
function write_cs(data/*:number*/, name/*:string*/, opts, wb/*:Workbook*/, rels) {
	return (name.slice(-4)===".bin" ? write_cs_bin : write_cs_xml)(data, opts, wb, rels);
}

S
SheetJS 已提交
13051
function write_sty(data, name/*:string*/, opts) {
13052
	return (name.slice(-4)===".bin" ? write_sty_bin : write_sty_xml)(data, opts);
S
SheetJS 已提交
13053 13054
}

S
SheetJS 已提交
13055
function write_sst(data/*:SST*/, name/*:string*/, opts) {
13056
	return (name.slice(-4)===".bin" ? write_sst_bin : write_sst_xml)(data, opts);
S
SheetJS 已提交
13057
}
S
SheetJS 已提交
13058 13059

function write_cmnt(data/*:Array<any>*/, name/*:string*/, opts) {
13060
	return (name.slice(-4)===".bin" ? write_comments_bin : write_comments_xml)(data, opts);
S
SheetJS 已提交
13061
}
S
SheetJS 已提交
13062
/*
S
SheetJS 已提交
13063
function write_cc(data, name:string, opts) {
13064
	return (name.slice(-4)===".bin" ? write_cc_bin : write_cc_xml)(data, opts);
S
SheetJS 已提交
13065 13066 13067 13068 13069
}
*/
var attregexg2=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
var attregex2=/([\w:]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;
var _chr = function(c) { return String.fromCharCode(c); };
S
SheetJS 已提交
13070
function xlml_parsexmltag(tag/*:string*/, skip_root/*:?boolean*/) {
S
SheetJS 已提交
13071
	var words = tag.split(/\s+/);
S
SheetJS 已提交
13072
	var z/*:any*/ = ([]/*:any*/); if(!skip_root) z[0] = words[0];
S
SheetJS 已提交
13073 13074 13075 13076
	if(words.length === 1) return z;
	var m = tag.match(attregexg2), y, j, w, i;
	if(m) for(i = 0; i != m.length; ++i) {
		y = m[i].match(attregex2);
S
SheetJS 已提交
13077
/*:: if(!y || !y[2]) continue; */
S
SheetJS 已提交
13078 13079 13080 13081 13082 13083 13084 13085 13086
		if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].substr(1,y[2].length-2);
		else {
			if(y[1].substr(0,6) === "xmlns:") w = "xmlns"+y[1].substr(6);
			else w = y[1].substr(j+1);
			z[w] = y[2].substr(1,y[2].length-2);
		}
	}
	return z;
}
S
SheetJS 已提交
13087
function xlml_parsexmltagobj(tag/*:string*/) {
S
SheetJS 已提交
13088 13089 13090 13091 13092 13093
	var words = tag.split(/\s+/);
	var z = {};
	if(words.length === 1) return z;
	var m = tag.match(attregexg2), y, j, w, i;
	if(m) for(i = 0; i != m.length; ++i) {
		y = m[i].match(attregex2);
S
SheetJS 已提交
13094
/*:: if(!y || !y[2]) continue; */
S
SheetJS 已提交
13095 13096 13097 13098 13099 13100 13101 13102 13103 13104 13105 13106
		if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].substr(1,y[2].length-2);
		else {
			if(y[1].substr(0,6) === "xmlns:") w = "xmlns"+y[1].substr(6);
			else w = y[1].substr(j+1);
			z[w] = y[2].substr(1,y[2].length-2);
		}
	}
	return z;
}

// ----

S
SheetJS 已提交
13107
function xlml_format(format, value)/*:string*/ {
S
SheetJS 已提交
13108 13109 13110 13111 13112
	var fmt = XLMLFormatMap[format] || unescapexml(format);
	if(fmt === "General") return SSF._general(value);
	return SSF.format(fmt, value);
}

S
SheetJS 已提交
13113 13114
function xlml_set_custprop(Custprops, Rn, cp, val/*:string*/) {
	var oval/*:any*/ = val;
S
SheetJS 已提交
13115
	switch((cp[0].match(/dt:dt="([\w.]+)"/)||["",""])[1]) {
S
SheetJS 已提交
13116 13117 13118
		case "boolean": oval = parsexmlbool(val); break;
		case "i2": case "int": oval = parseInt(val, 10); break;
		case "r4": case "float": oval = parseFloat(val); break;
S
SheetJS 已提交
13119
		case "date": case "dateTime.tz": oval = parseDate(val); break;
S
SheetJS 已提交
13120
		case "i8": case "string": case "fixed": case "uuid": case "bin.base64": break;
S
SheetJS 已提交
13121
		default: throw new Error("bad custprop:" + cp[0]);
S
SheetJS 已提交
13122
	}
S
SheetJS 已提交
13123
	Custprops[unescapexml(Rn[3])] = oval;
S
SheetJS 已提交
13124 13125
}

S
SheetJS 已提交
13126
function safe_format_xlml(cell/*:Cell*/, nf, o) {
S
SheetJS 已提交
13127
	if(cell.t === 'z') return;
S
SheetJS 已提交
13128
	if(!o || o.cellText !== false) try {
S
SheetJS 已提交
13129 13130 13131 13132 13133 13134 13135 13136 13137
		if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
		else if(nf === "General") {
			if(cell.t === 'n') {
				if((cell.v|0) === cell.v) cell.w = SSF._general_int(cell.v);
				else cell.w = SSF._general_num(cell.v);
			}
			else cell.w = SSF._general(cell.v);
		}
		else cell.w = xlml_format(nf||"General", cell.v);
S
SheetJS 已提交
13138 13139
	} catch(e) { if(o.WTF) throw e; }
	try {
S
SheetJS 已提交
13140 13141 13142
		var z = XLMLFormatMap[nf]||nf||"General";
		if(o.cellNF) cell.z = z;
		if(o.cellDates && cell.t == 'n' && SSF.is_date(z)) {
S
SheetJS 已提交
13143
			var _d = SSF.parse_date_code(cell.v); if(_d) { cell.t = 'd'; cell.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
S
SheetJS 已提交
13144
		}
S
SheetJS 已提交
13145 13146 13147 13148 13149 13150 13151 13152 13153 13154 13155 13156 13157 13158
	} catch(e) { if(o.WTF) throw e; }
}

function process_style_xlml(styles, stag, opts) {
	if(opts.cellStyles) {
		if(stag.Interior) {
			var I = stag.Interior;
			if(I.Pattern) I.patternType = XLMLPatternTypeMap[I.Pattern] || I.Pattern;
		}
	}
	styles[stag.ID] = stag;
}

/* TODO: there must exist some form of OSP-blessed spec */
S
SheetJS 已提交
13159
function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o) {
S
SheetJS 已提交
13160 13161
	var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
	var interiors = [];
13162
	var i = 0;
S
SheetJS 已提交
13163 13164 13165 13166 13167 13168 13169 13170 13171 13172 13173 13174 13175 13176 13177
	if(sid === undefined && row) sid = row.StyleID;
	if(sid === undefined && csty) sid = csty.StyleID;
	while(styles[sid] !== undefined) {
		if(styles[sid].nf) nf = styles[sid].nf;
		if(styles[sid].Interior) interiors.push(styles[sid].Interior);
		if(!styles[sid].Parent) break;
		sid = styles[sid].Parent;
	}
	switch(data.Type) {
		case 'Boolean':
			cell.t = 'b';
			cell.v = parsexmlbool(xml);
			break;
		case 'String':
			cell.t = 's'; cell.r = xlml_fixstr(unescapexml(xml));
S
SheetJS 已提交
13178
			cell.v = xml.indexOf("<") > -1 ? unescapexml(ss) : cell.r;
S
SheetJS 已提交
13179 13180
			break;
		case 'DateTime':
13181
			if(xml.slice(-1) != "Z") xml += "Z";
S
SheetJS 已提交
13182
			cell.v = (parseDate(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
S
SheetJS 已提交
13183
			if(cell.v !== cell.v) cell.v = unescapexml(xml);
S
SheetJS 已提交
13184
			else if(cell.v<60) cell.v = cell.v -1;
S
SheetJS 已提交
13185 13186 13187 13188 13189 13190
			if(!nf || nf == "General") nf = "yyyy-mm-dd";
			/* falls through */
		case 'Number':
			if(cell.v === undefined) cell.v=+xml;
			if(!cell.t) cell.t = 'n';
			break;
S
SheetJS 已提交
13191
		case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; if(o.cellText !== false) cell.w = xml; break;
S
SheetJS 已提交
13192
		default: cell.t = 's'; cell.v = xlml_fixstr(ss||xml); break;
S
SheetJS 已提交
13193 13194
	}
	safe_format_xlml(cell, nf, o);
S
SheetJS 已提交
13195
	if(o.cellFormula !== false) {
S
SheetJS 已提交
13196 13197 13198 13199 13200
		if(cell.Formula) {
			var fstr = unescapexml(cell.Formula);
			/* strictly speaking, the leading = is required but some writers omit */
			if(fstr.charCodeAt(0) == 61 /* = */) fstr = fstr.substr(1);
			cell.f = rc_to_a1(fstr, base);
S
SheetJS 已提交
13201
			delete cell.Formula;
S
SheetJS 已提交
13202 13203 13204 13205 13206 13207 13208 13209 13210 13211 13212
			if(cell.ArrayRange == "RC") cell.F = rc_to_a1("RC:RC", base);
			else if(cell.ArrayRange) {
				cell.F = rc_to_a1(cell.ArrayRange, base);
				arrayf.push([safe_decode_range(cell.F), cell.F]);
			}
		} else {
			for(i = 0; i < arrayf.length; ++i)
				if(base.r >= arrayf[i][0].s.r && base.r <= arrayf[i][0].e.r)
					if(base.c >= arrayf[i][0].s.c && base.c <= arrayf[i][0].e.c)
						cell.F = arrayf[i][1];
		}
S
SheetJS 已提交
13213 13214 13215 13216 13217 13218 13219 13220 13221 13222
	}
	if(o.cellStyles) {
		interiors.forEach(function(x) {
			if(!S.patternType && x.patternType) S.patternType = x.patternType;
		});
		cell.s = S;
	}
	cell.ixfe = cell.StyleID !== undefined ? cell.StyleID : 'Default';
}

S
SheetJS 已提交
13223
function xlml_clean_comment(comment/*:any*/) {
S
SheetJS 已提交
13224 13225
	comment.t = comment.v || "";
	comment.t = comment.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n");
S
SheetJS 已提交
13226 13227 13228
	comment.v = comment.w = comment.ixfe = undefined;
}

S
SheetJS 已提交
13229
function xlml_normalize(d)/*:string*/ {
S
SheetJS 已提交
13230
	if(has_buf &&/*::typeof Buffer !== "undefined" && d != null && d instanceof Buffer &&*/ Buffer.isBuffer(d)) return d.toString('utf8');
S
SheetJS 已提交
13231
	if(typeof d === 'string') return d;
S
SheetJS 已提交
13232
	throw new Error("Bad input format: expected Buffer or string");
S
SheetJS 已提交
13233 13234 13235
}

/* TODO: Everything */
13236
/* UOS uses CJK in tags */
S
SheetJS 已提交
13237
var xlmlregex = /<(\/?)([^\s?>!\/:]*:|)([^\s?>]*[^\s?>\/])[^>]*>/mg;
13238
//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
S
SheetJS 已提交
13239 13240
function parse_xlml_xml(d, _opts)/*:Workbook*/ {
	var opts = _opts || {};
S
SheetJS 已提交
13241
	make_ssf(SSF);
S
SheetJS 已提交
13242
	var str = debom(xlml_normalize(d));
S
SheetJS 已提交
13243
	if(opts && opts.type == 'binary' && typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str));
S
SheetJS 已提交
13244 13245 13246
	var opening = str.slice(0, 1024).toLowerCase(), ishtml = false;
	if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; });
	if(ishtml) return HTML_.to_workbook(str, opts);
S
SheetJS 已提交
13247 13248
	var Rn;
	var state = [], tmp;
13249
	if(DENSE != null && opts.dense == null) opts.dense = DENSE;
S
SheetJS 已提交
13250
	var sheets = {}, sheetnames = [], cursheet/*:Worksheet*/ = (opts.dense ? [] : {}), sheetname = "";
S
SheetJS 已提交
13251 13252
	var table = {}, cell = ({}/*:any*/), row = {};
	var dtag = xlml_parsexmltag('<Data ss:Type="String">'), didx = 0;
S
SheetJS 已提交
13253 13254 13255 13256 13257 13258 13259
	var c = 0, r = 0;
	var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
	var styles = {}, stag = {};
	var ss = "", fidx = 0;
	var mergecells = [];
	var Props = {}, Custprops = {}, pidx = 0, cp = {};
	var comments = [], comment = {};
S
SheetJS 已提交
13260
	var cstys = [], csty, seencol = false;
S
SheetJS 已提交
13261
	var arrayf = [];
S
SheetJS 已提交
13262
	var rowinfo = [], rowobj = {};
S
SheetJS 已提交
13263
	var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false} }/*:any*/), wsprops = {};
S
SheetJS 已提交
13264
	xlmlregex.lastIndex = 0;
S
SheetJS 已提交
13265
	str = str.replace(/<!--([\s\S]*?)-->/mg,"");
S
SheetJS 已提交
13266 13267 13268
	while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
		case 'Data':
			if(state[state.length-1][1]) break;
S
SheetJS 已提交
13269
			if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]=="Comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts);
S
SheetJS 已提交
13270 13271 13272 13273 13274
			else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; }
			break;
		case 'Cell':
			if(Rn[1]==='/'){
				if(comments.length > 0) cell.c = comments;
S
SheetJS 已提交
13275 13276 13277 13278 13279 13280
				if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== undefined) {
					if(opts.dense) {
						if(!cursheet[r]) cursheet[r] = [];
						cursheet[r][c] = cell;
					} else cursheet[encode_col(c) + encode_row(r)] = cell;
				}
S
SheetJS 已提交
13281
				if(cell.HRef) {
S
SheetJS 已提交
13282 13283
					cell.l = {Target:cell.HRef, Tooltip:cell.HRefScreenTip};
					delete cell.HRef; delete cell.HRefScreenTip;
S
SheetJS 已提交
13284 13285 13286 13287 13288 13289
				}
				if(cell.MergeAcross || cell.MergeDown) {
					var cc = c + (parseInt(cell.MergeAcross,10)|0);
					var rr = r + (parseInt(cell.MergeDown,10)|0);
					mergecells.push({s:{c:c,r:r},e:{c:cc,r:rr}});
				}
S
SheetJS 已提交
13290 13291 13292 13293 13294
				if(!opts.sheetStubs) { if(cell.MergeAcross) c = cc + 1; else ++c; }
				else if(cell.MergeAcross || cell.MergeDown) {
					/*:: if(!cc) cc = 0; if(!rr) rr = 0; */
					for(var cma = c; cma <= cc; ++cma) {
						for(var cmd = r; cmd <= rr; ++cmd) {
S
SheetJS 已提交
13295 13296 13297 13298 13299 13300
							if(cma > c || cmd > r) {
								if(opts.dense) {
									if(!cursheet[cmd]) cursheet[cmd] = [];
									cursheet[cmd][cma] = {t:'z'};
								} else cursheet[encode_col(cma) + encode_row(cmd)] = {t:'z'};
							}
S
SheetJS 已提交
13301 13302 13303 13304 13305
						}
					}
					c = cc + 1;
				}
				else ++c;
S
SheetJS 已提交
13306 13307 13308 13309 13310
			} else {
				cell = xlml_parsexmltagobj(Rn[0]);
				if(cell.Index) c = +cell.Index - 1;
				if(c < refguess.s.c) refguess.s.c = c;
				if(c > refguess.e.c) refguess.e.c = c;
13311
				if(Rn[0].slice(-2) === "/>") ++c;
S
SheetJS 已提交
13312 13313 13314 13315
				comments = [];
			}
			break;
		case 'Row':
13316
			if(Rn[1]==='/' || Rn[0].slice(-2) === "/>") {
S
SheetJS 已提交
13317 13318
				if(r < refguess.s.r) refguess.s.r = r;
				if(r > refguess.e.r) refguess.e.r = r;
13319
				if(Rn[0].slice(-2) === "/>") {
S
SheetJS 已提交
13320 13321 13322 13323 13324 13325 13326
					row = xlml_parsexmltag(Rn[0]);
					if(row.Index) r = +row.Index - 1;
				}
				c = 0; ++r;
			} else {
				row = xlml_parsexmltag(Rn[0]);
				if(row.Index) r = +row.Index - 1;
S
SheetJS 已提交
13327
				rowobj = {};
S
SheetJS 已提交
13328
				if(row.AutoFitHeight == "0" || row.Height) {
S
SheetJS 已提交
13329 13330 13331 13332
					rowobj.hpx = parseInt(row.Height, 10); rowobj.hpt = px2pt(rowobj.hpx);
					rowinfo[r] = rowobj;
				}
				if(row.Hidden == "1") { rowobj.hidden = true; rowinfo[r] = rowobj; }
S
SheetJS 已提交
13333 13334 13335 13336
			}
			break;
		case 'Worksheet': /* TODO: read range from FullRows/FullColumns */
			if(Rn[1]==='/'){
S
SheetJS 已提交
13337
				if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
S
SheetJS 已提交
13338 13339 13340
				sheetnames.push(sheetname);
				if(refguess.s.r <= refguess.e.r && refguess.s.c <= refguess.e.c) cursheet["!ref"] = encode_range(refguess);
				if(mergecells.length) cursheet["!merges"] = mergecells;
S
SheetJS 已提交
13341 13342
				if(cstys.length > 0) cursheet["!cols"] = cstys;
				if(rowinfo.length > 0) cursheet["!rows"] = rowinfo;
S
SheetJS 已提交
13343 13344 13345 13346 13347 13348
				sheets[sheetname] = cursheet;
			} else {
				refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
				r = c = 0;
				state.push([Rn[3], false]);
				tmp = xlml_parsexmltag(Rn[0]);
S
SheetJS 已提交
13349
				sheetname = unescapexml(tmp.Name);
S
SheetJS 已提交
13350
				cursheet = (opts.dense ? [] : {});
S
SheetJS 已提交
13351
				mergecells = [];
S
SheetJS 已提交
13352
				arrayf = [];
S
SheetJS 已提交
13353
				rowinfo = [];
S
SheetJS 已提交
13354 13355
				wsprops = {name:sheetname, Hidden:0};
				Workbook.Sheets.push(wsprops);
S
SheetJS 已提交
13356 13357 13358
			}
			break;
		case 'Table':
S
SheetJS 已提交
13359
			if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
S
SheetJS 已提交
13360 13361 13362 13363
			else if(Rn[0].slice(-2) == "/>") break;
			else {
				table = xlml_parsexmltag(Rn[0]);
				state.push([Rn[3], false]);
S
SheetJS 已提交
13364
				cstys = []; seencol = false;
S
SheetJS 已提交
13365 13366 13367 13368 13369 13370 13371 13372 13373
			}
			break;

		case 'Style':
			if(Rn[1]==='/') process_style_xlml(styles, stag, opts);
			else stag = xlml_parsexmltag(Rn[0]);
			break;

		case 'NumberFormat':
S
SheetJS 已提交
13374 13375 13376 13377
			stag.nf = unescapexml(xlml_parsexmltag(Rn[0]).Format || "General");
			if(XLMLFormatMap[stag.nf]) stag.nf = XLMLFormatMap[stag.nf];
			for(var ssfidx = 0; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == stag.nf) break;
			if(ssfidx == 0x188) for(ssfidx = 0x39; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == null) { SSF.load(stag.nf, ssfidx); break; }
S
SheetJS 已提交
13378 13379 13380 13381 13382
			break;

		case 'Column':
			if(state[state.length-1][0] !== 'Table') break;
			csty = xlml_parsexmltag(Rn[0]);
S
SheetJS 已提交
13383 13384
			if(csty.Hidden) { csty.hidden = true; delete csty.Hidden; }
			if(csty.Width) csty.wpx = parseInt(csty.Width, 10);
S
SheetJS 已提交
13385
			if(!seencol && csty.wpx > 10) {
S
SheetJS 已提交
13386
				seencol = true; MDW = DEF_MDW; //find_mdw_wpx(csty.wpx);
S
SheetJS 已提交
13387 13388 13389
				for(var _col = 0; _col < cstys.length; ++_col) if(cstys[_col]) process_col(cstys[_col]);
			}
			if(seencol) process_col(csty);
S
SheetJS 已提交
13390
			cstys[(csty.Index-1||cstys.length)] = csty;
S
SheetJS 已提交
13391
			for(var i = 0; i < +csty.Span; ++i) cstys[cstys.length] = dup(csty);
S
SheetJS 已提交
13392 13393
			break;

S
SheetJS 已提交
13394 13395 13396
		case 'NamedRange':
			if(!Workbook.Names) Workbook.Names = [];
			var _NamedRange = parsexmltag(Rn[0]);
S
SheetJS 已提交
13397
			var _DefinedName/*:DefinedName*/ = ({
S
SheetJS 已提交
13398 13399
				Name: _NamedRange.Name,
				Ref: rc_to_a1(_NamedRange.RefersTo.substr(1))
S
SheetJS 已提交
13400
			}/*:any*/);
S
SheetJS 已提交
13401
			if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1;
S
SheetJS 已提交
13402
			/*:: if(Workbook.Names) */Workbook.Names.push(_DefinedName);
S
SheetJS 已提交
13403 13404
			break;

S
SheetJS 已提交
13405 13406 13407 13408 13409 13410 13411 13412 13413 13414 13415 13416
		case 'NamedCell': break;
		case 'B': break;
		case 'I': break;
		case 'U': break;
		case 'S': break;
		case 'Sub': break;
		case 'Sup': break;
		case 'Span': break;
		case 'Border': break;
		case 'Alignment': break;
		case 'Borders': break;
		case 'Font':
13417
			if(Rn[0].slice(-2) === "/>") break;
S
SheetJS 已提交
13418 13419 13420 13421 13422 13423 13424 13425 13426 13427 13428 13429 13430 13431 13432 13433 13434 13435 13436 13437 13438 13439 13440 13441 13442
			else if(Rn[1]==="/") ss += str.slice(fidx, Rn.index);
			else fidx = Rn.index + Rn[0].length;
			break;
		case 'Interior':
			if(!opts.cellStyles) break;
			stag.Interior = xlml_parsexmltag(Rn[0]);
			break;
		case 'Protection': break;

		case 'Author':
		case 'Title':
		case 'Description':
		case 'Created':
		case 'Keywords':
		case 'Subject':
		case 'Category':
		case 'Company':
		case 'LastAuthor':
		case 'LastSaved':
		case 'LastPrinted':
		case 'Version':
		case 'Revision':
		case 'TotalTime':
		case 'HyperlinkBase':
		case 'Manager':
S
SheetJS 已提交
13443 13444 13445
		case 'ContentStatus':
		case 'Identifier':
		case 'Language':
13446
			if(Rn[0].slice(-2) === "/>") break;
S
SheetJS 已提交
13447 13448 13449 13450 13451 13452 13453
			else if(Rn[1]==="/") xlml_set_prop(Props, Rn[3], str.slice(pidx, Rn.index));
			else pidx = Rn.index + Rn[0].length;
			break;
		case 'Paragraphs': break;

		case 'Styles':
		case 'Workbook':
S
SheetJS 已提交
13454
			if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
S
SheetJS 已提交
13455 13456 13457 13458 13459
			else state.push([Rn[3], false]);
			break;

		case 'Comment':
			if(Rn[1]==='/'){
S
SheetJS 已提交
13460
				if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
S
SheetJS 已提交
13461 13462 13463 13464 13465 13466 13467 13468 13469
				xlml_clean_comment(comment);
				comments.push(comment);
			} else {
				state.push([Rn[3], false]);
				tmp = xlml_parsexmltag(Rn[0]);
				comment = {a:tmp.Author};
			}
			break;

S
SheetJS 已提交
13470 13471 13472 13473 13474 13475 13476 13477 13478
		case 'AutoFilter':
			if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
			else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
				var AutoFilter = xlml_parsexmltag(Rn[0]);
				cursheet['!autofilter'] = { ref:rc_to_a1(AutoFilter.Range).replace(/\$/g,"") };
				state.push([Rn[3], true]);
			}
			break;

S
SheetJS 已提交
13479 13480 13481 13482 13483 13484 13485 13486 13487 13488 13489 13490 13491 13492 13493 13494 13495 13496 13497 13498 13499 13500
		case 'Name': break;

		case 'ComponentOptions':
		case 'DocumentProperties':
		case 'CustomDocumentProperties':
		case 'OfficeDocumentSettings':
		case 'PivotTable':
		case 'PivotCache':
		case 'Names':
		case 'MapInfo':
		case 'PageBreaks':
		case 'QueryTable':
		case 'DataValidation':
		case 'Sorting':
		case 'Schema':
		case 'data':
		case 'ConditionalFormatting':
		case 'SmartTagType':
		case 'SmartTags':
		case 'ExcelWorkbook':
		case 'WorkbookOptions':
		case 'WorksheetOptions':
S
SheetJS 已提交
13501
			if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
S
SheetJS 已提交
13502 13503 13504 13505
			else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
			break;

		default:
13506 13507 13508 13509 13510
			/* FODS file root is <office:document> */
			if(state.length == 0 && Rn[3] == "document") return parse_fods(str, opts);
			/* UOS file root is <uof:UOF> */
			if(state.length == 0 && Rn[3] == "UOF") return parse_fods(str, opts);

S
SheetJS 已提交
13511 13512 13513 13514 13515 13516 13517 13518 13519 13520 13521 13522
			var seen = true;
			switch(state[state.length-1][0]) {
				/* OfficeDocumentSettings */
				case 'OfficeDocumentSettings': switch(Rn[3]) {
					case 'AllowPNG': break;
					case 'RemovePersonalInformation': break;
					case 'DownloadComponents': break;
					case 'LocationOfComponents': break;
					case 'Colors': break;
					case 'Color': break;
					case 'Index': break;
					case 'RGB': break;
S
SheetJS 已提交
13523
					case 'PixelsPerInch': break; // TODO: set PPI
S
SheetJS 已提交
13524 13525 13526 13527 13528 13529 13530 13531 13532 13533 13534 13535 13536 13537 13538 13539 13540 13541 13542 13543
					case 'TargetScreenSize': break;
					case 'ReadOnlyRecommended': break;
					default: seen = false;
				} break;

				/* ComponentOptions */
				case 'ComponentOptions': switch(Rn[3]) {
					case 'Toolbar': break;
					case 'HideOfficeLogo': break;
					case 'SpreadsheetAutoFit': break;
					case 'Label': break;
					case 'Caption': break;
					case 'MaxHeight': break;
					case 'MaxWidth': break;
					case 'NextSheetNumber': break;
					default: seen = false;
				} break;

				/* ExcelWorkbook */
				case 'ExcelWorkbook': switch(Rn[3]) {
S
SheetJS 已提交
13544 13545 13546 13547
					case 'Date1904':
						/*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
						Workbook.WBProps.date1904 = true;
						break;
S
SheetJS 已提交
13548 13549 13550 13551 13552 13553 13554 13555 13556 13557 13558 13559 13560 13561 13562 13563 13564 13565 13566 13567 13568 13569 13570 13571 13572 13573 13574 13575 13576 13577 13578 13579 13580 13581 13582 13583 13584 13585 13586 13587 13588 13589 13590 13591 13592 13593 13594 13595 13596 13597 13598 13599 13600 13601 13602 13603 13604
					case 'WindowHeight': break;
					case 'WindowWidth': break;
					case 'WindowTopX': break;
					case 'WindowTopY': break;
					case 'TabRatio': break;
					case 'ProtectStructure': break;
					case 'ProtectWindows': break;
					case 'ActiveSheet': break;
					case 'DisplayInkNotes': break;
					case 'FirstVisibleSheet': break;
					case 'SupBook': break;
					case 'SheetName': break;
					case 'SheetIndex': break;
					case 'SheetIndexFirst': break;
					case 'SheetIndexLast': break;
					case 'Dll': break;
					case 'AcceptLabelsInFormulas': break;
					case 'DoNotSaveLinkValues': break;
					case 'Iteration': break;
					case 'MaxIterations': break;
					case 'MaxChange': break;
					case 'Path': break;
					case 'Xct': break;
					case 'Count': break;
					case 'SelectedSheets': break;
					case 'Calculation': break;
					case 'Uncalced': break;
					case 'StartupPrompt': break;
					case 'Crn': break;
					case 'ExternName': break;
					case 'Formula': break;
					case 'ColFirst': break;
					case 'ColLast': break;
					case 'WantAdvise': break;
					case 'Boolean': break;
					case 'Error': break;
					case 'Text': break;
					case 'OLE': break;
					case 'NoAutoRecover': break;
					case 'PublishObjects': break;
					case 'DoNotCalculateBeforeSave': break;
					case 'Number': break;
					case 'RefModeR1C1': break;
					case 'EmbedSaveSmartTags': break;
					default: seen = false;
				} break;

				/* WorkbookOptions */
				case 'WorkbookOptions': switch(Rn[3]) {
					case 'OWCVersion': break;
					case 'Height': break;
					case 'Width': break;
					default: seen = false;
				} break;

				/* WorksheetOptions */
				case 'WorksheetOptions': switch(Rn[3]) {
S
SheetJS 已提交
13605
					case 'Visible':
S
SheetJS 已提交
13606
						if(Rn[0].slice(-2) === "/>"){/* empty */}
S
SheetJS 已提交
13607 13608 13609 13610 13611 13612
						else if(Rn[1]==="/") switch(str.slice(pidx, Rn.index)) {
							case "SheetHidden": wsprops.Hidden = 1; break;
							case "SheetVeryHidden": wsprops.Hidden = 2; break;
						}
						else pidx = Rn.index + Rn[0].length;
						break;
S
SheetJS 已提交
13613 13614 13615 13616 13617 13618 13619 13620 13621 13622 13623 13624 13625 13626 13627 13628
					case 'Header':
						if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
						cursheet['!margins'].header = parsexmltag(Rn[0]).Margin;
						break;
					case 'Footer':
						if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
						cursheet['!margins'].footer = parsexmltag(Rn[0]).Margin;
						break;
					case 'PageMargins':
						var pagemargins = parsexmltag(Rn[0]);
						if(!cursheet['!margins']) default_margins(cursheet['!margins']={},'xlml');
						if(pagemargins.Top) cursheet['!margins'].top = pagemargins.Top;
						if(pagemargins.Left) cursheet['!margins'].left = pagemargins.Left;
						if(pagemargins.Right) cursheet['!margins'].right = pagemargins.Right;
						if(pagemargins.Bottom) cursheet['!margins'].bottom = pagemargins.Bottom;
						break;
S
SheetJS 已提交
13629 13630 13631 13632 13633 13634 13635 13636 13637 13638 13639 13640 13641 13642 13643 13644 13645 13646 13647 13648 13649 13650 13651 13652 13653 13654 13655 13656 13657 13658 13659 13660 13661 13662 13663 13664 13665 13666 13667 13668 13669 13670 13671 13672 13673 13674 13675 13676 13677 13678 13679 13680 13681 13682 13683 13684 13685 13686 13687 13688 13689 13690 13691 13692 13693 13694 13695 13696 13697 13698 13699 13700 13701 13702 13703 13704 13705 13706 13707 13708 13709 13710 13711 13712 13713 13714 13715 13716 13717 13718 13719 13720 13721 13722 13723 13724 13725 13726 13727 13728 13729 13730 13731 13732 13733 13734 13735 13736 13737 13738 13739 13740 13741 13742 13743 13744 13745 13746 13747 13748 13749 13750 13751 13752 13753 13754 13755 13756 13757 13758 13759 13760 13761 13762 13763 13764 13765 13766 13767 13768 13769 13770 13771 13772 13773 13774 13775 13776 13777 13778 13779 13780 13781 13782 13783 13784 13785 13786 13787 13788 13789 13790 13791 13792 13793 13794 13795 13796 13797 13798 13799 13800 13801 13802 13803 13804 13805 13806
					case 'Unsynced': break;
					case 'Print': break;
					case 'Panes': break;
					case 'Scale': break;
					case 'Pane': break;
					case 'Number': break;
					case 'Layout': break;
					case 'PageSetup': break;
					case 'Selected': break;
					case 'ProtectObjects': break;
					case 'EnableSelection': break;
					case 'ProtectScenarios': break;
					case 'ValidPrinterInfo': break;
					case 'HorizontalResolution': break;
					case 'VerticalResolution': break;
					case 'NumberofCopies': break;
					case 'ActiveRow': break;
					case 'ActiveCol': break;
					case 'ActivePane': break;
					case 'TopRowVisible': break;
					case 'TopRowBottomPane': break;
					case 'LeftColumnVisible': break;
					case 'LeftColumnRightPane': break;
					case 'FitToPage': break;
					case 'RangeSelection': break;
					case 'PaperSizeIndex': break;
					case 'PageLayoutZoom': break;
					case 'PageBreakZoom': break;
					case 'FilterOn': break;
					case 'DoNotDisplayGridlines': break;
					case 'SplitHorizontal': break;
					case 'SplitVertical': break;
					case 'FreezePanes': break;
					case 'FrozenNoSplit': break;
					case 'FitWidth': break;
					case 'FitHeight': break;
					case 'CommentsLayout': break;
					case 'Zoom': break;
					case 'LeftToRight': break;
					case 'Gridlines': break;
					case 'AllowSort': break;
					case 'AllowFilter': break;
					case 'AllowInsertRows': break;
					case 'AllowDeleteRows': break;
					case 'AllowInsertCols': break;
					case 'AllowDeleteCols': break;
					case 'AllowInsertHyperlinks': break;
					case 'AllowFormatCells': break;
					case 'AllowSizeCols': break;
					case 'AllowSizeRows': break;
					case 'NoSummaryRowsBelowDetail': break;
					case 'TabColorIndex': break;
					case 'DoNotDisplayHeadings': break;
					case 'ShowPageLayoutZoom': break;
					case 'NoSummaryColumnsRightDetail': break;
					case 'BlackAndWhite': break;
					case 'DoNotDisplayZeros': break;
					case 'DisplayPageBreak': break;
					case 'RowColHeadings': break;
					case 'DoNotDisplayOutline': break;
					case 'NoOrientation': break;
					case 'AllowUsePivotTables': break;
					case 'ZeroHeight': break;
					case 'ViewableRange': break;
					case 'Selection': break;
					case 'ProtectContents': break;
					default: seen = false;
				} break;

				/* PivotTable */
				case 'PivotTable': case 'PivotCache': switch(Rn[3]) {
					case 'ImmediateItemsOnDrop': break;
					case 'ShowPageMultipleItemLabel': break;
					case 'CompactRowIndent': break;
					case 'Location': break;
					case 'PivotField': break;
					case 'Orientation': break;
					case 'LayoutForm': break;
					case 'LayoutSubtotalLocation': break;
					case 'LayoutCompactRow': break;
					case 'Position': break;
					case 'PivotItem': break;
					case 'DataType': break;
					case 'DataField': break;
					case 'SourceName': break;
					case 'ParentField': break;
					case 'PTLineItems': break;
					case 'PTLineItem': break;
					case 'CountOfSameItems': break;
					case 'Item': break;
					case 'ItemType': break;
					case 'PTSource': break;
					case 'CacheIndex': break;
					case 'ConsolidationReference': break;
					case 'FileName': break;
					case 'Reference': break;
					case 'NoColumnGrand': break;
					case 'NoRowGrand': break;
					case 'BlankLineAfterItems': break;
					case 'Hidden': break;
					case 'Subtotal': break;
					case 'BaseField': break;
					case 'MapChildItems': break;
					case 'Function': break;
					case 'RefreshOnFileOpen': break;
					case 'PrintSetTitles': break;
					case 'MergeLabels': break;
					case 'DefaultVersion': break;
					case 'RefreshName': break;
					case 'RefreshDate': break;
					case 'RefreshDateCopy': break;
					case 'VersionLastRefresh': break;
					case 'VersionLastUpdate': break;
					case 'VersionUpdateableMin': break;
					case 'VersionRefreshableMin': break;
					case 'Calculation': break;
					default: seen = false;
				} break;

				/* PageBreaks */
				case 'PageBreaks': switch(Rn[3]) {
					case 'ColBreaks': break;
					case 'ColBreak': break;
					case 'RowBreaks': break;
					case 'RowBreak': break;
					case 'ColStart': break;
					case 'ColEnd': break;
					case 'RowEnd': break;
					default: seen = false;
				} break;

				/* AutoFilter */
				case 'AutoFilter': switch(Rn[3]) {
					case 'AutoFilterColumn': break;
					case 'AutoFilterCondition': break;
					case 'AutoFilterAnd': break;
					case 'AutoFilterOr': break;
					default: seen = false;
				} break;

				/* QueryTable */
				case 'QueryTable': switch(Rn[3]) {
					case 'Id': break;
					case 'AutoFormatFont': break;
					case 'AutoFormatPattern': break;
					case 'QuerySource': break;
					case 'QueryType': break;
					case 'EnableRedirections': break;
					case 'RefreshedInXl9': break;
					case 'URLString': break;
					case 'HTMLTables': break;
					case 'Connection': break;
					case 'CommandText': break;
					case 'RefreshInfo': break;
					case 'NoTitles': break;
					case 'NextId': break;
					case 'ColumnInfo': break;
					case 'OverwriteCells': break;
					case 'DoNotPromptForFile': break;
					case 'TextWizardSettings': break;
					case 'Source': break;
					case 'Number': break;
					case 'Decimal': break;
					case 'ThousandSeparator': break;
					case 'TrailingMinusNumbers': break;
					case 'FormatSettings': break;
					case 'FieldType': break;
					case 'Delimiters': break;
					case 'Tab': break;
					case 'Comma': break;
					case 'AutoFormatName': break;
					case 'VersionLastEdit': break;
					case 'VersionLastRefresh': break;
					default: seen = false;
				} break;

				case 'Sorting':
				case 'ConditionalFormatting':
S
SheetJS 已提交
13807 13808
				case 'DataValidation':
				switch(Rn[3]) {
S
SheetJS 已提交
13809 13810 13811 13812 13813 13814 13815 13816 13817 13818 13819 13820 13821 13822 13823 13824 13825 13826 13827 13828 13829 13830 13831 13832 13833 13834 13835 13836 13837 13838 13839 13840 13841 13842 13843 13844 13845 13846 13847 13848 13849 13850 13851 13852 13853 13854 13855 13856 13857 13858 13859 13860 13861 13862 13863 13864 13865 13866 13867 13868
					case 'Range': break;
					case 'Type': break;
					case 'Min': break;
					case 'Max': break;
					case 'Sort': break;
					case 'Descending': break;
					case 'Order': break;
					case 'CaseSensitive': break;
					case 'Value': break;
					case 'ErrorStyle': break;
					case 'ErrorMessage': break;
					case 'ErrorTitle': break;
					case 'CellRangeList': break;
					case 'InputMessage': break;
					case 'InputTitle': break;
					case 'ComboHide': break;
					case 'InputHide': break;
					case 'Condition': break;
					case 'Qualifier': break;
					case 'UseBlank': break;
					case 'Value1': break;
					case 'Value2': break;
					case 'Format': break;
					default: seen = false;
				} break;

				/* MapInfo (schema) */
				case 'MapInfo': case 'Schema': case 'data': switch(Rn[3]) {
					case 'Map': break;
					case 'Entry': break;
					case 'Range': break;
					case 'XPath': break;
					case 'Field': break;
					case 'XSDType': break;
					case 'FilterOn': break;
					case 'Aggregate': break;
					case 'ElementType': break;
					case 'AttributeType': break;
				/* These are from xsd (XML Schema Definition) */
					case 'schema':
					case 'element':
					case 'complexType':
					case 'datatype':
					case 'all':
					case 'attribute':
					case 'extends': break;

					case 'row': break;
					default: seen = false;
				} break;

				/* SmartTags (can be anything) */
				case 'SmartTags': break;

				default: seen = false; break;
			}
			if(seen) break;
			/* CustomDocumentProperties */
			if(!state[state.length-1][1]) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
			if(state[state.length-1][0]==='CustomDocumentProperties') {
13869
				if(Rn[0].slice(-2) === "/>") break;
S
SheetJS 已提交
13870 13871 13872 13873 13874 13875
				else if(Rn[1]==="/") xlml_set_custprop(Custprops, Rn, cp, str.slice(pidx, Rn.index));
				else { cp = Rn; pidx = Rn.index + Rn[0].length; }
				break;
			}
			if(opts.WTF) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
	}
S
SheetJS 已提交
13876
	var out = ({}/*:any*/);
S
SheetJS 已提交
13877 13878
	if(!opts.bookSheets && !opts.bookProps) out.Sheets = sheets;
	out.SheetNames = sheetnames;
S
SheetJS 已提交
13879
	out.Workbook = Workbook;
S
SheetJS 已提交
13880 13881 13882 13883 13884 13885
	out.SSF = SSF.get_table();
	out.Props = Props;
	out.Custprops = Custprops;
	return out;
}

S
SheetJS 已提交
13886 13887 13888
function arr2str(data/*:any*/)/*:string*/ { return data.map(_chr).join(""); }

function parse_xlml(data/*:RawBytes|string*/, opts)/*:Workbook*/ {
S
SheetJS 已提交
13889 13890 13891 13892
	fix_read_opts(opts=opts||{});
	switch(opts.type||"base64") {
		case "base64": return parse_xlml_xml(Base64.decode(data), opts);
		case "binary": case "buffer": case "file": return parse_xlml_xml(data, opts);
S
SheetJS 已提交
13893
		case "array": return parse_xlml_xml(arr2str(data), opts);
S
SheetJS 已提交
13894
	}
S
SheetJS 已提交
13895
	/*:: throw new Error("unsupported type " + opts.type); */
S
SheetJS 已提交
13896 13897
}

13898
/* TODO */
S
SheetJS 已提交
13899 13900 13901
function write_props_xlml(wb, opts) {
	var o = [];
	/* DocumentProperties */
S
SheetJS 已提交
13902
	if(wb.Props) o.push(xlml_write_docprops(wb.Props, opts));
S
SheetJS 已提交
13903
	/* CustomDocumentProperties */
S
SheetJS 已提交
13904
	if(wb.Custprops) o.push(xlml_write_custprops(wb.Props, wb.Custprops, opts));
S
SheetJS 已提交
13905 13906
	return o.join("");
}
S
SheetJS 已提交
13907 13908 13909 13910 13911 13912 13913 13914 13915 13916 13917
/* TODO */
function write_wb_xlml(wb, opts) {
	/* OfficeDocumentSettings */
	/* ExcelWorkbook */
	return "";
}
/* TODO */
function write_sty_xlml(wb, opts)/*:string*/ {
	/* Styles */
	return "";
}
S
SheetJS 已提交
13918 13919
/* WorksheetOptions */
function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
S
SheetJS 已提交
13920
	if(!ws) return "";
S
SheetJS 已提交
13921
	var o = [];
S
SheetJS 已提交
13922 13923 13924 13925 13926 13927 13928 13929 13930 13931 13932 13933 13934 13935 13936 13937 13938 13939 13940 13941 13942 13943 13944 13945 13946 13947 13948 13949
	/* NOTE: spec technically allows any order, but stick with implied order */

	/* FitToPage */
	/* DoNotDisplayColHeaders */
	/* DoNotDisplayRowHeaders */
	/* ViewableRange */
	/* Selection */
	/* GridlineColor */
	/* Name */
	/* ExcelWorksheetType */
	/* IntlMacro */
	/* Unsynced */
	/* Selected */
	/* CodeName */

	if(ws['!margins']) {
		o.push("<PageSetup>");
		if(ws['!margins'].header) o.push(writextag("Header", null, {'x:Margin':ws['!margins'].header}));
		if(ws['!margins'].footer) o.push(writextag("Footer", null, {'x:Margin':ws['!margins'].footer}));
		o.push(writextag("PageMargins", null, {
			'x:Bottom': ws['!margins'].bottom || "0.75",
			'x:Left': ws['!margins'].left || "0.7",
			'x:Right': ws['!margins'].right || "0.7",
			'x:Top': ws['!margins'].top || "0.75"
		}));
		o.push("</PageSetup>");
	}

S
SheetJS 已提交
13950
	/* PageSetup */
S
SheetJS 已提交
13951 13952 13953 13954 13955 13956 13957 13958 13959 13960 13961 13962
	/* DisplayPageBreak */
	/* TransitionExpressionEvaluation */
	/* TransitionFormulaEntry */
	/* Print */
	/* Zoom */
	/* PageLayoutZoom */
	/* PageBreakZoom */
	/* ShowPageBreakZoom */
	/* DefaultRowHeight */
	/* DefaultColumnWidth */
	/* StandardWidth */

S
SheetJS 已提交
13963 13964
	if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) {
		/* Visible */
S
SheetJS 已提交
13965
		if(wb.Workbook.Sheets[idx].Hidden) o.push(writextag("Visible", (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden"), {}));
S
SheetJS 已提交
13966 13967 13968 13969 13970 13971
		else {
			/* Selected */
			for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break;
			if(i == idx) o.push("<Selected/>");
		}
	}
S
SheetJS 已提交
13972 13973 13974 13975 13976 13977 13978 13979 13980 13981 13982 13983 13984 13985 13986 13987 13988 13989 13990 13991 13992 13993 13994 13995 13996 13997 13998 13999 14000 14001 14002 14003 14004 14005 14006 14007 14008 14009 14010 14011 14012 14013 14014 14015 14016 14017 14018 14019 14020

	/* LeftColumnVisible */
	/* DisplayRightToLeft */
	/* GridlineColorIndex */
	/* DisplayFormulas */
	/* DoNotDisplayGridlines */
	/* DoNotDisplayHeadings */
	/* DoNotDisplayOutline */
	/* ApplyAutomaticOutlineStyles */
	/* NoSummaryRowsBelowDetail */
	/* NoSummaryColumnsRightDetail */
	/* DoNotDisplayZeros */
	/* ActiveRow */
	/* ActiveColumn */
	/* FilterOn */
	/* RangeSelection */
	/* TopRowVisible */
	/* TopRowBottomPane */
	/* LeftColumnRightPane */
	/* ActivePane */
	/* SplitHorizontal */
	/* SplitVertical */
	/* FreezePanes */
	/* FrozenNoSplit */
	/* TabColorIndex */
	/* Panes */

	/* NOTE: Password not supported in XLML Format */
	if(ws['!protect']) {
		o.push(writetag("ProtectContents", "True"));
		if(ws['!protect'].objects) o.push(writetag("ProtectObjects", "True"));
		if(ws['!protect'].scenarios) o.push(writetag("ProtectScenarios", "True"));
		if(ws['!protect'].selectLockedCells != null && !ws['!protect'].selectLockedCells) o.push(writetag("EnableSelection", "NoSelection"));
		else if(ws['!protect'].selectUnlockedCells != null && !ws['!protect'].selectUnlockedCells) o.push(writetag("EnableSelection", "UnlockedCells"));
	[
		[ "formatColumns", "AllowFormatCells" ],
		[ "formatRows", "AllowSizeCols" ],
		[ "formatCells", "AllowSizeRows" ],
		[ "insertColumns", "AllowInsertCols" ],
		[ "insertRows", "AllowInsertRows" ],
		[ "insertHyperlinks", "AllowInsertHyperlinks" ],
		[ "deleteColumns", "AllowDeleteCols" ],
		[ "deleteRows", "AllowDeleteRows" ],
		[ "sort", "AllowSort" ],
		[ "autoFilter", "AllowFilter" ],
		[ "pivotTables", "AllowUsePivotTables" ]
	].forEach(function(x) { if(ws['!protect'][x[0]]) o.push("<"+x[1]+"/>"); });
	}

S
SheetJS 已提交
14021 14022 14023
	if(o.length == 0) return "";
	return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x});
}
S
SheetJS 已提交
14024 14025 14026 14027 14028 14029 14030 14031
function write_ws_xlml_comment(comments) {
	return comments.map(function(c) {
		// TODO: formatted text
		var t = xlml_unfixstr(c.t||"");
		var d =writextag("ss:Data", t, {"xmlns":"http://www.w3.org/TR/REC-html40"});
		return writextag("Comment", d, {"ss:Author":c.a});
	}).join("");
}
S
SheetJS 已提交
14032
function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
S
SheetJS 已提交
14033
	if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>";
S
SheetJS 已提交
14034 14035 14036

	var attr = {};
	if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr));
S
SheetJS 已提交
14037 14038 14039 14040
	if(cell.F && cell.F.substr(0, ref.length) == ref) {
		var end = decode_cell(cell.F.substr(ref.length + 1));
		attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]");
	}
S
SheetJS 已提交
14041

S
SheetJS 已提交
14042 14043 14044 14045 14046
	if(cell.l && cell.l.Target) {
		attr["ss:HRef"] = escapexml(cell.l.Target);
		if(cell.l.Tooltip) attr["x:HRefScreenTip"] = escapexml(cell.l.Tooltip);
	}

14047 14048 14049 14050 14051 14052 14053 14054 14055
	if(ws['!merges']) {
		var marr = ws['!merges'];
		for(var mi = 0; mi != marr.length; ++mi) {
			if(marr[mi].s.c != addr.c || marr[mi].s.r != addr.r) continue;
			if(marr[mi].e.c > marr[mi].s.c) attr['ss:MergeAcross'] = marr[mi].e.c - marr[mi].s.c;
			if(marr[mi].e.r > marr[mi].s.r) attr['ss:MergeDown'] = marr[mi].e.r - marr[mi].s.r;
		}
	}

S
SheetJS 已提交
14056 14057
	var t = "", p = "";
	switch(cell.t) {
S
SheetJS 已提交
14058
		case 'z': return "";
S
SheetJS 已提交
14059 14060 14061 14062
		case 'n': t = 'Number'; p = String(cell.v); break;
		case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
		case 'e': t = 'Error'; p = BErr[cell.v]; break;
		case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); break;
S
SheetJS 已提交
14063
		case 's': t = 'String'; p = escapexml(cell.v||""); break;
S
SheetJS 已提交
14064
	}
S
SheetJS 已提交
14065 14066 14067 14068
	var _v = (cell.v != null ? p : "");
	if(opts && opts.type == 'binary' && typeof cptable !== 'undefined' && cell.t == 's') {
		_v = cptable.utils.encode(65001, _v);
		var __v = "";
S
SheetJS 已提交
14069
		for(var __i = 0; __i < _v.length; ++__i) __v += String.fromCharCode(_v[__i]);
S
SheetJS 已提交
14070 14071 14072
		_v = __v;
	}
	var m = '<Data ss:Type="' + t + '">' + _v + '</Data>';
S
SheetJS 已提交
14073

S
SheetJS 已提交
14074 14075
	if((cell.c||[]).length > 0) m += write_ws_xlml_comment(cell.c);

S
SheetJS 已提交
14076 14077
	return writextag("Cell", m, attr);
}
S
SheetJS 已提交
14078 14079 14080 14081 14082 14083 14084 14085 14086
function write_ws_xlml_row(R/*:number*/, row)/*:string*/ {
	var o = '<Row ss:Index="' + (R+1) + '"';
	if(row) {
		if(row.hpt && !row.hpx) row.hpx = pt2px(row.hpt);
		if(row.hpx) o += ' ss:AutoFitHeight="0" ss:Height="' + row.hpx + '"';
		if(row.hidden) o += ' ss:Hidden="1"';
	}
	return o + '>';
}
S
SheetJS 已提交
14087 14088 14089 14090
/* TODO */
function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
	if(!ws['!ref']) return "";
	var range = safe_decode_range(ws['!ref']);
14091
	var marr = ws['!merges'] || [], mi = 0;
S
SheetJS 已提交
14092
	var o = [];
S
SheetJS 已提交
14093
	if(ws['!cols']) ws['!cols'].forEach(function(n, i) {
S
SheetJS 已提交
14094 14095
		process_col(n);
		var w = !!n.width;
S
SheetJS 已提交
14096
		var p = col_obj_w(i, n);
S
SheetJS 已提交
14097
		var k/*:any*/ = {"ss:Index":i+1};
S
SheetJS 已提交
14098 14099 14100
		if(w) k['ss:Width'] = width2px(p.width);
		if(n.hidden) k['ss:Hidden']="1";
		o.push(writextag("Column",null,k));
S
SheetJS 已提交
14101
	});
S
SheetJS 已提交
14102
	var dense = Array.isArray(ws);
S
SheetJS 已提交
14103
	for(var R = range.s.r; R <= range.e.r; ++R) {
S
SheetJS 已提交
14104
		var row = [write_ws_xlml_row(R, (ws['!rows']||[])[R])];
S
SheetJS 已提交
14105
		for(var C = range.s.c; C <= range.e.c; ++C) {
14106 14107 14108 14109 14110 14111 14112 14113 14114 14115
			var skip = false;
			for(mi = 0; mi != marr.length; ++mi) {
				if(marr[mi].s.c > C) continue;
				if(marr[mi].s.r > R) continue;
				if(marr[mi].e.c < C) continue;
				if(marr[mi].e.r < R) continue;
				if(marr[mi].s.c != C || marr[mi].s.r != R) skip = true;
				break;
			}
			if(skip) continue;
S
SheetJS 已提交
14116
			var addr = {r:R,c:C};
S
SheetJS 已提交
14117 14118
			var ref = encode_cell(addr), cell = dense ? (ws[R]||[])[C] : ws[ref];
			row.push(write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr));
S
SheetJS 已提交
14119 14120
		}
		row.push("</Row>");
14121
		if(row.length > 2) o.push(row.join(""));
S
SheetJS 已提交
14122 14123 14124 14125 14126 14127 14128 14129 14130 14131 14132
	}
	return o.join("");
}
function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ {
	var o = [];
	var s = wb.SheetNames[idx];
	var ws = wb.Sheets[s];

	/* Table */
	var t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
	if(t.length > 0) o.push("<Table>" + t + "</Table>");
S
SheetJS 已提交
14133

S
SheetJS 已提交
14134
	/* WorksheetOptions */
S
SheetJS 已提交
14135 14136
	o.push(write_ws_xlml_wsopts(ws, opts, idx, wb));

S
SheetJS 已提交
14137 14138 14139 14140 14141 14142 14143 14144 14145 14146 14147 14148 14149 14150 14151 14152 14153 14154
	return o.join("");
}
function write_xlml(wb, opts)/*:string*/ {
	var d = [];
	d.push(write_props_xlml(wb, opts));
	d.push(write_wb_xlml(wb, opts));
	d.push(write_sty_xlml(wb, opts));
	for(var i = 0; i < wb.SheetNames.length; ++i)
		d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])}));
	return XML_HEADER + writextag("Workbook", d.join(""), {
		'xmlns':      XLMLNS.ss,
		'xmlns:o':    XLMLNS.o,
		'xmlns:x':    XLMLNS.x,
		'xmlns:ss':   XLMLNS.ss,
		'xmlns:dt':   XLMLNS.dt,
		'xmlns:html': XLMLNS.html
	});
}
S
SheetJS 已提交
14155 14156 14157 14158 14159 14160 14161 14162 14163 14164 14165 14166 14167 14168 14169 14170 14171 14172 14173 14174 14175 14176 14177 14178
/* [MS-OLEDS] 2.3.8 CompObjStream */
function parse_compobj(obj) {
	var v = {};
	var o = obj.content;

	/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
	var l = 28, m;
	m = __lpstr(o, l);
	l += 4 + __readUInt32LE(o,l);
	v.UserType = m;

	/* [MS-OLEDS] 2.3.1 ClipboardFormatOrAnsiString */
	m = __readUInt32LE(o,l); l+= 4;
	switch(m) {
		case 0x00000000: break;
		case 0xffffffff: case 0xfffffffe: l+=4; break;
		default:
			if(m > 0x190) throw new Error("Unsupported Clipboard: " + m.toString(16));
			l += m;
	}

	m = __lpstr(o, l); l += m.length === 0 ? 0 : 5 + m.length; v.Reserved1 = m;

	if((m = __readUInt32LE(o,l)) !== 0x71b2e9f4) return v;
S
SheetJS 已提交
14179
	throw new Error("Unsupported Unicode Extension");
S
SheetJS 已提交
14180 14181
}

S
SheetJS 已提交
14182 14183 14184 14185 14186 14187 14188 14189
/*
	Continue logic for:
	- 2.4.58 Continue
	- 2.4.59 ContinueBigName
	- 2.4.60 ContinueFrt
	- 2.4.61 ContinueFrt11
	- 2.4.62 ContinueFrt12
*/
S
SheetJS 已提交
14190
function slurp(R, blob, length/*:number*/, opts) {
S
SheetJS 已提交
14191 14192 14193 14194 14195 14196 14197 14198 14199 14200 14201 14202
	var l = length;
	var bufs = [];
	var d = blob.slice(blob.l,blob.l+l);
	if(opts && opts.enc && opts.enc.insitu_decrypt) switch(R.n) {
	case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': break;
	default:
		if(d.length === 0) break;
		opts.enc.insitu_decrypt(d);
	}
	bufs.push(d);
	blob.l += l;
	var next = (XLSRecordEnum[__readUInt16LE(blob,blob.l)]);
S
SheetJS 已提交
14203 14204
	var start = 0;
	while(next != null && next.n.slice(0,8) === 'Continue') {
S
SheetJS 已提交
14205
		l = __readUInt16LE(blob,blob.l+2);
S
SheetJS 已提交
14206 14207 14208 14209
		start = blob.l + 4;
		if(next.n == 'ContinueFrt') start += 4;
		else if(next.n.slice(0,11) == 'ContinueFrt') start += 12;
		bufs.push(blob.slice(start,blob.l+4+l));
S
SheetJS 已提交
14210 14211 14212
		blob.l += 4+l;
		next = (XLSRecordEnum[__readUInt16LE(blob, blob.l)]);
	}
S
SheetJS 已提交
14213
	var b = (bconcat(bufs)/*:any*/);
S
SheetJS 已提交
14214 14215 14216 14217 14218 14219
	prep_blob(b, 0);
	var ll = 0; b.lens = [];
	for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; }
	return R.f(b, b.length, opts);
}

S
SheetJS 已提交
14220
function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
S
SheetJS 已提交
14221
	if(p.t === 'z') return;
S
SheetJS 已提交
14222
	if(!p.XF) return;
S
SheetJS 已提交
14223
	var fmtid = 0;
S
SheetJS 已提交
14224
	try {
S
SheetJS 已提交
14225
		fmtid = p.z || p.XF.numFmtId || 0;
S
SheetJS 已提交
14226
		if(opts.cellNF) p.z = SSF._table[fmtid];
S
SheetJS 已提交
14227 14228 14229
	} catch(e) { if(opts.WTF) throw e; }
	if(!opts || opts.cellText !== false) try {
		if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
S
SheetJS 已提交
14230
		else if(fmtid === 0 || fmtid == "General") {
S
SheetJS 已提交
14231 14232 14233 14234 14235 14236
			if(p.t === 'n') {
				if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
				else p.w = SSF._general_num(p.v);
			}
			else p.w = SSF._general(p.v);
		}
S
SheetJS 已提交
14237
		else p.w = SSF.format(fmtid,p.v, {date1904:!!date1904});
S
SheetJS 已提交
14238
		if(opts.cellDates && fmtid && p.t == 'n' && SSF.is_date(SSF._table[fmtid] || String(fmtid))) {
S
SheetJS 已提交
14239
			var _d = SSF.parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
S
SheetJS 已提交
14240
		}
S
SheetJS 已提交
14241 14242 14243
	} catch(e) { if(opts.WTF) throw e; }
}

S
SheetJS 已提交
14244
function make_cell(val, ixfe, t)/*:Cell*/ {
S
SheetJS 已提交
14245
	return ({v:val, ixfe:ixfe, t:t}/*:any*/);
S
SheetJS 已提交
14246 14247 14248
}

// 2.3.2
S
SheetJS 已提交
14249 14250
function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
	var wb = ({opts:{}}/*:any*/);
S
SheetJS 已提交
14251
	var Sheets = {};
14252
	if(DENSE != null && options.dense == null) options.dense = DENSE;
S
SheetJS 已提交
14253
	var out/*:Worksheet*/ = ((options.dense ? [] : {})/*:any*/);
S
SheetJS 已提交
14254 14255
	var Directory = {};
	var found_sheet = false;
S
SheetJS 已提交
14256
	var range/*:Range*/ = ({}/*:any*/);
S
SheetJS 已提交
14257 14258 14259 14260
	var last_formula = null;
	var sst = [];
	var cur_sheet = "";
	var Preamble = {};
S
SheetJS 已提交
14261
	var lastcell, last_cell = "", cc, cmnt, rng, rngC, rngR;
S
SheetJS 已提交
14262 14263
	var shared_formulae = {};
	var array_formulae = []; /* TODO: something more clever */
S
SheetJS 已提交
14264
	var temp_val/*:Cell*/;
S
SheetJS 已提交
14265 14266 14267 14268
	var country;
	var cell_valid = true;
	var XFs = []; /* XF records */
	var palette = [];
S
SheetJS 已提交
14269
	var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false} }/*:any*/), wsprops = {};
S
SheetJS 已提交
14270 14271 14272 14273 14274
	var get_rgb = function getrgb(icv) {
		if(icv < 8) return XLSIcv[icv];
		if(icv < 64) return palette[icv-8] || XLSIcv[icv];
		return XLSIcv[icv];
	};
S
SheetJS 已提交
14275
	var process_cell_style = function pcs(cell, line/*:any*/, options) {
S
SheetJS 已提交
14276
		var xfd = line.XF.data;
S
SheetJS 已提交
14277
		if(!xfd || !xfd.patternType || !options || !options.cellStyles) return;
S
SheetJS 已提交
14278
		line.s = ({}/*:any*/);
S
SheetJS 已提交
14279 14280 14281 14282 14283
		line.s.patternType = xfd.patternType;
		var t;
		if((t = rgb2Hex(get_rgb(xfd.icvFore)))) { line.s.fgColor = {rgb:t}; }
		if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; }
	};
S
SheetJS 已提交
14284
	var addcell = function addcell(cell/*:any*/, line/*:any*/, options/*:any*/) {
S
SheetJS 已提交
14285
		if(file_depth > 1) return;
S
SheetJS 已提交
14286
		if(!cell_valid) return;
S
SheetJS 已提交
14287
		if(options.cellStyles && line.XF && line.XF.data) process_cell_style(cell, line, options);
S
SheetJS 已提交
14288 14289 14290 14291 14292 14293 14294 14295 14296 14297
		lastcell = cell;
		last_cell = encode_cell(cell);
		if(range.s) {
			if(cell.r < range.s.r) range.s.r = cell.r;
			if(cell.c < range.s.c) range.s.c = cell.c;
		}
		if(range.e) {
			if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1;
			if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1;
		}
S
SheetJS 已提交
14298 14299 14300 14301 14302 14303 14304 14305 14306 14307 14308 14309 14310
		if(options.cellFormula && line.f) {
			for(var afi = 0; afi < array_formulae.length; ++afi) {
				if(array_formulae[afi][0].s.c > cell.c) continue;
				if(array_formulae[afi][0].s.r > cell.r) continue;
				if(array_formulae[afi][0].e.c < cell.c) continue;
				if(array_formulae[afi][0].e.r < cell.r) continue;
				line.F = encode_range(array_formulae[afi][0]);
				if(array_formulae[afi][0].s.c != cell.c) delete line.f;
				if(array_formulae[afi][0].s.r != cell.r) delete line.f;
				if(line.f) line.f = "" + stringify_formula(array_formulae[afi][1], range, cell, supbooks, opts);
				break;
			}
		}
S
SheetJS 已提交
14311
		if(options.sheetRows && lastcell.r >= options.sheetRows) cell_valid = false;
S
SheetJS 已提交
14312 14313 14314 14315 14316 14317
		else {
			if(options.dense) {
				if(!out[cell.r]) out[cell.r] = [];
				out[cell.r][cell.c] = line;
			} else out[last_cell] = line;
		}
S
SheetJS 已提交
14318
	};
S
SheetJS 已提交
14319
	var opts = ({
S
SheetJS 已提交
14320 14321 14322 14323 14324 14325 14326 14327 14328 14329
		enc: false, // encrypted
		sbcch: 0, // cch in the preceding SupBook
		snames: [], // sheetnames
		sharedf: shared_formulae, // shared formulae by address
		arrayf: array_formulae, // array formulae array
		rrtabid: [], // RRTabId
		lastuser: "", // Last User from WriteAccess
		biff: 8, // BIFF version
		codepage: 0, // CP from CodePage record
		winlocked: 0, // fLockWn from WinProtect
S
SheetJS 已提交
14330
		cellStyles: !!options && !!options.cellStyles,
S
SheetJS 已提交
14331
		WTF: !!options && !!options.wtf
S
SheetJS 已提交
14332
	}/*:any*/);
S
SheetJS 已提交
14333 14334 14335
	if(options.password) opts.password = options.password;
	var mergecells = [];
	var objects = [];
S
SheetJS 已提交
14336 14337 14338
	var colinfo = [], rowinfo = [];
	var defwidth = 0, defheight = 0; // twips / MDW respectively
	var seencol = false;
S
SheetJS 已提交
14339
	var supbooks = ([]/*:any*/); // 1-indexed, will hold extern names
S
SheetJS 已提交
14340 14341 14342
	supbooks.SheetNames = opts.snames;
	supbooks.sharedf = opts.sharedf;
	supbooks.arrayf = opts.arrayf;
S
SheetJS 已提交
14343 14344
	supbooks.names = [];
	supbooks.XTI = [];
S
SheetJS 已提交
14345 14346
	var last_Rn = '';
	var file_depth = 0; /* TODO: make a real stack */
S
SheetJS 已提交
14347
	var BIFF2Fmt = 0;
S
SheetJS 已提交
14348
	var BIFF2FmtTable/*:Array<string>*/ = [];
S
SheetJS 已提交
14349
	var FilterDatabases = []; /* TODO: sort out supbooks and process elsewhere */
S
SheetJS 已提交
14350
	var last_lbl/*:?DefinedName*/;
S
SheetJS 已提交
14351 14352 14353 14354 14355 14356 14357 14358 14359 14360

	/* explicit override for some broken writers */
	opts.codepage = 1200;
	set_cp(1200);
	while(blob.l < blob.length - 1) {
		var s = blob.l;
		var RecordType = blob.read_shift(2);
		if(RecordType === 0 && last_Rn === 'EOF') break;
		var length = (blob.l === blob.length ? 0 : blob.read_shift(2)), y;
		var R = XLSRecordEnum[RecordType];
S
SheetJS 已提交
14361
		//console.log(RecordType.toString(16), RecordType, R, blob.l, length, blob.length);
S
SheetJS 已提交
14362
		//if(!R) console.log(blob.slice(blob.l, blob.l + length));
S
SheetJS 已提交
14363 14364 14365 14366 14367 14368 14369
		if(R && R.f) {
			if(options.bookSheets) {
				if(last_Rn === 'BoundSheet8' && R.n !== 'BoundSheet8') break;
			}
			last_Rn = R.n;
			if(R.r === 2 || R.r == 12) {
				var rt = blob.read_shift(2); length -= 2;
S
SheetJS 已提交
14370
				if(!opts.enc && rt !== RecordType) throw new Error("rt mismatch: " + rt + "!=" + RecordType);
S
SheetJS 已提交
14371 14372 14373 14374 14375 14376 14377 14378 14379 14380
				if(R.r == 12){ blob.l += 10; length -= 10; } // skip FRT
			}
			//console.error(R,blob.l,length,blob.length);
			var val;
			if(R.n === 'EOF') val = R.f(blob, length, opts);
			else val = slurp(R, blob, length, opts);
			var Rn = R.n;
			/* nested switch statements to workaround V8 128 limit */
			switch(Rn) {
				/* Workbook Options */
S
SheetJS 已提交
14381 14382 14383
				case 'Date1904':
					/*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
					wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
S
SheetJS 已提交
14384 14385 14386 14387 14388 14389
				case 'WriteProtect': wb.opts.WriteProtect = true; break;
				case 'FilePass':
					if(!opts.enc) blob.l = 0;
					opts.enc = val;
					if(opts.WTF) console.error(val);
					if(!options.password) throw new Error("File is password-protected");
S
SheetJS 已提交
14390
					if(val.valid == null) throw new Error("Encryption scheme unsupported");
S
SheetJS 已提交
14391 14392 14393 14394 14395 14396 14397 14398 14399 14400 14401 14402 14403 14404 14405 14406
					if(!val.valid) throw new Error("Password is incorrect");
					break;
				case 'WriteAccess': opts.lastuser = val; break;
				case 'FileSharing': break; //TODO
				case 'CodePage':
					/* overrides based on test cases */
					if(val === 0x5212) val = 1200;
					else if(val === 0x8001) val = 1252;
					opts.codepage = val;
					set_cp(val);
					break;
				case 'RRTabId': opts.rrtabid = val; break;
				case 'WinProtect': opts.winlocked = val; break;
				case 'Template': break; // TODO
				case 'RefreshAll': wb.opts.RefreshAll = val; break;
				case 'BookBool': break; // TODO
S
SheetJS 已提交
14407
				case 'UsesELFs': break;
S
SheetJS 已提交
14408
				case 'MTRSettings': break;
S
SheetJS 已提交
14409 14410 14411 14412 14413 14414 14415 14416 14417 14418 14419 14420 14421 14422 14423 14424
				case 'CalcCount': wb.opts.CalcCount = val; break;
				case 'CalcDelta': wb.opts.CalcDelta = val; break;
				case 'CalcIter': wb.opts.CalcIter = val; break;
				case 'CalcMode': wb.opts.CalcMode = val; break;
				case 'CalcPrecision': wb.opts.CalcPrecision = val; break;
				case 'CalcSaveRecalc': wb.opts.CalcSaveRecalc = val; break;
				case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
				case 'Uncalced': break;
				case 'ForceFullCalculation': wb.opts.FullCalc = val; break;
				case 'WsBool': break; // TODO
				case 'XF': XFs.push(val); break;
				case 'ExtSST': break; // TODO
				case 'BookExt': break; // TODO
				case 'RichTextStream': break;
				case 'BkHim': break;

S
SheetJS 已提交
14425 14426 14427 14428 14429 14430 14431
				case 'SupBook':
					supbooks.push([val]);
					supbooks[supbooks.length-1].XTI = [];
					break;
				case 'ExternName':
					supbooks[supbooks.length-1].push(val);
					break;
S
SheetJS 已提交
14432
				case 'Index': break; // TODO
S
SheetJS 已提交
14433
				case 'Lbl':
S
SheetJS 已提交
14434
					last_lbl = ({
S
SheetJS 已提交
14435 14436
						Name: val.Name,
						Ref: stringify_formula(val.rgce,range,null,supbooks,opts)
S
SheetJS 已提交
14437
					}/*:DefinedName*/);
S
SheetJS 已提交
14438 14439 14440 14441
					if(val.itab > 0) last_lbl.Sheet = val.itab - 1;
					supbooks.names.push(last_lbl);
					if(!supbooks[0]) supbooks[0] = [];
					supbooks[supbooks.length-1].push(val);
S
SheetJS 已提交
14442
					if(val.Name == "_xlnm._FilterDatabase" && val.itab > 0)
S
SheetJS 已提交
14443 14444 14445
						if(val.rgce && val.rgce[0] && val.rgce[0][0] && val.rgce[0][0][0] == 'PtgArea3d')
							FilterDatabases[val.itab - 1] = { ref: encode_range(val.rgce[0][0][1][2]) };
					break;
S
SheetJS 已提交
14446
				case 'ExternCount': opts.ExternCount = val; break;
S
SheetJS 已提交
14447 14448 14449 14450 14451 14452
				case 'ExternSheet':
					if(supbooks.length == 0) { supbooks[0] = []; supbooks[0].XTI = []; }
					supbooks[supbooks.length - 1].XTI = supbooks[supbooks.length - 1].XTI.concat(val); supbooks.XTI = supbooks.XTI.concat(val); break;
				case 'NameCmt':
					/* TODO: search for correct name */
					if(opts.biff < 8) break;
S
SheetJS 已提交
14453
					if(last_lbl != null) last_lbl.Comment = val[1];
S
SheetJS 已提交
14454
					break;
S
SheetJS 已提交
14455 14456 14457 14458 14459 14460 14461 14462 14463 14464 14465 14466 14467 14468 14469 14470 14471 14472 14473

				case 'Protect': out["!protect"] = val; break; /* for sheet or book */
				case 'Password': if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
				case 'Prot4Rev': case 'Prot4RevPass': break; /*TODO: Revision Control*/

				case 'BoundSheet8': {
					Directory[val.pos] = val;
					opts.snames.push(val.name);
				} break;
				case 'EOF': {
					if(--file_depth) break;
					if(range.e) {
						if(range.e.r > 0 && range.e.c > 0) {
							range.e.r--; range.e.c--;
							out["!ref"] = encode_range(range);
							range.e.r++; range.e.c++;
						}
						if(mergecells.length > 0) out["!merges"] = mergecells;
						if(objects.length > 0) out["!objects"] = objects;
S
SheetJS 已提交
14474 14475
						if(colinfo.length > 0) out["!cols"] = colinfo;
						if(rowinfo.length > 0) out["!rows"] = rowinfo;
S
SheetJS 已提交
14476
						Workbook.Sheets.push(wsprops);
S
SheetJS 已提交
14477 14478
					}
					if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out;
S
SheetJS 已提交
14479
					out = ((options.dense ? [] : {})/*:any*/);
S
SheetJS 已提交
14480 14481
				} break;
				case 'BOF': {
S
SheetJS 已提交
14482
					if(opts.biff !== 8){/* empty */}
S
SheetJS 已提交
14483 14484 14485
					else if(RecordType  === 0x0009) opts.biff = 2;
					else if(RecordType  === 0x0209) opts.biff = 3;
					else if(RecordType  === 0x0409) opts.biff = 4;
S
SheetJS 已提交
14486 14487 14488 14489
					else if(val.BIFFVer === 0x0500) opts.biff = 5;
					else if(val.BIFFVer === 0x0600) opts.biff = 8;
					else if(val.BIFFVer === 0x0002) opts.biff = 2;
					else if(val.BIFFVer === 0x0007) opts.biff = 2;
S
SheetJS 已提交
14490 14491
					if(file_depth++) break;
					cell_valid = true;
S
SheetJS 已提交
14492
					out = ((options.dense ? [] : {})/*:any*/);
S
SheetJS 已提交
14493

S
SheetJS 已提交
14494
					if(opts.biff < 5) {
S
SheetJS 已提交
14495 14496
						if(cur_sheet === "") cur_sheet = "Sheet1";
						range = {s:{r:0,c:0},e:{r:0,c:0}};
S
SheetJS 已提交
14497 14498 14499 14500
						/* fake BoundSheet8 */
						var fakebs8 = {pos: blob.l - length, name:cur_sheet};
						Directory[fakebs8.pos] = fakebs8;
						opts.snames.push(cur_sheet);
S
SheetJS 已提交
14501 14502
					}
					else cur_sheet = (Directory[s] || {name:""}).name;
14503
					if(val.dt == 0x20) out["!type"] = "chart";
S
SheetJS 已提交
14504 14505
					mergecells = [];
					objects = [];
S
SheetJS 已提交
14506
					array_formulae = []; opts.arrayf = array_formulae;
S
SheetJS 已提交
14507 14508 14509
					colinfo = []; rowinfo = [];
					defwidth = defheight = 0;
					seencol = false;
S
SheetJS 已提交
14510
					wsprops = {Hidden:(Directory[s]||{hs:0}).hs, name:cur_sheet };
S
SheetJS 已提交
14511
				} break;
S
SheetJS 已提交
14512

S
SheetJS 已提交
14513
				case 'Number': case 'BIFF2NUM': case 'BIFF2INT': {
S
SheetJS 已提交
14514
					if(out["!type"] == "chart") if(options.dense ? (out[val.r]||[])[val.c]: out[encode_cell({c:val.c, r:val.r})]) ++val.c;
S
SheetJS 已提交
14515
					temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe]||{}, v:val.val, t:'n'}/*:any*/);
S
SheetJS 已提交
14516
					if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
S
SheetJS 已提交
14517
					safe_format_xf(temp_val, options, wb.opts.Date1904);
S
SheetJS 已提交
14518 14519 14520
					addcell({c:val.c, r:val.r}, temp_val, options);
				} break;
				case 'BoolErr': {
S
SheetJS 已提交
14521
					temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t}/*:any*/);
S
SheetJS 已提交
14522
					if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
S
SheetJS 已提交
14523
					safe_format_xf(temp_val, options, wb.opts.Date1904);
S
SheetJS 已提交
14524 14525 14526
					addcell({c:val.c, r:val.r}, temp_val, options);
				} break;
				case 'RK': {
S
SheetJS 已提交
14527
					temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'}/*:any*/);
S
SheetJS 已提交
14528
					if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
S
SheetJS 已提交
14529
					safe_format_xf(temp_val, options, wb.opts.Date1904);
S
SheetJS 已提交
14530 14531 14532 14533 14534
					addcell({c:val.c, r:val.r}, temp_val, options);
				} break;
				case 'MulRk': {
					for(var j = val.c; j <= val.C; ++j) {
						var ixfe = val.rkrec[j-val.c][0];
S
SheetJS 已提交
14535
						temp_val= ({ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'}/*:any*/);
S
SheetJS 已提交
14536
						if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
S
SheetJS 已提交
14537
						safe_format_xf(temp_val, options, wb.opts.Date1904);
S
SheetJS 已提交
14538 14539 14540 14541
						addcell({c:j, r:val.r}, temp_val, options);
					}
				} break;
				case 'Formula': {
S
SheetJS 已提交
14542
					if(val.val == 'String') { last_formula = val; break; }
S
SheetJS 已提交
14543
					temp_val = make_cell(val.val, val.cell.ixfe, val.tt);
S
SheetJS 已提交
14544 14545 14546 14547 14548 14549 14550
					temp_val.XF = XFs[temp_val.ixfe];
					if(options.cellFormula) {
						var _f = val.formula;
						if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
							var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
							var _fe = encode_cell({r:_fr, c:_fc});
							if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
S
SheetJS 已提交
14551
							else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F;
S
SheetJS 已提交
14552
						} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
S
SheetJS 已提交
14553
					}
S
SheetJS 已提交
14554
					if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
S
SheetJS 已提交
14555 14556 14557
					safe_format_xf(temp_val, options, wb.opts.Date1904);
					addcell(val.cell, temp_val, options);
					last_formula = val;
S
SheetJS 已提交
14558 14559
				} break;
				case 'String': {
S
SheetJS 已提交
14560
					if(last_formula) { /* technically always true */
S
SheetJS 已提交
14561
						last_formula.val = val;
S
SheetJS 已提交
14562
						temp_val = make_cell(val, last_formula.cell.ixfe, 's');
S
SheetJS 已提交
14563
						temp_val.XF = XFs[temp_val.ixfe];
S
SheetJS 已提交
14564 14565 14566
						if(options.cellFormula) {
							temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
						}
S
SheetJS 已提交
14567
						if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
S
SheetJS 已提交
14568
						safe_format_xf(temp_val, options, wb.opts.Date1904);
S
SheetJS 已提交
14569 14570
						addcell(last_formula.cell, temp_val, options);
						last_formula = null;
S
SheetJS 已提交
14571
					} else throw new Error("String record expects Formula");
S
SheetJS 已提交
14572 14573 14574
				} break;
				case 'Array': {
					array_formulae.push(val);
S
SheetJS 已提交
14575
					var _arraystart = encode_cell(val[0].s);
S
SheetJS 已提交
14576 14577
					cc = options.dense ? (out[val[0].s.r]||[])[val[0].s.c] : out[_arraystart];
					if(options.cellFormula && cc) {
S
SheetJS 已提交
14578
						if(!last_formula) break; /* technically unreachable */
S
SheetJS 已提交
14579 14580 14581
						if(!_arraystart || !cc) break;
						cc.f = ""+stringify_formula(val[1], range, val[0], supbooks, opts);
						cc.F = encode_range(val[0]);
S
SheetJS 已提交
14582
					}
S
SheetJS 已提交
14583 14584 14585
				} break;
				case 'ShrFmla': {
					if(!cell_valid) break;
S
SheetJS 已提交
14586 14587 14588
					if(!options.cellFormula) break;
					if(last_cell) {
						/* TODO: capture range */
S
SheetJS 已提交
14589
						if(!last_formula) break; /* technically unreachable */
S
SheetJS 已提交
14590
						shared_formulae[encode_cell(last_formula.cell)]= val[0];
S
SheetJS 已提交
14591 14592
						cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
						(cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
S
SheetJS 已提交
14593
					}
S
SheetJS 已提交
14594 14595 14596 14597
				} break;
				case 'LabelSst':
					temp_val=make_cell(sst[val.isst].t, val.ixfe, 's');
					temp_val.XF = XFs[temp_val.ixfe];
S
SheetJS 已提交
14598
					if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
S
SheetJS 已提交
14599
					safe_format_xf(temp_val, options, wb.opts.Date1904);
S
SheetJS 已提交
14600 14601
					addcell({c:val.c, r:val.r}, temp_val, options);
					break;
S
SheetJS 已提交
14602
				case 'Blank': if(options.sheetStubs) {
S
SheetJS 已提交
14603
					temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'}/*:any*/);
S
SheetJS 已提交
14604
					if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
S
SheetJS 已提交
14605 14606 14607 14608 14609 14610
					safe_format_xf(temp_val, options, wb.opts.Date1904);
					addcell({c:val.c, r:val.r}, temp_val, options);
				} break;
				case 'MulBlank': if(options.sheetStubs) {
					for(var _j = val.c; _j <= val.C; ++_j) {
						var _ixfe = val.ixfe[_j-val.c];
S
SheetJS 已提交
14611
						temp_val= ({ixfe:_ixfe, XF:XFs[_ixfe], t:'z'}/*:any*/);
S
SheetJS 已提交
14612
						if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
S
SheetJS 已提交
14613 14614 14615 14616
						safe_format_xf(temp_val, options, wb.opts.Date1904);
						addcell({c:_j, r:val.r}, temp_val, options);
					}
				} break;
S
SheetJS 已提交
14617
				case 'RString':
S
SheetJS 已提交
14618 14619 14620
				case 'Label': case 'BIFF2STR':
					temp_val=make_cell(val.val, val.ixfe, 's');
					temp_val.XF = XFs[temp_val.ixfe];
S
SheetJS 已提交
14621
					if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
S
SheetJS 已提交
14622
					safe_format_xf(temp_val, options, wb.opts.Date1904);
S
SheetJS 已提交
14623 14624
					addcell({c:val.c, r:val.r}, temp_val, options);
					break;
S
SheetJS 已提交
14625

S
SheetJS 已提交
14626 14627 14628 14629 14630 14631 14632 14633 14634
				case 'Dimensions': {
					if(file_depth === 1) range = val; /* TODO: stack */
				} break;
				case 'SST': {
					sst = val;
				} break;
				case 'Format': { /* val = [id, fmt] */
					SSF.load(val[1], val[0]);
				} break;
S
SheetJS 已提交
14635
				case 'BIFF2FORMAT': {
S
SheetJS 已提交
14636 14637 14638
					BIFF2FmtTable[BIFF2Fmt++] = val;
					for(var b2idx = 0; b2idx < BIFF2Fmt + 163; ++b2idx) if(SSF._table[b2idx] == val) break;
					if(b2idx >= 163) SSF.load(val, BIFF2Fmt + 163);
S
SheetJS 已提交
14639
				} break;
S
SheetJS 已提交
14640 14641 14642 14643 14644

				case 'MergeCells': mergecells = mergecells.concat(val); break;

				case 'Obj': objects[val.cmo[0]] = opts.lastobj = val; break;
				case 'TxO': opts.lastobj.TxO = val; break;
S
SheetJS 已提交
14645
				case 'ImData': opts.lastobj.ImData = val; break;
S
SheetJS 已提交
14646 14647 14648

				case 'HLink': {
					for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
S
SheetJS 已提交
14649 14650 14651
						for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
							cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
							if(cc) cc.l = val[1];
S
SheetJS 已提交
14652
						}
S
SheetJS 已提交
14653 14654 14655
				} break;
				case 'HLinkTooltip': {
					for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
S
SheetJS 已提交
14656 14657 14658 14659
						for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
							cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
							if(cc) cc.l.Tooltip = val[1];
							}
S
SheetJS 已提交
14660 14661 14662 14663 14664
				} break;

				/* Comments */
				case 'Note': {
					if(opts.biff <= 5 && opts.biff >= 2) break; /* TODO: BIFF5 */
S
SheetJS 已提交
14665
					cc = options.dense ? (out[val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
S
SheetJS 已提交
14666 14667 14668 14669 14670 14671 14672 14673 14674 14675 14676
					var noteobj = objects[val[2]];
					if(!cc) break;
					if(!cc.c) cc.c = [];
					cmnt = {a:val[1],t:noteobj.TxO.t};
					cc.c.push(cmnt);
				} break;

				default: switch(R.n) { /* nested */
				case 'ClrtClient': break;
				case 'XFExt': update_xfext(XFs[val.ixfe], val.ext); break;

S
SheetJS 已提交
14677 14678 14679 14680 14681 14682 14683 14684 14685 14686 14687
				case 'DefColWidth': defwidth = val; break;
				case 'DefaultRowHeight': defheight = val[1]; break; // TODO: flags

				case 'ColInfo': {
					if(!opts.cellStyles) break;
					while(val.e >= val.s) {
						colinfo[val.e--] = { width: val.w/256 };
						if(!seencol) { seencol = true; find_mdw_colw(val.w/256); }
						process_col(colinfo[val.e+1]);
					}
				} break;
S
SheetJS 已提交
14688 14689
				case 'Row': {
					var rowobj = {};
14690
					if(val.level != null) { rowinfo[val.r] = rowobj; rowobj.level = val.level; }
S
SheetJS 已提交
14691 14692 14693 14694 14695 14696
					if(val.hidden) { rowinfo[val.r] = rowobj; rowobj.hidden = true; }
					if(val.hpt) {
						rowinfo[val.r] = rowobj;
						rowobj.hpt = val.hpt; rowobj.hpx = pt2px(val.hpt);
					}
				} break;
S
SheetJS 已提交
14697

S
SheetJS 已提交
14698 14699 14700 14701 14702
				case 'LeftMargin':
				case 'RightMargin':
				case 'TopMargin':
				case 'BottomMargin':
					if(!out['!margins']) default_margins(out['!margins'] = {});
S
SheetJS 已提交
14703
					out['!margins'][Rn.slice(0,-6).toLowerCase()] = val;
S
SheetJS 已提交
14704 14705 14706 14707 14708 14709 14710 14711
					break;

				case 'Setup': // TODO
					if(!out['!margins']) default_margins(out['!margins'] = {});
					out['!margins'].header = val.header;
					out['!margins'].footer = val.footer;
					break;

S
SheetJS 已提交
14712 14713 14714 14715 14716 14717 14718 14719 14720 14721 14722 14723 14724 14725
				case 'Header': break; // TODO
				case 'Footer': break; // TODO
				case 'HCenter': break; // TODO
				case 'VCenter': break; // TODO
				case 'Pls': break; // TODO
				case 'GCW': break;
				case 'LHRecord': break;
				case 'DBCell': break; // TODO
				case 'EntExU2': break; // TODO
				case 'SxView': break; // TODO
				case 'Sxvd': break; // TODO
				case 'SXVI': break; // TODO
				case 'SXVDEx': break; // TODO
				case 'SxIvd': break; // TODO
S
SheetJS 已提交
14726 14727 14728
				case 'SXString': break; // TODO
				case 'Sync': break;
				case 'Addin': break;
S
SheetJS 已提交
14729 14730 14731 14732 14733 14734 14735 14736 14737 14738
				case 'SXDI': break; // TODO
				case 'SXLI': break; // TODO
				case 'SXEx': break; // TODO
				case 'QsiSXTag': break; // TODO
				case 'Selection': break;
				case 'Feat': break;
				case 'FeatHdr': case 'FeatHdr11': break;
				case 'Feature11': case 'Feature12': case 'List12': break;
				case 'Country': country = val; break;
				case 'RecalcId': break;
S
SheetJS 已提交
14739
				case 'DxGCol': break; // TODO: htmlify
S
SheetJS 已提交
14740 14741 14742 14743 14744 14745 14746 14747 14748 14749 14750 14751 14752 14753 14754 14755 14756 14757 14758 14759 14760 14761 14762 14763 14764 14765 14766 14767 14768 14769 14770 14771 14772 14773 14774 14775 14776 14777 14778 14779 14780 14781 14782 14783 14784 14785 14786 14787 14788 14789 14790 14791 14792 14793 14794 14795
				case 'Fbi': case 'Fbi2': case 'GelFrame': break;
				case 'Font': break; // TODO
				case 'XFCRC': break; // TODO
				case 'Style': break; // TODO
				case 'StyleExt': break; // TODO
				case 'Palette': palette = val; break; // TODO
				case 'Theme': break; // TODO
				/* Protection */
				case 'ScenarioProtect': break;
				case 'ObjProtect': break;

				/* Conditional Formatting */
				case 'CondFmt12': break;

				/* Table */
				case 'Table': break; // TODO
				case 'TableStyles': break; // TODO
				case 'TableStyle': break; // TODO
				case 'TableStyleElement': break; // TODO

				/* PivotTable */
				case 'SXStreamID': break; // TODO
				case 'SXVS': break; // TODO
				case 'DConRef': break; // TODO
				case 'SXAddl': break; // TODO
				case 'DConBin': break; // TODO
				case 'DConName': break; // TODO
				case 'SXPI': break; // TODO
				case 'SxFormat': break; // TODO
				case 'SxSelect': break; // TODO
				case 'SxRule': break; // TODO
				case 'SxFilt': break; // TODO
				case 'SxItm': break; // TODO
				case 'SxDXF': break; // TODO

				/* Scenario Manager */
				case 'ScenMan': break;

				/* Data Consolidation */
				case 'DCon': break;

				/* Watched Cell */
				case 'CellWatch': break;

				/* Print Settings */
				case 'PrintRowCol': break;
				case 'PrintGrid': break;
				case 'PrintSize': break;

				case 'XCT': break;
				case 'CRN': break;

				case 'Scl': {
					//console.log("Zoom Level:", val[0]/val[1],val);
				} break;
				case 'SheetExt': {
S
SheetJS 已提交
14796
					/* empty */
S
SheetJS 已提交
14797 14798
				} break;
				case 'SheetExtOptional': {
S
SheetJS 已提交
14799
					/* empty */
S
SheetJS 已提交
14800 14801 14802 14803
				} break;

				/* VBA */
				case 'ObNoMacros': {
S
SheetJS 已提交
14804
					/* empty */
S
SheetJS 已提交
14805 14806
				} break;
				case 'ObProj': {
S
SheetJS 已提交
14807
					/* empty */
S
SheetJS 已提交
14808 14809
				} break;
				case 'CodeName': {
S
SheetJS 已提交
14810
					/* empty */
S
SheetJS 已提交
14811 14812
				} break;
				case 'GUIDTypeLib': {
S
SheetJS 已提交
14813
					/* empty */
S
SheetJS 已提交
14814 14815 14816 14817 14818 14819 14820 14821 14822 14823 14824 14825 14826 14827 14828 14829 14830 14831 14832 14833 14834
				} break;

				case 'WOpt': break; // TODO: WTF?
				case 'PhoneticInfo': break;

				case 'OleObjectSize': break;

				/* Differential Formatting */
				case 'DXF': case 'DXFN': case 'DXFN12': case 'DXFN12List': case 'DXFN12NoCB': break;

				/* Data Validation */
				case 'Dv': case 'DVal': break;

				/* Data Series */
				case 'BRAI': case 'Series': case 'SeriesText': break;

				/* Data Connection */
				case 'DConn': break;
				case 'DbOrParamQry': break;
				case 'DBQueryExt': break;

S
SheetJS 已提交
14835 14836 14837
				case 'OleDbConn': break;
				case 'ExtString': break;

S
SheetJS 已提交
14838 14839 14840 14841 14842 14843 14844
				/* Formatting */
				case 'IFmtRecord': break;
				case 'CondFmt': case 'CF': case 'CF12': case 'CFEx': break;

				/* Explicitly Ignored */
				case 'Excel9File': break;
				case 'Units': break;
S
SheetJS 已提交
14845
				case 'InterfaceHdr': case 'Mms': case 'InterfaceEnd': case 'DSF': case 'BuiltInFnGroupCount': break;
S
SheetJS 已提交
14846 14847 14848 14849 14850 14851 14852 14853 14854 14855 14856 14857 14858 14859 14860 14861 14862 14863 14864 14865 14866 14867 14868 14869 14870 14871 14872 14873 14874 14875 14876 14877 14878 14879 14880 14881 14882 14883 14884 14885 14886 14887 14888 14889 14890 14891 14892 14893 14894 14895 14896 14897 14898 14899 14900 14901 14902 14903 14904 14905 14906 14907 14908 14909 14910 14911 14912
				/* View Stuff */
				case 'Window1': case 'Window2': case 'HideObj': case 'GridSet': case 'Guts':
				case 'UserBView': case 'UserSViewBegin': case 'UserSViewEnd':
				case 'Pane': break;
				default: switch(R.n) { /* nested */
				/* Chart */
				case 'Dat':
				case 'Begin': case 'End':
				case 'StartBlock': case 'EndBlock':
				case 'Frame': case 'Area':
				case 'Axis': case 'AxisLine': case 'Tick': break;
				case 'AxesUsed':
				case 'CrtLayout12': case 'CrtLayout12A': case 'CrtLink': case 'CrtLine': case 'CrtMlFrt': case 'CrtMlFrtContinue': break;
				case 'LineFormat': case 'AreaFormat':
				case 'Chart': case 'Chart3d': case 'Chart3DBarShape': case 'ChartFormat': case 'ChartFrtInfo': break;
				case 'PlotArea': case 'PlotGrowth': break;
				case 'SeriesList': case 'SerParent': case 'SerAuxTrend': break;
				case 'DataFormat': case 'SerToCrt': case 'FontX': break;
				case 'CatSerRange': case 'AxcExt': case 'SerFmt': break;
				case 'ShtProps': break;
				case 'DefaultText': case 'Text': case 'CatLab': break;
				case 'DataLabExtContents': break;
				case 'Legend': case 'LegendException': break;
				case 'Pie': case 'Scatter': break;
				case 'PieFormat': case 'MarkerFormat': break;
				case 'StartObject': case 'EndObject': break;
				case 'AlRuns': case 'ObjectLink': break;
				case 'SIIndex': break;
				case 'AttachedLabel': case 'YMult': break;

				/* Chart Group */
				case 'Line': case 'Bar': break;
				case 'Surf': break;

				/* Axis Group */
				case 'AxisParent': break;
				case 'Pos': break;
				case 'ValueRange': break;

				/* Pivot Chart */
				case 'SXViewEx9': break; // TODO
				case 'SXViewLink': break;
				case 'PivotChartBits': break;
				case 'SBaseRef': break;
				case 'TextPropsStream': break;

				/* Chart Misc */
				case 'LnExt': break;
				case 'MkrExt': break;
				case 'CrtCoopt': break;

				/* Query Table */
				case 'Qsi': case 'Qsif': case 'Qsir': case 'QsiSXTag': break;
				case 'TxtQry': break;

				/* Filter */
				case 'FilterMode': break;
				case 'AutoFilter': case 'AutoFilterInfo': break;
				case 'AutoFilter12': break;
				case 'DropDownObjIds': break;
				case 'Sort': break;
				case 'SortData': break;

				/* Drawing */
				case 'ShapePropsStream': break;
				case 'MsoDrawing': case 'MsoDrawingGroup': case 'MsoDrawingSelection': break;
				/* Pub Stuff */
S
SheetJS 已提交
14913
				case 'WebPub': case 'AutoWebPub': break;
S
SheetJS 已提交
14914 14915 14916

				/* Print Stuff */
				case 'HeaderFooter': case 'HFPicture': case 'PLV':
S
SheetJS 已提交
14917
				case 'HorizontalPageBreaks': case 'VerticalPageBreaks': break;
S
SheetJS 已提交
14918 14919 14920 14921 14922 14923 14924 14925 14926
				/* Behavioral */
				case 'Backup': case 'CompressPictures': case 'Compat12': break;

				/* Should not Happen */
				case 'Continue': case 'ContinueFrt12': break;

				/* Future Records */
				case 'FrtFontList': case 'FrtWrapper': break;

S
SheetJS 已提交
14927
				default: switch(R.n) { /* nested */
S
SheetJS 已提交
14928 14929 14930
				/* BIFF5 records */
				case 'TabIdConf': case 'Radar': case 'RadarArea': case 'DropBar': case 'Intl': case 'CoordList': case 'SerAuxErrBar': break;

S
SheetJS 已提交
14931
				/* BIFF2-4 records */
S
SheetJS 已提交
14932
				case 'BIFF2FONTCLR': case 'BIFF2FMTCNT': case 'BIFF2FONTXTRA': break;
S
SheetJS 已提交
14933 14934 14935
				case 'BIFF2XF': case 'BIFF3XF': case 'BIFF4XF': break;
				case 'BIFF4FMTCNT': case 'BIFF2ROW': case 'BIFF2WINDOW2': break;

S
SheetJS 已提交
14936 14937 14938 14939
				/* Miscellaneous */
				case 'SCENARIO': case 'DConBin': case 'PicF': case 'DataLabExt':
				case 'Lel': case 'BopPop': case 'BopPopCustom': case 'RealTimeData':
				case 'Name': break;
S
SheetJS 已提交
14940 14941 14942 14943
				case 'LHNGraph': case 'FnGroupName': case 'AddMenu': case 'LPr': break;
				case 'ListObj': case 'ListField': break;
				case 'RRSort': break;
				case 'BigName': break;
S
SheetJS 已提交
14944 14945 14946 14947
				default: if(options.WTF) throw 'Unrecognized Record ' + R.n;
			}}}}
		} else blob.l += length;
	}
S
SheetJS 已提交
14948
	var sheetnamesraw = Object.keys(Directory).sort(function(a,b) { return Number(a) - Number(b); }).map(function(x){return Directory[x].name;});
S
SheetJS 已提交
14949 14950 14951 14952
	var sheetnames = sheetnamesraw.slice();
	wb.Directory=sheetnamesraw;
	wb.SheetNames=sheetnamesraw;
	if(!options.bookSheets) wb.Sheets=Sheets;
S
SheetJS 已提交
14953
	if(wb.Sheets) FilterDatabases.forEach(function(r,i) { wb.Sheets[wb.SheetNames[i]]['!autofilter'] = r; });
S
SheetJS 已提交
14954 14955 14956 14957 14958 14959
	wb.Preamble=Preamble;
	wb.Strings = sst;
	wb.SSF = SSF.get_table();
	if(opts.enc) wb.Encryption = opts.enc;
	wb.Metadata = {};
	if(country !== undefined) wb.Metadata.Country = country;
S
SheetJS 已提交
14960
	if(supbooks.names.length > 0) Workbook.Names = supbooks.names;
S
SheetJS 已提交
14961
	wb.Workbook = Workbook;
S
SheetJS 已提交
14962 14963 14964
	return wb;
}

S
SheetJS 已提交
14965 14966 14967
/* TODO: WTF */
function parse_props(cfb) {
	/* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
S
SheetJS 已提交
14968
	var DSI = CFB.find(cfb, '!DocumentSummaryInformation');
S
SheetJS 已提交
14969
	if(DSI) try { cfb.DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI); } catch(e) {/* empty */}
S
SheetJS 已提交
14970 14971

	/* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
S
SheetJS 已提交
14972
	var SI = CFB.find(cfb, '!SummaryInformation');
S
SheetJS 已提交
14973
	if(SI) try { cfb.Summary = parse_PropertySetStream(SI, SummaryPIDSI); } catch(e) {/* empty */}
S
SheetJS 已提交
14974 14975
}

S
SheetJS 已提交
14976
function parse_xlscfb(cfb/*:any*/, options/*:?ParseOpts*/)/*:Workbook*/ {
S
SheetJS 已提交
14977 14978 14979
if(!options) options = {};
fix_read_opts(options);
reset_cp();
S
SheetJS 已提交
14980
var CompObj, Summary, WB/*:?any*/;
S
SheetJS 已提交
14981
if(cfb.FullPaths) {
S
SheetJS 已提交
14982 14983 14984
	CompObj = CFB.find(cfb, '!CompObj');
	Summary = CFB.find(cfb, '!SummaryInformation');
	WB = CFB.find(cfb, '/Workbook');
S
SheetJS 已提交
14985 14986
} else {
	prep_blob(cfb, 0);
S
SheetJS 已提交
14987
	WB = ({content: cfb}/*:any*/);
S
SheetJS 已提交
14988 14989
}

S
SheetJS 已提交
14990
if(!WB) WB = CFB.find(cfb, '/Book');
S
SheetJS 已提交
14991
var CompObjP, SummaryP, WorkbookP/*:Workbook*/;
S
SheetJS 已提交
14992

S
SheetJS 已提交
14993
var _data/*:?any*/;
S
SheetJS 已提交
14994
if(CompObj) CompObjP = parse_compobj(CompObj);
S
SheetJS 已提交
14995
if(options.bookProps && !options.bookSheets) WorkbookP = ({}/*:any*/);
S
SheetJS 已提交
14996
else {
S
SheetJS 已提交
14997
	if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options);
S
SheetJS 已提交
14998
	/* Quattro Pro 7-8 */
S
SheetJS 已提交
14999
	else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, options);
S
SheetJS 已提交
15000
	/* Quattro Pro 9 */
S
SheetJS 已提交
15001
	else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, options);
S
SheetJS 已提交
15002 15003 15004
	else throw new Error("Cannot find Workbook stream");
}

S
SheetJS 已提交
15005
if(cfb.FullPaths) parse_props(cfb);
S
SheetJS 已提交
15006 15007 15008 15009 15010 15011

var props = {};
for(var y in cfb.Summary) props[y] = cfb.Summary[y];
for(y in cfb.DocSummary) props[y] = cfb.DocSummary[y];
WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
if(options.bookFiles) WorkbookP.cfb = cfb;
S
SheetJS 已提交
15012
/*WorkbookP.CompObjP = CompObjP; // TODO: storage? */
S
SheetJS 已提交
15013 15014 15015 15016 15017
return WorkbookP;
}

/* [MS-XLSB] 2.3 Record Enumeration */
var XLSBRecordEnum = {
S
SheetJS 已提交
15018 15019 15020 15021 15022 15023 15024 15025 15026 15027 15028 15029 15030 15031 15032 15033 15034 15035 15036 15037 15038 15039 15040 15041 15042 15043 15044 15045 15046 15047 15048 15049 15050
	/*::[*/0x0000/*::]*/: { n:"BrtRowHdr", f:parse_BrtRowHdr },
	/*::[*/0x0001/*::]*/: { n:"BrtCellBlank", f:parse_BrtCellBlank },
	/*::[*/0x0002/*::]*/: { n:"BrtCellRk", f:parse_BrtCellRk },
	/*::[*/0x0003/*::]*/: { n:"BrtCellError", f:parse_BrtCellError },
	/*::[*/0x0004/*::]*/: { n:"BrtCellBool", f:parse_BrtCellBool },
	/*::[*/0x0005/*::]*/: { n:"BrtCellReal", f:parse_BrtCellReal },
	/*::[*/0x0006/*::]*/: { n:"BrtCellSt", f:parse_BrtCellSt },
	/*::[*/0x0007/*::]*/: { n:"BrtCellIsst", f:parse_BrtCellIsst },
	/*::[*/0x0008/*::]*/: { n:"BrtFmlaString", f:parse_BrtFmlaString },
	/*::[*/0x0009/*::]*/: { n:"BrtFmlaNum", f:parse_BrtFmlaNum },
	/*::[*/0x000A/*::]*/: { n:"BrtFmlaBool", f:parse_BrtFmlaBool },
	/*::[*/0x000B/*::]*/: { n:"BrtFmlaError", f:parse_BrtFmlaError },
	/*::[*/0x0010/*::]*/: { n:"BrtFRTArchID$", f:parse_BrtFRTArchID$ },
	/*::[*/0x0013/*::]*/: { n:"BrtSSTItem", f:parse_RichStr },
	/*::[*/0x0014/*::]*/: { n:"BrtPCDIMissing", f:parsenoop },
	/*::[*/0x0015/*::]*/: { n:"BrtPCDINumber", f:parsenoop },
	/*::[*/0x0016/*::]*/: { n:"BrtPCDIBoolean", f:parsenoop },
	/*::[*/0x0017/*::]*/: { n:"BrtPCDIError", f:parsenoop },
	/*::[*/0x0018/*::]*/: { n:"BrtPCDIString", f:parsenoop },
	/*::[*/0x0019/*::]*/: { n:"BrtPCDIDatetime", f:parsenoop },
	/*::[*/0x001A/*::]*/: { n:"BrtPCDIIndex", f:parsenoop },
	/*::[*/0x001B/*::]*/: { n:"BrtPCDIAMissing", f:parsenoop },
	/*::[*/0x001C/*::]*/: { n:"BrtPCDIANumber", f:parsenoop },
	/*::[*/0x001D/*::]*/: { n:"BrtPCDIABoolean", f:parsenoop },
	/*::[*/0x001E/*::]*/: { n:"BrtPCDIAError", f:parsenoop },
	/*::[*/0x001F/*::]*/: { n:"BrtPCDIAString", f:parsenoop },
	/*::[*/0x0020/*::]*/: { n:"BrtPCDIADatetime", f:parsenoop },
	/*::[*/0x0021/*::]*/: { n:"BrtPCRRecord", f:parsenoop },
	/*::[*/0x0022/*::]*/: { n:"BrtPCRRecordDt", f:parsenoop },
	/*::[*/0x0023/*::]*/: { n:"BrtFRTBegin", f:parsenoop },
	/*::[*/0x0024/*::]*/: { n:"BrtFRTEnd", f:parsenoop },
	/*::[*/0x0025/*::]*/: { n:"BrtACBegin", f:parsenoop },
	/*::[*/0x0026/*::]*/: { n:"BrtACEnd", f:parsenoop },
S
SheetJS 已提交
15051
	/*::[*/0x0027/*::]*/: { n:"BrtName", f:parse_BrtName },
S
SheetJS 已提交
15052 15053 15054 15055
	/*::[*/0x0028/*::]*/: { n:"BrtIndexRowBlock", f:parsenoop },
	/*::[*/0x002A/*::]*/: { n:"BrtIndexBlock", f:parsenoop },
	/*::[*/0x002B/*::]*/: { n:"BrtFont", f:parse_BrtFont },
	/*::[*/0x002C/*::]*/: { n:"BrtFmt", f:parse_BrtFmt },
S
SheetJS 已提交
15056 15057
	/*::[*/0x002D/*::]*/: { n:"BrtFill", f:parse_BrtFill },
	/*::[*/0x002E/*::]*/: { n:"BrtBorder", f:parse_BrtBorder },
S
SheetJS 已提交
15058 15059 15060 15061 15062 15063 15064 15065 15066 15067 15068 15069 15070
	/*::[*/0x002F/*::]*/: { n:"BrtXF", f:parse_BrtXF },
	/*::[*/0x0030/*::]*/: { n:"BrtStyle", f:parsenoop },
	/*::[*/0x0031/*::]*/: { n:"BrtCellMeta", f:parsenoop },
	/*::[*/0x0032/*::]*/: { n:"BrtValueMeta", f:parsenoop },
	/*::[*/0x0033/*::]*/: { n:"BrtMdb", f:parsenoop },
	/*::[*/0x0034/*::]*/: { n:"BrtBeginFmd", f:parsenoop },
	/*::[*/0x0035/*::]*/: { n:"BrtEndFmd", f:parsenoop },
	/*::[*/0x0036/*::]*/: { n:"BrtBeginMdx", f:parsenoop },
	/*::[*/0x0037/*::]*/: { n:"BrtEndMdx", f:parsenoop },
	/*::[*/0x0038/*::]*/: { n:"BrtBeginMdxTuple", f:parsenoop },
	/*::[*/0x0039/*::]*/: { n:"BrtEndMdxTuple", f:parsenoop },
	/*::[*/0x003A/*::]*/: { n:"BrtMdxMbrIstr", f:parsenoop },
	/*::[*/0x003B/*::]*/: { n:"BrtStr", f:parsenoop },
S
SheetJS 已提交
15071
	/*::[*/0x003C/*::]*/: { n:"BrtColInfo", f:parse_ColInfo },
S
SheetJS 已提交
15072 15073 15074 15075 15076 15077 15078 15079 15080 15081 15082 15083 15084 15085 15086 15087 15088 15089 15090 15091 15092 15093 15094 15095 15096 15097 15098 15099 15100 15101 15102 15103 15104 15105 15106 15107 15108 15109 15110 15111
	/*::[*/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 },
	/*::[*/0x0043/*::]*/: { n:"BrtSxvcellBool", f:parsenoop },
	/*::[*/0x0044/*::]*/: { n:"BrtSxvcellErr", f:parsenoop },
	/*::[*/0x0045/*::]*/: { n:"BrtSxvcellDate", f:parsenoop },
	/*::[*/0x0046/*::]*/: { n:"BrtSxvcellNil", f:parsenoop },
	/*::[*/0x0080/*::]*/: { n:"BrtFileVersion", f:parsenoop },
	/*::[*/0x0081/*::]*/: { n:"BrtBeginSheet", f:parsenoop },
	/*::[*/0x0082/*::]*/: { n:"BrtEndSheet", f:parsenoop },
	/*::[*/0x0083/*::]*/: { n:"BrtBeginBook", f:parsenoop, p:0 },
	/*::[*/0x0084/*::]*/: { n:"BrtEndBook", f:parsenoop },
	/*::[*/0x0085/*::]*/: { n:"BrtBeginWsViews", f:parsenoop },
	/*::[*/0x0086/*::]*/: { n:"BrtEndWsViews", f:parsenoop },
	/*::[*/0x0087/*::]*/: { n:"BrtBeginBookViews", f:parsenoop },
	/*::[*/0x0088/*::]*/: { n:"BrtEndBookViews", f:parsenoop },
	/*::[*/0x0089/*::]*/: { n:"BrtBeginWsView", f:parsenoop },
	/*::[*/0x008A/*::]*/: { n:"BrtEndWsView", f:parsenoop },
	/*::[*/0x008B/*::]*/: { n:"BrtBeginCsViews", f:parsenoop },
	/*::[*/0x008C/*::]*/: { n:"BrtEndCsViews", f:parsenoop },
	/*::[*/0x008D/*::]*/: { n:"BrtBeginCsView", f:parsenoop },
	/*::[*/0x008E/*::]*/: { n:"BrtEndCsView", f:parsenoop },
	/*::[*/0x008F/*::]*/: { n:"BrtBeginBundleShs", f:parsenoop },
	/*::[*/0x0090/*::]*/: { n:"BrtEndBundleShs", f:parsenoop },
	/*::[*/0x0091/*::]*/: { n:"BrtBeginSheetData", f:parsenoop },
	/*::[*/0x0092/*::]*/: { n:"BrtEndSheetData", f:parsenoop },
	/*::[*/0x0093/*::]*/: { n:"BrtWsProp", f:parse_BrtWsProp },
	/*::[*/0x0094/*::]*/: { n:"BrtWsDim", f:parse_BrtWsDim, p:16 },
	/*::[*/0x0097/*::]*/: { n:"BrtPane", f:parsenoop },
	/*::[*/0x0098/*::]*/: { n:"BrtSel", f:parsenoop },
	/*::[*/0x0099/*::]*/: { n:"BrtWbProp", f:parse_BrtWbProp },
	/*::[*/0x009A/*::]*/: { n:"BrtWbFactoid", f:parsenoop },
	/*::[*/0x009B/*::]*/: { n:"BrtFileRecover", f:parsenoop },
	/*::[*/0x009C/*::]*/: { n:"BrtBundleSh", f:parse_BrtBundleSh },
	/*::[*/0x009D/*::]*/: { n:"BrtCalcProp", f:parsenoop },
	/*::[*/0x009E/*::]*/: { n:"BrtBookView", f:parsenoop },
	/*::[*/0x009F/*::]*/: { n:"BrtBeginSst", f:parse_BrtBeginSst },
	/*::[*/0x00A0/*::]*/: { n:"BrtEndSst", f:parsenoop },
S
SheetJS 已提交
15112
	/*::[*/0x00A1/*::]*/: { n:"BrtBeginAFilter", f:parse_UncheckedRfX },
S
SheetJS 已提交
15113 15114 15115 15116 15117 15118 15119 15120 15121 15122 15123 15124 15125 15126 15127 15128 15129 15130 15131 15132 15133 15134 15135 15136 15137 15138 15139 15140 15141 15142 15143 15144 15145 15146 15147 15148 15149 15150 15151 15152 15153 15154 15155 15156 15157 15158 15159 15160 15161 15162 15163 15164 15165 15166 15167 15168 15169 15170 15171 15172 15173 15174 15175 15176 15177 15178 15179 15180 15181 15182 15183 15184 15185 15186 15187 15188 15189 15190 15191 15192 15193 15194 15195 15196 15197 15198 15199 15200 15201 15202 15203 15204 15205 15206 15207 15208 15209 15210 15211 15212 15213 15214 15215 15216 15217 15218 15219 15220 15221 15222 15223 15224 15225 15226 15227 15228 15229 15230 15231 15232 15233 15234 15235 15236 15237 15238 15239 15240 15241 15242 15243 15244 15245 15246 15247 15248 15249 15250 15251 15252 15253 15254 15255 15256 15257 15258 15259 15260 15261 15262 15263 15264 15265 15266 15267 15268 15269 15270 15271 15272 15273 15274 15275 15276 15277 15278 15279 15280 15281 15282 15283 15284 15285 15286 15287 15288 15289 15290 15291 15292 15293 15294 15295 15296 15297 15298 15299 15300 15301 15302 15303 15304 15305
	/*::[*/0x00A2/*::]*/: { n:"BrtEndAFilter", f:parsenoop },
	/*::[*/0x00A3/*::]*/: { n:"BrtBeginFilterColumn", f:parsenoop },
	/*::[*/0x00A4/*::]*/: { n:"BrtEndFilterColumn", f:parsenoop },
	/*::[*/0x00A5/*::]*/: { n:"BrtBeginFilters", f:parsenoop },
	/*::[*/0x00A6/*::]*/: { n:"BrtEndFilters", f:parsenoop },
	/*::[*/0x00A7/*::]*/: { n:"BrtFilter", f:parsenoop },
	/*::[*/0x00A8/*::]*/: { n:"BrtColorFilter", f:parsenoop },
	/*::[*/0x00A9/*::]*/: { n:"BrtIconFilter", f:parsenoop },
	/*::[*/0x00AA/*::]*/: { n:"BrtTop10Filter", f:parsenoop },
	/*::[*/0x00AB/*::]*/: { n:"BrtDynamicFilter", f:parsenoop },
	/*::[*/0x00AC/*::]*/: { n:"BrtBeginCustomFilters", f:parsenoop },
	/*::[*/0x00AD/*::]*/: { n:"BrtEndCustomFilters", f:parsenoop },
	/*::[*/0x00AE/*::]*/: { n:"BrtCustomFilter", f:parsenoop },
	/*::[*/0x00AF/*::]*/: { n:"BrtAFilterDateGroupItem", f:parsenoop },
	/*::[*/0x00B0/*::]*/: { n:"BrtMergeCell", f:parse_BrtMergeCell },
	/*::[*/0x00B1/*::]*/: { n:"BrtBeginMergeCells", f:parsenoop },
	/*::[*/0x00B2/*::]*/: { n:"BrtEndMergeCells", f:parsenoop },
	/*::[*/0x00B3/*::]*/: { n:"BrtBeginPivotCacheDef", f:parsenoop },
	/*::[*/0x00B4/*::]*/: { n:"BrtEndPivotCacheDef", f:parsenoop },
	/*::[*/0x00B5/*::]*/: { n:"BrtBeginPCDFields", f:parsenoop },
	/*::[*/0x00B6/*::]*/: { n:"BrtEndPCDFields", f:parsenoop },
	/*::[*/0x00B7/*::]*/: { n:"BrtBeginPCDField", f:parsenoop },
	/*::[*/0x00B8/*::]*/: { n:"BrtEndPCDField", f:parsenoop },
	/*::[*/0x00B9/*::]*/: { n:"BrtBeginPCDSource", f:parsenoop },
	/*::[*/0x00BA/*::]*/: { n:"BrtEndPCDSource", f:parsenoop },
	/*::[*/0x00BB/*::]*/: { n:"BrtBeginPCDSRange", f:parsenoop },
	/*::[*/0x00BC/*::]*/: { n:"BrtEndPCDSRange", f:parsenoop },
	/*::[*/0x00BD/*::]*/: { n:"BrtBeginPCDFAtbl", f:parsenoop },
	/*::[*/0x00BE/*::]*/: { n:"BrtEndPCDFAtbl", f:parsenoop },
	/*::[*/0x00BF/*::]*/: { n:"BrtBeginPCDIRun", f:parsenoop },
	/*::[*/0x00C0/*::]*/: { n:"BrtEndPCDIRun", f:parsenoop },
	/*::[*/0x00C1/*::]*/: { n:"BrtBeginPivotCacheRecords", f:parsenoop },
	/*::[*/0x00C2/*::]*/: { n:"BrtEndPivotCacheRecords", f:parsenoop },
	/*::[*/0x00C3/*::]*/: { n:"BrtBeginPCDHierarchies", f:parsenoop },
	/*::[*/0x00C4/*::]*/: { n:"BrtEndPCDHierarchies", f:parsenoop },
	/*::[*/0x00C5/*::]*/: { n:"BrtBeginPCDHierarchy", f:parsenoop },
	/*::[*/0x00C6/*::]*/: { n:"BrtEndPCDHierarchy", f:parsenoop },
	/*::[*/0x00C7/*::]*/: { n:"BrtBeginPCDHFieldsUsage", f:parsenoop },
	/*::[*/0x00C8/*::]*/: { n:"BrtEndPCDHFieldsUsage", f:parsenoop },
	/*::[*/0x00C9/*::]*/: { n:"BrtBeginExtConnection", f:parsenoop },
	/*::[*/0x00CA/*::]*/: { n:"BrtEndExtConnection", f:parsenoop },
	/*::[*/0x00CB/*::]*/: { n:"BrtBeginECDbProps", f:parsenoop },
	/*::[*/0x00CC/*::]*/: { n:"BrtEndECDbProps", f:parsenoop },
	/*::[*/0x00CD/*::]*/: { n:"BrtBeginECOlapProps", f:parsenoop },
	/*::[*/0x00CE/*::]*/: { n:"BrtEndECOlapProps", f:parsenoop },
	/*::[*/0x00CF/*::]*/: { n:"BrtBeginPCDSConsol", f:parsenoop },
	/*::[*/0x00D0/*::]*/: { n:"BrtEndPCDSConsol", f:parsenoop },
	/*::[*/0x00D1/*::]*/: { n:"BrtBeginPCDSCPages", f:parsenoop },
	/*::[*/0x00D2/*::]*/: { n:"BrtEndPCDSCPages", f:parsenoop },
	/*::[*/0x00D3/*::]*/: { n:"BrtBeginPCDSCPage", f:parsenoop },
	/*::[*/0x00D4/*::]*/: { n:"BrtEndPCDSCPage", f:parsenoop },
	/*::[*/0x00D5/*::]*/: { n:"BrtBeginPCDSCPItem", f:parsenoop },
	/*::[*/0x00D6/*::]*/: { n:"BrtEndPCDSCPItem", f:parsenoop },
	/*::[*/0x00D7/*::]*/: { n:"BrtBeginPCDSCSets", f:parsenoop },
	/*::[*/0x00D8/*::]*/: { n:"BrtEndPCDSCSets", f:parsenoop },
	/*::[*/0x00D9/*::]*/: { n:"BrtBeginPCDSCSet", f:parsenoop },
	/*::[*/0x00DA/*::]*/: { n:"BrtEndPCDSCSet", f:parsenoop },
	/*::[*/0x00DB/*::]*/: { n:"BrtBeginPCDFGroup", f:parsenoop },
	/*::[*/0x00DC/*::]*/: { n:"BrtEndPCDFGroup", f:parsenoop },
	/*::[*/0x00DD/*::]*/: { n:"BrtBeginPCDFGItems", f:parsenoop },
	/*::[*/0x00DE/*::]*/: { n:"BrtEndPCDFGItems", f:parsenoop },
	/*::[*/0x00DF/*::]*/: { n:"BrtBeginPCDFGRange", f:parsenoop },
	/*::[*/0x00E0/*::]*/: { n:"BrtEndPCDFGRange", f:parsenoop },
	/*::[*/0x00E1/*::]*/: { n:"BrtBeginPCDFGDiscrete", f:parsenoop },
	/*::[*/0x00E2/*::]*/: { n:"BrtEndPCDFGDiscrete", f:parsenoop },
	/*::[*/0x00E3/*::]*/: { n:"BrtBeginPCDSDTupleCache", f:parsenoop },
	/*::[*/0x00E4/*::]*/: { n:"BrtEndPCDSDTupleCache", f:parsenoop },
	/*::[*/0x00E5/*::]*/: { n:"BrtBeginPCDSDTCEntries", f:parsenoop },
	/*::[*/0x00E6/*::]*/: { n:"BrtEndPCDSDTCEntries", f:parsenoop },
	/*::[*/0x00E7/*::]*/: { n:"BrtBeginPCDSDTCEMembers", f:parsenoop },
	/*::[*/0x00E8/*::]*/: { n:"BrtEndPCDSDTCEMembers", f:parsenoop },
	/*::[*/0x00E9/*::]*/: { n:"BrtBeginPCDSDTCEMember", f:parsenoop },
	/*::[*/0x00EA/*::]*/: { n:"BrtEndPCDSDTCEMember", f:parsenoop },
	/*::[*/0x00EB/*::]*/: { n:"BrtBeginPCDSDTCQueries", f:parsenoop },
	/*::[*/0x00EC/*::]*/: { n:"BrtEndPCDSDTCQueries", f:parsenoop },
	/*::[*/0x00ED/*::]*/: { n:"BrtBeginPCDSDTCQuery", f:parsenoop },
	/*::[*/0x00EE/*::]*/: { n:"BrtEndPCDSDTCQuery", f:parsenoop },
	/*::[*/0x00EF/*::]*/: { n:"BrtBeginPCDSDTCSets", f:parsenoop },
	/*::[*/0x00F0/*::]*/: { n:"BrtEndPCDSDTCSets", f:parsenoop },
	/*::[*/0x00F1/*::]*/: { n:"BrtBeginPCDSDTCSet", f:parsenoop },
	/*::[*/0x00F2/*::]*/: { n:"BrtEndPCDSDTCSet", f:parsenoop },
	/*::[*/0x00F3/*::]*/: { n:"BrtBeginPCDCalcItems", f:parsenoop },
	/*::[*/0x00F4/*::]*/: { n:"BrtEndPCDCalcItems", f:parsenoop },
	/*::[*/0x00F5/*::]*/: { n:"BrtBeginPCDCalcItem", f:parsenoop },
	/*::[*/0x00F6/*::]*/: { n:"BrtEndPCDCalcItem", f:parsenoop },
	/*::[*/0x00F7/*::]*/: { n:"BrtBeginPRule", f:parsenoop },
	/*::[*/0x00F8/*::]*/: { n:"BrtEndPRule", f:parsenoop },
	/*::[*/0x00F9/*::]*/: { n:"BrtBeginPRFilters", f:parsenoop },
	/*::[*/0x00FA/*::]*/: { n:"BrtEndPRFilters", f:parsenoop },
	/*::[*/0x00FB/*::]*/: { n:"BrtBeginPRFilter", f:parsenoop },
	/*::[*/0x00FC/*::]*/: { n:"BrtEndPRFilter", f:parsenoop },
	/*::[*/0x00FD/*::]*/: { n:"BrtBeginPNames", f:parsenoop },
	/*::[*/0x00FE/*::]*/: { n:"BrtEndPNames", f:parsenoop },
	/*::[*/0x00FF/*::]*/: { n:"BrtBeginPName", f:parsenoop },
	/*::[*/0x0100/*::]*/: { n:"BrtEndPName", f:parsenoop },
	/*::[*/0x0101/*::]*/: { n:"BrtBeginPNPairs", f:parsenoop },
	/*::[*/0x0102/*::]*/: { n:"BrtEndPNPairs", f:parsenoop },
	/*::[*/0x0103/*::]*/: { n:"BrtBeginPNPair", f:parsenoop },
	/*::[*/0x0104/*::]*/: { n:"BrtEndPNPair", f:parsenoop },
	/*::[*/0x0105/*::]*/: { n:"BrtBeginECWebProps", f:parsenoop },
	/*::[*/0x0106/*::]*/: { n:"BrtEndECWebProps", f:parsenoop },
	/*::[*/0x0107/*::]*/: { n:"BrtBeginEcWpTables", f:parsenoop },
	/*::[*/0x0108/*::]*/: { n:"BrtEndECWPTables", f:parsenoop },
	/*::[*/0x0109/*::]*/: { n:"BrtBeginECParams", f:parsenoop },
	/*::[*/0x010A/*::]*/: { n:"BrtEndECParams", f:parsenoop },
	/*::[*/0x010B/*::]*/: { n:"BrtBeginECParam", f:parsenoop },
	/*::[*/0x010C/*::]*/: { n:"BrtEndECParam", f:parsenoop },
	/*::[*/0x010D/*::]*/: { n:"BrtBeginPCDKPIs", f:parsenoop },
	/*::[*/0x010E/*::]*/: { n:"BrtEndPCDKPIs", f:parsenoop },
	/*::[*/0x010F/*::]*/: { n:"BrtBeginPCDKPI", f:parsenoop },
	/*::[*/0x0110/*::]*/: { n:"BrtEndPCDKPI", f:parsenoop },
	/*::[*/0x0111/*::]*/: { n:"BrtBeginDims", f:parsenoop },
	/*::[*/0x0112/*::]*/: { n:"BrtEndDims", f:parsenoop },
	/*::[*/0x0113/*::]*/: { n:"BrtBeginDim", f:parsenoop },
	/*::[*/0x0114/*::]*/: { n:"BrtEndDim", f:parsenoop },
	/*::[*/0x0115/*::]*/: { n:"BrtIndexPartEnd", f:parsenoop },
	/*::[*/0x0116/*::]*/: { n:"BrtBeginStyleSheet", f:parsenoop },
	/*::[*/0x0117/*::]*/: { n:"BrtEndStyleSheet", f:parsenoop },
	/*::[*/0x0118/*::]*/: { n:"BrtBeginSXView", f:parsenoop },
	/*::[*/0x0119/*::]*/: { n:"BrtEndSXVI", f:parsenoop },
	/*::[*/0x011A/*::]*/: { n:"BrtBeginSXVI", f:parsenoop },
	/*::[*/0x011B/*::]*/: { n:"BrtBeginSXVIs", f:parsenoop },
	/*::[*/0x011C/*::]*/: { n:"BrtEndSXVIs", f:parsenoop },
	/*::[*/0x011D/*::]*/: { n:"BrtBeginSXVD", f:parsenoop },
	/*::[*/0x011E/*::]*/: { n:"BrtEndSXVD", f:parsenoop },
	/*::[*/0x011F/*::]*/: { n:"BrtBeginSXVDs", f:parsenoop },
	/*::[*/0x0120/*::]*/: { n:"BrtEndSXVDs", f:parsenoop },
	/*::[*/0x0121/*::]*/: { n:"BrtBeginSXPI", f:parsenoop },
	/*::[*/0x0122/*::]*/: { n:"BrtEndSXPI", f:parsenoop },
	/*::[*/0x0123/*::]*/: { n:"BrtBeginSXPIs", f:parsenoop },
	/*::[*/0x0124/*::]*/: { n:"BrtEndSXPIs", f:parsenoop },
	/*::[*/0x0125/*::]*/: { n:"BrtBeginSXDI", f:parsenoop },
	/*::[*/0x0126/*::]*/: { n:"BrtEndSXDI", f:parsenoop },
	/*::[*/0x0127/*::]*/: { n:"BrtBeginSXDIs", f:parsenoop },
	/*::[*/0x0128/*::]*/: { n:"BrtEndSXDIs", f:parsenoop },
	/*::[*/0x0129/*::]*/: { n:"BrtBeginSXLI", f:parsenoop },
	/*::[*/0x012A/*::]*/: { n:"BrtEndSXLI", f:parsenoop },
	/*::[*/0x012B/*::]*/: { n:"BrtBeginSXLIRws", f:parsenoop },
	/*::[*/0x012C/*::]*/: { n:"BrtEndSXLIRws", f:parsenoop },
	/*::[*/0x012D/*::]*/: { n:"BrtBeginSXLICols", f:parsenoop },
	/*::[*/0x012E/*::]*/: { n:"BrtEndSXLICols", f:parsenoop },
	/*::[*/0x012F/*::]*/: { n:"BrtBeginSXFormat", f:parsenoop },
	/*::[*/0x0130/*::]*/: { n:"BrtEndSXFormat", f:parsenoop },
	/*::[*/0x0131/*::]*/: { n:"BrtBeginSXFormats", f:parsenoop },
	/*::[*/0x0132/*::]*/: { n:"BrtEndSxFormats", f:parsenoop },
	/*::[*/0x0133/*::]*/: { n:"BrtBeginSxSelect", f:parsenoop },
	/*::[*/0x0134/*::]*/: { n:"BrtEndSxSelect", f:parsenoop },
	/*::[*/0x0135/*::]*/: { n:"BrtBeginISXVDRws", f:parsenoop },
	/*::[*/0x0136/*::]*/: { n:"BrtEndISXVDRws", f:parsenoop },
	/*::[*/0x0137/*::]*/: { n:"BrtBeginISXVDCols", f:parsenoop },
	/*::[*/0x0138/*::]*/: { n:"BrtEndISXVDCols", f:parsenoop },
	/*::[*/0x0139/*::]*/: { n:"BrtEndSXLocation", f:parsenoop },
	/*::[*/0x013A/*::]*/: { n:"BrtBeginSXLocation", f:parsenoop },
	/*::[*/0x013B/*::]*/: { n:"BrtEndSXView", f:parsenoop },
	/*::[*/0x013C/*::]*/: { n:"BrtBeginSXTHs", f:parsenoop },
	/*::[*/0x013D/*::]*/: { n:"BrtEndSXTHs", f:parsenoop },
	/*::[*/0x013E/*::]*/: { n:"BrtBeginSXTH", f:parsenoop },
	/*::[*/0x013F/*::]*/: { n:"BrtEndSXTH", f:parsenoop },
	/*::[*/0x0140/*::]*/: { n:"BrtBeginISXTHRws", f:parsenoop },
	/*::[*/0x0141/*::]*/: { n:"BrtEndISXTHRws", f:parsenoop },
	/*::[*/0x0142/*::]*/: { n:"BrtBeginISXTHCols", f:parsenoop },
	/*::[*/0x0143/*::]*/: { n:"BrtEndISXTHCols", f:parsenoop },
	/*::[*/0x0144/*::]*/: { n:"BrtBeginSXTDMPS", f:parsenoop },
	/*::[*/0x0145/*::]*/: { n:"BrtEndSXTDMPs", f:parsenoop },
	/*::[*/0x0146/*::]*/: { n:"BrtBeginSXTDMP", f:parsenoop },
	/*::[*/0x0147/*::]*/: { n:"BrtEndSXTDMP", f:parsenoop },
	/*::[*/0x0148/*::]*/: { n:"BrtBeginSXTHItems", f:parsenoop },
	/*::[*/0x0149/*::]*/: { n:"BrtEndSXTHItems", f:parsenoop },
	/*::[*/0x014A/*::]*/: { n:"BrtBeginSXTHItem", f:parsenoop },
	/*::[*/0x014B/*::]*/: { n:"BrtEndSXTHItem", f:parsenoop },
	/*::[*/0x014C/*::]*/: { n:"BrtBeginMetadata", f:parsenoop },
	/*::[*/0x014D/*::]*/: { n:"BrtEndMetadata", f:parsenoop },
	/*::[*/0x014E/*::]*/: { n:"BrtBeginEsmdtinfo", f:parsenoop },
	/*::[*/0x014F/*::]*/: { n:"BrtMdtinfo", f:parsenoop },
	/*::[*/0x0150/*::]*/: { n:"BrtEndEsmdtinfo", f:parsenoop },
	/*::[*/0x0151/*::]*/: { n:"BrtBeginEsmdb", f:parsenoop },
	/*::[*/0x0152/*::]*/: { n:"BrtEndEsmdb", f:parsenoop },
	/*::[*/0x0153/*::]*/: { n:"BrtBeginEsfmd", f:parsenoop },
	/*::[*/0x0154/*::]*/: { n:"BrtEndEsfmd", f:parsenoop },
	/*::[*/0x0155/*::]*/: { n:"BrtBeginSingleCells", f:parsenoop },
	/*::[*/0x0156/*::]*/: { n:"BrtEndSingleCells", f:parsenoop },
	/*::[*/0x0157/*::]*/: { n:"BrtBeginList", f:parsenoop },
	/*::[*/0x0158/*::]*/: { n:"BrtEndList", f:parsenoop },
	/*::[*/0x0159/*::]*/: { n:"BrtBeginListCols", f:parsenoop },
	/*::[*/0x015A/*::]*/: { n:"BrtEndListCols", f:parsenoop },
	/*::[*/0x015B/*::]*/: { n:"BrtBeginListCol", f:parsenoop },
	/*::[*/0x015C/*::]*/: { n:"BrtEndListCol", f:parsenoop },
	/*::[*/0x015D/*::]*/: { n:"BrtBeginListXmlCPr", f:parsenoop },
	/*::[*/0x015E/*::]*/: { n:"BrtEndListXmlCPr", f:parsenoop },
	/*::[*/0x015F/*::]*/: { n:"BrtListCCFmla", f:parsenoop },
	/*::[*/0x0160/*::]*/: { n:"BrtListTrFmla", f:parsenoop },
	/*::[*/0x0161/*::]*/: { n:"BrtBeginExternals", f:parsenoop },
	/*::[*/0x0162/*::]*/: { n:"BrtEndExternals", f:parsenoop },
S
SheetJS 已提交
15306
	/*::[*/0x0163/*::]*/: { n:"BrtSupBookSrc", f:parse_RelID},
S
SheetJS 已提交
15307 15308 15309 15310 15311
	/*::[*/0x0165/*::]*/: { n:"BrtSupSelf", f:parsenoop },
	/*::[*/0x0166/*::]*/: { n:"BrtSupSame", f:parsenoop },
	/*::[*/0x0167/*::]*/: { n:"BrtSupTabs", f:parsenoop },
	/*::[*/0x0168/*::]*/: { n:"BrtBeginSupBook", f:parsenoop },
	/*::[*/0x0169/*::]*/: { n:"BrtPlaceholderName", f:parsenoop },
S
SheetJS 已提交
15312
	/*::[*/0x016A/*::]*/: { n:"BrtExternSheet", f:parse_ExternSheet },
S
SheetJS 已提交
15313 15314 15315 15316 15317 15318 15319 15320 15321 15322 15323 15324 15325 15326 15327 15328 15329 15330 15331 15332 15333 15334 15335 15336 15337 15338 15339 15340 15341 15342 15343 15344 15345 15346 15347 15348 15349 15350 15351 15352 15353 15354 15355 15356 15357 15358 15359 15360 15361 15362 15363 15364 15365 15366 15367 15368 15369 15370 15371 15372 15373
	/*::[*/0x016B/*::]*/: { n:"BrtExternTableStart", f:parsenoop },
	/*::[*/0x016C/*::]*/: { n:"BrtExternTableEnd", f:parsenoop },
	/*::[*/0x016E/*::]*/: { n:"BrtExternRowHdr", f:parsenoop },
	/*::[*/0x016F/*::]*/: { n:"BrtExternCellBlank", f:parsenoop },
	/*::[*/0x0170/*::]*/: { n:"BrtExternCellReal", f:parsenoop },
	/*::[*/0x0171/*::]*/: { n:"BrtExternCellBool", f:parsenoop },
	/*::[*/0x0172/*::]*/: { n:"BrtExternCellError", f:parsenoop },
	/*::[*/0x0173/*::]*/: { n:"BrtExternCellString", f:parsenoop },
	/*::[*/0x0174/*::]*/: { n:"BrtBeginEsmdx", f:parsenoop },
	/*::[*/0x0175/*::]*/: { n:"BrtEndEsmdx", f:parsenoop },
	/*::[*/0x0176/*::]*/: { n:"BrtBeginMdxSet", f:parsenoop },
	/*::[*/0x0177/*::]*/: { n:"BrtEndMdxSet", f:parsenoop },
	/*::[*/0x0178/*::]*/: { n:"BrtBeginMdxMbrProp", f:parsenoop },
	/*::[*/0x0179/*::]*/: { n:"BrtEndMdxMbrProp", f:parsenoop },
	/*::[*/0x017A/*::]*/: { n:"BrtBeginMdxKPI", f:parsenoop },
	/*::[*/0x017B/*::]*/: { n:"BrtEndMdxKPI", f:parsenoop },
	/*::[*/0x017C/*::]*/: { n:"BrtBeginEsstr", f:parsenoop },
	/*::[*/0x017D/*::]*/: { n:"BrtEndEsstr", f:parsenoop },
	/*::[*/0x017E/*::]*/: { n:"BrtBeginPRFItem", f:parsenoop },
	/*::[*/0x017F/*::]*/: { n:"BrtEndPRFItem", f:parsenoop },
	/*::[*/0x0180/*::]*/: { n:"BrtBeginPivotCacheIDs", f:parsenoop },
	/*::[*/0x0181/*::]*/: { n:"BrtEndPivotCacheIDs", f:parsenoop },
	/*::[*/0x0182/*::]*/: { n:"BrtBeginPivotCacheID", f:parsenoop },
	/*::[*/0x0183/*::]*/: { n:"BrtEndPivotCacheID", f:parsenoop },
	/*::[*/0x0184/*::]*/: { n:"BrtBeginISXVIs", f:parsenoop },
	/*::[*/0x0185/*::]*/: { n:"BrtEndISXVIs", f:parsenoop },
	/*::[*/0x0186/*::]*/: { n:"BrtBeginColInfos", f:parsenoop },
	/*::[*/0x0187/*::]*/: { n:"BrtEndColInfos", f:parsenoop },
	/*::[*/0x0188/*::]*/: { n:"BrtBeginRwBrk", f:parsenoop },
	/*::[*/0x0189/*::]*/: { n:"BrtEndRwBrk", f:parsenoop },
	/*::[*/0x018A/*::]*/: { n:"BrtBeginColBrk", f:parsenoop },
	/*::[*/0x018B/*::]*/: { n:"BrtEndColBrk", f:parsenoop },
	/*::[*/0x018C/*::]*/: { n:"BrtBrk", f:parsenoop },
	/*::[*/0x018D/*::]*/: { n:"BrtUserBookView", f:parsenoop },
	/*::[*/0x018E/*::]*/: { n:"BrtInfo", f:parsenoop },
	/*::[*/0x018F/*::]*/: { n:"BrtCUsr", f:parsenoop },
	/*::[*/0x0190/*::]*/: { n:"BrtUsr", f:parsenoop },
	/*::[*/0x0191/*::]*/: { n:"BrtBeginUsers", f:parsenoop },
	/*::[*/0x0193/*::]*/: { n:"BrtEOF", f:parsenoop },
	/*::[*/0x0194/*::]*/: { n:"BrtUCR", f:parsenoop },
	/*::[*/0x0195/*::]*/: { n:"BrtRRInsDel", f:parsenoop },
	/*::[*/0x0196/*::]*/: { n:"BrtRREndInsDel", f:parsenoop },
	/*::[*/0x0197/*::]*/: { n:"BrtRRMove", f:parsenoop },
	/*::[*/0x0198/*::]*/: { n:"BrtRREndMove", f:parsenoop },
	/*::[*/0x0199/*::]*/: { n:"BrtRRChgCell", f:parsenoop },
	/*::[*/0x019A/*::]*/: { n:"BrtRREndChgCell", f:parsenoop },
	/*::[*/0x019B/*::]*/: { n:"BrtRRHeader", f:parsenoop },
	/*::[*/0x019C/*::]*/: { n:"BrtRRUserView", f:parsenoop },
	/*::[*/0x019D/*::]*/: { n:"BrtRRRenSheet", f:parsenoop },
	/*::[*/0x019E/*::]*/: { n:"BrtRRInsertSh", f:parsenoop },
	/*::[*/0x019F/*::]*/: { n:"BrtRRDefName", f:parsenoop },
	/*::[*/0x01A0/*::]*/: { n:"BrtRRNote", f:parsenoop },
	/*::[*/0x01A1/*::]*/: { n:"BrtRRConflict", f:parsenoop },
	/*::[*/0x01A2/*::]*/: { n:"BrtRRTQSIF", f:parsenoop },
	/*::[*/0x01A3/*::]*/: { n:"BrtRRFormat", f:parsenoop },
	/*::[*/0x01A4/*::]*/: { n:"BrtRREndFormat", f:parsenoop },
	/*::[*/0x01A5/*::]*/: { n:"BrtRRAutoFmt", f:parsenoop },
	/*::[*/0x01A6/*::]*/: { n:"BrtBeginUserShViews", f:parsenoop },
	/*::[*/0x01A7/*::]*/: { n:"BrtBeginUserShView", f:parsenoop },
	/*::[*/0x01A8/*::]*/: { n:"BrtEndUserShView", f:parsenoop },
	/*::[*/0x01A9/*::]*/: { n:"BrtEndUserShViews", f:parsenoop },
S
SheetJS 已提交
15374 15375
	/*::[*/0x01AA/*::]*/: { n:"BrtArrFmla", f:parse_BrtArrFmla },
	/*::[*/0x01AB/*::]*/: { n:"BrtShrFmla", f:parse_BrtShrFmla },
S
SheetJS 已提交
15376 15377 15378 15379 15380 15381 15382 15383 15384 15385 15386 15387 15388 15389 15390 15391 15392 15393 15394 15395 15396 15397 15398 15399 15400 15401 15402 15403 15404 15405 15406 15407 15408 15409 15410 15411 15412 15413 15414 15415 15416 15417 15418 15419 15420 15421 15422 15423
	/*::[*/0x01AC/*::]*/: { n:"BrtTable", f:parsenoop },
	/*::[*/0x01AD/*::]*/: { n:"BrtBeginExtConnections", f:parsenoop },
	/*::[*/0x01AE/*::]*/: { n:"BrtEndExtConnections", f:parsenoop },
	/*::[*/0x01AF/*::]*/: { n:"BrtBeginPCDCalcMems", f:parsenoop },
	/*::[*/0x01B0/*::]*/: { n:"BrtEndPCDCalcMems", f:parsenoop },
	/*::[*/0x01B1/*::]*/: { n:"BrtBeginPCDCalcMem", f:parsenoop },
	/*::[*/0x01B2/*::]*/: { n:"BrtEndPCDCalcMem", f:parsenoop },
	/*::[*/0x01B3/*::]*/: { n:"BrtBeginPCDHGLevels", f:parsenoop },
	/*::[*/0x01B4/*::]*/: { n:"BrtEndPCDHGLevels", f:parsenoop },
	/*::[*/0x01B5/*::]*/: { n:"BrtBeginPCDHGLevel", f:parsenoop },
	/*::[*/0x01B6/*::]*/: { n:"BrtEndPCDHGLevel", f:parsenoop },
	/*::[*/0x01B7/*::]*/: { n:"BrtBeginPCDHGLGroups", f:parsenoop },
	/*::[*/0x01B8/*::]*/: { n:"BrtEndPCDHGLGroups", f:parsenoop },
	/*::[*/0x01B9/*::]*/: { n:"BrtBeginPCDHGLGroup", f:parsenoop },
	/*::[*/0x01BA/*::]*/: { n:"BrtEndPCDHGLGroup", f:parsenoop },
	/*::[*/0x01BB/*::]*/: { n:"BrtBeginPCDHGLGMembers", f:parsenoop },
	/*::[*/0x01BC/*::]*/: { n:"BrtEndPCDHGLGMembers", f:parsenoop },
	/*::[*/0x01BD/*::]*/: { n:"BrtBeginPCDHGLGMember", f:parsenoop },
	/*::[*/0x01BE/*::]*/: { n:"BrtEndPCDHGLGMember", f:parsenoop },
	/*::[*/0x01BF/*::]*/: { n:"BrtBeginQSI", f:parsenoop },
	/*::[*/0x01C0/*::]*/: { n:"BrtEndQSI", f:parsenoop },
	/*::[*/0x01C1/*::]*/: { n:"BrtBeginQSIR", f:parsenoop },
	/*::[*/0x01C2/*::]*/: { n:"BrtEndQSIR", f:parsenoop },
	/*::[*/0x01C3/*::]*/: { n:"BrtBeginDeletedNames", f:parsenoop },
	/*::[*/0x01C4/*::]*/: { n:"BrtEndDeletedNames", f:parsenoop },
	/*::[*/0x01C5/*::]*/: { n:"BrtBeginDeletedName", f:parsenoop },
	/*::[*/0x01C6/*::]*/: { n:"BrtEndDeletedName", f:parsenoop },
	/*::[*/0x01C7/*::]*/: { n:"BrtBeginQSIFs", f:parsenoop },
	/*::[*/0x01C8/*::]*/: { n:"BrtEndQSIFs", f:parsenoop },
	/*::[*/0x01C9/*::]*/: { n:"BrtBeginQSIF", f:parsenoop },
	/*::[*/0x01CA/*::]*/: { n:"BrtEndQSIF", f:parsenoop },
	/*::[*/0x01CB/*::]*/: { n:"BrtBeginAutoSortScope", f:parsenoop },
	/*::[*/0x01CC/*::]*/: { n:"BrtEndAutoSortScope", f:parsenoop },
	/*::[*/0x01CD/*::]*/: { n:"BrtBeginConditionalFormatting", f:parsenoop },
	/*::[*/0x01CE/*::]*/: { n:"BrtEndConditionalFormatting", f:parsenoop },
	/*::[*/0x01CF/*::]*/: { n:"BrtBeginCFRule", f:parsenoop },
	/*::[*/0x01D0/*::]*/: { n:"BrtEndCFRule", f:parsenoop },
	/*::[*/0x01D1/*::]*/: { n:"BrtBeginIconSet", f:parsenoop },
	/*::[*/0x01D2/*::]*/: { n:"BrtEndIconSet", f:parsenoop },
	/*::[*/0x01D3/*::]*/: { n:"BrtBeginDatabar", f:parsenoop },
	/*::[*/0x01D4/*::]*/: { n:"BrtEndDatabar", f:parsenoop },
	/*::[*/0x01D5/*::]*/: { n:"BrtBeginColorScale", f:parsenoop },
	/*::[*/0x01D6/*::]*/: { n:"BrtEndColorScale", f:parsenoop },
	/*::[*/0x01D7/*::]*/: { n:"BrtCFVO", f:parsenoop },
	/*::[*/0x01D8/*::]*/: { n:"BrtExternValueMeta", f:parsenoop },
	/*::[*/0x01D9/*::]*/: { n:"BrtBeginColorPalette", f:parsenoop },
	/*::[*/0x01DA/*::]*/: { n:"BrtEndColorPalette", f:parsenoop },
	/*::[*/0x01DB/*::]*/: { n:"BrtIndexedColor", f:parsenoop },
S
SheetJS 已提交
15424
	/*::[*/0x01DC/*::]*/: { n:"BrtMargins", f:parse_BrtMargins },
S
SheetJS 已提交
15425 15426 15427 15428 15429 15430 15431 15432
	/*::[*/0x01DD/*::]*/: { n:"BrtPrintOptions", f:parsenoop },
	/*::[*/0x01DE/*::]*/: { n:"BrtPageSetup", f:parsenoop },
	/*::[*/0x01DF/*::]*/: { n:"BrtBeginHeaderFooter", f:parsenoop },
	/*::[*/0x01E0/*::]*/: { n:"BrtEndHeaderFooter", f:parsenoop },
	/*::[*/0x01E1/*::]*/: { n:"BrtBeginSXCrtFormat", f:parsenoop },
	/*::[*/0x01E2/*::]*/: { n:"BrtEndSXCrtFormat", f:parsenoop },
	/*::[*/0x01E3/*::]*/: { n:"BrtBeginSXCrtFormats", f:parsenoop },
	/*::[*/0x01E4/*::]*/: { n:"BrtEndSXCrtFormats", f:parsenoop },
S
SheetJS 已提交
15433
	/*::[*/0x01E5/*::]*/: { n:"BrtWsFmtInfo", f:parse_BrtWsFmtInfo },
S
SheetJS 已提交
15434 15435 15436 15437 15438 15439 15440 15441 15442 15443 15444 15445 15446 15447 15448 15449 15450 15451 15452 15453 15454 15455 15456 15457 15458 15459 15460 15461 15462 15463 15464 15465 15466 15467 15468 15469 15470 15471 15472 15473 15474 15475 15476 15477 15478 15479 15480 15481 15482 15483 15484 15485 15486 15487 15488 15489 15490 15491 15492
	/*::[*/0x01E6/*::]*/: { n:"BrtBeginMgs", f:parsenoop },
	/*::[*/0x01E7/*::]*/: { n:"BrtEndMGs", f:parsenoop },
	/*::[*/0x01E8/*::]*/: { n:"BrtBeginMGMaps", f:parsenoop },
	/*::[*/0x01E9/*::]*/: { n:"BrtEndMGMaps", f:parsenoop },
	/*::[*/0x01EA/*::]*/: { n:"BrtBeginMG", f:parsenoop },
	/*::[*/0x01EB/*::]*/: { n:"BrtEndMG", f:parsenoop },
	/*::[*/0x01EC/*::]*/: { n:"BrtBeginMap", f:parsenoop },
	/*::[*/0x01ED/*::]*/: { n:"BrtEndMap", f:parsenoop },
	/*::[*/0x01EE/*::]*/: { n:"BrtHLink", f:parse_BrtHLink },
	/*::[*/0x01EF/*::]*/: { n:"BrtBeginDCon", f:parsenoop },
	/*::[*/0x01F0/*::]*/: { n:"BrtEndDCon", f:parsenoop },
	/*::[*/0x01F1/*::]*/: { n:"BrtBeginDRefs", f:parsenoop },
	/*::[*/0x01F2/*::]*/: { n:"BrtEndDRefs", f:parsenoop },
	/*::[*/0x01F3/*::]*/: { n:"BrtDRef", f:parsenoop },
	/*::[*/0x01F4/*::]*/: { n:"BrtBeginScenMan", f:parsenoop },
	/*::[*/0x01F5/*::]*/: { n:"BrtEndScenMan", f:parsenoop },
	/*::[*/0x01F6/*::]*/: { n:"BrtBeginSct", f:parsenoop },
	/*::[*/0x01F7/*::]*/: { n:"BrtEndSct", f:parsenoop },
	/*::[*/0x01F8/*::]*/: { n:"BrtSlc", f:parsenoop },
	/*::[*/0x01F9/*::]*/: { n:"BrtBeginDXFs", f:parsenoop },
	/*::[*/0x01FA/*::]*/: { n:"BrtEndDXFs", f:parsenoop },
	/*::[*/0x01FB/*::]*/: { n:"BrtDXF", f:parsenoop },
	/*::[*/0x01FC/*::]*/: { n:"BrtBeginTableStyles", f:parsenoop },
	/*::[*/0x01FD/*::]*/: { n:"BrtEndTableStyles", f:parsenoop },
	/*::[*/0x01FE/*::]*/: { n:"BrtBeginTableStyle", f:parsenoop },
	/*::[*/0x01FF/*::]*/: { n:"BrtEndTableStyle", f:parsenoop },
	/*::[*/0x0200/*::]*/: { n:"BrtTableStyleElement", f:parsenoop },
	/*::[*/0x0201/*::]*/: { n:"BrtTableStyleClient", f:parsenoop },
	/*::[*/0x0202/*::]*/: { n:"BrtBeginVolDeps", f:parsenoop },
	/*::[*/0x0203/*::]*/: { n:"BrtEndVolDeps", f:parsenoop },
	/*::[*/0x0204/*::]*/: { n:"BrtBeginVolType", f:parsenoop },
	/*::[*/0x0205/*::]*/: { n:"BrtEndVolType", f:parsenoop },
	/*::[*/0x0206/*::]*/: { n:"BrtBeginVolMain", f:parsenoop },
	/*::[*/0x0207/*::]*/: { n:"BrtEndVolMain", f:parsenoop },
	/*::[*/0x0208/*::]*/: { n:"BrtBeginVolTopic", f:parsenoop },
	/*::[*/0x0209/*::]*/: { n:"BrtEndVolTopic", f:parsenoop },
	/*::[*/0x020A/*::]*/: { n:"BrtVolSubtopic", f:parsenoop },
	/*::[*/0x020B/*::]*/: { n:"BrtVolRef", f:parsenoop },
	/*::[*/0x020C/*::]*/: { n:"BrtVolNum", f:parsenoop },
	/*::[*/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 },
	/*::[*/0x0215/*::]*/: { n:"BrtEndSortCond", f:parsenoop },
	/*::[*/0x0216/*::]*/: { n:"BrtBookProtection", f:parsenoop },
	/*::[*/0x0217/*::]*/: { n:"BrtSheetProtection", f:parsenoop },
	/*::[*/0x0218/*::]*/: { n:"BrtRangeProtection", f:parsenoop },
	/*::[*/0x0219/*::]*/: { n:"BrtPhoneticInfo", f:parsenoop },
	/*::[*/0x021A/*::]*/: { n:"BrtBeginECTxtWiz", f:parsenoop },
	/*::[*/0x021B/*::]*/: { n:"BrtEndECTxtWiz", f:parsenoop },
	/*::[*/0x021C/*::]*/: { n:"BrtBeginECTWFldInfoLst", f:parsenoop },
	/*::[*/0x021D/*::]*/: { n:"BrtEndECTWFldInfoLst", f:parsenoop },
	/*::[*/0x021E/*::]*/: { n:"BrtBeginECTwFldInfo", f:parsenoop },
	/*::[*/0x0224/*::]*/: { n:"BrtFileSharing", f:parsenoop },
	/*::[*/0x0225/*::]*/: { n:"BrtOleSize", f:parsenoop },
15493
	/*::[*/0x0226/*::]*/: { n:"BrtDrawing", f:parse_RelID },
S
SheetJS 已提交
15494 15495 15496 15497 15498 15499 15500 15501 15502 15503 15504 15505 15506 15507 15508 15509 15510 15511 15512 15513 15514 15515 15516 15517 15518 15519 15520 15521 15522 15523 15524 15525 15526 15527 15528 15529 15530 15531 15532 15533 15534 15535 15536 15537 15538 15539 15540 15541 15542 15543 15544 15545 15546 15547 15548 15549 15550 15551 15552 15553 15554 15555 15556 15557 15558 15559 15560 15561 15562 15563 15564 15565 15566 15567 15568 15569 15570 15571 15572 15573 15574 15575 15576 15577 15578 15579 15580 15581 15582 15583 15584 15585 15586 15587 15588 15589 15590 15591 15592 15593 15594 15595 15596 15597 15598 15599 15600 15601 15602 15603 15604 15605 15606 15607 15608 15609 15610 15611 15612 15613 15614 15615 15616 15617 15618 15619 15620 15621 15622 15623 15624 15625 15626 15627 15628 15629 15630 15631 15632 15633 15634 15635 15636 15637 15638 15639 15640 15641 15642 15643 15644 15645 15646 15647 15648 15649 15650 15651 15652 15653 15654 15655 15656 15657 15658 15659 15660 15661 15662 15663 15664 15665 15666 15667 15668 15669 15670 15671 15672 15673 15674 15675 15676 15677 15678 15679 15680 15681 15682 15683 15684 15685 15686 15687 15688 15689 15690 15691 15692 15693 15694 15695 15696 15697 15698 15699 15700 15701 15702 15703 15704 15705 15706 15707 15708 15709 15710 15711 15712 15713 15714 15715 15716 15717 15718 15719 15720 15721 15722 15723 15724 15725 15726 15727 15728 15729 15730 15731 15732 15733 15734 15735 15736 15737 15738 15739 15740 15741 15742 15743 15744 15745 15746 15747 15748 15749 15750 15751 15752 15753 15754 15755 15756 15757 15758 15759 15760 15761 15762 15763 15764 15765 15766 15767 15768 15769 15770 15771 15772 15773 15774 15775 15776 15777 15778 15779 15780 15781 15782 15783 15784 15785 15786 15787 15788 15789 15790 15791 15792 15793 15794 15795 15796 15797 15798 15799 15800 15801 15802 15803 15804 15805 15806 15807 15808 15809 15810 15811 15812 15813 15814 15815 15816 15817 15818 15819 15820 15821 15822 15823 15824 15825 15826 15827 15828 15829 15830 15831 15832 15833 15834 15835 15836 15837
	/*::[*/0x0227/*::]*/: { n:"BrtLegacyDrawing", f:parsenoop },
	/*::[*/0x0228/*::]*/: { n:"BrtLegacyDrawingHF", f:parsenoop },
	/*::[*/0x0229/*::]*/: { n:"BrtWebOpt", f:parsenoop },
	/*::[*/0x022A/*::]*/: { n:"BrtBeginWebPubItems", f:parsenoop },
	/*::[*/0x022B/*::]*/: { n:"BrtEndWebPubItems", f:parsenoop },
	/*::[*/0x022C/*::]*/: { n:"BrtBeginWebPubItem", f:parsenoop },
	/*::[*/0x022D/*::]*/: { n:"BrtEndWebPubItem", f:parsenoop },
	/*::[*/0x022E/*::]*/: { n:"BrtBeginSXCondFmt", f:parsenoop },
	/*::[*/0x022F/*::]*/: { n:"BrtEndSXCondFmt", f:parsenoop },
	/*::[*/0x0230/*::]*/: { n:"BrtBeginSXCondFmts", f:parsenoop },
	/*::[*/0x0231/*::]*/: { n:"BrtEndSXCondFmts", f:parsenoop },
	/*::[*/0x0232/*::]*/: { n:"BrtBkHim", f:parsenoop },
	/*::[*/0x0234/*::]*/: { n:"BrtColor", f:parsenoop },
	/*::[*/0x0235/*::]*/: { n:"BrtBeginIndexedColors", f:parsenoop },
	/*::[*/0x0236/*::]*/: { n:"BrtEndIndexedColors", f:parsenoop },
	/*::[*/0x0239/*::]*/: { n:"BrtBeginMRUColors", f:parsenoop },
	/*::[*/0x023A/*::]*/: { n:"BrtEndMRUColors", f:parsenoop },
	/*::[*/0x023C/*::]*/: { n:"BrtMRUColor", f:parsenoop },
	/*::[*/0x023D/*::]*/: { n:"BrtBeginDVals", f:parsenoop },
	/*::[*/0x023E/*::]*/: { n:"BrtEndDVals", f:parsenoop },
	/*::[*/0x0241/*::]*/: { n:"BrtSupNameStart", f:parsenoop },
	/*::[*/0x0242/*::]*/: { n:"BrtSupNameValueStart", f:parsenoop },
	/*::[*/0x0243/*::]*/: { n:"BrtSupNameValueEnd", f:parsenoop },
	/*::[*/0x0244/*::]*/: { n:"BrtSupNameNum", f:parsenoop },
	/*::[*/0x0245/*::]*/: { n:"BrtSupNameErr", f:parsenoop },
	/*::[*/0x0246/*::]*/: { n:"BrtSupNameSt", f:parsenoop },
	/*::[*/0x0247/*::]*/: { n:"BrtSupNameNil", f:parsenoop },
	/*::[*/0x0248/*::]*/: { n:"BrtSupNameBool", f:parsenoop },
	/*::[*/0x0249/*::]*/: { n:"BrtSupNameFmla", f:parsenoop },
	/*::[*/0x024A/*::]*/: { n:"BrtSupNameBits", f:parsenoop },
	/*::[*/0x024B/*::]*/: { n:"BrtSupNameEnd", f:parsenoop },
	/*::[*/0x024C/*::]*/: { n:"BrtEndSupBook", f:parsenoop },
	/*::[*/0x024D/*::]*/: { n:"BrtCellSmartTagProperty", f:parsenoop },
	/*::[*/0x024E/*::]*/: { n:"BrtBeginCellSmartTag", f:parsenoop },
	/*::[*/0x024F/*::]*/: { n:"BrtEndCellSmartTag", f:parsenoop },
	/*::[*/0x0250/*::]*/: { n:"BrtBeginCellSmartTags", f:parsenoop },
	/*::[*/0x0251/*::]*/: { n:"BrtEndCellSmartTags", f:parsenoop },
	/*::[*/0x0252/*::]*/: { n:"BrtBeginSmartTags", f:parsenoop },
	/*::[*/0x0253/*::]*/: { n:"BrtEndSmartTags", f:parsenoop },
	/*::[*/0x0254/*::]*/: { n:"BrtSmartTagType", f:parsenoop },
	/*::[*/0x0255/*::]*/: { n:"BrtBeginSmartTagTypes", f:parsenoop },
	/*::[*/0x0256/*::]*/: { n:"BrtEndSmartTagTypes", f:parsenoop },
	/*::[*/0x0257/*::]*/: { n:"BrtBeginSXFilters", f:parsenoop },
	/*::[*/0x0258/*::]*/: { n:"BrtEndSXFilters", f:parsenoop },
	/*::[*/0x0259/*::]*/: { n:"BrtBeginSXFILTER", f:parsenoop },
	/*::[*/0x025A/*::]*/: { n:"BrtEndSXFilter", f:parsenoop },
	/*::[*/0x025B/*::]*/: { n:"BrtBeginFills", f:parsenoop },
	/*::[*/0x025C/*::]*/: { n:"BrtEndFills", f:parsenoop },
	/*::[*/0x025D/*::]*/: { n:"BrtBeginCellWatches", f:parsenoop },
	/*::[*/0x025E/*::]*/: { n:"BrtEndCellWatches", f:parsenoop },
	/*::[*/0x025F/*::]*/: { n:"BrtCellWatch", f:parsenoop },
	/*::[*/0x0260/*::]*/: { n:"BrtBeginCRErrs", f:parsenoop },
	/*::[*/0x0261/*::]*/: { n:"BrtEndCRErrs", f:parsenoop },
	/*::[*/0x0262/*::]*/: { n:"BrtCrashRecErr", f:parsenoop },
	/*::[*/0x0263/*::]*/: { n:"BrtBeginFonts", f:parsenoop },
	/*::[*/0x0264/*::]*/: { n:"BrtEndFonts", f:parsenoop },
	/*::[*/0x0265/*::]*/: { n:"BrtBeginBorders", f:parsenoop },
	/*::[*/0x0266/*::]*/: { n:"BrtEndBorders", f:parsenoop },
	/*::[*/0x0267/*::]*/: { n:"BrtBeginFmts", f:parsenoop },
	/*::[*/0x0268/*::]*/: { n:"BrtEndFmts", f:parsenoop },
	/*::[*/0x0269/*::]*/: { n:"BrtBeginCellXFs", f:parsenoop },
	/*::[*/0x026A/*::]*/: { n:"BrtEndCellXFs", f:parsenoop },
	/*::[*/0x026B/*::]*/: { n:"BrtBeginStyles", f:parsenoop },
	/*::[*/0x026C/*::]*/: { n:"BrtEndStyles", f:parsenoop },
	/*::[*/0x0271/*::]*/: { n:"BrtBigName", f:parsenoop },
	/*::[*/0x0272/*::]*/: { n:"BrtBeginCellStyleXFs", f:parsenoop },
	/*::[*/0x0273/*::]*/: { n:"BrtEndCellStyleXFs", f:parsenoop },
	/*::[*/0x0274/*::]*/: { n:"BrtBeginComments", f:parsenoop },
	/*::[*/0x0275/*::]*/: { n:"BrtEndComments", f:parsenoop },
	/*::[*/0x0276/*::]*/: { n:"BrtBeginCommentAuthors", f:parsenoop },
	/*::[*/0x0277/*::]*/: { n:"BrtEndCommentAuthors", f:parsenoop },
	/*::[*/0x0278/*::]*/: { n:"BrtCommentAuthor", f:parse_BrtCommentAuthor },
	/*::[*/0x0279/*::]*/: { n:"BrtBeginCommentList", f:parsenoop },
	/*::[*/0x027A/*::]*/: { n:"BrtEndCommentList", f:parsenoop },
	/*::[*/0x027B/*::]*/: { n:"BrtBeginComment", f:parse_BrtBeginComment},
	/*::[*/0x027C/*::]*/: { n:"BrtEndComment", f:parsenoop },
	/*::[*/0x027D/*::]*/: { n:"BrtCommentText", f:parse_BrtCommentText },
	/*::[*/0x027E/*::]*/: { n:"BrtBeginOleObjects", f:parsenoop },
	/*::[*/0x027F/*::]*/: { n:"BrtOleObject", f:parsenoop },
	/*::[*/0x0280/*::]*/: { n:"BrtEndOleObjects", f:parsenoop },
	/*::[*/0x0281/*::]*/: { n:"BrtBeginSxrules", f:parsenoop },
	/*::[*/0x0282/*::]*/: { n:"BrtEndSxRules", f:parsenoop },
	/*::[*/0x0283/*::]*/: { n:"BrtBeginActiveXControls", f:parsenoop },
	/*::[*/0x0284/*::]*/: { n:"BrtActiveX", f:parsenoop },
	/*::[*/0x0285/*::]*/: { n:"BrtEndActiveXControls", f:parsenoop },
	/*::[*/0x0286/*::]*/: { n:"BrtBeginPCDSDTCEMembersSortBy", f:parsenoop },
	/*::[*/0x0288/*::]*/: { n:"BrtBeginCellIgnoreECs", f:parsenoop },
	/*::[*/0x0289/*::]*/: { n:"BrtCellIgnoreEC", f:parsenoop },
	/*::[*/0x028A/*::]*/: { n:"BrtEndCellIgnoreECs", f:parsenoop },
	/*::[*/0x028B/*::]*/: { n:"BrtCsProp", f:parsenoop },
	/*::[*/0x028C/*::]*/: { n:"BrtCsPageSetup", f:parsenoop },
	/*::[*/0x028D/*::]*/: { n:"BrtBeginUserCsViews", f:parsenoop },
	/*::[*/0x028E/*::]*/: { n:"BrtEndUserCsViews", f:parsenoop },
	/*::[*/0x028F/*::]*/: { n:"BrtBeginUserCsView", f:parsenoop },
	/*::[*/0x0290/*::]*/: { n:"BrtEndUserCsView", f:parsenoop },
	/*::[*/0x0291/*::]*/: { n:"BrtBeginPcdSFCIEntries", f:parsenoop },
	/*::[*/0x0292/*::]*/: { n:"BrtEndPCDSFCIEntries", f:parsenoop },
	/*::[*/0x0293/*::]*/: { n:"BrtPCDSFCIEntry", f:parsenoop },
	/*::[*/0x0294/*::]*/: { n:"BrtBeginListParts", f:parsenoop },
	/*::[*/0x0295/*::]*/: { n:"BrtListPart", f:parsenoop },
	/*::[*/0x0296/*::]*/: { n:"BrtEndListParts", f:parsenoop },
	/*::[*/0x0297/*::]*/: { n:"BrtSheetCalcProp", f:parsenoop },
	/*::[*/0x0298/*::]*/: { n:"BrtBeginFnGroup", f:parsenoop },
	/*::[*/0x0299/*::]*/: { n:"BrtFnGroup", f:parsenoop },
	/*::[*/0x029A/*::]*/: { n:"BrtEndFnGroup", f:parsenoop },
	/*::[*/0x029B/*::]*/: { n:"BrtSupAddin", f:parsenoop },
	/*::[*/0x029C/*::]*/: { n:"BrtSXTDMPOrder", f:parsenoop },
	/*::[*/0x029D/*::]*/: { n:"BrtCsProtection", f:parsenoop },
	/*::[*/0x029F/*::]*/: { n:"BrtBeginWsSortMap", f:parsenoop },
	/*::[*/0x02A0/*::]*/: { n:"BrtEndWsSortMap", f:parsenoop },
	/*::[*/0x02A1/*::]*/: { n:"BrtBeginRRSort", f:parsenoop },
	/*::[*/0x02A2/*::]*/: { n:"BrtEndRRSort", f:parsenoop },
	/*::[*/0x02A3/*::]*/: { n:"BrtRRSortItem", f:parsenoop },
	/*::[*/0x02A4/*::]*/: { n:"BrtFileSharingIso", f:parsenoop },
	/*::[*/0x02A5/*::]*/: { n:"BrtBookProtectionIso", f:parsenoop },
	/*::[*/0x02A6/*::]*/: { n:"BrtSheetProtectionIso", f:parsenoop },
	/*::[*/0x02A7/*::]*/: { n:"BrtCsProtectionIso", f:parsenoop },
	/*::[*/0x02A8/*::]*/: { n:"BrtRangeProtectionIso", f:parsenoop },
	/*::[*/0x0400/*::]*/: { n:"BrtRwDescent", f:parsenoop },
	/*::[*/0x0401/*::]*/: { n:"BrtKnownFonts", f:parsenoop },
	/*::[*/0x0402/*::]*/: { n:"BrtBeginSXTupleSet", f:parsenoop },
	/*::[*/0x0403/*::]*/: { n:"BrtEndSXTupleSet", f:parsenoop },
	/*::[*/0x0404/*::]*/: { n:"BrtBeginSXTupleSetHeader", f:parsenoop },
	/*::[*/0x0405/*::]*/: { n:"BrtEndSXTupleSetHeader", f:parsenoop },
	/*::[*/0x0406/*::]*/: { n:"BrtSXTupleSetHeaderItem", f:parsenoop },
	/*::[*/0x0407/*::]*/: { n:"BrtBeginSXTupleSetData", f:parsenoop },
	/*::[*/0x0408/*::]*/: { n:"BrtEndSXTupleSetData", f:parsenoop },
	/*::[*/0x0409/*::]*/: { n:"BrtBeginSXTupleSetRow", f:parsenoop },
	/*::[*/0x040A/*::]*/: { n:"BrtEndSXTupleSetRow", f:parsenoop },
	/*::[*/0x040B/*::]*/: { n:"BrtSXTupleSetRowItem", f:parsenoop },
	/*::[*/0x040C/*::]*/: { n:"BrtNameExt", f:parsenoop },
	/*::[*/0x040D/*::]*/: { n:"BrtPCDH14", f:parsenoop },
	/*::[*/0x040E/*::]*/: { n:"BrtBeginPCDCalcMem14", f:parsenoop },
	/*::[*/0x040F/*::]*/: { n:"BrtEndPCDCalcMem14", f:parsenoop },
	/*::[*/0x0410/*::]*/: { n:"BrtSXTH14", f:parsenoop },
	/*::[*/0x0411/*::]*/: { n:"BrtBeginSparklineGroup", f:parsenoop },
	/*::[*/0x0412/*::]*/: { n:"BrtEndSparklineGroup", f:parsenoop },
	/*::[*/0x0413/*::]*/: { n:"BrtSparkline", f:parsenoop },
	/*::[*/0x0414/*::]*/: { n:"BrtSXDI14", f:parsenoop },
	/*::[*/0x0415/*::]*/: { n:"BrtWsFmtInfoEx14", f:parsenoop },
	/*::[*/0x0416/*::]*/: { n:"BrtBeginConditionalFormatting14", f:parsenoop },
	/*::[*/0x0417/*::]*/: { n:"BrtEndConditionalFormatting14", f:parsenoop },
	/*::[*/0x0418/*::]*/: { n:"BrtBeginCFRule14", f:parsenoop },
	/*::[*/0x0419/*::]*/: { n:"BrtEndCFRule14", f:parsenoop },
	/*::[*/0x041A/*::]*/: { n:"BrtCFVO14", f:parsenoop },
	/*::[*/0x041B/*::]*/: { n:"BrtBeginDatabar14", f:parsenoop },
	/*::[*/0x041C/*::]*/: { n:"BrtBeginIconSet14", f:parsenoop },
	/*::[*/0x041D/*::]*/: { n:"BrtDVal14", f:parsenoop },
	/*::[*/0x041E/*::]*/: { n:"BrtBeginDVals14", f:parsenoop },
	/*::[*/0x041F/*::]*/: { n:"BrtColor14", f:parsenoop },
	/*::[*/0x0420/*::]*/: { n:"BrtBeginSparklines", f:parsenoop },
	/*::[*/0x0421/*::]*/: { n:"BrtEndSparklines", f:parsenoop },
	/*::[*/0x0422/*::]*/: { n:"BrtBeginSparklineGroups", f:parsenoop },
	/*::[*/0x0423/*::]*/: { n:"BrtEndSparklineGroups", f:parsenoop },
	/*::[*/0x0425/*::]*/: { n:"BrtSXVD14", f:parsenoop },
	/*::[*/0x0426/*::]*/: { n:"BrtBeginSxview14", f:parsenoop },
	/*::[*/0x0427/*::]*/: { n:"BrtEndSxview14", f:parsenoop },
	/*::[*/0x042A/*::]*/: { n:"BrtBeginPCD14", f:parsenoop },
	/*::[*/0x042B/*::]*/: { n:"BrtEndPCD14", f:parsenoop },
	/*::[*/0x042C/*::]*/: { n:"BrtBeginExtConn14", f:parsenoop },
	/*::[*/0x042D/*::]*/: { n:"BrtEndExtConn14", f:parsenoop },
	/*::[*/0x042E/*::]*/: { n:"BrtBeginSlicerCacheIDs", f:parsenoop },
	/*::[*/0x042F/*::]*/: { n:"BrtEndSlicerCacheIDs", f:parsenoop },
	/*::[*/0x0430/*::]*/: { n:"BrtBeginSlicerCacheID", f:parsenoop },
	/*::[*/0x0431/*::]*/: { n:"BrtEndSlicerCacheID", f:parsenoop },
	/*::[*/0x0433/*::]*/: { n:"BrtBeginSlicerCache", f:parsenoop },
	/*::[*/0x0434/*::]*/: { n:"BrtEndSlicerCache", f:parsenoop },
	/*::[*/0x0435/*::]*/: { n:"BrtBeginSlicerCacheDef", f:parsenoop },
	/*::[*/0x0436/*::]*/: { n:"BrtEndSlicerCacheDef", f:parsenoop },
	/*::[*/0x0437/*::]*/: { n:"BrtBeginSlicersEx", f:parsenoop },
	/*::[*/0x0438/*::]*/: { n:"BrtEndSlicersEx", f:parsenoop },
	/*::[*/0x0439/*::]*/: { n:"BrtBeginSlicerEx", f:parsenoop },
	/*::[*/0x043A/*::]*/: { n:"BrtEndSlicerEx", f:parsenoop },
	/*::[*/0x043B/*::]*/: { n:"BrtBeginSlicer", f:parsenoop },
	/*::[*/0x043C/*::]*/: { n:"BrtEndSlicer", f:parsenoop },
	/*::[*/0x043D/*::]*/: { n:"BrtSlicerCachePivotTables", f:parsenoop },
	/*::[*/0x043E/*::]*/: { n:"BrtBeginSlicerCacheOlapImpl", f:parsenoop },
	/*::[*/0x043F/*::]*/: { n:"BrtEndSlicerCacheOlapImpl", f:parsenoop },
	/*::[*/0x0440/*::]*/: { n:"BrtBeginSlicerCacheLevelsData", f:parsenoop },
	/*::[*/0x0441/*::]*/: { n:"BrtEndSlicerCacheLevelsData", f:parsenoop },
	/*::[*/0x0442/*::]*/: { n:"BrtBeginSlicerCacheLevelData", f:parsenoop },
	/*::[*/0x0443/*::]*/: { n:"BrtEndSlicerCacheLevelData", f:parsenoop },
	/*::[*/0x0444/*::]*/: { n:"BrtBeginSlicerCacheSiRanges", f:parsenoop },
	/*::[*/0x0445/*::]*/: { n:"BrtEndSlicerCacheSiRanges", f:parsenoop },
	/*::[*/0x0446/*::]*/: { n:"BrtBeginSlicerCacheSiRange", f:parsenoop },
	/*::[*/0x0447/*::]*/: { n:"BrtEndSlicerCacheSiRange", f:parsenoop },
	/*::[*/0x0448/*::]*/: { n:"BrtSlicerCacheOlapItem", f:parsenoop },
	/*::[*/0x0449/*::]*/: { n:"BrtBeginSlicerCacheSelections", f:parsenoop },
	/*::[*/0x044A/*::]*/: { n:"BrtSlicerCacheSelection", f:parsenoop },
	/*::[*/0x044B/*::]*/: { n:"BrtEndSlicerCacheSelections", f:parsenoop },
	/*::[*/0x044C/*::]*/: { n:"BrtBeginSlicerCacheNative", f:parsenoop },
	/*::[*/0x044D/*::]*/: { n:"BrtEndSlicerCacheNative", f:parsenoop },
	/*::[*/0x044E/*::]*/: { n:"BrtSlicerCacheNativeItem", f:parsenoop },
	/*::[*/0x044F/*::]*/: { n:"BrtRangeProtection14", f:parsenoop },
	/*::[*/0x0450/*::]*/: { n:"BrtRangeProtectionIso14", f:parsenoop },
	/*::[*/0x0451/*::]*/: { n:"BrtCellIgnoreEC14", f:parsenoop },
	/*::[*/0x0457/*::]*/: { n:"BrtList14", f:parsenoop },
	/*::[*/0x0458/*::]*/: { n:"BrtCFIcon", f:parsenoop },
	/*::[*/0x0459/*::]*/: { n:"BrtBeginSlicerCachesPivotCacheIDs", f:parsenoop },
	/*::[*/0x045A/*::]*/: { n:"BrtEndSlicerCachesPivotCacheIDs", f:parsenoop },
	/*::[*/0x045B/*::]*/: { n:"BrtBeginSlicers", f:parsenoop },
	/*::[*/0x045C/*::]*/: { n:"BrtEndSlicers", f:parsenoop },
	/*::[*/0x045D/*::]*/: { n:"BrtWbProp14", f:parsenoop },
	/*::[*/0x045E/*::]*/: { n:"BrtBeginSXEdit", f:parsenoop },
	/*::[*/0x045F/*::]*/: { n:"BrtEndSXEdit", f:parsenoop },
	/*::[*/0x0460/*::]*/: { n:"BrtBeginSXEdits", f:parsenoop },
	/*::[*/0x0461/*::]*/: { n:"BrtEndSXEdits", f:parsenoop },
	/*::[*/0x0462/*::]*/: { n:"BrtBeginSXChange", f:parsenoop },
	/*::[*/0x0463/*::]*/: { n:"BrtEndSXChange", f:parsenoop },
	/*::[*/0x0464/*::]*/: { n:"BrtBeginSXChanges", f:parsenoop },
	/*::[*/0x0465/*::]*/: { n:"BrtEndSXChanges", f:parsenoop },
	/*::[*/0x0466/*::]*/: { n:"BrtSXTupleItems", f:parsenoop },
	/*::[*/0x0468/*::]*/: { n:"BrtBeginSlicerStyle", f:parsenoop },
	/*::[*/0x0469/*::]*/: { n:"BrtEndSlicerStyle", f:parsenoop },
	/*::[*/0x046A/*::]*/: { n:"BrtSlicerStyleElement", f:parsenoop },
	/*::[*/0x046B/*::]*/: { n:"BrtBeginStyleSheetExt14", f:parsenoop },
	/*::[*/0x046C/*::]*/: { n:"BrtEndStyleSheetExt14", f:parsenoop },
	/*::[*/0x046D/*::]*/: { n:"BrtBeginSlicerCachesPivotCacheID", f:parsenoop },
	/*::[*/0x046E/*::]*/: { n:"BrtEndSlicerCachesPivotCacheID", f:parsenoop },
	/*::[*/0x046F/*::]*/: { n:"BrtBeginConditionalFormattings", f:parsenoop },
	/*::[*/0x0470/*::]*/: { n:"BrtEndConditionalFormattings", f:parsenoop },
	/*::[*/0x0471/*::]*/: { n:"BrtBeginPCDCalcMemExt", f:parsenoop },
	/*::[*/0x0472/*::]*/: { n:"BrtEndPCDCalcMemExt", f:parsenoop },
	/*::[*/0x0473/*::]*/: { n:"BrtBeginPCDCalcMemsExt", f:parsenoop },
	/*::[*/0x0474/*::]*/: { n:"BrtEndPCDCalcMemsExt", f:parsenoop },
	/*::[*/0x0475/*::]*/: { n:"BrtPCDField14", f:parsenoop },
	/*::[*/0x0476/*::]*/: { n:"BrtBeginSlicerStyles", f:parsenoop },
	/*::[*/0x0477/*::]*/: { n:"BrtEndSlicerStyles", f:parsenoop },
	/*::[*/0x0478/*::]*/: { n:"BrtBeginSlicerStyleElements", f:parsenoop },
	/*::[*/0x0479/*::]*/: { n:"BrtEndSlicerStyleElements", f:parsenoop },
	/*::[*/0x047A/*::]*/: { n:"BrtCFRuleExt", f:parsenoop },
	/*::[*/0x047B/*::]*/: { n:"BrtBeginSXCondFmt14", f:parsenoop },
	/*::[*/0x047C/*::]*/: { n:"BrtEndSXCondFmt14", f:parsenoop },
	/*::[*/0x047D/*::]*/: { n:"BrtBeginSXCondFmts14", f:parsenoop },
	/*::[*/0x047E/*::]*/: { n:"BrtEndSXCondFmts14", f:parsenoop },
	/*::[*/0x0480/*::]*/: { n:"BrtBeginSortCond14", f:parsenoop },
	/*::[*/0x0481/*::]*/: { n:"BrtEndSortCond14", f:parsenoop },
	/*::[*/0x0482/*::]*/: { n:"BrtEndDVals14", f:parsenoop },
	/*::[*/0x0483/*::]*/: { n:"BrtEndIconSet14", f:parsenoop },
	/*::[*/0x0484/*::]*/: { n:"BrtEndDatabar14", f:parsenoop },
	/*::[*/0x0485/*::]*/: { n:"BrtBeginColorScale14", f:parsenoop },
	/*::[*/0x0486/*::]*/: { n:"BrtEndColorScale14", f:parsenoop },
	/*::[*/0x0487/*::]*/: { n:"BrtBeginSxrules14", f:parsenoop },
	/*::[*/0x0488/*::]*/: { n:"BrtEndSxrules14", f:parsenoop },
	/*::[*/0x0489/*::]*/: { n:"BrtBeginPRule14", f:parsenoop },
	/*::[*/0x048A/*::]*/: { n:"BrtEndPRule14", f:parsenoop },
	/*::[*/0x048B/*::]*/: { n:"BrtBeginPRFilters14", f:parsenoop },
	/*::[*/0x048C/*::]*/: { n:"BrtEndPRFilters14", f:parsenoop },
	/*::[*/0x048D/*::]*/: { n:"BrtBeginPRFilter14", f:parsenoop },
	/*::[*/0x048E/*::]*/: { n:"BrtEndPRFilter14", f:parsenoop },
	/*::[*/0x048F/*::]*/: { n:"BrtBeginPRFItem14", f:parsenoop },
	/*::[*/0x0490/*::]*/: { n:"BrtEndPRFItem14", f:parsenoop },
	/*::[*/0x0491/*::]*/: { n:"BrtBeginCellIgnoreECs14", f:parsenoop },
	/*::[*/0x0492/*::]*/: { n:"BrtEndCellIgnoreECs14", f:parsenoop },
	/*::[*/0x0493/*::]*/: { n:"BrtDxf14", f:parsenoop },
	/*::[*/0x0494/*::]*/: { n:"BrtBeginDxF14s", f:parsenoop },
	/*::[*/0x0495/*::]*/: { n:"BrtEndDxf14s", f:parsenoop },
	/*::[*/0x0499/*::]*/: { n:"BrtFilter14", f:parsenoop },
	/*::[*/0x049A/*::]*/: { n:"BrtBeginCustomFilters14", f:parsenoop },
	/*::[*/0x049C/*::]*/: { n:"BrtCustomFilter14", f:parsenoop },
	/*::[*/0x049D/*::]*/: { n:"BrtIconFilter14", f:parsenoop },
	/*::[*/0x049E/*::]*/: { n:"BrtPivotCacheConnectionName", f:parsenoop },
	/*::[*/0x0800/*::]*/: { n:"BrtBeginDecoupledPivotCacheIDs", f:parsenoop },
	/*::[*/0x0801/*::]*/: { n:"BrtEndDecoupledPivotCacheIDs", f:parsenoop },
	/*::[*/0x0802/*::]*/: { n:"BrtDecoupledPivotCacheID", f:parsenoop },
	/*::[*/0x0803/*::]*/: { n:"BrtBeginPivotTableRefs", f:parsenoop },
	/*::[*/0x0804/*::]*/: { n:"BrtEndPivotTableRefs", f:parsenoop },
	/*::[*/0x0805/*::]*/: { n:"BrtPivotTableRef", f:parsenoop },
	/*::[*/0x0806/*::]*/: { n:"BrtSlicerCacheBookPivotTables", f:parsenoop },
	/*::[*/0x0807/*::]*/: { n:"BrtBeginSxvcells", f:parsenoop },
	/*::[*/0x0808/*::]*/: { n:"BrtEndSxvcells", f:parsenoop },
	/*::[*/0x0809/*::]*/: { n:"BrtBeginSxRow", f:parsenoop },
	/*::[*/0x080A/*::]*/: { n:"BrtEndSxRow", f:parsenoop },
	/*::[*/0x080C/*::]*/: { n:"BrtPcdCalcMem15", f:parsenoop },
	/*::[*/0x0813/*::]*/: { n:"BrtQsi15", f:parsenoop },
	/*::[*/0x0814/*::]*/: { n:"BrtBeginWebExtensions", f:parsenoop },
	/*::[*/0x0815/*::]*/: { n:"BrtEndWebExtensions", f:parsenoop },
	/*::[*/0x0816/*::]*/: { n:"BrtWebExtension", f:parsenoop },
	/*::[*/0x0817/*::]*/: { n:"BrtAbsPath15", f:parsenoop },
	/*::[*/0x0818/*::]*/: { n:"BrtBeginPivotTableUISettings", f:parsenoop },
	/*::[*/0x0819/*::]*/: { n:"BrtEndPivotTableUISettings", f:parsenoop },
	/*::[*/0x081B/*::]*/: { n:"BrtTableSlicerCacheIDs", f:parsenoop },
	/*::[*/0x081C/*::]*/: { n:"BrtTableSlicerCacheID", f:parsenoop },
	/*::[*/0x081D/*::]*/: { n:"BrtBeginTableSlicerCache", f:parsenoop },
	/*::[*/0x081E/*::]*/: { n:"BrtEndTableSlicerCache", f:parsenoop },
	/*::[*/0x081F/*::]*/: { n:"BrtSxFilter15", f:parsenoop },
	/*::[*/0x0820/*::]*/: { n:"BrtBeginTimelineCachePivotCacheIDs", f:parsenoop },
	/*::[*/0x0821/*::]*/: { n:"BrtEndTimelineCachePivotCacheIDs", f:parsenoop },
	/*::[*/0x0822/*::]*/: { n:"BrtTimelineCachePivotCacheID", f:parsenoop },
	/*::[*/0x0823/*::]*/: { n:"BrtBeginTimelineCacheIDs", f:parsenoop },
	/*::[*/0x0824/*::]*/: { n:"BrtEndTimelineCacheIDs", f:parsenoop },
	/*::[*/0x0825/*::]*/: { n:"BrtBeginTimelineCacheID", f:parsenoop },
	/*::[*/0x0826/*::]*/: { n:"BrtEndTimelineCacheID", f:parsenoop },
	/*::[*/0x0827/*::]*/: { n:"BrtBeginTimelinesEx", f:parsenoop },
	/*::[*/0x0828/*::]*/: { n:"BrtEndTimelinesEx", f:parsenoop },
	/*::[*/0x0829/*::]*/: { n:"BrtBeginTimelineEx", f:parsenoop },
	/*::[*/0x082A/*::]*/: { n:"BrtEndTimelineEx", f:parsenoop },
	/*::[*/0x082B/*::]*/: { n:"BrtWorkBookPr15", f:parsenoop },
	/*::[*/0x082C/*::]*/: { n:"BrtPCDH15", f:parsenoop },
	/*::[*/0x082D/*::]*/: { n:"BrtBeginTimelineStyle", f:parsenoop },
	/*::[*/0x082E/*::]*/: { n:"BrtEndTimelineStyle", f:parsenoop },
	/*::[*/0x082F/*::]*/: { n:"BrtTimelineStyleElement", f:parsenoop },
	/*::[*/0x0830/*::]*/: { n:"BrtBeginTimelineStylesheetExt15", f:parsenoop },
	/*::[*/0x0831/*::]*/: { n:"BrtEndTimelineStylesheetExt15", f:parsenoop },
	/*::[*/0x0832/*::]*/: { n:"BrtBeginTimelineStyles", f:parsenoop },
	/*::[*/0x0833/*::]*/: { n:"BrtEndTimelineStyles", f:parsenoop },
	/*::[*/0x0834/*::]*/: { n:"BrtBeginTimelineStyleElements", f:parsenoop },
	/*::[*/0x0835/*::]*/: { n:"BrtEndTimelineStyleElements", f:parsenoop },
	/*::[*/0x0836/*::]*/: { n:"BrtDxf15", f:parsenoop },
	/*::[*/0x0837/*::]*/: { n:"BrtBeginDxfs15", f:parsenoop },
	/*::[*/0x0838/*::]*/: { n:"brtEndDxfs15", f:parsenoop },
	/*::[*/0x0839/*::]*/: { n:"BrtSlicerCacheHideItemsWithNoData", f:parsenoop },
	/*::[*/0x083A/*::]*/: { n:"BrtBeginItemUniqueNames", f:parsenoop },
	/*::[*/0x083B/*::]*/: { n:"BrtEndItemUniqueNames", f:parsenoop },
	/*::[*/0x083C/*::]*/: { n:"BrtItemUniqueName", f:parsenoop },
	/*::[*/0x083D/*::]*/: { n:"BrtBeginExtConn15", f:parsenoop },
	/*::[*/0x083E/*::]*/: { n:"BrtEndExtConn15", f:parsenoop },
	/*::[*/0x083F/*::]*/: { n:"BrtBeginOledbPr15", f:parsenoop },
	/*::[*/0x0840/*::]*/: { n:"BrtEndOledbPr15", f:parsenoop },
	/*::[*/0x0841/*::]*/: { n:"BrtBeginDataFeedPr15", f:parsenoop },
	/*::[*/0x0842/*::]*/: { n:"BrtEndDataFeedPr15", f:parsenoop },
	/*::[*/0x0843/*::]*/: { n:"BrtTextPr15", f:parsenoop },
	/*::[*/0x0844/*::]*/: { n:"BrtRangePr15", f:parsenoop },
	/*::[*/0x0845/*::]*/: { n:"BrtDbCommand15", f:parsenoop },
	/*::[*/0x0846/*::]*/: { n:"BrtBeginDbTables15", f:parsenoop },
	/*::[*/0x0847/*::]*/: { n:"BrtEndDbTables15", f:parsenoop },
	/*::[*/0x0848/*::]*/: { n:"BrtDbTable15", f:parsenoop },
	/*::[*/0x0849/*::]*/: { n:"BrtBeginDataModel", f:parsenoop },
	/*::[*/0x084A/*::]*/: { n:"BrtEndDataModel", f:parsenoop },
	/*::[*/0x084B/*::]*/: { n:"BrtBeginModelTables", f:parsenoop },
	/*::[*/0x084C/*::]*/: { n:"BrtEndModelTables", f:parsenoop },
	/*::[*/0x084D/*::]*/: { n:"BrtModelTable", f:parsenoop },
	/*::[*/0x084E/*::]*/: { n:"BrtBeginModelRelationships", f:parsenoop },
	/*::[*/0x084F/*::]*/: { n:"BrtEndModelRelationships", f:parsenoop },
	/*::[*/0x0850/*::]*/: { n:"BrtModelRelationship", f:parsenoop },
	/*::[*/0x0851/*::]*/: { n:"BrtBeginECTxtWiz15", f:parsenoop },
	/*::[*/0x0852/*::]*/: { n:"BrtEndECTxtWiz15", f:parsenoop },
	/*::[*/0x0853/*::]*/: { n:"BrtBeginECTWFldInfoLst15", f:parsenoop },
	/*::[*/0x0854/*::]*/: { n:"BrtEndECTWFldInfoLst15", f:parsenoop },
	/*::[*/0x0855/*::]*/: { n:"BrtBeginECTWFldInfo15", f:parsenoop },
	/*::[*/0x0856/*::]*/: { n:"BrtFieldListActiveItem", f:parsenoop },
	/*::[*/0x0857/*::]*/: { n:"BrtPivotCacheIdVersion", f:parsenoop },
	/*::[*/0x0858/*::]*/: { n:"BrtSXDI15", f:parsenoop },
	/*::[*/0xFFFF/*::]*/: { n:"", f:parsenoop }
S
SheetJS 已提交
15838 15839 15840 15841 15842 15843
};

var evert_RE = evert_key(XLSBRecordEnum, 'n');

/* [MS-XLS] 2.3 Record Enumeration */
var XLSRecordEnum = {
S
SheetJS 已提交
15844 15845 15846 15847 15848 15849 15850 15851 15852 15853 15854 15855 15856 15857 15858 15859 15860 15861 15862 15863 15864 15865 15866 15867 15868 15869 15870 15871 15872 15873 15874 15875 15876 15877 15878 15879 15880 15881 15882 15883 15884 15885 15886 15887 15888 15889 15890 15891 15892 15893 15894 15895 15896 15897 15898 15899 15900 15901 15902 15903 15904 15905 15906 15907 15908 15909 15910 15911 15912 15913 15914 15915 15916 15917 15918 15919 15920 15921 15922 15923 15924 15925 15926 15927 15928 15929 15930 15931 15932 15933 15934 15935 15936 15937 15938 15939 15940 15941 15942 15943 15944 15945 15946 15947 15948 15949 15950 15951 15952 15953 15954 15955 15956 15957 15958 15959 15960 15961 15962 15963 15964 15965 15966 15967 15968 15969 15970 15971 15972 15973 15974 15975 15976 15977 15978 15979 15980 15981 15982 15983 15984 15985 15986 15987 15988 15989 15990 15991 15992 15993 15994 15995 15996 15997 15998 15999 16000 16001 16002 16003 16004 16005 16006 16007 16008 16009 16010 16011 16012 16013 16014 16015 16016 16017 16018 16019 16020 16021 16022 16023 16024 16025 16026 16027 16028 16029 16030 16031 16032 16033 16034 16035 16036
	/*::[*/0x0003/*::]*/: { n:"BIFF2NUM", f:parse_BIFF2NUM },
	/*::[*/0x0004/*::]*/: { n:"BIFF2STR", f:parse_BIFF2STR },
	/*::[*/0x0006/*::]*/: { n:"Formula", f:parse_Formula },
	/*::[*/0x0009/*::]*/: { n:'BOF', f:parse_BOF },
	/*::[*/0x000a/*::]*/: { n:'EOF', f:parse_EOF },
	/*::[*/0x000c/*::]*/: { n:"CalcCount", f:parse_CalcCount },
	/*::[*/0x000d/*::]*/: { n:"CalcMode", f:parse_CalcMode },
	/*::[*/0x000e/*::]*/: { n:"CalcPrecision", f:parse_CalcPrecision },
	/*::[*/0x000f/*::]*/: { n:"CalcRefMode", f:parse_CalcRefMode },
	/*::[*/0x0010/*::]*/: { n:"CalcDelta", f:parse_CalcDelta },
	/*::[*/0x0011/*::]*/: { n:"CalcIter", f:parse_CalcIter },
	/*::[*/0x0012/*::]*/: { n:"Protect", f:parse_Protect },
	/*::[*/0x0013/*::]*/: { n:"Password", f:parse_Password },
	/*::[*/0x0014/*::]*/: { n:"Header", f:parse_Header },
	/*::[*/0x0015/*::]*/: { n:"Footer", f:parse_Footer },
	/*::[*/0x0017/*::]*/: { n:"ExternSheet", f:parse_ExternSheet },
	/*::[*/0x0018/*::]*/: { n:"Lbl", f:parse_Lbl },
	/*::[*/0x0019/*::]*/: { n:"WinProtect", f:parse_WinProtect },
	/*::[*/0x001a/*::]*/: { n:"VerticalPageBreaks", f:parse_VerticalPageBreaks },
	/*::[*/0x001b/*::]*/: { n:"HorizontalPageBreaks", f:parse_HorizontalPageBreaks },
	/*::[*/0x001c/*::]*/: { n:"Note", f:parse_Note },
	/*::[*/0x001d/*::]*/: { n:"Selection", f:parse_Selection },
	/*::[*/0x0022/*::]*/: { n:"Date1904", f:parse_Date1904 },
	/*::[*/0x0023/*::]*/: { n:"ExternName", f:parse_ExternName },
	/*::[*/0x0026/*::]*/: { n:"LeftMargin", f:parse_LeftMargin },
	/*::[*/0x0027/*::]*/: { n:"RightMargin", f:parse_RightMargin },
	/*::[*/0x0028/*::]*/: { n:"TopMargin", f:parse_TopMargin },
	/*::[*/0x0029/*::]*/: { n:"BottomMargin", f:parse_BottomMargin },
	/*::[*/0x002a/*::]*/: { n:"PrintRowCol", f:parse_PrintRowCol },
	/*::[*/0x002b/*::]*/: { n:"PrintGrid", f:parse_PrintGrid },
	/*::[*/0x002f/*::]*/: { n:"FilePass", f:parse_FilePass },
	/*::[*/0x0031/*::]*/: { n:"Font", f:parse_Font },
	/*::[*/0x0033/*::]*/: { n:"PrintSize", f:parse_PrintSize },
	/*::[*/0x003c/*::]*/: { n:"Continue", f:parse_Continue },
	/*::[*/0x003d/*::]*/: { n:"Window1", f:parse_Window1 },
	/*::[*/0x0040/*::]*/: { n:"Backup", f:parse_Backup },
	/*::[*/0x0041/*::]*/: { n:"Pane", f:parse_Pane },
	/*::[*/0x0042/*::]*/: { n:'CodePage', f:parse_CodePage },
	/*::[*/0x004d/*::]*/: { n:"Pls", f:parse_Pls },
	/*::[*/0x0050/*::]*/: { n:"DCon", f:parse_DCon },
	/*::[*/0x0051/*::]*/: { n:"DConRef", f:parse_DConRef },
	/*::[*/0x0052/*::]*/: { n:"DConName", f:parse_DConName },
	/*::[*/0x0055/*::]*/: { n:"DefColWidth", f:parse_DefColWidth },
	/*::[*/0x0059/*::]*/: { n:"XCT", f:parse_XCT },
	/*::[*/0x005a/*::]*/: { n:"CRN", f:parse_CRN },
	/*::[*/0x005b/*::]*/: { n:"FileSharing", f:parse_FileSharing },
	/*::[*/0x005c/*::]*/: { n:'WriteAccess', f:parse_WriteAccess },
	/*::[*/0x005d/*::]*/: { n:"Obj", f:parse_Obj },
	/*::[*/0x005e/*::]*/: { n:"Uncalced", f:parse_Uncalced },
	/*::[*/0x005f/*::]*/: { n:"CalcSaveRecalc", f:parse_CalcSaveRecalc },
	/*::[*/0x0060/*::]*/: { n:"Template", f:parse_Template },
	/*::[*/0x0061/*::]*/: { n:"Intl", f:parse_Intl },
	/*::[*/0x0063/*::]*/: { n:"ObjProtect", f:parse_ObjProtect },
	/*::[*/0x007d/*::]*/: { n:"ColInfo", f:parse_ColInfo },
	/*::[*/0x0080/*::]*/: { n:"Guts", f:parse_Guts },
	/*::[*/0x0081/*::]*/: { n:"WsBool", f:parse_WsBool },
	/*::[*/0x0082/*::]*/: { n:"GridSet", f:parse_GridSet },
	/*::[*/0x0083/*::]*/: { n:"HCenter", f:parse_HCenter },
	/*::[*/0x0084/*::]*/: { n:"VCenter", f:parse_VCenter },
	/*::[*/0x0085/*::]*/: { n:'BoundSheet8', f:parse_BoundSheet8 },
	/*::[*/0x0086/*::]*/: { n:"WriteProtect", f:parse_WriteProtect },
	/*::[*/0x008c/*::]*/: { n:"Country", f:parse_Country },
	/*::[*/0x008d/*::]*/: { n:"HideObj", f:parse_HideObj },
	/*::[*/0x0090/*::]*/: { n:"Sort", f:parse_Sort },
	/*::[*/0x0092/*::]*/: { n:"Palette", f:parse_Palette },
	/*::[*/0x0097/*::]*/: { n:"Sync", f:parse_Sync },
	/*::[*/0x0098/*::]*/: { n:"LPr", f:parse_LPr },
	/*::[*/0x0099/*::]*/: { n:"DxGCol", f:parse_DxGCol },
	/*::[*/0x009a/*::]*/: { n:"FnGroupName", f:parse_FnGroupName },
	/*::[*/0x009b/*::]*/: { n:"FilterMode", f:parse_FilterMode },
	/*::[*/0x009c/*::]*/: { n:"BuiltInFnGroupCount", f:parse_BuiltInFnGroupCount },
	/*::[*/0x009d/*::]*/: { n:"AutoFilterInfo", f:parse_AutoFilterInfo },
	/*::[*/0x009e/*::]*/: { n:"AutoFilter", f:parse_AutoFilter },
	/*::[*/0x00a0/*::]*/: { n:"Scl", f:parse_Scl },
	/*::[*/0x00a1/*::]*/: { n:"Setup", f:parse_Setup },
	/*::[*/0x00ae/*::]*/: { n:"ScenMan", f:parse_ScenMan },
	/*::[*/0x00af/*::]*/: { n:"SCENARIO", f:parse_SCENARIO },
	/*::[*/0x00b0/*::]*/: { n:"SxView", f:parse_SxView },
	/*::[*/0x00b1/*::]*/: { n:"Sxvd", f:parse_Sxvd },
	/*::[*/0x00b2/*::]*/: { n:"SXVI", f:parse_SXVI },
	/*::[*/0x00b4/*::]*/: { n:"SxIvd", f:parse_SxIvd },
	/*::[*/0x00b5/*::]*/: { n:"SXLI", f:parse_SXLI },
	/*::[*/0x00b6/*::]*/: { n:"SXPI", f:parse_SXPI },
	/*::[*/0x00b8/*::]*/: { n:"DocRoute", f:parse_DocRoute },
	/*::[*/0x00b9/*::]*/: { n:"RecipName", f:parse_RecipName },
	/*::[*/0x00bd/*::]*/: { n:"MulRk", f:parse_MulRk },
	/*::[*/0x00be/*::]*/: { n:"MulBlank", f:parse_MulBlank },
	/*::[*/0x00c1/*::]*/: { n:'Mms', f:parse_Mms },
	/*::[*/0x00c5/*::]*/: { n:"SXDI", f:parse_SXDI },
	/*::[*/0x00c6/*::]*/: { n:"SXDB", f:parse_SXDB },
	/*::[*/0x00c7/*::]*/: { n:"SXFDB", f:parse_SXFDB },
	/*::[*/0x00c8/*::]*/: { n:"SXDBB", f:parse_SXDBB },
	/*::[*/0x00c9/*::]*/: { n:"SXNum", f:parse_SXNum },
	/*::[*/0x00ca/*::]*/: { n:"SxBool", f:parse_SxBool },
	/*::[*/0x00cb/*::]*/: { n:"SxErr", f:parse_SxErr },
	/*::[*/0x00cc/*::]*/: { n:"SXInt", f:parse_SXInt },
	/*::[*/0x00cd/*::]*/: { n:"SXString", f:parse_SXString },
	/*::[*/0x00ce/*::]*/: { n:"SXDtr", f:parse_SXDtr },
	/*::[*/0x00cf/*::]*/: { n:"SxNil", f:parse_SxNil },
	/*::[*/0x00d0/*::]*/: { n:"SXTbl", f:parse_SXTbl },
	/*::[*/0x00d1/*::]*/: { n:"SXTBRGIITM", f:parse_SXTBRGIITM },
	/*::[*/0x00d2/*::]*/: { n:"SxTbpg", f:parse_SxTbpg },
	/*::[*/0x00d3/*::]*/: { n:"ObProj", f:parse_ObProj },
	/*::[*/0x00d5/*::]*/: { n:"SXStreamID", f:parse_SXStreamID },
	/*::[*/0x00d7/*::]*/: { n:"DBCell", f:parse_DBCell },
	/*::[*/0x00d8/*::]*/: { n:"SXRng", f:parse_SXRng },
	/*::[*/0x00d9/*::]*/: { n:"SxIsxoper", f:parse_SxIsxoper },
	/*::[*/0x00da/*::]*/: { n:"BookBool", f:parse_BookBool },
	/*::[*/0x00dc/*::]*/: { n:"DbOrParamQry", f:parse_DbOrParamQry },
	/*::[*/0x00dd/*::]*/: { n:"ScenarioProtect", f:parse_ScenarioProtect },
	/*::[*/0x00de/*::]*/: { n:"OleObjectSize", f:parse_OleObjectSize },
	/*::[*/0x00e0/*::]*/: { n:"XF", f:parse_XF },
	/*::[*/0x00e1/*::]*/: { n:'InterfaceHdr', f:parse_InterfaceHdr },
	/*::[*/0x00e2/*::]*/: { n:'InterfaceEnd', f:parse_InterfaceEnd },
	/*::[*/0x00e3/*::]*/: { n:"SXVS", f:parse_SXVS },
	/*::[*/0x00e5/*::]*/: { n:"MergeCells", f:parse_MergeCells },
	/*::[*/0x00e9/*::]*/: { n:"BkHim", f:parse_BkHim },
	/*::[*/0x00eb/*::]*/: { n:"MsoDrawingGroup", f:parse_MsoDrawingGroup },
	/*::[*/0x00ec/*::]*/: { n:"MsoDrawing", f:parse_MsoDrawing },
	/*::[*/0x00ed/*::]*/: { n:"MsoDrawingSelection", f:parse_MsoDrawingSelection },
	/*::[*/0x00ef/*::]*/: { n:"PhoneticInfo", f:parse_PhoneticInfo },
	/*::[*/0x00f0/*::]*/: { n:"SxRule", f:parse_SxRule },
	/*::[*/0x00f1/*::]*/: { n:"SXEx", f:parse_SXEx },
	/*::[*/0x00f2/*::]*/: { n:"SxFilt", f:parse_SxFilt },
	/*::[*/0x00f4/*::]*/: { n:"SxDXF", f:parse_SxDXF },
	/*::[*/0x00f5/*::]*/: { n:"SxItm", f:parse_SxItm },
	/*::[*/0x00f6/*::]*/: { n:"SxName", f:parse_SxName },
	/*::[*/0x00f7/*::]*/: { n:"SxSelect", f:parse_SxSelect },
	/*::[*/0x00f8/*::]*/: { n:"SXPair", f:parse_SXPair },
	/*::[*/0x00f9/*::]*/: { n:"SxFmla", f:parse_SxFmla },
	/*::[*/0x00fb/*::]*/: { n:"SxFormat", f:parse_SxFormat },
	/*::[*/0x00fc/*::]*/: { n:"SST", f:parse_SST },
	/*::[*/0x00fd/*::]*/: { n:"LabelSst", f:parse_LabelSst },
	/*::[*/0x00ff/*::]*/: { n:"ExtSST", f:parse_ExtSST },
	/*::[*/0x0100/*::]*/: { n:"SXVDEx", f:parse_SXVDEx },
	/*::[*/0x0103/*::]*/: { n:"SXFormula", f:parse_SXFormula },
	/*::[*/0x0122/*::]*/: { n:"SXDBEx", f:parse_SXDBEx },
	/*::[*/0x0137/*::]*/: { n:"RRDInsDel", f:parse_RRDInsDel },
	/*::[*/0x0138/*::]*/: { n:"RRDHead", f:parse_RRDHead },
	/*::[*/0x013b/*::]*/: { n:"RRDChgCell", f:parse_RRDChgCell },
	/*::[*/0x013d/*::]*/: { n:"RRTabId", f:parse_RRTabId },
	/*::[*/0x013e/*::]*/: { n:"RRDRenSheet", f:parse_RRDRenSheet },
	/*::[*/0x013f/*::]*/: { n:"RRSort", f:parse_RRSort },
	/*::[*/0x0140/*::]*/: { n:"RRDMove", f:parse_RRDMove },
	/*::[*/0x014a/*::]*/: { n:"RRFormat", f:parse_RRFormat },
	/*::[*/0x014b/*::]*/: { n:"RRAutoFmt", f:parse_RRAutoFmt },
	/*::[*/0x014d/*::]*/: { n:"RRInsertSh", f:parse_RRInsertSh },
	/*::[*/0x014e/*::]*/: { n:"RRDMoveBegin", f:parse_RRDMoveBegin },
	/*::[*/0x014f/*::]*/: { n:"RRDMoveEnd", f:parse_RRDMoveEnd },
	/*::[*/0x0150/*::]*/: { n:"RRDInsDelBegin", f:parse_RRDInsDelBegin },
	/*::[*/0x0151/*::]*/: { n:"RRDInsDelEnd", f:parse_RRDInsDelEnd },
	/*::[*/0x0152/*::]*/: { n:"RRDConflict", f:parse_RRDConflict },
	/*::[*/0x0153/*::]*/: { n:"RRDDefName", f:parse_RRDDefName },
	/*::[*/0x0154/*::]*/: { n:"RRDRstEtxp", f:parse_RRDRstEtxp },
	/*::[*/0x015f/*::]*/: { n:"LRng", f:parse_LRng },
	/*::[*/0x0160/*::]*/: { n:"UsesELFs", f:parse_UsesELFs },
	/*::[*/0x0161/*::]*/: { n:"DSF", f:parse_DSF },
	/*::[*/0x0191/*::]*/: { n:"CUsr", f:parse_CUsr },
	/*::[*/0x0192/*::]*/: { n:"CbUsr", f:parse_CbUsr },
	/*::[*/0x0193/*::]*/: { n:"UsrInfo", f:parse_UsrInfo },
	/*::[*/0x0194/*::]*/: { n:"UsrExcl", f:parse_UsrExcl },
	/*::[*/0x0195/*::]*/: { n:"FileLock", f:parse_FileLock },
	/*::[*/0x0196/*::]*/: { n:"RRDInfo", f:parse_RRDInfo },
	/*::[*/0x0197/*::]*/: { n:"BCUsrs", f:parse_BCUsrs },
	/*::[*/0x0198/*::]*/: { n:"UsrChk", f:parse_UsrChk },
	/*::[*/0x01a9/*::]*/: { n:"UserBView", f:parse_UserBView },
	/*::[*/0x01aa/*::]*/: { n:"UserSViewBegin", f:parse_UserSViewBegin },
	/*::[*/0x01ab/*::]*/: { n:"UserSViewEnd", f:parse_UserSViewEnd },
	/*::[*/0x01ac/*::]*/: { n:"RRDUserView", f:parse_RRDUserView },
	/*::[*/0x01ad/*::]*/: { n:"Qsi", f:parse_Qsi },
	/*::[*/0x01ae/*::]*/: { n:"SupBook", f:parse_SupBook },
	/*::[*/0x01af/*::]*/: { n:"Prot4Rev", f:parse_Prot4Rev },
	/*::[*/0x01b0/*::]*/: { n:"CondFmt", f:parse_CondFmt },
	/*::[*/0x01b1/*::]*/: { n:"CF", f:parse_CF },
	/*::[*/0x01b2/*::]*/: { n:"DVal", f:parse_DVal },
	/*::[*/0x01b5/*::]*/: { n:"DConBin", f:parse_DConBin },
	/*::[*/0x01b6/*::]*/: { n:"TxO", f:parse_TxO },
	/*::[*/0x01b7/*::]*/: { n:"RefreshAll", f:parse_RefreshAll },
	/*::[*/0x01b8/*::]*/: { n:"HLink", f:parse_HLink },
	/*::[*/0x01b9/*::]*/: { n:"Lel", f:parse_Lel },
	/*::[*/0x01ba/*::]*/: { n:"CodeName", f:parse_XLSCodeName },
	/*::[*/0x01bb/*::]*/: { n:"SXFDBType", f:parse_SXFDBType },
	/*::[*/0x01bc/*::]*/: { n:"Prot4RevPass", f:parse_Prot4RevPass },
	/*::[*/0x01bd/*::]*/: { n:"ObNoMacros", f:parse_ObNoMacros },
	/*::[*/0x01be/*::]*/: { n:"Dv", f:parse_Dv },
	/*::[*/0x01c0/*::]*/: { n:"Excel9File", f:parse_Excel9File },
	/*::[*/0x01c1/*::]*/: { n:"RecalcId", f:parse_RecalcId, r:2},
	/*::[*/0x01c2/*::]*/: { n:"EntExU2", f:parse_EntExU2 },
	/*::[*/0x0200/*::]*/: { n:"Dimensions", f:parse_Dimensions },
	/*::[*/0x0201/*::]*/: { n:"Blank", f:parse_Blank },
	/*::[*/0x0203/*::]*/: { n:"Number", f:parse_Number },
	/*::[*/0x0204/*::]*/: { n:"Label", f:parse_Label },
	/*::[*/0x0205/*::]*/: { n:"BoolErr", f:parse_BoolErr },
S
SheetJS 已提交
16037
	/*::[*/0x0206/*::]*/: { n:"Formula", f:parse_Formula },
S
SheetJS 已提交
16038 16039 16040 16041 16042 16043 16044 16045 16046
	/*::[*/0x0207/*::]*/: { n:"String", f:parse_String },
	/*::[*/0x0208/*::]*/: { n:'Row', f:parse_Row },
	/*::[*/0x020b/*::]*/: { n:"Index", f:parse_Index },
	/*::[*/0x0221/*::]*/: { n:"Array", f:parse_Array },
	/*::[*/0x0225/*::]*/: { n:"DefaultRowHeight", f:parse_DefaultRowHeight },
	/*::[*/0x0236/*::]*/: { n:"Table", f:parse_Table },
	/*::[*/0x023e/*::]*/: { n:"Window2", f:parse_Window2 },
	/*::[*/0x027e/*::]*/: { n:"RK", f:parse_RK },
	/*::[*/0x0293/*::]*/: { n:"Style", f:parse_Style },
S
SheetJS 已提交
16047
	/*::[*/0x0406/*::]*/: { n:"Formula", f:parse_Formula },
S
SheetJS 已提交
16048 16049 16050 16051 16052 16053 16054 16055 16056 16057 16058 16059 16060 16061 16062 16063 16064 16065 16066 16067 16068 16069 16070 16071 16072 16073 16074 16075 16076 16077 16078 16079 16080 16081 16082 16083 16084 16085 16086 16087 16088 16089 16090 16091 16092 16093 16094 16095 16096 16097 16098 16099 16100 16101 16102 16103 16104 16105 16106 16107 16108 16109 16110 16111 16112 16113 16114 16115 16116 16117 16118 16119 16120
	/*::[*/0x0418/*::]*/: { n:"BigName", f:parse_BigName },
	/*::[*/0x041e/*::]*/: { n:"Format", f:parse_Format },
	/*::[*/0x043c/*::]*/: { n:"ContinueBigName", f:parse_ContinueBigName },
	/*::[*/0x04bc/*::]*/: { n:"ShrFmla", f:parse_ShrFmla },
	/*::[*/0x0800/*::]*/: { n:"HLinkTooltip", f:parse_HLinkTooltip },
	/*::[*/0x0801/*::]*/: { n:"WebPub", f:parse_WebPub },
	/*::[*/0x0802/*::]*/: { n:"QsiSXTag", f:parse_QsiSXTag },
	/*::[*/0x0803/*::]*/: { n:"DBQueryExt", f:parse_DBQueryExt },
	/*::[*/0x0804/*::]*/: { n:"ExtString", f:parse_ExtString },
	/*::[*/0x0805/*::]*/: { n:"TxtQry", f:parse_TxtQry },
	/*::[*/0x0806/*::]*/: { n:"Qsir", f:parse_Qsir },
	/*::[*/0x0807/*::]*/: { n:"Qsif", f:parse_Qsif },
	/*::[*/0x0808/*::]*/: { n:"RRDTQSIF", f:parse_RRDTQSIF },
	/*::[*/0x0809/*::]*/: { n:'BOF', f:parse_BOF },
	/*::[*/0x080a/*::]*/: { n:"OleDbConn", f:parse_OleDbConn },
	/*::[*/0x080b/*::]*/: { n:"WOpt", f:parse_WOpt },
	/*::[*/0x080c/*::]*/: { n:"SXViewEx", f:parse_SXViewEx },
	/*::[*/0x080d/*::]*/: { n:"SXTH", f:parse_SXTH },
	/*::[*/0x080e/*::]*/: { n:"SXPIEx", f:parse_SXPIEx },
	/*::[*/0x080f/*::]*/: { n:"SXVDTEx", f:parse_SXVDTEx },
	/*::[*/0x0810/*::]*/: { n:"SXViewEx9", f:parse_SXViewEx9 },
	/*::[*/0x0812/*::]*/: { n:"ContinueFrt", f:parse_ContinueFrt },
	/*::[*/0x0813/*::]*/: { n:"RealTimeData", f:parse_RealTimeData },
	/*::[*/0x0850/*::]*/: { n:"ChartFrtInfo", f:parse_ChartFrtInfo },
	/*::[*/0x0851/*::]*/: { n:"FrtWrapper", f:parse_FrtWrapper },
	/*::[*/0x0852/*::]*/: { n:"StartBlock", f:parse_StartBlock },
	/*::[*/0x0853/*::]*/: { n:"EndBlock", f:parse_EndBlock },
	/*::[*/0x0854/*::]*/: { n:"StartObject", f:parse_StartObject },
	/*::[*/0x0855/*::]*/: { n:"EndObject", f:parse_EndObject },
	/*::[*/0x0856/*::]*/: { n:"CatLab", f:parse_CatLab },
	/*::[*/0x0857/*::]*/: { n:"YMult", f:parse_YMult },
	/*::[*/0x0858/*::]*/: { n:"SXViewLink", f:parse_SXViewLink },
	/*::[*/0x0859/*::]*/: { n:"PivotChartBits", f:parse_PivotChartBits },
	/*::[*/0x085a/*::]*/: { n:"FrtFontList", f:parse_FrtFontList },
	/*::[*/0x0862/*::]*/: { n:"SheetExt", f:parse_SheetExt },
	/*::[*/0x0863/*::]*/: { n:"BookExt", f:parse_BookExt, r:12},
	/*::[*/0x0864/*::]*/: { n:"SXAddl", f:parse_SXAddl },
	/*::[*/0x0865/*::]*/: { n:"CrErr", f:parse_CrErr },
	/*::[*/0x0866/*::]*/: { n:"HFPicture", f:parse_HFPicture },
	/*::[*/0x0867/*::]*/: { n:'FeatHdr', f:parse_FeatHdr },
	/*::[*/0x0868/*::]*/: { n:"Feat", f:parse_Feat },
	/*::[*/0x086a/*::]*/: { n:"DataLabExt", f:parse_DataLabExt },
	/*::[*/0x086b/*::]*/: { n:"DataLabExtContents", f:parse_DataLabExtContents },
	/*::[*/0x086c/*::]*/: { n:"CellWatch", f:parse_CellWatch },
	/*::[*/0x0871/*::]*/: { n:"FeatHdr11", f:parse_FeatHdr11 },
	/*::[*/0x0872/*::]*/: { n:"Feature11", f:parse_Feature11 },
	/*::[*/0x0874/*::]*/: { n:"DropDownObjIds", f:parse_DropDownObjIds },
	/*::[*/0x0875/*::]*/: { n:"ContinueFrt11", f:parse_ContinueFrt11 },
	/*::[*/0x0876/*::]*/: { n:"DConn", f:parse_DConn },
	/*::[*/0x0877/*::]*/: { n:"List12", f:parse_List12 },
	/*::[*/0x0878/*::]*/: { n:"Feature12", f:parse_Feature12 },
	/*::[*/0x0879/*::]*/: { n:"CondFmt12", f:parse_CondFmt12 },
	/*::[*/0x087a/*::]*/: { n:"CF12", f:parse_CF12 },
	/*::[*/0x087b/*::]*/: { n:"CFEx", f:parse_CFEx },
	/*::[*/0x087c/*::]*/: { n:"XFCRC", f:parse_XFCRC, r:12 },
	/*::[*/0x087d/*::]*/: { n:"XFExt", f:parse_XFExt, r:12 },
	/*::[*/0x087e/*::]*/: { n:"AutoFilter12", f:parse_AutoFilter12 },
	/*::[*/0x087f/*::]*/: { n:"ContinueFrt12", f:parse_ContinueFrt12 },
	/*::[*/0x0884/*::]*/: { n:"MDTInfo", f:parse_MDTInfo },
	/*::[*/0x0885/*::]*/: { n:"MDXStr", f:parse_MDXStr },
	/*::[*/0x0886/*::]*/: { n:"MDXTuple", f:parse_MDXTuple },
	/*::[*/0x0887/*::]*/: { n:"MDXSet", f:parse_MDXSet },
	/*::[*/0x0888/*::]*/: { n:"MDXProp", f:parse_MDXProp },
	/*::[*/0x0889/*::]*/: { n:"MDXKPI", f:parse_MDXKPI },
	/*::[*/0x088a/*::]*/: { n:"MDB", f:parse_MDB },
	/*::[*/0x088b/*::]*/: { n:"PLV", f:parse_PLV },
	/*::[*/0x088c/*::]*/: { n:"Compat12", f:parse_Compat12, r:12 },
	/*::[*/0x088d/*::]*/: { n:"DXF", f:parse_DXF },
	/*::[*/0x088e/*::]*/: { n:"TableStyles", f:parse_TableStyles, r:12 },
	/*::[*/0x088f/*::]*/: { n:"TableStyle", f:parse_TableStyle },
	/*::[*/0x0890/*::]*/: { n:"TableStyleElement", f:parse_TableStyleElement },
	/*::[*/0x0892/*::]*/: { n:"StyleExt", f:parse_StyleExt },
	/*::[*/0x0893/*::]*/: { n:"NamePublish", f:parse_NamePublish },
S
SheetJS 已提交
16121
	/*::[*/0x0894/*::]*/: { n:"NameCmt", f:parse_NameCmt, r:12 },
S
SheetJS 已提交
16122 16123 16124 16125 16126 16127 16128 16129 16130 16131 16132 16133 16134 16135 16136 16137 16138 16139 16140 16141 16142 16143 16144 16145 16146 16147 16148 16149 16150 16151 16152 16153 16154 16155 16156 16157 16158 16159 16160 16161 16162 16163 16164 16165 16166 16167 16168 16169 16170 16171 16172 16173 16174 16175 16176 16177 16178 16179 16180 16181 16182 16183 16184 16185 16186 16187 16188 16189 16190 16191 16192 16193 16194 16195 16196 16197 16198 16199 16200 16201
	/*::[*/0x0895/*::]*/: { n:"SortData", f:parse_SortData },
	/*::[*/0x0896/*::]*/: { n:"Theme", f:parse_Theme, r:12 },
	/*::[*/0x0897/*::]*/: { n:"GUIDTypeLib", f:parse_GUIDTypeLib },
	/*::[*/0x0898/*::]*/: { n:"FnGrp12", f:parse_FnGrp12 },
	/*::[*/0x0899/*::]*/: { n:"NameFnGrp12", f:parse_NameFnGrp12 },
	/*::[*/0x089a/*::]*/: { n:"MTRSettings", f:parse_MTRSettings, r:12 },
	/*::[*/0x089b/*::]*/: { n:"CompressPictures", f:parse_CompressPictures },
	/*::[*/0x089c/*::]*/: { n:"HeaderFooter", f:parse_HeaderFooter },
	/*::[*/0x089d/*::]*/: { n:"CrtLayout12", f:parse_CrtLayout12 },
	/*::[*/0x089e/*::]*/: { n:"CrtMlFrt", f:parse_CrtMlFrt },
	/*::[*/0x089f/*::]*/: { n:"CrtMlFrtContinue", f:parse_CrtMlFrtContinue },
	/*::[*/0x08a3/*::]*/: { n:"ForceFullCalculation", f:parse_ForceFullCalculation },
	/*::[*/0x08a4/*::]*/: { n:"ShapePropsStream", f:parse_ShapePropsStream },
	/*::[*/0x08a5/*::]*/: { n:"TextPropsStream", f:parse_TextPropsStream },
	/*::[*/0x08a6/*::]*/: { n:"RichTextStream", f:parse_RichTextStream },
	/*::[*/0x08a7/*::]*/: { n:"CrtLayout12A", f:parse_CrtLayout12A },
	/*::[*/0x1001/*::]*/: { n:"Units", f:parse_Units },
	/*::[*/0x1002/*::]*/: { n:"Chart", f:parse_Chart },
	/*::[*/0x1003/*::]*/: { n:"Series", f:parse_Series },
	/*::[*/0x1006/*::]*/: { n:"DataFormat", f:parse_DataFormat },
	/*::[*/0x1007/*::]*/: { n:"LineFormat", f:parse_LineFormat },
	/*::[*/0x1009/*::]*/: { n:"MarkerFormat", f:parse_MarkerFormat },
	/*::[*/0x100a/*::]*/: { n:"AreaFormat", f:parse_AreaFormat },
	/*::[*/0x100b/*::]*/: { n:"PieFormat", f:parse_PieFormat },
	/*::[*/0x100c/*::]*/: { n:"AttachedLabel", f:parse_AttachedLabel },
	/*::[*/0x100d/*::]*/: { n:"SeriesText", f:parse_SeriesText },
	/*::[*/0x1014/*::]*/: { n:"ChartFormat", f:parse_ChartFormat },
	/*::[*/0x1015/*::]*/: { n:"Legend", f:parse_Legend },
	/*::[*/0x1016/*::]*/: { n:"SeriesList", f:parse_SeriesList },
	/*::[*/0x1017/*::]*/: { n:"Bar", f:parse_Bar },
	/*::[*/0x1018/*::]*/: { n:"Line", f:parse_Line },
	/*::[*/0x1019/*::]*/: { n:"Pie", f:parse_Pie },
	/*::[*/0x101a/*::]*/: { n:"Area", f:parse_Area },
	/*::[*/0x101b/*::]*/: { n:"Scatter", f:parse_Scatter },
	/*::[*/0x101c/*::]*/: { n:"CrtLine", f:parse_CrtLine },
	/*::[*/0x101d/*::]*/: { n:"Axis", f:parse_Axis },
	/*::[*/0x101e/*::]*/: { n:"Tick", f:parse_Tick },
	/*::[*/0x101f/*::]*/: { n:"ValueRange", f:parse_ValueRange },
	/*::[*/0x1020/*::]*/: { n:"CatSerRange", f:parse_CatSerRange },
	/*::[*/0x1021/*::]*/: { n:"AxisLine", f:parse_AxisLine },
	/*::[*/0x1022/*::]*/: { n:"CrtLink", f:parse_CrtLink },
	/*::[*/0x1024/*::]*/: { n:"DefaultText", f:parse_DefaultText },
	/*::[*/0x1025/*::]*/: { n:"Text", f:parse_Text },
	/*::[*/0x1026/*::]*/: { n:"FontX", f:parse_FontX },
	/*::[*/0x1027/*::]*/: { n:"ObjectLink", f:parse_ObjectLink },
	/*::[*/0x1032/*::]*/: { n:"Frame", f:parse_Frame },
	/*::[*/0x1033/*::]*/: { n:"Begin", f:parse_Begin },
	/*::[*/0x1034/*::]*/: { n:"End", f:parse_End },
	/*::[*/0x1035/*::]*/: { n:"PlotArea", f:parse_PlotArea },
	/*::[*/0x103a/*::]*/: { n:"Chart3d", f:parse_Chart3d },
	/*::[*/0x103c/*::]*/: { n:"PicF", f:parse_PicF },
	/*::[*/0x103d/*::]*/: { n:"DropBar", f:parse_DropBar },
	/*::[*/0x103e/*::]*/: { n:"Radar", f:parse_Radar },
	/*::[*/0x103f/*::]*/: { n:"Surf", f:parse_Surf },
	/*::[*/0x1040/*::]*/: { n:"RadarArea", f:parse_RadarArea },
	/*::[*/0x1041/*::]*/: { n:"AxisParent", f:parse_AxisParent },
	/*::[*/0x1043/*::]*/: { n:"LegendException", f:parse_LegendException },
	/*::[*/0x1044/*::]*/: { n:"ShtProps", f:parse_ShtProps },
	/*::[*/0x1045/*::]*/: { n:"SerToCrt", f:parse_SerToCrt },
	/*::[*/0x1046/*::]*/: { n:"AxesUsed", f:parse_AxesUsed },
	/*::[*/0x1048/*::]*/: { n:"SBaseRef", f:parse_SBaseRef },
	/*::[*/0x104a/*::]*/: { n:"SerParent", f:parse_SerParent },
	/*::[*/0x104b/*::]*/: { n:"SerAuxTrend", f:parse_SerAuxTrend },
	/*::[*/0x104e/*::]*/: { n:"IFmtRecord", f:parse_IFmtRecord },
	/*::[*/0x104f/*::]*/: { n:"Pos", f:parse_Pos },
	/*::[*/0x1050/*::]*/: { n:"AlRuns", f:parse_AlRuns },
	/*::[*/0x1051/*::]*/: { n:"BRAI", f:parse_BRAI },
	/*::[*/0x105b/*::]*/: { n:"SerAuxErrBar", f:parse_SerAuxErrBar },
	/*::[*/0x105c/*::]*/: { n:"ClrtClient", f:parse_ClrtClient },
	/*::[*/0x105d/*::]*/: { n:"SerFmt", f:parse_SerFmt },
	/*::[*/0x105f/*::]*/: { n:"Chart3DBarShape", f:parse_Chart3DBarShape },
	/*::[*/0x1060/*::]*/: { n:"Fbi", f:parse_Fbi },
	/*::[*/0x1061/*::]*/: { n:"BopPop", f:parse_BopPop },
	/*::[*/0x1062/*::]*/: { n:"AxcExt", f:parse_AxcExt },
	/*::[*/0x1063/*::]*/: { n:"Dat", f:parse_Dat },
	/*::[*/0x1064/*::]*/: { n:"PlotGrowth", f:parse_PlotGrowth },
	/*::[*/0x1065/*::]*/: { n:"SIIndex", f:parse_SIIndex },
	/*::[*/0x1066/*::]*/: { n:"GelFrame", f:parse_GelFrame },
	/*::[*/0x1067/*::]*/: { n:"BopPopCustom", f:parse_BopPopCustom },
	/*::[*/0x1068/*::]*/: { n:"Fbi2", f:parse_Fbi2 },
S
SheetJS 已提交
16202 16203

	/* These are specified in an older version of the spec */
S
SheetJS 已提交
16204
	/*::[*/0x0000/*::]*/: { n:"Dimensions", f:parse_Dimensions },
S
SheetJS 已提交
16205 16206 16207 16208 16209
	/*::[*/0x0002/*::]*/: { n:"BIFF2INT", f:parse_BIFF2INT },
	/*::[*/0x0005/*::]*/: { n:"BoolErr", f:parse_BoolErr },
	/*::[*/0x0007/*::]*/: { n:"String", f:parse_BIFF2STRING },
	/*::[*/0x0008/*::]*/: { n:"BIFF2ROW", f:parsenoop },
	/*::[*/0x000b/*::]*/: { n:"Index", f:parse_Index },
S
SheetJS 已提交
16210
	/*::[*/0x0016/*::]*/: { n:"ExternCount", f:parse_ExternCount },
S
SheetJS 已提交
16211 16212
	/*::[*/0x001e/*::]*/: { n:"BIFF2FORMAT", f:parse_BIFF2Format },
	/*::[*/0x001f/*::]*/: { n:"BIFF2FMTCNT", f:parsenoop }, /* 16-bit cnt of BIFF2FORMAT records */
S
SheetJS 已提交
16213
	/*::[*/0x0020/*::]*/: { n:"BIFF2COLINFO", f:parsenoop },
S
SheetJS 已提交
16214
	/*::[*/0x0021/*::]*/: { n:"Array", f:parse_Array },
S
SheetJS 已提交
16215 16216 16217 16218 16219 16220
	/*::[*/0x0025/*::]*/: { n:"DefaultRowHeight", f:parse_DefaultRowHeight },
	/*::[*/0x0032/*::]*/: { n:"BIFF2FONTXTRA", f:parse_BIFF2FONTXTRA },
	/*::[*/0x003e/*::]*/: { n:"BIFF2WINDOW2", f:parsenoop },
	/*::[*/0x0045/*::]*/: { n:"BIFF2FONTCLR", f:parsenoop },
	/*::[*/0x0056/*::]*/: { n:"BIFF4FMTCNT", f:parsenoop }, /* 16-bit cnt, similar to BIFF2 */
	/*::[*/0x007e/*::]*/: { n:"RK", f:parsenoop }, /* Not necessarily same as 0x027e */
S
SheetJS 已提交
16221
	/*::[*/0x007f/*::]*/: { n:"ImData", f:parse_ImData },
S
SheetJS 已提交
16222 16223 16224 16225 16226 16227 16228 16229 16230 16231 16232 16233
	/*::[*/0x0087/*::]*/: { n:"Addin", f:parsenoop },
	/*::[*/0x0088/*::]*/: { n:"Edg", f:parsenoop },
	/*::[*/0x0089/*::]*/: { n:"Pub", f:parsenoop },
	/*::[*/0x0091/*::]*/: { n:"Sub", f:parsenoop },
	/*::[*/0x0094/*::]*/: { n:"LHRecord", f:parsenoop },
	/*::[*/0x0095/*::]*/: { n:"LHNGraph", f:parsenoop },
	/*::[*/0x0096/*::]*/: { n:"Sound", f:parsenoop },
	/*::[*/0x00a9/*::]*/: { n:"CoordList", f:parsenoop },
	/*::[*/0x00ab/*::]*/: { n:"GCW", f:parsenoop },
	/*::[*/0x00bc/*::]*/: { n:"ShrFmla", f:parsenoop }, /* Not necessarily same as 0x04bc */
	/*::[*/0x00c2/*::]*/: { n:"AddMenu", f:parsenoop },
	/*::[*/0x00c3/*::]*/: { n:"DelMenu", f:parsenoop },
S
SheetJS 已提交
16234
	/*::[*/0x00d6/*::]*/: { n:"RString", f:parse_RString },
S
SheetJS 已提交
16235 16236 16237 16238 16239 16240 16241 16242 16243 16244 16245 16246 16247 16248 16249 16250 16251 16252 16253 16254
	/*::[*/0x00df/*::]*/: { n:"UDDesc", f:parsenoop },
	/*::[*/0x00ea/*::]*/: { n:"TabIdConf", f:parsenoop },
	/*::[*/0x0162/*::]*/: { n:"XL5Modify", f:parsenoop },
	/*::[*/0x01a5/*::]*/: { n:"FileSharing2", f:parsenoop },
	/*::[*/0x0209/*::]*/: { n:'BOF', f:parse_BOF },
	/*::[*/0x0218/*::]*/: { n:"Lbl", f:parse_Lbl },
	/*::[*/0x0223/*::]*/: { n:"ExternName", f:parse_ExternName },
	/*::[*/0x0231/*::]*/: { n:"Font", f:parsenoop },
	/*::[*/0x0409/*::]*/: { n:'BOF', f:parse_BOF },
	/*::[*/0x086d/*::]*/: { n:"FeatInfo", f:parsenoop },
	/*::[*/0x0873/*::]*/: { n:"FeatInfo11", f:parsenoop },
	/*::[*/0x0881/*::]*/: { n:"SXAddl12", f:parsenoop },
	/*::[*/0x08c0/*::]*/: { n:"AutoWebPub", f:parsenoop },
	/*::[*/0x08c1/*::]*/: { n:"ListObj", f:parsenoop },
	/*::[*/0x08c2/*::]*/: { n:"ListField", f:parsenoop },
	/*::[*/0x08c3/*::]*/: { n:"ListDV", f:parsenoop },
	/*::[*/0x08c4/*::]*/: { n:"ListCondFmt", f:parsenoop },
	/*::[*/0x08c5/*::]*/: { n:"ListCF", f:parsenoop },
	/*::[*/0x08c6/*::]*/: { n:"FMQry", f:parsenoop },
	/*::[*/0x08c7/*::]*/: { n:"FMSQry", f:parsenoop },
S
SheetJS 已提交
16255
	/*::[*/0x08c8/*::]*/: { n:"PLV", f:parsenoop },
S
SheetJS 已提交
16256 16257 16258 16259 16260 16261 16262 16263 16264
	/*::[*/0x08c9/*::]*/: { n:"LnExt", f:parsenoop },
	/*::[*/0x08ca/*::]*/: { n:"MkrExt", f:parsenoop },
	/*::[*/0x08cb/*::]*/: { n:"CrtCoopt", f:parsenoop },

	/*::[*/0x0043/*::]*/: { n:"BIFF2XF", f:parsenoop },
	/*::[*/0x0243/*::]*/: { n:"BIFF3XF", f:parsenoop },
	/*::[*/0x0443/*::]*/: { n:"BIFF4XF", f:parsenoop },

	/*::[*/0x7262/*::]*/: {}
S
SheetJS 已提交
16265 16266 16267
};


S
SheetJS 已提交
16268 16269 16270 16271 16272 16273 16274 16275 16276 16277 16278 16279 16280 16281 16282 16283 16284 16285 16286 16287 16288 16289 16290 16291 16292 16293 16294
/* BIFF2-4 single-sheet workbooks */
function write_biff_rec(ba/*:BufArray*/, t/*:number*/, payload, length/*:?number*/) {
	var len = (length || (payload||[]).length);
	var o = ba.next(4 + len);
	o.write_shift(2, t);
	o.write_shift(2, len);
	if(/*:: len != null &&*/len > 0 && is_buf(payload)) ba.push(payload);
}

function write_BOF(wb/*:Workbook*/, o) {
	if(o.bookType != 'biff2') throw "unsupported BIFF version";
	var out = new_buf(4);
	out.write_shift(2, 0x0002); // "unused"
	out.write_shift(2, 0x0010); // Sheet
	return out;
}

function write_BIFF2Cell(out, r/*:number*/, c/*:number*/) {
	if(!out) out = new_buf(7);
	out.write_shift(2, r);
	out.write_shift(2, c);
	out.write_shift(1, 0);
	out.write_shift(1, 0);
	out.write_shift(1, 0);
	return out;
}

S
SheetJS 已提交
16295
function write_BIFF2INT(r/*:number*/, c/*:number*/, val/*:number*/) {
S
SheetJS 已提交
16296 16297 16298 16299 16300 16301
	var out = new_buf(9);
	write_BIFF2Cell(out, r, c);
	out.write_shift(2, val);
	return out;
}

S
SheetJS 已提交
16302
function write_BIFF2NUMBER(r/*:number*/, c/*:number*/, val/*:number*/) {
S
SheetJS 已提交
16303 16304 16305 16306 16307 16308
	var out = new_buf(15);
	write_BIFF2Cell(out, r, c);
	out.write_shift(8, val, 'f');
	return out;
}

S
SheetJS 已提交
16309
function write_BIFF2BERR(r/*:number*/, c/*:number*/, val, t/*:?string*/) {
S
SheetJS 已提交
16310 16311 16312 16313 16314 16315 16316 16317
	var out = new_buf(9);
	write_BIFF2Cell(out, r, c);
	if(t == 'e') { out.write_shift(1, val); out.write_shift(1, 1); }
	else { out.write_shift(1, val?1:0); out.write_shift(1, 0); }
	return out;
}

/* TODO: codepage, large strings */
S
SheetJS 已提交
16318
function write_BIFF2LABEL(r/*:number*/, c/*:number*/, val) {
S
SheetJS 已提交
16319 16320 16321 16322 16323 16324 16325 16326
	var out = new_buf(8 + 2*val.length);
	write_BIFF2Cell(out, r, c);
	out.write_shift(1, val.length);
	out.write_shift(val.length, val, 'sbcs');
	return out.l < out.length ? out.slice(0, out.l) : out;
}

function write_ws_biff_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) {
S
SheetJS 已提交
16327
	if(cell.v != null) switch(cell.t) {
S
SheetJS 已提交
16328 16329 16330 16331
		case 'd': case 'n':
			var v = cell.t == 'd' ? datenum(cell.v) : cell.v;
			if((v == (v|0)) && (v >= 0) && (v < 65536))
				write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v));
S
SheetJS 已提交
16332
			else
S
SheetJS 已提交
16333
				write_biff_rec(ba, 0x0003, write_BIFF2NUMBER(R,C, v));
S
SheetJS 已提交
16334 16335
			return;
		case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
S
SheetJS 已提交
16336 16337 16338
		/* TODO: codepage, sst */
		case 's': case 'str':
			write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v));
S
SheetJS 已提交
16339
			return;
S
SheetJS 已提交
16340
	}
S
SheetJS 已提交
16341
	write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
S
SheetJS 已提交
16342 16343 16344
}

function write_biff_ws(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
S
SheetJS 已提交
16345
	var dense = Array.isArray(ws);
S
SheetJS 已提交
16346
	var range = safe_decode_range(ws['!ref'] || "A1"), ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
S
SheetJS 已提交
16347 16348 16349 16350 16351
	for(var R = range.s.r; R <= range.e.r; ++R) {
		rr = encode_row(R);
		for(var C = range.s.c; C <= range.e.c; ++C) {
			if(R === range.s.r) cols[C] = encode_col(C);
			ref = cols[C] + rr;
S
SheetJS 已提交
16352
			var cell = dense ? (ws[R]||[])[C] : ws[ref];
S
SheetJS 已提交
16353
			if(!cell) continue;
S
SheetJS 已提交
16354
			/* write cell */
S
SheetJS 已提交
16355
			write_ws_biff_cell(ba, cell, R, C, opts);
S
SheetJS 已提交
16356 16357 16358 16359 16360
		}
	}
}

/* Based on test files */
S
SheetJS 已提交
16361 16362
function write_biff_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
	var o = opts || {};
16363
	if(DENSE != null && o.dense == null) o.dense = DENSE;
S
SheetJS 已提交
16364 16365 16366 16367 16368 16369 16370 16371 16372 16373 16374 16375
	var ba = buf_array();
	var idx = 0;
	for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i;
	if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
	write_biff_rec(ba, 0x0009, write_BOF(wb, o));
	/* ... */
	write_biff_ws(ba, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
	/* ... */
	write_biff_rec(ba, 0x000a);
	// TODO
	return ba.end();
}
16376
/* note: browser DOM element cannot see mso- style attrs, must parse */
S
SheetJS 已提交
16377 16378 16379 16380 16381
var HTML_ = (function() {
	function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ {
		var opts = _opts || {};
		if(DENSE != null && opts.dense == null) opts.dense = DENSE;
		var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
S
SheetJS 已提交
16382
		var mtch/*:any*/ = str.match(/<table/i);
S
SheetJS 已提交
16383
		if(!mtch) throw new Error("Invalid HTML: could not find <table>");
S
SheetJS 已提交
16384 16385
		var mtch2/*:any*/ = str.match(/<\/table/i);
		var i/*:number*/ = mtch.index, j/*:number*/ = mtch2 && mtch2.index || str.length;
16386
		var rows = split_regex(str.slice(i, j), /(:?<tr[^>]*>)/i, "<tr>");
S
SheetJS 已提交
16387 16388 16389 16390 16391
		var R = -1, C = 0, RS = 0, CS = 0;
		var range = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
		var merges = [], midx = 0;
		for(i = 0; i < rows.length; ++i) {
			var row = rows[i].trim();
S
SheetJS 已提交
16392 16393 16394 16395
			var hd = row.substr(0,3).toLowerCase();
			if(hd == "<tr") { ++R; C = 0; continue; }
			if(hd != "<td") continue;
			var cells = row.split(/<\/td>/i);
S
SheetJS 已提交
16396 16397
			for(j = 0; j < cells.length; ++j) {
				var cell = cells[j].trim();
S
SheetJS 已提交
16398
				if(cell.substr(0,3).toLowerCase() != "<td") continue;
S
SheetJS 已提交
16399 16400 16401 16402 16403 16404 16405 16406 16407 16408 16409 16410 16411 16412 16413 16414
				var m = cell, cc = 0;
				/* TODO: parse styles etc */
				while(m.charAt(0) == "<" && (cc = m.indexOf(">")) > -1) m = m.slice(cc+1);
				while(m.indexOf(">") > -1) m = m.slice(0, m.lastIndexOf("<"));
				var tag = parsexmltag(cell.slice(0, cell.indexOf(">")));
				CS = tag.colspan ? +tag.colspan : 1;
				if((RS = +tag.rowspan)>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
				/* TODO: generate stub cells */
				if(!m.length) { C += CS; continue; }
				m = unescapexml(m).replace(/[\r\n]/g,"");
				if(range.s.r > R) range.s.r = R;
				if(range.e.r < R) range.e.r = R;
				if(range.s.c > C) range.s.c = C;
				if(range.e.c < C) range.e.c = C;
				if(opts.dense) {
					if(!ws[R]) ws[R] = [];
S
SheetJS 已提交
16415 16416
					if(opts.raw) ws[R][C] = {t:'s', v:m};
					else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)};
S
SheetJS 已提交
16417 16418 16419 16420
					else ws[R][C] = {t:'s', v:m};
				} else {
					var coord/*:string*/ = encode_cell({r:R, c:C});
					/* TODO: value parsing */
S
SheetJS 已提交
16421 16422
					if(opts.raw) ws[coord] = {t:'s', v:m};
					else if(!isNaN(fuzzynum(m))) ws[coord] = {t:'n', v:fuzzynum(m)};
S
SheetJS 已提交
16423 16424 16425
					else ws[coord] = {t:'s', v:m};
				}
				C += CS;
S
SheetJS 已提交
16426
			}
S
SheetJS 已提交
16427
		}
S
SheetJS 已提交
16428 16429
		ws['!ref'] = encode_range(range);
		return ws;
S
SheetJS 已提交
16430
	}
S
SheetJS 已提交
16431 16432 16433
	function html_to_book(str/*:string*/, opts)/*:Workbook*/ {
		return sheet_to_workbook(html_to_sheet(str, opts), opts);
	}
S
SheetJS 已提交
16434
	function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
S
SheetJS 已提交
16435
		var M = (ws['!merges'] ||[]);
16436
		var oo = [];
S
SheetJS 已提交
16437
		var nullcell = "<td" + (o.editable ? ' contenteditable="true"' : "" ) + "></td>";
16438 16439 16440 16441 16442 16443 16444
		for(var C = r.s.c; C <= r.e.c; ++C) {
			var RS = 0, CS = 0;
			for(var j = 0; j < M.length; ++j) {
				if(M[j].s.r > R || M[j].s.c > C) continue;
				if(M[j].e.r < R || M[j].e.c < C) continue;
				if(M[j].s.r < R || M[j].s.c < C) { RS = -1; break; }
				RS = M[j].e.r - M[j].s.r + 1; CS = M[j].e.c - M[j].s.c + 1; break;
S
SheetJS 已提交
16445
			}
16446 16447 16448
			if(RS < 0) continue;
			var coord = encode_cell({r:R,c:C});
			var cell = o.dense ? (ws[R]||[])[C] : ws[coord];
S
SheetJS 已提交
16449
			if(!cell || cell.v == null) { oo.push(nullcell); continue; }
16450 16451 16452 16453 16454
			/* TODO: html entities */
			var w = cell.h || escapexml(cell.w || (format_cell(cell), cell.w) || "");
			var sp = {};
			if(RS > 1) sp.rowspan = RS;
			if(CS > 1) sp.colspan = CS;
S
SheetJS 已提交
16455
			if(o.editable) sp.contenteditable = "true";
S
SheetJS 已提交
16456
			sp.id = "sjs-" + coord;
16457
			oo.push(writextag('td', w, sp));
S
SheetJS 已提交
16458
		}
S
SheetJS 已提交
16459 16460 16461 16462 16463 16464
		var preamble = "<tr>";
		return preamble + oo.join("") + "</tr>";
	}
	function make_html_preamble(ws/*:Worksheet*/, R/*:Range*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
		var out = [];
		return out.join("") + '<table>';
16465
	}
S
SheetJS 已提交
16466 16467 16468
	var _BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
	var _END = '</body></html>';
	function sheet_to_html(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*/, wb/*:?Workbook*/)/*:string*/ {
S
SheetJS 已提交
16469
		var o = opts || {};
S
SheetJS 已提交
16470 16471 16472
		var header = o.header != null ? o.header : _BEGIN;
		var footer = o.footer != null ? o.footer : _END;
		var out/*:Array<string>*/ = [header];
16473 16474
		var r = decode_range(ws['!ref']);
		o.dense = Array.isArray(ws);
S
SheetJS 已提交
16475
		out.push(make_html_preamble(ws, r, o));
S
SheetJS 已提交
16476
		for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
S
SheetJS 已提交
16477 16478
		out.push("</table>" + footer);
		return out.join("");
S
SheetJS 已提交
16479 16480 16481 16482 16483
	}

	return {
		to_workbook: html_to_book,
		to_sheet: html_to_sheet,
16484
		_row: make_html_row,
S
SheetJS 已提交
16485 16486
		BEGIN: _BEGIN,
		END: _END,
S
SheetJS 已提交
16487
		_preamble: make_html_preamble,
S
SheetJS 已提交
16488 16489 16490
		from_sheet: sheet_to_html
	};
})();
S
SheetJS 已提交
16491

S
SheetJS 已提交
16492 16493 16494 16495
function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
	var opts = _opts || {};
	if(DENSE != null) opts.dense = DENSE;
	var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
S
SheetJS 已提交
16496 16497 16498 16499 16500 16501 16502 16503
	var rows = table.getElementsByTagName('tr');
	var range = {s:{r:0,c:0},e:{r:rows.length - 1,c:0}};
	var merges = [], midx = 0;
	var R = 0, _C = 0, C = 0, RS = 0, CS = 0;
	for(; R < rows.length; ++R) {
		var row = rows[R];
		var elts = row.children;
		for(_C = C = 0; _C < elts.length; ++_C) {
16504
			var elt = elts[_C], v = elts[_C].innerText || elts[_C].textContent;
S
SheetJS 已提交
16505 16506 16507 16508 16509 16510
			for(midx = 0; midx < merges.length; ++midx) {
				var m = merges[midx];
				if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; }
			}
			/* TODO: figure out how to extract nonstandard mso- style */
			CS = +elt.getAttribute("colspan") || 1;
S
SheetJS 已提交
16511
			if((RS = +elt.getAttribute("rowspan"))>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
16512 16513
			var o/*:Cell*/ = {t:'s', v:v};
			if(v != null && v.length) {
S
SheetJS 已提交
16514 16515
				if(opts.raw) o = {t:'s', v:v};
				else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
16516 16517 16518 16519 16520 16521
				else if(!isNaN(fuzzydate(v).getDate())) {
					o = ({t:'d', v:parseDate(v)}/*:any*/);
					if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
					o.z = opts.dateNF || SSF._table[14];
				}
			}
S
SheetJS 已提交
16522 16523
			if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; }
			else ws[encode_cell({c:C, r:R})] = o;
S
SheetJS 已提交
16524
			if(range.e.c < C) range.e.c = C;
S
SheetJS 已提交
16525 16526 16527 16528
			C += CS;
		}
	}
	ws['!merges'] = merges;
S
SheetJS 已提交
16529
	ws['!ref'] = encode_range(range);
S
SheetJS 已提交
16530 16531 16532 16533 16534 16535
	return ws;
}

function table_to_book(table/*:HTMLElement*/, opts/*:?any*/)/*:Workbook*/ {
	return sheet_to_workbook(parse_dom_table(table, opts), opts);
}
S
SheetJS 已提交
16536
/* OpenDocument */
16537 16538 16539 16540 16541 16542 16543 16544 16545 16546 16547 16548 16549 16550 16551 16552 16553 16554
var parse_content_xml = (function() {

	var parse_text_p = function(text, tag) {
		return unescapexml(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,""));
	};

	var number_formats = {
		/* ods name: [short ssf fmt, long ssf fmt] */
		day: ["d", "dd"],
		month: ["m", "mm"],
		year: ["y", "yy"],
		hours: ["h", "hh"],
		minutes: ["m", "mm"],
		seconds: ["s", "ss"],
		"am-pm": ["A/P", "AM/PM"],
		"day-of-week": ["ddd", "dddd"]
	};

S
SheetJS 已提交
16555
	return function pcx(d/*:string*/, _opts)/*:Workbook*/ {
16556
		var opts = _opts || {};
16557
		if(DENSE != null && opts.dense == null) opts.dense = DENSE;
16558 16559 16560 16561 16562 16563
		var str = xlml_normalize(d);
		var state/*:Array<any>*/ = [], tmp;
		var tag/*:: = {}*/;
		var NFtag = {name:""}, NF = "", pidx = 0;
		var sheetag/*:: = {name:"", '名称':""}*/;
		var rowtag/*:: = {'行号':""}*/;
S
SheetJS 已提交
16564 16565
		var Sheets = {}, SheetNames/*:Array<string>*/ = [];
		var ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
S
TXT/PRN  
SheetJS 已提交
16566
		var Rn, q/*:: = ({t:"", v:null, z:null, w:"",c:[]}:any)*/;
16567 16568 16569 16570 16571 16572
		var ctag = {value:""};
		var textp = "", textpidx = 0, textptag/*:: = {}*/;
		var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
		var number_format_map = {};
		var merges = [], mrange = {}, mR = 0, mC = 0;
		var arrayf = [];
S
SheetJS 已提交
16573 16574
		var comments = [], comment = {};
		var creator = "", creatoridx = 0;
16575 16576 16577
		var rept = 1, isstub = false;
		var i = 0;
		xlmlregex.lastIndex = 0;
S
SheetJS 已提交
16578
		str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
16579 16580 16581 16582 16583 16584 16585 16586 16587 16588 16589 16590 16591 16592
		while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {

			case 'table': case '工作表': // 9.1.2 <table:table>
				if(Rn[1]==='/') {
					if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = encode_range(range);
					if(merges.length) ws['!merges'] = merges;
					sheetag.name = utf8read(sheetag['名称'] || sheetag.name);
					SheetNames.push(sheetag.name);
					Sheets[sheetag.name] = ws;
				}
				else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
					sheetag = parsexmltag(Rn[0], false);
					R = C = -1;
					range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0;
S
SheetJS 已提交
16593
					ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/); merges = [];
16594 16595 16596 16597 16598 16599 16600 16601
				}
				break;

			case 'table-row': case '行': // 9.1.3 <table:table-row>
				if(Rn[1] === '/') break;
				rowtag = parsexmltag(Rn[0], false);
				if(rowtag['行号']) R = rowtag['行号'] - 1; else ++R;
				C = -1; break;
S
SheetJS 已提交
16602 16603
			case 'covered-table-cell': // 9.1.5 <table:covered-table-cell>
				++C;
S
SheetJS 已提交
16604 16605 16606 16607
				if(opts.sheetStubs) {
					if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = {t:'z'}; }
					else ws[encode_cell({r:R,c:C})] = {t:'z'};
				}
S
SheetJS 已提交
16608
				break; /* stub */
16609 16610 16611 16612 16613 16614 16615 16616 16617 16618 16619 16620 16621 16622
			case 'table-cell': case '数据':
				if(Rn[0].charAt(Rn[0].length-2) === '/') {
					ctag = parsexmltag(Rn[0], false);
					if(ctag['number-columns-repeated']) C+= parseInt(ctag['number-columns-repeated'], 10);
					else ++C;
				}
				else if(Rn[1]!=='/') {
					++C;
					rept = 1;
					if(C > range.e.c) range.e.c = C;
					if(R > range.e.r) range.e.r = R;
					if(C < range.s.c) range.s.c = C;
					if(R < range.s.r) range.s.r = R;
					ctag = parsexmltag(Rn[0], false);
S
SheetJS 已提交
16623
					comments = []; comment = {};
S
TXT/PRN  
SheetJS 已提交
16624
					q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:"",c:[]*/}/*:any*/);
16625
					if(opts.cellFormula) {
S
SheetJS 已提交
16626
						if(ctag.formula) ctag.formula = unescapexml(ctag.formula);
16627 16628 16629 16630 16631 16632 16633 16634 16635 16636 16637 16638 16639 16640 16641 16642 16643 16644 16645 16646 16647 16648 16649 16650 16651 16652 16653 16654 16655
						if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
							mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
							mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
							mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
							q.F = encode_range(mrange);
							arrayf.push([mrange, q.F]);
						}
						if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula);
						else for(i = 0; i < arrayf.length; ++i)
							if(R >= arrayf[i][0].s.r && R <= arrayf[i][0].e.r)
								if(C >= arrayf[i][0].s.c && C <= arrayf[i][0].e.c)
									q.F = arrayf[i][1];
					}
					if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) {
						mR = parseInt(ctag['number-rows-spanned'],10) || 0;
						mC = parseInt(ctag['number-columns-spanned'],10) || 0;
						mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
						merges.push(mrange);
					}

					/* 19.675.2 table:number-columns-repeated */
					if(ctag['number-columns-repeated']) rept = parseInt(ctag['number-columns-repeated'], 10);

					/* 19.385 office:value-type */
					switch(q.t) {
						case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break;
						case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break;
						case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break;
						case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break;
S
SheetJS 已提交
16656
						case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']);
16657 16658
							if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v); }
							q.z = 'm/d/yy'; break;
16659 16660 16661 16662 16663
						case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400; break;
						case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
						default:
							if(q.t === 'string' || q.t === 'text' || !q.t) {
								q.t = 's';
16664
								if(ctag['string-value'] != null) textp = unescapexml(ctag['string-value']);
16665 16666 16667 16668 16669 16670 16671 16672
							} else throw new Error('Unsupported value type ' + q.t);
					}
				} else {
					isstub = false;
					if(q.t === 's') {
						q.v = textp || '';
						isstub = textpidx == 0;
					}
S
SheetJS 已提交
16673
					if(comments.length > 0) { q.c = comments; comments = []; }
S
SheetJS 已提交
16674
					if(textp && opts.cellText !== false) q.w = textp;
S
SheetJS 已提交
16675
					if(!isstub || opts.sheetStubs) {
16676
						if(!(opts.sheetRows && opts.sheetRows < R)) {
S
SheetJS 已提交
16677 16678 16679 16680 16681 16682 16683 16684
							if(opts.dense) {
								if(!ws[R]) ws[R] = [];
								ws[R][C] = q;
								while(--rept > 0) ws[R][++C] = dup(q);
							} else {
								ws[encode_cell({r:R,c:C})] = q;
								while(--rept > 0) ws[encode_cell({r:R,c:++C})] = dup(q);
							}
16685 16686 16687
							if(range.e.c <= C) range.e.c = C;
						}
					} else { C += rept; rept = 0; }
S
TXT/PRN  
SheetJS 已提交
16688
					q = {/*:: t:"", v:null, z:null, w:"",c:[]*/};
16689 16690 16691 16692 16693 16694 16695 16696 16697 16698 16699 16700 16701 16702 16703
					textp = "";
				}
				break; // 9.1.4 <table:table-cell>

			/* pure state */
			case 'document': // TODO: <office:document> is the root for FODS
			case 'document-content': case '电子表格文档': // 3.1.3.2 <office:document-content>
			case 'spreadsheet': case '主体': // 3.7 <office:spreadsheet>
			case 'scripts': // 3.12 <office:scripts>
			case 'styles': // TODO <office:styles>
			case 'font-face-decls': // 3.14 <office:font-face-decls>
				if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
				else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
				break;

S
SheetJS 已提交
16704 16705 16706 16707 16708 16709 16710 16711
			case 'annotation': // 14.1 <office:annotation>
				if(Rn[1]==='/'){
					if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
					comment.t = textp;
					comment.a = creator;
					comments.push(comment);
				}
				else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);}
S
TXT/PRN  
SheetJS 已提交
16712
				creator = ""; creatoridx = 0;
S
SheetJS 已提交
16713 16714 16715 16716 16717 16718 16719 16720
				textp = ""; textpidx = 0;
				break;

			case 'creator': // 4.3.2.7 <dc:creator>
				if(Rn[1]==='/') { creator = str.slice(creatoridx,Rn.index); }
				else creatoridx = Rn.index + Rn[0].length;
				break;

16721 16722 16723 16724 16725 16726 16727 16728 16729 16730 16731 16732 16733 16734 16735 16736 16737 16738 16739 16740 16741 16742 16743 16744 16745 16746 16747 16748 16749 16750 16751 16752 16753 16754 16755 16756 16757 16758 16759 16760 16761 16762 16763 16764 16765 16766 16767 16768 16769 16770 16771 16772 16773 16774 16775 16776 16777 16778 16779 16780 16781 16782 16783 16784 16785 16786 16787 16788 16789 16790 16791 16792 16793 16794 16795 16796 16797 16798 16799 16800 16801 16802 16803 16804 16805 16806 16807 16808 16809 16810 16811 16812 16813 16814 16815 16816 16817 16818 16819 16820 16821 16822 16823 16824 16825 16826
			/* ignore state */
			case 'meta': case '元数据': // TODO: <office:meta> <uof:元数据> FODS/UOF
			case 'settings': // TODO: <office:settings>
			case 'config-item-set': // TODO: <office:config-item-set>
			case 'config-item-map-indexed': // TODO: <office:config-item-map-indexed>
			case 'config-item-map-entry': // TODO: <office:config-item-map-entry>
			case 'config-item-map-named': // TODO: <office:config-item-map-entry>
			case 'shapes': // 9.2.8 <table:shapes>
			case 'frame': // 10.4.2 <draw:frame>
			case 'text-box': // 10.4.3 <draw:text-box>
			case 'image': // 10.4.4 <draw:image>
			case 'data-pilot-tables': // 9.6.2 <table:data-pilot-tables>
			case 'list-style': // 16.30 <text:list-style>
			case 'form': // 13.13 <form:form>
			case 'dde-links': // 9.8 <table:dde-links>
			case 'event-listeners': // TODO
				if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
				else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]);
				textp = ""; textpidx = 0;
				break;

			case 'scientific-number': // TODO: <number:scientific-number>
				break;
			case 'currency-symbol': // TODO: <number:currency-symbol>
				break;
			case 'currency-style': // TODO: <number:currency-style>
				break;
			case 'number-style': // 16.27.2 <number:number-style>
			case 'percentage-style': // 16.27.9 <number:percentage-style>
			case 'date-style': // 16.27.10 <number:date-style>
			case 'time-style': // 16.27.18 <number:time-style>
				if(Rn[1]==='/'){
					number_format_map[NFtag.name] = NF;
					if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
				} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
					NF = "";
					NFtag = parsexmltag(Rn[0], false);
					state.push([Rn[3], true]);
				} break;

			case 'script': break; // 3.13 <office:script>
			case 'libraries': break; // TODO: <ooo:libraries>
			case 'automatic-styles': break; // 3.15.3 <office:automatic-styles>
			case 'master-styles': break; // TODO: <office:automatic-styles>

			case 'default-style': // TODO: <style:default-style>
			case 'page-layout': break; // TODO: <style:page-layout>
			case 'style': break; // 16.2 <style:style>
			case 'map': break; // 16.3 <style:map>
			case 'font-face': break; // 16.21 <style:font-face>

			case 'paragraph-properties': break; // 17.6 <style:paragraph-properties>
			case 'table-properties': break; // 17.15 <style:table-properties>
			case 'table-column-properties': break; // 17.16 <style:table-column-properties>
			case 'table-row-properties': break; // 17.17 <style:table-row-properties>
			case 'table-cell-properties': break; // 17.18 <style:table-cell-properties>

			case 'number': // 16.27.3 <number:number>
				switch(state[state.length-1][0]) {
					case 'time-style':
					case 'date-style':
						tag = parsexmltag(Rn[0], false);
						NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
				} break;

			case 'fraction': break; // TODO 16.27.6 <number:fraction>

			case 'day': // 16.27.11 <number:day>
			case 'month': // 16.27.12 <number:month>
			case 'year': // 16.27.13 <number:year>
			case 'era': // 16.27.14 <number:era>
			case 'day-of-week': // 16.27.15 <number:day-of-week>
			case 'week-of-year': // 16.27.16 <number:week-of-year>
			case 'quarter': // 16.27.17 <number:quarter>
			case 'hours': // 16.27.19 <number:hours>
			case 'minutes': // 16.27.20 <number:minutes>
			case 'seconds': // 16.27.21 <number:seconds>
			case 'am-pm': // 16.27.22 <number:am-pm>
				switch(state[state.length-1][0]) {
					case 'time-style':
					case 'date-style':
						tag = parsexmltag(Rn[0], false);
						NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
				} break;

			case 'boolean-style': break; // 16.27.23 <number:boolean-style>
			case 'boolean': break; // 16.27.24 <number:boolean>
			case 'text-style': break; // 16.27.25 <number:text-style>
			case 'text': // 16.27.26 <number:text>
				if(Rn[0].slice(-2) === "/>") break;
				else if(Rn[1]==="/") switch(state[state.length-1][0]) {
					case 'number-style':
					case 'date-style':
					case 'time-style':
						NF += str.slice(pidx, Rn.index);
						break;
				}
				else pidx = Rn.index + Rn[0].length;
				break;
			case 'text-content': break; // 16.27.27 <number:text-content>
			case 'text-properties': break; // 16.27.27 <style:text-properties>

			case 'body': case '电子表格': break; // 3.3 16.9.6 19.726.3

			case 'forms': break; // 12.25.2 13.2
			case 'table-column': break; // 9.1.6 <table:table-column>
S
SheetJS 已提交
16827
			case 'table-header-rows': break; // 9.1.7 <table:table-header-rows>
16828 16829 16830
			/* TODO: outline levels */
			case 'table-row-group': break; // 9.1.9 <table:table-row-group>
			case 'table-column-group': break; // 9.1.10 <table:table-column-group>
S
SheetJS 已提交
16831
			case 'table-header-columns': break; // 9.1.11 <table:table-header-columns>
16832 16833 16834 16835 16836 16837 16838

			case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904

			case 'graphic-properties': break; // 17.21 <style:graphic-properties>
			case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
			case 'named-expressions': break; // 9.4.11 <table:named-expressions>
			case 'named-range': break; // 9.4.12 <table:named-range>
S
SheetJS 已提交
16839 16840
			case 'label-range': break; // 9.4.9 <table:label-range>
			case 'label-ranges': break; // 9.4.10 <table:label-ranges>
16841 16842 16843 16844 16845
			case 'named-expression': break; // 9.4.13 <table:named-expression>
			case 'sort': break; // 9.4.19 <table:sort>
			case 'sort-by': break; // 9.4.20 <table:sort-by>
			case 'sort-groups': break; // 9.4.22 <table:sort-groups>

S
SheetJS 已提交
16846
			case 'tab': break; // 6.1.4 <text:tab>
16847
			case 'line-break': break; // 6.1.5 <text:line-break>
S
SheetJS 已提交
16848 16849
			case 'span': break; // 6.1.7 <text:span>
			case 'p': case '文本串': // 5.1.3 <text:p>
S
SheetJS 已提交
16850
				if(Rn[1]==='/') textp = (textp.length > 0 ? textp + "\n" : "") + parse_text_p(str.slice(textpidx,Rn.index), textptag);
16851 16852
				else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
				break; // <text:p>
S
SheetJS 已提交
16853 16854 16855 16856 16857 16858

			case 'database-range': // 9.4.15 <table:database-range>
				if(Rn[1]==='/') break;
				try {
					var AutoFilter = ods_to_csf_range_3D(parsexmltag(Rn[0])['target-range-address']);
					Sheets[AutoFilter[0]]['!autofilter'] = { ref: AutoFilter[1] };
S
SheetJS 已提交
16859
				} catch(e) {/* empty */}
S
SheetJS 已提交
16860 16861
				break;

16862 16863 16864 16865 16866 16867 16868
			case 's': break; // <text:s>
			case 'date': break; // <*:date>

			case 'object': break; // 10.4.6.2 <draw:object>
			case 'title': case '标题': break; // <*:title> OR <uof:标题>
			case 'desc': break; // <*:desc>

S
SheetJS 已提交
16869
			/* 9.2 Advanced Tables */
16870
			case 'table-source': break; // 9.2.6
S
SheetJS 已提交
16871
			case 'scenario': break; // 9.2.6
16872 16873 16874 16875

			case 'iteration': break; // 9.4.3 <table:iteration>
			case 'content-validations': break; // 9.4.4 <table:
			case 'content-validation': break; // 9.4.5 <table:
S
SheetJS 已提交
16876
			case 'help-message': break; // 9.4.6 <table:
16877 16878 16879 16880 16881 16882 16883 16884 16885 16886 16887 16888 16889 16890 16891 16892 16893 16894 16895 16896 16897 16898 16899 16900 16901 16902 16903 16904 16905 16906 16907 16908 16909 16910 16911
			case 'error-message': break; // 9.4.7 <table:
			case 'database-ranges': break; // 9.4.14 <table:database-ranges>
			case 'filter': break; // 9.5.2 <table:filter>
			case 'filter-and': break; // 9.5.3 <table:filter-and>
			case 'filter-or': break; // 9.5.4 <table:filter-or>
			case 'filter-condition': break; // 9.5.5 <table:filter-condition>

			case 'list-level-style-bullet': break; // 16.31 <text:
			case 'list-level-style-number': break; // 16.32 <text:
			case 'list-level-properties': break; // 17.19 <style:

			/* 7.3 Document Fields */
			case 'sender-firstname': // 7.3.6.2
			case 'sender-lastname': // 7.3.6.3
			case 'sender-initials': // 7.3.6.4
			case 'sender-title': // 7.3.6.5
			case 'sender-position': // 7.3.6.6
			case 'sender-email': // 7.3.6.7
			case 'sender-phone-private': // 7.3.6.8
			case 'sender-fax': // 7.3.6.9
			case 'sender-company': // 7.3.6.10
			case 'sender-phone-work': // 7.3.6.11
			case 'sender-street': // 7.3.6.12
			case 'sender-city': // 7.3.6.13
			case 'sender-postal-code': // 7.3.6.14
			case 'sender-country': // 7.3.6.15
			case 'sender-state-or-province': // 7.3.6.16
			case 'author-name': // 7.3.7.1
			case 'author-initials': // 7.3.7.2
			case 'chapter': // 7.3.8
			case 'file-name': // 7.3.9
			case 'template-name': // 7.3.9
			case 'sheet-name': // 7.3.9
				break;

S
SheetJS 已提交
16912 16913
			case 'event-listener':
				break;
16914 16915 16916 16917 16918 16919 16920 16921 16922 16923 16924 16925 16926 16927 16928 16929 16930
			/* TODO: FODS Properties */
			case 'initial-creator':
			case 'creation-date':
			case 'generator':
			case 'document-statistic':
			case 'user-defined':
				break;

			/* TODO: FODS Config */
			case 'config-item':
				break;

			/* TODO: style tokens */
			case 'page-number': break; // TODO <text:page-number>
			case 'page-count': break; // TODO <text:page-count>
			case 'time': break; // TODO <text:time>

S
SheetJS 已提交
16931 16932 16933 16934 16935 16936
			/* 9.3 Advanced Table Cells */
			case 'cell-range-source': break; // 9.3.1 <table:
			case 'detective': break; // 9.3.2 <table:
			case 'operation': break; // 9.3.3 <table:
			case 'highlighted-range': break; // 9.3.4 <table:

16937 16938 16939 16940 16941 16942 16943 16944 16945 16946 16947 16948 16949 16950 16951 16952 16953 16954 16955 16956 16957 16958 16959 16960 16961 16962 16963 16964 16965 16966 16967 16968 16969 16970 16971 16972 16973 16974
			/* 9.6 Data Pilot Tables <table: */
			case 'data-pilot-table': // 9.6.3
			case 'source-cell-range': // 9.6.5
			case 'source-service': // 9.6.6
			case 'data-pilot-field': // 9.6.7
			case 'data-pilot-level': // 9.6.8
			case 'data-pilot-subtotals': // 9.6.9
			case 'data-pilot-subtotal': // 9.6.10
			case 'data-pilot-members': // 9.6.11
			case 'data-pilot-member': // 9.6.12
			case 'data-pilot-display-info': // 9.6.13
			case 'data-pilot-sort-info': // 9.6.14
			case 'data-pilot-layout-info': // 9.6.15
			case 'data-pilot-field-reference': // 9.6.16
			case 'data-pilot-groups': // 9.6.17
			case 'data-pilot-group': // 9.6.18
			case 'data-pilot-group-member': // 9.6.19
				break;

			/* 10.3 Drawing Shapes */
			case 'rect': // 10.3.2
				break;

			/* 14.6 DDE Connections */
			case 'dde-connection-decls': // 14.6.2 <text:
			case 'dde-connection-decl': // 14.6.3 <text:
			case 'dde-link': // 14.6.4 <table:
			case 'dde-source': // 14.6.5 <office:
				break;

			case 'properties': break; // 13.7 <form:properties>
			case 'property': break; // 13.8 <form:property>

			case 'a': break; // 6.1.8 hyperlink

			/* non-standard */
			case 'table-protection': break;
			case 'data-pilot-grand-total': break; // <table:
S
SheetJS 已提交
16975
			case 'office-document-common-attrs': break; // bare
16976 16977 16978 16979
			default:
				if(Rn[2] === 'dc:') break; // TODO: properties
				if(Rn[2] === 'draw:') break; // TODO: drawing
				if(Rn[2] === 'style:') break; // TODO: styles
S
SheetJS 已提交
16980
				if(Rn[2] === 'form:') break; // TODO: forms
16981 16982 16983 16984 16985
				if(Rn[2] === 'calcext:') break; // ignore undocumented extensions
				if(Rn[2] === 'loext:') break; // ignore undocumented extensions
				if(Rn[2] === 'uof:') break; // TODO: uof
				if(Rn[2] === '表:') break; // TODO: uof
				if(Rn[2] === '字:') break; // TODO: uof
S
SheetJS 已提交
16986
				if(opts.WTF) throw new Error(Rn);
16987 16988 16989 16990 16991 16992 16993 16994
		}
		var out = {
			Sheets: Sheets,
			SheetNames: SheetNames
		};
		return out;
	};
})();
S
SheetJS 已提交
16995 16996 16997 16998 16999 17000 17001 17002 17003 17004 17005 17006 17007 17008 17009 17010 17011 17012 17013 17014 17015

function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
	opts = opts || ({}/*:any*/);
	var ods = !!safegetzipfile(zip, 'objectdata');
	if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
	var content = getzipstr(zip, 'content.xml');
	if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
	return parse_content_xml(ods ? content : utf8read(content), opts);
}
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) {
	return parse_content_xml(data, opts);
}

/* OpenDocument */
var write_styles_ods/*:{(wb:any, opts:any):string}*/ = (function() {
	var payload = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><office:document-styles xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" office:version="1.2"></office:document-styles>';
	return function wso(wb, opts) {
		return payload;
	};
})();
var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
17016
	var null_cell_xml = '          <table:table-cell />\n';
17017
	var covered_cell_xml = '          <table:covered-table-cell/>\n';
17018 17019 17020 17021 17022
	var write_ws = function(ws, wb, i/*:number*/, opts)/*:string*/ {
		/* Section 9 Tables */
		var o = [];
		o.push('      <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n');
		var R=0,C=0, range = decode_range(ws['!ref']);
17023
		var marr = ws['!merges'] || [], mi = 0;
S
SheetJS 已提交
17024
		var dense = Array.isArray(ws);
17025 17026 17027 17028 17029
		for(R = 0; R < range.s.r; ++R) o.push('        <table:table-row></table:table-row>\n');
		for(; R <= range.e.r; ++R) {
			o.push('        <table:table-row>\n');
			for(C=0; C < range.s.c; ++C) o.push(null_cell_xml);
			for(; C <= range.e.c; ++C) {
S
SheetJS 已提交
17030
				var skip = false, ct = {}, textp = "";
17031 17032 17033 17034 17035 17036
				for(mi = 0; mi != marr.length; ++mi) {
					if(marr[mi].s.c > C) continue;
					if(marr[mi].s.r > R) continue;
					if(marr[mi].e.c < C) continue;
					if(marr[mi].e.r < R) continue;
					if(marr[mi].s.c != C || marr[mi].s.r != R) skip = true;
S
SheetJS 已提交
17037 17038
					ct['table:number-columns-spanned'] = (marr[mi].e.c - marr[mi].s.c + 1);
					ct['table:number-rows-spanned'] =    (marr[mi].e.r - marr[mi].s.r + 1);
17039 17040 17041
					break;
				}
				if(skip) { o.push(covered_cell_xml); continue; }
S
SheetJS 已提交
17042
				var ref = encode_cell({r:R, c:C}), cell = dense ? (ws[R]||[])[C]: ws[ref];
S
SheetJS 已提交
17043
				if(cell && cell.f) {
S
SheetJS 已提交
17044
					ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f));
S
SheetJS 已提交
17045 17046 17047
					if(cell.F) {
						if(cell.F.substr(0, ref.length) == ref) {
							var _Fref = decode_range(cell.F);
S
SheetJS 已提交
17048 17049 17050
							ct['table:number-matrix-columns-spanned'] = (_Fref.e.c - _Fref.s.c + 1);
							ct['table:number-matrix-rows-spanned'] =    (_Fref.e.r - _Fref.s.r + 1);
						}
S
SheetJS 已提交
17051 17052
					}
				}
S
SheetJS 已提交
17053 17054 17055 17056 17057 17058 17059 17060 17061 17062 17063 17064 17065 17066 17067 17068 17069 17070 17071 17072 17073 17074
				if(!cell) { o.push(null_cell_xml); continue; }
				switch(cell.t) {
					case 'b':
						textp = (cell.v ? 'TRUE' : 'FALSE');
						ct['office:value-type'] = "boolean";
						ct['office:boolean-value'] = (cell.v ? 'true' : 'false');
						break;
					case 'n':
						textp = (cell.w||String(cell.v||0));
						ct['office:value-type'] = "float";
						ct['office:value'] = (cell.v||0);
						break;
					case 's': case 'str':
						textp = escapexml(cell.v);
						ct['office:value-type'] = "string";
						break;
					case 'd':
						textp = (cell.w||(parseDate(cell.v).toISOString()));
						ct['office:value-type'] = "date";
						ct['office:date-value'] = (parseDate(cell.v).toISOString());
						ct['table:style-name'] = "ce1";
						break;
17075
					//case 'e':
S
SheetJS 已提交
17076 17077
					default: o.push(null_cell_xml); continue;
				}
S
SheetJS 已提交
17078
				o.push('          ' + writextag('table:table-cell', writextag('text:p', textp, {}), ct) + '\n');
17079 17080 17081 17082 17083 17084 17085
			}
			o.push('        </table:table-row>\n');
		}
		o.push('      </table:table>\n');
		return o.join("");
	};

S
SheetJS 已提交
17086 17087 17088 17089 17090 17091 17092 17093 17094 17095 17096 17097 17098
	var write_automatic_styles_ods = function(o/*:Array<string>*/) {
		o.push(' <office:automatic-styles>\n');
		o.push('  <number:date-style style:name="N37" number:automatic-order="true">\n');
		o.push('   <number:month number:style="long"/>\n');
		o.push('   <number:text>/</number:text>\n');
		o.push('   <number:day number:style="long"/>\n');
		o.push('   <number:text>/</number:text>\n');
		o.push('   <number:year/>\n');
		o.push('  </number:date-style>\n');
		o.push('  <style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N37"/>\n');
		o.push(' </office:automatic-styles>\n');
	};

17099 17100 17101
	return function wcx(wb, opts) {
		var o = [XML_HEADER];
		/* 3.1.3.2 */
S
SheetJS 已提交
17102 17103 17104 17105 17106 17107 17108 17109 17110 17111 17112 17113 17114 17115 17116 17117 17118 17119 17120 17121 17122 17123 17124 17125 17126 17127 17128 17129 17130 17131 17132 17133 17134 17135 17136 17137 17138 17139 17140 17141 17142 17143 17144 17145 17146 17147 17148 17149
		var attr = wxt_helper({
			'xmlns:office':       "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
			'xmlns:table':        "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
			'xmlns:style':        "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
			'xmlns:text':         "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
			'xmlns:draw':         "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
			'xmlns:fo':           "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
			'xmlns:xlink':        "http://www.w3.org/1999/xlink",
			'xmlns:dc':           "http://purl.org/dc/elements/1.1/",
			'xmlns:meta':         "urn:oasis:names:tc:opendocument:xmlns:meta:1.0",
			'xmlns:number':       "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
			'xmlns:presentation': "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0",
			'xmlns:svg':          "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
			'xmlns:chart':        "urn:oasis:names:tc:opendocument:xmlns:chart:1.0",
			'xmlns:dr3d':         "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0",
			'xmlns:math':         "http://www.w3.org/1998/Math/MathML",
			'xmlns:form':         "urn:oasis:names:tc:opendocument:xmlns:form:1.0",
			'xmlns:script':       "urn:oasis:names:tc:opendocument:xmlns:script:1.0",
			'xmlns:ooo':          "http://openoffice.org/2004/office",
			'xmlns:ooow':         "http://openoffice.org/2004/writer",
			'xmlns:oooc':         "http://openoffice.org/2004/calc",
			'xmlns:dom':          "http://www.w3.org/2001/xml-events",
			'xmlns:xforms':       "http://www.w3.org/2002/xforms",
			'xmlns:xsd':          "http://www.w3.org/2001/XMLSchema",
			'xmlns:xsi':          "http://www.w3.org/2001/XMLSchema-instance",
			'xmlns:sheet':        "urn:oasis:names:tc:opendocument:sh33tjs:1.0",
			'xmlns:rpt':          "http://openoffice.org/2005/report",
			'xmlns:of':           "urn:oasis:names:tc:opendocument:xmlns:of:1.2",
			'xmlns:xhtml':        "http://www.w3.org/1999/xhtml",
			'xmlns:grddl':        "http://www.w3.org/2003/g/data-view#",
			'xmlns:tableooo':     "http://openoffice.org/2009/table",
			'xmlns:drawooo':      "http://openoffice.org/2010/draw",
			'xmlns:calcext':      "urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0",
			'xmlns:loext':        "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0",
			'xmlns:field':        "urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0",
			'xmlns:formx':        "urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0",
			'xmlns:css3t':        "http://www.w3.org/TR/css3-text/",
			'office:version':     "1.2"
		});

		var fods = wxt_helper({
			'xmlns:config':"urn:oasis:names:tc:opendocument:xmlns:config:1.0",
			'office:mimetype':"application/vnd.oasis.opendocument.spreadsheet"
		});

		if(opts.bookType == "fods") o.push('<office:document' + attr + fods + '>\n');
		else o.push('<office:document-content' + attr  + '>\n');
		write_automatic_styles_ods(o);
17150 17151 17152 17153 17154 17155 17156 17157 17158 17159 17160 17161
		o.push('  <office:body>\n');
		o.push('    <office:spreadsheet>\n');
		for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts));
		o.push('    </office:spreadsheet>\n');
		o.push('  </office:body>\n');
		if(opts.bookType == "fods") o.push('</office:document>');
		else o.push('</office:document-content>');
		return o.join("");
	};
})();

function write_ods(wb/*:any*/, opts/*:any*/) {
S
SheetJS 已提交
17162
	if(opts.bookType == "fods") return write_content_ods(wb, opts);
17163 17164 17165 17166 17167 17168 17169 17170 17171 17172 17173 17174 17175 17176

	/*:: if(!jszip) throw new Error("JSZip is not available"); */
	var zip = new jszip();
	var f = "";

	var manifest/*:Array<Array<string> >*/ = [];
	var rdf = [];

	/* 3:3.3 and 2:2.2.4 */
	f = "mimetype";
	zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");

	/* Part 1 Section 2.2 Documents */
	f = "content.xml";
S
SheetJS 已提交
17177
	zip.file(f, write_content_ods(wb, opts));
17178 17179 17180
	manifest.push([f, "text/xml"]);
	rdf.push([f, "ContentFile"]);

S
SheetJS 已提交
17181 17182 17183 17184 17185 17186
	/* TODO: these are hard-coded styles to satiate excel */
	f = "styles.xml";
	zip.file(f, write_styles_ods(wb, opts));
	manifest.push([f, "text/xml"]);
	rdf.push([f, "StylesFile"]);

17187 17188 17189 17190 17191
	/* Part 3 Section 6 Metadata Manifest File */
	f = "manifest.rdf";
	zip.file(f, write_rdf(rdf, opts));
	manifest.push([f, "application/rdf+xml"]);

S
SheetJS 已提交
17192 17193 17194 17195 17196 17197
	/* TODO: this is hard-coded to satiate excel */
	f = "meta.xml";
	zip.file(f, write_meta_ods(wb, opts));
	manifest.push([f, "text/xml"]);
	rdf.push([f, "MetadataFile"]);

17198 17199 17200 17201 17202
	/* Part 3 Section 4 Manifest File */
	f = "META-INF/manifest.xml";
	zip.file(f, write_manifest(manifest, opts));

	return zip;
17203
}
S
SheetJS 已提交
17204 17205 17206 17207 17208 17209 17210

/* actual implementation elsewhere, wrappers are for read/write */
function write_obj_str(factory/*:WriteObjStrFactory*/) {
	return function write_str(wb/*:Workbook*/, o/*:WriteOpts*/)/*:string*/ {
		var idx = 0;
		for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i;
		if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
S
SheetJS 已提交
17211
		return factory.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb);
S
SheetJS 已提交
17212 17213 17214 17215 17216 17217 17218 17219
	};
}

var write_htm_str = write_obj_str(HTML_);
var write_csv_str = write_obj_str({from_sheet:sheet_to_csv});
var write_slk_str = write_obj_str(SYLK);
var write_dif_str = write_obj_str(DIF);
var write_prn_str = write_obj_str(PRN);
S
SheetJS 已提交
17220
var write_rtf_str = write_obj_str(RTF);
S
SheetJS 已提交
17221
var write_txt_str = write_obj_str({from_sheet:sheet_to_txt});
S
SheetJS 已提交
17222
function fix_opts_func(defaults/*:Array<Array<any> >*/)/*:{(o:any):void}*/ {
S
SheetJS 已提交
17223 17224 17225 17226 17227 17228 17229 17230 17231 17232 17233 17234 17235 17236
	return function fix_opts(opts) {
		for(var i = 0; i != defaults.length; ++i) {
			var d = defaults[i];
			if(opts[d[0]] === undefined) opts[d[0]] = d[1];
			if(d[2] === 'n') opts[d[0]] = Number(opts[d[0]]);
		}
	};
}

var fix_read_opts = fix_opts_func([
	['cellNF', false], /* emit cell number format string as .z */
	['cellHTML', true], /* emit html string as .h */
	['cellFormula', true], /* emit formulae as .f */
	['cellStyles', false], /* emits style/theme as .s */
S
SheetJS 已提交
17237
	['cellText', true], /* emit formatted text as .w */
S
SheetJS 已提交
17238 17239 17240 17241 17242 17243 17244 17245 17246 17247 17248 17249 17250 17251 17252 17253 17254 17255 17256 17257 17258 17259 17260 17261 17262 17263 17264
	['cellDates', false], /* emit date cells with type `d` */

	['sheetStubs', false], /* emit empty cells */
	['sheetRows', 0, 'n'], /* read n rows (0 = read all rows) */

	['bookDeps', false], /* parse calculation chains */
	['bookSheets', false], /* only try to get sheet names (no Sheets) */
	['bookProps', false], /* only try to get properties (no Sheets) */
	['bookFiles', false], /* include raw file structure (keys, files, cfb) */
	['bookVBA', false], /* include vba raw data (vbaraw) */

	['password',''], /* password */
	['WTF', false] /* WTF mode (throws errors) */
]);


var fix_write_opts = fix_opts_func([
	['cellDates', false], /* write date cells with type `d` */

	['bookSST', false], /* Generate Shared String Table */

	['bookType', 'xlsx'], /* Type of workbook (xlsx/m/b) */

	['compression', false], /* Use file compression */

	['WTF', false] /* WTF mode (throws errors) */
]);
S
SheetJS 已提交
17265
function get_sheet_type(n/*:string*/)/*:string*/ {
S
SheetJS 已提交
17266 17267 17268 17269 17270 17271 17272
	if(RELS.WS.indexOf(n) > -1) return "sheet";
	if(RELS.CS && n == RELS.CS) return "chart";
	if(RELS.DS && n == RELS.DS) return "dialog";
	if(RELS.MS && n == RELS.MS) return "macro";
	if(!n || !n.length) return "sheet";
	return n;
}
S
SheetJS 已提交
17273 17274 17275
function safe_parse_wbrels(wbrels, sheets) {
	if(!wbrels) return 0;
	try {
S
SheetJS 已提交
17276
		wbrels = sheets.map(function pwbr(w) { if(!w.id) w.id = w.strRelID; return [w.name, wbrels['!id'][w.id].Target, get_sheet_type(wbrels['!id'][w.id].Type)]; });
S
SheetJS 已提交
17277 17278 17279 17280
	} catch(e) { return null; }
	return !wbrels || wbrels.length === 0 ? null : wbrels;
}

17281
function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, sheetRels, sheets, stype/*:string*/, opts, wb, themes, styles) {
S
SheetJS 已提交
17282
	try {
S
SheetJS 已提交
17283
		sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
17284 17285 17286 17287 17288 17289 17290 17291 17292 17293 17294 17295 17296 17297
		var data = getzipdata(zip, path);
		switch(stype) {
			case 'sheet': sheets[sheet]=parse_ws(data, path, opts,sheetRels[sheet], wb, themes, styles); break;
			case 'chart':
				var cs = parse_cs(data, path, opts,sheetRels[sheet], wb, themes, styles);
				sheets[sheet] = cs;
				if(!cs || !cs['!chart']) break;
				var dfile = resolve_path(cs['!chart'].Target, path);
				var drelsp = get_rels_path(dfile);
				var draw = parse_drawing(getzipstr(zip, dfile, true), parse_rels(getzipstr(zip,drelsp,true), dfile));
				var chartp = resolve_path(draw, dfile);
				var crelsp = get_rels_path(chartp);
				cs = parse_chart(getzipstr(zip, chartp, true), chartp, opts, parse_rels(getzipstr(zip, crelsp,true), chartp), wb, cs);
				break;
S
SheetJS 已提交
17298 17299
			case 'macro': sheets[sheet]=parse_ms(data, path, opts,sheetRels[sheet], wb, themes, styles); break;
			case 'dialog': sheets[sheet]=parse_ds(data, path, opts,sheetRels[sheet], wb, themes, styles); break;
17300
		}
S
SheetJS 已提交
17301 17302 17303
	} catch(e) { if(opts.WTF) throw e; }
}

17304
var nodirs = function nodirs(x/*:string*/)/*:boolean*/{return x.slice(-1) != '/';};
S
SheetJS 已提交
17305
function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
S
SheetJS 已提交
17306 17307 17308 17309 17310 17311 17312
	make_ssf(SSF);
	opts = opts || {};
	fix_read_opts(opts);
	reset_cp();

	/* OpenDocument Part 3 Section 2.2.1 OpenDocument Package */
	if(safegetzipfile(zip, 'META-INF/manifest.xml')) return parse_ods(zip, opts);
17313 17314
	/* UOC */
	if(safegetzipfile(zip, 'objectdata.xml')) return parse_ods(zip, opts);
S
SheetJS 已提交
17315 17316

	var entries = keys(zip.files).filter(nodirs).sort();
S
SheetJS 已提交
17317
	var dir = parse_ct((getzipstr(zip, '[Content_Types].xml')/*:?any*/), opts);
S
SheetJS 已提交
17318 17319 17320 17321 17322 17323 17324 17325
	var xlsb = false;
	var sheets, binname;
	if(dir.workbooks.length === 0) {
		binname = "xl/workbook.xml";
		if(getzipdata(zip,binname, true)) dir.workbooks.push(binname);
	}
	if(dir.workbooks.length === 0) {
		binname = "xl/workbook.bin";
17326
		if(!getzipdata(zip,binname,true)) throw new Error("Could not find workbook");
S
SheetJS 已提交
17327 17328 17329
		dir.workbooks.push(binname);
		xlsb = true;
	}
17330
	if(dir.workbooks[0].slice(-3) == "bin") xlsb = true;
S
SheetJS 已提交
17331 17332
	if(xlsb) set_cp(1200);

S
SheetJS 已提交
17333 17334
	var themes = ({}/*:any*/);
	var styles = ({}/*:any*/);
S
SheetJS 已提交
17335 17336 17337 17338
	if(!opts.bookSheets && !opts.bookProps) {
		strs = [];
		if(dir.sst) strs=parse_sst(getzipdata(zip, dir.sst.replace(/^\//,'')), dir.sst, opts);

S
SheetJS 已提交
17339
		if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts);
P
Pieter Sheth-Voss 已提交
17340 17341

		if(dir.style) styles = parse_sty(getzipdata(zip, dir.style.replace(/^\//,'')),dir.style, themes, opts);
S
SheetJS 已提交
17342 17343 17344 17345 17346 17347 17348
	}

	var wb = parse_wb(getzipdata(zip, dir.workbooks[0].replace(/^\//,'')), dir.workbooks[0], opts);

	var props = {}, propdata = "";

	if(dir.coreprops.length !== 0) {
S
SheetJS 已提交
17349
		propdata = getzipstr(zip, dir.coreprops[0].replace(/^\//,''), true);
S
SheetJS 已提交
17350 17351
		if(propdata) props = parse_core_props(propdata);
		if(dir.extprops.length !== 0) {
S
SheetJS 已提交
17352
			propdata = getzipstr(zip, dir.extprops[0].replace(/^\//,''), true);
17353
			if(propdata) parse_ext_props(propdata, props, opts);
S
SheetJS 已提交
17354 17355 17356 17357 17358 17359
		}
	}

	var custprops = {};
	if(!opts.bookSheets || opts.bookProps) {
		if (dir.custprops.length !== 0) {
S
SheetJS 已提交
17360
			propdata = getzipstr(zip, dir.custprops[0].replace(/^\//,''), true);
S
SheetJS 已提交
17361 17362 17363 17364
			if(propdata) custprops = parse_cust_props(propdata, opts);
		}
	}

S
SheetJS 已提交
17365
	var out = ({}/*:any*/);
S
SheetJS 已提交
17366
	if(opts.bookSheets || opts.bookProps) {
17367 17368
		if(wb.Sheets) sheets = wb.Sheets.map(function pluck(x){ return x.name; });
		else if(props.Worksheets && props.SheetNames.length > 0) sheets=props.SheetNames;
S
SheetJS 已提交
17369
		if(opts.bookProps) { out.Props = props; out.Custprops = custprops; }
S
SheetJS 已提交
17370
		if(opts.bookSheets && typeof sheets !== 'undefined') out.SheetNames = sheets;
S
SheetJS 已提交
17371 17372 17373 17374 17375 17376 17377 17378
		if(opts.bookSheets ? out.SheetNames : opts.bookProps) return out;
	}
	sheets = {};

	var deps = {};
	if(opts.bookDeps && dir.calcchain) deps=parse_cc(getzipdata(zip, dir.calcchain.replace(/^\//,'')),dir.calcchain,opts);

	var i=0;
S
SheetJS 已提交
17379
	var sheetRels = ({}/*:any*/);
S
SheetJS 已提交
17380
	var path, relsPath;
S
SheetJS 已提交
17381

S
SheetJS 已提交
17382
	{
S
SheetJS 已提交
17383 17384 17385 17386 17387 17388
		var wbsheets = wb.Sheets;
		props.Worksheets = wbsheets.length;
		props.SheetNames = [];
		for(var j = 0; j != wbsheets.length; ++j) {
			props.SheetNames[j] = wbsheets[j].name;
		}
S
SheetJS 已提交
17389
	}
S
SheetJS 已提交
17390 17391 17392

	var wbext = xlsb ? "bin" : "xml";
	var wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
S
SheetJS 已提交
17393
	var wbrels = parse_rels(getzipstr(zip, wbrelsfile, true), wbrelsfile);
S
SheetJS 已提交
17394 17395 17396 17397
	if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
	/* Numbers iOS hack */
	var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
	for(i = 0; i != props.Worksheets; ++i) {
17398 17399 17400 17401 17402
		var stype = "sheet";
		if(wbrels && wbrels[i]) {
			path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
			stype = wbrels[i][2];
		} else {
S
SheetJS 已提交
17403 17404 17405 17406
			path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
			path = path.replace(/sheet0\./,"sheet.");
		}
		relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
17407
		safe_parse_sheet(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, stype, opts, wb, themes, styles);
S
SheetJS 已提交
17408 17409 17410 17411
	}

	if(dir.comments) parse_comments(zip, dir.comments, sheets, sheetRels, opts);

S
SheetJS 已提交
17412
	out = ({
S
SheetJS 已提交
17413 17414 17415 17416 17417 17418 17419 17420 17421 17422 17423
		Directory: dir,
		Workbook: wb,
		Props: props,
		Custprops: custprops,
		Deps: deps,
		Sheets: sheets,
		SheetNames: props.SheetNames,
		Strings: strs,
		Styles: styles,
		Themes: themes,
		SSF: SSF.get_table()
S
SheetJS 已提交
17424
	}/*:any*/);
S
SheetJS 已提交
17425 17426 17427 17428 17429
	if(opts.bookFiles) {
		out.keys = entries;
		out.files = zip.files;
	}
	if(opts.bookVBA) {
M
MURAKAMI Masahiko 已提交
17430
		if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,dir.vba[0].replace(/^\//,''),true);
S
SheetJS 已提交
17431
		else if(dir.defaults && dir.defaults.bin === 'application/vnd.ms-office.vbaProject') out.vbaraw = getzipdata(zip,'xl/vbaProject.bin',true);
S
SheetJS 已提交
17432 17433 17434
	}
	return out;
}
S
SheetJS 已提交
17435 17436 17437 17438

/* references to [MS-OFFCRYPTO] */
function parse_xlsxcfb(cfb, opts/*:?ParseOpts*/)/*:Workbook*/ {
	var f = 'Version';
S
SheetJS 已提交
17439
	var data = CFB.find(cfb, f);
S
SheetJS 已提交
17440
	if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
S
SheetJS 已提交
17441 17442 17443 17444
	var version = parse_DataSpaceVersionInfo(data.content);

	/* 2.3.4.1 */
	f = 'DataSpaceMap';
S
SheetJS 已提交
17445
	data = CFB.find(cfb, f);
S
SheetJS 已提交
17446
	if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
S
SheetJS 已提交
17447
	var dsm = parse_DataSpaceMap(data.content);
S
SheetJS 已提交
17448
	if(dsm.length != 1 || dsm[0].comps.length != 1 || dsm[0].comps[0].t != 0 || dsm[0].name != "StrongEncryptionDataSpace" || dsm[0].comps[0].v != "EncryptedPackage")
S
SheetJS 已提交
17449 17450 17451
		throw new Error("ECMA-376 Encrypted file bad " + f);

	f = 'StrongEncryptionDataSpace';
S
SheetJS 已提交
17452
	data = CFB.find(cfb, f);
S
SheetJS 已提交
17453
	if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
S
SheetJS 已提交
17454 17455 17456 17457 17458 17459
	var seds = parse_DataSpaceDefinition(data.content);
	if(seds.length != 1 || seds[0] != "StrongEncryptionTransform")
		throw new Error("ECMA-376 Encrypted file bad " + f);

	/* 2.3.4.3 */
	f = '!Primary';
S
SheetJS 已提交
17460
	data = CFB.find(cfb, f);
S
SheetJS 已提交
17461
	if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
S
SheetJS 已提交
17462 17463 17464
	var hdr = parse_Primary(data.content);

	f = 'EncryptionInfo';
S
SheetJS 已提交
17465
	data = CFB.find(cfb, f);
S
SheetJS 已提交
17466
	if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
S
SheetJS 已提交
17467 17468 17469 17470 17471
	var einfo = parse_EncryptionInfo(data.content);

	throw new Error("File is password-protected");
}

S
SheetJS 已提交
17472
function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
S
SheetJS 已提交
17473
	_shapeid = 1024;
S
SheetJS 已提交
17474 17475 17476 17477 17478 17479
	if(opts.bookType == "ods") return write_ods(wb, opts);
	if(wb && !wb.SSF) {
		wb.SSF = SSF.get_table();
	}
	if(wb && wb.SSF) {
		make_ssf(SSF); SSF.load_table(wb.SSF);
S
SheetJS 已提交
17480
		// $FlowIgnore
S
SheetJS 已提交
17481
		opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
S
SheetJS 已提交
17482
		opts.ssf = wb.SSF;
S
SheetJS 已提交
17483 17484
	}
	opts.rels = {}; opts.wbrels = {};
S
SheetJS 已提交
17485
	opts.Strings = /*::((*/[]/*:: :any):SST)*/; opts.Strings.Count = 0; opts.Strings.Unique = 0;
S
SheetJS 已提交
17486
	var wbext = opts.bookType == "xlsb" ? "bin" : "xml";
S
SheetJS 已提交
17487
	var vbafmt = opts.bookType == "xlsb" || opts.bookType == "xlsm";
S
SheetJS 已提交
17488
	var ct = new_ct();
S
SheetJS 已提交
17489
	fix_write_opts(opts = opts || {});
S
SheetJS 已提交
17490
	/*:: if(!jszip) throw new Error("JSZip is not available"); */
S
SheetJS 已提交
17491 17492 17493 17494 17495 17496
	var zip = new jszip();
	var f = "", rId = 0;

	opts.cellXfs = [];
	get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}});

S
SheetJS 已提交
17497 17498
	if(!wb.Props) wb.Props = {};

S
SheetJS 已提交
17499 17500 17501 17502 17503
	f = "docProps/core.xml";
	zip.file(f, write_core_props(wb.Props, opts));
	ct.coreprops.push(f);
	add_rels(opts.rels, 2, f, RELS.CORE_PROPS);

S
SheetJS 已提交
17504
	/*::if(!wb.Props) throw "unreachable"; */
S
SheetJS 已提交
17505
	f = "docProps/app.xml";
S
SheetJS 已提交
17506
	if(wb.Props && wb.Props.SheetNames){/* empty */}
S
TXT/PRN  
SheetJS 已提交
17507
	else if(!wb.Workbook || !wb.Workbook.Sheets) wb.Props.SheetNames = wb.SheetNames;
S
SheetJS 已提交
17508
	// $FlowIgnore
S
TXT/PRN  
SheetJS 已提交
17509
	else wb.Props.SheetNames = wb.SheetNames.map(function(x,i) { return [(wb.Workbook.Sheets[i]||{}).Hidden != 2, x];}).filter(function(x) { return x[0]; }).map(function(x) { return x[1]; });
S
SheetJS 已提交
17510
	wb.Props.Worksheets = wb.Props.SheetNames.length;
S
SheetJS 已提交
17511 17512 17513 17514 17515 17516 17517 17518 17519 17520 17521 17522 17523 17524 17525 17526 17527
	zip.file(f, write_ext_props(wb.Props, opts));
	ct.extprops.push(f);
	add_rels(opts.rels, 3, f, RELS.EXT_PROPS);

	if(wb.Custprops !== wb.Props && keys(wb.Custprops||{}).length > 0) {
		f = "docProps/custom.xml";
		zip.file(f, write_cust_props(wb.Custprops, opts));
		ct.custprops.push(f);
		add_rels(opts.rels, 4, f, RELS.CUST_PROPS);
	}

	f = "xl/workbook." + wbext;
	zip.file(f, write_wb(wb, f, opts));
	ct.workbooks.push(f);
	add_rels(opts.rels, 1, f, RELS.WB);

	for(rId=1;rId <= wb.SheetNames.length; ++rId) {
S
SheetJS 已提交
17528
		var wsrels = {'!id':{}};
S
SheetJS 已提交
17529
		var ws = wb.Sheets[wb.SheetNames[rId-1]];
S
SheetJS 已提交
17530 17531 17532 17533 17534 17535 17536 17537 17538 17539 17540 17541 17542 17543 17544 17545
		var _type = (ws || {})["!type"] || "sheet";
		switch(_type) {
		case "chart": /*
			f = "xl/chartsheets/sheet" + rId + "." + wbext;
			zip.file(f, write_cs(rId-1, f, opts, wb, wsrels));
			ct.charts.push(f);
			add_rels(wsrels, -1, "chartsheets/sheet" + rId + "." + wbext, RELS.CS);
			break; */
			/* falls through */
		default:
			f = "xl/worksheets/sheet" + rId + "." + wbext;
			zip.file(f, write_ws(rId-1, f, opts, wb, wsrels));
			ct.sheets.push(f);
			add_rels(opts.wbrels, -1, "worksheets/sheet" + rId + "." + wbext, RELS.WS[0]);
		}

S
SheetJS 已提交
17546 17547 17548 17549 17550 17551 17552 17553 17554 17555 17556 17557 17558 17559 17560
		if(ws) {
			var comments = ws['!comments'];
			if(comments && comments.length > 0) {
				var cf = "xl/comments" + rId + "." + wbext;
				zip.file(cf, write_cmnt(comments, cf, opts));
				ct.comments.push(cf);
				add_rels(wsrels, -1, "../comments" + rId + "." + wbext, RELS.CMNT);
			}
			if(ws['!legacy']) {
				zip.file("xl/drawings/vmlDrawing" + (rId) + ".vml", write_comments_vml(rId, ws['!comments']));
			}
			delete ws['!comments'];
			delete ws['!legacy'];
		}

S
SheetJS 已提交
17561
		if(wsrels['!id'].rId1) zip.file(get_rels_path(f), write_rels(wsrels));
S
SheetJS 已提交
17562 17563 17564 17565 17566 17567
	}

	if(opts.Strings != null && opts.Strings.length > 0) {
		f = "xl/sharedStrings." + wbext;
		zip.file(f, write_sst(opts.Strings, f, opts));
		ct.strs.push(f);
S
SheetJS 已提交
17568
		add_rels(opts.wbrels, -1, "sharedStrings." + wbext, RELS.SST);
S
SheetJS 已提交
17569 17570 17571 17572 17573
	}

	/* TODO: something more intelligent with themes */

	f = "xl/theme/theme1.xml";
S
SheetJS 已提交
17574
	zip.file(f, write_theme(wb.Themes, opts));
S
SheetJS 已提交
17575
	ct.themes.push(f);
S
SheetJS 已提交
17576
	add_rels(opts.wbrels, -1, "theme/theme1.xml", RELS.THEME);
S
SheetJS 已提交
17577 17578 17579 17580 17581 17582

	/* TODO: something more intelligent with styles */

	f = "xl/styles." + wbext;
	zip.file(f, write_sty(wb, f, opts));
	ct.styles.push(f);
S
SheetJS 已提交
17583
	add_rels(opts.wbrels, -1, "styles." + wbext, RELS.STY);
S
SheetJS 已提交
17584

S
SheetJS 已提交
17585 17586 17587 17588
	if(wb.vbaraw && vbafmt) {
		f = "xl/vbaProject.bin";
		zip.file(f, wb.vbaraw);
		ct.vba.push(f);
S
SheetJS 已提交
17589
		add_rels(opts.wbrels, -1, "vbaProject.bin", RELS.VBA);
S
SheetJS 已提交
17590 17591
	}

S
SheetJS 已提交
17592
	zip.file("[Content_Types].xml", write_ct(ct, opts));
S
SheetJS 已提交
17593 17594
	zip.file('_rels/.rels', write_rels(opts.rels));
	zip.file('xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));
S
SheetJS 已提交
17595 17596

	delete opts.revssf; delete opts.ssf;
S
SheetJS 已提交
17597 17598
	return zip;
}
S
SheetJS 已提交
17599 17600
function firstbyte(f/*:RawData*/,o/*:?TypeOpts*/)/*:Array<number>*/ {
	var x = "";
S
SheetJS 已提交
17601
	switch((o||{}).type || "base64") {
S
SheetJS 已提交
17602 17603 17604 17605
		case 'buffer': return [f[0], f[1], f[2], f[3]];
		case 'base64': x = Base64.decode(f.substr(0,24)); break;
		case 'binary': x = f; break;
		case 'array':  return [f[0], f[1], f[2], f[3]];
S
SheetJS 已提交
17606
		default: throw new Error("Unrecognized type " + (o && o.type || "undefined"));
S
SheetJS 已提交
17607
	}
S
SheetJS 已提交
17608
	return [x.charCodeAt(0), x.charCodeAt(1), x.charCodeAt(2), x.charCodeAt(3)];
S
SheetJS 已提交
17609 17610
}

S
SheetJS 已提交
17611 17612
function read_cfb(cfb/*:CFBContainer*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
	if(CFB.find(cfb, "EncryptedPackage")) return parse_xlsxcfb(cfb, opts);
S
SheetJS 已提交
17613 17614 17615
	return parse_xlscfb(cfb, opts);
}

S
SheetJS 已提交
17616 17617
function read_zip(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
	/*:: if(!jszip) throw new Error("JSZip is not available"); */
S
SheetJS 已提交
17618 17619 17620 17621 17622 17623 17624 17625 17626 17627 17628 17629
	var zip, d = data;
	var o = opts||{};
	if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
	switch(o.type) {
		case "base64": zip = new jszip(d, { base64:true }); break;
		case "binary": case "array": zip = new jszip(d, { base64:false }); break;
		case "buffer": zip = new jszip(d); break;
		default: throw new Error("Unrecognized type " + o.type);
	}
	return parse_zip(zip, o);
}

S
SheetJS 已提交
17630 17631 17632 17633 17634 17635 17636 17637 17638 17639 17640 17641 17642 17643 17644 17645 17646 17647 17648 17649 17650 17651 17652
function read_plaintext(data/*:string*/, o/*:ParseOpts*/)/*:Workbook*/ {
	var i = 0;
	main: while(i < data.length) switch(data.charCodeAt(i)) {
		case 0x0A: case 0x0D: case 0x20: ++i; break;
		case 0x3C: return parse_xlml(data.slice(i),o);
		default: break main;
	}
	return PRN.to_workbook(data, o);
}

function read_plaintext_raw(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
	var str = "", bytes = firstbyte(data, o);
	switch(o.type) {
		case 'base64': str = Base64.decode(data); break;
		case 'binary': str = data; break;
		case 'buffer': str = data.toString('binary'); break;
		case 'array': str = cc2str(data); break;
		default: throw new Error("Unrecognized type " + o.type);
	}
	if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str);
	return read_plaintext(str, o);
}

S
SheetJS 已提交
17653 17654 17655
function read_utf16(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
	var d = data;
	if(o.type == 'base64') d = Base64.decode(d);
S
SheetJS 已提交
17656
	d = cptable.utils.decode(1200, d.slice(2), 'str');
S
SheetJS 已提交
17657
	o.type = "binary";
S
SheetJS 已提交
17658
	return read_plaintext(d, o);
S
SheetJS 已提交
17659 17660
}

S
SheetJS 已提交
17661
function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
S
SheetJS 已提交
17662
	var zip, d = data, n=[0];
S
SheetJS 已提交
17663
	var o = opts||{};
S
SheetJS 已提交
17664 17665
	_ssfopts = {};
	if(o.dateNF) _ssfopts.dateNF = o.dateNF;
S
SheetJS 已提交
17666
	if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
S
SheetJS 已提交
17667
	if(o.type == "file") { o.type = "buffer"; d = _fs.readFileSync(data); }
S
SheetJS 已提交
17668
	switch((n = firstbyte(d, o))[0]) {
S
SheetJS 已提交
17669
		case 0xD0: return read_cfb(CFB.read(d, o), o);
S
SheetJS 已提交
17670
		case 0x09: return parse_xlscfb(s2a(o.type === 'base64' ? Base64.decode(d) : d), o);
S
SheetJS 已提交
17671
		case 0x3C: return parse_xlml(d, o);
17672
		case 0x49: if(n[1] == 0x44) return read_wb_ID(d, o); break;
S
SheetJS 已提交
17673
		case 0x54: if(n[1] == 0x41 && n[2] == 0x42 && n[3] == 0x4C) return DIF.to_workbook(d, o); break;
S
SheetJS 已提交
17674
		case 0x50: if(n[1] == 0x4B && n[2] < 0x20 && n[3] < 0x20) return read_zip(d, o); break;
S
SheetJS 已提交
17675
		case 0xEF: return n[3] == 0x3C ? parse_xlml(d, o) : PRN.to_workbook(d,o);
S
SheetJS 已提交
17676
		case 0xFF: if(n[1] == 0xFE){ return read_utf16(d, o); } break;
S
SheetJS 已提交
17677
		case 0x00: if(n[1] == 0x00 && n[2] >= 0x02 && n[3] == 0x00) return WK_.to_workbook(d, o); break;
S
SheetJS 已提交
17678
		case 0x03: case 0x83: case 0x8B: return DBF.to_workbook(d, o);
S
SheetJS 已提交
17679
		case 0x7B: if(n[1] == 0x5C && n[2] == 0x72 && n[3] == 0x74) return RTF.to_workbook(d, o); break;
S
SheetJS 已提交
17680
		case 0x0A: case 0x0D: case 0x20: return read_plaintext_raw(d, o);
S
SheetJS 已提交
17681
	}
S
TXT/PRN  
SheetJS 已提交
17682 17683 17684
	if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
	if(0x20>n[0]||n[0]>0x7F) throw new Error("Unsupported file " + n.join("|"));
	return PRN.to_workbook(d, o);
S
SheetJS 已提交
17685 17686
}

S
SheetJS 已提交
17687
function readFileSync(filename/*:string*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
S
SheetJS 已提交
17688
	var o = opts||{}; o.type = 'file';
S
SheetJS 已提交
17689
	return readSync(filename, o);
S
SheetJS 已提交
17690
}
S
SheetJS 已提交
17691
function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
S
SheetJS 已提交
17692 17693 17694
	var o = opts||{};
	var z = write_zip(wb, o);
	var oopts = {};
S
SheetJS 已提交
17695
	if(o.compression) oopts.compression = 'DEFLATE';
S
SheetJS 已提交
17696 17697 17698 17699 17700 17701 17702 17703 17704 17705 17706
	switch(o.type) {
		case "base64": oopts.type = "base64"; break;
		case "binary": oopts.type = "string"; break;
		case "buffer":
		case "file": oopts.type = "nodebuffer"; break;
		default: throw new Error("Unrecognized type " + o.type);
	}
	if(o.type === "file") return _fs.writeFileSync(o.file, z.generate(oopts));
	return z.generate(oopts);
}

S
TXT/PRN  
SheetJS 已提交
17707 17708 17709 17710 17711 17712 17713
/* TODO: test consistency */
function write_bstr_type(out/*:string*/, opts/*:WriteOpts*/) {
	switch(opts.type) {
		case "base64": return Base64.encode(out);
		case "binary": return out;
		case "file": return _fs.writeFileSync(opts.file, out, 'binary');
		case "buffer": {
S
SheetJS 已提交
17714
			if(has_buf) return new Buffer(out, 'binary');
S
TXT/PRN  
SheetJS 已提交
17715 17716 17717 17718 17719 17720
			else return out.split("").map(function(c) { return c.charCodeAt(0); });
		}
	}
	throw new Error("Unrecognized type " + opts.type);
}

S
SheetJS 已提交
17721
/* TODO: test consistency */
17722 17723
function write_string_type(out/*:string*/, opts/*:WriteOpts*/) {
	switch(opts.type) {
S
SheetJS 已提交
17724 17725
		case "base64": return Base64.encode(out);
		case "binary": return out;
S
SheetJS 已提交
17726
		case "file": return _fs.writeFileSync(opts.file, out, 'utf8');
S
SheetJS 已提交
17727 17728 17729
		case "buffer": {
			if(has_buf) return new Buffer(out, 'utf8');
			else return out.split("").map(function(c) { return c.charCodeAt(0); });
S
SheetJS 已提交
17730
		}
17731
	}
S
SheetJS 已提交
17732
	throw new Error("Unrecognized type " + opts.type);
17733 17734
}

S
SheetJS 已提交
17735
/* TODO: test consistency */
17736 17737
function write_binary_type(out, opts/*:WriteOpts*/) {
	switch(opts.type) {
S
SheetJS 已提交
17738
		case "base64":
17739 17740 17741
		case "binary":
			var bstr = "";
			for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]);
S
SheetJS 已提交
17742
			return opts.type == 'base64' ? Base64.encode(bstr) : bstr;
17743 17744 17745 17746 17747 17748
		case "file": return _fs.writeFileSync(opts.file, out);
		case "buffer": return out;
		default: throw new Error("Unrecognized type " + opts.type);
	}
}

S
SheetJS 已提交
17749
function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
S
SheetJS 已提交
17750
	check_wb(wb);
S
SheetJS 已提交
17751
	var o = opts||{};
S
SheetJS 已提交
17752
	switch(o.bookType || 'xlsb') {
S
SheetJS 已提交
17753 17754
		case 'xml':
		case 'xlml': return write_string_type(write_xlml(wb, o), o);
S
SheetJS 已提交
17755 17756
		case 'slk':
		case 'sylk': return write_string_type(write_slk_str(wb, o), o);
S
SheetJS 已提交
17757
		case 'html': return write_string_type(write_htm_str(wb, o), o);
S
TXT/PRN  
SheetJS 已提交
17758
		case 'txt': return write_bstr_type(write_txt_str(wb, o), o);
17759
		case 'csv': return write_string_type(write_csv_str(wb, o), o);
S
SheetJS 已提交
17760
		case 'dif': return write_string_type(write_dif_str(wb, o), o);
S
TXT/PRN  
SheetJS 已提交
17761
		case 'prn': return write_string_type(write_prn_str(wb, o), o);
S
SheetJS 已提交
17762
		case 'rtf': return write_string_type(write_rtf_str(wb, o), o);
17763 17764
		case 'fods': return write_string_type(write_ods(wb, o), o);
		case 'biff2': return write_binary_type(write_biff_buf(wb, o), o);
S
SheetJS 已提交
17765 17766 17767 17768 17769
		case 'xlsx':
		case 'xlsm':
		case 'xlsb':
		case 'ods': return write_zip_type(wb, o);
		default: throw new Error ("Unrecognized bookType |" + o.bookType + "|");
S
SheetJS 已提交
17770 17771 17772
	}
}

S
SheetJS 已提交
17773
function resolve_book_type(o/*?WriteFileOpts*/) {
S
SheetJS 已提交
17774
	if(!o.bookType) switch(o.file.slice(o.file.lastIndexOf(".")).toLowerCase()) {
S
SheetJS 已提交
17775 17776 17777
		case '.xlsx': o.bookType = 'xlsx'; break;
		case '.xlsm': o.bookType = 'xlsm'; break;
		case '.xlsb': o.bookType = 'xlsb'; break;
17778
		case '.fods': o.bookType = 'fods'; break;
S
SheetJS 已提交
17779
		case '.xlml': o.bookType = 'xlml'; break;
S
SheetJS 已提交
17780
		case '.sylk': o.bookType = 'sylk'; break;
S
SheetJS 已提交
17781
		case '.html': o.bookType = 'html'; break;
S
SheetJS 已提交
17782
		case '.xls': o.bookType = 'biff2'; break;
S
SheetJS 已提交
17783 17784
		case '.xml': o.bookType = 'xml'; break;
		case '.ods': o.bookType = 'ods'; break;
17785
		case '.csv': o.bookType = 'csv'; break;
S
TXT/PRN  
SheetJS 已提交
17786
		case '.txt': o.bookType = 'txt'; break;
S
SheetJS 已提交
17787
		case '.dif': o.bookType = 'dif'; break;
S
TXT/PRN  
SheetJS 已提交
17788
		case '.prn': o.bookType = 'prn'; break;
S
SheetJS 已提交
17789
		case '.rtf': o.bookType = 'rtf'; break;
S
SheetJS 已提交
17790
		case '.slk': o.bookType = 'sylk'; break;
S
SheetJS 已提交
17791
		case '.htm': o.bookType = 'html'; break;
S
SheetJS 已提交
17792
	}
S
SheetJS 已提交
17793 17794 17795 17796 17797 17798
}

function writeFileSync(wb/*:Workbook*/, filename/*:string*/, opts/*:?WriteFileOpts*/) {
	var o = opts||{}; o.type = 'file';
	o.file = filename;
	resolve_book_type(o);
S
SheetJS 已提交
17799 17800 17801
	return writeSync(wb, o);
}

S
SheetJS 已提交
17802 17803 17804 17805 17806 17807 17808 17809
function writeFileAsync(filename/*:string*/, wb/*:Workbook*/, opts/*:?WriteFileOpts*/, cb/*:?(e?:ErrnoError)=>void*/) {
	var o = opts||{}; o.type = 'file';
	o.file = filename;
	resolve_book_type(o);
	o.type = 'buffer';
	var _cb = cb; if(!(_cb instanceof Function)) _cb = (opts/*:any*/);
	return _fs.writeFile(filename, writeSync(wb, o), _cb);
}
S
SheetJS 已提交
17810
function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) {
17811 17812 17813
	if(sheet == null || sheet["!ref"] == null) return [];
	var val = {t:'n',v:0}, header = 0, offset = 1, hdr/*:Array<any>*/ = [], isempty = true, v=0, vv="";
	var r = {s:{r:0,c:0},e:{r:0,c:0}};
S
SheetJS 已提交
17814
	var o = opts || {};
S
SheetJS 已提交
17815
	var raw = o.raw;
JimJin's avatar
JimJin 已提交
17816
	var defval = o.defval;
17817
	var range = o.range != null ? o.range : sheet["!ref"];
S
SheetJS 已提交
17818 17819 17820 17821 17822 17823 17824 17825 17826 17827
	if(o.header === 1) header = 1;
	else if(o.header === "A") header = 2;
	else if(Array.isArray(o.header)) header = 3;
	switch(typeof range) {
		case 'string': r = safe_decode_range(range); break;
		case 'number': r = safe_decode_range(sheet["!ref"]); r.s.r = range; break;
		default: r = range;
	}
	if(header > 0) offset = 0;
	var rr = encode_row(r.s.r);
S
SheetJS 已提交
17828 17829
	var cols/*:Array<string>*/ = [];
	var out/*:Array<any>*/ = [];
17830
	var outi = 0, counter = 0;
S
SheetJS 已提交
17831
	var dense = Array.isArray(sheet);
17832
	var R = r.s.r, C = 0, CC = 0;
S
SheetJS 已提交
17833
	if(dense && !sheet[R]) sheet[R] = [];
S
SheetJS 已提交
17834 17835
	for(C = r.s.c; C <= r.e.c; ++C) {
		cols[C] = encode_col(C);
17836
		val = dense ? sheet[R][C] : sheet[cols[C] + rr];
S
SheetJS 已提交
17837
		switch(header) {
17838
			case 1: hdr[C] = C - r.s.c; break;
S
SheetJS 已提交
17839 17840 17841
			case 2: hdr[C] = cols[C]; break;
			case 3: hdr[C] = o.header[C - r.s.c]; break;
			default:
S
SheetJS 已提交
17842
				if(val == null) continue;
S
SheetJS 已提交
17843
				vv = v = format_cell(val, null, o);
17844 17845
				counter = 0;
				for(CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter);
17846
				hdr[C] = vv;
S
SheetJS 已提交
17847 17848
		}
	}
S
SheetJS 已提交
17849
	var row/*:any*/ = (header === 1) ? [] : {};
S
SheetJS 已提交
17850 17851 17852 17853 17854 17855
	for (R = r.s.r + offset; R <= r.e.r; ++R) {
		rr = encode_row(R);
		isempty = true;
		if(header === 1) row = [];
		else {
			row = {};
S
SheetJS 已提交
17856
			if(Object.defineProperty) try { Object.defineProperty(row, '__rowNum__', {value:R, enumerable:false}); } catch(e) { row.__rowNum__ = R; }
S
SheetJS 已提交
17857 17858
			else row.__rowNum__ = R;
		}
17859 17860
		if(!dense || sheet[R]) for (C = r.s.c; C <= r.e.c; ++C) {
			val = dense ? sheet[R][C] : sheet[cols[C] + rr];
JimJin's avatar
JimJin 已提交
17861 17862 17863 17864 17865
			if(val === undefined || val.t === undefined) {
				if(defval === undefined) continue;
				if(hdr[C] != null) { row[hdr[C]] = defval; isempty = false; }
				continue;
			}
S
SheetJS 已提交
17866 17867
			v = val.v;
			switch(val.t){
JimJin's avatar
JimJin 已提交
17868
				case 'z': if(v == null) break; continue;
S
SheetJS 已提交
17869
				case 'e': continue;
S
SheetJS 已提交
17870
				case 's': case 'd': case 'b': case 'n': break;
S
SheetJS 已提交
17871
				default: throw new Error('unrecognized type ' + val.t);
S
SheetJS 已提交
17872
			}
JimJin's avatar
JimJin 已提交
17873 17874 17875 17876 17877 17878
			if(hdr[C] != null) {
				if(v == null) {
					if(defval !== undefined) row[hdr[C]] = defval;
					else if(raw && v === null) row[hdr[C]] = null;
					else continue;
				} else {
S
SheetJS 已提交
17879
					row[hdr[C]] = raw ? v : format_cell(val,v,o);
JimJin's avatar
JimJin 已提交
17880
				}
S
SheetJS 已提交
17881 17882 17883
				isempty = false;
			}
		}
S
SheetJS 已提交
17884
		if((isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) out[outi++] = row;
S
SheetJS 已提交
17885 17886 17887 17888 17889
	}
	out.length = outi;
	return out;
}

S
SheetJS 已提交
17890 17891 17892
var qreg = /"/g;
function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, fs/*:number*/, rs/*:number*/, FS/*:string*/, o/*:Sheet2CSVOpts*/)/*:?string*/ {
	var isempty = true;
S
SheetJS 已提交
17893
	var row/*:Array<string>*/ = [], txt = "", rr = encode_row(R);
S
SheetJS 已提交
17894
	for(var C = r.s.c; C <= r.e.c; ++C) {
17895
		if (!cols[C]) continue;
S
SheetJS 已提交
17896 17897 17898 17899 17900
		var val = o.dense ? (sheet[R]||[])[C]: sheet[cols[C] + rr];
		if(val == null) txt = "";
		else if(val.v != null) {
			isempty = false;
			txt = ''+format_cell(val, null, o);
17901 17902
			for(var i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
			if(txt == "ID") txt = '"ID"';
S
SheetJS 已提交
17903 17904 17905 17906 17907
		} else if(val.f != null && !val.F) {
			isempty = false;
			txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"';
		} else txt = "";
		/* NOTE: Excel CSV does not support array formulae */
17908
		row.push(txt);
S
SheetJS 已提交
17909 17910
	}
	if(o.blankrows === false && isempty) return null;
17911
	return row.join(FS);
S
SheetJS 已提交
17912 17913 17914
}

function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ {
S
SheetJS 已提交
17915
	var out = [];
S
SheetJS 已提交
17916 17917 17918 17919 17920
	var o = opts == null ? {} : opts;
	if(sheet == null || sheet["!ref"] == null) return "";
	var r = safe_decode_range(sheet["!ref"]);
	var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
	var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
S
SheetJS 已提交
17921
	var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
S
SheetJS 已提交
17922 17923
	var row = "", cols = [];
	o.dense = Array.isArray(sheet);
S
SheetJS 已提交
17924 17925 17926
	var colInfos = o.skipHidden && sheet["!cols"] || [];
	var rowInfos = o.skipHidden && sheet["!rows"] || [];
	for(var C = r.s.c; C <= r.e.c; ++C) if (!((colInfos[C]||{}).hidden)) cols[C] = encode_col(C);
S
SheetJS 已提交
17927
	for(var R = r.s.r; R <= r.e.r; ++R) {
S
SheetJS 已提交
17928
		if ((rowInfos[R]||{}).hidden) continue;
S
SheetJS 已提交
17929 17930
		row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o);
		if(row == null) { continue; }
S
SheetJS 已提交
17931
		if(o.strip) row = row.replace(endregex,"");
S
SheetJS 已提交
17932
		out.push(row + RS);
S
SheetJS 已提交
17933
	}
S
SheetJS 已提交
17934
	delete o.dense;
S
SheetJS 已提交
17935
	return out.join("");
S
SheetJS 已提交
17936
}
S
SheetJS 已提交
17937

S
TXT/PRN  
SheetJS 已提交
17938 17939 17940 17941 17942 17943 17944
function sheet_to_txt(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
	if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n";
	var s = sheet_to_csv(sheet, opts);
	if(typeof cptable == 'undefined') return s;
	var o = cptable.utils.encode(1200, s);
	return "\xff\xfe" + o;
}
S
SheetJS 已提交
17945

S
SheetJS 已提交
17946 17947 17948
function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
	var y = "", x, val="";
	if(sheet == null || sheet["!ref"] == null) return [];
S
SheetJS 已提交
17949
	var r = safe_decode_range(sheet['!ref']), rr = "", cols = [], C;
17950
	var cmds/*:Array<string>*/ = [];
S
SheetJS 已提交
17951
	var dense = Array.isArray(sheet);
S
SheetJS 已提交
17952 17953 17954 17955 17956
	for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C);
	for(var R = r.s.r; R <= r.e.r; ++R) {
		rr = encode_row(R);
		for(C = r.s.c; C <= r.e.c; ++C) {
			y = cols[C] + rr;
S
SheetJS 已提交
17957
			x = dense ? (sheet[R]||[])[C] : sheet[y];
S
SheetJS 已提交
17958 17959
			val = "";
			if(x === undefined) continue;
S
SheetJS 已提交
17960 17961 17962 17963 17964 17965
			else if(x.F != null) {
				y = x.F;
				if(!x.f) continue;
				val = x.f;
				if(y.indexOf(":") == -1) y = y + ":" + y;
			}
S
SheetJS 已提交
17966
			if(x.f != null) val = x.f;
S
SheetJS 已提交
17967
			else if(x.t == 'z') continue;
S
SheetJS 已提交
17968 17969
			else if(x.t == 'n' && x.v != null) val = "" + x.v;
			else if(x.t == 'b') val = x.v ? "TRUE" : "FALSE";
S
SheetJS 已提交
17970 17971
			else if(x.w !== undefined) val = "'" + x.w;
			else if(x.v === undefined) continue;
S
SheetJS 已提交
17972
			else if(x.t == 's') val = "'" + x.v;
S
SheetJS 已提交
17973
			else val = ""+x.v;
17974
			cmds[cmds.length] = y + "=" + val;
S
SheetJS 已提交
17975 17976 17977 17978 17979
		}
	}
	return cmds;
}

17980 17981 17982
function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ {
	var o = opts || {};
	var ws = ({}/*:any*/);
17983
	var cell/*:Cell*/;
17984 17985 17986 17987 17988 17989 17990 17991
	var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:js.length}}/*:any*/);
	var hdr = o.header || [], C = 0;

	for(var R = 0; R != js.length; ++R) {
		Object.keys(js[R]).filter(function(x) { return js[R].hasOwnProperty(x); }).forEach(function(k) {
			if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k;
			var v = js[R][k];
			var t = 'z';
17992
			var z = "";
17993 17994 17995
			if(typeof v == 'number') t = 'n';
			else if(typeof v == 'boolean') t = 'b';
			else if(typeof v == 'string') t = 's';
17996 17997 17998 17999 18000 18001 18002
			else if(v instanceof Date) {
				t = 'd';
				if(!o.cellDates) { t = 'n'; v = datenum(v); }
				z = o.dateNF || SSF._table[14];
			}
			ws[encode_cell({c:C,r:R+1})] = cell = ({t:t, v:v}/*:any*/);
			if(z) cell.z = z;
18003 18004 18005 18006 18007 18008 18009 18010
		});
	}
	range.e.c = hdr.length - 1;
	for(C = 0; C < hdr.length; ++C) ws[encode_col(C) + "1"] = {t:'s', v:hdr[C]};
	ws['!ref'] = encode_range(range);
	return ws;
}

S
SheetJS 已提交
18011
var utils/*:any*/ = {
S
SheetJS 已提交
18012 18013 18014 18015 18016 18017 18018 18019 18020 18021 18022 18023 18024 18025
	encode_col: encode_col,
	encode_row: encode_row,
	encode_cell: encode_cell,
	encode_range: encode_range,
	decode_col: decode_col,
	decode_row: decode_row,
	split_cell: split_cell,
	decode_cell: decode_cell,
	decode_range: decode_range,
	format_cell: format_cell,
	get_formulae: sheet_to_formulae,
	make_csv: sheet_to_csv,
	make_json: sheet_to_json,
	make_formulae: sheet_to_formulae,
S
SheetJS 已提交
18026
	aoa_to_sheet: aoa_to_sheet,
18027
	json_to_sheet: json_to_sheet,
S
SheetJS 已提交
18028 18029
	table_to_sheet: parse_dom_table,
	table_to_book: table_to_book,
S
SheetJS 已提交
18030 18031
	sheet_to_csv: sheet_to_csv,
	sheet_to_json: sheet_to_json,
S
SheetJS 已提交
18032
	sheet_to_html: HTML_.from_sheet,
S
SheetJS 已提交
18033
	sheet_to_formulae: sheet_to_formulae,
S
SheetJS 已提交
18034
	sheet_to_row_object_array: sheet_to_json
S
SheetJS 已提交
18035
};
S
SheetJS 已提交
18036 18037 18038

(function(utils) {
utils.consts = utils.consts || {};
S
SheetJS 已提交
18039
function add_consts(R/*Array<any>*/) { R.forEach(function(a){ utils.consts[a[0]] = a[1]; }); }
S
SheetJS 已提交
18040

S
SheetJS 已提交
18041
function get_default(x/*:any*/, y/*:any*/, z/*:any*/)/*:any*/ { return x[y] != null ? x[y] : (x[y] = z); }
S
SheetJS 已提交
18042 18043 18044 18045 18046 18047 18048 18049

/* get cell, creating a stub if necessary */
function ws_get_cell_stub(ws/*:Worksheet*/, R, C/*:?number*/)/*:Cell*/ {
	/* A1 cell address */
	if(typeof R == "string") return ws[R] || (ws[R] = {t:'z'});
	/* cell address object */
	if(typeof R != "number") return ws_get_cell_stub(ws, encode_cell(R));
	/* R and C are 0-based indices */
S
SheetJS 已提交
18050
	return ws_get_cell_stub(ws, encode_cell({r:R,c:C||0}));
S
SheetJS 已提交
18051 18052 18053 18054 18055 18056 18057 18058 18059 18060 18061 18062 18063 18064 18065 18066 18067 18068 18069 18070 18071
}

/* find sheet index for given name / validate index */
function wb_sheet_idx(wb/*:Workbook*/, sh/*:number|string*/) {
	if(typeof sh == "number") {
		if(sh >= 0 && wb.SheetNames.length > sh) return sh;
		throw new Error("Cannot find sheet # " + sh);
	} else if(typeof sh == "string") {
		var idx = wb.SheetNames.indexOf(sh);
		if(idx > -1) return idx;
		throw new Error("Cannot find sheet name |" + sh + "|");
	} else throw new Error("Cannot find sheet |" + sh + "|");
}

/* simple blank workbook object */
utils.book_new = function()/*:Workbook*/ {
	return { SheetNames: [], Sheets: {} };
};

/* add a worksheet to the end of a given workbook */
utils.book_append_sheet = function(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/) {
S
SheetJS 已提交
18072 18073
	if(!name) for(var i = 1; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break;
	if(!name) throw new Error("Too many worksheets");
S
SheetJS 已提交
18074 18075 18076 18077 18078 18079 18080 18081 18082 18083 18084 18085 18086
	check_ws_name(name);
	if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!");

	wb.SheetNames.push(name);
	wb.Sheets[name] = ws;
};

/* set sheet visibility (visible/hidden/very hidden) */
utils.book_set_sheet_visibility = function(wb/*:Workbook*/, sh/*:number|string*/, vis/*:number*/) {
	get_default(wb,"Workbook",{});
	get_default(wb.Workbook,"Sheets",[]);

	var idx = wb_sheet_idx(wb, sh);
S
SheetJS 已提交
18087
	// $FlowIgnore
S
SheetJS 已提交
18088 18089 18090 18091 18092 18093
	get_default(wb.Workbook.Sheets,idx, {});

	switch(vis) {
		case 0: case 1: case 2: break;
		default: throw new Error("Bad sheet visibility setting " + vis);
	}
S
SheetJS 已提交
18094
	// $FlowIgnore
S
SheetJS 已提交
18095 18096 18097 18098 18099 18100 18101 18102 18103 18104 18105 18106 18107 18108 18109 18110 18111 18112 18113
	wb.Workbook.Sheets[idx].Hidden = vis;
};
add_consts([
	["SHEET_VISIBLE", 0],
	["SHEET_HIDDEN", 1],
	["SHEET_VERY_HIDDEN", 2]
]);

/* set number format */
utils.cell_set_number_format = function(cell/*:Cell*/, fmt/*:string|number*/) {
	cell.z = fmt;
	return cell;
};

/* set cell hyperlink */
utils.cell_set_hyperlink = function(cell/*:Cell*/, target/*:string*/, tooltip/*:?string*/) {
	if(!target) {
		delete cell.l;
	} else {
S
SheetJS 已提交
18114
		cell.l = ({ Target: target }/*:Hyperlink*/);
S
SheetJS 已提交
18115 18116 18117 18118 18119 18120 18121 18122 18123 18124 18125 18126 18127 18128 18129 18130 18131 18132 18133
		if(tooltip) cell.l.Tooltip = tooltip;
	}
	return cell;
};

/* add to cell comments */
utils.cell_add_comment = function(cell/*:Cell*/, text/*:string*/, author/*:?string*/) {
	if(!cell.c) cell.c = [];
	cell.c.push({t:text, a:author||"SheetJS"});
};

/* set array formula and flush related cells */
utils.sheet_set_array_formula = function(ws/*:Worksheet*/, range, formula/*:string*/) {
	var rng = typeof range != "string" ? range : safe_decode_range(range);
	var rngstr = typeof range == "string" ? range : encode_range(range);
	for(var R = rng.s.r; R <= rng.e.r; ++R) for(var C = rng.s.c; C <= rng.e.c; ++C) {
		var cell = ws_get_cell_stub(ws, R, C);
		cell.t = 'n';
		cell.F = rngstr;
18134
		delete cell.v;
S
SheetJS 已提交
18135 18136 18137
		if(R == rng.s.r && C == rng.s.c) cell.f = formula;
	}
	return ws;
18138
};
S
SheetJS 已提交
18139 18140 18141 18142

return utils;
})(utils);

18143 18144 18145 18146 18147
if(has_buf && typeof require != 'undefined') (function() {
	var Readable = require('stream').Readable;

	var write_csv_stream = function(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
		var stream = Readable();
S
SheetJS 已提交
18148
		var out = "";
18149 18150 18151 18152 18153 18154
		var o = opts == null ? {} : opts;
		if(sheet == null || sheet["!ref"] == null) { stream.push(null); return stream; }
		var r = safe_decode_range(sheet["!ref"]);
		var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
		var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
		var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
S
SheetJS 已提交
18155
		var row/*:?string*/ = "", cols = [];
S
SheetJS 已提交
18156
		o.dense = Array.isArray(sheet);
S
SheetJS 已提交
18157 18158 18159
		var colInfos = o.skipHidden && sheet["!cols"] || [];
		var rowInfos = o.skipHidden && sheet["!rows"] || [];
		for(var C = r.s.c; C <= r.e.c; ++C) if (!((colInfos[C]||{}).hidden)) cols[C] = encode_col(C);
S
SheetJS 已提交
18160
		var R = r.s.r;
18161 18162
		stream._read = function() {
			if(R > r.e.r) return stream.push(null);
S
SheetJS 已提交
18163 18164
			while(R <= r.e.r) {
				++R;
S
SheetJS 已提交
18165 18166
				if ((rowInfos[R-1]||{}).hidden) continue;
				row = make_csv_row(sheet, r, R-1, cols, fs, rs, FS, o);
S
SheetJS 已提交
18167 18168 18169 18170 18171
				if(row != null) {
					if(o.strip) row = row.replace(endregex,"");
					stream.push(row + RS);
					break;
				}
18172 18173 18174 18175 18176
			}
		};
		return stream;
	};

S
SheetJS 已提交
18177
	var write_html_stream = function(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*/) {
18178 18179
		var stream = Readable();

S
SheetJS 已提交
18180 18181 18182 18183 18184 18185 18186
		var o = opts || {};
		var header = o.header != null ? o.header : HTML_.BEGIN;
		var footer = o.footer != null ? o.footer : HTML_.END;
		stream.push(header);
		var r = decode_range(ws['!ref']);
		o.dense = Array.isArray(ws);
		stream.push(HTML_._preamble(ws, r, o));
18187 18188 18189 18190
		var R = r.s.r;
		var end = false;
		stream._read = function() {
			if(R > r.e.r) {
S
SheetJS 已提交
18191
				if(!end) { end = true; stream.push("</table>" + footer); }
18192 18193 18194
				return stream.push(null);
			}
			while(R <= r.e.r) {
S
SheetJS 已提交
18195
				stream.push(HTML_._row(ws, r, R, o));
18196 18197 18198 18199 18200 18201
				++R;
				break;
			}
		};
		return stream;
	};
18202 18203

	XLSX.stream = {
18204
		to_html: write_html_stream,
18205 18206 18207
		to_csv: write_csv_stream
	};
})();
S
SheetJS 已提交
18208

S
SheetJS 已提交
18209
XLSX.parse_xlscfb = parse_xlscfb;
18210 18211 18212
XLSX.parse_ods = parse_ods;
XLSX.parse_fods = parse_fods;
XLSX.write_ods = write_ods;
S
SheetJS 已提交
18213 18214 18215 18216 18217 18218 18219
XLSX.parse_zip = parse_zip;
XLSX.read = readSync; //xlsread
XLSX.readFile = readFileSync; //readFile
XLSX.readFileSync = readFileSync;
XLSX.write = writeSync;
XLSX.writeFile = writeFileSync;
XLSX.writeFileSync = writeFileSync;
S
SheetJS 已提交
18220
XLSX.writeFileAsync = writeFileAsync;
S
SheetJS 已提交
18221 18222 18223
XLSX.utils = utils;
XLSX.SSF = SSF;
})(typeof exports !== 'undefined' ? exports : XLSX);
18224
/*exported XLS */
S
SheetJS 已提交
18225
var XLS = XLSX;
18226 18227
/*exported ODS */
var ODS = XLSX;