UNPKG

763 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.17.4';
8var current_codepage = 1200, current_ansi = 1252;
9/*global cptable:true, window */
10if(typeof module !== "undefined" && typeof require !== 'undefined') {
11 if(typeof cptable === 'undefined') {
12 if(typeof global !== 'undefined') global.cptable = undefined;
13 else if(typeof window !== 'undefined') window.cptable = undefined;
14 }
15}
16
17var VALID_ANSI = [ 874, 932, 936, 949, 950 ];
18for(var i = 0; i <= 8; ++i) VALID_ANSI.push(1250 + i);
19/* ECMA-376 Part I 18.4.1 charset to codepage mapping */
20var CS2CP = ({
210: 1252, /* ANSI */
221: 65001, /* DEFAULT */
232: 65001, /* SYMBOL */
2477: 10000, /* MAC */
25128: 932, /* SHIFTJIS */
26129: 949, /* HANGUL */
27130: 1361, /* JOHAB */
28134: 936, /* GB2312 */
29136: 950, /* CHINESEBIG5 */
30161: 1253, /* GREEK */
31162: 1254, /* TURKISH */
32163: 1258, /* VIETNAMESE */
33177: 1255, /* HEBREW */
34178: 1256, /* ARABIC */
35186: 1257, /* BALTIC */
36204: 1251, /* RUSSIAN */
37222: 874, /* THAI */
38238: 1250, /* EASTEUROPE */
39255: 1252, /* OEM */
4069: 6969 /* MISC */
41});
42
43var set_ansi = function(cp) { if(VALID_ANSI.indexOf(cp) == -1) return; current_ansi = CS2CP[0] = cp; };
44function reset_ansi() { set_ansi(1252); }
45
46var set_cp = function(cp) { current_codepage = cp; set_ansi(cp); };
47function reset_cp() { set_cp(1200); reset_ansi(); }
48
49function char_codes(data) { var o = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; }
50
51function utf16leread(data) {
52 var o = [];
53 for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i) + (data.charCodeAt(2*i+1)<<8));
54 return o.join("");
55}
56function utf16beread(data) {
57 var o = [];
58 for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i+1) + (data.charCodeAt(2*i)<<8));
59 return o.join("");
60}
61
62var debom = function(data) {
63 var c1 = data.charCodeAt(0), c2 = data.charCodeAt(1);
64 if(c1 == 0xFF && c2 == 0xFE) return utf16leread(data.slice(2));
65 if(c1 == 0xFE && c2 == 0xFF) return utf16beread(data.slice(2));
66 if(c1 == 0xFEFF) return data.slice(1);
67 return data;
68};
69
70var _getchar = function _gc1(x) { return String.fromCharCode(x); };
71var _getansi = function _ga1(x) { return String.fromCharCode(x); };
72if(typeof cptable !== 'undefined') {
73 set_cp = function(cp) { current_codepage = cp; set_ansi(cp); };
74 debom = function(data) {
75 if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.slice(2))); }
76 return data;
77 };
78 _getchar = function _gc2(x) {
79 if(current_codepage === 1200) return String.fromCharCode(x);
80 return cptable.utils.decode(current_codepage, [x&255,x>>8])[0];
81 };
82 _getansi = function _ga2(x) {
83 return cptable.utils.decode(current_ansi, [x])[0];
84 };
85}
86var DENSE = null;
87var DIF_XL = true;
88var Base64 = (function make_b64(){
89 var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
90 return {
91 encode: function(input) {
92 var o = "";
93 var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0;
94 for(var i = 0; i < input.length; ) {
95 c1 = input.charCodeAt(i++);
96 e1 = (c1 >> 2);
97
98 c2 = input.charCodeAt(i++);
99 e2 = ((c1 & 3) << 4) | (c2 >> 4);
100
101 c3 = input.charCodeAt(i++);
102 e3 = ((c2 & 15) << 2) | (c3 >> 6);
103 e4 = (c3 & 63);
104 if (isNaN(c2)) { e3 = e4 = 64; }
105 else if (isNaN(c3)) { e4 = 64; }
106 o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4);
107 }
108 return o;
109 },
110 decode: function b64_decode(input) {
111 var o = "";
112 var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0;
113 input = input.replace(/[^\w\+\/\=]/g, "");
114 for(var i = 0; i < input.length;) {
115 e1 = map.indexOf(input.charAt(i++));
116 e2 = map.indexOf(input.charAt(i++));
117 c1 = (e1 << 2) | (e2 >> 4);
118 o += String.fromCharCode(c1);
119
120 e3 = map.indexOf(input.charAt(i++));
121 c2 = ((e2 & 15) << 4) | (e3 >> 2);
122 if (e3 !== 64) { o += String.fromCharCode(c2); }
123
124 e4 = map.indexOf(input.charAt(i++));
125 c3 = ((e3 & 3) << 6) | e4;
126 if (e4 !== 64) { o += String.fromCharCode(c3); }
127 }
128 return o;
129 }
130 };
131})();
132var has_buf = (typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.node);
133
134var Buffer_from = function(){};
135
136if(typeof Buffer !== 'undefined') {
137 var nbfs = !Buffer.from;
138 if(!nbfs) try { Buffer.from("foo", "utf8"); } catch(e) { nbfs = true; }
139 Buffer_from = nbfs ? function(buf, enc) { return (enc) ? new Buffer(buf, enc) : new Buffer(buf); } : Buffer.from.bind(Buffer);
140 // $FlowIgnore
141 if(!Buffer.alloc) Buffer.alloc = function(n) { return new Buffer(n); };
142 // $FlowIgnore
143 if(!Buffer.allocUnsafe) Buffer.allocUnsafe = function(n) { return new Buffer(n); };
144}
145
146function new_raw_buf(len) {
147 /* jshint -W056 */
148 return has_buf ? Buffer.alloc(len) : new Array(len);
149 /* jshint +W056 */
150}
151
152function new_unsafe_buf(len) {
153 /* jshint -W056 */
154 return has_buf ? Buffer.allocUnsafe(len) : new Array(len);
155 /* jshint +W056 */
156}
157
158var s2a = function s2a(s) {
159 if(has_buf) return Buffer_from(s, "binary");
160 return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; });
161};
162
163function s2ab(s) {
164 if(typeof ArrayBuffer === 'undefined') return s2a(s);
165 var buf = new ArrayBuffer(s.length), view = new Uint8Array(buf);
166 for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
167 return buf;
168}
169
170function a2s(data) {
171 if(Array.isArray(data)) return data.map(function(c) { return String.fromCharCode(c); }).join("");
172 var o = []; for(var i = 0; i < data.length; ++i) o[i] = String.fromCharCode(data[i]); return o.join("");
173}
174
175function a2u(data) {
176 if(typeof Uint8Array === 'undefined') throw new Error("Unsupported");
177 return new Uint8Array(data);
178}
179
180function ab2a(data) {
181 if(typeof ArrayBuffer == 'undefined') throw new Error("Unsupported");
182 if(data instanceof ArrayBuffer) return ab2a(new Uint8Array(data));
183var o = new Array(data.length);
184 for(var i = 0; i < data.length; ++i) o[i] = data[i];
185 return o;
186}
187
188var bconcat = function(bufs) { return [].concat.apply([], bufs); };
189
190var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/g;
191/* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */
192/*jshint -W041 */
193var SSF = ({});
194var make_ssf = function make_ssf(SSF){
195SSF.version = '0.11.2';
196function _strrev(x) { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; }
197function fill(c,l) { var o = ""; while(o.length < l) o+=c; return o; }
198function pad0(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
199function pad_(v,d){var t=""+v;return t.length>=d?t:fill(' ',d-t.length)+t;}
200function rpad_(v,d){var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);}
201function pad0r1(v,d){var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;}
202function pad0r2(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
203var p2_32 = Math.pow(2,32);
204function pad0r(v,d){if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); }
205function 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; }
206var days = [
207 ['Sun', 'Sunday'],
208 ['Mon', 'Monday'],
209 ['Tue', 'Tuesday'],
210 ['Wed', 'Wednesday'],
211 ['Thu', 'Thursday'],
212 ['Fri', 'Friday'],
213 ['Sat', 'Saturday']
214];
215var months = [
216 ['J', 'Jan', 'January'],
217 ['F', 'Feb', 'February'],
218 ['M', 'Mar', 'March'],
219 ['A', 'Apr', 'April'],
220 ['M', 'May', 'May'],
221 ['J', 'Jun', 'June'],
222 ['J', 'Jul', 'July'],
223 ['A', 'Aug', 'August'],
224 ['S', 'Sep', 'September'],
225 ['O', 'Oct', 'October'],
226 ['N', 'Nov', 'November'],
227 ['D', 'Dec', 'December']
228];
229function init_table(t) {
230 t[0]= 'General';
231 t[1]= '0';
232 t[2]= '0.00';
233 t[3]= '#,##0';
234 t[4]= '#,##0.00';
235 t[9]= '0%';
236 t[10]= '0.00%';
237 t[11]= '0.00E+00';
238 t[12]= '# ?/?';
239 t[13]= '# ??/??';
240 t[14]= 'm/d/yy';
241 t[15]= 'd-mmm-yy';
242 t[16]= 'd-mmm';
243 t[17]= 'mmm-yy';
244 t[18]= 'h:mm AM/PM';
245 t[19]= 'h:mm:ss AM/PM';
246 t[20]= 'h:mm';
247 t[21]= 'h:mm:ss';
248 t[22]= 'm/d/yy h:mm';
249 t[37]= '#,##0 ;(#,##0)';
250 t[38]= '#,##0 ;[Red](#,##0)';
251 t[39]= '#,##0.00;(#,##0.00)';
252 t[40]= '#,##0.00;[Red](#,##0.00)';
253 t[45]= 'mm:ss';
254 t[46]= '[h]:mm:ss';
255 t[47]= 'mmss.0';
256 t[48]= '##0.0E+0';
257 t[49]= '@';
258 t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "';
259}
260
261var table_fmt = {};
262init_table(table_fmt);
263/* Defaults determined by systematically testing in Excel 2019 */
264
265/* These formats appear to default to other formats in the table */
266var default_map = [];
267var defi = 0;
268
269// 5 -> 37 ... 8 -> 40
270for(defi = 5; defi <= 8; ++defi) default_map[defi] = 32 + defi;
271
272// 23 -> 0 ... 26 -> 0
273for(defi = 23; defi <= 26; ++defi) default_map[defi] = 0;
274
275// 27 -> 14 ... 31 -> 14
276for(defi = 27; defi <= 31; ++defi) default_map[defi] = 14;
277// 50 -> 14 ... 58 -> 14
278for(defi = 50; defi <= 58; ++defi) default_map[defi] = 14;
279
280// 59 -> 1 ... 62 -> 4
281for(defi = 59; defi <= 62; ++defi) default_map[defi] = defi - 58;
282// 67 -> 9 ... 68 -> 10
283for(defi = 67; defi <= 68; ++defi) default_map[defi] = defi - 58;
284// 72 -> 14 ... 75 -> 17
285for(defi = 72; defi <= 75; ++defi) default_map[defi] = defi - 58;
286
287// 69 -> 12 ... 71 -> 14
288for(defi = 67; defi <= 68; ++defi) default_map[defi] = defi - 57;
289
290// 76 -> 20 ... 78 -> 22
291for(defi = 76; defi <= 78; ++defi) default_map[defi] = defi - 56;
292
293// 79 -> 45 ... 81 -> 47
294for(defi = 79; defi <= 81; ++defi) default_map[defi] = defi - 34;
295
296// 82 -> 0 ... 65536 -> 0 (omitted)
297
298/* These formats technically refer to Accounting formats with no equivalent */
299var default_str = [];
300
301// 5 -- Currency, 0 decimal, black negative
302default_str[5] = default_str[63] = '"$"#,##0_);\\("$"#,##0\\)';
303// 6 -- Currency, 0 decimal, red negative
304default_str[6] = default_str[64] = '"$"#,##0_);[Red]\\("$"#,##0\\)';
305// 7 -- Currency, 2 decimal, black negative
306default_str[7] = default_str[65] = '"$"#,##0.00_);\\("$"#,##0.00\\)';
307// 8 -- Currency, 2 decimal, red negative
308default_str[8] = default_str[66] = '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)';
309
310// 41 -- Accounting, 0 decimal, No Symbol
311default_str[41] = '_(* #,##0_);_(* \\(#,##0\\);_(* "-"_);_(@_)';
312// 42 -- Accounting, 0 decimal, $ Symbol
313default_str[42] = '_("$"* #,##0_);_("$"* \\(#,##0\\);_("$"* "-"_);_(@_)';
314// 43 -- Accounting, 2 decimal, No Symbol
315default_str[43] = '_(* #,##0.00_);_(* \\(#,##0.00\\);_(* "-"??_);_(@_)';
316// 44 -- Accounting, 2 decimal, $ Symbol
317default_str[44] = '_("$"* #,##0.00_);_("$"* \\(#,##0.00\\);_("$"* "-"??_);_(@_)';
318function frac(x, D, mixed) {
319 var sgn = x < 0 ? -1 : 1;
320 var B = x * sgn;
321 var P_2 = 0, P_1 = 1, P = 0;
322 var Q_2 = 1, Q_1 = 0, Q = 0;
323 var A = Math.floor(B);
324 while(Q_1 < D) {
325 A = Math.floor(B);
326 P = A * P_1 + P_2;
327 Q = A * Q_1 + Q_2;
328 if((B - A) < 0.00000005) break;
329 B = 1 / (B - A);
330 P_2 = P_1; P_1 = P;
331 Q_2 = Q_1; Q_1 = Q;
332 }
333 if(Q > D) { if(Q_1 > D) { Q = Q_2; P = P_2; } else { Q = Q_1; P = P_1; } }
334 if(!mixed) return [0, sgn * P, Q];
335 var q = Math.floor(sgn * P/Q);
336 return [q, sgn*P - q*Q, Q];
337}
338function parse_date_code(v,opts,b2) {
339 if(v > 2958465 || v < 0) return null;
340 var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
341 var dout=[];
342 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};
343 if(Math.abs(out.u) < 1e-6) out.u = 0;
344 if(opts && opts.date1904) date += 1462;
345 if(out.u > 0.9999) {
346 out.u = 0;
347 if(++time == 86400) { out.T = time = 0; ++date; ++out.D; }
348 }
349 if(date === 60) {dout = b2 ? [1317,10,29] : [1900,2,29]; dow=3;}
350 else if(date === 0) {dout = b2 ? [1317,8,29] : [1900,1,0]; dow=6;}
351 else {
352 if(date > 60) --date;
353 /* 1 = Jan 1 1900 in Gregorian */
354 var d = new Date(1900, 0, 1);
355 d.setDate(d.getDate() + date - 1);
356 dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
357 dow = d.getDay();
358 if(date < 60) dow = (dow + 6) % 7;
359 if(b2) dow = fix_hijri(d, dout);
360 }
361 out.y = dout[0]; out.m = dout[1]; out.d = dout[2];
362 out.S = time % 60; time = Math.floor(time / 60);
363 out.M = time % 60; time = Math.floor(time / 60);
364 out.H = time;
365 out.q = dow;
366 return out;
367}
368SSF.parse_date_code = parse_date_code;
369var basedate = new Date(1899, 11, 31, 0, 0, 0);
370var dnthresh = basedate.getTime();
371var base1904 = new Date(1900, 2, 1, 0, 0, 0);
372function datenum_local(v, date1904) {
373 var epoch = v.getTime();
374 if(date1904) epoch -= 1461*24*60*60*1000;
375 else if(v >= base1904) epoch += 24*60*60*1000;
376 return (epoch - (dnthresh + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
377}
378/* The longest 32-bit integer text is "-4294967296", exactly 11 chars */
379function general_fmt_int(v) { return v.toString(10); }
380SSF._general_int = general_fmt_int;
381
382/* ECMA-376 18.8.30 numFmt*/
383/* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
384var general_fmt_num = (function make_general_fmt_num() {
385 var trailing_zeroes_and_decimal = /(?:\.0*|(\.\d*[1-9])0+)$/;
386 function strip_decimal(o) {
387 return (o.indexOf(".") == -1) ? o : o.replace(trailing_zeroes_and_decimal, "$1");
388 }
389
390 /* General Exponential always shows 2 digits exp and trims the mantissa */
391 var mantissa_zeroes_and_decimal = /(?:\.0*|(\.\d*[1-9])0+)[Ee]/;
392 var exp_with_single_digit = /(E[+-])(\d)$/;
393 function normalize_exp(o) {
394 if(o.indexOf("E") == -1) return o;
395 return o.replace(mantissa_zeroes_and_decimal,"$1E").replace(exp_with_single_digit,"$10$2");
396 }
397
398 /* exponent >= -9 and <= 9 */
399 function small_exp(v) {
400 var w = (v<0?12:11);
401 var o = strip_decimal(v.toFixed(12)); if(o.length <= w) return o;
402 o = v.toPrecision(10); if(o.length <= w) return o;
403 return v.toExponential(5);
404 }
405
406 /* exponent >= 11 or <= -10 likely exponential */
407 function large_exp(v) {
408 var o = strip_decimal(v.toFixed(11));
409 return (o.length > (v<0?12:11) || o === "0" || o === "-0") ? v.toPrecision(6) : o;
410 }
411
412 function general_fmt_num_base(v) {
413 var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
414
415 if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
416 else if(Math.abs(V) <= 9) o = small_exp(v);
417 else if(V === 10) o = v.toFixed(10).substr(0,12);
418 else o = large_exp(v);
419
420 return strip_decimal(normalize_exp(o.toUpperCase()));
421 }
422
423 return general_fmt_num_base;
424})();
425SSF._general_num = general_fmt_num;
426
427/*
428 "General" rules:
429 - text is passed through ("@")
430 - booleans are rendered as TRUE/FALSE
431 - "up to 11 characters" displayed for numbers
432 - Default date format (code 14) used for Dates
433
434 TODO: technically the display depends on the width of the cell
435*/
436function general_fmt(v, opts) {
437 switch(typeof v) {
438 case 'string': return v;
439 case 'boolean': return v ? "TRUE" : "FALSE";
440 case 'number': return (v|0) === v ? v.toString(10) : general_fmt_num(v);
441 case 'undefined': return "";
442 case 'object':
443 if(v == null) return "";
444 if(v instanceof Date) return format(14, datenum_local(v, opts && opts.date1904), opts);
445 }
446 throw new Error("unsupported value in General format: " + v);
447}
448SSF._general = general_fmt;
449function fix_hijri(date, o) {
450 /* TODO: properly adjust y/m/d and */
451 o[0] -= 581;
452 var dow = date.getDay();
453 if(date < 60) dow = (dow + 6) % 7;
454 return dow;
455}
456//var THAI_DIGITS = "\u0E50\u0E51\u0E52\u0E53\u0E54\u0E55\u0E56\u0E57\u0E58\u0E59".split("");
457/*jshint -W086 */
458function write_date(type, fmt, val, ss0) {
459 var o="", ss=0, tt=0, y = val.y, out, outl = 0;
460 switch(type) {
461 case 98: /* 'b' buddhist year */
462 y = val.y + 543;
463 /* falls through */
464 case 121: /* 'y' year */
465 switch(fmt.length) {
466 case 1: case 2: out = y % 100; outl = 2; break;
467 default: out = y % 10000; outl = 4; break;
468 } break;
469 case 109: /* 'm' month */
470 switch(fmt.length) {
471 case 1: case 2: out = val.m; outl = fmt.length; break;
472 case 3: return months[val.m-1][1];
473 case 5: return months[val.m-1][0];
474 default: return months[val.m-1][2];
475 } break;
476 case 100: /* 'd' day */
477 switch(fmt.length) {
478 case 1: case 2: out = val.d; outl = fmt.length; break;
479 case 3: return days[val.q][0];
480 default: return days[val.q][1];
481 } break;
482 case 104: /* 'h' 12-hour */
483 switch(fmt.length) {
484 case 1: case 2: out = 1+(val.H+11)%12; outl = fmt.length; break;
485 default: throw 'bad hour format: ' + fmt;
486 } break;
487 case 72: /* 'H' 24-hour */
488 switch(fmt.length) {
489 case 1: case 2: out = val.H; outl = fmt.length; break;
490 default: throw 'bad hour format: ' + fmt;
491 } break;
492 case 77: /* 'M' minutes */
493 switch(fmt.length) {
494 case 1: case 2: out = val.M; outl = fmt.length; break;
495 default: throw 'bad minute format: ' + fmt;
496 } break;
497 case 115: /* 's' seconds */
498 if(fmt != 's' && fmt != 'ss' && fmt != '.0' && fmt != '.00' && fmt != '.000') throw 'bad second format: ' + fmt;
499 if(val.u === 0 && (fmt == "s" || fmt == "ss")) return pad0(val.S, fmt.length);
500if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100;
501 else tt = ss0 === 1 ? 10 : 1;
502 ss = Math.round((tt)*(val.S + val.u));
503 if(ss >= 60*tt) ss = 0;
504 if(fmt === 's') return ss === 0 ? "0" : ""+ss/tt;
505 o = pad0(ss,2 + ss0);
506 if(fmt === 'ss') return o.substr(0,2);
507 return "." + o.substr(2,fmt.length-1);
508 case 90: /* 'Z' absolute time */
509 switch(fmt) {
510 case '[h]': case '[hh]': out = val.D*24+val.H; break;
511 case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
512 case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
513 default: throw 'bad abstime format: ' + fmt;
514 } outl = fmt.length === 3 ? 1 : 2; break;
515 case 101: /* 'e' era */
516 out = y; outl = 1; break;
517 }
518 var outstr = outl > 0 ? pad0(out, outl) : "";
519 return outstr;
520}
521/*jshint +W086 */
522function commaify(s) {
523 var w = 3;
524 if(s.length <= w) return s;
525 var j = (s.length % w), o = s.substr(0,j);
526 for(; j!=s.length; j+=w) o+=(o.length > 0 ? "," : "") + s.substr(j,w);
527 return o;
528}
529var write_num = (function make_write_num(){
530var pct1 = /%/g;
531function write_num_pct(type, fmt, val){
532 var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
533 return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
534}
535function write_num_cm(type, fmt, val){
536 var idx = fmt.length - 1;
537 while(fmt.charCodeAt(idx-1) === 44) --idx;
538 return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
539}
540function write_num_exp(fmt, val){
541 var o;
542 var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
543 if(fmt.match(/^#+0.0E\+0$/)) {
544 if(val == 0) return "0.0E+0";
545 else if(val < 0) return "-" + write_num_exp(fmt, -val);
546 var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
547 var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
548 if(ee < 0) ee += period;
549 o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
550 if(o.indexOf("e") === -1) {
551 var fakee = Math.floor(Math.log(val)*Math.LOG10E);
552 if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
553 else o += "E+" + (fakee - ee);
554 while(o.substr(0,2) === "0.") {
555 o = o.charAt(0) + o.substr(2,period) + "." + o.substr(2+period);
556 o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0.");
557 }
558 o = o.replace(/\+-/,"-");
559 }
560 o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
561 } else o = val.toExponential(idx);
562 if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
563 if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
564 return o.replace("e","E");
565}
566var frac1 = /# (\?+)( ?)\/( ?)(\d+)/;
567function write_num_f1(r, aval, sign) {
568 var den = parseInt(r[4],10), rr = Math.round(aval * den), base = Math.floor(rr/den);
569 var myn = (rr - base*den), myd = den;
570 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));
571}
572function write_num_f2(r, aval, sign) {
573 return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
574}
575var dec1 = /^#*0*\.([0#]+)/;
576var closeparen = /\).*[0#]/;
577var phone = /\(###\) ###\\?-####/;
578function hashq(str) {
579 var o = "", cc;
580 for(var i = 0; i != str.length; ++i) switch((cc=str.charCodeAt(i))) {
581 case 35: break;
582 case 63: o+= " "; break;
583 case 48: o+= "0"; break;
584 default: o+= String.fromCharCode(cc);
585 }
586 return o;
587}
588function rnd(val, d) { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
589function dec(val, d) {
590 var _frac = val - Math.floor(val), dd = Math.pow(10,d);
591 if (d < ('' + Math.round(_frac * dd)).length) return 0;
592 return Math.round(_frac * dd);
593}
594function carry(val, d) {
595 if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
596 return 1;
597 }
598 return 0;
599}
600function flr(val) {
601 if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0));
602 return ""+Math.floor(val);
603}
604function write_num_flt(type, fmt, val) {
605 if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
606 var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
607 if(val >= 0) return write_num_flt('n', ffmt, val);
608 return '(' + write_num_flt('n', ffmt, -val) + ')';
609 }
610 if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm(type, fmt, val);
611 if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val);
612 if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val);
613 if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
614 var o;
615 var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
616 if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length);
617 if(fmt.match(/^[#?]+$/)) {
618 o = pad0r(val,0); if(o === "0") o = "";
619 return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
620 }
621 if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign);
622 if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
623 if((r = fmt.match(dec1))) {
624 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); });
625 return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
626 }
627 fmt = fmt.replace(/^#+([0.])/, "$1");
628 if((r = fmt.match(/^(0*)\.(#*)$/))) {
629 return sign + rnd(aval, r[2].length).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
630 }
631 if((r = fmt.match(/^#{1,3},##0(\.?)$/))) return sign + commaify(pad0r(aval,0));
632 if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
633 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);
634 }
635 if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
636 if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
637 o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val));
638 ri = 0;
639 return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";}));
640 }
641 if(fmt.match(phone)) {
642 o = write_num_flt(type, "##########", val);
643 return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
644 }
645 var oa = "";
646 if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
647 ri = Math.min(r[4].length,7);
648 ff = frac(aval, Math.pow(10,ri)-1, false);
649 o = "" + sign;
650 oa = write_num("n", r[1], ff[1]);
651 if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
652 o += oa + r[2] + "/" + r[3];
653 oa = rpad_(ff[2],ri);
654 if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
655 o += oa;
656 return o;
657 }
658 if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
659 ri = Math.min(Math.max(r[1].length, r[4].length),7);
660 ff = frac(aval, Math.pow(10,ri)-1, true);
661 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));
662 }
663 if((r = fmt.match(/^[#0?]+$/))) {
664 o = pad0r(val, 0);
665 if(fmt.length <= o.length) return o;
666 return hashq(fmt.substr(0,fmt.length-o.length)) + o;
667 }
668 if((r = fmt.match(/^([#0?]+)\.([#0]+)$/))) {
669 o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
670 ri = o.indexOf(".");
671 var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
672 return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
673 }
674 if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
675 ri = dec(val, r[1].length);
676 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);
677 }
678 switch(fmt) {
679 case "###,##0.00": return write_num_flt(type, "#,##0.00", val);
680 case "###,###":
681 case "##,###":
682 case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : "";
683 case "###,###.00": return write_num_flt(type, "###,##0.00",val).replace(/^0\./,".");
684 case "#,###.00": return write_num_flt(type, "#,##0.00",val).replace(/^0\./,".");
685 default:
686 }
687 throw new Error("unsupported format |" + fmt + "|");
688}
689function write_num_cm2(type, fmt, val){
690 var idx = fmt.length - 1;
691 while(fmt.charCodeAt(idx-1) === 44) --idx;
692 return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
693}
694function write_num_pct2(type, fmt, val){
695 var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
696 return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
697}
698function write_num_exp2(fmt, val){
699 var o;
700 var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
701 if(fmt.match(/^#+0.0E\+0$/)) {
702 if(val == 0) return "0.0E+0";
703 else if(val < 0) return "-" + write_num_exp2(fmt, -val);
704 var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
705 var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
706 if(ee < 0) ee += period;
707 o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
708 if(!o.match(/[Ee]/)) {
709 var fakee = Math.floor(Math.log(val)*Math.LOG10E);
710 if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
711 else o += "E+" + (fakee - ee);
712 o = o.replace(/\+-/,"-");
713 }
714 o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
715 } else o = val.toExponential(idx);
716 if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
717 if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
718 return o.replace("e","E");
719}
720function write_num_int(type, fmt, val) {
721 if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
722 var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
723 if(val >= 0) return write_num_int('n', ffmt, val);
724 return '(' + write_num_int('n', ffmt, -val) + ')';
725 }
726 if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm2(type, fmt, val);
727 if(fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val);
728 if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val);
729 if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
730 var o;
731 var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
732 if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length);
733 if(fmt.match(/^[#?]+$/)) {
734 o = (""+val); if(val === 0) o = "";
735 return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
736 }
737 if((r = fmt.match(frac1))) return write_num_f2(r, aval, sign);
738 if(fmt.match(/^#+0+$/)) return sign + pad0(aval,fmt.length - fmt.indexOf("0"));
739 if((r = fmt.match(dec1))) {
740o = (""+val).replace(/^([^\.]+)$/,"$1."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1]));
741 o = o.replace(/\.(\d*)$/,function($$, $1) {
742return "." + $1 + fill("0", hashq(r[1]).length-$1.length); });
743 return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
744 }
745 fmt = fmt.replace(/^#+([0.])/, "$1");
746 if((r = fmt.match(/^(0*)\.(#*)$/))) {
747 return sign + (""+aval).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
748 }
749 if((r = fmt.match(/^#{1,3},##0(\.?)$/))) return sign + commaify((""+aval));
750 if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
751 return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify((""+val)) + "." + fill('0',r[1].length);
752 }
753 if((r = fmt.match(/^#,#*,#0/))) return write_num_int(type,fmt.replace(/^#,#*,/,""),val);
754 if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
755 o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val));
756 ri = 0;
757 return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";}));
758 }
759 if(fmt.match(phone)) {
760 o = write_num_int(type, "##########", val);
761 return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
762 }
763 var oa = "";
764 if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
765 ri = Math.min(r[4].length,7);
766 ff = frac(aval, Math.pow(10,ri)-1, false);
767 o = "" + sign;
768 oa = write_num("n", r[1], ff[1]);
769 if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
770 o += oa + r[2] + "/" + r[3];
771 oa = rpad_(ff[2],ri);
772 if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
773 o += oa;
774 return o;
775 }
776 if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
777 ri = Math.min(Math.max(r[1].length, r[4].length),7);
778 ff = frac(aval, Math.pow(10,ri)-1, true);
779 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));
780 }
781 if((r = fmt.match(/^[#0?]+$/))) {
782 o = "" + val;
783 if(fmt.length <= o.length) return o;
784 return hashq(fmt.substr(0,fmt.length-o.length)) + o;
785 }
786 if((r = fmt.match(/^([#0]+)\.([#0]+)$/))) {
787 o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
788 ri = o.indexOf(".");
789 var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
790 return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
791 }
792 if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
793 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);
794 }
795 switch(fmt) {
796 case "###,###":
797 case "##,###":
798 case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
799 default:
800 if(fmt.match(/\.[0#?]*$/)) return write_num_int(type, fmt.slice(0,fmt.lastIndexOf(".")), val) + hashq(fmt.slice(fmt.lastIndexOf(".")));
801 }
802 throw new Error("unsupported format |" + fmt + "|");
803}
804return function write_num(type, fmt, val) {
805 return (val|0) === val ? write_num_int(type, fmt, val) : write_num_flt(type, fmt, val);
806};})();
807function split_fmt(fmt) {
808 var out = [];
809 var in_str = false/*, cc*/;
810 for(var i = 0, j = 0; i < fmt.length; ++i) switch((/*cc=*/fmt.charCodeAt(i))) {
811 case 34: /* '"' */
812 in_str = !in_str; break;
813 case 95: case 42: case 92: /* '_' '*' '\\' */
814 ++i; break;
815 case 59: /* ';' */
816 out[out.length] = fmt.substr(j,i-j);
817 j = i+1;
818 }
819 out[out.length] = fmt.substr(j);
820 if(in_str === true) throw new Error("Format |" + fmt + "| unterminated string ");
821 return out;
822}
823SSF._split = split_fmt;
824var abstime = /\[[HhMmSs\u0E0A\u0E19\u0E17]*\]/;
825function fmt_is_date(fmt) {
826 var i = 0, /*cc = 0,*/ c = "", o = "";
827 while(i < fmt.length) {
828 switch((c = fmt.charAt(i))) {
829 case 'G': if(isgeneral(fmt, i)) i+= 6; i++; break;
830 case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;){/*empty*/} ++i; break;
831 case '\\': i+=2; break;
832 case '_': i+=2; break;
833 case '@': ++i; break;
834 case 'B': case 'b':
835 if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") return true;
836 /* falls through */
837 case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
838 /* falls through */
839 case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g': return true;
840 case 'A': case 'a': case '上':
841 if(fmt.substr(i, 3).toUpperCase() === "A/P") return true;
842 if(fmt.substr(i, 5).toUpperCase() === "AM/PM") return true;
843 if(fmt.substr(i, 5).toUpperCase() === "上午/下午") return true;
844 ++i; break;
845 case '[':
846 o = c;
847 while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
848 if(o.match(abstime)) return true;
849 break;
850 case '.':
851 /* falls through */
852 case '0': case '#':
853 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 */}
854 break;
855 case '?': while(fmt.charAt(++i) === c){/* empty */} break;
856 case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break;
857 case '(': case ')': ++i; break;
858 case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
859 while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){/* empty */} break;
860 case ' ': ++i; break;
861 default: ++i; break;
862 }
863 }
864 return false;
865}
866SSF.is_date = fmt_is_date;
867function eval_fmt(fmt, v, opts, flen) {
868 var out = [], o = "", i = 0, c = "", lst='t', dt, j, cc;
869 var hr='H';
870 /* Tokenize */
871 while(i < fmt.length) {
872 switch((c = fmt.charAt(i))) {
873 case 'G': /* General */
874 if(!isgeneral(fmt, i)) throw new Error('unrecognized character ' + c + ' in ' +fmt);
875 out[out.length] = {t:'G', v:'General'}; i+=7; break;
876 case '"': /* Literal text */
877 for(o="";(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) o += String.fromCharCode(cc);
878 out[out.length] = {t:'t', v:o}; ++i; break;
879 case '\\': var w = fmt.charAt(++i), t = (w === "(" || w === ")") ? w : 't';
880 out[out.length] = {t:t, v:w}; ++i; break;
881 case '_': out[out.length] = {t:'t', v:" "}; i+=2; break;
882 case '@': /* Text Placeholder */
883 out[out.length] = {t:'T', v:v}; ++i; break;
884 case 'B': case 'b':
885 if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") {
886 if(dt==null) { dt=parse_date_code(v, opts, fmt.charAt(i+1) === "2"); if(dt==null) return ""; }
887 out[out.length] = {t:'X', v:fmt.substr(i,2)}; lst = c; i+=2; break;
888 }
889 /* falls through */
890 case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
891 c = c.toLowerCase();
892 /* falls through */
893 case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g':
894 if(v < 0) return "";
895 if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
896 o = c; while(++i < fmt.length && fmt.charAt(i).toLowerCase() === c) o+=c;
897 if(c === 'm' && lst.toLowerCase() === 'h') c = 'M';
898 if(c === 'h') c = hr;
899 out[out.length] = {t:c, v:o}; lst = c; break;
900 case 'A': case 'a': case '上':
901 var q={t:c, v:c};
902 if(dt==null) dt=parse_date_code(v, opts);
903 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;}
904 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'; }
905 else if(fmt.substr(i,5).toUpperCase() === "上午/下午") { if(dt!=null) q.v = dt.H >= 12 ? "下午" : "上午"; q.t = 'T'; i+=5; hr='h'; }
906 else { q.t = "t"; ++i; }
907 if(dt==null && q.t === 'T') return "";
908 out[out.length] = q; lst = c; break;
909 case '[':
910 o = c;
911 while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
912 if(o.slice(-1) !== ']') throw 'unterminated "[" block: |' + o + '|';
913 if(o.match(abstime)) {
914 if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
915 out[out.length] = {t:'Z', v:o.toLowerCase()};
916 lst = o.charAt(1);
917 } else if(o.indexOf("$") > -1) {
918 o = (o.match(/\$([^-\[\]]*)/)||[])[1]||"$";
919 if(!fmt_is_date(fmt)) out[out.length] = {t:'t',v:o};
920 }
921 break;
922 /* Numbers */
923 case '.':
924 if(dt != null) {
925 o = c; while(++i < fmt.length && (c=fmt.charAt(i)) === "0") o += c;
926 out[out.length] = {t:'s', v:o}; break;
927 }
928 /* falls through */
929 case '0': case '#':
930 o = c; while(++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1) o += c;
931 out[out.length] = {t:'n', v:o}; break;
932 case '?':
933 o = c; while(fmt.charAt(++i) === c) o+=c;
934 out[out.length] = {t:c, v:o}; lst = c; break;
935 case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break; // **
936 case '(': case ')': out[out.length] = {t:(flen===1?'t':c), v:c}; ++i; break;
937 case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
938 o = c; while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1) o+=fmt.charAt(i);
939 out[out.length] = {t:'D', v:o}; break;
940 case ' ': out[out.length] = {t:c, v:c}; ++i; break;
941 case '$': out[out.length] = {t:'t', v:'$'}; ++i; break;
942 default:
943 if(",$-+/():!^&'~{}<>=€acfijklopqrtuvwxzP".indexOf(c) === -1) throw new Error('unrecognized character ' + c + ' in ' + fmt);
944 out[out.length] = {t:'t', v:c}; ++i; break;
945 }
946 }
947
948 /* Scan for date/time parts */
949 var bt = 0, ss0 = 0, ssm;
950 for(i=out.length-1, lst='t'; i >= 0; --i) {
951 switch(out[i].t) {
952 case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
953 case 's':
954 if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
955 if(bt < 3) bt = 3;
956 /* falls through */
957 case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
958 case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
959 case 'X': /*if(out[i].v === "B2");*/
960 break;
961 case 'Z':
962 if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1;
963 if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2;
964 if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
965 }
966 }
967 /* time rounding depends on presence of minute / second / usec fields */
968 switch(bt) {
969 case 0: break;
970 case 1:
971if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
972 if(dt.S >= 60) { dt.S = 0; ++dt.M; }
973 if(dt.M >= 60) { dt.M = 0; ++dt.H; }
974 break;
975 case 2:
976if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
977 if(dt.S >= 60) { dt.S = 0; ++dt.M; }
978 break;
979 }
980
981 /* replace fields */
982 var nstr = "", jj;
983 for(i=0; i < out.length; ++i) {
984 switch(out[i].t) {
985 case 't': case 'T': case ' ': case 'D': break;
986 case 'X': out[i].v = ""; out[i].t = ";"; break;
987 case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'b': case 'Z':
988out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
989 out[i].t = 't'; break;
990 case 'n': case '?':
991 jj = i+1;
992 while(out[jj] != null && (
993 (c=out[jj].t) === "?" || c === "D" ||
994 ((c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/')) ||
995 (out[i].t === '(' && (c === ' ' || c === 'n' || c === ')')) ||
996 (c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?'))
997 )) {
998 out[i].v += out[jj].v;
999 out[jj] = {v:"", t:";"}; ++jj;
1000 }
1001 nstr += out[i].v;
1002 i = jj-1; break;
1003 case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
1004 }
1005 }
1006 var vv = "", myv, ostr;
1007 if(nstr.length > 0) {
1008 if(nstr.charCodeAt(0) == 40) /* '(' */ {
1009 myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v);
1010 ostr = write_num('n', nstr, myv);
1011 } else {
1012 myv = (v<0 && flen > 1 ? -v : v);
1013 ostr = write_num('n', nstr, myv);
1014 if(myv < 0 && out[0] && out[0].t == 't') {
1015 ostr = ostr.substr(1);
1016 out[0].v = "-" + out[0].v;
1017 }
1018 }
1019 jj=ostr.length-1;
1020 var decpt = out.length;
1021 for(i=0; i < out.length; ++i) if(out[i] != null && out[i].t != 't' && out[i].v.indexOf(".") > -1) { decpt = i; break; }
1022 var lasti=out.length;
1023 if(decpt === out.length && ostr.indexOf("E") === -1) {
1024 for(i=out.length-1; i>= 0;--i) {
1025 if(out[i] == null || 'n?'.indexOf(out[i].t) === -1) continue;
1026 if(jj>=out[i].v.length-1) { jj -= out[i].v.length; out[i].v = ostr.substr(jj+1, out[i].v.length); }
1027 else if(jj < 0) out[i].v = "";
1028 else { out[i].v = ostr.substr(0, jj+1); jj = -1; }
1029 out[i].t = 't';
1030 lasti = i;
1031 }
1032 if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
1033 }
1034 else if(decpt !== out.length && ostr.indexOf("E") === -1) {
1035 jj = ostr.indexOf(".")-1;
1036 for(i=decpt; i>= 0; --i) {
1037 if(out[i] == null || 'n?'.indexOf(out[i].t) === -1) continue;
1038 j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1;
1039 vv = out[i].v.substr(j+1);
1040 for(; j>=0; --j) {
1041 if(jj>=0 && (out[i].v.charAt(j) === "0" || out[i].v.charAt(j) === "#")) vv = ostr.charAt(jj--) + vv;
1042 }
1043 out[i].v = vv;
1044 out[i].t = 't';
1045 lasti = i;
1046 }
1047 if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
1048 jj = ostr.indexOf(".")+1;
1049 for(i=decpt; i<out.length; ++i) {
1050 if(out[i] == null || ('n?('.indexOf(out[i].t) === -1 && i !== decpt)) continue;
1051 j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0;
1052 vv = out[i].v.substr(0,j);
1053 for(; j<out[i].v.length; ++j) {
1054 if(jj<ostr.length) vv += ostr.charAt(jj++);
1055 }
1056 out[i].v = vv;
1057 out[i].t = 't';
1058 lasti = i;
1059 }
1060 }
1061 }
1062 for(i=0; i<out.length; ++i) if(out[i] != null && 'n?'.indexOf(out[i].t)>-1) {
1063 myv = (flen >1 && v < 0 && i>0 && out[i-1].v === "-" ? -v:v);
1064 out[i].v = write_num(out[i].t, out[i].v, myv);
1065 out[i].t = 't';
1066 }
1067 var retval = "";
1068 for(i=0; i !== out.length; ++i) if(out[i] != null) retval += out[i].v;
1069 return retval;
1070}
1071SSF._eval = eval_fmt;
1072var cfregex = /\[[=<>]/;
1073var cfregex2 = /\[(=|>[=]?|<[>=]?)(-?\d+(?:\.\d*)?)\]/;
1074function chkcond(v, rr) {
1075 if(rr == null) return false;
1076 var thresh = parseFloat(rr[2]);
1077 switch(rr[1]) {
1078 case "=": if(v == thresh) return true; break;
1079 case ">": if(v > thresh) return true; break;
1080 case "<": if(v < thresh) return true; break;
1081 case "<>": if(v != thresh) return true; break;
1082 case ">=": if(v >= thresh) return true; break;
1083 case "<=": if(v <= thresh) return true; break;
1084 }
1085 return false;
1086}
1087function choose_fmt(f, v) {
1088 var fmt = split_fmt(f);
1089 var l = fmt.length, lat = fmt[l-1].indexOf("@");
1090 if(l<4 && lat>-1) --l;
1091 if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
1092 if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
1093 switch(fmt.length) {
1094 case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
1095 case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
1096 case 3: fmt = lat>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
1097 case 4: break;
1098 }
1099 var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2];
1100 if(fmt[0].indexOf("[") === -1 && fmt[1].indexOf("[") === -1) return [l, ff];
1101 if(fmt[0].match(cfregex) != null || fmt[1].match(cfregex) != null) {
1102 var m1 = fmt[0].match(cfregex2);
1103 var m2 = fmt[1].match(cfregex2);
1104 return chkcond(v, m1) ? [l, fmt[0]] : chkcond(v, m2) ? [l, fmt[1]] : [l, fmt[m1 != null && m2 != null ? 2 : 1]];
1105 }
1106 return [l, ff];
1107}
1108function format(fmt,v,o) {
1109 if(o == null) o = {};
1110 var sfmt = "";
1111 switch(typeof fmt) {
1112 case "string":
1113 if(fmt == "m/d/yy" && o.dateNF) sfmt = o.dateNF;
1114 else sfmt = fmt;
1115 break;
1116 case "number":
1117 if(fmt == 14 && o.dateNF) sfmt = o.dateNF;
1118 else sfmt = (o.table != null ? (o.table) : table_fmt)[fmt];
1119 if(sfmt == null) sfmt = (o.table && o.table[default_map[fmt]]) || table_fmt[default_map[fmt]];
1120 if(sfmt == null) sfmt = default_str[fmt] || "General";
1121 break;
1122 }
1123 if(isgeneral(sfmt,0)) return general_fmt(v, o);
1124 if(v instanceof Date) v = datenum_local(v, o.date1904);
1125 var f = choose_fmt(sfmt, v);
1126 if(isgeneral(f[1])) return general_fmt(v, o);
1127 if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
1128 else if(v === "" || v == null) return "";
1129 return eval_fmt(f[1], v, o, f[0]);
1130}
1131function load_entry(fmt, idx) {
1132 if(typeof idx != 'number') {
1133 idx = +idx || -1;
1134for(var i = 0; i < 0x0188; ++i) {
1135if(table_fmt[i] == undefined) { if(idx < 0) idx = i; continue; }
1136 if(table_fmt[i] == fmt) { idx = i; break; }
1137 }
1138if(idx < 0) idx = 0x187;
1139 }
1140table_fmt[idx] = fmt;
1141 return idx;
1142}
1143SSF.load = load_entry;
1144SSF._table = table_fmt;
1145SSF.get_table = function get_table() { return table_fmt; };
1146SSF.load_table = function load_table(tbl) {
1147 for(var i=0; i!=0x0188; ++i)
1148 if(tbl[i] !== undefined) load_entry(tbl[i], i);
1149};
1150SSF.init_table = init_table;
1151SSF.format = format;
1152};
1153make_ssf(SSF);
1154/* map from xlml named formats to SSF TODO: localize */
1155var XLMLFormatMap/*{[string]:string}*/ = ({
1156 "General Number": "General",
1157 "General Date": SSF._table[22],
1158 "Long Date": "dddd, mmmm dd, yyyy",
1159 "Medium Date": SSF._table[15],
1160 "Short Date": SSF._table[14],
1161 "Long Time": SSF._table[19],
1162 "Medium Time": SSF._table[18],
1163 "Short Time": SSF._table[20],
1164 "Currency": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
1165 "Fixed": SSF._table[2],
1166 "Standard": SSF._table[4],
1167 "Percent": SSF._table[10],
1168 "Scientific": SSF._table[11],
1169 "Yes/No": '"Yes";"Yes";"No";@',
1170 "True/False": '"True";"True";"False";@',
1171 "On/Off": '"Yes";"Yes";"No";@'
1172});
1173
1174var SSFImplicit/*{[number]:string}*/ = ({
1175 "5": '"$"#,##0_);\\("$"#,##0\\)',
1176 "6": '"$"#,##0_);[Red]\\("$"#,##0\\)',
1177 "7": '"$"#,##0.00_);\\("$"#,##0.00\\)',
1178 "8": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
1179 "23": 'General', "24": 'General', "25": 'General', "26": 'General',
1180 "27": 'm/d/yy', "28": 'm/d/yy', "29": 'm/d/yy', "30": 'm/d/yy', "31": 'm/d/yy',
1181 "32": 'h:mm:ss', "33": 'h:mm:ss', "34": 'h:mm:ss', "35": 'h:mm:ss',
1182 "36": 'm/d/yy',
1183 "41": '_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)',
1184 "42": '_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)',
1185 "43": '_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)',
1186 "44": '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)',
1187 "50": 'm/d/yy', "51": 'm/d/yy', "52": 'm/d/yy', "53": 'm/d/yy', "54": 'm/d/yy',
1188 "55": 'm/d/yy', "56": 'm/d/yy', "57": 'm/d/yy', "58": 'm/d/yy',
1189 "59": '0',
1190 "60": '0.00',
1191 "61": '#,##0',
1192 "62": '#,##0.00',
1193 "63": '"$"#,##0_);\\("$"#,##0\\)',
1194 "64": '"$"#,##0_);[Red]\\("$"#,##0\\)',
1195 "65": '"$"#,##0.00_);\\("$"#,##0.00\\)',
1196 "66": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
1197 "67": '0%',
1198 "68": '0.00%',
1199 "69": '# ?/?',
1200 "70": '# ??/??',
1201 "71": 'm/d/yy',
1202 "72": 'm/d/yy',
1203 "73": 'd-mmm-yy',
1204 "74": 'd-mmm',
1205 "75": 'mmm-yy',
1206 "76": 'h:mm',
1207 "77": 'h:mm:ss',
1208 "78": 'm/d/yy h:mm',
1209 "79": 'mm:ss',
1210 "80": '[h]:mm:ss',
1211 "81": 'mmss.0'
1212});
1213
1214/* dateNF parse TODO: move to SSF */
1215var dateNFregex = /[dD]+|[mM]+|[yYeE]+|[Hh]+|[Ss]+/g;
1216function dateNF_regex(dateNF) {
1217 var fmt = typeof dateNF == "number" ? SSF._table[dateNF] : dateNF;
1218 fmt = fmt.replace(dateNFregex, "(\\d+)");
1219 return new RegExp("^" + fmt + "$");
1220}
1221function dateNF_fix(str, dateNF, match) {
1222 var Y = -1, m = -1, d = -1, H = -1, M = -1, S = -1;
1223 (dateNF.match(dateNFregex)||[]).forEach(function(n, i) {
1224 var v = parseInt(match[i+1], 10);
1225 switch(n.toLowerCase().charAt(0)) {
1226 case 'y': Y = v; break; case 'd': d = v; break;
1227 case 'h': H = v; break; case 's': S = v; break;
1228 case 'm': if(H >= 0) M = v; else m = v; break;
1229 }
1230 });
1231 if(S >= 0 && M == -1 && m >= 0) { M = m; m = -1; }
1232 var datestr = (("" + (Y>=0?Y: new Date().getFullYear())).slice(-4) + "-" + ("00" + (m>=1?m:1)).slice(-2) + "-" + ("00" + (d>=1?d:1)).slice(-2));
1233 if(datestr.length == 7) datestr = "0" + datestr;
1234 if(datestr.length == 8) datestr = "20" + datestr;
1235 var timestr = (("00" + (H>=0?H:0)).slice(-2) + ":" + ("00" + (M>=0?M:0)).slice(-2) + ":" + ("00" + (S>=0?S:0)).slice(-2));
1236 if(H == -1 && M == -1 && S == -1) return datestr;
1237 if(Y == -1 && m == -1 && d == -1) return timestr;
1238 return datestr + "T" + timestr;
1239}
1240
1241var DO_NOT_EXPORT_CFB = true;
1242/* cfb.js (C) 2013-present SheetJS -- http://sheetjs.com */
1243/* vim: set ts=2: */
1244/*jshint eqnull:true */
1245/*exported CFB */
1246/*global Uint8Array:false, Uint16Array:false */
1247
1248/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
1249/* vim: set ts=2: */
1250/*exported CRC32 */
1251var CRC32;
1252(function (factory) {
1253 /*jshint ignore:start */
1254 /*eslint-disable */
1255 factory(CRC32 = {});
1256 /*eslint-enable */
1257 /*jshint ignore:end */
1258}(function(CRC32) {
1259CRC32.version = '1.2.0';
1260/* see perf/crc32table.js */
1261/*global Int32Array */
1262function signed_crc_table() {
1263 var c = 0, table = new Array(256);
1264
1265 for(var n =0; n != 256; ++n){
1266 c = n;
1267 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1268 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1269 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1270 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1271 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1272 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1273 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1274 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1275 table[n] = c;
1276 }
1277
1278 return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table;
1279}
1280
1281var T = signed_crc_table();
1282function crc32_bstr(bstr, seed) {
1283 var C = seed ^ -1, L = bstr.length - 1;
1284 for(var i = 0; i < L;) {
1285 C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
1286 C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
1287 }
1288 if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF];
1289 return C ^ -1;
1290}
1291
1292function crc32_buf(buf, seed) {
1293 if(buf.length > 10000) return crc32_buf_8(buf, seed);
1294 var C = seed ^ -1, L = buf.length - 3;
1295 for(var i = 0; i < L;) {
1296 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1297 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1298 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1299 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1300 }
1301 while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1302 return C ^ -1;
1303}
1304
1305function crc32_buf_8(buf, seed) {
1306 var C = seed ^ -1, L = buf.length - 7;
1307 for(var i = 0; i < L;) {
1308 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1309 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1310 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1311 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1312 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1313 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1314 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1315 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1316 }
1317 while(i < L+7) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1318 return C ^ -1;
1319}
1320
1321function crc32_str(str, seed) {
1322 var C = seed ^ -1;
1323 for(var i = 0, L=str.length, c, d; i < L;) {
1324 c = str.charCodeAt(i++);
1325 if(c < 0x80) {
1326 C = (C>>>8) ^ T[(C ^ c)&0xFF];
1327 } else if(c < 0x800) {
1328 C = (C>>>8) ^ T[(C ^ (192|((c>>6)&31)))&0xFF];
1329 C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF];
1330 } else if(c >= 0xD800 && c < 0xE000) {
1331 c = (c&1023)+64; d = str.charCodeAt(i++)&1023;
1332 C = (C>>>8) ^ T[(C ^ (240|((c>>8)&7)))&0xFF];
1333 C = (C>>>8) ^ T[(C ^ (128|((c>>2)&63)))&0xFF];
1334 C = (C>>>8) ^ T[(C ^ (128|((d>>6)&15)|((c&3)<<4)))&0xFF];
1335 C = (C>>>8) ^ T[(C ^ (128|(d&63)))&0xFF];
1336 } else {
1337 C = (C>>>8) ^ T[(C ^ (224|((c>>12)&15)))&0xFF];
1338 C = (C>>>8) ^ T[(C ^ (128|((c>>6)&63)))&0xFF];
1339 C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF];
1340 }
1341 }
1342 return C ^ -1;
1343}
1344CRC32.table = T;
1345CRC32.bstr = crc32_bstr;
1346CRC32.buf = crc32_buf;
1347CRC32.str = crc32_str;
1348}));
1349/* [MS-CFB] v20171201 */
1350var CFB = (function _CFB(){
1351var exports = {};
1352exports.version = '1.1.4';
1353/* [MS-CFB] 2.6.4 */
1354function namecmp(l, r) {
1355 var L = l.split("/"), R = r.split("/");
1356 for(var i = 0, c = 0, Z = Math.min(L.length, R.length); i < Z; ++i) {
1357 if((c = L[i].length - R[i].length)) return c;
1358 if(L[i] != R[i]) return L[i] < R[i] ? -1 : 1;
1359 }
1360 return L.length - R.length;
1361}
1362function dirname(p) {
1363 if(p.charAt(p.length - 1) == "/") return (p.slice(0,-1).indexOf("/") === -1) ? p : dirname(p.slice(0, -1));
1364 var c = p.lastIndexOf("/");
1365 return (c === -1) ? p : p.slice(0, c+1);
1366}
1367
1368function filename(p) {
1369 if(p.charAt(p.length - 1) == "/") return filename(p.slice(0, -1));
1370 var c = p.lastIndexOf("/");
1371 return (c === -1) ? p : p.slice(c+1);
1372}
1373/* -------------------------------------------------------------------------- */
1374/* DOS Date format:
1375 high|YYYYYYYm.mmmddddd.HHHHHMMM.MMMSSSSS|low
1376 add 1980 to stored year
1377 stored second should be doubled
1378*/
1379
1380/* write JS date to buf as a DOS date */
1381function write_dos_date(buf, date) {
1382 if(typeof date === "string") date = new Date(date);
1383 var hms = date.getHours();
1384 hms = hms << 6 | date.getMinutes();
1385 hms = hms << 5 | (date.getSeconds()>>>1);
1386 buf.write_shift(2, hms);
1387 var ymd = (date.getFullYear() - 1980);
1388 ymd = ymd << 4 | (date.getMonth()+1);
1389 ymd = ymd << 5 | date.getDate();
1390 buf.write_shift(2, ymd);
1391}
1392
1393/* read four bytes from buf and interpret as a DOS date */
1394function parse_dos_date(buf) {
1395 var hms = buf.read_shift(2) & 0xFFFF;
1396 var ymd = buf.read_shift(2) & 0xFFFF;
1397 var val = new Date();
1398 var d = ymd & 0x1F; ymd >>>= 5;
1399 var m = ymd & 0x0F; ymd >>>= 4;
1400 val.setMilliseconds(0);
1401 val.setFullYear(ymd + 1980);
1402 val.setMonth(m-1);
1403 val.setDate(d);
1404 var S = hms & 0x1F; hms >>>= 5;
1405 var M = hms & 0x3F; hms >>>= 6;
1406 val.setHours(hms);
1407 val.setMinutes(M);
1408 val.setSeconds(S<<1);
1409 return val;
1410}
1411function parse_extra_field(blob) {
1412 prep_blob(blob, 0);
1413 var o = {};
1414 var flags = 0;
1415 while(blob.l <= blob.length - 4) {
1416 var type = blob.read_shift(2);
1417 var sz = blob.read_shift(2), tgt = blob.l + sz;
1418 var p = {};
1419 switch(type) {
1420 /* UNIX-style Timestamps */
1421 case 0x5455: {
1422 flags = blob.read_shift(1);
1423 if(flags & 1) p.mtime = blob.read_shift(4);
1424 /* for some reason, CD flag corresponds to LFH */
1425 if(sz > 5) {
1426 if(flags & 2) p.atime = blob.read_shift(4);
1427 if(flags & 4) p.ctime = blob.read_shift(4);
1428 }
1429 if(p.mtime) p.mt = new Date(p.mtime*1000);
1430 }
1431 break;
1432 }
1433 blob.l = tgt;
1434 o[type] = p;
1435 }
1436 return o;
1437}
1438var fs;
1439function get_fs() { return fs || (fs = require('fs')); }
1440function parse(file, options) {
1441if(file[0] == 0x50 && file[1] == 0x4b) return parse_zip(file, options);
1442if(file.length < 512) throw new Error("CFB file size " + file.length + " < 512");
1443var mver = 3;
1444var ssz = 512;
1445var nmfs = 0; // number of mini FAT sectors
1446var difat_sec_cnt = 0;
1447var dir_start = 0;
1448var minifat_start = 0;
1449var difat_start = 0;
1450
1451var fat_addrs = []; // locations of FAT sectors
1452
1453/* [MS-CFB] 2.2 Compound File Header */
1454var blob = file.slice(0,512);
1455prep_blob(blob, 0);
1456
1457/* major version */
1458var mv = check_get_mver(blob);
1459mver = mv[0];
1460switch(mver) {
1461 case 3: ssz = 512; break; case 4: ssz = 4096; break;
1462 case 0: if(mv[1] == 0) return parse_zip(file, options);
1463 /* falls through */
1464 default: throw new Error("Major Version: Expected 3 or 4 saw " + mver);
1465}
1466
1467/* reprocess header */
1468if(ssz !== 512) { blob = file.slice(0,ssz); prep_blob(blob, 28 /* blob.l */); }
1469/* Save header for final object */
1470var header = file.slice(0,ssz);
1471
1472check_shifts(blob, mver);
1473
1474// Number of Directory Sectors
1475var dir_cnt = blob.read_shift(4, 'i');
1476if(mver === 3 && dir_cnt !== 0) throw new Error('# Directory Sectors: Expected 0 saw ' + dir_cnt);
1477
1478// Number of FAT Sectors
1479blob.l += 4;
1480
1481// First Directory Sector Location
1482dir_start = blob.read_shift(4, 'i');
1483
1484// Transaction Signature
1485blob.l += 4;
1486
1487// Mini Stream Cutoff Size
1488blob.chk('00100000', 'Mini Stream Cutoff Size: ');
1489
1490// First Mini FAT Sector Location
1491minifat_start = blob.read_shift(4, 'i');
1492
1493// Number of Mini FAT Sectors
1494nmfs = blob.read_shift(4, 'i');
1495
1496// First DIFAT sector location
1497difat_start = blob.read_shift(4, 'i');
1498
1499// Number of DIFAT Sectors
1500difat_sec_cnt = blob.read_shift(4, 'i');
1501
1502// Grab FAT Sector Locations
1503for(var q = -1, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */
1504 q = blob.read_shift(4, 'i');
1505 if(q<0) break;
1506 fat_addrs[j] = q;
1507}
1508
1509/** Break the file up into sectors */
1510var sectors = sectorify(file, ssz);
1511
1512sleuth_fat(difat_start, difat_sec_cnt, sectors, ssz, fat_addrs);
1513
1514/** Chains */
1515var sector_list = make_sector_list(sectors, dir_start, fat_addrs, ssz);
1516
1517sector_list[dir_start].name = "!Directory";
1518if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
1519sector_list[fat_addrs[0]].name = "!FAT";
1520sector_list.fat_addrs = fat_addrs;
1521sector_list.ssz = ssz;
1522
1523/* [MS-CFB] 2.6.1 Compound File Directory Entry */
1524var files = {}, Paths = [], FileIndex = [], FullPaths = [];
1525read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex, minifat_start);
1526
1527build_full_paths(FileIndex, FullPaths, Paths);
1528Paths.shift();
1529
1530var o = {
1531 FileIndex: FileIndex,
1532 FullPaths: FullPaths
1533};
1534
1535// $FlowIgnore
1536if(options && options.raw) o.raw = {header: header, sectors: sectors};
1537return o;
1538} // parse
1539
1540/* [MS-CFB] 2.2 Compound File Header -- read up to major version */
1541function check_get_mver(blob) {
1542 if(blob[blob.l] == 0x50 && blob[blob.l + 1] == 0x4b) return [0, 0];
1543 // header signature 8
1544 blob.chk(HEADER_SIGNATURE, 'Header Signature: ');
1545
1546 // clsid 16
1547 //blob.chk(HEADER_CLSID, 'CLSID: ');
1548 blob.l += 16;
1549
1550 // minor version 2
1551 var mver = blob.read_shift(2, 'u');
1552
1553 return [blob.read_shift(2,'u'), mver];
1554}
1555function check_shifts(blob, mver) {
1556 var shift = 0x09;
1557
1558 // Byte Order
1559 //blob.chk('feff', 'Byte Order: '); // note: some writers put 0xffff
1560 blob.l += 2;
1561
1562 // Sector Shift
1563 switch((shift = blob.read_shift(2))) {
1564 case 0x09: if(mver != 3) throw new Error('Sector Shift: Expected 9 saw ' + shift); break;
1565 case 0x0c: if(mver != 4) throw new Error('Sector Shift: Expected 12 saw ' + shift); break;
1566 default: throw new Error('Sector Shift: Expected 9 or 12 saw ' + shift);
1567 }
1568
1569 // Mini Sector Shift
1570 blob.chk('0600', 'Mini Sector Shift: ');
1571
1572 // Reserved
1573 blob.chk('000000000000', 'Reserved: ');
1574}
1575
1576/** Break the file up into sectors */
1577function sectorify(file, ssz) {
1578 var nsectors = Math.ceil(file.length/ssz)-1;
1579 var sectors = [];
1580 for(var i=1; i < nsectors; ++i) sectors[i-1] = file.slice(i*ssz,(i+1)*ssz);
1581 sectors[nsectors-1] = file.slice(nsectors*ssz);
1582 return sectors;
1583}
1584
1585/* [MS-CFB] 2.6.4 Red-Black Tree */
1586function build_full_paths(FI, FP, Paths) {
1587 var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length;
1588 var dad = [], q = [];
1589
1590 for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; }
1591
1592 for(; j < q.length; ++j) {
1593 i = q[j];
1594 L = FI[i].L; R = FI[i].R; C = FI[i].C;
1595 if(dad[i] === i) {
1596 if(L !== -1 /*NOSTREAM*/ && dad[L] !== L) dad[i] = dad[L];
1597 if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
1598 }
1599 if(C !== -1 /*NOSTREAM*/) dad[C] = i;
1600 if(L !== -1 && i != dad[i]) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
1601 if(R !== -1 && i != dad[i]) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
1602 }
1603 for(i=1; i < pl; ++i) if(dad[i] === i) {
1604 if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
1605 else if(L !== -1 && dad[L] !== L) dad[i] = dad[L];
1606 }
1607
1608 for(i=1; i < pl; ++i) {
1609 if(FI[i].type === 0 /* unknown */) continue;
1610 j = i;
1611 if(j != dad[j]) do {
1612 j = dad[j];
1613 FP[i] = FP[j] + "/" + FP[i];
1614 } while (j !== 0 && -1 !== dad[j] && j != dad[j]);
1615 dad[i] = -1;
1616 }
1617
1618 FP[0] += "/";
1619 for(i=1; i < pl; ++i) {
1620 if(FI[i].type !== 2 /* stream */) FP[i] += "/";
1621 }
1622}
1623
1624function get_mfat_entry(entry, payload, mini) {
1625 var start = entry.start, size = entry.size;
1626 //return (payload.slice(start*MSSZ, start*MSSZ + size));
1627 var o = [];
1628 var idx = start;
1629 while(mini && size > 0 && idx >= 0) {
1630 o.push(payload.slice(idx * MSSZ, idx * MSSZ + MSSZ));
1631 size -= MSSZ;
1632 idx = __readInt32LE(mini, idx * 4);
1633 }
1634 if(o.length === 0) return (new_buf(0));
1635 return (bconcat(o).slice(0, entry.size));
1636}
1637
1638/** Chase down the rest of the DIFAT chain to build a comprehensive list
1639 DIFAT chains by storing the next sector number as the last 32 bits */
1640function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) {
1641 var q = ENDOFCHAIN;
1642 if(idx === ENDOFCHAIN) {
1643 if(cnt !== 0) throw new Error("DIFAT chain shorter than expected");
1644 } else if(idx !== -1 /*FREESECT*/) {
1645 var sector = sectors[idx], m = (ssz>>>2)-1;
1646 if(!sector) return;
1647 for(var i = 0; i < m; ++i) {
1648 if((q = __readInt32LE(sector,i*4)) === ENDOFCHAIN) break;
1649 fat_addrs.push(q);
1650 }
1651 if(cnt >= 1) sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs);
1652 }
1653}
1654
1655/** Follow the linked list of sectors for a given starting point */
1656function get_sector_list(sectors, start, fat_addrs, ssz, chkd) {
1657 var buf = [], buf_chain = [];
1658 if(!chkd) chkd = [];
1659 var modulus = ssz - 1, j = 0, jj = 0;
1660 for(j=start; j>=0;) {
1661 chkd[j] = true;
1662 buf[buf.length] = j;
1663 buf_chain.push(sectors[j]);
1664 var addr = fat_addrs[Math.floor(j*4/ssz)];
1665 jj = ((j*4) & modulus);
1666 if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz);
1667 if(!sectors[addr]) break;
1668 j = __readInt32LE(sectors[addr], jj);
1669 }
1670 return {nodes: buf, data:__toBuffer([buf_chain])};
1671}
1672
1673/** Chase down the sector linked lists */
1674function make_sector_list(sectors, dir_start, fat_addrs, ssz) {
1675 var sl = sectors.length, sector_list = ([]);
1676 var chkd = [], buf = [], buf_chain = [];
1677 var modulus = ssz - 1, i=0, j=0, k=0, jj=0;
1678 for(i=0; i < sl; ++i) {
1679 buf = ([]);
1680 k = (i + dir_start); if(k >= sl) k-=sl;
1681 if(chkd[k]) continue;
1682 buf_chain = [];
1683 var seen = [];
1684 for(j=k; j>=0;) {
1685 seen[j] = true;
1686 chkd[j] = true;
1687 buf[buf.length] = j;
1688 buf_chain.push(sectors[j]);
1689 var addr = fat_addrs[Math.floor(j*4/ssz)];
1690 jj = ((j*4) & modulus);
1691 if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz);
1692 if(!sectors[addr]) break;
1693 j = __readInt32LE(sectors[addr], jj);
1694 if(seen[j]) break;
1695 }
1696 sector_list[k] = ({nodes: buf, data:__toBuffer([buf_chain])});
1697 }
1698 return sector_list;
1699}
1700
1701/* [MS-CFB] 2.6.1 Compound File Directory Entry */
1702function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex, mini) {
1703 var minifat_store = 0, pl = (Paths.length?2:0);
1704 var sector = sector_list[dir_start].data;
1705 var i = 0, namelen = 0, name;
1706 for(; i < sector.length; i+= 128) {
1707 var blob = sector.slice(i, i+128);
1708 prep_blob(blob, 64);
1709 namelen = blob.read_shift(2);
1710 name = __utf16le(blob,0,namelen-pl);
1711 Paths.push(name);
1712 var o = ({
1713 name: name,
1714 type: blob.read_shift(1),
1715 color: blob.read_shift(1),
1716 L: blob.read_shift(4, 'i'),
1717 R: blob.read_shift(4, 'i'),
1718 C: blob.read_shift(4, 'i'),
1719 clsid: blob.read_shift(16),
1720 state: blob.read_shift(4, 'i'),
1721 start: 0,
1722 size: 0
1723 });
1724 var ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2);
1725 if(ctime !== 0) o.ct = read_date(blob, blob.l-8);
1726 var mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2);
1727 if(mtime !== 0) o.mt = read_date(blob, blob.l-8);
1728 o.start = blob.read_shift(4, 'i');
1729 o.size = blob.read_shift(4, 'i');
1730 if(o.size < 0 && o.start < 0) { o.size = o.type = 0; o.start = ENDOFCHAIN; o.name = ""; }
1731 if(o.type === 5) { /* root */
1732 minifat_store = o.start;
1733 if(nmfs > 0 && minifat_store !== ENDOFCHAIN) sector_list[minifat_store].name = "!StreamData";
1734 /*minifat_size = o.size;*/
1735 } else if(o.size >= 4096 /* MSCSZ */) {
1736 o.storage = 'fat';
1737 if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz);
1738 sector_list[o.start].name = o.name;
1739 o.content = (sector_list[o.start].data.slice(0,o.size));
1740 } else {
1741 o.storage = 'minifat';
1742 if(o.size < 0) o.size = 0;
1743 else if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) {
1744 o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini]||{}).data);
1745 }
1746 }
1747 if(o.content) prep_blob(o.content, 0);
1748 files[name] = o;
1749 FileIndex.push(o);
1750 }
1751}
1752
1753function read_date(blob, offset) {
1754 return new Date(( ( (__readUInt32LE(blob,offset+4)/1e7)*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7 ) - 11644473600)*1000);
1755}
1756
1757function read_file(filename, options) {
1758 get_fs();
1759 return parse(fs.readFileSync(filename), options);
1760}
1761
1762function read(blob, options) {
1763 switch(options && options.type || "base64") {
1764 case "file": return read_file(blob, options);
1765 case "base64": return parse(s2a(Base64.decode(blob)), options);
1766 case "binary": return parse(s2a(blob), options);
1767 }
1768 return parse(blob, options);
1769}
1770
1771function init_cfb(cfb, opts) {
1772 var o = opts || {}, root = o.root || "Root Entry";
1773 if(!cfb.FullPaths) cfb.FullPaths = [];
1774 if(!cfb.FileIndex) cfb.FileIndex = [];
1775 if(cfb.FullPaths.length !== cfb.FileIndex.length) throw new Error("inconsistent CFB structure");
1776 if(cfb.FullPaths.length === 0) {
1777 cfb.FullPaths[0] = root + "/";
1778 cfb.FileIndex[0] = ({ name: root, type: 5 });
1779 }
1780 if(o.CLSID) cfb.FileIndex[0].clsid = o.CLSID;
1781 seed_cfb(cfb);
1782}
1783function seed_cfb(cfb) {
1784 var nm = "\u0001Sh33tJ5";
1785 if(CFB.find(cfb, "/" + nm)) return;
1786 var p = new_buf(4); p[0] = 55; p[1] = p[3] = 50; p[2] = 54;
1787 cfb.FileIndex.push(({ name: nm, type: 2, content:p, size:4, L:69, R:69, C:69 }));
1788 cfb.FullPaths.push(cfb.FullPaths[0] + nm);
1789 rebuild_cfb(cfb);
1790}
1791function rebuild_cfb(cfb, f) {
1792 init_cfb(cfb);
1793 var gc = false, s = false;
1794 for(var i = cfb.FullPaths.length - 1; i >= 0; --i) {
1795 var _file = cfb.FileIndex[i];
1796 switch(_file.type) {
1797 case 0:
1798 if(s) gc = true;
1799 else { cfb.FileIndex.pop(); cfb.FullPaths.pop(); }
1800 break;
1801 case 1: case 2: case 5:
1802 s = true;
1803 if(isNaN(_file.R * _file.L * _file.C)) gc = true;
1804 if(_file.R > -1 && _file.L > -1 && _file.R == _file.L) gc = true;
1805 break;
1806 default: gc = true; break;
1807 }
1808 }
1809 if(!gc && !f) return;
1810
1811 var now = new Date(1987, 1, 19), j = 0;
1812 var data = [];
1813 for(i = 0; i < cfb.FullPaths.length; ++i) {
1814 if(cfb.FileIndex[i].type === 0) continue;
1815 data.push([cfb.FullPaths[i], cfb.FileIndex[i]]);
1816 }
1817 for(i = 0; i < data.length; ++i) {
1818 var dad = dirname(data[i][0]);
1819 s = false;
1820 for(j = 0; j < data.length; ++j) if(data[j][0] === dad) s = true;
1821 if(!s) data.push([dad, ({
1822 name: filename(dad).replace("/",""),
1823 type: 1,
1824 clsid: HEADER_CLSID,
1825 ct: now, mt: now,
1826 content: null
1827 })]);
1828 }
1829
1830 data.sort(function(x,y) { return namecmp(x[0], y[0]); });
1831 cfb.FullPaths = []; cfb.FileIndex = [];
1832 for(i = 0; i < data.length; ++i) { cfb.FullPaths[i] = data[i][0]; cfb.FileIndex[i] = data[i][1]; }
1833 for(i = 0; i < data.length; ++i) {
1834 var elt = cfb.FileIndex[i];
1835 var nm = cfb.FullPaths[i];
1836
1837 elt.name = filename(nm).replace("/","");
1838 elt.L = elt.R = elt.C = -(elt.color = 1);
1839 elt.size = elt.content ? elt.content.length : 0;
1840 elt.start = 0;
1841 elt.clsid = (elt.clsid || HEADER_CLSID);
1842 if(i === 0) {
1843 elt.C = data.length > 1 ? 1 : -1;
1844 elt.size = 0;
1845 elt.type = 5;
1846 } else if(nm.slice(-1) == "/") {
1847 for(j=i+1;j < data.length; ++j) if(dirname(cfb.FullPaths[j])==nm) break;
1848 elt.C = j >= data.length ? -1 : j;
1849 for(j=i+1;j < data.length; ++j) if(dirname(cfb.FullPaths[j])==dirname(nm)) break;
1850 elt.R = j >= data.length ? -1 : j;
1851 elt.type = 1;
1852 } else {
1853 if(dirname(cfb.FullPaths[i+1]||"") == dirname(nm)) elt.R = i + 1;
1854 elt.type = 2;
1855 }
1856 }
1857
1858}
1859
1860function _write(cfb, options) {
1861 var _opts = options || {};
1862 rebuild_cfb(cfb);
1863 if(_opts.fileType == 'zip') return write_zip(cfb, _opts);
1864 var L = (function(cfb){
1865 var mini_size = 0, fat_size = 0;
1866 for(var i = 0; i < cfb.FileIndex.length; ++i) {
1867 var file = cfb.FileIndex[i];
1868 if(!file.content) continue;
1869var flen = file.content.length;
1870 if(flen > 0){
1871 if(flen < 0x1000) mini_size += (flen + 0x3F) >> 6;
1872 else fat_size += (flen + 0x01FF) >> 9;
1873 }
1874 }
1875 var dir_cnt = (cfb.FullPaths.length +3) >> 2;
1876 var mini_cnt = (mini_size + 7) >> 3;
1877 var mfat_cnt = (mini_size + 0x7F) >> 7;
1878 var fat_base = mini_cnt + fat_size + dir_cnt + mfat_cnt;
1879 var fat_cnt = (fat_base + 0x7F) >> 7;
1880 var difat_cnt = fat_cnt <= 109 ? 0 : Math.ceil((fat_cnt-109)/0x7F);
1881 while(((fat_base + fat_cnt + difat_cnt + 0x7F) >> 7) > fat_cnt) difat_cnt = ++fat_cnt <= 109 ? 0 : Math.ceil((fat_cnt-109)/0x7F);
1882 var L = [1, difat_cnt, fat_cnt, mfat_cnt, dir_cnt, fat_size, mini_size, 0];
1883 cfb.FileIndex[0].size = mini_size << 6;
1884 L[7] = (cfb.FileIndex[0].start=L[0]+L[1]+L[2]+L[3]+L[4]+L[5])+((L[6]+7) >> 3);
1885 return L;
1886 })(cfb);
1887 var o = new_buf(L[7] << 9);
1888 var i = 0, T = 0;
1889 {
1890 for(i = 0; i < 8; ++i) o.write_shift(1, HEADER_SIG[i]);
1891 for(i = 0; i < 8; ++i) o.write_shift(2, 0);
1892 o.write_shift(2, 0x003E);
1893 o.write_shift(2, 0x0003);
1894 o.write_shift(2, 0xFFFE);
1895 o.write_shift(2, 0x0009);
1896 o.write_shift(2, 0x0006);
1897 for(i = 0; i < 3; ++i) o.write_shift(2, 0);
1898 o.write_shift(4, 0);
1899 o.write_shift(4, L[2]);
1900 o.write_shift(4, L[0] + L[1] + L[2] + L[3] - 1);
1901 o.write_shift(4, 0);
1902 o.write_shift(4, 1<<12);
1903 o.write_shift(4, L[3] ? L[0] + L[1] + L[2] - 1: ENDOFCHAIN);
1904 o.write_shift(4, L[3]);
1905 o.write_shift(-4, L[1] ? L[0] - 1: ENDOFCHAIN);
1906 o.write_shift(4, L[1]);
1907 for(i = 0; i < 109; ++i) o.write_shift(-4, i < L[2] ? L[1] + i : -1);
1908 }
1909 if(L[1]) {
1910 for(T = 0; T < L[1]; ++T) {
1911 for(; i < 236 + T * 127; ++i) o.write_shift(-4, i < L[2] ? L[1] + i : -1);
1912 o.write_shift(-4, T === L[1] - 1 ? ENDOFCHAIN : T + 1);
1913 }
1914 }
1915 var chainit = function(w) {
1916 for(T += w; i<T-1; ++i) o.write_shift(-4, i+1);
1917 if(w) { ++i; o.write_shift(-4, ENDOFCHAIN); }
1918 };
1919 T = i = 0;
1920 for(T+=L[1]; i<T; ++i) o.write_shift(-4, consts.DIFSECT);
1921 for(T+=L[2]; i<T; ++i) o.write_shift(-4, consts.FATSECT);
1922 chainit(L[3]);
1923 chainit(L[4]);
1924 var j = 0, flen = 0;
1925 var file = cfb.FileIndex[0];
1926 for(; j < cfb.FileIndex.length; ++j) {
1927 file = cfb.FileIndex[j];
1928 if(!file.content) continue;
1929flen = file.content.length;
1930 if(flen < 0x1000) continue;
1931 file.start = T;
1932 chainit((flen + 0x01FF) >> 9);
1933 }
1934 chainit((L[6] + 7) >> 3);
1935 while(o.l & 0x1FF) o.write_shift(-4, consts.ENDOFCHAIN);
1936 T = i = 0;
1937 for(j = 0; j < cfb.FileIndex.length; ++j) {
1938 file = cfb.FileIndex[j];
1939 if(!file.content) continue;
1940flen = file.content.length;
1941 if(!flen || flen >= 0x1000) continue;
1942 file.start = T;
1943 chainit((flen + 0x3F) >> 6);
1944 }
1945 while(o.l & 0x1FF) o.write_shift(-4, consts.ENDOFCHAIN);
1946 for(i = 0; i < L[4]<<2; ++i) {
1947 var nm = cfb.FullPaths[i];
1948 if(!nm || nm.length === 0) {
1949 for(j = 0; j < 17; ++j) o.write_shift(4, 0);
1950 for(j = 0; j < 3; ++j) o.write_shift(4, -1);
1951 for(j = 0; j < 12; ++j) o.write_shift(4, 0);
1952 continue;
1953 }
1954 file = cfb.FileIndex[i];
1955 if(i === 0) file.start = file.size ? file.start - 1 : ENDOFCHAIN;
1956 var _nm = (i === 0 && _opts.root) || file.name;
1957 flen = 2*(_nm.length+1);
1958 o.write_shift(64, _nm, "utf16le");
1959 o.write_shift(2, flen);
1960 o.write_shift(1, file.type);
1961 o.write_shift(1, file.color);
1962 o.write_shift(-4, file.L);
1963 o.write_shift(-4, file.R);
1964 o.write_shift(-4, file.C);
1965 if(!file.clsid) for(j = 0; j < 4; ++j) o.write_shift(4, 0);
1966 else o.write_shift(16, file.clsid, "hex");
1967 o.write_shift(4, file.state || 0);
1968 o.write_shift(4, 0); o.write_shift(4, 0);
1969 o.write_shift(4, 0); o.write_shift(4, 0);
1970 o.write_shift(4, file.start);
1971 o.write_shift(4, file.size); o.write_shift(4, 0);
1972 }
1973 for(i = 1; i < cfb.FileIndex.length; ++i) {
1974 file = cfb.FileIndex[i];
1975if(file.size >= 0x1000) {
1976 o.l = (file.start+1) << 9;
1977 for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]);
1978 for(; j & 0x1FF; ++j) o.write_shift(1, 0);
1979 }
1980 }
1981 for(i = 1; i < cfb.FileIndex.length; ++i) {
1982 file = cfb.FileIndex[i];
1983if(file.size > 0 && file.size < 0x1000) {
1984 for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]);
1985 for(; j & 0x3F; ++j) o.write_shift(1, 0);
1986 }
1987 }
1988 while(o.l < o.length) o.write_shift(1, 0);
1989 return o;
1990}
1991/* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */
1992function find(cfb, path) {
1993 var UCFullPaths = cfb.FullPaths.map(function(x) { return x.toUpperCase(); });
1994 var UCPaths = UCFullPaths.map(function(x) { var y = x.split("/"); return y[y.length - (x.slice(-1) == "/" ? 2 : 1)]; });
1995 var k = false;
1996 if(path.charCodeAt(0) === 47 /* "/" */) { k = true; path = UCFullPaths[0].slice(0, -1) + path; }
1997 else k = path.indexOf("/") !== -1;
1998 var UCPath = path.toUpperCase();
1999 var w = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath);
2000 if(w !== -1) return cfb.FileIndex[w];
2001
2002 var m = !UCPath.match(chr1);
2003 UCPath = UCPath.replace(chr0,'');
2004 if(m) UCPath = UCPath.replace(chr1,'!');
2005 for(w = 0; w < UCFullPaths.length; ++w) {
2006 if((m ? UCFullPaths[w].replace(chr1,'!') : UCFullPaths[w]).replace(chr0,'') == UCPath) return cfb.FileIndex[w];
2007 if((m ? UCPaths[w].replace(chr1,'!') : UCPaths[w]).replace(chr0,'') == UCPath) return cfb.FileIndex[w];
2008 }
2009 return null;
2010}
2011/** CFB Constants */
2012var MSSZ = 64; /* Mini Sector Size = 1<<6 */
2013//var MSCSZ = 4096; /* Mini Stream Cutoff Size */
2014/* 2.1 Compound File Sector Numbers and Types */
2015var ENDOFCHAIN = -2;
2016/* 2.2 Compound File Header */
2017var HEADER_SIGNATURE = 'd0cf11e0a1b11ae1';
2018var HEADER_SIG = [0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1];
2019var HEADER_CLSID = '00000000000000000000000000000000';
2020var consts = {
2021 /* 2.1 Compund File Sector Numbers and Types */
2022 MAXREGSECT: -6,
2023 DIFSECT: -4,
2024 FATSECT: -3,
2025 ENDOFCHAIN: ENDOFCHAIN,
2026 FREESECT: -1,
2027 /* 2.2 Compound File Header */
2028 HEADER_SIGNATURE: HEADER_SIGNATURE,
2029 HEADER_MINOR_VERSION: '3e00',
2030 MAXREGSID: -6,
2031 NOSTREAM: -1,
2032 HEADER_CLSID: HEADER_CLSID,
2033 /* 2.6.1 Compound File Directory Entry */
2034 EntryTypes: ['unknown','storage','stream','lockbytes','property','root']
2035};
2036
2037function write_file(cfb, filename, options) {
2038 get_fs();
2039 var o = _write(cfb, options);
2040fs.writeFileSync(filename, o);
2041}
2042
2043function a2s(o) {
2044 var out = new Array(o.length);
2045 for(var i = 0; i < o.length; ++i) out[i] = String.fromCharCode(o[i]);
2046 return out.join("");
2047}
2048
2049function write(cfb, options) {
2050 var o = _write(cfb, options);
2051 switch(options && options.type) {
2052 case "file": get_fs(); fs.writeFileSync(options.filename, (o)); return o;
2053 case "binary": return a2s(o);
2054 case "base64": return Base64.encode(a2s(o));
2055 }
2056 return o;
2057}
2058/* node < 8.1 zlib does not expose bytesRead, so default to pure JS */
2059var _zlib;
2060function use_zlib(zlib) { try {
2061 var InflateRaw = zlib.InflateRaw;
2062 var InflRaw = new InflateRaw();
2063 InflRaw._processChunk(new Uint8Array([3, 0]), InflRaw._finishFlushFlag);
2064 if(InflRaw.bytesRead) _zlib = zlib;
2065 else throw new Error("zlib does not expose bytesRead");
2066} catch(e) {console.error("cannot use native zlib: " + (e.message || e)); } }
2067
2068function _inflateRawSync(payload, usz) {
2069 if(!_zlib) return _inflate(payload, usz);
2070 var InflateRaw = _zlib.InflateRaw;
2071 var InflRaw = new InflateRaw();
2072 var out = InflRaw._processChunk(payload.slice(payload.l), InflRaw._finishFlushFlag);
2073 payload.l += InflRaw.bytesRead;
2074 return out;
2075}
2076
2077function _deflateRawSync(payload) {
2078 return _zlib ? _zlib.deflateRawSync(payload) : _deflate(payload);
2079}
2080var CLEN_ORDER = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
2081
2082/* 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 ]; */
2083var 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 ];
2084
2085/* 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 ]; */
2086var 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 ];
2087
2088function bit_swap_8(n) { var t = (((((n<<1)|(n<<11)) & 0x22110) | (((n<<5)|(n<<15)) & 0x88440))); return ((t>>16) | (t>>8) |t)&0xFF; }
2089
2090var use_typed_arrays = typeof Uint8Array !== 'undefined';
2091
2092var bitswap8 = use_typed_arrays ? new Uint8Array(1<<8) : [];
2093for(var q = 0; q < (1<<8); ++q) bitswap8[q] = bit_swap_8(q);
2094
2095function bit_swap_n(n, b) {
2096 var rev = bitswap8[n & 0xFF];
2097 if(b <= 8) return rev >>> (8-b);
2098 rev = (rev << 8) | bitswap8[(n>>8)&0xFF];
2099 if(b <= 16) return rev >>> (16-b);
2100 rev = (rev << 8) | bitswap8[(n>>16)&0xFF];
2101 return rev >>> (24-b);
2102}
2103
2104/* helpers for unaligned bit reads */
2105function read_bits_2(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 6 ? 0 : buf[h+1]<<8))>>>w)& 0x03; }
2106function read_bits_3(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 5 ? 0 : buf[h+1]<<8))>>>w)& 0x07; }
2107function read_bits_4(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 4 ? 0 : buf[h+1]<<8))>>>w)& 0x0F; }
2108function read_bits_5(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 3 ? 0 : buf[h+1]<<8))>>>w)& 0x1F; }
2109function read_bits_7(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 1 ? 0 : buf[h+1]<<8))>>>w)& 0x7F; }
2110
2111/* works up to n = 3 * 8 + 1 = 25 */
2112function read_bits_n(buf, bl, n) {
2113 var w = (bl&7), h = (bl>>>3), f = ((1<<n)-1);
2114 var v = buf[h] >>> w;
2115 if(n < 8 - w) return v & f;
2116 v |= buf[h+1]<<(8-w);
2117 if(n < 16 - w) return v & f;
2118 v |= buf[h+2]<<(16-w);
2119 if(n < 24 - w) return v & f;
2120 v |= buf[h+3]<<(24-w);
2121 return v & f;
2122}
2123
2124/* until ArrayBuffer#realloc is a thing, fake a realloc */
2125function realloc(b, sz) {
2126 var L = b.length, M = 2*L > sz ? 2*L : sz + 5, i = 0;
2127 if(L >= sz) return b;
2128 if(has_buf) {
2129 var o = new_unsafe_buf(M);
2130 // $FlowIgnore
2131 if(b.copy) b.copy(o);
2132 else for(; i < b.length; ++i) o[i] = b[i];
2133 return o;
2134 } else if(use_typed_arrays) {
2135 var a = new Uint8Array(M);
2136 if(a.set) a.set(b);
2137 else for(; i < b.length; ++i) a[i] = b[i];
2138 return a;
2139 }
2140 b.length = M;
2141 return b;
2142}
2143
2144/* zero-filled arrays for older browsers */
2145function zero_fill_array(n) {
2146 var o = new Array(n);
2147 for(var i = 0; i < n; ++i) o[i] = 0;
2148 return o;
2149}var _deflate = (function() {
2150var _deflateRaw = (function() {
2151 return function deflateRaw(data, out) {
2152 var boff = 0;
2153 while(boff < data.length) {
2154 var L = Math.min(0xFFFF, data.length - boff);
2155 var h = boff + L == data.length;
2156 /* TODO: this is only type 0 stored */
2157 out.write_shift(1, +h);
2158 out.write_shift(2, L);
2159 out.write_shift(2, (~L) & 0xFFFF);
2160 while(L-- > 0) out[out.l++] = data[boff++];
2161 }
2162 return out.l;
2163 };
2164})();
2165
2166return function(data) {
2167 var buf = new_buf(50+Math.floor(data.length*1.1));
2168 var off = _deflateRaw(data, buf);
2169 return buf.slice(0, off);
2170};
2171})();
2172/* modified inflate function also moves original read head */
2173
2174/* build tree (used for literals and lengths) */
2175function build_tree(clens, cmap, MAX) {
2176 var maxlen = 1, w = 0, i = 0, j = 0, ccode = 0, L = clens.length;
2177
2178 var bl_count = use_typed_arrays ? new Uint16Array(32) : zero_fill_array(32);
2179 for(i = 0; i < 32; ++i) bl_count[i] = 0;
2180
2181 for(i = L; i < MAX; ++i) clens[i] = 0;
2182 L = clens.length;
2183
2184 var ctree = use_typed_arrays ? new Uint16Array(L) : zero_fill_array(L); // []
2185
2186 /* build code tree */
2187 for(i = 0; i < L; ++i) {
2188 bl_count[(w = clens[i])]++;
2189 if(maxlen < w) maxlen = w;
2190 ctree[i] = 0;
2191 }
2192 bl_count[0] = 0;
2193 for(i = 1; i <= maxlen; ++i) bl_count[i+16] = (ccode = (ccode + bl_count[i-1])<<1);
2194 for(i = 0; i < L; ++i) {
2195 ccode = clens[i];
2196 if(ccode != 0) ctree[i] = bl_count[ccode+16]++;
2197 }
2198
2199 /* cmap[maxlen + 4 bits] = (off&15) + (lit<<4) reverse mapping */
2200 var cleni = 0;
2201 for(i = 0; i < L; ++i) {
2202 cleni = clens[i];
2203 if(cleni != 0) {
2204 ccode = bit_swap_n(ctree[i], maxlen)>>(maxlen-cleni);
2205 for(j = (1<<(maxlen + 4 - cleni)) - 1; j>=0; --j)
2206 cmap[ccode|(j<<cleni)] = (cleni&15) | (i<<4);
2207 }
2208 }
2209 return maxlen;
2210}
2211
2212var fix_lmap = use_typed_arrays ? new Uint16Array(512) : zero_fill_array(512);
2213var fix_dmap = use_typed_arrays ? new Uint16Array(32) : zero_fill_array(32);
2214if(!use_typed_arrays) {
2215 for(var i = 0; i < 512; ++i) fix_lmap[i] = 0;
2216 for(i = 0; i < 32; ++i) fix_dmap[i] = 0;
2217}
2218(function() {
2219 var dlens = [];
2220 var i = 0;
2221 for(;i<32; i++) dlens.push(5);
2222 build_tree(dlens, fix_dmap, 32);
2223
2224 var clens = [];
2225 i = 0;
2226 for(; i<=143; i++) clens.push(8);
2227 for(; i<=255; i++) clens.push(9);
2228 for(; i<=279; i++) clens.push(7);
2229 for(; i<=287; i++) clens.push(8);
2230 build_tree(clens, fix_lmap, 288);
2231})();
2232
2233var dyn_lmap = use_typed_arrays ? new Uint16Array(32768) : zero_fill_array(32768);
2234var dyn_dmap = use_typed_arrays ? new Uint16Array(32768) : zero_fill_array(32768);
2235var dyn_cmap = use_typed_arrays ? new Uint16Array(128) : zero_fill_array(128);
2236var dyn_len_1 = 1, dyn_len_2 = 1;
2237
2238/* 5.5.3 Expanding Huffman Codes */
2239function dyn(data, boff) {
2240 /* nomenclature from RFC1951 refers to bit values; these are offset by the implicit constant */
2241 var _HLIT = read_bits_5(data, boff) + 257; boff += 5;
2242 var _HDIST = read_bits_5(data, boff) + 1; boff += 5;
2243 var _HCLEN = read_bits_4(data, boff) + 4; boff += 4;
2244 var w = 0;
2245
2246 /* grab and store code lengths */
2247 var clens = use_typed_arrays ? new Uint8Array(19) : zero_fill_array(19);
2248 var ctree = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
2249 var maxlen = 1;
2250 var bl_count = use_typed_arrays ? new Uint8Array(8) : zero_fill_array(8);
2251 var next_code = use_typed_arrays ? new Uint8Array(8) : zero_fill_array(8);
2252 var L = clens.length; /* 19 */
2253 for(var i = 0; i < _HCLEN; ++i) {
2254 clens[CLEN_ORDER[i]] = w = read_bits_3(data, boff);
2255 if(maxlen < w) maxlen = w;
2256 bl_count[w]++;
2257 boff += 3;
2258 }
2259
2260 /* build code tree */
2261 var ccode = 0;
2262 bl_count[0] = 0;
2263 for(i = 1; i <= maxlen; ++i) next_code[i] = ccode = (ccode + bl_count[i-1])<<1;
2264 for(i = 0; i < L; ++i) if((ccode = clens[i]) != 0) ctree[i] = next_code[ccode]++;
2265 /* cmap[7 bits from stream] = (off&7) + (lit<<3) */
2266 var cleni = 0;
2267 for(i = 0; i < L; ++i) {
2268 cleni = clens[i];
2269 if(cleni != 0) {
2270 ccode = bitswap8[ctree[i]]>>(8-cleni);
2271 for(var j = (1<<(7-cleni))-1; j>=0; --j) dyn_cmap[ccode|(j<<cleni)] = (cleni&7) | (i<<3);
2272 }
2273 }
2274
2275 /* read literal and dist codes at once */
2276 var hcodes = [];
2277 maxlen = 1;
2278 for(; hcodes.length < _HLIT + _HDIST;) {
2279 ccode = dyn_cmap[read_bits_7(data, boff)];
2280 boff += ccode & 7;
2281 switch((ccode >>>= 3)) {
2282 case 16:
2283 w = 3 + read_bits_2(data, boff); boff += 2;
2284 ccode = hcodes[hcodes.length - 1];
2285 while(w-- > 0) hcodes.push(ccode);
2286 break;
2287 case 17:
2288 w = 3 + read_bits_3(data, boff); boff += 3;
2289 while(w-- > 0) hcodes.push(0);
2290 break;
2291 case 18:
2292 w = 11 + read_bits_7(data, boff); boff += 7;
2293 while(w -- > 0) hcodes.push(0);
2294 break;
2295 default:
2296 hcodes.push(ccode);
2297 if(maxlen < ccode) maxlen = ccode;
2298 break;
2299 }
2300 }
2301
2302 /* build literal / length trees */
2303 var h1 = hcodes.slice(0, _HLIT), h2 = hcodes.slice(_HLIT);
2304 for(i = _HLIT; i < 286; ++i) h1[i] = 0;
2305 for(i = _HDIST; i < 30; ++i) h2[i] = 0;
2306 dyn_len_1 = build_tree(h1, dyn_lmap, 286);
2307 dyn_len_2 = build_tree(h2, dyn_dmap, 30);
2308 return boff;
2309}
2310
2311/* return [ data, bytesRead ] */
2312function inflate(data, usz) {
2313 /* shortcircuit for empty buffer [0x03, 0x00] */
2314 if(data[0] == 3 && !(data[1] & 0x3)) { return [new_raw_buf(usz), 2]; }
2315
2316 /* bit offset */
2317 var boff = 0;
2318
2319 /* header includes final bit and type bits */
2320 var header = 0;
2321
2322 var outbuf = new_unsafe_buf(usz ? usz : (1<<18));
2323 var woff = 0;
2324 var OL = outbuf.length>>>0;
2325 var max_len_1 = 0, max_len_2 = 0;
2326
2327 while((header&1) == 0) {
2328 header = read_bits_3(data, boff); boff += 3;
2329 if((header >>> 1) == 0) {
2330 /* Stored block */
2331 if(boff & 7) boff += 8 - (boff&7);
2332 /* 2 bytes sz, 2 bytes bit inverse */
2333 var sz = data[boff>>>3] | data[(boff>>>3)+1]<<8;
2334 boff += 32;
2335 /* push sz bytes */
2336 if(!usz && OL < woff + sz) { outbuf = realloc(outbuf, woff + sz); OL = outbuf.length; }
2337 if(typeof data.copy === 'function') {
2338 // $FlowIgnore
2339 data.copy(outbuf, woff, boff>>>3, (boff>>>3)+sz);
2340 woff += sz; boff += 8*sz;
2341 } else while(sz-- > 0) { outbuf[woff++] = data[boff>>>3]; boff += 8; }
2342 continue;
2343 } else if((header >>> 1) == 1) {
2344 /* Fixed Huffman */
2345 max_len_1 = 9; max_len_2 = 5;
2346 } else {
2347 /* Dynamic Huffman */
2348 boff = dyn(data, boff);
2349 max_len_1 = dyn_len_1; max_len_2 = dyn_len_2;
2350 }
2351 if(!usz && (OL < woff + 32767)) { outbuf = realloc(outbuf, woff + 32767); OL = outbuf.length; }
2352 for(;;) { // while(true) is apparently out of vogue in modern JS circles
2353 /* ingest code and move read head */
2354 var bits = read_bits_n(data, boff, max_len_1);
2355 var code = (header>>>1) == 1 ? fix_lmap[bits] : dyn_lmap[bits];
2356 boff += code & 15; code >>>= 4;
2357 /* 0-255 are literals, 256 is end of block token, 257+ are copy tokens */
2358 if(((code>>>8)&0xFF) === 0) outbuf[woff++] = code;
2359 else if(code == 256) break;
2360 else {
2361 code -= 257;
2362 var len_eb = (code < 8) ? 0 : ((code-4)>>2); if(len_eb > 5) len_eb = 0;
2363 var tgt = woff + LEN_LN[code];
2364 /* length extra bits */
2365 if(len_eb > 0) {
2366 tgt += read_bits_n(data, boff, len_eb);
2367 boff += len_eb;
2368 }
2369
2370 /* dist code */
2371 bits = read_bits_n(data, boff, max_len_2);
2372 code = (header>>>1) == 1 ? fix_dmap[bits] : dyn_dmap[bits];
2373 boff += code & 15; code >>>= 4;
2374 var dst_eb = (code < 4 ? 0 : (code-2)>>1);
2375 var dst = DST_LN[code];
2376 /* dist extra bits */
2377 if(dst_eb > 0) {
2378 dst += read_bits_n(data, boff, dst_eb);
2379 boff += dst_eb;
2380 }
2381
2382 /* in the common case, manual byte copy is faster than TA set / Buffer copy */
2383 if(!usz && OL < tgt) { outbuf = realloc(outbuf, tgt); OL = outbuf.length; }
2384 while(woff < tgt) { outbuf[woff] = outbuf[woff - dst]; ++woff; }
2385 }
2386 }
2387 }
2388 return [usz ? outbuf : outbuf.slice(0, woff), (boff+7)>>>3];
2389}
2390
2391function _inflate(payload, usz) {
2392 var data = payload.slice(payload.l||0);
2393 var out = inflate(data, usz);
2394 payload.l += out[1];
2395 return out[0];
2396}
2397
2398function warn_or_throw(wrn, msg) {
2399 if(wrn) { if(typeof console !== 'undefined') console.error(msg); }
2400 else throw new Error(msg);
2401}
2402
2403function parse_zip(file, options) {
2404 var blob = file;
2405 prep_blob(blob, 0);
2406
2407 var FileIndex = [], FullPaths = [];
2408 var o = {
2409 FileIndex: FileIndex,
2410 FullPaths: FullPaths
2411 };
2412 init_cfb(o, { root: options.root });
2413
2414 /* find end of central directory, start just after signature */
2415 var i = blob.length - 4;
2416 while((blob[i] != 0x50 || blob[i+1] != 0x4b || blob[i+2] != 0x05 || blob[i+3] != 0x06) && i >= 0) --i;
2417 blob.l = i + 4;
2418
2419 /* parse end of central directory */
2420 blob.l += 4;
2421 var fcnt = blob.read_shift(2);
2422 blob.l += 6;
2423 var start_cd = blob.read_shift(4);
2424
2425 /* parse central directory */
2426 blob.l = start_cd;
2427
2428 for(i = 0; i < fcnt; ++i) {
2429 /* trust local file header instead of CD entry */
2430 blob.l += 20;
2431 var csz = blob.read_shift(4);
2432 var usz = blob.read_shift(4);
2433 var namelen = blob.read_shift(2);
2434 var efsz = blob.read_shift(2);
2435 var fcsz = blob.read_shift(2);
2436 blob.l += 8;
2437 var offset = blob.read_shift(4);
2438 var EF = parse_extra_field(blob.slice(blob.l+namelen, blob.l+namelen+efsz));
2439 blob.l += namelen + efsz + fcsz;
2440
2441 var L = blob.l;
2442 blob.l = offset + 4;
2443 parse_local_file(blob, csz, usz, o, EF);
2444 blob.l = L;
2445 }
2446
2447 return o;
2448}
2449
2450
2451/* head starts just after local file header signature */
2452function parse_local_file(blob, csz, usz, o, EF) {
2453 /* [local file header] */
2454 blob.l += 2;
2455 var flags = blob.read_shift(2);
2456 var meth = blob.read_shift(2);
2457 var date = parse_dos_date(blob);
2458
2459 if(flags & 0x2041) throw new Error("Unsupported ZIP encryption");
2460 var crc32 = blob.read_shift(4);
2461 var _csz = blob.read_shift(4);
2462 var _usz = blob.read_shift(4);
2463
2464 var namelen = blob.read_shift(2);
2465 var efsz = blob.read_shift(2);
2466
2467 // TODO: flags & (1<<11) // UTF8
2468 var name = ""; for(var i = 0; i < namelen; ++i) name += String.fromCharCode(blob[blob.l++]);
2469 if(efsz) {
2470 var ef = parse_extra_field(blob.slice(blob.l, blob.l + efsz));
2471 if((ef[0x5455]||{}).mt) date = ef[0x5455].mt;
2472 if(((EF||{})[0x5455]||{}).mt) date = EF[0x5455].mt;
2473 }
2474 blob.l += efsz;
2475
2476 /* [encryption header] */
2477
2478 /* [file data] */
2479 var data = blob.slice(blob.l, blob.l + _csz);
2480 switch(meth) {
2481 case 8: data = _inflateRawSync(blob, _usz); break;
2482 case 0: break;
2483 default: throw new Error("Unsupported ZIP Compression method " + meth);
2484 }
2485
2486 /* [data descriptor] */
2487 var wrn = false;
2488 if(flags & 8) {
2489 crc32 = blob.read_shift(4);
2490 if(crc32 == 0x08074b50) { crc32 = blob.read_shift(4); wrn = true; }
2491 _csz = blob.read_shift(4);
2492 _usz = blob.read_shift(4);
2493 }
2494
2495 if(_csz != csz) warn_or_throw(wrn, "Bad compressed size: " + csz + " != " + _csz);
2496 if(_usz != usz) warn_or_throw(wrn, "Bad uncompressed size: " + usz + " != " + _usz);
2497 var _crc32 = CRC32.buf(data, 0);
2498 if((crc32>>0) != (_crc32>>0)) warn_or_throw(wrn, "Bad CRC32 checksum: " + crc32 + " != " + _crc32);
2499 cfb_add(o, name, data, {unsafe: true, mt: date});
2500}
2501function write_zip(cfb, options) {
2502 var _opts = options || {};
2503 var out = [], cdirs = [];
2504 var o = new_buf(1);
2505 var method = (_opts.compression ? 8 : 0), flags = 0;
2506 var desc = false;
2507 if(desc) flags |= 8;
2508 var i = 0, j = 0;
2509
2510 var start_cd = 0, fcnt = 0;
2511 var root = cfb.FullPaths[0], fp = root, fi = cfb.FileIndex[0];
2512 var crcs = [];
2513 var sz_cd = 0;
2514
2515 for(i = 1; i < cfb.FullPaths.length; ++i) {
2516 fp = cfb.FullPaths[i].slice(root.length); fi = cfb.FileIndex[i];
2517 if(!fi.size || !fi.content || fp == "\u0001Sh33tJ5") continue;
2518 var start = start_cd;
2519
2520 /* TODO: CP437 filename */
2521 var namebuf = new_buf(fp.length);
2522 for(j = 0; j < fp.length; ++j) namebuf.write_shift(1, fp.charCodeAt(j) & 0x7F);
2523 namebuf = namebuf.slice(0, namebuf.l);
2524 crcs[fcnt] = CRC32.buf(fi.content, 0);
2525
2526 var outbuf = fi.content;
2527 if(method == 8) outbuf = _deflateRawSync(outbuf);
2528
2529 /* local file header */
2530 o = new_buf(30);
2531 o.write_shift(4, 0x04034b50);
2532 o.write_shift(2, 20);
2533 o.write_shift(2, flags);
2534 o.write_shift(2, method);
2535 /* TODO: last mod file time/date */
2536 if(fi.mt) write_dos_date(o, fi.mt);
2537 else o.write_shift(4, 0);
2538 o.write_shift(-4, (flags & 8) ? 0 : crcs[fcnt]);
2539 o.write_shift(4, (flags & 8) ? 0 : outbuf.length);
2540 o.write_shift(4, (flags & 8) ? 0 : fi.content.length);
2541 o.write_shift(2, namebuf.length);
2542 o.write_shift(2, 0);
2543
2544 start_cd += o.length;
2545 out.push(o);
2546 start_cd += namebuf.length;
2547 out.push(namebuf);
2548
2549 /* TODO: encryption header ? */
2550 start_cd += outbuf.length;
2551 out.push(outbuf);
2552
2553 /* data descriptor */
2554 if(flags & 8) {
2555 o = new_buf(12);
2556 o.write_shift(-4, crcs[fcnt]);
2557 o.write_shift(4, outbuf.length);
2558 o.write_shift(4, fi.content.length);
2559 start_cd += o.l;
2560 out.push(o);
2561 }
2562
2563 /* central directory */
2564 o = new_buf(46);
2565 o.write_shift(4, 0x02014b50);
2566 o.write_shift(2, 0);
2567 o.write_shift(2, 20);
2568 o.write_shift(2, flags);
2569 o.write_shift(2, method);
2570 o.write_shift(4, 0); /* TODO: last mod file time/date */
2571 o.write_shift(-4, crcs[fcnt]);
2572
2573 o.write_shift(4, outbuf.length);
2574 o.write_shift(4, fi.content.length);
2575 o.write_shift(2, namebuf.length);
2576 o.write_shift(2, 0);
2577 o.write_shift(2, 0);
2578 o.write_shift(2, 0);
2579 o.write_shift(2, 0);
2580 o.write_shift(4, 0);
2581 o.write_shift(4, start);
2582
2583 sz_cd += o.l;
2584 cdirs.push(o);
2585 sz_cd += namebuf.length;
2586 cdirs.push(namebuf);
2587 ++fcnt;
2588 }
2589
2590 /* end of central directory */
2591 o = new_buf(22);
2592 o.write_shift(4, 0x06054b50);
2593 o.write_shift(2, 0);
2594 o.write_shift(2, 0);
2595 o.write_shift(2, fcnt);
2596 o.write_shift(2, fcnt);
2597 o.write_shift(4, sz_cd);
2598 o.write_shift(4, start_cd);
2599 o.write_shift(2, 0);
2600
2601 return bconcat(([bconcat((out)), bconcat(cdirs), o]));
2602}
2603function cfb_new(opts) {
2604 var o = ({});
2605 init_cfb(o, opts);
2606 return o;
2607}
2608
2609function cfb_add(cfb, name, content, opts) {
2610 var unsafe = opts && opts.unsafe;
2611 if(!unsafe) init_cfb(cfb);
2612 var file = !unsafe && CFB.find(cfb, name);
2613 if(!file) {
2614 var fpath = cfb.FullPaths[0];
2615 if(name.slice(0, fpath.length) == fpath) fpath = name;
2616 else {
2617 if(fpath.slice(-1) != "/") fpath += "/";
2618 fpath = (fpath + name).replace("//","/");
2619 }
2620 file = ({name: filename(name), type: 2});
2621 cfb.FileIndex.push(file);
2622 cfb.FullPaths.push(fpath);
2623 if(!unsafe) CFB.utils.cfb_gc(cfb);
2624 }
2625file.content = (content);
2626 file.size = content ? content.length : 0;
2627 if(opts) {
2628 if(opts.CLSID) file.clsid = opts.CLSID;
2629 if(opts.mt) file.mt = opts.mt;
2630 if(opts.ct) file.ct = opts.ct;
2631 }
2632 return file;
2633}
2634
2635function cfb_del(cfb, name) {
2636 init_cfb(cfb);
2637 var file = CFB.find(cfb, name);
2638 if(file) for(var j = 0; j < cfb.FileIndex.length; ++j) if(cfb.FileIndex[j] == file) {
2639 cfb.FileIndex.splice(j, 1);
2640 cfb.FullPaths.splice(j, 1);
2641 return true;
2642 }
2643 return false;
2644}
2645
2646function cfb_mov(cfb, old_name, new_name) {
2647 init_cfb(cfb);
2648 var file = CFB.find(cfb, old_name);
2649 if(file) for(var j = 0; j < cfb.FileIndex.length; ++j) if(cfb.FileIndex[j] == file) {
2650 cfb.FileIndex[j].name = filename(new_name);
2651 cfb.FullPaths[j] = new_name;
2652 return true;
2653 }
2654 return false;
2655}
2656
2657function cfb_gc(cfb) { rebuild_cfb(cfb, true); }
2658
2659exports.find = find;
2660exports.read = read;
2661exports.parse = parse;
2662exports.write = write;
2663exports.writeFile = write_file;
2664exports.utils = {
2665 cfb_new: cfb_new,
2666 cfb_add: cfb_add,
2667 cfb_del: cfb_del,
2668 cfb_mov: cfb_mov,
2669 cfb_gc: cfb_gc,
2670 ReadShift: ReadShift,
2671 CheckField: CheckField,
2672 prep_blob: prep_blob,
2673 bconcat: bconcat,
2674 use_zlib: use_zlib,
2675 _deflateRaw: _deflate,
2676 _inflateRaw: _inflate,
2677 consts: consts
2678};
2679
2680return exports;
2681})();
2682
2683if(typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO_NOT_EXPORT_CFB === 'undefined') { module.exports = CFB; }
2684var _fs;
2685if(typeof require !== 'undefined') try { _fs = require('fs'); } catch(e) {}
2686
2687/* normalize data for blob ctor */
2688function blobify(data) {
2689 if(typeof data === "string") return s2ab(data);
2690 if(Array.isArray(data)) return a2u(data);
2691 return data;
2692}
2693/* write or download file */
2694function write_dl(fname, payload, enc) {
2695 /*global IE_SaveFile, Blob, navigator, saveAs, document, File, chrome */
2696 if(typeof _fs !== 'undefined' && _fs.writeFileSync) return enc ? _fs.writeFileSync(fname, payload, enc) : _fs.writeFileSync(fname, payload);
2697 var data = (enc == "utf8") ? utf8write(payload) : payload;
2698if(typeof IE_SaveFile !== 'undefined') return IE_SaveFile(data, fname);
2699 if(typeof Blob !== 'undefined') {
2700 var blob = new Blob([blobify(data)], {type:"application/octet-stream"});
2701if(typeof navigator !== 'undefined' && navigator.msSaveBlob) return navigator.msSaveBlob(blob, fname);
2702if(typeof saveAs !== 'undefined') return saveAs(blob, fname);
2703 if(typeof URL !== 'undefined' && typeof document !== 'undefined' && document.createElement && URL.createObjectURL) {
2704 var url = URL.createObjectURL(blob);
2705if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
2706 if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
2707 return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
2708 }
2709 var a = document.createElement("a");
2710 if(a.download != null) {
2711a.download = fname; a.href = url; document.body.appendChild(a); a.click();
2712document.body.removeChild(a);
2713 if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
2714 return url;
2715 }
2716 }
2717 }
2718 // $FlowIgnore
2719 if(typeof $ !== 'undefined' && typeof File !== 'undefined' && typeof Folder !== 'undefined') try { // extendscript
2720 // $FlowIgnore
2721 var out = File(fname); out.open("w"); out.encoding = "binary";
2722 if(Array.isArray(payload)) payload = a2s(payload);
2723 out.write(payload); out.close(); return payload;
2724 } catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; }
2725 throw new Error("cannot save file " + fname);
2726}
2727
2728/* read binary data from file */
2729function read_binary(path) {
2730 if(typeof _fs !== 'undefined') return _fs.readFileSync(path);
2731 // $FlowIgnore
2732 if(typeof $ !== 'undefined' && typeof File !== 'undefined' && typeof Folder !== 'undefined') try { // extendscript
2733 // $FlowIgnore
2734 var infile = File(path); infile.open("r"); infile.encoding = "binary";
2735 var data = infile.read(); infile.close();
2736 return data;
2737 } catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; }
2738 throw new Error("Cannot access file " + path);
2739}
2740function keys(o) {
2741 var ks = Object.keys(o), o2 = [];
2742 for(var i = 0; i < ks.length; ++i) if(Object.prototype.hasOwnProperty.call(o, ks[i])) o2.push(ks[i]);
2743 return o2;
2744}
2745
2746function evert_key(obj, key) {
2747 var o = ([]), K = keys(obj);
2748 for(var i = 0; i !== K.length; ++i) if(o[obj[K[i]][key]] == null) o[obj[K[i]][key]] = K[i];
2749 return o;
2750}
2751
2752function evert(obj) {
2753 var o = ([]), K = keys(obj);
2754 for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = K[i];
2755 return o;
2756}
2757
2758function evert_num(obj) {
2759 var o = ([]), K = keys(obj);
2760 for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = parseInt(K[i],10);
2761 return o;
2762}
2763
2764function evert_arr(obj) {
2765 var o = ([]), K = keys(obj);
2766 for(var i = 0; i !== K.length; ++i) {
2767 if(o[obj[K[i]]] == null) o[obj[K[i]]] = [];
2768 o[obj[K[i]]].push(K[i]);
2769 }
2770 return o;
2771}
2772
2773var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
2774function datenum(v, date1904) {
2775 var epoch = v.getTime();
2776 if(date1904) epoch -= 1462*24*60*60*1000;
2777 var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
2778 return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
2779}
2780var refdate = new Date();
2781var dnthresh = basedate.getTime() + (refdate.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
2782var refoffset = refdate.getTimezoneOffset();
2783function numdate(v) {
2784 var out = new Date();
2785 out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh);
2786 if (out.getTimezoneOffset() !== refoffset) {
2787 out.setTime(out.getTime() + (out.getTimezoneOffset() - refoffset) * 60000);
2788 }
2789 return out;
2790}
2791
2792/* ISO 8601 Duration */
2793function parse_isodur(s) {
2794 var sec = 0, mt = 0, time = false;
2795 var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
2796 if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
2797 for(var i = 1; i != m.length; ++i) {
2798 if(!m[i]) continue;
2799 mt = 1;
2800 if(i > 3) time = true;
2801 switch(m[i].slice(m[i].length-1)) {
2802 case 'Y':
2803 throw new Error("Unsupported ISO Duration Field: " + m[i].slice(m[i].length-1));
2804 case 'D': mt *= 24;
2805 /* falls through */
2806 case 'H': mt *= 60;
2807 /* falls through */
2808 case 'M':
2809 if(!time) throw new Error("Unsupported ISO Duration Field: M");
2810 else mt *= 60;
2811 /* falls through */
2812 case 'S': break;
2813 }
2814 sec += mt * parseInt(m[i], 10);
2815 }
2816 return sec;
2817}
2818
2819var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
2820if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
2821var good_pd = good_pd_date.getFullYear() == 2017;
2822/* parses a date as a local date */
2823function parseDate(str, fixdate) {
2824 var d = new Date(str);
2825 if(good_pd) {
2826if(fixdate > 0) d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
2827 else if(fixdate < 0) d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000);
2828 return d;
2829 }
2830 if(str instanceof Date) return str;
2831 if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
2832 var s = d.getFullYear();
2833 if(str.indexOf("" + s) > -1) return d;
2834 d.setFullYear(d.getFullYear() + 100); return d;
2835 }
2836 var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
2837 var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
2838 if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000);
2839 return out;
2840}
2841
2842function cc2str(arr) {
2843 var o = "";
2844 for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
2845 return o;
2846}
2847
2848function dup(o) {
2849 if(typeof JSON != 'undefined' && !Array.isArray(o)) return JSON.parse(JSON.stringify(o));
2850 if(typeof o != 'object' || o == null) return o;
2851 if(o instanceof Date) return new Date(o.getTime());
2852 var out = {};
2853 for(var k in o) if(Object.prototype.hasOwnProperty.call(o, k)) out[k] = dup(o[k]);
2854 return out;
2855}
2856
2857function fill(c,l) { var o = ""; while(o.length < l) o+=c; return o; }
2858
2859/* TODO: stress test */
2860function fuzzynum(s) {
2861 var v = Number(s);
2862 if(isFinite(v)) return v;
2863 if(!isNaN(v)) return NaN;
2864 if(!/\d/.test(s)) return v;
2865 var wt = 1;
2866 var ss = s.replace(/([\d]),([\d])/g,"$1$2").replace(/[$]/g,"").replace(/[%]/g, function() { wt *= 100; return "";});
2867 if(!isNaN(v = Number(ss))) return v / wt;
2868 ss = ss.replace(/[(](.*)[)]/,function($$, $1) { wt = -wt; return $1;});
2869 if(!isNaN(v = Number(ss))) return v / wt;
2870 return v;
2871}
2872function fuzzydate(s) {
2873 var o = new Date(s), n = new Date(NaN);
2874 var y = o.getYear(), m = o.getMonth(), d = o.getDate();
2875 if(isNaN(d)) return n;
2876 if(y < 0 || y > 8099) return n;
2877 if((m > 0 || d > 1) && y != 101) return o;
2878 if(s.toLowerCase().match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) return o;
2879 if(s.match(/[^-0-9:,\/\\]/)) return n;
2880 return o;
2881}
2882
2883var safe_split_regex = "abacaba".split(/(:?b)/i).length == 5;
2884function split_regex(str, re, def) {
2885 if(safe_split_regex || typeof re == "string") return str.split(re);
2886 var p = str.split(re), o = [p[0]];
2887 for(var i = 1; i < p.length; ++i) { o.push(def); o.push(p[i]); }
2888 return o;
2889}
2890function getdatastr(data) {
2891 if(!data) return null;
2892 if(data.data) return debom(data.data);
2893 if(data.asNodeBuffer && has_buf) return debom(data.asNodeBuffer().toString('binary'));
2894 if(data.asBinary) return debom(data.asBinary());
2895 if(data._data && data._data.getContent) return debom(cc2str(Array.prototype.slice.call(data._data.getContent(),0)));
2896 if(data.content && data.type) return debom(cc2str(data.content));
2897 return null;
2898}
2899
2900function getdatabin(data) {
2901 if(!data) return null;
2902 if(data.data) return char_codes(data.data);
2903 if(data.asNodeBuffer && has_buf) return data.asNodeBuffer();
2904 if(data._data && data._data.getContent) {
2905 var o = data._data.getContent();
2906 if(typeof o == "string") return char_codes(o);
2907 return Array.prototype.slice.call(o);
2908 }
2909 if(data.content && data.type) return data.content;
2910 return null;
2911}
2912
2913function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getdatabin(data) : getdatastr(data); }
2914
2915/* Part 2 Section 10.1.2 "Mapping Content Types" Names are case-insensitive */
2916/* OASIS does not comment on filename case sensitivity */
2917function safegetzipfile(zip, file) {
2918 var k = zip.FullPaths || keys(zip.files);
2919 var f = file.toLowerCase().replace(/[\/]/g, '\\'), g = f.replace(/\\/g,'\/');
2920 for(var i=0; i<k.length; ++i) {
2921 var n = k[i].replace(/^Root Entry[\/]/,"").toLowerCase();
2922 if(f == n || g == n) return zip.files ? zip.files[k[i]] : zip.FileIndex[i];
2923 }
2924 return null;
2925}
2926
2927function getzipfile(zip, file) {
2928 var o = safegetzipfile(zip, file);
2929 if(o == null) throw new Error("Cannot find file " + file + " in zip");
2930 return o;
2931}
2932
2933function getzipdata(zip, file, safe) {
2934 if(!safe) return getdata(getzipfile(zip, file));
2935 if(!file) return null;
2936 try { return getzipdata(zip, file); } catch(e) { return null; }
2937}
2938
2939function getzipstr(zip, file, safe) {
2940 if(!safe) return getdatastr(getzipfile(zip, file));
2941 if(!file) return null;
2942 try { return getzipstr(zip, file); } catch(e) { return null; }
2943}
2944
2945function zipentries(zip) {
2946 var k = zip.FullPaths || keys(zip.files), o = [];
2947 for(var i = 0; i < k.length; ++i) if(k[i].slice(-1) != '/') o.push(k[i]);
2948 return o.sort();
2949}
2950
2951function zip_add_file(zip, path, content) {
2952 if(zip.FullPaths) CFB.utils.cfb_add(zip, path, content);
2953 else zip.file(path, content);
2954}
2955
2956var jszip;
2957/*global JSZipSync:true */
2958if(typeof JSZipSync !== 'undefined') jszip = JSZipSync;
2959if(typeof exports !== 'undefined') {
2960 if(typeof module !== 'undefined' && module.exports) {
2961 if(typeof jszip === 'undefined') jszip = undefined;
2962 }
2963}
2964
2965function zip_new() {
2966 if(!jszip) return CFB.utils.cfb_new();
2967 return new jszip();
2968}
2969
2970function zip_read(d, o) {
2971 var zip;
2972 if(jszip) switch(o.type) {
2973 case "base64": zip = new jszip(d, { base64:true }); break;
2974 case "binary": case "array": zip = new jszip(d, { base64:false }); break;
2975 case "buffer": zip = new jszip(d); break;
2976 default: throw new Error("Unrecognized type " + o.type);
2977 }
2978 else switch(o.type) {
2979 case "base64": zip = CFB.read(d, { type: "base64" }); break;
2980 case "binary": zip = CFB.read(d, { type: "binary" }); break;
2981 case "buffer": case "array": zip = CFB.read(d, { type: "buffer" }); break;
2982 default: throw new Error("Unrecognized type " + o.type);
2983 }
2984 return zip;
2985}
2986
2987function resolve_path(path, base) {
2988 if(path.charAt(0) == "/") return path.slice(1);
2989 var result = base.split('/');
2990 if(base.slice(-1) != "/") result.pop(); // folder path
2991 var target = path.split('/');
2992 while (target.length !== 0) {
2993 var step = target.shift();
2994 if (step === '..') result.pop();
2995 else if (step !== '.') result.push(step);
2996 }
2997 return result.join('/');
2998}
2999var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
3000var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
3001var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s*[\/\?]?>/mg;
3002
3003if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
3004var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
3005function parsexmltag(tag, skip_root, skip_LC) {
3006 var z = ({});
3007 var eq = 0, c = 0;
3008 for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
3009 if(!skip_root) z[0] = tag.slice(0, eq);
3010 if(eq === tag.length) return z;
3011 var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1;
3012 if(m) for(i = 0; i != m.length; ++i) {
3013 cc = m[i];
3014 for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
3015 q = cc.slice(0,c).trim();
3016 while(cc.charCodeAt(c+1) == 32) ++c;
3017 quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0;
3018 v = cc.slice(c+1+quot, cc.length-quot);
3019 for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
3020 if(j===q.length) {
3021 if(q.indexOf("_") > 0) q = q.slice(0, q.indexOf("_")); // from ods
3022 z[q] = v;
3023 if(!skip_LC) z[q.toLowerCase()] = v;
3024 }
3025 else {
3026 var k = (j===5 && q.slice(0,5)==="xmlns"?"xmlns":"")+q.slice(j+1);
3027 if(z[k] && q.slice(j-3,j) == "ext") continue; // from ods
3028 z[k] = v;
3029 if(!skip_LC) z[k.toLowerCase()] = v;
3030 }
3031 }
3032 return z;
3033}
3034function strip_ns(x) { return x.replace(nsregex2, "<$1"); }
3035
3036var encodings = {
3037 '&quot;': '"',
3038 '&apos;': "'",
3039 '&gt;': '>',
3040 '&lt;': '<',
3041 '&amp;': '&'
3042};
3043var rencoding = evert(encodings);
3044//var rencstr = "&<>'\"".split("");
3045
3046// TODO: CP remap (need to read file version to determine OS)
3047var unescapexml = (function() {
3048 /* 22.4.2.4 bstr (Basic String) */
3049 var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig;
3050 return function unescapexml(text) {
3051 var s = text + '', i = s.indexOf("<![CDATA[");
3052 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));});
3053 var j = s.indexOf("]]>");
3054 return unescapexml(s.slice(0, i)) + s.slice(i+9,j) + unescapexml(s.slice(j+3));
3055 };
3056})();
3057
3058var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
3059function escapexml(text){
3060 var s = text + '';
3061 return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";});
3062}
3063function escapexmltag(text){ return escapexml(text).replace(/ /g,"_x0020_"); }
3064
3065var htmlcharegex = /[\u0000-\u001f]/g;
3066function escapehtml(text){
3067 var s = text + '';
3068 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) + ";"; });
3069}
3070
3071function escapexlml(text){
3072 var s = text + '';
3073 return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; });
3074}
3075
3076/* TODO: handle codepages */
3077var xlml_fixstr = (function() {
3078 var entregex = /&#(\d+);/g;
3079 function entrepl($$,$1) { return String.fromCharCode(parseInt($1,10)); }
3080 return function xlml_fixstr(str) { return str.replace(entregex,entrepl); };
3081})();
3082var xlml_unfixstr = (function() {
3083 return function xlml_unfixstr(str) { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); };
3084})();
3085
3086function parsexmlbool(value) {
3087 switch(value) {
3088 case 1: case true: case '1': case 'true': case 'TRUE': return true;
3089 /* case '0': case 'false': case 'FALSE':*/
3090 default: return false;
3091 }
3092}
3093
3094var utf8read = function utf8reada(orig) {
3095 var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
3096 while (i < orig.length) {
3097 c = orig.charCodeAt(i++);
3098 if (c < 128) { out += String.fromCharCode(c); continue; }
3099 d = orig.charCodeAt(i++);
3100 if (c>191 && c<224) { f = ((c & 31) << 6); f |= (d & 63); out += String.fromCharCode(f); continue; }
3101 e = orig.charCodeAt(i++);
3102 if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; }
3103 f = orig.charCodeAt(i++);
3104 w = (((c & 7) << 18) | ((d & 63) << 12) | ((e & 63) << 6) | (f & 63))-65536;
3105 out += String.fromCharCode(0xD800 + ((w>>>10)&1023));
3106 out += String.fromCharCode(0xDC00 + (w&1023));
3107 }
3108 return out;
3109};
3110
3111var utf8write = function(orig) {
3112 var out = [], i = 0, c = 0, d = 0;
3113 while(i < orig.length) {
3114 c = orig.charCodeAt(i++);
3115 switch(true) {
3116 case c < 128: out.push(String.fromCharCode(c)); break;
3117 case c < 2048:
3118 out.push(String.fromCharCode(192 + (c >> 6)));
3119 out.push(String.fromCharCode(128 + (c & 63)));
3120 break;
3121 case c >= 55296 && c < 57344:
3122 c -= 55296; d = orig.charCodeAt(i++) - 56320 + (c<<10);
3123 out.push(String.fromCharCode(240 + ((d >>18) & 7)));
3124 out.push(String.fromCharCode(144 + ((d >>12) & 63)));
3125 out.push(String.fromCharCode(128 + ((d >> 6) & 63)));
3126 out.push(String.fromCharCode(128 + (d & 63)));
3127 break;
3128 default:
3129 out.push(String.fromCharCode(224 + (c >> 12)));
3130 out.push(String.fromCharCode(128 + ((c >> 6) & 63)));
3131 out.push(String.fromCharCode(128 + (c & 63)));
3132 }
3133 }
3134 return out.join("");
3135};
3136
3137if(has_buf) {
3138 var utf8readb = function utf8readb(data) {
3139 var out = Buffer.alloc(2*data.length), w, i, j = 1, k = 0, ww=0, c;
3140 for(i = 0; i < data.length; i+=j) {
3141 j = 1;
3142 if((c=data.charCodeAt(i)) < 128) w = c;
3143 else if(c < 224) { w = (c&31)*64+(data.charCodeAt(i+1)&63); j=2; }
3144 else if(c < 240) { w=(c&15)*4096+(data.charCodeAt(i+1)&63)*64+(data.charCodeAt(i+2)&63); j=3; }
3145 else { j = 4;
3146 w = (c & 7)*262144+(data.charCodeAt(i+1)&63)*4096+(data.charCodeAt(i+2)&63)*64+(data.charCodeAt(i+3)&63);
3147 w -= 65536; ww = 0xD800 + ((w>>>10)&1023); w = 0xDC00 + (w&1023);
3148 }
3149 if(ww !== 0) { out[k++] = ww&255; out[k++] = ww>>>8; ww = 0; }
3150 out[k++] = w%256; out[k++] = w>>>8;
3151 }
3152 return out.slice(0,k).toString('ucs2');
3153 };
3154 var corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3";
3155 if(utf8read(corpus) == utf8readb(corpus)) utf8read = utf8readb;
3156 var utf8readc = function utf8readc(data) { return Buffer_from(data, 'binary').toString('utf8'); };
3157 if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
3158
3159 utf8write = function(data) { return Buffer_from(data, 'utf8').toString("binary"); };
3160}
3161
3162// matches <foo>...</foo> extracts content
3163var matchtag = (function() {
3164 var mtcache = ({});
3165 return function matchtag(f,g) {
3166 var t = f+"|"+(g||"");
3167 if(mtcache[t]) return mtcache[t];
3168 return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([\\s\\S]*?)</(?:\\w+:)?'+f+'>',((g||""))));
3169 };
3170})();
3171
3172var htmldecode = (function() {
3173 var entities = [
3174 ['nbsp', ' '], ['middot', '·'],
3175 ['quot', '"'], ['apos', "'"], ['gt', '>'], ['lt', '<'], ['amp', '&']
3176 ].map(function(x) { return [new RegExp('&' + x[0] + ';', "ig"), x[1]]; });
3177 return function htmldecode(str) {
3178 var o = str
3179 // Remove new lines and spaces from start of content
3180 .replace(/^[\t\n\r ]+/, "")
3181 // Remove new lines and spaces from end of content
3182 .replace(/[\t\n\r ]+$/,"")
3183 // Added line which removes any white space characters after and before html tags
3184 .replace(/>\s+/g,">").replace(/\s+</g,"<")
3185 // Replace remaining new lines and spaces with space
3186 .replace(/[\t\n\r ]+/g, " ")
3187 // Replace <br> tags with new lines
3188 .replace(/<\s*[bB][rR]\s*\/?>/g,"\n")
3189 // Strip HTML elements
3190 .replace(/<[^>]*>/g,"");
3191 for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]);
3192 return o;
3193 };
3194})();
3195
3196var vtregex = (function(){ var vt_cache = {};
3197 return function vt_regex(bt) {
3198 if(vt_cache[bt] !== undefined) return vt_cache[bt];
3199 return (vt_cache[bt] = new RegExp("<(?:vt:)?" + bt + ">([\\s\\S]*?)</(?:vt:)?" + bt + ">", 'g') );
3200};})();
3201var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^>]*)>([\s\S]*)</;
3202function parseVector(data, opts) {
3203 var h = parsexmltag(data);
3204
3205 var matches = data.match(vtregex(h.baseType))||[];
3206 var res = [];
3207 if(matches.length != h.size) {
3208 if(opts.WTF) throw new Error("unexpected vector length " + matches.length + " != " + h.size);
3209 return res;
3210 }
3211 matches.forEach(function(x) {
3212 var v = x.replace(vtvregex,"").match(vtmregex);
3213 if(v) res.push({v:utf8read(v[2]), t:v[1]});
3214 });
3215 return res;
3216}
3217
3218var wtregex = /(^\s|\s$|\n)/;
3219function writetag(f,g) { return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>'; }
3220
3221function wxt_helper(h) { return keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join(""); }
3222function writextag(f,g,h) { return '<' + f + ((h != null) ? wxt_helper(h) : "") + ((g != null) ? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';}
3223
3224function write_w3cdtf(d, t) { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } return ""; }
3225
3226function write_vt(s, xlsx) {
3227 switch(typeof s) {
3228 case 'string':
3229 var o = writextag('vt:lpwstr', escapexml(s));
3230 if(xlsx) o = o.replace(/&quot;/g, "_x0022_");
3231 return o;
3232 case 'number': return writextag((s|0)==s?'vt:i4':'vt:r8', escapexml(String(s)));
3233 case 'boolean': return writextag('vt:bool',s?'true':'false');
3234 }
3235 if(s instanceof Date) return writextag('vt:filetime', write_w3cdtf(s));
3236 throw new Error("Unable to serialize " + s);
3237}
3238
3239var XMLNS = ({
3240 'dc': 'http://purl.org/dc/elements/1.1/',
3241 'dcterms': 'http://purl.org/dc/terms/',
3242 'dcmitype': 'http://purl.org/dc/dcmitype/',
3243 'mx': 'http://schemas.microsoft.com/office/mac/excel/2008/main',
3244 'r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
3245 'sjs': 'http://schemas.openxmlformats.org/package/2006/sheetjs/core-properties',
3246 'vt': 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes',
3247 'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
3248 'xsd': 'http://www.w3.org/2001/XMLSchema'
3249});
3250
3251XMLNS.main = [
3252 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
3253 'http://purl.oclc.org/ooxml/spreadsheetml/main',
3254 'http://schemas.microsoft.com/office/excel/2006/main',
3255 'http://schemas.microsoft.com/office/excel/2006/2'
3256];
3257
3258var XLMLNS = ({
3259 'o': 'urn:schemas-microsoft-com:office:office',
3260 'x': 'urn:schemas-microsoft-com:office:excel',
3261 'ss': 'urn:schemas-microsoft-com:office:spreadsheet',
3262 'dt': 'uuid:C2F41010-65B3-11d1-A29F-00AA00C14882',
3263 'mv': 'http://macVmlSchemaUri',
3264 'v': 'urn:schemas-microsoft-com:vml',
3265 'html': 'http://www.w3.org/TR/REC-html40'
3266});
3267function read_double_le(b, idx) {
3268 var s = 1 - 2 * (b[idx + 7] >>> 7);
3269 var e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 0x0f);
3270 var m = (b[idx+6]&0x0f);
3271 for(var i = 5; i >= 0; --i) m = m * 256 + b[idx + i];
3272 if(e == 0x7ff) return m == 0 ? (s * Infinity) : NaN;
3273 if(e == 0) e = -1022;
3274 else { e -= 1023; m += Math.pow(2,52); }
3275 return s * Math.pow(2, e - 52) * m;
3276}
3277
3278function write_double_le(b, v, idx) {
3279 var bs = ((((v < 0) || (1/v == -Infinity)) ? 1 : 0) << 7), e = 0, m = 0;
3280 var av = bs ? (-v) : v;
3281 if(!isFinite(av)) { e = 0x7ff; m = isNaN(v) ? 0x6969 : 0; }
3282 else if(av == 0) e = m = 0;
3283 else {
3284 e = Math.floor(Math.log(av) / Math.LN2);
3285 m = av * Math.pow(2, 52 - e);
3286 if((e <= -1023) && (!isFinite(m) || (m < Math.pow(2,52)))) { e = -1022; }
3287 else { m -= Math.pow(2,52); e+=1023; }
3288 }
3289 for(var i = 0; i <= 5; ++i, m/=256) b[idx + i] = m & 0xff;
3290 b[idx + 6] = ((e & 0x0f) << 4) | (m & 0xf);
3291 b[idx + 7] = (e >> 4) | bs;
3292}
3293
3294var __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; };
3295var ___toBuffer = __toBuffer;
3296var __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,''); };
3297var ___utf16le = __utf16le;
3298var __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(""); };
3299var ___hexlify = __hexlify;
3300var __utf8 = function(b,s,e) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
3301var ___utf8 = __utf8;
3302var __lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
3303var ___lpstr = __lpstr;
3304var __cpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
3305var ___cpstr = __cpstr;
3306var __lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
3307var ___lpwstr = __lpwstr;
3308var __lpp4, ___lpp4;
3309__lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
3310var __8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
3311var ___8lpp4 = __8lpp4;
3312var __double, ___double;
3313__double = ___double = function(b, idx) { return read_double_le(b, idx);};
3314var is_buf = function is_buf_a(a) { return Array.isArray(a); };
3315
3316if(has_buf) {
3317 __utf16le = function(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e).replace(chr0,'')/*.replace(chr1,'!')*/; };
3318 __hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
3319 __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) : "";};
3320 __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) : "";};
3321 __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);};
3322 __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);};
3323 __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);};
3324 __utf8 = function utf8_b(b, s, e) { return (Buffer.isBuffer(b)) ? b.toString('utf8',s,e) : ___utf8(b,s,e); };
3325 __toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);};
3326 bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); };
3327 __double = function double_(b, i) { if(Buffer.isBuffer(b)) return b.readDoubleLE(i); return ___double(b,i); };
3328 is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); };
3329}
3330
3331/* from js-xls */
3332if(typeof cptable !== 'undefined') {
3333 __utf16le = function(b,s,e) { return cptable.utils.decode(1200, b.slice(s,e)).replace(chr0, ''); };
3334 __utf8 = function(b,s,e) { return cptable.utils.decode(65001, b.slice(s,e)); };
3335 __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)) : "";};
3336 __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)) : "";};
3337 __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)) : "";};
3338 __lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";};
3339 __8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";};
3340}
3341
3342var __readUInt8 = function(b, idx) { return b[idx]; };
3343var __readUInt16LE = function(b, idx) { return (b[idx+1]*(1<<8))+b[idx]; };
3344var __readInt16LE = function(b, idx) { var u = (b[idx+1]*(1<<8))+b[idx]; return (u < 0x8000) ? u : ((0xffff - u + 1) * -1); };
3345var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
3346var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
3347var __readInt32BE = function(b, idx) { return (b[idx]<<24)|(b[idx+1]<<16)|(b[idx+2]<<8)|b[idx+3]; };
3348
3349function ReadShift(size, t) {
3350 var o="", oI, oR, oo=[], w, vv, i, loc;
3351 switch(t) {
3352 case 'dbcs':
3353 loc = this.l;
3354 if(has_buf && Buffer.isBuffer(this)) o = this.slice(this.l, this.l+2*size).toString("utf16le");
3355 else for(i = 0; i < size; ++i) { o+=String.fromCharCode(__readUInt16LE(this, loc)); loc+=2; }
3356 size *= 2;
3357 break;
3358
3359 case 'utf8': o = __utf8(this, this.l, this.l + size); break;
3360 case 'utf16le': size *= 2; o = __utf16le(this, this.l, this.l + size); break;
3361
3362 case 'wstr':
3363 if(typeof cptable !== 'undefined') o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l+2*size));
3364 else return ReadShift.call(this, size, 'dbcs');
3365 size = 2 * size; break;
3366
3367 /* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */
3368 case 'lpstr-ansi': o = __lpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break;
3369 case 'lpstr-cp': o = __cpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break;
3370 /* [MS-OLEDS] 2.1.5 LengthPrefixedUnicodeString */
3371 case 'lpwstr': o = __lpwstr(this, this.l); size = 4 + 2 * __readUInt32LE(this, this.l); break;
3372 /* [MS-OFFCRYPTO] 2.1.2 Length-Prefixed Padded Unicode String (UNICODE-LP-P4) */
3373 case 'lpp4': size = 4 + __readUInt32LE(this, this.l); o = __lpp4(this, this.l); if(size & 0x02) size += 2; break;
3374 /* [MS-OFFCRYPTO] 2.1.3 Length-Prefixed UTF-8 String (UTF-8-LP-P4) */
3375 case '8lpp4': size = 4 + __readUInt32LE(this, this.l); o = __8lpp4(this, this.l); if(size & 0x03) size += 4 - (size & 0x03); break;
3376
3377 case 'cstr': size = 0; o = "";
3378 while((w=__readUInt8(this, this.l + size++))!==0) oo.push(_getchar(w));
3379 o = oo.join(""); break;
3380 case '_wstr': size = 0; o = "";
3381 while((w=__readUInt16LE(this,this.l +size))!==0){oo.push(_getchar(w));size+=2;}
3382 size+=2; o = oo.join(""); break;
3383
3384 /* sbcs and dbcs support continue records in the SST way TODO codepages */
3385 case 'dbcs-cont': o = ""; loc = this.l;
3386 for(i = 0; i < size; ++i) {
3387 if(this.lens && this.lens.indexOf(loc) !== -1) {
3388 w = __readUInt8(this, loc);
3389 this.l = loc + 1;
3390 vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont');
3391 return oo.join("") + vv;
3392 }
3393 oo.push(_getchar(__readUInt16LE(this, loc)));
3394 loc+=2;
3395 } o = oo.join(""); size *= 2; break;
3396
3397 case 'cpstr':
3398 if(typeof cptable !== 'undefined') {
3399 o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l + size));
3400 break;
3401 }
3402 /* falls through */
3403 case 'sbcs-cont': o = ""; loc = this.l;
3404 for(i = 0; i != size; ++i) {
3405 if(this.lens && this.lens.indexOf(loc) !== -1) {
3406 w = __readUInt8(this, loc);
3407 this.l = loc + 1;
3408 vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont');
3409 return oo.join("") + vv;
3410 }
3411 oo.push(_getchar(__readUInt8(this, loc)));
3412 loc+=1;
3413 } o = oo.join(""); break;
3414
3415 default:
3416 switch(size) {
3417 case 1: oI = __readUInt8(this, this.l); this.l++; return oI;
3418 case 2: oI = (t === 'i' ? __readInt16LE : __readUInt16LE)(this, this.l); this.l += 2; return oI;
3419 case 4: case -4:
3420 if(t === 'i' || ((this[this.l+3] & 0x80)===0)) { oI = ((size > 0) ? __readInt32LE : __readInt32BE)(this, this.l); this.l += 4; return oI; }
3421 else { oR = __readUInt32LE(this, this.l); this.l += 4; } return oR;
3422 case 8: case -8:
3423 if(t === 'f') {
3424 if(size == 8) oR = __double(this, this.l);
3425 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);
3426 this.l += 8; return oR;
3427 } else size = 8;
3428 /* falls through */
3429 case 16: o = __hexlify(this, this.l, size); break;
3430 }}
3431 this.l+=size; return o;
3432}
3433
3434var __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); };
3435var __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); };
3436var __writeUInt16LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); };
3437
3438function WriteShift(t, val, f) {
3439 var size = 0, i = 0;
3440 if(f === 'dbcs') {
3441for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i);
3442 size = 2 * val.length;
3443 } else if(f === 'sbcs') {
3444 if(typeof cptable !== 'undefined' && current_ansi == 874) {
3445 /* TODO: use tables directly, don't encode */
3446for(i = 0; i != val.length; ++i) {
3447 var cppayload = cptable.utils.encode(current_ansi, val.charAt(i));
3448 this[this.l + i] = cppayload[0];
3449 }
3450 } else {
3451val = val.replace(/[^\x00-\x7F]/g, "_");
3452for(i = 0; i != val.length; ++i) this[this.l + i] = (val.charCodeAt(i) & 0xFF);
3453 }
3454 size = val.length;
3455 } else if(f === 'hex') {
3456 for(; i < t; ++i) {
3457this[this.l++] = (parseInt(val.slice(2*i, 2*i+2), 16)||0);
3458 } return this;
3459 } else if(f === 'utf16le') {
3460var end = Math.min(this.l + t, this.length);
3461 for(i = 0; i < Math.min(val.length, t); ++i) {
3462 var cc = val.charCodeAt(i);
3463 this[this.l++] = (cc & 0xff);
3464 this[this.l++] = (cc >> 8);
3465 }
3466 while(this.l < end) this[this.l++] = 0;
3467 return this;
3468 } else switch(t) {
3469 case 1: size = 1; this[this.l] = val&0xFF; break;
3470 case 2: size = 2; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; break;
3471 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;
3472 case 4: size = 4; __writeUInt32LE(this, val, this.l); break;
3473 case 8: size = 8; if(f === 'f') { write_double_le(this, val, this.l); break; }
3474 /* falls through */
3475 case 16: break;
3476 case -4: size = 4; __writeInt32LE(this, val, this.l); break;
3477 }
3478 this.l += size; return this;
3479}
3480
3481function CheckField(hexstr, fld) {
3482 var m = __hexlify(this,this.l,hexstr.length>>1);
3483 if(m !== hexstr) throw new Error(fld + 'Expected ' + hexstr + ' saw ' + m);
3484 this.l += hexstr.length>>1;
3485}
3486
3487function prep_blob(blob, pos) {
3488 blob.l = pos;
3489 blob.read_shift = ReadShift;
3490 blob.chk = CheckField;
3491 blob.write_shift = WriteShift;
3492}
3493
3494function parsenoop(blob, length) { blob.l += length; }
3495
3496function new_buf(sz) {
3497 var o = new_raw_buf(sz);
3498 prep_blob(o, 0);
3499 return o;
3500}
3501
3502/* [MS-XLSB] 2.1.4 Record */
3503function recordhopper(data, cb, opts) {
3504 if(!data) return;
3505 var tmpbyte, cntbyte, length;
3506 prep_blob(data, data.l || 0);
3507 var L = data.length, RT = 0, tgt = 0;
3508 while(data.l < L) {
3509 RT = data.read_shift(1);
3510 if(RT & 0x80) RT = (RT & 0x7F) + ((data.read_shift(1) & 0x7F)<<7);
3511 var R = XLSBRecordEnum[RT] || XLSBRecordEnum[0xFFFF];
3512 tmpbyte = data.read_shift(1);
3513 length = tmpbyte & 0x7F;
3514 for(cntbyte = 1; cntbyte <4 && (tmpbyte & 0x80); ++cntbyte) length += ((tmpbyte = data.read_shift(1)) & 0x7F)<<(7*cntbyte);
3515 tgt = data.l + length;
3516 var d = R.f && R.f(data, length, opts);
3517 data.l = tgt;
3518 if(cb(d, R.n, RT)) return;
3519 }
3520}
3521
3522/* control buffer usage for fixed-length buffers */
3523function buf_array() {
3524 var bufs = [], blksz = has_buf ? 256 : 2048;
3525 var newblk = function ba_newblk(sz) {
3526 var o = (new_buf(sz));
3527 prep_blob(o, 0);
3528 return o;
3529 };
3530
3531 var curbuf = newblk(blksz);
3532
3533 var endbuf = function ba_endbuf() {
3534 if(!curbuf) return;
3535 if(curbuf.length > curbuf.l) { curbuf = curbuf.slice(0, curbuf.l); curbuf.l = curbuf.length; }
3536 if(curbuf.length > 0) bufs.push(curbuf);
3537 curbuf = null;
3538 };
3539
3540 var next = function ba_next(sz) {
3541 if(curbuf && (sz < (curbuf.length - curbuf.l))) return curbuf;
3542 endbuf();
3543 return (curbuf = newblk(Math.max(sz+1, blksz)));
3544 };
3545
3546 var end = function ba_end() {
3547 endbuf();
3548 return __toBuffer([bufs]);
3549 };
3550
3551 var push = function ba_push(buf) { endbuf(); curbuf = buf; if(curbuf.l == null) curbuf.l = curbuf.length; next(blksz); };
3552
3553 return ({ next:next, push:push, end:end, _bufs:bufs });
3554}
3555
3556function write_record(ba, type, payload, length) {
3557 var t = +XLSBRE[type], l;
3558 if(isNaN(t)) return; // TODO: throw something here?
3559 if(!length) length = XLSBRecordEnum[t].p || (payload||[]).length || 0;
3560 l = 1 + (t >= 0x80 ? 1 : 0) + 1/* + length*/;
3561 if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l;
3562 var o = ba.next(l);
3563 if(t <= 0x7F) o.write_shift(1, t);
3564 else {
3565 o.write_shift(1, (t & 0x7F) + 0x80);
3566 o.write_shift(1, (t >> 7));
3567 }
3568 for(var i = 0; i != 4; ++i) {
3569 if(length >= 0x80) { o.write_shift(1, (length & 0x7F)+0x80); length >>= 7; }
3570 else { o.write_shift(1, length); break; }
3571 }
3572 if(length > 0 && is_buf(payload)) ba.push(payload);
3573}
3574/* XLS ranges enforced */
3575function shift_cell_xls(cell, tgt, opts) {
3576 var out = dup(cell);
3577 if(tgt.s) {
3578 if(out.cRel) out.c += tgt.s.c;
3579 if(out.rRel) out.r += tgt.s.r;
3580 } else {
3581 if(out.cRel) out.c += tgt.c;
3582 if(out.rRel) out.r += tgt.r;
3583 }
3584 if(!opts || opts.biff < 12) {
3585 while(out.c >= 0x100) out.c -= 0x100;
3586 while(out.r >= 0x10000) out.r -= 0x10000;
3587 }
3588 return out;
3589}
3590
3591function shift_range_xls(cell, range, opts) {
3592 var out = dup(cell);
3593 out.s = shift_cell_xls(out.s, range.s, opts);
3594 out.e = shift_cell_xls(out.e, range.s, opts);
3595 return out;
3596}
3597
3598function encode_cell_xls(c, biff) {
3599 if(c.cRel && c.c < 0) { c = dup(c); while(c.c < 0) c.c += (biff > 8) ? 0x4000 : 0x100; }
3600 if(c.rRel && c.r < 0) { c = dup(c); while(c.r < 0) c.r += (biff > 8) ? 0x100000 : ((biff > 5) ? 0x10000 : 0x4000); }
3601 var s = encode_cell(c);
3602 if(!c.cRel && c.cRel != null) s = fix_col(s);
3603 if(!c.rRel && c.rRel != null) s = fix_row(s);
3604 return s;
3605}
3606
3607function encode_range_xls(r, opts) {
3608 if(r.s.r == 0 && !r.s.rRel) {
3609 if(r.e.r == (opts.biff >= 12 ? 0xFFFFF : (opts.biff >= 8 ? 0x10000 : 0x4000)) && !r.e.rRel) {
3610 return (r.s.cRel ? "" : "$") + encode_col(r.s.c) + ":" + (r.e.cRel ? "" : "$") + encode_col(r.e.c);
3611 }
3612 }
3613 if(r.s.c == 0 && !r.s.cRel) {
3614 if(r.e.c == (opts.biff >= 12 ? 0x3FFF : 0xFF) && !r.e.cRel) {
3615 return (r.s.rRel ? "" : "$") + encode_row(r.s.r) + ":" + (r.e.rRel ? "" : "$") + encode_row(r.e.r);
3616 }
3617 }
3618 return encode_cell_xls(r.s, opts.biff) + ":" + encode_cell_xls(r.e, opts.biff);
3619}
3620var OFFCRYPTO = {};
3621
3622var make_offcrypto = function(O, _crypto) {
3623 var crypto;
3624 if(typeof _crypto !== 'undefined') crypto = _crypto;
3625 else if(typeof require !== 'undefined') {
3626 try { crypto = undefined; }
3627 catch(e) { crypto = null; }
3628 }
3629
3630 O.rc4 = function(key, data) {
3631 var S = new Array(256);
3632 var c = 0, i = 0, j = 0, t = 0;
3633 for(i = 0; i != 256; ++i) S[i] = i;
3634 for(i = 0; i != 256; ++i) {
3635 j = (j + S[i] + (key[i%key.length]).charCodeAt(0))&255;
3636 t = S[i]; S[i] = S[j]; S[j] = t;
3637 }
3638 // $FlowIgnore
3639 i = j = 0; var out = new_raw_buf(data.length);
3640 for(c = 0; c != data.length; ++c) {
3641 i = (i + 1)&255;
3642 j = (j + S[i])%256;
3643 t = S[i]; S[i] = S[j]; S[j] = t;
3644 out[c] = (data[c] ^ S[(S[i]+S[j])&255]);
3645 }
3646 return out;
3647 };
3648
3649 O.md5 = function(hex) {
3650 if(!crypto) throw new Error("Unsupported crypto");
3651 return crypto.createHash('md5').update(hex).digest('hex');
3652 };
3653};
3654/*global crypto:true */
3655make_offcrypto(OFFCRYPTO, typeof crypto !== "undefined" ? crypto : undefined);
3656
3657function decode_row(rowstr) { return parseInt(unfix_row(rowstr),10) - 1; }
3658function encode_row(row) { return "" + (row + 1); }
3659function fix_row(cstr) { return cstr.replace(/([A-Z]|^)(\d+)$/,"$1$$$2"); }
3660function unfix_row(cstr) { return cstr.replace(/\$(\d+)$/,"$1"); }
3661
3662function 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; }
3663function 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; }
3664function fix_col(cstr) { return cstr.replace(/^([A-Z])/,"$$$1"); }
3665function unfix_col(cstr) { return cstr.replace(/^\$([A-Z])/,"$1"); }
3666
3667function split_cell(cstr) { return cstr.replace(/(\$?[A-Z]*)(\$?\d*)/,"$1,$2").split(","); }
3668//function decode_cell(cstr) { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; }
3669function decode_cell(cstr) {
3670 var R = 0, C = 0;
3671 for(var i = 0; i < cstr.length; ++i) {
3672 var cc = cstr.charCodeAt(i);
3673 if(cc >= 48 && cc <= 57) R = 10 * R + (cc - 48);
3674 else if(cc >= 65 && cc <= 90) C = 26 * C + (cc - 64);
3675 }
3676 return { c: C - 1, r:R - 1 };
3677}
3678//function encode_cell(cell) { return encode_col(cell.c) + encode_row(cell.r); }
3679function encode_cell(cell) {
3680 var col = cell.c + 1;
3681 var s="";
3682 for(; col; col=((col-1)/26)|0) s = String.fromCharCode(((col-1)%26) + 65) + s;
3683 return s + (cell.r + 1);
3684}
3685function decode_range(range) {
3686 var idx = range.indexOf(":");
3687 if(idx == -1) return { s: decode_cell(range), e: decode_cell(range) };
3688 return { s: decode_cell(range.slice(0, idx)), e: decode_cell(range.slice(idx + 1)) };
3689}
3690function encode_range(cs,ce) {
3691 if(typeof ce === 'undefined' || typeof ce === 'number') {
3692return encode_range(cs.s, cs.e);
3693 }
3694if(typeof cs !== 'string') cs = encode_cell((cs));
3695 if(typeof ce !== 'string') ce = encode_cell((ce));
3696return cs == ce ? cs : cs + ":" + ce;
3697}
3698
3699function safe_decode_range(range) {
3700 var o = {s:{c:0,r:0},e:{c:0,r:0}};
3701 var idx = 0, i = 0, cc = 0;
3702 var len = range.length;
3703 for(idx = 0; i < len; ++i) {
3704 if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
3705 idx = 26*idx + cc;
3706 }
3707 o.s.c = --idx;
3708
3709 for(idx = 0; i < len; ++i) {
3710 if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
3711 idx = 10*idx + cc;
3712 }
3713 o.s.r = --idx;
3714
3715 if(i === len || range.charCodeAt(++i) === 58) { o.e.c=o.s.c; o.e.r=o.s.r; return o; }
3716
3717 for(idx = 0; i != len; ++i) {
3718 if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
3719 idx = 26*idx + cc;
3720 }
3721 o.e.c = --idx;
3722
3723 for(idx = 0; i != len; ++i) {
3724 if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
3725 idx = 10*idx + cc;
3726 }
3727 o.e.r = --idx;
3728 return o;
3729}
3730
3731function safe_format_cell(cell, v) {
3732 var q = (cell.t == 'd' && v instanceof Date);
3733 if(cell.z != null) try { return (cell.w = SSF.format(cell.z, q ? datenum(v) : v)); } catch(e) { }
3734 try { return (cell.w = SSF.format((cell.XF||{}).numFmtId||(q ? 14 : 0), q ? datenum(v) : v)); } catch(e) { return ''+v; }
3735}
3736
3737function format_cell(cell, v, o) {
3738 if(cell == null || cell.t == null || cell.t == 'z') return "";
3739 if(cell.w !== undefined) return cell.w;
3740 if(cell.t == 'd' && !cell.z && o && o.dateNF) cell.z = o.dateNF;
3741 if(cell.t == "e") return BErr[cell.v] || cell.v;
3742 if(v == undefined) return safe_format_cell(cell, cell.v);
3743 return safe_format_cell(cell, v);
3744}
3745
3746function sheet_to_workbook(sheet, opts) {
3747 var n = opts && opts.sheet ? opts.sheet : "Sheet1";
3748 var sheets = {}; sheets[n] = sheet;
3749 return { SheetNames: [n], Sheets: sheets };
3750}
3751
3752function sheet_add_aoa(_ws, data, opts) {
3753 var o = opts || {};
3754 var dense = _ws ? Array.isArray(_ws) : o.dense;
3755 if(DENSE != null && dense == null) dense = DENSE;
3756 var ws = _ws || (dense ? ([]) : ({}));
3757 var _R = 0, _C = 0;
3758 if(ws && o.origin != null) {
3759 if(typeof o.origin == 'number') _R = o.origin;
3760 else {
3761 var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
3762 _R = _origin.r; _C = _origin.c;
3763 }
3764 if(!ws["!ref"]) ws["!ref"] = "A1:A1";
3765 }
3766 var range = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}});
3767 if(ws['!ref']) {
3768 var _range = safe_decode_range(ws['!ref']);
3769 range.s.c = _range.s.c;
3770 range.s.r = _range.s.r;
3771 range.e.c = Math.max(range.e.c, _range.e.c);
3772 range.e.r = Math.max(range.e.r, _range.e.r);
3773 if(_R == -1) range.e.r = _R = _range.e.r + 1;
3774 }
3775 for(var R = 0; R != data.length; ++R) {
3776 if(!data[R]) continue;
3777 if(!Array.isArray(data[R])) throw new Error("aoa_to_sheet expects an array of arrays");
3778 for(var C = 0; C != data[R].length; ++C) {
3779 if(typeof data[R][C] === 'undefined') continue;
3780 var cell = ({v: data[R][C] });
3781 var __R = _R + R, __C = _C + C;
3782 if(range.s.r > __R) range.s.r = __R;
3783 if(range.s.c > __C) range.s.c = __C;
3784 if(range.e.r < __R) range.e.r = __R;
3785 if(range.e.c < __C) range.e.c = __C;
3786 if(data[R][C] && typeof data[R][C] === 'object' && !Array.isArray(data[R][C]) && !(data[R][C] instanceof Date)) cell = data[R][C];
3787 else {
3788 if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
3789 if(cell.v === null) {
3790 if(cell.f) cell.t = 'n';
3791 else if(o.nullError) { cell.t = 'e'; cell.v = 0; }
3792 else if(!o.sheetStubs) continue;
3793 else cell.t = 'z';
3794 }
3795 else if(typeof cell.v === 'number') cell.t = 'n';
3796 else if(typeof cell.v === 'boolean') cell.t = 'b';
3797 else if(cell.v instanceof Date) {
3798 cell.z = o.dateNF || SSF._table[14];
3799 if(o.cellDates) { cell.t = 'd'; cell.w = SSF.format(cell.z, datenum(cell.v)); }
3800 else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); }
3801 }
3802 else cell.t = 's';
3803 }
3804 if(dense) {
3805 if(!ws[__R]) ws[__R] = [];
3806 if(ws[__R][__C] && ws[__R][__C].z) cell.z = ws[__R][__C].z;
3807 ws[__R][__C] = cell;
3808 } else {
3809 var cell_ref = encode_cell(({c:__C,r:__R}));
3810 if(ws[cell_ref] && ws[cell_ref].z) cell.z = ws[cell_ref].z;
3811 ws[cell_ref] = cell;
3812 }
3813 }
3814 }
3815 if(range.s.c < 10000000) ws['!ref'] = encode_range(range);
3816 return ws;
3817}
3818function aoa_to_sheet(data, opts) { return sheet_add_aoa(null, data, opts); }
3819
3820function write_UInt32LE(x, o) {
3821 if (!o) o = new_buf(4);
3822 o.write_shift(4, x);
3823 return o;
3824}
3825
3826/* [MS-XLSB] 2.5.168 */
3827function parse_XLWideString(data) {
3828 var cchCharacters = data.read_shift(4);
3829 return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, 'dbcs');
3830}
3831function write_XLWideString(data, o) {
3832 var _null = false; if (o == null) { _null = true; o = new_buf(4 + 2 * data.length); }
3833 o.write_shift(4, data.length);
3834 if (data.length > 0) o.write_shift(0, data, 'dbcs');
3835 return _null ? o.slice(0, o.l) : o;
3836}
3837
3838/* [MS-XLSB] 2.5.91 */
3839//function parse_LPWideString(data) {
3840// var cchCharacters = data.read_shift(2);
3841// return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, "utf16le");
3842//}
3843
3844/* [MS-XLSB] 2.5.143 */
3845function parse_StrRun(data) {
3846 return { ich: data.read_shift(2), ifnt: data.read_shift(2) };
3847}
3848function write_StrRun(run, o) {
3849 if (!o) o = new_buf(4);
3850 o.write_shift(2, run.ich || 0);
3851 o.write_shift(2, run.ifnt || 0);
3852 return o;
3853}
3854
3855/* [MS-XLSB] 2.5.121 */
3856function parse_RichStr(data, length) {
3857 var start = data.l;
3858 var flags = data.read_shift(1);
3859 var str = parse_XLWideString(data);
3860 var rgsStrRun = [];
3861 var z = ({ t: str, h: str });
3862 if ((flags & 1) !== 0) { /* fRichStr */
3863 /* TODO: formatted string */
3864 var dwSizeStrRun = data.read_shift(4);
3865 for (var i = 0; i != dwSizeStrRun; ++i) rgsStrRun.push(parse_StrRun(data));
3866 z.r = rgsStrRun;
3867 }
3868 else z.r = [{ ich: 0, ifnt: 0 }];
3869 //if((flags & 2) !== 0) { /* fExtStr */
3870 // /* TODO: phonetic string */
3871 //}
3872 data.l = start + length;
3873 return z;
3874}
3875function write_RichStr(str, o) {
3876 /* TODO: formatted string */
3877 var _null = false; if (o == null) { _null = true; o = new_buf(15 + 4 * str.t.length); }
3878 o.write_shift(1, 0);
3879 write_XLWideString(str.t, o);
3880 return _null ? o.slice(0, o.l) : o;
3881}
3882/* [MS-XLSB] 2.4.328 BrtCommentText (RichStr w/1 run) */
3883var parse_BrtCommentText = parse_RichStr;
3884function write_BrtCommentText(str, o) {
3885 /* TODO: formatted string */
3886 var _null = false; if (o == null) { _null = true; o = new_buf(23 + 4 * str.t.length); }
3887 o.write_shift(1, 1);
3888 write_XLWideString(str.t, o);
3889 o.write_shift(4, 1);
3890 write_StrRun({ ich: 0, ifnt: 0 }, o);
3891 return _null ? o.slice(0, o.l) : o;
3892}
3893
3894/* [MS-XLSB] 2.5.9 */
3895function parse_XLSBCell(data) {
3896 var col = data.read_shift(4);
3897 var iStyleRef = data.read_shift(2);
3898 iStyleRef += data.read_shift(1) << 16;
3899 data.l++; //var fPhShow = data.read_shift(1);
3900 return { c: col, iStyleRef: iStyleRef };
3901}
3902function write_XLSBCell(cell, o) {
3903 if (o == null) o = new_buf(8);
3904 o.write_shift(-4, cell.c);
3905 o.write_shift(3, cell.iStyleRef || cell.s);
3906 o.write_shift(1, 0); /* fPhShow */
3907 return o;
3908}
3909
3910/* Short XLSB Cell does not include column */
3911function parse_XLSBShortCell(data) {
3912 var iStyleRef = data.read_shift(2);
3913 iStyleRef += data.read_shift(1) <<16;
3914 data.l++; //var fPhShow = data.read_shift(1);
3915 return { c:-1, iStyleRef: iStyleRef };
3916}
3917function write_XLSBShortCell(cell, o) {
3918 if(o == null) o = new_buf(4);
3919 o.write_shift(3, cell.iStyleRef || cell.s);
3920 o.write_shift(1, 0); /* fPhShow */
3921 return o;
3922}
3923
3924/* [MS-XLSB] 2.5.21 */
3925var parse_XLSBCodeName = parse_XLWideString;
3926var write_XLSBCodeName = write_XLWideString;
3927
3928/* [MS-XLSB] 2.5.166 */
3929function parse_XLNullableWideString(data) {
3930 var cchCharacters = data.read_shift(4);
3931 return cchCharacters === 0 || cchCharacters === 0xFFFFFFFF ? "" : data.read_shift(cchCharacters, 'dbcs');
3932}
3933function write_XLNullableWideString(data, o) {
3934 var _null = false; if (o == null) { _null = true; o = new_buf(127); }
3935 o.write_shift(4, data.length > 0 ? data.length : 0xFFFFFFFF);
3936 if (data.length > 0) o.write_shift(0, data, 'dbcs');
3937 return _null ? o.slice(0, o.l) : o;
3938}
3939
3940/* [MS-XLSB] 2.5.165 */
3941var parse_XLNameWideString = parse_XLWideString;
3942//var write_XLNameWideString = write_XLWideString;
3943
3944/* [MS-XLSB] 2.5.114 */
3945var parse_RelID = parse_XLNullableWideString;
3946var write_RelID = write_XLNullableWideString;
3947
3948
3949/* [MS-XLS] 2.5.217 ; [MS-XLSB] 2.5.122 */
3950function parse_RkNumber(data) {
3951 var b = data.slice(data.l, data.l + 4);
3952 var fX100 = (b[0] & 1), fInt = (b[0] & 2);
3953 data.l += 4;
3954 b[0] &= 0xFC; // b[0] &= ~3;
3955 var RK = fInt === 0 ? __double([0, 0, 0, 0, b[0], b[1], b[2], b[3]], 0) : __readInt32LE(b, 0) >> 2;
3956 return fX100 ? (RK / 100) : RK;
3957}
3958function write_RkNumber(data, o) {
3959 if (o == null) o = new_buf(4);
3960 var fX100 = 0, fInt = 0, d100 = data * 100;
3961 if ((data == (data | 0)) && (data >= -(1 << 29)) && (data < (1 << 29))) { fInt = 1; }
3962 else if ((d100 == (d100 | 0)) && (d100 >= -(1 << 29)) && (d100 < (1 << 29))) { fInt = 1; fX100 = 1; }
3963 if (fInt) o.write_shift(-4, ((fX100 ? d100 : data) << 2) + (fX100 + 2));
3964 else throw new Error("unsupported RkNumber " + data); // TODO
3965}
3966
3967
3968/* [MS-XLSB] 2.5.117 RfX */
3969function parse_RfX(data ) {
3970 var cell = ({ s: {}, e: {} });
3971 cell.s.r = data.read_shift(4);
3972 cell.e.r = data.read_shift(4);
3973 cell.s.c = data.read_shift(4);
3974 cell.e.c = data.read_shift(4);
3975 return cell;
3976}
3977function write_RfX(r, o) {
3978 if (!o) o = new_buf(16);
3979 o.write_shift(4, r.s.r);
3980 o.write_shift(4, r.e.r);
3981 o.write_shift(4, r.s.c);
3982 o.write_shift(4, r.e.c);
3983 return o;
3984}
3985
3986/* [MS-XLSB] 2.5.153 UncheckedRfX */
3987var parse_UncheckedRfX = parse_RfX;
3988var write_UncheckedRfX = write_RfX;
3989
3990/* [MS-XLSB] 2.5.155 UncheckedSqRfX */
3991//function parse_UncheckedSqRfX(data) {
3992// var cnt = data.read_shift(4);
3993// var out = [];
3994// for(var i = 0; i < cnt; ++i) {
3995// var rng = parse_UncheckedRfX(data);
3996// out.push(encode_range(rng));
3997// }
3998// return out.join(",");
3999//}
4000//function write_UncheckedSqRfX(sqrfx) {
4001// var parts = sqrfx.split(/\s*,\s*/);
4002// var o = new_buf(4); o.write_shift(4, parts.length);
4003// var out = [o];
4004// parts.forEach(function(rng) {
4005// out.push(write_UncheckedRfX(safe_decode_range(rng)));
4006// });
4007// return bconcat(out);
4008//}
4009
4010/* [MS-XLS] 2.5.342 ; [MS-XLSB] 2.5.171 */
4011/* TODO: error checking, NaN and Infinity values are not valid Xnum */
4012function parse_Xnum(data) {
4013 if(data.length - data.l < 8) throw "XLS Xnum Buffer underflow";
4014 return data.read_shift(8, 'f');
4015}
4016function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); }
4017
4018/* [MS-XLSB] 2.4.324 BrtColor */
4019function parse_BrtColor(data) {
4020 var out = {};
4021 var d = data.read_shift(1);
4022
4023 //var fValidRGB = d & 1;
4024 var xColorType = d >>> 1;
4025
4026 var index = data.read_shift(1);
4027 var nTS = data.read_shift(2, 'i');
4028 var bR = data.read_shift(1);
4029 var bG = data.read_shift(1);
4030 var bB = data.read_shift(1);
4031 data.l++; //var bAlpha = data.read_shift(1);
4032
4033 switch (xColorType) {
4034 case 0: out.auto = 1; break;
4035 case 1:
4036 out.index = index;
4037 var icv = XLSIcv[index];
4038 /* automatic pseudo index 81 */
4039 if (icv) out.rgb = rgb2Hex(icv);
4040 break;
4041 case 2:
4042 /* if(!fValidRGB) throw new Error("invalid"); */
4043 out.rgb = rgb2Hex([bR, bG, bB]);
4044 break;
4045 case 3: out.theme = index; break;
4046 }
4047 if (nTS != 0) out.tint = nTS > 0 ? nTS / 32767 : nTS / 32768;
4048
4049 return out;
4050}
4051function write_BrtColor(color, o) {
4052 if (!o) o = new_buf(8);
4053 if (!color || color.auto) { o.write_shift(4, 0); o.write_shift(4, 0); return o; }
4054 if (color.index != null) {
4055 o.write_shift(1, 0x02);
4056 o.write_shift(1, color.index);
4057 } else if (color.theme != null) {
4058 o.write_shift(1, 0x06);
4059 o.write_shift(1, color.theme);
4060 } else {
4061 o.write_shift(1, 0x05);
4062 o.write_shift(1, 0);
4063 }
4064 var nTS = color.tint || 0;
4065 if (nTS > 0) nTS *= 32767;
4066 else if (nTS < 0) nTS *= 32768;
4067 o.write_shift(2, nTS);
4068 if (!color.rgb || color.theme != null) {
4069 o.write_shift(2, 0);
4070 o.write_shift(1, 0);
4071 o.write_shift(1, 0);
4072 } else {
4073 var rgb = (color.rgb || 'FFFFFF');
4074 if (typeof rgb == 'number') rgb = ("000000" + rgb.toString(16)).slice(-6);
4075 o.write_shift(1, parseInt(rgb.slice(0, 2), 16));
4076 o.write_shift(1, parseInt(rgb.slice(2, 4), 16));
4077 o.write_shift(1, parseInt(rgb.slice(4, 6), 16));
4078 o.write_shift(1, 0xFF);
4079 }
4080 return o;
4081}
4082
4083/* [MS-XLSB] 2.5.52 */
4084function parse_FontFlags(data) {
4085 var d = data.read_shift(1);
4086 data.l++;
4087 var out = {
4088 fBold: d & 0x01,
4089 fItalic: d & 0x02,
4090 fUnderline: d & 0x04,
4091 fStrikeout: d & 0x08,
4092 fOutline: d & 0x10,
4093 fShadow: d & 0x20,
4094 fCondense: d & 0x40,
4095 fExtend: d & 0x80
4096 };
4097 return out;
4098}
4099function write_FontFlags(font, o) {
4100 if (!o) o = new_buf(2);
4101 var grbit =
4102 (font.italic ? 0x02 : 0) |
4103 (font.strike ? 0x08 : 0) |
4104 (font.outline ? 0x10 : 0) |
4105 (font.shadow ? 0x20 : 0) |
4106 (font.condense ? 0x40 : 0) |
4107 (font.extend ? 0x80 : 0);
4108 o.write_shift(1, grbit);
4109 o.write_shift(1, 0);
4110 return o;
4111}
4112
4113/* [MS-OLEDS] 2.3.1 and 2.3.2 */
4114function parse_ClipboardFormatOrString(o, w) {
4115 // $FlowIgnore
4116 var ClipFmt = { 2: "BITMAP", 3: "METAFILEPICT", 8: "DIB", 14: "ENHMETAFILE" };
4117 var m = o.read_shift(4);
4118 switch (m) {
4119 case 0x00000000: return "";
4120 case 0xffffffff: case 0xfffffffe: return ClipFmt[o.read_shift(4)] || "";
4121 }
4122 if (m > 0x190) throw new Error("Unsupported Clipboard: " + m.toString(16));
4123 o.l -= 4;
4124 return o.read_shift(0, w == 1 ? "lpstr" : "lpwstr");
4125}
4126function parse_ClipboardFormatOrAnsiString(o) { return parse_ClipboardFormatOrString(o, 1); }
4127function parse_ClipboardFormatOrUnicodeString(o) { return parse_ClipboardFormatOrString(o, 2); }
4128
4129/* [MS-OLEPS] 2.2 PropertyType */
4130//var VT_EMPTY = 0x0000;
4131//var VT_NULL = 0x0001;
4132var VT_I2 = 0x0002;
4133var VT_I4 = 0x0003;
4134//var VT_R4 = 0x0004;
4135//var VT_R8 = 0x0005;
4136//var VT_CY = 0x0006;
4137//var VT_DATE = 0x0007;
4138//var VT_BSTR = 0x0008;
4139//var VT_ERROR = 0x000A;
4140var VT_BOOL = 0x000B;
4141var VT_VARIANT = 0x000C;
4142//var VT_DECIMAL = 0x000E;
4143//var VT_I1 = 0x0010;
4144//var VT_UI1 = 0x0011;
4145//var VT_UI2 = 0x0012;
4146var VT_UI4 = 0x0013;
4147//var VT_I8 = 0x0014;
4148//var VT_UI8 = 0x0015;
4149//var VT_INT = 0x0016;
4150//var VT_UINT = 0x0017;
4151var VT_LPSTR = 0x001E;
4152//var VT_LPWSTR = 0x001F;
4153var VT_FILETIME = 0x0040;
4154var VT_BLOB = 0x0041;
4155//var VT_STREAM = 0x0042;
4156//var VT_STORAGE = 0x0043;
4157//var VT_STREAMED_Object = 0x0044;
4158//var VT_STORED_Object = 0x0045;
4159//var VT_BLOB_Object = 0x0046;
4160var VT_CF = 0x0047;
4161//var VT_CLSID = 0x0048;
4162//var VT_VERSIONED_STREAM = 0x0049;
4163var VT_VECTOR = 0x1000;
4164//var VT_ARRAY = 0x2000;
4165
4166var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
4167var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString
4168var VT_CUSTOM = [VT_STRING, VT_USTR];
4169
4170/* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */
4171var DocSummaryPIDDSI = {
41720x01: { n: 'CodePage', t: VT_I2 },
41730x02: { n: 'Category', t: VT_STRING },
41740x03: { n: 'PresentationFormat', t: VT_STRING },
41750x04: { n: 'ByteCount', t: VT_I4 },
41760x05: { n: 'LineCount', t: VT_I4 },
41770x06: { n: 'ParagraphCount', t: VT_I4 },
41780x07: { n: 'SlideCount', t: VT_I4 },
41790x08: { n: 'NoteCount', t: VT_I4 },
41800x09: { n: 'HiddenCount', t: VT_I4 },
41810x0a: { n: 'MultimediaClipCount', t: VT_I4 },
41820x0b: { n: 'ScaleCrop', t: VT_BOOL },
41830x0c: { n: 'HeadingPairs', t: VT_VECTOR | VT_VARIANT },
41840x0d: { n: 'TitlesOfParts', t: VT_VECTOR | VT_LPSTR },
41850x0e: { n: 'Manager', t: VT_STRING },
41860x0f: { n: 'Company', t: VT_STRING },
41870x10: { n: 'LinksUpToDate', t: VT_BOOL },
41880x11: { n: 'CharacterCount', t: VT_I4 },
41890x13: { n: 'SharedDoc', t: VT_BOOL },
41900x16: { n: 'HyperlinksChanged', t: VT_BOOL },
41910x17: { n: 'AppVersion', t: VT_I4, p: 'version' },
41920x18: { n: 'DigSig', t: VT_BLOB },
41930x1A: { n: 'ContentType', t: VT_STRING },
41940x1B: { n: 'ContentStatus', t: VT_STRING },
41950x1C: { n: 'Language', t: VT_STRING },
41960x1D: { n: 'Version', t: VT_STRING },
41970xFF: {},
4198 /* [MS-OLEPS] 2.18 */
41990x80000000: { n: 'Locale', t: VT_UI4 },
42000x80000003: { n: 'Behavior', t: VT_UI4 },
42010x72627262: {}
4202};
4203
4204/* [MS-OSHARED] 2.3.3.2.1.1 Summary Information Property Set PIDSI */
4205var SummaryPIDSI = {
42060x01: { n: 'CodePage', t: VT_I2 },
42070x02: { n: 'Title', t: VT_STRING },
42080x03: { n: 'Subject', t: VT_STRING },
42090x04: { n: 'Author', t: VT_STRING },
42100x05: { n: 'Keywords', t: VT_STRING },
42110x06: { n: 'Comments', t: VT_STRING },
42120x07: { n: 'Template', t: VT_STRING },
42130x08: { n: 'LastAuthor', t: VT_STRING },
42140x09: { n: 'RevNumber', t: VT_STRING },
42150x0A: { n: 'EditTime', t: VT_FILETIME },
42160x0B: { n: 'LastPrinted', t: VT_FILETIME },
42170x0C: { n: 'CreatedDate', t: VT_FILETIME },
42180x0D: { n: 'ModifiedDate', t: VT_FILETIME },
42190x0E: { n: 'PageCount', t: VT_I4 },
42200x0F: { n: 'WordCount', t: VT_I4 },
42210x10: { n: 'CharCount', t: VT_I4 },
42220x11: { n: 'Thumbnail', t: VT_CF },
42230x12: { n: 'Application', t: VT_STRING },
42240x13: { n: 'DocSecurity', t: VT_I4 },
42250xFF: {},
4226 /* [MS-OLEPS] 2.18 */
42270x80000000: { n: 'Locale', t: VT_UI4 },
42280x80000003: { n: 'Behavior', t: VT_UI4 },
42290x72627262: {}
4230};
4231
4232var DocSummaryRE = evert_key(DocSummaryPIDDSI, "n");
4233var SummaryRE = evert_key(SummaryPIDSI, "n");
4234
4235/* [MS-XLS] 2.4.63 Country/Region codes */
4236var CountryEnum = {
42370x0001: "US", // United States
42380x0002: "CA", // Canada
42390x0003: "", // Latin America (except Brazil)
42400x0007: "RU", // Russia
42410x0014: "EG", // Egypt
42420x001E: "GR", // Greece
42430x001F: "NL", // Netherlands
42440x0020: "BE", // Belgium
42450x0021: "FR", // France
42460x0022: "ES", // Spain
42470x0024: "HU", // Hungary
42480x0027: "IT", // Italy
42490x0029: "CH", // Switzerland
42500x002B: "AT", // Austria
42510x002C: "GB", // United Kingdom
42520x002D: "DK", // Denmark
42530x002E: "SE", // Sweden
42540x002F: "NO", // Norway
42550x0030: "PL", // Poland
42560x0031: "DE", // Germany
42570x0034: "MX", // Mexico
42580x0037: "BR", // Brazil
42590x003d: "AU", // Australia
42600x0040: "NZ", // New Zealand
42610x0042: "TH", // Thailand
42620x0051: "JP", // Japan
42630x0052: "KR", // Korea
42640x0054: "VN", // Viet Nam
42650x0056: "CN", // China
42660x005A: "TR", // Turkey
42670x0069: "JS", // Ramastan
42680x00D5: "DZ", // Algeria
42690x00D8: "MA", // Morocco
42700x00DA: "LY", // Libya
42710x015F: "PT", // Portugal
42720x0162: "IS", // Iceland
42730x0166: "FI", // Finland
42740x01A4: "CZ", // Czech Republic
42750x0376: "TW", // Taiwan
42760x03C1: "LB", // Lebanon
42770x03C2: "JO", // Jordan
42780x03C3: "SY", // Syria
42790x03C4: "IQ", // Iraq
42800x03C5: "KW", // Kuwait
42810x03C6: "SA", // Saudi Arabia
42820x03CB: "AE", // United Arab Emirates
42830x03CC: "IL", // Israel
42840x03CE: "QA", // Qatar
42850x03D5: "IR", // Iran
42860xFFFF: "US" // United States
4287};
4288
4289/* [MS-XLS] 2.5.127 */
4290var XLSFillPattern = [
4291 null,
4292 'solid',
4293 'mediumGray',
4294 'darkGray',
4295 'lightGray',
4296 'darkHorizontal',
4297 'darkVertical',
4298 'darkDown',
4299 'darkUp',
4300 'darkGrid',
4301 'darkTrellis',
4302 'lightHorizontal',
4303 'lightVertical',
4304 'lightDown',
4305 'lightUp',
4306 'lightGrid',
4307 'lightTrellis',
4308 'gray125',
4309 'gray0625'
4310];
4311
4312function rgbify(arr) { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); }
4313
4314/* [MS-XLS] 2.5.161 */
4315/* [MS-XLSB] 2.5.75 Icv */
4316var _XLSIcv = rgbify([
4317 /* Color Constants */
4318 0x000000,
4319 0xFFFFFF,
4320 0xFF0000,
4321 0x00FF00,
4322 0x0000FF,
4323 0xFFFF00,
4324 0xFF00FF,
4325 0x00FFFF,
4326
4327 /* Overridable Defaults */
4328 0x000000,
4329 0xFFFFFF,
4330 0xFF0000,
4331 0x00FF00,
4332 0x0000FF,
4333 0xFFFF00,
4334 0xFF00FF,
4335 0x00FFFF,
4336
4337 0x800000,
4338 0x008000,
4339 0x000080,
4340 0x808000,
4341 0x800080,
4342 0x008080,
4343 0xC0C0C0,
4344 0x808080,
4345 0x9999FF,
4346 0x993366,
4347 0xFFFFCC,
4348 0xCCFFFF,
4349 0x660066,
4350 0xFF8080,
4351 0x0066CC,
4352 0xCCCCFF,
4353
4354 0x000080,
4355 0xFF00FF,
4356 0xFFFF00,
4357 0x00FFFF,
4358 0x800080,
4359 0x800000,
4360 0x008080,
4361 0x0000FF,
4362 0x00CCFF,
4363 0xCCFFFF,
4364 0xCCFFCC,
4365 0xFFFF99,
4366 0x99CCFF,
4367 0xFF99CC,
4368 0xCC99FF,
4369 0xFFCC99,
4370
4371 0x3366FF,
4372 0x33CCCC,
4373 0x99CC00,
4374 0xFFCC00,
4375 0xFF9900,
4376 0xFF6600,
4377 0x666699,
4378 0x969696,
4379 0x003366,
4380 0x339966,
4381 0x003300,
4382 0x333300,
4383 0x993300,
4384 0x993366,
4385 0x333399,
4386 0x333333,
4387
4388 /* Other entries to appease BIFF8/12 */
4389 0xFFFFFF, /* 0x40 icvForeground ?? */
4390 0x000000, /* 0x41 icvBackground ?? */
4391 0x000000, /* 0x42 icvFrame ?? */
4392 0x000000, /* 0x43 icv3D ?? */
4393 0x000000, /* 0x44 icv3DText ?? */
4394 0x000000, /* 0x45 icv3DHilite ?? */
4395 0x000000, /* 0x46 icv3DShadow ?? */
4396 0x000000, /* 0x47 icvHilite ?? */
4397 0x000000, /* 0x48 icvCtlText ?? */
4398 0x000000, /* 0x49 icvCtlScrl ?? */
4399 0x000000, /* 0x4A icvCtlInv ?? */
4400 0x000000, /* 0x4B icvCtlBody ?? */
4401 0x000000, /* 0x4C icvCtlFrame ?? */
4402 0x000000, /* 0x4D icvCtlFore ?? */
4403 0x000000, /* 0x4E icvCtlBack ?? */
4404 0x000000, /* 0x4F icvCtlNeutral */
4405 0x000000, /* 0x50 icvInfoBk ?? */
4406 0x000000 /* 0x51 icvInfoText ?? */
4407]);
4408var XLSIcv = dup(_XLSIcv);
4409
4410/* [MS-XLSB] 2.5.97.2 */
4411var BErr = {
44120x00: "#NULL!",
44130x07: "#DIV/0!",
44140x0F: "#VALUE!",
44150x17: "#REF!",
44160x1D: "#NAME?",
44170x24: "#NUM!",
44180x2A: "#N/A",
44190x2B: "#GETTING_DATA",
44200xFF: "#WTF?"
4421};
4422var RBErr = evert_num(BErr);
4423/* Parts enumerated in OPC spec, MS-XLSB and MS-XLSX */
4424/* 12.3 Part Summary <SpreadsheetML> */
4425/* 14.2 Part Summary <DrawingML> */
4426/* [MS-XLSX] 2.1 Part Enumerations ; [MS-XLSB] 2.1.7 Part Enumeration */
4427var ct2type/*{[string]:string}*/ = ({
4428 /* Workbook */
4429 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": "workbooks",
4430
4431 /* Worksheet */
4432 "application/vnd.ms-excel.binIndexWs": "TODO", /* Binary Index */
4433
4434 /* Macrosheet */
4435 "application/vnd.ms-excel.intlmacrosheet": "TODO",
4436 "application/vnd.ms-excel.binIndexMs": "TODO", /* Binary Index */
4437
4438 /* File Properties */
4439 "application/vnd.openxmlformats-package.core-properties+xml": "coreprops",
4440 "application/vnd.openxmlformats-officedocument.custom-properties+xml": "custprops",
4441 "application/vnd.openxmlformats-officedocument.extended-properties+xml": "extprops",
4442
4443 /* Custom Data Properties */
4444 "application/vnd.openxmlformats-officedocument.customXmlProperties+xml": "TODO",
4445 "application/vnd.openxmlformats-officedocument.spreadsheetml.customProperty": "TODO",
4446
4447 /* PivotTable */
4448 "application/vnd.ms-excel.pivotTable": "TODO",
4449 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml": "TODO",
4450
4451 /* Chart Objects */
4452 "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": "TODO",
4453
4454 /* Chart Colors */
4455 "application/vnd.ms-office.chartcolorstyle+xml": "TODO",
4456
4457 /* Chart Style */
4458 "application/vnd.ms-office.chartstyle+xml": "TODO",
4459
4460 /* Chart Advanced */
4461 "application/vnd.ms-office.chartex+xml": "TODO",
4462
4463 /* Calculation Chain */
4464 "application/vnd.ms-excel.calcChain": "calcchains",
4465 "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains",
4466
4467 /* Printer Settings */
4468 "application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings": "TODO",
4469
4470 /* ActiveX */
4471 "application/vnd.ms-office.activeX": "TODO",
4472 "application/vnd.ms-office.activeX+xml": "TODO",
4473
4474 /* Custom Toolbars */
4475 "application/vnd.ms-excel.attachedToolbars": "TODO",
4476
4477 /* External Data Connections */
4478 "application/vnd.ms-excel.connections": "TODO",
4479 "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml": "TODO",
4480
4481 /* External Links */
4482 "application/vnd.ms-excel.externalLink": "links",
4483 "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml": "links",
4484
4485 /* Metadata */
4486 "application/vnd.ms-excel.sheetMetadata": "TODO",
4487 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml": "TODO",
4488
4489 /* PivotCache */
4490 "application/vnd.ms-excel.pivotCacheDefinition": "TODO",
4491 "application/vnd.ms-excel.pivotCacheRecords": "TODO",
4492 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml": "TODO",
4493 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml": "TODO",
4494
4495 /* Query Table */
4496 "application/vnd.ms-excel.queryTable": "TODO",
4497 "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml": "TODO",
4498
4499 /* Shared Workbook */
4500 "application/vnd.ms-excel.userNames": "TODO",
4501 "application/vnd.ms-excel.revisionHeaders": "TODO",
4502 "application/vnd.ms-excel.revisionLog": "TODO",
4503 "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml": "TODO",
4504 "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml": "TODO",
4505 "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml": "TODO",
4506
4507 /* Single Cell Table */
4508 "application/vnd.ms-excel.tableSingleCells": "TODO",
4509 "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml": "TODO",
4510
4511 /* Slicer */
4512 "application/vnd.ms-excel.slicer": "TODO",
4513 "application/vnd.ms-excel.slicerCache": "TODO",
4514 "application/vnd.ms-excel.slicer+xml": "TODO",
4515 "application/vnd.ms-excel.slicerCache+xml": "TODO",
4516
4517 /* Sort Map */
4518 "application/vnd.ms-excel.wsSortMap": "TODO",
4519
4520 /* Table */
4521 "application/vnd.ms-excel.table": "TODO",
4522 "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml": "TODO",
4523
4524 /* Themes */
4525 "application/vnd.openxmlformats-officedocument.theme+xml": "themes",
4526
4527 /* Theme Override */
4528 "application/vnd.openxmlformats-officedocument.themeOverride+xml": "TODO",
4529
4530 /* Timeline */
4531 "application/vnd.ms-excel.Timeline+xml": "TODO", /* verify */
4532 "application/vnd.ms-excel.TimelineCache+xml": "TODO", /* verify */
4533
4534 /* VBA */
4535 "application/vnd.ms-office.vbaProject": "vba",
4536 "application/vnd.ms-office.vbaProjectSignature": "vba",
4537
4538 /* Volatile Dependencies */
4539 "application/vnd.ms-office.volatileDependencies": "TODO",
4540 "application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml": "TODO",
4541
4542 /* Control Properties */
4543 "application/vnd.ms-excel.controlproperties+xml": "TODO",
4544
4545 /* Data Model */
4546 "application/vnd.openxmlformats-officedocument.model+data": "TODO",
4547
4548 /* Survey */
4549 "application/vnd.ms-excel.Survey+xml": "TODO",
4550
4551 /* Drawing */
4552 "application/vnd.openxmlformats-officedocument.drawing+xml": "drawings",
4553 "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml": "TODO",
4554 "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml": "TODO",
4555 "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml": "TODO",
4556 "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml": "TODO",
4557 "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml": "TODO",
4558
4559 /* VML */
4560 "application/vnd.openxmlformats-officedocument.vmlDrawing": "TODO",
4561
4562 "application/vnd.openxmlformats-package.relationships+xml": "rels",
4563 "application/vnd.openxmlformats-officedocument.oleObject": "TODO",
4564
4565 /* Image */
4566 "image/png": "TODO",
4567
4568 "sheet": "js"
4569});
4570
4571var CT_LIST = (function(){
4572 var o = {
4573 workbooks: {
4574 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
4575 xlsm: "application/vnd.ms-excel.sheet.macroEnabled.main+xml",
4576 xlsb: "application/vnd.ms-excel.sheet.binary.macroEnabled.main",
4577 xlam: "application/vnd.ms-excel.addin.macroEnabled.main+xml",
4578 xltx: "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
4579 },
4580 strs: { /* Shared Strings */
4581 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
4582 xlsb: "application/vnd.ms-excel.sharedStrings"
4583 },
4584 comments: { /* Comments */
4585 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
4586 xlsb: "application/vnd.ms-excel.comments"
4587 },
4588 sheets: { /* Worksheet */
4589 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
4590 xlsb: "application/vnd.ms-excel.worksheet"
4591 },
4592 charts: { /* Chartsheet */
4593 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml",
4594 xlsb: "application/vnd.ms-excel.chartsheet"
4595 },
4596 dialogs: { /* Dialogsheet */
4597 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml",
4598 xlsb: "application/vnd.ms-excel.dialogsheet"
4599 },
4600 macros: { /* Macrosheet (Excel 4.0 Macros) */
4601 xlsx: "application/vnd.ms-excel.macrosheet+xml",
4602 xlsb: "application/vnd.ms-excel.macrosheet"
4603 },
4604 styles: { /* Styles */
4605 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
4606 xlsb: "application/vnd.ms-excel.styles"
4607 }
4608 };
4609 keys(o).forEach(function(k) { ["xlsm", "xlam"].forEach(function(v) { if(!o[k][v]) o[k][v] = o[k].xlsx; }); });
4610 keys(o).forEach(function(k){ keys(o[k]).forEach(function(v) { ct2type[o[k][v]] = k; }); });
4611 return o;
4612})();
4613
4614var type2ct/*{[string]:Array<string>}*/ = evert_arr(ct2type);
4615
4616XMLNS.CT = 'http://schemas.openxmlformats.org/package/2006/content-types';
4617
4618function new_ct() {
4619 return ({
4620 workbooks:[], sheets:[], charts:[], dialogs:[], macros:[],
4621 rels:[], strs:[], comments:[], links:[],
4622 coreprops:[], extprops:[], custprops:[], themes:[], styles:[],
4623 calcchains:[], vba: [], drawings: [],
4624 TODO:[], xmlns: "" });
4625}
4626
4627function parse_ct(data) {
4628 var ct = new_ct();
4629 if(!data || !data.match) return ct;
4630 var ctext = {};
4631 (data.match(tagregex)||[]).forEach(function(x) {
4632 var y = parsexmltag(x);
4633 switch(y[0].replace(nsregex,"<")) {
4634 case '<?xml': break;
4635 case '<Types': ct.xmlns = y['xmlns' + (y[0].match(/<(\w+):/)||["",""])[1] ]; break;
4636 case '<Default': ctext[y.Extension] = y.ContentType; break;
4637 case '<Override':
4638 if(ct[ct2type[y.ContentType]] !== undefined) ct[ct2type[y.ContentType]].push(y.PartName);
4639 break;
4640 }
4641 });
4642 if(ct.xmlns !== XMLNS.CT) throw new Error("Unknown Namespace: " + ct.xmlns);
4643 ct.calcchain = ct.calcchains.length > 0 ? ct.calcchains[0] : "";
4644 ct.sst = ct.strs.length > 0 ? ct.strs[0] : "";
4645 ct.style = ct.styles.length > 0 ? ct.styles[0] : "";
4646 ct.defaults = ctext;
4647 delete ct.calcchains;
4648 return ct;
4649}
4650
4651var CTYPE_XML_ROOT = writextag('Types', null, {
4652 'xmlns': XMLNS.CT,
4653 'xmlns:xsd': XMLNS.xsd,
4654 'xmlns:xsi': XMLNS.xsi
4655});
4656
4657var CTYPE_DEFAULTS = [
4658 ['xml', 'application/xml'],
4659 ['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
4660 ['vml', 'application/vnd.openxmlformats-officedocument.vmlDrawing'],
4661 ['data', 'application/vnd.openxmlformats-officedocument.model+data'],
4662 /* from test files */
4663 ['bmp', 'image/bmp'],
4664 ['png', 'image/png'],
4665 ['gif', 'image/gif'],
4666 ['emf', 'image/x-emf'],
4667 ['wmf', 'image/x-wmf'],
4668 ['jpg', 'image/jpeg'], ['jpeg', 'image/jpeg'],
4669 ['tif', 'image/tiff'], ['tiff', 'image/tiff'],
4670 ['pdf', 'application/pdf'],
4671 ['rels', type2ct.rels[0]]
4672].map(function(x) {
4673 return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
4674});
4675
4676function write_ct(ct, opts) {
4677 var o = [], v;
4678 o[o.length] = (XML_HEADER);
4679 o[o.length] = (CTYPE_XML_ROOT);
4680 o = o.concat(CTYPE_DEFAULTS);
4681
4682 /* only write first instance */
4683 var f1 = function(w) {
4684 if(ct[w] && ct[w].length > 0) {
4685 v = ct[w][0];
4686 o[o.length] = (writextag('Override', null, {
4687 'PartName': (v[0] == '/' ? "":"/") + v,
4688 'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
4689 }));
4690 }
4691 };
4692
4693 /* book type-specific */
4694 var f2 = function(w) {
4695 (ct[w]||[]).forEach(function(v) {
4696 o[o.length] = (writextag('Override', null, {
4697 'PartName': (v[0] == '/' ? "":"/") + v,
4698 'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
4699 }));
4700 });
4701 };
4702
4703 /* standard type */
4704 var f3 = function(t) {
4705 (ct[t]||[]).forEach(function(v) {
4706 o[o.length] = (writextag('Override', null, {
4707 'PartName': (v[0] == '/' ? "":"/") + v,
4708 'ContentType': type2ct[t][0]
4709 }));
4710 });
4711 };
4712
4713 f1('workbooks');
4714 f2('sheets');
4715 f2('charts');
4716 f3('themes');
4717 ['strs', 'styles'].forEach(f1);
4718 ['coreprops', 'extprops', 'custprops'].forEach(f3);
4719 f3('vba');
4720 f3('comments');
4721 f3('drawings');
4722 if(o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
4723 return o.join("");
4724}
4725/* 9.3 Relationships */
4726var RELS = ({
4727 WB: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
4728 SHEET: "http://sheetjs.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
4729 HLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
4730 VML: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing",
4731 XPATH: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath",
4732 XMISS: "http://schemas.microsoft.com/office/2006/relationships/xlExternalLinkPath/xlPathMissing",
4733 XLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLink",
4734 CXML: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml",
4735 CXMLP: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXmlProps",
4736 VBA: "http://schemas.microsoft.com/office/2006/relationships/vbaProject"
4737});
4738
4739/* 9.3.3 Representing Relationships */
4740function get_rels_path(file) {
4741 var n = file.lastIndexOf("/");
4742 return file.slice(0,n+1) + '_rels/' + file.slice(n+1) + ".rels";
4743}
4744
4745function parse_rels(data, currentFilePath) {
4746 var rels = {"!id":{}};
4747 if (!data) return rels;
4748 if (currentFilePath.charAt(0) !== '/') {
4749 currentFilePath = '/'+currentFilePath;
4750 }
4751 var hash = {};
4752
4753 (data.match(tagregex)||[]).forEach(function(x) {
4754 var y = parsexmltag(x);
4755 /* 9.3.2.2 OPC_Relationships */
4756 if (y[0] === '<Relationship') {
4757 var rel = {}; rel.Type = y.Type; rel.Target = y.Target; rel.Id = y.Id; rel.TargetMode = y.TargetMode;
4758 var canonictarget = y.TargetMode === 'External' ? y.Target : resolve_path(y.Target, currentFilePath);
4759 rels[canonictarget] = rel;
4760 hash[y.Id] = rel;
4761 }
4762 });
4763 rels["!id"] = hash;
4764 return rels;
4765}
4766
4767XMLNS.RELS = 'http://schemas.openxmlformats.org/package/2006/relationships';
4768
4769var RELS_ROOT = writextag('Relationships', null, {
4770 //'xmlns:ns0': XMLNS.RELS,
4771 'xmlns': XMLNS.RELS
4772});
4773
4774/* TODO */
4775function write_rels(rels) {
4776 var o = [XML_HEADER, RELS_ROOT];
4777 keys(rels['!id']).forEach(function(rid) {
4778 o[o.length] = (writextag('Relationship', null, rels['!id'][rid]));
4779 });
4780 if(o.length>2){ o[o.length] = ('</Relationships>'); o[1]=o[1].replace("/>",">"); }
4781 return o.join("");
4782}
4783
4784var RELS_EXTERN = [RELS.HLINK, RELS.XPATH, RELS.XMISS];
4785function add_rels(rels, rId, f, type, relobj, targetmode) {
4786 if(!relobj) relobj = {};
4787 if(!rels['!id']) rels['!id'] = {};
4788 if(rId < 0) for(rId = 1; rels['!id']['rId' + rId]; ++rId){/* empty */}
4789 relobj.Id = 'rId' + rId;
4790 relobj.Type = type;
4791 relobj.Target = f;
4792 if(targetmode) relobj.TargetMode = targetmode;
4793 else if(RELS_EXTERN.indexOf(relobj.Type) > -1) relobj.TargetMode = "External";
4794 if(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId);
4795 rels['!id'][relobj.Id] = relobj;
4796 rels[('/' + relobj.Target).replace("//","/")] = relobj;
4797 return rId;
4798}
4799/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
4800/* Part 3 Section 4 Manifest File */
4801var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
4802function parse_manifest(d, opts) {
4803 var str = xlml_normalize(d);
4804 var Rn;
4805 var FEtag;
4806 while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
4807 case 'manifest': break; // 4.2 <manifest:manifest>
4808 case 'file-entry': // 4.3 <manifest:file-entry>
4809 FEtag = parsexmltag(Rn[0], false);
4810 if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet");
4811 break;
4812 case 'encryption-data': // 4.4 <manifest:encryption-data>
4813 case 'algorithm': // 4.5 <manifest:algorithm>
4814 case 'start-key-generation': // 4.6 <manifest:start-key-generation>
4815 case 'key-derivation': // 4.7 <manifest:key-derivation>
4816 throw new Error("Unsupported ODS Encryption");
4817 default: if(opts && opts.WTF) throw Rn;
4818 }
4819}
4820
4821function write_manifest(manifest) {
4822 var o = [XML_HEADER];
4823 o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
4824 o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
4825 for(var i = 0; i < manifest.length; ++i) o.push(' <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
4826 o.push('</manifest:manifest>');
4827 return o.join("");
4828}
4829
4830/* Part 3 Section 6 Metadata Manifest File */
4831function write_rdf_type(file, res, tag) {
4832 return [
4833 ' <rdf:Description rdf:about="' + file + '">\n',
4834 ' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
4835 ' </rdf:Description>\n'
4836 ].join("");
4837}
4838function write_rdf_has(base, file) {
4839 return [
4840 ' <rdf:Description rdf:about="' + base + '">\n',
4841 ' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
4842 ' </rdf:Description>\n'
4843 ].join("");
4844}
4845function write_rdf(rdf) {
4846 var o = [XML_HEADER];
4847 o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
4848 for(var i = 0; i != rdf.length; ++i) {
4849 o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
4850 o.push(write_rdf_has("",rdf[i][0]));
4851 }
4852 o.push(write_rdf_type("","Document", "pkg"));
4853 o.push('</rdf:RDF>');
4854 return o.join("");
4855}
4856/* TODO: pull properties */
4857var write_meta_ods = (function() {
4858 var payload = '<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
4859 return function wmo() {
4860 return payload;
4861 };
4862})();
4863
4864/* ECMA-376 Part II 11.1 Core Properties Part */
4865/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
4866var CORE_PROPS = [
4867 ["cp:category", "Category"],
4868 ["cp:contentStatus", "ContentStatus"],
4869 ["cp:keywords", "Keywords"],
4870 ["cp:lastModifiedBy", "LastAuthor"],
4871 ["cp:lastPrinted", "LastPrinted"],
4872 ["cp:revision", "RevNumber"],
4873 ["cp:version", "Version"],
4874 ["dc:creator", "Author"],
4875 ["dc:description", "Comments"],
4876 ["dc:identifier", "Identifier"],
4877 ["dc:language", "Language"],
4878 ["dc:subject", "Subject"],
4879 ["dc:title", "Title"],
4880 ["dcterms:created", "CreatedDate", 'date'],
4881 ["dcterms:modified", "ModifiedDate", 'date']
4882];
4883
4884XMLNS.CORE_PROPS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
4885RELS.CORE_PROPS = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';
4886
4887var CORE_PROPS_REGEX = (function() {
4888 var r = new Array(CORE_PROPS.length);
4889 for(var i = 0; i < CORE_PROPS.length; ++i) {
4890 var f = CORE_PROPS[i];
4891 var g = "(?:"+ f[0].slice(0,f[0].indexOf(":")) +":)"+ f[0].slice(f[0].indexOf(":")+1);
4892 r[i] = new RegExp("<" + g + "[^>]*>([\\s\\S]*?)<\/" + g + ">");
4893 }
4894 return r;
4895})();
4896
4897function parse_core_props(data) {
4898 var p = {};
4899 data = utf8read(data);
4900
4901 for(var i = 0; i < CORE_PROPS.length; ++i) {
4902 var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
4903 if(cur != null && cur.length > 0) p[f[1]] = unescapexml(cur[1]);
4904 if(f[2] === 'date' && p[f[1]]) p[f[1]] = parseDate(p[f[1]]);
4905 }
4906
4907 return p;
4908}
4909
4910var CORE_PROPS_XML_ROOT = writextag('cp:coreProperties', null, {
4911 //'xmlns': XMLNS.CORE_PROPS,
4912 'xmlns:cp': XMLNS.CORE_PROPS,
4913 'xmlns:dc': XMLNS.dc,
4914 'xmlns:dcterms': XMLNS.dcterms,
4915 'xmlns:dcmitype': XMLNS.dcmitype,
4916 'xmlns:xsi': XMLNS.xsi
4917});
4918
4919function cp_doit(f, g, h, o, p) {
4920 if(p[f] != null || g == null || g === "") return;
4921 p[f] = g;
4922 g = escapexml(g);
4923 o[o.length] = (h ? writextag(f,g,h) : writetag(f,g));
4924}
4925
4926function write_core_props(cp, _opts) {
4927 var opts = _opts || {};
4928 var o = [XML_HEADER, CORE_PROPS_XML_ROOT], p = {};
4929 if(!cp && !opts.Props) return o.join("");
4930
4931 if(cp) {
4932 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);
4933 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);
4934 }
4935
4936 for(var i = 0; i != CORE_PROPS.length; ++i) {
4937 var f = CORE_PROPS[i];
4938 var v = opts.Props && opts.Props[f[1]] != null ? opts.Props[f[1]] : cp ? cp[f[1]] : null;
4939 if(v === true) v = "1";
4940 else if(v === false) v = "0";
4941 else if(typeof v == "number") v = String(v);
4942 if(v != null) cp_doit(f[0], v, null, o, p);
4943 }
4944 if(o.length>2){ o[o.length] = ('</cp:coreProperties>'); o[1]=o[1].replace("/>",">"); }
4945 return o.join("");
4946}
4947/* 15.2.12.3 Extended File Properties Part */
4948/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
4949var EXT_PROPS = [
4950 ["Application", "Application", "string"],
4951 ["AppVersion", "AppVersion", "string"],
4952 ["Company", "Company", "string"],
4953 ["DocSecurity", "DocSecurity", "string"],
4954 ["Manager", "Manager", "string"],
4955 ["HyperlinksChanged", "HyperlinksChanged", "bool"],
4956 ["SharedDoc", "SharedDoc", "bool"],
4957 ["LinksUpToDate", "LinksUpToDate", "bool"],
4958 ["ScaleCrop", "ScaleCrop", "bool"],
4959 ["HeadingPairs", "HeadingPairs", "raw"],
4960 ["TitlesOfParts", "TitlesOfParts", "raw"]
4961];
4962
4963XMLNS.EXT_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
4964RELS.EXT_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';
4965
4966var PseudoPropsPairs = [
4967 "Worksheets", "SheetNames",
4968 "NamedRanges", "DefinedNames",
4969 "Chartsheets", "ChartNames"
4970];
4971function load_props_pairs(HP, TOP, props, opts) {
4972 var v = [];
4973 if(typeof HP == "string") v = parseVector(HP, opts);
4974 else for(var j = 0; j < HP.length; ++j) v = v.concat(HP[j].map(function(hp) { return {v:hp}; }));
4975 var parts = (typeof TOP == "string") ? parseVector(TOP, opts).map(function (x) { return x.v; }) : TOP;
4976 var idx = 0, len = 0;
4977 if(parts.length > 0) for(var i = 0; i !== v.length; i += 2) {
4978 len = +(v[i+1].v);
4979 switch(v[i].v) {
4980 case "Worksheets":
4981 case "工作表":
4982 case "Листы":
4983 case "أوراق العمل":
4984 case "ワークシート":
4985 case "גליונות עבודה":
4986 case "Arbeitsblätter":
4987 case "Çalışma Sayfaları":
4988 case "Feuilles de calcul":
4989 case "Fogli di lavoro":
4990 case "Folhas de cálculo":
4991 case "Planilhas":
4992 case "Regneark":
4993 case "Hojas de cálculo":
4994 case "Werkbladen":
4995 props.Worksheets = len;
4996 props.SheetNames = parts.slice(idx, idx + len);
4997 break;
4998
4999 case "Named Ranges":
5000 case "Rangos con nombre":
5001 case "名前付き一覧":
5002 case "Benannte Bereiche":
5003 case "Navngivne områder":
5004 props.NamedRanges = len;
5005 props.DefinedNames = parts.slice(idx, idx + len);
5006 break;
5007
5008 case "Charts":
5009 case "Diagramme":
5010 props.Chartsheets = len;
5011 props.ChartNames = parts.slice(idx, idx + len);
5012 break;
5013 }
5014 idx += len;
5015 }
5016}
5017
5018function parse_ext_props(data, p, opts) {
5019 var q = {}; if(!p) p = {};
5020 data = utf8read(data);
5021
5022 EXT_PROPS.forEach(function(f) {
5023 var xml = (data.match(matchtag(f[0]))||[])[1];
5024 switch(f[2]) {
5025 case "string": if(xml) p[f[1]] = unescapexml(xml); break;
5026 case "bool": p[f[1]] = xml === "true"; break;
5027 case "raw":
5028 var cur = data.match(new RegExp("<" + f[0] + "[^>]*>([\\s\\S]*?)<\/" + f[0] + ">"));
5029 if(cur && cur.length > 0) q[f[1]] = cur[1];
5030 break;
5031 }
5032 });
5033
5034 if(q.HeadingPairs && q.TitlesOfParts) load_props_pairs(q.HeadingPairs, q.TitlesOfParts, p, opts);
5035
5036 return p;
5037}
5038
5039var EXT_PROPS_XML_ROOT = writextag('Properties', null, {
5040 'xmlns': XMLNS.EXT_PROPS,
5041 'xmlns:vt': XMLNS.vt
5042});
5043
5044function write_ext_props(cp) {
5045 var o = [], W = writextag;
5046 if(!cp) cp = {};
5047 cp.Application = "SheetJS";
5048 o[o.length] = (XML_HEADER);
5049 o[o.length] = (EXT_PROPS_XML_ROOT);
5050
5051 EXT_PROPS.forEach(function(f) {
5052 if(cp[f[1]] === undefined) return;
5053 var v;
5054 switch(f[2]) {
5055 case 'string': v = escapexml(String(cp[f[1]])); break;
5056 case 'bool': v = cp[f[1]] ? 'true' : 'false'; break;
5057 }
5058 if(v !== undefined) o[o.length] = (W(f[0], v));
5059 });
5060
5061 /* TODO: HeadingPairs, TitlesOfParts */
5062 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"})));
5063 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"})));
5064 if(o.length>2){ o[o.length] = ('</Properties>'); o[1]=o[1].replace("/>",">"); }
5065 return o.join("");
5066}
5067/* 15.2.12.2 Custom File Properties Part */
5068XMLNS.CUST_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
5069RELS.CUST_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties';
5070
5071var custregex = /<[^>]+>[^<]*/g;
5072function parse_cust_props(data, opts) {
5073 var p = {}, name = "";
5074 var m = data.match(custregex);
5075 if(m) for(var i = 0; i != m.length; ++i) {
5076 var x = m[i], y = parsexmltag(x);
5077 switch(y[0]) {
5078 case '<?xml': break;
5079 case '<Properties': break;
5080 case '<property': name = unescapexml(y.name); break;
5081 case '</property>': name = null; break;
5082 default: if (x.indexOf('<vt:') === 0) {
5083 var toks = x.split('>');
5084 var type = toks[0].slice(4), text = toks[1];
5085 /* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */
5086 switch(type) {
5087 case 'lpstr': case 'bstr': case 'lpwstr':
5088 p[name] = unescapexml(text);
5089 break;
5090 case 'bool':
5091 p[name] = parsexmlbool(text);
5092 break;
5093 case 'i1': case 'i2': case 'i4': case 'i8': case 'int': case 'uint':
5094 p[name] = parseInt(text, 10);
5095 break;
5096 case 'r4': case 'r8': case 'decimal':
5097 p[name] = parseFloat(text);
5098 break;
5099 case 'filetime': case 'date':
5100 p[name] = parseDate(text);
5101 break;
5102 case 'cy': case 'error':
5103 p[name] = unescapexml(text);
5104 break;
5105 default:
5106 if(type.slice(-1) == '/') break;
5107 if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks);
5108 }
5109 } else if(x.slice(0,2) === "</") {/* empty */
5110 } else if(opts.WTF) throw new Error(x);
5111 }
5112 }
5113 return p;
5114}
5115
5116var CUST_PROPS_XML_ROOT = writextag('Properties', null, {
5117 'xmlns': XMLNS.CUST_PROPS,
5118 'xmlns:vt': XMLNS.vt
5119});
5120
5121function write_cust_props(cp) {
5122 var o = [XML_HEADER, CUST_PROPS_XML_ROOT];
5123 if(!cp) return o.join("");
5124 var pid = 1;
5125 keys(cp).forEach(function custprop(k) { ++pid;
5126 o[o.length] = (writextag('property', write_vt(cp[k], true), {
5127 'fmtid': '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}',
5128 'pid': pid,
5129 'name': escapexml(k)
5130 }));
5131 });
5132 if(o.length>2){ o[o.length] = '</Properties>'; o[1]=o[1].replace("/>",">"); }
5133 return o.join("");
5134}
5135/* Common Name -> XLML Name */
5136var XLMLDocPropsMap = {
5137 Title: 'Title',
5138 Subject: 'Subject',
5139 Author: 'Author',
5140 Keywords: 'Keywords',
5141 Comments: 'Description',
5142 LastAuthor: 'LastAuthor',
5143 RevNumber: 'Revision',
5144 Application: 'AppName',
5145 /* TotalTime: 'TotalTime', */
5146 LastPrinted: 'LastPrinted',
5147 CreatedDate: 'Created',
5148 ModifiedDate: 'LastSaved',
5149 /* Pages */
5150 /* Words */
5151 /* Characters */
5152 Category: 'Category',
5153 /* PresentationFormat */
5154 Manager: 'Manager',
5155 Company: 'Company',
5156 /* Guid */
5157 /* HyperlinkBase */
5158 /* Bytes */
5159 /* Lines */
5160 /* Paragraphs */
5161 /* CharactersWithSpaces */
5162 AppVersion: 'Version',
5163
5164 ContentStatus: 'ContentStatus', /* NOTE: missing from schema */
5165 Identifier: 'Identifier', /* NOTE: missing from schema */
5166 Language: 'Language' /* NOTE: missing from schema */
5167};
5168var evert_XLMLDPM = evert(XLMLDocPropsMap);
5169
5170function xlml_set_prop(Props, tag, val) {
5171 tag = evert_XLMLDPM[tag] || tag;
5172 Props[tag] = val;
5173}
5174
5175function xlml_write_docprops(Props, opts) {
5176 var o = [];
5177 keys(XLMLDocPropsMap).map(function(m) {
5178 for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i];
5179 for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i];
5180 throw m;
5181 }).forEach(function(p) {
5182 if(Props[p[1]] == null) return;
5183 var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]];
5184 switch(p[2]) {
5185 case 'date': m = new Date(m).toISOString().replace(/\.\d*Z/,"Z"); break;
5186 }
5187 if(typeof m == 'number') m = String(m);
5188 else if(m === true || m === false) { m = m ? "1" : "0"; }
5189 else if(m instanceof Date) m = new Date(m).toISOString().replace(/\.\d*Z/,"");
5190 o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m));
5191 });
5192 return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o });
5193}
5194function xlml_write_custprops(Props, Custprops) {
5195 var BLACKLIST = ["Worksheets","SheetNames"];
5196 var T = 'CustomDocumentProperties';
5197 var o = [];
5198 if(Props) keys(Props).forEach(function(k) {
5199if(!Object.prototype.hasOwnProperty.call(Props, k)) return;
5200 for(var i = 0; i < CORE_PROPS.length; ++i) if(k == CORE_PROPS[i][1]) return;
5201 for(i = 0; i < EXT_PROPS.length; ++i) if(k == EXT_PROPS[i][1]) return;
5202 for(i = 0; i < BLACKLIST.length; ++i) if(k == BLACKLIST[i]) return;
5203
5204 var m = Props[k];
5205 var t = "string";
5206 if(typeof m == 'number') { t = "float"; m = String(m); }
5207 else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
5208 else m = String(m);
5209 o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
5210 });
5211 if(Custprops) keys(Custprops).forEach(function(k) {
5212if(!Object.prototype.hasOwnProperty.call(Custprops, k)) return;
5213 if(Props && Object.prototype.hasOwnProperty.call(Props, k)) return;
5214 var m = Custprops[k];
5215 var t = "string";
5216 if(typeof m == 'number') { t = "float"; m = String(m); }
5217 else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
5218 else if(m instanceof Date) { t = "dateTime.tz"; m = m.toISOString(); }
5219 else m = String(m);
5220 o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
5221 });
5222 return '<' + T + ' xmlns="' + XLMLNS.o + '">' + o.join("") + '</' + T + '>';
5223}
5224/* [MS-DTYP] 2.3.3 FILETIME */
5225/* [MS-OLEDS] 2.1.3 FILETIME (Packet Version) */
5226/* [MS-OLEPS] 2.8 FILETIME (Packet Version) */
5227function parse_FILETIME(blob) {
5228 var dwLowDateTime = blob.read_shift(4), dwHighDateTime = blob.read_shift(4);
5229 return new Date(((dwHighDateTime/1e7*Math.pow(2,32) + dwLowDateTime/1e7) - 11644473600)*1000).toISOString().replace(/\.000/,"");
5230}
5231function write_FILETIME(time) {
5232 var date = (typeof time == "string") ? new Date(Date.parse(time)) : time;
5233 var t = date.getTime() / 1000 + 11644473600;
5234 var l = t % Math.pow(2,32), h = (t - l) / Math.pow(2,32);
5235 l *= 1e7; h *= 1e7;
5236 var w = (l / Math.pow(2,32)) | 0;
5237 if(w > 0) { l = l % Math.pow(2,32); h += w; }
5238 var o = new_buf(8); o.write_shift(4, l); o.write_shift(4, h); return o;
5239}
5240
5241/* [MS-OSHARED] 2.3.3.1.4 Lpstr */
5242function parse_lpstr(blob, type, pad) {
5243 var start = blob.l;
5244 var str = blob.read_shift(0, 'lpstr-cp');
5245 if(pad) while((blob.l - start) & 3) ++blob.l;
5246 return str;
5247}
5248
5249/* [MS-OSHARED] 2.3.3.1.6 Lpwstr */
5250function parse_lpwstr(blob, type, pad) {
5251 var str = blob.read_shift(0, 'lpwstr');
5252 if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3;
5253 return str;
5254}
5255
5256
5257/* [MS-OSHARED] 2.3.3.1.11 VtString */
5258/* [MS-OSHARED] 2.3.3.1.12 VtUnalignedString */
5259function parse_VtStringBase(blob, stringType, pad) {
5260 if(stringType === 0x1F /*VT_LPWSTR*/) return parse_lpwstr(blob);
5261 return parse_lpstr(blob, stringType, pad);
5262}
5263
5264function parse_VtString(blob, t, pad) { return parse_VtStringBase(blob, t, pad === false ? 0: 4); }
5265function parse_VtUnalignedString(blob, t) { if(!t) throw new Error("VtUnalignedString must have positive length"); return parse_VtStringBase(blob, t, 0); }
5266
5267/* [MS-OSHARED] 2.3.3.1.7 VtVecLpwstrValue */
5268function parse_VtVecLpwstrValue(blob) {
5269 var length = blob.read_shift(4);
5270 var ret = [];
5271 for(var i = 0; i != length; ++i) {
5272 var start = blob.l;
5273 ret[i] = blob.read_shift(0, 'lpwstr').replace(chr0,'');
5274 if((blob.l - start) & 0x02) blob.l += 2;
5275 }
5276 return ret;
5277}
5278
5279/* [MS-OSHARED] 2.3.3.1.9 VtVecUnalignedLpstrValue */
5280function parse_VtVecUnalignedLpstrValue(blob) {
5281 var length = blob.read_shift(4);
5282 var ret = [];
5283 for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr-cp').replace(chr0,'');
5284 return ret;
5285}
5286
5287
5288/* [MS-OSHARED] 2.3.3.1.13 VtHeadingPair */
5289function parse_VtHeadingPair(blob) {
5290 var start = blob.l;
5291 var headingString = parse_TypedPropertyValue(blob, VT_USTR);
5292 if(blob[blob.l] == 0x00 && blob[blob.l+1] == 0x00 && ((blob.l - start) & 0x02)) blob.l += 2;
5293 var headerParts = parse_TypedPropertyValue(blob, VT_I4);
5294 return [headingString, headerParts];
5295}
5296
5297/* [MS-OSHARED] 2.3.3.1.14 VtVecHeadingPairValue */
5298function parse_VtVecHeadingPairValue(blob) {
5299 var cElements = blob.read_shift(4);
5300 var out = [];
5301 for(var i = 0; i < cElements / 2; ++i) out.push(parse_VtHeadingPair(blob));
5302 return out;
5303}
5304
5305/* [MS-OLEPS] 2.18.1 Dictionary (uses 2.17, 2.16) */
5306function parse_dictionary(blob,CodePage) {
5307 var cnt = blob.read_shift(4);
5308 var dict = ({});
5309 for(var j = 0; j != cnt; ++j) {
5310 var pid = blob.read_shift(4);
5311 var len = blob.read_shift(4);
5312 dict[pid] = blob.read_shift(len, (CodePage === 0x4B0 ?'utf16le':'utf8')).replace(chr0,'').replace(chr1,'!');
5313 if(CodePage === 0x4B0 && (len % 2)) blob.l += 2;
5314 }
5315 if(blob.l & 3) blob.l = (blob.l>>2+1)<<2;
5316 return dict;
5317}
5318
5319/* [MS-OLEPS] 2.9 BLOB */
5320function parse_BLOB(blob) {
5321 var size = blob.read_shift(4);
5322 var bytes = blob.slice(blob.l,blob.l+size);
5323 blob.l += size;
5324 if((size & 3) > 0) blob.l += (4 - (size & 3)) & 3;
5325 return bytes;
5326}
5327
5328/* [MS-OLEPS] 2.11 ClipboardData */
5329function parse_ClipboardData(blob) {
5330 // TODO
5331 var o = {};
5332 o.Size = blob.read_shift(4);
5333 //o.Format = blob.read_shift(4);
5334 blob.l += o.Size + 3 - (o.Size - 1) % 4;
5335 return o;
5336}
5337
5338/* [MS-OLEPS] 2.15 TypedPropertyValue */
5339function parse_TypedPropertyValue(blob, type, _opts) {
5340 var t = blob.read_shift(2), ret, opts = _opts||{};
5341 blob.l += 2;
5342 if(type !== VT_VARIANT)
5343 if(t !== type && VT_CUSTOM.indexOf(type)===-1 && !((type & 0xFFFE) == 0x101E && (t & 0xFFFE) == 0x101E)) throw new Error('Expected type ' + type + ' saw ' + t);
5344 switch(type === VT_VARIANT ? t : type) {
5345 case 0x02 /*VT_I2*/: ret = blob.read_shift(2, 'i'); if(!opts.raw) blob.l += 2; return ret;
5346 case 0x03 /*VT_I4*/: ret = blob.read_shift(4, 'i'); return ret;
5347 case 0x0B /*VT_BOOL*/: return blob.read_shift(4) !== 0x0;
5348 case 0x13 /*VT_UI4*/: ret = blob.read_shift(4); return ret;
5349 case 0x1E /*VT_LPSTR*/: return parse_lpstr(blob, t, 4).replace(chr0,'');
5350 case 0x1F /*VT_LPWSTR*/: return parse_lpwstr(blob);
5351 case 0x40 /*VT_FILETIME*/: return parse_FILETIME(blob);
5352 case 0x41 /*VT_BLOB*/: return parse_BLOB(blob);
5353 case 0x47 /*VT_CF*/: return parse_ClipboardData(blob);
5354 case 0x50 /*VT_STRING*/: return parse_VtString(blob, t, !opts.raw).replace(chr0,'');
5355 case 0x51 /*VT_USTR*/: return parse_VtUnalignedString(blob, t/*, 4*/).replace(chr0,'');
5356 case 0x100C /*VT_VECTOR|VT_VARIANT*/: return parse_VtVecHeadingPairValue(blob);
5357 case 0x101E /*VT_VECTOR|VT_LPSTR*/:
5358 case 0x101F /*VT_VECTOR|VT_LPWSTR*/:
5359 return t == 0x101F ? parse_VtVecLpwstrValue(blob) : parse_VtVecUnalignedLpstrValue(blob);
5360 default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + t);
5361 }
5362}
5363function write_TypedPropertyValue(type, value) {
5364 var o = new_buf(4), p = new_buf(4);
5365 o.write_shift(4, type == 0x50 ? 0x1F : type);
5366 switch(type) {
5367 case 0x03 /*VT_I4*/: p.write_shift(-4, value); break;
5368 case 0x05 /*VT_I4*/: p = new_buf(8); p.write_shift(8, value, 'f'); break;
5369 case 0x0B /*VT_BOOL*/: p.write_shift(4, value ? 0x01 : 0x00); break;
5370 case 0x40 /*VT_FILETIME*/: p = write_FILETIME(value); break;
5371 case 0x1F /*VT_LPWSTR*/:
5372 case 0x50 /*VT_STRING*/:
5373p = new_buf(4 + 2 * (value.length + 1) + (value.length % 2 ? 0 : 2));
5374 p.write_shift(4, value.length + 1);
5375 p.write_shift(0, value, "dbcs");
5376 while(p.l != p.length) p.write_shift(1, 0);
5377 break;
5378 default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + value);
5379 }
5380 return bconcat([o, p]);
5381}
5382
5383/* [MS-OLEPS] 2.20 PropertySet */
5384function parse_PropertySet(blob, PIDSI) {
5385 var start_addr = blob.l;
5386 var size = blob.read_shift(4);
5387 var NumProps = blob.read_shift(4);
5388 var Props = [], i = 0;
5389 var CodePage = 0;
5390 var Dictionary = -1, DictObj = ({});
5391 for(i = 0; i != NumProps; ++i) {
5392 var PropID = blob.read_shift(4);
5393 var Offset = blob.read_shift(4);
5394 Props[i] = [PropID, Offset + start_addr];
5395 }
5396 Props.sort(function(x,y) { return x[1] - y[1]; });
5397 var PropH = {};
5398 for(i = 0; i != NumProps; ++i) {
5399 if(blob.l !== Props[i][1]) {
5400 var fail = true;
5401 if(i>0 && PIDSI) switch(PIDSI[Props[i-1][0]].t) {
5402 case 0x02 /*VT_I2*/: if(blob.l+2 === Props[i][1]) { blob.l+=2; fail = false; } break;
5403 case 0x50 /*VT_STRING*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
5404 case 0x100C /*VT_VECTOR|VT_VARIANT*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
5405 }
5406 if((!PIDSI||i==0) && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; }
5407 if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i);
5408 }
5409 if(PIDSI) {
5410 var piddsi = PIDSI[Props[i][0]];
5411 PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true});
5412 if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + ("0000" + String(PropH[piddsi.n] & 0xFFFF)).slice(-4);
5413 if(piddsi.n == "CodePage") switch(PropH[piddsi.n]) {
5414 case 0: PropH[piddsi.n] = 1252;
5415 /* falls through */
5416 case 874:
5417 case 932:
5418 case 936:
5419 case 949:
5420 case 950:
5421 case 1250:
5422 case 1251:
5423 case 1253:
5424 case 1254:
5425 case 1255:
5426 case 1256:
5427 case 1257:
5428 case 1258:
5429 case 10000:
5430 case 1200:
5431 case 1201:
5432 case 1252:
5433 case 65000: case -536:
5434 case 65001: case -535:
5435 set_cp(CodePage = (PropH[piddsi.n]>>>0) & 0xFFFF); break;
5436 default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
5437 }
5438 } else {
5439 if(Props[i][0] === 0x1) {
5440 CodePage = PropH.CodePage = (parse_TypedPropertyValue(blob, VT_I2));
5441 set_cp(CodePage);
5442 if(Dictionary !== -1) {
5443 var oldpos = blob.l;
5444 blob.l = Props[Dictionary][1];
5445 DictObj = parse_dictionary(blob,CodePage);
5446 blob.l = oldpos;
5447 }
5448 } else if(Props[i][0] === 0) {
5449 if(CodePage === 0) { Dictionary = i; blob.l = Props[i+1][1]; continue; }
5450 DictObj = parse_dictionary(blob,CodePage);
5451 } else {
5452 var name = DictObj[Props[i][0]];
5453 var val;
5454 /* [MS-OSHARED] 2.3.3.2.3.1.2 + PROPVARIANT */
5455 switch(blob[blob.l]) {
5456 case 0x41 /*VT_BLOB*/: blob.l += 4; val = parse_BLOB(blob); break;
5457 case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break;
5458 case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break;
5459 case 0x03 /*VT_I4*/: blob.l += 4; val = blob.read_shift(4, 'i'); break;
5460 case 0x13 /*VT_UI4*/: blob.l += 4; val = blob.read_shift(4); break;
5461 case 0x05 /*VT_R8*/: blob.l += 4; val = blob.read_shift(8, 'f'); break;
5462 case 0x0B /*VT_BOOL*/: blob.l += 4; val = parsebool(blob, 4); break;
5463 case 0x40 /*VT_FILETIME*/: blob.l += 4; val = parseDate(parse_FILETIME(blob)); break;
5464 default: throw new Error("unparsed value: " + blob[blob.l]);
5465 }
5466 PropH[name] = val;
5467 }
5468 }
5469 }
5470 blob.l = start_addr + size; /* step ahead to skip padding */
5471 return PropH;
5472}
5473var XLSPSSkip = [ "CodePage", "Thumbnail", "_PID_LINKBASE", "_PID_HLINKS", "SystemIdentifier", "FMTID" ].concat(PseudoPropsPairs);
5474function guess_property_type(val) {
5475 switch(typeof val) {
5476 case "boolean": return 0x0B;
5477 case "number": return ((val|0)==val) ? 0x03 : 0x05;
5478 case "string": return 0x1F;
5479 case "object": if(val instanceof Date) return 0x40; break;
5480 }
5481 return -1;
5482}
5483function write_PropertySet(entries, RE, PIDSI) {
5484 var hdr = new_buf(8), piao = [], prop = [];
5485 var sz = 8, i = 0;
5486
5487 var pr = new_buf(8), pio = new_buf(8);
5488 pr.write_shift(4, 0x0002);
5489 pr.write_shift(4, 0x04B0);
5490 pio.write_shift(4, 0x0001);
5491 prop.push(pr); piao.push(pio);
5492 sz += 8 + pr.length;
5493
5494 if(!RE) {
5495 pio = new_buf(8);
5496 pio.write_shift(4, 0);
5497 piao.unshift(pio);
5498
5499 var bufs = [new_buf(4)];
5500 bufs[0].write_shift(4, entries.length);
5501 for(i = 0; i < entries.length; ++i) {
5502 var value = entries[i][0];
5503 pr = new_buf(4 + 4 + 2 * (value.length + 1) + (value.length % 2 ? 0 : 2));
5504 pr.write_shift(4, i+2);
5505 pr.write_shift(4, value.length + 1);
5506 pr.write_shift(0, value, "dbcs");
5507 while(pr.l != pr.length) pr.write_shift(1, 0);
5508 bufs.push(pr);
5509 }
5510 pr = bconcat(bufs);
5511 prop.unshift(pr);
5512 sz += 8 + pr.length;
5513 }
5514
5515 for(i = 0; i < entries.length; ++i) {
5516 if(RE && !RE[entries[i][0]]) continue;
5517 if(XLSPSSkip.indexOf(entries[i][0]) > -1) continue;
5518 if(entries[i][1] == null) continue;
5519
5520 var val = entries[i][1], idx = 0;
5521 if(RE) {
5522 idx = +RE[entries[i][0]];
5523 var pinfo = (PIDSI)[idx];
5524 if(pinfo.p == "version" && typeof val == "string") {
5525var arr = val.split(".");
5526 val = ((+arr[0])<<16) + ((+arr[1])||0);
5527 }
5528 pr = write_TypedPropertyValue(pinfo.t, val);
5529 } else {
5530 var T = guess_property_type(val);
5531 if(T == -1) { T = 0x1F; val = String(val); }
5532 pr = write_TypedPropertyValue(T, val);
5533 }
5534 prop.push(pr);
5535
5536 pio = new_buf(8);
5537 pio.write_shift(4, !RE ? 2+i : idx);
5538 piao.push(pio);
5539
5540 sz += 8 + pr.length;
5541 }
5542
5543 var w = 8 * (prop.length + 1);
5544 for(i = 0; i < prop.length; ++i) { piao[i].write_shift(4, w); w += prop[i].length; }
5545 hdr.write_shift(4, sz);
5546 hdr.write_shift(4, prop.length);
5547 return bconcat([hdr].concat(piao).concat(prop));
5548}
5549
5550/* [MS-OLEPS] 2.21 PropertySetStream */
5551function parse_PropertySetStream(file, PIDSI, clsid) {
5552 var blob = file.content;
5553 if(!blob) return ({});
5554 prep_blob(blob, 0);
5555
5556 var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;
5557 blob.chk('feff', 'Byte Order: ');
5558
5559 /*var vers = */blob.read_shift(2); // TODO: check version
5560 var SystemIdentifier = blob.read_shift(4);
5561 var CLSID = blob.read_shift(16);
5562 if(CLSID !== CFB.utils.consts.HEADER_CLSID && CLSID !== clsid) throw new Error("Bad PropertySet CLSID " + CLSID);
5563 NumSets = blob.read_shift(4);
5564 if(NumSets !== 1 && NumSets !== 2) throw new Error("Unrecognized #Sets: " + NumSets);
5565 FMTID0 = blob.read_shift(16); Offset0 = blob.read_shift(4);
5566
5567 if(NumSets === 1 && Offset0 !== blob.l) throw new Error("Length mismatch: " + Offset0 + " !== " + blob.l);
5568 else if(NumSets === 2) { FMTID1 = blob.read_shift(16); Offset1 = blob.read_shift(4); }
5569 var PSet0 = parse_PropertySet(blob, PIDSI);
5570
5571 var rval = ({ SystemIdentifier: SystemIdentifier });
5572 for(var y in PSet0) rval[y] = PSet0[y];
5573 //rval.blob = blob;
5574 rval.FMTID = FMTID0;
5575 //rval.PSet0 = PSet0;
5576 if(NumSets === 1) return rval;
5577 if(Offset1 - blob.l == 2) blob.l += 2;
5578 if(blob.l !== Offset1) throw new Error("Length mismatch 2: " + blob.l + " !== " + Offset1);
5579 var PSet1;
5580 try { PSet1 = parse_PropertySet(blob, null); } catch(e) {/* empty */}
5581 for(y in PSet1) rval[y] = PSet1[y];
5582 rval.FMTID = [FMTID0, FMTID1]; // TODO: verify FMTID0/1
5583 return rval;
5584}
5585function write_PropertySetStream(entries, clsid, RE, PIDSI, entries2, clsid2) {
5586 var hdr = new_buf(entries2 ? 68 : 48);
5587 var bufs = [hdr];
5588 hdr.write_shift(2, 0xFFFE);
5589 hdr.write_shift(2, 0x0000); /* TODO: type 1 props */
5590 hdr.write_shift(4, 0x32363237);
5591 hdr.write_shift(16, CFB.utils.consts.HEADER_CLSID, "hex");
5592 hdr.write_shift(4, (entries2 ? 2 : 1));
5593 hdr.write_shift(16, clsid, "hex");
5594 hdr.write_shift(4, (entries2 ? 68 : 48));
5595 var ps0 = write_PropertySet(entries, RE, PIDSI);
5596 bufs.push(ps0);
5597
5598 if(entries2) {
5599 var ps1 = write_PropertySet(entries2, null, null);
5600 hdr.write_shift(16, clsid2, "hex");
5601 hdr.write_shift(4, 68 + ps0.length);
5602 bufs.push(ps1);
5603 }
5604 return bconcat(bufs);
5605}
5606
5607function parsenoop2(blob, length) { blob.read_shift(length); return null; }
5608function writezeroes(n, o) { if(!o) o=new_buf(n); for(var j=0; j<n; ++j) o.write_shift(1, 0); return o; }
5609
5610function parslurp(blob, length, cb) {
5611 var arr = [], target = blob.l + length;
5612 while(blob.l < target) arr.push(cb(blob, target - blob.l));
5613 if(target !== blob.l) throw new Error("Slurp error");
5614 return arr;
5615}
5616
5617function parsebool(blob, length) { return blob.read_shift(length) === 0x1; }
5618function writebool(v, o) { if(!o) o=new_buf(2); o.write_shift(2, +!!v); return o; }
5619
5620function parseuint16(blob) { return blob.read_shift(2, 'u'); }
5621function writeuint16(v, o) { if(!o) o=new_buf(2); o.write_shift(2, v); return o; }
5622function parseuint16a(blob, length) { return parslurp(blob,length,parseuint16);}
5623
5624/* --- 2.5 Structures --- */
5625
5626/* [MS-XLS] 2.5.10 Bes (boolean or error) */
5627function parse_Bes(blob) {
5628 var v = blob.read_shift(1), t = blob.read_shift(1);
5629 return t === 0x01 ? v : v === 0x01;
5630}
5631function write_Bes(v, t, o) {
5632 if(!o) o = new_buf(2);
5633 o.write_shift(1, ((t == 'e') ? +v : +!!v));
5634 o.write_shift(1, ((t == 'e') ? 1 : 0));
5635 return o;
5636}
5637
5638/* [MS-XLS] 2.5.240 ShortXLUnicodeString */
5639function parse_ShortXLUnicodeString(blob, length, opts) {
5640 var cch = blob.read_shift(opts && opts.biff >= 12 ? 2 : 1);
5641 var encoding = 'sbcs-cont';
5642 var cp = current_codepage;
5643 if(opts && opts.biff >= 8) current_codepage = 1200;
5644 if(!opts || opts.biff == 8 ) {
5645 var fHighByte = blob.read_shift(1);
5646 if(fHighByte) { encoding = 'dbcs-cont'; }
5647 } else if(opts.biff == 12) {
5648 encoding = 'wstr';
5649 }
5650 if(opts.biff >= 2 && opts.biff <= 5) encoding = 'cpstr';
5651 var o = cch ? blob.read_shift(cch, encoding) : "";
5652 current_codepage = cp;
5653 return o;
5654}
5655
5656/* 2.5.293 XLUnicodeRichExtendedString */
5657function parse_XLUnicodeRichExtendedString(blob) {
5658 var cp = current_codepage;
5659 current_codepage = 1200;
5660 var cch = blob.read_shift(2), flags = blob.read_shift(1);
5661 var /*fHighByte = flags & 0x1,*/ fExtSt = flags & 0x4, fRichSt = flags & 0x8;
5662 var width = 1 + (flags & 0x1); // 0x0 -> utf8, 0x1 -> dbcs
5663 var cRun = 0, cbExtRst;
5664 var z = {};
5665 if(fRichSt) cRun = blob.read_shift(2);
5666 if(fExtSt) cbExtRst = blob.read_shift(4);
5667 var encoding = width == 2 ? 'dbcs-cont' : 'sbcs-cont';
5668 var msg = cch === 0 ? "" : blob.read_shift(cch, encoding);
5669 if(fRichSt) blob.l += 4 * cRun; //TODO: parse this
5670 if(fExtSt) blob.l += cbExtRst; //TODO: parse this
5671 z.t = msg;
5672 if(!fRichSt) { z.raw = "<t>" + z.t + "</t>"; z.r = z.t; }
5673 current_codepage = cp;
5674 return z;
5675}
5676function write_XLUnicodeRichExtendedString(xlstr) {
5677 var str = (xlstr.t||""), nfmts = 1;
5678
5679 var hdr = new_buf(3 + (nfmts > 1 ? 2 : 0));
5680 hdr.write_shift(2, str.length);
5681 hdr.write_shift(1, (nfmts > 1 ? 0x08 : 0x00) | 0x01);
5682 if(nfmts > 1) hdr.write_shift(2, nfmts);
5683
5684 var otext = new_buf(2 * str.length);
5685 otext.write_shift(2 * str.length, str, 'utf16le');
5686
5687 var out = [hdr, otext];
5688
5689 return bconcat(out);
5690}
5691
5692/* 2.5.296 XLUnicodeStringNoCch */
5693function parse_XLUnicodeStringNoCch(blob, cch, opts) {
5694 var retval;
5695 if(opts) {
5696 if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'cpstr');
5697 if(opts.biff >= 12) return blob.read_shift(cch, 'dbcs-cont');
5698 }
5699 var fHighByte = blob.read_shift(1);
5700 if(fHighByte===0) { retval = blob.read_shift(cch, 'sbcs-cont'); }
5701 else { retval = blob.read_shift(cch, 'dbcs-cont'); }
5702 return retval;
5703}
5704
5705/* 2.5.294 XLUnicodeString */
5706function parse_XLUnicodeString(blob, length, opts) {
5707 var cch = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
5708 if(cch === 0) { blob.l++; return ""; }
5709 return parse_XLUnicodeStringNoCch(blob, cch, opts);
5710}
5711/* BIFF5 override */
5712function parse_XLUnicodeString2(blob, length, opts) {
5713 if(opts.biff > 5) return parse_XLUnicodeString(blob, length, opts);
5714 var cch = blob.read_shift(1);
5715 if(cch === 0) { blob.l++; return ""; }
5716 return blob.read_shift(cch, (opts.biff <= 4 || !blob.lens ) ? 'cpstr' : 'sbcs-cont');
5717}
5718/* TODO: BIFF5 and lower, codepage awareness */
5719function write_XLUnicodeString(str, opts, o) {
5720 if(!o) o = new_buf(3 + 2 * str.length);
5721 o.write_shift(2, str.length);
5722 o.write_shift(1, 1);
5723 o.write_shift(31, str, 'utf16le');
5724 return o;
5725}
5726
5727/* [MS-XLS] 2.5.61 ControlInfo */
5728function parse_ControlInfo(blob) {
5729 var flags = blob.read_shift(1);
5730 blob.l++;
5731 var accel = blob.read_shift(2);
5732 blob.l += 2;
5733 return [flags, accel];
5734}
5735
5736/* [MS-OSHARED] 2.3.7.6 URLMoniker TODO: flags */
5737function parse_URLMoniker(blob) {
5738 var len = blob.read_shift(4), start = blob.l;
5739 var extra = false;
5740 if(len > 24) {
5741 /* look ahead */
5742 blob.l += len - 24;
5743 if(blob.read_shift(16) === "795881f43b1d7f48af2c825dc4852763") extra = true;
5744 blob.l = start;
5745 }
5746 var url = blob.read_shift((extra?len-24:len)>>1, 'utf16le').replace(chr0,"");
5747 if(extra) blob.l += 24;
5748 return url;
5749}
5750
5751/* [MS-OSHARED] 2.3.7.8 FileMoniker TODO: all fields */
5752function parse_FileMoniker(blob) {
5753 var cAnti = blob.read_shift(2);
5754 var preamble = ""; while(cAnti-- > 0) preamble += "../";
5755 var ansiPath = blob.read_shift(0, 'lpstr-ansi');
5756 blob.l += 2; //var endServer = blob.read_shift(2);
5757 if(blob.read_shift(2) != 0xDEAD) throw new Error("Bad FileMoniker");
5758 var sz = blob.read_shift(4);
5759 if(sz === 0) return preamble + ansiPath.replace(/\\/g,"/");
5760 var bytes = blob.read_shift(4);
5761 if(blob.read_shift(2) != 3) throw new Error("Bad FileMoniker");
5762 var unicodePath = blob.read_shift(bytes>>1, 'utf16le').replace(chr0,"");
5763 return preamble + unicodePath;
5764}
5765
5766/* [MS-OSHARED] 2.3.7.2 HyperlinkMoniker TODO: all the monikers */
5767function parse_HyperlinkMoniker(blob, length) {
5768 var clsid = blob.read_shift(16); length -= 16;
5769 switch(clsid) {
5770 case "e0c9ea79f9bace118c8200aa004ba90b": return parse_URLMoniker(blob, length);
5771 case "0303000000000000c000000000000046": return parse_FileMoniker(blob, length);
5772 default: throw new Error("Unsupported Moniker " + clsid);
5773 }
5774}
5775
5776/* [MS-OSHARED] 2.3.7.9 HyperlinkString */
5777function parse_HyperlinkString(blob) {
5778 var len = blob.read_shift(4);
5779 var o = len > 0 ? blob.read_shift(len, 'utf16le').replace(chr0, "") : "";
5780 return o;
5781}
5782function write_HyperlinkString(str, o) {
5783 if(!o) o = new_buf(6 + str.length * 2);
5784 o.write_shift(4, 1 + str.length);
5785 for(var i = 0; i < str.length; ++i) o.write_shift(2, str.charCodeAt(i));
5786 o.write_shift(2, 0);
5787 return o;
5788}
5789
5790/* [MS-OSHARED] 2.3.7.1 Hyperlink Object */
5791function parse_Hyperlink(blob, length) {
5792 var end = blob.l + length;
5793 var sVer = blob.read_shift(4);
5794 if(sVer !== 2) throw new Error("Unrecognized streamVersion: " + sVer);
5795 var flags = blob.read_shift(2);
5796 blob.l += 2;
5797 var displayName, targetFrameName, moniker, oleMoniker, Loc="", guid, fileTime;
5798 if(flags & 0x0010) displayName = parse_HyperlinkString(blob, end - blob.l);
5799 if(flags & 0x0080) targetFrameName = parse_HyperlinkString(blob, end - blob.l);
5800 if((flags & 0x0101) === 0x0101) moniker = parse_HyperlinkString(blob, end - blob.l);
5801 if((flags & 0x0101) === 0x0001) oleMoniker = parse_HyperlinkMoniker(blob, end - blob.l);
5802 if(flags & 0x0008) Loc = parse_HyperlinkString(blob, end - blob.l);
5803 if(flags & 0x0020) guid = blob.read_shift(16);
5804 if(flags & 0x0040) fileTime = parse_FILETIME(blob/*, 8*/);
5805 blob.l = end;
5806 var target = targetFrameName||moniker||oleMoniker||"";
5807 if(target && Loc) target+="#"+Loc;
5808 if(!target) target = "#" + Loc;
5809 if((flags & 0x0002) && target.charAt(0) == "/" && target.charAt(1) != "/") target = "file://" + target;
5810 var out = ({Target:target});
5811 if(guid) out.guid = guid;
5812 if(fileTime) out.time = fileTime;
5813 if(displayName) out.Tooltip = displayName;
5814 return out;
5815}
5816function write_Hyperlink(hl) {
5817 var out = new_buf(512), i = 0;
5818 var Target = hl.Target;
5819 if(Target.slice(0,7) == "file://") Target = Target.slice(7);
5820 var hashidx = Target.indexOf("#");
5821 var F = hashidx > -1 ? 0x1f : 0x17;
5822 switch(Target.charAt(0)) { case "#": F=0x1c; break; case ".": F&=~2; break; }
5823 out.write_shift(4,2); out.write_shift(4, F);
5824 var data = [8,6815827,6619237,4849780,83]; for(i = 0; i < data.length; ++i) out.write_shift(4, data[i]);
5825 if(F == 0x1C) {
5826 Target = Target.slice(1);
5827 write_HyperlinkString(Target, out);
5828 } else if(F & 0x02) {
5829 data = "e0 c9 ea 79 f9 ba ce 11 8c 82 00 aa 00 4b a9 0b".split(" ");
5830 for(i = 0; i < data.length; ++i) out.write_shift(1, parseInt(data[i], 16));
5831 var Pretarget = hashidx > -1 ? Target.slice(0, hashidx) : Target;
5832 out.write_shift(4, 2*(Pretarget.length + 1));
5833 for(i = 0; i < Pretarget.length; ++i) out.write_shift(2, Pretarget.charCodeAt(i));
5834 out.write_shift(2, 0);
5835 if(F & 0x08) write_HyperlinkString(hashidx > -1 ? Target.slice(hashidx+1): "", out);
5836 } else {
5837 data = "03 03 00 00 00 00 00 00 c0 00 00 00 00 00 00 46".split(" ");
5838 for(i = 0; i < data.length; ++i) out.write_shift(1, parseInt(data[i], 16));
5839 var P = 0;
5840 while(Target.slice(P*3,P*3+3)=="../"||Target.slice(P*3,P*3+3)=="..\\") ++P;
5841 out.write_shift(2, P);
5842 out.write_shift(4, Target.length - 3 * P + 1);
5843 for(i = 0; i < Target.length - 3 * P; ++i) out.write_shift(1, Target.charCodeAt(i + 3 * P) & 0xFF);
5844 out.write_shift(1, 0);
5845 out.write_shift(2, 0xFFFF);
5846 out.write_shift(2, 0xDEAD);
5847 for(i = 0; i < 6; ++i) out.write_shift(4, 0);
5848 }
5849 return out.slice(0, out.l);
5850}
5851
5852/* 2.5.178 LongRGBA */
5853function parse_LongRGBA(blob) { var r = blob.read_shift(1), g = blob.read_shift(1), b = blob.read_shift(1), a = blob.read_shift(1); return [r,g,b,a]; }
5854
5855/* 2.5.177 LongRGB */
5856function parse_LongRGB(blob, length) { var x = parse_LongRGBA(blob, length); x[3] = 0; return x; }
5857
5858
5859/* [MS-XLS] 2.5.19 */
5860function parse_XLSCell(blob) {
5861 var rw = blob.read_shift(2); // 0-indexed
5862 var col = blob.read_shift(2);
5863 var ixfe = blob.read_shift(2);
5864 return ({r:rw, c:col, ixfe:ixfe});
5865}
5866function write_XLSCell(R, C, ixfe, o) {
5867 if(!o) o = new_buf(6);
5868 o.write_shift(2, R);
5869 o.write_shift(2, C);
5870 o.write_shift(2, ixfe||0);
5871 return o;
5872}
5873
5874/* [MS-XLS] 2.5.134 */
5875function parse_frtHeader(blob) {
5876 var rt = blob.read_shift(2);
5877 var flags = blob.read_shift(2); // TODO: parse these flags
5878 blob.l += 8;
5879 return {type: rt, flags: flags};
5880}
5881
5882
5883
5884function parse_OptXLUnicodeString(blob, length, opts) { return length === 0 ? "" : parse_XLUnicodeString2(blob, length, opts); }
5885
5886/* [MS-XLS] 2.5.344 */
5887function parse_XTI(blob, length, opts) {
5888 var w = opts.biff > 8 ? 4 : 2;
5889 var iSupBook = blob.read_shift(w), itabFirst = blob.read_shift(w,'i'), itabLast = blob.read_shift(w,'i');
5890 return [iSupBook, itabFirst, itabLast];
5891}
5892
5893/* [MS-XLS] 2.5.218 */
5894function parse_RkRec(blob) {
5895 var ixfe = blob.read_shift(2);
5896 var RK = parse_RkNumber(blob);
5897 return [ixfe, RK];
5898}
5899
5900/* [MS-XLS] 2.5.1 */
5901function parse_AddinUdf(blob, length, opts) {
5902 blob.l += 4; length -= 4;
5903 var l = blob.l + length;
5904 var udfName = parse_ShortXLUnicodeString(blob, length, opts);
5905 var cb = blob.read_shift(2);
5906 l -= blob.l;
5907 if(cb !== l) throw new Error("Malformed AddinUdf: padding = " + l + " != " + cb);
5908 blob.l += cb;
5909 return udfName;
5910}
5911
5912/* [MS-XLS] 2.5.209 TODO: Check sizes */
5913function parse_Ref8U(blob) {
5914 var rwFirst = blob.read_shift(2);
5915 var rwLast = blob.read_shift(2);
5916 var colFirst = blob.read_shift(2);
5917 var colLast = blob.read_shift(2);
5918 return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}};
5919}
5920function write_Ref8U(r, o) {
5921 if(!o) o = new_buf(8);
5922 o.write_shift(2, r.s.r);
5923 o.write_shift(2, r.e.r);
5924 o.write_shift(2, r.s.c);
5925 o.write_shift(2, r.e.c);
5926 return o;
5927}
5928
5929/* [MS-XLS] 2.5.211 */
5930function parse_RefU(blob) {
5931 var rwFirst = blob.read_shift(2);
5932 var rwLast = blob.read_shift(2);
5933 var colFirst = blob.read_shift(1);
5934 var colLast = blob.read_shift(1);
5935 return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}};
5936}
5937
5938/* [MS-XLS] 2.5.207 */
5939var parse_Ref = parse_RefU;
5940
5941/* [MS-XLS] 2.5.143 */
5942function parse_FtCmo(blob) {
5943 blob.l += 4;
5944 var ot = blob.read_shift(2);
5945 var id = blob.read_shift(2);
5946 var flags = blob.read_shift(2);
5947 blob.l+=12;
5948 return [id, ot, flags];
5949}
5950
5951/* [MS-XLS] 2.5.149 */
5952function parse_FtNts(blob) {
5953 var out = {};
5954 blob.l += 4;
5955 blob.l += 16; // GUID TODO
5956 out.fSharedNote = blob.read_shift(2);
5957 blob.l += 4;
5958 return out;
5959}
5960
5961/* [MS-XLS] 2.5.142 */
5962function parse_FtCf(blob) {
5963 var out = {};
5964 blob.l += 4;
5965 blob.cf = blob.read_shift(2);
5966 return out;
5967}
5968
5969/* [MS-XLS] 2.5.140 - 2.5.154 and friends */
5970function parse_FtSkip(blob) { blob.l += 2; blob.l += blob.read_shift(2); }
5971var FtTab = {
59720x00: parse_FtSkip, /* FtEnd */
59730x04: parse_FtSkip, /* FtMacro */
59740x05: parse_FtSkip, /* FtButton */
59750x06: parse_FtSkip, /* FtGmo */
59760x07: parse_FtCf, /* FtCf */
59770x08: parse_FtSkip, /* FtPioGrbit */
59780x09: parse_FtSkip, /* FtPictFmla */
59790x0A: parse_FtSkip, /* FtCbls */
59800x0B: parse_FtSkip, /* FtRbo */
59810x0C: parse_FtSkip, /* FtSbs */
59820x0D: parse_FtNts, /* FtNts */
59830x0E: parse_FtSkip, /* FtSbsFmla */
59840x0F: parse_FtSkip, /* FtGboData */
59850x10: parse_FtSkip, /* FtEdoData */
59860x11: parse_FtSkip, /* FtRboData */
59870x12: parse_FtSkip, /* FtCblsData */
59880x13: parse_FtSkip, /* FtLbsData */
59890x14: parse_FtSkip, /* FtCblsFmla */
59900x15: parse_FtCmo
5991};
5992function parse_FtArray(blob, length) {
5993 var tgt = blob.l + length;
5994 var fts = [];
5995 while(blob.l < tgt) {
5996 var ft = blob.read_shift(2);
5997 blob.l-=2;
5998 try {
5999 fts.push(FtTab[ft](blob, tgt - blob.l));
6000 } catch(e) { blob.l = tgt; return fts; }
6001 }
6002 if(blob.l != tgt) blob.l = tgt; //throw new Error("bad Object Ft-sequence");
6003 return fts;
6004}
6005
6006/* --- 2.4 Records --- */
6007
6008/* [MS-XLS] 2.4.21 */
6009function parse_BOF(blob, length) {
6010 var o = {BIFFVer:0, dt:0};
6011 o.BIFFVer = blob.read_shift(2); length -= 2;
6012 if(length >= 2) { o.dt = blob.read_shift(2); blob.l -= 2; }
6013 switch(o.BIFFVer) {
6014 case 0x0600: /* BIFF8 */
6015 case 0x0500: /* BIFF5 */
6016 case 0x0400: /* BIFF4 */
6017 case 0x0300: /* BIFF3 */
6018 case 0x0200: /* BIFF2 */
6019 case 0x0002: case 0x0007: /* BIFF2 */
6020 break;
6021 default: if(length > 6) throw new Error("Unexpected BIFF Ver " + o.BIFFVer);
6022 }
6023
6024 blob.read_shift(length);
6025 return o;
6026}
6027function write_BOF(wb, t, o) {
6028 var h = 0x0600, w = 16;
6029 switch(o.bookType) {
6030 case 'biff8': break;
6031 case 'biff5': h = 0x0500; w = 8; break;
6032 case 'biff4': h = 0x0004; w = 6; break;
6033 case 'biff3': h = 0x0003; w = 6; break;
6034 case 'biff2': h = 0x0002; w = 4; break;
6035 case 'xla': break;
6036 default: throw new Error("unsupported BIFF version");
6037 }
6038 var out = new_buf(w);
6039 out.write_shift(2, h);
6040 out.write_shift(2, t);
6041 if(w > 4) out.write_shift(2, 0x7262);
6042 if(w > 6) out.write_shift(2, 0x07CD);
6043 if(w > 8) {
6044 out.write_shift(2, 0xC009);
6045 out.write_shift(2, 0x0001);
6046 out.write_shift(2, 0x0706);
6047 out.write_shift(2, 0x0000);
6048 }
6049 return out;
6050}
6051
6052
6053/* [MS-XLS] 2.4.146 */
6054function parse_InterfaceHdr(blob, length) {
6055 if(length === 0) return 0x04b0;
6056 if((blob.read_shift(2))!==0x04b0){/* empty */}
6057 return 0x04b0;
6058}
6059
6060
6061/* [MS-XLS] 2.4.349 */
6062function parse_WriteAccess(blob, length, opts) {
6063 if(opts.enc) { blob.l += length; return ""; }
6064 var l = blob.l;
6065 // TODO: make sure XLUnicodeString doesnt overrun
6066 var UserName = parse_XLUnicodeString2(blob, 0, opts);
6067 blob.read_shift(length + l - blob.l);
6068 return UserName;
6069}
6070function write_WriteAccess(s, opts) {
6071 var b8 = !opts || opts.biff == 8;
6072 var o = new_buf(b8 ? 112 : 54);
6073 o.write_shift(opts.biff == 8 ? 2 : 1, 7);
6074 if(b8) o.write_shift(1, 0);
6075 o.write_shift(4, 0x33336853);
6076 o.write_shift(4, (0x00534A74 | (b8 ? 0 : 0x20000000)));
6077 while(o.l < o.length) o.write_shift(1, (b8 ? 0 : 32));
6078 return o;
6079}
6080
6081/* [MS-XLS] 2.4.351 */
6082function parse_WsBool(blob, length, opts) {
6083 var flags = opts && opts.biff == 8 || length == 2 ? blob.read_shift(2) : (blob.l += length, 0);
6084 return { fDialog: flags & 0x10, fBelow: flags & 0x40, fRight: flags & 0x80 };
6085}
6086
6087/* [MS-XLS] 2.4.28 */
6088function parse_BoundSheet8(blob, length, opts) {
6089 var pos = blob.read_shift(4);
6090 var hidden = blob.read_shift(1) & 0x03;
6091 var dt = blob.read_shift(1);
6092 switch(dt) {
6093 case 0: dt = 'Worksheet'; break;
6094 case 1: dt = 'Macrosheet'; break;
6095 case 2: dt = 'Chartsheet'; break;
6096 case 6: dt = 'VBAModule'; break;
6097 }
6098 var name = parse_ShortXLUnicodeString(blob, 0, opts);
6099 if(name.length === 0) name = "Sheet1";
6100 return { pos:pos, hs:hidden, dt:dt, name:name };
6101}
6102function write_BoundSheet8(data, opts) {
6103 var w = (!opts || opts.biff >= 8 ? 2 : 1);
6104 var o = new_buf(8 + w * data.name.length);
6105 o.write_shift(4, data.pos);
6106 o.write_shift(1, data.hs || 0);
6107 o.write_shift(1, data.dt);
6108 o.write_shift(1, data.name.length);
6109 if(opts.biff >= 8) o.write_shift(1, 1);
6110 o.write_shift(w * data.name.length, data.name, opts.biff < 8 ? 'sbcs' : 'utf16le');
6111 var out = o.slice(0, o.l);
6112 out.l = o.l; return out;
6113}
6114
6115/* [MS-XLS] 2.4.265 TODO */
6116function parse_SST(blob, length) {
6117 var end = blob.l + length;
6118 var cnt = blob.read_shift(4);
6119 var ucnt = blob.read_shift(4);
6120 var strs = ([]);
6121 for(var i = 0; i != ucnt && blob.l < end; ++i) {
6122 strs.push(parse_XLUnicodeRichExtendedString(blob));
6123 }
6124 strs.Count = cnt; strs.Unique = ucnt;
6125 return strs;
6126}
6127function write_SST(sst, opts) {
6128 var header = new_buf(8);
6129 header.write_shift(4, sst.Count);
6130 header.write_shift(4, sst.Unique);
6131 var strs = [];
6132 for(var j = 0; j < sst.length; ++j) strs[j] = write_XLUnicodeRichExtendedString(sst[j], opts);
6133 var o = bconcat([header].concat(strs));
6134o.parts = [header.length].concat(strs.map(function(str) { return str.length; }));
6135 return o;
6136}
6137
6138/* [MS-XLS] 2.4.107 */
6139function parse_ExtSST(blob, length) {
6140 var extsst = {};
6141 extsst.dsst = blob.read_shift(2);
6142 blob.l += length-2;
6143 return extsst;
6144}
6145
6146
6147/* [MS-XLS] 2.4.221 TODO: check BIFF2-4 */
6148function parse_Row(blob) {
6149 var z = ({});
6150 z.r = blob.read_shift(2);
6151 z.c = blob.read_shift(2);
6152 z.cnt = blob.read_shift(2) - z.c;
6153 var miyRw = blob.read_shift(2);
6154 blob.l += 4; // reserved(2), unused(2)
6155 var flags = blob.read_shift(1); // various flags
6156 blob.l += 3; // reserved(8), ixfe(12), flags(4)
6157 if(flags & 0x07) z.level = flags & 0x07;
6158 // collapsed: flags & 0x10
6159 if(flags & 0x20) z.hidden = true;
6160 if(flags & 0x40) z.hpt = miyRw / 20;
6161 return z;
6162}
6163
6164
6165/* [MS-XLS] 2.4.125 */
6166function parse_ForceFullCalculation(blob) {
6167 var header = parse_frtHeader(blob);
6168 if(header.type != 0x08A3) throw new Error("Invalid Future Record " + header.type);
6169 var fullcalc = blob.read_shift(4);
6170 return fullcalc !== 0x0;
6171}
6172
6173
6174
6175
6176
6177/* [MS-XLS] 2.4.215 rt */
6178function parse_RecalcId(blob) {
6179 blob.read_shift(2);
6180 return blob.read_shift(4);
6181}
6182
6183/* [MS-XLS] 2.4.87 */
6184function parse_DefaultRowHeight(blob, length, opts) {
6185 var f = 0;
6186 if(!(opts && opts.biff == 2)) {
6187 f = blob.read_shift(2);
6188 }
6189 var miyRw = blob.read_shift(2);
6190 if((opts && opts.biff == 2)) {
6191 f = 1 - (miyRw >> 15); miyRw &= 0x7fff;
6192 }
6193 var fl = {Unsynced:f&1,DyZero:(f&2)>>1,ExAsc:(f&4)>>2,ExDsc:(f&8)>>3};
6194 return [fl, miyRw];
6195}
6196
6197/* [MS-XLS] 2.4.345 TODO */
6198function parse_Window1(blob) {
6199 var xWn = blob.read_shift(2), yWn = blob.read_shift(2), dxWn = blob.read_shift(2), dyWn = blob.read_shift(2);
6200 var flags = blob.read_shift(2), iTabCur = blob.read_shift(2), iTabFirst = blob.read_shift(2);
6201 var ctabSel = blob.read_shift(2), wTabRatio = blob.read_shift(2);
6202 return { Pos: [xWn, yWn], Dim: [dxWn, dyWn], Flags: flags, CurTab: iTabCur,
6203 FirstTab: iTabFirst, Selected: ctabSel, TabRatio: wTabRatio };
6204}
6205function write_Window1() {
6206 var o = new_buf(18);
6207 o.write_shift(2, 0);
6208 o.write_shift(2, 0);
6209 o.write_shift(2, 0x7260);
6210 o.write_shift(2, 0x44c0);
6211 o.write_shift(2, 0x38);
6212 o.write_shift(2, 0);
6213 o.write_shift(2, 0);
6214 o.write_shift(2, 1);
6215 o.write_shift(2, 0x01f4);
6216 return o;
6217}
6218/* [MS-XLS] 2.4.346 TODO */
6219function parse_Window2(blob, length, opts) {
6220 if(opts && opts.biff >= 2 && opts.biff < 5) return {};
6221 var f = blob.read_shift(2);
6222 return { RTL: f & 0x40 };
6223}
6224function write_Window2(view) {
6225 var o = new_buf(18), f = 0x6b6;
6226 if(view && view.RTL) f |= 0x40;
6227 o.write_shift(2, f);
6228 o.write_shift(4, 0);
6229 o.write_shift(4, 64);
6230 o.write_shift(4, 0);
6231 o.write_shift(4, 0);
6232 return o;
6233}
6234
6235/* [MS-XLS] 2.4.189 TODO */
6236function parse_Pane(/*blob, length, opts*/) {
6237}
6238
6239/* [MS-XLS] 2.4.122 TODO */
6240function parse_Font(blob, length, opts) {
6241 var o = {
6242 dyHeight: blob.read_shift(2),
6243 fl: blob.read_shift(2)
6244 };
6245 switch((opts && opts.biff) || 8) {
6246 case 2: break;
6247 case 3: case 4: blob.l += 2; break;
6248 default: blob.l += 10; break;
6249 }
6250 o.name = parse_ShortXLUnicodeString(blob, 0, opts);
6251 return o;
6252}
6253function write_Font(data, opts) {
6254 var name = data.name || "Arial";
6255 var b5 = (opts && (opts.biff == 5)), w = (b5 ? (15 + name.length) : (16 + 2 * name.length));
6256 var o = new_buf(w);
6257 o.write_shift(2, (data.sz || 12) * 20);
6258 o.write_shift(4, 0);
6259 o.write_shift(2, 400);
6260 o.write_shift(4, 0);
6261 o.write_shift(2, 0);
6262 o.write_shift(1, name.length);
6263 if(!b5) o.write_shift(1, 1);
6264 o.write_shift((b5 ? 1 : 2) * name.length, name, (b5 ? "sbcs" : "utf16le"));
6265 return o;
6266}
6267
6268/* [MS-XLS] 2.4.149 */
6269function parse_LabelSst(blob) {
6270 var cell = parse_XLSCell(blob);
6271 cell.isst = blob.read_shift(4);
6272 return cell;
6273}
6274function write_LabelSst(R, C, v, os ) {
6275 var o = new_buf(10);
6276 write_XLSCell(R, C, os, o);
6277 o.write_shift(4, v);
6278 return o;
6279}
6280
6281/* [MS-XLS] 2.4.148 */
6282function parse_Label(blob, length, opts) {
6283 if(opts.biffguess && opts.biff == 2) opts.biff = 5;
6284 var target = blob.l + length;
6285 var cell = parse_XLSCell(blob, 6);
6286 if(opts.biff == 2) blob.l++;
6287 var str = parse_XLUnicodeString(blob, target - blob.l, opts);
6288 cell.val = str;
6289 return cell;
6290}
6291function write_Label(R, C, v, os, opts) {
6292 var b8 = !opts || opts.biff == 8;
6293 var o = new_buf(6 + 2 + (+b8) + (1 + b8) * v.length);
6294 write_XLSCell(R, C, os, o);
6295 o.write_shift(2, v.length);
6296 if(b8) o.write_shift(1, 1);
6297 o.write_shift((1 + b8) * v.length, v, b8 ? 'utf16le' : 'sbcs');
6298 return o;
6299}
6300
6301
6302/* [MS-XLS] 2.4.126 Number Formats */
6303function parse_Format(blob, length, opts) {
6304 var numFmtId = blob.read_shift(2);
6305 var fmtstr = parse_XLUnicodeString2(blob, 0, opts);
6306 return [numFmtId, fmtstr];
6307}
6308function write_Format(i, f, opts, o) {
6309 var b5 = (opts && (opts.biff == 5));
6310 if(!o) o = new_buf(b5 ? (3 + f.length) : (5 + 2 * f.length));
6311 o.write_shift(2, i);
6312 o.write_shift((b5 ? 1 : 2), f.length);
6313 if(!b5) o.write_shift(1, 1);
6314 o.write_shift((b5 ? 1 : 2) * f.length, f, (b5 ? 'sbcs' : 'utf16le'));
6315 var out = (o.length > o.l) ? o.slice(0, o.l) : o;
6316 if(out.l == null) out.l = out.length;
6317 return out;
6318}
6319var parse_BIFF2Format = parse_XLUnicodeString2;
6320
6321/* [MS-XLS] 2.4.90 */
6322function parse_Dimensions(blob, length, opts) {
6323 var end = blob.l + length;
6324 var w = opts.biff == 8 || !opts.biff ? 4 : 2;
6325 var r = blob.read_shift(w), R = blob.read_shift(w);
6326 var c = blob.read_shift(2), C = blob.read_shift(2);
6327 blob.l = end;
6328 return {s: {r:r, c:c}, e: {r:R, c:C}};
6329}
6330function write_Dimensions(range, opts) {
6331 var w = opts.biff == 8 || !opts.biff ? 4 : 2;
6332 var o = new_buf(2*w + 6);
6333 o.write_shift(w, range.s.r);
6334 o.write_shift(w, range.e.r + 1);
6335 o.write_shift(2, range.s.c);
6336 o.write_shift(2, range.e.c + 1);
6337 o.write_shift(2, 0);
6338 return o;
6339}
6340
6341/* [MS-XLS] 2.4.220 */
6342function parse_RK(blob) {
6343 var rw = blob.read_shift(2), col = blob.read_shift(2);
6344 var rkrec = parse_RkRec(blob);
6345 return {r:rw, c:col, ixfe:rkrec[0], rknum:rkrec[1]};
6346}
6347
6348/* [MS-XLS] 2.4.175 */
6349function parse_MulRk(blob, length) {
6350 var target = blob.l + length - 2;
6351 var rw = blob.read_shift(2), col = blob.read_shift(2);
6352 var rkrecs = [];
6353 while(blob.l < target) rkrecs.push(parse_RkRec(blob));
6354 if(blob.l !== target) throw new Error("MulRK read error");
6355 var lastcol = blob.read_shift(2);
6356 if(rkrecs.length != lastcol - col + 1) throw new Error("MulRK length mismatch");
6357 return {r:rw, c:col, C:lastcol, rkrec:rkrecs};
6358}
6359/* [MS-XLS] 2.4.174 */
6360function parse_MulBlank(blob, length) {
6361 var target = blob.l + length - 2;
6362 var rw = blob.read_shift(2), col = blob.read_shift(2);
6363 var ixfes = [];
6364 while(blob.l < target) ixfes.push(blob.read_shift(2));
6365 if(blob.l !== target) throw new Error("MulBlank read error");
6366 var lastcol = blob.read_shift(2);
6367 if(ixfes.length != lastcol - col + 1) throw new Error("MulBlank length mismatch");
6368 return {r:rw, c:col, C:lastcol, ixfe:ixfes};
6369}
6370
6371/* [MS-XLS] 2.5.20 2.5.249 TODO: interpret values here */
6372function parse_CellStyleXF(blob, length, style, opts) {
6373 var o = {};
6374 var a = blob.read_shift(4), b = blob.read_shift(4);
6375 var c = blob.read_shift(4), d = blob.read_shift(2);
6376 o.patternType = XLSFillPattern[c >> 26];
6377
6378 if(!opts.cellStyles) return o;
6379 o.alc = a & 0x07;
6380 o.fWrap = (a >> 3) & 0x01;
6381 o.alcV = (a >> 4) & 0x07;
6382 o.fJustLast = (a >> 7) & 0x01;
6383 o.trot = (a >> 8) & 0xFF;
6384 o.cIndent = (a >> 16) & 0x0F;
6385 o.fShrinkToFit = (a >> 20) & 0x01;
6386 o.iReadOrder = (a >> 22) & 0x02;
6387 o.fAtrNum = (a >> 26) & 0x01;
6388 o.fAtrFnt = (a >> 27) & 0x01;
6389 o.fAtrAlc = (a >> 28) & 0x01;
6390 o.fAtrBdr = (a >> 29) & 0x01;
6391 o.fAtrPat = (a >> 30) & 0x01;
6392 o.fAtrProt = (a >> 31) & 0x01;
6393
6394 o.dgLeft = b & 0x0F;
6395 o.dgRight = (b >> 4) & 0x0F;
6396 o.dgTop = (b >> 8) & 0x0F;
6397 o.dgBottom = (b >> 12) & 0x0F;
6398 o.icvLeft = (b >> 16) & 0x7F;
6399 o.icvRight = (b >> 23) & 0x7F;
6400 o.grbitDiag = (b >> 30) & 0x03;
6401
6402 o.icvTop = c & 0x7F;
6403 o.icvBottom = (c >> 7) & 0x7F;
6404 o.icvDiag = (c >> 14) & 0x7F;
6405 o.dgDiag = (c >> 21) & 0x0F;
6406
6407 o.icvFore = d & 0x7F;
6408 o.icvBack = (d >> 7) & 0x7F;
6409 o.fsxButton = (d >> 14) & 0x01;
6410 return o;
6411}
6412//function parse_CellXF(blob, length, opts) {return parse_CellStyleXF(blob,length,0, opts);}
6413//function parse_StyleXF(blob, length, opts) {return parse_CellStyleXF(blob,length,1, opts);}
6414
6415/* [MS-XLS] 2.4.353 TODO: actually do this right */
6416function parse_XF(blob, length, opts) {
6417 var o = {};
6418 o.ifnt = blob.read_shift(2); o.numFmtId = blob.read_shift(2); o.flags = blob.read_shift(2);
6419 o.fStyle = (o.flags >> 2) & 0x01;
6420 length -= 6;
6421 o.data = parse_CellStyleXF(blob, length, o.fStyle, opts);
6422 return o;
6423}
6424function write_XF(data, ixfeP, opts, o) {
6425 var b5 = (opts && (opts.biff == 5));
6426 if(!o) o = new_buf(b5 ? 16 : 20);
6427 o.write_shift(2, 0);
6428 if(data.style) {
6429 o.write_shift(2, (data.numFmtId||0));
6430 o.write_shift(2, 0xFFF4);
6431 } else {
6432 o.write_shift(2, (data.numFmtId||0));
6433 o.write_shift(2, (ixfeP<<4));
6434 }
6435 var f = 0;
6436 if(data.numFmtId > 0 && b5) f |= 0x0400;
6437 o.write_shift(4, f);
6438 o.write_shift(4, 0);
6439 if(!b5) o.write_shift(4, 0);
6440 o.write_shift(2, 0);
6441 return o;
6442}
6443
6444/* [MS-XLS] 2.4.134 */
6445function parse_Guts(blob) {
6446 blob.l += 4;
6447 var out = [blob.read_shift(2), blob.read_shift(2)];
6448 if(out[0] !== 0) out[0]--;
6449 if(out[1] !== 0) out[1]--;
6450 if(out[0] > 7 || out[1] > 7) throw new Error("Bad Gutters: " + out.join("|"));
6451 return out;
6452}
6453function write_Guts(guts) {
6454 var o = new_buf(8);
6455 o.write_shift(4, 0);
6456 o.write_shift(2, guts[0] ? guts[0] + 1 : 0);
6457 o.write_shift(2, guts[1] ? guts[1] + 1 : 0);
6458 return o;
6459}
6460
6461/* [MS-XLS] 2.4.24 */
6462function parse_BoolErr(blob, length, opts) {
6463 var cell = parse_XLSCell(blob, 6);
6464 if(opts.biff == 2 || length == 9) ++blob.l;
6465 var val = parse_Bes(blob, 2);
6466 cell.val = val;
6467 cell.t = (val === true || val === false) ? 'b' : 'e';
6468 return cell;
6469}
6470function write_BoolErr(R, C, v, os, opts, t) {
6471 var o = new_buf(8);
6472 write_XLSCell(R, C, os, o);
6473 write_Bes(v, t, o);
6474 return o;
6475}
6476
6477/* [MS-XLS] 2.4.180 Number */
6478function parse_Number(blob, length, opts) {
6479 if(opts.biffguess && opts.biff == 2) opts.biff = 5;
6480 var cell = parse_XLSCell(blob, 6);
6481 var xnum = parse_Xnum(blob, 8);
6482 cell.val = xnum;
6483 return cell;
6484}
6485function write_Number(R, C, v, os) {
6486 var o = new_buf(14);
6487 write_XLSCell(R, C, os, o);
6488 write_Xnum(v, o);
6489 return o;
6490}
6491
6492var parse_XLHeaderFooter = parse_OptXLUnicodeString; // TODO: parse 2.4.136
6493
6494/* [MS-XLS] 2.4.271 */
6495function parse_SupBook(blob, length, opts) {
6496 var end = blob.l + length;
6497 var ctab = blob.read_shift(2);
6498 var cch = blob.read_shift(2);
6499 opts.sbcch = cch;
6500 if(cch == 0x0401 || cch == 0x3A01) return [cch, ctab];
6501 if(cch < 0x01 || cch >0xff) throw new Error("Unexpected SupBook type: "+cch);
6502 var virtPath = parse_XLUnicodeStringNoCch(blob, cch);
6503 /* TODO: 2.5.277 Virtual Path */
6504 var rgst = [];
6505 while(end > blob.l) rgst.push(parse_XLUnicodeString(blob));
6506 return [cch, ctab, virtPath, rgst];
6507}
6508
6509/* [MS-XLS] 2.4.105 TODO */
6510function parse_ExternName(blob, length, opts) {
6511 var flags = blob.read_shift(2);
6512 var body;
6513 var o = ({
6514 fBuiltIn: flags & 0x01,
6515 fWantAdvise: (flags >>> 1) & 0x01,
6516 fWantPict: (flags >>> 2) & 0x01,
6517 fOle: (flags >>> 3) & 0x01,
6518 fOleLink: (flags >>> 4) & 0x01,
6519 cf: (flags >>> 5) & 0x3FF,
6520 fIcon: flags >>> 15 & 0x01
6521 });
6522 if(opts.sbcch === 0x3A01) body = parse_AddinUdf(blob, length-2, opts);
6523 //else throw new Error("unsupported SupBook cch: " + opts.sbcch);
6524 o.body = body || blob.read_shift(length-2);
6525 if(typeof body === "string") o.Name = body;
6526 return o;
6527}
6528
6529/* [MS-XLS] 2.4.150 TODO */
6530var XLSLblBuiltIn = [
6531 "_xlnm.Consolidate_Area",
6532 "_xlnm.Auto_Open",
6533 "_xlnm.Auto_Close",
6534 "_xlnm.Extract",
6535 "_xlnm.Database",
6536 "_xlnm.Criteria",
6537 "_xlnm.Print_Area",
6538 "_xlnm.Print_Titles",
6539 "_xlnm.Recorder",
6540 "_xlnm.Data_Form",
6541 "_xlnm.Auto_Activate",
6542 "_xlnm.Auto_Deactivate",
6543 "_xlnm.Sheet_Title",
6544 "_xlnm._FilterDatabase"
6545];
6546function parse_Lbl(blob, length, opts) {
6547 var target = blob.l + length;
6548 var flags = blob.read_shift(2);
6549 var chKey = blob.read_shift(1);
6550 var cch = blob.read_shift(1);
6551 var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
6552 var itab = 0;
6553 if(!opts || opts.biff >= 5) {
6554 if(opts.biff != 5) blob.l += 2;
6555 itab = blob.read_shift(2);
6556 if(opts.biff == 5) blob.l += 2;
6557 blob.l += 4;
6558 }
6559 var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
6560 if(flags & 0x20) name = XLSLblBuiltIn[name.charCodeAt(0)];
6561 var npflen = target - blob.l; if(opts && opts.biff == 2) --npflen;
6562 var rgce = (target == blob.l || cce === 0 || !(npflen > 0)) ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
6563 return {
6564 chKey: chKey,
6565 Name: name,
6566 itab: itab,
6567 rgce: rgce
6568 };
6569}
6570
6571/* [MS-XLS] 2.4.106 TODO: verify filename encoding */
6572function parse_ExternSheet(blob, length, opts) {
6573 if(opts.biff < 8) return parse_BIFF5ExternSheet(blob, length, opts);
6574 var o = [], target = blob.l + length, len = blob.read_shift(opts.biff > 8 ? 4 : 2);
6575 while(len-- !== 0) o.push(parse_XTI(blob, opts.biff > 8 ? 12 : 6, opts));
6576 // [iSupBook, itabFirst, itabLast];
6577 if(blob.l != target) throw new Error("Bad ExternSheet: " + blob.l + " != " + target);
6578 return o;
6579}
6580function parse_BIFF5ExternSheet(blob, length, opts) {
6581 if(blob[blob.l + 1] == 0x03) blob[blob.l]++;
6582 var o = parse_ShortXLUnicodeString(blob, length, opts);
6583 return o.charCodeAt(0) == 0x03 ? o.slice(1) : o;
6584}
6585
6586/* [MS-XLS] 2.4.176 TODO: check older biff */
6587function parse_NameCmt(blob, length, opts) {
6588 if(opts.biff < 8) { blob.l += length; return; }
6589 var cchName = blob.read_shift(2);
6590 var cchComment = blob.read_shift(2);
6591 var name = parse_XLUnicodeStringNoCch(blob, cchName, opts);
6592 var comment = parse_XLUnicodeStringNoCch(blob, cchComment, opts);
6593 return [name, comment];
6594}
6595
6596/* [MS-XLS] 2.4.260 */
6597function parse_ShrFmla(blob, length, opts) {
6598 var ref = parse_RefU(blob, 6);
6599 blob.l++;
6600 var cUse = blob.read_shift(1);
6601 length -= 8;
6602 return [parse_SharedParsedFormula(blob, length, opts), cUse, ref];
6603}
6604
6605/* [MS-XLS] 2.4.4 TODO */
6606function parse_Array(blob, length, opts) {
6607 var ref = parse_Ref(blob, 6);
6608 /* TODO: fAlwaysCalc */
6609 switch(opts.biff) {
6610 case 2: blob.l ++; length -= 7; break;
6611 case 3: case 4: blob.l += 2; length -= 8; break;
6612 default: blob.l += 6; length -= 12;
6613 }
6614 return [ref, parse_ArrayParsedFormula(blob, length, opts, ref)];
6615}
6616
6617/* [MS-XLS] 2.4.173 */
6618function parse_MTRSettings(blob) {
6619 var fMTREnabled = blob.read_shift(4) !== 0x00;
6620 var fUserSetThreadCount = blob.read_shift(4) !== 0x00;
6621 var cUserThreadCount = blob.read_shift(4);
6622 return [fMTREnabled, fUserSetThreadCount, cUserThreadCount];
6623}
6624
6625/* [MS-XLS] 2.5.186 TODO: BIFF5 */
6626function parse_NoteSh(blob, length, opts) {
6627 if(opts.biff < 8) return;
6628 var row = blob.read_shift(2), col = blob.read_shift(2);
6629 var flags = blob.read_shift(2), idObj = blob.read_shift(2);
6630 var stAuthor = parse_XLUnicodeString2(blob, 0, opts);
6631 if(opts.biff < 8) blob.read_shift(1);
6632 return [{r:row,c:col}, stAuthor, idObj, flags];
6633}
6634
6635/* [MS-XLS] 2.4.179 */
6636function parse_Note(blob, length, opts) {
6637 /* TODO: Support revisions */
6638 return parse_NoteSh(blob, length, opts);
6639}
6640
6641/* [MS-XLS] 2.4.168 */
6642function parse_MergeCells(blob, length) {
6643 var merges = [];
6644 var cmcs = blob.read_shift(2);
6645 while (cmcs--) merges.push(parse_Ref8U(blob,length));
6646 return merges;
6647}
6648function write_MergeCells(merges) {
6649 var o = new_buf(2 + merges.length * 8);
6650 o.write_shift(2, merges.length);
6651 for(var i = 0; i < merges.length; ++i) write_Ref8U(merges[i], o);
6652 return o;
6653}
6654
6655/* [MS-XLS] 2.4.181 TODO: parse all the things! */
6656function parse_Obj(blob, length, opts) {
6657 if(opts && opts.biff < 8) return parse_BIFF5Obj(blob, length, opts);
6658 var cmo = parse_FtCmo(blob, 22); // id, ot, flags
6659 var fts = parse_FtArray(blob, length-22, cmo[1]);
6660 return { cmo: cmo, ft:fts };
6661}
6662/* from older spec */
6663var parse_BIFF5OT = [];
6664parse_BIFF5OT[0x08] = function(blob, length) {
6665 var tgt = blob.l + length;
6666 blob.l += 10; // todo
6667 var cf = blob.read_shift(2);
6668 blob.l += 4;
6669 blob.l += 2; //var cbPictFmla = blob.read_shift(2);
6670 blob.l += 2;
6671 blob.l += 2; //var grbit = blob.read_shift(2);
6672 blob.l += 4;
6673 var cchName = blob.read_shift(1);
6674 blob.l += cchName; // TODO: stName
6675 blob.l = tgt; // TODO: fmla
6676 return { fmt:cf };
6677};
6678
6679function parse_BIFF5Obj(blob, length, opts) {
6680 blob.l += 4; //var cnt = blob.read_shift(4);
6681 var ot = blob.read_shift(2);
6682 var id = blob.read_shift(2);
6683 var grbit = blob.read_shift(2);
6684 blob.l += 2; //var colL = blob.read_shift(2);
6685 blob.l += 2; //var dxL = blob.read_shift(2);
6686 blob.l += 2; //var rwT = blob.read_shift(2);
6687 blob.l += 2; //var dyT = blob.read_shift(2);
6688 blob.l += 2; //var colR = blob.read_shift(2);
6689 blob.l += 2; //var dxR = blob.read_shift(2);
6690 blob.l += 2; //var rwB = blob.read_shift(2);
6691 blob.l += 2; //var dyB = blob.read_shift(2);
6692 blob.l += 2; //var cbMacro = blob.read_shift(2);
6693 blob.l += 6;
6694 length -= 36;
6695 var fts = [];
6696 fts.push((parse_BIFF5OT[ot]||parsenoop)(blob, length, opts));
6697 return { cmo: [id, ot, grbit], ft:fts };
6698}
6699
6700/* [MS-XLS] 2.4.329 TODO: parse properly */
6701function parse_TxO(blob, length, opts) {
6702 var s = blob.l;
6703 var texts = "";
6704try {
6705 blob.l += 4;
6706 var ot = (opts.lastobj||{cmo:[0,0]}).cmo[1];
6707 var controlInfo; // eslint-disable-line no-unused-vars
6708 if([0,5,7,11,12,14].indexOf(ot) == -1) blob.l += 6;
6709 else controlInfo = parse_ControlInfo(blob, 6, opts);
6710 var cchText = blob.read_shift(2);
6711 /*var cbRuns = */blob.read_shift(2);
6712 /*var ifntEmpty = */parseuint16(blob, 2);
6713 var len = blob.read_shift(2);
6714 blob.l += len;
6715 //var fmla = parse_ObjFmla(blob, s + length - blob.l);
6716
6717 for(var i = 1; i < blob.lens.length-1; ++i) {
6718 if(blob.l-s != blob.lens[i]) throw new Error("TxO: bad continue record");
6719 var hdr = blob[blob.l];
6720 var t = parse_XLUnicodeStringNoCch(blob, blob.lens[i+1]-blob.lens[i]-1);
6721 texts += t;
6722 if(texts.length >= (hdr ? cchText : 2*cchText)) break;
6723 }
6724 if(texts.length !== cchText && texts.length !== cchText*2) {
6725 throw new Error("cchText: " + cchText + " != " + texts.length);
6726 }
6727
6728 blob.l = s + length;
6729 /* [MS-XLS] 2.5.272 TxORuns */
6730// var rgTxoRuns = [];
6731// for(var j = 0; j != cbRuns/8-1; ++j) blob.l += 8;
6732// var cchText2 = blob.read_shift(2);
6733// if(cchText2 !== cchText) throw new Error("TxOLastRun mismatch: " + cchText2 + " " + cchText);
6734// blob.l += 6;
6735// if(s + length != blob.l) throw new Error("TxO " + (s + length) + ", at " + blob.l);
6736 return { t: texts };
6737} catch(e) { blob.l = s + length; return { t: texts }; }
6738}
6739
6740/* [MS-XLS] 2.4.140 */
6741function parse_HLink(blob, length) {
6742 var ref = parse_Ref8U(blob, 8);
6743 blob.l += 16; /* CLSID */
6744 var hlink = parse_Hyperlink(blob, length-24);
6745 return [ref, hlink];
6746}
6747function write_HLink(hl) {
6748 var O = new_buf(24);
6749 var ref = decode_cell(hl[0]);
6750 O.write_shift(2, ref.r); O.write_shift(2, ref.r);
6751 O.write_shift(2, ref.c); O.write_shift(2, ref.c);
6752 var clsid = "d0 c9 ea 79 f9 ba ce 11 8c 82 00 aa 00 4b a9 0b".split(" ");
6753 for(var i = 0; i < 16; ++i) O.write_shift(1, parseInt(clsid[i], 16));
6754 return bconcat([O, write_Hyperlink(hl[1])]);
6755}
6756
6757
6758/* [MS-XLS] 2.4.141 */
6759function parse_HLinkTooltip(blob, length) {
6760 blob.read_shift(2);
6761 var ref = parse_Ref8U(blob, 8);
6762 var wzTooltip = blob.read_shift((length-10)/2, 'dbcs-cont');
6763 wzTooltip = wzTooltip.replace(chr0,"");
6764 return [ref, wzTooltip];
6765}
6766function write_HLinkTooltip(hl) {
6767 var TT = hl[1].Tooltip;
6768 var O = new_buf(10 + 2 * (TT.length + 1));
6769 O.write_shift(2, 0x0800);
6770 var ref = decode_cell(hl[0]);
6771 O.write_shift(2, ref.r); O.write_shift(2, ref.r);
6772 O.write_shift(2, ref.c); O.write_shift(2, ref.c);
6773 for(var i = 0; i < TT.length; ++i) O.write_shift(2, TT.charCodeAt(i));
6774 O.write_shift(2, 0);
6775 return O;
6776}
6777
6778/* [MS-XLS] 2.4.63 */
6779function parse_Country(blob) {
6780 var o = [0,0], d;
6781 d = blob.read_shift(2); o[0] = CountryEnum[d] || d;
6782 d = blob.read_shift(2); o[1] = CountryEnum[d] || d;
6783 return o;
6784}
6785function write_Country(o) {
6786 if(!o) o = new_buf(4);
6787 o.write_shift(2, 0x01);
6788 o.write_shift(2, 0x01);
6789 return o;
6790}
6791
6792/* [MS-XLS] 2.4.50 ClrtClient */
6793function parse_ClrtClient(blob) {
6794 var ccv = blob.read_shift(2);
6795 var o = [];
6796 while(ccv-->0) o.push(parse_LongRGB(blob, 8));
6797 return o;
6798}
6799
6800/* [MS-XLS] 2.4.188 */
6801function parse_Palette(blob) {
6802 var ccv = blob.read_shift(2);
6803 var o = [];
6804 while(ccv-->0) o.push(parse_LongRGB(blob, 8));
6805 return o;
6806}
6807
6808/* [MS-XLS] 2.4.354 */
6809function parse_XFCRC(blob) {
6810 blob.l += 2;
6811 var o = {cxfs:0, crc:0};
6812 o.cxfs = blob.read_shift(2);
6813 o.crc = blob.read_shift(4);
6814 return o;
6815}
6816
6817/* [MS-XLS] 2.4.53 TODO: parse flags */
6818/* [MS-XLSB] 2.4.323 TODO: parse flags */
6819function parse_ColInfo(blob, length, opts) {
6820 if(!opts.cellStyles) return parsenoop(blob, length);
6821 var w = opts && opts.biff >= 12 ? 4 : 2;
6822 var colFirst = blob.read_shift(w);
6823 var colLast = blob.read_shift(w);
6824 var coldx = blob.read_shift(w);
6825 var ixfe = blob.read_shift(w);
6826 var flags = blob.read_shift(2);
6827 if(w == 2) blob.l += 2;
6828 var o = ({s:colFirst, e:colLast, w:coldx, ixfe:ixfe, flags:flags});
6829 if(opts.biff >= 5 || !opts.biff) o.level = (flags >> 8) & 0x7;
6830 return o;
6831}
6832function write_ColInfo(col, idx) {
6833 var o = new_buf(12);
6834 o.write_shift(2, idx);
6835 o.write_shift(2, idx);
6836 o.write_shift(2, col.width * 256);
6837 o.write_shift(2, 0);
6838 var f = 0;
6839 if(col.hidden) f |= 1;
6840 o.write_shift(1, f);
6841 f = col.level || 0;
6842 o.write_shift(1, f);
6843 o.write_shift(2, 0);
6844 return o;
6845}
6846
6847/* [MS-XLS] 2.4.257 */
6848function parse_Setup(blob, length) {
6849 var o = {};
6850 if(length < 32) return o;
6851 blob.l += 16;
6852 o.header = parse_Xnum(blob, 8);
6853 o.footer = parse_Xnum(blob, 8);
6854 blob.l += 2;
6855 return o;
6856}
6857
6858/* [MS-XLS] 2.4.261 */
6859function parse_ShtProps(blob, length, opts) {
6860 var def = {area:false};
6861 if(opts.biff != 5) { blob.l += length; return def; }
6862 var d = blob.read_shift(1); blob.l += 3;
6863 if((d & 0x10)) def.area = true;
6864 return def;
6865}
6866
6867/* [MS-XLS] 2.4.241 */
6868function write_RRTabId(n) {
6869 var out = new_buf(2 * n);
6870 for(var i = 0; i < n; ++i) out.write_shift(2, i+1);
6871 return out;
6872}
6873
6874var parse_Blank = parse_XLSCell; /* [MS-XLS] 2.4.20 Just the cell */
6875var parse_Scl = parseuint16a; /* [MS-XLS] 2.4.247 num, den */
6876var parse_String = parse_XLUnicodeString; /* [MS-XLS] 2.4.268 */
6877
6878/* --- Specific to versions before BIFF8 --- */
6879function parse_ImData(blob) {
6880 var cf = blob.read_shift(2);
6881 var env = blob.read_shift(2);
6882 var lcb = blob.read_shift(4);
6883 var o = {fmt:cf, env:env, len:lcb, data:blob.slice(blob.l,blob.l+lcb)};
6884 blob.l += lcb;
6885 return o;
6886}
6887
6888/* BIFF2_??? where ??? is the name from [XLS] */
6889function parse_BIFF2STR(blob, length, opts) {
6890 if(opts.biffguess && opts.biff == 5) opts.biff = 2;
6891 var cell = parse_XLSCell(blob, 6);
6892 ++blob.l;
6893 var str = parse_XLUnicodeString2(blob, length-7, opts);
6894 cell.t = 'str';
6895 cell.val = str;
6896 return cell;
6897}
6898
6899function parse_BIFF2NUM(blob) {
6900 var cell = parse_XLSCell(blob, 6);
6901 ++blob.l;
6902 var num = parse_Xnum(blob, 8);
6903 cell.t = 'n';
6904 cell.val = num;
6905 return cell;
6906}
6907function write_BIFF2NUM(r, c, val) {
6908 var out = new_buf(15);
6909 write_BIFF2Cell(out, r, c);
6910 out.write_shift(8, val, 'f');
6911 return out;
6912}
6913
6914function parse_BIFF2INT(blob) {
6915 var cell = parse_XLSCell(blob, 6);
6916 ++blob.l;
6917 var num = blob.read_shift(2);
6918 cell.t = 'n';
6919 cell.val = num;
6920 return cell;
6921}
6922function write_BIFF2INT(r, c, val) {
6923 var out = new_buf(9);
6924 write_BIFF2Cell(out, r, c);
6925 out.write_shift(2, val);
6926 return out;
6927}
6928
6929function parse_BIFF2STRING(blob) {
6930 var cch = blob.read_shift(1);
6931 if(cch === 0) { blob.l++; return ""; }
6932 return blob.read_shift(cch, 'sbcs-cont');
6933}
6934
6935/* TODO: convert to BIFF8 font struct */
6936function parse_BIFF2FONTXTRA(blob, length) {
6937 blob.l += 6; // unknown
6938 blob.l += 2; // font weight "bls"
6939 blob.l += 1; // charset
6940 blob.l += 3; // unknown
6941 blob.l += 1; // font family
6942 blob.l += length - 13;
6943}
6944
6945/* TODO: parse rich text runs */
6946function parse_RString(blob, length, opts) {
6947 var end = blob.l + length;
6948 var cell = parse_XLSCell(blob, 6);
6949 var cch = blob.read_shift(2);
6950 var str = parse_XLUnicodeStringNoCch(blob, cch, opts);
6951 blob.l = end;
6952 cell.t = 'str';
6953 cell.val = str;
6954 return cell;
6955}
6956/* from js-harb (C) 2014-present SheetJS */
6957var DBF = (function() {
6958var dbf_codepage_map = {
6959 /* Code Pages Supported by Visual FoxPro */
69600x01: 437, 0x02: 850,
69610x03: 1252, 0x04: 10000,
69620x64: 852, 0x65: 866,
69630x66: 865, 0x67: 861,
69640x68: 895, 0x69: 620,
69650x6A: 737, 0x6B: 857,
69660x78: 950, 0x79: 949,
69670x7A: 936, 0x7B: 932,
69680x7C: 874, 0x7D: 1255,
69690x7E: 1256, 0x96: 10007,
69700x97: 10029, 0x98: 10006,
69710xC8: 1250, 0xC9: 1251,
69720xCA: 1254, 0xCB: 1253,
6973
6974 /* shapefile DBF extension */
69750x00: 20127, 0x08: 865,
69760x09: 437, 0x0A: 850,
69770x0B: 437, 0x0D: 437,
69780x0E: 850, 0x0F: 437,
69790x10: 850, 0x11: 437,
69800x12: 850, 0x13: 932,
69810x14: 850, 0x15: 437,
69820x16: 850, 0x17: 865,
69830x18: 437, 0x19: 437,
69840x1A: 850, 0x1B: 437,
69850x1C: 863, 0x1D: 850,
69860x1F: 852, 0x22: 852,
69870x23: 852, 0x24: 860,
69880x25: 850, 0x26: 866,
69890x37: 850, 0x40: 852,
69900x4D: 936, 0x4E: 949,
69910x4F: 950, 0x50: 874,
69920x57: 1252, 0x58: 1252,
69930x59: 1252, 0x6C: 863,
69940x86: 737, 0x87: 852,
69950x88: 857, 0xCC: 1257,
6996
69970xFF: 16969
6998};
6999var dbf_reverse_map = evert({
70000x01: 437, 0x02: 850,
70010x03: 1252, 0x04: 10000,
70020x64: 852, 0x65: 866,
70030x66: 865, 0x67: 861,
70040x68: 895, 0x69: 620,
70050x6A: 737, 0x6B: 857,
70060x78: 950, 0x79: 949,
70070x7A: 936, 0x7B: 932,
70080x7C: 874, 0x7D: 1255,
70090x7E: 1256, 0x96: 10007,
70100x97: 10029, 0x98: 10006,
70110xC8: 1250, 0xC9: 1251,
70120xCA: 1254, 0xCB: 1253,
70130x00: 20127
7014});
7015var DBF_SUPPORTED_VERSIONS = [0x02, 0x03, 0x30, 0x31, 0x83, 0x8B, 0x8C, 0xF5];
7016/* TODO: find an actual specification */
7017function dbf_to_aoa(buf, opts) {
7018 var out = [];
7019 var d = (new_raw_buf(1));
7020 switch(opts.type) {
7021 case 'base64': d = s2a(Base64.decode(buf)); break;
7022 case 'binary': d = s2a(buf); break;
7023 case 'buffer':
7024 case 'array': d = buf; break;
7025 }
7026 prep_blob(d, 0);
7027
7028 /* header */
7029 var ft = d.read_shift(1);
7030 var memo = !!(ft & 0x88);
7031 var vfp = false, l7 = false;
7032 switch(ft) {
7033 case 0x02: break; // dBASE II
7034 case 0x03: break; // dBASE III
7035 case 0x30: vfp = true; memo = true; break; // VFP
7036 case 0x31: vfp = true; memo = true; break; // VFP with autoincrement
7037 // 0x43 dBASE IV SQL table files
7038 // 0x63 dBASE IV SQL system files
7039 case 0x83: break; // dBASE III with memo
7040 case 0x8B: break; // dBASE IV with memo
7041 case 0x8C: l7 = true; break; // dBASE Level 7 with memo
7042 // case 0xCB dBASE IV SQL table files with memo
7043 case 0xF5: break; // FoxPro 2.x with memo
7044 // case 0xFB FoxBASE
7045 default: throw new Error("DBF Unsupported Version: " + ft.toString(16));
7046 }
7047
7048 var nrow = 0, fpos = 0x0209;
7049 if(ft == 0x02) nrow = d.read_shift(2);
7050 d.l += 3; // dBASE II stores DDMMYY date, others use YYMMDD
7051 if(ft != 0x02) nrow = d.read_shift(4);
7052 if(nrow > 1048576) nrow = 1e6;
7053
7054 if(ft != 0x02) fpos = d.read_shift(2); // header length
7055 var rlen = d.read_shift(2); // record length
7056
7057 var /*flags = 0,*/ current_cp = opts.codepage || 1252;
7058 if(ft != 0x02) { // 20 reserved bytes
7059 d.l+=16;
7060 /*flags = */d.read_shift(1);
7061 //if(memo && ((flags & 0x02) === 0)) throw new Error("DBF Flags " + flags.toString(16) + " ft " + ft.toString(16));
7062
7063 /* codepage present in FoxPro and dBASE Level 7 */
7064 if(d[d.l] !== 0) current_cp = dbf_codepage_map[d[d.l]];
7065 d.l+=1;
7066
7067 d.l+=2;
7068 }
7069 if(l7) d.l += 36; // Level 7: 32 byte "Language driver name", 4 byte reserved
7070
7071var fields = [], field = ({});
7072 var hend = Math.min(d.length, (ft == 0x02 ? 0x209 : (fpos - 10 - (vfp ? 264 : 0))));
7073 var ww = l7 ? 32 : 11;
7074 while(d.l < hend && d[d.l] != 0x0d) {
7075 field = ({});
7076 field.name = cptable.utils.decode(current_cp, d.slice(d.l, d.l+ww)).replace(/[\u0000\r\n].*$/g,"");
7077 d.l += ww;
7078 field.type = String.fromCharCode(d.read_shift(1));
7079 if(ft != 0x02 && !l7) field.offset = d.read_shift(4);
7080 field.len = d.read_shift(1);
7081 if(ft == 0x02) field.offset = d.read_shift(2);
7082 field.dec = d.read_shift(1);
7083 if(field.name.length) fields.push(field);
7084 if(ft != 0x02) d.l += l7 ? 13 : 14;
7085 switch(field.type) {
7086 case 'B': // Double (VFP) / Binary (dBASE L7)
7087 if((!vfp || field.len != 8) && opts.WTF) console.log('Skipping ' + field.name + ':' + field.type);
7088 break;
7089 case 'G': // General (FoxPro and dBASE L7)
7090 case 'P': // Picture (FoxPro and dBASE L7)
7091 if(opts.WTF) console.log('Skipping ' + field.name + ':' + field.type);
7092 break;
7093 case '+': // Autoincrement (dBASE L7 only)
7094 case '0': // _NullFlags (VFP only)
7095 case '@': // Timestamp (dBASE L7 only)
7096 case 'C': // Character (dBASE II)
7097 case 'D': // Date (dBASE III)
7098 case 'F': // Float (dBASE IV)
7099 case 'I': // Long (VFP and dBASE L7)
7100 case 'L': // Logical (dBASE II)
7101 case 'M': // Memo (dBASE III)
7102 case 'N': // Number (dBASE II)
7103 case 'O': // Double (dBASE L7 only)
7104 case 'T': // Datetime (VFP only)
7105 case 'Y': // Currency (VFP only)
7106 break;
7107 default: throw new Error('Unknown Field Type: ' + field.type);
7108 }
7109 }
7110
7111 if(d[d.l] !== 0x0D) d.l = fpos-1;
7112 if(d.read_shift(1) !== 0x0D) throw new Error("DBF Terminator not found " + d.l + " " + d[d.l]);
7113 d.l = fpos;
7114
7115 /* data */
7116 var R = 0, C = 0;
7117 out[0] = [];
7118 for(C = 0; C != fields.length; ++C) out[0][C] = fields[C].name;
7119 while(nrow-- > 0) {
7120 if(d[d.l] === 0x2A) {
7121 // TODO: record marked as deleted -- create a hidden row?
7122 d.l+=rlen;
7123 continue;
7124 }
7125 ++d.l;
7126 out[++R] = []; C = 0;
7127 for(C = 0; C != fields.length; ++C) {
7128 var dd = d.slice(d.l, d.l+fields[C].len); d.l+=fields[C].len;
7129 prep_blob(dd, 0);
7130 var s = cptable.utils.decode(current_cp, dd);
7131 switch(fields[C].type) {
7132 case 'C':
7133 // NOTE: it is conventional to write ' / / ' for empty dates
7134 if(s.trim().length) out[R][C] = s.replace(/\s+$/,"");
7135 break;
7136 case 'D':
7137 if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8));
7138 else out[R][C] = s;
7139 break;
7140 case 'F': out[R][C] = parseFloat(s.trim()); break;
7141 case '+': case 'I': out[R][C] = l7 ? dd.read_shift(-4, 'i') ^ 0x80000000 : dd.read_shift(4, 'i'); break;
7142 case 'L': switch(s.trim().toUpperCase()) {
7143 case 'Y': case 'T': out[R][C] = true; break;
7144 case 'N': case 'F': out[R][C] = false; break;
7145 case '': case '?': break;
7146 default: throw new Error("DBF Unrecognized L:|" + s + "|");
7147 } break;
7148 case 'M': /* TODO: handle memo files */
7149 if(!memo) throw new Error("DBF Unexpected MEMO for type " + ft.toString(16));
7150 out[R][C] = "##MEMO##" + (l7 ? parseInt(s.trim(), 10): dd.read_shift(4));
7151 break;
7152 case 'N':
7153 s = s.replace(/\u0000/g,"").trim();
7154 // NOTE: dBASE II interprets " . " as 0
7155 if(s && s != ".") out[R][C] = +s || 0; break;
7156 case '@':
7157 // NOTE: dBASE specs appear to be incorrect
7158 out[R][C] = new Date(dd.read_shift(-8, 'f') - 0x388317533400);
7159 break;
7160 case 'T': out[R][C] = new Date((dd.read_shift(4) - 0x253D8C) * 0x5265C00 + dd.read_shift(4)); break;
7161 case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4; break;
7162 case 'O': out[R][C] = -dd.read_shift(-8, 'f'); break;
7163 case 'B': if(vfp && fields[C].len == 8) { out[R][C] = dd.read_shift(8,'f'); break; }
7164 /* falls through */
7165 case 'G': case 'P': dd.l += fields[C].len; break;
7166 case '0':
7167 if(fields[C].name === '_NullFlags') break;
7168 /* falls through */
7169 default: throw new Error("DBF Unsupported data type " + fields[C].type);
7170 }
7171 }
7172 }
7173 if(ft != 0x02) if(d.l < d.length && d[d.l++] != 0x1A) throw new Error("DBF EOF Marker missing " + (d.l-1) + " of " + d.length + " " + d[d.l-1].toString(16));
7174 if(opts && opts.sheetRows) out = out.slice(0, opts.sheetRows);
7175 return out;
7176}
7177
7178function dbf_to_sheet(buf, opts) {
7179 var o = opts || {};
7180 if(!o.dateNF) o.dateNF = "yyyymmdd";
7181 return aoa_to_sheet(dbf_to_aoa(buf, o), o);
7182}
7183
7184function dbf_to_workbook(buf, opts) {
7185 try { return sheet_to_workbook(dbf_to_sheet(buf, opts), opts); }
7186 catch(e) { if(opts && opts.WTF) throw e; }
7187 return ({SheetNames:[],Sheets:{}});
7188}
7189
7190var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 };
7191function sheet_to_dbf(ws, opts) {
7192 var o = opts || {};
7193 if(+o.codepage >= 0) set_cp(+o.codepage);
7194 if(o.type == "string") throw new Error("Cannot write DBF to JS string");
7195 var ba = buf_array();
7196 var aoa = sheet_to_json(ws, {header:1, raw:true, cellDates:true});
7197 var headers = aoa[0], data = aoa.slice(1);
7198 var i = 0, j = 0, hcnt = 0, rlen = 1;
7199 for(i = 0; i < headers.length; ++i) {
7200 if(i == null) continue;
7201 ++hcnt;
7202 if(typeof headers[i] === 'number') headers[i] = headers[i].toString(10);
7203 if(typeof headers[i] !== 'string') throw new Error("DBF Invalid column name " + headers[i] + " |" + (typeof headers[i]) + "|");
7204 if(headers.indexOf(headers[i]) !== i) for(j=0; j<1024;++j)
7205 if(headers.indexOf(headers[i] + "_" + j) == -1) { headers[i] += "_" + j; break; }
7206 }
7207 var range = safe_decode_range(ws['!ref']);
7208 var coltypes = [];
7209 for(i = 0; i <= range.e.c - range.s.c; ++i) {
7210 var col = [];
7211 for(j=0; j < data.length; ++j) {
7212 if(data[j][i] != null) col.push(data[j][i]);
7213 }
7214 if(col.length == 0 || headers[i] == null) { coltypes[i] = '?'; continue; }
7215 var guess = '', _guess = '';
7216 for(j = 0; j < col.length; ++j) {
7217 switch(typeof col[j]) {
7218 /* TODO: check if L2 compat is desired */
7219 case 'number': _guess = 'B'; break;
7220 case 'string': _guess = 'C'; break;
7221 case 'boolean': _guess = 'L'; break;
7222 case 'object': _guess = col[j] instanceof Date ? 'D' : 'C'; break;
7223 default: _guess = 'C';
7224 }
7225 guess = guess && guess != _guess ? 'C' : _guess;
7226 if(guess == 'C') break;
7227 }
7228 rlen += _RLEN[guess] || 0;
7229 coltypes[i] = guess;
7230 }
7231
7232 var h = ba.next(32);
7233 h.write_shift(4, 0x13021130);
7234 h.write_shift(4, data.length);
7235 h.write_shift(2, 296 + 32 * hcnt);
7236 h.write_shift(2, rlen);
7237 for(i=0; i < 4; ++i) h.write_shift(4, 0);
7238 h.write_shift(4, 0x00000000 | ((+dbf_reverse_map[current_ansi] || 0x03)<<8));
7239
7240 for(i = 0, j = 0; i < headers.length; ++i) {
7241 if(headers[i] == null) continue;
7242 var hf = ba.next(32);
7243 var _f = (headers[i].slice(-10) + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00").slice(0, 11);
7244 hf.write_shift(1, _f, "sbcs");
7245 hf.write_shift(1, coltypes[i] == '?' ? 'C' : coltypes[i], "sbcs");
7246 hf.write_shift(4, j);
7247 hf.write_shift(1, _RLEN[coltypes[i]] || 0);
7248 hf.write_shift(1, 0);
7249 hf.write_shift(1, 0x02);
7250 hf.write_shift(4, 0);
7251 hf.write_shift(1, 0);
7252 hf.write_shift(4, 0);
7253 hf.write_shift(4, 0);
7254 j += _RLEN[coltypes[i]] || 0;
7255 }
7256
7257 var hb = ba.next(264);
7258 hb.write_shift(4, 0x0000000D);
7259 for(i=0; i < 65;++i) hb.write_shift(4, 0x00000000);
7260 for(i=0; i < data.length; ++i) {
7261 var rout = ba.next(rlen);
7262 rout.write_shift(1, 0);
7263 for(j=0; j<headers.length; ++j) {
7264 if(headers[j] == null) continue;
7265 switch(coltypes[j]) {
7266 case 'L': rout.write_shift(1, data[i][j] == null ? 0x3F : data[i][j] ? 0x54 : 0x46); break;
7267 case 'B': rout.write_shift(8, data[i][j]||0, 'f'); break;
7268 case 'D':
7269 if(!data[i][j]) rout.write_shift(8, "00000000", "sbcs");
7270 else {
7271 rout.write_shift(4, ("0000"+data[i][j].getFullYear()).slice(-4), "sbcs");
7272 rout.write_shift(2, ("00"+(data[i][j].getMonth()+1)).slice(-2), "sbcs");
7273 rout.write_shift(2, ("00"+data[i][j].getDate()).slice(-2), "sbcs");
7274 } break;
7275 case 'C':
7276 var _s = String(data[i][j]||"");
7277 rout.write_shift(1, _s, "sbcs");
7278 for(hcnt=0; hcnt < 250-_s.length; ++hcnt) rout.write_shift(1, 0x20); break;
7279 }
7280 }
7281 // data
7282 }
7283 ba.next(1).write_shift(1, 0x1A);
7284 return ba.end();
7285}
7286 return {
7287 versions: DBF_SUPPORTED_VERSIONS,
7288 to_workbook: dbf_to_workbook,
7289 to_sheet: dbf_to_sheet,
7290 from_sheet: sheet_to_dbf
7291 };
7292})();
7293
7294var SYLK = (function() {
7295 /* TODO: stress test sequences */
7296 var sylk_escapes = ({
7297 AA:'À', BA:'Á', CA:'Â', DA:195, HA:'Ä', JA:197,
7298 AE:'È', BE:'É', CE:'Ê', HE:'Ë',
7299 AI:'Ì', BI:'Í', CI:'Î', HI:'Ï',
7300 AO:'Ò', BO:'Ó', CO:'Ô', DO:213, HO:'Ö',
7301 AU:'Ù', BU:'Ú', CU:'Û', HU:'Ü',
7302 Aa:'à', Ba:'á', Ca:'â', Da:227, Ha:'ä', Ja:229,
7303 Ae:'è', Be:'é', Ce:'ê', He:'ë',
7304 Ai:'ì', Bi:'í', Ci:'î', Hi:'ï',
7305 Ao:'ò', Bo:'ó', Co:'ô', Do:245, Ho:'ö',
7306 Au:'ù', Bu:'ú', Cu:'û', Hu:'ü',
7307 KC:'Ç', Kc:'ç', q:'æ', z:'œ', a:'Æ', j:'Œ',
7308 DN:209, Dn:241, Hy:255,
7309 S:169, c:170, R:174, "B ":180,
73100:176, 1:177, 2:178,
73113:179, 5:181, 6:182,
73127:183, Q:185, k:186, b:208, i:216, l:222, s:240, y:248,
7313 "!":161, '"':162, "#":163, "(":164, "%":165, "'":167, "H ":168,
7314 "+":171, ";":187, "<":188, "=":189, ">":190, "?":191, "{":223
7315 });
7316 var sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1") + "|\\|)", "gm");
7317 var sylk_char_fn = function(_, $1){ var o = sylk_escapes[$1]; return typeof o == "number" ? _getansi(o) : o; };
7318 var decode_sylk_char = function($$, $1, $2) { var newcc = (($1.charCodeAt(0) - 0x20)<<4) | ($2.charCodeAt(0) - 0x30); return newcc == 59 ? $$ : _getansi(newcc); };
7319 sylk_escapes["|"] = 254;
7320 /* TODO: find an actual specification */
7321 function sylk_to_aoa(d, opts) {
7322 switch(opts.type) {
7323 case 'base64': return sylk_to_aoa_str(Base64.decode(d), opts);
7324 case 'binary': return sylk_to_aoa_str(d, opts);
7325 case 'buffer': return sylk_to_aoa_str(has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d), opts);
7326 case 'array': return sylk_to_aoa_str(cc2str(d), opts);
7327 }
7328 throw new Error("Unrecognized type " + opts.type);
7329 }
7330 function sylk_to_aoa_str(str, opts) {
7331 var records = str.split(/[\n\r]+/), R = -1, C = -1, ri = 0, rj = 0, arr = [];
7332 var formats = [];
7333 var next_cell_format = null;
7334 var sht = {}, rowinfo = [], colinfo = [], cw = [];
7335 var Mval = 0, j;
7336 if(+opts.codepage >= 0) set_cp(+opts.codepage);
7337 for (; ri !== records.length; ++ri) {
7338 Mval = 0;
7339 var rstr=records[ri].trim().replace(/\x1B([\x20-\x2F])([\x30-\x3F])/g, decode_sylk_char).replace(sylk_char_regex, sylk_char_fn);
7340 var record=rstr.replace(/;;/g, "\u0000").split(";").map(function(x) { return x.replace(/\u0000/g, ";"); });
7341 var RT=record[0], val;
7342 if(rstr.length > 0) switch(RT) {
7343 case 'ID': break; /* header */
7344 case 'E': break; /* EOF */
7345 case 'B': break; /* dimensions */
7346 case 'O': break; /* options? */
7347 case 'W': break; /* window? */
7348 case 'P':
7349 if(record[1].charAt(0) == 'P')
7350 formats.push(rstr.slice(3).replace(/;;/g, ";"));
7351 break;
7352 case 'C':
7353 var C_seen_K = false, C_seen_X = false, C_seen_S = false, C_seen_E = false, _R = -1, _C = -1;
7354 for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
7355 case 'A': break; // TODO: comment
7356 case 'X': C = parseInt(record[rj].slice(1))-1; C_seen_X = true; break;
7357 case 'Y':
7358 R = parseInt(record[rj].slice(1))-1; if(!C_seen_X) C = 0;
7359 for(j = arr.length; j <= R; ++j) arr[j] = [];
7360 break;
7361 case 'K':
7362 val = record[rj].slice(1);
7363 if(val.charAt(0) === '"') val = val.slice(1,val.length - 1);
7364 else if(val === 'TRUE') val = true;
7365 else if(val === 'FALSE') val = false;
7366 else if(!isNaN(fuzzynum(val))) {
7367 val = fuzzynum(val);
7368 if(next_cell_format !== null && SSF.is_date(next_cell_format)) val = numdate(val);
7369 } else if(!isNaN(fuzzydate(val).getDate())) {
7370 val = parseDate(val);
7371 }
7372 if(typeof cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = cptable.utils.decode(opts.codepage, val);
7373 C_seen_K = true;
7374 break;
7375 case 'E':
7376 C_seen_E = true;
7377 var formula = rc_to_a1(record[rj].slice(1), {r:R,c:C});
7378 arr[R][C] = [arr[R][C], formula];
7379 break;
7380 case 'S':
7381 C_seen_S = true;
7382 arr[R][C] = [arr[R][C], "S5S"];
7383 break;
7384 case 'G': break; // unknown
7385 case 'R': _R = parseInt(record[rj].slice(1))-1; break;
7386 case 'C': _C = parseInt(record[rj].slice(1))-1; break;
7387 default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
7388 }
7389 if(C_seen_K) {
7390 if(arr[R][C] && arr[R][C].length == 2) arr[R][C][0] = val;
7391 else arr[R][C] = val;
7392 next_cell_format = null;
7393 }
7394 if(C_seen_S) {
7395 if(C_seen_E) throw new Error("SYLK shared formula cannot have own formula");
7396 var shrbase = _R > -1 && arr[_R][_C];
7397 if(!shrbase || !shrbase[1]) throw new Error("SYLK shared formula cannot find base");
7398 arr[R][C][1] = shift_formula_str(shrbase[1], {r: R - _R, c: C - _C});
7399 }
7400 break;
7401 case 'F':
7402 var F_seen = 0;
7403 for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
7404 case 'X': C = parseInt(record[rj].slice(1))-1; ++F_seen; break;
7405 case 'Y':
7406 R = parseInt(record[rj].slice(1))-1; /*C = 0;*/
7407 for(j = arr.length; j <= R; ++j) arr[j] = [];
7408 break;
7409 case 'M': Mval = parseInt(record[rj].slice(1)) / 20; break;
7410 case 'F': break; /* ??? */
7411 case 'G': break; /* hide grid */
7412 case 'P':
7413 next_cell_format = formats[parseInt(record[rj].slice(1))];
7414 break;
7415 case 'S': break; /* cell style */
7416 case 'D': break; /* column */
7417 case 'N': break; /* font */
7418 case 'W':
7419 cw = record[rj].slice(1).split(" ");
7420 for(j = parseInt(cw[0], 10); j <= parseInt(cw[1], 10); ++j) {
7421 Mval = parseInt(cw[2], 10);
7422 colinfo[j-1] = Mval === 0 ? {hidden:true}: {wch:Mval}; process_col(colinfo[j-1]);
7423 } break;
7424 case 'C': /* default column format */
7425 C = parseInt(record[rj].slice(1))-1;
7426 if(!colinfo[C]) colinfo[C] = {};
7427 break;
7428 case 'R': /* row properties */
7429 R = parseInt(record[rj].slice(1))-1;
7430 if(!rowinfo[R]) rowinfo[R] = {};
7431 if(Mval > 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); }
7432 else if(Mval === 0) rowinfo[R].hidden = true;
7433 break;
7434 default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
7435 }
7436 if(F_seen < 1) next_cell_format = null; break;
7437 default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
7438 }
7439 }
7440 if(rowinfo.length > 0) sht['!rows'] = rowinfo;
7441 if(colinfo.length > 0) sht['!cols'] = colinfo;
7442 if(opts && opts.sheetRows) arr = arr.slice(0, opts.sheetRows);
7443 return [arr, sht];
7444 }
7445
7446 function sylk_to_sheet(d, opts) {
7447 var aoasht = sylk_to_aoa(d, opts);
7448 var aoa = aoasht[0], ws = aoasht[1];
7449 var o = aoa_to_sheet(aoa, opts);
7450 keys(ws).forEach(function(k) { o[k] = ws[k]; });
7451 return o;
7452 }
7453
7454 function sylk_to_workbook(d, opts) { return sheet_to_workbook(sylk_to_sheet(d, opts), opts); }
7455
7456 function write_ws_cell_sylk(cell, ws, R, C) {
7457 var o = "C;Y" + (R+1) + ";X" + (C+1) + ";K";
7458 switch(cell.t) {
7459 case 'n':
7460 o += (cell.v||0);
7461 if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break;
7462 case 'b': o += cell.v ? "TRUE" : "FALSE"; break;
7463 case 'e': o += cell.w || cell.v; break;
7464 case 'd': o += '"' + (cell.w || cell.v) + '"'; break;
7465 case 's': o += '"' + cell.v.replace(/"/g,"") + '"'; break;
7466 }
7467 return o;
7468 }
7469
7470 function write_ws_cols_sylk(out, cols) {
7471 cols.forEach(function(col, i) {
7472 var rec = "F;W" + (i+1) + " " + (i+1) + " ";
7473 if(col.hidden) rec += "0";
7474 else {
7475 if(typeof col.width == 'number' && !col.wpx) col.wpx = width2px(col.width);
7476 if(typeof col.wpx == 'number' && !col.wch) col.wch = px2char(col.wpx);
7477 if(typeof col.wch == 'number') rec += Math.round(col.wch);
7478 }
7479 if(rec.charAt(rec.length - 1) != " ") out.push(rec);
7480 });
7481 }
7482
7483 function write_ws_rows_sylk(out, rows) {
7484 rows.forEach(function(row, i) {
7485 var rec = "F;";
7486 if(row.hidden) rec += "M0;";
7487 else if(row.hpt) rec += "M" + 20 * row.hpt + ";";
7488 else if(row.hpx) rec += "M" + 20 * px2pt(row.hpx) + ";";
7489 if(rec.length > 2) out.push(rec + "R" + (i+1));
7490 });
7491 }
7492
7493 function sheet_to_sylk(ws, opts) {
7494 var preamble = ["ID;PWXL;N;E"], o = [];
7495 var r = safe_decode_range(ws['!ref']), cell;
7496 var dense = Array.isArray(ws);
7497 var RS = "\r\n";
7498
7499 preamble.push("P;PGeneral");
7500 preamble.push("F;P0;DG0G8;M255");
7501 if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
7502 if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
7503
7504 preamble.push("B;Y" + (r.e.r - r.s.r + 1) + ";X" + (r.e.c - r.s.c + 1) + ";D" + [r.s.c,r.s.r,r.e.c,r.e.r].join(" "));
7505 for(var R = r.s.r; R <= r.e.r; ++R) {
7506 for(var C = r.s.c; C <= r.e.c; ++C) {
7507 var coord = encode_cell({r:R,c:C});
7508 cell = dense ? (ws[R]||[])[C]: ws[coord];
7509 if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
7510 o.push(write_ws_cell_sylk(cell, ws, R, C, opts));
7511 }
7512 }
7513 return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
7514 }
7515
7516 return {
7517 to_workbook: sylk_to_workbook,
7518 to_sheet: sylk_to_sheet,
7519 from_sheet: sheet_to_sylk
7520 };
7521})();
7522
7523var DIF = (function() {
7524 function dif_to_aoa(d, opts) {
7525 switch(opts.type) {
7526 case 'base64': return dif_to_aoa_str(Base64.decode(d), opts);
7527 case 'binary': return dif_to_aoa_str(d, opts);
7528 case 'buffer': return dif_to_aoa_str(has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d), opts);
7529 case 'array': return dif_to_aoa_str(cc2str(d), opts);
7530 }
7531 throw new Error("Unrecognized type " + opts.type);
7532 }
7533 function dif_to_aoa_str(str, opts) {
7534 var records = str.split('\n'), R = -1, C = -1, ri = 0, arr = [];
7535 for (; ri !== records.length; ++ri) {
7536 if (records[ri].trim() === 'BOT') { arr[++R] = []; C = 0; continue; }
7537 if (R < 0) continue;
7538 var metadata = records[ri].trim().split(",");
7539 var type = metadata[0], value = metadata[1];
7540 ++ri;
7541 var data = records[ri] || "";
7542 while(((data.match(/["]/g)||[]).length & 1) && ri < records.length - 1) data += "\n" + records[++ri];
7543 data = data.trim();
7544 switch (+type) {
7545 case -1:
7546 if (data === 'BOT') { arr[++R] = []; C = 0; continue; }
7547 else if (data !== 'EOD') throw new Error("Unrecognized DIF special command " + data);
7548 break;
7549 case 0:
7550 if(data === 'TRUE') arr[R][C] = true;
7551 else if(data === 'FALSE') arr[R][C] = false;
7552 else if(!isNaN(fuzzynum(value))) arr[R][C] = fuzzynum(value);
7553 else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value);
7554 else arr[R][C] = value;
7555 ++C; break;
7556 case 1:
7557 data = data.slice(1,data.length-1);
7558 data = data.replace(/""/g, '"');
7559 if(DIF_XL && data && data.match(/^=".*"$/)) data = data.slice(2, -1);
7560 arr[R][C++] = data !== '' ? data : null;
7561 break;
7562 }
7563 if (data === 'EOD') break;
7564 }
7565 if(opts && opts.sheetRows) arr = arr.slice(0, opts.sheetRows);
7566 return arr;
7567 }
7568
7569 function dif_to_sheet(str, opts) { return aoa_to_sheet(dif_to_aoa(str, opts), opts); }
7570 function dif_to_workbook(str, opts) { return sheet_to_workbook(dif_to_sheet(str, opts), opts); }
7571
7572 var sheet_to_dif = (function() {
7573 var push_field = function pf(o, topic, v, n, s) {
7574 o.push(topic);
7575 o.push(v + "," + n);
7576 o.push('"' + s.replace(/"/g,'""') + '"');
7577 };
7578 var push_value = function po(o, type, v, s) {
7579 o.push(type + "," + v);
7580 o.push(type == 1 ? '"' + s.replace(/"/g,'""') + '"' : s);
7581 };
7582 return function sheet_to_dif(ws) {
7583 var o = [];
7584 var r = safe_decode_range(ws['!ref']), cell;
7585 var dense = Array.isArray(ws);
7586 push_field(o, "TABLE", 0, 1, "sheetjs");
7587 push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,"");
7588 push_field(o, "TUPLES", 0, r.e.c - r.s.c + 1,"");
7589 push_field(o, "DATA", 0, 0,"");
7590 for(var R = r.s.r; R <= r.e.r; ++R) {
7591 push_value(o, -1, 0, "BOT");
7592 for(var C = r.s.c; C <= r.e.c; ++C) {
7593 var coord = encode_cell({r:R,c:C});
7594 cell = dense ? (ws[R]||[])[C] : ws[coord];
7595 if(!cell) { push_value(o, 1, 0, ""); continue;}
7596 switch(cell.t) {
7597 case 'n':
7598 var val = DIF_XL ? cell.w : cell.v;
7599 if(!val && cell.v != null) val = cell.v;
7600 if(val == null) {
7601 if(DIF_XL && cell.f && !cell.F) push_value(o, 1, 0, "=" + cell.f);
7602 else push_value(o, 1, 0, "");
7603 }
7604 else push_value(o, 0, val, "V");
7605 break;
7606 case 'b':
7607 push_value(o, 0, cell.v ? 1 : 0, cell.v ? "TRUE" : "FALSE");
7608 break;
7609 case 's':
7610 push_value(o, 1, 0, (!DIF_XL || isNaN(cell.v)) ? cell.v : '="' + cell.v + '"');
7611 break;
7612 case 'd':
7613 if(!cell.w) cell.w = SSF.format(cell.z || SSF._table[14], datenum(parseDate(cell.v)));
7614 if(DIF_XL) push_value(o, 0, cell.w, "V");
7615 else push_value(o, 1, 0, cell.w);
7616 break;
7617 default: push_value(o, 1, 0, "");
7618 }
7619 }
7620 }
7621 push_value(o, -1, 0, "EOD");
7622 var RS = "\r\n";
7623 var oo = o.join(RS);
7624 //while((oo.length & 0x7F) != 0) oo += "\0";
7625 return oo;
7626 };
7627 })();
7628 return {
7629 to_workbook: dif_to_workbook,
7630 to_sheet: dif_to_sheet,
7631 from_sheet: sheet_to_dif
7632 };
7633})();
7634
7635var ETH = (function() {
7636 function decode(s) { return s.replace(/\\b/g,"\\").replace(/\\c/g,":").replace(/\\n/g,"\n"); }
7637 function encode(s) { return s.replace(/\\/g, "\\b").replace(/:/g, "\\c").replace(/\n/g,"\\n"); }
7638
7639 function eth_to_aoa(str, opts) {
7640 var records = str.split('\n'), R = -1, C = -1, ri = 0, arr = [];
7641 for (; ri !== records.length; ++ri) {
7642 var record = records[ri].trim().split(":");
7643 if(record[0] !== 'cell') continue;
7644 var addr = decode_cell(record[1]);
7645 if(arr.length <= addr.r) for(R = arr.length; R <= addr.r; ++R) if(!arr[R]) arr[R] = [];
7646 R = addr.r; C = addr.c;
7647 switch(record[2]) {
7648 case 't': arr[R][C] = decode(record[3]); break;
7649 case 'v': arr[R][C] = +record[3]; break;
7650 case 'vtf': var _f = record[record.length - 1];
7651 /* falls through */
7652 case 'vtc':
7653 switch(record[3]) {
7654 case 'nl': arr[R][C] = +record[4] ? true : false; break;
7655 default: arr[R][C] = +record[4]; break;
7656 }
7657 if(record[2] == 'vtf') arr[R][C] = [arr[R][C], _f];
7658 }
7659 }
7660 if(opts && opts.sheetRows) arr = arr.slice(0, opts.sheetRows);
7661 return arr;
7662 }
7663
7664 function eth_to_sheet(d, opts) { return aoa_to_sheet(eth_to_aoa(d, opts), opts); }
7665 function eth_to_workbook(d, opts) { return sheet_to_workbook(eth_to_sheet(d, opts), opts); }
7666
7667 var header = [
7668 "socialcalc:version:1.5",
7669 "MIME-Version: 1.0",
7670 "Content-Type: multipart/mixed; boundary=SocialCalcSpreadsheetControlSave"
7671 ].join("\n");
7672
7673 var sep = [
7674 "--SocialCalcSpreadsheetControlSave",
7675 "Content-type: text/plain; charset=UTF-8"
7676 ].join("\n") + "\n";
7677
7678 /* TODO: the other parts */
7679 var meta = [
7680 "# SocialCalc Spreadsheet Control Save",
7681 "part:sheet"
7682 ].join("\n");
7683
7684 var end = "--SocialCalcSpreadsheetControlSave--";
7685
7686 function sheet_to_eth_data(ws) {
7687 if(!ws || !ws['!ref']) return "";
7688 var o = [], oo = [], cell, coord = "";
7689 var r = decode_range(ws['!ref']);
7690 var dense = Array.isArray(ws);
7691 for(var R = r.s.r; R <= r.e.r; ++R) {
7692 for(var C = r.s.c; C <= r.e.c; ++C) {
7693 coord = encode_cell({r:R,c:C});
7694 cell = dense ? (ws[R]||[])[C] : ws[coord];
7695 if(!cell || cell.v == null || cell.t === 'z') continue;
7696 oo = ["cell", coord, 't'];
7697 switch(cell.t) {
7698 case 's': case 'str': oo.push(encode(cell.v)); break;
7699 case 'n':
7700 if(!cell.f) { oo[2]='v'; oo[3]=cell.v; }
7701 else { oo[2]='vtf'; oo[3]='n'; oo[4]=cell.v; oo[5]=encode(cell.f); }
7702 break;
7703 case 'b':
7704 oo[2] = 'vt'+(cell.f?'f':'c'); oo[3]='nl'; oo[4]=cell.v?"1":"0";
7705 oo[5] = encode(cell.f||(cell.v?'TRUE':'FALSE'));
7706 break;
7707 case 'd':
7708 var t = datenum(parseDate(cell.v));
7709 oo[2] = 'vtc'; oo[3] = 'nd'; oo[4] = ""+t;
7710 oo[5] = cell.w || SSF.format(cell.z || SSF._table[14], t);
7711 break;
7712 case 'e': continue;
7713 }
7714 o.push(oo.join(":"));
7715 }
7716 }
7717 o.push("sheet:c:" + (r.e.c-r.s.c+1) + ":r:" + (r.e.r-r.s.r+1) + ":tvf:1");
7718 o.push("valueformat:1:text-wiki");
7719 //o.push("copiedfrom:" + ws['!ref']); // clipboard only
7720 return o.join("\n");
7721 }
7722
7723 function sheet_to_eth(ws) {
7724 return [header, sep, meta, sep, sheet_to_eth_data(ws), end].join("\n");
7725 // return ["version:1.5", sheet_to_eth_data(ws)].join("\n"); // clipboard form
7726 }
7727
7728 return {
7729 to_workbook: eth_to_workbook,
7730 to_sheet: eth_to_sheet,
7731 from_sheet: sheet_to_eth
7732 };
7733})();
7734
7735var PRN = (function() {
7736 function set_text_arr(data, arr, R, C, o) {
7737 if(o.raw) arr[R][C] = data;
7738 else if(data === ""){/* empty */}
7739 else if(data === 'TRUE') arr[R][C] = true;
7740 else if(data === 'FALSE') arr[R][C] = false;
7741 else if(!isNaN(fuzzynum(data))) arr[R][C] = fuzzynum(data);
7742 else if(!isNaN(fuzzydate(data).getDate())) arr[R][C] = parseDate(data);
7743 else arr[R][C] = data;
7744 }
7745
7746 function prn_to_aoa_str(f, opts) {
7747 var o = opts || {};
7748 var arr = ([]);
7749 if(!f || f.length === 0) return arr;
7750 var lines = f.split(/[\r\n]/);
7751 var L = lines.length - 1;
7752 while(L >= 0 && lines[L].length === 0) --L;
7753 var start = 10, idx = 0;
7754 var R = 0;
7755 for(; R <= L; ++R) {
7756 idx = lines[R].indexOf(" ");
7757 if(idx == -1) idx = lines[R].length; else idx++;
7758 start = Math.max(start, idx);
7759 }
7760 for(R = 0; R <= L; ++R) {
7761 arr[R] = [];
7762 /* TODO: confirm that widths are always 10 */
7763 var C = 0;
7764 set_text_arr(lines[R].slice(0, start).trim(), arr, R, C, o);
7765 for(C = 1; C <= (lines[R].length - start)/10 + 1; ++C)
7766 set_text_arr(lines[R].slice(start+(C-1)*10,start+C*10).trim(),arr,R,C,o);
7767 }
7768 if(o.sheetRows) arr = arr.slice(0, o.sheetRows);
7769 return arr;
7770 }
7771
7772 // List of accepted CSV separators
7773 var guess_seps = {
77740x2C: ',',
77750x09: "\t",
77760x3B: ';',
77770x7C: '|'
7778 };
7779
7780 // CSV separator weights to be used in case of equal numbers
7781 var guess_sep_weights = {
77820x2C: 3,
77830x09: 2,
77840x3B: 1,
77850x7C: 0
7786 };
7787
7788 function guess_sep(str) {
7789 var cnt = {}, instr = false, end = 0, cc = 0;
7790 for(;end < str.length;++end) {
7791 if((cc=str.charCodeAt(end)) == 0x22) instr = !instr;
7792 else if(!instr && cc in guess_seps) cnt[cc] = (cnt[cc]||0)+1;
7793 }
7794
7795 cc = [];
7796 for(end in cnt) if ( Object.prototype.hasOwnProperty.call(cnt, end) ) {
7797 cc.push([ cnt[end], end ]);
7798 }
7799
7800 if ( !cc.length ) {
7801 cnt = guess_sep_weights;
7802 for(end in cnt) if ( Object.prototype.hasOwnProperty.call(cnt, end) ) {
7803 cc.push([ cnt[end], end ]);
7804 }
7805 }
7806
7807 cc.sort(function(a, b) { return a[0] - b[0] || guess_sep_weights[a[1]] - guess_sep_weights[b[1]]; });
7808
7809 return guess_seps[cc.pop()[1]] || 0x2C;
7810 }
7811
7812 function dsv_to_sheet_str(str, opts) {
7813 var o = opts || {};
7814 var sep = "";
7815 if(DENSE != null && o.dense == null) o.dense = DENSE;
7816 var ws = o.dense ? ([]) : ({});
7817 var range = ({s: {c:0, r:0}, e: {c:0, r:0}});
7818
7819 if(str.slice(0,4) == "sep=") {
7820 // If the line ends in \r\n
7821 if(str.charCodeAt(5) == 13 && str.charCodeAt(6) == 10 ) {
7822 sep = str.charAt(4); str = str.slice(7);
7823 }
7824 // If line ends in \r OR \n
7825 else if(str.charCodeAt(5) == 13 || str.charCodeAt(5) == 10 ) {
7826 sep = str.charAt(4); str = str.slice(6);
7827 }
7828 else sep = guess_sep(str.slice(0,1024));
7829 }
7830 else if(o && o.FS) sep = o.FS;
7831 else sep = guess_sep(str.slice(0,1024));
7832 var R = 0, C = 0, v = 0;
7833 var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0);
7834 str = str.replace(/\r\n/mg, "\n");
7835 var _re = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
7836 function finish_cell() {
7837 var s = str.slice(start, end);
7838 var cell = ({});
7839 if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
7840 if(s.length === 0) cell.t = 'z';
7841 else if(o.raw) { cell.t = 's'; cell.v = s; }
7842 else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; }
7843 else if(s.charCodeAt(0) == 0x3D) {
7844 if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); }
7845 else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.slice(1); }
7846 else { cell.t = 's'; cell.v = s; } }
7847 else if(s == "TRUE") { cell.t = 'b'; cell.v = true; }
7848 else if(s == "FALSE") { cell.t = 'b'; cell.v = false; }
7849 else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; if(o.cellText !== false) cell.w = s; cell.v = v; }
7850 else if(!isNaN(fuzzydate(s).getDate()) || _re && s.match(_re)) {
7851 cell.z = o.dateNF || SSF._table[14];
7852 var k = 0;
7853 if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; }
7854 if(o.cellDates) { cell.t = 'd'; cell.v = parseDate(s, k); }
7855 else { cell.t = 'n'; cell.v = datenum(parseDate(s, k)); }
7856 if(o.cellText !== false) cell.w = SSF.format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v);
7857 if(!o.cellNF) delete cell.z;
7858 } else {
7859 cell.t = 's';
7860 cell.v = s;
7861 }
7862 if(cell.t == 'z'){}
7863 else if(o.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = cell; }
7864 else ws[encode_cell({c:C,r:R})] = cell;
7865 start = end+1; startcc = str.charCodeAt(start);
7866 if(range.e.c < C) range.e.c = C;
7867 if(range.e.r < R) range.e.r = R;
7868 if(cc == sepcc) ++C; else { C = 0; ++R; if(o.sheetRows && o.sheetRows <= R) return true; }
7869 }
7870 outer: for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) {
7871 case 0x22: if(startcc === 0x22) instr = !instr; break;
7872 case sepcc: case 0x0a: case 0x0d: if(!instr && finish_cell()) break outer; break;
7873 default: break;
7874 }
7875 if(end - start > 0) finish_cell();
7876
7877 ws['!ref'] = encode_range(range);
7878 return ws;
7879 }
7880
7881 function prn_to_sheet_str(str, opts) {
7882 if(!(opts && opts.PRN)) return dsv_to_sheet_str(str, opts);
7883 if(opts.FS) return dsv_to_sheet_str(str, opts);
7884 if(str.slice(0,4) == "sep=") return dsv_to_sheet_str(str, opts);
7885 if(str.indexOf("\t") >= 0 || str.indexOf(",") >= 0 || str.indexOf(";") >= 0) return dsv_to_sheet_str(str, opts);
7886 return aoa_to_sheet(prn_to_aoa_str(str, opts), opts);
7887 }
7888
7889 function prn_to_sheet(d, opts) {
7890 var str = "", bytes = opts.type == 'string' ? [0,0,0,0] : firstbyte(d, opts);
7891 switch(opts.type) {
7892 case 'base64': str = Base64.decode(d); break;
7893 case 'binary': str = d; break;
7894 case 'buffer':
7895 if(opts.codepage == 65001) str = d.toString('utf8'); // TODO: test if buf
7896 else if(opts.codepage && typeof cptable !== 'undefined') str = cptable.utils.decode(opts.codepage, d);
7897 else str = has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d);
7898 break;
7899 case 'array': str = cc2str(d); break;
7900 case 'string': str = d; break;
7901 default: throw new Error("Unrecognized type " + opts.type);
7902 }
7903 if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str.slice(3));
7904 else if(opts.type != 'string' && opts.codepage == 65001) str = utf8read(str);
7905 else if((opts.type == 'binary') && typeof cptable !== 'undefined' && opts.codepage) str = cptable.utils.decode(opts.codepage, cptable.utils.encode(28591,str));
7906 if(str.slice(0,19) == "socialcalc:version:") return ETH.to_sheet(opts.type == 'string' ? str : utf8read(str), opts);
7907 return prn_to_sheet_str(str, opts);
7908 }
7909
7910 function prn_to_workbook(d, opts) { return sheet_to_workbook(prn_to_sheet(d, opts), opts); }
7911
7912 function sheet_to_prn(ws) {
7913 var o = [];
7914 var r = safe_decode_range(ws['!ref']), cell;
7915 var dense = Array.isArray(ws);
7916 for(var R = r.s.r; R <= r.e.r; ++R) {
7917 var oo = [];
7918 for(var C = r.s.c; C <= r.e.c; ++C) {
7919 var coord = encode_cell({r:R,c:C});
7920 cell = dense ? (ws[R]||[])[C] : ws[coord];
7921 if(!cell || cell.v == null) { oo.push(" "); continue; }
7922 var w = (cell.w || (format_cell(cell), cell.w) || "").slice(0,10);
7923 while(w.length < 10) w += " ";
7924 oo.push(w + (C === 0 ? " " : ""));
7925 }
7926 o.push(oo.join(""));
7927 }
7928 return o.join("\n");
7929 }
7930
7931 return {
7932 to_workbook: prn_to_workbook,
7933 to_sheet: prn_to_sheet,
7934 from_sheet: sheet_to_prn
7935 };
7936})();
7937
7938/* Excel defaults to SYLK but warns if data is not valid */
7939function read_wb_ID(d, opts) {
7940 var o = opts || {}, OLD_WTF = !!o.WTF; o.WTF = true;
7941 try {
7942 var out = SYLK.to_workbook(d, o);
7943 o.WTF = OLD_WTF;
7944 return out;
7945 } catch(e) {
7946 o.WTF = OLD_WTF;
7947 if(!e.message.match(/SYLK bad record ID/) && OLD_WTF) throw e;
7948 return PRN.to_workbook(d, opts);
7949 }
7950}
7951
7952var WK_ = (function() {
7953 function lotushopper(data, cb, opts) {
7954 if(!data) return;
7955 prep_blob(data, data.l || 0);
7956 var Enum = opts.Enum || WK1Enum;
7957 while(data.l < data.length) {
7958 var RT = data.read_shift(2);
7959 var R = Enum[RT] || Enum[0xFFFF];
7960 var length = data.read_shift(2);
7961 var tgt = data.l + length;
7962 var d = R.f && R.f(data, length, opts);
7963 data.l = tgt;
7964 if(cb(d, R, RT)) return;
7965 }
7966 }
7967
7968 function lotus_to_workbook(d, opts) {
7969 switch(opts.type) {
7970 case 'base64': return lotus_to_workbook_buf(s2a(Base64.decode(d)), opts);
7971 case 'binary': return lotus_to_workbook_buf(s2a(d), opts);
7972 case 'buffer':
7973 case 'array': return lotus_to_workbook_buf(d, opts);
7974 }
7975 throw "Unsupported type " + opts.type;
7976 }
7977
7978 function lotus_to_workbook_buf(d, opts) {
7979 if(!d) return d;
7980 var o = opts || {};
7981 if(DENSE != null && o.dense == null) o.dense = DENSE;
7982 var s = ((o.dense ? [] : {})), n = "Sheet1", sidx = 0;
7983 var sheets = {}, snames = [n], realnames = [];
7984
7985 var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
7986 var sheetRows = o.sheetRows || 0;
7987
7988 if(d[2] == 0x02) {
7989 o.Enum = WK1Enum;
7990 lotushopper(d, function(val, R, RT) { switch(RT) {
7991 case 0x00: /* BOF */
7992 o.vers = val;
7993 if(val >= 0x1000) o.qpro = true;
7994 break;
7995 case 0x06: refguess = val; break; /* RANGE */
7996 case 0x0F: /* LABEL */
7997 case 0x33: /* STRING */
7998 if(!o.qpro) val[1].v = val[1].v.slice(1);
7999 /* falls through */
8000 case 0x0D: /* INTEGER */
8001 case 0x0E: /* NUMBER */
8002 case 0x10: /* FORMULA */
8003 /* TODO: actual translation of the format code */
8004 if(RT == 0x0E && (val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) {
8005 val[1].z = o.dateNF || SSF._table[14];
8006 if(o.cellDates) { val[1].t = 'd'; val[1].v = numdate(val[1].v); }
8007 }
8008 var tmpcell = o.dense ? (s[val[0].r]||[])[val[0].c] : s[encode_cell(val[0])];
8009 if(tmpcell) {
8010 tmpcell.t = val[1].t; tmpcell.v = val[1].v;
8011 if(val[1].z != null) tmpcell.z = val[1].z;
8012 if(val[1].f != null) tmpcell.f = val[1].f;
8013 break;
8014 }
8015 if(o.dense) {
8016 if(!s[val[0].r]) s[val[0].r] = [];
8017 s[val[0].r][val[0].c] = val[1];
8018 } else s[encode_cell(val[0])] = val[1];
8019 break;
8020 default:
8021 }}, o);
8022 } else if(d[2] == 0x1A || d[2] == 0x0E) {
8023 o.Enum = WK3Enum;
8024 if(d[2] == 0x0E) { o.qpro = true; d.l = 0; }
8025 lotushopper(d, function(val, R, RT) { switch(RT) {
8026 case 0x16: /* LABEL16 */
8027 val[1].v = val[1].v.slice(1);
8028 /* falls through */
8029 case 0x17: /* NUMBER17 */
8030 case 0x18: /* NUMBER18 */
8031 case 0x19: /* FORMULA19 */
8032 case 0x25: /* NUMBER25 */
8033 case 0x27: /* NUMBER27 */
8034 case 0x28: /* FORMULA28 */
8035 if(val[3] > sidx) {
8036 s["!ref"] = encode_range(refguess);
8037 sheets[n] = s;
8038 s = (o.dense ? [] : {});
8039 refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
8040 sidx = val[3]; n = "Sheet" + (sidx + 1);
8041 snames.push(n);
8042 }
8043 if(sheetRows > 0 && val[0].r >= sheetRows) break;
8044 if(o.dense) {
8045 if(!s[val[0].r]) s[val[0].r] = [];
8046 s[val[0].r][val[0].c] = val[1];
8047 } else s[encode_cell(val[0])] = val[1];
8048 if(refguess.e.c < val[0].c) refguess.e.c = val[0].c;
8049 if(refguess.e.r < val[0].r) refguess.e.r = val[0].r;
8050 break;
8051 case 0x1B: /* XFORMAT */
8052 if(val[0x36b0]) realnames[val[0x36b0][0]] = val[0x36b0][1];
8053 break;
8054 default: break;
8055 }}, o);
8056 } else throw new Error("Unrecognized LOTUS BOF " + d[2]);
8057
8058 s["!ref"] = encode_range(refguess);
8059 sheets[n] = s;
8060 if(!realnames.length) return { SheetNames: snames, Sheets: sheets };
8061 var osheets = {}, rnames = [];
8062 for(var i = 0; i < realnames.length; ++i) if(sheets[snames[i]]) {
8063 rnames.push(realnames[i]);
8064 osheets[realnames[i]] = sheets[snames[i]];
8065 }
8066 return { SheetNames: rnames, Sheets: osheets };
8067 }
8068
8069 function sheet_to_wk1(ws, opts) {
8070 var o = opts || {};
8071 if(+o.codepage >= 0) set_cp(+o.codepage);
8072 if(o.type == "string") throw new Error("Cannot write WK1 to JS string");
8073 var ba = buf_array();
8074 var range = safe_decode_range(ws["!ref"]);
8075 var dense = Array.isArray(ws);
8076 var cols = [];
8077
8078 write_biff_rec(ba, 0x00, write_BOF_WK1(0x0406));
8079 write_biff_rec(ba, 0x06, write_RANGE(range));
8080 for(var R = range.s.r; R <= range.e.r; ++R) {
8081 var rr = encode_row(R);
8082 for(var C = range.s.c; C <= range.e.c; ++C) {
8083 if(R === range.s.r) cols[C] = encode_col(C);
8084 var ref = cols[C] + rr;
8085 var cell = dense ? (ws[R]||[])[C] : ws[ref];
8086 if(!cell || cell.t == "z") continue;
8087 /* TODO: formula records */
8088 if(cell.t == "n") {
8089 if((cell.v|0)==cell.v && cell.v >= -32768 && cell.v <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, cell.v));
8090 else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, cell.v));
8091 } else {
8092 var str = format_cell(cell);
8093 write_biff_rec(ba, 0x0F, write_LABEL(R, C, str.slice(0, 239)));
8094 }
8095 }
8096 }
8097
8098 write_biff_rec(ba, 0x01);
8099 return ba.end();
8100 }
8101
8102 function book_to_wk3(wb, opts) {
8103 var o = opts || {};
8104 if(+o.codepage >= 0) set_cp(+o.codepage);
8105 if(o.type == "string") throw new Error("Cannot write WK3 to JS string");
8106 var ba = buf_array();
8107
8108 write_biff_rec(ba, 0x00, write_BOF_WK3(wb));
8109
8110 for(var i = 0, cnt = 0; i < wb.SheetNames.length; ++i) if((wb.Sheets[wb.SheetNames[i]] || {})["!ref"]) write_biff_rec(ba, 0x1b, write_XFORMAT_SHEETNAME(wb.SheetNames[i], cnt++));
8111
8112 var wsidx = 0;
8113 for(i = 0; i < wb.SheetNames.length; ++i) {
8114 var ws = wb.Sheets[wb.SheetNames[i]];
8115 if(!ws || !ws["!ref"]) continue;
8116 var range = safe_decode_range(ws["!ref"]);
8117 var dense = Array.isArray(ws);
8118 var cols = [];
8119 for(var R = range.s.r; R <= range.e.r; ++R) {
8120 var rr = encode_row(R);
8121 for(var C = range.s.c; C <= range.e.c; ++C) {
8122 if(R === range.s.r) cols[C] = encode_col(C);
8123 var ref = cols[C] + rr;
8124 var cell = dense ? (ws[R]||[])[C] : ws[ref];
8125 if(!cell || cell.t == "z") continue;
8126 /* TODO: FORMULA19 NUMBER18 records */
8127 if(cell.t == "n") {
8128 write_biff_rec(ba, 0x17, write_NUMBER_17(R, C, wsidx, cell.v));
8129 } else {
8130 var str = format_cell(cell);
8131 /* TODO: max len? */
8132 write_biff_rec(ba, 0x16, write_LABEL_16(R, C, wsidx, str.slice(0, 239)));
8133 }
8134 }
8135 }
8136 ++wsidx;
8137 }
8138
8139 write_biff_rec(ba, 0x01);
8140 return ba.end();
8141 }
8142
8143
8144 function write_BOF_WK1(v) {
8145 var out = new_buf(2);
8146 out.write_shift(2, v);
8147 return out;
8148 }
8149
8150 function write_BOF_WK3(wb) {
8151 var out = new_buf(26);
8152 out.write_shift(2, 0x1000);
8153 out.write_shift(2, 0x0004);
8154 out.write_shift(4, 0x0000);
8155 var rows = 0, cols = 0, wscnt = 0;
8156 for(var i = 0; i < wb.SheetNames.length; ++i) {
8157 var name = wb.SheetNames[i];
8158 var ws = wb.Sheets[name];
8159 if(!ws || !ws["!ref"]) continue;
8160 ++wscnt;
8161 var range = decode_range(ws["!ref"]);
8162 if(rows < range.e.r) rows = range.e.r;
8163 if(cols < range.e.c) cols = range.e.c;
8164 }
8165 out.write_shift(2, rows);
8166 out.write_shift(1, wscnt);
8167 out.write_shift(1, cols);
8168 out.write_shift(2, 0x00);
8169 out.write_shift(2, 0x00);
8170 out.write_shift(1, 0x01);
8171 out.write_shift(1, 0x02);
8172 out.write_shift(4, 0);
8173 out.write_shift(4, 0);
8174 return out;
8175 }
8176
8177 function parse_RANGE(blob) {
8178 var o = {s:{c:0,r:0},e:{c:0,r:0}};
8179 o.s.c = blob.read_shift(2);
8180 o.s.r = blob.read_shift(2);
8181 o.e.c = blob.read_shift(2);
8182 o.e.r = blob.read_shift(2);
8183 if(o.s.c == 0xFFFF) o.s.c = o.e.c = o.s.r = o.e.r = 0;
8184 return o;
8185 }
8186 function write_RANGE(range) {
8187 var out = new_buf(8);
8188 out.write_shift(2, range.s.c);
8189 out.write_shift(2, range.s.r);
8190 out.write_shift(2, range.e.c);
8191 out.write_shift(2, range.e.r);
8192 return out;
8193 }
8194
8195 function parse_cell(blob, length, opts) {
8196 var o = [{c:0,r:0}, {t:'n',v:0}, 0];
8197 if(opts.qpro && opts.vers != 0x5120) {
8198 o[0].c = blob.read_shift(1);
8199 blob.l++;
8200 o[0].r = blob.read_shift(2);
8201 blob.l+=2;
8202 } else {
8203 o[2] = blob.read_shift(1);
8204 o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2);
8205 }
8206 return o;
8207 }
8208
8209 function parse_LABEL(blob, length, opts) {
8210 var tgt = blob.l + length;
8211 var o = parse_cell(blob, length, opts);
8212 o[1].t = 's';
8213 if(opts.vers == 0x5120) {
8214 blob.l++;
8215 var len = blob.read_shift(1);
8216 o[1].v = blob.read_shift(len, 'utf8');
8217 return o;
8218 }
8219 if(opts.qpro) blob.l++;
8220 o[1].v = blob.read_shift(tgt - blob.l, 'cstr');
8221 return o;
8222 }
8223 function write_LABEL(R, C, s) {
8224 /* TODO: encoding */
8225 var o = new_buf(7 + s.length);
8226 o.write_shift(1, 0xFF);
8227 o.write_shift(2, C);
8228 o.write_shift(2, R);
8229 o.write_shift(1, 0x27); // ??
8230 for(var i = 0; i < o.length; ++i) {
8231 var cc = s.charCodeAt(i);
8232 o.write_shift(1, cc >= 0x80 ? 0x5F : cc);
8233 }
8234 o.write_shift(1, 0);
8235 return o;
8236 }
8237
8238 function parse_INTEGER(blob, length, opts) {
8239 var o = parse_cell(blob, length, opts);
8240 o[1].v = blob.read_shift(2, 'i');
8241 return o;
8242 }
8243 function write_INTEGER(R, C, v) {
8244 var o = new_buf(7);
8245 o.write_shift(1, 0xFF);
8246 o.write_shift(2, C);
8247 o.write_shift(2, R);
8248 o.write_shift(2, v, 'i');
8249 return o;
8250 }
8251
8252 function parse_NUMBER(blob, length, opts) {
8253 var o = parse_cell(blob, length, opts);
8254 o[1].v = blob.read_shift(8, 'f');
8255 return o;
8256 }
8257 function write_NUMBER(R, C, v) {
8258 var o = new_buf(13);
8259 o.write_shift(1, 0xFF);
8260 o.write_shift(2, C);
8261 o.write_shift(2, R);
8262 o.write_shift(8, v, 'f');
8263 return o;
8264 }
8265
8266 function parse_FORMULA(blob, length, opts) {
8267 var tgt = blob.l + length;
8268 var o = parse_cell(blob, length, opts);
8269 /* TODO: formula */
8270 o[1].v = blob.read_shift(8, 'f');
8271 if(opts.qpro) blob.l = tgt;
8272 else {
8273 var flen = blob.read_shift(2);
8274 wk1_fmla_to_csf(blob.slice(blob.l, blob.l + flen), o);
8275 blob.l += flen;
8276 }
8277 return o;
8278 }
8279
8280 function wk1_parse_rc(B, V, col) {
8281 var rel = V & 0x8000;
8282 V &= ~0x8000;
8283 V = (rel ? B : 0) + ((V >= 0x2000) ? V - 0x4000 : V);
8284 return (rel ? "" : "$") + (col ? encode_col(V) : encode_row(V));
8285 }
8286 var oprec = [
8287 8, 8, 8, 8, 8, 8, 8, 8, 6, 4, 4, 5, 5, 7, 3, 3,
8288 3, 3, 3, 3, 1, 1, 2, 6, 8, 8, 8, 8, 8, 8, 8, 8
8289 ];
8290 /* TODO: flesh out */
8291 var FuncTab = {
8292 0x33: ["FALSE", 0],
8293 0x34: ["TRUE", 0],
8294 0x46: ["LEN", 1],
8295 0x50: ["SUM", 69],
8296 0x51: ["AVERAGEA", 69],
8297 0x52: ["COUNTA", 69],
8298 0x53: ["MINA", 69],
8299 0x54: ["MAXA", 69],
8300 0x6F: ["T", 1]
8301 };
8302 var BinOpTab = [
8303 "", "", "", "", "", "", "", "",
8304 "", "+", "-", "*", "/", "^", "=", "<>",
8305 "<=", ">=", "<", ">", "", "", "", "",
8306 "&", "", "", "", "", "", "", ""
8307 ];
8308
8309 function wk1_fmla_to_csf(blob, o) {
8310 prep_blob(blob, 0);
8311 var out = [], argc = 0, R = "", C = "";
8312 while(blob.l < blob.length) {
8313 var cc = blob[blob.l++];
8314 switch(cc) {
8315 case 0x00: out.push(blob.read_shift(8, 'f')); break;
8316 case 0x01: {
8317 C = wk1_parse_rc(o[0].c, blob.read_shift(2), true);
8318 R = wk1_parse_rc(o[0].r, blob.read_shift(2), false);
8319 out.push(C + R);
8320 } break;
8321 case 0x02: {
8322 var c = wk1_parse_rc(o[0].c, blob.read_shift(2), true);
8323 var r = wk1_parse_rc(o[0].r, blob.read_shift(2), false);
8324 C = wk1_parse_rc(o[0].c, blob.read_shift(2), true);
8325 R = wk1_parse_rc(o[0].r, blob.read_shift(2), false);
8326 out.push(c + r + ":" + C + R);
8327 } break;
8328 case 0x03:
8329 if(blob.l < blob.length) { console.error("WK1 premature formula end"); return; }
8330 break;
8331 case 0x04: out.push("(" + out.pop() + ")"); break;
8332 case 0x05: out.push(blob.read_shift(2)); break;
8333 case 0x06: {
8334 /* TODO: text encoding */
8335 var Z = ""; while((cc = blob[blob.l++])) Z += String.fromCharCode(cc);
8336 out.push('"' + Z.replace(/"/g, '""') + '"'); break;
8337 } break;
8338
8339 case 0x08: out.push("-" + out.pop()); break;
8340 case 0x17: out.push("+" + out.pop()); break;
8341 case 0x16: out.push("NOT(" + out.pop() + ")"); break;
8342
8343 case 0x14: case 0x15: {
8344 var argR = out.pop(), argL = out.pop();
8345 out.push(["AND", "OR"][cc - 0x14] + "(" + argL + "," + argR + ")");
8346 } break;
8347
8348 default:
8349 if(cc < 0x20 && BinOpTab[cc]) {
8350 argR = out.pop(); argL = out.pop();
8351 out.push(argL + BinOpTab[cc] + argR);
8352 } else if(FuncTab[cc]) {
8353 argc = FuncTab[cc][1];
8354 if(argc == 69) argc = blob[blob.l++];
8355 if(argc > out.length) { console.error("WK1 bad formula parse 0x" + cc.toString(16) + ":|" + out.join("|") + "|"); return; }
8356 var args = out.slice(-argc);
8357 out.length -= argc;
8358 out.push(FuncTab[cc][0] + "(" + args.join(",") + ")");
8359 }
8360 else if(cc <= 0x07) return console.error("WK1 invalid opcode " + cc.toString(16));
8361 else if(cc <= 0x18) return console.error("WK1 unsupported op " + cc.toString(16));
8362 else if(cc <= 0x1E) return console.error("WK1 invalid opcode " + cc.toString(16));
8363 else if(cc <= 0x73) return console.error("WK1 unsupported function opcode " + cc.toString(16));
8364 // possible future functions ??
8365 else return console.error("WK1 unrecognized opcode " + cc.toString(16));
8366 }
8367 }
8368 if(out.length == 1) o[1].f = "" + out[0];
8369 else console.error("WK1 bad formula parse |" + out.join("|") + "|");
8370 }
8371
8372
8373 function parse_cell_3(blob) {
8374 var o = [{c:0,r:0}, {t:'n',v:0}, 0];
8375 o[0].r = blob.read_shift(2); o[3] = blob[blob.l++]; o[0].c = blob[blob.l++];
8376 return o;
8377 }
8378
8379 function parse_LABEL_16(blob, length) {
8380 var o = parse_cell_3(blob, length);
8381 o[1].t = 's';
8382 o[1].v = blob.read_shift(length - 4, 'cstr');
8383 return o;
8384 }
8385 function write_LABEL_16(R, C, wsidx, s) {
8386 /* TODO: encoding */
8387 var o = new_buf(6 + s.length);
8388 o.write_shift(2, R);
8389 o.write_shift(1, wsidx);
8390 o.write_shift(1, C);
8391 o.write_shift(1, 0x27);
8392 for(var i = 0; i < s.length; ++i) {
8393 var cc = s.charCodeAt(i);
8394 o.write_shift(1, cc >= 0x80 ? 0x5F : cc);
8395 }
8396 o.write_shift(1, 0);
8397 return o;
8398 }
8399
8400 function parse_NUMBER_18(blob, length) {
8401 var o = parse_cell_3(blob, length);
8402 o[1].v = blob.read_shift(2);
8403 var v = o[1].v >> 1;
8404 if(o[1].v & 0x1) {
8405 switch(v & 0x07) {
8406 case 0: v = (v >> 3) * 5000; break;
8407 case 1: v = (v >> 3) * 500; break;
8408 case 2: v = (v >> 3) / 20; break;
8409 case 3: v = (v >> 3) / 200; break;
8410 case 4: v = (v >> 3) / 2000; break;
8411 case 5: v = (v >> 3) / 20000; break;
8412 case 6: v = (v >> 3) / 16; break;
8413 case 7: v = (v >> 3) / 64; break;
8414 }
8415 }
8416 o[1].v = v;
8417 return o;
8418 }
8419
8420 function parse_NUMBER_17(blob, length) {
8421 var o = parse_cell_3(blob, length);
8422 var v1 = blob.read_shift(4);
8423 var v2 = blob.read_shift(4);
8424 var e = blob.read_shift(2);
8425 if(e == 0xFFFF) {
8426 if(v1 === 0 && v2 === 0xC0000000) { o[1].t = "e"; o[1].v = 0x0F; } // ERR -> #VALUE!
8427 else if(v1 === 0 && v2 === 0xD0000000) { o[1].t = "e"; o[1].v = 0x2A; } // NA -> #N/A
8428 else o[1].v = 0;
8429 return o;
8430 }
8431 var s = e & 0x8000; e = (e&0x7FFF) - 16446;
8432 o[1].v = (1 - s*2) * (v2 * Math.pow(2, e+32) + v1 * Math.pow(2, e));
8433 return o;
8434 }
8435 function write_NUMBER_17(R, C, wsidx, v) {
8436 var o = new_buf(14);
8437 o.write_shift(2, R);
8438 o.write_shift(1, wsidx);
8439 o.write_shift(1, C);
8440 if(v == 0) {
8441 o.write_shift(4, 0);
8442 o.write_shift(4, 0);
8443 o.write_shift(2, 0xFFFF);
8444 return o;
8445 }
8446 var s = 0, e = 0, v1 = 0, v2 = 0;
8447 if(v < 0) { s = 1; v = -v; }
8448 e = Math.log2(v) | 0;
8449 v /= Math.pow(2, e-31);
8450 v2 = (v)>>>0;
8451 if((v2&0x80000000) == 0) { v/=2; ++e; v2 = v >>> 0; }
8452 v -= v2;
8453 v2 |= 0x80000000;
8454 v2 >>>= 0;
8455 v *= Math.pow(2, 32);
8456 v1 = v>>>0;
8457 o.write_shift(4, v1);
8458 o.write_shift(4, v2);
8459 e += 0x3FFF + (s ? 0x8000 : 0);
8460 o.write_shift(2, e);
8461 return o;
8462 }
8463
8464 function parse_FORMULA_19(blob, length) {
8465 var o = parse_NUMBER_17(blob, 14);
8466 blob.l += length - 14; /* TODO: WK3 formula */
8467 return o;
8468 }
8469
8470 function parse_NUMBER_25(blob, length) {
8471 var o = parse_cell_3(blob, length);
8472 var v1 = blob.read_shift(4);
8473 o[1].v = v1 >> 6;
8474 return o;
8475 }
8476
8477 function parse_NUMBER_27(blob, length) {
8478 var o = parse_cell_3(blob, length);
8479 var v1 = blob.read_shift(8,'f');
8480 o[1].v = v1;
8481 return o;
8482 }
8483
8484 function parse_FORMULA_28(blob, length) {
8485 var o = parse_NUMBER_27(blob, 14);
8486 blob.l += length - 10; /* TODO: formula */
8487 return o;
8488 }
8489
8490 function parse_XFORMAT(blob, length) {
8491 var o = {}, tgt = blob.l + length;
8492 while(blob.l < tgt) {
8493 var dt = blob.read_shift(2);
8494 if(dt == 0x36b0) {
8495 o[dt] = [0, ""];
8496 o[dt][0] = blob.read_shift(2);
8497 while(blob[blob.l]) { o[dt][1] += String.fromCharCode(blob[blob.l]); blob.l++; } blob.l++;
8498 }
8499 // TODO: 0x3a99 ??
8500 }
8501 return o;
8502 }
8503 function write_XFORMAT_SHEETNAME(name, wsidx) {
8504 var out = new_buf(5 + name.length);
8505 out.write_shift(2, 0x36b0);
8506 out.write_shift(2, wsidx);
8507 for(var i = 0; i < name.length; ++i) {
8508 var cc = name.charCodeAt(i);
8509 out[out.l++] = cc > 0x7F ? 0x5F : cc;
8510 }
8511 out[out.l++] = 0;
8512 return out;
8513 }
8514
8515 var WK1Enum = {
85160x0000: { n:"BOF", f:parseuint16 },
85170x0001: { n:"EOF" },
85180x0002: { n:"CALCMODE" },
85190x0003: { n:"CALCORDER" },
85200x0004: { n:"SPLIT" },
85210x0005: { n:"SYNC" },
85220x0006: { n:"RANGE", f:parse_RANGE },
85230x0007: { n:"WINDOW1" },
85240x0008: { n:"COLW1" },
85250x0009: { n:"WINTWO" },
85260x000A: { n:"COLW2" },
85270x000B: { n:"NAME" },
85280x000C: { n:"BLANK" },
85290x000D: { n:"INTEGER", f:parse_INTEGER },
85300x000E: { n:"NUMBER", f:parse_NUMBER },
85310x000F: { n:"LABEL", f:parse_LABEL },
85320x0010: { n:"FORMULA", f:parse_FORMULA },
85330x0018: { n:"TABLE" },
85340x0019: { n:"ORANGE" },
85350x001A: { n:"PRANGE" },
85360x001B: { n:"SRANGE" },
85370x001C: { n:"FRANGE" },
85380x001D: { n:"KRANGE1" },
85390x0020: { n:"HRANGE" },
85400x0023: { n:"KRANGE2" },
85410x0024: { n:"PROTEC" },
85420x0025: { n:"FOOTER" },
85430x0026: { n:"HEADER" },
85440x0027: { n:"SETUP" },
85450x0028: { n:"MARGINS" },
85460x0029: { n:"LABELFMT" },
85470x002A: { n:"TITLES" },
85480x002B: { n:"SHEETJS" },
85490x002D: { n:"GRAPH" },
85500x002E: { n:"NGRAPH" },
85510x002F: { n:"CALCCOUNT" },
85520x0030: { n:"UNFORMATTED" },
85530x0031: { n:"CURSORW12" },
85540x0032: { n:"WINDOW" },
85550x0033: { n:"STRING", f:parse_LABEL },
85560x0037: { n:"PASSWORD" },
85570x0038: { n:"LOCKED" },
85580x003C: { n:"QUERY" },
85590x003D: { n:"QUERYNAME" },
85600x003E: { n:"PRINT" },
85610x003F: { n:"PRINTNAME" },
85620x0040: { n:"GRAPH2" },
85630x0041: { n:"GRAPHNAME" },
85640x0042: { n:"ZOOM" },
85650x0043: { n:"SYMSPLIT" },
85660x0044: { n:"NSROWS" },
85670x0045: { n:"NSCOLS" },
85680x0046: { n:"RULER" },
85690x0047: { n:"NNAME" },
85700x0048: { n:"ACOMM" },
85710x0049: { n:"AMACRO" },
85720x004A: { n:"PARSE" },
85730x0066: { n:"PRANGES??" },
85740x0067: { n:"RRANGES??" },
85750x0068: { n:"FNAME??" },
85760x0069: { n:"MRANGES??" },
85770xFFFF: { n:"" }
8578 };
8579
8580 var WK3Enum = {
85810x0000: { n:"BOF" },
85820x0001: { n:"EOF" },
85830x0002: { n:"PASSWORD" },
85840x0003: { n:"CALCSET" },
85850x0004: { n:"WINDOWSET" },
85860x0005: { n:"SHEETCELLPTR" },
85870x0006: { n:"SHEETLAYOUT" },
85880x0007: { n:"COLUMNWIDTH" },
85890x0008: { n:"HIDDENCOLUMN" },
85900x0009: { n:"USERRANGE" },
85910x000A: { n:"SYSTEMRANGE" },
85920x000B: { n:"ZEROFORCE" },
85930x000C: { n:"SORTKEYDIR" },
85940x000D: { n:"FILESEAL" },
85950x000E: { n:"DATAFILLNUMS" },
85960x000F: { n:"PRINTMAIN" },
85970x0010: { n:"PRINTSTRING" },
85980x0011: { n:"GRAPHMAIN" },
85990x0012: { n:"GRAPHSTRING" },
86000x0013: { n:"??" },
86010x0014: { n:"ERRCELL" },
86020x0015: { n:"NACELL" },
86030x0016: { n:"LABEL16", f:parse_LABEL_16},
86040x0017: { n:"NUMBER17", f:parse_NUMBER_17 },
86050x0018: { n:"NUMBER18", f:parse_NUMBER_18 },
86060x0019: { n:"FORMULA19", f:parse_FORMULA_19},
86070x001A: { n:"FORMULA1A" },
86080x001B: { n:"XFORMAT", f:parse_XFORMAT },
86090x001C: { n:"DTLABELMISC" },
86100x001D: { n:"DTLABELCELL" },
86110x001E: { n:"GRAPHWINDOW" },
86120x001F: { n:"CPA" },
86130x0020: { n:"LPLAUTO" },
86140x0021: { n:"QUERY" },
86150x0022: { n:"HIDDENSHEET" },
86160x0023: { n:"??" },
86170x0025: { n:"NUMBER25", f:parse_NUMBER_25 },
86180x0026: { n:"??" },
86190x0027: { n:"NUMBER27", f:parse_NUMBER_27 },
86200x0028: { n:"FORMULA28", f:parse_FORMULA_28 },
86210x008E: { n:"??" },
86220x0093: { n:"??" },
86230x0096: { n:"??" },
86240x0097: { n:"??" },
86250x0098: { n:"??" },
86260x0099: { n:"??" },
86270x009A: { n:"??" },
86280x009B: { n:"??" },
86290x009C: { n:"??" },
86300x00A3: { n:"??" },
86310x00AE: { n:"??" },
86320x00AF: { n:"??" },
86330x00B0: { n:"??" },
86340x00B1: { n:"??" },
86350x00B8: { n:"??" },
86360x00B9: { n:"??" },
86370x00BA: { n:"??" },
86380x00BB: { n:"??" },
86390x00BC: { n:"??" },
86400x00C3: { n:"??" },
86410x00C9: { n:"??" },
86420x00CD: { n:"??" },
86430x00CE: { n:"??" },
86440x00CF: { n:"??" },
86450x00D0: { n:"??" },
86460x0100: { n:"??" },
86470x0103: { n:"??" },
86480x0104: { n:"??" },
86490x0105: { n:"??" },
86500x0106: { n:"??" },
86510x0107: { n:"??" },
86520x0109: { n:"??" },
86530x010A: { n:"??" },
86540x010B: { n:"??" },
86550x010C: { n:"??" },
86560x010E: { n:"??" },
86570x010F: { n:"??" },
86580x0180: { n:"??" },
86590x0185: { n:"??" },
86600x0186: { n:"??" },
86610x0189: { n:"??" },
86620x018C: { n:"??" },
86630x0200: { n:"??" },
86640x0202: { n:"??" },
86650x0201: { n:"??" },
86660x0204: { n:"??" },
86670x0205: { n:"??" },
86680x0280: { n:"??" },
86690x0281: { n:"??" },
86700x0282: { n:"??" },
86710x0283: { n:"??" },
86720x0284: { n:"??" },
86730x0285: { n:"??" },
86740x0286: { n:"??" },
86750x0287: { n:"??" },
86760x0288: { n:"??" },
86770x0292: { n:"??" },
86780x0293: { n:"??" },
86790x0294: { n:"??" },
86800x0295: { n:"??" },
86810x0296: { n:"??" },
86820x0299: { n:"??" },
86830x029A: { n:"??" },
86840x0300: { n:"??" },
86850x0304: { n:"??" },
86860x0640: { n:"??" },
86870x0642: { n:"??" },
86880x0701: { n:"??" },
86890x0702: { n:"??" },
86900x0703: { n:"??" },
86910x0704: { n:"??" },
86920x0780: { n:"??" },
86930x0800: { n:"??" },
86940x0801: { n:"??" },
86950x0804: { n:"??" },
86960x0A80: { n:"??" },
86970x2AF6: { n:"??" },
86980x3231: { n:"??" },
86990x6E49: { n:"??" },
87000x6F44: { n:"??" },
87010xFFFF: { n:"" }
8702 };
8703 return {
8704 sheet_to_wk1: sheet_to_wk1,
8705 book_to_wk3: book_to_wk3,
8706 to_workbook: lotus_to_workbook
8707 };
8708})();
8709/* 18.4.7 rPr CT_RPrElt */
8710function parse_rpr(rpr) {
8711 var font = {}, m = rpr.match(tagregex), i = 0;
8712 var pass = false;
8713 if(m) for(;i!=m.length; ++i) {
8714 var y = parsexmltag(m[i]);
8715 switch(y[0].replace(/\w*:/g,"")) {
8716 /* 18.8.12 condense CT_BooleanProperty */
8717 /* ** not required . */
8718 case '<condense': break;
8719 /* 18.8.17 extend CT_BooleanProperty */
8720 /* ** not required . */
8721 case '<extend': break;
8722 /* 18.8.36 shadow CT_BooleanProperty */
8723 /* ** not required . */
8724 case '<shadow':
8725 if(!y.val) break;
8726 /* falls through */
8727 case '<shadow>':
8728 case '<shadow/>': font.shadow = 1; break;
8729 case '</shadow>': break;
8730
8731 /* 18.4.1 charset CT_IntProperty TODO */
8732 case '<charset':
8733 if(y.val == '1') break;
8734 font.cp = CS2CP[parseInt(y.val, 10)];
8735 break;
8736
8737 /* 18.4.2 outline CT_BooleanProperty TODO */
8738 case '<outline':
8739 if(!y.val) break;
8740 /* falls through */
8741 case '<outline>':
8742 case '<outline/>': font.outline = 1; break;
8743 case '</outline>': break;
8744
8745 /* 18.4.5 rFont CT_FontName */
8746 case '<rFont': font.name = y.val; break;
8747
8748 /* 18.4.11 sz CT_FontSize */
8749 case '<sz': font.sz = y.val; break;
8750
8751 /* 18.4.10 strike CT_BooleanProperty */
8752 case '<strike':
8753 if(!y.val) break;
8754 /* falls through */
8755 case '<strike>':
8756 case '<strike/>': font.strike = 1; break;
8757 case '</strike>': break;
8758
8759 /* 18.4.13 u CT_UnderlineProperty */
8760 case '<u':
8761 if(!y.val) break;
8762 switch(y.val) {
8763 case 'double': font.uval = "double"; break;
8764 case 'singleAccounting': font.uval = "single-accounting"; break;
8765 case 'doubleAccounting': font.uval = "double-accounting"; break;
8766 }
8767 /* falls through */
8768 case '<u>':
8769 case '<u/>': font.u = 1; break;
8770 case '</u>': break;
8771
8772 /* 18.8.2 b */
8773 case '<b':
8774 if(y.val == '0') break;
8775 /* falls through */
8776 case '<b>':
8777 case '<b/>': font.b = 1; break;
8778 case '</b>': break;
8779
8780 /* 18.8.26 i */
8781 case '<i':
8782 if(y.val == '0') break;
8783 /* falls through */
8784 case '<i>':
8785 case '<i/>': font.i = 1; break;
8786 case '</i>': break;
8787
8788 /* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */
8789 case '<color':
8790 if(y.rgb) font.color = y.rgb.slice(2,8);
8791 break;
8792
8793 /* 18.8.18 family ST_FontFamily */
8794 case '<family': font.family = y.val; break;
8795
8796 /* 18.4.14 vertAlign CT_VerticalAlignFontProperty TODO */
8797 case '<vertAlign': font.valign = y.val; break;
8798
8799 /* 18.8.35 scheme CT_FontScheme TODO */
8800 case '<scheme': break;
8801
8802 /* 18.2.10 extLst CT_ExtensionList ? */
8803 case '<extLst': case '<extLst>': case '</extLst>': break;
8804 case '<ext': pass = true; break;
8805 case '</ext>': pass = false; break;
8806 default:
8807 if(y[0].charCodeAt(1) !== 47 && !pass) throw new Error('Unrecognized rich format ' + y[0]);
8808 }
8809 }
8810 return font;
8811}
8812
8813var parse_rs = (function() {
8814 var tregex = matchtag("t"), rpregex = matchtag("rPr");
8815 /* 18.4.4 r CT_RElt */
8816 function parse_r(r) {
8817 /* 18.4.12 t ST_Xstring */
8818 var t = r.match(tregex)/*, cp = 65001*/;
8819 if(!t) return {t:"s", v:""};
8820
8821 var o = ({t:'s', v:unescapexml(t[1])});
8822 var rpr = r.match(rpregex);
8823 if(rpr) o.s = parse_rpr(rpr[1]);
8824 return o;
8825 }
8826 var rregex = /<(?:\w+:)?r>/g, rend = /<\/(?:\w+:)?r>/;
8827 return function parse_rs(rs) {
8828 return rs.replace(rregex,"").split(rend).map(parse_r).filter(function(r) { return r.v; });
8829 };
8830})();
8831
8832
8833/* Parse a list of <r> tags */
8834var rs_to_html = (function parse_rs_factory() {
8835 var nlregex = /(\r\n|\n)/g;
8836 function parse_rpr2(font, intro, outro) {
8837 var style = [];
8838
8839 if(font.u) style.push("text-decoration: underline;");
8840 if(font.uval) style.push("text-underline-style:" + font.uval + ";");
8841 if(font.sz) style.push("font-size:" + font.sz + "pt;");
8842 if(font.outline) style.push("text-effect: outline;");
8843 if(font.shadow) style.push("text-shadow: auto;");
8844 intro.push('<span style="' + style.join("") + '">');
8845
8846 if(font.b) { intro.push("<b>"); outro.push("</b>"); }
8847 if(font.i) { intro.push("<i>"); outro.push("</i>"); }
8848 if(font.strike) { intro.push("<s>"); outro.push("</s>"); }
8849
8850 var align = font.valign || "";
8851 if(align == "superscript" || align == "super") align = "sup";
8852 else if(align == "subscript") align = "sub";
8853 if(align != "") { intro.push("<" + align + ">"); outro.push("</" + align + ">"); }
8854
8855 outro.push("</span>");
8856 return font;
8857 }
8858
8859 /* 18.4.4 r CT_RElt */
8860 function r_to_html(r) {
8861 var terms = [[],r.v,[]];
8862 if(!r.v) return "";
8863
8864 if(r.s) parse_rpr2(r.s, terms[0], terms[2]);
8865
8866 return terms[0].join("") + terms[1].replace(nlregex,'<br/>') + terms[2].join("");
8867 }
8868
8869 return function parse_rs(rs) {
8870 return rs.map(r_to_html).join("");
8871 };
8872})();
8873
8874/* 18.4.8 si CT_Rst */
8875var sitregex = /<(?:\w+:)?t[^>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r>/;
8876var sirphregex = /<(?:\w+:)?rPh.*?>([\s\S]*?)<\/(?:\w+:)?rPh>/g;
8877function parse_si(x, opts) {
8878 var html = opts ? opts.cellHTML : true;
8879 var z = {};
8880 if(!x) return { t: "" };
8881 //var y;
8882 /* 18.4.12 t ST_Xstring (Plaintext String) */
8883 // TODO: is whitespace actually valid here?
8884 if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) {
8885 z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||""));
8886 z.r = utf8read(x);
8887 if(html) z.h = escapehtml(z.t);
8888 }
8889 /* 18.4.4 r CT_RElt (Rich Text Run) */
8890 else if((/*y = */x.match(sirregex))) {
8891 z.r = utf8read(x);
8892 z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")));
8893 if(html) z.h = rs_to_html(parse_rs(z.r));
8894 }
8895 /* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
8896 /* 18.4.6 rPh CT_PhoneticRun (TODO: needed for Asian support) */
8897 return z;
8898}
8899
8900/* 18.4 Shared String Table */
8901var sstr0 = /<(?:\w+:)?sst([^>]*)>([\s\S]*)<\/(?:\w+:)?sst>/;
8902var sstr1 = /<(?:\w+:)?(?:si|sstItem)>/g;
8903var sstr2 = /<\/(?:\w+:)?(?:si|sstItem)>/;
8904function parse_sst_xml(data, opts) {
8905 var s = ([]), ss = "";
8906 if(!data) return s;
8907 /* 18.4.9 sst CT_Sst */
8908 var sst = data.match(sstr0);
8909 if(sst) {
8910 ss = sst[2].replace(sstr1,"").split(sstr2);
8911 for(var i = 0; i != ss.length; ++i) {
8912 var o = parse_si(ss[i].trim(), opts);
8913 if(o != null) s[s.length] = o;
8914 }
8915 sst = parsexmltag(sst[1]); s.Count = sst.count; s.Unique = sst.uniqueCount;
8916 }
8917 return s;
8918}
8919
8920RELS.SST = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
8921var straywsregex = /^\s|\s$|[\t\n\r]/;
8922function write_sst_xml(sst, opts) {
8923 if(!opts.bookSST) return "";
8924 var o = [XML_HEADER];
8925 o[o.length] = (writextag('sst', null, {
8926 xmlns: XMLNS.main[0],
8927 count: sst.Count,
8928 uniqueCount: sst.Unique
8929 }));
8930 for(var i = 0; i != sst.length; ++i) { if(sst[i] == null) continue;
8931 var s = sst[i];
8932 var sitag = "<si>";
8933 if(s.r) sitag += s.r;
8934 else {
8935 sitag += "<t";
8936 if(!s.t) s.t = "";
8937 if(s.t.match(straywsregex)) sitag += ' xml:space="preserve"';
8938 sitag += ">" + escapexml(s.t) + "</t>";
8939 }
8940 sitag += "</si>";
8941 o[o.length] = (sitag);
8942 }
8943 if(o.length>2){ o[o.length] = ('</sst>'); o[1]=o[1].replace("/>",">"); }
8944 return o.join("");
8945}
8946/* [MS-XLSB] 2.4.221 BrtBeginSst */
8947function parse_BrtBeginSst(data) {
8948 return [data.read_shift(4), data.read_shift(4)];
8949}
8950
8951/* [MS-XLSB] 2.1.7.45 Shared Strings */
8952function parse_sst_bin(data, opts) {
8953 var s = ([]);
8954 var pass = false;
8955 recordhopper(data, function hopper_sst(val, R_n, RT) {
8956 switch(RT) {
8957 case 0x009F: /* 'BrtBeginSst' */
8958 s.Count = val[0]; s.Unique = val[1]; break;
8959 case 0x0013: /* 'BrtSSTItem' */
8960 s.push(val); break;
8961 case 0x00A0: /* 'BrtEndSst' */
8962 return true;
8963
8964 case 0x0023: /* 'BrtFRTBegin' */
8965 pass = true; break;
8966 case 0x0024: /* 'BrtFRTEnd' */
8967 pass = false; break;
8968
8969 default:
8970 if(R_n.indexOf("Begin") > 0){/* empty */}
8971 else if(R_n.indexOf("End") > 0){/* empty */}
8972 if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
8973 }
8974 });
8975 return s;
8976}
8977
8978function write_BrtBeginSst(sst, o) {
8979 if(!o) o = new_buf(8);
8980 o.write_shift(4, sst.Count);
8981 o.write_shift(4, sst.Unique);
8982 return o;
8983}
8984
8985var write_BrtSSTItem = write_RichStr;
8986
8987function write_sst_bin(sst) {
8988 var ba = buf_array();
8989 write_record(ba, "BrtBeginSst", write_BrtBeginSst(sst));
8990 for(var i = 0; i < sst.length; ++i) write_record(ba, "BrtSSTItem", write_BrtSSTItem(sst[i]));
8991 /* FRTSST */
8992 write_record(ba, "BrtEndSst");
8993 return ba.end();
8994}
8995function _JS2ANSI(str) {
8996 if(typeof cptable !== 'undefined') return cptable.utils.encode(current_ansi, str);
8997 var o = [], oo = str.split("");
8998 for(var i = 0; i < oo.length; ++i) o[i] = oo[i].charCodeAt(0);
8999 return o;
9000}
9001
9002/* [MS-OFFCRYPTO] 2.1.4 Version */
9003function parse_CRYPTOVersion(blob, length) {
9004 var o = {};
9005 o.Major = blob.read_shift(2);
9006 o.Minor = blob.read_shift(2);
9007if(length >= 4) blob.l += length - 4;
9008 return o;
9009}
9010
9011/* [MS-OFFCRYPTO] 2.1.5 DataSpaceVersionInfo */
9012function parse_DataSpaceVersionInfo(blob) {
9013 var o = {};
9014 o.id = blob.read_shift(0, 'lpp4');
9015 o.R = parse_CRYPTOVersion(blob, 4);
9016 o.U = parse_CRYPTOVersion(blob, 4);
9017 o.W = parse_CRYPTOVersion(blob, 4);
9018 return o;
9019}
9020
9021/* [MS-OFFCRYPTO] 2.1.6.1 DataSpaceMapEntry Structure */
9022function parse_DataSpaceMapEntry(blob) {
9023 var len = blob.read_shift(4);
9024 var end = blob.l + len - 4;
9025 var o = {};
9026 var cnt = blob.read_shift(4);
9027 var comps = [];
9028 /* [MS-OFFCRYPTO] 2.1.6.2 DataSpaceReferenceComponent Structure */
9029 while(cnt-- > 0) comps.push({ t: blob.read_shift(4), v: blob.read_shift(0, 'lpp4') });
9030 o.name = blob.read_shift(0, 'lpp4');
9031 o.comps = comps;
9032 if(blob.l != end) throw new Error("Bad DataSpaceMapEntry: " + blob.l + " != " + end);
9033 return o;
9034}
9035
9036/* [MS-OFFCRYPTO] 2.1.6 DataSpaceMap */
9037function parse_DataSpaceMap(blob) {
9038 var o = [];
9039 blob.l += 4; // must be 0x8
9040 var cnt = blob.read_shift(4);
9041 while(cnt-- > 0) o.push(parse_DataSpaceMapEntry(blob));
9042 return o;
9043}
9044
9045/* [MS-OFFCRYPTO] 2.1.7 DataSpaceDefinition */
9046function parse_DataSpaceDefinition(blob) {
9047 var o = [];
9048 blob.l += 4; // must be 0x8
9049 var cnt = blob.read_shift(4);
9050 while(cnt-- > 0) o.push(blob.read_shift(0, 'lpp4'));
9051 return o;
9052}
9053
9054/* [MS-OFFCRYPTO] 2.1.8 DataSpaceDefinition */
9055function parse_TransformInfoHeader(blob) {
9056 var o = {};
9057 /*var len = */blob.read_shift(4);
9058 blob.l += 4; // must be 0x1
9059 o.id = blob.read_shift(0, 'lpp4');
9060 o.name = blob.read_shift(0, 'lpp4');
9061 o.R = parse_CRYPTOVersion(blob, 4);
9062 o.U = parse_CRYPTOVersion(blob, 4);
9063 o.W = parse_CRYPTOVersion(blob, 4);
9064 return o;
9065}
9066
9067function parse_Primary(blob) {
9068 /* [MS-OFFCRYPTO] 2.2.6 IRMDSTransformInfo */
9069 var hdr = parse_TransformInfoHeader(blob);
9070 /* [MS-OFFCRYPTO] 2.1.9 EncryptionTransformInfo */
9071 hdr.ename = blob.read_shift(0, '8lpp4');
9072 hdr.blksz = blob.read_shift(4);
9073 hdr.cmode = blob.read_shift(4);
9074 if(blob.read_shift(4) != 0x04) throw new Error("Bad !Primary record");
9075 return hdr;
9076}
9077
9078/* [MS-OFFCRYPTO] 2.3.2 Encryption Header */
9079function parse_EncryptionHeader(blob, length) {
9080 var tgt = blob.l + length;
9081 var o = {};
9082 o.Flags = (blob.read_shift(4) & 0x3F);
9083 blob.l += 4;
9084 o.AlgID = blob.read_shift(4);
9085 var valid = false;
9086 switch(o.AlgID) {
9087 case 0x660E: case 0x660F: case 0x6610: valid = (o.Flags == 0x24); break;
9088 case 0x6801: valid = (o.Flags == 0x04); break;
9089 case 0: valid = (o.Flags == 0x10 || o.Flags == 0x04 || o.Flags == 0x24); break;
9090 default: throw 'Unrecognized encryption algorithm: ' + o.AlgID;
9091 }
9092 if(!valid) throw new Error("Encryption Flags/AlgID mismatch");
9093 o.AlgIDHash = blob.read_shift(4);
9094 o.KeySize = blob.read_shift(4);
9095 o.ProviderType = blob.read_shift(4);
9096 blob.l += 8;
9097 o.CSPName = blob.read_shift((tgt-blob.l)>>1, 'utf16le');
9098 blob.l = tgt;
9099 return o;
9100}
9101
9102/* [MS-OFFCRYPTO] 2.3.3 Encryption Verifier */
9103function parse_EncryptionVerifier(blob, length) {
9104 var o = {}, tgt = blob.l + length;
9105 blob.l += 4; // SaltSize must be 0x10
9106 o.Salt = blob.slice(blob.l, blob.l+16); blob.l += 16;
9107 o.Verifier = blob.slice(blob.l, blob.l+16); blob.l += 16;
9108 /*var sz = */blob.read_shift(4);
9109 o.VerifierHash = blob.slice(blob.l, tgt); blob.l = tgt;
9110 return o;
9111}
9112
9113/* [MS-OFFCRYPTO] 2.3.4.* EncryptionInfo Stream */
9114function parse_EncryptionInfo(blob) {
9115 var vers = parse_CRYPTOVersion(blob);
9116 switch(vers.Minor) {
9117 case 0x02: return [vers.Minor, parse_EncInfoStd(blob, vers)];
9118 case 0x03: return [vers.Minor, parse_EncInfoExt(blob, vers)];
9119 case 0x04: return [vers.Minor, parse_EncInfoAgl(blob, vers)];
9120 }
9121 throw new Error("ECMA-376 Encrypted file unrecognized Version: " + vers.Minor);
9122}
9123
9124/* [MS-OFFCRYPTO] 2.3.4.5 EncryptionInfo Stream (Standard Encryption) */
9125function parse_EncInfoStd(blob) {
9126 var flags = blob.read_shift(4);
9127 if((flags & 0x3F) != 0x24) throw new Error("EncryptionInfo mismatch");
9128 var sz = blob.read_shift(4);
9129 //var tgt = blob.l + sz;
9130 var hdr = parse_EncryptionHeader(blob, sz);
9131 var verifier = parse_EncryptionVerifier(blob, blob.length - blob.l);
9132 return { t:"Std", h:hdr, v:verifier };
9133}
9134/* [MS-OFFCRYPTO] 2.3.4.6 EncryptionInfo Stream (Extensible Encryption) */
9135function parse_EncInfoExt() { throw new Error("File is password-protected: ECMA-376 Extensible"); }
9136/* [MS-OFFCRYPTO] 2.3.4.10 EncryptionInfo Stream (Agile Encryption) */
9137function parse_EncInfoAgl(blob) {
9138 var KeyData = ["saltSize","blockSize","keyBits","hashSize","cipherAlgorithm","cipherChaining","hashAlgorithm","saltValue"];
9139 blob.l+=4;
9140 var xml = blob.read_shift(blob.length - blob.l, 'utf8');
9141 var o = {};
9142 xml.replace(tagregex, function xml_agile(x) {
9143 var y = parsexmltag(x);
9144 switch(strip_ns(y[0])) {
9145 case '<?xml': break;
9146 case '<encryption': case '</encryption>': break;
9147 case '<keyData': KeyData.forEach(function(k) { o[k] = y[k]; }); break;
9148 case '<dataIntegrity': o.encryptedHmacKey = y.encryptedHmacKey; o.encryptedHmacValue = y.encryptedHmacValue; break;
9149 case '<keyEncryptors>': case '<keyEncryptors': o.encs = []; break;
9150 case '</keyEncryptors>': break;
9151
9152 case '<keyEncryptor': o.uri = y.uri; break;
9153 case '</keyEncryptor>': break;
9154 case '<encryptedKey': o.encs.push(y); break;
9155 default: throw y[0];
9156 }
9157 });
9158 return o;
9159}
9160
9161/* [MS-OFFCRYPTO] 2.3.5.1 RC4 CryptoAPI Encryption Header */
9162function parse_RC4CryptoHeader(blob, length) {
9163 var o = {};
9164 var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4); length -= 4;
9165 if(vers.Minor != 2) throw new Error('unrecognized minor version code: ' + vers.Minor);
9166 if(vers.Major > 4 || vers.Major < 2) throw new Error('unrecognized major version code: ' + vers.Major);
9167 o.Flags = blob.read_shift(4); length -= 4;
9168 var sz = blob.read_shift(4); length -= 4;
9169 o.EncryptionHeader = parse_EncryptionHeader(blob, sz); length -= sz;
9170 o.EncryptionVerifier = parse_EncryptionVerifier(blob, length);
9171 return o;
9172}
9173/* [MS-OFFCRYPTO] 2.3.6.1 RC4 Encryption Header */
9174function parse_RC4Header(blob) {
9175 var o = {};
9176 var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4);
9177 if(vers.Major != 1 || vers.Minor != 1) throw 'unrecognized version code ' + vers.Major + ' : ' + vers.Minor;
9178 o.Salt = blob.read_shift(16);
9179 o.EncryptedVerifier = blob.read_shift(16);
9180 o.EncryptedVerifierHash = blob.read_shift(16);
9181 return o;
9182}
9183
9184/* [MS-OFFCRYPTO] 2.3.7.1 Binary Document Password Verifier Derivation */
9185function crypto_CreatePasswordVerifier_Method1(Password) {
9186 var Verifier = 0x0000, PasswordArray;
9187 var PasswordDecoded = _JS2ANSI(Password);
9188 var len = PasswordDecoded.length + 1, i, PasswordByte;
9189 var Intermediate1, Intermediate2, Intermediate3;
9190 PasswordArray = new_raw_buf(len);
9191 PasswordArray[0] = PasswordDecoded.length;
9192 for(i = 1; i != len; ++i) PasswordArray[i] = PasswordDecoded[i-1];
9193 for(i = len-1; i >= 0; --i) {
9194 PasswordByte = PasswordArray[i];
9195 Intermediate1 = ((Verifier & 0x4000) === 0x0000) ? 0 : 1;
9196 Intermediate2 = (Verifier << 1) & 0x7FFF;
9197 Intermediate3 = Intermediate1 | Intermediate2;
9198 Verifier = Intermediate3 ^ PasswordByte;
9199 }
9200 return Verifier ^ 0xCE4B;
9201}
9202
9203/* [MS-OFFCRYPTO] 2.3.7.2 Binary Document XOR Array Initialization */
9204var crypto_CreateXorArray_Method1 = (function() {
9205 var PadArray = [0xBB, 0xFF, 0xFF, 0xBA, 0xFF, 0xFF, 0xB9, 0x80, 0x00, 0xBE, 0x0F, 0x00, 0xBF, 0x0F, 0x00];
9206 var InitialCode = [0xE1F0, 0x1D0F, 0xCC9C, 0x84C0, 0x110C, 0x0E10, 0xF1CE, 0x313E, 0x1872, 0xE139, 0xD40F, 0x84F9, 0x280C, 0xA96A, 0x4EC3];
9207 var XorMatrix = [0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09, 0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF, 0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0, 0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40, 0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5, 0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A, 0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9, 0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0, 0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC, 0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10, 0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168, 0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C, 0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD, 0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC, 0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4];
9208 var Ror = function(Byte) { return ((Byte/2) | (Byte*128)) & 0xFF; };
9209 var XorRor = function(byte1, byte2) { return Ror(byte1 ^ byte2); };
9210 var CreateXorKey_Method1 = function(Password) {
9211 var XorKey = InitialCode[Password.length - 1];
9212 var CurrentElement = 0x68;
9213 for(var i = Password.length-1; i >= 0; --i) {
9214 var Char = Password[i];
9215 for(var j = 0; j != 7; ++j) {
9216 if(Char & 0x40) XorKey ^= XorMatrix[CurrentElement];
9217 Char *= 2; --CurrentElement;
9218 }
9219 }
9220 return XorKey;
9221 };
9222 return function(password) {
9223 var Password = _JS2ANSI(password);
9224 var XorKey = CreateXorKey_Method1(Password);
9225 var Index = Password.length;
9226 var ObfuscationArray = new_raw_buf(16);
9227 for(var i = 0; i != 16; ++i) ObfuscationArray[i] = 0x00;
9228 var Temp, PasswordLastChar, PadIndex;
9229 if((Index & 1) === 1) {
9230 Temp = XorKey >> 8;
9231 ObfuscationArray[Index] = XorRor(PadArray[0], Temp);
9232 --Index;
9233 Temp = XorKey & 0xFF;
9234 PasswordLastChar = Password[Password.length - 1];
9235 ObfuscationArray[Index] = XorRor(PasswordLastChar, Temp);
9236 }
9237 while(Index > 0) {
9238 --Index;
9239 Temp = XorKey >> 8;
9240 ObfuscationArray[Index] = XorRor(Password[Index], Temp);
9241 --Index;
9242 Temp = XorKey & 0xFF;
9243 ObfuscationArray[Index] = XorRor(Password[Index], Temp);
9244 }
9245 Index = 15;
9246 PadIndex = 15 - Password.length;
9247 while(PadIndex > 0) {
9248 Temp = XorKey >> 8;
9249 ObfuscationArray[Index] = XorRor(PadArray[PadIndex], Temp);
9250 --Index;
9251 --PadIndex;
9252 Temp = XorKey & 0xFF;
9253 ObfuscationArray[Index] = XorRor(Password[Index], Temp);
9254 --Index;
9255 --PadIndex;
9256 }
9257 return ObfuscationArray;
9258 };
9259})();
9260
9261/* [MS-OFFCRYPTO] 2.3.7.3 Binary Document XOR Data Transformation Method 1 */
9262var crypto_DecryptData_Method1 = function(password, Data, XorArrayIndex, XorArray, O) {
9263 /* If XorArray is set, use it; if O is not set, make changes in-place */
9264 if(!O) O = Data;
9265 if(!XorArray) XorArray = crypto_CreateXorArray_Method1(password);
9266 var Index, Value;
9267 for(Index = 0; Index != Data.length; ++Index) {
9268 Value = Data[Index];
9269 Value ^= XorArray[XorArrayIndex];
9270 Value = ((Value>>5) | (Value<<3)) & 0xFF;
9271 O[Index] = Value;
9272 ++XorArrayIndex;
9273 }
9274 return [O, XorArrayIndex, XorArray];
9275};
9276
9277var crypto_MakeXorDecryptor = function(password) {
9278 var XorArrayIndex = 0, XorArray = crypto_CreateXorArray_Method1(password);
9279 return function(Data) {
9280 var O = crypto_DecryptData_Method1("", Data, XorArrayIndex, XorArray);
9281 XorArrayIndex = O[1];
9282 return O[0];
9283 };
9284};
9285
9286/* 2.5.343 */
9287function parse_XORObfuscation(blob, length, opts, out) {
9288 var o = ({ key: parseuint16(blob), verificationBytes: parseuint16(blob) });
9289 if(opts.password) o.verifier = crypto_CreatePasswordVerifier_Method1(opts.password);
9290 out.valid = o.verificationBytes === o.verifier;
9291 if(out.valid) out.insitu = crypto_MakeXorDecryptor(opts.password);
9292 return o;
9293}
9294
9295/* 2.4.117 */
9296function parse_FilePassHeader(blob, length, oo) {
9297 var o = oo || {}; o.Info = blob.read_shift(2); blob.l -= 2;
9298 if(o.Info === 1) o.Data = parse_RC4Header(blob, length);
9299 else o.Data = parse_RC4CryptoHeader(blob, length);
9300 return o;
9301}
9302function parse_FilePass(blob, length, opts) {
9303 var o = ({ Type: opts.biff >= 8 ? blob.read_shift(2) : 0 }); /* wEncryptionType */
9304 if(o.Type) parse_FilePassHeader(blob, length-2, o);
9305 else parse_XORObfuscation(blob, opts.biff >= 8 ? length : length - 2, opts, o);
9306 return o;
9307}
9308
9309
9310var RTF = (function() {
9311 function rtf_to_sheet(d, opts) {
9312 switch(opts.type) {
9313 case 'base64': return rtf_to_sheet_str(Base64.decode(d), opts);
9314 case 'binary': return rtf_to_sheet_str(d, opts);
9315 case 'buffer': return rtf_to_sheet_str(has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d), opts);
9316 case 'array': return rtf_to_sheet_str(cc2str(d), opts);
9317 }
9318 throw new Error("Unrecognized type " + opts.type);
9319 }
9320
9321 /* TODO: this is a stub */
9322 function rtf_to_sheet_str(str, opts) {
9323 var o = opts || {};
9324 var ws = o.dense ? ([]) : ({});
9325
9326 var rows = str.match(/\\trowd.*?\\row\b/g);
9327 if(!rows.length) throw new Error("RTF missing table");
9328 var range = ({s: {c:0, r:0}, e: {c:0, r:rows.length - 1}});
9329 rows.forEach(function(rowtf, R) {
9330 if(Array.isArray(ws)) ws[R] = [];
9331 var rtfre = /\\\w+\b/g;
9332 var last_index = 0;
9333 var res;
9334 var C = -1;
9335 while((res = rtfre.exec(rowtf))) {
9336 switch(res[0]) {
9337 case "\\cell":
9338 var data = rowtf.slice(last_index, rtfre.lastIndex - res[0].length);
9339 if(data[0] == " ") data = data.slice(1);
9340 ++C;
9341 if(data.length) {
9342 // TODO: value parsing, including codepage adjustments
9343 var cell = {v: data, t:"s"};
9344 if(Array.isArray(ws)) ws[R][C] = cell;
9345 else ws[encode_cell({r:R, c:C})] = cell;
9346 }
9347 break;
9348 }
9349 last_index = rtfre.lastIndex;
9350 }
9351 if(C > range.e.c) range.e.c = C;
9352 });
9353 ws['!ref'] = encode_range(range);
9354 return ws;
9355 }
9356
9357 function rtf_to_workbook(d, opts) { return sheet_to_workbook(rtf_to_sheet(d, opts), opts); }
9358
9359 /* TODO: this is a stub */
9360 function sheet_to_rtf(ws) {
9361 var o = ["{\\rtf1\\ansi"];
9362 var r = safe_decode_range(ws['!ref']), cell;
9363 var dense = Array.isArray(ws);
9364 for(var R = r.s.r; R <= r.e.r; ++R) {
9365 o.push("\\trowd\\trautofit1");
9366 for(var C = r.s.c; C <= r.e.c; ++C) o.push("\\cellx" + (C+1));
9367 o.push("\\pard\\intbl");
9368 for(C = r.s.c; C <= r.e.c; ++C) {
9369 var coord = encode_cell({r:R,c:C});
9370 cell = dense ? (ws[R]||[])[C]: ws[coord];
9371 if(!cell || cell.v == null && (!cell.f || cell.F)) continue;
9372 o.push(" " + (cell.w || (format_cell(cell), cell.w)));
9373 o.push("\\cell");
9374 }
9375 o.push("\\pard\\intbl\\row");
9376 }
9377 return o.join("") + "}";
9378 }
9379
9380 return {
9381 to_workbook: rtf_to_workbook,
9382 to_sheet: rtf_to_sheet,
9383 from_sheet: sheet_to_rtf
9384 };
9385})();
9386function hex2RGB(h) {
9387 var o = h.slice(h[0]==="#"?1:0).slice(0,6);
9388 return [parseInt(o.slice(0,2),16),parseInt(o.slice(2,4),16),parseInt(o.slice(4,6),16)];
9389}
9390function rgb2Hex(rgb) {
9391 for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);
9392 return o.toString(16).toUpperCase().slice(1);
9393}
9394
9395function rgb2HSL(rgb) {
9396 var R = rgb[0]/255, G = rgb[1]/255, B=rgb[2]/255;
9397 var M = Math.max(R, G, B), m = Math.min(R, G, B), C = M - m;
9398 if(C === 0) return [0, 0, R];
9399
9400 var H6 = 0, S = 0, L2 = (M + m);
9401 S = C / (L2 > 1 ? 2 - L2 : L2);
9402 switch(M){
9403 case R: H6 = ((G - B) / C + 6)%6; break;
9404 case G: H6 = ((B - R) / C + 2); break;
9405 case B: H6 = ((R - G) / C + 4); break;
9406 }
9407 return [H6 / 6, S, L2 / 2];
9408}
9409
9410function hsl2RGB(hsl){
9411 var H = hsl[0], S = hsl[1], L = hsl[2];
9412 var C = S * 2 * (L < 0.5 ? L : 1 - L), m = L - C/2;
9413 var rgb = [m,m,m], h6 = 6*H;
9414
9415 var X;
9416 if(S !== 0) switch(h6|0) {
9417 case 0: case 6: X = C * h6; rgb[0] += C; rgb[1] += X; break;
9418 case 1: X = C * (2 - h6); rgb[0] += X; rgb[1] += C; break;
9419 case 2: X = C * (h6 - 2); rgb[1] += C; rgb[2] += X; break;
9420 case 3: X = C * (4 - h6); rgb[1] += X; rgb[2] += C; break;
9421 case 4: X = C * (h6 - 4); rgb[2] += C; rgb[0] += X; break;
9422 case 5: X = C * (6 - h6); rgb[2] += X; rgb[0] += C; break;
9423 }
9424 for(var i = 0; i != 3; ++i) rgb[i] = Math.round(rgb[i]*255);
9425 return rgb;
9426}
9427
9428/* 18.8.3 bgColor tint algorithm */
9429function rgb_tint(hex, tint) {
9430 if(tint === 0) return hex;
9431 var hsl = rgb2HSL(hex2RGB(hex));
9432 if (tint < 0) hsl[2] = hsl[2] * (1 + tint);
9433 else hsl[2] = 1 - (1 - hsl[2]) * (1 - tint);
9434 return rgb2Hex(hsl2RGB(hsl));
9435}
9436
9437/* 18.3.1.13 width calculations */
9438/* [MS-OI29500] 2.1.595 Column Width & Formatting */
9439var DEF_MDW = 6, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
9440function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); }
9441function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; }
9442function char2width(chr) { return (Math.round((chr * MDW + 5)/MDW*256))/256; }
9443//function px2char_(px) { return (((px - 5)/MDW * 100 + 0.5))/100; }
9444//function char2width_(chr) { return (((chr * MDW + 5)/MDW*256))/256; }
9445function cycle_width(collw) { return char2width(px2char(width2px(collw))); }
9446/* XLSX/XLSB/XLS specify width in units of MDW */
9447function find_mdw_colw(collw) {
9448 var delta = Math.abs(collw - cycle_width(collw)), _MDW = MDW;
9449 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; }
9450 MDW = _MDW;
9451}
9452/* XLML specifies width in terms of pixels */
9453/*function find_mdw_wpx(wpx) {
9454 var delta = Infinity, guess = 0, _MDW = MIN_MDW;
9455 for(MDW=MIN_MDW; MDW<MAX_MDW; ++MDW) {
9456 guess = char2width_(px2char_(wpx))*256;
9457 guess = (guess) % 1;
9458 if(guess > 0.5) guess--;
9459 if(Math.abs(guess) < delta) { delta = Math.abs(guess); _MDW = MDW; }
9460 }
9461 MDW = _MDW;
9462}*/
9463
9464function process_col(coll) {
9465 if(coll.width) {
9466 coll.wpx = width2px(coll.width);
9467 coll.wch = px2char(coll.wpx);
9468 coll.MDW = MDW;
9469 } else if(coll.wpx) {
9470 coll.wch = px2char(coll.wpx);
9471 coll.width = char2width(coll.wch);
9472 coll.MDW = MDW;
9473 } else if(typeof coll.wch == 'number') {
9474 coll.width = char2width(coll.wch);
9475 coll.wpx = width2px(coll.width);
9476 coll.MDW = MDW;
9477 }
9478 if(coll.customWidth) delete coll.customWidth;
9479}
9480
9481var DEF_PPI = 96, PPI = DEF_PPI;
9482function px2pt(px) { return px * 96 / PPI; }
9483function pt2px(pt) { return pt * PPI / 96; }
9484
9485/* [MS-EXSPXML3] 2.4.54 ST_enmPattern */
9486var XLMLPatternTypeMap = {
9487 "None": "none",
9488 "Solid": "solid",
9489 "Gray50": "mediumGray",
9490 "Gray75": "darkGray",
9491 "Gray25": "lightGray",
9492 "HorzStripe": "darkHorizontal",
9493 "VertStripe": "darkVertical",
9494 "ReverseDiagStripe": "darkDown",
9495 "DiagStripe": "darkUp",
9496 "DiagCross": "darkGrid",
9497 "ThickDiagCross": "darkTrellis",
9498 "ThinHorzStripe": "lightHorizontal",
9499 "ThinVertStripe": "lightVertical",
9500 "ThinReverseDiagStripe": "lightDown",
9501 "ThinHorzCross": "lightGrid"
9502};
9503
9504/* 18.8.5 borders CT_Borders */
9505function parse_borders(t, styles, themes, opts) {
9506 styles.Borders = [];
9507 var border = {};
9508 var pass = false;
9509 (t[0].match(tagregex)||[]).forEach(function(x) {
9510 var y = parsexmltag(x);
9511 switch(strip_ns(y[0])) {
9512 case '<borders': case '<borders>': case '</borders>': break;
9513
9514 /* 18.8.4 border CT_Border */
9515 case '<border': case '<border>': case '<border/>':
9516 border = {};
9517 if(y.diagonalUp) border.diagonalUp = parsexmlbool(y.diagonalUp);
9518 if(y.diagonalDown) border.diagonalDown = parsexmlbool(y.diagonalDown);
9519 styles.Borders.push(border);
9520 break;
9521 case '</border>': break;
9522
9523 /* note: not in spec, appears to be CT_BorderPr */
9524 case '<left/>': break;
9525 case '<left': case '<left>': break;
9526 case '</left>': break;
9527
9528 /* note: not in spec, appears to be CT_BorderPr */
9529 case '<right/>': break;
9530 case '<right': case '<right>': break;
9531 case '</right>': break;
9532
9533 /* 18.8.43 top CT_BorderPr */
9534 case '<top/>': break;
9535 case '<top': case '<top>': break;
9536 case '</top>': break;
9537
9538 /* 18.8.6 bottom CT_BorderPr */
9539 case '<bottom/>': break;
9540 case '<bottom': case '<bottom>': break;
9541 case '</bottom>': break;
9542
9543 /* 18.8.13 diagonal CT_BorderPr */
9544 case '<diagonal': case '<diagonal>': case '<diagonal/>': break;
9545 case '</diagonal>': break;
9546
9547 /* 18.8.25 horizontal CT_BorderPr */
9548 case '<horizontal': case '<horizontal>': case '<horizontal/>': break;
9549 case '</horizontal>': break;
9550
9551 /* 18.8.44 vertical CT_BorderPr */
9552 case '<vertical': case '<vertical>': case '<vertical/>': break;
9553 case '</vertical>': break;
9554
9555 /* 18.8.37 start CT_BorderPr */
9556 case '<start': case '<start>': case '<start/>': break;
9557 case '</start>': break;
9558
9559 /* 18.8.16 end CT_BorderPr */
9560 case '<end': case '<end>': case '<end/>': break;
9561 case '</end>': break;
9562
9563 /* 18.8.? color CT_Color */
9564 case '<color': case '<color>':
9565 break;
9566 case '<color/>': case '</color>': break;
9567
9568 /* 18.2.10 extLst CT_ExtensionList ? */
9569 case '<extLst': case '<extLst>': case '</extLst>': break;
9570 case '<ext': pass = true; break;
9571 case '</ext>': pass = false; break;
9572 default: if(opts && opts.WTF) {
9573 if(!pass) throw new Error('unrecognized ' + y[0] + ' in borders');
9574 }
9575 }
9576 });
9577}
9578
9579/* 18.8.21 fills CT_Fills */
9580function parse_fills(t, styles, themes, opts) {
9581 styles.Fills = [];
9582 var fill = {};
9583 var pass = false;
9584 (t[0].match(tagregex)||[]).forEach(function(x) {
9585 var y = parsexmltag(x);
9586 switch(strip_ns(y[0])) {
9587 case '<fills': case '<fills>': case '</fills>': break;
9588
9589 /* 18.8.20 fill CT_Fill */
9590 case '<fill>': case '<fill': case '<fill/>':
9591 fill = {}; styles.Fills.push(fill); break;
9592 case '</fill>': break;
9593
9594 /* 18.8.24 gradientFill CT_GradientFill */
9595 case '<gradientFill>': break;
9596 case '<gradientFill':
9597 case '</gradientFill>': styles.Fills.push(fill); fill = {}; break;
9598
9599 /* 18.8.32 patternFill CT_PatternFill */
9600 case '<patternFill': case '<patternFill>':
9601 if(y.patternType) fill.patternType = y.patternType;
9602 break;
9603 case '<patternFill/>': case '</patternFill>': break;
9604
9605 /* 18.8.3 bgColor CT_Color */
9606 case '<bgColor':
9607 if(!fill.bgColor) fill.bgColor = {};
9608 if(y.indexed) fill.bgColor.indexed = parseInt(y.indexed, 10);
9609 if(y.theme) fill.bgColor.theme = parseInt(y.theme, 10);
9610 if(y.tint) fill.bgColor.tint = parseFloat(y.tint);
9611 /* Excel uses ARGB strings */
9612 if(y.rgb) fill.bgColor.rgb = y.rgb.slice(-6);
9613 break;
9614 case '<bgColor/>': case '</bgColor>': break;
9615
9616 /* 18.8.19 fgColor CT_Color */
9617 case '<fgColor':
9618 if(!fill.fgColor) fill.fgColor = {};
9619 if(y.theme) fill.fgColor.theme = parseInt(y.theme, 10);
9620 if(y.tint) fill.fgColor.tint = parseFloat(y.tint);
9621 /* Excel uses ARGB strings */
9622 if(y.rgb != null) fill.fgColor.rgb = y.rgb.slice(-6);
9623 break;
9624 case '<fgColor/>': case '</fgColor>': break;
9625
9626 /* 18.8.38 stop CT_GradientStop */
9627 case '<stop': case '<stop/>': break;
9628 case '</stop>': break;
9629
9630 /* 18.8.? color CT_Color */
9631 case '<color': case '<color/>': break;
9632 case '</color>': break;
9633
9634 /* 18.2.10 extLst CT_ExtensionList ? */
9635 case '<extLst': case '<extLst>': case '</extLst>': break;
9636 case '<ext': pass = true; break;
9637 case '</ext>': pass = false; break;
9638 default: if(opts && opts.WTF) {
9639 if(!pass) throw new Error('unrecognized ' + y[0] + ' in fills');
9640 }
9641 }
9642 });
9643}
9644
9645/* 18.8.23 fonts CT_Fonts */
9646function parse_fonts(t, styles, themes, opts) {
9647 styles.Fonts = [];
9648 var font = {};
9649 var pass = false;
9650 (t[0].match(tagregex)||[]).forEach(function(x) {
9651 var y = parsexmltag(x);
9652 switch(strip_ns(y[0])) {
9653 case '<fonts': case '<fonts>': case '</fonts>': break;
9654
9655 /* 18.8.22 font CT_Font */
9656 case '<font': case '<font>': break;
9657 case '</font>': case '<font/>':
9658 styles.Fonts.push(font);
9659 font = {};
9660 break;
9661
9662 /* 18.8.29 name CT_FontName */
9663 case '<name': if(y.val) font.name = utf8read(y.val); break;
9664 case '<name/>': case '</name>': break;
9665
9666 /* 18.8.2 b CT_BooleanProperty */
9667 case '<b': font.bold = y.val ? parsexmlbool(y.val) : 1; break;
9668 case '<b/>': font.bold = 1; break;
9669
9670 /* 18.8.26 i CT_BooleanProperty */
9671 case '<i': font.italic = y.val ? parsexmlbool(y.val) : 1; break;
9672 case '<i/>': font.italic = 1; break;
9673
9674 /* 18.4.13 u CT_UnderlineProperty */
9675 case '<u':
9676 switch(y.val) {
9677 case "none": font.underline = 0x00; break;
9678 case "single": font.underline = 0x01; break;
9679 case "double": font.underline = 0x02; break;
9680 case "singleAccounting": font.underline = 0x21; break;
9681 case "doubleAccounting": font.underline = 0x22; break;
9682 } break;
9683 case '<u/>': font.underline = 1; break;
9684
9685 /* 18.4.10 strike CT_BooleanProperty */
9686 case '<strike': font.strike = y.val ? parsexmlbool(y.val) : 1; break;
9687 case '<strike/>': font.strike = 1; break;
9688
9689 /* 18.4.2 outline CT_BooleanProperty */
9690 case '<outline': font.outline = y.val ? parsexmlbool(y.val) : 1; break;
9691 case '<outline/>': font.outline = 1; break;
9692
9693 /* 18.8.36 shadow CT_BooleanProperty */
9694 case '<shadow': font.shadow = y.val ? parsexmlbool(y.val) : 1; break;
9695 case '<shadow/>': font.shadow = 1; break;
9696
9697 /* 18.8.12 condense CT_BooleanProperty */
9698 case '<condense': font.condense = y.val ? parsexmlbool(y.val) : 1; break;
9699 case '<condense/>': font.condense = 1; break;
9700
9701 /* 18.8.17 extend CT_BooleanProperty */
9702 case '<extend': font.extend = y.val ? parsexmlbool(y.val) : 1; break;
9703 case '<extend/>': font.extend = 1; break;
9704
9705 /* 18.4.11 sz CT_FontSize */
9706 case '<sz': if(y.val) font.sz = +y.val; break;
9707 case '<sz/>': case '</sz>': break;
9708
9709 /* 18.4.14 vertAlign CT_VerticalAlignFontProperty */
9710 case '<vertAlign': if(y.val) font.vertAlign = y.val; break;
9711 case '<vertAlign/>': case '</vertAlign>': break;
9712
9713 /* 18.8.18 family CT_FontFamily */
9714 case '<family': if(y.val) font.family = parseInt(y.val,10); break;
9715 case '<family/>': case '</family>': break;
9716
9717 /* 18.8.35 scheme CT_FontScheme */
9718 case '<scheme': if(y.val) font.scheme = y.val; break;
9719 case '<scheme/>': case '</scheme>': break;
9720
9721 /* 18.4.1 charset CT_IntProperty */
9722 case '<charset':
9723 if(y.val == '1') break;
9724 y.codepage = CS2CP[parseInt(y.val, 10)];
9725 break;
9726
9727 /* 18.?.? color CT_Color */
9728 case '<color':
9729 if(!font.color) font.color = {};
9730 if(y.auto) font.color.auto = parsexmlbool(y.auto);
9731
9732 if(y.rgb) font.color.rgb = y.rgb.slice(-6);
9733 else if(y.indexed) {
9734 font.color.index = parseInt(y.indexed, 10);
9735 var icv = XLSIcv[font.color.index];
9736 if(font.color.index == 81) icv = XLSIcv[1];
9737 if(!icv) icv = XLSIcv[1]; //throw new Error(x); // note: 206 is valid
9738 font.color.rgb = icv[0].toString(16) + icv[1].toString(16) + icv[2].toString(16);
9739 } else if(y.theme) {
9740 font.color.theme = parseInt(y.theme, 10);
9741 if(y.tint) font.color.tint = parseFloat(y.tint);
9742 if(y.theme && themes.themeElements && themes.themeElements.clrScheme) {
9743 font.color.rgb = rgb_tint(themes.themeElements.clrScheme[font.color.theme].rgb, font.color.tint || 0);
9744 }
9745 }
9746
9747 break;
9748 case '<color/>': case '</color>': break;
9749
9750 /* note: sometimes mc:AlternateContent appears bare */
9751 case '<AlternateContent': pass = true; break;
9752 case '</AlternateContent>': pass = false; break;
9753
9754 /* 18.2.10 extLst CT_ExtensionList ? */
9755 case '<extLst': case '<extLst>': case '</extLst>': break;
9756 case '<ext': pass = true; break;
9757 case '</ext>': pass = false; break;
9758 default: if(opts && opts.WTF) {
9759 if(!pass) throw new Error('unrecognized ' + y[0] + ' in fonts');
9760 }
9761 }
9762 });
9763}
9764
9765/* 18.8.31 numFmts CT_NumFmts */
9766function parse_numFmts(t, styles, opts) {
9767 styles.NumberFmt = [];
9768 var k/*Array<number>*/ = (keys(SSF._table));
9769 for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
9770 var m = t[0].match(tagregex);
9771 if(!m) return;
9772 for(i=0; i < m.length; ++i) {
9773 var y = parsexmltag(m[i]);
9774 switch(strip_ns(y[0])) {
9775 case '<numFmts': case '</numFmts>': case '<numFmts/>': case '<numFmts>': break;
9776 case '<numFmt': {
9777 var f=unescapexml(utf8read(y.formatCode)), j=parseInt(y.numFmtId,10);
9778 styles.NumberFmt[j] = f;
9779 if(j>0) {
9780 if(j > 0x188) {
9781 for(j = 0x188; j > 0x3c; --j) if(styles.NumberFmt[j] == null) break;
9782 styles.NumberFmt[j] = f;
9783 }
9784 SSF.load(f,j);
9785 }
9786 } break;
9787 case '</numFmt>': break;
9788 default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in numFmts');
9789 }
9790 }
9791}
9792
9793function write_numFmts(NF) {
9794 var o = ["<numFmts>"];
9795 [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
9796 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])}));
9797 });
9798 if(o.length === 1) return "";
9799 o[o.length] = ("</numFmts>");
9800 o[0] = writextag('numFmts', null, { count:o.length-2 }).replace("/>", ">");
9801 return o.join("");
9802}
9803
9804/* 18.8.10 cellXfs CT_CellXfs */
9805var cellXF_uint = [ "numFmtId", "fillId", "fontId", "borderId", "xfId" ];
9806var cellXF_bool = [ "applyAlignment", "applyBorder", "applyFill", "applyFont", "applyNumberFormat", "applyProtection", "pivotButton", "quotePrefix" ];
9807function parse_cellXfs(t, styles, opts) {
9808 styles.CellXf = [];
9809 var xf;
9810 var pass = false;
9811 (t[0].match(tagregex)||[]).forEach(function(x) {
9812 var y = parsexmltag(x), i = 0;
9813 switch(strip_ns(y[0])) {
9814 case '<cellXfs': case '<cellXfs>': case '<cellXfs/>': case '</cellXfs>': break;
9815
9816 /* 18.8.45 xf CT_Xf */
9817 case '<xf': case '<xf/>':
9818 xf = y;
9819 delete xf[0];
9820 for(i = 0; i < cellXF_uint.length; ++i) if(xf[cellXF_uint[i]])
9821 xf[cellXF_uint[i]] = parseInt(xf[cellXF_uint[i]], 10);
9822 for(i = 0; i < cellXF_bool.length; ++i) if(xf[cellXF_bool[i]])
9823 xf[cellXF_bool[i]] = parsexmlbool(xf[cellXF_bool[i]]);
9824 if(styles.NumberFmt && xf.numFmtId > 0x188) {
9825 for(i = 0x188; i > 0x3c; --i) if(styles.NumberFmt[xf.numFmtId] == styles.NumberFmt[i]) { xf.numFmtId = i; break; }
9826 }
9827 styles.CellXf.push(xf); break;
9828 case '</xf>': break;
9829
9830 /* 18.8.1 alignment CT_CellAlignment */
9831 case '<alignment': case '<alignment/>':
9832 var alignment = {};
9833 if(y.vertical) alignment.vertical = y.vertical;
9834 if(y.horizontal) alignment.horizontal = y.horizontal;
9835 if(y.textRotation != null) alignment.textRotation = y.textRotation;
9836 if(y.indent) alignment.indent = y.indent;
9837 if(y.wrapText) alignment.wrapText = parsexmlbool(y.wrapText);
9838 xf.alignment = alignment;
9839 break;
9840 case '</alignment>': break;
9841
9842 /* 18.8.33 protection CT_CellProtection */
9843 case '<protection':
9844 break;
9845 case '</protection>': case '<protection/>': break;
9846
9847 /* note: sometimes mc:AlternateContent appears bare */
9848 case '<AlternateContent': pass = true; break;
9849 case '</AlternateContent>': pass = false; break;
9850
9851 /* 18.2.10 extLst CT_ExtensionList ? */
9852 case '<extLst': case '<extLst>': case '</extLst>': break;
9853 case '<ext': pass = true; break;
9854 case '</ext>': pass = false; break;
9855 default: if(opts && opts.WTF) {
9856 if(!pass) throw new Error('unrecognized ' + y[0] + ' in cellXfs');
9857 }
9858 }
9859 });
9860}
9861
9862function write_cellXfs(cellXfs) {
9863 var o = [];
9864 o[o.length] = (writextag('cellXfs',null));
9865 cellXfs.forEach(function(c) {
9866 o[o.length] = (writextag('xf', null, c));
9867 });
9868 o[o.length] = ("</cellXfs>");
9869 if(o.length === 2) return "";
9870 o[0] = writextag('cellXfs',null, {count:o.length-2}).replace("/>",">");
9871 return o.join("");
9872}
9873
9874/* 18.8 Styles CT_Stylesheet*/
9875var parse_sty_xml= (function make_pstyx() {
9876var numFmtRegex = /<(?:\w+:)?numFmts([^>]*)>[\S\s]*?<\/(?:\w+:)?numFmts>/;
9877var cellXfRegex = /<(?:\w+:)?cellXfs([^>]*)>[\S\s]*?<\/(?:\w+:)?cellXfs>/;
9878var fillsRegex = /<(?:\w+:)?fills([^>]*)>[\S\s]*?<\/(?:\w+:)?fills>/;
9879var fontsRegex = /<(?:\w+:)?fonts([^>]*)>[\S\s]*?<\/(?:\w+:)?fonts>/;
9880var bordersRegex = /<(?:\w+:)?borders([^>]*)>[\S\s]*?<\/(?:\w+:)?borders>/;
9881
9882return function parse_sty_xml(data, themes, opts) {
9883 var styles = {};
9884 if(!data) return styles;
9885 data = data.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
9886 /* 18.8.39 styleSheet CT_Stylesheet */
9887 var t;
9888
9889 /* 18.8.31 numFmts CT_NumFmts ? */
9890 if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts);
9891
9892 /* 18.8.23 fonts CT_Fonts ? */
9893 if((t=data.match(fontsRegex))) parse_fonts(t, styles, themes, opts);
9894
9895 /* 18.8.21 fills CT_Fills ? */
9896 if((t=data.match(fillsRegex))) parse_fills(t, styles, themes, opts);
9897
9898 /* 18.8.5 borders CT_Borders ? */
9899 if((t=data.match(bordersRegex))) parse_borders(t, styles, themes, opts);
9900
9901 /* 18.8.9 cellStyleXfs CT_CellStyleXfs ? */
9902 /* 18.8.8 cellStyles CT_CellStyles ? */
9903
9904 /* 18.8.10 cellXfs CT_CellXfs ? */
9905 if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts);
9906
9907 /* 18.8.15 dxfs CT_Dxfs ? */
9908 /* 18.8.42 tableStyles CT_TableStyles ? */
9909 /* 18.8.11 colors CT_Colors ? */
9910 /* 18.2.10 extLst CT_ExtensionList ? */
9911
9912 return styles;
9913};
9914})();
9915
9916var STYLES_XML_ROOT = writextag('styleSheet', null, {
9917 'xmlns': XMLNS.main[0],
9918 'xmlns:vt': XMLNS.vt
9919});
9920
9921RELS.STY = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
9922
9923function write_sty_xml(wb, opts) {
9924 var o = [XML_HEADER, STYLES_XML_ROOT], w;
9925 if(wb.SSF && (w = write_numFmts(wb.SSF)) != null) o[o.length] = w;
9926 o[o.length] = ('<fonts count="1"><font><sz val="12"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font></fonts>');
9927 o[o.length] = ('<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
9928 o[o.length] = ('<borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>');
9929 o[o.length] = ('<cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>');
9930 if((w = write_cellXfs(opts.cellXfs))) o[o.length] = (w);
9931 o[o.length] = ('<cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles>');
9932 o[o.length] = ('<dxfs count="0"/>');
9933 o[o.length] = ('<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleMedium4"/>');
9934
9935 if(o.length>2){ o[o.length] = ('</styleSheet>'); o[1]=o[1].replace("/>",">"); }
9936 return o.join("");
9937}
9938/* [MS-XLSB] 2.4.657 BrtFmt */
9939function parse_BrtFmt(data, length) {
9940 var numFmtId = data.read_shift(2);
9941 var stFmtCode = parse_XLWideString(data,length-2);
9942 return [numFmtId, stFmtCode];
9943}
9944function write_BrtFmt(i, f, o) {
9945 if(!o) o = new_buf(6 + 4 * f.length);
9946 o.write_shift(2, i);
9947 write_XLWideString(f, o);
9948 var out = (o.length > o.l) ? o.slice(0, o.l) : o;
9949 if(o.l == null) o.l = o.length;
9950 return out;
9951}
9952
9953/* [MS-XLSB] 2.4.659 BrtFont TODO */
9954function parse_BrtFont(data, length, opts) {
9955 var out = ({});
9956
9957 out.sz = data.read_shift(2) / 20;
9958
9959 var grbit = parse_FontFlags(data, 2, opts);
9960 if(grbit.fItalic) out.italic = 1;
9961 if(grbit.fCondense) out.condense = 1;
9962 if(grbit.fExtend) out.extend = 1;
9963 if(grbit.fShadow) out.shadow = 1;
9964 if(grbit.fOutline) out.outline = 1;
9965 if(grbit.fStrikeout) out.strike = 1;
9966
9967 var bls = data.read_shift(2);
9968 if(bls === 0x02BC) out.bold = 1;
9969
9970 switch(data.read_shift(2)) {
9971 /* case 0: out.vertAlign = "baseline"; break; */
9972 case 1: out.vertAlign = "superscript"; break;
9973 case 2: out.vertAlign = "subscript"; break;
9974 }
9975
9976 var underline = data.read_shift(1);
9977 if(underline != 0) out.underline = underline;
9978
9979 var family = data.read_shift(1);
9980 if(family > 0) out.family = family;
9981
9982 var bCharSet = data.read_shift(1);
9983 if(bCharSet > 0) out.charset = bCharSet;
9984
9985 data.l++;
9986 out.color = parse_BrtColor(data, 8);
9987
9988 switch(data.read_shift(1)) {
9989 /* case 0: out.scheme = "none": break; */
9990 case 1: out.scheme = "major"; break;
9991 case 2: out.scheme = "minor"; break;
9992 }
9993
9994 out.name = parse_XLWideString(data, length - 21);
9995
9996 return out;
9997}
9998function write_BrtFont(font, o) {
9999 if(!o) o = new_buf(25+4*32);
10000 o.write_shift(2, font.sz * 20);
10001 write_FontFlags(font, o);
10002 o.write_shift(2, font.bold ? 0x02BC : 0x0190);
10003 var sss = 0;
10004 if(font.vertAlign == "superscript") sss = 1;
10005 else if(font.vertAlign == "subscript") sss = 2;
10006 o.write_shift(2, sss);
10007 o.write_shift(1, font.underline || 0);
10008 o.write_shift(1, font.family || 0);
10009 o.write_shift(1, font.charset || 0);
10010 o.write_shift(1, 0);
10011 write_BrtColor(font.color, o);
10012 var scheme = 0;
10013 if(font.scheme == "major") scheme = 1;
10014 if(font.scheme == "minor") scheme = 2;
10015 o.write_shift(1, scheme);
10016 write_XLWideString(font.name, o);
10017 return o.length > o.l ? o.slice(0, o.l) : o;
10018}
10019
10020/* [MS-XLSB] 2.4.650 BrtFill */
10021var XLSBFillPTNames = [
10022 "none",
10023 "solid",
10024 "mediumGray",
10025 "darkGray",
10026 "lightGray",
10027 "darkHorizontal",
10028 "darkVertical",
10029 "darkDown",
10030 "darkUp",
10031 "darkGrid",
10032 "darkTrellis",
10033 "lightHorizontal",
10034 "lightVertical",
10035 "lightDown",
10036 "lightUp",
10037 "lightGrid",
10038 "lightTrellis",
10039 "gray125",
10040 "gray0625"
10041];
10042var rev_XLSBFillPTNames = (evert(XLSBFillPTNames));
10043/* TODO: gradient fill representation */
10044var parse_BrtFill = parsenoop;
10045function write_BrtFill(fill, o) {
10046 if(!o) o = new_buf(4*3 + 8*7 + 16*1);
10047 var fls = rev_XLSBFillPTNames[fill.patternType];
10048 if(fls == null) fls = 0x28;
10049 o.write_shift(4, fls);
10050 var j = 0;
10051 if(fls != 0x28) {
10052 /* TODO: custom FG Color */
10053 write_BrtColor({auto:1}, o);
10054 /* TODO: custom BG Color */
10055 write_BrtColor({auto:1}, o);
10056
10057 for(; j < 12; ++j) o.write_shift(4, 0);
10058 } else {
10059 for(; j < 4; ++j) o.write_shift(4, 0);
10060
10061 for(; j < 12; ++j) o.write_shift(4, 0); /* TODO */
10062 /* iGradientType */
10063 /* xnumDegree */
10064 /* xnumFillToLeft */
10065 /* xnumFillToRight */
10066 /* xnumFillToTop */
10067 /* xnumFillToBottom */
10068 /* cNumStop */
10069 /* xfillGradientStop */
10070 }
10071 return o.length > o.l ? o.slice(0, o.l) : o;
10072}
10073
10074/* [MS-XLSB] 2.4.824 BrtXF */
10075function parse_BrtXF(data, length) {
10076 var tgt = data.l + length;
10077 var ixfeParent = data.read_shift(2);
10078 var ifmt = data.read_shift(2);
10079 data.l = tgt;
10080 return {ixfe:ixfeParent, numFmtId:ifmt };
10081}
10082function write_BrtXF(data, ixfeP, o) {
10083 if(!o) o = new_buf(16);
10084 o.write_shift(2, ixfeP||0);
10085 o.write_shift(2, data.numFmtId||0);
10086 o.write_shift(2, 0); /* iFont */
10087 o.write_shift(2, 0); /* iFill */
10088 o.write_shift(2, 0); /* ixBorder */
10089 o.write_shift(1, 0); /* trot */
10090 o.write_shift(1, 0); /* indent */
10091 var flow = 0;
10092 o.write_shift(1, flow); /* flags */
10093 o.write_shift(1, 0); /* flags */
10094 o.write_shift(1, 0); /* xfGrbitAtr */
10095 o.write_shift(1, 0);
10096 return o;
10097}
10098
10099/* [MS-XLSB] 2.5.4 Blxf TODO */
10100function write_Blxf(data, o) {
10101 if(!o) o = new_buf(10);
10102 o.write_shift(1, 0); /* dg */
10103 o.write_shift(1, 0);
10104 o.write_shift(4, 0); /* color */
10105 o.write_shift(4, 0); /* color */
10106 return o;
10107}
10108/* [MS-XLSB] 2.4.302 BrtBorder TODO */
10109var parse_BrtBorder = parsenoop;
10110function write_BrtBorder(border, o) {
10111 if(!o) o = new_buf(51);
10112 o.write_shift(1, 0); /* diagonal */
10113 write_Blxf(null, o); /* top */
10114 write_Blxf(null, o); /* bottom */
10115 write_Blxf(null, o); /* left */
10116 write_Blxf(null, o); /* right */
10117 write_Blxf(null, o); /* diag */
10118 return o.length > o.l ? o.slice(0, o.l) : o;
10119}
10120
10121/* [MS-XLSB] 2.4.763 BrtStyle TODO */
10122function write_BrtStyle(style, o) {
10123 if(!o) o = new_buf(12+4*10);
10124 o.write_shift(4, style.xfId);
10125 o.write_shift(2, 1);
10126 o.write_shift(1, +style.builtinId);
10127 o.write_shift(1, 0); /* iLevel */
10128 write_XLNullableWideString(style.name || "", o);
10129 return o.length > o.l ? o.slice(0, o.l) : o;
10130}
10131
10132/* [MS-XLSB] 2.4.272 BrtBeginTableStyles */
10133function write_BrtBeginTableStyles(cnt, defTableStyle, defPivotStyle) {
10134 var o = new_buf(4+256*2*4);
10135 o.write_shift(4, cnt);
10136 write_XLNullableWideString(defTableStyle, o);
10137 write_XLNullableWideString(defPivotStyle, o);
10138 return o.length > o.l ? o.slice(0, o.l) : o;
10139}
10140
10141/* [MS-XLSB] 2.1.7.50 Styles */
10142function parse_sty_bin(data, themes, opts) {
10143 var styles = {};
10144 styles.NumberFmt = ([]);
10145 for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y];
10146
10147 styles.CellXf = [];
10148 styles.Fonts = [];
10149 var state = [];
10150 var pass = false;
10151 recordhopper(data, function hopper_sty(val, R_n, RT) {
10152 switch(RT) {
10153 case 0x002C: /* 'BrtFmt' */
10154 styles.NumberFmt[val[0]] = val[1]; SSF.load(val[1], val[0]);
10155 break;
10156 case 0x002B: /* 'BrtFont' */
10157 styles.Fonts.push(val);
10158 if(val.color.theme != null && themes && themes.themeElements && themes.themeElements.clrScheme) {
10159 val.color.rgb = rgb_tint(themes.themeElements.clrScheme[val.color.theme].rgb, val.color.tint || 0);
10160 }
10161 break;
10162 case 0x0401: /* 'BrtKnownFonts' */ break;
10163 case 0x002D: /* 'BrtFill' */
10164 break;
10165 case 0x002E: /* 'BrtBorder' */
10166 break;
10167 case 0x002F: /* 'BrtXF' */
10168 if(state[state.length - 1] == "BrtBeginCellXFs") {
10169 styles.CellXf.push(val);
10170 }
10171 break;
10172 case 0x0030: /* 'BrtStyle' */
10173 case 0x01FB: /* 'BrtDXF' */
10174 case 0x023C: /* 'BrtMRUColor' */
10175 case 0x01DB: /* 'BrtIndexedColor': */
10176 break;
10177
10178 case 0x0493: /* 'BrtDXF14' */
10179 case 0x0836: /* 'BrtDXF15' */
10180 case 0x046A: /* 'BrtSlicerStyleElement' */
10181 case 0x0200: /* 'BrtTableStyleElement' */
10182 case 0x082F: /* 'BrtTimelineStyleElement' */
10183 case 0x0C00: /* 'BrtUid' */
10184 break;
10185
10186 case 0x0023: /* 'BrtFRTBegin' */
10187 pass = true; break;
10188 case 0x0024: /* 'BrtFRTEnd' */
10189 pass = false; break;
10190 case 0x0025: /* 'BrtACBegin' */
10191 state.push(R_n); pass = true; break;
10192 case 0x0026: /* 'BrtACEnd' */
10193 state.pop(); pass = false; break;
10194
10195 default:
10196 if((R_n||"").indexOf("Begin") > 0) state.push(R_n);
10197 else if((R_n||"").indexOf("End") > 0) state.pop();
10198 else if(!pass || (opts.WTF && state[state.length-1] != "BrtACBegin")) throw new Error("Unexpected record " + RT + " " + R_n);
10199 }
10200 });
10201 return styles;
10202}
10203
10204function write_FMTS_bin(ba, NF) {
10205 if(!NF) return;
10206 var cnt = 0;
10207 [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
10208for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) ++cnt;
10209 });
10210
10211 if(cnt == 0) return;
10212 write_record(ba, "BrtBeginFmts", write_UInt32LE(cnt));
10213 [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
10214for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_record(ba, "BrtFmt", write_BrtFmt(i, NF[i]));
10215 });
10216 write_record(ba, "BrtEndFmts");
10217}
10218
10219function write_FONTS_bin(ba) {
10220 var cnt = 1;
10221
10222 if(cnt == 0) return;
10223 write_record(ba, "BrtBeginFonts", write_UInt32LE(cnt));
10224 write_record(ba, "BrtFont", write_BrtFont({
10225 sz:12,
10226 color: {theme:1},
10227 name: "Calibri",
10228 family: 2,
10229 scheme: "minor"
10230 }));
10231 /* 1*65491BrtFont [ACFONTS] */
10232 write_record(ba, "BrtEndFonts");
10233}
10234
10235function write_FILLS_bin(ba) {
10236 var cnt = 2;
10237
10238 if(cnt == 0) return;
10239 write_record(ba, "BrtBeginFills", write_UInt32LE(cnt));
10240 write_record(ba, "BrtFill", write_BrtFill({patternType:"none"}));
10241 write_record(ba, "BrtFill", write_BrtFill({patternType:"gray125"}));
10242 /* 1*65431BrtFill */
10243 write_record(ba, "BrtEndFills");
10244}
10245
10246function write_BORDERS_bin(ba) {
10247 var cnt = 1;
10248
10249 if(cnt == 0) return;
10250 write_record(ba, "BrtBeginBorders", write_UInt32LE(cnt));
10251 write_record(ba, "BrtBorder", write_BrtBorder({}));
10252 /* 1*65430BrtBorder */
10253 write_record(ba, "BrtEndBorders");
10254}
10255
10256function write_CELLSTYLEXFS_bin(ba) {
10257 var cnt = 1;
10258 write_record(ba, "BrtBeginCellStyleXFs", write_UInt32LE(cnt));
10259 write_record(ba, "BrtXF", write_BrtXF({
10260 numFmtId: 0,
10261 fontId: 0,
10262 fillId: 0,
10263 borderId: 0
10264 }, 0xFFFF));
10265 /* 1*65430(BrtXF *FRT) */
10266 write_record(ba, "BrtEndCellStyleXFs");
10267}
10268
10269function write_CELLXFS_bin(ba, data) {
10270 write_record(ba, "BrtBeginCellXFs", write_UInt32LE(data.length));
10271 data.forEach(function(c) { write_record(ba, "BrtXF", write_BrtXF(c,0)); });
10272 /* 1*65430(BrtXF *FRT) */
10273 write_record(ba, "BrtEndCellXFs");
10274}
10275
10276function write_STYLES_bin(ba) {
10277 var cnt = 1;
10278
10279 write_record(ba, "BrtBeginStyles", write_UInt32LE(cnt));
10280 write_record(ba, "BrtStyle", write_BrtStyle({
10281 xfId:0,
10282 builtinId:0,
10283 name:"Normal"
10284 }));
10285 /* 1*65430(BrtStyle *FRT) */
10286 write_record(ba, "BrtEndStyles");
10287}
10288
10289function write_DXFS_bin(ba) {
10290 var cnt = 0;
10291
10292 write_record(ba, "BrtBeginDXFs", write_UInt32LE(cnt));
10293 /* *2147483647(BrtDXF *FRT) */
10294 write_record(ba, "BrtEndDXFs");
10295}
10296
10297function write_TABLESTYLES_bin(ba) {
10298 var cnt = 0;
10299
10300 write_record(ba, "BrtBeginTableStyles", write_BrtBeginTableStyles(cnt, "TableStyleMedium9", "PivotStyleMedium4"));
10301 /* *TABLESTYLE */
10302 write_record(ba, "BrtEndTableStyles");
10303}
10304
10305function write_COLORPALETTE_bin() {
10306 return;
10307 /* BrtBeginColorPalette [INDEXEDCOLORS] [MRUCOLORS] BrtEndColorPalette */
10308}
10309
10310/* [MS-XLSB] 2.1.7.50 Styles */
10311function write_sty_bin(wb, opts) {
10312 var ba = buf_array();
10313 write_record(ba, "BrtBeginStyleSheet");
10314 write_FMTS_bin(ba, wb.SSF);
10315 write_FONTS_bin(ba, wb);
10316 write_FILLS_bin(ba, wb);
10317 write_BORDERS_bin(ba, wb);
10318 write_CELLSTYLEXFS_bin(ba, wb);
10319 write_CELLXFS_bin(ba, opts.cellXfs);
10320 write_STYLES_bin(ba, wb);
10321 write_DXFS_bin(ba, wb);
10322 write_TABLESTYLES_bin(ba, wb);
10323 write_COLORPALETTE_bin(ba, wb);
10324 /* FRTSTYLESHEET*/
10325 write_record(ba, "BrtEndStyleSheet");
10326 return ba.end();
10327}
10328RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
10329
10330/* Even though theme layout is dk1 lt1 dk2 lt2, true order is lt1 dk1 lt2 dk2 */
10331var XLSXThemeClrScheme = [
10332 '</a:lt1>', '</a:dk1>', '</a:lt2>', '</a:dk2>',
10333 '</a:accent1>', '</a:accent2>', '</a:accent3>',
10334 '</a:accent4>', '</a:accent5>', '</a:accent6>',
10335 '</a:hlink>', '</a:folHlink>'
10336];
10337/* 20.1.6.2 clrScheme CT_ColorScheme */
10338function parse_clrScheme(t, themes, opts) {
10339 themes.themeElements.clrScheme = [];
10340 var color = {};
10341 (t[0].match(tagregex)||[]).forEach(function(x) {
10342 var y = parsexmltag(x);
10343 switch(y[0]) {
10344 /* 20.1.6.2 clrScheme (Color Scheme) CT_ColorScheme */
10345 case '<a:clrScheme': case '</a:clrScheme>': break;
10346
10347 /* 20.1.2.3.32 srgbClr CT_SRgbColor */
10348 case '<a:srgbClr':
10349 color.rgb = y.val; break;
10350
10351 /* 20.1.2.3.33 sysClr CT_SystemColor */
10352 case '<a:sysClr':
10353 color.rgb = y.lastClr; break;
10354
10355 /* 20.1.4.1.1 accent1 (Accent 1) */
10356 /* 20.1.4.1.2 accent2 (Accent 2) */
10357 /* 20.1.4.1.3 accent3 (Accent 3) */
10358 /* 20.1.4.1.4 accent4 (Accent 4) */
10359 /* 20.1.4.1.5 accent5 (Accent 5) */
10360 /* 20.1.4.1.6 accent6 (Accent 6) */
10361 /* 20.1.4.1.9 dk1 (Dark 1) */
10362 /* 20.1.4.1.10 dk2 (Dark 2) */
10363 /* 20.1.4.1.15 folHlink (Followed Hyperlink) */
10364 /* 20.1.4.1.19 hlink (Hyperlink) */
10365 /* 20.1.4.1.22 lt1 (Light 1) */
10366 /* 20.1.4.1.23 lt2 (Light 2) */
10367 case '<a:dk1>': case '</a:dk1>':
10368 case '<a:lt1>': case '</a:lt1>':
10369 case '<a:dk2>': case '</a:dk2>':
10370 case '<a:lt2>': case '</a:lt2>':
10371 case '<a:accent1>': case '</a:accent1>':
10372 case '<a:accent2>': case '</a:accent2>':
10373 case '<a:accent3>': case '</a:accent3>':
10374 case '<a:accent4>': case '</a:accent4>':
10375 case '<a:accent5>': case '</a:accent5>':
10376 case '<a:accent6>': case '</a:accent6>':
10377 case '<a:hlink>': case '</a:hlink>':
10378 case '<a:folHlink>': case '</a:folHlink>':
10379 if (y[0].charAt(1) === '/') {
10380 themes.themeElements.clrScheme[XLSXThemeClrScheme.indexOf(y[0])] = color;
10381 color = {};
10382 } else {
10383 color.name = y[0].slice(3, y[0].length - 1);
10384 }
10385 break;
10386
10387 default: if(opts && opts.WTF) throw new Error('Unrecognized ' + y[0] + ' in clrScheme');
10388 }
10389 });
10390}
10391
10392/* 20.1.4.1.18 fontScheme CT_FontScheme */
10393function parse_fontScheme() { }
10394
10395/* 20.1.4.1.15 fmtScheme CT_StyleMatrix */
10396function parse_fmtScheme() { }
10397
10398var clrsregex = /<a:clrScheme([^>]*)>[\s\S]*<\/a:clrScheme>/;
10399var fntsregex = /<a:fontScheme([^>]*)>[\s\S]*<\/a:fontScheme>/;
10400var fmtsregex = /<a:fmtScheme([^>]*)>[\s\S]*<\/a:fmtScheme>/;
10401
10402/* 20.1.6.10 themeElements CT_BaseStyles */
10403function parse_themeElements(data, themes, opts) {
10404 themes.themeElements = {};
10405
10406 var t;
10407
10408 [
10409 /* clrScheme CT_ColorScheme */
10410 ['clrScheme', clrsregex, parse_clrScheme],
10411 /* fontScheme CT_FontScheme */
10412 ['fontScheme', fntsregex, parse_fontScheme],
10413 /* fmtScheme CT_StyleMatrix */
10414 ['fmtScheme', fmtsregex, parse_fmtScheme]
10415 ].forEach(function(m) {
10416 if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements');
10417 m[2](t, themes, opts);
10418 });
10419}
10420
10421var themeltregex = /<a:themeElements([^>]*)>[\s\S]*<\/a:themeElements>/;
10422
10423/* 14.2.7 Theme Part */
10424function parse_theme_xml(data, opts) {
10425 /* 20.1.6.9 theme CT_OfficeStyleSheet */
10426 if(!data || data.length === 0) return parse_theme_xml(write_theme());
10427
10428 var t;
10429 var themes = {};
10430
10431 /* themeElements CT_BaseStyles */
10432 if(!(t=data.match(themeltregex))) throw new Error('themeElements not found in theme');
10433 parse_themeElements(t[0], themes, opts);
10434 themes.raw = data;
10435 return themes;
10436}
10437
10438function write_theme(Themes, opts) {
10439 if(opts && opts.themeXLSX) return opts.themeXLSX;
10440 if(Themes && typeof Themes.raw == "string") return Themes.raw;
10441 var o = [XML_HEADER];
10442 o[o.length] = '<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">';
10443 o[o.length] = '<a:themeElements>';
10444
10445 o[o.length] = '<a:clrScheme name="Office">';
10446 o[o.length] = '<a:dk1><a:sysClr val="windowText" lastClr="000000"/></a:dk1>';
10447 o[o.length] = '<a:lt1><a:sysClr val="window" lastClr="FFFFFF"/></a:lt1>';
10448 o[o.length] = '<a:dk2><a:srgbClr val="1F497D"/></a:dk2>';
10449 o[o.length] = '<a:lt2><a:srgbClr val="EEECE1"/></a:lt2>';
10450 o[o.length] = '<a:accent1><a:srgbClr val="4F81BD"/></a:accent1>';
10451 o[o.length] = '<a:accent2><a:srgbClr val="C0504D"/></a:accent2>';
10452 o[o.length] = '<a:accent3><a:srgbClr val="9BBB59"/></a:accent3>';
10453 o[o.length] = '<a:accent4><a:srgbClr val="8064A2"/></a:accent4>';
10454 o[o.length] = '<a:accent5><a:srgbClr val="4BACC6"/></a:accent5>';
10455 o[o.length] = '<a:accent6><a:srgbClr val="F79646"/></a:accent6>';
10456 o[o.length] = '<a:hlink><a:srgbClr val="0000FF"/></a:hlink>';
10457 o[o.length] = '<a:folHlink><a:srgbClr val="800080"/></a:folHlink>';
10458 o[o.length] = '</a:clrScheme>';
10459
10460 o[o.length] = '<a:fontScheme name="Office">';
10461 o[o.length] = '<a:majorFont>';
10462 o[o.length] = '<a:latin typeface="Cambria"/>';
10463 o[o.length] = '<a:ea typeface=""/>';
10464 o[o.length] = '<a:cs typeface=""/>';
10465 o[o.length] = '<a:font script="Jpan" typeface="MS Pゴシック"/>';
10466 o[o.length] = '<a:font script="Hang" typeface="맑은 고딕"/>';
10467 o[o.length] = '<a:font script="Hans" typeface="宋体"/>';
10468 o[o.length] = '<a:font script="Hant" typeface="新細明體"/>';
10469 o[o.length] = '<a:font script="Arab" typeface="Times New Roman"/>';
10470 o[o.length] = '<a:font script="Hebr" typeface="Times New Roman"/>';
10471 o[o.length] = '<a:font script="Thai" typeface="Tahoma"/>';
10472 o[o.length] = '<a:font script="Ethi" typeface="Nyala"/>';
10473 o[o.length] = '<a:font script="Beng" typeface="Vrinda"/>';
10474 o[o.length] = '<a:font script="Gujr" typeface="Shruti"/>';
10475 o[o.length] = '<a:font script="Khmr" typeface="MoolBoran"/>';
10476 o[o.length] = '<a:font script="Knda" typeface="Tunga"/>';
10477 o[o.length] = '<a:font script="Guru" typeface="Raavi"/>';
10478 o[o.length] = '<a:font script="Cans" typeface="Euphemia"/>';
10479 o[o.length] = '<a:font script="Cher" typeface="Plantagenet Cherokee"/>';
10480 o[o.length] = '<a:font script="Yiii" typeface="Microsoft Yi Baiti"/>';
10481 o[o.length] = '<a:font script="Tibt" typeface="Microsoft Himalaya"/>';
10482 o[o.length] = '<a:font script="Thaa" typeface="MV Boli"/>';
10483 o[o.length] = '<a:font script="Deva" typeface="Mangal"/>';
10484 o[o.length] = '<a:font script="Telu" typeface="Gautami"/>';
10485 o[o.length] = '<a:font script="Taml" typeface="Latha"/>';
10486 o[o.length] = '<a:font script="Syrc" typeface="Estrangelo Edessa"/>';
10487 o[o.length] = '<a:font script="Orya" typeface="Kalinga"/>';
10488 o[o.length] = '<a:font script="Mlym" typeface="Kartika"/>';
10489 o[o.length] = '<a:font script="Laoo" typeface="DokChampa"/>';
10490 o[o.length] = '<a:font script="Sinh" typeface="Iskoola Pota"/>';
10491 o[o.length] = '<a:font script="Mong" typeface="Mongolian Baiti"/>';
10492 o[o.length] = '<a:font script="Viet" typeface="Times New Roman"/>';
10493 o[o.length] = '<a:font script="Uigh" typeface="Microsoft Uighur"/>';
10494 o[o.length] = '<a:font script="Geor" typeface="Sylfaen"/>';
10495 o[o.length] = '</a:majorFont>';
10496 o[o.length] = '<a:minorFont>';
10497 o[o.length] = '<a:latin typeface="Calibri"/>';
10498 o[o.length] = '<a:ea typeface=""/>';
10499 o[o.length] = '<a:cs typeface=""/>';
10500 o[o.length] = '<a:font script="Jpan" typeface="MS Pゴシック"/>';
10501 o[o.length] = '<a:font script="Hang" typeface="맑은 고딕"/>';
10502 o[o.length] = '<a:font script="Hans" typeface="宋体"/>';
10503 o[o.length] = '<a:font script="Hant" typeface="新細明體"/>';
10504 o[o.length] = '<a:font script="Arab" typeface="Arial"/>';
10505 o[o.length] = '<a:font script="Hebr" typeface="Arial"/>';
10506 o[o.length] = '<a:font script="Thai" typeface="Tahoma"/>';
10507 o[o.length] = '<a:font script="Ethi" typeface="Nyala"/>';
10508 o[o.length] = '<a:font script="Beng" typeface="Vrinda"/>';
10509 o[o.length] = '<a:font script="Gujr" typeface="Shruti"/>';
10510 o[o.length] = '<a:font script="Khmr" typeface="DaunPenh"/>';
10511 o[o.length] = '<a:font script="Knda" typeface="Tunga"/>';
10512 o[o.length] = '<a:font script="Guru" typeface="Raavi"/>';
10513 o[o.length] = '<a:font script="Cans" typeface="Euphemia"/>';
10514 o[o.length] = '<a:font script="Cher" typeface="Plantagenet Cherokee"/>';
10515 o[o.length] = '<a:font script="Yiii" typeface="Microsoft Yi Baiti"/>';
10516 o[o.length] = '<a:font script="Tibt" typeface="Microsoft Himalaya"/>';
10517 o[o.length] = '<a:font script="Thaa" typeface="MV Boli"/>';
10518 o[o.length] = '<a:font script="Deva" typeface="Mangal"/>';
10519 o[o.length] = '<a:font script="Telu" typeface="Gautami"/>';
10520 o[o.length] = '<a:font script="Taml" typeface="Latha"/>';
10521 o[o.length] = '<a:font script="Syrc" typeface="Estrangelo Edessa"/>';
10522 o[o.length] = '<a:font script="Orya" typeface="Kalinga"/>';
10523 o[o.length] = '<a:font script="Mlym" typeface="Kartika"/>';
10524 o[o.length] = '<a:font script="Laoo" typeface="DokChampa"/>';
10525 o[o.length] = '<a:font script="Sinh" typeface="Iskoola Pota"/>';
10526 o[o.length] = '<a:font script="Mong" typeface="Mongolian Baiti"/>';
10527 o[o.length] = '<a:font script="Viet" typeface="Arial"/>';
10528 o[o.length] = '<a:font script="Uigh" typeface="Microsoft Uighur"/>';
10529 o[o.length] = '<a:font script="Geor" typeface="Sylfaen"/>';
10530 o[o.length] = '</a:minorFont>';
10531 o[o.length] = '</a:fontScheme>';
10532
10533 o[o.length] = '<a:fmtScheme name="Office">';
10534 o[o.length] = '<a:fillStyleLst>';
10535 o[o.length] = '<a:solidFill><a:schemeClr val="phClr"/></a:solidFill>';
10536 o[o.length] = '<a:gradFill rotWithShape="1">';
10537 o[o.length] = '<a:gsLst>';
10538 o[o.length] = '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="50000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
10539 o[o.length] = '<a:gs pos="35000"><a:schemeClr val="phClr"><a:tint val="37000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
10540 o[o.length] = '<a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="15000"/><a:satMod val="350000"/></a:schemeClr></a:gs>';
10541 o[o.length] = '</a:gsLst>';
10542 o[o.length] = '<a:lin ang="16200000" scaled="1"/>';
10543 o[o.length] = '</a:gradFill>';
10544 o[o.length] = '<a:gradFill rotWithShape="1">';
10545 o[o.length] = '<a:gsLst>';
10546 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>';
10547 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>';
10548 o[o.length] = '</a:gsLst>';
10549 o[o.length] = '<a:lin ang="16200000" scaled="0"/>';
10550 o[o.length] = '</a:gradFill>';
10551 o[o.length] = '</a:fillStyleLst>';
10552 o[o.length] = '<a:lnStyleLst>';
10553 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>';
10554 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>';
10555 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>';
10556 o[o.length] = '</a:lnStyleLst>';
10557 o[o.length] = '<a:effectStyleLst>';
10558 o[o.length] = '<a:effectStyle>';
10559 o[o.length] = '<a:effectLst>';
10560 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>';
10561 o[o.length] = '</a:effectLst>';
10562 o[o.length] = '</a:effectStyle>';
10563 o[o.length] = '<a:effectStyle>';
10564 o[o.length] = '<a:effectLst>';
10565 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>';
10566 o[o.length] = '</a:effectLst>';
10567 o[o.length] = '</a:effectStyle>';
10568 o[o.length] = '<a:effectStyle>';
10569 o[o.length] = '<a:effectLst>';
10570 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>';
10571 o[o.length] = '</a:effectLst>';
10572 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>';
10573 o[o.length] = '<a:sp3d><a:bevelT w="63500" h="25400"/></a:sp3d>';
10574 o[o.length] = '</a:effectStyle>';
10575 o[o.length] = '</a:effectStyleLst>';
10576 o[o.length] = '<a:bgFillStyleLst>';
10577 o[o.length] = '<a:solidFill><a:schemeClr val="phClr"/></a:solidFill>';
10578 o[o.length] = '<a:gradFill rotWithShape="1">';
10579 o[o.length] = '<a:gsLst>';
10580 o[o.length] = '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="40000"/><a:satMod val="350000"/></a:schemeClr></a:gs>';
10581 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>';
10582 o[o.length] = '<a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="20000"/><a:satMod val="255000"/></a:schemeClr></a:gs>';
10583 o[o.length] = '</a:gsLst>';
10584 o[o.length] = '<a:path path="circle"><a:fillToRect l="50000" t="-80000" r="50000" b="180000"/></a:path>';
10585 o[o.length] = '</a:gradFill>';
10586 o[o.length] = '<a:gradFill rotWithShape="1">';
10587 o[o.length] = '<a:gsLst>';
10588 o[o.length] = '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="80000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
10589 o[o.length] = '<a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="30000"/><a:satMod val="200000"/></a:schemeClr></a:gs>';
10590 o[o.length] = '</a:gsLst>';
10591 o[o.length] = '<a:path path="circle"><a:fillToRect l="50000" t="50000" r="50000" b="50000"/></a:path>';
10592 o[o.length] = '</a:gradFill>';
10593 o[o.length] = '</a:bgFillStyleLst>';
10594 o[o.length] = '</a:fmtScheme>';
10595 o[o.length] = '</a:themeElements>';
10596
10597 o[o.length] = '<a:objectDefaults>';
10598 o[o.length] = '<a:spDef>';
10599 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>';
10600 o[o.length] = '</a:spDef>';
10601 o[o.length] = '<a:lnDef>';
10602 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>';
10603 o[o.length] = '</a:lnDef>';
10604 o[o.length] = '</a:objectDefaults>';
10605 o[o.length] = '<a:extraClrSchemeLst/>';
10606 o[o.length] = '</a:theme>';
10607 return o.join("");
10608}
10609/* [MS-XLS] 2.4.326 TODO: payload is a zip file */
10610function parse_Theme(blob, length, opts) {
10611 var end = blob.l + length;
10612 var dwThemeVersion = blob.read_shift(4);
10613 if(dwThemeVersion === 124226) return;
10614 if(!opts.cellStyles) { blob.l = end; return; }
10615 var data = blob.slice(blob.l);
10616 blob.l = end;
10617 var zip; try { zip = zip_read(data, {type: "array"}); } catch(e) { return; }
10618 var themeXML = getzipstr(zip, "theme/theme/theme1.xml", true);
10619 if(!themeXML) return;
10620 return parse_theme_xml(themeXML, opts);
10621}
10622
10623/* 2.5.49 */
10624function parse_ColorTheme(blob) { return blob.read_shift(4); }
10625
10626/* 2.5.155 */
10627function parse_FullColorExt(blob) {
10628 var o = {};
10629 o.xclrType = blob.read_shift(2);
10630 o.nTintShade = blob.read_shift(2);
10631 switch(o.xclrType) {
10632 case 0: blob.l += 4; break;
10633 case 1: o.xclrValue = parse_IcvXF(blob, 4); break;
10634 case 2: o.xclrValue = parse_LongRGBA(blob, 4); break;
10635 case 3: o.xclrValue = parse_ColorTheme(blob, 4); break;
10636 case 4: blob.l += 4; break;
10637 }
10638 blob.l += 8;
10639 return o;
10640}
10641
10642/* 2.5.164 TODO: read 7 bits*/
10643function parse_IcvXF(blob, length) {
10644 return parsenoop(blob, length);
10645}
10646
10647/* 2.5.280 */
10648function parse_XFExtGradient(blob, length) {
10649 return parsenoop(blob, length);
10650}
10651
10652/* [MS-XLS] 2.5.108 */
10653function parse_ExtProp(blob) {
10654 var extType = blob.read_shift(2);
10655 var cb = blob.read_shift(2) - 4;
10656 var o = [extType];
10657 switch(extType) {
10658 case 0x04: case 0x05: case 0x07: case 0x08:
10659 case 0x09: case 0x0A: case 0x0B: case 0x0D:
10660 o[1] = parse_FullColorExt(blob, cb); break;
10661 case 0x06: o[1] = parse_XFExtGradient(blob, cb); break;
10662 case 0x0E: case 0x0F: o[1] = blob.read_shift(cb === 1 ? 1 : 2); break;
10663 default: throw new Error("Unrecognized ExtProp type: " + extType + " " + cb);
10664 }
10665 return o;
10666}
10667
10668/* 2.4.355 */
10669function parse_XFExt(blob, length) {
10670 var end = blob.l + length;
10671 blob.l += 2;
10672 var ixfe = blob.read_shift(2);
10673 blob.l += 2;
10674 var cexts = blob.read_shift(2);
10675 var ext = [];
10676 while(cexts-- > 0) ext.push(parse_ExtProp(blob, end-blob.l));
10677 return {ixfe:ixfe, ext:ext};
10678}
10679
10680/* xf is an XF, see parse_XFExt for xfext */
10681function update_xfext(xf, xfext) {
10682 xfext.forEach(function(xfe) {
10683 switch(xfe[0]) { /* 2.5.108 extPropData */
10684 case 0x04: break; /* foreground color */
10685 case 0x05: break; /* background color */
10686 case 0x06: break; /* gradient fill */
10687 case 0x07: break; /* top cell border color */
10688 case 0x08: break; /* bottom cell border color */
10689 case 0x09: break; /* left cell border color */
10690 case 0x0a: break; /* right cell border color */
10691 case 0x0b: break; /* diagonal cell border color */
10692 case 0x0d: /* text color */
10693 break;
10694 case 0x0e: break; /* font scheme */
10695 case 0x0f: break; /* indentation level */
10696 }
10697 });
10698}
10699
10700/* 18.6 Calculation Chain */
10701function parse_cc_xml(data) {
10702 var d = [];
10703 if(!data) return d;
10704 var i = 1;
10705 (data.match(tagregex)||[]).forEach(function(x) {
10706 var y = parsexmltag(x);
10707 switch(y[0]) {
10708 case '<?xml': break;
10709 /* 18.6.2 calcChain CT_CalcChain 1 */
10710 case '<calcChain': case '<calcChain>': case '</calcChain>': break;
10711 /* 18.6.1 c CT_CalcCell 1 */
10712 case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break;
10713 }
10714 });
10715 return d;
10716}
10717
10718//function write_cc_xml(data, opts) { }
10719
10720/* [MS-XLSB] 2.6.4.1 */
10721function parse_BrtCalcChainItem$(data) {
10722 var out = {};
10723 out.i = data.read_shift(4);
10724 var cell = {};
10725 cell.r = data.read_shift(4);
10726 cell.c = data.read_shift(4);
10727 out.r = encode_cell(cell);
10728 var flags = data.read_shift(1);
10729 if(flags & 0x2) out.l = '1';
10730 if(flags & 0x8) out.a = '1';
10731 return out;
10732}
10733
10734/* 18.6 Calculation Chain */
10735function parse_cc_bin(data, name, opts) {
10736 var out = [];
10737 var pass = false;
10738 recordhopper(data, function hopper_cc(val, R_n, RT) {
10739 switch(RT) {
10740 case 0x003F: /* 'BrtCalcChainItem$' */
10741 out.push(val); break;
10742
10743 default:
10744 if((R_n||"").indexOf("Begin") > 0){/* empty */}
10745 else if((R_n||"").indexOf("End") > 0){/* empty */}
10746 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
10747 }
10748 });
10749 return out;
10750}
10751
10752//function write_cc_bin(data, opts) { }
10753/* 18.14 Supplementary Workbook Data */
10754function parse_xlink_xml() {
10755 //var opts = _opts || {};
10756 //if(opts.WTF) throw "XLSX External Link";
10757}
10758
10759/* [MS-XLSB] 2.1.7.25 External Link */
10760function parse_xlink_bin(data, rel, name, _opts) {
10761 if(!data) return data;
10762 var opts = _opts || {};
10763
10764 var pass = false, end = false;
10765
10766 recordhopper(data, function xlink_parse(val, R_n, RT) {
10767 if(end) return;
10768 switch(RT) {
10769 case 0x0167: /* 'BrtSupTabs' */
10770 case 0x016B: /* 'BrtExternTableStart' */
10771 case 0x016C: /* 'BrtExternTableEnd' */
10772 case 0x016E: /* 'BrtExternRowHdr' */
10773 case 0x016F: /* 'BrtExternCellBlank' */
10774 case 0x0170: /* 'BrtExternCellReal' */
10775 case 0x0171: /* 'BrtExternCellBool' */
10776 case 0x0172: /* 'BrtExternCellError' */
10777 case 0x0173: /* 'BrtExternCellString' */
10778 case 0x01D8: /* 'BrtExternValueMeta' */
10779 case 0x0241: /* 'BrtSupNameStart' */
10780 case 0x0242: /* 'BrtSupNameValueStart' */
10781 case 0x0243: /* 'BrtSupNameValueEnd' */
10782 case 0x0244: /* 'BrtSupNameNum' */
10783 case 0x0245: /* 'BrtSupNameErr' */
10784 case 0x0246: /* 'BrtSupNameSt' */
10785 case 0x0247: /* 'BrtSupNameNil' */
10786 case 0x0248: /* 'BrtSupNameBool' */
10787 case 0x0249: /* 'BrtSupNameFmla' */
10788 case 0x024A: /* 'BrtSupNameBits' */
10789 case 0x024B: /* 'BrtSupNameEnd' */
10790 break;
10791
10792 case 0x0023: /* 'BrtFRTBegin' */
10793 pass = true; break;
10794 case 0x0024: /* 'BrtFRTEnd' */
10795 pass = false; break;
10796
10797 default:
10798 if((R_n||"").indexOf("Begin") > 0){/* empty */}
10799 else if((R_n||"").indexOf("End") > 0){/* empty */}
10800 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT.toString(16) + " " + R_n);
10801 }
10802 }, opts);
10803}
10804/* 20.5 DrawingML - SpreadsheetML Drawing */
10805RELS.IMG = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
10806RELS.DRAW = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing";
10807
10808/* 20.5.2.35 wsDr CT_Drawing */
10809function parse_drawing(data, rels) {
10810 if(!data) return "??";
10811 /*
10812 Chartsheet Drawing:
10813 - 20.5.2.35 wsDr CT_Drawing
10814 - 20.5.2.1 absoluteAnchor CT_AbsoluteAnchor
10815 - 20.5.2.16 graphicFrame CT_GraphicalObjectFrame
10816 - 20.1.2.2.16 graphic CT_GraphicalObject
10817 - 20.1.2.2.17 graphicData CT_GraphicalObjectData
10818 - chart reference
10819 the actual type is based on the URI of the graphicData
10820 TODO: handle embedded charts and other types of graphics
10821 */
10822 var id = (data.match(/<c:chart [^>]*r:id="([^"]*)"/)||["",""])[1];
10823
10824 return rels['!id'][id].Target;
10825}
10826
10827/* L.5.5.2 SpreadsheetML Comments + VML Schema */
10828var _shapeid = 1024;
10829function write_comments_vml(rId, comments) {
10830 var csize = [21600, 21600];
10831 /* L.5.2.1.2 Path Attribute */
10832 var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(",");
10833 var o = [
10834 writextag("xml", null, { 'xmlns:v': XLMLNS.v, 'xmlns:o': XLMLNS.o, 'xmlns:x': XLMLNS.x, 'xmlns:mv': XLMLNS.mv }).replace(/\/>/,">"),
10835 writextag("o:shapelayout", writextag("o:idmap", null, {'v:ext':"edit", 'data':rId}), {'v:ext':"edit"}),
10836 writextag("v:shapetype", [
10837 writextag("v:stroke", null, {joinstyle:"miter"}),
10838 writextag("v:path", null, {gradientshapeok:"t", 'o:connecttype':"rect"})
10839 ].join(""), {id:"_x0000_t202", 'o:spt':202, coordsize:csize.join(","),path:bbox})
10840 ];
10841 while(_shapeid < rId * 1000) _shapeid += 1000;
10842
10843 comments.forEach(function(x) {
10844 var c = decode_cell(x[0]);
10845 var fillopts = {'color2':"#BEFF82", 'type':"gradient"};
10846 if(fillopts.type == "gradient") fillopts.angle = "-180";
10847 var fillparm = fillopts.type == "gradient" ? writextag("o:fill", null, {type:"gradientUnscaled", 'v:ext':"view"}) : null;
10848 var fillxml = writextag('v:fill', fillparm, fillopts);
10849
10850 var shadata = ({on:"t", 'obscured':"t"});
10851 ++_shapeid;
10852
10853 o = o.concat([
10854 '<v:shape' + wxt_helper({
10855 id:'_x0000_s' + _shapeid,
10856 type:"#_x0000_t202",
10857 style:"position:absolute; margin-left:80pt;margin-top:5pt;width:104pt;height:64pt;z-index:10" + (x[1].hidden ? ";visibility:hidden" : "") ,
10858 fillcolor:"#ECFAD4",
10859 strokecolor:"#edeaa1"
10860 }) + '>',
10861 fillxml,
10862 writextag("v:shadow", null, shadata),
10863 writextag("v:path", null, {'o:connecttype':"none"}),
10864 '<v:textbox><div style="text-align:left"></div></v:textbox>',
10865 '<x:ClientData ObjectType="Note">',
10866 '<x:MoveWithCells/>',
10867 '<x:SizeWithCells/>',
10868 /* Part 4 19.4.2.3 Anchor (Anchor) */
10869 writetag('x:Anchor', [c.c+1, 0, c.r+1, 0, c.c+3, 20, c.r+5, 20].join(",")),
10870 writetag('x:AutoFill', "False"),
10871 writetag('x:Row', String(c.r)),
10872 writetag('x:Column', String(c.c)),
10873 x[1].hidden ? '' : '<x:Visible/>',
10874 '</x:ClientData>',
10875 '</v:shape>'
10876 ]); });
10877 o.push('</xml>');
10878 return o.join("");
10879}
10880RELS.CMNT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
10881
10882function sheet_insert_comments(sheet, comments) {
10883 var dense = Array.isArray(sheet);
10884 var cell;
10885 comments.forEach(function(comment) {
10886 var r = decode_cell(comment.ref);
10887 if(dense) {
10888 if(!sheet[r.r]) sheet[r.r] = [];
10889 cell = sheet[r.r][r.c];
10890 } else cell = sheet[comment.ref];
10891 if (!cell) {
10892 cell = ({t:"z"});
10893 if(dense) sheet[r.r][r.c] = cell;
10894 else sheet[comment.ref] = cell;
10895 var range = safe_decode_range(sheet["!ref"]||"BDWGO1000001:A1");
10896 if(range.s.r > r.r) range.s.r = r.r;
10897 if(range.e.r < r.r) range.e.r = r.r;
10898 if(range.s.c > r.c) range.s.c = r.c;
10899 if(range.e.c < r.c) range.e.c = r.c;
10900 var encoded = encode_range(range);
10901 if (encoded !== sheet["!ref"]) sheet["!ref"] = encoded;
10902 }
10903
10904 if (!cell.c) cell.c = [];
10905 var o = ({a: comment.author, t: comment.t, r: comment.r});
10906 if(comment.h) o.h = comment.h;
10907 cell.c.push(o);
10908 });
10909}
10910
10911/* 18.7 Comments */
10912function parse_comments_xml(data, opts) {
10913 /* 18.7.6 CT_Comments */
10914 if(data.match(/<(?:\w+:)?comments *\/>/)) return [];
10915 var authors = [];
10916 var commentList = [];
10917 var authtag = data.match(/<(?:\w+:)?authors>([\s\S]*)<\/(?:\w+:)?authors>/);
10918 if(authtag && authtag[1]) authtag[1].split(/<\/\w*:?author>/).forEach(function(x) {
10919 if(x === "" || x.trim() === "") return;
10920 var a = x.match(/<(?:\w+:)?author[^>]*>(.*)/);
10921 if(a) authors.push(a[1]);
10922 });
10923 var cmnttag = data.match(/<(?:\w+:)?commentList>([\s\S]*)<\/(?:\w+:)?commentList>/);
10924 if(cmnttag && cmnttag[1]) cmnttag[1].split(/<\/\w*:?comment>/).forEach(function(x) {
10925 if(x === "" || x.trim() === "") return;
10926 var cm = x.match(/<(?:\w+:)?comment[^>]*>/);
10927 if(!cm) return;
10928 var y = parsexmltag(cm[0]);
10929 var comment = ({ author: y.authorId && authors[y.authorId] || "sheetjsghost", ref: y.ref, guid: y.guid });
10930 var cell = decode_cell(y.ref);
10931 if(opts.sheetRows && opts.sheetRows <= cell.r) return;
10932 var textMatch = x.match(/<(?:\w+:)?text>([\s\S]*)<\/(?:\w+:)?text>/);
10933 var rt = !!textMatch && !!textMatch[1] && parse_si(textMatch[1]) || {r:"",t:"",h:""};
10934 comment.r = rt.r;
10935 if(rt.r == "<t></t>") rt.t = rt.h = "";
10936 comment.t = (rt.t||"").replace(/\r\n/g,"\n").replace(/\r/g,"\n");
10937 if(opts.cellHTML) comment.h = rt.h;
10938 commentList.push(comment);
10939 });
10940 return commentList;
10941}
10942
10943var CMNT_XML_ROOT = writextag('comments', null, { 'xmlns': XMLNS.main[0] });
10944function write_comments_xml(data) {
10945 var o = [XML_HEADER, CMNT_XML_ROOT];
10946
10947 var iauthor = [];
10948 o.push("<authors>");
10949 data.forEach(function(x) { x[1].forEach(function(w) { var a = escapexml(w.a);
10950 if(iauthor.indexOf(a) > -1) return;
10951 iauthor.push(a);
10952 o.push("<author>" + a + "</author>");
10953 }); });
10954 o.push("</authors>");
10955 o.push("<commentList>");
10956 data.forEach(function(d) {
10957 d[1].forEach(function(c) {
10958 /* 18.7.3 CT_Comment */
10959 o.push('<comment ref="' + d[0] + '" authorId="' + iauthor.indexOf(escapexml(c.a)) + '"><text>');
10960 o.push(writetag("t", c.t == null ? "" : escapexml(c.t)));
10961 o.push('</text></comment>');
10962 });
10963 });
10964 o.push("</commentList>");
10965 if(o.length>2) { o[o.length] = ('</comments>'); o[1]=o[1].replace("/>",">"); }
10966 return o.join("");
10967}
10968/* [MS-XLSB] 2.4.28 BrtBeginComment */
10969function parse_BrtBeginComment(data) {
10970 var out = {};
10971 out.iauthor = data.read_shift(4);
10972 var rfx = parse_UncheckedRfX(data, 16);
10973 out.rfx = rfx.s;
10974 out.ref = encode_cell(rfx.s);
10975 data.l += 16; /*var guid = parse_GUID(data); */
10976 return out;
10977}
10978function write_BrtBeginComment(data, o) {
10979 if(o == null) o = new_buf(36);
10980 o.write_shift(4, data[1].iauthor);
10981 write_UncheckedRfX((data[0]), o);
10982 o.write_shift(4, 0);
10983 o.write_shift(4, 0);
10984 o.write_shift(4, 0);
10985 o.write_shift(4, 0);
10986 return o;
10987}
10988
10989/* [MS-XLSB] 2.4.327 BrtCommentAuthor */
10990var parse_BrtCommentAuthor = parse_XLWideString;
10991function write_BrtCommentAuthor(data) { return write_XLWideString(data.slice(0, 54)); }
10992
10993/* [MS-XLSB] 2.1.7.8 Comments */
10994function parse_comments_bin(data, opts) {
10995 var out = [];
10996 var authors = [];
10997 var c = {};
10998 var pass = false;
10999 recordhopper(data, function hopper_cmnt(val, R_n, RT) {
11000 switch(RT) {
11001 case 0x0278: /* 'BrtCommentAuthor' */
11002 authors.push(val); break;
11003 case 0x027B: /* 'BrtBeginComment' */
11004 c = val; break;
11005 case 0x027D: /* 'BrtCommentText' */
11006 c.t = val.t; c.h = val.h; c.r = val.r; break;
11007 case 0x027C: /* 'BrtEndComment' */
11008 c.author = authors[c.iauthor];
11009 delete (c).iauthor;
11010 if(opts.sheetRows && c.rfx && opts.sheetRows <= c.rfx.r) break;
11011 if(!c.t) c.t = "";
11012 delete c.rfx; out.push(c); break;
11013
11014 case 0x0C00: /* 'BrtUid' */
11015 break;
11016
11017 case 0x0023: /* 'BrtFRTBegin' */
11018 pass = true; break;
11019 case 0x0024: /* 'BrtFRTEnd' */
11020 pass = false; break;
11021 case 0x0025: /* 'BrtACBegin' */ break;
11022 case 0x0026: /* 'BrtACEnd' */ break;
11023
11024
11025 default:
11026 if((R_n||"").indexOf("Begin") > 0){/* empty */}
11027 else if((R_n||"").indexOf("End") > 0){/* empty */}
11028 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
11029 }
11030 });
11031 return out;
11032}
11033
11034function write_comments_bin(data) {
11035 var ba = buf_array();
11036 var iauthor = [];
11037 write_record(ba, "BrtBeginComments");
11038
11039 write_record(ba, "BrtBeginCommentAuthors");
11040 data.forEach(function(comment) {
11041 comment[1].forEach(function(c) {
11042 if(iauthor.indexOf(c.a) > -1) return;
11043 iauthor.push(c.a.slice(0,54));
11044 write_record(ba, "BrtCommentAuthor", write_BrtCommentAuthor(c.a));
11045 });
11046 });
11047 write_record(ba, "BrtEndCommentAuthors");
11048
11049 write_record(ba, "BrtBeginCommentList");
11050 data.forEach(function(comment) {
11051 comment[1].forEach(function(c) {
11052 c.iauthor = iauthor.indexOf(c.a);
11053 var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])};
11054 write_record(ba, "BrtBeginComment", write_BrtBeginComment([range, c]));
11055 if(c.t && c.t.length > 0) write_record(ba, "BrtCommentText", write_BrtCommentText(c));
11056 write_record(ba, "BrtEndComment");
11057 delete c.iauthor;
11058 });
11059 });
11060 write_record(ba, "BrtEndCommentList");
11061
11062 write_record(ba, "BrtEndComments");
11063 return ba.end();
11064}
11065var CT_VBA = "application/vnd.ms-office.vbaProject";
11066function make_vba_xls(cfb) {
11067 var newcfb = CFB.utils.cfb_new({root:"R"});
11068 cfb.FullPaths.forEach(function(p, i) {
11069 if(p.slice(-1) === "/" || !p.match(/_VBA_PROJECT_CUR/)) return;
11070 var newpath = p.replace(/^[^\/]*/,"R").replace(/\/_VBA_PROJECT_CUR\u0000*/, "");
11071 CFB.utils.cfb_add(newcfb, newpath, cfb.FileIndex[i].content);
11072 });
11073 return CFB.write(newcfb);
11074}
11075
11076function fill_vba_xls(cfb, vba) {
11077 vba.FullPaths.forEach(function(p, i) {
11078 if(i == 0) return;
11079 var newpath = p.replace(/[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
11080 if(newpath.slice(-1) !== "/") CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content);
11081 });
11082}
11083
11084var VBAFMTS = [ "xlsb", "xlsm", "xlam", "biff8", "xla" ];
11085
11086RELS.DS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet";
11087RELS.MS = "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet";
11088
11089/* macro and dialog sheet stubs */
11090function parse_ds_bin() { return {'!type':'dialog'}; }
11091function parse_ds_xml() { return {'!type':'dialog'}; }
11092function parse_ms_bin() { return {'!type':'macro'}; }
11093function parse_ms_xml() { return {'!type':'macro'}; }
11094/* TODO: it will be useful to parse the function str */
11095var rc_to_a1 = (function(){
11096 var rcregex = /(^|[^A-Za-z_])R(\[?-?\d+\]|[1-9]\d*|)C(\[?-?\d+\]|[1-9]\d*|)(?![A-Za-z0-9_])/g;
11097 var rcbase = ({r:0,c:0});
11098 function rcfunc($$,$1,$2,$3) {
11099 var cRel = false, rRel = false;
11100
11101 if($2.length == 0) rRel = true;
11102 else if($2.charAt(0) == "[") { rRel = true; $2 = $2.slice(1, -1); }
11103
11104 if($3.length == 0) cRel = true;
11105 else if($3.charAt(0) == "[") { cRel = true; $3 = $3.slice(1, -1); }
11106
11107 var R = $2.length>0?parseInt($2,10)|0:0, C = $3.length>0?parseInt($3,10)|0:0;
11108
11109 if(cRel) C += rcbase.c; else --C;
11110 if(rRel) R += rcbase.r; else --R;
11111 return $1 + (cRel ? "" : "$") + encode_col(C) + (rRel ? "" : "$") + encode_row(R);
11112 }
11113 return function rc_to_a1(fstr, base) {
11114 rcbase = base;
11115 return fstr.replace(rcregex, rcfunc);
11116 };
11117})();
11118
11119var 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;
11120var a1_to_rc =(function(){
11121 return function a1_to_rc(fstr, base) {
11122 return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
11123 var c = decode_col($3) - ($2 ? 0 : base.c);
11124 var r = decode_row($5) - ($4 ? 0 : base.r);
11125 var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1));
11126 var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1));
11127 return $1 + "R" + R + "C" + C;
11128 });
11129 };
11130})();
11131
11132/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
11133function shift_formula_str(f, delta) {
11134 return f.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
11135 return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
11136 });
11137}
11138
11139function shift_formula_xlsx(f, range, cell) {
11140 var r = decode_range(range), s = r.s, c = decode_cell(cell);
11141 var delta = {r:c.r - s.r, c:c.c - s.c};
11142 return shift_formula_str(f, delta);
11143}
11144
11145/* TODO: parse formula */
11146function fuzzyfmla(f) {
11147 if(f.length == 1) return false;
11148 return true;
11149}
11150
11151function _xlfn(f) {
11152 return f.replace(/_xlfn\./g,"");
11153}
11154function parseread1(blob) { blob.l+=1; return; }
11155
11156/* [MS-XLS] 2.5.51 */
11157function parse_ColRelU(blob, length) {
11158 var c = blob.read_shift(length == 1 ? 1 : 2);
11159 return [c & 0x3FFF, (c >> 14) & 1, (c >> 15) & 1];
11160}
11161
11162/* [MS-XLS] 2.5.198.105 ; [MS-XLSB] 2.5.97.89 */
11163function parse_RgceArea(blob, length, opts) {
11164 var w = 2;
11165 if(opts) {
11166 if(opts.biff >= 2 && opts.biff <= 5) return parse_RgceArea_BIFF2(blob, length, opts);
11167 else if(opts.biff == 12) w = 4;
11168 }
11169 var r=blob.read_shift(w), R=blob.read_shift(w);
11170 var c=parse_ColRelU(blob, 2);
11171 var C=parse_ColRelU(blob, 2);
11172 return { s:{r:r, c:c[0], cRel:c[1], rRel:c[2]}, e:{r:R, c:C[0], cRel:C[1], rRel:C[2]} };
11173}
11174/* BIFF 2-5 encodes flags in the row field */
11175function parse_RgceArea_BIFF2(blob) {
11176 var r=parse_ColRelU(blob, 2), R=parse_ColRelU(blob, 2);
11177 var c=blob.read_shift(1);
11178 var C=blob.read_shift(1);
11179 return { s:{r:r[0], c:c, cRel:r[1], rRel:r[2]}, e:{r:R[0], c:C, cRel:R[1], rRel:R[2]} };
11180}
11181
11182/* [MS-XLS] 2.5.198.105 ; [MS-XLSB] 2.5.97.90 */
11183function parse_RgceAreaRel(blob, length, opts) {
11184 if(opts.biff < 8) return parse_RgceArea_BIFF2(blob, length, opts);
11185 var r=blob.read_shift(opts.biff == 12 ? 4 : 2), R=blob.read_shift(opts.biff == 12 ? 4 : 2);
11186 var c=parse_ColRelU(blob, 2);
11187 var C=parse_ColRelU(blob, 2);
11188 return { s:{r:r, c:c[0], cRel:c[1], rRel:c[2]}, e:{r:R, c:C[0], cRel:C[1], rRel:C[2]} };
11189}
11190
11191/* [MS-XLS] 2.5.198.109 ; [MS-XLSB] 2.5.97.91 */
11192function parse_RgceLoc(blob, length, opts) {
11193 if(opts && opts.biff >= 2 && opts.biff <= 5) return parse_RgceLoc_BIFF2(blob, length, opts);
11194 var r = blob.read_shift(opts && opts.biff == 12 ? 4 : 2);
11195 var c = parse_ColRelU(blob, 2);
11196 return {r:r, c:c[0], cRel:c[1], rRel:c[2]};
11197}
11198function parse_RgceLoc_BIFF2(blob) {
11199 var r = parse_ColRelU(blob, 2);
11200 var c = blob.read_shift(1);
11201 return {r:r[0], c:c, cRel:r[1], rRel:r[2]};
11202}
11203
11204/* [MS-XLS] 2.5.198.107, 2.5.47 */
11205function parse_RgceElfLoc(blob) {
11206 var r = blob.read_shift(2);
11207 var c = blob.read_shift(2);
11208 return {r:r, c:c & 0xFF, fQuoted:!!(c & 0x4000), cRel:c>>15, rRel:c>>15 };
11209}
11210
11211/* [MS-XLS] 2.5.198.111 ; [MS-XLSB] 2.5.97.92 TODO */
11212function parse_RgceLocRel(blob, length, opts) {
11213 var biff = opts && opts.biff ? opts.biff : 8;
11214 if(biff >= 2 && biff <= 5) return parse_RgceLocRel_BIFF2(blob, length, opts);
11215 var r = blob.read_shift(biff >= 12 ? 4 : 2);
11216 var cl = blob.read_shift(2);
11217 var cRel = (cl & 0x4000) >> 14, rRel = (cl & 0x8000) >> 15;
11218 cl &= 0x3FFF;
11219 if(rRel == 1) while(r > 0x7FFFF) r -= 0x100000;
11220 if(cRel == 1) while(cl > 0x1FFF) cl = cl - 0x4000;
11221 return {r:r,c:cl,cRel:cRel,rRel:rRel};
11222}
11223function parse_RgceLocRel_BIFF2(blob) {
11224 var rl = blob.read_shift(2);
11225 var c = blob.read_shift(1);
11226 var rRel = (rl & 0x8000) >> 15, cRel = (rl & 0x4000) >> 14;
11227 rl &= 0x3FFF;
11228 if(rRel == 1 && rl >= 0x2000) rl = rl - 0x4000;
11229 if(cRel == 1 && c >= 0x80) c = c - 0x100;
11230 return {r:rl,c:c,cRel:cRel,rRel:rRel};
11231}
11232
11233/* [MS-XLS] 2.5.198.27 ; [MS-XLSB] 2.5.97.18 */
11234function parse_PtgArea(blob, length, opts) {
11235 var type = (blob[blob.l++] & 0x60) >> 5;
11236 var area = parse_RgceArea(blob, opts.biff >= 2 && opts.biff <= 5 ? 6 : 8, opts);
11237 return [type, area];
11238}
11239
11240/* [MS-XLS] 2.5.198.28 ; [MS-XLSB] 2.5.97.19 */
11241function parse_PtgArea3d(blob, length, opts) {
11242 var type = (blob[blob.l++] & 0x60) >> 5;
11243 var ixti = blob.read_shift(2, 'i');
11244 var w = 8;
11245 if(opts) switch(opts.biff) {
11246 case 5: blob.l += 12; w = 6; break;
11247 case 12: w = 12; break;
11248 }
11249 var area = parse_RgceArea(blob, w, opts);
11250 return [type, ixti, area];
11251}
11252
11253/* [MS-XLS] 2.5.198.29 ; [MS-XLSB] 2.5.97.20 */
11254function parse_PtgAreaErr(blob, length, opts) {
11255 var type = (blob[blob.l++] & 0x60) >> 5;
11256 blob.l += opts && (opts.biff > 8) ? 12 : (opts.biff < 8 ? 6 : 8);
11257 return [type];
11258}
11259/* [MS-XLS] 2.5.198.30 ; [MS-XLSB] 2.5.97.21 */
11260function parse_PtgAreaErr3d(blob, length, opts) {
11261 var type = (blob[blob.l++] & 0x60) >> 5;
11262 var ixti = blob.read_shift(2);
11263 var w = 8;
11264 if(opts) switch(opts.biff) {
11265 case 5: blob.l += 12; w = 6; break;
11266 case 12: w = 12; break;
11267 }
11268 blob.l += w;
11269 return [type, ixti];
11270}
11271
11272/* [MS-XLS] 2.5.198.31 ; [MS-XLSB] 2.5.97.22 */
11273function parse_PtgAreaN(blob, length, opts) {
11274 var type = (blob[blob.l++] & 0x60) >> 5;
11275 var area = parse_RgceAreaRel(blob, length - 1, opts);
11276 return [type, area];
11277}
11278
11279/* [MS-XLS] 2.5.198.32 ; [MS-XLSB] 2.5.97.23 */
11280function parse_PtgArray(blob, length, opts) {
11281 var type = (blob[blob.l++] & 0x60) >> 5;
11282 blob.l += opts.biff == 2 ? 6 : opts.biff == 12 ? 14 : 7;
11283 return [type];
11284}
11285
11286/* [MS-XLS] 2.5.198.33 ; [MS-XLSB] 2.5.97.24 */
11287function parse_PtgAttrBaxcel(blob) {
11288 var bitSemi = blob[blob.l+1] & 0x01; /* 1 = volatile */
11289 var bitBaxcel = 1;
11290 blob.l += 4;
11291 return [bitSemi, bitBaxcel];
11292}
11293
11294/* [MS-XLS] 2.5.198.34 ; [MS-XLSB] 2.5.97.25 */
11295function parse_PtgAttrChoose(blob, length, opts) {
11296 blob.l +=2;
11297 var offset = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
11298 var o = [];
11299 /* offset is 1 less than the number of elements */
11300 for(var i = 0; i <= offset; ++i) o.push(blob.read_shift(opts && opts.biff == 2 ? 1 : 2));
11301 return o;
11302}
11303
11304/* [MS-XLS] 2.5.198.35 ; [MS-XLSB] 2.5.97.26 */
11305function parse_PtgAttrGoto(blob, length, opts) {
11306 var bitGoto = (blob[blob.l+1] & 0xFF) ? 1 : 0;
11307 blob.l += 2;
11308 return [bitGoto, blob.read_shift(opts && opts.biff == 2 ? 1 : 2)];
11309}
11310
11311/* [MS-XLS] 2.5.198.36 ; [MS-XLSB] 2.5.97.27 */
11312function parse_PtgAttrIf(blob, length, opts) {
11313 var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0;
11314 blob.l += 2;
11315 return [bitIf, blob.read_shift(opts && opts.biff == 2 ? 1 : 2)];
11316}
11317
11318/* [MS-XLSB] 2.5.97.28 */
11319function parse_PtgAttrIfError(blob) {
11320 var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0;
11321 blob.l += 2;
11322 return [bitIf, blob.read_shift(2)];
11323}
11324
11325/* [MS-XLS] 2.5.198.37 ; [MS-XLSB] 2.5.97.29 */
11326function parse_PtgAttrSemi(blob, length, opts) {
11327 var bitSemi = (blob[blob.l+1] & 0xFF) ? 1 : 0;
11328 blob.l += opts && opts.biff == 2 ? 3 : 4;
11329 return [bitSemi];
11330}
11331
11332/* [MS-XLS] 2.5.198.40 ; [MS-XLSB] 2.5.97.32 */
11333function parse_PtgAttrSpaceType(blob) {
11334 var type = blob.read_shift(1), cch = blob.read_shift(1);
11335 return [type, cch];
11336}
11337
11338/* [MS-XLS] 2.5.198.38 ; [MS-XLSB] 2.5.97.30 */
11339function parse_PtgAttrSpace(blob) {
11340 blob.read_shift(2);
11341 return parse_PtgAttrSpaceType(blob, 2);
11342}
11343
11344/* [MS-XLS] 2.5.198.39 ; [MS-XLSB] 2.5.97.31 */
11345function parse_PtgAttrSpaceSemi(blob) {
11346 blob.read_shift(2);
11347 return parse_PtgAttrSpaceType(blob, 2);
11348}
11349
11350/* [MS-XLS] 2.5.198.84 ; [MS-XLSB] 2.5.97.68 TODO */
11351function parse_PtgRef(blob, length, opts) {
11352 //var ptg = blob[blob.l] & 0x1F;
11353 var type = (blob[blob.l] & 0x60)>>5;
11354 blob.l += 1;
11355 var loc = parse_RgceLoc(blob, 0, opts);
11356 return [type, loc];
11357}
11358
11359/* [MS-XLS] 2.5.198.88 ; [MS-XLSB] 2.5.97.72 TODO */
11360function parse_PtgRefN(blob, length, opts) {
11361 var type = (blob[blob.l] & 0x60)>>5;
11362 blob.l += 1;
11363 var loc = parse_RgceLocRel(blob, 0, opts);
11364 return [type, loc];
11365}
11366
11367/* [MS-XLS] 2.5.198.85 ; [MS-XLSB] 2.5.97.69 TODO */
11368function parse_PtgRef3d(blob, length, opts) {
11369 var type = (blob[blob.l] & 0x60)>>5;
11370 blob.l += 1;
11371 var ixti = blob.read_shift(2); // XtiIndex
11372 if(opts && opts.biff == 5) blob.l += 12;
11373 var loc = parse_RgceLoc(blob, 0, opts); // TODO: or RgceLocRel
11374 return [type, ixti, loc];
11375}
11376
11377
11378/* [MS-XLS] 2.5.198.62 ; [MS-XLSB] 2.5.97.45 TODO */
11379function parse_PtgFunc(blob, length, opts) {
11380 //var ptg = blob[blob.l] & 0x1F;
11381 var type = (blob[blob.l] & 0x60)>>5;
11382 blob.l += 1;
11383 var iftab = blob.read_shift(opts && opts.biff <= 3 ? 1 : 2);
11384 return [FtabArgc[iftab], Ftab[iftab], type];
11385}
11386/* [MS-XLS] 2.5.198.63 ; [MS-XLSB] 2.5.97.46 TODO */
11387function parse_PtgFuncVar(blob, length, opts) {
11388 var type = blob[blob.l++];
11389 var cparams = blob.read_shift(1), tab = opts && opts.biff <= 3 ? [(type == 0x58 ? -1 : 0), blob.read_shift(1)]: parsetab(blob);
11390 return [cparams, (tab[0] === 0 ? Ftab : Cetab)[tab[1]]];
11391}
11392
11393function parsetab(blob) {
11394 return [blob[blob.l+1]>>7, blob.read_shift(2) & 0x7FFF];
11395}
11396
11397/* [MS-XLS] 2.5.198.41 ; [MS-XLSB] 2.5.97.33 */
11398function parse_PtgAttrSum(blob, length, opts) {
11399 blob.l += opts && opts.biff == 2 ? 3 : 4; return;
11400}
11401
11402/* [MS-XLS] 2.5.198.58 ; [MS-XLSB] 2.5.97.40 */
11403function parse_PtgExp(blob, length, opts) {
11404 blob.l++;
11405 if(opts && opts.biff == 12) return [blob.read_shift(4, 'i'), 0];
11406 var row = blob.read_shift(2);
11407 var col = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
11408 return [row, col];
11409}
11410
11411/* [MS-XLS] 2.5.198.57 ; [MS-XLSB] 2.5.97.39 */
11412function parse_PtgErr(blob) { blob.l++; return BErr[blob.read_shift(1)]; }
11413
11414/* [MS-XLS] 2.5.198.66 ; [MS-XLSB] 2.5.97.49 */
11415function parse_PtgInt(blob) { blob.l++; return blob.read_shift(2); }
11416
11417/* [MS-XLS] 2.5.198.42 ; [MS-XLSB] 2.5.97.34 */
11418function parse_PtgBool(blob) { blob.l++; return blob.read_shift(1)!==0;}
11419
11420/* [MS-XLS] 2.5.198.79 ; [MS-XLSB] 2.5.97.63 */
11421function parse_PtgNum(blob) { blob.l++; return parse_Xnum(blob, 8); }
11422
11423/* [MS-XLS] 2.5.198.89 ; [MS-XLSB] 2.5.97.74 */
11424function parse_PtgStr(blob, length, opts) { blob.l++; return parse_ShortXLUnicodeString(blob, length-1, opts); }
11425
11426/* [MS-XLS] 2.5.192.112 + 2.5.192.11{3,4,5,6,7} */
11427/* [MS-XLSB] 2.5.97.93 + 2.5.97.9{4,5,6,7} */
11428function parse_SerAr(blob, biff) {
11429 var val = [blob.read_shift(1)];
11430 if(biff == 12) switch(val[0]) {
11431 case 0x02: val[0] = 0x04; break; /* SerBool */
11432 case 0x04: val[0] = 0x10; break; /* SerErr */
11433 case 0x00: val[0] = 0x01; break; /* SerNum */
11434 case 0x01: val[0] = 0x02; break; /* SerStr */
11435 }
11436 switch(val[0]) {
11437 case 0x04: /* SerBool -- boolean */
11438 val[1] = parsebool(blob, 1) ? 'TRUE' : 'FALSE';
11439 if(biff != 12) blob.l += 7; break;
11440 case 0x25: /* appears to be an alias */
11441 case 0x10: /* SerErr -- error */
11442 val[1] = BErr[blob[blob.l]];
11443 blob.l += ((biff == 12) ? 4 : 8); break;
11444 case 0x00: /* SerNil -- honestly, I'm not sure how to reproduce this */
11445 blob.l += 8; break;
11446 case 0x01: /* SerNum -- Xnum */
11447 val[1] = parse_Xnum(blob, 8); break;
11448 case 0x02: /* SerStr -- XLUnicodeString (<256 chars) */
11449 val[1] = parse_XLUnicodeString2(blob, 0, {biff:biff > 0 && biff < 8 ? 2 : biff}); break;
11450 default: throw new Error("Bad SerAr: " + val[0]); /* Unreachable */
11451 }
11452 return val;
11453}
11454
11455/* [MS-XLS] 2.5.198.61 ; [MS-XLSB] 2.5.97.44 */
11456function parse_PtgExtraMem(blob, cce, opts) {
11457 var count = blob.read_shift((opts.biff == 12) ? 4 : 2);
11458 var out = [];
11459 for(var i = 0; i != count; ++i) out.push(((opts.biff == 12) ? parse_UncheckedRfX : parse_Ref8U)(blob, 8));
11460 return out;
11461}
11462
11463/* [MS-XLS] 2.5.198.59 ; [MS-XLSB] 2.5.97.41 */
11464function parse_PtgExtraArray(blob, length, opts) {
11465 var rows = 0, cols = 0;
11466 if(opts.biff == 12) {
11467 rows = blob.read_shift(4); // DRw
11468 cols = blob.read_shift(4); // DCol
11469 } else {
11470 cols = 1 + blob.read_shift(1); //DColByteU
11471 rows = 1 + blob.read_shift(2); //DRw
11472 }
11473 if(opts.biff >= 2 && opts.biff < 8) { --rows; if(--cols == 0) cols = 0x100; }
11474 // $FlowIgnore
11475 for(var i = 0, o = []; i != rows && (o[i] = []); ++i)
11476 for(var j = 0; j != cols; ++j) o[i][j] = parse_SerAr(blob, opts.biff);
11477 return o;
11478}
11479
11480/* [MS-XLS] 2.5.198.76 ; [MS-XLSB] 2.5.97.60 */
11481function parse_PtgName(blob, length, opts) {
11482 var type = (blob.read_shift(1) >>> 5) & 0x03;
11483 var w = (!opts || (opts.biff >= 8)) ? 4 : 2;
11484 var nameindex = blob.read_shift(w);
11485 switch(opts.biff) {
11486 case 2: blob.l += 5; break;
11487 case 3: case 4: blob.l += 8; break;
11488 case 5: blob.l += 12; break;
11489 }
11490 return [type, 0, nameindex];
11491}
11492
11493/* [MS-XLS] 2.5.198.77 ; [MS-XLSB] 2.5.97.61 */
11494function parse_PtgNameX(blob, length, opts) {
11495 if(opts.biff == 5) return parse_PtgNameX_BIFF5(blob, length, opts);
11496 var type = (blob.read_shift(1) >>> 5) & 0x03;
11497 var ixti = blob.read_shift(2); // XtiIndex
11498 var nameindex = blob.read_shift(4);
11499 return [type, ixti, nameindex];
11500}
11501function parse_PtgNameX_BIFF5(blob) {
11502 var type = (blob.read_shift(1) >>> 5) & 0x03;
11503 var ixti = blob.read_shift(2, 'i'); // XtiIndex
11504 blob.l += 8;
11505 var nameindex = blob.read_shift(2);
11506 blob.l += 12;
11507 return [type, ixti, nameindex];
11508}
11509
11510/* [MS-XLS] 2.5.198.70 ; [MS-XLSB] 2.5.97.54 */
11511function parse_PtgMemArea(blob, length, opts) {
11512 var type = (blob.read_shift(1) >>> 5) & 0x03;
11513 blob.l += (opts && opts.biff == 2 ? 3 : 4);
11514 var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
11515 return [type, cce];
11516}
11517
11518/* [MS-XLS] 2.5.198.72 ; [MS-XLSB] 2.5.97.56 */
11519function parse_PtgMemFunc(blob, length, opts) {
11520 var type = (blob.read_shift(1) >>> 5) & 0x03;
11521 var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
11522 return [type, cce];
11523}
11524
11525
11526/* [MS-XLS] 2.5.198.86 ; [MS-XLSB] 2.5.97.69 */
11527function parse_PtgRefErr(blob, length, opts) {
11528 var type = (blob.read_shift(1) >>> 5) & 0x03;
11529 blob.l += 4;
11530 if(opts.biff < 8) blob.l--;
11531 if(opts.biff == 12) blob.l += 2;
11532 return [type];
11533}
11534
11535/* [MS-XLS] 2.5.198.87 ; [MS-XLSB] 2.5.97.71 */
11536function parse_PtgRefErr3d(blob, length, opts) {
11537 var type = (blob[blob.l++] & 0x60) >> 5;
11538 var ixti = blob.read_shift(2);
11539 var w = 4;
11540 if(opts) switch(opts.biff) {
11541 case 5: w = 15; break;
11542 case 12: w = 6; break;
11543 }
11544 blob.l += w;
11545 return [type, ixti];
11546}
11547
11548/* [MS-XLS] 2.5.198.71 ; [MS-XLSB] 2.5.97.55 */
11549var parse_PtgMemErr = parsenoop;
11550/* [MS-XLS] 2.5.198.73 ; [MS-XLSB] 2.5.97.57 */
11551var parse_PtgMemNoMem = parsenoop;
11552/* [MS-XLS] 2.5.198.92 */
11553var parse_PtgTbl = parsenoop;
11554
11555function parse_PtgElfLoc(blob, length, opts) {
11556 blob.l += 2;
11557 return [parse_RgceElfLoc(blob, 4, opts)];
11558}
11559function parse_PtgElfNoop(blob) {
11560 blob.l += 6;
11561 return [];
11562}
11563/* [MS-XLS] 2.5.198.46 */
11564var parse_PtgElfCol = parse_PtgElfLoc;
11565/* [MS-XLS] 2.5.198.47 */
11566var parse_PtgElfColS = parse_PtgElfNoop;
11567/* [MS-XLS] 2.5.198.48 */
11568var parse_PtgElfColSV = parse_PtgElfNoop;
11569/* [MS-XLS] 2.5.198.49 */
11570var parse_PtgElfColV = parse_PtgElfLoc;
11571/* [MS-XLS] 2.5.198.50 */
11572function parse_PtgElfLel(blob) {
11573 blob.l += 2;
11574 return [parseuint16(blob), blob.read_shift(2) & 0x01];
11575}
11576/* [MS-XLS] 2.5.198.51 */
11577var parse_PtgElfRadical = parse_PtgElfLoc;
11578/* [MS-XLS] 2.5.198.52 */
11579var parse_PtgElfRadicalLel = parse_PtgElfLel;
11580/* [MS-XLS] 2.5.198.53 */
11581var parse_PtgElfRadicalS = parse_PtgElfNoop;
11582/* [MS-XLS] 2.5.198.54 */
11583var parse_PtgElfRw = parse_PtgElfLoc;
11584/* [MS-XLS] 2.5.198.55 */
11585var parse_PtgElfRwV = parse_PtgElfLoc;
11586
11587/* [MS-XLSB] 2.5.97.52 TODO */
11588var PtgListRT = [
11589 "Data",
11590 "All",
11591 "Headers",
11592 "??",
11593 "?Data2",
11594 "??",
11595 "?DataHeaders",
11596 "??",
11597 "Totals",
11598 "??",
11599 "??",
11600 "??",
11601 "?DataTotals",
11602 "??",
11603 "??",
11604 "??",
11605 "?Current"
11606];
11607function parse_PtgList(blob) {
11608 blob.l += 2;
11609 var ixti = blob.read_shift(2);
11610 var flags = blob.read_shift(2);
11611 var idx = blob.read_shift(4);
11612 var c = blob.read_shift(2);
11613 var C = blob.read_shift(2);
11614 var rt = PtgListRT[(flags >> 2) & 0x1F];
11615 return {ixti: ixti, coltype:(flags&0x3), rt:rt, idx:idx, c:c, C:C};
11616}
11617/* [MS-XLS] 2.5.198.91 ; [MS-XLSB] 2.5.97.76 */
11618function parse_PtgSxName(blob) {
11619 blob.l += 2;
11620 return [blob.read_shift(4)];
11621}
11622
11623/* [XLS] old spec */
11624function parse_PtgSheet(blob, length, opts) {
11625 blob.l += 5;
11626 blob.l += 2;
11627 blob.l += (opts.biff == 2 ? 1 : 4);
11628 return ["PTGSHEET"];
11629}
11630function parse_PtgEndSheet(blob, length, opts) {
11631 blob.l += (opts.biff == 2 ? 4 : 5);
11632 return ["PTGENDSHEET"];
11633}
11634function parse_PtgMemAreaN(blob) {
11635 var type = (blob.read_shift(1) >>> 5) & 0x03;
11636 var cce = blob.read_shift(2);
11637 return [type, cce];
11638}
11639function parse_PtgMemNoMemN(blob) {
11640 var type = (blob.read_shift(1) >>> 5) & 0x03;
11641 var cce = blob.read_shift(2);
11642 return [type, cce];
11643}
11644function parse_PtgAttrNoop(blob) {
11645 blob.l += 4;
11646 return [0, 0];
11647}
11648
11649/* [MS-XLS] 2.5.198.25 ; [MS-XLSB] 2.5.97.16 */
11650var PtgTypes = {
116510x01: { n:'PtgExp', f:parse_PtgExp },
116520x02: { n:'PtgTbl', f:parse_PtgTbl },
116530x03: { n:'PtgAdd', f:parseread1 },
116540x04: { n:'PtgSub', f:parseread1 },
116550x05: { n:'PtgMul', f:parseread1 },
116560x06: { n:'PtgDiv', f:parseread1 },
116570x07: { n:'PtgPower', f:parseread1 },
116580x08: { n:'PtgConcat', f:parseread1 },
116590x09: { n:'PtgLt', f:parseread1 },
116600x0A: { n:'PtgLe', f:parseread1 },
116610x0B: { n:'PtgEq', f:parseread1 },
116620x0C: { n:'PtgGe', f:parseread1 },
116630x0D: { n:'PtgGt', f:parseread1 },
116640x0E: { n:'PtgNe', f:parseread1 },
116650x0F: { n:'PtgIsect', f:parseread1 },
116660x10: { n:'PtgUnion', f:parseread1 },
116670x11: { n:'PtgRange', f:parseread1 },
116680x12: { n:'PtgUplus', f:parseread1 },
116690x13: { n:'PtgUminus', f:parseread1 },
116700x14: { n:'PtgPercent', f:parseread1 },
116710x15: { n:'PtgParen', f:parseread1 },
116720x16: { n:'PtgMissArg', f:parseread1 },
116730x17: { n:'PtgStr', f:parse_PtgStr },
116740x1A: { n:'PtgSheet', f:parse_PtgSheet },
116750x1B: { n:'PtgEndSheet', f:parse_PtgEndSheet },
116760x1C: { n:'PtgErr', f:parse_PtgErr },
116770x1D: { n:'PtgBool', f:parse_PtgBool },
116780x1E: { n:'PtgInt', f:parse_PtgInt },
116790x1F: { n:'PtgNum', f:parse_PtgNum },
116800x20: { n:'PtgArray', f:parse_PtgArray },
116810x21: { n:'PtgFunc', f:parse_PtgFunc },
116820x22: { n:'PtgFuncVar', f:parse_PtgFuncVar },
116830x23: { n:'PtgName', f:parse_PtgName },
116840x24: { n:'PtgRef', f:parse_PtgRef },
116850x25: { n:'PtgArea', f:parse_PtgArea },
116860x26: { n:'PtgMemArea', f:parse_PtgMemArea },
116870x27: { n:'PtgMemErr', f:parse_PtgMemErr },
116880x28: { n:'PtgMemNoMem', f:parse_PtgMemNoMem },
116890x29: { n:'PtgMemFunc', f:parse_PtgMemFunc },
116900x2A: { n:'PtgRefErr', f:parse_PtgRefErr },
116910x2B: { n:'PtgAreaErr', f:parse_PtgAreaErr },
116920x2C: { n:'PtgRefN', f:parse_PtgRefN },
116930x2D: { n:'PtgAreaN', f:parse_PtgAreaN },
116940x2E: { n:'PtgMemAreaN', f:parse_PtgMemAreaN },
116950x2F: { n:'PtgMemNoMemN', f:parse_PtgMemNoMemN },
116960x39: { n:'PtgNameX', f:parse_PtgNameX },
116970x3A: { n:'PtgRef3d', f:parse_PtgRef3d },
116980x3B: { n:'PtgArea3d', f:parse_PtgArea3d },
116990x3C: { n:'PtgRefErr3d', f:parse_PtgRefErr3d },
117000x3D: { n:'PtgAreaErr3d', f:parse_PtgAreaErr3d },
117010xFF: {}
11702};
11703/* These are duplicated in the PtgTypes table */
11704var PtgDupes = {
117050x40: 0x20, 0x60: 0x20,
117060x41: 0x21, 0x61: 0x21,
117070x42: 0x22, 0x62: 0x22,
117080x43: 0x23, 0x63: 0x23,
117090x44: 0x24, 0x64: 0x24,
117100x45: 0x25, 0x65: 0x25,
117110x46: 0x26, 0x66: 0x26,
117120x47: 0x27, 0x67: 0x27,
117130x48: 0x28, 0x68: 0x28,
117140x49: 0x29, 0x69: 0x29,
117150x4A: 0x2A, 0x6A: 0x2A,
117160x4B: 0x2B, 0x6B: 0x2B,
117170x4C: 0x2C, 0x6C: 0x2C,
117180x4D: 0x2D, 0x6D: 0x2D,
117190x4E: 0x2E, 0x6E: 0x2E,
117200x4F: 0x2F, 0x6F: 0x2F,
117210x58: 0x22, 0x78: 0x22,
117220x59: 0x39, 0x79: 0x39,
117230x5A: 0x3A, 0x7A: 0x3A,
117240x5B: 0x3B, 0x7B: 0x3B,
117250x5C: 0x3C, 0x7C: 0x3C,
117260x5D: 0x3D, 0x7D: 0x3D
11727};
11728(function(){for(var y in PtgDupes) PtgTypes[y] = PtgTypes[PtgDupes[y]];})();
11729
11730var Ptg18 = {
117310x01: { n:'PtgElfLel', f:parse_PtgElfLel },
117320x02: { n:'PtgElfRw', f:parse_PtgElfRw },
117330x03: { n:'PtgElfCol', f:parse_PtgElfCol },
117340x06: { n:'PtgElfRwV', f:parse_PtgElfRwV },
117350x07: { n:'PtgElfColV', f:parse_PtgElfColV },
117360x0A: { n:'PtgElfRadical', f:parse_PtgElfRadical },
117370x0B: { n:'PtgElfRadicalS', f:parse_PtgElfRadicalS },
117380x0D: { n:'PtgElfColS', f:parse_PtgElfColS },
117390x0F: { n:'PtgElfColSV', f:parse_PtgElfColSV },
117400x10: { n:'PtgElfRadicalLel', f:parse_PtgElfRadicalLel },
117410x19: { n:'PtgList', f:parse_PtgList },
117420x1D: { n:'PtgSxName', f:parse_PtgSxName },
117430xFF: {}
11744};
11745var Ptg19 = {
117460x00: { n:'PtgAttrNoop', f:parse_PtgAttrNoop },
117470x01: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
117480x02: { n:'PtgAttrIf', f:parse_PtgAttrIf },
117490x04: { n:'PtgAttrChoose', f:parse_PtgAttrChoose },
117500x08: { n:'PtgAttrGoto', f:parse_PtgAttrGoto },
117510x10: { n:'PtgAttrSum', f:parse_PtgAttrSum },
117520x20: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
117530x40: { n:'PtgAttrSpace', f:parse_PtgAttrSpace },
117540x41: { n:'PtgAttrSpaceSemi', f:parse_PtgAttrSpaceSemi },
117550x80: { n:'PtgAttrIfError', f:parse_PtgAttrIfError },
117560xFF: {}
11757};
11758Ptg19[0x21] = Ptg19[0x20];
11759
11760/* [MS-XLS] 2.5.198.103 ; [MS-XLSB] 2.5.97.87 */
11761function parse_RgbExtra(blob, length, rgce, opts) {
11762 if(opts.biff < 8) return parsenoop(blob, length);
11763 var target = blob.l + length;
11764 var o = [];
11765 for(var i = 0; i !== rgce.length; ++i) {
11766 switch(rgce[i][0]) {
11767 case 'PtgArray': /* PtgArray -> PtgExtraArray */
11768 rgce[i][1] = parse_PtgExtraArray(blob, 0, opts);
11769 o.push(rgce[i][1]);
11770 break;
11771 case 'PtgMemArea': /* PtgMemArea -> PtgExtraMem */
11772 rgce[i][2] = parse_PtgExtraMem(blob, rgce[i][1], opts);
11773 o.push(rgce[i][2]);
11774 break;
11775 case 'PtgExp': /* PtgExp -> PtgExtraCol */
11776 if(opts && opts.biff == 12) {
11777 rgce[i][1][1] = blob.read_shift(4);
11778 o.push(rgce[i][1]);
11779 } break;
11780 case 'PtgList': /* TODO: PtgList -> PtgExtraList */
11781 case 'PtgElfRadicalS': /* TODO: PtgElfRadicalS -> PtgExtraElf */
11782 case 'PtgElfColS': /* TODO: PtgElfColS -> PtgExtraElf */
11783 case 'PtgElfColSV': /* TODO: PtgElfColSV -> PtgExtraElf */
11784 throw "Unsupported " + rgce[i][0];
11785 default: break;
11786 }
11787 }
11788 length = target - blob.l;
11789 /* note: this is technically an error but Excel disregards */
11790 //if(target !== blob.l && blob.l !== target - length) throw new Error(target + " != " + blob.l);
11791 if(length !== 0) o.push(parsenoop(blob, length));
11792 return o;
11793}
11794
11795/* [MS-XLS] 2.5.198.104 ; [MS-XLSB] 2.5.97.88 */
11796function parse_Rgce(blob, length, opts) {
11797 var target = blob.l + length;
11798 var R, id, ptgs = [];
11799 while(target != blob.l) {
11800 length = target - blob.l;
11801 id = blob[blob.l];
11802 R = PtgTypes[id];
11803 if(id === 0x18 || id === 0x19) R = (id === 0x18 ? Ptg18 : Ptg19)[blob[blob.l + 1]];
11804 if(!R || !R.f) { /*ptgs.push*/(parsenoop(blob, length)); }
11805 else { ptgs.push([R.n, R.f(blob, length, opts)]); }
11806 }
11807 return ptgs;
11808}
11809
11810function stringify_array(f) {
11811 var o = [];
11812 for(var i = 0; i < f.length; ++i) {
11813 var x = f[i], r = [];
11814 for(var j = 0; j < x.length; ++j) {
11815 var y = x[j];
11816 if(y) switch(y[0]) {
11817 // TODO: handle embedded quotes
11818 case 0x02:
11819r.push('"' + y[1].replace(/"/g,'""') + '"'); break;
11820 default: r.push(y[1]);
11821 } else r.push("");
11822 }
11823 o.push(r.join(","));
11824 }
11825 return o.join(";");
11826}
11827
11828/* [MS-XLS] 2.2.2 ; [MS-XLSB] 2.2.2 TODO */
11829var PtgBinOp = {
11830 PtgAdd: "+",
11831 PtgConcat: "&",
11832 PtgDiv: "/",
11833 PtgEq: "=",
11834 PtgGe: ">=",
11835 PtgGt: ">",
11836 PtgLe: "<=",
11837 PtgLt: "<",
11838 PtgMul: "*",
11839 PtgNe: "<>",
11840 PtgPower: "^",
11841 PtgSub: "-"
11842};
11843
11844// List of invalid characters needs to be tested further
11845var quoteCharacters = new RegExp(/[^\w\u4E00-\u9FFF\u3040-\u30FF]/);
11846function formula_quote_sheet_name(sname, opts) {
11847 if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name");
11848 if (quoteCharacters.test(sname)) return "'" + sname + "'";
11849 return sname;
11850}
11851function get_ixti_raw(supbooks, ixti, opts) {
11852 if(!supbooks) return "SH33TJSERR0";
11853 if(opts.biff > 8 && (!supbooks.XTI || !supbooks.XTI[ixti])) return supbooks.SheetNames[ixti];
11854 if(!supbooks.XTI) return "SH33TJSERR6";
11855 var XTI = supbooks.XTI[ixti];
11856 if(opts.biff < 8) {
11857 if(ixti > 10000) ixti-= 65536;
11858 if(ixti < 0) ixti = -ixti;
11859 return ixti == 0 ? "" : supbooks.XTI[ixti - 1];
11860 }
11861 if(!XTI) return "SH33TJSERR1";
11862 var o = "";
11863 if(opts.biff > 8) switch(supbooks[XTI[0]][0]) {
11864 case 0x0165: /* 'BrtSupSelf' */
11865 o = XTI[1] == -1 ? "#REF" : supbooks.SheetNames[XTI[1]];
11866 return XTI[1] == XTI[2] ? o : o + ":" + supbooks.SheetNames[XTI[2]];
11867 case 0x0166: /* 'BrtSupSame' */
11868 if(opts.SID != null) return supbooks.SheetNames[opts.SID];
11869 return "SH33TJSSAME" + supbooks[XTI[0]][0];
11870 case 0x0163: /* 'BrtSupBookSrc' */
11871 /* falls through */
11872 default: return "SH33TJSSRC" + supbooks[XTI[0]][0];
11873 }
11874 switch(supbooks[XTI[0]][0][0]) {
11875 case 0x0401:
11876 o = XTI[1] == -1 ? "#REF" : (supbooks.SheetNames[XTI[1]] || "SH33TJSERR3");
11877 return XTI[1] == XTI[2] ? o : o + ":" + supbooks.SheetNames[XTI[2]];
11878 case 0x3A01: return supbooks[XTI[0]].slice(1).map(function(name) { return name.Name; }).join(";;"); //return "SH33TJSERR8";
11879 default:
11880 if(!supbooks[XTI[0]][0][3]) return "SH33TJSERR2";
11881 o = XTI[1] == -1 ? "#REF" : (supbooks[XTI[0]][0][3][XTI[1]] || "SH33TJSERR4");
11882 return XTI[1] == XTI[2] ? o : o + ":" + supbooks[XTI[0]][0][3][XTI[2]];
11883 }
11884}
11885function get_ixti(supbooks, ixti, opts) {
11886 var ixtiraw = get_ixti_raw(supbooks, ixti, opts);
11887 return ixtiraw == "#REF" ? ixtiraw : formula_quote_sheet_name(ixtiraw, opts);
11888}
11889function stringify_formula(formula/*Array<any>*/, range, cell, supbooks, opts) {
11890 var biff = (opts && opts.biff) || 8;
11891 var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}};
11892 var stack = [], e1, e2, c, ixti=0, nameidx=0, r, sname="";
11893 if(!formula[0] || !formula[0][0]) return "";
11894 var last_sp = -1, sp = "";
11895 for(var ff = 0, fflen = formula[0].length; ff < fflen; ++ff) {
11896 var f = formula[0][ff];
11897 switch(f[0]) {
11898 case 'PtgUminus': /* [MS-XLS] 2.5.198.93 */
11899 stack.push("-" + stack.pop()); break;
11900 case 'PtgUplus': /* [MS-XLS] 2.5.198.95 */
11901 stack.push("+" + stack.pop()); break;
11902 case 'PtgPercent': /* [MS-XLS] 2.5.198.81 */
11903 stack.push(stack.pop() + "%"); break;
11904
11905 case 'PtgAdd': /* [MS-XLS] 2.5.198.26 */
11906 case 'PtgConcat': /* [MS-XLS] 2.5.198.43 */
11907 case 'PtgDiv': /* [MS-XLS] 2.5.198.45 */
11908 case 'PtgEq': /* [MS-XLS] 2.5.198.56 */
11909 case 'PtgGe': /* [MS-XLS] 2.5.198.64 */
11910 case 'PtgGt': /* [MS-XLS] 2.5.198.65 */
11911 case 'PtgLe': /* [MS-XLS] 2.5.198.68 */
11912 case 'PtgLt': /* [MS-XLS] 2.5.198.69 */
11913 case 'PtgMul': /* [MS-XLS] 2.5.198.75 */
11914 case 'PtgNe': /* [MS-XLS] 2.5.198.78 */
11915 case 'PtgPower': /* [MS-XLS] 2.5.198.82 */
11916 case 'PtgSub': /* [MS-XLS] 2.5.198.90 */
11917 e1 = stack.pop(); e2 = stack.pop();
11918 if(last_sp >= 0) {
11919 switch(formula[0][last_sp][1][0]) {
11920 case 0:
11921 // $FlowIgnore
11922 sp = fill(" ", formula[0][last_sp][1][1]); break;
11923 case 1:
11924 // $FlowIgnore
11925 sp = fill("\r", formula[0][last_sp][1][1]); break;
11926 default:
11927 sp = "";
11928 // $FlowIgnore
11929 if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + formula[0][last_sp][1][0]);
11930 }
11931 e2 = e2 + sp;
11932 last_sp = -1;
11933 }
11934 stack.push(e2+PtgBinOp[f[0]]+e1);
11935 break;
11936
11937 case 'PtgIsect': /* [MS-XLS] 2.5.198.67 */
11938 e1 = stack.pop(); e2 = stack.pop();
11939 stack.push(e2+" "+e1);
11940 break;
11941 case 'PtgUnion': /* [MS-XLS] 2.5.198.94 */
11942 e1 = stack.pop(); e2 = stack.pop();
11943 stack.push(e2+","+e1);
11944 break;
11945 case 'PtgRange': /* [MS-XLS] 2.5.198.83 */
11946 e1 = stack.pop(); e2 = stack.pop();
11947 stack.push(e2+":"+e1);
11948 break;
11949
11950 case 'PtgAttrChoose': /* [MS-XLS] 2.5.198.34 */
11951 break;
11952 case 'PtgAttrGoto': /* [MS-XLS] 2.5.198.35 */
11953 break;
11954 case 'PtgAttrIf': /* [MS-XLS] 2.5.198.36 */
11955 break;
11956 case 'PtgAttrIfError': /* [MS-XLSB] 2.5.97.28 */
11957 break;
11958
11959
11960 case 'PtgRef': /* [MS-XLS] 2.5.198.84 */
11961c = shift_cell_xls((f[1][1]), _range, opts);
11962 stack.push(encode_cell_xls(c, biff));
11963 break;
11964 case 'PtgRefN': /* [MS-XLS] 2.5.198.88 */
11965c = cell ? shift_cell_xls((f[1][1]), cell, opts) : (f[1][1]);
11966 stack.push(encode_cell_xls(c, biff));
11967 break;
11968 case 'PtgRef3d': /* [MS-XLS] 2.5.198.85 */
11969ixti = f[1][1]; c = shift_cell_xls((f[1][2]), _range, opts);
11970 sname = get_ixti(supbooks, ixti, opts);
11971 var w = sname; /* IE9 fails on defined names */ // eslint-disable-line no-unused-vars
11972 stack.push(sname + "!" + encode_cell_xls(c, biff));
11973 break;
11974
11975 case 'PtgFunc': /* [MS-XLS] 2.5.198.62 */
11976 case 'PtgFuncVar': /* [MS-XLS] 2.5.198.63 */
11977 /* f[1] = [argc, func, type] */
11978 var argc = (f[1][0]), func = (f[1][1]);
11979 if(!argc) argc = 0;
11980 argc &= 0x7F;
11981 var args = argc == 0 ? [] : stack.slice(-argc);
11982 stack.length -= argc;
11983 if(func === 'User') func = args.shift();
11984 stack.push(func + "(" + args.join(",") + ")");
11985 break;
11986
11987 case 'PtgBool': /* [MS-XLS] 2.5.198.42 */
11988 stack.push(f[1] ? "TRUE" : "FALSE"); break;
11989 case 'PtgInt': /* [MS-XLS] 2.5.198.66 */
11990 stack.push(f[1]); break;
11991 case 'PtgNum': /* [MS-XLS] 2.5.198.79 TODO: precision? */
11992 stack.push(String(f[1])); break;
11993 case 'PtgStr': /* [MS-XLS] 2.5.198.89 */
11994 // $FlowIgnore
11995 stack.push('"' + f[1].replace(/"/g, '""') + '"'); break;
11996 case 'PtgErr': /* [MS-XLS] 2.5.198.57 */
11997 stack.push(f[1]); break;
11998 case 'PtgAreaN': /* [MS-XLS] 2.5.198.31 TODO */
11999r = shift_range_xls(f[1][1], cell ? {s:cell} : _range, opts);
12000 stack.push(encode_range_xls((r), opts));
12001 break;
12002 case 'PtgArea': /* [MS-XLS] 2.5.198.27 TODO: fixed points */
12003r = shift_range_xls(f[1][1], _range, opts);
12004 stack.push(encode_range_xls((r), opts));
12005 break;
12006 case 'PtgArea3d': /* [MS-XLS] 2.5.198.28 TODO */
12007ixti = f[1][1]; r = f[1][2];
12008 sname = get_ixti(supbooks, ixti, opts);
12009 stack.push(sname + "!" + encode_range_xls((r), opts));
12010 break;
12011 case 'PtgAttrSum': /* [MS-XLS] 2.5.198.41 */
12012 stack.push("SUM(" + stack.pop() + ")");
12013 break;
12014
12015 case 'PtgAttrBaxcel': /* [MS-XLS] 2.5.198.33 */
12016 case 'PtgAttrSemi': /* [MS-XLS] 2.5.198.37 */
12017 break;
12018
12019 case 'PtgName': /* [MS-XLS] 2.5.198.76 ; [MS-XLSB] 2.5.97.60 TODO: revisions */
12020 /* f[1] = type, 0, nameindex */
12021 nameidx = (f[1][2]);
12022 var lbl = (supbooks.names||[])[nameidx-1] || (supbooks[0]||[])[nameidx];
12023 var name = lbl ? lbl.Name : "SH33TJSNAME" + String(nameidx);
12024 if(name in XLSXFutureFunctions) name = XLSXFutureFunctions[name];
12025 stack.push(name);
12026 break;
12027
12028 case 'PtgNameX': /* [MS-XLS] 2.5.198.77 ; [MS-XLSB] 2.5.97.61 TODO: revisions */
12029 /* f[1] = type, ixti, nameindex */
12030 var bookidx = (f[1][1]); nameidx = (f[1][2]); var externbook;
12031 /* TODO: Properly handle missing values -- this should be using get_ixti_raw primarily */
12032 if(opts.biff <= 5) {
12033 if(bookidx < 0) bookidx = -bookidx;
12034 if(supbooks[bookidx]) externbook = supbooks[bookidx][nameidx];
12035 } else {
12036 var o = "";
12037 if(((supbooks[bookidx]||[])[0]||[])[0] == 0x3A01){/* empty */}
12038 else if(((supbooks[bookidx]||[])[0]||[])[0] == 0x0401){
12039 if(supbooks[bookidx][nameidx] && supbooks[bookidx][nameidx].itab > 0) {
12040 o = supbooks.SheetNames[supbooks[bookidx][nameidx].itab-1] + "!";
12041 }
12042 }
12043 else o = supbooks.SheetNames[nameidx-1]+ "!";
12044 if(supbooks[bookidx] && supbooks[bookidx][nameidx]) o += supbooks[bookidx][nameidx].Name;
12045 else if(supbooks[0] && supbooks[0][nameidx]) o += supbooks[0][nameidx].Name;
12046 else {
12047 var ixtidata = (get_ixti_raw(supbooks, bookidx, opts)||"").split(";;");
12048 if(ixtidata[nameidx - 1]) o = ixtidata[nameidx - 1]; // TODO: confirm this is correct
12049 else o += "SH33TJSERRX";
12050 }
12051 stack.push(o);
12052 break;
12053 }
12054 if(!externbook) externbook = {Name: "SH33TJSERRY"};
12055 stack.push(externbook.Name);
12056 break;
12057
12058 case 'PtgParen': /* [MS-XLS] 2.5.198.80 */
12059 var lp = '(', rp = ')';
12060 if(last_sp >= 0) {
12061 sp = "";
12062 switch(formula[0][last_sp][1][0]) {
12063 // $FlowIgnore
12064 case 2: lp = fill(" ", formula[0][last_sp][1][1]) + lp; break;
12065 // $FlowIgnore
12066 case 3: lp = fill("\r", formula[0][last_sp][1][1]) + lp; break;
12067 // $FlowIgnore
12068 case 4: rp = fill(" ", formula[0][last_sp][1][1]) + rp; break;
12069 // $FlowIgnore
12070 case 5: rp = fill("\r", formula[0][last_sp][1][1]) + rp; break;
12071 default:
12072 // $FlowIgnore
12073 if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + formula[0][last_sp][1][0]);
12074 }
12075 last_sp = -1;
12076 }
12077 stack.push(lp + stack.pop() + rp); break;
12078
12079 case 'PtgRefErr': /* [MS-XLS] 2.5.198.86 */
12080 stack.push('#REF!'); break;
12081
12082 case 'PtgRefErr3d': /* [MS-XLS] 2.5.198.87 */
12083 stack.push('#REF!'); break;
12084
12085 case 'PtgExp': /* [MS-XLS] 2.5.198.58 TODO */
12086 c = {c:(f[1][1]),r:(f[1][0])};
12087 var q = ({c: cell.c, r:cell.r});
12088 if(supbooks.sharedf[encode_cell(c)]) {
12089 var parsedf = (supbooks.sharedf[encode_cell(c)]);
12090 stack.push(stringify_formula(parsedf, _range, q, supbooks, opts));
12091 } else {
12092 var fnd = false;
12093 for(e1=0;e1!=supbooks.arrayf.length; ++e1) {
12094 /* TODO: should be something like range_has */
12095 e2 = supbooks.arrayf[e1];
12096 if(c.c < e2[0].s.c || c.c > e2[0].e.c) continue;
12097 if(c.r < e2[0].s.r || c.r > e2[0].e.r) continue;
12098 stack.push(stringify_formula(e2[1], _range, q, supbooks, opts));
12099 fnd = true;
12100 break;
12101 }
12102 if(!fnd) stack.push(f[1]);
12103 }
12104 break;
12105
12106 case 'PtgArray': /* [MS-XLS] 2.5.198.32 TODO */
12107 stack.push("{" + stringify_array(f[1]) + "}");
12108 break;
12109
12110 case 'PtgMemArea': /* [MS-XLS] 2.5.198.70 TODO: confirm this is a non-display */
12111 //stack.push("(" + f[2].map(encode_range).join(",") + ")");
12112 break;
12113
12114 case 'PtgAttrSpace': /* [MS-XLS] 2.5.198.38 */
12115 case 'PtgAttrSpaceSemi': /* [MS-XLS] 2.5.198.39 */
12116 last_sp = ff;
12117 break;
12118
12119 case 'PtgTbl': /* [MS-XLS] 2.5.198.92 TODO */
12120 break;
12121
12122 case 'PtgMemErr': /* [MS-XLS] 2.5.198.71 */
12123 break;
12124
12125 case 'PtgMissArg': /* [MS-XLS] 2.5.198.74 */
12126 stack.push("");
12127 break;
12128
12129 case 'PtgAreaErr': /* [MS-XLS] 2.5.198.29 */
12130 stack.push("#REF!"); break;
12131
12132 case 'PtgAreaErr3d': /* [MS-XLS] 2.5.198.30 */
12133 stack.push("#REF!"); break;
12134
12135 case 'PtgList': /* [MS-XLSB] 2.5.97.52 */
12136 // $FlowIgnore
12137 stack.push("Table" + f[1].idx + "[#" + f[1].rt + "]");
12138 break;
12139
12140 case 'PtgMemAreaN':
12141 case 'PtgMemNoMemN':
12142 case 'PtgAttrNoop':
12143 case 'PtgSheet':
12144 case 'PtgEndSheet':
12145 break;
12146
12147 case 'PtgMemFunc': /* [MS-XLS] 2.5.198.72 TODO */
12148 break;
12149 case 'PtgMemNoMem': /* [MS-XLS] 2.5.198.73 TODO */
12150 break;
12151
12152 case 'PtgElfCol': /* [MS-XLS] 2.5.198.46 */
12153 case 'PtgElfColS': /* [MS-XLS] 2.5.198.47 */
12154 case 'PtgElfColSV': /* [MS-XLS] 2.5.198.48 */
12155 case 'PtgElfColV': /* [MS-XLS] 2.5.198.49 */
12156 case 'PtgElfLel': /* [MS-XLS] 2.5.198.50 */
12157 case 'PtgElfRadical': /* [MS-XLS] 2.5.198.51 */
12158 case 'PtgElfRadicalLel': /* [MS-XLS] 2.5.198.52 */
12159 case 'PtgElfRadicalS': /* [MS-XLS] 2.5.198.53 */
12160 case 'PtgElfRw': /* [MS-XLS] 2.5.198.54 */
12161 case 'PtgElfRwV': /* [MS-XLS] 2.5.198.55 */
12162 throw new Error("Unsupported ELFs");
12163
12164 case 'PtgSxName': /* [MS-XLS] 2.5.198.91 TODO -- find a test case */
12165 throw new Error('Unrecognized Formula Token: ' + String(f));
12166 default: throw new Error('Unrecognized Formula Token: ' + String(f));
12167 }
12168 var PtgNonDisp = ['PtgAttrSpace', 'PtgAttrSpaceSemi', 'PtgAttrGoto'];
12169 if(opts.biff != 3) if(last_sp >= 0 && PtgNonDisp.indexOf(formula[0][ff][0]) == -1) {
12170 f = formula[0][last_sp];
12171 var _left = true;
12172 switch(f[1][0]) {
12173 /* note: some bad XLSB files omit the PtgParen */
12174 case 4: _left = false;
12175 /* falls through */
12176 case 0:
12177 // $FlowIgnore
12178 sp = fill(" ", f[1][1]); break;
12179 case 5: _left = false;
12180 /* falls through */
12181 case 1:
12182 // $FlowIgnore
12183 sp = fill("\r", f[1][1]); break;
12184 default:
12185 sp = "";
12186 // $FlowIgnore
12187 if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + f[1][0]);
12188 }
12189 stack.push((_left ? sp : "") + stack.pop() + (_left ? "" : sp));
12190 last_sp = -1;
12191 }
12192 }
12193 if(stack.length > 1 && opts.WTF) throw new Error("bad formula stack");
12194 return stack[0];
12195}
12196
12197/* [MS-XLS] 2.5.198.1 TODO */
12198function parse_ArrayParsedFormula(blob, length, opts) {
12199 var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
12200 var rgcb, cce = blob.read_shift(len); // length of rgce
12201 if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
12202 var rgce = parse_Rgce(blob, cce, opts);
12203 if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
12204 blob.l = target;
12205 return [rgce, rgcb];
12206}
12207
12208/* [MS-XLS] 2.5.198.3 TODO */
12209function parse_XLSCellParsedFormula(blob, length, opts) {
12210 var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
12211 var rgcb, cce = blob.read_shift(len); // length of rgce
12212 if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
12213 var rgce = parse_Rgce(blob, cce, opts);
12214 if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
12215 blob.l = target;
12216 return [rgce, rgcb];
12217}
12218
12219/* [MS-XLS] 2.5.198.21 */
12220function parse_NameParsedFormula(blob, length, opts, cce) {
12221 var target = blob.l + length;
12222 var rgce = parse_Rgce(blob, cce, opts);
12223 var rgcb;
12224 if(target !== blob.l) rgcb = parse_RgbExtra(blob, target - blob.l, rgce, opts);
12225 return [rgce, rgcb];
12226}
12227
12228/* [MS-XLS] 2.5.198.118 TODO */
12229function parse_SharedParsedFormula(blob, length, opts) {
12230 var target = blob.l + length;
12231 var rgcb, cce = blob.read_shift(2); // length of rgce
12232 var rgce = parse_Rgce(blob, cce, opts);
12233 if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
12234 if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
12235 return [rgce, rgcb];
12236}
12237
12238/* [MS-XLS] 2.5.133 TODO: how to emit empty strings? */
12239function parse_FormulaValue(blob) {
12240 var b;
12241 if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return [parse_Xnum(blob),'n'];
12242 switch(blob[blob.l]) {
12243 case 0x00: blob.l += 8; return ["String", 's'];
12244 case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return [b,'b'];
12245 case 0x02: b = blob[blob.l+2]; blob.l += 8; return [b,'e'];
12246 case 0x03: blob.l += 8; return ["",'s'];
12247 }
12248 return [];
12249}
12250function write_FormulaValue(value) {
12251 if(value == null) {
12252 // Blank String Value
12253 var o = new_buf(8);
12254 o.write_shift(1, 0x03);
12255 o.write_shift(1, 0);
12256 o.write_shift(2, 0);
12257 o.write_shift(2, 0);
12258 o.write_shift(2, 0xFFFF);
12259 return o;
12260 } else if(typeof value == "number") return write_Xnum(value);
12261 return write_Xnum(0);
12262}
12263
12264/* [MS-XLS] 2.4.127 TODO */
12265function parse_Formula(blob, length, opts) {
12266 var end = blob.l + length;
12267 var cell = parse_XLSCell(blob, 6);
12268 if(opts.biff == 2) ++blob.l;
12269 var val = parse_FormulaValue(blob,8);
12270 var flags = blob.read_shift(1);
12271 if(opts.biff != 2) {
12272 blob.read_shift(1);
12273 if(opts.biff >= 5) {
12274 /*var chn = */blob.read_shift(4);
12275 }
12276 }
12277 var cbf = parse_XLSCellParsedFormula(blob, end - blob.l, opts);
12278 return {cell:cell, val:val[0], formula:cbf, shared: (flags >> 3) & 1, tt:val[1]};
12279}
12280function write_Formula(cell, R, C, opts, os) {
12281 // Cell
12282 var o1 = write_XLSCell(R, C, os);
12283
12284 // FormulaValue
12285 var o2 = write_FormulaValue(cell.v);
12286
12287 // flags + cache
12288 var o3 = new_buf(6);
12289 var flags = 0x01 | 0x20;
12290 o3.write_shift(2, flags);
12291 o3.write_shift(4, 0);
12292
12293 // CellParsedFormula
12294 var bf = new_buf(cell.bf.length);
12295 for(var i = 0; i < cell.bf.length; ++i) bf[i] = cell.bf[i];
12296
12297 var out = bconcat([o1, o2, o3, bf]);
12298 return out;
12299}
12300
12301
12302/* XLSB Parsed Formula records have the same shape */
12303function parse_XLSBParsedFormula(data, length, opts) {
12304 var cce = data.read_shift(4);
12305 var rgce = parse_Rgce(data, cce, opts);
12306 var cb = data.read_shift(4);
12307 var rgcb = cb > 0 ? parse_RgbExtra(data, cb, rgce, opts) : null;
12308 return [rgce, rgcb];
12309}
12310
12311/* [MS-XLSB] 2.5.97.1 ArrayParsedFormula */
12312var parse_XLSBArrayParsedFormula = parse_XLSBParsedFormula;
12313/* [MS-XLSB] 2.5.97.4 CellParsedFormula */
12314var parse_XLSBCellParsedFormula = parse_XLSBParsedFormula;
12315/* [MS-XLSB] 2.5.97.8 DVParsedFormula */
12316//var parse_XLSBDVParsedFormula = parse_XLSBParsedFormula;
12317/* [MS-XLSB] 2.5.97.9 FRTParsedFormula */
12318//var parse_XLSBFRTParsedFormula = parse_XLSBParsedFormula2;
12319/* [MS-XLSB] 2.5.97.12 NameParsedFormula */
12320var parse_XLSBNameParsedFormula = parse_XLSBParsedFormula;
12321/* [MS-XLSB] 2.5.97.98 SharedParsedFormula */
12322var parse_XLSBSharedParsedFormula = parse_XLSBParsedFormula;
12323/* [MS-XLS] 2.5.198.4 */
12324var Cetab = {
123250x0000: 'BEEP',
123260x0001: 'OPEN',
123270x0002: 'OPEN.LINKS',
123280x0003: 'CLOSE.ALL',
123290x0004: 'SAVE',
123300x0005: 'SAVE.AS',
123310x0006: 'FILE.DELETE',
123320x0007: 'PAGE.SETUP',
123330x0008: 'PRINT',
123340x0009: 'PRINTER.SETUP',
123350x000A: 'QUIT',
123360x000B: 'NEW.WINDOW',
123370x000C: 'ARRANGE.ALL',
123380x000D: 'WINDOW.SIZE',
123390x000E: 'WINDOW.MOVE',
123400x000F: 'FULL',
123410x0010: 'CLOSE',
123420x0011: 'RUN',
123430x0016: 'SET.PRINT.AREA',
123440x0017: 'SET.PRINT.TITLES',
123450x0018: 'SET.PAGE.BREAK',
123460x0019: 'REMOVE.PAGE.BREAK',
123470x001A: 'FONT',
123480x001B: 'DISPLAY',
123490x001C: 'PROTECT.DOCUMENT',
123500x001D: 'PRECISION',
123510x001E: 'A1.R1C1',
123520x001F: 'CALCULATE.NOW',
123530x0020: 'CALCULATION',
123540x0022: 'DATA.FIND',
123550x0023: 'EXTRACT',
123560x0024: 'DATA.DELETE',
123570x0025: 'SET.DATABASE',
123580x0026: 'SET.CRITERIA',
123590x0027: 'SORT',
123600x0028: 'DATA.SERIES',
123610x0029: 'TABLE',
123620x002A: 'FORMAT.NUMBER',
123630x002B: 'ALIGNMENT',
123640x002C: 'STYLE',
123650x002D: 'BORDER',
123660x002E: 'CELL.PROTECTION',
123670x002F: 'COLUMN.WIDTH',
123680x0030: 'UNDO',
123690x0031: 'CUT',
123700x0032: 'COPY',
123710x0033: 'PASTE',
123720x0034: 'CLEAR',
123730x0035: 'PASTE.SPECIAL',
123740x0036: 'EDIT.DELETE',
123750x0037: 'INSERT',
123760x0038: 'FILL.RIGHT',
123770x0039: 'FILL.DOWN',
123780x003D: 'DEFINE.NAME',
123790x003E: 'CREATE.NAMES',
123800x003F: 'FORMULA.GOTO',
123810x0040: 'FORMULA.FIND',
123820x0041: 'SELECT.LAST.CELL',
123830x0042: 'SHOW.ACTIVE.CELL',
123840x0043: 'GALLERY.AREA',
123850x0044: 'GALLERY.BAR',
123860x0045: 'GALLERY.COLUMN',
123870x0046: 'GALLERY.LINE',
123880x0047: 'GALLERY.PIE',
123890x0048: 'GALLERY.SCATTER',
123900x0049: 'COMBINATION',
123910x004A: 'PREFERRED',
123920x004B: 'ADD.OVERLAY',
123930x004C: 'GRIDLINES',
123940x004D: 'SET.PREFERRED',
123950x004E: 'AXES',
123960x004F: 'LEGEND',
123970x0050: 'ATTACH.TEXT',
123980x0051: 'ADD.ARROW',
123990x0052: 'SELECT.CHART',
124000x0053: 'SELECT.PLOT.AREA',
124010x0054: 'PATTERNS',
124020x0055: 'MAIN.CHART',
124030x0056: 'OVERLAY',
124040x0057: 'SCALE',
124050x0058: 'FORMAT.LEGEND',
124060x0059: 'FORMAT.TEXT',
124070x005A: 'EDIT.REPEAT',
124080x005B: 'PARSE',
124090x005C: 'JUSTIFY',
124100x005D: 'HIDE',
124110x005E: 'UNHIDE',
124120x005F: 'WORKSPACE',
124130x0060: 'FORMULA',
124140x0061: 'FORMULA.FILL',
124150x0062: 'FORMULA.ARRAY',
124160x0063: 'DATA.FIND.NEXT',
124170x0064: 'DATA.FIND.PREV',
124180x0065: 'FORMULA.FIND.NEXT',
124190x0066: 'FORMULA.FIND.PREV',
124200x0067: 'ACTIVATE',
124210x0068: 'ACTIVATE.NEXT',
124220x0069: 'ACTIVATE.PREV',
124230x006A: 'UNLOCKED.NEXT',
124240x006B: 'UNLOCKED.PREV',
124250x006C: 'COPY.PICTURE',
124260x006D: 'SELECT',
124270x006E: 'DELETE.NAME',
124280x006F: 'DELETE.FORMAT',
124290x0070: 'VLINE',
124300x0071: 'HLINE',
124310x0072: 'VPAGE',
124320x0073: 'HPAGE',
124330x0074: 'VSCROLL',
124340x0075: 'HSCROLL',
124350x0076: 'ALERT',
124360x0077: 'NEW',
124370x0078: 'CANCEL.COPY',
124380x0079: 'SHOW.CLIPBOARD',
124390x007A: 'MESSAGE',
124400x007C: 'PASTE.LINK',
124410x007D: 'APP.ACTIVATE',
124420x007E: 'DELETE.ARROW',
124430x007F: 'ROW.HEIGHT',
124440x0080: 'FORMAT.MOVE',
124450x0081: 'FORMAT.SIZE',
124460x0082: 'FORMULA.REPLACE',
124470x0083: 'SEND.KEYS',
124480x0084: 'SELECT.SPECIAL',
124490x0085: 'APPLY.NAMES',
124500x0086: 'REPLACE.FONT',
124510x0087: 'FREEZE.PANES',
124520x0088: 'SHOW.INFO',
124530x0089: 'SPLIT',
124540x008A: 'ON.WINDOW',
124550x008B: 'ON.DATA',
124560x008C: 'DISABLE.INPUT',
124570x008E: 'OUTLINE',
124580x008F: 'LIST.NAMES',
124590x0090: 'FILE.CLOSE',
124600x0091: 'SAVE.WORKBOOK',
124610x0092: 'DATA.FORM',
124620x0093: 'COPY.CHART',
124630x0094: 'ON.TIME',
124640x0095: 'WAIT',
124650x0096: 'FORMAT.FONT',
124660x0097: 'FILL.UP',
124670x0098: 'FILL.LEFT',
124680x0099: 'DELETE.OVERLAY',
124690x009B: 'SHORT.MENUS',
124700x009F: 'SET.UPDATE.STATUS',
124710x00A1: 'COLOR.PALETTE',
124720x00A2: 'DELETE.STYLE',
124730x00A3: 'WINDOW.RESTORE',
124740x00A4: 'WINDOW.MAXIMIZE',
124750x00A6: 'CHANGE.LINK',
124760x00A7: 'CALCULATE.DOCUMENT',
124770x00A8: 'ON.KEY',
124780x00A9: 'APP.RESTORE',
124790x00AA: 'APP.MOVE',
124800x00AB: 'APP.SIZE',
124810x00AC: 'APP.MINIMIZE',
124820x00AD: 'APP.MAXIMIZE',
124830x00AE: 'BRING.TO.FRONT',
124840x00AF: 'SEND.TO.BACK',
124850x00B9: 'MAIN.CHART.TYPE',
124860x00BA: 'OVERLAY.CHART.TYPE',
124870x00BB: 'SELECT.END',
124880x00BC: 'OPEN.MAIL',
124890x00BD: 'SEND.MAIL',
124900x00BE: 'STANDARD.FONT',
124910x00BF: 'CONSOLIDATE',
124920x00C0: 'SORT.SPECIAL',
124930x00C1: 'GALLERY.3D.AREA',
124940x00C2: 'GALLERY.3D.COLUMN',
124950x00C3: 'GALLERY.3D.LINE',
124960x00C4: 'GALLERY.3D.PIE',
124970x00C5: 'VIEW.3D',
124980x00C6: 'GOAL.SEEK',
124990x00C7: 'WORKGROUP',
125000x00C8: 'FILL.GROUP',
125010x00C9: 'UPDATE.LINK',
125020x00CA: 'PROMOTE',
125030x00CB: 'DEMOTE',
125040x00CC: 'SHOW.DETAIL',
125050x00CE: 'UNGROUP',
125060x00CF: 'OBJECT.PROPERTIES',
125070x00D0: 'SAVE.NEW.OBJECT',
125080x00D1: 'SHARE',
125090x00D2: 'SHARE.NAME',
125100x00D3: 'DUPLICATE',
125110x00D4: 'APPLY.STYLE',
125120x00D5: 'ASSIGN.TO.OBJECT',
125130x00D6: 'OBJECT.PROTECTION',
125140x00D7: 'HIDE.OBJECT',
125150x00D8: 'SET.EXTRACT',
125160x00D9: 'CREATE.PUBLISHER',
125170x00DA: 'SUBSCRIBE.TO',
125180x00DB: 'ATTRIBUTES',
125190x00DC: 'SHOW.TOOLBAR',
125200x00DE: 'PRINT.PREVIEW',
125210x00DF: 'EDIT.COLOR',
125220x00E0: 'SHOW.LEVELS',
125230x00E1: 'FORMAT.MAIN',
125240x00E2: 'FORMAT.OVERLAY',
125250x00E3: 'ON.RECALC',
125260x00E4: 'EDIT.SERIES',
125270x00E5: 'DEFINE.STYLE',
125280x00F0: 'LINE.PRINT',
125290x00F3: 'ENTER.DATA',
125300x00F9: 'GALLERY.RADAR',
125310x00FA: 'MERGE.STYLES',
125320x00FB: 'EDITION.OPTIONS',
125330x00FC: 'PASTE.PICTURE',
125340x00FD: 'PASTE.PICTURE.LINK',
125350x00FE: 'SPELLING',
125360x0100: 'ZOOM',
125370x0103: 'INSERT.OBJECT',
125380x0104: 'WINDOW.MINIMIZE',
125390x0109: 'SOUND.NOTE',
125400x010A: 'SOUND.PLAY',
125410x010B: 'FORMAT.SHAPE',
125420x010C: 'EXTEND.POLYGON',
125430x010D: 'FORMAT.AUTO',
125440x0110: 'GALLERY.3D.BAR',
125450x0111: 'GALLERY.3D.SURFACE',
125460x0112: 'FILL.AUTO',
125470x0114: 'CUSTOMIZE.TOOLBAR',
125480x0115: 'ADD.TOOL',
125490x0116: 'EDIT.OBJECT',
125500x0117: 'ON.DOUBLECLICK',
125510x0118: 'ON.ENTRY',
125520x0119: 'WORKBOOK.ADD',
125530x011A: 'WORKBOOK.MOVE',
125540x011B: 'WORKBOOK.COPY',
125550x011C: 'WORKBOOK.OPTIONS',
125560x011D: 'SAVE.WORKSPACE',
125570x0120: 'CHART.WIZARD',
125580x0121: 'DELETE.TOOL',
125590x0122: 'MOVE.TOOL',
125600x0123: 'WORKBOOK.SELECT',
125610x0124: 'WORKBOOK.ACTIVATE',
125620x0125: 'ASSIGN.TO.TOOL',
125630x0127: 'COPY.TOOL',
125640x0128: 'RESET.TOOL',
125650x0129: 'CONSTRAIN.NUMERIC',
125660x012A: 'PASTE.TOOL',
125670x012E: 'WORKBOOK.NEW',
125680x0131: 'SCENARIO.CELLS',
125690x0132: 'SCENARIO.DELETE',
125700x0133: 'SCENARIO.ADD',
125710x0134: 'SCENARIO.EDIT',
125720x0135: 'SCENARIO.SHOW',
125730x0136: 'SCENARIO.SHOW.NEXT',
125740x0137: 'SCENARIO.SUMMARY',
125750x0138: 'PIVOT.TABLE.WIZARD',
125760x0139: 'PIVOT.FIELD.PROPERTIES',
125770x013A: 'PIVOT.FIELD',
125780x013B: 'PIVOT.ITEM',
125790x013C: 'PIVOT.ADD.FIELDS',
125800x013E: 'OPTIONS.CALCULATION',
125810x013F: 'OPTIONS.EDIT',
125820x0140: 'OPTIONS.VIEW',
125830x0141: 'ADDIN.MANAGER',
125840x0142: 'MENU.EDITOR',
125850x0143: 'ATTACH.TOOLBARS',
125860x0144: 'VBAActivate',
125870x0145: 'OPTIONS.CHART',
125880x0148: 'VBA.INSERT.FILE',
125890x014A: 'VBA.PROCEDURE.DEFINITION',
125900x0150: 'ROUTING.SLIP',
125910x0152: 'ROUTE.DOCUMENT',
125920x0153: 'MAIL.LOGON',
125930x0156: 'INSERT.PICTURE',
125940x0157: 'EDIT.TOOL',
125950x0158: 'GALLERY.DOUGHNUT',
125960x015E: 'CHART.TREND',
125970x0160: 'PIVOT.ITEM.PROPERTIES',
125980x0162: 'WORKBOOK.INSERT',
125990x0163: 'OPTIONS.TRANSITION',
126000x0164: 'OPTIONS.GENERAL',
126010x0172: 'FILTER.ADVANCED',
126020x0175: 'MAIL.ADD.MAILER',
126030x0176: 'MAIL.DELETE.MAILER',
126040x0177: 'MAIL.REPLY',
126050x0178: 'MAIL.REPLY.ALL',
126060x0179: 'MAIL.FORWARD',
126070x017A: 'MAIL.NEXT.LETTER',
126080x017B: 'DATA.LABEL',
126090x017C: 'INSERT.TITLE',
126100x017D: 'FONT.PROPERTIES',
126110x017E: 'MACRO.OPTIONS',
126120x017F: 'WORKBOOK.HIDE',
126130x0180: 'WORKBOOK.UNHIDE',
126140x0181: 'WORKBOOK.DELETE',
126150x0182: 'WORKBOOK.NAME',
126160x0184: 'GALLERY.CUSTOM',
126170x0186: 'ADD.CHART.AUTOFORMAT',
126180x0187: 'DELETE.CHART.AUTOFORMAT',
126190x0188: 'CHART.ADD.DATA',
126200x0189: 'AUTO.OUTLINE',
126210x018A: 'TAB.ORDER',
126220x018B: 'SHOW.DIALOG',
126230x018C: 'SELECT.ALL',
126240x018D: 'UNGROUP.SHEETS',
126250x018E: 'SUBTOTAL.CREATE',
126260x018F: 'SUBTOTAL.REMOVE',
126270x0190: 'RENAME.OBJECT',
126280x019C: 'WORKBOOK.SCROLL',
126290x019D: 'WORKBOOK.NEXT',
126300x019E: 'WORKBOOK.PREV',
126310x019F: 'WORKBOOK.TAB.SPLIT',
126320x01A0: 'FULL.SCREEN',
126330x01A1: 'WORKBOOK.PROTECT',
126340x01A4: 'SCROLLBAR.PROPERTIES',
126350x01A5: 'PIVOT.SHOW.PAGES',
126360x01A6: 'TEXT.TO.COLUMNS',
126370x01A7: 'FORMAT.CHARTTYPE',
126380x01A8: 'LINK.FORMAT',
126390x01A9: 'TRACER.DISPLAY',
126400x01AE: 'TRACER.NAVIGATE',
126410x01AF: 'TRACER.CLEAR',
126420x01B0: 'TRACER.ERROR',
126430x01B1: 'PIVOT.FIELD.GROUP',
126440x01B2: 'PIVOT.FIELD.UNGROUP',
126450x01B3: 'CHECKBOX.PROPERTIES',
126460x01B4: 'LABEL.PROPERTIES',
126470x01B5: 'LISTBOX.PROPERTIES',
126480x01B6: 'EDITBOX.PROPERTIES',
126490x01B7: 'PIVOT.REFRESH',
126500x01B8: 'LINK.COMBO',
126510x01B9: 'OPEN.TEXT',
126520x01BA: 'HIDE.DIALOG',
126530x01BB: 'SET.DIALOG.FOCUS',
126540x01BC: 'ENABLE.OBJECT',
126550x01BD: 'PUSHBUTTON.PROPERTIES',
126560x01BE: 'SET.DIALOG.DEFAULT',
126570x01BF: 'FILTER',
126580x01C0: 'FILTER.SHOW.ALL',
126590x01C1: 'CLEAR.OUTLINE',
126600x01C2: 'FUNCTION.WIZARD',
126610x01C3: 'ADD.LIST.ITEM',
126620x01C4: 'SET.LIST.ITEM',
126630x01C5: 'REMOVE.LIST.ITEM',
126640x01C6: 'SELECT.LIST.ITEM',
126650x01C7: 'SET.CONTROL.VALUE',
126660x01C8: 'SAVE.COPY.AS',
126670x01CA: 'OPTIONS.LISTS.ADD',
126680x01CB: 'OPTIONS.LISTS.DELETE',
126690x01CC: 'SERIES.AXES',
126700x01CD: 'SERIES.X',
126710x01CE: 'SERIES.Y',
126720x01CF: 'ERRORBAR.X',
126730x01D0: 'ERRORBAR.Y',
126740x01D1: 'FORMAT.CHART',
126750x01D2: 'SERIES.ORDER',
126760x01D3: 'MAIL.LOGOFF',
126770x01D4: 'CLEAR.ROUTING.SLIP',
126780x01D5: 'APP.ACTIVATE.MICROSOFT',
126790x01D6: 'MAIL.EDIT.MAILER',
126800x01D7: 'ON.SHEET',
126810x01D8: 'STANDARD.WIDTH',
126820x01D9: 'SCENARIO.MERGE',
126830x01DA: 'SUMMARY.INFO',
126840x01DB: 'FIND.FILE',
126850x01DC: 'ACTIVE.CELL.FONT',
126860x01DD: 'ENABLE.TIPWIZARD',
126870x01DE: 'VBA.MAKE.ADDIN',
126880x01E0: 'INSERTDATATABLE',
126890x01E1: 'WORKGROUP.OPTIONS',
126900x01E2: 'MAIL.SEND.MAILER',
126910x01E5: 'AUTOCORRECT',
126920x01E9: 'POST.DOCUMENT',
126930x01EB: 'PICKLIST',
126940x01ED: 'VIEW.SHOW',
126950x01EE: 'VIEW.DEFINE',
126960x01EF: 'VIEW.DELETE',
126970x01FD: 'SHEET.BACKGROUND',
126980x01FE: 'INSERT.MAP.OBJECT',
126990x01FF: 'OPTIONS.MENONO',
127000x0205: 'MSOCHECKS',
127010x0206: 'NORMAL',
127020x0207: 'LAYOUT',
127030x0208: 'RM.PRINT.AREA',
127040x0209: 'CLEAR.PRINT.AREA',
127050x020A: 'ADD.PRINT.AREA',
127060x020B: 'MOVE.BRK',
127070x0221: 'HIDECURR.NOTE',
127080x0222: 'HIDEALL.NOTES',
127090x0223: 'DELETE.NOTE',
127100x0224: 'TRAVERSE.NOTES',
127110x0225: 'ACTIVATE.NOTES',
127120x026C: 'PROTECT.REVISIONS',
127130x026D: 'UNPROTECT.REVISIONS',
127140x0287: 'OPTIONS.ME',
127150x028D: 'WEB.PUBLISH',
127160x029B: 'NEWWEBQUERY',
127170x02A1: 'PIVOT.TABLE.CHART',
127180x02F1: 'OPTIONS.SAVE',
127190x02F3: 'OPTIONS.SPELL',
127200x0328: 'HIDEALL.INKANNOTS'
12721};
12722
12723/* [MS-XLS] 2.5.198.17 */
12724/* [MS-XLSB] 2.5.97.10 */
12725var Ftab = {
127260x0000: 'COUNT',
127270x0001: 'IF',
127280x0002: 'ISNA',
127290x0003: 'ISERROR',
127300x0004: 'SUM',
127310x0005: 'AVERAGE',
127320x0006: 'MIN',
127330x0007: 'MAX',
127340x0008: 'ROW',
127350x0009: 'COLUMN',
127360x000A: 'NA',
127370x000B: 'NPV',
127380x000C: 'STDEV',
127390x000D: 'DOLLAR',
127400x000E: 'FIXED',
127410x000F: 'SIN',
127420x0010: 'COS',
127430x0011: 'TAN',
127440x0012: 'ATAN',
127450x0013: 'PI',
127460x0014: 'SQRT',
127470x0015: 'EXP',
127480x0016: 'LN',
127490x0017: 'LOG10',
127500x0018: 'ABS',
127510x0019: 'INT',
127520x001A: 'SIGN',
127530x001B: 'ROUND',
127540x001C: 'LOOKUP',
127550x001D: 'INDEX',
127560x001E: 'REPT',
127570x001F: 'MID',
127580x0020: 'LEN',
127590x0021: 'VALUE',
127600x0022: 'TRUE',
127610x0023: 'FALSE',
127620x0024: 'AND',
127630x0025: 'OR',
127640x0026: 'NOT',
127650x0027: 'MOD',
127660x0028: 'DCOUNT',
127670x0029: 'DSUM',
127680x002A: 'DAVERAGE',
127690x002B: 'DMIN',
127700x002C: 'DMAX',
127710x002D: 'DSTDEV',
127720x002E: 'VAR',
127730x002F: 'DVAR',
127740x0030: 'TEXT',
127750x0031: 'LINEST',
127760x0032: 'TREND',
127770x0033: 'LOGEST',
127780x0034: 'GROWTH',
127790x0035: 'GOTO',
127800x0036: 'HALT',
127810x0037: 'RETURN',
127820x0038: 'PV',
127830x0039: 'FV',
127840x003A: 'NPER',
127850x003B: 'PMT',
127860x003C: 'RATE',
127870x003D: 'MIRR',
127880x003E: 'IRR',
127890x003F: 'RAND',
127900x0040: 'MATCH',
127910x0041: 'DATE',
127920x0042: 'TIME',
127930x0043: 'DAY',
127940x0044: 'MONTH',
127950x0045: 'YEAR',
127960x0046: 'WEEKDAY',
127970x0047: 'HOUR',
127980x0048: 'MINUTE',
127990x0049: 'SECOND',
128000x004A: 'NOW',
128010x004B: 'AREAS',
128020x004C: 'ROWS',
128030x004D: 'COLUMNS',
128040x004E: 'OFFSET',
128050x004F: 'ABSREF',
128060x0050: 'RELREF',
128070x0051: 'ARGUMENT',
128080x0052: 'SEARCH',
128090x0053: 'TRANSPOSE',
128100x0054: 'ERROR',
128110x0055: 'STEP',
128120x0056: 'TYPE',
128130x0057: 'ECHO',
128140x0058: 'SET.NAME',
128150x0059: 'CALLER',
128160x005A: 'DEREF',
128170x005B: 'WINDOWS',
128180x005C: 'SERIES',
128190x005D: 'DOCUMENTS',
128200x005E: 'ACTIVE.CELL',
128210x005F: 'SELECTION',
128220x0060: 'RESULT',
128230x0061: 'ATAN2',
128240x0062: 'ASIN',
128250x0063: 'ACOS',
128260x0064: 'CHOOSE',
128270x0065: 'HLOOKUP',
128280x0066: 'VLOOKUP',
128290x0067: 'LINKS',
128300x0068: 'INPUT',
128310x0069: 'ISREF',
128320x006A: 'GET.FORMULA',
128330x006B: 'GET.NAME',
128340x006C: 'SET.VALUE',
128350x006D: 'LOG',
128360x006E: 'EXEC',
128370x006F: 'CHAR',
128380x0070: 'LOWER',
128390x0071: 'UPPER',
128400x0072: 'PROPER',
128410x0073: 'LEFT',
128420x0074: 'RIGHT',
128430x0075: 'EXACT',
128440x0076: 'TRIM',
128450x0077: 'REPLACE',
128460x0078: 'SUBSTITUTE',
128470x0079: 'CODE',
128480x007A: 'NAMES',
128490x007B: 'DIRECTORY',
128500x007C: 'FIND',
128510x007D: 'CELL',
128520x007E: 'ISERR',
128530x007F: 'ISTEXT',
128540x0080: 'ISNUMBER',
128550x0081: 'ISBLANK',
128560x0082: 'T',
128570x0083: 'N',
128580x0084: 'FOPEN',
128590x0085: 'FCLOSE',
128600x0086: 'FSIZE',
128610x0087: 'FREADLN',
128620x0088: 'FREAD',
128630x0089: 'FWRITELN',
128640x008A: 'FWRITE',
128650x008B: 'FPOS',
128660x008C: 'DATEVALUE',
128670x008D: 'TIMEVALUE',
128680x008E: 'SLN',
128690x008F: 'SYD',
128700x0090: 'DDB',
128710x0091: 'GET.DEF',
128720x0092: 'REFTEXT',
128730x0093: 'TEXTREF',
128740x0094: 'INDIRECT',
128750x0095: 'REGISTER',
128760x0096: 'CALL',
128770x0097: 'ADD.BAR',
128780x0098: 'ADD.MENU',
128790x0099: 'ADD.COMMAND',
128800x009A: 'ENABLE.COMMAND',
128810x009B: 'CHECK.COMMAND',
128820x009C: 'RENAME.COMMAND',
128830x009D: 'SHOW.BAR',
128840x009E: 'DELETE.MENU',
128850x009F: 'DELETE.COMMAND',
128860x00A0: 'GET.CHART.ITEM',
128870x00A1: 'DIALOG.BOX',
128880x00A2: 'CLEAN',
128890x00A3: 'MDETERM',
128900x00A4: 'MINVERSE',
128910x00A5: 'MMULT',
128920x00A6: 'FILES',
128930x00A7: 'IPMT',
128940x00A8: 'PPMT',
128950x00A9: 'COUNTA',
128960x00AA: 'CANCEL.KEY',
128970x00AB: 'FOR',
128980x00AC: 'WHILE',
128990x00AD: 'BREAK',
129000x00AE: 'NEXT',
129010x00AF: 'INITIATE',
129020x00B0: 'REQUEST',
129030x00B1: 'POKE',
129040x00B2: 'EXECUTE',
129050x00B3: 'TERMINATE',
129060x00B4: 'RESTART',
129070x00B5: 'HELP',
129080x00B6: 'GET.BAR',
129090x00B7: 'PRODUCT',
129100x00B8: 'FACT',
129110x00B9: 'GET.CELL',
129120x00BA: 'GET.WORKSPACE',
129130x00BB: 'GET.WINDOW',
129140x00BC: 'GET.DOCUMENT',
129150x00BD: 'DPRODUCT',
129160x00BE: 'ISNONTEXT',
129170x00BF: 'GET.NOTE',
129180x00C0: 'NOTE',
129190x00C1: 'STDEVP',
129200x00C2: 'VARP',
129210x00C3: 'DSTDEVP',
129220x00C4: 'DVARP',
129230x00C5: 'TRUNC',
129240x00C6: 'ISLOGICAL',
129250x00C7: 'DCOUNTA',
129260x00C8: 'DELETE.BAR',
129270x00C9: 'UNREGISTER',
129280x00CC: 'USDOLLAR',
129290x00CD: 'FINDB',
129300x00CE: 'SEARCHB',
129310x00CF: 'REPLACEB',
129320x00D0: 'LEFTB',
129330x00D1: 'RIGHTB',
129340x00D2: 'MIDB',
129350x00D3: 'LENB',
129360x00D4: 'ROUNDUP',
129370x00D5: 'ROUNDDOWN',
129380x00D6: 'ASC',
129390x00D7: 'DBCS',
129400x00D8: 'RANK',
129410x00DB: 'ADDRESS',
129420x00DC: 'DAYS360',
129430x00DD: 'TODAY',
129440x00DE: 'VDB',
129450x00DF: 'ELSE',
129460x00E0: 'ELSE.IF',
129470x00E1: 'END.IF',
129480x00E2: 'FOR.CELL',
129490x00E3: 'MEDIAN',
129500x00E4: 'SUMPRODUCT',
129510x00E5: 'SINH',
129520x00E6: 'COSH',
129530x00E7: 'TANH',
129540x00E8: 'ASINH',
129550x00E9: 'ACOSH',
129560x00EA: 'ATANH',
129570x00EB: 'DGET',
129580x00EC: 'CREATE.OBJECT',
129590x00ED: 'VOLATILE',
129600x00EE: 'LAST.ERROR',
129610x00EF: 'CUSTOM.UNDO',
129620x00F0: 'CUSTOM.REPEAT',
129630x00F1: 'FORMULA.CONVERT',
129640x00F2: 'GET.LINK.INFO',
129650x00F3: 'TEXT.BOX',
129660x00F4: 'INFO',
129670x00F5: 'GROUP',
129680x00F6: 'GET.OBJECT',
129690x00F7: 'DB',
129700x00F8: 'PAUSE',
129710x00FB: 'RESUME',
129720x00FC: 'FREQUENCY',
129730x00FD: 'ADD.TOOLBAR',
129740x00FE: 'DELETE.TOOLBAR',
129750x00FF: 'User',
129760x0100: 'RESET.TOOLBAR',
129770x0101: 'EVALUATE',
129780x0102: 'GET.TOOLBAR',
129790x0103: 'GET.TOOL',
129800x0104: 'SPELLING.CHECK',
129810x0105: 'ERROR.TYPE',
129820x0106: 'APP.TITLE',
129830x0107: 'WINDOW.TITLE',
129840x0108: 'SAVE.TOOLBAR',
129850x0109: 'ENABLE.TOOL',
129860x010A: 'PRESS.TOOL',
129870x010B: 'REGISTER.ID',
129880x010C: 'GET.WORKBOOK',
129890x010D: 'AVEDEV',
129900x010E: 'BETADIST',
129910x010F: 'GAMMALN',
129920x0110: 'BETAINV',
129930x0111: 'BINOMDIST',
129940x0112: 'CHIDIST',
129950x0113: 'CHIINV',
129960x0114: 'COMBIN',
129970x0115: 'CONFIDENCE',
129980x0116: 'CRITBINOM',
129990x0117: 'EVEN',
130000x0118: 'EXPONDIST',
130010x0119: 'FDIST',
130020x011A: 'FINV',
130030x011B: 'FISHER',
130040x011C: 'FISHERINV',
130050x011D: 'FLOOR',
130060x011E: 'GAMMADIST',
130070x011F: 'GAMMAINV',
130080x0120: 'CEILING',
130090x0121: 'HYPGEOMDIST',
130100x0122: 'LOGNORMDIST',
130110x0123: 'LOGINV',
130120x0124: 'NEGBINOMDIST',
130130x0125: 'NORMDIST',
130140x0126: 'NORMSDIST',
130150x0127: 'NORMINV',
130160x0128: 'NORMSINV',
130170x0129: 'STANDARDIZE',
130180x012A: 'ODD',
130190x012B: 'PERMUT',
130200x012C: 'POISSON',
130210x012D: 'TDIST',
130220x012E: 'WEIBULL',
130230x012F: 'SUMXMY2',
130240x0130: 'SUMX2MY2',
130250x0131: 'SUMX2PY2',
130260x0132: 'CHITEST',
130270x0133: 'CORREL',
130280x0134: 'COVAR',
130290x0135: 'FORECAST',
130300x0136: 'FTEST',
130310x0137: 'INTERCEPT',
130320x0138: 'PEARSON',
130330x0139: 'RSQ',
130340x013A: 'STEYX',
130350x013B: 'SLOPE',
130360x013C: 'TTEST',
130370x013D: 'PROB',
130380x013E: 'DEVSQ',
130390x013F: 'GEOMEAN',
130400x0140: 'HARMEAN',
130410x0141: 'SUMSQ',
130420x0142: 'KURT',
130430x0143: 'SKEW',
130440x0144: 'ZTEST',
130450x0145: 'LARGE',
130460x0146: 'SMALL',
130470x0147: 'QUARTILE',
130480x0148: 'PERCENTILE',
130490x0149: 'PERCENTRANK',
130500x014A: 'MODE',
130510x014B: 'TRIMMEAN',
130520x014C: 'TINV',
130530x014E: 'MOVIE.COMMAND',
130540x014F: 'GET.MOVIE',
130550x0150: 'CONCATENATE',
130560x0151: 'POWER',
130570x0152: 'PIVOT.ADD.DATA',
130580x0153: 'GET.PIVOT.TABLE',
130590x0154: 'GET.PIVOT.FIELD',
130600x0155: 'GET.PIVOT.ITEM',
130610x0156: 'RADIANS',
130620x0157: 'DEGREES',
130630x0158: 'SUBTOTAL',
130640x0159: 'SUMIF',
130650x015A: 'COUNTIF',
130660x015B: 'COUNTBLANK',
130670x015C: 'SCENARIO.GET',
130680x015D: 'OPTIONS.LISTS.GET',
130690x015E: 'ISPMT',
130700x015F: 'DATEDIF',
130710x0160: 'DATESTRING',
130720x0161: 'NUMBERSTRING',
130730x0162: 'ROMAN',
130740x0163: 'OPEN.DIALOG',
130750x0164: 'SAVE.DIALOG',
130760x0165: 'VIEW.GET',
130770x0166: 'GETPIVOTDATA',
130780x0167: 'HYPERLINK',
130790x0168: 'PHONETIC',
130800x0169: 'AVERAGEA',
130810x016A: 'MAXA',
130820x016B: 'MINA',
130830x016C: 'STDEVPA',
130840x016D: 'VARPA',
130850x016E: 'STDEVA',
130860x016F: 'VARA',
130870x0170: 'BAHTTEXT',
130880x0171: 'THAIDAYOFWEEK',
130890x0172: 'THAIDIGIT',
130900x0173: 'THAIMONTHOFYEAR',
130910x0174: 'THAINUMSOUND',
130920x0175: 'THAINUMSTRING',
130930x0176: 'THAISTRINGLENGTH',
130940x0177: 'ISTHAIDIGIT',
130950x0178: 'ROUNDBAHTDOWN',
130960x0179: 'ROUNDBAHTUP',
130970x017A: 'THAIYEAR',
130980x017B: 'RTD',
13099
131000x017C: 'CUBEVALUE',
131010x017D: 'CUBEMEMBER',
131020x017E: 'CUBEMEMBERPROPERTY',
131030x017F: 'CUBERANKEDMEMBER',
131040x0180: 'HEX2BIN',
131050x0181: 'HEX2DEC',
131060x0182: 'HEX2OCT',
131070x0183: 'DEC2BIN',
131080x0184: 'DEC2HEX',
131090x0185: 'DEC2OCT',
131100x0186: 'OCT2BIN',
131110x0187: 'OCT2HEX',
131120x0188: 'OCT2DEC',
131130x0189: 'BIN2DEC',
131140x018A: 'BIN2OCT',
131150x018B: 'BIN2HEX',
131160x018C: 'IMSUB',
131170x018D: 'IMDIV',
131180x018E: 'IMPOWER',
131190x018F: 'IMABS',
131200x0190: 'IMSQRT',
131210x0191: 'IMLN',
131220x0192: 'IMLOG2',
131230x0193: 'IMLOG10',
131240x0194: 'IMSIN',
131250x0195: 'IMCOS',
131260x0196: 'IMEXP',
131270x0197: 'IMARGUMENT',
131280x0198: 'IMCONJUGATE',
131290x0199: 'IMAGINARY',
131300x019A: 'IMREAL',
131310x019B: 'COMPLEX',
131320x019C: 'IMSUM',
131330x019D: 'IMPRODUCT',
131340x019E: 'SERIESSUM',
131350x019F: 'FACTDOUBLE',
131360x01A0: 'SQRTPI',
131370x01A1: 'QUOTIENT',
131380x01A2: 'DELTA',
131390x01A3: 'GESTEP',
131400x01A4: 'ISEVEN',
131410x01A5: 'ISODD',
131420x01A6: 'MROUND',
131430x01A7: 'ERF',
131440x01A8: 'ERFC',
131450x01A9: 'BESSELJ',
131460x01AA: 'BESSELK',
131470x01AB: 'BESSELY',
131480x01AC: 'BESSELI',
131490x01AD: 'XIRR',
131500x01AE: 'XNPV',
131510x01AF: 'PRICEMAT',
131520x01B0: 'YIELDMAT',
131530x01B1: 'INTRATE',
131540x01B2: 'RECEIVED',
131550x01B3: 'DISC',
131560x01B4: 'PRICEDISC',
131570x01B5: 'YIELDDISC',
131580x01B6: 'TBILLEQ',
131590x01B7: 'TBILLPRICE',
131600x01B8: 'TBILLYIELD',
131610x01B9: 'PRICE',
131620x01BA: 'YIELD',
131630x01BB: 'DOLLARDE',
131640x01BC: 'DOLLARFR',
131650x01BD: 'NOMINAL',
131660x01BE: 'EFFECT',
131670x01BF: 'CUMPRINC',
131680x01C0: 'CUMIPMT',
131690x01C1: 'EDATE',
131700x01C2: 'EOMONTH',
131710x01C3: 'YEARFRAC',
131720x01C4: 'COUPDAYBS',
131730x01C5: 'COUPDAYS',
131740x01C6: 'COUPDAYSNC',
131750x01C7: 'COUPNCD',
131760x01C8: 'COUPNUM',
131770x01C9: 'COUPPCD',
131780x01CA: 'DURATION',
131790x01CB: 'MDURATION',
131800x01CC: 'ODDLPRICE',
131810x01CD: 'ODDLYIELD',
131820x01CE: 'ODDFPRICE',
131830x01CF: 'ODDFYIELD',
131840x01D0: 'RANDBETWEEN',
131850x01D1: 'WEEKNUM',
131860x01D2: 'AMORDEGRC',
131870x01D3: 'AMORLINC',
131880x01D4: 'CONVERT',
131890x02D4: 'SHEETJS',
131900x01D5: 'ACCRINT',
131910x01D6: 'ACCRINTM',
131920x01D7: 'WORKDAY',
131930x01D8: 'NETWORKDAYS',
131940x01D9: 'GCD',
131950x01DA: 'MULTINOMIAL',
131960x01DB: 'LCM',
131970x01DC: 'FVSCHEDULE',
131980x01DD: 'CUBEKPIMEMBER',
131990x01DE: 'CUBESET',
132000x01DF: 'CUBESETCOUNT',
132010x01E0: 'IFERROR',
132020x01E1: 'COUNTIFS',
132030x01E2: 'SUMIFS',
132040x01E3: 'AVERAGEIF',
132050x01E4: 'AVERAGEIFS'
13206};
13207var FtabArgc = {
132080x0002: 1, /* ISNA */
132090x0003: 1, /* ISERROR */
132100x000A: 0, /* NA */
132110x000F: 1, /* SIN */
132120x0010: 1, /* COS */
132130x0011: 1, /* TAN */
132140x0012: 1, /* ATAN */
132150x0013: 0, /* PI */
132160x0014: 1, /* SQRT */
132170x0015: 1, /* EXP */
132180x0016: 1, /* LN */
132190x0017: 1, /* LOG10 */
132200x0018: 1, /* ABS */
132210x0019: 1, /* INT */
132220x001A: 1, /* SIGN */
132230x001B: 2, /* ROUND */
132240x001E: 2, /* REPT */
132250x001F: 3, /* MID */
132260x0020: 1, /* LEN */
132270x0021: 1, /* VALUE */
132280x0022: 0, /* TRUE */
132290x0023: 0, /* FALSE */
132300x0026: 1, /* NOT */
132310x0027: 2, /* MOD */
132320x0028: 3, /* DCOUNT */
132330x0029: 3, /* DSUM */
132340x002A: 3, /* DAVERAGE */
132350x002B: 3, /* DMIN */
132360x002C: 3, /* DMAX */
132370x002D: 3, /* DSTDEV */
132380x002F: 3, /* DVAR */
132390x0030: 2, /* TEXT */
132400x0035: 1, /* GOTO */
132410x003D: 3, /* MIRR */
132420x003F: 0, /* RAND */
132430x0041: 3, /* DATE */
132440x0042: 3, /* TIME */
132450x0043: 1, /* DAY */
132460x0044: 1, /* MONTH */
132470x0045: 1, /* YEAR */
132480x0046: 1, /* WEEKDAY */
132490x0047: 1, /* HOUR */
132500x0048: 1, /* MINUTE */
132510x0049: 1, /* SECOND */
132520x004A: 0, /* NOW */
132530x004B: 1, /* AREAS */
132540x004C: 1, /* ROWS */
132550x004D: 1, /* COLUMNS */
132560x004F: 2, /* ABSREF */
132570x0050: 2, /* RELREF */
132580x0053: 1, /* TRANSPOSE */
132590x0055: 0, /* STEP */
132600x0056: 1, /* TYPE */
132610x0059: 0, /* CALLER */
132620x005A: 1, /* DEREF */
132630x005E: 0, /* ACTIVE.CELL */
132640x005F: 0, /* SELECTION */
132650x0061: 2, /* ATAN2 */
132660x0062: 1, /* ASIN */
132670x0063: 1, /* ACOS */
132680x0065: 3, /* HLOOKUP */
132690x0066: 3, /* VLOOKUP */
132700x0069: 1, /* ISREF */
132710x006A: 1, /* GET.FORMULA */
132720x006C: 2, /* SET.VALUE */
132730x006F: 1, /* CHAR */
132740x0070: 1, /* LOWER */
132750x0071: 1, /* UPPER */
132760x0072: 1, /* PROPER */
132770x0075: 2, /* EXACT */
132780x0076: 1, /* TRIM */
132790x0077: 4, /* REPLACE */
132800x0079: 1, /* CODE */
132810x007E: 1, /* ISERR */
132820x007F: 1, /* ISTEXT */
132830x0080: 1, /* ISNUMBER */
132840x0081: 1, /* ISBLANK */
132850x0082: 1, /* T */
132860x0083: 1, /* N */
132870x0085: 1, /* FCLOSE */
132880x0086: 1, /* FSIZE */
132890x0087: 1, /* FREADLN */
132900x0088: 2, /* FREAD */
132910x0089: 2, /* FWRITELN */
132920x008A: 2, /* FWRITE */
132930x008C: 1, /* DATEVALUE */
132940x008D: 1, /* TIMEVALUE */
132950x008E: 3, /* SLN */
132960x008F: 4, /* SYD */
132970x0090: 4, /* DDB */
132980x00A1: 1, /* DIALOG.BOX */
132990x00A2: 1, /* CLEAN */
133000x00A3: 1, /* MDETERM */
133010x00A4: 1, /* MINVERSE */
133020x00A5: 2, /* MMULT */
133030x00AC: 1, /* WHILE */
133040x00AF: 2, /* INITIATE */
133050x00B0: 2, /* REQUEST */
133060x00B1: 3, /* POKE */
133070x00B2: 2, /* EXECUTE */
133080x00B3: 1, /* TERMINATE */
133090x00B8: 1, /* FACT */
133100x00BA: 1, /* GET.WORKSPACE */
133110x00BD: 3, /* DPRODUCT */
133120x00BE: 1, /* ISNONTEXT */
133130x00C3: 3, /* DSTDEVP */
133140x00C4: 3, /* DVARP */
133150x00C5: 1, /* TRUNC */
133160x00C6: 1, /* ISLOGICAL */
133170x00C7: 3, /* DCOUNTA */
133180x00C9: 1, /* UNREGISTER */
133190x00CF: 4, /* REPLACEB */
133200x00D2: 3, /* MIDB */
133210x00D3: 1, /* LENB */
133220x00D4: 2, /* ROUNDUP */
133230x00D5: 2, /* ROUNDDOWN */
133240x00D6: 1, /* ASC */
133250x00D7: 1, /* DBCS */
133260x00E1: 0, /* END.IF */
133270x00E5: 1, /* SINH */
133280x00E6: 1, /* COSH */
133290x00E7: 1, /* TANH */
133300x00E8: 1, /* ASINH */
133310x00E9: 1, /* ACOSH */
133320x00EA: 1, /* ATANH */
133330x00EB: 3, /* DGET */
133340x00F4: 1, /* INFO */
133350x00F7: 4, /* DB */
133360x00FC: 2, /* FREQUENCY */
133370x0101: 1, /* EVALUATE */
133380x0105: 1, /* ERROR.TYPE */
133390x010F: 1, /* GAMMALN */
133400x0111: 4, /* BINOMDIST */
133410x0112: 2, /* CHIDIST */
133420x0113: 2, /* CHIINV */
133430x0114: 2, /* COMBIN */
133440x0115: 3, /* CONFIDENCE */
133450x0116: 3, /* CRITBINOM */
133460x0117: 1, /* EVEN */
133470x0118: 3, /* EXPONDIST */
133480x0119: 3, /* FDIST */
133490x011A: 3, /* FINV */
133500x011B: 1, /* FISHER */
133510x011C: 1, /* FISHERINV */
133520x011D: 2, /* FLOOR */
133530x011E: 4, /* GAMMADIST */
133540x011F: 3, /* GAMMAINV */
133550x0120: 2, /* CEILING */
133560x0121: 4, /* HYPGEOMDIST */
133570x0122: 3, /* LOGNORMDIST */
133580x0123: 3, /* LOGINV */
133590x0124: 3, /* NEGBINOMDIST */
133600x0125: 4, /* NORMDIST */
133610x0126: 1, /* NORMSDIST */
133620x0127: 3, /* NORMINV */
133630x0128: 1, /* NORMSINV */
133640x0129: 3, /* STANDARDIZE */
133650x012A: 1, /* ODD */
133660x012B: 2, /* PERMUT */
133670x012C: 3, /* POISSON */
133680x012D: 3, /* TDIST */
133690x012E: 4, /* WEIBULL */
133700x012F: 2, /* SUMXMY2 */
133710x0130: 2, /* SUMX2MY2 */
133720x0131: 2, /* SUMX2PY2 */
133730x0132: 2, /* CHITEST */
133740x0133: 2, /* CORREL */
133750x0134: 2, /* COVAR */
133760x0135: 3, /* FORECAST */
133770x0136: 2, /* FTEST */
133780x0137: 2, /* INTERCEPT */
133790x0138: 2, /* PEARSON */
133800x0139: 2, /* RSQ */
133810x013A: 2, /* STEYX */
133820x013B: 2, /* SLOPE */
133830x013C: 4, /* TTEST */
133840x0145: 2, /* LARGE */
133850x0146: 2, /* SMALL */
133860x0147: 2, /* QUARTILE */
133870x0148: 2, /* PERCENTILE */
133880x014B: 2, /* TRIMMEAN */
133890x014C: 2, /* TINV */
133900x0151: 2, /* POWER */
133910x0156: 1, /* RADIANS */
133920x0157: 1, /* DEGREES */
133930x015A: 2, /* COUNTIF */
133940x015B: 1, /* COUNTBLANK */
133950x015E: 4, /* ISPMT */
133960x015F: 3, /* DATEDIF */
133970x0160: 1, /* DATESTRING */
133980x0161: 2, /* NUMBERSTRING */
133990x0168: 1, /* PHONETIC */
134000x0170: 1, /* BAHTTEXT */
134010x0171: 1, /* THAIDAYOFWEEK */
134020x0172: 1, /* THAIDIGIT */
134030x0173: 1, /* THAIMONTHOFYEAR */
134040x0174: 1, /* THAINUMSOUND */
134050x0175: 1, /* THAINUMSTRING */
134060x0176: 1, /* THAISTRINGLENGTH */
134070x0177: 1, /* ISTHAIDIGIT */
134080x0178: 1, /* ROUNDBAHTDOWN */
134090x0179: 1, /* ROUNDBAHTUP */
134100x017A: 1, /* THAIYEAR */
134110x017E: 3, /* CUBEMEMBERPROPERTY */
134120x0181: 1, /* HEX2DEC */
134130x0188: 1, /* OCT2DEC */
134140x0189: 1, /* BIN2DEC */
134150x018C: 2, /* IMSUB */
134160x018D: 2, /* IMDIV */
134170x018E: 2, /* IMPOWER */
134180x018F: 1, /* IMABS */
134190x0190: 1, /* IMSQRT */
134200x0191: 1, /* IMLN */
134210x0192: 1, /* IMLOG2 */
134220x0193: 1, /* IMLOG10 */
134230x0194: 1, /* IMSIN */
134240x0195: 1, /* IMCOS */
134250x0196: 1, /* IMEXP */
134260x0197: 1, /* IMARGUMENT */
134270x0198: 1, /* IMCONJUGATE */
134280x0199: 1, /* IMAGINARY */
134290x019A: 1, /* IMREAL */
134300x019E: 4, /* SERIESSUM */
134310x019F: 1, /* FACTDOUBLE */
134320x01A0: 1, /* SQRTPI */
134330x01A1: 2, /* QUOTIENT */
134340x01A4: 1, /* ISEVEN */
134350x01A5: 1, /* ISODD */
134360x01A6: 2, /* MROUND */
134370x01A8: 1, /* ERFC */
134380x01A9: 2, /* BESSELJ */
134390x01AA: 2, /* BESSELK */
134400x01AB: 2, /* BESSELY */
134410x01AC: 2, /* BESSELI */
134420x01AE: 3, /* XNPV */
134430x01B6: 3, /* TBILLEQ */
134440x01B7: 3, /* TBILLPRICE */
134450x01B8: 3, /* TBILLYIELD */
134460x01BB: 2, /* DOLLARDE */
134470x01BC: 2, /* DOLLARFR */
134480x01BD: 2, /* NOMINAL */
134490x01BE: 2, /* EFFECT */
134500x01BF: 6, /* CUMPRINC */
134510x01C0: 6, /* CUMIPMT */
134520x01C1: 2, /* EDATE */
134530x01C2: 2, /* EOMONTH */
134540x01D0: 2, /* RANDBETWEEN */
134550x01D4: 3, /* CONVERT */
134560x01DC: 2, /* FVSCHEDULE */
134570x01DF: 1, /* CUBESETCOUNT */
134580x01E0: 2, /* IFERROR */
134590xFFFF: 0
13460};
13461/* [MS-XLSX] 2.2.3 Functions */
13462/* [MS-XLSB] 2.5.97.10 Ftab */
13463var XLSXFutureFunctions = {
13464 "_xlfn.ACOT": "ACOT",
13465 "_xlfn.ACOTH": "ACOTH",
13466 "_xlfn.AGGREGATE": "AGGREGATE",
13467 "_xlfn.ARABIC": "ARABIC",
13468 "_xlfn.AVERAGEIF": "AVERAGEIF",
13469 "_xlfn.AVERAGEIFS": "AVERAGEIFS",
13470 "_xlfn.BASE": "BASE",
13471 "_xlfn.BETA.DIST": "BETA.DIST",
13472 "_xlfn.BETA.INV": "BETA.INV",
13473 "_xlfn.BINOM.DIST": "BINOM.DIST",
13474 "_xlfn.BINOM.DIST.RANGE": "BINOM.DIST.RANGE",
13475 "_xlfn.BINOM.INV": "BINOM.INV",
13476 "_xlfn.BITAND": "BITAND",
13477 "_xlfn.BITLSHIFT": "BITLSHIFT",
13478 "_xlfn.BITOR": "BITOR",
13479 "_xlfn.BITRSHIFT": "BITRSHIFT",
13480 "_xlfn.BITXOR": "BITXOR",
13481 "_xlfn.CEILING.MATH": "CEILING.MATH",
13482 "_xlfn.CEILING.PRECISE": "CEILING.PRECISE",
13483 "_xlfn.CHISQ.DIST": "CHISQ.DIST",
13484 "_xlfn.CHISQ.DIST.RT": "CHISQ.DIST.RT",
13485 "_xlfn.CHISQ.INV": "CHISQ.INV",
13486 "_xlfn.CHISQ.INV.RT": "CHISQ.INV.RT",
13487 "_xlfn.CHISQ.TEST": "CHISQ.TEST",
13488 "_xlfn.COMBINA": "COMBINA",
13489 "_xlfn.CONCAT": "CONCAT",
13490 "_xlfn.CONFIDENCE.NORM": "CONFIDENCE.NORM",
13491 "_xlfn.CONFIDENCE.T": "CONFIDENCE.T",
13492 "_xlfn.COT": "COT",
13493 "_xlfn.COTH": "COTH",
13494 "_xlfn.COUNTIFS": "COUNTIFS",
13495 "_xlfn.COVARIANCE.P": "COVARIANCE.P",
13496 "_xlfn.COVARIANCE.S": "COVARIANCE.S",
13497 "_xlfn.CSC": "CSC",
13498 "_xlfn.CSCH": "CSCH",
13499 "_xlfn.DAYS": "DAYS",
13500 "_xlfn.DECIMAL": "DECIMAL",
13501 "_xlfn.ECMA.CEILING": "ECMA.CEILING",
13502 "_xlfn.ERF.PRECISE": "ERF.PRECISE",
13503 "_xlfn.ERFC.PRECISE": "ERFC.PRECISE",
13504 "_xlfn.EXPON.DIST": "EXPON.DIST",
13505 "_xlfn.F.DIST": "F.DIST",
13506 "_xlfn.F.DIST.RT": "F.DIST.RT",
13507 "_xlfn.F.INV": "F.INV",
13508 "_xlfn.F.INV.RT": "F.INV.RT",
13509 "_xlfn.F.TEST": "F.TEST",
13510 "_xlfn.FILTERXML": "FILTERXML",
13511 "_xlfn.FLOOR.MATH": "FLOOR.MATH",
13512 "_xlfn.FLOOR.PRECISE": "FLOOR.PRECISE",
13513 "_xlfn.FORECAST.ETS": "FORECAST.ETS",
13514 "_xlfn.FORECAST.ETS.CONFINT": "FORECAST.ETS.CONFINT",
13515 "_xlfn.FORECAST.ETS.SEASONALITY": "FORECAST.ETS.SEASONALITY",
13516 "_xlfn.FORECAST.ETS.STAT": "FORECAST.ETS.STAT",
13517 "_xlfn.FORECAST.LINEAR": "FORECAST.LINEAR",
13518 "_xlfn.FORMULATEXT": "FORMULATEXT",
13519 "_xlfn.GAMMA": "GAMMA",
13520 "_xlfn.GAMMA.DIST": "GAMMA.DIST",
13521 "_xlfn.GAMMA.INV": "GAMMA.INV",
13522 "_xlfn.GAMMALN.PRECISE": "GAMMALN.PRECISE",
13523 "_xlfn.GAUSS": "GAUSS",
13524 "_xlfn.HYPGEOM.DIST": "HYPGEOM.DIST",
13525 "_xlfn.IFERROR": "IFERROR",
13526 "_xlfn.IFNA": "IFNA",
13527 "_xlfn.IFS": "IFS",
13528 "_xlfn.IMCOSH": "IMCOSH",
13529 "_xlfn.IMCOT": "IMCOT",
13530 "_xlfn.IMCSC": "IMCSC",
13531 "_xlfn.IMCSCH": "IMCSCH",
13532 "_xlfn.IMSEC": "IMSEC",
13533 "_xlfn.IMSECH": "IMSECH",
13534 "_xlfn.IMSINH": "IMSINH",
13535 "_xlfn.IMTAN": "IMTAN",
13536 "_xlfn.ISFORMULA": "ISFORMULA",
13537 "_xlfn.ISO.CEILING": "ISO.CEILING",
13538 "_xlfn.ISOWEEKNUM": "ISOWEEKNUM",
13539 "_xlfn.LOGNORM.DIST": "LOGNORM.DIST",
13540 "_xlfn.LOGNORM.INV": "LOGNORM.INV",
13541 "_xlfn.MAXIFS": "MAXIFS",
13542 "_xlfn.MINIFS": "MINIFS",
13543 "_xlfn.MODE.MULT": "MODE.MULT",
13544 "_xlfn.MODE.SNGL": "MODE.SNGL",
13545 "_xlfn.MUNIT": "MUNIT",
13546 "_xlfn.NEGBINOM.DIST": "NEGBINOM.DIST",
13547 "_xlfn.NETWORKDAYS.INTL": "NETWORKDAYS.INTL",
13548 "_xlfn.NIGBINOM": "NIGBINOM",
13549 "_xlfn.NORM.DIST": "NORM.DIST",
13550 "_xlfn.NORM.INV": "NORM.INV",
13551 "_xlfn.NORM.S.DIST": "NORM.S.DIST",
13552 "_xlfn.NORM.S.INV": "NORM.S.INV",
13553 "_xlfn.NUMBERVALUE": "NUMBERVALUE",
13554 "_xlfn.PDURATION": "PDURATION",
13555 "_xlfn.PERCENTILE.EXC": "PERCENTILE.EXC",
13556 "_xlfn.PERCENTILE.INC": "PERCENTILE.INC",
13557 "_xlfn.PERCENTRANK.EXC": "PERCENTRANK.EXC",
13558 "_xlfn.PERCENTRANK.INC": "PERCENTRANK.INC",
13559 "_xlfn.PERMUTATIONA": "PERMUTATIONA",
13560 "_xlfn.PHI": "PHI",
13561 "_xlfn.POISSON.DIST": "POISSON.DIST",
13562 "_xlfn.QUARTILE.EXC": "QUARTILE.EXC",
13563 "_xlfn.QUARTILE.INC": "QUARTILE.INC",
13564 "_xlfn.QUERYSTRING": "QUERYSTRING",
13565 "_xlfn.RANK.AVG": "RANK.AVG",
13566 "_xlfn.RANK.EQ": "RANK.EQ",
13567 "_xlfn.RRI": "RRI",
13568 "_xlfn.SEC": "SEC",
13569 "_xlfn.SECH": "SECH",
13570 "_xlfn.SHEET": "SHEET",
13571 "_xlfn.SHEETS": "SHEETS",
13572 "_xlfn.SKEW.P": "SKEW.P",
13573 "_xlfn.STDEV.P": "STDEV.P",
13574 "_xlfn.STDEV.S": "STDEV.S",
13575 "_xlfn.SUMIFS": "SUMIFS",
13576 "_xlfn.SWITCH": "SWITCH",
13577 "_xlfn.T.DIST": "T.DIST",
13578 "_xlfn.T.DIST.2T": "T.DIST.2T",
13579 "_xlfn.T.DIST.RT": "T.DIST.RT",
13580 "_xlfn.T.INV": "T.INV",
13581 "_xlfn.T.INV.2T": "T.INV.2T",
13582 "_xlfn.T.TEST": "T.TEST",
13583 "_xlfn.TEXTJOIN": "TEXTJOIN",
13584 "_xlfn.UNICHAR": "UNICHAR",
13585 "_xlfn.UNICODE": "UNICODE",
13586 "_xlfn.VAR.P": "VAR.P",
13587 "_xlfn.VAR.S": "VAR.S",
13588 "_xlfn.WEBSERVICE": "WEBSERVICE",
13589 "_xlfn.WEIBULL.DIST": "WEIBULL.DIST",
13590 "_xlfn.WORKDAY.INTL": "WORKDAY.INTL",
13591 "_xlfn.XOR": "XOR",
13592 "_xlfn.Z.TEST": "Z.TEST"
13593};
13594
13595/* Part 3 TODO: actually parse formulae */
13596function ods_to_csf_formula(f) {
13597 if(f.slice(0,3) == "of:") f = f.slice(3);
13598 /* 5.2 Basic Expressions */
13599 if(f.charCodeAt(0) == 61) {
13600 f = f.slice(1);
13601 if(f.charCodeAt(0) == 61) f = f.slice(1);
13602 }
13603 f = f.replace(/COM\.MICROSOFT\./g, "");
13604 /* Part 3 Section 5.8 References */
13605 f = f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, function($$, $1) { return $1.replace(/\./g,""); });
13606 /* TODO: something other than this */
13607 f = f.replace(/\[.(#[A-Z]*[?!])\]/g, "$1");
13608 return f.replace(/[;~]/g,",").replace(/\|/g,";");
13609}
13610
13611function csf_to_ods_formula(f) {
13612 var o = "of:=" + f.replace(crefregex, "$1[.$2$3$4$5]").replace(/\]:\[/g,":");
13613 /* TODO: something other than this */
13614 return o.replace(/;/g, "|").replace(/,/g,";");
13615}
13616
13617function ods_to_csf_3D(r) {
13618 var a = r.split(":");
13619 var s = a[0].split(".")[0];
13620 return [s, a[0].split(".")[1] + (a.length > 1 ? (":" + (a[1].split(".")[1] || a[1].split(".")[0])) : "")];
13621}
13622
13623function csf_to_ods_3D(r) {
13624 return r.replace(/\./,"!");
13625}
13626
13627var strs = {}; // shared strings
13628var _ssfopts = {}; // spreadsheet formatting options
13629
13630RELS.WS = [
13631 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
13632 "http://purl.oclc.org/ooxml/officeDocument/relationships/worksheet"
13633];
13634
13635/*global Map */
13636var browser_has_Map = typeof Map !== 'undefined';
13637
13638function get_sst_id(sst, str, rev) {
13639 var i = 0, len = sst.length;
13640 if(rev) {
13641 if(browser_has_Map ? rev.has(str) : Object.prototype.hasOwnProperty.call(rev, str)) {
13642 var revarr = browser_has_Map ? rev.get(str) : rev[str];
13643 for(; i < revarr.length; ++i) {
13644 if(sst[revarr[i]].t === str) { sst.Count ++; return revarr[i]; }
13645 }
13646 }
13647 } else for(; i < len; ++i) {
13648 if(sst[i].t === str) { sst.Count ++; return i; }
13649 }
13650 sst[len] = ({t:str}); sst.Count ++; sst.Unique ++;
13651 if(rev) {
13652 if(browser_has_Map) {
13653 if(!rev.has(str)) rev.set(str, []);
13654 rev.get(str).push(len);
13655 } else {
13656 if(!Object.prototype.hasOwnProperty.call(rev, str)) rev[str] = [];
13657 rev[str].push(len);
13658 }
13659 }
13660 return len;
13661}
13662
13663function col_obj_w(C, col) {
13664 var p = ({min:C+1,max:C+1});
13665 /* wch (chars), wpx (pixels) */
13666 var wch = -1;
13667 if(col.MDW) MDW = col.MDW;
13668 if(col.width != null) p.customWidth = 1;
13669 else if(col.wpx != null) wch = px2char(col.wpx);
13670 else if(col.wch != null) wch = col.wch;
13671 if(wch > -1) { p.width = char2width(wch); p.customWidth = 1; }
13672 else if(col.width != null) p.width = col.width;
13673 if(col.hidden) p.hidden = true;
13674 if(col.level != null) { p.outlineLevel = p.level = col.level; }
13675 return p;
13676}
13677
13678function default_margins(margins, mode) {
13679 if(!margins) return;
13680 var defs = [0.7, 0.7, 0.75, 0.75, 0.3, 0.3];
13681 if(mode == 'xlml') defs = [1, 1, 1, 1, 0.5, 0.5];
13682 if(margins.left == null) margins.left = defs[0];
13683 if(margins.right == null) margins.right = defs[1];
13684 if(margins.top == null) margins.top = defs[2];
13685 if(margins.bottom == null) margins.bottom = defs[3];
13686 if(margins.header == null) margins.header = defs[4];
13687 if(margins.footer == null) margins.footer = defs[5];
13688}
13689
13690function get_cell_style(styles, cell, opts) {
13691 var z = opts.revssf[cell.z != null ? cell.z : "General"];
13692 var i = 0x3c, len = styles.length;
13693 if(z == null && opts.ssf) {
13694 for(; i < 0x188; ++i) if(opts.ssf[i] == null) {
13695 SSF.load(cell.z, i);
13696 // $FlowIgnore
13697 opts.ssf[i] = cell.z;
13698 opts.revssf[cell.z] = z = i;
13699 break;
13700 }
13701 }
13702 for(i = 0; i != len; ++i) if(styles[i].numFmtId === z) return i;
13703 styles[len] = {
13704 numFmtId:z,
13705 fontId:0,
13706 fillId:0,
13707 borderId:0,
13708 xfId:0,
13709 applyNumberFormat:1
13710 };
13711 return len;
13712}
13713
13714function safe_format(p, fmtid, fillid, opts, themes, styles) {
13715 try {
13716 if(opts.cellNF) p.z = SSF._table[fmtid];
13717 } catch(e) { if(opts.WTF) throw e; }
13718 if(p.t === 'z' && !opts.cellStyles) return;
13719 if(p.t === 'd' && typeof p.v === 'string') p.v = parseDate(p.v);
13720 if((!opts || opts.cellText !== false) && p.t !== 'z') try {
13721 if(SSF._table[fmtid] == null) SSF.load(SSFImplicit[fmtid] || "General", fmtid);
13722 if(p.t === 'e') p.w = p.w || BErr[p.v];
13723 else if(fmtid === 0) {
13724 if(p.t === 'n') {
13725 if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
13726 else p.w = SSF._general_num(p.v);
13727 }
13728 else if(p.t === 'd') {
13729 var dd = datenum(p.v);
13730 if((dd|0) === dd) p.w = SSF._general_int(dd);
13731 else p.w = SSF._general_num(dd);
13732 }
13733 else if(p.v === undefined) return "";
13734 else p.w = SSF._general(p.v,_ssfopts);
13735 }
13736 else if(p.t === 'd') p.w = SSF.format(fmtid,datenum(p.v),_ssfopts);
13737 else p.w = SSF.format(fmtid,p.v,_ssfopts);
13738 } catch(e) { if(opts.WTF) throw e; }
13739 if(!opts.cellStyles) return;
13740 if(fillid != null) try {
13741 p.s = styles.Fills[fillid];
13742 if (p.s.fgColor && p.s.fgColor.theme && !p.s.fgColor.rgb) {
13743 p.s.fgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.fgColor.theme].rgb, p.s.fgColor.tint || 0);
13744 if(opts.WTF) p.s.fgColor.raw_rgb = themes.themeElements.clrScheme[p.s.fgColor.theme].rgb;
13745 }
13746 if (p.s.bgColor && p.s.bgColor.theme) {
13747 p.s.bgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.bgColor.theme].rgb, p.s.bgColor.tint || 0);
13748 if(opts.WTF) p.s.bgColor.raw_rgb = themes.themeElements.clrScheme[p.s.bgColor.theme].rgb;
13749 }
13750 } catch(e) { if(opts.WTF && styles.Fills) throw e; }
13751}
13752
13753function check_ws(ws, sname, i) {
13754 if(ws && ws['!ref']) {
13755 var range = safe_decode_range(ws['!ref']);
13756 if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
13757 }
13758}
13759function parse_ws_xml_dim(ws, s) {
13760 var d = safe_decode_range(s);
13761 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);
13762}
13763var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*[\/]?>/g;
13764var sheetdataregex = /<(?:\w+:)?sheetData[^>]*>([\s\S]*)<\/(?:\w+:)?sheetData>/;
13765var hlinkregex = /<(?:\w:)?hyperlink [^>]*>/mg;
13766var dimregex = /"(\w*:\w*)"/;
13767var colregex = /<(?:\w:)?col\b[^>]*[\/]?>/g;
13768var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
13769var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g;
13770var sheetprregex = /<(?:\w:)?sheetPr\b(?:[^>a-z][^>]*)?\/>/;
13771var sheetprregex2= /<(?:\w:)?sheetPr[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetPr)>/;
13772var svsregex = /<(?:\w:)?sheetViews[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetViews)>/;
13773
13774/* 18.3 Worksheets */
13775function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) {
13776 if(!data) return data;
13777 if(!rels) rels = {'!id':{}};
13778 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
13779
13780 /* 18.3.1.99 worksheet CT_Worksheet */
13781 var s = opts.dense ? ([]) : ({});
13782 var refguess = ({s: {r:2000000, c:2000000}, e: {r:0, c:0} });
13783
13784 var data1 = "", data2 = "";
13785 var mtch = data.match(sheetdataregex);
13786 if(mtch) {
13787 data1 = data.slice(0, mtch.index);
13788 data2 = data.slice(mtch.index + mtch[0].length);
13789 } else data1 = data2 = data;
13790
13791 /* 18.3.1.82 sheetPr CT_SheetPr */
13792 var sheetPr = data1.match(sheetprregex);
13793 if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
13794 else if((sheetPr = data1.match(sheetprregex2))) parse_ws_xml_sheetpr2(sheetPr[0], sheetPr[1]||"", s, wb, idx, styles, themes);
13795
13796 /* 18.3.1.35 dimension CT_SheetDimension */
13797 var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
13798 if(ridx > 0) {
13799 var ref = data1.slice(ridx,ridx+50).match(dimregex);
13800 if(ref) parse_ws_xml_dim(s, ref[1]);
13801 }
13802
13803 /* 18.3.1.88 sheetViews CT_SheetViews */
13804 var svs = data1.match(svsregex);
13805 if(svs && svs[1]) parse_ws_xml_sheetviews(svs[1], wb);
13806
13807 /* 18.3.1.17 cols CT_Cols */
13808 var columns = [];
13809 if(opts.cellStyles) {
13810 /* 18.3.1.13 col CT_Col */
13811 var cols = data1.match(colregex);
13812 if(cols) parse_ws_xml_cols(columns, cols);
13813 }
13814
13815 /* 18.3.1.80 sheetData CT_SheetData ? */
13816 if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
13817
13818 /* 18.3.1.2 autoFilter CT_AutoFilter */
13819 var afilter = data2.match(afregex);
13820 if(afilter) s['!autofilter'] = parse_ws_xml_autofilter(afilter[0]);
13821
13822 /* 18.3.1.55 mergeCells CT_MergeCells */
13823 var merges = [];
13824 var _merge = data2.match(mergecregex);
13825 if(_merge) for(ridx = 0; ridx != _merge.length; ++ridx)
13826 merges[ridx] = safe_decode_range(_merge[ridx].slice(_merge[ridx].indexOf("\"")+1));
13827
13828 /* 18.3.1.48 hyperlinks CT_Hyperlinks */
13829 var hlink = data2.match(hlinkregex);
13830 if(hlink) parse_ws_xml_hlinks(s, hlink, rels);
13831
13832 /* 18.3.1.62 pageMargins CT_PageMargins */
13833 var margins = data2.match(marginregex);
13834 if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));
13835
13836 if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
13837 if(opts.sheetRows > 0 && s["!ref"]) {
13838 var tmpref = safe_decode_range(s["!ref"]);
13839 if(opts.sheetRows <= +tmpref.e.r) {
13840 tmpref.e.r = opts.sheetRows - 1;
13841 if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
13842 if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
13843 if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c;
13844 if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c;
13845 s["!fullref"] = s["!ref"];
13846 s["!ref"] = encode_range(tmpref);
13847 }
13848 }
13849 if(columns.length > 0) s["!cols"] = columns;
13850 if(merges.length > 0) s["!merges"] = merges;
13851 return s;
13852}
13853
13854function write_ws_xml_merges(merges) {
13855 if(merges.length === 0) return "";
13856 var o = '<mergeCells count="' + merges.length + '">';
13857 for(var i = 0; i != merges.length; ++i) o += '<mergeCell ref="' + encode_range(merges[i]) + '"/>';
13858 return o + '</mergeCells>';
13859}
13860
13861/* 18.3.1.82-3 sheetPr CT_ChartsheetPr / CT_SheetPr */
13862function parse_ws_xml_sheetpr(sheetPr, s, wb, idx) {
13863 var data = parsexmltag(sheetPr);
13864 if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
13865 if(data.codeName) wb.Sheets[idx].CodeName = unescapexml(utf8read(data.codeName));
13866}
13867function parse_ws_xml_sheetpr2(sheetPr, body, s, wb, idx, styles, themes) {
13868 parse_ws_xml_sheetpr(sheetPr.slice(0, sheetPr.indexOf(">")), s, wb, idx);
13869}
13870function write_ws_xml_sheetpr(ws, wb, idx, opts, o) {
13871 var needed = false;
13872 var props = {}, payload = null;
13873 if(opts.bookType !== 'xlsx' && wb.vbaraw) {
13874 var cname = wb.SheetNames[idx];
13875 try { if(wb.Workbook) cname = wb.Workbook.Sheets[idx].CodeName || cname; } catch(e) {}
13876 needed = true;
13877 props.codeName = utf8write(escapexml(cname));
13878 }
13879
13880 if(ws && ws["!outline"]) {
13881 var outlineprops = {summaryBelow:1, summaryRight:1};
13882 if(ws["!outline"].above) outlineprops.summaryBelow = 0;
13883 if(ws["!outline"].left) outlineprops.summaryRight = 0;
13884 payload = (payload||"") + writextag('outlinePr', null, outlineprops);
13885 }
13886
13887 if(!needed && !payload) return;
13888 o[o.length] = (writextag('sheetPr', payload, props));
13889}
13890
13891/* 18.3.1.85 sheetProtection CT_SheetProtection */
13892var sheetprot_deffalse = ["objects", "scenarios", "selectLockedCells", "selectUnlockedCells"];
13893var sheetprot_deftrue = [
13894 "formatColumns", "formatRows", "formatCells",
13895 "insertColumns", "insertRows", "insertHyperlinks",
13896 "deleteColumns", "deleteRows",
13897 "sort", "autoFilter", "pivotTables"
13898];
13899function write_ws_xml_protection(sp) {
13900 // algorithmName, hashValue, saltValue, spinCount
13901 var o = ({sheet:1});
13902 sheetprot_deffalse.forEach(function(n) { if(sp[n] != null && sp[n]) o[n] = "1"; });
13903 sheetprot_deftrue.forEach(function(n) { if(sp[n] != null && !sp[n]) o[n] = "0"; });
13904 /* TODO: algorithm */
13905 if(sp.password) o.password = crypto_CreatePasswordVerifier_Method1(sp.password).toString(16).toUpperCase();
13906 return writextag('sheetProtection', null, o);
13907}
13908
13909function parse_ws_xml_hlinks(s, data, rels) {
13910 var dense = Array.isArray(s);
13911 for(var i = 0; i != data.length; ++i) {
13912 var val = parsexmltag(utf8read(data[i]), true);
13913 if(!val.ref) return;
13914 var rel = ((rels || {})['!id']||[])[val.id];
13915 if(rel) {
13916 val.Target = rel.Target;
13917 if(val.location) val.Target += "#"+unescapexml(val.location);
13918 } else {
13919 val.Target = "#" + unescapexml(val.location);
13920 rel = {Target: val.Target, TargetMode: 'Internal'};
13921 }
13922 val.Rel = rel;
13923 if(val.tooltip) { val.Tooltip = val.tooltip; delete val.tooltip; }
13924 var rng = safe_decode_range(val.ref);
13925 for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
13926 var addr = encode_cell({c:C,r:R});
13927 if(dense) {
13928 if(!s[R]) s[R] = [];
13929 if(!s[R][C]) s[R][C] = {t:"z",v:undefined};
13930 s[R][C].l = val;
13931 } else {
13932 if(!s[addr]) s[addr] = {t:"z",v:undefined};
13933 s[addr].l = val;
13934 }
13935 }
13936 }
13937}
13938
13939function parse_ws_xml_margins(margin) {
13940 var o = {};
13941 ["left", "right", "top", "bottom", "header", "footer"].forEach(function(k) {
13942 if(margin[k]) o[k] = parseFloat(margin[k]);
13943 });
13944 return o;
13945}
13946function write_ws_xml_margins(margin) {
13947 default_margins(margin);
13948 return writextag('pageMargins', null, margin);
13949}
13950
13951function parse_ws_xml_cols(columns, cols) {
13952 var seencol = false;
13953 for(var coli = 0; coli != cols.length; ++coli) {
13954 var coll = parsexmltag(cols[coli], true);
13955 if(coll.hidden) coll.hidden = parsexmlbool(coll.hidden);
13956 var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
13957 if(coll.outlineLevel) coll.level = (+coll.outlineLevel || 0);
13958 delete coll.min; delete coll.max; coll.width = +coll.width;
13959 if(!seencol && coll.width) { seencol = true; find_mdw_colw(coll.width); }
13960 process_col(coll);
13961 while(colm <= colM) columns[colm++] = dup(coll);
13962 }
13963}
13964function write_ws_xml_cols(ws, cols) {
13965 var o = ["<cols>"], col;
13966 for(var i = 0; i != cols.length; ++i) {
13967 if(!(col = cols[i])) continue;
13968 o[o.length] = (writextag('col', null, col_obj_w(i, col)));
13969 }
13970 o[o.length] = "</cols>";
13971 return o.join("");
13972}
13973
13974function parse_ws_xml_autofilter(data) {
13975 var o = { ref: (data.match(/ref="([^"]*)"/)||[])[1]};
13976 return o;
13977}
13978function write_ws_xml_autofilter(data, ws, wb, idx) {
13979 var ref = typeof data.ref == "string" ? data.ref : encode_range(data.ref);
13980 if(!wb.Workbook) wb.Workbook = ({Sheets:[]});
13981 if(!wb.Workbook.Names) wb.Workbook.Names = [];
13982 var names = wb.Workbook.Names;
13983 var range = decode_range(ref);
13984 if(range.s.r == range.e.r) { range.e.r = decode_range(ws["!ref"]).e.r; ref = encode_range(range); }
13985 for(var i = 0; i < names.length; ++i) {
13986 var name = names[i];
13987 if(name.Name != '_xlnm._FilterDatabase') continue;
13988 if(name.Sheet != idx) continue;
13989 name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break;
13990 }
13991 if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref });
13992 return writextag("autoFilter", null, {ref:ref});
13993}
13994
13995/* 18.3.1.88 sheetViews CT_SheetViews */
13996/* 18.3.1.87 sheetView CT_SheetView */
13997var sviewregex = /<(?:\w:)?sheetView(?:[^>a-z][^>]*)?\/?>/;
13998function parse_ws_xml_sheetviews(data, wb) {
13999 if(!wb.Views) wb.Views = [{}];
14000 (data.match(sviewregex)||[]).forEach(function(r, i) {
14001 var tag = parsexmltag(r);
14002 // $FlowIgnore
14003 if(!wb.Views[i]) wb.Views[i] = {};
14004 // $FlowIgnore
14005 if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
14006 // $FlowIgnore
14007 if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
14008 });
14009}
14010function write_ws_xml_sheetviews(ws, opts, idx, wb) {
14011 var sview = ({workbookViewId:"0"});
14012 // $FlowIgnore
14013 if((((wb||{}).Workbook||{}).Views||[])[0]) sview.rightToLeft = wb.Workbook.Views[0].RTL ? "1" : "0";
14014 return writextag("sheetViews", writextag("sheetView", null, sview), {});
14015}
14016
14017function write_ws_xml_cell(cell, ref, ws, opts) {
14018 if(cell.v === undefined && typeof cell.f !== "string" || cell.t === 'z') return "";
14019 var vv = "";
14020 var oldt = cell.t, oldv = cell.v;
14021 if(cell.t !== "z") switch(cell.t) {
14022 case 'b': vv = cell.v ? "1" : "0"; break;
14023 case 'n': vv = ''+cell.v; break;
14024 case 'e': vv = BErr[cell.v]; break;
14025 case 'd':
14026 if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
14027 else {
14028 cell = dup(cell);
14029 cell.t = 'n';
14030 vv = ''+(cell.v = datenum(parseDate(cell.v)));
14031 }
14032 if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
14033 break;
14034 default: vv = cell.v; break;
14035 }
14036 var v = writetag('v', escapexml(vv)), o = ({r:ref});
14037 /* TODO: cell style */
14038 var os = get_cell_style(opts.cellXfs, cell, opts);
14039 if(os !== 0) o.s = os;
14040 switch(cell.t) {
14041 case 'n': break;
14042 case 'd': o.t = "d"; break;
14043 case 'b': o.t = "b"; break;
14044 case 'e': o.t = "e"; break;
14045 case 'z': break;
14046 default: if(cell.v == null) { delete cell.t; break; }
14047 if(cell.v.length > 32767) throw new Error("Text length must not exceed 32767 characters");
14048 if(opts && opts.bookSST) {
14049 v = writetag('v', ''+get_sst_id(opts.Strings, cell.v, opts.revStrings));
14050 o.t = "s"; break;
14051 }
14052 o.t = "str"; break;
14053 }
14054 if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; }
14055 if(typeof cell.f == "string" && cell.f) {
14056 var ff = cell.F && cell.F.slice(0, ref.length) == ref ? {t:"array", ref:cell.F} : null;
14057 v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : "");
14058 }
14059 if(cell.l) ws['!links'].push([ref, cell.l]);
14060 if(cell.c) ws['!comments'].push([ref, cell.c]);
14061 return writextag('c', v, o);
14062}
14063
14064var parse_ws_xml_data = (function() {
14065 var cellregex = /<(?:\w+:)?c[ \/>]/, rowregex = /<\/(?:\w+:)?row>/;
14066 var rregex = /r=["']([^"']*)["']/, isregex = /<(?:\w+:)?is>([\S\s]*?)<\/(?:\w+:)?is>/;
14067 var refregex = /ref=["']([^"']*)["']/;
14068 var match_v = matchtag("v"), match_f = matchtag("f");
14069
14070return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
14071 var ri = 0, x = "", cells = [], cref = [], idx=0, i=0, cc=0, d="", p;
14072 var tag, tagr = 0, tagc = 0;
14073 var sstr, ftag;
14074 var fmtid = 0, fillid = 0;
14075 var do_format = Array.isArray(styles.CellXf), cf;
14076 var arrayf = [];
14077 var sharedf = [];
14078 var dense = Array.isArray(s);
14079 var rows = [], rowobj = {}, rowrite = false;
14080 var sheetStubs = !!opts.sheetStubs;
14081 for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
14082 x = marr[mt].trim();
14083 var xlen = x.length;
14084 if(xlen === 0) continue;
14085
14086 /* 18.3.1.73 row CT_Row */
14087 var rstarti = 0;
14088 outa: for(ri = 0; ri < xlen; ++ri) switch(/*x.charCodeAt(ri)*/x[ri]) {
14089 case ">" /*62*/:
14090 if(/*x.charCodeAt(ri-1) != 47*/x[ri-1] != "/") { ++ri; break outa; }
14091 if(opts && opts.cellStyles) {
14092 // TODO: avoid duplication
14093 tag = parsexmltag(x.slice(rstarti,ri), true);
14094 tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
14095 if(opts.sheetRows && opts.sheetRows < tagr) continue;
14096 rowobj = {}; rowrite = false;
14097 if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
14098 if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; }
14099 if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
14100 if(rowrite) rows[tagr-1] = rowobj;
14101 }
14102 break;
14103 case "<" /*60*/: rstarti = ri; break;
14104 }
14105 if(rstarti >= ri) break;
14106 tag = parsexmltag(x.slice(rstarti,ri), true);
14107 tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
14108 if(opts.sheetRows && opts.sheetRows < tagr) continue;
14109 if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
14110 if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
14111
14112 if(opts && opts.cellStyles) {
14113 rowobj = {}; rowrite = false;
14114 if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
14115 if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; }
14116 if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
14117 if(rowrite) rows[tagr-1] = rowobj;
14118 }
14119
14120 /* 18.3.1.4 c CT_Cell */
14121 cells = x.slice(ri).split(cellregex);
14122 for(var rslice = 0; rslice != cells.length; ++rslice) if(cells[rslice].trim().charAt(0) != "<") break;
14123 cells = cells.slice(rslice);
14124 for(ri = 0; ri != cells.length; ++ri) {
14125 x = cells[ri].trim();
14126 if(x.length === 0) continue;
14127 cref = x.match(rregex); idx = ri; i=0; cc=0;
14128 x = "<c " + (x.slice(0,1)=="<"?">":"") + x;
14129 if(cref != null && cref.length === 2) {
14130 idx = 0; d=cref[1];
14131 for(i=0; i != d.length; ++i) {
14132 if((cc=d.charCodeAt(i)-64) < 1 || cc > 26) break;
14133 idx = 26*idx + cc;
14134 }
14135 --idx;
14136 tagc = idx;
14137 } else ++tagc;
14138 for(i = 0; i != x.length; ++i) if(x.charCodeAt(i) === 62) break; ++i;
14139 tag = parsexmltag(x.slice(0,i), true);
14140 if(!tag.r) tag.r = encode_cell({r:tagr-1, c:tagc});
14141 d = x.slice(i);
14142 p = ({t:""});
14143
14144 if((cref=d.match(match_v))!= null && cref[1] !== '') p.v=unescapexml(cref[1]);
14145 if(opts.cellFormula) {
14146 if((cref=d.match(match_f))!= null && cref[1] !== '') {
14147 /* TODO: match against XLSXFutureFunctions */
14148 p.f=unescapexml(utf8read(cref[1])).replace(/\r\n/g, "\n");
14149 if(!opts.xlfn) p.f = _xlfn(p.f);
14150 if(cref[0].indexOf('t="array"') > -1) {
14151 p.F = (d.match(refregex)||[])[1];
14152 if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
14153 } else if(cref[0].indexOf('t="shared"') > -1) {
14154 // TODO: parse formula
14155 ftag = parsexmltag(cref[0]);
14156 var ___f = unescapexml(utf8read(cref[1]));
14157 if(!opts.xlfn) ___f = _xlfn(___f);
14158 sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
14159 }
14160 } else if((cref=d.match(/<f[^>]*\/>/))) {
14161 ftag = parsexmltag(cref[0]);
14162 if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
14163 }
14164 /* TODO: factor out contains logic */
14165 var _tag = decode_cell(tag.r);
14166 for(i = 0; i < arrayf.length; ++i)
14167 if(_tag.r >= arrayf[i][0].s.r && _tag.r <= arrayf[i][0].e.r)
14168 if(_tag.c >= arrayf[i][0].s.c && _tag.c <= arrayf[i][0].e.c)
14169 p.F = arrayf[i][1];
14170 }
14171
14172 if(tag.t == null && p.v === undefined) {
14173 if(p.f || p.F) {
14174 p.v = 0; p.t = "n";
14175 } else if(!sheetStubs) continue;
14176 else p.t = "z";
14177 }
14178 else p.t = tag.t || "n";
14179 if(guess.s.c > tagc) guess.s.c = tagc;
14180 if(guess.e.c < tagc) guess.e.c = tagc;
14181 /* 18.18.11 t ST_CellType */
14182 switch(p.t) {
14183 case 'n':
14184 if(p.v == "" || p.v == null) {
14185 if(!sheetStubs) continue;
14186 p.t = 'z';
14187 } else p.v = parseFloat(p.v);
14188 break;
14189 case 's':
14190 if(typeof p.v == 'undefined') {
14191 if(!sheetStubs) continue;
14192 p.t = 'z';
14193 } else {
14194 sstr = strs[parseInt(p.v, 10)];
14195 p.v = sstr.t;
14196 p.r = sstr.r;
14197 if(opts.cellHTML) p.h = sstr.h;
14198 }
14199 break;
14200 case 'str':
14201 p.t = "s";
14202 p.v = (p.v!=null) ? utf8read(p.v) : '';
14203 if(opts.cellHTML) p.h = escapehtml(p.v);
14204 break;
14205 case 'inlineStr':
14206 cref = d.match(isregex);
14207 p.t = 's';
14208 if(cref != null && (sstr = parse_si(cref[1]))) {
14209 p.v = sstr.t;
14210 if(opts.cellHTML) p.h = sstr.h;
14211 } else p.v = "";
14212 break;
14213 case 'b': p.v = parsexmlbool(p.v); break;
14214 case 'd':
14215 if(opts.cellDates) p.v = parseDate(p.v, 1);
14216 else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; }
14217 break;
14218 /* error string in .w, number in .v */
14219 case 'e':
14220 if(!opts || opts.cellText !== false) p.w = p.v;
14221 p.v = RBErr[p.v]; break;
14222 }
14223 /* formatting */
14224 fmtid = fillid = 0;
14225 cf = null;
14226 if(do_format && tag.s !== undefined) {
14227 cf = styles.CellXf[tag.s];
14228 if(cf != null) {
14229 if(cf.numFmtId != null) fmtid = cf.numFmtId;
14230 if(opts.cellStyles) {
14231 if(cf.fillId != null) fillid = cf.fillId;
14232 }
14233 }
14234 }
14235 safe_format(p, fmtid, fillid, opts, themes, styles);
14236 if(opts.cellDates && do_format && p.t == 'n' && SSF.is_date(SSF._table[fmtid])) { p.t = 'd'; p.v = numdate(p.v); }
14237 if(dense) {
14238 var _r = decode_cell(tag.r);
14239 if(!s[_r.r]) s[_r.r] = [];
14240 s[_r.r][_r.c] = p;
14241 } else s[tag.r] = p;
14242 }
14243 }
14244 if(rows.length > 0) s['!rows'] = rows;
14245}; })();
14246
14247function write_ws_xml_data(ws, opts, idx, wb) {
14248 var o = [], r = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols = [], R=0, C=0, rows = ws['!rows'];
14249 var dense = Array.isArray(ws);
14250 var params = ({r:rr}), row, height = -1;
14251 for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
14252 for(R = range.s.r; R <= range.e.r; ++R) {
14253 r = [];
14254 rr = encode_row(R);
14255 for(C = range.s.c; C <= range.e.c; ++C) {
14256 ref = cols[C] + rr;
14257 var _cell = dense ? (ws[R]||[])[C]: ws[ref];
14258 if(_cell === undefined) continue;
14259 if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
14260 }
14261 if(r.length > 0 || (rows && rows[R])) {
14262 params = ({r:rr});
14263 if(rows && rows[R]) {
14264 row = rows[R];
14265 if(row.hidden) params.hidden = 1;
14266 height = -1;
14267 if(row.hpx) height = px2pt(row.hpx);
14268 else if(row.hpt) height = row.hpt;
14269 if(height > -1) { params.ht = height; params.customHeight = 1; }
14270 if(row.level) { params.outlineLevel = row.level; }
14271 }
14272 o[o.length] = (writextag('row', r.join(""), params));
14273 }
14274 }
14275 if(rows) for(; R < rows.length; ++R) {
14276 if(rows && rows[R]) {
14277 params = ({r:R+1});
14278 row = rows[R];
14279 if(row.hidden) params.hidden = 1;
14280 height = -1;
14281 if (row.hpx) height = px2pt(row.hpx);
14282 else if (row.hpt) height = row.hpt;
14283 if (height > -1) { params.ht = height; params.customHeight = 1; }
14284 if (row.level) { params.outlineLevel = row.level; }
14285 o[o.length] = (writextag('row', "", params));
14286 }
14287 }
14288 return o.join("");
14289}
14290
14291var WS_XML_ROOT = writextag('worksheet', null, {
14292 'xmlns': XMLNS.main[0],
14293 'xmlns:r': XMLNS.r
14294});
14295
14296function write_ws_xml(idx, opts, wb, rels) {
14297 var o = [XML_HEADER, WS_XML_ROOT];
14298 var s = wb.SheetNames[idx], sidx = 0, rdata = "";
14299 var ws = wb.Sheets[s];
14300 if(ws == null) ws = {};
14301 var ref = ws['!ref'] || 'A1';
14302 var range = safe_decode_range(ref);
14303 if(range.e.c > 0x3FFF || range.e.r > 0xFFFFF) {
14304 if(opts.WTF) throw new Error("Range " + ref + " exceeds format limit A1:XFD1048576");
14305 range.e.c = Math.min(range.e.c, 0x3FFF);
14306 range.e.r = Math.min(range.e.c, 0xFFFFF);
14307 ref = encode_range(range);
14308 }
14309 if(!rels) rels = {};
14310 ws['!comments'] = [];
14311 var _drawing = [];
14312
14313 write_ws_xml_sheetpr(ws, wb, idx, opts, o);
14314
14315 o[o.length] = (writextag('dimension', null, {'ref': ref}));
14316
14317 o[o.length] = write_ws_xml_sheetviews(ws, opts, idx, wb);
14318
14319 /* TODO: store in WB, process styles */
14320 if(opts.sheetFormat) o[o.length] = (writextag('sheetFormatPr', null, {
14321 defaultRowHeight:opts.sheetFormat.defaultRowHeight||'16',
14322 baseColWidth:opts.sheetFormat.baseColWidth||'10',
14323 outlineLevelRow:opts.sheetFormat.outlineLevelRow||'7'
14324 }));
14325
14326 if(ws['!cols'] != null && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols']));
14327
14328 o[sidx = o.length] = '<sheetData/>';
14329 ws['!links'] = [];
14330 if(ws['!ref'] != null) {
14331 rdata = write_ws_xml_data(ws, opts, idx, wb, rels);
14332 if(rdata.length > 0) o[o.length] = (rdata);
14333 }
14334 if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
14335
14336 /* sheetCalcPr */
14337
14338 if(ws['!protect']) o[o.length] = write_ws_xml_protection(ws['!protect']);
14339
14340 /* protectedRanges */
14341 /* scenarios */
14342
14343 if(ws['!autofilter'] != null) o[o.length] = write_ws_xml_autofilter(ws['!autofilter'], ws, wb, idx);
14344
14345 /* sortState */
14346 /* dataConsolidate */
14347 /* customSheetViews */
14348
14349 if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
14350
14351 /* phoneticPr */
14352 /* conditionalFormatting */
14353 /* dataValidations */
14354
14355 var relc = -1, rel, rId = -1;
14356 if(ws['!links'].length > 0) {
14357 o[o.length] = "<hyperlinks>";
14358ws['!links'].forEach(function(l) {
14359 if(!l[1].Target) return;
14360 rel = ({"ref":l[0]});
14361 if(l[1].Target.charAt(0) != "#") {
14362 rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), RELS.HLINK);
14363 rel["r:id"] = "rId"+rId;
14364 }
14365 if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1));
14366 if(l[1].Tooltip) rel.tooltip = escapexml(l[1].Tooltip);
14367 o[o.length] = writextag("hyperlink",null,rel);
14368 });
14369 o[o.length] = "</hyperlinks>";
14370 }
14371 delete ws['!links'];
14372
14373 /* printOptions */
14374
14375 if(ws['!margins'] != null) o[o.length] = write_ws_xml_margins(ws['!margins']);
14376
14377 /* pageSetup */
14378 /* headerFooter */
14379 /* rowBreaks */
14380 /* colBreaks */
14381 /* customProperties */
14382 /* cellWatches */
14383
14384 if(!opts || opts.ignoreEC || (opts.ignoreEC == (void 0))) o[o.length] = writetag("ignoredErrors", writextag("ignoredError", null, {numberStoredAsText:1, sqref:ref}));
14385
14386 /* smartTags */
14387
14388 if(_drawing.length > 0) {
14389 rId = add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
14390 o[o.length] = writextag("drawing", null, {"r:id":"rId" + rId});
14391 ws['!drawing'] = _drawing;
14392 }
14393
14394 if(ws['!comments'].length > 0) {
14395 rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML);
14396 o[o.length] = writextag("legacyDrawing", null, {"r:id":"rId" + rId});
14397 ws['!legacy'] = rId;
14398 }
14399
14400 /* legacyDrawingHF */
14401 /* picture */
14402 /* oleObjects */
14403 /* controls */
14404 /* webPublishItems */
14405 /* tableParts */
14406 /* extLst */
14407
14408 if(o.length>1) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
14409 return o.join("");
14410}
14411
14412/* [MS-XLSB] 2.4.726 BrtRowHdr */
14413function parse_BrtRowHdr(data, length) {
14414 var z = ({});
14415 var tgt = data.l + length;
14416 z.r = data.read_shift(4);
14417 data.l += 4; // TODO: ixfe
14418 var miyRw = data.read_shift(2);
14419 data.l += 1; // TODO: top/bot padding
14420 var flags = data.read_shift(1);
14421 data.l = tgt;
14422 if(flags & 0x07) z.level = flags & 0x07;
14423 if(flags & 0x10) z.hidden = true;
14424 if(flags & 0x20) z.hpt = miyRw / 20;
14425 return z;
14426}
14427function write_BrtRowHdr(R, range, ws) {
14428 var o = new_buf(17+8*16);
14429 var row = (ws['!rows']||[])[R]||{};
14430 o.write_shift(4, R);
14431
14432 o.write_shift(4, 0); /* TODO: ixfe */
14433
14434 var miyRw = 0x0140;
14435 if(row.hpx) miyRw = px2pt(row.hpx) * 20;
14436 else if(row.hpt) miyRw = row.hpt * 20;
14437 o.write_shift(2, miyRw);
14438
14439 o.write_shift(1, 0); /* top/bot padding */
14440
14441 var flags = 0x0;
14442 if(row.level) flags |= row.level;
14443 if(row.hidden) flags |= 0x10;
14444 if(row.hpx || row.hpt) flags |= 0x20;
14445 o.write_shift(1, flags);
14446
14447 o.write_shift(1, 0); /* phonetic guide */
14448
14449 /* [MS-XLSB] 2.5.8 BrtColSpan explains the mechanism */
14450 var ncolspan = 0, lcs = o.l;
14451 o.l += 4;
14452
14453 var caddr = {r:R, c:0};
14454 for(var i = 0; i < 16; ++i) {
14455 if((range.s.c > ((i+1) << 10)) || (range.e.c < (i << 10))) continue;
14456 var first = -1, last = -1;
14457 for(var j = (i<<10); j < ((i+1)<<10); ++j) {
14458 caddr.c = j;
14459 var cell = Array.isArray(ws) ? (ws[caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)];
14460 if(cell) { if(first < 0) first = j; last = j; }
14461 }
14462 if(first < 0) continue;
14463 ++ncolspan;
14464 o.write_shift(4, first);
14465 o.write_shift(4, last);
14466 }
14467
14468 var l = o.l;
14469 o.l = lcs;
14470 o.write_shift(4, ncolspan);
14471 o.l = l;
14472
14473 return o.length > o.l ? o.slice(0, o.l) : o;
14474}
14475function write_row_header(ba, ws, range, R) {
14476 var o = write_BrtRowHdr(R, range, ws);
14477 if((o.length > 17) || (ws['!rows']||[])[R]) write_record(ba, 'BrtRowHdr', o);
14478}
14479
14480/* [MS-XLSB] 2.4.820 BrtWsDim */
14481var parse_BrtWsDim = parse_UncheckedRfX;
14482var write_BrtWsDim = write_UncheckedRfX;
14483
14484/* [MS-XLSB] 2.4.821 BrtWsFmtInfo */
14485function parse_BrtWsFmtInfo() {
14486}
14487//function write_BrtWsFmtInfo(ws, o) { }
14488
14489/* [MS-XLSB] 2.4.823 BrtWsProp */
14490function parse_BrtWsProp(data, length) {
14491 var z = {};
14492 var f = data[data.l]; ++data.l;
14493 z.above = !(f & 0x40);
14494 z.left = !(f & 0x80);
14495 /* TODO: pull flags */
14496 data.l += 18;
14497 z.name = parse_XLSBCodeName(data, length - 19);
14498 return z;
14499}
14500function write_BrtWsProp(str, outl, o) {
14501 if(o == null) o = new_buf(84+4*str.length);
14502 var f = 0xC0;
14503 if(outl) {
14504 if(outl.above) f &= ~0x40;
14505 if(outl.left) f &= ~0x80;
14506 }
14507 o.write_shift(1, f);
14508 for(var i = 1; i < 3; ++i) o.write_shift(1,0);
14509 write_BrtColor({auto:1}, o);
14510 o.write_shift(-4,-1);
14511 o.write_shift(-4,-1);
14512 write_XLSBCodeName(str, o);
14513 return o.slice(0, o.l);
14514}
14515
14516/* [MS-XLSB] 2.4.306 BrtCellBlank */
14517function parse_BrtCellBlank(data) {
14518 var cell = parse_XLSBCell(data);
14519 return [cell];
14520}
14521function write_BrtCellBlank(cell, ncell, o) {
14522 if(o == null) o = new_buf(8);
14523 return write_XLSBCell(ncell, o);
14524}
14525function parse_BrtShortBlank(data) {
14526 var cell = parse_XLSBShortCell(data);
14527 return [cell];
14528}
14529function write_BrtShortBlank(cell, ncell, o) {
14530 if(o == null) o = new_buf(4);
14531 return write_XLSBShortCell(ncell, o);
14532}
14533
14534/* [MS-XLSB] 2.4.307 BrtCellBool */
14535function parse_BrtCellBool(data) {
14536 var cell = parse_XLSBCell(data);
14537 var fBool = data.read_shift(1);
14538 return [cell, fBool, 'b'];
14539}
14540function write_BrtCellBool(cell, ncell, o) {
14541 if(o == null) o = new_buf(9);
14542 write_XLSBCell(ncell, o);
14543 o.write_shift(1, cell.v ? 1 : 0);
14544 return o;
14545}
14546function parse_BrtShortBool(data) {
14547 var cell = parse_XLSBShortCell(data);
14548 var fBool = data.read_shift(1);
14549 return [cell, fBool, 'b'];
14550}
14551function write_BrtShortBool(cell, ncell, o) {
14552 if(o == null) o = new_buf(5);
14553 write_XLSBShortCell(ncell, o);
14554 o.write_shift(1, cell.v ? 1 : 0);
14555 return o;
14556}
14557
14558/* [MS-XLSB] 2.4.308 BrtCellError */
14559function parse_BrtCellError(data) {
14560 var cell = parse_XLSBCell(data);
14561 var bError = data.read_shift(1);
14562 return [cell, bError, 'e'];
14563}
14564function write_BrtCellError(cell, ncell, o) {
14565 if(o == null) o = new_buf(9);
14566 write_XLSBCell(ncell, o);
14567 o.write_shift(1, cell.v);
14568 return o;
14569}
14570function parse_BrtShortError(data) {
14571 var cell = parse_XLSBShortCell(data);
14572 var bError = data.read_shift(1);
14573 return [cell, bError, 'e'];
14574}
14575function write_BrtShortError(cell, ncell, o) {
14576 if(o == null) o = new_buf(8);
14577 write_XLSBShortCell(ncell, o);
14578 o.write_shift(1, cell.v);
14579 o.write_shift(2, 0);
14580 o.write_shift(1, 0);
14581 return o;
14582}
14583
14584
14585/* [MS-XLSB] 2.4.311 BrtCellIsst */
14586function parse_BrtCellIsst(data) {
14587 var cell = parse_XLSBCell(data);
14588 var isst = data.read_shift(4);
14589 return [cell, isst, 's'];
14590}
14591function write_BrtCellIsst(cell, ncell, o) {
14592 if(o == null) o = new_buf(12);
14593 write_XLSBCell(ncell, o);
14594 o.write_shift(4, ncell.v);
14595 return o;
14596}
14597function parse_BrtShortIsst(data) {
14598 var cell = parse_XLSBShortCell(data);
14599 var isst = data.read_shift(4);
14600 return [cell, isst, 's'];
14601}
14602function write_BrtShortIsst(cell, ncell, o) {
14603 if(o == null) o = new_buf(8);
14604 write_XLSBShortCell(ncell, o);
14605 o.write_shift(4, ncell.v);
14606 return o;
14607}
14608
14609/* [MS-XLSB] 2.4.313 BrtCellReal */
14610function parse_BrtCellReal(data) {
14611 var cell = parse_XLSBCell(data);
14612 var value = parse_Xnum(data);
14613 return [cell, value, 'n'];
14614}
14615function write_BrtCellReal(cell, ncell, o) {
14616 if(o == null) o = new_buf(16);
14617 write_XLSBCell(ncell, o);
14618 write_Xnum(cell.v, o);
14619 return o;
14620}
14621function parse_BrtShortReal(data) {
14622 var cell = parse_XLSBShortCell(data);
14623 var value = parse_Xnum(data);
14624 return [cell, value, 'n'];
14625}
14626function write_BrtShortReal(cell, ncell, o) {
14627 if(o == null) o = new_buf(12);
14628 write_XLSBShortCell(ncell, o);
14629 write_Xnum(cell.v, o);
14630 return o;
14631}
14632
14633/* [MS-XLSB] 2.4.314 BrtCellRk */
14634function parse_BrtCellRk(data) {
14635 var cell = parse_XLSBCell(data);
14636 var value = parse_RkNumber(data);
14637 return [cell, value, 'n'];
14638}
14639function write_BrtCellRk(cell, ncell, o) {
14640 if(o == null) o = new_buf(12);
14641 write_XLSBCell(ncell, o);
14642 write_RkNumber(cell.v, o);
14643 return o;
14644}
14645function parse_BrtShortRk(data) {
14646 var cell = parse_XLSBShortCell(data);
14647 var value = parse_RkNumber(data);
14648 return [cell, value, 'n'];
14649}
14650function write_BrtShortRk(cell, ncell, o) {
14651 if(o == null) o = new_buf(8);
14652 write_XLSBShortCell(ncell, o);
14653 write_RkNumber(cell.v, o);
14654 return o;
14655}
14656
14657
14658/* [MS-XLSB] 2.4.317 BrtCellSt */
14659function parse_BrtCellSt(data) {
14660 var cell = parse_XLSBCell(data);
14661 var value = parse_XLWideString(data);
14662 return [cell, value, 'str'];
14663}
14664function write_BrtCellSt(cell, ncell, o) {
14665 if(o == null) o = new_buf(12 + 4 * cell.v.length);
14666 write_XLSBCell(ncell, o);
14667 write_XLWideString(cell.v, o);
14668 return o.length > o.l ? o.slice(0, o.l) : o;
14669}
14670function parse_BrtShortSt(data) {
14671 var cell = parse_XLSBShortCell(data);
14672 var value = parse_XLWideString(data);
14673 return [cell, value, 'str'];
14674}
14675function write_BrtShortSt(cell, ncell, o) {
14676 if(o == null) o = new_buf(8 + 4 * cell.v.length);
14677 write_XLSBShortCell(ncell, o);
14678 write_XLWideString(cell.v, o);
14679 return o.length > o.l ? o.slice(0, o.l) : o;
14680}
14681
14682/* [MS-XLSB] 2.4.653 BrtFmlaBool */
14683function parse_BrtFmlaBool(data, length, opts) {
14684 var end = data.l + length;
14685 var cell = parse_XLSBCell(data);
14686 cell.r = opts['!row'];
14687 var value = data.read_shift(1);
14688 var o = [cell, value, 'b'];
14689 if(opts.cellFormula) {
14690 data.l += 2;
14691 var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
14692 o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
14693 }
14694 else data.l = end;
14695 return o;
14696}
14697
14698/* [MS-XLSB] 2.4.654 BrtFmlaError */
14699function parse_BrtFmlaError(data, length, opts) {
14700 var end = data.l + length;
14701 var cell = parse_XLSBCell(data);
14702 cell.r = opts['!row'];
14703 var value = data.read_shift(1);
14704 var o = [cell, value, 'e'];
14705 if(opts.cellFormula) {
14706 data.l += 2;
14707 var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
14708 o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
14709 }
14710 else data.l = end;
14711 return o;
14712}
14713
14714/* [MS-XLSB] 2.4.655 BrtFmlaNum */
14715function parse_BrtFmlaNum(data, length, opts) {
14716 var end = data.l + length;
14717 var cell = parse_XLSBCell(data);
14718 cell.r = opts['!row'];
14719 var value = parse_Xnum(data);
14720 var o = [cell, value, 'n'];
14721 if(opts.cellFormula) {
14722 data.l += 2;
14723 var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
14724 o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
14725 }
14726 else data.l = end;
14727 return o;
14728}
14729
14730/* [MS-XLSB] 2.4.656 BrtFmlaString */
14731function parse_BrtFmlaString(data, length, opts) {
14732 var end = data.l + length;
14733 var cell = parse_XLSBCell(data);
14734 cell.r = opts['!row'];
14735 var value = parse_XLWideString(data);
14736 var o = [cell, value, 'str'];
14737 if(opts.cellFormula) {
14738 data.l += 2;
14739 var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
14740 o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
14741 }
14742 else data.l = end;
14743 return o;
14744}
14745
14746/* [MS-XLSB] 2.4.682 BrtMergeCell */
14747var parse_BrtMergeCell = parse_UncheckedRfX;
14748var write_BrtMergeCell = write_UncheckedRfX;
14749/* [MS-XLSB] 2.4.107 BrtBeginMergeCells */
14750function write_BrtBeginMergeCells(cnt, o) {
14751 if(o == null) o = new_buf(4);
14752 o.write_shift(4, cnt);
14753 return o;
14754}
14755
14756/* [MS-XLSB] 2.4.662 BrtHLink */
14757function parse_BrtHLink(data, length) {
14758 var end = data.l + length;
14759 var rfx = parse_UncheckedRfX(data, 16);
14760 var relId = parse_XLNullableWideString(data);
14761 var loc = parse_XLWideString(data);
14762 var tooltip = parse_XLWideString(data);
14763 var display = parse_XLWideString(data);
14764 data.l = end;
14765 var o = ({rfx:rfx, relId:relId, loc:loc, display:display});
14766 if(tooltip) o.Tooltip = tooltip;
14767 return o;
14768}
14769function write_BrtHLink(l, rId) {
14770 var o = new_buf(50+4*(l[1].Target.length + (l[1].Tooltip || "").length));
14771 write_UncheckedRfX({s:decode_cell(l[0]), e:decode_cell(l[0])}, o);
14772 write_RelID("rId" + rId, o);
14773 var locidx = l[1].Target.indexOf("#");
14774 var loc = locidx == -1 ? "" : l[1].Target.slice(locidx+1);
14775 write_XLWideString(loc || "", o);
14776 write_XLWideString(l[1].Tooltip || "", o);
14777 write_XLWideString("", o);
14778 return o.slice(0, o.l);
14779}
14780
14781/* [MS-XLSB] 2.4.692 BrtPane */
14782function parse_BrtPane(/*data, length, opts*/) {
14783}
14784
14785/* [MS-XLSB] 2.4.6 BrtArrFmla */
14786function parse_BrtArrFmla(data, length, opts) {
14787 var end = data.l + length;
14788 var rfx = parse_RfX(data, 16);
14789 var fAlwaysCalc = data.read_shift(1);
14790 var o = [rfx]; o[2] = fAlwaysCalc;
14791 if(opts.cellFormula) {
14792 var formula = parse_XLSBArrayParsedFormula(data, end - data.l, opts);
14793 o[1] = formula;
14794 } else data.l = end;
14795 return o;
14796}
14797
14798/* [MS-XLSB] 2.4.750 BrtShrFmla */
14799function parse_BrtShrFmla(data, length, opts) {
14800 var end = data.l + length;
14801 var rfx = parse_UncheckedRfX(data, 16);
14802 var o = [rfx];
14803 if(opts.cellFormula) {
14804 var formula = parse_XLSBSharedParsedFormula(data, end - data.l, opts);
14805 o[1] = formula;
14806 data.l = end;
14807 } else data.l = end;
14808 return o;
14809}
14810
14811/* [MS-XLSB] 2.4.323 BrtColInfo */
14812/* TODO: once XLS ColInfo is set, combine the functions */
14813function write_BrtColInfo(C, col, o) {
14814 if(o == null) o = new_buf(18);
14815 var p = col_obj_w(C, col);
14816 o.write_shift(-4, C);
14817 o.write_shift(-4, C);
14818 o.write_shift(4, (p.width || 10) * 256);
14819 o.write_shift(4, 0/*ixfe*/); // style
14820 var flags = 0;
14821 if(col.hidden) flags |= 0x01;
14822 if(typeof p.width == 'number') flags |= 0x02;
14823 if(col.level) flags |= (col.level << 8);
14824 o.write_shift(2, flags); // bit flag
14825 return o;
14826}
14827
14828/* [MS-XLSB] 2.4.678 BrtMargins */
14829var BrtMarginKeys = ["left","right","top","bottom","header","footer"];
14830function parse_BrtMargins(data) {
14831 var margins = ({});
14832 BrtMarginKeys.forEach(function(k) { margins[k] = parse_Xnum(data, 8); });
14833 return margins;
14834}
14835function write_BrtMargins(margins, o) {
14836 if(o == null) o = new_buf(6*8);
14837 default_margins(margins);
14838 BrtMarginKeys.forEach(function(k) { write_Xnum((margins)[k], o); });
14839 return o;
14840}
14841
14842/* [MS-XLSB] 2.4.299 BrtBeginWsView */
14843function parse_BrtBeginWsView(data) {
14844 var f = data.read_shift(2);
14845 data.l += 28;
14846 return { RTL: f & 0x20 };
14847}
14848function write_BrtBeginWsView(ws, Workbook, o) {
14849 if(o == null) o = new_buf(30);
14850 var f = 0x39c;
14851 if((((Workbook||{}).Views||[])[0]||{}).RTL) f |= 0x20;
14852 o.write_shift(2, f); // bit flag
14853 o.write_shift(4, 0);
14854 o.write_shift(4, 0); // view first row
14855 o.write_shift(4, 0); // view first col
14856 o.write_shift(1, 0); // gridline color ICV
14857 o.write_shift(1, 0);
14858 o.write_shift(2, 0);
14859 o.write_shift(2, 100); // zoom scale
14860 o.write_shift(2, 0);
14861 o.write_shift(2, 0);
14862 o.write_shift(2, 0);
14863 o.write_shift(4, 0); // workbook view id
14864 return o;
14865}
14866
14867/* [MS-XLSB] 2.4.309 BrtCellIgnoreEC */
14868function write_BrtCellIgnoreEC(ref) {
14869 var o = new_buf(24);
14870 o.write_shift(4, 4);
14871 o.write_shift(4, 1);
14872 write_UncheckedRfX(ref, o);
14873 return o;
14874}
14875
14876/* [MS-XLSB] 2.4.748 BrtSheetProtection */
14877function write_BrtSheetProtection(sp, o) {
14878 if(o == null) o = new_buf(16*4+2);
14879 o.write_shift(2, sp.password ? crypto_CreatePasswordVerifier_Method1(sp.password) : 0);
14880 o.write_shift(4, 1); // this record should not be written if no protection
14881 [
14882 ["objects", false], // fObjects
14883 ["scenarios", false], // fScenarios
14884 ["formatCells", true], // fFormatCells
14885 ["formatColumns", true], // fFormatColumns
14886 ["formatRows", true], // fFormatRows
14887 ["insertColumns", true], // fInsertColumns
14888 ["insertRows", true], // fInsertRows
14889 ["insertHyperlinks", true], // fInsertHyperlinks
14890 ["deleteColumns", true], // fDeleteColumns
14891 ["deleteRows", true], // fDeleteRows
14892 ["selectLockedCells", false], // fSelLockedCells
14893 ["sort", true], // fSort
14894 ["autoFilter", true], // fAutoFilter
14895 ["pivotTables", true], // fPivotTables
14896 ["selectUnlockedCells", false] // fSelUnlockedCells
14897 ].forEach(function(n) {
14898if(n[1]) o.write_shift(4, sp[n[0]] != null && !sp[n[0]] ? 1 : 0);
14899 else o.write_shift(4, sp[n[0]] != null && sp[n[0]] ? 0 : 1);
14900 });
14901 return o;
14902}
14903
14904function parse_BrtDVal(/*data, length, opts*/) {
14905}
14906function parse_BrtDVal14(/*data, length, opts*/) {
14907}
14908/* [MS-XLSB] 2.1.7.61 Worksheet */
14909function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles) {
14910 if(!data) return data;
14911 var opts = _opts || {};
14912 if(!rels) rels = {'!id':{}};
14913 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
14914 var s = (opts.dense ? [] : {});
14915
14916 var ref;
14917 var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
14918
14919 var state = [];
14920 var pass = false, end = false;
14921 var row, p, cf, R, C, addr, sstr, rr, cell;
14922 var merges = [];
14923 opts.biff = 12;
14924 opts['!row'] = 0;
14925
14926 var ai = 0, af = false;
14927
14928 var arrayf = [];
14929 var sharedf = {};
14930 var supbooks = opts.supbooks || wb.supbooks || ([[]]);
14931 supbooks.sharedf = sharedf;
14932 supbooks.arrayf = arrayf;
14933 supbooks.SheetNames = wb.SheetNames || wb.Sheets.map(function(x) { return x.name; });
14934 if(!opts.supbooks) {
14935 opts.supbooks = supbooks;
14936 if(wb.Names) for(var i = 0; i < wb.Names.length; ++i) supbooks[0][i+1] = wb.Names[i];
14937 }
14938
14939 var colinfo = [], rowinfo = [];
14940 var seencol = false;
14941
14942 XLSBRecordEnum[0x0010] = { n:"BrtShortReal", f:parse_BrtShortReal };
14943
14944 recordhopper(data, function ws_parse(val, R_n, RT) {
14945 if(end) return;
14946 switch(RT) {
14947 case 0x0094: /* 'BrtWsDim' */
14948 ref = val; break;
14949 case 0x0000: /* 'BrtRowHdr' */
14950 row = val;
14951 if(opts.sheetRows && opts.sheetRows <= row.r) end=true;
14952 rr = encode_row(R = row.r);
14953 opts['!row'] = row.r;
14954 if(val.hidden || val.hpt || val.level != null) {
14955 if(val.hpt) val.hpx = pt2px(val.hpt);
14956 rowinfo[val.r] = val;
14957 }
14958 break;
14959
14960 case 0x0002: /* 'BrtCellRk' */
14961 case 0x0003: /* 'BrtCellError' */
14962 case 0x0004: /* 'BrtCellBool' */
14963 case 0x0005: /* 'BrtCellReal' */
14964 case 0x0006: /* 'BrtCellSt' */
14965 case 0x0007: /* 'BrtCellIsst' */
14966 case 0x0008: /* 'BrtFmlaString' */
14967 case 0x0009: /* 'BrtFmlaNum' */
14968 case 0x000A: /* 'BrtFmlaBool' */
14969 case 0x000B: /* 'BrtFmlaError' */
14970 case 0x000D: /* 'BrtShortRk' */
14971 case 0x000E: /* 'BrtShortError' */
14972 case 0x000F: /* 'BrtShortBool' */
14973 case 0x0010: /* 'BrtShortReal' */
14974 case 0x0011: /* 'BrtShortSt' */
14975 case 0x0012: /* 'BrtShortIsst' */
14976 p = ({t:val[2]});
14977 switch(val[2]) {
14978 case 'n': p.v = val[1]; break;
14979 case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
14980 case 'b': p.v = val[1] ? true : false; break;
14981 case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break;
14982 case 'str': p.t = 's'; p.v = val[1]; break;
14983 }
14984 if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
14985 C = val[0].c == -1 ? C + 1 : val[0].c;
14986 if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
14987 else s[encode_col(C) + rr] = p;
14988 if(opts.cellFormula) {
14989 af = false;
14990 for(ai = 0; ai < arrayf.length; ++ai) {
14991 var aii = arrayf[ai];
14992 if(row.r >= aii[0].s.r && row.r <= aii[0].e.r)
14993 if(C >= aii[0].s.c && C <= aii[0].e.c) {
14994 p.F = encode_range(aii[0]); af = true;
14995 }
14996 }
14997 if(!af && val.length > 3) p.f = val[3];
14998 }
14999 if(refguess.s.r > row.r) refguess.s.r = row.r;
15000 if(refguess.s.c > C) refguess.s.c = C;
15001 if(refguess.e.r < row.r) refguess.e.r = row.r;
15002 if(refguess.e.c < C) refguess.e.c = C;
15003 if(opts.cellDates && cf && p.t == 'n' && SSF.is_date(SSF._table[cf.numFmtId])) {
15004 var _d = SSF.parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
15005 }
15006 break;
15007
15008 case 0x0001: /* 'BrtCellBlank' */
15009 case 0x000C: /* 'BrtShortBlank' */
15010 if(!opts.sheetStubs || pass) break;
15011 p = ({t:'z',v:undefined});
15012 C = val[0].c == -1 ? C + 1 : val[0].c;
15013 if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
15014 else s[encode_col(C) + rr] = p;
15015 if(refguess.s.r > row.r) refguess.s.r = row.r;
15016 if(refguess.s.c > C) refguess.s.c = C;
15017 if(refguess.e.r < row.r) refguess.e.r = row.r;
15018 if(refguess.e.c < C) refguess.e.c = C;
15019 break;
15020
15021 case 0x00B0: /* 'BrtMergeCell' */
15022 merges.push(val); break;
15023
15024 case 0x01EE: /* 'BrtHLink' */
15025 var rel = rels['!id'][val.relId];
15026 if(rel) {
15027 val.Target = rel.Target;
15028 if(val.loc) val.Target += "#"+val.loc;
15029 val.Rel = rel;
15030 } else if(val.relId == '') {
15031 val.Target = "#" + val.loc;
15032 }
15033 for(R=val.rfx.s.r;R<=val.rfx.e.r;++R) for(C=val.rfx.s.c;C<=val.rfx.e.c;++C) {
15034 if(opts.dense) {
15035 if(!s[R]) s[R] = [];
15036 if(!s[R][C]) s[R][C] = {t:'z',v:undefined};
15037 s[R][C].l = val;
15038 } else {
15039 addr = encode_cell({c:C,r:R});
15040 if(!s[addr]) s[addr] = {t:'z',v:undefined};
15041 s[addr].l = val;
15042 }
15043 }
15044 break;
15045
15046 case 0x01AA: /* 'BrtArrFmla' */
15047 if(!opts.cellFormula) break;
15048 arrayf.push(val);
15049 cell = ((opts.dense ? s[R][C] : s[encode_col(C) + rr]));
15050 cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
15051 cell.F = encode_range(val[0]);
15052 break;
15053 case 0x01AB: /* 'BrtShrFmla' */
15054 if(!opts.cellFormula) break;
15055 sharedf[encode_cell(val[0].s)] = val[1];
15056 cell = (opts.dense ? s[R][C] : s[encode_col(C) + rr]);
15057 cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
15058 break;
15059
15060 /* identical to 'ColInfo' in XLS */
15061 case 0x003C: /* 'BrtColInfo' */
15062 if(!opts.cellStyles) break;
15063 while(val.e >= val.s) {
15064 colinfo[val.e--] = { width: val.w/256, hidden: !!(val.flags & 0x01), level: val.level };
15065 if(!seencol) { seencol = true; find_mdw_colw(val.w/256); }
15066 process_col(colinfo[val.e+1]);
15067 }
15068 break;
15069
15070 case 0x00A1: /* 'BrtBeginAFilter' */
15071 s['!autofilter'] = { ref:encode_range(val) };
15072 break;
15073
15074 case 0x01DC: /* 'BrtMargins' */
15075 s['!margins'] = val;
15076 break;
15077
15078 case 0x0093: /* 'BrtWsProp' */
15079 if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
15080 if(val.name) wb.Sheets[idx].CodeName = val.name;
15081 if(val.above || val.left) s['!outline'] = { above: val.above, left: val.left };
15082 break;
15083
15084 case 0x0089: /* 'BrtBeginWsView' */
15085 if(!wb.Views) wb.Views = [{}];
15086 if(!wb.Views[0]) wb.Views[0] = {};
15087 if(val.RTL) wb.Views[0].RTL = true;
15088 break;
15089
15090 case 0x01E5: /* 'BrtWsFmtInfo' */
15091 break;
15092
15093 case 0x0040: /* 'BrtDVal' */
15094 case 0x041D: /* 'BrtDVal14' */
15095 break;
15096
15097 case 0x0097: /* 'BrtPane' */
15098 break;
15099 case 0x0098: /* 'BrtSel' */
15100 case 0x00AF: /* 'BrtAFilterDateGroupItem' */
15101 case 0x0284: /* 'BrtActiveX' */
15102 case 0x0271: /* 'BrtBigName' */
15103 case 0x0232: /* 'BrtBkHim' */
15104 case 0x018C: /* 'BrtBrk' */
15105 case 0x0458: /* 'BrtCFIcon' */
15106 case 0x047A: /* 'BrtCFRuleExt' */
15107 case 0x01D7: /* 'BrtCFVO' */
15108 case 0x041A: /* 'BrtCFVO14' */
15109 case 0x0289: /* 'BrtCellIgnoreEC' */
15110 case 0x0451: /* 'BrtCellIgnoreEC14' */
15111 case 0x0031: /* 'BrtCellMeta' */
15112 case 0x024D: /* 'BrtCellSmartTagProperty' */
15113 case 0x025F: /* 'BrtCellWatch' */
15114 case 0x0234: /* 'BrtColor' */
15115 case 0x041F: /* 'BrtColor14' */
15116 case 0x00A8: /* 'BrtColorFilter' */
15117 case 0x00AE: /* 'BrtCustomFilter' */
15118 case 0x049C: /* 'BrtCustomFilter14' */
15119 case 0x01F3: /* 'BrtDRef' */
15120 case 0x01FB: /* 'BrtDXF' */
15121 case 0x0226: /* 'BrtDrawing' */
15122 case 0x00AB: /* 'BrtDynamicFilter' */
15123 case 0x00A7: /* 'BrtFilter' */
15124 case 0x0499: /* 'BrtFilter14' */
15125 case 0x00A9: /* 'BrtIconFilter' */
15126 case 0x049D: /* 'BrtIconFilter14' */
15127 case 0x0227: /* 'BrtLegacyDrawing' */
15128 case 0x0228: /* 'BrtLegacyDrawingHF' */
15129 case 0x0295: /* 'BrtListPart' */
15130 case 0x027F: /* 'BrtOleObject' */
15131 case 0x01DE: /* 'BrtPageSetup' */
15132 case 0x0219: /* 'BrtPhoneticInfo' */
15133 case 0x01DD: /* 'BrtPrintOptions' */
15134 case 0x0218: /* 'BrtRangeProtection' */
15135 case 0x044F: /* 'BrtRangeProtection14' */
15136 case 0x02A8: /* 'BrtRangeProtectionIso' */
15137 case 0x0450: /* 'BrtRangeProtectionIso14' */
15138 case 0x0400: /* 'BrtRwDescent' */
15139 case 0x0297: /* 'BrtSheetCalcProp' */
15140 case 0x0217: /* 'BrtSheetProtection' */
15141 case 0x02A6: /* 'BrtSheetProtectionIso' */
15142 case 0x01F8: /* 'BrtSlc' */
15143 case 0x0413: /* 'BrtSparkline' */
15144 case 0x01AC: /* 'BrtTable' */
15145 case 0x00AA: /* 'BrtTop10Filter' */
15146 case 0x0C00: /* 'BrtUid' */
15147 case 0x0032: /* 'BrtValueMeta' */
15148 case 0x0816: /* 'BrtWebExtension' */
15149 case 0x0415: /* 'BrtWsFmtInfoEx14' */
15150 break;
15151
15152 case 0x0023: /* 'BrtFRTBegin' */
15153 pass = true; break;
15154 case 0x0024: /* 'BrtFRTEnd' */
15155 pass = false; break;
15156 case 0x0025: /* 'BrtACBegin' */
15157 state.push(R_n); pass = true; break;
15158 case 0x0026: /* 'BrtACEnd' */
15159 state.pop(); pass = false; break;
15160
15161 default:
15162 if((R_n||"").indexOf("Begin") > 0){/* empty */}
15163 else if((R_n||"").indexOf("End") > 0){/* empty */}
15164 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
15165 }
15166 }, opts);
15167
15168 delete opts.supbooks;
15169 delete opts['!row'];
15170
15171 if(!s["!ref"] && (refguess.s.r < 2000000 || ref && (ref.e.r > 0 || ref.e.c > 0 || ref.s.r > 0 || ref.s.c > 0))) s["!ref"] = encode_range(ref || refguess);
15172 if(opts.sheetRows && s["!ref"]) {
15173 var tmpref = safe_decode_range(s["!ref"]);
15174 if(opts.sheetRows <= +tmpref.e.r) {
15175 tmpref.e.r = opts.sheetRows - 1;
15176 if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
15177 if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
15178 if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c;
15179 if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c;
15180 s["!fullref"] = s["!ref"];
15181 s["!ref"] = encode_range(tmpref);
15182 }
15183 }
15184 if(merges.length > 0) s["!merges"] = merges;
15185 if(colinfo.length > 0) s["!cols"] = colinfo;
15186 if(rowinfo.length > 0) s["!rows"] = rowinfo;
15187 return s;
15188}
15189
15190/* TODO: something useful -- this is a stub */
15191function write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen) {
15192 if(cell.v === undefined) return false;
15193 var vv = "";
15194 switch(cell.t) {
15195 case 'b': vv = cell.v ? "1" : "0"; break;
15196 case 'd': // no BrtCellDate :(
15197 cell = dup(cell);
15198 cell.z = cell.z || SSF._table[14];
15199 cell.v = datenum(parseDate(cell.v)); cell.t = 'n';
15200 break;
15201 /* falls through */
15202 case 'n': case 'e': vv = ''+cell.v; break;
15203 default: vv = cell.v; break;
15204 }
15205 var o = ({r:R, c:C});
15206 /* TODO: cell style */
15207 o.s = get_cell_style(opts.cellXfs, cell, opts);
15208 if(cell.l) ws['!links'].push([encode_cell(o), cell.l]);
15209 if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
15210 switch(cell.t) {
15211 case 's': case 'str':
15212 if(opts.bookSST) {
15213 vv = get_sst_id(opts.Strings, (cell.v), opts.revStrings);
15214 o.t = "s"; o.v = vv;
15215 if(last_seen) write_record(ba, "BrtShortIsst", write_BrtShortIsst(cell, o));
15216 else write_record(ba, "BrtCellIsst", write_BrtCellIsst(cell, o));
15217 } else {
15218 o.t = "str";
15219 if(last_seen) write_record(ba, "BrtShortSt", write_BrtShortSt(cell, o));
15220 else write_record(ba, "BrtCellSt", write_BrtCellSt(cell, o));
15221 }
15222 return true;
15223 case 'n':
15224 /* TODO: determine threshold for Real vs RK */
15225 if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) {
15226 if(last_seen) write_record(ba, "BrtShortRk", write_BrtShortRk(cell, o));
15227 else write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o));
15228 } else {
15229 if(last_seen) write_record(ba, "BrtShortReal", write_BrtShortReal(cell, o));
15230 else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o));
15231 } return true;
15232 case 'b':
15233 o.t = "b";
15234 if(last_seen) write_record(ba, "BrtShortBool", write_BrtShortBool(cell, o));
15235 else write_record(ba, "BrtCellBool", write_BrtCellBool(cell, o));
15236 return true;
15237 case 'e':
15238 o.t = "e";
15239 if(last_seen) write_record(ba, "BrtShortError", write_BrtShortError(cell, o));
15240 else write_record(ba, "BrtCellError", write_BrtCellError(cell, o));
15241 return true;
15242 }
15243 if(last_seen) write_record(ba, "BrtShortBlank", write_BrtShortBlank(cell, o));
15244 else write_record(ba, "BrtCellBlank", write_BrtCellBlank(cell, o));
15245 return true;
15246}
15247
15248function write_CELLTABLE(ba, ws, idx, opts) {
15249 var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = [];
15250 write_record(ba, 'BrtBeginSheetData');
15251 var dense = Array.isArray(ws);
15252 var cap = range.e.r;
15253 if(ws['!rows']) cap = Math.max(range.e.r, ws['!rows'].length - 1);
15254 for(var R = range.s.r; R <= cap; ++R) {
15255 rr = encode_row(R);
15256 /* [ACCELLTABLE] */
15257 /* BrtRowHdr */
15258 write_row_header(ba, ws, range, R);
15259 var last_seen = false;
15260 if(R <= range.e.r) for(var C = range.s.c; C <= range.e.c; ++C) {
15261 /* *16384CELL */
15262 if(R === range.s.r) cols[C] = encode_col(C);
15263 ref = cols[C] + rr;
15264 var cell = dense ? (ws[R]||[])[C] : ws[ref];
15265 if(!cell) { last_seen = false; continue; }
15266 /* write cell */
15267 last_seen = write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen);
15268 }
15269 }
15270 write_record(ba, 'BrtEndSheetData');
15271}
15272
15273function write_MERGECELLS(ba, ws) {
15274 if(!ws || !ws['!merges']) return;
15275 write_record(ba, 'BrtBeginMergeCells', write_BrtBeginMergeCells(ws['!merges'].length));
15276 ws['!merges'].forEach(function(m) { write_record(ba, 'BrtMergeCell', write_BrtMergeCell(m)); });
15277 write_record(ba, 'BrtEndMergeCells');
15278}
15279
15280function write_COLINFOS(ba, ws) {
15281 if(!ws || !ws['!cols']) return;
15282 write_record(ba, 'BrtBeginColInfos');
15283 ws['!cols'].forEach(function(m, i) { if(m) write_record(ba, 'BrtColInfo', write_BrtColInfo(i, m)); });
15284 write_record(ba, 'BrtEndColInfos');
15285}
15286
15287function write_IGNOREECS(ba, ws) {
15288 if(!ws || !ws['!ref']) return;
15289 write_record(ba, 'BrtBeginCellIgnoreECs');
15290 write_record(ba, 'BrtCellIgnoreEC', write_BrtCellIgnoreEC(safe_decode_range(ws['!ref'])));
15291 write_record(ba, 'BrtEndCellIgnoreECs');
15292}
15293
15294function write_HLINKS(ba, ws, rels) {
15295 /* *BrtHLink */
15296 ws['!links'].forEach(function(l) {
15297 if(!l[1].Target) return;
15298 var rId = add_rels(rels, -1, l[1].Target.replace(/#.*$/, ""), RELS.HLINK);
15299 write_record(ba, "BrtHLink", write_BrtHLink(l, rId));
15300 });
15301 delete ws['!links'];
15302}
15303function write_LEGACYDRAWING(ba, ws, idx, rels) {
15304 /* [BrtLegacyDrawing] */
15305 if(ws['!comments'].length > 0) {
15306 var rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML);
15307 write_record(ba, "BrtLegacyDrawing", write_RelID("rId" + rId));
15308 ws['!legacy'] = rId;
15309 }
15310}
15311
15312function write_AUTOFILTER(ba, ws, wb, idx) {
15313 if(!ws['!autofilter']) return;
15314 var data = ws['!autofilter'];
15315 var ref = typeof data.ref === "string" ? data.ref : encode_range(data.ref);
15316
15317 /* Update FilterDatabase defined name for the worksheet */
15318 if(!wb.Workbook) wb.Workbook = ({Sheets:[]});
15319 if(!wb.Workbook.Names) wb.Workbook.Names = [];
15320 var names = wb.Workbook.Names;
15321 var range = decode_range(ref);
15322 if(range.s.r == range.e.r) { range.e.r = decode_range(ws["!ref"]).e.r; ref = encode_range(range); }
15323 for(var i = 0; i < names.length; ++i) {
15324 var name = names[i];
15325 if(name.Name != '_xlnm._FilterDatabase') continue;
15326 if(name.Sheet != idx) continue;
15327 name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break;
15328 }
15329 if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref });
15330
15331 write_record(ba, "BrtBeginAFilter", write_UncheckedRfX(safe_decode_range(ref)));
15332 /* *FILTERCOLUMN */
15333 /* [SORTSTATE] */
15334 /* BrtEndAFilter */
15335 write_record(ba, "BrtEndAFilter");
15336}
15337
15338function write_WSVIEWS2(ba, ws, Workbook) {
15339 write_record(ba, "BrtBeginWsViews");
15340 { /* 1*WSVIEW2 */
15341 /* [ACUID] */
15342 write_record(ba, "BrtBeginWsView", write_BrtBeginWsView(ws, Workbook));
15343 /* [BrtPane] */
15344 /* *4BrtSel */
15345 /* *4SXSELECT */
15346 /* *FRT */
15347 write_record(ba, "BrtEndWsView");
15348 }
15349 /* *FRT */
15350 write_record(ba, "BrtEndWsViews");
15351}
15352
15353function write_WSFMTINFO() {
15354 /* [ACWSFMTINFO] */
15355 //write_record(ba, "BrtWsFmtInfo", write_BrtWsFmtInfo(ws));
15356}
15357
15358function write_SHEETPROTECT(ba, ws) {
15359 if(!ws['!protect']) return;
15360 /* [BrtSheetProtectionIso] */
15361 write_record(ba, "BrtSheetProtection", write_BrtSheetProtection(ws['!protect']));
15362}
15363
15364function write_ws_bin(idx, opts, wb, rels) {
15365 var ba = buf_array();
15366 var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
15367 var c = s; try { if(wb && wb.Workbook) c = wb.Workbook.Sheets[idx].CodeName || c; } catch(e) {}
15368 var r = safe_decode_range(ws['!ref'] || "A1");
15369 if(r.e.c > 0x3FFF || r.e.r > 0xFFFFF) {
15370 if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:XFD1048576");
15371 r.e.c = Math.min(r.e.c, 0x3FFF);
15372 r.e.r = Math.min(r.e.c, 0xFFFFF);
15373 }
15374 ws['!links'] = [];
15375 /* passed back to write_zip and removed there */
15376 ws['!comments'] = [];
15377 write_record(ba, "BrtBeginSheet");
15378 if(wb.vbaraw || ws['!outline']) write_record(ba, "BrtWsProp", write_BrtWsProp(c, ws['!outline']));
15379 write_record(ba, "BrtWsDim", write_BrtWsDim(r));
15380 write_WSVIEWS2(ba, ws, wb.Workbook);
15381 write_WSFMTINFO(ba, ws);
15382 write_COLINFOS(ba, ws, idx, opts, wb);
15383 write_CELLTABLE(ba, ws, idx, opts, wb);
15384 /* [BrtSheetCalcProp] */
15385 write_SHEETPROTECT(ba, ws);
15386 /* *([BrtRangeProtectionIso] BrtRangeProtection) */
15387 /* [SCENMAN] */
15388 write_AUTOFILTER(ba, ws, wb, idx);
15389 /* [SORTSTATE] */
15390 /* [DCON] */
15391 /* [USERSHVIEWS] */
15392 write_MERGECELLS(ba, ws);
15393 /* [BrtPhoneticInfo] */
15394 /* *CONDITIONALFORMATTING */
15395 /* [DVALS] */
15396 write_HLINKS(ba, ws, rels);
15397 /* [BrtPrintOptions] */
15398 if(ws['!margins']) write_record(ba, "BrtMargins", write_BrtMargins(ws['!margins']));
15399 /* [BrtPageSetup] */
15400 /* [HEADERFOOTER] */
15401 /* [RWBRK] */
15402 /* [COLBRK] */
15403 /* *BrtBigName */
15404 /* [CELLWATCHES] */
15405 if(!opts || opts.ignoreEC || (opts.ignoreEC == (void 0))) write_IGNOREECS(ba, ws);
15406 /* [SMARTTAGS] */
15407 /* [BrtDrawing] */
15408 write_LEGACYDRAWING(ba, ws, idx, rels);
15409 /* [BrtLegacyDrawingHF] */
15410 /* [BrtBkHim] */
15411 /* [OLEOBJECTS] */
15412 /* [ACTIVEXCONTROLS] */
15413 /* [WEBPUBITEMS] */
15414 /* [LISTPARTS] */
15415 /* FRTWORKSHEET */
15416 write_record(ba, "BrtEndSheet");
15417 return ba.end();
15418}
15419RELS.CHART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart";
15420RELS.CHARTEX = "http://schemas.microsoft.com/office/2014/relationships/chartEx";
15421
15422function parse_Cache(data) {
15423 var col = [];
15424 var num = data.match(/^<c:numCache>/);
15425 var f;
15426
15427 /* 21.2.2.150 pt CT_NumVal */
15428 (data.match(/<c:pt idx="(\d*)">(.*?)<\/c:pt>/mg)||[]).forEach(function(pt) {
15429 var q = pt.match(/<c:pt idx="(\d*?)"><c:v>(.*)<\/c:v><\/c:pt>/);
15430 if(!q) return;
15431 col[+q[1]] = num ? +q[2] : q[2];
15432 });
15433
15434 /* 21.2.2.71 formatCode CT_Xstring */
15435 var nf = unescapexml((data.match(/<c:formatCode>([\s\S]*?)<\/c:formatCode>/) || ["","General"])[1]);
15436
15437 (data.match(/<c:f>(.*?)<\/c:f>/mg)||[]).forEach(function(F) { f = F.replace(/<.*?>/g,""); });
15438
15439 return [col, nf, f];
15440}
15441
15442/* 21.2 DrawingML - Charts */
15443function parse_chart(data, name, opts, rels, wb, csheet) {
15444 var cs = ((csheet || {"!type":"chart"}));
15445 if(!data) return csheet;
15446 /* 21.2.2.27 chart CT_Chart */
15447
15448 var C = 0, R = 0, col = "A";
15449 var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
15450
15451 /* 21.2.2.120 numCache CT_NumData */
15452 (data.match(/<c:numCache>[\s\S]*?<\/c:numCache>/gm)||[]).forEach(function(nc) {
15453 var cache = parse_Cache(nc);
15454 refguess.s.r = refguess.s.c = 0;
15455 refguess.e.c = C;
15456 col = encode_col(C);
15457 cache[0].forEach(function(n,i) {
15458 cs[col + encode_row(i)] = {t:'n', v:n, z:cache[1] };
15459 R = i;
15460 });
15461 if(refguess.e.r < R) refguess.e.r = R;
15462 ++C;
15463 });
15464 if(C > 0) cs["!ref"] = encode_range(refguess);
15465 return cs;
15466}
15467RELS.CS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet";
15468
15469var CS_XML_ROOT = writextag('chartsheet', null, {
15470 'xmlns': XMLNS.main[0],
15471 'xmlns:r': XMLNS.r
15472});
15473
15474/* 18.3 Worksheets also covers Chartsheets */
15475function parse_cs_xml(data, opts, idx, rels, wb) {
15476 if(!data) return data;
15477 /* 18.3.1.12 chartsheet CT_ChartSheet */
15478 if(!rels) rels = {'!id':{}};
15479 var s = ({'!type':"chart", '!drawel':null, '!rel':""});
15480 var m;
15481
15482 /* 18.3.1.83 sheetPr CT_ChartsheetPr */
15483 var sheetPr = data.match(sheetprregex);
15484 if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
15485
15486 /* 18.3.1.36 drawing CT_Drawing */
15487 if((m = data.match(/drawing r:id="(.*?)"/))) s['!rel'] = m[1];
15488
15489 if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
15490 return s;
15491}
15492function write_cs_xml(idx, opts, wb, rels) {
15493 var o = [XML_HEADER, CS_XML_ROOT];
15494 o[o.length] = writextag("drawing", null, {"r:id": "rId1"});
15495 add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
15496 if(o.length>2) { o[o.length] = ('</chartsheet>'); o[1]=o[1].replace("/>",">"); }
15497 return o.join("");
15498}
15499
15500/* [MS-XLSB] 2.4.331 BrtCsProp */
15501function parse_BrtCsProp(data, length) {
15502 data.l += 10;
15503 var name = parse_XLWideString(data, length - 10);
15504 return { name: name };
15505}
15506
15507/* [MS-XLSB] 2.1.7.7 Chart Sheet */
15508function parse_cs_bin(data, opts, idx, rels, wb) {
15509 if(!data) return data;
15510 if(!rels) rels = {'!id':{}};
15511 var s = {'!type':"chart", '!drawel':null, '!rel':""};
15512 var state = [];
15513 var pass = false;
15514 recordhopper(data, function cs_parse(val, R_n, RT) {
15515 switch(RT) {
15516
15517 case 0x0226: /* 'BrtDrawing' */
15518 s['!rel'] = val; break;
15519
15520 case 0x028B: /* 'BrtCsProp' */
15521 if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
15522 if(val.name) wb.Sheets[idx].CodeName = val.name;
15523 break;
15524
15525 case 0x0232: /* 'BrtBkHim' */
15526 case 0x028C: /* 'BrtCsPageSetup' */
15527 case 0x029D: /* 'BrtCsProtection' */
15528 case 0x02A7: /* 'BrtCsProtectionIso' */
15529 case 0x0227: /* 'BrtLegacyDrawing' */
15530 case 0x0228: /* 'BrtLegacyDrawingHF' */
15531 case 0x01DC: /* 'BrtMargins' */
15532 case 0x0C00: /* 'BrtUid' */
15533 break;
15534
15535 case 0x0023: /* 'BrtFRTBegin' */
15536 pass = true; break;
15537 case 0x0024: /* 'BrtFRTEnd' */
15538 pass = false; break;
15539 case 0x0025: /* 'BrtACBegin' */
15540 state.push(R_n); break;
15541 case 0x0026: /* 'BrtACEnd' */
15542 state.pop(); break;
15543
15544 default:
15545 if((R_n||"").indexOf("Begin") > 0) state.push(R_n);
15546 else if((R_n||"").indexOf("End") > 0) state.pop();
15547 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
15548 }
15549 }, opts);
15550
15551 if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
15552 return s;
15553}
15554function write_cs_bin() {
15555 var ba = buf_array();
15556 write_record(ba, "BrtBeginSheet");
15557 /* [BrtCsProp] */
15558 /* CSVIEWS */
15559 /* [[BrtCsProtectionIso] BrtCsProtection] */
15560 /* [USERCSVIEWS] */
15561 /* [BrtMargins] */
15562 /* [BrtCsPageSetup] */
15563 /* [HEADERFOOTER] */
15564 /* BrtDrawing */
15565 /* [BrtLegacyDrawing] */
15566 /* [BrtLegacyDrawingHF] */
15567 /* [BrtBkHim] */
15568 /* [WEBPUBITEMS] */
15569 /* FRTCHARTSHEET */
15570 write_record(ba, "BrtEndSheet");
15571 return ba.end();
15572}
15573/* 18.2.28 (CT_WorkbookProtection) Defaults */
15574var WBPropsDef = [
15575 ['allowRefreshQuery', false, "bool"],
15576 ['autoCompressPictures', true, "bool"],
15577 ['backupFile', false, "bool"],
15578 ['checkCompatibility', false, "bool"],
15579 ['CodeName', ''],
15580 ['date1904', false, "bool"],
15581 ['defaultThemeVersion', 0, "int"],
15582 ['filterPrivacy', false, "bool"],
15583 ['hidePivotFieldList', false, "bool"],
15584 ['promptedSolutions', false, "bool"],
15585 ['publishItems', false, "bool"],
15586 ['refreshAllConnections', false, "bool"],
15587 ['saveExternalLinkValues', true, "bool"],
15588 ['showBorderUnselectedTables', true, "bool"],
15589 ['showInkAnnotation', true, "bool"],
15590 ['showObjects', 'all'],
15591 ['showPivotChartFilter', false, "bool"],
15592 ['updateLinks', 'userSet']
15593];
15594
15595/* 18.2.30 (CT_BookView) Defaults */
15596var WBViewDef = [
15597 ['activeTab', 0, "int"],
15598 ['autoFilterDateGrouping', true, "bool"],
15599 ['firstSheet', 0, "int"],
15600 ['minimized', false, "bool"],
15601 ['showHorizontalScroll', true, "bool"],
15602 ['showSheetTabs', true, "bool"],
15603 ['showVerticalScroll', true, "bool"],
15604 ['tabRatio', 600, "int"],
15605 ['visibility', 'visible']
15606 //window{Height,Width}, {x,y}Window
15607];
15608
15609/* 18.2.19 (CT_Sheet) Defaults */
15610var SheetDef = [
15611 //['state', 'visible']
15612];
15613
15614/* 18.2.2 (CT_CalcPr) Defaults */
15615var CalcPrDef = [
15616 ['calcCompleted', 'true'],
15617 ['calcMode', 'auto'],
15618 ['calcOnSave', 'true'],
15619 ['concurrentCalc', 'true'],
15620 ['fullCalcOnLoad', 'false'],
15621 ['fullPrecision', 'true'],
15622 ['iterate', 'false'],
15623 ['iterateCount', '100'],
15624 ['iterateDelta', '0.001'],
15625 ['refMode', 'A1']
15626];
15627
15628/* 18.2.3 (CT_CustomWorkbookView) Defaults */
15629/*var CustomWBViewDef = [
15630 ['autoUpdate', 'false'],
15631 ['changesSavedWin', 'false'],
15632 ['includeHiddenRowCol', 'true'],
15633 ['includePrintSettings', 'true'],
15634 ['maximized', 'false'],
15635 ['minimized', 'false'],
15636 ['onlySync', 'false'],
15637 ['personalView', 'false'],
15638 ['showComments', 'commIndicator'],
15639 ['showFormulaBar', 'true'],
15640 ['showHorizontalScroll', 'true'],
15641 ['showObjects', 'all'],
15642 ['showSheetTabs', 'true'],
15643 ['showStatusbar', 'true'],
15644 ['showVerticalScroll', 'true'],
15645 ['tabRatio', '600'],
15646 ['xWindow', '0'],
15647 ['yWindow', '0']
15648];*/
15649
15650function push_defaults_array(target, defaults) {
15651 for(var j = 0; j != target.length; ++j) { var w = target[j];
15652 for(var i=0; i != defaults.length; ++i) { var z = defaults[i];
15653 if(w[z[0]] == null) w[z[0]] = z[1];
15654 else switch(z[2]) {
15655 case "bool": if(typeof w[z[0]] == "string") w[z[0]] = parsexmlbool(w[z[0]]); break;
15656 case "int": if(typeof w[z[0]] == "string") w[z[0]] = parseInt(w[z[0]], 10); break;
15657 }
15658 }
15659 }
15660}
15661function push_defaults(target, defaults) {
15662 for(var i = 0; i != defaults.length; ++i) { var z = defaults[i];
15663 if(target[z[0]] == null) target[z[0]] = z[1];
15664 else switch(z[2]) {
15665 case "bool": if(typeof target[z[0]] == "string") target[z[0]] = parsexmlbool(target[z[0]]); break;
15666 case "int": if(typeof target[z[0]] == "string") target[z[0]] = parseInt(target[z[0]], 10); break;
15667 }
15668 }
15669}
15670
15671function parse_wb_defaults(wb) {
15672 push_defaults(wb.WBProps, WBPropsDef);
15673 push_defaults(wb.CalcPr, CalcPrDef);
15674
15675 push_defaults_array(wb.WBView, WBViewDef);
15676 push_defaults_array(wb.Sheets, SheetDef);
15677
15678 _ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904);
15679}
15680
15681function safe1904(wb) {
15682 /* TODO: store date1904 somewhere else */
15683 if(!wb.Workbook) return "false";
15684 if(!wb.Workbook.WBProps) return "false";
15685 return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false";
15686}
15687
15688var badchars = "][*?\/\\".split("");
15689function check_ws_name(n, safe) {
15690 if(n.length > 31) { if(safe) return false; throw new Error("Sheet names cannot exceed 31 chars"); }
15691 var _good = true;
15692 badchars.forEach(function(c) {
15693 if(n.indexOf(c) == -1) return;
15694 if(!safe) throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
15695 _good = false;
15696 });
15697 return _good;
15698}
15699function check_wb_names(N, S, codes) {
15700 N.forEach(function(n,i) {
15701 check_ws_name(n);
15702 for(var j = 0; j < i; ++j) if(n == N[j]) throw new Error("Duplicate Sheet Name: " + n);
15703 if(codes) {
15704 var cn = (S && S[i] && S[i].CodeName) || n;
15705 if(cn.charCodeAt(0) == 95 && cn.length > 22) throw new Error("Bad Code Name: Worksheet" + cn);
15706 }
15707 });
15708}
15709function check_wb(wb) {
15710 if(!wb || !wb.SheetNames || !wb.Sheets) throw new Error("Invalid Workbook");
15711 if(!wb.SheetNames.length) throw new Error("Workbook is empty");
15712 var Sheets = (wb.Workbook && wb.Workbook.Sheets) || [];
15713 check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
15714 for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i);
15715 /* TODO: validate workbook */
15716}
15717/* 18.2 Workbook */
15718var wbnsregex = /<\w+:workbook/;
15719function parse_wb_xml(data, opts) {
15720 if(!data) throw new Error("Could not find file");
15721 var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, Names:[], xmlns: "" };
15722 var pass = false, xmlns = "xmlns";
15723 var dname = {}, dnstart = 0;
15724 data.replace(tagregex, function xml_wb(x, idx) {
15725 var y = parsexmltag(x);
15726 switch(strip_ns(y[0])) {
15727 case '<?xml': break;
15728
15729 /* 18.2.27 workbook CT_Workbook 1 */
15730 case '<workbook':
15731 if(x.match(wbnsregex)) xmlns = "xmlns" + x.match(/<(\w+):/)[1];
15732 wb.xmlns = y[xmlns];
15733 break;
15734 case '</workbook>': break;
15735
15736 /* 18.2.13 fileVersion CT_FileVersion ? */
15737 case '<fileVersion': delete y[0]; wb.AppVersion = y; break;
15738 case '<fileVersion/>': case '</fileVersion>': break;
15739
15740 /* 18.2.12 fileSharing CT_FileSharing ? */
15741 case '<fileSharing':
15742 break;
15743 case '<fileSharing/>': break;
15744
15745 /* 18.2.28 workbookPr CT_WorkbookPr ? */
15746 case '<workbookPr':
15747 case '<workbookPr/>':
15748 WBPropsDef.forEach(function(w) {
15749 if(y[w[0]] == null) return;
15750 switch(w[2]) {
15751 case "bool": wb.WBProps[w[0]] = parsexmlbool(y[w[0]]); break;
15752 case "int": wb.WBProps[w[0]] = parseInt(y[w[0]], 10); break;
15753 default: wb.WBProps[w[0]] = y[w[0]];
15754 }
15755 });
15756 if(y.codeName) wb.WBProps.CodeName = utf8read(y.codeName);
15757 break;
15758 case '</workbookPr>': break;
15759
15760 /* 18.2.29 workbookProtection CT_WorkbookProtection ? */
15761 case '<workbookProtection':
15762 break;
15763 case '<workbookProtection/>': break;
15764
15765 /* 18.2.1 bookViews CT_BookViews ? */
15766 case '<bookViews': case '<bookViews>': case '</bookViews>': break;
15767 /* 18.2.30 workbookView CT_BookView + */
15768 case '<workbookView': case '<workbookView/>': delete y[0]; wb.WBView.push(y); break;
15769 case '</workbookView>': break;
15770
15771 /* 18.2.20 sheets CT_Sheets 1 */
15772 case '<sheets': case '<sheets>': case '</sheets>': break; // aggregate sheet
15773 /* 18.2.19 sheet CT_Sheet + */
15774 case '<sheet':
15775 switch(y.state) {
15776 case "hidden": y.Hidden = 1; break;
15777 case "veryHidden": y.Hidden = 2; break;
15778 default: y.Hidden = 0;
15779 }
15780 delete y.state;
15781 y.name = unescapexml(utf8read(y.name));
15782 delete y[0]; wb.Sheets.push(y); break;
15783 case '</sheet>': break;
15784
15785 /* 18.2.15 functionGroups CT_FunctionGroups ? */
15786 case '<functionGroups': case '<functionGroups/>': break;
15787 /* 18.2.14 functionGroup CT_FunctionGroup + */
15788 case '<functionGroup': break;
15789
15790 /* 18.2.9 externalReferences CT_ExternalReferences ? */
15791 case '<externalReferences': case '</externalReferences>': case '<externalReferences>': break;
15792 /* 18.2.8 externalReference CT_ExternalReference + */
15793 case '<externalReference': break;
15794
15795 /* 18.2.6 definedNames CT_DefinedNames ? */
15796 case '<definedNames/>': break;
15797 case '<definedNames>': case '<definedNames': pass=true; break;
15798 case '</definedNames>': pass=false; break;
15799 /* 18.2.5 definedName CT_DefinedName + */
15800 case '<definedName': {
15801 dname = {};
15802 dname.Name = utf8read(y.name);
15803 if(y.comment) dname.Comment = y.comment;
15804 if(y.localSheetId) dname.Sheet = +y.localSheetId;
15805 if(parsexmlbool(y.hidden||"0")) dname.Hidden = true;
15806 dnstart = idx + x.length;
15807 } break;
15808 case '</definedName>': {
15809 dname.Ref = unescapexml(utf8read(data.slice(dnstart, idx)));
15810 wb.Names.push(dname);
15811 } break;
15812 case '<definedName/>': break;
15813
15814 /* 18.2.2 calcPr CT_CalcPr ? */
15815 case '<calcPr': delete y[0]; wb.CalcPr = y; break;
15816 case '<calcPr/>': delete y[0]; wb.CalcPr = y; break;
15817 case '</calcPr>': break;
15818
15819 /* 18.2.16 oleSize CT_OleSize ? (ref required) */
15820 case '<oleSize': break;
15821
15822 /* 18.2.4 customWorkbookViews CT_CustomWorkbookViews ? */
15823 case '<customWorkbookViews>': case '</customWorkbookViews>': case '<customWorkbookViews': break;
15824 /* 18.2.3 customWorkbookView CT_CustomWorkbookView + */
15825 case '<customWorkbookView': case '</customWorkbookView>': break;
15826
15827 /* 18.2.18 pivotCaches CT_PivotCaches ? */
15828 case '<pivotCaches>': case '</pivotCaches>': case '<pivotCaches': break;
15829 /* 18.2.17 pivotCache CT_PivotCache ? */
15830 case '<pivotCache': break;
15831
15832 /* 18.2.21 smartTagPr CT_SmartTagPr ? */
15833 case '<smartTagPr': case '<smartTagPr/>': break;
15834
15835 /* 18.2.23 smartTagTypes CT_SmartTagTypes ? */
15836 case '<smartTagTypes': case '<smartTagTypes>': case '</smartTagTypes>': break;
15837 /* 18.2.22 smartTagType CT_SmartTagType ? */
15838 case '<smartTagType': break;
15839
15840 /* 18.2.24 webPublishing CT_WebPublishing ? */
15841 case '<webPublishing': case '<webPublishing/>': break;
15842
15843 /* 18.2.11 fileRecoveryPr CT_FileRecoveryPr ? */
15844 case '<fileRecoveryPr': case '<fileRecoveryPr/>': break;
15845
15846 /* 18.2.26 webPublishObjects CT_WebPublishObjects ? */
15847 case '<webPublishObjects>': case '<webPublishObjects': case '</webPublishObjects>': break;
15848 /* 18.2.25 webPublishObject CT_WebPublishObject ? */
15849 case '<webPublishObject': break;
15850
15851 /* 18.2.10 extLst CT_ExtensionList ? */
15852 case '<extLst': case '<extLst>': case '</extLst>': case '<extLst/>': break;
15853 /* 18.2.7 ext CT_Extension + */
15854 case '<ext': pass=true; break; //TODO: check with versions of excel
15855 case '</ext>': pass=false; break;
15856
15857 /* Others */
15858 case '<ArchID': break;
15859 case '<AlternateContent':
15860 case '<AlternateContent>': pass=true; break;
15861 case '</AlternateContent>': pass=false; break;
15862
15863 /* TODO */
15864 case '<revisionPtr': break;
15865
15866 default: if(!pass && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in workbook');
15867 }
15868 return x;
15869 });
15870 if(XMLNS.main.indexOf(wb.xmlns) === -1) throw new Error("Unknown Namespace: " + wb.xmlns);
15871
15872 parse_wb_defaults(wb);
15873
15874 return wb;
15875}
15876
15877var WB_XML_ROOT = writextag('workbook', null, {
15878 'xmlns': XMLNS.main[0],
15879 //'xmlns:mx': XMLNS.mx,
15880 //'xmlns:s': XMLNS.main[0],
15881 'xmlns:r': XMLNS.r
15882});
15883
15884function write_wb_xml(wb) {
15885 var o = [XML_HEADER];
15886 o[o.length] = WB_XML_ROOT;
15887
15888 var write_names = (wb.Workbook && (wb.Workbook.Names||[]).length > 0);
15889
15890 /* fileVersion */
15891 /* fileSharing */
15892
15893 var workbookPr = ({codeName:"ThisWorkbook"});
15894 if(wb.Workbook && wb.Workbook.WBProps) {
15895 WBPropsDef.forEach(function(x) {
15896if((wb.Workbook.WBProps[x[0]]) == null) return;
15897 if((wb.Workbook.WBProps[x[0]]) == x[1]) return;
15898 workbookPr[x[0]] = (wb.Workbook.WBProps[x[0]]);
15899 });
15900if(wb.Workbook.WBProps.CodeName) { workbookPr.codeName = wb.Workbook.WBProps.CodeName; delete workbookPr.CodeName; }
15901 }
15902 o[o.length] = (writextag('workbookPr', null, workbookPr));
15903
15904 /* workbookProtection */
15905
15906 var sheets = wb.Workbook && wb.Workbook.Sheets || [];
15907 var i = 0;
15908
15909 /* bookViews only written if first worksheet is hidden */
15910 if(sheets && sheets[0] && !!sheets[0].Hidden) {
15911 o[o.length] = "<bookViews>";
15912 for(i = 0; i != wb.SheetNames.length; ++i) {
15913 if(!sheets[i]) break;
15914 if(!sheets[i].Hidden) break;
15915 }
15916 if(i == wb.SheetNames.length) i = 0;
15917 o[o.length] = '<workbookView firstSheet="' + i + '" activeTab="' + i + '"/>';
15918 o[o.length] = "</bookViews>";
15919 }
15920
15921 o[o.length] = "<sheets>";
15922 for(i = 0; i != wb.SheetNames.length; ++i) {
15923 var sht = ({name:escapexml(wb.SheetNames[i].slice(0,31))});
15924 sht.sheetId = ""+(i+1);
15925 sht["r:id"] = "rId"+(i+1);
15926 if(sheets[i]) switch(sheets[i].Hidden) {
15927 case 1: sht.state = "hidden"; break;
15928 case 2: sht.state = "veryHidden"; break;
15929 }
15930 o[o.length] = (writextag('sheet',null,sht));
15931 }
15932 o[o.length] = "</sheets>";
15933
15934 /* functionGroups */
15935 /* externalReferences */
15936
15937 if(write_names) {
15938 o[o.length] = "<definedNames>";
15939 if(wb.Workbook && wb.Workbook.Names) wb.Workbook.Names.forEach(function(n) {
15940 var d = {name:n.Name};
15941 if(n.Comment) d.comment = n.Comment;
15942 if(n.Sheet != null) d.localSheetId = ""+n.Sheet;
15943 if(n.Hidden) d.hidden = "1";
15944 if(!n.Ref) return;
15945 o[o.length] = writextag('definedName', escapexml(n.Ref), d);
15946 });
15947 o[o.length] = "</definedNames>";
15948 }
15949
15950 /* calcPr */
15951 /* oleSize */
15952 /* customWorkbookViews */
15953 /* pivotCaches */
15954 /* smartTagPr */
15955 /* smartTagTypes */
15956 /* webPublishing */
15957 /* fileRecoveryPr */
15958 /* webPublishObjects */
15959 /* extLst */
15960
15961 if(o.length>2){ o[o.length] = '</workbook>'; o[1]=o[1].replace("/>",">"); }
15962 return o.join("");
15963}
15964/* [MS-XLSB] 2.4.304 BrtBundleSh */
15965function parse_BrtBundleSh(data, length) {
15966 var z = {};
15967 z.Hidden = data.read_shift(4); //hsState ST_SheetState
15968 z.iTabID = data.read_shift(4);
15969 z.strRelID = parse_RelID(data,length-8);
15970 z.name = parse_XLWideString(data);
15971 return z;
15972}
15973function write_BrtBundleSh(data, o) {
15974 if(!o) o = new_buf(127);
15975 o.write_shift(4, data.Hidden);
15976 o.write_shift(4, data.iTabID);
15977 write_RelID(data.strRelID, o);
15978 write_XLWideString(data.name.slice(0,31), o);
15979 return o.length > o.l ? o.slice(0, o.l) : o;
15980}
15981
15982/* [MS-XLSB] 2.4.815 BrtWbProp */
15983function parse_BrtWbProp(data, length) {
15984 var o = ({});
15985 var flags = data.read_shift(4);
15986 o.defaultThemeVersion = data.read_shift(4);
15987 var strName = (length > 8) ? parse_XLWideString(data) : "";
15988 if(strName.length > 0) o.CodeName = strName;
15989 o.autoCompressPictures = !!(flags & 0x10000);
15990 o.backupFile = !!(flags & 0x40);
15991 o.checkCompatibility = !!(flags & 0x1000);
15992 o.date1904 = !!(flags & 0x01);
15993 o.filterPrivacy = !!(flags & 0x08);
15994 o.hidePivotFieldList = !!(flags & 0x400);
15995 o.promptedSolutions = !!(flags & 0x10);
15996 o.publishItems = !!(flags & 0x800);
15997 o.refreshAllConnections = !!(flags & 0x40000);
15998 o.saveExternalLinkValues = !!(flags & 0x80);
15999 o.showBorderUnselectedTables = !!(flags & 0x04);
16000 o.showInkAnnotation = !!(flags & 0x20);
16001 o.showObjects = ["all", "placeholders", "none"][(flags >> 13) & 0x03];
16002 o.showPivotChartFilter = !!(flags & 0x8000);
16003 o.updateLinks = ["userSet", "never", "always"][(flags >> 8) & 0x03];
16004 return o;
16005}
16006function write_BrtWbProp(data, o) {
16007 if(!o) o = new_buf(72);
16008 var flags = 0;
16009 if(data) {
16010 /* TODO: mirror parse_BrtWbProp fields */
16011 if(data.filterPrivacy) flags |= 0x08;
16012 }
16013 o.write_shift(4, flags);
16014 o.write_shift(4, 0);
16015 write_XLSBCodeName(data && data.CodeName || "ThisWorkbook", o);
16016 return o.slice(0, o.l);
16017}
16018
16019function parse_BrtFRTArchID$(data, length) {
16020 var o = {};
16021 data.read_shift(4);
16022 o.ArchID = data.read_shift(4);
16023 data.l += length - 8;
16024 return o;
16025}
16026
16027/* [MS-XLSB] 2.4.687 BrtName */
16028function parse_BrtName(data, length, opts) {
16029 var end = data.l + length;
16030 data.l += 4; //var flags = data.read_shift(4);
16031 data.l += 1; //var chKey = data.read_shift(1);
16032 var itab = data.read_shift(4);
16033 var name = parse_XLNameWideString(data);
16034 var formula = parse_XLSBNameParsedFormula(data, 0, opts);
16035 var comment = parse_XLNullableWideString(data);
16036 //if(0 /* fProc */) {
16037 // unusedstring1: XLNullableWideString
16038 // description: XLNullableWideString
16039 // helpTopic: XLNullableWideString
16040 // unusedstring2: XLNullableWideString
16041 //}
16042 data.l = end;
16043 var out = ({Name:name, Ptg:formula});
16044 if(itab < 0xFFFFFFF) out.Sheet = itab;
16045 if(comment) out.Comment = comment;
16046 return out;
16047}
16048
16049/* [MS-XLSB] 2.1.7.61 Workbook */
16050function parse_wb_bin(data, opts) {
16051 var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
16052 var state = [];
16053 var pass = false;
16054
16055 if(!opts) opts = {};
16056 opts.biff = 12;
16057
16058 var Names = [];
16059 var supbooks = ([[]]);
16060 supbooks.SheetNames = [];
16061 supbooks.XTI = [];
16062
16063 XLSBRecordEnum[0x0010] = { n:"BrtFRTArchID$", f:parse_BrtFRTArchID$ };
16064
16065 recordhopper(data, function hopper_wb(val, R_n, RT) {
16066 switch(RT) {
16067 case 0x009C: /* 'BrtBundleSh' */
16068 supbooks.SheetNames.push(val.name);
16069 wb.Sheets.push(val); break;
16070
16071 case 0x0099: /* 'BrtWbProp' */
16072 wb.WBProps = val; break;
16073
16074 case 0x0027: /* 'BrtName' */
16075 if(val.Sheet != null) opts.SID = val.Sheet;
16076 val.Ref = stringify_formula(val.Ptg, null, null, supbooks, opts);
16077 delete opts.SID;
16078 delete val.Ptg;
16079 Names.push(val);
16080 break;
16081 case 0x040C: /* 'BrtNameExt' */ break;
16082
16083 case 0x0165: /* 'BrtSupSelf' */
16084 case 0x0166: /* 'BrtSupSame' */
16085 case 0x0163: /* 'BrtSupBookSrc' */
16086 case 0x029B: /* 'BrtSupAddin' */
16087 if(!supbooks[0].length) supbooks[0] = [RT, val];
16088 else supbooks.push([RT, val]);
16089 supbooks[supbooks.length - 1].XTI = [];
16090 break;
16091 case 0x016A: /* 'BrtExternSheet' */
16092 if(supbooks.length === 0) { supbooks[0] = []; supbooks[0].XTI = []; }
16093 supbooks[supbooks.length - 1].XTI = supbooks[supbooks.length - 1].XTI.concat(val);
16094 supbooks.XTI = supbooks.XTI.concat(val);
16095 break;
16096 case 0x0169: /* 'BrtPlaceholderName' */
16097 break;
16098
16099 case 0x0817: /* 'BrtAbsPath15' */
16100 case 0x009E: /* 'BrtBookView' */
16101 case 0x008F: /* 'BrtBeginBundleShs' */
16102 case 0x0298: /* 'BrtBeginFnGroup' */
16103 case 0x0161: /* 'BrtBeginExternals' */
16104 break;
16105
16106 /* case 'BrtModelTimeGroupingCalcCol' */
16107 case 0x0C00: /* 'BrtUid' */
16108 case 0x0C01: /* 'BrtRevisionPtr' */
16109 case 0x0216: /* 'BrtBookProtection' */
16110 case 0x02A5: /* 'BrtBookProtectionIso' */
16111 case 0x009D: /* 'BrtCalcProp' */
16112 case 0x0262: /* 'BrtCrashRecErr' */
16113 case 0x0802: /* 'BrtDecoupledPivotCacheID' */
16114 case 0x009B: /* 'BrtFileRecover' */
16115 case 0x0224: /* 'BrtFileSharing' */
16116 case 0x02A4: /* 'BrtFileSharingIso' */
16117 case 0x0080: /* 'BrtFileVersion' */
16118 case 0x0299: /* 'BrtFnGroup' */
16119 case 0x0850: /* 'BrtModelRelationship' */
16120 case 0x084D: /* 'BrtModelTable' */
16121 case 0x0225: /* 'BrtOleSize' */
16122 case 0x0805: /* 'BrtPivotTableRef' */
16123 case 0x0254: /* 'BrtSmartTagType' */
16124 case 0x081C: /* 'BrtTableSlicerCacheID' */
16125 case 0x081B: /* 'BrtTableSlicerCacheIDs' */
16126 case 0x0822: /* 'BrtTimelineCachePivotCacheID' */
16127 case 0x018D: /* 'BrtUserBookView' */
16128 case 0x009A: /* 'BrtWbFactoid' */
16129 case 0x045D: /* 'BrtWbProp14' */
16130 case 0x0229: /* 'BrtWebOpt' */
16131 case 0x082B: /* 'BrtWorkBookPr15' */
16132 break;
16133
16134 case 0x0023: /* 'BrtFRTBegin' */
16135 state.push(R_n); pass = true; break;
16136 case 0x0024: /* 'BrtFRTEnd' */
16137 state.pop(); pass = false; break;
16138 case 0x0025: /* 'BrtACBegin' */
16139 state.push(R_n); pass = true; break;
16140 case 0x0026: /* 'BrtACEnd' */
16141 state.pop(); pass = false; break;
16142
16143 case 0x0010: /* 'BrtFRTArchID$' */ break;
16144
16145 default:
16146 if((R_n||"").indexOf("Begin") > 0){/* empty */}
16147 else if((R_n||"").indexOf("End") > 0){/* empty */}
16148 else if(!pass || (opts.WTF && state[state.length-1] != "BrtACBegin" && state[state.length-1] != "BrtFRTBegin")) throw new Error("Unexpected record " + RT + " " + R_n);
16149 }
16150 }, opts);
16151
16152 parse_wb_defaults(wb);
16153
16154 // $FlowIgnore
16155 wb.Names = Names;
16156
16157 (wb).supbooks = supbooks;
16158 return wb;
16159}
16160
16161function write_BUNDLESHS(ba, wb) {
16162 write_record(ba, "BrtBeginBundleShs");
16163 for(var idx = 0; idx != wb.SheetNames.length; ++idx) {
16164 var viz = wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx] && wb.Workbook.Sheets[idx].Hidden || 0;
16165 var d = { Hidden: viz, iTabID: idx+1, strRelID: 'rId' + (idx+1), name: wb.SheetNames[idx] };
16166 write_record(ba, "BrtBundleSh", write_BrtBundleSh(d));
16167 }
16168 write_record(ba, "BrtEndBundleShs");
16169}
16170
16171/* [MS-XLSB] 2.4.649 BrtFileVersion */
16172function write_BrtFileVersion(data, o) {
16173 if(!o) o = new_buf(127);
16174 for(var i = 0; i != 4; ++i) o.write_shift(4, 0);
16175 write_XLWideString("SheetJS", o);
16176 write_XLWideString(XLSX.version, o);
16177 write_XLWideString(XLSX.version, o);
16178 write_XLWideString("7262", o);
16179 return o.length > o.l ? o.slice(0, o.l) : o;
16180}
16181
16182/* [MS-XLSB] 2.4.301 BrtBookView */
16183function write_BrtBookView(idx, o) {
16184 if(!o) o = new_buf(29);
16185 o.write_shift(-4, 0);
16186 o.write_shift(-4, 460);
16187 o.write_shift(4, 28800);
16188 o.write_shift(4, 17600);
16189 o.write_shift(4, 500);
16190 o.write_shift(4, idx);
16191 o.write_shift(4, idx);
16192 var flags = 0x78;
16193 o.write_shift(1, flags);
16194 return o.length > o.l ? o.slice(0, o.l) : o;
16195}
16196
16197function write_BOOKVIEWS(ba, wb) {
16198 /* required if hidden tab appears before visible tab */
16199 if(!wb.Workbook || !wb.Workbook.Sheets) return;
16200 var sheets = wb.Workbook.Sheets;
16201 var i = 0, vistab = -1, hidden = -1;
16202 for(; i < sheets.length; ++i) {
16203 if(!sheets[i] || !sheets[i].Hidden && vistab == -1) vistab = i;
16204 else if(sheets[i].Hidden == 1 && hidden == -1) hidden = i;
16205 }
16206 if(hidden > vistab) return;
16207 write_record(ba, "BrtBeginBookViews");
16208 write_record(ba, "BrtBookView", write_BrtBookView(vistab));
16209 /* 1*(BrtBookView *FRT) */
16210 write_record(ba, "BrtEndBookViews");
16211}
16212
16213/* [MS-XLSB] 2.4.305 BrtCalcProp */
16214/*function write_BrtCalcProp(data, o) {
16215 if(!o) o = new_buf(26);
16216 o.write_shift(4,0); // force recalc
16217 o.write_shift(4,1);
16218 o.write_shift(4,0);
16219 write_Xnum(0, o);
16220 o.write_shift(-4, 1023);
16221 o.write_shift(1, 0x33);
16222 o.write_shift(1, 0x00);
16223 return o;
16224}*/
16225
16226/* [MS-XLSB] 2.4.646 BrtFileRecover */
16227/*function write_BrtFileRecover(data, o) {
16228 if(!o) o = new_buf(1);
16229 o.write_shift(1,0);
16230 return o;
16231}*/
16232
16233/* [MS-XLSB] 2.1.7.61 Workbook */
16234function write_wb_bin(wb, opts) {
16235 var ba = buf_array();
16236 write_record(ba, "BrtBeginBook");
16237 write_record(ba, "BrtFileVersion", write_BrtFileVersion());
16238 /* [[BrtFileSharingIso] BrtFileSharing] */
16239 write_record(ba, "BrtWbProp", write_BrtWbProp(wb.Workbook && wb.Workbook.WBProps || null));
16240 /* [ACABSPATH] */
16241 /* [[BrtBookProtectionIso] BrtBookProtection] */
16242 write_BOOKVIEWS(ba, wb, opts);
16243 write_BUNDLESHS(ba, wb, opts);
16244 /* [FNGROUP] */
16245 /* [EXTERNALS] */
16246 /* *BrtName */
16247 /* write_record(ba, "BrtCalcProp", write_BrtCalcProp()); */
16248 /* [BrtOleSize] */
16249 /* *(BrtUserBookView *FRT) */
16250 /* [PIVOTCACHEIDS] */
16251 /* [BrtWbFactoid] */
16252 /* [SMARTTAGTYPES] */
16253 /* [BrtWebOpt] */
16254 /* write_record(ba, "BrtFileRecover", write_BrtFileRecover()); */
16255 /* [WEBPUBITEMS] */
16256 /* [CRERRS] */
16257 /* FRTWORKBOOK */
16258 write_record(ba, "BrtEndBook");
16259
16260 return ba.end();
16261}
16262function parse_wb(data, name, opts) {
16263 if(name.slice(-4)===".bin") return parse_wb_bin((data), opts);
16264 return parse_wb_xml((data), opts);
16265}
16266
16267function parse_ws(data, name, idx, opts, rels, wb, themes, styles) {
16268 if(name.slice(-4)===".bin") return parse_ws_bin((data), opts, idx, rels, wb, themes, styles);
16269 return parse_ws_xml((data), opts, idx, rels, wb, themes, styles);
16270}
16271
16272function parse_cs(data, name, idx, opts, rels, wb, themes, styles) {
16273 if(name.slice(-4)===".bin") return parse_cs_bin((data), opts, idx, rels, wb, themes, styles);
16274 return parse_cs_xml((data), opts, idx, rels, wb, themes, styles);
16275}
16276
16277function parse_ms(data, name, idx, opts, rels, wb, themes, styles) {
16278 if(name.slice(-4)===".bin") return parse_ms_bin((data), opts, idx, rels, wb, themes, styles);
16279 return parse_ms_xml((data), opts, idx, rels, wb, themes, styles);
16280}
16281
16282function parse_ds(data, name, idx, opts, rels, wb, themes, styles) {
16283 if(name.slice(-4)===".bin") return parse_ds_bin((data), opts, idx, rels, wb, themes, styles);
16284 return parse_ds_xml((data), opts, idx, rels, wb, themes, styles);
16285}
16286
16287function parse_sty(data, name, themes, opts) {
16288 if(name.slice(-4)===".bin") return parse_sty_bin((data), themes, opts);
16289 return parse_sty_xml((data), themes, opts);
16290}
16291
16292function parse_theme(data, name, opts) {
16293 return parse_theme_xml(data, opts);
16294}
16295
16296function parse_sst(data, name, opts) {
16297 if(name.slice(-4)===".bin") return parse_sst_bin((data), opts);
16298 return parse_sst_xml((data), opts);
16299}
16300
16301function parse_cmnt(data, name, opts) {
16302 if(name.slice(-4)===".bin") return parse_comments_bin((data), opts);
16303 return parse_comments_xml((data), opts);
16304}
16305
16306function parse_cc(data, name, opts) {
16307 if(name.slice(-4)===".bin") return parse_cc_bin((data), name, opts);
16308 return parse_cc_xml((data), name, opts);
16309}
16310
16311function parse_xlink(data, rel, name, opts) {
16312 if(name.slice(-4)===".bin") return parse_xlink_bin((data), rel, name, opts);
16313 return parse_xlink_xml((data), rel, name, opts);
16314}
16315
16316function write_wb(wb, name, opts) {
16317 return (name.slice(-4)===".bin" ? write_wb_bin : write_wb_xml)(wb, opts);
16318}
16319
16320function write_ws(data, name, opts, wb, rels) {
16321 return (name.slice(-4)===".bin" ? write_ws_bin : write_ws_xml)(data, opts, wb, rels);
16322}
16323
16324// eslint-disable-next-line no-unused-vars
16325function write_cs(data, name, opts, wb, rels) {
16326 return (name.slice(-4)===".bin" ? write_cs_bin : write_cs_xml)(data, opts, wb, rels);
16327}
16328
16329function write_sty(data, name, opts) {
16330 return (name.slice(-4)===".bin" ? write_sty_bin : write_sty_xml)(data, opts);
16331}
16332
16333function write_sst(data, name, opts) {
16334 return (name.slice(-4)===".bin" ? write_sst_bin : write_sst_xml)(data, opts);
16335}
16336
16337function write_cmnt(data, name, opts) {
16338 return (name.slice(-4)===".bin" ? write_comments_bin : write_comments_xml)(data, opts);
16339}
16340/*
16341function write_cc(data, name:string, opts) {
16342 return (name.slice(-4)===".bin" ? write_cc_bin : write_cc_xml)(data, opts);
16343}
16344*/
16345var attregexg2=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
16346var attregex2=/([\w:]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;
16347function xlml_parsexmltag(tag, skip_root) {
16348 var words = tag.split(/\s+/);
16349 var z = ([]); if(!skip_root) z[0] = words[0];
16350 if(words.length === 1) return z;
16351 var m = tag.match(attregexg2), y, j, w, i;
16352 if(m) for(i = 0; i != m.length; ++i) {
16353 y = m[i].match(attregex2);
16354if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].slice(1,y[2].length-1);
16355 else {
16356 if(y[1].slice(0,6) === "xmlns:") w = "xmlns"+y[1].slice(6);
16357 else w = y[1].slice(j+1);
16358 z[w] = y[2].slice(1,y[2].length-1);
16359 }
16360 }
16361 return z;
16362}
16363function xlml_parsexmltagobj(tag) {
16364 var words = tag.split(/\s+/);
16365 var z = {};
16366 if(words.length === 1) return z;
16367 var m = tag.match(attregexg2), y, j, w, i;
16368 if(m) for(i = 0; i != m.length; ++i) {
16369 y = m[i].match(attregex2);
16370if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].slice(1,y[2].length-1);
16371 else {
16372 if(y[1].slice(0,6) === "xmlns:") w = "xmlns"+y[1].slice(6);
16373 else w = y[1].slice(j+1);
16374 z[w] = y[2].slice(1,y[2].length-1);
16375 }
16376 }
16377 return z;
16378}
16379
16380// ----
16381
16382function xlml_format(format, value) {
16383 var fmt = XLMLFormatMap[format] || unescapexml(format);
16384 if(fmt === "General") return SSF._general(value);
16385 return SSF.format(fmt, value);
16386}
16387
16388function xlml_set_custprop(Custprops, key, cp, val) {
16389 var oval = val;
16390 switch((cp[0].match(/dt:dt="([\w.]+)"/)||["",""])[1]) {
16391 case "boolean": oval = parsexmlbool(val); break;
16392 case "i2": case "int": oval = parseInt(val, 10); break;
16393 case "r4": case "float": oval = parseFloat(val); break;
16394 case "date": case "dateTime.tz": oval = parseDate(val); break;
16395 case "i8": case "string": case "fixed": case "uuid": case "bin.base64": break;
16396 default: throw new Error("bad custprop:" + cp[0]);
16397 }
16398 Custprops[unescapexml(key)] = oval;
16399}
16400
16401function safe_format_xlml(cell, nf, o) {
16402 if(cell.t === 'z') return;
16403 if(!o || o.cellText !== false) try {
16404 if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
16405 else if(nf === "General") {
16406 if(cell.t === 'n') {
16407 if((cell.v|0) === cell.v) cell.w = SSF._general_int(cell.v);
16408 else cell.w = SSF._general_num(cell.v);
16409 }
16410 else cell.w = SSF._general(cell.v);
16411 }
16412 else cell.w = xlml_format(nf||"General", cell.v);
16413 } catch(e) { if(o.WTF) throw e; }
16414 try {
16415 var z = XLMLFormatMap[nf]||nf||"General";
16416 if(o.cellNF) cell.z = z;
16417 if(o.cellDates && cell.t == 'n' && SSF.is_date(z)) {
16418 var _d = SSF.parse_date_code(cell.v); if(_d) { cell.t = 'd'; cell.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
16419 }
16420 } catch(e) { if(o.WTF) throw e; }
16421}
16422
16423function process_style_xlml(styles, stag, opts) {
16424 if(opts.cellStyles) {
16425 if(stag.Interior) {
16426 var I = stag.Interior;
16427 if(I.Pattern) I.patternType = XLMLPatternTypeMap[I.Pattern] || I.Pattern;
16428 }
16429 }
16430 styles[stag.ID] = stag;
16431}
16432
16433/* TODO: there must exist some form of OSP-blessed spec */
16434function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, arrayf, o) {
16435 var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
16436 var interiors = [];
16437 var i = 0;
16438 if(sid === undefined && row) sid = row.StyleID;
16439 if(sid === undefined && csty) sid = csty.StyleID;
16440 while(styles[sid] !== undefined) {
16441 if(styles[sid].nf) nf = styles[sid].nf;
16442 if(styles[sid].Interior) interiors.push(styles[sid].Interior);
16443 if(!styles[sid].Parent) break;
16444 sid = styles[sid].Parent;
16445 }
16446 switch(data.Type) {
16447 case 'Boolean':
16448 cell.t = 'b';
16449 cell.v = parsexmlbool(xml);
16450 break;
16451 case 'String':
16452 cell.t = 's'; cell.r = xlml_fixstr(unescapexml(xml));
16453 cell.v = (xml.indexOf("<") > -1 ? unescapexml(ss||xml).replace(/<.*?>/g, "") : cell.r); // todo: BR etc
16454 break;
16455 case 'DateTime':
16456 if(xml.slice(-1) != "Z") xml += "Z";
16457 cell.v = (parseDate(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
16458 if(cell.v !== cell.v) cell.v = unescapexml(xml);
16459 else if(cell.v<60) cell.v = cell.v -1;
16460 if(!nf || nf == "General") nf = "yyyy-mm-dd";
16461 /* falls through */
16462 case 'Number':
16463 if(cell.v === undefined) cell.v=+xml;
16464 if(!cell.t) cell.t = 'n';
16465 break;
16466 case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; if(o.cellText !== false) cell.w = xml; break;
16467 default:
16468 if(xml == "" && ss == "") { cell.t = 'z'; }
16469 else { cell.t = 's'; cell.v = xlml_fixstr(ss||xml); }
16470 break;
16471 }
16472 safe_format_xlml(cell, nf, o);
16473 if(o.cellFormula !== false) {
16474 if(cell.Formula) {
16475 var fstr = unescapexml(cell.Formula);
16476 /* strictly speaking, the leading = is required but some writers omit */
16477 if(fstr.charCodeAt(0) == 61 /* = */) fstr = fstr.slice(1);
16478 cell.f = rc_to_a1(fstr, base);
16479 delete cell.Formula;
16480 if(cell.ArrayRange == "RC") cell.F = rc_to_a1("RC:RC", base);
16481 else if(cell.ArrayRange) {
16482 cell.F = rc_to_a1(cell.ArrayRange, base);
16483 arrayf.push([safe_decode_range(cell.F), cell.F]);
16484 }
16485 } else {
16486 for(i = 0; i < arrayf.length; ++i)
16487 if(base.r >= arrayf[i][0].s.r && base.r <= arrayf[i][0].e.r)
16488 if(base.c >= arrayf[i][0].s.c && base.c <= arrayf[i][0].e.c)
16489 cell.F = arrayf[i][1];
16490 }
16491 }
16492 if(o.cellStyles) {
16493 interiors.forEach(function(x) {
16494 if(!S.patternType && x.patternType) S.patternType = x.patternType;
16495 });
16496 cell.s = S;
16497 }
16498 if(cell.StyleID !== undefined) cell.ixfe = cell.StyleID;
16499}
16500
16501function xlml_clean_comment(comment) {
16502 comment.t = comment.v || "";
16503 comment.t = comment.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n");
16504 comment.v = comment.w = comment.ixfe = undefined;
16505}
16506
16507function xlml_normalize(d) {
16508 if(has_buf && Buffer.isBuffer(d)) return d.toString('utf8');
16509 if(typeof d === 'string') return d;
16510 /* duktape */
16511 if(typeof Uint8Array !== 'undefined' && d instanceof Uint8Array) return utf8read(a2s(ab2a(d)));
16512 throw new Error("Bad input format: expected Buffer or string");
16513}
16514
16515/* TODO: Everything */
16516/* UOS uses CJK in tags */
16517var xlmlregex = /<(\/?)([^\s?><!\/:]*:|)([^\s?<>:\/]+)(?:[\s?:\/][^>]*)?>/mg;
16518//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
16519function parse_xlml_xml(d, _opts) {
16520 var opts = _opts || {};
16521 make_ssf(SSF);
16522 var str = debom(xlml_normalize(d));
16523 if(opts.type == 'binary' || opts.type == 'array' || opts.type == 'base64') {
16524 if(typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str));
16525 else str = utf8read(str);
16526 }
16527 var opening = str.slice(0, 1024).toLowerCase(), ishtml = false;
16528 if((opening.indexOf(">") & 1023) > Math.min((opening.indexOf(",") & 1023), (opening.indexOf(";")&1023))) { var _o = dup(opts); _o.type = "string"; return PRN.to_workbook(str, _o); }
16529 if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; });
16530 if(ishtml) return HTML_.to_workbook(str, opts);
16531 var Rn;
16532 var state = [], tmp;
16533 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
16534 var sheets = {}, sheetnames = [], cursheet = (opts.dense ? [] : {}), sheetname = "";
16535 var table = {}, cell = ({}), row = {};// eslint-disable-line no-unused-vars
16536 var dtag = xlml_parsexmltag('<Data ss:Type="String">'), didx = 0;
16537 var c = 0, r = 0;
16538 var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
16539 var styles = {}, stag = {};
16540 var ss = "", fidx = 0;
16541 var merges = [];
16542 var Props = {}, Custprops = {}, pidx = 0, cp = [];
16543 var comments = [], comment = ({});
16544 var cstys = [], csty, seencol = false;
16545 var arrayf = [];
16546 var rowinfo = [], rowobj = {}, cc = 0, rr = 0;
16547 var Workbook = ({ Sheets:[], WBProps:{date1904:false} }), wsprops = {};
16548 xlmlregex.lastIndex = 0;
16549 str = str.replace(/<!--([\s\S]*?)-->/mg,"");
16550 var raw_Rn3 = "";
16551 while((Rn = xlmlregex.exec(str))) switch((Rn[3] = (raw_Rn3 = Rn[3]).toLowerCase())) {
16552 case 'data' /*case 'Data'*/:
16553 if(raw_Rn3 == "data") {
16554 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
16555 else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
16556 break;
16557 }
16558 if(state[state.length-1][1]) break;
16559 if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]==/*"Comment"*/"comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts);
16560 else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; }
16561 break;
16562 case 'cell' /*case 'Cell'*/:
16563 if(Rn[1]==='/'){
16564 if(comments.length > 0) cell.c = comments;
16565 if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== undefined) {
16566 if(opts.dense) {
16567 if(!cursheet[r]) cursheet[r] = [];
16568 cursheet[r][c] = cell;
16569 } else cursheet[encode_col(c) + encode_row(r)] = cell;
16570 }
16571 if(cell.HRef) {
16572 cell.l = ({Target:unescapexml(cell.HRef)});
16573 if(cell.HRefScreenTip) cell.l.Tooltip = cell.HRefScreenTip;
16574 delete cell.HRef; delete cell.HRefScreenTip;
16575 }
16576 if(cell.MergeAcross || cell.MergeDown) {
16577 cc = c + (parseInt(cell.MergeAcross,10)|0);
16578 rr = r + (parseInt(cell.MergeDown,10)|0);
16579 merges.push({s:{c:c,r:r},e:{c:cc,r:rr}});
16580 }
16581 if(!opts.sheetStubs) { if(cell.MergeAcross) c = cc + 1; else ++c; }
16582 else if(cell.MergeAcross || cell.MergeDown) {
16583for(var cma = c; cma <= cc; ++cma) {
16584 for(var cmd = r; cmd <= rr; ++cmd) {
16585 if(cma > c || cmd > r) {
16586 if(opts.dense) {
16587 if(!cursheet[cmd]) cursheet[cmd] = [];
16588 cursheet[cmd][cma] = {t:'z'};
16589 } else cursheet[encode_col(cma) + encode_row(cmd)] = {t:'z'};
16590 }
16591 }
16592 }
16593 c = cc + 1;
16594 }
16595 else ++c;
16596 } else {
16597 cell = xlml_parsexmltagobj(Rn[0]);
16598 if(cell.Index) c = +cell.Index - 1;
16599 if(c < refguess.s.c) refguess.s.c = c;
16600 if(c > refguess.e.c) refguess.e.c = c;
16601 if(Rn[0].slice(-2) === "/>") ++c;
16602 comments = [];
16603 }
16604 break;
16605 case 'row' /*case 'Row'*/:
16606 if(Rn[1]==='/' || Rn[0].slice(-2) === "/>") {
16607 if(r < refguess.s.r) refguess.s.r = r;
16608 if(r > refguess.e.r) refguess.e.r = r;
16609 if(Rn[0].slice(-2) === "/>") {
16610 row = xlml_parsexmltag(Rn[0]);
16611 if(row.Index) r = +row.Index - 1;
16612 }
16613 c = 0; ++r;
16614 } else {
16615 row = xlml_parsexmltag(Rn[0]);
16616 if(row.Index) r = +row.Index - 1;
16617 rowobj = {};
16618 if(row.AutoFitHeight == "0" || row.Height) {
16619 rowobj.hpx = parseInt(row.Height, 10); rowobj.hpt = px2pt(rowobj.hpx);
16620 rowinfo[r] = rowobj;
16621 }
16622 if(row.Hidden == "1") { rowobj.hidden = true; rowinfo[r] = rowobj; }
16623 }
16624 break;
16625 case 'worksheet' /*case 'Worksheet'*/: /* TODO: read range from FullRows/FullColumns */
16626 if(Rn[1]==='/'){
16627 if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
16628 sheetnames.push(sheetname);
16629 if(refguess.s.r <= refguess.e.r && refguess.s.c <= refguess.e.c) {
16630 cursheet["!ref"] = encode_range(refguess);
16631 if(opts.sheetRows && opts.sheetRows <= refguess.e.r) {
16632 cursheet["!fullref"] = cursheet["!ref"];
16633 refguess.e.r = opts.sheetRows - 1;
16634 cursheet["!ref"] = encode_range(refguess);
16635 }
16636 }
16637 if(merges.length) cursheet["!merges"] = merges;
16638 if(cstys.length > 0) cursheet["!cols"] = cstys;
16639 if(rowinfo.length > 0) cursheet["!rows"] = rowinfo;
16640 sheets[sheetname] = cursheet;
16641 } else {
16642 refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
16643 r = c = 0;
16644 state.push([Rn[3], false]);
16645 tmp = xlml_parsexmltag(Rn[0]);
16646 sheetname = unescapexml(tmp.Name);
16647 cursheet = (opts.dense ? [] : {});
16648 merges = [];
16649 arrayf = [];
16650 rowinfo = [];
16651 wsprops = {name:sheetname, Hidden:0};
16652 Workbook.Sheets.push(wsprops);
16653 }
16654 break;
16655 case 'table' /*case 'Table'*/:
16656 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
16657 else if(Rn[0].slice(-2) == "/>") break;
16658 else {
16659 table = xlml_parsexmltag(Rn[0]);
16660 state.push([Rn[3], false]);
16661 cstys = []; seencol = false;
16662 }
16663 break;
16664
16665 case 'style' /*case 'Style'*/:
16666 if(Rn[1]==='/') process_style_xlml(styles, stag, opts);
16667 else stag = xlml_parsexmltag(Rn[0]);
16668 break;
16669
16670 case 'numberformat' /*case 'NumberFormat'*/:
16671 stag.nf = unescapexml(xlml_parsexmltag(Rn[0]).Format || "General");
16672 if(XLMLFormatMap[stag.nf]) stag.nf = XLMLFormatMap[stag.nf];
16673 for(var ssfidx = 0; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == stag.nf) break;
16674 if(ssfidx == 0x188) for(ssfidx = 0x39; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == null) { SSF.load(stag.nf, ssfidx); break; }
16675 break;
16676
16677 case 'column' /*case 'Column'*/:
16678 if(state[state.length-1][0] !== /*'Table'*/'table') break;
16679 csty = xlml_parsexmltag(Rn[0]);
16680 if(csty.Hidden) { csty.hidden = true; delete csty.Hidden; }
16681 if(csty.Width) csty.wpx = parseInt(csty.Width, 10);
16682 if(!seencol && csty.wpx > 10) {
16683 seencol = true; MDW = DEF_MDW; //find_mdw_wpx(csty.wpx);
16684 for(var _col = 0; _col < cstys.length; ++_col) if(cstys[_col]) process_col(cstys[_col]);
16685 }
16686 if(seencol) process_col(csty);
16687 cstys[(csty.Index-1||cstys.length)] = csty;
16688 for(var i = 0; i < +csty.Span; ++i) cstys[cstys.length] = dup(csty);
16689 break;
16690
16691 case 'namedrange' /*case 'NamedRange'*/:
16692 if(Rn[1]==='/') break;
16693 if(!Workbook.Names) Workbook.Names = [];
16694 var _NamedRange = parsexmltag(Rn[0]);
16695 var _DefinedName = ({
16696 Name: _NamedRange.Name,
16697 Ref: rc_to_a1(_NamedRange.RefersTo.slice(1), {r:0, c:0})
16698 });
16699 if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1;
16700Workbook.Names.push(_DefinedName);
16701 break;
16702
16703 case 'namedcell' /*case 'NamedCell'*/: break;
16704 case 'b' /*case 'B'*/: break;
16705 case 'i' /*case 'I'*/: break;
16706 case 'u' /*case 'U'*/: break;
16707 case 's' /*case 'S'*/: break;
16708 case 'em' /*case 'EM'*/: break;
16709 case 'h2' /*case 'H2'*/: break;
16710 case 'h3' /*case 'H3'*/: break;
16711 case 'sub' /*case 'Sub'*/: break;
16712 case 'sup' /*case 'Sup'*/: break;
16713 case 'span' /*case 'Span'*/: break;
16714 case 'alignment' /*case 'Alignment'*/:
16715 break;
16716 case 'borders' /*case 'Borders'*/: break;
16717 case 'border' /*case 'Border'*/: break;
16718 case 'font' /*case 'Font'*/:
16719 if(Rn[0].slice(-2) === "/>") break;
16720 else if(Rn[1]==="/") ss += str.slice(fidx, Rn.index);
16721 else fidx = Rn.index + Rn[0].length;
16722 break;
16723 case 'interior' /*case 'Interior'*/:
16724 if(!opts.cellStyles) break;
16725 stag.Interior = xlml_parsexmltag(Rn[0]);
16726 break;
16727 case 'protection' /*case 'Protection'*/: break;
16728
16729 case 'author' /*case 'Author'*/:
16730 case 'title' /*case 'Title'*/:
16731 case 'description' /*case 'Description'*/:
16732 case 'created' /*case 'Created'*/:
16733 case 'keywords' /*case 'Keywords'*/:
16734 case 'subject' /*case 'Subject'*/:
16735 case 'category' /*case 'Category'*/:
16736 case 'company' /*case 'Company'*/:
16737 case 'lastauthor' /*case 'LastAuthor'*/:
16738 case 'lastsaved' /*case 'LastSaved'*/:
16739 case 'lastprinted' /*case 'LastPrinted'*/:
16740 case 'version' /*case 'Version'*/:
16741 case 'revision' /*case 'Revision'*/:
16742 case 'totaltime' /*case 'TotalTime'*/:
16743 case 'hyperlinkbase' /*case 'HyperlinkBase'*/:
16744 case 'manager' /*case 'Manager'*/:
16745 case 'contentstatus' /*case 'ContentStatus'*/:
16746 case 'identifier' /*case 'Identifier'*/:
16747 case 'language' /*case 'Language'*/:
16748 case 'appname' /*case 'AppName'*/:
16749 if(Rn[0].slice(-2) === "/>") break;
16750 else if(Rn[1]==="/") xlml_set_prop(Props, raw_Rn3, str.slice(pidx, Rn.index));
16751 else pidx = Rn.index + Rn[0].length;
16752 break;
16753 case 'paragraphs' /*case 'Paragraphs'*/: break;
16754
16755 case 'styles' /*case 'Styles'*/:
16756 case 'workbook' /*case 'Workbook'*/:
16757 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
16758 else state.push([Rn[3], false]);
16759 break;
16760
16761 case 'comment' /*case 'Comment'*/:
16762 if(Rn[1]==='/'){
16763 if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
16764 xlml_clean_comment(comment);
16765 comments.push(comment);
16766 } else {
16767 state.push([Rn[3], false]);
16768 tmp = xlml_parsexmltag(Rn[0]);
16769 comment = ({a:tmp.Author});
16770 }
16771 break;
16772
16773 case 'autofilter' /*case 'AutoFilter'*/:
16774 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
16775 else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
16776 var AutoFilter = xlml_parsexmltag(Rn[0]);
16777 cursheet['!autofilter'] = { ref:rc_to_a1(AutoFilter.Range).replace(/\$/g,"") };
16778 state.push([Rn[3], true]);
16779 }
16780 break;
16781
16782 case 'name' /*case 'Name'*/: break;
16783
16784 case 'datavalidation' /*case 'DataValidation'*/:
16785 if(Rn[1]==='/'){
16786 if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
16787 } else {
16788 if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
16789 }
16790 break;
16791
16792 case 'pixelsperinch' /*case 'PixelsPerInch'*/:
16793 break;
16794 case 'componentoptions' /*case 'ComponentOptions'*/:
16795 case 'documentproperties' /*case 'DocumentProperties'*/:
16796 case 'customdocumentproperties' /*case 'CustomDocumentProperties'*/:
16797 case 'officedocumentsettings' /*case 'OfficeDocumentSettings'*/:
16798 case 'pivottable' /*case 'PivotTable'*/:
16799 case 'pivotcache' /*case 'PivotCache'*/:
16800 case 'names' /*case 'Names'*/:
16801 case 'mapinfo' /*case 'MapInfo'*/:
16802 case 'pagebreaks' /*case 'PageBreaks'*/:
16803 case 'querytable' /*case 'QueryTable'*/:
16804 case 'sorting' /*case 'Sorting'*/:
16805 case 'schema' /*case 'Schema'*/: //case 'data' /*case 'data'*/:
16806 case 'conditionalformatting' /*case 'ConditionalFormatting'*/:
16807 case 'smarttagtype' /*case 'SmartTagType'*/:
16808 case 'smarttags' /*case 'SmartTags'*/:
16809 case 'excelworkbook' /*case 'ExcelWorkbook'*/:
16810 case 'workbookoptions' /*case 'WorkbookOptions'*/:
16811 case 'worksheetoptions' /*case 'WorksheetOptions'*/:
16812 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
16813 else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
16814 break;
16815
16816 case 'null' /*case 'Null'*/: break;
16817
16818 default:
16819 /* FODS file root is <office:document> */
16820 if(state.length == 0 && Rn[3] == "document") return parse_fods(str, opts);
16821 /* UOS file root is <uof:UOF> */
16822 if(state.length == 0 && Rn[3] == "uof"/*"UOF"*/) return parse_fods(str, opts);
16823
16824 var seen = true;
16825 switch(state[state.length-1][0]) {
16826 /* OfficeDocumentSettings */
16827 case 'officedocumentsettings' /*case 'OfficeDocumentSettings'*/: switch(Rn[3]) {
16828 case 'allowpng' /*case 'AllowPNG'*/: break;
16829 case 'removepersonalinformation' /*case 'RemovePersonalInformation'*/: break;
16830 case 'downloadcomponents' /*case 'DownloadComponents'*/: break;
16831 case 'locationofcomponents' /*case 'LocationOfComponents'*/: break;
16832 case 'colors' /*case 'Colors'*/: break;
16833 case 'color' /*case 'Color'*/: break;
16834 case 'index' /*case 'Index'*/: break;
16835 case 'rgb' /*case 'RGB'*/: break;
16836 case 'targetscreensize' /*case 'TargetScreenSize'*/: break;
16837 case 'readonlyrecommended' /*case 'ReadOnlyRecommended'*/: break;
16838 default: seen = false;
16839 } break;
16840
16841 /* ComponentOptions */
16842 case 'componentoptions' /*case 'ComponentOptions'*/: switch(Rn[3]) {
16843 case 'toolbar' /*case 'Toolbar'*/: break;
16844 case 'hideofficelogo' /*case 'HideOfficeLogo'*/: break;
16845 case 'spreadsheetautofit' /*case 'SpreadsheetAutoFit'*/: break;
16846 case 'label' /*case 'Label'*/: break;
16847 case 'caption' /*case 'Caption'*/: break;
16848 case 'maxheight' /*case 'MaxHeight'*/: break;
16849 case 'maxwidth' /*case 'MaxWidth'*/: break;
16850 case 'nextsheetnumber' /*case 'NextSheetNumber'*/: break;
16851 default: seen = false;
16852 } break;
16853
16854 /* ExcelWorkbook */
16855 case 'excelworkbook' /*case 'ExcelWorkbook'*/: switch(Rn[3]) {
16856 case 'date1904' /*case 'Date1904'*/:
16857Workbook.WBProps.date1904 = true;
16858 break;
16859 case 'windowheight' /*case 'WindowHeight'*/: break;
16860 case 'windowwidth' /*case 'WindowWidth'*/: break;
16861 case 'windowtopx' /*case 'WindowTopX'*/: break;
16862 case 'windowtopy' /*case 'WindowTopY'*/: break;
16863 case 'tabratio' /*case 'TabRatio'*/: break;
16864 case 'protectstructure' /*case 'ProtectStructure'*/: break;
16865 case 'protectwindow' /*case 'ProtectWindow'*/: break;
16866 case 'protectwindows' /*case 'ProtectWindows'*/: break;
16867 case 'activesheet' /*case 'ActiveSheet'*/: break;
16868 case 'displayinknotes' /*case 'DisplayInkNotes'*/: break;
16869 case 'firstvisiblesheet' /*case 'FirstVisibleSheet'*/: break;
16870 case 'supbook' /*case 'SupBook'*/: break;
16871 case 'sheetname' /*case 'SheetName'*/: break;
16872 case 'sheetindex' /*case 'SheetIndex'*/: break;
16873 case 'sheetindexfirst' /*case 'SheetIndexFirst'*/: break;
16874 case 'sheetindexlast' /*case 'SheetIndexLast'*/: break;
16875 case 'dll' /*case 'Dll'*/: break;
16876 case 'acceptlabelsinformulas' /*case 'AcceptLabelsInFormulas'*/: break;
16877 case 'donotsavelinkvalues' /*case 'DoNotSaveLinkValues'*/: break;
16878 case 'iteration' /*case 'Iteration'*/: break;
16879 case 'maxiterations' /*case 'MaxIterations'*/: break;
16880 case 'maxchange' /*case 'MaxChange'*/: break;
16881 case 'path' /*case 'Path'*/: break;
16882 case 'xct' /*case 'Xct'*/: break;
16883 case 'count' /*case 'Count'*/: break;
16884 case 'selectedsheets' /*case 'SelectedSheets'*/: break;
16885 case 'calculation' /*case 'Calculation'*/: break;
16886 case 'uncalced' /*case 'Uncalced'*/: break;
16887 case 'startupprompt' /*case 'StartupPrompt'*/: break;
16888 case 'crn' /*case 'Crn'*/: break;
16889 case 'externname' /*case 'ExternName'*/: break;
16890 case 'formula' /*case 'Formula'*/: break;
16891 case 'colfirst' /*case 'ColFirst'*/: break;
16892 case 'collast' /*case 'ColLast'*/: break;
16893 case 'wantadvise' /*case 'WantAdvise'*/: break;
16894 case 'boolean' /*case 'Boolean'*/: break;
16895 case 'error' /*case 'Error'*/: break;
16896 case 'text' /*case 'Text'*/: break;
16897 case 'ole' /*case 'OLE'*/: break;
16898 case 'noautorecover' /*case 'NoAutoRecover'*/: break;
16899 case 'publishobjects' /*case 'PublishObjects'*/: break;
16900 case 'donotcalculatebeforesave' /*case 'DoNotCalculateBeforeSave'*/: break;
16901 case 'number' /*case 'Number'*/: break;
16902 case 'refmoder1c1' /*case 'RefModeR1C1'*/: break;
16903 case 'embedsavesmarttags' /*case 'EmbedSaveSmartTags'*/: break;
16904 default: seen = false;
16905 } break;
16906
16907 /* WorkbookOptions */
16908 case 'workbookoptions' /*case 'WorkbookOptions'*/: switch(Rn[3]) {
16909 case 'owcversion' /*case 'OWCVersion'*/: break;
16910 case 'height' /*case 'Height'*/: break;
16911 case 'width' /*case 'Width'*/: break;
16912 default: seen = false;
16913 } break;
16914
16915 /* WorksheetOptions */
16916 case 'worksheetoptions' /*case 'WorksheetOptions'*/: switch(Rn[3]) {
16917 case 'visible' /*case 'Visible'*/:
16918 if(Rn[0].slice(-2) === "/>"){/* empty */}
16919 else if(Rn[1]==="/") switch(str.slice(pidx, Rn.index)) {
16920 case "SheetHidden": wsprops.Hidden = 1; break;
16921 case "SheetVeryHidden": wsprops.Hidden = 2; break;
16922 }
16923 else pidx = Rn.index + Rn[0].length;
16924 break;
16925 case 'header' /*case 'Header'*/:
16926 if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
16927 cursheet['!margins'].header = parsexmltag(Rn[0]).Margin;
16928 break;
16929 case 'footer' /*case 'Footer'*/:
16930 if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
16931 cursheet['!margins'].footer = parsexmltag(Rn[0]).Margin;
16932 break;
16933 case 'pagemargins' /*case 'PageMargins'*/:
16934 var pagemargins = parsexmltag(Rn[0]);
16935 if(!cursheet['!margins']) default_margins(cursheet['!margins']={},'xlml');
16936 if(pagemargins.Top) cursheet['!margins'].top = pagemargins.Top;
16937 if(pagemargins.Left) cursheet['!margins'].left = pagemargins.Left;
16938 if(pagemargins.Right) cursheet['!margins'].right = pagemargins.Right;
16939 if(pagemargins.Bottom) cursheet['!margins'].bottom = pagemargins.Bottom;
16940 break;
16941 case 'displayrighttoleft' /*case 'DisplayRightToLeft'*/:
16942 if(!Workbook.Views) Workbook.Views = [];
16943 if(!Workbook.Views[0]) Workbook.Views[0] = {};
16944 Workbook.Views[0].RTL = true;
16945 break;
16946
16947 case 'freezepanes' /*case 'FreezePanes'*/: break;
16948 case 'frozennosplit' /*case 'FrozenNoSplit'*/: break;
16949
16950 case 'splithorizontal' /*case 'SplitHorizontal'*/:
16951 case 'splitvertical' /*case 'SplitVertical'*/:
16952 break;
16953
16954 case 'donotdisplaygridlines' /*case 'DoNotDisplayGridlines'*/:
16955 break;
16956
16957 case 'activerow' /*case 'ActiveRow'*/: break;
16958 case 'activecol' /*case 'ActiveCol'*/: break;
16959 case 'toprowbottompane' /*case 'TopRowBottomPane'*/: break;
16960 case 'leftcolumnrightpane' /*case 'LeftColumnRightPane'*/: break;
16961
16962 case 'unsynced' /*case 'Unsynced'*/: break;
16963 case 'print' /*case 'Print'*/: break;
16964 case 'printerrors' /*case 'PrintErrors'*/: break;
16965 case 'panes' /*case 'Panes'*/: break;
16966 case 'scale' /*case 'Scale'*/: break;
16967 case 'pane' /*case 'Pane'*/: break;
16968 case 'number' /*case 'Number'*/: break;
16969 case 'layout' /*case 'Layout'*/: break;
16970 case 'pagesetup' /*case 'PageSetup'*/: break;
16971 case 'selected' /*case 'Selected'*/: break;
16972 case 'protectobjects' /*case 'ProtectObjects'*/: break;
16973 case 'enableselection' /*case 'EnableSelection'*/: break;
16974 case 'protectscenarios' /*case 'ProtectScenarios'*/: break;
16975 case 'validprinterinfo' /*case 'ValidPrinterInfo'*/: break;
16976 case 'horizontalresolution' /*case 'HorizontalResolution'*/: break;
16977 case 'verticalresolution' /*case 'VerticalResolution'*/: break;
16978 case 'numberofcopies' /*case 'NumberofCopies'*/: break;
16979 case 'activepane' /*case 'ActivePane'*/: break;
16980 case 'toprowvisible' /*case 'TopRowVisible'*/: break;
16981 case 'leftcolumnvisible' /*case 'LeftColumnVisible'*/: break;
16982 case 'fittopage' /*case 'FitToPage'*/: break;
16983 case 'rangeselection' /*case 'RangeSelection'*/: break;
16984 case 'papersizeindex' /*case 'PaperSizeIndex'*/: break;
16985 case 'pagelayoutzoom' /*case 'PageLayoutZoom'*/: break;
16986 case 'pagebreakzoom' /*case 'PageBreakZoom'*/: break;
16987 case 'filteron' /*case 'FilterOn'*/: break;
16988 case 'fitwidth' /*case 'FitWidth'*/: break;
16989 case 'fitheight' /*case 'FitHeight'*/: break;
16990 case 'commentslayout' /*case 'CommentsLayout'*/: break;
16991 case 'zoom' /*case 'Zoom'*/: break;
16992 case 'lefttoright' /*case 'LeftToRight'*/: break;
16993 case 'gridlines' /*case 'Gridlines'*/: break;
16994 case 'allowsort' /*case 'AllowSort'*/: break;
16995 case 'allowfilter' /*case 'AllowFilter'*/: break;
16996 case 'allowinsertrows' /*case 'AllowInsertRows'*/: break;
16997 case 'allowdeleterows' /*case 'AllowDeleteRows'*/: break;
16998 case 'allowinsertcols' /*case 'AllowInsertCols'*/: break;
16999 case 'allowdeletecols' /*case 'AllowDeleteCols'*/: break;
17000 case 'allowinserthyperlinks' /*case 'AllowInsertHyperlinks'*/: break;
17001 case 'allowformatcells' /*case 'AllowFormatCells'*/: break;
17002 case 'allowsizecols' /*case 'AllowSizeCols'*/: break;
17003 case 'allowsizerows' /*case 'AllowSizeRows'*/: break;
17004 case 'nosummaryrowsbelowdetail' /*case 'NoSummaryRowsBelowDetail'*/:
17005 if(!cursheet["!outline"]) cursheet["!outline"] = {};
17006 cursheet["!outline"].above = true;
17007 break;
17008 case 'tabcolorindex' /*case 'TabColorIndex'*/: break;
17009 case 'donotdisplayheadings' /*case 'DoNotDisplayHeadings'*/: break;
17010 case 'showpagelayoutzoom' /*case 'ShowPageLayoutZoom'*/: break;
17011 case 'nosummarycolumnsrightdetail' /*case 'NoSummaryColumnsRightDetail'*/:
17012 if(!cursheet["!outline"]) cursheet["!outline"] = {};
17013 cursheet["!outline"].left = true;
17014 break;
17015 case 'blackandwhite' /*case 'BlackAndWhite'*/: break;
17016 case 'donotdisplayzeros' /*case 'DoNotDisplayZeros'*/: break;
17017 case 'displaypagebreak' /*case 'DisplayPageBreak'*/: break;
17018 case 'rowcolheadings' /*case 'RowColHeadings'*/: break;
17019 case 'donotdisplayoutline' /*case 'DoNotDisplayOutline'*/: break;
17020 case 'noorientation' /*case 'NoOrientation'*/: break;
17021 case 'allowusepivottables' /*case 'AllowUsePivotTables'*/: break;
17022 case 'zeroheight' /*case 'ZeroHeight'*/: break;
17023 case 'viewablerange' /*case 'ViewableRange'*/: break;
17024 case 'selection' /*case 'Selection'*/: break;
17025 case 'protectcontents' /*case 'ProtectContents'*/: break;
17026 default: seen = false;
17027 } break;
17028
17029 /* PivotTable */
17030 case 'pivottable' /*case 'PivotTable'*/: case 'pivotcache' /*case 'PivotCache'*/: switch(Rn[3]) {
17031 case 'immediateitemsondrop' /*case 'ImmediateItemsOnDrop'*/: break;
17032 case 'showpagemultipleitemlabel' /*case 'ShowPageMultipleItemLabel'*/: break;
17033 case 'compactrowindent' /*case 'CompactRowIndent'*/: break;
17034 case 'location' /*case 'Location'*/: break;
17035 case 'pivotfield' /*case 'PivotField'*/: break;
17036 case 'orientation' /*case 'Orientation'*/: break;
17037 case 'layoutform' /*case 'LayoutForm'*/: break;
17038 case 'layoutsubtotallocation' /*case 'LayoutSubtotalLocation'*/: break;
17039 case 'layoutcompactrow' /*case 'LayoutCompactRow'*/: break;
17040 case 'position' /*case 'Position'*/: break;
17041 case 'pivotitem' /*case 'PivotItem'*/: break;
17042 case 'datatype' /*case 'DataType'*/: break;
17043 case 'datafield' /*case 'DataField'*/: break;
17044 case 'sourcename' /*case 'SourceName'*/: break;
17045 case 'parentfield' /*case 'ParentField'*/: break;
17046 case 'ptlineitems' /*case 'PTLineItems'*/: break;
17047 case 'ptlineitem' /*case 'PTLineItem'*/: break;
17048 case 'countofsameitems' /*case 'CountOfSameItems'*/: break;
17049 case 'item' /*case 'Item'*/: break;
17050 case 'itemtype' /*case 'ItemType'*/: break;
17051 case 'ptsource' /*case 'PTSource'*/: break;
17052 case 'cacheindex' /*case 'CacheIndex'*/: break;
17053 case 'consolidationreference' /*case 'ConsolidationReference'*/: break;
17054 case 'filename' /*case 'FileName'*/: break;
17055 case 'reference' /*case 'Reference'*/: break;
17056 case 'nocolumngrand' /*case 'NoColumnGrand'*/: break;
17057 case 'norowgrand' /*case 'NoRowGrand'*/: break;
17058 case 'blanklineafteritems' /*case 'BlankLineAfterItems'*/: break;
17059 case 'hidden' /*case 'Hidden'*/: break;
17060 case 'subtotal' /*case 'Subtotal'*/: break;
17061 case 'basefield' /*case 'BaseField'*/: break;
17062 case 'mapchilditems' /*case 'MapChildItems'*/: break;
17063 case 'function' /*case 'Function'*/: break;
17064 case 'refreshonfileopen' /*case 'RefreshOnFileOpen'*/: break;
17065 case 'printsettitles' /*case 'PrintSetTitles'*/: break;
17066 case 'mergelabels' /*case 'MergeLabels'*/: break;
17067 case 'defaultversion' /*case 'DefaultVersion'*/: break;
17068 case 'refreshname' /*case 'RefreshName'*/: break;
17069 case 'refreshdate' /*case 'RefreshDate'*/: break;
17070 case 'refreshdatecopy' /*case 'RefreshDateCopy'*/: break;
17071 case 'versionlastrefresh' /*case 'VersionLastRefresh'*/: break;
17072 case 'versionlastupdate' /*case 'VersionLastUpdate'*/: break;
17073 case 'versionupdateablemin' /*case 'VersionUpdateableMin'*/: break;
17074 case 'versionrefreshablemin' /*case 'VersionRefreshableMin'*/: break;
17075 case 'calculation' /*case 'Calculation'*/: break;
17076 default: seen = false;
17077 } break;
17078
17079 /* PageBreaks */
17080 case 'pagebreaks' /*case 'PageBreaks'*/: switch(Rn[3]) {
17081 case 'colbreaks' /*case 'ColBreaks'*/: break;
17082 case 'colbreak' /*case 'ColBreak'*/: break;
17083 case 'rowbreaks' /*case 'RowBreaks'*/: break;
17084 case 'rowbreak' /*case 'RowBreak'*/: break;
17085 case 'colstart' /*case 'ColStart'*/: break;
17086 case 'colend' /*case 'ColEnd'*/: break;
17087 case 'rowend' /*case 'RowEnd'*/: break;
17088 default: seen = false;
17089 } break;
17090
17091 /* AutoFilter */
17092 case 'autofilter' /*case 'AutoFilter'*/: switch(Rn[3]) {
17093 case 'autofiltercolumn' /*case 'AutoFilterColumn'*/: break;
17094 case 'autofiltercondition' /*case 'AutoFilterCondition'*/: break;
17095 case 'autofilterand' /*case 'AutoFilterAnd'*/: break;
17096 case 'autofilteror' /*case 'AutoFilterOr'*/: break;
17097 default: seen = false;
17098 } break;
17099
17100 /* QueryTable */
17101 case 'querytable' /*case 'QueryTable'*/: switch(Rn[3]) {
17102 case 'id' /*case 'Id'*/: break;
17103 case 'autoformatfont' /*case 'AutoFormatFont'*/: break;
17104 case 'autoformatpattern' /*case 'AutoFormatPattern'*/: break;
17105 case 'querysource' /*case 'QuerySource'*/: break;
17106 case 'querytype' /*case 'QueryType'*/: break;
17107 case 'enableredirections' /*case 'EnableRedirections'*/: break;
17108 case 'refreshedinxl9' /*case 'RefreshedInXl9'*/: break;
17109 case 'urlstring' /*case 'URLString'*/: break;
17110 case 'htmltables' /*case 'HTMLTables'*/: break;
17111 case 'connection' /*case 'Connection'*/: break;
17112 case 'commandtext' /*case 'CommandText'*/: break;
17113 case 'refreshinfo' /*case 'RefreshInfo'*/: break;
17114 case 'notitles' /*case 'NoTitles'*/: break;
17115 case 'nextid' /*case 'NextId'*/: break;
17116 case 'columninfo' /*case 'ColumnInfo'*/: break;
17117 case 'overwritecells' /*case 'OverwriteCells'*/: break;
17118 case 'donotpromptforfile' /*case 'DoNotPromptForFile'*/: break;
17119 case 'textwizardsettings' /*case 'TextWizardSettings'*/: break;
17120 case 'source' /*case 'Source'*/: break;
17121 case 'number' /*case 'Number'*/: break;
17122 case 'decimal' /*case 'Decimal'*/: break;
17123 case 'thousandseparator' /*case 'ThousandSeparator'*/: break;
17124 case 'trailingminusnumbers' /*case 'TrailingMinusNumbers'*/: break;
17125 case 'formatsettings' /*case 'FormatSettings'*/: break;
17126 case 'fieldtype' /*case 'FieldType'*/: break;
17127 case 'delimiters' /*case 'Delimiters'*/: break;
17128 case 'tab' /*case 'Tab'*/: break;
17129 case 'comma' /*case 'Comma'*/: break;
17130 case 'autoformatname' /*case 'AutoFormatName'*/: break;
17131 case 'versionlastedit' /*case 'VersionLastEdit'*/: break;
17132 case 'versionlastrefresh' /*case 'VersionLastRefresh'*/: break;
17133 default: seen = false;
17134 } break;
17135
17136 case 'datavalidation' /*case 'DataValidation'*/:
17137 switch(Rn[3]) {
17138 case 'range' /*case 'Range'*/: break;
17139
17140 case 'type' /*case 'Type'*/: break;
17141 case 'min' /*case 'Min'*/: break;
17142 case 'max' /*case 'Max'*/: break;
17143 case 'sort' /*case 'Sort'*/: break;
17144 case 'descending' /*case 'Descending'*/: break;
17145 case 'order' /*case 'Order'*/: break;
17146 case 'casesensitive' /*case 'CaseSensitive'*/: break;
17147 case 'value' /*case 'Value'*/: break;
17148 case 'errorstyle' /*case 'ErrorStyle'*/: break;
17149 case 'errormessage' /*case 'ErrorMessage'*/: break;
17150 case 'errortitle' /*case 'ErrorTitle'*/: break;
17151 case 'inputmessage' /*case 'InputMessage'*/: break;
17152 case 'inputtitle' /*case 'InputTitle'*/: break;
17153 case 'combohide' /*case 'ComboHide'*/: break;
17154 case 'inputhide' /*case 'InputHide'*/: break;
17155 case 'condition' /*case 'Condition'*/: break;
17156 case 'qualifier' /*case 'Qualifier'*/: break;
17157 case 'useblank' /*case 'UseBlank'*/: break;
17158 case 'value1' /*case 'Value1'*/: break;
17159 case 'value2' /*case 'Value2'*/: break;
17160 case 'format' /*case 'Format'*/: break;
17161
17162 case 'cellrangelist' /*case 'CellRangeList'*/: break;
17163 default: seen = false;
17164 } break;
17165
17166 case 'sorting' /*case 'Sorting'*/:
17167 case 'conditionalformatting' /*case 'ConditionalFormatting'*/:
17168 switch(Rn[3]) {
17169 case 'range' /*case 'Range'*/: break;
17170 case 'type' /*case 'Type'*/: break;
17171 case 'min' /*case 'Min'*/: break;
17172 case 'max' /*case 'Max'*/: break;
17173 case 'sort' /*case 'Sort'*/: break;
17174 case 'descending' /*case 'Descending'*/: break;
17175 case 'order' /*case 'Order'*/: break;
17176 case 'casesensitive' /*case 'CaseSensitive'*/: break;
17177 case 'value' /*case 'Value'*/: break;
17178 case 'errorstyle' /*case 'ErrorStyle'*/: break;
17179 case 'errormessage' /*case 'ErrorMessage'*/: break;
17180 case 'errortitle' /*case 'ErrorTitle'*/: break;
17181 case 'cellrangelist' /*case 'CellRangeList'*/: break;
17182 case 'inputmessage' /*case 'InputMessage'*/: break;
17183 case 'inputtitle' /*case 'InputTitle'*/: break;
17184 case 'combohide' /*case 'ComboHide'*/: break;
17185 case 'inputhide' /*case 'InputHide'*/: break;
17186 case 'condition' /*case 'Condition'*/: break;
17187 case 'qualifier' /*case 'Qualifier'*/: break;
17188 case 'useblank' /*case 'UseBlank'*/: break;
17189 case 'value1' /*case 'Value1'*/: break;
17190 case 'value2' /*case 'Value2'*/: break;
17191 case 'format' /*case 'Format'*/: break;
17192 default: seen = false;
17193 } break;
17194
17195 /* MapInfo (schema) */
17196 case 'mapinfo' /*case 'MapInfo'*/: case 'schema' /*case 'Schema'*/: case 'data' /*case 'data'*/: switch(Rn[3]) {
17197 case 'map' /*case 'Map'*/: break;
17198 case 'entry' /*case 'Entry'*/: break;
17199 case 'range' /*case 'Range'*/: break;
17200 case 'xpath' /*case 'XPath'*/: break;
17201 case 'field' /*case 'Field'*/: break;
17202 case 'xsdtype' /*case 'XSDType'*/: break;
17203 case 'filteron' /*case 'FilterOn'*/: break;
17204 case 'aggregate' /*case 'Aggregate'*/: break;
17205 case 'elementtype' /*case 'ElementType'*/: break;
17206 case 'attributetype' /*case 'AttributeType'*/: break;
17207 /* These are from xsd (XML Schema Definition) */
17208 case 'schema' /*case 'schema'*/:
17209 case 'element' /*case 'element'*/:
17210 case 'complextype' /*case 'complexType'*/:
17211 case 'datatype' /*case 'datatype'*/:
17212 case 'all' /*case 'all'*/:
17213 case 'attribute' /*case 'attribute'*/:
17214 case 'extends' /*case 'extends'*/: break;
17215
17216 case 'row' /*case 'row'*/: break;
17217 default: seen = false;
17218 } break;
17219
17220 /* SmartTags (can be anything) */
17221 case 'smarttags' /*case 'SmartTags'*/: break;
17222
17223 default: seen = false; break;
17224 }
17225 if(seen) break;
17226 /* CustomDocumentProperties */
17227 if(Rn[3].match(/!\[CDATA/)) break;
17228 if(!state[state.length-1][1]) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
17229 if(state[state.length-1][0]===/*'CustomDocumentProperties'*/'customdocumentproperties') {
17230 if(Rn[0].slice(-2) === "/>") break;
17231 else if(Rn[1]==="/") xlml_set_custprop(Custprops, raw_Rn3, cp, str.slice(pidx, Rn.index));
17232 else { cp = Rn; pidx = Rn.index + Rn[0].length; }
17233 break;
17234 }
17235 if(opts.WTF) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
17236 }
17237 var out = ({});
17238 if(!opts.bookSheets && !opts.bookProps) out.Sheets = sheets;
17239 out.SheetNames = sheetnames;
17240 out.Workbook = Workbook;
17241 out.SSF = SSF.get_table();
17242 out.Props = Props;
17243 out.Custprops = Custprops;
17244 return out;
17245}
17246
17247function parse_xlml(data, opts) {
17248 fix_read_opts(opts=opts||{});
17249 switch(opts.type||"base64") {
17250 case "base64": return parse_xlml_xml(Base64.decode(data), opts);
17251 case "binary": case "buffer": case "file": return parse_xlml_xml(data, opts);
17252 case "array": return parse_xlml_xml(a2s(data), opts);
17253 }
17254}
17255
17256/* TODO */
17257function write_props_xlml(wb, opts) {
17258 var o = [];
17259 /* DocumentProperties */
17260 if(wb.Props) o.push(xlml_write_docprops(wb.Props, opts));
17261 /* CustomDocumentProperties */
17262 if(wb.Custprops) o.push(xlml_write_custprops(wb.Props, wb.Custprops, opts));
17263 return o.join("");
17264}
17265/* TODO */
17266function write_wb_xlml() {
17267 /* OfficeDocumentSettings */
17268 /* ExcelWorkbook */
17269 return "";
17270}
17271/* TODO */
17272function write_sty_xlml(wb, opts) {
17273 /* Styles */
17274 var styles = ['<Style ss:ID="Default" ss:Name="Normal"><NumberFormat/></Style>'];
17275 opts.cellXfs.forEach(function(xf, id) {
17276 var payload = [];
17277 payload.push(writextag('NumberFormat', null, {"ss:Format": escapexml(SSF._table[xf.numFmtId])}));
17278
17279 var o = {"ss:ID": "s" + (21+id)};
17280 styles.push(writextag('Style', payload.join(""), o));
17281 });
17282 return writextag("Styles", styles.join(""));
17283}
17284function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); }
17285function write_names_xlml(wb) {
17286 if(!((wb||{}).Workbook||{}).Names) return "";
17287var names = wb.Workbook.Names;
17288 var out = [];
17289 for(var i = 0; i < names.length; ++i) {
17290 var n = names[i];
17291 if(n.Sheet != null) continue;
17292 if(n.Name.match(/^_xlfn\./)) continue;
17293 out.push(write_name_xlml(n));
17294 }
17295 return writextag("Names", out.join(""));
17296}
17297function write_ws_xlml_names(ws, opts, idx, wb) {
17298 if(!ws) return "";
17299 if(!((wb||{}).Workbook||{}).Names) return "";
17300var names = wb.Workbook.Names;
17301 var out = [];
17302 for(var i = 0; i < names.length; ++i) {
17303 var n = names[i];
17304 if(n.Sheet != idx) continue;
17305 /*switch(n.Name) {
17306 case "_": continue;
17307 }*/
17308 if(n.Name.match(/^_xlfn\./)) continue;
17309 out.push(write_name_xlml(n));
17310 }
17311 return out.join("");
17312}
17313/* WorksheetOptions */
17314function write_ws_xlml_wsopts(ws, opts, idx, wb) {
17315 if(!ws) return "";
17316 var o = [];
17317 /* NOTE: spec technically allows any order, but stick with implied order */
17318
17319 /* FitToPage */
17320 /* DoNotDisplayColHeaders */
17321 /* DoNotDisplayRowHeaders */
17322 /* ViewableRange */
17323 /* Selection */
17324 /* GridlineColor */
17325 /* Name */
17326 /* ExcelWorksheetType */
17327 /* IntlMacro */
17328 /* Unsynced */
17329 /* Selected */
17330 /* CodeName */
17331
17332 if(ws['!margins']) {
17333 o.push("<PageSetup>");
17334 if(ws['!margins'].header) o.push(writextag("Header", null, {'x:Margin':ws['!margins'].header}));
17335 if(ws['!margins'].footer) o.push(writextag("Footer", null, {'x:Margin':ws['!margins'].footer}));
17336 o.push(writextag("PageMargins", null, {
17337 'x:Bottom': ws['!margins'].bottom || "0.75",
17338 'x:Left': ws['!margins'].left || "0.7",
17339 'x:Right': ws['!margins'].right || "0.7",
17340 'x:Top': ws['!margins'].top || "0.75"
17341 }));
17342 o.push("</PageSetup>");
17343 }
17344
17345 /* PageSetup */
17346 /* DisplayPageBreak */
17347 /* TransitionExpressionEvaluation */
17348 /* TransitionFormulaEntry */
17349 /* Print */
17350 /* Zoom */
17351 /* PageLayoutZoom */
17352 /* PageBreakZoom */
17353 /* ShowPageBreakZoom */
17354 /* DefaultRowHeight */
17355 /* DefaultColumnWidth */
17356 /* StandardWidth */
17357
17358 if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) {
17359 /* Visible */
17360 if(wb.Workbook.Sheets[idx].Hidden) o.push(writextag("Visible", (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden"), {}));
17361 else {
17362 /* Selected */
17363 for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break;
17364 if(i == idx) o.push("<Selected/>");
17365 }
17366 }
17367
17368 /* LeftColumnVisible */
17369
17370 if(((((wb||{}).Workbook||{}).Views||[])[0]||{}).RTL) o.push("<DisplayRightToLeft/>");
17371
17372 /* GridlineColorIndex */
17373 /* DisplayFormulas */
17374 /* DoNotDisplayGridlines */
17375 /* DoNotDisplayHeadings */
17376 /* DoNotDisplayOutline */
17377 /* ApplyAutomaticOutlineStyles */
17378 /* NoSummaryRowsBelowDetail */
17379 /* NoSummaryColumnsRightDetail */
17380 /* DoNotDisplayZeros */
17381 /* ActiveRow */
17382 /* ActiveColumn */
17383 /* FilterOn */
17384 /* RangeSelection */
17385 /* TopRowVisible */
17386 /* TopRowBottomPane */
17387 /* LeftColumnRightPane */
17388 /* ActivePane */
17389 /* SplitHorizontal */
17390 /* SplitVertical */
17391 /* FreezePanes */
17392 /* FrozenNoSplit */
17393 /* TabColorIndex */
17394 /* Panes */
17395
17396 /* NOTE: Password not supported in XLML Format */
17397 if(ws['!protect']) {
17398 o.push(writetag("ProtectContents", "True"));
17399 if(ws['!protect'].objects) o.push(writetag("ProtectObjects", "True"));
17400 if(ws['!protect'].scenarios) o.push(writetag("ProtectScenarios", "True"));
17401 if(ws['!protect'].selectLockedCells != null && !ws['!protect'].selectLockedCells) o.push(writetag("EnableSelection", "NoSelection"));
17402 else if(ws['!protect'].selectUnlockedCells != null && !ws['!protect'].selectUnlockedCells) o.push(writetag("EnableSelection", "UnlockedCells"));
17403 [
17404 [ "formatCells", "AllowFormatCells" ],
17405 [ "formatColumns", "AllowSizeCols" ],
17406 [ "formatRows", "AllowSizeRows" ],
17407 [ "insertColumns", "AllowInsertCols" ],
17408 [ "insertRows", "AllowInsertRows" ],
17409 [ "insertHyperlinks", "AllowInsertHyperlinks" ],
17410 [ "deleteColumns", "AllowDeleteCols" ],
17411 [ "deleteRows", "AllowDeleteRows" ],
17412 [ "sort", "AllowSort" ],
17413 [ "autoFilter", "AllowFilter" ],
17414 [ "pivotTables", "AllowUsePivotTables" ]
17415 ].forEach(function(x) { if(ws['!protect'][x[0]]) o.push("<"+x[1]+"/>"); });
17416 }
17417
17418 if(o.length == 0) return "";
17419 return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x});
17420}
17421function write_ws_xlml_comment(comments) {
17422 return comments.map(function(c) {
17423 // TODO: formatted text
17424 var t = xlml_unfixstr(c.t||"");
17425 var d =writextag("ss:Data", t, {"xmlns":"http://www.w3.org/TR/REC-html40"});
17426 return writextag("Comment", d, {"ss:Author":c.a});
17427 }).join("");
17428}
17429function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){
17430 if(!cell || (cell.v == undefined && cell.f == undefined)) return "";
17431
17432 var attr = {};
17433 if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr));
17434 if(cell.F && cell.F.slice(0, ref.length) == ref) {
17435 var end = decode_cell(cell.F.slice(ref.length + 1));
17436 attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]");
17437 }
17438
17439 if(cell.l && cell.l.Target) {
17440 attr["ss:HRef"] = escapexml(cell.l.Target);
17441 if(cell.l.Tooltip) attr["x:HRefScreenTip"] = escapexml(cell.l.Tooltip);
17442 }
17443
17444 if(ws['!merges']) {
17445 var marr = ws['!merges'];
17446 for(var mi = 0; mi != marr.length; ++mi) {
17447 if(marr[mi].s.c != addr.c || marr[mi].s.r != addr.r) continue;
17448 if(marr[mi].e.c > marr[mi].s.c) attr['ss:MergeAcross'] = marr[mi].e.c - marr[mi].s.c;
17449 if(marr[mi].e.r > marr[mi].s.r) attr['ss:MergeDown'] = marr[mi].e.r - marr[mi].s.r;
17450 }
17451 }
17452
17453 var t = "", p = "";
17454 switch(cell.t) {
17455 case 'z': if(!opts.sheetStubs) return ""; break;
17456 case 'n': t = 'Number'; p = String(cell.v); break;
17457 case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
17458 case 'e': t = 'Error'; p = BErr[cell.v]; break;
17459 case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break;
17460 case 's': t = 'String'; p = escapexlml(cell.v||""); break;
17461 }
17462 /* TODO: cell style */
17463 var os = get_cell_style(opts.cellXfs, cell, opts);
17464 attr["ss:StyleID"] = "s" + (21+os);
17465 attr["ss:Index"] = addr.c + 1;
17466 var _v = (cell.v != null ? p : "");
17467 var m = cell.t == 'z' ? "" : ('<Data ss:Type="' + t + '">' + _v + '</Data>');
17468
17469 if((cell.c||[]).length > 0) m += write_ws_xlml_comment(cell.c);
17470
17471 return writextag("Cell", m, attr);
17472}
17473function write_ws_xlml_row(R, row) {
17474 var o = '<Row ss:Index="' + (R+1) + '"';
17475 if(row) {
17476 if(row.hpt && !row.hpx) row.hpx = pt2px(row.hpt);
17477 if(row.hpx) o += ' ss:AutoFitHeight="0" ss:Height="' + row.hpx + '"';
17478 if(row.hidden) o += ' ss:Hidden="1"';
17479 }
17480 return o + '>';
17481}
17482/* TODO */
17483function write_ws_xlml_table(ws, opts, idx, wb) {
17484 if(!ws['!ref']) return "";
17485 var range = safe_decode_range(ws['!ref']);
17486 var marr = ws['!merges'] || [], mi = 0;
17487 var o = [];
17488 if(ws['!cols']) ws['!cols'].forEach(function(n, i) {
17489 process_col(n);
17490 var w = !!n.width;
17491 var p = col_obj_w(i, n);
17492 var k = {"ss:Index":i+1};
17493 if(w) k['ss:Width'] = width2px(p.width);
17494 if(n.hidden) k['ss:Hidden']="1";
17495 o.push(writextag("Column",null,k));
17496 });
17497 var dense = Array.isArray(ws);
17498 for(var R = range.s.r; R <= range.e.r; ++R) {
17499 var row = [write_ws_xlml_row(R, (ws['!rows']||[])[R])];
17500 for(var C = range.s.c; C <= range.e.c; ++C) {
17501 var skip = false;
17502 for(mi = 0; mi != marr.length; ++mi) {
17503 if(marr[mi].s.c > C) continue;
17504 if(marr[mi].s.r > R) continue;
17505 if(marr[mi].e.c < C) continue;
17506 if(marr[mi].e.r < R) continue;
17507 if(marr[mi].s.c != C || marr[mi].s.r != R) skip = true;
17508 break;
17509 }
17510 if(skip) continue;
17511 var addr = {r:R,c:C};
17512 var ref = encode_cell(addr), cell = dense ? (ws[R]||[])[C] : ws[ref];
17513 row.push(write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr));
17514 }
17515 row.push("</Row>");
17516 if(row.length > 2) o.push(row.join(""));
17517 }
17518 return o.join("");
17519}
17520function write_ws_xlml(idx, opts, wb) {
17521 var o = [];
17522 var s = wb.SheetNames[idx];
17523 var ws = wb.Sheets[s];
17524
17525 var t = ws ? write_ws_xlml_names(ws, opts, idx, wb) : "";
17526 if(t.length > 0) o.push("<Names>" + t + "</Names>");
17527
17528 /* Table */
17529 t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
17530 if(t.length > 0) o.push("<Table>" + t + "</Table>");
17531
17532 /* WorksheetOptions */
17533 o.push(write_ws_xlml_wsopts(ws, opts, idx, wb));
17534
17535 return o.join("");
17536}
17537function write_xlml(wb, opts) {
17538 if(!opts) opts = {};
17539 if(!wb.SSF) wb.SSF = SSF.get_table();
17540 if(wb.SSF) {
17541 make_ssf(SSF); SSF.load_table(wb.SSF);
17542 // $FlowIgnore
17543 opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
17544 opts.ssf = wb.SSF;
17545 opts.cellXfs = [];
17546 get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}});
17547 }
17548 var d = [];
17549 d.push(write_props_xlml(wb, opts));
17550 d.push(write_wb_xlml(wb, opts));
17551 d.push("");
17552 d.push("");
17553 for(var i = 0; i < wb.SheetNames.length; ++i)
17554 d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])}));
17555 d[2] = write_sty_xlml(wb, opts);
17556 d[3] = write_names_xlml(wb, opts);
17557 return XML_HEADER + writextag("Workbook", d.join(""), {
17558 'xmlns': XLMLNS.ss,
17559 'xmlns:o': XLMLNS.o,
17560 'xmlns:x': XLMLNS.x,
17561 'xmlns:ss': XLMLNS.ss,
17562 'xmlns:dt': XLMLNS.dt,
17563 'xmlns:html': XLMLNS.html
17564 });
17565}
17566/* [MS-OLEDS] 2.3.8 CompObjStream */
17567function parse_compobj(obj) {
17568 var v = {};
17569 var o = obj.content;
17570/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
17571 o.l = 28;
17572
17573 v.AnsiUserType = o.read_shift(0, "lpstr-ansi");
17574 v.AnsiClipboardFormat = parse_ClipboardFormatOrAnsiString(o);
17575
17576 if(o.length - o.l <= 4) return v;
17577
17578 var m = o.read_shift(4);
17579 if(m == 0 || m > 40) return v;
17580 o.l-=4; v.Reserved1 = o.read_shift(0, "lpstr-ansi");
17581
17582 if(o.length - o.l <= 4) return v;
17583 m = o.read_shift(4);
17584 if(m !== 0x71b239f4) return v;
17585 v.UnicodeClipboardFormat = parse_ClipboardFormatOrUnicodeString(o);
17586
17587 m = o.read_shift(4);
17588 if(m == 0 || m > 40) return v;
17589 o.l-=4; v.Reserved2 = o.read_shift(0, "lpwstr");
17590}
17591
17592/*
17593 Continue logic for:
17594 - 2.4.58 Continue
17595 - 2.4.59 ContinueBigName
17596 - 2.4.60 ContinueFrt
17597 - 2.4.61 ContinueFrt11
17598 - 2.4.62 ContinueFrt12
17599*/
17600function slurp(R, blob, length, opts) {
17601 var l = length;
17602 var bufs = [];
17603 var d = blob.slice(blob.l,blob.l+l);
17604 if(opts && opts.enc && opts.enc.insitu && d.length > 0) switch(R.n) {
17605 case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': case 'EOF':
17606 break;
17607 case 'BoundSheet8':
17608 break;
17609 default:
17610 opts.enc.insitu(d);
17611 }
17612 bufs.push(d);
17613 blob.l += l;
17614 var next = (XLSRecordEnum[__readUInt16LE(blob,blob.l)]);
17615 var start = 0;
17616 while(next != null && next.n.slice(0,8) === 'Continue') {
17617 l = __readUInt16LE(blob,blob.l+2);
17618 start = blob.l + 4;
17619 if(next.n == 'ContinueFrt') start += 4;
17620 else if(next.n.slice(0,11) == 'ContinueFrt') {
17621 start += 12;
17622 }
17623 d = blob.slice(start,blob.l+4+l);
17624 bufs.push(d);
17625 blob.l += 4+l;
17626 next = (XLSRecordEnum[__readUInt16LE(blob, blob.l)]);
17627 }
17628 var b = (bconcat(bufs));
17629 prep_blob(b, 0);
17630 var ll = 0; b.lens = [];
17631 for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; }
17632 if(b.length < length) throw "XLS Record " + (R && R.n || "??") + " Truncated: " + b.length + " < " + length;
17633 return R.f(b, b.length, opts);
17634}
17635
17636function safe_format_xf(p, opts, date1904) {
17637 if(p.t === 'z') return;
17638 if(!p.XF) return;
17639 var fmtid = 0;
17640 try {
17641 fmtid = p.z || p.XF.numFmtId || 0;
17642 if(opts.cellNF) p.z = SSF._table[fmtid];
17643 } catch(e) { if(opts.WTF) throw e; }
17644 if(!opts || opts.cellText !== false) try {
17645 if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
17646 else if(fmtid === 0 || fmtid == "General") {
17647 if(p.t === 'n') {
17648 if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
17649 else p.w = SSF._general_num(p.v);
17650 }
17651 else p.w = SSF._general(p.v);
17652 }
17653 else p.w = SSF.format(fmtid,p.v, {date1904:!!date1904, dateNF: opts && opts.dateNF});
17654 } catch(e) { if(opts.WTF) throw e; }
17655 if(opts.cellDates && fmtid && p.t == 'n' && SSF.is_date(SSF._table[fmtid] || String(fmtid))) {
17656 var _d = SSF.parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
17657 }
17658}
17659
17660function make_cell(val, ixfe, t) {
17661 return ({v:val, ixfe:ixfe, t:t});
17662}
17663
17664// 2.3.2
17665function parse_workbook(blob, options) {
17666 var wb = ({opts:{}});
17667 var Sheets = {};
17668 if(DENSE != null && options.dense == null) options.dense = DENSE;
17669 var out = ((options.dense ? [] : {}));
17670 var Directory = {};
17671 var range = ({});
17672 var last_formula = null;
17673 var sst = ([]);
17674 var cur_sheet = "";
17675 var Preamble = {};
17676 var lastcell, last_cell = "", cc, cmnt, rngC, rngR;
17677 var sharedf = {};
17678 var arrayf = [];
17679 var temp_val;
17680 var country;
17681 var XFs = []; /* XF records */
17682 var palette = [];
17683 var Workbook = ({ Sheets:[], WBProps:{date1904:false}, Views:[{}] }), wsprops = {};
17684 var get_rgb = function getrgb(icv) {
17685 if(icv < 8) return XLSIcv[icv];
17686 if(icv < 64) return palette[icv-8] || XLSIcv[icv];
17687 return XLSIcv[icv];
17688 };
17689 var process_cell_style = function pcs(cell, line, options) {
17690 var xfd = line.XF.data;
17691 if(!xfd || !xfd.patternType || !options || !options.cellStyles) return;
17692 line.s = ({});
17693 line.s.patternType = xfd.patternType;
17694 var t;
17695 if((t = rgb2Hex(get_rgb(xfd.icvFore)))) { line.s.fgColor = {rgb:t}; }
17696 if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; }
17697 };
17698 var addcell = function addcell(cell, line, options) {
17699 if(file_depth > 1) return;
17700 if(options.sheetRows && cell.r >= options.sheetRows) return;
17701 if(options.cellStyles && line.XF && line.XF.data) process_cell_style(cell, line, options);
17702 delete line.ixfe; delete line.XF;
17703 lastcell = cell;
17704 last_cell = encode_cell(cell);
17705 if(!range || !range.s || !range.e) range = {s:{r:0,c:0},e:{r:0,c:0}};
17706 if(cell.r < range.s.r) range.s.r = cell.r;
17707 if(cell.c < range.s.c) range.s.c = cell.c;
17708 if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1;
17709 if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1;
17710 if(options.cellFormula && line.f) {
17711 for(var afi = 0; afi < arrayf.length; ++afi) {
17712 if(arrayf[afi][0].s.c > cell.c || arrayf[afi][0].s.r > cell.r) continue;
17713 if(arrayf[afi][0].e.c < cell.c || arrayf[afi][0].e.r < cell.r) continue;
17714 line.F = encode_range(arrayf[afi][0]);
17715 if(arrayf[afi][0].s.c != cell.c || arrayf[afi][0].s.r != cell.r) delete line.f;
17716 if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts);
17717 break;
17718 }
17719 }
17720 {
17721 if(options.dense) {
17722 if(!out[cell.r]) out[cell.r] = [];
17723 out[cell.r][cell.c] = line;
17724 } else out[last_cell] = line;
17725 }
17726 };
17727 var opts = ({
17728 enc: false, // encrypted
17729 sbcch: 0, // cch in the preceding SupBook
17730 snames: [], // sheetnames
17731 sharedf: sharedf, // shared formulae by address
17732 arrayf: arrayf, // array formulae array
17733 rrtabid: [], // RRTabId
17734 lastuser: "", // Last User from WriteAccess
17735 biff: 8, // BIFF version
17736 codepage: 0, // CP from CodePage record
17737 winlocked: 0, // fLockWn from WinProtect
17738 cellStyles: !!options && !!options.cellStyles,
17739 WTF: !!options && !!options.wtf
17740 });
17741 if(options.password) opts.password = options.password;
17742 var themes;
17743 var merges = [];
17744 var objects = [];
17745 var colinfo = [], rowinfo = [];
17746 // eslint-disable-next-line no-unused-vars
17747 var defwidth = 0, defheight = 0; // twips / MDW respectively
17748 var seencol = false;
17749 var supbooks = ([]); // 1-indexed, will hold extern names
17750 supbooks.SheetNames = opts.snames;
17751 supbooks.sharedf = opts.sharedf;
17752 supbooks.arrayf = opts.arrayf;
17753 supbooks.names = [];
17754 supbooks.XTI = [];
17755 var last_Rn = '';
17756 var file_depth = 0; /* TODO: make a real stack */
17757 var BIFF2Fmt = 0, BIFF2FmtTable = [];
17758 var FilterDatabases = []; /* TODO: sort out supbooks and process elsewhere */
17759 var last_lbl;
17760
17761 /* explicit override for some broken writers */
17762 opts.codepage = 1200;
17763 set_cp(1200);
17764 var seen_codepage = false;
17765 while(blob.l < blob.length - 1) {
17766 var s = blob.l;
17767 var RecordType = blob.read_shift(2);
17768 if(RecordType === 0 && last_Rn === 'EOF') break;
17769 var length = (blob.l === blob.length ? 0 : blob.read_shift(2));
17770 var R = XLSRecordEnum[RecordType];
17771 //console.log(RecordType.toString(16), RecordType, R, blob.l, length, blob.length);
17772 //if(!R) console.log(blob.slice(blob.l, blob.l + length));
17773 if(R && R.f) {
17774 if(options.bookSheets) {
17775 if(last_Rn === 'BoundSheet8' && R.n !== 'BoundSheet8') break;
17776 }
17777 last_Rn = R.n;
17778 if(R.r === 2 || R.r == 12) {
17779 var rt = blob.read_shift(2); length -= 2;
17780 if(!opts.enc && rt !== RecordType && (((rt&0xFF)<<8)|(rt>>8)) !== RecordType) throw new Error("rt mismatch: " + rt + "!=" + RecordType);
17781 if(R.r == 12){
17782 blob.l += 10; length -= 10;
17783 } // skip FRT
17784 }
17785 //console.error(R,blob.l,length,blob.length);
17786 var val = ({});
17787 if(R.n === 'EOF') val = R.f(blob, length, opts);
17788 else val = slurp(R, blob, length, opts);
17789 var Rn = R.n;
17790if(file_depth == 0 && Rn != 'BOF') continue;
17791 /* nested switch statements to workaround V8 128 limit */
17792 switch(Rn) {
17793 /* Workbook Options */
17794 case 'Date1904':
17795wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
17796 case 'WriteProtect': wb.opts.WriteProtect = true; break;
17797 case 'FilePass':
17798 if(!opts.enc) blob.l = 0;
17799 opts.enc = val;
17800 if(!options.password) throw new Error("File is password-protected");
17801 if(val.valid == null) throw new Error("Encryption scheme unsupported");
17802 if(!val.valid) throw new Error("Password is incorrect");
17803 break;
17804 case 'WriteAccess': opts.lastuser = val; break;
17805 case 'FileSharing': break; //TODO
17806 case 'CodePage':
17807 var cpval = Number(val);
17808 /* overrides based on test cases */
17809 switch(cpval) {
17810 case 0x5212: cpval = 1200; break;
17811 case 0x8000: cpval = 10000; break;
17812 case 0x8001: cpval = 1252; break;
17813 }
17814 set_cp(opts.codepage = cpval);
17815 seen_codepage = true;
17816 break;
17817 case 'RRTabId': opts.rrtabid = val; break;
17818 case 'WinProtect': opts.winlocked = val; break;
17819 case 'Template': break; // TODO
17820 case 'BookBool': break; // TODO
17821 case 'UsesELFs': break;
17822 case 'MTRSettings': break;
17823 case 'RefreshAll':
17824 case 'CalcCount':
17825 case 'CalcDelta':
17826 case 'CalcIter':
17827 case 'CalcMode':
17828 case 'CalcPrecision':
17829 case 'CalcSaveRecalc':
17830 wb.opts[Rn] = val; break;
17831 case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
17832 case 'Uncalced': break;
17833 case 'ForceFullCalculation': wb.opts.FullCalc = val; break;
17834 case 'WsBool':
17835 if(val.fDialog) out["!type"] = "dialog";
17836 if(!val.fBelow) (out["!outline"] || (out["!outline"] = {})).above = true;
17837 if(!val.fRight) (out["!outline"] || (out["!outline"] = {})).left = true;
17838 break; // TODO
17839 case 'XF':
17840 XFs.push(val); break;
17841 case 'ExtSST': break; // TODO
17842 case 'BookExt': break; // TODO
17843 case 'RichTextStream': break;
17844 case 'BkHim': break;
17845
17846 case 'SupBook':
17847 supbooks.push([val]);
17848 supbooks[supbooks.length-1].XTI = [];
17849 break;
17850 case 'ExternName':
17851 supbooks[supbooks.length-1].push(val);
17852 break;
17853 case 'Index': break; // TODO
17854 case 'Lbl':
17855 last_lbl = ({
17856 Name: val.Name,
17857 Ref: stringify_formula(val.rgce,range,null,supbooks,opts)
17858 });
17859 if(val.itab > 0) last_lbl.Sheet = val.itab - 1;
17860 supbooks.names.push(last_lbl);
17861 if(!supbooks[0]) { supbooks[0] = []; supbooks[0].XTI = []; }
17862 supbooks[supbooks.length-1].push(val);
17863 if(val.Name == "_xlnm._FilterDatabase" && val.itab > 0)
17864 if(val.rgce && val.rgce[0] && val.rgce[0][0] && val.rgce[0][0][0] == 'PtgArea3d')
17865 FilterDatabases[val.itab - 1] = { ref: encode_range(val.rgce[0][0][1][2]) };
17866 break;
17867 case 'ExternCount': opts.ExternCount = val; break;
17868 case 'ExternSheet':
17869 if(supbooks.length == 0) { supbooks[0] = []; supbooks[0].XTI = []; }
17870 supbooks[supbooks.length - 1].XTI = supbooks[supbooks.length - 1].XTI.concat(val); supbooks.XTI = supbooks.XTI.concat(val); break;
17871 case 'NameCmt':
17872 /* TODO: search for correct name */
17873 if(opts.biff < 8) break;
17874 if(last_lbl != null) last_lbl.Comment = val[1];
17875 break;
17876
17877 case 'Protect': out["!protect"] = val; break; /* for sheet or book */
17878 case 'Password': if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
17879 case 'Prot4Rev': case 'Prot4RevPass': break; /*TODO: Revision Control*/
17880
17881 case 'BoundSheet8': {
17882 Directory[val.pos] = val;
17883 opts.snames.push(val.name);
17884 } break;
17885 case 'EOF': {
17886 if(--file_depth) break;
17887 if(range.e) {
17888 if(range.e.r > 0 && range.e.c > 0) {
17889 range.e.r--; range.e.c--;
17890 out["!ref"] = encode_range(range);
17891 if(options.sheetRows && options.sheetRows <= range.e.r) {
17892 var tmpri = range.e.r;
17893 range.e.r = options.sheetRows - 1;
17894 out["!fullref"] = out["!ref"];
17895 out["!ref"] = encode_range(range);
17896 range.e.r = tmpri;
17897 }
17898 range.e.r++; range.e.c++;
17899 }
17900 if(merges.length > 0) out["!merges"] = merges;
17901 if(objects.length > 0) out["!objects"] = objects;
17902 if(colinfo.length > 0) out["!cols"] = colinfo;
17903 if(rowinfo.length > 0) out["!rows"] = rowinfo;
17904 Workbook.Sheets.push(wsprops);
17905 }
17906 if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out;
17907 out = ((options.dense ? [] : {}));
17908 } break;
17909 case 'BOF': {
17910 if(opts.biff === 8) opts.biff = {
179110x0009:2,
179120x0209:3,
179130x0409:4
17914 }[RecordType] || {
179150x0200:2,
179160x0300:3,
179170x0400:4,
179180x0500:5,
179190x0600:8,
179200x0002:2,
179210x0007:2
17922 }[val.BIFFVer] || 8;
17923 opts.biffguess = val.BIFFVer == 0;
17924 if(val.BIFFVer == 0 && val.dt == 0x1000) { opts.biff = 5; seen_codepage = true; set_cp(opts.codepage = 28591); }
17925 if(opts.biff == 8 && val.BIFFVer == 0 && val.dt == 16) opts.biff = 2;
17926 if(file_depth++) break;
17927 out = ((options.dense ? [] : {}));
17928
17929 if(opts.biff < 8 && !seen_codepage) { seen_codepage = true; set_cp(opts.codepage = options.codepage || 1252); }
17930
17931 if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) {
17932 if(cur_sheet === "") cur_sheet = "Sheet1";
17933 range = {s:{r:0,c:0},e:{r:0,c:0}};
17934 /* fake BoundSheet8 */
17935 var fakebs8 = {pos: blob.l - length, name:cur_sheet};
17936 Directory[fakebs8.pos] = fakebs8;
17937 opts.snames.push(cur_sheet);
17938 }
17939 else cur_sheet = (Directory[s] || {name:""}).name;
17940 if(val.dt == 0x20) out["!type"] = "chart";
17941 if(val.dt == 0x40) out["!type"] = "macro";
17942 merges = [];
17943 objects = [];
17944 opts.arrayf = arrayf = [];
17945 colinfo = []; rowinfo = [];
17946 defwidth = defheight = 0;
17947 seencol = false;
17948 wsprops = {Hidden:(Directory[s]||{hs:0}).hs, name:cur_sheet };
17949 } break;
17950
17951 case 'Number': case 'BIFF2NUM': case 'BIFF2INT': {
17952 if(out["!type"] == "chart") if(options.dense ? (out[val.r]||[])[val.c]: out[encode_cell({c:val.c, r:val.r})]) ++val.c;
17953 temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe]||{}, v:val.val, t:'n'});
17954 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
17955 safe_format_xf(temp_val, options, wb.opts.Date1904);
17956 addcell({c:val.c, r:val.r}, temp_val, options);
17957 } break;
17958 case 'BoolErr': {
17959 temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t});
17960 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
17961 safe_format_xf(temp_val, options, wb.opts.Date1904);
17962 addcell({c:val.c, r:val.r}, temp_val, options);
17963 } break;
17964 case 'RK': {
17965 temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'});
17966 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
17967 safe_format_xf(temp_val, options, wb.opts.Date1904);
17968 addcell({c:val.c, r:val.r}, temp_val, options);
17969 } break;
17970 case 'MulRk': {
17971 for(var j = val.c; j <= val.C; ++j) {
17972 var ixfe = val.rkrec[j-val.c][0];
17973 temp_val= ({ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'});
17974 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
17975 safe_format_xf(temp_val, options, wb.opts.Date1904);
17976 addcell({c:j, r:val.r}, temp_val, options);
17977 }
17978 } break;
17979 case 'Formula': {
17980 if(val.val == 'String') { last_formula = val; break; }
17981 temp_val = make_cell(val.val, val.cell.ixfe, val.tt);
17982 temp_val.XF = XFs[temp_val.ixfe];
17983 if(options.cellFormula) {
17984 var _f = val.formula;
17985 if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
17986 var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
17987 var _fe = encode_cell({r:_fr, c:_fc});
17988 if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
17989 else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F;
17990 } else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
17991 }
17992 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
17993 safe_format_xf(temp_val, options, wb.opts.Date1904);
17994 addcell(val.cell, temp_val, options);
17995 last_formula = val;
17996 } break;
17997 case 'String': {
17998 if(last_formula) { /* technically always true */
17999 last_formula.val = val;
18000 temp_val = make_cell(val, last_formula.cell.ixfe, 's');
18001 temp_val.XF = XFs[temp_val.ixfe];
18002 if(options.cellFormula) {
18003 temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
18004 }
18005 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
18006 safe_format_xf(temp_val, options, wb.opts.Date1904);
18007 addcell(last_formula.cell, temp_val, options);
18008 last_formula = null;
18009 } else throw new Error("String record expects Formula");
18010 } break;
18011 case 'Array': {
18012 arrayf.push(val);
18013 var _arraystart = encode_cell(val[0].s);
18014 cc = options.dense ? (out[val[0].s.r]||[])[val[0].s.c] : out[_arraystart];
18015 if(options.cellFormula && cc) {
18016 if(!last_formula) break; /* technically unreachable */
18017 if(!_arraystart || !cc) break;
18018 cc.f = ""+stringify_formula(val[1], range, val[0], supbooks, opts);
18019 cc.F = encode_range(val[0]);
18020 }
18021 } break;
18022 case 'ShrFmla': {
18023 if(!options.cellFormula) break;
18024 if(last_cell) {
18025 /* TODO: capture range */
18026 if(!last_formula) break; /* technically unreachable */
18027 sharedf[encode_cell(last_formula.cell)]= val[0];
18028 cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
18029 (cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
18030 }
18031 } break;
18032 case 'LabelSst':
18033 temp_val=make_cell(sst[val.isst].t, val.ixfe, 's');
18034 if(sst[val.isst].h) temp_val.h = sst[val.isst].h;
18035 temp_val.XF = XFs[temp_val.ixfe];
18036 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
18037 safe_format_xf(temp_val, options, wb.opts.Date1904);
18038 addcell({c:val.c, r:val.r}, temp_val, options);
18039 break;
18040 case 'Blank': if(options.sheetStubs) {
18041 temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'});
18042 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
18043 safe_format_xf(temp_val, options, wb.opts.Date1904);
18044 addcell({c:val.c, r:val.r}, temp_val, options);
18045 } break;
18046 case 'MulBlank': if(options.sheetStubs) {
18047 for(var _j = val.c; _j <= val.C; ++_j) {
18048 var _ixfe = val.ixfe[_j-val.c];
18049 temp_val= ({ixfe:_ixfe, XF:XFs[_ixfe], t:'z'});
18050 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
18051 safe_format_xf(temp_val, options, wb.opts.Date1904);
18052 addcell({c:_j, r:val.r}, temp_val, options);
18053 }
18054 } break;
18055 case 'RString':
18056 case 'Label': case 'BIFF2STR':
18057 temp_val=make_cell(val.val, val.ixfe, 's');
18058 temp_val.XF = XFs[temp_val.ixfe];
18059 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
18060 safe_format_xf(temp_val, options, wb.opts.Date1904);
18061 addcell({c:val.c, r:val.r}, temp_val, options);
18062 break;
18063
18064 case 'Dimensions': {
18065 if(file_depth === 1) range = val; /* TODO: stack */
18066 } break;
18067 case 'SST': {
18068 sst = val;
18069 } break;
18070 case 'Format': { /* val = [id, fmt] */
18071 if(opts.biff == 4) {
18072 BIFF2FmtTable[BIFF2Fmt++] = val[1];
18073 for(var b4idx = 0; b4idx < BIFF2Fmt + 163; ++b4idx) if(SSF._table[b4idx] == val[1]) break;
18074 if(b4idx >= 163) SSF.load(val[1], BIFF2Fmt + 163);
18075 }
18076 else SSF.load(val[1], val[0]);
18077 } break;
18078 case 'BIFF2FORMAT': {
18079 BIFF2FmtTable[BIFF2Fmt++] = val;
18080 for(var b2idx = 0; b2idx < BIFF2Fmt + 163; ++b2idx) if(SSF._table[b2idx] == val) break;
18081 if(b2idx >= 163) SSF.load(val, BIFF2Fmt + 163);
18082 } break;
18083
18084 case 'MergeCells': merges = merges.concat(val); break;
18085
18086 case 'Obj': objects[val.cmo[0]] = opts.lastobj = val; break;
18087 case 'TxO': opts.lastobj.TxO = val; break;
18088 case 'ImData': opts.lastobj.ImData = val; break;
18089
18090 case 'HLink': {
18091 for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
18092 for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
18093 cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
18094 if(cc) cc.l = val[1];
18095 }
18096 } break;
18097 case 'HLinkTooltip': {
18098 for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
18099 for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
18100 cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
18101 if(cc && cc.l) cc.l.Tooltip = val[1];
18102 }
18103 } break;
18104
18105 /* Comments */
18106 case 'Note': {
18107 if(opts.biff <= 5 && opts.biff >= 2) break; /* TODO: BIFF5 */
18108 cc = options.dense ? (out[val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
18109 var noteobj = objects[val[2]];
18110 if(!cc) {
18111 if(options.dense) {
18112 if(!out[val[0].r]) out[val[0].r] = [];
18113 cc = out[val[0].r][val[0].c] = ({t:"z"});
18114 } else {
18115 cc = out[encode_cell(val[0])] = ({t:"z"});
18116 }
18117 range.e.r = Math.max(range.e.r, val[0].r);
18118 range.s.r = Math.min(range.s.r, val[0].r);
18119 range.e.c = Math.max(range.e.c, val[0].c);
18120 range.s.c = Math.min(range.s.c, val[0].c);
18121 }
18122 if(!cc.c) cc.c = [];
18123 cmnt = {a:val[1],t:noteobj.TxO.t};
18124 cc.c.push(cmnt);
18125 } break;
18126
18127 default: switch(R.n) { /* nested */
18128 case 'ClrtClient': break;
18129 case 'XFExt': update_xfext(XFs[val.ixfe], val.ext); break;
18130
18131 case 'DefColWidth': defwidth = val; break;
18132 case 'DefaultRowHeight': defheight = val[1]; break; // TODO: flags
18133
18134 case 'ColInfo': {
18135 if(!opts.cellStyles) break;
18136 while(val.e >= val.s) {
18137 colinfo[val.e--] = { width: val.w/256, level: (val.level || 0), hidden: !!(val.flags & 1) };
18138 if(!seencol) { seencol = true; find_mdw_colw(val.w/256); }
18139 process_col(colinfo[val.e+1]);
18140 }
18141 } break;
18142 case 'Row': {
18143 var rowobj = {};
18144 if(val.level != null) { rowinfo[val.r] = rowobj; rowobj.level = val.level; }
18145 if(val.hidden) { rowinfo[val.r] = rowobj; rowobj.hidden = true; }
18146 if(val.hpt) {
18147 rowinfo[val.r] = rowobj;
18148 rowobj.hpt = val.hpt; rowobj.hpx = pt2px(val.hpt);
18149 }
18150 } break;
18151
18152 case 'LeftMargin':
18153 case 'RightMargin':
18154 case 'TopMargin':
18155 case 'BottomMargin':
18156 if(!out['!margins']) default_margins(out['!margins'] = {});
18157 out['!margins'][Rn.slice(0,-6).toLowerCase()] = val;
18158 break;
18159
18160 case 'Selection': break;
18161
18162 case 'Setup': // TODO
18163 if(!out['!margins']) default_margins(out['!margins'] = {});
18164 out['!margins'].header = val.header;
18165 out['!margins'].footer = val.footer;
18166 break;
18167
18168 case 'Window2': // TODO
18169 // $FlowIgnore
18170 if(val.RTL) Workbook.Views[0].RTL = true;
18171 break;
18172
18173 case 'Header': break; // TODO
18174 case 'Footer': break; // TODO
18175 case 'HCenter': break; // TODO
18176 case 'VCenter': break; // TODO
18177 case 'Pls': break; // TODO
18178 case 'GCW': break;
18179 case 'LHRecord': break;
18180 case 'DBCell': break; // TODO
18181 case 'EntExU2': break; // TODO
18182 case 'SxView': break; // TODO
18183 case 'Sxvd': break; // TODO
18184 case 'SXVI': break; // TODO
18185 case 'SXVDEx': break; // TODO
18186 case 'SxIvd': break; // TODO
18187 case 'SXString': break; // TODO
18188 case 'Sync': break;
18189 case 'Addin': break;
18190 case 'SXDI': break; // TODO
18191 case 'SXLI': break; // TODO
18192 case 'SXEx': break; // TODO
18193 case 'QsiSXTag': break; // TODO
18194 case 'Feat': break;
18195 case 'FeatHdr': case 'FeatHdr11': break;
18196 case 'Feature11': case 'Feature12': case 'List12': break;
18197 case 'Country': country = val; break;
18198 case 'RecalcId': break;
18199 case 'DxGCol': break; // TODO: htmlify
18200 case 'Fbi': case 'Fbi2': case 'GelFrame': break;
18201 case 'Font': break; // TODO
18202 case 'XFCRC': break; // TODO
18203 case 'Style': break; // TODO
18204 case 'StyleExt': break; // TODO
18205 case 'Palette': palette = val; break;
18206 case 'Theme': themes = val; break;
18207 /* Protection */
18208 case 'ScenarioProtect': break;
18209 case 'ObjProtect': break;
18210
18211 /* Conditional Formatting */
18212 case 'CondFmt12': break;
18213
18214 /* Table */
18215 case 'Table': break; // TODO
18216 case 'TableStyles': break; // TODO
18217 case 'TableStyle': break; // TODO
18218 case 'TableStyleElement': break; // TODO
18219
18220 /* PivotTable */
18221 case 'SXStreamID': break; // TODO
18222 case 'SXVS': break; // TODO
18223 case 'DConRef': break; // TODO
18224 case 'SXAddl': break; // TODO
18225 case 'DConBin': break; // TODO
18226 case 'DConName': break; // TODO
18227 case 'SXPI': break; // TODO
18228 case 'SxFormat': break; // TODO
18229 case 'SxSelect': break; // TODO
18230 case 'SxRule': break; // TODO
18231 case 'SxFilt': break; // TODO
18232 case 'SxItm': break; // TODO
18233 case 'SxDXF': break; // TODO
18234
18235 /* Scenario Manager */
18236 case 'ScenMan': break;
18237
18238 /* Data Consolidation */
18239 case 'DCon': break;
18240
18241 /* Watched Cell */
18242 case 'CellWatch': break;
18243
18244 /* Print Settings */
18245 case 'PrintRowCol': break;
18246 case 'PrintGrid': break;
18247 case 'PrintSize': break;
18248
18249 case 'XCT': break;
18250 case 'CRN': break;
18251
18252 case 'Scl': {
18253 //console.log("Zoom Level:", val[0]/val[1],val);
18254 } break;
18255 case 'SheetExt': {
18256 /* empty */
18257 } break;
18258 case 'SheetExtOptional': {
18259 /* empty */
18260 } break;
18261
18262 /* VBA */
18263 case 'ObNoMacros': {
18264 /* empty */
18265 } break;
18266 case 'ObProj': {
18267 /* empty */
18268 } break;
18269 case 'CodeName': {
18270if(!cur_sheet) Workbook.WBProps.CodeName = val || "ThisWorkbook";
18271 else wsprops.CodeName = val || wsprops.name;
18272 } break;
18273 case 'GUIDTypeLib': {
18274 /* empty */
18275 } break;
18276
18277 case 'WOpt': break; // TODO: WTF?
18278 case 'PhoneticInfo': break;
18279
18280 case 'OleObjectSize': break;
18281
18282 /* Differential Formatting */
18283 case 'DXF': case 'DXFN': case 'DXFN12': case 'DXFN12List': case 'DXFN12NoCB': break;
18284
18285 /* Data Validation */
18286 case 'Dv': case 'DVal': break;
18287
18288 /* Data Series */
18289 case 'BRAI': case 'Series': case 'SeriesText': break;
18290
18291 /* Data Connection */
18292 case 'DConn': break;
18293 case 'DbOrParamQry': break;
18294 case 'DBQueryExt': break;
18295
18296 case 'OleDbConn': break;
18297 case 'ExtString': break;
18298
18299 /* Formatting */
18300 case 'IFmtRecord': break;
18301 case 'CondFmt': case 'CF': case 'CF12': case 'CFEx': break;
18302
18303 /* Explicitly Ignored */
18304 case 'Excel9File': break;
18305 case 'Units': break;
18306 case 'InterfaceHdr': case 'Mms': case 'InterfaceEnd': case 'DSF': break;
18307 case 'BuiltInFnGroupCount': /* 2.4.30 0x0E or 0x10 but excel 2011 generates 0x11? */ break;
18308 /* View Stuff */
18309 case 'Window1': case 'HideObj': case 'GridSet': case 'Guts':
18310 case 'UserBView': case 'UserSViewBegin': case 'UserSViewEnd': break;
18311 case 'Pane': break;
18312 default: switch(R.n) { /* nested */
18313 /* Chart */
18314 case 'Dat':
18315 case 'Begin': case 'End':
18316 case 'StartBlock': case 'EndBlock':
18317 case 'Frame': case 'Area':
18318 case 'Axis': case 'AxisLine': case 'Tick': break;
18319 case 'AxesUsed':
18320 case 'CrtLayout12': case 'CrtLayout12A': case 'CrtLink': case 'CrtLine': case 'CrtMlFrt': case 'CrtMlFrtContinue': break;
18321 case 'LineFormat': case 'AreaFormat':
18322 case 'Chart': case 'Chart3d': case 'Chart3DBarShape': case 'ChartFormat': case 'ChartFrtInfo': break;
18323 case 'PlotArea': case 'PlotGrowth': break;
18324 case 'SeriesList': case 'SerParent': case 'SerAuxTrend': break;
18325 case 'DataFormat': case 'SerToCrt': case 'FontX': break;
18326 case 'CatSerRange': case 'AxcExt': case 'SerFmt': break;
18327 case 'ShtProps': break;
18328 case 'DefaultText': case 'Text': case 'CatLab': break;
18329 case 'DataLabExtContents': break;
18330 case 'Legend': case 'LegendException': break;
18331 case 'Pie': case 'Scatter': break;
18332 case 'PieFormat': case 'MarkerFormat': break;
18333 case 'StartObject': case 'EndObject': break;
18334 case 'AlRuns': case 'ObjectLink': break;
18335 case 'SIIndex': break;
18336 case 'AttachedLabel': case 'YMult': break;
18337
18338 /* Chart Group */
18339 case 'Line': case 'Bar': break;
18340 case 'Surf': break;
18341
18342 /* Axis Group */
18343 case 'AxisParent': break;
18344 case 'Pos': break;
18345 case 'ValueRange': break;
18346
18347 /* Pivot Chart */
18348 case 'SXViewEx9': break; // TODO
18349 case 'SXViewLink': break;
18350 case 'PivotChartBits': break;
18351 case 'SBaseRef': break;
18352 case 'TextPropsStream': break;
18353
18354 /* Chart Misc */
18355 case 'LnExt': break;
18356 case 'MkrExt': break;
18357 case 'CrtCoopt': break;
18358
18359 /* Query Table */
18360 case 'Qsi': case 'Qsif': case 'Qsir': case 'QsiSXTag': break;
18361 case 'TxtQry': break;
18362
18363 /* Filter */
18364 case 'FilterMode': break;
18365 case 'AutoFilter': case 'AutoFilterInfo': break;
18366 case 'AutoFilter12': break;
18367 case 'DropDownObjIds': break;
18368 case 'Sort': break;
18369 case 'SortData': break;
18370
18371 /* Drawing */
18372 case 'ShapePropsStream': break;
18373 case 'MsoDrawing': case 'MsoDrawingGroup': case 'MsoDrawingSelection': break;
18374 /* Pub Stuff */
18375 case 'WebPub': case 'AutoWebPub': break;
18376
18377 /* Print Stuff */
18378 case 'HeaderFooter': case 'HFPicture': case 'PLV':
18379 case 'HorizontalPageBreaks': case 'VerticalPageBreaks': break;
18380 /* Behavioral */
18381 case 'Backup': case 'CompressPictures': case 'Compat12': break;
18382
18383 /* Should not Happen */
18384 case 'Continue': case 'ContinueFrt12': break;
18385
18386 /* Future Records */
18387 case 'FrtFontList': case 'FrtWrapper': break;
18388
18389 default: switch(R.n) { /* nested */
18390 /* BIFF5 records */
18391 case 'TabIdConf': case 'Radar': case 'RadarArea': case 'DropBar': case 'Intl': case 'CoordList': case 'SerAuxErrBar': break;
18392
18393 /* BIFF2-4 records */
18394 case 'BIFF2FONTCLR': case 'BIFF2FMTCNT': case 'BIFF2FONTXTRA': break;
18395 case 'BIFF2XF': case 'BIFF3XF': case 'BIFF4XF': break;
18396 case 'BIFF2XFINDEX': break;
18397 case 'BIFF4FMTCNT': case 'BIFF2ROW': case 'BIFF2WINDOW2': break;
18398
18399 /* Miscellaneous */
18400 case 'SCENARIO': case 'DConBin': case 'PicF': case 'DataLabExt':
18401 case 'Lel': case 'BopPop': case 'BopPopCustom': case 'RealTimeData':
18402 case 'Name': break;
18403 case 'LHNGraph': case 'FnGroupName': case 'AddMenu': case 'LPr': break;
18404 case 'ListObj': case 'ListField': break;
18405 case 'RRSort': break;
18406 case 'BigName': break;
18407 case 'ToolbarHdr': case 'ToolbarEnd': break;
18408 case 'DDEObjName': break;
18409 case 'FRTArchId$': break;
18410 default: if(options.WTF) throw 'Unrecognized Record ' + R.n;
18411 }}}}
18412 } else blob.l += length;
18413 }
18414 wb.SheetNames=keys(Directory).sort(function(a,b) { return Number(a) - Number(b); }).map(function(x){return Directory[x].name;});
18415 if(!options.bookSheets) wb.Sheets=Sheets;
18416 if(!wb.SheetNames.length && Preamble["!ref"]) {
18417 wb.SheetNames.push("Sheet1");
18418 if(wb.Sheets) wb.Sheets["Sheet1"] = Preamble;
18419 } else wb.Preamble=Preamble;
18420 if(wb.Sheets) FilterDatabases.forEach(function(r,i) { wb.Sheets[wb.SheetNames[i]]['!autofilter'] = r; });
18421 wb.Strings = sst;
18422 wb.SSF = SSF.get_table();
18423 if(opts.enc) wb.Encryption = opts.enc;
18424 if(themes) wb.Themes = themes;
18425 wb.Metadata = {};
18426 if(country !== undefined) wb.Metadata.Country = country;
18427 if(supbooks.names.length > 0) Workbook.Names = supbooks.names;
18428 wb.Workbook = Workbook;
18429 return wb;
18430}
18431
18432/* TODO: split props*/
18433var PSCLSID = {
18434 SI: "e0859ff2f94f6810ab9108002b27b3d9",
18435 DSI: "02d5cdd59c2e1b10939708002b2cf9ae",
18436 UDI: "05d5cdd59c2e1b10939708002b2cf9ae"
18437};
18438function parse_xls_props(cfb, props, o) {
18439 /* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
18440 var DSI = CFB.find(cfb, '!DocumentSummaryInformation');
18441 if(DSI && DSI.size > 0) try {
18442 var DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI, PSCLSID.DSI);
18443 for(var d in DocSummary) props[d] = DocSummary[d];
18444 } catch(e) {if(o.WTF) throw e;/* empty */}
18445
18446 /* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
18447 var SI = CFB.find(cfb, '!SummaryInformation');
18448 if(SI && SI.size > 0) try {
18449 var Summary = parse_PropertySetStream(SI, SummaryPIDSI, PSCLSID.SI);
18450 for(var s in Summary) if(props[s] == null) props[s] = Summary[s];
18451 } catch(e) {if(o.WTF) throw e;/* empty */}
18452
18453 if(props.HeadingPairs && props.TitlesOfParts) {
18454 load_props_pairs(props.HeadingPairs, props.TitlesOfParts, props, o);
18455 delete props.HeadingPairs; delete props.TitlesOfParts;
18456 }
18457}
18458function write_xls_props(wb, cfb) {
18459 var DSEntries = [], SEntries = [], CEntries = [];
18460 var i = 0, Keys;
18461 if(wb.Props) {
18462 Keys = keys(wb.Props);
18463 // $FlowIgnore
18464 for(i = 0; i < Keys.length; ++i) (Object.prototype.hasOwnProperty.call(DocSummaryRE, Keys[i]) ? DSEntries : Object.prototype.hasOwnProperty.call(SummaryRE, Keys[i]) ? SEntries : CEntries).push([Keys[i], wb.Props[Keys[i]]]);
18465 }
18466 if(wb.Custprops) {
18467 Keys = keys(wb.Custprops);
18468 // $FlowIgnore
18469 for(i = 0; i < Keys.length; ++i) if(!Object.prototype.hasOwnProperty.call((wb.Props||{}), Keys[i])) (Object.prototype.hasOwnProperty.call(DocSummaryRE, Keys[i]) ? DSEntries : Object.prototype.hasOwnProperty.call(SummaryRE, Keys[i]) ? SEntries : CEntries).push([Keys[i], wb.Custprops[Keys[i]]]);
18470 }
18471 var CEntries2 = [];
18472 for(i = 0; i < CEntries.length; ++i) {
18473 if(XLSPSSkip.indexOf(CEntries[i][0]) > -1) continue;
18474 if(CEntries[i][1] == null) continue;
18475 CEntries2.push(CEntries[i]);
18476 }
18477 if(SEntries.length) CFB.utils.cfb_add(cfb, "/\u0005SummaryInformation", write_PropertySetStream(SEntries, PSCLSID.SI, SummaryRE, SummaryPIDSI));
18478 if(DSEntries.length || CEntries2.length) CFB.utils.cfb_add(cfb, "/\u0005DocumentSummaryInformation", write_PropertySetStream(DSEntries, PSCLSID.DSI, DocSummaryRE, DocSummaryPIDDSI, CEntries2.length ? CEntries2 : null, PSCLSID.UDI));
18479}
18480
18481function parse_xlscfb(cfb, options) {
18482if(!options) options = {};
18483fix_read_opts(options);
18484reset_cp();
18485if(options.codepage) set_ansi(options.codepage);
18486var CompObj, WB;
18487if(cfb.FullPaths) {
18488 if(CFB.find(cfb, '/encryption')) throw new Error("File is password-protected");
18489 CompObj = CFB.find(cfb, '!CompObj');
18490 WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
18491} else {
18492 switch(options.type) {
18493 case 'base64': cfb = s2a(Base64.decode(cfb)); break;
18494 case 'binary': cfb = s2a(cfb); break;
18495 case 'buffer': break;
18496 case 'array': if(!Array.isArray(cfb)) cfb = Array.prototype.slice.call(cfb); break;
18497 }
18498 prep_blob(cfb, 0);
18499 WB = ({content: cfb});
18500}
18501var WorkbookP;
18502
18503var _data;
18504if(CompObj) parse_compobj(CompObj);
18505if(options.bookProps && !options.bookSheets) WorkbookP = ({});
18506else {
18507 var T = has_buf ? 'buffer' : 'array';
18508 if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options);
18509 /* Quattro Pro 7-8 */
18510 else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
18511 /* Quattro Pro 9 */
18512 else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
18513 else throw new Error("Cannot find Workbook stream");
18514 if(options.bookVBA && cfb.FullPaths && CFB.find(cfb, '/_VBA_PROJECT_CUR/VBA/dir')) WorkbookP.vbaraw = make_vba_xls(cfb);
18515}
18516
18517var props = {};
18518if(cfb.FullPaths) parse_xls_props(cfb, props, options);
18519
18520WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
18521if(options.bookFiles) WorkbookP.cfb = cfb;
18522/*WorkbookP.CompObjP = CompObjP; // TODO: storage? */
18523return WorkbookP;
18524}
18525
18526
18527function write_xlscfb(wb, opts) {
18528 var o = opts || {};
18529 var cfb = CFB.utils.cfb_new({root:"R"});
18530 var wbpath = "/Workbook";
18531 switch(o.bookType || "xls") {
18532 case "xls": o.bookType = "biff8";
18533 /* falls through */
18534 case "xla": if(!o.bookType) o.bookType = "xla";
18535 /* falls through */
18536 case "biff8": wbpath = "/Workbook"; o.biff = 8; break;
18537 case "biff5": wbpath = "/Book"; o.biff = 5; break;
18538 default: throw new Error("invalid type " + o.bookType + " for XLS CFB");
18539 }
18540 CFB.utils.cfb_add(cfb, wbpath, write_biff_buf(wb, o));
18541 if(o.biff == 8 && (wb.Props || wb.Custprops)) write_xls_props(wb, cfb);
18542 // TODO: SI, DSI, CO
18543 if(o.biff == 8 && wb.vbaraw) fill_vba_xls(cfb, CFB.read(wb.vbaraw, {type: typeof wb.vbaraw == "string" ? "binary" : "buffer"}));
18544 return cfb;
18545}
18546/* [MS-XLSB] 2.3 Record Enumeration */
18547var XLSBRecordEnum = {
185480x0000: { n:"BrtRowHdr", f:parse_BrtRowHdr },
185490x0001: { n:"BrtCellBlank", f:parse_BrtCellBlank },
185500x0002: { n:"BrtCellRk", f:parse_BrtCellRk },
185510x0003: { n:"BrtCellError", f:parse_BrtCellError },
185520x0004: { n:"BrtCellBool", f:parse_BrtCellBool },
185530x0005: { n:"BrtCellReal", f:parse_BrtCellReal },
185540x0006: { n:"BrtCellSt", f:parse_BrtCellSt },
185550x0007: { n:"BrtCellIsst", f:parse_BrtCellIsst },
185560x0008: { n:"BrtFmlaString", f:parse_BrtFmlaString },
185570x0009: { n:"BrtFmlaNum", f:parse_BrtFmlaNum },
185580x000A: { n:"BrtFmlaBool", f:parse_BrtFmlaBool },
185590x000B: { n:"BrtFmlaError", f:parse_BrtFmlaError },
185600x000C: { n:"BrtShortBlank", f:parse_BrtShortBlank },
185610x000D: { n:"BrtShortRk", f:parse_BrtShortRk },
185620x000E: { n:"BrtShortError", f:parse_BrtShortError },
185630x000F: { n:"BrtShortBool", f:parse_BrtShortBool },
185640x0010: { n:"BrtShortReal", f:parse_BrtShortReal },
185650x0011: { n:"BrtShortSt", f:parse_BrtShortSt },
185660x0012: { n:"BrtShortIsst", f:parse_BrtShortIsst },
185670x0013: { n:"BrtSSTItem", f:parse_RichStr },
185680x0014: { n:"BrtPCDIMissing" },
185690x0015: { n:"BrtPCDINumber" },
185700x0016: { n:"BrtPCDIBoolean" },
185710x0017: { n:"BrtPCDIError" },
185720x0018: { n:"BrtPCDIString" },
185730x0019: { n:"BrtPCDIDatetime" },
185740x001A: { n:"BrtPCDIIndex" },
185750x001B: { n:"BrtPCDIAMissing" },
185760x001C: { n:"BrtPCDIANumber" },
185770x001D: { n:"BrtPCDIABoolean" },
185780x001E: { n:"BrtPCDIAError" },
185790x001F: { n:"BrtPCDIAString" },
185800x0020: { n:"BrtPCDIADatetime" },
185810x0021: { n:"BrtPCRRecord" },
185820x0022: { n:"BrtPCRRecordDt" },
185830x0023: { n:"BrtFRTBegin" },
185840x0024: { n:"BrtFRTEnd" },
185850x0025: { n:"BrtACBegin" },
185860x0026: { n:"BrtACEnd" },
185870x0027: { n:"BrtName", f:parse_BrtName },
185880x0028: { n:"BrtIndexRowBlock" },
185890x002A: { n:"BrtIndexBlock" },
185900x002B: { n:"BrtFont", f:parse_BrtFont },
185910x002C: { n:"BrtFmt", f:parse_BrtFmt },
185920x002D: { n:"BrtFill", f:parse_BrtFill },
185930x002E: { n:"BrtBorder", f:parse_BrtBorder },
185940x002F: { n:"BrtXF", f:parse_BrtXF },
185950x0030: { n:"BrtStyle" },
185960x0031: { n:"BrtCellMeta" },
185970x0032: { n:"BrtValueMeta" },
185980x0033: { n:"BrtMdb" },
185990x0034: { n:"BrtBeginFmd" },
186000x0035: { n:"BrtEndFmd" },
186010x0036: { n:"BrtBeginMdx" },
186020x0037: { n:"BrtEndMdx" },
186030x0038: { n:"BrtBeginMdxTuple" },
186040x0039: { n:"BrtEndMdxTuple" },
186050x003A: { n:"BrtMdxMbrIstr" },
186060x003B: { n:"BrtStr" },
186070x003C: { n:"BrtColInfo", f:parse_ColInfo },
186080x003E: { n:"BrtCellRString" },
186090x003F: { n:"BrtCalcChainItem$", f:parse_BrtCalcChainItem$ },
186100x0040: { n:"BrtDVal", f:parse_BrtDVal },
186110x0041: { n:"BrtSxvcellNum" },
186120x0042: { n:"BrtSxvcellStr" },
186130x0043: { n:"BrtSxvcellBool" },
186140x0044: { n:"BrtSxvcellErr" },
186150x0045: { n:"BrtSxvcellDate" },
186160x0046: { n:"BrtSxvcellNil" },
186170x0080: { n:"BrtFileVersion" },
186180x0081: { n:"BrtBeginSheet" },
186190x0082: { n:"BrtEndSheet" },
186200x0083: { n:"BrtBeginBook", f:parsenoop, p:0 },
186210x0084: { n:"BrtEndBook" },
186220x0085: { n:"BrtBeginWsViews" },
186230x0086: { n:"BrtEndWsViews" },
186240x0087: { n:"BrtBeginBookViews" },
186250x0088: { n:"BrtEndBookViews" },
186260x0089: { n:"BrtBeginWsView", f:parse_BrtBeginWsView },
186270x008A: { n:"BrtEndWsView" },
186280x008B: { n:"BrtBeginCsViews" },
186290x008C: { n:"BrtEndCsViews" },
186300x008D: { n:"BrtBeginCsView" },
186310x008E: { n:"BrtEndCsView" },
186320x008F: { n:"BrtBeginBundleShs" },
186330x0090: { n:"BrtEndBundleShs" },
186340x0091: { n:"BrtBeginSheetData" },
186350x0092: { n:"BrtEndSheetData" },
186360x0093: { n:"BrtWsProp", f:parse_BrtWsProp },
186370x0094: { n:"BrtWsDim", f:parse_BrtWsDim, p:16 },
186380x0097: { n:"BrtPane", f:parse_BrtPane },
186390x0098: { n:"BrtSel" },
186400x0099: { n:"BrtWbProp", f:parse_BrtWbProp },
186410x009A: { n:"BrtWbFactoid" },
186420x009B: { n:"BrtFileRecover" },
186430x009C: { n:"BrtBundleSh", f:parse_BrtBundleSh },
186440x009D: { n:"BrtCalcProp" },
186450x009E: { n:"BrtBookView" },
186460x009F: { n:"BrtBeginSst", f:parse_BrtBeginSst },
186470x00A0: { n:"BrtEndSst" },
186480x00A1: { n:"BrtBeginAFilter", f:parse_UncheckedRfX },
186490x00A2: { n:"BrtEndAFilter" },
186500x00A3: { n:"BrtBeginFilterColumn" },
186510x00A4: { n:"BrtEndFilterColumn" },
186520x00A5: { n:"BrtBeginFilters" },
186530x00A6: { n:"BrtEndFilters" },
186540x00A7: { n:"BrtFilter" },
186550x00A8: { n:"BrtColorFilter" },
186560x00A9: { n:"BrtIconFilter" },
186570x00AA: { n:"BrtTop10Filter" },
186580x00AB: { n:"BrtDynamicFilter" },
186590x00AC: { n:"BrtBeginCustomFilters" },
186600x00AD: { n:"BrtEndCustomFilters" },
186610x00AE: { n:"BrtCustomFilter" },
186620x00AF: { n:"BrtAFilterDateGroupItem" },
186630x00B0: { n:"BrtMergeCell", f:parse_BrtMergeCell },
186640x00B1: { n:"BrtBeginMergeCells" },
186650x00B2: { n:"BrtEndMergeCells" },
186660x00B3: { n:"BrtBeginPivotCacheDef" },
186670x00B4: { n:"BrtEndPivotCacheDef" },
186680x00B5: { n:"BrtBeginPCDFields" },
186690x00B6: { n:"BrtEndPCDFields" },
186700x00B7: { n:"BrtBeginPCDField" },
186710x00B8: { n:"BrtEndPCDField" },
186720x00B9: { n:"BrtBeginPCDSource" },
186730x00BA: { n:"BrtEndPCDSource" },
186740x00BB: { n:"BrtBeginPCDSRange" },
186750x00BC: { n:"BrtEndPCDSRange" },
186760x00BD: { n:"BrtBeginPCDFAtbl" },
186770x00BE: { n:"BrtEndPCDFAtbl" },
186780x00BF: { n:"BrtBeginPCDIRun" },
186790x00C0: { n:"BrtEndPCDIRun" },
186800x00C1: { n:"BrtBeginPivotCacheRecords" },
186810x00C2: { n:"BrtEndPivotCacheRecords" },
186820x00C3: { n:"BrtBeginPCDHierarchies" },
186830x00C4: { n:"BrtEndPCDHierarchies" },
186840x00C5: { n:"BrtBeginPCDHierarchy" },
186850x00C6: { n:"BrtEndPCDHierarchy" },
186860x00C7: { n:"BrtBeginPCDHFieldsUsage" },
186870x00C8: { n:"BrtEndPCDHFieldsUsage" },
186880x00C9: { n:"BrtBeginExtConnection" },
186890x00CA: { n:"BrtEndExtConnection" },
186900x00CB: { n:"BrtBeginECDbProps" },
186910x00CC: { n:"BrtEndECDbProps" },
186920x00CD: { n:"BrtBeginECOlapProps" },
186930x00CE: { n:"BrtEndECOlapProps" },
186940x00CF: { n:"BrtBeginPCDSConsol" },
186950x00D0: { n:"BrtEndPCDSConsol" },
186960x00D1: { n:"BrtBeginPCDSCPages" },
186970x00D2: { n:"BrtEndPCDSCPages" },
186980x00D3: { n:"BrtBeginPCDSCPage" },
186990x00D4: { n:"BrtEndPCDSCPage" },
187000x00D5: { n:"BrtBeginPCDSCPItem" },
187010x00D6: { n:"BrtEndPCDSCPItem" },
187020x00D7: { n:"BrtBeginPCDSCSets" },
187030x00D8: { n:"BrtEndPCDSCSets" },
187040x00D9: { n:"BrtBeginPCDSCSet" },
187050x00DA: { n:"BrtEndPCDSCSet" },
187060x00DB: { n:"BrtBeginPCDFGroup" },
187070x00DC: { n:"BrtEndPCDFGroup" },
187080x00DD: { n:"BrtBeginPCDFGItems" },
187090x00DE: { n:"BrtEndPCDFGItems" },
187100x00DF: { n:"BrtBeginPCDFGRange" },
187110x00E0: { n:"BrtEndPCDFGRange" },
187120x00E1: { n:"BrtBeginPCDFGDiscrete" },
187130x00E2: { n:"BrtEndPCDFGDiscrete" },
187140x00E3: { n:"BrtBeginPCDSDTupleCache" },
187150x00E4: { n:"BrtEndPCDSDTupleCache" },
187160x00E5: { n:"BrtBeginPCDSDTCEntries" },
187170x00E6: { n:"BrtEndPCDSDTCEntries" },
187180x00E7: { n:"BrtBeginPCDSDTCEMembers" },
187190x00E8: { n:"BrtEndPCDSDTCEMembers" },
187200x00E9: { n:"BrtBeginPCDSDTCEMember" },
187210x00EA: { n:"BrtEndPCDSDTCEMember" },
187220x00EB: { n:"BrtBeginPCDSDTCQueries" },
187230x00EC: { n:"BrtEndPCDSDTCQueries" },
187240x00ED: { n:"BrtBeginPCDSDTCQuery" },
187250x00EE: { n:"BrtEndPCDSDTCQuery" },
187260x00EF: { n:"BrtBeginPCDSDTCSets" },
187270x00F0: { n:"BrtEndPCDSDTCSets" },
187280x00F1: { n:"BrtBeginPCDSDTCSet" },
187290x00F2: { n:"BrtEndPCDSDTCSet" },
187300x00F3: { n:"BrtBeginPCDCalcItems" },
187310x00F4: { n:"BrtEndPCDCalcItems" },
187320x00F5: { n:"BrtBeginPCDCalcItem" },
187330x00F6: { n:"BrtEndPCDCalcItem" },
187340x00F7: { n:"BrtBeginPRule" },
187350x00F8: { n:"BrtEndPRule" },
187360x00F9: { n:"BrtBeginPRFilters" },
187370x00FA: { n:"BrtEndPRFilters" },
187380x00FB: { n:"BrtBeginPRFilter" },
187390x00FC: { n:"BrtEndPRFilter" },
187400x00FD: { n:"BrtBeginPNames" },
187410x00FE: { n:"BrtEndPNames" },
187420x00FF: { n:"BrtBeginPName" },
187430x0100: { n:"BrtEndPName" },
187440x0101: { n:"BrtBeginPNPairs" },
187450x0102: { n:"BrtEndPNPairs" },
187460x0103: { n:"BrtBeginPNPair" },
187470x0104: { n:"BrtEndPNPair" },
187480x0105: { n:"BrtBeginECWebProps" },
187490x0106: { n:"BrtEndECWebProps" },
187500x0107: { n:"BrtBeginEcWpTables" },
187510x0108: { n:"BrtEndECWPTables" },
187520x0109: { n:"BrtBeginECParams" },
187530x010A: { n:"BrtEndECParams" },
187540x010B: { n:"BrtBeginECParam" },
187550x010C: { n:"BrtEndECParam" },
187560x010D: { n:"BrtBeginPCDKPIs" },
187570x010E: { n:"BrtEndPCDKPIs" },
187580x010F: { n:"BrtBeginPCDKPI" },
187590x0110: { n:"BrtEndPCDKPI" },
187600x0111: { n:"BrtBeginDims" },
187610x0112: { n:"BrtEndDims" },
187620x0113: { n:"BrtBeginDim" },
187630x0114: { n:"BrtEndDim" },
187640x0115: { n:"BrtIndexPartEnd" },
187650x0116: { n:"BrtBeginStyleSheet" },
187660x0117: { n:"BrtEndStyleSheet" },
187670x0118: { n:"BrtBeginSXView" },
187680x0119: { n:"BrtEndSXVI" },
187690x011A: { n:"BrtBeginSXVI" },
187700x011B: { n:"BrtBeginSXVIs" },
187710x011C: { n:"BrtEndSXVIs" },
187720x011D: { n:"BrtBeginSXVD" },
187730x011E: { n:"BrtEndSXVD" },
187740x011F: { n:"BrtBeginSXVDs" },
187750x0120: { n:"BrtEndSXVDs" },
187760x0121: { n:"BrtBeginSXPI" },
187770x0122: { n:"BrtEndSXPI" },
187780x0123: { n:"BrtBeginSXPIs" },
187790x0124: { n:"BrtEndSXPIs" },
187800x0125: { n:"BrtBeginSXDI" },
187810x0126: { n:"BrtEndSXDI" },
187820x0127: { n:"BrtBeginSXDIs" },
187830x0128: { n:"BrtEndSXDIs" },
187840x0129: { n:"BrtBeginSXLI" },
187850x012A: { n:"BrtEndSXLI" },
187860x012B: { n:"BrtBeginSXLIRws" },
187870x012C: { n:"BrtEndSXLIRws" },
187880x012D: { n:"BrtBeginSXLICols" },
187890x012E: { n:"BrtEndSXLICols" },
187900x012F: { n:"BrtBeginSXFormat" },
187910x0130: { n:"BrtEndSXFormat" },
187920x0131: { n:"BrtBeginSXFormats" },
187930x0132: { n:"BrtEndSxFormats" },
187940x0133: { n:"BrtBeginSxSelect" },
187950x0134: { n:"BrtEndSxSelect" },
187960x0135: { n:"BrtBeginISXVDRws" },
187970x0136: { n:"BrtEndISXVDRws" },
187980x0137: { n:"BrtBeginISXVDCols" },
187990x0138: { n:"BrtEndISXVDCols" },
188000x0139: { n:"BrtEndSXLocation" },
188010x013A: { n:"BrtBeginSXLocation" },
188020x013B: { n:"BrtEndSXView" },
188030x013C: { n:"BrtBeginSXTHs" },
188040x013D: { n:"BrtEndSXTHs" },
188050x013E: { n:"BrtBeginSXTH" },
188060x013F: { n:"BrtEndSXTH" },
188070x0140: { n:"BrtBeginISXTHRws" },
188080x0141: { n:"BrtEndISXTHRws" },
188090x0142: { n:"BrtBeginISXTHCols" },
188100x0143: { n:"BrtEndISXTHCols" },
188110x0144: { n:"BrtBeginSXTDMPS" },
188120x0145: { n:"BrtEndSXTDMPs" },
188130x0146: { n:"BrtBeginSXTDMP" },
188140x0147: { n:"BrtEndSXTDMP" },
188150x0148: { n:"BrtBeginSXTHItems" },
188160x0149: { n:"BrtEndSXTHItems" },
188170x014A: { n:"BrtBeginSXTHItem" },
188180x014B: { n:"BrtEndSXTHItem" },
188190x014C: { n:"BrtBeginMetadata" },
188200x014D: { n:"BrtEndMetadata" },
188210x014E: { n:"BrtBeginEsmdtinfo" },
188220x014F: { n:"BrtMdtinfo" },
188230x0150: { n:"BrtEndEsmdtinfo" },
188240x0151: { n:"BrtBeginEsmdb" },
188250x0152: { n:"BrtEndEsmdb" },
188260x0153: { n:"BrtBeginEsfmd" },
188270x0154: { n:"BrtEndEsfmd" },
188280x0155: { n:"BrtBeginSingleCells" },
188290x0156: { n:"BrtEndSingleCells" },
188300x0157: { n:"BrtBeginList" },
188310x0158: { n:"BrtEndList" },
188320x0159: { n:"BrtBeginListCols" },
188330x015A: { n:"BrtEndListCols" },
188340x015B: { n:"BrtBeginListCol" },
188350x015C: { n:"BrtEndListCol" },
188360x015D: { n:"BrtBeginListXmlCPr" },
188370x015E: { n:"BrtEndListXmlCPr" },
188380x015F: { n:"BrtListCCFmla" },
188390x0160: { n:"BrtListTrFmla" },
188400x0161: { n:"BrtBeginExternals" },
188410x0162: { n:"BrtEndExternals" },
188420x0163: { n:"BrtSupBookSrc", f:parse_RelID},
188430x0165: { n:"BrtSupSelf" },
188440x0166: { n:"BrtSupSame" },
188450x0167: { n:"BrtSupTabs" },
188460x0168: { n:"BrtBeginSupBook" },
188470x0169: { n:"BrtPlaceholderName" },
188480x016A: { n:"BrtExternSheet", f:parse_ExternSheet },
188490x016B: { n:"BrtExternTableStart" },
188500x016C: { n:"BrtExternTableEnd" },
188510x016E: { n:"BrtExternRowHdr" },
188520x016F: { n:"BrtExternCellBlank" },
188530x0170: { n:"BrtExternCellReal" },
188540x0171: { n:"BrtExternCellBool" },
188550x0172: { n:"BrtExternCellError" },
188560x0173: { n:"BrtExternCellString" },
188570x0174: { n:"BrtBeginEsmdx" },
188580x0175: { n:"BrtEndEsmdx" },
188590x0176: { n:"BrtBeginMdxSet" },
188600x0177: { n:"BrtEndMdxSet" },
188610x0178: { n:"BrtBeginMdxMbrProp" },
188620x0179: { n:"BrtEndMdxMbrProp" },
188630x017A: { n:"BrtBeginMdxKPI" },
188640x017B: { n:"BrtEndMdxKPI" },
188650x017C: { n:"BrtBeginEsstr" },
188660x017D: { n:"BrtEndEsstr" },
188670x017E: { n:"BrtBeginPRFItem" },
188680x017F: { n:"BrtEndPRFItem" },
188690x0180: { n:"BrtBeginPivotCacheIDs" },
188700x0181: { n:"BrtEndPivotCacheIDs" },
188710x0182: { n:"BrtBeginPivotCacheID" },
188720x0183: { n:"BrtEndPivotCacheID" },
188730x0184: { n:"BrtBeginISXVIs" },
188740x0185: { n:"BrtEndISXVIs" },
188750x0186: { n:"BrtBeginColInfos" },
188760x0187: { n:"BrtEndColInfos" },
188770x0188: { n:"BrtBeginRwBrk" },
188780x0189: { n:"BrtEndRwBrk" },
188790x018A: { n:"BrtBeginColBrk" },
188800x018B: { n:"BrtEndColBrk" },
188810x018C: { n:"BrtBrk" },
188820x018D: { n:"BrtUserBookView" },
188830x018E: { n:"BrtInfo" },
188840x018F: { n:"BrtCUsr" },
188850x0190: { n:"BrtUsr" },
188860x0191: { n:"BrtBeginUsers" },
188870x0193: { n:"BrtEOF" },
188880x0194: { n:"BrtUCR" },
188890x0195: { n:"BrtRRInsDel" },
188900x0196: { n:"BrtRREndInsDel" },
188910x0197: { n:"BrtRRMove" },
188920x0198: { n:"BrtRREndMove" },
188930x0199: { n:"BrtRRChgCell" },
188940x019A: { n:"BrtRREndChgCell" },
188950x019B: { n:"BrtRRHeader" },
188960x019C: { n:"BrtRRUserView" },
188970x019D: { n:"BrtRRRenSheet" },
188980x019E: { n:"BrtRRInsertSh" },
188990x019F: { n:"BrtRRDefName" },
189000x01A0: { n:"BrtRRNote" },
189010x01A1: { n:"BrtRRConflict" },
189020x01A2: { n:"BrtRRTQSIF" },
189030x01A3: { n:"BrtRRFormat" },
189040x01A4: { n:"BrtRREndFormat" },
189050x01A5: { n:"BrtRRAutoFmt" },
189060x01A6: { n:"BrtBeginUserShViews" },
189070x01A7: { n:"BrtBeginUserShView" },
189080x01A8: { n:"BrtEndUserShView" },
189090x01A9: { n:"BrtEndUserShViews" },
189100x01AA: { n:"BrtArrFmla", f:parse_BrtArrFmla },
189110x01AB: { n:"BrtShrFmla", f:parse_BrtShrFmla },
189120x01AC: { n:"BrtTable" },
189130x01AD: { n:"BrtBeginExtConnections" },
189140x01AE: { n:"BrtEndExtConnections" },
189150x01AF: { n:"BrtBeginPCDCalcMems" },
189160x01B0: { n:"BrtEndPCDCalcMems" },
189170x01B1: { n:"BrtBeginPCDCalcMem" },
189180x01B2: { n:"BrtEndPCDCalcMem" },
189190x01B3: { n:"BrtBeginPCDHGLevels" },
189200x01B4: { n:"BrtEndPCDHGLevels" },
189210x01B5: { n:"BrtBeginPCDHGLevel" },
189220x01B6: { n:"BrtEndPCDHGLevel" },
189230x01B7: { n:"BrtBeginPCDHGLGroups" },
189240x01B8: { n:"BrtEndPCDHGLGroups" },
189250x01B9: { n:"BrtBeginPCDHGLGroup" },
189260x01BA: { n:"BrtEndPCDHGLGroup" },
189270x01BB: { n:"BrtBeginPCDHGLGMembers" },
189280x01BC: { n:"BrtEndPCDHGLGMembers" },
189290x01BD: { n:"BrtBeginPCDHGLGMember" },
189300x01BE: { n:"BrtEndPCDHGLGMember" },
189310x01BF: { n:"BrtBeginQSI" },
189320x01C0: { n:"BrtEndQSI" },
189330x01C1: { n:"BrtBeginQSIR" },
189340x01C2: { n:"BrtEndQSIR" },
189350x01C3: { n:"BrtBeginDeletedNames" },
189360x01C4: { n:"BrtEndDeletedNames" },
189370x01C5: { n:"BrtBeginDeletedName" },
189380x01C6: { n:"BrtEndDeletedName" },
189390x01C7: { n:"BrtBeginQSIFs" },
189400x01C8: { n:"BrtEndQSIFs" },
189410x01C9: { n:"BrtBeginQSIF" },
189420x01CA: { n:"BrtEndQSIF" },
189430x01CB: { n:"BrtBeginAutoSortScope" },
189440x01CC: { n:"BrtEndAutoSortScope" },
189450x01CD: { n:"BrtBeginConditionalFormatting" },
189460x01CE: { n:"BrtEndConditionalFormatting" },
189470x01CF: { n:"BrtBeginCFRule" },
189480x01D0: { n:"BrtEndCFRule" },
189490x01D1: { n:"BrtBeginIconSet" },
189500x01D2: { n:"BrtEndIconSet" },
189510x01D3: { n:"BrtBeginDatabar" },
189520x01D4: { n:"BrtEndDatabar" },
189530x01D5: { n:"BrtBeginColorScale" },
189540x01D6: { n:"BrtEndColorScale" },
189550x01D7: { n:"BrtCFVO" },
189560x01D8: { n:"BrtExternValueMeta" },
189570x01D9: { n:"BrtBeginColorPalette" },
189580x01DA: { n:"BrtEndColorPalette" },
189590x01DB: { n:"BrtIndexedColor" },
189600x01DC: { n:"BrtMargins", f:parse_BrtMargins },
189610x01DD: { n:"BrtPrintOptions" },
189620x01DE: { n:"BrtPageSetup" },
189630x01DF: { n:"BrtBeginHeaderFooter" },
189640x01E0: { n:"BrtEndHeaderFooter" },
189650x01E1: { n:"BrtBeginSXCrtFormat" },
189660x01E2: { n:"BrtEndSXCrtFormat" },
189670x01E3: { n:"BrtBeginSXCrtFormats" },
189680x01E4: { n:"BrtEndSXCrtFormats" },
189690x01E5: { n:"BrtWsFmtInfo", f:parse_BrtWsFmtInfo },
189700x01E6: { n:"BrtBeginMgs" },
189710x01E7: { n:"BrtEndMGs" },
189720x01E8: { n:"BrtBeginMGMaps" },
189730x01E9: { n:"BrtEndMGMaps" },
189740x01EA: { n:"BrtBeginMG" },
189750x01EB: { n:"BrtEndMG" },
189760x01EC: { n:"BrtBeginMap" },
189770x01ED: { n:"BrtEndMap" },
189780x01EE: { n:"BrtHLink", f:parse_BrtHLink },
189790x01EF: { n:"BrtBeginDCon" },
189800x01F0: { n:"BrtEndDCon" },
189810x01F1: { n:"BrtBeginDRefs" },
189820x01F2: { n:"BrtEndDRefs" },
189830x01F3: { n:"BrtDRef" },
189840x01F4: { n:"BrtBeginScenMan" },
189850x01F5: { n:"BrtEndScenMan" },
189860x01F6: { n:"BrtBeginSct" },
189870x01F7: { n:"BrtEndSct" },
189880x01F8: { n:"BrtSlc" },
189890x01F9: { n:"BrtBeginDXFs" },
189900x01FA: { n:"BrtEndDXFs" },
189910x01FB: { n:"BrtDXF" },
189920x01FC: { n:"BrtBeginTableStyles" },
189930x01FD: { n:"BrtEndTableStyles" },
189940x01FE: { n:"BrtBeginTableStyle" },
189950x01FF: { n:"BrtEndTableStyle" },
189960x0200: { n:"BrtTableStyleElement" },
189970x0201: { n:"BrtTableStyleClient" },
189980x0202: { n:"BrtBeginVolDeps" },
189990x0203: { n:"BrtEndVolDeps" },
190000x0204: { n:"BrtBeginVolType" },
190010x0205: { n:"BrtEndVolType" },
190020x0206: { n:"BrtBeginVolMain" },
190030x0207: { n:"BrtEndVolMain" },
190040x0208: { n:"BrtBeginVolTopic" },
190050x0209: { n:"BrtEndVolTopic" },
190060x020A: { n:"BrtVolSubtopic" },
190070x020B: { n:"BrtVolRef" },
190080x020C: { n:"BrtVolNum" },
190090x020D: { n:"BrtVolErr" },
190100x020E: { n:"BrtVolStr" },
190110x020F: { n:"BrtVolBool" },
190120x0210: { n:"BrtBeginCalcChain$" },
190130x0211: { n:"BrtEndCalcChain$" },
190140x0212: { n:"BrtBeginSortState" },
190150x0213: { n:"BrtEndSortState" },
190160x0214: { n:"BrtBeginSortCond" },
190170x0215: { n:"BrtEndSortCond" },
190180x0216: { n:"BrtBookProtection" },
190190x0217: { n:"BrtSheetProtection" },
190200x0218: { n:"BrtRangeProtection" },
190210x0219: { n:"BrtPhoneticInfo" },
190220x021A: { n:"BrtBeginECTxtWiz" },
190230x021B: { n:"BrtEndECTxtWiz" },
190240x021C: { n:"BrtBeginECTWFldInfoLst" },
190250x021D: { n:"BrtEndECTWFldInfoLst" },
190260x021E: { n:"BrtBeginECTwFldInfo" },
190270x0224: { n:"BrtFileSharing" },
190280x0225: { n:"BrtOleSize" },
190290x0226: { n:"BrtDrawing", f:parse_RelID },
190300x0227: { n:"BrtLegacyDrawing" },
190310x0228: { n:"BrtLegacyDrawingHF" },
190320x0229: { n:"BrtWebOpt" },
190330x022A: { n:"BrtBeginWebPubItems" },
190340x022B: { n:"BrtEndWebPubItems" },
190350x022C: { n:"BrtBeginWebPubItem" },
190360x022D: { n:"BrtEndWebPubItem" },
190370x022E: { n:"BrtBeginSXCondFmt" },
190380x022F: { n:"BrtEndSXCondFmt" },
190390x0230: { n:"BrtBeginSXCondFmts" },
190400x0231: { n:"BrtEndSXCondFmts" },
190410x0232: { n:"BrtBkHim" },
190420x0234: { n:"BrtColor" },
190430x0235: { n:"BrtBeginIndexedColors" },
190440x0236: { n:"BrtEndIndexedColors" },
190450x0239: { n:"BrtBeginMRUColors" },
190460x023A: { n:"BrtEndMRUColors" },
190470x023C: { n:"BrtMRUColor" },
190480x023D: { n:"BrtBeginDVals" },
190490x023E: { n:"BrtEndDVals" },
190500x0241: { n:"BrtSupNameStart" },
190510x0242: { n:"BrtSupNameValueStart" },
190520x0243: { n:"BrtSupNameValueEnd" },
190530x0244: { n:"BrtSupNameNum" },
190540x0245: { n:"BrtSupNameErr" },
190550x0246: { n:"BrtSupNameSt" },
190560x0247: { n:"BrtSupNameNil" },
190570x0248: { n:"BrtSupNameBool" },
190580x0249: { n:"BrtSupNameFmla" },
190590x024A: { n:"BrtSupNameBits" },
190600x024B: { n:"BrtSupNameEnd" },
190610x024C: { n:"BrtEndSupBook" },
190620x024D: { n:"BrtCellSmartTagProperty" },
190630x024E: { n:"BrtBeginCellSmartTag" },
190640x024F: { n:"BrtEndCellSmartTag" },
190650x0250: { n:"BrtBeginCellSmartTags" },
190660x0251: { n:"BrtEndCellSmartTags" },
190670x0252: { n:"BrtBeginSmartTags" },
190680x0253: { n:"BrtEndSmartTags" },
190690x0254: { n:"BrtSmartTagType" },
190700x0255: { n:"BrtBeginSmartTagTypes" },
190710x0256: { n:"BrtEndSmartTagTypes" },
190720x0257: { n:"BrtBeginSXFilters" },
190730x0258: { n:"BrtEndSXFilters" },
190740x0259: { n:"BrtBeginSXFILTER" },
190750x025A: { n:"BrtEndSXFilter" },
190760x025B: { n:"BrtBeginFills" },
190770x025C: { n:"BrtEndFills" },
190780x025D: { n:"BrtBeginCellWatches" },
190790x025E: { n:"BrtEndCellWatches" },
190800x025F: { n:"BrtCellWatch" },
190810x0260: { n:"BrtBeginCRErrs" },
190820x0261: { n:"BrtEndCRErrs" },
190830x0262: { n:"BrtCrashRecErr" },
190840x0263: { n:"BrtBeginFonts" },
190850x0264: { n:"BrtEndFonts" },
190860x0265: { n:"BrtBeginBorders" },
190870x0266: { n:"BrtEndBorders" },
190880x0267: { n:"BrtBeginFmts" },
190890x0268: { n:"BrtEndFmts" },
190900x0269: { n:"BrtBeginCellXFs" },
190910x026A: { n:"BrtEndCellXFs" },
190920x026B: { n:"BrtBeginStyles" },
190930x026C: { n:"BrtEndStyles" },
190940x0271: { n:"BrtBigName" },
190950x0272: { n:"BrtBeginCellStyleXFs" },
190960x0273: { n:"BrtEndCellStyleXFs" },
190970x0274: { n:"BrtBeginComments" },
190980x0275: { n:"BrtEndComments" },
190990x0276: { n:"BrtBeginCommentAuthors" },
191000x0277: { n:"BrtEndCommentAuthors" },
191010x0278: { n:"BrtCommentAuthor", f:parse_BrtCommentAuthor },
191020x0279: { n:"BrtBeginCommentList" },
191030x027A: { n:"BrtEndCommentList" },
191040x027B: { n:"BrtBeginComment", f:parse_BrtBeginComment},
191050x027C: { n:"BrtEndComment" },
191060x027D: { n:"BrtCommentText", f:parse_BrtCommentText },
191070x027E: { n:"BrtBeginOleObjects" },
191080x027F: { n:"BrtOleObject" },
191090x0280: { n:"BrtEndOleObjects" },
191100x0281: { n:"BrtBeginSxrules" },
191110x0282: { n:"BrtEndSxRules" },
191120x0283: { n:"BrtBeginActiveXControls" },
191130x0284: { n:"BrtActiveX" },
191140x0285: { n:"BrtEndActiveXControls" },
191150x0286: { n:"BrtBeginPCDSDTCEMembersSortBy" },
191160x0288: { n:"BrtBeginCellIgnoreECs" },
191170x0289: { n:"BrtCellIgnoreEC" },
191180x028A: { n:"BrtEndCellIgnoreECs" },
191190x028B: { n:"BrtCsProp", f:parse_BrtCsProp },
191200x028C: { n:"BrtCsPageSetup" },
191210x028D: { n:"BrtBeginUserCsViews" },
191220x028E: { n:"BrtEndUserCsViews" },
191230x028F: { n:"BrtBeginUserCsView" },
191240x0290: { n:"BrtEndUserCsView" },
191250x0291: { n:"BrtBeginPcdSFCIEntries" },
191260x0292: { n:"BrtEndPCDSFCIEntries" },
191270x0293: { n:"BrtPCDSFCIEntry" },
191280x0294: { n:"BrtBeginListParts" },
191290x0295: { n:"BrtListPart" },
191300x0296: { n:"BrtEndListParts" },
191310x0297: { n:"BrtSheetCalcProp" },
191320x0298: { n:"BrtBeginFnGroup" },
191330x0299: { n:"BrtFnGroup" },
191340x029A: { n:"BrtEndFnGroup" },
191350x029B: { n:"BrtSupAddin" },
191360x029C: { n:"BrtSXTDMPOrder" },
191370x029D: { n:"BrtCsProtection" },
191380x029F: { n:"BrtBeginWsSortMap" },
191390x02A0: { n:"BrtEndWsSortMap" },
191400x02A1: { n:"BrtBeginRRSort" },
191410x02A2: { n:"BrtEndRRSort" },
191420x02A3: { n:"BrtRRSortItem" },
191430x02A4: { n:"BrtFileSharingIso" },
191440x02A5: { n:"BrtBookProtectionIso" },
191450x02A6: { n:"BrtSheetProtectionIso" },
191460x02A7: { n:"BrtCsProtectionIso" },
191470x02A8: { n:"BrtRangeProtectionIso" },
191480x02A9: { n:"BrtDValList" },
191490x0400: { n:"BrtRwDescent" },
191500x0401: { n:"BrtKnownFonts" },
191510x0402: { n:"BrtBeginSXTupleSet" },
191520x0403: { n:"BrtEndSXTupleSet" },
191530x0404: { n:"BrtBeginSXTupleSetHeader" },
191540x0405: { n:"BrtEndSXTupleSetHeader" },
191550x0406: { n:"BrtSXTupleSetHeaderItem" },
191560x0407: { n:"BrtBeginSXTupleSetData" },
191570x0408: { n:"BrtEndSXTupleSetData" },
191580x0409: { n:"BrtBeginSXTupleSetRow" },
191590x040A: { n:"BrtEndSXTupleSetRow" },
191600x040B: { n:"BrtSXTupleSetRowItem" },
191610x040C: { n:"BrtNameExt" },
191620x040D: { n:"BrtPCDH14" },
191630x040E: { n:"BrtBeginPCDCalcMem14" },
191640x040F: { n:"BrtEndPCDCalcMem14" },
191650x0410: { n:"BrtSXTH14" },
191660x0411: { n:"BrtBeginSparklineGroup" },
191670x0412: { n:"BrtEndSparklineGroup" },
191680x0413: { n:"BrtSparkline" },
191690x0414: { n:"BrtSXDI14" },
191700x0415: { n:"BrtWsFmtInfoEx14" },
191710x0416: { n:"BrtBeginConditionalFormatting14" },
191720x0417: { n:"BrtEndConditionalFormatting14" },
191730x0418: { n:"BrtBeginCFRule14" },
191740x0419: { n:"BrtEndCFRule14" },
191750x041A: { n:"BrtCFVO14" },
191760x041B: { n:"BrtBeginDatabar14" },
191770x041C: { n:"BrtBeginIconSet14" },
191780x041D: { n:"BrtDVal14", f: parse_BrtDVal14 },
191790x041E: { n:"BrtBeginDVals14" },
191800x041F: { n:"BrtColor14" },
191810x0420: { n:"BrtBeginSparklines" },
191820x0421: { n:"BrtEndSparklines" },
191830x0422: { n:"BrtBeginSparklineGroups" },
191840x0423: { n:"BrtEndSparklineGroups" },
191850x0425: { n:"BrtSXVD14" },
191860x0426: { n:"BrtBeginSXView14" },
191870x0427: { n:"BrtEndSXView14" },
191880x0428: { n:"BrtBeginSXView16" },
191890x0429: { n:"BrtEndSXView16" },
191900x042A: { n:"BrtBeginPCD14" },
191910x042B: { n:"BrtEndPCD14" },
191920x042C: { n:"BrtBeginExtConn14" },
191930x042D: { n:"BrtEndExtConn14" },
191940x042E: { n:"BrtBeginSlicerCacheIDs" },
191950x042F: { n:"BrtEndSlicerCacheIDs" },
191960x0430: { n:"BrtBeginSlicerCacheID" },
191970x0431: { n:"BrtEndSlicerCacheID" },
191980x0433: { n:"BrtBeginSlicerCache" },
191990x0434: { n:"BrtEndSlicerCache" },
192000x0435: { n:"BrtBeginSlicerCacheDef" },
192010x0436: { n:"BrtEndSlicerCacheDef" },
192020x0437: { n:"BrtBeginSlicersEx" },
192030x0438: { n:"BrtEndSlicersEx" },
192040x0439: { n:"BrtBeginSlicerEx" },
192050x043A: { n:"BrtEndSlicerEx" },
192060x043B: { n:"BrtBeginSlicer" },
192070x043C: { n:"BrtEndSlicer" },
192080x043D: { n:"BrtSlicerCachePivotTables" },
192090x043E: { n:"BrtBeginSlicerCacheOlapImpl" },
192100x043F: { n:"BrtEndSlicerCacheOlapImpl" },
192110x0440: { n:"BrtBeginSlicerCacheLevelsData" },
192120x0441: { n:"BrtEndSlicerCacheLevelsData" },
192130x0442: { n:"BrtBeginSlicerCacheLevelData" },
192140x0443: { n:"BrtEndSlicerCacheLevelData" },
192150x0444: { n:"BrtBeginSlicerCacheSiRanges" },
192160x0445: { n:"BrtEndSlicerCacheSiRanges" },
192170x0446: { n:"BrtBeginSlicerCacheSiRange" },
192180x0447: { n:"BrtEndSlicerCacheSiRange" },
192190x0448: { n:"BrtSlicerCacheOlapItem" },
192200x0449: { n:"BrtBeginSlicerCacheSelections" },
192210x044A: { n:"BrtSlicerCacheSelection" },
192220x044B: { n:"BrtEndSlicerCacheSelections" },
192230x044C: { n:"BrtBeginSlicerCacheNative" },
192240x044D: { n:"BrtEndSlicerCacheNative" },
192250x044E: { n:"BrtSlicerCacheNativeItem" },
192260x044F: { n:"BrtRangeProtection14" },
192270x0450: { n:"BrtRangeProtectionIso14" },
192280x0451: { n:"BrtCellIgnoreEC14" },
192290x0457: { n:"BrtList14" },
192300x0458: { n:"BrtCFIcon" },
192310x0459: { n:"BrtBeginSlicerCachesPivotCacheIDs" },
192320x045A: { n:"BrtEndSlicerCachesPivotCacheIDs" },
192330x045B: { n:"BrtBeginSlicers" },
192340x045C: { n:"BrtEndSlicers" },
192350x045D: { n:"BrtWbProp14" },
192360x045E: { n:"BrtBeginSXEdit" },
192370x045F: { n:"BrtEndSXEdit" },
192380x0460: { n:"BrtBeginSXEdits" },
192390x0461: { n:"BrtEndSXEdits" },
192400x0462: { n:"BrtBeginSXChange" },
192410x0463: { n:"BrtEndSXChange" },
192420x0464: { n:"BrtBeginSXChanges" },
192430x0465: { n:"BrtEndSXChanges" },
192440x0466: { n:"BrtSXTupleItems" },
192450x0468: { n:"BrtBeginSlicerStyle" },
192460x0469: { n:"BrtEndSlicerStyle" },
192470x046A: { n:"BrtSlicerStyleElement" },
192480x046B: { n:"BrtBeginStyleSheetExt14" },
192490x046C: { n:"BrtEndStyleSheetExt14" },
192500x046D: { n:"BrtBeginSlicerCachesPivotCacheID" },
192510x046E: { n:"BrtEndSlicerCachesPivotCacheID" },
192520x046F: { n:"BrtBeginConditionalFormattings" },
192530x0470: { n:"BrtEndConditionalFormattings" },
192540x0471: { n:"BrtBeginPCDCalcMemExt" },
192550x0472: { n:"BrtEndPCDCalcMemExt" },
192560x0473: { n:"BrtBeginPCDCalcMemsExt" },
192570x0474: { n:"BrtEndPCDCalcMemsExt" },
192580x0475: { n:"BrtPCDField14" },
192590x0476: { n:"BrtBeginSlicerStyles" },
192600x0477: { n:"BrtEndSlicerStyles" },
192610x0478: { n:"BrtBeginSlicerStyleElements" },
192620x0479: { n:"BrtEndSlicerStyleElements" },
192630x047A: { n:"BrtCFRuleExt" },
192640x047B: { n:"BrtBeginSXCondFmt14" },
192650x047C: { n:"BrtEndSXCondFmt14" },
192660x047D: { n:"BrtBeginSXCondFmts14" },
192670x047E: { n:"BrtEndSXCondFmts14" },
192680x0480: { n:"BrtBeginSortCond14" },
192690x0481: { n:"BrtEndSortCond14" },
192700x0482: { n:"BrtEndDVals14" },
192710x0483: { n:"BrtEndIconSet14" },
192720x0484: { n:"BrtEndDatabar14" },
192730x0485: { n:"BrtBeginColorScale14" },
192740x0486: { n:"BrtEndColorScale14" },
192750x0487: { n:"BrtBeginSxrules14" },
192760x0488: { n:"BrtEndSxrules14" },
192770x0489: { n:"BrtBeginPRule14" },
192780x048A: { n:"BrtEndPRule14" },
192790x048B: { n:"BrtBeginPRFilters14" },
192800x048C: { n:"BrtEndPRFilters14" },
192810x048D: { n:"BrtBeginPRFilter14" },
192820x048E: { n:"BrtEndPRFilter14" },
192830x048F: { n:"BrtBeginPRFItem14" },
192840x0490: { n:"BrtEndPRFItem14" },
192850x0491: { n:"BrtBeginCellIgnoreECs14" },
192860x0492: { n:"BrtEndCellIgnoreECs14" },
192870x0493: { n:"BrtDxf14" },
192880x0494: { n:"BrtBeginDxF14s" },
192890x0495: { n:"BrtEndDxf14s" },
192900x0499: { n:"BrtFilter14" },
192910x049A: { n:"BrtBeginCustomFilters14" },
192920x049C: { n:"BrtCustomFilter14" },
192930x049D: { n:"BrtIconFilter14" },
192940x049E: { n:"BrtPivotCacheConnectionName" },
192950x0800: { n:"BrtBeginDecoupledPivotCacheIDs" },
192960x0801: { n:"BrtEndDecoupledPivotCacheIDs" },
192970x0802: { n:"BrtDecoupledPivotCacheID" },
192980x0803: { n:"BrtBeginPivotTableRefs" },
192990x0804: { n:"BrtEndPivotTableRefs" },
193000x0805: { n:"BrtPivotTableRef" },
193010x0806: { n:"BrtSlicerCacheBookPivotTables" },
193020x0807: { n:"BrtBeginSxvcells" },
193030x0808: { n:"BrtEndSxvcells" },
193040x0809: { n:"BrtBeginSxRow" },
193050x080A: { n:"BrtEndSxRow" },
193060x080C: { n:"BrtPcdCalcMem15" },
193070x0813: { n:"BrtQsi15" },
193080x0814: { n:"BrtBeginWebExtensions" },
193090x0815: { n:"BrtEndWebExtensions" },
193100x0816: { n:"BrtWebExtension" },
193110x0817: { n:"BrtAbsPath15" },
193120x0818: { n:"BrtBeginPivotTableUISettings" },
193130x0819: { n:"BrtEndPivotTableUISettings" },
193140x081B: { n:"BrtTableSlicerCacheIDs" },
193150x081C: { n:"BrtTableSlicerCacheID" },
193160x081D: { n:"BrtBeginTableSlicerCache" },
193170x081E: { n:"BrtEndTableSlicerCache" },
193180x081F: { n:"BrtSxFilter15" },
193190x0820: { n:"BrtBeginTimelineCachePivotCacheIDs" },
193200x0821: { n:"BrtEndTimelineCachePivotCacheIDs" },
193210x0822: { n:"BrtTimelineCachePivotCacheID" },
193220x0823: { n:"BrtBeginTimelineCacheIDs" },
193230x0824: { n:"BrtEndTimelineCacheIDs" },
193240x0825: { n:"BrtBeginTimelineCacheID" },
193250x0826: { n:"BrtEndTimelineCacheID" },
193260x0827: { n:"BrtBeginTimelinesEx" },
193270x0828: { n:"BrtEndTimelinesEx" },
193280x0829: { n:"BrtBeginTimelineEx" },
193290x082A: { n:"BrtEndTimelineEx" },
193300x082B: { n:"BrtWorkBookPr15" },
193310x082C: { n:"BrtPCDH15" },
193320x082D: { n:"BrtBeginTimelineStyle" },
193330x082E: { n:"BrtEndTimelineStyle" },
193340x082F: { n:"BrtTimelineStyleElement" },
193350x0830: { n:"BrtBeginTimelineStylesheetExt15" },
193360x0831: { n:"BrtEndTimelineStylesheetExt15" },
193370x0832: { n:"BrtBeginTimelineStyles" },
193380x0833: { n:"BrtEndTimelineStyles" },
193390x0834: { n:"BrtBeginTimelineStyleElements" },
193400x0835: { n:"BrtEndTimelineStyleElements" },
193410x0836: { n:"BrtDxf15" },
193420x0837: { n:"BrtBeginDxfs15" },
193430x0838: { n:"brtEndDxfs15" },
193440x0839: { n:"BrtSlicerCacheHideItemsWithNoData" },
193450x083A: { n:"BrtBeginItemUniqueNames" },
193460x083B: { n:"BrtEndItemUniqueNames" },
193470x083C: { n:"BrtItemUniqueName" },
193480x083D: { n:"BrtBeginExtConn15" },
193490x083E: { n:"BrtEndExtConn15" },
193500x083F: { n:"BrtBeginOledbPr15" },
193510x0840: { n:"BrtEndOledbPr15" },
193520x0841: { n:"BrtBeginDataFeedPr15" },
193530x0842: { n:"BrtEndDataFeedPr15" },
193540x0843: { n:"BrtTextPr15" },
193550x0844: { n:"BrtRangePr15" },
193560x0845: { n:"BrtDbCommand15" },
193570x0846: { n:"BrtBeginDbTables15" },
193580x0847: { n:"BrtEndDbTables15" },
193590x0848: { n:"BrtDbTable15" },
193600x0849: { n:"BrtBeginDataModel" },
193610x084A: { n:"BrtEndDataModel" },
193620x084B: { n:"BrtBeginModelTables" },
193630x084C: { n:"BrtEndModelTables" },
193640x084D: { n:"BrtModelTable" },
193650x084E: { n:"BrtBeginModelRelationships" },
193660x084F: { n:"BrtEndModelRelationships" },
193670x0850: { n:"BrtModelRelationship" },
193680x0851: { n:"BrtBeginECTxtWiz15" },
193690x0852: { n:"BrtEndECTxtWiz15" },
193700x0853: { n:"BrtBeginECTWFldInfoLst15" },
193710x0854: { n:"BrtEndECTWFldInfoLst15" },
193720x0855: { n:"BrtBeginECTWFldInfo15" },
193730x0856: { n:"BrtFieldListActiveItem" },
193740x0857: { n:"BrtPivotCacheIdVersion" },
193750x0858: { n:"BrtSXDI15" },
193760x0859: { n:"BrtBeginModelTimeGroupings" },
193770x085A: { n:"BrtEndModelTimeGroupings" },
193780x085B: { n:"BrtBeginModelTimeGrouping" },
193790x085C: { n:"BrtEndModelTimeGrouping" },
193800x085D: { n:"BrtModelTimeGroupingCalcCol" },
193810x0C00: { n:"BrtUid" },
193820x0C01: { n:"BrtRevisionPtr" },
193830x13e7: { n:"BrtBeginCalcFeatures" },
193840x13e8: { n:"BrtEndCalcFeatures" },
193850x13e9: { n:"BrtCalcFeature" },
193860xFFFF: { n:"" }
19387};
19388
19389var XLSBRE = evert_key(XLSBRecordEnum, 'n');
19390XLSBRE["BrtFRTArchID$"] = 0x0010;
19391
19392/* [MS-XLS] 2.3 Record Enumeration (and other sources) */
19393var XLSRecordEnum = {
19394 /* [MS-XLS] 2.3 Record Enumeration 2021-08-17 */
193950x0006: { n:"Formula", f:parse_Formula },
193960x000a: { n:'EOF', f:parsenoop2 },
193970x000c: { n:"CalcCount", f:parseuint16 },
193980x000d: { n:"CalcMode", f:parseuint16 },
193990x000e: { n:"CalcPrecision", f:parsebool },
194000x000f: { n:"CalcRefMode", f:parsebool },
194010x0010: { n:"CalcDelta", f:parse_Xnum },
194020x0011: { n:"CalcIter", f:parsebool },
194030x0012: { n:"Protect", f:parsebool },
194040x0013: { n:"Password", f:parseuint16 },
194050x0014: { n:"Header", f:parse_XLHeaderFooter },
194060x0015: { n:"Footer", f:parse_XLHeaderFooter },
194070x0017: { n:"ExternSheet", f:parse_ExternSheet },
194080x0018: { n:"Lbl", f:parse_Lbl },
194090x0019: { n:"WinProtect", f:parsebool },
194100x001a: { n:"VerticalPageBreaks" },
194110x001b: { n:"HorizontalPageBreaks" },
194120x001c: { n:"Note", f:parse_Note },
194130x001d: { n:"Selection" },
194140x0022: { n:"Date1904", f:parsebool },
194150x0023: { n:"ExternName", f:parse_ExternName },
194160x0026: { n:"LeftMargin", f:parse_Xnum },
194170x0027: { n:"RightMargin", f:parse_Xnum },
194180x0028: { n:"TopMargin", f:parse_Xnum },
194190x0029: { n:"BottomMargin", f:parse_Xnum },
194200x002a: { n:"PrintRowCol", f:parsebool },
194210x002b: { n:"PrintGrid", f:parsebool },
194220x002f: { n:"FilePass", f:parse_FilePass },
194230x0031: { n:"Font", f:parse_Font },
194240x0033: { n:"PrintSize", f:parseuint16 },
194250x003c: { n:"Continue" },
194260x003d: { n:"Window1", f:parse_Window1 },
194270x0040: { n:"Backup", f:parsebool },
194280x0041: { n:"Pane", f:parse_Pane },
194290x0042: { n:'CodePage', f:parseuint16 },
194300x004d: { n:"Pls" },
194310x0050: { n:"DCon" },
194320x0051: { n:"DConRef" },
194330x0052: { n:"DConName" },
194340x0055: { n:"DefColWidth", f:parseuint16 },
194350x0059: { n:"XCT" },
194360x005a: { n:"CRN" },
194370x005b: { n:"FileSharing" },
194380x005c: { n:'WriteAccess', f:parse_WriteAccess },
194390x005d: { n:"Obj", f:parse_Obj },
194400x005e: { n:"Uncalced" },
194410x005f: { n:"CalcSaveRecalc", f:parsebool },
194420x0060: { n:"Template" },
194430x0061: { n:"Intl" },
194440x0063: { n:"ObjProtect", f:parsebool },
194450x007d: { n:"ColInfo", f:parse_ColInfo },
194460x0080: { n:"Guts", f:parse_Guts },
194470x0081: { n:"WsBool", f:parse_WsBool },
194480x0082: { n:"GridSet", f:parseuint16 },
194490x0083: { n:"HCenter", f:parsebool },
194500x0084: { n:"VCenter", f:parsebool },
194510x0085: { n:'BoundSheet8', f:parse_BoundSheet8 },
194520x0086: { n:"WriteProtect" },
194530x008c: { n:"Country", f:parse_Country },
194540x008d: { n:"HideObj", f:parseuint16 },
194550x0090: { n:"Sort" },
194560x0092: { n:"Palette", f:parse_Palette },
194570x0097: { n:"Sync" },
194580x0098: { n:"LPr" },
194590x0099: { n:"DxGCol" },
194600x009a: { n:"FnGroupName" },
194610x009b: { n:"FilterMode" },
194620x009c: { n:"BuiltInFnGroupCount", f:parseuint16 },
194630x009d: { n:"AutoFilterInfo" },
194640x009e: { n:"AutoFilter" },
194650x00a0: { n:"Scl", f:parse_Scl },
194660x00a1: { n:"Setup", f:parse_Setup },
194670x00ae: { n:"ScenMan" },
194680x00af: { n:"SCENARIO" },
194690x00b0: { n:"SxView" },
194700x00b1: { n:"Sxvd" },
194710x00b2: { n:"SXVI" },
194720x00b4: { n:"SxIvd" },
194730x00b5: { n:"SXLI" },
194740x00b6: { n:"SXPI" },
194750x00b8: { n:"DocRoute" },
194760x00b9: { n:"RecipName" },
194770x00bd: { n:"MulRk", f:parse_MulRk },
194780x00be: { n:"MulBlank", f:parse_MulBlank },
194790x00c1: { n:'Mms', f:parsenoop2 },
194800x00c5: { n:"SXDI" },
194810x00c6: { n:"SXDB" },
194820x00c7: { n:"SXFDB" },
194830x00c8: { n:"SXDBB" },
194840x00c9: { n:"SXNum" },
194850x00ca: { n:"SxBool", f:parsebool },
194860x00cb: { n:"SxErr" },
194870x00cc: { n:"SXInt" },
194880x00cd: { n:"SXString" },
194890x00ce: { n:"SXDtr" },
194900x00cf: { n:"SxNil" },
194910x00d0: { n:"SXTbl" },
194920x00d1: { n:"SXTBRGIITM" },
194930x00d2: { n:"SxTbpg" },
194940x00d3: { n:"ObProj" },
194950x00d5: { n:"SXStreamID" },
194960x00d7: { n:"DBCell" },
194970x00d8: { n:"SXRng" },
194980x00d9: { n:"SxIsxoper" },
194990x00da: { n:"BookBool", f:parseuint16 },
195000x00dc: { n:"DbOrParamQry" },
195010x00dd: { n:"ScenarioProtect", f:parsebool },
195020x00de: { n:"OleObjectSize" },
195030x00e0: { n:"XF", f:parse_XF },
195040x00e1: { n:'InterfaceHdr', f:parse_InterfaceHdr },
195050x00e2: { n:'InterfaceEnd', f:parsenoop2 },
195060x00e3: { n:"SXVS" },
195070x00e5: { n:"MergeCells", f:parse_MergeCells },
195080x00e9: { n:"BkHim" },
195090x00eb: { n:"MsoDrawingGroup" },
195100x00ec: { n:"MsoDrawing" },
195110x00ed: { n:"MsoDrawingSelection" },
195120x00ef: { n:"PhoneticInfo" },
195130x00f0: { n:"SxRule" },
195140x00f1: { n:"SXEx" },
195150x00f2: { n:"SxFilt" },
195160x00f4: { n:"SxDXF" },
195170x00f5: { n:"SxItm" },
195180x00f6: { n:"SxName" },
195190x00f7: { n:"SxSelect" },
195200x00f8: { n:"SXPair" },
195210x00f9: { n:"SxFmla" },
195220x00fb: { n:"SxFormat" },
195230x00fc: { n:"SST", f:parse_SST },
195240x00fd: { n:"LabelSst", f:parse_LabelSst },
195250x00ff: { n:"ExtSST", f:parse_ExtSST },
195260x0100: { n:"SXVDEx" },
195270x0103: { n:"SXFormula" },
195280x0122: { n:"SXDBEx" },
195290x0137: { n:"RRDInsDel" },
195300x0138: { n:"RRDHead" },
195310x013b: { n:"RRDChgCell" },
195320x013d: { n:"RRTabId", f:parseuint16a },
195330x013e: { n:"RRDRenSheet" },
195340x013f: { n:"RRSort" },
195350x0140: { n:"RRDMove" },
195360x014a: { n:"RRFormat" },
195370x014b: { n:"RRAutoFmt" },
195380x014d: { n:"RRInsertSh" },
195390x014e: { n:"RRDMoveBegin" },
195400x014f: { n:"RRDMoveEnd" },
195410x0150: { n:"RRDInsDelBegin" },
195420x0151: { n:"RRDInsDelEnd" },
195430x0152: { n:"RRDConflict" },
195440x0153: { n:"RRDDefName" },
195450x0154: { n:"RRDRstEtxp" },
195460x015f: { n:"LRng" },
195470x0160: { n:"UsesELFs", f:parsebool },
195480x0161: { n:"DSF", f:parsenoop2 },
195490x0191: { n:"CUsr" },
195500x0192: { n:"CbUsr" },
195510x0193: { n:"UsrInfo" },
195520x0194: { n:"UsrExcl" },
195530x0195: { n:"FileLock" },
195540x0196: { n:"RRDInfo" },
195550x0197: { n:"BCUsrs" },
195560x0198: { n:"UsrChk" },
195570x01a9: { n:"UserBView" },
195580x01aa: { n:"UserSViewBegin" },
195590x01ab: { n:"UserSViewEnd" },
195600x01ac: { n:"RRDUserView" },
195610x01ad: { n:"Qsi" },
195620x01ae: { n:"SupBook", f:parse_SupBook },
195630x01af: { n:"Prot4Rev", f:parsebool },
195640x01b0: { n:"CondFmt" },
195650x01b1: { n:"CF" },
195660x01b2: { n:"DVal" },
195670x01b5: { n:"DConBin" },
195680x01b6: { n:"TxO", f:parse_TxO },
195690x01b7: { n:"RefreshAll", f:parsebool },
195700x01b8: { n:"HLink", f:parse_HLink },
195710x01b9: { n:"Lel" },
195720x01ba: { n:"CodeName", f:parse_XLUnicodeString },
195730x01bb: { n:"SXFDBType" },
195740x01bc: { n:"Prot4RevPass", f:parseuint16 },
195750x01bd: { n:"ObNoMacros" },
195760x01be: { n:"Dv" },
195770x01c0: { n:"Excel9File", f:parsenoop2 },
195780x01c1: { n:"RecalcId", f:parse_RecalcId, r:2},
195790x01c2: { n:"EntExU2", f:parsenoop2 },
195800x0200: { n:"Dimensions", f:parse_Dimensions },
195810x0201: { n:"Blank", f:parse_Blank },
195820x0203: { n:"Number", f:parse_Number },
195830x0204: { n:"Label", f:parse_Label },
195840x0205: { n:"BoolErr", f:parse_BoolErr },
195850x0207: { n:"String", f:parse_String },
195860x0208: { n:'Row', f:parse_Row },
195870x020b: { n:"Index" },
195880x0221: { n:"Array", f:parse_Array },
195890x0225: { n:"DefaultRowHeight", f:parse_DefaultRowHeight },
195900x0236: { n:"Table" },
195910x023e: { n:"Window2", f:parse_Window2 },
195920x027e: { n:"RK", f:parse_RK },
195930x0293: { n:"Style" },
195940x0418: { n:"BigName" },
195950x041e: { n:"Format", f:parse_Format },
195960x043c: { n:"ContinueBigName" },
195970x04bc: { n:"ShrFmla", f:parse_ShrFmla },
195980x0800: { n:"HLinkTooltip", f:parse_HLinkTooltip },
195990x0801: { n:"WebPub" },
196000x0802: { n:"QsiSXTag" },
196010x0803: { n:"DBQueryExt" },
196020x0804: { n:"ExtString" },
196030x0805: { n:"TxtQry" },
196040x0806: { n:"Qsir" },
196050x0807: { n:"Qsif" },
196060x0808: { n:"RRDTQSIF" },
196070x0809: { n:'BOF', f:parse_BOF },
196080x080a: { n:"OleDbConn" },
196090x080b: { n:"WOpt" },
196100x080c: { n:"SXViewEx" },
196110x080d: { n:"SXTH" },
196120x080e: { n:"SXPIEx" },
196130x080f: { n:"SXVDTEx" },
196140x0810: { n:"SXViewEx9" },
196150x0812: { n:"ContinueFrt" },
196160x0813: { n:"RealTimeData" },
196170x0850: { n:"ChartFrtInfo" },
196180x0851: { n:"FrtWrapper" },
196190x0852: { n:"StartBlock" },
196200x0853: { n:"EndBlock" },
196210x0854: { n:"StartObject" },
196220x0855: { n:"EndObject" },
196230x0856: { n:"CatLab" },
196240x0857: { n:"YMult" },
196250x0858: { n:"SXViewLink" },
196260x0859: { n:"PivotChartBits" },
196270x085a: { n:"FrtFontList" },
196280x0862: { n:"SheetExt" },
196290x0863: { n:"BookExt", r:12},
196300x0864: { n:"SXAddl" },
196310x0865: { n:"CrErr" },
196320x0866: { n:"HFPicture" },
196330x0867: { n:'FeatHdr', f:parsenoop2 },
196340x0868: { n:"Feat" },
196350x086a: { n:"DataLabExt" },
196360x086b: { n:"DataLabExtContents" },
196370x086c: { n:"CellWatch" },
196380x0871: { n:"FeatHdr11" },
196390x0872: { n:"Feature11" },
196400x0874: { n:"DropDownObjIds" },
196410x0875: { n:"ContinueFrt11" },
196420x0876: { n:"DConn" },
196430x0877: { n:"List12" },
196440x0878: { n:"Feature12" },
196450x0879: { n:"CondFmt12" },
196460x087a: { n:"CF12" },
196470x087b: { n:"CFEx" },
196480x087c: { n:"XFCRC", f:parse_XFCRC, r:12 },
196490x087d: { n:"XFExt", f:parse_XFExt, r:12 },
196500x087e: { n:"AutoFilter12" },
196510x087f: { n:"ContinueFrt12" },
196520x0884: { n:"MDTInfo" },
196530x0885: { n:"MDXStr" },
196540x0886: { n:"MDXTuple" },
196550x0887: { n:"MDXSet" },
196560x0888: { n:"MDXProp" },
196570x0889: { n:"MDXKPI" },
196580x088a: { n:"MDB" },
196590x088b: { n:"PLV" },
196600x088c: { n:"Compat12", f:parsebool, r:12 },
196610x088d: { n:"DXF" },
196620x088e: { n:"TableStyles", r:12 },
196630x088f: { n:"TableStyle" },
196640x0890: { n:"TableStyleElement" },
196650x0892: { n:"StyleExt" },
196660x0893: { n:"NamePublish" },
196670x0894: { n:"NameCmt", f:parse_NameCmt, r:12 },
196680x0895: { n:"SortData" },
196690x0896: { n:"Theme", f:parse_Theme, r:12 },
196700x0897: { n:"GUIDTypeLib" },
196710x0898: { n:"FnGrp12" },
196720x0899: { n:"NameFnGrp12" },
196730x089a: { n:"MTRSettings", f:parse_MTRSettings, r:12 },
196740x089b: { n:"CompressPictures", f:parsenoop2 },
196750x089c: { n:"HeaderFooter" },
196760x089d: { n:"CrtLayout12" },
196770x089e: { n:"CrtMlFrt" },
196780x089f: { n:"CrtMlFrtContinue" },
196790x08a3: { n:"ForceFullCalculation", f:parse_ForceFullCalculation },
196800x08a4: { n:"ShapePropsStream" },
196810x08a5: { n:"TextPropsStream" },
196820x08a6: { n:"RichTextStream" },
196830x08a7: { n:"CrtLayout12A" },
196840x1001: { n:"Units" },
196850x1002: { n:"Chart" },
196860x1003: { n:"Series" },
196870x1006: { n:"DataFormat" },
196880x1007: { n:"LineFormat" },
196890x1009: { n:"MarkerFormat" },
196900x100a: { n:"AreaFormat" },
196910x100b: { n:"PieFormat" },
196920x100c: { n:"AttachedLabel" },
196930x100d: { n:"SeriesText" },
196940x1014: { n:"ChartFormat" },
196950x1015: { n:"Legend" },
196960x1016: { n:"SeriesList" },
196970x1017: { n:"Bar" },
196980x1018: { n:"Line" },
196990x1019: { n:"Pie" },
197000x101a: { n:"Area" },
197010x101b: { n:"Scatter" },
197020x101c: { n:"CrtLine" },
197030x101d: { n:"Axis" },
197040x101e: { n:"Tick" },
197050x101f: { n:"ValueRange" },
197060x1020: { n:"CatSerRange" },
197070x1021: { n:"AxisLine" },
197080x1022: { n:"CrtLink" },
197090x1024: { n:"DefaultText" },
197100x1025: { n:"Text" },
197110x1026: { n:"FontX", f:parseuint16 },
197120x1027: { n:"ObjectLink" },
197130x1032: { n:"Frame" },
197140x1033: { n:"Begin" },
197150x1034: { n:"End" },
197160x1035: { n:"PlotArea" },
197170x103a: { n:"Chart3d" },
197180x103c: { n:"PicF" },
197190x103d: { n:"DropBar" },
197200x103e: { n:"Radar" },
197210x103f: { n:"Surf" },
197220x1040: { n:"RadarArea" },
197230x1041: { n:"AxisParent" },
197240x1043: { n:"LegendException" },
197250x1044: { n:"ShtProps", f:parse_ShtProps },
197260x1045: { n:"SerToCrt" },
197270x1046: { n:"AxesUsed" },
197280x1048: { n:"SBaseRef" },
197290x104a: { n:"SerParent" },
197300x104b: { n:"SerAuxTrend" },
197310x104e: { n:"IFmtRecord" },
197320x104f: { n:"Pos" },
197330x1050: { n:"AlRuns" },
197340x1051: { n:"BRAI" },
197350x105b: { n:"SerAuxErrBar" },
197360x105c: { n:"ClrtClient", f:parse_ClrtClient },
197370x105d: { n:"SerFmt" },
197380x105f: { n:"Chart3DBarShape" },
197390x1060: { n:"Fbi" },
197400x1061: { n:"BopPop" },
197410x1062: { n:"AxcExt" },
197420x1063: { n:"Dat" },
197430x1064: { n:"PlotGrowth" },
197440x1065: { n:"SIIndex" },
197450x1066: { n:"GelFrame" },
197460x1067: { n:"BopPopCustom" },
197470x1068: { n:"Fbi2" },
19748
197490x0000: { n:"Dimensions", f:parse_Dimensions },
197500x0001: { n:"BIFF2BLANK" },
197510x0002: { n:"BIFF2INT", f:parse_BIFF2INT },
197520x0003: { n:"BIFF2NUM", f:parse_BIFF2NUM },
197530x0004: { n:"BIFF2STR", f:parse_BIFF2STR },
197540x0005: { n:"BoolErr", f:parse_BoolErr },
197550x0007: { n:"String", f:parse_BIFF2STRING },
197560x0008: { n:"BIFF2ROW" },
197570x0009: { n:'BOF', f:parse_BOF },
197580x000b: { n:"Index" },
197590x0016: { n:"ExternCount", f:parseuint16 },
197600x001e: { n:"BIFF2FORMAT", f:parse_BIFF2Format },
197610x001f: { n:"BIFF2FMTCNT" }, /* 16-bit cnt of BIFF2FORMAT records */
197620x0020: { n:"BIFF2COLINFO" },
197630x0021: { n:"Array", f:parse_Array },
197640x0024: { n:"COLWIDTH" },
197650x0025: { n:"DefaultRowHeight", f:parse_DefaultRowHeight },
19766 // 0x2c ??
19767 // 0x2d ??
19768 // 0x2e ??
19769 // 0x30 FONTCOUNT: number of fonts
197700x0032: { n:"BIFF2FONTXTRA", f:parse_BIFF2FONTXTRA },
19771 // 0x35: INFOOPTS
19772 // 0x36: TABLE (BIFF2 only)
19773 // 0x37: TABLE2 (BIFF2 only)
19774 // 0x38: WNDESK
19775 // 0x39 ??
19776 // 0x3a: BEGINPREF
19777 // 0x3b: ENDPREF
197780x003e: { n:"BIFF2WINDOW2" },
19779 // 0x3f ??
19780 // 0x46: SHOWSCROLL
19781 // 0x47: SHOWFORMULA
19782 // 0x48: STATUSBAR
19783 // 0x49: SHORTMENUS
19784 // 0x4A:
19785 // 0x4B:
19786 // 0x4C:
19787 // 0x4E:
19788 // 0x4F:
19789 // 0x58: TOOLBAR (BIFF3)
19790
19791 /* - - - */
197920x0034: { n:"DDEObjName" },
197930x0043: { n:"BIFF2XF" },
197940x0044: { n:"BIFF2XFINDEX", f:parseuint16 },
197950x0045: { n:"BIFF2FONTCLR" },
197960x0056: { n:"BIFF4FMTCNT" }, /* 16-bit cnt, similar to BIFF2 */
197970x007e: { n:"RK" }, /* Not necessarily same as 0x027e */
197980x007f: { n:"ImData", f:parse_ImData },
197990x0087: { n:"Addin" },
198000x0088: { n:"Edg" },
198010x0089: { n:"Pub" },
19802 // 0x8A
19803 // 0x8B LH: alternate menu key flag (BIFF3/4)
19804 // 0x8E
19805 // 0x8F
198060x0091: { n:"Sub" },
19807 // 0x93 STYLE
198080x0094: { n:"LHRecord" },
198090x0095: { n:"LHNGraph" },
198100x0096: { n:"Sound" },
19811 // 0xA2 FNPROTO: function prototypes (BIFF4)
19812 // 0xA3
19813 // 0xA8
198140x00a9: { n:"CoordList" },
198150x00ab: { n:"GCW" },
198160x00bc: { n:"ShrFmla" }, /* Not necessarily same as 0x04bc */
198170x00bf: { n:"ToolbarHdr" },
198180x00c0: { n:"ToolbarEnd" },
198190x00c2: { n:"AddMenu" },
198200x00c3: { n:"DelMenu" },
198210x00d6: { n:"RString", f:parse_RString },
198220x00df: { n:"UDDesc" },
198230x00ea: { n:"TabIdConf" },
198240x0162: { n:"XL5Modify" },
198250x01a5: { n:"FileSharing2" },
198260x0206: { n:"Formula", f:parse_Formula },
198270x0209: { n:'BOF', f:parse_BOF },
198280x0218: { n:"Lbl", f:parse_Lbl },
198290x0223: { n:"ExternName", f:parse_ExternName },
198300x0231: { n:"Font" },
198310x0243: { n:"BIFF3XF" },
198320x0406: { n:"Formula", f:parse_Formula },
198330x0409: { n:'BOF', f:parse_BOF },
198340x0443: { n:"BIFF4XF" },
198350x086d: { n:"FeatInfo" },
198360x0873: { n:"FeatInfo11" },
198370x0881: { n:"SXAddl12" },
198380x08c0: { n:"AutoWebPub" },
198390x08c1: { n:"ListObj" },
198400x08c2: { n:"ListField" },
198410x08c3: { n:"ListDV" },
198420x08c4: { n:"ListCondFmt" },
198430x08c5: { n:"ListCF" },
198440x08c6: { n:"FMQry" },
198450x08c7: { n:"FMSQry" },
198460x08c8: { n:"PLV" },
198470x08c9: { n:"LnExt" },
198480x08ca: { n:"MkrExt" },
198490x08cb: { n:"CrtCoopt" },
198500x08d6: { n:"FRTArchId$", r:12 },
19851
198520x7262: {}
19853};
19854
19855var XLSRE = evert_key(XLSRecordEnum, 'n');
19856function write_biff_rec(ba, type, payload, length) {
19857 var t = typeof type == "number" ? type : (+type || +XLSRE[type]);
19858 if(isNaN(t)) return;
19859 var len = length || (payload||[]).length || 0;
19860 var o = ba.next(4);
19861 o.write_shift(2, t);
19862 o.write_shift(2, len);
19863 if(len > 0 && is_buf(payload)) ba.push(payload);
19864}
19865
19866function write_biff_continue(ba, type, payload, length) {
19867 var len = length || (payload||[]).length || 0;
19868 if(len <= 8224) return write_biff_rec(ba, type, payload, len);
19869 var t = +type || +XLSRE[type];
19870 if(isNaN(t)) return;
19871 var parts = payload.parts || [], sidx = 0;
19872 var i = 0, w = 0;
19873 while(w + (parts[sidx] || 8224) <= 8224) { w+= (parts[sidx] || 8224); sidx++; }
19874 var o = ba.next(4);
19875 o.write_shift(2, t);
19876 o.write_shift(2, w);
19877 ba.push(payload.slice(i, i + w));
19878 i += w;
19879 while(i < len) {
19880 o = ba.next(4);
19881 o.write_shift(2, 0x3c); // TODO: figure out correct continue type
19882 w = 0;
19883 while(w + (parts[sidx] || 8224) <= 8224) { w+= (parts[sidx] || 8224); sidx++; }
19884 o.write_shift(2, w);
19885 ba.push(payload.slice(i, i+w)); i+= w;
19886 }
19887}
19888
19889function write_BIFF2Cell(out, r, c) {
19890 if(!out) out = new_buf(7);
19891 out.write_shift(2, r);
19892 out.write_shift(2, c);
19893 out.write_shift(2, 0);
19894 out.write_shift(1, 0);
19895 return out;
19896}
19897
19898function write_BIFF2BERR(r, c, val, t) {
19899 var out = new_buf(9);
19900 write_BIFF2Cell(out, r, c);
19901 write_Bes(val, t || 'b', out);
19902 return out;
19903}
19904
19905/* TODO: codepage, large strings */
19906function write_BIFF2LABEL(r, c, val) {
19907 var out = new_buf(8 + 2*val.length);
19908 write_BIFF2Cell(out, r, c);
19909 out.write_shift(1, val.length);
19910 out.write_shift(val.length, val, 'sbcs');
19911 return out.l < out.length ? out.slice(0, out.l) : out;
19912}
19913
19914function write_ws_biff2_cell(ba, cell, R, C) {
19915 if(cell.v != null) switch(cell.t) {
19916 case 'd': case 'n':
19917 var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
19918 if((v == (v|0)) && (v >= 0) && (v < 65536))
19919 write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v));
19920 else
19921 write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v));
19922 return;
19923 case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
19924 /* TODO: codepage, sst */
19925 case 's': case 'str':
19926 write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, (cell.v||"").slice(0,255)));
19927 return;
19928 }
19929 write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
19930}
19931
19932function write_ws_biff2(ba, ws, idx, opts) {
19933 var dense = Array.isArray(ws);
19934 var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = [];
19935 if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
19936 if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
19937 range.e.c = Math.min(range.e.c, 0xFF);
19938 range.e.r = Math.min(range.e.c, 0x3FFF);
19939 ref = encode_range(range);
19940 }
19941 for(var R = range.s.r; R <= range.e.r; ++R) {
19942 rr = encode_row(R);
19943 for(var C = range.s.c; C <= range.e.c; ++C) {
19944 if(R === range.s.r) cols[C] = encode_col(C);
19945 ref = cols[C] + rr;
19946 var cell = dense ? (ws[R]||[])[C] : ws[ref];
19947 if(!cell) continue;
19948 /* write cell */
19949 write_ws_biff2_cell(ba, cell, R, C, opts);
19950 }
19951 }
19952}
19953
19954/* Based on test files */
19955function write_biff2_buf(wb, opts) {
19956 var o = opts || {};
19957 if(DENSE != null && o.dense == null) o.dense = DENSE;
19958 var ba = buf_array();
19959 var idx = 0;
19960 for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i;
19961 if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
19962 write_biff_rec(ba, (o.biff == 4 ? 0x0409 : (o.biff == 3 ? 0x0209 : 0x0009)), write_BOF(wb, 0x10, o));
19963 /* ... */
19964 write_ws_biff2(ba, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
19965 /* ... */
19966 write_biff_rec(ba, 0x000A);
19967 return ba.end();
19968}
19969
19970function write_FONTS_biff8(ba, data, opts) {
19971 write_biff_rec(ba, "Font", write_Font({
19972 sz:12,
19973 color: {theme:1},
19974 name: "Arial",
19975 family: 2,
19976 scheme: "minor"
19977 }, opts));
19978}
19979
19980
19981function write_FMTS_biff8(ba, NF, opts) {
19982 if(!NF) return;
19983 [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
19984for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_biff_rec(ba, "Format", write_Format(i, NF[i], opts));
19985 });
19986}
19987
19988function write_FEAT(ba, ws) {
19989 /* [MS-XLS] 2.4.112 */
19990 var o = new_buf(19);
19991 o.write_shift(4, 0x867); o.write_shift(4, 0); o.write_shift(4, 0);
19992 o.write_shift(2, 3); o.write_shift(1, 1); o.write_shift(4, 0);
19993 write_biff_rec(ba, "FeatHdr", o);
19994 /* [MS-XLS] 2.4.111 */
19995 o = new_buf(39);
19996 o.write_shift(4, 0x868); o.write_shift(4, 0); o.write_shift(4, 0);
19997 o.write_shift(2, 3); o.write_shift(1, 0); o.write_shift(4, 0);
19998 o.write_shift(2, 1); o.write_shift(4, 4); o.write_shift(2, 0);
19999 write_Ref8U(safe_decode_range(ws['!ref']||"A1"), o);
20000 o.write_shift(4, 4);
20001 write_biff_rec(ba, "Feat", o);
20002}
20003
20004function write_CELLXFS_biff8(ba, opts) {
20005 for(var i = 0; i < 16; ++i) write_biff_rec(ba, "XF", write_XF({numFmtId:0, style:true}, 0, opts));
20006 opts.cellXfs.forEach(function(c) {
20007 write_biff_rec(ba, "XF", write_XF(c, 0, opts));
20008 });
20009}
20010
20011function write_ws_biff8_hlinks(ba, ws) {
20012 for(var R=0; R<ws['!links'].length; ++R) {
20013 var HL = ws['!links'][R];
20014 write_biff_rec(ba, "HLink", write_HLink(HL));
20015 if(HL[1].Tooltip) write_biff_rec(ba, "HLinkTooltip", write_HLinkTooltip(HL));
20016 }
20017 delete ws['!links'];
20018}
20019
20020function write_ws_cols_biff8(ba, cols, ws) {
20021 if(!cols) return;
20022 var cnt = 0;
20023 cols.forEach(function(col, idx) {
20024 if(++cnt <= 256 && col) {
20025 write_biff_rec(ba, "ColInfo", write_ColInfo(col_obj_w(idx, col), idx));
20026 }
20027 });
20028}
20029
20030function write_ws_biff8_cell(ba, cell, R, C, opts) {
20031 var os = 16 + get_cell_style(opts.cellXfs, cell, opts);
20032 if(cell.v == null && !cell.bf) {
20033 write_biff_rec(ba, "Blank", write_XLSCell(R, C, os));
20034 return;
20035 }
20036 if(cell.bf) write_biff_rec(ba, "Formula", write_Formula(cell, R, C, opts, os));
20037 else switch(cell.t) {
20038 case 'd': case 'n':
20039 var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
20040 /* TODO: emit RK as appropriate */
20041 write_biff_rec(ba, "Number", write_Number(R, C, v, os, opts));
20042 break;
20043 case 'b': case 'e':
20044 write_biff_rec(ba, 0x0205, write_BoolErr(R, C, cell.v, os, opts, cell.t));
20045 break;
20046 /* TODO: codepage, sst */
20047 case 's': case 'str':
20048 if(opts.bookSST) {
20049 var isst = get_sst_id(opts.Strings, cell.v, opts.revStrings);
20050 write_biff_rec(ba, "LabelSst", write_LabelSst(R, C, isst, os, opts));
20051 } else write_biff_rec(ba, "Label", write_Label(R, C, (cell.v||"").slice(0,255), os, opts));
20052 break;
20053 default:
20054 write_biff_rec(ba, "Blank", write_XLSCell(R, C, os));
20055 }
20056}
20057
20058/* [MS-XLS] 2.1.7.20.5 */
20059function write_ws_biff8(idx, opts, wb) {
20060 var ba = buf_array();
20061 var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
20062 var _WB = ((wb||{}).Workbook||{});
20063 var _sheet = ((_WB.Sheets||[])[idx]||{});
20064 var dense = Array.isArray(ws);
20065 var b8 = opts.biff == 8;
20066 var ref, rr = "", cols = [];
20067 var range = safe_decode_range(ws['!ref'] || "A1");
20068 var MAX_ROWS = b8 ? 65536 : 16384;
20069 if(range.e.c > 0xFF || range.e.r >= MAX_ROWS) {
20070 if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
20071 range.e.c = Math.min(range.e.c, 0xFF);
20072 range.e.r = Math.min(range.e.c, MAX_ROWS-1);
20073 }
20074
20075 write_biff_rec(ba, 0x0809, write_BOF(wb, 0x10, opts));
20076 /* [Uncalced] Index */
20077 write_biff_rec(ba, "CalcMode", writeuint16(1));
20078 write_biff_rec(ba, "CalcCount", writeuint16(100));
20079 write_biff_rec(ba, "CalcRefMode", writebool(true));
20080 write_biff_rec(ba, "CalcIter", writebool(false));
20081 write_biff_rec(ba, "CalcDelta", write_Xnum(0.001));
20082 write_biff_rec(ba, "CalcSaveRecalc", writebool(true));
20083 write_biff_rec(ba, "PrintRowCol", writebool(false));
20084 write_biff_rec(ba, "PrintGrid", writebool(false));
20085 write_biff_rec(ba, "GridSet", writeuint16(1));
20086 write_biff_rec(ba, "Guts", write_Guts([0,0]));
20087 /* DefaultRowHeight WsBool [Sync] [LPr] [HorizontalPageBreaks] [VerticalPageBreaks] */
20088 /* Header (string) */
20089 /* Footer (string) */
20090 write_biff_rec(ba, "HCenter", writebool(false));
20091 write_biff_rec(ba, "VCenter", writebool(false));
20092 /* ... */
20093 if(b8) write_ws_cols_biff8(ba, ws["!cols"], ws);
20094 /* ... */
20095 write_biff_rec(ba, 0x200, write_Dimensions(range, opts));
20096 /* ... */
20097
20098 if(b8) ws['!links'] = [];
20099 for(var R = range.s.r; R <= range.e.r; ++R) {
20100 rr = encode_row(R);
20101 for(var C = range.s.c; C <= range.e.c; ++C) {
20102 if(R === range.s.r) cols[C] = encode_col(C);
20103 ref = cols[C] + rr;
20104 var cell = dense ? (ws[R]||[])[C] : ws[ref];
20105 if(!cell) continue;
20106 /* write cell */
20107 write_ws_biff8_cell(ba, cell, R, C, opts);
20108 if(b8 && cell.l) ws['!links'].push([ref, cell.l]);
20109 }
20110 }
20111 var cname = _sheet.CodeName || _sheet.name || s;
20112 /* ... */
20113 if(b8) write_biff_rec(ba, "Window2", write_Window2((_WB.Views||[])[0]));
20114 /* ... */
20115 if(b8 && (ws['!merges']||[]).length) write_biff_rec(ba, "MergeCells", write_MergeCells(ws['!merges']));
20116 /* [LRng] *QUERYTABLE [PHONETICINFO] CONDFMTS */
20117 if(b8) write_ws_biff8_hlinks(ba, ws);
20118 /* [DVAL] */
20119 write_biff_rec(ba, "CodeName", write_XLUnicodeString(cname, opts));
20120 /* *WebPub *CellWatch [SheetExt] */
20121 if(b8) write_FEAT(ba, ws);
20122 /* *FEAT11 *RECORD12 */
20123 write_biff_rec(ba, "EOF");
20124 return ba.end();
20125}
20126
20127/* [MS-XLS] 2.1.7.20.3 */
20128function write_biff8_global(wb, bufs, opts) {
20129 var A = buf_array();
20130 var _WB = ((wb||{}).Workbook||{});
20131 var _sheets = (_WB.Sheets||[]);
20132 var _wb = _WB.WBProps||{};
20133 var b8 = opts.biff == 8, b5 = opts.biff == 5;
20134 write_biff_rec(A, 0x0809, write_BOF(wb, 0x05, opts));
20135 if(opts.bookType == "xla") write_biff_rec(A, "Addin");
20136 write_biff_rec(A, "InterfaceHdr", b8 ? writeuint16(0x04b0) : null);
20137 write_biff_rec(A, "Mms", writezeroes(2));
20138 if(b5) write_biff_rec(A, "ToolbarHdr");
20139 if(b5) write_biff_rec(A, "ToolbarEnd");
20140 write_biff_rec(A, "InterfaceEnd");
20141 write_biff_rec(A, "WriteAccess", write_WriteAccess("SheetJS", opts));
20142 /* [FileSharing] */
20143 write_biff_rec(A, "CodePage", writeuint16(b8 ? 0x04b0 : 0x04E4));
20144 /* *2047 Lel */
20145 if(b8) write_biff_rec(A, "DSF", writeuint16(0));
20146 if(b8) write_biff_rec(A, "Excel9File");
20147 write_biff_rec(A, "RRTabId", write_RRTabId(wb.SheetNames.length));
20148 if(b8 && wb.vbaraw) write_biff_rec(A, "ObProj");
20149 /* [ObNoMacros] */
20150 if(b8 && wb.vbaraw) {
20151 var cname = _wb.CodeName || "ThisWorkbook";
20152 write_biff_rec(A, "CodeName", write_XLUnicodeString(cname, opts));
20153 }
20154 write_biff_rec(A, "BuiltInFnGroupCount", writeuint16(0x11));
20155 /* *FnGroupName *FnGrp12 */
20156 /* *Lbl */
20157 /* [OleObjectSize] */
20158 write_biff_rec(A, "WinProtect", writebool(false));
20159 write_biff_rec(A, "Protect", writebool(false));
20160 write_biff_rec(A, "Password", writeuint16(0));
20161 if(b8) write_biff_rec(A, "Prot4Rev", writebool(false));
20162 if(b8) write_biff_rec(A, "Prot4RevPass", writeuint16(0));
20163 write_biff_rec(A, "Window1", write_Window1(opts));
20164 write_biff_rec(A, "Backup", writebool(false));
20165 write_biff_rec(A, "HideObj", writeuint16(0));
20166 write_biff_rec(A, "Date1904", writebool(safe1904(wb)=="true"));
20167 write_biff_rec(A, "CalcPrecision", writebool(true));
20168 if(b8) write_biff_rec(A, "RefreshAll", writebool(false));
20169 write_biff_rec(A, "BookBool", writeuint16(0));
20170 /* ... */
20171 write_FONTS_biff8(A, wb, opts);
20172 write_FMTS_biff8(A, wb.SSF, opts);
20173 write_CELLXFS_biff8(A, opts);
20174 /* ... */
20175 if(b8) write_biff_rec(A, "UsesELFs", writebool(false));
20176 var a = A.end();
20177
20178 var C = buf_array();
20179 /* METADATA [MTRSettings] [ForceFullCalculation] */
20180 if(b8) write_biff_rec(C, "Country", write_Country());
20181 /* *SUPBOOK *LBL *RTD [RecalcId] *HFPicture *MSODRAWINGGROUP */
20182
20183 /* BIFF8: [SST *Continue] ExtSST */
20184 if(b8 && opts.Strings) write_biff_continue(C, "SST", write_SST(opts.Strings, opts));
20185
20186 /* *WebPub [WOpt] [CrErr] [BookExt] *FeatHdr *DConn [THEME] [CompressPictures] [Compat12] [GUIDTypeLib] */
20187 write_biff_rec(C, "EOF");
20188 var c = C.end();
20189
20190 var B = buf_array();
20191 var blen = 0, j = 0;
20192 for(j = 0; j < wb.SheetNames.length; ++j) blen += (b8 ? 12 : 11) + (b8 ? 2 : 1) * wb.SheetNames[j].length;
20193 var start = a.length + blen + c.length;
20194 for(j = 0; j < wb.SheetNames.length; ++j) {
20195 var _sheet = _sheets[j] || ({});
20196 write_biff_rec(B, "BoundSheet8", write_BoundSheet8({pos:start, hs:_sheet.Hidden||0, dt:0, name:wb.SheetNames[j]}, opts));
20197 start += bufs[j].length;
20198 }
20199 /* 1*BoundSheet8 */
20200 var b = B.end();
20201 if(blen != b.length) throw new Error("BS8 " + blen + " != " + b.length);
20202
20203 var out = [];
20204 if(a.length) out.push(a);
20205 if(b.length) out.push(b);
20206 if(c.length) out.push(c);
20207 return __toBuffer([out]);
20208}
20209
20210/* [MS-XLS] 2.1.7.20 Workbook Stream */
20211function write_biff8_buf(wb, opts) {
20212 var o = opts || {};
20213 var bufs = [];
20214
20215 if(wb && !wb.SSF) {
20216 wb.SSF = SSF.get_table();
20217 }
20218 if(wb && wb.SSF) {
20219 make_ssf(SSF); SSF.load_table(wb.SSF);
20220 // $FlowIgnore
20221 o.revssf = evert_num(wb.SSF); o.revssf[wb.SSF[65535]] = 0;
20222 o.ssf = wb.SSF;
20223 }
20224
20225 o.Strings = []; o.Strings.Count = 0; o.Strings.Unique = 0;
20226 fix_write_opts(o);
20227
20228 o.cellXfs = [];
20229 get_cell_style(o.cellXfs, {}, {revssf:{"General":0}});
20230
20231 if(!wb.Props) wb.Props = {};
20232
20233 for(var i = 0; i < wb.SheetNames.length; ++i) bufs[bufs.length] = write_ws_biff8(i, o, wb);
20234 bufs.unshift(write_biff8_global(wb, bufs, o));
20235 return __toBuffer([bufs]);
20236}
20237
20238function write_biff_buf(wb, opts) {
20239 var o = opts || {};
20240 switch(o.biff || 2) {
20241 case 8: case 5: return write_biff8_buf(wb, opts);
20242 case 4: case 3: case 2: return write_biff2_buf(wb, opts);
20243 }
20244 throw new Error("invalid type " + o.bookType + " for BIFF");
20245}
20246/* note: browser DOM element cannot see mso- style attrs, must parse */
20247var HTML_ = (function() {
20248 function html_to_sheet(str, _opts) {
20249 var opts = _opts || {};
20250 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
20251 var ws = opts.dense ? ([]) : ({});
20252 str = str.replace(/<!--.*?-->/g, "");
20253 var mtch = str.match(/<table/i);
20254 if(!mtch) throw new Error("Invalid HTML: could not find <table>");
20255 var mtch2 = str.match(/<\/table/i);
20256 var i = mtch.index, j = mtch2 && mtch2.index || str.length;
20257 var rows = split_regex(str.slice(i, j), /(:?<tr[^>]*>)/i, "<tr>");
20258 var R = -1, C = 0, RS = 0, CS = 0;
20259 var range = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
20260 var merges = [];
20261 for(i = 0; i < rows.length; ++i) {
20262 var row = rows[i].trim();
20263 var hd = row.slice(0,3).toLowerCase();
20264 if(hd == "<tr") { ++R; if(opts.sheetRows && opts.sheetRows <= R) { --R; break; } C = 0; continue; }
20265 if(hd != "<td" && hd != "<th") continue;
20266 var cells = row.split(/<\/t[dh]>/i);
20267 for(j = 0; j < cells.length; ++j) {
20268 var cell = cells[j].trim();
20269 if(!cell.match(/<t[dh]/i)) continue;
20270 var m = cell, cc = 0;
20271 /* TODO: parse styles etc */
20272 while(m.charAt(0) == "<" && (cc = m.indexOf(">")) > -1) m = m.slice(cc+1);
20273 for(var midx = 0; midx < merges.length; ++midx) {
20274 var _merge = merges[midx];
20275 if(_merge.s.c == C && _merge.s.r < R && R <= _merge.e.r) { C = _merge.e.c + 1; midx = -1; }
20276 }
20277 var tag = parsexmltag(cell.slice(0, cell.indexOf(">")));
20278 CS = tag.colspan ? +tag.colspan : 1;
20279 if((RS = +tag.rowspan)>1 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
20280 var _t = tag.t || tag["data-t"] || "";
20281 /* TODO: generate stub cells */
20282 if(!m.length) { C += CS; continue; }
20283 m = htmldecode(m);
20284 if(range.s.r > R) range.s.r = R; if(range.e.r < R) range.e.r = R;
20285 if(range.s.c > C) range.s.c = C; if(range.e.c < C) range.e.c = C;
20286 if(!m.length) continue;
20287 var o = {t:'s', v:m};
20288 if(opts.raw || !m.trim().length || _t == 's'){}
20289 else if(m === 'TRUE') o = {t:'b', v:true};
20290 else if(m === 'FALSE') o = {t:'b', v:false};
20291 else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)};
20292 else if(!isNaN(fuzzydate(m).getDate())) {
20293 o = ({t:'d', v:parseDate(m)});
20294 if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)});
20295 o.z = opts.dateNF || SSF._table[14];
20296 }
20297 if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; }
20298 else ws[encode_cell({r:R, c:C})] = o;
20299 C += CS;
20300 }
20301 }
20302 ws['!ref'] = encode_range(range);
20303 if(merges.length) ws["!merges"] = merges;
20304 return ws;
20305 }
20306 function html_to_book(str, opts) {
20307 var mtch = str.match(/<table.*?>[\s\S]*?<\/table>/gi);
20308 if(!mtch || mtch.length == 0) throw new Error("Invalid HTML: could not find <table>");
20309 if(mtch.length == 1) return sheet_to_workbook(html_to_sheet(mtch[0], opts), opts);
20310 var wb = utils.book_new();
20311 mtch.forEach(function(s, idx) { utils.book_append_sheet(wb, html_to_sheet(s, opts), "Sheet" + (idx+1)); });
20312 return wb;
20313 }
20314 function make_html_row(ws, r, R, o) {
20315 var M = (ws['!merges'] ||[]);
20316 var oo = [];
20317 for(var C = r.s.c; C <= r.e.c; ++C) {
20318 var RS = 0, CS = 0;
20319 for(var j = 0; j < M.length; ++j) {
20320 if(M[j].s.r > R || M[j].s.c > C) continue;
20321 if(M[j].e.r < R || M[j].e.c < C) continue;
20322 if(M[j].s.r < R || M[j].s.c < C) { RS = -1; break; }
20323 RS = M[j].e.r - M[j].s.r + 1; CS = M[j].e.c - M[j].s.c + 1; break;
20324 }
20325 if(RS < 0) continue;
20326 var coord = encode_cell({r:R,c:C});
20327 var cell = o.dense ? (ws[R]||[])[C] : ws[coord];
20328 /* TODO: html entities */
20329 var w = (cell && cell.v != null) && (cell.h || escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || "";
20330 var sp = ({});
20331 if(RS > 1) sp.rowspan = RS;
20332 if(CS > 1) sp.colspan = CS;
20333 if(o.editable) w = '<span contenteditable="true">' + w + '</span>';
20334 else if(cell) {
20335 sp["data-t"] = cell && cell.t || 'z';
20336 if(cell.v != null) sp["data-v"] = cell.v;
20337 if(cell.z != null) sp["data-z"] = cell.z;
20338 if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + cell.l.Target +'">' + w + '</a>';
20339 }
20340 sp.id = (o.id || "sjs") + "-" + coord;
20341 oo.push(writextag('td', w, sp));
20342 }
20343 var preamble = "<tr>";
20344 return preamble + oo.join("") + "</tr>";
20345 }
20346 function make_html_preamble(ws, R, o) {
20347 var out = [];
20348 return out.join("") + '<table' + (o && o.id ? ' id="' + o.id + '"' : "") + '>';
20349 }
20350 var _BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
20351 var _END = '</body></html>';
20352 function sheet_to_html(ws, opts/*, wb:?Workbook*/) {
20353 var o = opts || {};
20354 var header = o.header != null ? o.header : _BEGIN;
20355 var footer = o.footer != null ? o.footer : _END;
20356 var out = [header];
20357 var r = decode_range(ws['!ref']);
20358 o.dense = Array.isArray(ws);
20359 out.push(make_html_preamble(ws, r, o));
20360 for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
20361 out.push("</table>" + footer);
20362 return out.join("");
20363
20364 }
20365 return {
20366 to_workbook: html_to_book,
20367 to_sheet: html_to_sheet,
20368 _row: make_html_row,
20369 BEGIN: _BEGIN,
20370 END: _END,
20371 _preamble: make_html_preamble,
20372 from_sheet: sheet_to_html
20373 };
20374})();
20375
20376function sheet_add_dom(ws, table, _opts) {
20377 var opts = _opts || {};
20378 if(DENSE != null) opts.dense = DENSE;
20379 var or_R = 0, or_C = 0;
20380 if(opts.origin != null) {
20381 if(typeof opts.origin == 'number') or_R = opts.origin;
20382 else {
20383 var _origin = typeof opts.origin == "string" ? decode_cell(opts.origin) : opts.origin;
20384 or_R = _origin.r; or_C = _origin.c;
20385 }
20386 }
20387 var rows = table.getElementsByTagName('tr');
20388 var sheetRows = Math.min(opts.sheetRows||10000000, rows.length);
20389 var range = {s:{r:0,c:0},e:{r:or_R,c:or_C}};
20390 if(ws["!ref"]) {
20391 var _range = decode_range(ws["!ref"]);
20392 range.s.r = Math.min(range.s.r, _range.s.r);
20393 range.s.c = Math.min(range.s.c, _range.s.c);
20394 range.e.r = Math.max(range.e.r, _range.e.r);
20395 range.e.c = Math.max(range.e.c, _range.e.c);
20396 if(or_R == -1) range.e.r = or_R = _range.e.r + 1;
20397 }
20398 var merges = [], midx = 0;
20399 var rowinfo = ws["!rows"] || (ws["!rows"] = []);
20400 var _R = 0, R = 0, _C = 0, C = 0, RS = 0, CS = 0;
20401 if(!ws["!cols"]) ws['!cols'] = [];
20402 for(; _R < rows.length && R < sheetRows; ++_R) {
20403 var row = rows[_R];
20404 if (is_dom_element_hidden(row)) {
20405 if (opts.display) continue;
20406 rowinfo[R] = {hidden: true};
20407 }
20408 var elts = (row.children);
20409 for(_C = C = 0; _C < elts.length; ++_C) {
20410 var elt = elts[_C];
20411 if (opts.display && is_dom_element_hidden(elt)) continue;
20412 var v = elt.hasAttribute('data-v') ? elt.getAttribute('data-v') : elt.hasAttribute('v') ? elt.getAttribute('v') : htmldecode(elt.innerHTML);
20413 var z = elt.getAttribute('data-z') || elt.getAttribute('z');
20414 for(midx = 0; midx < merges.length; ++midx) {
20415 var m = merges[midx];
20416 if(m.s.c == C + or_C && m.s.r < R + or_R && R + or_R <= m.e.r) { C = m.e.c+1 - or_C; midx = -1; }
20417 }
20418 /* TODO: figure out how to extract nonstandard mso- style */
20419 CS = +elt.getAttribute("colspan") || 1;
20420 if( ((RS = (+elt.getAttribute("rowspan") || 1)))>1 || CS>1) merges.push({s:{r:R + or_R,c:C + or_C},e:{r:R + or_R + (RS||1) - 1, c:C + or_C + (CS||1) - 1}});
20421 var o = {t:'s', v:v};
20422 var _t = elt.getAttribute("data-t") || elt.getAttribute("t") || "";
20423 if(v != null) {
20424 if(v.length == 0) o.t = _t || 'z';
20425 else if(opts.raw || v.trim().length == 0 || _t == "s"){}
20426 else if(v === 'TRUE') o = {t:'b', v:true};
20427 else if(v === 'FALSE') o = {t:'b', v:false};
20428 else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
20429 else if(!isNaN(fuzzydate(v).getDate())) {
20430 o = ({t:'d', v:parseDate(v)});
20431 if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)});
20432 o.z = opts.dateNF || SSF._table[14];
20433 }
20434 }
20435 if(o.z === undefined && z != null) o.z = z;
20436 /* The first link is used. Links are assumed to be fully specified.
20437 * TODO: The right way to process relative links is to make a new <a> */
20438 var l = "", Aelts = elt.getElementsByTagName("A");
20439 if(Aelts && Aelts.length) for(var Aelti = 0; Aelti < Aelts.length; ++Aelti) if(Aelts[Aelti].hasAttribute("href")) {
20440 l = Aelts[Aelti].getAttribute("href"); if(l.charAt(0) != "#") break;
20441 }
20442 if(l && l.charAt(0) != "#") o.l = ({ Target: l });
20443 if(opts.dense) { if(!ws[R + or_R]) ws[R + or_R] = []; ws[R + or_R][C + or_C] = o; }
20444 else ws[encode_cell({c:C + or_C, r:R + or_R})] = o;
20445 if(range.e.c < C + or_C) range.e.c = C + or_C;
20446 C += CS;
20447 }
20448 ++R;
20449 }
20450 if(merges.length) ws['!merges'] = (ws["!merges"] || []).concat(merges);
20451 range.e.r = Math.max(range.e.r, R - 1 + or_R);
20452 ws['!ref'] = encode_range(range);
20453 if(R >= sheetRows) ws['!fullref'] = encode_range((range.e.r = rows.length-_R+R-1 + or_R,range)); // We can count the real number of rows to parse but we don't to improve the performance
20454 return ws;
20455}
20456
20457function parse_dom_table(table, _opts) {
20458 var opts = _opts || {};
20459 var ws = opts.dense ? ([]) : ({});
20460 return sheet_add_dom(ws, table, _opts);
20461}
20462
20463function table_to_book(table, opts) {
20464 return sheet_to_workbook(parse_dom_table(table, opts), opts);
20465}
20466
20467function is_dom_element_hidden(element) {
20468 var display = '';
20469 var get_computed_style = get_get_computed_style_function(element);
20470 if(get_computed_style) display = get_computed_style(element).getPropertyValue('display');
20471 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)
20472 return display === 'none';
20473}
20474
20475/* global getComputedStyle */
20476function get_get_computed_style_function(element) {
20477 // The proper getComputedStyle implementation is the one defined in the element window
20478 if(element.ownerDocument.defaultView && typeof element.ownerDocument.defaultView.getComputedStyle === 'function') return element.ownerDocument.defaultView.getComputedStyle;
20479 // If it is not available, try to get one from the global namespace
20480 if(typeof getComputedStyle === 'function') return getComputedStyle;
20481 return null;
20482}
20483/* OpenDocument */
20484var parse_content_xml = (function() {
20485
20486 var parse_text_p = function(text) {
20487 /* 6.1.2 White Space Characters */
20488 var fixed = text
20489 .replace(/[\t\r\n]/g, " ").trim().replace(/ +/g, " ")
20490 .replace(/<text:s\/>/g," ")
20491 .replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); })
20492 .replace(/<text:tab[^>]*\/>/g,"\t")
20493 .replace(/<text:line-break\/>/g,"\n");
20494 var v = unescapexml(fixed.replace(/<[^>]*>/g,""));
20495
20496 return [v];
20497 };
20498
20499 var number_formats = {
20500 /* ods name: [short ssf fmt, long ssf fmt] */
20501 day: ["d", "dd"],
20502 month: ["m", "mm"],
20503 year: ["y", "yy"],
20504 hours: ["h", "hh"],
20505 minutes: ["m", "mm"],
20506 seconds: ["s", "ss"],
20507 "am-pm": ["A/P", "AM/PM"],
20508 "day-of-week": ["ddd", "dddd"],
20509 era: ["e", "ee"],
20510 /* there is no native representation of LO "Q" format */
20511 quarter: ["\\Qm", "m\\\"th quarter\""]
20512 };
20513
20514 return function pcx(d, _opts) {
20515 var opts = _opts || {};
20516 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
20517 var str = xlml_normalize(d);
20518 var state = [], tmp;
20519 var tag;
20520 var NFtag = {name:""}, NF = "", pidx = 0;
20521 var sheetag;
20522 var rowtag;
20523 var Sheets = {}, SheetNames = [];
20524 var ws = opts.dense ? ([]) : ({});
20525 var Rn, q;
20526 var ctag = ({value:""});
20527 var textp = "", textpidx = 0, textptag;
20528 var textR = [];
20529 var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
20530 var row_ol = 0;
20531 var number_format_map = {};
20532 var merges = [], mrange = {}, mR = 0, mC = 0;
20533 var rowinfo = [], rowpeat = 1, colpeat = 1;
20534 var arrayf = [];
20535 var WB = {Names:[]};
20536 var atag = ({});
20537 var _Ref = ["", ""];
20538 var comments = [], comment = ({});
20539 var creator = "", creatoridx = 0;
20540 var isstub = false, intable = false;
20541 var i = 0;
20542 xlmlregex.lastIndex = 0;
20543 str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
20544 while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
20545
20546 case 'table': case '工作表': // 9.1.2 <table:table>
20547 if(Rn[1]==='/') {
20548 if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = encode_range(range);
20549 else ws['!ref'] = "A1:A1";
20550 if(opts.sheetRows > 0 && opts.sheetRows <= range.e.r) {
20551 ws['!fullref'] = ws['!ref'];
20552 range.e.r = opts.sheetRows - 1;
20553 ws['!ref'] = encode_range(range);
20554 }
20555 if(merges.length) ws['!merges'] = merges;
20556 if(rowinfo.length) ws["!rows"] = rowinfo;
20557 sheetag.name = sheetag['名称'] || sheetag.name;
20558 if(typeof JSON !== 'undefined') JSON.stringify(sheetag);
20559 SheetNames.push(sheetag.name);
20560 Sheets[sheetag.name] = ws;
20561 intable = false;
20562 }
20563 else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
20564 sheetag = parsexmltag(Rn[0], false);
20565 R = C = -1;
20566 range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0;
20567 ws = opts.dense ? ([]) : ({}); merges = [];
20568 rowinfo = [];
20569 intable = true;
20570 }
20571 break;
20572
20573 case 'table-row-group': // 9.1.9 <table:table-row-group>
20574 if(Rn[1] === "/") --row_ol; else ++row_ol;
20575 break;
20576 case 'table-row': case '行': // 9.1.3 <table:table-row>
20577 if(Rn[1] === '/') { R+=rowpeat; rowpeat = 1; break; }
20578 rowtag = parsexmltag(Rn[0], false);
20579 if(rowtag['行号']) R = rowtag['行号'] - 1; else if(R == -1) R = 0;
20580 rowpeat = +rowtag['number-rows-repeated'] || 1;
20581 /* TODO: remove magic */
20582 if(rowpeat < 10) for(i = 0; i < rowpeat; ++i) if(row_ol > 0) rowinfo[R + i] = {level: row_ol};
20583 C = -1; break;
20584 case 'covered-table-cell': // 9.1.5 <table:covered-table-cell>
20585 if(Rn[1] !== '/') ++C;
20586 if(opts.sheetStubs) {
20587 if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = {t:'z'}; }
20588 else ws[encode_cell({r:R,c:C})] = {t:'z'};
20589 }
20590 textp = ""; textR = [];
20591 break; /* stub */
20592 case 'table-cell': case '数据':
20593 if(Rn[0].charAt(Rn[0].length-2) === '/') {
20594 ++C;
20595 ctag = parsexmltag(Rn[0], false);
20596 colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
20597 q = ({t:'z', v:null});
20598 if(ctag.formula && opts.cellFormula != false) q.f = ods_to_csf_formula(unescapexml(ctag.formula));
20599 if((ctag['数据类型'] || ctag['value-type']) == "string") {
20600 q.t = "s"; q.v = unescapexml(ctag['string-value'] || "");
20601 if(opts.dense) {
20602 if(!ws[R]) ws[R] = [];
20603 ws[R][C] = q;
20604 } else {
20605 ws[encode_cell({r:R,c:C})] = q;
20606 }
20607 }
20608 C+= colpeat-1;
20609 } else if(Rn[1]!=='/') {
20610 ++C;
20611 textp = ""; textpidx = 0; textR = [];
20612 colpeat = 1;
20613 var rptR = rowpeat ? R + rowpeat - 1 : R;
20614 if(C > range.e.c) range.e.c = C;
20615 if(C < range.s.c) range.s.c = C;
20616 if(R < range.s.r) range.s.r = R;
20617 if(rptR > range.e.r) range.e.r = rptR;
20618 ctag = parsexmltag(Rn[0], false);
20619 comments = []; comment = ({});
20620 q = ({t:ctag['数据类型'] || ctag['value-type'], v:null});
20621 if(opts.cellFormula) {
20622 if(ctag.formula) ctag.formula = unescapexml(ctag.formula);
20623 if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
20624 mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
20625 mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
20626 mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
20627 q.F = encode_range(mrange);
20628 arrayf.push([mrange, q.F]);
20629 }
20630 if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula);
20631 else for(i = 0; i < arrayf.length; ++i)
20632 if(R >= arrayf[i][0].s.r && R <= arrayf[i][0].e.r)
20633 if(C >= arrayf[i][0].s.c && C <= arrayf[i][0].e.c)
20634 q.F = arrayf[i][1];
20635 }
20636 if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) {
20637 mR = parseInt(ctag['number-rows-spanned'],10) || 0;
20638 mC = parseInt(ctag['number-columns-spanned'],10) || 0;
20639 mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
20640 merges.push(mrange);
20641 }
20642
20643 /* 19.675.2 table:number-columns-repeated */
20644 if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10);
20645
20646 /* 19.385 office:value-type */
20647 switch(q.t) {
20648 case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break;
20649 case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break;
20650 case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break;
20651 case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break;
20652 case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']);
20653 if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v); }
20654 q.z = 'm/d/yy'; break;
20655 case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400;
20656 if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); }
20657 q.z = 'HH:MM:SS'; break;
20658 case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
20659 default:
20660 if(q.t === 'string' || q.t === 'text' || !q.t) {
20661 q.t = 's';
20662 if(ctag['string-value'] != null) { textp = unescapexml(ctag['string-value']); textR = []; }
20663 } else throw new Error('Unsupported value type ' + q.t);
20664 }
20665 } else {
20666 isstub = false;
20667 if(q.t === 's') {
20668 q.v = textp || '';
20669 if(textR.length) q.R = textR;
20670 isstub = textpidx == 0;
20671 }
20672 if(atag.Target) q.l = atag;
20673 if(comments.length > 0) { q.c = comments; comments = []; }
20674 if(textp && opts.cellText !== false) q.w = textp;
20675 if(isstub) { q.t = "z"; delete q.v; }
20676 if(!isstub || opts.sheetStubs) {
20677 if(!(opts.sheetRows && opts.sheetRows <= R)) {
20678 for(var rpt = 0; rpt < rowpeat; ++rpt) {
20679 colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
20680 if(opts.dense) {
20681 if(!ws[R + rpt]) ws[R + rpt] = [];
20682 ws[R + rpt][C] = rpt == 0 ? q : dup(q);
20683 while(--colpeat > 0) ws[R + rpt][C + colpeat] = dup(q);
20684 } else {
20685 ws[encode_cell({r:R + rpt,c:C})] = q;
20686 while(--colpeat > 0) ws[encode_cell({r:R + rpt,c:C + colpeat})] = dup(q);
20687 }
20688 if(range.e.c <= C) range.e.c = C;
20689 }
20690 }
20691 }
20692 colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
20693 C += colpeat-1; colpeat = 0;
20694 q = {};
20695 textp = ""; textR = [];
20696 }
20697 atag = ({});
20698 break; // 9.1.4 <table:table-cell>
20699
20700 /* pure state */
20701 case 'document': // TODO: <office:document> is the root for FODS
20702 case 'document-content': case '电子表格文档': // 3.1.3.2 <office:document-content>
20703 case 'spreadsheet': case '主体': // 3.7 <office:spreadsheet>
20704 case 'scripts': // 3.12 <office:scripts>
20705 case 'styles': // TODO <office:styles>
20706 case 'font-face-decls': // 3.14 <office:font-face-decls>
20707 case 'master-styles': // 3.15.4 <office:master-styles> -- relevant for FODS
20708 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
20709 else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
20710 break;
20711
20712 case 'annotation': // 14.1 <office:annotation>
20713 if(Rn[1]==='/'){
20714 if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
20715 comment.t = textp;
20716 if(textR.length) comment.R = textR;
20717 comment.a = creator;
20718 comments.push(comment);
20719 }
20720 else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);}
20721 creator = ""; creatoridx = 0;
20722 textp = ""; textpidx = 0; textR = [];
20723 break;
20724
20725 case 'creator': // 4.3.2.7 <dc:creator>
20726 if(Rn[1]==='/') { creator = str.slice(creatoridx,Rn.index); }
20727 else creatoridx = Rn.index + Rn[0].length;
20728 break;
20729
20730 /* ignore state */
20731 case 'meta': case '元数据': // TODO: <office:meta> <uof:元数据> FODS/UOF
20732 case 'settings': // TODO: <office:settings>
20733 case 'config-item-set': // TODO: <office:config-item-set>
20734 case 'config-item-map-indexed': // TODO: <office:config-item-map-indexed>
20735 case 'config-item-map-entry': // TODO: <office:config-item-map-entry>
20736 case 'config-item-map-named': // TODO: <office:config-item-map-entry>
20737 case 'shapes': // 9.2.8 <table:shapes>
20738 case 'frame': // 10.4.2 <draw:frame>
20739 case 'text-box': // 10.4.3 <draw:text-box>
20740 case 'image': // 10.4.4 <draw:image>
20741 case 'data-pilot-tables': // 9.6.2 <table:data-pilot-tables>
20742 case 'list-style': // 16.30 <text:list-style>
20743 case 'form': // 13.13 <form:form>
20744 case 'dde-links': // 9.8 <table:dde-links>
20745 case 'event-listeners': // TODO
20746 case 'chart': // TODO
20747 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
20748 else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]);
20749 textp = ""; textpidx = 0; textR = [];
20750 break;
20751
20752 case 'scientific-number': // TODO: <number:scientific-number>
20753 break;
20754 case 'currency-symbol': // TODO: <number:currency-symbol>
20755 break;
20756 case 'currency-style': // TODO: <number:currency-style>
20757 break;
20758 case 'number-style': // 16.27.2 <number:number-style>
20759 case 'percentage-style': // 16.27.9 <number:percentage-style>
20760 case 'date-style': // 16.27.10 <number:date-style>
20761 case 'time-style': // 16.27.18 <number:time-style>
20762 if(Rn[1]==='/'){
20763 number_format_map[NFtag.name] = NF;
20764 if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
20765 } else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
20766 NF = "";
20767 NFtag = parsexmltag(Rn[0], false);
20768 state.push([Rn[3], true]);
20769 } break;
20770
20771 case 'script': break; // 3.13 <office:script>
20772 case 'libraries': break; // TODO: <ooo:libraries>
20773 case 'automatic-styles': break; // 3.15.3 <office:automatic-styles>
20774
20775 case 'default-style': // TODO: <style:default-style>
20776 case 'page-layout': break; // TODO: <style:page-layout>
20777 case 'style': // 16.2 <style:style>
20778 break;
20779 case 'map': break; // 16.3 <style:map>
20780 case 'font-face': break; // 16.21 <style:font-face>
20781
20782 case 'paragraph-properties': break; // 17.6 <style:paragraph-properties>
20783 case 'table-properties': break; // 17.15 <style:table-properties>
20784 case 'table-column-properties': break; // 17.16 <style:table-column-properties>
20785 case 'table-row-properties': break; // 17.17 <style:table-row-properties>
20786 case 'table-cell-properties': break; // 17.18 <style:table-cell-properties>
20787
20788 case 'number': // 16.27.3 <number:number>
20789 switch(state[state.length-1][0]) {
20790 case 'time-style':
20791 case 'date-style':
20792 tag = parsexmltag(Rn[0], false);
20793 NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
20794 } break;
20795
20796 case 'fraction': break; // TODO 16.27.6 <number:fraction>
20797
20798 case 'day': // 16.27.11 <number:day>
20799 case 'month': // 16.27.12 <number:month>
20800 case 'year': // 16.27.13 <number:year>
20801 case 'era': // 16.27.14 <number:era>
20802 case 'day-of-week': // 16.27.15 <number:day-of-week>
20803 case 'week-of-year': // 16.27.16 <number:week-of-year>
20804 case 'quarter': // 16.27.17 <number:quarter>
20805 case 'hours': // 16.27.19 <number:hours>
20806 case 'minutes': // 16.27.20 <number:minutes>
20807 case 'seconds': // 16.27.21 <number:seconds>
20808 case 'am-pm': // 16.27.22 <number:am-pm>
20809 switch(state[state.length-1][0]) {
20810 case 'time-style':
20811 case 'date-style':
20812 tag = parsexmltag(Rn[0], false);
20813 NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
20814 } break;
20815
20816 case 'boolean-style': break; // 16.27.23 <number:boolean-style>
20817 case 'boolean': break; // 16.27.24 <number:boolean>
20818 case 'text-style': break; // 16.27.25 <number:text-style>
20819 case 'text': // 16.27.26 <number:text>
20820 if(Rn[0].slice(-2) === "/>") break;
20821 else if(Rn[1]==="/") switch(state[state.length-1][0]) {
20822 case 'number-style':
20823 case 'date-style':
20824 case 'time-style':
20825 NF += str.slice(pidx, Rn.index);
20826 break;
20827 }
20828 else pidx = Rn.index + Rn[0].length;
20829 break;
20830
20831 case 'named-range': // 9.4.12 <table:named-range>
20832 tag = parsexmltag(Rn[0], false);
20833 _Ref = ods_to_csf_3D(tag['cell-range-address']);
20834 var nrange = ({Name:tag.name, Ref:_Ref[0] + '!' + _Ref[1]});
20835 if(intable) nrange.Sheet = SheetNames.length;
20836 WB.Names.push(nrange);
20837 break;
20838
20839 case 'text-content': break; // 16.27.27 <number:text-content>
20840 case 'text-properties': break; // 16.27.27 <style:text-properties>
20841 case 'embedded-text': break; // 16.27.4 <number:embedded-text>
20842
20843 case 'body': case '电子表格': break; // 3.3 16.9.6 19.726.3
20844
20845 case 'forms': break; // 12.25.2 13.2
20846 case 'table-column': break; // 9.1.6 <table:table-column>
20847 case 'table-header-rows': break; // 9.1.7 <table:table-header-rows>
20848 case 'table-rows': break; // 9.1.12 <table:table-rows>
20849 /* TODO: outline levels */
20850 case 'table-column-group': break; // 9.1.10 <table:table-column-group>
20851 case 'table-header-columns': break; // 9.1.11 <table:table-header-columns>
20852 case 'table-columns': break; // 9.1.12 <table:table-columns>
20853
20854 case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
20855
20856 case 'graphic-properties': break; // 17.21 <style:graphic-properties>
20857 case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
20858 case 'named-expressions': break; // 9.4.11 <table:named-expressions>
20859 case 'label-range': break; // 9.4.9 <table:label-range>
20860 case 'label-ranges': break; // 9.4.10 <table:label-ranges>
20861 case 'named-expression': break; // 9.4.13 <table:named-expression>
20862 case 'sort': break; // 9.4.19 <table:sort>
20863 case 'sort-by': break; // 9.4.20 <table:sort-by>
20864 case 'sort-groups': break; // 9.4.22 <table:sort-groups>
20865
20866 case 'tab': break; // 6.1.4 <text:tab>
20867 case 'line-break': break; // 6.1.5 <text:line-break>
20868 case 'span': break; // 6.1.7 <text:span>
20869 case 'p': case '文本串': // 5.1.3 <text:p>
20870 if(['master-styles'].indexOf(state[state.length-1][0]) > -1) break;
20871 if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) {
20872 var ptp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
20873 textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0];
20874 } else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
20875 break; // <text:p>
20876 case 's': break; // <text:s>
20877
20878 case 'database-range': // 9.4.15 <table:database-range>
20879 if(Rn[1]==='/') break;
20880 try {
20881 _Ref = ods_to_csf_3D(parsexmltag(Rn[0])['target-range-address']);
20882 Sheets[_Ref[0]]['!autofilter'] = { ref:_Ref[1] };
20883 } catch(e) {/* empty */}
20884 break;
20885
20886 case 'date': break; // <*:date>
20887
20888 case 'object': break; // 10.4.6.2 <draw:object>
20889 case 'title': case '标题': break; // <*:title> OR <uof:标题>
20890 case 'desc': break; // <*:desc>
20891 case 'binary-data': break; // 10.4.5 TODO: b64 blob
20892
20893 /* 9.2 Advanced Tables */
20894 case 'table-source': break; // 9.2.6
20895 case 'scenario': break; // 9.2.6
20896
20897 case 'iteration': break; // 9.4.3 <table:iteration>
20898 case 'content-validations': break; // 9.4.4 <table:
20899 case 'content-validation': break; // 9.4.5 <table:
20900 case 'help-message': break; // 9.4.6 <table:
20901 case 'error-message': break; // 9.4.7 <table:
20902 case 'database-ranges': break; // 9.4.14 <table:database-ranges>
20903 case 'filter': break; // 9.5.2 <table:filter>
20904 case 'filter-and': break; // 9.5.3 <table:filter-and>
20905 case 'filter-or': break; // 9.5.4 <table:filter-or>
20906 case 'filter-condition': break; // 9.5.5 <table:filter-condition>
20907
20908 case 'list-level-style-bullet': break; // 16.31 <text:
20909 case 'list-level-style-number': break; // 16.32 <text:
20910 case 'list-level-properties': break; // 17.19 <style:
20911
20912 /* 7.3 Document Fields */
20913 case 'sender-firstname': // 7.3.6.2
20914 case 'sender-lastname': // 7.3.6.3
20915 case 'sender-initials': // 7.3.6.4
20916 case 'sender-title': // 7.3.6.5
20917 case 'sender-position': // 7.3.6.6
20918 case 'sender-email': // 7.3.6.7
20919 case 'sender-phone-private': // 7.3.6.8
20920 case 'sender-fax': // 7.3.6.9
20921 case 'sender-company': // 7.3.6.10
20922 case 'sender-phone-work': // 7.3.6.11
20923 case 'sender-street': // 7.3.6.12
20924 case 'sender-city': // 7.3.6.13
20925 case 'sender-postal-code': // 7.3.6.14
20926 case 'sender-country': // 7.3.6.15
20927 case 'sender-state-or-province': // 7.3.6.16
20928 case 'author-name': // 7.3.7.1
20929 case 'author-initials': // 7.3.7.2
20930 case 'chapter': // 7.3.8
20931 case 'file-name': // 7.3.9
20932 case 'template-name': // 7.3.9
20933 case 'sheet-name': // 7.3.9
20934 break;
20935
20936 case 'event-listener':
20937 break;
20938 /* TODO: FODS Properties */
20939 case 'initial-creator':
20940 case 'creation-date':
20941 case 'print-date':
20942 case 'generator':
20943 case 'document-statistic':
20944 case 'user-defined':
20945 case 'editing-duration':
20946 case 'editing-cycles':
20947 break;
20948
20949 /* TODO: FODS Config */
20950 case 'config-item':
20951 break;
20952
20953 /* TODO: style tokens */
20954 case 'page-number': break; // TODO <text:page-number>
20955 case 'page-count': break; // TODO <text:page-count>
20956 case 'time': break; // TODO <text:time>
20957
20958 /* 9.3 Advanced Table Cells */
20959 case 'cell-range-source': break; // 9.3.1 <table:
20960 case 'detective': break; // 9.3.2 <table:
20961 case 'operation': break; // 9.3.3 <table:
20962 case 'highlighted-range': break; // 9.3.4 <table:
20963
20964 /* 9.6 Data Pilot Tables <table: */
20965 case 'data-pilot-table': // 9.6.3
20966 case 'source-cell-range': // 9.6.5
20967 case 'source-service': // 9.6.6
20968 case 'data-pilot-field': // 9.6.7
20969 case 'data-pilot-level': // 9.6.8
20970 case 'data-pilot-subtotals': // 9.6.9
20971 case 'data-pilot-subtotal': // 9.6.10
20972 case 'data-pilot-members': // 9.6.11
20973 case 'data-pilot-member': // 9.6.12
20974 case 'data-pilot-display-info': // 9.6.13
20975 case 'data-pilot-sort-info': // 9.6.14
20976 case 'data-pilot-layout-info': // 9.6.15
20977 case 'data-pilot-field-reference': // 9.6.16
20978 case 'data-pilot-groups': // 9.6.17
20979 case 'data-pilot-group': // 9.6.18
20980 case 'data-pilot-group-member': // 9.6.19
20981 break;
20982
20983 /* 10.3 Drawing Shapes */
20984 case 'rect': // 10.3.2
20985 break;
20986
20987 /* 14.6 DDE Connections */
20988 case 'dde-connection-decls': // 14.6.2 <text:
20989 case 'dde-connection-decl': // 14.6.3 <text:
20990 case 'dde-link': // 14.6.4 <table:
20991 case 'dde-source': // 14.6.5 <office:
20992 break;
20993
20994 case 'properties': break; // 13.7 <form:properties>
20995 case 'property': break; // 13.8 <form:property>
20996
20997 case 'a': // 6.1.8 hyperlink
20998 if(Rn[1]!== '/') {
20999 atag = parsexmltag(Rn[0], false);
21000 if(!atag.href) break;
21001 atag.Target = unescapexml(atag.href); delete atag.href;
21002 if(atag.Target.charAt(0) == "#" && atag.Target.indexOf(".") > -1) {
21003 _Ref = ods_to_csf_3D(atag.Target.slice(1));
21004 atag.Target = "#" + _Ref[0] + "!" + _Ref[1];
21005 } else if(atag.Target.match(/^\.\.[\\\/]/)) atag.Target = atag.Target.slice(3);
21006 }
21007 break;
21008
21009 /* non-standard */
21010 case 'table-protection': break;
21011 case 'data-pilot-grand-total': break; // <table:
21012 case 'office-document-common-attrs': break; // bare
21013 default: switch(Rn[2]) {
21014 case 'dc:': // TODO: properties
21015 case 'calcext:': // ignore undocumented extensions
21016 case 'loext:': // ignore undocumented extensions
21017 case 'ooo:': // ignore undocumented extensions
21018 case 'chartooo:': // ignore undocumented extensions
21019 case 'draw:': // TODO: drawing
21020 case 'style:': // TODO: styles
21021 case 'chart:': // TODO: charts
21022 case 'form:': // TODO: forms
21023 case 'uof:': // TODO: uof
21024 case '表:': // TODO: uof
21025 case '字:': // TODO: uof
21026 break;
21027 default: if(opts.WTF) throw new Error(Rn);
21028 }
21029 }
21030 var out = ({
21031 Sheets: Sheets,
21032 SheetNames: SheetNames,
21033 Workbook: WB
21034 });
21035 if(opts.bookSheets) delete out.Sheets;
21036 return out;
21037 };
21038})();
21039
21040function parse_ods(zip, opts) {
21041 opts = opts || ({});
21042 if(safegetzipfile(zip, 'META-INF/manifest.xml')) parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
21043 var content = getzipstr(zip, 'content.xml');
21044 if(!content) throw new Error("Missing content.xml in ODS / UOF file");
21045 var wb = parse_content_xml(utf8read(content), opts);
21046 if(safegetzipfile(zip, 'meta.xml')) wb.Props = parse_core_props(getzipdata(zip, 'meta.xml'));
21047 return wb;
21048}
21049function parse_fods(data, opts) {
21050 return parse_content_xml(data, opts);
21051}
21052
21053/* OpenDocument */
21054var write_styles_ods = (function() {
21055 var master_styles = '<office:master-styles>'
21056 + '<style:master-page style:name="mp1" style:page-layout-name="mp1">'
21057 + '<style:header/>'
21058 + '<style:header-left style:display="false"/>'
21059 + '<style:footer/>'
21060 + '<style:footer-left style:display="false"/>'
21061 + '</style:master-page>'
21062 + '</office:master-styles>';
21063
21064 var payload = '<office:document-styles ' + wxt_helper({
21065 'xmlns:office': "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
21066 'xmlns:table': "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
21067 'xmlns:style': "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
21068 'xmlns:text': "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
21069 'xmlns:draw': "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
21070 'xmlns:fo': "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
21071 'xmlns:xlink': "http://www.w3.org/1999/xlink",
21072 'xmlns:dc': "http://purl.org/dc/elements/1.1/",
21073 'xmlns:number': "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
21074 'xmlns:svg': "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
21075 'xmlns:of': "urn:oasis:names:tc:opendocument:xmlns:of:1.2",
21076 'office:version': "1.2"
21077 }) + '>' + master_styles + '</office:document-styles>';
21078
21079 return function wso() {
21080 return XML_HEADER + payload;
21081 };
21082})();
21083var write_content_ods = (function() {
21084 /* 6.1.2 White Space Characters */
21085 var write_text_p = function(text) {
21086 return escapexml(text)
21087 .replace(/ +/g, function($$){return '<text:s text:c="'+$$.length+'"/>';})
21088 .replace(/\t/g, "<text:tab/>")
21089 .replace(/\n/g, "</text:p><text:p>")
21090 .replace(/^ /, "<text:s/>").replace(/ $/, "<text:s/>");
21091 };
21092
21093 var null_cell_xml = ' <table:table-cell />\n';
21094 var covered_cell_xml = ' <table:covered-table-cell/>\n';
21095 var write_ws = function(ws, wb, i) {
21096 /* Section 9 Tables */
21097 var o = [];
21098 o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="ta1">\n');
21099 var R=0,C=0, range = decode_range(ws['!ref']||"A1");
21100 var marr = ws['!merges'] || [], mi = 0;
21101 var dense = Array.isArray(ws);
21102 if(ws["!cols"]) {
21103 for(C = 0; C <= range.e.c; ++C) o.push(' <table:table-column' + (ws["!cols"][C] ? ' table:style-name="co' + ws["!cols"][C].ods + '"' : '') + '></table:table-column>\n');
21104 }
21105 var H = "", ROWS = ws["!rows"]||[];
21106 for(R = 0; R < range.s.r; ++R) {
21107 H = ROWS[R] ? ' table:style-name="ro' + ROWS[R].ods + '"' : "";
21108 o.push(' <table:table-row' + H + '></table:table-row>\n');
21109 }
21110 for(; R <= range.e.r; ++R) {
21111 H = ROWS[R] ? ' table:style-name="ro' + ROWS[R].ods + '"' : "";
21112 o.push(' <table:table-row' + H + '>\n');
21113 for(C=0; C < range.s.c; ++C) o.push(null_cell_xml);
21114 for(; C <= range.e.c; ++C) {
21115 var skip = false, ct = {}, textp = "";
21116 for(mi = 0; mi != marr.length; ++mi) {
21117 if(marr[mi].s.c > C) continue;
21118 if(marr[mi].s.r > R) continue;
21119 if(marr[mi].e.c < C) continue;
21120 if(marr[mi].e.r < R) continue;
21121 if(marr[mi].s.c != C || marr[mi].s.r != R) skip = true;
21122 ct['table:number-columns-spanned'] = (marr[mi].e.c - marr[mi].s.c + 1);
21123 ct['table:number-rows-spanned'] = (marr[mi].e.r - marr[mi].s.r + 1);
21124 break;
21125 }
21126 if(skip) { o.push(covered_cell_xml); continue; }
21127 var ref = encode_cell({r:R, c:C}), cell = dense ? (ws[R]||[])[C]: ws[ref];
21128 if(cell && cell.f) {
21129 ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f));
21130 if(cell.F) {
21131 if(cell.F.slice(0, ref.length) == ref) {
21132 var _Fref = decode_range(cell.F);
21133 ct['table:number-matrix-columns-spanned'] = (_Fref.e.c - _Fref.s.c + 1);
21134 ct['table:number-matrix-rows-spanned'] = (_Fref.e.r - _Fref.s.r + 1);
21135 }
21136 }
21137 }
21138 if(!cell) { o.push(null_cell_xml); continue; }
21139 switch(cell.t) {
21140 case 'b':
21141 textp = (cell.v ? 'TRUE' : 'FALSE');
21142 ct['office:value-type'] = "boolean";
21143 ct['office:boolean-value'] = (cell.v ? 'true' : 'false');
21144 break;
21145 case 'n':
21146 textp = (cell.w||String(cell.v||0));
21147 ct['office:value-type'] = "float";
21148 ct['office:value'] = (cell.v||0);
21149 break;
21150 case 's': case 'str':
21151 textp = cell.v == null ? "" : cell.v;
21152 ct['office:value-type'] = "string";
21153 break;
21154 case 'd':
21155 textp = (cell.w||(parseDate(cell.v).toISOString()));
21156 ct['office:value-type'] = "date";
21157 ct['office:date-value'] = (parseDate(cell.v).toISOString());
21158 ct['table:style-name'] = "ce1";
21159 break;
21160 //case 'e':
21161 default: o.push(null_cell_xml); continue;
21162 }
21163 var text_p = write_text_p(textp);
21164 if(cell.l && cell.l.Target) {
21165 var _tgt = cell.l.Target;
21166 _tgt = _tgt.charAt(0) == "#" ? "#" + csf_to_ods_3D(_tgt.slice(1)) : _tgt;
21167 // TODO: choose correct parent path format based on link delimiters
21168 if(_tgt.charAt(0) != "#" && !_tgt.match(/^\w+:/)) _tgt = '../' + _tgt;
21169 text_p = writextag('text:a', text_p, {'xlink:href': _tgt.replace(/&/g, "&amp;")});
21170 }
21171 o.push(' ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n');
21172 }
21173 o.push(' </table:table-row>\n');
21174 }
21175 o.push(' </table:table>\n');
21176 return o.join("");
21177 };
21178
21179 var write_automatic_styles_ods = function(o, wb) {
21180 o.push(' <office:automatic-styles>\n');
21181
21182 o.push(' <number:date-style style:name="N37" number:automatic-order="true">\n');
21183 o.push(' <number:month number:style="long"/>\n');
21184 o.push(' <number:text>/</number:text>\n');
21185 o.push(' <number:day number:style="long"/>\n');
21186 o.push(' <number:text>/</number:text>\n');
21187 o.push(' <number:year/>\n');
21188 o.push(' </number:date-style>\n');
21189
21190 /* column styles */
21191 var cidx = 0;
21192 wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
21193 if(!ws) return;
21194 if(ws["!cols"]) {
21195 for(var C = 0; C < ws["!cols"].length; ++C) if(ws["!cols"][C]) {
21196 var colobj = ws["!cols"][C];
21197 if(colobj.width == null && colobj.wpx == null && colobj.wch == null) continue;
21198 process_col(colobj);
21199 colobj.ods = cidx;
21200 var w = ws["!cols"][C].wpx + "px";
21201 o.push(' <style:style style:name="co' + cidx + '" style:family="table-column">\n');
21202 o.push(' <style:table-column-properties fo:break-before="auto" style:column-width="' + w + '"/>\n');
21203 o.push(' </style:style>\n');
21204 ++cidx;
21205 }
21206 }
21207 });
21208
21209 /* row styles */
21210 var ridx = 0;
21211 wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
21212 if(!ws) return;
21213 if(ws["!rows"]) {
21214 for(var R = 0; R < ws["!rows"].length; ++R) if(ws["!rows"][R]) {
21215 ws["!rows"][R].ods = ridx;
21216 var h = ws["!rows"][R].hpx + "px";
21217 o.push(' <style:style style:name="ro' + ridx + '" style:family="table-row">\n');
21218 o.push(' <style:table-row-properties fo:break-before="auto" style:row-height="' + h + '"/>\n');
21219 o.push(' </style:style>\n');
21220 ++ridx;
21221 }
21222 }
21223 });
21224
21225 /* table */
21226 o.push(' <style:style style:name="ta1" style:family="table" style:master-page-name="mp1">\n');
21227 o.push(' <style:table-properties table:display="true" style:writing-mode="lr-tb"/>\n');
21228 o.push(' </style:style>\n');
21229
21230 /* table cells, text */
21231 o.push(' <style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N37"/>\n');
21232
21233 /* page-layout */
21234
21235 o.push(' </office:automatic-styles>\n');
21236 };
21237
21238 return function wcx(wb, opts) {
21239 var o = [XML_HEADER];
21240 /* 3.1.3.2 */
21241 var attr = wxt_helper({
21242 'xmlns:office': "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
21243 'xmlns:table': "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
21244 'xmlns:style': "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
21245 'xmlns:text': "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
21246 'xmlns:draw': "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
21247 'xmlns:fo': "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
21248 'xmlns:xlink': "http://www.w3.org/1999/xlink",
21249 'xmlns:dc': "http://purl.org/dc/elements/1.1/",
21250 'xmlns:meta': "urn:oasis:names:tc:opendocument:xmlns:meta:1.0",
21251 'xmlns:number': "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
21252 'xmlns:presentation': "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0",
21253 'xmlns:svg': "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
21254 'xmlns:chart': "urn:oasis:names:tc:opendocument:xmlns:chart:1.0",
21255 'xmlns:dr3d': "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0",
21256 'xmlns:math': "http://www.w3.org/1998/Math/MathML",
21257 'xmlns:form': "urn:oasis:names:tc:opendocument:xmlns:form:1.0",
21258 'xmlns:script': "urn:oasis:names:tc:opendocument:xmlns:script:1.0",
21259 'xmlns:ooo': "http://openoffice.org/2004/office",
21260 'xmlns:ooow': "http://openoffice.org/2004/writer",
21261 'xmlns:oooc': "http://openoffice.org/2004/calc",
21262 'xmlns:dom': "http://www.w3.org/2001/xml-events",
21263 'xmlns:xforms': "http://www.w3.org/2002/xforms",
21264 'xmlns:xsd': "http://www.w3.org/2001/XMLSchema",
21265 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance",
21266 'xmlns:sheet': "urn:oasis:names:tc:opendocument:sh33tjs:1.0",
21267 'xmlns:rpt': "http://openoffice.org/2005/report",
21268 'xmlns:of': "urn:oasis:names:tc:opendocument:xmlns:of:1.2",
21269 'xmlns:xhtml': "http://www.w3.org/1999/xhtml",
21270 'xmlns:grddl': "http://www.w3.org/2003/g/data-view#",
21271 'xmlns:tableooo': "http://openoffice.org/2009/table",
21272 'xmlns:drawooo': "http://openoffice.org/2010/draw",
21273 'xmlns:calcext': "urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0",
21274 'xmlns:loext': "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0",
21275 'xmlns:field': "urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0",
21276 'xmlns:formx': "urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0",
21277 'xmlns:css3t': "http://www.w3.org/TR/css3-text/",
21278 'office:version': "1.2"
21279 });
21280
21281 var fods = wxt_helper({
21282 'xmlns:config': "urn:oasis:names:tc:opendocument:xmlns:config:1.0",
21283 'office:mimetype': "application/vnd.oasis.opendocument.spreadsheet"
21284 });
21285
21286 if(opts.bookType == "fods") {
21287 o.push('<office:document' + attr + fods + '>\n');
21288 o.push(write_meta_ods().replace(/office:document-meta/g, "office:meta"));
21289 // TODO: settings (equiv of settings.xml for ODS)
21290 } else o.push('<office:document-content' + attr + '>\n');
21291 // o.push(' <office:scripts/>\n');
21292 write_automatic_styles_ods(o, wb);
21293 o.push(' <office:body>\n');
21294 o.push(' <office:spreadsheet>\n');
21295 for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts));
21296 o.push(' </office:spreadsheet>\n');
21297 o.push(' </office:body>\n');
21298 if(opts.bookType == "fods") o.push('</office:document>');
21299 else o.push('</office:document-content>');
21300 return o.join("");
21301 };
21302})();
21303
21304function write_ods(wb, opts) {
21305 if(opts.bookType == "fods") return write_content_ods(wb, opts);
21306
21307 var zip = zip_new();
21308 var f = "";
21309
21310 var manifest = [];
21311 var rdf = [];
21312
21313 /* Part 3 Section 3.3 MIME Media Type */
21314 f = "mimetype";
21315 zip_add_file(zip, f, "application/vnd.oasis.opendocument.spreadsheet");
21316
21317 /* Part 1 Section 2.2 Documents */
21318 f = "content.xml";
21319 zip_add_file(zip, f, write_content_ods(wb, opts));
21320 manifest.push([f, "text/xml"]);
21321 rdf.push([f, "ContentFile"]);
21322
21323 /* TODO: these are hard-coded styles to satiate excel */
21324 f = "styles.xml";
21325 zip_add_file(zip, f, write_styles_ods(wb, opts));
21326 manifest.push([f, "text/xml"]);
21327 rdf.push([f, "StylesFile"]);
21328
21329 /* TODO: this is hard-coded to satiate excel */
21330 f = "meta.xml";
21331 zip_add_file(zip, f, XML_HEADER + write_meta_ods());
21332 manifest.push([f, "text/xml"]);
21333 rdf.push([f, "MetadataFile"]);
21334
21335 /* Part 3 Section 6 Metadata Manifest File */
21336 f = "manifest.rdf";
21337 zip_add_file(zip, f, write_rdf(rdf/*, opts*/));
21338 manifest.push([f, "application/rdf+xml"]);
21339
21340 /* Part 3 Section 4 Manifest File */
21341 f = "META-INF/manifest.xml";
21342 zip_add_file(zip, f, write_manifest(manifest/*, opts*/));
21343
21344 return zip;
21345}
21346
21347function write_sheet_index(wb, sheet) {
21348 if(!sheet) return 0;
21349 var idx = wb.SheetNames.indexOf(sheet);
21350 if(idx == -1) throw new Error("Sheet not found: " + sheet);
21351 return idx;
21352}
21353
21354function write_obj_str(factory) {
21355 return function write_str(wb, o) {
21356 var idx = write_sheet_index(wb, o.sheet);
21357 return factory.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb);
21358 };
21359}
21360
21361var write_htm_str = write_obj_str(HTML_);
21362var write_csv_str = write_obj_str({from_sheet:sheet_to_csv});
21363var write_slk_str = write_obj_str(typeof SYLK !== "undefined" ? SYLK : {});
21364var write_dif_str = write_obj_str(typeof DIF !== "undefined" ? DIF : {});
21365var write_prn_str = write_obj_str(typeof PRN !== "undefined" ? PRN : {});
21366var write_rtf_str = write_obj_str(typeof RTF !== "undefined" ? RTF : {});
21367var write_txt_str = write_obj_str({from_sheet:sheet_to_txt});
21368var write_dbf_buf = write_obj_str(typeof DBF !== "undefined" ? DBF : {});
21369var write_eth_str = write_obj_str(typeof ETH !== "undefined" ? ETH : {});
21370var write_wk1_buf = write_obj_str(typeof WK_ !== "undefined" ? {from_sheet:WK_.sheet_to_wk1} : {});
21371
21372function fix_opts_func(defaults) {
21373 return function fix_opts(opts) {
21374 for(var i = 0; i != defaults.length; ++i) {
21375 var d = defaults[i];
21376 if(opts[d[0]] === undefined) opts[d[0]] = d[1];
21377 if(d[2] === 'n') opts[d[0]] = Number(opts[d[0]]);
21378 }
21379 };
21380}
21381
21382var fix_read_opts = function(opts) {
21383fix_opts_func([
21384 ['cellNF', false], /* emit cell number format string as .z */
21385 ['cellHTML', true], /* emit html string as .h */
21386 ['cellFormula', true], /* emit formulae as .f */
21387 ['cellStyles', false], /* emits style/theme as .s */
21388 ['cellText', true], /* emit formatted text as .w */
21389 ['cellDates', false], /* emit date cells with type `d` */
21390
21391 ['sheetStubs', false], /* emit empty cells */
21392 ['sheetRows', 0, 'n'], /* read n rows (0 = read all rows) */
21393
21394 ['bookDeps', false], /* parse calculation chains */
21395 ['bookSheets', false], /* only try to get sheet names (no Sheets) */
21396 ['bookProps', false], /* only try to get properties (no Sheets) */
21397 ['bookFiles', false], /* include raw file structure (keys, files, cfb) */
21398 ['bookVBA', false], /* include vba raw data (vbaraw) */
21399
21400 ['password',''], /* password */
21401 ['WTF', false] /* WTF mode (throws errors) */
21402])(opts);
21403};
21404
21405var fix_write_opts = fix_opts_func([
21406 ['cellDates', false], /* write date cells with type `d` */
21407
21408 ['bookSST', false], /* Generate Shared String Table */
21409
21410 ['bookType', 'xlsx'], /* Type of workbook (xlsx/m/b) */
21411
21412 ['compression', false], /* Use file compression */
21413
21414 ['WTF', false] /* WTF mode (throws errors) */
21415]);
21416function get_sheet_type(n) {
21417 if(RELS.WS.indexOf(n) > -1) return "sheet";
21418 if(RELS.CS && n == RELS.CS) return "chart";
21419 if(RELS.DS && n == RELS.DS) return "dialog";
21420 if(RELS.MS && n == RELS.MS) return "macro";
21421 return (n && n.length) ? n : "sheet";
21422}
21423function safe_parse_wbrels(wbrels, sheets) {
21424 if(!wbrels) return 0;
21425 try {
21426 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)]; });
21427 } catch(e) { return null; }
21428 return !wbrels || wbrels.length === 0 ? null : wbrels;
21429}
21430
21431function safe_parse_sheet(zip, path, relsPath, sheet, idx, sheetRels, sheets, stype, opts, wb, themes, styles) {
21432 try {
21433 sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
21434 var data = getzipdata(zip, path);
21435 var _ws;
21436 switch(stype) {
21437 case 'sheet': _ws = parse_ws(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
21438 case 'chart': _ws = parse_cs(data, path, idx, opts, sheetRels[sheet], wb, themes, styles);
21439 if(!_ws || !_ws['!drawel']) break;
21440 var dfile = resolve_path(_ws['!drawel'].Target, path);
21441 var drelsp = get_rels_path(dfile);
21442 var draw = parse_drawing(getzipstr(zip, dfile, true), parse_rels(getzipstr(zip, drelsp, true), dfile));
21443 var chartp = resolve_path(draw, dfile);
21444 var crelsp = get_rels_path(chartp);
21445 _ws = parse_chart(getzipstr(zip, chartp, true), chartp, opts, parse_rels(getzipstr(zip, crelsp, true), chartp), wb, _ws);
21446 break;
21447 case 'macro': _ws = parse_ms(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
21448 case 'dialog': _ws = parse_ds(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
21449 default: throw new Error("Unrecognized sheet type " + stype);
21450 }
21451 sheets[sheet] = _ws;
21452
21453 /* scan rels for comments */
21454 var comments = [];
21455 if(sheetRels && sheetRels[sheet]) keys(sheetRels[sheet]).forEach(function(n) {
21456 if(sheetRels[sheet][n].Type == RELS.CMNT) {
21457 var dfile = resolve_path(sheetRels[sheet][n].Target, path);
21458 comments = parse_cmnt(getzipdata(zip, dfile, true), dfile, opts);
21459 if(!comments || !comments.length) return;
21460 sheet_insert_comments(_ws, comments);
21461 }
21462 });
21463 } catch(e) { if(opts.WTF) throw e; }
21464}
21465
21466function strip_front_slash(x) { return x.charAt(0) == '/' ? x.slice(1) : x; }
21467
21468function parse_zip(zip, opts) {
21469 make_ssf(SSF);
21470 opts = opts || {};
21471 fix_read_opts(opts);
21472
21473 /* OpenDocument Part 3 Section 2.2.1 OpenDocument Package */
21474 if(safegetzipfile(zip, 'META-INF/manifest.xml')) return parse_ods(zip, opts);
21475 /* UOC */
21476 if(safegetzipfile(zip, 'objectdata.xml')) return parse_ods(zip, opts);
21477 /* Numbers */
21478 if(safegetzipfile(zip, 'Index/Document.iwa')) throw new Error('Unsupported NUMBERS file');
21479
21480 var entries = zipentries(zip);
21481 var dir = parse_ct((getzipstr(zip, '[Content_Types].xml')));
21482 var xlsb = false;
21483 var sheets, binname;
21484 if(dir.workbooks.length === 0) {
21485 binname = "xl/workbook.xml";
21486 if(getzipdata(zip,binname, true)) dir.workbooks.push(binname);
21487 }
21488 if(dir.workbooks.length === 0) {
21489 binname = "xl/workbook.bin";
21490 if(!getzipdata(zip,binname,true)) throw new Error("Could not find workbook");
21491 dir.workbooks.push(binname);
21492 xlsb = true;
21493 }
21494 if(dir.workbooks[0].slice(-3) == "bin") xlsb = true;
21495
21496 var themes = ({});
21497 var styles = ({});
21498 if(!opts.bookSheets && !opts.bookProps) {
21499 strs = [];
21500 if(dir.sst) try { strs=parse_sst(getzipdata(zip, strip_front_slash(dir.sst)), dir.sst, opts); } catch(e) { if(opts.WTF) throw e; }
21501
21502 if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts);
21503
21504 if(dir.style) styles = parse_sty(getzipdata(zip, strip_front_slash(dir.style)), dir.style, themes, opts);
21505 }
21506
21507 /*var externbooks = */dir.links.map(function(link) {
21508 try {
21509 var rels = parse_rels(getzipstr(zip, get_rels_path(strip_front_slash(link))), link);
21510 return parse_xlink(getzipdata(zip, strip_front_slash(link)), rels, link, opts);
21511 } catch(e) {}
21512 });
21513
21514 var wb = parse_wb(getzipdata(zip, strip_front_slash(dir.workbooks[0])), dir.workbooks[0], opts);
21515
21516 var props = {}, propdata = "";
21517
21518 if(dir.coreprops.length) {
21519 propdata = getzipdata(zip, strip_front_slash(dir.coreprops[0]), true);
21520 if(propdata) props = parse_core_props(propdata);
21521 if(dir.extprops.length !== 0) {
21522 propdata = getzipdata(zip, strip_front_slash(dir.extprops[0]), true);
21523 if(propdata) parse_ext_props(propdata, props, opts);
21524 }
21525 }
21526
21527 var custprops = {};
21528 if(!opts.bookSheets || opts.bookProps) {
21529 if (dir.custprops.length !== 0) {
21530 propdata = getzipstr(zip, strip_front_slash(dir.custprops[0]), true);
21531 if(propdata) custprops = parse_cust_props(propdata, opts);
21532 }
21533 }
21534
21535 var out = ({});
21536 if(opts.bookSheets || opts.bookProps) {
21537 if(wb.Sheets) sheets = wb.Sheets.map(function pluck(x){ return x.name; });
21538 else if(props.Worksheets && props.SheetNames.length > 0) sheets=props.SheetNames;
21539 if(opts.bookProps) { out.Props = props; out.Custprops = custprops; }
21540 if(opts.bookSheets && typeof sheets !== 'undefined') out.SheetNames = sheets;
21541 if(opts.bookSheets ? out.SheetNames : opts.bookProps) return out;
21542 }
21543 sheets = {};
21544
21545 var deps = {};
21546 if(opts.bookDeps && dir.calcchain) deps=parse_cc(getzipdata(zip, strip_front_slash(dir.calcchain)),dir.calcchain,opts);
21547
21548 var i=0;
21549 var sheetRels = ({});
21550 var path, relsPath;
21551
21552 {
21553 var wbsheets = wb.Sheets;
21554 props.Worksheets = wbsheets.length;
21555 props.SheetNames = [];
21556 for(var j = 0; j != wbsheets.length; ++j) {
21557 props.SheetNames[j] = wbsheets[j].name;
21558 }
21559 }
21560
21561 var wbext = xlsb ? "bin" : "xml";
21562 var wbrelsi = dir.workbooks[0].lastIndexOf("/");
21563 var wbrelsfile = (dir.workbooks[0].slice(0, wbrelsi+1) + "_rels/" + dir.workbooks[0].slice(wbrelsi+1) + ".rels").replace(/^\//,"");
21564 if(!safegetzipfile(zip, wbrelsfile)) wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
21565 var wbrels = parse_rels(getzipstr(zip, wbrelsfile, true), wbrelsfile);
21566 if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
21567
21568 /* Numbers iOS hack */
21569 var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
21570 wsloop: for(i = 0; i != props.Worksheets; ++i) {
21571 var stype = "sheet";
21572 if(wbrels && wbrels[i]) {
21573 path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
21574 if(!safegetzipfile(zip, path)) path = wbrels[i][1];
21575 if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/.*$/,"") + wbrels[i][1];
21576 stype = wbrels[i][2];
21577 } else {
21578 path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
21579 path = path.replace(/sheet0\./,"sheet.");
21580 }
21581 relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
21582 if(opts && opts.sheets != null) switch(typeof opts.sheets) {
21583 case "number": if(i != opts.sheets) continue wsloop; break;
21584 case "string": if(props.SheetNames[i].toLowerCase() != opts.sheets.toLowerCase()) continue wsloop; break;
21585 default: if(Array.isArray && Array.isArray(opts.sheets)) {
21586 var snjseen = false;
21587 for(var snj = 0; snj != opts.sheets.length; ++snj) {
21588 if(typeof opts.sheets[snj] == "number" && opts.sheets[snj] == i) snjseen=1;
21589 if(typeof opts.sheets[snj] == "string" && opts.sheets[snj].toLowerCase() == props.SheetNames[i].toLowerCase()) snjseen = 1;
21590 }
21591 if(!snjseen) continue wsloop;
21592 }
21593 }
21594 safe_parse_sheet(zip, path, relsPath, props.SheetNames[i], i, sheetRels, sheets, stype, opts, wb, themes, styles);
21595 }
21596
21597 out = ({
21598 Directory: dir,
21599 Workbook: wb,
21600 Props: props,
21601 Custprops: custprops,
21602 Deps: deps,
21603 Sheets: sheets,
21604 SheetNames: props.SheetNames,
21605 Strings: strs,
21606 Styles: styles,
21607 Themes: themes,
21608 SSF: SSF.get_table()
21609 });
21610 if(opts && opts.bookFiles) {
21611 if(zip.files) {
21612 out.keys = entries;
21613 out.files = zip.files;
21614 } else {
21615 out.keys = [];
21616 out.files = {};
21617 zip.FullPaths.forEach(function(p, idx) {
21618 p = p.replace(/^Root Entry[\/]/, "");
21619 out.keys.push(p);
21620 out.files[p] = zip.FileIndex[idx];
21621 });
21622 }
21623 }
21624 if(opts && opts.bookVBA) {
21625 if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,strip_front_slash(dir.vba[0]),true);
21626 else if(dir.defaults && dir.defaults.bin === CT_VBA) out.vbaraw = getzipdata(zip, 'xl/vbaProject.bin',true);
21627 }
21628 return out;
21629}
21630
21631/* [MS-OFFCRYPTO] 2.1.1 */
21632function parse_xlsxcfb(cfb, _opts) {
21633 var opts = _opts || {};
21634 var f = 'Workbook', data = CFB.find(cfb, f);
21635 try {
21636 f = '/!DataSpaces/Version';
21637 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
21638 /*var version = */parse_DataSpaceVersionInfo(data.content);
21639
21640 /* 2.3.4.1 */
21641 f = '/!DataSpaces/DataSpaceMap';
21642 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
21643 var dsm = parse_DataSpaceMap(data.content);
21644 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")
21645 throw new Error("ECMA-376 Encrypted file bad " + f);
21646
21647 /* 2.3.4.2 */
21648 f = '/!DataSpaces/DataSpaceInfo/StrongEncryptionDataSpace';
21649 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
21650 var seds = parse_DataSpaceDefinition(data.content);
21651 if(seds.length != 1 || seds[0] != "StrongEncryptionTransform")
21652 throw new Error("ECMA-376 Encrypted file bad " + f);
21653
21654 /* 2.3.4.3 */
21655 f = '/!DataSpaces/TransformInfo/StrongEncryptionTransform/!Primary';
21656 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
21657 /*var hdr = */parse_Primary(data.content);
21658 } catch(e) {}
21659
21660 f = '/EncryptionInfo';
21661 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
21662 var einfo = parse_EncryptionInfo(data.content);
21663
21664 /* 2.3.4.4 */
21665 f = '/EncryptedPackage';
21666 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
21667
21668/*global decrypt_agile */
21669if(einfo[0] == 0x04 && typeof decrypt_agile !== 'undefined') return decrypt_agile(einfo[1], data.content, opts.password || "", opts);
21670/*global decrypt_std76 */
21671if(einfo[0] == 0x02 && typeof decrypt_std76 !== 'undefined') return decrypt_std76(einfo[1], data.content, opts.password || "", opts);
21672 throw new Error("File is password-protected");
21673}
21674
21675function write_zip(wb, opts) {
21676 _shapeid = 1024;
21677 if(opts.bookType == "ods") return write_ods(wb, opts);
21678 if(wb && !wb.SSF) {
21679 wb.SSF = SSF.get_table();
21680 }
21681 if(wb && wb.SSF) {
21682 make_ssf(SSF); SSF.load_table(wb.SSF);
21683 // $FlowIgnore
21684 opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
21685 opts.ssf = wb.SSF;
21686 }
21687 opts.rels = {}; opts.wbrels = {};
21688 opts.Strings = []; opts.Strings.Count = 0; opts.Strings.Unique = 0;
21689 if(browser_has_Map) opts.revStrings = new Map();
21690 else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; }
21691 var wbext = opts.bookType == "xlsb" ? "bin" : "xml";
21692 var vbafmt = VBAFMTS.indexOf(opts.bookType) > -1;
21693 var ct = new_ct();
21694 fix_write_opts(opts = opts || {});
21695 var zip = zip_new();
21696 var f = "", rId = 0;
21697
21698 opts.cellXfs = [];
21699 get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}});
21700
21701 if(!wb.Props) wb.Props = {};
21702
21703 f = "docProps/core.xml";
21704 zip_add_file(zip, f, write_core_props(wb.Props, opts));
21705 ct.coreprops.push(f);
21706 add_rels(opts.rels, 2, f, RELS.CORE_PROPS);
21707
21708f = "docProps/app.xml";
21709 if(wb.Props && wb.Props.SheetNames){/* empty */}
21710 else if(!wb.Workbook || !wb.Workbook.Sheets) wb.Props.SheetNames = wb.SheetNames;
21711 else {
21712 var _sn = [];
21713 for(var _i = 0; _i < wb.SheetNames.length; ++_i)
21714 if((wb.Workbook.Sheets[_i]||{}).Hidden != 2) _sn.push(wb.SheetNames[_i]);
21715 wb.Props.SheetNames = _sn;
21716 }
21717 wb.Props.Worksheets = wb.Props.SheetNames.length;
21718 zip_add_file(zip, f, write_ext_props(wb.Props, opts));
21719 ct.extprops.push(f);
21720 add_rels(opts.rels, 3, f, RELS.EXT_PROPS);
21721
21722 if(wb.Custprops !== wb.Props && keys(wb.Custprops||{}).length > 0) {
21723 f = "docProps/custom.xml";
21724 zip_add_file(zip, f, write_cust_props(wb.Custprops, opts));
21725 ct.custprops.push(f);
21726 add_rels(opts.rels, 4, f, RELS.CUST_PROPS);
21727 }
21728
21729 for(rId=1;rId <= wb.SheetNames.length; ++rId) {
21730 var wsrels = {'!id':{}};
21731 var ws = wb.Sheets[wb.SheetNames[rId-1]];
21732 var _type = (ws || {})["!type"] || "sheet";
21733 switch(_type) {
21734 case "chart":
21735 /* falls through */
21736 default:
21737 f = "xl/worksheets/sheet" + rId + "." + wbext;
21738 zip_add_file(zip, f, write_ws(rId-1, f, opts, wb, wsrels));
21739 ct.sheets.push(f);
21740 add_rels(opts.wbrels, -1, "worksheets/sheet" + rId + "." + wbext, RELS.WS[0]);
21741 }
21742
21743 if(ws) {
21744 var comments = ws['!comments'];
21745 var need_vml = false;
21746 if(comments && comments.length > 0) {
21747 var cf = "xl/comments" + rId + "." + wbext;
21748 zip_add_file(zip, cf, write_cmnt(comments, cf, opts));
21749 ct.comments.push(cf);
21750 add_rels(wsrels, -1, "../comments" + rId + "." + wbext, RELS.CMNT);
21751 need_vml = true;
21752 }
21753 if(ws['!legacy']) {
21754 if(need_vml) zip_add_file(zip, "xl/drawings/vmlDrawing" + (rId) + ".vml", write_comments_vml(rId, ws['!comments']));
21755 }
21756 delete ws['!comments'];
21757 delete ws['!legacy'];
21758 }
21759
21760 if(wsrels['!id'].rId1) zip_add_file(zip, get_rels_path(f), write_rels(wsrels));
21761 }
21762
21763 if(opts.Strings != null && opts.Strings.length > 0) {
21764 f = "xl/sharedStrings." + wbext;
21765 zip_add_file(zip, f, write_sst(opts.Strings, f, opts));
21766 ct.strs.push(f);
21767 add_rels(opts.wbrels, -1, "sharedStrings." + wbext, RELS.SST);
21768 }
21769
21770 f = "xl/workbook." + wbext;
21771 zip_add_file(zip, f, write_wb(wb, f, opts));
21772 ct.workbooks.push(f);
21773 add_rels(opts.rels, 1, f, RELS.WB);
21774
21775 /* TODO: something more intelligent with themes */
21776
21777 f = "xl/theme/theme1.xml";
21778 zip_add_file(zip, f, write_theme(wb.Themes, opts));
21779 ct.themes.push(f);
21780 add_rels(opts.wbrels, -1, "theme/theme1.xml", RELS.THEME);
21781
21782 /* TODO: something more intelligent with styles */
21783
21784 f = "xl/styles." + wbext;
21785 zip_add_file(zip, f, write_sty(wb, f, opts));
21786 ct.styles.push(f);
21787 add_rels(opts.wbrels, -1, "styles." + wbext, RELS.STY);
21788
21789 if(wb.vbaraw && vbafmt) {
21790 f = "xl/vbaProject.bin";
21791 zip_add_file(zip, f, wb.vbaraw);
21792 ct.vba.push(f);
21793 add_rels(opts.wbrels, -1, "vbaProject.bin", RELS.VBA);
21794 }
21795
21796 zip_add_file(zip, "[Content_Types].xml", write_ct(ct, opts));
21797 zip_add_file(zip, '_rels/.rels', write_rels(opts.rels));
21798 zip_add_file(zip, 'xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));
21799
21800 delete opts.revssf; delete opts.ssf;
21801 return zip;
21802}
21803function firstbyte(f,o) {
21804 var x = "";
21805 switch((o||{}).type || "base64") {
21806 case 'buffer': return [f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]];
21807 case 'base64': x = Base64.decode(f.slice(0,12)); break;
21808 case 'binary': x = f; break;
21809 case 'array': return [f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]];
21810 default: throw new Error("Unrecognized type " + (o && o.type || "undefined"));
21811 }
21812 return [x.charCodeAt(0), x.charCodeAt(1), x.charCodeAt(2), x.charCodeAt(3), x.charCodeAt(4), x.charCodeAt(5), x.charCodeAt(6), x.charCodeAt(7)];
21813}
21814
21815function read_cfb(cfb, opts) {
21816 if(CFB.find(cfb, "EncryptedPackage")) return parse_xlsxcfb(cfb, opts);
21817 return parse_xlscfb(cfb, opts);
21818}
21819
21820function read_zip(data, opts) {
21821 var zip, d = data;
21822 var o = opts||{};
21823 if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
21824 zip = zip_read(d, o);
21825 return parse_zip(zip, o);
21826}
21827
21828function read_plaintext(data, o) {
21829 var i = 0;
21830 main: while(i < data.length) switch(data.charCodeAt(i)) {
21831 case 0x0A: case 0x0D: case 0x20: ++i; break;
21832 case 0x3C: return parse_xlml(data.slice(i),o);
21833 default: break main;
21834 }
21835 return PRN.to_workbook(data, o);
21836}
21837
21838function read_plaintext_raw(data, o) {
21839 var str = "", bytes = firstbyte(data, o);
21840 switch(o.type) {
21841 case 'base64': str = Base64.decode(data); break;
21842 case 'binary': str = data; break;
21843 case 'buffer': str = data.toString('binary'); break;
21844 case 'array': str = cc2str(data); break;
21845 default: throw new Error("Unrecognized type " + o.type);
21846 }
21847 if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str);
21848 return read_plaintext(str, o);
21849}
21850
21851function read_utf16(data, o) {
21852 var d = data;
21853 if(o.type == 'base64') d = Base64.decode(d);
21854 d = cptable.utils.decode(1200, d.slice(2), 'str');
21855 o.type = "binary";
21856 return read_plaintext(d, o);
21857}
21858
21859function bstrify(data) {
21860 return !data.match(/[^\x00-\x7F]/) ? data : utf8write(data);
21861}
21862
21863function read_prn(data, d, o, str) {
21864 if(str) { o.type = "string"; return PRN.to_workbook(data, o); }
21865 return PRN.to_workbook(d, o);
21866}
21867
21868function readSync(data, opts) {
21869 reset_cp();
21870 var o = opts||{};
21871 if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), (o = dup(o), o.type = "array", o));
21872 var d = data, n = [0,0,0,0], str = false;
21873 if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; }
21874 _ssfopts = {};
21875 if(o.dateNF) _ssfopts.dateNF = o.dateNF;
21876 if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
21877 if(o.type == "file") { o.type = has_buf ? "buffer" : "binary"; d = read_binary(data); }
21878 if(o.type == "string") { str = true; o.type = "binary"; o.codepage = 65001; d = bstrify(data); }
21879 if(o.type == 'array' && typeof Uint8Array !== 'undefined' && data instanceof Uint8Array && typeof ArrayBuffer !== 'undefined') {
21880 // $FlowIgnore
21881 var ab=new ArrayBuffer(3), vu=new Uint8Array(ab); vu.foo="bar";
21882 // $FlowIgnore
21883 if(!vu.foo) {o=dup(o); o.type='array'; return readSync(ab2a(d), o);}
21884 }
21885 switch((n = firstbyte(d, o))[0]) {
21886 case 0xD0: if(n[1] === 0xCF && n[2] === 0x11 && n[3] === 0xE0 && n[4] === 0xA1 && n[5] === 0xB1 && n[6] === 0x1A && n[7] === 0xE1) return read_cfb(CFB.read(d, o), o); break;
21887 case 0x09: if(n[1] <= 0x08) return parse_xlscfb(d, o); break;
21888 case 0x3C: return parse_xlml(d, o);
21889 case 0x49:
21890 if(n[1] === 0x49 && n[2] === 0x2a && n[3] === 0x00) throw new Error("TIFF Image File is not a spreadsheet");
21891 if(n[1] === 0x44) return read_wb_ID(d, o);
21892 break;
21893 case 0x54: if(n[1] === 0x41 && n[2] === 0x42 && n[3] === 0x4C) return DIF.to_workbook(d, o); break;
21894 case 0x50: return (n[1] === 0x4B && n[2] < 0x09 && n[3] < 0x09) ? read_zip(d, o) : read_prn(data, d, o, str);
21895 case 0xEF: return n[3] === 0x3C ? parse_xlml(d, o) : read_prn(data, d, o, str);
21896 case 0xFF: if(n[1] === 0xFE) { return read_utf16(d, o); } break;
21897 case 0x00: if(n[1] === 0x00 && n[2] >= 0x02 && n[3] === 0x00) return WK_.to_workbook(d, o); break;
21898 case 0x03: case 0x83: case 0x8B: case 0x8C: return DBF.to_workbook(d, o);
21899 case 0x7B: if(n[1] === 0x5C && n[2] === 0x72 && n[3] === 0x74) return RTF.to_workbook(d, o); break;
21900 case 0x0A: case 0x0D: case 0x20: return read_plaintext_raw(d, o);
21901 case 0x89: if(n[1] === 0x50 && n[2] === 0x4E && n[3] === 0x47) throw new Error("PNG Image File is not a spreadsheet"); break;
21902 }
21903 if(DBF.versions.indexOf(n[0]) > -1 && n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
21904 return read_prn(data, d, o, str);
21905}
21906
21907function readFileSync(filename, opts) {
21908 var o = opts||{}; o.type = 'file';
21909 return readSync(filename, o);
21910}
21911function write_cfb_ctr(cfb, o) {
21912 switch(o.type) {
21913 case "base64": case "binary": break;
21914 case "buffer": case "array": o.type = ""; break;
21915 case "file": return write_dl(o.file, CFB.write(cfb, {type:has_buf ? 'buffer' : ""}));
21916 case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files");
21917 default: throw new Error("Unrecognized type " + o.type);
21918 }
21919 return CFB.write(cfb, o);
21920}
21921
21922function write_zip_type(wb, opts) {
21923 var o = dup(opts||{});
21924 var z = write_zip(wb, o);
21925 var oopts = {};
21926 if(o.compression) oopts.compression = 'DEFLATE';
21927 if(o.password) oopts.type = has_buf ? "nodebuffer" : "string";
21928 else switch(o.type) {
21929 case "base64": oopts.type = "base64"; break;
21930 case "binary": oopts.type = "string"; break;
21931 case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files");
21932 case "buffer":
21933 case "file": oopts.type = has_buf ? "nodebuffer" : "string"; break;
21934 default: throw new Error("Unrecognized type " + o.type);
21935 }
21936 var out = z.FullPaths ? CFB.write(z, {fileType:"zip", type: {"nodebuffer": "buffer", "string": "binary"}[oopts.type] || oopts.type}) : z.generate(oopts);
21937/*jshint -W083 */
21938 if(o.password && typeof encrypt_agile !== 'undefined') return write_cfb_ctr(encrypt_agile(out, o.password), o); // eslint-disable-line no-undef
21939/*jshint +W083 */
21940 if(o.type === "file") return write_dl(o.file, out);
21941 return o.type == "string" ? utf8read(out) : out;
21942}
21943
21944function write_cfb_type(wb, opts) {
21945 var o = opts||{};
21946 var cfb = write_xlscfb(wb, o);
21947 return write_cfb_ctr(cfb, o);
21948}
21949
21950function write_string_type(out, opts, bom) {
21951 if(!bom) bom = "";
21952 var o = bom + out;
21953 switch(opts.type) {
21954 case "base64": return Base64.encode(utf8write(o));
21955 case "binary": return utf8write(o);
21956 case "string": return out;
21957 case "file": return write_dl(opts.file, o, 'utf8');
21958 case "buffer": {
21959 if(has_buf) return Buffer_from(o, 'utf8');
21960 else return write_string_type(o, {type:'binary'}).split("").map(function(c) { return c.charCodeAt(0); });
21961 }
21962 }
21963 throw new Error("Unrecognized type " + opts.type);
21964}
21965
21966function write_stxt_type(out, opts) {
21967 switch(opts.type) {
21968 case "base64": return Base64.encode(out);
21969 case "binary": return out;
21970 case "string": return out; /* override in sheet_to_txt */
21971 case "file": return write_dl(opts.file, out, 'binary');
21972 case "buffer": {
21973 if(has_buf) return Buffer_from(out, 'binary');
21974 else return out.split("").map(function(c) { return c.charCodeAt(0); });
21975 }
21976 }
21977 throw new Error("Unrecognized type " + opts.type);
21978}
21979
21980/* TODO: test consistency */
21981function write_binary_type(out, opts) {
21982 switch(opts.type) {
21983 case "string":
21984 case "base64":
21985 case "binary":
21986 var bstr = "";
21987 // $FlowIgnore
21988 for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]);
21989 return opts.type == 'base64' ? Base64.encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr;
21990 case "file": return write_dl(opts.file, out);
21991 case "buffer": return out;
21992 default: throw new Error("Unrecognized type " + opts.type);
21993 }
21994}
21995
21996function writeSync(wb, opts) {
21997 reset_cp();
21998 check_wb(wb);
21999 var o = dup(opts||{});
22000 if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; }
22001 if(o.type == "array") { o.type = "binary"; var out = (writeSync(wb, o)); o.type = "array"; return s2ab(out); }
22002 switch(o.bookType || 'xlsb') {
22003 case 'xml':
22004 case 'xlml': return write_string_type(write_xlml(wb, o), o);
22005 case 'slk':
22006 case 'sylk': return write_string_type(write_slk_str(wb, o), o);
22007 case 'htm':
22008 case 'html': return write_string_type(write_htm_str(wb, o), o);
22009 case 'txt': return write_stxt_type(write_txt_str(wb, o), o);
22010 case 'csv': return write_string_type(write_csv_str(wb, o), o, "\ufeff");
22011 case 'dif': return write_string_type(write_dif_str(wb, o), o);
22012 case 'dbf': return write_binary_type(write_dbf_buf(wb, o), o);
22013 case 'prn': return write_string_type(write_prn_str(wb, o), o);
22014 case 'rtf': return write_string_type(write_rtf_str(wb, o), o);
22015 case 'eth': return write_string_type(write_eth_str(wb, o), o);
22016 case 'fods': return write_string_type(write_ods(wb, o), o);
22017 case 'wk1': return write_binary_type(write_wk1_buf(wb, o), o);
22018 case 'wk3': return write_binary_type(WK_.book_to_wk3(wb, o), o);
22019 case 'biff2': if(!o.biff) o.biff = 2; /* falls through */
22020 case 'biff3': if(!o.biff) o.biff = 3; /* falls through */
22021 case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o);
22022 case 'biff5': if(!o.biff) o.biff = 5; /* falls through */
22023 case 'biff8':
22024 case 'xla':
22025 case 'xls': if(!o.biff) o.biff = 8; return write_cfb_type(wb, o);
22026 case 'xlsx':
22027 case 'xlsm':
22028 case 'xlam':
22029 case 'xlsb':
22030 case 'ods': return write_zip_type(wb, o);
22031 default: throw new Error ("Unrecognized bookType |" + o.bookType + "|");
22032 }
22033}
22034
22035function resolve_book_type(o) {
22036 if(o.bookType) return;
22037 var _BT = {
22038 "xls": "biff8",
22039 "htm": "html",
22040 "slk": "sylk",
22041 "socialcalc": "eth",
22042 "Sh33tJS": "WTF"
22043 };
22044 var ext = o.file.slice(o.file.lastIndexOf(".")).toLowerCase();
22045 if(ext.match(/^\.[a-z]+$/)) o.bookType = ext.slice(1);
22046 o.bookType = _BT[o.bookType] || o.bookType;
22047}
22048
22049function writeFileSync(wb, filename, opts) {
22050 var o = opts||{}; o.type = 'file';
22051 o.file = filename;
22052 resolve_book_type(o);
22053 return writeSync(wb, o);
22054}
22055
22056function writeFileAsync(filename, wb, opts, cb) {
22057 var o = opts||{}; o.type = 'file';
22058 o.file = filename;
22059 resolve_book_type(o);
22060 o.type = 'buffer';
22061 var _cb = cb; if(!(_cb instanceof Function)) _cb = (opts);
22062 return _fs.writeFile(filename, writeSync(wb, o), _cb);
22063}
22064function make_json_row(sheet, r, R, cols, header, hdr, dense, o) {
22065 var rr = encode_row(R);
22066 var defval = o.defval, raw = o.raw || !Object.prototype.hasOwnProperty.call(o, "raw");
22067 var isempty = true;
22068 var row = (header === 1) ? [] : {};
22069 if(header !== 1) {
22070 if(Object.defineProperty) try { Object.defineProperty(row, '__rowNum__', {value:R, enumerable:false}); } catch(e) { row.__rowNum__ = R; }
22071 else row.__rowNum__ = R;
22072 }
22073 if(!dense || sheet[R]) for (var C = r.s.c; C <= r.e.c; ++C) {
22074 var val = dense ? sheet[R][C] : sheet[cols[C] + rr];
22075 if(val === undefined || val.t === undefined) {
22076 if(defval === undefined) continue;
22077 if(hdr[C] != null) { row[hdr[C]] = defval; }
22078 continue;
22079 }
22080 var v = val.v;
22081 switch(val.t){
22082 case 'z': if(v == null) break; continue;
22083 case 'e': v = (v == 0 ? null : void 0); break;
22084 case 's': case 'd': case 'b': case 'n': break;
22085 default: throw new Error('unrecognized type ' + val.t);
22086 }
22087 if(hdr[C] != null) {
22088 if(v == null) {
22089 if(val.t == "e" && v === null) row[hdr[C]] = null;
22090 else if(defval !== undefined) row[hdr[C]] = defval;
22091 else if(raw && v === null) row[hdr[C]] = null;
22092 else continue;
22093 } else {
22094 row[hdr[C]] = raw || (o.rawNumbers && val.t == "n") ? v : format_cell(val,v,o);
22095 }
22096 if(v != null) isempty = false;
22097 }
22098 }
22099 return { row: row, isempty: isempty };
22100}
22101
22102
22103function sheet_to_json(sheet, opts) {
22104 if(sheet == null || sheet["!ref"] == null) return [];
22105 var val = {t:'n',v:0}, header = 0, offset = 1, hdr = [], v=0, vv="";
22106 var r = {s:{r:0,c:0},e:{r:0,c:0}};
22107 var o = opts || {};
22108 var range = o.range != null ? o.range : sheet["!ref"];
22109 if(o.header === 1) header = 1;
22110 else if(o.header === "A") header = 2;
22111 else if(Array.isArray(o.header)) header = 3;
22112 else if(o.header == null) header = 0;
22113 switch(typeof range) {
22114 case 'string': r = safe_decode_range(range); break;
22115 case 'number': r = safe_decode_range(sheet["!ref"]); r.s.r = range; break;
22116 default: r = range;
22117 }
22118 if(header > 0) offset = 0;
22119 var rr = encode_row(r.s.r);
22120 var cols = [];
22121 var out = [];
22122 var outi = 0, counter = 0;
22123 var dense = Array.isArray(sheet);
22124 var R = r.s.r, C = 0, CC = 0;
22125 if(dense && !sheet[R]) sheet[R] = [];
22126 for(C = r.s.c; C <= r.e.c; ++C) {
22127 cols[C] = encode_col(C);
22128 val = dense ? sheet[R][C] : sheet[cols[C] + rr];
22129 switch(header) {
22130 case 1: hdr[C] = C - r.s.c; break;
22131 case 2: hdr[C] = cols[C]; break;
22132 case 3: hdr[C] = o.header[C - r.s.c]; break;
22133 default:
22134 if(val == null) val = {w: "__EMPTY", t: "s"};
22135 vv = v = format_cell(val, null, o);
22136 counter = 0;
22137 for(CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter);
22138 hdr[C] = vv;
22139 }
22140 }
22141 for (R = r.s.r + offset; R <= r.e.r; ++R) {
22142 var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o);
22143 if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) out[outi++] = row.row;
22144 }
22145 out.length = outi;
22146 return out;
22147}
22148
22149var qreg = /"/g;
22150function make_csv_row(sheet, r, R, cols, fs, rs, FS, o) {
22151 var isempty = true;
22152 var row = [], txt = "", rr = encode_row(R);
22153 for(var C = r.s.c; C <= r.e.c; ++C) {
22154 if (!cols[C]) continue;
22155 var val = o.dense ? (sheet[R]||[])[C]: sheet[cols[C] + rr];
22156 if(val == null) txt = "";
22157 else if(val.v != null) {
22158 isempty = false;
22159 txt = ''+(o.rawNumbers && val.t == "n" ? val.v : format_cell(val, null, o));
22160 for(var i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34 || o.forceQuotes) {txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
22161 if(txt == "ID") txt = '"ID"';
22162 } else if(val.f != null && !val.F) {
22163 isempty = false;
22164 txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"';
22165 } else txt = "";
22166 /* NOTE: Excel CSV does not support array formulae */
22167 row.push(txt);
22168 }
22169 if(o.blankrows === false && isempty) return null;
22170 return row.join(FS);
22171}
22172
22173function sheet_to_csv(sheet, opts) {
22174 var out = [];
22175 var o = opts == null ? {} : opts;
22176 if(sheet == null || sheet["!ref"] == null) return "";
22177 var r = safe_decode_range(sheet["!ref"]);
22178 var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
22179 var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
22180 var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
22181 var row = "", cols = [];
22182 o.dense = Array.isArray(sheet);
22183 var colinfo = o.skipHidden && sheet["!cols"] || [];
22184 var rowinfo = o.skipHidden && sheet["!rows"] || [];
22185 for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
22186 for(var R = r.s.r; R <= r.e.r; ++R) {
22187 if ((rowinfo[R]||{}).hidden) continue;
22188 row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o);
22189 if(row == null) { continue; }
22190 if(o.strip) row = row.replace(endregex,"");
22191 out.push(row + RS);
22192 }
22193 delete o.dense;
22194 return out.join("");
22195}
22196
22197function sheet_to_txt(sheet, opts) {
22198 if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n";
22199 var s = sheet_to_csv(sheet, opts);
22200 if(typeof cptable == 'undefined' || opts.type == 'string') return s;
22201 var o = cptable.utils.encode(1200, s, 'str');
22202 return String.fromCharCode(255) + String.fromCharCode(254) + o;
22203}
22204
22205function sheet_to_formulae(sheet) {
22206 var y = "", x, val="";
22207 if(sheet == null || sheet["!ref"] == null) return [];
22208 var r = safe_decode_range(sheet['!ref']), rr = "", cols = [], C;
22209 var cmds = [];
22210 var dense = Array.isArray(sheet);
22211 for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C);
22212 for(var R = r.s.r; R <= r.e.r; ++R) {
22213 rr = encode_row(R);
22214 for(C = r.s.c; C <= r.e.c; ++C) {
22215 y = cols[C] + rr;
22216 x = dense ? (sheet[R]||[])[C] : sheet[y];
22217 val = "";
22218 if(x === undefined) continue;
22219 else if(x.F != null) {
22220 y = x.F;
22221 if(!x.f) continue;
22222 val = x.f;
22223 if(y.indexOf(":") == -1) y = y + ":" + y;
22224 }
22225 if(x.f != null) val = x.f;
22226 else if(x.t == 'z') continue;
22227 else if(x.t == 'n' && x.v != null) val = "" + x.v;
22228 else if(x.t == 'b') val = x.v ? "TRUE" : "FALSE";
22229 else if(x.w !== undefined) val = "'" + x.w;
22230 else if(x.v === undefined) continue;
22231 else if(x.t == 's') val = "'" + x.v;
22232 else val = ""+x.v;
22233 cmds[cmds.length] = y + "=" + val;
22234 }
22235 }
22236 return cmds;
22237}
22238
22239function sheet_add_json(_ws, js, opts) {
22240 var o = opts || {};
22241 var offset = +!o.skipHeader;
22242 var ws = _ws || ({});
22243 var _R = 0, _C = 0;
22244 if(ws && o.origin != null) {
22245 if(typeof o.origin == 'number') _R = o.origin;
22246 else {
22247 var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
22248 _R = _origin.r; _C = _origin.c;
22249 }
22250 }
22251 var cell;
22252 var range = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}});
22253 if(ws['!ref']) {
22254 var _range = safe_decode_range(ws['!ref']);
22255 range.e.c = Math.max(range.e.c, _range.e.c);
22256 range.e.r = Math.max(range.e.r, _range.e.r);
22257 if(_R == -1) { _R = _range.e.r + 1; range.e.r = _R + js.length - 1 + offset; }
22258 } else {
22259 if(_R == -1) { _R = 0; range.e.r = js.length - 1 + offset; }
22260 }
22261 var hdr = o.header || [], C = 0;
22262
22263 js.forEach(function (JS, R) {
22264 keys(JS).forEach(function(k) {
22265 if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k;
22266 var v = JS[k];
22267 var t = 'z';
22268 var z = "";
22269 var ref = encode_cell({c:_C + C,r:_R + R + offset});
22270 cell = utils.sheet_get_cell(ws, ref);
22271 if(v && typeof v === 'object' && !(v instanceof Date)){
22272 ws[ref] = v;
22273 } else {
22274 if(typeof v == 'number') t = 'n';
22275 else if(typeof v == 'boolean') t = 'b';
22276 else if(typeof v == 'string') t = 's';
22277 else if(v instanceof Date) {
22278 t = 'd';
22279 if(!o.cellDates) { t = 'n'; v = datenum(v); }
22280 z = (o.dateNF || SSF._table[14]);
22281 }
22282 else if(v === null && o.nullError) { t = 'e'; v = 0; }
22283 if(!cell) ws[ref] = cell = ({t:t, v:v});
22284 else {
22285 cell.t = t; cell.v = v;
22286 delete cell.w; delete cell.R;
22287 if(z) cell.z = z;
22288 }
22289 if(z) cell.z = z;
22290 }
22291 });
22292 });
22293 range.e.c = Math.max(range.e.c, _C + hdr.length - 1);
22294 var __R = encode_row(_R);
22295 if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]};
22296 ws['!ref'] = encode_range(range);
22297 return ws;
22298}
22299function json_to_sheet(js, opts) { return sheet_add_json(null, js, opts); }
22300
22301var utils = {
22302 encode_col: encode_col,
22303 encode_row: encode_row,
22304 encode_cell: encode_cell,
22305 encode_range: encode_range,
22306 decode_col: decode_col,
22307 decode_row: decode_row,
22308 split_cell: split_cell,
22309 decode_cell: decode_cell,
22310 decode_range: decode_range,
22311 format_cell: format_cell,
22312 get_formulae: sheet_to_formulae,
22313 make_csv: sheet_to_csv,
22314 make_json: sheet_to_json,
22315 make_formulae: sheet_to_formulae,
22316 sheet_add_aoa: sheet_add_aoa,
22317 sheet_add_json: sheet_add_json,
22318 sheet_add_dom: sheet_add_dom,
22319 aoa_to_sheet: aoa_to_sheet,
22320 json_to_sheet: json_to_sheet,
22321 table_to_sheet: parse_dom_table,
22322 table_to_book: table_to_book,
22323 sheet_to_csv: sheet_to_csv,
22324 sheet_to_txt: sheet_to_txt,
22325 sheet_to_json: sheet_to_json,
22326 sheet_to_html: HTML_.from_sheet,
22327 sheet_to_formulae: sheet_to_formulae,
22328 sheet_to_row_object_array: sheet_to_json
22329};
22330
22331(function(utils) {
22332utils.consts = utils.consts || {};
22333function add_consts(R/*Array<any>*/) { R.forEach(function(a){ utils.consts[a[0]] = a[1]; }); }
22334
22335function get_default(x, y, z) { return x[y] != null ? x[y] : (x[y] = z); }
22336
22337/* get cell, creating a stub if necessary */
22338function ws_get_cell_stub(ws, R, C) {
22339 /* A1 cell address */
22340 if(typeof R == "string") {
22341 /* dense */
22342 if(Array.isArray(ws)) {
22343 var RC = decode_cell(R);
22344 if(!ws[RC.r]) ws[RC.r] = [];
22345 return ws[RC.r][RC.c] || (ws[RC.r][RC.c] = {t:'z'});
22346 }
22347 return ws[R] || (ws[R] = {t:'z'});
22348 }
22349 /* cell address object */
22350 if(typeof R != "number") return ws_get_cell_stub(ws, encode_cell(R));
22351 /* R and C are 0-based indices */
22352 return ws_get_cell_stub(ws, encode_cell({r:R,c:C||0}));
22353}
22354utils.sheet_get_cell = ws_get_cell_stub;
22355
22356/* find sheet index for given name / validate index */
22357function wb_sheet_idx(wb, sh) {
22358 if(typeof sh == "number") {
22359 if(sh >= 0 && wb.SheetNames.length > sh) return sh;
22360 throw new Error("Cannot find sheet # " + sh);
22361 } else if(typeof sh == "string") {
22362 var idx = wb.SheetNames.indexOf(sh);
22363 if(idx > -1) return idx;
22364 throw new Error("Cannot find sheet name |" + sh + "|");
22365 } else throw new Error("Cannot find sheet |" + sh + "|");
22366}
22367
22368/* simple blank workbook object */
22369utils.book_new = function() {
22370 return { SheetNames: [], Sheets: {} };
22371};
22372
22373/* add a worksheet to the end of a given workbook */
22374utils.book_append_sheet = function(wb, ws, name) {
22375 if(!name) for(var i = 1; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break;
22376 if(!name || wb.SheetNames.length >= 0xFFFF) throw new Error("Too many worksheets");
22377 check_ws_name(name);
22378 if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!");
22379
22380 wb.SheetNames.push(name);
22381 wb.Sheets[name] = ws;
22382};
22383
22384/* set sheet visibility (visible/hidden/very hidden) */
22385utils.book_set_sheet_visibility = function(wb, sh, vis) {
22386 get_default(wb,"Workbook",{});
22387 get_default(wb.Workbook,"Sheets",[]);
22388
22389 var idx = wb_sheet_idx(wb, sh);
22390 // $FlowIgnore
22391 get_default(wb.Workbook.Sheets,idx, {});
22392
22393 switch(vis) {
22394 case 0: case 1: case 2: break;
22395 default: throw new Error("Bad sheet visibility setting " + vis);
22396 }
22397 // $FlowIgnore
22398 wb.Workbook.Sheets[idx].Hidden = vis;
22399};
22400add_consts([
22401 ["SHEET_VISIBLE", 0],
22402 ["SHEET_HIDDEN", 1],
22403 ["SHEET_VERY_HIDDEN", 2]
22404]);
22405
22406/* set number format */
22407utils.cell_set_number_format = function(cell, fmt) {
22408 cell.z = fmt;
22409 return cell;
22410};
22411
22412/* set cell hyperlink */
22413utils.cell_set_hyperlink = function(cell, target, tooltip) {
22414 if(!target) {
22415 delete cell.l;
22416 } else {
22417 cell.l = ({ Target: target });
22418 if(tooltip) cell.l.Tooltip = tooltip;
22419 }
22420 return cell;
22421};
22422utils.cell_set_internal_link = function(cell, range, tooltip) { return utils.cell_set_hyperlink(cell, "#" + range, tooltip); };
22423
22424/* add to cell comments */
22425utils.cell_add_comment = function(cell, text, author) {
22426 if(!cell.c) cell.c = [];
22427 cell.c.push({t:text, a:author||"SheetJS"});
22428};
22429
22430/* set array formula and flush related cells */
22431utils.sheet_set_array_formula = function(ws, range, formula) {
22432 var rng = typeof range != "string" ? range : safe_decode_range(range);
22433 var rngstr = typeof range == "string" ? range : encode_range(range);
22434 for(var R = rng.s.r; R <= rng.e.r; ++R) for(var C = rng.s.c; C <= rng.e.c; ++C) {
22435 var cell = ws_get_cell_stub(ws, R, C);
22436 cell.t = 'n';
22437 cell.F = rngstr;
22438 delete cell.v;
22439 if(R == rng.s.r && C == rng.s.c) cell.f = formula;
22440 }
22441 return ws;
22442};
22443
22444return utils;
22445})(utils);
22446
22447if(has_buf && typeof require != 'undefined') (function() {
22448 var Readable = {}.Readable;
22449
22450 var write_csv_stream = function(sheet, opts) {
22451 var stream = Readable();
22452 var o = opts == null ? {} : opts;
22453 if(sheet == null || sheet["!ref"] == null) { stream.push(null); return stream; }
22454 var r = safe_decode_range(sheet["!ref"]);
22455 var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
22456 var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
22457 var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
22458 var row = "", cols = [];
22459 o.dense = Array.isArray(sheet);
22460 var colinfo = o.skipHidden && sheet["!cols"] || [];
22461 var rowinfo = o.skipHidden && sheet["!rows"] || [];
22462 for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
22463 var R = r.s.r;
22464 var BOM = false;
22465 stream._read = function() {
22466 if(!BOM) { BOM = true; return stream.push("\uFEFF"); }
22467 while(R <= r.e.r) {
22468 ++R;
22469 if ((rowinfo[R-1]||{}).hidden) continue;
22470 row = make_csv_row(sheet, r, R-1, cols, fs, rs, FS, o);
22471 if(row != null) {
22472 if(o.strip) row = row.replace(endregex,"");
22473 stream.push(row + RS);
22474 break;
22475 }
22476 }
22477 if(R > r.e.r) return stream.push(null);
22478 };
22479 return stream;
22480 };
22481
22482 var write_html_stream = function(ws, opts) {
22483 var stream = Readable();
22484
22485 var o = opts || {};
22486 var header = o.header != null ? o.header : HTML_.BEGIN;
22487 var footer = o.footer != null ? o.footer : HTML_.END;
22488 stream.push(header);
22489 var r = decode_range(ws['!ref']);
22490 o.dense = Array.isArray(ws);
22491 stream.push(HTML_._preamble(ws, r, o));
22492 var R = r.s.r;
22493 var end = false;
22494 stream._read = function() {
22495 if(R > r.e.r) {
22496 if(!end) { end = true; stream.push("</table>" + footer); }
22497 return stream.push(null);
22498 }
22499 while(R <= r.e.r) {
22500 stream.push(HTML_._row(ws, r, R, o));
22501 ++R;
22502 break;
22503 }
22504 };
22505 return stream;
22506 };
22507
22508 var write_json_stream = function(sheet, opts) {
22509 var stream = Readable({objectMode:true});
22510
22511 if(sheet == null || sheet["!ref"] == null) { stream.push(null); return stream; }
22512 var val = {t:'n',v:0}, header = 0, offset = 1, hdr = [], v=0, vv="";
22513 var r = {s:{r:0,c:0},e:{r:0,c:0}};
22514 var o = opts || {};
22515 var range = o.range != null ? o.range : sheet["!ref"];
22516 if(o.header === 1) header = 1;
22517 else if(o.header === "A") header = 2;
22518 else if(Array.isArray(o.header)) header = 3;
22519 switch(typeof range) {
22520 case 'string': r = safe_decode_range(range); break;
22521 case 'number': r = safe_decode_range(sheet["!ref"]); r.s.r = range; break;
22522 default: r = range;
22523 }
22524 if(header > 0) offset = 0;
22525 var rr = encode_row(r.s.r);
22526 var cols = [];
22527 var counter = 0;
22528 var dense = Array.isArray(sheet);
22529 var R = r.s.r, C = 0, CC = 0;
22530 if(dense && !sheet[R]) sheet[R] = [];
22531 for(C = r.s.c; C <= r.e.c; ++C) {
22532 cols[C] = encode_col(C);
22533 val = dense ? sheet[R][C] : sheet[cols[C] + rr];
22534 switch(header) {
22535 case 1: hdr[C] = C - r.s.c; break;
22536 case 2: hdr[C] = cols[C]; break;
22537 case 3: hdr[C] = o.header[C - r.s.c]; break;
22538 default:
22539 if(val == null) val = {w: "__EMPTY", t: "s"};
22540 vv = v = format_cell(val, null, o);
22541 counter = 0;
22542 for(CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter);
22543 hdr[C] = vv;
22544 }
22545 }
22546 R = r.s.r + offset;
22547 stream._read = function() {
22548 if(R > r.e.r) return stream.push(null);
22549 while(R <= r.e.r) {
22550 //if ((rowinfo[R-1]||{}).hidden) continue;
22551 var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o);
22552 ++R;
22553 if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) {
22554 stream.push(row.row);
22555 break;
22556 }
22557 }
22558 };
22559 return stream;
22560 };
22561
22562 XLSX.stream = {
22563 to_json: write_json_stream,
22564 to_html: write_html_stream,
22565 to_csv: write_csv_stream
22566 };
22567})();
22568
22569if(typeof parse_xlscfb !== "undefined") XLSX.parse_xlscfb = parse_xlscfb;
22570XLSX.parse_zip = parse_zip;
22571XLSX.read = readSync; //xlsread
22572XLSX.readFile = readFileSync; //readFile
22573XLSX.readFileSync = readFileSync;
22574XLSX.write = writeSync;
22575XLSX.writeFile = writeFileSync;
22576XLSX.writeFileSync = writeFileSync;
22577XLSX.writeFileAsync = writeFileAsync;
22578XLSX.utils = utils;
22579XLSX.SSF = SSF;
22580if(typeof CFB !== "undefined") XLSX.CFB = CFB;
22581}
22582/*global define */
22583if(typeof exports !== 'undefined') make_xlsx_lib(exports);
22584else if(typeof module !== 'undefined' && module.exports) make_xlsx_lib(module.exports);
22585else if(typeof define === 'function' && define.amd) define('xlsx', function() { if(!XLSX.version) make_xlsx_lib(XLSX); return XLSX; });
22586else make_xlsx_lib(XLSX);
22587/* NOTE: the following extra line is needed for "Lightning Locker Service" */
22588if(typeof window !== 'undefined' && !window.XLSX) window.XLSX = XLSX;
22589/*exported XLS, ODS */
22590var XLS = XLSX, ODS = XLSX;