UNPKG

833 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 = {};
6XLSX.version = '0.17.4';
7var current_codepage = 1200, current_ansi = 1252;
8
9var VALID_ANSI = [ 874, 932, 936, 949, 950 ];
10for(var i = 0; i <= 8; ++i) VALID_ANSI.push(1250 + i);
11/* ECMA-376 Part I 18.4.1 charset to codepage mapping */
12var CS2CP = ({
13 /*::[*/0/*::]*/: 1252, /* ANSI */
14 /*::[*/1/*::]*/: 65001, /* DEFAULT */
15 /*::[*/2/*::]*/: 65001, /* SYMBOL */
16 /*::[*/77/*::]*/: 10000, /* MAC */
17 /*::[*/128/*::]*/: 932, /* SHIFTJIS */
18 /*::[*/129/*::]*/: 949, /* HANGUL */
19 /*::[*/130/*::]*/: 1361, /* JOHAB */
20 /*::[*/134/*::]*/: 936, /* GB2312 */
21 /*::[*/136/*::]*/: 950, /* CHINESEBIG5 */
22 /*::[*/161/*::]*/: 1253, /* GREEK */
23 /*::[*/162/*::]*/: 1254, /* TURKISH */
24 /*::[*/163/*::]*/: 1258, /* VIETNAMESE */
25 /*::[*/177/*::]*/: 1255, /* HEBREW */
26 /*::[*/178/*::]*/: 1256, /* ARABIC */
27 /*::[*/186/*::]*/: 1257, /* BALTIC */
28 /*::[*/204/*::]*/: 1251, /* RUSSIAN */
29 /*::[*/222/*::]*/: 874, /* THAI */
30 /*::[*/238/*::]*/: 1250, /* EASTEUROPE */
31 /*::[*/255/*::]*/: 1252, /* OEM */
32 /*::[*/69/*::]*/: 6969 /* MISC */
33}/*:any*/);
34
35var set_ansi = function(cp/*:number*/) { if(VALID_ANSI.indexOf(cp) == -1) return; current_ansi = CS2CP[0] = cp; };
36function reset_ansi() { set_ansi(1252); }
37
38var set_cp = function(cp/*:number*/) { current_codepage = cp; set_ansi(cp); };
39function reset_cp() { set_cp(1200); reset_ansi(); }
40
41function char_codes(data/*:string*/)/*:Array<number>*/ { var o/*:Array<number>*/ = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; }
42
43function utf16leread(data/*:string*/)/*:string*/ {
44 var o/*:Array<string>*/ = [];
45 for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i) + (data.charCodeAt(2*i+1)<<8));
46 return o.join("");
47}
48function utf16beread(data/*:string*/)/*:string*/ {
49 var o/*:Array<string>*/ = [];
50 for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i+1) + (data.charCodeAt(2*i)<<8));
51 return o.join("");
52}
53
54var debom = function(data/*:string*/)/*:string*/ {
55 var c1 = data.charCodeAt(0), c2 = data.charCodeAt(1);
56 if(c1 == 0xFF && c2 == 0xFE) return utf16leread(data.slice(2));
57 if(c1 == 0xFE && c2 == 0xFF) return utf16beread(data.slice(2));
58 if(c1 == 0xFEFF) return data.slice(1);
59 return data;
60};
61
62var _getchar = function _gc1(x/*:number*/)/*:string*/ { return String.fromCharCode(x); };
63var _getansi = function _ga1(x/*:number*/)/*:string*/ { return String.fromCharCode(x); };
64var DENSE = null;
65var DIF_XL = true;
66var Base64 = (function make_b64(){
67 var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
68 return {
69 encode: function(input/*:string*/)/*:string*/ {
70 var o = "";
71 var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0;
72 for(var i = 0; i < input.length; ) {
73 c1 = input.charCodeAt(i++);
74 e1 = (c1 >> 2);
75
76 c2 = input.charCodeAt(i++);
77 e2 = ((c1 & 3) << 4) | (c2 >> 4);
78
79 c3 = input.charCodeAt(i++);
80 e3 = ((c2 & 15) << 2) | (c3 >> 6);
81 e4 = (c3 & 63);
82 if (isNaN(c2)) { e3 = e4 = 64; }
83 else if (isNaN(c3)) { e4 = 64; }
84 o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4);
85 }
86 return o;
87 },
88 decode: function b64_decode(input/*:string*/)/*:string*/ {
89 var o = "";
90 var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0;
91 input = input.replace(/[^\w\+\/\=]/g, "");
92 for(var i = 0; i < input.length;) {
93 e1 = map.indexOf(input.charAt(i++));
94 e2 = map.indexOf(input.charAt(i++));
95 c1 = (e1 << 2) | (e2 >> 4);
96 o += String.fromCharCode(c1);
97
98 e3 = map.indexOf(input.charAt(i++));
99 c2 = ((e2 & 15) << 4) | (e3 >> 2);
100 if (e3 !== 64) { o += String.fromCharCode(c2); }
101
102 e4 = map.indexOf(input.charAt(i++));
103 c3 = ((e3 & 3) << 6) | e4;
104 if (e4 !== 64) { o += String.fromCharCode(c3); }
105 }
106 return o;
107 }
108 };
109})();
110var has_buf = (typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.node);
111
112var Buffer_from = /*::(*/function(){}/*:: :any)*/;
113
114if(typeof Buffer !== 'undefined') {
115 var nbfs = !Buffer.from;
116 if(!nbfs) try { Buffer.from("foo", "utf8"); } catch(e) { nbfs = true; }
117 Buffer_from = nbfs ? function(buf, enc) { return (enc) ? new Buffer(buf, enc) : new Buffer(buf); } : Buffer.from.bind(Buffer);
118 // $FlowIgnore
119 if(!Buffer.alloc) Buffer.alloc = function(n) { return new Buffer(n); };
120 // $FlowIgnore
121 if(!Buffer.allocUnsafe) Buffer.allocUnsafe = function(n) { return new Buffer(n); };
122}
123
124function new_raw_buf(len/*:number*/) {
125 /* jshint -W056 */
126 return has_buf ? Buffer.alloc(len) : new Array(len);
127 /* jshint +W056 */
128}
129
130function new_unsafe_buf(len/*:number*/) {
131 /* jshint -W056 */
132 return has_buf ? Buffer.allocUnsafe(len) : new Array(len);
133 /* jshint +W056 */
134}
135
136var s2a = function s2a(s/*:string*/)/*:any*/ {
137 if(has_buf) return Buffer_from(s, "binary");
138 return s.split("").map(function(x/*:string*/)/*:number*/{ return x.charCodeAt(0) & 0xff; });
139};
140
141function s2ab(s/*:string*/)/*:any*/ {
142 if(typeof ArrayBuffer === 'undefined') return s2a(s);
143 var buf = new ArrayBuffer(s.length), view = new Uint8Array(buf);
144 for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
145 return buf;
146}
147
148function a2s(data/*:any*/)/*:string*/ {
149 if(Array.isArray(data)) return data.map(function(c) { return String.fromCharCode(c); }).join("");
150 var o/*:Array<string>*/ = []; for(var i = 0; i < data.length; ++i) o[i] = String.fromCharCode(data[i]); return o.join("");
151}
152
153function a2u(data/*:Array<number>*/)/*:Uint8Array*/ {
154 if(typeof Uint8Array === 'undefined') throw new Error("Unsupported");
155 return new Uint8Array(data);
156}
157
158function ab2a(data/*:ArrayBuffer|Uint8Array*/)/*:Array<number>*/ {
159 if(typeof ArrayBuffer == 'undefined') throw new Error("Unsupported");
160 if(data instanceof ArrayBuffer) return ab2a(new Uint8Array(data));
161 /*:: if(data instanceof ArrayBuffer) throw new Error("unreachable"); */
162 var o = new Array(data.length);
163 for(var i = 0; i < data.length; ++i) o[i] = data[i];
164 return o;
165}
166
167var bconcat = function(bufs) { return [].concat.apply([], bufs); };
168
169var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/g;
170/*::
171declare type Block = any;
172declare type BufArray = {
173 newblk(sz:number):Block;
174 next(sz:number):Block;
175 end():any;
176 push(buf:Block):void;
177};
178
179type RecordHopperCB = {(d:any, Rn:string, RT:number):?boolean;};
180
181type EvertType = {[string]:string};
182type EvertNumType = {[string]:number};
183type EvertArrType = {[string]:Array<string>};
184
185type StringConv = {(string):string};
186
187type WriteObjStrFactory = {from_sheet(ws:Worksheet, o:any, wb:?Workbook):string};
188*/
189/* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */
190/*jshint -W041 */
191var SSF/*:SSFModule*/ = ({}/*:any*/);
192var make_ssf = function make_ssf(SSF/*:SSFModule*/){
193SSF.version = '0.11.2';
194function _strrev(x/*:string*/)/*:string*/ { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; }
195function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; }
196function pad0(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
197function pad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v;return t.length>=d?t:fill(' ',d-t.length)+t;}
198function rpad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);}
199function pad0r1(v/*:any*/,d/*:number*/)/*:string*/{var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;}
200function pad0r2(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
201var p2_32 = Math.pow(2,32);
202function pad0r(v/*:any*/,d/*:number*/)/*:string*/{if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); }
203function isgeneral(s/*:string*/, i/*:?number*/)/*:boolean*/ { i = i || 0; return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; }
204/*::
205type SSF_write_num = {(type:string, fmt:string, val:number):string};
206*/
207var days/*:Array<Array<string> >*/ = [
208 ['Sun', 'Sunday'],
209 ['Mon', 'Monday'],
210 ['Tue', 'Tuesday'],
211 ['Wed', 'Wednesday'],
212 ['Thu', 'Thursday'],
213 ['Fri', 'Friday'],
214 ['Sat', 'Saturday']
215];
216var months/*:Array<Array<string> >*/ = [
217 ['J', 'Jan', 'January'],
218 ['F', 'Feb', 'February'],
219 ['M', 'Mar', 'March'],
220 ['A', 'Apr', 'April'],
221 ['M', 'May', 'May'],
222 ['J', 'Jun', 'June'],
223 ['J', 'Jul', 'July'],
224 ['A', 'Aug', 'August'],
225 ['S', 'Sep', 'September'],
226 ['O', 'Oct', 'October'],
227 ['N', 'Nov', 'November'],
228 ['D', 'Dec', 'December']
229];
230function init_table(t/*:any*/) {
231 t[0]= 'General';
232 t[1]= '0';
233 t[2]= '0.00';
234 t[3]= '#,##0';
235 t[4]= '#,##0.00';
236 t[9]= '0%';
237 t[10]= '0.00%';
238 t[11]= '0.00E+00';
239 t[12]= '# ?/?';
240 t[13]= '# ??/??';
241 t[14]= 'm/d/yy';
242 t[15]= 'd-mmm-yy';
243 t[16]= 'd-mmm';
244 t[17]= 'mmm-yy';
245 t[18]= 'h:mm AM/PM';
246 t[19]= 'h:mm:ss AM/PM';
247 t[20]= 'h:mm';
248 t[21]= 'h:mm:ss';
249 t[22]= 'm/d/yy h:mm';
250 t[37]= '#,##0 ;(#,##0)';
251 t[38]= '#,##0 ;[Red](#,##0)';
252 t[39]= '#,##0.00;(#,##0.00)';
253 t[40]= '#,##0.00;[Red](#,##0.00)';
254 t[45]= 'mm:ss';
255 t[46]= '[h]:mm:ss';
256 t[47]= 'mmss.0';
257 t[48]= '##0.0E+0';
258 t[49]= '@';
259 t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "';
260}
261
262var table_fmt = {};
263init_table(table_fmt);
264/* Defaults determined by systematically testing in Excel 2019 */
265
266/* These formats appear to default to other formats in the table */
267var default_map/*:Array<number>*/ = [];
268var defi = 0;
269
270// 5 -> 37 ... 8 -> 40
271for(defi = 5; defi <= 8; ++defi) default_map[defi] = 32 + defi;
272
273// 23 -> 0 ... 26 -> 0
274for(defi = 23; defi <= 26; ++defi) default_map[defi] = 0;
275
276// 27 -> 14 ... 31 -> 14
277for(defi = 27; defi <= 31; ++defi) default_map[defi] = 14;
278// 50 -> 14 ... 58 -> 14
279for(defi = 50; defi <= 58; ++defi) default_map[defi] = 14;
280
281// 59 -> 1 ... 62 -> 4
282for(defi = 59; defi <= 62; ++defi) default_map[defi] = defi - 58;
283// 67 -> 9 ... 68 -> 10
284for(defi = 67; defi <= 68; ++defi) default_map[defi] = defi - 58;
285// 72 -> 14 ... 75 -> 17
286for(defi = 72; defi <= 75; ++defi) default_map[defi] = defi - 58;
287
288// 69 -> 12 ... 71 -> 14
289for(defi = 67; defi <= 68; ++defi) default_map[defi] = defi - 57;
290
291// 76 -> 20 ... 78 -> 22
292for(defi = 76; defi <= 78; ++defi) default_map[defi] = defi - 56;
293
294// 79 -> 45 ... 81 -> 47
295for(defi = 79; defi <= 81; ++defi) default_map[defi] = defi - 34;
296
297// 82 -> 0 ... 65536 -> 0 (omitted)
298
299/* These formats technically refer to Accounting formats with no equivalent */
300var default_str/*:Array<string>*/ = [];
301
302// 5 -- Currency, 0 decimal, black negative
303default_str[5] = default_str[63] = '"$"#,##0_);\\("$"#,##0\\)';
304// 6 -- Currency, 0 decimal, red negative
305default_str[6] = default_str[64] = '"$"#,##0_);[Red]\\("$"#,##0\\)';
306// 7 -- Currency, 2 decimal, black negative
307default_str[7] = default_str[65] = '"$"#,##0.00_);\\("$"#,##0.00\\)';
308// 8 -- Currency, 2 decimal, red negative
309default_str[8] = default_str[66] = '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)';
310
311// 41 -- Accounting, 0 decimal, No Symbol
312default_str[41] = '_(* #,##0_);_(* \\(#,##0\\);_(* "-"_);_(@_)';
313// 42 -- Accounting, 0 decimal, $ Symbol
314default_str[42] = '_("$"* #,##0_);_("$"* \\(#,##0\\);_("$"* "-"_);_(@_)';
315// 43 -- Accounting, 2 decimal, No Symbol
316default_str[43] = '_(* #,##0.00_);_(* \\(#,##0.00\\);_(* "-"??_);_(@_)';
317// 44 -- Accounting, 2 decimal, $ Symbol
318default_str[44] = '_("$"* #,##0.00_);_("$"* \\(#,##0.00\\);_("$"* "-"??_);_(@_)';
319function frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
320 var sgn = x < 0 ? -1 : 1;
321 var B = x * sgn;
322 var P_2 = 0, P_1 = 1, P = 0;
323 var Q_2 = 1, Q_1 = 0, Q = 0;
324 var A = Math.floor(B);
325 while(Q_1 < D) {
326 A = Math.floor(B);
327 P = A * P_1 + P_2;
328 Q = A * Q_1 + Q_2;
329 if((B - A) < 0.00000005) break;
330 B = 1 / (B - A);
331 P_2 = P_1; P_1 = P;
332 Q_2 = Q_1; Q_1 = Q;
333 }
334 if(Q > D) { if(Q_1 > D) { Q = Q_2; P = P_2; } else { Q = Q_1; P = P_1; } }
335 if(!mixed) return [0, sgn * P, Q];
336 var q = Math.floor(sgn * P/Q);
337 return [q, sgn*P - q*Q, Q];
338}
339function parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
340 if(v > 2958465 || v < 0) return null;
341 var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
342 var dout=[];
343 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};
344 if(Math.abs(out.u) < 1e-6) out.u = 0;
345 if(opts && opts.date1904) date += 1462;
346 if(out.u > 0.9999) {
347 out.u = 0;
348 if(++time == 86400) { out.T = time = 0; ++date; ++out.D; }
349 }
350 if(date === 60) {dout = b2 ? [1317,10,29] : [1900,2,29]; dow=3;}
351 else if(date === 0) {dout = b2 ? [1317,8,29] : [1900,1,0]; dow=6;}
352 else {
353 if(date > 60) --date;
354 /* 1 = Jan 1 1900 in Gregorian */
355 var d = new Date(1900, 0, 1);
356 d.setDate(d.getDate() + date - 1);
357 dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
358 dow = d.getDay();
359 if(date < 60) dow = (dow + 6) % 7;
360 if(b2) dow = fix_hijri(d, dout);
361 }
362 out.y = dout[0]; out.m = dout[1]; out.d = dout[2];
363 out.S = time % 60; time = Math.floor(time / 60);
364 out.M = time % 60; time = Math.floor(time / 60);
365 out.H = time;
366 out.q = dow;
367 return out;
368}
369SSF.parse_date_code = parse_date_code;
370var basedate = new Date(1899, 11, 31, 0, 0, 0);
371var dnthresh = basedate.getTime();
372var base1904 = new Date(1900, 2, 1, 0, 0, 0);
373function datenum_local(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
374 var epoch = v.getTime();
375 if(date1904) epoch -= 1461*24*60*60*1000;
376 else if(v >= base1904) epoch += 24*60*60*1000;
377 return (epoch - (dnthresh + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
378}
379/* The longest 32-bit integer text is "-4294967296", exactly 11 chars */
380function general_fmt_int(v/*:number*/)/*:string*/ { return v.toString(10); }
381SSF._general_int = general_fmt_int;
382
383/* ECMA-376 18.8.30 numFmt*/
384/* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
385var general_fmt_num = (function make_general_fmt_num() {
386 var trailing_zeroes_and_decimal = /(?:\.0*|(\.\d*[1-9])0+)$/;
387 function strip_decimal(o/*:string*/)/*:string*/ {
388 return (o.indexOf(".") == -1) ? o : o.replace(trailing_zeroes_and_decimal, "$1");
389 }
390
391 /* General Exponential always shows 2 digits exp and trims the mantissa */
392 var mantissa_zeroes_and_decimal = /(?:\.0*|(\.\d*[1-9])0+)[Ee]/;
393 var exp_with_single_digit = /(E[+-])(\d)$/;
394 function normalize_exp(o/*:string*/)/*:string*/ {
395 if(o.indexOf("E") == -1) return o;
396 return o.replace(mantissa_zeroes_and_decimal,"$1E").replace(exp_with_single_digit,"$10$2");
397 }
398
399 /* exponent >= -9 and <= 9 */
400 function small_exp(v/*:number*/)/*:string*/ {
401 var w = (v<0?12:11);
402 var o = strip_decimal(v.toFixed(12)); if(o.length <= w) return o;
403 o = v.toPrecision(10); if(o.length <= w) return o;
404 return v.toExponential(5);
405 }
406
407 /* exponent >= 11 or <= -10 likely exponential */
408 function large_exp(v/*:number*/)/*:string*/ {
409 var o = strip_decimal(v.toFixed(11));
410 return (o.length > (v<0?12:11) || o === "0" || o === "-0") ? v.toPrecision(6) : o;
411 }
412
413 function general_fmt_num_base(v/*:number*/)/*:string*/ {
414 var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
415
416 if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
417 else if(Math.abs(V) <= 9) o = small_exp(v);
418 else if(V === 10) o = v.toFixed(10).substr(0,12);
419 else o = large_exp(v);
420
421 return strip_decimal(normalize_exp(o.toUpperCase()));
422 }
423
424 return general_fmt_num_base;
425})();
426SSF._general_num = general_fmt_num;
427
428/*
429 "General" rules:
430 - text is passed through ("@")
431 - booleans are rendered as TRUE/FALSE
432 - "up to 11 characters" displayed for numbers
433 - Default date format (code 14) used for Dates
434
435 TODO: technically the display depends on the width of the cell
436*/
437function general_fmt(v/*:any*/, opts/*:any*/) {
438 switch(typeof v) {
439 case 'string': return v;
440 case 'boolean': return v ? "TRUE" : "FALSE";
441 case 'number': return (v|0) === v ? v.toString(10) : general_fmt_num(v);
442 case 'undefined': return "";
443 case 'object':
444 if(v == null) return "";
445 if(v instanceof Date) return format(14, datenum_local(v, opts && opts.date1904), opts);
446 }
447 throw new Error("unsupported value in General format: " + v);
448}
449SSF._general = general_fmt;
450function fix_hijri(date/*:Date*/, o/*:[number, number, number]*/) {
451 /* TODO: properly adjust y/m/d and */
452 o[0] -= 581;
453 var dow = date.getDay();
454 if(date < 60) dow = (dow + 6) % 7;
455 return dow;
456}
457//var THAI_DIGITS = "\u0E50\u0E51\u0E52\u0E53\u0E54\u0E55\u0E56\u0E57\u0E58\u0E59".split("");
458/*jshint -W086 */
459function write_date(type/*:number*/, fmt/*:string*/, val, ss0/*:?number*/)/*:string*/ {
460 var o="", ss=0, tt=0, y = val.y, out, outl = 0;
461 switch(type) {
462 case 98: /* 'b' buddhist year */
463 y = val.y + 543;
464 /* falls through */
465 case 121: /* 'y' year */
466 switch(fmt.length) {
467 case 1: case 2: out = y % 100; outl = 2; break;
468 default: out = y % 10000; outl = 4; break;
469 } break;
470 case 109: /* 'm' month */
471 switch(fmt.length) {
472 case 1: case 2: out = val.m; outl = fmt.length; break;
473 case 3: return months[val.m-1][1];
474 case 5: return months[val.m-1][0];
475 default: return months[val.m-1][2];
476 } break;
477 case 100: /* 'd' day */
478 switch(fmt.length) {
479 case 1: case 2: out = val.d; outl = fmt.length; break;
480 case 3: return days[val.q][0];
481 default: return days[val.q][1];
482 } break;
483 case 104: /* 'h' 12-hour */
484 switch(fmt.length) {
485 case 1: case 2: out = 1+(val.H+11)%12; outl = fmt.length; break;
486 default: throw 'bad hour format: ' + fmt;
487 } break;
488 case 72: /* 'H' 24-hour */
489 switch(fmt.length) {
490 case 1: case 2: out = val.H; outl = fmt.length; break;
491 default: throw 'bad hour format: ' + fmt;
492 } break;
493 case 77: /* 'M' minutes */
494 switch(fmt.length) {
495 case 1: case 2: out = val.M; outl = fmt.length; break;
496 default: throw 'bad minute format: ' + fmt;
497 } break;
498 case 115: /* 's' seconds */
499 if(fmt != 's' && fmt != 'ss' && fmt != '.0' && fmt != '.00' && fmt != '.000') throw 'bad second format: ' + fmt;
500 if(val.u === 0 && (fmt == "s" || fmt == "ss")) return pad0(val.S, fmt.length);
501 /*::if(!ss0) ss0 = 0; */
502 if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100;
503 else tt = ss0 === 1 ? 10 : 1;
504 ss = Math.round((tt)*(val.S + val.u));
505 if(ss >= 60*tt) ss = 0;
506 if(fmt === 's') return ss === 0 ? "0" : ""+ss/tt;
507 o = pad0(ss,2 + ss0);
508 if(fmt === 'ss') return o.substr(0,2);
509 return "." + o.substr(2,fmt.length-1);
510 case 90: /* 'Z' absolute time */
511 switch(fmt) {
512 case '[h]': case '[hh]': out = val.D*24+val.H; break;
513 case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
514 case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
515 default: throw 'bad abstime format: ' + fmt;
516 } outl = fmt.length === 3 ? 1 : 2; break;
517 case 101: /* 'e' era */
518 out = y; outl = 1; break;
519 }
520 var outstr = outl > 0 ? pad0(out, outl) : "";
521 return outstr;
522}
523/*jshint +W086 */
524function commaify(s/*:string*/)/*:string*/ {
525 var w = 3;
526 if(s.length <= w) return s;
527 var j = (s.length % w), o = s.substr(0,j);
528 for(; j!=s.length; j+=w) o+=(o.length > 0 ? "," : "") + s.substr(j,w);
529 return o;
530}
531var write_num/*:SSF_write_num*/ = (function make_write_num(){
532var pct1 = /%/g;
533function write_num_pct(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
534 var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
535 return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
536}
537function write_num_cm(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
538 var idx = fmt.length - 1;
539 while(fmt.charCodeAt(idx-1) === 44) --idx;
540 return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
541}
542function write_num_exp(fmt/*:string*/, val/*:number*/)/*:string*/{
543 var o/*:string*/;
544 var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
545 if(fmt.match(/^#+0.0E\+0$/)) {
546 if(val == 0) return "0.0E+0";
547 else if(val < 0) return "-" + write_num_exp(fmt, -val);
548 var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
549 var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
550 if(ee < 0) ee += period;
551 o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
552 if(o.indexOf("e") === -1) {
553 var fakee = Math.floor(Math.log(val)*Math.LOG10E);
554 if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
555 else o += "E+" + (fakee - ee);
556 while(o.substr(0,2) === "0.") {
557 o = o.charAt(0) + o.substr(2,period) + "." + o.substr(2+period);
558 o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0.");
559 }
560 o = o.replace(/\+-/,"-");
561 }
562 o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
563 } else o = val.toExponential(idx);
564 if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
565 if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
566 return o.replace("e","E");
567}
568var frac1 = /# (\?+)( ?)\/( ?)(\d+)/;
569function write_num_f1(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:string*/ {
570 var den = parseInt(r[4],10), rr = Math.round(aval * den), base = Math.floor(rr/den);
571 var myn = (rr - base*den), myd = den;
572 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));
573}
574function write_num_f2(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:string*/ {
575 return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
576}
577var dec1 = /^#*0*\.([0#]+)/;
578var closeparen = /\).*[0#]/;
579var phone = /\(###\) ###\\?-####/;
580function hashq(str/*:string*/)/*:string*/ {
581 var o = "", cc;
582 for(var i = 0; i != str.length; ++i) switch((cc=str.charCodeAt(i))) {
583 case 35: break;
584 case 63: o+= " "; break;
585 case 48: o+= "0"; break;
586 default: o+= String.fromCharCode(cc);
587 }
588 return o;
589}
590function rnd(val/*:number*/, d/*:number*/)/*:string*/ { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
591function dec(val/*:number*/, d/*:number*/)/*:number*/ {
592 var _frac = val - Math.floor(val), dd = Math.pow(10,d);
593 if (d < ('' + Math.round(_frac * dd)).length) return 0;
594 return Math.round(_frac * dd);
595}
596function carry(val/*:number*/, d/*:number*/)/*:number*/ {
597 if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
598 return 1;
599 }
600 return 0;
601}
602function flr(val/*:number*/)/*:string*/ {
603 if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0));
604 return ""+Math.floor(val);
605}
606function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
607 if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
608 var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
609 if(val >= 0) return write_num_flt('n', ffmt, val);
610 return '(' + write_num_flt('n', ffmt, -val) + ')';
611 }
612 if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm(type, fmt, val);
613 if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val);
614 if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val);
615 if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
616 var o;
617 var r/*:?Array<string>*/, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
618 if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length);
619 if(fmt.match(/^[#?]+$/)) {
620 o = pad0r(val,0); if(o === "0") o = "";
621 return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
622 }
623 if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign);
624 if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
625 if((r = fmt.match(dec1))) {
626 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); });
627 return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
628 }
629 fmt = fmt.replace(/^#+([0.])/, "$1");
630 if((r = fmt.match(/^(0*)\.(#*)$/))) {
631 return sign + rnd(aval, r[2].length).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
632 }
633 if((r = fmt.match(/^#{1,3},##0(\.?)$/))) return sign + commaify(pad0r(aval,0));
634 if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
635 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);
636 }
637 if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
638 if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
639 o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val));
640 ri = 0;
641 return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";}));
642 }
643 if(fmt.match(phone)) {
644 o = write_num_flt(type, "##########", val);
645 return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
646 }
647 var oa = "";
648 if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
649 ri = Math.min(/*::String(*/r[4]/*::)*/.length,7);
650 ff = frac(aval, Math.pow(10,ri)-1, false);
651 o = "" + sign;
652 oa = write_num("n", /*::String(*/r[1]/*::)*/, ff[1]);
653 if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
654 o += oa + /*::String(*/r[2]/*::)*/ + "/" + /*::String(*/r[3]/*::)*/;
655 oa = rpad_(ff[2],ri);
656 if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
657 o += oa;
658 return o;
659 }
660 if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
661 ri = Math.min(Math.max(r[1].length, r[4].length),7);
662 ff = frac(aval, Math.pow(10,ri)-1, true);
663 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));
664 }
665 if((r = fmt.match(/^[#0?]+$/))) {
666 o = pad0r(val, 0);
667 if(fmt.length <= o.length) return o;
668 return hashq(fmt.substr(0,fmt.length-o.length)) + o;
669 }
670 if((r = fmt.match(/^([#0?]+)\.([#0]+)$/))) {
671 o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
672 ri = o.indexOf(".");
673 var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
674 return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
675 }
676 if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
677 ri = dec(val, r[1].length);
678 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);
679 }
680 switch(fmt) {
681 case "###,##0.00": return write_num_flt(type, "#,##0.00", val);
682 case "###,###":
683 case "##,###":
684 case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : "";
685 case "###,###.00": return write_num_flt(type, "###,##0.00",val).replace(/^0\./,".");
686 case "#,###.00": return write_num_flt(type, "#,##0.00",val).replace(/^0\./,".");
687 default:
688 }
689 throw new Error("unsupported format |" + fmt + "|");
690}
691function write_num_cm2(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
692 var idx = fmt.length - 1;
693 while(fmt.charCodeAt(idx-1) === 44) --idx;
694 return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
695}
696function write_num_pct2(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/{
697 var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
698 return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
699}
700function write_num_exp2(fmt/*:string*/, val/*:number*/)/*:string*/{
701 var o/*:string*/;
702 var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
703 if(fmt.match(/^#+0.0E\+0$/)) {
704 if(val == 0) return "0.0E+0";
705 else if(val < 0) return "-" + write_num_exp2(fmt, -val);
706 var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
707 var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
708 if(ee < 0) ee += period;
709 o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
710 if(!o.match(/[Ee]/)) {
711 var fakee = Math.floor(Math.log(val)*Math.LOG10E);
712 if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
713 else o += "E+" + (fakee - ee);
714 o = o.replace(/\+-/,"-");
715 }
716 o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
717 } else o = val.toExponential(idx);
718 if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
719 if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
720 return o.replace("e","E");
721}
722function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
723 if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
724 var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
725 if(val >= 0) return write_num_int('n', ffmt, val);
726 return '(' + write_num_int('n', ffmt, -val) + ')';
727 }
728 if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm2(type, fmt, val);
729 if(fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val);
730 if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val);
731 if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
732 var o;
733 var r/*:?Array<string>*/, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
734 if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length);
735 if(fmt.match(/^[#?]+$/)) {
736 o = (""+val); if(val === 0) o = "";
737 return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
738 }
739 if((r = fmt.match(frac1))) return write_num_f2(r, aval, sign);
740 if(fmt.match(/^#+0+$/)) return sign + pad0(aval,fmt.length - fmt.indexOf("0"));
741 if((r = fmt.match(dec1))) {
742 /*:: if(!Array.isArray(r)) throw new Error("unreachable"); */
743 o = (""+val).replace(/^([^\.]+)$/,"$1."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1]));
744 o = o.replace(/\.(\d*)$/,function($$, $1) {
745 /*:: if(!Array.isArray(r)) throw new Error("unreachable"); */
746 return "." + $1 + fill("0", hashq(r[1]).length-$1.length); });
747 return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
748 }
749 fmt = fmt.replace(/^#+([0.])/, "$1");
750 if((r = fmt.match(/^(0*)\.(#*)$/))) {
751 return sign + (""+aval).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
752 }
753 if((r = fmt.match(/^#{1,3},##0(\.?)$/))) return sign + commaify((""+aval));
754 if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
755 return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify((""+val)) + "." + fill('0',r[1].length);
756 }
757 if((r = fmt.match(/^#,#*,#0/))) return write_num_int(type,fmt.replace(/^#,#*,/,""),val);
758 if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
759 o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val));
760 ri = 0;
761 return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";}));
762 }
763 if(fmt.match(phone)) {
764 o = write_num_int(type, "##########", val);
765 return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
766 }
767 var oa = "";
768 if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
769 ri = Math.min(/*::String(*/r[4]/*::)*/.length,7);
770 ff = frac(aval, Math.pow(10,ri)-1, false);
771 o = "" + sign;
772 oa = write_num("n", /*::String(*/r[1]/*::)*/, ff[1]);
773 if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
774 o += oa + /*::String(*/r[2]/*::)*/ + "/" + /*::String(*/r[3]/*::)*/;
775 oa = rpad_(ff[2],ri);
776 if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
777 o += oa;
778 return o;
779 }
780 if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
781 ri = Math.min(Math.max(r[1].length, r[4].length),7);
782 ff = frac(aval, Math.pow(10,ri)-1, true);
783 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));
784 }
785 if((r = fmt.match(/^[#0?]+$/))) {
786 o = "" + val;
787 if(fmt.length <= o.length) return o;
788 return hashq(fmt.substr(0,fmt.length-o.length)) + o;
789 }
790 if((r = fmt.match(/^([#0]+)\.([#0]+)$/))) {
791 o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
792 ri = o.indexOf(".");
793 var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
794 return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
795 }
796 if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
797 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);
798 }
799 switch(fmt) {
800 case "###,###":
801 case "##,###":
802 case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
803 default:
804 if(fmt.match(/\.[0#?]*$/)) return write_num_int(type, fmt.slice(0,fmt.lastIndexOf(".")), val) + hashq(fmt.slice(fmt.lastIndexOf(".")));
805 }
806 throw new Error("unsupported format |" + fmt + "|");
807}
808return function write_num(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string*/ {
809 return (val|0) === val ? write_num_int(type, fmt, val) : write_num_flt(type, fmt, val);
810};})();
811function split_fmt(fmt/*:string*/)/*:Array<string>*/ {
812 var out/*:Array<string>*/ = [];
813 var in_str = false/*, cc*/;
814 for(var i = 0, j = 0; i < fmt.length; ++i) switch((/*cc=*/fmt.charCodeAt(i))) {
815 case 34: /* '"' */
816 in_str = !in_str; break;
817 case 95: case 42: case 92: /* '_' '*' '\\' */
818 ++i; break;
819 case 59: /* ';' */
820 out[out.length] = fmt.substr(j,i-j);
821 j = i+1;
822 }
823 out[out.length] = fmt.substr(j);
824 if(in_str === true) throw new Error("Format |" + fmt + "| unterminated string ");
825 return out;
826}
827SSF._split = split_fmt;
828var abstime = /\[[HhMmSs\u0E0A\u0E19\u0E17]*\]/;
829function fmt_is_date(fmt/*:string*/)/*:boolean*/ {
830 var i = 0, /*cc = 0,*/ c = "", o = "";
831 while(i < fmt.length) {
832 switch((c = fmt.charAt(i))) {
833 case 'G': if(isgeneral(fmt, i)) i+= 6; i++; break;
834 case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;){/*empty*/} ++i; break;
835 case '\\': i+=2; break;
836 case '_': i+=2; break;
837 case '@': ++i; break;
838 case 'B': case 'b':
839 if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") return true;
840 /* falls through */
841 case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
842 /* falls through */
843 case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g': return true;
844 case 'A': case 'a': case '上':
845 if(fmt.substr(i, 3).toUpperCase() === "A/P") return true;
846 if(fmt.substr(i, 5).toUpperCase() === "AM/PM") return true;
847 if(fmt.substr(i, 5).toUpperCase() === "上午/下午") return true;
848 ++i; break;
849 case '[':
850 o = c;
851 while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
852 if(o.match(abstime)) return true;
853 break;
854 case '.':
855 /* falls through */
856 case '0': case '#':
857 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 */}
858 break;
859 case '?': while(fmt.charAt(++i) === c){/* empty */} break;
860 case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break;
861 case '(': case ')': ++i; break;
862 case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
863 while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){/* empty */} break;
864 case ' ': ++i; break;
865 default: ++i; break;
866 }
867 }
868 return false;
869}
870SSF.is_date = fmt_is_date;
871function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
872 var out = [], o = "", i = 0, c = "", lst='t', dt, j, cc;
873 var hr='H';
874 /* Tokenize */
875 while(i < fmt.length) {
876 switch((c = fmt.charAt(i))) {
877 case 'G': /* General */
878 if(!isgeneral(fmt, i)) throw new Error('unrecognized character ' + c + ' in ' +fmt);
879 out[out.length] = {t:'G', v:'General'}; i+=7; break;
880 case '"': /* Literal text */
881 for(o="";(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) o += String.fromCharCode(cc);
882 out[out.length] = {t:'t', v:o}; ++i; break;
883 case '\\': var w = fmt.charAt(++i), t = (w === "(" || w === ")") ? w : 't';
884 out[out.length] = {t:t, v:w}; ++i; break;
885 case '_': out[out.length] = {t:'t', v:" "}; i+=2; break;
886 case '@': /* Text Placeholder */
887 out[out.length] = {t:'T', v:v}; ++i; break;
888 case 'B': case 'b':
889 if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") {
890 if(dt==null) { dt=parse_date_code(v, opts, fmt.charAt(i+1) === "2"); if(dt==null) return ""; }
891 out[out.length] = {t:'X', v:fmt.substr(i,2)}; lst = c; i+=2; break;
892 }
893 /* falls through */
894 case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
895 c = c.toLowerCase();
896 /* falls through */
897 case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g':
898 if(v < 0) return "";
899 if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
900 o = c; while(++i < fmt.length && fmt.charAt(i).toLowerCase() === c) o+=c;
901 if(c === 'm' && lst.toLowerCase() === 'h') c = 'M';
902 if(c === 'h') c = hr;
903 out[out.length] = {t:c, v:o}; lst = c; break;
904 case 'A': case 'a': case '上':
905 var q={t:c, v:c};
906 if(dt==null) dt=parse_date_code(v, opts);
907 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;}
908 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'; }
909 else if(fmt.substr(i,5).toUpperCase() === "上午/下午") { if(dt!=null) q.v = dt.H >= 12 ? "下午" : "上午"; q.t = 'T'; i+=5; hr='h'; }
910 else { q.t = "t"; ++i; }
911 if(dt==null && q.t === 'T') return "";
912 out[out.length] = q; lst = c; break;
913 case '[':
914 o = c;
915 while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
916 if(o.slice(-1) !== ']') throw 'unterminated "[" block: |' + o + '|';
917 if(o.match(abstime)) {
918 if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
919 out[out.length] = {t:'Z', v:o.toLowerCase()};
920 lst = o.charAt(1);
921 } else if(o.indexOf("$") > -1) {
922 o = (o.match(/\$([^-\[\]]*)/)||[])[1]||"$";
923 if(!fmt_is_date(fmt)) out[out.length] = {t:'t',v:o};
924 }
925 break;
926 /* Numbers */
927 case '.':
928 if(dt != null) {
929 o = c; while(++i < fmt.length && (c=fmt.charAt(i)) === "0") o += c;
930 out[out.length] = {t:'s', v:o}; break;
931 }
932 /* falls through */
933 case '0': case '#':
934 o = c; while(++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1) o += c;
935 out[out.length] = {t:'n', v:o}; break;
936 case '?':
937 o = c; while(fmt.charAt(++i) === c) o+=c;
938 out[out.length] = {t:c, v:o}; lst = c; break;
939 case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break; // **
940 case '(': case ')': out[out.length] = {t:(flen===1?'t':c), v:c}; ++i; break;
941 case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
942 o = c; while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1) o+=fmt.charAt(i);
943 out[out.length] = {t:'D', v:o}; break;
944 case ' ': out[out.length] = {t:c, v:c}; ++i; break;
945 case '$': out[out.length] = {t:'t', v:'$'}; ++i; break;
946 default:
947 if(",$-+/():!^&'~{}<>=€acfijklopqrtuvwxzP".indexOf(c) === -1) throw new Error('unrecognized character ' + c + ' in ' + fmt);
948 out[out.length] = {t:'t', v:c}; ++i; break;
949 }
950 }
951
952 /* Scan for date/time parts */
953 var bt = 0, ss0 = 0, ssm;
954 for(i=out.length-1, lst='t'; i >= 0; --i) {
955 switch(out[i].t) {
956 case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
957 case 's':
958 if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
959 if(bt < 3) bt = 3;
960 /* falls through */
961 case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
962 case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
963 case 'X': /*if(out[i].v === "B2");*/
964 break;
965 case 'Z':
966 if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1;
967 if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2;
968 if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
969 }
970 }
971 /* time rounding depends on presence of minute / second / usec fields */
972 switch(bt) {
973 case 0: break;
974 case 1:
975 /*::if(!dt) break;*/
976 if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
977 if(dt.S >= 60) { dt.S = 0; ++dt.M; }
978 if(dt.M >= 60) { dt.M = 0; ++dt.H; }
979 break;
980 case 2:
981 /*::if(!dt) break;*/
982 if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
983 if(dt.S >= 60) { dt.S = 0; ++dt.M; }
984 break;
985 }
986
987 /* replace fields */
988 var nstr = "", jj;
989 for(i=0; i < out.length; ++i) {
990 switch(out[i].t) {
991 case 't': case 'T': case ' ': case 'D': break;
992 case 'X': out[i].v = ""; out[i].t = ";"; break;
993 case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'b': case 'Z':
994 /*::if(!dt) throw "unreachable"; */
995 out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
996 out[i].t = 't'; break;
997 case 'n': case '?':
998 jj = i+1;
999 while(out[jj] != null && (
1000 (c=out[jj].t) === "?" || c === "D" ||
1001 ((c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/')) ||
1002 (out[i].t === '(' && (c === ' ' || c === 'n' || c === ')')) ||
1003 (c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?'))
1004 )) {
1005 out[i].v += out[jj].v;
1006 out[jj] = {v:"", t:";"}; ++jj;
1007 }
1008 nstr += out[i].v;
1009 i = jj-1; break;
1010 case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
1011 }
1012 }
1013 var vv = "", myv, ostr;
1014 if(nstr.length > 0) {
1015 if(nstr.charCodeAt(0) == 40) /* '(' */ {
1016 myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v);
1017 ostr = write_num('n', nstr, myv);
1018 } else {
1019 myv = (v<0 && flen > 1 ? -v : v);
1020 ostr = write_num('n', nstr, myv);
1021 if(myv < 0 && out[0] && out[0].t == 't') {
1022 ostr = ostr.substr(1);
1023 out[0].v = "-" + out[0].v;
1024 }
1025 }
1026 jj=ostr.length-1;
1027 var decpt = out.length;
1028 for(i=0; i < out.length; ++i) if(out[i] != null && out[i].t != 't' && out[i].v.indexOf(".") > -1) { decpt = i; break; }
1029 var lasti=out.length;
1030 if(decpt === out.length && ostr.indexOf("E") === -1) {
1031 for(i=out.length-1; i>= 0;--i) {
1032 if(out[i] == null || 'n?'.indexOf(out[i].t) === -1) continue;
1033 if(jj>=out[i].v.length-1) { jj -= out[i].v.length; out[i].v = ostr.substr(jj+1, out[i].v.length); }
1034 else if(jj < 0) out[i].v = "";
1035 else { out[i].v = ostr.substr(0, jj+1); jj = -1; }
1036 out[i].t = 't';
1037 lasti = i;
1038 }
1039 if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
1040 }
1041 else if(decpt !== out.length && ostr.indexOf("E") === -1) {
1042 jj = ostr.indexOf(".")-1;
1043 for(i=decpt; i>= 0; --i) {
1044 if(out[i] == null || 'n?'.indexOf(out[i].t) === -1) continue;
1045 j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1;
1046 vv = out[i].v.substr(j+1);
1047 for(; j>=0; --j) {
1048 if(jj>=0 && (out[i].v.charAt(j) === "0" || out[i].v.charAt(j) === "#")) vv = ostr.charAt(jj--) + vv;
1049 }
1050 out[i].v = vv;
1051 out[i].t = 't';
1052 lasti = i;
1053 }
1054 if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
1055 jj = ostr.indexOf(".")+1;
1056 for(i=decpt; i<out.length; ++i) {
1057 if(out[i] == null || ('n?('.indexOf(out[i].t) === -1 && i !== decpt)) continue;
1058 j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0;
1059 vv = out[i].v.substr(0,j);
1060 for(; j<out[i].v.length; ++j) {
1061 if(jj<ostr.length) vv += ostr.charAt(jj++);
1062 }
1063 out[i].v = vv;
1064 out[i].t = 't';
1065 lasti = i;
1066 }
1067 }
1068 }
1069 for(i=0; i<out.length; ++i) if(out[i] != null && 'n?'.indexOf(out[i].t)>-1) {
1070 myv = (flen >1 && v < 0 && i>0 && out[i-1].v === "-" ? -v:v);
1071 out[i].v = write_num(out[i].t, out[i].v, myv);
1072 out[i].t = 't';
1073 }
1074 var retval = "";
1075 for(i=0; i !== out.length; ++i) if(out[i] != null) retval += out[i].v;
1076 return retval;
1077}
1078SSF._eval = eval_fmt;
1079var cfregex = /\[[=<>]/;
1080var cfregex2 = /\[(=|>[=]?|<[>=]?)(-?\d+(?:\.\d*)?)\]/;
1081function chkcond(v, rr) {
1082 if(rr == null) return false;
1083 var thresh = parseFloat(rr[2]);
1084 switch(rr[1]) {
1085 case "=": if(v == thresh) return true; break;
1086 case ">": if(v > thresh) return true; break;
1087 case "<": if(v < thresh) return true; break;
1088 case "<>": if(v != thresh) return true; break;
1089 case ">=": if(v >= thresh) return true; break;
1090 case "<=": if(v <= thresh) return true; break;
1091 }
1092 return false;
1093}
1094function choose_fmt(f/*:string*/, v/*:any*/) {
1095 var fmt = split_fmt(f);
1096 var l = fmt.length, lat = fmt[l-1].indexOf("@");
1097 if(l<4 && lat>-1) --l;
1098 if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
1099 if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
1100 switch(fmt.length) {
1101 case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
1102 case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
1103 case 3: fmt = lat>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
1104 case 4: break;
1105 }
1106 var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2];
1107 if(fmt[0].indexOf("[") === -1 && fmt[1].indexOf("[") === -1) return [l, ff];
1108 if(fmt[0].match(cfregex) != null || fmt[1].match(cfregex) != null) {
1109 var m1 = fmt[0].match(cfregex2);
1110 var m2 = fmt[1].match(cfregex2);
1111 return chkcond(v, m1) ? [l, fmt[0]] : chkcond(v, m2) ? [l, fmt[1]] : [l, fmt[m1 != null && m2 != null ? 2 : 1]];
1112 }
1113 return [l, ff];
1114}
1115function format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
1116 if(o == null) o = {};
1117 var sfmt = "";
1118 switch(typeof fmt) {
1119 case "string":
1120 if(fmt == "m/d/yy" && o.dateNF) sfmt = o.dateNF;
1121 else sfmt = fmt;
1122 break;
1123 case "number":
1124 if(fmt == 14 && o.dateNF) sfmt = o.dateNF;
1125 else sfmt = (o.table != null ? (o.table/*:any*/) : table_fmt)[fmt];
1126 if(sfmt == null) sfmt = (o.table && o.table[default_map[fmt]]) || table_fmt[default_map[fmt]];
1127 if(sfmt == null) sfmt = default_str[fmt] || "General";
1128 break;
1129 }
1130 if(isgeneral(sfmt,0)) return general_fmt(v, o);
1131 if(v instanceof Date) v = datenum_local(v, o.date1904);
1132 var f = choose_fmt(sfmt, v);
1133 if(isgeneral(f[1])) return general_fmt(v, o);
1134 if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
1135 else if(v === "" || v == null) return "";
1136 return eval_fmt(f[1], v, o, f[0]);
1137}
1138function load_entry(fmt/*:string*/, idx/*:?number*/)/*:number*/ {
1139 if(typeof idx != 'number') {
1140 idx = +idx || -1;
1141/*::if(typeof idx != 'number') return 0x188; */
1142 for(var i = 0; i < 0x0188; ++i) {
1143/*::if(typeof idx != 'number') return 0x188; */
1144 if(table_fmt[i] == undefined) { if(idx < 0) idx = i; continue; }
1145 if(table_fmt[i] == fmt) { idx = i; break; }
1146 }
1147/*::if(typeof idx != 'number') return 0x188; */
1148 if(idx < 0) idx = 0x187;
1149 }
1150/*::if(typeof idx != 'number') return 0x188; */
1151 table_fmt[idx] = fmt;
1152 return idx;
1153}
1154SSF.load = load_entry;
1155SSF._table = table_fmt;
1156SSF.get_table = function get_table()/*:SSFTable*/ { return table_fmt; };
1157SSF.load_table = function load_table(tbl/*:SSFTable*/)/*:void*/ {
1158 for(var i=0; i!=0x0188; ++i)
1159 if(tbl[i] !== undefined) load_entry(tbl[i], i);
1160};
1161SSF.init_table = init_table;
1162SSF.format = format;
1163};
1164make_ssf(SSF);
1165/* map from xlml named formats to SSF TODO: localize */
1166var XLMLFormatMap/*{[string]:string}*/ = ({
1167 "General Number": "General",
1168 "General Date": SSF._table[22],
1169 "Long Date": "dddd, mmmm dd, yyyy",
1170 "Medium Date": SSF._table[15],
1171 "Short Date": SSF._table[14],
1172 "Long Time": SSF._table[19],
1173 "Medium Time": SSF._table[18],
1174 "Short Time": SSF._table[20],
1175 "Currency": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
1176 "Fixed": SSF._table[2],
1177 "Standard": SSF._table[4],
1178 "Percent": SSF._table[10],
1179 "Scientific": SSF._table[11],
1180 "Yes/No": '"Yes";"Yes";"No";@',
1181 "True/False": '"True";"True";"False";@',
1182 "On/Off": '"Yes";"Yes";"No";@'
1183}/*:any*/);
1184
1185var SSFImplicit/*{[number]:string}*/ = ({
1186 "5": '"$"#,##0_);\\("$"#,##0\\)',
1187 "6": '"$"#,##0_);[Red]\\("$"#,##0\\)',
1188 "7": '"$"#,##0.00_);\\("$"#,##0.00\\)',
1189 "8": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
1190 "23": 'General', "24": 'General', "25": 'General', "26": 'General',
1191 "27": 'm/d/yy', "28": 'm/d/yy', "29": 'm/d/yy', "30": 'm/d/yy', "31": 'm/d/yy',
1192 "32": 'h:mm:ss', "33": 'h:mm:ss', "34": 'h:mm:ss', "35": 'h:mm:ss',
1193 "36": 'm/d/yy',
1194 "41": '_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)',
1195 "42": '_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)',
1196 "43": '_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)',
1197 "44": '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)',
1198 "50": 'm/d/yy', "51": 'm/d/yy', "52": 'm/d/yy', "53": 'm/d/yy', "54": 'm/d/yy',
1199 "55": 'm/d/yy', "56": 'm/d/yy', "57": 'm/d/yy', "58": 'm/d/yy',
1200 "59": '0',
1201 "60": '0.00',
1202 "61": '#,##0',
1203 "62": '#,##0.00',
1204 "63": '"$"#,##0_);\\("$"#,##0\\)',
1205 "64": '"$"#,##0_);[Red]\\("$"#,##0\\)',
1206 "65": '"$"#,##0.00_);\\("$"#,##0.00\\)',
1207 "66": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
1208 "67": '0%',
1209 "68": '0.00%',
1210 "69": '# ?/?',
1211 "70": '# ??/??',
1212 "71": 'm/d/yy',
1213 "72": 'm/d/yy',
1214 "73": 'd-mmm-yy',
1215 "74": 'd-mmm',
1216 "75": 'mmm-yy',
1217 "76": 'h:mm',
1218 "77": 'h:mm:ss',
1219 "78": 'm/d/yy h:mm',
1220 "79": 'mm:ss',
1221 "80": '[h]:mm:ss',
1222 "81": 'mmss.0'
1223}/*:any*/);
1224
1225/* dateNF parse TODO: move to SSF */
1226var dateNFregex = /[dD]+|[mM]+|[yYeE]+|[Hh]+|[Ss]+/g;
1227function dateNF_regex(dateNF/*:string|number*/)/*:RegExp*/ {
1228 var fmt = typeof dateNF == "number" ? SSF._table[dateNF] : dateNF;
1229 fmt = fmt.replace(dateNFregex, "(\\d+)");
1230 return new RegExp("^" + fmt + "$");
1231}
1232function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/*:string*/ {
1233 var Y = -1, m = -1, d = -1, H = -1, M = -1, S = -1;
1234 (dateNF.match(dateNFregex)||[]).forEach(function(n, i) {
1235 var v = parseInt(match[i+1], 10);
1236 switch(n.toLowerCase().charAt(0)) {
1237 case 'y': Y = v; break; case 'd': d = v; break;
1238 case 'h': H = v; break; case 's': S = v; break;
1239 case 'm': if(H >= 0) M = v; else m = v; break;
1240 }
1241 });
1242 if(S >= 0 && M == -1 && m >= 0) { M = m; m = -1; }
1243 var datestr = (("" + (Y>=0?Y: new Date().getFullYear())).slice(-4) + "-" + ("00" + (m>=1?m:1)).slice(-2) + "-" + ("00" + (d>=1?d:1)).slice(-2));
1244 if(datestr.length == 7) datestr = "0" + datestr;
1245 if(datestr.length == 8) datestr = "20" + datestr;
1246 var timestr = (("00" + (H>=0?H:0)).slice(-2) + ":" + ("00" + (M>=0?M:0)).slice(-2) + ":" + ("00" + (S>=0?S:0)).slice(-2));
1247 if(H == -1 && M == -1 && S == -1) return datestr;
1248 if(Y == -1 && m == -1 && d == -1) return timestr;
1249 return datestr + "T" + timestr;
1250}
1251
1252var DO_NOT_EXPORT_CFB = true;
1253/*::
1254declare var Base64:any;
1255declare var ReadShift:any;
1256declare var CheckField:any;
1257declare var prep_blob:any;
1258declare var __readUInt32LE:any;
1259declare var __readInt32LE:any;
1260declare var __toBuffer:any;
1261declare var __utf16le:any;
1262declare var bconcat:any;
1263declare var s2a:any;
1264declare var chr0:any;
1265declare var chr1:any;
1266declare var has_buf:boolean;
1267declare var new_buf:any;
1268declare var new_raw_buf:any;
1269declare var new_unsafe_buf:any;
1270*/
1271/* cfb.js (C) 2013-present SheetJS -- http://sheetjs.com */
1272/* vim: set ts=2: */
1273/*jshint eqnull:true */
1274/*exported CFB */
1275/*global Uint8Array:false, Uint16Array:false */
1276
1277/*::
1278declare var DO_NOT_EXPORT_CFB:?boolean;
1279type SectorEntry = {
1280 name?:string;
1281 nodes?:Array<number>;
1282 data:RawBytes;
1283};
1284type SectorList = {
1285 [k:string|number]:SectorEntry;
1286 name:?string;
1287 fat_addrs:Array<number>;
1288 ssz:number;
1289}
1290type CFBFiles = {[n:string]:CFBEntry};
1291*/
1292/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
1293/* vim: set ts=2: */
1294/*exported CRC32 */
1295var CRC32;
1296(function (factory) {
1297 /*jshint ignore:start */
1298 /*eslint-disable */
1299 factory(CRC32 = {});
1300 /*eslint-enable */
1301 /*jshint ignore:end */
1302}(function(CRC32) {
1303CRC32.version = '1.2.0';
1304/* see perf/crc32table.js */
1305/*global Int32Array */
1306function signed_crc_table()/*:any*/ {
1307 var c = 0, table/*:Array<number>*/ = new Array(256);
1308
1309 for(var n =0; n != 256; ++n){
1310 c = n;
1311 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1312 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1313 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1314 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1315 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1316 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1317 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1318 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
1319 table[n] = c;
1320 }
1321
1322 return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table;
1323}
1324
1325var T = signed_crc_table();
1326function crc32_bstr(bstr/*:string*/, seed/*:number*/)/*:number*/ {
1327 var C = seed ^ -1, L = bstr.length - 1;
1328 for(var i = 0; i < L;) {
1329 C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
1330 C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
1331 }
1332 if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF];
1333 return C ^ -1;
1334}
1335
1336function crc32_buf(buf/*:Uint8Array|Array<number>*/, seed/*:number*/)/*:number*/ {
1337 if(buf.length > 10000) return crc32_buf_8(buf, seed);
1338 var C = seed ^ -1, L = buf.length - 3;
1339 for(var i = 0; i < L;) {
1340 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1341 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1342 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1343 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1344 }
1345 while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1346 return C ^ -1;
1347}
1348
1349function crc32_buf_8(buf/*:Uint8Array|Array<number>*/, seed/*:number*/)/*:number*/ {
1350 var C = seed ^ -1, L = buf.length - 7;
1351 for(var i = 0; i < L;) {
1352 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1353 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1354 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1355 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1356 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1357 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1358 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1359 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1360 }
1361 while(i < L+7) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
1362 return C ^ -1;
1363}
1364
1365function crc32_str(str/*:string*/, seed/*:number*/)/*:number*/ {
1366 var C = seed ^ -1;
1367 for(var i = 0, L=str.length, c, d; i < L;) {
1368 c = str.charCodeAt(i++);
1369 if(c < 0x80) {
1370 C = (C>>>8) ^ T[(C ^ c)&0xFF];
1371 } else if(c < 0x800) {
1372 C = (C>>>8) ^ T[(C ^ (192|((c>>6)&31)))&0xFF];
1373 C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF];
1374 } else if(c >= 0xD800 && c < 0xE000) {
1375 c = (c&1023)+64; d = str.charCodeAt(i++)&1023;
1376 C = (C>>>8) ^ T[(C ^ (240|((c>>8)&7)))&0xFF];
1377 C = (C>>>8) ^ T[(C ^ (128|((c>>2)&63)))&0xFF];
1378 C = (C>>>8) ^ T[(C ^ (128|((d>>6)&15)|((c&3)<<4)))&0xFF];
1379 C = (C>>>8) ^ T[(C ^ (128|(d&63)))&0xFF];
1380 } else {
1381 C = (C>>>8) ^ T[(C ^ (224|((c>>12)&15)))&0xFF];
1382 C = (C>>>8) ^ T[(C ^ (128|((c>>6)&63)))&0xFF];
1383 C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF];
1384 }
1385 }
1386 return C ^ -1;
1387}
1388CRC32.table = T;
1389CRC32.bstr = crc32_bstr;
1390CRC32.buf = crc32_buf;
1391CRC32.str = crc32_str;
1392}));
1393/* [MS-CFB] v20171201 */
1394var CFB = (function _CFB(){
1395var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
1396exports.version = '1.1.4';
1397/* [MS-CFB] 2.6.4 */
1398function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
1399 var L = l.split("/"), R = r.split("/");
1400 for(var i = 0, c = 0, Z = Math.min(L.length, R.length); i < Z; ++i) {
1401 if((c = L[i].length - R[i].length)) return c;
1402 if(L[i] != R[i]) return L[i] < R[i] ? -1 : 1;
1403 }
1404 return L.length - R.length;
1405}
1406function dirname(p/*:string*/)/*:string*/ {
1407 if(p.charAt(p.length - 1) == "/") return (p.slice(0,-1).indexOf("/") === -1) ? p : dirname(p.slice(0, -1));
1408 var c = p.lastIndexOf("/");
1409 return (c === -1) ? p : p.slice(0, c+1);
1410}
1411
1412function filename(p/*:string*/)/*:string*/ {
1413 if(p.charAt(p.length - 1) == "/") return filename(p.slice(0, -1));
1414 var c = p.lastIndexOf("/");
1415 return (c === -1) ? p : p.slice(c+1);
1416}
1417/* -------------------------------------------------------------------------- */
1418/* DOS Date format:
1419 high|YYYYYYYm.mmmddddd.HHHHHMMM.MMMSSSSS|low
1420 add 1980 to stored year
1421 stored second should be doubled
1422*/
1423
1424/* write JS date to buf as a DOS date */
1425function write_dos_date(buf/*:CFBlob*/, date/*:Date|string*/) {
1426 if(typeof date === "string") date = new Date(date);
1427 var hms/*:number*/ = date.getHours();
1428 hms = hms << 6 | date.getMinutes();
1429 hms = hms << 5 | (date.getSeconds()>>>1);
1430 buf.write_shift(2, hms);
1431 var ymd/*:number*/ = (date.getFullYear() - 1980);
1432 ymd = ymd << 4 | (date.getMonth()+1);
1433 ymd = ymd << 5 | date.getDate();
1434 buf.write_shift(2, ymd);
1435}
1436
1437/* read four bytes from buf and interpret as a DOS date */
1438function parse_dos_date(buf/*:CFBlob*/)/*:Date*/ {
1439 var hms = buf.read_shift(2) & 0xFFFF;
1440 var ymd = buf.read_shift(2) & 0xFFFF;
1441 var val = new Date();
1442 var d = ymd & 0x1F; ymd >>>= 5;
1443 var m = ymd & 0x0F; ymd >>>= 4;
1444 val.setMilliseconds(0);
1445 val.setFullYear(ymd + 1980);
1446 val.setMonth(m-1);
1447 val.setDate(d);
1448 var S = hms & 0x1F; hms >>>= 5;
1449 var M = hms & 0x3F; hms >>>= 6;
1450 val.setHours(hms);
1451 val.setMinutes(M);
1452 val.setSeconds(S<<1);
1453 return val;
1454}
1455function parse_extra_field(blob/*:CFBlob*/)/*:any*/ {
1456 prep_blob(blob, 0);
1457 var o = /*::(*/{}/*:: :any)*/;
1458 var flags = 0;
1459 while(blob.l <= blob.length - 4) {
1460 var type = blob.read_shift(2);
1461 var sz = blob.read_shift(2), tgt = blob.l + sz;
1462 var p = {};
1463 switch(type) {
1464 /* UNIX-style Timestamps */
1465 case 0x5455: {
1466 flags = blob.read_shift(1);
1467 if(flags & 1) p.mtime = blob.read_shift(4);
1468 /* for some reason, CD flag corresponds to LFH */
1469 if(sz > 5) {
1470 if(flags & 2) p.atime = blob.read_shift(4);
1471 if(flags & 4) p.ctime = blob.read_shift(4);
1472 }
1473 if(p.mtime) p.mt = new Date(p.mtime*1000);
1474 }
1475 break;
1476 }
1477 blob.l = tgt;
1478 o[type] = p;
1479 }
1480 return o;
1481}
1482var fs/*:: = require('fs'); */;
1483function get_fs() { return fs || (fs = {}); }
1484function parse(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/ {
1485if(file[0] == 0x50 && file[1] == 0x4b) return parse_zip(file, options);
1486if(file.length < 512) throw new Error("CFB file size " + file.length + " < 512");
1487var mver = 3;
1488var ssz = 512;
1489var nmfs = 0; // number of mini FAT sectors
1490var difat_sec_cnt = 0;
1491var dir_start = 0;
1492var minifat_start = 0;
1493var difat_start = 0;
1494
1495var fat_addrs/*:Array<number>*/ = []; // locations of FAT sectors
1496
1497/* [MS-CFB] 2.2 Compound File Header */
1498var blob/*:CFBlob*/ = /*::(*/file.slice(0,512)/*:: :any)*/;
1499prep_blob(blob, 0);
1500
1501/* major version */
1502var mv = check_get_mver(blob);
1503mver = mv[0];
1504switch(mver) {
1505 case 3: ssz = 512; break; case 4: ssz = 4096; break;
1506 case 0: if(mv[1] == 0) return parse_zip(file, options);
1507 /* falls through */
1508 default: throw new Error("Major Version: Expected 3 or 4 saw " + mver);
1509}
1510
1511/* reprocess header */
1512if(ssz !== 512) { blob = /*::(*/file.slice(0,ssz)/*:: :any)*/; prep_blob(blob, 28 /* blob.l */); }
1513/* Save header for final object */
1514var header/*:RawBytes*/ = file.slice(0,ssz);
1515
1516check_shifts(blob, mver);
1517
1518// Number of Directory Sectors
1519var dir_cnt/*:number*/ = blob.read_shift(4, 'i');
1520if(mver === 3 && dir_cnt !== 0) throw new Error('# Directory Sectors: Expected 0 saw ' + dir_cnt);
1521
1522// Number of FAT Sectors
1523blob.l += 4;
1524
1525// First Directory Sector Location
1526dir_start = blob.read_shift(4, 'i');
1527
1528// Transaction Signature
1529blob.l += 4;
1530
1531// Mini Stream Cutoff Size
1532blob.chk('00100000', 'Mini Stream Cutoff Size: ');
1533
1534// First Mini FAT Sector Location
1535minifat_start = blob.read_shift(4, 'i');
1536
1537// Number of Mini FAT Sectors
1538nmfs = blob.read_shift(4, 'i');
1539
1540// First DIFAT sector location
1541difat_start = blob.read_shift(4, 'i');
1542
1543// Number of DIFAT Sectors
1544difat_sec_cnt = blob.read_shift(4, 'i');
1545
1546// Grab FAT Sector Locations
1547for(var q = -1, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */
1548 q = blob.read_shift(4, 'i');
1549 if(q<0) break;
1550 fat_addrs[j] = q;
1551}
1552
1553/** Break the file up into sectors */
1554var sectors/*:Array<RawBytes>*/ = sectorify(file, ssz);
1555
1556sleuth_fat(difat_start, difat_sec_cnt, sectors, ssz, fat_addrs);
1557
1558/** Chains */
1559var sector_list/*:SectorList*/ = make_sector_list(sectors, dir_start, fat_addrs, ssz);
1560
1561sector_list[dir_start].name = "!Directory";
1562if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
1563sector_list[fat_addrs[0]].name = "!FAT";
1564sector_list.fat_addrs = fat_addrs;
1565sector_list.ssz = ssz;
1566
1567/* [MS-CFB] 2.6.1 Compound File Directory Entry */
1568var files/*:CFBFiles*/ = {}, Paths/*:Array<string>*/ = [], FileIndex/*:CFBFileIndex*/ = [], FullPaths/*:Array<string>*/ = [];
1569read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex, minifat_start);
1570
1571build_full_paths(FileIndex, FullPaths, Paths);
1572Paths.shift();
1573
1574var o = {
1575 FileIndex: FileIndex,
1576 FullPaths: FullPaths
1577};
1578
1579// $FlowIgnore
1580if(options && options.raw) o.raw = {header: header, sectors: sectors};
1581return o;
1582} // parse
1583
1584/* [MS-CFB] 2.2 Compound File Header -- read up to major version */
1585function check_get_mver(blob/*:CFBlob*/)/*:[number, number]*/ {
1586 if(blob[blob.l] == 0x50 && blob[blob.l + 1] == 0x4b) return [0, 0];
1587 // header signature 8
1588 blob.chk(HEADER_SIGNATURE, 'Header Signature: ');
1589
1590 // clsid 16
1591 //blob.chk(HEADER_CLSID, 'CLSID: ');
1592 blob.l += 16;
1593
1594 // minor version 2
1595 var mver/*:number*/ = blob.read_shift(2, 'u');
1596
1597 return [blob.read_shift(2,'u'), mver];
1598}
1599function check_shifts(blob/*:CFBlob*/, mver/*:number*/)/*:void*/ {
1600 var shift = 0x09;
1601
1602 // Byte Order
1603 //blob.chk('feff', 'Byte Order: '); // note: some writers put 0xffff
1604 blob.l += 2;
1605
1606 // Sector Shift
1607 switch((shift = blob.read_shift(2))) {
1608 case 0x09: if(mver != 3) throw new Error('Sector Shift: Expected 9 saw ' + shift); break;
1609 case 0x0c: if(mver != 4) throw new Error('Sector Shift: Expected 12 saw ' + shift); break;
1610 default: throw new Error('Sector Shift: Expected 9 or 12 saw ' + shift);
1611 }
1612
1613 // Mini Sector Shift
1614 blob.chk('0600', 'Mini Sector Shift: ');
1615
1616 // Reserved
1617 blob.chk('000000000000', 'Reserved: ');
1618}
1619
1620/** Break the file up into sectors */
1621function sectorify(file/*:RawBytes*/, ssz/*:number*/)/*:Array<RawBytes>*/ {
1622 var nsectors = Math.ceil(file.length/ssz)-1;
1623 var sectors/*:Array<RawBytes>*/ = [];
1624 for(var i=1; i < nsectors; ++i) sectors[i-1] = file.slice(i*ssz,(i+1)*ssz);
1625 sectors[nsectors-1] = file.slice(nsectors*ssz);
1626 return sectors;
1627}
1628
1629/* [MS-CFB] 2.6.4 Red-Black Tree */
1630function build_full_paths(FI/*:CFBFileIndex*/, FP/*:Array<string>*/, Paths/*:Array<string>*/)/*:void*/ {
1631 var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length;
1632 var dad/*:Array<number>*/ = [], q/*:Array<number>*/ = [];
1633
1634 for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; }
1635
1636 for(; j < q.length; ++j) {
1637 i = q[j];
1638 L = FI[i].L; R = FI[i].R; C = FI[i].C;
1639 if(dad[i] === i) {
1640 if(L !== -1 /*NOSTREAM*/ && dad[L] !== L) dad[i] = dad[L];
1641 if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
1642 }
1643 if(C !== -1 /*NOSTREAM*/) dad[C] = i;
1644 if(L !== -1 && i != dad[i]) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
1645 if(R !== -1 && i != dad[i]) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
1646 }
1647 for(i=1; i < pl; ++i) if(dad[i] === i) {
1648 if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
1649 else if(L !== -1 && dad[L] !== L) dad[i] = dad[L];
1650 }
1651
1652 for(i=1; i < pl; ++i) {
1653 if(FI[i].type === 0 /* unknown */) continue;
1654 j = i;
1655 if(j != dad[j]) do {
1656 j = dad[j];
1657 FP[i] = FP[j] + "/" + FP[i];
1658 } while (j !== 0 && -1 !== dad[j] && j != dad[j]);
1659 dad[i] = -1;
1660 }
1661
1662 FP[0] += "/";
1663 for(i=1; i < pl; ++i) {
1664 if(FI[i].type !== 2 /* stream */) FP[i] += "/";
1665 }
1666}
1667
1668function get_mfat_entry(entry/*:CFBEntry*/, payload/*:RawBytes*/, mini/*:?RawBytes*/)/*:CFBlob*/ {
1669 var start = entry.start, size = entry.size;
1670 //return (payload.slice(start*MSSZ, start*MSSZ + size)/*:any*/);
1671 var o = [];
1672 var idx = start;
1673 while(mini && size > 0 && idx >= 0) {
1674 o.push(payload.slice(idx * MSSZ, idx * MSSZ + MSSZ));
1675 size -= MSSZ;
1676 idx = __readInt32LE(mini, idx * 4);
1677 }
1678 if(o.length === 0) return (new_buf(0)/*:any*/);
1679 return (bconcat(o).slice(0, entry.size)/*:any*/);
1680}
1681
1682/** Chase down the rest of the DIFAT chain to build a comprehensive list
1683 DIFAT chains by storing the next sector number as the last 32 bits */
1684function sleuth_fat(idx/*:number*/, cnt/*:number*/, sectors/*:Array<RawBytes>*/, ssz/*:number*/, fat_addrs)/*:void*/ {
1685 var q/*:number*/ = ENDOFCHAIN;
1686 if(idx === ENDOFCHAIN) {
1687 if(cnt !== 0) throw new Error("DIFAT chain shorter than expected");
1688 } else if(idx !== -1 /*FREESECT*/) {
1689 var sector = sectors[idx], m = (ssz>>>2)-1;
1690 if(!sector) return;
1691 for(var i = 0; i < m; ++i) {
1692 if((q = __readInt32LE(sector,i*4)) === ENDOFCHAIN) break;
1693 fat_addrs.push(q);
1694 }
1695 sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs);
1696 }
1697}
1698
1699/** Follow the linked list of sectors for a given starting point */
1700function get_sector_list(sectors/*:Array<RawBytes>*/, start/*:number*/, fat_addrs/*:Array<number>*/, ssz/*:number*/, chkd/*:?Array<boolean>*/)/*:SectorEntry*/ {
1701 var buf/*:Array<number>*/ = [], buf_chain/*:Array<any>*/ = [];
1702 if(!chkd) chkd = [];
1703 var modulus = ssz - 1, j = 0, jj = 0;
1704 for(j=start; j>=0;) {
1705 chkd[j] = true;
1706 buf[buf.length] = j;
1707 buf_chain.push(sectors[j]);
1708 var addr = fat_addrs[Math.floor(j*4/ssz)];
1709 jj = ((j*4) & modulus);
1710 if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz);
1711 if(!sectors[addr]) break;
1712 j = __readInt32LE(sectors[addr], jj);
1713 }
1714 return {nodes: buf, data:__toBuffer([buf_chain])};
1715}
1716
1717/** Chase down the sector linked lists */
1718function make_sector_list(sectors/*:Array<RawBytes>*/, dir_start/*:number*/, fat_addrs/*:Array<number>*/, ssz/*:number*/)/*:SectorList*/ {
1719 var sl = sectors.length, sector_list/*:SectorList*/ = ([]/*:any*/);
1720 var chkd/*:Array<boolean>*/ = [], buf/*:Array<number>*/ = [], buf_chain/*:Array<RawBytes>*/ = [];
1721 var modulus = ssz - 1, i=0, j=0, k=0, jj=0;
1722 for(i=0; i < sl; ++i) {
1723 buf = ([]/*:Array<number>*/);
1724 k = (i + dir_start); if(k >= sl) k-=sl;
1725 if(chkd[k]) continue;
1726 buf_chain = [];
1727 var seen = [];
1728 for(j=k; j>=0;) {
1729 seen[j] = true;
1730 chkd[j] = true;
1731 buf[buf.length] = j;
1732 buf_chain.push(sectors[j]);
1733 var addr/*:number*/ = fat_addrs[Math.floor(j*4/ssz)];
1734 jj = ((j*4) & modulus);
1735 if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz);
1736 if(!sectors[addr]) break;
1737 j = __readInt32LE(sectors[addr], jj);
1738 if(seen[j]) break;
1739 }
1740 sector_list[k] = ({nodes: buf, data:__toBuffer([buf_chain])}/*:SectorEntry*/);
1741 }
1742 return sector_list;
1743}
1744
1745/* [MS-CFB] 2.6.1 Compound File Directory Entry */
1746function read_directory(dir_start/*:number*/, sector_list/*:SectorList*/, sectors/*:Array<RawBytes>*/, Paths/*:Array<string>*/, nmfs, files, FileIndex, mini) {
1747 var minifat_store = 0, pl = (Paths.length?2:0);
1748 var sector = sector_list[dir_start].data;
1749 var i = 0, namelen = 0, name;
1750 for(; i < sector.length; i+= 128) {
1751 var blob/*:CFBlob*/ = /*::(*/sector.slice(i, i+128)/*:: :any)*/;
1752 prep_blob(blob, 64);
1753 namelen = blob.read_shift(2);
1754 name = __utf16le(blob,0,namelen-pl);
1755 Paths.push(name);
1756 var o/*:CFBEntry*/ = ({
1757 name: name,
1758 type: blob.read_shift(1),
1759 color: blob.read_shift(1),
1760 L: blob.read_shift(4, 'i'),
1761 R: blob.read_shift(4, 'i'),
1762 C: blob.read_shift(4, 'i'),
1763 clsid: blob.read_shift(16),
1764 state: blob.read_shift(4, 'i'),
1765 start: 0,
1766 size: 0
1767 });
1768 var ctime/*:number*/ = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2);
1769 if(ctime !== 0) o.ct = read_date(blob, blob.l-8);
1770 var mtime/*:number*/ = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2);
1771 if(mtime !== 0) o.mt = read_date(blob, blob.l-8);
1772 o.start = blob.read_shift(4, 'i');
1773 o.size = blob.read_shift(4, 'i');
1774 if(o.size < 0 && o.start < 0) { o.size = o.type = 0; o.start = ENDOFCHAIN; o.name = ""; }
1775 if(o.type === 5) { /* root */
1776 minifat_store = o.start;
1777 if(nmfs > 0 && minifat_store !== ENDOFCHAIN) sector_list[minifat_store].name = "!StreamData";
1778 /*minifat_size = o.size;*/
1779 } else if(o.size >= 4096 /* MSCSZ */) {
1780 o.storage = 'fat';
1781 if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz);
1782 sector_list[o.start].name = o.name;
1783 o.content = (sector_list[o.start].data.slice(0,o.size)/*:any*/);
1784 } else {
1785 o.storage = 'minifat';
1786 if(o.size < 0) o.size = 0;
1787 else if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) {
1788 o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini]||{}).data);
1789 }
1790 }
1791 if(o.content) prep_blob(o.content, 0);
1792 files[name] = o;
1793 FileIndex.push(o);
1794 }
1795}
1796
1797function read_date(blob/*:RawBytes|CFBlob*/, offset/*:number*/)/*:Date*/ {
1798 return new Date(( ( (__readUInt32LE(blob,offset+4)/1e7)*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7 ) - 11644473600)*1000);
1799}
1800
1801function read_file(filename/*:string*/, options/*:CFBReadOpts*/) {
1802 get_fs();
1803 return parse(fs.readFileSync(filename), options);
1804}
1805
1806function read(blob/*:RawBytes|string*/, options/*:CFBReadOpts*/) {
1807 switch(options && options.type || "base64") {
1808 case "file": /*:: if(typeof blob !== 'string') throw "Must pass a filename when type='file'"; */return read_file(blob, options);
1809 case "base64": /*:: if(typeof blob !== 'string') throw "Must pass a base64-encoded binary string when type='file'"; */return parse(s2a(Base64.decode(blob)), options);
1810 case "binary": /*:: if(typeof blob !== 'string') throw "Must pass a binary string when type='file'"; */return parse(s2a(blob), options);
1811 }
1812 return parse(/*::typeof blob == 'string' ? new Buffer(blob, 'utf-8') : */blob, options);
1813}
1814
1815function init_cfb(cfb/*:CFBContainer*/, opts/*:?any*/)/*:void*/ {
1816 var o = opts || {}, root = o.root || "Root Entry";
1817 if(!cfb.FullPaths) cfb.FullPaths = [];
1818 if(!cfb.FileIndex) cfb.FileIndex = [];
1819 if(cfb.FullPaths.length !== cfb.FileIndex.length) throw new Error("inconsistent CFB structure");
1820 if(cfb.FullPaths.length === 0) {
1821 cfb.FullPaths[0] = root + "/";
1822 cfb.FileIndex[0] = ({ name: root, type: 5 }/*:any*/);
1823 }
1824 if(o.CLSID) cfb.FileIndex[0].clsid = o.CLSID;
1825 seed_cfb(cfb);
1826}
1827function seed_cfb(cfb/*:CFBContainer*/)/*:void*/ {
1828 var nm = "\u0001Sh33tJ5";
1829 if(CFB.find(cfb, "/" + nm)) return;
1830 var p = new_buf(4); p[0] = 55; p[1] = p[3] = 50; p[2] = 54;
1831 cfb.FileIndex.push(({ name: nm, type: 2, content:p, size:4, L:69, R:69, C:69 }/*:any*/));
1832 cfb.FullPaths.push(cfb.FullPaths[0] + nm);
1833 rebuild_cfb(cfb);
1834}
1835function rebuild_cfb(cfb/*:CFBContainer*/, f/*:?boolean*/)/*:void*/ {
1836 init_cfb(cfb);
1837 var gc = false, s = false;
1838 for(var i = cfb.FullPaths.length - 1; i >= 0; --i) {
1839 var _file = cfb.FileIndex[i];
1840 switch(_file.type) {
1841 case 0:
1842 if(s) gc = true;
1843 else { cfb.FileIndex.pop(); cfb.FullPaths.pop(); }
1844 break;
1845 case 1: case 2: case 5:
1846 s = true;
1847 if(isNaN(_file.R * _file.L * _file.C)) gc = true;
1848 if(_file.R > -1 && _file.L > -1 && _file.R == _file.L) gc = true;
1849 break;
1850 default: gc = true; break;
1851 }
1852 }
1853 if(!gc && !f) return;
1854
1855 var now = new Date(1987, 1, 19), j = 0;
1856 var data/*:Array<[string, CFBEntry]>*/ = [];
1857 for(i = 0; i < cfb.FullPaths.length; ++i) {
1858 if(cfb.FileIndex[i].type === 0) continue;
1859 data.push([cfb.FullPaths[i], cfb.FileIndex[i]]);
1860 }
1861 for(i = 0; i < data.length; ++i) {
1862 var dad = dirname(data[i][0]);
1863 s = false;
1864 for(j = 0; j < data.length; ++j) if(data[j][0] === dad) s = true;
1865 if(!s) data.push([dad, ({
1866 name: filename(dad).replace("/",""),
1867 type: 1,
1868 clsid: HEADER_CLSID,
1869 ct: now, mt: now,
1870 content: null
1871 }/*:any*/)]);
1872 }
1873
1874 data.sort(function(x,y) { return namecmp(x[0], y[0]); });
1875 cfb.FullPaths = []; cfb.FileIndex = [];
1876 for(i = 0; i < data.length; ++i) { cfb.FullPaths[i] = data[i][0]; cfb.FileIndex[i] = data[i][1]; }
1877 for(i = 0; i < data.length; ++i) {
1878 var elt = cfb.FileIndex[i];
1879 var nm = cfb.FullPaths[i];
1880
1881 elt.name = filename(nm).replace("/","");
1882 elt.L = elt.R = elt.C = -(elt.color = 1);
1883 elt.size = elt.content ? elt.content.length : 0;
1884 elt.start = 0;
1885 elt.clsid = (elt.clsid || HEADER_CLSID);
1886 if(i === 0) {
1887 elt.C = data.length > 1 ? 1 : -1;
1888 elt.size = 0;
1889 elt.type = 5;
1890 } else if(nm.slice(-1) == "/") {
1891 for(j=i+1;j < data.length; ++j) if(dirname(cfb.FullPaths[j])==nm) break;
1892 elt.C = j >= data.length ? -1 : j;
1893 for(j=i+1;j < data.length; ++j) if(dirname(cfb.FullPaths[j])==dirname(nm)) break;
1894 elt.R = j >= data.length ? -1 : j;
1895 elt.type = 1;
1896 } else {
1897 if(dirname(cfb.FullPaths[i+1]||"") == dirname(nm)) elt.R = i + 1;
1898 elt.type = 2;
1899 }
1900 }
1901
1902}
1903
1904function _write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes*/ {
1905 var _opts = options || {};
1906 rebuild_cfb(cfb);
1907 if(_opts.fileType == 'zip') return write_zip(cfb, _opts);
1908 var L = (function(cfb/*:CFBContainer*/)/*:Array<number>*/{
1909 var mini_size = 0, fat_size = 0;
1910 for(var i = 0; i < cfb.FileIndex.length; ++i) {
1911 var file = cfb.FileIndex[i];
1912 if(!file.content) continue;
1913 /*:: if(file.content == null) throw new Error("unreachable"); */
1914 var flen = file.content.length;
1915 if(flen > 0){
1916 if(flen < 0x1000) mini_size += (flen + 0x3F) >> 6;
1917 else fat_size += (flen + 0x01FF) >> 9;
1918 }
1919 }
1920 var dir_cnt = (cfb.FullPaths.length +3) >> 2;
1921 var mini_cnt = (mini_size + 7) >> 3;
1922 var mfat_cnt = (mini_size + 0x7F) >> 7;
1923 var fat_base = mini_cnt + fat_size + dir_cnt + mfat_cnt;
1924 var fat_cnt = (fat_base + 0x7F) >> 7;
1925 var difat_cnt = fat_cnt <= 109 ? 0 : Math.ceil((fat_cnt-109)/0x7F);
1926 while(((fat_base + fat_cnt + difat_cnt + 0x7F) >> 7) > fat_cnt) difat_cnt = ++fat_cnt <= 109 ? 0 : Math.ceil((fat_cnt-109)/0x7F);
1927 var L = [1, difat_cnt, fat_cnt, mfat_cnt, dir_cnt, fat_size, mini_size, 0];
1928 cfb.FileIndex[0].size = mini_size << 6;
1929 L[7] = (cfb.FileIndex[0].start=L[0]+L[1]+L[2]+L[3]+L[4]+L[5])+((L[6]+7) >> 3);
1930 return L;
1931 })(cfb);
1932 var o = new_buf(L[7] << 9);
1933 var i = 0, T = 0;
1934 {
1935 for(i = 0; i < 8; ++i) o.write_shift(1, HEADER_SIG[i]);
1936 for(i = 0; i < 8; ++i) o.write_shift(2, 0);
1937 o.write_shift(2, 0x003E);
1938 o.write_shift(2, 0x0003);
1939 o.write_shift(2, 0xFFFE);
1940 o.write_shift(2, 0x0009);
1941 o.write_shift(2, 0x0006);
1942 for(i = 0; i < 3; ++i) o.write_shift(2, 0);
1943 o.write_shift(4, 0);
1944 o.write_shift(4, L[2]);
1945 o.write_shift(4, L[0] + L[1] + L[2] + L[3] - 1);
1946 o.write_shift(4, 0);
1947 o.write_shift(4, 1<<12);
1948 o.write_shift(4, L[3] ? L[0] + L[1] + L[2] - 1: ENDOFCHAIN);
1949 o.write_shift(4, L[3]);
1950 o.write_shift(-4, L[1] ? L[0] - 1: ENDOFCHAIN);
1951 o.write_shift(4, L[1]);
1952 for(i = 0; i < 109; ++i) o.write_shift(-4, i < L[2] ? L[1] + i : -1);
1953 }
1954 if(L[1]) {
1955 for(T = 0; T < L[1]; ++T) {
1956 for(; i < 236 + T * 127; ++i) o.write_shift(-4, i < L[2] ? L[1] + i : -1);
1957 o.write_shift(-4, T === L[1] - 1 ? ENDOFCHAIN : T + 1);
1958 }
1959 }
1960 var chainit = function(w/*:number*/)/*:void*/ {
1961 for(T += w; i<T-1; ++i) o.write_shift(-4, i+1);
1962 if(w) { ++i; o.write_shift(-4, ENDOFCHAIN); }
1963 };
1964 T = i = 0;
1965 for(T+=L[1]; i<T; ++i) o.write_shift(-4, consts.DIFSECT);
1966 for(T+=L[2]; i<T; ++i) o.write_shift(-4, consts.FATSECT);
1967 chainit(L[3]);
1968 chainit(L[4]);
1969 var j/*:number*/ = 0, flen/*:number*/ = 0;
1970 var file/*:CFBEntry*/ = cfb.FileIndex[0];
1971 for(; j < cfb.FileIndex.length; ++j) {
1972 file = cfb.FileIndex[j];
1973 if(!file.content) continue;
1974 /*:: if(file.content == null) throw new Error("unreachable"); */
1975 flen = file.content.length;
1976 if(flen < 0x1000) continue;
1977 file.start = T;
1978 chainit((flen + 0x01FF) >> 9);
1979 }
1980 chainit((L[6] + 7) >> 3);
1981 while(o.l & 0x1FF) o.write_shift(-4, consts.ENDOFCHAIN);
1982 T = i = 0;
1983 for(j = 0; j < cfb.FileIndex.length; ++j) {
1984 file = cfb.FileIndex[j];
1985 if(!file.content) continue;
1986 /*:: if(file.content == null) throw new Error("unreachable"); */
1987 flen = file.content.length;
1988 if(!flen || flen >= 0x1000) continue;
1989 file.start = T;
1990 chainit((flen + 0x3F) >> 6);
1991 }
1992 while(o.l & 0x1FF) o.write_shift(-4, consts.ENDOFCHAIN);
1993 for(i = 0; i < L[4]<<2; ++i) {
1994 var nm = cfb.FullPaths[i];
1995 if(!nm || nm.length === 0) {
1996 for(j = 0; j < 17; ++j) o.write_shift(4, 0);
1997 for(j = 0; j < 3; ++j) o.write_shift(4, -1);
1998 for(j = 0; j < 12; ++j) o.write_shift(4, 0);
1999 continue;
2000 }
2001 file = cfb.FileIndex[i];
2002 if(i === 0) file.start = file.size ? file.start - 1 : ENDOFCHAIN;
2003 var _nm/*:string*/ = (i === 0 && _opts.root) || file.name;
2004 flen = 2*(_nm.length+1);
2005 o.write_shift(64, _nm, "utf16le");
2006 o.write_shift(2, flen);
2007 o.write_shift(1, file.type);
2008 o.write_shift(1, file.color);
2009 o.write_shift(-4, file.L);
2010 o.write_shift(-4, file.R);
2011 o.write_shift(-4, file.C);
2012 if(!file.clsid) for(j = 0; j < 4; ++j) o.write_shift(4, 0);
2013 else o.write_shift(16, file.clsid, "hex");
2014 o.write_shift(4, file.state || 0);
2015 o.write_shift(4, 0); o.write_shift(4, 0);
2016 o.write_shift(4, 0); o.write_shift(4, 0);
2017 o.write_shift(4, file.start);
2018 o.write_shift(4, file.size); o.write_shift(4, 0);
2019 }
2020 for(i = 1; i < cfb.FileIndex.length; ++i) {
2021 file = cfb.FileIndex[i];
2022 /*:: if(!file.content) throw new Error("unreachable"); */
2023 if(file.size >= 0x1000) {
2024 o.l = (file.start+1) << 9;
2025 for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]);
2026 for(; j & 0x1FF; ++j) o.write_shift(1, 0);
2027 }
2028 }
2029 for(i = 1; i < cfb.FileIndex.length; ++i) {
2030 file = cfb.FileIndex[i];
2031 /*:: if(!file.content) throw new Error("unreachable"); */
2032 if(file.size > 0 && file.size < 0x1000) {
2033 for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]);
2034 for(; j & 0x3F; ++j) o.write_shift(1, 0);
2035 }
2036 }
2037 while(o.l < o.length) o.write_shift(1, 0);
2038 return o;
2039}
2040/* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */
2041function find(cfb/*:CFBContainer*/, path/*:string*/)/*:?CFBEntry*/ {
2042 var UCFullPaths/*:Array<string>*/ = cfb.FullPaths.map(function(x) { return x.toUpperCase(); });
2043 var UCPaths/*:Array<string>*/ = UCFullPaths.map(function(x) { var y = x.split("/"); return y[y.length - (x.slice(-1) == "/" ? 2 : 1)]; });
2044 var k/*:boolean*/ = false;
2045 if(path.charCodeAt(0) === 47 /* "/" */) { k = true; path = UCFullPaths[0].slice(0, -1) + path; }
2046 else k = path.indexOf("/") !== -1;
2047 var UCPath/*:string*/ = path.toUpperCase();
2048 var w/*:number*/ = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath);
2049 if(w !== -1) return cfb.FileIndex[w];
2050
2051 var m = !UCPath.match(chr1);
2052 UCPath = UCPath.replace(chr0,'');
2053 if(m) UCPath = UCPath.replace(chr1,'!');
2054 for(w = 0; w < UCFullPaths.length; ++w) {
2055 if((m ? UCFullPaths[w].replace(chr1,'!') : UCFullPaths[w]).replace(chr0,'') == UCPath) return cfb.FileIndex[w];
2056 if((m ? UCPaths[w].replace(chr1,'!') : UCPaths[w]).replace(chr0,'') == UCPath) return cfb.FileIndex[w];
2057 }
2058 return null;
2059}
2060/** CFB Constants */
2061var MSSZ = 64; /* Mini Sector Size = 1<<6 */
2062//var MSCSZ = 4096; /* Mini Stream Cutoff Size */
2063/* 2.1 Compound File Sector Numbers and Types */
2064var ENDOFCHAIN = -2;
2065/* 2.2 Compound File Header */
2066var HEADER_SIGNATURE = 'd0cf11e0a1b11ae1';
2067var HEADER_SIG = [0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1];
2068var HEADER_CLSID = '00000000000000000000000000000000';
2069var consts = {
2070 /* 2.1 Compund File Sector Numbers and Types */
2071 MAXREGSECT: -6,
2072 DIFSECT: -4,
2073 FATSECT: -3,
2074 ENDOFCHAIN: ENDOFCHAIN,
2075 FREESECT: -1,
2076 /* 2.2 Compound File Header */
2077 HEADER_SIGNATURE: HEADER_SIGNATURE,
2078 HEADER_MINOR_VERSION: '3e00',
2079 MAXREGSID: -6,
2080 NOSTREAM: -1,
2081 HEADER_CLSID: HEADER_CLSID,
2082 /* 2.6.1 Compound File Directory Entry */
2083 EntryTypes: ['unknown','storage','stream','lockbytes','property','root']
2084};
2085
2086function write_file(cfb/*:CFBContainer*/, filename/*:string*/, options/*:CFBWriteOpts*/)/*:void*/ {
2087 get_fs();
2088 var o = _write(cfb, options);
2089 /*:: if(typeof Buffer == 'undefined' || !Buffer.isBuffer(o) || !(o instanceof Buffer)) throw new Error("unreachable"); */
2090 fs.writeFileSync(filename, o);
2091}
2092
2093function a2s(o/*:RawBytes*/)/*:string*/ {
2094 var out = new Array(o.length);
2095 for(var i = 0; i < o.length; ++i) out[i] = String.fromCharCode(o[i]);
2096 return out.join("");
2097}
2098
2099function write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes|string*/ {
2100 var o = _write(cfb, options);
2101 switch(options && options.type) {
2102 case "file": get_fs(); fs.writeFileSync(options.filename, (o/*:any*/)); return o;
2103 case "binary": return a2s(o);
2104 case "base64": return Base64.encode(a2s(o));
2105 }
2106 return o;
2107}
2108/* node < 8.1 zlib does not expose bytesRead, so default to pure JS */
2109var _zlib;
2110function use_zlib(zlib) { try {
2111 var InflateRaw = zlib.InflateRaw;
2112 var InflRaw = new InflateRaw();
2113 InflRaw._processChunk(new Uint8Array([3, 0]), InflRaw._finishFlushFlag);
2114 if(InflRaw.bytesRead) _zlib = zlib;
2115 else throw new Error("zlib does not expose bytesRead");
2116} catch(e) {console.error("cannot use native zlib: " + (e.message || e)); } }
2117
2118function _inflateRawSync(payload, usz) {
2119 if(!_zlib) return _inflate(payload, usz);
2120 var InflateRaw = _zlib.InflateRaw;
2121 var InflRaw = new InflateRaw();
2122 var out = InflRaw._processChunk(payload.slice(payload.l), InflRaw._finishFlushFlag);
2123 payload.l += InflRaw.bytesRead;
2124 return out;
2125}
2126
2127function _deflateRawSync(payload) {
2128 return _zlib ? _zlib.deflateRawSync(payload) : _deflate(payload);
2129}
2130var CLEN_ORDER = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
2131
2132/* 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 ]; */
2133var 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 ];
2134
2135/* 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 ]; */
2136var 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 ];
2137
2138function bit_swap_8(n) { var t = (((((n<<1)|(n<<11)) & 0x22110) | (((n<<5)|(n<<15)) & 0x88440))); return ((t>>16) | (t>>8) |t)&0xFF; }
2139
2140var use_typed_arrays = typeof Uint8Array !== 'undefined';
2141
2142var bitswap8 = use_typed_arrays ? new Uint8Array(1<<8) : [];
2143for(var q = 0; q < (1<<8); ++q) bitswap8[q] = bit_swap_8(q);
2144
2145function bit_swap_n(n, b) {
2146 var rev = bitswap8[n & 0xFF];
2147 if(b <= 8) return rev >>> (8-b);
2148 rev = (rev << 8) | bitswap8[(n>>8)&0xFF];
2149 if(b <= 16) return rev >>> (16-b);
2150 rev = (rev << 8) | bitswap8[(n>>16)&0xFF];
2151 return rev >>> (24-b);
2152}
2153
2154/* helpers for unaligned bit reads */
2155function read_bits_2(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 6 ? 0 : buf[h+1]<<8))>>>w)& 0x03; }
2156function read_bits_3(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 5 ? 0 : buf[h+1]<<8))>>>w)& 0x07; }
2157function read_bits_4(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 4 ? 0 : buf[h+1]<<8))>>>w)& 0x0F; }
2158function read_bits_5(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 3 ? 0 : buf[h+1]<<8))>>>w)& 0x1F; }
2159function read_bits_7(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 1 ? 0 : buf[h+1]<<8))>>>w)& 0x7F; }
2160
2161/* works up to n = 3 * 8 + 1 = 25 */
2162function read_bits_n(buf, bl, n) {
2163 var w = (bl&7), h = (bl>>>3), f = ((1<<n)-1);
2164 var v = buf[h] >>> w;
2165 if(n < 8 - w) return v & f;
2166 v |= buf[h+1]<<(8-w);
2167 if(n < 16 - w) return v & f;
2168 v |= buf[h+2]<<(16-w);
2169 if(n < 24 - w) return v & f;
2170 v |= buf[h+3]<<(24-w);
2171 return v & f;
2172}
2173
2174/* until ArrayBuffer#realloc is a thing, fake a realloc */
2175function realloc(b, sz/*:number*/) {
2176 var L = b.length, M = 2*L > sz ? 2*L : sz + 5, i = 0;
2177 if(L >= sz) return b;
2178 if(has_buf) {
2179 var o = new_unsafe_buf(M);
2180 // $FlowIgnore
2181 if(b.copy) b.copy(o);
2182 else for(; i < b.length; ++i) o[i] = b[i];
2183 return o;
2184 } else if(use_typed_arrays) {
2185 var a = new Uint8Array(M);
2186 if(a.set) a.set(b);
2187 else for(; i < b.length; ++i) a[i] = b[i];
2188 return a;
2189 }
2190 b.length = M;
2191 return b;
2192}
2193
2194/* zero-filled arrays for older browsers */
2195function zero_fill_array(n) {
2196 var o = new Array(n);
2197 for(var i = 0; i < n; ++i) o[i] = 0;
2198 return o;
2199}var _deflate = (function() {
2200var _deflateRaw = (function() {
2201 return function deflateRaw(data, out) {
2202 var boff = 0;
2203 while(boff < data.length) {
2204 var L = Math.min(0xFFFF, data.length - boff);
2205 var h = boff + L == data.length;
2206 /* TODO: this is only type 0 stored */
2207 out.write_shift(1, +h);
2208 out.write_shift(2, L);
2209 out.write_shift(2, (~L) & 0xFFFF);
2210 while(L-- > 0) out[out.l++] = data[boff++];
2211 }
2212 return out.l;
2213 };
2214})();
2215
2216return function(data) {
2217 var buf = new_buf(50+Math.floor(data.length*1.1));
2218 var off = _deflateRaw(data, buf);
2219 return buf.slice(0, off);
2220};
2221})();
2222/* modified inflate function also moves original read head */
2223
2224/* build tree (used for literals and lengths) */
2225function build_tree(clens, cmap, MAX/*:number*/)/*:number*/ {
2226 var maxlen = 1, w = 0, i = 0, j = 0, ccode = 0, L = clens.length;
2227
2228 var bl_count = use_typed_arrays ? new Uint16Array(32) : zero_fill_array(32);
2229 for(i = 0; i < 32; ++i) bl_count[i] = 0;
2230
2231 for(i = L; i < MAX; ++i) clens[i] = 0;
2232 L = clens.length;
2233
2234 var ctree = use_typed_arrays ? new Uint16Array(L) : zero_fill_array(L); // []
2235
2236 /* build code tree */
2237 for(i = 0; i < L; ++i) {
2238 bl_count[(w = clens[i])]++;
2239 if(maxlen < w) maxlen = w;
2240 ctree[i] = 0;
2241 }
2242 bl_count[0] = 0;
2243 for(i = 1; i <= maxlen; ++i) bl_count[i+16] = (ccode = (ccode + bl_count[i-1])<<1);
2244 for(i = 0; i < L; ++i) {
2245 ccode = clens[i];
2246 if(ccode != 0) ctree[i] = bl_count[ccode+16]++;
2247 }
2248
2249 /* cmap[maxlen + 4 bits] = (off&15) + (lit<<4) reverse mapping */
2250 var cleni = 0;
2251 for(i = 0; i < L; ++i) {
2252 cleni = clens[i];
2253 if(cleni != 0) {
2254 ccode = bit_swap_n(ctree[i], maxlen)>>(maxlen-cleni);
2255 for(j = (1<<(maxlen + 4 - cleni)) - 1; j>=0; --j)
2256 cmap[ccode|(j<<cleni)] = (cleni&15) | (i<<4);
2257 }
2258 }
2259 return maxlen;
2260}
2261
2262var fix_lmap = use_typed_arrays ? new Uint16Array(512) : zero_fill_array(512);
2263var fix_dmap = use_typed_arrays ? new Uint16Array(32) : zero_fill_array(32);
2264if(!use_typed_arrays) {
2265 for(var i = 0; i < 512; ++i) fix_lmap[i] = 0;
2266 for(i = 0; i < 32; ++i) fix_dmap[i] = 0;
2267}
2268(function() {
2269 var dlens/*:Array<number>*/ = [];
2270 var i = 0;
2271 for(;i<32; i++) dlens.push(5);
2272 build_tree(dlens, fix_dmap, 32);
2273
2274 var clens/*:Array<number>*/ = [];
2275 i = 0;
2276 for(; i<=143; i++) clens.push(8);
2277 for(; i<=255; i++) clens.push(9);
2278 for(; i<=279; i++) clens.push(7);
2279 for(; i<=287; i++) clens.push(8);
2280 build_tree(clens, fix_lmap, 288);
2281})();
2282
2283var dyn_lmap = use_typed_arrays ? new Uint16Array(32768) : zero_fill_array(32768);
2284var dyn_dmap = use_typed_arrays ? new Uint16Array(32768) : zero_fill_array(32768);
2285var dyn_cmap = use_typed_arrays ? new Uint16Array(128) : zero_fill_array(128);
2286var dyn_len_1 = 1, dyn_len_2 = 1;
2287
2288/* 5.5.3 Expanding Huffman Codes */
2289function dyn(data, boff/*:number*/) {
2290 /* nomenclature from RFC1951 refers to bit values; these are offset by the implicit constant */
2291 var _HLIT = read_bits_5(data, boff) + 257; boff += 5;
2292 var _HDIST = read_bits_5(data, boff) + 1; boff += 5;
2293 var _HCLEN = read_bits_4(data, boff) + 4; boff += 4;
2294 var w = 0;
2295
2296 /* grab and store code lengths */
2297 var clens = use_typed_arrays ? new Uint8Array(19) : zero_fill_array(19);
2298 var ctree = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
2299 var maxlen = 1;
2300 var bl_count = use_typed_arrays ? new Uint8Array(8) : zero_fill_array(8);
2301 var next_code = use_typed_arrays ? new Uint8Array(8) : zero_fill_array(8);
2302 var L = clens.length; /* 19 */
2303 for(var i = 0; i < _HCLEN; ++i) {
2304 clens[CLEN_ORDER[i]] = w = read_bits_3(data, boff);
2305 if(maxlen < w) maxlen = w;
2306 bl_count[w]++;
2307 boff += 3;
2308 }
2309
2310 /* build code tree */
2311 var ccode = 0;
2312 bl_count[0] = 0;
2313 for(i = 1; i <= maxlen; ++i) next_code[i] = ccode = (ccode + bl_count[i-1])<<1;
2314 for(i = 0; i < L; ++i) if((ccode = clens[i]) != 0) ctree[i] = next_code[ccode]++;
2315 /* cmap[7 bits from stream] = (off&7) + (lit<<3) */
2316 var cleni = 0;
2317 for(i = 0; i < L; ++i) {
2318 cleni = clens[i];
2319 if(cleni != 0) {
2320 ccode = bitswap8[ctree[i]]>>(8-cleni);
2321 for(var j = (1<<(7-cleni))-1; j>=0; --j) dyn_cmap[ccode|(j<<cleni)] = (cleni&7) | (i<<3);
2322 }
2323 }
2324
2325 /* read literal and dist codes at once */
2326 var hcodes/*:Array<number>*/ = [];
2327 maxlen = 1;
2328 for(; hcodes.length < _HLIT + _HDIST;) {
2329 ccode = dyn_cmap[read_bits_7(data, boff)];
2330 boff += ccode & 7;
2331 switch((ccode >>>= 3)) {
2332 case 16:
2333 w = 3 + read_bits_2(data, boff); boff += 2;
2334 ccode = hcodes[hcodes.length - 1];
2335 while(w-- > 0) hcodes.push(ccode);
2336 break;
2337 case 17:
2338 w = 3 + read_bits_3(data, boff); boff += 3;
2339 while(w-- > 0) hcodes.push(0);
2340 break;
2341 case 18:
2342 w = 11 + read_bits_7(data, boff); boff += 7;
2343 while(w -- > 0) hcodes.push(0);
2344 break;
2345 default:
2346 hcodes.push(ccode);
2347 if(maxlen < ccode) maxlen = ccode;
2348 break;
2349 }
2350 }
2351
2352 /* build literal / length trees */
2353 var h1 = hcodes.slice(0, _HLIT), h2 = hcodes.slice(_HLIT);
2354 for(i = _HLIT; i < 286; ++i) h1[i] = 0;
2355 for(i = _HDIST; i < 30; ++i) h2[i] = 0;
2356 dyn_len_1 = build_tree(h1, dyn_lmap, 286);
2357 dyn_len_2 = build_tree(h2, dyn_dmap, 30);
2358 return boff;
2359}
2360
2361/* return [ data, bytesRead ] */
2362function inflate(data, usz/*:number*/) {
2363 /* shortcircuit for empty buffer [0x03, 0x00] */
2364 if(data[0] == 3 && !(data[1] & 0x3)) { return [new_raw_buf(usz), 2]; }
2365
2366 /* bit offset */
2367 var boff = 0;
2368
2369 /* header includes final bit and type bits */
2370 var header = 0;
2371
2372 var outbuf = new_unsafe_buf(usz ? usz : (1<<18));
2373 var woff = 0;
2374 var OL = outbuf.length>>>0;
2375 var max_len_1 = 0, max_len_2 = 0;
2376
2377 while((header&1) == 0) {
2378 header = read_bits_3(data, boff); boff += 3;
2379 if((header >>> 1) == 0) {
2380 /* Stored block */
2381 if(boff & 7) boff += 8 - (boff&7);
2382 /* 2 bytes sz, 2 bytes bit inverse */
2383 var sz = data[boff>>>3] | data[(boff>>>3)+1]<<8;
2384 boff += 32;
2385 /* push sz bytes */
2386 if(!usz && OL < woff + sz) { outbuf = realloc(outbuf, woff + sz); OL = outbuf.length; }
2387 if(typeof data.copy === 'function') {
2388 // $FlowIgnore
2389 data.copy(outbuf, woff, boff>>>3, (boff>>>3)+sz);
2390 woff += sz; boff += 8*sz;
2391 } else while(sz-- > 0) { outbuf[woff++] = data[boff>>>3]; boff += 8; }
2392 continue;
2393 } else if((header >>> 1) == 1) {
2394 /* Fixed Huffman */
2395 max_len_1 = 9; max_len_2 = 5;
2396 } else {
2397 /* Dynamic Huffman */
2398 boff = dyn(data, boff);
2399 max_len_1 = dyn_len_1; max_len_2 = dyn_len_2;
2400 }
2401 if(!usz && (OL < woff + 32767)) { outbuf = realloc(outbuf, woff + 32767); OL = outbuf.length; }
2402 for(;;) { // while(true) is apparently out of vogue in modern JS circles
2403 /* ingest code and move read head */
2404 var bits = read_bits_n(data, boff, max_len_1);
2405 var code = (header>>>1) == 1 ? fix_lmap[bits] : dyn_lmap[bits];
2406 boff += code & 15; code >>>= 4;
2407 /* 0-255 are literals, 256 is end of block token, 257+ are copy tokens */
2408 if(((code>>>8)&0xFF) === 0) outbuf[woff++] = code;
2409 else if(code == 256) break;
2410 else {
2411 code -= 257;
2412 var len_eb = (code < 8) ? 0 : ((code-4)>>2); if(len_eb > 5) len_eb = 0;
2413 var tgt = woff + LEN_LN[code];
2414 /* length extra bits */
2415 if(len_eb > 0) {
2416 tgt += read_bits_n(data, boff, len_eb);
2417 boff += len_eb;
2418 }
2419
2420 /* dist code */
2421 bits = read_bits_n(data, boff, max_len_2);
2422 code = (header>>>1) == 1 ? fix_dmap[bits] : dyn_dmap[bits];
2423 boff += code & 15; code >>>= 4;
2424 var dst_eb = (code < 4 ? 0 : (code-2)>>1);
2425 var dst = DST_LN[code];
2426 /* dist extra bits */
2427 if(dst_eb > 0) {
2428 dst += read_bits_n(data, boff, dst_eb);
2429 boff += dst_eb;
2430 }
2431
2432 /* in the common case, manual byte copy is faster than TA set / Buffer copy */
2433 if(!usz && OL < tgt) { outbuf = realloc(outbuf, tgt); OL = outbuf.length; }
2434 while(woff < tgt) { outbuf[woff] = outbuf[woff - dst]; ++woff; }
2435 }
2436 }
2437 }
2438 return [usz ? outbuf : outbuf.slice(0, woff), (boff+7)>>>3];
2439}
2440
2441function _inflate(payload, usz) {
2442 var data = payload.slice(payload.l||0);
2443 var out = inflate(data, usz);
2444 payload.l += out[1];
2445 return out[0];
2446}
2447
2448function warn_or_throw(wrn, msg) {
2449 if(wrn) { if(typeof console !== 'undefined') console.error(msg); }
2450 else throw new Error(msg);
2451}
2452
2453function parse_zip(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/ {
2454 var blob/*:CFBlob*/ = /*::(*/file/*:: :any)*/;
2455 prep_blob(blob, 0);
2456
2457 var FileIndex/*:CFBFileIndex*/ = [], FullPaths/*:Array<string>*/ = [];
2458 var o = {
2459 FileIndex: FileIndex,
2460 FullPaths: FullPaths
2461 };
2462 init_cfb(o, { root: options.root });
2463
2464 /* find end of central directory, start just after signature */
2465 var i = blob.length - 4;
2466 while((blob[i] != 0x50 || blob[i+1] != 0x4b || blob[i+2] != 0x05 || blob[i+3] != 0x06) && i >= 0) --i;
2467 blob.l = i + 4;
2468
2469 /* parse end of central directory */
2470 blob.l += 4;
2471 var fcnt = blob.read_shift(2);
2472 blob.l += 6;
2473 var start_cd = blob.read_shift(4);
2474
2475 /* parse central directory */
2476 blob.l = start_cd;
2477
2478 for(i = 0; i < fcnt; ++i) {
2479 /* trust local file header instead of CD entry */
2480 blob.l += 20;
2481 var csz = blob.read_shift(4);
2482 var usz = blob.read_shift(4);
2483 var namelen = blob.read_shift(2);
2484 var efsz = blob.read_shift(2);
2485 var fcsz = blob.read_shift(2);
2486 blob.l += 8;
2487 var offset = blob.read_shift(4);
2488 var EF = parse_extra_field(/*::(*/blob.slice(blob.l+namelen, blob.l+namelen+efsz)/*:: :any)*/);
2489 blob.l += namelen + efsz + fcsz;
2490
2491 var L = blob.l;
2492 blob.l = offset + 4;
2493 parse_local_file(blob, csz, usz, o, EF);
2494 blob.l = L;
2495 }
2496
2497 return o;
2498}
2499
2500
2501/* head starts just after local file header signature */
2502function parse_local_file(blob/*:CFBlob*/, csz/*:number*/, usz/*:number*/, o/*:CFBContainer*/, EF) {
2503 /* [local file header] */
2504 blob.l += 2;
2505 var flags = blob.read_shift(2);
2506 var meth = blob.read_shift(2);
2507 var date = parse_dos_date(blob);
2508
2509 if(flags & 0x2041) throw new Error("Unsupported ZIP encryption");
2510 var crc32 = blob.read_shift(4);
2511 var _csz = blob.read_shift(4);
2512 var _usz = blob.read_shift(4);
2513
2514 var namelen = blob.read_shift(2);
2515 var efsz = blob.read_shift(2);
2516
2517 // TODO: flags & (1<<11) // UTF8
2518 var name = ""; for(var i = 0; i < namelen; ++i) name += String.fromCharCode(blob[blob.l++]);
2519 if(efsz) {
2520 var ef = parse_extra_field(/*::(*/blob.slice(blob.l, blob.l + efsz)/*:: :any)*/);
2521 if((ef[0x5455]||{}).mt) date = ef[0x5455].mt;
2522 if(((EF||{})[0x5455]||{}).mt) date = EF[0x5455].mt;
2523 }
2524 blob.l += efsz;
2525
2526 /* [encryption header] */
2527
2528 /* [file data] */
2529 var data = blob.slice(blob.l, blob.l + _csz);
2530 switch(meth) {
2531 case 8: data = _inflateRawSync(blob, _usz); break;
2532 case 0: break;
2533 default: throw new Error("Unsupported ZIP Compression method " + meth);
2534 }
2535
2536 /* [data descriptor] */
2537 var wrn = false;
2538 if(flags & 8) {
2539 crc32 = blob.read_shift(4);
2540 if(crc32 == 0x08074b50) { crc32 = blob.read_shift(4); wrn = true; }
2541 _csz = blob.read_shift(4);
2542 _usz = blob.read_shift(4);
2543 }
2544
2545 if(_csz != csz) warn_or_throw(wrn, "Bad compressed size: " + csz + " != " + _csz);
2546 if(_usz != usz) warn_or_throw(wrn, "Bad uncompressed size: " + usz + " != " + _usz);
2547 var _crc32 = CRC32.buf(data, 0);
2548 if((crc32>>0) != (_crc32>>0)) warn_or_throw(wrn, "Bad CRC32 checksum: " + crc32 + " != " + _crc32);
2549 cfb_add(o, name, data, {unsafe: true, mt: date});
2550}
2551function write_zip(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes*/ {
2552 var _opts = options || {};
2553 var out = [], cdirs = [];
2554 var o/*:CFBlob*/ = new_buf(1);
2555 var method = (_opts.compression ? 8 : 0), flags = 0;
2556 var desc = false;
2557 if(desc) flags |= 8;
2558 var i = 0, j = 0;
2559
2560 var start_cd = 0, fcnt = 0;
2561 var root = cfb.FullPaths[0], fp = root, fi = cfb.FileIndex[0];
2562 var crcs = [];
2563 var sz_cd = 0;
2564
2565 for(i = 1; i < cfb.FullPaths.length; ++i) {
2566 fp = cfb.FullPaths[i].slice(root.length); fi = cfb.FileIndex[i];
2567 if(!fi.size || !fi.content || fp == "\u0001Sh33tJ5") continue;
2568 var start = start_cd;
2569
2570 /* TODO: CP437 filename */
2571 var namebuf = new_buf(fp.length);
2572 for(j = 0; j < fp.length; ++j) namebuf.write_shift(1, fp.charCodeAt(j) & 0x7F);
2573 namebuf = namebuf.slice(0, namebuf.l);
2574 crcs[fcnt] = CRC32.buf(/*::((*/fi.content/*::||[]):any)*/, 0);
2575
2576 var outbuf = fi.content/*::||[]*/;
2577 if(method == 8) outbuf = _deflateRawSync(outbuf);
2578
2579 /* local file header */
2580 o = new_buf(30);
2581 o.write_shift(4, 0x04034b50);
2582 o.write_shift(2, 20);
2583 o.write_shift(2, flags);
2584 o.write_shift(2, method);
2585 /* TODO: last mod file time/date */
2586 if(fi.mt) write_dos_date(o, fi.mt);
2587 else o.write_shift(4, 0);
2588 o.write_shift(-4, (flags & 8) ? 0 : crcs[fcnt]);
2589 o.write_shift(4, (flags & 8) ? 0 : outbuf.length);
2590 o.write_shift(4, (flags & 8) ? 0 : /*::(*/fi.content/*::||[])*/.length);
2591 o.write_shift(2, namebuf.length);
2592 o.write_shift(2, 0);
2593
2594 start_cd += o.length;
2595 out.push(o);
2596 start_cd += namebuf.length;
2597 out.push(namebuf);
2598
2599 /* TODO: encryption header ? */
2600 start_cd += outbuf.length;
2601 out.push(outbuf);
2602
2603 /* data descriptor */
2604 if(flags & 8) {
2605 o = new_buf(12);
2606 o.write_shift(-4, crcs[fcnt]);
2607 o.write_shift(4, outbuf.length);
2608 o.write_shift(4, /*::(*/fi.content/*::||[])*/.length);
2609 start_cd += o.l;
2610 out.push(o);
2611 }
2612
2613 /* central directory */
2614 o = new_buf(46);
2615 o.write_shift(4, 0x02014b50);
2616 o.write_shift(2, 0);
2617 o.write_shift(2, 20);
2618 o.write_shift(2, flags);
2619 o.write_shift(2, method);
2620 o.write_shift(4, 0); /* TODO: last mod file time/date */
2621 o.write_shift(-4, crcs[fcnt]);
2622
2623 o.write_shift(4, outbuf.length);
2624 o.write_shift(4, /*::(*/fi.content/*::||[])*/.length);
2625 o.write_shift(2, namebuf.length);
2626 o.write_shift(2, 0);
2627 o.write_shift(2, 0);
2628 o.write_shift(2, 0);
2629 o.write_shift(2, 0);
2630 o.write_shift(4, 0);
2631 o.write_shift(4, start);
2632
2633 sz_cd += o.l;
2634 cdirs.push(o);
2635 sz_cd += namebuf.length;
2636 cdirs.push(namebuf);
2637 ++fcnt;
2638 }
2639
2640 /* end of central directory */
2641 o = new_buf(22);
2642 o.write_shift(4, 0x06054b50);
2643 o.write_shift(2, 0);
2644 o.write_shift(2, 0);
2645 o.write_shift(2, fcnt);
2646 o.write_shift(2, fcnt);
2647 o.write_shift(4, sz_cd);
2648 o.write_shift(4, start_cd);
2649 o.write_shift(2, 0);
2650
2651 return bconcat(([bconcat((out/*:any*/)), bconcat(cdirs), o]/*:any*/));
2652}
2653function cfb_new(opts/*:?any*/)/*:CFBContainer*/ {
2654 var o/*:CFBContainer*/ = ({}/*:any*/);
2655 init_cfb(o, opts);
2656 return o;
2657}
2658
2659function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, opts/*:?any*/)/*:CFBEntry*/ {
2660 var unsafe = opts && opts.unsafe;
2661 if(!unsafe) init_cfb(cfb);
2662 var file = !unsafe && CFB.find(cfb, name);
2663 if(!file) {
2664 var fpath/*:string*/ = cfb.FullPaths[0];
2665 if(name.slice(0, fpath.length) == fpath) fpath = name;
2666 else {
2667 if(fpath.slice(-1) != "/") fpath += "/";
2668 fpath = (fpath + name).replace("//","/");
2669 }
2670 file = ({name: filename(name), type: 2}/*:any*/);
2671 cfb.FileIndex.push(file);
2672 cfb.FullPaths.push(fpath);
2673 if(!unsafe) CFB.utils.cfb_gc(cfb);
2674 }
2675 /*:: if(!file) throw new Error("unreachable"); */
2676 file.content = (content/*:any*/);
2677 file.size = content ? content.length : 0;
2678 if(opts) {
2679 if(opts.CLSID) file.clsid = opts.CLSID;
2680 if(opts.mt) file.mt = opts.mt;
2681 if(opts.ct) file.ct = opts.ct;
2682 }
2683 return file;
2684}
2685
2686function cfb_del(cfb/*:CFBContainer*/, name/*:string*/)/*:boolean*/ {
2687 init_cfb(cfb);
2688 var file = CFB.find(cfb, name);
2689 if(file) for(var j = 0; j < cfb.FileIndex.length; ++j) if(cfb.FileIndex[j] == file) {
2690 cfb.FileIndex.splice(j, 1);
2691 cfb.FullPaths.splice(j, 1);
2692 return true;
2693 }
2694 return false;
2695}
2696
2697function cfb_mov(cfb/*:CFBContainer*/, old_name/*:string*/, new_name/*:string*/)/*:boolean*/ {
2698 init_cfb(cfb);
2699 var file = CFB.find(cfb, old_name);
2700 if(file) for(var j = 0; j < cfb.FileIndex.length; ++j) if(cfb.FileIndex[j] == file) {
2701 cfb.FileIndex[j].name = filename(new_name);
2702 cfb.FullPaths[j] = new_name;
2703 return true;
2704 }
2705 return false;
2706}
2707
2708function cfb_gc(cfb/*:CFBContainer*/)/*:void*/ { rebuild_cfb(cfb, true); }
2709
2710exports.find = find;
2711exports.read = read;
2712exports.parse = parse;
2713exports.write = write;
2714exports.writeFile = write_file;
2715exports.utils = {
2716 cfb_new: cfb_new,
2717 cfb_add: cfb_add,
2718 cfb_del: cfb_del,
2719 cfb_mov: cfb_mov,
2720 cfb_gc: cfb_gc,
2721 ReadShift: ReadShift,
2722 CheckField: CheckField,
2723 prep_blob: prep_blob,
2724 bconcat: bconcat,
2725 use_zlib: use_zlib,
2726 _deflateRaw: _deflate,
2727 _inflateRaw: _inflate,
2728 consts: consts
2729};
2730
2731return exports;
2732})();
2733
2734if(typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO_NOT_EXPORT_CFB === 'undefined') { module.exports = CFB; }
2735import * as _fs from 'fs';
2736
2737/* normalize data for blob ctor */
2738function blobify(data) {
2739 if(typeof data === "string") return s2ab(data);
2740 if(Array.isArray(data)) return a2u(data);
2741 return data;
2742}
2743/* write or download file */
2744function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
2745 /*global IE_SaveFile, Blob, navigator, saveAs, document, File, chrome */
2746 if(typeof _fs !== 'undefined' && _fs.writeFileSync) return enc ? _fs.writeFileSync(fname, payload, enc) : _fs.writeFileSync(fname, payload);
2747 var data = (enc == "utf8") ? utf8write(payload) : payload;
2748 /*:: declare var IE_SaveFile: any; */
2749 if(typeof IE_SaveFile !== 'undefined') return IE_SaveFile(data, fname);
2750 if(typeof Blob !== 'undefined') {
2751 var blob = new Blob([blobify(data)], {type:"application/octet-stream"});
2752 /*:: declare var navigator: any; */
2753 if(typeof navigator !== 'undefined' && navigator.msSaveBlob) return navigator.msSaveBlob(blob, fname);
2754 /*:: declare var saveAs: any; */
2755 if(typeof saveAs !== 'undefined') return saveAs(blob, fname);
2756 if(typeof URL !== 'undefined' && typeof document !== 'undefined' && document.createElement && URL.createObjectURL) {
2757 var url = URL.createObjectURL(blob);
2758 /*:: declare var chrome: any; */
2759 if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
2760 if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
2761 return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
2762 }
2763 var a = document.createElement("a");
2764 if(a.download != null) {
2765 /*:: if(document.body == null) throw new Error("unreachable"); */
2766 a.download = fname; a.href = url; document.body.appendChild(a); a.click();
2767 /*:: if(document.body == null) throw new Error("unreachable"); */ document.body.removeChild(a);
2768 if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
2769 return url;
2770 }
2771 }
2772 }
2773 // $FlowIgnore
2774 if(typeof $ !== 'undefined' && typeof File !== 'undefined' && typeof Folder !== 'undefined') try { // extendscript
2775 // $FlowIgnore
2776 var out = File(fname); out.open("w"); out.encoding = "binary";
2777 if(Array.isArray(payload)) payload = a2s(payload);
2778 out.write(payload); out.close(); return payload;
2779 } catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; }
2780 throw new Error("cannot save file " + fname);
2781}
2782
2783/* read binary data from file */
2784function read_binary(path/*:string*/) {
2785 if(typeof _fs !== 'undefined') return _fs.readFileSync(path);
2786 // $FlowIgnore
2787 if(typeof $ !== 'undefined' && typeof File !== 'undefined' && typeof Folder !== 'undefined') try { // extendscript
2788 // $FlowIgnore
2789 var infile = File(path); infile.open("r"); infile.encoding = "binary";
2790 var data = infile.read(); infile.close();
2791 return data;
2792 } catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; }
2793 throw new Error("Cannot access file " + path);
2794}
2795function keys(o/*:any*/)/*:Array<any>*/ {
2796 var ks = Object.keys(o), o2 = [];
2797 for(var i = 0; i < ks.length; ++i) if(Object.prototype.hasOwnProperty.call(o, ks[i])) o2.push(ks[i]);
2798 return o2;
2799}
2800
2801function evert_key(obj/*:any*/, key/*:string*/)/*:EvertType*/ {
2802 var o = ([]/*:any*/), K = keys(obj);
2803 for(var i = 0; i !== K.length; ++i) if(o[obj[K[i]][key]] == null) o[obj[K[i]][key]] = K[i];
2804 return o;
2805}
2806
2807function evert(obj/*:any*/)/*:EvertType*/ {
2808 var o = ([]/*:any*/), K = keys(obj);
2809 for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = K[i];
2810 return o;
2811}
2812
2813function evert_num(obj/*:any*/)/*:EvertNumType*/ {
2814 var o = ([]/*:any*/), K = keys(obj);
2815 for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = parseInt(K[i],10);
2816 return o;
2817}
2818
2819function evert_arr(obj/*:any*/)/*:EvertArrType*/ {
2820 var o/*:EvertArrType*/ = ([]/*:any*/), K = keys(obj);
2821 for(var i = 0; i !== K.length; ++i) {
2822 if(o[obj[K[i]]] == null) o[obj[K[i]]] = [];
2823 o[obj[K[i]]].push(K[i]);
2824 }
2825 return o;
2826}
2827
2828var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
2829function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
2830 var epoch = v.getTime();
2831 if(date1904) epoch -= 1462*24*60*60*1000;
2832 var dnthresh = basedate.getTime() + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
2833 return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
2834}
2835var refdate = new Date();
2836var dnthresh = basedate.getTime() + (refdate.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
2837var refoffset = refdate.getTimezoneOffset();
2838function numdate(v/*:number*/)/*:Date*/ {
2839 var out = new Date();
2840 out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh);
2841 if (out.getTimezoneOffset() !== refoffset) {
2842 out.setTime(out.getTime() + (out.getTimezoneOffset() - refoffset) * 60000);
2843 }
2844 return out;
2845}
2846
2847/* ISO 8601 Duration */
2848function parse_isodur(s) {
2849 var sec = 0, mt = 0, time = false;
2850 var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
2851 if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
2852 for(var i = 1; i != m.length; ++i) {
2853 if(!m[i]) continue;
2854 mt = 1;
2855 if(i > 3) time = true;
2856 switch(m[i].slice(m[i].length-1)) {
2857 case 'Y':
2858 throw new Error("Unsupported ISO Duration Field: " + m[i].slice(m[i].length-1));
2859 case 'D': mt *= 24;
2860 /* falls through */
2861 case 'H': mt *= 60;
2862 /* falls through */
2863 case 'M':
2864 if(!time) throw new Error("Unsupported ISO Duration Field: M");
2865 else mt *= 60;
2866 /* falls through */
2867 case 'S': break;
2868 }
2869 sec += mt * parseInt(m[i], 10);
2870 }
2871 return sec;
2872}
2873
2874var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
2875if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
2876var good_pd = good_pd_date.getFullYear() == 2017;
2877/* parses a date as a local date */
2878function parseDate(str/*:string|Date*/, fixdate/*:?number*/)/*:Date*/ {
2879 var d = new Date(str);
2880 if(good_pd) {
2881 /*:: if(fixdate == null) fixdate = 0; */
2882 if(fixdate > 0) d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
2883 else if(fixdate < 0) d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000);
2884 return d;
2885 }
2886 if(str instanceof Date) return str;
2887 if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
2888 var s = d.getFullYear();
2889 if(str.indexOf("" + s) > -1) return d;
2890 d.setFullYear(d.getFullYear() + 100); return d;
2891 }
2892 var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
2893 var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
2894 if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000);
2895 return out;
2896}
2897
2898function cc2str(arr/*:Array<number>*/)/*:string*/ {
2899 var o = "";
2900 for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
2901 return o;
2902}
2903
2904function dup(o/*:any*/)/*:any*/ {
2905 if(typeof JSON != 'undefined' && !Array.isArray(o)) return JSON.parse(JSON.stringify(o));
2906 if(typeof o != 'object' || o == null) return o;
2907 if(o instanceof Date) return new Date(o.getTime());
2908 var out = {};
2909 for(var k in o) if(Object.prototype.hasOwnProperty.call(o, k)) out[k] = dup(o[k]);
2910 return out;
2911}
2912
2913function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; }
2914
2915/* TODO: stress test */
2916function fuzzynum(s/*:string*/)/*:number*/ {
2917 var v/*:number*/ = Number(s);
2918 if(isFinite(v)) return v;
2919 if(!isNaN(v)) return NaN;
2920 if(!/\d/.test(s)) return v;
2921 var wt = 1;
2922 var ss = s.replace(/([\d]),([\d])/g,"$1$2").replace(/[$]/g,"").replace(/[%]/g, function() { wt *= 100; return "";});
2923 if(!isNaN(v = Number(ss))) return v / wt;
2924 ss = ss.replace(/[(](.*)[)]/,function($$, $1) { wt = -wt; return $1;});
2925 if(!isNaN(v = Number(ss))) return v / wt;
2926 return v;
2927}
2928function fuzzydate(s/*:string*/)/*:Date*/ {
2929 var o = new Date(s), n = new Date(NaN);
2930 var y = o.getYear(), m = o.getMonth(), d = o.getDate();
2931 if(isNaN(d)) return n;
2932 if(y < 0 || y > 8099) return n;
2933 if((m > 0 || d > 1) && y != 101) return o;
2934 if(s.toLowerCase().match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) return o;
2935 if(s.match(/[^-0-9:,\/\\]/)) return n;
2936 return o;
2937}
2938
2939var safe_split_regex = "abacaba".split(/(:?b)/i).length == 5;
2940function split_regex(str/*:string*/, re, def/*:string*/)/*:Array<string>*/ {
2941 if(safe_split_regex || typeof re == "string") return str.split(re);
2942 var p = str.split(re), o = [p[0]];
2943 for(var i = 1; i < p.length; ++i) { o.push(def); o.push(p[i]); }
2944 return o;
2945}
2946function getdatastr(data)/*:?string*/ {
2947 if(!data) return null;
2948 if(data.data) return debom(data.data);
2949 if(data.asNodeBuffer && has_buf) return debom(data.asNodeBuffer().toString('binary'));
2950 if(data.asBinary) return debom(data.asBinary());
2951 if(data._data && data._data.getContent) return debom(cc2str(Array.prototype.slice.call(data._data.getContent(),0)));
2952 if(data.content && data.type) return debom(cc2str(data.content));
2953 return null;
2954}
2955
2956function getdatabin(data) {
2957 if(!data) return null;
2958 if(data.data) return char_codes(data.data);
2959 if(data.asNodeBuffer && has_buf) return data.asNodeBuffer();
2960 if(data._data && data._data.getContent) {
2961 var o = data._data.getContent();
2962 if(typeof o == "string") return char_codes(o);
2963 return Array.prototype.slice.call(o);
2964 }
2965 if(data.content && data.type) return data.content;
2966 return null;
2967}
2968
2969function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getdatabin(data) : getdatastr(data); }
2970
2971/* Part 2 Section 10.1.2 "Mapping Content Types" Names are case-insensitive */
2972/* OASIS does not comment on filename case sensitivity */
2973function safegetzipfile(zip, file/*:string*/) {
2974 var k = zip.FullPaths || keys(zip.files);
2975 var f = file.toLowerCase().replace(/[\/]/g, '\\'), g = f.replace(/\\/g,'\/');
2976 for(var i=0; i<k.length; ++i) {
2977 var n = k[i].replace(/^Root Entry[\/]/,"").toLowerCase();
2978 if(f == n || g == n) return zip.files ? zip.files[k[i]] : zip.FileIndex[i];
2979 }
2980 return null;
2981}
2982
2983function getzipfile(zip, file/*:string*/) {
2984 var o = safegetzipfile(zip, file);
2985 if(o == null) throw new Error("Cannot find file " + file + " in zip");
2986 return o;
2987}
2988
2989function getzipdata(zip, file/*:string*/, safe/*:?boolean*/)/*:any*/ {
2990 if(!safe) return getdata(getzipfile(zip, file));
2991 if(!file) return null;
2992 try { return getzipdata(zip, file); } catch(e) { return null; }
2993}
2994
2995function getzipstr(zip, file/*:string*/, safe/*:?boolean*/)/*:?string*/ {
2996 if(!safe) return getdatastr(getzipfile(zip, file));
2997 if(!file) return null;
2998 try { return getzipstr(zip, file); } catch(e) { return null; }
2999}
3000
3001function zipentries(zip) {
3002 var k = zip.FullPaths || keys(zip.files), o = [];
3003 for(var i = 0; i < k.length; ++i) if(k[i].slice(-1) != '/') o.push(k[i].replace(/^Root Entry[\/]/, ""));
3004 return o.sort();
3005}
3006
3007function zip_add_file(zip, path, content) {
3008 if(zip.FullPaths) CFB.utils.cfb_add(zip, path, typeof content == "string" ? (has_buf ? Buffer_from(content) : s2a(utf8write(content))) : content);
3009 else zip.file(path, content);
3010}
3011
3012var jszip;
3013
3014function zip_new() {
3015 return CFB.utils.cfb_new();
3016}
3017
3018function zip_read(d, o) {
3019 var zip;
3020 switch(o.type) {
3021 case "base64": zip = CFB.read(d, { type: "base64" }); break;
3022 case "binary": zip = CFB.read(d, { type: "binary" }); break;
3023 case "buffer": case "array": zip = CFB.read(d, { type: "buffer" }); break;
3024 default: throw new Error("Unrecognized type " + o.type);
3025 }
3026 return zip;
3027}
3028
3029function resolve_path(path/*:string*/, base/*:string*/)/*:string*/ {
3030 if(path.charAt(0) == "/") return path.slice(1);
3031 var result = base.split('/');
3032 if(base.slice(-1) != "/") result.pop(); // folder path
3033 var target = path.split('/');
3034 while (target.length !== 0) {
3035 var step = target.shift();
3036 if (step === '..') result.pop();
3037 else if (step !== '.') result.push(step);
3038 }
3039 return result.join('/');
3040}
3041var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
3042var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
3043var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s*[\/\?]?>/mg;
3044
3045if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
3046var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
3047function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/, skip_LC/*:?boolean*/)/*:any*/ {
3048 var z = ({}/*:any*/);
3049 var eq = 0, c = 0;
3050 for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
3051 if(!skip_root) z[0] = tag.slice(0, eq);
3052 if(eq === tag.length) return z;
3053 var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1;
3054 if(m) for(i = 0; i != m.length; ++i) {
3055 cc = m[i];
3056 for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
3057 q = cc.slice(0,c).trim();
3058 while(cc.charCodeAt(c+1) == 32) ++c;
3059 quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0;
3060 v = cc.slice(c+1+quot, cc.length-quot);
3061 for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
3062 if(j===q.length) {
3063 if(q.indexOf("_") > 0) q = q.slice(0, q.indexOf("_")); // from ods
3064 z[q] = v;
3065 if(!skip_LC) z[q.toLowerCase()] = v;
3066 }
3067 else {
3068 var k = (j===5 && q.slice(0,5)==="xmlns"?"xmlns":"")+q.slice(j+1);
3069 if(z[k] && q.slice(j-3,j) == "ext") continue; // from ods
3070 z[k] = v;
3071 if(!skip_LC) z[k.toLowerCase()] = v;
3072 }
3073 }
3074 return z;
3075}
3076function strip_ns(x/*:string*/)/*:string*/ { return x.replace(nsregex2, "<$1"); }
3077
3078var encodings = {
3079 '&quot;': '"',
3080 '&apos;': "'",
3081 '&gt;': '>',
3082 '&lt;': '<',
3083 '&amp;': '&'
3084};
3085var rencoding = evert(encodings);
3086//var rencstr = "&<>'\"".split("");
3087
3088// TODO: CP remap (need to read file version to determine OS)
3089var unescapexml/*:StringConv*/ = (function() {
3090 /* 22.4.2.4 bstr (Basic String) */
3091 var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig;
3092 return function unescapexml(text/*:string*/)/*:string*/ {
3093 var s = text + '', i = s.indexOf("<![CDATA[");
3094 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));});
3095 var j = s.indexOf("]]>");
3096 return unescapexml(s.slice(0, i)) + s.slice(i+9,j) + unescapexml(s.slice(j+3));
3097 };
3098})();
3099
3100var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
3101function escapexml(text/*:string*/)/*:string*/{
3102 var s = text + '';
3103 return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";});
3104}
3105function escapexmltag(text/*:string*/)/*:string*/{ return escapexml(text).replace(/ /g,"_x0020_"); }
3106
3107var htmlcharegex = /[\u0000-\u001f]/g;
3108function escapehtml(text/*:string*/)/*:string*/{
3109 var s = text + '';
3110 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) + ";"; });
3111}
3112
3113function escapexlml(text/*:string*/)/*:string*/{
3114 var s = text + '';
3115 return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; });
3116}
3117
3118/* TODO: handle codepages */
3119var xlml_fixstr/*:StringConv*/ = (function() {
3120 var entregex = /&#(\d+);/g;
3121 function entrepl($$/*:string*/,$1/*:string*/)/*:string*/ { return String.fromCharCode(parseInt($1,10)); }
3122 return function xlml_fixstr(str/*:string*/)/*:string*/ { return str.replace(entregex,entrepl); };
3123})();
3124var xlml_unfixstr/*:StringConv*/ = (function() {
3125 return function xlml_unfixstr(str/*:string*/)/*:string*/ { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); };
3126})();
3127
3128function parsexmlbool(value/*:any*/)/*:boolean*/ {
3129 switch(value) {
3130 case 1: case true: case '1': case 'true': case 'TRUE': return true;
3131 /* case '0': case 'false': case 'FALSE':*/
3132 default: return false;
3133 }
3134}
3135
3136var utf8read/*:StringConv*/ = function utf8reada(orig/*:string*/)/*:string*/ {
3137 var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
3138 while (i < orig.length) {
3139 c = orig.charCodeAt(i++);
3140 if (c < 128) { out += String.fromCharCode(c); continue; }
3141 d = orig.charCodeAt(i++);
3142 if (c>191 && c<224) { f = ((c & 31) << 6); f |= (d & 63); out += String.fromCharCode(f); continue; }
3143 e = orig.charCodeAt(i++);
3144 if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; }
3145 f = orig.charCodeAt(i++);
3146 w = (((c & 7) << 18) | ((d & 63) << 12) | ((e & 63) << 6) | (f & 63))-65536;
3147 out += String.fromCharCode(0xD800 + ((w>>>10)&1023));
3148 out += String.fromCharCode(0xDC00 + (w&1023));
3149 }
3150 return out;
3151};
3152
3153var utf8write/*:StringConv*/ = function(orig/*:string*/)/*:string*/ {
3154 var out/*:Array<string>*/ = [], i = 0, c = 0, d = 0;
3155 while(i < orig.length) {
3156 c = orig.charCodeAt(i++);
3157 switch(true) {
3158 case c < 128: out.push(String.fromCharCode(c)); break;
3159 case c < 2048:
3160 out.push(String.fromCharCode(192 + (c >> 6)));
3161 out.push(String.fromCharCode(128 + (c & 63)));
3162 break;
3163 case c >= 55296 && c < 57344:
3164 c -= 55296; d = orig.charCodeAt(i++) - 56320 + (c<<10);
3165 out.push(String.fromCharCode(240 + ((d >>18) & 7)));
3166 out.push(String.fromCharCode(144 + ((d >>12) & 63)));
3167 out.push(String.fromCharCode(128 + ((d >> 6) & 63)));
3168 out.push(String.fromCharCode(128 + (d & 63)));
3169 break;
3170 default:
3171 out.push(String.fromCharCode(224 + (c >> 12)));
3172 out.push(String.fromCharCode(128 + ((c >> 6) & 63)));
3173 out.push(String.fromCharCode(128 + (c & 63)));
3174 }
3175 }
3176 return out.join("");
3177};
3178
3179if(has_buf) {
3180 var utf8readb = function utf8readb(data) {
3181 var out = Buffer.alloc(2*data.length), w, i, j = 1, k = 0, ww=0, c;
3182 for(i = 0; i < data.length; i+=j) {
3183 j = 1;
3184 if((c=data.charCodeAt(i)) < 128) w = c;
3185 else if(c < 224) { w = (c&31)*64+(data.charCodeAt(i+1)&63); j=2; }
3186 else if(c < 240) { w=(c&15)*4096+(data.charCodeAt(i+1)&63)*64+(data.charCodeAt(i+2)&63); j=3; }
3187 else { j = 4;
3188 w = (c & 7)*262144+(data.charCodeAt(i+1)&63)*4096+(data.charCodeAt(i+2)&63)*64+(data.charCodeAt(i+3)&63);
3189 w -= 65536; ww = 0xD800 + ((w>>>10)&1023); w = 0xDC00 + (w&1023);
3190 }
3191 if(ww !== 0) { out[k++] = ww&255; out[k++] = ww>>>8; ww = 0; }
3192 out[k++] = w%256; out[k++] = w>>>8;
3193 }
3194 return out.slice(0,k).toString('ucs2');
3195 };
3196 var corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3";
3197 if(utf8read(corpus) == utf8readb(corpus)) utf8read = utf8readb;
3198 var utf8readc = function utf8readc(data) { return Buffer_from(data, 'binary').toString('utf8'); };
3199 if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
3200
3201 utf8write = function(data) { return Buffer_from(data, 'utf8').toString("binary"); };
3202}
3203
3204// matches <foo>...</foo> extracts content
3205var matchtag = (function() {
3206 var mtcache/*:{[k:string]:RegExp}*/ = ({}/*:any*/);
3207 return function matchtag(f/*:string*/,g/*:?string*/)/*:RegExp*/ {
3208 var t = f+"|"+(g||"");
3209 if(mtcache[t]) return mtcache[t];
3210 return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([\\s\\S]*?)</(?:\\w+:)?'+f+'>',((g||"")/*:any*/)));
3211 };
3212})();
3213
3214var htmldecode/*:{(s:string):string}*/ = (function() {
3215 var entities/*:Array<[RegExp, string]>*/ = [
3216 ['nbsp', ' '], ['middot', '·'],
3217 ['quot', '"'], ['apos', "'"], ['gt', '>'], ['lt', '<'], ['amp', '&']
3218 ].map(function(x/*:[string, string]*/) { return [new RegExp('&' + x[0] + ';', "ig"), x[1]]; });
3219 return function htmldecode(str/*:string*/)/*:string*/ {
3220 var o = str
3221 // Remove new lines and spaces from start of content
3222 .replace(/^[\t\n\r ]+/, "")
3223 // Remove new lines and spaces from end of content
3224 .replace(/[\t\n\r ]+$/,"")
3225 // Added line which removes any white space characters after and before html tags
3226 .replace(/>\s+/g,">").replace(/\s+</g,"<")
3227 // Replace remaining new lines and spaces with space
3228 .replace(/[\t\n\r ]+/g, " ")
3229 // Replace <br> tags with new lines
3230 .replace(/<\s*[bB][rR]\s*\/?>/g,"\n")
3231 // Strip HTML elements
3232 .replace(/<[^>]*>/g,"");
3233 for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]);
3234 return o;
3235 };
3236})();
3237
3238var vtregex = (function(){ var vt_cache = {};
3239 return function vt_regex(bt) {
3240 if(vt_cache[bt] !== undefined) return vt_cache[bt];
3241 return (vt_cache[bt] = new RegExp("<(?:vt:)?" + bt + ">([\\s\\S]*?)</(?:vt:)?" + bt + ">", 'g') );
3242};})();
3243var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^>]*)>([\s\S]*)</;
3244function parseVector(data/*:string*/, opts)/*:Array<{v:string,t:string}>*/ {
3245 var h = parsexmltag(data);
3246
3247 var matches/*:Array<string>*/ = data.match(vtregex(h.baseType))||[];
3248 var res/*:Array<any>*/ = [];
3249 if(matches.length != h.size) {
3250 if(opts.WTF) throw new Error("unexpected vector length " + matches.length + " != " + h.size);
3251 return res;
3252 }
3253 matches.forEach(function(x/*:string*/) {
3254 var v = x.replace(vtvregex,"").match(vtmregex);
3255 if(v) res.push({v:utf8read(v[2]), t:v[1]});
3256 });
3257 return res;
3258}
3259
3260var wtregex = /(^\s|\s$|\n)/;
3261function writetag(f/*:string*/,g/*:string*/)/*:string*/ { return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>'; }
3262
3263function wxt_helper(h)/*:string*/ { return keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join(""); }
3264function writextag(f/*:string*/,g/*:?string*/,h) { return '<' + f + ((h != null) ? wxt_helper(h) : "") + ((g != null) ? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';}
3265
3266function write_w3cdtf(d/*:Date*/, t/*:?boolean*/)/*:string*/ { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } return ""; }
3267
3268function write_vt(s, xlsx/*:?boolean*/)/*:string*/ {
3269 switch(typeof s) {
3270 case 'string':
3271 var o = writextag('vt:lpwstr', escapexml(s));
3272 if(xlsx) o = o.replace(/&quot;/g, "_x0022_");
3273 return o;
3274 case 'number': return writextag((s|0)==s?'vt:i4':'vt:r8', escapexml(String(s)));
3275 case 'boolean': return writextag('vt:bool',s?'true':'false');
3276 }
3277 if(s instanceof Date) return writextag('vt:filetime', write_w3cdtf(s));
3278 throw new Error("Unable to serialize " + s);
3279}
3280
3281var XMLNS = ({
3282 'dc': 'http://purl.org/dc/elements/1.1/',
3283 'dcterms': 'http://purl.org/dc/terms/',
3284 'dcmitype': 'http://purl.org/dc/dcmitype/',
3285 'mx': 'http://schemas.microsoft.com/office/mac/excel/2008/main',
3286 'r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
3287 'sjs': 'http://schemas.openxmlformats.org/package/2006/sheetjs/core-properties',
3288 'vt': 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes',
3289 'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
3290 'xsd': 'http://www.w3.org/2001/XMLSchema'
3291}/*:any*/);
3292
3293XMLNS.main = [
3294 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
3295 'http://purl.oclc.org/ooxml/spreadsheetml/main',
3296 'http://schemas.microsoft.com/office/excel/2006/main',
3297 'http://schemas.microsoft.com/office/excel/2006/2'
3298];
3299
3300var XLMLNS = ({
3301 'o': 'urn:schemas-microsoft-com:office:office',
3302 'x': 'urn:schemas-microsoft-com:office:excel',
3303 'ss': 'urn:schemas-microsoft-com:office:spreadsheet',
3304 'dt': 'uuid:C2F41010-65B3-11d1-A29F-00AA00C14882',
3305 'mv': 'http://macVmlSchemaUri',
3306 'v': 'urn:schemas-microsoft-com:vml',
3307 'html': 'http://www.w3.org/TR/REC-html40'
3308}/*:any*/);
3309function read_double_le(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ {
3310 var s = 1 - 2 * (b[idx + 7] >>> 7);
3311 var e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 0x0f);
3312 var m = (b[idx+6]&0x0f);
3313 for(var i = 5; i >= 0; --i) m = m * 256 + b[idx + i];
3314 if(e == 0x7ff) return m == 0 ? (s * Infinity) : NaN;
3315 if(e == 0) e = -1022;
3316 else { e -= 1023; m += Math.pow(2,52); }
3317 return s * Math.pow(2, e - 52) * m;
3318}
3319
3320function write_double_le(b/*:RawBytes|CFBlob*/, v/*:number*/, idx/*:number*/) {
3321 var bs = ((((v < 0) || (1/v == -Infinity)) ? 1 : 0) << 7), e = 0, m = 0;
3322 var av = bs ? (-v) : v;
3323 if(!isFinite(av)) { e = 0x7ff; m = isNaN(v) ? 0x6969 : 0; }
3324 else if(av == 0) e = m = 0;
3325 else {
3326 e = Math.floor(Math.log(av) / Math.LN2);
3327 m = av * Math.pow(2, 52 - e);
3328 if((e <= -1023) && (!isFinite(m) || (m < Math.pow(2,52)))) { e = -1022; }
3329 else { m -= Math.pow(2,52); e+=1023; }
3330 }
3331 for(var i = 0; i <= 5; ++i, m/=256) b[idx + i] = m & 0xff;
3332 b[idx + 6] = ((e & 0x0f) << 4) | (m & 0xf);
3333 b[idx + 7] = (e >> 4) | bs;
3334}
3335
3336var __toBuffer = function(bufs/*:Array<Array<RawBytes> >*/)/*:RawBytes*/ { 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; };
3337var ___toBuffer = __toBuffer;
3338var __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join("").replace(chr0,''); };
3339var ___utf16le = __utf16le;
3340var __hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); };
3341var ___hexlify = __hexlify;
3342var __utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
3343var ___utf8 = __utf8;
3344var __lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
3345var ___lpstr = __lpstr;
3346var __cpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
3347var ___cpstr = __cpstr;
3348var __lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
3349var ___lpwstr = __lpwstr;
3350var __lpp4, ___lpp4;
3351__lpp4 = ___lpp4 = function lpp4_(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
3352var __8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
3353var ___8lpp4 = __8lpp4;
3354var __double, ___double;
3355__double = ___double = function(b/*:RawBytes|CFBlob*/, idx/*:number*/) { return read_double_le(b, idx);};
3356var is_buf = function is_buf_a(a) { return Array.isArray(a); };
3357
3358if(has_buf/*:: && typeof Buffer !== 'undefined'*/) {
3359 __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___utf16le(b,s,e); return b.toString('utf16le',s,e).replace(chr0,'')/*.replace(chr1,'!')*/; };
3360 __hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { return Buffer.isBuffer(b)/*:: && b instanceof Buffer*/ ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
3361 __lpstr = function lpstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
3362 __cpstr = function cpstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___cpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
3363 __lpwstr = function lpwstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
3364 __lpp4 = function lpp4_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);};
3365 __8lpp4 = function lpp4_8b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);};
3366 __utf8 = function utf8_b(b/*:RawBytes|CFBlob*/, s/*:number*/, e/*:number*/) { return (Buffer.isBuffer(b)/*:: && (b instanceof Buffer)*/) ? b.toString('utf8',s,e) : ___utf8(b,s,e); };
3367 __toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);};
3368 bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); };
3369 __double = function double_(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(Buffer.isBuffer(b)/*::&& b instanceof Buffer*/) return b.readDoubleLE(i); return ___double(b,i); };
3370 is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); };
3371}
3372
3373/* from js-xls */
3374if(typeof cptable !== 'undefined') {
3375 __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(1200, b.slice(s,e)).replace(chr0, ''); };
3376 __utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(65001, b.slice(s,e)); };
3377 __lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_ansi, b.slice(i+4, i+4+len-1)) : "";};
3378 __cpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";};
3379 __lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";};
3380 __lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";};
3381 __8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";};
3382}
3383
3384var __readUInt8 = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx]; };
3385var __readUInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx+1]*(1<<8))+b[idx]; };
3386var __readInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { var u = (b[idx+1]*(1<<8))+b[idx]; return (u < 0x8000) ? u : ((0xffff - u + 1) * -1); };
3387var __readUInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
3388var __readInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
3389var __readInt32BE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx]<<24)|(b[idx+1]<<16)|(b[idx+2]<<8)|b[idx+3]; };
3390
3391function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
3392 var o="", oI/*:: :number = 0*/, oR, oo=[], w, vv, i, loc;
3393 switch(t) {
3394 case 'dbcs':
3395 loc = this.l;
3396 if(has_buf && Buffer.isBuffer(this)) o = this.slice(this.l, this.l+2*size).toString("utf16le");
3397 else for(i = 0; i < size; ++i) { o+=String.fromCharCode(__readUInt16LE(this, loc)); loc+=2; }
3398 size *= 2;
3399 break;
3400
3401 case 'utf8': o = __utf8(this, this.l, this.l + size); break;
3402 case 'utf16le': size *= 2; o = __utf16le(this, this.l, this.l + size); break;
3403
3404 case 'wstr':
3405 if(typeof cptable !== 'undefined') o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l+2*size));
3406 else return ReadShift.call(this, size, 'dbcs');
3407 size = 2 * size; break;
3408
3409 /* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */
3410 case 'lpstr-ansi': o = __lpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break;
3411 case 'lpstr-cp': o = __cpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break;
3412 /* [MS-OLEDS] 2.1.5 LengthPrefixedUnicodeString */
3413 case 'lpwstr': o = __lpwstr(this, this.l); size = 4 + 2 * __readUInt32LE(this, this.l); break;
3414 /* [MS-OFFCRYPTO] 2.1.2 Length-Prefixed Padded Unicode String (UNICODE-LP-P4) */
3415 case 'lpp4': size = 4 + __readUInt32LE(this, this.l); o = __lpp4(this, this.l); if(size & 0x02) size += 2; break;
3416 /* [MS-OFFCRYPTO] 2.1.3 Length-Prefixed UTF-8 String (UTF-8-LP-P4) */
3417 case '8lpp4': size = 4 + __readUInt32LE(this, this.l); o = __8lpp4(this, this.l); if(size & 0x03) size += 4 - (size & 0x03); break;
3418
3419 case 'cstr': size = 0; o = "";
3420 while((w=__readUInt8(this, this.l + size++))!==0) oo.push(_getchar(w));
3421 o = oo.join(""); break;
3422 case '_wstr': size = 0; o = "";
3423 while((w=__readUInt16LE(this,this.l +size))!==0){oo.push(_getchar(w));size+=2;}
3424 size+=2; o = oo.join(""); break;
3425
3426 /* sbcs and dbcs support continue records in the SST way TODO codepages */
3427 case 'dbcs-cont': o = ""; loc = this.l;
3428 for(i = 0; i < size; ++i) {
3429 if(this.lens && this.lens.indexOf(loc) !== -1) {
3430 w = __readUInt8(this, loc);
3431 this.l = loc + 1;
3432 vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont');
3433 return oo.join("") + vv;
3434 }
3435 oo.push(_getchar(__readUInt16LE(this, loc)));
3436 loc+=2;
3437 } o = oo.join(""); size *= 2; break;
3438
3439 case 'cpstr':
3440 if(typeof cptable !== 'undefined') {
3441 o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l + size));
3442 break;
3443 }
3444 /* falls through */
3445 case 'sbcs-cont': o = ""; loc = this.l;
3446 for(i = 0; i != size; ++i) {
3447 if(this.lens && this.lens.indexOf(loc) !== -1) {
3448 w = __readUInt8(this, loc);
3449 this.l = loc + 1;
3450 vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont');
3451 return oo.join("") + vv;
3452 }
3453 oo.push(_getchar(__readUInt8(this, loc)));
3454 loc+=1;
3455 } o = oo.join(""); break;
3456
3457 default:
3458 switch(size) {
3459 case 1: oI = __readUInt8(this, this.l); this.l++; return oI;
3460 case 2: oI = (t === 'i' ? __readInt16LE : __readUInt16LE)(this, this.l); this.l += 2; return oI;
3461 case 4: case -4:
3462 if(t === 'i' || ((this[this.l+3] & 0x80)===0)) { oI = ((size > 0) ? __readInt32LE : __readInt32BE)(this, this.l); this.l += 4; return oI; }
3463 else { oR = __readUInt32LE(this, this.l); this.l += 4; } return oR;
3464 case 8: case -8:
3465 if(t === 'f') {
3466 if(size == 8) oR = __double(this, this.l);
3467 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);
3468 this.l += 8; return oR;
3469 } else size = 8;
3470 /* falls through */
3471 case 16: o = __hexlify(this, this.l, size); break;
3472 }}
3473 this.l+=size; return o;
3474}
3475
3476var __writeUInt32LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); b[idx+2] = ((val >>> 16) & 0xFF); b[idx+3] = ((val >>> 24) & 0xFF); };
3477var __writeInt32LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); };
3478var __writeUInt16LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); };
3479
3480function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/)/*:any*/ {
3481 var size = 0, i = 0;
3482 if(f === 'dbcs') {
3483 /*:: if(typeof val !== 'string') throw new Error("unreachable"); */
3484 for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i);
3485 size = 2 * val.length;
3486 } else if(f === 'sbcs') {
3487 if(typeof cptable !== 'undefined' && current_ansi == 874) {
3488 /* TODO: use tables directly, don't encode */
3489 /*:: if(typeof val !== "string") throw new Error("unreachable"); */
3490 for(i = 0; i != val.length; ++i) {
3491 var cppayload = cptable.utils.encode(current_ansi, val.charAt(i));
3492 this[this.l + i] = cppayload[0];
3493 }
3494 } else {
3495 /*:: if(typeof val !== 'string') throw new Error("unreachable"); */
3496 val = val.replace(/[^\x00-\x7F]/g, "_");
3497 /*:: if(typeof val !== 'string') throw new Error("unreachable"); */
3498 for(i = 0; i != val.length; ++i) this[this.l + i] = (val.charCodeAt(i) & 0xFF);
3499 }
3500 size = val.length;
3501 } else if(f === 'hex') {
3502 for(; i < t; ++i) {
3503 /*:: if(typeof val !== "string") throw new Error("unreachable"); */
3504 this[this.l++] = (parseInt(val.slice(2*i, 2*i+2), 16)||0);
3505 } return this;
3506 } else if(f === 'utf16le') {
3507 /*:: if(typeof val !== "string") throw new Error("unreachable"); */
3508 var end/*:number*/ = Math.min(this.l + t, this.length);
3509 for(i = 0; i < Math.min(val.length, t); ++i) {
3510 var cc = val.charCodeAt(i);
3511 this[this.l++] = (cc & 0xff);
3512 this[this.l++] = (cc >> 8);
3513 }
3514 while(this.l < end) this[this.l++] = 0;
3515 return this;
3516 } else /*:: if(typeof val === 'number') */ switch(t) {
3517 case 1: size = 1; this[this.l] = val&0xFF; break;
3518 case 2: size = 2; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; break;
3519 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;
3520 case 4: size = 4; __writeUInt32LE(this, val, this.l); break;
3521 case 8: size = 8; if(f === 'f') { write_double_le(this, val, this.l); break; }
3522 /* falls through */
3523 case 16: break;
3524 case -4: size = 4; __writeInt32LE(this, val, this.l); break;
3525 }
3526 this.l += size; return this;
3527}
3528
3529function CheckField(hexstr/*:string*/, fld/*:string*/)/*:void*/ {
3530 var m = __hexlify(this,this.l,hexstr.length>>1);
3531 if(m !== hexstr) throw new Error(fld + 'Expected ' + hexstr + ' saw ' + m);
3532 this.l += hexstr.length>>1;
3533}
3534
3535function prep_blob(blob, pos/*:number*/)/*:void*/ {
3536 blob.l = pos;
3537 blob.read_shift = /*::(*/ReadShift/*:: :any)*/;
3538 blob.chk = CheckField;
3539 blob.write_shift = WriteShift;
3540}
3541
3542function parsenoop(blob, length/*:: :number, opts?:any */) { blob.l += length; }
3543
3544function new_buf(sz/*:number*/)/*:Block*/ {
3545 var o = new_raw_buf(sz);
3546 prep_blob(o, 0);
3547 return o;
3548}
3549
3550/* [MS-XLSB] 2.1.4 Record */
3551function recordhopper(data, cb/*:RecordHopperCB*/, opts/*:?any*/) {
3552 if(!data) return;
3553 var tmpbyte, cntbyte, length;
3554 prep_blob(data, data.l || 0);
3555 var L = data.length, RT = 0, tgt = 0;
3556 while(data.l < L) {
3557 RT = data.read_shift(1);
3558 if(RT & 0x80) RT = (RT & 0x7F) + ((data.read_shift(1) & 0x7F)<<7);
3559 var R = XLSBRecordEnum[RT] || XLSBRecordEnum[0xFFFF];
3560 tmpbyte = data.read_shift(1);
3561 length = tmpbyte & 0x7F;
3562 for(cntbyte = 1; cntbyte <4 && (tmpbyte & 0x80); ++cntbyte) length += ((tmpbyte = data.read_shift(1)) & 0x7F)<<(7*cntbyte);
3563 tgt = data.l + length;
3564 var d = R.f && R.f(data, length, opts);
3565 data.l = tgt;
3566 if(cb(d, R.n, RT)) return;
3567 }
3568}
3569
3570/* control buffer usage for fixed-length buffers */
3571function buf_array()/*:BufArray*/ {
3572 var bufs/*:Array<Block>*/ = [], blksz = has_buf ? 256 : 2048;
3573 var newblk = function ba_newblk(sz/*:number*/)/*:Block*/ {
3574 var o/*:Block*/ = (new_buf(sz)/*:any*/);
3575 prep_blob(o, 0);
3576 return o;
3577 };
3578
3579 var curbuf/*:Block*/ = newblk(blksz);
3580
3581 var endbuf = function ba_endbuf() {
3582 if(!curbuf) return;
3583 if(curbuf.length > curbuf.l) { curbuf = curbuf.slice(0, curbuf.l); curbuf.l = curbuf.length; }
3584 if(curbuf.length > 0) bufs.push(curbuf);
3585 curbuf = null;
3586 };
3587
3588 var next = function ba_next(sz/*:number*/)/*:Block*/ {
3589 if(curbuf && (sz < (curbuf.length - curbuf.l))) return curbuf;
3590 endbuf();
3591 return (curbuf = newblk(Math.max(sz+1, blksz)));
3592 };
3593
3594 var end = function ba_end() {
3595 endbuf();
3596 return __toBuffer([bufs]);
3597 };
3598
3599 var push = function ba_push(buf) { endbuf(); curbuf = buf; if(curbuf.l == null) curbuf.l = curbuf.length; next(blksz); };
3600
3601 return ({ next:next, push:push, end:end, _bufs:bufs }/*:any*/);
3602}
3603
3604function write_record(ba/*:BufArray*/, type/*:string*/, payload, length/*:?number*/) {
3605 var t/*:number*/ = +XLSBRE[type], l;
3606 if(isNaN(t)) return; // TODO: throw something here?
3607 if(!length) length = XLSBRecordEnum[t].p || (payload||[]).length || 0;
3608 l = 1 + (t >= 0x80 ? 1 : 0) + 1/* + length*/;
3609 if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l;
3610 var o = ba.next(l);
3611 if(t <= 0x7F) o.write_shift(1, t);
3612 else {
3613 o.write_shift(1, (t & 0x7F) + 0x80);
3614 o.write_shift(1, (t >> 7));
3615 }
3616 for(var i = 0; i != 4; ++i) {
3617 if(length >= 0x80) { o.write_shift(1, (length & 0x7F)+0x80); length >>= 7; }
3618 else { o.write_shift(1, length); break; }
3619 }
3620 if(/*:: length != null &&*/length > 0 && is_buf(payload)) ba.push(payload);
3621}
3622/* XLS ranges enforced */
3623function shift_cell_xls(cell/*:CellAddress*/, tgt/*:any*/, opts/*:?any*/)/*:CellAddress*/ {
3624 var out = dup(cell);
3625 if(tgt.s) {
3626 if(out.cRel) out.c += tgt.s.c;
3627 if(out.rRel) out.r += tgt.s.r;
3628 } else {
3629 if(out.cRel) out.c += tgt.c;
3630 if(out.rRel) out.r += tgt.r;
3631 }
3632 if(!opts || opts.biff < 12) {
3633 while(out.c >= 0x100) out.c -= 0x100;
3634 while(out.r >= 0x10000) out.r -= 0x10000;
3635 }
3636 return out;
3637}
3638
3639function shift_range_xls(cell, range, opts) {
3640 var out = dup(cell);
3641 out.s = shift_cell_xls(out.s, range.s, opts);
3642 out.e = shift_cell_xls(out.e, range.s, opts);
3643 return out;
3644}
3645
3646function encode_cell_xls(c/*:CellAddress*/, biff/*:number*/)/*:string*/ {
3647 if(c.cRel && c.c < 0) { c = dup(c); while(c.c < 0) c.c += (biff > 8) ? 0x4000 : 0x100; }
3648 if(c.rRel && c.r < 0) { c = dup(c); while(c.r < 0) c.r += (biff > 8) ? 0x100000 : ((biff > 5) ? 0x10000 : 0x4000); }
3649 var s = encode_cell(c);
3650 if(!c.cRel && c.cRel != null) s = fix_col(s);
3651 if(!c.rRel && c.rRel != null) s = fix_row(s);
3652 return s;
3653}
3654
3655function encode_range_xls(r, opts)/*:string*/ {
3656 if(r.s.r == 0 && !r.s.rRel) {
3657 if(r.e.r == (opts.biff >= 12 ? 0xFFFFF : (opts.biff >= 8 ? 0x10000 : 0x4000)) && !r.e.rRel) {
3658 return (r.s.cRel ? "" : "$") + encode_col(r.s.c) + ":" + (r.e.cRel ? "" : "$") + encode_col(r.e.c);
3659 }
3660 }
3661 if(r.s.c == 0 && !r.s.cRel) {
3662 if(r.e.c == (opts.biff >= 12 ? 0x3FFF : 0xFF) && !r.e.cRel) {
3663 return (r.s.rRel ? "" : "$") + encode_row(r.s.r) + ":" + (r.e.rRel ? "" : "$") + encode_row(r.e.r);
3664 }
3665 }
3666 return encode_cell_xls(r.s, opts.biff) + ":" + encode_cell_xls(r.e, opts.biff);
3667}
3668function decode_row(rowstr/*:string*/)/*:number*/ { return parseInt(unfix_row(rowstr),10) - 1; }
3669function encode_row(row/*:number*/)/*:string*/ { return "" + (row + 1); }
3670function fix_row(cstr/*:string*/)/*:string*/ { return cstr.replace(/([A-Z]|^)(\d+)$/,"$1$$$2"); }
3671function unfix_row(cstr/*:string*/)/*:string*/ { return cstr.replace(/\$(\d+)$/,"$1"); }
3672
3673function decode_col(colstr/*:string*/)/*:number*/ { var c = unfix_col(colstr), d = 0, i = 0; for(; i !== c.length; ++i) d = 26*d + c.charCodeAt(i) - 64; return d - 1; }
3674function encode_col(col/*:number*/)/*:string*/ { 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; }
3675function fix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^([A-Z])/,"$$$1"); }
3676function unfix_col(cstr/*:string*/)/*:string*/ { return cstr.replace(/^\$([A-Z])/,"$1"); }
3677
3678function split_cell(cstr/*:string*/)/*:Array<string>*/ { return cstr.replace(/(\$?[A-Z]*)(\$?\d*)/,"$1,$2").split(","); }
3679//function decode_cell(cstr/*:string*/)/*:CellAddress*/ { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; }
3680function decode_cell(cstr/*:string*/)/*:CellAddress*/ {
3681 var R = 0, C = 0;
3682 for(var i = 0; i < cstr.length; ++i) {
3683 var cc = cstr.charCodeAt(i);
3684 if(cc >= 48 && cc <= 57) R = 10 * R + (cc - 48);
3685 else if(cc >= 65 && cc <= 90) C = 26 * C + (cc - 64);
3686 }
3687 return { c: C - 1, r:R - 1 };
3688}
3689//function encode_cell(cell/*:CellAddress*/)/*:string*/ { return encode_col(cell.c) + encode_row(cell.r); }
3690function encode_cell(cell/*:CellAddress*/)/*:string*/ {
3691 var col = cell.c + 1;
3692 var s="";
3693 for(; col; col=((col-1)/26)|0) s = String.fromCharCode(((col-1)%26) + 65) + s;
3694 return s + (cell.r + 1);
3695}
3696function decode_range(range/*:string*/)/*:Range*/ {
3697 var idx = range.indexOf(":");
3698 if(idx == -1) return { s: decode_cell(range), e: decode_cell(range) };
3699 return { s: decode_cell(range.slice(0, idx)), e: decode_cell(range.slice(idx + 1)) };
3700}
3701/*# if only one arg, it is assumed to be a Range. If 2 args, both are cell addresses */
3702function encode_range(cs/*:CellAddrSpec|Range*/,ce/*:?CellAddrSpec*/)/*:string*/ {
3703 if(typeof ce === 'undefined' || typeof ce === 'number') {
3704/*:: if(!(cs instanceof Range)) throw "unreachable"; */
3705 return encode_range(cs.s, cs.e);
3706 }
3707/*:: if((cs instanceof Range)) throw "unreachable"; */
3708 if(typeof cs !== 'string') cs = encode_cell((cs/*:any*/));
3709 if(typeof ce !== 'string') ce = encode_cell((ce/*:any*/));
3710/*:: if(typeof cs !== 'string') throw "unreachable"; */
3711/*:: if(typeof ce !== 'string') throw "unreachable"; */
3712 return cs == ce ? cs : cs + ":" + ce;
3713}
3714
3715function safe_decode_range(range/*:string*/)/*:Range*/ {
3716 var o = {s:{c:0,r:0},e:{c:0,r:0}};
3717 var idx = 0, i = 0, cc = 0;
3718 var len = range.length;
3719 for(idx = 0; i < len; ++i) {
3720 if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
3721 idx = 26*idx + cc;
3722 }
3723 o.s.c = --idx;
3724
3725 for(idx = 0; i < len; ++i) {
3726 if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
3727 idx = 10*idx + cc;
3728 }
3729 o.s.r = --idx;
3730
3731 if(i === len || range.charCodeAt(++i) === 58) { o.e.c=o.s.c; o.e.r=o.s.r; return o; }
3732
3733 for(idx = 0; i != len; ++i) {
3734 if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
3735 idx = 26*idx + cc;
3736 }
3737 o.e.c = --idx;
3738
3739 for(idx = 0; i != len; ++i) {
3740 if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
3741 idx = 10*idx + cc;
3742 }
3743 o.e.r = --idx;
3744 return o;
3745}
3746
3747function safe_format_cell(cell/*:Cell*/, v/*:any*/) {
3748 var q = (cell.t == 'd' && v instanceof Date);
3749 if(cell.z != null) try { return (cell.w = SSF.format(cell.z, q ? datenum(v) : v)); } catch(e) { }
3750 try { return (cell.w = SSF.format((cell.XF||{}).numFmtId||(q ? 14 : 0), q ? datenum(v) : v)); } catch(e) { return ''+v; }
3751}
3752
3753function format_cell(cell/*:Cell*/, v/*:any*/, o/*:any*/) {
3754 if(cell == null || cell.t == null || cell.t == 'z') return "";
3755 if(cell.w !== undefined) return cell.w;
3756 if(cell.t == 'd' && !cell.z && o && o.dateNF) cell.z = o.dateNF;
3757 if(cell.t == "e") return BErr[cell.v] || cell.v;
3758 if(v == undefined) return safe_format_cell(cell, cell.v);
3759 return safe_format_cell(cell, v);
3760}
3761
3762function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ {
3763 var n = opts && opts.sheet ? opts.sheet : "Sheet1";
3764 var sheets = {}; sheets[n] = sheet;
3765 return { SheetNames: [n], Sheets: sheets };
3766}
3767
3768function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
3769 var o = opts || {};
3770 var dense = _ws ? Array.isArray(_ws) : o.dense;
3771 if(DENSE != null && dense == null) dense = DENSE;
3772 var ws/*:Worksheet*/ = _ws || (dense ? ([]/*:any*/) : ({}/*:any*/));
3773 var _R = 0, _C = 0;
3774 if(ws && o.origin != null) {
3775 if(typeof o.origin == 'number') _R = o.origin;
3776 else {
3777 var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
3778 _R = _origin.r; _C = _origin.c;
3779 }
3780 if(!ws["!ref"]) ws["!ref"] = "A1:A1";
3781 }
3782 var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/);
3783 if(ws['!ref']) {
3784 var _range = safe_decode_range(ws['!ref']);
3785 range.s.c = _range.s.c;
3786 range.s.r = _range.s.r;
3787 range.e.c = Math.max(range.e.c, _range.e.c);
3788 range.e.r = Math.max(range.e.r, _range.e.r);
3789 if(_R == -1) range.e.r = _R = _range.e.r + 1;
3790 }
3791 for(var R = 0; R != data.length; ++R) {
3792 if(!data[R]) continue;
3793 if(!Array.isArray(data[R])) throw new Error("aoa_to_sheet expects an array of arrays");
3794 for(var C = 0; C != data[R].length; ++C) {
3795 if(typeof data[R][C] === 'undefined') continue;
3796 var cell/*:Cell*/ = ({v: data[R][C] }/*:any*/);
3797 var __R = _R + R, __C = _C + C;
3798 if(range.s.r > __R) range.s.r = __R;
3799 if(range.s.c > __C) range.s.c = __C;
3800 if(range.e.r < __R) range.e.r = __R;
3801 if(range.e.c < __C) range.e.c = __C;
3802 if(data[R][C] && typeof data[R][C] === 'object' && !Array.isArray(data[R][C]) && !(data[R][C] instanceof Date)) cell = data[R][C];
3803 else {
3804 if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
3805 if(cell.v === null) {
3806 if(cell.f) cell.t = 'n';
3807 else if(o.nullError) { cell.t = 'e'; cell.v = 0; }
3808 else if(!o.sheetStubs) continue;
3809 else cell.t = 'z';
3810 }
3811 else if(typeof cell.v === 'number') cell.t = 'n';
3812 else if(typeof cell.v === 'boolean') cell.t = 'b';
3813 else if(cell.v instanceof Date) {
3814 cell.z = o.dateNF || SSF._table[14];
3815 if(o.cellDates) { cell.t = 'd'; cell.w = SSF.format(cell.z, datenum(cell.v)); }
3816 else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); }
3817 }
3818 else cell.t = 's';
3819 }
3820 if(dense) {
3821 if(!ws[__R]) ws[__R] = [];
3822 if(ws[__R][__C] && ws[__R][__C].z) cell.z = ws[__R][__C].z;
3823 ws[__R][__C] = cell;
3824 } else {
3825 var cell_ref = encode_cell(({c:__C,r:__R}/*:any*/));
3826 if(ws[cell_ref] && ws[cell_ref].z) cell.z = ws[cell_ref].z;
3827 ws[cell_ref] = cell;
3828 }
3829 }
3830 }
3831 if(range.s.c < 10000000) ws['!ref'] = encode_range(range);
3832 return ws;
3833}
3834function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { return sheet_add_aoa(null, data, opts); }
3835
3836function write_UInt32LE(x/*:number*/, o) {
3837 if (!o) o = new_buf(4);
3838 o.write_shift(4, x);
3839 return o;
3840}
3841
3842/* [MS-XLSB] 2.5.168 */
3843function parse_XLWideString(data/*::, length*/)/*:string*/ {
3844 var cchCharacters = data.read_shift(4);
3845 return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, 'dbcs');
3846}
3847function write_XLWideString(data/*:string*/, o) {
3848 var _null = false; if (o == null) { _null = true; o = new_buf(4 + 2 * data.length); }
3849 o.write_shift(4, data.length);
3850 if (data.length > 0) o.write_shift(0, data, 'dbcs');
3851 return _null ? o.slice(0, o.l) : o;
3852}
3853
3854/* [MS-XLSB] 2.5.91 */
3855//function parse_LPWideString(data/*::, length*/)/*:string*/ {
3856// var cchCharacters = data.read_shift(2);
3857// return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, "utf16le");
3858//}
3859
3860/* [MS-XLSB] 2.5.143 */
3861function parse_StrRun(data) {
3862 return { ich: data.read_shift(2), ifnt: data.read_shift(2) };
3863}
3864function write_StrRun(run, o) {
3865 if (!o) o = new_buf(4);
3866 o.write_shift(2, run.ich || 0);
3867 o.write_shift(2, run.ifnt || 0);
3868 return o;
3869}
3870
3871/* [MS-XLSB] 2.5.121 */
3872function parse_RichStr(data, length/*:number*/)/*:XLString*/ {
3873 var start = data.l;
3874 var flags = data.read_shift(1);
3875 var str = parse_XLWideString(data);
3876 var rgsStrRun = [];
3877 var z = ({ t: str, h: str }/*:any*/);
3878 if ((flags & 1) !== 0) { /* fRichStr */
3879 /* TODO: formatted string */
3880 var dwSizeStrRun = data.read_shift(4);
3881 for (var i = 0; i != dwSizeStrRun; ++i) rgsStrRun.push(parse_StrRun(data));
3882 z.r = rgsStrRun;
3883 }
3884 else z.r = [{ ich: 0, ifnt: 0 }];
3885 //if((flags & 2) !== 0) { /* fExtStr */
3886 // /* TODO: phonetic string */
3887 //}
3888 data.l = start + length;
3889 return z;
3890}
3891function write_RichStr(str/*:XLString*/, o/*:?Block*/)/*:Block*/ {
3892 /* TODO: formatted string */
3893 var _null = false; if (o == null) { _null = true; o = new_buf(15 + 4 * str.t.length); }
3894 o.write_shift(1, 0);
3895 write_XLWideString(str.t, o);
3896 return _null ? o.slice(0, o.l) : o;
3897}
3898/* [MS-XLSB] 2.4.328 BrtCommentText (RichStr w/1 run) */
3899var parse_BrtCommentText = parse_RichStr;
3900function write_BrtCommentText(str/*:XLString*/, o/*:?Block*/)/*:Block*/ {
3901 /* TODO: formatted string */
3902 var _null = false; if (o == null) { _null = true; o = new_buf(23 + 4 * str.t.length); }
3903 o.write_shift(1, 1);
3904 write_XLWideString(str.t, o);
3905 o.write_shift(4, 1);
3906 write_StrRun({ ich: 0, ifnt: 0 }, o);
3907 return _null ? o.slice(0, o.l) : o;
3908}
3909
3910/* [MS-XLSB] 2.5.9 */
3911function parse_XLSBCell(data)/*:any*/ {
3912 var col = data.read_shift(4);
3913 var iStyleRef = data.read_shift(2);
3914 iStyleRef += data.read_shift(1) << 16;
3915 data.l++; //var fPhShow = data.read_shift(1);
3916 return { c: col, iStyleRef: iStyleRef };
3917}
3918function write_XLSBCell(cell/*:any*/, o/*:?Block*/) {
3919 if (o == null) o = new_buf(8);
3920 o.write_shift(-4, cell.c);
3921 o.write_shift(3, cell.iStyleRef || cell.s);
3922 o.write_shift(1, 0); /* fPhShow */
3923 return o;
3924}
3925
3926/* Short XLSB Cell does not include column */
3927function parse_XLSBShortCell(data)/*:any*/ {
3928 var iStyleRef = data.read_shift(2);
3929 iStyleRef += data.read_shift(1) <<16;
3930 data.l++; //var fPhShow = data.read_shift(1);
3931 return { c:-1, iStyleRef: iStyleRef };
3932}
3933function write_XLSBShortCell(cell/*:any*/, o/*:?Block*/) {
3934 if(o == null) o = new_buf(4);
3935 o.write_shift(3, cell.iStyleRef || cell.s);
3936 o.write_shift(1, 0); /* fPhShow */
3937 return o;
3938}
3939
3940/* [MS-XLSB] 2.5.21 */
3941var parse_XLSBCodeName = parse_XLWideString;
3942var write_XLSBCodeName = write_XLWideString;
3943
3944/* [MS-XLSB] 2.5.166 */
3945function parse_XLNullableWideString(data/*::, length*/)/*:string*/ {
3946 var cchCharacters = data.read_shift(4);
3947 return cchCharacters === 0 || cchCharacters === 0xFFFFFFFF ? "" : data.read_shift(cchCharacters, 'dbcs');
3948}
3949function write_XLNullableWideString(data/*:string*/, o) {
3950 var _null = false; if (o == null) { _null = true; o = new_buf(127); }
3951 o.write_shift(4, data.length > 0 ? data.length : 0xFFFFFFFF);
3952 if (data.length > 0) o.write_shift(0, data, 'dbcs');
3953 return _null ? o.slice(0, o.l) : o;
3954}
3955
3956/* [MS-XLSB] 2.5.165 */
3957var parse_XLNameWideString = parse_XLWideString;
3958//var write_XLNameWideString = write_XLWideString;
3959
3960/* [MS-XLSB] 2.5.114 */
3961var parse_RelID = parse_XLNullableWideString;
3962var write_RelID = write_XLNullableWideString;
3963
3964
3965/* [MS-XLS] 2.5.217 ; [MS-XLSB] 2.5.122 */
3966function parse_RkNumber(data)/*:number*/ {
3967 var b = data.slice(data.l, data.l + 4);
3968 var fX100 = (b[0] & 1), fInt = (b[0] & 2);
3969 data.l += 4;
3970 b[0] &= 0xFC; // b[0] &= ~3;
3971 var RK = fInt === 0 ? __double([0, 0, 0, 0, b[0], b[1], b[2], b[3]], 0) : __readInt32LE(b, 0) >> 2;
3972 return fX100 ? (RK / 100) : RK;
3973}
3974function write_RkNumber(data/*:number*/, o) {
3975 if (o == null) o = new_buf(4);
3976 var fX100 = 0, fInt = 0, d100 = data * 100;
3977 if ((data == (data | 0)) && (data >= -(1 << 29)) && (data < (1 << 29))) { fInt = 1; }
3978 else if ((d100 == (d100 | 0)) && (d100 >= -(1 << 29)) && (d100 < (1 << 29))) { fInt = 1; fX100 = 1; }
3979 if (fInt) o.write_shift(-4, ((fX100 ? d100 : data) << 2) + (fX100 + 2));
3980 else throw new Error("unsupported RkNumber " + data); // TODO
3981}
3982
3983
3984/* [MS-XLSB] 2.5.117 RfX */
3985function parse_RfX(data /*::, length*/)/*:Range*/ {
3986 var cell/*:Range*/ = ({ s: {}, e: {} }/*:any*/);
3987 cell.s.r = data.read_shift(4);
3988 cell.e.r = data.read_shift(4);
3989 cell.s.c = data.read_shift(4);
3990 cell.e.c = data.read_shift(4);
3991 return cell;
3992}
3993function write_RfX(r/*:Range*/, o) {
3994 if (!o) o = new_buf(16);
3995 o.write_shift(4, r.s.r);
3996 o.write_shift(4, r.e.r);
3997 o.write_shift(4, r.s.c);
3998 o.write_shift(4, r.e.c);
3999 return o;
4000}
4001
4002/* [MS-XLSB] 2.5.153 UncheckedRfX */
4003var parse_UncheckedRfX = parse_RfX;
4004var write_UncheckedRfX = write_RfX;
4005
4006/* [MS-XLSB] 2.5.155 UncheckedSqRfX */
4007//function parse_UncheckedSqRfX(data) {
4008// var cnt = data.read_shift(4);
4009// var out = [];
4010// for(var i = 0; i < cnt; ++i) {
4011// var rng = parse_UncheckedRfX(data);
4012// out.push(encode_range(rng));
4013// }
4014// return out.join(",");
4015//}
4016//function write_UncheckedSqRfX(sqrfx/*:string*/) {
4017// var parts = sqrfx.split(/\s*,\s*/);
4018// var o = new_buf(4); o.write_shift(4, parts.length);
4019// var out = [o];
4020// parts.forEach(function(rng) {
4021// out.push(write_UncheckedRfX(safe_decode_range(rng)));
4022// });
4023// return bconcat(out);
4024//}
4025
4026/* [MS-XLS] 2.5.342 ; [MS-XLSB] 2.5.171 */
4027/* TODO: error checking, NaN and Infinity values are not valid Xnum */
4028function parse_Xnum(data/*::, length*/) {
4029 if(data.length - data.l < 8) throw "XLS Xnum Buffer underflow";
4030 return data.read_shift(8, 'f');
4031}
4032function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); }
4033
4034/* [MS-XLSB] 2.4.324 BrtColor */
4035function parse_BrtColor(data/*::, length*/) {
4036 var out = {};
4037 var d = data.read_shift(1);
4038
4039 //var fValidRGB = d & 1;
4040 var xColorType = d >>> 1;
4041
4042 var index = data.read_shift(1);
4043 var nTS = data.read_shift(2, 'i');
4044 var bR = data.read_shift(1);
4045 var bG = data.read_shift(1);
4046 var bB = data.read_shift(1);
4047 data.l++; //var bAlpha = data.read_shift(1);
4048
4049 switch (xColorType) {
4050 case 0: out.auto = 1; break;
4051 case 1:
4052 out.index = index;
4053 var icv = XLSIcv[index];
4054 /* automatic pseudo index 81 */
4055 if (icv) out.rgb = rgb2Hex(icv);
4056 break;
4057 case 2:
4058 /* if(!fValidRGB) throw new Error("invalid"); */
4059 out.rgb = rgb2Hex([bR, bG, bB]);
4060 break;
4061 case 3: out.theme = index; break;
4062 }
4063 if (nTS != 0) out.tint = nTS > 0 ? nTS / 32767 : nTS / 32768;
4064
4065 return out;
4066}
4067function write_BrtColor(color, o) {
4068 if (!o) o = new_buf(8);
4069 if (!color || color.auto) { o.write_shift(4, 0); o.write_shift(4, 0); return o; }
4070 if (color.index != null) {
4071 o.write_shift(1, 0x02);
4072 o.write_shift(1, color.index);
4073 } else if (color.theme != null) {
4074 o.write_shift(1, 0x06);
4075 o.write_shift(1, color.theme);
4076 } else {
4077 o.write_shift(1, 0x05);
4078 o.write_shift(1, 0);
4079 }
4080 var nTS = color.tint || 0;
4081 if (nTS > 0) nTS *= 32767;
4082 else if (nTS < 0) nTS *= 32768;
4083 o.write_shift(2, nTS);
4084 if (!color.rgb || color.theme != null) {
4085 o.write_shift(2, 0);
4086 o.write_shift(1, 0);
4087 o.write_shift(1, 0);
4088 } else {
4089 var rgb = (color.rgb || 'FFFFFF');
4090 if (typeof rgb == 'number') rgb = ("000000" + rgb.toString(16)).slice(-6);
4091 o.write_shift(1, parseInt(rgb.slice(0, 2), 16));
4092 o.write_shift(1, parseInt(rgb.slice(2, 4), 16));
4093 o.write_shift(1, parseInt(rgb.slice(4, 6), 16));
4094 o.write_shift(1, 0xFF);
4095 }
4096 return o;
4097}
4098
4099/* [MS-XLSB] 2.5.52 */
4100function parse_FontFlags(data/*::, length, opts*/) {
4101 var d = data.read_shift(1);
4102 data.l++;
4103 var out = {
4104 fBold: d & 0x01,
4105 fItalic: d & 0x02,
4106 fUnderline: d & 0x04,
4107 fStrikeout: d & 0x08,
4108 fOutline: d & 0x10,
4109 fShadow: d & 0x20,
4110 fCondense: d & 0x40,
4111 fExtend: d & 0x80
4112 };
4113 return out;
4114}
4115function write_FontFlags(font, o) {
4116 if (!o) o = new_buf(2);
4117 var grbit =
4118 (font.italic ? 0x02 : 0) |
4119 (font.strike ? 0x08 : 0) |
4120 (font.outline ? 0x10 : 0) |
4121 (font.shadow ? 0x20 : 0) |
4122 (font.condense ? 0x40 : 0) |
4123 (font.extend ? 0x80 : 0);
4124 o.write_shift(1, grbit);
4125 o.write_shift(1, 0);
4126 return o;
4127}
4128
4129/* [MS-OLEDS] 2.3.1 and 2.3.2 */
4130function parse_ClipboardFormatOrString(o, w/*:number*/)/*:string*/ {
4131 // $FlowIgnore
4132 var ClipFmt = { 2: "BITMAP", 3: "METAFILEPICT", 8: "DIB", 14: "ENHMETAFILE" };
4133 var m/*:number*/ = o.read_shift(4);
4134 switch (m) {
4135 case 0x00000000: return "";
4136 case 0xffffffff: case 0xfffffffe: return ClipFmt[o.read_shift(4)] || "";
4137 }
4138 if (m > 0x190) throw new Error("Unsupported Clipboard: " + m.toString(16));
4139 o.l -= 4;
4140 return o.read_shift(0, w == 1 ? "lpstr" : "lpwstr");
4141}
4142function parse_ClipboardFormatOrAnsiString(o) { return parse_ClipboardFormatOrString(o, 1); }
4143function parse_ClipboardFormatOrUnicodeString(o) { return parse_ClipboardFormatOrString(o, 2); }
4144
4145/* [MS-OLEPS] 2.2 PropertyType */
4146//var VT_EMPTY = 0x0000;
4147//var VT_NULL = 0x0001;
4148var VT_I2 = 0x0002;
4149var VT_I4 = 0x0003;
4150//var VT_R4 = 0x0004;
4151//var VT_R8 = 0x0005;
4152//var VT_CY = 0x0006;
4153//var VT_DATE = 0x0007;
4154//var VT_BSTR = 0x0008;
4155//var VT_ERROR = 0x000A;
4156var VT_BOOL = 0x000B;
4157var VT_VARIANT = 0x000C;
4158//var VT_DECIMAL = 0x000E;
4159//var VT_I1 = 0x0010;
4160//var VT_UI1 = 0x0011;
4161//var VT_UI2 = 0x0012;
4162var VT_UI4 = 0x0013;
4163//var VT_I8 = 0x0014;
4164//var VT_UI8 = 0x0015;
4165//var VT_INT = 0x0016;
4166//var VT_UINT = 0x0017;
4167var VT_LPSTR = 0x001E;
4168//var VT_LPWSTR = 0x001F;
4169var VT_FILETIME = 0x0040;
4170var VT_BLOB = 0x0041;
4171//var VT_STREAM = 0x0042;
4172//var VT_STORAGE = 0x0043;
4173//var VT_STREAMED_Object = 0x0044;
4174//var VT_STORED_Object = 0x0045;
4175//var VT_BLOB_Object = 0x0046;
4176var VT_CF = 0x0047;
4177//var VT_CLSID = 0x0048;
4178//var VT_VERSIONED_STREAM = 0x0049;
4179var VT_VECTOR = 0x1000;
4180//var VT_ARRAY = 0x2000;
4181
4182var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
4183var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString
4184var VT_CUSTOM = [VT_STRING, VT_USTR];
4185
4186/* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */
4187var DocSummaryPIDDSI = {
4188 /*::[*/0x01/*::]*/: { n: 'CodePage', t: VT_I2 },
4189 /*::[*/0x02/*::]*/: { n: 'Category', t: VT_STRING },
4190 /*::[*/0x03/*::]*/: { n: 'PresentationFormat', t: VT_STRING },
4191 /*::[*/0x04/*::]*/: { n: 'ByteCount', t: VT_I4 },
4192 /*::[*/0x05/*::]*/: { n: 'LineCount', t: VT_I4 },
4193 /*::[*/0x06/*::]*/: { n: 'ParagraphCount', t: VT_I4 },
4194 /*::[*/0x07/*::]*/: { n: 'SlideCount', t: VT_I4 },
4195 /*::[*/0x08/*::]*/: { n: 'NoteCount', t: VT_I4 },
4196 /*::[*/0x09/*::]*/: { n: 'HiddenCount', t: VT_I4 },
4197 /*::[*/0x0a/*::]*/: { n: 'MultimediaClipCount', t: VT_I4 },
4198 /*::[*/0x0b/*::]*/: { n: 'ScaleCrop', t: VT_BOOL },
4199 /*::[*/0x0c/*::]*/: { n: 'HeadingPairs', t: VT_VECTOR | VT_VARIANT },
4200 /*::[*/0x0d/*::]*/: { n: 'TitlesOfParts', t: VT_VECTOR | VT_LPSTR },
4201 /*::[*/0x0e/*::]*/: { n: 'Manager', t: VT_STRING },
4202 /*::[*/0x0f/*::]*/: { n: 'Company', t: VT_STRING },
4203 /*::[*/0x10/*::]*/: { n: 'LinksUpToDate', t: VT_BOOL },
4204 /*::[*/0x11/*::]*/: { n: 'CharacterCount', t: VT_I4 },
4205 /*::[*/0x13/*::]*/: { n: 'SharedDoc', t: VT_BOOL },
4206 /*::[*/0x16/*::]*/: { n: 'HyperlinksChanged', t: VT_BOOL },
4207 /*::[*/0x17/*::]*/: { n: 'AppVersion', t: VT_I4, p: 'version' },
4208 /*::[*/0x18/*::]*/: { n: 'DigSig', t: VT_BLOB },
4209 /*::[*/0x1A/*::]*/: { n: 'ContentType', t: VT_STRING },
4210 /*::[*/0x1B/*::]*/: { n: 'ContentStatus', t: VT_STRING },
4211 /*::[*/0x1C/*::]*/: { n: 'Language', t: VT_STRING },
4212 /*::[*/0x1D/*::]*/: { n: 'Version', t: VT_STRING },
4213 /*::[*/0xFF/*::]*/: {},
4214 /* [MS-OLEPS] 2.18 */
4215 /*::[*/0x80000000/*::]*/: { n: 'Locale', t: VT_UI4 },
4216 /*::[*/0x80000003/*::]*/: { n: 'Behavior', t: VT_UI4 },
4217 /*::[*/0x72627262/*::]*/: {}
4218};
4219
4220/* [MS-OSHARED] 2.3.3.2.1.1 Summary Information Property Set PIDSI */
4221var SummaryPIDSI = {
4222 /*::[*/0x01/*::]*/: { n: 'CodePage', t: VT_I2 },
4223 /*::[*/0x02/*::]*/: { n: 'Title', t: VT_STRING },
4224 /*::[*/0x03/*::]*/: { n: 'Subject', t: VT_STRING },
4225 /*::[*/0x04/*::]*/: { n: 'Author', t: VT_STRING },
4226 /*::[*/0x05/*::]*/: { n: 'Keywords', t: VT_STRING },
4227 /*::[*/0x06/*::]*/: { n: 'Comments', t: VT_STRING },
4228 /*::[*/0x07/*::]*/: { n: 'Template', t: VT_STRING },
4229 /*::[*/0x08/*::]*/: { n: 'LastAuthor', t: VT_STRING },
4230 /*::[*/0x09/*::]*/: { n: 'RevNumber', t: VT_STRING },
4231 /*::[*/0x0A/*::]*/: { n: 'EditTime', t: VT_FILETIME },
4232 /*::[*/0x0B/*::]*/: { n: 'LastPrinted', t: VT_FILETIME },
4233 /*::[*/0x0C/*::]*/: { n: 'CreatedDate', t: VT_FILETIME },
4234 /*::[*/0x0D/*::]*/: { n: 'ModifiedDate', t: VT_FILETIME },
4235 /*::[*/0x0E/*::]*/: { n: 'PageCount', t: VT_I4 },
4236 /*::[*/0x0F/*::]*/: { n: 'WordCount', t: VT_I4 },
4237 /*::[*/0x10/*::]*/: { n: 'CharCount', t: VT_I4 },
4238 /*::[*/0x11/*::]*/: { n: 'Thumbnail', t: VT_CF },
4239 /*::[*/0x12/*::]*/: { n: 'Application', t: VT_STRING },
4240 /*::[*/0x13/*::]*/: { n: 'DocSecurity', t: VT_I4 },
4241 /*::[*/0xFF/*::]*/: {},
4242 /* [MS-OLEPS] 2.18 */
4243 /*::[*/0x80000000/*::]*/: { n: 'Locale', t: VT_UI4 },
4244 /*::[*/0x80000003/*::]*/: { n: 'Behavior', t: VT_UI4 },
4245 /*::[*/0x72627262/*::]*/: {}
4246};
4247
4248var DocSummaryRE/*:{[key:string]:string}*/ = evert_key(DocSummaryPIDDSI, "n");
4249var SummaryRE/*:{[key:string]:string}*/ = evert_key(SummaryPIDSI, "n");
4250
4251/* [MS-XLS] 2.4.63 Country/Region codes */
4252var CountryEnum = {
4253 /*::[*/0x0001/*::]*/: "US", // United States
4254 /*::[*/0x0002/*::]*/: "CA", // Canada
4255 /*::[*/0x0003/*::]*/: "", // Latin America (except Brazil)
4256 /*::[*/0x0007/*::]*/: "RU", // Russia
4257 /*::[*/0x0014/*::]*/: "EG", // Egypt
4258 /*::[*/0x001E/*::]*/: "GR", // Greece
4259 /*::[*/0x001F/*::]*/: "NL", // Netherlands
4260 /*::[*/0x0020/*::]*/: "BE", // Belgium
4261 /*::[*/0x0021/*::]*/: "FR", // France
4262 /*::[*/0x0022/*::]*/: "ES", // Spain
4263 /*::[*/0x0024/*::]*/: "HU", // Hungary
4264 /*::[*/0x0027/*::]*/: "IT", // Italy
4265 /*::[*/0x0029/*::]*/: "CH", // Switzerland
4266 /*::[*/0x002B/*::]*/: "AT", // Austria
4267 /*::[*/0x002C/*::]*/: "GB", // United Kingdom
4268 /*::[*/0x002D/*::]*/: "DK", // Denmark
4269 /*::[*/0x002E/*::]*/: "SE", // Sweden
4270 /*::[*/0x002F/*::]*/: "NO", // Norway
4271 /*::[*/0x0030/*::]*/: "PL", // Poland
4272 /*::[*/0x0031/*::]*/: "DE", // Germany
4273 /*::[*/0x0034/*::]*/: "MX", // Mexico
4274 /*::[*/0x0037/*::]*/: "BR", // Brazil
4275 /*::[*/0x003d/*::]*/: "AU", // Australia
4276 /*::[*/0x0040/*::]*/: "NZ", // New Zealand
4277 /*::[*/0x0042/*::]*/: "TH", // Thailand
4278 /*::[*/0x0051/*::]*/: "JP", // Japan
4279 /*::[*/0x0052/*::]*/: "KR", // Korea
4280 /*::[*/0x0054/*::]*/: "VN", // Viet Nam
4281 /*::[*/0x0056/*::]*/: "CN", // China
4282 /*::[*/0x005A/*::]*/: "TR", // Turkey
4283 /*::[*/0x0069/*::]*/: "JS", // Ramastan
4284 /*::[*/0x00D5/*::]*/: "DZ", // Algeria
4285 /*::[*/0x00D8/*::]*/: "MA", // Morocco
4286 /*::[*/0x00DA/*::]*/: "LY", // Libya
4287 /*::[*/0x015F/*::]*/: "PT", // Portugal
4288 /*::[*/0x0162/*::]*/: "IS", // Iceland
4289 /*::[*/0x0166/*::]*/: "FI", // Finland
4290 /*::[*/0x01A4/*::]*/: "CZ", // Czech Republic
4291 /*::[*/0x0376/*::]*/: "TW", // Taiwan
4292 /*::[*/0x03C1/*::]*/: "LB", // Lebanon
4293 /*::[*/0x03C2/*::]*/: "JO", // Jordan
4294 /*::[*/0x03C3/*::]*/: "SY", // Syria
4295 /*::[*/0x03C4/*::]*/: "IQ", // Iraq
4296 /*::[*/0x03C5/*::]*/: "KW", // Kuwait
4297 /*::[*/0x03C6/*::]*/: "SA", // Saudi Arabia
4298 /*::[*/0x03CB/*::]*/: "AE", // United Arab Emirates
4299 /*::[*/0x03CC/*::]*/: "IL", // Israel
4300 /*::[*/0x03CE/*::]*/: "QA", // Qatar
4301 /*::[*/0x03D5/*::]*/: "IR", // Iran
4302 /*::[*/0xFFFF/*::]*/: "US" // United States
4303};
4304
4305/* [MS-XLS] 2.5.127 */
4306var XLSFillPattern = [
4307 null,
4308 'solid',
4309 'mediumGray',
4310 'darkGray',
4311 'lightGray',
4312 'darkHorizontal',
4313 'darkVertical',
4314 'darkDown',
4315 'darkUp',
4316 'darkGrid',
4317 'darkTrellis',
4318 'lightHorizontal',
4319 'lightVertical',
4320 'lightDown',
4321 'lightUp',
4322 'lightGrid',
4323 'lightTrellis',
4324 'gray125',
4325 'gray0625'
4326];
4327
4328function rgbify(arr/*:Array<number>*/)/*:Array<[number, number, number]>*/ { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); }
4329
4330/* [MS-XLS] 2.5.161 */
4331/* [MS-XLSB] 2.5.75 Icv */
4332var _XLSIcv = rgbify([
4333 /* Color Constants */
4334 0x000000,
4335 0xFFFFFF,
4336 0xFF0000,
4337 0x00FF00,
4338 0x0000FF,
4339 0xFFFF00,
4340 0xFF00FF,
4341 0x00FFFF,
4342
4343 /* Overridable Defaults */
4344 0x000000,
4345 0xFFFFFF,
4346 0xFF0000,
4347 0x00FF00,
4348 0x0000FF,
4349 0xFFFF00,
4350 0xFF00FF,
4351 0x00FFFF,
4352
4353 0x800000,
4354 0x008000,
4355 0x000080,
4356 0x808000,
4357 0x800080,
4358 0x008080,
4359 0xC0C0C0,
4360 0x808080,
4361 0x9999FF,
4362 0x993366,
4363 0xFFFFCC,
4364 0xCCFFFF,
4365 0x660066,
4366 0xFF8080,
4367 0x0066CC,
4368 0xCCCCFF,
4369
4370 0x000080,
4371 0xFF00FF,
4372 0xFFFF00,
4373 0x00FFFF,
4374 0x800080,
4375 0x800000,
4376 0x008080,
4377 0x0000FF,
4378 0x00CCFF,
4379 0xCCFFFF,
4380 0xCCFFCC,
4381 0xFFFF99,
4382 0x99CCFF,
4383 0xFF99CC,
4384 0xCC99FF,
4385 0xFFCC99,
4386
4387 0x3366FF,
4388 0x33CCCC,
4389 0x99CC00,
4390 0xFFCC00,
4391 0xFF9900,
4392 0xFF6600,
4393 0x666699,
4394 0x969696,
4395 0x003366,
4396 0x339966,
4397 0x003300,
4398 0x333300,
4399 0x993300,
4400 0x993366,
4401 0x333399,
4402 0x333333,
4403
4404 /* Other entries to appease BIFF8/12 */
4405 0xFFFFFF, /* 0x40 icvForeground ?? */
4406 0x000000, /* 0x41 icvBackground ?? */
4407 0x000000, /* 0x42 icvFrame ?? */
4408 0x000000, /* 0x43 icv3D ?? */
4409 0x000000, /* 0x44 icv3DText ?? */
4410 0x000000, /* 0x45 icv3DHilite ?? */
4411 0x000000, /* 0x46 icv3DShadow ?? */
4412 0x000000, /* 0x47 icvHilite ?? */
4413 0x000000, /* 0x48 icvCtlText ?? */
4414 0x000000, /* 0x49 icvCtlScrl ?? */
4415 0x000000, /* 0x4A icvCtlInv ?? */
4416 0x000000, /* 0x4B icvCtlBody ?? */
4417 0x000000, /* 0x4C icvCtlFrame ?? */
4418 0x000000, /* 0x4D icvCtlFore ?? */
4419 0x000000, /* 0x4E icvCtlBack ?? */
4420 0x000000, /* 0x4F icvCtlNeutral */
4421 0x000000, /* 0x50 icvInfoBk ?? */
4422 0x000000 /* 0x51 icvInfoText ?? */
4423]);
4424var XLSIcv = dup(_XLSIcv);
4425
4426/* [MS-XLSB] 2.5.97.2 */
4427var BErr = {
4428 /*::[*/0x00/*::]*/: "#NULL!",
4429 /*::[*/0x07/*::]*/: "#DIV/0!",
4430 /*::[*/0x0F/*::]*/: "#VALUE!",
4431 /*::[*/0x17/*::]*/: "#REF!",
4432 /*::[*/0x1D/*::]*/: "#NAME?",
4433 /*::[*/0x24/*::]*/: "#NUM!",
4434 /*::[*/0x2A/*::]*/: "#N/A",
4435 /*::[*/0x2B/*::]*/: "#GETTING_DATA",
4436 /*::[*/0xFF/*::]*/: "#WTF?"
4437};
4438var RBErr = evert_num(BErr);
4439/* Parts enumerated in OPC spec, MS-XLSB and MS-XLSX */
4440/* 12.3 Part Summary <SpreadsheetML> */
4441/* 14.2 Part Summary <DrawingML> */
4442/* [MS-XLSX] 2.1 Part Enumerations ; [MS-XLSB] 2.1.7 Part Enumeration */
4443var ct2type/*{[string]:string}*/ = ({
4444 /* Workbook */
4445 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": "workbooks",
4446
4447 /* Worksheet */
4448 "application/vnd.ms-excel.binIndexWs": "TODO", /* Binary Index */
4449
4450 /* Macrosheet */
4451 "application/vnd.ms-excel.intlmacrosheet": "TODO",
4452 "application/vnd.ms-excel.binIndexMs": "TODO", /* Binary Index */
4453
4454 /* File Properties */
4455 "application/vnd.openxmlformats-package.core-properties+xml": "coreprops",
4456 "application/vnd.openxmlformats-officedocument.custom-properties+xml": "custprops",
4457 "application/vnd.openxmlformats-officedocument.extended-properties+xml": "extprops",
4458
4459 /* Custom Data Properties */
4460 "application/vnd.openxmlformats-officedocument.customXmlProperties+xml": "TODO",
4461 "application/vnd.openxmlformats-officedocument.spreadsheetml.customProperty": "TODO",
4462
4463 /* PivotTable */
4464 "application/vnd.ms-excel.pivotTable": "TODO",
4465 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml": "TODO",
4466
4467 /* Chart Objects */
4468 "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": "TODO",
4469
4470 /* Chart Colors */
4471 "application/vnd.ms-office.chartcolorstyle+xml": "TODO",
4472
4473 /* Chart Style */
4474 "application/vnd.ms-office.chartstyle+xml": "TODO",
4475
4476 /* Chart Advanced */
4477 "application/vnd.ms-office.chartex+xml": "TODO",
4478
4479 /* Calculation Chain */
4480 "application/vnd.ms-excel.calcChain": "calcchains",
4481 "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains",
4482
4483 /* Printer Settings */
4484 "application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings": "TODO",
4485
4486 /* ActiveX */
4487 "application/vnd.ms-office.activeX": "TODO",
4488 "application/vnd.ms-office.activeX+xml": "TODO",
4489
4490 /* Custom Toolbars */
4491 "application/vnd.ms-excel.attachedToolbars": "TODO",
4492
4493 /* External Data Connections */
4494 "application/vnd.ms-excel.connections": "TODO",
4495 "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml": "TODO",
4496
4497 /* External Links */
4498 "application/vnd.ms-excel.externalLink": "links",
4499 "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml": "links",
4500
4501 /* Metadata */
4502 "application/vnd.ms-excel.sheetMetadata": "TODO",
4503 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml": "TODO",
4504
4505 /* PivotCache */
4506 "application/vnd.ms-excel.pivotCacheDefinition": "TODO",
4507 "application/vnd.ms-excel.pivotCacheRecords": "TODO",
4508 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml": "TODO",
4509 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml": "TODO",
4510
4511 /* Query Table */
4512 "application/vnd.ms-excel.queryTable": "TODO",
4513 "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml": "TODO",
4514
4515 /* Shared Workbook */
4516 "application/vnd.ms-excel.userNames": "TODO",
4517 "application/vnd.ms-excel.revisionHeaders": "TODO",
4518 "application/vnd.ms-excel.revisionLog": "TODO",
4519 "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml": "TODO",
4520 "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml": "TODO",
4521 "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml": "TODO",
4522
4523 /* Single Cell Table */
4524 "application/vnd.ms-excel.tableSingleCells": "TODO",
4525 "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml": "TODO",
4526
4527 /* Slicer */
4528 "application/vnd.ms-excel.slicer": "TODO",
4529 "application/vnd.ms-excel.slicerCache": "TODO",
4530 "application/vnd.ms-excel.slicer+xml": "TODO",
4531 "application/vnd.ms-excel.slicerCache+xml": "TODO",
4532
4533 /* Sort Map */
4534 "application/vnd.ms-excel.wsSortMap": "TODO",
4535
4536 /* Table */
4537 "application/vnd.ms-excel.table": "TODO",
4538 "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml": "TODO",
4539
4540 /* Themes */
4541 "application/vnd.openxmlformats-officedocument.theme+xml": "themes",
4542
4543 /* Theme Override */
4544 "application/vnd.openxmlformats-officedocument.themeOverride+xml": "TODO",
4545
4546 /* Timeline */
4547 "application/vnd.ms-excel.Timeline+xml": "TODO", /* verify */
4548 "application/vnd.ms-excel.TimelineCache+xml": "TODO", /* verify */
4549
4550 /* VBA */
4551 "application/vnd.ms-office.vbaProject": "vba",
4552 "application/vnd.ms-office.vbaProjectSignature": "vba",
4553
4554 /* Volatile Dependencies */
4555 "application/vnd.ms-office.volatileDependencies": "TODO",
4556 "application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml": "TODO",
4557
4558 /* Control Properties */
4559 "application/vnd.ms-excel.controlproperties+xml": "TODO",
4560
4561 /* Data Model */
4562 "application/vnd.openxmlformats-officedocument.model+data": "TODO",
4563
4564 /* Survey */
4565 "application/vnd.ms-excel.Survey+xml": "TODO",
4566
4567 /* Drawing */
4568 "application/vnd.openxmlformats-officedocument.drawing+xml": "drawings",
4569 "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml": "TODO",
4570 "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml": "TODO",
4571 "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml": "TODO",
4572 "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml": "TODO",
4573 "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml": "TODO",
4574
4575 /* VML */
4576 "application/vnd.openxmlformats-officedocument.vmlDrawing": "TODO",
4577
4578 "application/vnd.openxmlformats-package.relationships+xml": "rels",
4579 "application/vnd.openxmlformats-officedocument.oleObject": "TODO",
4580
4581 /* Image */
4582 "image/png": "TODO",
4583
4584 "sheet": "js"
4585}/*:any*/);
4586
4587var CT_LIST = (function(){
4588 var o = {
4589 workbooks: {
4590 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
4591 xlsm: "application/vnd.ms-excel.sheet.macroEnabled.main+xml",
4592 xlsb: "application/vnd.ms-excel.sheet.binary.macroEnabled.main",
4593 xlam: "application/vnd.ms-excel.addin.macroEnabled.main+xml",
4594 xltx: "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
4595 },
4596 strs: { /* Shared Strings */
4597 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
4598 xlsb: "application/vnd.ms-excel.sharedStrings"
4599 },
4600 comments: { /* Comments */
4601 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
4602 xlsb: "application/vnd.ms-excel.comments"
4603 },
4604 sheets: { /* Worksheet */
4605 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
4606 xlsb: "application/vnd.ms-excel.worksheet"
4607 },
4608 charts: { /* Chartsheet */
4609 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml",
4610 xlsb: "application/vnd.ms-excel.chartsheet"
4611 },
4612 dialogs: { /* Dialogsheet */
4613 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml",
4614 xlsb: "application/vnd.ms-excel.dialogsheet"
4615 },
4616 macros: { /* Macrosheet (Excel 4.0 Macros) */
4617 xlsx: "application/vnd.ms-excel.macrosheet+xml",
4618 xlsb: "application/vnd.ms-excel.macrosheet"
4619 },
4620 styles: { /* Styles */
4621 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
4622 xlsb: "application/vnd.ms-excel.styles"
4623 }
4624 };
4625 keys(o).forEach(function(k) { ["xlsm", "xlam"].forEach(function(v) { if(!o[k][v]) o[k][v] = o[k].xlsx; }); });
4626 keys(o).forEach(function(k){ keys(o[k]).forEach(function(v) { ct2type[o[k][v]] = k; }); });
4627 return o;
4628})();
4629
4630var type2ct/*{[string]:Array<string>}*/ = evert_arr(ct2type);
4631
4632XMLNS.CT = 'http://schemas.openxmlformats.org/package/2006/content-types';
4633
4634function new_ct()/*:any*/ {
4635 return ({
4636 workbooks:[], sheets:[], charts:[], dialogs:[], macros:[],
4637 rels:[], strs:[], comments:[], links:[],
4638 coreprops:[], extprops:[], custprops:[], themes:[], styles:[],
4639 calcchains:[], vba: [], drawings: [],
4640 TODO:[], xmlns: "" }/*:any*/);
4641}
4642
4643function parse_ct(data/*:?string*/) {
4644 var ct = new_ct();
4645 if(!data || !data.match) return ct;
4646 var ctext = {};
4647 (data.match(tagregex)||[]).forEach(function(x) {
4648 var y = parsexmltag(x);
4649 switch(y[0].replace(nsregex,"<")) {
4650 case '<?xml': break;
4651 case '<Types': ct.xmlns = y['xmlns' + (y[0].match(/<(\w+):/)||["",""])[1] ]; break;
4652 case '<Default': ctext[y.Extension] = y.ContentType; break;
4653 case '<Override':
4654 if(ct[ct2type[y.ContentType]] !== undefined) ct[ct2type[y.ContentType]].push(y.PartName);
4655 break;
4656 }
4657 });
4658 if(ct.xmlns !== XMLNS.CT) throw new Error("Unknown Namespace: " + ct.xmlns);
4659 ct.calcchain = ct.calcchains.length > 0 ? ct.calcchains[0] : "";
4660 ct.sst = ct.strs.length > 0 ? ct.strs[0] : "";
4661 ct.style = ct.styles.length > 0 ? ct.styles[0] : "";
4662 ct.defaults = ctext;
4663 delete ct.calcchains;
4664 return ct;
4665}
4666
4667var CTYPE_XML_ROOT = writextag('Types', null, {
4668 'xmlns': XMLNS.CT,
4669 'xmlns:xsd': XMLNS.xsd,
4670 'xmlns:xsi': XMLNS.xsi
4671});
4672
4673var CTYPE_DEFAULTS = [
4674 ['xml', 'application/xml'],
4675 ['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
4676 ['vml', 'application/vnd.openxmlformats-officedocument.vmlDrawing'],
4677 ['data', 'application/vnd.openxmlformats-officedocument.model+data'],
4678 /* from test files */
4679 ['bmp', 'image/bmp'],
4680 ['png', 'image/png'],
4681 ['gif', 'image/gif'],
4682 ['emf', 'image/x-emf'],
4683 ['wmf', 'image/x-wmf'],
4684 ['jpg', 'image/jpeg'], ['jpeg', 'image/jpeg'],
4685 ['tif', 'image/tiff'], ['tiff', 'image/tiff'],
4686 ['pdf', 'application/pdf'],
4687 ['rels', type2ct.rels[0]]
4688].map(function(x) {
4689 return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
4690});
4691
4692function write_ct(ct, opts)/*:string*/ {
4693 var o/*:Array<string>*/ = [], v;
4694 o[o.length] = (XML_HEADER);
4695 o[o.length] = (CTYPE_XML_ROOT);
4696 o = o.concat(CTYPE_DEFAULTS);
4697
4698 /* only write first instance */
4699 var f1 = function(w) {
4700 if(ct[w] && ct[w].length > 0) {
4701 v = ct[w][0];
4702 o[o.length] = (writextag('Override', null, {
4703 'PartName': (v[0] == '/' ? "":"/") + v,
4704 'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
4705 }));
4706 }
4707 };
4708
4709 /* book type-specific */
4710 var f2 = function(w) {
4711 (ct[w]||[]).forEach(function(v) {
4712 o[o.length] = (writextag('Override', null, {
4713 'PartName': (v[0] == '/' ? "":"/") + v,
4714 'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
4715 }));
4716 });
4717 };
4718
4719 /* standard type */
4720 var f3 = function(t) {
4721 (ct[t]||[]).forEach(function(v) {
4722 o[o.length] = (writextag('Override', null, {
4723 'PartName': (v[0] == '/' ? "":"/") + v,
4724 'ContentType': type2ct[t][0]
4725 }));
4726 });
4727 };
4728
4729 f1('workbooks');
4730 f2('sheets');
4731 f2('charts');
4732 f3('themes');
4733 ['strs', 'styles'].forEach(f1);
4734 ['coreprops', 'extprops', 'custprops'].forEach(f3);
4735 f3('vba');
4736 f3('comments');
4737 f3('drawings');
4738 if(o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
4739 return o.join("");
4740}
4741/* 9.3 Relationships */
4742var RELS = ({
4743 WB: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
4744 SHEET: "http://sheetjs.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
4745 HLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
4746 VML: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing",
4747 XPATH: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath",
4748 XMISS: "http://schemas.microsoft.com/office/2006/relationships/xlExternalLinkPath/xlPathMissing",
4749 XLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLink",
4750 CXML: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml",
4751 CXMLP: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXmlProps",
4752 VBA: "http://schemas.microsoft.com/office/2006/relationships/vbaProject"
4753}/*:any*/);
4754
4755/* 9.3.3 Representing Relationships */
4756function get_rels_path(file/*:string*/)/*:string*/ {
4757 var n = file.lastIndexOf("/");
4758 return file.slice(0,n+1) + '_rels/' + file.slice(n+1) + ".rels";
4759}
4760
4761function parse_rels(data/*:?string*/, currentFilePath/*:string*/) {
4762 var rels = {"!id":{}};
4763 if (!data) return rels;
4764 if (currentFilePath.charAt(0) !== '/') {
4765 currentFilePath = '/'+currentFilePath;
4766 }
4767 var hash = {};
4768
4769 (data.match(tagregex)||[]).forEach(function(x) {
4770 var y = parsexmltag(x);
4771 /* 9.3.2.2 OPC_Relationships */
4772 if (y[0] === '<Relationship') {
4773 var rel = {}; rel.Type = y.Type; rel.Target = y.Target; rel.Id = y.Id; rel.TargetMode = y.TargetMode;
4774 var canonictarget = y.TargetMode === 'External' ? y.Target : resolve_path(y.Target, currentFilePath);
4775 rels[canonictarget] = rel;
4776 hash[y.Id] = rel;
4777 }
4778 });
4779 rels["!id"] = hash;
4780 return rels;
4781}
4782
4783XMLNS.RELS = 'http://schemas.openxmlformats.org/package/2006/relationships';
4784
4785var RELS_ROOT = writextag('Relationships', null, {
4786 //'xmlns:ns0': XMLNS.RELS,
4787 'xmlns': XMLNS.RELS
4788});
4789
4790/* TODO */
4791function write_rels(rels)/*:string*/ {
4792 var o = [XML_HEADER, RELS_ROOT];
4793 keys(rels['!id']).forEach(function(rid) {
4794 o[o.length] = (writextag('Relationship', null, rels['!id'][rid]));
4795 });
4796 if(o.length>2){ o[o.length] = ('</Relationships>'); o[1]=o[1].replace("/>",">"); }
4797 return o.join("");
4798}
4799
4800var RELS_EXTERN = [RELS.HLINK, RELS.XPATH, RELS.XMISS];
4801function add_rels(rels, rId/*:number*/, f, type, relobj, targetmode/*:?string*/)/*:number*/ {
4802 if(!relobj) relobj = {};
4803 if(!rels['!id']) rels['!id'] = {};
4804 if(rId < 0) for(rId = 1; rels['!id']['rId' + rId]; ++rId){/* empty */}
4805 relobj.Id = 'rId' + rId;
4806 relobj.Type = type;
4807 relobj.Target = f;
4808 if(targetmode) relobj.TargetMode = targetmode;
4809 else if(RELS_EXTERN.indexOf(relobj.Type) > -1) relobj.TargetMode = "External";
4810 if(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId);
4811 rels['!id'][relobj.Id] = relobj;
4812 rels[('/' + relobj.Target).replace("//","/")] = relobj;
4813 return rId;
4814}
4815/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
4816/* Part 3 Section 4 Manifest File */
4817var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
4818function parse_manifest(d, opts) {
4819 var str = xlml_normalize(d);
4820 var Rn;
4821 var FEtag;
4822 while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
4823 case 'manifest': break; // 4.2 <manifest:manifest>
4824 case 'file-entry': // 4.3 <manifest:file-entry>
4825 FEtag = parsexmltag(Rn[0], false);
4826 if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet");
4827 break;
4828 case 'encryption-data': // 4.4 <manifest:encryption-data>
4829 case 'algorithm': // 4.5 <manifest:algorithm>
4830 case 'start-key-generation': // 4.6 <manifest:start-key-generation>
4831 case 'key-derivation': // 4.7 <manifest:key-derivation>
4832 throw new Error("Unsupported ODS Encryption");
4833 default: if(opts && opts.WTF) throw Rn;
4834 }
4835}
4836
4837function write_manifest(manifest/*:Array<Array<string> >*/)/*:string*/ {
4838 var o = [XML_HEADER];
4839 o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
4840 o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
4841 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');
4842 o.push('</manifest:manifest>');
4843 return o.join("");
4844}
4845
4846/* Part 3 Section 6 Metadata Manifest File */
4847function write_rdf_type(file/*:string*/, res/*:string*/, tag/*:?string*/) {
4848 return [
4849 ' <rdf:Description rdf:about="' + file + '">\n',
4850 ' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
4851 ' </rdf:Description>\n'
4852 ].join("");
4853}
4854function write_rdf_has(base/*:string*/, file/*:string*/) {
4855 return [
4856 ' <rdf:Description rdf:about="' + base + '">\n',
4857 ' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
4858 ' </rdf:Description>\n'
4859 ].join("");
4860}
4861function write_rdf(rdf) {
4862 var o = [XML_HEADER];
4863 o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
4864 for(var i = 0; i != rdf.length; ++i) {
4865 o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
4866 o.push(write_rdf_has("",rdf[i][0]));
4867 }
4868 o.push(write_rdf_type("","Document", "pkg"));
4869 o.push('</rdf:RDF>');
4870 return o.join("");
4871}
4872/* TODO: pull properties */
4873var write_meta_ods/*:{(wb:Workbook, opts:any):string}*/ = (function() {
4874 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>';
4875 return function wmo(/*:: wb: Workbook, opts: any*/)/*:string*/ {
4876 return payload;
4877 };
4878})();
4879
4880/* ECMA-376 Part II 11.1 Core Properties Part */
4881/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
4882var CORE_PROPS/*:Array<Array<string> >*/ = [
4883 ["cp:category", "Category"],
4884 ["cp:contentStatus", "ContentStatus"],
4885 ["cp:keywords", "Keywords"],
4886 ["cp:lastModifiedBy", "LastAuthor"],
4887 ["cp:lastPrinted", "LastPrinted"],
4888 ["cp:revision", "RevNumber"],
4889 ["cp:version", "Version"],
4890 ["dc:creator", "Author"],
4891 ["dc:description", "Comments"],
4892 ["dc:identifier", "Identifier"],
4893 ["dc:language", "Language"],
4894 ["dc:subject", "Subject"],
4895 ["dc:title", "Title"],
4896 ["dcterms:created", "CreatedDate", 'date'],
4897 ["dcterms:modified", "ModifiedDate", 'date']
4898];
4899
4900XMLNS.CORE_PROPS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
4901RELS.CORE_PROPS = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';
4902
4903var CORE_PROPS_REGEX/*:Array<RegExp>*/ = (function() {
4904 var r = new Array(CORE_PROPS.length);
4905 for(var i = 0; i < CORE_PROPS.length; ++i) {
4906 var f = CORE_PROPS[i];
4907 var g = "(?:"+ f[0].slice(0,f[0].indexOf(":")) +":)"+ f[0].slice(f[0].indexOf(":")+1);
4908 r[i] = new RegExp("<" + g + "[^>]*>([\\s\\S]*?)<\/" + g + ">");
4909 }
4910 return r;
4911})();
4912
4913function parse_core_props(data) {
4914 var p = {};
4915 data = utf8read(data);
4916
4917 for(var i = 0; i < CORE_PROPS.length; ++i) {
4918 var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
4919 if(cur != null && cur.length > 0) p[f[1]] = unescapexml(cur[1]);
4920 if(f[2] === 'date' && p[f[1]]) p[f[1]] = parseDate(p[f[1]]);
4921 }
4922
4923 return p;
4924}
4925
4926var CORE_PROPS_XML_ROOT = writextag('cp:coreProperties', null, {
4927 //'xmlns': XMLNS.CORE_PROPS,
4928 'xmlns:cp': XMLNS.CORE_PROPS,
4929 'xmlns:dc': XMLNS.dc,
4930 'xmlns:dcterms': XMLNS.dcterms,
4931 'xmlns:dcmitype': XMLNS.dcmitype,
4932 'xmlns:xsi': XMLNS.xsi
4933});
4934
4935function cp_doit(f, g, h, o, p) {
4936 if(p[f] != null || g == null || g === "") return;
4937 p[f] = g;
4938 g = escapexml(g);
4939 o[o.length] = (h ? writextag(f,g,h) : writetag(f,g));
4940}
4941
4942function write_core_props(cp, _opts) {
4943 var opts = _opts || {};
4944 var o = [XML_HEADER, CORE_PROPS_XML_ROOT], p = {};
4945 if(!cp && !opts.Props) return o.join("");
4946
4947 if(cp) {
4948 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);
4949 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);
4950 }
4951
4952 for(var i = 0; i != CORE_PROPS.length; ++i) {
4953 var f = CORE_PROPS[i];
4954 var v = opts.Props && opts.Props[f[1]] != null ? opts.Props[f[1]] : cp ? cp[f[1]] : null;
4955 if(v === true) v = "1";
4956 else if(v === false) v = "0";
4957 else if(typeof v == "number") v = String(v);
4958 if(v != null) cp_doit(f[0], v, null, o, p);
4959 }
4960 if(o.length>2){ o[o.length] = ('</cp:coreProperties>'); o[1]=o[1].replace("/>",">"); }
4961 return o.join("");
4962}
4963/* 15.2.12.3 Extended File Properties Part */
4964/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
4965var EXT_PROPS/*:Array<Array<string> >*/ = [
4966 ["Application", "Application", "string"],
4967 ["AppVersion", "AppVersion", "string"],
4968 ["Company", "Company", "string"],
4969 ["DocSecurity", "DocSecurity", "string"],
4970 ["Manager", "Manager", "string"],
4971 ["HyperlinksChanged", "HyperlinksChanged", "bool"],
4972 ["SharedDoc", "SharedDoc", "bool"],
4973 ["LinksUpToDate", "LinksUpToDate", "bool"],
4974 ["ScaleCrop", "ScaleCrop", "bool"],
4975 ["HeadingPairs", "HeadingPairs", "raw"],
4976 ["TitlesOfParts", "TitlesOfParts", "raw"]
4977];
4978
4979XMLNS.EXT_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
4980RELS.EXT_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';
4981
4982var PseudoPropsPairs = [
4983 "Worksheets", "SheetNames",
4984 "NamedRanges", "DefinedNames",
4985 "Chartsheets", "ChartNames"
4986];
4987function load_props_pairs(HP/*:string|Array<Array<any>>*/, TOP, props, opts) {
4988 var v = [];
4989 if(typeof HP == "string") v = parseVector(HP, opts);
4990 else for(var j = 0; j < HP.length; ++j) v = v.concat(HP[j].map(function(hp) { return {v:hp}; }));
4991 var parts = (typeof TOP == "string") ? parseVector(TOP, opts).map(function (x) { return x.v; }) : TOP;
4992 var idx = 0, len = 0;
4993 if(parts.length > 0) for(var i = 0; i !== v.length; i += 2) {
4994 len = +(v[i+1].v);
4995 switch(v[i].v) {
4996 case "Worksheets":
4997 case "工作表":
4998 case "Листы":
4999 case "أوراق العمل":
5000 case "ワークシート":
5001 case "גליונות עבודה":
5002 case "Arbeitsblätter":
5003 case "Çalışma Sayfaları":
5004 case "Feuilles de calcul":
5005 case "Fogli di lavoro":
5006 case "Folhas de cálculo":
5007 case "Planilhas":
5008 case "Regneark":
5009 case "Hojas de cálculo":
5010 case "Werkbladen":
5011 props.Worksheets = len;
5012 props.SheetNames = parts.slice(idx, idx + len);
5013 break;
5014
5015 case "Named Ranges":
5016 case "Rangos con nombre":
5017 case "名前付き一覧":
5018 case "Benannte Bereiche":
5019 case "Navngivne områder":
5020 props.NamedRanges = len;
5021 props.DefinedNames = parts.slice(idx, idx + len);
5022 break;
5023
5024 case "Charts":
5025 case "Diagramme":
5026 props.Chartsheets = len;
5027 props.ChartNames = parts.slice(idx, idx + len);
5028 break;
5029 }
5030 idx += len;
5031 }
5032}
5033
5034function parse_ext_props(data, p, opts) {
5035 var q = {}; if(!p) p = {};
5036 data = utf8read(data);
5037
5038 EXT_PROPS.forEach(function(f) {
5039 var xml = (data.match(matchtag(f[0]))||[])[1];
5040 switch(f[2]) {
5041 case "string": if(xml) p[f[1]] = unescapexml(xml); break;
5042 case "bool": p[f[1]] = xml === "true"; break;
5043 case "raw":
5044 var cur = data.match(new RegExp("<" + f[0] + "[^>]*>([\\s\\S]*?)<\/" + f[0] + ">"));
5045 if(cur && cur.length > 0) q[f[1]] = cur[1];
5046 break;
5047 }
5048 });
5049
5050 if(q.HeadingPairs && q.TitlesOfParts) load_props_pairs(q.HeadingPairs, q.TitlesOfParts, p, opts);
5051
5052 return p;
5053}
5054
5055var EXT_PROPS_XML_ROOT = writextag('Properties', null, {
5056 'xmlns': XMLNS.EXT_PROPS,
5057 'xmlns:vt': XMLNS.vt
5058});
5059
5060function write_ext_props(cp/*::, opts*/)/*:string*/ {
5061 var o/*:Array<string>*/ = [], W = writextag;
5062 if(!cp) cp = {};
5063 cp.Application = "SheetJS";
5064 o[o.length] = (XML_HEADER);
5065 o[o.length] = (EXT_PROPS_XML_ROOT);
5066
5067 EXT_PROPS.forEach(function(f) {
5068 if(cp[f[1]] === undefined) return;
5069 var v;
5070 switch(f[2]) {
5071 case 'string': v = escapexml(String(cp[f[1]])); break;
5072 case 'bool': v = cp[f[1]] ? 'true' : 'false'; break;
5073 }
5074 if(v !== undefined) o[o.length] = (W(f[0], v));
5075 });
5076
5077 /* TODO: HeadingPairs, TitlesOfParts */
5078 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"})));
5079 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"})));
5080 if(o.length>2){ o[o.length] = ('</Properties>'); o[1]=o[1].replace("/>",">"); }
5081 return o.join("");
5082}
5083/* 15.2.12.2 Custom File Properties Part */
5084XMLNS.CUST_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
5085RELS.CUST_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties';
5086
5087var custregex = /<[^>]+>[^<]*/g;
5088function parse_cust_props(data/*:string*/, opts) {
5089 var p = {}, name = "";
5090 var m = data.match(custregex);
5091 if(m) for(var i = 0; i != m.length; ++i) {
5092 var x = m[i], y = parsexmltag(x);
5093 switch(y[0]) {
5094 case '<?xml': break;
5095 case '<Properties': break;
5096 case '<property': name = unescapexml(y.name); break;
5097 case '</property>': name = null; break;
5098 default: if (x.indexOf('<vt:') === 0) {
5099 var toks = x.split('>');
5100 var type = toks[0].slice(4), text = toks[1];
5101 /* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */
5102 switch(type) {
5103 case 'lpstr': case 'bstr': case 'lpwstr':
5104 p[name] = unescapexml(text);
5105 break;
5106 case 'bool':
5107 p[name] = parsexmlbool(text);
5108 break;
5109 case 'i1': case 'i2': case 'i4': case 'i8': case 'int': case 'uint':
5110 p[name] = parseInt(text, 10);
5111 break;
5112 case 'r4': case 'r8': case 'decimal':
5113 p[name] = parseFloat(text);
5114 break;
5115 case 'filetime': case 'date':
5116 p[name] = parseDate(text);
5117 break;
5118 case 'cy': case 'error':
5119 p[name] = unescapexml(text);
5120 break;
5121 default:
5122 if(type.slice(-1) == '/') break;
5123 if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks);
5124 }
5125 } else if(x.slice(0,2) === "</") {/* empty */
5126 } else if(opts.WTF) throw new Error(x);
5127 }
5128 }
5129 return p;
5130}
5131
5132var CUST_PROPS_XML_ROOT = writextag('Properties', null, {
5133 'xmlns': XMLNS.CUST_PROPS,
5134 'xmlns:vt': XMLNS.vt
5135});
5136
5137function write_cust_props(cp/*::, opts*/)/*:string*/ {
5138 var o = [XML_HEADER, CUST_PROPS_XML_ROOT];
5139 if(!cp) return o.join("");
5140 var pid = 1;
5141 keys(cp).forEach(function custprop(k) { ++pid;
5142 o[o.length] = (writextag('property', write_vt(cp[k], true), {
5143 'fmtid': '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}',
5144 'pid': pid,
5145 'name': escapexml(k)
5146 }));
5147 });
5148 if(o.length>2){ o[o.length] = '</Properties>'; o[1]=o[1].replace("/>",">"); }
5149 return o.join("");
5150}
5151/* Common Name -> XLML Name */
5152var XLMLDocPropsMap = {
5153 Title: 'Title',
5154 Subject: 'Subject',
5155 Author: 'Author',
5156 Keywords: 'Keywords',
5157 Comments: 'Description',
5158 LastAuthor: 'LastAuthor',
5159 RevNumber: 'Revision',
5160 Application: 'AppName',
5161 /* TotalTime: 'TotalTime', */
5162 LastPrinted: 'LastPrinted',
5163 CreatedDate: 'Created',
5164 ModifiedDate: 'LastSaved',
5165 /* Pages */
5166 /* Words */
5167 /* Characters */
5168 Category: 'Category',
5169 /* PresentationFormat */
5170 Manager: 'Manager',
5171 Company: 'Company',
5172 /* Guid */
5173 /* HyperlinkBase */
5174 /* Bytes */
5175 /* Lines */
5176 /* Paragraphs */
5177 /* CharactersWithSpaces */
5178 AppVersion: 'Version',
5179
5180 ContentStatus: 'ContentStatus', /* NOTE: missing from schema */
5181 Identifier: 'Identifier', /* NOTE: missing from schema */
5182 Language: 'Language' /* NOTE: missing from schema */
5183};
5184var evert_XLMLDPM = evert(XLMLDocPropsMap);
5185
5186function xlml_set_prop(Props, tag/*:string*/, val) {
5187 tag = evert_XLMLDPM[tag] || tag;
5188 Props[tag] = val;
5189}
5190
5191function xlml_write_docprops(Props, opts) {
5192 var o/*:Array<string>*/ = [];
5193 keys(XLMLDocPropsMap).map(function(m) {
5194 for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i];
5195 for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i];
5196 throw m;
5197 }).forEach(function(p) {
5198 if(Props[p[1]] == null) return;
5199 var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]];
5200 switch(p[2]) {
5201 case 'date': m = new Date(m).toISOString().replace(/\.\d*Z/,"Z"); break;
5202 }
5203 if(typeof m == 'number') m = String(m);
5204 else if(m === true || m === false) { m = m ? "1" : "0"; }
5205 else if(m instanceof Date) m = new Date(m).toISOString().replace(/\.\d*Z/,"");
5206 o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m));
5207 });
5208 return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o });
5209}
5210function xlml_write_custprops(Props, Custprops/*::, opts*/) {
5211 var BLACKLIST = ["Worksheets","SheetNames"];
5212 var T = 'CustomDocumentProperties';
5213 var o/*:Array<string>*/ = [];
5214 if(Props) keys(Props).forEach(function(k) {
5215 /*:: if(!Props) return; */
5216 if(!Object.prototype.hasOwnProperty.call(Props, k)) return;
5217 for(var i = 0; i < CORE_PROPS.length; ++i) if(k == CORE_PROPS[i][1]) return;
5218 for(i = 0; i < EXT_PROPS.length; ++i) if(k == EXT_PROPS[i][1]) return;
5219 for(i = 0; i < BLACKLIST.length; ++i) if(k == BLACKLIST[i]) return;
5220
5221 var m = Props[k];
5222 var t = "string";
5223 if(typeof m == 'number') { t = "float"; m = String(m); }
5224 else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
5225 else m = String(m);
5226 o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
5227 });
5228 if(Custprops) keys(Custprops).forEach(function(k) {
5229 /*:: if(!Custprops) return; */
5230 if(!Object.prototype.hasOwnProperty.call(Custprops, k)) return;
5231 if(Props && Object.prototype.hasOwnProperty.call(Props, k)) return;
5232 var m = Custprops[k];
5233 var t = "string";
5234 if(typeof m == 'number') { t = "float"; m = String(m); }
5235 else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
5236 else if(m instanceof Date) { t = "dateTime.tz"; m = m.toISOString(); }
5237 else m = String(m);
5238 o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
5239 });
5240 return '<' + T + ' xmlns="' + XLMLNS.o + '">' + o.join("") + '</' + T + '>';
5241}
5242/* [MS-DTYP] 2.3.3 FILETIME */
5243/* [MS-OLEDS] 2.1.3 FILETIME (Packet Version) */
5244/* [MS-OLEPS] 2.8 FILETIME (Packet Version) */
5245function parse_FILETIME(blob) {
5246 var dwLowDateTime = blob.read_shift(4), dwHighDateTime = blob.read_shift(4);
5247 return new Date(((dwHighDateTime/1e7*Math.pow(2,32) + dwLowDateTime/1e7) - 11644473600)*1000).toISOString().replace(/\.000/,"");
5248}
5249function write_FILETIME(time/*:string|Date*/) {
5250 var date = (typeof time == "string") ? new Date(Date.parse(time)) : time;
5251 var t = date.getTime() / 1000 + 11644473600;
5252 var l = t % Math.pow(2,32), h = (t - l) / Math.pow(2,32);
5253 l *= 1e7; h *= 1e7;
5254 var w = (l / Math.pow(2,32)) | 0;
5255 if(w > 0) { l = l % Math.pow(2,32); h += w; }
5256 var o = new_buf(8); o.write_shift(4, l); o.write_shift(4, h); return o;
5257}
5258
5259/* [MS-OSHARED] 2.3.3.1.4 Lpstr */
5260function parse_lpstr(blob, type, pad/*:?number*/) {
5261 var start = blob.l;
5262 var str = blob.read_shift(0, 'lpstr-cp');
5263 if(pad) while((blob.l - start) & 3) ++blob.l;
5264 return str;
5265}
5266
5267/* [MS-OSHARED] 2.3.3.1.6 Lpwstr */
5268function parse_lpwstr(blob, type, pad) {
5269 var str = blob.read_shift(0, 'lpwstr');
5270 if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3;
5271 return str;
5272}
5273
5274
5275/* [MS-OSHARED] 2.3.3.1.11 VtString */
5276/* [MS-OSHARED] 2.3.3.1.12 VtUnalignedString */
5277function parse_VtStringBase(blob, stringType, pad) {
5278 if(stringType === 0x1F /*VT_LPWSTR*/) return parse_lpwstr(blob);
5279 return parse_lpstr(blob, stringType, pad);
5280}
5281
5282function parse_VtString(blob, t/*:number*/, pad/*:?boolean*/) { return parse_VtStringBase(blob, t, pad === false ? 0: 4); }
5283function parse_VtUnalignedString(blob, t/*:number*/) { if(!t) throw new Error("VtUnalignedString must have positive length"); return parse_VtStringBase(blob, t, 0); }
5284
5285/* [MS-OSHARED] 2.3.3.1.7 VtVecLpwstrValue */
5286function parse_VtVecLpwstrValue(blob)/*:Array<string>*/ {
5287 var length = blob.read_shift(4);
5288 var ret/*:Array<string>*/ = [];
5289 for(var i = 0; i != length; ++i) {
5290 var start = blob.l;
5291 ret[i] = blob.read_shift(0, 'lpwstr').replace(chr0,'');
5292 if((blob.l - start) & 0x02) blob.l += 2;
5293 }
5294 return ret;
5295}
5296
5297/* [MS-OSHARED] 2.3.3.1.9 VtVecUnalignedLpstrValue */
5298function parse_VtVecUnalignedLpstrValue(blob)/*:Array<string>*/ {
5299 var length = blob.read_shift(4);
5300 var ret/*:Array<string>*/ = [];
5301 for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr-cp').replace(chr0,'');
5302 return ret;
5303}
5304
5305
5306/* [MS-OSHARED] 2.3.3.1.13 VtHeadingPair */
5307function parse_VtHeadingPair(blob) {
5308 var start = blob.l;
5309 var headingString = parse_TypedPropertyValue(blob, VT_USTR);
5310 if(blob[blob.l] == 0x00 && blob[blob.l+1] == 0x00 && ((blob.l - start) & 0x02)) blob.l += 2;
5311 var headerParts = parse_TypedPropertyValue(blob, VT_I4);
5312 return [headingString, headerParts];
5313}
5314
5315/* [MS-OSHARED] 2.3.3.1.14 VtVecHeadingPairValue */
5316function parse_VtVecHeadingPairValue(blob) {
5317 var cElements = blob.read_shift(4);
5318 var out = [];
5319 for(var i = 0; i < cElements / 2; ++i) out.push(parse_VtHeadingPair(blob));
5320 return out;
5321}
5322
5323/* [MS-OLEPS] 2.18.1 Dictionary (uses 2.17, 2.16) */
5324function parse_dictionary(blob,CodePage) {
5325 var cnt = blob.read_shift(4);
5326 var dict/*:{[number]:string}*/ = ({}/*:any*/);
5327 for(var j = 0; j != cnt; ++j) {
5328 var pid = blob.read_shift(4);
5329 var len = blob.read_shift(4);
5330 dict[pid] = blob.read_shift(len, (CodePage === 0x4B0 ?'utf16le':'utf8')).replace(chr0,'').replace(chr1,'!');
5331 if(CodePage === 0x4B0 && (len % 2)) blob.l += 2;
5332 }
5333 if(blob.l & 3) blob.l = (blob.l>>2+1)<<2;
5334 return dict;
5335}
5336
5337/* [MS-OLEPS] 2.9 BLOB */
5338function parse_BLOB(blob) {
5339 var size = blob.read_shift(4);
5340 var bytes = blob.slice(blob.l,blob.l+size);
5341 blob.l += size;
5342 if((size & 3) > 0) blob.l += (4 - (size & 3)) & 3;
5343 return bytes;
5344}
5345
5346/* [MS-OLEPS] 2.11 ClipboardData */
5347function parse_ClipboardData(blob) {
5348 // TODO
5349 var o = {};
5350 o.Size = blob.read_shift(4);
5351 //o.Format = blob.read_shift(4);
5352 blob.l += o.Size + 3 - (o.Size - 1) % 4;
5353 return o;
5354}
5355
5356/* [MS-OLEPS] 2.15 TypedPropertyValue */
5357function parse_TypedPropertyValue(blob, type/*:number*/, _opts)/*:any*/ {
5358 var t = blob.read_shift(2), ret, opts = _opts||{};
5359 blob.l += 2;
5360 if(type !== VT_VARIANT)
5361 if(t !== type && VT_CUSTOM.indexOf(type)===-1 && !((type & 0xFFFE) == 0x101E && (t & 0xFFFE) == 0x101E)) throw new Error('Expected type ' + type + ' saw ' + t);
5362 switch(type === VT_VARIANT ? t : type) {
5363 case 0x02 /*VT_I2*/: ret = blob.read_shift(2, 'i'); if(!opts.raw) blob.l += 2; return ret;
5364 case 0x03 /*VT_I4*/: ret = blob.read_shift(4, 'i'); return ret;
5365 case 0x0B /*VT_BOOL*/: return blob.read_shift(4) !== 0x0;
5366 case 0x13 /*VT_UI4*/: ret = blob.read_shift(4); return ret;
5367 case 0x1E /*VT_LPSTR*/: return parse_lpstr(blob, t, 4).replace(chr0,'');
5368 case 0x1F /*VT_LPWSTR*/: return parse_lpwstr(blob);
5369 case 0x40 /*VT_FILETIME*/: return parse_FILETIME(blob);
5370 case 0x41 /*VT_BLOB*/: return parse_BLOB(blob);
5371 case 0x47 /*VT_CF*/: return parse_ClipboardData(blob);
5372 case 0x50 /*VT_STRING*/: return parse_VtString(blob, t, !opts.raw).replace(chr0,'');
5373 case 0x51 /*VT_USTR*/: return parse_VtUnalignedString(blob, t/*, 4*/).replace(chr0,'');
5374 case 0x100C /*VT_VECTOR|VT_VARIANT*/: return parse_VtVecHeadingPairValue(blob);
5375 case 0x101E /*VT_VECTOR|VT_LPSTR*/:
5376 case 0x101F /*VT_VECTOR|VT_LPWSTR*/:
5377 return t == 0x101F ? parse_VtVecLpwstrValue(blob) : parse_VtVecUnalignedLpstrValue(blob);
5378 default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + t);
5379 }
5380}
5381function write_TypedPropertyValue(type/*:number*/, value) {
5382 var o = new_buf(4), p = new_buf(4);
5383 o.write_shift(4, type == 0x50 ? 0x1F : type);
5384 switch(type) {
5385 case 0x03 /*VT_I4*/: p.write_shift(-4, value); break;
5386 case 0x05 /*VT_I4*/: p = new_buf(8); p.write_shift(8, value, 'f'); break;
5387 case 0x0B /*VT_BOOL*/: p.write_shift(4, value ? 0x01 : 0x00); break;
5388 case 0x40 /*VT_FILETIME*/: /*:: if(typeof value !== "string" && !(value instanceof Date)) throw "unreachable"; */ p = write_FILETIME(value); break;
5389 case 0x1F /*VT_LPWSTR*/:
5390 case 0x50 /*VT_STRING*/:
5391 /*:: if(typeof value !== "string") throw "unreachable"; */
5392 p = new_buf(4 + 2 * (value.length + 1) + (value.length % 2 ? 0 : 2));
5393 p.write_shift(4, value.length + 1);
5394 p.write_shift(0, value, "dbcs");
5395 while(p.l != p.length) p.write_shift(1, 0);
5396 break;
5397 default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + value);
5398 }
5399 return bconcat([o, p]);
5400}
5401
5402/* [MS-OLEPS] 2.20 PropertySet */
5403function parse_PropertySet(blob, PIDSI) {
5404 var start_addr = blob.l;
5405 var size = blob.read_shift(4);
5406 var NumProps = blob.read_shift(4);
5407 var Props = [], i = 0;
5408 var CodePage = 0;
5409 var Dictionary = -1, DictObj/*:{[number]:string}*/ = ({}/*:any*/);
5410 for(i = 0; i != NumProps; ++i) {
5411 var PropID = blob.read_shift(4);
5412 var Offset = blob.read_shift(4);
5413 Props[i] = [PropID, Offset + start_addr];
5414 }
5415 Props.sort(function(x,y) { return x[1] - y[1]; });
5416 var PropH = {};
5417 for(i = 0; i != NumProps; ++i) {
5418 if(blob.l !== Props[i][1]) {
5419 var fail = true;
5420 if(i>0 && PIDSI) switch(PIDSI[Props[i-1][0]].t) {
5421 case 0x02 /*VT_I2*/: if(blob.l+2 === Props[i][1]) { blob.l+=2; fail = false; } break;
5422 case 0x50 /*VT_STRING*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
5423 case 0x100C /*VT_VECTOR|VT_VARIANT*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
5424 }
5425 if((!PIDSI||i==0) && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; }
5426 if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i);
5427 }
5428 if(PIDSI) {
5429 var piddsi = PIDSI[Props[i][0]];
5430 PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true});
5431 if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + ("0000" + String(PropH[piddsi.n] & 0xFFFF)).slice(-4);
5432 if(piddsi.n == "CodePage") switch(PropH[piddsi.n]) {
5433 case 0: PropH[piddsi.n] = 1252;
5434 /* falls through */
5435 case 874:
5436 case 932:
5437 case 936:
5438 case 949:
5439 case 950:
5440 case 1250:
5441 case 1251:
5442 case 1253:
5443 case 1254:
5444 case 1255:
5445 case 1256:
5446 case 1257:
5447 case 1258:
5448 case 10000:
5449 case 1200:
5450 case 1201:
5451 case 1252:
5452 case 65000: case -536:
5453 case 65001: case -535:
5454 set_cp(CodePage = (PropH[piddsi.n]>>>0) & 0xFFFF); break;
5455 default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
5456 }
5457 } else {
5458 if(Props[i][0] === 0x1) {
5459 CodePage = PropH.CodePage = (parse_TypedPropertyValue(blob, VT_I2)/*:number*/);
5460 set_cp(CodePage);
5461 if(Dictionary !== -1) {
5462 var oldpos = blob.l;
5463 blob.l = Props[Dictionary][1];
5464 DictObj = parse_dictionary(blob,CodePage);
5465 blob.l = oldpos;
5466 }
5467 } else if(Props[i][0] === 0) {
5468 if(CodePage === 0) { Dictionary = i; blob.l = Props[i+1][1]; continue; }
5469 DictObj = parse_dictionary(blob,CodePage);
5470 } else {
5471 var name = DictObj[Props[i][0]];
5472 var val;
5473 /* [MS-OSHARED] 2.3.3.2.3.1.2 + PROPVARIANT */
5474 switch(blob[blob.l]) {
5475 case 0x41 /*VT_BLOB*/: blob.l += 4; val = parse_BLOB(blob); break;
5476 case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break;
5477 case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break;
5478 case 0x03 /*VT_I4*/: blob.l += 4; val = blob.read_shift(4, 'i'); break;
5479 case 0x13 /*VT_UI4*/: blob.l += 4; val = blob.read_shift(4); break;
5480 case 0x05 /*VT_R8*/: blob.l += 4; val = blob.read_shift(8, 'f'); break;
5481 case 0x0B /*VT_BOOL*/: blob.l += 4; val = parsebool(blob, 4); break;
5482 case 0x40 /*VT_FILETIME*/: blob.l += 4; val = parseDate(parse_FILETIME(blob)); break;
5483 default: throw new Error("unparsed value: " + blob[blob.l]);
5484 }
5485 PropH[name] = val;
5486 }
5487 }
5488 }
5489 blob.l = start_addr + size; /* step ahead to skip padding */
5490 return PropH;
5491}
5492var XLSPSSkip = [ "CodePage", "Thumbnail", "_PID_LINKBASE", "_PID_HLINKS", "SystemIdentifier", "FMTID" ].concat(PseudoPropsPairs);
5493function guess_property_type(val/*:any*/)/*:number*/ {
5494 switch(typeof val) {
5495 case "boolean": return 0x0B;
5496 case "number": return ((val|0)==val) ? 0x03 : 0x05;
5497 case "string": return 0x1F;
5498 case "object": if(val instanceof Date) return 0x40; break;
5499 }
5500 return -1;
5501}
5502function write_PropertySet(entries, RE, PIDSI) {
5503 var hdr = new_buf(8), piao = [], prop = [];
5504 var sz = 8, i = 0;
5505
5506 var pr = new_buf(8), pio = new_buf(8);
5507 pr.write_shift(4, 0x0002);
5508 pr.write_shift(4, 0x04B0);
5509 pio.write_shift(4, 0x0001);
5510 prop.push(pr); piao.push(pio);
5511 sz += 8 + pr.length;
5512
5513 if(!RE) {
5514 pio = new_buf(8);
5515 pio.write_shift(4, 0);
5516 piao.unshift(pio);
5517
5518 var bufs = [new_buf(4)];
5519 bufs[0].write_shift(4, entries.length);
5520 for(i = 0; i < entries.length; ++i) {
5521 var value = entries[i][0];
5522 pr = new_buf(4 + 4 + 2 * (value.length + 1) + (value.length % 2 ? 0 : 2));
5523 pr.write_shift(4, i+2);
5524 pr.write_shift(4, value.length + 1);
5525 pr.write_shift(0, value, "dbcs");
5526 while(pr.l != pr.length) pr.write_shift(1, 0);
5527 bufs.push(pr);
5528 }
5529 pr = bconcat(bufs);
5530 prop.unshift(pr);
5531 sz += 8 + pr.length;
5532 }
5533
5534 for(i = 0; i < entries.length; ++i) {
5535 if(RE && !RE[entries[i][0]]) continue;
5536 if(XLSPSSkip.indexOf(entries[i][0]) > -1) continue;
5537 if(entries[i][1] == null) continue;
5538
5539 var val = entries[i][1], idx = 0;
5540 if(RE) {
5541 idx = +RE[entries[i][0]];
5542 var pinfo = (PIDSI/*:: || {}*/)[idx]/*:: || {} */;
5543 if(pinfo.p == "version" && typeof val == "string") {
5544 /*:: if(typeof val !== "string") throw "unreachable"; */
5545 var arr = val.split(".");
5546 val = ((+arr[0])<<16) + ((+arr[1])||0);
5547 }
5548 pr = write_TypedPropertyValue(pinfo.t, val);
5549 } else {
5550 var T = guess_property_type(val);
5551 if(T == -1) { T = 0x1F; val = String(val); }
5552 pr = write_TypedPropertyValue(T, val);
5553 }
5554 prop.push(pr);
5555
5556 pio = new_buf(8);
5557 pio.write_shift(4, !RE ? 2+i : idx);
5558 piao.push(pio);
5559
5560 sz += 8 + pr.length;
5561 }
5562
5563 var w = 8 * (prop.length + 1);
5564 for(i = 0; i < prop.length; ++i) { piao[i].write_shift(4, w); w += prop[i].length; }
5565 hdr.write_shift(4, sz);
5566 hdr.write_shift(4, prop.length);
5567 return bconcat([hdr].concat(piao).concat(prop));
5568}
5569
5570/* [MS-OLEPS] 2.21 PropertySetStream */
5571function parse_PropertySetStream(file, PIDSI, clsid) {
5572 var blob = file.content;
5573 if(!blob) return ({}/*:any*/);
5574 prep_blob(blob, 0);
5575
5576 var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;
5577 blob.chk('feff', 'Byte Order: ');
5578
5579 /*var vers = */blob.read_shift(2); // TODO: check version
5580 var SystemIdentifier = blob.read_shift(4);
5581 var CLSID = blob.read_shift(16);
5582 if(CLSID !== CFB.utils.consts.HEADER_CLSID && CLSID !== clsid) throw new Error("Bad PropertySet CLSID " + CLSID);
5583 NumSets = blob.read_shift(4);
5584 if(NumSets !== 1 && NumSets !== 2) throw new Error("Unrecognized #Sets: " + NumSets);
5585 FMTID0 = blob.read_shift(16); Offset0 = blob.read_shift(4);
5586
5587 if(NumSets === 1 && Offset0 !== blob.l) throw new Error("Length mismatch: " + Offset0 + " !== " + blob.l);
5588 else if(NumSets === 2) { FMTID1 = blob.read_shift(16); Offset1 = blob.read_shift(4); }
5589 var PSet0 = parse_PropertySet(blob, PIDSI);
5590
5591 var rval = ({ SystemIdentifier: SystemIdentifier }/*:any*/);
5592 for(var y in PSet0) rval[y] = PSet0[y];
5593 //rval.blob = blob;
5594 rval.FMTID = FMTID0;
5595 //rval.PSet0 = PSet0;
5596 if(NumSets === 1) return rval;
5597 if(Offset1 - blob.l == 2) blob.l += 2;
5598 if(blob.l !== Offset1) throw new Error("Length mismatch 2: " + blob.l + " !== " + Offset1);
5599 var PSet1;
5600 try { PSet1 = parse_PropertySet(blob, null); } catch(e) {/* empty */}
5601 for(y in PSet1) rval[y] = PSet1[y];
5602 rval.FMTID = [FMTID0, FMTID1]; // TODO: verify FMTID0/1
5603 return rval;
5604}
5605function write_PropertySetStream(entries, clsid, RE, PIDSI/*:{[key:string|number]:any}*/, entries2/*:?any*/, clsid2/*:?any*/) {
5606 var hdr = new_buf(entries2 ? 68 : 48);
5607 var bufs = [hdr];
5608 hdr.write_shift(2, 0xFFFE);
5609 hdr.write_shift(2, 0x0000); /* TODO: type 1 props */
5610 hdr.write_shift(4, 0x32363237);
5611 hdr.write_shift(16, CFB.utils.consts.HEADER_CLSID, "hex");
5612 hdr.write_shift(4, (entries2 ? 2 : 1));
5613 hdr.write_shift(16, clsid, "hex");
5614 hdr.write_shift(4, (entries2 ? 68 : 48));
5615 var ps0 = write_PropertySet(entries, RE, PIDSI);
5616 bufs.push(ps0);
5617
5618 if(entries2) {
5619 var ps1 = write_PropertySet(entries2, null, null);
5620 hdr.write_shift(16, clsid2, "hex");
5621 hdr.write_shift(4, 68 + ps0.length);
5622 bufs.push(ps1);
5623 }
5624 return bconcat(bufs);
5625}
5626
5627function parsenoop2(blob, length) { blob.read_shift(length); return null; }
5628function writezeroes(n, o) { if(!o) o=new_buf(n); for(var j=0; j<n; ++j) o.write_shift(1, 0); return o; }
5629
5630function parslurp(blob, length, cb) {
5631 var arr = [], target = blob.l + length;
5632 while(blob.l < target) arr.push(cb(blob, target - blob.l));
5633 if(target !== blob.l) throw new Error("Slurp error");
5634 return arr;
5635}
5636
5637function parsebool(blob, length/*:number*/) { return blob.read_shift(length) === 0x1; }
5638function writebool(v/*:any*/, o) { if(!o) o=new_buf(2); o.write_shift(2, +!!v); return o; }
5639
5640function parseuint16(blob/*::, length:?number, opts:?any*/) { return blob.read_shift(2, 'u'); }
5641function writeuint16(v/*:number*/, o) { if(!o) o=new_buf(2); o.write_shift(2, v); return o; }
5642function parseuint16a(blob, length/*:: :?number, opts:?any*/) { return parslurp(blob,length,parseuint16);}
5643
5644/* --- 2.5 Structures --- */
5645
5646/* [MS-XLS] 2.5.10 Bes (boolean or error) */
5647function parse_Bes(blob/*::, length*/) {
5648 var v = blob.read_shift(1), t = blob.read_shift(1);
5649 return t === 0x01 ? v : v === 0x01;
5650}
5651function write_Bes(v, t/*:string*/, o) {
5652 if(!o) o = new_buf(2);
5653 o.write_shift(1, ((t == 'e') ? +v : +!!v));
5654 o.write_shift(1, ((t == 'e') ? 1 : 0));
5655 return o;
5656}
5657
5658/* [MS-XLS] 2.5.240 ShortXLUnicodeString */
5659function parse_ShortXLUnicodeString(blob, length, opts) {
5660 var cch = blob.read_shift(opts && opts.biff >= 12 ? 2 : 1);
5661 var encoding = 'sbcs-cont';
5662 var cp = current_codepage;
5663 if(opts && opts.biff >= 8) current_codepage = 1200;
5664 if(!opts || opts.biff == 8 ) {
5665 var fHighByte = blob.read_shift(1);
5666 if(fHighByte) { encoding = 'dbcs-cont'; }
5667 } else if(opts.biff == 12) {
5668 encoding = 'wstr';
5669 }
5670 if(opts.biff >= 2 && opts.biff <= 5) encoding = 'cpstr';
5671 var o = cch ? blob.read_shift(cch, encoding) : "";
5672 current_codepage = cp;
5673 return o;
5674}
5675
5676/* 2.5.293 XLUnicodeRichExtendedString */
5677function parse_XLUnicodeRichExtendedString(blob) {
5678 var cp = current_codepage;
5679 current_codepage = 1200;
5680 var cch = blob.read_shift(2), flags = blob.read_shift(1);
5681 var /*fHighByte = flags & 0x1,*/ fExtSt = flags & 0x4, fRichSt = flags & 0x8;
5682 var width = 1 + (flags & 0x1); // 0x0 -> utf8, 0x1 -> dbcs
5683 var cRun = 0, cbExtRst;
5684 var z = {};
5685 if(fRichSt) cRun = blob.read_shift(2);
5686 if(fExtSt) cbExtRst = blob.read_shift(4);
5687 var encoding = width == 2 ? 'dbcs-cont' : 'sbcs-cont';
5688 var msg = cch === 0 ? "" : blob.read_shift(cch, encoding);
5689 if(fRichSt) blob.l += 4 * cRun; //TODO: parse this
5690 if(fExtSt) blob.l += cbExtRst; //TODO: parse this
5691 z.t = msg;
5692 if(!fRichSt) { z.raw = "<t>" + z.t + "</t>"; z.r = z.t; }
5693 current_codepage = cp;
5694 return z;
5695}
5696function write_XLUnicodeRichExtendedString(xlstr/*:: :XLString, opts*/) {
5697 var str = (xlstr.t||""), nfmts = 1;
5698
5699 var hdr = new_buf(3 + (nfmts > 1 ? 2 : 0));
5700 hdr.write_shift(2, str.length);
5701 hdr.write_shift(1, (nfmts > 1 ? 0x08 : 0x00) | 0x01);
5702 if(nfmts > 1) hdr.write_shift(2, nfmts);
5703
5704 var otext = new_buf(2 * str.length);
5705 otext.write_shift(2 * str.length, str, 'utf16le');
5706
5707 var out = [hdr, otext];
5708
5709 return bconcat(out);
5710}
5711
5712/* 2.5.296 XLUnicodeStringNoCch */
5713function parse_XLUnicodeStringNoCch(blob, cch, opts) {
5714 var retval;
5715 if(opts) {
5716 if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'cpstr');
5717 if(opts.biff >= 12) return blob.read_shift(cch, 'dbcs-cont');
5718 }
5719 var fHighByte = blob.read_shift(1);
5720 if(fHighByte===0) { retval = blob.read_shift(cch, 'sbcs-cont'); }
5721 else { retval = blob.read_shift(cch, 'dbcs-cont'); }
5722 return retval;
5723}
5724
5725/* 2.5.294 XLUnicodeString */
5726function parse_XLUnicodeString(blob, length, opts) {
5727 var cch = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
5728 if(cch === 0) { blob.l++; return ""; }
5729 return parse_XLUnicodeStringNoCch(blob, cch, opts);
5730}
5731/* BIFF5 override */
5732function parse_XLUnicodeString2(blob, length, opts) {
5733 if(opts.biff > 5) return parse_XLUnicodeString(blob, length, opts);
5734 var cch = blob.read_shift(1);
5735 if(cch === 0) { blob.l++; return ""; }
5736 return blob.read_shift(cch, (opts.biff <= 4 || !blob.lens ) ? 'cpstr' : 'sbcs-cont');
5737}
5738/* TODO: BIFF5 and lower, codepage awareness */
5739function write_XLUnicodeString(str, opts, o) {
5740 if(!o) o = new_buf(3 + 2 * str.length);
5741 o.write_shift(2, str.length);
5742 o.write_shift(1, 1);
5743 o.write_shift(31, str, 'utf16le');
5744 return o;
5745}
5746
5747/* [MS-XLS] 2.5.61 ControlInfo */
5748function parse_ControlInfo(blob/*::, length, opts*/) {
5749 var flags = blob.read_shift(1);
5750 blob.l++;
5751 var accel = blob.read_shift(2);
5752 blob.l += 2;
5753 return [flags, accel];
5754}
5755
5756/* [MS-OSHARED] 2.3.7.6 URLMoniker TODO: flags */
5757function parse_URLMoniker(blob/*::, length, opts*/) {
5758 var len = blob.read_shift(4), start = blob.l;
5759 var extra = false;
5760 if(len > 24) {
5761 /* look ahead */
5762 blob.l += len - 24;
5763 if(blob.read_shift(16) === "795881f43b1d7f48af2c825dc4852763") extra = true;
5764 blob.l = start;
5765 }
5766 var url = blob.read_shift((extra?len-24:len)>>1, 'utf16le').replace(chr0,"");
5767 if(extra) blob.l += 24;
5768 return url;
5769}
5770
5771/* [MS-OSHARED] 2.3.7.8 FileMoniker TODO: all fields */
5772function parse_FileMoniker(blob/*::, length*/) {
5773 var cAnti = blob.read_shift(2);
5774 var preamble = ""; while(cAnti-- > 0) preamble += "../";
5775 var ansiPath = blob.read_shift(0, 'lpstr-ansi');
5776 blob.l += 2; //var endServer = blob.read_shift(2);
5777 if(blob.read_shift(2) != 0xDEAD) throw new Error("Bad FileMoniker");
5778 var sz = blob.read_shift(4);
5779 if(sz === 0) return preamble + ansiPath.replace(/\\/g,"/");
5780 var bytes = blob.read_shift(4);
5781 if(blob.read_shift(2) != 3) throw new Error("Bad FileMoniker");
5782 var unicodePath = blob.read_shift(bytes>>1, 'utf16le').replace(chr0,"");
5783 return preamble + unicodePath;
5784}
5785
5786/* [MS-OSHARED] 2.3.7.2 HyperlinkMoniker TODO: all the monikers */
5787function parse_HyperlinkMoniker(blob, length) {
5788 var clsid = blob.read_shift(16); length -= 16;
5789 switch(clsid) {
5790 case "e0c9ea79f9bace118c8200aa004ba90b": return parse_URLMoniker(blob, length);
5791 case "0303000000000000c000000000000046": return parse_FileMoniker(blob, length);
5792 default: throw new Error("Unsupported Moniker " + clsid);
5793 }
5794}
5795
5796/* [MS-OSHARED] 2.3.7.9 HyperlinkString */
5797function parse_HyperlinkString(blob/*::, length*/) {
5798 var len = blob.read_shift(4);
5799 var o = len > 0 ? blob.read_shift(len, 'utf16le').replace(chr0, "") : "";
5800 return o;
5801}
5802function write_HyperlinkString(str/*:string*/, o) {
5803 if(!o) o = new_buf(6 + str.length * 2);
5804 o.write_shift(4, 1 + str.length);
5805 for(var i = 0; i < str.length; ++i) o.write_shift(2, str.charCodeAt(i));
5806 o.write_shift(2, 0);
5807 return o;
5808}
5809
5810/* [MS-OSHARED] 2.3.7.1 Hyperlink Object */
5811function parse_Hyperlink(blob, length)/*:Hyperlink*/ {
5812 var end = blob.l + length;
5813 var sVer = blob.read_shift(4);
5814 if(sVer !== 2) throw new Error("Unrecognized streamVersion: " + sVer);
5815 var flags = blob.read_shift(2);
5816 blob.l += 2;
5817 var displayName, targetFrameName, moniker, oleMoniker, Loc="", guid, fileTime;
5818 if(flags & 0x0010) displayName = parse_HyperlinkString(blob, end - blob.l);
5819 if(flags & 0x0080) targetFrameName = parse_HyperlinkString(blob, end - blob.l);
5820 if((flags & 0x0101) === 0x0101) moniker = parse_HyperlinkString(blob, end - blob.l);
5821 if((flags & 0x0101) === 0x0001) oleMoniker = parse_HyperlinkMoniker(blob, end - blob.l);
5822 if(flags & 0x0008) Loc = parse_HyperlinkString(blob, end - blob.l);
5823 if(flags & 0x0020) guid = blob.read_shift(16);
5824 if(flags & 0x0040) fileTime = parse_FILETIME(blob/*, 8*/);
5825 blob.l = end;
5826 var target = targetFrameName||moniker||oleMoniker||"";
5827 if(target && Loc) target+="#"+Loc;
5828 if(!target) target = "#" + Loc;
5829 if((flags & 0x0002) && target.charAt(0) == "/" && target.charAt(1) != "/") target = "file://" + target;
5830 var out = ({Target:target}/*:any*/);
5831 if(guid) out.guid = guid;
5832 if(fileTime) out.time = fileTime;
5833 if(displayName) out.Tooltip = displayName;
5834 return out;
5835}
5836function write_Hyperlink(hl) {
5837 var out = new_buf(512), i = 0;
5838 var Target = hl.Target;
5839 if(Target.slice(0,7) == "file://") Target = Target.slice(7);
5840 var hashidx = Target.indexOf("#");
5841 var F = hashidx > -1 ? 0x1f : 0x17;
5842 switch(Target.charAt(0)) { case "#": F=0x1c; break; case ".": F&=~2; break; }
5843 out.write_shift(4,2); out.write_shift(4, F);
5844 var data = [8,6815827,6619237,4849780,83]; for(i = 0; i < data.length; ++i) out.write_shift(4, data[i]);
5845 if(F == 0x1C) {
5846 Target = Target.slice(1);
5847 write_HyperlinkString(Target, out);
5848 } else if(F & 0x02) {
5849 data = "e0 c9 ea 79 f9 ba ce 11 8c 82 00 aa 00 4b a9 0b".split(" ");
5850 for(i = 0; i < data.length; ++i) out.write_shift(1, parseInt(data[i], 16));
5851 var Pretarget = hashidx > -1 ? Target.slice(0, hashidx) : Target;
5852 out.write_shift(4, 2*(Pretarget.length + 1));
5853 for(i = 0; i < Pretarget.length; ++i) out.write_shift(2, Pretarget.charCodeAt(i));
5854 out.write_shift(2, 0);
5855 if(F & 0x08) write_HyperlinkString(hashidx > -1 ? Target.slice(hashidx+1): "", out);
5856 } else {
5857 data = "03 03 00 00 00 00 00 00 c0 00 00 00 00 00 00 46".split(" ");
5858 for(i = 0; i < data.length; ++i) out.write_shift(1, parseInt(data[i], 16));
5859 var P = 0;
5860 while(Target.slice(P*3,P*3+3)=="../"||Target.slice(P*3,P*3+3)=="..\\") ++P;
5861 out.write_shift(2, P);
5862 out.write_shift(4, Target.length - 3 * P + 1);
5863 for(i = 0; i < Target.length - 3 * P; ++i) out.write_shift(1, Target.charCodeAt(i + 3 * P) & 0xFF);
5864 out.write_shift(1, 0);
5865 out.write_shift(2, 0xFFFF);
5866 out.write_shift(2, 0xDEAD);
5867 for(i = 0; i < 6; ++i) out.write_shift(4, 0);
5868 }
5869 return out.slice(0, out.l);
5870}
5871
5872/* 2.5.178 LongRGBA */
5873function parse_LongRGBA(blob/*::, length*/) { var r = blob.read_shift(1), g = blob.read_shift(1), b = blob.read_shift(1), a = blob.read_shift(1); return [r,g,b,a]; }
5874
5875/* 2.5.177 LongRGB */
5876function parse_LongRGB(blob, length) { var x = parse_LongRGBA(blob, length); x[3] = 0; return x; }
5877
5878
5879/* [MS-XLS] 2.5.19 */
5880function parse_XLSCell(blob/*::, length*/)/*:Cell*/ {
5881 var rw = blob.read_shift(2); // 0-indexed
5882 var col = blob.read_shift(2);
5883 var ixfe = blob.read_shift(2);
5884 return ({r:rw, c:col, ixfe:ixfe}/*:any*/);
5885}
5886function write_XLSCell(R/*:number*/, C/*:number*/, ixfe/*:?number*/, o) {
5887 if(!o) o = new_buf(6);
5888 o.write_shift(2, R);
5889 o.write_shift(2, C);
5890 o.write_shift(2, ixfe||0);
5891 return o;
5892}
5893
5894/* [MS-XLS] 2.5.134 */
5895function parse_frtHeader(blob) {
5896 var rt = blob.read_shift(2);
5897 var flags = blob.read_shift(2); // TODO: parse these flags
5898 blob.l += 8;
5899 return {type: rt, flags: flags};
5900}
5901
5902
5903
5904function parse_OptXLUnicodeString(blob, length, opts) { return length === 0 ? "" : parse_XLUnicodeString2(blob, length, opts); }
5905
5906/* [MS-XLS] 2.5.344 */
5907function parse_XTI(blob, length, opts) {
5908 var w = opts.biff > 8 ? 4 : 2;
5909 var iSupBook = blob.read_shift(w), itabFirst = blob.read_shift(w,'i'), itabLast = blob.read_shift(w,'i');
5910 return [iSupBook, itabFirst, itabLast];
5911}
5912
5913/* [MS-XLS] 2.5.218 */
5914function parse_RkRec(blob) {
5915 var ixfe = blob.read_shift(2);
5916 var RK = parse_RkNumber(blob);
5917 return [ixfe, RK];
5918}
5919
5920/* [MS-XLS] 2.5.1 */
5921function parse_AddinUdf(blob, length, opts) {
5922 blob.l += 4; length -= 4;
5923 var l = blob.l + length;
5924 var udfName = parse_ShortXLUnicodeString(blob, length, opts);
5925 var cb = blob.read_shift(2);
5926 l -= blob.l;
5927 if(cb !== l) throw new Error("Malformed AddinUdf: padding = " + l + " != " + cb);
5928 blob.l += cb;
5929 return udfName;
5930}
5931
5932/* [MS-XLS] 2.5.209 TODO: Check sizes */
5933function parse_Ref8U(blob/*::, length*/) {
5934 var rwFirst = blob.read_shift(2);
5935 var rwLast = blob.read_shift(2);
5936 var colFirst = blob.read_shift(2);
5937 var colLast = blob.read_shift(2);
5938 return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}};
5939}
5940function write_Ref8U(r/*:Range*/, o) {
5941 if(!o) o = new_buf(8);
5942 o.write_shift(2, r.s.r);
5943 o.write_shift(2, r.e.r);
5944 o.write_shift(2, r.s.c);
5945 o.write_shift(2, r.e.c);
5946 return o;
5947}
5948
5949/* [MS-XLS] 2.5.211 */
5950function parse_RefU(blob/*::, length*/) {
5951 var rwFirst = blob.read_shift(2);
5952 var rwLast = blob.read_shift(2);
5953 var colFirst = blob.read_shift(1);
5954 var colLast = blob.read_shift(1);
5955 return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}};
5956}
5957
5958/* [MS-XLS] 2.5.207 */
5959var parse_Ref = parse_RefU;
5960
5961/* [MS-XLS] 2.5.143 */
5962function parse_FtCmo(blob/*::, length*/) {
5963 blob.l += 4;
5964 var ot = blob.read_shift(2);
5965 var id = blob.read_shift(2);
5966 var flags = blob.read_shift(2);
5967 blob.l+=12;
5968 return [id, ot, flags];
5969}
5970
5971/* [MS-XLS] 2.5.149 */
5972function parse_FtNts(blob) {
5973 var out = {};
5974 blob.l += 4;
5975 blob.l += 16; // GUID TODO
5976 out.fSharedNote = blob.read_shift(2);
5977 blob.l += 4;
5978 return out;
5979}
5980
5981/* [MS-XLS] 2.5.142 */
5982function parse_FtCf(blob) {
5983 var out = {};
5984 blob.l += 4;
5985 blob.cf = blob.read_shift(2);
5986 return out;
5987}
5988
5989/* [MS-XLS] 2.5.140 - 2.5.154 and friends */
5990function parse_FtSkip(blob) { blob.l += 2; blob.l += blob.read_shift(2); }
5991var FtTab = {
5992 /*::[*/0x00/*::]*/: parse_FtSkip, /* FtEnd */
5993 /*::[*/0x04/*::]*/: parse_FtSkip, /* FtMacro */
5994 /*::[*/0x05/*::]*/: parse_FtSkip, /* FtButton */
5995 /*::[*/0x06/*::]*/: parse_FtSkip, /* FtGmo */
5996 /*::[*/0x07/*::]*/: parse_FtCf, /* FtCf */
5997 /*::[*/0x08/*::]*/: parse_FtSkip, /* FtPioGrbit */
5998 /*::[*/0x09/*::]*/: parse_FtSkip, /* FtPictFmla */
5999 /*::[*/0x0A/*::]*/: parse_FtSkip, /* FtCbls */
6000 /*::[*/0x0B/*::]*/: parse_FtSkip, /* FtRbo */
6001 /*::[*/0x0C/*::]*/: parse_FtSkip, /* FtSbs */
6002 /*::[*/0x0D/*::]*/: parse_FtNts, /* FtNts */
6003 /*::[*/0x0E/*::]*/: parse_FtSkip, /* FtSbsFmla */
6004 /*::[*/0x0F/*::]*/: parse_FtSkip, /* FtGboData */
6005 /*::[*/0x10/*::]*/: parse_FtSkip, /* FtEdoData */
6006 /*::[*/0x11/*::]*/: parse_FtSkip, /* FtRboData */
6007 /*::[*/0x12/*::]*/: parse_FtSkip, /* FtCblsData */
6008 /*::[*/0x13/*::]*/: parse_FtSkip, /* FtLbsData */
6009 /*::[*/0x14/*::]*/: parse_FtSkip, /* FtCblsFmla */
6010 /*::[*/0x15/*::]*/: parse_FtCmo
6011};
6012function parse_FtArray(blob, length/*::, ot*/) {
6013 var tgt = blob.l + length;
6014 var fts = [];
6015 while(blob.l < tgt) {
6016 var ft = blob.read_shift(2);
6017 blob.l-=2;
6018 try {
6019 fts.push(FtTab[ft](blob, tgt - blob.l));
6020 } catch(e) { blob.l = tgt; return fts; }
6021 }
6022 if(blob.l != tgt) blob.l = tgt; //throw new Error("bad Object Ft-sequence");
6023 return fts;
6024}
6025
6026/* --- 2.4 Records --- */
6027
6028/* [MS-XLS] 2.4.21 */
6029function parse_BOF(blob, length) {
6030 var o = {BIFFVer:0, dt:0};
6031 o.BIFFVer = blob.read_shift(2); length -= 2;
6032 if(length >= 2) { o.dt = blob.read_shift(2); blob.l -= 2; }
6033 switch(o.BIFFVer) {
6034 case 0x0600: /* BIFF8 */
6035 case 0x0500: /* BIFF5 */
6036 case 0x0400: /* BIFF4 */
6037 case 0x0300: /* BIFF3 */
6038 case 0x0200: /* BIFF2 */
6039 case 0x0002: case 0x0007: /* BIFF2 */
6040 break;
6041 default: if(length > 6) throw new Error("Unexpected BIFF Ver " + o.BIFFVer);
6042 }
6043
6044 blob.read_shift(length);
6045 return o;
6046}
6047function write_BOF(wb/*:Workbook*/, t/*:number*/, o) {
6048 var h = 0x0600, w = 16;
6049 switch(o.bookType) {
6050 case 'biff8': break;
6051 case 'biff5': h = 0x0500; w = 8; break;
6052 case 'biff4': h = 0x0004; w = 6; break;
6053 case 'biff3': h = 0x0003; w = 6; break;
6054 case 'biff2': h = 0x0002; w = 4; break;
6055 case 'xla': break;
6056 default: throw new Error("unsupported BIFF version");
6057 }
6058 var out = new_buf(w);
6059 out.write_shift(2, h);
6060 out.write_shift(2, t);
6061 if(w > 4) out.write_shift(2, 0x7262);
6062 if(w > 6) out.write_shift(2, 0x07CD);
6063 if(w > 8) {
6064 out.write_shift(2, 0xC009);
6065 out.write_shift(2, 0x0001);
6066 out.write_shift(2, 0x0706);
6067 out.write_shift(2, 0x0000);
6068 }
6069 return out;
6070}
6071
6072
6073/* [MS-XLS] 2.4.146 */
6074function parse_InterfaceHdr(blob, length) {
6075 if(length === 0) return 0x04b0;
6076 if((blob.read_shift(2))!==0x04b0){/* empty */}
6077 return 0x04b0;
6078}
6079
6080
6081/* [MS-XLS] 2.4.349 */
6082function parse_WriteAccess(blob, length, opts) {
6083 if(opts.enc) { blob.l += length; return ""; }
6084 var l = blob.l;
6085 // TODO: make sure XLUnicodeString doesnt overrun
6086 var UserName = parse_XLUnicodeString2(blob, 0, opts);
6087 blob.read_shift(length + l - blob.l);
6088 return UserName;
6089}
6090function write_WriteAccess(s/*:string*/, opts) {
6091 var b8 = !opts || opts.biff == 8;
6092 var o = new_buf(b8 ? 112 : 54);
6093 o.write_shift(opts.biff == 8 ? 2 : 1, 7);
6094 if(b8) o.write_shift(1, 0);
6095 o.write_shift(4, 0x33336853);
6096 o.write_shift(4, (0x00534A74 | (b8 ? 0 : 0x20000000)));
6097 while(o.l < o.length) o.write_shift(1, (b8 ? 0 : 32));
6098 return o;
6099}
6100
6101/* [MS-XLS] 2.4.351 */
6102function parse_WsBool(blob, length, opts) {
6103 var flags = opts && opts.biff == 8 || length == 2 ? blob.read_shift(2) : (blob.l += length, 0);
6104 return { fDialog: flags & 0x10, fBelow: flags & 0x40, fRight: flags & 0x80 };
6105}
6106
6107/* [MS-XLS] 2.4.28 */
6108function parse_BoundSheet8(blob, length, opts) {
6109 var pos = blob.read_shift(4);
6110 var hidden = blob.read_shift(1) & 0x03;
6111 var dt = blob.read_shift(1);
6112 switch(dt) {
6113 case 0: dt = 'Worksheet'; break;
6114 case 1: dt = 'Macrosheet'; break;
6115 case 2: dt = 'Chartsheet'; break;
6116 case 6: dt = 'VBAModule'; break;
6117 }
6118 var name = parse_ShortXLUnicodeString(blob, 0, opts);
6119 if(name.length === 0) name = "Sheet1";
6120 return { pos:pos, hs:hidden, dt:dt, name:name };
6121}
6122function write_BoundSheet8(data, opts) {
6123 var w = (!opts || opts.biff >= 8 ? 2 : 1);
6124 var o = new_buf(8 + w * data.name.length);
6125 o.write_shift(4, data.pos);
6126 o.write_shift(1, data.hs || 0);
6127 o.write_shift(1, data.dt);
6128 o.write_shift(1, data.name.length);
6129 if(opts.biff >= 8) o.write_shift(1, 1);
6130 o.write_shift(w * data.name.length, data.name, opts.biff < 8 ? 'sbcs' : 'utf16le');
6131 var out = o.slice(0, o.l);
6132 out.l = o.l; return out;
6133}
6134
6135/* [MS-XLS] 2.4.265 TODO */
6136function parse_SST(blob, length)/*:SST*/ {
6137 var end = blob.l + length;
6138 var cnt = blob.read_shift(4);
6139 var ucnt = blob.read_shift(4);
6140 var strs/*:SST*/ = ([]/*:any*/);
6141 for(var i = 0; i != ucnt && blob.l < end; ++i) {
6142 strs.push(parse_XLUnicodeRichExtendedString(blob));
6143 }
6144 strs.Count = cnt; strs.Unique = ucnt;
6145 return strs;
6146}
6147function write_SST(sst, opts) {
6148 var header = new_buf(8);
6149 header.write_shift(4, sst.Count);
6150 header.write_shift(4, sst.Unique);
6151 var strs = [];
6152 for(var j = 0; j < sst.length; ++j) strs[j] = write_XLUnicodeRichExtendedString(sst[j], opts);
6153 var o = bconcat([header].concat(strs));
6154 /*::(*/o/*:: :any)*/.parts = [header.length].concat(strs.map(function(str) { return str.length; }));
6155 return o;
6156}
6157
6158/* [MS-XLS] 2.4.107 */
6159function parse_ExtSST(blob, length) {
6160 var extsst = {};
6161 extsst.dsst = blob.read_shift(2);
6162 blob.l += length-2;
6163 return extsst;
6164}
6165
6166
6167/* [MS-XLS] 2.4.221 TODO: check BIFF2-4 */
6168function parse_Row(blob) {
6169 var z = ({}/*:any*/);
6170 z.r = blob.read_shift(2);
6171 z.c = blob.read_shift(2);
6172 z.cnt = blob.read_shift(2) - z.c;
6173 var miyRw = blob.read_shift(2);
6174 blob.l += 4; // reserved(2), unused(2)
6175 var flags = blob.read_shift(1); // various flags
6176 blob.l += 3; // reserved(8), ixfe(12), flags(4)
6177 if(flags & 0x07) z.level = flags & 0x07;
6178 // collapsed: flags & 0x10
6179 if(flags & 0x20) z.hidden = true;
6180 if(flags & 0x40) z.hpt = miyRw / 20;
6181 return z;
6182}
6183
6184
6185/* [MS-XLS] 2.4.125 */
6186function parse_ForceFullCalculation(blob) {
6187 var header = parse_frtHeader(blob);
6188 if(header.type != 0x08A3) throw new Error("Invalid Future Record " + header.type);
6189 var fullcalc = blob.read_shift(4);
6190 return fullcalc !== 0x0;
6191}
6192
6193
6194
6195
6196
6197/* [MS-XLS] 2.4.215 rt */
6198function parse_RecalcId(blob) {
6199 blob.read_shift(2);
6200 return blob.read_shift(4);
6201}
6202
6203/* [MS-XLS] 2.4.87 */
6204function parse_DefaultRowHeight(blob, length, opts) {
6205 var f = 0;
6206 if(!(opts && opts.biff == 2)) {
6207 f = blob.read_shift(2);
6208 }
6209 var miyRw = blob.read_shift(2);
6210 if((opts && opts.biff == 2)) {
6211 f = 1 - (miyRw >> 15); miyRw &= 0x7fff;
6212 }
6213 var fl = {Unsynced:f&1,DyZero:(f&2)>>1,ExAsc:(f&4)>>2,ExDsc:(f&8)>>3};
6214 return [fl, miyRw];
6215}
6216
6217/* [MS-XLS] 2.4.345 TODO */
6218function parse_Window1(blob) {
6219 var xWn = blob.read_shift(2), yWn = blob.read_shift(2), dxWn = blob.read_shift(2), dyWn = blob.read_shift(2);
6220 var flags = blob.read_shift(2), iTabCur = blob.read_shift(2), iTabFirst = blob.read_shift(2);
6221 var ctabSel = blob.read_shift(2), wTabRatio = blob.read_shift(2);
6222 return { Pos: [xWn, yWn], Dim: [dxWn, dyWn], Flags: flags, CurTab: iTabCur,
6223 FirstTab: iTabFirst, Selected: ctabSel, TabRatio: wTabRatio };
6224}
6225function write_Window1(/*::opts*/) {
6226 var o = new_buf(18);
6227 o.write_shift(2, 0);
6228 o.write_shift(2, 0);
6229 o.write_shift(2, 0x7260);
6230 o.write_shift(2, 0x44c0);
6231 o.write_shift(2, 0x38);
6232 o.write_shift(2, 0);
6233 o.write_shift(2, 0);
6234 o.write_shift(2, 1);
6235 o.write_shift(2, 0x01f4);
6236 return o;
6237}
6238/* [MS-XLS] 2.4.346 TODO */
6239function parse_Window2(blob, length, opts) {
6240 if(opts && opts.biff >= 2 && opts.biff < 5) return {};
6241 var f = blob.read_shift(2);
6242 return { RTL: f & 0x40 };
6243}
6244function write_Window2(view) {
6245 var o = new_buf(18), f = 0x6b6;
6246 if(view && view.RTL) f |= 0x40;
6247 o.write_shift(2, f);
6248 o.write_shift(4, 0);
6249 o.write_shift(4, 64);
6250 o.write_shift(4, 0);
6251 o.write_shift(4, 0);
6252 return o;
6253}
6254
6255/* [MS-XLS] 2.4.189 TODO */
6256function parse_Pane(/*blob, length, opts*/) {
6257}
6258
6259/* [MS-XLS] 2.4.122 TODO */
6260function parse_Font(blob, length, opts) {
6261 var o/*:any*/ = {
6262 dyHeight: blob.read_shift(2),
6263 fl: blob.read_shift(2)
6264 };
6265 switch((opts && opts.biff) || 8) {
6266 case 2: break;
6267 case 3: case 4: blob.l += 2; break;
6268 default: blob.l += 10; break;
6269 }
6270 o.name = parse_ShortXLUnicodeString(blob, 0, opts);
6271 return o;
6272}
6273function write_Font(data, opts) {
6274 var name = data.name || "Arial";
6275 var b5 = (opts && (opts.biff == 5)), w = (b5 ? (15 + name.length) : (16 + 2 * name.length));
6276 var o = new_buf(w);
6277 o.write_shift(2, (data.sz || 12) * 20);
6278 o.write_shift(4, 0);
6279 o.write_shift(2, 400);
6280 o.write_shift(4, 0);
6281 o.write_shift(2, 0);
6282 o.write_shift(1, name.length);
6283 if(!b5) o.write_shift(1, 1);
6284 o.write_shift((b5 ? 1 : 2) * name.length, name, (b5 ? "sbcs" : "utf16le"));
6285 return o;
6286}
6287
6288/* [MS-XLS] 2.4.149 */
6289function parse_LabelSst(blob) {
6290 var cell = parse_XLSCell(blob);
6291 cell.isst = blob.read_shift(4);
6292 return cell;
6293}
6294function write_LabelSst(R/*:number*/, C/*:number*/, v/*:number*/, os/*:number*/ /*::, opts*/) {
6295 var o = new_buf(10);
6296 write_XLSCell(R, C, os, o);
6297 o.write_shift(4, v);
6298 return o;
6299}
6300
6301/* [MS-XLS] 2.4.148 */
6302function parse_Label(blob, length, opts) {
6303 if(opts.biffguess && opts.biff == 2) opts.biff = 5;
6304 var target = blob.l + length;
6305 var cell = parse_XLSCell(blob, 6);
6306 if(opts.biff == 2) blob.l++;
6307 var str = parse_XLUnicodeString(blob, target - blob.l, opts);
6308 cell.val = str;
6309 return cell;
6310}
6311function write_Label(R/*:number*/, C/*:number*/, v/*:string*/, os/*:number*/, opts) {
6312 var b8 = !opts || opts.biff == 8;
6313 var o = new_buf(6 + 2 + (+b8) + (1 + b8) * v.length);
6314 write_XLSCell(R, C, os, o);
6315 o.write_shift(2, v.length);
6316 if(b8) o.write_shift(1, 1);
6317 o.write_shift((1 + b8) * v.length, v, b8 ? 'utf16le' : 'sbcs');
6318 return o;
6319}
6320
6321
6322/* [MS-XLS] 2.4.126 Number Formats */
6323function parse_Format(blob, length, opts) {
6324 var numFmtId = blob.read_shift(2);
6325 var fmtstr = parse_XLUnicodeString2(blob, 0, opts);
6326 return [numFmtId, fmtstr];
6327}
6328function write_Format(i/*:number*/, f/*:string*/, opts, o) {
6329 var b5 = (opts && (opts.biff == 5));
6330 if(!o) o = new_buf(b5 ? (3 + f.length) : (5 + 2 * f.length));
6331 o.write_shift(2, i);
6332 o.write_shift((b5 ? 1 : 2), f.length);
6333 if(!b5) o.write_shift(1, 1);
6334 o.write_shift((b5 ? 1 : 2) * f.length, f, (b5 ? 'sbcs' : 'utf16le'));
6335 var out = (o.length > o.l) ? o.slice(0, o.l) : o;
6336 if(out.l == null) out.l = out.length;
6337 return out;
6338}
6339var parse_BIFF2Format = parse_XLUnicodeString2;
6340
6341/* [MS-XLS] 2.4.90 */
6342function parse_Dimensions(blob, length, opts) {
6343 var end = blob.l + length;
6344 var w = opts.biff == 8 || !opts.biff ? 4 : 2;
6345 var r = blob.read_shift(w), R = blob.read_shift(w);
6346 var c = blob.read_shift(2), C = blob.read_shift(2);
6347 blob.l = end;
6348 return {s: {r:r, c:c}, e: {r:R, c:C}};
6349}
6350function write_Dimensions(range, opts) {
6351 var w = opts.biff == 8 || !opts.biff ? 4 : 2;
6352 var o = new_buf(2*w + 6);
6353 o.write_shift(w, range.s.r);
6354 o.write_shift(w, range.e.r + 1);
6355 o.write_shift(2, range.s.c);
6356 o.write_shift(2, range.e.c + 1);
6357 o.write_shift(2, 0);
6358 return o;
6359}
6360
6361/* [MS-XLS] 2.4.220 */
6362function parse_RK(blob) {
6363 var rw = blob.read_shift(2), col = blob.read_shift(2);
6364 var rkrec = parse_RkRec(blob);
6365 return {r:rw, c:col, ixfe:rkrec[0], rknum:rkrec[1]};
6366}
6367
6368/* [MS-XLS] 2.4.175 */
6369function parse_MulRk(blob, length) {
6370 var target = blob.l + length - 2;
6371 var rw = blob.read_shift(2), col = blob.read_shift(2);
6372 var rkrecs = [];
6373 while(blob.l < target) rkrecs.push(parse_RkRec(blob));
6374 if(blob.l !== target) throw new Error("MulRK read error");
6375 var lastcol = blob.read_shift(2);
6376 if(rkrecs.length != lastcol - col + 1) throw new Error("MulRK length mismatch");
6377 return {r:rw, c:col, C:lastcol, rkrec:rkrecs};
6378}
6379/* [MS-XLS] 2.4.174 */
6380function parse_MulBlank(blob, length) {
6381 var target = blob.l + length - 2;
6382 var rw = blob.read_shift(2), col = blob.read_shift(2);
6383 var ixfes = [];
6384 while(blob.l < target) ixfes.push(blob.read_shift(2));
6385 if(blob.l !== target) throw new Error("MulBlank read error");
6386 var lastcol = blob.read_shift(2);
6387 if(ixfes.length != lastcol - col + 1) throw new Error("MulBlank length mismatch");
6388 return {r:rw, c:col, C:lastcol, ixfe:ixfes};
6389}
6390
6391/* [MS-XLS] 2.5.20 2.5.249 TODO: interpret values here */
6392function parse_CellStyleXF(blob, length, style, opts) {
6393 var o = {};
6394 var a = blob.read_shift(4), b = blob.read_shift(4);
6395 var c = blob.read_shift(4), d = blob.read_shift(2);
6396 o.patternType = XLSFillPattern[c >> 26];
6397
6398 if(!opts.cellStyles) return o;
6399 o.alc = a & 0x07;
6400 o.fWrap = (a >> 3) & 0x01;
6401 o.alcV = (a >> 4) & 0x07;
6402 o.fJustLast = (a >> 7) & 0x01;
6403 o.trot = (a >> 8) & 0xFF;
6404 o.cIndent = (a >> 16) & 0x0F;
6405 o.fShrinkToFit = (a >> 20) & 0x01;
6406 o.iReadOrder = (a >> 22) & 0x02;
6407 o.fAtrNum = (a >> 26) & 0x01;
6408 o.fAtrFnt = (a >> 27) & 0x01;
6409 o.fAtrAlc = (a >> 28) & 0x01;
6410 o.fAtrBdr = (a >> 29) & 0x01;
6411 o.fAtrPat = (a >> 30) & 0x01;
6412 o.fAtrProt = (a >> 31) & 0x01;
6413
6414 o.dgLeft = b & 0x0F;
6415 o.dgRight = (b >> 4) & 0x0F;
6416 o.dgTop = (b >> 8) & 0x0F;
6417 o.dgBottom = (b >> 12) & 0x0F;
6418 o.icvLeft = (b >> 16) & 0x7F;
6419 o.icvRight = (b >> 23) & 0x7F;
6420 o.grbitDiag = (b >> 30) & 0x03;
6421
6422 o.icvTop = c & 0x7F;
6423 o.icvBottom = (c >> 7) & 0x7F;
6424 o.icvDiag = (c >> 14) & 0x7F;
6425 o.dgDiag = (c >> 21) & 0x0F;
6426
6427 o.icvFore = d & 0x7F;
6428 o.icvBack = (d >> 7) & 0x7F;
6429 o.fsxButton = (d >> 14) & 0x01;
6430 return o;
6431}
6432//function parse_CellXF(blob, length, opts) {return parse_CellStyleXF(blob,length,0, opts);}
6433//function parse_StyleXF(blob, length, opts) {return parse_CellStyleXF(blob,length,1, opts);}
6434
6435/* [MS-XLS] 2.4.353 TODO: actually do this right */
6436function parse_XF(blob, length, opts) {
6437 var o = {};
6438 o.ifnt = blob.read_shift(2); o.numFmtId = blob.read_shift(2); o.flags = blob.read_shift(2);
6439 o.fStyle = (o.flags >> 2) & 0x01;
6440 length -= 6;
6441 o.data = parse_CellStyleXF(blob, length, o.fStyle, opts);
6442 return o;
6443}
6444function write_XF(data, ixfeP, opts, o) {
6445 var b5 = (opts && (opts.biff == 5));
6446 if(!o) o = new_buf(b5 ? 16 : 20);
6447 o.write_shift(2, 0);
6448 if(data.style) {
6449 o.write_shift(2, (data.numFmtId||0));
6450 o.write_shift(2, 0xFFF4);
6451 } else {
6452 o.write_shift(2, (data.numFmtId||0));
6453 o.write_shift(2, (ixfeP<<4));
6454 }
6455 var f = 0;
6456 if(data.numFmtId > 0 && b5) f |= 0x0400;
6457 o.write_shift(4, f);
6458 o.write_shift(4, 0);
6459 if(!b5) o.write_shift(4, 0);
6460 o.write_shift(2, 0);
6461 return o;
6462}
6463
6464/* [MS-XLS] 2.4.134 */
6465function parse_Guts(blob) {
6466 blob.l += 4;
6467 var out = [blob.read_shift(2), blob.read_shift(2)];
6468 if(out[0] !== 0) out[0]--;
6469 if(out[1] !== 0) out[1]--;
6470 if(out[0] > 7 || out[1] > 7) throw new Error("Bad Gutters: " + out.join("|"));
6471 return out;
6472}
6473function write_Guts(guts/*:Array<number>*/) {
6474 var o = new_buf(8);
6475 o.write_shift(4, 0);
6476 o.write_shift(2, guts[0] ? guts[0] + 1 : 0);
6477 o.write_shift(2, guts[1] ? guts[1] + 1 : 0);
6478 return o;
6479}
6480
6481/* [MS-XLS] 2.4.24 */
6482function parse_BoolErr(blob, length, opts) {
6483 var cell = parse_XLSCell(blob, 6);
6484 if(opts.biff == 2 || length == 9) ++blob.l;
6485 var val = parse_Bes(blob, 2);
6486 cell.val = val;
6487 cell.t = (val === true || val === false) ? 'b' : 'e';
6488 return cell;
6489}
6490function write_BoolErr(R/*:number*/, C/*:number*/, v, os/*:number*/, opts, t/*:string*/) {
6491 var o = new_buf(8);
6492 write_XLSCell(R, C, os, o);
6493 write_Bes(v, t, o);
6494 return o;
6495}
6496
6497/* [MS-XLS] 2.4.180 Number */
6498function parse_Number(blob, length, opts) {
6499 if(opts.biffguess && opts.biff == 2) opts.biff = 5;
6500 var cell = parse_XLSCell(blob, 6);
6501 var xnum = parse_Xnum(blob, 8);
6502 cell.val = xnum;
6503 return cell;
6504}
6505function write_Number(R/*:number*/, C/*:number*/, v, os/*:: :number, opts*/) {
6506 var o = new_buf(14);
6507 write_XLSCell(R, C, os, o);
6508 write_Xnum(v, o);
6509 return o;
6510}
6511
6512var parse_XLHeaderFooter = parse_OptXLUnicodeString; // TODO: parse 2.4.136
6513
6514/* [MS-XLS] 2.4.271 */
6515function parse_SupBook(blob, length, opts) {
6516 var end = blob.l + length;
6517 var ctab = blob.read_shift(2);
6518 var cch = blob.read_shift(2);
6519 opts.sbcch = cch;
6520 if(cch == 0x0401 || cch == 0x3A01) return [cch, ctab];
6521 if(cch < 0x01 || cch >0xff) throw new Error("Unexpected SupBook type: "+cch);
6522 var virtPath = parse_XLUnicodeStringNoCch(blob, cch);
6523 /* TODO: 2.5.277 Virtual Path */
6524 var rgst = [];
6525 while(end > blob.l) rgst.push(parse_XLUnicodeString(blob));
6526 return [cch, ctab, virtPath, rgst];
6527}
6528
6529/* [MS-XLS] 2.4.105 TODO */
6530function parse_ExternName(blob, length, opts) {
6531 var flags = blob.read_shift(2);
6532 var body;
6533 var o = ({
6534 fBuiltIn: flags & 0x01,
6535 fWantAdvise: (flags >>> 1) & 0x01,
6536 fWantPict: (flags >>> 2) & 0x01,
6537 fOle: (flags >>> 3) & 0x01,
6538 fOleLink: (flags >>> 4) & 0x01,
6539 cf: (flags >>> 5) & 0x3FF,
6540 fIcon: flags >>> 15 & 0x01
6541 }/*:any*/);
6542 if(opts.sbcch === 0x3A01) body = parse_AddinUdf(blob, length-2, opts);
6543 //else throw new Error("unsupported SupBook cch: " + opts.sbcch);
6544 o.body = body || blob.read_shift(length-2);
6545 if(typeof body === "string") o.Name = body;
6546 return o;
6547}
6548
6549/* [MS-XLS] 2.4.150 TODO */
6550var XLSLblBuiltIn = [
6551 "_xlnm.Consolidate_Area",
6552 "_xlnm.Auto_Open",
6553 "_xlnm.Auto_Close",
6554 "_xlnm.Extract",
6555 "_xlnm.Database",
6556 "_xlnm.Criteria",
6557 "_xlnm.Print_Area",
6558 "_xlnm.Print_Titles",
6559 "_xlnm.Recorder",
6560 "_xlnm.Data_Form",
6561 "_xlnm.Auto_Activate",
6562 "_xlnm.Auto_Deactivate",
6563 "_xlnm.Sheet_Title",
6564 "_xlnm._FilterDatabase"
6565];
6566function parse_Lbl(blob, length, opts) {
6567 var target = blob.l + length;
6568 var flags = blob.read_shift(2);
6569 var chKey = blob.read_shift(1);
6570 var cch = blob.read_shift(1);
6571 var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
6572 var itab = 0;
6573 if(!opts || opts.biff >= 5) {
6574 if(opts.biff != 5) blob.l += 2;
6575 itab = blob.read_shift(2);
6576 if(opts.biff == 5) blob.l += 2;
6577 blob.l += 4;
6578 }
6579 var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
6580 if(flags & 0x20) name = XLSLblBuiltIn[name.charCodeAt(0)];
6581 var npflen = target - blob.l; if(opts && opts.biff == 2) --npflen;
6582 var rgce = (target == blob.l || cce === 0 || !(npflen > 0)) ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
6583 return {
6584 chKey: chKey,
6585 Name: name,
6586 itab: itab,
6587 rgce: rgce
6588 };
6589}
6590
6591/* [MS-XLS] 2.4.106 TODO: verify filename encoding */
6592function parse_ExternSheet(blob, length, opts) {
6593 if(opts.biff < 8) return parse_BIFF5ExternSheet(blob, length, opts);
6594 var o = [], target = blob.l + length, len = blob.read_shift(opts.biff > 8 ? 4 : 2);
6595 while(len-- !== 0) o.push(parse_XTI(blob, opts.biff > 8 ? 12 : 6, opts));
6596 // [iSupBook, itabFirst, itabLast];
6597 if(blob.l != target) throw new Error("Bad ExternSheet: " + blob.l + " != " + target);
6598 return o;
6599}
6600function parse_BIFF5ExternSheet(blob, length, opts) {
6601 if(blob[blob.l + 1] == 0x03) blob[blob.l]++;
6602 var o = parse_ShortXLUnicodeString(blob, length, opts);
6603 return o.charCodeAt(0) == 0x03 ? o.slice(1) : o;
6604}
6605
6606/* [MS-XLS] 2.4.176 TODO: check older biff */
6607function parse_NameCmt(blob, length, opts) {
6608 if(opts.biff < 8) { blob.l += length; return; }
6609 var cchName = blob.read_shift(2);
6610 var cchComment = blob.read_shift(2);
6611 var name = parse_XLUnicodeStringNoCch(blob, cchName, opts);
6612 var comment = parse_XLUnicodeStringNoCch(blob, cchComment, opts);
6613 return [name, comment];
6614}
6615
6616/* [MS-XLS] 2.4.260 */
6617function parse_ShrFmla(blob, length, opts) {
6618 var ref = parse_RefU(blob, 6);
6619 blob.l++;
6620 var cUse = blob.read_shift(1);
6621 length -= 8;
6622 return [parse_SharedParsedFormula(blob, length, opts), cUse, ref];
6623}
6624
6625/* [MS-XLS] 2.4.4 TODO */
6626function parse_Array(blob, length, opts) {
6627 var ref = parse_Ref(blob, 6);
6628 /* TODO: fAlwaysCalc */
6629 switch(opts.biff) {
6630 case 2: blob.l ++; length -= 7; break;
6631 case 3: case 4: blob.l += 2; length -= 8; break;
6632 default: blob.l += 6; length -= 12;
6633 }
6634 return [ref, parse_ArrayParsedFormula(blob, length, opts, ref)];
6635}
6636
6637/* [MS-XLS] 2.4.173 */
6638function parse_MTRSettings(blob) {
6639 var fMTREnabled = blob.read_shift(4) !== 0x00;
6640 var fUserSetThreadCount = blob.read_shift(4) !== 0x00;
6641 var cUserThreadCount = blob.read_shift(4);
6642 return [fMTREnabled, fUserSetThreadCount, cUserThreadCount];
6643}
6644
6645/* [MS-XLS] 2.5.186 TODO: BIFF5 */
6646function parse_NoteSh(blob, length, opts) {
6647 if(opts.biff < 8) return;
6648 var row = blob.read_shift(2), col = blob.read_shift(2);
6649 var flags = blob.read_shift(2), idObj = blob.read_shift(2);
6650 var stAuthor = parse_XLUnicodeString2(blob, 0, opts);
6651 if(opts.biff < 8) blob.read_shift(1);
6652 return [{r:row,c:col}, stAuthor, idObj, flags];
6653}
6654
6655/* [MS-XLS] 2.4.179 */
6656function parse_Note(blob, length, opts) {
6657 /* TODO: Support revisions */
6658 return parse_NoteSh(blob, length, opts);
6659}
6660
6661/* [MS-XLS] 2.4.168 */
6662function parse_MergeCells(blob, length)/*:Array<Range>*/ {
6663 var merges/*:Array<Range>*/ = [];
6664 var cmcs = blob.read_shift(2);
6665 while (cmcs--) merges.push(parse_Ref8U(blob,length));
6666 return merges;
6667}
6668function write_MergeCells(merges/*:Array<Range>*/) {
6669 var o = new_buf(2 + merges.length * 8);
6670 o.write_shift(2, merges.length);
6671 for(var i = 0; i < merges.length; ++i) write_Ref8U(merges[i], o);
6672 return o;
6673}
6674
6675/* [MS-XLS] 2.4.181 TODO: parse all the things! */
6676function parse_Obj(blob, length, opts) {
6677 if(opts && opts.biff < 8) return parse_BIFF5Obj(blob, length, opts);
6678 var cmo = parse_FtCmo(blob, 22); // id, ot, flags
6679 var fts = parse_FtArray(blob, length-22, cmo[1]);
6680 return { cmo: cmo, ft:fts };
6681}
6682/* from older spec */
6683var parse_BIFF5OT = [];
6684parse_BIFF5OT[0x08] = function(blob, length) {
6685 var tgt = blob.l + length;
6686 blob.l += 10; // todo
6687 var cf = blob.read_shift(2);
6688 blob.l += 4;
6689 blob.l += 2; //var cbPictFmla = blob.read_shift(2);
6690 blob.l += 2;
6691 blob.l += 2; //var grbit = blob.read_shift(2);
6692 blob.l += 4;
6693 var cchName = blob.read_shift(1);
6694 blob.l += cchName; // TODO: stName
6695 blob.l = tgt; // TODO: fmla
6696 return { fmt:cf };
6697};
6698
6699function parse_BIFF5Obj(blob, length, opts) {
6700 blob.l += 4; //var cnt = blob.read_shift(4);
6701 var ot = blob.read_shift(2);
6702 var id = blob.read_shift(2);
6703 var grbit = blob.read_shift(2);
6704 blob.l += 2; //var colL = blob.read_shift(2);
6705 blob.l += 2; //var dxL = blob.read_shift(2);
6706 blob.l += 2; //var rwT = blob.read_shift(2);
6707 blob.l += 2; //var dyT = blob.read_shift(2);
6708 blob.l += 2; //var colR = blob.read_shift(2);
6709 blob.l += 2; //var dxR = blob.read_shift(2);
6710 blob.l += 2; //var rwB = blob.read_shift(2);
6711 blob.l += 2; //var dyB = blob.read_shift(2);
6712 blob.l += 2; //var cbMacro = blob.read_shift(2);
6713 blob.l += 6;
6714 length -= 36;
6715 var fts = [];
6716 fts.push((parse_BIFF5OT[ot]||parsenoop)(blob, length, opts));
6717 return { cmo: [id, ot, grbit], ft:fts };
6718}
6719
6720/* [MS-XLS] 2.4.329 TODO: parse properly */
6721function parse_TxO(blob, length, opts) {
6722 var s = blob.l;
6723 var texts = "";
6724try {
6725 blob.l += 4;
6726 var ot = (opts.lastobj||{cmo:[0,0]}).cmo[1];
6727 var controlInfo; // eslint-disable-line no-unused-vars
6728 if([0,5,7,11,12,14].indexOf(ot) == -1) blob.l += 6;
6729 else controlInfo = parse_ControlInfo(blob, 6, opts);
6730 var cchText = blob.read_shift(2);
6731 /*var cbRuns = */blob.read_shift(2);
6732 /*var ifntEmpty = */parseuint16(blob, 2);
6733 var len = blob.read_shift(2);
6734 blob.l += len;
6735 //var fmla = parse_ObjFmla(blob, s + length - blob.l);
6736
6737 for(var i = 1; i < blob.lens.length-1; ++i) {
6738 if(blob.l-s != blob.lens[i]) throw new Error("TxO: bad continue record");
6739 var hdr = blob[blob.l];
6740 var t = parse_XLUnicodeStringNoCch(blob, blob.lens[i+1]-blob.lens[i]-1);
6741 texts += t;
6742 if(texts.length >= (hdr ? cchText : 2*cchText)) break;
6743 }
6744 if(texts.length !== cchText && texts.length !== cchText*2) {
6745 throw new Error("cchText: " + cchText + " != " + texts.length);
6746 }
6747
6748 blob.l = s + length;
6749 /* [MS-XLS] 2.5.272 TxORuns */
6750// var rgTxoRuns = [];
6751// for(var j = 0; j != cbRuns/8-1; ++j) blob.l += 8;
6752// var cchText2 = blob.read_shift(2);
6753// if(cchText2 !== cchText) throw new Error("TxOLastRun mismatch: " + cchText2 + " " + cchText);
6754// blob.l += 6;
6755// if(s + length != blob.l) throw new Error("TxO " + (s + length) + ", at " + blob.l);
6756 return { t: texts };
6757} catch(e) { blob.l = s + length; return { t: texts }; }
6758}
6759
6760/* [MS-XLS] 2.4.140 */
6761function parse_HLink(blob, length) {
6762 var ref = parse_Ref8U(blob, 8);
6763 blob.l += 16; /* CLSID */
6764 var hlink = parse_Hyperlink(blob, length-24);
6765 return [ref, hlink];
6766}
6767function write_HLink(hl) {
6768 var O = new_buf(24);
6769 var ref = decode_cell(hl[0]);
6770 O.write_shift(2, ref.r); O.write_shift(2, ref.r);
6771 O.write_shift(2, ref.c); O.write_shift(2, ref.c);
6772 var clsid = "d0 c9 ea 79 f9 ba ce 11 8c 82 00 aa 00 4b a9 0b".split(" ");
6773 for(var i = 0; i < 16; ++i) O.write_shift(1, parseInt(clsid[i], 16));
6774 return bconcat([O, write_Hyperlink(hl[1])]);
6775}
6776
6777
6778/* [MS-XLS] 2.4.141 */
6779function parse_HLinkTooltip(blob, length) {
6780 blob.read_shift(2);
6781 var ref = parse_Ref8U(blob, 8);
6782 var wzTooltip = blob.read_shift((length-10)/2, 'dbcs-cont');
6783 wzTooltip = wzTooltip.replace(chr0,"");
6784 return [ref, wzTooltip];
6785}
6786function write_HLinkTooltip(hl) {
6787 var TT = hl[1].Tooltip;
6788 var O = new_buf(10 + 2 * (TT.length + 1));
6789 O.write_shift(2, 0x0800);
6790 var ref = decode_cell(hl[0]);
6791 O.write_shift(2, ref.r); O.write_shift(2, ref.r);
6792 O.write_shift(2, ref.c); O.write_shift(2, ref.c);
6793 for(var i = 0; i < TT.length; ++i) O.write_shift(2, TT.charCodeAt(i));
6794 O.write_shift(2, 0);
6795 return O;
6796}
6797
6798/* [MS-XLS] 2.4.63 */
6799function parse_Country(blob)/*:[string|number, string|number]*/ {
6800 var o = [0,0], d;
6801 d = blob.read_shift(2); o[0] = CountryEnum[d] || d;
6802 d = blob.read_shift(2); o[1] = CountryEnum[d] || d;
6803 return o;
6804}
6805function write_Country(o) {
6806 if(!o) o = new_buf(4);
6807 o.write_shift(2, 0x01);
6808 o.write_shift(2, 0x01);
6809 return o;
6810}
6811
6812/* [MS-XLS] 2.4.50 ClrtClient */
6813function parse_ClrtClient(blob) {
6814 var ccv = blob.read_shift(2);
6815 var o = [];
6816 while(ccv-->0) o.push(parse_LongRGB(blob, 8));
6817 return o;
6818}
6819
6820/* [MS-XLS] 2.4.188 */
6821function parse_Palette(blob) {
6822 var ccv = blob.read_shift(2);
6823 var o = [];
6824 while(ccv-->0) o.push(parse_LongRGB(blob, 8));
6825 return o;
6826}
6827
6828/* [MS-XLS] 2.4.354 */
6829function parse_XFCRC(blob) {
6830 blob.l += 2;
6831 var o = {cxfs:0, crc:0};
6832 o.cxfs = blob.read_shift(2);
6833 o.crc = blob.read_shift(4);
6834 return o;
6835}
6836
6837/* [MS-XLS] 2.4.53 TODO: parse flags */
6838/* [MS-XLSB] 2.4.323 TODO: parse flags */
6839function parse_ColInfo(blob, length, opts) {
6840 if(!opts.cellStyles) return parsenoop(blob, length);
6841 var w = opts && opts.biff >= 12 ? 4 : 2;
6842 var colFirst = blob.read_shift(w);
6843 var colLast = blob.read_shift(w);
6844 var coldx = blob.read_shift(w);
6845 var ixfe = blob.read_shift(w);
6846 var flags = blob.read_shift(2);
6847 if(w == 2) blob.l += 2;
6848 var o = ({s:colFirst, e:colLast, w:coldx, ixfe:ixfe, flags:flags}/*:any*/);
6849 if(opts.biff >= 5 || !opts.biff) o.level = (flags >> 8) & 0x7;
6850 return o;
6851}
6852function write_ColInfo(col, idx) {
6853 var o = new_buf(12);
6854 o.write_shift(2, idx);
6855 o.write_shift(2, idx);
6856 o.write_shift(2, col.width * 256);
6857 o.write_shift(2, 0);
6858 var f = 0;
6859 if(col.hidden) f |= 1;
6860 o.write_shift(1, f);
6861 f = col.level || 0;
6862 o.write_shift(1, f);
6863 o.write_shift(2, 0);
6864 return o;
6865}
6866
6867/* [MS-XLS] 2.4.257 */
6868function parse_Setup(blob, length) {
6869 var o = {};
6870 if(length < 32) return o;
6871 blob.l += 16;
6872 o.header = parse_Xnum(blob, 8);
6873 o.footer = parse_Xnum(blob, 8);
6874 blob.l += 2;
6875 return o;
6876}
6877
6878/* [MS-XLS] 2.4.261 */
6879function parse_ShtProps(blob, length, opts) {
6880 var def = {area:false};
6881 if(opts.biff != 5) { blob.l += length; return def; }
6882 var d = blob.read_shift(1); blob.l += 3;
6883 if((d & 0x10)) def.area = true;
6884 return def;
6885}
6886
6887/* [MS-XLS] 2.4.241 */
6888function write_RRTabId(n/*:number*/) {
6889 var out = new_buf(2 * n);
6890 for(var i = 0; i < n; ++i) out.write_shift(2, i+1);
6891 return out;
6892}
6893
6894var parse_Blank = parse_XLSCell; /* [MS-XLS] 2.4.20 Just the cell */
6895var parse_Scl = parseuint16a; /* [MS-XLS] 2.4.247 num, den */
6896var parse_String = parse_XLUnicodeString; /* [MS-XLS] 2.4.268 */
6897
6898/* --- Specific to versions before BIFF8 --- */
6899function parse_ImData(blob) {
6900 var cf = blob.read_shift(2);
6901 var env = blob.read_shift(2);
6902 var lcb = blob.read_shift(4);
6903 var o = {fmt:cf, env:env, len:lcb, data:blob.slice(blob.l,blob.l+lcb)};
6904 blob.l += lcb;
6905 return o;
6906}
6907
6908/* BIFF2_??? where ??? is the name from [XLS] */
6909function parse_BIFF2STR(blob, length, opts) {
6910 if(opts.biffguess && opts.biff == 5) opts.biff = 2;
6911 var cell = parse_XLSCell(blob, 6);
6912 ++blob.l;
6913 var str = parse_XLUnicodeString2(blob, length-7, opts);
6914 cell.t = 'str';
6915 cell.val = str;
6916 return cell;
6917}
6918
6919function parse_BIFF2NUM(blob/*::, length*/) {
6920 var cell = parse_XLSCell(blob, 6);
6921 ++blob.l;
6922 var num = parse_Xnum(blob, 8);
6923 cell.t = 'n';
6924 cell.val = num;
6925 return cell;
6926}
6927function write_BIFF2NUM(r/*:number*/, c/*:number*/, val/*:number*/) {
6928 var out = new_buf(15);
6929 write_BIFF2Cell(out, r, c);
6930 out.write_shift(8, val, 'f');
6931 return out;
6932}
6933
6934function parse_BIFF2INT(blob) {
6935 var cell = parse_XLSCell(blob, 6);
6936 ++blob.l;
6937 var num = blob.read_shift(2);
6938 cell.t = 'n';
6939 cell.val = num;
6940 return cell;
6941}
6942function write_BIFF2INT(r/*:number*/, c/*:number*/, val/*:number*/) {
6943 var out = new_buf(9);
6944 write_BIFF2Cell(out, r, c);
6945 out.write_shift(2, val);
6946 return out;
6947}
6948
6949function parse_BIFF2STRING(blob) {
6950 var cch = blob.read_shift(1);
6951 if(cch === 0) { blob.l++; return ""; }
6952 return blob.read_shift(cch, 'sbcs-cont');
6953}
6954
6955/* TODO: convert to BIFF8 font struct */
6956function parse_BIFF2FONTXTRA(blob, length) {
6957 blob.l += 6; // unknown
6958 blob.l += 2; // font weight "bls"
6959 blob.l += 1; // charset
6960 blob.l += 3; // unknown
6961 blob.l += 1; // font family
6962 blob.l += length - 13;
6963}
6964
6965/* TODO: parse rich text runs */
6966function parse_RString(blob, length, opts) {
6967 var end = blob.l + length;
6968 var cell = parse_XLSCell(blob, 6);
6969 var cch = blob.read_shift(2);
6970 var str = parse_XLUnicodeStringNoCch(blob, cch, opts);
6971 blob.l = end;
6972 cell.t = 'str';
6973 cell.val = str;
6974 return cell;
6975}
6976/* from js-harb (C) 2014-present SheetJS */
6977var DBF = (function() {
6978var dbf_codepage_map = {
6979 /* Code Pages Supported by Visual FoxPro */
6980 /*::[*/0x01/*::]*/: 437, /*::[*/0x02/*::]*/: 850,
6981 /*::[*/0x03/*::]*/: 1252, /*::[*/0x04/*::]*/: 10000,
6982 /*::[*/0x64/*::]*/: 852, /*::[*/0x65/*::]*/: 866,
6983 /*::[*/0x66/*::]*/: 865, /*::[*/0x67/*::]*/: 861,
6984 /*::[*/0x68/*::]*/: 895, /*::[*/0x69/*::]*/: 620,
6985 /*::[*/0x6A/*::]*/: 737, /*::[*/0x6B/*::]*/: 857,
6986 /*::[*/0x78/*::]*/: 950, /*::[*/0x79/*::]*/: 949,
6987 /*::[*/0x7A/*::]*/: 936, /*::[*/0x7B/*::]*/: 932,
6988 /*::[*/0x7C/*::]*/: 874, /*::[*/0x7D/*::]*/: 1255,
6989 /*::[*/0x7E/*::]*/: 1256, /*::[*/0x96/*::]*/: 10007,
6990 /*::[*/0x97/*::]*/: 10029, /*::[*/0x98/*::]*/: 10006,
6991 /*::[*/0xC8/*::]*/: 1250, /*::[*/0xC9/*::]*/: 1251,
6992 /*::[*/0xCA/*::]*/: 1254, /*::[*/0xCB/*::]*/: 1253,
6993
6994 /* shapefile DBF extension */
6995 /*::[*/0x00/*::]*/: 20127, /*::[*/0x08/*::]*/: 865,
6996 /*::[*/0x09/*::]*/: 437, /*::[*/0x0A/*::]*/: 850,
6997 /*::[*/0x0B/*::]*/: 437, /*::[*/0x0D/*::]*/: 437,
6998 /*::[*/0x0E/*::]*/: 850, /*::[*/0x0F/*::]*/: 437,
6999 /*::[*/0x10/*::]*/: 850, /*::[*/0x11/*::]*/: 437,
7000 /*::[*/0x12/*::]*/: 850, /*::[*/0x13/*::]*/: 932,
7001 /*::[*/0x14/*::]*/: 850, /*::[*/0x15/*::]*/: 437,
7002 /*::[*/0x16/*::]*/: 850, /*::[*/0x17/*::]*/: 865,
7003 /*::[*/0x18/*::]*/: 437, /*::[*/0x19/*::]*/: 437,
7004 /*::[*/0x1A/*::]*/: 850, /*::[*/0x1B/*::]*/: 437,
7005 /*::[*/0x1C/*::]*/: 863, /*::[*/0x1D/*::]*/: 850,
7006 /*::[*/0x1F/*::]*/: 852, /*::[*/0x22/*::]*/: 852,
7007 /*::[*/0x23/*::]*/: 852, /*::[*/0x24/*::]*/: 860,
7008 /*::[*/0x25/*::]*/: 850, /*::[*/0x26/*::]*/: 866,
7009 /*::[*/0x37/*::]*/: 850, /*::[*/0x40/*::]*/: 852,
7010 /*::[*/0x4D/*::]*/: 936, /*::[*/0x4E/*::]*/: 949,
7011 /*::[*/0x4F/*::]*/: 950, /*::[*/0x50/*::]*/: 874,
7012 /*::[*/0x57/*::]*/: 1252, /*::[*/0x58/*::]*/: 1252,
7013 /*::[*/0x59/*::]*/: 1252, /*::[*/0x6C/*::]*/: 863,
7014 /*::[*/0x86/*::]*/: 737, /*::[*/0x87/*::]*/: 852,
7015 /*::[*/0x88/*::]*/: 857, /*::[*/0xCC/*::]*/: 1257,
7016
7017 /*::[*/0xFF/*::]*/: 16969
7018};
7019var dbf_reverse_map = evert({
7020 /*::[*/0x01/*::]*/: 437, /*::[*/0x02/*::]*/: 850,
7021 /*::[*/0x03/*::]*/: 1252, /*::[*/0x04/*::]*/: 10000,
7022 /*::[*/0x64/*::]*/: 852, /*::[*/0x65/*::]*/: 866,
7023 /*::[*/0x66/*::]*/: 865, /*::[*/0x67/*::]*/: 861,
7024 /*::[*/0x68/*::]*/: 895, /*::[*/0x69/*::]*/: 620,
7025 /*::[*/0x6A/*::]*/: 737, /*::[*/0x6B/*::]*/: 857,
7026 /*::[*/0x78/*::]*/: 950, /*::[*/0x79/*::]*/: 949,
7027 /*::[*/0x7A/*::]*/: 936, /*::[*/0x7B/*::]*/: 932,
7028 /*::[*/0x7C/*::]*/: 874, /*::[*/0x7D/*::]*/: 1255,
7029 /*::[*/0x7E/*::]*/: 1256, /*::[*/0x96/*::]*/: 10007,
7030 /*::[*/0x97/*::]*/: 10029, /*::[*/0x98/*::]*/: 10006,
7031 /*::[*/0xC8/*::]*/: 1250, /*::[*/0xC9/*::]*/: 1251,
7032 /*::[*/0xCA/*::]*/: 1254, /*::[*/0xCB/*::]*/: 1253,
7033 /*::[*/0x00/*::]*/: 20127
7034});
7035var DBF_SUPPORTED_VERSIONS = [0x02, 0x03, 0x30, 0x31, 0x83, 0x8B, 0x8C, 0xF5];
7036/* TODO: find an actual specification */
7037function dbf_to_aoa(buf, opts)/*:AOA*/ {
7038 var out/*:AOA*/ = [];
7039 var d/*:Block*/ = (new_raw_buf(1)/*:any*/);
7040 switch(opts.type) {
7041 case 'base64': d = s2a(Base64.decode(buf)); break;
7042 case 'binary': d = s2a(buf); break;
7043 case 'buffer':
7044 case 'array': d = buf; break;
7045 }
7046 prep_blob(d, 0);
7047
7048 /* header */
7049 var ft = d.read_shift(1);
7050 var memo = !!(ft & 0x88);
7051 var vfp = false, l7 = false;
7052 switch(ft) {
7053 case 0x02: break; // dBASE II
7054 case 0x03: break; // dBASE III
7055 case 0x30: vfp = true; memo = true; break; // VFP
7056 case 0x31: vfp = true; memo = true; break; // VFP with autoincrement
7057 // 0x43 dBASE IV SQL table files
7058 // 0x63 dBASE IV SQL system files
7059 case 0x83: break; // dBASE III with memo
7060 case 0x8B: break; // dBASE IV with memo
7061 case 0x8C: l7 = true; break; // dBASE Level 7 with memo
7062 // case 0xCB dBASE IV SQL table files with memo
7063 case 0xF5: break; // FoxPro 2.x with memo
7064 // case 0xFB FoxBASE
7065 default: throw new Error("DBF Unsupported Version: " + ft.toString(16));
7066 }
7067
7068 var nrow = 0, fpos = 0x0209;
7069 if(ft == 0x02) nrow = d.read_shift(2);
7070 d.l += 3; // dBASE II stores DDMMYY date, others use YYMMDD
7071 if(ft != 0x02) nrow = d.read_shift(4);
7072 if(nrow > 1048576) nrow = 1e6;
7073
7074 if(ft != 0x02) fpos = d.read_shift(2); // header length
7075 var rlen = d.read_shift(2); // record length
7076
7077 var /*flags = 0,*/ current_cp = opts.codepage || 1252;
7078 if(ft != 0x02) { // 20 reserved bytes
7079 d.l+=16;
7080 /*flags = */d.read_shift(1);
7081 //if(memo && ((flags & 0x02) === 0)) throw new Error("DBF Flags " + flags.toString(16) + " ft " + ft.toString(16));
7082
7083 /* codepage present in FoxPro and dBASE Level 7 */
7084 if(d[d.l] !== 0) current_cp = dbf_codepage_map[d[d.l]];
7085 d.l+=1;
7086
7087 d.l+=2;
7088 }
7089 if(l7) d.l += 36; // Level 7: 32 byte "Language driver name", 4 byte reserved
7090
7091/*:: type DBFField = { name:string; len:number; type:string; } */
7092 var fields/*:Array<DBFField>*/ = [], field/*:DBFField*/ = ({}/*:any*/);
7093 var hend = Math.min(d.length, (ft == 0x02 ? 0x209 : (fpos - 10 - (vfp ? 264 : 0))));
7094 var ww = l7 ? 32 : 11;
7095 while(d.l < hend && d[d.l] != 0x0d) {
7096 field = ({}/*:any*/);
7097 field.name = cptable.utils.decode(current_cp, d.slice(d.l, d.l+ww)).replace(/[\u0000\r\n].*$/g,"");
7098 d.l += ww;
7099 field.type = String.fromCharCode(d.read_shift(1));
7100 if(ft != 0x02 && !l7) field.offset = d.read_shift(4);
7101 field.len = d.read_shift(1);
7102 if(ft == 0x02) field.offset = d.read_shift(2);
7103 field.dec = d.read_shift(1);
7104 if(field.name.length) fields.push(field);
7105 if(ft != 0x02) d.l += l7 ? 13 : 14;
7106 switch(field.type) {
7107 case 'B': // Double (VFP) / Binary (dBASE L7)
7108 if((!vfp || field.len != 8) && opts.WTF) console.log('Skipping ' + field.name + ':' + field.type);
7109 break;
7110 case 'G': // General (FoxPro and dBASE L7)
7111 case 'P': // Picture (FoxPro and dBASE L7)
7112 if(opts.WTF) console.log('Skipping ' + field.name + ':' + field.type);
7113 break;
7114 case '+': // Autoincrement (dBASE L7 only)
7115 case '0': // _NullFlags (VFP only)
7116 case '@': // Timestamp (dBASE L7 only)
7117 case 'C': // Character (dBASE II)
7118 case 'D': // Date (dBASE III)
7119 case 'F': // Float (dBASE IV)
7120 case 'I': // Long (VFP and dBASE L7)
7121 case 'L': // Logical (dBASE II)
7122 case 'M': // Memo (dBASE III)
7123 case 'N': // Number (dBASE II)
7124 case 'O': // Double (dBASE L7 only)
7125 case 'T': // Datetime (VFP only)
7126 case 'Y': // Currency (VFP only)
7127 break;
7128 default: throw new Error('Unknown Field Type: ' + field.type);
7129 }
7130 }
7131
7132 if(d[d.l] !== 0x0D) d.l = fpos-1;
7133 if(d.read_shift(1) !== 0x0D) throw new Error("DBF Terminator not found " + d.l + " " + d[d.l]);
7134 d.l = fpos;
7135
7136 /* data */
7137 var R = 0, C = 0;
7138 out[0] = [];
7139 for(C = 0; C != fields.length; ++C) out[0][C] = fields[C].name;
7140 while(nrow-- > 0) {
7141 if(d[d.l] === 0x2A) {
7142 // TODO: record marked as deleted -- create a hidden row?
7143 d.l+=rlen;
7144 continue;
7145 }
7146 ++d.l;
7147 out[++R] = []; C = 0;
7148 for(C = 0; C != fields.length; ++C) {
7149 var dd = d.slice(d.l, d.l+fields[C].len); d.l+=fields[C].len;
7150 prep_blob(dd, 0);
7151 var s = cptable.utils.decode(current_cp, dd);
7152 switch(fields[C].type) {
7153 case 'C':
7154 // NOTE: it is conventional to write ' / / ' for empty dates
7155 if(s.trim().length) out[R][C] = s.replace(/\s+$/,"");
7156 break;
7157 case 'D':
7158 if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8));
7159 else out[R][C] = s;
7160 break;
7161 case 'F': out[R][C] = parseFloat(s.trim()); break;
7162 case '+': case 'I': out[R][C] = l7 ? dd.read_shift(-4, 'i') ^ 0x80000000 : dd.read_shift(4, 'i'); break;
7163 case 'L': switch(s.trim().toUpperCase()) {
7164 case 'Y': case 'T': out[R][C] = true; break;
7165 case 'N': case 'F': out[R][C] = false; break;
7166 case '': case '?': break;
7167 default: throw new Error("DBF Unrecognized L:|" + s + "|");
7168 } break;
7169 case 'M': /* TODO: handle memo files */
7170 if(!memo) throw new Error("DBF Unexpected MEMO for type " + ft.toString(16));
7171 out[R][C] = "##MEMO##" + (l7 ? parseInt(s.trim(), 10): dd.read_shift(4));
7172 break;
7173 case 'N':
7174 s = s.replace(/\u0000/g,"").trim();
7175 // NOTE: dBASE II interprets " . " as 0
7176 if(s && s != ".") out[R][C] = +s || 0; break;
7177 case '@':
7178 // NOTE: dBASE specs appear to be incorrect
7179 out[R][C] = new Date(dd.read_shift(-8, 'f') - 0x388317533400);
7180 break;
7181 case 'T': out[R][C] = new Date((dd.read_shift(4) - 0x253D8C) * 0x5265C00 + dd.read_shift(4)); break;
7182 case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4; break;
7183 case 'O': out[R][C] = -dd.read_shift(-8, 'f'); break;
7184 case 'B': if(vfp && fields[C].len == 8) { out[R][C] = dd.read_shift(8,'f'); break; }
7185 /* falls through */
7186 case 'G': case 'P': dd.l += fields[C].len; break;
7187 case '0':
7188 if(fields[C].name === '_NullFlags') break;
7189 /* falls through */
7190 default: throw new Error("DBF Unsupported data type " + fields[C].type);
7191 }
7192 }
7193 }
7194 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));
7195 if(opts && opts.sheetRows) out = out.slice(0, opts.sheetRows);
7196 return out;
7197}
7198
7199function dbf_to_sheet(buf, opts)/*:Worksheet*/ {
7200 var o = opts || {};
7201 if(!o.dateNF) o.dateNF = "yyyymmdd";
7202 return aoa_to_sheet(dbf_to_aoa(buf, o), o);
7203}
7204
7205function dbf_to_workbook(buf, opts)/*:Workbook*/ {
7206 try { return sheet_to_workbook(dbf_to_sheet(buf, opts), opts); }
7207 catch(e) { if(opts && opts.WTF) throw e; }
7208 return ({SheetNames:[],Sheets:{}});
7209}
7210
7211var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 };
7212function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
7213 var o = opts || {};
7214 if(+o.codepage >= 0) set_cp(+o.codepage);
7215 if(o.type == "string") throw new Error("Cannot write DBF to JS string");
7216 var ba = buf_array();
7217 var aoa/*:AOA*/ = sheet_to_json(ws, {header:1, raw:true, cellDates:true});
7218 var headers = aoa[0], data = aoa.slice(1);
7219 var i = 0, j = 0, hcnt = 0, rlen = 1;
7220 for(i = 0; i < headers.length; ++i) {
7221 if(i == null) continue;
7222 ++hcnt;
7223 if(typeof headers[i] === 'number') headers[i] = headers[i].toString(10);
7224 if(typeof headers[i] !== 'string') throw new Error("DBF Invalid column name " + headers[i] + " |" + (typeof headers[i]) + "|");
7225 if(headers.indexOf(headers[i]) !== i) for(j=0; j<1024;++j)
7226 if(headers.indexOf(headers[i] + "_" + j) == -1) { headers[i] += "_" + j; break; }
7227 }
7228 var range = safe_decode_range(ws['!ref']);
7229 var coltypes/*:Array<string>*/ = [];
7230 for(i = 0; i <= range.e.c - range.s.c; ++i) {
7231 var col/*:Array<any>*/ = [];
7232 for(j=0; j < data.length; ++j) {
7233 if(data[j][i] != null) col.push(data[j][i]);
7234 }
7235 if(col.length == 0 || headers[i] == null) { coltypes[i] = '?'; continue; }
7236 var guess = '', _guess = '';
7237 for(j = 0; j < col.length; ++j) {
7238 switch(typeof col[j]) {
7239 /* TODO: check if L2 compat is desired */
7240 case 'number': _guess = 'B'; break;
7241 case 'string': _guess = 'C'; break;
7242 case 'boolean': _guess = 'L'; break;
7243 case 'object': _guess = col[j] instanceof Date ? 'D' : 'C'; break;
7244 default: _guess = 'C';
7245 }
7246 guess = guess && guess != _guess ? 'C' : _guess;
7247 if(guess == 'C') break;
7248 }
7249 rlen += _RLEN[guess] || 0;
7250 coltypes[i] = guess;
7251 }
7252
7253 var h = ba.next(32);
7254 h.write_shift(4, 0x13021130);
7255 h.write_shift(4, data.length);
7256 h.write_shift(2, 296 + 32 * hcnt);
7257 h.write_shift(2, rlen);
7258 for(i=0; i < 4; ++i) h.write_shift(4, 0);
7259 h.write_shift(4, 0x00000000 | ((+dbf_reverse_map[/*::String(*/current_ansi/*::)*/] || 0x03)<<8));
7260
7261 for(i = 0, j = 0; i < headers.length; ++i) {
7262 if(headers[i] == null) continue;
7263 var hf = ba.next(32);
7264 var _f = (headers[i].slice(-10) + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00").slice(0, 11);
7265 hf.write_shift(1, _f, "sbcs");
7266 hf.write_shift(1, coltypes[i] == '?' ? 'C' : coltypes[i], "sbcs");
7267 hf.write_shift(4, j);
7268 hf.write_shift(1, _RLEN[coltypes[i]] || 0);
7269 hf.write_shift(1, 0);
7270 hf.write_shift(1, 0x02);
7271 hf.write_shift(4, 0);
7272 hf.write_shift(1, 0);
7273 hf.write_shift(4, 0);
7274 hf.write_shift(4, 0);
7275 j += _RLEN[coltypes[i]] || 0;
7276 }
7277
7278 var hb = ba.next(264);
7279 hb.write_shift(4, 0x0000000D);
7280 for(i=0; i < 65;++i) hb.write_shift(4, 0x00000000);
7281 for(i=0; i < data.length; ++i) {
7282 var rout = ba.next(rlen);
7283 rout.write_shift(1, 0);
7284 for(j=0; j<headers.length; ++j) {
7285 if(headers[j] == null) continue;
7286 switch(coltypes[j]) {
7287 case 'L': rout.write_shift(1, data[i][j] == null ? 0x3F : data[i][j] ? 0x54 : 0x46); break;
7288 case 'B': rout.write_shift(8, data[i][j]||0, 'f'); break;
7289 case 'D':
7290 if(!data[i][j]) rout.write_shift(8, "00000000", "sbcs");
7291 else {
7292 rout.write_shift(4, ("0000"+data[i][j].getFullYear()).slice(-4), "sbcs");
7293 rout.write_shift(2, ("00"+(data[i][j].getMonth()+1)).slice(-2), "sbcs");
7294 rout.write_shift(2, ("00"+data[i][j].getDate()).slice(-2), "sbcs");
7295 } break;
7296 case 'C':
7297 var _s = String(data[i][j]||"");
7298 rout.write_shift(1, _s, "sbcs");
7299 for(hcnt=0; hcnt < 250-_s.length; ++hcnt) rout.write_shift(1, 0x20); break;
7300 }
7301 }
7302 // data
7303 }
7304 ba.next(1).write_shift(1, 0x1A);
7305 return ba.end();
7306}
7307 return {
7308 versions: DBF_SUPPORTED_VERSIONS,
7309 to_workbook: dbf_to_workbook,
7310 to_sheet: dbf_to_sheet,
7311 from_sheet: sheet_to_dbf
7312 };
7313})();
7314
7315var SYLK = (function() {
7316 /* TODO: stress test sequences */
7317 var sylk_escapes = ({
7318 AA:'À', BA:'Á', CA:'Â', DA:195, HA:'Ä', JA:197,
7319 AE:'È', BE:'É', CE:'Ê', HE:'Ë',
7320 AI:'Ì', BI:'Í', CI:'Î', HI:'Ï',
7321 AO:'Ò', BO:'Ó', CO:'Ô', DO:213, HO:'Ö',
7322 AU:'Ù', BU:'Ú', CU:'Û', HU:'Ü',
7323 Aa:'à', Ba:'á', Ca:'â', Da:227, Ha:'ä', Ja:229,
7324 Ae:'è', Be:'é', Ce:'ê', He:'ë',
7325 Ai:'ì', Bi:'í', Ci:'î', Hi:'ï',
7326 Ao:'ò', Bo:'ó', Co:'ô', Do:245, Ho:'ö',
7327 Au:'ù', Bu:'ú', Cu:'û', Hu:'ü',
7328 KC:'Ç', Kc:'ç', q:'æ', z:'œ', a:'Æ', j:'Œ',
7329 DN:209, Dn:241, Hy:255,
7330 S:169, c:170, R:174, "B ":180,
7331 /*::[*/0/*::]*/:176, /*::[*/1/*::]*/:177, /*::[*/2/*::]*/:178,
7332 /*::[*/3/*::]*/:179, /*::[*/5/*::]*/:181, /*::[*/6/*::]*/:182,
7333 /*::[*/7/*::]*/:183, Q:185, k:186, b:208, i:216, l:222, s:240, y:248,
7334 "!":161, '"':162, "#":163, "(":164, "%":165, "'":167, "H ":168,
7335 "+":171, ";":187, "<":188, "=":189, ">":190, "?":191, "{":223
7336 }/*:any*/);
7337 var sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1") + "|\\|)", "gm");
7338 var sylk_char_fn = function(_, $1){ var o = sylk_escapes[$1]; return typeof o == "number" ? _getansi(o) : o; };
7339 var decode_sylk_char = function($$, $1, $2) { var newcc = (($1.charCodeAt(0) - 0x20)<<4) | ($2.charCodeAt(0) - 0x30); return newcc == 59 ? $$ : _getansi(newcc); };
7340 sylk_escapes["|"] = 254;
7341 /* TODO: find an actual specification */
7342 function sylk_to_aoa(d/*:RawData*/, opts)/*:[AOA, Worksheet]*/ {
7343 switch(opts.type) {
7344 case 'base64': return sylk_to_aoa_str(Base64.decode(d), opts);
7345 case 'binary': return sylk_to_aoa_str(d, opts);
7346 case 'buffer': return sylk_to_aoa_str(has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d), opts);
7347 case 'array': return sylk_to_aoa_str(cc2str(d), opts);
7348 }
7349 throw new Error("Unrecognized type " + opts.type);
7350 }
7351 function sylk_to_aoa_str(str/*:string*/, opts)/*:[AOA, Worksheet]*/ {
7352 var records = str.split(/[\n\r]+/), R = -1, C = -1, ri = 0, rj = 0, arr/*:AOA*/ = [];
7353 var formats/*:Array<string>*/ = [];
7354 var next_cell_format/*:string|null*/ = null;
7355 var sht = {}, rowinfo/*:Array<RowInfo>*/ = [], colinfo/*:Array<ColInfo>*/ = [], cw/*:Array<string>*/ = [];
7356 var Mval = 0, j;
7357 if(+opts.codepage >= 0) set_cp(+opts.codepage);
7358 for (; ri !== records.length; ++ri) {
7359 Mval = 0;
7360 var rstr=records[ri].trim().replace(/\x1B([\x20-\x2F])([\x30-\x3F])/g, decode_sylk_char).replace(sylk_char_regex, sylk_char_fn);
7361 var record=rstr.replace(/;;/g, "\u0000").split(";").map(function(x) { return x.replace(/\u0000/g, ";"); });
7362 var RT=record[0], val;
7363 if(rstr.length > 0) switch(RT) {
7364 case 'ID': break; /* header */
7365 case 'E': break; /* EOF */
7366 case 'B': break; /* dimensions */
7367 case 'O': break; /* options? */
7368 case 'W': break; /* window? */
7369 case 'P':
7370 if(record[1].charAt(0) == 'P')
7371 formats.push(rstr.slice(3).replace(/;;/g, ";"));
7372 break;
7373 case 'C':
7374 var C_seen_K = false, C_seen_X = false, C_seen_S = false, C_seen_E = false, _R = -1, _C = -1;
7375 for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
7376 case 'A': break; // TODO: comment
7377 case 'X': C = parseInt(record[rj].slice(1))-1; C_seen_X = true; break;
7378 case 'Y':
7379 R = parseInt(record[rj].slice(1))-1; if(!C_seen_X) C = 0;
7380 for(j = arr.length; j <= R; ++j) arr[j] = [];
7381 break;
7382 case 'K':
7383 val = record[rj].slice(1);
7384 if(val.charAt(0) === '"') val = val.slice(1,val.length - 1);
7385 else if(val === 'TRUE') val = true;
7386 else if(val === 'FALSE') val = false;
7387 else if(!isNaN(fuzzynum(val))) {
7388 val = fuzzynum(val);
7389 if(next_cell_format !== null && SSF.is_date(next_cell_format)) val = numdate(val);
7390 } else if(!isNaN(fuzzydate(val).getDate())) {
7391 val = parseDate(val);
7392 }
7393 if(typeof cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = cptable.utils.decode(opts.codepage, val);
7394 C_seen_K = true;
7395 break;
7396 case 'E':
7397 C_seen_E = true;
7398 var formula = rc_to_a1(record[rj].slice(1), {r:R,c:C});
7399 arr[R][C] = [arr[R][C], formula];
7400 break;
7401 case 'S':
7402 C_seen_S = true;
7403 arr[R][C] = [arr[R][C], "S5S"];
7404 break;
7405 case 'G': break; // unknown
7406 case 'R': _R = parseInt(record[rj].slice(1))-1; break;
7407 case 'C': _C = parseInt(record[rj].slice(1))-1; break;
7408 default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
7409 }
7410 if(C_seen_K) {
7411 if(arr[R][C] && arr[R][C].length == 2) arr[R][C][0] = val;
7412 else arr[R][C] = val;
7413 next_cell_format = null;
7414 }
7415 if(C_seen_S) {
7416 if(C_seen_E) throw new Error("SYLK shared formula cannot have own formula");
7417 var shrbase = _R > -1 && arr[_R][_C];
7418 if(!shrbase || !shrbase[1]) throw new Error("SYLK shared formula cannot find base");
7419 arr[R][C][1] = shift_formula_str(shrbase[1], {r: R - _R, c: C - _C});
7420 }
7421 break;
7422 case 'F':
7423 var F_seen = 0;
7424 for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
7425 case 'X': C = parseInt(record[rj].slice(1))-1; ++F_seen; break;
7426 case 'Y':
7427 R = parseInt(record[rj].slice(1))-1; /*C = 0;*/
7428 for(j = arr.length; j <= R; ++j) arr[j] = [];
7429 break;
7430 case 'M': Mval = parseInt(record[rj].slice(1)) / 20; break;
7431 case 'F': break; /* ??? */
7432 case 'G': break; /* hide grid */
7433 case 'P':
7434 next_cell_format = formats[parseInt(record[rj].slice(1))];
7435 break;
7436 case 'S': break; /* cell style */
7437 case 'D': break; /* column */
7438 case 'N': break; /* font */
7439 case 'W':
7440 cw = record[rj].slice(1).split(" ");
7441 for(j = parseInt(cw[0], 10); j <= parseInt(cw[1], 10); ++j) {
7442 Mval = parseInt(cw[2], 10);
7443 colinfo[j-1] = Mval === 0 ? {hidden:true}: {wch:Mval}; process_col(colinfo[j-1]);
7444 } break;
7445 case 'C': /* default column format */
7446 C = parseInt(record[rj].slice(1))-1;
7447 if(!colinfo[C]) colinfo[C] = {};
7448 break;
7449 case 'R': /* row properties */
7450 R = parseInt(record[rj].slice(1))-1;
7451 if(!rowinfo[R]) rowinfo[R] = {};
7452 if(Mval > 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); }
7453 else if(Mval === 0) rowinfo[R].hidden = true;
7454 break;
7455 default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
7456 }
7457 if(F_seen < 1) next_cell_format = null; break;
7458 default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
7459 }
7460 }
7461 if(rowinfo.length > 0) sht['!rows'] = rowinfo;
7462 if(colinfo.length > 0) sht['!cols'] = colinfo;
7463 if(opts && opts.sheetRows) arr = arr.slice(0, opts.sheetRows);
7464 return [arr, sht];
7465 }
7466
7467 function sylk_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
7468 var aoasht = sylk_to_aoa(d, opts);
7469 var aoa = aoasht[0], ws = aoasht[1];
7470 var o = aoa_to_sheet(aoa, opts);
7471 keys(ws).forEach(function(k) { o[k] = ws[k]; });
7472 return o;
7473 }
7474
7475 function sylk_to_workbook(d/*:RawData*/, opts)/*:Workbook*/ { return sheet_to_workbook(sylk_to_sheet(d, opts), opts); }
7476
7477 function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*//*::, opts*/)/*:string*/ {
7478 var o = "C;Y" + (R+1) + ";X" + (C+1) + ";K";
7479 switch(cell.t) {
7480 case 'n':
7481 o += (cell.v||0);
7482 if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break;
7483 case 'b': o += cell.v ? "TRUE" : "FALSE"; break;
7484 case 'e': o += cell.w || cell.v; break;
7485 case 'd': o += '"' + (cell.w || cell.v) + '"'; break;
7486 case 's': o += '"' + cell.v.replace(/"/g,"") + '"'; break;
7487 }
7488 return o;
7489 }
7490
7491 function write_ws_cols_sylk(out, cols) {
7492 cols.forEach(function(col, i) {
7493 var rec = "F;W" + (i+1) + " " + (i+1) + " ";
7494 if(col.hidden) rec += "0";
7495 else {
7496 if(typeof col.width == 'number' && !col.wpx) col.wpx = width2px(col.width);
7497 if(typeof col.wpx == 'number' && !col.wch) col.wch = px2char(col.wpx);
7498 if(typeof col.wch == 'number') rec += Math.round(col.wch);
7499 }
7500 if(rec.charAt(rec.length - 1) != " ") out.push(rec);
7501 });
7502 }
7503
7504 function write_ws_rows_sylk(out/*:Array<string>*/, rows/*:Array<RowInfo>*/) {
7505 rows.forEach(function(row, i) {
7506 var rec = "F;";
7507 if(row.hidden) rec += "M0;";
7508 else if(row.hpt) rec += "M" + 20 * row.hpt + ";";
7509 else if(row.hpx) rec += "M" + 20 * px2pt(row.hpx) + ";";
7510 if(rec.length > 2) out.push(rec + "R" + (i+1));
7511 });
7512 }
7513
7514 function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
7515 var preamble/*:Array<string>*/ = ["ID;PWXL;N;E"], o/*:Array<string>*/ = [];
7516 var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
7517 var dense = Array.isArray(ws);
7518 var RS = "\r\n";
7519
7520 preamble.push("P;PGeneral");
7521 preamble.push("F;P0;DG0G8;M255");
7522 if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
7523 if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
7524
7525 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(" "));
7526 for(var R = r.s.r; R <= r.e.r; ++R) {
7527 for(var C = r.s.c; C <= r.e.c; ++C) {
7528 var coord = encode_cell({r:R,c:C});
7529 cell = dense ? (ws[R]||[])[C]: ws[coord];
7530 if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
7531 o.push(write_ws_cell_sylk(cell, ws, R, C, opts));
7532 }
7533 }
7534 return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
7535 }
7536
7537 return {
7538 to_workbook: sylk_to_workbook,
7539 to_sheet: sylk_to_sheet,
7540 from_sheet: sheet_to_sylk
7541 };
7542})();
7543
7544var DIF = (function() {
7545 function dif_to_aoa(d/*:RawData*/, opts)/*:AOA*/ {
7546 switch(opts.type) {
7547 case 'base64': return dif_to_aoa_str(Base64.decode(d), opts);
7548 case 'binary': return dif_to_aoa_str(d, opts);
7549 case 'buffer': return dif_to_aoa_str(has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d), opts);
7550 case 'array': return dif_to_aoa_str(cc2str(d), opts);
7551 }
7552 throw new Error("Unrecognized type " + opts.type);
7553 }
7554 function dif_to_aoa_str(str/*:string*/, opts)/*:AOA*/ {
7555 var records = str.split('\n'), R = -1, C = -1, ri = 0, arr/*:AOA*/ = [];
7556 for (; ri !== records.length; ++ri) {
7557 if (records[ri].trim() === 'BOT') { arr[++R] = []; C = 0; continue; }
7558 if (R < 0) continue;
7559 var metadata = records[ri].trim().split(",");
7560 var type = metadata[0], value = metadata[1];
7561 ++ri;
7562 var data = records[ri] || "";
7563 while(((data.match(/["]/g)||[]).length & 1) && ri < records.length - 1) data += "\n" + records[++ri];
7564 data = data.trim();
7565 switch (+type) {
7566 case -1:
7567 if (data === 'BOT') { arr[++R] = []; C = 0; continue; }
7568 else if (data !== 'EOD') throw new Error("Unrecognized DIF special command " + data);
7569 break;
7570 case 0:
7571 if(data === 'TRUE') arr[R][C] = true;
7572 else if(data === 'FALSE') arr[R][C] = false;
7573 else if(!isNaN(fuzzynum(value))) arr[R][C] = fuzzynum(value);
7574 else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value);
7575 else arr[R][C] = value;
7576 ++C; break;
7577 case 1:
7578 data = data.slice(1,data.length-1);
7579 data = data.replace(/""/g, '"');
7580 if(DIF_XL && data && data.match(/^=".*"$/)) data = data.slice(2, -1);
7581 arr[R][C++] = data !== '' ? data : null;
7582 break;
7583 }
7584 if (data === 'EOD') break;
7585 }
7586 if(opts && opts.sheetRows) arr = arr.slice(0, opts.sheetRows);
7587 return arr;
7588 }
7589
7590 function dif_to_sheet(str/*:string*/, opts)/*:Worksheet*/ { return aoa_to_sheet(dif_to_aoa(str, opts), opts); }
7591 function dif_to_workbook(str/*:string*/, opts)/*:Workbook*/ { return sheet_to_workbook(dif_to_sheet(str, opts), opts); }
7592
7593 var sheet_to_dif = (function() {
7594 var push_field = function pf(o/*:Array<string>*/, topic/*:string*/, v/*:number*/, n/*:number*/, s/*:string*/) {
7595 o.push(topic);
7596 o.push(v + "," + n);
7597 o.push('"' + s.replace(/"/g,'""') + '"');
7598 };
7599 var push_value = function po(o/*:Array<string>*/, type/*:number*/, v/*:any*/, s/*:string*/) {
7600 o.push(type + "," + v);
7601 o.push(type == 1 ? '"' + s.replace(/"/g,'""') + '"' : s);
7602 };
7603 return function sheet_to_dif(ws/*:Worksheet*//*::, opts:?any*/)/*:string*/ {
7604 var o/*:Array<string>*/ = [];
7605 var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
7606 var dense = Array.isArray(ws);
7607 push_field(o, "TABLE", 0, 1, "sheetjs");
7608 push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,"");
7609 push_field(o, "TUPLES", 0, r.e.c - r.s.c + 1,"");
7610 push_field(o, "DATA", 0, 0,"");
7611 for(var R = r.s.r; R <= r.e.r; ++R) {
7612 push_value(o, -1, 0, "BOT");
7613 for(var C = r.s.c; C <= r.e.c; ++C) {
7614 var coord = encode_cell({r:R,c:C});
7615 cell = dense ? (ws[R]||[])[C] : ws[coord];
7616 if(!cell) { push_value(o, 1, 0, ""); continue;}
7617 switch(cell.t) {
7618 case 'n':
7619 var val = DIF_XL ? cell.w : cell.v;
7620 if(!val && cell.v != null) val = cell.v;
7621 if(val == null) {
7622 if(DIF_XL && cell.f && !cell.F) push_value(o, 1, 0, "=" + cell.f);
7623 else push_value(o, 1, 0, "");
7624 }
7625 else push_value(o, 0, val, "V");
7626 break;
7627 case 'b':
7628 push_value(o, 0, cell.v ? 1 : 0, cell.v ? "TRUE" : "FALSE");
7629 break;
7630 case 's':
7631 push_value(o, 1, 0, (!DIF_XL || isNaN(cell.v)) ? cell.v : '="' + cell.v + '"');
7632 break;
7633 case 'd':
7634 if(!cell.w) cell.w = SSF.format(cell.z || SSF._table[14], datenum(parseDate(cell.v)));
7635 if(DIF_XL) push_value(o, 0, cell.w, "V");
7636 else push_value(o, 1, 0, cell.w);
7637 break;
7638 default: push_value(o, 1, 0, "");
7639 }
7640 }
7641 }
7642 push_value(o, -1, 0, "EOD");
7643 var RS = "\r\n";
7644 var oo = o.join(RS);
7645 //while((oo.length & 0x7F) != 0) oo += "\0";
7646 return oo;
7647 };
7648 })();
7649 return {
7650 to_workbook: dif_to_workbook,
7651 to_sheet: dif_to_sheet,
7652 from_sheet: sheet_to_dif
7653 };
7654})();
7655
7656var ETH = (function() {
7657 function decode(s/*:string*/)/*:string*/ { return s.replace(/\\b/g,"\\").replace(/\\c/g,":").replace(/\\n/g,"\n"); }
7658 function encode(s/*:string*/)/*:string*/ { return s.replace(/\\/g, "\\b").replace(/:/g, "\\c").replace(/\n/g,"\\n"); }
7659
7660 function eth_to_aoa(str/*:string*/, opts)/*:AOA*/ {
7661 var records = str.split('\n'), R = -1, C = -1, ri = 0, arr/*:AOA*/ = [];
7662 for (; ri !== records.length; ++ri) {
7663 var record = records[ri].trim().split(":");
7664 if(record[0] !== 'cell') continue;
7665 var addr = decode_cell(record[1]);
7666 if(arr.length <= addr.r) for(R = arr.length; R <= addr.r; ++R) if(!arr[R]) arr[R] = [];
7667 R = addr.r; C = addr.c;
7668 switch(record[2]) {
7669 case 't': arr[R][C] = decode(record[3]); break;
7670 case 'v': arr[R][C] = +record[3]; break;
7671 case 'vtf': var _f = record[record.length - 1];
7672 /* falls through */
7673 case 'vtc':
7674 switch(record[3]) {
7675 case 'nl': arr[R][C] = +record[4] ? true : false; break;
7676 default: arr[R][C] = +record[4]; break;
7677 }
7678 if(record[2] == 'vtf') arr[R][C] = [arr[R][C], _f];
7679 }
7680 }
7681 if(opts && opts.sheetRows) arr = arr.slice(0, opts.sheetRows);
7682 return arr;
7683 }
7684
7685 function eth_to_sheet(d/*:string*/, opts)/*:Worksheet*/ { return aoa_to_sheet(eth_to_aoa(d, opts), opts); }
7686 function eth_to_workbook(d/*:string*/, opts)/*:Workbook*/ { return sheet_to_workbook(eth_to_sheet(d, opts), opts); }
7687
7688 var header = [
7689 "socialcalc:version:1.5",
7690 "MIME-Version: 1.0",
7691 "Content-Type: multipart/mixed; boundary=SocialCalcSpreadsheetControlSave"
7692 ].join("\n");
7693
7694 var sep = [
7695 "--SocialCalcSpreadsheetControlSave",
7696 "Content-type: text/plain; charset=UTF-8"
7697 ].join("\n") + "\n";
7698
7699 /* TODO: the other parts */
7700 var meta = [
7701 "# SocialCalc Spreadsheet Control Save",
7702 "part:sheet"
7703 ].join("\n");
7704
7705 var end = "--SocialCalcSpreadsheetControlSave--";
7706
7707 function sheet_to_eth_data(ws/*:Worksheet*/)/*:string*/ {
7708 if(!ws || !ws['!ref']) return "";
7709 var o/*:Array<string>*/ = [], oo/*:Array<string>*/ = [], cell, coord = "";
7710 var r = decode_range(ws['!ref']);
7711 var dense = Array.isArray(ws);
7712 for(var R = r.s.r; R <= r.e.r; ++R) {
7713 for(var C = r.s.c; C <= r.e.c; ++C) {
7714 coord = encode_cell({r:R,c:C});
7715 cell = dense ? (ws[R]||[])[C] : ws[coord];
7716 if(!cell || cell.v == null || cell.t === 'z') continue;
7717 oo = ["cell", coord, 't'];
7718 switch(cell.t) {
7719 case 's': case 'str': oo.push(encode(cell.v)); break;
7720 case 'n':
7721 if(!cell.f) { oo[2]='v'; oo[3]=cell.v; }
7722 else { oo[2]='vtf'; oo[3]='n'; oo[4]=cell.v; oo[5]=encode(cell.f); }
7723 break;
7724 case 'b':
7725 oo[2] = 'vt'+(cell.f?'f':'c'); oo[3]='nl'; oo[4]=cell.v?"1":"0";
7726 oo[5] = encode(cell.f||(cell.v?'TRUE':'FALSE'));
7727 break;
7728 case 'd':
7729 var t = datenum(parseDate(cell.v));
7730 oo[2] = 'vtc'; oo[3] = 'nd'; oo[4] = ""+t;
7731 oo[5] = cell.w || SSF.format(cell.z || SSF._table[14], t);
7732 break;
7733 case 'e': continue;
7734 }
7735 o.push(oo.join(":"));
7736 }
7737 }
7738 o.push("sheet:c:" + (r.e.c-r.s.c+1) + ":r:" + (r.e.r-r.s.r+1) + ":tvf:1");
7739 o.push("valueformat:1:text-wiki");
7740 //o.push("copiedfrom:" + ws['!ref']); // clipboard only
7741 return o.join("\n");
7742 }
7743
7744 function sheet_to_eth(ws/*:Worksheet*//*::, opts:?any*/)/*:string*/ {
7745 return [header, sep, meta, sep, sheet_to_eth_data(ws), end].join("\n");
7746 // return ["version:1.5", sheet_to_eth_data(ws)].join("\n"); // clipboard form
7747 }
7748
7749 return {
7750 to_workbook: eth_to_workbook,
7751 to_sheet: eth_to_sheet,
7752 from_sheet: sheet_to_eth
7753 };
7754})();
7755
7756var PRN = (function() {
7757 function set_text_arr(data/*:string*/, arr/*:AOA*/, R/*:number*/, C/*:number*/, o/*:any*/) {
7758 if(o.raw) arr[R][C] = data;
7759 else if(data === ""){/* empty */}
7760 else if(data === 'TRUE') arr[R][C] = true;
7761 else if(data === 'FALSE') arr[R][C] = false;
7762 else if(!isNaN(fuzzynum(data))) arr[R][C] = fuzzynum(data);
7763 else if(!isNaN(fuzzydate(data).getDate())) arr[R][C] = parseDate(data);
7764 else arr[R][C] = data;
7765 }
7766
7767 function prn_to_aoa_str(f/*:string*/, opts)/*:AOA*/ {
7768 var o = opts || {};
7769 var arr/*:AOA*/ = ([]/*:any*/);
7770 if(!f || f.length === 0) return arr;
7771 var lines = f.split(/[\r\n]/);
7772 var L = lines.length - 1;
7773 while(L >= 0 && lines[L].length === 0) --L;
7774 var start = 10, idx = 0;
7775 var R = 0;
7776 for(; R <= L; ++R) {
7777 idx = lines[R].indexOf(" ");
7778 if(idx == -1) idx = lines[R].length; else idx++;
7779 start = Math.max(start, idx);
7780 }
7781 for(R = 0; R <= L; ++R) {
7782 arr[R] = [];
7783 /* TODO: confirm that widths are always 10 */
7784 var C = 0;
7785 set_text_arr(lines[R].slice(0, start).trim(), arr, R, C, o);
7786 for(C = 1; C <= (lines[R].length - start)/10 + 1; ++C)
7787 set_text_arr(lines[R].slice(start+(C-1)*10,start+C*10).trim(),arr,R,C,o);
7788 }
7789 if(o.sheetRows) arr = arr.slice(0, o.sheetRows);
7790 return arr;
7791 }
7792
7793 // List of accepted CSV separators
7794 var guess_seps = {
7795 /*::[*/0x2C/*::]*/: ',',
7796 /*::[*/0x09/*::]*/: "\t",
7797 /*::[*/0x3B/*::]*/: ';',
7798 /*::[*/0x7C/*::]*/: '|'
7799 };
7800
7801 // CSV separator weights to be used in case of equal numbers
7802 var guess_sep_weights = {
7803 /*::[*/0x2C/*::]*/: 3,
7804 /*::[*/0x09/*::]*/: 2,
7805 /*::[*/0x3B/*::]*/: 1,
7806 /*::[*/0x7C/*::]*/: 0
7807 };
7808
7809 function guess_sep(str) {
7810 var cnt = {}, instr = false, end = 0, cc = 0;
7811 for(;end < str.length;++end) {
7812 if((cc=str.charCodeAt(end)) == 0x22) instr = !instr;
7813 else if(!instr && cc in guess_seps) cnt[cc] = (cnt[cc]||0)+1;
7814 }
7815
7816 cc = [];
7817 for(end in cnt) if ( Object.prototype.hasOwnProperty.call(cnt, end) ) {
7818 cc.push([ cnt[end], end ]);
7819 }
7820
7821 if ( !cc.length ) {
7822 cnt = guess_sep_weights;
7823 for(end in cnt) if ( Object.prototype.hasOwnProperty.call(cnt, end) ) {
7824 cc.push([ cnt[end], end ]);
7825 }
7826 }
7827
7828 cc.sort(function(a, b) { return a[0] - b[0] || guess_sep_weights[a[1]] - guess_sep_weights[b[1]]; });
7829
7830 return guess_seps[cc.pop()[1]] || 0x2C;
7831 }
7832
7833 function dsv_to_sheet_str(str/*:string*/, opts)/*:Worksheet*/ {
7834 var o = opts || {};
7835 var sep = "";
7836 if(DENSE != null && o.dense == null) o.dense = DENSE;
7837 var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/);
7838 var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:0}}/*:any*/);
7839
7840 if(str.slice(0,4) == "sep=") {
7841 // If the line ends in \r\n
7842 if(str.charCodeAt(5) == 13 && str.charCodeAt(6) == 10 ) {
7843 sep = str.charAt(4); str = str.slice(7);
7844 }
7845 // If line ends in \r OR \n
7846 else if(str.charCodeAt(5) == 13 || str.charCodeAt(5) == 10 ) {
7847 sep = str.charAt(4); str = str.slice(6);
7848 }
7849 else sep = guess_sep(str.slice(0,1024));
7850 }
7851 else if(o && o.FS) sep = o.FS;
7852 else sep = guess_sep(str.slice(0,1024));
7853 var R = 0, C = 0, v = 0;
7854 var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0);
7855 str = str.replace(/\r\n/mg, "\n");
7856 var _re/*:?RegExp*/ = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
7857 function finish_cell() {
7858 var s = str.slice(start, end);
7859 var cell = ({}/*:any*/);
7860 if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
7861 if(s.length === 0) cell.t = 'z';
7862 else if(o.raw) { cell.t = 's'; cell.v = s; }
7863 else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; }
7864 else if(s.charCodeAt(0) == 0x3D) {
7865 if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); }
7866 else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.slice(1); }
7867 else { cell.t = 's'; cell.v = s; } }
7868 else if(s == "TRUE") { cell.t = 'b'; cell.v = true; }
7869 else if(s == "FALSE") { cell.t = 'b'; cell.v = false; }
7870 else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; if(o.cellText !== false) cell.w = s; cell.v = v; }
7871 else if(!isNaN(fuzzydate(s).getDate()) || _re && s.match(_re)) {
7872 cell.z = o.dateNF || SSF._table[14];
7873 var k = 0;
7874 if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; }
7875 if(o.cellDates) { cell.t = 'd'; cell.v = parseDate(s, k); }
7876 else { cell.t = 'n'; cell.v = datenum(parseDate(s, k)); }
7877 if(o.cellText !== false) cell.w = SSF.format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v);
7878 if(!o.cellNF) delete cell.z;
7879 } else {
7880 cell.t = 's';
7881 cell.v = s;
7882 }
7883 if(cell.t == 'z'){}
7884 else if(o.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = cell; }
7885 else ws[encode_cell({c:C,r:R})] = cell;
7886 start = end+1; startcc = str.charCodeAt(start);
7887 if(range.e.c < C) range.e.c = C;
7888 if(range.e.r < R) range.e.r = R;
7889 if(cc == sepcc) ++C; else { C = 0; ++R; if(o.sheetRows && o.sheetRows <= R) return true; }
7890 }
7891 outer: for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) {
7892 case 0x22: if(startcc === 0x22) instr = !instr; break;
7893 case sepcc: case 0x0a: case 0x0d: if(!instr && finish_cell()) break outer; break;
7894 default: break;
7895 }
7896 if(end - start > 0) finish_cell();
7897
7898 ws['!ref'] = encode_range(range);
7899 return ws;
7900 }
7901
7902 function prn_to_sheet_str(str/*:string*/, opts)/*:Worksheet*/ {
7903 if(!(opts && opts.PRN)) return dsv_to_sheet_str(str, opts);
7904 if(opts.FS) return dsv_to_sheet_str(str, opts);
7905 if(str.slice(0,4) == "sep=") return dsv_to_sheet_str(str, opts);
7906 if(str.indexOf("\t") >= 0 || str.indexOf(",") >= 0 || str.indexOf(";") >= 0) return dsv_to_sheet_str(str, opts);
7907 return aoa_to_sheet(prn_to_aoa_str(str, opts), opts);
7908 }
7909
7910 function prn_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
7911 var str = "", bytes = opts.type == 'string' ? [0,0,0,0] : firstbyte(d, opts);
7912 switch(opts.type) {
7913 case 'base64': str = Base64.decode(d); break;
7914 case 'binary': str = d; break;
7915 case 'buffer':
7916 if(opts.codepage == 65001) str = d.toString('utf8'); // TODO: test if buf
7917 else if(opts.codepage && typeof cptable !== 'undefined') str = cptable.utils.decode(opts.codepage, d);
7918 else str = has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d);
7919 break;
7920 case 'array': str = cc2str(d); break;
7921 case 'string': str = d; break;
7922 default: throw new Error("Unrecognized type " + opts.type);
7923 }
7924 if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str.slice(3));
7925 else if(opts.type != 'string' && opts.codepage == 65001) str = utf8read(str);
7926 else if((opts.type == 'binary') && typeof cptable !== 'undefined' && opts.codepage) str = cptable.utils.decode(opts.codepage, cptable.utils.encode(28591,str));
7927 if(str.slice(0,19) == "socialcalc:version:") return ETH.to_sheet(opts.type == 'string' ? str : utf8read(str), opts);
7928 return prn_to_sheet_str(str, opts);
7929 }
7930
7931 function prn_to_workbook(d/*:RawData*/, opts)/*:Workbook*/ { return sheet_to_workbook(prn_to_sheet(d, opts), opts); }
7932
7933 function sheet_to_prn(ws/*:Worksheet*//*::, opts:?any*/)/*:string*/ {
7934 var o/*:Array<string>*/ = [];
7935 var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
7936 var dense = Array.isArray(ws);
7937 for(var R = r.s.r; R <= r.e.r; ++R) {
7938 var oo/*:Array<string>*/ = [];
7939 for(var C = r.s.c; C <= r.e.c; ++C) {
7940 var coord = encode_cell({r:R,c:C});
7941 cell = dense ? (ws[R]||[])[C] : ws[coord];
7942 if(!cell || cell.v == null) { oo.push(" "); continue; }
7943 var w = (cell.w || (format_cell(cell), cell.w) || "").slice(0,10);
7944 while(w.length < 10) w += " ";
7945 oo.push(w + (C === 0 ? " " : ""));
7946 }
7947 o.push(oo.join(""));
7948 }
7949 return o.join("\n");
7950 }
7951
7952 return {
7953 to_workbook: prn_to_workbook,
7954 to_sheet: prn_to_sheet,
7955 from_sheet: sheet_to_prn
7956 };
7957})();
7958
7959/* Excel defaults to SYLK but warns if data is not valid */
7960function read_wb_ID(d, opts) {
7961 var o = opts || {}, OLD_WTF = !!o.WTF; o.WTF = true;
7962 try {
7963 var out = SYLK.to_workbook(d, o);
7964 o.WTF = OLD_WTF;
7965 return out;
7966 } catch(e) {
7967 o.WTF = OLD_WTF;
7968 if(!e.message.match(/SYLK bad record ID/) && OLD_WTF) throw e;
7969 return PRN.to_workbook(d, opts);
7970 }
7971}
7972
7973var WK_ = /*#__PURE__*/ (function() {
7974 function lotushopper(data, cb/*:RecordHopperCB*/, opts/*:any*/) {
7975 if(!data) return;
7976 prep_blob(data, data.l || 0);
7977 var Enum = opts.Enum || WK1Enum;
7978 while(data.l < data.length) {
7979 var RT = data.read_shift(2);
7980 var R = Enum[RT] || Enum[0xFFFF];
7981 var length = data.read_shift(2);
7982 var tgt = data.l + length;
7983 var d = R.f && R.f(data, length, opts);
7984 data.l = tgt;
7985 if(cb(d, R, RT)) return;
7986 }
7987 }
7988
7989 function lotus_to_workbook(d/*:RawData*/, opts) {
7990 switch(opts.type) {
7991 case 'base64': return lotus_to_workbook_buf(s2a(Base64.decode(d)), opts);
7992 case 'binary': return lotus_to_workbook_buf(s2a(d), opts);
7993 case 'buffer':
7994 case 'array': return lotus_to_workbook_buf(d, opts);
7995 }
7996 throw "Unsupported type " + opts.type;
7997 }
7998
7999 function lotus_to_workbook_buf(d, opts)/*:Workbook*/ {
8000 if(!d) return d;
8001 var o = opts || {};
8002 if(DENSE != null && o.dense == null) o.dense = DENSE;
8003 var s/*:Worksheet*/ = ((o.dense ? [] : {})/*:any*/), n = "Sheet1", sidx = 0;
8004 var sheets = {}, snames = [n], realnames = [];
8005
8006 var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
8007 var sheetRows = o.sheetRows || 0;
8008
8009 if(d[2] == 0x02) {
8010 o.Enum = WK1Enum;
8011 lotushopper(d, function(val, R, RT) { switch(RT) {
8012 case 0x00: /* BOF */
8013 o.vers = val;
8014 if(val >= 0x1000) o.qpro = true;
8015 break;
8016 case 0x06: refguess = val; break; /* RANGE */
8017 case 0x0F: /* LABEL */
8018 case 0x33: /* STRING */
8019 if(!o.qpro) val[1].v = val[1].v.slice(1);
8020 /* falls through */
8021 case 0x0D: /* INTEGER */
8022 case 0x0E: /* NUMBER */
8023 case 0x10: /* FORMULA */
8024 /* TODO: actual translation of the format code */
8025 if(RT == 0x0E && (val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) {
8026 val[1].z = o.dateNF || SSF._table[14];
8027 if(o.cellDates) { val[1].t = 'd'; val[1].v = numdate(val[1].v); }
8028 }
8029 var tmpcell = o.dense ? (s[val[0].r]||[])[val[0].c] : s[encode_cell(val[0])];
8030 if(tmpcell) {
8031 tmpcell.t = val[1].t; tmpcell.v = val[1].v;
8032 if(val[1].z != null) tmpcell.z = val[1].z;
8033 if(val[1].f != null) tmpcell.f = val[1].f;
8034 break;
8035 }
8036 if(o.dense) {
8037 if(!s[val[0].r]) s[val[0].r] = [];
8038 s[val[0].r][val[0].c] = val[1];
8039 } else s[encode_cell(val[0])] = val[1];
8040 break;
8041 default:
8042 }}, o);
8043 } else if(d[2] == 0x1A || d[2] == 0x0E) {
8044 o.Enum = WK3Enum;
8045 if(d[2] == 0x0E) { o.qpro = true; d.l = 0; }
8046 lotushopper(d, function(val, R, RT) { switch(RT) {
8047 case 0x16: /* LABEL16 */
8048 val[1].v = val[1].v.slice(1);
8049 /* falls through */
8050 case 0x17: /* NUMBER17 */
8051 case 0x18: /* NUMBER18 */
8052 case 0x19: /* FORMULA19 */
8053 case 0x25: /* NUMBER25 */
8054 case 0x27: /* NUMBER27 */
8055 case 0x28: /* FORMULA28 */
8056 if(val[3] > sidx) {
8057 s["!ref"] = encode_range(refguess);
8058 sheets[n] = s;
8059 s = (o.dense ? [] : {});
8060 refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
8061 sidx = val[3]; n = "Sheet" + (sidx + 1);
8062 snames.push(n);
8063 }
8064 if(sheetRows > 0 && val[0].r >= sheetRows) break;
8065 if(o.dense) {
8066 if(!s[val[0].r]) s[val[0].r] = [];
8067 s[val[0].r][val[0].c] = val[1];
8068 } else s[encode_cell(val[0])] = val[1];
8069 if(refguess.e.c < val[0].c) refguess.e.c = val[0].c;
8070 if(refguess.e.r < val[0].r) refguess.e.r = val[0].r;
8071 break;
8072 case 0x1B: /* XFORMAT */
8073 if(val[0x36b0]) realnames[val[0x36b0][0]] = val[0x36b0][1];
8074 break;
8075 default: break;
8076 }}, o);
8077 } else throw new Error("Unrecognized LOTUS BOF " + d[2]);
8078
8079 s["!ref"] = encode_range(refguess);
8080 sheets[n] = s;
8081 if(!realnames.length) return { SheetNames: snames, Sheets: sheets };
8082 var osheets = {}, rnames = [];
8083 for(var i = 0; i < realnames.length; ++i) if(sheets[snames[i]]) {
8084 rnames.push(realnames[i]);
8085 osheets[realnames[i]] = sheets[snames[i]];
8086 }
8087 return { SheetNames: rnames, Sheets: osheets };
8088 }
8089
8090 function sheet_to_wk1(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
8091 var o = opts || {};
8092 if(+o.codepage >= 0) set_cp(+o.codepage);
8093 if(o.type == "string") throw new Error("Cannot write WK1 to JS string");
8094 var ba = buf_array();
8095 var range = safe_decode_range(ws["!ref"]);
8096 var dense = Array.isArray(ws);
8097 var cols = [];
8098
8099 write_biff_rec(ba, 0x00, write_BOF_WK1(0x0406));
8100 write_biff_rec(ba, 0x06, write_RANGE(range));
8101 for(var R = range.s.r; R <= range.e.r; ++R) {
8102 var rr = encode_row(R);
8103 for(var C = range.s.c; C <= range.e.c; ++C) {
8104 if(R === range.s.r) cols[C] = encode_col(C);
8105 var ref = cols[C] + rr;
8106 var cell = dense ? (ws[R]||[])[C] : ws[ref];
8107 if(!cell || cell.t == "z") continue;
8108 /* TODO: formula records */
8109 if(cell.t == "n") {
8110 if((cell.v|0)==cell.v && cell.v >= -32768 && cell.v <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, cell.v));
8111 else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, cell.v));
8112 } else {
8113 var str = format_cell(cell);
8114 write_biff_rec(ba, 0x0F, write_LABEL(R, C, str.slice(0, 239)));
8115 }
8116 }
8117 }
8118
8119 write_biff_rec(ba, 0x01);
8120 return ba.end();
8121 }
8122
8123 function book_to_wk3(wb/*:Workbook*/, opts/*:WriteOpts*/) {
8124 var o = opts || {};
8125 if(+o.codepage >= 0) set_cp(+o.codepage);
8126 if(o.type == "string") throw new Error("Cannot write WK3 to JS string");
8127 var ba = buf_array();
8128
8129 write_biff_rec(ba, 0x00, write_BOF_WK3(wb));
8130
8131 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++));
8132
8133 var wsidx = 0;
8134 for(i = 0; i < wb.SheetNames.length; ++i) {
8135 var ws = wb.Sheets[wb.SheetNames[i]];
8136 if(!ws || !ws["!ref"]) continue;
8137 var range = safe_decode_range(ws["!ref"]);
8138 var dense = Array.isArray(ws);
8139 var cols = [];
8140 for(var R = range.s.r; R <= range.e.r; ++R) {
8141 var rr = encode_row(R);
8142 for(var C = range.s.c; C <= range.e.c; ++C) {
8143 if(R === range.s.r) cols[C] = encode_col(C);
8144 var ref = cols[C] + rr;
8145 var cell = dense ? (ws[R]||[])[C] : ws[ref];
8146 if(!cell || cell.t == "z") continue;
8147 /* TODO: FORMULA19 NUMBER18 records */
8148 if(cell.t == "n") {
8149 write_biff_rec(ba, 0x17, write_NUMBER_17(R, C, wsidx, cell.v));
8150 } else {
8151 var str = format_cell(cell);
8152 /* TODO: max len? */
8153 write_biff_rec(ba, 0x16, write_LABEL_16(R, C, wsidx, str.slice(0, 239)));
8154 }
8155 }
8156 }
8157 ++wsidx;
8158 }
8159
8160 write_biff_rec(ba, 0x01);
8161 return ba.end();
8162 }
8163
8164
8165 function write_BOF_WK1(v/*:number*/) {
8166 var out = new_buf(2);
8167 out.write_shift(2, v);
8168 return out;
8169 }
8170
8171 function write_BOF_WK3(wb/*:Workbook*/) {
8172 var out = new_buf(26);
8173 out.write_shift(2, 0x1000);
8174 out.write_shift(2, 0x0004);
8175 out.write_shift(4, 0x0000);
8176 var rows = 0, cols = 0, wscnt = 0;
8177 for(var i = 0; i < wb.SheetNames.length; ++i) {
8178 var name = wb.SheetNames[i];
8179 var ws = wb.Sheets[name];
8180 if(!ws || !ws["!ref"]) continue;
8181 ++wscnt;
8182 var range = decode_range(ws["!ref"]);
8183 if(rows < range.e.r) rows = range.e.r;
8184 if(cols < range.e.c) cols = range.e.c;
8185 }
8186 out.write_shift(2, rows);
8187 out.write_shift(1, wscnt);
8188 out.write_shift(1, cols);
8189 out.write_shift(2, 0x00);
8190 out.write_shift(2, 0x00);
8191 out.write_shift(1, 0x01);
8192 out.write_shift(1, 0x02);
8193 out.write_shift(4, 0);
8194 out.write_shift(4, 0);
8195 return out;
8196 }
8197
8198 function parse_RANGE(blob) {
8199 var o = {s:{c:0,r:0},e:{c:0,r:0}};
8200 o.s.c = blob.read_shift(2);
8201 o.s.r = blob.read_shift(2);
8202 o.e.c = blob.read_shift(2);
8203 o.e.r = blob.read_shift(2);
8204 if(o.s.c == 0xFFFF) o.s.c = o.e.c = o.s.r = o.e.r = 0;
8205 return o;
8206 }
8207 function write_RANGE(range) {
8208 var out = new_buf(8);
8209 out.write_shift(2, range.s.c);
8210 out.write_shift(2, range.s.r);
8211 out.write_shift(2, range.e.c);
8212 out.write_shift(2, range.e.r);
8213 return out;
8214 }
8215
8216 function parse_cell(blob, length, opts) {
8217 var o = [{c:0,r:0}, {t:'n',v:0}, 0];
8218 if(opts.qpro && opts.vers != 0x5120) {
8219 o[0].c = blob.read_shift(1);
8220 blob.l++;
8221 o[0].r = blob.read_shift(2);
8222 blob.l+=2;
8223 } else {
8224 o[2] = blob.read_shift(1);
8225 o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2);
8226 }
8227 return o;
8228 }
8229
8230 function parse_LABEL(blob, length, opts) {
8231 var tgt = blob.l + length;
8232 var o = parse_cell(blob, length, opts);
8233 o[1].t = 's';
8234 if(opts.vers == 0x5120) {
8235 blob.l++;
8236 var len = blob.read_shift(1);
8237 o[1].v = blob.read_shift(len, 'utf8');
8238 return o;
8239 }
8240 if(opts.qpro) blob.l++;
8241 o[1].v = blob.read_shift(tgt - blob.l, 'cstr');
8242 return o;
8243 }
8244 function write_LABEL(R, C, s) {
8245 /* TODO: encoding */
8246 var o = new_buf(7 + s.length);
8247 o.write_shift(1, 0xFF);
8248 o.write_shift(2, C);
8249 o.write_shift(2, R);
8250 o.write_shift(1, 0x27); // ??
8251 for(var i = 0; i < o.length; ++i) {
8252 var cc = s.charCodeAt(i);
8253 o.write_shift(1, cc >= 0x80 ? 0x5F : cc);
8254 }
8255 o.write_shift(1, 0);
8256 return o;
8257 }
8258
8259 function parse_INTEGER(blob, length, opts) {
8260 var o = parse_cell(blob, length, opts);
8261 o[1].v = blob.read_shift(2, 'i');
8262 return o;
8263 }
8264 function write_INTEGER(R, C, v) {
8265 var o = new_buf(7);
8266 o.write_shift(1, 0xFF);
8267 o.write_shift(2, C);
8268 o.write_shift(2, R);
8269 o.write_shift(2, v, 'i');
8270 return o;
8271 }
8272
8273 function parse_NUMBER(blob, length, opts) {
8274 var o = parse_cell(blob, length, opts);
8275 o[1].v = blob.read_shift(8, 'f');
8276 return o;
8277 }
8278 function write_NUMBER(R, C, v) {
8279 var o = new_buf(13);
8280 o.write_shift(1, 0xFF);
8281 o.write_shift(2, C);
8282 o.write_shift(2, R);
8283 o.write_shift(8, v, 'f');
8284 return o;
8285 }
8286
8287 function parse_FORMULA(blob, length, opts) {
8288 var tgt = blob.l + length;
8289 var o = parse_cell(blob, length, opts);
8290 /* TODO: formula */
8291 o[1].v = blob.read_shift(8, 'f');
8292 if(opts.qpro) blob.l = tgt;
8293 else {
8294 var flen = blob.read_shift(2);
8295 wk1_fmla_to_csf(blob.slice(blob.l, blob.l + flen), o);
8296 blob.l += flen;
8297 }
8298 return o;
8299 }
8300
8301 function wk1_parse_rc(B, V, col) {
8302 var rel = V & 0x8000;
8303 V &= ~0x8000;
8304 V = (rel ? B : 0) + ((V >= 0x2000) ? V - 0x4000 : V);
8305 return (rel ? "" : "$") + (col ? encode_col(V) : encode_row(V));
8306 }
8307 var oprec = [
8308 8, 8, 8, 8, 8, 8, 8, 8, 6, 4, 4, 5, 5, 7, 3, 3,
8309 3, 3, 3, 3, 1, 1, 2, 6, 8, 8, 8, 8, 8, 8, 8, 8
8310 ];
8311 /* TODO: flesh out */
8312 var FuncTab = {
8313 0x33: ["FALSE", 0],
8314 0x34: ["TRUE", 0],
8315 0x46: ["LEN", 1],
8316 0x50: ["SUM", 69],
8317 0x51: ["AVERAGEA", 69],
8318 0x52: ["COUNTA", 69],
8319 0x53: ["MINA", 69],
8320 0x54: ["MAXA", 69],
8321 0x6F: ["T", 1]
8322 };
8323 var BinOpTab = [
8324 "", "", "", "", "", "", "", "",
8325 "", "+", "-", "*", "/", "^", "=", "<>",
8326 "<=", ">=", "<", ">", "", "", "", "",
8327 "&", "", "", "", "", "", "", ""
8328 ];
8329
8330 function wk1_fmla_to_csf(blob, o) {
8331 prep_blob(blob, 0);
8332 var out = [], argc = 0, R = "", C = "";
8333 while(blob.l < blob.length) {
8334 var cc = blob[blob.l++];
8335 switch(cc) {
8336 case 0x00: out.push(blob.read_shift(8, 'f')); break;
8337 case 0x01: {
8338 C = wk1_parse_rc(o[0].c, blob.read_shift(2), true);
8339 R = wk1_parse_rc(o[0].r, blob.read_shift(2), false);
8340 out.push(C + R);
8341 } break;
8342 case 0x02: {
8343 var c = wk1_parse_rc(o[0].c, blob.read_shift(2), true);
8344 var r = wk1_parse_rc(o[0].r, blob.read_shift(2), false);
8345 C = wk1_parse_rc(o[0].c, blob.read_shift(2), true);
8346 R = wk1_parse_rc(o[0].r, blob.read_shift(2), false);
8347 out.push(c + r + ":" + C + R);
8348 } break;
8349 case 0x03:
8350 if(blob.l < blob.length) { console.error("WK1 premature formula end"); return; }
8351 break;
8352 case 0x04: out.push("(" + out.pop() + ")"); break;
8353 case 0x05: out.push(blob.read_shift(2)); break;
8354 case 0x06: {
8355 /* TODO: text encoding */
8356 var Z = ""; while((cc = blob[blob.l++])) Z += String.fromCharCode(cc);
8357 out.push('"' + Z.replace(/"/g, '""') + '"'); break;
8358 } break;
8359
8360 case 0x08: out.push("-" + out.pop()); break;
8361 case 0x17: out.push("+" + out.pop()); break;
8362 case 0x16: out.push("NOT(" + out.pop() + ")"); break;
8363
8364 case 0x14: case 0x15: {
8365 var argR = out.pop(), argL = out.pop();
8366 out.push(["AND", "OR"][cc - 0x14] + "(" + argL + "," + argR + ")");
8367 } break;
8368
8369 default:
8370 if(cc < 0x20 && BinOpTab[cc]) {
8371 argR = out.pop(); argL = out.pop();
8372 out.push(argL + BinOpTab[cc] + argR);
8373 } else if(FuncTab[cc]) {
8374 argc = FuncTab[cc][1];
8375 if(argc == 69) argc = blob[blob.l++];
8376 if(argc > out.length) { console.error("WK1 bad formula parse 0x" + cc.toString(16) + ":|" + out.join("|") + "|"); return; }
8377 var args = out.slice(-argc);
8378 out.length -= argc;
8379 out.push(FuncTab[cc][0] + "(" + args.join(",") + ")");
8380 }
8381 else if(cc <= 0x07) return console.error("WK1 invalid opcode " + cc.toString(16));
8382 else if(cc <= 0x18) return console.error("WK1 unsupported op " + cc.toString(16));
8383 else if(cc <= 0x1E) return console.error("WK1 invalid opcode " + cc.toString(16));
8384 else if(cc <= 0x73) return console.error("WK1 unsupported function opcode " + cc.toString(16));
8385 // possible future functions ??
8386 else return console.error("WK1 unrecognized opcode " + cc.toString(16));
8387 }
8388 }
8389 if(out.length == 1) o[1].f = "" + out[0];
8390 else console.error("WK1 bad formula parse |" + out.join("|") + "|");
8391 }
8392
8393
8394 function parse_cell_3(blob/*::, length*/) {
8395 var o = [{c:0,r:0}, {t:'n',v:0}, 0];
8396 o[0].r = blob.read_shift(2); o[3] = blob[blob.l++]; o[0].c = blob[blob.l++];
8397 return o;
8398 }
8399
8400 function parse_LABEL_16(blob, length) {
8401 var o = parse_cell_3(blob, length);
8402 o[1].t = 's';
8403 o[1].v = blob.read_shift(length - 4, 'cstr');
8404 return o;
8405 }
8406 function write_LABEL_16(R, C, wsidx, s) {
8407 /* TODO: encoding */
8408 var o = new_buf(6 + s.length);
8409 o.write_shift(2, R);
8410 o.write_shift(1, wsidx);
8411 o.write_shift(1, C);
8412 o.write_shift(1, 0x27);
8413 for(var i = 0; i < s.length; ++i) {
8414 var cc = s.charCodeAt(i);
8415 o.write_shift(1, cc >= 0x80 ? 0x5F : cc);
8416 }
8417 o.write_shift(1, 0);
8418 return o;
8419 }
8420
8421 function parse_NUMBER_18(blob, length) {
8422 var o = parse_cell_3(blob, length);
8423 o[1].v = blob.read_shift(2);
8424 var v = o[1].v >> 1;
8425 if(o[1].v & 0x1) {
8426 switch(v & 0x07) {
8427 case 0: v = (v >> 3) * 5000; break;
8428 case 1: v = (v >> 3) * 500; break;
8429 case 2: v = (v >> 3) / 20; break;
8430 case 3: v = (v >> 3) / 200; break;
8431 case 4: v = (v >> 3) / 2000; break;
8432 case 5: v = (v >> 3) / 20000; break;
8433 case 6: v = (v >> 3) / 16; break;
8434 case 7: v = (v >> 3) / 64; break;
8435 }
8436 }
8437 o[1].v = v;
8438 return o;
8439 }
8440
8441 function parse_NUMBER_17(blob, length) {
8442 var o = parse_cell_3(blob, length);
8443 var v1 = blob.read_shift(4);
8444 var v2 = blob.read_shift(4);
8445 var e = blob.read_shift(2);
8446 if(e == 0xFFFF) {
8447 if(v1 === 0 && v2 === 0xC0000000) { o[1].t = "e"; o[1].v = 0x0F; } // ERR -> #VALUE!
8448 else if(v1 === 0 && v2 === 0xD0000000) { o[1].t = "e"; o[1].v = 0x2A; } // NA -> #N/A
8449 else o[1].v = 0;
8450 return o;
8451 }
8452 var s = e & 0x8000; e = (e&0x7FFF) - 16446;
8453 o[1].v = (1 - s*2) * (v2 * Math.pow(2, e+32) + v1 * Math.pow(2, e));
8454 return o;
8455 }
8456 function write_NUMBER_17(R, C, wsidx, v) {
8457 var o = new_buf(14);
8458 o.write_shift(2, R);
8459 o.write_shift(1, wsidx);
8460 o.write_shift(1, C);
8461 if(v == 0) {
8462 o.write_shift(4, 0);
8463 o.write_shift(4, 0);
8464 o.write_shift(2, 0xFFFF);
8465 return o;
8466 }
8467 var s = 0, e = 0, v1 = 0, v2 = 0;
8468 if(v < 0) { s = 1; v = -v; }
8469 e = Math.log2(v) | 0;
8470 v /= Math.pow(2, e-31);
8471 v2 = (v)>>>0;
8472 if((v2&0x80000000) == 0) { v/=2; ++e; v2 = v >>> 0; }
8473 v -= v2;
8474 v2 |= 0x80000000;
8475 v2 >>>= 0;
8476 v *= Math.pow(2, 32);
8477 v1 = v>>>0;
8478 o.write_shift(4, v1);
8479 o.write_shift(4, v2);
8480 e += 0x3FFF + (s ? 0x8000 : 0);
8481 o.write_shift(2, e);
8482 return o;
8483 }
8484
8485 function parse_FORMULA_19(blob, length) {
8486 var o = parse_NUMBER_17(blob, 14);
8487 blob.l += length - 14; /* TODO: WK3 formula */
8488 return o;
8489 }
8490
8491 function parse_NUMBER_25(blob, length) {
8492 var o = parse_cell_3(blob, length);
8493 var v1 = blob.read_shift(4);
8494 o[1].v = v1 >> 6;
8495 return o;
8496 }
8497
8498 function parse_NUMBER_27(blob, length) {
8499 var o = parse_cell_3(blob, length);
8500 var v1 = blob.read_shift(8,'f');
8501 o[1].v = v1;
8502 return o;
8503 }
8504
8505 function parse_FORMULA_28(blob, length) {
8506 var o = parse_NUMBER_27(blob, 14);
8507 blob.l += length - 10; /* TODO: formula */
8508 return o;
8509 }
8510
8511 function parse_XFORMAT(blob, length) {
8512 var o = {}, tgt = blob.l + length;
8513 while(blob.l < tgt) {
8514 var dt = blob.read_shift(2);
8515 if(dt == 0x36b0) {
8516 o[dt] = [0, ""];
8517 o[dt][0] = blob.read_shift(2);
8518 while(blob[blob.l]) { o[dt][1] += String.fromCharCode(blob[blob.l]); blob.l++; } blob.l++;
8519 }
8520 // TODO: 0x3a99 ??
8521 }
8522 return o;
8523 }
8524 function write_XFORMAT_SHEETNAME(name, wsidx) {
8525 var out = new_buf(5 + name.length);
8526 out.write_shift(2, 0x36b0);
8527 out.write_shift(2, wsidx);
8528 for(var i = 0; i < name.length; ++i) {
8529 var cc = name.charCodeAt(i);
8530 out[out.l++] = cc > 0x7F ? 0x5F : cc;
8531 }
8532 out[out.l++] = 0;
8533 return out;
8534 }
8535
8536 var WK1Enum = {
8537 /*::[*/0x0000/*::]*/: { n:"BOF", f:parseuint16 },
8538 /*::[*/0x0001/*::]*/: { n:"EOF" },
8539 /*::[*/0x0002/*::]*/: { n:"CALCMODE" },
8540 /*::[*/0x0003/*::]*/: { n:"CALCORDER" },
8541 /*::[*/0x0004/*::]*/: { n:"SPLIT" },
8542 /*::[*/0x0005/*::]*/: { n:"SYNC" },
8543 /*::[*/0x0006/*::]*/: { n:"RANGE", f:parse_RANGE },
8544 /*::[*/0x0007/*::]*/: { n:"WINDOW1" },
8545 /*::[*/0x0008/*::]*/: { n:"COLW1" },
8546 /*::[*/0x0009/*::]*/: { n:"WINTWO" },
8547 /*::[*/0x000A/*::]*/: { n:"COLW2" },
8548 /*::[*/0x000B/*::]*/: { n:"NAME" },
8549 /*::[*/0x000C/*::]*/: { n:"BLANK" },
8550 /*::[*/0x000D/*::]*/: { n:"INTEGER", f:parse_INTEGER },
8551 /*::[*/0x000E/*::]*/: { n:"NUMBER", f:parse_NUMBER },
8552 /*::[*/0x000F/*::]*/: { n:"LABEL", f:parse_LABEL },
8553 /*::[*/0x0010/*::]*/: { n:"FORMULA", f:parse_FORMULA },
8554 /*::[*/0x0018/*::]*/: { n:"TABLE" },
8555 /*::[*/0x0019/*::]*/: { n:"ORANGE" },
8556 /*::[*/0x001A/*::]*/: { n:"PRANGE" },
8557 /*::[*/0x001B/*::]*/: { n:"SRANGE" },
8558 /*::[*/0x001C/*::]*/: { n:"FRANGE" },
8559 /*::[*/0x001D/*::]*/: { n:"KRANGE1" },
8560 /*::[*/0x0020/*::]*/: { n:"HRANGE" },
8561 /*::[*/0x0023/*::]*/: { n:"KRANGE2" },
8562 /*::[*/0x0024/*::]*/: { n:"PROTEC" },
8563 /*::[*/0x0025/*::]*/: { n:"FOOTER" },
8564 /*::[*/0x0026/*::]*/: { n:"HEADER" },
8565 /*::[*/0x0027/*::]*/: { n:"SETUP" },
8566 /*::[*/0x0028/*::]*/: { n:"MARGINS" },
8567 /*::[*/0x0029/*::]*/: { n:"LABELFMT" },
8568 /*::[*/0x002A/*::]*/: { n:"TITLES" },
8569 /*::[*/0x002B/*::]*/: { n:"SHEETJS" },
8570 /*::[*/0x002D/*::]*/: { n:"GRAPH" },
8571 /*::[*/0x002E/*::]*/: { n:"NGRAPH" },
8572 /*::[*/0x002F/*::]*/: { n:"CALCCOUNT" },
8573 /*::[*/0x0030/*::]*/: { n:"UNFORMATTED" },
8574 /*::[*/0x0031/*::]*/: { n:"CURSORW12" },
8575 /*::[*/0x0032/*::]*/: { n:"WINDOW" },
8576 /*::[*/0x0033/*::]*/: { n:"STRING", f:parse_LABEL },
8577 /*::[*/0x0037/*::]*/: { n:"PASSWORD" },
8578 /*::[*/0x0038/*::]*/: { n:"LOCKED" },
8579 /*::[*/0x003C/*::]*/: { n:"QUERY" },
8580 /*::[*/0x003D/*::]*/: { n:"QUERYNAME" },
8581 /*::[*/0x003E/*::]*/: { n:"PRINT" },
8582 /*::[*/0x003F/*::]*/: { n:"PRINTNAME" },
8583 /*::[*/0x0040/*::]*/: { n:"GRAPH2" },
8584 /*::[*/0x0041/*::]*/: { n:"GRAPHNAME" },
8585 /*::[*/0x0042/*::]*/: { n:"ZOOM" },
8586 /*::[*/0x0043/*::]*/: { n:"SYMSPLIT" },
8587 /*::[*/0x0044/*::]*/: { n:"NSROWS" },
8588 /*::[*/0x0045/*::]*/: { n:"NSCOLS" },
8589 /*::[*/0x0046/*::]*/: { n:"RULER" },
8590 /*::[*/0x0047/*::]*/: { n:"NNAME" },
8591 /*::[*/0x0048/*::]*/: { n:"ACOMM" },
8592 /*::[*/0x0049/*::]*/: { n:"AMACRO" },
8593 /*::[*/0x004A/*::]*/: { n:"PARSE" },
8594 /*::[*/0x0066/*::]*/: { n:"PRANGES??" },
8595 /*::[*/0x0067/*::]*/: { n:"RRANGES??" },
8596 /*::[*/0x0068/*::]*/: { n:"FNAME??" },
8597 /*::[*/0x0069/*::]*/: { n:"MRANGES??" },
8598 /*::[*/0xFFFF/*::]*/: { n:"" }
8599 };
8600
8601 var WK3Enum = {
8602 /*::[*/0x0000/*::]*/: { n:"BOF" },
8603 /*::[*/0x0001/*::]*/: { n:"EOF" },
8604 /*::[*/0x0002/*::]*/: { n:"PASSWORD" },
8605 /*::[*/0x0003/*::]*/: { n:"CALCSET" },
8606 /*::[*/0x0004/*::]*/: { n:"WINDOWSET" },
8607 /*::[*/0x0005/*::]*/: { n:"SHEETCELLPTR" },
8608 /*::[*/0x0006/*::]*/: { n:"SHEETLAYOUT" },
8609 /*::[*/0x0007/*::]*/: { n:"COLUMNWIDTH" },
8610 /*::[*/0x0008/*::]*/: { n:"HIDDENCOLUMN" },
8611 /*::[*/0x0009/*::]*/: { n:"USERRANGE" },
8612 /*::[*/0x000A/*::]*/: { n:"SYSTEMRANGE" },
8613 /*::[*/0x000B/*::]*/: { n:"ZEROFORCE" },
8614 /*::[*/0x000C/*::]*/: { n:"SORTKEYDIR" },
8615 /*::[*/0x000D/*::]*/: { n:"FILESEAL" },
8616 /*::[*/0x000E/*::]*/: { n:"DATAFILLNUMS" },
8617 /*::[*/0x000F/*::]*/: { n:"PRINTMAIN" },
8618 /*::[*/0x0010/*::]*/: { n:"PRINTSTRING" },
8619 /*::[*/0x0011/*::]*/: { n:"GRAPHMAIN" },
8620 /*::[*/0x0012/*::]*/: { n:"GRAPHSTRING" },
8621 /*::[*/0x0013/*::]*/: { n:"??" },
8622 /*::[*/0x0014/*::]*/: { n:"ERRCELL" },
8623 /*::[*/0x0015/*::]*/: { n:"NACELL" },
8624 /*::[*/0x0016/*::]*/: { n:"LABEL16", f:parse_LABEL_16},
8625 /*::[*/0x0017/*::]*/: { n:"NUMBER17", f:parse_NUMBER_17 },
8626 /*::[*/0x0018/*::]*/: { n:"NUMBER18", f:parse_NUMBER_18 },
8627 /*::[*/0x0019/*::]*/: { n:"FORMULA19", f:parse_FORMULA_19},
8628 /*::[*/0x001A/*::]*/: { n:"FORMULA1A" },
8629 /*::[*/0x001B/*::]*/: { n:"XFORMAT", f:parse_XFORMAT },
8630 /*::[*/0x001C/*::]*/: { n:"DTLABELMISC" },
8631 /*::[*/0x001D/*::]*/: { n:"DTLABELCELL" },
8632 /*::[*/0x001E/*::]*/: { n:"GRAPHWINDOW" },
8633 /*::[*/0x001F/*::]*/: { n:"CPA" },
8634 /*::[*/0x0020/*::]*/: { n:"LPLAUTO" },
8635 /*::[*/0x0021/*::]*/: { n:"QUERY" },
8636 /*::[*/0x0022/*::]*/: { n:"HIDDENSHEET" },
8637 /*::[*/0x0023/*::]*/: { n:"??" },
8638 /*::[*/0x0025/*::]*/: { n:"NUMBER25", f:parse_NUMBER_25 },
8639 /*::[*/0x0026/*::]*/: { n:"??" },
8640 /*::[*/0x0027/*::]*/: { n:"NUMBER27", f:parse_NUMBER_27 },
8641 /*::[*/0x0028/*::]*/: { n:"FORMULA28", f:parse_FORMULA_28 },
8642 /*::[*/0x008E/*::]*/: { n:"??" },
8643 /*::[*/0x0093/*::]*/: { n:"??" },
8644 /*::[*/0x0096/*::]*/: { n:"??" },
8645 /*::[*/0x0097/*::]*/: { n:"??" },
8646 /*::[*/0x0098/*::]*/: { n:"??" },
8647 /*::[*/0x0099/*::]*/: { n:"??" },
8648 /*::[*/0x009A/*::]*/: { n:"??" },
8649 /*::[*/0x009B/*::]*/: { n:"??" },
8650 /*::[*/0x009C/*::]*/: { n:"??" },
8651 /*::[*/0x00A3/*::]*/: { n:"??" },
8652 /*::[*/0x00AE/*::]*/: { n:"??" },
8653 /*::[*/0x00AF/*::]*/: { n:"??" },
8654 /*::[*/0x00B0/*::]*/: { n:"??" },
8655 /*::[*/0x00B1/*::]*/: { n:"??" },
8656 /*::[*/0x00B8/*::]*/: { n:"??" },
8657 /*::[*/0x00B9/*::]*/: { n:"??" },
8658 /*::[*/0x00BA/*::]*/: { n:"??" },
8659 /*::[*/0x00BB/*::]*/: { n:"??" },
8660 /*::[*/0x00BC/*::]*/: { n:"??" },
8661 /*::[*/0x00C3/*::]*/: { n:"??" },
8662 /*::[*/0x00C9/*::]*/: { n:"??" },
8663 /*::[*/0x00CD/*::]*/: { n:"??" },
8664 /*::[*/0x00CE/*::]*/: { n:"??" },
8665 /*::[*/0x00CF/*::]*/: { n:"??" },
8666 /*::[*/0x00D0/*::]*/: { n:"??" },
8667 /*::[*/0x0100/*::]*/: { n:"??" },
8668 /*::[*/0x0103/*::]*/: { n:"??" },
8669 /*::[*/0x0104/*::]*/: { n:"??" },
8670 /*::[*/0x0105/*::]*/: { n:"??" },
8671 /*::[*/0x0106/*::]*/: { n:"??" },
8672 /*::[*/0x0107/*::]*/: { n:"??" },
8673 /*::[*/0x0109/*::]*/: { n:"??" },
8674 /*::[*/0x010A/*::]*/: { n:"??" },
8675 /*::[*/0x010B/*::]*/: { n:"??" },
8676 /*::[*/0x010C/*::]*/: { n:"??" },
8677 /*::[*/0x010E/*::]*/: { n:"??" },
8678 /*::[*/0x010F/*::]*/: { n:"??" },
8679 /*::[*/0x0180/*::]*/: { n:"??" },
8680 /*::[*/0x0185/*::]*/: { n:"??" },
8681 /*::[*/0x0186/*::]*/: { n:"??" },
8682 /*::[*/0x0189/*::]*/: { n:"??" },
8683 /*::[*/0x018C/*::]*/: { n:"??" },
8684 /*::[*/0x0200/*::]*/: { n:"??" },
8685 /*::[*/0x0202/*::]*/: { n:"??" },
8686 /*::[*/0x0201/*::]*/: { n:"??" },
8687 /*::[*/0x0204/*::]*/: { n:"??" },
8688 /*::[*/0x0205/*::]*/: { n:"??" },
8689 /*::[*/0x0280/*::]*/: { n:"??" },
8690 /*::[*/0x0281/*::]*/: { n:"??" },
8691 /*::[*/0x0282/*::]*/: { n:"??" },
8692 /*::[*/0x0283/*::]*/: { n:"??" },
8693 /*::[*/0x0284/*::]*/: { n:"??" },
8694 /*::[*/0x0285/*::]*/: { n:"??" },
8695 /*::[*/0x0286/*::]*/: { n:"??" },
8696 /*::[*/0x0287/*::]*/: { n:"??" },
8697 /*::[*/0x0288/*::]*/: { n:"??" },
8698 /*::[*/0x0292/*::]*/: { n:"??" },
8699 /*::[*/0x0293/*::]*/: { n:"??" },
8700 /*::[*/0x0294/*::]*/: { n:"??" },
8701 /*::[*/0x0295/*::]*/: { n:"??" },
8702 /*::[*/0x0296/*::]*/: { n:"??" },
8703 /*::[*/0x0299/*::]*/: { n:"??" },
8704 /*::[*/0x029A/*::]*/: { n:"??" },
8705 /*::[*/0x0300/*::]*/: { n:"??" },
8706 /*::[*/0x0304/*::]*/: { n:"??" },
8707 /*::[*/0x0640/*::]*/: { n:"??" },
8708 /*::[*/0x0642/*::]*/: { n:"??" },
8709 /*::[*/0x0701/*::]*/: { n:"??" },
8710 /*::[*/0x0702/*::]*/: { n:"??" },
8711 /*::[*/0x0703/*::]*/: { n:"??" },
8712 /*::[*/0x0704/*::]*/: { n:"??" },
8713 /*::[*/0x0780/*::]*/: { n:"??" },
8714 /*::[*/0x0800/*::]*/: { n:"??" },
8715 /*::[*/0x0801/*::]*/: { n:"??" },
8716 /*::[*/0x0804/*::]*/: { n:"??" },
8717 /*::[*/0x0A80/*::]*/: { n:"??" },
8718 /*::[*/0x2AF6/*::]*/: { n:"??" },
8719 /*::[*/0x3231/*::]*/: { n:"??" },
8720 /*::[*/0x6E49/*::]*/: { n:"??" },
8721 /*::[*/0x6F44/*::]*/: { n:"??" },
8722 /*::[*/0xFFFF/*::]*/: { n:"" }
8723 };
8724 return {
8725 sheet_to_wk1: sheet_to_wk1,
8726 book_to_wk3: book_to_wk3,
8727 to_workbook: lotus_to_workbook
8728 };
8729})();
8730/* 18.4.7 rPr CT_RPrElt */
8731function parse_rpr(rpr) {
8732 var font = {}, m = rpr.match(tagregex), i = 0;
8733 var pass = false;
8734 if(m) for(;i!=m.length; ++i) {
8735 var y = parsexmltag(m[i]);
8736 switch(y[0].replace(/\w*:/g,"")) {
8737 /* 18.8.12 condense CT_BooleanProperty */
8738 /* ** not required . */
8739 case '<condense': break;
8740 /* 18.8.17 extend CT_BooleanProperty */
8741 /* ** not required . */
8742 case '<extend': break;
8743 /* 18.8.36 shadow CT_BooleanProperty */
8744 /* ** not required . */
8745 case '<shadow':
8746 if(!y.val) break;
8747 /* falls through */
8748 case '<shadow>':
8749 case '<shadow/>': font.shadow = 1; break;
8750 case '</shadow>': break;
8751
8752 /* 18.4.1 charset CT_IntProperty TODO */
8753 case '<charset':
8754 if(y.val == '1') break;
8755 font.cp = CS2CP[parseInt(y.val, 10)];
8756 break;
8757
8758 /* 18.4.2 outline CT_BooleanProperty TODO */
8759 case '<outline':
8760 if(!y.val) break;
8761 /* falls through */
8762 case '<outline>':
8763 case '<outline/>': font.outline = 1; break;
8764 case '</outline>': break;
8765
8766 /* 18.4.5 rFont CT_FontName */
8767 case '<rFont': font.name = y.val; break;
8768
8769 /* 18.4.11 sz CT_FontSize */
8770 case '<sz': font.sz = y.val; break;
8771
8772 /* 18.4.10 strike CT_BooleanProperty */
8773 case '<strike':
8774 if(!y.val) break;
8775 /* falls through */
8776 case '<strike>':
8777 case '<strike/>': font.strike = 1; break;
8778 case '</strike>': break;
8779
8780 /* 18.4.13 u CT_UnderlineProperty */
8781 case '<u':
8782 if(!y.val) break;
8783 switch(y.val) {
8784 case 'double': font.uval = "double"; break;
8785 case 'singleAccounting': font.uval = "single-accounting"; break;
8786 case 'doubleAccounting': font.uval = "double-accounting"; break;
8787 }
8788 /* falls through */
8789 case '<u>':
8790 case '<u/>': font.u = 1; break;
8791 case '</u>': break;
8792
8793 /* 18.8.2 b */
8794 case '<b':
8795 if(y.val == '0') break;
8796 /* falls through */
8797 case '<b>':
8798 case '<b/>': font.b = 1; break;
8799 case '</b>': break;
8800
8801 /* 18.8.26 i */
8802 case '<i':
8803 if(y.val == '0') break;
8804 /* falls through */
8805 case '<i>':
8806 case '<i/>': font.i = 1; break;
8807 case '</i>': break;
8808
8809 /* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */
8810 case '<color':
8811 if(y.rgb) font.color = y.rgb.slice(2,8);
8812 break;
8813
8814 /* 18.8.18 family ST_FontFamily */
8815 case '<family': font.family = y.val; break;
8816
8817 /* 18.4.14 vertAlign CT_VerticalAlignFontProperty TODO */
8818 case '<vertAlign': font.valign = y.val; break;
8819
8820 /* 18.8.35 scheme CT_FontScheme TODO */
8821 case '<scheme': break;
8822
8823 /* 18.2.10 extLst CT_ExtensionList ? */
8824 case '<extLst': case '<extLst>': case '</extLst>': break;
8825 case '<ext': pass = true; break;
8826 case '</ext>': pass = false; break;
8827 default:
8828 if(y[0].charCodeAt(1) !== 47 && !pass) throw new Error('Unrecognized rich format ' + y[0]);
8829 }
8830 }
8831 return font;
8832}
8833
8834var parse_rs = (function() {
8835 var tregex = matchtag("t"), rpregex = matchtag("rPr");
8836 /* 18.4.4 r CT_RElt */
8837 function parse_r(r) {
8838 /* 18.4.12 t ST_Xstring */
8839 var t = r.match(tregex)/*, cp = 65001*/;
8840 if(!t) return {t:"s", v:""};
8841
8842 var o/*:Cell*/ = ({t:'s', v:unescapexml(t[1])}/*:any*/);
8843 var rpr = r.match(rpregex);
8844 if(rpr) o.s = parse_rpr(rpr[1]);
8845 return o;
8846 }
8847 var rregex = /<(?:\w+:)?r>/g, rend = /<\/(?:\w+:)?r>/;
8848 return function parse_rs(rs) {
8849 return rs.replace(rregex,"").split(rend).map(parse_r).filter(function(r) { return r.v; });
8850 };
8851})();
8852
8853
8854/* Parse a list of <r> tags */
8855var rs_to_html = (function parse_rs_factory() {
8856 var nlregex = /(\r\n|\n)/g;
8857 function parse_rpr2(font, intro, outro) {
8858 var style/*:Array<string>*/ = [];
8859
8860 if(font.u) style.push("text-decoration: underline;");
8861 if(font.uval) style.push("text-underline-style:" + font.uval + ";");
8862 if(font.sz) style.push("font-size:" + font.sz + "pt;");
8863 if(font.outline) style.push("text-effect: outline;");
8864 if(font.shadow) style.push("text-shadow: auto;");
8865 intro.push('<span style="' + style.join("") + '">');
8866
8867 if(font.b) { intro.push("<b>"); outro.push("</b>"); }
8868 if(font.i) { intro.push("<i>"); outro.push("</i>"); }
8869 if(font.strike) { intro.push("<s>"); outro.push("</s>"); }
8870
8871 var align = font.valign || "";
8872 if(align == "superscript" || align == "super") align = "sup";
8873 else if(align == "subscript") align = "sub";
8874 if(align != "") { intro.push("<" + align + ">"); outro.push("</" + align + ">"); }
8875
8876 outro.push("</span>");
8877 return font;
8878 }
8879
8880 /* 18.4.4 r CT_RElt */
8881 function r_to_html(r) {
8882 var terms/*:[Array<string>, string, Array<string>]*/ = [[],r.v,[]];
8883 if(!r.v) return "";
8884
8885 if(r.s) parse_rpr2(r.s, terms[0], terms[2]);
8886
8887 return terms[0].join("") + terms[1].replace(nlregex,'<br/>') + terms[2].join("");
8888 }
8889
8890 return function parse_rs(rs) {
8891 return rs.map(r_to_html).join("");
8892 };
8893})();
8894
8895/* 18.4.8 si CT_Rst */
8896var sitregex = /<(?:\w+:)?t[^>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r>/;
8897var sirphregex = /<(?:\w+:)?rPh.*?>([\s\S]*?)<\/(?:\w+:)?rPh>/g;
8898function parse_si(x, opts) {
8899 var html = opts ? opts.cellHTML : true;
8900 var z = {};
8901 if(!x) return { t: "" };
8902 //var y;
8903 /* 18.4.12 t ST_Xstring (Plaintext String) */
8904 // TODO: is whitespace actually valid here?
8905 if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) {
8906 z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||""));
8907 z.r = utf8read(x);
8908 if(html) z.h = escapehtml(z.t);
8909 }
8910 /* 18.4.4 r CT_RElt (Rich Text Run) */
8911 else if((/*y = */x.match(sirregex))) {
8912 z.r = utf8read(x);
8913 z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")));
8914 if(html) z.h = rs_to_html(parse_rs(z.r));
8915 }
8916 /* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
8917 /* 18.4.6 rPh CT_PhoneticRun (TODO: needed for Asian support) */
8918 return z;
8919}
8920
8921/* 18.4 Shared String Table */
8922var sstr0 = /<(?:\w+:)?sst([^>]*)>([\s\S]*)<\/(?:\w+:)?sst>/;
8923var sstr1 = /<(?:\w+:)?(?:si|sstItem)>/g;
8924var sstr2 = /<\/(?:\w+:)?(?:si|sstItem)>/;
8925function parse_sst_xml(data/*:string*/, opts)/*:SST*/ {
8926 var s/*:SST*/ = ([]/*:any*/), ss = "";
8927 if(!data) return s;
8928 /* 18.4.9 sst CT_Sst */
8929 var sst = data.match(sstr0);
8930 if(sst) {
8931 ss = sst[2].replace(sstr1,"").split(sstr2);
8932 for(var i = 0; i != ss.length; ++i) {
8933 var o = parse_si(ss[i].trim(), opts);
8934 if(o != null) s[s.length] = o;
8935 }
8936 sst = parsexmltag(sst[1]); s.Count = sst.count; s.Unique = sst.uniqueCount;
8937 }
8938 return s;
8939}
8940
8941RELS.SST = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
8942var straywsregex = /^\s|\s$|[\t\n\r]/;
8943function write_sst_xml(sst/*:SST*/, opts)/*:string*/ {
8944 if(!opts.bookSST) return "";
8945 var o = [XML_HEADER];
8946 o[o.length] = (writextag('sst', null, {
8947 xmlns: XMLNS.main[0],
8948 count: sst.Count,
8949 uniqueCount: sst.Unique
8950 }));
8951 for(var i = 0; i != sst.length; ++i) { if(sst[i] == null) continue;
8952 var s/*:XLString*/ = sst[i];
8953 var sitag = "<si>";
8954 if(s.r) sitag += s.r;
8955 else {
8956 sitag += "<t";
8957 if(!s.t) s.t = "";
8958 if(s.t.match(straywsregex)) sitag += ' xml:space="preserve"';
8959 sitag += ">" + escapexml(s.t) + "</t>";
8960 }
8961 sitag += "</si>";
8962 o[o.length] = (sitag);
8963 }
8964 if(o.length>2){ o[o.length] = ('</sst>'); o[1]=o[1].replace("/>",">"); }
8965 return o.join("");
8966}
8967/* [MS-XLSB] 2.4.221 BrtBeginSst */
8968function parse_BrtBeginSst(data) {
8969 return [data.read_shift(4), data.read_shift(4)];
8970}
8971
8972/* [MS-XLSB] 2.1.7.45 Shared Strings */
8973function parse_sst_bin(data, opts)/*:SST*/ {
8974 var s/*:SST*/ = ([]/*:any*/);
8975 var pass = false;
8976 recordhopper(data, function hopper_sst(val, R_n, RT) {
8977 switch(RT) {
8978 case 0x009F: /* 'BrtBeginSst' */
8979 s.Count = val[0]; s.Unique = val[1]; break;
8980 case 0x0013: /* 'BrtSSTItem' */
8981 s.push(val); break;
8982 case 0x00A0: /* 'BrtEndSst' */
8983 return true;
8984
8985 case 0x0023: /* 'BrtFRTBegin' */
8986 pass = true; break;
8987 case 0x0024: /* 'BrtFRTEnd' */
8988 pass = false; break;
8989
8990 default:
8991 if(R_n.indexOf("Begin") > 0){/* empty */}
8992 else if(R_n.indexOf("End") > 0){/* empty */}
8993 if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
8994 }
8995 });
8996 return s;
8997}
8998
8999function write_BrtBeginSst(sst, o) {
9000 if(!o) o = new_buf(8);
9001 o.write_shift(4, sst.Count);
9002 o.write_shift(4, sst.Unique);
9003 return o;
9004}
9005
9006var write_BrtSSTItem = write_RichStr;
9007
9008function write_sst_bin(sst/*::, opts*/) {
9009 var ba = buf_array();
9010 write_record(ba, "BrtBeginSst", write_BrtBeginSst(sst));
9011 for(var i = 0; i < sst.length; ++i) write_record(ba, "BrtSSTItem", write_BrtSSTItem(sst[i]));
9012 /* FRTSST */
9013 write_record(ba, "BrtEndSst");
9014 return ba.end();
9015}
9016function _JS2ANSI(str/*:string*/)/*:Array<number>*/ {
9017 if(typeof cptable !== 'undefined') return cptable.utils.encode(current_ansi, str);
9018 var o/*:Array<number>*/ = [], oo = str.split("");
9019 for(var i = 0; i < oo.length; ++i) o[i] = oo[i].charCodeAt(0);
9020 return o;
9021}
9022
9023/* [MS-OFFCRYPTO] 2.1.4 Version */
9024function parse_CRYPTOVersion(blob, length/*:?number*/) {
9025 var o/*:any*/ = {};
9026 o.Major = blob.read_shift(2);
9027 o.Minor = blob.read_shift(2);
9028 /*:: if(length == null) return o; */
9029 if(length >= 4) blob.l += length - 4;
9030 return o;
9031}
9032
9033/* [MS-OFFCRYPTO] 2.1.5 DataSpaceVersionInfo */
9034function parse_DataSpaceVersionInfo(blob) {
9035 var o = {};
9036 o.id = blob.read_shift(0, 'lpp4');
9037 o.R = parse_CRYPTOVersion(blob, 4);
9038 o.U = parse_CRYPTOVersion(blob, 4);
9039 o.W = parse_CRYPTOVersion(blob, 4);
9040 return o;
9041}
9042
9043/* [MS-OFFCRYPTO] 2.1.6.1 DataSpaceMapEntry Structure */
9044function parse_DataSpaceMapEntry(blob) {
9045 var len = blob.read_shift(4);
9046 var end = blob.l + len - 4;
9047 var o = {};
9048 var cnt = blob.read_shift(4);
9049 var comps/*:Array<{t:number, v:string}>*/ = [];
9050 /* [MS-OFFCRYPTO] 2.1.6.2 DataSpaceReferenceComponent Structure */
9051 while(cnt-- > 0) comps.push({ t: blob.read_shift(4), v: blob.read_shift(0, 'lpp4') });
9052 o.name = blob.read_shift(0, 'lpp4');
9053 o.comps = comps;
9054 if(blob.l != end) throw new Error("Bad DataSpaceMapEntry: " + blob.l + " != " + end);
9055 return o;
9056}
9057
9058/* [MS-OFFCRYPTO] 2.1.6 DataSpaceMap */
9059function parse_DataSpaceMap(blob) {
9060 var o = [];
9061 blob.l += 4; // must be 0x8
9062 var cnt = blob.read_shift(4);
9063 while(cnt-- > 0) o.push(parse_DataSpaceMapEntry(blob));
9064 return o;
9065}
9066
9067/* [MS-OFFCRYPTO] 2.1.7 DataSpaceDefinition */
9068function parse_DataSpaceDefinition(blob)/*:Array<string>*/ {
9069 var o/*:Array<string>*/ = [];
9070 blob.l += 4; // must be 0x8
9071 var cnt = blob.read_shift(4);
9072 while(cnt-- > 0) o.push(blob.read_shift(0, 'lpp4'));
9073 return o;
9074}
9075
9076/* [MS-OFFCRYPTO] 2.1.8 DataSpaceDefinition */
9077function parse_TransformInfoHeader(blob) {
9078 var o = {};
9079 /*var len = */blob.read_shift(4);
9080 blob.l += 4; // must be 0x1
9081 o.id = blob.read_shift(0, 'lpp4');
9082 o.name = blob.read_shift(0, 'lpp4');
9083 o.R = parse_CRYPTOVersion(blob, 4);
9084 o.U = parse_CRYPTOVersion(blob, 4);
9085 o.W = parse_CRYPTOVersion(blob, 4);
9086 return o;
9087}
9088
9089function parse_Primary(blob) {
9090 /* [MS-OFFCRYPTO] 2.2.6 IRMDSTransformInfo */
9091 var hdr = parse_TransformInfoHeader(blob);
9092 /* [MS-OFFCRYPTO] 2.1.9 EncryptionTransformInfo */
9093 hdr.ename = blob.read_shift(0, '8lpp4');
9094 hdr.blksz = blob.read_shift(4);
9095 hdr.cmode = blob.read_shift(4);
9096 if(blob.read_shift(4) != 0x04) throw new Error("Bad !Primary record");
9097 return hdr;
9098}
9099
9100/* [MS-OFFCRYPTO] 2.3.2 Encryption Header */
9101function parse_EncryptionHeader(blob, length/*:number*/) {
9102 var tgt = blob.l + length;
9103 var o = {};
9104 o.Flags = (blob.read_shift(4) & 0x3F);
9105 blob.l += 4;
9106 o.AlgID = blob.read_shift(4);
9107 var valid = false;
9108 switch(o.AlgID) {
9109 case 0x660E: case 0x660F: case 0x6610: valid = (o.Flags == 0x24); break;
9110 case 0x6801: valid = (o.Flags == 0x04); break;
9111 case 0: valid = (o.Flags == 0x10 || o.Flags == 0x04 || o.Flags == 0x24); break;
9112 default: throw 'Unrecognized encryption algorithm: ' + o.AlgID;
9113 }
9114 if(!valid) throw new Error("Encryption Flags/AlgID mismatch");
9115 o.AlgIDHash = blob.read_shift(4);
9116 o.KeySize = blob.read_shift(4);
9117 o.ProviderType = blob.read_shift(4);
9118 blob.l += 8;
9119 o.CSPName = blob.read_shift((tgt-blob.l)>>1, 'utf16le');
9120 blob.l = tgt;
9121 return o;
9122}
9123
9124/* [MS-OFFCRYPTO] 2.3.3 Encryption Verifier */
9125function parse_EncryptionVerifier(blob, length/*:number*/) {
9126 var o = {}, tgt = blob.l + length;
9127 blob.l += 4; // SaltSize must be 0x10
9128 o.Salt = blob.slice(blob.l, blob.l+16); blob.l += 16;
9129 o.Verifier = blob.slice(blob.l, blob.l+16); blob.l += 16;
9130 /*var sz = */blob.read_shift(4);
9131 o.VerifierHash = blob.slice(blob.l, tgt); blob.l = tgt;
9132 return o;
9133}
9134
9135/* [MS-OFFCRYPTO] 2.3.4.* EncryptionInfo Stream */
9136function parse_EncryptionInfo(blob) {
9137 var vers = parse_CRYPTOVersion(blob);
9138 switch(vers.Minor) {
9139 case 0x02: return [vers.Minor, parse_EncInfoStd(blob, vers)];
9140 case 0x03: return [vers.Minor, parse_EncInfoExt(blob, vers)];
9141 case 0x04: return [vers.Minor, parse_EncInfoAgl(blob, vers)];
9142 }
9143 throw new Error("ECMA-376 Encrypted file unrecognized Version: " + vers.Minor);
9144}
9145
9146/* [MS-OFFCRYPTO] 2.3.4.5 EncryptionInfo Stream (Standard Encryption) */
9147function parse_EncInfoStd(blob/*::, vers*/) {
9148 var flags = blob.read_shift(4);
9149 if((flags & 0x3F) != 0x24) throw new Error("EncryptionInfo mismatch");
9150 var sz = blob.read_shift(4);
9151 //var tgt = blob.l + sz;
9152 var hdr = parse_EncryptionHeader(blob, sz);
9153 var verifier = parse_EncryptionVerifier(blob, blob.length - blob.l);
9154 return { t:"Std", h:hdr, v:verifier };
9155}
9156/* [MS-OFFCRYPTO] 2.3.4.6 EncryptionInfo Stream (Extensible Encryption) */
9157function parse_EncInfoExt(/*::blob, vers*/) { throw new Error("File is password-protected: ECMA-376 Extensible"); }
9158/* [MS-OFFCRYPTO] 2.3.4.10 EncryptionInfo Stream (Agile Encryption) */
9159function parse_EncInfoAgl(blob/*::, vers*/) {
9160 var KeyData = ["saltSize","blockSize","keyBits","hashSize","cipherAlgorithm","cipherChaining","hashAlgorithm","saltValue"];
9161 blob.l+=4;
9162 var xml = blob.read_shift(blob.length - blob.l, 'utf8');
9163 var o = {};
9164 xml.replace(tagregex, function xml_agile(x) {
9165 var y/*:any*/ = parsexmltag(x);
9166 switch(strip_ns(y[0])) {
9167 case '<?xml': break;
9168 case '<encryption': case '</encryption>': break;
9169 case '<keyData': KeyData.forEach(function(k) { o[k] = y[k]; }); break;
9170 case '<dataIntegrity': o.encryptedHmacKey = y.encryptedHmacKey; o.encryptedHmacValue = y.encryptedHmacValue; break;
9171 case '<keyEncryptors>': case '<keyEncryptors': o.encs = []; break;
9172 case '</keyEncryptors>': break;
9173
9174 case '<keyEncryptor': o.uri = y.uri; break;
9175 case '</keyEncryptor>': break;
9176 case '<encryptedKey': o.encs.push(y); break;
9177 default: throw y[0];
9178 }
9179 });
9180 return o;
9181}
9182
9183/* [MS-OFFCRYPTO] 2.3.5.1 RC4 CryptoAPI Encryption Header */
9184function parse_RC4CryptoHeader(blob, length/*:number*/) {
9185 var o = {};
9186 var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4); length -= 4;
9187 if(vers.Minor != 2) throw new Error('unrecognized minor version code: ' + vers.Minor);
9188 if(vers.Major > 4 || vers.Major < 2) throw new Error('unrecognized major version code: ' + vers.Major);
9189 o.Flags = blob.read_shift(4); length -= 4;
9190 var sz = blob.read_shift(4); length -= 4;
9191 o.EncryptionHeader = parse_EncryptionHeader(blob, sz); length -= sz;
9192 o.EncryptionVerifier = parse_EncryptionVerifier(blob, length);
9193 return o;
9194}
9195/* [MS-OFFCRYPTO] 2.3.6.1 RC4 Encryption Header */
9196function parse_RC4Header(blob/*::, length*/) {
9197 var o = {};
9198 var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4);
9199 if(vers.Major != 1 || vers.Minor != 1) throw 'unrecognized version code ' + vers.Major + ' : ' + vers.Minor;
9200 o.Salt = blob.read_shift(16);
9201 o.EncryptedVerifier = blob.read_shift(16);
9202 o.EncryptedVerifierHash = blob.read_shift(16);
9203 return o;
9204}
9205
9206/* [MS-OFFCRYPTO] 2.3.7.1 Binary Document Password Verifier Derivation */
9207function crypto_CreatePasswordVerifier_Method1(Password/*:string*/) {
9208 var Verifier = 0x0000, PasswordArray;
9209 var PasswordDecoded = _JS2ANSI(Password);
9210 var len = PasswordDecoded.length + 1, i, PasswordByte;
9211 var Intermediate1, Intermediate2, Intermediate3;
9212 PasswordArray = new_raw_buf(len);
9213 PasswordArray[0] = PasswordDecoded.length;
9214 for(i = 1; i != len; ++i) PasswordArray[i] = PasswordDecoded[i-1];
9215 for(i = len-1; i >= 0; --i) {
9216 PasswordByte = PasswordArray[i];
9217 Intermediate1 = ((Verifier & 0x4000) === 0x0000) ? 0 : 1;
9218 Intermediate2 = (Verifier << 1) & 0x7FFF;
9219 Intermediate3 = Intermediate1 | Intermediate2;
9220 Verifier = Intermediate3 ^ PasswordByte;
9221 }
9222 return Verifier ^ 0xCE4B;
9223}
9224
9225/* [MS-OFFCRYPTO] 2.3.7.2 Binary Document XOR Array Initialization */
9226var crypto_CreateXorArray_Method1 = (function() {
9227 var PadArray = [0xBB, 0xFF, 0xFF, 0xBA, 0xFF, 0xFF, 0xB9, 0x80, 0x00, 0xBE, 0x0F, 0x00, 0xBF, 0x0F, 0x00];
9228 var InitialCode = [0xE1F0, 0x1D0F, 0xCC9C, 0x84C0, 0x110C, 0x0E10, 0xF1CE, 0x313E, 0x1872, 0xE139, 0xD40F, 0x84F9, 0x280C, 0xA96A, 0x4EC3];
9229 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];
9230 var Ror = function(Byte) { return ((Byte/2) | (Byte*128)) & 0xFF; };
9231 var XorRor = function(byte1, byte2) { return Ror(byte1 ^ byte2); };
9232 var CreateXorKey_Method1 = function(Password) {
9233 var XorKey = InitialCode[Password.length - 1];
9234 var CurrentElement = 0x68;
9235 for(var i = Password.length-1; i >= 0; --i) {
9236 var Char = Password[i];
9237 for(var j = 0; j != 7; ++j) {
9238 if(Char & 0x40) XorKey ^= XorMatrix[CurrentElement];
9239 Char *= 2; --CurrentElement;
9240 }
9241 }
9242 return XorKey;
9243 };
9244 return function(password/*:string*/) {
9245 var Password = _JS2ANSI(password);
9246 var XorKey = CreateXorKey_Method1(Password);
9247 var Index = Password.length;
9248 var ObfuscationArray = new_raw_buf(16);
9249 for(var i = 0; i != 16; ++i) ObfuscationArray[i] = 0x00;
9250 var Temp, PasswordLastChar, PadIndex;
9251 if((Index & 1) === 1) {
9252 Temp = XorKey >> 8;
9253 ObfuscationArray[Index] = XorRor(PadArray[0], Temp);
9254 --Index;
9255 Temp = XorKey & 0xFF;
9256 PasswordLastChar = Password[Password.length - 1];
9257 ObfuscationArray[Index] = XorRor(PasswordLastChar, Temp);
9258 }
9259 while(Index > 0) {
9260 --Index;
9261 Temp = XorKey >> 8;
9262 ObfuscationArray[Index] = XorRor(Password[Index], Temp);
9263 --Index;
9264 Temp = XorKey & 0xFF;
9265 ObfuscationArray[Index] = XorRor(Password[Index], Temp);
9266 }
9267 Index = 15;
9268 PadIndex = 15 - Password.length;
9269 while(PadIndex > 0) {
9270 Temp = XorKey >> 8;
9271 ObfuscationArray[Index] = XorRor(PadArray[PadIndex], Temp);
9272 --Index;
9273 --PadIndex;
9274 Temp = XorKey & 0xFF;
9275 ObfuscationArray[Index] = XorRor(Password[Index], Temp);
9276 --Index;
9277 --PadIndex;
9278 }
9279 return ObfuscationArray;
9280 };
9281})();
9282
9283/* [MS-OFFCRYPTO] 2.3.7.3 Binary Document XOR Data Transformation Method 1 */
9284var crypto_DecryptData_Method1 = function(password/*:string*/, Data, XorArrayIndex, XorArray, O) {
9285 /* If XorArray is set, use it; if O is not set, make changes in-place */
9286 if(!O) O = Data;
9287 if(!XorArray) XorArray = crypto_CreateXorArray_Method1(password);
9288 var Index, Value;
9289 for(Index = 0; Index != Data.length; ++Index) {
9290 Value = Data[Index];
9291 Value ^= XorArray[XorArrayIndex];
9292 Value = ((Value>>5) | (Value<<3)) & 0xFF;
9293 O[Index] = Value;
9294 ++XorArrayIndex;
9295 }
9296 return [O, XorArrayIndex, XorArray];
9297};
9298
9299var crypto_MakeXorDecryptor = function(password/*:string*/) {
9300 var XorArrayIndex = 0, XorArray = crypto_CreateXorArray_Method1(password);
9301 return function(Data) {
9302 var O = crypto_DecryptData_Method1("", Data, XorArrayIndex, XorArray);
9303 XorArrayIndex = O[1];
9304 return O[0];
9305 };
9306};
9307
9308/* 2.5.343 */
9309function parse_XORObfuscation(blob, length, opts, out) {
9310 var o = ({ key: parseuint16(blob), verificationBytes: parseuint16(blob) }/*:any*/);
9311 if(opts.password) o.verifier = crypto_CreatePasswordVerifier_Method1(opts.password);
9312 out.valid = o.verificationBytes === o.verifier;
9313 if(out.valid) out.insitu = crypto_MakeXorDecryptor(opts.password);
9314 return o;
9315}
9316
9317/* 2.4.117 */
9318function parse_FilePassHeader(blob, length/*:number*/, oo) {
9319 var o = oo || {}; o.Info = blob.read_shift(2); blob.l -= 2;
9320 if(o.Info === 1) o.Data = parse_RC4Header(blob, length);
9321 else o.Data = parse_RC4CryptoHeader(blob, length);
9322 return o;
9323}
9324function parse_FilePass(blob, length/*:number*/, opts) {
9325 var o = ({ Type: opts.biff >= 8 ? blob.read_shift(2) : 0 }/*:any*/); /* wEncryptionType */
9326 if(o.Type) parse_FilePassHeader(blob, length-2, o);
9327 else parse_XORObfuscation(blob, opts.biff >= 8 ? length : length - 2, opts, o);
9328 return o;
9329}
9330
9331
9332var RTF = (function() {
9333 function rtf_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
9334 switch(opts.type) {
9335 case 'base64': return rtf_to_sheet_str(Base64.decode(d), opts);
9336 case 'binary': return rtf_to_sheet_str(d, opts);
9337 case 'buffer': return rtf_to_sheet_str(has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d), opts);
9338 case 'array': return rtf_to_sheet_str(cc2str(d), opts);
9339 }
9340 throw new Error("Unrecognized type " + opts.type);
9341 }
9342
9343 /* TODO: this is a stub */
9344 function rtf_to_sheet_str(str/*:string*/, opts)/*:Worksheet*/ {
9345 var o = opts || {};
9346 var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/);
9347
9348 var rows = str.match(/\\trowd.*?\\row\b/g);
9349 if(!rows.length) throw new Error("RTF missing table");
9350 var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:rows.length - 1}}/*:any*/);
9351 rows.forEach(function(rowtf, R) {
9352 if(Array.isArray(ws)) ws[R] = [];
9353 var rtfre = /\\\w+\b/g;
9354 var last_index = 0;
9355 var res;
9356 var C = -1;
9357 while((res = rtfre.exec(rowtf))) {
9358 switch(res[0]) {
9359 case "\\cell":
9360 var data = rowtf.slice(last_index, rtfre.lastIndex - res[0].length);
9361 if(data[0] == " ") data = data.slice(1);
9362 ++C;
9363 if(data.length) {
9364 // TODO: value parsing, including codepage adjustments
9365 var cell = {v: data, t:"s"};
9366 if(Array.isArray(ws)) ws[R][C] = cell;
9367 else ws[encode_cell({r:R, c:C})] = cell;
9368 }
9369 break;
9370 }
9371 last_index = rtfre.lastIndex;
9372 }
9373 if(C > range.e.c) range.e.c = C;
9374 });
9375 ws['!ref'] = encode_range(range);
9376 return ws;
9377 }
9378
9379 function rtf_to_workbook(d/*:RawData*/, opts)/*:Workbook*/ { return sheet_to_workbook(rtf_to_sheet(d, opts), opts); }
9380
9381 /* TODO: this is a stub */
9382 function sheet_to_rtf(ws/*:Worksheet*//*::, opts*/)/*:string*/ {
9383 var o = ["{\\rtf1\\ansi"];
9384 var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
9385 var dense = Array.isArray(ws);
9386 for(var R = r.s.r; R <= r.e.r; ++R) {
9387 o.push("\\trowd\\trautofit1");
9388 for(var C = r.s.c; C <= r.e.c; ++C) o.push("\\cellx" + (C+1));
9389 o.push("\\pard\\intbl");
9390 for(C = r.s.c; C <= r.e.c; ++C) {
9391 var coord = encode_cell({r:R,c:C});
9392 cell = dense ? (ws[R]||[])[C]: ws[coord];
9393 if(!cell || cell.v == null && (!cell.f || cell.F)) continue;
9394 o.push(" " + (cell.w || (format_cell(cell), cell.w)));
9395 o.push("\\cell");
9396 }
9397 o.push("\\pard\\intbl\\row");
9398 }
9399 return o.join("") + "}";
9400 }
9401
9402 return {
9403 to_workbook: rtf_to_workbook,
9404 to_sheet: rtf_to_sheet,
9405 from_sheet: sheet_to_rtf
9406 };
9407})();
9408function hex2RGB(h) {
9409 var o = h.slice(h[0]==="#"?1:0).slice(0,6);
9410 return [parseInt(o.slice(0,2),16),parseInt(o.slice(2,4),16),parseInt(o.slice(4,6),16)];
9411}
9412function rgb2Hex(rgb) {
9413 for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);
9414 return o.toString(16).toUpperCase().slice(1);
9415}
9416
9417function rgb2HSL(rgb) {
9418 var R = rgb[0]/255, G = rgb[1]/255, B=rgb[2]/255;
9419 var M = Math.max(R, G, B), m = Math.min(R, G, B), C = M - m;
9420 if(C === 0) return [0, 0, R];
9421
9422 var H6 = 0, S = 0, L2 = (M + m);
9423 S = C / (L2 > 1 ? 2 - L2 : L2);
9424 switch(M){
9425 case R: H6 = ((G - B) / C + 6)%6; break;
9426 case G: H6 = ((B - R) / C + 2); break;
9427 case B: H6 = ((R - G) / C + 4); break;
9428 }
9429 return [H6 / 6, S, L2 / 2];
9430}
9431
9432function hsl2RGB(hsl){
9433 var H = hsl[0], S = hsl[1], L = hsl[2];
9434 var C = S * 2 * (L < 0.5 ? L : 1 - L), m = L - C/2;
9435 var rgb = [m,m,m], h6 = 6*H;
9436
9437 var X;
9438 if(S !== 0) switch(h6|0) {
9439 case 0: case 6: X = C * h6; rgb[0] += C; rgb[1] += X; break;
9440 case 1: X = C * (2 - h6); rgb[0] += X; rgb[1] += C; break;
9441 case 2: X = C * (h6 - 2); rgb[1] += C; rgb[2] += X; break;
9442 case 3: X = C * (4 - h6); rgb[1] += X; rgb[2] += C; break;
9443 case 4: X = C * (h6 - 4); rgb[2] += C; rgb[0] += X; break;
9444 case 5: X = C * (6 - h6); rgb[2] += X; rgb[0] += C; break;
9445 }
9446 for(var i = 0; i != 3; ++i) rgb[i] = Math.round(rgb[i]*255);
9447 return rgb;
9448}
9449
9450/* 18.8.3 bgColor tint algorithm */
9451function rgb_tint(hex, tint) {
9452 if(tint === 0) return hex;
9453 var hsl = rgb2HSL(hex2RGB(hex));
9454 if (tint < 0) hsl[2] = hsl[2] * (1 + tint);
9455 else hsl[2] = 1 - (1 - hsl[2]) * (1 - tint);
9456 return rgb2Hex(hsl2RGB(hsl));
9457}
9458
9459/* 18.3.1.13 width calculations */
9460/* [MS-OI29500] 2.1.595 Column Width & Formatting */
9461var DEF_MDW = 6, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
9462function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); }
9463function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; }
9464function char2width(chr) { return (Math.round((chr * MDW + 5)/MDW*256))/256; }
9465//function px2char_(px) { return (((px - 5)/MDW * 100 + 0.5))/100; }
9466//function char2width_(chr) { return (((chr * MDW + 5)/MDW*256))/256; }
9467function cycle_width(collw) { return char2width(px2char(width2px(collw))); }
9468/* XLSX/XLSB/XLS specify width in units of MDW */
9469function find_mdw_colw(collw) {
9470 var delta = Math.abs(collw - cycle_width(collw)), _MDW = MDW;
9471 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; }
9472 MDW = _MDW;
9473}
9474/* XLML specifies width in terms of pixels */
9475/*function find_mdw_wpx(wpx) {
9476 var delta = Infinity, guess = 0, _MDW = MIN_MDW;
9477 for(MDW=MIN_MDW; MDW<MAX_MDW; ++MDW) {
9478 guess = char2width_(px2char_(wpx))*256;
9479 guess = (guess) % 1;
9480 if(guess > 0.5) guess--;
9481 if(Math.abs(guess) < delta) { delta = Math.abs(guess); _MDW = MDW; }
9482 }
9483 MDW = _MDW;
9484}*/
9485
9486function process_col(coll/*:ColInfo*/) {
9487 if(coll.width) {
9488 coll.wpx = width2px(coll.width);
9489 coll.wch = px2char(coll.wpx);
9490 coll.MDW = MDW;
9491 } else if(coll.wpx) {
9492 coll.wch = px2char(coll.wpx);
9493 coll.width = char2width(coll.wch);
9494 coll.MDW = MDW;
9495 } else if(typeof coll.wch == 'number') {
9496 coll.width = char2width(coll.wch);
9497 coll.wpx = width2px(coll.width);
9498 coll.MDW = MDW;
9499 }
9500 if(coll.customWidth) delete coll.customWidth;
9501}
9502
9503var DEF_PPI = 96, PPI = DEF_PPI;
9504function px2pt(px) { return px * 96 / PPI; }
9505function pt2px(pt) { return pt * PPI / 96; }
9506
9507/* [MS-EXSPXML3] 2.4.54 ST_enmPattern */
9508var XLMLPatternTypeMap = {
9509 "None": "none",
9510 "Solid": "solid",
9511 "Gray50": "mediumGray",
9512 "Gray75": "darkGray",
9513 "Gray25": "lightGray",
9514 "HorzStripe": "darkHorizontal",
9515 "VertStripe": "darkVertical",
9516 "ReverseDiagStripe": "darkDown",
9517 "DiagStripe": "darkUp",
9518 "DiagCross": "darkGrid",
9519 "ThickDiagCross": "darkTrellis",
9520 "ThinHorzStripe": "lightHorizontal",
9521 "ThinVertStripe": "lightVertical",
9522 "ThinReverseDiagStripe": "lightDown",
9523 "ThinHorzCross": "lightGrid"
9524};
9525
9526/* 18.8.5 borders CT_Borders */
9527function parse_borders(t, styles, themes, opts) {
9528 styles.Borders = [];
9529 var border = {};
9530 var pass = false;
9531 (t[0].match(tagregex)||[]).forEach(function(x) {
9532 var y = parsexmltag(x);
9533 switch(strip_ns(y[0])) {
9534 case '<borders': case '<borders>': case '</borders>': break;
9535
9536 /* 18.8.4 border CT_Border */
9537 case '<border': case '<border>': case '<border/>':
9538 border = /*::(*/{}/*:: :any)*/;
9539 if(y.diagonalUp) border.diagonalUp = parsexmlbool(y.diagonalUp);
9540 if(y.diagonalDown) border.diagonalDown = parsexmlbool(y.diagonalDown);
9541 styles.Borders.push(border);
9542 break;
9543 case '</border>': break;
9544
9545 /* note: not in spec, appears to be CT_BorderPr */
9546 case '<left/>': break;
9547 case '<left': case '<left>': break;
9548 case '</left>': break;
9549
9550 /* note: not in spec, appears to be CT_BorderPr */
9551 case '<right/>': break;
9552 case '<right': case '<right>': break;
9553 case '</right>': break;
9554
9555 /* 18.8.43 top CT_BorderPr */
9556 case '<top/>': break;
9557 case '<top': case '<top>': break;
9558 case '</top>': break;
9559
9560 /* 18.8.6 bottom CT_BorderPr */
9561 case '<bottom/>': break;
9562 case '<bottom': case '<bottom>': break;
9563 case '</bottom>': break;
9564
9565 /* 18.8.13 diagonal CT_BorderPr */
9566 case '<diagonal': case '<diagonal>': case '<diagonal/>': break;
9567 case '</diagonal>': break;
9568
9569 /* 18.8.25 horizontal CT_BorderPr */
9570 case '<horizontal': case '<horizontal>': case '<horizontal/>': break;
9571 case '</horizontal>': break;
9572
9573 /* 18.8.44 vertical CT_BorderPr */
9574 case '<vertical': case '<vertical>': case '<vertical/>': break;
9575 case '</vertical>': break;
9576
9577 /* 18.8.37 start CT_BorderPr */
9578 case '<start': case '<start>': case '<start/>': break;
9579 case '</start>': break;
9580
9581 /* 18.8.16 end CT_BorderPr */
9582 case '<end': case '<end>': case '<end/>': break;
9583 case '</end>': break;
9584
9585 /* 18.8.? color CT_Color */
9586 case '<color': case '<color>':
9587 break;
9588 case '<color/>': case '</color>': break;
9589
9590 /* 18.2.10 extLst CT_ExtensionList ? */
9591 case '<extLst': case '<extLst>': case '</extLst>': break;
9592 case '<ext': pass = true; break;
9593 case '</ext>': pass = false; break;
9594 default: if(opts && opts.WTF) {
9595 if(!pass) throw new Error('unrecognized ' + y[0] + ' in borders');
9596 }
9597 }
9598 });
9599}
9600
9601/* 18.8.21 fills CT_Fills */
9602function parse_fills(t, styles, themes, opts) {
9603 styles.Fills = [];
9604 var fill = {};
9605 var pass = false;
9606 (t[0].match(tagregex)||[]).forEach(function(x) {
9607 var y = parsexmltag(x);
9608 switch(strip_ns(y[0])) {
9609 case '<fills': case '<fills>': case '</fills>': break;
9610
9611 /* 18.8.20 fill CT_Fill */
9612 case '<fill>': case '<fill': case '<fill/>':
9613 fill = {}; styles.Fills.push(fill); break;
9614 case '</fill>': break;
9615
9616 /* 18.8.24 gradientFill CT_GradientFill */
9617 case '<gradientFill>': break;
9618 case '<gradientFill':
9619 case '</gradientFill>': styles.Fills.push(fill); fill = {}; break;
9620
9621 /* 18.8.32 patternFill CT_PatternFill */
9622 case '<patternFill': case '<patternFill>':
9623 if(y.patternType) fill.patternType = y.patternType;
9624 break;
9625 case '<patternFill/>': case '</patternFill>': break;
9626
9627 /* 18.8.3 bgColor CT_Color */
9628 case '<bgColor':
9629 if(!fill.bgColor) fill.bgColor = {};
9630 if(y.indexed) fill.bgColor.indexed = parseInt(y.indexed, 10);
9631 if(y.theme) fill.bgColor.theme = parseInt(y.theme, 10);
9632 if(y.tint) fill.bgColor.tint = parseFloat(y.tint);
9633 /* Excel uses ARGB strings */
9634 if(y.rgb) fill.bgColor.rgb = y.rgb.slice(-6);
9635 break;
9636 case '<bgColor/>': case '</bgColor>': break;
9637
9638 /* 18.8.19 fgColor CT_Color */
9639 case '<fgColor':
9640 if(!fill.fgColor) fill.fgColor = {};
9641 if(y.theme) fill.fgColor.theme = parseInt(y.theme, 10);
9642 if(y.tint) fill.fgColor.tint = parseFloat(y.tint);
9643 /* Excel uses ARGB strings */
9644 if(y.rgb != null) fill.fgColor.rgb = y.rgb.slice(-6);
9645 break;
9646 case '<fgColor/>': case '</fgColor>': break;
9647
9648 /* 18.8.38 stop CT_GradientStop */
9649 case '<stop': case '<stop/>': break;
9650 case '</stop>': break;
9651
9652 /* 18.8.? color CT_Color */
9653 case '<color': case '<color/>': break;
9654 case '</color>': break;
9655
9656 /* 18.2.10 extLst CT_ExtensionList ? */
9657 case '<extLst': case '<extLst>': case '</extLst>': break;
9658 case '<ext': pass = true; break;
9659 case '</ext>': pass = false; break;
9660 default: if(opts && opts.WTF) {
9661 if(!pass) throw new Error('unrecognized ' + y[0] + ' in fills');
9662 }
9663 }
9664 });
9665}
9666
9667/* 18.8.23 fonts CT_Fonts */
9668function parse_fonts(t, styles, themes, opts) {
9669 styles.Fonts = [];
9670 var font = {};
9671 var pass = false;
9672 (t[0].match(tagregex)||[]).forEach(function(x) {
9673 var y = parsexmltag(x);
9674 switch(strip_ns(y[0])) {
9675 case '<fonts': case '<fonts>': case '</fonts>': break;
9676
9677 /* 18.8.22 font CT_Font */
9678 case '<font': case '<font>': break;
9679 case '</font>': case '<font/>':
9680 styles.Fonts.push(font);
9681 font = {};
9682 break;
9683
9684 /* 18.8.29 name CT_FontName */
9685 case '<name': if(y.val) font.name = utf8read(y.val); break;
9686 case '<name/>': case '</name>': break;
9687
9688 /* 18.8.2 b CT_BooleanProperty */
9689 case '<b': font.bold = y.val ? parsexmlbool(y.val) : 1; break;
9690 case '<b/>': font.bold = 1; break;
9691
9692 /* 18.8.26 i CT_BooleanProperty */
9693 case '<i': font.italic = y.val ? parsexmlbool(y.val) : 1; break;
9694 case '<i/>': font.italic = 1; break;
9695
9696 /* 18.4.13 u CT_UnderlineProperty */
9697 case '<u':
9698 switch(y.val) {
9699 case "none": font.underline = 0x00; break;
9700 case "single": font.underline = 0x01; break;
9701 case "double": font.underline = 0x02; break;
9702 case "singleAccounting": font.underline = 0x21; break;
9703 case "doubleAccounting": font.underline = 0x22; break;
9704 } break;
9705 case '<u/>': font.underline = 1; break;
9706
9707 /* 18.4.10 strike CT_BooleanProperty */
9708 case '<strike': font.strike = y.val ? parsexmlbool(y.val) : 1; break;
9709 case '<strike/>': font.strike = 1; break;
9710
9711 /* 18.4.2 outline CT_BooleanProperty */
9712 case '<outline': font.outline = y.val ? parsexmlbool(y.val) : 1; break;
9713 case '<outline/>': font.outline = 1; break;
9714
9715 /* 18.8.36 shadow CT_BooleanProperty */
9716 case '<shadow': font.shadow = y.val ? parsexmlbool(y.val) : 1; break;
9717 case '<shadow/>': font.shadow = 1; break;
9718
9719 /* 18.8.12 condense CT_BooleanProperty */
9720 case '<condense': font.condense = y.val ? parsexmlbool(y.val) : 1; break;
9721 case '<condense/>': font.condense = 1; break;
9722
9723 /* 18.8.17 extend CT_BooleanProperty */
9724 case '<extend': font.extend = y.val ? parsexmlbool(y.val) : 1; break;
9725 case '<extend/>': font.extend = 1; break;
9726
9727 /* 18.4.11 sz CT_FontSize */
9728 case '<sz': if(y.val) font.sz = +y.val; break;
9729 case '<sz/>': case '</sz>': break;
9730
9731 /* 18.4.14 vertAlign CT_VerticalAlignFontProperty */
9732 case '<vertAlign': if(y.val) font.vertAlign = y.val; break;
9733 case '<vertAlign/>': case '</vertAlign>': break;
9734
9735 /* 18.8.18 family CT_FontFamily */
9736 case '<family': if(y.val) font.family = parseInt(y.val,10); break;
9737 case '<family/>': case '</family>': break;
9738
9739 /* 18.8.35 scheme CT_FontScheme */
9740 case '<scheme': if(y.val) font.scheme = y.val; break;
9741 case '<scheme/>': case '</scheme>': break;
9742
9743 /* 18.4.1 charset CT_IntProperty */
9744 case '<charset':
9745 if(y.val == '1') break;
9746 y.codepage = CS2CP[parseInt(y.val, 10)];
9747 break;
9748
9749 /* 18.?.? color CT_Color */
9750 case '<color':
9751 if(!font.color) font.color = {};
9752 if(y.auto) font.color.auto = parsexmlbool(y.auto);
9753
9754 if(y.rgb) font.color.rgb = y.rgb.slice(-6);
9755 else if(y.indexed) {
9756 font.color.index = parseInt(y.indexed, 10);
9757 var icv = XLSIcv[font.color.index];
9758 if(font.color.index == 81) icv = XLSIcv[1];
9759 if(!icv) icv = XLSIcv[1]; //throw new Error(x); // note: 206 is valid
9760 font.color.rgb = icv[0].toString(16) + icv[1].toString(16) + icv[2].toString(16);
9761 } else if(y.theme) {
9762 font.color.theme = parseInt(y.theme, 10);
9763 if(y.tint) font.color.tint = parseFloat(y.tint);
9764 if(y.theme && themes.themeElements && themes.themeElements.clrScheme) {
9765 font.color.rgb = rgb_tint(themes.themeElements.clrScheme[font.color.theme].rgb, font.color.tint || 0);
9766 }
9767 }
9768
9769 break;
9770 case '<color/>': case '</color>': break;
9771
9772 /* note: sometimes mc:AlternateContent appears bare */
9773 case '<AlternateContent': pass = true; break;
9774 case '</AlternateContent>': pass = false; break;
9775
9776 /* 18.2.10 extLst CT_ExtensionList ? */
9777 case '<extLst': case '<extLst>': case '</extLst>': break;
9778 case '<ext': pass = true; break;
9779 case '</ext>': pass = false; break;
9780 default: if(opts && opts.WTF) {
9781 if(!pass) throw new Error('unrecognized ' + y[0] + ' in fonts');
9782 }
9783 }
9784 });
9785}
9786
9787/* 18.8.31 numFmts CT_NumFmts */
9788function parse_numFmts(t, styles, opts) {
9789 styles.NumberFmt = [];
9790 var k/*Array<number>*/ = (keys(SSF._table)/*:any*/);
9791 for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
9792 var m = t[0].match(tagregex);
9793 if(!m) return;
9794 for(i=0; i < m.length; ++i) {
9795 var y = parsexmltag(m[i]);
9796 switch(strip_ns(y[0])) {
9797 case '<numFmts': case '</numFmts>': case '<numFmts/>': case '<numFmts>': break;
9798 case '<numFmt': {
9799 var f=unescapexml(utf8read(y.formatCode)), j=parseInt(y.numFmtId,10);
9800 styles.NumberFmt[j] = f;
9801 if(j>0) {
9802 if(j > 0x188) {
9803 for(j = 0x188; j > 0x3c; --j) if(styles.NumberFmt[j] == null) break;
9804 styles.NumberFmt[j] = f;
9805 }
9806 SSF.load(f,j);
9807 }
9808 } break;
9809 case '</numFmt>': break;
9810 default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in numFmts');
9811 }
9812 }
9813}
9814
9815function write_numFmts(NF/*:{[n:number|string]:string}*//*::, opts*/) {
9816 var o = ["<numFmts>"];
9817 [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
9818 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])}));
9819 });
9820 if(o.length === 1) return "";
9821 o[o.length] = ("</numFmts>");
9822 o[0] = writextag('numFmts', null, { count:o.length-2 }).replace("/>", ">");
9823 return o.join("");
9824}
9825
9826/* 18.8.10 cellXfs CT_CellXfs */
9827var cellXF_uint = [ "numFmtId", "fillId", "fontId", "borderId", "xfId" ];
9828var cellXF_bool = [ "applyAlignment", "applyBorder", "applyFill", "applyFont", "applyNumberFormat", "applyProtection", "pivotButton", "quotePrefix" ];
9829function parse_cellXfs(t, styles, opts) {
9830 styles.CellXf = [];
9831 var xf;
9832 var pass = false;
9833 (t[0].match(tagregex)||[]).forEach(function(x) {
9834 var y = parsexmltag(x), i = 0;
9835 switch(strip_ns(y[0])) {
9836 case '<cellXfs': case '<cellXfs>': case '<cellXfs/>': case '</cellXfs>': break;
9837
9838 /* 18.8.45 xf CT_Xf */
9839 case '<xf': case '<xf/>':
9840 xf = y;
9841 delete xf[0];
9842 for(i = 0; i < cellXF_uint.length; ++i) if(xf[cellXF_uint[i]])
9843 xf[cellXF_uint[i]] = parseInt(xf[cellXF_uint[i]], 10);
9844 for(i = 0; i < cellXF_bool.length; ++i) if(xf[cellXF_bool[i]])
9845 xf[cellXF_bool[i]] = parsexmlbool(xf[cellXF_bool[i]]);
9846 if(styles.NumberFmt && xf.numFmtId > 0x188) {
9847 for(i = 0x188; i > 0x3c; --i) if(styles.NumberFmt[xf.numFmtId] == styles.NumberFmt[i]) { xf.numFmtId = i; break; }
9848 }
9849 styles.CellXf.push(xf); break;
9850 case '</xf>': break;
9851
9852 /* 18.8.1 alignment CT_CellAlignment */
9853 case '<alignment': case '<alignment/>':
9854 var alignment = {};
9855 if(y.vertical) alignment.vertical = y.vertical;
9856 if(y.horizontal) alignment.horizontal = y.horizontal;
9857 if(y.textRotation != null) alignment.textRotation = y.textRotation;
9858 if(y.indent) alignment.indent = y.indent;
9859 if(y.wrapText) alignment.wrapText = parsexmlbool(y.wrapText);
9860 xf.alignment = alignment;
9861 break;
9862 case '</alignment>': break;
9863
9864 /* 18.8.33 protection CT_CellProtection */
9865 case '<protection':
9866 break;
9867 case '</protection>': case '<protection/>': break;
9868
9869 /* note: sometimes mc:AlternateContent appears bare */
9870 case '<AlternateContent': pass = true; break;
9871 case '</AlternateContent>': pass = false; break;
9872
9873 /* 18.2.10 extLst CT_ExtensionList ? */
9874 case '<extLst': case '<extLst>': case '</extLst>': break;
9875 case '<ext': pass = true; break;
9876 case '</ext>': pass = false; break;
9877 default: if(opts && opts.WTF) {
9878 if(!pass) throw new Error('unrecognized ' + y[0] + ' in cellXfs');
9879 }
9880 }
9881 });
9882}
9883
9884function write_cellXfs(cellXfs)/*:string*/ {
9885 var o/*:Array<string>*/ = [];
9886 o[o.length] = (writextag('cellXfs',null));
9887 cellXfs.forEach(function(c) {
9888 o[o.length] = (writextag('xf', null, c));
9889 });
9890 o[o.length] = ("</cellXfs>");
9891 if(o.length === 2) return "";
9892 o[0] = writextag('cellXfs',null, {count:o.length-2}).replace("/>",">");
9893 return o.join("");
9894}
9895
9896/* 18.8 Styles CT_Stylesheet*/
9897var parse_sty_xml= (function make_pstyx() {
9898var numFmtRegex = /<(?:\w+:)?numFmts([^>]*)>[\S\s]*?<\/(?:\w+:)?numFmts>/;
9899var cellXfRegex = /<(?:\w+:)?cellXfs([^>]*)>[\S\s]*?<\/(?:\w+:)?cellXfs>/;
9900var fillsRegex = /<(?:\w+:)?fills([^>]*)>[\S\s]*?<\/(?:\w+:)?fills>/;
9901var fontsRegex = /<(?:\w+:)?fonts([^>]*)>[\S\s]*?<\/(?:\w+:)?fonts>/;
9902var bordersRegex = /<(?:\w+:)?borders([^>]*)>[\S\s]*?<\/(?:\w+:)?borders>/;
9903
9904return function parse_sty_xml(data, themes, opts) {
9905 var styles = {};
9906 if(!data) return styles;
9907 data = data.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
9908 /* 18.8.39 styleSheet CT_Stylesheet */
9909 var t;
9910
9911 /* 18.8.31 numFmts CT_NumFmts ? */
9912 if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts);
9913
9914 /* 18.8.23 fonts CT_Fonts ? */
9915 if((t=data.match(fontsRegex))) parse_fonts(t, styles, themes, opts);
9916
9917 /* 18.8.21 fills CT_Fills ? */
9918 if((t=data.match(fillsRegex))) parse_fills(t, styles, themes, opts);
9919
9920 /* 18.8.5 borders CT_Borders ? */
9921 if((t=data.match(bordersRegex))) parse_borders(t, styles, themes, opts);
9922
9923 /* 18.8.9 cellStyleXfs CT_CellStyleXfs ? */
9924 /* 18.8.8 cellStyles CT_CellStyles ? */
9925
9926 /* 18.8.10 cellXfs CT_CellXfs ? */
9927 if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts);
9928
9929 /* 18.8.15 dxfs CT_Dxfs ? */
9930 /* 18.8.42 tableStyles CT_TableStyles ? */
9931 /* 18.8.11 colors CT_Colors ? */
9932 /* 18.2.10 extLst CT_ExtensionList ? */
9933
9934 return styles;
9935};
9936})();
9937
9938var STYLES_XML_ROOT = writextag('styleSheet', null, {
9939 'xmlns': XMLNS.main[0],
9940 'xmlns:vt': XMLNS.vt
9941});
9942
9943RELS.STY = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
9944
9945function write_sty_xml(wb/*:Workbook*/, opts)/*:string*/ {
9946 var o = [XML_HEADER, STYLES_XML_ROOT], w;
9947 if(wb.SSF && (w = write_numFmts(wb.SSF)) != null) o[o.length] = w;
9948 o[o.length] = ('<fonts count="1"><font><sz val="12"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font></fonts>');
9949 o[o.length] = ('<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
9950 o[o.length] = ('<borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>');
9951 o[o.length] = ('<cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>');
9952 if((w = write_cellXfs(opts.cellXfs))) o[o.length] = (w);
9953 o[o.length] = ('<cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles>');
9954 o[o.length] = ('<dxfs count="0"/>');
9955 o[o.length] = ('<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleMedium4"/>');
9956
9957 if(o.length>2){ o[o.length] = ('</styleSheet>'); o[1]=o[1].replace("/>",">"); }
9958 return o.join("");
9959}
9960/* [MS-XLSB] 2.4.657 BrtFmt */
9961function parse_BrtFmt(data, length/*:number*/) {
9962 var numFmtId = data.read_shift(2);
9963 var stFmtCode = parse_XLWideString(data,length-2);
9964 return [numFmtId, stFmtCode];
9965}
9966function write_BrtFmt(i/*:number*/, f/*:string*/, o) {
9967 if(!o) o = new_buf(6 + 4 * f.length);
9968 o.write_shift(2, i);
9969 write_XLWideString(f, o);
9970 var out = (o.length > o.l) ? o.slice(0, o.l) : o;
9971 if(o.l == null) o.l = o.length;
9972 return out;
9973}
9974
9975/* [MS-XLSB] 2.4.659 BrtFont TODO */
9976function parse_BrtFont(data, length/*:number*/, opts) {
9977 var out = ({}/*:any*/);
9978
9979 out.sz = data.read_shift(2) / 20;
9980
9981 var grbit = parse_FontFlags(data, 2, opts);
9982 if(grbit.fItalic) out.italic = 1;
9983 if(grbit.fCondense) out.condense = 1;
9984 if(grbit.fExtend) out.extend = 1;
9985 if(grbit.fShadow) out.shadow = 1;
9986 if(grbit.fOutline) out.outline = 1;
9987 if(grbit.fStrikeout) out.strike = 1;
9988
9989 var bls = data.read_shift(2);
9990 if(bls === 0x02BC) out.bold = 1;
9991
9992 switch(data.read_shift(2)) {
9993 /* case 0: out.vertAlign = "baseline"; break; */
9994 case 1: out.vertAlign = "superscript"; break;
9995 case 2: out.vertAlign = "subscript"; break;
9996 }
9997
9998 var underline = data.read_shift(1);
9999 if(underline != 0) out.underline = underline;
10000
10001 var family = data.read_shift(1);
10002 if(family > 0) out.family = family;
10003
10004 var bCharSet = data.read_shift(1);
10005 if(bCharSet > 0) out.charset = bCharSet;
10006
10007 data.l++;
10008 out.color = parse_BrtColor(data, 8);
10009
10010 switch(data.read_shift(1)) {
10011 /* case 0: out.scheme = "none": break; */
10012 case 1: out.scheme = "major"; break;
10013 case 2: out.scheme = "minor"; break;
10014 }
10015
10016 out.name = parse_XLWideString(data, length - 21);
10017
10018 return out;
10019}
10020function write_BrtFont(font/*:any*/, o) {
10021 if(!o) o = new_buf(25+4*32);
10022 o.write_shift(2, font.sz * 20);
10023 write_FontFlags(font, o);
10024 o.write_shift(2, font.bold ? 0x02BC : 0x0190);
10025 var sss = 0;
10026 if(font.vertAlign == "superscript") sss = 1;
10027 else if(font.vertAlign == "subscript") sss = 2;
10028 o.write_shift(2, sss);
10029 o.write_shift(1, font.underline || 0);
10030 o.write_shift(1, font.family || 0);
10031 o.write_shift(1, font.charset || 0);
10032 o.write_shift(1, 0);
10033 write_BrtColor(font.color, o);
10034 var scheme = 0;
10035 if(font.scheme == "major") scheme = 1;
10036 if(font.scheme == "minor") scheme = 2;
10037 o.write_shift(1, scheme);
10038 write_XLWideString(font.name, o);
10039 return o.length > o.l ? o.slice(0, o.l) : o;
10040}
10041
10042/* [MS-XLSB] 2.4.650 BrtFill */
10043var XLSBFillPTNames = [
10044 "none",
10045 "solid",
10046 "mediumGray",
10047 "darkGray",
10048 "lightGray",
10049 "darkHorizontal",
10050 "darkVertical",
10051 "darkDown",
10052 "darkUp",
10053 "darkGrid",
10054 "darkTrellis",
10055 "lightHorizontal",
10056 "lightVertical",
10057 "lightDown",
10058 "lightUp",
10059 "lightGrid",
10060 "lightTrellis",
10061 "gray125",
10062 "gray0625"
10063];
10064var rev_XLSBFillPTNames/*:EvertNumType*/ = (evert(XLSBFillPTNames)/*:any*/);
10065/* TODO: gradient fill representation */
10066var parse_BrtFill = parsenoop;
10067function write_BrtFill(fill, o) {
10068 if(!o) o = new_buf(4*3 + 8*7 + 16*1);
10069 var fls/*:number*/ = rev_XLSBFillPTNames[fill.patternType];
10070 if(fls == null) fls = 0x28;
10071 o.write_shift(4, fls);
10072 var j = 0;
10073 if(fls != 0x28) {
10074 /* TODO: custom FG Color */
10075 write_BrtColor({auto:1}, o);
10076 /* TODO: custom BG Color */
10077 write_BrtColor({auto:1}, o);
10078
10079 for(; j < 12; ++j) o.write_shift(4, 0);
10080 } else {
10081 for(; j < 4; ++j) o.write_shift(4, 0);
10082
10083 for(; j < 12; ++j) o.write_shift(4, 0); /* TODO */
10084 /* iGradientType */
10085 /* xnumDegree */
10086 /* xnumFillToLeft */
10087 /* xnumFillToRight */
10088 /* xnumFillToTop */
10089 /* xnumFillToBottom */
10090 /* cNumStop */
10091 /* xfillGradientStop */
10092 }
10093 return o.length > o.l ? o.slice(0, o.l) : o;
10094}
10095
10096/* [MS-XLSB] 2.4.824 BrtXF */
10097function parse_BrtXF(data, length/*:number*/) {
10098 var tgt = data.l + length;
10099 var ixfeParent = data.read_shift(2);
10100 var ifmt = data.read_shift(2);
10101 data.l = tgt;
10102 return {ixfe:ixfeParent, numFmtId:ifmt };
10103}
10104function write_BrtXF(data, ixfeP, o) {
10105 if(!o) o = new_buf(16);
10106 o.write_shift(2, ixfeP||0);
10107 o.write_shift(2, data.numFmtId||0);
10108 o.write_shift(2, 0); /* iFont */
10109 o.write_shift(2, 0); /* iFill */
10110 o.write_shift(2, 0); /* ixBorder */
10111 o.write_shift(1, 0); /* trot */
10112 o.write_shift(1, 0); /* indent */
10113 var flow = 0;
10114 o.write_shift(1, flow); /* flags */
10115 o.write_shift(1, 0); /* flags */
10116 o.write_shift(1, 0); /* xfGrbitAtr */
10117 o.write_shift(1, 0);
10118 return o;
10119}
10120
10121/* [MS-XLSB] 2.5.4 Blxf TODO */
10122function write_Blxf(data, o) {
10123 if(!o) o = new_buf(10);
10124 o.write_shift(1, 0); /* dg */
10125 o.write_shift(1, 0);
10126 o.write_shift(4, 0); /* color */
10127 o.write_shift(4, 0); /* color */
10128 return o;
10129}
10130/* [MS-XLSB] 2.4.302 BrtBorder TODO */
10131var parse_BrtBorder = parsenoop;
10132function write_BrtBorder(border, o) {
10133 if(!o) o = new_buf(51);
10134 o.write_shift(1, 0); /* diagonal */
10135 write_Blxf(null, o); /* top */
10136 write_Blxf(null, o); /* bottom */
10137 write_Blxf(null, o); /* left */
10138 write_Blxf(null, o); /* right */
10139 write_Blxf(null, o); /* diag */
10140 return o.length > o.l ? o.slice(0, o.l) : o;
10141}
10142
10143/* [MS-XLSB] 2.4.763 BrtStyle TODO */
10144function write_BrtStyle(style, o) {
10145 if(!o) o = new_buf(12+4*10);
10146 o.write_shift(4, style.xfId);
10147 o.write_shift(2, 1);
10148 o.write_shift(1, +style.builtinId);
10149 o.write_shift(1, 0); /* iLevel */
10150 write_XLNullableWideString(style.name || "", o);
10151 return o.length > o.l ? o.slice(0, o.l) : o;
10152}
10153
10154/* [MS-XLSB] 2.4.272 BrtBeginTableStyles */
10155function write_BrtBeginTableStyles(cnt, defTableStyle, defPivotStyle) {
10156 var o = new_buf(4+256*2*4);
10157 o.write_shift(4, cnt);
10158 write_XLNullableWideString(defTableStyle, o);
10159 write_XLNullableWideString(defPivotStyle, o);
10160 return o.length > o.l ? o.slice(0, o.l) : o;
10161}
10162
10163/* [MS-XLSB] 2.1.7.50 Styles */
10164function parse_sty_bin(data, themes, opts) {
10165 var styles = {};
10166 styles.NumberFmt = ([]/*:any*/);
10167 for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y];
10168
10169 styles.CellXf = [];
10170 styles.Fonts = [];
10171 var state/*:Array<string>*/ = [];
10172 var pass = false;
10173 recordhopper(data, function hopper_sty(val, R_n, RT) {
10174 switch(RT) {
10175 case 0x002C: /* 'BrtFmt' */
10176 styles.NumberFmt[val[0]] = val[1]; SSF.load(val[1], val[0]);
10177 break;
10178 case 0x002B: /* 'BrtFont' */
10179 styles.Fonts.push(val);
10180 if(val.color.theme != null && themes && themes.themeElements && themes.themeElements.clrScheme) {
10181 val.color.rgb = rgb_tint(themes.themeElements.clrScheme[val.color.theme].rgb, val.color.tint || 0);
10182 }
10183 break;
10184 case 0x0401: /* 'BrtKnownFonts' */ break;
10185 case 0x002D: /* 'BrtFill' */
10186 break;
10187 case 0x002E: /* 'BrtBorder' */
10188 break;
10189 case 0x002F: /* 'BrtXF' */
10190 if(state[state.length - 1] == "BrtBeginCellXFs") {
10191 styles.CellXf.push(val);
10192 }
10193 break;
10194 case 0x0030: /* 'BrtStyle' */
10195 case 0x01FB: /* 'BrtDXF' */
10196 case 0x023C: /* 'BrtMRUColor' */
10197 case 0x01DB: /* 'BrtIndexedColor': */
10198 break;
10199
10200 case 0x0493: /* 'BrtDXF14' */
10201 case 0x0836: /* 'BrtDXF15' */
10202 case 0x046A: /* 'BrtSlicerStyleElement' */
10203 case 0x0200: /* 'BrtTableStyleElement' */
10204 case 0x082F: /* 'BrtTimelineStyleElement' */
10205 case 0x0C00: /* 'BrtUid' */
10206 break;
10207
10208 case 0x0023: /* 'BrtFRTBegin' */
10209 pass = true; break;
10210 case 0x0024: /* 'BrtFRTEnd' */
10211 pass = false; break;
10212 case 0x0025: /* 'BrtACBegin' */
10213 state.push(R_n); pass = true; break;
10214 case 0x0026: /* 'BrtACEnd' */
10215 state.pop(); pass = false; break;
10216
10217 default:
10218 if((R_n||"").indexOf("Begin") > 0) state.push(R_n);
10219 else if((R_n||"").indexOf("End") > 0) state.pop();
10220 else if(!pass || (opts.WTF && state[state.length-1] != "BrtACBegin")) throw new Error("Unexpected record " + RT + " " + R_n);
10221 }
10222 });
10223 return styles;
10224}
10225
10226function write_FMTS_bin(ba, NF/*:?SSFTable*/) {
10227 if(!NF) return;
10228 var cnt = 0;
10229 [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
10230 /*:: if(!NF) return; */
10231 for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) ++cnt;
10232 });
10233
10234 if(cnt == 0) return;
10235 write_record(ba, "BrtBeginFmts", write_UInt32LE(cnt));
10236 [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
10237 /*:: if(!NF) return; */
10238 for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_record(ba, "BrtFmt", write_BrtFmt(i, NF[i]));
10239 });
10240 write_record(ba, "BrtEndFmts");
10241}
10242
10243function write_FONTS_bin(ba/*::, data*/) {
10244 var cnt = 1;
10245
10246 if(cnt == 0) return;
10247 write_record(ba, "BrtBeginFonts", write_UInt32LE(cnt));
10248 write_record(ba, "BrtFont", write_BrtFont({
10249 sz:12,
10250 color: {theme:1},
10251 name: "Calibri",
10252 family: 2,
10253 scheme: "minor"
10254 }));
10255 /* 1*65491BrtFont [ACFONTS] */
10256 write_record(ba, "BrtEndFonts");
10257}
10258
10259function write_FILLS_bin(ba/*::, data*/) {
10260 var cnt = 2;
10261
10262 if(cnt == 0) return;
10263 write_record(ba, "BrtBeginFills", write_UInt32LE(cnt));
10264 write_record(ba, "BrtFill", write_BrtFill({patternType:"none"}));
10265 write_record(ba, "BrtFill", write_BrtFill({patternType:"gray125"}));
10266 /* 1*65431BrtFill */
10267 write_record(ba, "BrtEndFills");
10268}
10269
10270function write_BORDERS_bin(ba/*::, data*/) {
10271 var cnt = 1;
10272
10273 if(cnt == 0) return;
10274 write_record(ba, "BrtBeginBorders", write_UInt32LE(cnt));
10275 write_record(ba, "BrtBorder", write_BrtBorder({}));
10276 /* 1*65430BrtBorder */
10277 write_record(ba, "BrtEndBorders");
10278}
10279
10280function write_CELLSTYLEXFS_bin(ba/*::, data*/) {
10281 var cnt = 1;
10282 write_record(ba, "BrtBeginCellStyleXFs", write_UInt32LE(cnt));
10283 write_record(ba, "BrtXF", write_BrtXF({
10284 numFmtId: 0,
10285 fontId: 0,
10286 fillId: 0,
10287 borderId: 0
10288 }, 0xFFFF));
10289 /* 1*65430(BrtXF *FRT) */
10290 write_record(ba, "BrtEndCellStyleXFs");
10291}
10292
10293function write_CELLXFS_bin(ba, data) {
10294 write_record(ba, "BrtBeginCellXFs", write_UInt32LE(data.length));
10295 data.forEach(function(c) { write_record(ba, "BrtXF", write_BrtXF(c,0)); });
10296 /* 1*65430(BrtXF *FRT) */
10297 write_record(ba, "BrtEndCellXFs");
10298}
10299
10300function write_STYLES_bin(ba/*::, data*/) {
10301 var cnt = 1;
10302
10303 write_record(ba, "BrtBeginStyles", write_UInt32LE(cnt));
10304 write_record(ba, "BrtStyle", write_BrtStyle({
10305 xfId:0,
10306 builtinId:0,
10307 name:"Normal"
10308 }));
10309 /* 1*65430(BrtStyle *FRT) */
10310 write_record(ba, "BrtEndStyles");
10311}
10312
10313function write_DXFS_bin(ba/*::, data*/) {
10314 var cnt = 0;
10315
10316 write_record(ba, "BrtBeginDXFs", write_UInt32LE(cnt));
10317 /* *2147483647(BrtDXF *FRT) */
10318 write_record(ba, "BrtEndDXFs");
10319}
10320
10321function write_TABLESTYLES_bin(ba/*::, data*/) {
10322 var cnt = 0;
10323
10324 write_record(ba, "BrtBeginTableStyles", write_BrtBeginTableStyles(cnt, "TableStyleMedium9", "PivotStyleMedium4"));
10325 /* *TABLESTYLE */
10326 write_record(ba, "BrtEndTableStyles");
10327}
10328
10329function write_COLORPALETTE_bin(/*::ba, data*/) {
10330 return;
10331 /* BrtBeginColorPalette [INDEXEDCOLORS] [MRUCOLORS] BrtEndColorPalette */
10332}
10333
10334/* [MS-XLSB] 2.1.7.50 Styles */
10335function write_sty_bin(wb, opts) {
10336 var ba = buf_array();
10337 write_record(ba, "BrtBeginStyleSheet");
10338 write_FMTS_bin(ba, wb.SSF);
10339 write_FONTS_bin(ba, wb);
10340 write_FILLS_bin(ba, wb);
10341 write_BORDERS_bin(ba, wb);
10342 write_CELLSTYLEXFS_bin(ba, wb);
10343 write_CELLXFS_bin(ba, opts.cellXfs);
10344 write_STYLES_bin(ba, wb);
10345 write_DXFS_bin(ba, wb);
10346 write_TABLESTYLES_bin(ba, wb);
10347 write_COLORPALETTE_bin(ba, wb);
10348 /* FRTSTYLESHEET*/
10349 write_record(ba, "BrtEndStyleSheet");
10350 return ba.end();
10351}
10352RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
10353
10354/* Even though theme layout is dk1 lt1 dk2 lt2, true order is lt1 dk1 lt2 dk2 */
10355var XLSXThemeClrScheme = [
10356 '</a:lt1>', '</a:dk1>', '</a:lt2>', '</a:dk2>',
10357 '</a:accent1>', '</a:accent2>', '</a:accent3>',
10358 '</a:accent4>', '</a:accent5>', '</a:accent6>',
10359 '</a:hlink>', '</a:folHlink>'
10360];
10361/* 20.1.6.2 clrScheme CT_ColorScheme */
10362function parse_clrScheme(t, themes, opts) {
10363 themes.themeElements.clrScheme = [];
10364 var color = {};
10365 (t[0].match(tagregex)||[]).forEach(function(x) {
10366 var y = parsexmltag(x);
10367 switch(y[0]) {
10368 /* 20.1.6.2 clrScheme (Color Scheme) CT_ColorScheme */
10369 case '<a:clrScheme': case '</a:clrScheme>': break;
10370
10371 /* 20.1.2.3.32 srgbClr CT_SRgbColor */
10372 case '<a:srgbClr':
10373 color.rgb = y.val; break;
10374
10375 /* 20.1.2.3.33 sysClr CT_SystemColor */
10376 case '<a:sysClr':
10377 color.rgb = y.lastClr; break;
10378
10379 /* 20.1.4.1.1 accent1 (Accent 1) */
10380 /* 20.1.4.1.2 accent2 (Accent 2) */
10381 /* 20.1.4.1.3 accent3 (Accent 3) */
10382 /* 20.1.4.1.4 accent4 (Accent 4) */
10383 /* 20.1.4.1.5 accent5 (Accent 5) */
10384 /* 20.1.4.1.6 accent6 (Accent 6) */
10385 /* 20.1.4.1.9 dk1 (Dark 1) */
10386 /* 20.1.4.1.10 dk2 (Dark 2) */
10387 /* 20.1.4.1.15 folHlink (Followed Hyperlink) */
10388 /* 20.1.4.1.19 hlink (Hyperlink) */
10389 /* 20.1.4.1.22 lt1 (Light 1) */
10390 /* 20.1.4.1.23 lt2 (Light 2) */
10391 case '<a:dk1>': case '</a:dk1>':
10392 case '<a:lt1>': case '</a:lt1>':
10393 case '<a:dk2>': case '</a:dk2>':
10394 case '<a:lt2>': case '</a:lt2>':
10395 case '<a:accent1>': case '</a:accent1>':
10396 case '<a:accent2>': case '</a:accent2>':
10397 case '<a:accent3>': case '</a:accent3>':
10398 case '<a:accent4>': case '</a:accent4>':
10399 case '<a:accent5>': case '</a:accent5>':
10400 case '<a:accent6>': case '</a:accent6>':
10401 case '<a:hlink>': case '</a:hlink>':
10402 case '<a:folHlink>': case '</a:folHlink>':
10403 if (y[0].charAt(1) === '/') {
10404 themes.themeElements.clrScheme[XLSXThemeClrScheme.indexOf(y[0])] = color;
10405 color = {};
10406 } else {
10407 color.name = y[0].slice(3, y[0].length - 1);
10408 }
10409 break;
10410
10411 default: if(opts && opts.WTF) throw new Error('Unrecognized ' + y[0] + ' in clrScheme');
10412 }
10413 });
10414}
10415
10416/* 20.1.4.1.18 fontScheme CT_FontScheme */
10417function parse_fontScheme(/*::t, themes, opts*/) { }
10418
10419/* 20.1.4.1.15 fmtScheme CT_StyleMatrix */
10420function parse_fmtScheme(/*::t, themes, opts*/) { }
10421
10422var clrsregex = /<a:clrScheme([^>]*)>[\s\S]*<\/a:clrScheme>/;
10423var fntsregex = /<a:fontScheme([^>]*)>[\s\S]*<\/a:fontScheme>/;
10424var fmtsregex = /<a:fmtScheme([^>]*)>[\s\S]*<\/a:fmtScheme>/;
10425
10426/* 20.1.6.10 themeElements CT_BaseStyles */
10427function parse_themeElements(data, themes, opts) {
10428 themes.themeElements = {};
10429
10430 var t;
10431
10432 [
10433 /* clrScheme CT_ColorScheme */
10434 ['clrScheme', clrsregex, parse_clrScheme],
10435 /* fontScheme CT_FontScheme */
10436 ['fontScheme', fntsregex, parse_fontScheme],
10437 /* fmtScheme CT_StyleMatrix */
10438 ['fmtScheme', fmtsregex, parse_fmtScheme]
10439 ].forEach(function(m) {
10440 if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements');
10441 m[2](t, themes, opts);
10442 });
10443}
10444
10445var themeltregex = /<a:themeElements([^>]*)>[\s\S]*<\/a:themeElements>/;
10446
10447/* 14.2.7 Theme Part */
10448function parse_theme_xml(data/*:string*/, opts) {
10449 /* 20.1.6.9 theme CT_OfficeStyleSheet */
10450 if(!data || data.length === 0) return parse_theme_xml(write_theme());
10451
10452 var t;
10453 var themes = {};
10454
10455 /* themeElements CT_BaseStyles */
10456 if(!(t=data.match(themeltregex))) throw new Error('themeElements not found in theme');
10457 parse_themeElements(t[0], themes, opts);
10458 themes.raw = data;
10459 return themes;
10460}
10461
10462function write_theme(Themes, opts)/*:string*/ {
10463 if(opts && opts.themeXLSX) return opts.themeXLSX;
10464 if(Themes && typeof Themes.raw == "string") return Themes.raw;
10465 var o = [XML_HEADER];
10466 o[o.length] = '<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">';
10467 o[o.length] = '<a:themeElements>';
10468
10469 o[o.length] = '<a:clrScheme name="Office">';
10470 o[o.length] = '<a:dk1><a:sysClr val="windowText" lastClr="000000"/></a:dk1>';
10471 o[o.length] = '<a:lt1><a:sysClr val="window" lastClr="FFFFFF"/></a:lt1>';
10472 o[o.length] = '<a:dk2><a:srgbClr val="1F497D"/></a:dk2>';
10473 o[o.length] = '<a:lt2><a:srgbClr val="EEECE1"/></a:lt2>';
10474 o[o.length] = '<a:accent1><a:srgbClr val="4F81BD"/></a:accent1>';
10475 o[o.length] = '<a:accent2><a:srgbClr val="C0504D"/></a:accent2>';
10476 o[o.length] = '<a:accent3><a:srgbClr val="9BBB59"/></a:accent3>';
10477 o[o.length] = '<a:accent4><a:srgbClr val="8064A2"/></a:accent4>';
10478 o[o.length] = '<a:accent5><a:srgbClr val="4BACC6"/></a:accent5>';
10479 o[o.length] = '<a:accent6><a:srgbClr val="F79646"/></a:accent6>';
10480 o[o.length] = '<a:hlink><a:srgbClr val="0000FF"/></a:hlink>';
10481 o[o.length] = '<a:folHlink><a:srgbClr val="800080"/></a:folHlink>';
10482 o[o.length] = '</a:clrScheme>';
10483
10484 o[o.length] = '<a:fontScheme name="Office">';
10485 o[o.length] = '<a:majorFont>';
10486 o[o.length] = '<a:latin typeface="Cambria"/>';
10487 o[o.length] = '<a:ea typeface=""/>';
10488 o[o.length] = '<a:cs typeface=""/>';
10489 o[o.length] = '<a:font script="Jpan" typeface="MS Pゴシック"/>';
10490 o[o.length] = '<a:font script="Hang" typeface="맑은 고딕"/>';
10491 o[o.length] = '<a:font script="Hans" typeface="宋体"/>';
10492 o[o.length] = '<a:font script="Hant" typeface="新細明體"/>';
10493 o[o.length] = '<a:font script="Arab" typeface="Times New Roman"/>';
10494 o[o.length] = '<a:font script="Hebr" typeface="Times New Roman"/>';
10495 o[o.length] = '<a:font script="Thai" typeface="Tahoma"/>';
10496 o[o.length] = '<a:font script="Ethi" typeface="Nyala"/>';
10497 o[o.length] = '<a:font script="Beng" typeface="Vrinda"/>';
10498 o[o.length] = '<a:font script="Gujr" typeface="Shruti"/>';
10499 o[o.length] = '<a:font script="Khmr" typeface="MoolBoran"/>';
10500 o[o.length] = '<a:font script="Knda" typeface="Tunga"/>';
10501 o[o.length] = '<a:font script="Guru" typeface="Raavi"/>';
10502 o[o.length] = '<a:font script="Cans" typeface="Euphemia"/>';
10503 o[o.length] = '<a:font script="Cher" typeface="Plantagenet Cherokee"/>';
10504 o[o.length] = '<a:font script="Yiii" typeface="Microsoft Yi Baiti"/>';
10505 o[o.length] = '<a:font script="Tibt" typeface="Microsoft Himalaya"/>';
10506 o[o.length] = '<a:font script="Thaa" typeface="MV Boli"/>';
10507 o[o.length] = '<a:font script="Deva" typeface="Mangal"/>';
10508 o[o.length] = '<a:font script="Telu" typeface="Gautami"/>';
10509 o[o.length] = '<a:font script="Taml" typeface="Latha"/>';
10510 o[o.length] = '<a:font script="Syrc" typeface="Estrangelo Edessa"/>';
10511 o[o.length] = '<a:font script="Orya" typeface="Kalinga"/>';
10512 o[o.length] = '<a:font script="Mlym" typeface="Kartika"/>';
10513 o[o.length] = '<a:font script="Laoo" typeface="DokChampa"/>';
10514 o[o.length] = '<a:font script="Sinh" typeface="Iskoola Pota"/>';
10515 o[o.length] = '<a:font script="Mong" typeface="Mongolian Baiti"/>';
10516 o[o.length] = '<a:font script="Viet" typeface="Times New Roman"/>';
10517 o[o.length] = '<a:font script="Uigh" typeface="Microsoft Uighur"/>';
10518 o[o.length] = '<a:font script="Geor" typeface="Sylfaen"/>';
10519 o[o.length] = '</a:majorFont>';
10520 o[o.length] = '<a:minorFont>';
10521 o[o.length] = '<a:latin typeface="Calibri"/>';
10522 o[o.length] = '<a:ea typeface=""/>';
10523 o[o.length] = '<a:cs typeface=""/>';
10524 o[o.length] = '<a:font script="Jpan" typeface="MS Pゴシック"/>';
10525 o[o.length] = '<a:font script="Hang" typeface="맑은 고딕"/>';
10526 o[o.length] = '<a:font script="Hans" typeface="宋体"/>';
10527 o[o.length] = '<a:font script="Hant" typeface="新細明體"/>';
10528 o[o.length] = '<a:font script="Arab" typeface="Arial"/>';
10529 o[o.length] = '<a:font script="Hebr" typeface="Arial"/>';
10530 o[o.length] = '<a:font script="Thai" typeface="Tahoma"/>';
10531 o[o.length] = '<a:font script="Ethi" typeface="Nyala"/>';
10532 o[o.length] = '<a:font script="Beng" typeface="Vrinda"/>';
10533 o[o.length] = '<a:font script="Gujr" typeface="Shruti"/>';
10534 o[o.length] = '<a:font script="Khmr" typeface="DaunPenh"/>';
10535 o[o.length] = '<a:font script="Knda" typeface="Tunga"/>';
10536 o[o.length] = '<a:font script="Guru" typeface="Raavi"/>';
10537 o[o.length] = '<a:font script="Cans" typeface="Euphemia"/>';
10538 o[o.length] = '<a:font script="Cher" typeface="Plantagenet Cherokee"/>';
10539 o[o.length] = '<a:font script="Yiii" typeface="Microsoft Yi Baiti"/>';
10540 o[o.length] = '<a:font script="Tibt" typeface="Microsoft Himalaya"/>';
10541 o[o.length] = '<a:font script="Thaa" typeface="MV Boli"/>';
10542 o[o.length] = '<a:font script="Deva" typeface="Mangal"/>';
10543 o[o.length] = '<a:font script="Telu" typeface="Gautami"/>';
10544 o[o.length] = '<a:font script="Taml" typeface="Latha"/>';
10545 o[o.length] = '<a:font script="Syrc" typeface="Estrangelo Edessa"/>';
10546 o[o.length] = '<a:font script="Orya" typeface="Kalinga"/>';
10547 o[o.length] = '<a:font script="Mlym" typeface="Kartika"/>';
10548 o[o.length] = '<a:font script="Laoo" typeface="DokChampa"/>';
10549 o[o.length] = '<a:font script="Sinh" typeface="Iskoola Pota"/>';
10550 o[o.length] = '<a:font script="Mong" typeface="Mongolian Baiti"/>';
10551 o[o.length] = '<a:font script="Viet" typeface="Arial"/>';
10552 o[o.length] = '<a:font script="Uigh" typeface="Microsoft Uighur"/>';
10553 o[o.length] = '<a:font script="Geor" typeface="Sylfaen"/>';
10554 o[o.length] = '</a:minorFont>';
10555 o[o.length] = '</a:fontScheme>';
10556
10557 o[o.length] = '<a:fmtScheme name="Office">';
10558 o[o.length] = '<a:fillStyleLst>';
10559 o[o.length] = '<a:solidFill><a:schemeClr val="phClr"/></a:solidFill>';
10560 o[o.length] = '<a:gradFill rotWithShape="1">';
10561 o[o.length] = '<a:gsLst>';
10562 o[o.length] = '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="50000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
10563 o[o.length] = '<a:gs pos="35000"><a:schemeClr val="phClr"><a:tint val="37000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
10564 o[o.length] = '<a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="15000"/><a:satMod val="350000"/></a:schemeClr></a:gs>';
10565 o[o.length] = '</a:gsLst>';
10566 o[o.length] = '<a:lin ang="16200000" scaled="1"/>';
10567 o[o.length] = '</a:gradFill>';
10568 o[o.length] = '<a:gradFill rotWithShape="1">';
10569 o[o.length] = '<a:gsLst>';
10570 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>';
10571 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>';
10572 o[o.length] = '</a:gsLst>';
10573 o[o.length] = '<a:lin ang="16200000" scaled="0"/>';
10574 o[o.length] = '</a:gradFill>';
10575 o[o.length] = '</a:fillStyleLst>';
10576 o[o.length] = '<a:lnStyleLst>';
10577 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>';
10578 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>';
10579 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>';
10580 o[o.length] = '</a:lnStyleLst>';
10581 o[o.length] = '<a:effectStyleLst>';
10582 o[o.length] = '<a:effectStyle>';
10583 o[o.length] = '<a:effectLst>';
10584 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>';
10585 o[o.length] = '</a:effectLst>';
10586 o[o.length] = '</a:effectStyle>';
10587 o[o.length] = '<a:effectStyle>';
10588 o[o.length] = '<a:effectLst>';
10589 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>';
10590 o[o.length] = '</a:effectLst>';
10591 o[o.length] = '</a:effectStyle>';
10592 o[o.length] = '<a:effectStyle>';
10593 o[o.length] = '<a:effectLst>';
10594 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>';
10595 o[o.length] = '</a:effectLst>';
10596 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>';
10597 o[o.length] = '<a:sp3d><a:bevelT w="63500" h="25400"/></a:sp3d>';
10598 o[o.length] = '</a:effectStyle>';
10599 o[o.length] = '</a:effectStyleLst>';
10600 o[o.length] = '<a:bgFillStyleLst>';
10601 o[o.length] = '<a:solidFill><a:schemeClr val="phClr"/></a:solidFill>';
10602 o[o.length] = '<a:gradFill rotWithShape="1">';
10603 o[o.length] = '<a:gsLst>';
10604 o[o.length] = '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="40000"/><a:satMod val="350000"/></a:schemeClr></a:gs>';
10605 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>';
10606 o[o.length] = '<a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="20000"/><a:satMod val="255000"/></a:schemeClr></a:gs>';
10607 o[o.length] = '</a:gsLst>';
10608 o[o.length] = '<a:path path="circle"><a:fillToRect l="50000" t="-80000" r="50000" b="180000"/></a:path>';
10609 o[o.length] = '</a:gradFill>';
10610 o[o.length] = '<a:gradFill rotWithShape="1">';
10611 o[o.length] = '<a:gsLst>';
10612 o[o.length] = '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="80000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
10613 o[o.length] = '<a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="30000"/><a:satMod val="200000"/></a:schemeClr></a:gs>';
10614 o[o.length] = '</a:gsLst>';
10615 o[o.length] = '<a:path path="circle"><a:fillToRect l="50000" t="50000" r="50000" b="50000"/></a:path>';
10616 o[o.length] = '</a:gradFill>';
10617 o[o.length] = '</a:bgFillStyleLst>';
10618 o[o.length] = '</a:fmtScheme>';
10619 o[o.length] = '</a:themeElements>';
10620
10621 o[o.length] = '<a:objectDefaults>';
10622 o[o.length] = '<a:spDef>';
10623 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>';
10624 o[o.length] = '</a:spDef>';
10625 o[o.length] = '<a:lnDef>';
10626 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>';
10627 o[o.length] = '</a:lnDef>';
10628 o[o.length] = '</a:objectDefaults>';
10629 o[o.length] = '<a:extraClrSchemeLst/>';
10630 o[o.length] = '</a:theme>';
10631 return o.join("");
10632}
10633/* [MS-XLS] 2.4.326 TODO: payload is a zip file */
10634function parse_Theme(blob, length, opts) {
10635 var end = blob.l + length;
10636 var dwThemeVersion = blob.read_shift(4);
10637 if(dwThemeVersion === 124226) return;
10638 if(!opts.cellStyles) { blob.l = end; return; }
10639 var data = blob.slice(blob.l);
10640 blob.l = end;
10641 var zip; try { zip = zip_read(data, {type: "array"}); } catch(e) { return; }
10642 var themeXML = getzipstr(zip, "theme/theme/theme1.xml", true);
10643 if(!themeXML) return;
10644 return parse_theme_xml(themeXML, opts);
10645}
10646
10647/* 2.5.49 */
10648function parse_ColorTheme(blob/*::, length*/) { return blob.read_shift(4); }
10649
10650/* 2.5.155 */
10651function parse_FullColorExt(blob/*::, length*/) {
10652 var o = {};
10653 o.xclrType = blob.read_shift(2);
10654 o.nTintShade = blob.read_shift(2);
10655 switch(o.xclrType) {
10656 case 0: blob.l += 4; break;
10657 case 1: o.xclrValue = parse_IcvXF(blob, 4); break;
10658 case 2: o.xclrValue = parse_LongRGBA(blob, 4); break;
10659 case 3: o.xclrValue = parse_ColorTheme(blob, 4); break;
10660 case 4: blob.l += 4; break;
10661 }
10662 blob.l += 8;
10663 return o;
10664}
10665
10666/* 2.5.164 TODO: read 7 bits*/
10667function parse_IcvXF(blob, length) {
10668 return parsenoop(blob, length);
10669}
10670
10671/* 2.5.280 */
10672function parse_XFExtGradient(blob, length) {
10673 return parsenoop(blob, length);
10674}
10675
10676/* [MS-XLS] 2.5.108 */
10677function parse_ExtProp(blob/*::, length*/)/*:Array<any>*/ {
10678 var extType = blob.read_shift(2);
10679 var cb = blob.read_shift(2) - 4;
10680 var o = [extType];
10681 switch(extType) {
10682 case 0x04: case 0x05: case 0x07: case 0x08:
10683 case 0x09: case 0x0A: case 0x0B: case 0x0D:
10684 o[1] = parse_FullColorExt(blob, cb); break;
10685 case 0x06: o[1] = parse_XFExtGradient(blob, cb); break;
10686 case 0x0E: case 0x0F: o[1] = blob.read_shift(cb === 1 ? 1 : 2); break;
10687 default: throw new Error("Unrecognized ExtProp type: " + extType + " " + cb);
10688 }
10689 return o;
10690}
10691
10692/* 2.4.355 */
10693function parse_XFExt(blob, length) {
10694 var end = blob.l + length;
10695 blob.l += 2;
10696 var ixfe = blob.read_shift(2);
10697 blob.l += 2;
10698 var cexts = blob.read_shift(2);
10699 var ext/*:AOA*/ = [];
10700 while(cexts-- > 0) ext.push(parse_ExtProp(blob, end-blob.l));
10701 return {ixfe:ixfe, ext:ext};
10702}
10703
10704/* xf is an XF, see parse_XFExt for xfext */
10705function update_xfext(xf, xfext) {
10706 xfext.forEach(function(xfe) {
10707 switch(xfe[0]) { /* 2.5.108 extPropData */
10708 case 0x04: break; /* foreground color */
10709 case 0x05: break; /* background color */
10710 case 0x06: break; /* gradient fill */
10711 case 0x07: break; /* top cell border color */
10712 case 0x08: break; /* bottom cell border color */
10713 case 0x09: break; /* left cell border color */
10714 case 0x0a: break; /* right cell border color */
10715 case 0x0b: break; /* diagonal cell border color */
10716 case 0x0d: /* text color */
10717 break;
10718 case 0x0e: break; /* font scheme */
10719 case 0x0f: break; /* indentation level */
10720 }
10721 });
10722}
10723
10724/* 18.6 Calculation Chain */
10725function parse_cc_xml(data/*::, name, opts*/)/*:Array<any>*/ {
10726 var d = [];
10727 if(!data) return d;
10728 var i = 1;
10729 (data.match(tagregex)||[]).forEach(function(x) {
10730 var y = parsexmltag(x);
10731 switch(y[0]) {
10732 case '<?xml': break;
10733 /* 18.6.2 calcChain CT_CalcChain 1 */
10734 case '<calcChain': case '<calcChain>': case '</calcChain>': break;
10735 /* 18.6.1 c CT_CalcCell 1 */
10736 case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break;
10737 }
10738 });
10739 return d;
10740}
10741
10742//function write_cc_xml(data, opts) { }
10743
10744/* [MS-XLSB] 2.6.4.1 */
10745function parse_BrtCalcChainItem$(data) {
10746 var out = {};
10747 out.i = data.read_shift(4);
10748 var cell = {};
10749 cell.r = data.read_shift(4);
10750 cell.c = data.read_shift(4);
10751 out.r = encode_cell(cell);
10752 var flags = data.read_shift(1);
10753 if(flags & 0x2) out.l = '1';
10754 if(flags & 0x8) out.a = '1';
10755 return out;
10756}
10757
10758/* 18.6 Calculation Chain */
10759function parse_cc_bin(data, name, opts) {
10760 var out = [];
10761 var pass = false;
10762 recordhopper(data, function hopper_cc(val, R_n, RT) {
10763 switch(RT) {
10764 case 0x003F: /* 'BrtCalcChainItem$' */
10765 out.push(val); break;
10766
10767 default:
10768 if((R_n||"").indexOf("Begin") > 0){/* empty */}
10769 else if((R_n||"").indexOf("End") > 0){/* empty */}
10770 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
10771 }
10772 });
10773 return out;
10774}
10775
10776//function write_cc_bin(data, opts) { }
10777/* 18.14 Supplementary Workbook Data */
10778function parse_xlink_xml(/*::data, rel, name:string, _opts*/) {
10779 //var opts = _opts || {};
10780 //if(opts.WTF) throw "XLSX External Link";
10781}
10782
10783/* [MS-XLSB] 2.1.7.25 External Link */
10784function parse_xlink_bin(data, rel, name/*:string*/, _opts) {
10785 if(!data) return data;
10786 var opts = _opts || {};
10787
10788 var pass = false, end = false;
10789
10790 recordhopper(data, function xlink_parse(val, R_n, RT) {
10791 if(end) return;
10792 switch(RT) {
10793 case 0x0167: /* 'BrtSupTabs' */
10794 case 0x016B: /* 'BrtExternTableStart' */
10795 case 0x016C: /* 'BrtExternTableEnd' */
10796 case 0x016E: /* 'BrtExternRowHdr' */
10797 case 0x016F: /* 'BrtExternCellBlank' */
10798 case 0x0170: /* 'BrtExternCellReal' */
10799 case 0x0171: /* 'BrtExternCellBool' */
10800 case 0x0172: /* 'BrtExternCellError' */
10801 case 0x0173: /* 'BrtExternCellString' */
10802 case 0x01D8: /* 'BrtExternValueMeta' */
10803 case 0x0241: /* 'BrtSupNameStart' */
10804 case 0x0242: /* 'BrtSupNameValueStart' */
10805 case 0x0243: /* 'BrtSupNameValueEnd' */
10806 case 0x0244: /* 'BrtSupNameNum' */
10807 case 0x0245: /* 'BrtSupNameErr' */
10808 case 0x0246: /* 'BrtSupNameSt' */
10809 case 0x0247: /* 'BrtSupNameNil' */
10810 case 0x0248: /* 'BrtSupNameBool' */
10811 case 0x0249: /* 'BrtSupNameFmla' */
10812 case 0x024A: /* 'BrtSupNameBits' */
10813 case 0x024B: /* 'BrtSupNameEnd' */
10814 break;
10815
10816 case 0x0023: /* 'BrtFRTBegin' */
10817 pass = true; break;
10818 case 0x0024: /* 'BrtFRTEnd' */
10819 pass = false; break;
10820
10821 default:
10822 if((R_n||"").indexOf("Begin") > 0){/* empty */}
10823 else if((R_n||"").indexOf("End") > 0){/* empty */}
10824 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT.toString(16) + " " + R_n);
10825 }
10826 }, opts);
10827}
10828/* 20.5 DrawingML - SpreadsheetML Drawing */
10829RELS.IMG = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
10830RELS.DRAW = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing";
10831
10832/* 20.5.2.35 wsDr CT_Drawing */
10833function parse_drawing(data, rels/*:any*/) {
10834 if(!data) return "??";
10835 /*
10836 Chartsheet Drawing:
10837 - 20.5.2.35 wsDr CT_Drawing
10838 - 20.5.2.1 absoluteAnchor CT_AbsoluteAnchor
10839 - 20.5.2.16 graphicFrame CT_GraphicalObjectFrame
10840 - 20.1.2.2.16 graphic CT_GraphicalObject
10841 - 20.1.2.2.17 graphicData CT_GraphicalObjectData
10842 - chart reference
10843 the actual type is based on the URI of the graphicData
10844 TODO: handle embedded charts and other types of graphics
10845 */
10846 var id = (data.match(/<c:chart [^>]*r:id="([^"]*)"/)||["",""])[1];
10847
10848 return rels['!id'][id].Target;
10849}
10850
10851/* L.5.5.2 SpreadsheetML Comments + VML Schema */
10852var _shapeid = 1024;
10853function write_comments_vml(rId/*:number*/, comments) {
10854 var csize = [21600, 21600];
10855 /* L.5.2.1.2 Path Attribute */
10856 var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(",");
10857 var o = [
10858 writextag("xml", null, { 'xmlns:v': XLMLNS.v, 'xmlns:o': XLMLNS.o, 'xmlns:x': XLMLNS.x, 'xmlns:mv': XLMLNS.mv }).replace(/\/>/,">"),
10859 writextag("o:shapelayout", writextag("o:idmap", null, {'v:ext':"edit", 'data':rId}), {'v:ext':"edit"}),
10860 writextag("v:shapetype", [
10861 writextag("v:stroke", null, {joinstyle:"miter"}),
10862 writextag("v:path", null, {gradientshapeok:"t", 'o:connecttype':"rect"})
10863 ].join(""), {id:"_x0000_t202", 'o:spt':202, coordsize:csize.join(","),path:bbox})
10864 ];
10865 while(_shapeid < rId * 1000) _shapeid += 1000;
10866
10867 comments.forEach(function(x) {
10868 var c = decode_cell(x[0]);
10869 var fillopts = /*::(*/{'color2':"#BEFF82", 'type':"gradient"}/*:: :any)*/;
10870 if(fillopts.type == "gradient") fillopts.angle = "-180";
10871 var fillparm = fillopts.type == "gradient" ? writextag("o:fill", null, {type:"gradientUnscaled", 'v:ext':"view"}) : null;
10872 var fillxml = writextag('v:fill', fillparm, fillopts);
10873
10874 var shadata = ({on:"t", 'obscured':"t"}/*:any*/);
10875 ++_shapeid;
10876
10877 o = o.concat([
10878 '<v:shape' + wxt_helper({
10879 id:'_x0000_s' + _shapeid,
10880 type:"#_x0000_t202",
10881 style:"position:absolute; margin-left:80pt;margin-top:5pt;width:104pt;height:64pt;z-index:10" + (x[1].hidden ? ";visibility:hidden" : "") ,
10882 fillcolor:"#ECFAD4",
10883 strokecolor:"#edeaa1"
10884 }) + '>',
10885 fillxml,
10886 writextag("v:shadow", null, shadata),
10887 writextag("v:path", null, {'o:connecttype':"none"}),
10888 '<v:textbox><div style="text-align:left"></div></v:textbox>',
10889 '<x:ClientData ObjectType="Note">',
10890 '<x:MoveWithCells/>',
10891 '<x:SizeWithCells/>',
10892 /* Part 4 19.4.2.3 Anchor (Anchor) */
10893 writetag('x:Anchor', [c.c+1, 0, c.r+1, 0, c.c+3, 20, c.r+5, 20].join(",")),
10894 writetag('x:AutoFill', "False"),
10895 writetag('x:Row', String(c.r)),
10896 writetag('x:Column', String(c.c)),
10897 x[1].hidden ? '' : '<x:Visible/>',
10898 '</x:ClientData>',
10899 '</v:shape>'
10900 ]); });
10901 o.push('</xml>');
10902 return o.join("");
10903}
10904RELS.CMNT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
10905
10906function sheet_insert_comments(sheet, comments/*:Array<RawComment>*/) {
10907 var dense = Array.isArray(sheet);
10908 var cell/*:Cell*/;
10909 comments.forEach(function(comment) {
10910 var r = decode_cell(comment.ref);
10911 if(dense) {
10912 if(!sheet[r.r]) sheet[r.r] = [];
10913 cell = sheet[r.r][r.c];
10914 } else cell = sheet[comment.ref];
10915 if (!cell) {
10916 cell = ({t:"z"}/*:any*/);
10917 if(dense) sheet[r.r][r.c] = cell;
10918 else sheet[comment.ref] = cell;
10919 var range = safe_decode_range(sheet["!ref"]||"BDWGO1000001:A1");
10920 if(range.s.r > r.r) range.s.r = r.r;
10921 if(range.e.r < r.r) range.e.r = r.r;
10922 if(range.s.c > r.c) range.s.c = r.c;
10923 if(range.e.c < r.c) range.e.c = r.c;
10924 var encoded = encode_range(range);
10925 if (encoded !== sheet["!ref"]) sheet["!ref"] = encoded;
10926 }
10927
10928 if (!cell.c) cell.c = [];
10929 var o/*:Comment*/ = ({a: comment.author, t: comment.t, r: comment.r});
10930 if(comment.h) o.h = comment.h;
10931 cell.c.push(o);
10932 });
10933}
10934
10935/* 18.7 Comments */
10936function parse_comments_xml(data/*:string*/, opts)/*:Array<RawComment>*/ {
10937 /* 18.7.6 CT_Comments */
10938 if(data.match(/<(?:\w+:)?comments *\/>/)) return [];
10939 var authors/*:Array<string>*/ = [];
10940 var commentList/*:Array<RawComment>*/ = [];
10941 var authtag = data.match(/<(?:\w+:)?authors>([\s\S]*)<\/(?:\w+:)?authors>/);
10942 if(authtag && authtag[1]) authtag[1].split(/<\/\w*:?author>/).forEach(function(x) {
10943 if(x === "" || x.trim() === "") return;
10944 var a = x.match(/<(?:\w+:)?author[^>]*>(.*)/);
10945 if(a) authors.push(a[1]);
10946 });
10947 var cmnttag = data.match(/<(?:\w+:)?commentList>([\s\S]*)<\/(?:\w+:)?commentList>/);
10948 if(cmnttag && cmnttag[1]) cmnttag[1].split(/<\/\w*:?comment>/).forEach(function(x) {
10949 if(x === "" || x.trim() === "") return;
10950 var cm = x.match(/<(?:\w+:)?comment[^>]*>/);
10951 if(!cm) return;
10952 var y = parsexmltag(cm[0]);
10953 var comment/*:RawComment*/ = ({ author: y.authorId && authors[y.authorId] || "sheetjsghost", ref: y.ref, guid: y.guid }/*:any*/);
10954 var cell = decode_cell(y.ref);
10955 if(opts.sheetRows && opts.sheetRows <= cell.r) return;
10956 var textMatch = x.match(/<(?:\w+:)?text>([\s\S]*)<\/(?:\w+:)?text>/);
10957 var rt = !!textMatch && !!textMatch[1] && parse_si(textMatch[1]) || {r:"",t:"",h:""};
10958 comment.r = rt.r;
10959 if(rt.r == "<t></t>") rt.t = rt.h = "";
10960 comment.t = (rt.t||"").replace(/\r\n/g,"\n").replace(/\r/g,"\n");
10961 if(opts.cellHTML) comment.h = rt.h;
10962 commentList.push(comment);
10963 });
10964 return commentList;
10965}
10966
10967var CMNT_XML_ROOT = writextag('comments', null, { 'xmlns': XMLNS.main[0] });
10968function write_comments_xml(data/*::, opts*/) {
10969 var o = [XML_HEADER, CMNT_XML_ROOT];
10970
10971 var iauthor/*:Array<string>*/ = [];
10972 o.push("<authors>");
10973 data.forEach(function(x) { x[1].forEach(function(w) { var a = escapexml(w.a);
10974 if(iauthor.indexOf(a) > -1) return;
10975 iauthor.push(a);
10976 o.push("<author>" + a + "</author>");
10977 }); });
10978 o.push("</authors>");
10979 o.push("<commentList>");
10980 data.forEach(function(d) {
10981 d[1].forEach(function(c) {
10982 /* 18.7.3 CT_Comment */
10983 o.push('<comment ref="' + d[0] + '" authorId="' + iauthor.indexOf(escapexml(c.a)) + '"><text>');
10984 o.push(writetag("t", c.t == null ? "" : escapexml(c.t)));
10985 o.push('</text></comment>');
10986 });
10987 });
10988 o.push("</commentList>");
10989 if(o.length>2) { o[o.length] = ('</comments>'); o[1]=o[1].replace("/>",">"); }
10990 return o.join("");
10991}
10992/* [MS-XLSB] 2.4.28 BrtBeginComment */
10993function parse_BrtBeginComment(data) {
10994 var out = {};
10995 out.iauthor = data.read_shift(4);
10996 var rfx = parse_UncheckedRfX(data, 16);
10997 out.rfx = rfx.s;
10998 out.ref = encode_cell(rfx.s);
10999 data.l += 16; /*var guid = parse_GUID(data); */
11000 return out;
11001}
11002function write_BrtBeginComment(data, o) {
11003 if(o == null) o = new_buf(36);
11004 o.write_shift(4, data[1].iauthor);
11005 write_UncheckedRfX((data[0]/*:any*/), o);
11006 o.write_shift(4, 0);
11007 o.write_shift(4, 0);
11008 o.write_shift(4, 0);
11009 o.write_shift(4, 0);
11010 return o;
11011}
11012
11013/* [MS-XLSB] 2.4.327 BrtCommentAuthor */
11014var parse_BrtCommentAuthor = parse_XLWideString;
11015function write_BrtCommentAuthor(data) { return write_XLWideString(data.slice(0, 54)); }
11016
11017/* [MS-XLSB] 2.1.7.8 Comments */
11018function parse_comments_bin(data, opts)/*:Array<RawComment>*/ {
11019 var out/*:Array<RawComment>*/ = [];
11020 var authors/*:Array<string>*/ = [];
11021 var c = {};
11022 var pass = false;
11023 recordhopper(data, function hopper_cmnt(val, R_n, RT) {
11024 switch(RT) {
11025 case 0x0278: /* 'BrtCommentAuthor' */
11026 authors.push(val); break;
11027 case 0x027B: /* 'BrtBeginComment' */
11028 c = val; break;
11029 case 0x027D: /* 'BrtCommentText' */
11030 c.t = val.t; c.h = val.h; c.r = val.r; break;
11031 case 0x027C: /* 'BrtEndComment' */
11032 c.author = authors[c.iauthor];
11033 delete (c/*:any*/).iauthor;
11034 if(opts.sheetRows && c.rfx && opts.sheetRows <= c.rfx.r) break;
11035 if(!c.t) c.t = "";
11036 delete c.rfx; out.push(c); break;
11037
11038 case 0x0C00: /* 'BrtUid' */
11039 break;
11040
11041 case 0x0023: /* 'BrtFRTBegin' */
11042 pass = true; break;
11043 case 0x0024: /* 'BrtFRTEnd' */
11044 pass = false; break;
11045 case 0x0025: /* 'BrtACBegin' */ break;
11046 case 0x0026: /* 'BrtACEnd' */ break;
11047
11048
11049 default:
11050 if((R_n||"").indexOf("Begin") > 0){/* empty */}
11051 else if((R_n||"").indexOf("End") > 0){/* empty */}
11052 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
11053 }
11054 });
11055 return out;
11056}
11057
11058function write_comments_bin(data/*::, opts*/) {
11059 var ba = buf_array();
11060 var iauthor/*:Array<string>*/ = [];
11061 write_record(ba, "BrtBeginComments");
11062
11063 write_record(ba, "BrtBeginCommentAuthors");
11064 data.forEach(function(comment) {
11065 comment[1].forEach(function(c) {
11066 if(iauthor.indexOf(c.a) > -1) return;
11067 iauthor.push(c.a.slice(0,54));
11068 write_record(ba, "BrtCommentAuthor", write_BrtCommentAuthor(c.a));
11069 });
11070 });
11071 write_record(ba, "BrtEndCommentAuthors");
11072
11073 write_record(ba, "BrtBeginCommentList");
11074 data.forEach(function(comment) {
11075 comment[1].forEach(function(c) {
11076 c.iauthor = iauthor.indexOf(c.a);
11077 var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])};
11078 write_record(ba, "BrtBeginComment", write_BrtBeginComment([range, c]));
11079 if(c.t && c.t.length > 0) write_record(ba, "BrtCommentText", write_BrtCommentText(c));
11080 write_record(ba, "BrtEndComment");
11081 delete c.iauthor;
11082 });
11083 });
11084 write_record(ba, "BrtEndCommentList");
11085
11086 write_record(ba, "BrtEndComments");
11087 return ba.end();
11088}
11089var CT_VBA = "application/vnd.ms-office.vbaProject";
11090function make_vba_xls(cfb/*:CFBContainer*/) {
11091 var newcfb = CFB.utils.cfb_new({root:"R"});
11092 cfb.FullPaths.forEach(function(p, i) {
11093 if(p.slice(-1) === "/" || !p.match(/_VBA_PROJECT_CUR/)) return;
11094 var newpath = p.replace(/^[^\/]*/,"R").replace(/\/_VBA_PROJECT_CUR\u0000*/, "");
11095 CFB.utils.cfb_add(newcfb, newpath, cfb.FileIndex[i].content);
11096 });
11097 return CFB.write(newcfb);
11098}
11099
11100function fill_vba_xls(cfb/*:CFBContainer*/, vba/*:CFBContainer*/)/*:void*/ {
11101 vba.FullPaths.forEach(function(p, i) {
11102 if(i == 0) return;
11103 var newpath = p.replace(/[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
11104 if(newpath.slice(-1) !== "/") CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content);
11105 });
11106}
11107
11108var VBAFMTS = [ "xlsb", "xlsm", "xlam", "biff8", "xla" ];
11109
11110RELS.DS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet";
11111RELS.MS = "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet";
11112
11113/* macro and dialog sheet stubs */
11114function parse_ds_bin(/*::data:any, opts, idx:number, rels, wb, themes, styles*/)/*:Worksheet*/ { return {'!type':'dialog'}; }
11115function parse_ds_xml(/*::data:any, opts, idx:number, rels, wb, themes, styles*/)/*:Worksheet*/ { return {'!type':'dialog'}; }
11116function parse_ms_bin(/*::data:any, opts, idx:number, rels, wb, themes, styles*/)/*:Worksheet*/ { return {'!type':'macro'}; }
11117function parse_ms_xml(/*::data:any, opts, idx:number, rels, wb, themes, styles*/)/*:Worksheet*/ { return {'!type':'macro'}; }
11118/* TODO: it will be useful to parse the function str */
11119var rc_to_a1 = (function(){
11120 var rcregex = /(^|[^A-Za-z_])R(\[?-?\d+\]|[1-9]\d*|)C(\[?-?\d+\]|[1-9]\d*|)(?![A-Za-z0-9_])/g;
11121 var rcbase/*:Cell*/ = ({r:0,c:0}/*:any*/);
11122 function rcfunc($$,$1,$2,$3) {
11123 var cRel = false, rRel = false;
11124
11125 if($2.length == 0) rRel = true;
11126 else if($2.charAt(0) == "[") { rRel = true; $2 = $2.slice(1, -1); }
11127
11128 if($3.length == 0) cRel = true;
11129 else if($3.charAt(0) == "[") { cRel = true; $3 = $3.slice(1, -1); }
11130
11131 var R = $2.length>0?parseInt($2,10)|0:0, C = $3.length>0?parseInt($3,10)|0:0;
11132
11133 if(cRel) C += rcbase.c; else --C;
11134 if(rRel) R += rcbase.r; else --R;
11135 return $1 + (cRel ? "" : "$") + encode_col(C) + (rRel ? "" : "$") + encode_row(R);
11136 }
11137 return function rc_to_a1(fstr/*:string*/, base/*:Cell*/)/*:string*/ {
11138 rcbase = base;
11139 return fstr.replace(rcregex, rcfunc);
11140 };
11141})();
11142
11143var 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;
11144var a1_to_rc =(function(){
11145 return function a1_to_rc(fstr/*:string*/, base/*:CellAddress*/) {
11146 return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
11147 var c = decode_col($3) - ($2 ? 0 : base.c);
11148 var r = decode_row($5) - ($4 ? 0 : base.r);
11149 var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1));
11150 var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1));
11151 return $1 + "R" + R + "C" + C;
11152 });
11153 };
11154})();
11155
11156/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
11157function shift_formula_str(f/*:string*/, delta/*:Cell*/)/*:string*/ {
11158 return f.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
11159 return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
11160 });
11161}
11162
11163function shift_formula_xlsx(f/*:string*/, range/*:string*/, cell/*:string*/)/*:string*/ {
11164 var r = decode_range(range), s = r.s, c = decode_cell(cell);
11165 var delta = {r:c.r - s.r, c:c.c - s.c};
11166 return shift_formula_str(f, delta);
11167}
11168
11169/* TODO: parse formula */
11170function fuzzyfmla(f/*:string*/)/*:boolean*/ {
11171 if(f.length == 1) return false;
11172 return true;
11173}
11174
11175function _xlfn(f/*:string*/)/*:string*/ {
11176 return f.replace(/_xlfn\./g,"");
11177}
11178function parseread1(blob) { blob.l+=1; return; }
11179
11180/* [MS-XLS] 2.5.51 */
11181function parse_ColRelU(blob, length) {
11182 var c = blob.read_shift(length == 1 ? 1 : 2);
11183 return [c & 0x3FFF, (c >> 14) & 1, (c >> 15) & 1];
11184}
11185
11186/* [MS-XLS] 2.5.198.105 ; [MS-XLSB] 2.5.97.89 */
11187function parse_RgceArea(blob, length, opts) {
11188 var w = 2;
11189 if(opts) {
11190 if(opts.biff >= 2 && opts.biff <= 5) return parse_RgceArea_BIFF2(blob, length, opts);
11191 else if(opts.biff == 12) w = 4;
11192 }
11193 var r=blob.read_shift(w), R=blob.read_shift(w);
11194 var c=parse_ColRelU(blob, 2);
11195 var C=parse_ColRelU(blob, 2);
11196 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]} };
11197}
11198/* BIFF 2-5 encodes flags in the row field */
11199function parse_RgceArea_BIFF2(blob/*::, length, opts*/) {
11200 var r=parse_ColRelU(blob, 2), R=parse_ColRelU(blob, 2);
11201 var c=blob.read_shift(1);
11202 var C=blob.read_shift(1);
11203 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]} };
11204}
11205
11206/* [MS-XLS] 2.5.198.105 ; [MS-XLSB] 2.5.97.90 */
11207function parse_RgceAreaRel(blob, length, opts) {
11208 if(opts.biff < 8) return parse_RgceArea_BIFF2(blob, length, opts);
11209 var r=blob.read_shift(opts.biff == 12 ? 4 : 2), R=blob.read_shift(opts.biff == 12 ? 4 : 2);
11210 var c=parse_ColRelU(blob, 2);
11211 var C=parse_ColRelU(blob, 2);
11212 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]} };
11213}
11214
11215/* [MS-XLS] 2.5.198.109 ; [MS-XLSB] 2.5.97.91 */
11216function parse_RgceLoc(blob, length, opts) {
11217 if(opts && opts.biff >= 2 && opts.biff <= 5) return parse_RgceLoc_BIFF2(blob, length, opts);
11218 var r = blob.read_shift(opts && opts.biff == 12 ? 4 : 2);
11219 var c = parse_ColRelU(blob, 2);
11220 return {r:r, c:c[0], cRel:c[1], rRel:c[2]};
11221}
11222function parse_RgceLoc_BIFF2(blob/*::, length, opts*/) {
11223 var r = parse_ColRelU(blob, 2);
11224 var c = blob.read_shift(1);
11225 return {r:r[0], c:c, cRel:r[1], rRel:r[2]};
11226}
11227
11228/* [MS-XLS] 2.5.198.107, 2.5.47 */
11229function parse_RgceElfLoc(blob/*::, length, opts*/) {
11230 var r = blob.read_shift(2);
11231 var c = blob.read_shift(2);
11232 return {r:r, c:c & 0xFF, fQuoted:!!(c & 0x4000), cRel:c>>15, rRel:c>>15 };
11233}
11234
11235/* [MS-XLS] 2.5.198.111 ; [MS-XLSB] 2.5.97.92 TODO */
11236function parse_RgceLocRel(blob, length, opts) {
11237 var biff = opts && opts.biff ? opts.biff : 8;
11238 if(biff >= 2 && biff <= 5) return parse_RgceLocRel_BIFF2(blob, length, opts);
11239 var r = blob.read_shift(biff >= 12 ? 4 : 2);
11240 var cl = blob.read_shift(2);
11241 var cRel = (cl & 0x4000) >> 14, rRel = (cl & 0x8000) >> 15;
11242 cl &= 0x3FFF;
11243 if(rRel == 1) while(r > 0x7FFFF) r -= 0x100000;
11244 if(cRel == 1) while(cl > 0x1FFF) cl = cl - 0x4000;
11245 return {r:r,c:cl,cRel:cRel,rRel:rRel};
11246}
11247function parse_RgceLocRel_BIFF2(blob/*::, length:number, opts*/) {
11248 var rl = blob.read_shift(2);
11249 var c = blob.read_shift(1);
11250 var rRel = (rl & 0x8000) >> 15, cRel = (rl & 0x4000) >> 14;
11251 rl &= 0x3FFF;
11252 if(rRel == 1 && rl >= 0x2000) rl = rl - 0x4000;
11253 if(cRel == 1 && c >= 0x80) c = c - 0x100;
11254 return {r:rl,c:c,cRel:cRel,rRel:rRel};
11255}
11256
11257/* [MS-XLS] 2.5.198.27 ; [MS-XLSB] 2.5.97.18 */
11258function parse_PtgArea(blob, length, opts) {
11259 var type = (blob[blob.l++] & 0x60) >> 5;
11260 var area = parse_RgceArea(blob, opts.biff >= 2 && opts.biff <= 5 ? 6 : 8, opts);
11261 return [type, area];
11262}
11263
11264/* [MS-XLS] 2.5.198.28 ; [MS-XLSB] 2.5.97.19 */
11265function parse_PtgArea3d(blob, length, opts) {
11266 var type = (blob[blob.l++] & 0x60) >> 5;
11267 var ixti = blob.read_shift(2, 'i');
11268 var w = 8;
11269 if(opts) switch(opts.biff) {
11270 case 5: blob.l += 12; w = 6; break;
11271 case 12: w = 12; break;
11272 }
11273 var area = parse_RgceArea(blob, w, opts);
11274 return [type, ixti, area];
11275}
11276
11277/* [MS-XLS] 2.5.198.29 ; [MS-XLSB] 2.5.97.20 */
11278function parse_PtgAreaErr(blob, length, opts) {
11279 var type = (blob[blob.l++] & 0x60) >> 5;
11280 blob.l += opts && (opts.biff > 8) ? 12 : (opts.biff < 8 ? 6 : 8);
11281 return [type];
11282}
11283/* [MS-XLS] 2.5.198.30 ; [MS-XLSB] 2.5.97.21 */
11284function parse_PtgAreaErr3d(blob, length, opts) {
11285 var type = (blob[blob.l++] & 0x60) >> 5;
11286 var ixti = blob.read_shift(2);
11287 var w = 8;
11288 if(opts) switch(opts.biff) {
11289 case 5: blob.l += 12; w = 6; break;
11290 case 12: w = 12; break;
11291 }
11292 blob.l += w;
11293 return [type, ixti];
11294}
11295
11296/* [MS-XLS] 2.5.198.31 ; [MS-XLSB] 2.5.97.22 */
11297function parse_PtgAreaN(blob, length, opts) {
11298 var type = (blob[blob.l++] & 0x60) >> 5;
11299 var area = parse_RgceAreaRel(blob, length - 1, opts);
11300 return [type, area];
11301}
11302
11303/* [MS-XLS] 2.5.198.32 ; [MS-XLSB] 2.5.97.23 */
11304function parse_PtgArray(blob, length, opts) {
11305 var type = (blob[blob.l++] & 0x60) >> 5;
11306 blob.l += opts.biff == 2 ? 6 : opts.biff == 12 ? 14 : 7;
11307 return [type];
11308}
11309
11310/* [MS-XLS] 2.5.198.33 ; [MS-XLSB] 2.5.97.24 */
11311function parse_PtgAttrBaxcel(blob) {
11312 var bitSemi = blob[blob.l+1] & 0x01; /* 1 = volatile */
11313 var bitBaxcel = 1;
11314 blob.l += 4;
11315 return [bitSemi, bitBaxcel];
11316}
11317
11318/* [MS-XLS] 2.5.198.34 ; [MS-XLSB] 2.5.97.25 */
11319function parse_PtgAttrChoose(blob, length, opts)/*:Array<number>*/ {
11320 blob.l +=2;
11321 var offset = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
11322 var o/*:Array<number>*/ = [];
11323 /* offset is 1 less than the number of elements */
11324 for(var i = 0; i <= offset; ++i) o.push(blob.read_shift(opts && opts.biff == 2 ? 1 : 2));
11325 return o;
11326}
11327
11328/* [MS-XLS] 2.5.198.35 ; [MS-XLSB] 2.5.97.26 */
11329function parse_PtgAttrGoto(blob, length, opts) {
11330 var bitGoto = (blob[blob.l+1] & 0xFF) ? 1 : 0;
11331 blob.l += 2;
11332 return [bitGoto, blob.read_shift(opts && opts.biff == 2 ? 1 : 2)];
11333}
11334
11335/* [MS-XLS] 2.5.198.36 ; [MS-XLSB] 2.5.97.27 */
11336function parse_PtgAttrIf(blob, length, opts) {
11337 var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0;
11338 blob.l += 2;
11339 return [bitIf, blob.read_shift(opts && opts.biff == 2 ? 1 : 2)];
11340}
11341
11342/* [MS-XLSB] 2.5.97.28 */
11343function parse_PtgAttrIfError(blob) {
11344 var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0;
11345 blob.l += 2;
11346 return [bitIf, blob.read_shift(2)];
11347}
11348
11349/* [MS-XLS] 2.5.198.37 ; [MS-XLSB] 2.5.97.29 */
11350function parse_PtgAttrSemi(blob, length, opts) {
11351 var bitSemi = (blob[blob.l+1] & 0xFF) ? 1 : 0;
11352 blob.l += opts && opts.biff == 2 ? 3 : 4;
11353 return [bitSemi];
11354}
11355
11356/* [MS-XLS] 2.5.198.40 ; [MS-XLSB] 2.5.97.32 */
11357function parse_PtgAttrSpaceType(blob/*::, length*/) {
11358 var type = blob.read_shift(1), cch = blob.read_shift(1);
11359 return [type, cch];
11360}
11361
11362/* [MS-XLS] 2.5.198.38 ; [MS-XLSB] 2.5.97.30 */
11363function parse_PtgAttrSpace(blob) {
11364 blob.read_shift(2);
11365 return parse_PtgAttrSpaceType(blob, 2);
11366}
11367
11368/* [MS-XLS] 2.5.198.39 ; [MS-XLSB] 2.5.97.31 */
11369function parse_PtgAttrSpaceSemi(blob) {
11370 blob.read_shift(2);
11371 return parse_PtgAttrSpaceType(blob, 2);
11372}
11373
11374/* [MS-XLS] 2.5.198.84 ; [MS-XLSB] 2.5.97.68 TODO */
11375function parse_PtgRef(blob, length, opts) {
11376 //var ptg = blob[blob.l] & 0x1F;
11377 var type = (blob[blob.l] & 0x60)>>5;
11378 blob.l += 1;
11379 var loc = parse_RgceLoc(blob, 0, opts);
11380 return [type, loc];
11381}
11382
11383/* [MS-XLS] 2.5.198.88 ; [MS-XLSB] 2.5.97.72 TODO */
11384function parse_PtgRefN(blob, length, opts) {
11385 var type = (blob[blob.l] & 0x60)>>5;
11386 blob.l += 1;
11387 var loc = parse_RgceLocRel(blob, 0, opts);
11388 return [type, loc];
11389}
11390
11391/* [MS-XLS] 2.5.198.85 ; [MS-XLSB] 2.5.97.69 TODO */
11392function parse_PtgRef3d(blob, length, opts) {
11393 var type = (blob[blob.l] & 0x60)>>5;
11394 blob.l += 1;
11395 var ixti = blob.read_shift(2); // XtiIndex
11396 if(opts && opts.biff == 5) blob.l += 12;
11397 var loc = parse_RgceLoc(blob, 0, opts); // TODO: or RgceLocRel
11398 return [type, ixti, loc];
11399}
11400
11401
11402/* [MS-XLS] 2.5.198.62 ; [MS-XLSB] 2.5.97.45 TODO */
11403function parse_PtgFunc(blob, length, opts) {
11404 //var ptg = blob[blob.l] & 0x1F;
11405 var type = (blob[blob.l] & 0x60)>>5;
11406 blob.l += 1;
11407 var iftab = blob.read_shift(opts && opts.biff <= 3 ? 1 : 2);
11408 return [FtabArgc[iftab], Ftab[iftab], type];
11409}
11410/* [MS-XLS] 2.5.198.63 ; [MS-XLSB] 2.5.97.46 TODO */
11411function parse_PtgFuncVar(blob, length, opts) {
11412 var type = blob[blob.l++];
11413 var cparams = blob.read_shift(1), tab = opts && opts.biff <= 3 ? [(type == 0x58 ? -1 : 0), blob.read_shift(1)]: parsetab(blob);
11414 return [cparams, (tab[0] === 0 ? Ftab : Cetab)[tab[1]]];
11415}
11416
11417function parsetab(blob) {
11418 return [blob[blob.l+1]>>7, blob.read_shift(2) & 0x7FFF];
11419}
11420
11421/* [MS-XLS] 2.5.198.41 ; [MS-XLSB] 2.5.97.33 */
11422function parse_PtgAttrSum(blob, length, opts) {
11423 blob.l += opts && opts.biff == 2 ? 3 : 4; return;
11424}
11425
11426/* [MS-XLS] 2.5.198.58 ; [MS-XLSB] 2.5.97.40 */
11427function parse_PtgExp(blob, length, opts) {
11428 blob.l++;
11429 if(opts && opts.biff == 12) return [blob.read_shift(4, 'i'), 0];
11430 var row = blob.read_shift(2);
11431 var col = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
11432 return [row, col];
11433}
11434
11435/* [MS-XLS] 2.5.198.57 ; [MS-XLSB] 2.5.97.39 */
11436function parse_PtgErr(blob) { blob.l++; return BErr[blob.read_shift(1)]; }
11437
11438/* [MS-XLS] 2.5.198.66 ; [MS-XLSB] 2.5.97.49 */
11439function parse_PtgInt(blob) { blob.l++; return blob.read_shift(2); }
11440
11441/* [MS-XLS] 2.5.198.42 ; [MS-XLSB] 2.5.97.34 */
11442function parse_PtgBool(blob) { blob.l++; return blob.read_shift(1)!==0;}
11443
11444/* [MS-XLS] 2.5.198.79 ; [MS-XLSB] 2.5.97.63 */
11445function parse_PtgNum(blob) { blob.l++; return parse_Xnum(blob, 8); }
11446
11447/* [MS-XLS] 2.5.198.89 ; [MS-XLSB] 2.5.97.74 */
11448function parse_PtgStr(blob, length, opts) { blob.l++; return parse_ShortXLUnicodeString(blob, length-1, opts); }
11449
11450/* [MS-XLS] 2.5.192.112 + 2.5.192.11{3,4,5,6,7} */
11451/* [MS-XLSB] 2.5.97.93 + 2.5.97.9{4,5,6,7} */
11452function parse_SerAr(blob, biff/*:number*/) {
11453 var val = [blob.read_shift(1)];
11454 if(biff == 12) switch(val[0]) {
11455 case 0x02: val[0] = 0x04; break; /* SerBool */
11456 case 0x04: val[0] = 0x10; break; /* SerErr */
11457 case 0x00: val[0] = 0x01; break; /* SerNum */
11458 case 0x01: val[0] = 0x02; break; /* SerStr */
11459 }
11460 switch(val[0]) {
11461 case 0x04: /* SerBool -- boolean */
11462 val[1] = parsebool(blob, 1) ? 'TRUE' : 'FALSE';
11463 if(biff != 12) blob.l += 7; break;
11464 case 0x25: /* appears to be an alias */
11465 case 0x10: /* SerErr -- error */
11466 val[1] = BErr[blob[blob.l]];
11467 blob.l += ((biff == 12) ? 4 : 8); break;
11468 case 0x00: /* SerNil -- honestly, I'm not sure how to reproduce this */
11469 blob.l += 8; break;
11470 case 0x01: /* SerNum -- Xnum */
11471 val[1] = parse_Xnum(blob, 8); break;
11472 case 0x02: /* SerStr -- XLUnicodeString (<256 chars) */
11473 val[1] = parse_XLUnicodeString2(blob, 0, {biff:biff > 0 && biff < 8 ? 2 : biff}); break;
11474 default: throw new Error("Bad SerAr: " + val[0]); /* Unreachable */
11475 }
11476 return val;
11477}
11478
11479/* [MS-XLS] 2.5.198.61 ; [MS-XLSB] 2.5.97.44 */
11480function parse_PtgExtraMem(blob, cce, opts) {
11481 var count = blob.read_shift((opts.biff == 12) ? 4 : 2);
11482 var out/*:Array<Range>*/ = [];
11483 for(var i = 0; i != count; ++i) out.push(((opts.biff == 12) ? parse_UncheckedRfX : parse_Ref8U)(blob, 8));
11484 return out;
11485}
11486
11487/* [MS-XLS] 2.5.198.59 ; [MS-XLSB] 2.5.97.41 */
11488function parse_PtgExtraArray(blob, length, opts) {
11489 var rows = 0, cols = 0;
11490 if(opts.biff == 12) {
11491 rows = blob.read_shift(4); // DRw
11492 cols = blob.read_shift(4); // DCol
11493 } else {
11494 cols = 1 + blob.read_shift(1); //DColByteU
11495 rows = 1 + blob.read_shift(2); //DRw
11496 }
11497 if(opts.biff >= 2 && opts.biff < 8) { --rows; if(--cols == 0) cols = 0x100; }
11498 // $FlowIgnore
11499 for(var i = 0, o/*:Array<Array<any>>*/ = []; i != rows && (o[i] = []); ++i)
11500 for(var j = 0; j != cols; ++j) o[i][j] = parse_SerAr(blob, opts.biff);
11501 return o;
11502}
11503
11504/* [MS-XLS] 2.5.198.76 ; [MS-XLSB] 2.5.97.60 */
11505function parse_PtgName(blob, length, opts) {
11506 var type = (blob.read_shift(1) >>> 5) & 0x03;
11507 var w = (!opts || (opts.biff >= 8)) ? 4 : 2;
11508 var nameindex = blob.read_shift(w);
11509 switch(opts.biff) {
11510 case 2: blob.l += 5; break;
11511 case 3: case 4: blob.l += 8; break;
11512 case 5: blob.l += 12; break;
11513 }
11514 return [type, 0, nameindex];
11515}
11516
11517/* [MS-XLS] 2.5.198.77 ; [MS-XLSB] 2.5.97.61 */
11518function parse_PtgNameX(blob, length, opts) {
11519 if(opts.biff == 5) return parse_PtgNameX_BIFF5(blob, length, opts);
11520 var type = (blob.read_shift(1) >>> 5) & 0x03;
11521 var ixti = blob.read_shift(2); // XtiIndex
11522 var nameindex = blob.read_shift(4);
11523 return [type, ixti, nameindex];
11524}
11525function parse_PtgNameX_BIFF5(blob/*::, length, opts*/) {
11526 var type = (blob.read_shift(1) >>> 5) & 0x03;
11527 var ixti = blob.read_shift(2, 'i'); // XtiIndex
11528 blob.l += 8;
11529 var nameindex = blob.read_shift(2);
11530 blob.l += 12;
11531 return [type, ixti, nameindex];
11532}
11533
11534/* [MS-XLS] 2.5.198.70 ; [MS-XLSB] 2.5.97.54 */
11535function parse_PtgMemArea(blob, length, opts) {
11536 var type = (blob.read_shift(1) >>> 5) & 0x03;
11537 blob.l += (opts && opts.biff == 2 ? 3 : 4);
11538 var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
11539 return [type, cce];
11540}
11541
11542/* [MS-XLS] 2.5.198.72 ; [MS-XLSB] 2.5.97.56 */
11543function parse_PtgMemFunc(blob, length, opts) {
11544 var type = (blob.read_shift(1) >>> 5) & 0x03;
11545 var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
11546 return [type, cce];
11547}
11548
11549
11550/* [MS-XLS] 2.5.198.86 ; [MS-XLSB] 2.5.97.69 */
11551function parse_PtgRefErr(blob, length, opts) {
11552 var type = (blob.read_shift(1) >>> 5) & 0x03;
11553 blob.l += 4;
11554 if(opts.biff < 8) blob.l--;
11555 if(opts.biff == 12) blob.l += 2;
11556 return [type];
11557}
11558
11559/* [MS-XLS] 2.5.198.87 ; [MS-XLSB] 2.5.97.71 */
11560function parse_PtgRefErr3d(blob, length, opts) {
11561 var type = (blob[blob.l++] & 0x60) >> 5;
11562 var ixti = blob.read_shift(2);
11563 var w = 4;
11564 if(opts) switch(opts.biff) {
11565 case 5: w = 15; break;
11566 case 12: w = 6; break;
11567 }
11568 blob.l += w;
11569 return [type, ixti];
11570}
11571
11572/* [MS-XLS] 2.5.198.71 ; [MS-XLSB] 2.5.97.55 */
11573var parse_PtgMemErr = parsenoop;
11574/* [MS-XLS] 2.5.198.73 ; [MS-XLSB] 2.5.97.57 */
11575var parse_PtgMemNoMem = parsenoop;
11576/* [MS-XLS] 2.5.198.92 */
11577var parse_PtgTbl = parsenoop;
11578
11579function parse_PtgElfLoc(blob, length, opts) {
11580 blob.l += 2;
11581 return [parse_RgceElfLoc(blob, 4, opts)];
11582}
11583function parse_PtgElfNoop(blob/*::, length, opts*/) {
11584 blob.l += 6;
11585 return [];
11586}
11587/* [MS-XLS] 2.5.198.46 */
11588var parse_PtgElfCol = parse_PtgElfLoc;
11589/* [MS-XLS] 2.5.198.47 */
11590var parse_PtgElfColS = parse_PtgElfNoop;
11591/* [MS-XLS] 2.5.198.48 */
11592var parse_PtgElfColSV = parse_PtgElfNoop;
11593/* [MS-XLS] 2.5.198.49 */
11594var parse_PtgElfColV = parse_PtgElfLoc;
11595/* [MS-XLS] 2.5.198.50 */
11596function parse_PtgElfLel(blob/*::, length, opts*/) {
11597 blob.l += 2;
11598 return [parseuint16(blob), blob.read_shift(2) & 0x01];
11599}
11600/* [MS-XLS] 2.5.198.51 */
11601var parse_PtgElfRadical = parse_PtgElfLoc;
11602/* [MS-XLS] 2.5.198.52 */
11603var parse_PtgElfRadicalLel = parse_PtgElfLel;
11604/* [MS-XLS] 2.5.198.53 */
11605var parse_PtgElfRadicalS = parse_PtgElfNoop;
11606/* [MS-XLS] 2.5.198.54 */
11607var parse_PtgElfRw = parse_PtgElfLoc;
11608/* [MS-XLS] 2.5.198.55 */
11609var parse_PtgElfRwV = parse_PtgElfLoc;
11610
11611/* [MS-XLSB] 2.5.97.52 TODO */
11612var PtgListRT = [
11613 "Data",
11614 "All",
11615 "Headers",
11616 "??",
11617 "?Data2",
11618 "??",
11619 "?DataHeaders",
11620 "??",
11621 "Totals",
11622 "??",
11623 "??",
11624 "??",
11625 "?DataTotals",
11626 "??",
11627 "??",
11628 "??",
11629 "?Current"
11630];
11631function parse_PtgList(blob/*::, length, opts*/) {
11632 blob.l += 2;
11633 var ixti = blob.read_shift(2);
11634 var flags = blob.read_shift(2);
11635 var idx = blob.read_shift(4);
11636 var c = blob.read_shift(2);
11637 var C = blob.read_shift(2);
11638 var rt = PtgListRT[(flags >> 2) & 0x1F];
11639 return {ixti: ixti, coltype:(flags&0x3), rt:rt, idx:idx, c:c, C:C};
11640}
11641/* [MS-XLS] 2.5.198.91 ; [MS-XLSB] 2.5.97.76 */
11642function parse_PtgSxName(blob/*::, length, opts*/) {
11643 blob.l += 2;
11644 return [blob.read_shift(4)];
11645}
11646
11647/* [XLS] old spec */
11648function parse_PtgSheet(blob, length, opts) {
11649 blob.l += 5;
11650 blob.l += 2;
11651 blob.l += (opts.biff == 2 ? 1 : 4);
11652 return ["PTGSHEET"];
11653}
11654function parse_PtgEndSheet(blob, length, opts) {
11655 blob.l += (opts.biff == 2 ? 4 : 5);
11656 return ["PTGENDSHEET"];
11657}
11658function parse_PtgMemAreaN(blob/*::, length, opts*/) {
11659 var type = (blob.read_shift(1) >>> 5) & 0x03;
11660 var cce = blob.read_shift(2);
11661 return [type, cce];
11662}
11663function parse_PtgMemNoMemN(blob/*::, length, opts*/) {
11664 var type = (blob.read_shift(1) >>> 5) & 0x03;
11665 var cce = blob.read_shift(2);
11666 return [type, cce];
11667}
11668function parse_PtgAttrNoop(blob/*::, length, opts*/) {
11669 blob.l += 4;
11670 return [0, 0];
11671}
11672
11673/* [MS-XLS] 2.5.198.25 ; [MS-XLSB] 2.5.97.16 */
11674var PtgTypes = {
11675 /*::[*/0x01/*::]*/: { n:'PtgExp', f:parse_PtgExp },
11676 /*::[*/0x02/*::]*/: { n:'PtgTbl', f:parse_PtgTbl },
11677 /*::[*/0x03/*::]*/: { n:'PtgAdd', f:parseread1 },
11678 /*::[*/0x04/*::]*/: { n:'PtgSub', f:parseread1 },
11679 /*::[*/0x05/*::]*/: { n:'PtgMul', f:parseread1 },
11680 /*::[*/0x06/*::]*/: { n:'PtgDiv', f:parseread1 },
11681 /*::[*/0x07/*::]*/: { n:'PtgPower', f:parseread1 },
11682 /*::[*/0x08/*::]*/: { n:'PtgConcat', f:parseread1 },
11683 /*::[*/0x09/*::]*/: { n:'PtgLt', f:parseread1 },
11684 /*::[*/0x0A/*::]*/: { n:'PtgLe', f:parseread1 },
11685 /*::[*/0x0B/*::]*/: { n:'PtgEq', f:parseread1 },
11686 /*::[*/0x0C/*::]*/: { n:'PtgGe', f:parseread1 },
11687 /*::[*/0x0D/*::]*/: { n:'PtgGt', f:parseread1 },
11688 /*::[*/0x0E/*::]*/: { n:'PtgNe', f:parseread1 },
11689 /*::[*/0x0F/*::]*/: { n:'PtgIsect', f:parseread1 },
11690 /*::[*/0x10/*::]*/: { n:'PtgUnion', f:parseread1 },
11691 /*::[*/0x11/*::]*/: { n:'PtgRange', f:parseread1 },
11692 /*::[*/0x12/*::]*/: { n:'PtgUplus', f:parseread1 },
11693 /*::[*/0x13/*::]*/: { n:'PtgUminus', f:parseread1 },
11694 /*::[*/0x14/*::]*/: { n:'PtgPercent', f:parseread1 },
11695 /*::[*/0x15/*::]*/: { n:'PtgParen', f:parseread1 },
11696 /*::[*/0x16/*::]*/: { n:'PtgMissArg', f:parseread1 },
11697 /*::[*/0x17/*::]*/: { n:'PtgStr', f:parse_PtgStr },
11698 /*::[*/0x1A/*::]*/: { n:'PtgSheet', f:parse_PtgSheet },
11699 /*::[*/0x1B/*::]*/: { n:'PtgEndSheet', f:parse_PtgEndSheet },
11700 /*::[*/0x1C/*::]*/: { n:'PtgErr', f:parse_PtgErr },
11701 /*::[*/0x1D/*::]*/: { n:'PtgBool', f:parse_PtgBool },
11702 /*::[*/0x1E/*::]*/: { n:'PtgInt', f:parse_PtgInt },
11703 /*::[*/0x1F/*::]*/: { n:'PtgNum', f:parse_PtgNum },
11704 /*::[*/0x20/*::]*/: { n:'PtgArray', f:parse_PtgArray },
11705 /*::[*/0x21/*::]*/: { n:'PtgFunc', f:parse_PtgFunc },
11706 /*::[*/0x22/*::]*/: { n:'PtgFuncVar', f:parse_PtgFuncVar },
11707 /*::[*/0x23/*::]*/: { n:'PtgName', f:parse_PtgName },
11708 /*::[*/0x24/*::]*/: { n:'PtgRef', f:parse_PtgRef },
11709 /*::[*/0x25/*::]*/: { n:'PtgArea', f:parse_PtgArea },
11710 /*::[*/0x26/*::]*/: { n:'PtgMemArea', f:parse_PtgMemArea },
11711 /*::[*/0x27/*::]*/: { n:'PtgMemErr', f:parse_PtgMemErr },
11712 /*::[*/0x28/*::]*/: { n:'PtgMemNoMem', f:parse_PtgMemNoMem },
11713 /*::[*/0x29/*::]*/: { n:'PtgMemFunc', f:parse_PtgMemFunc },
11714 /*::[*/0x2A/*::]*/: { n:'PtgRefErr', f:parse_PtgRefErr },
11715 /*::[*/0x2B/*::]*/: { n:'PtgAreaErr', f:parse_PtgAreaErr },
11716 /*::[*/0x2C/*::]*/: { n:'PtgRefN', f:parse_PtgRefN },
11717 /*::[*/0x2D/*::]*/: { n:'PtgAreaN', f:parse_PtgAreaN },
11718 /*::[*/0x2E/*::]*/: { n:'PtgMemAreaN', f:parse_PtgMemAreaN },
11719 /*::[*/0x2F/*::]*/: { n:'PtgMemNoMemN', f:parse_PtgMemNoMemN },
11720 /*::[*/0x39/*::]*/: { n:'PtgNameX', f:parse_PtgNameX },
11721 /*::[*/0x3A/*::]*/: { n:'PtgRef3d', f:parse_PtgRef3d },
11722 /*::[*/0x3B/*::]*/: { n:'PtgArea3d', f:parse_PtgArea3d },
11723 /*::[*/0x3C/*::]*/: { n:'PtgRefErr3d', f:parse_PtgRefErr3d },
11724 /*::[*/0x3D/*::]*/: { n:'PtgAreaErr3d', f:parse_PtgAreaErr3d },
11725 /*::[*/0xFF/*::]*/: {}
11726};
11727/* These are duplicated in the PtgTypes table */
11728var PtgDupes = {
11729 /*::[*/0x40/*::]*/: 0x20, /*::[*/0x60/*::]*/: 0x20,
11730 /*::[*/0x41/*::]*/: 0x21, /*::[*/0x61/*::]*/: 0x21,
11731 /*::[*/0x42/*::]*/: 0x22, /*::[*/0x62/*::]*/: 0x22,
11732 /*::[*/0x43/*::]*/: 0x23, /*::[*/0x63/*::]*/: 0x23,
11733 /*::[*/0x44/*::]*/: 0x24, /*::[*/0x64/*::]*/: 0x24,
11734 /*::[*/0x45/*::]*/: 0x25, /*::[*/0x65/*::]*/: 0x25,
11735 /*::[*/0x46/*::]*/: 0x26, /*::[*/0x66/*::]*/: 0x26,
11736 /*::[*/0x47/*::]*/: 0x27, /*::[*/0x67/*::]*/: 0x27,
11737 /*::[*/0x48/*::]*/: 0x28, /*::[*/0x68/*::]*/: 0x28,
11738 /*::[*/0x49/*::]*/: 0x29, /*::[*/0x69/*::]*/: 0x29,
11739 /*::[*/0x4A/*::]*/: 0x2A, /*::[*/0x6A/*::]*/: 0x2A,
11740 /*::[*/0x4B/*::]*/: 0x2B, /*::[*/0x6B/*::]*/: 0x2B,
11741 /*::[*/0x4C/*::]*/: 0x2C, /*::[*/0x6C/*::]*/: 0x2C,
11742 /*::[*/0x4D/*::]*/: 0x2D, /*::[*/0x6D/*::]*/: 0x2D,
11743 /*::[*/0x4E/*::]*/: 0x2E, /*::[*/0x6E/*::]*/: 0x2E,
11744 /*::[*/0x4F/*::]*/: 0x2F, /*::[*/0x6F/*::]*/: 0x2F,
11745 /*::[*/0x58/*::]*/: 0x22, /*::[*/0x78/*::]*/: 0x22,
11746 /*::[*/0x59/*::]*/: 0x39, /*::[*/0x79/*::]*/: 0x39,
11747 /*::[*/0x5A/*::]*/: 0x3A, /*::[*/0x7A/*::]*/: 0x3A,
11748 /*::[*/0x5B/*::]*/: 0x3B, /*::[*/0x7B/*::]*/: 0x3B,
11749 /*::[*/0x5C/*::]*/: 0x3C, /*::[*/0x7C/*::]*/: 0x3C,
11750 /*::[*/0x5D/*::]*/: 0x3D, /*::[*/0x7D/*::]*/: 0x3D
11751};
11752(function(){for(var y in PtgDupes) PtgTypes[y] = PtgTypes[PtgDupes[y]];})();
11753
11754var Ptg18 = {
11755 /*::[*/0x01/*::]*/: { n:'PtgElfLel', f:parse_PtgElfLel },
11756 /*::[*/0x02/*::]*/: { n:'PtgElfRw', f:parse_PtgElfRw },
11757 /*::[*/0x03/*::]*/: { n:'PtgElfCol', f:parse_PtgElfCol },
11758 /*::[*/0x06/*::]*/: { n:'PtgElfRwV', f:parse_PtgElfRwV },
11759 /*::[*/0x07/*::]*/: { n:'PtgElfColV', f:parse_PtgElfColV },
11760 /*::[*/0x0A/*::]*/: { n:'PtgElfRadical', f:parse_PtgElfRadical },
11761 /*::[*/0x0B/*::]*/: { n:'PtgElfRadicalS', f:parse_PtgElfRadicalS },
11762 /*::[*/0x0D/*::]*/: { n:'PtgElfColS', f:parse_PtgElfColS },
11763 /*::[*/0x0F/*::]*/: { n:'PtgElfColSV', f:parse_PtgElfColSV },
11764 /*::[*/0x10/*::]*/: { n:'PtgElfRadicalLel', f:parse_PtgElfRadicalLel },
11765 /*::[*/0x19/*::]*/: { n:'PtgList', f:parse_PtgList },
11766 /*::[*/0x1D/*::]*/: { n:'PtgSxName', f:parse_PtgSxName },
11767 /*::[*/0xFF/*::]*/: {}
11768};
11769var Ptg19 = {
11770 /*::[*/0x00/*::]*/: { n:'PtgAttrNoop', f:parse_PtgAttrNoop },
11771 /*::[*/0x01/*::]*/: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
11772 /*::[*/0x02/*::]*/: { n:'PtgAttrIf', f:parse_PtgAttrIf },
11773 /*::[*/0x04/*::]*/: { n:'PtgAttrChoose', f:parse_PtgAttrChoose },
11774 /*::[*/0x08/*::]*/: { n:'PtgAttrGoto', f:parse_PtgAttrGoto },
11775 /*::[*/0x10/*::]*/: { n:'PtgAttrSum', f:parse_PtgAttrSum },
11776 /*::[*/0x20/*::]*/: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
11777 /*::[*/0x40/*::]*/: { n:'PtgAttrSpace', f:parse_PtgAttrSpace },
11778 /*::[*/0x41/*::]*/: { n:'PtgAttrSpaceSemi', f:parse_PtgAttrSpaceSemi },
11779 /*::[*/0x80/*::]*/: { n:'PtgAttrIfError', f:parse_PtgAttrIfError },
11780 /*::[*/0xFF/*::]*/: {}
11781};
11782Ptg19[0x21] = Ptg19[0x20];
11783
11784/* [MS-XLS] 2.5.198.103 ; [MS-XLSB] 2.5.97.87 */
11785function parse_RgbExtra(blob, length, rgce, opts) {
11786 if(opts.biff < 8) return parsenoop(blob, length);
11787 var target = blob.l + length;
11788 var o = [];
11789 for(var i = 0; i !== rgce.length; ++i) {
11790 switch(rgce[i][0]) {
11791 case 'PtgArray': /* PtgArray -> PtgExtraArray */
11792 rgce[i][1] = parse_PtgExtraArray(blob, 0, opts);
11793 o.push(rgce[i][1]);
11794 break;
11795 case 'PtgMemArea': /* PtgMemArea -> PtgExtraMem */
11796 rgce[i][2] = parse_PtgExtraMem(blob, rgce[i][1], opts);
11797 o.push(rgce[i][2]);
11798 break;
11799 case 'PtgExp': /* PtgExp -> PtgExtraCol */
11800 if(opts && opts.biff == 12) {
11801 rgce[i][1][1] = blob.read_shift(4);
11802 o.push(rgce[i][1]);
11803 } break;
11804 case 'PtgList': /* TODO: PtgList -> PtgExtraList */
11805 case 'PtgElfRadicalS': /* TODO: PtgElfRadicalS -> PtgExtraElf */
11806 case 'PtgElfColS': /* TODO: PtgElfColS -> PtgExtraElf */
11807 case 'PtgElfColSV': /* TODO: PtgElfColSV -> PtgExtraElf */
11808 throw "Unsupported " + rgce[i][0];
11809 default: break;
11810 }
11811 }
11812 length = target - blob.l;
11813 /* note: this is technically an error but Excel disregards */
11814 //if(target !== blob.l && blob.l !== target - length) throw new Error(target + " != " + blob.l);
11815 if(length !== 0) o.push(parsenoop(blob, length));
11816 return o;
11817}
11818
11819/* [MS-XLS] 2.5.198.104 ; [MS-XLSB] 2.5.97.88 */
11820function parse_Rgce(blob, length, opts) {
11821 var target = blob.l + length;
11822 var R, id, ptgs = [];
11823 while(target != blob.l) {
11824 length = target - blob.l;
11825 id = blob[blob.l];
11826 R = PtgTypes[id];
11827 if(id === 0x18 || id === 0x19) R = (id === 0x18 ? Ptg18 : Ptg19)[blob[blob.l + 1]];
11828 if(!R || !R.f) { /*ptgs.push*/(parsenoop(blob, length)); }
11829 else { ptgs.push([R.n, R.f(blob, length, opts)]); }
11830 }
11831 return ptgs;
11832}
11833
11834function stringify_array(f/*:Array<Array<string>>*/)/*:string*/ {
11835 var o/*:Array<string>*/ = [];
11836 for(var i = 0; i < f.length; ++i) {
11837 var x = f[i], r/*:Array<string>*/ = [];
11838 for(var j = 0; j < x.length; ++j) {
11839 var y = x[j];
11840 if(y) switch(y[0]) {
11841 // TODO: handle embedded quotes
11842 case 0x02:
11843 /*:: if(typeof y[1] != 'string') throw "unreachable"; */
11844 r.push('"' + y[1].replace(/"/g,'""') + '"'); break;
11845 default: r.push(y[1]);
11846 } else r.push("");
11847 }
11848 o.push(r.join(","));
11849 }
11850 return o.join(";");
11851}
11852
11853/* [MS-XLS] 2.2.2 ; [MS-XLSB] 2.2.2 TODO */
11854var PtgBinOp = {
11855 PtgAdd: "+",
11856 PtgConcat: "&",
11857 PtgDiv: "/",
11858 PtgEq: "=",
11859 PtgGe: ">=",
11860 PtgGt: ">",
11861 PtgLe: "<=",
11862 PtgLt: "<",
11863 PtgMul: "*",
11864 PtgNe: "<>",
11865 PtgPower: "^",
11866 PtgSub: "-"
11867};
11868
11869// List of invalid characters needs to be tested further
11870var quoteCharacters /*:RegExp */ = new RegExp(/[^\w\u4E00-\u9FFF\u3040-\u30FF]/);
11871function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ {
11872 if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name");
11873 if (quoteCharacters.test(sname)) return "'" + sname + "'";
11874 return sname;
11875}
11876function get_ixti_raw(supbooks, ixti/*:number*/, opts)/*:string*/ {
11877 if(!supbooks) return "SH33TJSERR0";
11878 if(opts.biff > 8 && (!supbooks.XTI || !supbooks.XTI[ixti])) return supbooks.SheetNames[ixti];
11879 if(!supbooks.XTI) return "SH33TJSERR6";
11880 var XTI = supbooks.XTI[ixti];
11881 if(opts.biff < 8) {
11882 if(ixti > 10000) ixti-= 65536;
11883 if(ixti < 0) ixti = -ixti;
11884 return ixti == 0 ? "" : supbooks.XTI[ixti - 1];
11885 }
11886 if(!XTI) return "SH33TJSERR1";
11887 var o = "";
11888 if(opts.biff > 8) switch(supbooks[XTI[0]][0]) {
11889 case 0x0165: /* 'BrtSupSelf' */
11890 o = XTI[1] == -1 ? "#REF" : supbooks.SheetNames[XTI[1]];
11891 return XTI[1] == XTI[2] ? o : o + ":" + supbooks.SheetNames[XTI[2]];
11892 case 0x0166: /* 'BrtSupSame' */
11893 if(opts.SID != null) return supbooks.SheetNames[opts.SID];
11894 return "SH33TJSSAME" + supbooks[XTI[0]][0];
11895 case 0x0163: /* 'BrtSupBookSrc' */
11896 /* falls through */
11897 default: return "SH33TJSSRC" + supbooks[XTI[0]][0];
11898 }
11899 switch(supbooks[XTI[0]][0][0]) {
11900 case 0x0401:
11901 o = XTI[1] == -1 ? "#REF" : (supbooks.SheetNames[XTI[1]] || "SH33TJSERR3");
11902 return XTI[1] == XTI[2] ? o : o + ":" + supbooks.SheetNames[XTI[2]];
11903 case 0x3A01: return supbooks[XTI[0]].slice(1).map(function(name) { return name.Name; }).join(";;"); //return "SH33TJSERR8";
11904 default:
11905 if(!supbooks[XTI[0]][0][3]) return "SH33TJSERR2";
11906 o = XTI[1] == -1 ? "#REF" : (supbooks[XTI[0]][0][3][XTI[1]] || "SH33TJSERR4");
11907 return XTI[1] == XTI[2] ? o : o + ":" + supbooks[XTI[0]][0][3][XTI[2]];
11908 }
11909}
11910function get_ixti(supbooks, ixti/*:number*/, opts)/*:string*/ {
11911 var ixtiraw = get_ixti_raw(supbooks, ixti, opts);
11912 return ixtiraw == "#REF" ? ixtiraw : formula_quote_sheet_name(ixtiraw, opts);
11913}
11914function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, opts)/*:string*/ {
11915 var biff = (opts && opts.biff) || 8;
11916 var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}};
11917 var stack/*:Array<string>*/ = [], e1, e2, /*::type,*/ c/*:CellAddress*/, ixti=0, nameidx=0, r, sname="";
11918 if(!formula[0] || !formula[0][0]) return "";
11919 var last_sp = -1, sp = "";
11920 for(var ff = 0, fflen = formula[0].length; ff < fflen; ++ff) {
11921 var f = formula[0][ff];
11922 switch(f[0]) {
11923 case 'PtgUminus': /* [MS-XLS] 2.5.198.93 */
11924 stack.push("-" + stack.pop()); break;
11925 case 'PtgUplus': /* [MS-XLS] 2.5.198.95 */
11926 stack.push("+" + stack.pop()); break;
11927 case 'PtgPercent': /* [MS-XLS] 2.5.198.81 */
11928 stack.push(stack.pop() + "%"); break;
11929
11930 case 'PtgAdd': /* [MS-XLS] 2.5.198.26 */
11931 case 'PtgConcat': /* [MS-XLS] 2.5.198.43 */
11932 case 'PtgDiv': /* [MS-XLS] 2.5.198.45 */
11933 case 'PtgEq': /* [MS-XLS] 2.5.198.56 */
11934 case 'PtgGe': /* [MS-XLS] 2.5.198.64 */
11935 case 'PtgGt': /* [MS-XLS] 2.5.198.65 */
11936 case 'PtgLe': /* [MS-XLS] 2.5.198.68 */
11937 case 'PtgLt': /* [MS-XLS] 2.5.198.69 */
11938 case 'PtgMul': /* [MS-XLS] 2.5.198.75 */
11939 case 'PtgNe': /* [MS-XLS] 2.5.198.78 */
11940 case 'PtgPower': /* [MS-XLS] 2.5.198.82 */
11941 case 'PtgSub': /* [MS-XLS] 2.5.198.90 */
11942 e1 = stack.pop(); e2 = stack.pop();
11943 if(last_sp >= 0) {
11944 switch(formula[0][last_sp][1][0]) {
11945 case 0:
11946 // $FlowIgnore
11947 sp = fill(" ", formula[0][last_sp][1][1]); break;
11948 case 1:
11949 // $FlowIgnore
11950 sp = fill("\r", formula[0][last_sp][1][1]); break;
11951 default:
11952 sp = "";
11953 // $FlowIgnore
11954 if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + formula[0][last_sp][1][0]);
11955 }
11956 e2 = e2 + sp;
11957 last_sp = -1;
11958 }
11959 stack.push(e2+PtgBinOp[f[0]]+e1);
11960 break;
11961
11962 case 'PtgIsect': /* [MS-XLS] 2.5.198.67 */
11963 e1 = stack.pop(); e2 = stack.pop();
11964 stack.push(e2+" "+e1);
11965 break;
11966 case 'PtgUnion': /* [MS-XLS] 2.5.198.94 */
11967 e1 = stack.pop(); e2 = stack.pop();
11968 stack.push(e2+","+e1);
11969 break;
11970 case 'PtgRange': /* [MS-XLS] 2.5.198.83 */
11971 e1 = stack.pop(); e2 = stack.pop();
11972 stack.push(e2+":"+e1);
11973 break;
11974
11975 case 'PtgAttrChoose': /* [MS-XLS] 2.5.198.34 */
11976 break;
11977 case 'PtgAttrGoto': /* [MS-XLS] 2.5.198.35 */
11978 break;
11979 case 'PtgAttrIf': /* [MS-XLS] 2.5.198.36 */
11980 break;
11981 case 'PtgAttrIfError': /* [MS-XLSB] 2.5.97.28 */
11982 break;
11983
11984
11985 case 'PtgRef': /* [MS-XLS] 2.5.198.84 */
11986 /*::type = f[1][0]; */c = shift_cell_xls((f[1][1]/*:any*/), _range, opts);
11987 stack.push(encode_cell_xls(c, biff));
11988 break;
11989 case 'PtgRefN': /* [MS-XLS] 2.5.198.88 */
11990 /*::type = f[1][0]; */c = cell ? shift_cell_xls((f[1][1]/*:any*/), cell, opts) : (f[1][1]/*:any*/);
11991 stack.push(encode_cell_xls(c, biff));
11992 break;
11993 case 'PtgRef3d': /* [MS-XLS] 2.5.198.85 */
11994 /*::type = f[1][0]; */ixti = /*::Number(*/f[1][1]/*::)*/; c = shift_cell_xls((f[1][2]/*:any*/), _range, opts);
11995 sname = get_ixti(supbooks, ixti, opts);
11996 var w = sname; /* IE9 fails on defined names */ // eslint-disable-line no-unused-vars
11997 stack.push(sname + "!" + encode_cell_xls(c, biff));
11998 break;
11999
12000 case 'PtgFunc': /* [MS-XLS] 2.5.198.62 */
12001 case 'PtgFuncVar': /* [MS-XLS] 2.5.198.63 */
12002 /* f[1] = [argc, func, type] */
12003 var argc/*:number*/ = (f[1][0]/*:any*/), func/*:string*/ = (f[1][1]/*:any*/);
12004 if(!argc) argc = 0;
12005 argc &= 0x7F;
12006 var args = argc == 0 ? [] : stack.slice(-argc);
12007 stack.length -= argc;
12008 if(func === 'User') func = args.shift();
12009 stack.push(func + "(" + args.join(",") + ")");
12010 break;
12011
12012 case 'PtgBool': /* [MS-XLS] 2.5.198.42 */
12013 stack.push(f[1] ? "TRUE" : "FALSE"); break;
12014 case 'PtgInt': /* [MS-XLS] 2.5.198.66 */
12015 stack.push(/*::String(*/f[1]/*::)*/); break;
12016 case 'PtgNum': /* [MS-XLS] 2.5.198.79 TODO: precision? */
12017 stack.push(String(f[1])); break;
12018 case 'PtgStr': /* [MS-XLS] 2.5.198.89 */
12019 // $FlowIgnore
12020 stack.push('"' + f[1].replace(/"/g, '""') + '"'); break;
12021 case 'PtgErr': /* [MS-XLS] 2.5.198.57 */
12022 stack.push(/*::String(*/f[1]/*::)*/); break;
12023 case 'PtgAreaN': /* [MS-XLS] 2.5.198.31 TODO */
12024 /*::type = f[1][0]; */r = shift_range_xls(f[1][1], cell ? {s:cell} : _range, opts);
12025 stack.push(encode_range_xls((r/*:any*/), opts));
12026 break;
12027 case 'PtgArea': /* [MS-XLS] 2.5.198.27 TODO: fixed points */
12028 /*::type = f[1][0]; */r = shift_range_xls(f[1][1], _range, opts);
12029 stack.push(encode_range_xls((r/*:any*/), opts));
12030 break;
12031 case 'PtgArea3d': /* [MS-XLS] 2.5.198.28 TODO */
12032 /*::type = f[1][0]; */ixti = /*::Number(*/f[1][1]/*::)*/; r = f[1][2];
12033 sname = get_ixti(supbooks, ixti, opts);
12034 stack.push(sname + "!" + encode_range_xls((r/*:any*/), opts));
12035 break;
12036 case 'PtgAttrSum': /* [MS-XLS] 2.5.198.41 */
12037 stack.push("SUM(" + stack.pop() + ")");
12038 break;
12039
12040 case 'PtgAttrBaxcel': /* [MS-XLS] 2.5.198.33 */
12041 case 'PtgAttrSemi': /* [MS-XLS] 2.5.198.37 */
12042 break;
12043
12044 case 'PtgName': /* [MS-XLS] 2.5.198.76 ; [MS-XLSB] 2.5.97.60 TODO: revisions */
12045 /* f[1] = type, 0, nameindex */
12046 nameidx = (f[1][2]/*:any*/);
12047 var lbl = (supbooks.names||[])[nameidx-1] || (supbooks[0]||[])[nameidx];
12048 var name = lbl ? lbl.Name : "SH33TJSNAME" + String(nameidx);
12049 if(name in XLSXFutureFunctions) name = XLSXFutureFunctions[name];
12050 stack.push(name);
12051 break;
12052
12053 case 'PtgNameX': /* [MS-XLS] 2.5.198.77 ; [MS-XLSB] 2.5.97.61 TODO: revisions */
12054 /* f[1] = type, ixti, nameindex */
12055 var bookidx/*:number*/ = (f[1][1]/*:any*/); nameidx = (f[1][2]/*:any*/); var externbook;
12056 /* TODO: Properly handle missing values -- this should be using get_ixti_raw primarily */
12057 if(opts.biff <= 5) {
12058 if(bookidx < 0) bookidx = -bookidx;
12059 if(supbooks[bookidx]) externbook = supbooks[bookidx][nameidx];
12060 } else {
12061 var o = "";
12062 if(((supbooks[bookidx]||[])[0]||[])[0] == 0x3A01){/* empty */}
12063 else if(((supbooks[bookidx]||[])[0]||[])[0] == 0x0401){
12064 if(supbooks[bookidx][nameidx] && supbooks[bookidx][nameidx].itab > 0) {
12065 o = supbooks.SheetNames[supbooks[bookidx][nameidx].itab-1] + "!";
12066 }
12067 }
12068 else o = supbooks.SheetNames[nameidx-1]+ "!";
12069 if(supbooks[bookidx] && supbooks[bookidx][nameidx]) o += supbooks[bookidx][nameidx].Name;
12070 else if(supbooks[0] && supbooks[0][nameidx]) o += supbooks[0][nameidx].Name;
12071 else {
12072 var ixtidata = (get_ixti_raw(supbooks, bookidx, opts)||"").split(";;");
12073 if(ixtidata[nameidx - 1]) o = ixtidata[nameidx - 1]; // TODO: confirm this is correct
12074 else o += "SH33TJSERRX";
12075 }
12076 stack.push(o);
12077 break;
12078 }
12079 if(!externbook) externbook = {Name: "SH33TJSERRY"};
12080 stack.push(externbook.Name);
12081 break;
12082
12083 case 'PtgParen': /* [MS-XLS] 2.5.198.80 */
12084 var lp = '(', rp = ')';
12085 if(last_sp >= 0) {
12086 sp = "";
12087 switch(formula[0][last_sp][1][0]) {
12088 // $FlowIgnore
12089 case 2: lp = fill(" ", formula[0][last_sp][1][1]) + lp; break;
12090 // $FlowIgnore
12091 case 3: lp = fill("\r", formula[0][last_sp][1][1]) + lp; break;
12092 // $FlowIgnore
12093 case 4: rp = fill(" ", formula[0][last_sp][1][1]) + rp; break;
12094 // $FlowIgnore
12095 case 5: rp = fill("\r", formula[0][last_sp][1][1]) + rp; break;
12096 default:
12097 // $FlowIgnore
12098 if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + formula[0][last_sp][1][0]);
12099 }
12100 last_sp = -1;
12101 }
12102 stack.push(lp + stack.pop() + rp); break;
12103
12104 case 'PtgRefErr': /* [MS-XLS] 2.5.198.86 */
12105 stack.push('#REF!'); break;
12106
12107 case 'PtgRefErr3d': /* [MS-XLS] 2.5.198.87 */
12108 stack.push('#REF!'); break;
12109
12110 case 'PtgExp': /* [MS-XLS] 2.5.198.58 TODO */
12111 c = {c:(f[1][1]/*:any*/),r:(f[1][0]/*:any*/)};
12112 var q = ({c: cell.c, r:cell.r}/*:any*/);
12113 if(supbooks.sharedf[encode_cell(c)]) {
12114 var parsedf = (supbooks.sharedf[encode_cell(c)]);
12115 stack.push(stringify_formula(parsedf, _range, q, supbooks, opts));
12116 } else {
12117 var fnd = false;
12118 for(e1=0;e1!=supbooks.arrayf.length; ++e1) {
12119 /* TODO: should be something like range_has */
12120 e2 = supbooks.arrayf[e1];
12121 if(c.c < e2[0].s.c || c.c > e2[0].e.c) continue;
12122 if(c.r < e2[0].s.r || c.r > e2[0].e.r) continue;
12123 stack.push(stringify_formula(e2[1], _range, q, supbooks, opts));
12124 fnd = true;
12125 break;
12126 }
12127 if(!fnd) stack.push(/*::String(*/f[1]/*::)*/);
12128 }
12129 break;
12130
12131 case 'PtgArray': /* [MS-XLS] 2.5.198.32 TODO */
12132 stack.push("{" + stringify_array(/*::(*/f[1]/*:: :any)*/) + "}");
12133 break;
12134
12135 case 'PtgMemArea': /* [MS-XLS] 2.5.198.70 TODO: confirm this is a non-display */
12136 //stack.push("(" + f[2].map(encode_range).join(",") + ")");
12137 break;
12138
12139 case 'PtgAttrSpace': /* [MS-XLS] 2.5.198.38 */
12140 case 'PtgAttrSpaceSemi': /* [MS-XLS] 2.5.198.39 */
12141 last_sp = ff;
12142 break;
12143
12144 case 'PtgTbl': /* [MS-XLS] 2.5.198.92 TODO */
12145 break;
12146
12147 case 'PtgMemErr': /* [MS-XLS] 2.5.198.71 */
12148 break;
12149
12150 case 'PtgMissArg': /* [MS-XLS] 2.5.198.74 */
12151 stack.push("");
12152 break;
12153
12154 case 'PtgAreaErr': /* [MS-XLS] 2.5.198.29 */
12155 stack.push("#REF!"); break;
12156
12157 case 'PtgAreaErr3d': /* [MS-XLS] 2.5.198.30 */
12158 stack.push("#REF!"); break;
12159
12160 case 'PtgList': /* [MS-XLSB] 2.5.97.52 */
12161 // $FlowIgnore
12162 stack.push("Table" + f[1].idx + "[#" + f[1].rt + "]");
12163 break;
12164
12165 case 'PtgMemAreaN':
12166 case 'PtgMemNoMemN':
12167 case 'PtgAttrNoop':
12168 case 'PtgSheet':
12169 case 'PtgEndSheet':
12170 break;
12171
12172 case 'PtgMemFunc': /* [MS-XLS] 2.5.198.72 TODO */
12173 break;
12174 case 'PtgMemNoMem': /* [MS-XLS] 2.5.198.73 TODO */
12175 break;
12176
12177 case 'PtgElfCol': /* [MS-XLS] 2.5.198.46 */
12178 case 'PtgElfColS': /* [MS-XLS] 2.5.198.47 */
12179 case 'PtgElfColSV': /* [MS-XLS] 2.5.198.48 */
12180 case 'PtgElfColV': /* [MS-XLS] 2.5.198.49 */
12181 case 'PtgElfLel': /* [MS-XLS] 2.5.198.50 */
12182 case 'PtgElfRadical': /* [MS-XLS] 2.5.198.51 */
12183 case 'PtgElfRadicalLel': /* [MS-XLS] 2.5.198.52 */
12184 case 'PtgElfRadicalS': /* [MS-XLS] 2.5.198.53 */
12185 case 'PtgElfRw': /* [MS-XLS] 2.5.198.54 */
12186 case 'PtgElfRwV': /* [MS-XLS] 2.5.198.55 */
12187 throw new Error("Unsupported ELFs");
12188
12189 case 'PtgSxName': /* [MS-XLS] 2.5.198.91 TODO -- find a test case */
12190 throw new Error('Unrecognized Formula Token: ' + String(f));
12191 default: throw new Error('Unrecognized Formula Token: ' + String(f));
12192 }
12193 var PtgNonDisp = ['PtgAttrSpace', 'PtgAttrSpaceSemi', 'PtgAttrGoto'];
12194 if(opts.biff != 3) if(last_sp >= 0 && PtgNonDisp.indexOf(formula[0][ff][0]) == -1) {
12195 f = formula[0][last_sp];
12196 var _left = true;
12197 switch(f[1][0]) {
12198 /* note: some bad XLSB files omit the PtgParen */
12199 case 4: _left = false;
12200 /* falls through */
12201 case 0:
12202 // $FlowIgnore
12203 sp = fill(" ", f[1][1]); break;
12204 case 5: _left = false;
12205 /* falls through */
12206 case 1:
12207 // $FlowIgnore
12208 sp = fill("\r", f[1][1]); break;
12209 default:
12210 sp = "";
12211 // $FlowIgnore
12212 if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + f[1][0]);
12213 }
12214 stack.push((_left ? sp : "") + stack.pop() + (_left ? "" : sp));
12215 last_sp = -1;
12216 }
12217 }
12218 if(stack.length > 1 && opts.WTF) throw new Error("bad formula stack");
12219 return stack[0];
12220}
12221
12222/* [MS-XLS] 2.5.198.1 TODO */
12223function parse_ArrayParsedFormula(blob, length, opts/*::, ref*/) {
12224 var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
12225 var rgcb, cce = blob.read_shift(len); // length of rgce
12226 if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
12227 var rgce = parse_Rgce(blob, cce, opts);
12228 if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
12229 blob.l = target;
12230 return [rgce, rgcb];
12231}
12232
12233/* [MS-XLS] 2.5.198.3 TODO */
12234function parse_XLSCellParsedFormula(blob, length, opts) {
12235 var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
12236 var rgcb, cce = blob.read_shift(len); // length of rgce
12237 if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
12238 var rgce = parse_Rgce(blob, cce, opts);
12239 if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
12240 blob.l = target;
12241 return [rgce, rgcb];
12242}
12243
12244/* [MS-XLS] 2.5.198.21 */
12245function parse_NameParsedFormula(blob, length, opts, cce) {
12246 var target = blob.l + length;
12247 var rgce = parse_Rgce(blob, cce, opts);
12248 var rgcb;
12249 if(target !== blob.l) rgcb = parse_RgbExtra(blob, target - blob.l, rgce, opts);
12250 return [rgce, rgcb];
12251}
12252
12253/* [MS-XLS] 2.5.198.118 TODO */
12254function parse_SharedParsedFormula(blob, length, opts) {
12255 var target = blob.l + length;
12256 var rgcb, cce = blob.read_shift(2); // length of rgce
12257 var rgce = parse_Rgce(blob, cce, opts);
12258 if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
12259 if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
12260 return [rgce, rgcb];
12261}
12262
12263/* [MS-XLS] 2.5.133 TODO: how to emit empty strings? */
12264function parse_FormulaValue(blob/*::, length*/) {
12265 var b;
12266 if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return [parse_Xnum(blob),'n'];
12267 switch(blob[blob.l]) {
12268 case 0x00: blob.l += 8; return ["String", 's'];
12269 case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return [b,'b'];
12270 case 0x02: b = blob[blob.l+2]; blob.l += 8; return [b,'e'];
12271 case 0x03: blob.l += 8; return ["",'s'];
12272 }
12273 return [];
12274}
12275function write_FormulaValue(value) {
12276 if(value == null) {
12277 // Blank String Value
12278 var o = new_buf(8);
12279 o.write_shift(1, 0x03);
12280 o.write_shift(1, 0);
12281 o.write_shift(2, 0);
12282 o.write_shift(2, 0);
12283 o.write_shift(2, 0xFFFF);
12284 return o;
12285 } else if(typeof value == "number") return write_Xnum(value);
12286 return write_Xnum(0);
12287}
12288
12289/* [MS-XLS] 2.4.127 TODO */
12290function parse_Formula(blob, length, opts) {
12291 var end = blob.l + length;
12292 var cell = parse_XLSCell(blob, 6);
12293 if(opts.biff == 2) ++blob.l;
12294 var val = parse_FormulaValue(blob,8);
12295 var flags = blob.read_shift(1);
12296 if(opts.biff != 2) {
12297 blob.read_shift(1);
12298 if(opts.biff >= 5) {
12299 /*var chn = */blob.read_shift(4);
12300 }
12301 }
12302 var cbf = parse_XLSCellParsedFormula(blob, end - blob.l, opts);
12303 return {cell:cell, val:val[0], formula:cbf, shared: (flags >> 3) & 1, tt:val[1]};
12304}
12305function write_Formula(cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, os/*:number*/) {
12306 // Cell
12307 var o1 = write_XLSCell(R, C, os);
12308
12309 // FormulaValue
12310 var o2 = write_FormulaValue(cell.v);
12311
12312 // flags + cache
12313 var o3 = new_buf(6);
12314 var flags = 0x01 | 0x20;
12315 o3.write_shift(2, flags);
12316 o3.write_shift(4, 0);
12317
12318 // CellParsedFormula
12319 var bf = new_buf(cell.bf.length);
12320 for(var i = 0; i < cell.bf.length; ++i) bf[i] = cell.bf[i];
12321
12322 var out = bconcat([o1, o2, o3, bf]);
12323 return out;
12324}
12325
12326
12327/* XLSB Parsed Formula records have the same shape */
12328function parse_XLSBParsedFormula(data, length, opts) {
12329 var cce = data.read_shift(4);
12330 var rgce = parse_Rgce(data, cce, opts);
12331 var cb = data.read_shift(4);
12332 var rgcb = cb > 0 ? parse_RgbExtra(data, cb, rgce, opts) : null;
12333 return [rgce, rgcb];
12334}
12335
12336/* [MS-XLSB] 2.5.97.1 ArrayParsedFormula */
12337var parse_XLSBArrayParsedFormula = parse_XLSBParsedFormula;
12338/* [MS-XLSB] 2.5.97.4 CellParsedFormula */
12339var parse_XLSBCellParsedFormula = parse_XLSBParsedFormula;
12340/* [MS-XLSB] 2.5.97.8 DVParsedFormula */
12341//var parse_XLSBDVParsedFormula = parse_XLSBParsedFormula;
12342/* [MS-XLSB] 2.5.97.9 FRTParsedFormula */
12343//var parse_XLSBFRTParsedFormula = parse_XLSBParsedFormula2;
12344/* [MS-XLSB] 2.5.97.12 NameParsedFormula */
12345var parse_XLSBNameParsedFormula = parse_XLSBParsedFormula;
12346/* [MS-XLSB] 2.5.97.98 SharedParsedFormula */
12347var parse_XLSBSharedParsedFormula = parse_XLSBParsedFormula;
12348/* [MS-XLS] 2.5.198.4 */
12349var Cetab = {
12350 /*::[*/0x0000/*::]*/: 'BEEP',
12351 /*::[*/0x0001/*::]*/: 'OPEN',
12352 /*::[*/0x0002/*::]*/: 'OPEN.LINKS',
12353 /*::[*/0x0003/*::]*/: 'CLOSE.ALL',
12354 /*::[*/0x0004/*::]*/: 'SAVE',
12355 /*::[*/0x0005/*::]*/: 'SAVE.AS',
12356 /*::[*/0x0006/*::]*/: 'FILE.DELETE',
12357 /*::[*/0x0007/*::]*/: 'PAGE.SETUP',
12358 /*::[*/0x0008/*::]*/: 'PRINT',
12359 /*::[*/0x0009/*::]*/: 'PRINTER.SETUP',
12360 /*::[*/0x000A/*::]*/: 'QUIT',
12361 /*::[*/0x000B/*::]*/: 'NEW.WINDOW',
12362 /*::[*/0x000C/*::]*/: 'ARRANGE.ALL',
12363 /*::[*/0x000D/*::]*/: 'WINDOW.SIZE',
12364 /*::[*/0x000E/*::]*/: 'WINDOW.MOVE',
12365 /*::[*/0x000F/*::]*/: 'FULL',
12366 /*::[*/0x0010/*::]*/: 'CLOSE',
12367 /*::[*/0x0011/*::]*/: 'RUN',
12368 /*::[*/0x0016/*::]*/: 'SET.PRINT.AREA',
12369 /*::[*/0x0017/*::]*/: 'SET.PRINT.TITLES',
12370 /*::[*/0x0018/*::]*/: 'SET.PAGE.BREAK',
12371 /*::[*/0x0019/*::]*/: 'REMOVE.PAGE.BREAK',
12372 /*::[*/0x001A/*::]*/: 'FONT',
12373 /*::[*/0x001B/*::]*/: 'DISPLAY',
12374 /*::[*/0x001C/*::]*/: 'PROTECT.DOCUMENT',
12375 /*::[*/0x001D/*::]*/: 'PRECISION',
12376 /*::[*/0x001E/*::]*/: 'A1.R1C1',
12377 /*::[*/0x001F/*::]*/: 'CALCULATE.NOW',
12378 /*::[*/0x0020/*::]*/: 'CALCULATION',
12379 /*::[*/0x0022/*::]*/: 'DATA.FIND',
12380 /*::[*/0x0023/*::]*/: 'EXTRACT',
12381 /*::[*/0x0024/*::]*/: 'DATA.DELETE',
12382 /*::[*/0x0025/*::]*/: 'SET.DATABASE',
12383 /*::[*/0x0026/*::]*/: 'SET.CRITERIA',
12384 /*::[*/0x0027/*::]*/: 'SORT',
12385 /*::[*/0x0028/*::]*/: 'DATA.SERIES',
12386 /*::[*/0x0029/*::]*/: 'TABLE',
12387 /*::[*/0x002A/*::]*/: 'FORMAT.NUMBER',
12388 /*::[*/0x002B/*::]*/: 'ALIGNMENT',
12389 /*::[*/0x002C/*::]*/: 'STYLE',
12390 /*::[*/0x002D/*::]*/: 'BORDER',
12391 /*::[*/0x002E/*::]*/: 'CELL.PROTECTION',
12392 /*::[*/0x002F/*::]*/: 'COLUMN.WIDTH',
12393 /*::[*/0x0030/*::]*/: 'UNDO',
12394 /*::[*/0x0031/*::]*/: 'CUT',
12395 /*::[*/0x0032/*::]*/: 'COPY',
12396 /*::[*/0x0033/*::]*/: 'PASTE',
12397 /*::[*/0x0034/*::]*/: 'CLEAR',
12398 /*::[*/0x0035/*::]*/: 'PASTE.SPECIAL',
12399 /*::[*/0x0036/*::]*/: 'EDIT.DELETE',
12400 /*::[*/0x0037/*::]*/: 'INSERT',
12401 /*::[*/0x0038/*::]*/: 'FILL.RIGHT',
12402 /*::[*/0x0039/*::]*/: 'FILL.DOWN',
12403 /*::[*/0x003D/*::]*/: 'DEFINE.NAME',
12404 /*::[*/0x003E/*::]*/: 'CREATE.NAMES',
12405 /*::[*/0x003F/*::]*/: 'FORMULA.GOTO',
12406 /*::[*/0x0040/*::]*/: 'FORMULA.FIND',
12407 /*::[*/0x0041/*::]*/: 'SELECT.LAST.CELL',
12408 /*::[*/0x0042/*::]*/: 'SHOW.ACTIVE.CELL',
12409 /*::[*/0x0043/*::]*/: 'GALLERY.AREA',
12410 /*::[*/0x0044/*::]*/: 'GALLERY.BAR',
12411 /*::[*/0x0045/*::]*/: 'GALLERY.COLUMN',
12412 /*::[*/0x0046/*::]*/: 'GALLERY.LINE',
12413 /*::[*/0x0047/*::]*/: 'GALLERY.PIE',
12414 /*::[*/0x0048/*::]*/: 'GALLERY.SCATTER',
12415 /*::[*/0x0049/*::]*/: 'COMBINATION',
12416 /*::[*/0x004A/*::]*/: 'PREFERRED',
12417 /*::[*/0x004B/*::]*/: 'ADD.OVERLAY',
12418 /*::[*/0x004C/*::]*/: 'GRIDLINES',
12419 /*::[*/0x004D/*::]*/: 'SET.PREFERRED',
12420 /*::[*/0x004E/*::]*/: 'AXES',
12421 /*::[*/0x004F/*::]*/: 'LEGEND',
12422 /*::[*/0x0050/*::]*/: 'ATTACH.TEXT',
12423 /*::[*/0x0051/*::]*/: 'ADD.ARROW',
12424 /*::[*/0x0052/*::]*/: 'SELECT.CHART',
12425 /*::[*/0x0053/*::]*/: 'SELECT.PLOT.AREA',
12426 /*::[*/0x0054/*::]*/: 'PATTERNS',
12427 /*::[*/0x0055/*::]*/: 'MAIN.CHART',
12428 /*::[*/0x0056/*::]*/: 'OVERLAY',
12429 /*::[*/0x0057/*::]*/: 'SCALE',
12430 /*::[*/0x0058/*::]*/: 'FORMAT.LEGEND',
12431 /*::[*/0x0059/*::]*/: 'FORMAT.TEXT',
12432 /*::[*/0x005A/*::]*/: 'EDIT.REPEAT',
12433 /*::[*/0x005B/*::]*/: 'PARSE',
12434 /*::[*/0x005C/*::]*/: 'JUSTIFY',
12435 /*::[*/0x005D/*::]*/: 'HIDE',
12436 /*::[*/0x005E/*::]*/: 'UNHIDE',
12437 /*::[*/0x005F/*::]*/: 'WORKSPACE',
12438 /*::[*/0x0060/*::]*/: 'FORMULA',
12439 /*::[*/0x0061/*::]*/: 'FORMULA.FILL',
12440 /*::[*/0x0062/*::]*/: 'FORMULA.ARRAY',
12441 /*::[*/0x0063/*::]*/: 'DATA.FIND.NEXT',
12442 /*::[*/0x0064/*::]*/: 'DATA.FIND.PREV',
12443 /*::[*/0x0065/*::]*/: 'FORMULA.FIND.NEXT',
12444 /*::[*/0x0066/*::]*/: 'FORMULA.FIND.PREV',
12445 /*::[*/0x0067/*::]*/: 'ACTIVATE',
12446 /*::[*/0x0068/*::]*/: 'ACTIVATE.NEXT',
12447 /*::[*/0x0069/*::]*/: 'ACTIVATE.PREV',
12448 /*::[*/0x006A/*::]*/: 'UNLOCKED.NEXT',
12449 /*::[*/0x006B/*::]*/: 'UNLOCKED.PREV',
12450 /*::[*/0x006C/*::]*/: 'COPY.PICTURE',
12451 /*::[*/0x006D/*::]*/: 'SELECT',
12452 /*::[*/0x006E/*::]*/: 'DELETE.NAME',
12453 /*::[*/0x006F/*::]*/: 'DELETE.FORMAT',
12454 /*::[*/0x0070/*::]*/: 'VLINE',
12455 /*::[*/0x0071/*::]*/: 'HLINE',
12456 /*::[*/0x0072/*::]*/: 'VPAGE',
12457 /*::[*/0x0073/*::]*/: 'HPAGE',
12458 /*::[*/0x0074/*::]*/: 'VSCROLL',
12459 /*::[*/0x0075/*::]*/: 'HSCROLL',
12460 /*::[*/0x0076/*::]*/: 'ALERT',
12461 /*::[*/0x0077/*::]*/: 'NEW',
12462 /*::[*/0x0078/*::]*/: 'CANCEL.COPY',
12463 /*::[*/0x0079/*::]*/: 'SHOW.CLIPBOARD',
12464 /*::[*/0x007A/*::]*/: 'MESSAGE',
12465 /*::[*/0x007C/*::]*/: 'PASTE.LINK',
12466 /*::[*/0x007D/*::]*/: 'APP.ACTIVATE',
12467 /*::[*/0x007E/*::]*/: 'DELETE.ARROW',
12468 /*::[*/0x007F/*::]*/: 'ROW.HEIGHT',
12469 /*::[*/0x0080/*::]*/: 'FORMAT.MOVE',
12470 /*::[*/0x0081/*::]*/: 'FORMAT.SIZE',
12471 /*::[*/0x0082/*::]*/: 'FORMULA.REPLACE',
12472 /*::[*/0x0083/*::]*/: 'SEND.KEYS',
12473 /*::[*/0x0084/*::]*/: 'SELECT.SPECIAL',
12474 /*::[*/0x0085/*::]*/: 'APPLY.NAMES',
12475 /*::[*/0x0086/*::]*/: 'REPLACE.FONT',
12476 /*::[*/0x0087/*::]*/: 'FREEZE.PANES',
12477 /*::[*/0x0088/*::]*/: 'SHOW.INFO',
12478 /*::[*/0x0089/*::]*/: 'SPLIT',
12479 /*::[*/0x008A/*::]*/: 'ON.WINDOW',
12480 /*::[*/0x008B/*::]*/: 'ON.DATA',
12481 /*::[*/0x008C/*::]*/: 'DISABLE.INPUT',
12482 /*::[*/0x008E/*::]*/: 'OUTLINE',
12483 /*::[*/0x008F/*::]*/: 'LIST.NAMES',
12484 /*::[*/0x0090/*::]*/: 'FILE.CLOSE',
12485 /*::[*/0x0091/*::]*/: 'SAVE.WORKBOOK',
12486 /*::[*/0x0092/*::]*/: 'DATA.FORM',
12487 /*::[*/0x0093/*::]*/: 'COPY.CHART',
12488 /*::[*/0x0094/*::]*/: 'ON.TIME',
12489 /*::[*/0x0095/*::]*/: 'WAIT',
12490 /*::[*/0x0096/*::]*/: 'FORMAT.FONT',
12491 /*::[*/0x0097/*::]*/: 'FILL.UP',
12492 /*::[*/0x0098/*::]*/: 'FILL.LEFT',
12493 /*::[*/0x0099/*::]*/: 'DELETE.OVERLAY',
12494 /*::[*/0x009B/*::]*/: 'SHORT.MENUS',
12495 /*::[*/0x009F/*::]*/: 'SET.UPDATE.STATUS',
12496 /*::[*/0x00A1/*::]*/: 'COLOR.PALETTE',
12497 /*::[*/0x00A2/*::]*/: 'DELETE.STYLE',
12498 /*::[*/0x00A3/*::]*/: 'WINDOW.RESTORE',
12499 /*::[*/0x00A4/*::]*/: 'WINDOW.MAXIMIZE',
12500 /*::[*/0x00A6/*::]*/: 'CHANGE.LINK',
12501 /*::[*/0x00A7/*::]*/: 'CALCULATE.DOCUMENT',
12502 /*::[*/0x00A8/*::]*/: 'ON.KEY',
12503 /*::[*/0x00A9/*::]*/: 'APP.RESTORE',
12504 /*::[*/0x00AA/*::]*/: 'APP.MOVE',
12505 /*::[*/0x00AB/*::]*/: 'APP.SIZE',
12506 /*::[*/0x00AC/*::]*/: 'APP.MINIMIZE',
12507 /*::[*/0x00AD/*::]*/: 'APP.MAXIMIZE',
12508 /*::[*/0x00AE/*::]*/: 'BRING.TO.FRONT',
12509 /*::[*/0x00AF/*::]*/: 'SEND.TO.BACK',
12510 /*::[*/0x00B9/*::]*/: 'MAIN.CHART.TYPE',
12511 /*::[*/0x00BA/*::]*/: 'OVERLAY.CHART.TYPE',
12512 /*::[*/0x00BB/*::]*/: 'SELECT.END',
12513 /*::[*/0x00BC/*::]*/: 'OPEN.MAIL',
12514 /*::[*/0x00BD/*::]*/: 'SEND.MAIL',
12515 /*::[*/0x00BE/*::]*/: 'STANDARD.FONT',
12516 /*::[*/0x00BF/*::]*/: 'CONSOLIDATE',
12517 /*::[*/0x00C0/*::]*/: 'SORT.SPECIAL',
12518 /*::[*/0x00C1/*::]*/: 'GALLERY.3D.AREA',
12519 /*::[*/0x00C2/*::]*/: 'GALLERY.3D.COLUMN',
12520 /*::[*/0x00C3/*::]*/: 'GALLERY.3D.LINE',
12521 /*::[*/0x00C4/*::]*/: 'GALLERY.3D.PIE',
12522 /*::[*/0x00C5/*::]*/: 'VIEW.3D',
12523 /*::[*/0x00C6/*::]*/: 'GOAL.SEEK',
12524 /*::[*/0x00C7/*::]*/: 'WORKGROUP',
12525 /*::[*/0x00C8/*::]*/: 'FILL.GROUP',
12526 /*::[*/0x00C9/*::]*/: 'UPDATE.LINK',
12527 /*::[*/0x00CA/*::]*/: 'PROMOTE',
12528 /*::[*/0x00CB/*::]*/: 'DEMOTE',
12529 /*::[*/0x00CC/*::]*/: 'SHOW.DETAIL',
12530 /*::[*/0x00CE/*::]*/: 'UNGROUP',
12531 /*::[*/0x00CF/*::]*/: 'OBJECT.PROPERTIES',
12532 /*::[*/0x00D0/*::]*/: 'SAVE.NEW.OBJECT',
12533 /*::[*/0x00D1/*::]*/: 'SHARE',
12534 /*::[*/0x00D2/*::]*/: 'SHARE.NAME',
12535 /*::[*/0x00D3/*::]*/: 'DUPLICATE',
12536 /*::[*/0x00D4/*::]*/: 'APPLY.STYLE',
12537 /*::[*/0x00D5/*::]*/: 'ASSIGN.TO.OBJECT',
12538 /*::[*/0x00D6/*::]*/: 'OBJECT.PROTECTION',
12539 /*::[*/0x00D7/*::]*/: 'HIDE.OBJECT',
12540 /*::[*/0x00D8/*::]*/: 'SET.EXTRACT',
12541 /*::[*/0x00D9/*::]*/: 'CREATE.PUBLISHER',
12542 /*::[*/0x00DA/*::]*/: 'SUBSCRIBE.TO',
12543 /*::[*/0x00DB/*::]*/: 'ATTRIBUTES',
12544 /*::[*/0x00DC/*::]*/: 'SHOW.TOOLBAR',
12545 /*::[*/0x00DE/*::]*/: 'PRINT.PREVIEW',
12546 /*::[*/0x00DF/*::]*/: 'EDIT.COLOR',
12547 /*::[*/0x00E0/*::]*/: 'SHOW.LEVELS',
12548 /*::[*/0x00E1/*::]*/: 'FORMAT.MAIN',
12549 /*::[*/0x00E2/*::]*/: 'FORMAT.OVERLAY',
12550 /*::[*/0x00E3/*::]*/: 'ON.RECALC',
12551 /*::[*/0x00E4/*::]*/: 'EDIT.SERIES',
12552 /*::[*/0x00E5/*::]*/: 'DEFINE.STYLE',
12553 /*::[*/0x00F0/*::]*/: 'LINE.PRINT',
12554 /*::[*/0x00F3/*::]*/: 'ENTER.DATA',
12555 /*::[*/0x00F9/*::]*/: 'GALLERY.RADAR',
12556 /*::[*/0x00FA/*::]*/: 'MERGE.STYLES',
12557 /*::[*/0x00FB/*::]*/: 'EDITION.OPTIONS',
12558 /*::[*/0x00FC/*::]*/: 'PASTE.PICTURE',
12559 /*::[*/0x00FD/*::]*/: 'PASTE.PICTURE.LINK',
12560 /*::[*/0x00FE/*::]*/: 'SPELLING',
12561 /*::[*/0x0100/*::]*/: 'ZOOM',
12562 /*::[*/0x0103/*::]*/: 'INSERT.OBJECT',
12563 /*::[*/0x0104/*::]*/: 'WINDOW.MINIMIZE',
12564 /*::[*/0x0109/*::]*/: 'SOUND.NOTE',
12565 /*::[*/0x010A/*::]*/: 'SOUND.PLAY',
12566 /*::[*/0x010B/*::]*/: 'FORMAT.SHAPE',
12567 /*::[*/0x010C/*::]*/: 'EXTEND.POLYGON',
12568 /*::[*/0x010D/*::]*/: 'FORMAT.AUTO',
12569 /*::[*/0x0110/*::]*/: 'GALLERY.3D.BAR',
12570 /*::[*/0x0111/*::]*/: 'GALLERY.3D.SURFACE',
12571 /*::[*/0x0112/*::]*/: 'FILL.AUTO',
12572 /*::[*/0x0114/*::]*/: 'CUSTOMIZE.TOOLBAR',
12573 /*::[*/0x0115/*::]*/: 'ADD.TOOL',
12574 /*::[*/0x0116/*::]*/: 'EDIT.OBJECT',
12575 /*::[*/0x0117/*::]*/: 'ON.DOUBLECLICK',
12576 /*::[*/0x0118/*::]*/: 'ON.ENTRY',
12577 /*::[*/0x0119/*::]*/: 'WORKBOOK.ADD',
12578 /*::[*/0x011A/*::]*/: 'WORKBOOK.MOVE',
12579 /*::[*/0x011B/*::]*/: 'WORKBOOK.COPY',
12580 /*::[*/0x011C/*::]*/: 'WORKBOOK.OPTIONS',
12581 /*::[*/0x011D/*::]*/: 'SAVE.WORKSPACE',
12582 /*::[*/0x0120/*::]*/: 'CHART.WIZARD',
12583 /*::[*/0x0121/*::]*/: 'DELETE.TOOL',
12584 /*::[*/0x0122/*::]*/: 'MOVE.TOOL',
12585 /*::[*/0x0123/*::]*/: 'WORKBOOK.SELECT',
12586 /*::[*/0x0124/*::]*/: 'WORKBOOK.ACTIVATE',
12587 /*::[*/0x0125/*::]*/: 'ASSIGN.TO.TOOL',
12588 /*::[*/0x0127/*::]*/: 'COPY.TOOL',
12589 /*::[*/0x0128/*::]*/: 'RESET.TOOL',
12590 /*::[*/0x0129/*::]*/: 'CONSTRAIN.NUMERIC',
12591 /*::[*/0x012A/*::]*/: 'PASTE.TOOL',
12592 /*::[*/0x012E/*::]*/: 'WORKBOOK.NEW',
12593 /*::[*/0x0131/*::]*/: 'SCENARIO.CELLS',
12594 /*::[*/0x0132/*::]*/: 'SCENARIO.DELETE',
12595 /*::[*/0x0133/*::]*/: 'SCENARIO.ADD',
12596 /*::[*/0x0134/*::]*/: 'SCENARIO.EDIT',
12597 /*::[*/0x0135/*::]*/: 'SCENARIO.SHOW',
12598 /*::[*/0x0136/*::]*/: 'SCENARIO.SHOW.NEXT',
12599 /*::[*/0x0137/*::]*/: 'SCENARIO.SUMMARY',
12600 /*::[*/0x0138/*::]*/: 'PIVOT.TABLE.WIZARD',
12601 /*::[*/0x0139/*::]*/: 'PIVOT.FIELD.PROPERTIES',
12602 /*::[*/0x013A/*::]*/: 'PIVOT.FIELD',
12603 /*::[*/0x013B/*::]*/: 'PIVOT.ITEM',
12604 /*::[*/0x013C/*::]*/: 'PIVOT.ADD.FIELDS',
12605 /*::[*/0x013E/*::]*/: 'OPTIONS.CALCULATION',
12606 /*::[*/0x013F/*::]*/: 'OPTIONS.EDIT',
12607 /*::[*/0x0140/*::]*/: 'OPTIONS.VIEW',
12608 /*::[*/0x0141/*::]*/: 'ADDIN.MANAGER',
12609 /*::[*/0x0142/*::]*/: 'MENU.EDITOR',
12610 /*::[*/0x0143/*::]*/: 'ATTACH.TOOLBARS',
12611 /*::[*/0x0144/*::]*/: 'VBAActivate',
12612 /*::[*/0x0145/*::]*/: 'OPTIONS.CHART',
12613 /*::[*/0x0148/*::]*/: 'VBA.INSERT.FILE',
12614 /*::[*/0x014A/*::]*/: 'VBA.PROCEDURE.DEFINITION',
12615 /*::[*/0x0150/*::]*/: 'ROUTING.SLIP',
12616 /*::[*/0x0152/*::]*/: 'ROUTE.DOCUMENT',
12617 /*::[*/0x0153/*::]*/: 'MAIL.LOGON',
12618 /*::[*/0x0156/*::]*/: 'INSERT.PICTURE',
12619 /*::[*/0x0157/*::]*/: 'EDIT.TOOL',
12620 /*::[*/0x0158/*::]*/: 'GALLERY.DOUGHNUT',
12621 /*::[*/0x015E/*::]*/: 'CHART.TREND',
12622 /*::[*/0x0160/*::]*/: 'PIVOT.ITEM.PROPERTIES',
12623 /*::[*/0x0162/*::]*/: 'WORKBOOK.INSERT',
12624 /*::[*/0x0163/*::]*/: 'OPTIONS.TRANSITION',
12625 /*::[*/0x0164/*::]*/: 'OPTIONS.GENERAL',
12626 /*::[*/0x0172/*::]*/: 'FILTER.ADVANCED',
12627 /*::[*/0x0175/*::]*/: 'MAIL.ADD.MAILER',
12628 /*::[*/0x0176/*::]*/: 'MAIL.DELETE.MAILER',
12629 /*::[*/0x0177/*::]*/: 'MAIL.REPLY',
12630 /*::[*/0x0178/*::]*/: 'MAIL.REPLY.ALL',
12631 /*::[*/0x0179/*::]*/: 'MAIL.FORWARD',
12632 /*::[*/0x017A/*::]*/: 'MAIL.NEXT.LETTER',
12633 /*::[*/0x017B/*::]*/: 'DATA.LABEL',
12634 /*::[*/0x017C/*::]*/: 'INSERT.TITLE',
12635 /*::[*/0x017D/*::]*/: 'FONT.PROPERTIES',
12636 /*::[*/0x017E/*::]*/: 'MACRO.OPTIONS',
12637 /*::[*/0x017F/*::]*/: 'WORKBOOK.HIDE',
12638 /*::[*/0x0180/*::]*/: 'WORKBOOK.UNHIDE',
12639 /*::[*/0x0181/*::]*/: 'WORKBOOK.DELETE',
12640 /*::[*/0x0182/*::]*/: 'WORKBOOK.NAME',
12641 /*::[*/0x0184/*::]*/: 'GALLERY.CUSTOM',
12642 /*::[*/0x0186/*::]*/: 'ADD.CHART.AUTOFORMAT',
12643 /*::[*/0x0187/*::]*/: 'DELETE.CHART.AUTOFORMAT',
12644 /*::[*/0x0188/*::]*/: 'CHART.ADD.DATA',
12645 /*::[*/0x0189/*::]*/: 'AUTO.OUTLINE',
12646 /*::[*/0x018A/*::]*/: 'TAB.ORDER',
12647 /*::[*/0x018B/*::]*/: 'SHOW.DIALOG',
12648 /*::[*/0x018C/*::]*/: 'SELECT.ALL',
12649 /*::[*/0x018D/*::]*/: 'UNGROUP.SHEETS',
12650 /*::[*/0x018E/*::]*/: 'SUBTOTAL.CREATE',
12651 /*::[*/0x018F/*::]*/: 'SUBTOTAL.REMOVE',
12652 /*::[*/0x0190/*::]*/: 'RENAME.OBJECT',
12653 /*::[*/0x019C/*::]*/: 'WORKBOOK.SCROLL',
12654 /*::[*/0x019D/*::]*/: 'WORKBOOK.NEXT',
12655 /*::[*/0x019E/*::]*/: 'WORKBOOK.PREV',
12656 /*::[*/0x019F/*::]*/: 'WORKBOOK.TAB.SPLIT',
12657 /*::[*/0x01A0/*::]*/: 'FULL.SCREEN',
12658 /*::[*/0x01A1/*::]*/: 'WORKBOOK.PROTECT',
12659 /*::[*/0x01A4/*::]*/: 'SCROLLBAR.PROPERTIES',
12660 /*::[*/0x01A5/*::]*/: 'PIVOT.SHOW.PAGES',
12661 /*::[*/0x01A6/*::]*/: 'TEXT.TO.COLUMNS',
12662 /*::[*/0x01A7/*::]*/: 'FORMAT.CHARTTYPE',
12663 /*::[*/0x01A8/*::]*/: 'LINK.FORMAT',
12664 /*::[*/0x01A9/*::]*/: 'TRACER.DISPLAY',
12665 /*::[*/0x01AE/*::]*/: 'TRACER.NAVIGATE',
12666 /*::[*/0x01AF/*::]*/: 'TRACER.CLEAR',
12667 /*::[*/0x01B0/*::]*/: 'TRACER.ERROR',
12668 /*::[*/0x01B1/*::]*/: 'PIVOT.FIELD.GROUP',
12669 /*::[*/0x01B2/*::]*/: 'PIVOT.FIELD.UNGROUP',
12670 /*::[*/0x01B3/*::]*/: 'CHECKBOX.PROPERTIES',
12671 /*::[*/0x01B4/*::]*/: 'LABEL.PROPERTIES',
12672 /*::[*/0x01B5/*::]*/: 'LISTBOX.PROPERTIES',
12673 /*::[*/0x01B6/*::]*/: 'EDITBOX.PROPERTIES',
12674 /*::[*/0x01B7/*::]*/: 'PIVOT.REFRESH',
12675 /*::[*/0x01B8/*::]*/: 'LINK.COMBO',
12676 /*::[*/0x01B9/*::]*/: 'OPEN.TEXT',
12677 /*::[*/0x01BA/*::]*/: 'HIDE.DIALOG',
12678 /*::[*/0x01BB/*::]*/: 'SET.DIALOG.FOCUS',
12679 /*::[*/0x01BC/*::]*/: 'ENABLE.OBJECT',
12680 /*::[*/0x01BD/*::]*/: 'PUSHBUTTON.PROPERTIES',
12681 /*::[*/0x01BE/*::]*/: 'SET.DIALOG.DEFAULT',
12682 /*::[*/0x01BF/*::]*/: 'FILTER',
12683 /*::[*/0x01C0/*::]*/: 'FILTER.SHOW.ALL',
12684 /*::[*/0x01C1/*::]*/: 'CLEAR.OUTLINE',
12685 /*::[*/0x01C2/*::]*/: 'FUNCTION.WIZARD',
12686 /*::[*/0x01C3/*::]*/: 'ADD.LIST.ITEM',
12687 /*::[*/0x01C4/*::]*/: 'SET.LIST.ITEM',
12688 /*::[*/0x01C5/*::]*/: 'REMOVE.LIST.ITEM',
12689 /*::[*/0x01C6/*::]*/: 'SELECT.LIST.ITEM',
12690 /*::[*/0x01C7/*::]*/: 'SET.CONTROL.VALUE',
12691 /*::[*/0x01C8/*::]*/: 'SAVE.COPY.AS',
12692 /*::[*/0x01CA/*::]*/: 'OPTIONS.LISTS.ADD',
12693 /*::[*/0x01CB/*::]*/: 'OPTIONS.LISTS.DELETE',
12694 /*::[*/0x01CC/*::]*/: 'SERIES.AXES',
12695 /*::[*/0x01CD/*::]*/: 'SERIES.X',
12696 /*::[*/0x01CE/*::]*/: 'SERIES.Y',
12697 /*::[*/0x01CF/*::]*/: 'ERRORBAR.X',
12698 /*::[*/0x01D0/*::]*/: 'ERRORBAR.Y',
12699 /*::[*/0x01D1/*::]*/: 'FORMAT.CHART',
12700 /*::[*/0x01D2/*::]*/: 'SERIES.ORDER',
12701 /*::[*/0x01D3/*::]*/: 'MAIL.LOGOFF',
12702 /*::[*/0x01D4/*::]*/: 'CLEAR.ROUTING.SLIP',
12703 /*::[*/0x01D5/*::]*/: 'APP.ACTIVATE.MICROSOFT',
12704 /*::[*/0x01D6/*::]*/: 'MAIL.EDIT.MAILER',
12705 /*::[*/0x01D7/*::]*/: 'ON.SHEET',
12706 /*::[*/0x01D8/*::]*/: 'STANDARD.WIDTH',
12707 /*::[*/0x01D9/*::]*/: 'SCENARIO.MERGE',
12708 /*::[*/0x01DA/*::]*/: 'SUMMARY.INFO',
12709 /*::[*/0x01DB/*::]*/: 'FIND.FILE',
12710 /*::[*/0x01DC/*::]*/: 'ACTIVE.CELL.FONT',
12711 /*::[*/0x01DD/*::]*/: 'ENABLE.TIPWIZARD',
12712 /*::[*/0x01DE/*::]*/: 'VBA.MAKE.ADDIN',
12713 /*::[*/0x01E0/*::]*/: 'INSERTDATATABLE',
12714 /*::[*/0x01E1/*::]*/: 'WORKGROUP.OPTIONS',
12715 /*::[*/0x01E2/*::]*/: 'MAIL.SEND.MAILER',
12716 /*::[*/0x01E5/*::]*/: 'AUTOCORRECT',
12717 /*::[*/0x01E9/*::]*/: 'POST.DOCUMENT',
12718 /*::[*/0x01EB/*::]*/: 'PICKLIST',
12719 /*::[*/0x01ED/*::]*/: 'VIEW.SHOW',
12720 /*::[*/0x01EE/*::]*/: 'VIEW.DEFINE',
12721 /*::[*/0x01EF/*::]*/: 'VIEW.DELETE',
12722 /*::[*/0x01FD/*::]*/: 'SHEET.BACKGROUND',
12723 /*::[*/0x01FE/*::]*/: 'INSERT.MAP.OBJECT',
12724 /*::[*/0x01FF/*::]*/: 'OPTIONS.MENONO',
12725 /*::[*/0x0205/*::]*/: 'MSOCHECKS',
12726 /*::[*/0x0206/*::]*/: 'NORMAL',
12727 /*::[*/0x0207/*::]*/: 'LAYOUT',
12728 /*::[*/0x0208/*::]*/: 'RM.PRINT.AREA',
12729 /*::[*/0x0209/*::]*/: 'CLEAR.PRINT.AREA',
12730 /*::[*/0x020A/*::]*/: 'ADD.PRINT.AREA',
12731 /*::[*/0x020B/*::]*/: 'MOVE.BRK',
12732 /*::[*/0x0221/*::]*/: 'HIDECURR.NOTE',
12733 /*::[*/0x0222/*::]*/: 'HIDEALL.NOTES',
12734 /*::[*/0x0223/*::]*/: 'DELETE.NOTE',
12735 /*::[*/0x0224/*::]*/: 'TRAVERSE.NOTES',
12736 /*::[*/0x0225/*::]*/: 'ACTIVATE.NOTES',
12737 /*::[*/0x026C/*::]*/: 'PROTECT.REVISIONS',
12738 /*::[*/0x026D/*::]*/: 'UNPROTECT.REVISIONS',
12739 /*::[*/0x0287/*::]*/: 'OPTIONS.ME',
12740 /*::[*/0x028D/*::]*/: 'WEB.PUBLISH',
12741 /*::[*/0x029B/*::]*/: 'NEWWEBQUERY',
12742 /*::[*/0x02A1/*::]*/: 'PIVOT.TABLE.CHART',
12743 /*::[*/0x02F1/*::]*/: 'OPTIONS.SAVE',
12744 /*::[*/0x02F3/*::]*/: 'OPTIONS.SPELL',
12745 /*::[*/0x0328/*::]*/: 'HIDEALL.INKANNOTS'
12746};
12747
12748/* [MS-XLS] 2.5.198.17 */
12749/* [MS-XLSB] 2.5.97.10 */
12750var Ftab = {
12751 /*::[*/0x0000/*::]*/: 'COUNT',
12752 /*::[*/0x0001/*::]*/: 'IF',
12753 /*::[*/0x0002/*::]*/: 'ISNA',
12754 /*::[*/0x0003/*::]*/: 'ISERROR',
12755 /*::[*/0x0004/*::]*/: 'SUM',
12756 /*::[*/0x0005/*::]*/: 'AVERAGE',
12757 /*::[*/0x0006/*::]*/: 'MIN',
12758 /*::[*/0x0007/*::]*/: 'MAX',
12759 /*::[*/0x0008/*::]*/: 'ROW',
12760 /*::[*/0x0009/*::]*/: 'COLUMN',
12761 /*::[*/0x000A/*::]*/: 'NA',
12762 /*::[*/0x000B/*::]*/: 'NPV',
12763 /*::[*/0x000C/*::]*/: 'STDEV',
12764 /*::[*/0x000D/*::]*/: 'DOLLAR',
12765 /*::[*/0x000E/*::]*/: 'FIXED',
12766 /*::[*/0x000F/*::]*/: 'SIN',
12767 /*::[*/0x0010/*::]*/: 'COS',
12768 /*::[*/0x0011/*::]*/: 'TAN',
12769 /*::[*/0x0012/*::]*/: 'ATAN',
12770 /*::[*/0x0013/*::]*/: 'PI',
12771 /*::[*/0x0014/*::]*/: 'SQRT',
12772 /*::[*/0x0015/*::]*/: 'EXP',
12773 /*::[*/0x0016/*::]*/: 'LN',
12774 /*::[*/0x0017/*::]*/: 'LOG10',
12775 /*::[*/0x0018/*::]*/: 'ABS',
12776 /*::[*/0x0019/*::]*/: 'INT',
12777 /*::[*/0x001A/*::]*/: 'SIGN',
12778 /*::[*/0x001B/*::]*/: 'ROUND',
12779 /*::[*/0x001C/*::]*/: 'LOOKUP',
12780 /*::[*/0x001D/*::]*/: 'INDEX',
12781 /*::[*/0x001E/*::]*/: 'REPT',
12782 /*::[*/0x001F/*::]*/: 'MID',
12783 /*::[*/0x0020/*::]*/: 'LEN',
12784 /*::[*/0x0021/*::]*/: 'VALUE',
12785 /*::[*/0x0022/*::]*/: 'TRUE',
12786 /*::[*/0x0023/*::]*/: 'FALSE',
12787 /*::[*/0x0024/*::]*/: 'AND',
12788 /*::[*/0x0025/*::]*/: 'OR',
12789 /*::[*/0x0026/*::]*/: 'NOT',
12790 /*::[*/0x0027/*::]*/: 'MOD',
12791 /*::[*/0x0028/*::]*/: 'DCOUNT',
12792 /*::[*/0x0029/*::]*/: 'DSUM',
12793 /*::[*/0x002A/*::]*/: 'DAVERAGE',
12794 /*::[*/0x002B/*::]*/: 'DMIN',
12795 /*::[*/0x002C/*::]*/: 'DMAX',
12796 /*::[*/0x002D/*::]*/: 'DSTDEV',
12797 /*::[*/0x002E/*::]*/: 'VAR',
12798 /*::[*/0x002F/*::]*/: 'DVAR',
12799 /*::[*/0x0030/*::]*/: 'TEXT',
12800 /*::[*/0x0031/*::]*/: 'LINEST',
12801 /*::[*/0x0032/*::]*/: 'TREND',
12802 /*::[*/0x0033/*::]*/: 'LOGEST',
12803 /*::[*/0x0034/*::]*/: 'GROWTH',
12804 /*::[*/0x0035/*::]*/: 'GOTO',
12805 /*::[*/0x0036/*::]*/: 'HALT',
12806 /*::[*/0x0037/*::]*/: 'RETURN',
12807 /*::[*/0x0038/*::]*/: 'PV',
12808 /*::[*/0x0039/*::]*/: 'FV',
12809 /*::[*/0x003A/*::]*/: 'NPER',
12810 /*::[*/0x003B/*::]*/: 'PMT',
12811 /*::[*/0x003C/*::]*/: 'RATE',
12812 /*::[*/0x003D/*::]*/: 'MIRR',
12813 /*::[*/0x003E/*::]*/: 'IRR',
12814 /*::[*/0x003F/*::]*/: 'RAND',
12815 /*::[*/0x0040/*::]*/: 'MATCH',
12816 /*::[*/0x0041/*::]*/: 'DATE',
12817 /*::[*/0x0042/*::]*/: 'TIME',
12818 /*::[*/0x0043/*::]*/: 'DAY',
12819 /*::[*/0x0044/*::]*/: 'MONTH',
12820 /*::[*/0x0045/*::]*/: 'YEAR',
12821 /*::[*/0x0046/*::]*/: 'WEEKDAY',
12822 /*::[*/0x0047/*::]*/: 'HOUR',
12823 /*::[*/0x0048/*::]*/: 'MINUTE',
12824 /*::[*/0x0049/*::]*/: 'SECOND',
12825 /*::[*/0x004A/*::]*/: 'NOW',
12826 /*::[*/0x004B/*::]*/: 'AREAS',
12827 /*::[*/0x004C/*::]*/: 'ROWS',
12828 /*::[*/0x004D/*::]*/: 'COLUMNS',
12829 /*::[*/0x004E/*::]*/: 'OFFSET',
12830 /*::[*/0x004F/*::]*/: 'ABSREF',
12831 /*::[*/0x0050/*::]*/: 'RELREF',
12832 /*::[*/0x0051/*::]*/: 'ARGUMENT',
12833 /*::[*/0x0052/*::]*/: 'SEARCH',
12834 /*::[*/0x0053/*::]*/: 'TRANSPOSE',
12835 /*::[*/0x0054/*::]*/: 'ERROR',
12836 /*::[*/0x0055/*::]*/: 'STEP',
12837 /*::[*/0x0056/*::]*/: 'TYPE',
12838 /*::[*/0x0057/*::]*/: 'ECHO',
12839 /*::[*/0x0058/*::]*/: 'SET.NAME',
12840 /*::[*/0x0059/*::]*/: 'CALLER',
12841 /*::[*/0x005A/*::]*/: 'DEREF',
12842 /*::[*/0x005B/*::]*/: 'WINDOWS',
12843 /*::[*/0x005C/*::]*/: 'SERIES',
12844 /*::[*/0x005D/*::]*/: 'DOCUMENTS',
12845 /*::[*/0x005E/*::]*/: 'ACTIVE.CELL',
12846 /*::[*/0x005F/*::]*/: 'SELECTION',
12847 /*::[*/0x0060/*::]*/: 'RESULT',
12848 /*::[*/0x0061/*::]*/: 'ATAN2',
12849 /*::[*/0x0062/*::]*/: 'ASIN',
12850 /*::[*/0x0063/*::]*/: 'ACOS',
12851 /*::[*/0x0064/*::]*/: 'CHOOSE',
12852 /*::[*/0x0065/*::]*/: 'HLOOKUP',
12853 /*::[*/0x0066/*::]*/: 'VLOOKUP',
12854 /*::[*/0x0067/*::]*/: 'LINKS',
12855 /*::[*/0x0068/*::]*/: 'INPUT',
12856 /*::[*/0x0069/*::]*/: 'ISREF',
12857 /*::[*/0x006A/*::]*/: 'GET.FORMULA',
12858 /*::[*/0x006B/*::]*/: 'GET.NAME',
12859 /*::[*/0x006C/*::]*/: 'SET.VALUE',
12860 /*::[*/0x006D/*::]*/: 'LOG',
12861 /*::[*/0x006E/*::]*/: 'EXEC',
12862 /*::[*/0x006F/*::]*/: 'CHAR',
12863 /*::[*/0x0070/*::]*/: 'LOWER',
12864 /*::[*/0x0071/*::]*/: 'UPPER',
12865 /*::[*/0x0072/*::]*/: 'PROPER',
12866 /*::[*/0x0073/*::]*/: 'LEFT',
12867 /*::[*/0x0074/*::]*/: 'RIGHT',
12868 /*::[*/0x0075/*::]*/: 'EXACT',
12869 /*::[*/0x0076/*::]*/: 'TRIM',
12870 /*::[*/0x0077/*::]*/: 'REPLACE',
12871 /*::[*/0x0078/*::]*/: 'SUBSTITUTE',
12872 /*::[*/0x0079/*::]*/: 'CODE',
12873 /*::[*/0x007A/*::]*/: 'NAMES',
12874 /*::[*/0x007B/*::]*/: 'DIRECTORY',
12875 /*::[*/0x007C/*::]*/: 'FIND',
12876 /*::[*/0x007D/*::]*/: 'CELL',
12877 /*::[*/0x007E/*::]*/: 'ISERR',
12878 /*::[*/0x007F/*::]*/: 'ISTEXT',
12879 /*::[*/0x0080/*::]*/: 'ISNUMBER',
12880 /*::[*/0x0081/*::]*/: 'ISBLANK',
12881 /*::[*/0x0082/*::]*/: 'T',
12882 /*::[*/0x0083/*::]*/: 'N',
12883 /*::[*/0x0084/*::]*/: 'FOPEN',
12884 /*::[*/0x0085/*::]*/: 'FCLOSE',
12885 /*::[*/0x0086/*::]*/: 'FSIZE',
12886 /*::[*/0x0087/*::]*/: 'FREADLN',
12887 /*::[*/0x0088/*::]*/: 'FREAD',
12888 /*::[*/0x0089/*::]*/: 'FWRITELN',
12889 /*::[*/0x008A/*::]*/: 'FWRITE',
12890 /*::[*/0x008B/*::]*/: 'FPOS',
12891 /*::[*/0x008C/*::]*/: 'DATEVALUE',
12892 /*::[*/0x008D/*::]*/: 'TIMEVALUE',
12893 /*::[*/0x008E/*::]*/: 'SLN',
12894 /*::[*/0x008F/*::]*/: 'SYD',
12895 /*::[*/0x0090/*::]*/: 'DDB',
12896 /*::[*/0x0091/*::]*/: 'GET.DEF',
12897 /*::[*/0x0092/*::]*/: 'REFTEXT',
12898 /*::[*/0x0093/*::]*/: 'TEXTREF',
12899 /*::[*/0x0094/*::]*/: 'INDIRECT',
12900 /*::[*/0x0095/*::]*/: 'REGISTER',
12901 /*::[*/0x0096/*::]*/: 'CALL',
12902 /*::[*/0x0097/*::]*/: 'ADD.BAR',
12903 /*::[*/0x0098/*::]*/: 'ADD.MENU',
12904 /*::[*/0x0099/*::]*/: 'ADD.COMMAND',
12905 /*::[*/0x009A/*::]*/: 'ENABLE.COMMAND',
12906 /*::[*/0x009B/*::]*/: 'CHECK.COMMAND',
12907 /*::[*/0x009C/*::]*/: 'RENAME.COMMAND',
12908 /*::[*/0x009D/*::]*/: 'SHOW.BAR',
12909 /*::[*/0x009E/*::]*/: 'DELETE.MENU',
12910 /*::[*/0x009F/*::]*/: 'DELETE.COMMAND',
12911 /*::[*/0x00A0/*::]*/: 'GET.CHART.ITEM',
12912 /*::[*/0x00A1/*::]*/: 'DIALOG.BOX',
12913 /*::[*/0x00A2/*::]*/: 'CLEAN',
12914 /*::[*/0x00A3/*::]*/: 'MDETERM',
12915 /*::[*/0x00A4/*::]*/: 'MINVERSE',
12916 /*::[*/0x00A5/*::]*/: 'MMULT',
12917 /*::[*/0x00A6/*::]*/: 'FILES',
12918 /*::[*/0x00A7/*::]*/: 'IPMT',
12919 /*::[*/0x00A8/*::]*/: 'PPMT',
12920 /*::[*/0x00A9/*::]*/: 'COUNTA',
12921 /*::[*/0x00AA/*::]*/: 'CANCEL.KEY',
12922 /*::[*/0x00AB/*::]*/: 'FOR',
12923 /*::[*/0x00AC/*::]*/: 'WHILE',
12924 /*::[*/0x00AD/*::]*/: 'BREAK',
12925 /*::[*/0x00AE/*::]*/: 'NEXT',
12926 /*::[*/0x00AF/*::]*/: 'INITIATE',
12927 /*::[*/0x00B0/*::]*/: 'REQUEST',
12928 /*::[*/0x00B1/*::]*/: 'POKE',
12929 /*::[*/0x00B2/*::]*/: 'EXECUTE',
12930 /*::[*/0x00B3/*::]*/: 'TERMINATE',
12931 /*::[*/0x00B4/*::]*/: 'RESTART',
12932 /*::[*/0x00B5/*::]*/: 'HELP',
12933 /*::[*/0x00B6/*::]*/: 'GET.BAR',
12934 /*::[*/0x00B7/*::]*/: 'PRODUCT',
12935 /*::[*/0x00B8/*::]*/: 'FACT',
12936 /*::[*/0x00B9/*::]*/: 'GET.CELL',
12937 /*::[*/0x00BA/*::]*/: 'GET.WORKSPACE',
12938 /*::[*/0x00BB/*::]*/: 'GET.WINDOW',
12939 /*::[*/0x00BC/*::]*/: 'GET.DOCUMENT',
12940 /*::[*/0x00BD/*::]*/: 'DPRODUCT',
12941 /*::[*/0x00BE/*::]*/: 'ISNONTEXT',
12942 /*::[*/0x00BF/*::]*/: 'GET.NOTE',
12943 /*::[*/0x00C0/*::]*/: 'NOTE',
12944 /*::[*/0x00C1/*::]*/: 'STDEVP',
12945 /*::[*/0x00C2/*::]*/: 'VARP',
12946 /*::[*/0x00C3/*::]*/: 'DSTDEVP',
12947 /*::[*/0x00C4/*::]*/: 'DVARP',
12948 /*::[*/0x00C5/*::]*/: 'TRUNC',
12949 /*::[*/0x00C6/*::]*/: 'ISLOGICAL',
12950 /*::[*/0x00C7/*::]*/: 'DCOUNTA',
12951 /*::[*/0x00C8/*::]*/: 'DELETE.BAR',
12952 /*::[*/0x00C9/*::]*/: 'UNREGISTER',
12953 /*::[*/0x00CC/*::]*/: 'USDOLLAR',
12954 /*::[*/0x00CD/*::]*/: 'FINDB',
12955 /*::[*/0x00CE/*::]*/: 'SEARCHB',
12956 /*::[*/0x00CF/*::]*/: 'REPLACEB',
12957 /*::[*/0x00D0/*::]*/: 'LEFTB',
12958 /*::[*/0x00D1/*::]*/: 'RIGHTB',
12959 /*::[*/0x00D2/*::]*/: 'MIDB',
12960 /*::[*/0x00D3/*::]*/: 'LENB',
12961 /*::[*/0x00D4/*::]*/: 'ROUNDUP',
12962 /*::[*/0x00D5/*::]*/: 'ROUNDDOWN',
12963 /*::[*/0x00D6/*::]*/: 'ASC',
12964 /*::[*/0x00D7/*::]*/: 'DBCS',
12965 /*::[*/0x00D8/*::]*/: 'RANK',
12966 /*::[*/0x00DB/*::]*/: 'ADDRESS',
12967 /*::[*/0x00DC/*::]*/: 'DAYS360',
12968 /*::[*/0x00DD/*::]*/: 'TODAY',
12969 /*::[*/0x00DE/*::]*/: 'VDB',
12970 /*::[*/0x00DF/*::]*/: 'ELSE',
12971 /*::[*/0x00E0/*::]*/: 'ELSE.IF',
12972 /*::[*/0x00E1/*::]*/: 'END.IF',
12973 /*::[*/0x00E2/*::]*/: 'FOR.CELL',
12974 /*::[*/0x00E3/*::]*/: 'MEDIAN',
12975 /*::[*/0x00E4/*::]*/: 'SUMPRODUCT',
12976 /*::[*/0x00E5/*::]*/: 'SINH',
12977 /*::[*/0x00E6/*::]*/: 'COSH',
12978 /*::[*/0x00E7/*::]*/: 'TANH',
12979 /*::[*/0x00E8/*::]*/: 'ASINH',
12980 /*::[*/0x00E9/*::]*/: 'ACOSH',
12981 /*::[*/0x00EA/*::]*/: 'ATANH',
12982 /*::[*/0x00EB/*::]*/: 'DGET',
12983 /*::[*/0x00EC/*::]*/: 'CREATE.OBJECT',
12984 /*::[*/0x00ED/*::]*/: 'VOLATILE',
12985 /*::[*/0x00EE/*::]*/: 'LAST.ERROR',
12986 /*::[*/0x00EF/*::]*/: 'CUSTOM.UNDO',
12987 /*::[*/0x00F0/*::]*/: 'CUSTOM.REPEAT',
12988 /*::[*/0x00F1/*::]*/: 'FORMULA.CONVERT',
12989 /*::[*/0x00F2/*::]*/: 'GET.LINK.INFO',
12990 /*::[*/0x00F3/*::]*/: 'TEXT.BOX',
12991 /*::[*/0x00F4/*::]*/: 'INFO',
12992 /*::[*/0x00F5/*::]*/: 'GROUP',
12993 /*::[*/0x00F6/*::]*/: 'GET.OBJECT',
12994 /*::[*/0x00F7/*::]*/: 'DB',
12995 /*::[*/0x00F8/*::]*/: 'PAUSE',
12996 /*::[*/0x00FB/*::]*/: 'RESUME',
12997 /*::[*/0x00FC/*::]*/: 'FREQUENCY',
12998 /*::[*/0x00FD/*::]*/: 'ADD.TOOLBAR',
12999 /*::[*/0x00FE/*::]*/: 'DELETE.TOOLBAR',
13000 /*::[*/0x00FF/*::]*/: 'User',
13001 /*::[*/0x0100/*::]*/: 'RESET.TOOLBAR',
13002 /*::[*/0x0101/*::]*/: 'EVALUATE',
13003 /*::[*/0x0102/*::]*/: 'GET.TOOLBAR',
13004 /*::[*/0x0103/*::]*/: 'GET.TOOL',
13005 /*::[*/0x0104/*::]*/: 'SPELLING.CHECK',
13006 /*::[*/0x0105/*::]*/: 'ERROR.TYPE',
13007 /*::[*/0x0106/*::]*/: 'APP.TITLE',
13008 /*::[*/0x0107/*::]*/: 'WINDOW.TITLE',
13009 /*::[*/0x0108/*::]*/: 'SAVE.TOOLBAR',
13010 /*::[*/0x0109/*::]*/: 'ENABLE.TOOL',
13011 /*::[*/0x010A/*::]*/: 'PRESS.TOOL',
13012 /*::[*/0x010B/*::]*/: 'REGISTER.ID',
13013 /*::[*/0x010C/*::]*/: 'GET.WORKBOOK',
13014 /*::[*/0x010D/*::]*/: 'AVEDEV',
13015 /*::[*/0x010E/*::]*/: 'BETADIST',
13016 /*::[*/0x010F/*::]*/: 'GAMMALN',
13017 /*::[*/0x0110/*::]*/: 'BETAINV',
13018 /*::[*/0x0111/*::]*/: 'BINOMDIST',
13019 /*::[*/0x0112/*::]*/: 'CHIDIST',
13020 /*::[*/0x0113/*::]*/: 'CHIINV',
13021 /*::[*/0x0114/*::]*/: 'COMBIN',
13022 /*::[*/0x0115/*::]*/: 'CONFIDENCE',
13023 /*::[*/0x0116/*::]*/: 'CRITBINOM',
13024 /*::[*/0x0117/*::]*/: 'EVEN',
13025 /*::[*/0x0118/*::]*/: 'EXPONDIST',
13026 /*::[*/0x0119/*::]*/: 'FDIST',
13027 /*::[*/0x011A/*::]*/: 'FINV',
13028 /*::[*/0x011B/*::]*/: 'FISHER',
13029 /*::[*/0x011C/*::]*/: 'FISHERINV',
13030 /*::[*/0x011D/*::]*/: 'FLOOR',
13031 /*::[*/0x011E/*::]*/: 'GAMMADIST',
13032 /*::[*/0x011F/*::]*/: 'GAMMAINV',
13033 /*::[*/0x0120/*::]*/: 'CEILING',
13034 /*::[*/0x0121/*::]*/: 'HYPGEOMDIST',
13035 /*::[*/0x0122/*::]*/: 'LOGNORMDIST',
13036 /*::[*/0x0123/*::]*/: 'LOGINV',
13037 /*::[*/0x0124/*::]*/: 'NEGBINOMDIST',
13038 /*::[*/0x0125/*::]*/: 'NORMDIST',
13039 /*::[*/0x0126/*::]*/: 'NORMSDIST',
13040 /*::[*/0x0127/*::]*/: 'NORMINV',
13041 /*::[*/0x0128/*::]*/: 'NORMSINV',
13042 /*::[*/0x0129/*::]*/: 'STANDARDIZE',
13043 /*::[*/0x012A/*::]*/: 'ODD',
13044 /*::[*/0x012B/*::]*/: 'PERMUT',
13045 /*::[*/0x012C/*::]*/: 'POISSON',
13046 /*::[*/0x012D/*::]*/: 'TDIST',
13047 /*::[*/0x012E/*::]*/: 'WEIBULL',
13048 /*::[*/0x012F/*::]*/: 'SUMXMY2',
13049 /*::[*/0x0130/*::]*/: 'SUMX2MY2',
13050 /*::[*/0x0131/*::]*/: 'SUMX2PY2',
13051 /*::[*/0x0132/*::]*/: 'CHITEST',
13052 /*::[*/0x0133/*::]*/: 'CORREL',
13053 /*::[*/0x0134/*::]*/: 'COVAR',
13054 /*::[*/0x0135/*::]*/: 'FORECAST',
13055 /*::[*/0x0136/*::]*/: 'FTEST',
13056 /*::[*/0x0137/*::]*/: 'INTERCEPT',
13057 /*::[*/0x0138/*::]*/: 'PEARSON',
13058 /*::[*/0x0139/*::]*/: 'RSQ',
13059 /*::[*/0x013A/*::]*/: 'STEYX',
13060 /*::[*/0x013B/*::]*/: 'SLOPE',
13061 /*::[*/0x013C/*::]*/: 'TTEST',
13062 /*::[*/0x013D/*::]*/: 'PROB',
13063 /*::[*/0x013E/*::]*/: 'DEVSQ',
13064 /*::[*/0x013F/*::]*/: 'GEOMEAN',
13065 /*::[*/0x0140/*::]*/: 'HARMEAN',
13066 /*::[*/0x0141/*::]*/: 'SUMSQ',
13067 /*::[*/0x0142/*::]*/: 'KURT',
13068 /*::[*/0x0143/*::]*/: 'SKEW',
13069 /*::[*/0x0144/*::]*/: 'ZTEST',
13070 /*::[*/0x0145/*::]*/: 'LARGE',
13071 /*::[*/0x0146/*::]*/: 'SMALL',
13072 /*::[*/0x0147/*::]*/: 'QUARTILE',
13073 /*::[*/0x0148/*::]*/: 'PERCENTILE',
13074 /*::[*/0x0149/*::]*/: 'PERCENTRANK',
13075 /*::[*/0x014A/*::]*/: 'MODE',
13076 /*::[*/0x014B/*::]*/: 'TRIMMEAN',
13077 /*::[*/0x014C/*::]*/: 'TINV',
13078 /*::[*/0x014E/*::]*/: 'MOVIE.COMMAND',
13079 /*::[*/0x014F/*::]*/: 'GET.MOVIE',
13080 /*::[*/0x0150/*::]*/: 'CONCATENATE',
13081 /*::[*/0x0151/*::]*/: 'POWER',
13082 /*::[*/0x0152/*::]*/: 'PIVOT.ADD.DATA',
13083 /*::[*/0x0153/*::]*/: 'GET.PIVOT.TABLE',
13084 /*::[*/0x0154/*::]*/: 'GET.PIVOT.FIELD',
13085 /*::[*/0x0155/*::]*/: 'GET.PIVOT.ITEM',
13086 /*::[*/0x0156/*::]*/: 'RADIANS',
13087 /*::[*/0x0157/*::]*/: 'DEGREES',
13088 /*::[*/0x0158/*::]*/: 'SUBTOTAL',
13089 /*::[*/0x0159/*::]*/: 'SUMIF',
13090 /*::[*/0x015A/*::]*/: 'COUNTIF',
13091 /*::[*/0x015B/*::]*/: 'COUNTBLANK',
13092 /*::[*/0x015C/*::]*/: 'SCENARIO.GET',
13093 /*::[*/0x015D/*::]*/: 'OPTIONS.LISTS.GET',
13094 /*::[*/0x015E/*::]*/: 'ISPMT',
13095 /*::[*/0x015F/*::]*/: 'DATEDIF',
13096 /*::[*/0x0160/*::]*/: 'DATESTRING',
13097 /*::[*/0x0161/*::]*/: 'NUMBERSTRING',
13098 /*::[*/0x0162/*::]*/: 'ROMAN',
13099 /*::[*/0x0163/*::]*/: 'OPEN.DIALOG',
13100 /*::[*/0x0164/*::]*/: 'SAVE.DIALOG',
13101 /*::[*/0x0165/*::]*/: 'VIEW.GET',
13102 /*::[*/0x0166/*::]*/: 'GETPIVOTDATA',
13103 /*::[*/0x0167/*::]*/: 'HYPERLINK',
13104 /*::[*/0x0168/*::]*/: 'PHONETIC',
13105 /*::[*/0x0169/*::]*/: 'AVERAGEA',
13106 /*::[*/0x016A/*::]*/: 'MAXA',
13107 /*::[*/0x016B/*::]*/: 'MINA',
13108 /*::[*/0x016C/*::]*/: 'STDEVPA',
13109 /*::[*/0x016D/*::]*/: 'VARPA',
13110 /*::[*/0x016E/*::]*/: 'STDEVA',
13111 /*::[*/0x016F/*::]*/: 'VARA',
13112 /*::[*/0x0170/*::]*/: 'BAHTTEXT',
13113 /*::[*/0x0171/*::]*/: 'THAIDAYOFWEEK',
13114 /*::[*/0x0172/*::]*/: 'THAIDIGIT',
13115 /*::[*/0x0173/*::]*/: 'THAIMONTHOFYEAR',
13116 /*::[*/0x0174/*::]*/: 'THAINUMSOUND',
13117 /*::[*/0x0175/*::]*/: 'THAINUMSTRING',
13118 /*::[*/0x0176/*::]*/: 'THAISTRINGLENGTH',
13119 /*::[*/0x0177/*::]*/: 'ISTHAIDIGIT',
13120 /*::[*/0x0178/*::]*/: 'ROUNDBAHTDOWN',
13121 /*::[*/0x0179/*::]*/: 'ROUNDBAHTUP',
13122 /*::[*/0x017A/*::]*/: 'THAIYEAR',
13123 /*::[*/0x017B/*::]*/: 'RTD',
13124
13125 /*::[*/0x017C/*::]*/: 'CUBEVALUE',
13126 /*::[*/0x017D/*::]*/: 'CUBEMEMBER',
13127 /*::[*/0x017E/*::]*/: 'CUBEMEMBERPROPERTY',
13128 /*::[*/0x017F/*::]*/: 'CUBERANKEDMEMBER',
13129 /*::[*/0x0180/*::]*/: 'HEX2BIN',
13130 /*::[*/0x0181/*::]*/: 'HEX2DEC',
13131 /*::[*/0x0182/*::]*/: 'HEX2OCT',
13132 /*::[*/0x0183/*::]*/: 'DEC2BIN',
13133 /*::[*/0x0184/*::]*/: 'DEC2HEX',
13134 /*::[*/0x0185/*::]*/: 'DEC2OCT',
13135 /*::[*/0x0186/*::]*/: 'OCT2BIN',
13136 /*::[*/0x0187/*::]*/: 'OCT2HEX',
13137 /*::[*/0x0188/*::]*/: 'OCT2DEC',
13138 /*::[*/0x0189/*::]*/: 'BIN2DEC',
13139 /*::[*/0x018A/*::]*/: 'BIN2OCT',
13140 /*::[*/0x018B/*::]*/: 'BIN2HEX',
13141 /*::[*/0x018C/*::]*/: 'IMSUB',
13142 /*::[*/0x018D/*::]*/: 'IMDIV',
13143 /*::[*/0x018E/*::]*/: 'IMPOWER',
13144 /*::[*/0x018F/*::]*/: 'IMABS',
13145 /*::[*/0x0190/*::]*/: 'IMSQRT',
13146 /*::[*/0x0191/*::]*/: 'IMLN',
13147 /*::[*/0x0192/*::]*/: 'IMLOG2',
13148 /*::[*/0x0193/*::]*/: 'IMLOG10',
13149 /*::[*/0x0194/*::]*/: 'IMSIN',
13150 /*::[*/0x0195/*::]*/: 'IMCOS',
13151 /*::[*/0x0196/*::]*/: 'IMEXP',
13152 /*::[*/0x0197/*::]*/: 'IMARGUMENT',
13153 /*::[*/0x0198/*::]*/: 'IMCONJUGATE',
13154 /*::[*/0x0199/*::]*/: 'IMAGINARY',
13155 /*::[*/0x019A/*::]*/: 'IMREAL',
13156 /*::[*/0x019B/*::]*/: 'COMPLEX',
13157 /*::[*/0x019C/*::]*/: 'IMSUM',
13158 /*::[*/0x019D/*::]*/: 'IMPRODUCT',
13159 /*::[*/0x019E/*::]*/: 'SERIESSUM',
13160 /*::[*/0x019F/*::]*/: 'FACTDOUBLE',
13161 /*::[*/0x01A0/*::]*/: 'SQRTPI',
13162 /*::[*/0x01A1/*::]*/: 'QUOTIENT',
13163 /*::[*/0x01A2/*::]*/: 'DELTA',
13164 /*::[*/0x01A3/*::]*/: 'GESTEP',
13165 /*::[*/0x01A4/*::]*/: 'ISEVEN',
13166 /*::[*/0x01A5/*::]*/: 'ISODD',
13167 /*::[*/0x01A6/*::]*/: 'MROUND',
13168 /*::[*/0x01A7/*::]*/: 'ERF',
13169 /*::[*/0x01A8/*::]*/: 'ERFC',
13170 /*::[*/0x01A9/*::]*/: 'BESSELJ',
13171 /*::[*/0x01AA/*::]*/: 'BESSELK',
13172 /*::[*/0x01AB/*::]*/: 'BESSELY',
13173 /*::[*/0x01AC/*::]*/: 'BESSELI',
13174 /*::[*/0x01AD/*::]*/: 'XIRR',
13175 /*::[*/0x01AE/*::]*/: 'XNPV',
13176 /*::[*/0x01AF/*::]*/: 'PRICEMAT',
13177 /*::[*/0x01B0/*::]*/: 'YIELDMAT',
13178 /*::[*/0x01B1/*::]*/: 'INTRATE',
13179 /*::[*/0x01B2/*::]*/: 'RECEIVED',
13180 /*::[*/0x01B3/*::]*/: 'DISC',
13181 /*::[*/0x01B4/*::]*/: 'PRICEDISC',
13182 /*::[*/0x01B5/*::]*/: 'YIELDDISC',
13183 /*::[*/0x01B6/*::]*/: 'TBILLEQ',
13184 /*::[*/0x01B7/*::]*/: 'TBILLPRICE',
13185 /*::[*/0x01B8/*::]*/: 'TBILLYIELD',
13186 /*::[*/0x01B9/*::]*/: 'PRICE',
13187 /*::[*/0x01BA/*::]*/: 'YIELD',
13188 /*::[*/0x01BB/*::]*/: 'DOLLARDE',
13189 /*::[*/0x01BC/*::]*/: 'DOLLARFR',
13190 /*::[*/0x01BD/*::]*/: 'NOMINAL',
13191 /*::[*/0x01BE/*::]*/: 'EFFECT',
13192 /*::[*/0x01BF/*::]*/: 'CUMPRINC',
13193 /*::[*/0x01C0/*::]*/: 'CUMIPMT',
13194 /*::[*/0x01C1/*::]*/: 'EDATE',
13195 /*::[*/0x01C2/*::]*/: 'EOMONTH',
13196 /*::[*/0x01C3/*::]*/: 'YEARFRAC',
13197 /*::[*/0x01C4/*::]*/: 'COUPDAYBS',
13198 /*::[*/0x01C5/*::]*/: 'COUPDAYS',
13199 /*::[*/0x01C6/*::]*/: 'COUPDAYSNC',
13200 /*::[*/0x01C7/*::]*/: 'COUPNCD',
13201 /*::[*/0x01C8/*::]*/: 'COUPNUM',
13202 /*::[*/0x01C9/*::]*/: 'COUPPCD',
13203 /*::[*/0x01CA/*::]*/: 'DURATION',
13204 /*::[*/0x01CB/*::]*/: 'MDURATION',
13205 /*::[*/0x01CC/*::]*/: 'ODDLPRICE',
13206 /*::[*/0x01CD/*::]*/: 'ODDLYIELD',
13207 /*::[*/0x01CE/*::]*/: 'ODDFPRICE',
13208 /*::[*/0x01CF/*::]*/: 'ODDFYIELD',
13209 /*::[*/0x01D0/*::]*/: 'RANDBETWEEN',
13210 /*::[*/0x01D1/*::]*/: 'WEEKNUM',
13211 /*::[*/0x01D2/*::]*/: 'AMORDEGRC',
13212 /*::[*/0x01D3/*::]*/: 'AMORLINC',
13213 /*::[*/0x01D4/*::]*/: 'CONVERT',
13214 /*::[*/0x02D4/*::]*/: 'SHEETJS',
13215 /*::[*/0x01D5/*::]*/: 'ACCRINT',
13216 /*::[*/0x01D6/*::]*/: 'ACCRINTM',
13217 /*::[*/0x01D7/*::]*/: 'WORKDAY',
13218 /*::[*/0x01D8/*::]*/: 'NETWORKDAYS',
13219 /*::[*/0x01D9/*::]*/: 'GCD',
13220 /*::[*/0x01DA/*::]*/: 'MULTINOMIAL',
13221 /*::[*/0x01DB/*::]*/: 'LCM',
13222 /*::[*/0x01DC/*::]*/: 'FVSCHEDULE',
13223 /*::[*/0x01DD/*::]*/: 'CUBEKPIMEMBER',
13224 /*::[*/0x01DE/*::]*/: 'CUBESET',
13225 /*::[*/0x01DF/*::]*/: 'CUBESETCOUNT',
13226 /*::[*/0x01E0/*::]*/: 'IFERROR',
13227 /*::[*/0x01E1/*::]*/: 'COUNTIFS',
13228 /*::[*/0x01E2/*::]*/: 'SUMIFS',
13229 /*::[*/0x01E3/*::]*/: 'AVERAGEIF',
13230 /*::[*/0x01E4/*::]*/: 'AVERAGEIFS'
13231};
13232var FtabArgc = {
13233 /*::[*/0x0002/*::]*/: 1, /* ISNA */
13234 /*::[*/0x0003/*::]*/: 1, /* ISERROR */
13235 /*::[*/0x000A/*::]*/: 0, /* NA */
13236 /*::[*/0x000F/*::]*/: 1, /* SIN */
13237 /*::[*/0x0010/*::]*/: 1, /* COS */
13238 /*::[*/0x0011/*::]*/: 1, /* TAN */
13239 /*::[*/0x0012/*::]*/: 1, /* ATAN */
13240 /*::[*/0x0013/*::]*/: 0, /* PI */
13241 /*::[*/0x0014/*::]*/: 1, /* SQRT */
13242 /*::[*/0x0015/*::]*/: 1, /* EXP */
13243 /*::[*/0x0016/*::]*/: 1, /* LN */
13244 /*::[*/0x0017/*::]*/: 1, /* LOG10 */
13245 /*::[*/0x0018/*::]*/: 1, /* ABS */
13246 /*::[*/0x0019/*::]*/: 1, /* INT */
13247 /*::[*/0x001A/*::]*/: 1, /* SIGN */
13248 /*::[*/0x001B/*::]*/: 2, /* ROUND */
13249 /*::[*/0x001E/*::]*/: 2, /* REPT */
13250 /*::[*/0x001F/*::]*/: 3, /* MID */
13251 /*::[*/0x0020/*::]*/: 1, /* LEN */
13252 /*::[*/0x0021/*::]*/: 1, /* VALUE */
13253 /*::[*/0x0022/*::]*/: 0, /* TRUE */
13254 /*::[*/0x0023/*::]*/: 0, /* FALSE */
13255 /*::[*/0x0026/*::]*/: 1, /* NOT */
13256 /*::[*/0x0027/*::]*/: 2, /* MOD */
13257 /*::[*/0x0028/*::]*/: 3, /* DCOUNT */
13258 /*::[*/0x0029/*::]*/: 3, /* DSUM */
13259 /*::[*/0x002A/*::]*/: 3, /* DAVERAGE */
13260 /*::[*/0x002B/*::]*/: 3, /* DMIN */
13261 /*::[*/0x002C/*::]*/: 3, /* DMAX */
13262 /*::[*/0x002D/*::]*/: 3, /* DSTDEV */
13263 /*::[*/0x002F/*::]*/: 3, /* DVAR */
13264 /*::[*/0x0030/*::]*/: 2, /* TEXT */
13265 /*::[*/0x0035/*::]*/: 1, /* GOTO */
13266 /*::[*/0x003D/*::]*/: 3, /* MIRR */
13267 /*::[*/0x003F/*::]*/: 0, /* RAND */
13268 /*::[*/0x0041/*::]*/: 3, /* DATE */
13269 /*::[*/0x0042/*::]*/: 3, /* TIME */
13270 /*::[*/0x0043/*::]*/: 1, /* DAY */
13271 /*::[*/0x0044/*::]*/: 1, /* MONTH */
13272 /*::[*/0x0045/*::]*/: 1, /* YEAR */
13273 /*::[*/0x0046/*::]*/: 1, /* WEEKDAY */
13274 /*::[*/0x0047/*::]*/: 1, /* HOUR */
13275 /*::[*/0x0048/*::]*/: 1, /* MINUTE */
13276 /*::[*/0x0049/*::]*/: 1, /* SECOND */
13277 /*::[*/0x004A/*::]*/: 0, /* NOW */
13278 /*::[*/0x004B/*::]*/: 1, /* AREAS */
13279 /*::[*/0x004C/*::]*/: 1, /* ROWS */
13280 /*::[*/0x004D/*::]*/: 1, /* COLUMNS */
13281 /*::[*/0x004F/*::]*/: 2, /* ABSREF */
13282 /*::[*/0x0050/*::]*/: 2, /* RELREF */
13283 /*::[*/0x0053/*::]*/: 1, /* TRANSPOSE */
13284 /*::[*/0x0055/*::]*/: 0, /* STEP */
13285 /*::[*/0x0056/*::]*/: 1, /* TYPE */
13286 /*::[*/0x0059/*::]*/: 0, /* CALLER */
13287 /*::[*/0x005A/*::]*/: 1, /* DEREF */
13288 /*::[*/0x005E/*::]*/: 0, /* ACTIVE.CELL */
13289 /*::[*/0x005F/*::]*/: 0, /* SELECTION */
13290 /*::[*/0x0061/*::]*/: 2, /* ATAN2 */
13291 /*::[*/0x0062/*::]*/: 1, /* ASIN */
13292 /*::[*/0x0063/*::]*/: 1, /* ACOS */
13293 /*::[*/0x0065/*::]*/: 3, /* HLOOKUP */
13294 /*::[*/0x0066/*::]*/: 3, /* VLOOKUP */
13295 /*::[*/0x0069/*::]*/: 1, /* ISREF */
13296 /*::[*/0x006A/*::]*/: 1, /* GET.FORMULA */
13297 /*::[*/0x006C/*::]*/: 2, /* SET.VALUE */
13298 /*::[*/0x006F/*::]*/: 1, /* CHAR */
13299 /*::[*/0x0070/*::]*/: 1, /* LOWER */
13300 /*::[*/0x0071/*::]*/: 1, /* UPPER */
13301 /*::[*/0x0072/*::]*/: 1, /* PROPER */
13302 /*::[*/0x0075/*::]*/: 2, /* EXACT */
13303 /*::[*/0x0076/*::]*/: 1, /* TRIM */
13304 /*::[*/0x0077/*::]*/: 4, /* REPLACE */
13305 /*::[*/0x0079/*::]*/: 1, /* CODE */
13306 /*::[*/0x007E/*::]*/: 1, /* ISERR */
13307 /*::[*/0x007F/*::]*/: 1, /* ISTEXT */
13308 /*::[*/0x0080/*::]*/: 1, /* ISNUMBER */
13309 /*::[*/0x0081/*::]*/: 1, /* ISBLANK */
13310 /*::[*/0x0082/*::]*/: 1, /* T */
13311 /*::[*/0x0083/*::]*/: 1, /* N */
13312 /*::[*/0x0085/*::]*/: 1, /* FCLOSE */
13313 /*::[*/0x0086/*::]*/: 1, /* FSIZE */
13314 /*::[*/0x0087/*::]*/: 1, /* FREADLN */
13315 /*::[*/0x0088/*::]*/: 2, /* FREAD */
13316 /*::[*/0x0089/*::]*/: 2, /* FWRITELN */
13317 /*::[*/0x008A/*::]*/: 2, /* FWRITE */
13318 /*::[*/0x008C/*::]*/: 1, /* DATEVALUE */
13319 /*::[*/0x008D/*::]*/: 1, /* TIMEVALUE */
13320 /*::[*/0x008E/*::]*/: 3, /* SLN */
13321 /*::[*/0x008F/*::]*/: 4, /* SYD */
13322 /*::[*/0x0090/*::]*/: 4, /* DDB */
13323 /*::[*/0x00A1/*::]*/: 1, /* DIALOG.BOX */
13324 /*::[*/0x00A2/*::]*/: 1, /* CLEAN */
13325 /*::[*/0x00A3/*::]*/: 1, /* MDETERM */
13326 /*::[*/0x00A4/*::]*/: 1, /* MINVERSE */
13327 /*::[*/0x00A5/*::]*/: 2, /* MMULT */
13328 /*::[*/0x00AC/*::]*/: 1, /* WHILE */
13329 /*::[*/0x00AF/*::]*/: 2, /* INITIATE */
13330 /*::[*/0x00B0/*::]*/: 2, /* REQUEST */
13331 /*::[*/0x00B1/*::]*/: 3, /* POKE */
13332 /*::[*/0x00B2/*::]*/: 2, /* EXECUTE */
13333 /*::[*/0x00B3/*::]*/: 1, /* TERMINATE */
13334 /*::[*/0x00B8/*::]*/: 1, /* FACT */
13335 /*::[*/0x00BA/*::]*/: 1, /* GET.WORKSPACE */
13336 /*::[*/0x00BD/*::]*/: 3, /* DPRODUCT */
13337 /*::[*/0x00BE/*::]*/: 1, /* ISNONTEXT */
13338 /*::[*/0x00C3/*::]*/: 3, /* DSTDEVP */
13339 /*::[*/0x00C4/*::]*/: 3, /* DVARP */
13340 /*::[*/0x00C5/*::]*/: 1, /* TRUNC */
13341 /*::[*/0x00C6/*::]*/: 1, /* ISLOGICAL */
13342 /*::[*/0x00C7/*::]*/: 3, /* DCOUNTA */
13343 /*::[*/0x00C9/*::]*/: 1, /* UNREGISTER */
13344 /*::[*/0x00CF/*::]*/: 4, /* REPLACEB */
13345 /*::[*/0x00D2/*::]*/: 3, /* MIDB */
13346 /*::[*/0x00D3/*::]*/: 1, /* LENB */
13347 /*::[*/0x00D4/*::]*/: 2, /* ROUNDUP */
13348 /*::[*/0x00D5/*::]*/: 2, /* ROUNDDOWN */
13349 /*::[*/0x00D6/*::]*/: 1, /* ASC */
13350 /*::[*/0x00D7/*::]*/: 1, /* DBCS */
13351 /*::[*/0x00E1/*::]*/: 0, /* END.IF */
13352 /*::[*/0x00E5/*::]*/: 1, /* SINH */
13353 /*::[*/0x00E6/*::]*/: 1, /* COSH */
13354 /*::[*/0x00E7/*::]*/: 1, /* TANH */
13355 /*::[*/0x00E8/*::]*/: 1, /* ASINH */
13356 /*::[*/0x00E9/*::]*/: 1, /* ACOSH */
13357 /*::[*/0x00EA/*::]*/: 1, /* ATANH */
13358 /*::[*/0x00EB/*::]*/: 3, /* DGET */
13359 /*::[*/0x00F4/*::]*/: 1, /* INFO */
13360 /*::[*/0x00F7/*::]*/: 4, /* DB */
13361 /*::[*/0x00FC/*::]*/: 2, /* FREQUENCY */
13362 /*::[*/0x0101/*::]*/: 1, /* EVALUATE */
13363 /*::[*/0x0105/*::]*/: 1, /* ERROR.TYPE */
13364 /*::[*/0x010F/*::]*/: 1, /* GAMMALN */
13365 /*::[*/0x0111/*::]*/: 4, /* BINOMDIST */
13366 /*::[*/0x0112/*::]*/: 2, /* CHIDIST */
13367 /*::[*/0x0113/*::]*/: 2, /* CHIINV */
13368 /*::[*/0x0114/*::]*/: 2, /* COMBIN */
13369 /*::[*/0x0115/*::]*/: 3, /* CONFIDENCE */
13370 /*::[*/0x0116/*::]*/: 3, /* CRITBINOM */
13371 /*::[*/0x0117/*::]*/: 1, /* EVEN */
13372 /*::[*/0x0118/*::]*/: 3, /* EXPONDIST */
13373 /*::[*/0x0119/*::]*/: 3, /* FDIST */
13374 /*::[*/0x011A/*::]*/: 3, /* FINV */
13375 /*::[*/0x011B/*::]*/: 1, /* FISHER */
13376 /*::[*/0x011C/*::]*/: 1, /* FISHERINV */
13377 /*::[*/0x011D/*::]*/: 2, /* FLOOR */
13378 /*::[*/0x011E/*::]*/: 4, /* GAMMADIST */
13379 /*::[*/0x011F/*::]*/: 3, /* GAMMAINV */
13380 /*::[*/0x0120/*::]*/: 2, /* CEILING */
13381 /*::[*/0x0121/*::]*/: 4, /* HYPGEOMDIST */
13382 /*::[*/0x0122/*::]*/: 3, /* LOGNORMDIST */
13383 /*::[*/0x0123/*::]*/: 3, /* LOGINV */
13384 /*::[*/0x0124/*::]*/: 3, /* NEGBINOMDIST */
13385 /*::[*/0x0125/*::]*/: 4, /* NORMDIST */
13386 /*::[*/0x0126/*::]*/: 1, /* NORMSDIST */
13387 /*::[*/0x0127/*::]*/: 3, /* NORMINV */
13388 /*::[*/0x0128/*::]*/: 1, /* NORMSINV */
13389 /*::[*/0x0129/*::]*/: 3, /* STANDARDIZE */
13390 /*::[*/0x012A/*::]*/: 1, /* ODD */
13391 /*::[*/0x012B/*::]*/: 2, /* PERMUT */
13392 /*::[*/0x012C/*::]*/: 3, /* POISSON */
13393 /*::[*/0x012D/*::]*/: 3, /* TDIST */
13394 /*::[*/0x012E/*::]*/: 4, /* WEIBULL */
13395 /*::[*/0x012F/*::]*/: 2, /* SUMXMY2 */
13396 /*::[*/0x0130/*::]*/: 2, /* SUMX2MY2 */
13397 /*::[*/0x0131/*::]*/: 2, /* SUMX2PY2 */
13398 /*::[*/0x0132/*::]*/: 2, /* CHITEST */
13399 /*::[*/0x0133/*::]*/: 2, /* CORREL */
13400 /*::[*/0x0134/*::]*/: 2, /* COVAR */
13401 /*::[*/0x0135/*::]*/: 3, /* FORECAST */
13402 /*::[*/0x0136/*::]*/: 2, /* FTEST */
13403 /*::[*/0x0137/*::]*/: 2, /* INTERCEPT */
13404 /*::[*/0x0138/*::]*/: 2, /* PEARSON */
13405 /*::[*/0x0139/*::]*/: 2, /* RSQ */
13406 /*::[*/0x013A/*::]*/: 2, /* STEYX */
13407 /*::[*/0x013B/*::]*/: 2, /* SLOPE */
13408 /*::[*/0x013C/*::]*/: 4, /* TTEST */
13409 /*::[*/0x0145/*::]*/: 2, /* LARGE */
13410 /*::[*/0x0146/*::]*/: 2, /* SMALL */
13411 /*::[*/0x0147/*::]*/: 2, /* QUARTILE */
13412 /*::[*/0x0148/*::]*/: 2, /* PERCENTILE */
13413 /*::[*/0x014B/*::]*/: 2, /* TRIMMEAN */
13414 /*::[*/0x014C/*::]*/: 2, /* TINV */
13415 /*::[*/0x0151/*::]*/: 2, /* POWER */
13416 /*::[*/0x0156/*::]*/: 1, /* RADIANS */
13417 /*::[*/0x0157/*::]*/: 1, /* DEGREES */
13418 /*::[*/0x015A/*::]*/: 2, /* COUNTIF */
13419 /*::[*/0x015B/*::]*/: 1, /* COUNTBLANK */
13420 /*::[*/0x015E/*::]*/: 4, /* ISPMT */
13421 /*::[*/0x015F/*::]*/: 3, /* DATEDIF */
13422 /*::[*/0x0160/*::]*/: 1, /* DATESTRING */
13423 /*::[*/0x0161/*::]*/: 2, /* NUMBERSTRING */
13424 /*::[*/0x0168/*::]*/: 1, /* PHONETIC */
13425 /*::[*/0x0170/*::]*/: 1, /* BAHTTEXT */
13426 /*::[*/0x0171/*::]*/: 1, /* THAIDAYOFWEEK */
13427 /*::[*/0x0172/*::]*/: 1, /* THAIDIGIT */
13428 /*::[*/0x0173/*::]*/: 1, /* THAIMONTHOFYEAR */
13429 /*::[*/0x0174/*::]*/: 1, /* THAINUMSOUND */
13430 /*::[*/0x0175/*::]*/: 1, /* THAINUMSTRING */
13431 /*::[*/0x0176/*::]*/: 1, /* THAISTRINGLENGTH */
13432 /*::[*/0x0177/*::]*/: 1, /* ISTHAIDIGIT */
13433 /*::[*/0x0178/*::]*/: 1, /* ROUNDBAHTDOWN */
13434 /*::[*/0x0179/*::]*/: 1, /* ROUNDBAHTUP */
13435 /*::[*/0x017A/*::]*/: 1, /* THAIYEAR */
13436 /*::[*/0x017E/*::]*/: 3, /* CUBEMEMBERPROPERTY */
13437 /*::[*/0x0181/*::]*/: 1, /* HEX2DEC */
13438 /*::[*/0x0188/*::]*/: 1, /* OCT2DEC */
13439 /*::[*/0x0189/*::]*/: 1, /* BIN2DEC */
13440 /*::[*/0x018C/*::]*/: 2, /* IMSUB */
13441 /*::[*/0x018D/*::]*/: 2, /* IMDIV */
13442 /*::[*/0x018E/*::]*/: 2, /* IMPOWER */
13443 /*::[*/0x018F/*::]*/: 1, /* IMABS */
13444 /*::[*/0x0190/*::]*/: 1, /* IMSQRT */
13445 /*::[*/0x0191/*::]*/: 1, /* IMLN */
13446 /*::[*/0x0192/*::]*/: 1, /* IMLOG2 */
13447 /*::[*/0x0193/*::]*/: 1, /* IMLOG10 */
13448 /*::[*/0x0194/*::]*/: 1, /* IMSIN */
13449 /*::[*/0x0195/*::]*/: 1, /* IMCOS */
13450 /*::[*/0x0196/*::]*/: 1, /* IMEXP */
13451 /*::[*/0x0197/*::]*/: 1, /* IMARGUMENT */
13452 /*::[*/0x0198/*::]*/: 1, /* IMCONJUGATE */
13453 /*::[*/0x0199/*::]*/: 1, /* IMAGINARY */
13454 /*::[*/0x019A/*::]*/: 1, /* IMREAL */
13455 /*::[*/0x019E/*::]*/: 4, /* SERIESSUM */
13456 /*::[*/0x019F/*::]*/: 1, /* FACTDOUBLE */
13457 /*::[*/0x01A0/*::]*/: 1, /* SQRTPI */
13458 /*::[*/0x01A1/*::]*/: 2, /* QUOTIENT */
13459 /*::[*/0x01A4/*::]*/: 1, /* ISEVEN */
13460 /*::[*/0x01A5/*::]*/: 1, /* ISODD */
13461 /*::[*/0x01A6/*::]*/: 2, /* MROUND */
13462 /*::[*/0x01A8/*::]*/: 1, /* ERFC */
13463 /*::[*/0x01A9/*::]*/: 2, /* BESSELJ */
13464 /*::[*/0x01AA/*::]*/: 2, /* BESSELK */
13465 /*::[*/0x01AB/*::]*/: 2, /* BESSELY */
13466 /*::[*/0x01AC/*::]*/: 2, /* BESSELI */
13467 /*::[*/0x01AE/*::]*/: 3, /* XNPV */
13468 /*::[*/0x01B6/*::]*/: 3, /* TBILLEQ */
13469 /*::[*/0x01B7/*::]*/: 3, /* TBILLPRICE */
13470 /*::[*/0x01B8/*::]*/: 3, /* TBILLYIELD */
13471 /*::[*/0x01BB/*::]*/: 2, /* DOLLARDE */
13472 /*::[*/0x01BC/*::]*/: 2, /* DOLLARFR */
13473 /*::[*/0x01BD/*::]*/: 2, /* NOMINAL */
13474 /*::[*/0x01BE/*::]*/: 2, /* EFFECT */
13475 /*::[*/0x01BF/*::]*/: 6, /* CUMPRINC */
13476 /*::[*/0x01C0/*::]*/: 6, /* CUMIPMT */
13477 /*::[*/0x01C1/*::]*/: 2, /* EDATE */
13478 /*::[*/0x01C2/*::]*/: 2, /* EOMONTH */
13479 /*::[*/0x01D0/*::]*/: 2, /* RANDBETWEEN */
13480 /*::[*/0x01D4/*::]*/: 3, /* CONVERT */
13481 /*::[*/0x01DC/*::]*/: 2, /* FVSCHEDULE */
13482 /*::[*/0x01DF/*::]*/: 1, /* CUBESETCOUNT */
13483 /*::[*/0x01E0/*::]*/: 2, /* IFERROR */
13484 /*::[*/0xFFFF/*::]*/: 0
13485};
13486/* [MS-XLSX] 2.2.3 Functions */
13487/* [MS-XLSB] 2.5.97.10 Ftab */
13488var XLSXFutureFunctions = {
13489 "_xlfn.ACOT": "ACOT",
13490 "_xlfn.ACOTH": "ACOTH",
13491 "_xlfn.AGGREGATE": "AGGREGATE",
13492 "_xlfn.ARABIC": "ARABIC",
13493 "_xlfn.AVERAGEIF": "AVERAGEIF",
13494 "_xlfn.AVERAGEIFS": "AVERAGEIFS",
13495 "_xlfn.BASE": "BASE",
13496 "_xlfn.BETA.DIST": "BETA.DIST",
13497 "_xlfn.BETA.INV": "BETA.INV",
13498 "_xlfn.BINOM.DIST": "BINOM.DIST",
13499 "_xlfn.BINOM.DIST.RANGE": "BINOM.DIST.RANGE",
13500 "_xlfn.BINOM.INV": "BINOM.INV",
13501 "_xlfn.BITAND": "BITAND",
13502 "_xlfn.BITLSHIFT": "BITLSHIFT",
13503 "_xlfn.BITOR": "BITOR",
13504 "_xlfn.BITRSHIFT": "BITRSHIFT",
13505 "_xlfn.BITXOR": "BITXOR",
13506 "_xlfn.CEILING.MATH": "CEILING.MATH",
13507 "_xlfn.CEILING.PRECISE": "CEILING.PRECISE",
13508 "_xlfn.CHISQ.DIST": "CHISQ.DIST",
13509 "_xlfn.CHISQ.DIST.RT": "CHISQ.DIST.RT",
13510 "_xlfn.CHISQ.INV": "CHISQ.INV",
13511 "_xlfn.CHISQ.INV.RT": "CHISQ.INV.RT",
13512 "_xlfn.CHISQ.TEST": "CHISQ.TEST",
13513 "_xlfn.COMBINA": "COMBINA",
13514 "_xlfn.CONCAT": "CONCAT",
13515 "_xlfn.CONFIDENCE.NORM": "CONFIDENCE.NORM",
13516 "_xlfn.CONFIDENCE.T": "CONFIDENCE.T",
13517 "_xlfn.COT": "COT",
13518 "_xlfn.COTH": "COTH",
13519 "_xlfn.COUNTIFS": "COUNTIFS",
13520 "_xlfn.COVARIANCE.P": "COVARIANCE.P",
13521 "_xlfn.COVARIANCE.S": "COVARIANCE.S",
13522 "_xlfn.CSC": "CSC",
13523 "_xlfn.CSCH": "CSCH",
13524 "_xlfn.DAYS": "DAYS",
13525 "_xlfn.DECIMAL": "DECIMAL",
13526 "_xlfn.ECMA.CEILING": "ECMA.CEILING",
13527 "_xlfn.ERF.PRECISE": "ERF.PRECISE",
13528 "_xlfn.ERFC.PRECISE": "ERFC.PRECISE",
13529 "_xlfn.EXPON.DIST": "EXPON.DIST",
13530 "_xlfn.F.DIST": "F.DIST",
13531 "_xlfn.F.DIST.RT": "F.DIST.RT",
13532 "_xlfn.F.INV": "F.INV",
13533 "_xlfn.F.INV.RT": "F.INV.RT",
13534 "_xlfn.F.TEST": "F.TEST",
13535 "_xlfn.FILTERXML": "FILTERXML",
13536 "_xlfn.FLOOR.MATH": "FLOOR.MATH",
13537 "_xlfn.FLOOR.PRECISE": "FLOOR.PRECISE",
13538 "_xlfn.FORECAST.ETS": "FORECAST.ETS",
13539 "_xlfn.FORECAST.ETS.CONFINT": "FORECAST.ETS.CONFINT",
13540 "_xlfn.FORECAST.ETS.SEASONALITY": "FORECAST.ETS.SEASONALITY",
13541 "_xlfn.FORECAST.ETS.STAT": "FORECAST.ETS.STAT",
13542 "_xlfn.FORECAST.LINEAR": "FORECAST.LINEAR",
13543 "_xlfn.FORMULATEXT": "FORMULATEXT",
13544 "_xlfn.GAMMA": "GAMMA",
13545 "_xlfn.GAMMA.DIST": "GAMMA.DIST",
13546 "_xlfn.GAMMA.INV": "GAMMA.INV",
13547 "_xlfn.GAMMALN.PRECISE": "GAMMALN.PRECISE",
13548 "_xlfn.GAUSS": "GAUSS",
13549 "_xlfn.HYPGEOM.DIST": "HYPGEOM.DIST",
13550 "_xlfn.IFERROR": "IFERROR",
13551 "_xlfn.IFNA": "IFNA",
13552 "_xlfn.IFS": "IFS",
13553 "_xlfn.IMCOSH": "IMCOSH",
13554 "_xlfn.IMCOT": "IMCOT",
13555 "_xlfn.IMCSC": "IMCSC",
13556 "_xlfn.IMCSCH": "IMCSCH",
13557 "_xlfn.IMSEC": "IMSEC",
13558 "_xlfn.IMSECH": "IMSECH",
13559 "_xlfn.IMSINH": "IMSINH",
13560 "_xlfn.IMTAN": "IMTAN",
13561 "_xlfn.ISFORMULA": "ISFORMULA",
13562 "_xlfn.ISO.CEILING": "ISO.CEILING",
13563 "_xlfn.ISOWEEKNUM": "ISOWEEKNUM",
13564 "_xlfn.LOGNORM.DIST": "LOGNORM.DIST",
13565 "_xlfn.LOGNORM.INV": "LOGNORM.INV",
13566 "_xlfn.MAXIFS": "MAXIFS",
13567 "_xlfn.MINIFS": "MINIFS",
13568 "_xlfn.MODE.MULT": "MODE.MULT",
13569 "_xlfn.MODE.SNGL": "MODE.SNGL",
13570 "_xlfn.MUNIT": "MUNIT",
13571 "_xlfn.NEGBINOM.DIST": "NEGBINOM.DIST",
13572 "_xlfn.NETWORKDAYS.INTL": "NETWORKDAYS.INTL",
13573 "_xlfn.NIGBINOM": "NIGBINOM",
13574 "_xlfn.NORM.DIST": "NORM.DIST",
13575 "_xlfn.NORM.INV": "NORM.INV",
13576 "_xlfn.NORM.S.DIST": "NORM.S.DIST",
13577 "_xlfn.NORM.S.INV": "NORM.S.INV",
13578 "_xlfn.NUMBERVALUE": "NUMBERVALUE",
13579 "_xlfn.PDURATION": "PDURATION",
13580 "_xlfn.PERCENTILE.EXC": "PERCENTILE.EXC",
13581 "_xlfn.PERCENTILE.INC": "PERCENTILE.INC",
13582 "_xlfn.PERCENTRANK.EXC": "PERCENTRANK.EXC",
13583 "_xlfn.PERCENTRANK.INC": "PERCENTRANK.INC",
13584 "_xlfn.PERMUTATIONA": "PERMUTATIONA",
13585 "_xlfn.PHI": "PHI",
13586 "_xlfn.POISSON.DIST": "POISSON.DIST",
13587 "_xlfn.QUARTILE.EXC": "QUARTILE.EXC",
13588 "_xlfn.QUARTILE.INC": "QUARTILE.INC",
13589 "_xlfn.QUERYSTRING": "QUERYSTRING",
13590 "_xlfn.RANK.AVG": "RANK.AVG",
13591 "_xlfn.RANK.EQ": "RANK.EQ",
13592 "_xlfn.RRI": "RRI",
13593 "_xlfn.SEC": "SEC",
13594 "_xlfn.SECH": "SECH",
13595 "_xlfn.SHEET": "SHEET",
13596 "_xlfn.SHEETS": "SHEETS",
13597 "_xlfn.SKEW.P": "SKEW.P",
13598 "_xlfn.STDEV.P": "STDEV.P",
13599 "_xlfn.STDEV.S": "STDEV.S",
13600 "_xlfn.SUMIFS": "SUMIFS",
13601 "_xlfn.SWITCH": "SWITCH",
13602 "_xlfn.T.DIST": "T.DIST",
13603 "_xlfn.T.DIST.2T": "T.DIST.2T",
13604 "_xlfn.T.DIST.RT": "T.DIST.RT",
13605 "_xlfn.T.INV": "T.INV",
13606 "_xlfn.T.INV.2T": "T.INV.2T",
13607 "_xlfn.T.TEST": "T.TEST",
13608 "_xlfn.TEXTJOIN": "TEXTJOIN",
13609 "_xlfn.UNICHAR": "UNICHAR",
13610 "_xlfn.UNICODE": "UNICODE",
13611 "_xlfn.VAR.P": "VAR.P",
13612 "_xlfn.VAR.S": "VAR.S",
13613 "_xlfn.WEBSERVICE": "WEBSERVICE",
13614 "_xlfn.WEIBULL.DIST": "WEIBULL.DIST",
13615 "_xlfn.WORKDAY.INTL": "WORKDAY.INTL",
13616 "_xlfn.XOR": "XOR",
13617 "_xlfn.Z.TEST": "Z.TEST"
13618};
13619
13620/* Part 3 TODO: actually parse formulae */
13621function ods_to_csf_formula(f/*:string*/)/*:string*/ {
13622 if(f.slice(0,3) == "of:") f = f.slice(3);
13623 /* 5.2 Basic Expressions */
13624 if(f.charCodeAt(0) == 61) {
13625 f = f.slice(1);
13626 if(f.charCodeAt(0) == 61) f = f.slice(1);
13627 }
13628 f = f.replace(/COM\.MICROSOFT\./g, "");
13629 /* Part 3 Section 5.8 References */
13630 f = f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, function($$, $1) { return $1.replace(/\./g,""); });
13631 /* TODO: something other than this */
13632 f = f.replace(/\[.(#[A-Z]*[?!])\]/g, "$1");
13633 return f.replace(/[;~]/g,",").replace(/\|/g,";");
13634}
13635
13636function csf_to_ods_formula(f/*:string*/)/*:string*/ {
13637 var o = "of:=" + f.replace(crefregex, "$1[.$2$3$4$5]").replace(/\]:\[/g,":");
13638 /* TODO: something other than this */
13639 return o.replace(/;/g, "|").replace(/,/g,";");
13640}
13641
13642function ods_to_csf_3D(r/*:string*/)/*:[string, string]*/ {
13643 var a = r.split(":");
13644 var s = a[0].split(".")[0];
13645 return [s, a[0].split(".")[1] + (a.length > 1 ? (":" + (a[1].split(".")[1] || a[1].split(".")[0])) : "")];
13646}
13647
13648function csf_to_ods_3D(r/*:string*/)/*:string*/ {
13649 return r.replace(/\./,"!");
13650}
13651
13652var strs = {}; // shared strings
13653var _ssfopts = {}; // spreadsheet formatting options
13654
13655RELS.WS = [
13656 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
13657 "http://purl.oclc.org/ooxml/officeDocument/relationships/worksheet"
13658];
13659
13660/*global Map */
13661var browser_has_Map = typeof Map !== 'undefined';
13662
13663function get_sst_id(sst/*:SST*/, str/*:string*/, rev)/*:number*/ {
13664 var i = 0, len = sst.length;
13665 if(rev) {
13666 if(browser_has_Map ? rev.has(str) : Object.prototype.hasOwnProperty.call(rev, str)) {
13667 var revarr = browser_has_Map ? rev.get(str) : rev[str];
13668 for(; i < revarr.length; ++i) {
13669 if(sst[revarr[i]].t === str) { sst.Count ++; return revarr[i]; }
13670 }
13671 }
13672 } else for(; i < len; ++i) {
13673 if(sst[i].t === str) { sst.Count ++; return i; }
13674 }
13675 sst[len] = ({t:str}/*:any*/); sst.Count ++; sst.Unique ++;
13676 if(rev) {
13677 if(browser_has_Map) {
13678 if(!rev.has(str)) rev.set(str, []);
13679 rev.get(str).push(len);
13680 } else {
13681 if(!Object.prototype.hasOwnProperty.call(rev, str)) rev[str] = [];
13682 rev[str].push(len);
13683 }
13684 }
13685 return len;
13686}
13687
13688function col_obj_w(C/*:number*/, col) {
13689 var p = ({min:C+1,max:C+1}/*:any*/);
13690 /* wch (chars), wpx (pixels) */
13691 var wch = -1;
13692 if(col.MDW) MDW = col.MDW;
13693 if(col.width != null) p.customWidth = 1;
13694 else if(col.wpx != null) wch = px2char(col.wpx);
13695 else if(col.wch != null) wch = col.wch;
13696 if(wch > -1) { p.width = char2width(wch); p.customWidth = 1; }
13697 else if(col.width != null) p.width = col.width;
13698 if(col.hidden) p.hidden = true;
13699 if(col.level != null) { p.outlineLevel = p.level = col.level; }
13700 return p;
13701}
13702
13703function default_margins(margins/*:Margins*/, mode/*:?string*/) {
13704 if(!margins) return;
13705 var defs = [0.7, 0.7, 0.75, 0.75, 0.3, 0.3];
13706 if(mode == 'xlml') defs = [1, 1, 1, 1, 0.5, 0.5];
13707 if(margins.left == null) margins.left = defs[0];
13708 if(margins.right == null) margins.right = defs[1];
13709 if(margins.top == null) margins.top = defs[2];
13710 if(margins.bottom == null) margins.bottom = defs[3];
13711 if(margins.header == null) margins.header = defs[4];
13712 if(margins.footer == null) margins.footer = defs[5];
13713}
13714
13715function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) {
13716 var z = opts.revssf[cell.z != null ? cell.z : "General"];
13717 var i = 0x3c, len = styles.length;
13718 if(z == null && opts.ssf) {
13719 for(; i < 0x188; ++i) if(opts.ssf[i] == null) {
13720 SSF.load(cell.z, i);
13721 // $FlowIgnore
13722 opts.ssf[i] = cell.z;
13723 opts.revssf[cell.z] = z = i;
13724 break;
13725 }
13726 }
13727 for(i = 0; i != len; ++i) if(styles[i].numFmtId === z) return i;
13728 styles[len] = {
13729 numFmtId:z,
13730 fontId:0,
13731 fillId:0,
13732 borderId:0,
13733 xfId:0,
13734 applyNumberFormat:1
13735 };
13736 return len;
13737}
13738
13739function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) {
13740 try {
13741 if(opts.cellNF) p.z = SSF._table[fmtid];
13742 } catch(e) { if(opts.WTF) throw e; }
13743 if(p.t === 'z' && !opts.cellStyles) return;
13744 if(p.t === 'd' && typeof p.v === 'string') p.v = parseDate(p.v);
13745 if((!opts || opts.cellText !== false) && p.t !== 'z') try {
13746 if(SSF._table[fmtid] == null) SSF.load(SSFImplicit[fmtid] || "General", fmtid);
13747 if(p.t === 'e') p.w = p.w || BErr[p.v];
13748 else if(fmtid === 0) {
13749 if(p.t === 'n') {
13750 if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
13751 else p.w = SSF._general_num(p.v);
13752 }
13753 else if(p.t === 'd') {
13754 var dd = datenum(p.v);
13755 if((dd|0) === dd) p.w = SSF._general_int(dd);
13756 else p.w = SSF._general_num(dd);
13757 }
13758 else if(p.v === undefined) return "";
13759 else p.w = SSF._general(p.v,_ssfopts);
13760 }
13761 else if(p.t === 'd') p.w = SSF.format(fmtid,datenum(p.v),_ssfopts);
13762 else p.w = SSF.format(fmtid,p.v,_ssfopts);
13763 } catch(e) { if(opts.WTF) throw e; }
13764 if(!opts.cellStyles) return;
13765 if(fillid != null) try {
13766 p.s = styles.Fills[fillid];
13767 if (p.s.fgColor && p.s.fgColor.theme && !p.s.fgColor.rgb) {
13768 p.s.fgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.fgColor.theme].rgb, p.s.fgColor.tint || 0);
13769 if(opts.WTF) p.s.fgColor.raw_rgb = themes.themeElements.clrScheme[p.s.fgColor.theme].rgb;
13770 }
13771 if (p.s.bgColor && p.s.bgColor.theme) {
13772 p.s.bgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.bgColor.theme].rgb, p.s.bgColor.tint || 0);
13773 if(opts.WTF) p.s.bgColor.raw_rgb = themes.themeElements.clrScheme[p.s.bgColor.theme].rgb;
13774 }
13775 } catch(e) { if(opts.WTF && styles.Fills) throw e; }
13776}
13777
13778function check_ws(ws/*:Worksheet*/, sname/*:string*/, i/*:number*/) {
13779 if(ws && ws['!ref']) {
13780 var range = safe_decode_range(ws['!ref']);
13781 if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
13782 }
13783}
13784function parse_ws_xml_dim(ws/*:Worksheet*/, s/*:string*/) {
13785 var d = safe_decode_range(s);
13786 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);
13787}
13788var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*[\/]?>/g;
13789var sheetdataregex = /<(?:\w+:)?sheetData[^>]*>([\s\S]*)<\/(?:\w+:)?sheetData>/;
13790var hlinkregex = /<(?:\w:)?hyperlink [^>]*>/mg;
13791var dimregex = /"(\w*:\w*)"/;
13792var colregex = /<(?:\w:)?col\b[^>]*[\/]?>/g;
13793var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
13794var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g;
13795var sheetprregex = /<(?:\w:)?sheetPr\b(?:[^>a-z][^>]*)?\/>/;
13796var sheetprregex2= /<(?:\w:)?sheetPr[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetPr)>/;
13797var svsregex = /<(?:\w:)?sheetViews[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetViews)>/;
13798
13799/* 18.3 Worksheets */
13800function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ {
13801 if(!data) return data;
13802 if(!rels) rels = {'!id':{}};
13803 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
13804
13805 /* 18.3.1.99 worksheet CT_Worksheet */
13806 var s = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
13807 var refguess/*:Range*/ = ({s: {r:2000000, c:2000000}, e: {r:0, c:0} }/*:any*/);
13808
13809 var data1 = "", data2 = "";
13810 var mtch/*:?any*/ = data.match(sheetdataregex);
13811 if(mtch) {
13812 data1 = data.slice(0, mtch.index);
13813 data2 = data.slice(mtch.index + mtch[0].length);
13814 } else data1 = data2 = data;
13815
13816 /* 18.3.1.82 sheetPr CT_SheetPr */
13817 var sheetPr = data1.match(sheetprregex);
13818 if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
13819 else if((sheetPr = data1.match(sheetprregex2))) parse_ws_xml_sheetpr2(sheetPr[0], sheetPr[1]||"", s, wb, idx, styles, themes);
13820
13821 /* 18.3.1.35 dimension CT_SheetDimension */
13822 var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
13823 if(ridx > 0) {
13824 var ref = data1.slice(ridx,ridx+50).match(dimregex);
13825 if(ref) parse_ws_xml_dim(s, ref[1]);
13826 }
13827
13828 /* 18.3.1.88 sheetViews CT_SheetViews */
13829 var svs = data1.match(svsregex);
13830 if(svs && svs[1]) parse_ws_xml_sheetviews(svs[1], wb);
13831
13832 /* 18.3.1.17 cols CT_Cols */
13833 var columns/*:Array<ColInfo>*/ = [];
13834 if(opts.cellStyles) {
13835 /* 18.3.1.13 col CT_Col */
13836 var cols = data1.match(colregex);
13837 if(cols) parse_ws_xml_cols(columns, cols);
13838 }
13839
13840 /* 18.3.1.80 sheetData CT_SheetData ? */
13841 if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
13842
13843 /* 18.3.1.2 autoFilter CT_AutoFilter */
13844 var afilter = data2.match(afregex);
13845 if(afilter) s['!autofilter'] = parse_ws_xml_autofilter(afilter[0]);
13846
13847 /* 18.3.1.55 mergeCells CT_MergeCells */
13848 var merges/*:Array<Range>*/ = [];
13849 var _merge = data2.match(mergecregex);
13850 if(_merge) for(ridx = 0; ridx != _merge.length; ++ridx)
13851 merges[ridx] = safe_decode_range(_merge[ridx].slice(_merge[ridx].indexOf("\"")+1));
13852
13853 /* 18.3.1.48 hyperlinks CT_Hyperlinks */
13854 var hlink = data2.match(hlinkregex);
13855 if(hlink) parse_ws_xml_hlinks(s, hlink, rels);
13856
13857 /* 18.3.1.62 pageMargins CT_PageMargins */
13858 var margins = data2.match(marginregex);
13859 if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));
13860
13861 if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
13862 if(opts.sheetRows > 0 && s["!ref"]) {
13863 var tmpref = safe_decode_range(s["!ref"]);
13864 if(opts.sheetRows <= +tmpref.e.r) {
13865 tmpref.e.r = opts.sheetRows - 1;
13866 if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
13867 if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
13868 if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c;
13869 if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c;
13870 s["!fullref"] = s["!ref"];
13871 s["!ref"] = encode_range(tmpref);
13872 }
13873 }
13874 if(columns.length > 0) s["!cols"] = columns;
13875 if(merges.length > 0) s["!merges"] = merges;
13876 return s;
13877}
13878
13879function write_ws_xml_merges(merges/*:Array<Range>*/)/*:string*/ {
13880 if(merges.length === 0) return "";
13881 var o = '<mergeCells count="' + merges.length + '">';
13882 for(var i = 0; i != merges.length; ++i) o += '<mergeCell ref="' + encode_range(merges[i]) + '"/>';
13883 return o + '</mergeCells>';
13884}
13885
13886/* 18.3.1.82-3 sheetPr CT_ChartsheetPr / CT_SheetPr */
13887function parse_ws_xml_sheetpr(sheetPr/*:string*/, s, wb/*:WBWBProps*/, idx/*:number*/) {
13888 var data = parsexmltag(sheetPr);
13889 if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
13890 if(data.codeName) wb.Sheets[idx].CodeName = unescapexml(utf8read(data.codeName));
13891}
13892function parse_ws_xml_sheetpr2(sheetPr/*:string*/, body/*:string*/, s, wb/*:WBWBProps*/, idx/*:number*/, styles, themes) {
13893 parse_ws_xml_sheetpr(sheetPr.slice(0, sheetPr.indexOf(">")), s, wb, idx);
13894}
13895function write_ws_xml_sheetpr(ws, wb, idx, opts, o) {
13896 var needed = false;
13897 var props = {}, payload = null;
13898 if(opts.bookType !== 'xlsx' && wb.vbaraw) {
13899 var cname = wb.SheetNames[idx];
13900 try { if(wb.Workbook) cname = wb.Workbook.Sheets[idx].CodeName || cname; } catch(e) {}
13901 needed = true;
13902 props.codeName = utf8write(escapexml(cname));
13903 }
13904
13905 if(ws && ws["!outline"]) {
13906 var outlineprops = {summaryBelow:1, summaryRight:1};
13907 if(ws["!outline"].above) outlineprops.summaryBelow = 0;
13908 if(ws["!outline"].left) outlineprops.summaryRight = 0;
13909 payload = (payload||"") + writextag('outlinePr', null, outlineprops);
13910 }
13911
13912 if(!needed && !payload) return;
13913 o[o.length] = (writextag('sheetPr', payload, props));
13914}
13915
13916/* 18.3.1.85 sheetProtection CT_SheetProtection */
13917var sheetprot_deffalse = ["objects", "scenarios", "selectLockedCells", "selectUnlockedCells"];
13918var sheetprot_deftrue = [
13919 "formatColumns", "formatRows", "formatCells",
13920 "insertColumns", "insertRows", "insertHyperlinks",
13921 "deleteColumns", "deleteRows",
13922 "sort", "autoFilter", "pivotTables"
13923];
13924function write_ws_xml_protection(sp)/*:string*/ {
13925 // algorithmName, hashValue, saltValue, spinCount
13926 var o = ({sheet:1}/*:any*/);
13927 sheetprot_deffalse.forEach(function(n) { if(sp[n] != null && sp[n]) o[n] = "1"; });
13928 sheetprot_deftrue.forEach(function(n) { if(sp[n] != null && !sp[n]) o[n] = "0"; });
13929 /* TODO: algorithm */
13930 if(sp.password) o.password = crypto_CreatePasswordVerifier_Method1(sp.password).toString(16).toUpperCase();
13931 return writextag('sheetProtection', null, o);
13932}
13933
13934function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
13935 var dense = Array.isArray(s);
13936 for(var i = 0; i != data.length; ++i) {
13937 var val = parsexmltag(utf8read(data[i]), true);
13938 if(!val.ref) return;
13939 var rel = ((rels || {})['!id']||[])[val.id];
13940 if(rel) {
13941 val.Target = rel.Target;
13942 if(val.location) val.Target += "#"+unescapexml(val.location);
13943 } else {
13944 val.Target = "#" + unescapexml(val.location);
13945 rel = {Target: val.Target, TargetMode: 'Internal'};
13946 }
13947 val.Rel = rel;
13948 if(val.tooltip) { val.Tooltip = val.tooltip; delete val.tooltip; }
13949 var rng = safe_decode_range(val.ref);
13950 for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
13951 var addr = encode_cell({c:C,r:R});
13952 if(dense) {
13953 if(!s[R]) s[R] = [];
13954 if(!s[R][C]) s[R][C] = {t:"z",v:undefined};
13955 s[R][C].l = val;
13956 } else {
13957 if(!s[addr]) s[addr] = {t:"z",v:undefined};
13958 s[addr].l = val;
13959 }
13960 }
13961 }
13962}
13963
13964function parse_ws_xml_margins(margin) {
13965 var o = {};
13966 ["left", "right", "top", "bottom", "header", "footer"].forEach(function(k) {
13967 if(margin[k]) o[k] = parseFloat(margin[k]);
13968 });
13969 return o;
13970}
13971function write_ws_xml_margins(margin)/*:string*/ {
13972 default_margins(margin);
13973 return writextag('pageMargins', null, margin);
13974}
13975
13976function parse_ws_xml_cols(columns, cols) {
13977 var seencol = false;
13978 for(var coli = 0; coli != cols.length; ++coli) {
13979 var coll = parsexmltag(cols[coli], true);
13980 if(coll.hidden) coll.hidden = parsexmlbool(coll.hidden);
13981 var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
13982 if(coll.outlineLevel) coll.level = (+coll.outlineLevel || 0);
13983 delete coll.min; delete coll.max; coll.width = +coll.width;
13984 if(!seencol && coll.width) { seencol = true; find_mdw_colw(coll.width); }
13985 process_col(coll);
13986 while(colm <= colM) columns[colm++] = dup(coll);
13987 }
13988}
13989function write_ws_xml_cols(ws, cols)/*:string*/ {
13990 var o = ["<cols>"], col;
13991 for(var i = 0; i != cols.length; ++i) {
13992 if(!(col = cols[i])) continue;
13993 o[o.length] = (writextag('col', null, col_obj_w(i, col)));
13994 }
13995 o[o.length] = "</cols>";
13996 return o.join("");
13997}
13998
13999function parse_ws_xml_autofilter(data/*:string*/) {
14000 var o = { ref: (data.match(/ref="([^"]*)"/)||[])[1]};
14001 return o;
14002}
14003function write_ws_xml_autofilter(data, ws, wb, idx)/*:string*/ {
14004 var ref = typeof data.ref == "string" ? data.ref : encode_range(data.ref);
14005 if(!wb.Workbook) wb.Workbook = ({Sheets:[]}/*:any*/);
14006 if(!wb.Workbook.Names) wb.Workbook.Names = [];
14007 var names/*: Array<any> */ = wb.Workbook.Names;
14008 var range = decode_range(ref);
14009 if(range.s.r == range.e.r) { range.e.r = decode_range(ws["!ref"]).e.r; ref = encode_range(range); }
14010 for(var i = 0; i < names.length; ++i) {
14011 var name = names[i];
14012 if(name.Name != '_xlnm._FilterDatabase') continue;
14013 if(name.Sheet != idx) continue;
14014 name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break;
14015 }
14016 if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref });
14017 return writextag("autoFilter", null, {ref:ref});
14018}
14019
14020/* 18.3.1.88 sheetViews CT_SheetViews */
14021/* 18.3.1.87 sheetView CT_SheetView */
14022var sviewregex = /<(?:\w:)?sheetView(?:[^>a-z][^>]*)?\/?>/;
14023function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) {
14024 if(!wb.Views) wb.Views = [{}];
14025 (data.match(sviewregex)||[]).forEach(function(r/*:string*/, i/*:number*/) {
14026 var tag = parsexmltag(r);
14027 // $FlowIgnore
14028 if(!wb.Views[i]) wb.Views[i] = {};
14029 // $FlowIgnore
14030 if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
14031 // $FlowIgnore
14032 if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
14033 });
14034}
14035function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
14036 var sview = ({workbookViewId:"0"}/*:any*/);
14037 // $FlowIgnore
14038 if((((wb||{}).Workbook||{}).Views||[])[0]) sview.rightToLeft = wb.Workbook.Views[0].RTL ? "1" : "0";
14039 return writextag("sheetViews", writextag("sheetView", null, sview), {});
14040}
14041
14042function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string*/ {
14043 if(cell.v === undefined && typeof cell.f !== "string" || cell.t === 'z') return "";
14044 var vv = "";
14045 var oldt = cell.t, oldv = cell.v;
14046 if(cell.t !== "z") switch(cell.t) {
14047 case 'b': vv = cell.v ? "1" : "0"; break;
14048 case 'n': vv = ''+cell.v; break;
14049 case 'e': vv = BErr[cell.v]; break;
14050 case 'd':
14051 if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
14052 else {
14053 cell = dup(cell);
14054 cell.t = 'n';
14055 vv = ''+(cell.v = datenum(parseDate(cell.v)));
14056 }
14057 if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
14058 break;
14059 default: vv = cell.v; break;
14060 }
14061 var v = writetag('v', escapexml(vv)), o = ({r:ref}/*:any*/);
14062 /* TODO: cell style */
14063 var os = get_cell_style(opts.cellXfs, cell, opts);
14064 if(os !== 0) o.s = os;
14065 switch(cell.t) {
14066 case 'n': break;
14067 case 'd': o.t = "d"; break;
14068 case 'b': o.t = "b"; break;
14069 case 'e': o.t = "e"; break;
14070 case 'z': break;
14071 default: if(cell.v == null) { delete cell.t; break; }
14072 if(cell.v.length > 32767) throw new Error("Text length must not exceed 32767 characters");
14073 if(opts && opts.bookSST) {
14074 v = writetag('v', ''+get_sst_id(opts.Strings, cell.v, opts.revStrings));
14075 o.t = "s"; break;
14076 }
14077 o.t = "str"; break;
14078 }
14079 if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; }
14080 if(typeof cell.f == "string" && cell.f) {
14081 var ff = cell.F && cell.F.slice(0, ref.length) == ref ? {t:"array", ref:cell.F} : null;
14082 v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : "");
14083 }
14084 if(cell.l) ws['!links'].push([ref, cell.l]);
14085 if(cell.c) ws['!comments'].push([ref, cell.c]);
14086 return writextag('c', v, o);
14087}
14088
14089var parse_ws_xml_data = (function() {
14090 var cellregex = /<(?:\w+:)?c[ \/>]/, rowregex = /<\/(?:\w+:)?row>/;
14091 var rregex = /r=["']([^"']*)["']/, isregex = /<(?:\w+:)?is>([\S\s]*?)<\/(?:\w+:)?is>/;
14092 var refregex = /ref=["']([^"']*)["']/;
14093 var match_v = matchtag("v"), match_f = matchtag("f");
14094
14095return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles) {
14096 var ri = 0, x = "", cells/*:Array<string>*/ = [], cref/*:?Array<string>*/ = [], idx=0, i=0, cc=0, d="", p/*:any*/;
14097 var tag, tagr = 0, tagc = 0;
14098 var sstr, ftag;
14099 var fmtid = 0, fillid = 0;
14100 var do_format = Array.isArray(styles.CellXf), cf;
14101 var arrayf/*:Array<[Range, string]>*/ = [];
14102 var sharedf = [];
14103 var dense = Array.isArray(s);
14104 var rows/*:Array<RowInfo>*/ = [], rowobj = {}, rowrite = false;
14105 var sheetStubs = !!opts.sheetStubs;
14106 for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
14107 x = marr[mt].trim();
14108 var xlen = x.length;
14109 if(xlen === 0) continue;
14110
14111 /* 18.3.1.73 row CT_Row */
14112 var rstarti = 0;
14113 outa: for(ri = 0; ri < xlen; ++ri) switch(/*x.charCodeAt(ri)*/x[ri]) {
14114 case ">" /*62*/:
14115 if(/*x.charCodeAt(ri-1) != 47*/x[ri-1] != "/") { ++ri; break outa; }
14116 if(opts && opts.cellStyles) {
14117 // TODO: avoid duplication
14118 tag = parsexmltag(x.slice(rstarti,ri), true);
14119 tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
14120 if(opts.sheetRows && opts.sheetRows < tagr) continue;
14121 rowobj = {}; rowrite = false;
14122 if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
14123 if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; }
14124 if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
14125 if(rowrite) rows[tagr-1] = rowobj;
14126 }
14127 break;
14128 case "<" /*60*/: rstarti = ri; break;
14129 }
14130 if(rstarti >= ri) break;
14131 tag = parsexmltag(x.slice(rstarti,ri), true);
14132 tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
14133 if(opts.sheetRows && opts.sheetRows < tagr) continue;
14134 if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
14135 if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
14136
14137 if(opts && opts.cellStyles) {
14138 rowobj = {}; rowrite = false;
14139 if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
14140 if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; }
14141 if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
14142 if(rowrite) rows[tagr-1] = rowobj;
14143 }
14144
14145 /* 18.3.1.4 c CT_Cell */
14146 cells = x.slice(ri).split(cellregex);
14147 for(var rslice = 0; rslice != cells.length; ++rslice) if(cells[rslice].trim().charAt(0) != "<") break;
14148 cells = cells.slice(rslice);
14149 for(ri = 0; ri != cells.length; ++ri) {
14150 x = cells[ri].trim();
14151 if(x.length === 0) continue;
14152 cref = x.match(rregex); idx = ri; i=0; cc=0;
14153 x = "<c " + (x.slice(0,1)=="<"?">":"") + x;
14154 if(cref != null && cref.length === 2) {
14155 idx = 0; d=cref[1];
14156 for(i=0; i != d.length; ++i) {
14157 if((cc=d.charCodeAt(i)-64) < 1 || cc > 26) break;
14158 idx = 26*idx + cc;
14159 }
14160 --idx;
14161 tagc = idx;
14162 } else ++tagc;
14163 for(i = 0; i != x.length; ++i) if(x.charCodeAt(i) === 62) break; ++i;
14164 tag = parsexmltag(x.slice(0,i), true);
14165 if(!tag.r) tag.r = encode_cell({r:tagr-1, c:tagc});
14166 d = x.slice(i);
14167 p = ({t:""}/*:any*/);
14168
14169 if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
14170 if(opts.cellFormula) {
14171 if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') {
14172 /* TODO: match against XLSXFutureFunctions */
14173 p.f=unescapexml(utf8read(cref[1])).replace(/\r\n/g, "\n");
14174 if(!opts.xlfn) p.f = _xlfn(p.f);
14175 if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
14176 p.F = (d.match(refregex)||[])[1];
14177 if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
14178 } else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
14179 // TODO: parse formula
14180 ftag = parsexmltag(cref[0]);
14181 var ___f = unescapexml(utf8read(cref[1]));
14182 if(!opts.xlfn) ___f = _xlfn(___f);
14183 sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
14184 }
14185 } else if((cref=d.match(/<f[^>]*\/>/))) {
14186 ftag = parsexmltag(cref[0]);
14187 if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
14188 }
14189 /* TODO: factor out contains logic */
14190 var _tag = decode_cell(tag.r);
14191 for(i = 0; i < arrayf.length; ++i)
14192 if(_tag.r >= arrayf[i][0].s.r && _tag.r <= arrayf[i][0].e.r)
14193 if(_tag.c >= arrayf[i][0].s.c && _tag.c <= arrayf[i][0].e.c)
14194 p.F = arrayf[i][1];
14195 }
14196
14197 if(tag.t == null && p.v === undefined) {
14198 if(p.f || p.F) {
14199 p.v = 0; p.t = "n";
14200 } else if(!sheetStubs) continue;
14201 else p.t = "z";
14202 }
14203 else p.t = tag.t || "n";
14204 if(guess.s.c > tagc) guess.s.c = tagc;
14205 if(guess.e.c < tagc) guess.e.c = tagc;
14206 /* 18.18.11 t ST_CellType */
14207 switch(p.t) {
14208 case 'n':
14209 if(p.v == "" || p.v == null) {
14210 if(!sheetStubs) continue;
14211 p.t = 'z';
14212 } else p.v = parseFloat(p.v);
14213 break;
14214 case 's':
14215 if(typeof p.v == 'undefined') {
14216 if(!sheetStubs) continue;
14217 p.t = 'z';
14218 } else {
14219 sstr = strs[parseInt(p.v, 10)];
14220 p.v = sstr.t;
14221 p.r = sstr.r;
14222 if(opts.cellHTML) p.h = sstr.h;
14223 }
14224 break;
14225 case 'str':
14226 p.t = "s";
14227 p.v = (p.v!=null) ? utf8read(p.v) : '';
14228 if(opts.cellHTML) p.h = escapehtml(p.v);
14229 break;
14230 case 'inlineStr':
14231 cref = d.match(isregex);
14232 p.t = 's';
14233 if(cref != null && (sstr = parse_si(cref[1]))) {
14234 p.v = sstr.t;
14235 if(opts.cellHTML) p.h = sstr.h;
14236 } else p.v = "";
14237 break;
14238 case 'b': p.v = parsexmlbool(p.v); break;
14239 case 'd':
14240 if(opts.cellDates) p.v = parseDate(p.v, 1);
14241 else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; }
14242 break;
14243 /* error string in .w, number in .v */
14244 case 'e':
14245 if(!opts || opts.cellText !== false) p.w = p.v;
14246 p.v = RBErr[p.v]; break;
14247 }
14248 /* formatting */
14249 fmtid = fillid = 0;
14250 cf = null;
14251 if(do_format && tag.s !== undefined) {
14252 cf = styles.CellXf[tag.s];
14253 if(cf != null) {
14254 if(cf.numFmtId != null) fmtid = cf.numFmtId;
14255 if(opts.cellStyles) {
14256 if(cf.fillId != null) fillid = cf.fillId;
14257 }
14258 }
14259 }
14260 safe_format(p, fmtid, fillid, opts, themes, styles);
14261 if(opts.cellDates && do_format && p.t == 'n' && SSF.is_date(SSF._table[fmtid])) { p.t = 'd'; p.v = numdate(p.v); }
14262 if(dense) {
14263 var _r = decode_cell(tag.r);
14264 if(!s[_r.r]) s[_r.r] = [];
14265 s[_r.r][_r.c] = p;
14266 } else s[tag.r] = p;
14267 }
14268 }
14269 if(rows.length > 0) s['!rows'] = rows;
14270}; })();
14271
14272function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*//*::, rels*/)/*:string*/ {
14273 var o/*:Array<string>*/ = [], r/*:Array<string>*/ = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols/*:Array<string>*/ = [], R=0, C=0, rows = ws['!rows'];
14274 var dense = Array.isArray(ws);
14275 var params = ({r:rr}/*:any*/), row/*:RowInfo*/, height = -1;
14276 for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
14277 for(R = range.s.r; R <= range.e.r; ++R) {
14278 r = [];
14279 rr = encode_row(R);
14280 for(C = range.s.c; C <= range.e.c; ++C) {
14281 ref = cols[C] + rr;
14282 var _cell = dense ? (ws[R]||[])[C]: ws[ref];
14283 if(_cell === undefined) continue;
14284 if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
14285 }
14286 if(r.length > 0 || (rows && rows[R])) {
14287 params = ({r:rr}/*:any*/);
14288 if(rows && rows[R]) {
14289 row = rows[R];
14290 if(row.hidden) params.hidden = 1;
14291 height = -1;
14292 if(row.hpx) height = px2pt(row.hpx);
14293 else if(row.hpt) height = row.hpt;
14294 if(height > -1) { params.ht = height; params.customHeight = 1; }
14295 if(row.level) { params.outlineLevel = row.level; }
14296 }
14297 o[o.length] = (writextag('row', r.join(""), params));
14298 }
14299 }
14300 if(rows) for(; R < rows.length; ++R) {
14301 if(rows && rows[R]) {
14302 params = ({r:R+1}/*:any*/);
14303 row = rows[R];
14304 if(row.hidden) params.hidden = 1;
14305 height = -1;
14306 if (row.hpx) height = px2pt(row.hpx);
14307 else if (row.hpt) height = row.hpt;
14308 if (height > -1) { params.ht = height; params.customHeight = 1; }
14309 if (row.level) { params.outlineLevel = row.level; }
14310 o[o.length] = (writextag('row', "", params));
14311 }
14312 }
14313 return o.join("");
14314}
14315
14316var WS_XML_ROOT = writextag('worksheet', null, {
14317 'xmlns': XMLNS.main[0],
14318 'xmlns:r': XMLNS.r
14319});
14320
14321function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
14322 var o = [XML_HEADER, WS_XML_ROOT];
14323 var s = wb.SheetNames[idx], sidx = 0, rdata = "";
14324 var ws = wb.Sheets[s];
14325 if(ws == null) ws = {};
14326 var ref = ws['!ref'] || 'A1';
14327 var range = safe_decode_range(ref);
14328 if(range.e.c > 0x3FFF || range.e.r > 0xFFFFF) {
14329 if(opts.WTF) throw new Error("Range " + ref + " exceeds format limit A1:XFD1048576");
14330 range.e.c = Math.min(range.e.c, 0x3FFF);
14331 range.e.r = Math.min(range.e.c, 0xFFFFF);
14332 ref = encode_range(range);
14333 }
14334 if(!rels) rels = {};
14335 ws['!comments'] = [];
14336 var _drawing = [];
14337
14338 write_ws_xml_sheetpr(ws, wb, idx, opts, o);
14339
14340 o[o.length] = (writextag('dimension', null, {'ref': ref}));
14341
14342 o[o.length] = write_ws_xml_sheetviews(ws, opts, idx, wb);
14343
14344 /* TODO: store in WB, process styles */
14345 if(opts.sheetFormat) o[o.length] = (writextag('sheetFormatPr', null, {
14346 defaultRowHeight:opts.sheetFormat.defaultRowHeight||'16',
14347 baseColWidth:opts.sheetFormat.baseColWidth||'10',
14348 outlineLevelRow:opts.sheetFormat.outlineLevelRow||'7'
14349 }));
14350
14351 if(ws['!cols'] != null && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols']));
14352
14353 o[sidx = o.length] = '<sheetData/>';
14354 ws['!links'] = [];
14355 if(ws['!ref'] != null) {
14356 rdata = write_ws_xml_data(ws, opts, idx, wb, rels);
14357 if(rdata.length > 0) o[o.length] = (rdata);
14358 }
14359 if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
14360
14361 /* sheetCalcPr */
14362
14363 if(ws['!protect']) o[o.length] = write_ws_xml_protection(ws['!protect']);
14364
14365 /* protectedRanges */
14366 /* scenarios */
14367
14368 if(ws['!autofilter'] != null) o[o.length] = write_ws_xml_autofilter(ws['!autofilter'], ws, wb, idx);
14369
14370 /* sortState */
14371 /* dataConsolidate */
14372 /* customSheetViews */
14373
14374 if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
14375
14376 /* phoneticPr */
14377 /* conditionalFormatting */
14378 /* dataValidations */
14379
14380 var relc = -1, rel, rId = -1;
14381 if(/*::(*/ws['!links']/*::||[])*/.length > 0) {
14382 o[o.length] = "<hyperlinks>";
14383 /*::(*/ws['!links']/*::||[])*/.forEach(function(l) {
14384 if(!l[1].Target) return;
14385 rel = ({"ref":l[0]}/*:any*/);
14386 if(l[1].Target.charAt(0) != "#") {
14387 rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), RELS.HLINK);
14388 rel["r:id"] = "rId"+rId;
14389 }
14390 if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1));
14391 if(l[1].Tooltip) rel.tooltip = escapexml(l[1].Tooltip);
14392 o[o.length] = writextag("hyperlink",null,rel);
14393 });
14394 o[o.length] = "</hyperlinks>";
14395 }
14396 delete ws['!links'];
14397
14398 /* printOptions */
14399
14400 if(ws['!margins'] != null) o[o.length] = write_ws_xml_margins(ws['!margins']);
14401
14402 /* pageSetup */
14403 /* headerFooter */
14404 /* rowBreaks */
14405 /* colBreaks */
14406 /* customProperties */
14407 /* cellWatches */
14408
14409 if(!opts || opts.ignoreEC || (opts.ignoreEC == (void 0))) o[o.length] = writetag("ignoredErrors", writextag("ignoredError", null, {numberStoredAsText:1, sqref:ref}));
14410
14411 /* smartTags */
14412
14413 if(_drawing.length > 0) {
14414 rId = add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
14415 o[o.length] = writextag("drawing", null, {"r:id":"rId" + rId});
14416 ws['!drawing'] = _drawing;
14417 }
14418
14419 if(ws['!comments'].length > 0) {
14420 rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML);
14421 o[o.length] = writextag("legacyDrawing", null, {"r:id":"rId" + rId});
14422 ws['!legacy'] = rId;
14423 }
14424
14425 /* legacyDrawingHF */
14426 /* picture */
14427 /* oleObjects */
14428 /* controls */
14429 /* webPublishItems */
14430 /* tableParts */
14431 /* extLst */
14432
14433 if(o.length>1) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
14434 return o.join("");
14435}
14436
14437/* [MS-XLSB] 2.4.726 BrtRowHdr */
14438function parse_BrtRowHdr(data, length) {
14439 var z = ({}/*:any*/);
14440 var tgt = data.l + length;
14441 z.r = data.read_shift(4);
14442 data.l += 4; // TODO: ixfe
14443 var miyRw = data.read_shift(2);
14444 data.l += 1; // TODO: top/bot padding
14445 var flags = data.read_shift(1);
14446 data.l = tgt;
14447 if(flags & 0x07) z.level = flags & 0x07;
14448 if(flags & 0x10) z.hidden = true;
14449 if(flags & 0x20) z.hpt = miyRw / 20;
14450 return z;
14451}
14452function write_BrtRowHdr(R/*:number*/, range, ws) {
14453 var o = new_buf(17+8*16);
14454 var row = (ws['!rows']||[])[R]||{};
14455 o.write_shift(4, R);
14456
14457 o.write_shift(4, 0); /* TODO: ixfe */
14458
14459 var miyRw = 0x0140;
14460 if(row.hpx) miyRw = px2pt(row.hpx) * 20;
14461 else if(row.hpt) miyRw = row.hpt * 20;
14462 o.write_shift(2, miyRw);
14463
14464 o.write_shift(1, 0); /* top/bot padding */
14465
14466 var flags = 0x0;
14467 if(row.level) flags |= row.level;
14468 if(row.hidden) flags |= 0x10;
14469 if(row.hpx || row.hpt) flags |= 0x20;
14470 o.write_shift(1, flags);
14471
14472 o.write_shift(1, 0); /* phonetic guide */
14473
14474 /* [MS-XLSB] 2.5.8 BrtColSpan explains the mechanism */
14475 var ncolspan = 0, lcs = o.l;
14476 o.l += 4;
14477
14478 var caddr = {r:R, c:0};
14479 for(var i = 0; i < 16; ++i) {
14480 if((range.s.c > ((i+1) << 10)) || (range.e.c < (i << 10))) continue;
14481 var first = -1, last = -1;
14482 for(var j = (i<<10); j < ((i+1)<<10); ++j) {
14483 caddr.c = j;
14484 var cell = Array.isArray(ws) ? (ws[caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)];
14485 if(cell) { if(first < 0) first = j; last = j; }
14486 }
14487 if(first < 0) continue;
14488 ++ncolspan;
14489 o.write_shift(4, first);
14490 o.write_shift(4, last);
14491 }
14492
14493 var l = o.l;
14494 o.l = lcs;
14495 o.write_shift(4, ncolspan);
14496 o.l = l;
14497
14498 return o.length > o.l ? o.slice(0, o.l) : o;
14499}
14500function write_row_header(ba, ws, range, R) {
14501 var o = write_BrtRowHdr(R, range, ws);
14502 if((o.length > 17) || (ws['!rows']||[])[R]) write_record(ba, 'BrtRowHdr', o);
14503}
14504
14505/* [MS-XLSB] 2.4.820 BrtWsDim */
14506var parse_BrtWsDim = parse_UncheckedRfX;
14507var write_BrtWsDim = write_UncheckedRfX;
14508
14509/* [MS-XLSB] 2.4.821 BrtWsFmtInfo */
14510function parse_BrtWsFmtInfo(/*::data, length*/) {
14511}
14512//function write_BrtWsFmtInfo(ws, o) { }
14513
14514/* [MS-XLSB] 2.4.823 BrtWsProp */
14515function parse_BrtWsProp(data, length) {
14516 var z = {};
14517 var f = data[data.l]; ++data.l;
14518 z.above = !(f & 0x40);
14519 z.left = !(f & 0x80);
14520 /* TODO: pull flags */
14521 data.l += 18;
14522 z.name = parse_XLSBCodeName(data, length - 19);
14523 return z;
14524}
14525function write_BrtWsProp(str, outl, o) {
14526 if(o == null) o = new_buf(84+4*str.length);
14527 var f = 0xC0;
14528 if(outl) {
14529 if(outl.above) f &= ~0x40;
14530 if(outl.left) f &= ~0x80;
14531 }
14532 o.write_shift(1, f);
14533 for(var i = 1; i < 3; ++i) o.write_shift(1,0);
14534 write_BrtColor({auto:1}, o);
14535 o.write_shift(-4,-1);
14536 o.write_shift(-4,-1);
14537 write_XLSBCodeName(str, o);
14538 return o.slice(0, o.l);
14539}
14540
14541/* [MS-XLSB] 2.4.306 BrtCellBlank */
14542function parse_BrtCellBlank(data) {
14543 var cell = parse_XLSBCell(data);
14544 return [cell];
14545}
14546function write_BrtCellBlank(cell, ncell, o) {
14547 if(o == null) o = new_buf(8);
14548 return write_XLSBCell(ncell, o);
14549}
14550function parse_BrtShortBlank(data) {
14551 var cell = parse_XLSBShortCell(data);
14552 return [cell];
14553}
14554function write_BrtShortBlank(cell, ncell, o) {
14555 if(o == null) o = new_buf(4);
14556 return write_XLSBShortCell(ncell, o);
14557}
14558
14559/* [MS-XLSB] 2.4.307 BrtCellBool */
14560function parse_BrtCellBool(data) {
14561 var cell = parse_XLSBCell(data);
14562 var fBool = data.read_shift(1);
14563 return [cell, fBool, 'b'];
14564}
14565function write_BrtCellBool(cell, ncell, o) {
14566 if(o == null) o = new_buf(9);
14567 write_XLSBCell(ncell, o);
14568 o.write_shift(1, cell.v ? 1 : 0);
14569 return o;
14570}
14571function parse_BrtShortBool(data) {
14572 var cell = parse_XLSBShortCell(data);
14573 var fBool = data.read_shift(1);
14574 return [cell, fBool, 'b'];
14575}
14576function write_BrtShortBool(cell, ncell, o) {
14577 if(o == null) o = new_buf(5);
14578 write_XLSBShortCell(ncell, o);
14579 o.write_shift(1, cell.v ? 1 : 0);
14580 return o;
14581}
14582
14583/* [MS-XLSB] 2.4.308 BrtCellError */
14584function parse_BrtCellError(data) {
14585 var cell = parse_XLSBCell(data);
14586 var bError = data.read_shift(1);
14587 return [cell, bError, 'e'];
14588}
14589function write_BrtCellError(cell, ncell, o) {
14590 if(o == null) o = new_buf(9);
14591 write_XLSBCell(ncell, o);
14592 o.write_shift(1, cell.v);
14593 return o;
14594}
14595function parse_BrtShortError(data) {
14596 var cell = parse_XLSBShortCell(data);
14597 var bError = data.read_shift(1);
14598 return [cell, bError, 'e'];
14599}
14600function write_BrtShortError(cell, ncell, o) {
14601 if(o == null) o = new_buf(8);
14602 write_XLSBShortCell(ncell, o);
14603 o.write_shift(1, cell.v);
14604 o.write_shift(2, 0);
14605 o.write_shift(1, 0);
14606 return o;
14607}
14608
14609
14610/* [MS-XLSB] 2.4.311 BrtCellIsst */
14611function parse_BrtCellIsst(data) {
14612 var cell = parse_XLSBCell(data);
14613 var isst = data.read_shift(4);
14614 return [cell, isst, 's'];
14615}
14616function write_BrtCellIsst(cell, ncell, o) {
14617 if(o == null) o = new_buf(12);
14618 write_XLSBCell(ncell, o);
14619 o.write_shift(4, ncell.v);
14620 return o;
14621}
14622function parse_BrtShortIsst(data) {
14623 var cell = parse_XLSBShortCell(data);
14624 var isst = data.read_shift(4);
14625 return [cell, isst, 's'];
14626}
14627function write_BrtShortIsst(cell, ncell, o) {
14628 if(o == null) o = new_buf(8);
14629 write_XLSBShortCell(ncell, o);
14630 o.write_shift(4, ncell.v);
14631 return o;
14632}
14633
14634/* [MS-XLSB] 2.4.313 BrtCellReal */
14635function parse_BrtCellReal(data) {
14636 var cell = parse_XLSBCell(data);
14637 var value = parse_Xnum(data);
14638 return [cell, value, 'n'];
14639}
14640function write_BrtCellReal(cell, ncell, o) {
14641 if(o == null) o = new_buf(16);
14642 write_XLSBCell(ncell, o);
14643 write_Xnum(cell.v, o);
14644 return o;
14645}
14646function parse_BrtShortReal(data) {
14647 var cell = parse_XLSBShortCell(data);
14648 var value = parse_Xnum(data);
14649 return [cell, value, 'n'];
14650}
14651function write_BrtShortReal(cell, ncell, o) {
14652 if(o == null) o = new_buf(12);
14653 write_XLSBShortCell(ncell, o);
14654 write_Xnum(cell.v, o);
14655 return o;
14656}
14657
14658/* [MS-XLSB] 2.4.314 BrtCellRk */
14659function parse_BrtCellRk(data) {
14660 var cell = parse_XLSBCell(data);
14661 var value = parse_RkNumber(data);
14662 return [cell, value, 'n'];
14663}
14664function write_BrtCellRk(cell, ncell, o) {
14665 if(o == null) o = new_buf(12);
14666 write_XLSBCell(ncell, o);
14667 write_RkNumber(cell.v, o);
14668 return o;
14669}
14670function parse_BrtShortRk(data) {
14671 var cell = parse_XLSBShortCell(data);
14672 var value = parse_RkNumber(data);
14673 return [cell, value, 'n'];
14674}
14675function write_BrtShortRk(cell, ncell, o) {
14676 if(o == null) o = new_buf(8);
14677 write_XLSBShortCell(ncell, o);
14678 write_RkNumber(cell.v, o);
14679 return o;
14680}
14681
14682
14683/* [MS-XLSB] 2.4.317 BrtCellSt */
14684function parse_BrtCellSt(data) {
14685 var cell = parse_XLSBCell(data);
14686 var value = parse_XLWideString(data);
14687 return [cell, value, 'str'];
14688}
14689function write_BrtCellSt(cell, ncell, o) {
14690 if(o == null) o = new_buf(12 + 4 * cell.v.length);
14691 write_XLSBCell(ncell, o);
14692 write_XLWideString(cell.v, o);
14693 return o.length > o.l ? o.slice(0, o.l) : o;
14694}
14695function parse_BrtShortSt(data) {
14696 var cell = parse_XLSBShortCell(data);
14697 var value = parse_XLWideString(data);
14698 return [cell, value, 'str'];
14699}
14700function write_BrtShortSt(cell, ncell, o) {
14701 if(o == null) o = new_buf(8 + 4 * cell.v.length);
14702 write_XLSBShortCell(ncell, o);
14703 write_XLWideString(cell.v, o);
14704 return o.length > o.l ? o.slice(0, o.l) : o;
14705}
14706
14707/* [MS-XLSB] 2.4.653 BrtFmlaBool */
14708function parse_BrtFmlaBool(data, length, opts) {
14709 var end = data.l + length;
14710 var cell = parse_XLSBCell(data);
14711 cell.r = opts['!row'];
14712 var value = data.read_shift(1);
14713 var o = [cell, value, 'b'];
14714 if(opts.cellFormula) {
14715 data.l += 2;
14716 var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
14717 o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
14718 }
14719 else data.l = end;
14720 return o;
14721}
14722
14723/* [MS-XLSB] 2.4.654 BrtFmlaError */
14724function parse_BrtFmlaError(data, length, opts) {
14725 var end = data.l + length;
14726 var cell = parse_XLSBCell(data);
14727 cell.r = opts['!row'];
14728 var value = data.read_shift(1);
14729 var o = [cell, value, 'e'];
14730 if(opts.cellFormula) {
14731 data.l += 2;
14732 var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
14733 o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
14734 }
14735 else data.l = end;
14736 return o;
14737}
14738
14739/* [MS-XLSB] 2.4.655 BrtFmlaNum */
14740function parse_BrtFmlaNum(data, length, opts) {
14741 var end = data.l + length;
14742 var cell = parse_XLSBCell(data);
14743 cell.r = opts['!row'];
14744 var value = parse_Xnum(data);
14745 var o = [cell, value, 'n'];
14746 if(opts.cellFormula) {
14747 data.l += 2;
14748 var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
14749 o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
14750 }
14751 else data.l = end;
14752 return o;
14753}
14754
14755/* [MS-XLSB] 2.4.656 BrtFmlaString */
14756function parse_BrtFmlaString(data, length, opts) {
14757 var end = data.l + length;
14758 var cell = parse_XLSBCell(data);
14759 cell.r = opts['!row'];
14760 var value = parse_XLWideString(data);
14761 var o = [cell, value, 'str'];
14762 if(opts.cellFormula) {
14763 data.l += 2;
14764 var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
14765 o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
14766 }
14767 else data.l = end;
14768 return o;
14769}
14770
14771/* [MS-XLSB] 2.4.682 BrtMergeCell */
14772var parse_BrtMergeCell = parse_UncheckedRfX;
14773var write_BrtMergeCell = write_UncheckedRfX;
14774/* [MS-XLSB] 2.4.107 BrtBeginMergeCells */
14775function write_BrtBeginMergeCells(cnt, o) {
14776 if(o == null) o = new_buf(4);
14777 o.write_shift(4, cnt);
14778 return o;
14779}
14780
14781/* [MS-XLSB] 2.4.662 BrtHLink */
14782function parse_BrtHLink(data, length/*::, opts*/) {
14783 var end = data.l + length;
14784 var rfx = parse_UncheckedRfX(data, 16);
14785 var relId = parse_XLNullableWideString(data);
14786 var loc = parse_XLWideString(data);
14787 var tooltip = parse_XLWideString(data);
14788 var display = parse_XLWideString(data);
14789 data.l = end;
14790 var o = ({rfx:rfx, relId:relId, loc:loc, display:display}/*:any*/);
14791 if(tooltip) o.Tooltip = tooltip;
14792 return o;
14793}
14794function write_BrtHLink(l, rId) {
14795 var o = new_buf(50+4*(l[1].Target.length + (l[1].Tooltip || "").length));
14796 write_UncheckedRfX({s:decode_cell(l[0]), e:decode_cell(l[0])}, o);
14797 write_RelID("rId" + rId, o);
14798 var locidx = l[1].Target.indexOf("#");
14799 var loc = locidx == -1 ? "" : l[1].Target.slice(locidx+1);
14800 write_XLWideString(loc || "", o);
14801 write_XLWideString(l[1].Tooltip || "", o);
14802 write_XLWideString("", o);
14803 return o.slice(0, o.l);
14804}
14805
14806/* [MS-XLSB] 2.4.692 BrtPane */
14807function parse_BrtPane(/*data, length, opts*/) {
14808}
14809
14810/* [MS-XLSB] 2.4.6 BrtArrFmla */
14811function parse_BrtArrFmla(data, length, opts) {
14812 var end = data.l + length;
14813 var rfx = parse_RfX(data, 16);
14814 var fAlwaysCalc = data.read_shift(1);
14815 var o = [rfx]; o[2] = fAlwaysCalc;
14816 if(opts.cellFormula) {
14817 var formula = parse_XLSBArrayParsedFormula(data, end - data.l, opts);
14818 o[1] = formula;
14819 } else data.l = end;
14820 return o;
14821}
14822
14823/* [MS-XLSB] 2.4.750 BrtShrFmla */
14824function parse_BrtShrFmla(data, length, opts) {
14825 var end = data.l + length;
14826 var rfx = parse_UncheckedRfX(data, 16);
14827 var o = [rfx];
14828 if(opts.cellFormula) {
14829 var formula = parse_XLSBSharedParsedFormula(data, end - data.l, opts);
14830 o[1] = formula;
14831 data.l = end;
14832 } else data.l = end;
14833 return o;
14834}
14835
14836/* [MS-XLSB] 2.4.323 BrtColInfo */
14837/* TODO: once XLS ColInfo is set, combine the functions */
14838function write_BrtColInfo(C/*:number*/, col, o) {
14839 if(o == null) o = new_buf(18);
14840 var p = col_obj_w(C, col);
14841 o.write_shift(-4, C);
14842 o.write_shift(-4, C);
14843 o.write_shift(4, (p.width || 10) * 256);
14844 o.write_shift(4, 0/*ixfe*/); // style
14845 var flags = 0;
14846 if(col.hidden) flags |= 0x01;
14847 if(typeof p.width == 'number') flags |= 0x02;
14848 if(col.level) flags |= (col.level << 8);
14849 o.write_shift(2, flags); // bit flag
14850 return o;
14851}
14852
14853/* [MS-XLSB] 2.4.678 BrtMargins */
14854var BrtMarginKeys = ["left","right","top","bottom","header","footer"];
14855function parse_BrtMargins(data/*::, length, opts*/)/*:Margins*/ {
14856 var margins = ({}/*:any*/);
14857 BrtMarginKeys.forEach(function(k) { margins[k] = parse_Xnum(data, 8); });
14858 return margins;
14859}
14860function write_BrtMargins(margins/*:Margins*/, o) {
14861 if(o == null) o = new_buf(6*8);
14862 default_margins(margins);
14863 BrtMarginKeys.forEach(function(k) { write_Xnum((margins/*:any*/)[k], o); });
14864 return o;
14865}
14866
14867/* [MS-XLSB] 2.4.299 BrtBeginWsView */
14868function parse_BrtBeginWsView(data/*::, length, opts*/) {
14869 var f = data.read_shift(2);
14870 data.l += 28;
14871 return { RTL: f & 0x20 };
14872}
14873function write_BrtBeginWsView(ws, Workbook, o) {
14874 if(o == null) o = new_buf(30);
14875 var f = 0x39c;
14876 if((((Workbook||{}).Views||[])[0]||{}).RTL) f |= 0x20;
14877 o.write_shift(2, f); // bit flag
14878 o.write_shift(4, 0);
14879 o.write_shift(4, 0); // view first row
14880 o.write_shift(4, 0); // view first col
14881 o.write_shift(1, 0); // gridline color ICV
14882 o.write_shift(1, 0);
14883 o.write_shift(2, 0);
14884 o.write_shift(2, 100); // zoom scale
14885 o.write_shift(2, 0);
14886 o.write_shift(2, 0);
14887 o.write_shift(2, 0);
14888 o.write_shift(4, 0); // workbook view id
14889 return o;
14890}
14891
14892/* [MS-XLSB] 2.4.309 BrtCellIgnoreEC */
14893function write_BrtCellIgnoreEC(ref) {
14894 var o = new_buf(24);
14895 o.write_shift(4, 4);
14896 o.write_shift(4, 1);
14897 write_UncheckedRfX(ref, o);
14898 return o;
14899}
14900
14901/* [MS-XLSB] 2.4.748 BrtSheetProtection */
14902function write_BrtSheetProtection(sp, o) {
14903 if(o == null) o = new_buf(16*4+2);
14904 o.write_shift(2, sp.password ? crypto_CreatePasswordVerifier_Method1(sp.password) : 0);
14905 o.write_shift(4, 1); // this record should not be written if no protection
14906 [
14907 ["objects", false], // fObjects
14908 ["scenarios", false], // fScenarios
14909 ["formatCells", true], // fFormatCells
14910 ["formatColumns", true], // fFormatColumns
14911 ["formatRows", true], // fFormatRows
14912 ["insertColumns", true], // fInsertColumns
14913 ["insertRows", true], // fInsertRows
14914 ["insertHyperlinks", true], // fInsertHyperlinks
14915 ["deleteColumns", true], // fDeleteColumns
14916 ["deleteRows", true], // fDeleteRows
14917 ["selectLockedCells", false], // fSelLockedCells
14918 ["sort", true], // fSort
14919 ["autoFilter", true], // fAutoFilter
14920 ["pivotTables", true], // fPivotTables
14921 ["selectUnlockedCells", false] // fSelUnlockedCells
14922 ].forEach(function(n) {
14923 /*:: if(o == null) throw "unreachable"; */
14924 if(n[1]) o.write_shift(4, sp[n[0]] != null && !sp[n[0]] ? 1 : 0);
14925 else o.write_shift(4, sp[n[0]] != null && sp[n[0]] ? 0 : 1);
14926 });
14927 return o;
14928}
14929
14930function parse_BrtDVal(/*data, length, opts*/) {
14931}
14932function parse_BrtDVal14(/*data, length, opts*/) {
14933}
14934/* [MS-XLSB] 2.1.7.61 Worksheet */
14935function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ {
14936 if(!data) return data;
14937 var opts = _opts || {};
14938 if(!rels) rels = {'!id':{}};
14939 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
14940 var s/*:Worksheet*/ = (opts.dense ? [] : {});
14941
14942 var ref;
14943 var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
14944
14945 var state/*:Array<string>*/ = [];
14946 var pass = false, end = false;
14947 var row, p, cf, R, C, addr, sstr, rr, cell/*:Cell*/;
14948 var merges/*:Array<Range>*/ = [];
14949 opts.biff = 12;
14950 opts['!row'] = 0;
14951
14952 var ai = 0, af = false;
14953
14954 var arrayf/*:Array<[Range, string]>*/ = [];
14955 var sharedf = {};
14956 var supbooks = opts.supbooks || /*::(*/wb/*:: :any)*/.supbooks || ([[]]/*:any*/);
14957 supbooks.sharedf = sharedf;
14958 supbooks.arrayf = arrayf;
14959 supbooks.SheetNames = wb.SheetNames || wb.Sheets.map(function(x) { return x.name; });
14960 if(!opts.supbooks) {
14961 opts.supbooks = supbooks;
14962 if(wb.Names) for(var i = 0; i < wb.Names.length; ++i) supbooks[0][i+1] = wb.Names[i];
14963 }
14964
14965 var colinfo/*:Array<ColInfo>*/ = [], rowinfo/*:Array<RowInfo>*/ = [];
14966 var seencol = false;
14967
14968 XLSBRecordEnum[0x0010] = { n:"BrtShortReal", f:parse_BrtShortReal };
14969
14970 recordhopper(data, function ws_parse(val, R_n, RT) {
14971 if(end) return;
14972 switch(RT) {
14973 case 0x0094: /* 'BrtWsDim' */
14974 ref = val; break;
14975 case 0x0000: /* 'BrtRowHdr' */
14976 row = val;
14977 if(opts.sheetRows && opts.sheetRows <= row.r) end=true;
14978 rr = encode_row(R = row.r);
14979 opts['!row'] = row.r;
14980 if(val.hidden || val.hpt || val.level != null) {
14981 if(val.hpt) val.hpx = pt2px(val.hpt);
14982 rowinfo[val.r] = val;
14983 }
14984 break;
14985
14986 case 0x0002: /* 'BrtCellRk' */
14987 case 0x0003: /* 'BrtCellError' */
14988 case 0x0004: /* 'BrtCellBool' */
14989 case 0x0005: /* 'BrtCellReal' */
14990 case 0x0006: /* 'BrtCellSt' */
14991 case 0x0007: /* 'BrtCellIsst' */
14992 case 0x0008: /* 'BrtFmlaString' */
14993 case 0x0009: /* 'BrtFmlaNum' */
14994 case 0x000A: /* 'BrtFmlaBool' */
14995 case 0x000B: /* 'BrtFmlaError' */
14996 case 0x000D: /* 'BrtShortRk' */
14997 case 0x000E: /* 'BrtShortError' */
14998 case 0x000F: /* 'BrtShortBool' */
14999 case 0x0010: /* 'BrtShortReal' */
15000 case 0x0011: /* 'BrtShortSt' */
15001 case 0x0012: /* 'BrtShortIsst' */
15002 p = ({t:val[2]}/*:any*/);
15003 switch(val[2]) {
15004 case 'n': p.v = val[1]; break;
15005 case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
15006 case 'b': p.v = val[1] ? true : false; break;
15007 case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break;
15008 case 'str': p.t = 's'; p.v = val[1]; break;
15009 }
15010 if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
15011 C = val[0].c == -1 ? C + 1 : val[0].c;
15012 if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
15013 else s[encode_col(C) + rr] = p;
15014 if(opts.cellFormula) {
15015 af = false;
15016 for(ai = 0; ai < arrayf.length; ++ai) {
15017 var aii = arrayf[ai];
15018 if(row.r >= aii[0].s.r && row.r <= aii[0].e.r)
15019 if(C >= aii[0].s.c && C <= aii[0].e.c) {
15020 p.F = encode_range(aii[0]); af = true;
15021 }
15022 }
15023 if(!af && val.length > 3) p.f = val[3];
15024 }
15025 if(refguess.s.r > row.r) refguess.s.r = row.r;
15026 if(refguess.s.c > C) refguess.s.c = C;
15027 if(refguess.e.r < row.r) refguess.e.r = row.r;
15028 if(refguess.e.c < C) refguess.e.c = C;
15029 if(opts.cellDates && cf && p.t == 'n' && SSF.is_date(SSF._table[cf.numFmtId])) {
15030 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); }
15031 }
15032 break;
15033
15034 case 0x0001: /* 'BrtCellBlank' */
15035 case 0x000C: /* 'BrtShortBlank' */
15036 if(!opts.sheetStubs || pass) break;
15037 p = ({t:'z',v:undefined}/*:any*/);
15038 C = val[0].c == -1 ? C + 1 : val[0].c;
15039 if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
15040 else s[encode_col(C) + rr] = p;
15041 if(refguess.s.r > row.r) refguess.s.r = row.r;
15042 if(refguess.s.c > C) refguess.s.c = C;
15043 if(refguess.e.r < row.r) refguess.e.r = row.r;
15044 if(refguess.e.c < C) refguess.e.c = C;
15045 break;
15046
15047 case 0x00B0: /* 'BrtMergeCell' */
15048 merges.push(val); break;
15049
15050 case 0x01EE: /* 'BrtHLink' */
15051 var rel = rels['!id'][val.relId];
15052 if(rel) {
15053 val.Target = rel.Target;
15054 if(val.loc) val.Target += "#"+val.loc;
15055 val.Rel = rel;
15056 } else if(val.relId == '') {
15057 val.Target = "#" + val.loc;
15058 }
15059 for(R=val.rfx.s.r;R<=val.rfx.e.r;++R) for(C=val.rfx.s.c;C<=val.rfx.e.c;++C) {
15060 if(opts.dense) {
15061 if(!s[R]) s[R] = [];
15062 if(!s[R][C]) s[R][C] = {t:'z',v:undefined};
15063 s[R][C].l = val;
15064 } else {
15065 addr = encode_cell({c:C,r:R});
15066 if(!s[addr]) s[addr] = {t:'z',v:undefined};
15067 s[addr].l = val;
15068 }
15069 }
15070 break;
15071
15072 case 0x01AA: /* 'BrtArrFmla' */
15073 if(!opts.cellFormula) break;
15074 arrayf.push(val);
15075 cell = ((opts.dense ? s[R][C] : s[encode_col(C) + rr])/*:any*/);
15076 cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
15077 cell.F = encode_range(val[0]);
15078 break;
15079 case 0x01AB: /* 'BrtShrFmla' */
15080 if(!opts.cellFormula) break;
15081 sharedf[encode_cell(val[0].s)] = val[1];
15082 cell = (opts.dense ? s[R][C] : s[encode_col(C) + rr]);
15083 cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
15084 break;
15085
15086 /* identical to 'ColInfo' in XLS */
15087 case 0x003C: /* 'BrtColInfo' */
15088 if(!opts.cellStyles) break;
15089 while(val.e >= val.s) {
15090 colinfo[val.e--] = { width: val.w/256, hidden: !!(val.flags & 0x01), level: val.level };
15091 if(!seencol) { seencol = true; find_mdw_colw(val.w/256); }
15092 process_col(colinfo[val.e+1]);
15093 }
15094 break;
15095
15096 case 0x00A1: /* 'BrtBeginAFilter' */
15097 s['!autofilter'] = { ref:encode_range(val) };
15098 break;
15099
15100 case 0x01DC: /* 'BrtMargins' */
15101 s['!margins'] = val;
15102 break;
15103
15104 case 0x0093: /* 'BrtWsProp' */
15105 if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
15106 if(val.name) wb.Sheets[idx].CodeName = val.name;
15107 if(val.above || val.left) s['!outline'] = { above: val.above, left: val.left };
15108 break;
15109
15110 case 0x0089: /* 'BrtBeginWsView' */
15111 if(!wb.Views) wb.Views = [{}];
15112 if(!wb.Views[0]) wb.Views[0] = {};
15113 if(val.RTL) wb.Views[0].RTL = true;
15114 break;
15115
15116 case 0x01E5: /* 'BrtWsFmtInfo' */
15117 break;
15118
15119 case 0x0040: /* 'BrtDVal' */
15120 case 0x041D: /* 'BrtDVal14' */
15121 break;
15122
15123 case 0x0097: /* 'BrtPane' */
15124 break;
15125 case 0x0098: /* 'BrtSel' */
15126 case 0x00AF: /* 'BrtAFilterDateGroupItem' */
15127 case 0x0284: /* 'BrtActiveX' */
15128 case 0x0271: /* 'BrtBigName' */
15129 case 0x0232: /* 'BrtBkHim' */
15130 case 0x018C: /* 'BrtBrk' */
15131 case 0x0458: /* 'BrtCFIcon' */
15132 case 0x047A: /* 'BrtCFRuleExt' */
15133 case 0x01D7: /* 'BrtCFVO' */
15134 case 0x041A: /* 'BrtCFVO14' */
15135 case 0x0289: /* 'BrtCellIgnoreEC' */
15136 case 0x0451: /* 'BrtCellIgnoreEC14' */
15137 case 0x0031: /* 'BrtCellMeta' */
15138 case 0x024D: /* 'BrtCellSmartTagProperty' */
15139 case 0x025F: /* 'BrtCellWatch' */
15140 case 0x0234: /* 'BrtColor' */
15141 case 0x041F: /* 'BrtColor14' */
15142 case 0x00A8: /* 'BrtColorFilter' */
15143 case 0x00AE: /* 'BrtCustomFilter' */
15144 case 0x049C: /* 'BrtCustomFilter14' */
15145 case 0x01F3: /* 'BrtDRef' */
15146 case 0x01FB: /* 'BrtDXF' */
15147 case 0x0226: /* 'BrtDrawing' */
15148 case 0x00AB: /* 'BrtDynamicFilter' */
15149 case 0x00A7: /* 'BrtFilter' */
15150 case 0x0499: /* 'BrtFilter14' */
15151 case 0x00A9: /* 'BrtIconFilter' */
15152 case 0x049D: /* 'BrtIconFilter14' */
15153 case 0x0227: /* 'BrtLegacyDrawing' */
15154 case 0x0228: /* 'BrtLegacyDrawingHF' */
15155 case 0x0295: /* 'BrtListPart' */
15156 case 0x027F: /* 'BrtOleObject' */
15157 case 0x01DE: /* 'BrtPageSetup' */
15158 case 0x0219: /* 'BrtPhoneticInfo' */
15159 case 0x01DD: /* 'BrtPrintOptions' */
15160 case 0x0218: /* 'BrtRangeProtection' */
15161 case 0x044F: /* 'BrtRangeProtection14' */
15162 case 0x02A8: /* 'BrtRangeProtectionIso' */
15163 case 0x0450: /* 'BrtRangeProtectionIso14' */
15164 case 0x0400: /* 'BrtRwDescent' */
15165 case 0x0297: /* 'BrtSheetCalcProp' */
15166 case 0x0217: /* 'BrtSheetProtection' */
15167 case 0x02A6: /* 'BrtSheetProtectionIso' */
15168 case 0x01F8: /* 'BrtSlc' */
15169 case 0x0413: /* 'BrtSparkline' */
15170 case 0x01AC: /* 'BrtTable' */
15171 case 0x00AA: /* 'BrtTop10Filter' */
15172 case 0x0C00: /* 'BrtUid' */
15173 case 0x0032: /* 'BrtValueMeta' */
15174 case 0x0816: /* 'BrtWebExtension' */
15175 case 0x0415: /* 'BrtWsFmtInfoEx14' */
15176 break;
15177
15178 case 0x0023: /* 'BrtFRTBegin' */
15179 pass = true; break;
15180 case 0x0024: /* 'BrtFRTEnd' */
15181 pass = false; break;
15182 case 0x0025: /* 'BrtACBegin' */
15183 state.push(R_n); pass = true; break;
15184 case 0x0026: /* 'BrtACEnd' */
15185 state.pop(); pass = false; break;
15186
15187 default:
15188 if((R_n||"").indexOf("Begin") > 0){/* empty */}
15189 else if((R_n||"").indexOf("End") > 0){/* empty */}
15190 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
15191 }
15192 }, opts);
15193
15194 delete opts.supbooks;
15195 delete opts['!row'];
15196
15197 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);
15198 if(opts.sheetRows && s["!ref"]) {
15199 var tmpref = safe_decode_range(s["!ref"]);
15200 if(opts.sheetRows <= +tmpref.e.r) {
15201 tmpref.e.r = opts.sheetRows - 1;
15202 if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
15203 if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
15204 if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c;
15205 if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c;
15206 s["!fullref"] = s["!ref"];
15207 s["!ref"] = encode_range(tmpref);
15208 }
15209 }
15210 if(merges.length > 0) s["!merges"] = merges;
15211 if(colinfo.length > 0) s["!cols"] = colinfo;
15212 if(rowinfo.length > 0) s["!rows"] = rowinfo;
15213 return s;
15214}
15215
15216/* TODO: something useful -- this is a stub */
15217function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/)/*:boolean*/ {
15218 if(cell.v === undefined) return false;
15219 var vv = "";
15220 switch(cell.t) {
15221 case 'b': vv = cell.v ? "1" : "0"; break;
15222 case 'd': // no BrtCellDate :(
15223 cell = dup(cell);
15224 cell.z = cell.z || SSF._table[14];
15225 cell.v = datenum(parseDate(cell.v)); cell.t = 'n';
15226 break;
15227 /* falls through */
15228 case 'n': case 'e': vv = ''+cell.v; break;
15229 default: vv = cell.v; break;
15230 }
15231 var o/*:any*/ = ({r:R, c:C}/*:any*/);
15232 /* TODO: cell style */
15233 o.s = get_cell_style(opts.cellXfs, cell, opts);
15234 if(cell.l) ws['!links'].push([encode_cell(o), cell.l]);
15235 if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
15236 switch(cell.t) {
15237 case 's': case 'str':
15238 if(opts.bookSST) {
15239 vv = get_sst_id(opts.Strings, (cell.v/*:any*/), opts.revStrings);
15240 o.t = "s"; o.v = vv;
15241 if(last_seen) write_record(ba, "BrtShortIsst", write_BrtShortIsst(cell, o));
15242 else write_record(ba, "BrtCellIsst", write_BrtCellIsst(cell, o));
15243 } else {
15244 o.t = "str";
15245 if(last_seen) write_record(ba, "BrtShortSt", write_BrtShortSt(cell, o));
15246 else write_record(ba, "BrtCellSt", write_BrtCellSt(cell, o));
15247 }
15248 return true;
15249 case 'n':
15250 /* TODO: determine threshold for Real vs RK */
15251 if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) {
15252 if(last_seen) write_record(ba, "BrtShortRk", write_BrtShortRk(cell, o));
15253 else write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o));
15254 } else {
15255 if(last_seen) write_record(ba, "BrtShortReal", write_BrtShortReal(cell, o));
15256 else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o));
15257 } return true;
15258 case 'b':
15259 o.t = "b";
15260 if(last_seen) write_record(ba, "BrtShortBool", write_BrtShortBool(cell, o));
15261 else write_record(ba, "BrtCellBool", write_BrtCellBool(cell, o));
15262 return true;
15263 case 'e':
15264 o.t = "e";
15265 if(last_seen) write_record(ba, "BrtShortError", write_BrtShortError(cell, o));
15266 else write_record(ba, "BrtCellError", write_BrtCellError(cell, o));
15267 return true;
15268 }
15269 if(last_seen) write_record(ba, "BrtShortBlank", write_BrtShortBlank(cell, o));
15270 else write_record(ba, "BrtCellBlank", write_BrtCellBlank(cell, o));
15271 return true;
15272}
15273
15274function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
15275 var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols/*:Array<string>*/ = [];
15276 write_record(ba, 'BrtBeginSheetData');
15277 var dense = Array.isArray(ws);
15278 var cap = range.e.r;
15279 if(ws['!rows']) cap = Math.max(range.e.r, ws['!rows'].length - 1);
15280 for(var R = range.s.r; R <= cap; ++R) {
15281 rr = encode_row(R);
15282 /* [ACCELLTABLE] */
15283 /* BrtRowHdr */
15284 write_row_header(ba, ws, range, R);
15285 var last_seen = false;
15286 if(R <= range.e.r) for(var C = range.s.c; C <= range.e.c; ++C) {
15287 /* *16384CELL */
15288 if(R === range.s.r) cols[C] = encode_col(C);
15289 ref = cols[C] + rr;
15290 var cell = dense ? (ws[R]||[])[C] : ws[ref];
15291 if(!cell) { last_seen = false; continue; }
15292 /* write cell */
15293 last_seen = write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen);
15294 }
15295 }
15296 write_record(ba, 'BrtEndSheetData');
15297}
15298
15299function write_MERGECELLS(ba, ws/*:Worksheet*/) {
15300 if(!ws || !ws['!merges']) return;
15301 write_record(ba, 'BrtBeginMergeCells', write_BrtBeginMergeCells(ws['!merges'].length));
15302 ws['!merges'].forEach(function(m) { write_record(ba, 'BrtMergeCell', write_BrtMergeCell(m)); });
15303 write_record(ba, 'BrtEndMergeCells');
15304}
15305
15306function write_COLINFOS(ba, ws/*:Worksheet*//*::, idx:number, opts, wb:Workbook*/) {
15307 if(!ws || !ws['!cols']) return;
15308 write_record(ba, 'BrtBeginColInfos');
15309 ws['!cols'].forEach(function(m, i) { if(m) write_record(ba, 'BrtColInfo', write_BrtColInfo(i, m)); });
15310 write_record(ba, 'BrtEndColInfos');
15311}
15312
15313function write_IGNOREECS(ba, ws/*:Worksheet*/) {
15314 if(!ws || !ws['!ref']) return;
15315 write_record(ba, 'BrtBeginCellIgnoreECs');
15316 write_record(ba, 'BrtCellIgnoreEC', write_BrtCellIgnoreEC(safe_decode_range(ws['!ref'])));
15317 write_record(ba, 'BrtEndCellIgnoreECs');
15318}
15319
15320function write_HLINKS(ba, ws/*:Worksheet*/, rels) {
15321 /* *BrtHLink */
15322 ws['!links'].forEach(function(l) {
15323 if(!l[1].Target) return;
15324 var rId = add_rels(rels, -1, l[1].Target.replace(/#.*$/, ""), RELS.HLINK);
15325 write_record(ba, "BrtHLink", write_BrtHLink(l, rId));
15326 });
15327 delete ws['!links'];
15328}
15329function write_LEGACYDRAWING(ba, ws/*:Worksheet*/, idx/*:number*/, rels) {
15330 /* [BrtLegacyDrawing] */
15331 if(ws['!comments'].length > 0) {
15332 var rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML);
15333 write_record(ba, "BrtLegacyDrawing", write_RelID("rId" + rId));
15334 ws['!legacy'] = rId;
15335 }
15336}
15337
15338function write_AUTOFILTER(ba, ws, wb, idx) {
15339 if(!ws['!autofilter']) return;
15340 var data = ws['!autofilter'];
15341 var ref = typeof data.ref === "string" ? data.ref : encode_range(data.ref);
15342
15343 /* Update FilterDatabase defined name for the worksheet */
15344 if(!wb.Workbook) wb.Workbook = ({Sheets:[]}/*:any*/);
15345 if(!wb.Workbook.Names) wb.Workbook.Names = [];
15346 var names/*: Array<any> */ = wb.Workbook.Names;
15347 var range = decode_range(ref);
15348 if(range.s.r == range.e.r) { range.e.r = decode_range(ws["!ref"]).e.r; ref = encode_range(range); }
15349 for(var i = 0; i < names.length; ++i) {
15350 var name = names[i];
15351 if(name.Name != '_xlnm._FilterDatabase') continue;
15352 if(name.Sheet != idx) continue;
15353 name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break;
15354 }
15355 if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref });
15356
15357 write_record(ba, "BrtBeginAFilter", write_UncheckedRfX(safe_decode_range(ref)));
15358 /* *FILTERCOLUMN */
15359 /* [SORTSTATE] */
15360 /* BrtEndAFilter */
15361 write_record(ba, "BrtEndAFilter");
15362}
15363
15364function write_WSVIEWS2(ba, ws, Workbook) {
15365 write_record(ba, "BrtBeginWsViews");
15366 { /* 1*WSVIEW2 */
15367 /* [ACUID] */
15368 write_record(ba, "BrtBeginWsView", write_BrtBeginWsView(ws, Workbook));
15369 /* [BrtPane] */
15370 /* *4BrtSel */
15371 /* *4SXSELECT */
15372 /* *FRT */
15373 write_record(ba, "BrtEndWsView");
15374 }
15375 /* *FRT */
15376 write_record(ba, "BrtEndWsViews");
15377}
15378
15379function write_WSFMTINFO(/*::ba, ws*/) {
15380 /* [ACWSFMTINFO] */
15381 //write_record(ba, "BrtWsFmtInfo", write_BrtWsFmtInfo(ws));
15382}
15383
15384function write_SHEETPROTECT(ba, ws) {
15385 if(!ws['!protect']) return;
15386 /* [BrtSheetProtectionIso] */
15387 write_record(ba, "BrtSheetProtection", write_BrtSheetProtection(ws['!protect']));
15388}
15389
15390function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
15391 var ba = buf_array();
15392 var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
15393 var c/*:string*/ = s; try { if(wb && wb.Workbook) c = wb.Workbook.Sheets[idx].CodeName || c; } catch(e) {}
15394 var r = safe_decode_range(ws['!ref'] || "A1");
15395 if(r.e.c > 0x3FFF || r.e.r > 0xFFFFF) {
15396 if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:XFD1048576");
15397 r.e.c = Math.min(r.e.c, 0x3FFF);
15398 r.e.r = Math.min(r.e.c, 0xFFFFF);
15399 }
15400 ws['!links'] = [];
15401 /* passed back to write_zip and removed there */
15402 ws['!comments'] = [];
15403 write_record(ba, "BrtBeginSheet");
15404 if(wb.vbaraw || ws['!outline']) write_record(ba, "BrtWsProp", write_BrtWsProp(c, ws['!outline']));
15405 write_record(ba, "BrtWsDim", write_BrtWsDim(r));
15406 write_WSVIEWS2(ba, ws, wb.Workbook);
15407 write_WSFMTINFO(ba, ws);
15408 write_COLINFOS(ba, ws, idx, opts, wb);
15409 write_CELLTABLE(ba, ws, idx, opts, wb);
15410 /* [BrtSheetCalcProp] */
15411 write_SHEETPROTECT(ba, ws);
15412 /* *([BrtRangeProtectionIso] BrtRangeProtection) */
15413 /* [SCENMAN] */
15414 write_AUTOFILTER(ba, ws, wb, idx);
15415 /* [SORTSTATE] */
15416 /* [DCON] */
15417 /* [USERSHVIEWS] */
15418 write_MERGECELLS(ba, ws);
15419 /* [BrtPhoneticInfo] */
15420 /* *CONDITIONALFORMATTING */
15421 /* [DVALS] */
15422 write_HLINKS(ba, ws, rels);
15423 /* [BrtPrintOptions] */
15424 if(ws['!margins']) write_record(ba, "BrtMargins", write_BrtMargins(ws['!margins']));
15425 /* [BrtPageSetup] */
15426 /* [HEADERFOOTER] */
15427 /* [RWBRK] */
15428 /* [COLBRK] */
15429 /* *BrtBigName */
15430 /* [CELLWATCHES] */
15431 if(!opts || opts.ignoreEC || (opts.ignoreEC == (void 0))) write_IGNOREECS(ba, ws);
15432 /* [SMARTTAGS] */
15433 /* [BrtDrawing] */
15434 write_LEGACYDRAWING(ba, ws, idx, rels);
15435 /* [BrtLegacyDrawingHF] */
15436 /* [BrtBkHim] */
15437 /* [OLEOBJECTS] */
15438 /* [ACTIVEXCONTROLS] */
15439 /* [WEBPUBITEMS] */
15440 /* [LISTPARTS] */
15441 /* FRTWORKSHEET */
15442 write_record(ba, "BrtEndSheet");
15443 return ba.end();
15444}
15445RELS.CHART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart";
15446RELS.CHARTEX = "http://schemas.microsoft.com/office/2014/relationships/chartEx";
15447
15448function parse_Cache(data/*:string*/)/*:[Array<number|string>, string, ?string]*/ {
15449 var col/*:Array<number|string>*/ = [];
15450 var num = data.match(/^<c:numCache>/);
15451 var f;
15452
15453 /* 21.2.2.150 pt CT_NumVal */
15454 (data.match(/<c:pt idx="(\d*)">(.*?)<\/c:pt>/mg)||[]).forEach(function(pt) {
15455 var q = pt.match(/<c:pt idx="(\d*?)"><c:v>(.*)<\/c:v><\/c:pt>/);
15456 if(!q) return;
15457 col[+q[1]] = num ? +q[2] : q[2];
15458 });
15459
15460 /* 21.2.2.71 formatCode CT_Xstring */
15461 var nf = unescapexml((data.match(/<c:formatCode>([\s\S]*?)<\/c:formatCode>/) || ["","General"])[1]);
15462
15463 (data.match(/<c:f>(.*?)<\/c:f>/mg)||[]).forEach(function(F) { f = F.replace(/<.*?>/g,""); });
15464
15465 return [col, nf, f];
15466}
15467
15468/* 21.2 DrawingML - Charts */
15469function parse_chart(data/*:?string*/, name/*:string*/, opts, rels, wb, csheet) {
15470 var cs/*:Worksheet*/ = ((csheet || {"!type":"chart"})/*:any*/);
15471 if(!data) return csheet;
15472 /* 21.2.2.27 chart CT_Chart */
15473
15474 var C = 0, R = 0, col = "A";
15475 var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
15476
15477 /* 21.2.2.120 numCache CT_NumData */
15478 (data.match(/<c:numCache>[\s\S]*?<\/c:numCache>/gm)||[]).forEach(function(nc) {
15479 var cache = parse_Cache(nc);
15480 refguess.s.r = refguess.s.c = 0;
15481 refguess.e.c = C;
15482 col = encode_col(C);
15483 cache[0].forEach(function(n,i) {
15484 cs[col + encode_row(i)] = {t:'n', v:n, z:cache[1] };
15485 R = i;
15486 });
15487 if(refguess.e.r < R) refguess.e.r = R;
15488 ++C;
15489 });
15490 if(C > 0) cs["!ref"] = encode_range(refguess);
15491 return cs;
15492}
15493RELS.CS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet";
15494
15495var CS_XML_ROOT = writextag('chartsheet', null, {
15496 'xmlns': XMLNS.main[0],
15497 'xmlns:r': XMLNS.r
15498});
15499
15500/* 18.3 Worksheets also covers Chartsheets */
15501function parse_cs_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*::, themes, styles*/)/*:Worksheet*/ {
15502 if(!data) return data;
15503 /* 18.3.1.12 chartsheet CT_ChartSheet */
15504 if(!rels) rels = {'!id':{}};
15505 var s = ({'!type':"chart", '!drawel':null, '!rel':""}/*:any*/);
15506 var m;
15507
15508 /* 18.3.1.83 sheetPr CT_ChartsheetPr */
15509 var sheetPr = data.match(sheetprregex);
15510 if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
15511
15512 /* 18.3.1.36 drawing CT_Drawing */
15513 if((m = data.match(/drawing r:id="(.*?)"/))) s['!rel'] = m[1];
15514
15515 if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
15516 return s;
15517}
15518function write_cs_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
15519 var o = [XML_HEADER, CS_XML_ROOT];
15520 o[o.length] = writextag("drawing", null, {"r:id": "rId1"});
15521 add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
15522 if(o.length>2) { o[o.length] = ('</chartsheet>'); o[1]=o[1].replace("/>",">"); }
15523 return o.join("");
15524}
15525
15526/* [MS-XLSB] 2.4.331 BrtCsProp */
15527function parse_BrtCsProp(data, length/*:number*/) {
15528 data.l += 10;
15529 var name = parse_XLWideString(data, length - 10);
15530 return { name: name };
15531}
15532
15533/* [MS-XLSB] 2.1.7.7 Chart Sheet */
15534function parse_cs_bin(data, opts, idx/*:number*/, rels, wb/*::, themes, styles*/)/*:Worksheet*/ {
15535 if(!data) return data;
15536 if(!rels) rels = {'!id':{}};
15537 var s = {'!type':"chart", '!drawel':null, '!rel':""};
15538 var state/*:Array<string>*/ = [];
15539 var pass = false;
15540 recordhopper(data, function cs_parse(val, R_n, RT) {
15541 switch(RT) {
15542
15543 case 0x0226: /* 'BrtDrawing' */
15544 s['!rel'] = val; break;
15545
15546 case 0x028B: /* 'BrtCsProp' */
15547 if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
15548 if(val.name) wb.Sheets[idx].CodeName = val.name;
15549 break;
15550
15551 case 0x0232: /* 'BrtBkHim' */
15552 case 0x028C: /* 'BrtCsPageSetup' */
15553 case 0x029D: /* 'BrtCsProtection' */
15554 case 0x02A7: /* 'BrtCsProtectionIso' */
15555 case 0x0227: /* 'BrtLegacyDrawing' */
15556 case 0x0228: /* 'BrtLegacyDrawingHF' */
15557 case 0x01DC: /* 'BrtMargins' */
15558 case 0x0C00: /* 'BrtUid' */
15559 break;
15560
15561 case 0x0023: /* 'BrtFRTBegin' */
15562 pass = true; break;
15563 case 0x0024: /* 'BrtFRTEnd' */
15564 pass = false; break;
15565 case 0x0025: /* 'BrtACBegin' */
15566 state.push(R_n); break;
15567 case 0x0026: /* 'BrtACEnd' */
15568 state.pop(); break;
15569
15570 default:
15571 if((R_n||"").indexOf("Begin") > 0) state.push(R_n);
15572 else if((R_n||"").indexOf("End") > 0) state.pop();
15573 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
15574 }
15575 }, opts);
15576
15577 if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
15578 return s;
15579}
15580function write_cs_bin(/*::idx:number, opts, wb:Workbook, rels*/) {
15581 var ba = buf_array();
15582 write_record(ba, "BrtBeginSheet");
15583 /* [BrtCsProp] */
15584 /* CSVIEWS */
15585 /* [[BrtCsProtectionIso] BrtCsProtection] */
15586 /* [USERCSVIEWS] */
15587 /* [BrtMargins] */
15588 /* [BrtCsPageSetup] */
15589 /* [HEADERFOOTER] */
15590 /* BrtDrawing */
15591 /* [BrtLegacyDrawing] */
15592 /* [BrtLegacyDrawingHF] */
15593 /* [BrtBkHim] */
15594 /* [WEBPUBITEMS] */
15595 /* FRTCHARTSHEET */
15596 write_record(ba, "BrtEndSheet");
15597 return ba.end();
15598}
15599/* 18.2.28 (CT_WorkbookProtection) Defaults */
15600var WBPropsDef = [
15601 ['allowRefreshQuery', false, "bool"],
15602 ['autoCompressPictures', true, "bool"],
15603 ['backupFile', false, "bool"],
15604 ['checkCompatibility', false, "bool"],
15605 ['CodeName', ''],
15606 ['date1904', false, "bool"],
15607 ['defaultThemeVersion', 0, "int"],
15608 ['filterPrivacy', false, "bool"],
15609 ['hidePivotFieldList', false, "bool"],
15610 ['promptedSolutions', false, "bool"],
15611 ['publishItems', false, "bool"],
15612 ['refreshAllConnections', false, "bool"],
15613 ['saveExternalLinkValues', true, "bool"],
15614 ['showBorderUnselectedTables', true, "bool"],
15615 ['showInkAnnotation', true, "bool"],
15616 ['showObjects', 'all'],
15617 ['showPivotChartFilter', false, "bool"],
15618 ['updateLinks', 'userSet']
15619];
15620
15621/* 18.2.30 (CT_BookView) Defaults */
15622var WBViewDef = [
15623 ['activeTab', 0, "int"],
15624 ['autoFilterDateGrouping', true, "bool"],
15625 ['firstSheet', 0, "int"],
15626 ['minimized', false, "bool"],
15627 ['showHorizontalScroll', true, "bool"],
15628 ['showSheetTabs', true, "bool"],
15629 ['showVerticalScroll', true, "bool"],
15630 ['tabRatio', 600, "int"],
15631 ['visibility', 'visible']
15632 //window{Height,Width}, {x,y}Window
15633];
15634
15635/* 18.2.19 (CT_Sheet) Defaults */
15636var SheetDef = [
15637 //['state', 'visible']
15638];
15639
15640/* 18.2.2 (CT_CalcPr) Defaults */
15641var CalcPrDef = [
15642 ['calcCompleted', 'true'],
15643 ['calcMode', 'auto'],
15644 ['calcOnSave', 'true'],
15645 ['concurrentCalc', 'true'],
15646 ['fullCalcOnLoad', 'false'],
15647 ['fullPrecision', 'true'],
15648 ['iterate', 'false'],
15649 ['iterateCount', '100'],
15650 ['iterateDelta', '0.001'],
15651 ['refMode', 'A1']
15652];
15653
15654/* 18.2.3 (CT_CustomWorkbookView) Defaults */
15655/*var CustomWBViewDef = [
15656 ['autoUpdate', 'false'],
15657 ['changesSavedWin', 'false'],
15658 ['includeHiddenRowCol', 'true'],
15659 ['includePrintSettings', 'true'],
15660 ['maximized', 'false'],
15661 ['minimized', 'false'],
15662 ['onlySync', 'false'],
15663 ['personalView', 'false'],
15664 ['showComments', 'commIndicator'],
15665 ['showFormulaBar', 'true'],
15666 ['showHorizontalScroll', 'true'],
15667 ['showObjects', 'all'],
15668 ['showSheetTabs', 'true'],
15669 ['showStatusbar', 'true'],
15670 ['showVerticalScroll', 'true'],
15671 ['tabRatio', '600'],
15672 ['xWindow', '0'],
15673 ['yWindow', '0']
15674];*/
15675
15676function push_defaults_array(target, defaults) {
15677 for(var j = 0; j != target.length; ++j) { var w = target[j];
15678 for(var i=0; i != defaults.length; ++i) { var z = defaults[i];
15679 if(w[z[0]] == null) w[z[0]] = z[1];
15680 else switch(z[2]) {
15681 case "bool": if(typeof w[z[0]] == "string") w[z[0]] = parsexmlbool(w[z[0]]); break;
15682 case "int": if(typeof w[z[0]] == "string") w[z[0]] = parseInt(w[z[0]], 10); break;
15683 }
15684 }
15685 }
15686}
15687function push_defaults(target, defaults) {
15688 for(var i = 0; i != defaults.length; ++i) { var z = defaults[i];
15689 if(target[z[0]] == null) target[z[0]] = z[1];
15690 else switch(z[2]) {
15691 case "bool": if(typeof target[z[0]] == "string") target[z[0]] = parsexmlbool(target[z[0]]); break;
15692 case "int": if(typeof target[z[0]] == "string") target[z[0]] = parseInt(target[z[0]], 10); break;
15693 }
15694 }
15695}
15696
15697function parse_wb_defaults(wb) {
15698 push_defaults(wb.WBProps, WBPropsDef);
15699 push_defaults(wb.CalcPr, CalcPrDef);
15700
15701 push_defaults_array(wb.WBView, WBViewDef);
15702 push_defaults_array(wb.Sheets, SheetDef);
15703
15704 _ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904);
15705}
15706
15707function safe1904(wb/*:Workbook*/)/*:string*/ {
15708 /* TODO: store date1904 somewhere else */
15709 if(!wb.Workbook) return "false";
15710 if(!wb.Workbook.WBProps) return "false";
15711 return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false";
15712}
15713
15714var badchars = "][*?\/\\".split("");
15715function check_ws_name(n/*:string*/, safe/*:?boolean*/)/*:boolean*/ {
15716 if(n.length > 31) { if(safe) return false; throw new Error("Sheet names cannot exceed 31 chars"); }
15717 var _good = true;
15718 badchars.forEach(function(c) {
15719 if(n.indexOf(c) == -1) return;
15720 if(!safe) throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
15721 _good = false;
15722 });
15723 return _good;
15724}
15725function check_wb_names(N, S, codes) {
15726 N.forEach(function(n,i) {
15727 check_ws_name(n);
15728 for(var j = 0; j < i; ++j) if(n == N[j]) throw new Error("Duplicate Sheet Name: " + n);
15729 if(codes) {
15730 var cn = (S && S[i] && S[i].CodeName) || n;
15731 if(cn.charCodeAt(0) == 95 && cn.length > 22) throw new Error("Bad Code Name: Worksheet" + cn);
15732 }
15733 });
15734}
15735function check_wb(wb) {
15736 if(!wb || !wb.SheetNames || !wb.Sheets) throw new Error("Invalid Workbook");
15737 if(!wb.SheetNames.length) throw new Error("Workbook is empty");
15738 var Sheets = (wb.Workbook && wb.Workbook.Sheets) || [];
15739 check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
15740 for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i);
15741 /* TODO: validate workbook */
15742}
15743/* 18.2 Workbook */
15744var wbnsregex = /<\w+:workbook/;
15745function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
15746 if(!data) throw new Error("Could not find file");
15747 var wb = /*::(*/{ AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, Names:[], xmlns: "" }/*::)*/;
15748 var pass = false, xmlns = "xmlns";
15749 var dname = {}, dnstart = 0;
15750 data.replace(tagregex, function xml_wb(x, idx) {
15751 var y/*:any*/ = parsexmltag(x);
15752 switch(strip_ns(y[0])) {
15753 case '<?xml': break;
15754
15755 /* 18.2.27 workbook CT_Workbook 1 */
15756 case '<workbook':
15757 if(x.match(wbnsregex)) xmlns = "xmlns" + x.match(/<(\w+):/)[1];
15758 wb.xmlns = y[xmlns];
15759 break;
15760 case '</workbook>': break;
15761
15762 /* 18.2.13 fileVersion CT_FileVersion ? */
15763 case '<fileVersion': delete y[0]; wb.AppVersion = y; break;
15764 case '<fileVersion/>': case '</fileVersion>': break;
15765
15766 /* 18.2.12 fileSharing CT_FileSharing ? */
15767 case '<fileSharing':
15768 break;
15769 case '<fileSharing/>': break;
15770
15771 /* 18.2.28 workbookPr CT_WorkbookPr ? */
15772 case '<workbookPr':
15773 case '<workbookPr/>':
15774 WBPropsDef.forEach(function(w) {
15775 if(y[w[0]] == null) return;
15776 switch(w[2]) {
15777 case "bool": wb.WBProps[w[0]] = parsexmlbool(y[w[0]]); break;
15778 case "int": wb.WBProps[w[0]] = parseInt(y[w[0]], 10); break;
15779 default: wb.WBProps[w[0]] = y[w[0]];
15780 }
15781 });
15782 if(y.codeName) wb.WBProps.CodeName = utf8read(y.codeName);
15783 break;
15784 case '</workbookPr>': break;
15785
15786 /* 18.2.29 workbookProtection CT_WorkbookProtection ? */
15787 case '<workbookProtection':
15788 break;
15789 case '<workbookProtection/>': break;
15790
15791 /* 18.2.1 bookViews CT_BookViews ? */
15792 case '<bookViews': case '<bookViews>': case '</bookViews>': break;
15793 /* 18.2.30 workbookView CT_BookView + */
15794 case '<workbookView': case '<workbookView/>': delete y[0]; wb.WBView.push(y); break;
15795 case '</workbookView>': break;
15796
15797 /* 18.2.20 sheets CT_Sheets 1 */
15798 case '<sheets': case '<sheets>': case '</sheets>': break; // aggregate sheet
15799 /* 18.2.19 sheet CT_Sheet + */
15800 case '<sheet':
15801 switch(y.state) {
15802 case "hidden": y.Hidden = 1; break;
15803 case "veryHidden": y.Hidden = 2; break;
15804 default: y.Hidden = 0;
15805 }
15806 delete y.state;
15807 y.name = unescapexml(utf8read(y.name));
15808 delete y[0]; wb.Sheets.push(y); break;
15809 case '</sheet>': break;
15810
15811 /* 18.2.15 functionGroups CT_FunctionGroups ? */
15812 case '<functionGroups': case '<functionGroups/>': break;
15813 /* 18.2.14 functionGroup CT_FunctionGroup + */
15814 case '<functionGroup': break;
15815
15816 /* 18.2.9 externalReferences CT_ExternalReferences ? */
15817 case '<externalReferences': case '</externalReferences>': case '<externalReferences>': break;
15818 /* 18.2.8 externalReference CT_ExternalReference + */
15819 case '<externalReference': break;
15820
15821 /* 18.2.6 definedNames CT_DefinedNames ? */
15822 case '<definedNames/>': break;
15823 case '<definedNames>': case '<definedNames': pass=true; break;
15824 case '</definedNames>': pass=false; break;
15825 /* 18.2.5 definedName CT_DefinedName + */
15826 case '<definedName': {
15827 dname = {};
15828 dname.Name = utf8read(y.name);
15829 if(y.comment) dname.Comment = y.comment;
15830 if(y.localSheetId) dname.Sheet = +y.localSheetId;
15831 if(parsexmlbool(y.hidden||"0")) dname.Hidden = true;
15832 dnstart = idx + x.length;
15833 } break;
15834 case '</definedName>': {
15835 dname.Ref = unescapexml(utf8read(data.slice(dnstart, idx)));
15836 wb.Names.push(dname);
15837 } break;
15838 case '<definedName/>': break;
15839
15840 /* 18.2.2 calcPr CT_CalcPr ? */
15841 case '<calcPr': delete y[0]; wb.CalcPr = y; break;
15842 case '<calcPr/>': delete y[0]; wb.CalcPr = y; break;
15843 case '</calcPr>': break;
15844
15845 /* 18.2.16 oleSize CT_OleSize ? (ref required) */
15846 case '<oleSize': break;
15847
15848 /* 18.2.4 customWorkbookViews CT_CustomWorkbookViews ? */
15849 case '<customWorkbookViews>': case '</customWorkbookViews>': case '<customWorkbookViews': break;
15850 /* 18.2.3 customWorkbookView CT_CustomWorkbookView + */
15851 case '<customWorkbookView': case '</customWorkbookView>': break;
15852
15853 /* 18.2.18 pivotCaches CT_PivotCaches ? */
15854 case '<pivotCaches>': case '</pivotCaches>': case '<pivotCaches': break;
15855 /* 18.2.17 pivotCache CT_PivotCache ? */
15856 case '<pivotCache': break;
15857
15858 /* 18.2.21 smartTagPr CT_SmartTagPr ? */
15859 case '<smartTagPr': case '<smartTagPr/>': break;
15860
15861 /* 18.2.23 smartTagTypes CT_SmartTagTypes ? */
15862 case '<smartTagTypes': case '<smartTagTypes>': case '</smartTagTypes>': break;
15863 /* 18.2.22 smartTagType CT_SmartTagType ? */
15864 case '<smartTagType': break;
15865
15866 /* 18.2.24 webPublishing CT_WebPublishing ? */
15867 case '<webPublishing': case '<webPublishing/>': break;
15868
15869 /* 18.2.11 fileRecoveryPr CT_FileRecoveryPr ? */
15870 case '<fileRecoveryPr': case '<fileRecoveryPr/>': break;
15871
15872 /* 18.2.26 webPublishObjects CT_WebPublishObjects ? */
15873 case '<webPublishObjects>': case '<webPublishObjects': case '</webPublishObjects>': break;
15874 /* 18.2.25 webPublishObject CT_WebPublishObject ? */
15875 case '<webPublishObject': break;
15876
15877 /* 18.2.10 extLst CT_ExtensionList ? */
15878 case '<extLst': case '<extLst>': case '</extLst>': case '<extLst/>': break;
15879 /* 18.2.7 ext CT_Extension + */
15880 case '<ext': pass=true; break; //TODO: check with versions of excel
15881 case '</ext>': pass=false; break;
15882
15883 /* Others */
15884 case '<ArchID': break;
15885 case '<AlternateContent':
15886 case '<AlternateContent>': pass=true; break;
15887 case '</AlternateContent>': pass=false; break;
15888
15889 /* TODO */
15890 case '<revisionPtr': break;
15891
15892 default: if(!pass && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in workbook');
15893 }
15894 return x;
15895 });
15896 if(XMLNS.main.indexOf(wb.xmlns) === -1) throw new Error("Unknown Namespace: " + wb.xmlns);
15897
15898 parse_wb_defaults(wb);
15899
15900 return wb;
15901}
15902
15903var WB_XML_ROOT = writextag('workbook', null, {
15904 'xmlns': XMLNS.main[0],
15905 //'xmlns:mx': XMLNS.mx,
15906 //'xmlns:s': XMLNS.main[0],
15907 'xmlns:r': XMLNS.r
15908});
15909
15910function write_wb_xml(wb/*:Workbook*//*::, opts:?WriteOpts*/)/*:string*/ {
15911 var o = [XML_HEADER];
15912 o[o.length] = WB_XML_ROOT;
15913
15914 var write_names = (wb.Workbook && (wb.Workbook.Names||[]).length > 0);
15915
15916 /* fileVersion */
15917 /* fileSharing */
15918
15919 var workbookPr/*:any*/ = ({codeName:"ThisWorkbook"}/*:any*/);
15920 if(wb.Workbook && wb.Workbook.WBProps) {
15921 WBPropsDef.forEach(function(x) {
15922 /*:: if(!wb.Workbook || !wb.Workbook.WBProps) throw "unreachable"; */
15923 if((wb.Workbook.WBProps[x[0]]/*:any*/) == null) return;
15924 if((wb.Workbook.WBProps[x[0]]/*:any*/) == x[1]) return;
15925 workbookPr[x[0]] = (wb.Workbook.WBProps[x[0]]/*:any*/);
15926 });
15927 /*:: if(!wb.Workbook || !wb.Workbook.WBProps) throw "unreachable"; */
15928 if(wb.Workbook.WBProps.CodeName) { workbookPr.codeName = wb.Workbook.WBProps.CodeName; delete workbookPr.CodeName; }
15929 }
15930 o[o.length] = (writextag('workbookPr', null, workbookPr));
15931
15932 /* workbookProtection */
15933
15934 var sheets = wb.Workbook && wb.Workbook.Sheets || [];
15935 var i = 0;
15936
15937 /* bookViews only written if first worksheet is hidden */
15938 if(sheets && sheets[0] && !!sheets[0].Hidden) {
15939 o[o.length] = "<bookViews>";
15940 for(i = 0; i != wb.SheetNames.length; ++i) {
15941 if(!sheets[i]) break;
15942 if(!sheets[i].Hidden) break;
15943 }
15944 if(i == wb.SheetNames.length) i = 0;
15945 o[o.length] = '<workbookView firstSheet="' + i + '" activeTab="' + i + '"/>';
15946 o[o.length] = "</bookViews>";
15947 }
15948
15949 o[o.length] = "<sheets>";
15950 for(i = 0; i != wb.SheetNames.length; ++i) {
15951 var sht = ({name:escapexml(wb.SheetNames[i].slice(0,31))}/*:any*/);
15952 sht.sheetId = ""+(i+1);
15953 sht["r:id"] = "rId"+(i+1);
15954 if(sheets[i]) switch(sheets[i].Hidden) {
15955 case 1: sht.state = "hidden"; break;
15956 case 2: sht.state = "veryHidden"; break;
15957 }
15958 o[o.length] = (writextag('sheet',null,sht));
15959 }
15960 o[o.length] = "</sheets>";
15961
15962 /* functionGroups */
15963 /* externalReferences */
15964
15965 if(write_names) {
15966 o[o.length] = "<definedNames>";
15967 if(wb.Workbook && wb.Workbook.Names) wb.Workbook.Names.forEach(function(n) {
15968 var d/*:any*/ = {name:n.Name};
15969 if(n.Comment) d.comment = n.Comment;
15970 if(n.Sheet != null) d.localSheetId = ""+n.Sheet;
15971 if(n.Hidden) d.hidden = "1";
15972 if(!n.Ref) return;
15973 o[o.length] = writextag('definedName', escapexml(n.Ref), d);
15974 });
15975 o[o.length] = "</definedNames>";
15976 }
15977
15978 /* calcPr */
15979 /* oleSize */
15980 /* customWorkbookViews */
15981 /* pivotCaches */
15982 /* smartTagPr */
15983 /* smartTagTypes */
15984 /* webPublishing */
15985 /* fileRecoveryPr */
15986 /* webPublishObjects */
15987 /* extLst */
15988
15989 if(o.length>2){ o[o.length] = '</workbook>'; o[1]=o[1].replace("/>",">"); }
15990 return o.join("");
15991}
15992/* [MS-XLSB] 2.4.304 BrtBundleSh */
15993function parse_BrtBundleSh(data, length/*:number*/) {
15994 var z = {};
15995 z.Hidden = data.read_shift(4); //hsState ST_SheetState
15996 z.iTabID = data.read_shift(4);
15997 z.strRelID = parse_RelID(data,length-8);
15998 z.name = parse_XLWideString(data);
15999 return z;
16000}
16001function write_BrtBundleSh(data, o) {
16002 if(!o) o = new_buf(127);
16003 o.write_shift(4, data.Hidden);
16004 o.write_shift(4, data.iTabID);
16005 write_RelID(data.strRelID, o);
16006 write_XLWideString(data.name.slice(0,31), o);
16007 return o.length > o.l ? o.slice(0, o.l) : o;
16008}
16009
16010/* [MS-XLSB] 2.4.815 BrtWbProp */
16011function parse_BrtWbProp(data, length)/*:WBProps*/ {
16012 var o/*:WBProps*/ = ({}/*:any*/);
16013 var flags = data.read_shift(4);
16014 o.defaultThemeVersion = data.read_shift(4);
16015 var strName = (length > 8) ? parse_XLWideString(data) : "";
16016 if(strName.length > 0) o.CodeName = strName;
16017 o.autoCompressPictures = !!(flags & 0x10000);
16018 o.backupFile = !!(flags & 0x40);
16019 o.checkCompatibility = !!(flags & 0x1000);
16020 o.date1904 = !!(flags & 0x01);
16021 o.filterPrivacy = !!(flags & 0x08);
16022 o.hidePivotFieldList = !!(flags & 0x400);
16023 o.promptedSolutions = !!(flags & 0x10);
16024 o.publishItems = !!(flags & 0x800);
16025 o.refreshAllConnections = !!(flags & 0x40000);
16026 o.saveExternalLinkValues = !!(flags & 0x80);
16027 o.showBorderUnselectedTables = !!(flags & 0x04);
16028 o.showInkAnnotation = !!(flags & 0x20);
16029 o.showObjects = ["all", "placeholders", "none"][(flags >> 13) & 0x03];
16030 o.showPivotChartFilter = !!(flags & 0x8000);
16031 o.updateLinks = ["userSet", "never", "always"][(flags >> 8) & 0x03];
16032 return o;
16033}
16034function write_BrtWbProp(data/*:?WBProps*/, o) {
16035 if(!o) o = new_buf(72);
16036 var flags = 0;
16037 if(data) {
16038 /* TODO: mirror parse_BrtWbProp fields */
16039 if(data.filterPrivacy) flags |= 0x08;
16040 }
16041 o.write_shift(4, flags);
16042 o.write_shift(4, 0);
16043 write_XLSBCodeName(data && data.CodeName || "ThisWorkbook", o);
16044 return o.slice(0, o.l);
16045}
16046
16047function parse_BrtFRTArchID$(data, length) {
16048 var o = {};
16049 data.read_shift(4);
16050 o.ArchID = data.read_shift(4);
16051 data.l += length - 8;
16052 return o;
16053}
16054
16055/* [MS-XLSB] 2.4.687 BrtName */
16056function parse_BrtName(data, length, opts) {
16057 var end = data.l + length;
16058 data.l += 4; //var flags = data.read_shift(4);
16059 data.l += 1; //var chKey = data.read_shift(1);
16060 var itab = data.read_shift(4);
16061 var name = parse_XLNameWideString(data);
16062 var formula = parse_XLSBNameParsedFormula(data, 0, opts);
16063 var comment = parse_XLNullableWideString(data);
16064 //if(0 /* fProc */) {
16065 // unusedstring1: XLNullableWideString
16066 // description: XLNullableWideString
16067 // helpTopic: XLNullableWideString
16068 // unusedstring2: XLNullableWideString
16069 //}
16070 data.l = end;
16071 var out = ({Name:name, Ptg:formula}/*:any*/);
16072 if(itab < 0xFFFFFFF) out.Sheet = itab;
16073 if(comment) out.Comment = comment;
16074 return out;
16075}
16076
16077/* [MS-XLSB] 2.1.7.61 Workbook */
16078function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
16079 var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
16080 var state/*:Array<string>*/ = [];
16081 var pass = false;
16082
16083 if(!opts) opts = {};
16084 opts.biff = 12;
16085
16086 var Names = [];
16087 var supbooks = ([[]]/*:any*/);
16088 supbooks.SheetNames = [];
16089 supbooks.XTI = [];
16090
16091 XLSBRecordEnum[0x0010] = { n:"BrtFRTArchID$", f:parse_BrtFRTArchID$ };
16092
16093 recordhopper(data, function hopper_wb(val, R_n, RT) {
16094 switch(RT) {
16095 case 0x009C: /* 'BrtBundleSh' */
16096 supbooks.SheetNames.push(val.name);
16097 wb.Sheets.push(val); break;
16098
16099 case 0x0099: /* 'BrtWbProp' */
16100 wb.WBProps = val; break;
16101
16102 case 0x0027: /* 'BrtName' */
16103 if(val.Sheet != null) opts.SID = val.Sheet;
16104 val.Ref = stringify_formula(val.Ptg, null, null, supbooks, opts);
16105 delete opts.SID;
16106 delete val.Ptg;
16107 Names.push(val);
16108 break;
16109 case 0x040C: /* 'BrtNameExt' */ break;
16110
16111 case 0x0165: /* 'BrtSupSelf' */
16112 case 0x0166: /* 'BrtSupSame' */
16113 case 0x0163: /* 'BrtSupBookSrc' */
16114 case 0x029B: /* 'BrtSupAddin' */
16115 if(!supbooks[0].length) supbooks[0] = [RT, val];
16116 else supbooks.push([RT, val]);
16117 supbooks[supbooks.length - 1].XTI = [];
16118 break;
16119 case 0x016A: /* 'BrtExternSheet' */
16120 if(supbooks.length === 0) { supbooks[0] = []; supbooks[0].XTI = []; }
16121 supbooks[supbooks.length - 1].XTI = supbooks[supbooks.length - 1].XTI.concat(val);
16122 supbooks.XTI = supbooks.XTI.concat(val);
16123 break;
16124 case 0x0169: /* 'BrtPlaceholderName' */
16125 break;
16126
16127 case 0x0817: /* 'BrtAbsPath15' */
16128 case 0x009E: /* 'BrtBookView' */
16129 case 0x008F: /* 'BrtBeginBundleShs' */
16130 case 0x0298: /* 'BrtBeginFnGroup' */
16131 case 0x0161: /* 'BrtBeginExternals' */
16132 break;
16133
16134 /* case 'BrtModelTimeGroupingCalcCol' */
16135 case 0x0C00: /* 'BrtUid' */
16136 case 0x0C01: /* 'BrtRevisionPtr' */
16137 case 0x0216: /* 'BrtBookProtection' */
16138 case 0x02A5: /* 'BrtBookProtectionIso' */
16139 case 0x009D: /* 'BrtCalcProp' */
16140 case 0x0262: /* 'BrtCrashRecErr' */
16141 case 0x0802: /* 'BrtDecoupledPivotCacheID' */
16142 case 0x009B: /* 'BrtFileRecover' */
16143 case 0x0224: /* 'BrtFileSharing' */
16144 case 0x02A4: /* 'BrtFileSharingIso' */
16145 case 0x0080: /* 'BrtFileVersion' */
16146 case 0x0299: /* 'BrtFnGroup' */
16147 case 0x0850: /* 'BrtModelRelationship' */
16148 case 0x084D: /* 'BrtModelTable' */
16149 case 0x0225: /* 'BrtOleSize' */
16150 case 0x0805: /* 'BrtPivotTableRef' */
16151 case 0x0254: /* 'BrtSmartTagType' */
16152 case 0x081C: /* 'BrtTableSlicerCacheID' */
16153 case 0x081B: /* 'BrtTableSlicerCacheIDs' */
16154 case 0x0822: /* 'BrtTimelineCachePivotCacheID' */
16155 case 0x018D: /* 'BrtUserBookView' */
16156 case 0x009A: /* 'BrtWbFactoid' */
16157 case 0x045D: /* 'BrtWbProp14' */
16158 case 0x0229: /* 'BrtWebOpt' */
16159 case 0x082B: /* 'BrtWorkBookPr15' */
16160 break;
16161
16162 case 0x0023: /* 'BrtFRTBegin' */
16163 state.push(R_n); pass = true; break;
16164 case 0x0024: /* 'BrtFRTEnd' */
16165 state.pop(); pass = false; break;
16166 case 0x0025: /* 'BrtACBegin' */
16167 state.push(R_n); pass = true; break;
16168 case 0x0026: /* 'BrtACEnd' */
16169 state.pop(); pass = false; break;
16170
16171 case 0x0010: /* 'BrtFRTArchID$' */ break;
16172
16173 default:
16174 if((R_n||"").indexOf("Begin") > 0){/* empty */}
16175 else if((R_n||"").indexOf("End") > 0){/* empty */}
16176 else if(!pass || (opts.WTF && state[state.length-1] != "BrtACBegin" && state[state.length-1] != "BrtFRTBegin")) throw new Error("Unexpected record " + RT + " " + R_n);
16177 }
16178 }, opts);
16179
16180 parse_wb_defaults(wb);
16181
16182 // $FlowIgnore
16183 wb.Names = Names;
16184
16185 (wb/*:any*/).supbooks = supbooks;
16186 return wb;
16187}
16188
16189function write_BUNDLESHS(ba, wb/*::, opts*/) {
16190 write_record(ba, "BrtBeginBundleShs");
16191 for(var idx = 0; idx != wb.SheetNames.length; ++idx) {
16192 var viz = wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx] && wb.Workbook.Sheets[idx].Hidden || 0;
16193 var d = { Hidden: viz, iTabID: idx+1, strRelID: 'rId' + (idx+1), name: wb.SheetNames[idx] };
16194 write_record(ba, "BrtBundleSh", write_BrtBundleSh(d));
16195 }
16196 write_record(ba, "BrtEndBundleShs");
16197}
16198
16199/* [MS-XLSB] 2.4.649 BrtFileVersion */
16200function write_BrtFileVersion(data, o) {
16201 if(!o) o = new_buf(127);
16202 for(var i = 0; i != 4; ++i) o.write_shift(4, 0);
16203 write_XLWideString("SheetJS", o);
16204 write_XLWideString(XLSX.version, o);
16205 write_XLWideString(XLSX.version, o);
16206 write_XLWideString("7262", o);
16207 return o.length > o.l ? o.slice(0, o.l) : o;
16208}
16209
16210/* [MS-XLSB] 2.4.301 BrtBookView */
16211function write_BrtBookView(idx, o) {
16212 if(!o) o = new_buf(29);
16213 o.write_shift(-4, 0);
16214 o.write_shift(-4, 460);
16215 o.write_shift(4, 28800);
16216 o.write_shift(4, 17600);
16217 o.write_shift(4, 500);
16218 o.write_shift(4, idx);
16219 o.write_shift(4, idx);
16220 var flags = 0x78;
16221 o.write_shift(1, flags);
16222 return o.length > o.l ? o.slice(0, o.l) : o;
16223}
16224
16225function write_BOOKVIEWS(ba, wb/*::, opts*/) {
16226 /* required if hidden tab appears before visible tab */
16227 if(!wb.Workbook || !wb.Workbook.Sheets) return;
16228 var sheets = wb.Workbook.Sheets;
16229 var i = 0, vistab = -1, hidden = -1;
16230 for(; i < sheets.length; ++i) {
16231 if(!sheets[i] || !sheets[i].Hidden && vistab == -1) vistab = i;
16232 else if(sheets[i].Hidden == 1 && hidden == -1) hidden = i;
16233 }
16234 if(hidden > vistab) return;
16235 write_record(ba, "BrtBeginBookViews");
16236 write_record(ba, "BrtBookView", write_BrtBookView(vistab));
16237 /* 1*(BrtBookView *FRT) */
16238 write_record(ba, "BrtEndBookViews");
16239}
16240
16241/* [MS-XLSB] 2.4.305 BrtCalcProp */
16242/*function write_BrtCalcProp(data, o) {
16243 if(!o) o = new_buf(26);
16244 o.write_shift(4,0); // force recalc
16245 o.write_shift(4,1);
16246 o.write_shift(4,0);
16247 write_Xnum(0, o);
16248 o.write_shift(-4, 1023);
16249 o.write_shift(1, 0x33);
16250 o.write_shift(1, 0x00);
16251 return o;
16252}*/
16253
16254/* [MS-XLSB] 2.4.646 BrtFileRecover */
16255/*function write_BrtFileRecover(data, o) {
16256 if(!o) o = new_buf(1);
16257 o.write_shift(1,0);
16258 return o;
16259}*/
16260
16261/* [MS-XLSB] 2.1.7.61 Workbook */
16262function write_wb_bin(wb, opts) {
16263 var ba = buf_array();
16264 write_record(ba, "BrtBeginBook");
16265 write_record(ba, "BrtFileVersion", write_BrtFileVersion());
16266 /* [[BrtFileSharingIso] BrtFileSharing] */
16267 write_record(ba, "BrtWbProp", write_BrtWbProp(wb.Workbook && wb.Workbook.WBProps || null));
16268 /* [ACABSPATH] */
16269 /* [[BrtBookProtectionIso] BrtBookProtection] */
16270 write_BOOKVIEWS(ba, wb, opts);
16271 write_BUNDLESHS(ba, wb, opts);
16272 /* [FNGROUP] */
16273 /* [EXTERNALS] */
16274 /* *BrtName */
16275 /* write_record(ba, "BrtCalcProp", write_BrtCalcProp()); */
16276 /* [BrtOleSize] */
16277 /* *(BrtUserBookView *FRT) */
16278 /* [PIVOTCACHEIDS] */
16279 /* [BrtWbFactoid] */
16280 /* [SMARTTAGTYPES] */
16281 /* [BrtWebOpt] */
16282 /* write_record(ba, "BrtFileRecover", write_BrtFileRecover()); */
16283 /* [WEBPUBITEMS] */
16284 /* [CRERRS] */
16285 /* FRTWORKBOOK */
16286 write_record(ba, "BrtEndBook");
16287
16288 return ba.end();
16289}
16290function parse_wb(data, name/*:string*/, opts)/*:WorkbookFile*/ {
16291 if(name.slice(-4)===".bin") return parse_wb_bin((data/*:any*/), opts);
16292 return parse_wb_xml((data/*:any*/), opts);
16293}
16294
16295function parse_ws(data, name/*:string*/, idx/*:number*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
16296 if(name.slice(-4)===".bin") return parse_ws_bin((data/*:any*/), opts, idx, rels, wb, themes, styles);
16297 return parse_ws_xml((data/*:any*/), opts, idx, rels, wb, themes, styles);
16298}
16299
16300function parse_cs(data, name/*:string*/, idx/*:number*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
16301 if(name.slice(-4)===".bin") return parse_cs_bin((data/*:any*/), opts, idx, rels, wb, themes, styles);
16302 return parse_cs_xml((data/*:any*/), opts, idx, rels, wb, themes, styles);
16303}
16304
16305function parse_ms(data, name/*:string*/, idx/*:number*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
16306 if(name.slice(-4)===".bin") return parse_ms_bin((data/*:any*/), opts, idx, rels, wb, themes, styles);
16307 return parse_ms_xml((data/*:any*/), opts, idx, rels, wb, themes, styles);
16308}
16309
16310function parse_ds(data, name/*:string*/, idx/*:number*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
16311 if(name.slice(-4)===".bin") return parse_ds_bin((data/*:any*/), opts, idx, rels, wb, themes, styles);
16312 return parse_ds_xml((data/*:any*/), opts, idx, rels, wb, themes, styles);
16313}
16314
16315function parse_sty(data, name/*:string*/, themes, opts) {
16316 if(name.slice(-4)===".bin") return parse_sty_bin((data/*:any*/), themes, opts);
16317 return parse_sty_xml((data/*:any*/), themes, opts);
16318}
16319
16320function parse_theme(data/*:string*/, name/*:string*/, opts) {
16321 return parse_theme_xml(data, opts);
16322}
16323
16324function parse_sst(data, name/*:string*/, opts)/*:SST*/ {
16325 if(name.slice(-4)===".bin") return parse_sst_bin((data/*:any*/), opts);
16326 return parse_sst_xml((data/*:any*/), opts);
16327}
16328
16329function parse_cmnt(data, name/*:string*/, opts)/*:Array<RawComment>*/ {
16330 if(name.slice(-4)===".bin") return parse_comments_bin((data/*:any*/), opts);
16331 return parse_comments_xml((data/*:any*/), opts);
16332}
16333
16334function parse_cc(data, name/*:string*/, opts) {
16335 if(name.slice(-4)===".bin") return parse_cc_bin((data/*:any*/), name, opts);
16336 return parse_cc_xml((data/*:any*/), name, opts);
16337}
16338
16339function parse_xlink(data, rel, name/*:string*/, opts) {
16340 if(name.slice(-4)===".bin") return parse_xlink_bin((data/*:any*/), rel, name, opts);
16341 return parse_xlink_xml((data/*:any*/), rel, name, opts);
16342}
16343
16344function write_wb(wb, name/*:string*/, opts) {
16345 return (name.slice(-4)===".bin" ? write_wb_bin : write_wb_xml)(wb, opts);
16346}
16347
16348function write_ws(data/*:number*/, name/*:string*/, opts, wb/*:Workbook*/, rels) {
16349 return (name.slice(-4)===".bin" ? write_ws_bin : write_ws_xml)(data, opts, wb, rels);
16350}
16351
16352// eslint-disable-next-line no-unused-vars
16353function write_cs(data/*:number*/, name/*:string*/, opts, wb/*:Workbook*/, rels) {
16354 return (name.slice(-4)===".bin" ? write_cs_bin : write_cs_xml)(data, opts, wb, rels);
16355}
16356
16357function write_sty(data, name/*:string*/, opts) {
16358 return (name.slice(-4)===".bin" ? write_sty_bin : write_sty_xml)(data, opts);
16359}
16360
16361function write_sst(data/*:SST*/, name/*:string*/, opts) {
16362 return (name.slice(-4)===".bin" ? write_sst_bin : write_sst_xml)(data, opts);
16363}
16364
16365function write_cmnt(data/*:Array<any>*/, name/*:string*/, opts) {
16366 return (name.slice(-4)===".bin" ? write_comments_bin : write_comments_xml)(data, opts);
16367}
16368/*
16369function write_cc(data, name:string, opts) {
16370 return (name.slice(-4)===".bin" ? write_cc_bin : write_cc_xml)(data, opts);
16371}
16372*/
16373var attregexg2=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
16374var attregex2=/([\w:]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;
16375function xlml_parsexmltag(tag/*:string*/, skip_root/*:?boolean*/) {
16376 var words = tag.split(/\s+/);
16377 var z/*:any*/ = ([]/*:any*/); if(!skip_root) z[0] = words[0];
16378 if(words.length === 1) return z;
16379 var m = tag.match(attregexg2), y, j, w, i;
16380 if(m) for(i = 0; i != m.length; ++i) {
16381 y = m[i].match(attregex2);
16382/*:: if(!y || !y[2]) continue; */
16383 if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].slice(1,y[2].length-1);
16384 else {
16385 if(y[1].slice(0,6) === "xmlns:") w = "xmlns"+y[1].slice(6);
16386 else w = y[1].slice(j+1);
16387 z[w] = y[2].slice(1,y[2].length-1);
16388 }
16389 }
16390 return z;
16391}
16392function xlml_parsexmltagobj(tag/*:string*/) {
16393 var words = tag.split(/\s+/);
16394 var z = {};
16395 if(words.length === 1) return z;
16396 var m = tag.match(attregexg2), y, j, w, i;
16397 if(m) for(i = 0; i != m.length; ++i) {
16398 y = m[i].match(attregex2);
16399/*:: if(!y || !y[2]) continue; */
16400 if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].slice(1,y[2].length-1);
16401 else {
16402 if(y[1].slice(0,6) === "xmlns:") w = "xmlns"+y[1].slice(6);
16403 else w = y[1].slice(j+1);
16404 z[w] = y[2].slice(1,y[2].length-1);
16405 }
16406 }
16407 return z;
16408}
16409
16410// ----
16411
16412function xlml_format(format, value)/*:string*/ {
16413 var fmt = XLMLFormatMap[format] || unescapexml(format);
16414 if(fmt === "General") return SSF._general(value);
16415 return SSF.format(fmt, value);
16416}
16417
16418function xlml_set_custprop(Custprops, key, cp, val/*:string*/) {
16419 var oval/*:any*/ = val;
16420 switch((cp[0].match(/dt:dt="([\w.]+)"/)||["",""])[1]) {
16421 case "boolean": oval = parsexmlbool(val); break;
16422 case "i2": case "int": oval = parseInt(val, 10); break;
16423 case "r4": case "float": oval = parseFloat(val); break;
16424 case "date": case "dateTime.tz": oval = parseDate(val); break;
16425 case "i8": case "string": case "fixed": case "uuid": case "bin.base64": break;
16426 default: throw new Error("bad custprop:" + cp[0]);
16427 }
16428 Custprops[unescapexml(key)] = oval;
16429}
16430
16431function safe_format_xlml(cell/*:Cell*/, nf, o) {
16432 if(cell.t === 'z') return;
16433 if(!o || o.cellText !== false) try {
16434 if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
16435 else if(nf === "General") {
16436 if(cell.t === 'n') {
16437 if((cell.v|0) === cell.v) cell.w = SSF._general_int(cell.v);
16438 else cell.w = SSF._general_num(cell.v);
16439 }
16440 else cell.w = SSF._general(cell.v);
16441 }
16442 else cell.w = xlml_format(nf||"General", cell.v);
16443 } catch(e) { if(o.WTF) throw e; }
16444 try {
16445 var z = XLMLFormatMap[nf]||nf||"General";
16446 if(o.cellNF) cell.z = z;
16447 if(o.cellDates && cell.t == 'n' && SSF.is_date(z)) {
16448 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); }
16449 }
16450 } catch(e) { if(o.WTF) throw e; }
16451}
16452
16453function process_style_xlml(styles, stag, opts) {
16454 if(opts.cellStyles) {
16455 if(stag.Interior) {
16456 var I = stag.Interior;
16457 if(I.Pattern) I.patternType = XLMLPatternTypeMap[I.Pattern] || I.Pattern;
16458 }
16459 }
16460 styles[stag.ID] = stag;
16461}
16462
16463/* TODO: there must exist some form of OSP-blessed spec */
16464function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o) {
16465 var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
16466 var interiors = [];
16467 var i = 0;
16468 if(sid === undefined && row) sid = row.StyleID;
16469 if(sid === undefined && csty) sid = csty.StyleID;
16470 while(styles[sid] !== undefined) {
16471 if(styles[sid].nf) nf = styles[sid].nf;
16472 if(styles[sid].Interior) interiors.push(styles[sid].Interior);
16473 if(!styles[sid].Parent) break;
16474 sid = styles[sid].Parent;
16475 }
16476 switch(data.Type) {
16477 case 'Boolean':
16478 cell.t = 'b';
16479 cell.v = parsexmlbool(xml);
16480 break;
16481 case 'String':
16482 cell.t = 's'; cell.r = xlml_fixstr(unescapexml(xml));
16483 cell.v = (xml.indexOf("<") > -1 ? unescapexml(ss||xml).replace(/<.*?>/g, "") : cell.r); // todo: BR etc
16484 break;
16485 case 'DateTime':
16486 if(xml.slice(-1) != "Z") xml += "Z";
16487 cell.v = (parseDate(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
16488 if(cell.v !== cell.v) cell.v = unescapexml(xml);
16489 else if(cell.v<60) cell.v = cell.v -1;
16490 if(!nf || nf == "General") nf = "yyyy-mm-dd";
16491 /* falls through */
16492 case 'Number':
16493 if(cell.v === undefined) cell.v=+xml;
16494 if(!cell.t) cell.t = 'n';
16495 break;
16496 case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; if(o.cellText !== false) cell.w = xml; break;
16497 default:
16498 if(xml == "" && ss == "") { cell.t = 'z'; }
16499 else { cell.t = 's'; cell.v = xlml_fixstr(ss||xml); }
16500 break;
16501 }
16502 safe_format_xlml(cell, nf, o);
16503 if(o.cellFormula !== false) {
16504 if(cell.Formula) {
16505 var fstr = unescapexml(cell.Formula);
16506 /* strictly speaking, the leading = is required but some writers omit */
16507 if(fstr.charCodeAt(0) == 61 /* = */) fstr = fstr.slice(1);
16508 cell.f = rc_to_a1(fstr, base);
16509 delete cell.Formula;
16510 if(cell.ArrayRange == "RC") cell.F = rc_to_a1("RC:RC", base);
16511 else if(cell.ArrayRange) {
16512 cell.F = rc_to_a1(cell.ArrayRange, base);
16513 arrayf.push([safe_decode_range(cell.F), cell.F]);
16514 }
16515 } else {
16516 for(i = 0; i < arrayf.length; ++i)
16517 if(base.r >= arrayf[i][0].s.r && base.r <= arrayf[i][0].e.r)
16518 if(base.c >= arrayf[i][0].s.c && base.c <= arrayf[i][0].e.c)
16519 cell.F = arrayf[i][1];
16520 }
16521 }
16522 if(o.cellStyles) {
16523 interiors.forEach(function(x) {
16524 if(!S.patternType && x.patternType) S.patternType = x.patternType;
16525 });
16526 cell.s = S;
16527 }
16528 if(cell.StyleID !== undefined) cell.ixfe = cell.StyleID;
16529}
16530
16531function xlml_clean_comment(comment/*:any*/) {
16532 comment.t = comment.v || "";
16533 comment.t = comment.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n");
16534 comment.v = comment.w = comment.ixfe = undefined;
16535}
16536
16537function xlml_normalize(d)/*:string*/ {
16538 if(has_buf &&/*::typeof Buffer !== "undefined" && d != null && d instanceof Buffer &&*/ Buffer.isBuffer(d)) return d.toString('utf8');
16539 if(typeof d === 'string') return d;
16540 /* duktape */
16541 if(typeof Uint8Array !== 'undefined' && d instanceof Uint8Array) return utf8read(a2s(ab2a(d)));
16542 throw new Error("Bad input format: expected Buffer or string");
16543}
16544
16545/* TODO: Everything */
16546/* UOS uses CJK in tags */
16547var xlmlregex = /<(\/?)([^\s?><!\/:]*:|)([^\s?<>:\/]+)(?:[\s?:\/][^>]*)?>/mg;
16548//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
16549function parse_xlml_xml(d, _opts)/*:Workbook*/ {
16550 var opts = _opts || {};
16551 make_ssf(SSF);
16552 var str = debom(xlml_normalize(d));
16553 if(opts.type == 'binary' || opts.type == 'array' || opts.type == 'base64') {
16554 if(typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str));
16555 else str = utf8read(str);
16556 }
16557 var opening = str.slice(0, 1024).toLowerCase(), ishtml = false;
16558 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); }
16559 if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; });
16560 if(ishtml) return HTML_.to_workbook(str, opts);
16561 var Rn;
16562 var state = [], tmp;
16563 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
16564 var sheets = {}, sheetnames/*:Array<string>*/ = [], cursheet/*:Worksheet*/ = (opts.dense ? [] : {}), sheetname = "";
16565 var table = {}, cell = ({}/*:any*/), row = {};// eslint-disable-line no-unused-vars
16566 var dtag = xlml_parsexmltag('<Data ss:Type="String">'), didx = 0;
16567 var c = 0, r = 0;
16568 var refguess/*:Range*/ = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
16569 var styles = {}, stag = {};
16570 var ss = "", fidx = 0;
16571 var merges/*:Array<Range>*/ = [];
16572 var Props = {}, Custprops = {}, pidx = 0, cp = [];
16573 var comments/*:Array<Comment>*/ = [], comment/*:Comment*/ = ({}/*:any*/);
16574 var cstys = [], csty, seencol = false;
16575 var arrayf/*:Array<[Range, string]>*/ = [];
16576 var rowinfo/*:Array<RowInfo>*/ = [], rowobj = {}, cc = 0, rr = 0;
16577 var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false} }/*:any*/), wsprops = {};
16578 xlmlregex.lastIndex = 0;
16579 str = str.replace(/<!--([\s\S]*?)-->/mg,"");
16580 var raw_Rn3 = "";
16581 while((Rn = xlmlregex.exec(str))) switch((Rn[3] = (raw_Rn3 = Rn[3]).toLowerCase())) {
16582 case 'data' /*case 'Data'*/:
16583 if(raw_Rn3 == "data") {
16584 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
16585 else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
16586 break;
16587 }
16588 if(state[state.length-1][1]) break;
16589 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);
16590 else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; }
16591 break;
16592 case 'cell' /*case 'Cell'*/:
16593 if(Rn[1]==='/'){
16594 if(comments.length > 0) cell.c = comments;
16595 if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== undefined) {
16596 if(opts.dense) {
16597 if(!cursheet[r]) cursheet[r] = [];
16598 cursheet[r][c] = cell;
16599 } else cursheet[encode_col(c) + encode_row(r)] = cell;
16600 }
16601 if(cell.HRef) {
16602 cell.l = ({Target:unescapexml(cell.HRef)}/*:any*/);
16603 if(cell.HRefScreenTip) cell.l.Tooltip = cell.HRefScreenTip;
16604 delete cell.HRef; delete cell.HRefScreenTip;
16605 }
16606 if(cell.MergeAcross || cell.MergeDown) {
16607 cc = c + (parseInt(cell.MergeAcross,10)|0);
16608 rr = r + (parseInt(cell.MergeDown,10)|0);
16609 merges.push({s:{c:c,r:r},e:{c:cc,r:rr}});
16610 }
16611 if(!opts.sheetStubs) { if(cell.MergeAcross) c = cc + 1; else ++c; }
16612 else if(cell.MergeAcross || cell.MergeDown) {
16613 /*:: if(!cc) cc = 0; if(!rr) rr = 0; */
16614 for(var cma = c; cma <= cc; ++cma) {
16615 for(var cmd = r; cmd <= rr; ++cmd) {
16616 if(cma > c || cmd > r) {
16617 if(opts.dense) {
16618 if(!cursheet[cmd]) cursheet[cmd] = [];
16619 cursheet[cmd][cma] = {t:'z'};
16620 } else cursheet[encode_col(cma) + encode_row(cmd)] = {t:'z'};
16621 }
16622 }
16623 }
16624 c = cc + 1;
16625 }
16626 else ++c;
16627 } else {
16628 cell = xlml_parsexmltagobj(Rn[0]);
16629 if(cell.Index) c = +cell.Index - 1;
16630 if(c < refguess.s.c) refguess.s.c = c;
16631 if(c > refguess.e.c) refguess.e.c = c;
16632 if(Rn[0].slice(-2) === "/>") ++c;
16633 comments = [];
16634 }
16635 break;
16636 case 'row' /*case 'Row'*/:
16637 if(Rn[1]==='/' || Rn[0].slice(-2) === "/>") {
16638 if(r < refguess.s.r) refguess.s.r = r;
16639 if(r > refguess.e.r) refguess.e.r = r;
16640 if(Rn[0].slice(-2) === "/>") {
16641 row = xlml_parsexmltag(Rn[0]);
16642 if(row.Index) r = +row.Index - 1;
16643 }
16644 c = 0; ++r;
16645 } else {
16646 row = xlml_parsexmltag(Rn[0]);
16647 if(row.Index) r = +row.Index - 1;
16648 rowobj = {};
16649 if(row.AutoFitHeight == "0" || row.Height) {
16650 rowobj.hpx = parseInt(row.Height, 10); rowobj.hpt = px2pt(rowobj.hpx);
16651 rowinfo[r] = rowobj;
16652 }
16653 if(row.Hidden == "1") { rowobj.hidden = true; rowinfo[r] = rowobj; }
16654 }
16655 break;
16656 case 'worksheet' /*case 'Worksheet'*/: /* TODO: read range from FullRows/FullColumns */
16657 if(Rn[1]==='/'){
16658 if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
16659 sheetnames.push(sheetname);
16660 if(refguess.s.r <= refguess.e.r && refguess.s.c <= refguess.e.c) {
16661 cursheet["!ref"] = encode_range(refguess);
16662 if(opts.sheetRows && opts.sheetRows <= refguess.e.r) {
16663 cursheet["!fullref"] = cursheet["!ref"];
16664 refguess.e.r = opts.sheetRows - 1;
16665 cursheet["!ref"] = encode_range(refguess);
16666 }
16667 }
16668 if(merges.length) cursheet["!merges"] = merges;
16669 if(cstys.length > 0) cursheet["!cols"] = cstys;
16670 if(rowinfo.length > 0) cursheet["!rows"] = rowinfo;
16671 sheets[sheetname] = cursheet;
16672 } else {
16673 refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
16674 r = c = 0;
16675 state.push([Rn[3], false]);
16676 tmp = xlml_parsexmltag(Rn[0]);
16677 sheetname = unescapexml(tmp.Name);
16678 cursheet = (opts.dense ? [] : {});
16679 merges = [];
16680 arrayf = [];
16681 rowinfo = [];
16682 wsprops = {name:sheetname, Hidden:0};
16683 Workbook.Sheets.push(wsprops);
16684 }
16685 break;
16686 case 'table' /*case 'Table'*/:
16687 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
16688 else if(Rn[0].slice(-2) == "/>") break;
16689 else {
16690 table = xlml_parsexmltag(Rn[0]);
16691 state.push([Rn[3], false]);
16692 cstys = []; seencol = false;
16693 }
16694 break;
16695
16696 case 'style' /*case 'Style'*/:
16697 if(Rn[1]==='/') process_style_xlml(styles, stag, opts);
16698 else stag = xlml_parsexmltag(Rn[0]);
16699 break;
16700
16701 case 'numberformat' /*case 'NumberFormat'*/:
16702 stag.nf = unescapexml(xlml_parsexmltag(Rn[0]).Format || "General");
16703 if(XLMLFormatMap[stag.nf]) stag.nf = XLMLFormatMap[stag.nf];
16704 for(var ssfidx = 0; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == stag.nf) break;
16705 if(ssfidx == 0x188) for(ssfidx = 0x39; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == null) { SSF.load(stag.nf, ssfidx); break; }
16706 break;
16707
16708 case 'column' /*case 'Column'*/:
16709 if(state[state.length-1][0] !== /*'Table'*/'table') break;
16710 csty = xlml_parsexmltag(Rn[0]);
16711 if(csty.Hidden) { csty.hidden = true; delete csty.Hidden; }
16712 if(csty.Width) csty.wpx = parseInt(csty.Width, 10);
16713 if(!seencol && csty.wpx > 10) {
16714 seencol = true; MDW = DEF_MDW; //find_mdw_wpx(csty.wpx);
16715 for(var _col = 0; _col < cstys.length; ++_col) if(cstys[_col]) process_col(cstys[_col]);
16716 }
16717 if(seencol) process_col(csty);
16718 cstys[(csty.Index-1||cstys.length)] = csty;
16719 for(var i = 0; i < +csty.Span; ++i) cstys[cstys.length] = dup(csty);
16720 break;
16721
16722 case 'namedrange' /*case 'NamedRange'*/:
16723 if(Rn[1]==='/') break;
16724 if(!Workbook.Names) Workbook.Names = [];
16725 var _NamedRange = parsexmltag(Rn[0]);
16726 var _DefinedName/*:DefinedName*/ = ({
16727 Name: _NamedRange.Name,
16728 Ref: rc_to_a1(_NamedRange.RefersTo.slice(1), {r:0, c:0})
16729 }/*:any*/);
16730 if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1;
16731 /*:: if(Workbook.Names) */Workbook.Names.push(_DefinedName);
16732 break;
16733
16734 case 'namedcell' /*case 'NamedCell'*/: break;
16735 case 'b' /*case 'B'*/: break;
16736 case 'i' /*case 'I'*/: break;
16737 case 'u' /*case 'U'*/: break;
16738 case 's' /*case 'S'*/: break;
16739 case 'em' /*case 'EM'*/: break;
16740 case 'h2' /*case 'H2'*/: break;
16741 case 'h3' /*case 'H3'*/: break;
16742 case 'sub' /*case 'Sub'*/: break;
16743 case 'sup' /*case 'Sup'*/: break;
16744 case 'span' /*case 'Span'*/: break;
16745 case 'alignment' /*case 'Alignment'*/:
16746 break;
16747 case 'borders' /*case 'Borders'*/: break;
16748 case 'border' /*case 'Border'*/: break;
16749 case 'font' /*case 'Font'*/:
16750 if(Rn[0].slice(-2) === "/>") break;
16751 else if(Rn[1]==="/") ss += str.slice(fidx, Rn.index);
16752 else fidx = Rn.index + Rn[0].length;
16753 break;
16754 case 'interior' /*case 'Interior'*/:
16755 if(!opts.cellStyles) break;
16756 stag.Interior = xlml_parsexmltag(Rn[0]);
16757 break;
16758 case 'protection' /*case 'Protection'*/: break;
16759
16760 case 'author' /*case 'Author'*/:
16761 case 'title' /*case 'Title'*/:
16762 case 'description' /*case 'Description'*/:
16763 case 'created' /*case 'Created'*/:
16764 case 'keywords' /*case 'Keywords'*/:
16765 case 'subject' /*case 'Subject'*/:
16766 case 'category' /*case 'Category'*/:
16767 case 'company' /*case 'Company'*/:
16768 case 'lastauthor' /*case 'LastAuthor'*/:
16769 case 'lastsaved' /*case 'LastSaved'*/:
16770 case 'lastprinted' /*case 'LastPrinted'*/:
16771 case 'version' /*case 'Version'*/:
16772 case 'revision' /*case 'Revision'*/:
16773 case 'totaltime' /*case 'TotalTime'*/:
16774 case 'hyperlinkbase' /*case 'HyperlinkBase'*/:
16775 case 'manager' /*case 'Manager'*/:
16776 case 'contentstatus' /*case 'ContentStatus'*/:
16777 case 'identifier' /*case 'Identifier'*/:
16778 case 'language' /*case 'Language'*/:
16779 case 'appname' /*case 'AppName'*/:
16780 if(Rn[0].slice(-2) === "/>") break;
16781 else if(Rn[1]==="/") xlml_set_prop(Props, raw_Rn3, str.slice(pidx, Rn.index));
16782 else pidx = Rn.index + Rn[0].length;
16783 break;
16784 case 'paragraphs' /*case 'Paragraphs'*/: break;
16785
16786 case 'styles' /*case 'Styles'*/:
16787 case 'workbook' /*case 'Workbook'*/:
16788 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
16789 else state.push([Rn[3], false]);
16790 break;
16791
16792 case 'comment' /*case 'Comment'*/:
16793 if(Rn[1]==='/'){
16794 if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
16795 xlml_clean_comment(comment);
16796 comments.push(comment);
16797 } else {
16798 state.push([Rn[3], false]);
16799 tmp = xlml_parsexmltag(Rn[0]);
16800 comment = ({a:tmp.Author}/*:any*/);
16801 }
16802 break;
16803
16804 case 'autofilter' /*case 'AutoFilter'*/:
16805 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
16806 else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
16807 var AutoFilter = xlml_parsexmltag(Rn[0]);
16808 cursheet['!autofilter'] = { ref:rc_to_a1(AutoFilter.Range).replace(/\$/g,"") };
16809 state.push([Rn[3], true]);
16810 }
16811 break;
16812
16813 case 'name' /*case 'Name'*/: break;
16814
16815 case 'datavalidation' /*case 'DataValidation'*/:
16816 if(Rn[1]==='/'){
16817 if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
16818 } else {
16819 if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
16820 }
16821 break;
16822
16823 case 'pixelsperinch' /*case 'PixelsPerInch'*/:
16824 break;
16825 case 'componentoptions' /*case 'ComponentOptions'*/:
16826 case 'documentproperties' /*case 'DocumentProperties'*/:
16827 case 'customdocumentproperties' /*case 'CustomDocumentProperties'*/:
16828 case 'officedocumentsettings' /*case 'OfficeDocumentSettings'*/:
16829 case 'pivottable' /*case 'PivotTable'*/:
16830 case 'pivotcache' /*case 'PivotCache'*/:
16831 case 'names' /*case 'Names'*/:
16832 case 'mapinfo' /*case 'MapInfo'*/:
16833 case 'pagebreaks' /*case 'PageBreaks'*/:
16834 case 'querytable' /*case 'QueryTable'*/:
16835 case 'sorting' /*case 'Sorting'*/:
16836 case 'schema' /*case 'Schema'*/: //case 'data' /*case 'data'*/:
16837 case 'conditionalformatting' /*case 'ConditionalFormatting'*/:
16838 case 'smarttagtype' /*case 'SmartTagType'*/:
16839 case 'smarttags' /*case 'SmartTags'*/:
16840 case 'excelworkbook' /*case 'ExcelWorkbook'*/:
16841 case 'workbookoptions' /*case 'WorkbookOptions'*/:
16842 case 'worksheetoptions' /*case 'WorksheetOptions'*/:
16843 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
16844 else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
16845 break;
16846
16847 case 'null' /*case 'Null'*/: break;
16848
16849 default:
16850 /* FODS file root is <office:document> */
16851 if(state.length == 0 && Rn[3] == "document") return parse_fods(str, opts);
16852 /* UOS file root is <uof:UOF> */
16853 if(state.length == 0 && Rn[3] == "uof"/*"UOF"*/) return parse_fods(str, opts);
16854
16855 var seen = true;
16856 switch(state[state.length-1][0]) {
16857 /* OfficeDocumentSettings */
16858 case 'officedocumentsettings' /*case 'OfficeDocumentSettings'*/: switch(Rn[3]) {
16859 case 'allowpng' /*case 'AllowPNG'*/: break;
16860 case 'removepersonalinformation' /*case 'RemovePersonalInformation'*/: break;
16861 case 'downloadcomponents' /*case 'DownloadComponents'*/: break;
16862 case 'locationofcomponents' /*case 'LocationOfComponents'*/: break;
16863 case 'colors' /*case 'Colors'*/: break;
16864 case 'color' /*case 'Color'*/: break;
16865 case 'index' /*case 'Index'*/: break;
16866 case 'rgb' /*case 'RGB'*/: break;
16867 case 'targetscreensize' /*case 'TargetScreenSize'*/: break;
16868 case 'readonlyrecommended' /*case 'ReadOnlyRecommended'*/: break;
16869 default: seen = false;
16870 } break;
16871
16872 /* ComponentOptions */
16873 case 'componentoptions' /*case 'ComponentOptions'*/: switch(Rn[3]) {
16874 case 'toolbar' /*case 'Toolbar'*/: break;
16875 case 'hideofficelogo' /*case 'HideOfficeLogo'*/: break;
16876 case 'spreadsheetautofit' /*case 'SpreadsheetAutoFit'*/: break;
16877 case 'label' /*case 'Label'*/: break;
16878 case 'caption' /*case 'Caption'*/: break;
16879 case 'maxheight' /*case 'MaxHeight'*/: break;
16880 case 'maxwidth' /*case 'MaxWidth'*/: break;
16881 case 'nextsheetnumber' /*case 'NextSheetNumber'*/: break;
16882 default: seen = false;
16883 } break;
16884
16885 /* ExcelWorkbook */
16886 case 'excelworkbook' /*case 'ExcelWorkbook'*/: switch(Rn[3]) {
16887 case 'date1904' /*case 'Date1904'*/:
16888 /*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
16889 Workbook.WBProps.date1904 = true;
16890 break;
16891 case 'windowheight' /*case 'WindowHeight'*/: break;
16892 case 'windowwidth' /*case 'WindowWidth'*/: break;
16893 case 'windowtopx' /*case 'WindowTopX'*/: break;
16894 case 'windowtopy' /*case 'WindowTopY'*/: break;
16895 case 'tabratio' /*case 'TabRatio'*/: break;
16896 case 'protectstructure' /*case 'ProtectStructure'*/: break;
16897 case 'protectwindow' /*case 'ProtectWindow'*/: break;
16898 case 'protectwindows' /*case 'ProtectWindows'*/: break;
16899 case 'activesheet' /*case 'ActiveSheet'*/: break;
16900 case 'displayinknotes' /*case 'DisplayInkNotes'*/: break;
16901 case 'firstvisiblesheet' /*case 'FirstVisibleSheet'*/: break;
16902 case 'supbook' /*case 'SupBook'*/: break;
16903 case 'sheetname' /*case 'SheetName'*/: break;
16904 case 'sheetindex' /*case 'SheetIndex'*/: break;
16905 case 'sheetindexfirst' /*case 'SheetIndexFirst'*/: break;
16906 case 'sheetindexlast' /*case 'SheetIndexLast'*/: break;
16907 case 'dll' /*case 'Dll'*/: break;
16908 case 'acceptlabelsinformulas' /*case 'AcceptLabelsInFormulas'*/: break;
16909 case 'donotsavelinkvalues' /*case 'DoNotSaveLinkValues'*/: break;
16910 case 'iteration' /*case 'Iteration'*/: break;
16911 case 'maxiterations' /*case 'MaxIterations'*/: break;
16912 case 'maxchange' /*case 'MaxChange'*/: break;
16913 case 'path' /*case 'Path'*/: break;
16914 case 'xct' /*case 'Xct'*/: break;
16915 case 'count' /*case 'Count'*/: break;
16916 case 'selectedsheets' /*case 'SelectedSheets'*/: break;
16917 case 'calculation' /*case 'Calculation'*/: break;
16918 case 'uncalced' /*case 'Uncalced'*/: break;
16919 case 'startupprompt' /*case 'StartupPrompt'*/: break;
16920 case 'crn' /*case 'Crn'*/: break;
16921 case 'externname' /*case 'ExternName'*/: break;
16922 case 'formula' /*case 'Formula'*/: break;
16923 case 'colfirst' /*case 'ColFirst'*/: break;
16924 case 'collast' /*case 'ColLast'*/: break;
16925 case 'wantadvise' /*case 'WantAdvise'*/: break;
16926 case 'boolean' /*case 'Boolean'*/: break;
16927 case 'error' /*case 'Error'*/: break;
16928 case 'text' /*case 'Text'*/: break;
16929 case 'ole' /*case 'OLE'*/: break;
16930 case 'noautorecover' /*case 'NoAutoRecover'*/: break;
16931 case 'publishobjects' /*case 'PublishObjects'*/: break;
16932 case 'donotcalculatebeforesave' /*case 'DoNotCalculateBeforeSave'*/: break;
16933 case 'number' /*case 'Number'*/: break;
16934 case 'refmoder1c1' /*case 'RefModeR1C1'*/: break;
16935 case 'embedsavesmarttags' /*case 'EmbedSaveSmartTags'*/: break;
16936 default: seen = false;
16937 } break;
16938
16939 /* WorkbookOptions */
16940 case 'workbookoptions' /*case 'WorkbookOptions'*/: switch(Rn[3]) {
16941 case 'owcversion' /*case 'OWCVersion'*/: break;
16942 case 'height' /*case 'Height'*/: break;
16943 case 'width' /*case 'Width'*/: break;
16944 default: seen = false;
16945 } break;
16946
16947 /* WorksheetOptions */
16948 case 'worksheetoptions' /*case 'WorksheetOptions'*/: switch(Rn[3]) {
16949 case 'visible' /*case 'Visible'*/:
16950 if(Rn[0].slice(-2) === "/>"){/* empty */}
16951 else if(Rn[1]==="/") switch(str.slice(pidx, Rn.index)) {
16952 case "SheetHidden": wsprops.Hidden = 1; break;
16953 case "SheetVeryHidden": wsprops.Hidden = 2; break;
16954 }
16955 else pidx = Rn.index + Rn[0].length;
16956 break;
16957 case 'header' /*case 'Header'*/:
16958 if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
16959 cursheet['!margins'].header = parsexmltag(Rn[0]).Margin;
16960 break;
16961 case 'footer' /*case 'Footer'*/:
16962 if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
16963 cursheet['!margins'].footer = parsexmltag(Rn[0]).Margin;
16964 break;
16965 case 'pagemargins' /*case 'PageMargins'*/:
16966 var pagemargins = parsexmltag(Rn[0]);
16967 if(!cursheet['!margins']) default_margins(cursheet['!margins']={},'xlml');
16968 if(pagemargins.Top) cursheet['!margins'].top = pagemargins.Top;
16969 if(pagemargins.Left) cursheet['!margins'].left = pagemargins.Left;
16970 if(pagemargins.Right) cursheet['!margins'].right = pagemargins.Right;
16971 if(pagemargins.Bottom) cursheet['!margins'].bottom = pagemargins.Bottom;
16972 break;
16973 case 'displayrighttoleft' /*case 'DisplayRightToLeft'*/:
16974 if(!Workbook.Views) Workbook.Views = [];
16975 if(!Workbook.Views[0]) Workbook.Views[0] = {};
16976 Workbook.Views[0].RTL = true;
16977 break;
16978
16979 case 'freezepanes' /*case 'FreezePanes'*/: break;
16980 case 'frozennosplit' /*case 'FrozenNoSplit'*/: break;
16981
16982 case 'splithorizontal' /*case 'SplitHorizontal'*/:
16983 case 'splitvertical' /*case 'SplitVertical'*/:
16984 break;
16985
16986 case 'donotdisplaygridlines' /*case 'DoNotDisplayGridlines'*/:
16987 break;
16988
16989 case 'activerow' /*case 'ActiveRow'*/: break;
16990 case 'activecol' /*case 'ActiveCol'*/: break;
16991 case 'toprowbottompane' /*case 'TopRowBottomPane'*/: break;
16992 case 'leftcolumnrightpane' /*case 'LeftColumnRightPane'*/: break;
16993
16994 case 'unsynced' /*case 'Unsynced'*/: break;
16995 case 'print' /*case 'Print'*/: break;
16996 case 'printerrors' /*case 'PrintErrors'*/: break;
16997 case 'panes' /*case 'Panes'*/: break;
16998 case 'scale' /*case 'Scale'*/: break;
16999 case 'pane' /*case 'Pane'*/: break;
17000 case 'number' /*case 'Number'*/: break;
17001 case 'layout' /*case 'Layout'*/: break;
17002 case 'pagesetup' /*case 'PageSetup'*/: break;
17003 case 'selected' /*case 'Selected'*/: break;
17004 case 'protectobjects' /*case 'ProtectObjects'*/: break;
17005 case 'enableselection' /*case 'EnableSelection'*/: break;
17006 case 'protectscenarios' /*case 'ProtectScenarios'*/: break;
17007 case 'validprinterinfo' /*case 'ValidPrinterInfo'*/: break;
17008 case 'horizontalresolution' /*case 'HorizontalResolution'*/: break;
17009 case 'verticalresolution' /*case 'VerticalResolution'*/: break;
17010 case 'numberofcopies' /*case 'NumberofCopies'*/: break;
17011 case 'activepane' /*case 'ActivePane'*/: break;
17012 case 'toprowvisible' /*case 'TopRowVisible'*/: break;
17013 case 'leftcolumnvisible' /*case 'LeftColumnVisible'*/: break;
17014 case 'fittopage' /*case 'FitToPage'*/: break;
17015 case 'rangeselection' /*case 'RangeSelection'*/: break;
17016 case 'papersizeindex' /*case 'PaperSizeIndex'*/: break;
17017 case 'pagelayoutzoom' /*case 'PageLayoutZoom'*/: break;
17018 case 'pagebreakzoom' /*case 'PageBreakZoom'*/: break;
17019 case 'filteron' /*case 'FilterOn'*/: break;
17020 case 'fitwidth' /*case 'FitWidth'*/: break;
17021 case 'fitheight' /*case 'FitHeight'*/: break;
17022 case 'commentslayout' /*case 'CommentsLayout'*/: break;
17023 case 'zoom' /*case 'Zoom'*/: break;
17024 case 'lefttoright' /*case 'LeftToRight'*/: break;
17025 case 'gridlines' /*case 'Gridlines'*/: break;
17026 case 'allowsort' /*case 'AllowSort'*/: break;
17027 case 'allowfilter' /*case 'AllowFilter'*/: break;
17028 case 'allowinsertrows' /*case 'AllowInsertRows'*/: break;
17029 case 'allowdeleterows' /*case 'AllowDeleteRows'*/: break;
17030 case 'allowinsertcols' /*case 'AllowInsertCols'*/: break;
17031 case 'allowdeletecols' /*case 'AllowDeleteCols'*/: break;
17032 case 'allowinserthyperlinks' /*case 'AllowInsertHyperlinks'*/: break;
17033 case 'allowformatcells' /*case 'AllowFormatCells'*/: break;
17034 case 'allowsizecols' /*case 'AllowSizeCols'*/: break;
17035 case 'allowsizerows' /*case 'AllowSizeRows'*/: break;
17036 case 'nosummaryrowsbelowdetail' /*case 'NoSummaryRowsBelowDetail'*/:
17037 if(!cursheet["!outline"]) cursheet["!outline"] = {};
17038 cursheet["!outline"].above = true;
17039 break;
17040 case 'tabcolorindex' /*case 'TabColorIndex'*/: break;
17041 case 'donotdisplayheadings' /*case 'DoNotDisplayHeadings'*/: break;
17042 case 'showpagelayoutzoom' /*case 'ShowPageLayoutZoom'*/: break;
17043 case 'nosummarycolumnsrightdetail' /*case 'NoSummaryColumnsRightDetail'*/:
17044 if(!cursheet["!outline"]) cursheet["!outline"] = {};
17045 cursheet["!outline"].left = true;
17046 break;
17047 case 'blackandwhite' /*case 'BlackAndWhite'*/: break;
17048 case 'donotdisplayzeros' /*case 'DoNotDisplayZeros'*/: break;
17049 case 'displaypagebreak' /*case 'DisplayPageBreak'*/: break;
17050 case 'rowcolheadings' /*case 'RowColHeadings'*/: break;
17051 case 'donotdisplayoutline' /*case 'DoNotDisplayOutline'*/: break;
17052 case 'noorientation' /*case 'NoOrientation'*/: break;
17053 case 'allowusepivottables' /*case 'AllowUsePivotTables'*/: break;
17054 case 'zeroheight' /*case 'ZeroHeight'*/: break;
17055 case 'viewablerange' /*case 'ViewableRange'*/: break;
17056 case 'selection' /*case 'Selection'*/: break;
17057 case 'protectcontents' /*case 'ProtectContents'*/: break;
17058 default: seen = false;
17059 } break;
17060
17061 /* PivotTable */
17062 case 'pivottable' /*case 'PivotTable'*/: case 'pivotcache' /*case 'PivotCache'*/: switch(Rn[3]) {
17063 case 'immediateitemsondrop' /*case 'ImmediateItemsOnDrop'*/: break;
17064 case 'showpagemultipleitemlabel' /*case 'ShowPageMultipleItemLabel'*/: break;
17065 case 'compactrowindent' /*case 'CompactRowIndent'*/: break;
17066 case 'location' /*case 'Location'*/: break;
17067 case 'pivotfield' /*case 'PivotField'*/: break;
17068 case 'orientation' /*case 'Orientation'*/: break;
17069 case 'layoutform' /*case 'LayoutForm'*/: break;
17070 case 'layoutsubtotallocation' /*case 'LayoutSubtotalLocation'*/: break;
17071 case 'layoutcompactrow' /*case 'LayoutCompactRow'*/: break;
17072 case 'position' /*case 'Position'*/: break;
17073 case 'pivotitem' /*case 'PivotItem'*/: break;
17074 case 'datatype' /*case 'DataType'*/: break;
17075 case 'datafield' /*case 'DataField'*/: break;
17076 case 'sourcename' /*case 'SourceName'*/: break;
17077 case 'parentfield' /*case 'ParentField'*/: break;
17078 case 'ptlineitems' /*case 'PTLineItems'*/: break;
17079 case 'ptlineitem' /*case 'PTLineItem'*/: break;
17080 case 'countofsameitems' /*case 'CountOfSameItems'*/: break;
17081 case 'item' /*case 'Item'*/: break;
17082 case 'itemtype' /*case 'ItemType'*/: break;
17083 case 'ptsource' /*case 'PTSource'*/: break;
17084 case 'cacheindex' /*case 'CacheIndex'*/: break;
17085 case 'consolidationreference' /*case 'ConsolidationReference'*/: break;
17086 case 'filename' /*case 'FileName'*/: break;
17087 case 'reference' /*case 'Reference'*/: break;
17088 case 'nocolumngrand' /*case 'NoColumnGrand'*/: break;
17089 case 'norowgrand' /*case 'NoRowGrand'*/: break;
17090 case 'blanklineafteritems' /*case 'BlankLineAfterItems'*/: break;
17091 case 'hidden' /*case 'Hidden'*/: break;
17092 case 'subtotal' /*case 'Subtotal'*/: break;
17093 case 'basefield' /*case 'BaseField'*/: break;
17094 case 'mapchilditems' /*case 'MapChildItems'*/: break;
17095 case 'function' /*case 'Function'*/: break;
17096 case 'refreshonfileopen' /*case 'RefreshOnFileOpen'*/: break;
17097 case 'printsettitles' /*case 'PrintSetTitles'*/: break;
17098 case 'mergelabels' /*case 'MergeLabels'*/: break;
17099 case 'defaultversion' /*case 'DefaultVersion'*/: break;
17100 case 'refreshname' /*case 'RefreshName'*/: break;
17101 case 'refreshdate' /*case 'RefreshDate'*/: break;
17102 case 'refreshdatecopy' /*case 'RefreshDateCopy'*/: break;
17103 case 'versionlastrefresh' /*case 'VersionLastRefresh'*/: break;
17104 case 'versionlastupdate' /*case 'VersionLastUpdate'*/: break;
17105 case 'versionupdateablemin' /*case 'VersionUpdateableMin'*/: break;
17106 case 'versionrefreshablemin' /*case 'VersionRefreshableMin'*/: break;
17107 case 'calculation' /*case 'Calculation'*/: break;
17108 default: seen = false;
17109 } break;
17110
17111 /* PageBreaks */
17112 case 'pagebreaks' /*case 'PageBreaks'*/: switch(Rn[3]) {
17113 case 'colbreaks' /*case 'ColBreaks'*/: break;
17114 case 'colbreak' /*case 'ColBreak'*/: break;
17115 case 'rowbreaks' /*case 'RowBreaks'*/: break;
17116 case 'rowbreak' /*case 'RowBreak'*/: break;
17117 case 'colstart' /*case 'ColStart'*/: break;
17118 case 'colend' /*case 'ColEnd'*/: break;
17119 case 'rowend' /*case 'RowEnd'*/: break;
17120 default: seen = false;
17121 } break;
17122
17123 /* AutoFilter */
17124 case 'autofilter' /*case 'AutoFilter'*/: switch(Rn[3]) {
17125 case 'autofiltercolumn' /*case 'AutoFilterColumn'*/: break;
17126 case 'autofiltercondition' /*case 'AutoFilterCondition'*/: break;
17127 case 'autofilterand' /*case 'AutoFilterAnd'*/: break;
17128 case 'autofilteror' /*case 'AutoFilterOr'*/: break;
17129 default: seen = false;
17130 } break;
17131
17132 /* QueryTable */
17133 case 'querytable' /*case 'QueryTable'*/: switch(Rn[3]) {
17134 case 'id' /*case 'Id'*/: break;
17135 case 'autoformatfont' /*case 'AutoFormatFont'*/: break;
17136 case 'autoformatpattern' /*case 'AutoFormatPattern'*/: break;
17137 case 'querysource' /*case 'QuerySource'*/: break;
17138 case 'querytype' /*case 'QueryType'*/: break;
17139 case 'enableredirections' /*case 'EnableRedirections'*/: break;
17140 case 'refreshedinxl9' /*case 'RefreshedInXl9'*/: break;
17141 case 'urlstring' /*case 'URLString'*/: break;
17142 case 'htmltables' /*case 'HTMLTables'*/: break;
17143 case 'connection' /*case 'Connection'*/: break;
17144 case 'commandtext' /*case 'CommandText'*/: break;
17145 case 'refreshinfo' /*case 'RefreshInfo'*/: break;
17146 case 'notitles' /*case 'NoTitles'*/: break;
17147 case 'nextid' /*case 'NextId'*/: break;
17148 case 'columninfo' /*case 'ColumnInfo'*/: break;
17149 case 'overwritecells' /*case 'OverwriteCells'*/: break;
17150 case 'donotpromptforfile' /*case 'DoNotPromptForFile'*/: break;
17151 case 'textwizardsettings' /*case 'TextWizardSettings'*/: break;
17152 case 'source' /*case 'Source'*/: break;
17153 case 'number' /*case 'Number'*/: break;
17154 case 'decimal' /*case 'Decimal'*/: break;
17155 case 'thousandseparator' /*case 'ThousandSeparator'*/: break;
17156 case 'trailingminusnumbers' /*case 'TrailingMinusNumbers'*/: break;
17157 case 'formatsettings' /*case 'FormatSettings'*/: break;
17158 case 'fieldtype' /*case 'FieldType'*/: break;
17159 case 'delimiters' /*case 'Delimiters'*/: break;
17160 case 'tab' /*case 'Tab'*/: break;
17161 case 'comma' /*case 'Comma'*/: break;
17162 case 'autoformatname' /*case 'AutoFormatName'*/: break;
17163 case 'versionlastedit' /*case 'VersionLastEdit'*/: break;
17164 case 'versionlastrefresh' /*case 'VersionLastRefresh'*/: break;
17165 default: seen = false;
17166 } break;
17167
17168 case 'datavalidation' /*case 'DataValidation'*/:
17169 switch(Rn[3]) {
17170 case 'range' /*case 'Range'*/: break;
17171
17172 case 'type' /*case 'Type'*/: break;
17173 case 'min' /*case 'Min'*/: break;
17174 case 'max' /*case 'Max'*/: break;
17175 case 'sort' /*case 'Sort'*/: break;
17176 case 'descending' /*case 'Descending'*/: break;
17177 case 'order' /*case 'Order'*/: break;
17178 case 'casesensitive' /*case 'CaseSensitive'*/: break;
17179 case 'value' /*case 'Value'*/: break;
17180 case 'errorstyle' /*case 'ErrorStyle'*/: break;
17181 case 'errormessage' /*case 'ErrorMessage'*/: break;
17182 case 'errortitle' /*case 'ErrorTitle'*/: break;
17183 case 'inputmessage' /*case 'InputMessage'*/: break;
17184 case 'inputtitle' /*case 'InputTitle'*/: break;
17185 case 'combohide' /*case 'ComboHide'*/: break;
17186 case 'inputhide' /*case 'InputHide'*/: break;
17187 case 'condition' /*case 'Condition'*/: break;
17188 case 'qualifier' /*case 'Qualifier'*/: break;
17189 case 'useblank' /*case 'UseBlank'*/: break;
17190 case 'value1' /*case 'Value1'*/: break;
17191 case 'value2' /*case 'Value2'*/: break;
17192 case 'format' /*case 'Format'*/: break;
17193
17194 case 'cellrangelist' /*case 'CellRangeList'*/: break;
17195 default: seen = false;
17196 } break;
17197
17198 case 'sorting' /*case 'Sorting'*/:
17199 case 'conditionalformatting' /*case 'ConditionalFormatting'*/:
17200 switch(Rn[3]) {
17201 case 'range' /*case 'Range'*/: break;
17202 case 'type' /*case 'Type'*/: break;
17203 case 'min' /*case 'Min'*/: break;
17204 case 'max' /*case 'Max'*/: break;
17205 case 'sort' /*case 'Sort'*/: break;
17206 case 'descending' /*case 'Descending'*/: break;
17207 case 'order' /*case 'Order'*/: break;
17208 case 'casesensitive' /*case 'CaseSensitive'*/: break;
17209 case 'value' /*case 'Value'*/: break;
17210 case 'errorstyle' /*case 'ErrorStyle'*/: break;
17211 case 'errormessage' /*case 'ErrorMessage'*/: break;
17212 case 'errortitle' /*case 'ErrorTitle'*/: break;
17213 case 'cellrangelist' /*case 'CellRangeList'*/: break;
17214 case 'inputmessage' /*case 'InputMessage'*/: break;
17215 case 'inputtitle' /*case 'InputTitle'*/: break;
17216 case 'combohide' /*case 'ComboHide'*/: break;
17217 case 'inputhide' /*case 'InputHide'*/: break;
17218 case 'condition' /*case 'Condition'*/: break;
17219 case 'qualifier' /*case 'Qualifier'*/: break;
17220 case 'useblank' /*case 'UseBlank'*/: break;
17221 case 'value1' /*case 'Value1'*/: break;
17222 case 'value2' /*case 'Value2'*/: break;
17223 case 'format' /*case 'Format'*/: break;
17224 default: seen = false;
17225 } break;
17226
17227 /* MapInfo (schema) */
17228 case 'mapinfo' /*case 'MapInfo'*/: case 'schema' /*case 'Schema'*/: case 'data' /*case 'data'*/: switch(Rn[3]) {
17229 case 'map' /*case 'Map'*/: break;
17230 case 'entry' /*case 'Entry'*/: break;
17231 case 'range' /*case 'Range'*/: break;
17232 case 'xpath' /*case 'XPath'*/: break;
17233 case 'field' /*case 'Field'*/: break;
17234 case 'xsdtype' /*case 'XSDType'*/: break;
17235 case 'filteron' /*case 'FilterOn'*/: break;
17236 case 'aggregate' /*case 'Aggregate'*/: break;
17237 case 'elementtype' /*case 'ElementType'*/: break;
17238 case 'attributetype' /*case 'AttributeType'*/: break;
17239 /* These are from xsd (XML Schema Definition) */
17240 case 'schema' /*case 'schema'*/:
17241 case 'element' /*case 'element'*/:
17242 case 'complextype' /*case 'complexType'*/:
17243 case 'datatype' /*case 'datatype'*/:
17244 case 'all' /*case 'all'*/:
17245 case 'attribute' /*case 'attribute'*/:
17246 case 'extends' /*case 'extends'*/: break;
17247
17248 case 'row' /*case 'row'*/: break;
17249 default: seen = false;
17250 } break;
17251
17252 /* SmartTags (can be anything) */
17253 case 'smarttags' /*case 'SmartTags'*/: break;
17254
17255 default: seen = false; break;
17256 }
17257 if(seen) break;
17258 /* CustomDocumentProperties */
17259 if(Rn[3].match(/!\[CDATA/)) break;
17260 if(!state[state.length-1][1]) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
17261 if(state[state.length-1][0]===/*'CustomDocumentProperties'*/'customdocumentproperties') {
17262 if(Rn[0].slice(-2) === "/>") break;
17263 else if(Rn[1]==="/") xlml_set_custprop(Custprops, raw_Rn3, cp, str.slice(pidx, Rn.index));
17264 else { cp = Rn; pidx = Rn.index + Rn[0].length; }
17265 break;
17266 }
17267 if(opts.WTF) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
17268 }
17269 var out = ({}/*:any*/);
17270 if(!opts.bookSheets && !opts.bookProps) out.Sheets = sheets;
17271 out.SheetNames = sheetnames;
17272 out.Workbook = Workbook;
17273 out.SSF = SSF.get_table();
17274 out.Props = Props;
17275 out.Custprops = Custprops;
17276 return out;
17277}
17278
17279function parse_xlml(data/*:RawBytes|string*/, opts)/*:Workbook*/ {
17280 fix_read_opts(opts=opts||{});
17281 switch(opts.type||"base64") {
17282 case "base64": return parse_xlml_xml(Base64.decode(data), opts);
17283 case "binary": case "buffer": case "file": return parse_xlml_xml(data, opts);
17284 case "array": return parse_xlml_xml(a2s(data), opts);
17285 }
17286 /*:: throw new Error("unsupported type " + opts.type); */
17287}
17288
17289/* TODO */
17290function write_props_xlml(wb/*:Workbook*/, opts)/*:string*/ {
17291 var o/*:Array<string>*/ = [];
17292 /* DocumentProperties */
17293 if(wb.Props) o.push(xlml_write_docprops(wb.Props, opts));
17294 /* CustomDocumentProperties */
17295 if(wb.Custprops) o.push(xlml_write_custprops(wb.Props, wb.Custprops, opts));
17296 return o.join("");
17297}
17298/* TODO */
17299function write_wb_xlml(/*::wb, opts*/)/*:string*/ {
17300 /* OfficeDocumentSettings */
17301 /* ExcelWorkbook */
17302 return "";
17303}
17304/* TODO */
17305function write_sty_xlml(wb, opts)/*:string*/ {
17306 /* Styles */
17307 var styles/*:Array<string>*/ = ['<Style ss:ID="Default" ss:Name="Normal"><NumberFormat/></Style>'];
17308 opts.cellXfs.forEach(function(xf, id) {
17309 var payload/*:Array<string>*/ = [];
17310 payload.push(writextag('NumberFormat', null, {"ss:Format": escapexml(SSF._table[xf.numFmtId])}));
17311
17312 var o = /*::(*/{"ss:ID": "s" + (21+id)}/*:: :any)*/;
17313 styles.push(writextag('Style', payload.join(""), o));
17314 });
17315 return writextag("Styles", styles.join(""));
17316}
17317function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); }
17318function write_names_xlml(wb/*::, opts*/)/*:string*/ {
17319 if(!((wb||{}).Workbook||{}).Names) return "";
17320 /*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */
17321 var names/*:Array<any>*/ = wb.Workbook.Names;
17322 var out/*:Array<string>*/ = [];
17323 for(var i = 0; i < names.length; ++i) {
17324 var n = names[i];
17325 if(n.Sheet != null) continue;
17326 if(n.Name.match(/^_xlfn\./)) continue;
17327 out.push(write_name_xlml(n));
17328 }
17329 return writextag("Names", out.join(""));
17330}
17331function write_ws_xlml_names(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
17332 if(!ws) return "";
17333 if(!((wb||{}).Workbook||{}).Names) return "";
17334 /*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */
17335 var names/*:Array<any>*/ = wb.Workbook.Names;
17336 var out/*:Array<string>*/ = [];
17337 for(var i = 0; i < names.length; ++i) {
17338 var n = names[i];
17339 if(n.Sheet != idx) continue;
17340 /*switch(n.Name) {
17341 case "_": continue;
17342 }*/
17343 if(n.Name.match(/^_xlfn\./)) continue;
17344 out.push(write_name_xlml(n));
17345 }
17346 return out.join("");
17347}
17348/* WorksheetOptions */
17349function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
17350 if(!ws) return "";
17351 var o/*:Array<string>*/ = [];
17352 /* NOTE: spec technically allows any order, but stick with implied order */
17353
17354 /* FitToPage */
17355 /* DoNotDisplayColHeaders */
17356 /* DoNotDisplayRowHeaders */
17357 /* ViewableRange */
17358 /* Selection */
17359 /* GridlineColor */
17360 /* Name */
17361 /* ExcelWorksheetType */
17362 /* IntlMacro */
17363 /* Unsynced */
17364 /* Selected */
17365 /* CodeName */
17366
17367 if(ws['!margins']) {
17368 o.push("<PageSetup>");
17369 if(ws['!margins'].header) o.push(writextag("Header", null, {'x:Margin':ws['!margins'].header}));
17370 if(ws['!margins'].footer) o.push(writextag("Footer", null, {'x:Margin':ws['!margins'].footer}));
17371 o.push(writextag("PageMargins", null, {
17372 'x:Bottom': ws['!margins'].bottom || "0.75",
17373 'x:Left': ws['!margins'].left || "0.7",
17374 'x:Right': ws['!margins'].right || "0.7",
17375 'x:Top': ws['!margins'].top || "0.75"
17376 }));
17377 o.push("</PageSetup>");
17378 }
17379
17380 /* PageSetup */
17381 /* DisplayPageBreak */
17382 /* TransitionExpressionEvaluation */
17383 /* TransitionFormulaEntry */
17384 /* Print */
17385 /* Zoom */
17386 /* PageLayoutZoom */
17387 /* PageBreakZoom */
17388 /* ShowPageBreakZoom */
17389 /* DefaultRowHeight */
17390 /* DefaultColumnWidth */
17391 /* StandardWidth */
17392
17393 if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) {
17394 /* Visible */
17395 if(wb.Workbook.Sheets[idx].Hidden) o.push(writextag("Visible", (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden"), {}));
17396 else {
17397 /* Selected */
17398 for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break;
17399 if(i == idx) o.push("<Selected/>");
17400 }
17401 }
17402
17403 /* LeftColumnVisible */
17404
17405 if(((((wb||{}).Workbook||{}).Views||[])[0]||{}).RTL) o.push("<DisplayRightToLeft/>");
17406
17407 /* GridlineColorIndex */
17408 /* DisplayFormulas */
17409 /* DoNotDisplayGridlines */
17410 /* DoNotDisplayHeadings */
17411 /* DoNotDisplayOutline */
17412 /* ApplyAutomaticOutlineStyles */
17413 /* NoSummaryRowsBelowDetail */
17414 /* NoSummaryColumnsRightDetail */
17415 /* DoNotDisplayZeros */
17416 /* ActiveRow */
17417 /* ActiveColumn */
17418 /* FilterOn */
17419 /* RangeSelection */
17420 /* TopRowVisible */
17421 /* TopRowBottomPane */
17422 /* LeftColumnRightPane */
17423 /* ActivePane */
17424 /* SplitHorizontal */
17425 /* SplitVertical */
17426 /* FreezePanes */
17427 /* FrozenNoSplit */
17428 /* TabColorIndex */
17429 /* Panes */
17430
17431 /* NOTE: Password not supported in XLML Format */
17432 if(ws['!protect']) {
17433 o.push(writetag("ProtectContents", "True"));
17434 if(ws['!protect'].objects) o.push(writetag("ProtectObjects", "True"));
17435 if(ws['!protect'].scenarios) o.push(writetag("ProtectScenarios", "True"));
17436 if(ws['!protect'].selectLockedCells != null && !ws['!protect'].selectLockedCells) o.push(writetag("EnableSelection", "NoSelection"));
17437 else if(ws['!protect'].selectUnlockedCells != null && !ws['!protect'].selectUnlockedCells) o.push(writetag("EnableSelection", "UnlockedCells"));
17438 [
17439 [ "formatCells", "AllowFormatCells" ],
17440 [ "formatColumns", "AllowSizeCols" ],
17441 [ "formatRows", "AllowSizeRows" ],
17442 [ "insertColumns", "AllowInsertCols" ],
17443 [ "insertRows", "AllowInsertRows" ],
17444 [ "insertHyperlinks", "AllowInsertHyperlinks" ],
17445 [ "deleteColumns", "AllowDeleteCols" ],
17446 [ "deleteRows", "AllowDeleteRows" ],
17447 [ "sort", "AllowSort" ],
17448 [ "autoFilter", "AllowFilter" ],
17449 [ "pivotTables", "AllowUsePivotTables" ]
17450 ].forEach(function(x) { if(ws['!protect'][x[0]]) o.push("<"+x[1]+"/>"); });
17451 }
17452
17453 if(o.length == 0) return "";
17454 return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x});
17455}
17456function write_ws_xlml_comment(comments/*:Array<any>*/)/*:string*/ {
17457 return comments.map(function(c) {
17458 // TODO: formatted text
17459 var t = xlml_unfixstr(c.t||"");
17460 var d =writextag("ss:Data", t, {"xmlns":"http://www.w3.org/TR/REC-html40"});
17461 return writextag("Comment", d, {"ss:Author":c.a});
17462 }).join("");
17463}
17464function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, addr)/*:string*/{
17465 if(!cell || (cell.v == undefined && cell.f == undefined)) return "";
17466
17467 var attr = {};
17468 if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr));
17469 if(cell.F && cell.F.slice(0, ref.length) == ref) {
17470 var end = decode_cell(cell.F.slice(ref.length + 1));
17471 attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]");
17472 }
17473
17474 if(cell.l && cell.l.Target) {
17475 attr["ss:HRef"] = escapexml(cell.l.Target);
17476 if(cell.l.Tooltip) attr["x:HRefScreenTip"] = escapexml(cell.l.Tooltip);
17477 }
17478
17479 if(ws['!merges']) {
17480 var marr = ws['!merges'];
17481 for(var mi = 0; mi != marr.length; ++mi) {
17482 if(marr[mi].s.c != addr.c || marr[mi].s.r != addr.r) continue;
17483 if(marr[mi].e.c > marr[mi].s.c) attr['ss:MergeAcross'] = marr[mi].e.c - marr[mi].s.c;
17484 if(marr[mi].e.r > marr[mi].s.r) attr['ss:MergeDown'] = marr[mi].e.r - marr[mi].s.r;
17485 }
17486 }
17487
17488 var t = "", p = "";
17489 switch(cell.t) {
17490 case 'z': if(!opts.sheetStubs) return ""; break;
17491 case 'n': t = 'Number'; p = String(cell.v); break;
17492 case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
17493 case 'e': t = 'Error'; p = BErr[cell.v]; break;
17494 case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break;
17495 case 's': t = 'String'; p = escapexlml(cell.v||""); break;
17496 }
17497 /* TODO: cell style */
17498 var os = get_cell_style(opts.cellXfs, cell, opts);
17499 attr["ss:StyleID"] = "s" + (21+os);
17500 attr["ss:Index"] = addr.c + 1;
17501 var _v = (cell.v != null ? p : "");
17502 var m = cell.t == 'z' ? "" : ('<Data ss:Type="' + t + '">' + _v + '</Data>');
17503
17504 if((cell.c||[]).length > 0) m += write_ws_xlml_comment(cell.c);
17505
17506 return writextag("Cell", m, attr);
17507}
17508function write_ws_xlml_row(R/*:number*/, row)/*:string*/ {
17509 var o = '<Row ss:Index="' + (R+1) + '"';
17510 if(row) {
17511 if(row.hpt && !row.hpx) row.hpx = pt2px(row.hpt);
17512 if(row.hpx) o += ' ss:AutoFitHeight="0" ss:Height="' + row.hpx + '"';
17513 if(row.hidden) o += ' ss:Hidden="1"';
17514 }
17515 return o + '>';
17516}
17517/* TODO */
17518function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
17519 if(!ws['!ref']) return "";
17520 var range/*:Range*/ = safe_decode_range(ws['!ref']);
17521 var marr/*:Array<Range>*/ = ws['!merges'] || [], mi = 0;
17522 var o/*:Array<string>*/ = [];
17523 if(ws['!cols']) ws['!cols'].forEach(function(n, i) {
17524 process_col(n);
17525 var w = !!n.width;
17526 var p = col_obj_w(i, n);
17527 var k/*:any*/ = {"ss:Index":i+1};
17528 if(w) k['ss:Width'] = width2px(p.width);
17529 if(n.hidden) k['ss:Hidden']="1";
17530 o.push(writextag("Column",null,k));
17531 });
17532 var dense = Array.isArray(ws);
17533 for(var R = range.s.r; R <= range.e.r; ++R) {
17534 var row = [write_ws_xlml_row(R, (ws['!rows']||[])[R])];
17535 for(var C = range.s.c; C <= range.e.c; ++C) {
17536 var skip = false;
17537 for(mi = 0; mi != marr.length; ++mi) {
17538 if(marr[mi].s.c > C) continue;
17539 if(marr[mi].s.r > R) continue;
17540 if(marr[mi].e.c < C) continue;
17541 if(marr[mi].e.r < R) continue;
17542 if(marr[mi].s.c != C || marr[mi].s.r != R) skip = true;
17543 break;
17544 }
17545 if(skip) continue;
17546 var addr = {r:R,c:C};
17547 var ref = encode_cell(addr), cell = dense ? (ws[R]||[])[C] : ws[ref];
17548 row.push(write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr));
17549 }
17550 row.push("</Row>");
17551 if(row.length > 2) o.push(row.join(""));
17552 }
17553 return o.join("");
17554}
17555function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ {
17556 var o/*:Array<string>*/ = [];
17557 var s = wb.SheetNames[idx];
17558 var ws = wb.Sheets[s];
17559
17560 var t/*:string*/ = ws ? write_ws_xlml_names(ws, opts, idx, wb) : "";
17561 if(t.length > 0) o.push("<Names>" + t + "</Names>");
17562
17563 /* Table */
17564 t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
17565 if(t.length > 0) o.push("<Table>" + t + "</Table>");
17566
17567 /* WorksheetOptions */
17568 o.push(write_ws_xlml_wsopts(ws, opts, idx, wb));
17569
17570 return o.join("");
17571}
17572function write_xlml(wb, opts)/*:string*/ {
17573 if(!opts) opts = {};
17574 if(!wb.SSF) wb.SSF = SSF.get_table();
17575 if(wb.SSF) {
17576 make_ssf(SSF); SSF.load_table(wb.SSF);
17577 // $FlowIgnore
17578 opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
17579 opts.ssf = wb.SSF;
17580 opts.cellXfs = [];
17581 get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}});
17582 }
17583 var d/*:Array<string>*/ = [];
17584 d.push(write_props_xlml(wb, opts));
17585 d.push(write_wb_xlml(wb, opts));
17586 d.push("");
17587 d.push("");
17588 for(var i = 0; i < wb.SheetNames.length; ++i)
17589 d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])}));
17590 d[2] = write_sty_xlml(wb, opts);
17591 d[3] = write_names_xlml(wb, opts);
17592 return XML_HEADER + writextag("Workbook", d.join(""), {
17593 'xmlns': XLMLNS.ss,
17594 'xmlns:o': XLMLNS.o,
17595 'xmlns:x': XLMLNS.x,
17596 'xmlns:ss': XLMLNS.ss,
17597 'xmlns:dt': XLMLNS.dt,
17598 'xmlns:html': XLMLNS.html
17599 });
17600}
17601/* [MS-OLEDS] 2.3.8 CompObjStream */
17602function parse_compobj(obj/*:CFBEntry*/) {
17603 var v = {};
17604 var o = obj.content;
17605 /*:: if(o == null) return; */
17606
17607 /* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
17608 o.l = 28;
17609
17610 v.AnsiUserType = o.read_shift(0, "lpstr-ansi");
17611 v.AnsiClipboardFormat = parse_ClipboardFormatOrAnsiString(o);
17612
17613 if(o.length - o.l <= 4) return v;
17614
17615 var m/*:number*/ = o.read_shift(4);
17616 if(m == 0 || m > 40) return v;
17617 o.l-=4; v.Reserved1 = o.read_shift(0, "lpstr-ansi");
17618
17619 if(o.length - o.l <= 4) return v;
17620 m = o.read_shift(4);
17621 if(m !== 0x71b239f4) return v;
17622 v.UnicodeClipboardFormat = parse_ClipboardFormatOrUnicodeString(o);
17623
17624 m = o.read_shift(4);
17625 if(m == 0 || m > 40) return v;
17626 o.l-=4; v.Reserved2 = o.read_shift(0, "lpwstr");
17627}
17628
17629/*
17630 Continue logic for:
17631 - 2.4.58 Continue
17632 - 2.4.59 ContinueBigName
17633 - 2.4.60 ContinueFrt
17634 - 2.4.61 ContinueFrt11
17635 - 2.4.62 ContinueFrt12
17636*/
17637function slurp(R, blob, length/*:number*/, opts)/*:any*/ {
17638 var l = length;
17639 var bufs = [];
17640 var d = blob.slice(blob.l,blob.l+l);
17641 if(opts && opts.enc && opts.enc.insitu && d.length > 0) switch(R.n) {
17642 case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': case 'EOF':
17643 break;
17644 case 'BoundSheet8':
17645 break;
17646 default:
17647 opts.enc.insitu(d);
17648 }
17649 bufs.push(d);
17650 blob.l += l;
17651 var next = (XLSRecordEnum[__readUInt16LE(blob,blob.l)]);
17652 var start = 0;
17653 while(next != null && next.n.slice(0,8) === 'Continue') {
17654 l = __readUInt16LE(blob,blob.l+2);
17655 start = blob.l + 4;
17656 if(next.n == 'ContinueFrt') start += 4;
17657 else if(next.n.slice(0,11) == 'ContinueFrt') {
17658 start += 12;
17659 }
17660 d = blob.slice(start,blob.l+4+l);
17661 bufs.push(d);
17662 blob.l += 4+l;
17663 next = (XLSRecordEnum[__readUInt16LE(blob, blob.l)]);
17664 }
17665 var b = (bconcat(bufs)/*:any*/);
17666 prep_blob(b, 0);
17667 var ll = 0; b.lens = [];
17668 for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; }
17669 if(b.length < length) throw "XLS Record " + (R && R.n || "??") + " Truncated: " + b.length + " < " + length;
17670 return R.f(b, b.length, opts);
17671}
17672
17673function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
17674 if(p.t === 'z') return;
17675 if(!p.XF) return;
17676 var fmtid = 0;
17677 try {
17678 fmtid = p.z || p.XF.numFmtId || 0;
17679 if(opts.cellNF) p.z = SSF._table[fmtid];
17680 } catch(e) { if(opts.WTF) throw e; }
17681 if(!opts || opts.cellText !== false) try {
17682 if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
17683 else if(fmtid === 0 || fmtid == "General") {
17684 if(p.t === 'n') {
17685 if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
17686 else p.w = SSF._general_num(p.v);
17687 }
17688 else p.w = SSF._general(p.v);
17689 }
17690 else p.w = SSF.format(fmtid,p.v, {date1904:!!date1904, dateNF: opts && opts.dateNF});
17691 } catch(e) { if(opts.WTF) throw e; }
17692 if(opts.cellDates && fmtid && p.t == 'n' && SSF.is_date(SSF._table[fmtid] || String(fmtid))) {
17693 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); }
17694 }
17695}
17696
17697function make_cell(val, ixfe, t)/*:Cell*/ {
17698 return ({v:val, ixfe:ixfe, t:t}/*:any*/);
17699}
17700
17701// 2.3.2
17702function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
17703 var wb = ({opts:{}}/*:any*/);
17704 var Sheets = {};
17705 if(DENSE != null && options.dense == null) options.dense = DENSE;
17706 var out/*:Worksheet*/ = ((options.dense ? [] : {})/*:any*/);
17707 var Directory = {};
17708 var range/*:Range*/ = ({}/*:any*/);
17709 var last_formula = null;
17710 var sst/*:SST*/ = ([]/*:any*/);
17711 var cur_sheet = "";
17712 var Preamble = {};
17713 var lastcell, last_cell = "", cc/*:Cell*/, cmnt, rngC, rngR;
17714 var sharedf = {};
17715 var arrayf/*:Array<[Range, string]>*/ = [];
17716 var temp_val/*:Cell*/;
17717 var country;
17718 var XFs = []; /* XF records */
17719 var palette/*:Array<[number, number, number]>*/ = [];
17720 var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false}, Views:[{}] }/*:any*/), wsprops = {};
17721 var get_rgb = function getrgb(icv/*:number*/)/*:[number, number, number]*/ {
17722 if(icv < 8) return XLSIcv[icv];
17723 if(icv < 64) return palette[icv-8] || XLSIcv[icv];
17724 return XLSIcv[icv];
17725 };
17726 var process_cell_style = function pcs(cell, line/*:any*/, options) {
17727 var xfd = line.XF.data;
17728 if(!xfd || !xfd.patternType || !options || !options.cellStyles) return;
17729 line.s = ({}/*:any*/);
17730 line.s.patternType = xfd.patternType;
17731 var t;
17732 if((t = rgb2Hex(get_rgb(xfd.icvFore)))) { line.s.fgColor = {rgb:t}; }
17733 if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; }
17734 };
17735 var addcell = function addcell(cell/*:any*/, line/*:any*/, options/*:any*/) {
17736 if(file_depth > 1) return;
17737 if(options.sheetRows && cell.r >= options.sheetRows) return;
17738 if(options.cellStyles && line.XF && line.XF.data) process_cell_style(cell, line, options);
17739 delete line.ixfe; delete line.XF;
17740 lastcell = cell;
17741 last_cell = encode_cell(cell);
17742 if(!range || !range.s || !range.e) range = {s:{r:0,c:0},e:{r:0,c:0}};
17743 if(cell.r < range.s.r) range.s.r = cell.r;
17744 if(cell.c < range.s.c) range.s.c = cell.c;
17745 if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1;
17746 if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1;
17747 if(options.cellFormula && line.f) {
17748 for(var afi = 0; afi < arrayf.length; ++afi) {
17749 if(arrayf[afi][0].s.c > cell.c || arrayf[afi][0].s.r > cell.r) continue;
17750 if(arrayf[afi][0].e.c < cell.c || arrayf[afi][0].e.r < cell.r) continue;
17751 line.F = encode_range(arrayf[afi][0]);
17752 if(arrayf[afi][0].s.c != cell.c || arrayf[afi][0].s.r != cell.r) delete line.f;
17753 if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts);
17754 break;
17755 }
17756 }
17757 {
17758 if(options.dense) {
17759 if(!out[cell.r]) out[cell.r] = [];
17760 out[cell.r][cell.c] = line;
17761 } else out[last_cell] = line;
17762 }
17763 };
17764 var opts = ({
17765 enc: false, // encrypted
17766 sbcch: 0, // cch in the preceding SupBook
17767 snames: [], // sheetnames
17768 sharedf: sharedf, // shared formulae by address
17769 arrayf: arrayf, // array formulae array
17770 rrtabid: [], // RRTabId
17771 lastuser: "", // Last User from WriteAccess
17772 biff: 8, // BIFF version
17773 codepage: 0, // CP from CodePage record
17774 winlocked: 0, // fLockWn from WinProtect
17775 cellStyles: !!options && !!options.cellStyles,
17776 WTF: !!options && !!options.wtf
17777 }/*:any*/);
17778 if(options.password) opts.password = options.password;
17779 var themes;
17780 var merges/*:Array<Range>*/ = [];
17781 var objects = [];
17782 var colinfo/*:Array<ColInfo>*/ = [], rowinfo/*:Array<RowInfo>*/ = [];
17783 // eslint-disable-next-line no-unused-vars
17784 var defwidth = 0, defheight = 0; // twips / MDW respectively
17785 var seencol = false;
17786 var supbooks = ([]/*:any*/); // 1-indexed, will hold extern names
17787 supbooks.SheetNames = opts.snames;
17788 supbooks.sharedf = opts.sharedf;
17789 supbooks.arrayf = opts.arrayf;
17790 supbooks.names = [];
17791 supbooks.XTI = [];
17792 var last_Rn = '';
17793 var file_depth = 0; /* TODO: make a real stack */
17794 var BIFF2Fmt = 0, BIFF2FmtTable/*:Array<string>*/ = [];
17795 var FilterDatabases = []; /* TODO: sort out supbooks and process elsewhere */
17796 var last_lbl/*:?DefinedName*/;
17797
17798 /* explicit override for some broken writers */
17799 opts.codepage = 1200;
17800 set_cp(1200);
17801 var seen_codepage = false;
17802 while(blob.l < blob.length - 1) {
17803 var s = blob.l;
17804 var RecordType = blob.read_shift(2);
17805 if(RecordType === 0 && last_Rn === 'EOF') break;
17806 var length = (blob.l === blob.length ? 0 : blob.read_shift(2));
17807 var R = XLSRecordEnum[RecordType];
17808 //console.log(RecordType.toString(16), RecordType, R, blob.l, length, blob.length);
17809 //if(!R) console.log(blob.slice(blob.l, blob.l + length));
17810 if(R && R.f) {
17811 if(options.bookSheets) {
17812 if(last_Rn === 'BoundSheet8' && R.n !== 'BoundSheet8') break;
17813 }
17814 last_Rn = R.n;
17815 if(R.r === 2 || R.r == 12) {
17816 var rt = blob.read_shift(2); length -= 2;
17817 if(!opts.enc && rt !== RecordType && (((rt&0xFF)<<8)|(rt>>8)) !== RecordType) throw new Error("rt mismatch: " + rt + "!=" + RecordType);
17818 if(R.r == 12){
17819 blob.l += 10; length -= 10;
17820 } // skip FRT
17821 }
17822 //console.error(R,blob.l,length,blob.length);
17823 var val/*:any*/ = ({}/*:any*/);
17824 if(R.n === 'EOF') val = /*::(*/R.f(blob, length, opts)/*:: :any)*/;
17825 else val = /*::(*/slurp(R, blob, length, opts)/*:: :any)*/;
17826 var Rn = R.n;
17827 /*:: val = (val:any); */
17828 if(file_depth == 0 && Rn != 'BOF') continue;
17829 /* nested switch statements to workaround V8 128 limit */
17830 switch(Rn) {
17831 /* Workbook Options */
17832 case 'Date1904':
17833 /*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
17834 wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
17835 case 'WriteProtect': wb.opts.WriteProtect = true; break;
17836 case 'FilePass':
17837 if(!opts.enc) blob.l = 0;
17838 opts.enc = val;
17839 if(!options.password) throw new Error("File is password-protected");
17840 if(val.valid == null) throw new Error("Encryption scheme unsupported");
17841 if(!val.valid) throw new Error("Password is incorrect");
17842 break;
17843 case 'WriteAccess': opts.lastuser = val; break;
17844 case 'FileSharing': break; //TODO
17845 case 'CodePage':
17846 var cpval = Number(val);
17847 /* overrides based on test cases */
17848 switch(cpval) {
17849 case 0x5212: cpval = 1200; break;
17850 case 0x8000: cpval = 10000; break;
17851 case 0x8001: cpval = 1252; break;
17852 }
17853 set_cp(opts.codepage = cpval);
17854 seen_codepage = true;
17855 break;
17856 case 'RRTabId': opts.rrtabid = val; break;
17857 case 'WinProtect': opts.winlocked = val; break;
17858 case 'Template': break; // TODO
17859 case 'BookBool': break; // TODO
17860 case 'UsesELFs': break;
17861 case 'MTRSettings': break;
17862 case 'RefreshAll':
17863 case 'CalcCount':
17864 case 'CalcDelta':
17865 case 'CalcIter':
17866 case 'CalcMode':
17867 case 'CalcPrecision':
17868 case 'CalcSaveRecalc':
17869 wb.opts[Rn] = val; break;
17870 case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
17871 case 'Uncalced': break;
17872 case 'ForceFullCalculation': wb.opts.FullCalc = val; break;
17873 case 'WsBool':
17874 if(val.fDialog) out["!type"] = "dialog";
17875 if(!val.fBelow) (out["!outline"] || (out["!outline"] = {})).above = true;
17876 if(!val.fRight) (out["!outline"] || (out["!outline"] = {})).left = true;
17877 break; // TODO
17878 case 'XF':
17879 XFs.push(val); break;
17880 case 'ExtSST': break; // TODO
17881 case 'BookExt': break; // TODO
17882 case 'RichTextStream': break;
17883 case 'BkHim': break;
17884
17885 case 'SupBook':
17886 supbooks.push([val]);
17887 supbooks[supbooks.length-1].XTI = [];
17888 break;
17889 case 'ExternName':
17890 supbooks[supbooks.length-1].push(val);
17891 break;
17892 case 'Index': break; // TODO
17893 case 'Lbl':
17894 last_lbl = ({
17895 Name: val.Name,
17896 Ref: stringify_formula(val.rgce,range,null,supbooks,opts)
17897 }/*:DefinedName*/);
17898 if(val.itab > 0) last_lbl.Sheet = val.itab - 1;
17899 supbooks.names.push(last_lbl);
17900 if(!supbooks[0]) { supbooks[0] = []; supbooks[0].XTI = []; }
17901 supbooks[supbooks.length-1].push(val);
17902 if(val.Name == "_xlnm._FilterDatabase" && val.itab > 0)
17903 if(val.rgce && val.rgce[0] && val.rgce[0][0] && val.rgce[0][0][0] == 'PtgArea3d')
17904 FilterDatabases[val.itab - 1] = { ref: encode_range(val.rgce[0][0][1][2]) };
17905 break;
17906 case 'ExternCount': opts.ExternCount = val; break;
17907 case 'ExternSheet':
17908 if(supbooks.length == 0) { supbooks[0] = []; supbooks[0].XTI = []; }
17909 supbooks[supbooks.length - 1].XTI = supbooks[supbooks.length - 1].XTI.concat(val); supbooks.XTI = supbooks.XTI.concat(val); break;
17910 case 'NameCmt':
17911 /* TODO: search for correct name */
17912 if(opts.biff < 8) break;
17913 if(last_lbl != null) last_lbl.Comment = val[1];
17914 break;
17915
17916 case 'Protect': out["!protect"] = val; break; /* for sheet or book */
17917 case 'Password': if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
17918 case 'Prot4Rev': case 'Prot4RevPass': break; /*TODO: Revision Control*/
17919
17920 case 'BoundSheet8': {
17921 Directory[val.pos] = val;
17922 opts.snames.push(val.name);
17923 } break;
17924 case 'EOF': {
17925 if(--file_depth) break;
17926 if(range.e) {
17927 if(range.e.r > 0 && range.e.c > 0) {
17928 range.e.r--; range.e.c--;
17929 out["!ref"] = encode_range(range);
17930 if(options.sheetRows && options.sheetRows <= range.e.r) {
17931 var tmpri = range.e.r;
17932 range.e.r = options.sheetRows - 1;
17933 out["!fullref"] = out["!ref"];
17934 out["!ref"] = encode_range(range);
17935 range.e.r = tmpri;
17936 }
17937 range.e.r++; range.e.c++;
17938 }
17939 if(merges.length > 0) out["!merges"] = merges;
17940 if(objects.length > 0) out["!objects"] = objects;
17941 if(colinfo.length > 0) out["!cols"] = colinfo;
17942 if(rowinfo.length > 0) out["!rows"] = rowinfo;
17943 Workbook.Sheets.push(wsprops);
17944 }
17945 if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out;
17946 out = ((options.dense ? [] : {})/*:any*/);
17947 } break;
17948 case 'BOF': {
17949 if(opts.biff === 8) opts.biff = {
17950 /*::[*/0x0009/*::]*/:2,
17951 /*::[*/0x0209/*::]*/:3,
17952 /*::[*/0x0409/*::]*/:4
17953 }[RecordType] || {
17954 /*::[*/0x0200/*::]*/:2,
17955 /*::[*/0x0300/*::]*/:3,
17956 /*::[*/0x0400/*::]*/:4,
17957 /*::[*/0x0500/*::]*/:5,
17958 /*::[*/0x0600/*::]*/:8,
17959 /*::[*/0x0002/*::]*/:2,
17960 /*::[*/0x0007/*::]*/:2
17961 }[val.BIFFVer] || 8;
17962 opts.biffguess = val.BIFFVer == 0;
17963 if(val.BIFFVer == 0 && val.dt == 0x1000) { opts.biff = 5; seen_codepage = true; set_cp(opts.codepage = 28591); }
17964 if(opts.biff == 8 && val.BIFFVer == 0 && val.dt == 16) opts.biff = 2;
17965 if(file_depth++) break;
17966 out = ((options.dense ? [] : {})/*:any*/);
17967
17968 if(opts.biff < 8 && !seen_codepage) { seen_codepage = true; set_cp(opts.codepage = options.codepage || 1252); }
17969
17970 if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) {
17971 if(cur_sheet === "") cur_sheet = "Sheet1";
17972 range = {s:{r:0,c:0},e:{r:0,c:0}};
17973 /* fake BoundSheet8 */
17974 var fakebs8 = {pos: blob.l - length, name:cur_sheet};
17975 Directory[fakebs8.pos] = fakebs8;
17976 opts.snames.push(cur_sheet);
17977 }
17978 else cur_sheet = (Directory[s] || {name:""}).name;
17979 if(val.dt == 0x20) out["!type"] = "chart";
17980 if(val.dt == 0x40) out["!type"] = "macro";
17981 merges = [];
17982 objects = [];
17983 opts.arrayf = arrayf = [];
17984 colinfo = []; rowinfo = [];
17985 defwidth = defheight = 0;
17986 seencol = false;
17987 wsprops = {Hidden:(Directory[s]||{hs:0}).hs, name:cur_sheet };
17988 } break;
17989
17990 case 'Number': case 'BIFF2NUM': case 'BIFF2INT': {
17991 if(out["!type"] == "chart") if(options.dense ? (out[val.r]||[])[val.c]: out[encode_cell({c:val.c, r:val.r})]) ++val.c;
17992 temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe]||{}, v:val.val, t:'n'}/*:any*/);
17993 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
17994 safe_format_xf(temp_val, options, wb.opts.Date1904);
17995 addcell({c:val.c, r:val.r}, temp_val, options);
17996 } break;
17997 case 'BoolErr': {
17998 temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t}/*:any*/);
17999 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
18000 safe_format_xf(temp_val, options, wb.opts.Date1904);
18001 addcell({c:val.c, r:val.r}, temp_val, options);
18002 } break;
18003 case 'RK': {
18004 temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'}/*:any*/);
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({c:val.c, r:val.r}, temp_val, options);
18008 } break;
18009 case 'MulRk': {
18010 for(var j = val.c; j <= val.C; ++j) {
18011 var ixfe = val.rkrec[j-val.c][0];
18012 temp_val= ({ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'}/*:any*/);
18013 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
18014 safe_format_xf(temp_val, options, wb.opts.Date1904);
18015 addcell({c:j, r:val.r}, temp_val, options);
18016 }
18017 } break;
18018 case 'Formula': {
18019 if(val.val == 'String') { last_formula = val; break; }
18020 temp_val = make_cell(val.val, val.cell.ixfe, val.tt);
18021 temp_val.XF = XFs[temp_val.ixfe];
18022 if(options.cellFormula) {
18023 var _f = val.formula;
18024 if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
18025 var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
18026 var _fe = encode_cell({r:_fr, c:_fc});
18027 if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
18028 else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F;
18029 } else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
18030 }
18031 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
18032 safe_format_xf(temp_val, options, wb.opts.Date1904);
18033 addcell(val.cell, temp_val, options);
18034 last_formula = val;
18035 } break;
18036 case 'String': {
18037 if(last_formula) { /* technically always true */
18038 last_formula.val = val;
18039 temp_val = make_cell(val, last_formula.cell.ixfe, 's');
18040 temp_val.XF = XFs[temp_val.ixfe];
18041 if(options.cellFormula) {
18042 temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
18043 }
18044 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
18045 safe_format_xf(temp_val, options, wb.opts.Date1904);
18046 addcell(last_formula.cell, temp_val, options);
18047 last_formula = null;
18048 } else throw new Error("String record expects Formula");
18049 } break;
18050 case 'Array': {
18051 arrayf.push(val);
18052 var _arraystart = encode_cell(val[0].s);
18053 cc = options.dense ? (out[val[0].s.r]||[])[val[0].s.c] : out[_arraystart];
18054 if(options.cellFormula && cc) {
18055 if(!last_formula) break; /* technically unreachable */
18056 if(!_arraystart || !cc) break;
18057 cc.f = ""+stringify_formula(val[1], range, val[0], supbooks, opts);
18058 cc.F = encode_range(val[0]);
18059 }
18060 } break;
18061 case 'ShrFmla': {
18062 if(!options.cellFormula) break;
18063 if(last_cell) {
18064 /* TODO: capture range */
18065 if(!last_formula) break; /* technically unreachable */
18066 sharedf[encode_cell(last_formula.cell)]= val[0];
18067 cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
18068 (cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
18069 }
18070 } break;
18071 case 'LabelSst':
18072 temp_val=make_cell(sst[val.isst].t, val.ixfe, 's');
18073 if(sst[val.isst].h) temp_val.h = sst[val.isst].h;
18074 temp_val.XF = XFs[temp_val.ixfe];
18075 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
18076 safe_format_xf(temp_val, options, wb.opts.Date1904);
18077 addcell({c:val.c, r:val.r}, temp_val, options);
18078 break;
18079 case 'Blank': if(options.sheetStubs) {
18080 temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'}/*:any*/);
18081 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
18082 safe_format_xf(temp_val, options, wb.opts.Date1904);
18083 addcell({c:val.c, r:val.r}, temp_val, options);
18084 } break;
18085 case 'MulBlank': if(options.sheetStubs) {
18086 for(var _j = val.c; _j <= val.C; ++_j) {
18087 var _ixfe = val.ixfe[_j-val.c];
18088 temp_val= ({ixfe:_ixfe, XF:XFs[_ixfe], t:'z'}/*:any*/);
18089 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
18090 safe_format_xf(temp_val, options, wb.opts.Date1904);
18091 addcell({c:_j, r:val.r}, temp_val, options);
18092 }
18093 } break;
18094 case 'RString':
18095 case 'Label': case 'BIFF2STR':
18096 temp_val=make_cell(val.val, val.ixfe, 's');
18097 temp_val.XF = XFs[temp_val.ixfe];
18098 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
18099 safe_format_xf(temp_val, options, wb.opts.Date1904);
18100 addcell({c:val.c, r:val.r}, temp_val, options);
18101 break;
18102
18103 case 'Dimensions': {
18104 if(file_depth === 1) range = val; /* TODO: stack */
18105 } break;
18106 case 'SST': {
18107 sst = val;
18108 } break;
18109 case 'Format': { /* val = [id, fmt] */
18110 if(opts.biff == 4) {
18111 BIFF2FmtTable[BIFF2Fmt++] = val[1];
18112 for(var b4idx = 0; b4idx < BIFF2Fmt + 163; ++b4idx) if(SSF._table[b4idx] == val[1]) break;
18113 if(b4idx >= 163) SSF.load(val[1], BIFF2Fmt + 163);
18114 }
18115 else SSF.load(val[1], val[0]);
18116 } break;
18117 case 'BIFF2FORMAT': {
18118 BIFF2FmtTable[BIFF2Fmt++] = val;
18119 for(var b2idx = 0; b2idx < BIFF2Fmt + 163; ++b2idx) if(SSF._table[b2idx] == val) break;
18120 if(b2idx >= 163) SSF.load(val, BIFF2Fmt + 163);
18121 } break;
18122
18123 case 'MergeCells': merges = merges.concat(val); break;
18124
18125 case 'Obj': objects[val.cmo[0]] = opts.lastobj = val; break;
18126 case 'TxO': opts.lastobj.TxO = val; break;
18127 case 'ImData': opts.lastobj.ImData = val; break;
18128
18129 case 'HLink': {
18130 for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
18131 for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
18132 cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
18133 if(cc) cc.l = val[1];
18134 }
18135 } break;
18136 case 'HLinkTooltip': {
18137 for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
18138 for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
18139 cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
18140 if(cc && cc.l) cc.l.Tooltip = val[1];
18141 }
18142 } break;
18143
18144 /* Comments */
18145 case 'Note': {
18146 if(opts.biff <= 5 && opts.biff >= 2) break; /* TODO: BIFF5 */
18147 cc = options.dense ? (out[val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
18148 var noteobj = objects[val[2]];
18149 if(!cc) {
18150 if(options.dense) {
18151 if(!out[val[0].r]) out[val[0].r] = [];
18152 cc = out[val[0].r][val[0].c] = ({t:"z"}/*:any*/);
18153 } else {
18154 cc = out[encode_cell(val[0])] = ({t:"z"}/*:any*/);
18155 }
18156 range.e.r = Math.max(range.e.r, val[0].r);
18157 range.s.r = Math.min(range.s.r, val[0].r);
18158 range.e.c = Math.max(range.e.c, val[0].c);
18159 range.s.c = Math.min(range.s.c, val[0].c);
18160 }
18161 if(!cc.c) cc.c = [];
18162 cmnt = {a:val[1],t:noteobj.TxO.t};
18163 cc.c.push(cmnt);
18164 } break;
18165
18166 default: switch(R.n) { /* nested */
18167 case 'ClrtClient': break;
18168 case 'XFExt': update_xfext(XFs[val.ixfe], val.ext); break;
18169
18170 case 'DefColWidth': defwidth = val; break;
18171 case 'DefaultRowHeight': defheight = val[1]; break; // TODO: flags
18172
18173 case 'ColInfo': {
18174 if(!opts.cellStyles) break;
18175 while(val.e >= val.s) {
18176 colinfo[val.e--] = { width: val.w/256, level: (val.level || 0), hidden: !!(val.flags & 1) };
18177 if(!seencol) { seencol = true; find_mdw_colw(val.w/256); }
18178 process_col(colinfo[val.e+1]);
18179 }
18180 } break;
18181 case 'Row': {
18182 var rowobj = {};
18183 if(val.level != null) { rowinfo[val.r] = rowobj; rowobj.level = val.level; }
18184 if(val.hidden) { rowinfo[val.r] = rowobj; rowobj.hidden = true; }
18185 if(val.hpt) {
18186 rowinfo[val.r] = rowobj;
18187 rowobj.hpt = val.hpt; rowobj.hpx = pt2px(val.hpt);
18188 }
18189 } break;
18190
18191 case 'LeftMargin':
18192 case 'RightMargin':
18193 case 'TopMargin':
18194 case 'BottomMargin':
18195 if(!out['!margins']) default_margins(out['!margins'] = {});
18196 out['!margins'][Rn.slice(0,-6).toLowerCase()] = val;
18197 break;
18198
18199 case 'Selection': break;
18200
18201 case 'Setup': // TODO
18202 if(!out['!margins']) default_margins(out['!margins'] = {});
18203 out['!margins'].header = val.header;
18204 out['!margins'].footer = val.footer;
18205 break;
18206
18207 case 'Window2': // TODO
18208 // $FlowIgnore
18209 if(val.RTL) Workbook.Views[0].RTL = true;
18210 break;
18211
18212 case 'Header': break; // TODO
18213 case 'Footer': break; // TODO
18214 case 'HCenter': break; // TODO
18215 case 'VCenter': break; // TODO
18216 case 'Pls': break; // TODO
18217 case 'GCW': break;
18218 case 'LHRecord': break;
18219 case 'DBCell': break; // TODO
18220 case 'EntExU2': break; // TODO
18221 case 'SxView': break; // TODO
18222 case 'Sxvd': break; // TODO
18223 case 'SXVI': break; // TODO
18224 case 'SXVDEx': break; // TODO
18225 case 'SxIvd': break; // TODO
18226 case 'SXString': break; // TODO
18227 case 'Sync': break;
18228 case 'Addin': break;
18229 case 'SXDI': break; // TODO
18230 case 'SXLI': break; // TODO
18231 case 'SXEx': break; // TODO
18232 case 'QsiSXTag': break; // TODO
18233 case 'Feat': break;
18234 case 'FeatHdr': case 'FeatHdr11': break;
18235 case 'Feature11': case 'Feature12': case 'List12': break;
18236 case 'Country': country = val; break;
18237 case 'RecalcId': break;
18238 case 'DxGCol': break; // TODO: htmlify
18239 case 'Fbi': case 'Fbi2': case 'GelFrame': break;
18240 case 'Font': break; // TODO
18241 case 'XFCRC': break; // TODO
18242 case 'Style': break; // TODO
18243 case 'StyleExt': break; // TODO
18244 case 'Palette': palette = val; break;
18245 case 'Theme': themes = val; break;
18246 /* Protection */
18247 case 'ScenarioProtect': break;
18248 case 'ObjProtect': break;
18249
18250 /* Conditional Formatting */
18251 case 'CondFmt12': break;
18252
18253 /* Table */
18254 case 'Table': break; // TODO
18255 case 'TableStyles': break; // TODO
18256 case 'TableStyle': break; // TODO
18257 case 'TableStyleElement': break; // TODO
18258
18259 /* PivotTable */
18260 case 'SXStreamID': break; // TODO
18261 case 'SXVS': break; // TODO
18262 case 'DConRef': break; // TODO
18263 case 'SXAddl': break; // TODO
18264 case 'DConBin': break; // TODO
18265 case 'DConName': break; // TODO
18266 case 'SXPI': break; // TODO
18267 case 'SxFormat': break; // TODO
18268 case 'SxSelect': break; // TODO
18269 case 'SxRule': break; // TODO
18270 case 'SxFilt': break; // TODO
18271 case 'SxItm': break; // TODO
18272 case 'SxDXF': break; // TODO
18273
18274 /* Scenario Manager */
18275 case 'ScenMan': break;
18276
18277 /* Data Consolidation */
18278 case 'DCon': break;
18279
18280 /* Watched Cell */
18281 case 'CellWatch': break;
18282
18283 /* Print Settings */
18284 case 'PrintRowCol': break;
18285 case 'PrintGrid': break;
18286 case 'PrintSize': break;
18287
18288 case 'XCT': break;
18289 case 'CRN': break;
18290
18291 case 'Scl': {
18292 //console.log("Zoom Level:", val[0]/val[1],val);
18293 } break;
18294 case 'SheetExt': {
18295 /* empty */
18296 } break;
18297 case 'SheetExtOptional': {
18298 /* empty */
18299 } break;
18300
18301 /* VBA */
18302 case 'ObNoMacros': {
18303 /* empty */
18304 } break;
18305 case 'ObProj': {
18306 /* empty */
18307 } break;
18308 case 'CodeName': {
18309 /*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
18310 if(!cur_sheet) Workbook.WBProps.CodeName = val || "ThisWorkbook";
18311 else wsprops.CodeName = val || wsprops.name;
18312 } break;
18313 case 'GUIDTypeLib': {
18314 /* empty */
18315 } break;
18316
18317 case 'WOpt': break; // TODO: WTF?
18318 case 'PhoneticInfo': break;
18319
18320 case 'OleObjectSize': break;
18321
18322 /* Differential Formatting */
18323 case 'DXF': case 'DXFN': case 'DXFN12': case 'DXFN12List': case 'DXFN12NoCB': break;
18324
18325 /* Data Validation */
18326 case 'Dv': case 'DVal': break;
18327
18328 /* Data Series */
18329 case 'BRAI': case 'Series': case 'SeriesText': break;
18330
18331 /* Data Connection */
18332 case 'DConn': break;
18333 case 'DbOrParamQry': break;
18334 case 'DBQueryExt': break;
18335
18336 case 'OleDbConn': break;
18337 case 'ExtString': break;
18338
18339 /* Formatting */
18340 case 'IFmtRecord': break;
18341 case 'CondFmt': case 'CF': case 'CF12': case 'CFEx': break;
18342
18343 /* Explicitly Ignored */
18344 case 'Excel9File': break;
18345 case 'Units': break;
18346 case 'InterfaceHdr': case 'Mms': case 'InterfaceEnd': case 'DSF': break;
18347 case 'BuiltInFnGroupCount': /* 2.4.30 0x0E or 0x10 but excel 2011 generates 0x11? */ break;
18348 /* View Stuff */
18349 case 'Window1': case 'HideObj': case 'GridSet': case 'Guts':
18350 case 'UserBView': case 'UserSViewBegin': case 'UserSViewEnd': break;
18351 case 'Pane': break;
18352 default: switch(R.n) { /* nested */
18353 /* Chart */
18354 case 'Dat':
18355 case 'Begin': case 'End':
18356 case 'StartBlock': case 'EndBlock':
18357 case 'Frame': case 'Area':
18358 case 'Axis': case 'AxisLine': case 'Tick': break;
18359 case 'AxesUsed':
18360 case 'CrtLayout12': case 'CrtLayout12A': case 'CrtLink': case 'CrtLine': case 'CrtMlFrt': case 'CrtMlFrtContinue': break;
18361 case 'LineFormat': case 'AreaFormat':
18362 case 'Chart': case 'Chart3d': case 'Chart3DBarShape': case 'ChartFormat': case 'ChartFrtInfo': break;
18363 case 'PlotArea': case 'PlotGrowth': break;
18364 case 'SeriesList': case 'SerParent': case 'SerAuxTrend': break;
18365 case 'DataFormat': case 'SerToCrt': case 'FontX': break;
18366 case 'CatSerRange': case 'AxcExt': case 'SerFmt': break;
18367 case 'ShtProps': break;
18368 case 'DefaultText': case 'Text': case 'CatLab': break;
18369 case 'DataLabExtContents': break;
18370 case 'Legend': case 'LegendException': break;
18371 case 'Pie': case 'Scatter': break;
18372 case 'PieFormat': case 'MarkerFormat': break;
18373 case 'StartObject': case 'EndObject': break;
18374 case 'AlRuns': case 'ObjectLink': break;
18375 case 'SIIndex': break;
18376 case 'AttachedLabel': case 'YMult': break;
18377
18378 /* Chart Group */
18379 case 'Line': case 'Bar': break;
18380 case 'Surf': break;
18381
18382 /* Axis Group */
18383 case 'AxisParent': break;
18384 case 'Pos': break;
18385 case 'ValueRange': break;
18386
18387 /* Pivot Chart */
18388 case 'SXViewEx9': break; // TODO
18389 case 'SXViewLink': break;
18390 case 'PivotChartBits': break;
18391 case 'SBaseRef': break;
18392 case 'TextPropsStream': break;
18393
18394 /* Chart Misc */
18395 case 'LnExt': break;
18396 case 'MkrExt': break;
18397 case 'CrtCoopt': break;
18398
18399 /* Query Table */
18400 case 'Qsi': case 'Qsif': case 'Qsir': case 'QsiSXTag': break;
18401 case 'TxtQry': break;
18402
18403 /* Filter */
18404 case 'FilterMode': break;
18405 case 'AutoFilter': case 'AutoFilterInfo': break;
18406 case 'AutoFilter12': break;
18407 case 'DropDownObjIds': break;
18408 case 'Sort': break;
18409 case 'SortData': break;
18410
18411 /* Drawing */
18412 case 'ShapePropsStream': break;
18413 case 'MsoDrawing': case 'MsoDrawingGroup': case 'MsoDrawingSelection': break;
18414 /* Pub Stuff */
18415 case 'WebPub': case 'AutoWebPub': break;
18416
18417 /* Print Stuff */
18418 case 'HeaderFooter': case 'HFPicture': case 'PLV':
18419 case 'HorizontalPageBreaks': case 'VerticalPageBreaks': break;
18420 /* Behavioral */
18421 case 'Backup': case 'CompressPictures': case 'Compat12': break;
18422
18423 /* Should not Happen */
18424 case 'Continue': case 'ContinueFrt12': break;
18425
18426 /* Future Records */
18427 case 'FrtFontList': case 'FrtWrapper': break;
18428
18429 default: switch(R.n) { /* nested */
18430 /* BIFF5 records */
18431 case 'TabIdConf': case 'Radar': case 'RadarArea': case 'DropBar': case 'Intl': case 'CoordList': case 'SerAuxErrBar': break;
18432
18433 /* BIFF2-4 records */
18434 case 'BIFF2FONTCLR': case 'BIFF2FMTCNT': case 'BIFF2FONTXTRA': break;
18435 case 'BIFF2XF': case 'BIFF3XF': case 'BIFF4XF': break;
18436 case 'BIFF2XFINDEX': break;
18437 case 'BIFF4FMTCNT': case 'BIFF2ROW': case 'BIFF2WINDOW2': break;
18438
18439 /* Miscellaneous */
18440 case 'SCENARIO': case 'DConBin': case 'PicF': case 'DataLabExt':
18441 case 'Lel': case 'BopPop': case 'BopPopCustom': case 'RealTimeData':
18442 case 'Name': break;
18443 case 'LHNGraph': case 'FnGroupName': case 'AddMenu': case 'LPr': break;
18444 case 'ListObj': case 'ListField': break;
18445 case 'RRSort': break;
18446 case 'BigName': break;
18447 case 'ToolbarHdr': case 'ToolbarEnd': break;
18448 case 'DDEObjName': break;
18449 case 'FRTArchId$': break;
18450 default: if(options.WTF) throw 'Unrecognized Record ' + R.n;
18451 }}}}
18452 } else blob.l += length;
18453 }
18454 wb.SheetNames=keys(Directory).sort(function(a,b) { return Number(a) - Number(b); }).map(function(x){return Directory[x].name;});
18455 if(!options.bookSheets) wb.Sheets=Sheets;
18456 if(!wb.SheetNames.length && Preamble["!ref"]) {
18457 wb.SheetNames.push("Sheet1");
18458 if(wb.Sheets) wb.Sheets["Sheet1"] = Preamble;
18459 } else wb.Preamble=Preamble;
18460 if(wb.Sheets) FilterDatabases.forEach(function(r,i) { wb.Sheets[wb.SheetNames[i]]['!autofilter'] = r; });
18461 wb.Strings = sst;
18462 wb.SSF = SSF.get_table();
18463 if(opts.enc) wb.Encryption = opts.enc;
18464 if(themes) wb.Themes = themes;
18465 wb.Metadata = {};
18466 if(country !== undefined) wb.Metadata.Country = country;
18467 if(supbooks.names.length > 0) Workbook.Names = supbooks.names;
18468 wb.Workbook = Workbook;
18469 return wb;
18470}
18471
18472/* TODO: split props*/
18473var PSCLSID = {
18474 SI: "e0859ff2f94f6810ab9108002b27b3d9",
18475 DSI: "02d5cdd59c2e1b10939708002b2cf9ae",
18476 UDI: "05d5cdd59c2e1b10939708002b2cf9ae"
18477};
18478function parse_xls_props(cfb/*:CFBContainer*/, props, o) {
18479 /* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
18480 var DSI = CFB.find(cfb, '!DocumentSummaryInformation');
18481 if(DSI && DSI.size > 0) try {
18482 var DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI, PSCLSID.DSI);
18483 for(var d in DocSummary) props[d] = DocSummary[d];
18484 } catch(e) {if(o.WTF) throw e;/* empty */}
18485
18486 /* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
18487 var SI = CFB.find(cfb, '!SummaryInformation');
18488 if(SI && SI.size > 0) try {
18489 var Summary = parse_PropertySetStream(SI, SummaryPIDSI, PSCLSID.SI);
18490 for(var s in Summary) if(props[s] == null) props[s] = Summary[s];
18491 } catch(e) {if(o.WTF) throw e;/* empty */}
18492
18493 if(props.HeadingPairs && props.TitlesOfParts) {
18494 load_props_pairs(props.HeadingPairs, props.TitlesOfParts, props, o);
18495 delete props.HeadingPairs; delete props.TitlesOfParts;
18496 }
18497}
18498function write_xls_props(wb/*:Workbook*/, cfb/*:CFBContainer*/) {
18499 var DSEntries = [], SEntries = [], CEntries = [];
18500 var i = 0, Keys;
18501 if(wb.Props) {
18502 Keys = keys(wb.Props);
18503 // $FlowIgnore
18504 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]]]);
18505 }
18506 if(wb.Custprops) {
18507 Keys = keys(wb.Custprops);
18508 // $FlowIgnore
18509 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]]]);
18510 }
18511 var CEntries2 = [];
18512 for(i = 0; i < CEntries.length; ++i) {
18513 if(XLSPSSkip.indexOf(CEntries[i][0]) > -1) continue;
18514 if(CEntries[i][1] == null) continue;
18515 CEntries2.push(CEntries[i]);
18516 }
18517 if(SEntries.length) CFB.utils.cfb_add(cfb, "/\u0005SummaryInformation", write_PropertySetStream(SEntries, PSCLSID.SI, SummaryRE, SummaryPIDSI));
18518 if(DSEntries.length || CEntries2.length) CFB.utils.cfb_add(cfb, "/\u0005DocumentSummaryInformation", write_PropertySetStream(DSEntries, PSCLSID.DSI, DocSummaryRE, DocSummaryPIDDSI, CEntries2.length ? CEntries2 : null, PSCLSID.UDI));
18519}
18520
18521function parse_xlscfb(cfb/*:any*/, options/*:?ParseOpts*/)/*:Workbook*/ {
18522if(!options) options = {};
18523fix_read_opts(options);
18524reset_cp();
18525if(options.codepage) set_ansi(options.codepage);
18526var CompObj/*:?CFBEntry*/, WB/*:?any*/;
18527if(cfb.FullPaths) {
18528 if(CFB.find(cfb, '/encryption')) throw new Error("File is password-protected");
18529 CompObj = CFB.find(cfb, '!CompObj');
18530 WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
18531} else {
18532 switch(options.type) {
18533 case 'base64': cfb = s2a(Base64.decode(cfb)); break;
18534 case 'binary': cfb = s2a(cfb); break;
18535 case 'buffer': break;
18536 case 'array': if(!Array.isArray(cfb)) cfb = Array.prototype.slice.call(cfb); break;
18537 }
18538 prep_blob(cfb, 0);
18539 WB = ({content: cfb}/*:any*/);
18540}
18541var /*::CompObjP, */WorkbookP/*:: :Workbook = XLSX.utils.book_new(); */;
18542
18543var _data/*:?any*/;
18544if(CompObj) /*::CompObjP = */parse_compobj(CompObj);
18545if(options.bookProps && !options.bookSheets) WorkbookP = ({}/*:any*/);
18546else/*:: if(cfb instanceof CFBContainer) */ {
18547 var T = has_buf ? 'buffer' : 'array';
18548 if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options);
18549 /* Quattro Pro 7-8 */
18550 else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
18551 /* Quattro Pro 9 */
18552 else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
18553 else throw new Error("Cannot find Workbook stream");
18554 if(options.bookVBA && cfb.FullPaths && CFB.find(cfb, '/_VBA_PROJECT_CUR/VBA/dir')) WorkbookP.vbaraw = make_vba_xls(cfb);
18555}
18556
18557var props = {};
18558if(cfb.FullPaths) parse_xls_props(/*::((*/cfb/*:: :any):CFBContainer)*/, props, options);
18559
18560WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
18561if(options.bookFiles) WorkbookP.cfb = cfb;
18562/*WorkbookP.CompObjP = CompObjP; // TODO: storage? */
18563return WorkbookP;
18564}
18565
18566
18567function write_xlscfb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:CFBContainer*/ {
18568 var o = opts || {};
18569 var cfb = CFB.utils.cfb_new({root:"R"});
18570 var wbpath = "/Workbook";
18571 switch(o.bookType || "xls") {
18572 case "xls": o.bookType = "biff8";
18573 /* falls through */
18574 case "xla": if(!o.bookType) o.bookType = "xla";
18575 /* falls through */
18576 case "biff8": wbpath = "/Workbook"; o.biff = 8; break;
18577 case "biff5": wbpath = "/Book"; o.biff = 5; break;
18578 default: throw new Error("invalid type " + o.bookType + " for XLS CFB");
18579 }
18580 CFB.utils.cfb_add(cfb, wbpath, write_biff_buf(wb, o));
18581 if(o.biff == 8 && (wb.Props || wb.Custprops)) write_xls_props(wb, cfb);
18582 // TODO: SI, DSI, CO
18583 if(o.biff == 8 && wb.vbaraw) fill_vba_xls(cfb, CFB.read(wb.vbaraw, {type: typeof wb.vbaraw == "string" ? "binary" : "buffer"}));
18584 return cfb;
18585}
18586/* [MS-XLSB] 2.3 Record Enumeration */
18587var XLSBRecordEnum = {
18588 /*::[*/0x0000/*::]*/: { n:"BrtRowHdr", f:parse_BrtRowHdr },
18589 /*::[*/0x0001/*::]*/: { n:"BrtCellBlank", f:parse_BrtCellBlank },
18590 /*::[*/0x0002/*::]*/: { n:"BrtCellRk", f:parse_BrtCellRk },
18591 /*::[*/0x0003/*::]*/: { n:"BrtCellError", f:parse_BrtCellError },
18592 /*::[*/0x0004/*::]*/: { n:"BrtCellBool", f:parse_BrtCellBool },
18593 /*::[*/0x0005/*::]*/: { n:"BrtCellReal", f:parse_BrtCellReal },
18594 /*::[*/0x0006/*::]*/: { n:"BrtCellSt", f:parse_BrtCellSt },
18595 /*::[*/0x0007/*::]*/: { n:"BrtCellIsst", f:parse_BrtCellIsst },
18596 /*::[*/0x0008/*::]*/: { n:"BrtFmlaString", f:parse_BrtFmlaString },
18597 /*::[*/0x0009/*::]*/: { n:"BrtFmlaNum", f:parse_BrtFmlaNum },
18598 /*::[*/0x000A/*::]*/: { n:"BrtFmlaBool", f:parse_BrtFmlaBool },
18599 /*::[*/0x000B/*::]*/: { n:"BrtFmlaError", f:parse_BrtFmlaError },
18600 /*::[*/0x000C/*::]*/: { n:"BrtShortBlank", f:parse_BrtShortBlank },
18601 /*::[*/0x000D/*::]*/: { n:"BrtShortRk", f:parse_BrtShortRk },
18602 /*::[*/0x000E/*::]*/: { n:"BrtShortError", f:parse_BrtShortError },
18603 /*::[*/0x000F/*::]*/: { n:"BrtShortBool", f:parse_BrtShortBool },
18604 /*::[*/0x0010/*::]*/: { n:"BrtShortReal", f:parse_BrtShortReal },
18605 /*::[*/0x0011/*::]*/: { n:"BrtShortSt", f:parse_BrtShortSt },
18606 /*::[*/0x0012/*::]*/: { n:"BrtShortIsst", f:parse_BrtShortIsst },
18607 /*::[*/0x0013/*::]*/: { n:"BrtSSTItem", f:parse_RichStr },
18608 /*::[*/0x0014/*::]*/: { n:"BrtPCDIMissing" },
18609 /*::[*/0x0015/*::]*/: { n:"BrtPCDINumber" },
18610 /*::[*/0x0016/*::]*/: { n:"BrtPCDIBoolean" },
18611 /*::[*/0x0017/*::]*/: { n:"BrtPCDIError" },
18612 /*::[*/0x0018/*::]*/: { n:"BrtPCDIString" },
18613 /*::[*/0x0019/*::]*/: { n:"BrtPCDIDatetime" },
18614 /*::[*/0x001A/*::]*/: { n:"BrtPCDIIndex" },
18615 /*::[*/0x001B/*::]*/: { n:"BrtPCDIAMissing" },
18616 /*::[*/0x001C/*::]*/: { n:"BrtPCDIANumber" },
18617 /*::[*/0x001D/*::]*/: { n:"BrtPCDIABoolean" },
18618 /*::[*/0x001E/*::]*/: { n:"BrtPCDIAError" },
18619 /*::[*/0x001F/*::]*/: { n:"BrtPCDIAString" },
18620 /*::[*/0x0020/*::]*/: { n:"BrtPCDIADatetime" },
18621 /*::[*/0x0021/*::]*/: { n:"BrtPCRRecord" },
18622 /*::[*/0x0022/*::]*/: { n:"BrtPCRRecordDt" },
18623 /*::[*/0x0023/*::]*/: { n:"BrtFRTBegin" },
18624 /*::[*/0x0024/*::]*/: { n:"BrtFRTEnd" },
18625 /*::[*/0x0025/*::]*/: { n:"BrtACBegin" },
18626 /*::[*/0x0026/*::]*/: { n:"BrtACEnd" },
18627 /*::[*/0x0027/*::]*/: { n:"BrtName", f:parse_BrtName },
18628 /*::[*/0x0028/*::]*/: { n:"BrtIndexRowBlock" },
18629 /*::[*/0x002A/*::]*/: { n:"BrtIndexBlock" },
18630 /*::[*/0x002B/*::]*/: { n:"BrtFont", f:parse_BrtFont },
18631 /*::[*/0x002C/*::]*/: { n:"BrtFmt", f:parse_BrtFmt },
18632 /*::[*/0x002D/*::]*/: { n:"BrtFill", f:parse_BrtFill },
18633 /*::[*/0x002E/*::]*/: { n:"BrtBorder", f:parse_BrtBorder },
18634 /*::[*/0x002F/*::]*/: { n:"BrtXF", f:parse_BrtXF },
18635 /*::[*/0x0030/*::]*/: { n:"BrtStyle" },
18636 /*::[*/0x0031/*::]*/: { n:"BrtCellMeta" },
18637 /*::[*/0x0032/*::]*/: { n:"BrtValueMeta" },
18638 /*::[*/0x0033/*::]*/: { n:"BrtMdb" },
18639 /*::[*/0x0034/*::]*/: { n:"BrtBeginFmd" },
18640 /*::[*/0x0035/*::]*/: { n:"BrtEndFmd" },
18641 /*::[*/0x0036/*::]*/: { n:"BrtBeginMdx" },
18642 /*::[*/0x0037/*::]*/: { n:"BrtEndMdx" },
18643 /*::[*/0x0038/*::]*/: { n:"BrtBeginMdxTuple" },
18644 /*::[*/0x0039/*::]*/: { n:"BrtEndMdxTuple" },
18645 /*::[*/0x003A/*::]*/: { n:"BrtMdxMbrIstr" },
18646 /*::[*/0x003B/*::]*/: { n:"BrtStr" },
18647 /*::[*/0x003C/*::]*/: { n:"BrtColInfo", f:parse_ColInfo },
18648 /*::[*/0x003E/*::]*/: { n:"BrtCellRString" },
18649 /*::[*/0x003F/*::]*/: { n:"BrtCalcChainItem$", f:parse_BrtCalcChainItem$ },
18650 /*::[*/0x0040/*::]*/: { n:"BrtDVal", f:parse_BrtDVal },
18651 /*::[*/0x0041/*::]*/: { n:"BrtSxvcellNum" },
18652 /*::[*/0x0042/*::]*/: { n:"BrtSxvcellStr" },
18653 /*::[*/0x0043/*::]*/: { n:"BrtSxvcellBool" },
18654 /*::[*/0x0044/*::]*/: { n:"BrtSxvcellErr" },
18655 /*::[*/0x0045/*::]*/: { n:"BrtSxvcellDate" },
18656 /*::[*/0x0046/*::]*/: { n:"BrtSxvcellNil" },
18657 /*::[*/0x0080/*::]*/: { n:"BrtFileVersion" },
18658 /*::[*/0x0081/*::]*/: { n:"BrtBeginSheet" },
18659 /*::[*/0x0082/*::]*/: { n:"BrtEndSheet" },
18660 /*::[*/0x0083/*::]*/: { n:"BrtBeginBook", f:parsenoop, p:0 },
18661 /*::[*/0x0084/*::]*/: { n:"BrtEndBook" },
18662 /*::[*/0x0085/*::]*/: { n:"BrtBeginWsViews" },
18663 /*::[*/0x0086/*::]*/: { n:"BrtEndWsViews" },
18664 /*::[*/0x0087/*::]*/: { n:"BrtBeginBookViews" },
18665 /*::[*/0x0088/*::]*/: { n:"BrtEndBookViews" },
18666 /*::[*/0x0089/*::]*/: { n:"BrtBeginWsView", f:parse_BrtBeginWsView },
18667 /*::[*/0x008A/*::]*/: { n:"BrtEndWsView" },
18668 /*::[*/0x008B/*::]*/: { n:"BrtBeginCsViews" },
18669 /*::[*/0x008C/*::]*/: { n:"BrtEndCsViews" },
18670 /*::[*/0x008D/*::]*/: { n:"BrtBeginCsView" },
18671 /*::[*/0x008E/*::]*/: { n:"BrtEndCsView" },
18672 /*::[*/0x008F/*::]*/: { n:"BrtBeginBundleShs" },
18673 /*::[*/0x0090/*::]*/: { n:"BrtEndBundleShs" },
18674 /*::[*/0x0091/*::]*/: { n:"BrtBeginSheetData" },
18675 /*::[*/0x0092/*::]*/: { n:"BrtEndSheetData" },
18676 /*::[*/0x0093/*::]*/: { n:"BrtWsProp", f:parse_BrtWsProp },
18677 /*::[*/0x0094/*::]*/: { n:"BrtWsDim", f:parse_BrtWsDim, p:16 },
18678 /*::[*/0x0097/*::]*/: { n:"BrtPane", f:parse_BrtPane },
18679 /*::[*/0x0098/*::]*/: { n:"BrtSel" },
18680 /*::[*/0x0099/*::]*/: { n:"BrtWbProp", f:parse_BrtWbProp },
18681 /*::[*/0x009A/*::]*/: { n:"BrtWbFactoid" },
18682 /*::[*/0x009B/*::]*/: { n:"BrtFileRecover" },
18683 /*::[*/0x009C/*::]*/: { n:"BrtBundleSh", f:parse_BrtBundleSh },
18684 /*::[*/0x009D/*::]*/: { n:"BrtCalcProp" },
18685 /*::[*/0x009E/*::]*/: { n:"BrtBookView" },
18686 /*::[*/0x009F/*::]*/: { n:"BrtBeginSst", f:parse_BrtBeginSst },
18687 /*::[*/0x00A0/*::]*/: { n:"BrtEndSst" },
18688 /*::[*/0x00A1/*::]*/: { n:"BrtBeginAFilter", f:parse_UncheckedRfX },
18689 /*::[*/0x00A2/*::]*/: { n:"BrtEndAFilter" },
18690 /*::[*/0x00A3/*::]*/: { n:"BrtBeginFilterColumn" },
18691 /*::[*/0x00A4/*::]*/: { n:"BrtEndFilterColumn" },
18692 /*::[*/0x00A5/*::]*/: { n:"BrtBeginFilters" },
18693 /*::[*/0x00A6/*::]*/: { n:"BrtEndFilters" },
18694 /*::[*/0x00A7/*::]*/: { n:"BrtFilter" },
18695 /*::[*/0x00A8/*::]*/: { n:"BrtColorFilter" },
18696 /*::[*/0x00A9/*::]*/: { n:"BrtIconFilter" },
18697 /*::[*/0x00AA/*::]*/: { n:"BrtTop10Filter" },
18698 /*::[*/0x00AB/*::]*/: { n:"BrtDynamicFilter" },
18699 /*::[*/0x00AC/*::]*/: { n:"BrtBeginCustomFilters" },
18700 /*::[*/0x00AD/*::]*/: { n:"BrtEndCustomFilters" },
18701 /*::[*/0x00AE/*::]*/: { n:"BrtCustomFilter" },
18702 /*::[*/0x00AF/*::]*/: { n:"BrtAFilterDateGroupItem" },
18703 /*::[*/0x00B0/*::]*/: { n:"BrtMergeCell", f:parse_BrtMergeCell },
18704 /*::[*/0x00B1/*::]*/: { n:"BrtBeginMergeCells" },
18705 /*::[*/0x00B2/*::]*/: { n:"BrtEndMergeCells" },
18706 /*::[*/0x00B3/*::]*/: { n:"BrtBeginPivotCacheDef" },
18707 /*::[*/0x00B4/*::]*/: { n:"BrtEndPivotCacheDef" },
18708 /*::[*/0x00B5/*::]*/: { n:"BrtBeginPCDFields" },
18709 /*::[*/0x00B6/*::]*/: { n:"BrtEndPCDFields" },
18710 /*::[*/0x00B7/*::]*/: { n:"BrtBeginPCDField" },
18711 /*::[*/0x00B8/*::]*/: { n:"BrtEndPCDField" },
18712 /*::[*/0x00B9/*::]*/: { n:"BrtBeginPCDSource" },
18713 /*::[*/0x00BA/*::]*/: { n:"BrtEndPCDSource" },
18714 /*::[*/0x00BB/*::]*/: { n:"BrtBeginPCDSRange" },
18715 /*::[*/0x00BC/*::]*/: { n:"BrtEndPCDSRange" },
18716 /*::[*/0x00BD/*::]*/: { n:"BrtBeginPCDFAtbl" },
18717 /*::[*/0x00BE/*::]*/: { n:"BrtEndPCDFAtbl" },
18718 /*::[*/0x00BF/*::]*/: { n:"BrtBeginPCDIRun" },
18719 /*::[*/0x00C0/*::]*/: { n:"BrtEndPCDIRun" },
18720 /*::[*/0x00C1/*::]*/: { n:"BrtBeginPivotCacheRecords" },
18721 /*::[*/0x00C2/*::]*/: { n:"BrtEndPivotCacheRecords" },
18722 /*::[*/0x00C3/*::]*/: { n:"BrtBeginPCDHierarchies" },
18723 /*::[*/0x00C4/*::]*/: { n:"BrtEndPCDHierarchies" },
18724 /*::[*/0x00C5/*::]*/: { n:"BrtBeginPCDHierarchy" },
18725 /*::[*/0x00C6/*::]*/: { n:"BrtEndPCDHierarchy" },
18726 /*::[*/0x00C7/*::]*/: { n:"BrtBeginPCDHFieldsUsage" },
18727 /*::[*/0x00C8/*::]*/: { n:"BrtEndPCDHFieldsUsage" },
18728 /*::[*/0x00C9/*::]*/: { n:"BrtBeginExtConnection" },
18729 /*::[*/0x00CA/*::]*/: { n:"BrtEndExtConnection" },
18730 /*::[*/0x00CB/*::]*/: { n:"BrtBeginECDbProps" },
18731 /*::[*/0x00CC/*::]*/: { n:"BrtEndECDbProps" },
18732 /*::[*/0x00CD/*::]*/: { n:"BrtBeginECOlapProps" },
18733 /*::[*/0x00CE/*::]*/: { n:"BrtEndECOlapProps" },
18734 /*::[*/0x00CF/*::]*/: { n:"BrtBeginPCDSConsol" },
18735 /*::[*/0x00D0/*::]*/: { n:"BrtEndPCDSConsol" },
18736 /*::[*/0x00D1/*::]*/: { n:"BrtBeginPCDSCPages" },
18737 /*::[*/0x00D2/*::]*/: { n:"BrtEndPCDSCPages" },
18738 /*::[*/0x00D3/*::]*/: { n:"BrtBeginPCDSCPage" },
18739 /*::[*/0x00D4/*::]*/: { n:"BrtEndPCDSCPage" },
18740 /*::[*/0x00D5/*::]*/: { n:"BrtBeginPCDSCPItem" },
18741 /*::[*/0x00D6/*::]*/: { n:"BrtEndPCDSCPItem" },
18742 /*::[*/0x00D7/*::]*/: { n:"BrtBeginPCDSCSets" },
18743 /*::[*/0x00D8/*::]*/: { n:"BrtEndPCDSCSets" },
18744 /*::[*/0x00D9/*::]*/: { n:"BrtBeginPCDSCSet" },
18745 /*::[*/0x00DA/*::]*/: { n:"BrtEndPCDSCSet" },
18746 /*::[*/0x00DB/*::]*/: { n:"BrtBeginPCDFGroup" },
18747 /*::[*/0x00DC/*::]*/: { n:"BrtEndPCDFGroup" },
18748 /*::[*/0x00DD/*::]*/: { n:"BrtBeginPCDFGItems" },
18749 /*::[*/0x00DE/*::]*/: { n:"BrtEndPCDFGItems" },
18750 /*::[*/0x00DF/*::]*/: { n:"BrtBeginPCDFGRange" },
18751 /*::[*/0x00E0/*::]*/: { n:"BrtEndPCDFGRange" },
18752 /*::[*/0x00E1/*::]*/: { n:"BrtBeginPCDFGDiscrete" },
18753 /*::[*/0x00E2/*::]*/: { n:"BrtEndPCDFGDiscrete" },
18754 /*::[*/0x00E3/*::]*/: { n:"BrtBeginPCDSDTupleCache" },
18755 /*::[*/0x00E4/*::]*/: { n:"BrtEndPCDSDTupleCache" },
18756 /*::[*/0x00E5/*::]*/: { n:"BrtBeginPCDSDTCEntries" },
18757 /*::[*/0x00E6/*::]*/: { n:"BrtEndPCDSDTCEntries" },
18758 /*::[*/0x00E7/*::]*/: { n:"BrtBeginPCDSDTCEMembers" },
18759 /*::[*/0x00E8/*::]*/: { n:"BrtEndPCDSDTCEMembers" },
18760 /*::[*/0x00E9/*::]*/: { n:"BrtBeginPCDSDTCEMember" },
18761 /*::[*/0x00EA/*::]*/: { n:"BrtEndPCDSDTCEMember" },
18762 /*::[*/0x00EB/*::]*/: { n:"BrtBeginPCDSDTCQueries" },
18763 /*::[*/0x00EC/*::]*/: { n:"BrtEndPCDSDTCQueries" },
18764 /*::[*/0x00ED/*::]*/: { n:"BrtBeginPCDSDTCQuery" },
18765 /*::[*/0x00EE/*::]*/: { n:"BrtEndPCDSDTCQuery" },
18766 /*::[*/0x00EF/*::]*/: { n:"BrtBeginPCDSDTCSets" },
18767 /*::[*/0x00F0/*::]*/: { n:"BrtEndPCDSDTCSets" },
18768 /*::[*/0x00F1/*::]*/: { n:"BrtBeginPCDSDTCSet" },
18769 /*::[*/0x00F2/*::]*/: { n:"BrtEndPCDSDTCSet" },
18770 /*::[*/0x00F3/*::]*/: { n:"BrtBeginPCDCalcItems" },
18771 /*::[*/0x00F4/*::]*/: { n:"BrtEndPCDCalcItems" },
18772 /*::[*/0x00F5/*::]*/: { n:"BrtBeginPCDCalcItem" },
18773 /*::[*/0x00F6/*::]*/: { n:"BrtEndPCDCalcItem" },
18774 /*::[*/0x00F7/*::]*/: { n:"BrtBeginPRule" },
18775 /*::[*/0x00F8/*::]*/: { n:"BrtEndPRule" },
18776 /*::[*/0x00F9/*::]*/: { n:"BrtBeginPRFilters" },
18777 /*::[*/0x00FA/*::]*/: { n:"BrtEndPRFilters" },
18778 /*::[*/0x00FB/*::]*/: { n:"BrtBeginPRFilter" },
18779 /*::[*/0x00FC/*::]*/: { n:"BrtEndPRFilter" },
18780 /*::[*/0x00FD/*::]*/: { n:"BrtBeginPNames" },
18781 /*::[*/0x00FE/*::]*/: { n:"BrtEndPNames" },
18782 /*::[*/0x00FF/*::]*/: { n:"BrtBeginPName" },
18783 /*::[*/0x0100/*::]*/: { n:"BrtEndPName" },
18784 /*::[*/0x0101/*::]*/: { n:"BrtBeginPNPairs" },
18785 /*::[*/0x0102/*::]*/: { n:"BrtEndPNPairs" },
18786 /*::[*/0x0103/*::]*/: { n:"BrtBeginPNPair" },
18787 /*::[*/0x0104/*::]*/: { n:"BrtEndPNPair" },
18788 /*::[*/0x0105/*::]*/: { n:"BrtBeginECWebProps" },
18789 /*::[*/0x0106/*::]*/: { n:"BrtEndECWebProps" },
18790 /*::[*/0x0107/*::]*/: { n:"BrtBeginEcWpTables" },
18791 /*::[*/0x0108/*::]*/: { n:"BrtEndECWPTables" },
18792 /*::[*/0x0109/*::]*/: { n:"BrtBeginECParams" },
18793 /*::[*/0x010A/*::]*/: { n:"BrtEndECParams" },
18794 /*::[*/0x010B/*::]*/: { n:"BrtBeginECParam" },
18795 /*::[*/0x010C/*::]*/: { n:"BrtEndECParam" },
18796 /*::[*/0x010D/*::]*/: { n:"BrtBeginPCDKPIs" },
18797 /*::[*/0x010E/*::]*/: { n:"BrtEndPCDKPIs" },
18798 /*::[*/0x010F/*::]*/: { n:"BrtBeginPCDKPI" },
18799 /*::[*/0x0110/*::]*/: { n:"BrtEndPCDKPI" },
18800 /*::[*/0x0111/*::]*/: { n:"BrtBeginDims" },
18801 /*::[*/0x0112/*::]*/: { n:"BrtEndDims" },
18802 /*::[*/0x0113/*::]*/: { n:"BrtBeginDim" },
18803 /*::[*/0x0114/*::]*/: { n:"BrtEndDim" },
18804 /*::[*/0x0115/*::]*/: { n:"BrtIndexPartEnd" },
18805 /*::[*/0x0116/*::]*/: { n:"BrtBeginStyleSheet" },
18806 /*::[*/0x0117/*::]*/: { n:"BrtEndStyleSheet" },
18807 /*::[*/0x0118/*::]*/: { n:"BrtBeginSXView" },
18808 /*::[*/0x0119/*::]*/: { n:"BrtEndSXVI" },
18809 /*::[*/0x011A/*::]*/: { n:"BrtBeginSXVI" },
18810 /*::[*/0x011B/*::]*/: { n:"BrtBeginSXVIs" },
18811 /*::[*/0x011C/*::]*/: { n:"BrtEndSXVIs" },
18812 /*::[*/0x011D/*::]*/: { n:"BrtBeginSXVD" },
18813 /*::[*/0x011E/*::]*/: { n:"BrtEndSXVD" },
18814 /*::[*/0x011F/*::]*/: { n:"BrtBeginSXVDs" },
18815 /*::[*/0x0120/*::]*/: { n:"BrtEndSXVDs" },
18816 /*::[*/0x0121/*::]*/: { n:"BrtBeginSXPI" },
18817 /*::[*/0x0122/*::]*/: { n:"BrtEndSXPI" },
18818 /*::[*/0x0123/*::]*/: { n:"BrtBeginSXPIs" },
18819 /*::[*/0x0124/*::]*/: { n:"BrtEndSXPIs" },
18820 /*::[*/0x0125/*::]*/: { n:"BrtBeginSXDI" },
18821 /*::[*/0x0126/*::]*/: { n:"BrtEndSXDI" },
18822 /*::[*/0x0127/*::]*/: { n:"BrtBeginSXDIs" },
18823 /*::[*/0x0128/*::]*/: { n:"BrtEndSXDIs" },
18824 /*::[*/0x0129/*::]*/: { n:"BrtBeginSXLI" },
18825 /*::[*/0x012A/*::]*/: { n:"BrtEndSXLI" },
18826 /*::[*/0x012B/*::]*/: { n:"BrtBeginSXLIRws" },
18827 /*::[*/0x012C/*::]*/: { n:"BrtEndSXLIRws" },
18828 /*::[*/0x012D/*::]*/: { n:"BrtBeginSXLICols" },
18829 /*::[*/0x012E/*::]*/: { n:"BrtEndSXLICols" },
18830 /*::[*/0x012F/*::]*/: { n:"BrtBeginSXFormat" },
18831 /*::[*/0x0130/*::]*/: { n:"BrtEndSXFormat" },
18832 /*::[*/0x0131/*::]*/: { n:"BrtBeginSXFormats" },
18833 /*::[*/0x0132/*::]*/: { n:"BrtEndSxFormats" },
18834 /*::[*/0x0133/*::]*/: { n:"BrtBeginSxSelect" },
18835 /*::[*/0x0134/*::]*/: { n:"BrtEndSxSelect" },
18836 /*::[*/0x0135/*::]*/: { n:"BrtBeginISXVDRws" },
18837 /*::[*/0x0136/*::]*/: { n:"BrtEndISXVDRws" },
18838 /*::[*/0x0137/*::]*/: { n:"BrtBeginISXVDCols" },
18839 /*::[*/0x0138/*::]*/: { n:"BrtEndISXVDCols" },
18840 /*::[*/0x0139/*::]*/: { n:"BrtEndSXLocation" },
18841 /*::[*/0x013A/*::]*/: { n:"BrtBeginSXLocation" },
18842 /*::[*/0x013B/*::]*/: { n:"BrtEndSXView" },
18843 /*::[*/0x013C/*::]*/: { n:"BrtBeginSXTHs" },
18844 /*::[*/0x013D/*::]*/: { n:"BrtEndSXTHs" },
18845 /*::[*/0x013E/*::]*/: { n:"BrtBeginSXTH" },
18846 /*::[*/0x013F/*::]*/: { n:"BrtEndSXTH" },
18847 /*::[*/0x0140/*::]*/: { n:"BrtBeginISXTHRws" },
18848 /*::[*/0x0141/*::]*/: { n:"BrtEndISXTHRws" },
18849 /*::[*/0x0142/*::]*/: { n:"BrtBeginISXTHCols" },
18850 /*::[*/0x0143/*::]*/: { n:"BrtEndISXTHCols" },
18851 /*::[*/0x0144/*::]*/: { n:"BrtBeginSXTDMPS" },
18852 /*::[*/0x0145/*::]*/: { n:"BrtEndSXTDMPs" },
18853 /*::[*/0x0146/*::]*/: { n:"BrtBeginSXTDMP" },
18854 /*::[*/0x0147/*::]*/: { n:"BrtEndSXTDMP" },
18855 /*::[*/0x0148/*::]*/: { n:"BrtBeginSXTHItems" },
18856 /*::[*/0x0149/*::]*/: { n:"BrtEndSXTHItems" },
18857 /*::[*/0x014A/*::]*/: { n:"BrtBeginSXTHItem" },
18858 /*::[*/0x014B/*::]*/: { n:"BrtEndSXTHItem" },
18859 /*::[*/0x014C/*::]*/: { n:"BrtBeginMetadata" },
18860 /*::[*/0x014D/*::]*/: { n:"BrtEndMetadata" },
18861 /*::[*/0x014E/*::]*/: { n:"BrtBeginEsmdtinfo" },
18862 /*::[*/0x014F/*::]*/: { n:"BrtMdtinfo" },
18863 /*::[*/0x0150/*::]*/: { n:"BrtEndEsmdtinfo" },
18864 /*::[*/0x0151/*::]*/: { n:"BrtBeginEsmdb" },
18865 /*::[*/0x0152/*::]*/: { n:"BrtEndEsmdb" },
18866 /*::[*/0x0153/*::]*/: { n:"BrtBeginEsfmd" },
18867 /*::[*/0x0154/*::]*/: { n:"BrtEndEsfmd" },
18868 /*::[*/0x0155/*::]*/: { n:"BrtBeginSingleCells" },
18869 /*::[*/0x0156/*::]*/: { n:"BrtEndSingleCells" },
18870 /*::[*/0x0157/*::]*/: { n:"BrtBeginList" },
18871 /*::[*/0x0158/*::]*/: { n:"BrtEndList" },
18872 /*::[*/0x0159/*::]*/: { n:"BrtBeginListCols" },
18873 /*::[*/0x015A/*::]*/: { n:"BrtEndListCols" },
18874 /*::[*/0x015B/*::]*/: { n:"BrtBeginListCol" },
18875 /*::[*/0x015C/*::]*/: { n:"BrtEndListCol" },
18876 /*::[*/0x015D/*::]*/: { n:"BrtBeginListXmlCPr" },
18877 /*::[*/0x015E/*::]*/: { n:"BrtEndListXmlCPr" },
18878 /*::[*/0x015F/*::]*/: { n:"BrtListCCFmla" },
18879 /*::[*/0x0160/*::]*/: { n:"BrtListTrFmla" },
18880 /*::[*/0x0161/*::]*/: { n:"BrtBeginExternals" },
18881 /*::[*/0x0162/*::]*/: { n:"BrtEndExternals" },
18882 /*::[*/0x0163/*::]*/: { n:"BrtSupBookSrc", f:parse_RelID},
18883 /*::[*/0x0165/*::]*/: { n:"BrtSupSelf" },
18884 /*::[*/0x0166/*::]*/: { n:"BrtSupSame" },
18885 /*::[*/0x0167/*::]*/: { n:"BrtSupTabs" },
18886 /*::[*/0x0168/*::]*/: { n:"BrtBeginSupBook" },
18887 /*::[*/0x0169/*::]*/: { n:"BrtPlaceholderName" },
18888 /*::[*/0x016A/*::]*/: { n:"BrtExternSheet", f:parse_ExternSheet },
18889 /*::[*/0x016B/*::]*/: { n:"BrtExternTableStart" },
18890 /*::[*/0x016C/*::]*/: { n:"BrtExternTableEnd" },
18891 /*::[*/0x016E/*::]*/: { n:"BrtExternRowHdr" },
18892 /*::[*/0x016F/*::]*/: { n:"BrtExternCellBlank" },
18893 /*::[*/0x0170/*::]*/: { n:"BrtExternCellReal" },
18894 /*::[*/0x0171/*::]*/: { n:"BrtExternCellBool" },
18895 /*::[*/0x0172/*::]*/: { n:"BrtExternCellError" },
18896 /*::[*/0x0173/*::]*/: { n:"BrtExternCellString" },
18897 /*::[*/0x0174/*::]*/: { n:"BrtBeginEsmdx" },
18898 /*::[*/0x0175/*::]*/: { n:"BrtEndEsmdx" },
18899 /*::[*/0x0176/*::]*/: { n:"BrtBeginMdxSet" },
18900 /*::[*/0x0177/*::]*/: { n:"BrtEndMdxSet" },
18901 /*::[*/0x0178/*::]*/: { n:"BrtBeginMdxMbrProp" },
18902 /*::[*/0x0179/*::]*/: { n:"BrtEndMdxMbrProp" },
18903 /*::[*/0x017A/*::]*/: { n:"BrtBeginMdxKPI" },
18904 /*::[*/0x017B/*::]*/: { n:"BrtEndMdxKPI" },
18905 /*::[*/0x017C/*::]*/: { n:"BrtBeginEsstr" },
18906 /*::[*/0x017D/*::]*/: { n:"BrtEndEsstr" },
18907 /*::[*/0x017E/*::]*/: { n:"BrtBeginPRFItem" },
18908 /*::[*/0x017F/*::]*/: { n:"BrtEndPRFItem" },
18909 /*::[*/0x0180/*::]*/: { n:"BrtBeginPivotCacheIDs" },
18910 /*::[*/0x0181/*::]*/: { n:"BrtEndPivotCacheIDs" },
18911 /*::[*/0x0182/*::]*/: { n:"BrtBeginPivotCacheID" },
18912 /*::[*/0x0183/*::]*/: { n:"BrtEndPivotCacheID" },
18913 /*::[*/0x0184/*::]*/: { n:"BrtBeginISXVIs" },
18914 /*::[*/0x0185/*::]*/: { n:"BrtEndISXVIs" },
18915 /*::[*/0x0186/*::]*/: { n:"BrtBeginColInfos" },
18916 /*::[*/0x0187/*::]*/: { n:"BrtEndColInfos" },
18917 /*::[*/0x0188/*::]*/: { n:"BrtBeginRwBrk" },
18918 /*::[*/0x0189/*::]*/: { n:"BrtEndRwBrk" },
18919 /*::[*/0x018A/*::]*/: { n:"BrtBeginColBrk" },
18920 /*::[*/0x018B/*::]*/: { n:"BrtEndColBrk" },
18921 /*::[*/0x018C/*::]*/: { n:"BrtBrk" },
18922 /*::[*/0x018D/*::]*/: { n:"BrtUserBookView" },
18923 /*::[*/0x018E/*::]*/: { n:"BrtInfo" },
18924 /*::[*/0x018F/*::]*/: { n:"BrtCUsr" },
18925 /*::[*/0x0190/*::]*/: { n:"BrtUsr" },
18926 /*::[*/0x0191/*::]*/: { n:"BrtBeginUsers" },
18927 /*::[*/0x0193/*::]*/: { n:"BrtEOF" },
18928 /*::[*/0x0194/*::]*/: { n:"BrtUCR" },
18929 /*::[*/0x0195/*::]*/: { n:"BrtRRInsDel" },
18930 /*::[*/0x0196/*::]*/: { n:"BrtRREndInsDel" },
18931 /*::[*/0x0197/*::]*/: { n:"BrtRRMove" },
18932 /*::[*/0x0198/*::]*/: { n:"BrtRREndMove" },
18933 /*::[*/0x0199/*::]*/: { n:"BrtRRChgCell" },
18934 /*::[*/0x019A/*::]*/: { n:"BrtRREndChgCell" },
18935 /*::[*/0x019B/*::]*/: { n:"BrtRRHeader" },
18936 /*::[*/0x019C/*::]*/: { n:"BrtRRUserView" },
18937 /*::[*/0x019D/*::]*/: { n:"BrtRRRenSheet" },
18938 /*::[*/0x019E/*::]*/: { n:"BrtRRInsertSh" },
18939 /*::[*/0x019F/*::]*/: { n:"BrtRRDefName" },
18940 /*::[*/0x01A0/*::]*/: { n:"BrtRRNote" },
18941 /*::[*/0x01A1/*::]*/: { n:"BrtRRConflict" },
18942 /*::[*/0x01A2/*::]*/: { n:"BrtRRTQSIF" },
18943 /*::[*/0x01A3/*::]*/: { n:"BrtRRFormat" },
18944 /*::[*/0x01A4/*::]*/: { n:"BrtRREndFormat" },
18945 /*::[*/0x01A5/*::]*/: { n:"BrtRRAutoFmt" },
18946 /*::[*/0x01A6/*::]*/: { n:"BrtBeginUserShViews" },
18947 /*::[*/0x01A7/*::]*/: { n:"BrtBeginUserShView" },
18948 /*::[*/0x01A8/*::]*/: { n:"BrtEndUserShView" },
18949 /*::[*/0x01A9/*::]*/: { n:"BrtEndUserShViews" },
18950 /*::[*/0x01AA/*::]*/: { n:"BrtArrFmla", f:parse_BrtArrFmla },
18951 /*::[*/0x01AB/*::]*/: { n:"BrtShrFmla", f:parse_BrtShrFmla },
18952 /*::[*/0x01AC/*::]*/: { n:"BrtTable" },
18953 /*::[*/0x01AD/*::]*/: { n:"BrtBeginExtConnections" },
18954 /*::[*/0x01AE/*::]*/: { n:"BrtEndExtConnections" },
18955 /*::[*/0x01AF/*::]*/: { n:"BrtBeginPCDCalcMems" },
18956 /*::[*/0x01B0/*::]*/: { n:"BrtEndPCDCalcMems" },
18957 /*::[*/0x01B1/*::]*/: { n:"BrtBeginPCDCalcMem" },
18958 /*::[*/0x01B2/*::]*/: { n:"BrtEndPCDCalcMem" },
18959 /*::[*/0x01B3/*::]*/: { n:"BrtBeginPCDHGLevels" },
18960 /*::[*/0x01B4/*::]*/: { n:"BrtEndPCDHGLevels" },
18961 /*::[*/0x01B5/*::]*/: { n:"BrtBeginPCDHGLevel" },
18962 /*::[*/0x01B6/*::]*/: { n:"BrtEndPCDHGLevel" },
18963 /*::[*/0x01B7/*::]*/: { n:"BrtBeginPCDHGLGroups" },
18964 /*::[*/0x01B8/*::]*/: { n:"BrtEndPCDHGLGroups" },
18965 /*::[*/0x01B9/*::]*/: { n:"BrtBeginPCDHGLGroup" },
18966 /*::[*/0x01BA/*::]*/: { n:"BrtEndPCDHGLGroup" },
18967 /*::[*/0x01BB/*::]*/: { n:"BrtBeginPCDHGLGMembers" },
18968 /*::[*/0x01BC/*::]*/: { n:"BrtEndPCDHGLGMembers" },
18969 /*::[*/0x01BD/*::]*/: { n:"BrtBeginPCDHGLGMember" },
18970 /*::[*/0x01BE/*::]*/: { n:"BrtEndPCDHGLGMember" },
18971 /*::[*/0x01BF/*::]*/: { n:"BrtBeginQSI" },
18972 /*::[*/0x01C0/*::]*/: { n:"BrtEndQSI" },
18973 /*::[*/0x01C1/*::]*/: { n:"BrtBeginQSIR" },
18974 /*::[*/0x01C2/*::]*/: { n:"BrtEndQSIR" },
18975 /*::[*/0x01C3/*::]*/: { n:"BrtBeginDeletedNames" },
18976 /*::[*/0x01C4/*::]*/: { n:"BrtEndDeletedNames" },
18977 /*::[*/0x01C5/*::]*/: { n:"BrtBeginDeletedName" },
18978 /*::[*/0x01C6/*::]*/: { n:"BrtEndDeletedName" },
18979 /*::[*/0x01C7/*::]*/: { n:"BrtBeginQSIFs" },
18980 /*::[*/0x01C8/*::]*/: { n:"BrtEndQSIFs" },
18981 /*::[*/0x01C9/*::]*/: { n:"BrtBeginQSIF" },
18982 /*::[*/0x01CA/*::]*/: { n:"BrtEndQSIF" },
18983 /*::[*/0x01CB/*::]*/: { n:"BrtBeginAutoSortScope" },
18984 /*::[*/0x01CC/*::]*/: { n:"BrtEndAutoSortScope" },
18985 /*::[*/0x01CD/*::]*/: { n:"BrtBeginConditionalFormatting" },
18986 /*::[*/0x01CE/*::]*/: { n:"BrtEndConditionalFormatting" },
18987 /*::[*/0x01CF/*::]*/: { n:"BrtBeginCFRule" },
18988 /*::[*/0x01D0/*::]*/: { n:"BrtEndCFRule" },
18989 /*::[*/0x01D1/*::]*/: { n:"BrtBeginIconSet" },
18990 /*::[*/0x01D2/*::]*/: { n:"BrtEndIconSet" },
18991 /*::[*/0x01D3/*::]*/: { n:"BrtBeginDatabar" },
18992 /*::[*/0x01D4/*::]*/: { n:"BrtEndDatabar" },
18993 /*::[*/0x01D5/*::]*/: { n:"BrtBeginColorScale" },
18994 /*::[*/0x01D6/*::]*/: { n:"BrtEndColorScale" },
18995 /*::[*/0x01D7/*::]*/: { n:"BrtCFVO" },
18996 /*::[*/0x01D8/*::]*/: { n:"BrtExternValueMeta" },
18997 /*::[*/0x01D9/*::]*/: { n:"BrtBeginColorPalette" },
18998 /*::[*/0x01DA/*::]*/: { n:"BrtEndColorPalette" },
18999 /*::[*/0x01DB/*::]*/: { n:"BrtIndexedColor" },
19000 /*::[*/0x01DC/*::]*/: { n:"BrtMargins", f:parse_BrtMargins },
19001 /*::[*/0x01DD/*::]*/: { n:"BrtPrintOptions" },
19002 /*::[*/0x01DE/*::]*/: { n:"BrtPageSetup" },
19003 /*::[*/0x01DF/*::]*/: { n:"BrtBeginHeaderFooter" },
19004 /*::[*/0x01E0/*::]*/: { n:"BrtEndHeaderFooter" },
19005 /*::[*/0x01E1/*::]*/: { n:"BrtBeginSXCrtFormat" },
19006 /*::[*/0x01E2/*::]*/: { n:"BrtEndSXCrtFormat" },
19007 /*::[*/0x01E3/*::]*/: { n:"BrtBeginSXCrtFormats" },
19008 /*::[*/0x01E4/*::]*/: { n:"BrtEndSXCrtFormats" },
19009 /*::[*/0x01E5/*::]*/: { n:"BrtWsFmtInfo", f:parse_BrtWsFmtInfo },
19010 /*::[*/0x01E6/*::]*/: { n:"BrtBeginMgs" },
19011 /*::[*/0x01E7/*::]*/: { n:"BrtEndMGs" },
19012 /*::[*/0x01E8/*::]*/: { n:"BrtBeginMGMaps" },
19013 /*::[*/0x01E9/*::]*/: { n:"BrtEndMGMaps" },
19014 /*::[*/0x01EA/*::]*/: { n:"BrtBeginMG" },
19015 /*::[*/0x01EB/*::]*/: { n:"BrtEndMG" },
19016 /*::[*/0x01EC/*::]*/: { n:"BrtBeginMap" },
19017 /*::[*/0x01ED/*::]*/: { n:"BrtEndMap" },
19018 /*::[*/0x01EE/*::]*/: { n:"BrtHLink", f:parse_BrtHLink },
19019 /*::[*/0x01EF/*::]*/: { n:"BrtBeginDCon" },
19020 /*::[*/0x01F0/*::]*/: { n:"BrtEndDCon" },
19021 /*::[*/0x01F1/*::]*/: { n:"BrtBeginDRefs" },
19022 /*::[*/0x01F2/*::]*/: { n:"BrtEndDRefs" },
19023 /*::[*/0x01F3/*::]*/: { n:"BrtDRef" },
19024 /*::[*/0x01F4/*::]*/: { n:"BrtBeginScenMan" },
19025 /*::[*/0x01F5/*::]*/: { n:"BrtEndScenMan" },
19026 /*::[*/0x01F6/*::]*/: { n:"BrtBeginSct" },
19027 /*::[*/0x01F7/*::]*/: { n:"BrtEndSct" },
19028 /*::[*/0x01F8/*::]*/: { n:"BrtSlc" },
19029 /*::[*/0x01F9/*::]*/: { n:"BrtBeginDXFs" },
19030 /*::[*/0x01FA/*::]*/: { n:"BrtEndDXFs" },
19031 /*::[*/0x01FB/*::]*/: { n:"BrtDXF" },
19032 /*::[*/0x01FC/*::]*/: { n:"BrtBeginTableStyles" },
19033 /*::[*/0x01FD/*::]*/: { n:"BrtEndTableStyles" },
19034 /*::[*/0x01FE/*::]*/: { n:"BrtBeginTableStyle" },
19035 /*::[*/0x01FF/*::]*/: { n:"BrtEndTableStyle" },
19036 /*::[*/0x0200/*::]*/: { n:"BrtTableStyleElement" },
19037 /*::[*/0x0201/*::]*/: { n:"BrtTableStyleClient" },
19038 /*::[*/0x0202/*::]*/: { n:"BrtBeginVolDeps" },
19039 /*::[*/0x0203/*::]*/: { n:"BrtEndVolDeps" },
19040 /*::[*/0x0204/*::]*/: { n:"BrtBeginVolType" },
19041 /*::[*/0x0205/*::]*/: { n:"BrtEndVolType" },
19042 /*::[*/0x0206/*::]*/: { n:"BrtBeginVolMain" },
19043 /*::[*/0x0207/*::]*/: { n:"BrtEndVolMain" },
19044 /*::[*/0x0208/*::]*/: { n:"BrtBeginVolTopic" },
19045 /*::[*/0x0209/*::]*/: { n:"BrtEndVolTopic" },
19046 /*::[*/0x020A/*::]*/: { n:"BrtVolSubtopic" },
19047 /*::[*/0x020B/*::]*/: { n:"BrtVolRef" },
19048 /*::[*/0x020C/*::]*/: { n:"BrtVolNum" },
19049 /*::[*/0x020D/*::]*/: { n:"BrtVolErr" },
19050 /*::[*/0x020E/*::]*/: { n:"BrtVolStr" },
19051 /*::[*/0x020F/*::]*/: { n:"BrtVolBool" },
19052 /*::[*/0x0210/*::]*/: { n:"BrtBeginCalcChain$" },
19053 /*::[*/0x0211/*::]*/: { n:"BrtEndCalcChain$" },
19054 /*::[*/0x0212/*::]*/: { n:"BrtBeginSortState" },
19055 /*::[*/0x0213/*::]*/: { n:"BrtEndSortState" },
19056 /*::[*/0x0214/*::]*/: { n:"BrtBeginSortCond" },
19057 /*::[*/0x0215/*::]*/: { n:"BrtEndSortCond" },
19058 /*::[*/0x0216/*::]*/: { n:"BrtBookProtection" },
19059 /*::[*/0x0217/*::]*/: { n:"BrtSheetProtection" },
19060 /*::[*/0x0218/*::]*/: { n:"BrtRangeProtection" },
19061 /*::[*/0x0219/*::]*/: { n:"BrtPhoneticInfo" },
19062 /*::[*/0x021A/*::]*/: { n:"BrtBeginECTxtWiz" },
19063 /*::[*/0x021B/*::]*/: { n:"BrtEndECTxtWiz" },
19064 /*::[*/0x021C/*::]*/: { n:"BrtBeginECTWFldInfoLst" },
19065 /*::[*/0x021D/*::]*/: { n:"BrtEndECTWFldInfoLst" },
19066 /*::[*/0x021E/*::]*/: { n:"BrtBeginECTwFldInfo" },
19067 /*::[*/0x0224/*::]*/: { n:"BrtFileSharing" },
19068 /*::[*/0x0225/*::]*/: { n:"BrtOleSize" },
19069 /*::[*/0x0226/*::]*/: { n:"BrtDrawing", f:parse_RelID },
19070 /*::[*/0x0227/*::]*/: { n:"BrtLegacyDrawing" },
19071 /*::[*/0x0228/*::]*/: { n:"BrtLegacyDrawingHF" },
19072 /*::[*/0x0229/*::]*/: { n:"BrtWebOpt" },
19073 /*::[*/0x022A/*::]*/: { n:"BrtBeginWebPubItems" },
19074 /*::[*/0x022B/*::]*/: { n:"BrtEndWebPubItems" },
19075 /*::[*/0x022C/*::]*/: { n:"BrtBeginWebPubItem" },
19076 /*::[*/0x022D/*::]*/: { n:"BrtEndWebPubItem" },
19077 /*::[*/0x022E/*::]*/: { n:"BrtBeginSXCondFmt" },
19078 /*::[*/0x022F/*::]*/: { n:"BrtEndSXCondFmt" },
19079 /*::[*/0x0230/*::]*/: { n:"BrtBeginSXCondFmts" },
19080 /*::[*/0x0231/*::]*/: { n:"BrtEndSXCondFmts" },
19081 /*::[*/0x0232/*::]*/: { n:"BrtBkHim" },
19082 /*::[*/0x0234/*::]*/: { n:"BrtColor" },
19083 /*::[*/0x0235/*::]*/: { n:"BrtBeginIndexedColors" },
19084 /*::[*/0x0236/*::]*/: { n:"BrtEndIndexedColors" },
19085 /*::[*/0x0239/*::]*/: { n:"BrtBeginMRUColors" },
19086 /*::[*/0x023A/*::]*/: { n:"BrtEndMRUColors" },
19087 /*::[*/0x023C/*::]*/: { n:"BrtMRUColor" },
19088 /*::[*/0x023D/*::]*/: { n:"BrtBeginDVals" },
19089 /*::[*/0x023E/*::]*/: { n:"BrtEndDVals" },
19090 /*::[*/0x0241/*::]*/: { n:"BrtSupNameStart" },
19091 /*::[*/0x0242/*::]*/: { n:"BrtSupNameValueStart" },
19092 /*::[*/0x0243/*::]*/: { n:"BrtSupNameValueEnd" },
19093 /*::[*/0x0244/*::]*/: { n:"BrtSupNameNum" },
19094 /*::[*/0x0245/*::]*/: { n:"BrtSupNameErr" },
19095 /*::[*/0x0246/*::]*/: { n:"BrtSupNameSt" },
19096 /*::[*/0x0247/*::]*/: { n:"BrtSupNameNil" },
19097 /*::[*/0x0248/*::]*/: { n:"BrtSupNameBool" },
19098 /*::[*/0x0249/*::]*/: { n:"BrtSupNameFmla" },
19099 /*::[*/0x024A/*::]*/: { n:"BrtSupNameBits" },
19100 /*::[*/0x024B/*::]*/: { n:"BrtSupNameEnd" },
19101 /*::[*/0x024C/*::]*/: { n:"BrtEndSupBook" },
19102 /*::[*/0x024D/*::]*/: { n:"BrtCellSmartTagProperty" },
19103 /*::[*/0x024E/*::]*/: { n:"BrtBeginCellSmartTag" },
19104 /*::[*/0x024F/*::]*/: { n:"BrtEndCellSmartTag" },
19105 /*::[*/0x0250/*::]*/: { n:"BrtBeginCellSmartTags" },
19106 /*::[*/0x0251/*::]*/: { n:"BrtEndCellSmartTags" },
19107 /*::[*/0x0252/*::]*/: { n:"BrtBeginSmartTags" },
19108 /*::[*/0x0253/*::]*/: { n:"BrtEndSmartTags" },
19109 /*::[*/0x0254/*::]*/: { n:"BrtSmartTagType" },
19110 /*::[*/0x0255/*::]*/: { n:"BrtBeginSmartTagTypes" },
19111 /*::[*/0x0256/*::]*/: { n:"BrtEndSmartTagTypes" },
19112 /*::[*/0x0257/*::]*/: { n:"BrtBeginSXFilters" },
19113 /*::[*/0x0258/*::]*/: { n:"BrtEndSXFilters" },
19114 /*::[*/0x0259/*::]*/: { n:"BrtBeginSXFILTER" },
19115 /*::[*/0x025A/*::]*/: { n:"BrtEndSXFilter" },
19116 /*::[*/0x025B/*::]*/: { n:"BrtBeginFills" },
19117 /*::[*/0x025C/*::]*/: { n:"BrtEndFills" },
19118 /*::[*/0x025D/*::]*/: { n:"BrtBeginCellWatches" },
19119 /*::[*/0x025E/*::]*/: { n:"BrtEndCellWatches" },
19120 /*::[*/0x025F/*::]*/: { n:"BrtCellWatch" },
19121 /*::[*/0x0260/*::]*/: { n:"BrtBeginCRErrs" },
19122 /*::[*/0x0261/*::]*/: { n:"BrtEndCRErrs" },
19123 /*::[*/0x0262/*::]*/: { n:"BrtCrashRecErr" },
19124 /*::[*/0x0263/*::]*/: { n:"BrtBeginFonts" },
19125 /*::[*/0x0264/*::]*/: { n:"BrtEndFonts" },
19126 /*::[*/0x0265/*::]*/: { n:"BrtBeginBorders" },
19127 /*::[*/0x0266/*::]*/: { n:"BrtEndBorders" },
19128 /*::[*/0x0267/*::]*/: { n:"BrtBeginFmts" },
19129 /*::[*/0x0268/*::]*/: { n:"BrtEndFmts" },
19130 /*::[*/0x0269/*::]*/: { n:"BrtBeginCellXFs" },
19131 /*::[*/0x026A/*::]*/: { n:"BrtEndCellXFs" },
19132 /*::[*/0x026B/*::]*/: { n:"BrtBeginStyles" },
19133 /*::[*/0x026C/*::]*/: { n:"BrtEndStyles" },
19134 /*::[*/0x0271/*::]*/: { n:"BrtBigName" },
19135 /*::[*/0x0272/*::]*/: { n:"BrtBeginCellStyleXFs" },
19136 /*::[*/0x0273/*::]*/: { n:"BrtEndCellStyleXFs" },
19137 /*::[*/0x0274/*::]*/: { n:"BrtBeginComments" },
19138 /*::[*/0x0275/*::]*/: { n:"BrtEndComments" },
19139 /*::[*/0x0276/*::]*/: { n:"BrtBeginCommentAuthors" },
19140 /*::[*/0x0277/*::]*/: { n:"BrtEndCommentAuthors" },
19141 /*::[*/0x0278/*::]*/: { n:"BrtCommentAuthor", f:parse_BrtCommentAuthor },
19142 /*::[*/0x0279/*::]*/: { n:"BrtBeginCommentList" },
19143 /*::[*/0x027A/*::]*/: { n:"BrtEndCommentList" },
19144 /*::[*/0x027B/*::]*/: { n:"BrtBeginComment", f:parse_BrtBeginComment},
19145 /*::[*/0x027C/*::]*/: { n:"BrtEndComment" },
19146 /*::[*/0x027D/*::]*/: { n:"BrtCommentText", f:parse_BrtCommentText },
19147 /*::[*/0x027E/*::]*/: { n:"BrtBeginOleObjects" },
19148 /*::[*/0x027F/*::]*/: { n:"BrtOleObject" },
19149 /*::[*/0x0280/*::]*/: { n:"BrtEndOleObjects" },
19150 /*::[*/0x0281/*::]*/: { n:"BrtBeginSxrules" },
19151 /*::[*/0x0282/*::]*/: { n:"BrtEndSxRules" },
19152 /*::[*/0x0283/*::]*/: { n:"BrtBeginActiveXControls" },
19153 /*::[*/0x0284/*::]*/: { n:"BrtActiveX" },
19154 /*::[*/0x0285/*::]*/: { n:"BrtEndActiveXControls" },
19155 /*::[*/0x0286/*::]*/: { n:"BrtBeginPCDSDTCEMembersSortBy" },
19156 /*::[*/0x0288/*::]*/: { n:"BrtBeginCellIgnoreECs" },
19157 /*::[*/0x0289/*::]*/: { n:"BrtCellIgnoreEC" },
19158 /*::[*/0x028A/*::]*/: { n:"BrtEndCellIgnoreECs" },
19159 /*::[*/0x028B/*::]*/: { n:"BrtCsProp", f:parse_BrtCsProp },
19160 /*::[*/0x028C/*::]*/: { n:"BrtCsPageSetup" },
19161 /*::[*/0x028D/*::]*/: { n:"BrtBeginUserCsViews" },
19162 /*::[*/0x028E/*::]*/: { n:"BrtEndUserCsViews" },
19163 /*::[*/0x028F/*::]*/: { n:"BrtBeginUserCsView" },
19164 /*::[*/0x0290/*::]*/: { n:"BrtEndUserCsView" },
19165 /*::[*/0x0291/*::]*/: { n:"BrtBeginPcdSFCIEntries" },
19166 /*::[*/0x0292/*::]*/: { n:"BrtEndPCDSFCIEntries" },
19167 /*::[*/0x0293/*::]*/: { n:"BrtPCDSFCIEntry" },
19168 /*::[*/0x0294/*::]*/: { n:"BrtBeginListParts" },
19169 /*::[*/0x0295/*::]*/: { n:"BrtListPart" },
19170 /*::[*/0x0296/*::]*/: { n:"BrtEndListParts" },
19171 /*::[*/0x0297/*::]*/: { n:"BrtSheetCalcProp" },
19172 /*::[*/0x0298/*::]*/: { n:"BrtBeginFnGroup" },
19173 /*::[*/0x0299/*::]*/: { n:"BrtFnGroup" },
19174 /*::[*/0x029A/*::]*/: { n:"BrtEndFnGroup" },
19175 /*::[*/0x029B/*::]*/: { n:"BrtSupAddin" },
19176 /*::[*/0x029C/*::]*/: { n:"BrtSXTDMPOrder" },
19177 /*::[*/0x029D/*::]*/: { n:"BrtCsProtection" },
19178 /*::[*/0x029F/*::]*/: { n:"BrtBeginWsSortMap" },
19179 /*::[*/0x02A0/*::]*/: { n:"BrtEndWsSortMap" },
19180 /*::[*/0x02A1/*::]*/: { n:"BrtBeginRRSort" },
19181 /*::[*/0x02A2/*::]*/: { n:"BrtEndRRSort" },
19182 /*::[*/0x02A3/*::]*/: { n:"BrtRRSortItem" },
19183 /*::[*/0x02A4/*::]*/: { n:"BrtFileSharingIso" },
19184 /*::[*/0x02A5/*::]*/: { n:"BrtBookProtectionIso" },
19185 /*::[*/0x02A6/*::]*/: { n:"BrtSheetProtectionIso" },
19186 /*::[*/0x02A7/*::]*/: { n:"BrtCsProtectionIso" },
19187 /*::[*/0x02A8/*::]*/: { n:"BrtRangeProtectionIso" },
19188 /*::[*/0x02A9/*::]*/: { n:"BrtDValList" },
19189 /*::[*/0x0400/*::]*/: { n:"BrtRwDescent" },
19190 /*::[*/0x0401/*::]*/: { n:"BrtKnownFonts" },
19191 /*::[*/0x0402/*::]*/: { n:"BrtBeginSXTupleSet" },
19192 /*::[*/0x0403/*::]*/: { n:"BrtEndSXTupleSet" },
19193 /*::[*/0x0404/*::]*/: { n:"BrtBeginSXTupleSetHeader" },
19194 /*::[*/0x0405/*::]*/: { n:"BrtEndSXTupleSetHeader" },
19195 /*::[*/0x0406/*::]*/: { n:"BrtSXTupleSetHeaderItem" },
19196 /*::[*/0x0407/*::]*/: { n:"BrtBeginSXTupleSetData" },
19197 /*::[*/0x0408/*::]*/: { n:"BrtEndSXTupleSetData" },
19198 /*::[*/0x0409/*::]*/: { n:"BrtBeginSXTupleSetRow" },
19199 /*::[*/0x040A/*::]*/: { n:"BrtEndSXTupleSetRow" },
19200 /*::[*/0x040B/*::]*/: { n:"BrtSXTupleSetRowItem" },
19201 /*::[*/0x040C/*::]*/: { n:"BrtNameExt" },
19202 /*::[*/0x040D/*::]*/: { n:"BrtPCDH14" },
19203 /*::[*/0x040E/*::]*/: { n:"BrtBeginPCDCalcMem14" },
19204 /*::[*/0x040F/*::]*/: { n:"BrtEndPCDCalcMem14" },
19205 /*::[*/0x0410/*::]*/: { n:"BrtSXTH14" },
19206 /*::[*/0x0411/*::]*/: { n:"BrtBeginSparklineGroup" },
19207 /*::[*/0x0412/*::]*/: { n:"BrtEndSparklineGroup" },
19208 /*::[*/0x0413/*::]*/: { n:"BrtSparkline" },
19209 /*::[*/0x0414/*::]*/: { n:"BrtSXDI14" },
19210 /*::[*/0x0415/*::]*/: { n:"BrtWsFmtInfoEx14" },
19211 /*::[*/0x0416/*::]*/: { n:"BrtBeginConditionalFormatting14" },
19212 /*::[*/0x0417/*::]*/: { n:"BrtEndConditionalFormatting14" },
19213 /*::[*/0x0418/*::]*/: { n:"BrtBeginCFRule14" },
19214 /*::[*/0x0419/*::]*/: { n:"BrtEndCFRule14" },
19215 /*::[*/0x041A/*::]*/: { n:"BrtCFVO14" },
19216 /*::[*/0x041B/*::]*/: { n:"BrtBeginDatabar14" },
19217 /*::[*/0x041C/*::]*/: { n:"BrtBeginIconSet14" },
19218 /*::[*/0x041D/*::]*/: { n:"BrtDVal14", f: parse_BrtDVal14 },
19219 /*::[*/0x041E/*::]*/: { n:"BrtBeginDVals14" },
19220 /*::[*/0x041F/*::]*/: { n:"BrtColor14" },
19221 /*::[*/0x0420/*::]*/: { n:"BrtBeginSparklines" },
19222 /*::[*/0x0421/*::]*/: { n:"BrtEndSparklines" },
19223 /*::[*/0x0422/*::]*/: { n:"BrtBeginSparklineGroups" },
19224 /*::[*/0x0423/*::]*/: { n:"BrtEndSparklineGroups" },
19225 /*::[*/0x0425/*::]*/: { n:"BrtSXVD14" },
19226 /*::[*/0x0426/*::]*/: { n:"BrtBeginSXView14" },
19227 /*::[*/0x0427/*::]*/: { n:"BrtEndSXView14" },
19228 /*::[*/0x0428/*::]*/: { n:"BrtBeginSXView16" },
19229 /*::[*/0x0429/*::]*/: { n:"BrtEndSXView16" },
19230 /*::[*/0x042A/*::]*/: { n:"BrtBeginPCD14" },
19231 /*::[*/0x042B/*::]*/: { n:"BrtEndPCD14" },
19232 /*::[*/0x042C/*::]*/: { n:"BrtBeginExtConn14" },
19233 /*::[*/0x042D/*::]*/: { n:"BrtEndExtConn14" },
19234 /*::[*/0x042E/*::]*/: { n:"BrtBeginSlicerCacheIDs" },
19235 /*::[*/0x042F/*::]*/: { n:"BrtEndSlicerCacheIDs" },
19236 /*::[*/0x0430/*::]*/: { n:"BrtBeginSlicerCacheID" },
19237 /*::[*/0x0431/*::]*/: { n:"BrtEndSlicerCacheID" },
19238 /*::[*/0x0433/*::]*/: { n:"BrtBeginSlicerCache" },
19239 /*::[*/0x0434/*::]*/: { n:"BrtEndSlicerCache" },
19240 /*::[*/0x0435/*::]*/: { n:"BrtBeginSlicerCacheDef" },
19241 /*::[*/0x0436/*::]*/: { n:"BrtEndSlicerCacheDef" },
19242 /*::[*/0x0437/*::]*/: { n:"BrtBeginSlicersEx" },
19243 /*::[*/0x0438/*::]*/: { n:"BrtEndSlicersEx" },
19244 /*::[*/0x0439/*::]*/: { n:"BrtBeginSlicerEx" },
19245 /*::[*/0x043A/*::]*/: { n:"BrtEndSlicerEx" },
19246 /*::[*/0x043B/*::]*/: { n:"BrtBeginSlicer" },
19247 /*::[*/0x043C/*::]*/: { n:"BrtEndSlicer" },
19248 /*::[*/0x043D/*::]*/: { n:"BrtSlicerCachePivotTables" },
19249 /*::[*/0x043E/*::]*/: { n:"BrtBeginSlicerCacheOlapImpl" },
19250 /*::[*/0x043F/*::]*/: { n:"BrtEndSlicerCacheOlapImpl" },
19251 /*::[*/0x0440/*::]*/: { n:"BrtBeginSlicerCacheLevelsData" },
19252 /*::[*/0x0441/*::]*/: { n:"BrtEndSlicerCacheLevelsData" },
19253 /*::[*/0x0442/*::]*/: { n:"BrtBeginSlicerCacheLevelData" },
19254 /*::[*/0x0443/*::]*/: { n:"BrtEndSlicerCacheLevelData" },
19255 /*::[*/0x0444/*::]*/: { n:"BrtBeginSlicerCacheSiRanges" },
19256 /*::[*/0x0445/*::]*/: { n:"BrtEndSlicerCacheSiRanges" },
19257 /*::[*/0x0446/*::]*/: { n:"BrtBeginSlicerCacheSiRange" },
19258 /*::[*/0x0447/*::]*/: { n:"BrtEndSlicerCacheSiRange" },
19259 /*::[*/0x0448/*::]*/: { n:"BrtSlicerCacheOlapItem" },
19260 /*::[*/0x0449/*::]*/: { n:"BrtBeginSlicerCacheSelections" },
19261 /*::[*/0x044A/*::]*/: { n:"BrtSlicerCacheSelection" },
19262 /*::[*/0x044B/*::]*/: { n:"BrtEndSlicerCacheSelections" },
19263 /*::[*/0x044C/*::]*/: { n:"BrtBeginSlicerCacheNative" },
19264 /*::[*/0x044D/*::]*/: { n:"BrtEndSlicerCacheNative" },
19265 /*::[*/0x044E/*::]*/: { n:"BrtSlicerCacheNativeItem" },
19266 /*::[*/0x044F/*::]*/: { n:"BrtRangeProtection14" },
19267 /*::[*/0x0450/*::]*/: { n:"BrtRangeProtectionIso14" },
19268 /*::[*/0x0451/*::]*/: { n:"BrtCellIgnoreEC14" },
19269 /*::[*/0x0457/*::]*/: { n:"BrtList14" },
19270 /*::[*/0x0458/*::]*/: { n:"BrtCFIcon" },
19271 /*::[*/0x0459/*::]*/: { n:"BrtBeginSlicerCachesPivotCacheIDs" },
19272 /*::[*/0x045A/*::]*/: { n:"BrtEndSlicerCachesPivotCacheIDs" },
19273 /*::[*/0x045B/*::]*/: { n:"BrtBeginSlicers" },
19274 /*::[*/0x045C/*::]*/: { n:"BrtEndSlicers" },
19275 /*::[*/0x045D/*::]*/: { n:"BrtWbProp14" },
19276 /*::[*/0x045E/*::]*/: { n:"BrtBeginSXEdit" },
19277 /*::[*/0x045F/*::]*/: { n:"BrtEndSXEdit" },
19278 /*::[*/0x0460/*::]*/: { n:"BrtBeginSXEdits" },
19279 /*::[*/0x0461/*::]*/: { n:"BrtEndSXEdits" },
19280 /*::[*/0x0462/*::]*/: { n:"BrtBeginSXChange" },
19281 /*::[*/0x0463/*::]*/: { n:"BrtEndSXChange" },
19282 /*::[*/0x0464/*::]*/: { n:"BrtBeginSXChanges" },
19283 /*::[*/0x0465/*::]*/: { n:"BrtEndSXChanges" },
19284 /*::[*/0x0466/*::]*/: { n:"BrtSXTupleItems" },
19285 /*::[*/0x0468/*::]*/: { n:"BrtBeginSlicerStyle" },
19286 /*::[*/0x0469/*::]*/: { n:"BrtEndSlicerStyle" },
19287 /*::[*/0x046A/*::]*/: { n:"BrtSlicerStyleElement" },
19288 /*::[*/0x046B/*::]*/: { n:"BrtBeginStyleSheetExt14" },
19289 /*::[*/0x046C/*::]*/: { n:"BrtEndStyleSheetExt14" },
19290 /*::[*/0x046D/*::]*/: { n:"BrtBeginSlicerCachesPivotCacheID" },
19291 /*::[*/0x046E/*::]*/: { n:"BrtEndSlicerCachesPivotCacheID" },
19292 /*::[*/0x046F/*::]*/: { n:"BrtBeginConditionalFormattings" },
19293 /*::[*/0x0470/*::]*/: { n:"BrtEndConditionalFormattings" },
19294 /*::[*/0x0471/*::]*/: { n:"BrtBeginPCDCalcMemExt" },
19295 /*::[*/0x0472/*::]*/: { n:"BrtEndPCDCalcMemExt" },
19296 /*::[*/0x0473/*::]*/: { n:"BrtBeginPCDCalcMemsExt" },
19297 /*::[*/0x0474/*::]*/: { n:"BrtEndPCDCalcMemsExt" },
19298 /*::[*/0x0475/*::]*/: { n:"BrtPCDField14" },
19299 /*::[*/0x0476/*::]*/: { n:"BrtBeginSlicerStyles" },
19300 /*::[*/0x0477/*::]*/: { n:"BrtEndSlicerStyles" },
19301 /*::[*/0x0478/*::]*/: { n:"BrtBeginSlicerStyleElements" },
19302 /*::[*/0x0479/*::]*/: { n:"BrtEndSlicerStyleElements" },
19303 /*::[*/0x047A/*::]*/: { n:"BrtCFRuleExt" },
19304 /*::[*/0x047B/*::]*/: { n:"BrtBeginSXCondFmt14" },
19305 /*::[*/0x047C/*::]*/: { n:"BrtEndSXCondFmt14" },
19306 /*::[*/0x047D/*::]*/: { n:"BrtBeginSXCondFmts14" },
19307 /*::[*/0x047E/*::]*/: { n:"BrtEndSXCondFmts14" },
19308 /*::[*/0x0480/*::]*/: { n:"BrtBeginSortCond14" },
19309 /*::[*/0x0481/*::]*/: { n:"BrtEndSortCond14" },
19310 /*::[*/0x0482/*::]*/: { n:"BrtEndDVals14" },
19311 /*::[*/0x0483/*::]*/: { n:"BrtEndIconSet14" },
19312 /*::[*/0x0484/*::]*/: { n:"BrtEndDatabar14" },
19313 /*::[*/0x0485/*::]*/: { n:"BrtBeginColorScale14" },
19314 /*::[*/0x0486/*::]*/: { n:"BrtEndColorScale14" },
19315 /*::[*/0x0487/*::]*/: { n:"BrtBeginSxrules14" },
19316 /*::[*/0x0488/*::]*/: { n:"BrtEndSxrules14" },
19317 /*::[*/0x0489/*::]*/: { n:"BrtBeginPRule14" },
19318 /*::[*/0x048A/*::]*/: { n:"BrtEndPRule14" },
19319 /*::[*/0x048B/*::]*/: { n:"BrtBeginPRFilters14" },
19320 /*::[*/0x048C/*::]*/: { n:"BrtEndPRFilters14" },
19321 /*::[*/0x048D/*::]*/: { n:"BrtBeginPRFilter14" },
19322 /*::[*/0x048E/*::]*/: { n:"BrtEndPRFilter14" },
19323 /*::[*/0x048F/*::]*/: { n:"BrtBeginPRFItem14" },
19324 /*::[*/0x0490/*::]*/: { n:"BrtEndPRFItem14" },
19325 /*::[*/0x0491/*::]*/: { n:"BrtBeginCellIgnoreECs14" },
19326 /*::[*/0x0492/*::]*/: { n:"BrtEndCellIgnoreECs14" },
19327 /*::[*/0x0493/*::]*/: { n:"BrtDxf14" },
19328 /*::[*/0x0494/*::]*/: { n:"BrtBeginDxF14s" },
19329 /*::[*/0x0495/*::]*/: { n:"BrtEndDxf14s" },
19330 /*::[*/0x0499/*::]*/: { n:"BrtFilter14" },
19331 /*::[*/0x049A/*::]*/: { n:"BrtBeginCustomFilters14" },
19332 /*::[*/0x049C/*::]*/: { n:"BrtCustomFilter14" },
19333 /*::[*/0x049D/*::]*/: { n:"BrtIconFilter14" },
19334 /*::[*/0x049E/*::]*/: { n:"BrtPivotCacheConnectionName" },
19335 /*::[*/0x0800/*::]*/: { n:"BrtBeginDecoupledPivotCacheIDs" },
19336 /*::[*/0x0801/*::]*/: { n:"BrtEndDecoupledPivotCacheIDs" },
19337 /*::[*/0x0802/*::]*/: { n:"BrtDecoupledPivotCacheID" },
19338 /*::[*/0x0803/*::]*/: { n:"BrtBeginPivotTableRefs" },
19339 /*::[*/0x0804/*::]*/: { n:"BrtEndPivotTableRefs" },
19340 /*::[*/0x0805/*::]*/: { n:"BrtPivotTableRef" },
19341 /*::[*/0x0806/*::]*/: { n:"BrtSlicerCacheBookPivotTables" },
19342 /*::[*/0x0807/*::]*/: { n:"BrtBeginSxvcells" },
19343 /*::[*/0x0808/*::]*/: { n:"BrtEndSxvcells" },
19344 /*::[*/0x0809/*::]*/: { n:"BrtBeginSxRow" },
19345 /*::[*/0x080A/*::]*/: { n:"BrtEndSxRow" },
19346 /*::[*/0x080C/*::]*/: { n:"BrtPcdCalcMem15" },
19347 /*::[*/0x0813/*::]*/: { n:"BrtQsi15" },
19348 /*::[*/0x0814/*::]*/: { n:"BrtBeginWebExtensions" },
19349 /*::[*/0x0815/*::]*/: { n:"BrtEndWebExtensions" },
19350 /*::[*/0x0816/*::]*/: { n:"BrtWebExtension" },
19351 /*::[*/0x0817/*::]*/: { n:"BrtAbsPath15" },
19352 /*::[*/0x0818/*::]*/: { n:"BrtBeginPivotTableUISettings" },
19353 /*::[*/0x0819/*::]*/: { n:"BrtEndPivotTableUISettings" },
19354 /*::[*/0x081B/*::]*/: { n:"BrtTableSlicerCacheIDs" },
19355 /*::[*/0x081C/*::]*/: { n:"BrtTableSlicerCacheID" },
19356 /*::[*/0x081D/*::]*/: { n:"BrtBeginTableSlicerCache" },
19357 /*::[*/0x081E/*::]*/: { n:"BrtEndTableSlicerCache" },
19358 /*::[*/0x081F/*::]*/: { n:"BrtSxFilter15" },
19359 /*::[*/0x0820/*::]*/: { n:"BrtBeginTimelineCachePivotCacheIDs" },
19360 /*::[*/0x0821/*::]*/: { n:"BrtEndTimelineCachePivotCacheIDs" },
19361 /*::[*/0x0822/*::]*/: { n:"BrtTimelineCachePivotCacheID" },
19362 /*::[*/0x0823/*::]*/: { n:"BrtBeginTimelineCacheIDs" },
19363 /*::[*/0x0824/*::]*/: { n:"BrtEndTimelineCacheIDs" },
19364 /*::[*/0x0825/*::]*/: { n:"BrtBeginTimelineCacheID" },
19365 /*::[*/0x0826/*::]*/: { n:"BrtEndTimelineCacheID" },
19366 /*::[*/0x0827/*::]*/: { n:"BrtBeginTimelinesEx" },
19367 /*::[*/0x0828/*::]*/: { n:"BrtEndTimelinesEx" },
19368 /*::[*/0x0829/*::]*/: { n:"BrtBeginTimelineEx" },
19369 /*::[*/0x082A/*::]*/: { n:"BrtEndTimelineEx" },
19370 /*::[*/0x082B/*::]*/: { n:"BrtWorkBookPr15" },
19371 /*::[*/0x082C/*::]*/: { n:"BrtPCDH15" },
19372 /*::[*/0x082D/*::]*/: { n:"BrtBeginTimelineStyle" },
19373 /*::[*/0x082E/*::]*/: { n:"BrtEndTimelineStyle" },
19374 /*::[*/0x082F/*::]*/: { n:"BrtTimelineStyleElement" },
19375 /*::[*/0x0830/*::]*/: { n:"BrtBeginTimelineStylesheetExt15" },
19376 /*::[*/0x0831/*::]*/: { n:"BrtEndTimelineStylesheetExt15" },
19377 /*::[*/0x0832/*::]*/: { n:"BrtBeginTimelineStyles" },
19378 /*::[*/0x0833/*::]*/: { n:"BrtEndTimelineStyles" },
19379 /*::[*/0x0834/*::]*/: { n:"BrtBeginTimelineStyleElements" },
19380 /*::[*/0x0835/*::]*/: { n:"BrtEndTimelineStyleElements" },
19381 /*::[*/0x0836/*::]*/: { n:"BrtDxf15" },
19382 /*::[*/0x0837/*::]*/: { n:"BrtBeginDxfs15" },
19383 /*::[*/0x0838/*::]*/: { n:"brtEndDxfs15" },
19384 /*::[*/0x0839/*::]*/: { n:"BrtSlicerCacheHideItemsWithNoData" },
19385 /*::[*/0x083A/*::]*/: { n:"BrtBeginItemUniqueNames" },
19386 /*::[*/0x083B/*::]*/: { n:"BrtEndItemUniqueNames" },
19387 /*::[*/0x083C/*::]*/: { n:"BrtItemUniqueName" },
19388 /*::[*/0x083D/*::]*/: { n:"BrtBeginExtConn15" },
19389 /*::[*/0x083E/*::]*/: { n:"BrtEndExtConn15" },
19390 /*::[*/0x083F/*::]*/: { n:"BrtBeginOledbPr15" },
19391 /*::[*/0x0840/*::]*/: { n:"BrtEndOledbPr15" },
19392 /*::[*/0x0841/*::]*/: { n:"BrtBeginDataFeedPr15" },
19393 /*::[*/0x0842/*::]*/: { n:"BrtEndDataFeedPr15" },
19394 /*::[*/0x0843/*::]*/: { n:"BrtTextPr15" },
19395 /*::[*/0x0844/*::]*/: { n:"BrtRangePr15" },
19396 /*::[*/0x0845/*::]*/: { n:"BrtDbCommand15" },
19397 /*::[*/0x0846/*::]*/: { n:"BrtBeginDbTables15" },
19398 /*::[*/0x0847/*::]*/: { n:"BrtEndDbTables15" },
19399 /*::[*/0x0848/*::]*/: { n:"BrtDbTable15" },
19400 /*::[*/0x0849/*::]*/: { n:"BrtBeginDataModel" },
19401 /*::[*/0x084A/*::]*/: { n:"BrtEndDataModel" },
19402 /*::[*/0x084B/*::]*/: { n:"BrtBeginModelTables" },
19403 /*::[*/0x084C/*::]*/: { n:"BrtEndModelTables" },
19404 /*::[*/0x084D/*::]*/: { n:"BrtModelTable" },
19405 /*::[*/0x084E/*::]*/: { n:"BrtBeginModelRelationships" },
19406 /*::[*/0x084F/*::]*/: { n:"BrtEndModelRelationships" },
19407 /*::[*/0x0850/*::]*/: { n:"BrtModelRelationship" },
19408 /*::[*/0x0851/*::]*/: { n:"BrtBeginECTxtWiz15" },
19409 /*::[*/0x0852/*::]*/: { n:"BrtEndECTxtWiz15" },
19410 /*::[*/0x0853/*::]*/: { n:"BrtBeginECTWFldInfoLst15" },
19411 /*::[*/0x0854/*::]*/: { n:"BrtEndECTWFldInfoLst15" },
19412 /*::[*/0x0855/*::]*/: { n:"BrtBeginECTWFldInfo15" },
19413 /*::[*/0x0856/*::]*/: { n:"BrtFieldListActiveItem" },
19414 /*::[*/0x0857/*::]*/: { n:"BrtPivotCacheIdVersion" },
19415 /*::[*/0x0858/*::]*/: { n:"BrtSXDI15" },
19416 /*::[*/0x0859/*::]*/: { n:"BrtBeginModelTimeGroupings" },
19417 /*::[*/0x085A/*::]*/: { n:"BrtEndModelTimeGroupings" },
19418 /*::[*/0x085B/*::]*/: { n:"BrtBeginModelTimeGrouping" },
19419 /*::[*/0x085C/*::]*/: { n:"BrtEndModelTimeGrouping" },
19420 /*::[*/0x085D/*::]*/: { n:"BrtModelTimeGroupingCalcCol" },
19421 /*::[*/0x0C00/*::]*/: { n:"BrtUid" },
19422 /*::[*/0x0C01/*::]*/: { n:"BrtRevisionPtr" },
19423 /*::[*/0x13e7/*::]*/: { n:"BrtBeginCalcFeatures" },
19424 /*::[*/0x13e8/*::]*/: { n:"BrtEndCalcFeatures" },
19425 /*::[*/0x13e9/*::]*/: { n:"BrtCalcFeature" },
19426 /*::[*/0xFFFF/*::]*/: { n:"" }
19427};
19428
19429var XLSBRE = evert_key(XLSBRecordEnum, 'n');
19430XLSBRE["BrtFRTArchID$"] = 0x0010;
19431
19432/* [MS-XLS] 2.3 Record Enumeration (and other sources) */
19433var XLSRecordEnum = {
19434 /* [MS-XLS] 2.3 Record Enumeration 2021-08-17 */
19435 /*::[*/0x0006/*::]*/: { n:"Formula", f:parse_Formula },
19436 /*::[*/0x000a/*::]*/: { n:'EOF', f:parsenoop2 },
19437 /*::[*/0x000c/*::]*/: { n:"CalcCount", f:parseuint16 },
19438 /*::[*/0x000d/*::]*/: { n:"CalcMode", f:parseuint16 },
19439 /*::[*/0x000e/*::]*/: { n:"CalcPrecision", f:parsebool },
19440 /*::[*/0x000f/*::]*/: { n:"CalcRefMode", f:parsebool },
19441 /*::[*/0x0010/*::]*/: { n:"CalcDelta", f:parse_Xnum },
19442 /*::[*/0x0011/*::]*/: { n:"CalcIter", f:parsebool },
19443 /*::[*/0x0012/*::]*/: { n:"Protect", f:parsebool },
19444 /*::[*/0x0013/*::]*/: { n:"Password", f:parseuint16 },
19445 /*::[*/0x0014/*::]*/: { n:"Header", f:parse_XLHeaderFooter },
19446 /*::[*/0x0015/*::]*/: { n:"Footer", f:parse_XLHeaderFooter },
19447 /*::[*/0x0017/*::]*/: { n:"ExternSheet", f:parse_ExternSheet },
19448 /*::[*/0x0018/*::]*/: { n:"Lbl", f:parse_Lbl },
19449 /*::[*/0x0019/*::]*/: { n:"WinProtect", f:parsebool },
19450 /*::[*/0x001a/*::]*/: { n:"VerticalPageBreaks" },
19451 /*::[*/0x001b/*::]*/: { n:"HorizontalPageBreaks" },
19452 /*::[*/0x001c/*::]*/: { n:"Note", f:parse_Note },
19453 /*::[*/0x001d/*::]*/: { n:"Selection" },
19454 /*::[*/0x0022/*::]*/: { n:"Date1904", f:parsebool },
19455 /*::[*/0x0023/*::]*/: { n:"ExternName", f:parse_ExternName },
19456 /*::[*/0x0026/*::]*/: { n:"LeftMargin", f:parse_Xnum },
19457 /*::[*/0x0027/*::]*/: { n:"RightMargin", f:parse_Xnum },
19458 /*::[*/0x0028/*::]*/: { n:"TopMargin", f:parse_Xnum },
19459 /*::[*/0x0029/*::]*/: { n:"BottomMargin", f:parse_Xnum },
19460 /*::[*/0x002a/*::]*/: { n:"PrintRowCol", f:parsebool },
19461 /*::[*/0x002b/*::]*/: { n:"PrintGrid", f:parsebool },
19462 /*::[*/0x002f/*::]*/: { n:"FilePass", f:parse_FilePass },
19463 /*::[*/0x0031/*::]*/: { n:"Font", f:parse_Font },
19464 /*::[*/0x0033/*::]*/: { n:"PrintSize", f:parseuint16 },
19465 /*::[*/0x003c/*::]*/: { n:"Continue" },
19466 /*::[*/0x003d/*::]*/: { n:"Window1", f:parse_Window1 },
19467 /*::[*/0x0040/*::]*/: { n:"Backup", f:parsebool },
19468 /*::[*/0x0041/*::]*/: { n:"Pane", f:parse_Pane },
19469 /*::[*/0x0042/*::]*/: { n:'CodePage', f:parseuint16 },
19470 /*::[*/0x004d/*::]*/: { n:"Pls" },
19471 /*::[*/0x0050/*::]*/: { n:"DCon" },
19472 /*::[*/0x0051/*::]*/: { n:"DConRef" },
19473 /*::[*/0x0052/*::]*/: { n:"DConName" },
19474 /*::[*/0x0055/*::]*/: { n:"DefColWidth", f:parseuint16 },
19475 /*::[*/0x0059/*::]*/: { n:"XCT" },
19476 /*::[*/0x005a/*::]*/: { n:"CRN" },
19477 /*::[*/0x005b/*::]*/: { n:"FileSharing" },
19478 /*::[*/0x005c/*::]*/: { n:'WriteAccess', f:parse_WriteAccess },
19479 /*::[*/0x005d/*::]*/: { n:"Obj", f:parse_Obj },
19480 /*::[*/0x005e/*::]*/: { n:"Uncalced" },
19481 /*::[*/0x005f/*::]*/: { n:"CalcSaveRecalc", f:parsebool },
19482 /*::[*/0x0060/*::]*/: { n:"Template" },
19483 /*::[*/0x0061/*::]*/: { n:"Intl" },
19484 /*::[*/0x0063/*::]*/: { n:"ObjProtect", f:parsebool },
19485 /*::[*/0x007d/*::]*/: { n:"ColInfo", f:parse_ColInfo },
19486 /*::[*/0x0080/*::]*/: { n:"Guts", f:parse_Guts },
19487 /*::[*/0x0081/*::]*/: { n:"WsBool", f:parse_WsBool },
19488 /*::[*/0x0082/*::]*/: { n:"GridSet", f:parseuint16 },
19489 /*::[*/0x0083/*::]*/: { n:"HCenter", f:parsebool },
19490 /*::[*/0x0084/*::]*/: { n:"VCenter", f:parsebool },
19491 /*::[*/0x0085/*::]*/: { n:'BoundSheet8', f:parse_BoundSheet8 },
19492 /*::[*/0x0086/*::]*/: { n:"WriteProtect" },
19493 /*::[*/0x008c/*::]*/: { n:"Country", f:parse_Country },
19494 /*::[*/0x008d/*::]*/: { n:"HideObj", f:parseuint16 },
19495 /*::[*/0x0090/*::]*/: { n:"Sort" },
19496 /*::[*/0x0092/*::]*/: { n:"Palette", f:parse_Palette },
19497 /*::[*/0x0097/*::]*/: { n:"Sync" },
19498 /*::[*/0x0098/*::]*/: { n:"LPr" },
19499 /*::[*/0x0099/*::]*/: { n:"DxGCol" },
19500 /*::[*/0x009a/*::]*/: { n:"FnGroupName" },
19501 /*::[*/0x009b/*::]*/: { n:"FilterMode" },
19502 /*::[*/0x009c/*::]*/: { n:"BuiltInFnGroupCount", f:parseuint16 },
19503 /*::[*/0x009d/*::]*/: { n:"AutoFilterInfo" },
19504 /*::[*/0x009e/*::]*/: { n:"AutoFilter" },
19505 /*::[*/0x00a0/*::]*/: { n:"Scl", f:parse_Scl },
19506 /*::[*/0x00a1/*::]*/: { n:"Setup", f:parse_Setup },
19507 /*::[*/0x00ae/*::]*/: { n:"ScenMan" },
19508 /*::[*/0x00af/*::]*/: { n:"SCENARIO" },
19509 /*::[*/0x00b0/*::]*/: { n:"SxView" },
19510 /*::[*/0x00b1/*::]*/: { n:"Sxvd" },
19511 /*::[*/0x00b2/*::]*/: { n:"SXVI" },
19512 /*::[*/0x00b4/*::]*/: { n:"SxIvd" },
19513 /*::[*/0x00b5/*::]*/: { n:"SXLI" },
19514 /*::[*/0x00b6/*::]*/: { n:"SXPI" },
19515 /*::[*/0x00b8/*::]*/: { n:"DocRoute" },
19516 /*::[*/0x00b9/*::]*/: { n:"RecipName" },
19517 /*::[*/0x00bd/*::]*/: { n:"MulRk", f:parse_MulRk },
19518 /*::[*/0x00be/*::]*/: { n:"MulBlank", f:parse_MulBlank },
19519 /*::[*/0x00c1/*::]*/: { n:'Mms', f:parsenoop2 },
19520 /*::[*/0x00c5/*::]*/: { n:"SXDI" },
19521 /*::[*/0x00c6/*::]*/: { n:"SXDB" },
19522 /*::[*/0x00c7/*::]*/: { n:"SXFDB" },
19523 /*::[*/0x00c8/*::]*/: { n:"SXDBB" },
19524 /*::[*/0x00c9/*::]*/: { n:"SXNum" },
19525 /*::[*/0x00ca/*::]*/: { n:"SxBool", f:parsebool },
19526 /*::[*/0x00cb/*::]*/: { n:"SxErr" },
19527 /*::[*/0x00cc/*::]*/: { n:"SXInt" },
19528 /*::[*/0x00cd/*::]*/: { n:"SXString" },
19529 /*::[*/0x00ce/*::]*/: { n:"SXDtr" },
19530 /*::[*/0x00cf/*::]*/: { n:"SxNil" },
19531 /*::[*/0x00d0/*::]*/: { n:"SXTbl" },
19532 /*::[*/0x00d1/*::]*/: { n:"SXTBRGIITM" },
19533 /*::[*/0x00d2/*::]*/: { n:"SxTbpg" },
19534 /*::[*/0x00d3/*::]*/: { n:"ObProj" },
19535 /*::[*/0x00d5/*::]*/: { n:"SXStreamID" },
19536 /*::[*/0x00d7/*::]*/: { n:"DBCell" },
19537 /*::[*/0x00d8/*::]*/: { n:"SXRng" },
19538 /*::[*/0x00d9/*::]*/: { n:"SxIsxoper" },
19539 /*::[*/0x00da/*::]*/: { n:"BookBool", f:parseuint16 },
19540 /*::[*/0x00dc/*::]*/: { n:"DbOrParamQry" },
19541 /*::[*/0x00dd/*::]*/: { n:"ScenarioProtect", f:parsebool },
19542 /*::[*/0x00de/*::]*/: { n:"OleObjectSize" },
19543 /*::[*/0x00e0/*::]*/: { n:"XF", f:parse_XF },
19544 /*::[*/0x00e1/*::]*/: { n:'InterfaceHdr', f:parse_InterfaceHdr },
19545 /*::[*/0x00e2/*::]*/: { n:'InterfaceEnd', f:parsenoop2 },
19546 /*::[*/0x00e3/*::]*/: { n:"SXVS" },
19547 /*::[*/0x00e5/*::]*/: { n:"MergeCells", f:parse_MergeCells },
19548 /*::[*/0x00e9/*::]*/: { n:"BkHim" },
19549 /*::[*/0x00eb/*::]*/: { n:"MsoDrawingGroup" },
19550 /*::[*/0x00ec/*::]*/: { n:"MsoDrawing" },
19551 /*::[*/0x00ed/*::]*/: { n:"MsoDrawingSelection" },
19552 /*::[*/0x00ef/*::]*/: { n:"PhoneticInfo" },
19553 /*::[*/0x00f0/*::]*/: { n:"SxRule" },
19554 /*::[*/0x00f1/*::]*/: { n:"SXEx" },
19555 /*::[*/0x00f2/*::]*/: { n:"SxFilt" },
19556 /*::[*/0x00f4/*::]*/: { n:"SxDXF" },
19557 /*::[*/0x00f5/*::]*/: { n:"SxItm" },
19558 /*::[*/0x00f6/*::]*/: { n:"SxName" },
19559 /*::[*/0x00f7/*::]*/: { n:"SxSelect" },
19560 /*::[*/0x00f8/*::]*/: { n:"SXPair" },
19561 /*::[*/0x00f9/*::]*/: { n:"SxFmla" },
19562 /*::[*/0x00fb/*::]*/: { n:"SxFormat" },
19563 /*::[*/0x00fc/*::]*/: { n:"SST", f:parse_SST },
19564 /*::[*/0x00fd/*::]*/: { n:"LabelSst", f:parse_LabelSst },
19565 /*::[*/0x00ff/*::]*/: { n:"ExtSST", f:parse_ExtSST },
19566 /*::[*/0x0100/*::]*/: { n:"SXVDEx" },
19567 /*::[*/0x0103/*::]*/: { n:"SXFormula" },
19568 /*::[*/0x0122/*::]*/: { n:"SXDBEx" },
19569 /*::[*/0x0137/*::]*/: { n:"RRDInsDel" },
19570 /*::[*/0x0138/*::]*/: { n:"RRDHead" },
19571 /*::[*/0x013b/*::]*/: { n:"RRDChgCell" },
19572 /*::[*/0x013d/*::]*/: { n:"RRTabId", f:parseuint16a },
19573 /*::[*/0x013e/*::]*/: { n:"RRDRenSheet" },
19574 /*::[*/0x013f/*::]*/: { n:"RRSort" },
19575 /*::[*/0x0140/*::]*/: { n:"RRDMove" },
19576 /*::[*/0x014a/*::]*/: { n:"RRFormat" },
19577 /*::[*/0x014b/*::]*/: { n:"RRAutoFmt" },
19578 /*::[*/0x014d/*::]*/: { n:"RRInsertSh" },
19579 /*::[*/0x014e/*::]*/: { n:"RRDMoveBegin" },
19580 /*::[*/0x014f/*::]*/: { n:"RRDMoveEnd" },
19581 /*::[*/0x0150/*::]*/: { n:"RRDInsDelBegin" },
19582 /*::[*/0x0151/*::]*/: { n:"RRDInsDelEnd" },
19583 /*::[*/0x0152/*::]*/: { n:"RRDConflict" },
19584 /*::[*/0x0153/*::]*/: { n:"RRDDefName" },
19585 /*::[*/0x0154/*::]*/: { n:"RRDRstEtxp" },
19586 /*::[*/0x015f/*::]*/: { n:"LRng" },
19587 /*::[*/0x0160/*::]*/: { n:"UsesELFs", f:parsebool },
19588 /*::[*/0x0161/*::]*/: { n:"DSF", f:parsenoop2 },
19589 /*::[*/0x0191/*::]*/: { n:"CUsr" },
19590 /*::[*/0x0192/*::]*/: { n:"CbUsr" },
19591 /*::[*/0x0193/*::]*/: { n:"UsrInfo" },
19592 /*::[*/0x0194/*::]*/: { n:"UsrExcl" },
19593 /*::[*/0x0195/*::]*/: { n:"FileLock" },
19594 /*::[*/0x0196/*::]*/: { n:"RRDInfo" },
19595 /*::[*/0x0197/*::]*/: { n:"BCUsrs" },
19596 /*::[*/0x0198/*::]*/: { n:"UsrChk" },
19597 /*::[*/0x01a9/*::]*/: { n:"UserBView" },
19598 /*::[*/0x01aa/*::]*/: { n:"UserSViewBegin" },
19599 /*::[*/0x01ab/*::]*/: { n:"UserSViewEnd" },
19600 /*::[*/0x01ac/*::]*/: { n:"RRDUserView" },
19601 /*::[*/0x01ad/*::]*/: { n:"Qsi" },
19602 /*::[*/0x01ae/*::]*/: { n:"SupBook", f:parse_SupBook },
19603 /*::[*/0x01af/*::]*/: { n:"Prot4Rev", f:parsebool },
19604 /*::[*/0x01b0/*::]*/: { n:"CondFmt" },
19605 /*::[*/0x01b1/*::]*/: { n:"CF" },
19606 /*::[*/0x01b2/*::]*/: { n:"DVal" },
19607 /*::[*/0x01b5/*::]*/: { n:"DConBin" },
19608 /*::[*/0x01b6/*::]*/: { n:"TxO", f:parse_TxO },
19609 /*::[*/0x01b7/*::]*/: { n:"RefreshAll", f:parsebool },
19610 /*::[*/0x01b8/*::]*/: { n:"HLink", f:parse_HLink },
19611 /*::[*/0x01b9/*::]*/: { n:"Lel" },
19612 /*::[*/0x01ba/*::]*/: { n:"CodeName", f:parse_XLUnicodeString },
19613 /*::[*/0x01bb/*::]*/: { n:"SXFDBType" },
19614 /*::[*/0x01bc/*::]*/: { n:"Prot4RevPass", f:parseuint16 },
19615 /*::[*/0x01bd/*::]*/: { n:"ObNoMacros" },
19616 /*::[*/0x01be/*::]*/: { n:"Dv" },
19617 /*::[*/0x01c0/*::]*/: { n:"Excel9File", f:parsenoop2 },
19618 /*::[*/0x01c1/*::]*/: { n:"RecalcId", f:parse_RecalcId, r:2},
19619 /*::[*/0x01c2/*::]*/: { n:"EntExU2", f:parsenoop2 },
19620 /*::[*/0x0200/*::]*/: { n:"Dimensions", f:parse_Dimensions },
19621 /*::[*/0x0201/*::]*/: { n:"Blank", f:parse_Blank },
19622 /*::[*/0x0203/*::]*/: { n:"Number", f:parse_Number },
19623 /*::[*/0x0204/*::]*/: { n:"Label", f:parse_Label },
19624 /*::[*/0x0205/*::]*/: { n:"BoolErr", f:parse_BoolErr },
19625 /*::[*/0x0207/*::]*/: { n:"String", f:parse_String },
19626 /*::[*/0x0208/*::]*/: { n:'Row', f:parse_Row },
19627 /*::[*/0x020b/*::]*/: { n:"Index" },
19628 /*::[*/0x0221/*::]*/: { n:"Array", f:parse_Array },
19629 /*::[*/0x0225/*::]*/: { n:"DefaultRowHeight", f:parse_DefaultRowHeight },
19630 /*::[*/0x0236/*::]*/: { n:"Table" },
19631 /*::[*/0x023e/*::]*/: { n:"Window2", f:parse_Window2 },
19632 /*::[*/0x027e/*::]*/: { n:"RK", f:parse_RK },
19633 /*::[*/0x0293/*::]*/: { n:"Style" },
19634 /*::[*/0x0418/*::]*/: { n:"BigName" },
19635 /*::[*/0x041e/*::]*/: { n:"Format", f:parse_Format },
19636 /*::[*/0x043c/*::]*/: { n:"ContinueBigName" },
19637 /*::[*/0x04bc/*::]*/: { n:"ShrFmla", f:parse_ShrFmla },
19638 /*::[*/0x0800/*::]*/: { n:"HLinkTooltip", f:parse_HLinkTooltip },
19639 /*::[*/0x0801/*::]*/: { n:"WebPub" },
19640 /*::[*/0x0802/*::]*/: { n:"QsiSXTag" },
19641 /*::[*/0x0803/*::]*/: { n:"DBQueryExt" },
19642 /*::[*/0x0804/*::]*/: { n:"ExtString" },
19643 /*::[*/0x0805/*::]*/: { n:"TxtQry" },
19644 /*::[*/0x0806/*::]*/: { n:"Qsir" },
19645 /*::[*/0x0807/*::]*/: { n:"Qsif" },
19646 /*::[*/0x0808/*::]*/: { n:"RRDTQSIF" },
19647 /*::[*/0x0809/*::]*/: { n:'BOF', f:parse_BOF },
19648 /*::[*/0x080a/*::]*/: { n:"OleDbConn" },
19649 /*::[*/0x080b/*::]*/: { n:"WOpt" },
19650 /*::[*/0x080c/*::]*/: { n:"SXViewEx" },
19651 /*::[*/0x080d/*::]*/: { n:"SXTH" },
19652 /*::[*/0x080e/*::]*/: { n:"SXPIEx" },
19653 /*::[*/0x080f/*::]*/: { n:"SXVDTEx" },
19654 /*::[*/0x0810/*::]*/: { n:"SXViewEx9" },
19655 /*::[*/0x0812/*::]*/: { n:"ContinueFrt" },
19656 /*::[*/0x0813/*::]*/: { n:"RealTimeData" },
19657 /*::[*/0x0850/*::]*/: { n:"ChartFrtInfo" },
19658 /*::[*/0x0851/*::]*/: { n:"FrtWrapper" },
19659 /*::[*/0x0852/*::]*/: { n:"StartBlock" },
19660 /*::[*/0x0853/*::]*/: { n:"EndBlock" },
19661 /*::[*/0x0854/*::]*/: { n:"StartObject" },
19662 /*::[*/0x0855/*::]*/: { n:"EndObject" },
19663 /*::[*/0x0856/*::]*/: { n:"CatLab" },
19664 /*::[*/0x0857/*::]*/: { n:"YMult" },
19665 /*::[*/0x0858/*::]*/: { n:"SXViewLink" },
19666 /*::[*/0x0859/*::]*/: { n:"PivotChartBits" },
19667 /*::[*/0x085a/*::]*/: { n:"FrtFontList" },
19668 /*::[*/0x0862/*::]*/: { n:"SheetExt" },
19669 /*::[*/0x0863/*::]*/: { n:"BookExt", r:12},
19670 /*::[*/0x0864/*::]*/: { n:"SXAddl" },
19671 /*::[*/0x0865/*::]*/: { n:"CrErr" },
19672 /*::[*/0x0866/*::]*/: { n:"HFPicture" },
19673 /*::[*/0x0867/*::]*/: { n:'FeatHdr', f:parsenoop2 },
19674 /*::[*/0x0868/*::]*/: { n:"Feat" },
19675 /*::[*/0x086a/*::]*/: { n:"DataLabExt" },
19676 /*::[*/0x086b/*::]*/: { n:"DataLabExtContents" },
19677 /*::[*/0x086c/*::]*/: { n:"CellWatch" },
19678 /*::[*/0x0871/*::]*/: { n:"FeatHdr11" },
19679 /*::[*/0x0872/*::]*/: { n:"Feature11" },
19680 /*::[*/0x0874/*::]*/: { n:"DropDownObjIds" },
19681 /*::[*/0x0875/*::]*/: { n:"ContinueFrt11" },
19682 /*::[*/0x0876/*::]*/: { n:"DConn" },
19683 /*::[*/0x0877/*::]*/: { n:"List12" },
19684 /*::[*/0x0878/*::]*/: { n:"Feature12" },
19685 /*::[*/0x0879/*::]*/: { n:"CondFmt12" },
19686 /*::[*/0x087a/*::]*/: { n:"CF12" },
19687 /*::[*/0x087b/*::]*/: { n:"CFEx" },
19688 /*::[*/0x087c/*::]*/: { n:"XFCRC", f:parse_XFCRC, r:12 },
19689 /*::[*/0x087d/*::]*/: { n:"XFExt", f:parse_XFExt, r:12 },
19690 /*::[*/0x087e/*::]*/: { n:"AutoFilter12" },
19691 /*::[*/0x087f/*::]*/: { n:"ContinueFrt12" },
19692 /*::[*/0x0884/*::]*/: { n:"MDTInfo" },
19693 /*::[*/0x0885/*::]*/: { n:"MDXStr" },
19694 /*::[*/0x0886/*::]*/: { n:"MDXTuple" },
19695 /*::[*/0x0887/*::]*/: { n:"MDXSet" },
19696 /*::[*/0x0888/*::]*/: { n:"MDXProp" },
19697 /*::[*/0x0889/*::]*/: { n:"MDXKPI" },
19698 /*::[*/0x088a/*::]*/: { n:"MDB" },
19699 /*::[*/0x088b/*::]*/: { n:"PLV" },
19700 /*::[*/0x088c/*::]*/: { n:"Compat12", f:parsebool, r:12 },
19701 /*::[*/0x088d/*::]*/: { n:"DXF" },
19702 /*::[*/0x088e/*::]*/: { n:"TableStyles", r:12 },
19703 /*::[*/0x088f/*::]*/: { n:"TableStyle" },
19704 /*::[*/0x0890/*::]*/: { n:"TableStyleElement" },
19705 /*::[*/0x0892/*::]*/: { n:"StyleExt" },
19706 /*::[*/0x0893/*::]*/: { n:"NamePublish" },
19707 /*::[*/0x0894/*::]*/: { n:"NameCmt", f:parse_NameCmt, r:12 },
19708 /*::[*/0x0895/*::]*/: { n:"SortData" },
19709 /*::[*/0x0896/*::]*/: { n:"Theme", f:parse_Theme, r:12 },
19710 /*::[*/0x0897/*::]*/: { n:"GUIDTypeLib" },
19711 /*::[*/0x0898/*::]*/: { n:"FnGrp12" },
19712 /*::[*/0x0899/*::]*/: { n:"NameFnGrp12" },
19713 /*::[*/0x089a/*::]*/: { n:"MTRSettings", f:parse_MTRSettings, r:12 },
19714 /*::[*/0x089b/*::]*/: { n:"CompressPictures", f:parsenoop2 },
19715 /*::[*/0x089c/*::]*/: { n:"HeaderFooter" },
19716 /*::[*/0x089d/*::]*/: { n:"CrtLayout12" },
19717 /*::[*/0x089e/*::]*/: { n:"CrtMlFrt" },
19718 /*::[*/0x089f/*::]*/: { n:"CrtMlFrtContinue" },
19719 /*::[*/0x08a3/*::]*/: { n:"ForceFullCalculation", f:parse_ForceFullCalculation },
19720 /*::[*/0x08a4/*::]*/: { n:"ShapePropsStream" },
19721 /*::[*/0x08a5/*::]*/: { n:"TextPropsStream" },
19722 /*::[*/0x08a6/*::]*/: { n:"RichTextStream" },
19723 /*::[*/0x08a7/*::]*/: { n:"CrtLayout12A" },
19724 /*::[*/0x1001/*::]*/: { n:"Units" },
19725 /*::[*/0x1002/*::]*/: { n:"Chart" },
19726 /*::[*/0x1003/*::]*/: { n:"Series" },
19727 /*::[*/0x1006/*::]*/: { n:"DataFormat" },
19728 /*::[*/0x1007/*::]*/: { n:"LineFormat" },
19729 /*::[*/0x1009/*::]*/: { n:"MarkerFormat" },
19730 /*::[*/0x100a/*::]*/: { n:"AreaFormat" },
19731 /*::[*/0x100b/*::]*/: { n:"PieFormat" },
19732 /*::[*/0x100c/*::]*/: { n:"AttachedLabel" },
19733 /*::[*/0x100d/*::]*/: { n:"SeriesText" },
19734 /*::[*/0x1014/*::]*/: { n:"ChartFormat" },
19735 /*::[*/0x1015/*::]*/: { n:"Legend" },
19736 /*::[*/0x1016/*::]*/: { n:"SeriesList" },
19737 /*::[*/0x1017/*::]*/: { n:"Bar" },
19738 /*::[*/0x1018/*::]*/: { n:"Line" },
19739 /*::[*/0x1019/*::]*/: { n:"Pie" },
19740 /*::[*/0x101a/*::]*/: { n:"Area" },
19741 /*::[*/0x101b/*::]*/: { n:"Scatter" },
19742 /*::[*/0x101c/*::]*/: { n:"CrtLine" },
19743 /*::[*/0x101d/*::]*/: { n:"Axis" },
19744 /*::[*/0x101e/*::]*/: { n:"Tick" },
19745 /*::[*/0x101f/*::]*/: { n:"ValueRange" },
19746 /*::[*/0x1020/*::]*/: { n:"CatSerRange" },
19747 /*::[*/0x1021/*::]*/: { n:"AxisLine" },
19748 /*::[*/0x1022/*::]*/: { n:"CrtLink" },
19749 /*::[*/0x1024/*::]*/: { n:"DefaultText" },
19750 /*::[*/0x1025/*::]*/: { n:"Text" },
19751 /*::[*/0x1026/*::]*/: { n:"FontX", f:parseuint16 },
19752 /*::[*/0x1027/*::]*/: { n:"ObjectLink" },
19753 /*::[*/0x1032/*::]*/: { n:"Frame" },
19754 /*::[*/0x1033/*::]*/: { n:"Begin" },
19755 /*::[*/0x1034/*::]*/: { n:"End" },
19756 /*::[*/0x1035/*::]*/: { n:"PlotArea" },
19757 /*::[*/0x103a/*::]*/: { n:"Chart3d" },
19758 /*::[*/0x103c/*::]*/: { n:"PicF" },
19759 /*::[*/0x103d/*::]*/: { n:"DropBar" },
19760 /*::[*/0x103e/*::]*/: { n:"Radar" },
19761 /*::[*/0x103f/*::]*/: { n:"Surf" },
19762 /*::[*/0x1040/*::]*/: { n:"RadarArea" },
19763 /*::[*/0x1041/*::]*/: { n:"AxisParent" },
19764 /*::[*/0x1043/*::]*/: { n:"LegendException" },
19765 /*::[*/0x1044/*::]*/: { n:"ShtProps", f:parse_ShtProps },
19766 /*::[*/0x1045/*::]*/: { n:"SerToCrt" },
19767 /*::[*/0x1046/*::]*/: { n:"AxesUsed" },
19768 /*::[*/0x1048/*::]*/: { n:"SBaseRef" },
19769 /*::[*/0x104a/*::]*/: { n:"SerParent" },
19770 /*::[*/0x104b/*::]*/: { n:"SerAuxTrend" },
19771 /*::[*/0x104e/*::]*/: { n:"IFmtRecord" },
19772 /*::[*/0x104f/*::]*/: { n:"Pos" },
19773 /*::[*/0x1050/*::]*/: { n:"AlRuns" },
19774 /*::[*/0x1051/*::]*/: { n:"BRAI" },
19775 /*::[*/0x105b/*::]*/: { n:"SerAuxErrBar" },
19776 /*::[*/0x105c/*::]*/: { n:"ClrtClient", f:parse_ClrtClient },
19777 /*::[*/0x105d/*::]*/: { n:"SerFmt" },
19778 /*::[*/0x105f/*::]*/: { n:"Chart3DBarShape" },
19779 /*::[*/0x1060/*::]*/: { n:"Fbi" },
19780 /*::[*/0x1061/*::]*/: { n:"BopPop" },
19781 /*::[*/0x1062/*::]*/: { n:"AxcExt" },
19782 /*::[*/0x1063/*::]*/: { n:"Dat" },
19783 /*::[*/0x1064/*::]*/: { n:"PlotGrowth" },
19784 /*::[*/0x1065/*::]*/: { n:"SIIndex" },
19785 /*::[*/0x1066/*::]*/: { n:"GelFrame" },
19786 /*::[*/0x1067/*::]*/: { n:"BopPopCustom" },
19787 /*::[*/0x1068/*::]*/: { n:"Fbi2" },
19788
19789 /*::[*/0x0000/*::]*/: { n:"Dimensions", f:parse_Dimensions },
19790 /*::[*/0x0001/*::]*/: { n:"BIFF2BLANK" },
19791 /*::[*/0x0002/*::]*/: { n:"BIFF2INT", f:parse_BIFF2INT },
19792 /*::[*/0x0003/*::]*/: { n:"BIFF2NUM", f:parse_BIFF2NUM },
19793 /*::[*/0x0004/*::]*/: { n:"BIFF2STR", f:parse_BIFF2STR },
19794 /*::[*/0x0005/*::]*/: { n:"BoolErr", f:parse_BoolErr },
19795 /*::[*/0x0007/*::]*/: { n:"String", f:parse_BIFF2STRING },
19796 /*::[*/0x0008/*::]*/: { n:"BIFF2ROW" },
19797 /*::[*/0x0009/*::]*/: { n:'BOF', f:parse_BOF },
19798 /*::[*/0x000b/*::]*/: { n:"Index" },
19799 /*::[*/0x0016/*::]*/: { n:"ExternCount", f:parseuint16 },
19800 /*::[*/0x001e/*::]*/: { n:"BIFF2FORMAT", f:parse_BIFF2Format },
19801 /*::[*/0x001f/*::]*/: { n:"BIFF2FMTCNT" }, /* 16-bit cnt of BIFF2FORMAT records */
19802 /*::[*/0x0020/*::]*/: { n:"BIFF2COLINFO" },
19803 /*::[*/0x0021/*::]*/: { n:"Array", f:parse_Array },
19804 /*::[*/0x0024/*::]*/: { n:"COLWIDTH" },
19805 /*::[*/0x0025/*::]*/: { n:"DefaultRowHeight", f:parse_DefaultRowHeight },
19806 // 0x2c ??
19807 // 0x2d ??
19808 // 0x2e ??
19809 // 0x30 FONTCOUNT: number of fonts
19810 /*::[*/0x0032/*::]*/: { n:"BIFF2FONTXTRA", f:parse_BIFF2FONTXTRA },
19811 // 0x35: INFOOPTS
19812 // 0x36: TABLE (BIFF2 only)
19813 // 0x37: TABLE2 (BIFF2 only)
19814 // 0x38: WNDESK
19815 // 0x39 ??
19816 // 0x3a: BEGINPREF
19817 // 0x3b: ENDPREF
19818 /*::[*/0x003e/*::]*/: { n:"BIFF2WINDOW2" },
19819 // 0x3f ??
19820 // 0x46: SHOWSCROLL
19821 // 0x47: SHOWFORMULA
19822 // 0x48: STATUSBAR
19823 // 0x49: SHORTMENUS
19824 // 0x4A:
19825 // 0x4B:
19826 // 0x4C:
19827 // 0x4E:
19828 // 0x4F:
19829 // 0x58: TOOLBAR (BIFF3)
19830
19831 /* - - - */
19832 /*::[*/0x0034/*::]*/: { n:"DDEObjName" },
19833 /*::[*/0x0043/*::]*/: { n:"BIFF2XF" },
19834 /*::[*/0x0044/*::]*/: { n:"BIFF2XFINDEX", f:parseuint16 },
19835 /*::[*/0x0045/*::]*/: { n:"BIFF2FONTCLR" },
19836 /*::[*/0x0056/*::]*/: { n:"BIFF4FMTCNT" }, /* 16-bit cnt, similar to BIFF2 */
19837 /*::[*/0x007e/*::]*/: { n:"RK" }, /* Not necessarily same as 0x027e */
19838 /*::[*/0x007f/*::]*/: { n:"ImData", f:parse_ImData },
19839 /*::[*/0x0087/*::]*/: { n:"Addin" },
19840 /*::[*/0x0088/*::]*/: { n:"Edg" },
19841 /*::[*/0x0089/*::]*/: { n:"Pub" },
19842 // 0x8A
19843 // 0x8B LH: alternate menu key flag (BIFF3/4)
19844 // 0x8E
19845 // 0x8F
19846 /*::[*/0x0091/*::]*/: { n:"Sub" },
19847 // 0x93 STYLE
19848 /*::[*/0x0094/*::]*/: { n:"LHRecord" },
19849 /*::[*/0x0095/*::]*/: { n:"LHNGraph" },
19850 /*::[*/0x0096/*::]*/: { n:"Sound" },
19851 // 0xA2 FNPROTO: function prototypes (BIFF4)
19852 // 0xA3
19853 // 0xA8
19854 /*::[*/0x00a9/*::]*/: { n:"CoordList" },
19855 /*::[*/0x00ab/*::]*/: { n:"GCW" },
19856 /*::[*/0x00bc/*::]*/: { n:"ShrFmla" }, /* Not necessarily same as 0x04bc */
19857 /*::[*/0x00bf/*::]*/: { n:"ToolbarHdr" },
19858 /*::[*/0x00c0/*::]*/: { n:"ToolbarEnd" },
19859 /*::[*/0x00c2/*::]*/: { n:"AddMenu" },
19860 /*::[*/0x00c3/*::]*/: { n:"DelMenu" },
19861 /*::[*/0x00d6/*::]*/: { n:"RString", f:parse_RString },
19862 /*::[*/0x00df/*::]*/: { n:"UDDesc" },
19863 /*::[*/0x00ea/*::]*/: { n:"TabIdConf" },
19864 /*::[*/0x0162/*::]*/: { n:"XL5Modify" },
19865 /*::[*/0x01a5/*::]*/: { n:"FileSharing2" },
19866 /*::[*/0x0206/*::]*/: { n:"Formula", f:parse_Formula },
19867 /*::[*/0x0209/*::]*/: { n:'BOF', f:parse_BOF },
19868 /*::[*/0x0218/*::]*/: { n:"Lbl", f:parse_Lbl },
19869 /*::[*/0x0223/*::]*/: { n:"ExternName", f:parse_ExternName },
19870 /*::[*/0x0231/*::]*/: { n:"Font" },
19871 /*::[*/0x0243/*::]*/: { n:"BIFF3XF" },
19872 /*::[*/0x0406/*::]*/: { n:"Formula", f:parse_Formula },
19873 /*::[*/0x0409/*::]*/: { n:'BOF', f:parse_BOF },
19874 /*::[*/0x0443/*::]*/: { n:"BIFF4XF" },
19875 /*::[*/0x086d/*::]*/: { n:"FeatInfo" },
19876 /*::[*/0x0873/*::]*/: { n:"FeatInfo11" },
19877 /*::[*/0x0881/*::]*/: { n:"SXAddl12" },
19878 /*::[*/0x08c0/*::]*/: { n:"AutoWebPub" },
19879 /*::[*/0x08c1/*::]*/: { n:"ListObj" },
19880 /*::[*/0x08c2/*::]*/: { n:"ListField" },
19881 /*::[*/0x08c3/*::]*/: { n:"ListDV" },
19882 /*::[*/0x08c4/*::]*/: { n:"ListCondFmt" },
19883 /*::[*/0x08c5/*::]*/: { n:"ListCF" },
19884 /*::[*/0x08c6/*::]*/: { n:"FMQry" },
19885 /*::[*/0x08c7/*::]*/: { n:"FMSQry" },
19886 /*::[*/0x08c8/*::]*/: { n:"PLV" },
19887 /*::[*/0x08c9/*::]*/: { n:"LnExt" },
19888 /*::[*/0x08ca/*::]*/: { n:"MkrExt" },
19889 /*::[*/0x08cb/*::]*/: { n:"CrtCoopt" },
19890 /*::[*/0x08d6/*::]*/: { n:"FRTArchId$", r:12 },
19891
19892 /*::[*/0x7262/*::]*/: {}
19893};
19894
19895var XLSRE = evert_key(XLSRecordEnum, 'n');
19896function write_biff_rec(ba/*:BufArray*/, type/*:number|string*/, payload, length/*:?number*/)/*:void*/ {
19897 var t/*:number*/ = typeof type == "number" ? type : (+type || +XLSRE[/*::String(*/type/*::)*/]);
19898 if(isNaN(t)) return;
19899 var len = length || (payload||[]).length || 0;
19900 var o = ba.next(4);
19901 o.write_shift(2, t);
19902 o.write_shift(2, len);
19903 if(/*:: len != null &&*/len > 0 && is_buf(payload)) ba.push(payload);
19904}
19905
19906function write_biff_continue(ba/*:BufArray*/, type/*:number|string*/, payload, length/*:?number*/)/*:void*/ {
19907 var len = length || (payload||[]).length || 0;
19908 if(len <= 8224) return write_biff_rec(ba, type, payload, len);
19909 var t/*:number*/ = +type || +XLSRE[/*::String(*/type/*::)*/];
19910 if(isNaN(t)) return;
19911 var parts = payload.parts || [], sidx = 0;
19912 var i = 0, w = 0;
19913 while(w + (parts[sidx] || 8224) <= 8224) { w+= (parts[sidx] || 8224); sidx++; }
19914 var o = ba.next(4);
19915 o.write_shift(2, t);
19916 o.write_shift(2, w);
19917 ba.push(payload.slice(i, i + w));
19918 i += w;
19919 while(i < len) {
19920 o = ba.next(4);
19921 o.write_shift(2, 0x3c); // TODO: figure out correct continue type
19922 w = 0;
19923 while(w + (parts[sidx] || 8224) <= 8224) { w+= (parts[sidx] || 8224); sidx++; }
19924 o.write_shift(2, w);
19925 ba.push(payload.slice(i, i+w)); i+= w;
19926 }
19927}
19928
19929function write_BIFF2Cell(out, r/*:number*/, c/*:number*/) {
19930 if(!out) out = new_buf(7);
19931 out.write_shift(2, r);
19932 out.write_shift(2, c);
19933 out.write_shift(2, 0);
19934 out.write_shift(1, 0);
19935 return out;
19936}
19937
19938function write_BIFF2BERR(r/*:number*/, c/*:number*/, val, t/*:?string*/) {
19939 var out = new_buf(9);
19940 write_BIFF2Cell(out, r, c);
19941 write_Bes(val, t || 'b', out);
19942 return out;
19943}
19944
19945/* TODO: codepage, large strings */
19946function write_BIFF2LABEL(r/*:number*/, c/*:number*/, val) {
19947 var out = new_buf(8 + 2*val.length);
19948 write_BIFF2Cell(out, r, c);
19949 out.write_shift(1, val.length);
19950 out.write_shift(val.length, val, 'sbcs');
19951 return out.l < out.length ? out.slice(0, out.l) : out;
19952}
19953
19954function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*//*::, opts*/) {
19955 if(cell.v != null) switch(cell.t) {
19956 case 'd': case 'n':
19957 var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
19958 if((v == (v|0)) && (v >= 0) && (v < 65536))
19959 write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v));
19960 else
19961 write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v));
19962 return;
19963 case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
19964 /* TODO: codepage, sst */
19965 case 's': case 'str':
19966 write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, (cell.v||"").slice(0,255)));
19967 return;
19968 }
19969 write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
19970}
19971
19972function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
19973 var dense = Array.isArray(ws);
19974 var range = safe_decode_range(ws['!ref'] || "A1"), ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
19975 if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
19976 if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
19977 range.e.c = Math.min(range.e.c, 0xFF);
19978 range.e.r = Math.min(range.e.c, 0x3FFF);
19979 ref = encode_range(range);
19980 }
19981 for(var R = range.s.r; R <= range.e.r; ++R) {
19982 rr = encode_row(R);
19983 for(var C = range.s.c; C <= range.e.c; ++C) {
19984 if(R === range.s.r) cols[C] = encode_col(C);
19985 ref = cols[C] + rr;
19986 var cell = dense ? (ws[R]||[])[C] : ws[ref];
19987 if(!cell) continue;
19988 /* write cell */
19989 write_ws_biff2_cell(ba, cell, R, C, opts);
19990 }
19991 }
19992}
19993
19994/* Based on test files */
19995function write_biff2_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
19996 var o = opts || {};
19997 if(DENSE != null && o.dense == null) o.dense = DENSE;
19998 var ba = buf_array();
19999 var idx = 0;
20000 for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i;
20001 if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
20002 write_biff_rec(ba, (o.biff == 4 ? 0x0409 : (o.biff == 3 ? 0x0209 : 0x0009)), write_BOF(wb, 0x10, o));
20003 /* ... */
20004 write_ws_biff2(ba, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
20005 /* ... */
20006 write_biff_rec(ba, 0x000A);
20007 return ba.end();
20008}
20009
20010function write_FONTS_biff8(ba, data, opts) {
20011 write_biff_rec(ba, "Font", write_Font({
20012 sz:12,
20013 color: {theme:1},
20014 name: "Arial",
20015 family: 2,
20016 scheme: "minor"
20017 }, opts));
20018}
20019
20020
20021function write_FMTS_biff8(ba, NF/*:?SSFTable*/, opts) {
20022 if(!NF) return;
20023 [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
20024 /*:: if(!NF) return; */
20025 for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_biff_rec(ba, "Format", write_Format(i, NF[i], opts));
20026 });
20027}
20028
20029function write_FEAT(ba, ws) {
20030 /* [MS-XLS] 2.4.112 */
20031 var o = new_buf(19);
20032 o.write_shift(4, 0x867); o.write_shift(4, 0); o.write_shift(4, 0);
20033 o.write_shift(2, 3); o.write_shift(1, 1); o.write_shift(4, 0);
20034 write_biff_rec(ba, "FeatHdr", o);
20035 /* [MS-XLS] 2.4.111 */
20036 o = new_buf(39);
20037 o.write_shift(4, 0x868); o.write_shift(4, 0); o.write_shift(4, 0);
20038 o.write_shift(2, 3); o.write_shift(1, 0); o.write_shift(4, 0);
20039 o.write_shift(2, 1); o.write_shift(4, 4); o.write_shift(2, 0);
20040 write_Ref8U(safe_decode_range(ws['!ref']||"A1"), o);
20041 o.write_shift(4, 4);
20042 write_biff_rec(ba, "Feat", o);
20043}
20044
20045function write_CELLXFS_biff8(ba, opts) {
20046 for(var i = 0; i < 16; ++i) write_biff_rec(ba, "XF", write_XF({numFmtId:0, style:true}, 0, opts));
20047 opts.cellXfs.forEach(function(c) {
20048 write_biff_rec(ba, "XF", write_XF(c, 0, opts));
20049 });
20050}
20051
20052function write_ws_biff8_hlinks(ba/*:BufArray*/, ws) {
20053 for(var R=0; R<ws['!links'].length; ++R) {
20054 var HL = ws['!links'][R];
20055 write_biff_rec(ba, "HLink", write_HLink(HL));
20056 if(HL[1].Tooltip) write_biff_rec(ba, "HLinkTooltip", write_HLinkTooltip(HL));
20057 }
20058 delete ws['!links'];
20059}
20060
20061function write_ws_cols_biff8(ba, cols, ws) {
20062 if(!cols) return;
20063 var cnt = 0;
20064 cols.forEach(function(col, idx) {
20065 if(++cnt <= 256 && col) {
20066 write_biff_rec(ba, "ColInfo", write_ColInfo(col_obj_w(idx, col), idx));
20067 }
20068 });
20069}
20070
20071function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) {
20072 var os = 16 + get_cell_style(opts.cellXfs, cell, opts);
20073 if(cell.v == null && !cell.bf) {
20074 write_biff_rec(ba, "Blank", write_XLSCell(R, C, os));
20075 return;
20076 }
20077 if(cell.bf) write_biff_rec(ba, "Formula", write_Formula(cell, R, C, opts, os));
20078 else switch(cell.t) {
20079 case 'd': case 'n':
20080 var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
20081 /* TODO: emit RK as appropriate */
20082 write_biff_rec(ba, "Number", write_Number(R, C, v, os, opts));
20083 break;
20084 case 'b': case 'e':
20085 write_biff_rec(ba, 0x0205, write_BoolErr(R, C, cell.v, os, opts, cell.t));
20086 break;
20087 /* TODO: codepage, sst */
20088 case 's': case 'str':
20089 if(opts.bookSST) {
20090 var isst = get_sst_id(opts.Strings, cell.v, opts.revStrings);
20091 write_biff_rec(ba, "LabelSst", write_LabelSst(R, C, isst, os, opts));
20092 } else write_biff_rec(ba, "Label", write_Label(R, C, (cell.v||"").slice(0,255), os, opts));
20093 break;
20094 default:
20095 write_biff_rec(ba, "Blank", write_XLSCell(R, C, os));
20096 }
20097}
20098
20099/* [MS-XLS] 2.1.7.20.5 */
20100function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
20101 var ba = buf_array();
20102 var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
20103 var _WB/*:WBWBProps*/ = ((wb||{}).Workbook||{}/*:any*/);
20104 var _sheet/*:WBWSProp*/ = ((_WB.Sheets||[])[idx]||{}/*:any*/);
20105 var dense = Array.isArray(ws);
20106 var b8 = opts.biff == 8;
20107 var ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
20108 var range = safe_decode_range(ws['!ref'] || "A1");
20109 var MAX_ROWS = b8 ? 65536 : 16384;
20110 if(range.e.c > 0xFF || range.e.r >= MAX_ROWS) {
20111 if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
20112 range.e.c = Math.min(range.e.c, 0xFF);
20113 range.e.r = Math.min(range.e.c, MAX_ROWS-1);
20114 }
20115
20116 write_biff_rec(ba, 0x0809, write_BOF(wb, 0x10, opts));
20117 /* [Uncalced] Index */
20118 write_biff_rec(ba, "CalcMode", writeuint16(1));
20119 write_biff_rec(ba, "CalcCount", writeuint16(100));
20120 write_biff_rec(ba, "CalcRefMode", writebool(true));
20121 write_biff_rec(ba, "CalcIter", writebool(false));
20122 write_biff_rec(ba, "CalcDelta", write_Xnum(0.001));
20123 write_biff_rec(ba, "CalcSaveRecalc", writebool(true));
20124 write_biff_rec(ba, "PrintRowCol", writebool(false));
20125 write_biff_rec(ba, "PrintGrid", writebool(false));
20126 write_biff_rec(ba, "GridSet", writeuint16(1));
20127 write_biff_rec(ba, "Guts", write_Guts([0,0]));
20128 /* DefaultRowHeight WsBool [Sync] [LPr] [HorizontalPageBreaks] [VerticalPageBreaks] */
20129 /* Header (string) */
20130 /* Footer (string) */
20131 write_biff_rec(ba, "HCenter", writebool(false));
20132 write_biff_rec(ba, "VCenter", writebool(false));
20133 /* ... */
20134 if(b8) write_ws_cols_biff8(ba, ws["!cols"], ws);
20135 /* ... */
20136 write_biff_rec(ba, 0x200, write_Dimensions(range, opts));
20137 /* ... */
20138
20139 if(b8) ws['!links'] = [];
20140 for(var R = range.s.r; R <= range.e.r; ++R) {
20141 rr = encode_row(R);
20142 for(var C = range.s.c; C <= range.e.c; ++C) {
20143 if(R === range.s.r) cols[C] = encode_col(C);
20144 ref = cols[C] + rr;
20145 var cell = dense ? (ws[R]||[])[C] : ws[ref];
20146 if(!cell) continue;
20147 /* write cell */
20148 write_ws_biff8_cell(ba, cell, R, C, opts);
20149 if(b8 && cell.l) ws['!links'].push([ref, cell.l]);
20150 }
20151 }
20152 var cname/*:string*/ = _sheet.CodeName || _sheet.name || s;
20153 /* ... */
20154 if(b8) write_biff_rec(ba, "Window2", write_Window2((_WB.Views||[])[0]));
20155 /* ... */
20156 if(b8 && (ws['!merges']||[]).length) write_biff_rec(ba, "MergeCells", write_MergeCells(ws['!merges']));
20157 /* [LRng] *QUERYTABLE [PHONETICINFO] CONDFMTS */
20158 if(b8) write_ws_biff8_hlinks(ba, ws);
20159 /* [DVAL] */
20160 write_biff_rec(ba, "CodeName", write_XLUnicodeString(cname, opts));
20161 /* *WebPub *CellWatch [SheetExt] */
20162 if(b8) write_FEAT(ba, ws);
20163 /* *FEAT11 *RECORD12 */
20164 write_biff_rec(ba, "EOF");
20165 return ba.end();
20166}
20167
20168/* [MS-XLS] 2.1.7.20.3 */
20169function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) {
20170 var A = buf_array();
20171 var _WB/*:WBWBProps*/ = ((wb||{}).Workbook||{}/*:any*/);
20172 var _sheets/*:Array<WBWSProp>*/ = (_WB.Sheets||[]);
20173 var _wb/*:WBProps*/ = /*::((*/_WB.WBProps||{/*::CodeName:"ThisWorkbook"*/}/*:: ):any)*/;
20174 var b8 = opts.biff == 8, b5 = opts.biff == 5;
20175 write_biff_rec(A, 0x0809, write_BOF(wb, 0x05, opts));
20176 if(opts.bookType == "xla") write_biff_rec(A, "Addin");
20177 write_biff_rec(A, "InterfaceHdr", b8 ? writeuint16(0x04b0) : null);
20178 write_biff_rec(A, "Mms", writezeroes(2));
20179 if(b5) write_biff_rec(A, "ToolbarHdr");
20180 if(b5) write_biff_rec(A, "ToolbarEnd");
20181 write_biff_rec(A, "InterfaceEnd");
20182 write_biff_rec(A, "WriteAccess", write_WriteAccess("SheetJS", opts));
20183 /* [FileSharing] */
20184 write_biff_rec(A, "CodePage", writeuint16(b8 ? 0x04b0 : 0x04E4));
20185 /* *2047 Lel */
20186 if(b8) write_biff_rec(A, "DSF", writeuint16(0));
20187 if(b8) write_biff_rec(A, "Excel9File");
20188 write_biff_rec(A, "RRTabId", write_RRTabId(wb.SheetNames.length));
20189 if(b8 && wb.vbaraw) write_biff_rec(A, "ObProj");
20190 /* [ObNoMacros] */
20191 if(b8 && wb.vbaraw) {
20192 var cname/*:string*/ = _wb.CodeName || "ThisWorkbook";
20193 write_biff_rec(A, "CodeName", write_XLUnicodeString(cname, opts));
20194 }
20195 write_biff_rec(A, "BuiltInFnGroupCount", writeuint16(0x11));
20196 /* *FnGroupName *FnGrp12 */
20197 /* *Lbl */
20198 /* [OleObjectSize] */
20199 write_biff_rec(A, "WinProtect", writebool(false));
20200 write_biff_rec(A, "Protect", writebool(false));
20201 write_biff_rec(A, "Password", writeuint16(0));
20202 if(b8) write_biff_rec(A, "Prot4Rev", writebool(false));
20203 if(b8) write_biff_rec(A, "Prot4RevPass", writeuint16(0));
20204 write_biff_rec(A, "Window1", write_Window1(opts));
20205 write_biff_rec(A, "Backup", writebool(false));
20206 write_biff_rec(A, "HideObj", writeuint16(0));
20207 write_biff_rec(A, "Date1904", writebool(safe1904(wb)=="true"));
20208 write_biff_rec(A, "CalcPrecision", writebool(true));
20209 if(b8) write_biff_rec(A, "RefreshAll", writebool(false));
20210 write_biff_rec(A, "BookBool", writeuint16(0));
20211 /* ... */
20212 write_FONTS_biff8(A, wb, opts);
20213 write_FMTS_biff8(A, wb.SSF, opts);
20214 write_CELLXFS_biff8(A, opts);
20215 /* ... */
20216 if(b8) write_biff_rec(A, "UsesELFs", writebool(false));
20217 var a = A.end();
20218
20219 var C = buf_array();
20220 /* METADATA [MTRSettings] [ForceFullCalculation] */
20221 if(b8) write_biff_rec(C, "Country", write_Country());
20222 /* *SUPBOOK *LBL *RTD [RecalcId] *HFPicture *MSODRAWINGGROUP */
20223
20224 /* BIFF8: [SST *Continue] ExtSST */
20225 if(b8 && opts.Strings) write_biff_continue(C, "SST", write_SST(opts.Strings, opts));
20226
20227 /* *WebPub [WOpt] [CrErr] [BookExt] *FeatHdr *DConn [THEME] [CompressPictures] [Compat12] [GUIDTypeLib] */
20228 write_biff_rec(C, "EOF");
20229 var c = C.end();
20230
20231 var B = buf_array();
20232 var blen = 0, j = 0;
20233 for(j = 0; j < wb.SheetNames.length; ++j) blen += (b8 ? 12 : 11) + (b8 ? 2 : 1) * wb.SheetNames[j].length;
20234 var start = a.length + blen + c.length;
20235 for(j = 0; j < wb.SheetNames.length; ++j) {
20236 var _sheet/*:WBWSProp*/ = _sheets[j] || ({}/*:any*/);
20237 write_biff_rec(B, "BoundSheet8", write_BoundSheet8({pos:start, hs:_sheet.Hidden||0, dt:0, name:wb.SheetNames[j]}, opts));
20238 start += bufs[j].length;
20239 }
20240 /* 1*BoundSheet8 */
20241 var b = B.end();
20242 if(blen != b.length) throw new Error("BS8 " + blen + " != " + b.length);
20243
20244 var out = [];
20245 if(a.length) out.push(a);
20246 if(b.length) out.push(b);
20247 if(c.length) out.push(c);
20248 return __toBuffer([out]);
20249}
20250
20251/* [MS-XLS] 2.1.7.20 Workbook Stream */
20252function write_biff8_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
20253 var o = opts || {};
20254 var bufs = [];
20255
20256 if(wb && !wb.SSF) {
20257 wb.SSF = SSF.get_table();
20258 }
20259 if(wb && wb.SSF) {
20260 make_ssf(SSF); SSF.load_table(wb.SSF);
20261 // $FlowIgnore
20262 o.revssf = evert_num(wb.SSF); o.revssf[wb.SSF[65535]] = 0;
20263 o.ssf = wb.SSF;
20264 }
20265
20266 o.Strings = /*::((*/[]/*:: :any):SST)*/; o.Strings.Count = 0; o.Strings.Unique = 0;
20267 fix_write_opts(o);
20268
20269 o.cellXfs = [];
20270 get_cell_style(o.cellXfs, {}, {revssf:{"General":0}});
20271
20272 if(!wb.Props) wb.Props = {};
20273
20274 for(var i = 0; i < wb.SheetNames.length; ++i) bufs[bufs.length] = write_ws_biff8(i, o, wb);
20275 bufs.unshift(write_biff8_global(wb, bufs, o));
20276 return __toBuffer([bufs]);
20277}
20278
20279function write_biff_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
20280 var o = opts || {};
20281 switch(o.biff || 2) {
20282 case 8: case 5: return write_biff8_buf(wb, opts);
20283 case 4: case 3: case 2: return write_biff2_buf(wb, opts);
20284 }
20285 throw new Error("invalid type " + o.bookType + " for BIFF");
20286}
20287/* note: browser DOM element cannot see mso- style attrs, must parse */
20288var HTML_ = (function() {
20289 function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ {
20290 var opts = _opts || {};
20291 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
20292 var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
20293 str = str.replace(/<!--.*?-->/g, "");
20294 var mtch/*:any*/ = str.match(/<table/i);
20295 if(!mtch) throw new Error("Invalid HTML: could not find <table>");
20296 var mtch2/*:any*/ = str.match(/<\/table/i);
20297 var i/*:number*/ = mtch.index, j/*:number*/ = mtch2 && mtch2.index || str.length;
20298 var rows = split_regex(str.slice(i, j), /(:?<tr[^>]*>)/i, "<tr>");
20299 var R = -1, C = 0, RS = 0, CS = 0;
20300 var range/*:Range*/ = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
20301 var merges/*:Array<Range>*/ = [];
20302 for(i = 0; i < rows.length; ++i) {
20303 var row = rows[i].trim();
20304 var hd = row.slice(0,3).toLowerCase();
20305 if(hd == "<tr") { ++R; if(opts.sheetRows && opts.sheetRows <= R) { --R; break; } C = 0; continue; }
20306 if(hd != "<td" && hd != "<th") continue;
20307 var cells = row.split(/<\/t[dh]>/i);
20308 for(j = 0; j < cells.length; ++j) {
20309 var cell = cells[j].trim();
20310 if(!cell.match(/<t[dh]/i)) continue;
20311 var m = cell, cc = 0;
20312 /* TODO: parse styles etc */
20313 while(m.charAt(0) == "<" && (cc = m.indexOf(">")) > -1) m = m.slice(cc+1);
20314 for(var midx = 0; midx < merges.length; ++midx) {
20315 var _merge/*:Range*/ = merges[midx];
20316 if(_merge.s.c == C && _merge.s.r < R && R <= _merge.e.r) { C = _merge.e.c + 1; midx = -1; }
20317 }
20318 var tag = parsexmltag(cell.slice(0, cell.indexOf(">")));
20319 CS = tag.colspan ? +tag.colspan : 1;
20320 if((RS = +tag.rowspan)>1 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
20321 var _t/*:string*/ = tag.t || tag["data-t"] || "";
20322 /* TODO: generate stub cells */
20323 if(!m.length) { C += CS; continue; }
20324 m = htmldecode(m);
20325 if(range.s.r > R) range.s.r = R; if(range.e.r < R) range.e.r = R;
20326 if(range.s.c > C) range.s.c = C; if(range.e.c < C) range.e.c = C;
20327 if(!m.length) continue;
20328 var o/*:Cell*/ = {t:'s', v:m};
20329 if(opts.raw || !m.trim().length || _t == 's'){}
20330 else if(m === 'TRUE') o = {t:'b', v:true};
20331 else if(m === 'FALSE') o = {t:'b', v:false};
20332 else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)};
20333 else if(!isNaN(fuzzydate(m).getDate())) {
20334 o = ({t:'d', v:parseDate(m)}/*:any*/);
20335 if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
20336 o.z = opts.dateNF || SSF._table[14];
20337 }
20338 if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; }
20339 else ws[encode_cell({r:R, c:C})] = o;
20340 C += CS;
20341 }
20342 }
20343 ws['!ref'] = encode_range(range);
20344 if(merges.length) ws["!merges"] = merges;
20345 return ws;
20346 }
20347 function html_to_book(str/*:string*/, opts)/*:Workbook*/ {
20348 var mtch = str.match(/<table.*?>[\s\S]*?<\/table>/gi);
20349 if(!mtch || mtch.length == 0) throw new Error("Invalid HTML: could not find <table>");
20350 if(mtch.length == 1) return sheet_to_workbook(html_to_sheet(mtch[0], opts), opts);
20351 var wb = utils.book_new();
20352 mtch.forEach(function(s, idx) { utils.book_append_sheet(wb, html_to_sheet(s, opts), "Sheet" + (idx+1)); });
20353 return wb;
20354 }
20355 function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
20356 var M/*:Array<Range>*/ = (ws['!merges'] ||[]);
20357 var oo/*:Array<string>*/ = [];
20358 for(var C = r.s.c; C <= r.e.c; ++C) {
20359 var RS = 0, CS = 0;
20360 for(var j = 0; j < M.length; ++j) {
20361 if(M[j].s.r > R || M[j].s.c > C) continue;
20362 if(M[j].e.r < R || M[j].e.c < C) continue;
20363 if(M[j].s.r < R || M[j].s.c < C) { RS = -1; break; }
20364 RS = M[j].e.r - M[j].s.r + 1; CS = M[j].e.c - M[j].s.c + 1; break;
20365 }
20366 if(RS < 0) continue;
20367 var coord = encode_cell({r:R,c:C});
20368 var cell = o.dense ? (ws[R]||[])[C] : ws[coord];
20369 /* TODO: html entities */
20370 var w = (cell && cell.v != null) && (cell.h || escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || "";
20371 var sp = ({}/*:any*/);
20372 if(RS > 1) sp.rowspan = RS;
20373 if(CS > 1) sp.colspan = CS;
20374 if(o.editable) w = '<span contenteditable="true">' + w + '</span>';
20375 else if(cell) {
20376 sp["data-t"] = cell && cell.t || 'z';
20377 if(cell.v != null) sp["data-v"] = cell.v;
20378 if(cell.z != null) sp["data-z"] = cell.z;
20379 if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + cell.l.Target +'">' + w + '</a>';
20380 }
20381 sp.id = (o.id || "sjs") + "-" + coord;
20382 oo.push(writextag('td', w, sp));
20383 }
20384 var preamble = "<tr>";
20385 return preamble + oo.join("") + "</tr>";
20386 }
20387 function make_html_preamble(ws/*:Worksheet*/, R/*:Range*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
20388 var out/*:Array<string>*/ = [];
20389 return out.join("") + '<table' + (o && o.id ? ' id="' + o.id + '"' : "") + '>';
20390 }
20391 var _BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
20392 var _END = '</body></html>';
20393 function sheet_to_html(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*//*, wb:?Workbook*/)/*:string*/ {
20394 var o = opts || {};
20395 var header = o.header != null ? o.header : _BEGIN;
20396 var footer = o.footer != null ? o.footer : _END;
20397 var out/*:Array<string>*/ = [header];
20398 var r = decode_range(ws['!ref']);
20399 o.dense = Array.isArray(ws);
20400 out.push(make_html_preamble(ws, r, o));
20401 for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
20402 out.push("</table>" + footer);
20403 return out.join("");
20404
20405 }
20406 return {
20407 to_workbook: html_to_book,
20408 to_sheet: html_to_sheet,
20409 _row: make_html_row,
20410 BEGIN: _BEGIN,
20411 END: _END,
20412 _preamble: make_html_preamble,
20413 from_sheet: sheet_to_html
20414 };
20415})();
20416
20417function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
20418 var opts = _opts || {};
20419 if(DENSE != null) opts.dense = DENSE;
20420 var or_R = 0, or_C = 0;
20421 if(opts.origin != null) {
20422 if(typeof opts.origin == 'number') or_R = opts.origin;
20423 else {
20424 var _origin/*:CellAddress*/ = typeof opts.origin == "string" ? decode_cell(opts.origin) : opts.origin;
20425 or_R = _origin.r; or_C = _origin.c;
20426 }
20427 }
20428 var rows/*:HTMLCollection<HTMLTableRowElement>*/ = table.getElementsByTagName('tr');
20429 var sheetRows = Math.min(opts.sheetRows||10000000, rows.length);
20430 var range/*:Range*/ = {s:{r:0,c:0},e:{r:or_R,c:or_C}};
20431 if(ws["!ref"]) {
20432 var _range/*:Range*/ = decode_range(ws["!ref"]);
20433 range.s.r = Math.min(range.s.r, _range.s.r);
20434 range.s.c = Math.min(range.s.c, _range.s.c);
20435 range.e.r = Math.max(range.e.r, _range.e.r);
20436 range.e.c = Math.max(range.e.c, _range.e.c);
20437 if(or_R == -1) range.e.r = or_R = _range.e.r + 1;
20438 }
20439 var merges/*:Array<Range>*/ = [], midx = 0;
20440 var rowinfo/*:Array<RowInfo>*/ = ws["!rows"] || (ws["!rows"] = []);
20441 var _R = 0, R = 0, _C = 0, C = 0, RS = 0, CS = 0;
20442 if(!ws["!cols"]) ws['!cols'] = [];
20443 for(; _R < rows.length && R < sheetRows; ++_R) {
20444 var row/*:HTMLTableRowElement*/ = rows[_R];
20445 if (is_dom_element_hidden(row)) {
20446 if (opts.display) continue;
20447 rowinfo[R] = {hidden: true};
20448 }
20449 var elts/*:HTMLCollection<HTMLTableCellElement>*/ = (row.children/*:any*/);
20450 for(_C = C = 0; _C < elts.length; ++_C) {
20451 var elt/*:HTMLTableCellElement*/ = elts[_C];
20452 if (opts.display && is_dom_element_hidden(elt)) continue;
20453 var v/*:?string*/ = elt.hasAttribute('data-v') ? elt.getAttribute('data-v') : elt.hasAttribute('v') ? elt.getAttribute('v') : htmldecode(elt.innerHTML);
20454 var z/*:?string*/ = elt.getAttribute('data-z') || elt.getAttribute('z');
20455 for(midx = 0; midx < merges.length; ++midx) {
20456 var m/*:Range*/ = merges[midx];
20457 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; }
20458 }
20459 /* TODO: figure out how to extract nonstandard mso- style */
20460 CS = +elt.getAttribute("colspan") || 1;
20461 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}});
20462 var o/*:Cell*/ = {t:'s', v:v};
20463 var _t/*:string*/ = elt.getAttribute("data-t") || elt.getAttribute("t") || "";
20464 if(v != null) {
20465 if(v.length == 0) o.t = _t || 'z';
20466 else if(opts.raw || v.trim().length == 0 || _t == "s"){}
20467 else if(v === 'TRUE') o = {t:'b', v:true};
20468 else if(v === 'FALSE') o = {t:'b', v:false};
20469 else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
20470 else if(!isNaN(fuzzydate(v).getDate())) {
20471 o = ({t:'d', v:parseDate(v)}/*:any*/);
20472 if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
20473 o.z = opts.dateNF || SSF._table[14];
20474 }
20475 }
20476 if(o.z === undefined && z != null) o.z = z;
20477 /* The first link is used. Links are assumed to be fully specified.
20478 * TODO: The right way to process relative links is to make a new <a> */
20479 var l = "", Aelts = elt.getElementsByTagName("A");
20480 if(Aelts && Aelts.length) for(var Aelti = 0; Aelti < Aelts.length; ++Aelti) if(Aelts[Aelti].hasAttribute("href")) {
20481 l = Aelts[Aelti].getAttribute("href"); if(l.charAt(0) != "#") break;
20482 }
20483 if(l && l.charAt(0) != "#") o.l = ({ Target: l });
20484 if(opts.dense) { if(!ws[R + or_R]) ws[R + or_R] = []; ws[R + or_R][C + or_C] = o; }
20485 else ws[encode_cell({c:C + or_C, r:R + or_R})] = o;
20486 if(range.e.c < C + or_C) range.e.c = C + or_C;
20487 C += CS;
20488 }
20489 ++R;
20490 }
20491 if(merges.length) ws['!merges'] = (ws["!merges"] || []).concat(merges);
20492 range.e.r = Math.max(range.e.r, R - 1 + or_R);
20493 ws['!ref'] = encode_range(range);
20494 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
20495 return ws;
20496}
20497
20498function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
20499 var opts = _opts || {};
20500 var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
20501 return sheet_add_dom(ws, table, _opts);
20502}
20503
20504function table_to_book(table/*:HTMLElement*/, opts/*:?any*/)/*:Workbook*/ {
20505 return sheet_to_workbook(parse_dom_table(table, opts), opts);
20506}
20507
20508function is_dom_element_hidden(element/*:HTMLElement*/)/*:boolean*/ {
20509 var display/*:string*/ = '';
20510 var get_computed_style/*:?function*/ = get_get_computed_style_function(element);
20511 if(get_computed_style) display = get_computed_style(element).getPropertyValue('display');
20512 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)
20513 return display === 'none';
20514}
20515
20516/* global getComputedStyle */
20517function get_get_computed_style_function(element/*:HTMLElement*/)/*:?function*/ {
20518 // The proper getComputedStyle implementation is the one defined in the element window
20519 if(element.ownerDocument.defaultView && typeof element.ownerDocument.defaultView.getComputedStyle === 'function') return element.ownerDocument.defaultView.getComputedStyle;
20520 // If it is not available, try to get one from the global namespace
20521 if(typeof getComputedStyle === 'function') return getComputedStyle;
20522 return null;
20523}
20524/* OpenDocument */
20525var parse_content_xml = (function() {
20526
20527 var parse_text_p = function(text/*:string*//*::, tag*/)/*:Array<any>*/ {
20528 /* 6.1.2 White Space Characters */
20529 var fixed = text
20530 .replace(/[\t\r\n]/g, " ").trim().replace(/ +/g, " ")
20531 .replace(/<text:s\/>/g," ")
20532 .replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); })
20533 .replace(/<text:tab[^>]*\/>/g,"\t")
20534 .replace(/<text:line-break\/>/g,"\n");
20535 var v = unescapexml(fixed.replace(/<[^>]*>/g,""));
20536
20537 return [v];
20538 };
20539
20540 var number_formats = {
20541 /* ods name: [short ssf fmt, long ssf fmt] */
20542 day: ["d", "dd"],
20543 month: ["m", "mm"],
20544 year: ["y", "yy"],
20545 hours: ["h", "hh"],
20546 minutes: ["m", "mm"],
20547 seconds: ["s", "ss"],
20548 "am-pm": ["A/P", "AM/PM"],
20549 "day-of-week": ["ddd", "dddd"],
20550 era: ["e", "ee"],
20551 /* there is no native representation of LO "Q" format */
20552 quarter: ["\\Qm", "m\\\"th quarter\""]
20553 };
20554
20555 return function pcx(d/*:string*/, _opts)/*:Workbook*/ {
20556 var opts = _opts || {};
20557 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
20558 var str = xlml_normalize(d);
20559 var state/*:Array<any>*/ = [], tmp;
20560 var tag/*:: = {}*/;
20561 var NFtag = {name:""}, NF = "", pidx = 0;
20562 var sheetag/*:: = {name:"", '名称':""}*/;
20563 var rowtag/*:: = {'行号':""}*/;
20564 var Sheets = {}, SheetNames/*:Array<string>*/ = [];
20565 var ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
20566 var Rn, q/*:: :any = ({t:"", v:null, z:null, w:"",c:[],}:any)*/;
20567 var ctag = ({value:""}/*:any*/);
20568 var textp = "", textpidx = 0, textptag/*:: = {}*/;
20569 var textR = [];
20570 var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
20571 var row_ol = 0;
20572 var number_format_map = {};
20573 var merges/*:Array<Range>*/ = [], mrange = {}, mR = 0, mC = 0;
20574 var rowinfo/*:Array<RowInfo>*/ = [], rowpeat = 1, colpeat = 1;
20575 var arrayf/*:Array<[Range, string]>*/ = [];
20576 var WB = {Names:[]};
20577 var atag = ({}/*:any*/);
20578 var _Ref/*:[string, string]*/ = ["", ""];
20579 var comments/*:Array<Comment>*/ = [], comment/*:Comment*/ = ({}/*:any*/);
20580 var creator = "", creatoridx = 0;
20581 var isstub = false, intable = false;
20582 var i = 0;
20583 xlmlregex.lastIndex = 0;
20584 str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
20585 while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
20586
20587 case 'table': case '工作表': // 9.1.2 <table:table>
20588 if(Rn[1]==='/') {
20589 if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = encode_range(range);
20590 else ws['!ref'] = "A1:A1";
20591 if(opts.sheetRows > 0 && opts.sheetRows <= range.e.r) {
20592 ws['!fullref'] = ws['!ref'];
20593 range.e.r = opts.sheetRows - 1;
20594 ws['!ref'] = encode_range(range);
20595 }
20596 if(merges.length) ws['!merges'] = merges;
20597 if(rowinfo.length) ws["!rows"] = rowinfo;
20598 sheetag.name = sheetag['名称'] || sheetag.name;
20599 if(typeof JSON !== 'undefined') JSON.stringify(sheetag);
20600 SheetNames.push(sheetag.name);
20601 Sheets[sheetag.name] = ws;
20602 intable = false;
20603 }
20604 else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
20605 sheetag = parsexmltag(Rn[0], false);
20606 R = C = -1;
20607 range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0;
20608 ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/); merges = [];
20609 rowinfo = [];
20610 intable = true;
20611 }
20612 break;
20613
20614 case 'table-row-group': // 9.1.9 <table:table-row-group>
20615 if(Rn[1] === "/") --row_ol; else ++row_ol;
20616 break;
20617 case 'table-row': case '行': // 9.1.3 <table:table-row>
20618 if(Rn[1] === '/') { R+=rowpeat; rowpeat = 1; break; }
20619 rowtag = parsexmltag(Rn[0], false);
20620 if(rowtag['行号']) R = rowtag['行号'] - 1; else if(R == -1) R = 0;
20621 rowpeat = +rowtag['number-rows-repeated'] || 1;
20622 /* TODO: remove magic */
20623 if(rowpeat < 10) for(i = 0; i < rowpeat; ++i) if(row_ol > 0) rowinfo[R + i] = {level: row_ol};
20624 C = -1; break;
20625 case 'covered-table-cell': // 9.1.5 <table:covered-table-cell>
20626 if(Rn[1] !== '/') ++C;
20627 if(opts.sheetStubs) {
20628 if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = {t:'z'}; }
20629 else ws[encode_cell({r:R,c:C})] = {t:'z'};
20630 }
20631 textp = ""; textR = [];
20632 break; /* stub */
20633 case 'table-cell': case '数据':
20634 if(Rn[0].charAt(Rn[0].length-2) === '/') {
20635 ++C;
20636 ctag = parsexmltag(Rn[0], false);
20637 colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
20638 q = ({t:'z', v:null/*:: , z:null, w:"",c:[]*/}/*:any*/);
20639 if(ctag.formula && opts.cellFormula != false) q.f = ods_to_csf_formula(unescapexml(ctag.formula));
20640 if((ctag['数据类型'] || ctag['value-type']) == "string") {
20641 q.t = "s"; q.v = unescapexml(ctag['string-value'] || "");
20642 if(opts.dense) {
20643 if(!ws[R]) ws[R] = [];
20644 ws[R][C] = q;
20645 } else {
20646 ws[encode_cell({r:R,c:C})] = q;
20647 }
20648 }
20649 C+= colpeat-1;
20650 } else if(Rn[1]!=='/') {
20651 ++C;
20652 textp = ""; textpidx = 0; textR = [];
20653 colpeat = 1;
20654 var rptR = rowpeat ? R + rowpeat - 1 : R;
20655 if(C > range.e.c) range.e.c = C;
20656 if(C < range.s.c) range.s.c = C;
20657 if(R < range.s.r) range.s.r = R;
20658 if(rptR > range.e.r) range.e.r = rptR;
20659 ctag = parsexmltag(Rn[0], false);
20660 comments = []; comment = ({}/*:any*/);
20661 q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:"",c:[]*/}/*:any*/);
20662 if(opts.cellFormula) {
20663 if(ctag.formula) ctag.formula = unescapexml(ctag.formula);
20664 if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
20665 mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
20666 mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
20667 mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
20668 q.F = encode_range(mrange);
20669 arrayf.push([mrange, q.F]);
20670 }
20671 if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula);
20672 else for(i = 0; i < arrayf.length; ++i)
20673 if(R >= arrayf[i][0].s.r && R <= arrayf[i][0].e.r)
20674 if(C >= arrayf[i][0].s.c && C <= arrayf[i][0].e.c)
20675 q.F = arrayf[i][1];
20676 }
20677 if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) {
20678 mR = parseInt(ctag['number-rows-spanned'],10) || 0;
20679 mC = parseInt(ctag['number-columns-spanned'],10) || 0;
20680 mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
20681 merges.push(mrange);
20682 }
20683
20684 /* 19.675.2 table:number-columns-repeated */
20685 if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10);
20686
20687 /* 19.385 office:value-type */
20688 switch(q.t) {
20689 case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break;
20690 case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break;
20691 case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break;
20692 case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break;
20693 case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']);
20694 if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v); }
20695 q.z = 'm/d/yy'; break;
20696 case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400;
20697 if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); }
20698 q.z = 'HH:MM:SS'; break;
20699 case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
20700 default:
20701 if(q.t === 'string' || q.t === 'text' || !q.t) {
20702 q.t = 's';
20703 if(ctag['string-value'] != null) { textp = unescapexml(ctag['string-value']); textR = []; }
20704 } else throw new Error('Unsupported value type ' + q.t);
20705 }
20706 } else {
20707 isstub = false;
20708 if(q.t === 's') {
20709 q.v = textp || '';
20710 if(textR.length) q.R = textR;
20711 isstub = textpidx == 0;
20712 }
20713 if(atag.Target) q.l = atag;
20714 if(comments.length > 0) { q.c = comments; comments = []; }
20715 if(textp && opts.cellText !== false) q.w = textp;
20716 if(isstub) { q.t = "z"; delete q.v; }
20717 if(!isstub || opts.sheetStubs) {
20718 if(!(opts.sheetRows && opts.sheetRows <= R)) {
20719 for(var rpt = 0; rpt < rowpeat; ++rpt) {
20720 colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
20721 if(opts.dense) {
20722 if(!ws[R + rpt]) ws[R + rpt] = [];
20723 ws[R + rpt][C] = rpt == 0 ? q : dup(q);
20724 while(--colpeat > 0) ws[R + rpt][C + colpeat] = dup(q);
20725 } else {
20726 ws[encode_cell({r:R + rpt,c:C})] = q;
20727 while(--colpeat > 0) ws[encode_cell({r:R + rpt,c:C + colpeat})] = dup(q);
20728 }
20729 if(range.e.c <= C) range.e.c = C;
20730 }
20731 }
20732 }
20733 colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
20734 C += colpeat-1; colpeat = 0;
20735 q = {/*:: t:"", v:null, z:null, w:"",c:[]*/};
20736 textp = ""; textR = [];
20737 }
20738 atag = ({}/*:any*/);
20739 break; // 9.1.4 <table:table-cell>
20740
20741 /* pure state */
20742 case 'document': // TODO: <office:document> is the root for FODS
20743 case 'document-content': case '电子表格文档': // 3.1.3.2 <office:document-content>
20744 case 'spreadsheet': case '主体': // 3.7 <office:spreadsheet>
20745 case 'scripts': // 3.12 <office:scripts>
20746 case 'styles': // TODO <office:styles>
20747 case 'font-face-decls': // 3.14 <office:font-face-decls>
20748 case 'master-styles': // 3.15.4 <office:master-styles> -- relevant for FODS
20749 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
20750 else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
20751 break;
20752
20753 case 'annotation': // 14.1 <office:annotation>
20754 if(Rn[1]==='/'){
20755 if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
20756 comment.t = textp;
20757 if(textR.length) /*::(*/comment/*:: :any)*/.R = textR;
20758 comment.a = creator;
20759 comments.push(comment);
20760 }
20761 else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);}
20762 creator = ""; creatoridx = 0;
20763 textp = ""; textpidx = 0; textR = [];
20764 break;
20765
20766 case 'creator': // 4.3.2.7 <dc:creator>
20767 if(Rn[1]==='/') { creator = str.slice(creatoridx,Rn.index); }
20768 else creatoridx = Rn.index + Rn[0].length;
20769 break;
20770
20771 /* ignore state */
20772 case 'meta': case '元数据': // TODO: <office:meta> <uof:元数据> FODS/UOF
20773 case 'settings': // TODO: <office:settings>
20774 case 'config-item-set': // TODO: <office:config-item-set>
20775 case 'config-item-map-indexed': // TODO: <office:config-item-map-indexed>
20776 case 'config-item-map-entry': // TODO: <office:config-item-map-entry>
20777 case 'config-item-map-named': // TODO: <office:config-item-map-entry>
20778 case 'shapes': // 9.2.8 <table:shapes>
20779 case 'frame': // 10.4.2 <draw:frame>
20780 case 'text-box': // 10.4.3 <draw:text-box>
20781 case 'image': // 10.4.4 <draw:image>
20782 case 'data-pilot-tables': // 9.6.2 <table:data-pilot-tables>
20783 case 'list-style': // 16.30 <text:list-style>
20784 case 'form': // 13.13 <form:form>
20785 case 'dde-links': // 9.8 <table:dde-links>
20786 case 'event-listeners': // TODO
20787 case 'chart': // TODO
20788 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
20789 else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]);
20790 textp = ""; textpidx = 0; textR = [];
20791 break;
20792
20793 case 'scientific-number': // TODO: <number:scientific-number>
20794 break;
20795 case 'currency-symbol': // TODO: <number:currency-symbol>
20796 break;
20797 case 'currency-style': // TODO: <number:currency-style>
20798 break;
20799 case 'number-style': // 16.27.2 <number:number-style>
20800 case 'percentage-style': // 16.27.9 <number:percentage-style>
20801 case 'date-style': // 16.27.10 <number:date-style>
20802 case 'time-style': // 16.27.18 <number:time-style>
20803 if(Rn[1]==='/'){
20804 number_format_map[NFtag.name] = NF;
20805 if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
20806 } else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
20807 NF = "";
20808 NFtag = parsexmltag(Rn[0], false);
20809 state.push([Rn[3], true]);
20810 } break;
20811
20812 case 'script': break; // 3.13 <office:script>
20813 case 'libraries': break; // TODO: <ooo:libraries>
20814 case 'automatic-styles': break; // 3.15.3 <office:automatic-styles>
20815
20816 case 'default-style': // TODO: <style:default-style>
20817 case 'page-layout': break; // TODO: <style:page-layout>
20818 case 'style': // 16.2 <style:style>
20819 break;
20820 case 'map': break; // 16.3 <style:map>
20821 case 'font-face': break; // 16.21 <style:font-face>
20822
20823 case 'paragraph-properties': break; // 17.6 <style:paragraph-properties>
20824 case 'table-properties': break; // 17.15 <style:table-properties>
20825 case 'table-column-properties': break; // 17.16 <style:table-column-properties>
20826 case 'table-row-properties': break; // 17.17 <style:table-row-properties>
20827 case 'table-cell-properties': break; // 17.18 <style:table-cell-properties>
20828
20829 case 'number': // 16.27.3 <number:number>
20830 switch(state[state.length-1][0]) {
20831 case 'time-style':
20832 case 'date-style':
20833 tag = parsexmltag(Rn[0], false);
20834 NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
20835 } break;
20836
20837 case 'fraction': break; // TODO 16.27.6 <number:fraction>
20838
20839 case 'day': // 16.27.11 <number:day>
20840 case 'month': // 16.27.12 <number:month>
20841 case 'year': // 16.27.13 <number:year>
20842 case 'era': // 16.27.14 <number:era>
20843 case 'day-of-week': // 16.27.15 <number:day-of-week>
20844 case 'week-of-year': // 16.27.16 <number:week-of-year>
20845 case 'quarter': // 16.27.17 <number:quarter>
20846 case 'hours': // 16.27.19 <number:hours>
20847 case 'minutes': // 16.27.20 <number:minutes>
20848 case 'seconds': // 16.27.21 <number:seconds>
20849 case 'am-pm': // 16.27.22 <number:am-pm>
20850 switch(state[state.length-1][0]) {
20851 case 'time-style':
20852 case 'date-style':
20853 tag = parsexmltag(Rn[0], false);
20854 NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
20855 } break;
20856
20857 case 'boolean-style': break; // 16.27.23 <number:boolean-style>
20858 case 'boolean': break; // 16.27.24 <number:boolean>
20859 case 'text-style': break; // 16.27.25 <number:text-style>
20860 case 'text': // 16.27.26 <number:text>
20861 if(Rn[0].slice(-2) === "/>") break;
20862 else if(Rn[1]==="/") switch(state[state.length-1][0]) {
20863 case 'number-style':
20864 case 'date-style':
20865 case 'time-style':
20866 NF += str.slice(pidx, Rn.index);
20867 break;
20868 }
20869 else pidx = Rn.index + Rn[0].length;
20870 break;
20871
20872 case 'named-range': // 9.4.12 <table:named-range>
20873 tag = parsexmltag(Rn[0], false);
20874 _Ref = ods_to_csf_3D(tag['cell-range-address']);
20875 var nrange = ({Name:tag.name, Ref:_Ref[0] + '!' + _Ref[1]}/*:any*/);
20876 if(intable) nrange.Sheet = SheetNames.length;
20877 WB.Names.push(nrange);
20878 break;
20879
20880 case 'text-content': break; // 16.27.27 <number:text-content>
20881 case 'text-properties': break; // 16.27.27 <style:text-properties>
20882 case 'embedded-text': break; // 16.27.4 <number:embedded-text>
20883
20884 case 'body': case '电子表格': break; // 3.3 16.9.6 19.726.3
20885
20886 case 'forms': break; // 12.25.2 13.2
20887 case 'table-column': break; // 9.1.6 <table:table-column>
20888 case 'table-header-rows': break; // 9.1.7 <table:table-header-rows>
20889 case 'table-rows': break; // 9.1.12 <table:table-rows>
20890 /* TODO: outline levels */
20891 case 'table-column-group': break; // 9.1.10 <table:table-column-group>
20892 case 'table-header-columns': break; // 9.1.11 <table:table-header-columns>
20893 case 'table-columns': break; // 9.1.12 <table:table-columns>
20894
20895 case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
20896
20897 case 'graphic-properties': break; // 17.21 <style:graphic-properties>
20898 case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
20899 case 'named-expressions': break; // 9.4.11 <table:named-expressions>
20900 case 'label-range': break; // 9.4.9 <table:label-range>
20901 case 'label-ranges': break; // 9.4.10 <table:label-ranges>
20902 case 'named-expression': break; // 9.4.13 <table:named-expression>
20903 case 'sort': break; // 9.4.19 <table:sort>
20904 case 'sort-by': break; // 9.4.20 <table:sort-by>
20905 case 'sort-groups': break; // 9.4.22 <table:sort-groups>
20906
20907 case 'tab': break; // 6.1.4 <text:tab>
20908 case 'line-break': break; // 6.1.5 <text:line-break>
20909 case 'span': break; // 6.1.7 <text:span>
20910 case 'p': case '文本串': // 5.1.3 <text:p>
20911 if(['master-styles'].indexOf(state[state.length-1][0]) > -1) break;
20912 if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) {
20913 var ptp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
20914 textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0];
20915 } else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
20916 break; // <text:p>
20917 case 's': break; // <text:s>
20918
20919 case 'database-range': // 9.4.15 <table:database-range>
20920 if(Rn[1]==='/') break;
20921 try {
20922 _Ref = ods_to_csf_3D(parsexmltag(Rn[0])['target-range-address']);
20923 Sheets[_Ref[0]]['!autofilter'] = { ref:_Ref[1] };
20924 } catch(e) {/* empty */}
20925 break;
20926
20927 case 'date': break; // <*:date>
20928
20929 case 'object': break; // 10.4.6.2 <draw:object>
20930 case 'title': case '标题': break; // <*:title> OR <uof:标题>
20931 case 'desc': break; // <*:desc>
20932 case 'binary-data': break; // 10.4.5 TODO: b64 blob
20933
20934 /* 9.2 Advanced Tables */
20935 case 'table-source': break; // 9.2.6
20936 case 'scenario': break; // 9.2.6
20937
20938 case 'iteration': break; // 9.4.3 <table:iteration>
20939 case 'content-validations': break; // 9.4.4 <table:
20940 case 'content-validation': break; // 9.4.5 <table:
20941 case 'help-message': break; // 9.4.6 <table:
20942 case 'error-message': break; // 9.4.7 <table:
20943 case 'database-ranges': break; // 9.4.14 <table:database-ranges>
20944 case 'filter': break; // 9.5.2 <table:filter>
20945 case 'filter-and': break; // 9.5.3 <table:filter-and>
20946 case 'filter-or': break; // 9.5.4 <table:filter-or>
20947 case 'filter-condition': break; // 9.5.5 <table:filter-condition>
20948
20949 case 'list-level-style-bullet': break; // 16.31 <text:
20950 case 'list-level-style-number': break; // 16.32 <text:
20951 case 'list-level-properties': break; // 17.19 <style:
20952
20953 /* 7.3 Document Fields */
20954 case 'sender-firstname': // 7.3.6.2
20955 case 'sender-lastname': // 7.3.6.3
20956 case 'sender-initials': // 7.3.6.4
20957 case 'sender-title': // 7.3.6.5
20958 case 'sender-position': // 7.3.6.6
20959 case 'sender-email': // 7.3.6.7
20960 case 'sender-phone-private': // 7.3.6.8
20961 case 'sender-fax': // 7.3.6.9
20962 case 'sender-company': // 7.3.6.10
20963 case 'sender-phone-work': // 7.3.6.11
20964 case 'sender-street': // 7.3.6.12
20965 case 'sender-city': // 7.3.6.13
20966 case 'sender-postal-code': // 7.3.6.14
20967 case 'sender-country': // 7.3.6.15
20968 case 'sender-state-or-province': // 7.3.6.16
20969 case 'author-name': // 7.3.7.1
20970 case 'author-initials': // 7.3.7.2
20971 case 'chapter': // 7.3.8
20972 case 'file-name': // 7.3.9
20973 case 'template-name': // 7.3.9
20974 case 'sheet-name': // 7.3.9
20975 break;
20976
20977 case 'event-listener':
20978 break;
20979 /* TODO: FODS Properties */
20980 case 'initial-creator':
20981 case 'creation-date':
20982 case 'print-date':
20983 case 'generator':
20984 case 'document-statistic':
20985 case 'user-defined':
20986 case 'editing-duration':
20987 case 'editing-cycles':
20988 break;
20989
20990 /* TODO: FODS Config */
20991 case 'config-item':
20992 break;
20993
20994 /* TODO: style tokens */
20995 case 'page-number': break; // TODO <text:page-number>
20996 case 'page-count': break; // TODO <text:page-count>
20997 case 'time': break; // TODO <text:time>
20998
20999 /* 9.3 Advanced Table Cells */
21000 case 'cell-range-source': break; // 9.3.1 <table:
21001 case 'detective': break; // 9.3.2 <table:
21002 case 'operation': break; // 9.3.3 <table:
21003 case 'highlighted-range': break; // 9.3.4 <table:
21004
21005 /* 9.6 Data Pilot Tables <table: */
21006 case 'data-pilot-table': // 9.6.3
21007 case 'source-cell-range': // 9.6.5
21008 case 'source-service': // 9.6.6
21009 case 'data-pilot-field': // 9.6.7
21010 case 'data-pilot-level': // 9.6.8
21011 case 'data-pilot-subtotals': // 9.6.9
21012 case 'data-pilot-subtotal': // 9.6.10
21013 case 'data-pilot-members': // 9.6.11
21014 case 'data-pilot-member': // 9.6.12
21015 case 'data-pilot-display-info': // 9.6.13
21016 case 'data-pilot-sort-info': // 9.6.14
21017 case 'data-pilot-layout-info': // 9.6.15
21018 case 'data-pilot-field-reference': // 9.6.16
21019 case 'data-pilot-groups': // 9.6.17
21020 case 'data-pilot-group': // 9.6.18
21021 case 'data-pilot-group-member': // 9.6.19
21022 break;
21023
21024 /* 10.3 Drawing Shapes */
21025 case 'rect': // 10.3.2
21026 break;
21027
21028 /* 14.6 DDE Connections */
21029 case 'dde-connection-decls': // 14.6.2 <text:
21030 case 'dde-connection-decl': // 14.6.3 <text:
21031 case 'dde-link': // 14.6.4 <table:
21032 case 'dde-source': // 14.6.5 <office:
21033 break;
21034
21035 case 'properties': break; // 13.7 <form:properties>
21036 case 'property': break; // 13.8 <form:property>
21037
21038 case 'a': // 6.1.8 hyperlink
21039 if(Rn[1]!== '/') {
21040 atag = parsexmltag(Rn[0], false);
21041 if(!atag.href) break;
21042 atag.Target = unescapexml(atag.href); delete atag.href;
21043 if(atag.Target.charAt(0) == "#" && atag.Target.indexOf(".") > -1) {
21044 _Ref = ods_to_csf_3D(atag.Target.slice(1));
21045 atag.Target = "#" + _Ref[0] + "!" + _Ref[1];
21046 } else if(atag.Target.match(/^\.\.[\\\/]/)) atag.Target = atag.Target.slice(3);
21047 }
21048 break;
21049
21050 /* non-standard */
21051 case 'table-protection': break;
21052 case 'data-pilot-grand-total': break; // <table:
21053 case 'office-document-common-attrs': break; // bare
21054 default: switch(Rn[2]) {
21055 case 'dc:': // TODO: properties
21056 case 'calcext:': // ignore undocumented extensions
21057 case 'loext:': // ignore undocumented extensions
21058 case 'ooo:': // ignore undocumented extensions
21059 case 'chartooo:': // ignore undocumented extensions
21060 case 'draw:': // TODO: drawing
21061 case 'style:': // TODO: styles
21062 case 'chart:': // TODO: charts
21063 case 'form:': // TODO: forms
21064 case 'uof:': // TODO: uof
21065 case '表:': // TODO: uof
21066 case '字:': // TODO: uof
21067 break;
21068 default: if(opts.WTF) throw new Error(Rn);
21069 }
21070 }
21071 var out/*:Workbook*/ = ({
21072 Sheets: Sheets,
21073 SheetNames: SheetNames,
21074 Workbook: WB
21075 }/*:any*/);
21076 if(opts.bookSheets) delete /*::(*/out/*:: :any)*/.Sheets;
21077 return out;
21078 };
21079})();
21080
21081function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
21082 opts = opts || ({}/*:any*/);
21083 if(safegetzipfile(zip, 'META-INF/manifest.xml')) parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
21084 var content = getzipstr(zip, 'content.xml');
21085 if(!content) throw new Error("Missing content.xml in ODS / UOF file");
21086 var wb = parse_content_xml(utf8read(content), opts);
21087 if(safegetzipfile(zip, 'meta.xml')) wb.Props = parse_core_props(getzipdata(zip, 'meta.xml'));
21088 return wb;
21089}
21090function parse_fods(data/*:string*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
21091 return parse_content_xml(data, opts);
21092}
21093
21094/* OpenDocument */
21095var write_styles_ods/*:{(wb:any, opts:any):string}*/ = (function() {
21096 var master_styles = '<office:master-styles>'
21097 + '<style:master-page style:name="mp1" style:page-layout-name="mp1">'
21098 + '<style:header/>'
21099 + '<style:header-left style:display="false"/>'
21100 + '<style:footer/>'
21101 + '<style:footer-left style:display="false"/>'
21102 + '</style:master-page>'
21103 + '</office:master-styles>';
21104
21105 var payload = '<office:document-styles ' + wxt_helper({
21106 'xmlns:office': "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
21107 'xmlns:table': "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
21108 'xmlns:style': "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
21109 'xmlns:text': "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
21110 'xmlns:draw': "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
21111 'xmlns:fo': "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
21112 'xmlns:xlink': "http://www.w3.org/1999/xlink",
21113 'xmlns:dc': "http://purl.org/dc/elements/1.1/",
21114 'xmlns:number': "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
21115 'xmlns:svg': "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
21116 'xmlns:of': "urn:oasis:names:tc:opendocument:xmlns:of:1.2",
21117 'office:version': "1.2"
21118 }) + '>' + master_styles + '</office:document-styles>';
21119
21120 return function wso(/*::wb, opts*/) {
21121 return XML_HEADER + payload;
21122 };
21123})();
21124var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
21125 /* 6.1.2 White Space Characters */
21126 var write_text_p = function(text/*:string*/)/*:string*/ {
21127 return escapexml(text)
21128 .replace(/ +/g, function($$){return '<text:s text:c="'+$$.length+'"/>';})
21129 .replace(/\t/g, "<text:tab/>")
21130 .replace(/\n/g, "</text:p><text:p>")
21131 .replace(/^ /, "<text:s/>").replace(/ $/, "<text:s/>");
21132 };
21133
21134 var null_cell_xml = ' <table:table-cell />\n';
21135 var covered_cell_xml = ' <table:covered-table-cell/>\n';
21136 var write_ws = function(ws, wb/*:Workbook*/, i/*:number*//*::, opts*/)/*:string*/ {
21137 /* Section 9 Tables */
21138 var o/*:Array<string>*/ = [];
21139 o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="ta1">\n');
21140 var R=0,C=0, range = decode_range(ws['!ref']||"A1");
21141 var marr/*:Array<Range>*/ = ws['!merges'] || [], mi = 0;
21142 var dense = Array.isArray(ws);
21143 if(ws["!cols"]) {
21144 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');
21145 }
21146 var H = "", ROWS = ws["!rows"]||[];
21147 for(R = 0; R < range.s.r; ++R) {
21148 H = ROWS[R] ? ' table:style-name="ro' + ROWS[R].ods + '"' : "";
21149 o.push(' <table:table-row' + H + '></table:table-row>\n');
21150 }
21151 for(; R <= range.e.r; ++R) {
21152 H = ROWS[R] ? ' table:style-name="ro' + ROWS[R].ods + '"' : "";
21153 o.push(' <table:table-row' + H + '>\n');
21154 for(C=0; C < range.s.c; ++C) o.push(null_cell_xml);
21155 for(; C <= range.e.c; ++C) {
21156 var skip = false, ct = {}, textp = "";
21157 for(mi = 0; mi != marr.length; ++mi) {
21158 if(marr[mi].s.c > C) continue;
21159 if(marr[mi].s.r > R) continue;
21160 if(marr[mi].e.c < C) continue;
21161 if(marr[mi].e.r < R) continue;
21162 if(marr[mi].s.c != C || marr[mi].s.r != R) skip = true;
21163 ct['table:number-columns-spanned'] = (marr[mi].e.c - marr[mi].s.c + 1);
21164 ct['table:number-rows-spanned'] = (marr[mi].e.r - marr[mi].s.r + 1);
21165 break;
21166 }
21167 if(skip) { o.push(covered_cell_xml); continue; }
21168 var ref = encode_cell({r:R, c:C}), cell = dense ? (ws[R]||[])[C]: ws[ref];
21169 if(cell && cell.f) {
21170 ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f));
21171 if(cell.F) {
21172 if(cell.F.slice(0, ref.length) == ref) {
21173 var _Fref = decode_range(cell.F);
21174 ct['table:number-matrix-columns-spanned'] = (_Fref.e.c - _Fref.s.c + 1);
21175 ct['table:number-matrix-rows-spanned'] = (_Fref.e.r - _Fref.s.r + 1);
21176 }
21177 }
21178 }
21179 if(!cell) { o.push(null_cell_xml); continue; }
21180 switch(cell.t) {
21181 case 'b':
21182 textp = (cell.v ? 'TRUE' : 'FALSE');
21183 ct['office:value-type'] = "boolean";
21184 ct['office:boolean-value'] = (cell.v ? 'true' : 'false');
21185 break;
21186 case 'n':
21187 textp = (cell.w||String(cell.v||0));
21188 ct['office:value-type'] = "float";
21189 ct['office:value'] = (cell.v||0);
21190 break;
21191 case 's': case 'str':
21192 textp = cell.v == null ? "" : cell.v;
21193 ct['office:value-type'] = "string";
21194 break;
21195 case 'd':
21196 textp = (cell.w||(parseDate(cell.v).toISOString()));
21197 ct['office:value-type'] = "date";
21198 ct['office:date-value'] = (parseDate(cell.v).toISOString());
21199 ct['table:style-name'] = "ce1";
21200 break;
21201 //case 'e':
21202 default: o.push(null_cell_xml); continue;
21203 }
21204 var text_p = write_text_p(textp);
21205 if(cell.l && cell.l.Target) {
21206 var _tgt = cell.l.Target;
21207 _tgt = _tgt.charAt(0) == "#" ? "#" + csf_to_ods_3D(_tgt.slice(1)) : _tgt;
21208 // TODO: choose correct parent path format based on link delimiters
21209 if(_tgt.charAt(0) != "#" && !_tgt.match(/^\w+:/)) _tgt = '../' + _tgt;
21210 text_p = writextag('text:a', text_p, {'xlink:href': _tgt.replace(/&/g, "&amp;")});
21211 }
21212 o.push(' ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n');
21213 }
21214 o.push(' </table:table-row>\n');
21215 }
21216 o.push(' </table:table>\n');
21217 return o.join("");
21218 };
21219
21220 var write_automatic_styles_ods = function(o/*:Array<string>*/, wb) {
21221 o.push(' <office:automatic-styles>\n');
21222
21223 o.push(' <number:date-style style:name="N37" number:automatic-order="true">\n');
21224 o.push(' <number:month number:style="long"/>\n');
21225 o.push(' <number:text>/</number:text>\n');
21226 o.push(' <number:day number:style="long"/>\n');
21227 o.push(' <number:text>/</number:text>\n');
21228 o.push(' <number:year/>\n');
21229 o.push(' </number:date-style>\n');
21230
21231 /* column styles */
21232 var cidx = 0;
21233 wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
21234 if(!ws) return;
21235 if(ws["!cols"]) {
21236 for(var C = 0; C < ws["!cols"].length; ++C) if(ws["!cols"][C]) {
21237 var colobj = ws["!cols"][C];
21238 if(colobj.width == null && colobj.wpx == null && colobj.wch == null) continue;
21239 process_col(colobj);
21240 colobj.ods = cidx;
21241 var w = ws["!cols"][C].wpx + "px";
21242 o.push(' <style:style style:name="co' + cidx + '" style:family="table-column">\n');
21243 o.push(' <style:table-column-properties fo:break-before="auto" style:column-width="' + w + '"/>\n');
21244 o.push(' </style:style>\n');
21245 ++cidx;
21246 }
21247 }
21248 });
21249
21250 /* row styles */
21251 var ridx = 0;
21252 wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
21253 if(!ws) return;
21254 if(ws["!rows"]) {
21255 for(var R = 0; R < ws["!rows"].length; ++R) if(ws["!rows"][R]) {
21256 ws["!rows"][R].ods = ridx;
21257 var h = ws["!rows"][R].hpx + "px";
21258 o.push(' <style:style style:name="ro' + ridx + '" style:family="table-row">\n');
21259 o.push(' <style:table-row-properties fo:break-before="auto" style:row-height="' + h + '"/>\n');
21260 o.push(' </style:style>\n');
21261 ++ridx;
21262 }
21263 }
21264 });
21265
21266 /* table */
21267 o.push(' <style:style style:name="ta1" style:family="table" style:master-page-name="mp1">\n');
21268 o.push(' <style:table-properties table:display="true" style:writing-mode="lr-tb"/>\n');
21269 o.push(' </style:style>\n');
21270
21271 /* table cells, text */
21272 o.push(' <style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N37"/>\n');
21273
21274 /* page-layout */
21275
21276 o.push(' </office:automatic-styles>\n');
21277 };
21278
21279 return function wcx(wb, opts) {
21280 var o = [XML_HEADER];
21281 /* 3.1.3.2 */
21282 var attr = wxt_helper({
21283 'xmlns:office': "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
21284 'xmlns:table': "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
21285 'xmlns:style': "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
21286 'xmlns:text': "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
21287 'xmlns:draw': "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
21288 'xmlns:fo': "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
21289 'xmlns:xlink': "http://www.w3.org/1999/xlink",
21290 'xmlns:dc': "http://purl.org/dc/elements/1.1/",
21291 'xmlns:meta': "urn:oasis:names:tc:opendocument:xmlns:meta:1.0",
21292 'xmlns:number': "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
21293 'xmlns:presentation': "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0",
21294 'xmlns:svg': "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
21295 'xmlns:chart': "urn:oasis:names:tc:opendocument:xmlns:chart:1.0",
21296 'xmlns:dr3d': "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0",
21297 'xmlns:math': "http://www.w3.org/1998/Math/MathML",
21298 'xmlns:form': "urn:oasis:names:tc:opendocument:xmlns:form:1.0",
21299 'xmlns:script': "urn:oasis:names:tc:opendocument:xmlns:script:1.0",
21300 'xmlns:ooo': "http://openoffice.org/2004/office",
21301 'xmlns:ooow': "http://openoffice.org/2004/writer",
21302 'xmlns:oooc': "http://openoffice.org/2004/calc",
21303 'xmlns:dom': "http://www.w3.org/2001/xml-events",
21304 'xmlns:xforms': "http://www.w3.org/2002/xforms",
21305 'xmlns:xsd': "http://www.w3.org/2001/XMLSchema",
21306 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance",
21307 'xmlns:sheet': "urn:oasis:names:tc:opendocument:sh33tjs:1.0",
21308 'xmlns:rpt': "http://openoffice.org/2005/report",
21309 'xmlns:of': "urn:oasis:names:tc:opendocument:xmlns:of:1.2",
21310 'xmlns:xhtml': "http://www.w3.org/1999/xhtml",
21311 'xmlns:grddl': "http://www.w3.org/2003/g/data-view#",
21312 'xmlns:tableooo': "http://openoffice.org/2009/table",
21313 'xmlns:drawooo': "http://openoffice.org/2010/draw",
21314 'xmlns:calcext': "urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0",
21315 'xmlns:loext': "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0",
21316 'xmlns:field': "urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0",
21317 'xmlns:formx': "urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0",
21318 'xmlns:css3t': "http://www.w3.org/TR/css3-text/",
21319 'office:version': "1.2"
21320 });
21321
21322 var fods = wxt_helper({
21323 'xmlns:config': "urn:oasis:names:tc:opendocument:xmlns:config:1.0",
21324 'office:mimetype': "application/vnd.oasis.opendocument.spreadsheet"
21325 });
21326
21327 if(opts.bookType == "fods") {
21328 o.push('<office:document' + attr + fods + '>\n');
21329 o.push(write_meta_ods().replace(/office:document-meta/g, "office:meta"));
21330 // TODO: settings (equiv of settings.xml for ODS)
21331 } else o.push('<office:document-content' + attr + '>\n');
21332 // o.push(' <office:scripts/>\n');
21333 write_automatic_styles_ods(o, wb);
21334 o.push(' <office:body>\n');
21335 o.push(' <office:spreadsheet>\n');
21336 for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts));
21337 o.push(' </office:spreadsheet>\n');
21338 o.push(' </office:body>\n');
21339 if(opts.bookType == "fods") o.push('</office:document>');
21340 else o.push('</office:document-content>');
21341 return o.join("");
21342 };
21343})();
21344
21345function write_ods(wb/*:any*/, opts/*:any*/) {
21346 if(opts.bookType == "fods") return write_content_ods(wb, opts);
21347
21348 var zip = zip_new();
21349 var f = "";
21350
21351 var manifest/*:Array<Array<string> >*/ = [];
21352 var rdf/*:Array<[string, string]>*/ = [];
21353
21354 /* Part 3 Section 3.3 MIME Media Type */
21355 f = "mimetype";
21356 zip_add_file(zip, f, "application/vnd.oasis.opendocument.spreadsheet");
21357
21358 /* Part 1 Section 2.2 Documents */
21359 f = "content.xml";
21360 zip_add_file(zip, f, write_content_ods(wb, opts));
21361 manifest.push([f, "text/xml"]);
21362 rdf.push([f, "ContentFile"]);
21363
21364 /* TODO: these are hard-coded styles to satiate excel */
21365 f = "styles.xml";
21366 zip_add_file(zip, f, write_styles_ods(wb, opts));
21367 manifest.push([f, "text/xml"]);
21368 rdf.push([f, "StylesFile"]);
21369
21370 /* TODO: this is hard-coded to satiate excel */
21371 f = "meta.xml";
21372 zip_add_file(zip, f, XML_HEADER + write_meta_ods(/*::wb, opts*/));
21373 manifest.push([f, "text/xml"]);
21374 rdf.push([f, "MetadataFile"]);
21375
21376 /* Part 3 Section 6 Metadata Manifest File */
21377 f = "manifest.rdf";
21378 zip_add_file(zip, f, write_rdf(rdf/*, opts*/));
21379 manifest.push([f, "application/rdf+xml"]);
21380
21381 /* Part 3 Section 4 Manifest File */
21382 f = "META-INF/manifest.xml";
21383 zip_add_file(zip, f, write_manifest(manifest/*, opts*/));
21384
21385 return zip;
21386}
21387
21388function write_sheet_index(wb/*:Workbook*/, sheet/*:?string*/)/*:number*/ {
21389 if(!sheet) return 0;
21390 var idx = wb.SheetNames.indexOf(sheet);
21391 if(idx == -1) throw new Error("Sheet not found: " + sheet);
21392 return idx;
21393}
21394
21395function write_obj_str(factory/*:WriteObjStrFactory*/) {
21396 return function write_str(wb/*:Workbook*/, o/*:WriteOpts*/)/*:string*/ {
21397 var idx = write_sheet_index(wb, o.sheet);
21398 return factory.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb);
21399 };
21400}
21401
21402var write_htm_str = write_obj_str(HTML_);
21403var write_csv_str = write_obj_str({from_sheet:sheet_to_csv});
21404var write_slk_str = write_obj_str(typeof SYLK !== "undefined" ? SYLK : {});
21405var write_dif_str = write_obj_str(typeof DIF !== "undefined" ? DIF : {});
21406var write_prn_str = write_obj_str(typeof PRN !== "undefined" ? PRN : {});
21407var write_rtf_str = write_obj_str(typeof RTF !== "undefined" ? RTF : {});
21408var write_txt_str = write_obj_str({from_sheet:sheet_to_txt});
21409var write_dbf_buf = write_obj_str(typeof DBF !== "undefined" ? DBF : {});
21410var write_eth_str = write_obj_str(typeof ETH !== "undefined" ? ETH : {});
21411var write_wk1_buf = write_obj_str(typeof WK_ !== "undefined" ? {from_sheet:WK_.sheet_to_wk1} : {});
21412
21413function fix_opts_func(defaults/*:Array<Array<any> >*/)/*:{(o:any):void}*/ {
21414 return function fix_opts(opts) {
21415 for(var i = 0; i != defaults.length; ++i) {
21416 var d = defaults[i];
21417 if(opts[d[0]] === undefined) opts[d[0]] = d[1];
21418 if(d[2] === 'n') opts[d[0]] = Number(opts[d[0]]);
21419 }
21420 };
21421}
21422
21423var fix_read_opts = function(opts) {
21424fix_opts_func([
21425 ['cellNF', false], /* emit cell number format string as .z */
21426 ['cellHTML', true], /* emit html string as .h */
21427 ['cellFormula', true], /* emit formulae as .f */
21428 ['cellStyles', false], /* emits style/theme as .s */
21429 ['cellText', true], /* emit formatted text as .w */
21430 ['cellDates', false], /* emit date cells with type `d` */
21431
21432 ['sheetStubs', false], /* emit empty cells */
21433 ['sheetRows', 0, 'n'], /* read n rows (0 = read all rows) */
21434
21435 ['bookDeps', false], /* parse calculation chains */
21436 ['bookSheets', false], /* only try to get sheet names (no Sheets) */
21437 ['bookProps', false], /* only try to get properties (no Sheets) */
21438 ['bookFiles', false], /* include raw file structure (keys, files, cfb) */
21439 ['bookVBA', false], /* include vba raw data (vbaraw) */
21440
21441 ['password',''], /* password */
21442 ['WTF', false] /* WTF mode (throws errors) */
21443])(opts);
21444};
21445
21446var fix_write_opts = fix_opts_func([
21447 ['cellDates', false], /* write date cells with type `d` */
21448
21449 ['bookSST', false], /* Generate Shared String Table */
21450
21451 ['bookType', 'xlsx'], /* Type of workbook (xlsx/m/b) */
21452
21453 ['compression', false], /* Use file compression */
21454
21455 ['WTF', false] /* WTF mode (throws errors) */
21456]);
21457function get_sheet_type(n/*:string*/)/*:string*/ {
21458 if(RELS.WS.indexOf(n) > -1) return "sheet";
21459 if(RELS.CS && n == RELS.CS) return "chart";
21460 if(RELS.DS && n == RELS.DS) return "dialog";
21461 if(RELS.MS && n == RELS.MS) return "macro";
21462 return (n && n.length) ? n : "sheet";
21463}
21464function safe_parse_wbrels(wbrels, sheets) {
21465 if(!wbrels) return 0;
21466 try {
21467 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)]; });
21468 } catch(e) { return null; }
21469 return !wbrels || wbrels.length === 0 ? null : wbrels;
21470}
21471
21472function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/*:number*/, sheetRels, sheets, stype/*:string*/, opts, wb, themes, styles) {
21473 try {
21474 sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
21475 var data = getzipdata(zip, path);
21476 var _ws;
21477 switch(stype) {
21478 case 'sheet': _ws = parse_ws(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
21479 case 'chart': _ws = parse_cs(data, path, idx, opts, sheetRels[sheet], wb, themes, styles);
21480 if(!_ws || !_ws['!drawel']) break;
21481 var dfile = resolve_path(_ws['!drawel'].Target, path);
21482 var drelsp = get_rels_path(dfile);
21483 var draw = parse_drawing(getzipstr(zip, dfile, true), parse_rels(getzipstr(zip, drelsp, true), dfile));
21484 var chartp = resolve_path(draw, dfile);
21485 var crelsp = get_rels_path(chartp);
21486 _ws = parse_chart(getzipstr(zip, chartp, true), chartp, opts, parse_rels(getzipstr(zip, crelsp, true), chartp), wb, _ws);
21487 break;
21488 case 'macro': _ws = parse_ms(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
21489 case 'dialog': _ws = parse_ds(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
21490 default: throw new Error("Unrecognized sheet type " + stype);
21491 }
21492 sheets[sheet] = _ws;
21493
21494 /* scan rels for comments */
21495 var comments = [];
21496 if(sheetRels && sheetRels[sheet]) keys(sheetRels[sheet]).forEach(function(n) {
21497 if(sheetRels[sheet][n].Type == RELS.CMNT) {
21498 var dfile = resolve_path(sheetRels[sheet][n].Target, path);
21499 comments = parse_cmnt(getzipdata(zip, dfile, true), dfile, opts);
21500 if(!comments || !comments.length) return;
21501 sheet_insert_comments(_ws, comments);
21502 }
21503 });
21504 } catch(e) { if(opts.WTF) throw e; }
21505}
21506
21507function strip_front_slash(x/*:string*/)/*:string*/ { return x.charAt(0) == '/' ? x.slice(1) : x; }
21508
21509function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
21510 make_ssf(SSF);
21511 opts = opts || {};
21512 fix_read_opts(opts);
21513
21514 /* OpenDocument Part 3 Section 2.2.1 OpenDocument Package */
21515 if(safegetzipfile(zip, 'META-INF/manifest.xml')) return parse_ods(zip, opts);
21516 /* UOC */
21517 if(safegetzipfile(zip, 'objectdata.xml')) return parse_ods(zip, opts);
21518 /* Numbers */
21519 if(safegetzipfile(zip, 'Index/Document.iwa')) throw new Error('Unsupported NUMBERS file');
21520
21521 var entries = zipentries(zip);
21522 var dir = parse_ct((getzipstr(zip, '[Content_Types].xml')/*:?any*/));
21523 var xlsb = false;
21524 var sheets, binname;
21525 if(dir.workbooks.length === 0) {
21526 binname = "xl/workbook.xml";
21527 if(getzipdata(zip,binname, true)) dir.workbooks.push(binname);
21528 }
21529 if(dir.workbooks.length === 0) {
21530 binname = "xl/workbook.bin";
21531 if(!getzipdata(zip,binname,true)) throw new Error("Could not find workbook");
21532 dir.workbooks.push(binname);
21533 xlsb = true;
21534 }
21535 if(dir.workbooks[0].slice(-3) == "bin") xlsb = true;
21536
21537 var themes = ({}/*:any*/);
21538 var styles = ({}/*:any*/);
21539 if(!opts.bookSheets && !opts.bookProps) {
21540 strs = [];
21541 if(dir.sst) try { strs=parse_sst(getzipdata(zip, strip_front_slash(dir.sst)), dir.sst, opts); } catch(e) { if(opts.WTF) throw e; }
21542
21543 if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts);
21544
21545 if(dir.style) styles = parse_sty(getzipdata(zip, strip_front_slash(dir.style)), dir.style, themes, opts);
21546 }
21547
21548 /*var externbooks = */dir.links.map(function(link) {
21549 try {
21550 var rels = parse_rels(getzipstr(zip, get_rels_path(strip_front_slash(link))), link);
21551 return parse_xlink(getzipdata(zip, strip_front_slash(link)), rels, link, opts);
21552 } catch(e) {}
21553 });
21554
21555 var wb = parse_wb(getzipdata(zip, strip_front_slash(dir.workbooks[0])), dir.workbooks[0], opts);
21556
21557 var props = {}, propdata = "";
21558
21559 if(dir.coreprops.length) {
21560 propdata = getzipdata(zip, strip_front_slash(dir.coreprops[0]), true);
21561 if(propdata) props = parse_core_props(propdata);
21562 if(dir.extprops.length !== 0) {
21563 propdata = getzipdata(zip, strip_front_slash(dir.extprops[0]), true);
21564 if(propdata) parse_ext_props(propdata, props, opts);
21565 }
21566 }
21567
21568 var custprops = {};
21569 if(!opts.bookSheets || opts.bookProps) {
21570 if (dir.custprops.length !== 0) {
21571 propdata = getzipstr(zip, strip_front_slash(dir.custprops[0]), true);
21572 if(propdata) custprops = parse_cust_props(propdata, opts);
21573 }
21574 }
21575
21576 var out = ({}/*:any*/);
21577 if(opts.bookSheets || opts.bookProps) {
21578 if(wb.Sheets) sheets = wb.Sheets.map(function pluck(x){ return x.name; });
21579 else if(props.Worksheets && props.SheetNames.length > 0) sheets=props.SheetNames;
21580 if(opts.bookProps) { out.Props = props; out.Custprops = custprops; }
21581 if(opts.bookSheets && typeof sheets !== 'undefined') out.SheetNames = sheets;
21582 if(opts.bookSheets ? out.SheetNames : opts.bookProps) return out;
21583 }
21584 sheets = {};
21585
21586 var deps = {};
21587 if(opts.bookDeps && dir.calcchain) deps=parse_cc(getzipdata(zip, strip_front_slash(dir.calcchain)),dir.calcchain,opts);
21588
21589 var i=0;
21590 var sheetRels = ({}/*:any*/);
21591 var path, relsPath;
21592
21593 {
21594 var wbsheets = wb.Sheets;
21595 props.Worksheets = wbsheets.length;
21596 props.SheetNames = [];
21597 for(var j = 0; j != wbsheets.length; ++j) {
21598 props.SheetNames[j] = wbsheets[j].name;
21599 }
21600 }
21601
21602 var wbext = xlsb ? "bin" : "xml";
21603 var wbrelsi = dir.workbooks[0].lastIndexOf("/");
21604 var wbrelsfile = (dir.workbooks[0].slice(0, wbrelsi+1) + "_rels/" + dir.workbooks[0].slice(wbrelsi+1) + ".rels").replace(/^\//,"");
21605 if(!safegetzipfile(zip, wbrelsfile)) wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
21606 var wbrels = parse_rels(getzipstr(zip, wbrelsfile, true), wbrelsfile);
21607 if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
21608
21609 /* Numbers iOS hack */
21610 var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
21611 wsloop: for(i = 0; i != props.Worksheets; ++i) {
21612 var stype = "sheet";
21613 if(wbrels && wbrels[i]) {
21614 path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
21615 if(!safegetzipfile(zip, path)) path = wbrels[i][1];
21616 if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/.*$/,"") + wbrels[i][1];
21617 stype = wbrels[i][2];
21618 } else {
21619 path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
21620 path = path.replace(/sheet0\./,"sheet.");
21621 }
21622 relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
21623 if(opts && opts.sheets != null) switch(typeof opts.sheets) {
21624 case "number": if(i != opts.sheets) continue wsloop; break;
21625 case "string": if(props.SheetNames[i].toLowerCase() != opts.sheets.toLowerCase()) continue wsloop; break;
21626 default: if(Array.isArray && Array.isArray(opts.sheets)) {
21627 var snjseen = false;
21628 for(var snj = 0; snj != opts.sheets.length; ++snj) {
21629 if(typeof opts.sheets[snj] == "number" && opts.sheets[snj] == i) snjseen=1;
21630 if(typeof opts.sheets[snj] == "string" && opts.sheets[snj].toLowerCase() == props.SheetNames[i].toLowerCase()) snjseen = 1;
21631 }
21632 if(!snjseen) continue wsloop;
21633 }
21634 }
21635 safe_parse_sheet(zip, path, relsPath, props.SheetNames[i], i, sheetRels, sheets, stype, opts, wb, themes, styles);
21636 }
21637
21638 out = ({
21639 Directory: dir,
21640 Workbook: wb,
21641 Props: props,
21642 Custprops: custprops,
21643 Deps: deps,
21644 Sheets: sheets,
21645 SheetNames: props.SheetNames,
21646 Strings: strs,
21647 Styles: styles,
21648 Themes: themes,
21649 SSF: SSF.get_table()
21650 }/*:any*/);
21651 if(opts && opts.bookFiles) {
21652 if(zip.files) {
21653 out.keys = entries;
21654 out.files = zip.files;
21655 } else {
21656 out.keys = [];
21657 out.files = {};
21658 zip.FullPaths.forEach(function(p, idx) {
21659 p = p.replace(/^Root Entry[\/]/, "");
21660 out.keys.push(p);
21661 out.files[p] = zip.FileIndex[idx];
21662 });
21663 }
21664 }
21665 if(opts && opts.bookVBA) {
21666 if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,strip_front_slash(dir.vba[0]),true);
21667 else if(dir.defaults && dir.defaults.bin === CT_VBA) out.vbaraw = getzipdata(zip, 'xl/vbaProject.bin',true);
21668 }
21669 return out;
21670}
21671
21672/* [MS-OFFCRYPTO] 2.1.1 */
21673function parse_xlsxcfb(cfb, _opts/*:?ParseOpts*/)/*:Workbook*/ {
21674 var opts = _opts || {};
21675 var f = 'Workbook', data = CFB.find(cfb, f);
21676 try {
21677 f = '/!DataSpaces/Version';
21678 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
21679 /*var version = */parse_DataSpaceVersionInfo(data.content);
21680
21681 /* 2.3.4.1 */
21682 f = '/!DataSpaces/DataSpaceMap';
21683 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
21684 var dsm = parse_DataSpaceMap(data.content);
21685 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")
21686 throw new Error("ECMA-376 Encrypted file bad " + f);
21687
21688 /* 2.3.4.2 */
21689 f = '/!DataSpaces/DataSpaceInfo/StrongEncryptionDataSpace';
21690 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
21691 var seds = parse_DataSpaceDefinition(data.content);
21692 if(seds.length != 1 || seds[0] != "StrongEncryptionTransform")
21693 throw new Error("ECMA-376 Encrypted file bad " + f);
21694
21695 /* 2.3.4.3 */
21696 f = '/!DataSpaces/TransformInfo/StrongEncryptionTransform/!Primary';
21697 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
21698 /*var hdr = */parse_Primary(data.content);
21699 } catch(e) {}
21700
21701 f = '/EncryptionInfo';
21702 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
21703 var einfo = parse_EncryptionInfo(data.content);
21704
21705 /* 2.3.4.4 */
21706 f = '/EncryptedPackage';
21707 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
21708
21709/*global decrypt_agile */
21710/*:: declare var decrypt_agile:any; */
21711 if(einfo[0] == 0x04 && typeof decrypt_agile !== 'undefined') return decrypt_agile(einfo[1], data.content, opts.password || "", opts);
21712/*global decrypt_std76 */
21713/*:: declare var decrypt_std76:any; */
21714 if(einfo[0] == 0x02 && typeof decrypt_std76 !== 'undefined') return decrypt_std76(einfo[1], data.content, opts.password || "", opts);
21715 throw new Error("File is password-protected");
21716}
21717
21718function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
21719 _shapeid = 1024;
21720 if(opts.bookType == "ods") return write_ods(wb, opts);
21721 if(wb && !wb.SSF) {
21722 wb.SSF = SSF.get_table();
21723 }
21724 if(wb && wb.SSF) {
21725 make_ssf(SSF); SSF.load_table(wb.SSF);
21726 // $FlowIgnore
21727 opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
21728 opts.ssf = wb.SSF;
21729 }
21730 opts.rels = {}; opts.wbrels = {};
21731 opts.Strings = /*::((*/[]/*:: :any):SST)*/; opts.Strings.Count = 0; opts.Strings.Unique = 0;
21732 if(browser_has_Map) opts.revStrings = new Map();
21733 else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; }
21734 var wbext = opts.bookType == "xlsb" ? "bin" : "xml";
21735 var vbafmt = VBAFMTS.indexOf(opts.bookType) > -1;
21736 var ct = new_ct();
21737 fix_write_opts(opts = opts || {});
21738 var zip = zip_new();
21739 var f = "", rId = 0;
21740
21741 opts.cellXfs = [];
21742 get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}});
21743
21744 if(!wb.Props) wb.Props = {};
21745
21746 f = "docProps/core.xml";
21747 zip_add_file(zip, f, write_core_props(wb.Props, opts));
21748 ct.coreprops.push(f);
21749 add_rels(opts.rels, 2, f, RELS.CORE_PROPS);
21750
21751 /*::if(!wb.Props) throw "unreachable"; */
21752 f = "docProps/app.xml";
21753 if(wb.Props && wb.Props.SheetNames){/* empty */}
21754 else if(!wb.Workbook || !wb.Workbook.Sheets) wb.Props.SheetNames = wb.SheetNames;
21755 else {
21756 var _sn = [];
21757 for(var _i = 0; _i < wb.SheetNames.length; ++_i)
21758 if((wb.Workbook.Sheets[_i]||{}).Hidden != 2) _sn.push(wb.SheetNames[_i]);
21759 wb.Props.SheetNames = _sn;
21760 }
21761 wb.Props.Worksheets = wb.Props.SheetNames.length;
21762 zip_add_file(zip, f, write_ext_props(wb.Props, opts));
21763 ct.extprops.push(f);
21764 add_rels(opts.rels, 3, f, RELS.EXT_PROPS);
21765
21766 if(wb.Custprops !== wb.Props && keys(wb.Custprops||{}).length > 0) {
21767 f = "docProps/custom.xml";
21768 zip_add_file(zip, f, write_cust_props(wb.Custprops, opts));
21769 ct.custprops.push(f);
21770 add_rels(opts.rels, 4, f, RELS.CUST_PROPS);
21771 }
21772
21773 for(rId=1;rId <= wb.SheetNames.length; ++rId) {
21774 var wsrels = {'!id':{}};
21775 var ws = wb.Sheets[wb.SheetNames[rId-1]];
21776 var _type = (ws || {})["!type"] || "sheet";
21777 switch(_type) {
21778 case "chart":
21779 /* falls through */
21780 default:
21781 f = "xl/worksheets/sheet" + rId + "." + wbext;
21782 zip_add_file(zip, f, write_ws(rId-1, f, opts, wb, wsrels));
21783 ct.sheets.push(f);
21784 add_rels(opts.wbrels, -1, "worksheets/sheet" + rId + "." + wbext, RELS.WS[0]);
21785 }
21786
21787 if(ws) {
21788 var comments = ws['!comments'];
21789 var need_vml = false;
21790 if(comments && comments.length > 0) {
21791 var cf = "xl/comments" + rId + "." + wbext;
21792 zip_add_file(zip, cf, write_cmnt(comments, cf, opts));
21793 ct.comments.push(cf);
21794 add_rels(wsrels, -1, "../comments" + rId + "." + wbext, RELS.CMNT);
21795 need_vml = true;
21796 }
21797 if(ws['!legacy']) {
21798 if(need_vml) zip_add_file(zip, "xl/drawings/vmlDrawing" + (rId) + ".vml", write_comments_vml(rId, ws['!comments']));
21799 }
21800 delete ws['!comments'];
21801 delete ws['!legacy'];
21802 }
21803
21804 if(wsrels['!id'].rId1) zip_add_file(zip, get_rels_path(f), write_rels(wsrels));
21805 }
21806
21807 if(opts.Strings != null && opts.Strings.length > 0) {
21808 f = "xl/sharedStrings." + wbext;
21809 zip_add_file(zip, f, write_sst(opts.Strings, f, opts));
21810 ct.strs.push(f);
21811 add_rels(opts.wbrels, -1, "sharedStrings." + wbext, RELS.SST);
21812 }
21813
21814 f = "xl/workbook." + wbext;
21815 zip_add_file(zip, f, write_wb(wb, f, opts));
21816 ct.workbooks.push(f);
21817 add_rels(opts.rels, 1, f, RELS.WB);
21818
21819 /* TODO: something more intelligent with themes */
21820
21821 f = "xl/theme/theme1.xml";
21822 zip_add_file(zip, f, write_theme(wb.Themes, opts));
21823 ct.themes.push(f);
21824 add_rels(opts.wbrels, -1, "theme/theme1.xml", RELS.THEME);
21825
21826 /* TODO: something more intelligent with styles */
21827
21828 f = "xl/styles." + wbext;
21829 zip_add_file(zip, f, write_sty(wb, f, opts));
21830 ct.styles.push(f);
21831 add_rels(opts.wbrels, -1, "styles." + wbext, RELS.STY);
21832
21833 if(wb.vbaraw && vbafmt) {
21834 f = "xl/vbaProject.bin";
21835 zip_add_file(zip, f, wb.vbaraw);
21836 ct.vba.push(f);
21837 add_rels(opts.wbrels, -1, "vbaProject.bin", RELS.VBA);
21838 }
21839
21840 zip_add_file(zip, "[Content_Types].xml", write_ct(ct, opts));
21841 zip_add_file(zip, '_rels/.rels', write_rels(opts.rels));
21842 zip_add_file(zip, 'xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));
21843
21844 delete opts.revssf; delete opts.ssf;
21845 return zip;
21846}
21847function firstbyte(f/*:RawData*/,o/*:?TypeOpts*/)/*:Array<number>*/ {
21848 var x = "";
21849 switch((o||{}).type || "base64") {
21850 case 'buffer': return [f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]];
21851 case 'base64': x = Base64.decode(f.slice(0,12)); break;
21852 case 'binary': x = f; break;
21853 case 'array': return [f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]];
21854 default: throw new Error("Unrecognized type " + (o && o.type || "undefined"));
21855 }
21856 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)];
21857}
21858
21859function read_cfb(cfb/*:CFBContainer*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
21860 if(CFB.find(cfb, "EncryptedPackage")) return parse_xlsxcfb(cfb, opts);
21861 return parse_xlscfb(cfb, opts);
21862}
21863
21864function read_zip(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
21865 var zip, d = data;
21866 var o = opts||{};
21867 if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
21868 zip = zip_read(d, o);
21869 return parse_zip(zip, o);
21870}
21871
21872function read_plaintext(data/*:string*/, o/*:ParseOpts*/)/*:Workbook*/ {
21873 var i = 0;
21874 main: while(i < data.length) switch(data.charCodeAt(i)) {
21875 case 0x0A: case 0x0D: case 0x20: ++i; break;
21876 case 0x3C: return parse_xlml(data.slice(i),o);
21877 default: break main;
21878 }
21879 return PRN.to_workbook(data, o);
21880}
21881
21882function read_plaintext_raw(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
21883 var str = "", bytes = firstbyte(data, o);
21884 switch(o.type) {
21885 case 'base64': str = Base64.decode(data); break;
21886 case 'binary': str = data; break;
21887 case 'buffer': str = data.toString('binary'); break;
21888 case 'array': str = cc2str(data); break;
21889 default: throw new Error("Unrecognized type " + o.type);
21890 }
21891 if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str);
21892 return read_plaintext(str, o);
21893}
21894
21895function read_utf16(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
21896 var d = data;
21897 if(o.type == 'base64') d = Base64.decode(d);
21898 d = cptable.utils.decode(1200, d.slice(2), 'str');
21899 o.type = "binary";
21900 return read_plaintext(d, o);
21901}
21902
21903function bstrify(data/*:string*/)/*:string*/ {
21904 return !data.match(/[^\x00-\x7F]/) ? data : utf8write(data);
21905}
21906
21907function read_prn(data, d, o, str) {
21908 if(str) { o.type = "string"; return PRN.to_workbook(data, o); }
21909 return PRN.to_workbook(d, o);
21910}
21911
21912function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
21913 reset_cp();
21914 var o = opts||{};
21915 if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), (o = dup(o), o.type = "array", o));
21916 var d = data, n = [0,0,0,0], str = false;
21917 if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; }
21918 _ssfopts = {};
21919 if(o.dateNF) _ssfopts.dateNF = o.dateNF;
21920 if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
21921 if(o.type == "file") { o.type = has_buf ? "buffer" : "binary"; d = read_binary(data); }
21922 if(o.type == "string") { str = true; o.type = "binary"; o.codepage = 65001; d = bstrify(data); }
21923 if(o.type == 'array' && typeof Uint8Array !== 'undefined' && data instanceof Uint8Array && typeof ArrayBuffer !== 'undefined') {
21924 // $FlowIgnore
21925 var ab=new ArrayBuffer(3), vu=new Uint8Array(ab); vu.foo="bar";
21926 // $FlowIgnore
21927 if(!vu.foo) {o=dup(o); o.type='array'; return readSync(ab2a(d), o);}
21928 }
21929 switch((n = firstbyte(d, o))[0]) {
21930 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;
21931 case 0x09: if(n[1] <= 0x08) return parse_xlscfb(d, o); break;
21932 case 0x3C: return parse_xlml(d, o);
21933 case 0x49:
21934 if(n[1] === 0x49 && n[2] === 0x2a && n[3] === 0x00) throw new Error("TIFF Image File is not a spreadsheet");
21935 if(n[1] === 0x44) return read_wb_ID(d, o);
21936 break;
21937 case 0x54: if(n[1] === 0x41 && n[2] === 0x42 && n[3] === 0x4C) return DIF.to_workbook(d, o); break;
21938 case 0x50: return (n[1] === 0x4B && n[2] < 0x09 && n[3] < 0x09) ? read_zip(d, o) : read_prn(data, d, o, str);
21939 case 0xEF: return n[3] === 0x3C ? parse_xlml(d, o) : read_prn(data, d, o, str);
21940 case 0xFF: if(n[1] === 0xFE) { return read_utf16(d, o); } break;
21941 case 0x00: if(n[1] === 0x00 && n[2] >= 0x02 && n[3] === 0x00) return WK_.to_workbook(d, o); break;
21942 case 0x03: case 0x83: case 0x8B: case 0x8C: return DBF.to_workbook(d, o);
21943 case 0x7B: if(n[1] === 0x5C && n[2] === 0x72 && n[3] === 0x74) return RTF.to_workbook(d, o); break;
21944 case 0x0A: case 0x0D: case 0x20: return read_plaintext_raw(d, o);
21945 case 0x89: if(n[1] === 0x50 && n[2] === 0x4E && n[3] === 0x47) throw new Error("PNG Image File is not a spreadsheet"); break;
21946 }
21947 if(DBF.versions.indexOf(n[0]) > -1 && n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
21948 return read_prn(data, d, o, str);
21949}
21950
21951function readFileSync(filename/*:string*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
21952 var o = opts||{}; o.type = 'file';
21953 return readSync(filename, o);
21954}
21955function write_cfb_ctr(cfb/*:CFBContainer*/, o/*:WriteOpts*/)/*:any*/ {
21956 switch(o.type) {
21957 case "base64": case "binary": break;
21958 case "buffer": case "array": o.type = ""; break;
21959 case "file": return write_dl(o.file, CFB.write(cfb, {type:has_buf ? 'buffer' : ""}));
21960 case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files");
21961 default: throw new Error("Unrecognized type " + o.type);
21962 }
21963 return CFB.write(cfb, o);
21964}
21965
21966/*:: declare var encrypt_agile:any; */
21967function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:any*/ {
21968 var o = dup(opts||{});
21969 var z = write_zip(wb, o);
21970 var oopts = {};
21971 if(o.compression) oopts.compression = 'DEFLATE';
21972 if(o.password) oopts.type = has_buf ? "nodebuffer" : "string";
21973 else switch(o.type) {
21974 case "base64": oopts.type = "base64"; break;
21975 case "binary": oopts.type = "string"; break;
21976 case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files");
21977 case "buffer":
21978 case "file": oopts.type = has_buf ? "nodebuffer" : "string"; break;
21979 default: throw new Error("Unrecognized type " + o.type);
21980 }
21981 var out = z.FullPaths ? CFB.write(z, {fileType:"zip", type: /*::(*/{"nodebuffer": "buffer", "string": "binary"}/*:: :any)*/[oopts.type] || oopts.type}) : z.generate(oopts);
21982/*jshint -W083 */
21983 if(o.password && typeof encrypt_agile !== 'undefined') return write_cfb_ctr(encrypt_agile(out, o.password), o); // eslint-disable-line no-undef
21984/*jshint +W083 */
21985 if(o.type === "file") return write_dl(o.file, out);
21986 return o.type == "string" ? utf8read(/*::(*/out/*:: :any)*/) : out;
21987}
21988
21989function write_cfb_type(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:any*/ {
21990 var o = opts||{};
21991 var cfb/*:CFBContainer*/ = write_xlscfb(wb, o);
21992 return write_cfb_ctr(cfb, o);
21993}
21994
21995function write_string_type(out/*:string*/, opts/*:WriteOpts*/, bom/*:?string*/)/*:any*/ {
21996 if(!bom) bom = "";
21997 var o = bom + out;
21998 switch(opts.type) {
21999 case "base64": return Base64.encode(utf8write(o));
22000 case "binary": return utf8write(o);
22001 case "string": return out;
22002 case "file": return write_dl(opts.file, o, 'utf8');
22003 case "buffer": {
22004 if(has_buf) return Buffer_from(o, 'utf8');
22005 else return write_string_type(o, {type:'binary'}).split("").map(function(c) { return c.charCodeAt(0); });
22006 }
22007 }
22008 throw new Error("Unrecognized type " + opts.type);
22009}
22010
22011function write_stxt_type(out/*:string*/, opts/*:WriteOpts*/)/*:any*/ {
22012 switch(opts.type) {
22013 case "base64": return Base64.encode(out);
22014 case "binary": return out;
22015 case "string": return out; /* override in sheet_to_txt */
22016 case "file": return write_dl(opts.file, out, 'binary');
22017 case "buffer": {
22018 if(has_buf) return Buffer_from(out, 'binary');
22019 else return out.split("").map(function(c) { return c.charCodeAt(0); });
22020 }
22021 }
22022 throw new Error("Unrecognized type " + opts.type);
22023}
22024
22025/* TODO: test consistency */
22026function write_binary_type(out, opts/*:WriteOpts*/)/*:any*/ {
22027 switch(opts.type) {
22028 case "string":
22029 case "base64":
22030 case "binary":
22031 var bstr = "";
22032 // $FlowIgnore
22033 for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]);
22034 return opts.type == 'base64' ? Base64.encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr;
22035 case "file": return write_dl(opts.file, out);
22036 case "buffer": return out;
22037 default: throw new Error("Unrecognized type " + opts.type);
22038 }
22039}
22040
22041function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
22042 reset_cp();
22043 check_wb(wb);
22044 var o = dup(opts||{});
22045 if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; }
22046 if(o.type == "array") { o.type = "binary"; var out/*:string*/ = (writeSync(wb, o)/*:any*/); o.type = "array"; return s2ab(out); }
22047 switch(o.bookType || 'xlsb') {
22048 case 'xml':
22049 case 'xlml': return write_string_type(write_xlml(wb, o), o);
22050 case 'slk':
22051 case 'sylk': return write_string_type(write_slk_str(wb, o), o);
22052 case 'htm':
22053 case 'html': return write_string_type(write_htm_str(wb, o), o);
22054 case 'txt': return write_stxt_type(write_txt_str(wb, o), o);
22055 case 'csv': return write_string_type(write_csv_str(wb, o), o, "\ufeff");
22056 case 'dif': return write_string_type(write_dif_str(wb, o), o);
22057 case 'dbf': return write_binary_type(write_dbf_buf(wb, o), o);
22058 case 'prn': return write_string_type(write_prn_str(wb, o), o);
22059 case 'rtf': return write_string_type(write_rtf_str(wb, o), o);
22060 case 'eth': return write_string_type(write_eth_str(wb, o), o);
22061 case 'fods': return write_string_type(write_ods(wb, o), o);
22062 case 'wk1': return write_binary_type(write_wk1_buf(wb, o), o);
22063 case 'wk3': return write_binary_type(WK_.book_to_wk3(wb, o), o);
22064 case 'biff2': if(!o.biff) o.biff = 2; /* falls through */
22065 case 'biff3': if(!o.biff) o.biff = 3; /* falls through */
22066 case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o);
22067 case 'biff5': if(!o.biff) o.biff = 5; /* falls through */
22068 case 'biff8':
22069 case 'xla':
22070 case 'xls': if(!o.biff) o.biff = 8; return write_cfb_type(wb, o);
22071 case 'xlsx':
22072 case 'xlsm':
22073 case 'xlam':
22074 case 'xlsb':
22075 case 'ods': return write_zip_type(wb, o);
22076 default: throw new Error ("Unrecognized bookType |" + o.bookType + "|");
22077 }
22078}
22079
22080function resolve_book_type(o/*:WriteFileOpts*/) {
22081 if(o.bookType) return;
22082 var _BT = {
22083 "xls": "biff8",
22084 "htm": "html",
22085 "slk": "sylk",
22086 "socialcalc": "eth",
22087 "Sh33tJS": "WTF"
22088 };
22089 var ext = o.file.slice(o.file.lastIndexOf(".")).toLowerCase();
22090 if(ext.match(/^\.[a-z]+$/)) o.bookType = ext.slice(1);
22091 o.bookType = _BT[o.bookType] || o.bookType;
22092}
22093
22094function writeFileSync(wb/*:Workbook*/, filename/*:string*/, opts/*:?WriteFileOpts*/) {
22095 var o = opts||{}; o.type = 'file';
22096 o.file = filename;
22097 resolve_book_type(o);
22098 return writeSync(wb, o);
22099}
22100
22101function writeFileAsync(filename/*:string*/, wb/*:Workbook*/, opts/*:?WriteFileOpts*/, cb/*:?(e?:ErrnoError)=>void*/) {
22102 var o = opts||{}; o.type = 'file';
22103 o.file = filename;
22104 resolve_book_type(o);
22105 o.type = 'buffer';
22106 var _cb = cb; if(!(_cb instanceof Function)) _cb = (opts/*:any*/);
22107 return _fs.writeFile(filename, writeSync(wb, o), _cb);
22108}
22109/*::
22110type MJRObject = {
22111 row: any;
22112 isempty: boolean;
22113};
22114*/
22115function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, header/*:number*/, hdr/*:Array<any>*/, dense/*:boolean*/, o/*:Sheet2JSONOpts*/)/*:MJRObject*/ {
22116 var rr = encode_row(R);
22117 var defval = o.defval, raw = o.raw || !Object.prototype.hasOwnProperty.call(o, "raw");
22118 var isempty = true;
22119 var row/*:any*/ = (header === 1) ? [] : {};
22120 if(header !== 1) {
22121 if(Object.defineProperty) try { Object.defineProperty(row, '__rowNum__', {value:R, enumerable:false}); } catch(e) { row.__rowNum__ = R; }
22122 else row.__rowNum__ = R;
22123 }
22124 if(!dense || sheet[R]) for (var C = r.s.c; C <= r.e.c; ++C) {
22125 var val = dense ? sheet[R][C] : sheet[cols[C] + rr];
22126 if(val === undefined || val.t === undefined) {
22127 if(defval === undefined) continue;
22128 if(hdr[C] != null) { row[hdr[C]] = defval; }
22129 continue;
22130 }
22131 var v = val.v;
22132 switch(val.t){
22133 case 'z': if(v == null) break; continue;
22134 case 'e': v = (v == 0 ? null : void 0); break;
22135 case 's': case 'd': case 'b': case 'n': break;
22136 default: throw new Error('unrecognized type ' + val.t);
22137 }
22138 if(hdr[C] != null) {
22139 if(v == null) {
22140 if(val.t == "e" && v === null) row[hdr[C]] = null;
22141 else if(defval !== undefined) row[hdr[C]] = defval;
22142 else if(raw && v === null) row[hdr[C]] = null;
22143 else continue;
22144 } else {
22145 row[hdr[C]] = raw || (o.rawNumbers && val.t == "n") ? v : format_cell(val,v,o);
22146 }
22147 if(v != null) isempty = false;
22148 }
22149 }
22150 return { row: row, isempty: isempty };
22151}
22152
22153
22154function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) {
22155 if(sheet == null || sheet["!ref"] == null) return [];
22156 var val = {t:'n',v:0}, header = 0, offset = 1, hdr/*:Array<any>*/ = [], v=0, vv="";
22157 var r = {s:{r:0,c:0},e:{r:0,c:0}};
22158 var o = opts || {};
22159 var range = o.range != null ? o.range : sheet["!ref"];
22160 if(o.header === 1) header = 1;
22161 else if(o.header === "A") header = 2;
22162 else if(Array.isArray(o.header)) header = 3;
22163 else if(o.header == null) header = 0;
22164 switch(typeof range) {
22165 case 'string': r = safe_decode_range(range); break;
22166 case 'number': r = safe_decode_range(sheet["!ref"]); r.s.r = range; break;
22167 default: r = range;
22168 }
22169 if(header > 0) offset = 0;
22170 var rr = encode_row(r.s.r);
22171 var cols/*:Array<string>*/ = [];
22172 var out/*:Array<any>*/ = [];
22173 var outi = 0, counter = 0;
22174 var dense = Array.isArray(sheet);
22175 var R = r.s.r, C = 0, CC = 0;
22176 if(dense && !sheet[R]) sheet[R] = [];
22177 for(C = r.s.c; C <= r.e.c; ++C) {
22178 cols[C] = encode_col(C);
22179 val = dense ? sheet[R][C] : sheet[cols[C] + rr];
22180 switch(header) {
22181 case 1: hdr[C] = C - r.s.c; break;
22182 case 2: hdr[C] = cols[C]; break;
22183 case 3: hdr[C] = o.header[C - r.s.c]; break;
22184 default:
22185 if(val == null) val = {w: "__EMPTY", t: "s"};
22186 vv = v = format_cell(val, null, o);
22187 counter = 0;
22188 for(CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter);
22189 hdr[C] = vv;
22190 }
22191 }
22192 for (R = r.s.r + offset; R <= r.e.r; ++R) {
22193 var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o);
22194 if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) out[outi++] = row.row;
22195 }
22196 out.length = outi;
22197 return out;
22198}
22199
22200var qreg = /"/g;
22201function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array<string>*/, fs/*:number*/, rs/*:number*/, FS/*:string*/, o/*:Sheet2CSVOpts*/)/*:?string*/ {
22202 var isempty = true;
22203 var row/*:Array<string>*/ = [], txt = "", rr = encode_row(R);
22204 for(var C = r.s.c; C <= r.e.c; ++C) {
22205 if (!cols[C]) continue;
22206 var val = o.dense ? (sheet[R]||[])[C]: sheet[cols[C] + rr];
22207 if(val == null) txt = "";
22208 else if(val.v != null) {
22209 isempty = false;
22210 txt = ''+(o.rawNumbers && val.t == "n" ? val.v : format_cell(val, null, o));
22211 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; }
22212 if(txt == "ID") txt = '"ID"';
22213 } else if(val.f != null && !val.F) {
22214 isempty = false;
22215 txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"';
22216 } else txt = "";
22217 /* NOTE: Excel CSV does not support array formulae */
22218 row.push(txt);
22219 }
22220 if(o.blankrows === false && isempty) return null;
22221 return row.join(FS);
22222}
22223
22224function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ {
22225 var out/*:Array<string>*/ = [];
22226 var o = opts == null ? {} : opts;
22227 if(sheet == null || sheet["!ref"] == null) return "";
22228 var r = safe_decode_range(sheet["!ref"]);
22229 var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
22230 var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
22231 var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
22232 var row = "", cols/*:Array<string>*/ = [];
22233 o.dense = Array.isArray(sheet);
22234 var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
22235 var rowinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!rows"] || [];
22236 for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
22237 for(var R = r.s.r; R <= r.e.r; ++R) {
22238 if ((rowinfo[R]||{}).hidden) continue;
22239 row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o);
22240 if(row == null) { continue; }
22241 if(o.strip) row = row.replace(endregex,"");
22242 out.push(row + RS);
22243 }
22244 delete o.dense;
22245 return out.join("");
22246}
22247
22248function sheet_to_txt(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
22249 if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n";
22250 var s = sheet_to_csv(sheet, opts);
22251 if(typeof cptable == 'undefined' || opts.type == 'string') return s;
22252 var o = cptable.utils.encode(1200, s, 'str');
22253 return String.fromCharCode(255) + String.fromCharCode(254) + o;
22254}
22255
22256function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
22257 var y = "", x, val="";
22258 if(sheet == null || sheet["!ref"] == null) return [];
22259 var r = safe_decode_range(sheet['!ref']), rr = "", cols/*:Array<string>*/ = [], C;
22260 var cmds/*:Array<string>*/ = [];
22261 var dense = Array.isArray(sheet);
22262 for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C);
22263 for(var R = r.s.r; R <= r.e.r; ++R) {
22264 rr = encode_row(R);
22265 for(C = r.s.c; C <= r.e.c; ++C) {
22266 y = cols[C] + rr;
22267 x = dense ? (sheet[R]||[])[C] : sheet[y];
22268 val = "";
22269 if(x === undefined) continue;
22270 else if(x.F != null) {
22271 y = x.F;
22272 if(!x.f) continue;
22273 val = x.f;
22274 if(y.indexOf(":") == -1) y = y + ":" + y;
22275 }
22276 if(x.f != null) val = x.f;
22277 else if(x.t == 'z') continue;
22278 else if(x.t == 'n' && x.v != null) val = "" + x.v;
22279 else if(x.t == 'b') val = x.v ? "TRUE" : "FALSE";
22280 else if(x.w !== undefined) val = "'" + x.w;
22281 else if(x.v === undefined) continue;
22282 else if(x.t == 's') val = "'" + x.v;
22283 else val = ""+x.v;
22284 cmds[cmds.length] = y + "=" + val;
22285 }
22286 }
22287 return cmds;
22288}
22289
22290function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet*/ {
22291 var o = opts || {};
22292 var offset = +!o.skipHeader;
22293 var ws/*:Worksheet*/ = _ws || ({}/*:any*/);
22294 var _R = 0, _C = 0;
22295 if(ws && o.origin != null) {
22296 if(typeof o.origin == 'number') _R = o.origin;
22297 else {
22298 var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
22299 _R = _origin.r; _C = _origin.c;
22300 }
22301 }
22302 var cell/*:Cell*/;
22303 var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}}/*:any*/);
22304 if(ws['!ref']) {
22305 var _range = safe_decode_range(ws['!ref']);
22306 range.e.c = Math.max(range.e.c, _range.e.c);
22307 range.e.r = Math.max(range.e.r, _range.e.r);
22308 if(_R == -1) { _R = _range.e.r + 1; range.e.r = _R + js.length - 1 + offset; }
22309 } else {
22310 if(_R == -1) { _R = 0; range.e.r = js.length - 1 + offset; }
22311 }
22312 var hdr/*:Array<string>*/ = o.header || [], C = 0;
22313
22314 js.forEach(function (JS, R/*:number*/) {
22315 keys(JS).forEach(function(k) {
22316 if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k;
22317 var v = JS[k];
22318 var t = 'z';
22319 var z = "";
22320 var ref = encode_cell({c:_C + C,r:_R + R + offset});
22321 cell = utils.sheet_get_cell(ws, ref);
22322 if(v && typeof v === 'object' && !(v instanceof Date)){
22323 ws[ref] = v;
22324 } else {
22325 if(typeof v == 'number') t = 'n';
22326 else if(typeof v == 'boolean') t = 'b';
22327 else if(typeof v == 'string') t = 's';
22328 else if(v instanceof Date) {
22329 t = 'd';
22330 if(!o.cellDates) { t = 'n'; v = datenum(v); }
22331 z = (o.dateNF || SSF._table[14]);
22332 }
22333 else if(v === null && o.nullError) { t = 'e'; v = 0; }
22334 if(!cell) ws[ref] = cell = ({t:t, v:v}/*:any*/);
22335 else {
22336 cell.t = t; cell.v = v;
22337 delete cell.w; delete cell.R;
22338 if(z) cell.z = z;
22339 }
22340 if(z) cell.z = z;
22341 }
22342 });
22343 });
22344 range.e.c = Math.max(range.e.c, _C + hdr.length - 1);
22345 var __R = encode_row(_R);
22346 if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]};
22347 ws['!ref'] = encode_range(range);
22348 return ws;
22349}
22350function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ { return sheet_add_json(null, js, opts); }
22351
22352var utils/*:any*/ = {
22353 encode_col: encode_col,
22354 encode_row: encode_row,
22355 encode_cell: encode_cell,
22356 encode_range: encode_range,
22357 decode_col: decode_col,
22358 decode_row: decode_row,
22359 split_cell: split_cell,
22360 decode_cell: decode_cell,
22361 decode_range: decode_range,
22362 format_cell: format_cell,
22363 get_formulae: sheet_to_formulae,
22364 make_csv: sheet_to_csv,
22365 make_json: sheet_to_json,
22366 make_formulae: sheet_to_formulae,
22367 sheet_add_aoa: sheet_add_aoa,
22368 sheet_add_json: sheet_add_json,
22369 sheet_add_dom: sheet_add_dom,
22370 aoa_to_sheet: aoa_to_sheet,
22371 json_to_sheet: json_to_sheet,
22372 table_to_sheet: parse_dom_table,
22373 table_to_book: table_to_book,
22374 sheet_to_csv: sheet_to_csv,
22375 sheet_to_txt: sheet_to_txt,
22376 sheet_to_json: sheet_to_json,
22377 sheet_to_html: HTML_.from_sheet,
22378 sheet_to_formulae: sheet_to_formulae,
22379 sheet_to_row_object_array: sheet_to_json
22380};
22381
22382(function(utils) {
22383utils.consts = utils.consts || {};
22384function add_consts(R/*Array<any>*/) { R.forEach(function(a){ utils.consts[a[0]] = a[1]; }); }
22385
22386function get_default(x/*:any*/, y/*:any*/, z/*:any*/)/*:any*/ { return x[y] != null ? x[y] : (x[y] = z); }
22387
22388/* get cell, creating a stub if necessary */
22389function ws_get_cell_stub(ws/*:Worksheet*/, R, C/*:?number*/)/*:Cell*/ {
22390 /* A1 cell address */
22391 if(typeof R == "string") {
22392 /* dense */
22393 if(Array.isArray(ws)) {
22394 var RC = decode_cell(R);
22395 if(!ws[RC.r]) ws[RC.r] = [];
22396 return ws[RC.r][RC.c] || (ws[RC.r][RC.c] = {t:'z'});
22397 }
22398 return ws[R] || (ws[R] = {t:'z'});
22399 }
22400 /* cell address object */
22401 if(typeof R != "number") return ws_get_cell_stub(ws, encode_cell(R));
22402 /* R and C are 0-based indices */
22403 return ws_get_cell_stub(ws, encode_cell({r:R,c:C||0}));
22404}
22405utils.sheet_get_cell = ws_get_cell_stub;
22406
22407/* find sheet index for given name / validate index */
22408function wb_sheet_idx(wb/*:Workbook*/, sh/*:number|string*/) {
22409 if(typeof sh == "number") {
22410 if(sh >= 0 && wb.SheetNames.length > sh) return sh;
22411 throw new Error("Cannot find sheet # " + sh);
22412 } else if(typeof sh == "string") {
22413 var idx = wb.SheetNames.indexOf(sh);
22414 if(idx > -1) return idx;
22415 throw new Error("Cannot find sheet name |" + sh + "|");
22416 } else throw new Error("Cannot find sheet |" + sh + "|");
22417}
22418
22419/* simple blank workbook object */
22420utils.book_new = function()/*:Workbook*/ {
22421 return { SheetNames: [], Sheets: {} };
22422};
22423
22424/* add a worksheet to the end of a given workbook */
22425utils.book_append_sheet = function(wb/*:Workbook*/, ws/*:Worksheet*/, name/*:?string*/) {
22426 if(!name) for(var i = 1; i <= 0xFFFF; ++i, name = undefined) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break;
22427 if(!name || wb.SheetNames.length >= 0xFFFF) throw new Error("Too many worksheets");
22428 check_ws_name(name);
22429 if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!");
22430
22431 wb.SheetNames.push(name);
22432 wb.Sheets[name] = ws;
22433};
22434
22435/* set sheet visibility (visible/hidden/very hidden) */
22436utils.book_set_sheet_visibility = function(wb/*:Workbook*/, sh/*:number|string*/, vis/*:number*/) {
22437 get_default(wb,"Workbook",{});
22438 get_default(wb.Workbook,"Sheets",[]);
22439
22440 var idx = wb_sheet_idx(wb, sh);
22441 // $FlowIgnore
22442 get_default(wb.Workbook.Sheets,idx, {});
22443
22444 switch(vis) {
22445 case 0: case 1: case 2: break;
22446 default: throw new Error("Bad sheet visibility setting " + vis);
22447 }
22448 // $FlowIgnore
22449 wb.Workbook.Sheets[idx].Hidden = vis;
22450};
22451add_consts([
22452 ["SHEET_VISIBLE", 0],
22453 ["SHEET_HIDDEN", 1],
22454 ["SHEET_VERY_HIDDEN", 2]
22455]);
22456
22457/* set number format */
22458utils.cell_set_number_format = function(cell/*:Cell*/, fmt/*:string|number*/) {
22459 cell.z = fmt;
22460 return cell;
22461};
22462
22463/* set cell hyperlink */
22464utils.cell_set_hyperlink = function(cell/*:Cell*/, target/*:string*/, tooltip/*:?string*/) {
22465 if(!target) {
22466 delete cell.l;
22467 } else {
22468 cell.l = ({ Target: target }/*:Hyperlink*/);
22469 if(tooltip) cell.l.Tooltip = tooltip;
22470 }
22471 return cell;
22472};
22473utils.cell_set_internal_link = function(cell/*:Cell*/, range/*:string*/, tooltip/*:?string*/) { return utils.cell_set_hyperlink(cell, "#" + range, tooltip); };
22474
22475/* add to cell comments */
22476utils.cell_add_comment = function(cell/*:Cell*/, text/*:string*/, author/*:?string*/) {
22477 if(!cell.c) cell.c = [];
22478 cell.c.push({t:text, a:author||"SheetJS"});
22479};
22480
22481/* set array formula and flush related cells */
22482utils.sheet_set_array_formula = function(ws/*:Worksheet*/, range, formula/*:string*/) {
22483 var rng = typeof range != "string" ? range : safe_decode_range(range);
22484 var rngstr = typeof range == "string" ? range : encode_range(range);
22485 for(var R = rng.s.r; R <= rng.e.r; ++R) for(var C = rng.s.c; C <= rng.e.c; ++C) {
22486 var cell = ws_get_cell_stub(ws, R, C);
22487 cell.t = 'n';
22488 cell.F = rngstr;
22489 delete cell.v;
22490 if(R == rng.s.r && C == rng.s.c) cell.f = formula;
22491 }
22492 return ws;
22493};
22494
22495return utils;
22496})(utils);
22497
22498export const version = XLSX.version;
22499export {
22500 parse_xlscfb,
22501 parse_zip,
22502 readSync as read,
22503 readFileSync as readFile,
22504 readFileSync,
22505 writeSync as write,
22506 writeFileSync as writeFile,
22507 writeFileSync,
22508 writeFileAsync,
22509 utils,
22510 SSF,
22511 CFB
22512};