UNPKG

303 kBJavaScriptView Raw
1/*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
2/* vim: set ts=2: */
3/*exported XLSX */
4/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
5var XLSX = {};
6function make_xlsx_lib(XLSX){
7XLSX.version = '0.15.6';
8var current_codepage = 1200, current_ansi = 1252;
9
10var VALID_ANSI = [ 874, 932, 936, 949, 950 ];
11for(var i = 0; i <= 8; ++i) VALID_ANSI.push(1250 + i);
12/* ECMA-376 Part I 18.4.1 charset to codepage mapping */
13var CS2CP = ({
140: 1252, /* ANSI */
151: 65001, /* DEFAULT */
162: 65001, /* SYMBOL */
1777: 10000, /* MAC */
18128: 932, /* SHIFTJIS */
19129: 949, /* HANGUL */
20130: 1361, /* JOHAB */
21134: 936, /* GB2312 */
22136: 950, /* CHINESEBIG5 */
23161: 1253, /* GREEK */
24162: 1254, /* TURKISH */
25163: 1258, /* VIETNAMESE */
26177: 1255, /* HEBREW */
27178: 1256, /* ARABIC */
28186: 1257, /* BALTIC */
29204: 1251, /* RUSSIAN */
30222: 874, /* THAI */
31238: 1250, /* EASTEUROPE */
32255: 1252, /* OEM */
3369: 6969 /* MISC */
34});
35
36var set_ansi = function(cp) { if(VALID_ANSI.indexOf(cp) == -1) return; current_ansi = CS2CP[0] = cp; };
37function reset_ansi() { set_ansi(1252); }
38
39var set_cp = function(cp) { current_codepage = cp; set_ansi(cp); };
40function reset_cp() { set_cp(1200); reset_ansi(); }
41
42function char_codes(data) { var o = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; }
43
44function utf16leread(data) {
45 var o = [];
46 for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i) + (data.charCodeAt(2*i+1)<<8));
47 return o.join("");
48}
49function utf16beread(data) {
50 var o = [];
51 for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i+1) + (data.charCodeAt(2*i)<<8));
52 return o.join("");
53}
54
55var debom = function(data) {
56 var c1 = data.charCodeAt(0), c2 = data.charCodeAt(1);
57 if(c1 == 0xFF && c2 == 0xFE) return utf16leread(data.slice(2));
58 if(c1 == 0xFE && c2 == 0xFF) return utf16beread(data.slice(2));
59 if(c1 == 0xFEFF) return data.slice(1);
60 return data;
61};
62
63var _getchar = function _gc1(x) { return String.fromCharCode(x); };
64var _getansi = function _ga1(x) { return String.fromCharCode(x); };
65var DENSE = null;
66var DIF_XL = true;
67var Base64 = (function make_b64(){
68 var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
69 return {
70 encode: function(input) {
71 var o = "";
72 var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0;
73 for(var i = 0; i < input.length; ) {
74 c1 = input.charCodeAt(i++);
75 e1 = (c1 >> 2);
76
77 c2 = input.charCodeAt(i++);
78 e2 = ((c1 & 3) << 4) | (c2 >> 4);
79
80 c3 = input.charCodeAt(i++);
81 e3 = ((c2 & 15) << 2) | (c3 >> 6);
82 e4 = (c3 & 63);
83 if (isNaN(c2)) { e3 = e4 = 64; }
84 else if (isNaN(c3)) { e4 = 64; }
85 o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4);
86 }
87 return o;
88 },
89 decode: function b64_decode(input) {
90 var o = "";
91 var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0;
92 input = input.replace(/[^\w\+\/\=]/g, "");
93 for(var i = 0; i < input.length;) {
94 e1 = map.indexOf(input.charAt(i++));
95 e2 = map.indexOf(input.charAt(i++));
96 c1 = (e1 << 2) | (e2 >> 4);
97 o += String.fromCharCode(c1);
98
99 e3 = map.indexOf(input.charAt(i++));
100 c2 = ((e2 & 15) << 4) | (e3 >> 2);
101 if (e3 !== 64) { o += String.fromCharCode(c2); }
102
103 e4 = map.indexOf(input.charAt(i++));
104 c3 = ((e3 & 3) << 6) | e4;
105 if (e4 !== 64) { o += String.fromCharCode(c3); }
106 }
107 return o;
108 }
109 };
110})();
111var has_buf = (typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.node);
112
113var Buffer_from = function(){};
114
115if(typeof Buffer !== 'undefined') {
116 var nbfs = !Buffer.from;
117 if(!nbfs) try { Buffer.from("foo", "utf8"); } catch(e) { nbfs = true; }
118 Buffer_from = nbfs ? function(buf, enc) { return (enc) ? new Buffer(buf, enc) : new Buffer(buf); } : Buffer.from.bind(Buffer);
119 // $FlowIgnore
120 if(!Buffer.alloc) Buffer.alloc = function(n) { return new Buffer(n); };
121 // $FlowIgnore
122 if(!Buffer.allocUnsafe) Buffer.allocUnsafe = function(n) { return new Buffer(n); };
123}
124
125function new_raw_buf(len) {
126 /* jshint -W056 */
127 return has_buf ? Buffer.alloc(len) : new Array(len);
128 /* jshint +W056 */
129}
130
131function new_unsafe_buf(len) {
132 /* jshint -W056 */
133 return has_buf ? Buffer.allocUnsafe(len) : new Array(len);
134 /* jshint +W056 */
135}
136
137var s2a = function s2a(s) {
138 if(has_buf) return Buffer_from(s, "binary");
139 return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; });
140};
141
142function s2ab(s) {
143 if(typeof ArrayBuffer === 'undefined') return s2a(s);
144 var buf = new ArrayBuffer(s.length), view = new Uint8Array(buf);
145 for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
146 return buf;
147}
148
149function a2s(data) {
150 if(Array.isArray(data)) return data.map(function(c) { return String.fromCharCode(c); }).join("");
151 var o = []; for(var i = 0; i < data.length; ++i) o[i] = String.fromCharCode(data[i]); return o.join("");
152}
153
154function a2u(data) {
155 if(typeof Uint8Array === 'undefined') throw new Error("Unsupported");
156 return new Uint8Array(data);
157}
158
159function ab2a(data) {
160 if(typeof ArrayBuffer == 'undefined') throw new Error("Unsupported");
161 if(data instanceof ArrayBuffer) return ab2a(new Uint8Array(data));
162var o = new Array(data.length);
163 for(var i = 0; i < data.length; ++i) o[i] = data[i];
164 return o;
165}
166
167var bconcat = function(bufs) { return [].concat.apply([], bufs); };
168
169var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/g;
170/* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */
171/*jshint -W041 */
172var SSF = ({});
173var make_ssf = function make_ssf(SSF){
174SSF.version = '0.10.3';
175function _strrev(x) { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; }
176function fill(c,l) { var o = ""; while(o.length < l) o+=c; return o; }
177function pad0(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
178function pad_(v,d){var t=""+v;return t.length>=d?t:fill(' ',d-t.length)+t;}
179function rpad_(v,d){var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);}
180function pad0r1(v,d){var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;}
181function pad0r2(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
182var p2_32 = Math.pow(2,32);
183function pad0r(v,d){if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); }
184function isgeneral(s, i) { 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; }
185var days = [
186 ['Sun', 'Sunday'],
187 ['Mon', 'Monday'],
188 ['Tue', 'Tuesday'],
189 ['Wed', 'Wednesday'],
190 ['Thu', 'Thursday'],
191 ['Fri', 'Friday'],
192 ['Sat', 'Saturday']
193];
194var months = [
195 ['J', 'Jan', 'January'],
196 ['F', 'Feb', 'February'],
197 ['M', 'Mar', 'March'],
198 ['A', 'Apr', 'April'],
199 ['M', 'May', 'May'],
200 ['J', 'Jun', 'June'],
201 ['J', 'Jul', 'July'],
202 ['A', 'Aug', 'August'],
203 ['S', 'Sep', 'September'],
204 ['O', 'Oct', 'October'],
205 ['N', 'Nov', 'November'],
206 ['D', 'Dec', 'December']
207];
208function init_table(t) {
209 t[0]= 'General';
210 t[1]= '0';
211 t[2]= '0.00';
212 t[3]= '#,##0';
213 t[4]= '#,##0.00';
214 t[9]= '0%';
215 t[10]= '0.00%';
216 t[11]= '0.00E+00';
217 t[12]= '# ?/?';
218 t[13]= '# ??/??';
219 t[14]= 'm/d/yy';
220 t[15]= 'd-mmm-yy';
221 t[16]= 'd-mmm';
222 t[17]= 'mmm-yy';
223 t[18]= 'h:mm AM/PM';
224 t[19]= 'h:mm:ss AM/PM';
225 t[20]= 'h:mm';
226 t[21]= 'h:mm:ss';
227 t[22]= 'm/d/yy h:mm';
228 t[37]= '#,##0 ;(#,##0)';
229 t[38]= '#,##0 ;[Red](#,##0)';
230 t[39]= '#,##0.00;(#,##0.00)';
231 t[40]= '#,##0.00;[Red](#,##0.00)';
232 t[45]= 'mm:ss';
233 t[46]= '[h]:mm:ss';
234 t[47]= 'mmss.0';
235 t[48]= '##0.0E+0';
236 t[49]= '@';
237 t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "';
238 t[65535]= 'General';
239}
240
241var table_fmt = {};
242init_table(table_fmt);
243function frac(x, D, mixed) {
244 var sgn = x < 0 ? -1 : 1;
245 var B = x * sgn;
246 var P_2 = 0, P_1 = 1, P = 0;
247 var Q_2 = 1, Q_1 = 0, Q = 0;
248 var A = Math.floor(B);
249 while(Q_1 < D) {
250 A = Math.floor(B);
251 P = A * P_1 + P_2;
252 Q = A * Q_1 + Q_2;
253 if((B - A) < 0.00000005) break;
254 B = 1 / (B - A);
255 P_2 = P_1; P_1 = P;
256 Q_2 = Q_1; Q_1 = Q;
257 }
258 if(Q > D) { if(Q_1 > D) { Q = Q_2; P = P_2; } else { Q = Q_1; P = P_1; } }
259 if(!mixed) return [0, sgn * P, Q];
260 var q = Math.floor(sgn * P/Q);
261 return [q, sgn*P - q*Q, Q];
262}
263function parse_date_code(v,opts,b2) {
264 if(v > 2958465 || v < 0) return null;
265 var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
266 var dout=[];
267 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};
268 if(Math.abs(out.u) < 1e-6) out.u = 0;
269 if(opts && opts.date1904) date += 1462;
270 if(out.u > 0.9999) {
271 out.u = 0;
272 if(++time == 86400) { out.T = time = 0; ++date; ++out.D; }
273 }
274 if(date === 60) {dout = b2 ? [1317,10,29] : [1900,2,29]; dow=3;}
275 else if(date === 0) {dout = b2 ? [1317,8,29] : [1900,1,0]; dow=6;}
276 else {
277 if(date > 60) --date;
278 /* 1 = Jan 1 1900 in Gregorian */
279 var d = new Date(1900, 0, 1);
280 d.setDate(d.getDate() + date - 1);
281 dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
282 dow = d.getDay();
283 if(date < 60) dow = (dow + 6) % 7;
284 if(b2) dow = fix_hijri(d, dout);
285 }
286 out.y = dout[0]; out.m = dout[1]; out.d = dout[2];
287 out.S = time % 60; time = Math.floor(time / 60);
288 out.M = time % 60; time = Math.floor(time / 60);
289 out.H = time;
290 out.q = dow;
291 return out;
292}
293SSF.parse_date_code = parse_date_code;
294var basedate = new Date(1899, 11, 31, 0, 0, 0);
295var dnthresh = basedate.getTime();
296var base1904 = new Date(1900, 2, 1, 0, 0, 0);
297function datenum_local(v, date1904) {
298 var epoch = v.getTime();
299 if(date1904) epoch -= 1461*24*60*60*1000;
300 else if(v >= base1904) epoch += 24*60*60*1000;
301 return (epoch - (dnthresh + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
302}
303function general_fmt_int(v) { return v.toString(10); }
304SSF._general_int = general_fmt_int;
305var general_fmt_num = (function make_general_fmt_num() {
306var gnr1 = /\.(\d*[1-9])0+$/, gnr2 = /\.0*$/, gnr4 = /\.(\d*[1-9])0+/, gnr5 = /\.0*[Ee]/, gnr6 = /(E[+-])(\d)$/;
307function gfn2(v) {
308 var w = (v<0?12:11);
309 var o = gfn5(v.toFixed(12)); if(o.length <= w) return o;
310 o = v.toPrecision(10); if(o.length <= w) return o;
311 return v.toExponential(5);
312}
313function gfn3(v) {
314 var o = v.toFixed(11).replace(gnr1,".$1");
315 if(o.length > (v<0?12:11)) o = v.toPrecision(6);
316 return o;
317}
318function gfn4(o) {
319 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");
320 return o;
321}
322function gfn5(o) {
323 return o.indexOf(".") > -1 ? o.replace(gnr2,"").replace(gnr1,".$1") : o;
324}
325return function general_fmt_num(v) {
326 var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
327 if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
328 else if(Math.abs(V) <= 9) o = gfn2(v);
329 else if(V === 10) o = v.toFixed(10).substr(0,12);
330 else o = gfn3(v);
331 return gfn5(gfn4(o));
332};})();
333SSF._general_num = general_fmt_num;
334function general_fmt(v, opts) {
335 switch(typeof v) {
336 case 'string': return v;
337 case 'boolean': return v ? "TRUE" : "FALSE";
338 case 'number': return (v|0) === v ? v.toString(10) : general_fmt_num(v);
339 case 'undefined': return "";
340 case 'object':
341 if(v == null) return "";
342 if(v instanceof Date) return format(14, datenum_local(v, opts && opts.date1904), opts);
343 }
344 throw new Error("unsupported value in General format: " + v);
345}
346SSF._general = general_fmt;
347function fix_hijri() { return 0; }
348/*jshint -W086 */
349function write_date(type, fmt, val, ss0) {
350 var o="", ss=0, tt=0, y = val.y, out, outl = 0;
351 switch(type) {
352 case 98: /* 'b' buddhist year */
353 y = val.y + 543;
354 /* falls through */
355 case 121: /* 'y' year */
356 switch(fmt.length) {
357 case 1: case 2: out = y % 100; outl = 2; break;
358 default: out = y % 10000; outl = 4; break;
359 } break;
360 case 109: /* 'm' month */
361 switch(fmt.length) {
362 case 1: case 2: out = val.m; outl = fmt.length; break;
363 case 3: return months[val.m-1][1];
364 case 5: return months[val.m-1][0];
365 default: return months[val.m-1][2];
366 } break;
367 case 100: /* 'd' day */
368 switch(fmt.length) {
369 case 1: case 2: out = val.d; outl = fmt.length; break;
370 case 3: return days[val.q][0];
371 default: return days[val.q][1];
372 } break;
373 case 104: /* 'h' 12-hour */
374 switch(fmt.length) {
375 case 1: case 2: out = 1+(val.H+11)%12; outl = fmt.length; break;
376 default: throw 'bad hour format: ' + fmt;
377 } break;
378 case 72: /* 'H' 24-hour */
379 switch(fmt.length) {
380 case 1: case 2: out = val.H; outl = fmt.length; break;
381 default: throw 'bad hour format: ' + fmt;
382 } break;
383 case 77: /* 'M' minutes */
384 switch(fmt.length) {
385 case 1: case 2: out = val.M; outl = fmt.length; break;
386 default: throw 'bad minute format: ' + fmt;
387 } break;
388 case 115: /* 's' seconds */
389 if(fmt != 's' && fmt != 'ss' && fmt != '.0' && fmt != '.00' && fmt != '.000') throw 'bad second format: ' + fmt;
390 if(val.u === 0 && (fmt == "s" || fmt == "ss")) return pad0(val.S, fmt.length);
391if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100;
392 else tt = ss0 === 1 ? 10 : 1;
393 ss = Math.round((tt)*(val.S + val.u));
394 if(ss >= 60*tt) ss = 0;
395 if(fmt === 's') return ss === 0 ? "0" : ""+ss/tt;
396 o = pad0(ss,2 + ss0);
397 if(fmt === 'ss') return o.substr(0,2);
398 return "." + o.substr(2,fmt.length-1);
399 case 90: /* 'Z' absolute time */
400 switch(fmt) {
401 case '[h]': case '[hh]': out = val.D*24+val.H; break;
402 case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
403 case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
404 default: throw 'bad abstime format: ' + fmt;
405 } outl = fmt.length === 3 ? 1 : 2; break;
406 case 101: /* 'e' era */
407 out = y; outl = 1;
408 }
409 if(outl > 0) return pad0(out, outl); else return "";
410}
411/*jshint +W086 */
412function commaify(s) {
413 var w = 3;
414 if(s.length <= w) return s;
415 var j = (s.length % w), o = s.substr(0,j);
416 for(; j!=s.length; j+=w) o+=(o.length > 0 ? "," : "") + s.substr(j,w);
417 return o;
418}
419var write_num = (function make_write_num(){
420var pct1 = /%/g;
421function write_num_pct(type, fmt, val){
422 var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
423 return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
424}
425function write_num_cm(type, fmt, val){
426 var idx = fmt.length - 1;
427 while(fmt.charCodeAt(idx-1) === 44) --idx;
428 return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
429}
430function write_num_exp(fmt, val){
431 var o;
432 var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
433 if(fmt.match(/^#+0.0E\+0$/)) {
434 if(val == 0) return "0.0E+0";
435 else if(val < 0) return "-" + write_num_exp(fmt, -val);
436 var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
437 var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
438 if(ee < 0) ee += period;
439 o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
440 if(o.indexOf("e") === -1) {
441 var fakee = Math.floor(Math.log(val)*Math.LOG10E);
442 if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
443 else o += "E+" + (fakee - ee);
444 while(o.substr(0,2) === "0.") {
445 o = o.charAt(0) + o.substr(2,period) + "." + o.substr(2+period);
446 o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0.");
447 }
448 o = o.replace(/\+-/,"-");
449 }
450 o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
451 } else o = val.toExponential(idx);
452 if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
453 if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
454 return o.replace("e","E");
455}
456var frac1 = /# (\?+)( ?)\/( ?)(\d+)/;
457function write_num_f1(r, aval, sign) {
458 var den = parseInt(r[4],10), rr = Math.round(aval * den), base = Math.floor(rr/den);
459 var myn = (rr - base*den), myd = den;
460 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));
461}
462function write_num_f2(r, aval, sign) {
463 return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
464}
465var dec1 = /^#*0*\.([0#]+)/;
466var closeparen = /\).*[0#]/;
467var phone = /\(###\) ###\\?-####/;
468function hashq(str) {
469 var o = "", cc;
470 for(var i = 0; i != str.length; ++i) switch((cc=str.charCodeAt(i))) {
471 case 35: break;
472 case 63: o+= " "; break;
473 case 48: o+= "0"; break;
474 default: o+= String.fromCharCode(cc);
475 }
476 return o;
477}
478function rnd(val, d) { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
479function dec(val, d) {
480 if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
481 return 0;
482 }
483 return Math.round((val-Math.floor(val))*Math.pow(10,d));
484}
485function carry(val, d) {
486 if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
487 return 1;
488 }
489 return 0;
490}
491function flr(val) { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); }
492function write_num_flt(type, fmt, val) {
493 if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
494 var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
495 if(val >= 0) return write_num_flt('n', ffmt, val);
496 return '(' + write_num_flt('n', ffmt, -val) + ')';
497 }
498 if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm(type, fmt, val);
499 if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val);
500 if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val);
501 if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
502 var o;
503 var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
504 if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length);
505 if(fmt.match(/^[#?]+$/)) {
506 o = pad0r(val,0); if(o === "0") o = "";
507 return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
508 }
509 if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign);
510 if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
511 if((r = fmt.match(dec1))) {
512 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); });
513 return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
514 }
515 fmt = fmt.replace(/^#+([0.])/, "$1");
516 if((r = fmt.match(/^(0*)\.(#*)$/))) {
517 return sign + rnd(aval, r[2].length).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
518 }
519 if((r = fmt.match(/^#{1,3},##0(\.?)$/))) return sign + commaify(pad0r(aval,0));
520 if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
521 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);
522 }
523 if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
524 if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
525 o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val));
526 ri = 0;
527 return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";}));
528 }
529 if(fmt.match(phone)) {
530 o = write_num_flt(type, "##########", val);
531 return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
532 }
533 var oa = "";
534 if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
535 ri = Math.min(r[4].length,7);
536 ff = frac(aval, Math.pow(10,ri)-1, false);
537 o = "" + sign;
538 oa = write_num("n", r[1], ff[1]);
539 if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
540 o += oa + r[2] + "/" + r[3];
541 oa = rpad_(ff[2],ri);
542 if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
543 o += oa;
544 return o;
545 }
546 if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
547 ri = Math.min(Math.max(r[1].length, r[4].length),7);
548 ff = frac(aval, Math.pow(10,ri)-1, true);
549 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));
550 }
551 if((r = fmt.match(/^[#0?]+$/))) {
552 o = pad0r(val, 0);
553 if(fmt.length <= o.length) return o;
554 return hashq(fmt.substr(0,fmt.length-o.length)) + o;
555 }
556 if((r = fmt.match(/^([#0?]+)\.([#0]+)$/))) {
557 o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
558 ri = o.indexOf(".");
559 var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
560 return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
561 }
562 if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
563 ri = dec(val, r[1].length);
564 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);
565 }
566 switch(fmt) {
567 case "###,##0.00": return write_num_flt(type, "#,##0.00", val);
568 case "###,###":
569 case "##,###":
570 case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : "";
571 case "###,###.00": return write_num_flt(type, "###,##0.00",val).replace(/^0\./,".");
572 case "#,###.00": return write_num_flt(type, "#,##0.00",val).replace(/^0\./,".");
573 default:
574 }
575 throw new Error("unsupported format |" + fmt + "|");
576}
577function write_num_cm2(type, fmt, val){
578 var idx = fmt.length - 1;
579 while(fmt.charCodeAt(idx-1) === 44) --idx;
580 return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
581}
582function write_num_pct2(type, fmt, val){
583 var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
584 return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
585}
586function write_num_exp2(fmt, val){
587 var o;
588 var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
589 if(fmt.match(/^#+0.0E\+0$/)) {
590 if(val == 0) return "0.0E+0";
591 else if(val < 0) return "-" + write_num_exp2(fmt, -val);
592 var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
593 var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
594 if(ee < 0) ee += period;
595 o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
596 if(!o.match(/[Ee]/)) {
597 var fakee = Math.floor(Math.log(val)*Math.LOG10E);
598 if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
599 else o += "E+" + (fakee - ee);
600 o = o.replace(/\+-/,"-");
601 }
602 o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
603 } else o = val.toExponential(idx);
604 if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
605 if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
606 return o.replace("e","E");
607}
608function write_num_int(type, fmt, val) {
609 if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
610 var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
611 if(val >= 0) return write_num_int('n', ffmt, val);
612 return '(' + write_num_int('n', ffmt, -val) + ')';
613 }
614 if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm2(type, fmt, val);
615 if(fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val);
616 if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val);
617 if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
618 var o;
619 var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
620 if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length);
621 if(fmt.match(/^[#?]+$/)) {
622 o = (""+val); if(val === 0) o = "";
623 return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
624 }
625 if((r = fmt.match(frac1))) return write_num_f2(r, aval, sign);
626 if(fmt.match(/^#+0+$/)) return sign + pad0(aval,fmt.length - fmt.indexOf("0"));
627 if((r = fmt.match(dec1))) {
628o = (""+val).replace(/^([^\.]+)$/,"$1."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1]));
629 o = o.replace(/\.(\d*)$/,function($$, $1) {
630return "." + $1 + fill("0", hashq(r[1]).length-$1.length); });
631 return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
632 }
633 fmt = fmt.replace(/^#+([0.])/, "$1");
634 if((r = fmt.match(/^(0*)\.(#*)$/))) {
635 return sign + (""+aval).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
636 }
637 if((r = fmt.match(/^#{1,3},##0(\.?)$/))) return sign + commaify((""+aval));
638 if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
639 return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify((""+val)) + "." + fill('0',r[1].length);
640 }
641 if((r = fmt.match(/^#,#*,#0/))) return write_num_int(type,fmt.replace(/^#,#*,/,""),val);
642 if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
643 o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val));
644 ri = 0;
645 return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";}));
646 }
647 if(fmt.match(phone)) {
648 o = write_num_int(type, "##########", val);
649 return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
650 }
651 var oa = "";
652 if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
653 ri = Math.min(r[4].length,7);
654 ff = frac(aval, Math.pow(10,ri)-1, false);
655 o = "" + sign;
656 oa = write_num("n", r[1], ff[1]);
657 if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
658 o += oa + r[2] + "/" + r[3];
659 oa = rpad_(ff[2],ri);
660 if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
661 o += oa;
662 return o;
663 }
664 if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
665 ri = Math.min(Math.max(r[1].length, r[4].length),7);
666 ff = frac(aval, Math.pow(10,ri)-1, true);
667 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));
668 }
669 if((r = fmt.match(/^[#0?]+$/))) {
670 o = "" + val;
671 if(fmt.length <= o.length) return o;
672 return hashq(fmt.substr(0,fmt.length-o.length)) + o;
673 }
674 if((r = fmt.match(/^([#0]+)\.([#0]+)$/))) {
675 o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
676 ri = o.indexOf(".");
677 var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
678 return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
679 }
680 if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
681 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);
682 }
683 switch(fmt) {
684 case "###,###":
685 case "##,###":
686 case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
687 default:
688 if(fmt.match(/\.[0#?]*$/)) return write_num_int(type, fmt.slice(0,fmt.lastIndexOf(".")), val) + hashq(fmt.slice(fmt.lastIndexOf(".")));
689 }
690 throw new Error("unsupported format |" + fmt + "|");
691}
692return function write_num(type, fmt, val) {
693 return (val|0) === val ? write_num_int(type, fmt, val) : write_num_flt(type, fmt, val);
694};})();
695function split_fmt(fmt) {
696 var out = [];
697 var in_str = false/*, cc*/;
698 for(var i = 0, j = 0; i < fmt.length; ++i) switch((/*cc=*/fmt.charCodeAt(i))) {
699 case 34: /* '"' */
700 in_str = !in_str; break;
701 case 95: case 42: case 92: /* '_' '*' '\\' */
702 ++i; break;
703 case 59: /* ';' */
704 out[out.length] = fmt.substr(j,i-j);
705 j = i+1;
706 }
707 out[out.length] = fmt.substr(j);
708 if(in_str === true) throw new Error("Format |" + fmt + "| unterminated string ");
709 return out;
710}
711SSF._split = split_fmt;
712var abstime = /\[[HhMmSs]*\]/;
713function fmt_is_date(fmt) {
714 var i = 0, /*cc = 0,*/ c = "", o = "";
715 while(i < fmt.length) {
716 switch((c = fmt.charAt(i))) {
717 case 'G': if(isgeneral(fmt, i)) i+= 6; i++; break;
718 case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;){/*empty*/} ++i; break;
719 case '\\': i+=2; break;
720 case '_': i+=2; break;
721 case '@': ++i; break;
722 case 'B': case 'b':
723 if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") return true;
724 /* falls through */
725 case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
726 /* falls through */
727 case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g': return true;
728 case 'A': case 'a':
729 if(fmt.substr(i, 3).toUpperCase() === "A/P") return true;
730 if(fmt.substr(i, 5).toUpperCase() === "AM/PM") return true;
731 ++i; break;
732 case '[':
733 o = c;
734 while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
735 if(o.match(abstime)) return true;
736 break;
737 case '.':
738 /* falls through */
739 case '0': case '#':
740 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 */}
741 break;
742 case '?': while(fmt.charAt(++i) === c){/* empty */} break;
743 case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break;
744 case '(': case ')': ++i; break;
745 case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
746 while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){/* empty */} break;
747 case ' ': ++i; break;
748 default: ++i; break;
749 }
750 }
751 return false;
752}
753SSF.is_date = fmt_is_date;
754function eval_fmt(fmt, v, opts, flen) {
755 var out = [], o = "", i = 0, c = "", lst='t', dt, j, cc;
756 var hr='H';
757 /* Tokenize */
758 while(i < fmt.length) {
759 switch((c = fmt.charAt(i))) {
760 case 'G': /* General */
761 if(!isgeneral(fmt, i)) throw new Error('unrecognized character ' + c + ' in ' +fmt);
762 out[out.length] = {t:'G', v:'General'}; i+=7; break;
763 case '"': /* Literal text */
764 for(o="";(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) o += String.fromCharCode(cc);
765 out[out.length] = {t:'t', v:o}; ++i; break;
766 case '\\': var w = fmt.charAt(++i), t = (w === "(" || w === ")") ? w : 't';
767 out[out.length] = {t:t, v:w}; ++i; break;
768 case '_': out[out.length] = {t:'t', v:" "}; i+=2; break;
769 case '@': /* Text Placeholder */
770 out[out.length] = {t:'T', v:v}; ++i; break;
771 case 'B': case 'b':
772 if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") {
773 if(dt==null) { dt=parse_date_code(v, opts, fmt.charAt(i+1) === "2"); if(dt==null) return ""; }
774 out[out.length] = {t:'X', v:fmt.substr(i,2)}; lst = c; i+=2; break;
775 }
776 /* falls through */
777 case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
778 c = c.toLowerCase();
779 /* falls through */
780 case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g':
781 if(v < 0) return "";
782 if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
783 o = c; while(++i < fmt.length && fmt.charAt(i).toLowerCase() === c) o+=c;
784 if(c === 'm' && lst.toLowerCase() === 'h') c = 'M';
785 if(c === 'h') c = hr;
786 out[out.length] = {t:c, v:o}; lst = c; break;
787 case 'A': case 'a':
788 var q={t:c, v:c};
789 if(dt==null) dt=parse_date_code(v, opts);
790 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;}
791 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'; }
792 else { q.t = "t"; ++i; }
793 if(dt==null && q.t === 'T') return "";
794 out[out.length] = q; lst = c; break;
795 case '[':
796 o = c;
797 while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
798 if(o.slice(-1) !== ']') throw 'unterminated "[" block: |' + o + '|';
799 if(o.match(abstime)) {
800 if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
801 out[out.length] = {t:'Z', v:o.toLowerCase()};
802 lst = o.charAt(1);
803 } else if(o.indexOf("$") > -1) {
804 o = (o.match(/\$([^-\[\]]*)/)||[])[1]||"$";
805 if(!fmt_is_date(fmt)) out[out.length] = {t:'t',v:o};
806 }
807 break;
808 /* Numbers */
809 case '.':
810 if(dt != null) {
811 o = c; while(++i < fmt.length && (c=fmt.charAt(i)) === "0") o += c;
812 out[out.length] = {t:'s', v:o}; break;
813 }
814 /* falls through */
815 case '0': case '#':
816 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;
817 out[out.length] = {t:'n', v:o}; break;
818 case '?':
819 o = c; while(fmt.charAt(++i) === c) o+=c;
820 out[out.length] = {t:c, v:o}; lst = c; break;
821 case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break; // **
822 case '(': case ')': out[out.length] = {t:(flen===1?'t':c), v:c}; ++i; break;
823 case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
824 o = c; while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1) o+=fmt.charAt(i);
825 out[out.length] = {t:'D', v:o}; break;
826 case ' ': out[out.length] = {t:c, v:c}; ++i; break;
827 case "$": out[out.length] = {t:'t', v:'$'}; ++i; break;
828 default:
829 if(",$-+/():!^&'~{}<>=€acfijklopqrtuvwxzP".indexOf(c) === -1) throw new Error('unrecognized character ' + c + ' in ' + fmt);
830 out[out.length] = {t:'t', v:c}; ++i; break;
831 }
832 }
833 var bt = 0, ss0 = 0, ssm;
834 for(i=out.length-1, lst='t'; i >= 0; --i) {
835 switch(out[i].t) {
836 case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
837 case 's':
838 if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
839 if(bt < 3) bt = 3;
840 /* falls through */
841 case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
842 case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
843 case 'X': /*if(out[i].v === "B2");*/
844 break;
845 case 'Z':
846 if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1;
847 if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2;
848 if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
849 }
850 }
851 switch(bt) {
852 case 0: break;
853 case 1:
854if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
855 if(dt.S >= 60) { dt.S = 0; ++dt.M; }
856 if(dt.M >= 60) { dt.M = 0; ++dt.H; }
857 break;
858 case 2:
859if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
860 if(dt.S >= 60) { dt.S = 0; ++dt.M; }
861 break;
862 }
863 /* replace fields */
864 var nstr = "", jj;
865 for(i=0; i < out.length; ++i) {
866 switch(out[i].t) {
867 case 't': case 'T': case ' ': case 'D': break;
868 case 'X': out[i].v = ""; out[i].t = ";"; break;
869 case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'b': case 'Z':
870out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
871 out[i].t = 't'; break;
872 case 'n': case '(': case '?':
873 jj = i+1;
874 while(out[jj] != null && (
875 (c=out[jj].t) === "?" || c === "D" ||
876 ((c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/')) ||
877 (out[i].t === '(' && (c === ' ' || c === 'n' || c === ')')) ||
878 (c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?'))
879 )) {
880 out[i].v += out[jj].v;
881 out[jj] = {v:"", t:";"}; ++jj;
882 }
883 nstr += out[i].v;
884 i = jj-1; break;
885 case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
886 }
887 }
888 var vv = "", myv, ostr;
889 if(nstr.length > 0) {
890 if(nstr.charCodeAt(0) == 40) /* '(' */ {
891 myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v);
892 ostr = write_num('(', nstr, myv);
893 } else {
894 myv = (v<0 && flen > 1 ? -v : v);
895 ostr = write_num('n', nstr, myv);
896 if(myv < 0 && out[0] && out[0].t == 't') {
897 ostr = ostr.substr(1);
898 out[0].v = "-" + out[0].v;
899 }
900 }
901 jj=ostr.length-1;
902 var decpt = out.length;
903 for(i=0; i < out.length; ++i) if(out[i] != null && out[i].t != 't' && out[i].v.indexOf(".") > -1) { decpt = i; break; }
904 var lasti=out.length;
905 if(decpt === out.length && ostr.indexOf("E") === -1) {
906 for(i=out.length-1; i>= 0;--i) {
907 if(out[i] == null || 'n?('.indexOf(out[i].t) === -1) continue;
908 if(jj>=out[i].v.length-1) { jj -= out[i].v.length; out[i].v = ostr.substr(jj+1, out[i].v.length); }
909 else if(jj < 0) out[i].v = "";
910 else { out[i].v = ostr.substr(0, jj+1); jj = -1; }
911 out[i].t = 't';
912 lasti = i;
913 }
914 if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
915 }
916 else if(decpt !== out.length && ostr.indexOf("E") === -1) {
917 jj = ostr.indexOf(".")-1;
918 for(i=decpt; i>= 0; --i) {
919 if(out[i] == null || 'n?('.indexOf(out[i].t) === -1) continue;
920 j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1;
921 vv = out[i].v.substr(j+1);
922 for(; j>=0; --j) {
923 if(jj>=0 && (out[i].v.charAt(j) === "0" || out[i].v.charAt(j) === "#")) vv = ostr.charAt(jj--) + vv;
924 }
925 out[i].v = vv;
926 out[i].t = 't';
927 lasti = i;
928 }
929 if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
930 jj = ostr.indexOf(".")+1;
931 for(i=decpt; i<out.length; ++i) {
932 if(out[i] == null || ('n?('.indexOf(out[i].t) === -1 && i !== decpt)) continue;
933 j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0;
934 vv = out[i].v.substr(0,j);
935 for(; j<out[i].v.length; ++j) {
936 if(jj<ostr.length) vv += ostr.charAt(jj++);
937 }
938 out[i].v = vv;
939 out[i].t = 't';
940 lasti = i;
941 }
942 }
943 }
944 for(i=0; i<out.length; ++i) if(out[i] != null && 'n(?'.indexOf(out[i].t)>-1) {
945 myv = (flen >1 && v < 0 && i>0 && out[i-1].v === "-" ? -v:v);
946 out[i].v = write_num(out[i].t, out[i].v, myv);
947 out[i].t = 't';
948 }
949 var retval = "";
950 for(i=0; i !== out.length; ++i) if(out[i] != null) retval += out[i].v;
951 return retval;
952}
953SSF._eval = eval_fmt;
954var cfregex = /\[[=<>]/;
955var cfregex2 = /\[(=|>[=]?|<[>=]?)(-?\d+(?:\.\d*)?)\]/;
956function chkcond(v, rr) {
957 if(rr == null) return false;
958 var thresh = parseFloat(rr[2]);
959 switch(rr[1]) {
960 case "=": if(v == thresh) return true; break;
961 case ">": if(v > thresh) return true; break;
962 case "<": if(v < thresh) return true; break;
963 case "<>": if(v != thresh) return true; break;
964 case ">=": if(v >= thresh) return true; break;
965 case "<=": if(v <= thresh) return true; break;
966 }
967 return false;
968}
969function choose_fmt(f, v) {
970 var fmt = split_fmt(f);
971 var l = fmt.length, lat = fmt[l-1].indexOf("@");
972 if(l<4 && lat>-1) --l;
973 if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
974 if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
975 switch(fmt.length) {
976 case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
977 case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
978 case 3: fmt = lat>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
979 case 4: break;
980 }
981 var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2];
982 if(fmt[0].indexOf("[") === -1 && fmt[1].indexOf("[") === -1) return [l, ff];
983 if(fmt[0].match(cfregex) != null || fmt[1].match(cfregex) != null) {
984 var m1 = fmt[0].match(cfregex2);
985 var m2 = fmt[1].match(cfregex2);
986 return chkcond(v, m1) ? [l, fmt[0]] : chkcond(v, m2) ? [l, fmt[1]] : [l, fmt[m1 != null && m2 != null ? 2 : 1]];
987 }
988 return [l, ff];
989}
990function format(fmt,v,o) {
991 if(o == null) o = {};
992 var sfmt = "";
993 switch(typeof fmt) {
994 case "string":
995 if(fmt == "m/d/yy" && o.dateNF) sfmt = o.dateNF;
996 else sfmt = fmt;
997 break;
998 case "number":
999 if(fmt == 14 && o.dateNF) sfmt = o.dateNF;
1000 else sfmt = (o.table != null ? (o.table) : table_fmt)[fmt];
1001 break;
1002 }
1003 if(isgeneral(sfmt,0)) return general_fmt(v, o);
1004 if(v instanceof Date) v = datenum_local(v, o.date1904);
1005 var f = choose_fmt(sfmt, v);
1006 if(isgeneral(f[1])) return general_fmt(v, o);
1007 if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
1008 else if(v === "" || v == null) return "";
1009 return eval_fmt(f[1], v, o, f[0]);
1010}
1011function load_entry(fmt, idx) {
1012 if(typeof idx != 'number') {
1013 idx = +idx || -1;
1014for(var i = 0; i < 0x0188; ++i) {
1015if(table_fmt[i] == undefined) { if(idx < 0) idx = i; continue; }
1016 if(table_fmt[i] == fmt) { idx = i; break; }
1017 }
1018if(idx < 0) idx = 0x187;
1019 }
1020table_fmt[idx] = fmt;
1021 return idx;
1022}
1023SSF.load = load_entry;
1024SSF._table = table_fmt;
1025SSF.get_table = function get_table() { return table_fmt; };
1026SSF.load_table = function load_table(tbl) {
1027 for(var i=0; i!=0x0188; ++i)
1028 if(tbl[i] !== undefined) load_entry(tbl[i], i);
1029};
1030SSF.init_table = init_table;
1031SSF.format = format;
1032};
1033make_ssf(SSF);
1034/* map from xlml named formats to SSF TODO: localize */
1035var XLMLFormatMap/*{[string]:string}*/ = ({
1036 "General Number": "General",
1037 "General Date": SSF._table[22],
1038 "Long Date": "dddd, mmmm dd, yyyy",
1039 "Medium Date": SSF._table[15],
1040 "Short Date": SSF._table[14],
1041 "Long Time": SSF._table[19],
1042 "Medium Time": SSF._table[18],
1043 "Short Time": SSF._table[20],
1044 "Currency": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
1045 "Fixed": SSF._table[2],
1046 "Standard": SSF._table[4],
1047 "Percent": SSF._table[10],
1048 "Scientific": SSF._table[11],
1049 "Yes/No": '"Yes";"Yes";"No";@',
1050 "True/False": '"True";"True";"False";@',
1051 "On/Off": '"Yes";"Yes";"No";@'
1052});
1053
1054var SSFImplicit/*{[number]:string}*/ = ({
1055 "5": '"$"#,##0_);\\("$"#,##0\\)',
1056 "6": '"$"#,##0_);[Red]\\("$"#,##0\\)',
1057 "7": '"$"#,##0.00_);\\("$"#,##0.00\\)',
1058 "8": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
1059 "23": 'General', "24": 'General', "25": 'General', "26": 'General',
1060 "27": 'm/d/yy', "28": 'm/d/yy', "29": 'm/d/yy', "30": 'm/d/yy', "31": 'm/d/yy',
1061 "32": 'h:mm:ss', "33": 'h:mm:ss', "34": 'h:mm:ss', "35": 'h:mm:ss',
1062 "36": 'm/d/yy',
1063 "41": '_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)',
1064 "42": '_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)',
1065 "43": '_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)',
1066 "44": '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)',
1067 "50": 'm/d/yy', "51": 'm/d/yy', "52": 'm/d/yy', "53": 'm/d/yy', "54": 'm/d/yy',
1068 "55": 'm/d/yy', "56": 'm/d/yy', "57": 'm/d/yy', "58": 'm/d/yy',
1069 "59": '0',
1070 "60": '0.00',
1071 "61": '#,##0',
1072 "62": '#,##0.00',
1073 "63": '"$"#,##0_);\\("$"#,##0\\)',
1074 "64": '"$"#,##0_);[Red]\\("$"#,##0\\)',
1075 "65": '"$"#,##0.00_);\\("$"#,##0.00\\)',
1076 "66": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
1077 "67": '0%',
1078 "68": '0.00%',
1079 "69": '# ?/?',
1080 "70": '# ??/??',
1081 "71": 'm/d/yy',
1082 "72": 'm/d/yy',
1083 "73": 'd-mmm-yy',
1084 "74": 'd-mmm',
1085 "75": 'mmm-yy',
1086 "76": 'h:mm',
1087 "77": 'h:mm:ss',
1088 "78": 'm/d/yy h:mm',
1089 "79": 'mm:ss',
1090 "80": '[h]:mm:ss',
1091 "81": 'mmss.0'
1092});
1093
1094/* dateNF parse TODO: move to SSF */
1095var dateNFregex = /[dD]+|[mM]+|[yYeE]+|[Hh]+|[Ss]+/g;
1096function dateNF_regex(dateNF) {
1097 var fmt = typeof dateNF == "number" ? SSF._table[dateNF] : dateNF;
1098 fmt = fmt.replace(dateNFregex, "(\\d+)");
1099 return new RegExp("^" + fmt + "$");
1100}
1101function dateNF_fix(str, dateNF, match) {
1102 var Y = -1, m = -1, d = -1, H = -1, M = -1, S = -1;
1103 (dateNF.match(dateNFregex)||[]).forEach(function(n, i) {
1104 var v = parseInt(match[i+1], 10);
1105 switch(n.toLowerCase().charAt(0)) {
1106 case 'y': Y = v; break; case 'd': d = v; break;
1107 case 'h': H = v; break; case 's': S = v; break;
1108 case 'm': if(H >= 0) M = v; else m = v; break;
1109 }
1110 });
1111 if(S >= 0 && M == -1 && m >= 0) { M = m; m = -1; }
1112 var datestr = (("" + (Y>=0?Y: new Date().getFullYear())).slice(-4) + "-" + ("00" + (m>=1?m:1)).slice(-2) + "-" + ("00" + (d>=1?d:1)).slice(-2));
1113 if(datestr.length == 7) datestr = "0" + datestr;
1114 if(datestr.length == 8) datestr = "20" + datestr;
1115 var timestr = (("00" + (H>=0?H:0)).slice(-2) + ":" + ("00" + (M>=0?M:0)).slice(-2) + ":" + ("00" + (S>=0?S:0)).slice(-2));
1116 if(H == -1 && M == -1 && S == -1) return datestr;
1117 if(Y == -1 && m == -1 && d == -1) return timestr;
1118 return datestr + "T" + timestr;
1119}
1120
1121var DO_NOT_EXPORT_CFB = true;
1122/* cfb.js (C) 2013-present SheetJS -- http://sheetjs.com */
1123/* vim: set ts=2: */
1124/*jshint eqnull:true */
1125/*exported CFB */
1126/*global Uint8Array:false, Uint16Array:false */
1127
1128/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
1129/* vim: set ts=2: */
1130/*exported CRC32 */
1131var CRC32;
1132(function (factory) {
1133 /*jshint ignore:start */
1134 /*eslint-disable */
1135 factory(CRC32 = {});
1136 /*eslint-enable */
1137 /*jshint ignore:end */
1138}(function(CRC32) {
1139CRC32.version = '1.2.0';
1140/* see perf/crc32table.js */
1141/*global Int32Array */
1142function signed_crc_table() {
1143 var c = 0, table = new Array(256);
1144
1145 for(var n =0; n != 256; ++n){
1146 c = n;
1147 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1148 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1149 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1150 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1151 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1152 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1153 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1154 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1155 table[n] = c;
1156 }
1157
1158 return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table;
1159}
1160
1161var T = signed_crc_table();
1162function crc32_bstr(bstr, seed) {
1163 var C = seed ^ -1, L = bstr.length - 1;
1164 for(var i = 0; i < L;) {
1165 C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
1166 C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
1167 }
1168 if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF];
1169 return C ^ -1;
1170}
1171
1172function crc32_buf(buf, seed) {
1173 if(buf.length > 10000) return crc32_buf_8(buf, seed);
1174 var C = seed ^ -1, L = buf.length - 3;
1175 for(var i = 0; i < L;) {
1176 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1177 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1178 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1179 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1180 }
1181 while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1182 return C ^ -1;
1183}
1184
1185function crc32_buf_8(buf, seed) {
1186 var C = seed ^ -1, L = buf.length - 7;
1187 for(var i = 0; i < L;) {
1188 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1189 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1190 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1191 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1192 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1193 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1194 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1195 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1196 }
1197 while(i < L+7) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1198 return C ^ -1;
1199}
1200
1201function crc32_str(str, seed) {
1202 var C = seed ^ -1;
1203 for(var i = 0, L=str.length, c, d; i < L;) {
1204 c = str.charCodeAt(i++);
1205 if(c < 0x80) {
1206 C = (C>>>8) ^ T[(C ^ c)&0xFF];
1207 } else if(c < 0x800) {
1208 C = (C>>>8) ^ T[(C ^ (192|((c>>6)&31)))&0xFF];
1209 C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF];
1210 } else if(c >= 0xD800 && c < 0xE000) {
1211 c = (c&1023)+64; d = str.charCodeAt(i++)&1023;
1212 C = (C>>>8) ^ T[(C ^ (240|((c>>8)&7)))&0xFF];
1213 C = (C>>>8) ^ T[(C ^ (128|((c>>2)&63)))&0xFF];
1214 C = (C>>>8) ^ T[(C ^ (128|((d>>6)&15)|((c&3)<<4)))&0xFF];
1215 C = (C>>>8) ^ T[(C ^ (128|(d&63)))&0xFF];
1216 } else {
1217 C = (C>>>8) ^ T[(C ^ (224|((c>>12)&15)))&0xFF];
1218 C = (C>>>8) ^ T[(C ^ (128|((c>>6)&63)))&0xFF];
1219 C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF];
1220 }
1221 }
1222 return C ^ -1;
1223}
1224CRC32.table = T;
1225CRC32.bstr = crc32_bstr;
1226CRC32.buf = crc32_buf;
1227CRC32.str = crc32_str;
1228}));
1229/* [MS-CFB] v20171201 */
1230var CFB = (function _CFB(){
1231var exports = {};
1232exports.version = '1.1.4';
1233/* [MS-CFB] 2.6.4 */
1234function namecmp(l, r) {
1235 var L = l.split("/"), R = r.split("/");
1236 for(var i = 0, c = 0, Z = Math.min(L.length, R.length); i < Z; ++i) {
1237 if((c = L[i].length - R[i].length)) return c;
1238 if(L[i] != R[i]) return L[i] < R[i] ? -1 : 1;
1239 }
1240 return L.length - R.length;
1241}
1242function dirname(p) {
1243 if(p.charAt(p.length - 1) == "/") return (p.slice(0,-1).indexOf("/") === -1) ? p : dirname(p.slice(0, -1));
1244 var c = p.lastIndexOf("/");
1245 return (c === -1) ? p : p.slice(0, c+1);
1246}
1247
1248function filename(p) {
1249 if(p.charAt(p.length - 1) == "/") return filename(p.slice(0, -1));
1250 var c = p.lastIndexOf("/");
1251 return (c === -1) ? p : p.slice(c+1);
1252}
1253/* -------------------------------------------------------------------------- */
1254/* DOS Date format:
1255 high|YYYYYYYm.mmmddddd.HHHHHMMM.MMMSSSSS|low
1256 add 1980 to stored year
1257 stored second should be doubled
1258*/
1259
1260/* write JS date to buf as a DOS date */
1261function write_dos_date(buf, date) {
1262 if(typeof date === "string") date = new Date(date);
1263 var hms = date.getHours();
1264 hms = hms << 6 | date.getMinutes();
1265 hms = hms << 5 | (date.getSeconds()>>>1);
1266 buf.write_shift(2, hms);
1267 var ymd = (date.getFullYear() - 1980);
1268 ymd = ymd << 4 | (date.getMonth()+1);
1269 ymd = ymd << 5 | date.getDate();
1270 buf.write_shift(2, ymd);
1271}
1272
1273/* read four bytes from buf and interpret as a DOS date */
1274function parse_dos_date(buf) {
1275 var hms = buf.read_shift(2) & 0xFFFF;
1276 var ymd = buf.read_shift(2) & 0xFFFF;
1277 var val = new Date();
1278 var d = ymd & 0x1F; ymd >>>= 5;
1279 var m = ymd & 0x0F; ymd >>>= 4;
1280 val.setMilliseconds(0);
1281 val.setFullYear(ymd + 1980);
1282 val.setMonth(m-1);
1283 val.setDate(d);
1284 var S = hms & 0x1F; hms >>>= 5;
1285 var M = hms & 0x3F; hms >>>= 6;
1286 val.setHours(hms);
1287 val.setMinutes(M);
1288 val.setSeconds(S<<1);
1289 return val;
1290}
1291function parse_extra_field(blob) {
1292 prep_blob(blob, 0);
1293 var o = {};
1294 var flags = 0;
1295 while(blob.l <= blob.length - 4) {
1296 var type = blob.read_shift(2);
1297 var sz = blob.read_shift(2), tgt = blob.l + sz;
1298 var p = {};
1299 switch(type) {
1300 /* UNIX-style Timestamps */
1301 case 0x5455: {
1302 flags = blob.read_shift(1);
1303 if(flags & 1) p.mtime = blob.read_shift(4);
1304 /* for some reason, CD flag corresponds to LFH */
1305 if(sz > 5) {
1306 if(flags & 2) p.atime = blob.read_shift(4);
1307 if(flags & 4) p.ctime = blob.read_shift(4);
1308 }
1309 if(p.mtime) p.mt = new Date(p.mtime*1000);
1310 }
1311 break;
1312 }
1313 blob.l = tgt;
1314 o[type] = p;
1315 }
1316 return o;
1317}
1318var fs;
1319function get_fs() { return fs || (fs = require('fs')); }
1320function parse(file, options) {
1321if(file[0] == 0x50 && file[1] == 0x4b) return parse_zip(file, options);
1322if(file.length < 512) throw new Error("CFB file size " + file.length + " < 512");
1323var mver = 3;
1324var ssz = 512;
1325var nmfs = 0; // number of mini FAT sectors
1326var difat_sec_cnt = 0;
1327var dir_start = 0;
1328var minifat_start = 0;
1329var difat_start = 0;
1330
1331var fat_addrs = []; // locations of FAT sectors
1332
1333/* [MS-CFB] 2.2 Compound File Header */
1334var blob = file.slice(0,512);
1335prep_blob(blob, 0);
1336
1337/* major version */
1338var mv = check_get_mver(blob);
1339mver = mv[0];
1340switch(mver) {
1341 case 3: ssz = 512; break; case 4: ssz = 4096; break;
1342 case 0: if(mv[1] == 0) return parse_zip(file, options);
1343 /* falls through */
1344 default: throw new Error("Major Version: Expected 3 or 4 saw " + mver);
1345}
1346
1347/* reprocess header */
1348if(ssz !== 512) { blob = file.slice(0,ssz); prep_blob(blob, 28 /* blob.l */); }
1349/* Save header for final object */
1350var header = file.slice(0,ssz);
1351
1352check_shifts(blob, mver);
1353
1354// Number of Directory Sectors
1355var dir_cnt = blob.read_shift(4, 'i');
1356if(mver === 3 && dir_cnt !== 0) throw new Error('# Directory Sectors: Expected 0 saw ' + dir_cnt);
1357
1358// Number of FAT Sectors
1359blob.l += 4;
1360
1361// First Directory Sector Location
1362dir_start = blob.read_shift(4, 'i');
1363
1364// Transaction Signature
1365blob.l += 4;
1366
1367// Mini Stream Cutoff Size
1368blob.chk('00100000', 'Mini Stream Cutoff Size: ');
1369
1370// First Mini FAT Sector Location
1371minifat_start = blob.read_shift(4, 'i');
1372
1373// Number of Mini FAT Sectors
1374nmfs = blob.read_shift(4, 'i');
1375
1376// First DIFAT sector location
1377difat_start = blob.read_shift(4, 'i');
1378
1379// Number of DIFAT Sectors
1380difat_sec_cnt = blob.read_shift(4, 'i');
1381
1382// Grab FAT Sector Locations
1383for(var q = -1, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */
1384 q = blob.read_shift(4, 'i');
1385 if(q<0) break;
1386 fat_addrs[j] = q;
1387}
1388
1389/** Break the file up into sectors */
1390var sectors = sectorify(file, ssz);
1391
1392sleuth_fat(difat_start, difat_sec_cnt, sectors, ssz, fat_addrs);
1393
1394/** Chains */
1395var sector_list = make_sector_list(sectors, dir_start, fat_addrs, ssz);
1396
1397sector_list[dir_start].name = "!Directory";
1398if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
1399sector_list[fat_addrs[0]].name = "!FAT";
1400sector_list.fat_addrs = fat_addrs;
1401sector_list.ssz = ssz;
1402
1403/* [MS-CFB] 2.6.1 Compound File Directory Entry */
1404var files = {}, Paths = [], FileIndex = [], FullPaths = [];
1405read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex, minifat_start);
1406
1407build_full_paths(FileIndex, FullPaths, Paths);
1408Paths.shift();
1409
1410var o = {
1411 FileIndex: FileIndex,
1412 FullPaths: FullPaths
1413};
1414
1415// $FlowIgnore
1416if(options && options.raw) o.raw = {header: header, sectors: sectors};
1417return o;
1418} // parse
1419
1420/* [MS-CFB] 2.2 Compound File Header -- read up to major version */
1421function check_get_mver(blob) {
1422 if(blob[blob.l] == 0x50 && blob[blob.l + 1] == 0x4b) return [0, 0];
1423 // header signature 8
1424 blob.chk(HEADER_SIGNATURE, 'Header Signature: ');
1425
1426 // clsid 16
1427 //blob.chk(HEADER_CLSID, 'CLSID: ');
1428 blob.l += 16;
1429
1430 // minor version 2
1431 var mver = blob.read_shift(2, 'u');
1432
1433 return [blob.read_shift(2,'u'), mver];
1434}
1435function check_shifts(blob, mver) {
1436 var shift = 0x09;
1437
1438 // Byte Order
1439 //blob.chk('feff', 'Byte Order: '); // note: some writers put 0xffff
1440 blob.l += 2;
1441
1442 // Sector Shift
1443 switch((shift = blob.read_shift(2))) {
1444 case 0x09: if(mver != 3) throw new Error('Sector Shift: Expected 9 saw ' + shift); break;
1445 case 0x0c: if(mver != 4) throw new Error('Sector Shift: Expected 12 saw ' + shift); break;
1446 default: throw new Error('Sector Shift: Expected 9 or 12 saw ' + shift);
1447 }
1448
1449 // Mini Sector Shift
1450 blob.chk('0600', 'Mini Sector Shift: ');
1451
1452 // Reserved
1453 blob.chk('000000000000', 'Reserved: ');
1454}
1455
1456/** Break the file up into sectors */
1457function sectorify(file, ssz) {
1458 var nsectors = Math.ceil(file.length/ssz)-1;
1459 var sectors = [];
1460 for(var i=1; i < nsectors; ++i) sectors[i-1] = file.slice(i*ssz,(i+1)*ssz);
1461 sectors[nsectors-1] = file.slice(nsectors*ssz);
1462 return sectors;
1463}
1464
1465/* [MS-CFB] 2.6.4 Red-Black Tree */
1466function build_full_paths(FI, FP, Paths) {
1467 var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length;
1468 var dad = [], q = [];
1469
1470 for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; }
1471
1472 for(; j < q.length; ++j) {
1473 i = q[j];
1474 L = FI[i].L; R = FI[i].R; C = FI[i].C;
1475 if(dad[i] === i) {
1476 if(L !== -1 /*NOSTREAM*/ && dad[L] !== L) dad[i] = dad[L];
1477 if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
1478 }
1479 if(C !== -1 /*NOSTREAM*/) dad[C] = i;
1480 if(L !== -1 && i != dad[i]) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
1481 if(R !== -1 && i != dad[i]) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
1482 }
1483 for(i=1; i < pl; ++i) if(dad[i] === i) {
1484 if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
1485 else if(L !== -1 && dad[L] !== L) dad[i] = dad[L];
1486 }
1487
1488 for(i=1; i < pl; ++i) {
1489 if(FI[i].type === 0 /* unknown */) continue;
1490 j = i;
1491 if(j != dad[j]) do {
1492 j = dad[j];
1493 FP[i] = FP[j] + "/" + FP[i];
1494 } while (j !== 0 && -1 !== dad[j] && j != dad[j]);
1495 dad[i] = -1;
1496 }
1497
1498 FP[0] += "/";
1499 for(i=1; i < pl; ++i) {
1500 if(FI[i].type !== 2 /* stream */) FP[i] += "/";
1501 }
1502}
1503
1504function get_mfat_entry(entry, payload, mini) {
1505 var start = entry.start, size = entry.size;
1506 //return (payload.slice(start*MSSZ, start*MSSZ + size));
1507 var o = [];
1508 var idx = start;
1509 while(mini && size > 0 && idx >= 0) {
1510 o.push(payload.slice(idx * MSSZ, idx * MSSZ + MSSZ));
1511 size -= MSSZ;
1512 idx = __readInt32LE(mini, idx * 4);
1513 }
1514 if(o.length === 0) return (new_buf(0));
1515 return (bconcat(o).slice(0, entry.size));
1516}
1517
1518/** Chase down the rest of the DIFAT chain to build a comprehensive list
1519 DIFAT chains by storing the next sector number as the last 32 bits */
1520function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) {
1521 var q = ENDOFCHAIN;
1522 if(idx === ENDOFCHAIN) {
1523 if(cnt !== 0) throw new Error("DIFAT chain shorter than expected");
1524 } else if(idx !== -1 /*FREESECT*/) {
1525 var sector = sectors[idx], m = (ssz>>>2)-1;
1526 if(!sector) return;
1527 for(var i = 0; i < m; ++i) {
1528 if((q = __readInt32LE(sector,i*4)) === ENDOFCHAIN) break;
1529 fat_addrs.push(q);
1530 }
1531 sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs);
1532 }
1533}
1534
1535/** Follow the linked list of sectors for a given starting point */
1536function get_sector_list(sectors, start, fat_addrs, ssz, chkd) {
1537 var buf = [], buf_chain = [];
1538 if(!chkd) chkd = [];
1539 var modulus = ssz - 1, j = 0, jj = 0;
1540 for(j=start; j>=0;) {
1541 chkd[j] = true;
1542 buf[buf.length] = j;
1543 buf_chain.push(sectors[j]);
1544 var addr = fat_addrs[Math.floor(j*4/ssz)];
1545 jj = ((j*4) & modulus);
1546 if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz);
1547 if(!sectors[addr]) break;
1548 j = __readInt32LE(sectors[addr], jj);
1549 }
1550 return {nodes: buf, data:__toBuffer([buf_chain])};
1551}
1552
1553/** Chase down the sector linked lists */
1554function make_sector_list(sectors, dir_start, fat_addrs, ssz) {
1555 var sl = sectors.length, sector_list = ([]);
1556 var chkd = [], buf = [], buf_chain = [];
1557 var modulus = ssz - 1, i=0, j=0, k=0, jj=0;
1558 for(i=0; i < sl; ++i) {
1559 buf = ([]);
1560 k = (i + dir_start); if(k >= sl) k-=sl;
1561 if(chkd[k]) continue;
1562 buf_chain = [];
1563 var seen = [];
1564 for(j=k; j>=0;) {
1565 seen[j] = true;
1566 chkd[j] = true;
1567 buf[buf.length] = j;
1568 buf_chain.push(sectors[j]);
1569 var addr = fat_addrs[Math.floor(j*4/ssz)];
1570 jj = ((j*4) & modulus);
1571 if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz);
1572 if(!sectors[addr]) break;
1573 j = __readInt32LE(sectors[addr], jj);
1574 if(seen[j]) break;
1575 }
1576 sector_list[k] = ({nodes: buf, data:__toBuffer([buf_chain])});
1577 }
1578 return sector_list;
1579}
1580
1581/* [MS-CFB] 2.6.1 Compound File Directory Entry */
1582function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex, mini) {
1583 var minifat_store = 0, pl = (Paths.length?2:0);
1584 var sector = sector_list[dir_start].data;
1585 var i = 0, namelen = 0, name;
1586 for(; i < sector.length; i+= 128) {
1587 var blob = sector.slice(i, i+128);
1588 prep_blob(blob, 64);
1589 namelen = blob.read_shift(2);
1590 name = __utf16le(blob,0,namelen-pl);
1591 Paths.push(name);
1592 var o = ({
1593 name: name,
1594 type: blob.read_shift(1),
1595 color: blob.read_shift(1),
1596 L: blob.read_shift(4, 'i'),
1597 R: blob.read_shift(4, 'i'),
1598 C: blob.read_shift(4, 'i'),
1599 clsid: blob.read_shift(16),
1600 state: blob.read_shift(4, 'i'),
1601 start: 0,
1602 size: 0
1603 });
1604 var ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2);
1605 if(ctime !== 0) o.ct = read_date(blob, blob.l-8);
1606 var mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2);
1607 if(mtime !== 0) o.mt = read_date(blob, blob.l-8);
1608 o.start = blob.read_shift(4, 'i');
1609 o.size = blob.read_shift(4, 'i');
1610 if(o.size < 0 && o.start < 0) { o.size = o.type = 0; o.start = ENDOFCHAIN; o.name = ""; }
1611 if(o.type === 5) { /* root */
1612 minifat_store = o.start;
1613 if(nmfs > 0 && minifat_store !== ENDOFCHAIN) sector_list[minifat_store].name = "!StreamData";
1614 /*minifat_size = o.size;*/
1615 } else if(o.size >= 4096 /* MSCSZ */) {
1616 o.storage = 'fat';
1617 if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz);
1618 sector_list[o.start].name = o.name;
1619 o.content = (sector_list[o.start].data.slice(0,o.size));
1620 } else {
1621 o.storage = 'minifat';
1622 if(o.size < 0) o.size = 0;
1623 else if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) {
1624 o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini]||{}).data);
1625 }
1626 }
1627 if(o.content) prep_blob(o.content, 0);
1628 files[name] = o;
1629 FileIndex.push(o);
1630 }
1631}
1632
1633function read_date(blob, offset) {
1634 return new Date(( ( (__readUInt32LE(blob,offset+4)/1e7)*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7 ) - 11644473600)*1000);
1635}
1636
1637function read_file(filename, options) {
1638 get_fs();
1639 return parse(fs.readFileSync(filename), options);
1640}
1641
1642function read(blob, options) {
1643 switch(options && options.type || "base64") {
1644 case "file": return read_file(blob, options);
1645 case "base64": return parse(s2a(Base64.decode(blob)), options);
1646 case "binary": return parse(s2a(blob), options);
1647 }
1648 return parse(blob, options);
1649}
1650
1651function init_cfb(cfb, opts) {
1652 var o = opts || {}, root = o.root || "Root Entry";
1653 if(!cfb.FullPaths) cfb.FullPaths = [];
1654 if(!cfb.FileIndex) cfb.FileIndex = [];
1655 if(cfb.FullPaths.length !== cfb.FileIndex.length) throw new Error("inconsistent CFB structure");
1656 if(cfb.FullPaths.length === 0) {
1657 cfb.FullPaths[0] = root + "/";
1658 cfb.FileIndex[0] = ({ name: root, type: 5 });
1659 }
1660 if(o.CLSID) cfb.FileIndex[0].clsid = o.CLSID;
1661 seed_cfb(cfb);
1662}
1663function seed_cfb(cfb) {
1664 var nm = "\u0001Sh33tJ5";
1665 if(CFB.find(cfb, "/" + nm)) return;
1666 var p = new_buf(4); p[0] = 55; p[1] = p[3] = 50; p[2] = 54;
1667 cfb.FileIndex.push(({ name: nm, type: 2, content:p, size:4, L:69, R:69, C:69 }));
1668 cfb.FullPaths.push(cfb.FullPaths[0] + nm);
1669 rebuild_cfb(cfb);
1670}
1671function rebuild_cfb(cfb, f) {
1672 init_cfb(cfb);
1673 var gc = false, s = false;
1674 for(var i = cfb.FullPaths.length - 1; i >= 0; --i) {
1675 var _file = cfb.FileIndex[i];
1676 switch(_file.type) {
1677 case 0:
1678 if(s) gc = true;
1679 else { cfb.FileIndex.pop(); cfb.FullPaths.pop(); }
1680 break;
1681 case 1: case 2: case 5:
1682 s = true;
1683 if(isNaN(_file.R * _file.L * _file.C)) gc = true;
1684 if(_file.R > -1 && _file.L > -1 && _file.R == _file.L) gc = true;
1685 break;
1686 default: gc = true; break;
1687 }
1688 }
1689 if(!gc && !f) return;
1690
1691 var now = new Date(1987, 1, 19), j = 0;
1692 var data = [];
1693 for(i = 0; i < cfb.FullPaths.length; ++i) {
1694 if(cfb.FileIndex[i].type === 0) continue;
1695 data.push([cfb.FullPaths[i], cfb.FileIndex[i]]);
1696 }
1697 for(i = 0; i < data.length; ++i) {
1698 var dad = dirname(data[i][0]);
1699 s = false;
1700 for(j = 0; j < data.length; ++j) if(data[j][0] === dad) s = true;
1701 if(!s) data.push([dad, ({
1702 name: filename(dad).replace("/",""),
1703 type: 1,
1704 clsid: HEADER_CLSID,
1705 ct: now, mt: now,
1706 content: null
1707 })]);
1708 }
1709
1710 data.sort(function(x,y) { return namecmp(x[0], y[0]); });
1711 cfb.FullPaths = []; cfb.FileIndex = [];
1712 for(i = 0; i < data.length; ++i) { cfb.FullPaths[i] = data[i][0]; cfb.FileIndex[i] = data[i][1]; }
1713 for(i = 0; i < data.length; ++i) {
1714 var elt = cfb.FileIndex[i];
1715 var nm = cfb.FullPaths[i];
1716
1717 elt.name = filename(nm).replace("/","");
1718 elt.L = elt.R = elt.C = -(elt.color = 1);
1719 elt.size = elt.content ? elt.content.length : 0;
1720 elt.start = 0;
1721 elt.clsid = (elt.clsid || HEADER_CLSID);
1722 if(i === 0) {
1723 elt.C = data.length > 1 ? 1 : -1;
1724 elt.size = 0;
1725 elt.type = 5;
1726 } else if(nm.slice(-1) == "/") {
1727 for(j=i+1;j < data.length; ++j) if(dirname(cfb.FullPaths[j])==nm) break;
1728 elt.C = j >= data.length ? -1 : j;
1729 for(j=i+1;j < data.length; ++j) if(dirname(cfb.FullPaths[j])==dirname(nm)) break;
1730 elt.R = j >= data.length ? -1 : j;
1731 elt.type = 1;
1732 } else {
1733 if(dirname(cfb.FullPaths[i+1]||"") == dirname(nm)) elt.R = i + 1;
1734 elt.type = 2;
1735 }
1736 }
1737
1738}
1739
1740function _write(cfb, options) {
1741 var _opts = options || {};
1742 rebuild_cfb(cfb);
1743 if(_opts.fileType == 'zip') return write_zip(cfb, _opts);
1744 var L = (function(cfb){
1745 var mini_size = 0, fat_size = 0;
1746 for(var i = 0; i < cfb.FileIndex.length; ++i) {
1747 var file = cfb.FileIndex[i];
1748 if(!file.content) continue;
1749var flen = file.content.length;
1750 if(flen > 0){
1751 if(flen < 0x1000) mini_size += (flen + 0x3F) >> 6;
1752 else fat_size += (flen + 0x01FF) >> 9;
1753 }
1754 }
1755 var dir_cnt = (cfb.FullPaths.length +3) >> 2;
1756 var mini_cnt = (mini_size + 7) >> 3;
1757 var mfat_cnt = (mini_size + 0x7F) >> 7;
1758 var fat_base = mini_cnt + fat_size + dir_cnt + mfat_cnt;
1759 var fat_cnt = (fat_base + 0x7F) >> 7;
1760 var difat_cnt = fat_cnt <= 109 ? 0 : Math.ceil((fat_cnt-109)/0x7F);
1761 while(((fat_base + fat_cnt + difat_cnt + 0x7F) >> 7) > fat_cnt) difat_cnt = ++fat_cnt <= 109 ? 0 : Math.ceil((fat_cnt-109)/0x7F);
1762 var L = [1, difat_cnt, fat_cnt, mfat_cnt, dir_cnt, fat_size, mini_size, 0];
1763 cfb.FileIndex[0].size = mini_size << 6;
1764 L[7] = (cfb.FileIndex[0].start=L[0]+L[1]+L[2]+L[3]+L[4]+L[5])+((L[6]+7) >> 3);
1765 return L;
1766 })(cfb);
1767 var o = new_buf(L[7] << 9);
1768 var i = 0, T = 0;
1769 {
1770 for(i = 0; i < 8; ++i) o.write_shift(1, HEADER_SIG[i]);
1771 for(i = 0; i < 8; ++i) o.write_shift(2, 0);
1772 o.write_shift(2, 0x003E);
1773 o.write_shift(2, 0x0003);
1774 o.write_shift(2, 0xFFFE);
1775 o.write_shift(2, 0x0009);
1776 o.write_shift(2, 0x0006);
1777 for(i = 0; i < 3; ++i) o.write_shift(2, 0);
1778 o.write_shift(4, 0);
1779 o.write_shift(4, L[2]);
1780 o.write_shift(4, L[0] + L[1] + L[2] + L[3] - 1);
1781 o.write_shift(4, 0);
1782 o.write_shift(4, 1<<12);
1783 o.write_shift(4, L[3] ? L[0] + L[1] + L[2] - 1: ENDOFCHAIN);
1784 o.write_shift(4, L[3]);
1785 o.write_shift(-4, L[1] ? L[0] - 1: ENDOFCHAIN);
1786 o.write_shift(4, L[1]);
1787 for(i = 0; i < 109; ++i) o.write_shift(-4, i < L[2] ? L[1] + i : -1);
1788 }
1789 if(L[1]) {
1790 for(T = 0; T < L[1]; ++T) {
1791 for(; i < 236 + T * 127; ++i) o.write_shift(-4, i < L[2] ? L[1] + i : -1);
1792 o.write_shift(-4, T === L[1] - 1 ? ENDOFCHAIN : T + 1);
1793 }
1794 }
1795 var chainit = function(w) {
1796 for(T += w; i<T-1; ++i) o.write_shift(-4, i+1);
1797 if(w) { ++i; o.write_shift(-4, ENDOFCHAIN); }
1798 };
1799 T = i = 0;
1800 for(T+=L[1]; i<T; ++i) o.write_shift(-4, consts.DIFSECT);
1801 for(T+=L[2]; i<T; ++i) o.write_shift(-4, consts.FATSECT);
1802 chainit(L[3]);
1803 chainit(L[4]);
1804 var j = 0, flen = 0;
1805 var file = cfb.FileIndex[0];
1806 for(; j < cfb.FileIndex.length; ++j) {
1807 file = cfb.FileIndex[j];
1808 if(!file.content) continue;
1809flen = file.content.length;
1810 if(flen < 0x1000) continue;
1811 file.start = T;
1812 chainit((flen + 0x01FF) >> 9);
1813 }
1814 chainit((L[6] + 7) >> 3);
1815 while(o.l & 0x1FF) o.write_shift(-4, consts.ENDOFCHAIN);
1816 T = i = 0;
1817 for(j = 0; j < cfb.FileIndex.length; ++j) {
1818 file = cfb.FileIndex[j];
1819 if(!file.content) continue;
1820flen = file.content.length;
1821 if(!flen || flen >= 0x1000) continue;
1822 file.start = T;
1823 chainit((flen + 0x3F) >> 6);
1824 }
1825 while(o.l & 0x1FF) o.write_shift(-4, consts.ENDOFCHAIN);
1826 for(i = 0; i < L[4]<<2; ++i) {
1827 var nm = cfb.FullPaths[i];
1828 if(!nm || nm.length === 0) {
1829 for(j = 0; j < 17; ++j) o.write_shift(4, 0);
1830 for(j = 0; j < 3; ++j) o.write_shift(4, -1);
1831 for(j = 0; j < 12; ++j) o.write_shift(4, 0);
1832 continue;
1833 }
1834 file = cfb.FileIndex[i];
1835 if(i === 0) file.start = file.size ? file.start - 1 : ENDOFCHAIN;
1836 var _nm = (i === 0 && _opts.root) || file.name;
1837 flen = 2*(_nm.length+1);
1838 o.write_shift(64, _nm, "utf16le");
1839 o.write_shift(2, flen);
1840 o.write_shift(1, file.type);
1841 o.write_shift(1, file.color);
1842 o.write_shift(-4, file.L);
1843 o.write_shift(-4, file.R);
1844 o.write_shift(-4, file.C);
1845 if(!file.clsid) for(j = 0; j < 4; ++j) o.write_shift(4, 0);
1846 else o.write_shift(16, file.clsid, "hex");
1847 o.write_shift(4, file.state || 0);
1848 o.write_shift(4, 0); o.write_shift(4, 0);
1849 o.write_shift(4, 0); o.write_shift(4, 0);
1850 o.write_shift(4, file.start);
1851 o.write_shift(4, file.size); o.write_shift(4, 0);
1852 }
1853 for(i = 1; i < cfb.FileIndex.length; ++i) {
1854 file = cfb.FileIndex[i];
1855if(file.size >= 0x1000) {
1856 o.l = (file.start+1) << 9;
1857 for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]);
1858 for(; j & 0x1FF; ++j) o.write_shift(1, 0);
1859 }
1860 }
1861 for(i = 1; i < cfb.FileIndex.length; ++i) {
1862 file = cfb.FileIndex[i];
1863if(file.size > 0 && file.size < 0x1000) {
1864 for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]);
1865 for(; j & 0x3F; ++j) o.write_shift(1, 0);
1866 }
1867 }
1868 while(o.l < o.length) o.write_shift(1, 0);
1869 return o;
1870}
1871/* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */
1872function find(cfb, path) {
1873 var UCFullPaths = cfb.FullPaths.map(function(x) { return x.toUpperCase(); });
1874 var UCPaths = UCFullPaths.map(function(x) { var y = x.split("/"); return y[y.length - (x.slice(-1) == "/" ? 2 : 1)]; });
1875 var k = false;
1876 if(path.charCodeAt(0) === 47 /* "/" */) { k = true; path = UCFullPaths[0].slice(0, -1) + path; }
1877 else k = path.indexOf("/") !== -1;
1878 var UCPath = path.toUpperCase();
1879 var w = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath);
1880 if(w !== -1) return cfb.FileIndex[w];
1881
1882 var m = !UCPath.match(chr1);
1883 UCPath = UCPath.replace(chr0,'');
1884 if(m) UCPath = UCPath.replace(chr1,'!');
1885 for(w = 0; w < UCFullPaths.length; ++w) {
1886 if((m ? UCFullPaths[w].replace(chr1,'!') : UCFullPaths[w]).replace(chr0,'') == UCPath) return cfb.FileIndex[w];
1887 if((m ? UCPaths[w].replace(chr1,'!') : UCPaths[w]).replace(chr0,'') == UCPath) return cfb.FileIndex[w];
1888 }
1889 return null;
1890}
1891/** CFB Constants */
1892var MSSZ = 64; /* Mini Sector Size = 1<<6 */
1893//var MSCSZ = 4096; /* Mini Stream Cutoff Size */
1894/* 2.1 Compound File Sector Numbers and Types */
1895var ENDOFCHAIN = -2;
1896/* 2.2 Compound File Header */
1897var HEADER_SIGNATURE = 'd0cf11e0a1b11ae1';
1898var HEADER_SIG = [0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1];
1899var HEADER_CLSID = '00000000000000000000000000000000';
1900var consts = {
1901 /* 2.1 Compund File Sector Numbers and Types */
1902 MAXREGSECT: -6,
1903 DIFSECT: -4,
1904 FATSECT: -3,
1905 ENDOFCHAIN: ENDOFCHAIN,
1906 FREESECT: -1,
1907 /* 2.2 Compound File Header */
1908 HEADER_SIGNATURE: HEADER_SIGNATURE,
1909 HEADER_MINOR_VERSION: '3e00',
1910 MAXREGSID: -6,
1911 NOSTREAM: -1,
1912 HEADER_CLSID: HEADER_CLSID,
1913 /* 2.6.1 Compound File Directory Entry */
1914 EntryTypes: ['unknown','storage','stream','lockbytes','property','root']
1915};
1916
1917function write_file(cfb, filename, options) {
1918 get_fs();
1919 var o = _write(cfb, options);
1920fs.writeFileSync(filename, o);
1921}
1922
1923function a2s(o) {
1924 var out = new Array(o.length);
1925 for(var i = 0; i < o.length; ++i) out[i] = String.fromCharCode(o[i]);
1926 return out.join("");
1927}
1928
1929function write(cfb, options) {
1930 var o = _write(cfb, options);
1931 switch(options && options.type) {
1932 case "file": get_fs(); fs.writeFileSync(options.filename, (o)); return o;
1933 case "binary": return a2s(o);
1934 case "base64": return Base64.encode(a2s(o));
1935 }
1936 return o;
1937}
1938/* node < 8.1 zlib does not expose bytesRead, so default to pure JS */
1939var _zlib;
1940function use_zlib(zlib) { try {
1941 var InflateRaw = zlib.InflateRaw;
1942 var InflRaw = new InflateRaw();
1943 InflRaw._processChunk(new Uint8Array([3, 0]), InflRaw._finishFlushFlag);
1944 if(InflRaw.bytesRead) _zlib = zlib;
1945 else throw new Error("zlib does not expose bytesRead");
1946} catch(e) {console.error("cannot use native zlib: " + (e.message || e)); } }
1947
1948function _inflateRawSync(payload, usz) {
1949 if(!_zlib) return _inflate(payload, usz);
1950 var InflateRaw = _zlib.InflateRaw;
1951 var InflRaw = new InflateRaw();
1952 var out = InflRaw._processChunk(payload.slice(payload.l), InflRaw._finishFlushFlag);
1953 payload.l += InflRaw.bytesRead;
1954 return out;
1955}
1956
1957function _deflateRawSync(payload) {
1958 return _zlib ? _zlib.deflateRawSync(payload) : _deflate(payload);
1959}
1960var CLEN_ORDER = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
1961
1962/* LEN_ID = [ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285 ]; */
1963var LEN_LN = [ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13 , 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 ];
1964
1965/* DST_ID = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 ]; */
1966var DST_LN = [ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 ];
1967
1968function bit_swap_8(n) { var t = (((((n<<1)|(n<<11)) & 0x22110) | (((n<<5)|(n<<15)) & 0x88440))); return ((t>>16) | (t>>8) |t)&0xFF; }
1969
1970var use_typed_arrays = typeof Uint8Array !== 'undefined';
1971
1972var bitswap8 = use_typed_arrays ? new Uint8Array(1<<8) : [];
1973for(var q = 0; q < (1<<8); ++q) bitswap8[q] = bit_swap_8(q);
1974
1975function bit_swap_n(n, b) {
1976 var rev = bitswap8[n & 0xFF];
1977 if(b <= 8) return rev >>> (8-b);
1978 rev = (rev << 8) | bitswap8[(n>>8)&0xFF];
1979 if(b <= 16) return rev >>> (16-b);
1980 rev = (rev << 8) | bitswap8[(n>>16)&0xFF];
1981 return rev >>> (24-b);
1982}
1983
1984/* helpers for unaligned bit reads */
1985function read_bits_2(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 6 ? 0 : buf[h+1]<<8))>>>w)& 0x03; }
1986function read_bits_3(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 5 ? 0 : buf[h+1]<<8))>>>w)& 0x07; }
1987function read_bits_4(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 4 ? 0 : buf[h+1]<<8))>>>w)& 0x0F; }
1988function read_bits_5(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 3 ? 0 : buf[h+1]<<8))>>>w)& 0x1F; }
1989function read_bits_7(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 1 ? 0 : buf[h+1]<<8))>>>w)& 0x7F; }
1990
1991/* works up to n = 3 * 8 + 1 = 25 */
1992function read_bits_n(buf, bl, n) {
1993 var w = (bl&7), h = (bl>>>3), f = ((1<<n)-1);
1994 var v = buf[h] >>> w;
1995 if(n < 8 - w) return v & f;
1996 v |= buf[h+1]<<(8-w);
1997 if(n < 16 - w) return v & f;
1998 v |= buf[h+2]<<(16-w);
1999 if(n < 24 - w) return v & f;
2000 v |= buf[h+3]<<(24-w);
2001 return v & f;
2002}
2003
2004/* until ArrayBuffer#realloc is a thing, fake a realloc */
2005function realloc(b, sz) {
2006 var L = b.length, M = 2*L > sz ? 2*L : sz + 5, i = 0;
2007 if(L >= sz) return b;
2008 if(has_buf) {
2009 var o = new_unsafe_buf(M);
2010 // $FlowIgnore
2011 if(b.copy) b.copy(o);
2012 else for(; i < b.length; ++i) o[i] = b[i];
2013 return o;
2014 } else if(use_typed_arrays) {
2015 var a = new Uint8Array(M);
2016 if(a.set) a.set(b);
2017 else for(; i < b.length; ++i) a[i] = b[i];
2018 return a;
2019 }
2020 b.length = M;
2021 return b;
2022}
2023
2024/* zero-filled arrays for older browsers */
2025function zero_fill_array(n) {
2026 var o = new Array(n);
2027 for(var i = 0; i < n; ++i) o[i] = 0;
2028 return o;
2029}var _deflate = (function() {
2030var _deflateRaw = (function() {
2031 return function deflateRaw(data, out) {
2032 var boff = 0;
2033 while(boff < data.length) {
2034 var L = Math.min(0xFFFF, data.length - boff);
2035 var h = boff + L == data.length;
2036 /* TODO: this is only type 0 stored */
2037 out.write_shift(1, +h);
2038 out.write_shift(2, L);
2039 out.write_shift(2, (~L) & 0xFFFF);
2040 while(L-- > 0) out[out.l++] = data[boff++];
2041 }
2042 return out.l;
2043 };
2044})();
2045
2046return function(data) {
2047 var buf = new_buf(50+Math.floor(data.length*1.1));
2048 var off = _deflateRaw(data, buf);
2049 return buf.slice(0, off);
2050};
2051})();
2052/* modified inflate function also moves original read head */
2053
2054/* build tree (used for literals and lengths) */
2055function build_tree(clens, cmap, MAX) {
2056 var maxlen = 1, w = 0, i = 0, j = 0, ccode = 0, L = clens.length;
2057
2058 var bl_count = use_typed_arrays ? new Uint16Array(32) : zero_fill_array(32);
2059 for(i = 0; i < 32; ++i) bl_count[i] = 0;
2060
2061 for(i = L; i < MAX; ++i) clens[i] = 0;
2062 L = clens.length;
2063
2064 var ctree = use_typed_arrays ? new Uint16Array(L) : zero_fill_array(L); // []
2065
2066 /* build code tree */
2067 for(i = 0; i < L; ++i) {
2068 bl_count[(w = clens[i])]++;
2069 if(maxlen < w) maxlen = w;
2070 ctree[i] = 0;
2071 }
2072 bl_count[0] = 0;
2073 for(i = 1; i <= maxlen; ++i) bl_count[i+16] = (ccode = (ccode + bl_count[i-1])<<1);
2074 for(i = 0; i < L; ++i) {
2075 ccode = clens[i];
2076 if(ccode != 0) ctree[i] = bl_count[ccode+16]++;
2077 }
2078
2079 /* cmap[maxlen + 4 bits] = (off&15) + (lit<<4) reverse mapping */
2080 var cleni = 0;
2081 for(i = 0; i < L; ++i) {
2082 cleni = clens[i];
2083 if(cleni != 0) {
2084 ccode = bit_swap_n(ctree[i], maxlen)>>(maxlen-cleni);
2085 for(j = (1<<(maxlen + 4 - cleni)) - 1; j>=0; --j)
2086 cmap[ccode|(j<<cleni)] = (cleni&15) | (i<<4);
2087 }
2088 }
2089 return maxlen;
2090}
2091
2092var fix_lmap = use_typed_arrays ? new Uint16Array(512) : zero_fill_array(512);
2093var fix_dmap = use_typed_arrays ? new Uint16Array(32) : zero_fill_array(32);
2094if(!use_typed_arrays) {
2095 for(var i = 0; i < 512; ++i) fix_lmap[i] = 0;
2096 for(i = 0; i < 32; ++i) fix_dmap[i] = 0;
2097}
2098(function() {
2099 var dlens = [];
2100 var i = 0;
2101 for(;i<32; i++) dlens.push(5);
2102 build_tree(dlens, fix_dmap, 32);
2103
2104 var clens = [];
2105 i = 0;
2106 for(; i<=143; i++) clens.push(8);
2107 for(; i<=255; i++) clens.push(9);
2108 for(; i<=279; i++) clens.push(7);
2109 for(; i<=287; i++) clens.push(8);
2110 build_tree(clens, fix_lmap, 288);
2111})();
2112
2113var dyn_lmap = use_typed_arrays ? new Uint16Array(32768) : zero_fill_array(32768);
2114var dyn_dmap = use_typed_arrays ? new Uint16Array(32768) : zero_fill_array(32768);
2115var dyn_cmap = use_typed_arrays ? new Uint16Array(128) : zero_fill_array(128);
2116var dyn_len_1 = 1, dyn_len_2 = 1;
2117
2118/* 5.5.3 Expanding Huffman Codes */
2119function dyn(data, boff) {
2120 /* nomenclature from RFC1951 refers to bit values; these are offset by the implicit constant */
2121 var _HLIT = read_bits_5(data, boff) + 257; boff += 5;
2122 var _HDIST = read_bits_5(data, boff) + 1; boff += 5;
2123 var _HCLEN = read_bits_4(data, boff) + 4; boff += 4;
2124 var w = 0;
2125
2126 /* grab and store code lengths */
2127 var clens = use_typed_arrays ? new Uint8Array(19) : zero_fill_array(19);
2128 var ctree = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
2129 var maxlen = 1;
2130 var bl_count = use_typed_arrays ? new Uint8Array(8) : zero_fill_array(8);
2131 var next_code = use_typed_arrays ? new Uint8Array(8) : zero_fill_array(8);
2132 var L = clens.length; /* 19 */
2133 for(var i = 0; i < _HCLEN; ++i) {
2134 clens[CLEN_ORDER[i]] = w = read_bits_3(data, boff);
2135 if(maxlen < w) maxlen = w;
2136 bl_count[w]++;
2137 boff += 3;
2138 }
2139
2140 /* build code tree */
2141 var ccode = 0;
2142 bl_count[0] = 0;
2143 for(i = 1; i <= maxlen; ++i) next_code[i] = ccode = (ccode + bl_count[i-1])<<1;
2144 for(i = 0; i < L; ++i) if((ccode = clens[i]) != 0) ctree[i] = next_code[ccode]++;
2145 /* cmap[7 bits from stream] = (off&7) + (lit<<3) */
2146 var cleni = 0;
2147 for(i = 0; i < L; ++i) {
2148 cleni = clens[i];
2149 if(cleni != 0) {
2150 ccode = bitswap8[ctree[i]]>>(8-cleni);
2151 for(var j = (1<<(7-cleni))-1; j>=0; --j) dyn_cmap[ccode|(j<<cleni)] = (cleni&7) | (i<<3);
2152 }
2153 }
2154
2155 /* read literal and dist codes at once */
2156 var hcodes = [];
2157 maxlen = 1;
2158 for(; hcodes.length < _HLIT + _HDIST;) {
2159 ccode = dyn_cmap[read_bits_7(data, boff)];
2160 boff += ccode & 7;
2161 switch((ccode >>>= 3)) {
2162 case 16:
2163 w = 3 + read_bits_2(data, boff); boff += 2;
2164 ccode = hcodes[hcodes.length - 1];
2165 while(w-- > 0) hcodes.push(ccode);
2166 break;
2167 case 17:
2168 w = 3 + read_bits_3(data, boff); boff += 3;
2169 while(w-- > 0) hcodes.push(0);
2170 break;
2171 case 18:
2172 w = 11 + read_bits_7(data, boff); boff += 7;
2173 while(w -- > 0) hcodes.push(0);
2174 break;
2175 default:
2176 hcodes.push(ccode);
2177 if(maxlen < ccode) maxlen = ccode;
2178 break;
2179 }
2180 }
2181
2182 /* build literal / length trees */
2183 var h1 = hcodes.slice(0, _HLIT), h2 = hcodes.slice(_HLIT);
2184 for(i = _HLIT; i < 286; ++i) h1[i] = 0;
2185 for(i = _HDIST; i < 30; ++i) h2[i] = 0;
2186 dyn_len_1 = build_tree(h1, dyn_lmap, 286);
2187 dyn_len_2 = build_tree(h2, dyn_dmap, 30);
2188 return boff;
2189}
2190
2191/* return [ data, bytesRead ] */
2192function inflate(data, usz) {
2193 /* shortcircuit for empty buffer [0x03, 0x00] */
2194 if(data[0] == 3 && !(data[1] & 0x3)) { return [new_raw_buf(usz), 2]; }
2195
2196 /* bit offset */
2197 var boff = 0;
2198
2199 /* header includes final bit and type bits */
2200 var header = 0;
2201
2202 var outbuf = new_unsafe_buf(usz ? usz : (1<<18));
2203 var woff = 0;
2204 var OL = outbuf.length>>>0;
2205 var max_len_1 = 0, max_len_2 = 0;
2206
2207 while((header&1) == 0) {
2208 header = read_bits_3(data, boff); boff += 3;
2209 if((header >>> 1) == 0) {
2210 /* Stored block */
2211 if(boff & 7) boff += 8 - (boff&7);
2212 /* 2 bytes sz, 2 bytes bit inverse */
2213 var sz = data[boff>>>3] | data[(boff>>>3)+1]<<8;
2214 boff += 32;
2215 /* push sz bytes */
2216 if(!usz && OL < woff + sz) { outbuf = realloc(outbuf, woff + sz); OL = outbuf.length; }
2217 if(typeof data.copy === 'function') {
2218 // $FlowIgnore
2219 data.copy(outbuf, woff, boff>>>3, (boff>>>3)+sz);
2220 woff += sz; boff += 8*sz;
2221 } else while(sz-- > 0) { outbuf[woff++] = data[boff>>>3]; boff += 8; }
2222 continue;
2223 } else if((header >>> 1) == 1) {
2224 /* Fixed Huffman */
2225 max_len_1 = 9; max_len_2 = 5;
2226 } else {
2227 /* Dynamic Huffman */
2228 boff = dyn(data, boff);
2229 max_len_1 = dyn_len_1; max_len_2 = dyn_len_2;
2230 }
2231 if(!usz && (OL < woff + 32767)) { outbuf = realloc(outbuf, woff + 32767); OL = outbuf.length; }
2232 for(;;) { // while(true) is apparently out of vogue in modern JS circles
2233 /* ingest code and move read head */
2234 var bits = read_bits_n(data, boff, max_len_1);
2235 var code = (header>>>1) == 1 ? fix_lmap[bits] : dyn_lmap[bits];
2236 boff += code & 15; code >>>= 4;
2237 /* 0-255 are literals, 256 is end of block token, 257+ are copy tokens */
2238 if(((code>>>8)&0xFF) === 0) outbuf[woff++] = code;
2239 else if(code == 256) break;
2240 else {
2241 code -= 257;
2242 var len_eb = (code < 8) ? 0 : ((code-4)>>2); if(len_eb > 5) len_eb = 0;
2243 var tgt = woff + LEN_LN[code];
2244 /* length extra bits */
2245 if(len_eb > 0) {
2246 tgt += read_bits_n(data, boff, len_eb);
2247 boff += len_eb;
2248 }
2249
2250 /* dist code */
2251 bits = read_bits_n(data, boff, max_len_2);
2252 code = (header>>>1) == 1 ? fix_dmap[bits] : dyn_dmap[bits];
2253 boff += code & 15; code >>>= 4;
2254 var dst_eb = (code < 4 ? 0 : (code-2)>>1);
2255 var dst = DST_LN[code];
2256 /* dist extra bits */
2257 if(dst_eb > 0) {
2258 dst += read_bits_n(data, boff, dst_eb);
2259 boff += dst_eb;
2260 }
2261
2262 /* in the common case, manual byte copy is faster than TA set / Buffer copy */
2263 if(!usz && OL < tgt) { outbuf = realloc(outbuf, tgt); OL = outbuf.length; }
2264 while(woff < tgt) { outbuf[woff] = outbuf[woff - dst]; ++woff; }
2265 }
2266 }
2267 }
2268 return [usz ? outbuf : outbuf.slice(0, woff), (boff+7)>>>3];
2269}
2270
2271function _inflate(payload, usz) {
2272 var data = payload.slice(payload.l||0);
2273 var out = inflate(data, usz);
2274 payload.l += out[1];
2275 return out[0];
2276}
2277
2278function warn_or_throw(wrn, msg) {
2279 if(wrn) { if(typeof console !== 'undefined') console.error(msg); }
2280 else throw new Error(msg);
2281}
2282
2283function parse_zip(file, options) {
2284 var blob = file;
2285 prep_blob(blob, 0);
2286
2287 var FileIndex = [], FullPaths = [];
2288 var o = {
2289 FileIndex: FileIndex,
2290 FullPaths: FullPaths
2291 };
2292 init_cfb(o, { root: options.root });
2293
2294 /* find end of central directory, start just after signature */
2295 var i = blob.length - 4;
2296 while((blob[i] != 0x50 || blob[i+1] != 0x4b || blob[i+2] != 0x05 || blob[i+3] != 0x06) && i >= 0) --i;
2297 blob.l = i + 4;
2298
2299 /* parse end of central directory */
2300 blob.l += 4;
2301 var fcnt = blob.read_shift(2);
2302 blob.l += 6;
2303 var start_cd = blob.read_shift(4);
2304
2305 /* parse central directory */
2306 blob.l = start_cd;
2307
2308 for(i = 0; i < fcnt; ++i) {
2309 /* trust local file header instead of CD entry */
2310 blob.l += 20;
2311 var csz = blob.read_shift(4);
2312 var usz = blob.read_shift(4);
2313 var namelen = blob.read_shift(2);
2314 var efsz = blob.read_shift(2);
2315 var fcsz = blob.read_shift(2);
2316 blob.l += 8;
2317 var offset = blob.read_shift(4);
2318 var EF = parse_extra_field(blob.slice(blob.l+namelen, blob.l+namelen+efsz));
2319 blob.l += namelen + efsz + fcsz;
2320
2321 var L = blob.l;
2322 blob.l = offset + 4;
2323 parse_local_file(blob, csz, usz, o, EF);
2324 blob.l = L;
2325 }
2326
2327 return o;
2328}
2329
2330
2331/* head starts just after local file header signature */
2332function parse_local_file(blob, csz, usz, o, EF) {
2333 /* [local file header] */
2334 blob.l += 2;
2335 var flags = blob.read_shift(2);
2336 var meth = blob.read_shift(2);
2337 var date = parse_dos_date(blob);
2338
2339 if(flags & 0x2041) throw new Error("Unsupported ZIP encryption");
2340 var crc32 = blob.read_shift(4);
2341 var _csz = blob.read_shift(4);
2342 var _usz = blob.read_shift(4);
2343
2344 var namelen = blob.read_shift(2);
2345 var efsz = blob.read_shift(2);
2346
2347 // TODO: flags & (1<<11) // UTF8
2348 var name = ""; for(var i = 0; i < namelen; ++i) name += String.fromCharCode(blob[blob.l++]);
2349 if(efsz) {
2350 var ef = parse_extra_field(blob.slice(blob.l, blob.l + efsz));
2351 if((ef[0x5455]||{}).mt) date = ef[0x5455].mt;
2352 if(((EF||{})[0x5455]||{}).mt) date = EF[0x5455].mt;
2353 }
2354 blob.l += efsz;
2355
2356 /* [encryption header] */
2357
2358 /* [file data] */
2359 var data = blob.slice(blob.l, blob.l + _csz);
2360 switch(meth) {
2361 case 8: data = _inflateRawSync(blob, _usz); break;
2362 case 0: break;
2363 default: throw new Error("Unsupported ZIP Compression method " + meth);
2364 }
2365
2366 /* [data descriptor] */
2367 var wrn = false;
2368 if(flags & 8) {
2369 crc32 = blob.read_shift(4);
2370 if(crc32 == 0x08074b50) { crc32 = blob.read_shift(4); wrn = true; }
2371 _csz = blob.read_shift(4);
2372 _usz = blob.read_shift(4);
2373 }
2374
2375 if(_csz != csz) warn_or_throw(wrn, "Bad compressed size: " + csz + " != " + _csz);
2376 if(_usz != usz) warn_or_throw(wrn, "Bad uncompressed size: " + usz + " != " + _usz);
2377 var _crc32 = CRC32.buf(data, 0);
2378 if((crc32>>0) != (_crc32>>0)) warn_or_throw(wrn, "Bad CRC32 checksum: " + crc32 + " != " + _crc32);
2379 cfb_add(o, name, data, {unsafe: true, mt: date});
2380}
2381function write_zip(cfb, options) {
2382 var _opts = options || {};
2383 var out = [], cdirs = [];
2384 var o = new_buf(1);
2385 var method = (_opts.compression ? 8 : 0), flags = 0;
2386 var desc = false;
2387 if(desc) flags |= 8;
2388 var i = 0, j = 0;
2389
2390 var start_cd = 0, fcnt = 0;
2391 var root = cfb.FullPaths[0], fp = root, fi = cfb.FileIndex[0];
2392 var crcs = [];
2393 var sz_cd = 0;
2394
2395 for(i = 1; i < cfb.FullPaths.length; ++i) {
2396 fp = cfb.FullPaths[i].slice(root.length); fi = cfb.FileIndex[i];
2397 if(!fi.size || !fi.content || fp == "\u0001Sh33tJ5") continue;
2398 var start = start_cd;
2399
2400 /* TODO: CP437 filename */
2401 var namebuf = new_buf(fp.length);
2402 for(j = 0; j < fp.length; ++j) namebuf.write_shift(1, fp.charCodeAt(j) & 0x7F);
2403 namebuf = namebuf.slice(0, namebuf.l);
2404 crcs[fcnt] = CRC32.buf(fi.content, 0);
2405
2406 var outbuf = fi.content;
2407 if(method == 8) outbuf = _deflateRawSync(outbuf);
2408
2409 /* local file header */
2410 o = new_buf(30);
2411 o.write_shift(4, 0x04034b50);
2412 o.write_shift(2, 20);
2413 o.write_shift(2, flags);
2414 o.write_shift(2, method);
2415 /* TODO: last mod file time/date */
2416 if(fi.mt) write_dos_date(o, fi.mt);
2417 else o.write_shift(4, 0);
2418 o.write_shift(-4, (flags & 8) ? 0 : crcs[fcnt]);
2419 o.write_shift(4, (flags & 8) ? 0 : outbuf.length);
2420 o.write_shift(4, (flags & 8) ? 0 : fi.content.length);
2421 o.write_shift(2, namebuf.length);
2422 o.write_shift(2, 0);
2423
2424 start_cd += o.length;
2425 out.push(o);
2426 start_cd += namebuf.length;
2427 out.push(namebuf);
2428
2429 /* TODO: encryption header ? */
2430 start_cd += outbuf.length;
2431 out.push(outbuf);
2432
2433 /* data descriptor */
2434 if(flags & 8) {
2435 o = new_buf(12);
2436 o.write_shift(-4, crcs[fcnt]);
2437 o.write_shift(4, outbuf.length);
2438 o.write_shift(4, fi.content.length);
2439 start_cd += o.l;
2440 out.push(o);
2441 }
2442
2443 /* central directory */
2444 o = new_buf(46);
2445 o.write_shift(4, 0x02014b50);
2446 o.write_shift(2, 0);
2447 o.write_shift(2, 20);
2448 o.write_shift(2, flags);
2449 o.write_shift(2, method);
2450 o.write_shift(4, 0); /* TODO: last mod file time/date */
2451 o.write_shift(-4, crcs[fcnt]);
2452
2453 o.write_shift(4, outbuf.length);
2454 o.write_shift(4, fi.content.length);
2455 o.write_shift(2, namebuf.length);
2456 o.write_shift(2, 0);
2457 o.write_shift(2, 0);
2458 o.write_shift(2, 0);
2459 o.write_shift(2, 0);
2460 o.write_shift(4, 0);
2461 o.write_shift(4, start);
2462
2463 sz_cd += o.l;
2464 cdirs.push(o);
2465 sz_cd += namebuf.length;
2466 cdirs.push(namebuf);
2467 ++fcnt;
2468 }
2469
2470 /* end of central directory */
2471 o = new_buf(22);
2472 o.write_shift(4, 0x06054b50);
2473 o.write_shift(2, 0);
2474 o.write_shift(2, 0);
2475 o.write_shift(2, fcnt);
2476 o.write_shift(2, fcnt);
2477 o.write_shift(4, sz_cd);
2478 o.write_shift(4, start_cd);
2479 o.write_shift(2, 0);
2480
2481 return bconcat(([bconcat((out)), bconcat(cdirs), o]));
2482}
2483function cfb_new(opts) {
2484 var o = ({});
2485 init_cfb(o, opts);
2486 return o;
2487}
2488
2489function cfb_add(cfb, name, content, opts) {
2490 var unsafe = opts && opts.unsafe;
2491 if(!unsafe) init_cfb(cfb);
2492 var file = !unsafe && CFB.find(cfb, name);
2493 if(!file) {
2494 var fpath = cfb.FullPaths[0];
2495 if(name.slice(0, fpath.length) == fpath) fpath = name;
2496 else {
2497 if(fpath.slice(-1) != "/") fpath += "/";
2498 fpath = (fpath + name).replace("//","/");
2499 }
2500 file = ({name: filename(name), type: 2});
2501 cfb.FileIndex.push(file);
2502 cfb.FullPaths.push(fpath);
2503 if(!unsafe) CFB.utils.cfb_gc(cfb);
2504 }
2505file.content = (content);
2506 file.size = content ? content.length : 0;
2507 if(opts) {
2508 if(opts.CLSID) file.clsid = opts.CLSID;
2509 if(opts.mt) file.mt = opts.mt;
2510 if(opts.ct) file.ct = opts.ct;
2511 }
2512 return file;
2513}
2514
2515function cfb_del(cfb, name) {
2516 init_cfb(cfb);
2517 var file = CFB.find(cfb, name);
2518 if(file) for(var j = 0; j < cfb.FileIndex.length; ++j) if(cfb.FileIndex[j] == file) {
2519 cfb.FileIndex.splice(j, 1);
2520 cfb.FullPaths.splice(j, 1);
2521 return true;
2522 }
2523 return false;
2524}
2525
2526function cfb_mov(cfb, old_name, new_name) {
2527 init_cfb(cfb);
2528 var file = CFB.find(cfb, old_name);
2529 if(file) for(var j = 0; j < cfb.FileIndex.length; ++j) if(cfb.FileIndex[j] == file) {
2530 cfb.FileIndex[j].name = filename(new_name);
2531 cfb.FullPaths[j] = new_name;
2532 return true;
2533 }
2534 return false;
2535}
2536
2537function cfb_gc(cfb) { rebuild_cfb(cfb, true); }
2538
2539exports.find = find;
2540exports.read = read;
2541exports.parse = parse;
2542exports.write = write;
2543exports.writeFile = write_file;
2544exports.utils = {
2545 cfb_new: cfb_new,
2546 cfb_add: cfb_add,
2547 cfb_del: cfb_del,
2548 cfb_mov: cfb_mov,
2549 cfb_gc: cfb_gc,
2550 ReadShift: ReadShift,
2551 CheckField: CheckField,
2552 prep_blob: prep_blob,
2553 bconcat: bconcat,
2554 use_zlib: use_zlib,
2555 _deflateRaw: _deflate,
2556 _inflateRaw: _inflate,
2557 consts: consts
2558};
2559
2560return exports;
2561})();
2562
2563if(typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO_NOT_EXPORT_CFB === 'undefined') { module.exports = CFB; }
2564var _fs;
2565if(typeof require !== 'undefined') try { _fs = require('fs'); } catch(e) {}
2566
2567/* normalize data for blob ctor */
2568function blobify(data) {
2569 if(typeof data === "string") return s2ab(data);
2570 if(Array.isArray(data)) return a2u(data);
2571 return data;
2572}
2573/* write or download file */
2574function write_dl(fname, payload, enc) {
2575 /*global IE_SaveFile, Blob, navigator, saveAs, document, File, chrome */
2576 if(typeof _fs !== 'undefined' && _fs.writeFileSync) return enc ? _fs.writeFileSync(fname, payload, enc) : _fs.writeFileSync(fname, payload);
2577 var data = (enc == "utf8") ? utf8write(payload) : payload;
2578if(typeof IE_SaveFile !== 'undefined') return IE_SaveFile(data, fname);
2579 if(typeof Blob !== 'undefined') {
2580 var blob = new Blob([blobify(data)], {type:"application/octet-stream"});
2581if(typeof navigator !== 'undefined' && navigator.msSaveBlob) return navigator.msSaveBlob(blob, fname);
2582if(typeof saveAs !== 'undefined') return saveAs(blob, fname);
2583 if(typeof URL !== 'undefined' && typeof document !== 'undefined' && document.createElement && URL.createObjectURL) {
2584 var url = URL.createObjectURL(blob);
2585if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
2586 if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
2587 return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
2588 }
2589 var a = document.createElement("a");
2590 if(a.download != null) {
2591a.download = fname; a.href = url; document.body.appendChild(a); a.click();
2592document.body.removeChild(a);
2593 if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
2594 return url;
2595 }
2596 }
2597 }
2598 // $FlowIgnore
2599 if(typeof $ !== 'undefined' && typeof File !== 'undefined' && typeof Folder !== 'undefined') try { // extendscript
2600 // $FlowIgnore
2601 var out = File(fname); out.open("w"); out.encoding = "binary";
2602 if(Array.isArray(payload)) payload = a2s(payload);
2603 out.write(payload); out.close(); return payload;
2604 } catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; }
2605 throw new Error("cannot save file " + fname);
2606}
2607
2608/* read binary data from file */
2609function read_binary(path) {
2610 if(typeof _fs !== 'undefined') return _fs.readFileSync(path);
2611 // $FlowIgnore
2612 if(typeof $ !== 'undefined' && typeof File !== 'undefined' && typeof Folder !== 'undefined') try { // extendscript
2613 // $FlowIgnore
2614 var infile = File(path); infile.open("r"); infile.encoding = "binary";
2615 var data = infile.read(); infile.close();
2616 return data;
2617 } catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; }
2618 throw new Error("Cannot access file " + path);
2619}
2620function keys(o) {
2621 var ks = Object.keys(o), o2 = [];
2622 for(var i = 0; i < ks.length; ++i) if(Object.prototype.hasOwnProperty.call(o, ks[i])) o2.push(ks[i]);
2623 return o2;
2624}
2625
2626function evert_key(obj, key) {
2627 var o = ([]), K = keys(obj);
2628 for(var i = 0; i !== K.length; ++i) if(o[obj[K[i]][key]] == null) o[obj[K[i]][key]] = K[i];
2629 return o;
2630}
2631
2632function evert(obj) {
2633 var o = ([]), K = keys(obj);
2634 for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = K[i];
2635 return o;
2636}
2637
2638function evert_num(obj) {
2639 var o = ([]), K = keys(obj);
2640 for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = parseInt(K[i],10);
2641 return o;
2642}
2643
2644function evert_arr(obj) {
2645 var o = ([]), K = keys(obj);
2646 for(var i = 0; i !== K.length; ++i) {
2647 if(o[obj[K[i]]] == null) o[obj[K[i]]] = [];
2648 o[obj[K[i]]].push(K[i]);
2649 }
2650 return o;
2651}
2652
2653var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
2654var dnthresh = basedate.getTime() + (new Date().getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
2655function datenum(v, date1904) {
2656 var epoch = v.getTime();
2657 if(date1904) epoch -= 1462*24*60*60*1000;
2658 return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
2659}
2660function numdate(v) {
2661 var out = new Date();
2662 out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh);
2663 return out;
2664}
2665
2666/* ISO 8601 Duration */
2667function parse_isodur(s) {
2668 var sec = 0, mt = 0, time = false;
2669 var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
2670 if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
2671 for(var i = 1; i != m.length; ++i) {
2672 if(!m[i]) continue;
2673 mt = 1;
2674 if(i > 3) time = true;
2675 switch(m[i].slice(m[i].length-1)) {
2676 case 'Y':
2677 throw new Error("Unsupported ISO Duration Field: " + m[i].slice(m[i].length-1));
2678 case 'D': mt *= 24;
2679 /* falls through */
2680 case 'H': mt *= 60;
2681 /* falls through */
2682 case 'M':
2683 if(!time) throw new Error("Unsupported ISO Duration Field: M");
2684 else mt *= 60;
2685 /* falls through */
2686 case 'S': break;
2687 }
2688 sec += mt * parseInt(m[i], 10);
2689 }
2690 return sec;
2691}
2692
2693var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
2694if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
2695var good_pd = good_pd_date.getFullYear() == 2017;
2696/* parses a date as a local date */
2697function parseDate(str, fixdate) {
2698 var d = new Date(str);
2699 if(good_pd) {
2700if(fixdate > 0) d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
2701 else if(fixdate < 0) d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000);
2702 return d;
2703 }
2704 if(str instanceof Date) return str;
2705 if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
2706 var s = d.getFullYear();
2707 if(str.indexOf("" + s) > -1) return d;
2708 d.setFullYear(d.getFullYear() + 100); return d;
2709 }
2710 var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
2711 var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
2712 if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000);
2713 return out;
2714}
2715
2716function cc2str(arr) {
2717 var o = "";
2718 for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
2719 return o;
2720}
2721
2722function dup(o) {
2723 if(typeof JSON != 'undefined' && !Array.isArray(o)) return JSON.parse(JSON.stringify(o));
2724 if(typeof o != 'object' || o == null) return o;
2725 if(o instanceof Date) return new Date(o.getTime());
2726 var out = {};
2727 for(var k in o) if(Object.prototype.hasOwnProperty.call(o, k)) out[k] = dup(o[k]);
2728 return out;
2729}
2730
2731function fill(c,l) { var o = ""; while(o.length < l) o+=c; return o; }
2732
2733/* TODO: stress test */
2734function fuzzynum(s) {
2735 var v = Number(s);
2736 if(!isNaN(v)) return v;
2737 var wt = 1;
2738 var ss = s.replace(/([\d]),([\d])/g,"$1$2").replace(/[$]/g,"").replace(/[%]/g, function() { wt *= 100; return "";});
2739 if(!isNaN(v = Number(ss))) return v / wt;
2740 ss = ss.replace(/[(](.*)[)]/,function($$, $1) { wt = -wt; return $1;});
2741 if(!isNaN(v = Number(ss))) return v / wt;
2742 return v;
2743}
2744function fuzzydate(s) {
2745 var o = new Date(s), n = new Date(NaN);
2746 var y = o.getYear(), m = o.getMonth(), d = o.getDate();
2747 if(isNaN(d)) return n;
2748 if(y < 0 || y > 8099) return n;
2749 if((m > 0 || d > 1) && y != 101) return o;
2750 if(s.toLowerCase().match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) return o;
2751 if(s.match(/[^-0-9:,\/\\]/)) return n;
2752 return o;
2753}
2754
2755var safe_split_regex = "abacaba".split(/(:?b)/i).length == 5;
2756function split_regex(str, re, def) {
2757 if(safe_split_regex || typeof re == "string") return str.split(re);
2758 var p = str.split(re), o = [p[0]];
2759 for(var i = 1; i < p.length; ++i) { o.push(def); o.push(p[i]); }
2760 return o;
2761}
2762function getdatastr(data) {
2763 if(!data) return null;
2764 if(data.data) return debom(data.data);
2765 if(data.asNodeBuffer && has_buf) return debom(data.asNodeBuffer().toString('binary'));
2766 if(data.asBinary) return debom(data.asBinary());
2767 if(data._data && data._data.getContent) return debom(cc2str(Array.prototype.slice.call(data._data.getContent(),0)));
2768 if(data.content && data.type) return debom(cc2str(data.content));
2769 return null;
2770}
2771
2772function getdatabin(data) {
2773 if(!data) return null;
2774 if(data.data) return char_codes(data.data);
2775 if(data.asNodeBuffer && has_buf) return data.asNodeBuffer();
2776 if(data._data && data._data.getContent) {
2777 var o = data._data.getContent();
2778 if(typeof o == "string") return char_codes(o);
2779 return Array.prototype.slice.call(o);
2780 }
2781 if(data.content && data.type) return data.content;
2782 return null;
2783}
2784
2785function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getdatabin(data) : getdatastr(data); }
2786
2787/* Part 2 Section 10.1.2 "Mapping Content Types" Names are case-insensitive */
2788/* OASIS does not comment on filename case sensitivity */
2789function safegetzipfile(zip, file) {
2790 var k = zip.FullPaths || keys(zip.files);
2791 var f = file.toLowerCase(), g = f.replace(/\\/g,'\/');
2792 for(var i=0; i<k.length; ++i) {
2793 var n = k[i].replace(/^Root Entry[\/]/,"").toLowerCase();
2794 if(f == n || g == n) return zip.FileIndex[i];
2795 }
2796 return null;
2797}
2798
2799function getzipfile(zip, file) {
2800 var o = safegetzipfile(zip, file);
2801 if(o == null) throw new Error("Cannot find file " + file + " in zip");
2802 return o;
2803}
2804
2805function getzipdata(zip, file, safe) {
2806 if(!safe) return getdata(getzipfile(zip, file));
2807 if(!file) return null;
2808 try { return getzipdata(zip, file); } catch(e) { return null; }
2809}
2810
2811function getzipstr(zip, file, safe) {
2812 if(!safe) return getdatastr(getzipfile(zip, file));
2813 if(!file) return null;
2814 try { return getzipstr(zip, file); } catch(e) { return null; }
2815}
2816
2817function zipentries(zip) {
2818 var k = zip.FullPaths || keys(zip.files), o = [];
2819 for(var i = 0; i < k.length; ++i) if(k[i].slice(-1) != '/') o.push(k[i].replace(/^Root Entry[\/]/, ""));
2820 return o.sort();
2821}
2822
2823function zip_add_file(zip, path, content) {
2824 if(zip.FullPaths) CFB.utils.cfb_add(zip, path, typeof content == "string" ? (has_buf ? Buffer_from(content) : s2a(utf8write(content))) : content);
2825 else zip.file(path, content);
2826}
2827
2828
2829function zip_new() {
2830 return CFB.utils.cfb_new();
2831}
2832
2833function zip_read(d, o) {
2834 var zip;
2835 switch(o.type) {
2836 case "base64": zip = CFB.read(d, { type: "base64" }); break;
2837 case "binary": zip = CFB.read(d, { type: "binary" }); break;
2838 case "buffer": case "array": zip = CFB.read(d, { type: "buffer" }); break;
2839 default: throw new Error("Unrecognized type " + o.type);
2840 }
2841 return zip;
2842}
2843
2844function resolve_path(path, base) {
2845 if(path.charAt(0) == "/") return path.slice(1);
2846 var result = base.split('/');
2847 if(base.slice(-1) != "/") result.pop(); // folder path
2848 var target = path.split('/');
2849 while (target.length !== 0) {
2850 var step = target.shift();
2851 if (step === '..') result.pop();
2852 else if (step !== '.') result.push(step);
2853 }
2854 return result.join('/');
2855}
2856var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
2857var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
2858var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s?[\/\?]?>/g;
2859
2860if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
2861var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
2862function parsexmltag(tag, skip_root, skip_LC) {
2863 var z = ({});
2864 var eq = 0, c = 0;
2865 for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
2866 if(!skip_root) z[0] = tag.slice(0, eq);
2867 if(eq === tag.length) return z;
2868 var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1;
2869 if(m) for(i = 0; i != m.length; ++i) {
2870 cc = m[i];
2871 for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
2872 q = cc.slice(0,c).trim();
2873 while(cc.charCodeAt(c+1) == 32) ++c;
2874 quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0;
2875 v = cc.slice(c+1+quot, cc.length-quot);
2876 for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
2877 if(j===q.length) {
2878 if(q.indexOf("_") > 0) q = q.slice(0, q.indexOf("_")); // from ods
2879 z[q] = v;
2880 if(!skip_LC) z[q.toLowerCase()] = v;
2881 }
2882 else {
2883 var k = (j===5 && q.slice(0,5)==="xmlns"?"xmlns":"")+q.slice(j+1);
2884 if(z[k] && q.slice(j-3,j) == "ext") continue; // from ods
2885 z[k] = v;
2886 if(!skip_LC) z[k.toLowerCase()] = v;
2887 }
2888 }
2889 return z;
2890}
2891function strip_ns(x) { return x.replace(nsregex2, "<$1"); }
2892
2893var encodings = {
2894 '&quot;': '"',
2895 '&apos;': "'",
2896 '&gt;': '>',
2897 '&lt;': '<',
2898 '&amp;': '&'
2899};
2900var rencoding = evert(encodings);
2901//var rencstr = "&<>'\"".split("");
2902
2903// TODO: CP remap (need to read file version to determine OS)
2904var unescapexml = (function() {
2905 /* 22.4.2.4 bstr (Basic String) */
2906 var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig;
2907 return function unescapexml(text) {
2908 var s = text + '', i = s.indexOf("<![CDATA[");
2909 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));});
2910 var j = s.indexOf("]]>");
2911 return unescapexml(s.slice(0, i)) + s.slice(i+9,j) + unescapexml(s.slice(j+3));
2912 };
2913})();
2914
2915var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
2916function escapexml(text){
2917 var s = text + '';
2918 return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";});
2919}
2920function escapexmltag(text){ return escapexml(text).replace(/ /g,"_x0020_"); }
2921
2922var htmlcharegex = /[\u0000-\u001f]/g;
2923function escapehtml(text){
2924 var s = text + '';
2925 return s.replace(decregex, function(y) { return rencoding[y]; }).replace(/\n/g, "<br/>").replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; });
2926}
2927
2928function escapexlml(text){
2929 var s = text + '';
2930 return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; });
2931}
2932
2933/* TODO: handle codepages */
2934var xlml_fixstr = (function() {
2935 var entregex = /&#(\d+);/g;
2936 function entrepl($$,$1) { return String.fromCharCode(parseInt($1,10)); }
2937 return function xlml_fixstr(str) { return str.replace(entregex,entrepl); };
2938})();
2939var xlml_unfixstr = (function() {
2940 return function xlml_unfixstr(str) { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); };
2941})();
2942
2943function parsexmlbool(value) {
2944 switch(value) {
2945 case 1: case true: case '1': case 'true': case 'TRUE': return true;
2946 /* case '0': case 'false': case 'FALSE':*/
2947 default: return false;
2948 }
2949}
2950
2951var utf8read = function utf8reada(orig) {
2952 var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
2953 while (i < orig.length) {
2954 c = orig.charCodeAt(i++);
2955 if (c < 128) { out += String.fromCharCode(c); continue; }
2956 d = orig.charCodeAt(i++);
2957 if (c>191 && c<224) { f = ((c & 31) << 6); f |= (d & 63); out += String.fromCharCode(f); continue; }
2958 e = orig.charCodeAt(i++);
2959 if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; }
2960 f = orig.charCodeAt(i++);
2961 w = (((c & 7) << 18) | ((d & 63) << 12) | ((e & 63) << 6) | (f & 63))-65536;
2962 out += String.fromCharCode(0xD800 + ((w>>>10)&1023));
2963 out += String.fromCharCode(0xDC00 + (w&1023));
2964 }
2965 return out;
2966};
2967
2968var utf8write = function(orig) {
2969 var out = [], i = 0, c = 0, d = 0;
2970 while(i < orig.length) {
2971 c = orig.charCodeAt(i++);
2972 switch(true) {
2973 case c < 128: out.push(String.fromCharCode(c)); break;
2974 case c < 2048:
2975 out.push(String.fromCharCode(192 + (c >> 6)));
2976 out.push(String.fromCharCode(128 + (c & 63)));
2977 break;
2978 case c >= 55296 && c < 57344:
2979 c -= 55296; d = orig.charCodeAt(i++) - 56320 + (c<<10);
2980 out.push(String.fromCharCode(240 + ((d >>18) & 7)));
2981 out.push(String.fromCharCode(144 + ((d >>12) & 63)));
2982 out.push(String.fromCharCode(128 + ((d >> 6) & 63)));
2983 out.push(String.fromCharCode(128 + (d & 63)));
2984 break;
2985 default:
2986 out.push(String.fromCharCode(224 + (c >> 12)));
2987 out.push(String.fromCharCode(128 + ((c >> 6) & 63)));
2988 out.push(String.fromCharCode(128 + (c & 63)));
2989 }
2990 }
2991 return out.join("");
2992};
2993
2994if(has_buf) {
2995 var utf8readb = function utf8readb(data) {
2996 var out = Buffer.alloc(2*data.length), w, i, j = 1, k = 0, ww=0, c;
2997 for(i = 0; i < data.length; i+=j) {
2998 j = 1;
2999 if((c=data.charCodeAt(i)) < 128) w = c;
3000 else if(c < 224) { w = (c&31)*64+(data.charCodeAt(i+1)&63); j=2; }
3001 else if(c < 240) { w=(c&15)*4096+(data.charCodeAt(i+1)&63)*64+(data.charCodeAt(i+2)&63); j=3; }
3002 else { j = 4;
3003 w = (c & 7)*262144+(data.charCodeAt(i+1)&63)*4096+(data.charCodeAt(i+2)&63)*64+(data.charCodeAt(i+3)&63);
3004 w -= 65536; ww = 0xD800 + ((w>>>10)&1023); w = 0xDC00 + (w&1023);
3005 }
3006 if(ww !== 0) { out[k++] = ww&255; out[k++] = ww>>>8; ww = 0; }
3007 out[k++] = w%256; out[k++] = w>>>8;
3008 }
3009 return out.slice(0,k).toString('ucs2');
3010 };
3011 var corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3";
3012 if(utf8read(corpus) == utf8readb(corpus)) utf8read = utf8readb;
3013 var utf8readc = function utf8readc(data) { return Buffer_from(data, 'binary').toString('utf8'); };
3014 if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
3015
3016 utf8write = function(data) { return Buffer_from(data, 'utf8').toString("binary"); };
3017}
3018
3019// matches <foo>...</foo> extracts content
3020var matchtag = (function() {
3021 var mtcache = ({});
3022 return function matchtag(f,g) {
3023 var t = f+"|"+(g||"");
3024 if(mtcache[t]) return mtcache[t];
3025 return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([\\s\\S]*?)</(?:\\w+:)?'+f+'>',((g||""))));
3026 };
3027})();
3028
3029var htmldecode = (function() {
3030 var entities = [
3031 ['nbsp', ' '], ['middot', '·'],
3032 ['quot', '"'], ['apos', "'"], ['gt', '>'], ['lt', '<'], ['amp', '&']
3033 ].map(function(x) { return [new RegExp('&' + x[0] + ';', "ig"), x[1]]; });
3034 return function htmldecode(str) {
3035 var o = str
3036 // Remove new lines and spaces from start of content
3037 .replace(/^[\t\n\r ]+/, "")
3038 // Remove new lines and spaces from end of content
3039 .replace(/[\t\n\r ]+$/,"")
3040 // Added line which removes any white space characters after and before html tags
3041 .replace(/>\s+/g,">").replace(/\s+</g,"<")
3042 // Replace remaining new lines and spaces with space
3043 .replace(/[\t\n\r ]+/g, " ")
3044 // Replace <br> tags with new lines
3045 .replace(/<\s*[bB][rR]\s*\/?>/g,"\n")
3046 // Strip HTML elements
3047 .replace(/<[^>]*>/g,"");
3048 for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]);
3049 return o;
3050 };
3051})();
3052
3053var vtregex = (function(){ var vt_cache = {};
3054 return function vt_regex(bt) {
3055 if(vt_cache[bt] !== undefined) return vt_cache[bt];
3056 return (vt_cache[bt] = new RegExp("<(?:vt:)?" + bt + ">([\\s\\S]*?)</(?:vt:)?" + bt + ">", 'g') );
3057};})();
3058var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^>]*)>([\s\S]*)</;
3059function parseVector(data, opts) {
3060 var h = parsexmltag(data);
3061
3062 var matches = data.match(vtregex(h.baseType))||[];
3063 var res = [];
3064 if(matches.length != h.size) {
3065 if(opts.WTF) throw new Error("unexpected vector length " + matches.length + " != " + h.size);
3066 return res;
3067 }
3068 matches.forEach(function(x) {
3069 var v = x.replace(vtvregex,"").match(vtmregex);
3070 if(v) res.push({v:utf8read(v[2]), t:v[1]});
3071 });
3072 return res;
3073}
3074
3075var wtregex = /(^\s|\s$|\n)/;
3076function writetag(f,g) { return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>'; }
3077
3078function wxt_helper(h) { return keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join(""); }
3079function writextag(f,g,h) { return '<' + f + ((h != null) ? wxt_helper(h) : "") + ((g != null) ? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';}
3080
3081function write_w3cdtf(d, t) { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } return ""; }
3082
3083function write_vt(s) {
3084 switch(typeof s) {
3085 case 'string': return writextag('vt:lpwstr', escapexml(s));
3086 case 'number': return writextag((s|0)==s?'vt:i4':'vt:r8', escapexml(String(s)));
3087 case 'boolean': return writextag('vt:bool',s?'true':'false');
3088 }
3089 if(s instanceof Date) return writextag('vt:filetime', write_w3cdtf(s));
3090 throw new Error("Unable to serialize " + s);
3091}
3092
3093var XMLNS = ({
3094 'dc': 'http://purl.org/dc/elements/1.1/',
3095 'dcterms': 'http://purl.org/dc/terms/',
3096 'dcmitype': 'http://purl.org/dc/dcmitype/',
3097 'mx': 'http://schemas.microsoft.com/office/mac/excel/2008/main',
3098 'r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
3099 'sjs': 'http://schemas.openxmlformats.org/package/2006/sheetjs/core-properties',
3100 'vt': 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes',
3101 'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
3102 'xsd': 'http://www.w3.org/2001/XMLSchema'
3103});
3104
3105XMLNS.main = [
3106 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
3107 'http://purl.oclc.org/ooxml/spreadsheetml/main',
3108 'http://schemas.microsoft.com/office/excel/2006/main',
3109 'http://schemas.microsoft.com/office/excel/2006/2'
3110];
3111
3112var XLMLNS = ({
3113 'o': 'urn:schemas-microsoft-com:office:office',
3114 'x': 'urn:schemas-microsoft-com:office:excel',
3115 'ss': 'urn:schemas-microsoft-com:office:spreadsheet',
3116 'dt': 'uuid:C2F41010-65B3-11d1-A29F-00AA00C14882',
3117 'mv': 'http://macVmlSchemaUri',
3118 'v': 'urn:schemas-microsoft-com:vml',
3119 'html': 'http://www.w3.org/TR/REC-html40'
3120});
3121function read_double_le(b, idx) {
3122 var s = 1 - 2 * (b[idx + 7] >>> 7);
3123 var e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 0x0f);
3124 var m = (b[idx+6]&0x0f);
3125 for(var i = 5; i >= 0; --i) m = m * 256 + b[idx + i];
3126 if(e == 0x7ff) return m == 0 ? (s * Infinity) : NaN;
3127 if(e == 0) e = -1022;
3128 else { e -= 1023; m += Math.pow(2,52); }
3129 return s * Math.pow(2, e - 52) * m;
3130}
3131
3132function write_double_le(b, v, idx) {
3133 var bs = ((((v < 0) || (1/v == -Infinity)) ? 1 : 0) << 7), e = 0, m = 0;
3134 var av = bs ? (-v) : v;
3135 if(!isFinite(av)) { e = 0x7ff; m = isNaN(v) ? 0x6969 : 0; }
3136 else if(av == 0) e = m = 0;
3137 else {
3138 e = Math.floor(Math.log(av) / Math.LN2);
3139 m = av * Math.pow(2, 52 - e);
3140 if((e <= -1023) && (!isFinite(m) || (m < Math.pow(2,52)))) { e = -1022; }
3141 else { m -= Math.pow(2,52); e+=1023; }
3142 }
3143 for(var i = 0; i <= 5; ++i, m/=256) b[idx + i] = m & 0xff;
3144 b[idx + 6] = ((e & 0x0f) << 4) | (m & 0xf);
3145 b[idx + 7] = (e >> 4) | bs;
3146}
3147
3148var __toBuffer = function(bufs) { var x=[],w=10240; for(var i=0;i<bufs[0].length;++i) if(bufs[0][i]) for(var j=0,L=bufs[0][i].length;j<L;j+=w) x.push.apply(x, bufs[0][i].slice(j,j+w)); return x; };
3149var ___toBuffer = __toBuffer;
3150var __utf16le = function(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join("").replace(chr0,''); };
3151var ___utf16le = __utf16le;
3152var __hexlify = function(b,s,l) { var ss=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); };
3153var ___hexlify = __hexlify;
3154var __utf8 = function(b,s,e) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
3155var ___utf8 = __utf8;
3156var __lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
3157var ___lpstr = __lpstr;
3158var __cpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
3159var ___cpstr = __cpstr;
3160var __lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
3161var ___lpwstr = __lpwstr;
3162var __lpp4, ___lpp4;
3163__lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
3164var __8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
3165var ___8lpp4 = __8lpp4;
3166var __double, ___double;
3167__double = ___double = function(b, idx) { return read_double_le(b, idx);};
3168var is_buf = function is_buf_a(a) { return Array.isArray(a); };
3169
3170if(has_buf) {
3171 __utf16le = function(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e).replace(chr0,'')/*.replace(chr1,'!')*/; };
3172 __hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
3173 __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) : "";};
3174 __cpstr = function cpstr_b(b, i) { if(!Buffer.isBuffer(b)) return ___cpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
3175 __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);};
3176 __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);};
3177 __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);};
3178 __utf8 = function utf8_b(b, s, e) { return (Buffer.isBuffer(b)) ? b.toString('utf8',s,e) : ___utf8(b,s,e); };
3179 __toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);};
3180 bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); };
3181 __double = function double_(b, i) { if(Buffer.isBuffer(b)) return b.readDoubleLE(i); return ___double(b,i); };
3182 is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); };
3183}
3184
3185/* from js-xls */
3186if(typeof cptable !== 'undefined') {
3187 __utf16le = function(b,s,e) { return cptable.utils.decode(1200, b.slice(s,e)).replace(chr0, ''); };
3188 __utf8 = function(b,s,e) { return cptable.utils.decode(65001, b.slice(s,e)); };
3189 __lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_ansi, b.slice(i+4, i+4+len-1)) : "";};
3190 __cpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";};
3191 __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)) : "";};
3192 __lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";};
3193 __8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";};
3194}
3195
3196var __readUInt8 = function(b, idx) { return b[idx]; };
3197var __readUInt16LE = function(b, idx) { return (b[idx+1]*(1<<8))+b[idx]; };
3198var __readInt16LE = function(b, idx) { var u = (b[idx+1]*(1<<8))+b[idx]; return (u < 0x8000) ? u : ((0xffff - u + 1) * -1); };
3199var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
3200var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
3201var __readInt32BE = function(b, idx) { return (b[idx]<<24)|(b[idx+1]<<16)|(b[idx+2]<<8)|b[idx+3]; };
3202
3203function ReadShift(size, t) {
3204 var o="", oI, oR, oo=[], w, vv, i, loc;
3205 switch(t) {
3206 case 'dbcs':
3207 loc = this.l;
3208 if(has_buf && Buffer.isBuffer(this)) o = this.slice(this.l, this.l+2*size).toString("utf16le");
3209 else for(i = 0; i < size; ++i) { o+=String.fromCharCode(__readUInt16LE(this, loc)); loc+=2; }
3210 size *= 2;
3211 break;
3212
3213 case 'utf8': o = __utf8(this, this.l, this.l + size); break;
3214 case 'utf16le': size *= 2; o = __utf16le(this, this.l, this.l + size); break;
3215
3216 case 'wstr':
3217 if(typeof cptable !== 'undefined') o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l+2*size));
3218 else return ReadShift.call(this, size, 'dbcs');
3219 size = 2 * size; break;
3220
3221 /* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */
3222 case 'lpstr-ansi': o = __lpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break;
3223 case 'lpstr-cp': o = __cpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break;
3224 /* [MS-OLEDS] 2.1.5 LengthPrefixedUnicodeString */
3225 case 'lpwstr': o = __lpwstr(this, this.l); size = 4 + 2 * __readUInt32LE(this, this.l); break;
3226 /* [MS-OFFCRYPTO] 2.1.2 Length-Prefixed Padded Unicode String (UNICODE-LP-P4) */
3227 case 'lpp4': size = 4 + __readUInt32LE(this, this.l); o = __lpp4(this, this.l); if(size & 0x02) size += 2; break;
3228 /* [MS-OFFCRYPTO] 2.1.3 Length-Prefixed UTF-8 String (UTF-8-LP-P4) */
3229 case '8lpp4': size = 4 + __readUInt32LE(this, this.l); o = __8lpp4(this, this.l); if(size & 0x03) size += 4 - (size & 0x03); break;
3230
3231 case 'cstr': size = 0; o = "";
3232 while((w=__readUInt8(this, this.l + size++))!==0) oo.push(_getchar(w));
3233 o = oo.join(""); break;
3234 case '_wstr': size = 0; o = "";
3235 while((w=__readUInt16LE(this,this.l +size))!==0){oo.push(_getchar(w));size+=2;}
3236 size+=2; o = oo.join(""); break;
3237
3238 /* sbcs and dbcs support continue records in the SST way TODO codepages */
3239 case 'dbcs-cont': o = ""; loc = this.l;
3240 for(i = 0; i < size; ++i) {
3241 if(this.lens && this.lens.indexOf(loc) !== -1) {
3242 w = __readUInt8(this, loc);
3243 this.l = loc + 1;
3244 vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont');
3245 return oo.join("") + vv;
3246 }
3247 oo.push(_getchar(__readUInt16LE(this, loc)));
3248 loc+=2;
3249 } o = oo.join(""); size *= 2; break;
3250
3251 case 'cpstr':
3252 if(typeof cptable !== 'undefined') {
3253 o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l + size));
3254 break;
3255 }
3256 /* falls through */
3257 case 'sbcs-cont': o = ""; loc = this.l;
3258 for(i = 0; i != size; ++i) {
3259 if(this.lens && this.lens.indexOf(loc) !== -1) {
3260 w = __readUInt8(this, loc);
3261 this.l = loc + 1;
3262 vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont');
3263 return oo.join("") + vv;
3264 }
3265 oo.push(_getchar(__readUInt8(this, loc)));
3266 loc+=1;
3267 } o = oo.join(""); break;
3268
3269 default:
3270 switch(size) {
3271 case 1: oI = __readUInt8(this, this.l); this.l++; return oI;
3272 case 2: oI = (t === 'i' ? __readInt16LE : __readUInt16LE)(this, this.l); this.l += 2; return oI;
3273 case 4: case -4:
3274 if(t === 'i' || ((this[this.l+3] & 0x80)===0)) { oI = ((size > 0) ? __readInt32LE : __readInt32BE)(this, this.l); this.l += 4; return oI; }
3275 else { oR = __readUInt32LE(this, this.l); this.l += 4; } return oR;
3276 case 8: case -8:
3277 if(t === 'f') {
3278 if(size == 8) oR = __double(this, this.l);
3279 else oR = __double([this[this.l+7],this[this.l+6],this[this.l+5],this[this.l+4],this[this.l+3],this[this.l+2],this[this.l+1],this[this.l+0]], 0);
3280 this.l += 8; return oR;
3281 } else size = 8;
3282 /* falls through */
3283 case 16: o = __hexlify(this, this.l, size); break;
3284 }}
3285 this.l+=size; return o;
3286}
3287
3288var __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); };
3289var __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); };
3290var __writeUInt16LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); };
3291
3292function WriteShift(t, val, f) {
3293 var size = 0, i = 0;
3294 if(f === 'dbcs') {
3295for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i);
3296 size = 2 * val.length;
3297 } else if(f === 'sbcs') {
3298 if(typeof cptable !== 'undefined' && current_ansi == 874) {
3299 /* TODO: use tables directly, don't encode */
3300for(i = 0; i != val.length; ++i) {
3301 var cppayload = cptable.utils.encode(current_ansi, val.charAt(i));
3302 this[this.l + i] = cppayload[0];
3303 }
3304 } else {
3305val = val.replace(/[^\x00-\x7F]/g, "_");
3306for(i = 0; i != val.length; ++i) this[this.l + i] = (val.charCodeAt(i) & 0xFF);
3307 }
3308 size = val.length;
3309 } else if(f === 'hex') {
3310 for(; i < t; ++i) {
3311this[this.l++] = (parseInt(val.slice(2*i, 2*i+2), 16)||0);
3312 } return this;
3313 } else if(f === 'utf16le') {
3314var end = Math.min(this.l + t, this.length);
3315 for(i = 0; i < Math.min(val.length, t); ++i) {
3316 var cc = val.charCodeAt(i);
3317 this[this.l++] = (cc & 0xff);
3318 this[this.l++] = (cc >> 8);
3319 }
3320 while(this.l < end) this[this.l++] = 0;
3321 return this;
3322 } else switch(t) {
3323 case 1: size = 1; this[this.l] = val&0xFF; break;
3324 case 2: size = 2; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; break;
3325 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;
3326 case 4: size = 4; __writeUInt32LE(this, val, this.l); break;
3327 case 8: size = 8; if(f === 'f') { write_double_le(this, val, this.l); break; }
3328 /* falls through */
3329 case 16: break;
3330 case -4: size = 4; __writeInt32LE(this, val, this.l); break;
3331 }
3332 this.l += size; return this;
3333}
3334
3335function CheckField(hexstr, fld) {
3336 var m = __hexlify(this,this.l,hexstr.length>>1);
3337 if(m !== hexstr) throw new Error(fld + 'Expected ' + hexstr + ' saw ' + m);
3338 this.l += hexstr.length>>1;
3339}
3340
3341function prep_blob(blob, pos) {
3342 blob.l = pos;
3343 blob.read_shift = ReadShift;
3344 blob.chk = CheckField;
3345 blob.write_shift = WriteShift;
3346}
3347
3348function parsenoop(blob, length) { blob.l += length; }
3349
3350function new_buf(sz) {
3351 var o = new_raw_buf(sz);
3352 prep_blob(o, 0);
3353 return o;
3354}
3355
3356/* [MS-XLSB] 2.1.4 Record */
3357function recordhopper(data, cb, opts) {
3358 if(!data) return;
3359 var tmpbyte, cntbyte, length;
3360 prep_blob(data, data.l || 0);
3361 var L = data.length, RT = 0, tgt = 0;
3362 while(data.l < L) {
3363 RT = data.read_shift(1);
3364 if(RT & 0x80) RT = (RT & 0x7F) + ((data.read_shift(1) & 0x7F)<<7);
3365 var R = XLSBRecordEnum[RT] || XLSBRecordEnum[0xFFFF];
3366 tmpbyte = data.read_shift(1);
3367 length = tmpbyte & 0x7F;
3368 for(cntbyte = 1; cntbyte <4 && (tmpbyte & 0x80); ++cntbyte) length += ((tmpbyte = data.read_shift(1)) & 0x7F)<<(7*cntbyte);
3369 tgt = data.l + length;
3370 var d = (R.f||parsenoop)(data, length, opts);
3371 data.l = tgt;
3372 if(cb(d, R.n, RT)) return;
3373 }
3374}
3375
3376/* control buffer usage for fixed-length buffers */
3377function buf_array() {
3378 var bufs = [], blksz = has_buf ? 256 : 2048;
3379 var newblk = function ba_newblk(sz) {
3380 var o = (new_buf(sz));
3381 prep_blob(o, 0);
3382 return o;
3383 };
3384
3385 var curbuf = newblk(blksz);
3386
3387 var endbuf = function ba_endbuf() {
3388 if(!curbuf) return;
3389 if(curbuf.length > curbuf.l) { curbuf = curbuf.slice(0, curbuf.l); curbuf.l = curbuf.length; }
3390 if(curbuf.length > 0) bufs.push(curbuf);
3391 curbuf = null;
3392 };
3393
3394 var next = function ba_next(sz) {
3395 if(curbuf && (sz < (curbuf.length - curbuf.l))) return curbuf;
3396 endbuf();
3397 return (curbuf = newblk(Math.max(sz+1, blksz)));
3398 };
3399
3400 var end = function ba_end() {
3401 endbuf();
3402 return __toBuffer([bufs]);
3403 };
3404
3405 var push = function ba_push(buf) { endbuf(); curbuf = buf; if(curbuf.l == null) curbuf.l = curbuf.length; next(blksz); };
3406
3407 return ({ next:next, push:push, end:end, _bufs:bufs });
3408}
3409
3410function write_record(ba, type, payload, length) {
3411 var t = +XLSBRE[type], l;
3412 if(isNaN(t)) return; // TODO: throw something here?
3413 if(!length) length = XLSBRecordEnum[t].p || (payload||[]).length || 0;
3414 l = 1 + (t >= 0x80 ? 1 : 0) + 1/* + length*/;
3415 if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l;
3416 var o = ba.next(l);
3417 if(t <= 0x7F) o.write_shift(1, t);
3418 else {
3419 o.write_shift(1, (t & 0x7F) + 0x80);
3420 o.write_shift(1, (t >> 7));
3421 }
3422 for(var i = 0; i != 4; ++i) {
3423 if(length >= 0x80) { o.write_shift(1, (length & 0x7F)+0x80); length >>= 7; }
3424 else { o.write_shift(1, length); break; }
3425 }
3426 if(length > 0 && is_buf(payload)) ba.push(payload);
3427}
3428/* XLS ranges enforced */
3429function shift_cell_xls(cell, tgt, opts) {
3430 var out = dup(cell);
3431 if(tgt.s) {
3432 if(out.cRel) out.c += tgt.s.c;
3433 if(out.rRel) out.r += tgt.s.r;
3434 } else {
3435 if(out.cRel) out.c += tgt.c;
3436 if(out.rRel) out.r += tgt.r;
3437 }
3438 if(!opts || opts.biff < 12) {
3439 while(out.c >= 0x100) out.c -= 0x100;
3440 while(out.r >= 0x10000) out.r -= 0x10000;
3441 }
3442 return out;
3443}
3444
3445function shift_range_xls(cell, range, opts) {
3446 var out = dup(cell);
3447 out.s = shift_cell_xls(out.s, range.s, opts);
3448 out.e = shift_cell_xls(out.e, range.s, opts);
3449 return out;
3450}
3451
3452function encode_cell_xls(c, biff) {
3453 if(c.cRel && c.c < 0) { c = dup(c); while(c.c < 0) c.c += (biff > 8) ? 0x4000 : 0x100; }
3454 if(c.rRel && c.r < 0) { c = dup(c); while(c.r < 0) c.r += (biff > 8) ? 0x100000 : ((biff > 5) ? 0x10000 : 0x4000); }
3455 var s = encode_cell(c);
3456 if(!c.cRel && c.cRel != null) s = fix_col(s);
3457 if(!c.rRel && c.rRel != null) s = fix_row(s);
3458 return s;
3459}
3460
3461function encode_range_xls(r, opts) {
3462 if(r.s.r == 0 && !r.s.rRel) {
3463 if(r.e.r == (opts.biff >= 12 ? 0xFFFFF : (opts.biff >= 8 ? 0x10000 : 0x4000)) && !r.e.rRel) {
3464 return (r.s.cRel ? "" : "$") + encode_col(r.s.c) + ":" + (r.e.cRel ? "" : "$") + encode_col(r.e.c);
3465 }
3466 }
3467 if(r.s.c == 0 && !r.s.cRel) {
3468 if(r.e.c == (opts.biff >= 12 ? 0x3FFF : 0xFF) && !r.e.cRel) {
3469 return (r.s.rRel ? "" : "$") + encode_row(r.s.r) + ":" + (r.e.rRel ? "" : "$") + encode_row(r.e.r);
3470 }
3471 }
3472 return encode_cell_xls(r.s, opts.biff) + ":" + encode_cell_xls(r.e, opts.biff);
3473}
3474function decode_row(rowstr) { return parseInt(unfix_row(rowstr),10) - 1; }
3475function encode_row(row) { return "" + (row + 1); }
3476function fix_row(cstr) { return cstr.replace(/([A-Z]|^)(\d+)$/,"$1$$$2"); }
3477function unfix_row(cstr) { return cstr.replace(/\$(\d+)$/,"$1"); }
3478
3479function decode_col(colstr) { var c = unfix_col(colstr), d = 0, i = 0; for(; i !== c.length; ++i) d = 26*d + c.charCodeAt(i) - 64; return d - 1; }
3480function encode_col(col) { if(col < 0) throw new Error("invalid column " + col); var s=""; for(++col; col; col=Math.floor((col-1)/26)) s = String.fromCharCode(((col-1)%26) + 65) + s; return s; }
3481function fix_col(cstr) { return cstr.replace(/^([A-Z])/,"$$$1"); }
3482function unfix_col(cstr) { return cstr.replace(/^\$([A-Z])/,"$1"); }
3483
3484function split_cell(cstr) { return cstr.replace(/(\$?[A-Z]*)(\$?\d*)/,"$1,$2").split(","); }
3485function decode_cell(cstr) { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; }
3486function encode_cell(cell) { return encode_col(cell.c) + encode_row(cell.r); }
3487function decode_range(range) { var x =range.split(":").map(decode_cell); return {s:x[0],e:x[x.length-1]}; }
3488function encode_range(cs,ce) {
3489 if(typeof ce === 'undefined' || typeof ce === 'number') {
3490return encode_range(cs.s, cs.e);
3491 }
3492if(typeof cs !== 'string') cs = encode_cell((cs));
3493 if(typeof ce !== 'string') ce = encode_cell((ce));
3494return cs == ce ? cs : cs + ":" + ce;
3495}
3496
3497function safe_decode_range(range) {
3498 var o = {s:{c:0,r:0},e:{c:0,r:0}};
3499 var idx = 0, i = 0, cc = 0;
3500 var len = range.length;
3501 for(idx = 0; i < len; ++i) {
3502 if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
3503 idx = 26*idx + cc;
3504 }
3505 o.s.c = --idx;
3506
3507 for(idx = 0; i < len; ++i) {
3508 if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
3509 idx = 10*idx + cc;
3510 }
3511 o.s.r = --idx;
3512
3513 if(i === len || range.charCodeAt(++i) === 58) { o.e.c=o.s.c; o.e.r=o.s.r; return o; }
3514
3515 for(idx = 0; i != len; ++i) {
3516 if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
3517 idx = 26*idx + cc;
3518 }
3519 o.e.c = --idx;
3520
3521 for(idx = 0; i != len; ++i) {
3522 if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
3523 idx = 10*idx + cc;
3524 }
3525 o.e.r = --idx;
3526 return o;
3527}
3528
3529function safe_format_cell(cell, v) {
3530 var q = (cell.t == 'd' && v instanceof Date);
3531 if(cell.z != null) try { return (cell.w = SSF.format(cell.z, q ? datenum(v) : v)); } catch(e) { }
3532 try { return (cell.w = SSF.format((cell.XF||{}).numFmtId||(q ? 14 : 0), q ? datenum(v) : v)); } catch(e) { return ''+v; }
3533}
3534
3535function format_cell(cell, v, o) {
3536 if(cell == null || cell.t == null || cell.t == 'z') return "";
3537 if(cell.w !== undefined) return cell.w;
3538 if(cell.t == 'd' && !cell.z && o && o.dateNF) cell.z = o.dateNF;
3539 if(v == undefined) return safe_format_cell(cell, cell.v);
3540 return safe_format_cell(cell, v);
3541}
3542
3543function sheet_to_workbook(sheet, opts) {
3544 var n = opts && opts.sheet ? opts.sheet : "Sheet1";
3545 var sheets = {}; sheets[n] = sheet;
3546 return { SheetNames: [n], Sheets: sheets };
3547}
3548
3549function sheet_add_aoa(_ws, data, opts) {
3550 var o = opts || {};
3551 var dense = _ws ? Array.isArray(_ws) : o.dense;
3552 if(DENSE != null && dense == null) dense = DENSE;
3553 var ws = _ws || (dense ? ([]) : ({}));
3554 var _R = 0, _C = 0;
3555 if(ws && o.origin != null) {
3556 if(typeof o.origin == 'number') _R = o.origin;
3557 else {
3558 var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
3559 _R = _origin.r; _C = _origin.c;
3560 }
3561 }
3562 var range = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}});
3563 if(ws['!ref']) {
3564 var _range = safe_decode_range(ws['!ref']);
3565 range.s.c = _range.s.c;
3566 range.s.r = _range.s.r;
3567 range.e.c = Math.max(range.e.c, _range.e.c);
3568 range.e.r = Math.max(range.e.r, _range.e.r);
3569 if(_R == -1) range.e.r = _R = _range.e.r + 1;
3570 }
3571 for(var R = 0; R != data.length; ++R) {
3572 if(!data[R]) continue;
3573 if(!Array.isArray(data[R])) throw new Error("aoa_to_sheet expects an array of arrays");
3574 for(var C = 0; C != data[R].length; ++C) {
3575 if(typeof data[R][C] === 'undefined') continue;
3576 var cell = ({v: data[R][C] });
3577 var __R = _R + R, __C = _C + C;
3578 if(range.s.r > __R) range.s.r = __R;
3579 if(range.s.c > __C) range.s.c = __C;
3580 if(range.e.r < __R) range.e.r = __R;
3581 if(range.e.c < __C) range.e.c = __C;
3582 if(data[R][C] && typeof data[R][C] === 'object' && !Array.isArray(data[R][C]) && !(data[R][C] instanceof Date)) cell = data[R][C];
3583 else {
3584 if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
3585 if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.sheetStubs) continue; else cell.t = 'z'; }
3586 else if(typeof cell.v === 'number') cell.t = 'n';
3587 else if(typeof cell.v === 'boolean') cell.t = 'b';
3588 else if(cell.v instanceof Date) {
3589 cell.z = o.dateNF || SSF._table[14];
3590 if(o.cellDates) { cell.t = 'd'; cell.w = SSF.format(cell.z, datenum(cell.v)); }
3591 else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); }
3592 }
3593 else cell.t = 's';
3594 }
3595 if(dense) {
3596 if(!ws[__R]) ws[__R] = [];
3597 if(ws[__R][__C] && ws[__R][__C].z) cell.z = ws[__R][__C].z;
3598 ws[__R][__C] = cell;
3599 } else {
3600 var cell_ref = encode_cell(({c:__C,r:__R}));
3601 if(ws[cell_ref] && ws[cell_ref].z) cell.z = ws[cell_ref].z;
3602 ws[cell_ref] = cell;
3603 }
3604 }
3605 }
3606 if(range.s.c < 10000000) ws['!ref'] = encode_range(range);
3607 return ws;
3608}
3609function aoa_to_sheet(data, opts) { return sheet_add_aoa(null, data, opts); }
3610
3611/* [MS-OLEPS] 2.2 PropertyType */
3612//var VT_EMPTY = 0x0000;
3613//var VT_NULL = 0x0001;
3614var VT_I2 = 0x0002;
3615var VT_I4 = 0x0003;
3616//var VT_R4 = 0x0004;
3617//var VT_R8 = 0x0005;
3618//var VT_CY = 0x0006;
3619//var VT_DATE = 0x0007;
3620//var VT_BSTR = 0x0008;
3621//var VT_ERROR = 0x000A;
3622var VT_BOOL = 0x000B;
3623var VT_VARIANT = 0x000C;
3624//var VT_DECIMAL = 0x000E;
3625//var VT_I1 = 0x0010;
3626//var VT_UI1 = 0x0011;
3627//var VT_UI2 = 0x0012;
3628var VT_UI4 = 0x0013;
3629//var VT_I8 = 0x0014;
3630//var VT_UI8 = 0x0015;
3631//var VT_INT = 0x0016;
3632//var VT_UINT = 0x0017;
3633var VT_LPSTR = 0x001E;
3634//var VT_LPWSTR = 0x001F;
3635var VT_FILETIME = 0x0040;
3636var VT_BLOB = 0x0041;
3637//var VT_STREAM = 0x0042;
3638//var VT_STORAGE = 0x0043;
3639//var VT_STREAMED_Object = 0x0044;
3640//var VT_STORED_Object = 0x0045;
3641//var VT_BLOB_Object = 0x0046;
3642var VT_CF = 0x0047;
3643//var VT_CLSID = 0x0048;
3644//var VT_VERSIONED_STREAM = 0x0049;
3645var VT_VECTOR = 0x1000;
3646//var VT_ARRAY = 0x2000;
3647
3648var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
3649var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString
3650var VT_CUSTOM = [VT_STRING, VT_USTR];
3651
3652/* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */
3653var DocSummaryPIDDSI = {
36540x01: { n: 'CodePage', t: VT_I2 },
36550x02: { n: 'Category', t: VT_STRING },
36560x03: { n: 'PresentationFormat', t: VT_STRING },
36570x04: { n: 'ByteCount', t: VT_I4 },
36580x05: { n: 'LineCount', t: VT_I4 },
36590x06: { n: 'ParagraphCount', t: VT_I4 },
36600x07: { n: 'SlideCount', t: VT_I4 },
36610x08: { n: 'NoteCount', t: VT_I4 },
36620x09: { n: 'HiddenCount', t: VT_I4 },
36630x0a: { n: 'MultimediaClipCount', t: VT_I4 },
36640x0b: { n: 'ScaleCrop', t: VT_BOOL },
36650x0c: { n: 'HeadingPairs', t: VT_VECTOR | VT_VARIANT },
36660x0d: { n: 'TitlesOfParts', t: VT_VECTOR | VT_LPSTR },
36670x0e: { n: 'Manager', t: VT_STRING },
36680x0f: { n: 'Company', t: VT_STRING },
36690x10: { n: 'LinksUpToDate', t: VT_BOOL },
36700x11: { n: 'CharacterCount', t: VT_I4 },
36710x13: { n: 'SharedDoc', t: VT_BOOL },
36720x16: { n: 'HyperlinksChanged', t: VT_BOOL },
36730x17: { n: 'AppVersion', t: VT_I4, p: 'version' },
36740x18: { n: 'DigSig', t: VT_BLOB },
36750x1A: { n: 'ContentType', t: VT_STRING },
36760x1B: { n: 'ContentStatus', t: VT_STRING },
36770x1C: { n: 'Language', t: VT_STRING },
36780x1D: { n: 'Version', t: VT_STRING },
36790xFF: {}
3680};
3681
3682/* [MS-OSHARED] 2.3.3.2.1.1 Summary Information Property Set PIDSI */
3683var SummaryPIDSI = {
36840x01: { n: 'CodePage', t: VT_I2 },
36850x02: { n: 'Title', t: VT_STRING },
36860x03: { n: 'Subject', t: VT_STRING },
36870x04: { n: 'Author', t: VT_STRING },
36880x05: { n: 'Keywords', t: VT_STRING },
36890x06: { n: 'Comments', t: VT_STRING },
36900x07: { n: 'Template', t: VT_STRING },
36910x08: { n: 'LastAuthor', t: VT_STRING },
36920x09: { n: 'RevNumber', t: VT_STRING },
36930x0A: { n: 'EditTime', t: VT_FILETIME },
36940x0B: { n: 'LastPrinted', t: VT_FILETIME },
36950x0C: { n: 'CreatedDate', t: VT_FILETIME },
36960x0D: { n: 'ModifiedDate', t: VT_FILETIME },
36970x0E: { n: 'PageCount', t: VT_I4 },
36980x0F: { n: 'WordCount', t: VT_I4 },
36990x10: { n: 'CharCount', t: VT_I4 },
37000x11: { n: 'Thumbnail', t: VT_CF },
37010x12: { n: 'Application', t: VT_STRING },
37020x13: { n: 'DocSecurity', t: VT_I4 },
37030xFF: {}
3704};
3705
3706/* [MS-OLEPS] 2.18 */
3707var SpecialProperties = {
37080x80000000: { n: 'Locale', t: VT_UI4 },
37090x80000003: { n: 'Behavior', t: VT_UI4 },
37100x72627262: {}
3711};
3712
3713(function() {
3714 for(var y in SpecialProperties) if(Object.prototype.hasOwnProperty.call(SpecialProperties, y))
3715 DocSummaryPIDDSI[y] = SummaryPIDSI[y] = SpecialProperties[y];
3716})();
3717
3718var DocSummaryRE = evert_key(DocSummaryPIDDSI, "n");
3719var SummaryRE = evert_key(SummaryPIDSI, "n");
3720
3721/* [MS-XLS] 2.4.63 Country/Region codes */
3722var CountryEnum = {
37230x0001: "US", // United States
37240x0002: "CA", // Canada
37250x0003: "", // Latin America (except Brazil)
37260x0007: "RU", // Russia
37270x0014: "EG", // Egypt
37280x001E: "GR", // Greece
37290x001F: "NL", // Netherlands
37300x0020: "BE", // Belgium
37310x0021: "FR", // France
37320x0022: "ES", // Spain
37330x0024: "HU", // Hungary
37340x0027: "IT", // Italy
37350x0029: "CH", // Switzerland
37360x002B: "AT", // Austria
37370x002C: "GB", // United Kingdom
37380x002D: "DK", // Denmark
37390x002E: "SE", // Sweden
37400x002F: "NO", // Norway
37410x0030: "PL", // Poland
37420x0031: "DE", // Germany
37430x0034: "MX", // Mexico
37440x0037: "BR", // Brazil
37450x003d: "AU", // Australia
37460x0040: "NZ", // New Zealand
37470x0042: "TH", // Thailand
37480x0051: "JP", // Japan
37490x0052: "KR", // Korea
37500x0054: "VN", // Viet Nam
37510x0056: "CN", // China
37520x005A: "TR", // Turkey
37530x0069: "JS", // Ramastan
37540x00D5: "DZ", // Algeria
37550x00D8: "MA", // Morocco
37560x00DA: "LY", // Libya
37570x015F: "PT", // Portugal
37580x0162: "IS", // Iceland
37590x0166: "FI", // Finland
37600x01A4: "CZ", // Czech Republic
37610x0376: "TW", // Taiwan
37620x03C1: "LB", // Lebanon
37630x03C2: "JO", // Jordan
37640x03C3: "SY", // Syria
37650x03C4: "IQ", // Iraq
37660x03C5: "KW", // Kuwait
37670x03C6: "SA", // Saudi Arabia
37680x03CB: "AE", // United Arab Emirates
37690x03CC: "IL", // Israel
37700x03CE: "QA", // Qatar
37710x03D5: "IR", // Iran
37720xFFFF: "US" // United States
3773};
3774
3775/* [MS-XLS] 2.5.127 */
3776var XLSFillPattern = [
3777 null,
3778 'solid',
3779 'mediumGray',
3780 'darkGray',
3781 'lightGray',
3782 'darkHorizontal',
3783 'darkVertical',
3784 'darkDown',
3785 'darkUp',
3786 'darkGrid',
3787 'darkTrellis',
3788 'lightHorizontal',
3789 'lightVertical',
3790 'lightDown',
3791 'lightUp',
3792 'lightGrid',
3793 'lightTrellis',
3794 'gray125',
3795 'gray0625'
3796];
3797
3798function rgbify(arr) { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); }
3799
3800/* [MS-XLS] 2.5.161 */
3801/* [MS-XLSB] 2.5.75 Icv */
3802var _XLSIcv = rgbify([
3803 /* Color Constants */
3804 0x000000,
3805 0xFFFFFF,
3806 0xFF0000,
3807 0x00FF00,
3808 0x0000FF,
3809 0xFFFF00,
3810 0xFF00FF,
3811 0x00FFFF,
3812
3813 /* Overridable Defaults */
3814 0x000000,
3815 0xFFFFFF,
3816 0xFF0000,
3817 0x00FF00,
3818 0x0000FF,
3819 0xFFFF00,
3820 0xFF00FF,
3821 0x00FFFF,
3822
3823 0x800000,
3824 0x008000,
3825 0x000080,
3826 0x808000,
3827 0x800080,
3828 0x008080,
3829 0xC0C0C0,
3830 0x808080,
3831 0x9999FF,
3832 0x993366,
3833 0xFFFFCC,
3834 0xCCFFFF,
3835 0x660066,
3836 0xFF8080,
3837 0x0066CC,
3838 0xCCCCFF,
3839
3840 0x000080,
3841 0xFF00FF,
3842 0xFFFF00,
3843 0x00FFFF,
3844 0x800080,
3845 0x800000,
3846 0x008080,
3847 0x0000FF,
3848 0x00CCFF,
3849 0xCCFFFF,
3850 0xCCFFCC,
3851 0xFFFF99,
3852 0x99CCFF,
3853 0xFF99CC,
3854 0xCC99FF,
3855 0xFFCC99,
3856
3857 0x3366FF,
3858 0x33CCCC,
3859 0x99CC00,
3860 0xFFCC00,
3861 0xFF9900,
3862 0xFF6600,
3863 0x666699,
3864 0x969696,
3865 0x003366,
3866 0x339966,
3867 0x003300,
3868 0x333300,
3869 0x993300,
3870 0x993366,
3871 0x333399,
3872 0x333333,
3873
3874 /* Other entries to appease BIFF8/12 */
3875 0xFFFFFF, /* 0x40 icvForeground ?? */
3876 0x000000, /* 0x41 icvBackground ?? */
3877 0x000000, /* 0x42 icvFrame ?? */
3878 0x000000, /* 0x43 icv3D ?? */
3879 0x000000, /* 0x44 icv3DText ?? */
3880 0x000000, /* 0x45 icv3DHilite ?? */
3881 0x000000, /* 0x46 icv3DShadow ?? */
3882 0x000000, /* 0x47 icvHilite ?? */
3883 0x000000, /* 0x48 icvCtlText ?? */
3884 0x000000, /* 0x49 icvCtlScrl ?? */
3885 0x000000, /* 0x4A icvCtlInv ?? */
3886 0x000000, /* 0x4B icvCtlBody ?? */
3887 0x000000, /* 0x4C icvCtlFrame ?? */
3888 0x000000, /* 0x4D icvCtlFore ?? */
3889 0x000000, /* 0x4E icvCtlBack ?? */
3890 0x000000, /* 0x4F icvCtlNeutral */
3891 0x000000, /* 0x50 icvInfoBk ?? */
3892 0x000000 /* 0x51 icvInfoText ?? */
3893]);
3894var XLSIcv = dup(_XLSIcv);
3895/* Parts enumerated in OPC spec, MS-XLSB and MS-XLSX */
3896/* 12.3 Part Summary <SpreadsheetML> */
3897/* 14.2 Part Summary <DrawingML> */
3898/* [MS-XLSX] 2.1 Part Enumerations ; [MS-XLSB] 2.1.7 Part Enumeration */
3899var ct2type/*{[string]:string}*/ = ({
3900 /* Workbook */
3901 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": "workbooks",
3902
3903 /* Worksheet */
3904 "application/vnd.ms-excel.binIndexWs": "TODO", /* Binary Index */
3905
3906 /* Macrosheet */
3907 "application/vnd.ms-excel.intlmacrosheet": "TODO",
3908 "application/vnd.ms-excel.binIndexMs": "TODO", /* Binary Index */
3909
3910 /* File Properties */
3911 "application/vnd.openxmlformats-package.core-properties+xml": "coreprops",
3912 "application/vnd.openxmlformats-officedocument.custom-properties+xml": "custprops",
3913 "application/vnd.openxmlformats-officedocument.extended-properties+xml": "extprops",
3914
3915 /* Custom Data Properties */
3916 "application/vnd.openxmlformats-officedocument.customXmlProperties+xml": "TODO",
3917 "application/vnd.openxmlformats-officedocument.spreadsheetml.customProperty": "TODO",
3918
3919 /* PivotTable */
3920 "application/vnd.ms-excel.pivotTable": "TODO",
3921 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml": "TODO",
3922
3923 /* Chart Objects */
3924 "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": "TODO",
3925
3926 /* Chart Colors */
3927 "application/vnd.ms-office.chartcolorstyle+xml": "TODO",
3928
3929 /* Chart Style */
3930 "application/vnd.ms-office.chartstyle+xml": "TODO",
3931
3932 /* Chart Advanced */
3933 "application/vnd.ms-office.chartex+xml": "TODO",
3934
3935 /* Calculation Chain */
3936 "application/vnd.ms-excel.calcChain": "calcchains",
3937 "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains",
3938
3939 /* Printer Settings */
3940 "application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings": "TODO",
3941
3942 /* ActiveX */
3943 "application/vnd.ms-office.activeX": "TODO",
3944 "application/vnd.ms-office.activeX+xml": "TODO",
3945
3946 /* Custom Toolbars */
3947 "application/vnd.ms-excel.attachedToolbars": "TODO",
3948
3949 /* External Data Connections */
3950 "application/vnd.ms-excel.connections": "TODO",
3951 "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml": "TODO",
3952
3953 /* External Links */
3954 "application/vnd.ms-excel.externalLink": "links",
3955 "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml": "links",
3956
3957 /* Metadata */
3958 "application/vnd.ms-excel.sheetMetadata": "TODO",
3959 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml": "TODO",
3960
3961 /* PivotCache */
3962 "application/vnd.ms-excel.pivotCacheDefinition": "TODO",
3963 "application/vnd.ms-excel.pivotCacheRecords": "TODO",
3964 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml": "TODO",
3965 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml": "TODO",
3966
3967 /* Query Table */
3968 "application/vnd.ms-excel.queryTable": "TODO",
3969 "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml": "TODO",
3970
3971 /* Shared Workbook */
3972 "application/vnd.ms-excel.userNames": "TODO",
3973 "application/vnd.ms-excel.revisionHeaders": "TODO",
3974 "application/vnd.ms-excel.revisionLog": "TODO",
3975 "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml": "TODO",
3976 "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml": "TODO",
3977 "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml": "TODO",
3978
3979 /* Single Cell Table */
3980 "application/vnd.ms-excel.tableSingleCells": "TODO",
3981 "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml": "TODO",
3982
3983 /* Slicer */
3984 "application/vnd.ms-excel.slicer": "TODO",
3985 "application/vnd.ms-excel.slicerCache": "TODO",
3986 "application/vnd.ms-excel.slicer+xml": "TODO",
3987 "application/vnd.ms-excel.slicerCache+xml": "TODO",
3988
3989 /* Sort Map */
3990 "application/vnd.ms-excel.wsSortMap": "TODO",
3991
3992 /* Table */
3993 "application/vnd.ms-excel.table": "TODO",
3994 "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml": "TODO",
3995
3996 /* Themes */
3997 "application/vnd.openxmlformats-officedocument.theme+xml": "themes",
3998
3999 /* Theme Override */
4000 "application/vnd.openxmlformats-officedocument.themeOverride+xml": "TODO",
4001
4002 /* Timeline */
4003 "application/vnd.ms-excel.Timeline+xml": "TODO", /* verify */
4004 "application/vnd.ms-excel.TimelineCache+xml": "TODO", /* verify */
4005
4006 /* VBA */
4007 "application/vnd.ms-office.vbaProject": "vba",
4008 "application/vnd.ms-office.vbaProjectSignature": "vba",
4009
4010 /* Volatile Dependencies */
4011 "application/vnd.ms-office.volatileDependencies": "TODO",
4012 "application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml": "TODO",
4013
4014 /* Control Properties */
4015 "application/vnd.ms-excel.controlproperties+xml": "TODO",
4016
4017 /* Data Model */
4018 "application/vnd.openxmlformats-officedocument.model+data": "TODO",
4019
4020 /* Survey */
4021 "application/vnd.ms-excel.Survey+xml": "TODO",
4022
4023 /* Drawing */
4024 "application/vnd.openxmlformats-officedocument.drawing+xml": "drawings",
4025 "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml": "TODO",
4026 "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml": "TODO",
4027 "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml": "TODO",
4028 "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml": "TODO",
4029 "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml": "TODO",
4030
4031 /* VML */
4032 "application/vnd.openxmlformats-officedocument.vmlDrawing": "TODO",
4033
4034 "application/vnd.openxmlformats-package.relationships+xml": "rels",
4035 "application/vnd.openxmlformats-officedocument.oleObject": "TODO",
4036
4037 /* Image */
4038 "image/png": "TODO",
4039
4040 "sheet": "js"
4041});
4042
4043var CT_LIST = (function(){
4044 var o = {
4045 workbooks: {
4046 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
4047 xlsm: "application/vnd.ms-excel.sheet.macroEnabled.main+xml",
4048 xlsb: "application/vnd.ms-excel.sheet.binary.macroEnabled.main",
4049 xlam: "application/vnd.ms-excel.addin.macroEnabled.main+xml",
4050 xltx: "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
4051 },
4052 strs: { /* Shared Strings */
4053 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
4054 xlsb: "application/vnd.ms-excel.sharedStrings"
4055 },
4056 comments: { /* Comments */
4057 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
4058 xlsb: "application/vnd.ms-excel.comments"
4059 },
4060 sheets: { /* Worksheet */
4061 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
4062 xlsb: "application/vnd.ms-excel.worksheet"
4063 },
4064 charts: { /* Chartsheet */
4065 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml",
4066 xlsb: "application/vnd.ms-excel.chartsheet"
4067 },
4068 dialogs: { /* Dialogsheet */
4069 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml",
4070 xlsb: "application/vnd.ms-excel.dialogsheet"
4071 },
4072 macros: { /* Macrosheet (Excel 4.0 Macros) */
4073 xlsx: "application/vnd.ms-excel.macrosheet+xml",
4074 xlsb: "application/vnd.ms-excel.macrosheet"
4075 },
4076 styles: { /* Styles */
4077 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
4078 xlsb: "application/vnd.ms-excel.styles"
4079 }
4080 };
4081 keys(o).forEach(function(k) { ["xlsm", "xlam"].forEach(function(v) { if(!o[k][v]) o[k][v] = o[k].xlsx; }); });
4082 keys(o).forEach(function(k){ keys(o[k]).forEach(function(v) { ct2type[o[k][v]] = k; }); });
4083 return o;
4084})();
4085
4086var type2ct/*{[string]:Array<string>}*/ = evert_arr(ct2type);
4087
4088XMLNS.CT = 'http://schemas.openxmlformats.org/package/2006/content-types';
4089
4090function new_ct() {
4091 return ({
4092 workbooks:[], sheets:[], charts:[], dialogs:[], macros:[],
4093 rels:[], strs:[], comments:[], links:[],
4094 coreprops:[], extprops:[], custprops:[], themes:[], styles:[],
4095 calcchains:[], vba: [], drawings: [],
4096 TODO:[], xmlns: "" });
4097}
4098
4099function parse_ct(data) {
4100 var ct = new_ct();
4101 if(!data || !data.match) return ct;
4102 var ctext = {};
4103 (data.match(tagregex)||[]).forEach(function(x) {
4104 var y = parsexmltag(x);
4105 switch(y[0].replace(nsregex,"<")) {
4106 case '<?xml': break;
4107 case '<Types': ct.xmlns = y['xmlns' + (y[0].match(/<(\w+):/)||["",""])[1] ]; break;
4108 case '<Default': ctext[y.Extension] = y.ContentType; break;
4109 case '<Override':
4110 if(ct[ct2type[y.ContentType]] !== undefined) ct[ct2type[y.ContentType]].push(y.PartName);
4111 break;
4112 }
4113 });
4114 if(ct.xmlns !== XMLNS.CT) throw new Error("Unknown Namespace: " + ct.xmlns);
4115 ct.calcchain = ct.calcchains.length > 0 ? ct.calcchains[0] : "";
4116 ct.sst = ct.strs.length > 0 ? ct.strs[0] : "";
4117 ct.style = ct.styles.length > 0 ? ct.styles[0] : "";
4118 ct.defaults = ctext;
4119 delete ct.calcchains;
4120 return ct;
4121}
4122
4123var CTYPE_XML_ROOT = writextag('Types', null, {
4124 'xmlns': XMLNS.CT,
4125 'xmlns:xsd': XMLNS.xsd,
4126 'xmlns:xsi': XMLNS.xsi
4127});
4128
4129var CTYPE_DEFAULTS = [
4130 ['xml', 'application/xml'],
4131 ['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
4132 ['vml', 'application/vnd.openxmlformats-officedocument.vmlDrawing'],
4133 ['data', 'application/vnd.openxmlformats-officedocument.model+data'],
4134 /* from test files */
4135 ['bmp', 'image/bmp'],
4136 ['png', 'image/png'],
4137 ['gif', 'image/gif'],
4138 ['emf', 'image/x-emf'],
4139 ['wmf', 'image/x-wmf'],
4140 ['jpg', 'image/jpeg'], ['jpeg', 'image/jpeg'],
4141 ['tif', 'image/tiff'], ['tiff', 'image/tiff'],
4142 ['pdf', 'application/pdf'],
4143 ['rels', type2ct.rels[0]]
4144].map(function(x) {
4145 return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
4146});
4147
4148function write_ct(ct, opts) {
4149 var o = [], v;
4150 o[o.length] = (XML_HEADER);
4151 o[o.length] = (CTYPE_XML_ROOT);
4152 o = o.concat(CTYPE_DEFAULTS);
4153
4154 /* only write first instance */
4155 var f1 = function(w) {
4156 if(ct[w] && ct[w].length > 0) {
4157 v = ct[w][0];
4158 o[o.length] = (writextag('Override', null, {
4159 'PartName': (v[0] == '/' ? "":"/") + v,
4160 'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
4161 }));
4162 }
4163 };
4164
4165 /* book type-specific */
4166 var f2 = function(w) {
4167 (ct[w]||[]).forEach(function(v) {
4168 o[o.length] = (writextag('Override', null, {
4169 'PartName': (v[0] == '/' ? "":"/") + v,
4170 'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
4171 }));
4172 });
4173 };
4174
4175 /* standard type */
4176 var f3 = function(t) {
4177 (ct[t]||[]).forEach(function(v) {
4178 o[o.length] = (writextag('Override', null, {
4179 'PartName': (v[0] == '/' ? "":"/") + v,
4180 'ContentType': type2ct[t][0]
4181 }));
4182 });
4183 };
4184
4185 f1('workbooks');
4186 f2('sheets');
4187 f2('charts');
4188 f3('themes');
4189 ['strs', 'styles'].forEach(f1);
4190 ['coreprops', 'extprops', 'custprops'].forEach(f3);
4191 f3('vba');
4192 f3('comments');
4193 f3('drawings');
4194 if(o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
4195 return o.join("");
4196}
4197/* 9.3 Relationships */
4198var RELS = ({
4199 WB: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
4200 SHEET: "http://sheetjs.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
4201 HLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
4202 VML: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing",
4203 XPATH: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath",
4204 XMISS: "http://schemas.microsoft.com/office/2006/relationships/xlExternalLinkPath/xlPathMissing",
4205 XLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLink",
4206 VBA: "http://schemas.microsoft.com/office/2006/relationships/vbaProject"
4207});
4208
4209/* 9.3.3 Representing Relationships */
4210function get_rels_path(file) {
4211 var n = file.lastIndexOf("/");
4212 return file.slice(0,n+1) + '_rels/' + file.slice(n+1) + ".rels";
4213}
4214
4215function parse_rels(data, currentFilePath) {
4216 var rels = {"!id":{}};
4217 if (!data) return rels;
4218 if (currentFilePath.charAt(0) !== '/') {
4219 currentFilePath = '/'+currentFilePath;
4220 }
4221 var hash = {};
4222
4223 (data.match(tagregex)||[]).forEach(function(x) {
4224 var y = parsexmltag(x);
4225 /* 9.3.2.2 OPC_Relationships */
4226 if (y[0] === '<Relationship') {
4227 var rel = {}; rel.Type = y.Type; rel.Target = y.Target; rel.Id = y.Id; rel.TargetMode = y.TargetMode;
4228 var canonictarget = y.TargetMode === 'External' ? y.Target : resolve_path(y.Target, currentFilePath);
4229 rels[canonictarget] = rel;
4230 hash[y.Id] = rel;
4231 }
4232 });
4233 rels["!id"] = hash;
4234 return rels;
4235}
4236
4237XMLNS.RELS = 'http://schemas.openxmlformats.org/package/2006/relationships';
4238
4239var RELS_ROOT = writextag('Relationships', null, {
4240 //'xmlns:ns0': XMLNS.RELS,
4241 'xmlns': XMLNS.RELS
4242});
4243
4244/* TODO */
4245function write_rels(rels) {
4246 var o = [XML_HEADER, RELS_ROOT];
4247 keys(rels['!id']).forEach(function(rid) {
4248 o[o.length] = (writextag('Relationship', null, rels['!id'][rid]));
4249 });
4250 if(o.length>2){ o[o.length] = ('</Relationships>'); o[1]=o[1].replace("/>",">"); }
4251 return o.join("");
4252}
4253
4254var RELS_EXTERN = [RELS.HLINK, RELS.XPATH, RELS.XMISS];
4255function add_rels(rels, rId, f, type, relobj, targetmode) {
4256 if(!relobj) relobj = {};
4257 if(!rels['!id']) rels['!id'] = {};
4258 if(rId < 0) for(rId = 1; rels['!id']['rId' + rId]; ++rId){/* empty */}
4259 relobj.Id = 'rId' + rId;
4260 relobj.Type = type;
4261 relobj.Target = f;
4262 if(targetmode) relobj.TargetMode = targetmode;
4263 else if(RELS_EXTERN.indexOf(relobj.Type) > -1) relobj.TargetMode = "External";
4264 if(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId);
4265 rels['!id'][relobj.Id] = relobj;
4266 rels[('/' + relobj.Target).replace("//","/")] = relobj;
4267 return rId;
4268}
4269/* ECMA-376 Part II 11.1 Core Properties Part */
4270/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
4271var CORE_PROPS = [
4272 ["cp:category", "Category"],
4273 ["cp:contentStatus", "ContentStatus"],
4274 ["cp:keywords", "Keywords"],
4275 ["cp:lastModifiedBy", "LastAuthor"],
4276 ["cp:lastPrinted", "LastPrinted"],
4277 ["cp:revision", "RevNumber"],
4278 ["cp:version", "Version"],
4279 ["dc:creator", "Author"],
4280 ["dc:description", "Comments"],
4281 ["dc:identifier", "Identifier"],
4282 ["dc:language", "Language"],
4283 ["dc:subject", "Subject"],
4284 ["dc:title", "Title"],
4285 ["dcterms:created", "CreatedDate", 'date'],
4286 ["dcterms:modified", "ModifiedDate", 'date']
4287];
4288
4289XMLNS.CORE_PROPS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
4290RELS.CORE_PROPS = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';
4291
4292var CORE_PROPS_REGEX = (function() {
4293 var r = new Array(CORE_PROPS.length);
4294 for(var i = 0; i < CORE_PROPS.length; ++i) {
4295 var f = CORE_PROPS[i];
4296 var g = "(?:"+ f[0].slice(0,f[0].indexOf(":")) +":)"+ f[0].slice(f[0].indexOf(":")+1);
4297 r[i] = new RegExp("<" + g + "[^>]*>([\\s\\S]*?)<\/" + g + ">");
4298 }
4299 return r;
4300})();
4301
4302function parse_core_props(data) {
4303 var p = {};
4304 data = utf8read(data);
4305
4306 for(var i = 0; i < CORE_PROPS.length; ++i) {
4307 var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
4308 if(cur != null && cur.length > 0) p[f[1]] = unescapexml(cur[1]);
4309 if(f[2] === 'date' && p[f[1]]) p[f[1]] = parseDate(p[f[1]]);
4310 }
4311
4312 return p;
4313}
4314
4315var CORE_PROPS_XML_ROOT = writextag('cp:coreProperties', null, {
4316 //'xmlns': XMLNS.CORE_PROPS,
4317 'xmlns:cp': XMLNS.CORE_PROPS,
4318 'xmlns:dc': XMLNS.dc,
4319 'xmlns:dcterms': XMLNS.dcterms,
4320 'xmlns:dcmitype': XMLNS.dcmitype,
4321 'xmlns:xsi': XMLNS.xsi
4322});
4323
4324function cp_doit(f, g, h, o, p) {
4325 if(p[f] != null || g == null || g === "") return;
4326 p[f] = g;
4327 g = escapexml(g);
4328 o[o.length] = (h ? writextag(f,g,h) : writetag(f,g));
4329}
4330
4331function write_core_props(cp, _opts) {
4332 var opts = _opts || {};
4333 var o = [XML_HEADER, CORE_PROPS_XML_ROOT], p = {};
4334 if(!cp && !opts.Props) return o.join("");
4335
4336 if(cp) {
4337 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);
4338 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);
4339 }
4340
4341 for(var i = 0; i != CORE_PROPS.length; ++i) {
4342 var f = CORE_PROPS[i];
4343 var v = opts.Props && opts.Props[f[1]] != null ? opts.Props[f[1]] : cp ? cp[f[1]] : null;
4344 if(v === true) v = "1";
4345 else if(v === false) v = "0";
4346 else if(typeof v == "number") v = String(v);
4347 if(v != null) cp_doit(f[0], v, null, o, p);
4348 }
4349 if(o.length>2){ o[o.length] = ('</cp:coreProperties>'); o[1]=o[1].replace("/>",">"); }
4350 return o.join("");
4351}
4352/* 15.2.12.3 Extended File Properties Part */
4353/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
4354var EXT_PROPS = [
4355 ["Application", "Application", "string"],
4356 ["AppVersion", "AppVersion", "string"],
4357 ["Company", "Company", "string"],
4358 ["DocSecurity", "DocSecurity", "string"],
4359 ["Manager", "Manager", "string"],
4360 ["HyperlinksChanged", "HyperlinksChanged", "bool"],
4361 ["SharedDoc", "SharedDoc", "bool"],
4362 ["LinksUpToDate", "LinksUpToDate", "bool"],
4363 ["ScaleCrop", "ScaleCrop", "bool"],
4364 ["HeadingPairs", "HeadingPairs", "raw"],
4365 ["TitlesOfParts", "TitlesOfParts", "raw"]
4366];
4367
4368XMLNS.EXT_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
4369RELS.EXT_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';
4370
4371var PseudoPropsPairs = [
4372 "Worksheets", "SheetNames",
4373 "NamedRanges", "DefinedNames",
4374 "Chartsheets", "ChartNames"
4375];
4376function load_props_pairs(HP, TOP, props, opts) {
4377 var v = [];
4378 if(typeof HP == "string") v = parseVector(HP, opts);
4379 else for(var j = 0; j < HP.length; ++j) v = v.concat(HP[j].map(function(hp) { return {v:hp}; }));
4380 var parts = (typeof TOP == "string") ? parseVector(TOP, opts).map(function (x) { return x.v; }) : TOP;
4381 var idx = 0, len = 0;
4382 if(parts.length > 0) for(var i = 0; i !== v.length; i += 2) {
4383 len = +(v[i+1].v);
4384 switch(v[i].v) {
4385 case "Worksheets":
4386 case "工作表":
4387 case "Листы":
4388 case "أوراق العمل":
4389 case "ワークシート":
4390 case "גליונות עבודה":
4391 case "Arbeitsblätter":
4392 case "Çalışma Sayfaları":
4393 case "Feuilles de calcul":
4394 case "Fogli di lavoro":
4395 case "Folhas de cálculo":
4396 case "Planilhas":
4397 case "Regneark":
4398 case "Hojas de cálculo":
4399 case "Werkbladen":
4400 props.Worksheets = len;
4401 props.SheetNames = parts.slice(idx, idx + len);
4402 break;
4403
4404 case "Named Ranges":
4405 case "Rangos con nombre":
4406 case "名前付き一覧":
4407 case "Benannte Bereiche":
4408 case "Navngivne områder":
4409 props.NamedRanges = len;
4410 props.DefinedNames = parts.slice(idx, idx + len);
4411 break;
4412
4413 case "Charts":
4414 case "Diagramme":
4415 props.Chartsheets = len;
4416 props.ChartNames = parts.slice(idx, idx + len);
4417 break;
4418 }
4419 idx += len;
4420 }
4421}
4422
4423function parse_ext_props(data, p, opts) {
4424 var q = {}; if(!p) p = {};
4425 data = utf8read(data);
4426
4427 EXT_PROPS.forEach(function(f) {
4428 var xml = (data.match(matchtag(f[0]))||[])[1];
4429 switch(f[2]) {
4430 case "string": p[f[1]] = unescapexml(xml||""); break;
4431 case "bool": p[f[1]] = xml === "true"; break;
4432 case "raw":
4433 var cur = data.match(new RegExp("<" + f[0] + "[^>]*>([\\s\\S]*?)<\/" + f[0] + ">"));
4434 if(cur && cur.length > 0) q[f[1]] = cur[1];
4435 break;
4436 }
4437 });
4438
4439 if(q.HeadingPairs && q.TitlesOfParts) load_props_pairs(q.HeadingPairs, q.TitlesOfParts, p, opts);
4440
4441 return p;
4442}
4443
4444var EXT_PROPS_XML_ROOT = writextag('Properties', null, {
4445 'xmlns': XMLNS.EXT_PROPS,
4446 'xmlns:vt': XMLNS.vt
4447});
4448
4449function write_ext_props(cp) {
4450 var o = [], W = writextag;
4451 if(!cp) cp = {};
4452 cp.Application = "SheetJS";
4453 o[o.length] = (XML_HEADER);
4454 o[o.length] = (EXT_PROPS_XML_ROOT);
4455
4456 EXT_PROPS.forEach(function(f) {
4457 if(cp[f[1]] === undefined) return;
4458 var v;
4459 switch(f[2]) {
4460 case 'string': v = escapexml(String(cp[f[1]])); break;
4461 case 'bool': v = cp[f[1]] ? 'true' : 'false'; break;
4462 }
4463 if(v !== undefined) o[o.length] = (W(f[0], v));
4464 });
4465
4466 /* TODO: HeadingPairs, TitlesOfParts */
4467 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"})));
4468 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"})));
4469 if(o.length>2){ o[o.length] = ('</Properties>'); o[1]=o[1].replace("/>",">"); }
4470 return o.join("");
4471}
4472/* 15.2.12.2 Custom File Properties Part */
4473XMLNS.CUST_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
4474RELS.CUST_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties';
4475
4476var custregex = /<[^>]+>[^<]*/g;
4477function parse_cust_props(data, opts) {
4478 var p = {}, name = "";
4479 var m = data.match(custregex);
4480 if(m) for(var i = 0; i != m.length; ++i) {
4481 var x = m[i], y = parsexmltag(x);
4482 switch(y[0]) {
4483 case '<?xml': break;
4484 case '<Properties': break;
4485 case '<property': name = unescapexml(y.name); break;
4486 case '</property>': name = null; break;
4487 default: if (x.indexOf('<vt:') === 0) {
4488 var toks = x.split('>');
4489 var type = toks[0].slice(4), text = toks[1];
4490 /* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */
4491 switch(type) {
4492 case 'lpstr': case 'bstr': case 'lpwstr':
4493 p[name] = unescapexml(text);
4494 break;
4495 case 'bool':
4496 p[name] = parsexmlbool(text);
4497 break;
4498 case 'i1': case 'i2': case 'i4': case 'i8': case 'int': case 'uint':
4499 p[name] = parseInt(text, 10);
4500 break;
4501 case 'r4': case 'r8': case 'decimal':
4502 p[name] = parseFloat(text);
4503 break;
4504 case 'filetime': case 'date':
4505 p[name] = parseDate(text);
4506 break;
4507 case 'cy': case 'error':
4508 p[name] = unescapexml(text);
4509 break;
4510 default:
4511 if(type.slice(-1) == '/') break;
4512 if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks);
4513 }
4514 } else if(x.slice(0,2) === "</") {/* empty */
4515 } else if(opts.WTF) throw new Error(x);
4516 }
4517 }
4518 return p;
4519}
4520
4521var CUST_PROPS_XML_ROOT = writextag('Properties', null, {
4522 'xmlns': XMLNS.CUST_PROPS,
4523 'xmlns:vt': XMLNS.vt
4524});
4525
4526function write_cust_props(cp) {
4527 var o = [XML_HEADER, CUST_PROPS_XML_ROOT];
4528 if(!cp) return o.join("");
4529 var pid = 1;
4530 keys(cp).forEach(function custprop(k) { ++pid;
4531 o[o.length] = (writextag('property', write_vt(cp[k]), {
4532 'fmtid': '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}',
4533 'pid': pid,
4534 'name': escapexml(k)
4535 }));
4536 });
4537 if(o.length>2){ o[o.length] = '</Properties>'; o[1]=o[1].replace("/>",">"); }
4538 return o.join("");
4539}
4540/* 18.4.7 rPr CT_RPrElt */
4541function parse_rpr(rpr) {
4542 var font = {}, m = rpr.match(tagregex), i = 0;
4543 var pass = false;
4544 if(m) for(;i!=m.length; ++i) {
4545 var y = parsexmltag(m[i]);
4546 switch(y[0].replace(/\w*:/g,"")) {
4547 /* 18.8.12 condense CT_BooleanProperty */
4548 /* ** not required . */
4549 case '<condense': break;
4550 /* 18.8.17 extend CT_BooleanProperty */
4551 /* ** not required . */
4552 case '<extend': break;
4553 /* 18.8.36 shadow CT_BooleanProperty */
4554 /* ** not required . */
4555 case '<shadow':
4556 if(!y.val) break;
4557 /* falls through */
4558 case '<shadow>':
4559 case '<shadow/>': font.shadow = 1; break;
4560 case '</shadow>': break;
4561
4562 /* 18.4.1 charset CT_IntProperty TODO */
4563 case '<charset':
4564 if(y.val == '1') break;
4565 font.cp = CS2CP[parseInt(y.val, 10)];
4566 break;
4567
4568 /* 18.4.2 outline CT_BooleanProperty TODO */
4569 case '<outline':
4570 if(!y.val) break;
4571 /* falls through */
4572 case '<outline>':
4573 case '<outline/>': font.outline = 1; break;
4574 case '</outline>': break;
4575
4576 /* 18.4.5 rFont CT_FontName */
4577 case '<rFont': font.name = y.val; break;
4578
4579 /* 18.4.11 sz CT_FontSize */
4580 case '<sz': font.sz = y.val; break;
4581
4582 /* 18.4.10 strike CT_BooleanProperty */
4583 case '<strike':
4584 if(!y.val) break;
4585 /* falls through */
4586 case '<strike>':
4587 case '<strike/>': font.strike = 1; break;
4588 case '</strike>': break;
4589
4590 /* 18.4.13 u CT_UnderlineProperty */
4591 case '<u':
4592 if(!y.val) break;
4593 switch(y.val) {
4594 case 'double': font.uval = "double"; break;
4595 case 'singleAccounting': font.uval = "single-accounting"; break;
4596 case 'doubleAccounting': font.uval = "double-accounting"; break;
4597 }
4598 /* falls through */
4599 case '<u>':
4600 case '<u/>': font.u = 1; break;
4601 case '</u>': break;
4602
4603 /* 18.8.2 b */
4604 case '<b':
4605 if(y.val == '0') break;
4606 /* falls through */
4607 case '<b>':
4608 case '<b/>': font.b = 1; break;
4609 case '</b>': break;
4610
4611 /* 18.8.26 i */
4612 case '<i':
4613 if(y.val == '0') break;
4614 /* falls through */
4615 case '<i>':
4616 case '<i/>': font.i = 1; break;
4617 case '</i>': break;
4618
4619 /* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */
4620 case '<color':
4621 if(y.rgb) font.color = y.rgb.slice(2,8);
4622 break;
4623
4624 /* 18.8.18 family ST_FontFamily */
4625 case '<family': font.family = y.val; break;
4626
4627 /* 18.4.14 vertAlign CT_VerticalAlignFontProperty TODO */
4628 case '<vertAlign': font.valign = y.val; break;
4629
4630 /* 18.8.35 scheme CT_FontScheme TODO */
4631 case '<scheme': break;
4632
4633 /* 18.2.10 extLst CT_ExtensionList ? */
4634 case '<extLst': case '<extLst>': case '</extLst>': break;
4635 case '<ext': pass = true; break;
4636 case '</ext>': pass = false; break;
4637 default:
4638 if(y[0].charCodeAt(1) !== 47 && !pass) throw new Error('Unrecognized rich format ' + y[0]);
4639 }
4640 }
4641 return font;
4642}
4643
4644var parse_rs = (function() {
4645 var tregex = matchtag("t"), rpregex = matchtag("rPr");
4646 /* 18.4.4 r CT_RElt */
4647 function parse_r(r) {
4648 /* 18.4.12 t ST_Xstring */
4649 var t = r.match(tregex)/*, cp = 65001*/;
4650 if(!t) return {t:"s", v:""};
4651
4652 var o = ({t:'s', v:unescapexml(t[1])});
4653 var rpr = r.match(rpregex);
4654 if(rpr) o.s = parse_rpr(rpr[1]);
4655 return o;
4656 }
4657 var rregex = /<(?:\w+:)?r>/g, rend = /<\/(?:\w+:)?r>/;
4658 return function parse_rs(rs) {
4659 return rs.replace(rregex,"").split(rend).map(parse_r).filter(function(r) { return r.v; });
4660 };
4661})();
4662
4663
4664/* Parse a list of <r> tags */
4665var rs_to_html = (function parse_rs_factory() {
4666 var nlregex = /(\r\n|\n)/g;
4667 function parse_rpr2(font, intro, outro) {
4668 var style = [];
4669
4670 if(font.u) style.push("text-decoration: underline;");
4671 if(font.uval) style.push("text-underline-style:" + font.uval + ";");
4672 if(font.sz) style.push("font-size:" + font.sz + "pt;");
4673 if(font.outline) style.push("text-effect: outline;");
4674 if(font.shadow) style.push("text-shadow: auto;");
4675 intro.push('<span style="' + style.join("") + '">');
4676
4677 if(font.b) { intro.push("<b>"); outro.push("</b>"); }
4678 if(font.i) { intro.push("<i>"); outro.push("</i>"); }
4679 if(font.strike) { intro.push("<s>"); outro.push("</s>"); }
4680
4681 var align = font.valign || "";
4682 if(align == "superscript" || align == "super") align = "sup";
4683 else if(align == "subscript") align = "sub";
4684 if(align != "") { intro.push("<" + align + ">"); outro.push("</" + align + ">"); }
4685
4686 outro.push("</span>");
4687 return font;
4688 }
4689
4690 /* 18.4.4 r CT_RElt */
4691 function r_to_html(r) {
4692 var terms = [[],r.v,[]];
4693 if(!r.v) return "";
4694
4695 if(r.s) parse_rpr2(r.s, terms[0], terms[2]);
4696
4697 return terms[0].join("") + terms[1].replace(nlregex,'<br/>') + terms[2].join("");
4698 }
4699
4700 return function parse_rs(rs) {
4701 return rs.map(r_to_html).join("");
4702 };
4703})();
4704
4705/* 18.4.8 si CT_Rst */
4706var sitregex = /<(?:\w+:)?t[^>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r>/;
4707var sirphregex = /<(?:\w+:)?rPh.*?>([\s\S]*?)<\/(?:\w+:)?rPh>/g;
4708function parse_si(x, opts) {
4709 var html = opts ? opts.cellHTML : true;
4710 var z = {};
4711 if(!x) return null;
4712 //var y;
4713 /* 18.4.12 t ST_Xstring (Plaintext String) */
4714 // TODO: is whitespace actually valid here?
4715 if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) {
4716 z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||""));
4717 z.r = utf8read(x);
4718 if(html) z.h = escapehtml(z.t);
4719 }
4720 /* 18.4.4 r CT_RElt (Rich Text Run) */
4721 else if((/*y = */x.match(sirregex))) {
4722 z.r = utf8read(x);
4723 z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")));
4724 if(html) z.h = rs_to_html(parse_rs(z.r));
4725 }
4726 /* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
4727 /* 18.4.6 rPh CT_PhoneticRun (TODO: needed for Asian support) */
4728 return z;
4729}
4730
4731/* 18.4 Shared String Table */
4732var sstr0 = /<(?:\w+:)?sst([^>]*)>([\s\S]*)<\/(?:\w+:)?sst>/;
4733var sstr1 = /<(?:\w+:)?(?:si|sstItem)>/g;
4734var sstr2 = /<\/(?:\w+:)?(?:si|sstItem)>/;
4735function parse_sst_xml(data, opts) {
4736 var s = ([]), ss = "";
4737 if(!data) return s;
4738 /* 18.4.9 sst CT_Sst */
4739 var sst = data.match(sstr0);
4740 if(sst) {
4741 ss = sst[2].replace(sstr1,"").split(sstr2);
4742 for(var i = 0; i != ss.length; ++i) {
4743 var o = parse_si(ss[i].trim(), opts);
4744 if(o != null) s[s.length] = o;
4745 }
4746 sst = parsexmltag(sst[1]); s.Count = sst.count; s.Unique = sst.uniqueCount;
4747 }
4748 return s;
4749}
4750
4751RELS.SST = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
4752var straywsregex = /^\s|\s$|[\t\n\r]/;
4753function write_sst_xml(sst, opts) {
4754 if(!opts.bookSST) return "";
4755 var o = [XML_HEADER];
4756 o[o.length] = (writextag('sst', null, {
4757 xmlns: XMLNS.main[0],
4758 count: sst.Count,
4759 uniqueCount: sst.Unique
4760 }));
4761 for(var i = 0; i != sst.length; ++i) { if(sst[i] == null) continue;
4762 var s = sst[i];
4763 var sitag = "<si>";
4764 if(s.r) sitag += s.r;
4765 else {
4766 sitag += "<t";
4767 if(!s.t) s.t = "";
4768 if(s.t.match(straywsregex)) sitag += ' xml:space="preserve"';
4769 sitag += ">" + escapexml(s.t) + "</t>";
4770 }
4771 sitag += "</si>";
4772 o[o.length] = (sitag);
4773 }
4774 if(o.length>2){ o[o.length] = ('</sst>'); o[1]=o[1].replace("/>",">"); }
4775 return o.join("");
4776}
4777function hex2RGB(h) {
4778 var o = h.slice(h[0]==="#"?1:0).slice(0,6);
4779 return [parseInt(o.slice(0,2),16),parseInt(o.slice(2,4),16),parseInt(o.slice(4,6),16)];
4780}
4781function rgb2Hex(rgb) {
4782 for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);
4783 return o.toString(16).toUpperCase().slice(1);
4784}
4785
4786function rgb2HSL(rgb) {
4787 var R = rgb[0]/255, G = rgb[1]/255, B=rgb[2]/255;
4788 var M = Math.max(R, G, B), m = Math.min(R, G, B), C = M - m;
4789 if(C === 0) return [0, 0, R];
4790
4791 var H6 = 0, S = 0, L2 = (M + m);
4792 S = C / (L2 > 1 ? 2 - L2 : L2);
4793 switch(M){
4794 case R: H6 = ((G - B) / C + 6)%6; break;
4795 case G: H6 = ((B - R) / C + 2); break;
4796 case B: H6 = ((R - G) / C + 4); break;
4797 }
4798 return [H6 / 6, S, L2 / 2];
4799}
4800
4801function hsl2RGB(hsl){
4802 var H = hsl[0], S = hsl[1], L = hsl[2];
4803 var C = S * 2 * (L < 0.5 ? L : 1 - L), m = L - C/2;
4804 var rgb = [m,m,m], h6 = 6*H;
4805
4806 var X;
4807 if(S !== 0) switch(h6|0) {
4808 case 0: case 6: X = C * h6; rgb[0] += C; rgb[1] += X; break;
4809 case 1: X = C * (2 - h6); rgb[0] += X; rgb[1] += C; break;
4810 case 2: X = C * (h6 - 2); rgb[1] += C; rgb[2] += X; break;
4811 case 3: X = C * (4 - h6); rgb[1] += X; rgb[2] += C; break;
4812 case 4: X = C * (h6 - 4); rgb[2] += C; rgb[0] += X; break;
4813 case 5: X = C * (6 - h6); rgb[2] += X; rgb[0] += C; break;
4814 }
4815 for(var i = 0; i != 3; ++i) rgb[i] = Math.round(rgb[i]*255);
4816 return rgb;
4817}
4818
4819/* 18.8.3 bgColor tint algorithm */
4820function rgb_tint(hex, tint) {
4821 if(tint === 0) return hex;
4822 var hsl = rgb2HSL(hex2RGB(hex));
4823 if (tint < 0) hsl[2] = hsl[2] * (1 + tint);
4824 else hsl[2] = 1 - (1 - hsl[2]) * (1 - tint);
4825 return rgb2Hex(hsl2RGB(hsl));
4826}
4827
4828/* 18.3.1.13 width calculations */
4829/* [MS-OI29500] 2.1.595 Column Width & Formatting */
4830var DEF_MDW = 6, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
4831function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); }
4832function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; }
4833function char2width(chr) { return (Math.round((chr * MDW + 5)/MDW*256))/256; }
4834//function px2char_(px) { return (((px - 5)/MDW * 100 + 0.5))/100; }
4835//function char2width_(chr) { return (((chr * MDW + 5)/MDW*256))/256; }
4836function cycle_width(collw) { return char2width(px2char(width2px(collw))); }
4837/* XLSX/XLSB/XLS specify width in units of MDW */
4838function find_mdw_colw(collw) {
4839 var delta = Math.abs(collw - cycle_width(collw)), _MDW = MDW;
4840 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; }
4841 MDW = _MDW;
4842}
4843/* XLML specifies width in terms of pixels */
4844/*function find_mdw_wpx(wpx) {
4845 var delta = Infinity, guess = 0, _MDW = MIN_MDW;
4846 for(MDW=MIN_MDW; MDW<MAX_MDW; ++MDW) {
4847 guess = char2width_(px2char_(wpx))*256;
4848 guess = (guess) % 1;
4849 if(guess > 0.5) guess--;
4850 if(Math.abs(guess) < delta) { delta = Math.abs(guess); _MDW = MDW; }
4851 }
4852 MDW = _MDW;
4853}*/
4854
4855function process_col(coll) {
4856 if(coll.width) {
4857 coll.wpx = width2px(coll.width);
4858 coll.wch = px2char(coll.wpx);
4859 coll.MDW = MDW;
4860 } else if(coll.wpx) {
4861 coll.wch = px2char(coll.wpx);
4862 coll.width = char2width(coll.wch);
4863 coll.MDW = MDW;
4864 } else if(typeof coll.wch == 'number') {
4865 coll.width = char2width(coll.wch);
4866 coll.wpx = width2px(coll.width);
4867 coll.MDW = MDW;
4868 }
4869 if(coll.customWidth) delete coll.customWidth;
4870}
4871
4872var DEF_PPI = 96, PPI = DEF_PPI;
4873function px2pt(px) { return px * 96 / PPI; }
4874function pt2px(pt) { return pt * PPI / 96; }
4875
4876/* [MS-EXSPXML3] 2.4.54 ST_enmPattern */
4877var XLMLPatternTypeMap = {
4878 "None": "none",
4879 "Solid": "solid",
4880 "Gray50": "mediumGray",
4881 "Gray75": "darkGray",
4882 "Gray25": "lightGray",
4883 "HorzStripe": "darkHorizontal",
4884 "VertStripe": "darkVertical",
4885 "ReverseDiagStripe": "darkDown",
4886 "DiagStripe": "darkUp",
4887 "DiagCross": "darkGrid",
4888 "ThickDiagCross": "darkTrellis",
4889 "ThinHorzStripe": "lightHorizontal",
4890 "ThinVertStripe": "lightVertical",
4891 "ThinReverseDiagStripe": "lightDown",
4892 "ThinHorzCross": "lightGrid"
4893};
4894
4895/* 18.8.5 borders CT_Borders */
4896function parse_borders(t, styles, themes, opts) {
4897 styles.Borders = [];
4898 var border = {};
4899 var pass = false;
4900 (t[0].match(tagregex)||[]).forEach(function(x) {
4901 var y = parsexmltag(x);
4902 switch(strip_ns(y[0])) {
4903 case '<borders': case '<borders>': case '</borders>': break;
4904
4905 /* 18.8.4 border CT_Border */
4906 case '<border': case '<border>': case '<border/>':
4907 border = {};
4908 if(y.diagonalUp) border.diagonalUp = parsexmlbool(y.diagonalUp);
4909 if(y.diagonalDown) border.diagonalDown = parsexmlbool(y.diagonalDown);
4910 styles.Borders.push(border);
4911 break;
4912 case '</border>': break;
4913
4914 /* note: not in spec, appears to be CT_BorderPr */
4915 case '<left/>': break;
4916 case '<left': case '<left>': break;
4917 case '</left>': break;
4918
4919 /* note: not in spec, appears to be CT_BorderPr */
4920 case '<right/>': break;
4921 case '<right': case '<right>': break;
4922 case '</right>': break;
4923
4924 /* 18.8.43 top CT_BorderPr */
4925 case '<top/>': break;
4926 case '<top': case '<top>': break;
4927 case '</top>': break;
4928
4929 /* 18.8.6 bottom CT_BorderPr */
4930 case '<bottom/>': break;
4931 case '<bottom': case '<bottom>': break;
4932 case '</bottom>': break;
4933
4934 /* 18.8.13 diagonal CT_BorderPr */
4935 case '<diagonal': case '<diagonal>': case '<diagonal/>': break;
4936 case '</diagonal>': break;
4937
4938 /* 18.8.25 horizontal CT_BorderPr */
4939 case '<horizontal': case '<horizontal>': case '<horizontal/>': break;
4940 case '</horizontal>': break;
4941
4942 /* 18.8.44 vertical CT_BorderPr */
4943 case '<vertical': case '<vertical>': case '<vertical/>': break;
4944 case '</vertical>': break;
4945
4946 /* 18.8.37 start CT_BorderPr */
4947 case '<start': case '<start>': case '<start/>': break;
4948 case '</start>': break;
4949
4950 /* 18.8.16 end CT_BorderPr */
4951 case '<end': case '<end>': case '<end/>': break;
4952 case '</end>': break;
4953
4954 /* 18.8.? color CT_Color */
4955 case '<color': case '<color>':
4956 break;
4957 case '<color/>': case '</color>': break;
4958
4959 /* 18.2.10 extLst CT_ExtensionList ? */
4960 case '<extLst': case '<extLst>': case '</extLst>': break;
4961 case '<ext': pass = true; break;
4962 case '</ext>': pass = false; break;
4963 default: if(opts && opts.WTF) {
4964 if(!pass) throw new Error('unrecognized ' + y[0] + ' in borders');
4965 }
4966 }
4967 });
4968}
4969
4970/* 18.8.21 fills CT_Fills */
4971function parse_fills(t, styles, themes, opts) {
4972 styles.Fills = [];
4973 var fill = {};
4974 var pass = false;
4975 (t[0].match(tagregex)||[]).forEach(function(x) {
4976 var y = parsexmltag(x);
4977 switch(strip_ns(y[0])) {
4978 case '<fills': case '<fills>': case '</fills>': break;
4979
4980 /* 18.8.20 fill CT_Fill */
4981 case '<fill>': case '<fill': case '<fill/>':
4982 fill = {}; styles.Fills.push(fill); break;
4983 case '</fill>': break;
4984
4985 /* 18.8.24 gradientFill CT_GradientFill */
4986 case '<gradientFill>': break;
4987 case '<gradientFill':
4988 case '</gradientFill>': styles.Fills.push(fill); fill = {}; break;
4989
4990 /* 18.8.32 patternFill CT_PatternFill */
4991 case '<patternFill': case '<patternFill>':
4992 if(y.patternType) fill.patternType = y.patternType;
4993 break;
4994 case '<patternFill/>': case '</patternFill>': break;
4995
4996 /* 18.8.3 bgColor CT_Color */
4997 case '<bgColor':
4998 if(!fill.bgColor) fill.bgColor = {};
4999 if(y.indexed) fill.bgColor.indexed = parseInt(y.indexed, 10);
5000 if(y.theme) fill.bgColor.theme = parseInt(y.theme, 10);
5001 if(y.tint) fill.bgColor.tint = parseFloat(y.tint);
5002 /* Excel uses ARGB strings */
5003 if(y.rgb) fill.bgColor.rgb = y.rgb.slice(-6);
5004 break;
5005 case '<bgColor/>': case '</bgColor>': break;
5006
5007 /* 18.8.19 fgColor CT_Color */
5008 case '<fgColor':
5009 if(!fill.fgColor) fill.fgColor = {};
5010 if(y.theme) fill.fgColor.theme = parseInt(y.theme, 10);
5011 if(y.tint) fill.fgColor.tint = parseFloat(y.tint);
5012 /* Excel uses ARGB strings */
5013 if(y.rgb != null) fill.fgColor.rgb = y.rgb.slice(-6);
5014 break;
5015 case '<fgColor/>': case '</fgColor>': break;
5016
5017 /* 18.8.38 stop CT_GradientStop */
5018 case '<stop': case '<stop/>': break;
5019 case '</stop>': break;
5020
5021 /* 18.8.? color CT_Color */
5022 case '<color': case '<color/>': break;
5023 case '</color>': break;
5024
5025 /* 18.2.10 extLst CT_ExtensionList ? */
5026 case '<extLst': case '<extLst>': case '</extLst>': break;
5027 case '<ext': pass = true; break;
5028 case '</ext>': pass = false; break;
5029 default: if(opts && opts.WTF) {
5030 if(!pass) throw new Error('unrecognized ' + y[0] + ' in fills');
5031 }
5032 }
5033 });
5034}
5035
5036/* 18.8.23 fonts CT_Fonts */
5037function parse_fonts(t, styles, themes, opts) {
5038 styles.Fonts = [];
5039 var font = {};
5040 var pass = false;
5041 (t[0].match(tagregex)||[]).forEach(function(x) {
5042 var y = parsexmltag(x);
5043 switch(strip_ns(y[0])) {
5044 case '<fonts': case '<fonts>': case '</fonts>': break;
5045
5046 /* 18.8.22 font CT_Font */
5047 case '<font': case '<font>': break;
5048 case '</font>': case '<font/>':
5049 styles.Fonts.push(font);
5050 font = {};
5051 break;
5052
5053 /* 18.8.29 name CT_FontName */
5054 case '<name': if(y.val) font.name = utf8read(y.val); break;
5055 case '<name/>': case '</name>': break;
5056
5057 /* 18.8.2 b CT_BooleanProperty */
5058 case '<b': font.bold = y.val ? parsexmlbool(y.val) : 1; break;
5059 case '<b/>': font.bold = 1; break;
5060
5061 /* 18.8.26 i CT_BooleanProperty */
5062 case '<i': font.italic = y.val ? parsexmlbool(y.val) : 1; break;
5063 case '<i/>': font.italic = 1; break;
5064
5065 /* 18.4.13 u CT_UnderlineProperty */
5066 case '<u':
5067 switch(y.val) {
5068 case "none": font.underline = 0x00; break;
5069 case "single": font.underline = 0x01; break;
5070 case "double": font.underline = 0x02; break;
5071 case "singleAccounting": font.underline = 0x21; break;
5072 case "doubleAccounting": font.underline = 0x22; break;
5073 } break;
5074 case '<u/>': font.underline = 1; break;
5075
5076 /* 18.4.10 strike CT_BooleanProperty */
5077 case '<strike': font.strike = y.val ? parsexmlbool(y.val) : 1; break;
5078 case '<strike/>': font.strike = 1; break;
5079
5080 /* 18.4.2 outline CT_BooleanProperty */
5081 case '<outline': font.outline = y.val ? parsexmlbool(y.val) : 1; break;
5082 case '<outline/>': font.outline = 1; break;
5083
5084 /* 18.8.36 shadow CT_BooleanProperty */
5085 case '<shadow': font.shadow = y.val ? parsexmlbool(y.val) : 1; break;
5086 case '<shadow/>': font.shadow = 1; break;
5087
5088 /* 18.8.12 condense CT_BooleanProperty */
5089 case '<condense': font.condense = y.val ? parsexmlbool(y.val) : 1; break;
5090 case '<condense/>': font.condense = 1; break;
5091
5092 /* 18.8.17 extend CT_BooleanProperty */
5093 case '<extend': font.extend = y.val ? parsexmlbool(y.val) : 1; break;
5094 case '<extend/>': font.extend = 1; break;
5095
5096 /* 18.4.11 sz CT_FontSize */
5097 case '<sz': if(y.val) font.sz = +y.val; break;
5098 case '<sz/>': case '</sz>': break;
5099
5100 /* 18.4.14 vertAlign CT_VerticalAlignFontProperty */
5101 case '<vertAlign': if(y.val) font.vertAlign = y.val; break;
5102 case '<vertAlign/>': case '</vertAlign>': break;
5103
5104 /* 18.8.18 family CT_FontFamily */
5105 case '<family': if(y.val) font.family = parseInt(y.val,10); break;
5106 case '<family/>': case '</family>': break;
5107
5108 /* 18.8.35 scheme CT_FontScheme */
5109 case '<scheme': if(y.val) font.scheme = y.val; break;
5110 case '<scheme/>': case '</scheme>': break;
5111
5112 /* 18.4.1 charset CT_IntProperty */
5113 case '<charset':
5114 if(y.val == '1') break;
5115 y.codepage = CS2CP[parseInt(y.val, 10)];
5116 break;
5117
5118 /* 18.?.? color CT_Color */
5119 case '<color':
5120 if(!font.color) font.color = {};
5121 if(y.auto) font.color.auto = parsexmlbool(y.auto);
5122
5123 if(y.rgb) font.color.rgb = y.rgb.slice(-6);
5124 else if(y.indexed) {
5125 font.color.index = parseInt(y.indexed, 10);
5126 var icv = XLSIcv[font.color.index];
5127 if(font.color.index == 81) icv = XLSIcv[1];
5128 if(!icv) throw new Error(x);
5129 font.color.rgb = icv[0].toString(16) + icv[1].toString(16) + icv[2].toString(16);
5130 } else if(y.theme) {
5131 font.color.theme = parseInt(y.theme, 10);
5132 if(y.tint) font.color.tint = parseFloat(y.tint);
5133 if(y.theme && themes.themeElements && themes.themeElements.clrScheme) {
5134 font.color.rgb = rgb_tint(themes.themeElements.clrScheme[font.color.theme].rgb, font.color.tint || 0);
5135 }
5136 }
5137
5138 break;
5139 case '<color/>': case '</color>': break;
5140
5141 /* note: sometimes mc:AlternateContent appears bare */
5142 case '<AlternateContent': pass = true; break;
5143 case '</AlternateContent>': pass = false; break;
5144
5145 /* 18.2.10 extLst CT_ExtensionList ? */
5146 case '<extLst': case '<extLst>': case '</extLst>': break;
5147 case '<ext': pass = true; break;
5148 case '</ext>': pass = false; break;
5149 default: if(opts && opts.WTF) {
5150 if(!pass) throw new Error('unrecognized ' + y[0] + ' in fonts');
5151 }
5152 }
5153 });
5154}
5155
5156/* 18.8.31 numFmts CT_NumFmts */
5157function parse_numFmts(t, styles, opts) {
5158 styles.NumberFmt = [];
5159 var k/*Array<number>*/ = (keys(SSF._table));
5160 for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
5161 var m = t[0].match(tagregex);
5162 if(!m) return;
5163 for(i=0; i < m.length; ++i) {
5164 var y = parsexmltag(m[i]);
5165 switch(strip_ns(y[0])) {
5166 case '<numFmts': case '</numFmts>': case '<numFmts/>': case '<numFmts>': break;
5167 case '<numFmt': {
5168 var f=unescapexml(utf8read(y.formatCode)), j=parseInt(y.numFmtId,10);
5169 styles.NumberFmt[j] = f;
5170 if(j>0) {
5171 if(j > 0x188) {
5172 for(j = 0x188; j > 0x3c; --j) if(styles.NumberFmt[j] == null) break;
5173 styles.NumberFmt[j] = f;
5174 }
5175 SSF.load(f,j);
5176 }
5177 } break;
5178 case '</numFmt>': break;
5179 default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in numFmts');
5180 }
5181 }
5182}
5183
5184function write_numFmts(NF) {
5185 var o = ["<numFmts>"];
5186 [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
5187 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])}));
5188 });
5189 if(o.length === 1) return "";
5190 o[o.length] = ("</numFmts>");
5191 o[0] = writextag('numFmts', null, { count:o.length-2 }).replace("/>", ">");
5192 return o.join("");
5193}
5194
5195/* 18.8.10 cellXfs CT_CellXfs */
5196var cellXF_uint = [ "numFmtId", "fillId", "fontId", "borderId", "xfId" ];
5197var cellXF_bool = [ "applyAlignment", "applyBorder", "applyFill", "applyFont", "applyNumberFormat", "applyProtection", "pivotButton", "quotePrefix" ];
5198function parse_cellXfs(t, styles, opts) {
5199 styles.CellXf = [];
5200 var xf;
5201 var pass = false;
5202 (t[0].match(tagregex)||[]).forEach(function(x) {
5203 var y = parsexmltag(x), i = 0;
5204 switch(strip_ns(y[0])) {
5205 case '<cellXfs': case '<cellXfs>': case '<cellXfs/>': case '</cellXfs>': break;
5206
5207 /* 18.8.45 xf CT_Xf */
5208 case '<xf': case '<xf/>':
5209 xf = y;
5210 delete xf[0];
5211 for(i = 0; i < cellXF_uint.length; ++i) if(xf[cellXF_uint[i]])
5212 xf[cellXF_uint[i]] = parseInt(xf[cellXF_uint[i]], 10);
5213 for(i = 0; i < cellXF_bool.length; ++i) if(xf[cellXF_bool[i]])
5214 xf[cellXF_bool[i]] = parsexmlbool(xf[cellXF_bool[i]]);
5215 if(xf.numFmtId > 0x188) {
5216 for(i = 0x188; i > 0x3c; --i) if(styles.NumberFmt[xf.numFmtId] == styles.NumberFmt[i]) { xf.numFmtId = i; break; }
5217 }
5218 styles.CellXf.push(xf); break;
5219 case '</xf>': break;
5220
5221 /* 18.8.1 alignment CT_CellAlignment */
5222 case '<alignment': case '<alignment/>':
5223 var alignment = {};
5224 if(y.vertical) alignment.vertical = y.vertical;
5225 if(y.horizontal) alignment.horizontal = y.horizontal;
5226 if(y.textRotation != null) alignment.textRotation = y.textRotation;
5227 if(y.indent) alignment.indent = y.indent;
5228 if(y.wrapText) alignment.wrapText = parsexmlbool(y.wrapText);
5229 xf.alignment = alignment;
5230 break;
5231 case '</alignment>': break;
5232
5233 /* 18.8.33 protection CT_CellProtection */
5234 case '<protection':
5235 break;
5236 case '</protection>': case '<protection/>': break;
5237
5238 /* note: sometimes mc:AlternateContent appears bare */
5239 case '<AlternateContent': pass = true; break;
5240 case '</AlternateContent>': pass = false; break;
5241
5242 /* 18.2.10 extLst CT_ExtensionList ? */
5243 case '<extLst': case '<extLst>': case '</extLst>': break;
5244 case '<ext': pass = true; break;
5245 case '</ext>': pass = false; break;
5246 default: if(opts && opts.WTF) {
5247 if(!pass) throw new Error('unrecognized ' + y[0] + ' in cellXfs');
5248 }
5249 }
5250 });
5251}
5252
5253function write_cellXfs(cellXfs) {
5254 var o = [];
5255 o[o.length] = (writextag('cellXfs',null));
5256 cellXfs.forEach(function(c) {
5257 o[o.length] = (writextag('xf', null, c));
5258 });
5259 o[o.length] = ("</cellXfs>");
5260 if(o.length === 2) return "";
5261 o[0] = writextag('cellXfs',null, {count:o.length-2}).replace("/>",">");
5262 return o.join("");
5263}
5264
5265/* 18.8 Styles CT_Stylesheet*/
5266var parse_sty_xml= (function make_pstyx() {
5267var numFmtRegex = /<(?:\w+:)?numFmts([^>]*)>[\S\s]*?<\/(?:\w+:)?numFmts>/;
5268var cellXfRegex = /<(?:\w+:)?cellXfs([^>]*)>[\S\s]*?<\/(?:\w+:)?cellXfs>/;
5269var fillsRegex = /<(?:\w+:)?fills([^>]*)>[\S\s]*?<\/(?:\w+:)?fills>/;
5270var fontsRegex = /<(?:\w+:)?fonts([^>]*)>[\S\s]*?<\/(?:\w+:)?fonts>/;
5271var bordersRegex = /<(?:\w+:)?borders([^>]*)>[\S\s]*?<\/(?:\w+:)?borders>/;
5272
5273return function parse_sty_xml(data, themes, opts) {
5274 var styles = {};
5275 if(!data) return styles;
5276 data = data.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
5277 /* 18.8.39 styleSheet CT_Stylesheet */
5278 var t;
5279
5280 /* 18.8.31 numFmts CT_NumFmts ? */
5281 if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts);
5282
5283 /* 18.8.23 fonts CT_Fonts ? */
5284 if((t=data.match(fontsRegex))) parse_fonts(t, styles, themes, opts);
5285
5286 /* 18.8.21 fills CT_Fills ? */
5287 if((t=data.match(fillsRegex))) parse_fills(t, styles, themes, opts);
5288
5289 /* 18.8.5 borders CT_Borders ? */
5290 if((t=data.match(bordersRegex))) parse_borders(t, styles, themes, opts);
5291
5292 /* 18.8.9 cellStyleXfs CT_CellStyleXfs ? */
5293 /* 18.8.8 cellStyles CT_CellStyles ? */
5294
5295 /* 18.8.10 cellXfs CT_CellXfs ? */
5296 if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts);
5297
5298 /* 18.8.15 dxfs CT_Dxfs ? */
5299 /* 18.8.42 tableStyles CT_TableStyles ? */
5300 /* 18.8.11 colors CT_Colors ? */
5301 /* 18.2.10 extLst CT_ExtensionList ? */
5302
5303 return styles;
5304};
5305})();
5306
5307var STYLES_XML_ROOT = writextag('styleSheet', null, {
5308 'xmlns': XMLNS.main[0],
5309 'xmlns:vt': XMLNS.vt
5310});
5311
5312RELS.STY = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
5313
5314function write_sty_xml(wb, opts) {
5315 var o = [XML_HEADER, STYLES_XML_ROOT], w;
5316 if(wb.SSF && (w = write_numFmts(wb.SSF)) != null) o[o.length] = w;
5317 o[o.length] = ('<fonts count="1"><font><sz val="12"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font></fonts>');
5318 o[o.length] = ('<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
5319 o[o.length] = ('<borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>');
5320 o[o.length] = ('<cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>');
5321 if((w = write_cellXfs(opts.cellXfs))) o[o.length] = (w);
5322 o[o.length] = ('<cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles>');
5323 o[o.length] = ('<dxfs count="0"/>');
5324 o[o.length] = ('<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleMedium4"/>');
5325
5326 if(o.length>2){ o[o.length] = ('</styleSheet>'); o[1]=o[1].replace("/>",">"); }
5327 return o.join("");
5328}
5329RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
5330
5331/* Even though theme layout is dk1 lt1 dk2 lt2, true order is lt1 dk1 lt2 dk2 */
5332var XLSXThemeClrScheme = [
5333 '</a:lt1>', '</a:dk1>', '</a:lt2>', '</a:dk2>',
5334 '</a:accent1>', '</a:accent2>', '</a:accent3>',
5335 '</a:accent4>', '</a:accent5>', '</a:accent6>',
5336 '</a:hlink>', '</a:folHlink>'
5337];
5338/* 20.1.6.2 clrScheme CT_ColorScheme */
5339function parse_clrScheme(t, themes, opts) {
5340 themes.themeElements.clrScheme = [];
5341 var color = {};
5342 (t[0].match(tagregex)||[]).forEach(function(x) {
5343 var y = parsexmltag(x);
5344 switch(y[0]) {
5345 /* 20.1.6.2 clrScheme (Color Scheme) CT_ColorScheme */
5346 case '<a:clrScheme': case '</a:clrScheme>': break;
5347
5348 /* 20.1.2.3.32 srgbClr CT_SRgbColor */
5349 case '<a:srgbClr':
5350 color.rgb = y.val; break;
5351
5352 /* 20.1.2.3.33 sysClr CT_SystemColor */
5353 case '<a:sysClr':
5354 color.rgb = y.lastClr; break;
5355
5356 /* 20.1.4.1.1 accent1 (Accent 1) */
5357 /* 20.1.4.1.2 accent2 (Accent 2) */
5358 /* 20.1.4.1.3 accent3 (Accent 3) */
5359 /* 20.1.4.1.4 accent4 (Accent 4) */
5360 /* 20.1.4.1.5 accent5 (Accent 5) */
5361 /* 20.1.4.1.6 accent6 (Accent 6) */
5362 /* 20.1.4.1.9 dk1 (Dark 1) */
5363 /* 20.1.4.1.10 dk2 (Dark 2) */
5364 /* 20.1.4.1.15 folHlink (Followed Hyperlink) */
5365 /* 20.1.4.1.19 hlink (Hyperlink) */
5366 /* 20.1.4.1.22 lt1 (Light 1) */
5367 /* 20.1.4.1.23 lt2 (Light 2) */
5368 case '<a:dk1>': case '</a:dk1>':
5369 case '<a:lt1>': case '</a:lt1>':
5370 case '<a:dk2>': case '</a:dk2>':
5371 case '<a:lt2>': case '</a:lt2>':
5372 case '<a:accent1>': case '</a:accent1>':
5373 case '<a:accent2>': case '</a:accent2>':
5374 case '<a:accent3>': case '</a:accent3>':
5375 case '<a:accent4>': case '</a:accent4>':
5376 case '<a:accent5>': case '</a:accent5>':
5377 case '<a:accent6>': case '</a:accent6>':
5378 case '<a:hlink>': case '</a:hlink>':
5379 case '<a:folHlink>': case '</a:folHlink>':
5380 if (y[0].charAt(1) === '/') {
5381 themes.themeElements.clrScheme[XLSXThemeClrScheme.indexOf(y[0])] = color;
5382 color = {};
5383 } else {
5384 color.name = y[0].slice(3, y[0].length - 1);
5385 }
5386 break;
5387
5388 default: if(opts && opts.WTF) throw new Error('Unrecognized ' + y[0] + ' in clrScheme');
5389 }
5390 });
5391}
5392
5393/* 20.1.4.1.18 fontScheme CT_FontScheme */
5394function parse_fontScheme() { }
5395
5396/* 20.1.4.1.15 fmtScheme CT_StyleMatrix */
5397function parse_fmtScheme() { }
5398
5399var clrsregex = /<a:clrScheme([^>]*)>[\s\S]*<\/a:clrScheme>/;
5400var fntsregex = /<a:fontScheme([^>]*)>[\s\S]*<\/a:fontScheme>/;
5401var fmtsregex = /<a:fmtScheme([^>]*)>[\s\S]*<\/a:fmtScheme>/;
5402
5403/* 20.1.6.10 themeElements CT_BaseStyles */
5404function parse_themeElements(data, themes, opts) {
5405 themes.themeElements = {};
5406
5407 var t;
5408
5409 [
5410 /* clrScheme CT_ColorScheme */
5411 ['clrScheme', clrsregex, parse_clrScheme],
5412 /* fontScheme CT_FontScheme */
5413 ['fontScheme', fntsregex, parse_fontScheme],
5414 /* fmtScheme CT_StyleMatrix */
5415 ['fmtScheme', fmtsregex, parse_fmtScheme]
5416 ].forEach(function(m) {
5417 if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements');
5418 m[2](t, themes, opts);
5419 });
5420}
5421
5422var themeltregex = /<a:themeElements([^>]*)>[\s\S]*<\/a:themeElements>/;
5423
5424/* 14.2.7 Theme Part */
5425function parse_theme_xml(data, opts) {
5426 /* 20.1.6.9 theme CT_OfficeStyleSheet */
5427 if(!data || data.length === 0) return parse_theme_xml(write_theme());
5428
5429 var t;
5430 var themes = {};
5431
5432 /* themeElements CT_BaseStyles */
5433 if(!(t=data.match(themeltregex))) throw new Error('themeElements not found in theme');
5434 parse_themeElements(t[0], themes, opts);
5435 themes.raw = data;
5436 return themes;
5437}
5438
5439function write_theme(Themes, opts) {
5440 if(opts && opts.themeXLSX) return opts.themeXLSX;
5441 if(Themes && typeof Themes.raw == "string") return Themes.raw;
5442 var o = [XML_HEADER];
5443 o[o.length] = '<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">';
5444 o[o.length] = '<a:themeElements>';
5445
5446 o[o.length] = '<a:clrScheme name="Office">';
5447 o[o.length] = '<a:dk1><a:sysClr val="windowText" lastClr="000000"/></a:dk1>';
5448 o[o.length] = '<a:lt1><a:sysClr val="window" lastClr="FFFFFF"/></a:lt1>';
5449 o[o.length] = '<a:dk2><a:srgbClr val="1F497D"/></a:dk2>';
5450 o[o.length] = '<a:lt2><a:srgbClr val="EEECE1"/></a:lt2>';
5451 o[o.length] = '<a:accent1><a:srgbClr val="4F81BD"/></a:accent1>';
5452 o[o.length] = '<a:accent2><a:srgbClr val="C0504D"/></a:accent2>';
5453 o[o.length] = '<a:accent3><a:srgbClr val="9BBB59"/></a:accent3>';
5454 o[o.length] = '<a:accent4><a:srgbClr val="8064A2"/></a:accent4>';
5455 o[o.length] = '<a:accent5><a:srgbClr val="4BACC6"/></a:accent5>';
5456 o[o.length] = '<a:accent6><a:srgbClr val="F79646"/></a:accent6>';
5457 o[o.length] = '<a:hlink><a:srgbClr val="0000FF"/></a:hlink>';
5458 o[o.length] = '<a:folHlink><a:srgbClr val="800080"/></a:folHlink>';
5459 o[o.length] = '</a:clrScheme>';
5460
5461 o[o.length] = '<a:fontScheme name="Office">';
5462 o[o.length] = '<a:majorFont>';
5463 o[o.length] = '<a:latin typeface="Cambria"/>';
5464 o[o.length] = '<a:ea typeface=""/>';
5465 o[o.length] = '<a:cs typeface=""/>';
5466 o[o.length] = '<a:font script="Jpan" typeface="MS Pゴシック"/>';
5467 o[o.length] = '<a:font script="Hang" typeface="맑은 고딕"/>';
5468 o[o.length] = '<a:font script="Hans" typeface="宋体"/>';
5469 o[o.length] = '<a:font script="Hant" typeface="新細明體"/>';
5470 o[o.length] = '<a:font script="Arab" typeface="Times New Roman"/>';
5471 o[o.length] = '<a:font script="Hebr" typeface="Times New Roman"/>';
5472 o[o.length] = '<a:font script="Thai" typeface="Tahoma"/>';
5473 o[o.length] = '<a:font script="Ethi" typeface="Nyala"/>';
5474 o[o.length] = '<a:font script="Beng" typeface="Vrinda"/>';
5475 o[o.length] = '<a:font script="Gujr" typeface="Shruti"/>';
5476 o[o.length] = '<a:font script="Khmr" typeface="MoolBoran"/>';
5477 o[o.length] = '<a:font script="Knda" typeface="Tunga"/>';
5478 o[o.length] = '<a:font script="Guru" typeface="Raavi"/>';
5479 o[o.length] = '<a:font script="Cans" typeface="Euphemia"/>';
5480 o[o.length] = '<a:font script="Cher" typeface="Plantagenet Cherokee"/>';
5481 o[o.length] = '<a:font script="Yiii" typeface="Microsoft Yi Baiti"/>';
5482 o[o.length] = '<a:font script="Tibt" typeface="Microsoft Himalaya"/>';
5483 o[o.length] = '<a:font script="Thaa" typeface="MV Boli"/>';
5484 o[o.length] = '<a:font script="Deva" typeface="Mangal"/>';
5485 o[o.length] = '<a:font script="Telu" typeface="Gautami"/>';
5486 o[o.length] = '<a:font script="Taml" typeface="Latha"/>';
5487 o[o.length] = '<a:font script="Syrc" typeface="Estrangelo Edessa"/>';
5488 o[o.length] = '<a:font script="Orya" typeface="Kalinga"/>';
5489 o[o.length] = '<a:font script="Mlym" typeface="Kartika"/>';
5490 o[o.length] = '<a:font script="Laoo" typeface="DokChampa"/>';
5491 o[o.length] = '<a:font script="Sinh" typeface="Iskoola Pota"/>';
5492 o[o.length] = '<a:font script="Mong" typeface="Mongolian Baiti"/>';
5493 o[o.length] = '<a:font script="Viet" typeface="Times New Roman"/>';
5494 o[o.length] = '<a:font script="Uigh" typeface="Microsoft Uighur"/>';
5495 o[o.length] = '<a:font script="Geor" typeface="Sylfaen"/>';
5496 o[o.length] = '</a:majorFont>';
5497 o[o.length] = '<a:minorFont>';
5498 o[o.length] = '<a:latin typeface="Calibri"/>';
5499 o[o.length] = '<a:ea typeface=""/>';
5500 o[o.length] = '<a:cs typeface=""/>';
5501 o[o.length] = '<a:font script="Jpan" typeface="MS Pゴシック"/>';
5502 o[o.length] = '<a:font script="Hang" typeface="맑은 고딕"/>';
5503 o[o.length] = '<a:font script="Hans" typeface="宋体"/>';
5504 o[o.length] = '<a:font script="Hant" typeface="新細明體"/>';
5505 o[o.length] = '<a:font script="Arab" typeface="Arial"/>';
5506 o[o.length] = '<a:font script="Hebr" typeface="Arial"/>';
5507 o[o.length] = '<a:font script="Thai" typeface="Tahoma"/>';
5508 o[o.length] = '<a:font script="Ethi" typeface="Nyala"/>';
5509 o[o.length] = '<a:font script="Beng" typeface="Vrinda"/>';
5510 o[o.length] = '<a:font script="Gujr" typeface="Shruti"/>';
5511 o[o.length] = '<a:font script="Khmr" typeface="DaunPenh"/>';
5512 o[o.length] = '<a:font script="Knda" typeface="Tunga"/>';
5513 o[o.length] = '<a:font script="Guru" typeface="Raavi"/>';
5514 o[o.length] = '<a:font script="Cans" typeface="Euphemia"/>';
5515 o[o.length] = '<a:font script="Cher" typeface="Plantagenet Cherokee"/>';
5516 o[o.length] = '<a:font script="Yiii" typeface="Microsoft Yi Baiti"/>';
5517 o[o.length] = '<a:font script="Tibt" typeface="Microsoft Himalaya"/>';
5518 o[o.length] = '<a:font script="Thaa" typeface="MV Boli"/>';
5519 o[o.length] = '<a:font script="Deva" typeface="Mangal"/>';
5520 o[o.length] = '<a:font script="Telu" typeface="Gautami"/>';
5521 o[o.length] = '<a:font script="Taml" typeface="Latha"/>';
5522 o[o.length] = '<a:font script="Syrc" typeface="Estrangelo Edessa"/>';
5523 o[o.length] = '<a:font script="Orya" typeface="Kalinga"/>';
5524 o[o.length] = '<a:font script="Mlym" typeface="Kartika"/>';
5525 o[o.length] = '<a:font script="Laoo" typeface="DokChampa"/>';
5526 o[o.length] = '<a:font script="Sinh" typeface="Iskoola Pota"/>';
5527 o[o.length] = '<a:font script="Mong" typeface="Mongolian Baiti"/>';
5528 o[o.length] = '<a:font script="Viet" typeface="Arial"/>';
5529 o[o.length] = '<a:font script="Uigh" typeface="Microsoft Uighur"/>';
5530 o[o.length] = '<a:font script="Geor" typeface="Sylfaen"/>';
5531 o[o.length] = '</a:minorFont>';
5532 o[o.length] = '</a:fontScheme>';
5533
5534 o[o.length] = '<a:fmtScheme name="Office">';
5535 o[o.length] = '<a:fillStyleLst>';
5536 o[o.length] = '<a:solidFill><a:schemeClr val="phClr"/></a:solidFill>';
5537 o[o.length] = '<a:gradFill rotWithShape="1">';
5538 o[o.length] = '<a:gsLst>';
5539 o[o.length] = '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="50000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
5540 o[o.length] = '<a:gs pos="35000"><a:schemeClr val="phClr"><a:tint val="37000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
5541 o[o.length] = '<a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="15000"/><a:satMod val="350000"/></a:schemeClr></a:gs>';
5542 o[o.length] = '</a:gsLst>';
5543 o[o.length] = '<a:lin ang="16200000" scaled="1"/>';
5544 o[o.length] = '</a:gradFill>';
5545 o[o.length] = '<a:gradFill rotWithShape="1">';
5546 o[o.length] = '<a:gsLst>';
5547 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>';
5548 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>';
5549 o[o.length] = '</a:gsLst>';
5550 o[o.length] = '<a:lin ang="16200000" scaled="0"/>';
5551 o[o.length] = '</a:gradFill>';
5552 o[o.length] = '</a:fillStyleLst>';
5553 o[o.length] = '<a:lnStyleLst>';
5554 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>';
5555 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>';
5556 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>';
5557 o[o.length] = '</a:lnStyleLst>';
5558 o[o.length] = '<a:effectStyleLst>';
5559 o[o.length] = '<a:effectStyle>';
5560 o[o.length] = '<a:effectLst>';
5561 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>';
5562 o[o.length] = '</a:effectLst>';
5563 o[o.length] = '</a:effectStyle>';
5564 o[o.length] = '<a:effectStyle>';
5565 o[o.length] = '<a:effectLst>';
5566 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>';
5567 o[o.length] = '</a:effectLst>';
5568 o[o.length] = '</a:effectStyle>';
5569 o[o.length] = '<a:effectStyle>';
5570 o[o.length] = '<a:effectLst>';
5571 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>';
5572 o[o.length] = '</a:effectLst>';
5573 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>';
5574 o[o.length] = '<a:sp3d><a:bevelT w="63500" h="25400"/></a:sp3d>';
5575 o[o.length] = '</a:effectStyle>';
5576 o[o.length] = '</a:effectStyleLst>';
5577 o[o.length] = '<a:bgFillStyleLst>';
5578 o[o.length] = '<a:solidFill><a:schemeClr val="phClr"/></a:solidFill>';
5579 o[o.length] = '<a:gradFill rotWithShape="1">';
5580 o[o.length] = '<a:gsLst>';
5581 o[o.length] = '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="40000"/><a:satMod val="350000"/></a:schemeClr></a:gs>';
5582 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>';
5583 o[o.length] = '<a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="20000"/><a:satMod val="255000"/></a:schemeClr></a:gs>';
5584 o[o.length] = '</a:gsLst>';
5585 o[o.length] = '<a:path path="circle"><a:fillToRect l="50000" t="-80000" r="50000" b="180000"/></a:path>';
5586 o[o.length] = '</a:gradFill>';
5587 o[o.length] = '<a:gradFill rotWithShape="1">';
5588 o[o.length] = '<a:gsLst>';
5589 o[o.length] = '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="80000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
5590 o[o.length] = '<a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="30000"/><a:satMod val="200000"/></a:schemeClr></a:gs>';
5591 o[o.length] = '</a:gsLst>';
5592 o[o.length] = '<a:path path="circle"><a:fillToRect l="50000" t="50000" r="50000" b="50000"/></a:path>';
5593 o[o.length] = '</a:gradFill>';
5594 o[o.length] = '</a:bgFillStyleLst>';
5595 o[o.length] = '</a:fmtScheme>';
5596 o[o.length] = '</a:themeElements>';
5597
5598 o[o.length] = '<a:objectDefaults>';
5599 o[o.length] = '<a:spDef>';
5600 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>';
5601 o[o.length] = '</a:spDef>';
5602 o[o.length] = '<a:lnDef>';
5603 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>';
5604 o[o.length] = '</a:lnDef>';
5605 o[o.length] = '</a:objectDefaults>';
5606 o[o.length] = '<a:extraClrSchemeLst/>';
5607 o[o.length] = '</a:theme>';
5608 return o.join("");
5609}
5610/* 18.14 Supplementary Workbook Data */
5611function parse_xlink_xml() {
5612 //var opts = _opts || {};
5613 //if(opts.WTF) throw "XLSX External Link";
5614}
5615
5616/* [MS-XLSB] 2.1.7.25 External Link */
5617function parse_xlink_bin(data, rel, name, _opts) {
5618 if(!data) return data;
5619 var opts = _opts || {};
5620
5621 var pass = false, end = false;
5622
5623 recordhopper(data, function xlink_parse(val, R_n, RT) {
5624 if(end) return;
5625 switch(RT) {
5626 case 0x0167: /* 'BrtSupTabs' */
5627 case 0x016B: /* 'BrtExternTableStart' */
5628 case 0x016C: /* 'BrtExternTableEnd' */
5629 case 0x016E: /* 'BrtExternRowHdr' */
5630 case 0x016F: /* 'BrtExternCellBlank' */
5631 case 0x0170: /* 'BrtExternCellReal' */
5632 case 0x0171: /* 'BrtExternCellBool' */
5633 case 0x0172: /* 'BrtExternCellError' */
5634 case 0x0173: /* 'BrtExternCellString' */
5635 case 0x01D8: /* 'BrtExternValueMeta' */
5636 case 0x0241: /* 'BrtSupNameStart' */
5637 case 0x0242: /* 'BrtSupNameValueStart' */
5638 case 0x0243: /* 'BrtSupNameValueEnd' */
5639 case 0x0244: /* 'BrtSupNameNum' */
5640 case 0x0245: /* 'BrtSupNameErr' */
5641 case 0x0246: /* 'BrtSupNameSt' */
5642 case 0x0247: /* 'BrtSupNameNil' */
5643 case 0x0248: /* 'BrtSupNameBool' */
5644 case 0x0249: /* 'BrtSupNameFmla' */
5645 case 0x024A: /* 'BrtSupNameBits' */
5646 case 0x024B: /* 'BrtSupNameEnd' */
5647 break;
5648
5649 case 0x0023: /* 'BrtFRTBegin' */
5650 pass = true; break;
5651 case 0x0024: /* 'BrtFRTEnd' */
5652 pass = false; break;
5653
5654 default:
5655 if((R_n||"").indexOf("Begin") > 0){/* empty */}
5656 else if((R_n||"").indexOf("End") > 0){/* empty */}
5657 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT.toString(16) + " " + R_n);
5658 }
5659 }, opts);
5660}
5661/* 20.5 DrawingML - SpreadsheetML Drawing */
5662RELS.IMG = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
5663RELS.DRAW = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing";
5664
5665/* 20.5.2.35 wsDr CT_Drawing */
5666function parse_drawing(data, rels) {
5667 if(!data) return "??";
5668 /*
5669 Chartsheet Drawing:
5670 - 20.5.2.35 wsDr CT_Drawing
5671 - 20.5.2.1 absoluteAnchor CT_AbsoluteAnchor
5672 - 20.5.2.16 graphicFrame CT_GraphicalObjectFrame
5673 - 20.1.2.2.16 graphic CT_GraphicalObject
5674 - 20.1.2.2.17 graphicData CT_GraphicalObjectData
5675 - chart reference
5676 the actual type is based on the URI of the graphicData
5677 TODO: handle embedded charts and other types of graphics
5678 */
5679 var id = (data.match(/<c:chart [^>]*r:id="([^"]*)"/)||["",""])[1];
5680
5681 return rels['!id'][id].Target;
5682}
5683
5684/* L.5.5.2 SpreadsheetML Comments + VML Schema */
5685var _shapeid = 1024;
5686function write_comments_vml(rId, comments) {
5687 var csize = [21600, 21600];
5688 /* L.5.2.1.2 Path Attribute */
5689 var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(",");
5690 var o = [
5691 writextag("xml", null, { 'xmlns:v': XLMLNS.v, 'xmlns:o': XLMLNS.o, 'xmlns:x': XLMLNS.x, 'xmlns:mv': XLMLNS.mv }).replace(/\/>/,">"),
5692 writextag("o:shapelayout", writextag("o:idmap", null, {'v:ext':"edit", 'data':rId}), {'v:ext':"edit"}),
5693 writextag("v:shapetype", [
5694 writextag("v:stroke", null, {joinstyle:"miter"}),
5695 writextag("v:path", null, {gradientshapeok:"t", 'o:connecttype':"rect"})
5696 ].join(""), {id:"_x0000_t202", 'o:spt':202, coordsize:csize.join(","),path:bbox})
5697 ];
5698 while(_shapeid < rId * 1000) _shapeid += 1000;
5699
5700 comments.forEach(function(x) {
5701 var c = decode_cell(x[0]);
5702 var fillopts = {'color2':"#BEFF82", 'type':"gradient"};
5703 if(fillopts.type == "gradient") fillopts.angle = "-180";
5704 var fillparm = fillopts.type == "gradient" ? writextag("o:fill", null, {type:"gradientUnscaled", 'v:ext':"view"}) : null;
5705 var fillxml = writextag('v:fill', fillparm, fillopts);
5706
5707 var shadata = ({on:"t", 'obscured':"t"});
5708 ++_shapeid;
5709
5710 o = o.concat([
5711 '<v:shape' + wxt_helper({
5712 id:'_x0000_s' + _shapeid,
5713 type:"#_x0000_t202",
5714 style:"position:absolute; margin-left:80pt;margin-top:5pt;width:104pt;height:64pt;z-index:10" + (x[1].hidden ? ";visibility:hidden" : "") ,
5715 fillcolor:"#ECFAD4",
5716 strokecolor:"#edeaa1"
5717 }) + '>',
5718 fillxml,
5719 writextag("v:shadow", null, shadata),
5720 writextag("v:path", null, {'o:connecttype':"none"}),
5721 '<v:textbox><div style="text-align:left"></div></v:textbox>',
5722 '<x:ClientData ObjectType="Note">',
5723 '<x:MoveWithCells/>',
5724 '<x:SizeWithCells/>',
5725 /* Part 4 19.4.2.3 Anchor (Anchor) */
5726 writetag('x:Anchor', [c.c+1, 0, c.r+1, 0, c.c+3, 20, c.r+5, 20].join(",")),
5727 writetag('x:AutoFill', "False"),
5728 writetag('x:Row', String(c.r)),
5729 writetag('x:Column', String(c.c)),
5730 x[1].hidden ? '' : '<x:Visible/>',
5731 '</x:ClientData>',
5732 '</v:shape>'
5733 ]); });
5734 o.push('</xml>');
5735 return o.join("");
5736}
5737RELS.CMNT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
5738
5739function sheet_insert_comments(sheet, comments) {
5740 var dense = Array.isArray(sheet);
5741 var cell;
5742 comments.forEach(function(comment) {
5743 var r = decode_cell(comment.ref);
5744 if(dense) {
5745 if(!sheet[r.r]) sheet[r.r] = [];
5746 cell = sheet[r.r][r.c];
5747 } else cell = sheet[comment.ref];
5748 if (!cell) {
5749 cell = ({t:"z"});
5750 if(dense) sheet[r.r][r.c] = cell;
5751 else sheet[comment.ref] = cell;
5752 var range = safe_decode_range(sheet["!ref"]||"BDWGO1000001:A1");
5753 if(range.s.r > r.r) range.s.r = r.r;
5754 if(range.e.r < r.r) range.e.r = r.r;
5755 if(range.s.c > r.c) range.s.c = r.c;
5756 if(range.e.c < r.c) range.e.c = r.c;
5757 var encoded = encode_range(range);
5758 if (encoded !== sheet["!ref"]) sheet["!ref"] = encoded;
5759 }
5760
5761 if (!cell.c) cell.c = [];
5762 var o = ({a: comment.author, t: comment.t, r: comment.r});
5763 if(comment.h) o.h = comment.h;
5764 cell.c.push(o);
5765 });
5766}
5767
5768/* 18.7 Comments */
5769function parse_comments_xml(data, opts) {
5770 /* 18.7.6 CT_Comments */
5771 if(data.match(/<(?:\w+:)?comments *\/>/)) return [];
5772 var authors = [];
5773 var commentList = [];
5774 var authtag = data.match(/<(?:\w+:)?authors>([\s\S]*)<\/(?:\w+:)?authors>/);
5775 if(authtag && authtag[1]) authtag[1].split(/<\/\w*:?author>/).forEach(function(x) {
5776 if(x === "" || x.trim() === "") return;
5777 var a = x.match(/<(?:\w+:)?author[^>]*>(.*)/);
5778 if(a) authors.push(a[1]);
5779 });
5780 var cmnttag = data.match(/<(?:\w+:)?commentList>([\s\S]*)<\/(?:\w+:)?commentList>/);
5781 if(cmnttag && cmnttag[1]) cmnttag[1].split(/<\/\w*:?comment>/).forEach(function(x) {
5782 if(x === "" || x.trim() === "") return;
5783 var cm = x.match(/<(?:\w+:)?comment[^>]*>/);
5784 if(!cm) return;
5785 var y = parsexmltag(cm[0]);
5786 var comment = ({ author: y.authorId && authors[y.authorId] || "sheetjsghost", ref: y.ref, guid: y.guid });
5787 var cell = decode_cell(y.ref);
5788 if(opts.sheetRows && opts.sheetRows <= cell.r) return;
5789 var textMatch = x.match(/<(?:\w+:)?text>([\s\S]*)<\/(?:\w+:)?text>/);
5790 var rt = !!textMatch && !!textMatch[1] && parse_si(textMatch[1]) || {r:"",t:"",h:""};
5791 comment.r = rt.r;
5792 if(rt.r == "<t></t>") rt.t = rt.h = "";
5793 comment.t = rt.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n");
5794 if(opts.cellHTML) comment.h = rt.h;
5795 commentList.push(comment);
5796 });
5797 return commentList;
5798}
5799
5800var CMNT_XML_ROOT = writextag('comments', null, { 'xmlns': XMLNS.main[0] });
5801function write_comments_xml(data) {
5802 var o = [XML_HEADER, CMNT_XML_ROOT];
5803
5804 var iauthor = [];
5805 o.push("<authors>");
5806 data.forEach(function(x) { x[1].forEach(function(w) { var a = escapexml(w.a);
5807 if(iauthor.indexOf(a) > -1) return;
5808 iauthor.push(a);
5809 o.push("<author>" + a + "</author>");
5810 }); });
5811 o.push("</authors>");
5812 o.push("<commentList>");
5813 data.forEach(function(d) {
5814 d[1].forEach(function(c) {
5815 /* 18.7.3 CT_Comment */
5816 o.push('<comment ref="' + d[0] + '" authorId="' + iauthor.indexOf(escapexml(c.a)) + '"><text>');
5817 o.push(writetag("t", c.t == null ? "" : escapexml(c.t)));
5818 o.push('</text></comment>');
5819 });
5820 });
5821 o.push("</commentList>");
5822 if(o.length>2) { o[o.length] = ('</comments>'); o[1]=o[1].replace("/>",">"); }
5823 return o.join("");
5824}
5825var CT_VBA = "application/vnd.ms-office.vbaProject";
5826function make_vba_xls(cfb) {
5827 var newcfb = CFB.utils.cfb_new({root:"R"});
5828 cfb.FullPaths.forEach(function(p, i) {
5829 if(p.slice(-1) === "/" || !p.match(/_VBA_PROJECT_CUR/)) return;
5830 var newpath = p.replace(/^[^\/]*/,"R").replace(/\/_VBA_PROJECT_CUR\u0000*/, "");
5831 CFB.utils.cfb_add(newcfb, newpath, cfb.FileIndex[i].content);
5832 });
5833 return CFB.write(newcfb);
5834}
5835
5836function fill_vba_xls(cfb, vba) {
5837 vba.FullPaths.forEach(function(p, i) {
5838 if(i == 0) return;
5839 var newpath = p.replace(/[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
5840 if(newpath.slice(-1) !== "/") CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content);
5841 });
5842}
5843
5844var VBAFMTS = [ "xlsb", "xlsm", "xlam", "biff8", "xla" ];
5845
5846RELS.DS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet";
5847RELS.MS = "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet";
5848
5849/* macro and dialog sheet stubs */
5850function parse_ds_bin() { return {'!type':'dialog'}; }
5851function parse_ds_xml() { return {'!type':'dialog'}; }
5852function parse_ms_bin() { return {'!type':'macro'}; }
5853function parse_ms_xml() { return {'!type':'macro'}; }
5854/* TODO: it will be useful to parse the function str */
5855var rc_to_a1 = (function(){
5856 var rcregex = /(^|[^A-Za-z_])R(\[?-?\d+\]|[1-9]\d*|)C(\[?-?\d+\]|[1-9]\d*|)(?![A-Za-z0-9_])/g;
5857 var rcbase = ({r:0,c:0});
5858 function rcfunc($$,$1,$2,$3) {
5859 var cRel = false, rRel = false;
5860
5861 if($2.length == 0) rRel = true;
5862 else if($2.charAt(0) == "[") { rRel = true; $2 = $2.slice(1, -1); }
5863
5864 if($3.length == 0) cRel = true;
5865 else if($3.charAt(0) == "[") { cRel = true; $3 = $3.slice(1, -1); }
5866
5867 var R = $2.length>0?parseInt($2,10)|0:0, C = $3.length>0?parseInt($3,10)|0:0;
5868
5869 if(cRel) C += rcbase.c; else --C;
5870 if(rRel) R += rcbase.r; else --R;
5871 return $1 + (cRel ? "" : "$") + encode_col(C) + (rRel ? "" : "$") + encode_row(R);
5872 }
5873 return function rc_to_a1(fstr, base) {
5874 rcbase = base;
5875 return fstr.replace(rcregex, rcfunc);
5876 };
5877})();
5878
5879var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)(10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})(?![_.\(A-Za-z0-9])/g;
5880var a1_to_rc =(function(){
5881 return function a1_to_rc(fstr, base) {
5882 return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
5883 var c = decode_col($3) - ($2 ? 0 : base.c);
5884 var r = decode_row($5) - ($4 ? 0 : base.r);
5885 var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1));
5886 var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1));
5887 return $1 + "R" + R + "C" + C;
5888 });
5889 };
5890})();
5891
5892/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
5893function shift_formula_str(f, delta) {
5894 return f.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
5895 return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
5896 });
5897}
5898
5899function shift_formula_xlsx(f, range, cell) {
5900 var r = decode_range(range), s = r.s, c = decode_cell(cell);
5901 var delta = {r:c.r - s.r, c:c.c - s.c};
5902 return shift_formula_str(f, delta);
5903}
5904
5905/* TODO: parse formula */
5906function fuzzyfmla(f) {
5907 if(f.length == 1) return false;
5908 return true;
5909}
5910
5911function _xlfn(f) {
5912 return f.replace(/_xlfn\./g,"");
5913}
5914var strs = {}; // shared strings
5915var _ssfopts = {}; // spreadsheet formatting options
5916
5917RELS.WS = [
5918 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
5919 "http://purl.oclc.org/ooxml/officeDocument/relationships/worksheet"
5920];
5921
5922/*global Map */
5923var browser_has_Map = typeof Map !== 'undefined';
5924
5925function get_sst_id(sst, str, rev) {
5926 var i = 0, len = sst.length;
5927 if(rev) {
5928 if(browser_has_Map ? rev.has(str) : Object.prototype.hasOwnProperty.call(rev, str)) {
5929 var revarr = browser_has_Map ? rev.get(str) : rev[str];
5930 for(; i < revarr.length; ++i) {
5931 if(sst[revarr[i]].t === str) { sst.Count ++; return revarr[i]; }
5932 }
5933 }
5934 } else for(; i < len; ++i) {
5935 if(sst[i].t === str) { sst.Count ++; return i; }
5936 }
5937 sst[len] = ({t:str}); sst.Count ++; sst.Unique ++;
5938 if(rev) {
5939 if(browser_has_Map) {
5940 if(!rev.has(str)) rev.set(str, []);
5941 rev.get(str).push(len);
5942 } else {
5943 if(!Object.prototype.hasOwnProperty.call(rev, str)) rev[str] = [];
5944 rev[str].push(len);
5945 }
5946 }
5947 return len;
5948}
5949
5950function col_obj_w(C, col) {
5951 var p = ({min:C+1,max:C+1});
5952 /* wch (chars), wpx (pixels) */
5953 var wch = -1;
5954 if(col.MDW) MDW = col.MDW;
5955 if(col.width != null) p.customWidth = 1;
5956 else if(col.wpx != null) wch = px2char(col.wpx);
5957 else if(col.wch != null) wch = col.wch;
5958 if(wch > -1) { p.width = char2width(wch); p.customWidth = 1; }
5959 else if(col.width != null) p.width = col.width;
5960 if(col.hidden) p.hidden = true;
5961 return p;
5962}
5963
5964function default_margins(margins, mode) {
5965 if(!margins) return;
5966 var defs = [0.7, 0.7, 0.75, 0.75, 0.3, 0.3];
5967 if(mode == 'xlml') defs = [1, 1, 1, 1, 0.5, 0.5];
5968 if(margins.left == null) margins.left = defs[0];
5969 if(margins.right == null) margins.right = defs[1];
5970 if(margins.top == null) margins.top = defs[2];
5971 if(margins.bottom == null) margins.bottom = defs[3];
5972 if(margins.header == null) margins.header = defs[4];
5973 if(margins.footer == null) margins.footer = defs[5];
5974}
5975
5976function get_cell_style(styles, cell, opts) {
5977 var z = opts.revssf[cell.z != null ? cell.z : "General"];
5978 var i = 0x3c, len = styles.length;
5979 if(z == null && opts.ssf) {
5980 for(; i < 0x188; ++i) if(opts.ssf[i] == null) {
5981 SSF.load(cell.z, i);
5982 // $FlowIgnore
5983 opts.ssf[i] = cell.z;
5984 opts.revssf[cell.z] = z = i;
5985 break;
5986 }
5987 }
5988 for(i = 0; i != len; ++i) if(styles[i].numFmtId === z) return i;
5989 styles[len] = {
5990 numFmtId:z,
5991 fontId:0,
5992 fillId:0,
5993 borderId:0,
5994 xfId:0,
5995 applyNumberFormat:1
5996 };
5997 return len;
5998}
5999
6000function safe_format(p, fmtid, fillid, opts, themes, styles) {
6001 try {
6002 if(opts.cellNF) p.z = SSF._table[fmtid];
6003 } catch(e) { if(opts.WTF) throw e; }
6004 if(p.t === 'z') return;
6005 if(p.t === 'd' && typeof p.v === 'string') p.v = parseDate(p.v);
6006 if(!opts || opts.cellText !== false) try {
6007 if(SSF._table[fmtid] == null) SSF.load(SSFImplicit[fmtid] || "General", fmtid);
6008 if(p.t === 'e') p.w = p.w || BErr[p.v];
6009 else if(fmtid === 0) {
6010 if(p.t === 'n') {
6011 if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
6012 else p.w = SSF._general_num(p.v);
6013 }
6014 else if(p.t === 'd') {
6015 var dd = datenum(p.v);
6016 if((dd|0) === dd) p.w = SSF._general_int(dd);
6017 else p.w = SSF._general_num(dd);
6018 }
6019 else if(p.v === undefined) return "";
6020 else p.w = SSF._general(p.v,_ssfopts);
6021 }
6022 else if(p.t === 'd') p.w = SSF.format(fmtid,datenum(p.v),_ssfopts);
6023 else p.w = SSF.format(fmtid,p.v,_ssfopts);
6024 } catch(e) { if(opts.WTF) throw e; }
6025 if(!opts.cellStyles) return;
6026 if(fillid != null) try {
6027 p.s = styles.Fills[fillid];
6028 if (p.s.fgColor && p.s.fgColor.theme && !p.s.fgColor.rgb) {
6029 p.s.fgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.fgColor.theme].rgb, p.s.fgColor.tint || 0);
6030 if(opts.WTF) p.s.fgColor.raw_rgb = themes.themeElements.clrScheme[p.s.fgColor.theme].rgb;
6031 }
6032 if (p.s.bgColor && p.s.bgColor.theme) {
6033 p.s.bgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.bgColor.theme].rgb, p.s.bgColor.tint || 0);
6034 if(opts.WTF) p.s.bgColor.raw_rgb = themes.themeElements.clrScheme[p.s.bgColor.theme].rgb;
6035 }
6036 } catch(e) { if(opts.WTF && styles.Fills) throw e; }
6037}
6038
6039function check_ws(ws, sname, i) {
6040 if(ws && ws['!ref']) {
6041 var range = safe_decode_range(ws['!ref']);
6042 if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
6043 }
6044}
6045function parse_ws_xml_dim(ws, s) {
6046 var d = safe_decode_range(s);
6047 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);
6048}
6049var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*[\/]?>/g;
6050var sheetdataregex = /<(?:\w+:)?sheetData[^>]*>([\s\S]*)<\/(?:\w+:)?sheetData>/;
6051var hlinkregex = /<(?:\w:)?hyperlink [^>]*>/mg;
6052var dimregex = /"(\w*:\w*)"/;
6053var colregex = /<(?:\w:)?col\b[^>]*[\/]?>/g;
6054var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
6055var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g;
6056var sheetprregex = /<(?:\w:)?sheetPr\b(?:[^>a-z][^>]*)?\/>/;
6057var svsregex = /<(?:\w:)?sheetViews[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetViews)>/;
6058
6059/* 18.3 Worksheets */
6060function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) {
6061 if(!data) return data;
6062 if(!rels) rels = {'!id':{}};
6063 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
6064
6065 /* 18.3.1.99 worksheet CT_Worksheet */
6066 var s = opts.dense ? ([]) : ({});
6067 var refguess = ({s: {r:2000000, c:2000000}, e: {r:0, c:0} });
6068
6069 var data1 = "", data2 = "";
6070 var mtch = data.match(sheetdataregex);
6071 if(mtch) {
6072 data1 = data.slice(0, mtch.index);
6073 data2 = data.slice(mtch.index + mtch[0].length);
6074 } else data1 = data2 = data;
6075
6076 /* 18.3.1.82 sheetPr CT_SheetPr */
6077 var sheetPr = data1.match(sheetprregex);
6078 if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
6079
6080 /* 18.3.1.35 dimension CT_SheetDimension */
6081 var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
6082 if(ridx > 0) {
6083 var ref = data1.slice(ridx,ridx+50).match(dimregex);
6084 if(ref) parse_ws_xml_dim(s, ref[1]);
6085 }
6086
6087 /* 18.3.1.88 sheetViews CT_SheetViews */
6088 var svs = data1.match(svsregex);
6089 if(svs && svs[1]) parse_ws_xml_sheetviews(svs[1], wb);
6090
6091 /* 18.3.1.17 cols CT_Cols */
6092 var columns = [];
6093 if(opts.cellStyles) {
6094 /* 18.3.1.13 col CT_Col */
6095 var cols = data1.match(colregex);
6096 if(cols) parse_ws_xml_cols(columns, cols);
6097 }
6098
6099 /* 18.3.1.80 sheetData CT_SheetData ? */
6100 if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
6101
6102 /* 18.3.1.2 autoFilter CT_AutoFilter */
6103 var afilter = data2.match(afregex);
6104 if(afilter) s['!autofilter'] = parse_ws_xml_autofilter(afilter[0]);
6105
6106 /* 18.3.1.55 mergeCells CT_MergeCells */
6107 var merges = [];
6108 var _merge = data2.match(mergecregex);
6109 if(_merge) for(ridx = 0; ridx != _merge.length; ++ridx)
6110 merges[ridx] = safe_decode_range(_merge[ridx].slice(_merge[ridx].indexOf("\"")+1));
6111
6112 /* 18.3.1.48 hyperlinks CT_Hyperlinks */
6113 var hlink = data2.match(hlinkregex);
6114 if(hlink) parse_ws_xml_hlinks(s, hlink, rels);
6115
6116 /* 18.3.1.62 pageMargins CT_PageMargins */
6117 var margins = data2.match(marginregex);
6118 if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));
6119
6120 if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
6121 if(opts.sheetRows > 0 && s["!ref"]) {
6122 var tmpref = safe_decode_range(s["!ref"]);
6123 if(opts.sheetRows <= +tmpref.e.r) {
6124 tmpref.e.r = opts.sheetRows - 1;
6125 if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
6126 if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
6127 if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c;
6128 if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c;
6129 s["!fullref"] = s["!ref"];
6130 s["!ref"] = encode_range(tmpref);
6131 }
6132 }
6133 if(columns.length > 0) s["!cols"] = columns;
6134 if(merges.length > 0) s["!merges"] = merges;
6135 return s;
6136}
6137
6138function write_ws_xml_merges(merges) {
6139 if(merges.length === 0) return "";
6140 var o = '<mergeCells count="' + merges.length + '">';
6141 for(var i = 0; i != merges.length; ++i) o += '<mergeCell ref="' + encode_range(merges[i]) + '"/>';
6142 return o + '</mergeCells>';
6143}
6144
6145/* 18.3.1.82-3 sheetPr CT_ChartsheetPr / CT_SheetPr */
6146function parse_ws_xml_sheetpr(sheetPr, s, wb, idx) {
6147 var data = parsexmltag(sheetPr);
6148 if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
6149 if(data.codeName) wb.Sheets[idx].CodeName = data.codeName;
6150}
6151function write_ws_xml_sheetpr(ws, wb, idx, opts, o) {
6152 var needed = false;
6153 var props = {}, payload = null;
6154 if(opts.bookType !== 'xlsx' && wb.vbaraw) {
6155 var cname = wb.SheetNames[idx];
6156 try { if(wb.Workbook) cname = wb.Workbook.Sheets[idx].CodeName || cname; } catch(e) {}
6157 needed = true;
6158 props.codeName = escapexml(cname);
6159 }
6160
6161 if(!needed && !payload) return;
6162 o[o.length] = (writextag('sheetPr', payload, props));
6163}
6164
6165/* 18.3.1.85 sheetProtection CT_SheetProtection */
6166var sheetprot_deffalse = ["objects", "scenarios", "selectLockedCells", "selectUnlockedCells"];
6167var sheetprot_deftrue = [
6168 "formatColumns", "formatRows", "formatCells",
6169 "insertColumns", "insertRows", "insertHyperlinks",
6170 "deleteColumns", "deleteRows",
6171 "sort", "autoFilter", "pivotTables"
6172];
6173function write_ws_xml_protection(sp) {
6174 // algorithmName, hashValue, saltValue, spinCountpassword
6175 var o = ({sheet:1});
6176 sheetprot_deffalse.forEach(function(n) { if(sp[n] != null && sp[n]) o[n] = "1"; });
6177 sheetprot_deftrue.forEach(function(n) { if(sp[n] != null && !sp[n]) o[n] = "0"; });
6178 /* TODO: algorithm */
6179 if(sp.password) o.password = crypto_CreatePasswordVerifier_Method1(sp.password).toString(16).toUpperCase();
6180 return writextag('sheetProtection', null, o);
6181}
6182
6183function parse_ws_xml_hlinks(s, data, rels) {
6184 var dense = Array.isArray(s);
6185 for(var i = 0; i != data.length; ++i) {
6186 var val = parsexmltag(utf8read(data[i]), true);
6187 if(!val.ref) return;
6188 var rel = ((rels || {})['!id']||[])[val.id];
6189 if(rel) {
6190 val.Target = rel.Target;
6191 if(val.location) val.Target += "#"+val.location;
6192 } else {
6193 val.Target = "#" + val.location;
6194 rel = {Target: val.Target, TargetMode: 'Internal'};
6195 }
6196 val.Rel = rel;
6197 if(val.tooltip) { val.Tooltip = val.tooltip; delete val.tooltip; }
6198 var rng = safe_decode_range(val.ref);
6199 for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
6200 var addr = encode_cell({c:C,r:R});
6201 if(dense) {
6202 if(!s[R]) s[R] = [];
6203 if(!s[R][C]) s[R][C] = {t:"z",v:undefined};
6204 s[R][C].l = val;
6205 } else {
6206 if(!s[addr]) s[addr] = {t:"z",v:undefined};
6207 s[addr].l = val;
6208 }
6209 }
6210 }
6211}
6212
6213function parse_ws_xml_margins(margin) {
6214 var o = {};
6215 ["left", "right", "top", "bottom", "header", "footer"].forEach(function(k) {
6216 if(margin[k]) o[k] = parseFloat(margin[k]);
6217 });
6218 return o;
6219}
6220function write_ws_xml_margins(margin) {
6221 default_margins(margin);
6222 return writextag('pageMargins', null, margin);
6223}
6224
6225function parse_ws_xml_cols(columns, cols) {
6226 var seencol = false;
6227 for(var coli = 0; coli != cols.length; ++coli) {
6228 var coll = parsexmltag(cols[coli], true);
6229 if(coll.hidden) coll.hidden = parsexmlbool(coll.hidden);
6230 var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
6231 delete coll.min; delete coll.max; coll.width = +coll.width;
6232 if(!seencol && coll.width) { seencol = true; find_mdw_colw(coll.width); }
6233 process_col(coll);
6234 while(colm <= colM) columns[colm++] = dup(coll);
6235 }
6236}
6237function write_ws_xml_cols(ws, cols) {
6238 var o = ["<cols>"], col;
6239 for(var i = 0; i != cols.length; ++i) {
6240 if(!(col = cols[i])) continue;
6241 o[o.length] = (writextag('col', null, col_obj_w(i, col)));
6242 }
6243 o[o.length] = "</cols>";
6244 return o.join("");
6245}
6246
6247function parse_ws_xml_autofilter(data) {
6248 var o = { ref: (data.match(/ref="([^"]*)"/)||[])[1]};
6249 return o;
6250}
6251function write_ws_xml_autofilter(data, ws, wb, idx) {
6252 var ref = typeof data.ref == "string" ? data.ref : encode_range(data.ref);
6253 if(!wb.Workbook) wb.Workbook = ({Sheets:[]});
6254 if(!wb.Workbook.Names) wb.Workbook.Names = [];
6255 var names = wb.Workbook.Names;
6256 var range = decode_range(ref);
6257 if(range.s.r == range.e.r) { range.e.r = decode_range(ws["!ref"]).e.r; ref = encode_range(range); }
6258 for(var i = 0; i < names.length; ++i) {
6259 var name = names[i];
6260 if(name.Name != '_xlnm._FilterDatabase') continue;
6261 if(name.Sheet != idx) continue;
6262 name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break;
6263 }
6264 if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref });
6265 return writextag("autoFilter", null, {ref:ref});
6266}
6267
6268/* 18.3.1.88 sheetViews CT_SheetViews */
6269/* 18.3.1.87 sheetView CT_SheetView */
6270var sviewregex = /<(?:\w:)?sheetView(?:[^>a-z][^>]*)?\/?>/;
6271function parse_ws_xml_sheetviews(data, wb) {
6272 if(!wb.Views) wb.Views = [{}];
6273 (data.match(sviewregex)||[]).forEach(function(r, i) {
6274 var tag = parsexmltag(r);
6275 // $FlowIgnore
6276 if(!wb.Views[i]) wb.Views[i] = {};
6277 // $FlowIgnore
6278 if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
6279 });
6280}
6281function write_ws_xml_sheetviews(ws, opts, idx, wb) {
6282 var sview = ({workbookViewId:"0"});
6283 // $FlowIgnore
6284 if((((wb||{}).Workbook||{}).Views||[])[0]) sview.rightToLeft = wb.Workbook.Views[0].RTL ? "1" : "0";
6285 return writextag("sheetViews", writextag("sheetView", null, sview), {});
6286}
6287
6288function write_ws_xml_cell(cell, ref, ws, opts) {
6289 if(cell.v === undefined && cell.f === undefined || cell.t === 'z') return "";
6290 var vv = "";
6291 var oldt = cell.t, oldv = cell.v;
6292 if(cell.t !== "z") switch(cell.t) {
6293 case 'b': vv = cell.v ? "1" : "0"; break;
6294 case 'n': vv = ''+cell.v; break;
6295 case 'e': vv = BErr[cell.v]; break;
6296 case 'd':
6297 if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
6298 else {
6299 cell = dup(cell);
6300 cell.t = 'n';
6301 vv = ''+(cell.v = datenum(parseDate(cell.v)));
6302 }
6303 if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
6304 break;
6305 default: vv = cell.v; break;
6306 }
6307 var v = writetag('v', escapexml(vv)), o = ({r:ref});
6308 /* TODO: cell style */
6309 var os = get_cell_style(opts.cellXfs, cell, opts);
6310 if(os !== 0) o.s = os;
6311 switch(cell.t) {
6312 case 'n': break;
6313 case 'd': o.t = "d"; break;
6314 case 'b': o.t = "b"; break;
6315 case 'e': o.t = "e"; break;
6316 case 'z': break;
6317 default: if(cell.v == null) { delete cell.t; break; }
6318 if(opts && opts.bookSST) {
6319 v = writetag('v', ''+get_sst_id(opts.Strings, cell.v, opts.revStrings));
6320 o.t = "s"; break;
6321 }
6322 o.t = "str"; break;
6323 }
6324 if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; }
6325 if(cell.f) {
6326 var ff = cell.F && cell.F.slice(0, ref.length) == ref ? {t:"array", ref:cell.F} : null;
6327 v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : "");
6328 }
6329 if(cell.l) ws['!links'].push([ref, cell.l]);
6330 if(cell.c) ws['!comments'].push([ref, cell.c]);
6331 return writextag('c', v, o);
6332}
6333
6334var parse_ws_xml_data = (function() {
6335 var cellregex = /<(?:\w+:)?c[ >]/, rowregex = /<\/(?:\w+:)?row>/;
6336 var rregex = /r=["']([^"']*)["']/, isregex = /<(?:\w+:)?is>([\S\s]*?)<\/(?:\w+:)?is>/;
6337 var refregex = /ref=["']([^"']*)["']/;
6338 var match_v = matchtag("v"), match_f = matchtag("f");
6339
6340return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
6341 var ri = 0, x = "", cells = [], cref = [], idx=0, i=0, cc=0, d="", p;
6342 var tag, tagr = 0, tagc = 0;
6343 var sstr, ftag;
6344 var fmtid = 0, fillid = 0;
6345 var do_format = Array.isArray(styles.CellXf), cf;
6346 var arrayf = [];
6347 var sharedf = [];
6348 var dense = Array.isArray(s);
6349 var rows = [], rowobj = {}, rowrite = false;
6350 for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
6351 x = marr[mt].trim();
6352 var xlen = x.length;
6353 if(xlen === 0) continue;
6354
6355 /* 18.3.1.73 row CT_Row */
6356 for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
6357 tag = parsexmltag(x.slice(0,ri), true);
6358 tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
6359 if(opts.sheetRows && opts.sheetRows < tagr) continue;
6360 if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
6361 if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
6362
6363 if(opts && opts.cellStyles) {
6364 rowobj = {}; rowrite = false;
6365 if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
6366 if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; }
6367 if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
6368 if(rowrite) rows[tagr-1] = rowobj;
6369 }
6370
6371 /* 18.3.1.4 c CT_Cell */
6372 cells = x.slice(ri).split(cellregex);
6373 for(var rslice = 0; rslice != cells.length; ++rslice) if(cells[rslice].trim().charAt(0) != "<") break;
6374 cells = cells.slice(rslice);
6375 for(ri = 0; ri != cells.length; ++ri) {
6376 x = cells[ri].trim();
6377 if(x.length === 0) continue;
6378 cref = x.match(rregex); idx = ri; i=0; cc=0;
6379 x = "<c " + (x.slice(0,1)=="<"?">":"") + x;
6380 if(cref != null && cref.length === 2) {
6381 idx = 0; d=cref[1];
6382 for(i=0; i != d.length; ++i) {
6383 if((cc=d.charCodeAt(i)-64) < 1 || cc > 26) break;
6384 idx = 26*idx + cc;
6385 }
6386 --idx;
6387 tagc = idx;
6388 } else ++tagc;
6389 for(i = 0; i != x.length; ++i) if(x.charCodeAt(i) === 62) break; ++i;
6390 tag = parsexmltag(x.slice(0,i), true);
6391 if(!tag.r) tag.r = encode_cell({r:tagr-1, c:tagc});
6392 d = x.slice(i);
6393 p = ({t:""});
6394
6395 if((cref=d.match(match_v))!= null && cref[1] !== '') p.v=unescapexml(cref[1]);
6396 if(opts.cellFormula) {
6397 if((cref=d.match(match_f))!= null && cref[1] !== '') {
6398 /* TODO: match against XLSXFutureFunctions */
6399 p.f=_xlfn(unescapexml(utf8read(cref[1])));
6400 if(cref[0].indexOf('t="array"') > -1) {
6401 p.F = (d.match(refregex)||[])[1];
6402 if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
6403 } else if(cref[0].indexOf('t="shared"') > -1) {
6404 // TODO: parse formula
6405 ftag = parsexmltag(cref[0]);
6406 sharedf[parseInt(ftag.si, 10)] = [ftag, _xlfn(unescapexml(utf8read(cref[1]))), tag.r];
6407 }
6408 } else if((cref=d.match(/<f[^>]*\/>/))) {
6409 ftag = parsexmltag(cref[0]);
6410 if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
6411 }
6412 /* TODO: factor out contains logic */
6413 var _tag = decode_cell(tag.r);
6414 for(i = 0; i < arrayf.length; ++i)
6415 if(_tag.r >= arrayf[i][0].s.r && _tag.r <= arrayf[i][0].e.r)
6416 if(_tag.c >= arrayf[i][0].s.c && _tag.c <= arrayf[i][0].e.c)
6417 p.F = arrayf[i][1];
6418 }
6419
6420 if(tag.t == null && p.v === undefined) {
6421 if(p.f || p.F) {
6422 p.v = 0; p.t = "n";
6423 } else if(!opts.sheetStubs) continue;
6424 else p.t = "z";
6425 }
6426 else p.t = tag.t || "n";
6427 if(guess.s.c > tagc) guess.s.c = tagc;
6428 if(guess.e.c < tagc) guess.e.c = tagc;
6429 /* 18.18.11 t ST_CellType */
6430 switch(p.t) {
6431 case 'n':
6432 if(p.v == "" || p.v == null) {
6433 if(!opts.sheetStubs) continue;
6434 p.t = 'z';
6435 } else p.v = parseFloat(p.v);
6436 break;
6437 case 's':
6438 if(typeof p.v == 'undefined') {
6439 if(!opts.sheetStubs) continue;
6440 p.t = 'z';
6441 } else {
6442 sstr = strs[parseInt(p.v, 10)];
6443 p.v = sstr.t;
6444 p.r = sstr.r;
6445 if(opts.cellHTML) p.h = sstr.h;
6446 }
6447 break;
6448 case 'str':
6449 p.t = "s";
6450 p.v = (p.v!=null) ? utf8read(p.v) : '';
6451 if(opts.cellHTML) p.h = escapehtml(p.v);
6452 break;
6453 case 'inlineStr':
6454 cref = d.match(isregex);
6455 p.t = 's';
6456 if(cref != null && (sstr = parse_si(cref[1]))) {
6457 p.v = sstr.t;
6458 if(opts.cellHTML) p.h = sstr.h;
6459 } else p.v = "";
6460 break;
6461 case 'b': p.v = parsexmlbool(p.v); break;
6462 case 'd':
6463 if(opts.cellDates) p.v = parseDate(p.v, 1);
6464 else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; }
6465 break;
6466 /* error string in .w, number in .v */
6467 case 'e':
6468 if(!opts || opts.cellText !== false) p.w = p.v;
6469 p.v = RBErr[p.v]; break;
6470 }
6471 /* formatting */
6472 fmtid = fillid = 0;
6473 cf = null;
6474 if(do_format && tag.s !== undefined) {
6475 cf = styles.CellXf[tag.s];
6476 if(cf != null) {
6477 if(cf.numFmtId != null) fmtid = cf.numFmtId;
6478 if(opts.cellStyles) {
6479 if(cf.fillId != null) fillid = cf.fillId;
6480 }
6481 }
6482 }
6483 safe_format(p, fmtid, fillid, opts, themes, styles);
6484 if(opts.cellDates && do_format && p.t == 'n' && SSF.is_date(SSF._table[fmtid])) { p.t = 'd'; p.v = numdate(p.v); }
6485 if(dense) {
6486 var _r = decode_cell(tag.r);
6487 if(!s[_r.r]) s[_r.r] = [];
6488 s[_r.r][_r.c] = p;
6489 } else s[tag.r] = p;
6490 }
6491 }
6492 if(rows.length > 0) s['!rows'] = rows;
6493}; })();
6494
6495function write_ws_xml_data(ws, opts, idx, wb) {
6496 var o = [], r = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols = [], R=0, C=0, rows = ws['!rows'];
6497 var dense = Array.isArray(ws);
6498 var params = ({r:rr}), row, height = -1;
6499 for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
6500 for(R = range.s.r; R <= range.e.r; ++R) {
6501 r = [];
6502 rr = encode_row(R);
6503 for(C = range.s.c; C <= range.e.c; ++C) {
6504 ref = cols[C] + rr;
6505 var _cell = dense ? (ws[R]||[])[C]: ws[ref];
6506 if(_cell === undefined) continue;
6507 if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
6508 }
6509 if(r.length > 0 || (rows && rows[R])) {
6510 params = ({r:rr});
6511 if(rows && rows[R]) {
6512 row = rows[R];
6513 if(row.hidden) params.hidden = 1;
6514 height = -1;
6515 if(row.hpx) height = px2pt(row.hpx);
6516 else if(row.hpt) height = row.hpt;
6517 if(height > -1) { params.ht = height; params.customHeight = 1; }
6518 if(row.level) { params.outlineLevel = row.level; }
6519 }
6520 o[o.length] = (writextag('row', r.join(""), params));
6521 }
6522 }
6523 if(rows) for(; R < rows.length; ++R) {
6524 if(rows && rows[R]) {
6525 params = ({r:R+1});
6526 row = rows[R];
6527 if(row.hidden) params.hidden = 1;
6528 height = -1;
6529 if (row.hpx) height = px2pt(row.hpx);
6530 else if (row.hpt) height = row.hpt;
6531 if (height > -1) { params.ht = height; params.customHeight = 1; }
6532 if (row.level) { params.outlineLevel = row.level; }
6533 o[o.length] = (writextag('row', "", params));
6534 }
6535 }
6536 return o.join("");
6537}
6538
6539var WS_XML_ROOT = writextag('worksheet', null, {
6540 'xmlns': XMLNS.main[0],
6541 'xmlns:r': XMLNS.r
6542});
6543
6544function write_ws_xml(idx, opts, wb, rels) {
6545 var o = [XML_HEADER, WS_XML_ROOT];
6546 var s = wb.SheetNames[idx], sidx = 0, rdata = "";
6547 var ws = wb.Sheets[s];
6548 if(ws == null) ws = {};
6549 var ref = ws['!ref'] || 'A1';
6550 var range = safe_decode_range(ref);
6551 if(range.e.c > 0x3FFF || range.e.r > 0xFFFFF) {
6552 if(opts.WTF) throw new Error("Range " + ref + " exceeds format limit A1:XFD1048576");
6553 range.e.c = Math.min(range.e.c, 0x3FFF);
6554 range.e.r = Math.min(range.e.c, 0xFFFFF);
6555 ref = encode_range(range);
6556 }
6557 if(!rels) rels = {};
6558 ws['!comments'] = [];
6559 var _drawing = [];
6560
6561 write_ws_xml_sheetpr(ws, wb, idx, opts, o);
6562
6563 o[o.length] = (writextag('dimension', null, {'ref': ref}));
6564
6565 o[o.length] = write_ws_xml_sheetviews(ws, opts, idx, wb);
6566
6567 /* TODO: store in WB, process styles */
6568 if(opts.sheetFormat) o[o.length] = (writextag('sheetFormatPr', null, {
6569 defaultRowHeight:opts.sheetFormat.defaultRowHeight||'16',
6570 baseColWidth:opts.sheetFormat.baseColWidth||'10',
6571 outlineLevelRow:opts.sheetFormat.outlineLevelRow||'7'
6572 }));
6573
6574 if(ws['!cols'] != null && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols']));
6575
6576 o[sidx = o.length] = '<sheetData/>';
6577 ws['!links'] = [];
6578 if(ws['!ref'] != null) {
6579 rdata = write_ws_xml_data(ws, opts, idx, wb, rels);
6580 if(rdata.length > 0) o[o.length] = (rdata);
6581 }
6582 if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
6583
6584 /* sheetCalcPr */
6585
6586 if(ws['!protect'] != null) o[o.length] = write_ws_xml_protection(ws['!protect']);
6587
6588 /* protectedRanges */
6589 /* scenarios */
6590
6591 if(ws['!autofilter'] != null) o[o.length] = write_ws_xml_autofilter(ws['!autofilter'], ws, wb, idx);
6592
6593 /* sortState */
6594 /* dataConsolidate */
6595 /* customSheetViews */
6596
6597 if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
6598
6599 /* phoneticPr */
6600 /* conditionalFormatting */
6601 /* dataValidations */
6602
6603 var relc = -1, rel, rId = -1;
6604 if(ws['!links'].length > 0) {
6605 o[o.length] = "<hyperlinks>";
6606ws['!links'].forEach(function(l) {
6607 if(!l[1].Target) return;
6608 rel = ({"ref":l[0]});
6609 if(l[1].Target.charAt(0) != "#") {
6610 rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), RELS.HLINK);
6611 rel["r:id"] = "rId"+rId;
6612 }
6613 if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1));
6614 if(l[1].Tooltip) rel.tooltip = escapexml(l[1].Tooltip);
6615 o[o.length] = writextag("hyperlink",null,rel);
6616 });
6617 o[o.length] = "</hyperlinks>";
6618 }
6619 delete ws['!links'];
6620
6621 /* printOptions */
6622
6623 if(ws['!margins'] != null) o[o.length] = write_ws_xml_margins(ws['!margins']);
6624
6625 /* pageSetup */
6626 /* headerFooter */
6627 /* rowBreaks */
6628 /* colBreaks */
6629 /* customProperties */
6630 /* cellWatches */
6631
6632 if(!opts || opts.ignoreEC || (opts.ignoreEC == (void 0))) o[o.length] = writetag("ignoredErrors", writextag("ignoredError", null, {numberStoredAsText:1, sqref:ref}));
6633
6634 /* smartTags */
6635
6636 if(_drawing.length > 0) {
6637 rId = add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
6638 o[o.length] = writextag("drawing", null, {"r:id":"rId" + rId});
6639 ws['!drawing'] = _drawing;
6640 }
6641
6642 if(ws['!comments'].length > 0) {
6643 rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML);
6644 o[o.length] = writextag("legacyDrawing", null, {"r:id":"rId" + rId});
6645 ws['!legacy'] = rId;
6646 }
6647
6648 /* legacyDrawingHF */
6649 /* picture */
6650 /* oleObjects */
6651 /* controls */
6652 /* webPublishItems */
6653 /* tableParts */
6654 /* extLst */
6655
6656 if(o.length>1) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
6657 return o.join("");
6658}
6659RELS.CHART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart";
6660RELS.CHARTEX = "http://schemas.microsoft.com/office/2014/relationships/chartEx";
6661
6662function parse_Cache(data) {
6663 var col = [];
6664 var num = data.match(/^<c:numCache>/);
6665 var f;
6666
6667 /* 21.2.2.150 pt CT_NumVal */
6668 (data.match(/<c:pt idx="(\d*)">(.*?)<\/c:pt>/mg)||[]).forEach(function(pt) {
6669 var q = pt.match(/<c:pt idx="(\d*?)"><c:v>(.*)<\/c:v><\/c:pt>/);
6670 if(!q) return;
6671 col[+q[1]] = num ? +q[2] : q[2];
6672 });
6673
6674 /* 21.2.2.71 formatCode CT_Xstring */
6675 var nf = unescapexml((data.match(/<c:formatCode>([\s\S]*?)<\/c:formatCode>/) || ["","General"])[1]);
6676
6677 (data.match(/<c:f>(.*?)<\/c:f>/mg)||[]).forEach(function(F) { f = F.replace(/<.*?>/g,""); });
6678
6679 return [col, nf, f];
6680}
6681
6682/* 21.2 DrawingML - Charts */
6683function parse_chart(data, name, opts, rels, wb, csheet) {
6684 var cs = ((csheet || {"!type":"chart"}));
6685 if(!data) return csheet;
6686 /* 21.2.2.27 chart CT_Chart */
6687
6688 var C = 0, R = 0, col = "A";
6689 var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
6690
6691 /* 21.2.2.120 numCache CT_NumData */
6692 (data.match(/<c:numCache>[\s\S]*?<\/c:numCache>/gm)||[]).forEach(function(nc) {
6693 var cache = parse_Cache(nc);
6694 refguess.s.r = refguess.s.c = 0;
6695 refguess.e.c = C;
6696 col = encode_col(C);
6697 cache[0].forEach(function(n,i) {
6698 cs[col + encode_row(i)] = {t:'n', v:n, z:cache[1] };
6699 R = i;
6700 });
6701 if(refguess.e.r < R) refguess.e.r = R;
6702 ++C;
6703 });
6704 if(C > 0) cs["!ref"] = encode_range(refguess);
6705 return cs;
6706}
6707RELS.CS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet";
6708
6709var CS_XML_ROOT = writextag('chartsheet', null, {
6710 'xmlns': XMLNS.main[0],
6711 'xmlns:r': XMLNS.r
6712});
6713
6714/* 18.3 Worksheets also covers Chartsheets */
6715function parse_cs_xml(data, opts, idx, rels, wb) {
6716 if(!data) return data;
6717 /* 18.3.1.12 chartsheet CT_ChartSheet */
6718 if(!rels) rels = {'!id':{}};
6719 var s = ({'!type':"chart", '!drawel':null, '!rel':""});
6720 var m;
6721
6722 /* 18.3.1.83 sheetPr CT_ChartsheetPr */
6723 var sheetPr = data.match(sheetprregex);
6724 if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
6725
6726 /* 18.3.1.36 drawing CT_Drawing */
6727 if((m = data.match(/drawing r:id="(.*?)"/))) s['!rel'] = m[1];
6728
6729 if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
6730 return s;
6731}
6732function write_cs_xml(idx, opts, wb, rels) {
6733 var o = [XML_HEADER, CS_XML_ROOT];
6734 o[o.length] = writextag("drawing", null, {"r:id": "rId1"});
6735 add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
6736 if(o.length>2) { o[o.length] = ('</chartsheet>'); o[1]=o[1].replace("/>",">"); }
6737 return o.join("");
6738}
6739
6740/* [MS-XLSB] 2.4.331 BrtCsProp */
6741function parse_BrtCsProp(data, length) {
6742 data.l += 10;
6743 var name = parse_XLWideString(data, length - 10);
6744 return { name: name };
6745}
6746
6747/* [MS-XLSB] 2.1.7.7 Chart Sheet */
6748function parse_cs_bin(data, opts, idx, rels, wb) {
6749 if(!data) return data;
6750 if(!rels) rels = {'!id':{}};
6751 var s = {'!type':"chart", '!drawel':null, '!rel':""};
6752 var state = [];
6753 var pass = false;
6754 recordhopper(data, function cs_parse(val, R_n, RT) {
6755 switch(RT) {
6756
6757 case 0x0226: /* 'BrtDrawing' */
6758 s['!rel'] = val; break;
6759
6760 case 0x028B: /* 'BrtCsProp' */
6761 if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
6762 if(val.name) wb.Sheets[idx].CodeName = val.name;
6763 break;
6764
6765 case 0x0232: /* 'BrtBkHim' */
6766 case 0x028C: /* 'BrtCsPageSetup' */
6767 case 0x029D: /* 'BrtCsProtection' */
6768 case 0x02A7: /* 'BrtCsProtectionIso' */
6769 case 0x0227: /* 'BrtLegacyDrawing' */
6770 case 0x0228: /* 'BrtLegacyDrawingHF' */
6771 case 0x01DC: /* 'BrtMargins' */
6772 case 0x0C00: /* 'BrtUid' */
6773 break;
6774
6775 case 0x0023: /* 'BrtFRTBegin' */
6776 pass = true; break;
6777 case 0x0024: /* 'BrtFRTEnd' */
6778 pass = false; break;
6779 case 0x0025: /* 'BrtACBegin' */
6780 state.push(R_n); break;
6781 case 0x0026: /* 'BrtACEnd' */
6782 state.pop(); break;
6783
6784 default:
6785 if((R_n||"").indexOf("Begin") > 0) state.push(R_n);
6786 else if((R_n||"").indexOf("End") > 0) state.pop();
6787 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
6788 }
6789 }, opts);
6790
6791 if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
6792 return s;
6793}
6794function write_cs_bin() {
6795 var ba = buf_array();
6796 write_record(ba, "BrtBeginSheet");
6797 /* [BrtCsProp] */
6798 /* CSVIEWS */
6799 /* [[BrtCsProtectionIso] BrtCsProtection] */
6800 /* [USERCSVIEWS] */
6801 /* [BrtMargins] */
6802 /* [BrtCsPageSetup] */
6803 /* [HEADERFOOTER] */
6804 /* BrtDrawing */
6805 /* [BrtLegacyDrawing] */
6806 /* [BrtLegacyDrawingHF] */
6807 /* [BrtBkHim] */
6808 /* [WEBPUBITEMS] */
6809 /* FRTCHARTSHEET */
6810 write_record(ba, "BrtEndSheet");
6811 return ba.end();
6812}
6813/* 18.2.28 (CT_WorkbookProtection) Defaults */
6814var WBPropsDef = [
6815 ['allowRefreshQuery', false, "bool"],
6816 ['autoCompressPictures', true, "bool"],
6817 ['backupFile', false, "bool"],
6818 ['checkCompatibility', false, "bool"],
6819 ['CodeName', ''],
6820 ['date1904', false, "bool"],
6821 ['defaultThemeVersion', 0, "int"],
6822 ['filterPrivacy', false, "bool"],
6823 ['hidePivotFieldList', false, "bool"],
6824 ['promptedSolutions', false, "bool"],
6825 ['publishItems', false, "bool"],
6826 ['refreshAllConnections', false, "bool"],
6827 ['saveExternalLinkValues', true, "bool"],
6828 ['showBorderUnselectedTables', true, "bool"],
6829 ['showInkAnnotation', true, "bool"],
6830 ['showObjects', 'all'],
6831 ['showPivotChartFilter', false, "bool"],
6832 ['updateLinks', 'userSet']
6833];
6834
6835/* 18.2.30 (CT_BookView) Defaults */
6836var WBViewDef = [
6837 ['activeTab', 0, "int"],
6838 ['autoFilterDateGrouping', true, "bool"],
6839 ['firstSheet', 0, "int"],
6840 ['minimized', false, "bool"],
6841 ['showHorizontalScroll', true, "bool"],
6842 ['showSheetTabs', true, "bool"],
6843 ['showVerticalScroll', true, "bool"],
6844 ['tabRatio', 600, "int"],
6845 ['visibility', 'visible']
6846 //window{Height,Width}, {x,y}Window
6847];
6848
6849/* 18.2.19 (CT_Sheet) Defaults */
6850var SheetDef = [
6851 //['state', 'visible']
6852];
6853
6854/* 18.2.2 (CT_CalcPr) Defaults */
6855var CalcPrDef = [
6856 ['calcCompleted', 'true'],
6857 ['calcMode', 'auto'],
6858 ['calcOnSave', 'true'],
6859 ['concurrentCalc', 'true'],
6860 ['fullCalcOnLoad', 'false'],
6861 ['fullPrecision', 'true'],
6862 ['iterate', 'false'],
6863 ['iterateCount', '100'],
6864 ['iterateDelta', '0.001'],
6865 ['refMode', 'A1']
6866];
6867
6868/* 18.2.3 (CT_CustomWorkbookView) Defaults */
6869/*var CustomWBViewDef = [
6870 ['autoUpdate', 'false'],
6871 ['changesSavedWin', 'false'],
6872 ['includeHiddenRowCol', 'true'],
6873 ['includePrintSettings', 'true'],
6874 ['maximized', 'false'],
6875 ['minimized', 'false'],
6876 ['onlySync', 'false'],
6877 ['personalView', 'false'],
6878 ['showComments', 'commIndicator'],
6879 ['showFormulaBar', 'true'],
6880 ['showHorizontalScroll', 'true'],
6881 ['showObjects', 'all'],
6882 ['showSheetTabs', 'true'],
6883 ['showStatusbar', 'true'],
6884 ['showVerticalScroll', 'true'],
6885 ['tabRatio', '600'],
6886 ['xWindow', '0'],
6887 ['yWindow', '0']
6888];*/
6889
6890function push_defaults_array(target, defaults) {
6891 for(var j = 0; j != target.length; ++j) { var w = target[j];
6892 for(var i=0; i != defaults.length; ++i) { var z = defaults[i];
6893 if(w[z[0]] == null) w[z[0]] = z[1];
6894 else switch(z[2]) {
6895 case "bool": if(typeof w[z[0]] == "string") w[z[0]] = parsexmlbool(w[z[0]]); break;
6896 case "int": if(typeof w[z[0]] == "string") w[z[0]] = parseInt(w[z[0]], 10); break;
6897 }
6898 }
6899 }
6900}
6901function push_defaults(target, defaults) {
6902 for(var i = 0; i != defaults.length; ++i) { var z = defaults[i];
6903 if(target[z[0]] == null) target[z[0]] = z[1];
6904 else switch(z[2]) {
6905 case "bool": if(typeof target[z[0]] == "string") target[z[0]] = parsexmlbool(target[z[0]]); break;
6906 case "int": if(typeof target[z[0]] == "string") target[z[0]] = parseInt(target[z[0]], 10); break;
6907 }
6908 }
6909}
6910
6911function parse_wb_defaults(wb) {
6912 push_defaults(wb.WBProps, WBPropsDef);
6913 push_defaults(wb.CalcPr, CalcPrDef);
6914
6915 push_defaults_array(wb.WBView, WBViewDef);
6916 push_defaults_array(wb.Sheets, SheetDef);
6917
6918 _ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904);
6919}
6920
6921function safe1904(wb) {
6922 /* TODO: store date1904 somewhere else */
6923 if(!wb.Workbook) return "false";
6924 if(!wb.Workbook.WBProps) return "false";
6925 return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false";
6926}
6927
6928var badchars = "][*?\/\\".split("");
6929function check_ws_name(n, safe) {
6930 if(n.length > 31) { if(safe) return false; throw new Error("Sheet names cannot exceed 31 chars"); }
6931 var _good = true;
6932 badchars.forEach(function(c) {
6933 if(n.indexOf(c) == -1) return;
6934 if(!safe) throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
6935 _good = false;
6936 });
6937 return _good;
6938}
6939function check_wb_names(N, S, codes) {
6940 N.forEach(function(n,i) {
6941 check_ws_name(n);
6942 for(var j = 0; j < i; ++j) if(n == N[j]) throw new Error("Duplicate Sheet Name: " + n);
6943 if(codes) {
6944 var cn = (S && S[i] && S[i].CodeName) || n;
6945 if(cn.charCodeAt(0) == 95 && cn.length > 22) throw new Error("Bad Code Name: Worksheet" + cn);
6946 }
6947 });
6948}
6949function check_wb(wb) {
6950 if(!wb || !wb.SheetNames || !wb.Sheets) throw new Error("Invalid Workbook");
6951 if(!wb.SheetNames.length) throw new Error("Workbook is empty");
6952 var Sheets = (wb.Workbook && wb.Workbook.Sheets) || [];
6953 check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
6954 for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i);
6955 /* TODO: validate workbook */
6956}
6957/* 18.2 Workbook */
6958var wbnsregex = /<\w+:workbook/;
6959function parse_wb_xml(data, opts) {
6960 if(!data) throw new Error("Could not find file");
6961 var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, Names:[], xmlns: "" };
6962 var pass = false, xmlns = "xmlns";
6963 var dname = {}, dnstart = 0;
6964 data.replace(tagregex, function xml_wb(x, idx) {
6965 var y = parsexmltag(x);
6966 switch(strip_ns(y[0])) {
6967 case '<?xml': break;
6968
6969 /* 18.2.27 workbook CT_Workbook 1 */
6970 case '<workbook':
6971 if(x.match(wbnsregex)) xmlns = "xmlns" + x.match(/<(\w+):/)[1];
6972 wb.xmlns = y[xmlns];
6973 break;
6974 case '</workbook>': break;
6975
6976 /* 18.2.13 fileVersion CT_FileVersion ? */
6977 case '<fileVersion': delete y[0]; wb.AppVersion = y; break;
6978 case '<fileVersion/>': case '</fileVersion>': break;
6979
6980 /* 18.2.12 fileSharing CT_FileSharing ? */
6981 case '<fileSharing':
6982 break;
6983 case '<fileSharing/>': break;
6984
6985 /* 18.2.28 workbookPr CT_WorkbookPr ? */
6986 case '<workbookPr':
6987 case '<workbookPr/>':
6988 WBPropsDef.forEach(function(w) {
6989 if(y[w[0]] == null) return;
6990 switch(w[2]) {
6991 case "bool": wb.WBProps[w[0]] = parsexmlbool(y[w[0]]); break;
6992 case "int": wb.WBProps[w[0]] = parseInt(y[w[0]], 10); break;
6993 default: wb.WBProps[w[0]] = y[w[0]];
6994 }
6995 });
6996 if(y.codeName) wb.WBProps.CodeName = y.codeName;
6997 break;
6998 case '</workbookPr>': break;
6999
7000 /* 18.2.29 workbookProtection CT_WorkbookProtection ? */
7001 case '<workbookProtection':
7002 break;
7003 case '<workbookProtection/>': break;
7004
7005 /* 18.2.1 bookViews CT_BookViews ? */
7006 case '<bookViews': case '<bookViews>': case '</bookViews>': break;
7007 /* 18.2.30 workbookView CT_BookView + */
7008 case '<workbookView': case '<workbookView/>': delete y[0]; wb.WBView.push(y); break;
7009 case '</workbookView>': break;
7010
7011 /* 18.2.20 sheets CT_Sheets 1 */
7012 case '<sheets': case '<sheets>': case '</sheets>': break; // aggregate sheet
7013 /* 18.2.19 sheet CT_Sheet + */
7014 case '<sheet':
7015 switch(y.state) {
7016 case "hidden": y.Hidden = 1; break;
7017 case "veryHidden": y.Hidden = 2; break;
7018 default: y.Hidden = 0;
7019 }
7020 delete y.state;
7021 y.name = unescapexml(utf8read(y.name));
7022 delete y[0]; wb.Sheets.push(y); break;
7023 case '</sheet>': break;
7024
7025 /* 18.2.15 functionGroups CT_FunctionGroups ? */
7026 case '<functionGroups': case '<functionGroups/>': break;
7027 /* 18.2.14 functionGroup CT_FunctionGroup + */
7028 case '<functionGroup': break;
7029
7030 /* 18.2.9 externalReferences CT_ExternalReferences ? */
7031 case '<externalReferences': case '</externalReferences>': case '<externalReferences>': break;
7032 /* 18.2.8 externalReference CT_ExternalReference + */
7033 case '<externalReference': break;
7034
7035 /* 18.2.6 definedNames CT_DefinedNames ? */
7036 case '<definedNames/>': break;
7037 case '<definedNames>': case '<definedNames': pass=true; break;
7038 case '</definedNames>': pass=false; break;
7039 /* 18.2.5 definedName CT_DefinedName + */
7040 case '<definedName': {
7041 dname = {};
7042 dname.Name = utf8read(y.name);
7043 if(y.comment) dname.Comment = y.comment;
7044 if(y.localSheetId) dname.Sheet = +y.localSheetId;
7045 if(parsexmlbool(y.hidden||"0")) dname.Hidden = true;
7046 dnstart = idx + x.length;
7047 } break;
7048 case '</definedName>': {
7049 dname.Ref = unescapexml(utf8read(data.slice(dnstart, idx)));
7050 wb.Names.push(dname);
7051 } break;
7052 case '<definedName/>': break;
7053
7054 /* 18.2.2 calcPr CT_CalcPr ? */
7055 case '<calcPr': delete y[0]; wb.CalcPr = y; break;
7056 case '<calcPr/>': delete y[0]; wb.CalcPr = y; break;
7057 case '</calcPr>': break;
7058
7059 /* 18.2.16 oleSize CT_OleSize ? (ref required) */
7060 case '<oleSize': break;
7061
7062 /* 18.2.4 customWorkbookViews CT_CustomWorkbookViews ? */
7063 case '<customWorkbookViews>': case '</customWorkbookViews>': case '<customWorkbookViews': break;
7064 /* 18.2.3 customWorkbookView CT_CustomWorkbookView + */
7065 case '<customWorkbookView': case '</customWorkbookView>': break;
7066
7067 /* 18.2.18 pivotCaches CT_PivotCaches ? */
7068 case '<pivotCaches>': case '</pivotCaches>': case '<pivotCaches': break;
7069 /* 18.2.17 pivotCache CT_PivotCache ? */
7070 case '<pivotCache': break;
7071
7072 /* 18.2.21 smartTagPr CT_SmartTagPr ? */
7073 case '<smartTagPr': case '<smartTagPr/>': break;
7074
7075 /* 18.2.23 smartTagTypes CT_SmartTagTypes ? */
7076 case '<smartTagTypes': case '<smartTagTypes>': case '</smartTagTypes>': break;
7077 /* 18.2.22 smartTagType CT_SmartTagType ? */
7078 case '<smartTagType': break;
7079
7080 /* 18.2.24 webPublishing CT_WebPublishing ? */
7081 case '<webPublishing': case '<webPublishing/>': break;
7082
7083 /* 18.2.11 fileRecoveryPr CT_FileRecoveryPr ? */
7084 case '<fileRecoveryPr': case '<fileRecoveryPr/>': break;
7085
7086 /* 18.2.26 webPublishObjects CT_WebPublishObjects ? */
7087 case '<webPublishObjects>': case '<webPublishObjects': case '</webPublishObjects>': break;
7088 /* 18.2.25 webPublishObject CT_WebPublishObject ? */
7089 case '<webPublishObject': break;
7090
7091 /* 18.2.10 extLst CT_ExtensionList ? */
7092 case '<extLst': case '<extLst>': case '</extLst>': case '<extLst/>': break;
7093 /* 18.2.7 ext CT_Extension + */
7094 case '<ext': pass=true; break; //TODO: check with versions of excel
7095 case '</ext>': pass=false; break;
7096
7097 /* Others */
7098 case '<ArchID': break;
7099 case '<AlternateContent':
7100 case '<AlternateContent>': pass=true; break;
7101 case '</AlternateContent>': pass=false; break;
7102
7103 /* TODO */
7104 case '<revisionPtr': break;
7105
7106 default: if(!pass && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in workbook');
7107 }
7108 return x;
7109 });
7110 if(XMLNS.main.indexOf(wb.xmlns) === -1) throw new Error("Unknown Namespace: " + wb.xmlns);
7111
7112 parse_wb_defaults(wb);
7113
7114 return wb;
7115}
7116
7117var WB_XML_ROOT = writextag('workbook', null, {
7118 'xmlns': XMLNS.main[0],
7119 //'xmlns:mx': XMLNS.mx,
7120 //'xmlns:s': XMLNS.main[0],
7121 'xmlns:r': XMLNS.r
7122});
7123
7124function write_wb_xml(wb) {
7125 var o = [XML_HEADER];
7126 o[o.length] = WB_XML_ROOT;
7127
7128 var write_names = (wb.Workbook && (wb.Workbook.Names||[]).length > 0);
7129
7130 /* fileVersion */
7131 /* fileSharing */
7132
7133 var workbookPr = ({codeName:"ThisWorkbook"});
7134 if(wb.Workbook && wb.Workbook.WBProps) {
7135 WBPropsDef.forEach(function(x) {
7136if((wb.Workbook.WBProps[x[0]]) == null) return;
7137 if((wb.Workbook.WBProps[x[0]]) == x[1]) return;
7138 workbookPr[x[0]] = (wb.Workbook.WBProps[x[0]]);
7139 });
7140if(wb.Workbook.WBProps.CodeName) { workbookPr.codeName = wb.Workbook.WBProps.CodeName; delete workbookPr.CodeName; }
7141 }
7142 o[o.length] = (writextag('workbookPr', null, workbookPr));
7143
7144 /* workbookProtection */
7145
7146 var sheets = wb.Workbook && wb.Workbook.Sheets || [];
7147 var i = 0;
7148
7149 /* bookViews */
7150
7151 o[o.length] = "<sheets>";
7152 for(i = 0; i != wb.SheetNames.length; ++i) {
7153 var sht = ({name:escapexml(wb.SheetNames[i].slice(0,31))});
7154 sht.sheetId = ""+(i+1);
7155 sht["r:id"] = "rId"+(i+1);
7156 if(sheets[i]) switch(sheets[i].Hidden) {
7157 case 1: sht.state = "hidden"; break;
7158 case 2: sht.state = "veryHidden"; break;
7159 }
7160 o[o.length] = (writextag('sheet',null,sht));
7161 }
7162 o[o.length] = "</sheets>";
7163
7164 /* functionGroups */
7165 /* externalReferences */
7166
7167 if(write_names) {
7168 o[o.length] = "<definedNames>";
7169 if(wb.Workbook && wb.Workbook.Names) wb.Workbook.Names.forEach(function(n) {
7170 var d = {name:n.Name};
7171 if(n.Comment) d.comment = n.Comment;
7172 if(n.Sheet != null) d.localSheetId = ""+n.Sheet;
7173 if(n.Hidden) d.hidden = "1";
7174 if(!n.Ref) return;
7175 o[o.length] = writextag('definedName', escapexml(n.Ref), d);
7176 });
7177 o[o.length] = "</definedNames>";
7178 }
7179
7180 /* calcPr */
7181 /* oleSize */
7182 /* customWorkbookViews */
7183 /* pivotCaches */
7184 /* smartTagPr */
7185 /* smartTagTypes */
7186 /* webPublishing */
7187 /* fileRecoveryPr */
7188 /* webPublishObjects */
7189 /* extLst */
7190
7191 if(o.length>2){ o[o.length] = '</workbook>'; o[1]=o[1].replace("/>",">"); }
7192 return o.join("");
7193}
7194function parse_wb(data, name, opts) {
7195 if(name.slice(-4)===".bin") return parse_wb_bin((data), opts);
7196 return parse_wb_xml((data), opts);
7197}
7198
7199function parse_ws(data, name, idx, opts, rels, wb, themes, styles) {
7200 if(name.slice(-4)===".bin") return parse_ws_bin((data), opts, idx, rels, wb, themes, styles);
7201 return parse_ws_xml((data), opts, idx, rels, wb, themes, styles);
7202}
7203
7204function parse_cs(data, name, idx, opts, rels, wb, themes, styles) {
7205 if(name.slice(-4)===".bin") return parse_cs_bin((data), opts, idx, rels, wb, themes, styles);
7206 return parse_cs_xml((data), opts, idx, rels, wb, themes, styles);
7207}
7208
7209function parse_ms(data, name, idx, opts, rels, wb, themes, styles) {
7210 if(name.slice(-4)===".bin") return parse_ms_bin((data), opts, idx, rels, wb, themes, styles);
7211 return parse_ms_xml((data), opts, idx, rels, wb, themes, styles);
7212}
7213
7214function parse_ds(data, name, idx, opts, rels, wb, themes, styles) {
7215 if(name.slice(-4)===".bin") return parse_ds_bin((data), opts, idx, rels, wb, themes, styles);
7216 return parse_ds_xml((data), opts, idx, rels, wb, themes, styles);
7217}
7218
7219function parse_sty(data, name, themes, opts) {
7220 if(name.slice(-4)===".bin") return parse_sty_bin((data), themes, opts);
7221 return parse_sty_xml((data), themes, opts);
7222}
7223
7224function parse_theme(data, name, opts) {
7225 return parse_theme_xml(data, opts);
7226}
7227
7228function parse_sst(data, name, opts) {
7229 if(name.slice(-4)===".bin") return parse_sst_bin((data), opts);
7230 return parse_sst_xml((data), opts);
7231}
7232
7233function parse_cmnt(data, name, opts) {
7234 if(name.slice(-4)===".bin") return parse_comments_bin((data), opts);
7235 return parse_comments_xml((data), opts);
7236}
7237
7238function parse_cc(data, name, opts) {
7239 if(name.slice(-4)===".bin") return parse_cc_bin((data), name, opts);
7240 return parse_cc_xml((data), name, opts);
7241}
7242
7243function parse_xlink(data, rel, name, opts) {
7244 if(name.slice(-4)===".bin") return parse_xlink_bin((data), rel, name, opts);
7245 return parse_xlink_xml((data), rel, name, opts);
7246}
7247
7248function write_wb(wb, name, opts) {
7249 return (name.slice(-4)===".bin" ? write_wb_bin : write_wb_xml)(wb, opts);
7250}
7251
7252function write_ws(data, name, opts, wb, rels) {
7253 return (name.slice(-4)===".bin" ? write_ws_bin : write_ws_xml)(data, opts, wb, rels);
7254}
7255
7256// eslint-disable-next-line no-unused-vars
7257function write_cs(data, name, opts, wb, rels) {
7258 return (name.slice(-4)===".bin" ? write_cs_bin : write_cs_xml)(data, opts, wb, rels);
7259}
7260
7261function write_sty(data, name, opts) {
7262 return (name.slice(-4)===".bin" ? write_sty_bin : write_sty_xml)(data, opts);
7263}
7264
7265function write_sst(data, name, opts) {
7266 return (name.slice(-4)===".bin" ? write_sst_bin : write_sst_xml)(data, opts);
7267}
7268
7269function write_cmnt(data, name, opts) {
7270 return (name.slice(-4)===".bin" ? write_comments_bin : write_comments_xml)(data, opts);
7271}
7272/*
7273function write_cc(data, name:string, opts) {
7274 return (name.slice(-4)===".bin" ? write_cc_bin : write_cc_xml)(data, opts);
7275}
7276*/
7277/* note: browser DOM element cannot see mso- style attrs, must parse */
7278var HTML_ = (function() {
7279 function html_to_sheet(str, _opts) {
7280 var opts = _opts || {};
7281 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
7282 var ws = opts.dense ? ([]) : ({});
7283 str = str.replace(/<!--.*?-->/g, "");
7284 var mtch = str.match(/<table/i);
7285 if(!mtch) throw new Error("Invalid HTML: could not find <table>");
7286 var mtch2 = str.match(/<\/table/i);
7287 var i = mtch.index, j = mtch2 && mtch2.index || str.length;
7288 var rows = split_regex(str.slice(i, j), /(:?<tr[^>]*>)/i, "<tr>");
7289 var R = -1, C = 0, RS = 0, CS = 0;
7290 var range = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
7291 var merges = [];
7292 for(i = 0; i < rows.length; ++i) {
7293 var row = rows[i].trim();
7294 var hd = row.slice(0,3).toLowerCase();
7295 if(hd == "<tr") { ++R; if(opts.sheetRows && opts.sheetRows <= R) { --R; break; } C = 0; continue; }
7296 if(hd != "<td" && hd != "<th") continue;
7297 var cells = row.split(/<\/t[dh]>/i);
7298 for(j = 0; j < cells.length; ++j) {
7299 var cell = cells[j].trim();
7300 if(!cell.match(/<t[dh]/i)) continue;
7301 var m = cell, cc = 0;
7302 /* TODO: parse styles etc */
7303 while(m.charAt(0) == "<" && (cc = m.indexOf(">")) > -1) m = m.slice(cc+1);
7304 for(var midx = 0; midx < merges.length; ++midx) {
7305 var _merge = merges[midx];
7306 if(_merge.s.c == C && _merge.s.r < R && R <= _merge.e.r) { C = _merge.e.c + 1; midx = -1; }
7307 }
7308 var tag = parsexmltag(cell.slice(0, cell.indexOf(">")));
7309 CS = tag.colspan ? +tag.colspan : 1;
7310 if((RS = +tag.rowspan)>1 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
7311 var _t = tag.t || "";
7312 /* TODO: generate stub cells */
7313 if(!m.length) { C += CS; continue; }
7314 m = htmldecode(m);
7315 if(range.s.r > R) range.s.r = R; if(range.e.r < R) range.e.r = R;
7316 if(range.s.c > C) range.s.c = C; if(range.e.c < C) range.e.c = C;
7317 if(!m.length) continue;
7318 var o = {t:'s', v:m};
7319 if(opts.raw || !m.trim().length || _t == 's'){}
7320 else if(m === 'TRUE') o = {t:'b', v:true};
7321 else if(m === 'FALSE') o = {t:'b', v:false};
7322 else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)};
7323 else if(!isNaN(fuzzydate(m).getDate())) {
7324 o = ({t:'d', v:parseDate(m)});
7325 if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)});
7326 o.z = opts.dateNF || SSF._table[14];
7327 }
7328 if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; }
7329 else ws[encode_cell({r:R, c:C})] = o;
7330 C += CS;
7331 }
7332 }
7333 ws['!ref'] = encode_range(range);
7334 if(merges.length) ws["!merges"] = merges;
7335 return ws;
7336 }
7337 function html_to_book(str, opts) {
7338 return sheet_to_workbook(html_to_sheet(str, opts), opts);
7339 }
7340 function make_html_row(ws, r, R, o) {
7341 var M = (ws['!merges'] ||[]);
7342 var oo = [];
7343 for(var C = r.s.c; C <= r.e.c; ++C) {
7344 var RS = 0, CS = 0;
7345 for(var j = 0; j < M.length; ++j) {
7346 if(M[j].s.r > R || M[j].s.c > C) continue;
7347 if(M[j].e.r < R || M[j].e.c < C) continue;
7348 if(M[j].s.r < R || M[j].s.c < C) { RS = -1; break; }
7349 RS = M[j].e.r - M[j].s.r + 1; CS = M[j].e.c - M[j].s.c + 1; break;
7350 }
7351 if(RS < 0) continue;
7352 var coord = encode_cell({r:R,c:C});
7353 var cell = o.dense ? (ws[R]||[])[C] : ws[coord];
7354 /* TODO: html entities */
7355 var w = (cell && cell.v != null) && (cell.h || escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || "";
7356 var sp = ({});
7357 if(RS > 1) sp.rowspan = RS;
7358 if(CS > 1) sp.colspan = CS;
7359 sp.t = cell && cell.t || 'z';
7360 if(o.editable) w = '<span contenteditable="true">' + w + '</span>';
7361 sp.id = (o.id || "sjs") + "-" + coord;
7362 oo.push(writextag('td', w, sp));
7363 }
7364 var preamble = "<tr>";
7365 return preamble + oo.join("") + "</tr>";
7366 }
7367 function make_html_preamble(ws, R, o) {
7368 var out = [];
7369 return out.join("") + '<table' + (o && o.id ? ' id="' + o.id + '"' : "") + '>';
7370 }
7371 var _BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
7372 var _END = '</body></html>';
7373 function sheet_to_html(ws, opts/*, wb:?Workbook*/) {
7374 var o = opts || {};
7375 var header = o.header != null ? o.header : _BEGIN;
7376 var footer = o.footer != null ? o.footer : _END;
7377 var out = [header];
7378 var r = decode_range(ws['!ref']);
7379 o.dense = Array.isArray(ws);
7380 out.push(make_html_preamble(ws, r, o));
7381 for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
7382 out.push("</table>" + footer);
7383 return out.join("");
7384 }
7385
7386 return {
7387 to_workbook: html_to_book,
7388 to_sheet: html_to_sheet,
7389 _row: make_html_row,
7390 BEGIN: _BEGIN,
7391 END: _END,
7392 _preamble: make_html_preamble,
7393 from_sheet: sheet_to_html
7394 };
7395})();
7396
7397function parse_dom_table(table, _opts) {
7398 var opts = _opts || {};
7399 if(DENSE != null) opts.dense = DENSE;
7400 var ws = opts.dense ? ([]) : ({});
7401 var rows = table.getElementsByTagName('tr');
7402 var sheetRows = opts.sheetRows || 10000000;
7403 var range = {s:{r:0,c:0},e:{r:0,c:0}};
7404 var merges = [], midx = 0;
7405 var rowinfo = [];
7406 var _R = 0, R = 0, _C = 0, C = 0, RS = 0, CS = 0;
7407 for(; _R < rows.length && R < sheetRows; ++_R) {
7408 var row = rows[_R];
7409 if (is_dom_element_hidden(row)) {
7410 if (opts.display) continue;
7411 rowinfo[R] = {hidden: true};
7412 }
7413 var elts = (row.children);
7414 for(_C = C = 0; _C < elts.length; ++_C) {
7415 var elt = elts[_C];
7416 if (opts.display && is_dom_element_hidden(elt)) continue;
7417 var v = htmldecode(elt.innerHTML);
7418 for(midx = 0; midx < merges.length; ++midx) {
7419 var m = merges[midx];
7420 if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; }
7421 }
7422 /* TODO: figure out how to extract nonstandard mso- style */
7423 CS = +elt.getAttribute("colspan") || 1;
7424 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}});
7425 var o = {t:'s', v:v};
7426 var _t = elt.getAttribute("t") || "";
7427 if(v != null) {
7428 if(v.length == 0) o.t = _t || 'z';
7429 else if(opts.raw || v.trim().length == 0 || _t == "s"){}
7430 else if(v === 'TRUE') o = {t:'b', v:true};
7431 else if(v === 'FALSE') o = {t:'b', v:false};
7432 else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
7433 else if(!isNaN(fuzzydate(v).getDate())) {
7434 o = ({t:'d', v:parseDate(v)});
7435 if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)});
7436 o.z = opts.dateNF || SSF._table[14];
7437 }
7438 }
7439 if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; }
7440 else ws[encode_cell({c:C, r:R})] = o;
7441 if(range.e.c < C) range.e.c = C;
7442 C += CS;
7443 }
7444 ++R;
7445 }
7446 if(merges.length) ws['!merges'] = merges;
7447 if(rowinfo.length) ws['!rows'] = rowinfo;
7448 range.e.r = R - 1;
7449 ws['!ref'] = encode_range(range);
7450 if(R >= sheetRows) ws['!fullref'] = encode_range((range.e.r = rows.length-_R+R-1,range)); // We can count the real number of rows to parse but we don't to improve the performance
7451 return ws;
7452}
7453
7454function table_to_book(table, opts) {
7455 return sheet_to_workbook(parse_dom_table(table, opts), opts);
7456}
7457
7458function is_dom_element_hidden(element) {
7459 var display = '';
7460 var get_computed_style = get_get_computed_style_function(element);
7461 if(get_computed_style) display = get_computed_style(element).getPropertyValue('display');
7462 if(!display) display = element.style.display; // Fallback for cases when getComputedStyle is not available (e.g. an old browser or some Node.js environments) or doesn't work (e.g. if the element is not inserted to a document)
7463 return display === 'none';
7464}
7465
7466/* global getComputedStyle */
7467function get_get_computed_style_function(element) {
7468 // The proper getComputedStyle implementation is the one defined in the element window
7469 if(element.ownerDocument.defaultView && typeof element.ownerDocument.defaultView.getComputedStyle === 'function') return element.ownerDocument.defaultView.getComputedStyle;
7470 // If it is not available, try to get one from the global namespace
7471 if(typeof getComputedStyle === 'function') return getComputedStyle;
7472 return null;
7473}
7474function write_sheet_index(wb, sheet) {
7475 if(!sheet) return 0;
7476 var idx = wb.SheetNames.indexOf(sheet);
7477 if(idx == -1) throw new Error("Sheet not found: " + sheet);
7478 return idx;
7479}
7480
7481function write_obj_str(factory) {
7482 return function write_str(wb, o) {
7483 var idx = write_sheet_index(wb, o.sheet);
7484 return factory.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb);
7485 };
7486}
7487
7488var write_htm_str = write_obj_str(HTML_);
7489var write_csv_str = write_obj_str({from_sheet:sheet_to_csv});
7490var write_slk_str = write_obj_str(typeof SYLK !== "undefined" ? SYLK : {});
7491var write_dif_str = write_obj_str(typeof DIF !== "undefined" ? DIF : {});
7492var write_prn_str = write_obj_str(typeof PRN !== "undefined" ? PRN : {});
7493var write_rtf_str = write_obj_str(typeof RTF !== "undefined" ? RTF : {});
7494var write_txt_str = write_obj_str({from_sheet:sheet_to_txt});
7495var write_dbf_buf = write_obj_str(typeof DBF !== "undefined" ? DBF : {});
7496var write_eth_str = write_obj_str(typeof ETH !== "undefined" ? ETH : {});
7497
7498function fix_opts_func(defaults) {
7499 return function fix_opts(opts) {
7500 for(var i = 0; i != defaults.length; ++i) {
7501 var d = defaults[i];
7502 if(opts[d[0]] === undefined) opts[d[0]] = d[1];
7503 if(d[2] === 'n') opts[d[0]] = Number(opts[d[0]]);
7504 }
7505 };
7506}
7507
7508var fix_read_opts = fix_opts_func([
7509 ['cellNF', false], /* emit cell number format string as .z */
7510 ['cellHTML', true], /* emit html string as .h */
7511 ['cellFormula', true], /* emit formulae as .f */
7512 ['cellStyles', false], /* emits style/theme as .s */
7513 ['cellText', true], /* emit formatted text as .w */
7514 ['cellDates', false], /* emit date cells with type `d` */
7515
7516 ['sheetStubs', false], /* emit empty cells */
7517 ['sheetRows', 0, 'n'], /* read n rows (0 = read all rows) */
7518
7519 ['bookDeps', false], /* parse calculation chains */
7520 ['bookSheets', false], /* only try to get sheet names (no Sheets) */
7521 ['bookProps', false], /* only try to get properties (no Sheets) */
7522 ['bookFiles', false], /* include raw file structure (keys, files, cfb) */
7523 ['bookVBA', false], /* include vba raw data (vbaraw) */
7524
7525 ['password',''], /* password */
7526 ['WTF', false] /* WTF mode (throws errors) */
7527]);
7528
7529
7530var fix_write_opts = fix_opts_func([
7531 ['cellDates', false], /* write date cells with type `d` */
7532
7533 ['bookSST', false], /* Generate Shared String Table */
7534
7535 ['bookType', 'xlsx'], /* Type of workbook (xlsx/m/b) */
7536
7537 ['compression', false], /* Use file compression */
7538
7539 ['WTF', false] /* WTF mode (throws errors) */
7540]);
7541function get_sheet_type(n) {
7542 if(RELS.WS.indexOf(n) > -1) return "sheet";
7543 if(RELS.CS && n == RELS.CS) return "chart";
7544 if(RELS.DS && n == RELS.DS) return "dialog";
7545 if(RELS.MS && n == RELS.MS) return "macro";
7546 return (n && n.length) ? n : "sheet";
7547}
7548function safe_parse_wbrels(wbrels, sheets) {
7549 if(!wbrels) return 0;
7550 try {
7551 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)]; });
7552 } catch(e) { return null; }
7553 return !wbrels || wbrels.length === 0 ? null : wbrels;
7554}
7555
7556function safe_parse_sheet(zip, path, relsPath, sheet, idx, sheetRels, sheets, stype, opts, wb, themes, styles) {
7557 try {
7558 sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
7559 var data = getzipdata(zip, path);
7560 var _ws;
7561 switch(stype) {
7562 case 'sheet': _ws = parse_ws(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
7563 case 'chart': _ws = parse_cs(data, path, idx, opts, sheetRels[sheet], wb, themes, styles);
7564 if(!_ws || !_ws['!drawel']) break;
7565 var dfile = resolve_path(_ws['!drawel'].Target, path);
7566 var drelsp = get_rels_path(dfile);
7567 var draw = parse_drawing(getzipstr(zip, dfile, true), parse_rels(getzipstr(zip, drelsp, true), dfile));
7568 var chartp = resolve_path(draw, dfile);
7569 var crelsp = get_rels_path(chartp);
7570 _ws = parse_chart(getzipstr(zip, chartp, true), chartp, opts, parse_rels(getzipstr(zip, crelsp, true), chartp), wb, _ws);
7571 break;
7572 case 'macro': _ws = parse_ms(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
7573 case 'dialog': _ws = parse_ds(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
7574 default: throw new Error("Unrecognized sheet type " + stype);
7575 }
7576 sheets[sheet] = _ws;
7577
7578 /* scan rels for comments */
7579 var comments = [];
7580 if(sheetRels && sheetRels[sheet]) keys(sheetRels[sheet]).forEach(function(n) {
7581 if(sheetRels[sheet][n].Type == RELS.CMNT) {
7582 var dfile = resolve_path(sheetRels[sheet][n].Target, path);
7583 comments = parse_cmnt(getzipdata(zip, dfile, true), dfile, opts);
7584 if(!comments || !comments.length) return;
7585 sheet_insert_comments(_ws, comments);
7586 }
7587 });
7588 } catch(e) { if(opts.WTF) throw e; }
7589}
7590
7591function strip_front_slash(x) { return x.charAt(0) == '/' ? x.slice(1) : x; }
7592
7593function parse_zip(zip, opts) {
7594 make_ssf(SSF);
7595 opts = opts || {};
7596 fix_read_opts(opts);
7597
7598 /* OpenDocument Part 3 Section 2.2.1 OpenDocument Package */
7599 if(safegetzipfile(zip, 'META-INF/manifest.xml')) return parse_ods(zip, opts);
7600 /* UOC */
7601 if(safegetzipfile(zip, 'objectdata.xml')) return parse_ods(zip, opts);
7602 /* Numbers */
7603 if(safegetzipfile(zip, 'Index/Document.iwa')) throw new Error('Unsupported NUMBERS file');
7604
7605 var entries = zipentries(zip);
7606 var dir = parse_ct((getzipstr(zip, '[Content_Types].xml')));
7607 var xlsb = false;
7608 var sheets, binname;
7609 if(dir.workbooks.length === 0) {
7610 binname = "xl/workbook.xml";
7611 if(getzipdata(zip,binname, true)) dir.workbooks.push(binname);
7612 }
7613 if(dir.workbooks.length === 0) {
7614 binname = "xl/workbook.bin";
7615 if(!getzipdata(zip,binname,true)) throw new Error("Could not find workbook");
7616 dir.workbooks.push(binname);
7617 xlsb = true;
7618 }
7619 if(dir.workbooks[0].slice(-3) == "bin") xlsb = true;
7620
7621 var themes = ({});
7622 var styles = ({});
7623 if(!opts.bookSheets && !opts.bookProps) {
7624 strs = [];
7625 if(dir.sst) try { strs=parse_sst(getzipdata(zip, strip_front_slash(dir.sst)), dir.sst, opts); } catch(e) { if(opts.WTF) throw e; }
7626
7627 if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts);
7628
7629 if(dir.style) styles = parse_sty(getzipdata(zip, strip_front_slash(dir.style)), dir.style, themes, opts);
7630 }
7631
7632 /*var externbooks = */dir.links.map(function(link) {
7633 try {
7634 var rels = parse_rels(getzipstr(zip, get_rels_path(strip_front_slash(link))), link);
7635 return parse_xlink(getzipdata(zip, strip_front_slash(link)), rels, link, opts);
7636 } catch(e) {}
7637 });
7638
7639 var wb = parse_wb(getzipdata(zip, strip_front_slash(dir.workbooks[0])), dir.workbooks[0], opts);
7640
7641 var props = {}, propdata = "";
7642
7643 if(dir.coreprops.length) {
7644 propdata = getzipdata(zip, strip_front_slash(dir.coreprops[0]), true);
7645 if(propdata) props = parse_core_props(propdata);
7646 if(dir.extprops.length !== 0) {
7647 propdata = getzipdata(zip, strip_front_slash(dir.extprops[0]), true);
7648 if(propdata) parse_ext_props(propdata, props, opts);
7649 }
7650 }
7651
7652 var custprops = {};
7653 if(!opts.bookSheets || opts.bookProps) {
7654 if (dir.custprops.length !== 0) {
7655 propdata = getzipstr(zip, strip_front_slash(dir.custprops[0]), true);
7656 if(propdata) custprops = parse_cust_props(propdata, opts);
7657 }
7658 }
7659
7660 var out = ({});
7661 if(opts.bookSheets || opts.bookProps) {
7662 if(wb.Sheets) sheets = wb.Sheets.map(function pluck(x){ return x.name; });
7663 else if(props.Worksheets && props.SheetNames.length > 0) sheets=props.SheetNames;
7664 if(opts.bookProps) { out.Props = props; out.Custprops = custprops; }
7665 if(opts.bookSheets && typeof sheets !== 'undefined') out.SheetNames = sheets;
7666 if(opts.bookSheets ? out.SheetNames : opts.bookProps) return out;
7667 }
7668 sheets = {};
7669
7670 var deps = {};
7671 if(opts.bookDeps && dir.calcchain) deps=parse_cc(getzipdata(zip, strip_front_slash(dir.calcchain)),dir.calcchain,opts);
7672
7673 var i=0;
7674 var sheetRels = ({});
7675 var path, relsPath;
7676
7677 {
7678 var wbsheets = wb.Sheets;
7679 props.Worksheets = wbsheets.length;
7680 props.SheetNames = [];
7681 for(var j = 0; j != wbsheets.length; ++j) {
7682 props.SheetNames[j] = wbsheets[j].name;
7683 }
7684 }
7685
7686 var wbext = xlsb ? "bin" : "xml";
7687 var wbrelsi = dir.workbooks[0].lastIndexOf("/");
7688 var wbrelsfile = (dir.workbooks[0].slice(0, wbrelsi+1) + "_rels/" + dir.workbooks[0].slice(wbrelsi+1) + ".rels").replace(/^\//,"");
7689 if(!safegetzipfile(zip, wbrelsfile)) wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
7690 var wbrels = parse_rels(getzipstr(zip, wbrelsfile, true), wbrelsfile);
7691 if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
7692
7693 /* Numbers iOS hack */
7694 var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
7695 wsloop: for(i = 0; i != props.Worksheets; ++i) {
7696 var stype = "sheet";
7697 if(wbrels && wbrels[i]) {
7698 path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
7699 if(!safegetzipfile(zip, path)) path = wbrels[i][1];
7700 if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/.*$/,"") + wbrels[i][1];
7701 stype = wbrels[i][2];
7702 } else {
7703 path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
7704 path = path.replace(/sheet0\./,"sheet.");
7705 }
7706 relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
7707 if(opts && opts.sheets != null) switch(typeof opts.sheets) {
7708 case "number": if(i != opts.sheets) continue wsloop; break;
7709 case "string": if(props.SheetNames[i].toLowerCase() != opts.sheets.toLowerCase()) continue wsloop; break;
7710 default: if(Array.isArray && Array.isArray(opts.sheets)) {
7711 var snjseen = false;
7712 for(var snj = 0; snj != opts.sheets.length; ++snj) {
7713 if(typeof opts.sheets[snj] == "number" && opts.sheets[snj] == i) snjseen=1;
7714 if(typeof opts.sheets[snj] == "string" && opts.sheets[snj].toLowerCase() == props.SheetNames[i].toLowerCase()) snjseen = 1;
7715 }
7716 if(!snjseen) continue wsloop;
7717 }
7718 }
7719 safe_parse_sheet(zip, path, relsPath, props.SheetNames[i], i, sheetRels, sheets, stype, opts, wb, themes, styles);
7720 }
7721
7722 out = ({
7723 Directory: dir,
7724 Workbook: wb,
7725 Props: props,
7726 Custprops: custprops,
7727 Deps: deps,
7728 Sheets: sheets,
7729 SheetNames: props.SheetNames,
7730 Strings: strs,
7731 Styles: styles,
7732 Themes: themes,
7733 SSF: SSF.get_table()
7734 });
7735 if(opts && opts.bookFiles) {
7736 out.keys = entries;
7737 out.files = zip.files;
7738 }
7739 if(opts && opts.bookVBA) {
7740 if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,strip_front_slash(dir.vba[0]),true);
7741 else if(dir.defaults && dir.defaults.bin === CT_VBA) out.vbaraw = getzipdata(zip, 'xl/vbaProject.bin',true);
7742 }
7743 return out;
7744}
7745
7746/* [MS-OFFCRYPTO] 2.1.1 */
7747function parse_xlsxcfb(cfb, _opts) {
7748 var opts = _opts || {};
7749 var f = 'Workbook', data = CFB.find(cfb, f);
7750 try {
7751 f = '/!DataSpaces/Version';
7752 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
7753 /*var version = */parse_DataSpaceVersionInfo(data.content);
7754
7755 /* 2.3.4.1 */
7756 f = '/!DataSpaces/DataSpaceMap';
7757 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
7758 var dsm = parse_DataSpaceMap(data.content);
7759 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")
7760 throw new Error("ECMA-376 Encrypted file bad " + f);
7761
7762 /* 2.3.4.2 */
7763 f = '/!DataSpaces/DataSpaceInfo/StrongEncryptionDataSpace';
7764 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
7765 var seds = parse_DataSpaceDefinition(data.content);
7766 if(seds.length != 1 || seds[0] != "StrongEncryptionTransform")
7767 throw new Error("ECMA-376 Encrypted file bad " + f);
7768
7769 /* 2.3.4.3 */
7770 f = '/!DataSpaces/TransformInfo/StrongEncryptionTransform/!Primary';
7771 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
7772 /*var hdr = */parse_Primary(data.content);
7773 } catch(e) {}
7774
7775 f = '/EncryptionInfo';
7776 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
7777 var einfo = parse_EncryptionInfo(data.content);
7778
7779 /* 2.3.4.4 */
7780 f = '/EncryptedPackage';
7781 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
7782
7783/*global decrypt_agile */
7784if(einfo[0] == 0x04 && typeof decrypt_agile !== 'undefined') return decrypt_agile(einfo[1], data.content, opts.password || "", opts);
7785/*global decrypt_std76 */
7786if(einfo[0] == 0x02 && typeof decrypt_std76 !== 'undefined') return decrypt_std76(einfo[1], data.content, opts.password || "", opts);
7787 throw new Error("File is password-protected");
7788}
7789
7790function write_zip(wb, opts) {
7791 _shapeid = 1024;
7792 if(opts.bookType == "ods") return write_ods(wb, opts);
7793 if(wb && !wb.SSF) {
7794 wb.SSF = SSF.get_table();
7795 }
7796 if(wb && wb.SSF) {
7797 make_ssf(SSF); SSF.load_table(wb.SSF);
7798 // $FlowIgnore
7799 opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
7800 opts.ssf = wb.SSF;
7801 }
7802 opts.rels = {}; opts.wbrels = {};
7803 opts.Strings = []; opts.Strings.Count = 0; opts.Strings.Unique = 0;
7804 if(browser_has_Map) opts.revStrings = new Map();
7805 else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; }
7806 var wbext = opts.bookType == "xlsb" ? "bin" : "xml";
7807 var vbafmt = VBAFMTS.indexOf(opts.bookType) > -1;
7808 var ct = new_ct();
7809 fix_write_opts(opts = opts || {});
7810var zip = zip_new();
7811 var f = "", rId = 0;
7812
7813 opts.cellXfs = [];
7814 get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}});
7815
7816 if(!wb.Props) wb.Props = {};
7817
7818 f = "docProps/core.xml";
7819 zip_add_file(zip, f, write_core_props(wb.Props, opts));
7820 ct.coreprops.push(f);
7821 add_rels(opts.rels, 2, f, RELS.CORE_PROPS);
7822
7823f = "docProps/app.xml";
7824 if(wb.Props && wb.Props.SheetNames){/* empty */}
7825 else if(!wb.Workbook || !wb.Workbook.Sheets) wb.Props.SheetNames = wb.SheetNames;
7826 else {
7827 var _sn = [];
7828 for(var _i = 0; _i < wb.SheetNames.length; ++_i)
7829 if((wb.Workbook.Sheets[_i]||{}).Hidden != 2) _sn.push(wb.SheetNames[_i]);
7830 wb.Props.SheetNames = _sn;
7831 }
7832 wb.Props.Worksheets = wb.Props.SheetNames.length;
7833 zip_add_file(zip, f, write_ext_props(wb.Props, opts));
7834 ct.extprops.push(f);
7835 add_rels(opts.rels, 3, f, RELS.EXT_PROPS);
7836
7837 if(wb.Custprops !== wb.Props && keys(wb.Custprops||{}).length > 0) {
7838 f = "docProps/custom.xml";
7839 zip_add_file(zip, f, write_cust_props(wb.Custprops, opts));
7840 ct.custprops.push(f);
7841 add_rels(opts.rels, 4, f, RELS.CUST_PROPS);
7842 }
7843
7844 for(rId=1;rId <= wb.SheetNames.length; ++rId) {
7845 var wsrels = {'!id':{}};
7846 var ws = wb.Sheets[wb.SheetNames[rId-1]];
7847 var _type = (ws || {})["!type"] || "sheet";
7848 switch(_type) {
7849 case "chart":
7850 /* falls through */
7851 default:
7852 f = "xl/worksheets/sheet" + rId + "." + wbext;
7853 zip_add_file(zip, f, write_ws(rId-1, f, opts, wb, wsrels));
7854 ct.sheets.push(f);
7855 add_rels(opts.wbrels, -1, "worksheets/sheet" + rId + "." + wbext, RELS.WS[0]);
7856 }
7857
7858 if(ws) {
7859 var comments = ws['!comments'];
7860 var need_vml = false;
7861 if(comments && comments.length > 0) {
7862 var cf = "xl/comments" + rId + "." + wbext;
7863 zip_add_file(zip, cf, write_cmnt(comments, cf, opts));
7864 ct.comments.push(cf);
7865 add_rels(wsrels, -1, "../comments" + rId + "." + wbext, RELS.CMNT);
7866 need_vml = true;
7867 }
7868 if(ws['!legacy']) {
7869 if(need_vml) zip_add_file(zip, "xl/drawings/vmlDrawing" + (rId) + ".vml", write_comments_vml(rId, ws['!comments']));
7870 }
7871 delete ws['!comments'];
7872 delete ws['!legacy'];
7873 }
7874
7875 if(wsrels['!id'].rId1) zip_add_file(zip, get_rels_path(f), write_rels(wsrels));
7876 }
7877
7878 if(opts.Strings != null && opts.Strings.length > 0) {
7879 f = "xl/sharedStrings." + wbext;
7880 zip_add_file(zip, f, write_sst(opts.Strings, f, opts));
7881 ct.strs.push(f);
7882 add_rels(opts.wbrels, -1, "sharedStrings." + wbext, RELS.SST);
7883 }
7884
7885 f = "xl/workbook." + wbext;
7886 zip_add_file(zip, f, write_wb(wb, f, opts));
7887 ct.workbooks.push(f);
7888 add_rels(opts.rels, 1, f, RELS.WB);
7889
7890 /* TODO: something more intelligent with themes */
7891
7892 f = "xl/theme/theme1.xml";
7893 zip_add_file(zip, f, write_theme(wb.Themes, opts));
7894 ct.themes.push(f);
7895 add_rels(opts.wbrels, -1, "theme/theme1.xml", RELS.THEME);
7896
7897 /* TODO: something more intelligent with styles */
7898
7899 f = "xl/styles." + wbext;
7900 zip_add_file(zip, f, write_sty(wb, f, opts));
7901 ct.styles.push(f);
7902 add_rels(opts.wbrels, -1, "styles." + wbext, RELS.STY);
7903
7904 if(wb.vbaraw && vbafmt) {
7905 f = "xl/vbaProject.bin";
7906 zip_add_file(zip, f, wb.vbaraw);
7907 ct.vba.push(f);
7908 add_rels(opts.wbrels, -1, "vbaProject.bin", RELS.VBA);
7909 }
7910
7911 zip_add_file(zip, "[Content_Types].xml", write_ct(ct, opts));
7912 zip_add_file(zip, '_rels/.rels', write_rels(opts.rels));
7913 zip_add_file(zip, 'xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));
7914
7915 delete opts.revssf; delete opts.ssf;
7916 return zip;
7917}
7918function firstbyte(f,o) {
7919 var x = "";
7920 switch((o||{}).type || "base64") {
7921 case 'buffer': return [f[0], f[1], f[2], f[3]];
7922 case 'base64': x = Base64.decode(f.slice(0,24)); break;
7923 case 'binary': x = f; break;
7924 case 'array': return [f[0], f[1], f[2], f[3]];
7925 default: throw new Error("Unrecognized type " + (o && o.type || "undefined"));
7926 }
7927 return [x.charCodeAt(0), x.charCodeAt(1), x.charCodeAt(2), x.charCodeAt(3)];
7928}
7929
7930function read_cfb(cfb, opts) {
7931 if(CFB.find(cfb, "EncryptedPackage")) return parse_xlsxcfb(cfb, opts);
7932 return parse_xlscfb(cfb, opts);
7933}
7934
7935function read_zip(data, opts) {
7936var zip, d = data;
7937 var o = opts||{};
7938 if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
7939 zip = zip_read(d, o);
7940 return parse_zip(zip, o);
7941}
7942
7943function read_plaintext(data, o) {
7944 var i = 0;
7945 main: while(i < data.length) switch(data.charCodeAt(i)) {
7946 case 0x0A: case 0x0D: case 0x20: ++i; break;
7947 case 0x3C: return parse_xlml(data.slice(i),o);
7948 default: break main;
7949 }
7950 return PRN.to_workbook(data, o);
7951}
7952
7953function read_plaintext_raw(data, o) {
7954 var str = "", bytes = firstbyte(data, o);
7955 switch(o.type) {
7956 case 'base64': str = Base64.decode(data); break;
7957 case 'binary': str = data; break;
7958 case 'buffer': str = data.toString('binary'); break;
7959 case 'array': str = cc2str(data); break;
7960 default: throw new Error("Unrecognized type " + o.type);
7961 }
7962 if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str);
7963 return read_plaintext(str, o);
7964}
7965
7966function read_utf16(data, o) {
7967 var d = data;
7968 if(o.type == 'base64') d = Base64.decode(d);
7969 d = cptable.utils.decode(1200, d.slice(2), 'str');
7970 o.type = "binary";
7971 return read_plaintext(d, o);
7972}
7973
7974function bstrify(data) {
7975 return !data.match(/[^\x00-\x7F]/) ? data : utf8write(data);
7976}
7977
7978function read_prn(data, d, o, str) {
7979 if(str) { o.type = "string"; return PRN.to_workbook(data, o); }
7980 return PRN.to_workbook(d, o);
7981}
7982
7983function readSync(data, opts) {
7984 reset_cp();
7985 if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), opts);
7986 var d = data, n = [0,0,0,0], str = false;
7987 var o = opts||{};
7988 if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; }
7989 _ssfopts = {};
7990 if(o.dateNF) _ssfopts.dateNF = o.dateNF;
7991 if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
7992 if(o.type == "file") { o.type = has_buf ? "buffer" : "binary"; d = read_binary(data); }
7993 if(o.type == "string") { str = true; o.type = "binary"; o.codepage = 65001; d = bstrify(data); }
7994 if(o.type == 'array' && typeof Uint8Array !== 'undefined' && data instanceof Uint8Array && typeof ArrayBuffer !== 'undefined') {
7995 // $FlowIgnore
7996 var ab=new ArrayBuffer(3), vu=new Uint8Array(ab); vu.foo="bar";
7997 // $FlowIgnore
7998 if(!vu.foo) {o=dup(o); o.type='array'; return readSync(ab2a(d), o);}
7999 }
8000 switch((n = firstbyte(d, o))[0]) {
8001 case 0xD0: return read_cfb(CFB.read(d, o), o);
8002 case 0x09: if(n[1] <= 0x04) return parse_xlscfb(d, o); break;
8003 case 0x3C: return parse_xlml(d, o);
8004 case 0x49: if(n[1] === 0x44) return read_wb_ID(d, o); break;
8005 case 0x54: if(n[1] === 0x41 && n[2] === 0x42 && n[3] === 0x4C) return DIF.to_workbook(d, o); break;
8006 case 0x50: return (n[1] === 0x4B && n[2] < 0x09 && n[3] < 0x09) ? read_zip(d, o) : read_prn(data, d, o, str);
8007 case 0xEF: return n[3] === 0x3C ? parse_xlml(d, o) : read_prn(data, d, o, str);
8008 case 0xFF: if(n[1] === 0xFE) { return read_utf16(d, o); } break;
8009 case 0x00: if(n[1] === 0x00 && n[2] >= 0x02 && n[3] === 0x00) return WK_.to_workbook(d, o); break;
8010 case 0x03: case 0x83: case 0x8B: case 0x8C: return DBF.to_workbook(d, o);
8011 case 0x7B: if(n[1] === 0x5C && n[2] === 0x72 && n[3] === 0x74) return RTF.to_workbook(d, o); break;
8012 case 0x0A: case 0x0D: case 0x20: return read_plaintext_raw(d, o);
8013 }
8014 if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
8015 return read_prn(data, d, o, str);
8016}
8017
8018function readFileSync(filename, opts) {
8019 var o = opts||{}; o.type = 'file';
8020 return readSync(filename, o);
8021}
8022function write_cfb_ctr(cfb, o) {
8023 switch(o.type) {
8024 case "base64": case "binary": break;
8025 case "buffer": case "array": o.type = ""; break;
8026 case "file": return write_dl(o.file, CFB.write(cfb, {type:has_buf ? 'buffer' : ""}));
8027 case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files");
8028 default: throw new Error("Unrecognized type " + o.type);
8029 }
8030 return CFB.write(cfb, o);
8031}
8032
8033function write_zip_type(wb, opts) {
8034 var o = opts||{};
8035 var z = write_zip(wb, o);
8036 var oopts = {};
8037 if(o.compression) oopts.compression = 'DEFLATE';
8038 if(o.password) oopts.type = has_buf ? "nodebuffer" : "string";
8039 else switch(o.type) {
8040 case "base64": oopts.type = "base64"; break;
8041 case "binary": oopts.type = "string"; break;
8042 case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files");
8043 case "buffer":
8044 case "file": oopts.type = has_buf ? "nodebuffer" : "string"; break;
8045 default: throw new Error("Unrecognized type " + o.type);
8046 }
8047 var out = z.FullPaths ? CFB.write(z, {fileType:"zip", type: {"nodebuffer": "buffer", "string": "binary"}[oopts.type] || oopts.type}) : z.generate(oopts);
8048/*jshint -W083 */
8049 if(o.password && typeof encrypt_agile !== 'undefined') return write_cfb_ctr(encrypt_agile(out, o.password), o); // eslint-disable-line no-undef
8050/*jshint +W083 */
8051 if(o.type === "file") return write_dl(o.file, out);
8052 return o.type == "string" ? utf8read(out) : out;
8053}
8054
8055function write_cfb_type(wb, opts) {
8056 var o = opts||{};
8057 var cfb = write_xlscfb(wb, o);
8058 return write_cfb_ctr(cfb, o);
8059}
8060
8061function write_string_type(out, opts, bom) {
8062 if(!bom) bom = "";
8063 var o = bom + out;
8064 switch(opts.type) {
8065 case "base64": return Base64.encode(utf8write(o));
8066 case "binary": return utf8write(o);
8067 case "string": return out;
8068 case "file": return write_dl(opts.file, o, 'utf8');
8069 case "buffer": {
8070 if(has_buf) return Buffer_from(o, 'utf8');
8071 else return write_string_type(o, {type:'binary'}).split("").map(function(c) { return c.charCodeAt(0); });
8072 }
8073 }
8074 throw new Error("Unrecognized type " + opts.type);
8075}
8076
8077function write_stxt_type(out, opts) {
8078 switch(opts.type) {
8079 case "base64": return Base64.encode(out);
8080 case "binary": return out;
8081 case "string": return out; /* override in sheet_to_txt */
8082 case "file": return write_dl(opts.file, out, 'binary');
8083 case "buffer": {
8084 if(has_buf) return Buffer_from(out, 'binary');
8085 else return out.split("").map(function(c) { return c.charCodeAt(0); });
8086 }
8087 }
8088 throw new Error("Unrecognized type " + opts.type);
8089}
8090
8091/* TODO: test consistency */
8092function write_binary_type(out, opts) {
8093 switch(opts.type) {
8094 case "string":
8095 case "base64":
8096 case "binary":
8097 var bstr = "";
8098 // $FlowIgnore
8099 for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]);
8100 return opts.type == 'base64' ? Base64.encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr;
8101 case "file": return write_dl(opts.file, out);
8102 case "buffer": return out;
8103 default: throw new Error("Unrecognized type " + opts.type);
8104 }
8105}
8106
8107function writeSync(wb, opts) {
8108 reset_cp();
8109 check_wb(wb);
8110 var o = opts||{};
8111 if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; }
8112 if(o.type == "array") { o.type = "binary"; var out = (writeSync(wb, o)); o.type = "array"; return s2ab(out); }
8113 switch(o.bookType || 'xlsb') {
8114 case 'xml':
8115 case 'xlml': return write_string_type(write_xlml(wb, o), o);
8116 case 'slk':
8117 case 'sylk': return write_string_type(write_slk_str(wb, o), o);
8118 case 'htm':
8119 case 'html': return write_string_type(write_htm_str(wb, o), o);
8120 case 'txt': return write_stxt_type(write_txt_str(wb, o), o);
8121 case 'csv': return write_string_type(write_csv_str(wb, o), o, "\ufeff");
8122 case 'dif': return write_string_type(write_dif_str(wb, o), o);
8123 case 'dbf': return write_binary_type(write_dbf_buf(wb, o), o);
8124 case 'prn': return write_string_type(write_prn_str(wb, o), o);
8125 case 'rtf': return write_string_type(write_rtf_str(wb, o), o);
8126 case 'eth': return write_string_type(write_eth_str(wb, o), o);
8127 case 'fods': return write_string_type(write_ods(wb, o), o);
8128 case 'biff2': if(!o.biff) o.biff = 2; /* falls through */
8129 case 'biff3': if(!o.biff) o.biff = 3; /* falls through */
8130 case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o);
8131 case 'biff5': if(!o.biff) o.biff = 5; /* falls through */
8132 case 'biff8':
8133 case 'xla':
8134 case 'xls': if(!o.biff) o.biff = 8; return write_cfb_type(wb, o);
8135 case 'xlsx':
8136 case 'xlsm':
8137 case 'xlam':
8138 case 'xlsb':
8139 case 'ods': return write_zip_type(wb, o);
8140 default: throw new Error ("Unrecognized bookType |" + o.bookType + "|");
8141 }
8142}
8143
8144function resolve_book_type(o) {
8145 if(o.bookType) return;
8146 var _BT = {
8147 "xls": "biff8",
8148 "htm": "html",
8149 "slk": "sylk",
8150 "socialcalc": "eth",
8151 "Sh33tJS": "WTF"
8152 };
8153 var ext = o.file.slice(o.file.lastIndexOf(".")).toLowerCase();
8154 if(ext.match(/^\.[a-z]+$/)) o.bookType = ext.slice(1);
8155 o.bookType = _BT[o.bookType] || o.bookType;
8156}
8157
8158function writeFileSync(wb, filename, opts) {
8159 var o = opts||{}; o.type = 'file';
8160 o.file = filename;
8161 resolve_book_type(o);
8162 return writeSync(wb, o);
8163}
8164
8165function writeFileAsync(filename, wb, opts, cb) {
8166 var o = opts||{}; o.type = 'file';
8167 o.file = filename;
8168 resolve_book_type(o);
8169 o.type = 'buffer';
8170 var _cb = cb; if(!(_cb instanceof Function)) _cb = (opts);
8171 return _fs.writeFile(filename, writeSync(wb, o), _cb);
8172}
8173function make_json_row(sheet, r, R, cols, header, hdr, dense, o) {
8174 var rr = encode_row(R);
8175 var defval = o.defval, raw = o.raw || !Object.prototype.hasOwnProperty.call(o, "raw");
8176 var isempty = true;
8177 var row = (header === 1) ? [] : {};
8178 if(header !== 1) {
8179 if(Object.defineProperty) try { Object.defineProperty(row, '__rowNum__', {value:R, enumerable:false}); } catch(e) { row.__rowNum__ = R; }
8180 else row.__rowNum__ = R;
8181 }
8182 if(!dense || sheet[R]) for (var C = r.s.c; C <= r.e.c; ++C) {
8183 var val = dense ? sheet[R][C] : sheet[cols[C] + rr];
8184 if(val === undefined || val.t === undefined) {
8185 if(defval === undefined) continue;
8186 if(hdr[C] != null) { row[hdr[C]] = defval; }
8187 continue;
8188 }
8189 var v = val.v;
8190 switch(val.t){
8191 case 'z': if(v == null) break; continue;
8192 case 'e': v = void 0; break;
8193 case 's': case 'd': case 'b': case 'n': break;
8194 default: throw new Error('unrecognized type ' + val.t);
8195 }
8196 if(hdr[C] != null) {
8197 if(v == null) {
8198 if(defval !== undefined) row[hdr[C]] = defval;
8199 else if(raw && v === null) row[hdr[C]] = null;
8200 else continue;
8201 } else {
8202 row[hdr[C]] = raw ? v : format_cell(val,v,o);
8203 }
8204 if(v != null) isempty = false;
8205 }
8206 }
8207 return { row: row, isempty: isempty };
8208}
8209
8210
8211function sheet_to_json(sheet, opts) {
8212 if(sheet == null || sheet["!ref"] == null) return [];
8213 var val = {t:'n',v:0}, header = 0, offset = 1, hdr = [], v=0, vv="";
8214 var r = {s:{r:0,c:0},e:{r:0,c:0}};
8215 var o = opts || {};
8216 var range = o.range != null ? o.range : sheet["!ref"];
8217 if(o.header === 1) header = 1;
8218 else if(o.header === "A") header = 2;
8219 else if(Array.isArray(o.header)) header = 3;
8220 else if(o.header == null) header = 0;
8221 switch(typeof range) {
8222 case 'string': r = safe_decode_range(range); break;
8223 case 'number': r = safe_decode_range(sheet["!ref"]); r.s.r = range; break;
8224 default: r = range;
8225 }
8226 if(header > 0) offset = 0;
8227 var rr = encode_row(r.s.r);
8228 var cols = [];
8229 var out = [];
8230 var outi = 0, counter = 0;
8231 var dense = Array.isArray(sheet);
8232 var R = r.s.r, C = 0, CC = 0;
8233 if(dense && !sheet[R]) sheet[R] = [];
8234 for(C = r.s.c; C <= r.e.c; ++C) {
8235 cols[C] = encode_col(C);
8236 val = dense ? sheet[R][C] : sheet[cols[C] + rr];
8237 switch(header) {
8238 case 1: hdr[C] = C - r.s.c; break;
8239 case 2: hdr[C] = cols[C]; break;
8240 case 3: hdr[C] = o.header[C - r.s.c]; break;
8241 default:
8242 if(val == null) val = {w: "__EMPTY", t: "s"};
8243 vv = v = format_cell(val, null, o);
8244 counter = 0;
8245 for(CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter);
8246 hdr[C] = vv;
8247 }
8248 }
8249 for (R = r.s.r + offset; R <= r.e.r; ++R) {
8250 var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o);
8251 if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) out[outi++] = row.row;
8252 }
8253 out.length = outi;
8254 return out;
8255}
8256
8257var qreg = /"/g;
8258function make_csv_row(sheet, r, R, cols, fs, rs, FS, o) {
8259 var isempty = true;
8260 var row = [], txt = "", rr = encode_row(R);
8261 for(var C = r.s.c; C <= r.e.c; ++C) {
8262 if (!cols[C]) continue;
8263 var val = o.dense ? (sheet[R]||[])[C]: sheet[cols[C] + rr];
8264 if(val == null) txt = "";
8265 else if(val.v != null) {
8266 isempty = false;
8267 txt = ''+format_cell(val, null, o);
8268 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; }
8269 if(txt == "ID") txt = '"ID"';
8270 } else if(val.f != null && !val.F) {
8271 isempty = false;
8272 txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"';
8273 } else txt = "";
8274 /* NOTE: Excel CSV does not support array formulae */
8275 row.push(txt);
8276 }
8277 if(o.blankrows === false && isempty) return null;
8278 return row.join(FS);
8279}
8280
8281function sheet_to_csv(sheet, opts) {
8282 var out = [];
8283 var o = opts == null ? {} : opts;
8284 if(sheet == null || sheet["!ref"] == null) return "";
8285 var r = safe_decode_range(sheet["!ref"]);
8286 var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
8287 var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
8288 var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
8289 var row = "", cols = [];
8290 o.dense = Array.isArray(sheet);
8291 var colinfo = o.skipHidden && sheet["!cols"] || [];
8292 var rowinfo = o.skipHidden && sheet["!rows"] || [];
8293 for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
8294 for(var R = r.s.r; R <= r.e.r; ++R) {
8295 if ((rowinfo[R]||{}).hidden) continue;
8296 row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o);
8297 if(row == null) { continue; }
8298 if(o.strip) row = row.replace(endregex,"");
8299 out.push(row + RS);
8300 }
8301 delete o.dense;
8302 return out.join("");
8303}
8304
8305function sheet_to_txt(sheet, opts) {
8306 if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n";
8307 var s = sheet_to_csv(sheet, opts);
8308 if(typeof cptable == 'undefined' || opts.type == 'string') return s;
8309 var o = cptable.utils.encode(1200, s, 'str');
8310 return String.fromCharCode(255) + String.fromCharCode(254) + o;
8311}
8312
8313function sheet_to_formulae(sheet) {
8314 var y = "", x, val="";
8315 if(sheet == null || sheet["!ref"] == null) return [];
8316 var r = safe_decode_range(sheet['!ref']), rr = "", cols = [], C;
8317 var cmds = [];
8318 var dense = Array.isArray(sheet);
8319 for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C);
8320 for(var R = r.s.r; R <= r.e.r; ++R) {
8321 rr = encode_row(R);
8322 for(C = r.s.c; C <= r.e.c; ++C) {
8323 y = cols[C] + rr;
8324 x = dense ? (sheet[R]||[])[C] : sheet[y];
8325 val = "";
8326 if(x === undefined) continue;
8327 else if(x.F != null) {
8328 y = x.F;
8329 if(!x.f) continue;
8330 val = x.f;
8331 if(y.indexOf(":") == -1) y = y + ":" + y;
8332 }
8333 if(x.f != null) val = x.f;
8334 else if(x.t == 'z') continue;
8335 else if(x.t == 'n' && x.v != null) val = "" + x.v;
8336 else if(x.t == 'b') val = x.v ? "TRUE" : "FALSE";
8337 else if(x.w !== undefined) val = "'" + x.w;
8338 else if(x.v === undefined) continue;
8339 else if(x.t == 's') val = "'" + x.v;
8340 else val = ""+x.v;
8341 cmds[cmds.length] = y + "=" + val;
8342 }
8343 }
8344 return cmds;
8345}
8346
8347function sheet_add_json(_ws, js, opts) {
8348 var o = opts || {};
8349 var offset = +!o.skipHeader;
8350 var ws = _ws || ({});
8351 var _R = 0, _C = 0;
8352 if(ws && o.origin != null) {
8353 if(typeof o.origin == 'number') _R = o.origin;
8354 else {
8355 var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
8356 _R = _origin.r; _C = _origin.c;
8357 }
8358 }
8359 var cell;
8360 var range = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}});
8361 if(ws['!ref']) {
8362 var _range = safe_decode_range(ws['!ref']);
8363 range.e.c = Math.max(range.e.c, _range.e.c);
8364 range.e.r = Math.max(range.e.r, _range.e.r);
8365 if(_R == -1) { _R = range.e.r + 1; range.e.r = _R + js.length - 1 + offset; }
8366 }
8367 var hdr = o.header || [], C = 0;
8368
8369 js.forEach(function (JS, R) {
8370 keys(JS).forEach(function(k) {
8371 if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k;
8372 var v = JS[k];
8373 var t = 'z';
8374 var z = "";
8375 var ref = encode_cell({c:_C + C,r:_R + R + offset});
8376 cell = utils.sheet_get_cell(ws, ref);
8377 if(v && typeof v === 'object' && !(v instanceof Date)){
8378 ws[ref] = v;
8379 } else {
8380 if(typeof v == 'number') t = 'n';
8381 else if(typeof v == 'boolean') t = 'b';
8382 else if(typeof v == 'string') t = 's';
8383 else if(v instanceof Date) {
8384 t = 'd';
8385 if(!o.cellDates) { t = 'n'; v = datenum(v); }
8386 z = (o.dateNF || SSF._table[14]);
8387 }
8388 if(!cell) ws[ref] = cell = ({t:t, v:v});
8389 else {
8390 cell.t = t; cell.v = v;
8391 delete cell.w; delete cell.R;
8392 if(z) cell.z = z;
8393 }
8394 if(z) cell.z = z;
8395 }
8396 });
8397 });
8398 range.e.c = Math.max(range.e.c, _C + hdr.length - 1);
8399 var __R = encode_row(_R);
8400 if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]};
8401 ws['!ref'] = encode_range(range);
8402 return ws;
8403}
8404function json_to_sheet(js, opts) { return sheet_add_json(null, js, opts); }
8405
8406var utils = {
8407 encode_col: encode_col,
8408 encode_row: encode_row,
8409 encode_cell: encode_cell,
8410 encode_range: encode_range,
8411 decode_col: decode_col,
8412 decode_row: decode_row,
8413 split_cell: split_cell,
8414 decode_cell: decode_cell,
8415 decode_range: decode_range,
8416 format_cell: format_cell,
8417 get_formulae: sheet_to_formulae,
8418 make_csv: sheet_to_csv,
8419 make_json: sheet_to_json,
8420 make_formulae: sheet_to_formulae,
8421 sheet_add_aoa: sheet_add_aoa,
8422 sheet_add_json: sheet_add_json,
8423 aoa_to_sheet: aoa_to_sheet,
8424 json_to_sheet: json_to_sheet,
8425 table_to_sheet: parse_dom_table,
8426 table_to_book: table_to_book,
8427 sheet_to_csv: sheet_to_csv,
8428 sheet_to_txt: sheet_to_txt,
8429 sheet_to_json: sheet_to_json,
8430 sheet_to_html: HTML_.from_sheet,
8431 sheet_to_formulae: sheet_to_formulae,
8432 sheet_to_row_object_array: sheet_to_json
8433};
8434
8435(function(utils) {
8436utils.consts = utils.consts || {};
8437function add_consts(R/*Array<any>*/) { R.forEach(function(a){ utils.consts[a[0]] = a[1]; }); }
8438
8439function get_default(x, y, z) { return x[y] != null ? x[y] : (x[y] = z); }
8440
8441/* get cell, creating a stub if necessary */
8442function ws_get_cell_stub(ws, R, C) {
8443 /* A1 cell address */
8444 if(typeof R == "string") {
8445 /* dense */
8446 if(Array.isArray(ws)) {
8447 var RC = decode_cell(R);
8448 if(!ws[RC.r]) ws[RC.r] = [];
8449 return ws[RC.r][RC.c] || (ws[RC.r][RC.c] = {t:'z'});
8450 }
8451 return ws[R] || (ws[R] = {t:'z'});
8452 }
8453 /* cell address object */
8454 if(typeof R != "number") return ws_get_cell_stub(ws, encode_cell(R));
8455 /* R and C are 0-based indices */
8456 return ws_get_cell_stub(ws, encode_cell({r:R,c:C||0}));
8457}
8458utils.sheet_get_cell = ws_get_cell_stub;
8459
8460/* find sheet index for given name / validate index */
8461function wb_sheet_idx(wb, sh) {
8462 if(typeof sh == "number") {
8463 if(sh >= 0 && wb.SheetNames.length > sh) return sh;
8464 throw new Error("Cannot find sheet # " + sh);
8465 } else if(typeof sh == "string") {
8466 var idx = wb.SheetNames.indexOf(sh);
8467 if(idx > -1) return idx;
8468 throw new Error("Cannot find sheet name |" + sh + "|");
8469 } else throw new Error("Cannot find sheet |" + sh + "|");
8470}
8471
8472/* simple blank workbook object */
8473utils.book_new = function() {
8474 return { SheetNames: [], Sheets: {} };
8475};
8476
8477/* add a worksheet to the end of a given workbook */
8478utils.book_append_sheet = function(wb, ws, name) {
8479 if(!name) for(var i = 1; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break;
8480 if(!name) throw new Error("Too many worksheets");
8481 check_ws_name(name);
8482 if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!");
8483
8484 wb.SheetNames.push(name);
8485 wb.Sheets[name] = ws;
8486};
8487
8488/* set sheet visibility (visible/hidden/very hidden) */
8489utils.book_set_sheet_visibility = function(wb, sh, vis) {
8490 get_default(wb,"Workbook",{});
8491 get_default(wb.Workbook,"Sheets",[]);
8492
8493 var idx = wb_sheet_idx(wb, sh);
8494 // $FlowIgnore
8495 get_default(wb.Workbook.Sheets,idx, {});
8496
8497 switch(vis) {
8498 case 0: case 1: case 2: break;
8499 default: throw new Error("Bad sheet visibility setting " + vis);
8500 }
8501 // $FlowIgnore
8502 wb.Workbook.Sheets[idx].Hidden = vis;
8503};
8504add_consts([
8505 ["SHEET_VISIBLE", 0],
8506 ["SHEET_HIDDEN", 1],
8507 ["SHEET_VERY_HIDDEN", 2]
8508]);
8509
8510/* set number format */
8511utils.cell_set_number_format = function(cell, fmt) {
8512 cell.z = fmt;
8513 return cell;
8514};
8515
8516/* set cell hyperlink */
8517utils.cell_set_hyperlink = function(cell, target, tooltip) {
8518 if(!target) {
8519 delete cell.l;
8520 } else {
8521 cell.l = ({ Target: target });
8522 if(tooltip) cell.l.Tooltip = tooltip;
8523 }
8524 return cell;
8525};
8526utils.cell_set_internal_link = function(cell, range, tooltip) { return utils.cell_set_hyperlink(cell, "#" + range, tooltip); };
8527
8528/* add to cell comments */
8529utils.cell_add_comment = function(cell, text, author) {
8530 if(!cell.c) cell.c = [];
8531 cell.c.push({t:text, a:author||"SheetJS"});
8532};
8533
8534/* set array formula and flush related cells */
8535utils.sheet_set_array_formula = function(ws, range, formula) {
8536 var rng = typeof range != "string" ? range : safe_decode_range(range);
8537 var rngstr = typeof range == "string" ? range : encode_range(range);
8538 for(var R = rng.s.r; R <= rng.e.r; ++R) for(var C = rng.s.c; C <= rng.e.c; ++C) {
8539 var cell = ws_get_cell_stub(ws, R, C);
8540 cell.t = 'n';
8541 cell.F = rngstr;
8542 delete cell.v;
8543 if(R == rng.s.r && C == rng.s.c) cell.f = formula;
8544 }
8545 return ws;
8546};
8547
8548return utils;
8549})(utils);
8550
8551if(typeof parse_xlscfb !== "undefined") XLSX.parse_xlscfb = parse_xlscfb;
8552XLSX.parse_zip = parse_zip;
8553XLSX.read = readSync; //xlsread
8554XLSX.readFile = readFileSync; //readFile
8555XLSX.readFileSync = readFileSync;
8556XLSX.write = writeSync;
8557XLSX.writeFile = writeFileSync;
8558XLSX.writeFileSync = writeFileSync;
8559XLSX.writeFileAsync = writeFileAsync;
8560XLSX.utils = utils;
8561XLSX.SSF = SSF;
8562if(typeof CFB !== "undefined") XLSX.CFB = CFB;
8563}
8564/*global define */
8565if(typeof exports !== 'undefined') make_xlsx_lib(exports);
8566else if(typeof module !== 'undefined' && module.exports) make_xlsx_lib(module.exports);
8567else if(typeof define === 'function' && define.amd) define('xlsx', function() { if(!XLSX.version) make_xlsx_lib(XLSX); return XLSX; });
8568else make_xlsx_lib(XLSX);
8569/*exported XLS, ODS */
8570var XLS = XLSX, ODS = XLSX;