Subversion-Projekte lars-tiefland.ci

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
776 lars 1
/* xlsx.js (C) 2013-2015 SheetJS -- http://sheetjs.com */
2
/* vim: set ts=2: */
3
/*jshint -W041 */
4
/*jshint funcscope:true, eqnull:true */
5
var XLSX = {};
6
(function make_xlsx(XLSX){
7
XLSX.version = '0.8.0';
8
var current_codepage = 1200, current_cptable;
9
if(typeof module !== "undefined" && typeof require !== 'undefined') {
10
    if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel');
11
    current_cptable = cptable[current_codepage];
12
}
13
function reset_cp() { set_cp(1200); }
14
var set_cp = function(cp) { current_codepage = cp; };
15
 
16
function char_codes(data) { var o = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; }
17
var debom_xml = function(data) { return data; };
18
 
19
var _getchar = function _gc1(x) { return String.fromCharCode(x); };
20
if(typeof cptable !== 'undefined') {
21
    set_cp = function(cp) { current_codepage = cp; current_cptable = cptable[cp]; };
22
    debom_xml = function(data) {
23
        if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.substr(2))); }
24
        return data;
25
    };
26
    _getchar = function _gc2(x) {
27
        if(current_codepage === 1200) return String.fromCharCode(x);
28
        return cptable.utils.decode(current_codepage, [x&255,x>>8])[0];
29
    };
30
}
31
var Base64 = (function make_b64(){
32
    var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
33
    return {
34
        encode: function(input, utf8) {
35
            var o = "";
36
            var c1, c2, c3, e1, e2, e3, e4;
37
            for(var i = 0; i < input.length; ) {
38
                c1 = input.charCodeAt(i++);
39
                c2 = input.charCodeAt(i++);
40
                c3 = input.charCodeAt(i++);
41
                e1 = c1 >> 2;
42
                e2 = (c1 & 3) << 4 | c2 >> 4;
43
                e3 = (c2 & 15) << 2 | c3 >> 6;
44
                e4 = c3 & 63;
45
                if (isNaN(c2)) { e3 = e4 = 64; }
46
                else if (isNaN(c3)) { e4 = 64; }
47
                o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4);
48
            }
49
            return o;
50
        },
51
        decode: function b64_decode(input, utf8) {
52
            var o = "";
53
            var c1, c2, c3;
54
            var e1, e2, e3, e4;
55
            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
56
            for(var i = 0; i < input.length;) {
57
                e1 = map.indexOf(input.charAt(i++));
58
                e2 = map.indexOf(input.charAt(i++));
59
                e3 = map.indexOf(input.charAt(i++));
60
                e4 = map.indexOf(input.charAt(i++));
61
                c1 = e1 << 2 | e2 >> 4;
62
                c2 = (e2 & 15) << 4 | e3 >> 2;
63
                c3 = (e3 & 3) << 6 | e4;
64
                o += String.fromCharCode(c1);
65
                if (e3 != 64) { o += String.fromCharCode(c2); }
66
                if (e4 != 64) { o += String.fromCharCode(c3); }
67
            }
68
            return o;
69
        }
70
    };
71
})();
72
var has_buf = (typeof Buffer !== 'undefined');
73
 
74
function new_raw_buf(len) {
75
    /* jshint -W056 */
76
    return new (has_buf ? Buffer : Array)(len);
77
    /* jshint +W056 */
78
}
79
 
80
function s2a(s) {
81
    if(has_buf) return new Buffer(s, "binary");
82
    return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; });
83
}
84
 
85
var bconcat = function(bufs) { return [].concat.apply([], bufs); };
86
 
87
var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/;
88
/* ssf.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
89
/*jshint -W041 */
90
var SSF = {};
91
var make_ssf = function make_ssf(SSF){
92
SSF.version = '0.8.1';
93
function _strrev(x) { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; }
94
function fill(c,l) { var o = ""; while(o.length < l) o+=c; return o; }
95
function pad0(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
96
function pad_(v,d){var t=""+v;return t.length>=d?t:fill(' ',d-t.length)+t;}
97
function rpad_(v,d){var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);}
98
function pad0r1(v,d){var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;}
99
function pad0r2(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
100
var p2_32 = Math.pow(2,32);
101
function pad0r(v,d){if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); }
102
function isgeneral(s, i) { 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; }
103
/* Options */
104
var opts_fmt = [
105
    ["date1904", 0],
106
    ["output", ""],
107
    ["WTF", false]
108
];
109
function fixopts(o){
110
    for(var y = 0; y != opts_fmt.length; ++y) if(o[opts_fmt[y][0]]===undefined) o[opts_fmt[y][0]]=opts_fmt[y][1];
111
}
112
SSF.opts = opts_fmt;
113
var table_fmt = {
114
    0:  'General',
115
    1:  '0',
116
    2:  '0.00',
117
    3:  '#,##0',
118
    4:  '#,##0.00',
119
    9:  '0%',
120
    10: '0.00%',
121
    11: '0.00E+00',
122
    12: '# ?/?',
123
    13: '# ??/??',
124
    14: 'm/d/yy',
125
    15: 'd-mmm-yy',
126
    16: 'd-mmm',
127
    17: 'mmm-yy',
128
    18: 'h:mm AM/PM',
129
    19: 'h:mm:ss AM/PM',
130
    20: 'h:mm',
131
    21: 'h:mm:ss',
132
    22: 'm/d/yy h:mm',
133
    37: '#,##0 ;(#,##0)',
134
    38: '#,##0 ;[Red](#,##0)',
135
    39: '#,##0.00;(#,##0.00)',
136
    40: '#,##0.00;[Red](#,##0.00)',
137
    45: 'mm:ss',
138
    46: '[h]:mm:ss',
139
    47: 'mmss.0',
140
    48: '##0.0E+0',
141
    49: '@',
142
    56: '"上午/下午 "hh"時"mm"分"ss"秒 "',
143
    65535: 'General'
144
};
145
var days = [
146
    ['Sun', 'Sunday'],
147
    ['Mon', 'Monday'],
148
    ['Tue', 'Tuesday'],
149
    ['Wed', 'Wednesday'],
150
    ['Thu', 'Thursday'],
151
    ['Fri', 'Friday'],
152
    ['Sat', 'Saturday']
153
];
154
var months = [
155
    ['J', 'Jan', 'January'],
156
    ['F', 'Feb', 'February'],
157
    ['M', 'Mar', 'March'],
158
    ['A', 'Apr', 'April'],
159
    ['M', 'May', 'May'],
160
    ['J', 'Jun', 'June'],
161
    ['J', 'Jul', 'July'],
162
    ['A', 'Aug', 'August'],
163
    ['S', 'Sep', 'September'],
164
    ['O', 'Oct', 'October'],
165
    ['N', 'Nov', 'November'],
166
    ['D', 'Dec', 'December']
167
];
168
function frac(x, D, mixed) {
169
    var sgn = x < 0 ? -1 : 1;
170
    var B = x * sgn;
171
    var P_2 = 0, P_1 = 1, P = 0;
172
    var Q_2 = 1, Q_1 = 0, Q = 0;
173
    var A = Math.floor(B);
174
    while(Q_1 < D) {
175
        A = Math.floor(B);
176
        P = A * P_1 + P_2;
177
        Q = A * Q_1 + Q_2;
178
        if((B - A) < 0.0000000005) break;
179
        B = 1 / (B - A);
180
        P_2 = P_1; P_1 = P;
181
        Q_2 = Q_1; Q_1 = Q;
182
    }
183
    if(Q > D) { Q = Q_1; P = P_1; }
184
    if(Q > D) { Q = Q_2; P = P_2; }
185
    if(!mixed) return [0, sgn * P, Q];
186
    if(Q===0) throw "Unexpected state: "+P+" "+P_1+" "+P_2+" "+Q+" "+Q_1+" "+Q_2;
187
    var q = Math.floor(sgn * P/Q);
188
    return [q, sgn*P - q*Q, Q];
189
}
190
function general_fmt_int(v, opts) { return ""+v; }
191
SSF._general_int = general_fmt_int;
192
var general_fmt_num = (function make_general_fmt_num() {
193
var gnr1 = /\.(\d*[1-9])0+$/, gnr2 = /\.0*$/, gnr4 = /\.(\d*[1-9])0+/, gnr5 = /\.0*[Ee]/, gnr6 = /(E[+-])(\d)$/;
194
function gfn2(v) {
195
    var w = (v<0?12:11);
196
    var o = gfn5(v.toFixed(12)); if(o.length <= w) return o;
197
    o = v.toPrecision(10); if(o.length <= w) return o;
198
    return v.toExponential(5);
199
}
200
function gfn3(v) {
201
    var o = v.toFixed(11).replace(gnr1,".$1");
202
    if(o.length > (v<0?12:11)) o = v.toPrecision(6);
203
    return o;
204
}
205
function gfn4(o) {
206
    for(var i = 0; i != o.length; ++i) if((o.charCodeAt(i) | 0x20) === 101) return o.replace(gnr4,".$1").replace(gnr5,"E").replace("e","E").replace(gnr6,"$10$2");
207
    return o;
208
}
209
function gfn5(o) {
210
    //for(var i = 0; i != o.length; ++i) if(o.charCodeAt(i) === 46) return o.replace(gnr2,"").replace(gnr1,".$1");
211
    //return o;
212
    return o.indexOf(".") > -1 ? o.replace(gnr2,"").replace(gnr1,".$1") : o;
213
}
214
return function general_fmt_num(v, opts) {
215
    var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
216
    if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
217
    else if(Math.abs(V) <= 9) o = gfn2(v);
218
    else if(V === 10) o = v.toFixed(10).substr(0,12);
219
    else o = gfn3(v);
220
    return gfn5(gfn4(o));
221
};})();
222
SSF._general_num = general_fmt_num;
223
function general_fmt(v, opts) {
224
    switch(typeof v) {
225
        case 'string': return v;
226
        case 'boolean': return v ? "TRUE" : "FALSE";
227
        case 'number': return (v|0) === v ? general_fmt_int(v, opts) : general_fmt_num(v, opts);
228
    }
229
    throw new Error("unsupported value in General format: " + v);
230
}
231
SSF._general = general_fmt;
232
function fix_hijri(date, o) { return 0; }
233
function parse_date_code(v,opts,b2) {
234
    if(v > 2958465 || v < 0) return null;
235
    var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
236
    var dout=[];
237
    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};
238
    if(Math.abs(out.u) < 1e-6) out.u = 0;
239
    fixopts(opts != null ? opts : (opts=[]));
240
    if(opts.date1904) date += 1462;
241
    if(out.u > 0.999) {
242
        out.u = 0;
243
        if(++time == 86400) { time = 0; ++date; }
244
    }
245
    if(date === 60) {dout = b2 ? [1317,10,29] : [1900,2,29]; dow=3;}
246
    else if(date === 0) {dout = b2 ? [1317,8,29] : [1900,1,0]; dow=6;}
247
    else {
248
        if(date > 60) --date;
249
        /* 1 = Jan 1 1900 */
250
        var d = new Date(1900,0,1);
251
        d.setDate(d.getDate() + date - 1);
252
        dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
253
        dow = d.getDay();
254
        if(date < 60) dow = (dow + 6) % 7;
255
        if(b2) dow = fix_hijri(d, dout);
256
    }
257
    out.y = dout[0]; out.m = dout[1]; out.d = dout[2];
258
    out.S = time % 60; time = Math.floor(time / 60);
259
    out.M = time % 60; time = Math.floor(time / 60);
260
    out.H = time;
261
    out.q = dow;
262
    return out;
263
}
264
SSF.parse_date_code = parse_date_code;
265
/*jshint -W086 */
266
function write_date(type, fmt, val, ss0) {
267
    var o="", ss=0, tt=0, y = val.y, out, outl = 0;
268
    switch(type) {
269
        case 98: /* 'b' buddhist year */
270
            y = val.y + 543;
271
            /* falls through */
272
        case 121: /* 'y' year */
273
        switch(fmt.length) {
274
            case 1: case 2: out = y % 100; outl = 2; break;
275
            default: out = y % 10000; outl = 4; break;
276
        } break;
277
        case 109: /* 'm' month */
278
        switch(fmt.length) {
279
            case 1: case 2: out = val.m; outl = fmt.length; break;
280
            case 3: return months[val.m-1][1];
281
            case 5: return months[val.m-1][0];
282
            default: return months[val.m-1][2];
283
        } break;
284
        case 100: /* 'd' day */
285
        switch(fmt.length) {
286
            case 1: case 2: out = val.d; outl = fmt.length; break;
287
            case 3: return days[val.q][0];
288
            default: return days[val.q][1];
289
        } break;
290
        case 104: /* 'h' 12-hour */
291
        switch(fmt.length) {
292
            case 1: case 2: out = 1+(val.H+11)%12; outl = fmt.length; break;
293
            default: throw 'bad hour format: ' + fmt;
294
        } break;
295
        case 72: /* 'H' 24-hour */
296
        switch(fmt.length) {
297
            case 1: case 2: out = val.H; outl = fmt.length; break;
298
            default: throw 'bad hour format: ' + fmt;
299
        } break;
300
        case 77: /* 'M' minutes */
301
        switch(fmt.length) {
302
            case 1: case 2: out = val.M; outl = fmt.length; break;
303
            default: throw 'bad minute format: ' + fmt;
304
        } break;
305
        case 115: /* 's' seconds */
306
        if(val.u === 0) switch(fmt) {
307
            case 's': case 'ss': return pad0(val.S, fmt.length);
308
            case '.0': case '.00': case '.000':
309
        }
310
        switch(fmt) {
311
            case 's': case 'ss': case '.0': case '.00': case '.000':
312
                if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100;
313
                else tt = ss0 === 1 ? 10 : 1;
314
                ss = Math.round((tt)*(val.S + val.u));
315
                if(ss >= 60*tt) ss = 0;
316
                if(fmt === 's') return ss === 0 ? "0" : ""+ss/tt;
317
                o = pad0(ss,2 + ss0);
318
                if(fmt === 'ss') return o.substr(0,2);
319
                return "." + o.substr(2,fmt.length-1);
320
            default: throw 'bad second format: ' + fmt;
321
        }
322
        case 90: /* 'Z' absolute time */
323
        switch(fmt) {
324
            case '[h]': case '[hh]': out = val.D*24+val.H; break;
325
            case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
326
            case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
327
            default: throw 'bad abstime format: ' + fmt;
328
        } outl = fmt.length === 3 ? 1 : 2; break;
329
        case 101: /* 'e' era */
330
            out = y; outl = 1;
331
    }
332
    if(outl > 0) return pad0(out, outl); else return "";
333
}
334
/*jshint +W086 */
335
function commaify(s) {
336
    if(s.length <= 3) return s;
337
    var j = (s.length % 3), o = s.substr(0,j);
338
    for(; j!=s.length; j+=3) o+=(o.length > 0 ? "," : "") + s.substr(j,3);
339
    return o;
340
}
341
var write_num = (function make_write_num(){
342
var pct1 = /%/g;
343
function write_num_pct(type, fmt, val){
344
    var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
345
    return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
346
}
347
function write_num_cm(type, fmt, val){
348
    var idx = fmt.length - 1;
349
    while(fmt.charCodeAt(idx-1) === 44) --idx;
350
    return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
351
}
352
function write_num_exp(fmt, val){
353
    var o;
354
    var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
355
    if(fmt.match(/^#+0.0E\+0$/)) {
356
        var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
357
        var ee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E)%period;
358
        if(ee < 0) ee += period;
359
        o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
360
        if(o.indexOf("e") === -1) {
361
            var fakee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E);
362
            if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
363
            else o += "E+" + (fakee - ee);
364
            while(o.substr(0,2) === "0.") {
365
                o = o[0] + o.substr(2,period) + "." + o.substr(2+period);
366
                o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0.");
367
            }
368
            o = o.replace(/\+-/,"-");
369
        }
370
        o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
371
    } else o = val.toExponential(idx);
372
    if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o[o.length-1];
373
    if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
374
    return o.replace("e","E");
375
}
376
var frac1 = /# (\?+)( ?)\/( ?)(\d+)/;
377
function write_num_f1(r, aval, sign) {
378
    var den = parseInt(r[4]), rr = Math.round(aval * den), base = Math.floor(rr/den);
379
    var myn = (rr - base*den), myd = den;
380
    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));
381
}
382
function write_num_f2(r, aval, sign) {
383
    return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
384
}
385
var dec1 = /^#*0*\.(0+)/;
386
var closeparen = /\).*[0#]/;
387
var phone = /\(###\) ###\\?-####/;
388
function hashq(str) {
389
    var o = "", cc;
390
    for(var i = 0; i != str.length; ++i) switch((cc=str.charCodeAt(i))) {
391
        case 35: break;
392
        case 63: o+= " "; break;
393
        case 48: o+= "0"; break;
394
        default: o+= String.fromCharCode(cc);
395
    }
396
    return o;
397
}
398
function rnd(val, d) { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
399
function dec(val, d) { return Math.round((val-Math.floor(val))*Math.pow(10,d)); }
400
function flr(val) { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); }
401
function write_num_flt(type, fmt, val) {
402
    if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
403
        var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
404
        if(val >= 0) return write_num_flt('n', ffmt, val);
405
        return '(' + write_num_flt('n', ffmt, -val) + ')';
406
    }
407
    if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm(type, fmt, val);
408
    if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val);
409
    if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val);
410
    if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt[1]==' '?2:1),val);
411
    var o, oo;
412
    var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
413
    if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length);
414
    if(fmt.match(/^[#?]+$/)) {
415
        o = pad0r(val,0); if(o === "0") o = "";
416
        return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
417
    }
418
    if((r = fmt.match(frac1)) !== null) return write_num_f1(r, aval, sign);
419
    if(fmt.match(/^#+0+$/) !== null) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
420
    if((r = fmt.match(dec1)) !== null) {
421
        o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
422
        return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
423
    }
424
    fmt = fmt.replace(/^#+([0.])/, "$1");
425
    if((r = fmt.match(/^(0*)\.(#*)$/)) !== null) {
426
        return sign + rnd(aval, r[2].length).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
427
    }
428
    if((r = fmt.match(/^#,##0(\.?)$/)) !== null) return sign + commaify(pad0r(aval,0));
429
    if((r = fmt.match(/^#,##0\.([#0]*0)$/)) !== null) {
430
        return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val))) + "." + pad0(dec(val, r[1].length),r[1].length);
431
    }
432
    if((r = fmt.match(/^#,#*,#0/)) !== null) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
433
    if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/)) !== null) {
434
        o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val));
435
        ri = 0;
436
        return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==='0'?'0':"";}));
437
    }
438
    if(fmt.match(phone) !== null) {
439
        o = write_num_flt(type, "##########", val);
440
        return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
441
    }
442
    var oa = "";
443
    if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/)) !== null) {
444
        ri = Math.min(r[4].length,7);
445
        ff = frac(aval, Math.pow(10,ri)-1, false);
446
        o = "" + sign;
447
        oa = write_num("n", r[1], ff[1]);
448
        if(oa[oa.length-1] == " ") oa = oa.substr(0,oa.length-1) + "0";
449
        o += oa + r[2] + "/" + r[3];
450
        oa = rpad_(ff[2],ri);
451
        if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
452
        o += oa;
453
        return o;
454
    }
455
    if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/)) !== null) {
456
        ri = Math.min(Math.max(r[1].length, r[4].length),7);
457
        ff = frac(aval, Math.pow(10,ri)-1, true);
458
        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));
459
    }
460
    if((r = fmt.match(/^[#0?]+$/)) !== null) {
461
        o = pad0r(val, 0);
462
        if(fmt.length <= o.length) return o;
463
        return hashq(fmt.substr(0,fmt.length-o.length)) + o;
464
    }
465
  if((r = fmt.match(/^([#0?]+)\.([#0]+)$/)) !== null) {
466
        o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
467
        ri = o.indexOf(".");
468
        var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
469
        return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
470
    }
471
    if((r = fmt.match(/^00,000\.([#0]*0)$/)) !== null) {
472
        ri = dec(val, r[1].length);
473
        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);
474
    }
475
    switch(fmt) {
476
        case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : "";
477
        default:
478
    }
479
    throw new Error("unsupported format |" + fmt + "|");
480
}
481
function write_num_cm2(type, fmt, val){
482
    var idx = fmt.length - 1;
483
    while(fmt.charCodeAt(idx-1) === 44) --idx;
484
    return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
485
}
486
function write_num_pct2(type, fmt, val){
487
    var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
488
    return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
489
}
490
function write_num_exp2(fmt, val){
491
    var o;
492
    var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
493
    if(fmt.match(/^#+0.0E\+0$/)) {
494
        var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
495
        var ee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E)%period;
496
        if(ee < 0) ee += period;
497
        o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
498
        if(!o.match(/[Ee]/)) {
499
            var fakee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E);
500
            if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
501
            else o += "E+" + (fakee - ee);
502
            o = o.replace(/\+-/,"-");
503
        }
504
        o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
505
    } else o = val.toExponential(idx);
506
    if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o[o.length-1];
507
    if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
508
    return o.replace("e","E");
509
}
510
function write_num_int(type, fmt, val) {
511
    if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
512
        var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
513
        if(val >= 0) return write_num_int('n', ffmt, val);
514
        return '(' + write_num_int('n', ffmt, -val) + ')';
515
    }
516
    if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm2(type, fmt, val);
517
    if(fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val);
518
    if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val);
519
    if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt[1]==' '?2:1),val);
520
    var o;
521
    var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
522
    if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length);
523
    if(fmt.match(/^[#?]+$/)) {
524
        o = (""+val); if(val === 0) o = "";
525
        return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
526
    }
527
    if((r = fmt.match(frac1)) !== null) return write_num_f2(r, aval, sign);
528
    if(fmt.match(/^#+0+$/) !== null) return sign + pad0(aval,fmt.length - fmt.indexOf("0"));
529
    if((r = fmt.match(dec1)) !== null) {
530
        o = (""+val).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
531
        return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
532
    }
533
    fmt = fmt.replace(/^#+([0.])/, "$1");
534
    if((r = fmt.match(/^(0*)\.(#*)$/)) !== null) {
535
        return sign + (""+aval).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
536
    }
537
    if((r = fmt.match(/^#,##0(\.?)$/)) !== null) return sign + commaify((""+aval));
538
    if((r = fmt.match(/^#,##0\.([#0]*0)$/)) !== null) {
539
        return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify((""+val)) + "." + fill('0',r[1].length);
540
    }
541
    if((r = fmt.match(/^#,#*,#0/)) !== null) return write_num_int(type,fmt.replace(/^#,#*,/,""),val);
542
    if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/)) !== null) {
543
        o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val));
544
        ri = 0;
545
        return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==='0'?'0':"";}));
546
    }
547
    if(fmt.match(phone) !== null) {
548
        o = write_num_int(type, "##########", val);
549
        return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
550
    }
551
    var oa = "";
552
    if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/)) !== null) {
553
        ri = Math.min(r[4].length,7);
554
        ff = frac(aval, Math.pow(10,ri)-1, false);
555
        o = "" + sign;
556
        oa = write_num("n", r[1], ff[1]);
557
        if(oa[oa.length-1] == " ") oa = oa.substr(0,oa.length-1) + "0";
558
        o += oa + r[2] + "/" + r[3];
559
        oa = rpad_(ff[2],ri);
560
        if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
561
        o += oa;
562
        return o;
563
    }
564
    if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/)) !== null) {
565
        ri = Math.min(Math.max(r[1].length, r[4].length),7);
566
        ff = frac(aval, Math.pow(10,ri)-1, true);
567
        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));
568
    }
569
    if((r = fmt.match(/^[#0?]+$/)) !== null) {
570
        o = "" + val;
571
        if(fmt.length <= o.length) return o;
572
        return hashq(fmt.substr(0,fmt.length-o.length)) + o;
573
    }
574
    if((r = fmt.match(/^([#0]+)\.([#0]+)$/)) !== null) {
575
        o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
576
        ri = o.indexOf(".");
577
        var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
578
        return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
579
    }
580
    if((r = fmt.match(/^00,000\.([#0]*0)$/)) !== null) {
581
        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);
582
    }
583
    switch(fmt) {
584
        case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
585
        default:
586
    }
587
    throw new Error("unsupported format |" + fmt + "|");
588
}
589
return function write_num(type, fmt, val) {
590
    return (val|0) === val ? write_num_int(type, fmt, val) : write_num_flt(type, fmt, val);
591
};})();
592
function split_fmt(fmt) {
593
    var out = [];
594
    var in_str = false, cc;
595
    for(var i = 0, j = 0; i < fmt.length; ++i) switch((cc=fmt.charCodeAt(i))) {
596
        case 34: /* '"' */
597
            in_str = !in_str; break;
598
        case 95: case 42: case 92: /* '_' '*' '\\' */
599
            ++i; break;
600
        case 59: /* ';' */
601
            out[out.length] = fmt.substr(j,i-j);
602
            j = i+1;
603
    }
604
    out[out.length] = fmt.substr(j);
605
    if(in_str === true) throw new Error("Format |" + fmt + "| unterminated string ");
606
    return out;
607
}
608
SSF._split = split_fmt;
609
var abstime = /\[[HhMmSs]*\]/;
610
function eval_fmt(fmt, v, opts, flen) {
611
    var out = [], o = "", i = 0, c = "", lst='t', q, dt, j, cc;
612
    var hr='H';
613
    /* Tokenize */
614
    while(i < fmt.length) {
615
        switch((c = fmt[i])) {
616
            case 'G': /* General */
617
                if(!isgeneral(fmt, i)) throw new Error('unrecognized character ' + c + ' in ' +fmt);
618
                out[out.length] = {t:'G', v:'General'}; i+=7; break;
619
            case '"': /* Literal text */
620
                for(o="";(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) o += String.fromCharCode(cc);
621
                out[out.length] = {t:'t', v:o}; ++i; break;
622
            case '\\': var w = fmt[++i], t = (w === "(" || w === ")") ? w : 't';
623
                out[out.length] = {t:t, v:w}; ++i; break;
624
            case '_': out[out.length] = {t:'t', v:" "}; i+=2; break;
625
            case '@': /* Text Placeholder */
626
                out[out.length] = {t:'T', v:v}; ++i; break;
627
            case 'B': case 'b':
628
                if(fmt[i+1] === "1" || fmt[i+1] === "2") {
629
          if(dt==null) { dt=parse_date_code(v, opts, fmt[i+1] === "2"); if(dt==null) return ""; }
630
                    out[out.length] = {t:'X', v:fmt.substr(i,2)}; lst = c; i+=2; break;
631
                }
632
                /* falls through */
633
            case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
634
                c = c.toLowerCase();
635
                /* falls through */
636
            case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g':
637
                if(v < 0) return "";
638
                if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
639
                o = c; while(++i<fmt.length && fmt[i].toLowerCase() === c) o+=c;
640
                if(c === 'm' && lst.toLowerCase() === 'h') c = 'M'; /* m = minute */
641
                if(c === 'h') c = hr;
642
                out[out.length] = {t:c, v:o}; lst = c; break;
643
            case 'A':
644
                q={t:c, v:"A"};
645
                if(dt==null) dt=parse_date_code(v, opts);
646
        if(fmt.substr(i, 3) === "A/P") { if(dt!=null) q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;}
647
        else if(fmt.substr(i,5) === "AM/PM") { if(dt!=null) q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; }
648
                else { q.t = "t"; ++i; }
649
                if(dt==null && q.t === 'T') return "";
650
                out[out.length] = q; lst = c; break;
651
            case '[':
652
                o = c;
653
                while(fmt[i++] !== ']' && i < fmt.length) o += fmt[i];
654
                if(o.substr(-1) !== ']') throw 'unterminated "[" block: |' + o + '|';
655
                if(o.match(abstime)) {
656
                    if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
657
                    out[out.length] = {t:'Z', v:o.toLowerCase()};
658
                } else { o=""; }
659
                break;
660
            /* Numbers */
661
            case '.':
662
                if(dt != null) {
663
                    o = c; while((c=fmt[++i]) === "0") o += c;
664
                    out[out.length] = {t:'s', v:o}; break;
665
                }
666
                /* falls through */
667
            case '0': case '#':
668
                o = c; while("0#?.,E+-%".indexOf(c=fmt[++i]) > -1 || c=='\\' && fmt[i+1] == "-" && "0#".indexOf(fmt[i+2])>-1) o += c;
669
                out[out.length] = {t:'n', v:o}; break;
670
            case '?':
671
                o = c; while(fmt[++i] === c) o+=c;
672
                q={t:c, v:o}; out[out.length] = q; lst = c; break;
673
            case '*': ++i; if(fmt[i] == ' ' || fmt[i] == '*') ++i; break; // **
674
            case '(': case ')': out[out.length] = {t:(flen===1?'t':c), v:c}; ++i; break;
675
            case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
676
                o = c; while("0123456789".indexOf(fmt[++i]) > -1) o+=fmt[i];
677
                out[out.length] = {t:'D', v:o}; break;
678
            case ' ': out[out.length] = {t:c, v:c}; ++i; break;
679
            default:
680
                if(",$-+/():!^&'~{}<>=€acfijklopqrtuvwxz".indexOf(c) === -1) throw new Error('unrecognized character ' + c + ' in ' + fmt);
681
                out[out.length] = {t:'t', v:c}; ++i; break;
682
        }
683
    }
684
    var bt = 0, ss0 = 0, ssm;
685
    for(i=out.length-1, lst='t'; i >= 0; --i) {
686
        switch(out[i].t) {
687
            case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
688
            case 's':
689
                if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
690
                if(bt < 3) bt = 3;
691
            /* falls through */
692
            case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
693
            case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
694
            case 'X': if(out[i].v === "B2");
695
                break;
696
            case 'Z':
697
                if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1;
698
                if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2;
699
                if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
700
        }
701
    }
702
    switch(bt) {
703
        case 0: break;
704
        case 1:
705
            if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
706
            if(dt.S >=  60) { dt.S = 0; ++dt.M; }
707
            if(dt.M >=  60) { dt.M = 0; ++dt.H; }
708
            break;
709
        case 2:
710
            if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
711
            if(dt.S >=  60) { dt.S = 0; ++dt.M; }
712
            break;
713
    }
714
    /* replace fields */
715
    var nstr = "", jj;
716
    for(i=0; i < out.length; ++i) {
717
        switch(out[i].t) {
718
            case 't': case 'T': case ' ': case 'D': break;
719
            case 'X': out[i] = undefined; break;
720
            case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'b': case 'Z':
721
                out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
722
                out[i].t = 't'; break;
723
            case 'n': case '(': case '?':
724
                jj = i+1;
725
                while(out[jj] != null && (
726
                    (c=out[jj].t) === "?" || c === "D" ||
727
                    (c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/') ||
728
                    out[i].t === '(' && (c === ' ' || c === 'n' || c === ')') ||
729
                    c === 't' && (out[jj].v === '/' || '$€'.indexOf(out[jj].v) > -1 || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?')
730
                )) {
731
                    out[i].v += out[jj].v;
732
                    out[jj] = undefined; ++jj;
733
                }
734
                nstr += out[i].v;
735
                i = jj-1; break;
736
            case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
737
        }
738
    }
739
    var vv = "", myv, ostr;
740
    if(nstr.length > 0) {
741
        myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v); /* '-' */
742
        ostr = write_num(nstr.charCodeAt(0) === 40 ? '(' : 'n', nstr, myv); /* '(' */
743
        jj=ostr.length-1;
744
        var decpt = out.length;
745
        for(i=0; i < out.length; ++i) if(out[i] != null && out[i].v.indexOf(".") > -1) { decpt = i; break; }
746
        var lasti=out.length;
747
        if(decpt === out.length && ostr.indexOf("E") === -1) {
748
            for(i=out.length-1; i>= 0;--i) {
749
                if(out[i] == null || 'n?('.indexOf(out[i].t) === -1) continue;
750
                if(jj>=out[i].v.length-1) { jj -= out[i].v.length; out[i].v = ostr.substr(jj+1, out[i].v.length); }
751
                else if(jj < 0) out[i].v = "";
752
                else { out[i].v = ostr.substr(0, jj+1); jj = -1; }
753
                out[i].t = 't';
754
                lasti = i;
755
            }
756
            if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
757
        }
758
        else if(decpt !== out.length && ostr.indexOf("E") === -1) {
759
            jj = ostr.indexOf(".")-1;
760
            for(i=decpt; i>= 0; --i) {
761
                if(out[i] == null || 'n?('.indexOf(out[i].t) === -1) continue;
762
                j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1;
763
                vv = out[i].v.substr(j+1);
764
                for(; j>=0; --j) {
765
                    if(jj>=0 && (out[i].v[j] === "0" || out[i].v[j] === "#")) vv = ostr[jj--] + vv;
766
                }
767
                out[i].v = vv;
768
                out[i].t = 't';
769
                lasti = i;
770
            }
771
            if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
772
            jj = ostr.indexOf(".")+1;
773
            for(i=decpt; i<out.length; ++i) {
774
                if(out[i] == null || 'n?('.indexOf(out[i].t) === -1 && i !== decpt ) continue;
775
                j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0;
776
                vv = out[i].v.substr(0,j);
777
                for(; j<out[i].v.length; ++j) {
778
                    if(jj<ostr.length) vv += ostr[jj++];
779
                }
780
                out[i].v = vv;
781
                out[i].t = 't';
782
                lasti = i;
783
            }
784
        }
785
    }
786
    for(i=0; i<out.length; ++i) if(out[i] != null && 'n(?'.indexOf(out[i].t)>-1) {
787
        myv = (flen >1 && v < 0 && i>0 && out[i-1].v === "-" ? -v:v);
788
        out[i].v = write_num(out[i].t, out[i].v, myv);
789
        out[i].t = 't';
790
    }
791
    var retval = "";
792
    for(i=0; i !== out.length; ++i) if(out[i] != null) retval += out[i].v;
793
    return retval;
794
}
795
SSF._eval = eval_fmt;
796
var cfregex = /\[[=<>]/;
797
var cfregex2 = /\[([=<>]*)(-?\d+\.?\d*)\]/;
798
function chkcond(v, rr) {
799
    if(rr == null) return false;
800
    var thresh = parseFloat(rr[2]);
801
    switch(rr[1]) {
802
        case "=":  if(v == thresh) return true; break;
803
        case ">":  if(v >  thresh) return true; break;
804
        case "<":  if(v <  thresh) return true; break;
805
        case "<>": if(v != thresh) return true; break;
806
        case ">=": if(v >= thresh) return true; break;
807
        case "<=": if(v <= thresh) return true; break;
808
    }
809
    return false;
810
}
811
function choose_fmt(f, v) {
812
    var fmt = split_fmt(f);
813
    var l = fmt.length, lat = fmt[l-1].indexOf("@");
814
    if(l<4 && lat>-1) --l;
815
    if(fmt.length > 4) throw "cannot find right format for |" + fmt + "|";
816
    if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
817
    switch(fmt.length) {
818
        case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
819
        case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
820
        case 3: fmt = lat>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
821
        case 4: break;
822
    }
823
    var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2];
824
    if(fmt[0].indexOf("[") === -1 && fmt[1].indexOf("[") === -1) return [l, ff];
825
    if(fmt[0].match(cfregex) != null || fmt[1].match(cfregex) != null) {
826
        var m1 = fmt[0].match(cfregex2);
827
        var m2 = fmt[1].match(cfregex2);
828
        return chkcond(v, m1) ? [l, fmt[0]] : chkcond(v, m2) ? [l, fmt[1]] : [l, fmt[m1 != null && m2 != null ? 2 : 1]];
829
    }
830
    return [l, ff];
831
}
832
function format(fmt,v,o) {
833
    fixopts(o != null ? o : (o=[]));
834
    var sfmt = "";
835
    switch(typeof fmt) {
836
        case "string": sfmt = fmt; break;
837
        case "number": sfmt = (o.table != null ? o.table : table_fmt)[fmt]; break;
838
    }
839
    if(isgeneral(sfmt,0)) return general_fmt(v, o);
840
    var f = choose_fmt(sfmt, v);
841
    if(isgeneral(f[1])) return general_fmt(v, o);
842
    if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
843
    else if(v === "" || v == null) return "";
844
    return eval_fmt(f[1], v, o, f[0]);
845
}
846
SSF._table = table_fmt;
847
SSF.load = function load_entry(fmt, idx) { table_fmt[idx] = fmt; };
848
SSF.format = format;
849
SSF.get_table = function get_table() { return table_fmt; };
850
SSF.load_table = function load_table(tbl) { for(var i=0; i!=0x0188; ++i) if(tbl[i] !== undefined) SSF.load(tbl[i], i); };
851
};
852
make_ssf(SSF);
853
/* map from xlml named formats to SSF TODO: localize */
854
var XLMLFormatMap = {
855
    "General Number": "General",
856
    "General Date": SSF._table[22],
857
    "Long Date": "dddd, mmmm dd, yyyy",
858
    "Medium Date": SSF._table[15],
859
    "Short Date": SSF._table[14],
860
    "Long Time": SSF._table[19],
861
    "Medium Time": SSF._table[18],
862
    "Short Time": SSF._table[20],
863
    "Currency": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
864
    "Fixed": SSF._table[2],
865
    "Standard": SSF._table[4],
866
    "Percent": SSF._table[10],
867
    "Scientific": SSF._table[11],
868
    "Yes/No": '"Yes";"Yes";"No";@',
869
    "True/False": '"True";"True";"False";@',
870
    "On/Off": '"Yes";"Yes";"No";@'
871
};
872
 
873
var DO_NOT_EXPORT_CFB = true;
874
/* cfb.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
875
/* vim: set ts=2: */
876
/*jshint eqnull:true */
877
 
878
/* [MS-CFB] v20130118 */
879
var CFB = (function _CFB(){
880
var exports = {};
881
exports.version = '0.10.2';
882
function parse(file) {
883
var mver = 3; // major version
884
var ssz = 512; // sector size
885
var nmfs = 0; // number of mini FAT sectors
886
var ndfs = 0; // number of DIFAT sectors
887
var dir_start = 0; // first directory sector location
888
var minifat_start = 0; // first mini FAT sector location
889
var difat_start = 0; // first mini FAT sector location
890
 
891
var fat_addrs = []; // locations of FAT sectors
892
 
893
/* [MS-CFB] 2.2 Compound File Header */
894
var blob = file.slice(0,512);
895
prep_blob(blob, 0);
896
 
897
/* major version */
898
var mv = check_get_mver(blob);
899
mver = mv[0];
900
switch(mver) {
901
    case 3: ssz = 512; break; case 4: ssz = 4096; break;
902
    default: throw "Major Version: Expected 3 or 4 saw " + mver;
903
}
904
 
905
/* reprocess header */
906
if(ssz !== 512) { blob = file.slice(0,ssz); prep_blob(blob, 28 /* blob.l */); }
907
/* Save header for final object */
908
var header = file.slice(0,ssz);
909
 
910
check_shifts(blob, mver);
911
 
912
// Number of Directory Sectors
913
var nds = blob.read_shift(4, 'i');
914
if(mver === 3 && nds !== 0) throw '# Directory Sectors: Expected 0 saw ' + nds;
915
 
916
// Number of FAT Sectors
917
//var nfs = blob.read_shift(4, 'i');
918
blob.l += 4;
919
 
920
// First Directory Sector Location
921
dir_start = blob.read_shift(4, 'i');
922
 
923
// Transaction Signature
924
blob.l += 4;
925
 
926
// Mini Stream Cutoff Size
927
blob.chk('00100000', 'Mini Stream Cutoff Size: ');
928
 
929
// First Mini FAT Sector Location
930
minifat_start = blob.read_shift(4, 'i');
931
 
932
// Number of Mini FAT Sectors
933
nmfs = blob.read_shift(4, 'i');
934
 
935
// First DIFAT sector location
936
difat_start = blob.read_shift(4, 'i');
937
 
938
// Number of DIFAT Sectors
939
ndfs = blob.read_shift(4, 'i');
940
 
941
// Grab FAT Sector Locations
942
for(var q, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */
943
    q = blob.read_shift(4, 'i');
944
    if(q<0) break;
945
    fat_addrs[j] = q;
946
}
947
 
948
/** Break the file up into sectors */
949
var sectors = sectorify(file, ssz);
950
 
951
sleuth_fat(difat_start, ndfs, sectors, ssz, fat_addrs);
952
 
953
/** Chains */
954
var sector_list = make_sector_list(sectors, dir_start, fat_addrs, ssz);
955
 
956
sector_list[dir_start].name = "!Directory";
957
if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
958
sector_list[fat_addrs[0]].name = "!FAT";
959
sector_list.fat_addrs = fat_addrs;
960
sector_list.ssz = ssz;
961
 
962
/* [MS-CFB] 2.6.1 Compound File Directory Entry */
963
var files = {}, Paths = [], FileIndex = [], FullPaths = [], FullPathDir = {};
964
read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex);
965
 
966
build_full_paths(FileIndex, FullPathDir, FullPaths, Paths);
967
 
968
var root_name = Paths.shift();
969
Paths.root = root_name;
970
 
971
/* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */
972
var find_path = make_find_path(FullPaths, Paths, FileIndex, files, root_name);
973
 
974
return {
975
    raw: {header: header, sectors: sectors},
976
    FileIndex: FileIndex,
977
    FullPaths: FullPaths,
978
    FullPathDir: FullPathDir,
979
    find: find_path
980
};
981
} // parse
982
 
983
/* [MS-CFB] 2.2 Compound File Header -- read up to major version */
984
function check_get_mver(blob) {
985
    // header signature 8
986
    blob.chk(HEADER_SIGNATURE, 'Header Signature: ');
987
 
988
    // clsid 16
989
    blob.chk(HEADER_CLSID, 'CLSID: ');
990
 
991
    // minor version 2
992
    var mver = blob.read_shift(2, 'u');
993
 
994
    return [blob.read_shift(2,'u'), mver];
995
}
996
function check_shifts(blob, mver) {
997
    var shift = 0x09;
998
 
999
    // Byte Order
1000
    blob.chk('feff', 'Byte Order: ');
1001
 
1002
    // Sector Shift
1003
    switch((shift = blob.read_shift(2))) {
1004
        case 0x09: if(mver !== 3) throw 'MajorVersion/SectorShift Mismatch'; break;
1005
        case 0x0c: if(mver !== 4) throw 'MajorVersion/SectorShift Mismatch'; break;
1006
        default: throw 'Sector Shift: Expected 9 or 12 saw ' + shift;
1007
    }
1008
 
1009
    // Mini Sector Shift
1010
    blob.chk('0600', 'Mini Sector Shift: ');
1011
 
1012
    // Reserved
1013
    blob.chk('000000000000', 'Reserved: ');
1014
}
1015
 
1016
/** Break the file up into sectors */
1017
function sectorify(file, ssz) {
1018
    var nsectors = Math.ceil(file.length/ssz)-1;
1019
    var sectors = new Array(nsectors);
1020
    for(var i=1; i < nsectors; ++i) sectors[i-1] = file.slice(i*ssz,(i+1)*ssz);
1021
    sectors[nsectors-1] = file.slice(nsectors*ssz);
1022
    return sectors;
1023
}
1024
 
1025
/* [MS-CFB] 2.6.4 Red-Black Tree */
1026
function build_full_paths(FI, FPD, FP, Paths) {
1027
    var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length;
1028
    var dad = new Array(pl), q = new Array(pl);
1029
 
1030
    for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; }
1031
 
1032
    for(; j < q.length; ++j) {
1033
        i = q[j];
1034
        L = FI[i].L; R = FI[i].R; C = FI[i].C;
1035
        if(dad[i] === i) {
1036
            if(L !== -1 /*NOSTREAM*/ && dad[L] !== L) dad[i] = dad[L];
1037
            if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
1038
        }
1039
        if(C !== -1 /*NOSTREAM*/) dad[C] = i;
1040
        if(L !== -1) { dad[L] = dad[i]; q.push(L); }
1041
        if(R !== -1) { dad[R] = dad[i]; q.push(R); }
1042
    }
1043
    for(i=1; i !== pl; ++i) if(dad[i] === i) {
1044
        if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
1045
        else if(L !== -1 && dad[L] !== L) dad[i] = dad[L];
1046
    }
1047
 
1048
    for(i=1; i < pl; ++i) {
1049
        if(FI[i].type === 0 /* unknown */) continue;
1050
        j = dad[i];
1051
        if(j === 0) FP[i] = FP[0] + "/" + FP[i];
1052
        else while(j !== 0) {
1053
            FP[i] = FP[j] + "/" + FP[i];
1054
            j = dad[j];
1055
        }
1056
        dad[i] = 0;
1057
    }
1058
 
1059
    FP[0] += "/";
1060
    for(i=1; i < pl; ++i) {
1061
        if(FI[i].type !== 2 /* stream */) FP[i] += "/";
1062
        FPD[FP[i]] = FI[i];
1063
    }
1064
}
1065
 
1066
/* [MS-CFB] 2.6.4 */
1067
function make_find_path(FullPaths, Paths, FileIndex, files, root_name) {
1068
    var UCFullPaths = new Array(FullPaths.length);
1069
    var UCPaths = new Array(Paths.length), i;
1070
    for(i = 0; i < FullPaths.length; ++i) UCFullPaths[i] = FullPaths[i].toUpperCase().replace(chr0,'').replace(chr1,'!');
1071
    for(i = 0; i < Paths.length; ++i) UCPaths[i] = Paths[i].toUpperCase().replace(chr0,'').replace(chr1,'!');
1072
    return function find_path(path) {
1073
        var k;
1074
        if(path.charCodeAt(0) === 47 /* "/" */) { k=true; path = root_name + path; }
1075
        else k = path.indexOf("/") !== -1;
1076
        var UCPath = path.toUpperCase().replace(chr0,'').replace(chr1,'!');
1077
        var w = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath);
1078
        if(w === -1) return null;
1079
        return k === true ? FileIndex[w] : files[Paths[w]];
1080
    };
1081
}
1082
 
1083
/** Chase down the rest of the DIFAT chain to build a comprehensive list
1084
    DIFAT chains by storing the next sector number as the last 32 bytes */
1085
function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) {
1086
    var q;
1087
    if(idx === ENDOFCHAIN) {
1088
        if(cnt !== 0) throw "DIFAT chain shorter than expected";
1089
    } else if(idx !== -1 /*FREESECT*/) {
1090
        var sector = sectors[idx], m = (ssz>>>2)-1;
1091
        for(var i = 0; i < m; ++i) {
1092
            if((q = __readInt32LE(sector,i*4)) === ENDOFCHAIN) break;
1093
            fat_addrs.push(q);
1094
        }
1095
        sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs);
1096
    }
1097
}
1098
 
1099
/** Follow the linked list of sectors for a given starting point */
1100
function get_sector_list(sectors, start, fat_addrs, ssz, chkd) {
1101
    var sl = sectors.length;
1102
    var buf, buf_chain;
1103
    if(!chkd) chkd = new Array(sl);
1104
    var modulus = ssz - 1, j, jj;
1105
    buf = [];
1106
    buf_chain = [];
1107
    for(j=start; j>=0;) {
1108
        chkd[j] = true;
1109
        buf[buf.length] = j;
1110
        buf_chain.push(sectors[j]);
1111
        var addr = fat_addrs[Math.floor(j*4/ssz)];
1112
        jj = ((j*4) & modulus);
1113
        if(ssz < 4 + jj) throw "FAT boundary crossed: " + j + " 4 "+ssz;
1114
        j = __readInt32LE(sectors[addr], jj);
1115
    }
1116
    return {nodes: buf, data:__toBuffer([buf_chain])};
1117
}
1118
 
1119
/** Chase down the sector linked lists */
1120
function make_sector_list(sectors, dir_start, fat_addrs, ssz) {
1121
    var sl = sectors.length, sector_list = new Array(sl);
1122
    var chkd = new Array(sl), buf, buf_chain;
1123
    var modulus = ssz - 1, i, j, k, jj;
1124
    for(i=0; i < sl; ++i) {
1125
        buf = [];
1126
        k = (i + dir_start); if(k >= sl) k-=sl;
1127
        if(chkd[k] === true) continue;
1128
        buf_chain = [];
1129
        for(j=k; j>=0;) {
1130
            chkd[j] = true;
1131
            buf[buf.length] = j;
1132
            buf_chain.push(sectors[j]);
1133
            var addr = fat_addrs[Math.floor(j*4/ssz)];
1134
            jj = ((j*4) & modulus);
1135
            if(ssz < 4 + jj) throw "FAT boundary crossed: " + j + " 4 "+ssz;
1136
            j = __readInt32LE(sectors[addr], jj);
1137
        }
1138
        sector_list[k] = {nodes: buf, data:__toBuffer([buf_chain])};
1139
    }
1140
    return sector_list;
1141
}
1142
 
1143
/* [MS-CFB] 2.6.1 Compound File Directory Entry */
1144
function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex) {
1145
    var blob;
1146
    var minifat_store = 0, pl = (Paths.length?2:0);
1147
    var sector = sector_list[dir_start].data;
1148
    var i = 0, namelen = 0, name, o, ctime, mtime;
1149
    for(; i < sector.length; i+= 128) {
1150
        blob = sector.slice(i, i+128);
1151
        prep_blob(blob, 64);
1152
        namelen = blob.read_shift(2);
1153
        if(namelen === 0) continue;
1154
        name = __utf16le(blob,0,namelen-pl);
1155
        Paths.push(name);
1156
        o = {
1157
            name:  name,
1158
            type:  blob.read_shift(1),
1159
            color: blob.read_shift(1),
1160
            L:     blob.read_shift(4, 'i'),
1161
            R:     blob.read_shift(4, 'i'),
1162
            C:     blob.read_shift(4, 'i'),
1163
            clsid: blob.read_shift(16),
1164
            state: blob.read_shift(4, 'i')
1165
        };
1166
        ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2);
1167
        if(ctime !== 0) {
1168
            o.ctime = ctime; o.ct = read_date(blob, blob.l-8);
1169
        }
1170
        mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2);
1171
        if(mtime !== 0) {
1172
            o.mtime = mtime; o.mt = read_date(blob, blob.l-8);
1173
        }
1174
        o.start = blob.read_shift(4, 'i');
1175
        o.size = blob.read_shift(4, 'i');
1176
        if(o.type === 5) { /* root */
1177
            minifat_store = o.start;
1178
            if(nmfs > 0 && minifat_store !== ENDOFCHAIN) sector_list[minifat_store].name = "!StreamData";
1179
            /*minifat_size = o.size;*/
1180
        } else if(o.size >= 4096 /* MSCSZ */) {
1181
            o.storage = 'fat';
1182
            if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz);
1183
            sector_list[o.start].name = o.name;
1184
            o.content = sector_list[o.start].data.slice(0,o.size);
1185
            prep_blob(o.content, 0);
1186
        } else {
1187
            o.storage = 'minifat';
1188
            if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN) {
1189
                o.content = sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size);
1190
                prep_blob(o.content, 0);
1191
            }
1192
        }
1193
        files[name] = o;
1194
        FileIndex.push(o);
1195
    }
1196
}
1197
 
1198
function read_date(blob, offset) {
1199
    return new Date(( ( (__readUInt32LE(blob,offset+4)/1e7)*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7 ) - 11644473600)*1000);
1200
}
1201
 
1202
var fs;
1203
function readFileSync(filename, options) {
1204
    if(fs === undefined) fs = require('fs');
1205
    return parse(fs.readFileSync(filename), options);
1206
}
1207
 
1208
function readSync(blob, options) {
1209
    switch(options !== undefined && options.type !== undefined ? options.type : "base64") {
1210
        case "file": return readFileSync(blob, options);
1211
        case "base64": return parse(s2a(Base64.decode(blob)), options);
1212
        case "binary": return parse(s2a(blob), options);
1213
    }
1214
    return parse(blob);
1215
}
1216
 
1217
/** CFB Constants */
1218
var MSSZ = 64; /* Mini Sector Size = 1<<6 */
1219
//var MSCSZ = 4096; /* Mini Stream Cutoff Size */
1220
/* 2.1 Compound File Sector Numbers and Types */
1221
var ENDOFCHAIN = -2;
1222
/* 2.2 Compound File Header */
1223
var HEADER_SIGNATURE = 'd0cf11e0a1b11ae1';
1224
var HEADER_CLSID = '00000000000000000000000000000000';
1225
var consts = {
1226
    /* 2.1 Compund File Sector Numbers and Types */
1227
    MAXREGSECT: -6,
1228
    DIFSECT: -4,
1229
    FATSECT: -3,
1230
    ENDOFCHAIN: ENDOFCHAIN,
1231
    FREESECT: -1,
1232
    /* 2.2 Compound File Header */
1233
    HEADER_SIGNATURE: HEADER_SIGNATURE,
1234
    HEADER_MINOR_VERSION: '3e00',
1235
    MAXREGSID: -6,
1236
    NOSTREAM: -1,
1237
    HEADER_CLSID: HEADER_CLSID,
1238
    /* 2.6.1 Compound File Directory Entry */
1239
    EntryTypes: ['unknown','storage','stream','lockbytes','property','root']
1240
};
1241
 
1242
exports.read = readSync;
1243
exports.parse = parse;
1244
exports.utils = {
1245
    ReadShift: ReadShift,
1246
    CheckField: CheckField,
1247
    prep_blob: prep_blob,
1248
    bconcat: bconcat,
1249
    consts: consts
1250
};
1251
 
1252
return exports;
1253
})();
1254
 
1255
if(typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO_NOT_EXPORT_CFB === 'undefined') { module.exports = CFB; }
1256
function isval(x) { return x !== undefined && x !== null; }
1257
 
1258
function keys(o) { return Object.keys(o); }
1259
 
1260
function evert_key(obj, key) {
1261
    var o = [], K = keys(obj);
1262
    for(var i = 0; i !== K.length; ++i) o[obj[K[i]][key]] = K[i];
1263
    return o;
1264
}
1265
 
1266
function evert(obj) {
1267
    var o = [], K = keys(obj);
1268
    for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = K[i];
1269
    return o;
1270
}
1271
 
1272
function evert_num(obj) {
1273
    var o = [], K = keys(obj);
1274
    for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = parseInt(K[i],10);
1275
    return o;
1276
}
1277
 
1278
function evert_arr(obj) {
1279
    var o = [], K = keys(obj);
1280
    for(var i = 0; i !== K.length; ++i) {
1281
        if(o[obj[K[i]]] == null) o[obj[K[i]]] = [];
1282
        o[obj[K[i]]].push(K[i]);
1283
    }
1284
    return o;
1285
}
1286
 
1287
/* TODO: date1904 logic */
1288
function datenum(v, date1904) {
1289
    if(date1904) v+=1462;
1290
    var epoch = Date.parse(v);
1291
    return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
1292
}
1293
 
1294
function cc2str(arr) {
1295
    var o = "";
1296
    for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
1297
    return o;
1298
}
1299
 
1300
function getdata(data) {
1301
    if(!data) return null;
1302
    if(data.name.substr(-4) === ".bin") {
1303
        if(data.data) return char_codes(data.data);
1304
        if(data.asNodeBuffer && has_buf) return data.asNodeBuffer();
1305
        if(data._data && data._data.getContent) return Array.prototype.slice.call(data._data.getContent());
1306
    } else {
1307
        if(data.data) return data.name.substr(-4) !== ".bin" ? debom_xml(data.data) : char_codes(data.data);
1308
        if(data.asNodeBuffer && has_buf) return debom_xml(data.asNodeBuffer().toString('binary'));
1309
        if(data.asBinary) return debom_xml(data.asBinary());
1310
        if(data._data && data._data.getContent) return debom_xml(cc2str(Array.prototype.slice.call(data._data.getContent(),0)));
1311
    }
1312
    return null;
1313
}
1314
 
1315
function safegetzipfile(zip, file) {
1316
    var f = file; if(zip.files[f]) return zip.files[f];
1317
    f = file.toLowerCase(); if(zip.files[f]) return zip.files[f];
1318
    f = f.replace(/\//g,'\\'); if(zip.files[f]) return zip.files[f];
1319
    return null;
1320
}
1321
 
1322
function getzipfile(zip, file) {
1323
    var o = safegetzipfile(zip, file);
1324
    if(o == null) throw new Error("Cannot find file " + file + " in zip");
1325
    return o;
1326
}
1327
 
1328
function getzipdata(zip, file, safe) {
1329
    if(!safe) return getdata(getzipfile(zip, file));
1330
    if(!file) return null;
1331
    try { return getzipdata(zip, file); } catch(e) { return null; }
1332
}
1333
 
1334
var _fs, jszip;
1335
if(typeof JSZip !== 'undefined') jszip = JSZip;
1336
if (typeof exports !== 'undefined') {
1337
    if (typeof module !== 'undefined' && module.exports) {
1338
        if(has_buf && typeof jszip === 'undefined') jszip = require('js'+'zip');
1339
        if(typeof jszip === 'undefined') jszip = require('./js'+'zip').JSZip;
1340
        _fs = require('f'+'s');
1341
    }
1342
}
1343
var attregexg=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
1344
var tagregex=/<[^>]*>/g;
1345
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
1346
function parsexmltag(tag, skip_root) {
1347
    var z = [];
1348
    var eq = 0, c = 0;
1349
    for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
1350
    if(!skip_root) z[0] = tag.substr(0, eq);
1351
    if(eq === tag.length) return z;
1352
    var m = tag.match(attregexg), j=0, w="", v="", i=0, q="", cc="";
1353
    if(m) for(i = 0; i != m.length; ++i) {
1354
        cc = m[i];
1355
        for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
1356
        q = cc.substr(0,c); v = cc.substring(c+2, cc.length-1);
1357
        for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
1358
        if(j===q.length) z[q] = v;
1359
        else z[(j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1)] = v;
1360
    }
1361
    return z;
1362
}
1363
function strip_ns(x) { return x.replace(nsregex2, "<$1"); }
1364
 
1365
var encodings = {
1366
    '&quot;': '"',
1367
    '&apos;': "'",
1368
    '&gt;': '>',
1369
    '&lt;': '<',
1370
    '&amp;': '&'
1371
};
1372
var rencoding = evert(encodings);
1373
var rencstr = "&<>'\"".split("");
1374
 
1375
// TODO: CP remap (need to read file version to determine OS)
1376
var unescapexml = (function() {
1377
    var encregex = /&[a-z]*;/g, coderegex = /_x([\da-fA-F]+)_/g;
1378
    return function unescapexml(text){
1379
        var s = text + '';
1380
        return s.replace(encregex, function($$) { return encodings[$$]; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
1381
    };
1382
})();
1383
 
1384
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
1385
function escapexml(text){
1386
    var s = text + '';
1387
    return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).substr(-4) + "_";});
1388
}
1389
 
1390
/* TODO: handle codepages */
1391
var xlml_fixstr = (function() {
1392
    var entregex = /&#(\d+);/g;
1393
    function entrepl($$,$1) { return String.fromCharCode(parseInt($1,10)); }
1394
    return function xlml_fixstr(str) { return str.replace(entregex,entrepl); };
1395
})();
1396
 
1397
function parsexmlbool(value, tag) {
1398
    switch(value) {
1399
        case '1': case 'true': case 'TRUE': return true;
1400
        /* case '0': case 'false': case 'FALSE':*/
1401
        default: return false;
1402
    }
1403
}
1404
 
1405
var utf8read = function utf8reada(orig) {
1406
    var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
1407
    while (i < orig.length) {
1408
        c = orig.charCodeAt(i++);
1409
        if (c < 128) { out += String.fromCharCode(c); continue; }
1410
        d = orig.charCodeAt(i++);
1411
        if (c>191 && c<224) { out += String.fromCharCode(((c & 31) << 6) | (d & 63)); continue; }
1412
        e = orig.charCodeAt(i++);
1413
        if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; }
1414
        f = orig.charCodeAt(i++);
1415
        w = (((c & 7) << 18) | ((d & 63) << 12) | ((e & 63) << 6) | (f & 63))-65536;
1416
        out += String.fromCharCode(0xD800 + ((w>>>10)&1023));
1417
        out += String.fromCharCode(0xDC00 + (w&1023));
1418
    }
1419
    return out;
1420
};
1421
 
1422
 
1423
if(has_buf) {
1424
    var utf8readb = function utf8readb(data) {
1425
        var out = new Buffer(2*data.length), w, i, j = 1, k = 0, ww=0, c;
1426
        for(i = 0; i < data.length; i+=j) {
1427
            j = 1;
1428
            if((c=data.charCodeAt(i)) < 128) w = c;
1429
            else if(c < 224) { w = (c&31)*64+(data.charCodeAt(i+1)&63); j=2; }
1430
            else if(c < 240) { w=(c&15)*4096+(data.charCodeAt(i+1)&63)*64+(data.charCodeAt(i+2)&63); j=3; }
1431
            else { j = 4;
1432
                w = (c & 7)*262144+(data.charCodeAt(i+1)&63)*4096+(data.charCodeAt(i+2)&63)*64+(data.charCodeAt(i+3)&63);
1433
                w -= 65536; ww = 0xD800 + ((w>>>10)&1023); w = 0xDC00 + (w&1023);
1434
            }
1435
            if(ww !== 0) { out[k++] = ww&255; out[k++] = ww>>>8; ww = 0; }
1436
            out[k++] = w%256; out[k++] = w>>>8;
1437
        }
1438
        out.length = k;
1439
        return out.toString('ucs2');
1440
    };
1441
    var corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3";
1442
    if(utf8read(corpus) == utf8readb(corpus)) utf8read = utf8readb;
1443
    var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
1444
    if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
1445
}
1446
 
1447
// matches <foo>...</foo> extracts content
1448
var matchtag = (function() {
1449
    var mtcache = {};
1450
    return function matchtag(f,g) {
1451
        var t = f+"|"+g;
1452
        if(mtcache[t] !== undefined) return mtcache[t];
1453
        return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([^\u2603]*)</(?:\\w+:)?'+f+'>',(g||"")));
1454
    };
1455
})();
1456
 
1457
var vtregex = (function(){ var vt_cache = {};
1458
    return function vt_regex(bt) {
1459
        if(vt_cache[bt] !== undefined) return vt_cache[bt];
1460
        return (vt_cache[bt] = new RegExp("<vt:" + bt + ">(.*?)</vt:" + bt + ">", 'g') );
1461
};})();
1462
var vtvregex = /<\/?vt:variant>/g, vtmregex = /<vt:([^>]*)>(.*)</;
1463
function parseVector(data) {
1464
    var h = parsexmltag(data);
1465
 
1466
    var matches = data.match(vtregex(h.baseType))||[];
1467
    if(matches.length != h.size) throw "unexpected vector length " + matches.length + " != " + h.size;
1468
    var res = [];
1469
    matches.forEach(function(x) {
1470
        var v = x.replace(vtvregex,"").match(vtmregex);
1471
        res.push({v:v[2], t:v[1]});
1472
    });
1473
    return res;
1474
}
1475
 
1476
var wtregex = /(^\s|\s$|\n)/;
1477
function writetag(f,g) {return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>';}
1478
 
1479
function wxt_helper(h) { return keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join(""); }
1480
function writextag(f,g,h) { return '<' + f + (isval(h) ? wxt_helper(h) : "") + (isval(g) ? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';}
1481
 
1482
function write_w3cdtf(d, t) { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } }
1483
 
1484
function write_vt(s) {
1485
    switch(typeof s) {
1486
        case 'string': return writextag('vt:lpwstr', s);
1487
        case 'number': return writextag((s|0)==s?'vt:i4':'vt:r8', String(s));
1488
        case 'boolean': return writextag('vt:bool',s?'true':'false');
1489
    }
1490
    if(s instanceof Date) return writextag('vt:filetime', write_w3cdtf(s));
1491
    throw new Error("Unable to serialize " + s);
1492
}
1493
 
1494
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
1495
var XMLNS = {
1496
    'dc': 'http://purl.org/dc/elements/1.1/',
1497
    'dcterms': 'http://purl.org/dc/terms/',
1498
    'dcmitype': 'http://purl.org/dc/dcmitype/',
1499
    'mx': 'http://schemas.microsoft.com/office/mac/excel/2008/main',
1500
    'r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
1501
    'sjs': 'http://schemas.openxmlformats.org/package/2006/sheetjs/core-properties',
1502
    'vt': 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes',
1503
    'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
1504
    'xsd': 'http://www.w3.org/2001/XMLSchema'
1505
};
1506
 
1507
XMLNS.main = [
1508
    'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
1509
    'http://purl.oclc.org/ooxml/spreadsheetml/main',
1510
    'http://schemas.microsoft.com/office/excel/2006/main',
1511
    'http://schemas.microsoft.com/office/excel/2006/2'
1512
];
1513
 
1514
function readIEEE754(buf, idx, isLE, nl, ml) {
1515
    if(isLE === undefined) isLE = true;
1516
    if(!nl) nl = 8;
1517
    if(!ml && nl === 8) ml = 52;
1518
    var e, m, el = nl * 8 - ml - 1, eMax = (1 << el) - 1, eBias = eMax >> 1;
1519
    var bits = -7, d = isLE ? -1 : 1, i = isLE ? (nl - 1) : 0, s = buf[idx + i];
1520
 
1521
    i += d;
1522
    e = s & ((1 << (-bits)) - 1); s >>>= (-bits); bits += el;
1523
    for (; bits > 0; e = e * 256 + buf[idx + i], i += d, bits -= 8);
1524
    m = e & ((1 << (-bits)) - 1); e >>>= (-bits); bits += ml;
1525
    for (; bits > 0; m = m * 256 + buf[idx + i], i += d, bits -= 8);
1526
    if (e === eMax) return m ? NaN : ((s ? -1 : 1) * Infinity);
1527
    else if (e === 0) e = 1 - eBias;
1528
    else { m = m + Math.pow(2, ml); e = e - eBias; }
1529
    return (s ? -1 : 1) * m * Math.pow(2, e - ml);
1530
}
1531
 
1532
var __toBuffer, ___toBuffer;
1533
__toBuffer = ___toBuffer = function toBuffer_(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; };
1534
var __utf16le, ___utf16le;
1535
__utf16le = ___utf16le = function utf16le_(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join(""); };
1536
var __hexlify, ___hexlify;
1537
__hexlify = ___hexlify = function hexlify_(b,s,l) { return b.slice(s,(s+l)).map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); };
1538
var __utf8, ___utf8;
1539
__utf8 = ___utf8 = function(b,s,e) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
1540
var __lpstr, ___lpstr;
1541
__lpstr = ___lpstr = function lpstr_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
1542
var __lpwstr, ___lpwstr;
1543
__lpwstr = ___lpwstr = function lpwstr_(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
1544
var __double, ___double;
1545
__double = ___double = function(b, idx) { return readIEEE754(b, idx);};
1546
 
1547
var is_buf = function is_buf_a(a) { return Array.isArray(a); };
1548
if(has_buf) {
1549
    __utf16le = function utf16le_b(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e); };
1550
    __hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
1551
    __lpstr = function lpstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
1552
    __lpwstr = function lpwstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
1553
    __utf8 = function utf8_b(s,e) { return this.toString('utf8',s,e); };
1554
    __toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);};
1555
    bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); };
1556
    __double = function double_(b,i) { if(Buffer.isBuffer(b)) return b.readDoubleLE(i); return ___double(b,i); };
1557
    is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); };
1558
}
1559
 
1560
/* from js-xls */
1561
if(typeof cptable !== 'undefined') {
1562
    __utf16le = function(b,s,e) { return cptable.utils.decode(1200, b.slice(s,e)); };
1563
    __utf8 = function(b,s,e) { return cptable.utils.decode(65001, b.slice(s,e)); };
1564
    __lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";};
1565
    __lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";};
1566
}
1567
 
1568
var __readUInt8 = function(b, idx) { return b[idx]; };
1569
var __readUInt16LE = function(b, idx) { return b[idx+1]*(1<<8)+b[idx]; };
1570
var __readInt16LE = function(b, idx) { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; };
1571
var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
1572
var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
1573
 
1574
var ___unhexlify = function(s) { return s.match(/../g).map(function(x) { return parseInt(x,16);}); };
1575
var __unhexlify = typeof Buffer !== "undefined" ? function(s) { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;
1576
 
1577
function ReadShift(size, t) {
1578
    var o="", oI, oR, oo=[], w, vv, i, loc;
1579
    switch(t) {
1580
        case 'dbcs':
1581
            loc = this.l;
1582
            if(has_buf && Buffer.isBuffer(this)) o = this.slice(this.l, this.l+2*size).toString("utf16le");
1583
            else for(i = 0; i != size; ++i) { o+=String.fromCharCode(__readUInt16LE(this, loc)); loc+=2; }
1584
            size *= 2;
1585
            break;
1586
 
1587
        case 'utf8': o = __utf8(this, this.l, this.l + size); break;
1588
        case 'utf16le': size *= 2; o = __utf16le(this, this.l, this.l + size); break;
1589
 
1590
        /* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */
1591
        case 'lpstr': o = __lpstr(this, this.l); size = 5 + o.length; break;
1592
        /* [MS-OLEDS] 2.1.5 LengthPrefixedUnicodeString */
1593
        case 'lpwstr': o = __lpwstr(this, this.l); size = 5 + o.length; if(o[o.length-1] == '\u0000') size += 2; break;
1594
 
1595
        case 'cstr': size = 0; o = "";
1596
            while((w=__readUInt8(this, this.l + size++))!==0) oo.push(_getchar(w));
1597
            o = oo.join(""); break;
1598
        case 'wstr': size = 0; o = "";
1599
            while((w=__readUInt16LE(this,this.l +size))!==0){oo.push(_getchar(w));size+=2;}
1600
            size+=2; o = oo.join(""); break;
1601
 
1602
        /* sbcs and dbcs support continue records in the SST way TODO codepages */
1603
        case 'dbcs-cont': o = ""; loc = this.l;
1604
            for(i = 0; i != size; ++i) {
1605
                if(this.lens && this.lens.indexOf(loc) !== -1) {
1606
                    w = __readUInt8(this, loc);
1607
                    this.l = loc + 1;
1608
                    vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont');
1609
                    return oo.join("") + vv;
1610
                }
1611
                oo.push(_getchar(__readUInt16LE(this, loc)));
1612
                loc+=2;
1613
            } o = oo.join(""); size *= 2; break;
1614
 
1615
        case 'sbcs-cont': o = ""; loc = this.l;
1616
            for(i = 0; i != size; ++i) {
1617
                if(this.lens && this.lens.indexOf(loc) !== -1) {
1618
                    w = __readUInt8(this, loc);
1619
                    this.l = loc + 1;
1620
                    vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont');
1621
                    return oo.join("") + vv;
1622
                }
1623
                oo.push(_getchar(__readUInt8(this, loc)));
1624
                loc+=1;
1625
            } o = oo.join(""); break;
1626
 
1627
        default:
1628
    switch(size) {
1629
        case 1: oI = __readUInt8(this, this.l); this.l++; return oI;
1630
        case 2: oI = (t === 'i' ? __readInt16LE : __readUInt16LE)(this, this.l); this.l += 2; return oI;
1631
        case 4:
1632
            if(t === 'i' || (this[this.l+3] & 0x80)===0) { oI = __readInt32LE(this, this.l); this.l += 4; return oI; }
1633
            else { oR = __readUInt32LE(this, this.l); this.l += 4; return oR; } break;
1634
        case 8: if(t === 'f') { oR = __double(this, this.l); this.l += 8; return oR; }
1635
        /* falls through */
1636
        case 16: o = __hexlify(this, this.l, size); break;
1637
    }}
1638
    this.l+=size; return o;
1639
}
1640
 
1641
function WriteShift(t, val, f) {
1642
    var size, i;
1643
    if(f === 'dbcs') {
1644
        for(i = 0; i != val.length; ++i) this.writeUInt16LE(val.charCodeAt(i), this.l + 2 * i);
1645
        size = 2 * val.length;
1646
    } else switch(t) {
1647
        case  1: size = 1; this[this.l] = val&255; break;
1648
        case  3: size = 3; this[this.l+2] = val & 255; val >>>= 8; this[this.l+1] = val&255; val >>>= 8; this[this.l] = val&255; break;
1649
        case  4: size = 4; this.writeUInt32LE(val, this.l); break;
1650
        case  8: size = 8; if(f === 'f') { this.writeDoubleLE(val, this.l); break; }
1651
        /* falls through */
1652
        case 16: break;
1653
        case -4: size = 4; this.writeInt32LE(val, this.l); break;
1654
    }
1655
    this.l += size; return this;
1656
}
1657
 
1658
function CheckField(hexstr, fld) {
1659
    var m = __hexlify(this,this.l,hexstr.length>>1);
1660
    if(m !== hexstr) throw fld + 'Expected ' + hexstr + ' saw ' + m;
1661
    this.l += hexstr.length>>1;
1662
}
1663
 
1664
function prep_blob(blob, pos) {
1665
    blob.l = pos;
1666
    blob.read_shift = ReadShift;
1667
    blob.chk = CheckField;
1668
    blob.write_shift = WriteShift;
1669
}
1670
 
1671
function parsenoop(blob, length) { blob.l += length; }
1672
 
1673
function writenoop(blob, length) { blob.l += length; }
1674
 
1675
function new_buf(sz) {
1676
    var o = new_raw_buf(sz);
1677
    prep_blob(o, 0);
1678
    return o;
1679
}
1680
 
1681
/* [MS-XLSB] 2.1.4 Record */
1682
function recordhopper(data, cb, opts) {
1683
    var tmpbyte, cntbyte, length;
1684
    prep_blob(data, data.l || 0);
1685
    while(data.l < data.length) {
1686
        var RT = data.read_shift(1);
1687
        if(RT & 0x80) RT = (RT & 0x7F) + ((data.read_shift(1) & 0x7F)<<7);
1688
        var R = XLSBRecordEnum[RT] || XLSBRecordEnum[0xFFFF];
1689
        tmpbyte = data.read_shift(1);
1690
        length = tmpbyte & 0x7F;
1691
        for(cntbyte = 1; cntbyte <4 && (tmpbyte & 0x80); ++cntbyte) length += ((tmpbyte = data.read_shift(1)) & 0x7F)<<(7*cntbyte);
1692
        var d = R.f(data, length, opts);
1693
        if(cb(d, R, RT)) return;
1694
    }
1695
}
1696
 
1697
/* control buffer usage for fixed-length buffers */
1698
function buf_array() {
1699
    var bufs = [], blksz = 2048;
1700
    var newblk = function ba_newblk(sz) {
1701
        var o = new_buf(sz);
1702
        prep_blob(o, 0);
1703
        return o;
1704
    };
1705
 
1706
    var curbuf = newblk(blksz);
1707
 
1708
    var endbuf = function ba_endbuf() {
1709
        curbuf.length = curbuf.l;
1710
        if(curbuf.length > 0) bufs.push(curbuf);
1711
        curbuf = null;
1712
    };
1713
 
1714
    var next = function ba_next(sz) {
1715
        if(sz < curbuf.length - curbuf.l) return curbuf;
1716
        endbuf();
1717
        return (curbuf = newblk(Math.max(sz+1, blksz)));
1718
    };
1719
 
1720
    var end = function ba_end() {
1721
        endbuf();
1722
        return __toBuffer([bufs]);
1723
    };
1724
 
1725
    var push = function ba_push(buf) { endbuf(); curbuf = buf; next(blksz); };
1726
 
1727
    return { next:next, push:push, end:end, _bufs:bufs };
1728
}
1729
 
1730
function write_record(ba, type, payload, length) {
1731
    var t = evert_RE[type], l;
1732
    if(!length) length = XLSBRecordEnum[t].p || (payload||[]).length || 0;
1733
    l = 1 + (t >= 0x80 ? 1 : 0) + 1 + length;
1734
    if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l;
1735
    var o = ba.next(l);
1736
    if(t <= 0x7F) o.write_shift(1, t);
1737
    else {
1738
        o.write_shift(1, (t & 0x7F) + 0x80);
1739
        o.write_shift(1, (t >> 7));
1740
    }
1741
    for(var i = 0; i != 4; ++i) {
1742
        if(length >= 0x80) { o.write_shift(1, (length & 0x7F)+0x80); length >>= 7; }
1743
        else { o.write_shift(1, length); break; }
1744
    }
1745
    if(length > 0 && is_buf(payload)) ba.push(payload);
1746
}
1747
/* XLS ranges enforced */
1748
function shift_cell_xls(cell, tgt) {
1749
    if(tgt.s) {
1750
        if(cell.cRel) cell.c += tgt.s.c;
1751
        if(cell.rRel) cell.r += tgt.s.r;
1752
    } else {
1753
        cell.c += tgt.c;
1754
        cell.r += tgt.r;
1755
    }
1756
    cell.cRel = cell.rRel = 0;
1757
    while(cell.c >= 0x100) cell.c -= 0x100;
1758
    while(cell.r >= 0x10000) cell.r -= 0x10000;
1759
    return cell;
1760
}
1761
 
1762
function shift_range_xls(cell, range) {
1763
    cell.s = shift_cell_xls(cell.s, range.s);
1764
    cell.e = shift_cell_xls(cell.e, range.s);
1765
    return cell;
1766
}
1767
 
1768
var OFFCRYPTO = {};
1769
var make_offcrypto = function(O, _crypto) {
1770
    var crypto;
1771
    if(typeof _crypto !== 'undefined') crypto = _crypto;
1772
    else if(typeof require !== 'undefined') {
1773
        try { crypto = require('cry'+'pto'); }
1774
        catch(e) { crypto = null; }
1775
    }
1776
 
1777
    O.rc4 = function(key, data) {
1778
        var S = new Array(256);
1779
        var c = 0, i = 0, j = 0, t = 0;
1780
        for(i = 0; i != 256; ++i) S[i] = i;
1781
        for(i = 0; i != 256; ++i) {
1782
            j = (j + S[i] + (key[i%key.length]).charCodeAt(0))&255;
1783
            t = S[i]; S[i] = S[j]; S[j] = t;
1784
        }
1785
        i = j = 0; out = Buffer(data.length);
1786
        for(c = 0; c != data.length; ++c) {
1787
            i = (i + 1)&255;
1788
            j = (j + S[i])%256;
1789
            t = S[i]; S[i] = S[j]; S[j] = t;
1790
            out[c] = (data[c] ^ S[(S[i]+S[j])&255]);
1791
        }
1792
        return out;
1793
    };
1794
 
1795
    if(crypto) {
1796
        O.md5 = function(hex) { return crypto.createHash('md5').update(hex).digest('hex'); };
1797
    } else {
1798
        O.md5 = function(hex) { throw "unimplemented"; };
1799
    }
1800
};
1801
make_offcrypto(OFFCRYPTO, typeof crypto !== "undefined" ? crypto : undefined);
1802
 
1803
 
1804
/* [MS-XLSB] 2.5.143 */
1805
function parse_StrRun(data, length) {
1806
    return { ich: data.read_shift(2), ifnt: data.read_shift(2) };
1807
}
1808
 
1809
/* [MS-XLSB] 2.1.7.121 */
1810
function parse_RichStr(data, length) {
1811
    var start = data.l;
1812
    var flags = data.read_shift(1);
1813
    var str = parse_XLWideString(data);
1814
    var rgsStrRun = [];
1815
    var z = { t: str, h: str };
1816
    if((flags & 1) !== 0) { /* fRichStr */
1817
        /* TODO: formatted string */
1818
        var dwSizeStrRun = data.read_shift(4);
1819
        for(var i = 0; i != dwSizeStrRun; ++i) rgsStrRun.push(parse_StrRun(data));
1820
        z.r = rgsStrRun;
1821
    }
1822
    else z.r = "<t>" + escapexml(str) + "</t>";
1823
    if((flags & 2) !== 0) { /* fExtStr */
1824
        /* TODO: phonetic string */
1825
    }
1826
    data.l = start + length;
1827
    return z;
1828
}
1829
function write_RichStr(str, o) {
1830
    /* TODO: formatted string */
1831
    if(o == null) o = new_buf(5+2*str.t.length);
1832
    o.write_shift(1,0);
1833
    write_XLWideString(str.t, o);
1834
    return o;
1835
}
1836
 
1837
/* [MS-XLSB] 2.5.9 */
1838
function parse_XLSBCell(data) {
1839
    var col = data.read_shift(4);
1840
    var iStyleRef = data.read_shift(2);
1841
    iStyleRef += data.read_shift(1) <<16;
1842
    var fPhShow = data.read_shift(1);
1843
    return { c:col, iStyleRef: iStyleRef };
1844
}
1845
function write_XLSBCell(cell, o) {
1846
    if(o == null) o = new_buf(8);
1847
    o.write_shift(-4, cell.c);
1848
    o.write_shift(3, cell.iStyleRef === undefined ? cell.iStyleRef : cell.s);
1849
    o.write_shift(1, 0); /* fPhShow */
1850
    return o;
1851
}
1852
 
1853
 
1854
/* [MS-XLSB] 2.5.21 */
1855
function parse_XLSBCodeName (data, length) { return parse_XLWideString(data, length); }
1856
 
1857
/* [MS-XLSB] 2.5.166 */
1858
function parse_XLNullableWideString(data) {
1859
    var cchCharacters = data.read_shift(4);
1860
    return cchCharacters === 0 || cchCharacters === 0xFFFFFFFF ? "" : data.read_shift(cchCharacters, 'dbcs');
1861
}
1862
function write_XLNullableWideString(data, o) {
1863
    if(!o) o = new_buf(127);
1864
    o.write_shift(4, data.length > 0 ? data.length : 0xFFFFFFFF);
1865
    if(data.length > 0) o.write_shift(0, data, 'dbcs');
1866
    return o;
1867
}
1868
 
1869
/* [MS-XLSB] 2.5.168 */
1870
function parse_XLWideString(data) {
1871
    var cchCharacters = data.read_shift(4);
1872
    return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, 'dbcs');
1873
}
1874
function write_XLWideString(data, o) {
1875
    if(o == null) o = new_buf(4+2*data.length);
1876
    o.write_shift(4, data.length);
1877
    if(data.length > 0) o.write_shift(0, data, 'dbcs');
1878
    return o;
1879
}
1880
 
1881
/* [MS-XLSB] 2.5.114 */
1882
var parse_RelID = parse_XLNullableWideString;
1883
var write_RelID = write_XLNullableWideString;
1884
 
1885
 
1886
/* [MS-XLSB] 2.5.122 */
1887
/* [MS-XLS] 2.5.217 */
1888
function parse_RkNumber(data) {
1889
    var b = data.slice(data.l, data.l+4);
1890
    var fX100 = b[0] & 1, fInt = b[0] & 2;
1891
    data.l+=4;
1892
    b[0] &= 0xFC; // b[0] &= ~3;
1893
    var RK = fInt === 0 ? __double([0,0,0,0,b[0],b[1],b[2],b[3]],0) : __readInt32LE(b,0)>>2;
1894
    return fX100 ? RK/100 : RK;
1895
}
1896
 
1897
/* [MS-XLSB] 2.5.153 */
1898
function parse_UncheckedRfX(data) {
1899
    var cell = {s: {}, e: {}};
1900
    cell.s.r = data.read_shift(4);
1901
    cell.e.r = data.read_shift(4);
1902
    cell.s.c = data.read_shift(4);
1903
    cell.e.c = data.read_shift(4);
1904
    return cell;
1905
}
1906
 
1907
function write_UncheckedRfX(r, o) {
1908
    if(!o) o = new_buf(16);
1909
    o.write_shift(4, r.s.r);
1910
    o.write_shift(4, r.e.r);
1911
    o.write_shift(4, r.s.c);
1912
    o.write_shift(4, r.e.c);
1913
    return o;
1914
}
1915
 
1916
/* [MS-XLSB] 2.5.171 */
1917
/* [MS-XLS] 2.5.342 */
1918
function parse_Xnum(data, length) { return data.read_shift(8, 'f'); }
1919
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, 'f', data); }
1920
 
1921
/* [MS-XLSB] 2.5.198.2 */
1922
var BErr = {
1923
    0x00: "#NULL!",
1924
    0x07: "#DIV/0!",
1925
    0x0F: "#VALUE!",
1926
    0x17: "#REF!",
1927
    0x1D: "#NAME?",
1928
    0x24: "#NUM!",
1929
    0x2A: "#N/A",
1930
    0x2B: "#GETTING_DATA",
1931
    0xFF: "#WTF?"
1932
};
1933
var RBErr = evert_num(BErr);
1934
 
1935
/* [MS-XLSB] 2.4.321 BrtColor */
1936
function parse_BrtColor(data, length) {
1937
    var out = {};
1938
    var d = data.read_shift(1);
1939
    out.fValidRGB = d & 1;
1940
    out.xColorType = d >>> 1;
1941
    out.index = data.read_shift(1);
1942
    out.nTintAndShade = data.read_shift(2, 'i');
1943
    out.bRed   = data.read_shift(1);
1944
    out.bGreen = data.read_shift(1);
1945
    out.bBlue  = data.read_shift(1);
1946
    out.bAlpha = data.read_shift(1);
1947
}
1948
 
1949
/* [MS-XLSB] 2.5.52 */
1950
function parse_FontFlags(data, length) {
1951
    var d = data.read_shift(1);
1952
    data.l++;
1953
    var out = {
1954
        fItalic: d & 0x2,
1955
        fStrikeout: d & 0x8,
1956
        fOutline: d & 0x10,
1957
        fShadow: d & 0x20,
1958
        fCondense: d & 0x40,
1959
        fExtend: d & 0x80
1960
    };
1961
    return out;
1962
}
1963
/* [MS-OLEPS] 2.2 PropertyType */
1964
{
1965
    var VT_EMPTY    = 0x0000;
1966
    var VT_NULL     = 0x0001;
1967
    var VT_I2       = 0x0002;
1968
    var VT_I4       = 0x0003;
1969
    var VT_R4       = 0x0004;
1970
    var VT_R8       = 0x0005;
1971
    var VT_CY       = 0x0006;
1972
    var VT_DATE     = 0x0007;
1973
    var VT_BSTR     = 0x0008;
1974
    var VT_ERROR    = 0x000A;
1975
    var VT_BOOL     = 0x000B;
1976
    var VT_VARIANT  = 0x000C;
1977
    var VT_DECIMAL  = 0x000E;
1978
    var VT_I1       = 0x0010;
1979
    var VT_UI1      = 0x0011;
1980
    var VT_UI2      = 0x0012;
1981
    var VT_UI4      = 0x0013;
1982
    var VT_I8       = 0x0014;
1983
    var VT_UI8      = 0x0015;
1984
    var VT_INT      = 0x0016;
1985
    var VT_UINT     = 0x0017;
1986
    var VT_LPSTR    = 0x001E;
1987
    var VT_LPWSTR   = 0x001F;
1988
    var VT_FILETIME = 0x0040;
1989
    var VT_BLOB     = 0x0041;
1990
    var VT_STREAM   = 0x0042;
1991
    var VT_STORAGE  = 0x0043;
1992
    var VT_STREAMED_Object  = 0x0044;
1993
    var VT_STORED_Object    = 0x0045;
1994
    var VT_BLOB_Object      = 0x0046;
1995
    var VT_CF       = 0x0047;
1996
    var VT_CLSID    = 0x0048;
1997
    var VT_VERSIONED_STREAM = 0x0049;
1998
    var VT_VECTOR   = 0x1000;
1999
    var VT_ARRAY    = 0x2000;
2000
 
2001
    var VT_STRING   = 0x0050; // 2.3.3.1.11 VtString
2002
    var VT_USTR     = 0x0051; // 2.3.3.1.12 VtUnalignedString
2003
    var VT_CUSTOM   = [VT_STRING, VT_USTR];
2004
}
2005
 
2006
/* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */
2007
var DocSummaryPIDDSI = {
2008
    0x01: { n: 'CodePage', t: VT_I2 },
2009
    0x02: { n: 'Category', t: VT_STRING },
2010
    0x03: { n: 'PresentationFormat', t: VT_STRING },
2011
    0x04: { n: 'ByteCount', t: VT_I4 },
2012
    0x05: { n: 'LineCount', t: VT_I4 },
2013
    0x06: { n: 'ParagraphCount', t: VT_I4 },
2014
    0x07: { n: 'SlideCount', t: VT_I4 },
2015
    0x08: { n: 'NoteCount', t: VT_I4 },
2016
    0x09: { n: 'HiddenCount', t: VT_I4 },
2017
    0x0a: { n: 'MultimediaClipCount', t: VT_I4 },
2018
    0x0b: { n: 'Scale', t: VT_BOOL },
2019
    0x0c: { n: 'HeadingPair', t: VT_VECTOR | VT_VARIANT },
2020
    0x0d: { n: 'DocParts', t: VT_VECTOR | VT_LPSTR },
2021
    0x0e: { n: 'Manager', t: VT_STRING },
2022
    0x0f: { n: 'Company', t: VT_STRING },
2023
    0x10: { n: 'LinksDirty', t: VT_BOOL },
2024
    0x11: { n: 'CharacterCount', t: VT_I4 },
2025
    0x13: { n: 'SharedDoc', t: VT_BOOL },
2026
    0x16: { n: 'HLinksChanged', t: VT_BOOL },
2027
    0x17: { n: 'AppVersion', t: VT_I4, p: 'version' },
2028
    0x1A: { n: 'ContentType', t: VT_STRING },
2029
    0x1B: { n: 'ContentStatus', t: VT_STRING },
2030
    0x1C: { n: 'Language', t: VT_STRING },
2031
    0x1D: { n: 'Version', t: VT_STRING },
2032
    0xFF: {}
2033
};
2034
 
2035
/* [MS-OSHARED] 2.3.3.2.1.1 Summary Information Property Set PIDSI */
2036
var SummaryPIDSI = {
2037
    0x01: { n: 'CodePage', t: VT_I2 },
2038
    0x02: { n: 'Title', t: VT_STRING },
2039
    0x03: { n: 'Subject', t: VT_STRING },
2040
    0x04: { n: 'Author', t: VT_STRING },
2041
    0x05: { n: 'Keywords', t: VT_STRING },
2042
    0x06: { n: 'Comments', t: VT_STRING },
2043
    0x07: { n: 'Template', t: VT_STRING },
2044
    0x08: { n: 'LastAuthor', t: VT_STRING },
2045
    0x09: { n: 'RevNumber', t: VT_STRING },
2046
    0x0A: { n: 'EditTime', t: VT_FILETIME },
2047
    0x0B: { n: 'LastPrinted', t: VT_FILETIME },
2048
    0x0C: { n: 'CreatedDate', t: VT_FILETIME },
2049
    0x0D: { n: 'ModifiedDate', t: VT_FILETIME },
2050
    0x0E: { n: 'PageCount', t: VT_I4 },
2051
    0x0F: { n: 'WordCount', t: VT_I4 },
2052
    0x10: { n: 'CharCount', t: VT_I4 },
2053
    0x11: { n: 'Thumbnail', t: VT_CF },
2054
    0x12: { n: 'ApplicationName', t: VT_LPSTR },
2055
    0x13: { n: 'DocumentSecurity', t: VT_I4 },
2056
    0xFF: {}
2057
};
2058
 
2059
/* [MS-OLEPS] 2.18 */
2060
var SpecialProperties = {
2061
    0x80000000: { n: 'Locale', t: VT_UI4 },
2062
    0x80000003: { n: 'Behavior', t: VT_UI4 },
2063
    0x72627262: {}
2064
};
2065
 
2066
(function() {
2067
    for(var y in SpecialProperties) if(SpecialProperties.hasOwnProperty(y))
2068
    DocSummaryPIDDSI[y] = SummaryPIDSI[y] = SpecialProperties[y];
2069
})();
2070
 
2071
/* [MS-XLS] 2.4.63 Country/Region codes */
2072
var CountryEnum = {
2073
    0x0001: "US", // United States
2074
    0x0002: "CA", // Canada
2075
    0x0003: "", // Latin America (except Brazil)
2076
    0x0007: "RU", // Russia
2077
    0x0014: "EG", // Egypt
2078
    0x001E: "GR", // Greece
2079
    0x001F: "NL", // Netherlands
2080
    0x0020: "BE", // Belgium
2081
    0x0021: "FR", // France
2082
    0x0022: "ES", // Spain
2083
    0x0024: "HU", // Hungary
2084
    0x0027: "IT", // Italy
2085
    0x0029: "CH", // Switzerland
2086
    0x002B: "AT", // Austria
2087
    0x002C: "GB", // United Kingdom
2088
    0x002D: "DK", // Denmark
2089
    0x002E: "SE", // Sweden
2090
    0x002F: "NO", // Norway
2091
    0x0030: "PL", // Poland
2092
    0x0031: "DE", // Germany
2093
    0x0034: "MX", // Mexico
2094
    0x0037: "BR", // Brazil
2095
    0x003d: "AU", // Australia
2096
    0x0040: "NZ", // New Zealand
2097
    0x0042: "TH", // Thailand
2098
    0x0051: "JP", // Japan
2099
    0x0052: "KR", // Korea
2100
    0x0054: "VN", // Viet Nam
2101
    0x0056: "CN", // China
2102
    0x005A: "TR", // Turkey
2103
    0x0069: "JS", // Ramastan
2104
    0x00D5: "DZ", // Algeria
2105
    0x00D8: "MA", // Morocco
2106
    0x00DA: "LY", // Libya
2107
    0x015F: "PT", // Portugal
2108
    0x0162: "IS", // Iceland
2109
    0x0166: "FI", // Finland
2110
    0x01A4: "CZ", // Czech Republic
2111
    0x0376: "TW", // Taiwan
2112
    0x03C1: "LB", // Lebanon
2113
    0x03C2: "JO", // Jordan
2114
    0x03C3: "SY", // Syria
2115
    0x03C4: "IQ", // Iraq
2116
    0x03C5: "KW", // Kuwait
2117
    0x03C6: "SA", // Saudi Arabia
2118
    0x03CB: "AE", // United Arab Emirates
2119
    0x03CC: "IL", // Israel
2120
    0x03CE: "QA", // Qatar
2121
    0x03D5: "IR", // Iran
2122
    0xFFFF: "US"  // United States
2123
};
2124
 
2125
/* [MS-XLS] 2.5.127 */
2126
var XLSFillPattern = [
2127
    null,
2128
    'solid',
2129
    'mediumGray',
2130
    'darkGray',
2131
    'lightGray',
2132
    'darkHorizontal',
2133
    'darkVertical',
2134
    'darkDown',
2135
    'darkUp',
2136
    'darkGrid',
2137
    'darkTrellis',
2138
    'lightHorizontal',
2139
    'lightVertical',
2140
    'lightDown',
2141
    'lightUp',
2142
    'lightGrid',
2143
    'lightTrellis',
2144
    'gray125',
2145
    'gray0625'
2146
];
2147
 
2148
function rgbify(arr) { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); }
2149
 
2150
/* [MS-XLS] 2.5.161 */
2151
var XLSIcv = rgbify([
2152
    /* Color Constants */
2153
    0x000000,
2154
    0xFFFFFF,
2155
    0xFF0000,
2156
    0x00FF00,
2157
    0x0000FF,
2158
    0xFFFF00,
2159
    0xFF00FF,
2160
    0x00FFFF,
2161
 
2162
    /* Defaults */
2163
    0x000000,
2164
    0xFFFFFF,
2165
    0xFF0000,
2166
    0x00FF00,
2167
    0x0000FF,
2168
    0xFFFF00,
2169
    0xFF00FF,
2170
    0x00FFFF,
2171
 
2172
    0x800000,
2173
    0x008000,
2174
    0x000080,
2175
    0x808000,
2176
    0x800080,
2177
    0x008080,
2178
    0xC0C0C0,
2179
    0x808080,
2180
    0x9999FF,
2181
    0x993366,
2182
    0xFFFFCC,
2183
    0xCCFFFF,
2184
    0x660066,
2185
    0xFF8080,
2186
    0x0066CC,
2187
    0xCCCCFF,
2188
 
2189
    0x000080,
2190
    0xFF00FF,
2191
    0xFFFF00,
2192
    0x00FFFF,
2193
    0x800080,
2194
    0x800000,
2195
    0x008080,
2196
    0x0000FF,
2197
    0x00CCFF,
2198
    0xCCFFFF,
2199
    0xCCFFCC,
2200
    0xFFFF99,
2201
    0x99CCFF,
2202
    0xFF99CC,
2203
    0xCC99FF,
2204
    0xFFCC99,
2205
 
2206
    0x3366FF,
2207
    0x33CCCC,
2208
    0x99CC00,
2209
    0xFFCC00,
2210
    0xFF9900,
2211
    0xFF6600,
2212
    0x666699,
2213
    0x969696,
2214
    0x003366,
2215
    0x339966,
2216
    0x003300,
2217
    0x333300,
2218
    0x993300,
2219
    0x993366,
2220
    0x333399,
2221
    0x333333,
2222
 
2223
    /* Sheet */
2224
    0xFFFFFF,
2225
    0x000000
2226
]);
2227
 
2228
/* Parts enumerated in OPC spec, MS-XLSB and MS-XLSX */
2229
/* 12.3 Part Summary <SpreadsheetML> */
2230
/* 14.2 Part Summary <DrawingML> */
2231
/* [MS-XLSX] 2.1 Part Enumerations */
2232
/* [MS-XLSB] 2.1.7 Part Enumeration */
2233
var ct2type = {
2234
    /* Workbook */
2235
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": "workbooks",
2236
 
2237
    /* Worksheet */
2238
    "application/vnd.ms-excel.binIndexWs": "TODO", /* Binary Index */
2239
 
2240
    /* Chartsheet */
2241
    "application/vnd.ms-excel.chartsheet": "TODO",
2242
    "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml": "TODO",
2243
 
2244
    /* Dialogsheet */
2245
    "application/vnd.ms-excel.dialogsheet": "TODO",
2246
    "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml": "TODO",
2247
 
2248
    /* Macrosheet */
2249
    "application/vnd.ms-excel.macrosheet": "TODO",
2250
    "application/vnd.ms-excel.macrosheet+xml": "TODO",
2251
    "application/vnd.ms-excel.intlmacrosheet": "TODO",
2252
    "application/vnd.ms-excel.binIndexMs": "TODO", /* Binary Index */
2253
 
2254
    /* File Properties */
2255
    "application/vnd.openxmlformats-package.core-properties+xml": "coreprops",
2256
    "application/vnd.openxmlformats-officedocument.custom-properties+xml": "custprops",
2257
    "application/vnd.openxmlformats-officedocument.extended-properties+xml": "extprops",
2258
 
2259
    /* Custom Data Properties */
2260
    "application/vnd.openxmlformats-officedocument.customXmlProperties+xml": "TODO",
2261
 
2262
    /* Comments */
2263
    "application/vnd.ms-excel.comments": "comments",
2264
    "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": "comments",
2265
 
2266
    /* PivotTable */
2267
    "application/vnd.ms-excel.pivotTable": "TODO",
2268
    "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml": "TODO",
2269
 
2270
    /* Calculation Chain */
2271
    "application/vnd.ms-excel.calcChain": "calcchains",
2272
    "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains",
2273
 
2274
    /* Printer Settings */
2275
    "application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings": "TODO",
2276
 
2277
    /* ActiveX */
2278
    "application/vnd.ms-office.activeX": "TODO",
2279
    "application/vnd.ms-office.activeX+xml": "TODO",
2280
 
2281
    /* Custom Toolbars */
2282
    "application/vnd.ms-excel.attachedToolbars": "TODO",
2283
 
2284
    /* External Data Connections */
2285
    "application/vnd.ms-excel.connections": "TODO",
2286
    "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml": "TODO",
2287
 
2288
    /* External Links */
2289
    "application/vnd.ms-excel.externalLink": "TODO",
2290
    "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml": "TODO",
2291
 
2292
    /* Metadata */
2293
    "application/vnd.ms-excel.sheetMetadata": "TODO",
2294
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml": "TODO",
2295
 
2296
    /* PivotCache */
2297
    "application/vnd.ms-excel.pivotCacheDefinition": "TODO",
2298
    "application/vnd.ms-excel.pivotCacheRecords": "TODO",
2299
    "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml": "TODO",
2300
    "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml": "TODO",
2301
 
2302
    /* Query Table */
2303
    "application/vnd.ms-excel.queryTable": "TODO",
2304
    "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml": "TODO",
2305
 
2306
    /* Shared Workbook */
2307
    "application/vnd.ms-excel.userNames": "TODO",
2308
    "application/vnd.ms-excel.revisionHeaders": "TODO",
2309
    "application/vnd.ms-excel.revisionLog": "TODO",
2310
    "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml": "TODO",
2311
    "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml": "TODO",
2312
    "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml": "TODO",
2313
 
2314
    /* Single Cell Table */
2315
    "application/vnd.ms-excel.tableSingleCells": "TODO",
2316
    "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml": "TODO",
2317
 
2318
    /* Slicer */
2319
    "application/vnd.ms-excel.slicer": "TODO",
2320
    "application/vnd.ms-excel.slicerCache": "TODO",
2321
    "application/vnd.ms-excel.slicer+xml": "TODO",
2322
    "application/vnd.ms-excel.slicerCache+xml": "TODO",
2323
 
2324
    /* Sort Map */
2325
    "application/vnd.ms-excel.wsSortMap": "TODO",
2326
 
2327
    /* Table */
2328
    "application/vnd.ms-excel.table": "TODO",
2329
    "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml": "TODO",
2330
 
2331
    /* Themes */
2332
    "application/vnd.openxmlformats-officedocument.theme+xml": "themes",
2333
 
2334
    /* Timeline */
2335
    "application/vnd.ms-excel.Timeline+xml": "TODO", /* verify */
2336
    "application/vnd.ms-excel.TimelineCache+xml": "TODO", /* verify */
2337
 
2338
    /* VBA */
2339
    "application/vnd.ms-office.vbaProject": "vba",
2340
    "application/vnd.ms-office.vbaProjectSignature": "vba",
2341
 
2342
    /* Volatile Dependencies */
2343
    "application/vnd.ms-office.volatileDependencies": "TODO",
2344
    "application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml": "TODO",
2345
 
2346
    /* Control Properties */
2347
    "application/vnd.ms-excel.controlproperties+xml": "TODO",
2348
 
2349
    /* Data Model */
2350
    "application/vnd.openxmlformats-officedocument.model+data": "TODO",
2351
 
2352
    /* Survey */
2353
    "application/vnd.ms-excel.Survey+xml": "TODO",
2354
 
2355
    /* Drawing */
2356
    "application/vnd.openxmlformats-officedocument.drawing+xml": "TODO",
2357
    "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": "TODO",
2358
    "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml": "TODO",
2359
    "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml": "TODO",
2360
    "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml": "TODO",
2361
    "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml": "TODO",
2362
    "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml": "TODO",
2363
 
2364
    /* VML */
2365
    "application/vnd.openxmlformats-officedocument.vmlDrawing": "TODO",
2366
 
2367
    "application/vnd.openxmlformats-package.relationships+xml": "rels",
2368
    "application/vnd.openxmlformats-officedocument.oleObject": "TODO",
2369
 
2370
    "sheet": "js"
2371
};
2372
 
2373
var CT_LIST = (function(){
2374
    var o = {
2375
        workbooks: {
2376
            xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
2377
            xlsm: "application/vnd.ms-excel.sheet.macroEnabled.main+xml",
2378
            xlsb: "application/vnd.ms-excel.sheet.binary.macroEnabled.main",
2379
            xltx: "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
2380
        },
2381
        strs: { /* Shared Strings */
2382
            xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
2383
            xlsb: "application/vnd.ms-excel.sharedStrings"
2384
        },
2385
        sheets: {
2386
            xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
2387
            xlsb: "application/vnd.ms-excel.worksheet"
2388
        },
2389
        styles: {/* Styles */
2390
            xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
2391
            xlsb: "application/vnd.ms-excel.styles"
2392
        }
2393
    };
2394
    keys(o).forEach(function(k) { if(!o[k].xlsm) o[k].xlsm = o[k].xlsx; });
2395
    keys(o).forEach(function(k){ keys(o[k]).forEach(function(v) { ct2type[o[k][v]] = k; }); });
2396
    return o;
2397
})();
2398
 
2399
var type2ct = evert_arr(ct2type);
2400
 
2401
XMLNS.CT = 'http://schemas.openxmlformats.org/package/2006/content-types';
2402
 
2403
function parse_ct(data, opts) {
2404
    var ctext = {};
2405
    if(!data || !data.match) return data;
2406
    var ct = { workbooks: [], sheets: [], calcchains: [], themes: [], styles: [],
2407
        coreprops: [], extprops: [], custprops: [], strs:[], comments: [], vba: [],
2408
        TODO:[], rels:[], xmlns: "" };
2409
    (data.match(tagregex)||[]).forEach(function(x) {
2410
        var y = parsexmltag(x);
2411
        switch(y[0].replace(nsregex,"<")) {
2412
            case '<?xml': break;
2413
            case '<Types': ct.xmlns = y['xmlns' + (y[0].match(/<(\w+):/)||["",""])[1] ]; break;
2414
            case '<Default': ctext[y.Extension] = y.ContentType; break;
2415
            case '<Override':
2416
                if(ct[ct2type[y.ContentType]] !== undefined) ct[ct2type[y.ContentType]].push(y.PartName);
2417
                else if(opts.WTF) console.error(y);
2418
                break;
2419
        }
2420
    });
2421
    if(ct.xmlns !== XMLNS.CT) throw new Error("Unknown Namespace: " + ct.xmlns);
2422
    ct.calcchain = ct.calcchains.length > 0 ? ct.calcchains[0] : "";
2423
    ct.sst = ct.strs.length > 0 ? ct.strs[0] : "";
2424
    ct.style = ct.styles.length > 0 ? ct.styles[0] : "";
2425
    ct.defaults = ctext;
2426
    delete ct.calcchains;
2427
    return ct;
2428
}
2429
 
2430
var CTYPE_XML_ROOT = writextag('Types', null, {
2431
    'xmlns': XMLNS.CT,
2432
    'xmlns:xsd': XMLNS.xsd,
2433
    'xmlns:xsi': XMLNS.xsi
2434
});
2435
 
2436
var CTYPE_DEFAULTS = [
2437
    ['xml', 'application/xml'],
2438
    ['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
2439
    ['rels', type2ct.rels[0]]
2440
].map(function(x) {
2441
    return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
2442
});
2443
 
2444
function write_ct(ct, opts) {
2445
    var o = [], v;
2446
    o[o.length] = (XML_HEADER);
2447
    o[o.length] = (CTYPE_XML_ROOT);
2448
    o = o.concat(CTYPE_DEFAULTS);
2449
    var f1 = function(w) {
2450
        if(ct[w] && ct[w].length > 0) {
2451
            v = ct[w][0];
2452
            o[o.length] = (writextag('Override', null, {
2453
                'PartName': (v[0] == '/' ? "":"/") + v,
2454
                'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
2455
            }));
2456
        }
2457
    };
2458
    var f2 = function(w) {
2459
        ct[w].forEach(function(v) {
2460
            o[o.length] = (writextag('Override', null, {
2461
                'PartName': (v[0] == '/' ? "":"/") + v,
2462
                'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
2463
            }));
2464
        });
2465
    };
2466
    var f3 = function(t) {
2467
        (ct[t]||[]).forEach(function(v) {
2468
            o[o.length] = (writextag('Override', null, {
2469
                'PartName': (v[0] == '/' ? "":"/") + v,
2470
                'ContentType': type2ct[t][0]
2471
            }));
2472
        });
2473
    };
2474
    f1('workbooks');
2475
    f2('sheets');
2476
    f3('themes');
2477
    ['strs', 'styles'].forEach(f1);
2478
    ['coreprops', 'extprops', 'custprops'].forEach(f3);
2479
    if(o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
2480
    return o.join("");
2481
}
2482
/* 9.3.2 OPC Relationships Markup */
2483
var RELS = {
2484
    WB: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
2485
    SHEET: "http://sheetjs.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
2486
};
2487
 
2488
function parse_rels(data, currentFilePath) {
2489
    if (!data) return data;
2490
    if (currentFilePath.charAt(0) !== '/') {
2491
        currentFilePath = '/'+currentFilePath;
2492
    }
2493
    var rels = {};
2494
    var hash = {};
2495
    var resolveRelativePathIntoAbsolute = function (to) {
2496
        var toksFrom = currentFilePath.split('/');
2497
        toksFrom.pop(); // folder path
2498
        var toksTo = to.split('/');
2499
        var reversed = [];
2500
        while (toksTo.length !== 0) {
2501
            var tokTo = toksTo.shift();
2502
            if (tokTo === '..') {
2503
                toksFrom.pop();
2504
            } else if (tokTo !== '.') {
2505
                toksFrom.push(tokTo);
2506
            }
2507
        }
2508
        return toksFrom.join('/');
2509
    };
2510
 
2511
    data.match(tagregex).forEach(function(x) {
2512
        var y = parsexmltag(x);
2513
        /* 9.3.2.2 OPC_Relationships */
2514
        if (y[0] === '<Relationship') {
2515
            var rel = {}; rel.Type = y.Type; rel.Target = y.Target; rel.Id = y.Id; rel.TargetMode = y.TargetMode;
2516
            var canonictarget = y.TargetMode === 'External' ? y.Target : resolveRelativePathIntoAbsolute(y.Target);
2517
            rels[canonictarget] = rel;
2518
            hash[y.Id] = rel;
2519
        }
2520
    });
2521
    rels["!id"] = hash;
2522
    return rels;
2523
}
2524
 
2525
XMLNS.RELS = 'http://schemas.openxmlformats.org/package/2006/relationships';
2526
 
2527
var RELS_ROOT = writextag('Relationships', null, {
2528
    //'xmlns:ns0': XMLNS.RELS,
2529
    'xmlns': XMLNS.RELS
2530
});
2531
 
2532
/* TODO */
2533
function write_rels(rels) {
2534
    var o = [];
2535
    o[o.length] = (XML_HEADER);
2536
    o[o.length] = (RELS_ROOT);
2537
    keys(rels['!id']).forEach(function(rid) { var rel = rels['!id'][rid];
2538
        o[o.length] = (writextag('Relationship', null, rel));
2539
    });
2540
    if(o.length>2){ o[o.length] = ('</Relationships>'); o[1]=o[1].replace("/>",">"); }
2541
    return o.join("");
2542
}
2543
/* ECMA-376 Part II 11.1 Core Properties Part */
2544
/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
2545
var CORE_PROPS = [
2546
    ["cp:category", "Category"],
2547
    ["cp:contentStatus", "ContentStatus"],
2548
    ["cp:keywords", "Keywords"],
2549
    ["cp:lastModifiedBy", "LastAuthor"],
2550
    ["cp:lastPrinted", "LastPrinted"],
2551
    ["cp:revision", "RevNumber"],
2552
    ["cp:version", "Version"],
2553
    ["dc:creator", "Author"],
2554
    ["dc:description", "Comments"],
2555
    ["dc:identifier", "Identifier"],
2556
    ["dc:language", "Language"],
2557
    ["dc:subject", "Subject"],
2558
    ["dc:title", "Title"],
2559
    ["dcterms:created", "CreatedDate", 'date'],
2560
    ["dcterms:modified", "ModifiedDate", 'date']
2561
];
2562
 
2563
XMLNS.CORE_PROPS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
2564
RELS.CORE_PROPS  = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';
2565
 
2566
var CORE_PROPS_REGEX = (function() {
2567
    var r = new Array(CORE_PROPS.length);
2568
    for(var i = 0; i < CORE_PROPS.length; ++i) {
2569
        var f = CORE_PROPS[i];
2570
        var g = "(?:"+ f[0].substr(0,f[0].indexOf(":")) +":)"+ f[0].substr(f[0].indexOf(":")+1);
2571
        r[i] = new RegExp("<" + g + "[^>]*>(.*)<\/" + g + ">");
2572
    }
2573
    return r;
2574
})();
2575
 
2576
function parse_core_props(data) {
2577
    var p = {};
2578
 
2579
    for(var i = 0; i < CORE_PROPS.length; ++i) {
2580
        var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
2581
        if(cur != null && cur.length > 0) p[f[1]] = cur[1];
2582
        if(f[2] === 'date' && p[f[1]]) p[f[1]] = new Date(p[f[1]]);
2583
    }
2584
 
2585
    return p;
2586
}
2587
 
2588
var CORE_PROPS_XML_ROOT = writextag('cp:coreProperties', null, {
2589
    //'xmlns': XMLNS.CORE_PROPS,
2590
    'xmlns:cp': XMLNS.CORE_PROPS,
2591
    'xmlns:dc': XMLNS.dc,
2592
    'xmlns:dcterms': XMLNS.dcterms,
2593
    'xmlns:dcmitype': XMLNS.dcmitype,
2594
    'xmlns:xsi': XMLNS.xsi
2595
});
2596
 
2597
function cp_doit(f, g, h, o, p) {
2598
    if(p[f] != null || g == null || g === "") return;
2599
    p[f] = g;
2600
    o[o.length] = (h ? writextag(f,g,h) : writetag(f,g));
2601
}
2602
 
2603
function write_core_props(cp, opts) {
2604
    var o = [XML_HEADER, CORE_PROPS_XML_ROOT], p = {};
2605
    if(!cp) return o.join("");
2606
 
2607
 
2608
    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);
2609
    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);
2610
 
2611
    for(var i = 0; i != CORE_PROPS.length; ++i) { var f = CORE_PROPS[i]; cp_doit(f[0], cp[f[1]], null, o, p); }
2612
    if(o.length>2){ o[o.length] = ('</cp:coreProperties>'); o[1]=o[1].replace("/>",">"); }
2613
    return o.join("");
2614
}
2615
/* 15.2.12.3 Extended File Properties Part */
2616
/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
2617
var EXT_PROPS = [
2618
    ["Application", "Application", "string"],
2619
    ["AppVersion", "AppVersion", "string"],
2620
    ["Company", "Company", "string"],
2621
    ["DocSecurity", "DocSecurity", "string"],
2622
    ["Manager", "Manager", "string"],
2623
    ["HyperlinksChanged", "HyperlinksChanged", "bool"],
2624
    ["SharedDoc", "SharedDoc", "bool"],
2625
    ["LinksUpToDate", "LinksUpToDate", "bool"],
2626
    ["ScaleCrop", "ScaleCrop", "bool"],
2627
    ["HeadingPairs", "HeadingPairs", "raw"],
2628
    ["TitlesOfParts", "TitlesOfParts", "raw"]
2629
];
2630
 
2631
XMLNS.EXT_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
2632
RELS.EXT_PROPS  = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';
2633
 
2634
function parse_ext_props(data, p) {
2635
    var q = {}; if(!p) p = {};
2636
 
2637
    EXT_PROPS.forEach(function(f) {
2638
        switch(f[2]) {
2639
            case "string": p[f[1]] = (data.match(matchtag(f[0]))||[])[1]; break;
2640
            case "bool": p[f[1]] = (data.match(matchtag(f[0]))||[])[1] === "true"; break;
2641
            case "raw":
2642
                var cur = data.match(new RegExp("<" + f[0] + "[^>]*>(.*)<\/" + f[0] + ">"));
2643
                if(cur && cur.length > 0) q[f[1]] = cur[1];
2644
                break;
2645
        }
2646
    });
2647
 
2648
    if(q.HeadingPairs && q.TitlesOfParts) {
2649
        var v = parseVector(q.HeadingPairs);
2650
        var j = 0, widx = 0;
2651
        for(var i = 0; i !== v.length; ++i) {
2652
            switch(v[i].v) {
2653
                case "Worksheets": widx = j; p.Worksheets = +(v[++i].v); break;
2654
                case "Named Ranges": ++i; break; // TODO: Handle Named Ranges
2655
            }
2656
        }
2657
        var parts = parseVector(q.TitlesOfParts).map(function(x) { return utf8read(x.v); });
2658
        p.SheetNames = parts.slice(widx, widx + p.Worksheets);
2659
    }
2660
    return p;
2661
}
2662
 
2663
var EXT_PROPS_XML_ROOT = writextag('Properties', null, {
2664
    'xmlns': XMLNS.EXT_PROPS,
2665
    'xmlns:vt': XMLNS.vt
2666
});
2667
 
2668
function write_ext_props(cp, opts) {
2669
    var o = [], p = {}, W = writextag;
2670
    if(!cp) cp = {};
2671
    cp.Application = "SheetJS";
2672
    o[o.length] = (XML_HEADER);
2673
    o[o.length] = (EXT_PROPS_XML_ROOT);
2674
 
2675
    EXT_PROPS.forEach(function(f) {
2676
        if(cp[f[1]] === undefined) return;
2677
        var v;
2678
        switch(f[2]) {
2679
            case 'string': v = cp[f[1]]; break;
2680
            case 'bool': v = cp[f[1]] ? 'true' : 'false'; break;
2681
        }
2682
        if(v !== undefined) o[o.length] = (W(f[0], v));
2683
    });
2684
 
2685
    /* TODO: HeadingPairs, TitlesOfParts */
2686
    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"})));
2687
    o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + s + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
2688
    if(o.length>2){ o[o.length] = ('</Properties>'); o[1]=o[1].replace("/>",">"); }
2689
    return o.join("");
2690
}
2691
/* 15.2.12.2 Custom File Properties Part */
2692
XMLNS.CUST_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
2693
RELS.CUST_PROPS  = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties';
2694
 
2695
var custregex = /<[^>]+>[^<]*/g;
2696
function parse_cust_props(data, opts) {
2697
    var p = {}, name;
2698
    var m = data.match(custregex);
2699
    if(m) for(var i = 0; i != m.length; ++i) {
2700
        var x = m[i], y = parsexmltag(x);
2701
        switch(y[0]) {
2702
            case '<?xml': break;
2703
            case '<Properties':
2704
                if(y.xmlns !== XMLNS.CUST_PROPS) throw "unrecognized xmlns " + y.xmlns;
2705
                if(y.xmlnsvt && y.xmlnsvt !== XMLNS.vt) throw "unrecognized vt " + y.xmlnsvt;
2706
                break;
2707
            case '<property': name = y.name; break;
2708
            case '</property>': name = null; break;
2709
            default: if (x.indexOf('<vt:') === 0) {
2710
                var toks = x.split('>');
2711
                var type = toks[0].substring(4), text = toks[1];
2712
                /* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */
2713
                switch(type) {
2714
                    case 'lpstr': case 'lpwstr': case 'bstr': case 'lpwstr':
2715
                        p[name] = unescapexml(text);
2716
                        break;
2717
                    case 'bool':
2718
                        p[name] = parsexmlbool(text, '<vt:bool>');
2719
                        break;
2720
                    case 'i1': case 'i2': case 'i4': case 'i8': case 'int': case 'uint':
2721
                        p[name] = parseInt(text, 10);
2722
                        break;
2723
                    case 'r4': case 'r8': case 'decimal':
2724
                        p[name] = parseFloat(text);
2725
                        break;
2726
                    case 'filetime': case 'date':
2727
                        p[name] = new Date(text);
2728
                        break;
2729
                    case 'cy': case 'error':
2730
                        p[name] = unescapexml(text);
2731
                        break;
2732
                    default:
2733
                        if(typeof console !== 'undefined') console.warn('Unexpected', x, type, toks);
2734
                }
2735
            } else if(x.substr(0,2) === "</") {
2736
            } else if(opts.WTF) throw new Error(x);
2737
        }
2738
    }
2739
    return p;
2740
}
2741
 
2742
var CUST_PROPS_XML_ROOT = writextag('Properties', null, {
2743
    'xmlns': XMLNS.CUST_PROPS,
2744
    'xmlns:vt': XMLNS.vt
2745
});
2746
 
2747
function write_cust_props(cp, opts) {
2748
    var o = [XML_HEADER, CUST_PROPS_XML_ROOT];
2749
    if(!cp) return o.join("");
2750
    var pid = 1;
2751
    keys(cp).forEach(function custprop(k) { ++pid;
2752
        o[o.length] = (writextag('property', write_vt(cp[k]), {
2753
            'fmtid': '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}',
2754
            'pid': pid,
2755
            'name': k
2756
        }));
2757
    });
2758
    if(o.length>2){ o[o.length] = '</Properties>'; o[1]=o[1].replace("/>",">"); }
2759
    return o.join("");
2760
}
2761
function xlml_set_prop(Props, tag, val) {
2762
    /* TODO: Normalize the properties */
2763
    switch(tag) {
2764
        case 'Description': tag = 'Comments'; break;
2765
    }
2766
    Props[tag] = val;
2767
}
2768
 
2769
/* [MS-DTYP] 2.3.3 FILETIME */
2770
/* [MS-OLEDS] 2.1.3 FILETIME (Packet Version) */
2771
/* [MS-OLEPS] 2.8 FILETIME (Packet Version) */
2772
function parse_FILETIME(blob) {
2773
    var dwLowDateTime = blob.read_shift(4), dwHighDateTime = blob.read_shift(4);
2774
    return new Date(((dwHighDateTime/1e7*Math.pow(2,32) + dwLowDateTime/1e7) - 11644473600)*1000).toISOString().replace(/\.000/,"");
2775
}
2776
 
2777
/* [MS-OSHARED] 2.3.3.1.4 Lpstr */
2778
function parse_lpstr(blob, type, pad) {
2779
    var str = blob.read_shift(0, 'lpstr');
2780
    if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3;
2781
    return str;
2782
}
2783
 
2784
/* [MS-OSHARED] 2.3.3.1.6 Lpwstr */
2785
function parse_lpwstr(blob, type, pad) {
2786
    var str = blob.read_shift(0, 'lpwstr');
2787
    if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3;
2788
    return str;
2789
}
2790
 
2791
 
2792
/* [MS-OSHARED] 2.3.3.1.11 VtString */
2793
/* [MS-OSHARED] 2.3.3.1.12 VtUnalignedString */
2794
function parse_VtStringBase(blob, stringType, pad) {
2795
    if(stringType === 0x1F /*VT_LPWSTR*/) return parse_lpwstr(blob);
2796
    return parse_lpstr(blob, stringType, pad);
2797
}
2798
 
2799
function parse_VtString(blob, t, pad) { return parse_VtStringBase(blob, t, pad === false ? 0: 4); }
2800
function parse_VtUnalignedString(blob, t) { if(!t) throw new Error("dafuq?"); return parse_VtStringBase(blob, t, 0); }
2801
 
2802
/* [MS-OSHARED] 2.3.3.1.9 VtVecUnalignedLpstrValue */
2803
function parse_VtVecUnalignedLpstrValue(blob) {
2804
    var length = blob.read_shift(4);
2805
    var ret = [];
2806
    for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr');
2807
    return ret;
2808
}
2809
 
2810
/* [MS-OSHARED] 2.3.3.1.10 VtVecUnalignedLpstr */
2811
function parse_VtVecUnalignedLpstr(blob) {
2812
    return parse_VtVecUnalignedLpstrValue(blob);
2813
}
2814
 
2815
/* [MS-OSHARED] 2.3.3.1.13 VtHeadingPair */
2816
function parse_VtHeadingPair(blob) {
2817
    var headingString = parse_TypedPropertyValue(blob, VT_USTR);
2818
    var headerParts = parse_TypedPropertyValue(blob, VT_I4);
2819
    return [headingString, headerParts];
2820
}
2821
 
2822
/* [MS-OSHARED] 2.3.3.1.14 VtVecHeadingPairValue */
2823
function parse_VtVecHeadingPairValue(blob) {
2824
    var cElements = blob.read_shift(4);
2825
    var out = [];
2826
    for(var i = 0; i != cElements / 2; ++i) out.push(parse_VtHeadingPair(blob));
2827
    return out;
2828
}
2829
 
2830
/* [MS-OSHARED] 2.3.3.1.15 VtVecHeadingPair */
2831
function parse_VtVecHeadingPair(blob) {
2832
    // NOTE: When invoked, wType & padding were already consumed
2833
    return parse_VtVecHeadingPairValue(blob);
2834
}
2835
 
2836
/* [MS-OLEPS] 2.18.1 Dictionary (uses 2.17, 2.16) */
2837
function parse_dictionary(blob,CodePage) {
2838
    var cnt = blob.read_shift(4);
2839
    var dict = {};
2840
    for(var j = 0; j != cnt; ++j) {
2841
        var pid = blob.read_shift(4);
2842
        var len = blob.read_shift(4);
2843
        dict[pid] = blob.read_shift(len, (CodePage === 0x4B0 ?'utf16le':'utf8')).replace(chr0,'').replace(chr1,'!');
2844
    }
2845
    if(blob.l & 3) blob.l = (blob.l>>2+1)<<2;
2846
    return dict;
2847
}
2848
 
2849
/* [MS-OLEPS] 2.9 BLOB */
2850
function parse_BLOB(blob) {
2851
    var size = blob.read_shift(4);
2852
    var bytes = blob.slice(blob.l,blob.l+size);
2853
    if(size & 3 > 0) blob.l += (4 - (size & 3)) & 3;
2854
    return bytes;
2855
}
2856
 
2857
/* [MS-OLEPS] 2.11 ClipboardData */
2858
function parse_ClipboardData(blob) {
2859
    // TODO
2860
    var o = {};
2861
    o.Size = blob.read_shift(4);
2862
    //o.Format = blob.read_shift(4);
2863
    blob.l += o.Size;
2864
    return o;
2865
}
2866
 
2867
/* [MS-OLEPS] 2.14 Vector and Array Property Types */
2868
function parse_VtVector(blob, cb) {
2869
    /* [MS-OLEPS] 2.14.2 VectorHeader */
2870
/*  var Length = blob.read_shift(4);
2871
    var o = [];
2872
    for(var i = 0; i != Length; ++i) {
2873
        o.push(cb(blob));
2874
    }
2875
    return o;*/
2876
}
2877
 
2878
/* [MS-OLEPS] 2.15 TypedPropertyValue */
2879
function parse_TypedPropertyValue(blob, type, _opts) {
2880
    var t = blob.read_shift(2), ret, opts = _opts||{};
2881
    blob.l += 2;
2882
    if(type !== VT_VARIANT)
2883
    if(t !== type && VT_CUSTOM.indexOf(type)===-1) throw new Error('Expected type ' + type + ' saw ' + t);
2884
    switch(type === VT_VARIANT ? t : type) {
2885
        case 0x02 /*VT_I2*/: ret = blob.read_shift(2, 'i'); if(!opts.raw) blob.l += 2; return ret;
2886
        case 0x03 /*VT_I4*/: ret = blob.read_shift(4, 'i'); return ret;
2887
        case 0x0B /*VT_BOOL*/: return blob.read_shift(4) !== 0x0;
2888
        case 0x13 /*VT_UI4*/: ret = blob.read_shift(4); return ret;
2889
        case 0x1E /*VT_LPSTR*/: return parse_lpstr(blob, t, 4).replace(chr0,'');
2890
        case 0x1F /*VT_LPWSTR*/: return parse_lpwstr(blob);
2891
        case 0x40 /*VT_FILETIME*/: return parse_FILETIME(blob);
2892
        case 0x41 /*VT_BLOB*/: return parse_BLOB(blob);
2893
        case 0x47 /*VT_CF*/: return parse_ClipboardData(blob);
2894
        case 0x50 /*VT_STRING*/: return parse_VtString(blob, t, !opts.raw && 4).replace(chr0,'');
2895
        case 0x51 /*VT_USTR*/: return parse_VtUnalignedString(blob, t, 4).replace(chr0,'');
2896
        case 0x100C /*VT_VECTOR|VT_VARIANT*/: return parse_VtVecHeadingPair(blob);
2897
        case 0x101E /*VT_LPSTR*/: return parse_VtVecUnalignedLpstr(blob);
2898
        default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + t);
2899
    }
2900
}
2901
/* [MS-OLEPS] 2.14.2 VectorHeader */
2902
/*function parse_VTVectorVariant(blob) {
2903
    var Length = blob.read_shift(4);
2904
 
2905
    if(Length & 1 !== 0) throw new Error("VectorHeader Length=" + Length + " must be even");
2906
    var o = [];
2907
    for(var i = 0; i != Length; ++i) {
2908
        o.push(parse_TypedPropertyValue(blob, VT_VARIANT));
2909
    }
2910
    return o;
2911
}*/
2912
 
2913
/* [MS-OLEPS] 2.20 PropertySet */
2914
function parse_PropertySet(blob, PIDSI) {
2915
    var start_addr = blob.l;
2916
    var size = blob.read_shift(4);
2917
    var NumProps = blob.read_shift(4);
2918
    var Props = [], i = 0;
2919
    var CodePage = 0;
2920
    var Dictionary = -1, DictObj;
2921
    for(i = 0; i != NumProps; ++i) {
2922
        var PropID = blob.read_shift(4);
2923
        var Offset = blob.read_shift(4);
2924
        Props[i] = [PropID, Offset + start_addr];
2925
    }
2926
    var PropH = {};
2927
    for(i = 0; i != NumProps; ++i) {
2928
        if(blob.l !== Props[i][1]) {
2929
            var fail = true;
2930
            if(i>0 && PIDSI) switch(PIDSI[Props[i-1][0]].t) {
2931
                case 0x02 /*VT_I2*/: if(blob.l +2 === Props[i][1]) { blob.l+=2; fail = false; } break;
2932
                case 0x50 /*VT_STRING*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
2933
                case 0x100C /*VT_VECTOR|VT_VARIANT*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
2934
            }
2935
            if(!PIDSI && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; }
2936
            if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i);
2937
        }
2938
        if(PIDSI) {
2939
            var piddsi = PIDSI[Props[i][0]];
2940
            PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true});
2941
            if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + String(PropH[piddsi.n] & 0xFFFF);
2942
            if(piddsi.n == "CodePage") switch(PropH[piddsi.n]) {
2943
                case 0: PropH[piddsi.n] = 1252;
2944
                    /* falls through */
2945
                case 10000: // OSX Roman
2946
                case 1252: // Windows Latin
2947
 
2948
                case 874: // SB Windows Thai
2949
                case 1250: // SB Windows Central Europe
2950
                case 1251: // SB Windows Cyrillic
2951
                case 1253: // SB Windows Greek
2952
                case 1254: // SB Windows Turkish
2953
                case 1255: // SB Windows Hebrew
2954
                case 1256: // SB Windows Arabic
2955
                case 1257: // SB Windows Baltic
2956
                case 1258: // SB Windows Vietnam
2957
 
2958
                case 932: // DB Windows Japanese Shift-JIS
2959
                case 936: // DB Windows Simplified Chinese GBK
2960
                case 949: // DB Windows Korean
2961
                case 950: // DB Windows Traditional Chinese Big5
2962
 
2963
                case 1200: // UTF16LE
2964
                case 1201: // UTF16BE
2965
                case 65000: case -536: // UTF-7
2966
                case 65001: case -535: // UTF-8
2967
                    set_cp(CodePage = PropH[piddsi.n]); break;
2968
                default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
2969
            }
2970
        } else {
2971
            if(Props[i][0] === 0x1) {
2972
                CodePage = PropH.CodePage = parse_TypedPropertyValue(blob, VT_I2);
2973
                set_cp(CodePage);
2974
                if(Dictionary !== -1) {
2975
                    var oldpos = blob.l;
2976
                    blob.l = Props[Dictionary][1];
2977
                    DictObj = parse_dictionary(blob,CodePage);
2978
                    blob.l = oldpos;
2979
                }
2980
            } else if(Props[i][0] === 0) {
2981
                if(CodePage === 0) { Dictionary = i; blob.l = Props[i+1][1]; continue; }
2982
                DictObj = parse_dictionary(blob,CodePage);
2983
            } else {
2984
                var name = DictObj[Props[i][0]];
2985
                var val;
2986
                /* [MS-OSHARED] 2.3.3.2.3.1.2 + PROPVARIANT */
2987
                switch(blob[blob.l]) {
2988
                    case 0x41 /*VT_BLOB*/: blob.l += 4; val = parse_BLOB(blob); break;
2989
                    case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]); break;
2990
                    case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]); break;
2991
                    case 0x03 /*VT_I4*/: blob.l += 4; val = blob.read_shift(4, 'i'); break;
2992
                    case 0x13 /*VT_UI4*/: blob.l += 4; val = blob.read_shift(4); break;
2993
                    case 0x05 /*VT_R8*/: blob.l += 4; val = blob.read_shift(8, 'f'); break;
2994
                    case 0x0B /*VT_BOOL*/: blob.l += 4; val = parsebool(blob, 4); break;
2995
                    case 0x40 /*VT_FILETIME*/: blob.l += 4; val = new Date(parse_FILETIME(blob)); break;
2996
                    default: throw new Error("unparsed value: " + blob[blob.l]);
2997
                }
2998
                PropH[name] = val;
2999
            }
3000
        }
3001
    }
3002
    blob.l = start_addr + size; /* step ahead to skip padding */
3003
    return PropH;
3004
}
3005
 
3006
/* [MS-OLEPS] 2.21 PropertySetStream */
3007
function parse_PropertySetStream(file, PIDSI) {
3008
    var blob = file.content;
3009
    prep_blob(blob, 0);
3010
 
3011
    var NumSets, FMTID0, FMTID1, Offset0, Offset1;
3012
    blob.chk('feff', 'Byte Order: ');
3013
 
3014
    var vers = blob.read_shift(2); // TODO: check version
3015
    var SystemIdentifier = blob.read_shift(4);
3016
    blob.chk(CFB.utils.consts.HEADER_CLSID, 'CLSID: ');
3017
    NumSets = blob.read_shift(4);
3018
    if(NumSets !== 1 && NumSets !== 2) throw "Unrecognized #Sets: " + NumSets;
3019
    FMTID0 = blob.read_shift(16); Offset0 = blob.read_shift(4);
3020
 
3021
    if(NumSets === 1 && Offset0 !== blob.l) throw "Length mismatch";
3022
    else if(NumSets === 2) { FMTID1 = blob.read_shift(16); Offset1 = blob.read_shift(4); }
3023
    var PSet0 = parse_PropertySet(blob, PIDSI);
3024
 
3025
    var rval = { SystemIdentifier: SystemIdentifier };
3026
    for(var y in PSet0) rval[y] = PSet0[y];
3027
    //rval.blob = blob;
3028
    rval.FMTID = FMTID0;
3029
    //rval.PSet0 = PSet0;
3030
    if(NumSets === 1) return rval;
3031
    if(blob.l !== Offset1) throw "Length mismatch 2: " + blob.l + " !== " + Offset1;
3032
    var PSet1;
3033
    try { PSet1 = parse_PropertySet(blob, null); } catch(e) { }
3034
    for(y in PSet1) rval[y] = PSet1[y];
3035
    rval.FMTID = [FMTID0, FMTID1]; // TODO: verify FMTID0/1
3036
    return rval;
3037
}
3038
 
3039
 
3040
function parsenoop2(blob, length) { blob.read_shift(length); return null; }
3041
 
3042
function parslurp(blob, length, cb) {
3043
    var arr = [], target = blob.l + length;
3044
    while(blob.l < target) arr.push(cb(blob, target - blob.l));
3045
    if(target !== blob.l) throw new Error("Slurp error");
3046
    return arr;
3047
}
3048
 
3049
function parslurp2(blob, length, cb) {
3050
    var arr = [], target = blob.l + length, len = blob.read_shift(2);
3051
    while(len-- !== 0) arr.push(cb(blob, target - blob.l));
3052
    if(target !== blob.l) throw new Error("Slurp error");
3053
    return arr;
3054
}
3055
 
3056
function parsebool(blob, length) { return blob.read_shift(length) === 0x1; }
3057
 
3058
function parseuint16(blob) { return blob.read_shift(2, 'u'); }
3059
function parseuint16a(blob, length) { return parslurp(blob,length,parseuint16);}
3060
 
3061
/* --- 2.5 Structures --- */
3062
 
3063
/* [MS-XLS] 2.5.14 Boolean */
3064
var parse_Boolean = parsebool;
3065
 
3066
/* [MS-XLS] 2.5.10 Bes (boolean or error) */
3067
function parse_Bes(blob) {
3068
    var v = blob.read_shift(1), t = blob.read_shift(1);
3069
    return t === 0x01 ? v : v === 0x01;
3070
}
3071
 
3072
/* [MS-XLS] 2.5.240 ShortXLUnicodeString */
3073
function parse_ShortXLUnicodeString(blob, length, opts) {
3074
    var cch = blob.read_shift(1);
3075
    var width = 1, encoding = 'sbcs-cont';
3076
    var cp = current_codepage;
3077
    if(opts && opts.biff >= 8) current_codepage = 1200;
3078
    if(opts === undefined || opts.biff !== 5) {
3079
        var fHighByte = blob.read_shift(1);
3080
        if(fHighByte) { width = 2; encoding = 'dbcs-cont'; }
3081
    }
3082
    var o = cch ? blob.read_shift(cch, encoding) : "";
3083
    current_codepage = cp;
3084
    return o;
3085
}
3086
 
3087
/* 2.5.293 XLUnicodeRichExtendedString */
3088
function parse_XLUnicodeRichExtendedString(blob) {
3089
    var cp = current_codepage;
3090
    current_codepage = 1200;
3091
    var cch = blob.read_shift(2), flags = blob.read_shift(1);
3092
    var fHighByte = flags & 0x1, fExtSt = flags & 0x4, fRichSt = flags & 0x8;
3093
    var width = 1 + (flags & 0x1); // 0x0 -> utf8, 0x1 -> dbcs
3094
    var cRun, cbExtRst;
3095
    var z = {};
3096
    if(fRichSt) cRun = blob.read_shift(2);
3097
    if(fExtSt) cbExtRst = blob.read_shift(4);
3098
    var encoding = (flags & 0x1) ? 'dbcs-cont' : 'sbcs-cont';
3099
    var msg = cch === 0 ? "" : blob.read_shift(cch, encoding);
3100
    if(fRichSt) blob.l += 4 * cRun; //TODO: parse this
3101
    if(fExtSt) blob.l += cbExtRst; //TODO: parse this
3102
    z.t = msg;
3103
    if(!fRichSt) { z.raw = "<t>" + z.t + "</t>"; z.r = z.t; }
3104
    current_codepage = cp;
3105
    return z;
3106
}
3107
 
3108
/* 2.5.296 XLUnicodeStringNoCch */
3109
function parse_XLUnicodeStringNoCch(blob, cch, opts) {
3110
    var retval;
3111
    var fHighByte = blob.read_shift(1);
3112
    if(fHighByte===0) { retval = blob.read_shift(cch, 'sbcs-cont'); }
3113
    else { retval = blob.read_shift(cch, 'dbcs-cont'); }
3114
    return retval;
3115
}
3116
 
3117
/* 2.5.294 XLUnicodeString */
3118
function parse_XLUnicodeString(blob, length, opts) {
3119
    var cch = blob.read_shift(opts !== undefined && opts.biff > 0 && opts.biff < 8 ? 1 : 2);
3120
    if(cch === 0) { blob.l++; return ""; }
3121
    return parse_XLUnicodeStringNoCch(blob, cch, opts);
3122
}
3123
/* BIFF5 override */
3124
function parse_XLUnicodeString2(blob, length, opts) {
3125
    if(opts.biff !== 5 && opts.biff !== 2) return parse_XLUnicodeString(blob, length, opts);
3126
    var cch = blob.read_shift(1);
3127
    if(cch === 0) { blob.l++; return ""; }
3128
    return blob.read_shift(cch, 'sbcs-cont');
3129
}
3130
 
3131
/* [MS-XLS] 2.5.61 ControlInfo */
3132
var parse_ControlInfo = parsenoop;
3133
 
3134
/* [MS-OSHARED] 2.3.7.6 URLMoniker TODO: flags */
3135
var parse_URLMoniker = function(blob, length) {
3136
    var len = blob.read_shift(4), start = blob.l;
3137
    var extra = false;
3138
    if(len > 24) {
3139
        /* look ahead */
3140
        blob.l += len - 24;
3141
        if(blob.read_shift(16) === "795881f43b1d7f48af2c825dc4852763") extra = true;
3142
        blob.l = start;
3143
    }
3144
    var url = blob.read_shift((extra?len-24:len)>>1, 'utf16le').replace(chr0,"");
3145
    if(extra) blob.l += 24;
3146
    return url;
3147
};
3148
 
3149
/* [MS-OSHARED] 2.3.7.8 FileMoniker TODO: all fields */
3150
var parse_FileMoniker = function(blob, length) {
3151
    var cAnti = blob.read_shift(2);
3152
    var ansiLength = blob.read_shift(4);
3153
    var ansiPath = blob.read_shift(ansiLength, 'cstr');
3154
    var endServer = blob.read_shift(2);
3155
    var versionNumber = blob.read_shift(2);
3156
    var cbUnicodePathSize = blob.read_shift(4);
3157
    if(cbUnicodePathSize === 0) return ansiPath.replace(/\\/g,"/");
3158
    var cbUnicodePathBytes = blob.read_shift(4);
3159
    var usKeyValue = blob.read_shift(2);
3160
    var unicodePath = blob.read_shift(cbUnicodePathBytes>>1, 'utf16le').replace(chr0,"");
3161
    return unicodePath;
3162
};
3163
 
3164
/* [MS-OSHARED] 2.3.7.2 HyperlinkMoniker TODO: all the monikers */
3165
var parse_HyperlinkMoniker = function(blob, length) {
3166
    var clsid = blob.read_shift(16); length -= 16;
3167
    switch(clsid) {
3168
        case "e0c9ea79f9bace118c8200aa004ba90b": return parse_URLMoniker(blob, length);
3169
        case "0303000000000000c000000000000046": return parse_FileMoniker(blob, length);
3170
        default: throw "unsupported moniker " + clsid;
3171
    }
3172
};
3173
 
3174
/* [MS-OSHARED] 2.3.7.9 HyperlinkString */
3175
var parse_HyperlinkString = function(blob, length) {
3176
    var len = blob.read_shift(4);
3177
    var o = blob.read_shift(len, 'utf16le').replace(chr0, "");
3178
    return o;
3179
};
3180
 
3181
/* [MS-OSHARED] 2.3.7.1 Hyperlink Object TODO: unify params with XLSX */
3182
var parse_Hyperlink = function(blob, length) {
3183
    var end = blob.l + length;
3184
    var sVer = blob.read_shift(4);
3185
    if(sVer !== 2) throw new Error("Unrecognized streamVersion: " + sVer);
3186
    var flags = blob.read_shift(2);
3187
    blob.l += 2;
3188
    var displayName, targetFrameName, moniker, oleMoniker, location, guid, fileTime;
3189
    if(flags & 0x0010) displayName = parse_HyperlinkString(blob, end - blob.l);
3190
    if(flags & 0x0080) targetFrameName = parse_HyperlinkString(blob, end - blob.l);
3191
    if((flags & 0x0101) === 0x0101) moniker = parse_HyperlinkString(blob, end - blob.l);
3192
    if((flags & 0x0101) === 0x0001) oleMoniker = parse_HyperlinkMoniker(blob, end - blob.l);
3193
    if(flags & 0x0008) location = parse_HyperlinkString(blob, end - blob.l);
3194
    if(flags & 0x0020) guid = blob.read_shift(16);
3195
    if(flags & 0x0040) fileTime = parse_FILETIME(blob, 8);
3196
    blob.l = end;
3197
    var target = (targetFrameName||moniker||oleMoniker);
3198
    if(location) target+="#"+location;
3199
    return {Target: target};
3200
};
3201
 
3202
/* 2.5.178 LongRGBA */
3203
function parse_LongRGBA(blob, length) { var r = blob.read_shift(1), g = blob.read_shift(1), b = blob.read_shift(1), a = blob.read_shift(1); return [r,g,b,a]; }
3204
 
3205
/* 2.5.177 LongRGB */
3206
function parse_LongRGB(blob, length) { var x = parse_LongRGBA(blob, length); x[3] = 0; return x; }
3207
 
3208
 
3209
/* --- MS-XLS --- */
3210
 
3211
/* 2.5.19 */
3212
function parse_XLSCell(blob, length) {
3213
    var rw = blob.read_shift(2); // 0-indexed
3214
    var col = blob.read_shift(2);
3215
    var ixfe = blob.read_shift(2);
3216
    return {r:rw, c:col, ixfe:ixfe};
3217
}
3218
 
3219
/* 2.5.134 */
3220
function parse_frtHeader(blob) {
3221
    var rt = blob.read_shift(2);
3222
    var flags = blob.read_shift(2); // TODO: parse these flags
3223
    blob.l += 8;
3224
    return {type: rt, flags: flags};
3225
}
3226
 
3227
 
3228
 
3229
function parse_OptXLUnicodeString(blob, length, opts) { return length === 0 ? "" : parse_XLUnicodeString2(blob, length, opts); }
3230
 
3231
/* 2.5.158 */
3232
var HIDEOBJENUM = ['SHOWALL', 'SHOWPLACEHOLDER', 'HIDEALL'];
3233
var parse_HideObjEnum = parseuint16;
3234
 
3235
/* 2.5.344 */
3236
function parse_XTI(blob, length) {
3237
    var iSupBook = blob.read_shift(2), itabFirst = blob.read_shift(2,'i'), itabLast = blob.read_shift(2,'i');
3238
    return [iSupBook, itabFirst, itabLast];
3239
}
3240
 
3241
/* 2.5.218 */
3242
function parse_RkRec(blob, length) {
3243
    var ixfe = blob.read_shift(2);
3244
    var RK = parse_RkNumber(blob);
3245
    //console.log("::", ixfe, RK,";;");
3246
    return [ixfe, RK];
3247
}
3248
 
3249
/* 2.5.1 */
3250
function parse_AddinUdf(blob, length) {
3251
    blob.l += 4; length -= 4;
3252
    var l = blob.l + length;
3253
    var udfName = parse_ShortXLUnicodeString(blob, length);
3254
    var cb = blob.read_shift(2);
3255
    l -= blob.l;
3256
    if(cb !== l) throw "Malformed AddinUdf: padding = " + l + " != " + cb;
3257
    blob.l += cb;
3258
    return udfName;
3259
}
3260
 
3261
/* 2.5.209 TODO: Check sizes */
3262
function parse_Ref8U(blob, length) {
3263
    var rwFirst = blob.read_shift(2);
3264
    var rwLast = blob.read_shift(2);
3265
    var colFirst = blob.read_shift(2);
3266
    var colLast = blob.read_shift(2);
3267
    return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}};
3268
}
3269
 
3270
/* 2.5.211 */
3271
function parse_RefU(blob, length) {
3272
    var rwFirst = blob.read_shift(2);
3273
    var rwLast = blob.read_shift(2);
3274
    var colFirst = blob.read_shift(1);
3275
    var colLast = blob.read_shift(1);
3276
    return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}};
3277
}
3278
 
3279
/* 2.5.207 */
3280
var parse_Ref = parse_RefU;
3281
 
3282
/* 2.5.143 */
3283
function parse_FtCmo(blob, length) {
3284
    blob.l += 4;
3285
    var ot = blob.read_shift(2);
3286
    var id = blob.read_shift(2);
3287
    var flags = blob.read_shift(2);
3288
    blob.l+=12;
3289
    return [id, ot, flags];
3290
}
3291
 
3292
/* 2.5.149 */
3293
function parse_FtNts(blob, length) {
3294
    var out = {};
3295
    blob.l += 4;
3296
    blob.l += 16; // GUID TODO
3297
    out.fSharedNote = blob.read_shift(2);
3298
    blob.l += 4;
3299
    return out;
3300
}
3301
 
3302
/* 2.5.142 */
3303
function parse_FtCf(blob, length) {
3304
    var out = {};
3305
    blob.l += 4;
3306
    blob.cf = blob.read_shift(2);
3307
    return out;
3308
}
3309
 
3310
/* 2.5.140 - 2.5.154 and friends */
3311
var FtTab = {
3312
    0x15: parse_FtCmo,
3313
    0x13: parsenoop,                                /* FtLbsData */
3314
    0x12: function(blob, length) { blob.l += 12; }, /* FtCblsData */
3315
    0x11: function(blob, length) { blob.l += 8; },  /* FtRboData */
3316
    0x10: parsenoop,                                /* FtEdoData */
3317
    0x0F: parsenoop,                                /* FtGboData */
3318
    0x0D: parse_FtNts,                              /* FtNts */
3319
    0x0C: function(blob, length) { blob.l += 24; }, /* FtSbs */
3320
    0x0B: function(blob, length) { blob.l += 10; }, /* FtRbo */
3321
    0x0A: function(blob, length) { blob.l += 16; }, /* FtCbls */
3322
    0x09: parsenoop,                                /* FtPictFmla */
3323
    0x08: function(blob, length) { blob.l += 6; },  /* FtPioGrbit */
3324
    0x07: parse_FtCf,                               /* FtCf */
3325
    0x06: function(blob, length) { blob.l += 6; },  /* FtGmo */
3326
    0x04: parsenoop,                                /* FtMacro */
3327
    0x00: function(blob, length) { blob.l += 4; }   /* FtEnding */
3328
};
3329
function parse_FtArray(blob, length, ot) {
3330
    var s = blob.l;
3331
    var fts = [];
3332
    while(blob.l < s + length) {
3333
        var ft = blob.read_shift(2);
3334
        blob.l-=2;
3335
        try {
3336
            fts.push(FtTab[ft](blob, s + length - blob.l));
3337
        } catch(e) { blob.l = s + length; return fts; }
3338
    }
3339
    if(blob.l != s + length) blob.l = s + length; //throw "bad Object Ft-sequence";
3340
    return fts;
3341
}
3342
 
3343
/* 2.5.129 */
3344
var parse_FontIndex = parseuint16;
3345
 
3346
/* --- 2.4 Records --- */
3347
 
3348
/* 2.4.21 */
3349
function parse_BOF(blob, length) {
3350
    var o = {};
3351
    o.BIFFVer = blob.read_shift(2); length -= 2;
3352
    switch(o.BIFFVer) {
3353
        case 0x0600: /* BIFF8 */
3354
        case 0x0500: /* BIFF5 */
3355
        case 0x0002: case 0x0007: /* BIFF2 */
3356
            break;
3357
        default: throw "Unexpected BIFF Ver " + o.BIFFVer;
3358
    }
3359
    blob.read_shift(length);
3360
    return o;
3361
}
3362
 
3363
 
3364
/* 2.4.146 */
3365
function parse_InterfaceHdr(blob, length) {
3366
    if(length === 0) return 0x04b0;
3367
    var q;
3368
    if((q=blob.read_shift(2))!==0x04b0) throw 'InterfaceHdr codePage ' + q;
3369
    return 0x04b0;
3370
}
3371
 
3372
 
3373
/* 2.4.349 */
3374
function parse_WriteAccess(blob, length, opts) {
3375
    if(opts.enc) { blob.l += length; return ""; }
3376
    var l = blob.l;
3377
    // TODO: make sure XLUnicodeString doesnt overrun
3378
    var UserName = parse_XLUnicodeString(blob, 0, opts);
3379
    blob.read_shift(length + l - blob.l);
3380
    return UserName;
3381
}
3382
 
3383
/* 2.4.28 */
3384
function parse_BoundSheet8(blob, length, opts) {
3385
    var pos = blob.read_shift(4);
3386
    var hidden = blob.read_shift(1) >> 6;
3387
    var dt = blob.read_shift(1);
3388
    switch(dt) {
3389
        case 0: dt = 'Worksheet'; break;
3390
        case 1: dt = 'Macrosheet'; break;
3391
        case 2: dt = 'Chartsheet'; break;
3392
        case 6: dt = 'VBAModule'; break;
3393
    }
3394
    var name = parse_ShortXLUnicodeString(blob, 0, opts);
3395
    if(name.length === 0) name = "Sheet1";
3396
    return { pos:pos, hs:hidden, dt:dt, name:name };
3397
}
3398
 
3399
/* 2.4.265 TODO */
3400
function parse_SST(blob, length) {
3401
    var cnt = blob.read_shift(4);
3402
    var ucnt = blob.read_shift(4);
3403
    var strs = [];
3404
    for(var i = 0; i != ucnt; ++i) {
3405
        strs.push(parse_XLUnicodeRichExtendedString(blob));
3406
    }
3407
    strs.Count = cnt; strs.Unique = ucnt;
3408
    return strs;
3409
}
3410
 
3411
/* 2.4.107 */
3412
function parse_ExtSST(blob, length) {
3413
    var extsst = {};
3414
    extsst.dsst = blob.read_shift(2);
3415
    blob.l += length-2;
3416
    return extsst;
3417
}
3418
 
3419
 
3420
/* 2.4.221 TODO*/
3421
function parse_Row(blob, length) {
3422
    var rw = blob.read_shift(2), col = blob.read_shift(2), Col = blob.read_shift(2), rht = blob.read_shift(2);
3423
    blob.read_shift(4); // reserved(2), unused(2)
3424
    var flags = blob.read_shift(1); // various flags
3425
    blob.read_shift(1); // reserved
3426
    blob.read_shift(2); //ixfe, other flags
3427
    return {r:rw, c:col, cnt:Col-col};
3428
}
3429
 
3430
 
3431
/* 2.4.125 */
3432
function parse_ForceFullCalculation(blob, length) {
3433
    var header = parse_frtHeader(blob);
3434
    if(header.type != 0x08A3) throw "Invalid Future Record " + header.type;
3435
    var fullcalc = blob.read_shift(4);
3436
    return fullcalc !== 0x0;
3437
}
3438
 
3439
 
3440
var parse_CompressPictures = parsenoop2; /* 2.4.55 Not interesting */
3441
 
3442
 
3443
 
3444
/* 2.4.215 rt */
3445
function parse_RecalcId(blob, length) {
3446
    blob.read_shift(2);
3447
    return blob.read_shift(4);
3448
}
3449
 
3450
/* 2.4.87 */
3451
function parse_DefaultRowHeight (blob, length) {
3452
    var f = blob.read_shift(2), miyRw;
3453
    miyRw = blob.read_shift(2); // flags & 0x02 -> hidden, else empty
3454
    var fl = {Unsynced:f&1,DyZero:(f&2)>>1,ExAsc:(f&4)>>2,ExDsc:(f&8)>>3};
3455
    return [fl, miyRw];
3456
}
3457
 
3458
/* 2.4.345 TODO */
3459
function parse_Window1(blob, length) {
3460
    var xWn = blob.read_shift(2), yWn = blob.read_shift(2), dxWn = blob.read_shift(2), dyWn = blob.read_shift(2);
3461
    var flags = blob.read_shift(2), iTabCur = blob.read_shift(2), iTabFirst = blob.read_shift(2);
3462
    var ctabSel = blob.read_shift(2), wTabRatio = blob.read_shift(2);
3463
    return { Pos: [xWn, yWn], Dim: [dxWn, dyWn], Flags: flags, CurTab: iTabCur,
3464
        FirstTab: iTabFirst, Selected: ctabSel, TabRatio: wTabRatio };
3465
}
3466
 
3467
/* 2.4.122 TODO */
3468
function parse_Font(blob, length, opts) {
3469
    blob.l += 14;
3470
    var name = parse_ShortXLUnicodeString(blob, 0, opts);
3471
    return name;
3472
}
3473
 
3474
/* 2.4.149 */
3475
function parse_LabelSst(blob, length) {
3476
    var cell = parse_XLSCell(blob);
3477
    cell.isst = blob.read_shift(4);
3478
    return cell;
3479
}
3480
 
3481
/* 2.4.148 */
3482
function parse_Label(blob, length, opts) {
3483
    var cell = parse_XLSCell(blob, 6);
3484
    var str = parse_XLUnicodeString(blob, length-6, opts);
3485
    cell.val = str;
3486
    return cell;
3487
}
3488
 
3489
/* 2.4.126 Number Formats */
3490
function parse_Format(blob, length, opts) {
3491
    var ifmt = blob.read_shift(2);
3492
    var fmtstr = parse_XLUnicodeString2(blob, 0, opts);
3493
    return [ifmt, fmtstr];
3494
}
3495
 
3496
/* 2.4.90 */
3497
function parse_Dimensions(blob, length) {
3498
    var w = length === 10 ? 2 : 4;
3499
    var r = blob.read_shift(w), R = blob.read_shift(w),
3500
        c = blob.read_shift(2), C = blob.read_shift(2);
3501
    blob.l += 2;
3502
    return {s: {r:r, c:c}, e: {r:R, c:C}};
3503
}
3504
 
3505
/* 2.4.220 */
3506
function parse_RK(blob, length) {
3507
    var rw = blob.read_shift(2), col = blob.read_shift(2);
3508
    var rkrec = parse_RkRec(blob);
3509
    return {r:rw, c:col, ixfe:rkrec[0], rknum:rkrec[1]};
3510
}
3511
 
3512
/* 2.4.175 */
3513
function parse_MulRk(blob, length) {
3514
    var target = blob.l + length - 2;
3515
    var rw = blob.read_shift(2), col = blob.read_shift(2);
3516
    var rkrecs = [];
3517
    while(blob.l < target) rkrecs.push(parse_RkRec(blob));
3518
    if(blob.l !== target) throw "MulRK read error";
3519
    var lastcol = blob.read_shift(2);
3520
    if(rkrecs.length != lastcol - col + 1) throw "MulRK length mismatch";
3521
    return {r:rw, c:col, C:lastcol, rkrec:rkrecs};
3522
}
3523
 
3524
/* 2.5.20 2.5.249 TODO */
3525
function parse_CellStyleXF(blob, length, style) {
3526
    var o = {};
3527
    var a = blob.read_shift(4), b = blob.read_shift(4);
3528
    var c = blob.read_shift(4), d = blob.read_shift(2);
3529
    o.patternType = XLSFillPattern[c >> 26];
3530
    o.icvFore = d & 0x7F;
3531
    o.icvBack = (d >> 7) & 0x7F;
3532
    return o;
3533
}
3534
function parse_CellXF(blob, length) {return parse_CellStyleXF(blob,length,0);}
3535
function parse_StyleXF(blob, length) {return parse_CellStyleXF(blob,length,1);}
3536
 
3537
/* 2.4.353 TODO: actually do this right */
3538
function parse_XF(blob, length) {
3539
    var o = {};
3540
    o.ifnt = blob.read_shift(2); o.ifmt = blob.read_shift(2); o.flags = blob.read_shift(2);
3541
    o.fStyle = (o.flags >> 2) & 0x01;
3542
    length -= 6;
3543
    o.data = parse_CellStyleXF(blob, length, o.fStyle);
3544
    return o;
3545
}
3546
 
3547
/* 2.4.134 */
3548
function parse_Guts(blob, length) {
3549
    blob.l += 4;
3550
    var out = [blob.read_shift(2), blob.read_shift(2)];
3551
    if(out[0] !== 0) out[0]--;
3552
    if(out[1] !== 0) out[1]--;
3553
    if(out[0] > 7 || out[1] > 7) throw "Bad Gutters: " + out;
3554
    return out;
3555
}
3556
 
3557
/* 2.4.24 */
3558
function parse_BoolErr(blob, length) {
3559
    var cell = parse_XLSCell(blob, 6);
3560
    var val = parse_Bes(blob, 2);
3561
    cell.val = val;
3562
    cell.t = (val === true || val === false) ? 'b' : 'e';
3563
    return cell;
3564
}
3565
 
3566
/* 2.4.180 Number */
3567
function parse_Number(blob, length) {
3568
    var cell = parse_XLSCell(blob, 6);
3569
    var xnum = parse_Xnum(blob, 8);
3570
    cell.val = xnum;
3571
    return cell;
3572
}
3573
 
3574
var parse_XLHeaderFooter = parse_OptXLUnicodeString; // TODO: parse 2.4.136
3575
 
3576
/* 2.4.271 */
3577
function parse_SupBook(blob, length, opts) {
3578
    var end = blob.l + length;
3579
    var ctab = blob.read_shift(2);
3580
    var cch = blob.read_shift(2);
3581
    var virtPath;
3582
    if(cch >=0x01 && cch <=0xff) virtPath = parse_XLUnicodeStringNoCch(blob, cch);
3583
    var rgst = blob.read_shift(end - blob.l);
3584
    opts.sbcch = cch;
3585
    return [cch, ctab, virtPath, rgst];
3586
}
3587
 
3588
/* 2.4.105 TODO */
3589
function parse_ExternName(blob, length, opts) {
3590
    var flags = blob.read_shift(2);
3591
    var body;
3592
    var o = {
3593
        fBuiltIn: flags & 0x01,
3594
        fWantAdvise: (flags >>> 1) & 0x01,
3595
        fWantPict: (flags >>> 2) & 0x01,
3596
        fOle: (flags >>> 3) & 0x01,
3597
        fOleLink: (flags >>> 4) & 0x01,
3598
        cf: (flags >>> 5) & 0x3FF,
3599
        fIcon: flags >>> 15 & 0x01
3600
    };
3601
    if(opts.sbcch === 0x3A01) body = parse_AddinUdf(blob, length-2);
3602
    //else throw new Error("unsupported SupBook cch: " + opts.sbcch);
3603
    o.body = body || blob.read_shift(length-2);
3604
    return o;
3605
}
3606
 
3607
/* 2.4.150 TODO */
3608
function parse_Lbl(blob, length, opts) {
3609
    if(opts.biff < 8) return parse_Label(blob, length, opts);
3610
    var target = blob.l + length;
3611
    var flags = blob.read_shift(2);
3612
    var chKey = blob.read_shift(1);
3613
    var cch = blob.read_shift(1);
3614
    var cce = blob.read_shift(2);
3615
    blob.l += 2;
3616
    var itab = blob.read_shift(2);
3617
    blob.l += 4;
3618
    var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
3619
    var rgce = parse_NameParsedFormula(blob, target - blob.l, opts, cce);
3620
    return {
3621
        chKey: chKey,
3622
        Name: name,
3623
        rgce: rgce
3624
    };
3625
}
3626
 
3627
/* 2.4.106 TODO: verify supbook manipulation */
3628
function parse_ExternSheet(blob, length, opts) {
3629
    if(opts.biff < 8) return parse_ShortXLUnicodeString(blob, length, opts);
3630
    var o = parslurp2(blob,length,parse_XTI);
3631
    var oo = [];
3632
    if(opts.sbcch === 0x0401) {
3633
        for(var i = 0; i != o.length; ++i) oo.push(opts.snames[o[i][1]]);
3634
        return oo;
3635
    }
3636
    else return o;
3637
}
3638
 
3639
/* 2.4.260 */
3640
function parse_ShrFmla(blob, length, opts) {
3641
    var ref = parse_RefU(blob, 6);
3642
    blob.l++;
3643
    var cUse = blob.read_shift(1);
3644
    length -= 8;
3645
    return [parse_SharedParsedFormula(blob, length, opts), cUse];
3646
}
3647
 
3648
/* 2.4.4 TODO */
3649
function parse_Array(blob, length, opts) {
3650
    var ref = parse_Ref(blob, 6);
3651
    blob.l += 6; length -= 12; /* TODO: fAlwaysCalc */
3652
    return [ref, parse_ArrayParsedFormula(blob, length, opts, ref)];
3653
}
3654
 
3655
/* 2.4.173 */
3656
function parse_MTRSettings(blob, length) {
3657
    var fMTREnabled = blob.read_shift(4) !== 0x00;
3658
    var fUserSetThreadCount = blob.read_shift(4) !== 0x00;
3659
    var cUserThreadCount = blob.read_shift(4);
3660
    return [fMTREnabled, fUserSetThreadCount, cUserThreadCount];
3661
}
3662
 
3663
/* 2.5.186 TODO: BIFF5 */
3664
function parse_NoteSh(blob, length, opts) {
3665
    if(opts.biff < 8) return;
3666
    var row = blob.read_shift(2), col = blob.read_shift(2);
3667
    var flags = blob.read_shift(2), idObj = blob.read_shift(2);
3668
    var stAuthor = parse_XLUnicodeString2(blob, 0, opts);
3669
    if(opts.biff < 8) blob.read_shift(1);
3670
    return [{r:row,c:col}, stAuthor, idObj, flags];
3671
}
3672
 
3673
/* 2.4.179 */
3674
function parse_Note(blob, length, opts) {
3675
    /* TODO: Support revisions */
3676
    return parse_NoteSh(blob, length, opts);
3677
}
3678
 
3679
/* 2.4.168 */
3680
function parse_MergeCells(blob, length) {
3681
    var merges = [];
3682
    var cmcs = blob.read_shift(2);
3683
    while (cmcs--) merges.push(parse_Ref8U(blob,length));
3684
    return merges;
3685
}
3686
 
3687
/* 2.4.181 TODO: parse all the things! */
3688
function parse_Obj(blob, length) {
3689
    var cmo = parse_FtCmo(blob, 22); // id, ot, flags
3690
    var fts = parse_FtArray(blob, length-22, cmo[1]);
3691
    return { cmo: cmo, ft:fts };
3692
}
3693
 
3694
/* 2.4.329 TODO: parse properly */
3695
function parse_TxO(blob, length, opts) {
3696
    var s = blob.l;
3697
try {
3698
    blob.l += 4;
3699
    var ot = (opts.lastobj||{cmo:[0,0]}).cmo[1];
3700
    var controlInfo;
3701
    if([0,5,7,11,12,14].indexOf(ot) == -1) blob.l += 6;
3702
    else controlInfo = parse_ControlInfo(blob, 6, opts);
3703
    var cchText = blob.read_shift(2);
3704
    var cbRuns = blob.read_shift(2);
3705
    var ifntEmpty = parse_FontIndex(blob, 2);
3706
    var len = blob.read_shift(2);
3707
    blob.l += len;
3708
    //var fmla = parse_ObjFmla(blob, s + length - blob.l);
3709
 
3710
    var texts = "";
3711
    for(var i = 1; i < blob.lens.length-1; ++i) {
3712
        if(blob.l-s != blob.lens[i]) throw "TxO: bad continue record";
3713
        var hdr = blob[blob.l];
3714
        var t = parse_XLUnicodeStringNoCch(blob, blob.lens[i+1]-blob.lens[i]-1);
3715
        texts += t;
3716
        if(texts.length >= (hdr ? cchText : 2*cchText)) break;
3717
    }
3718
    if(texts.length !== cchText && texts.length !== cchText*2) {
3719
        throw "cchText: " + cchText + " != " + texts.length;
3720
    }
3721
 
3722
    blob.l = s + length;
3723
    /* 2.5.272 TxORuns */
3724
//  var rgTxoRuns = [];
3725
//  for(var j = 0; j != cbRuns/8-1; ++j) blob.l += 8;
3726
//  var cchText2 = blob.read_shift(2);
3727
//  if(cchText2 !== cchText) throw "TxOLastRun mismatch: " + cchText2 + " " + cchText;
3728
//  blob.l += 6;
3729
//  if(s + length != blob.l) throw "TxO " + (s + length) + ", at " + blob.l;
3730
    return { t: texts };
3731
} catch(e) { blob.l = s + length; return { t: texts||"" }; }
3732
}
3733
 
3734
/* 2.4.140 */
3735
var parse_HLink = function(blob, length) {
3736
    var ref = parse_Ref8U(blob, 8);
3737
    blob.l += 16; /* CLSID */
3738
    var hlink = parse_Hyperlink(blob, length-24);
3739
    return [ref, hlink];
3740
};
3741
 
3742
/* 2.4.141 */
3743
var parse_HLinkTooltip = function(blob, length) {
3744
    var end = blob.l + length;
3745
    blob.read_shift(2);
3746
    var ref = parse_Ref8U(blob, 8);
3747
    var wzTooltip = blob.read_shift((length-10)/2, 'dbcs-cont');
3748
    wzTooltip = wzTooltip.replace(chr0,"");
3749
    return [ref, wzTooltip];
3750
};
3751
 
3752
/* 2.4.63 */
3753
function parse_Country(blob, length) {
3754
    var o = [], d;
3755
    d = blob.read_shift(2); o[0] = CountryEnum[d] || d;
3756
    d = blob.read_shift(2); o[1] = CountryEnum[d] || d;
3757
    return o;
3758
}
3759
 
3760
/* 2.4.50 ClrtClient */
3761
function parse_ClrtClient(blob, length) {
3762
    var ccv = blob.read_shift(2);
3763
    var o = [];
3764
    while(ccv-->0) o.push(parse_LongRGB(blob, 8));
3765
    return o;
3766
}
3767
 
3768
/* 2.4.188 */
3769
function parse_Palette(blob, length) {
3770
    var ccv = blob.read_shift(2);
3771
    var o = [];
3772
    while(ccv-->0) o.push(parse_LongRGB(blob, 8));
3773
    return o;
3774
}
3775
 
3776
/* 2.4.354 */
3777
function parse_XFCRC(blob, length) {
3778
    blob.l += 2;
3779
    var o = {cxfs:0, crc:0};
3780
    o.cxfs = blob.read_shift(2);
3781
    o.crc = blob.read_shift(4);
3782
    return o;
3783
}
3784
 
3785
 
3786
var parse_Style = parsenoop;
3787
var parse_StyleExt = parsenoop;
3788
 
3789
var parse_ColInfo = parsenoop;
3790
 
3791
var parse_Window2 = parsenoop;
3792
 
3793
 
3794
var parse_Backup = parsebool; /* 2.4.14 */
3795
var parse_Blank = parse_XLSCell; /* 2.4.20 Just the cell */
3796
var parse_BottomMargin = parse_Xnum; /* 2.4.27 */
3797
var parse_BuiltInFnGroupCount = parseuint16; /* 2.4.30 0x0E or 0x10 but excel 2011 generates 0x11? */
3798
var parse_CalcCount = parseuint16; /* 2.4.31 #Iterations */
3799
var parse_CalcDelta = parse_Xnum; /* 2.4.32 */
3800
var parse_CalcIter = parsebool;  /* 2.4.33 1=iterative calc */
3801
var parse_CalcMode = parseuint16; /* 2.4.34 0=manual, 1=auto (def), 2=table */
3802
var parse_CalcPrecision = parsebool; /* 2.4.35 */
3803
var parse_CalcRefMode = parsenoop2; /* 2.4.36 */
3804
var parse_CalcSaveRecalc = parsebool; /* 2.4.37 */
3805
var parse_CodePage = parseuint16; /* 2.4.52 */
3806
var parse_Compat12 = parsebool; /* 2.4.54 true = no compatibility check */
3807
var parse_Date1904 = parsebool; /* 2.4.77 - 1=1904,0=1900 */
3808
var parse_DefColWidth = parseuint16; /* 2.4.89 */
3809
var parse_DSF = parsenoop2; /* 2.4.94 -- MUST be ignored */
3810
var parse_EntExU2 = parsenoop2; /* 2.4.102 -- Explicitly says to ignore */
3811
var parse_EOF = parsenoop2; /* 2.4.103 */
3812
var parse_Excel9File = parsenoop2; /* 2.4.104 -- Optional and unused */
3813
var parse_FeatHdr = parsenoop2; /* 2.4.112 */
3814
var parse_FontX = parseuint16; /* 2.4.123 */
3815
var parse_Footer = parse_XLHeaderFooter; /* 2.4.124 */
3816
var parse_GridSet = parseuint16; /* 2.4.132, =1 */
3817
var parse_HCenter = parsebool; /* 2.4.135 sheet centered horizontal on print */
3818
var parse_Header = parse_XLHeaderFooter; /* 2.4.136 */
3819
var parse_HideObj = parse_HideObjEnum; /* 2.4.139 */
3820
var parse_InterfaceEnd = parsenoop2; /* 2.4.145 -- noop */
3821
var parse_LeftMargin = parse_Xnum; /* 2.4.151 */
3822
var parse_Mms = parsenoop2; /* 2.4.169 -- Explicitly says to ignore */
3823
var parse_ObjProtect = parsebool; /* 2.4.183 -- must be 1 if present */
3824
var parse_Password = parseuint16; /* 2.4.191 */
3825
var parse_PrintGrid = parsebool; /* 2.4.202 */
3826
var parse_PrintRowCol = parsebool; /* 2.4.203 */
3827
var parse_PrintSize = parseuint16; /* 2.4.204 0:3 */
3828
var parse_Prot4Rev = parsebool; /* 2.4.205 */
3829
var parse_Prot4RevPass = parseuint16; /* 2.4.206 */
3830
var parse_Protect = parsebool; /* 2.4.207 */
3831
var parse_RefreshAll = parsebool; /* 2.4.217 -- must be 0 if not template */
3832
var parse_RightMargin = parse_Xnum; /* 2.4.219 */
3833
var parse_RRTabId = parseuint16a; /* 2.4.241 */
3834
var parse_ScenarioProtect = parsebool; /* 2.4.245 */
3835
var parse_Scl = parseuint16a; /* 2.4.247 num, den */
3836
var parse_String = parse_XLUnicodeString; /* 2.4.268 */
3837
var parse_SxBool = parsebool; /* 2.4.274 */
3838
var parse_TopMargin = parse_Xnum; /* 2.4.328 */
3839
var parse_UsesELFs = parsebool; /* 2.4.337 -- should be 0 */
3840
var parse_VCenter = parsebool; /* 2.4.342 */
3841
var parse_WinProtect = parsebool; /* 2.4.347 */
3842
var parse_WriteProtect = parsenoop; /* 2.4.350 empty record */
3843
 
3844
 
3845
/* ---- */
3846
var parse_VerticalPageBreaks = parsenoop;
3847
var parse_HorizontalPageBreaks = parsenoop;
3848
var parse_Selection = parsenoop;
3849
var parse_Continue = parsenoop;
3850
var parse_Pane = parsenoop;
3851
var parse_Pls = parsenoop;
3852
var parse_DCon = parsenoop;
3853
var parse_DConRef = parsenoop;
3854
var parse_DConName = parsenoop;
3855
var parse_XCT = parsenoop;
3856
var parse_CRN = parsenoop;
3857
var parse_FileSharing = parsenoop;
3858
var parse_Uncalced = parsenoop;
3859
var parse_Template = parsenoop;
3860
var parse_Intl = parsenoop;
3861
var parse_WsBool = parsenoop;
3862
var parse_Sort = parsenoop;
3863
var parse_Sync = parsenoop;
3864
var parse_LPr = parsenoop;
3865
var parse_DxGCol = parsenoop;
3866
var parse_FnGroupName = parsenoop;
3867
var parse_FilterMode = parsenoop;
3868
var parse_AutoFilterInfo = parsenoop;
3869
var parse_AutoFilter = parsenoop;
3870
var parse_Setup = parsenoop;
3871
var parse_ScenMan = parsenoop;
3872
var parse_SCENARIO = parsenoop;
3873
var parse_SxView = parsenoop;
3874
var parse_Sxvd = parsenoop;
3875
var parse_SXVI = parsenoop;
3876
var parse_SxIvd = parsenoop;
3877
var parse_SXLI = parsenoop;
3878
var parse_SXPI = parsenoop;
3879
var parse_DocRoute = parsenoop;
3880
var parse_RecipName = parsenoop;
3881
var parse_MulBlank = parsenoop;
3882
var parse_SXDI = parsenoop;
3883
var parse_SXDB = parsenoop;
3884
var parse_SXFDB = parsenoop;
3885
var parse_SXDBB = parsenoop;
3886
var parse_SXNum = parsenoop;
3887
var parse_SxErr = parsenoop;
3888
var parse_SXInt = parsenoop;
3889
var parse_SXString = parsenoop;
3890
var parse_SXDtr = parsenoop;
3891
var parse_SxNil = parsenoop;
3892
var parse_SXTbl = parsenoop;
3893
var parse_SXTBRGIITM = parsenoop;
3894
var parse_SxTbpg = parsenoop;
3895
var parse_ObProj = parsenoop;
3896
var parse_SXStreamID = parsenoop;
3897
var parse_DBCell = parsenoop;
3898
var parse_SXRng = parsenoop;
3899
var parse_SxIsxoper = parsenoop;
3900
var parse_BookBool = parsenoop;
3901
var parse_DbOrParamQry = parsenoop;
3902
var parse_OleObjectSize = parsenoop;
3903
var parse_SXVS = parsenoop;
3904
var parse_BkHim = parsenoop;
3905
var parse_MsoDrawingGroup = parsenoop;
3906
var parse_MsoDrawing = parsenoop;
3907
var parse_MsoDrawingSelection = parsenoop;
3908
var parse_PhoneticInfo = parsenoop;
3909
var parse_SxRule = parsenoop;
3910
var parse_SXEx = parsenoop;
3911
var parse_SxFilt = parsenoop;
3912
var parse_SxDXF = parsenoop;
3913
var parse_SxItm = parsenoop;
3914
var parse_SxName = parsenoop;
3915
var parse_SxSelect = parsenoop;
3916
var parse_SXPair = parsenoop;
3917
var parse_SxFmla = parsenoop;
3918
var parse_SxFormat = parsenoop;
3919
var parse_SXVDEx = parsenoop;
3920
var parse_SXFormula = parsenoop;
3921
var parse_SXDBEx = parsenoop;
3922
var parse_RRDInsDel = parsenoop;
3923
var parse_RRDHead = parsenoop;
3924
var parse_RRDChgCell = parsenoop;
3925
var parse_RRDRenSheet = parsenoop;
3926
var parse_RRSort = parsenoop;
3927
var parse_RRDMove = parsenoop;
3928
var parse_RRFormat = parsenoop;
3929
var parse_RRAutoFmt = parsenoop;
3930
var parse_RRInsertSh = parsenoop;
3931
var parse_RRDMoveBegin = parsenoop;
3932
var parse_RRDMoveEnd = parsenoop;
3933
var parse_RRDInsDelBegin = parsenoop;
3934
var parse_RRDInsDelEnd = parsenoop;
3935
var parse_RRDConflict = parsenoop;
3936
var parse_RRDDefName = parsenoop;
3937
var parse_RRDRstEtxp = parsenoop;
3938
var parse_LRng = parsenoop;
3939
var parse_CUsr = parsenoop;
3940
var parse_CbUsr = parsenoop;
3941
var parse_UsrInfo = parsenoop;
3942
var parse_UsrExcl = parsenoop;
3943
var parse_FileLock = parsenoop;
3944
var parse_RRDInfo = parsenoop;
3945
var parse_BCUsrs = parsenoop;
3946
var parse_UsrChk = parsenoop;
3947
var parse_UserBView = parsenoop;
3948
var parse_UserSViewBegin = parsenoop; // overloaded
3949
var parse_UserSViewEnd = parsenoop;
3950
var parse_RRDUserView = parsenoop;
3951
var parse_Qsi = parsenoop;
3952
var parse_CondFmt = parsenoop;
3953
var parse_CF = parsenoop;
3954
var parse_DVal = parsenoop;
3955
var parse_DConBin = parsenoop;
3956
var parse_Lel = parsenoop;
3957
var parse_XLSCodeName = parse_XLUnicodeString;
3958
var parse_SXFDBType = parsenoop;
3959
var parse_ObNoMacros = parsenoop;
3960
var parse_Dv = parsenoop;
3961
var parse_Index = parsenoop;
3962
var parse_Table = parsenoop;
3963
var parse_BigName = parsenoop;
3964
var parse_ContinueBigName = parsenoop;
3965
var parse_WebPub = parsenoop;
3966
var parse_QsiSXTag = parsenoop;
3967
var parse_DBQueryExt = parsenoop;
3968
var parse_ExtString = parsenoop;
3969
var parse_TxtQry = parsenoop;
3970
var parse_Qsir = parsenoop;
3971
var parse_Qsif = parsenoop;
3972
var parse_RRDTQSIF = parsenoop;
3973
var parse_OleDbConn = parsenoop;
3974
var parse_WOpt = parsenoop;
3975
var parse_SXViewEx = parsenoop;
3976
var parse_SXTH = parsenoop;
3977
var parse_SXPIEx = parsenoop;
3978
var parse_SXVDTEx = parsenoop;
3979
var parse_SXViewEx9 = parsenoop;
3980
var parse_ContinueFrt = parsenoop;
3981
var parse_RealTimeData = parsenoop;
3982
var parse_ChartFrtInfo = parsenoop;
3983
var parse_FrtWrapper = parsenoop;
3984
var parse_StartBlock = parsenoop;
3985
var parse_EndBlock = parsenoop;
3986
var parse_StartObject = parsenoop;
3987
var parse_EndObject = parsenoop;
3988
var parse_CatLab = parsenoop;
3989
var parse_YMult = parsenoop;
3990
var parse_SXViewLink = parsenoop;
3991
var parse_PivotChartBits = parsenoop;
3992
var parse_FrtFontList = parsenoop;
3993
var parse_SheetExt = parsenoop;
3994
var parse_BookExt = parsenoop;
3995
var parse_SXAddl = parsenoop;
3996
var parse_CrErr = parsenoop;
3997
var parse_HFPicture = parsenoop;
3998
var parse_Feat = parsenoop;
3999
var parse_DataLabExt = parsenoop;
4000
var parse_DataLabExtContents = parsenoop;
4001
var parse_CellWatch = parsenoop;
4002
var parse_FeatHdr11 = parsenoop;
4003
var parse_Feature11 = parsenoop;
4004
var parse_DropDownObjIds = parsenoop;
4005
var parse_ContinueFrt11 = parsenoop;
4006
var parse_DConn = parsenoop;
4007
var parse_List12 = parsenoop;
4008
var parse_Feature12 = parsenoop;
4009
var parse_CondFmt12 = parsenoop;
4010
var parse_CF12 = parsenoop;
4011
var parse_CFEx = parsenoop;
4012
var parse_AutoFilter12 = parsenoop;
4013
var parse_ContinueFrt12 = parsenoop;
4014
var parse_MDTInfo = parsenoop;
4015
var parse_MDXStr = parsenoop;
4016
var parse_MDXTuple = parsenoop;
4017
var parse_MDXSet = parsenoop;
4018
var parse_MDXProp = parsenoop;
4019
var parse_MDXKPI = parsenoop;
4020
var parse_MDB = parsenoop;
4021
var parse_PLV = parsenoop;
4022
var parse_DXF = parsenoop;
4023
var parse_TableStyles = parsenoop;
4024
var parse_TableStyle = parsenoop;
4025
var parse_TableStyleElement = parsenoop;
4026
var parse_NamePublish = parsenoop;
4027
var parse_NameCmt = parsenoop;
4028
var parse_SortData = parsenoop;
4029
var parse_GUIDTypeLib = parsenoop;
4030
var parse_FnGrp12 = parsenoop;
4031
var parse_NameFnGrp12 = parsenoop;
4032
var parse_HeaderFooter = parsenoop;
4033
var parse_CrtLayout12 = parsenoop;
4034
var parse_CrtMlFrt = parsenoop;
4035
var parse_CrtMlFrtContinue = parsenoop;
4036
var parse_ShapePropsStream = parsenoop;
4037
var parse_TextPropsStream = parsenoop;
4038
var parse_RichTextStream = parsenoop;
4039
var parse_CrtLayout12A = parsenoop;
4040
var parse_Units = parsenoop;
4041
var parse_Chart = parsenoop;
4042
var parse_Series = parsenoop;
4043
var parse_DataFormat = parsenoop;
4044
var parse_LineFormat = parsenoop;
4045
var parse_MarkerFormat = parsenoop;
4046
var parse_AreaFormat = parsenoop;
4047
var parse_PieFormat = parsenoop;
4048
var parse_AttachedLabel = parsenoop;
4049
var parse_SeriesText = parsenoop;
4050
var parse_ChartFormat = parsenoop;
4051
var parse_Legend = parsenoop;
4052
var parse_SeriesList = parsenoop;
4053
var parse_Bar = parsenoop;
4054
var parse_Line = parsenoop;
4055
var parse_Pie = parsenoop;
4056
var parse_Area = parsenoop;
4057
var parse_Scatter = parsenoop;
4058
var parse_CrtLine = parsenoop;
4059
var parse_Axis = parsenoop;
4060
var parse_Tick = parsenoop;
4061
var parse_ValueRange = parsenoop;
4062
var parse_CatSerRange = parsenoop;
4063
var parse_AxisLine = parsenoop;
4064
var parse_CrtLink = parsenoop;
4065
var parse_DefaultText = parsenoop;
4066
var parse_Text = parsenoop;
4067
var parse_ObjectLink = parsenoop;
4068
var parse_Frame = parsenoop;
4069
var parse_Begin = parsenoop;
4070
var parse_End = parsenoop;
4071
var parse_PlotArea = parsenoop;
4072
var parse_Chart3d = parsenoop;
4073
var parse_PicF = parsenoop;
4074
var parse_DropBar = parsenoop;
4075
var parse_Radar = parsenoop;
4076
var parse_Surf = parsenoop;
4077
var parse_RadarArea = parsenoop;
4078
var parse_AxisParent = parsenoop;
4079
var parse_LegendException = parsenoop;
4080
var parse_ShtProps = parsenoop;
4081
var parse_SerToCrt = parsenoop;
4082
var parse_AxesUsed = parsenoop;
4083
var parse_SBaseRef = parsenoop;
4084
var parse_SerParent = parsenoop;
4085
var parse_SerAuxTrend = parsenoop;
4086
var parse_IFmtRecord = parsenoop;
4087
var parse_Pos = parsenoop;
4088
var parse_AlRuns = parsenoop;
4089
var parse_BRAI = parsenoop;
4090
var parse_SerAuxErrBar = parsenoop;
4091
var parse_SerFmt = parsenoop;
4092
var parse_Chart3DBarShape = parsenoop;
4093
var parse_Fbi = parsenoop;
4094
var parse_BopPop = parsenoop;
4095
var parse_AxcExt = parsenoop;
4096
var parse_Dat = parsenoop;
4097
var parse_PlotGrowth = parsenoop;
4098
var parse_SIIndex = parsenoop;
4099
var parse_GelFrame = parsenoop;
4100
var parse_BopPopCustom = parsenoop;
4101
var parse_Fbi2 = parsenoop;
4102
 
4103
/* --- Specific to versions before BIFF8 --- */
4104
function parse_BIFF5String(blob) {
4105
    var len = blob.read_shift(1);
4106
    return blob.read_shift(len, 'sbcs-cont');
4107
}
4108
 
4109
/* BIFF2_??? where ??? is the name from [XLS] */
4110
function parse_BIFF2STR(blob, length, opts) {
4111
    var cell = parse_XLSCell(blob, 6);
4112
    ++blob.l;
4113
    var str = parse_XLUnicodeString2(blob, length-7, opts);
4114
    cell.val = str;
4115
    return cell;
4116
}
4117
 
4118
function parse_BIFF2NUM(blob, length, opts) {
4119
    var cell = parse_XLSCell(blob, 6);
4120
    ++blob.l;
4121
    var num = parse_Xnum(blob, 8);
4122
    cell.val = num;
4123
    return cell;
4124
}
4125
 
4126
/* 18.4.1 charset to codepage mapping */
4127
var CS2CP = {
4128
    0:    1252, /* ANSI */
4129
    1:   65001, /* DEFAULT */
4130
    2:   65001, /* SYMBOL */
4131
    77:  10000, /* MAC */
4132
    128:   932, /* SHIFTJIS */
4133
    129:   949, /* HANGUL */
4134
    130:  1361, /* JOHAB */
4135
    134:   936, /* GB2312 */
4136
    136:   950, /* CHINESEBIG5 */
4137
    161:  1253, /* GREEK */
4138
    162:  1254, /* TURKISH */
4139
    163:  1258, /* VIETNAMESE */
4140
    177:  1255, /* HEBREW */
4141
    178:  1256, /* ARABIC */
4142
    186:  1257, /* BALTIC */
4143
    204:  1251, /* RUSSIAN */
4144
    222:   874, /* THAI */
4145
    238:  1250, /* EASTEUROPE */
4146
    255:  1252, /* OEM */
4147
    69:   6969  /* MISC */
4148
};
4149
 
4150
/* Parse a list of <r> tags */
4151
var parse_rs = (function parse_rs_factory() {
4152
    var tregex = matchtag("t"), rpregex = matchtag("rPr"), rregex = /<r>/g, rend = /<\/r>/, nlregex = /\r\n/g;
4153
    /* 18.4.7 rPr CT_RPrElt */
4154
    var parse_rpr = function parse_rpr(rpr, intro, outro) {
4155
        var font = {}, cp = 65001;
4156
        var m = rpr.match(tagregex), i = 0;
4157
        if(m) for(;i!=m.length; ++i) {
4158
            var y = parsexmltag(m[i]);
4159
            switch(y[0]) {
4160
                /* 18.8.12 condense CT_BooleanProperty */
4161
                /* ** not required . */
4162
                case '<condense': break;
4163
                /* 18.8.17 extend CT_BooleanProperty */
4164
                /* ** not required . */
4165
                case '<extend': break;
4166
                /* 18.8.36 shadow CT_BooleanProperty */
4167
                /* ** not required . */
4168
                case '<shadow':
4169
                    /* falls through */
4170
                case '<shadow/>': break;
4171
 
4172
                /* 18.4.1 charset CT_IntProperty TODO */
4173
                case '<charset':
4174
                    if(y.val == '1') break;
4175
                    cp = CS2CP[parseInt(y.val, 10)];
4176
                    break;
4177
 
4178
                /* 18.4.2 outline CT_BooleanProperty TODO */
4179
                case '<outline':
4180
                    /* falls through */
4181
                case '<outline/>': break;
4182
 
4183
                /* 18.4.5 rFont CT_FontName */
4184
                case '<rFont': font.name = y.val; break;
4185
 
4186
                /* 18.4.11 sz CT_FontSize */
4187
                case '<sz': font.sz = y.val; break;
4188
 
4189
                /* 18.4.10 strike CT_BooleanProperty */
4190
                case '<strike':
4191
                    if(!y.val) break;
4192
                    /* falls through */
4193
                case '<strike/>': font.strike = 1; break;
4194
                case '</strike>': break;
4195
 
4196
                /* 18.4.13 u CT_UnderlineProperty */
4197
                case '<u':
4198
                    if(!y.val) break;
4199
                    /* falls through */
4200
                case '<u/>': font.u = 1; break;
4201
                case '</u>': break;
4202
 
4203
                /* 18.8.2 b */
4204
                case '<b':
4205
                    if(!y.val) break;
4206
                    /* falls through */
4207
                case '<b/>': font.b = 1; break;
4208
                case '</b>': break;
4209
 
4210
                /* 18.8.26 i */
4211
                case '<i':
4212
                    if(!y.val) break;
4213
                    /* falls through */
4214
                case '<i/>': font.i = 1; break;
4215
                case '</i>': break;
4216
 
4217
                /* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */
4218
                case '<color':
4219
                    if(y.rgb) font.color = y.rgb.substr(2,6);
4220
                    break;
4221
 
4222
                /* 18.8.18 family ST_FontFamily */
4223
                case '<family': font.family = y.val; break;
4224
 
4225
                /* 18.4.14 vertAlign CT_VerticalAlignFontProperty TODO */
4226
                case '<vertAlign': break;
4227
 
4228
                /* 18.8.35 scheme CT_FontScheme TODO */
4229
                case '<scheme': break;
4230
 
4231
                default:
4232
                    if(y[0].charCodeAt(1) !== 47) throw 'Unrecognized rich format ' + y[0];
4233
            }
4234
        }
4235
        /* TODO: These should be generated styles, not inline */
4236
        var style = [];
4237
        if(font.b) style.push("font-weight: bold;");
4238
        if(font.i) style.push("font-style: italic;");
4239
        intro.push('<span style="' + style.join("") + '">');
4240
        outro.push("</span>");
4241
        return cp;
4242
    };
4243
 
4244
    /* 18.4.4 r CT_RElt */
4245
    function parse_r(r) {
4246
        var terms = [[],"",[]];
4247
        /* 18.4.12 t ST_Xstring */
4248
        var t = r.match(tregex), cp = 65001;
4249
        if(!isval(t)) return "";
4250
        terms[1] = t[1];
4251
 
4252
        var rpr = r.match(rpregex);
4253
        if(isval(rpr)) cp = parse_rpr(rpr[1], terms[0], terms[2]);
4254
 
4255
        return terms[0].join("") + terms[1].replace(nlregex,'<br/>') + terms[2].join("");
4256
    }
4257
    return function parse_rs(rs) {
4258
        return rs.replace(rregex,"").split(rend).map(parse_r).join("");
4259
    };
4260
})();
4261
 
4262
/* 18.4.8 si CT_Rst */
4263
var sitregex = /<t[^>]*>([^<]*)<\/t>/g, sirregex = /<r>/;
4264
function parse_si(x, opts) {
4265
    var html = opts ? opts.cellHTML : true;
4266
    var z = {};
4267
    if(!x) return null;
4268
    var y;
4269
    /* 18.4.12 t ST_Xstring (Plaintext String) */
4270
    if(x.charCodeAt(1) === 116) {
4271
        z.t = utf8read(unescapexml(x.substr(x.indexOf(">")+1).split(/<\/t>/)[0]));
4272
        z.r = x;
4273
        if(html) z.h = z.t;
4274
    }
4275
    /* 18.4.4 r CT_RElt (Rich Text Run) */
4276
    else if((y = x.match(sirregex))) {
4277
        z.r = x;
4278
        z.t = utf8read(unescapexml(x.match(sitregex).join("").replace(tagregex,"")));
4279
        if(html) z.h = parse_rs(x);
4280
    }
4281
    /* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
4282
    /* 18.4.6 rPh CT_PhoneticRun (TODO: needed for Asian support) */
4283
    return z;
4284
}
4285
 
4286
/* 18.4 Shared String Table */
4287
var sstr0 = /<sst([^>]*)>([\s\S]*)<\/sst>/;
4288
var sstr1 = /<(?:si|sstItem)>/g;
4289
var sstr2 = /<\/(?:si|sstItem)>/;
4290
function parse_sst_xml(data, opts) {
4291
    var s = [], ss;
4292
    /* 18.4.9 sst CT_Sst */
4293
    var sst = data.match(sstr0);
4294
    if(isval(sst)) {
4295
        ss = sst[2].replace(sstr1,"").split(sstr2);
4296
        for(var i = 0; i != ss.length; ++i) {
4297
            var o = parse_si(ss[i], opts);
4298
            if(o != null) s[s.length] = o;
4299
        }
4300
        sst = parsexmltag(sst[1]); s.Count = sst.count; s.Unique = sst.uniqueCount;
4301
    }
4302
    return s;
4303
}
4304
 
4305
RELS.SST = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
4306
var straywsregex = /^\s|\s$|[\t\n\r]/;
4307
function write_sst_xml(sst, opts) {
4308
    if(!opts.bookSST) return "";
4309
    var o = [XML_HEADER];
4310
    o[o.length] = (writextag('sst', null, {
4311
        xmlns: XMLNS.main[0],
4312
        count: sst.Count,
4313
        uniqueCount: sst.Unique
4314
    }));
4315
    for(var i = 0; i != sst.length; ++i) { if(sst[i] == null) continue;
4316
        var s = sst[i];
4317
        var sitag = "<si>";
4318
        if(s.r) sitag += s.r;
4319
        else {
4320
            sitag += "<t";
4321
            if(s.t.match(straywsregex)) sitag += ' xml:space="preserve"';
4322
            sitag += ">" + escapexml(s.t) + "</t>";
4323
        }
4324
        sitag += "</si>";
4325
        o[o.length] = (sitag);
4326
    }
4327
    if(o.length>2){ o[o.length] = ('</sst>'); o[1]=o[1].replace("/>",">"); }
4328
    return o.join("");
4329
}
4330
/* [MS-XLSB] 2.4.219 BrtBeginSst */
4331
function parse_BrtBeginSst(data, length) {
4332
    return [data.read_shift(4), data.read_shift(4)];
4333
}
4334
 
4335
/* [MS-XLSB] 2.1.7.45 Shared Strings */
4336
function parse_sst_bin(data, opts) {
4337
    var s = [];
4338
    var pass = false;
4339
    recordhopper(data, function hopper_sst(val, R, RT) {
4340
        switch(R.n) {
4341
            case 'BrtBeginSst': s.Count = val[0]; s.Unique = val[1]; break;
4342
            case 'BrtSSTItem': s.push(val); break;
4343
            case 'BrtEndSst': return true;
4344
            /* TODO: produce a test case with a future record */
4345
            case 'BrtFRTBegin': pass = true; break;
4346
            case 'BrtFRTEnd': pass = false; break;
4347
            default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
4348
        }
4349
    });
4350
    return s;
4351
}
4352
 
4353
function write_BrtBeginSst(sst, o) {
4354
    if(!o) o = new_buf(8);
4355
    o.write_shift(4, sst.Count);
4356
    o.write_shift(4, sst.Unique);
4357
    return o;
4358
}
4359
 
4360
var write_BrtSSTItem = write_RichStr;
4361
 
4362
function write_sst_bin(sst, opts) {
4363
    var ba = buf_array();
4364
    write_record(ba, "BrtBeginSst", write_BrtBeginSst(sst));
4365
    for(var i = 0; i < sst.length; ++i) write_record(ba, "BrtSSTItem", write_BrtSSTItem(sst[i]));
4366
    write_record(ba, "BrtEndSst");
4367
    return ba.end();
4368
}
4369
function _JS2ANSI(str) { if(typeof cptable !== 'undefined') return cptable.utils.encode(1252, str); return str.split("").map(function(x) { return x.charCodeAt(0); }); }
4370
 
4371
/* [MS-OFFCRYPTO] 2.1.4 Version */
4372
function parse_Version(blob, length) {
4373
    var o = {};
4374
    o.Major = blob.read_shift(2);
4375
    o.Minor = blob.read_shift(2);
4376
    return o;
4377
}
4378
/* [MS-OFFCRYPTO] 2.3.2 Encryption Header */
4379
function parse_EncryptionHeader(blob, length) {
4380
    var o = {};
4381
    o.Flags = blob.read_shift(4);
4382
 
4383
    // Check if SizeExtra is 0x00000000
4384
    var tmp = blob.read_shift(4);
4385
    if(tmp !== 0) throw 'Unrecognized SizeExtra: ' + tmp;
4386
 
4387
    o.AlgID = blob.read_shift(4);
4388
    switch(o.AlgID) {
4389
        case 0: case 0x6801: case 0x660E: case 0x660F: case 0x6610: break;
4390
        default: throw 'Unrecognized encryption algorithm: ' + o.AlgID;
4391
    }
4392
    parsenoop(blob, length-12);
4393
    return o;
4394
}
4395
 
4396
/* [MS-OFFCRYPTO] 2.3.3 Encryption Verifier */
4397
function parse_EncryptionVerifier(blob, length) {
4398
    return parsenoop(blob, length);
4399
}
4400
/* [MS-OFFCRYPTO] 2.3.5.1 RC4 CryptoAPI Encryption Header */
4401
function parse_RC4CryptoHeader(blob, length) {
4402
    var o = {};
4403
    var vers = o.EncryptionVersionInfo = parse_Version(blob, 4); length -= 4;
4404
    if(vers.Minor != 2) throw 'unrecognized minor version code: ' + vers.Minor;
4405
    if(vers.Major > 4 || vers.Major < 2) throw 'unrecognized major version code: ' + vers.Major;
4406
    o.Flags = blob.read_shift(4); length -= 4;
4407
    var sz = blob.read_shift(4); length -= 4;
4408
    o.EncryptionHeader = parse_EncryptionHeader(blob, sz); length -= sz;
4409
    o.EncryptionVerifier = parse_EncryptionVerifier(blob, length);
4410
    return o;
4411
}
4412
/* [MS-OFFCRYPTO] 2.3.6.1 RC4 Encryption Header */
4413
function parse_RC4Header(blob, length) {
4414
    var o = {};
4415
    var vers = o.EncryptionVersionInfo = parse_Version(blob, 4); length -= 4;
4416
    if(vers.Major != 1 || vers.Minor != 1) throw 'unrecognized version code ' + vers.Major + ' : ' + vers.Minor;
4417
    o.Salt = blob.read_shift(16);
4418
    o.EncryptedVerifier = blob.read_shift(16);
4419
    o.EncryptedVerifierHash = blob.read_shift(16);
4420
    return o;
4421
}
4422
 
4423
/* [MS-OFFCRYPTO] 2.3.7.1 Binary Document Password Verifier Derivation */
4424
function crypto_CreatePasswordVerifier_Method1(Password) {
4425
    var Verifier = 0x0000, PasswordArray;
4426
    var PasswordDecoded = _JS2ANSI(Password);
4427
    var len = PasswordDecoded.length + 1, i, PasswordByte;
4428
    var Intermediate1, Intermediate2, Intermediate3;
4429
    PasswordArray = new_raw_buf(len);
4430
    PasswordArray[0] = PasswordDecoded.length;
4431
    for(i = 1; i != len; ++i) PasswordArray[i] = PasswordDecoded[i-1];
4432
    for(i = len-1; i >= 0; --i) {
4433
        PasswordByte = PasswordArray[i];
4434
        Intermediate1 = ((Verifier & 0x4000) === 0x0000) ? 0 : 1;
4435
        Intermediate2 = (Verifier << 1) & 0x7FFF;
4436
        Intermediate3 = Intermediate1 | Intermediate2;
4437
        Verifier = Intermediate3 ^ PasswordByte;
4438
    }
4439
    return Verifier ^ 0xCE4B;
4440
}
4441
 
4442
/* [MS-OFFCRYPTO] 2.3.7.2 Binary Document XOR Array Initialization */
4443
var crypto_CreateXorArray_Method1 = (function() {
4444
    var PadArray = [0xBB, 0xFF, 0xFF, 0xBA, 0xFF, 0xFF, 0xB9, 0x80, 0x00, 0xBE, 0x0F, 0x00, 0xBF, 0x0F, 0x00];
4445
    var InitialCode = [0xE1F0, 0x1D0F, 0xCC9C, 0x84C0, 0x110C, 0x0E10, 0xF1CE, 0x313E, 0x1872, 0xE139, 0xD40F, 0x84F9, 0x280C, 0xA96A, 0x4EC3];
4446
    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];
4447
    var Ror = function(Byte) { return ((Byte/2) | (Byte*128)) & 0xFF; };
4448
    var XorRor = function(byte1, byte2) { return Ror(byte1 ^ byte2); };
4449
    var CreateXorKey_Method1 = function(Password) {
4450
        var XorKey = InitialCode[Password.length - 1];
4451
        var CurrentElement = 0x68;
4452
        for(var i = Password.length-1; i >= 0; --i) {
4453
            var Char = Password[i];
4454
            for(var j = 0; j != 7; ++j) {
4455
                if(Char & 0x40) XorKey ^= XorMatrix[CurrentElement];
4456
                Char *= 2; --CurrentElement;
4457
            }
4458
        }
4459
        return XorKey;
4460
    };
4461
    return function(password) {
4462
        var Password = _JS2ANSI(password);
4463
        var XorKey = CreateXorKey_Method1(Password);
4464
        var Index = Password.length;
4465
        var ObfuscationArray = new_raw_buf(16);
4466
        for(var i = 0; i != 16; ++i) ObfuscationArray[i] = 0x00;
4467
        var Temp, PasswordLastChar, PadIndex;
4468
        if((Index & 1) === 1) {
4469
            Temp = XorKey >> 8;
4470
            ObfuscationArray[Index] = XorRor(PadArray[0], Temp);
4471
            --Index;
4472
            Temp = XorKey & 0xFF;
4473
            PasswordLastChar = Password[Password.length - 1];
4474
            ObfuscationArray[Index] = XorRor(PasswordLastChar, Temp);
4475
        }
4476
        while(Index > 0) {
4477
            --Index;
4478
            Temp = XorKey >> 8;
4479
            ObfuscationArray[Index] = XorRor(Password[Index], Temp);
4480
            --Index;
4481
            Temp = XorKey & 0xFF;
4482
            ObfuscationArray[Index] = XorRor(Password[Index], Temp);
4483
        }
4484
        Index = 15;
4485
        PadIndex = 15 - Password.length;
4486
        while(PadIndex > 0) {
4487
            Temp = XorKey >> 8;
4488
            ObfuscationArray[Index] = XorRor(PadArray[PadIndex], Temp);
4489
            --Index;
4490
            --PadIndex;
4491
            Temp = XorKey & 0xFF;
4492
            ObfuscationArray[Index] = XorRor(Password[Index], Temp);
4493
            --Index;
4494
            --PadIndex;
4495
        }
4496
        return ObfuscationArray;
4497
    };
4498
})();
4499
 
4500
/* [MS-OFFCRYPTO] 2.3.7.3 Binary Document XOR Data Transformation Method 1 */
4501
var crypto_DecryptData_Method1 = function(password, Data, XorArrayIndex, XorArray, O) {
4502
    /* If XorArray is set, use it; if O is not set, make changes in-place */
4503
    if(!O) O = Data;
4504
    if(!XorArray) XorArray = crypto_CreateXorArray_Method1(password);
4505
    var Index, Value;
4506
    for(Index = 0; Index != Data.length; ++Index) {
4507
        Value = Data[Index];
4508
        Value ^= XorArray[XorArrayIndex];
4509
        Value = ((Value>>5) | (Value<<3)) & 0xFF;
4510
        O[Index] = Value;
4511
        ++XorArrayIndex;
4512
    }
4513
    return [O, XorArrayIndex, XorArray];
4514
};
4515
 
4516
var crypto_MakeXorDecryptor = function(password) {
4517
    var XorArrayIndex = 0, XorArray = crypto_CreateXorArray_Method1(password);
4518
    return function(Data) {
4519
        var O = crypto_DecryptData_Method1(null, Data, XorArrayIndex, XorArray);
4520
        XorArrayIndex = O[1];
4521
        return O[0];
4522
    };
4523
};
4524
 
4525
/* 2.5.343 */
4526
function parse_XORObfuscation(blob, length, opts, out) {
4527
    var o = { key: parseuint16(blob), verificationBytes: parseuint16(blob) };
4528
    if(opts.password) o.verifier = crypto_CreatePasswordVerifier_Method1(opts.password);
4529
    out.valid = o.verificationBytes === o.verifier;
4530
    if(out.valid) out.insitu_decrypt = crypto_MakeXorDecryptor(opts.password);
4531
    return o;
4532
}
4533
 
4534
/* 2.4.117 */
4535
function parse_FilePassHeader(blob, length, oo) {
4536
    var o = oo || {}; o.Info = blob.read_shift(2); blob.l -= 2;
4537
    if(o.Info === 1) o.Data = parse_RC4Header(blob, length);
4538
    else o.Data = parse_RC4CryptoHeader(blob, length);
4539
    return o;
4540
}
4541
function parse_FilePass(blob, length, opts) {
4542
    var o = { Type: blob.read_shift(2) }; /* wEncryptionType */
4543
    if(o.Type) parse_FilePassHeader(blob, length-2, o);
4544
    else parse_XORObfuscation(blob, length-2, opts, o);
4545
    return o;
4546
}
4547
 
4548
 
4549
function hex2RGB(h) {
4550
    var o = h.substr(h[0]==="#"?1:0,6);
4551
    return [parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16)];
4552
}
4553
function rgb2Hex(rgb) {
4554
    for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);
4555
    return o.toString(16).toUpperCase().substr(1);
4556
}
4557
 
4558
function rgb2HSL(rgb) {
4559
    var R = rgb[0]/255, G = rgb[1]/255, B=rgb[2]/255;
4560
    var M = Math.max(R, G, B), m = Math.min(R, G, B), C = M - m;
4561
    if(C === 0) return [0, 0, R];
4562
 
4563
    var H6 = 0, S = 0, L2 = (M + m);
4564
    S = C / (L2 > 1 ? 2 - L2 : L2);
4565
    switch(M){
4566
        case R: H6 = ((G - B) / C + 6)%6; break;
4567
        case G: H6 = ((B - R) / C + 2); break;
4568
        case B: H6 = ((R - G) / C + 4); break;
4569
    }
4570
    return [H6 / 6, S, L2 / 2];
4571
}
4572
 
4573
function hsl2RGB(hsl){
4574
    var H = hsl[0], S = hsl[1], L = hsl[2];
4575
    var C = S * 2 * (L < 0.5 ? L : 1 - L), m = L - C/2;
4576
    var rgb = [m,m,m], h6 = 6*H;
4577
 
4578
    var X;
4579
    if(S !== 0) switch(h6|0) {
4580
        case 0: case 6: X = C * h6; rgb[0] += C; rgb[1] += X; break;
4581
        case 1: X = C * (2 - h6);   rgb[0] += X; rgb[1] += C; break;
4582
        case 2: X = C * (h6 - 2);   rgb[1] += C; rgb[2] += X; break;
4583
        case 3: X = C * (4 - h6);   rgb[1] += X; rgb[2] += C; break;
4584
        case 4: X = C * (h6 - 4);   rgb[2] += C; rgb[0] += X; break;
4585
        case 5: X = C * (6 - h6);   rgb[2] += X; rgb[0] += C; break;
4586
    }
4587
    for(var i = 0; i != 3; ++i) rgb[i] = Math.round(rgb[i]*255);
4588
    return rgb;
4589
}
4590
 
4591
/* 18.8.3 bgColor tint algorithm */
4592
function rgb_tint(hex, tint) {
4593
    if(tint === 0) return hex;
4594
    var hsl = rgb2HSL(hex2RGB(hex));
4595
    if (tint < 0) hsl[2] = hsl[2] * (1 + tint);
4596
    else hsl[2] = 1 - (1 - hsl[2]) * (1 - tint);
4597
    return rgb2Hex(hsl2RGB(hsl));
4598
}
4599
 
4600
/* 18.3.1.13 width calculations */
4601
var DEF_MDW = 7, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
4602
function width2px(width) { return (( width + ((128/MDW)|0)/256 )* MDW )|0; }
4603
function px2char(px) { return (((px - 5)/MDW * 100 + 0.5)|0)/100; }
4604
function char2width(chr) { return (((chr * MDW + 5)/MDW*256)|0)/256; }
4605
function cycle_width(collw) { return char2width(px2char(width2px(collw))); }
4606
function find_mdw(collw, coll) {
4607
    if(cycle_width(collw) != collw) {
4608
        for(MDW=DEF_MDW; MDW>MIN_MDW; --MDW) if(cycle_width(collw) === collw) break;
4609
        if(MDW === MIN_MDW) for(MDW=DEF_MDW+1; MDW<MAX_MDW; ++MDW) if(cycle_width(collw) === collw) break;
4610
        if(MDW === MAX_MDW) MDW = DEF_MDW;
4611
    }
4612
}
4613
 
4614
/* [MS-EXSPXML3] 2.4.54 ST_enmPattern */
4615
var XLMLPatternTypeMap = {
4616
    "None": "none",
4617
    "Solid": "solid",
4618
    "Gray50": "mediumGray",
4619
    "Gray75": "darkGray",
4620
    "Gray25": "lightGray",
4621
    "HorzStripe": "darkHorizontal",
4622
    "VertStripe": "darkVertical",
4623
    "ReverseDiagStripe": "darkDown",
4624
    "DiagStripe": "darkUp",
4625
    "DiagCross": "darkGrid",
4626
    "ThickDiagCross": "darkTrellis",
4627
    "ThinHorzStripe": "lightHorizontal",
4628
    "ThinVertStripe": "lightVertical",
4629
    "ThinReverseDiagStripe": "lightDown",
4630
    "ThinHorzCross": "lightGrid"
4631
};
4632
 
4633
var styles = {}; // shared styles
4634
 
4635
var themes = {}; // shared themes
4636
 
4637
/* 18.8.21 fills CT_Fills */
4638
function parse_fills(t, opts) {
4639
    styles.Fills = [];
4640
    var fill = {};
4641
    t[0].match(tagregex).forEach(function(x) {
4642
        var y = parsexmltag(x);
4643
        switch(y[0]) {
4644
            case '<fills': case '<fills>': case '</fills>': break;
4645
 
4646
            /* 18.8.20 fill CT_Fill */
4647
            case '<fill>': break;
4648
            case '</fill>': styles.Fills.push(fill); fill = {}; break;
4649
 
4650
            /* 18.8.32 patternFill CT_PatternFill */
4651
            case '<patternFill':
4652
                if(y.patternType) fill.patternType = y.patternType;
4653
                break;
4654
            case '<patternFill/>': case '</patternFill>': break;
4655
 
4656
            /* 18.8.3 bgColor CT_Color */
4657
            case '<bgColor':
4658
                if(!fill.bgColor) fill.bgColor = {};
4659
                if(y.indexed) fill.bgColor.indexed = parseInt(y.indexed, 10);
4660
                if(y.theme) fill.bgColor.theme = parseInt(y.theme, 10);
4661
                if(y.tint) fill.bgColor.tint = parseFloat(y.tint);
4662
                /* Excel uses ARGB strings */
4663
                if(y.rgb) fill.bgColor.rgb = y.rgb.substring(y.rgb.length - 6);
4664
                break;
4665
            case '<bgColor/>': case '</bgColor>': break;
4666
 
4667
            /* 18.8.19 fgColor CT_Color */
4668
            case '<fgColor':
4669
                if(!fill.fgColor) fill.fgColor = {};
4670
                if(y.theme) fill.fgColor.theme = parseInt(y.theme, 10);
4671
                if(y.tint) fill.fgColor.tint = parseFloat(y.tint);
4672
                /* Excel uses ARGB strings */
4673
                if(y.rgb) fill.fgColor.rgb = y.rgb.substring(y.rgb.length - 6);
4674
                break;
4675
            case '<fgColor/>': case '</fgColor>': break;
4676
 
4677
            default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in fills';
4678
        }
4679
    });
4680
}
4681
 
4682
/* 18.8.31 numFmts CT_NumFmts */
4683
function parse_numFmts(t, opts) {
4684
    styles.NumberFmt = [];
4685
    var k = keys(SSF._table);
4686
    for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
4687
    var m = t[0].match(tagregex);
4688
    for(i=0; i < m.length; ++i) {
4689
        var y = parsexmltag(m[i]);
4690
        switch(y[0]) {
4691
            case '<numFmts': case '</numFmts>': case '<numFmts/>': case '<numFmts>': break;
4692
            case '<numFmt': {
4693
                var f=unescapexml(utf8read(y.formatCode)), j=parseInt(y.numFmtId,10);
4694
                styles.NumberFmt[j] = f; if(j>0) SSF.load(f,j);
4695
            } break;
4696
            default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in numFmts';
4697
        }
4698
    }
4699
}
4700
 
4701
function write_numFmts(NF, opts) {
4702
    var o = ["<numFmts>"];
4703
    [[5,8],[23,26],[41,44],[63,66],[164,392]].forEach(function(r) {
4704
        for(var i = r[0]; i <= r[1]; ++i) if(NF[i] !== undefined) o[o.length] = (writextag('numFmt',null,{numFmtId:i,formatCode:escapexml(NF[i])}));
4705
    });
4706
    if(o.length === 1) return "";
4707
    o[o.length] = ("</numFmts>");
4708
    o[0] = writextag('numFmts', null, { count:o.length-2 }).replace("/>", ">");
4709
    return o.join("");
4710
}
4711
 
4712
/* 18.8.10 cellXfs CT_CellXfs */
4713
function parse_cellXfs(t, opts) {
4714
    styles.CellXf = [];
4715
    t[0].match(tagregex).forEach(function(x) {
4716
        var y = parsexmltag(x);
4717
        switch(y[0]) {
4718
            case '<cellXfs': case '<cellXfs>': case '<cellXfs/>': case '</cellXfs>': break;
4719
 
4720
            /* 18.8.45 xf CT_Xf */
4721
            case '<xf': delete y[0];
4722
                if(y.numFmtId) y.numFmtId = parseInt(y.numFmtId, 10);
4723
                if(y.fillId) y.fillId = parseInt(y.fillId, 10);
4724
                styles.CellXf.push(y); break;
4725
            case '</xf>': break;
4726
 
4727
            /* 18.8.1 alignment CT_CellAlignment */
4728
            case '<alignment': case '<alignment/>': break;
4729
 
4730
            /* 18.8.33 protection CT_CellProtection */
4731
            case '<protection': case '</protection>': case '<protection/>': break;
4732
 
4733
            case '<extLst': case '</extLst>': break;
4734
            case '<ext': break;
4735
            default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in cellXfs';
4736
        }
4737
    });
4738
}
4739
 
4740
function write_cellXfs(cellXfs) {
4741
    var o = [];
4742
    o[o.length] = (writextag('cellXfs',null));
4743
    cellXfs.forEach(function(c) { o[o.length] = (writextag('xf', null, c)); });
4744
    o[o.length] = ("</cellXfs>");
4745
    if(o.length === 2) return "";
4746
    o[0] = writextag('cellXfs',null, {count:o.length-2}).replace("/>",">");
4747
    return o.join("");
4748
}
4749
 
4750
/* 18.8 Styles CT_Stylesheet*/
4751
var parse_sty_xml= (function make_pstyx() {
4752
var numFmtRegex = /<numFmts([^>]*)>.*<\/numFmts>/;
4753
var cellXfRegex = /<cellXfs([^>]*)>.*<\/cellXfs>/;
4754
var fillsRegex = /<fills([^>]*)>.*<\/fills>/;
4755
 
4756
return function parse_sty_xml(data, opts) {
4757
    /* 18.8.39 styleSheet CT_Stylesheet */
4758
    var t;
4759
 
4760
    /* numFmts CT_NumFmts ? */
4761
    if((t=data.match(numFmtRegex))) parse_numFmts(t, opts);
4762
 
4763
    /* fonts CT_Fonts ? */
4764
    /*if((t=data.match(/<fonts([^>]*)>.*<\/fonts>/))) parse_fonts(t, opts);*/
4765
 
4766
    /* fills CT_Fills */
4767
    if((t=data.match(fillsRegex))) parse_fills(t, opts);
4768
 
4769
    /* borders CT_Borders ? */
4770
    /* cellStyleXfs CT_CellStyleXfs ? */
4771
 
4772
    /* cellXfs CT_CellXfs ? */
4773
    if((t=data.match(cellXfRegex))) parse_cellXfs(t, opts);
4774
 
4775
    /* dxfs CT_Dxfs ? */
4776
    /* tableStyles CT_TableStyles ? */
4777
    /* colors CT_Colors ? */
4778
    /* extLst CT_ExtensionList ? */
4779
 
4780
    return styles;
4781
};
4782
})();
4783
 
4784
var STYLES_XML_ROOT = writextag('styleSheet', null, {
4785
    'xmlns': XMLNS.main[0],
4786
    'xmlns:vt': XMLNS.vt
4787
});
4788
 
4789
RELS.STY = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
4790
 
4791
function write_sty_xml(wb, opts) {
4792
    var o = [XML_HEADER, STYLES_XML_ROOT], w;
4793
    if((w = write_numFmts(wb.SSF)) != null) o[o.length] = w;
4794
    o[o.length] = ('<fonts count="1"><font><sz val="12"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font></fonts>');
4795
    o[o.length] = ('<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
4796
    o[o.length] = ('<borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>');
4797
    o[o.length] = ('<cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>');
4798
    if((w = write_cellXfs(opts.cellXfs))) o[o.length] = (w);
4799
    o[o.length] = ('<cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles>');
4800
    o[o.length] = ('<dxfs count="0"/>');
4801
    o[o.length] = ('<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleMedium4"/>');
4802
 
4803
    if(o.length>2){ o[o.length] = ('</styleSheet>'); o[1]=o[1].replace("/>",">"); }
4804
    return o.join("");
4805
}
4806
/* [MS-XLSB] 2.4.651 BrtFmt */
4807
function parse_BrtFmt(data, length) {
4808
    var ifmt = data.read_shift(2);
4809
    var stFmtCode = parse_XLWideString(data,length-2);
4810
    return [ifmt, stFmtCode];
4811
}
4812
 
4813
/* [MS-XLSB] 2.4.653 BrtFont TODO */
4814
function parse_BrtFont(data, length) {
4815
    var out = {flags:{}};
4816
    out.dyHeight = data.read_shift(2);
4817
    out.grbit = parse_FontFlags(data, 2);
4818
    out.bls = data.read_shift(2);
4819
    out.sss = data.read_shift(2);
4820
    out.uls = data.read_shift(1);
4821
    out.bFamily = data.read_shift(1);
4822
    out.bCharSet = data.read_shift(1);
4823
    data.l++;
4824
    out.brtColor = parse_BrtColor(data, 8);
4825
    out.bFontScheme = data.read_shift(1);
4826
    out.name = parse_XLWideString(data, length - 21);
4827
 
4828
    out.flags.Bold = out.bls === 0x02BC;
4829
    out.flags.Italic = out.grbit.fItalic;
4830
    out.flags.Strikeout = out.grbit.fStrikeout;
4831
    out.flags.Outline = out.grbit.fOutline;
4832
    out.flags.Shadow = out.grbit.fShadow;
4833
    out.flags.Condense = out.grbit.fCondense;
4834
    out.flags.Extend = out.grbit.fExtend;
4835
    out.flags.Sub = out.sss & 0x2;
4836
    out.flags.Sup = out.sss & 0x1;
4837
    return out;
4838
}
4839
 
4840
/* [MS-XLSB] 2.4.816 BrtXF */
4841
function parse_BrtXF(data, length) {
4842
    var ixfeParent = data.read_shift(2);
4843
    var ifmt = data.read_shift(2);
4844
    parsenoop(data, length-4);
4845
    return {ixfe:ixfeParent, ifmt:ifmt };
4846
}
4847
 
4848
/* [MS-XLSB] 2.1.7.50 Styles */
4849
function parse_sty_bin(data, opts) {
4850
    styles.NumberFmt = [];
4851
    for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y];
4852
 
4853
    styles.CellXf = [];
4854
    var state = ""; /* TODO: this should be a stack */
4855
    var pass = false;
4856
    recordhopper(data, function hopper_sty(val, R, RT) {
4857
        switch(R.n) {
4858
            case 'BrtFmt':
4859
                styles.NumberFmt[val[0]] = val[1]; SSF.load(val[1], val[0]);
4860
                break;
4861
            case 'BrtFont': break; /* TODO */
4862
            case 'BrtKnownFonts': break; /* TODO */
4863
            case 'BrtFill': break; /* TODO */
4864
            case 'BrtBorder': break; /* TODO */
4865
            case 'BrtXF':
4866
                if(state === "CELLXFS") {
4867
                    styles.CellXf.push(val);
4868
                }
4869
                break; /* TODO */
4870
            case 'BrtStyle': break; /* TODO */
4871
            case 'BrtDXF': break; /* TODO */
4872
            case 'BrtMRUColor': break; /* TODO */
4873
            case 'BrtIndexedColor': break; /* TODO */
4874
            case 'BrtBeginStyleSheet': break;
4875
            case 'BrtEndStyleSheet': break;
4876
            case 'BrtBeginTableStyle': break;
4877
            case 'BrtTableStyleElement': break;
4878
            case 'BrtEndTableStyle': break;
4879
            case 'BrtBeginFmts': state = "FMTS"; break;
4880
            case 'BrtEndFmts': state = ""; break;
4881
            case 'BrtBeginFonts': state = "FONTS"; break;
4882
            case 'BrtEndFonts': state = ""; break;
4883
            case 'BrtACBegin': state = "ACFONTS"; break;
4884
            case 'BrtACEnd': state = ""; break;
4885
            case 'BrtBeginFills': state = "FILLS"; break;
4886
            case 'BrtEndFills': state = ""; break;
4887
            case 'BrtBeginBorders': state = "BORDERS"; break;
4888
            case 'BrtEndBorders': state = ""; break;
4889
            case 'BrtBeginCellStyleXFs': state = "CELLSTYLEXFS"; break;
4890
            case 'BrtEndCellStyleXFs': state = ""; break;
4891
            case 'BrtBeginCellXFs': state = "CELLXFS"; break;
4892
            case 'BrtEndCellXFs': state = ""; break;
4893
            case 'BrtBeginStyles': state = "STYLES"; break;
4894
            case 'BrtEndStyles': state = ""; break;
4895
            case 'BrtBeginDXFs': state = "DXFS"; break;
4896
            case 'BrtEndDXFs': state = ""; break;
4897
            case 'BrtBeginTableStyles': state = "TABLESTYLES"; break;
4898
            case 'BrtEndTableStyles': state = ""; break;
4899
            case 'BrtBeginColorPalette': state = "COLORPALETTE"; break;
4900
            case 'BrtEndColorPalette': state = ""; break;
4901
            case 'BrtBeginIndexedColors': state = "INDEXEDCOLORS"; break;
4902
            case 'BrtEndIndexedColors': state = ""; break;
4903
            case 'BrtBeginMRUColors': state = "MRUCOLORS"; break;
4904
            case 'BrtEndMRUColors': state = ""; break;
4905
            case 'BrtFRTBegin': pass = true; break;
4906
            case 'BrtFRTEnd': pass = false; break;
4907
            case 'BrtBeginStyleSheetExt14': break;
4908
            case 'BrtBeginSlicerStyles': break;
4909
            case 'BrtEndSlicerStyles': break;
4910
            case 'BrtBeginTimelineStylesheetExt15': break;
4911
            case 'BrtEndTimelineStylesheetExt15': break;
4912
            case 'BrtBeginTimelineStyles': break;
4913
            case 'BrtEndTimelineStyles': break;
4914
            case 'BrtEndStyleSheetExt14': break;
4915
            default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
4916
        }
4917
    });
4918
    return styles;
4919
}
4920
 
4921
/* [MS-XLSB] 2.1.7.50 Styles */
4922
function write_sty_bin(data, opts) {
4923
    var ba = buf_array();
4924
    write_record(ba, "BrtBeginStyleSheet");
4925
    /* [FMTS] */
4926
    /* [FONTS] */
4927
    /* [FILLS] */
4928
    /* [BORDERS] */
4929
    /* CELLSTYLEXFS */
4930
    /* CELLXFS*/
4931
    /* STYLES */
4932
    /* DXFS */
4933
    /* TABLESTYLES */
4934
    /* [COLORPALETTE] */
4935
    /* FRTSTYLESHEET*/
4936
    write_record(ba, "BrtEndStyleSheet");
4937
    return ba.end();
4938
}
4939
RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
4940
 
4941
/* 20.1.6.2 clrScheme CT_ColorScheme */
4942
function parse_clrScheme(t, opts) {
4943
    themes.themeElements.clrScheme = [];
4944
    var color = {};
4945
    t[0].match(tagregex).forEach(function(x) {
4946
        var y = parsexmltag(x);
4947
        switch(y[0]) {
4948
            case '<a:clrScheme': case '</a:clrScheme>': break;
4949
 
4950
            /* 20.1.2.3.32 srgbClr CT_SRgbColor */
4951
            case '<a:srgbClr': color.rgb = y.val; break;
4952
 
4953
            /* 20.1.2.3.33 sysClr CT_SystemColor */
4954
            case '<a:sysClr': color.rgb = y.lastClr; break;
4955
 
4956
            /* 20.1.4.1.9 dk1 (Dark 1) */
4957
            case '<a:dk1>':
4958
            case '</a:dk1>':
4959
            /* 20.1.4.1.10 dk2 (Dark 2) */
4960
            case '<a:dk2>':
4961
            case '</a:dk2>':
4962
            /* 20.1.4.1.22 lt1 (Light 1) */
4963
            case '<a:lt1>':
4964
            case '</a:lt1>':
4965
            /* 20.1.4.1.23 lt2 (Light 2) */
4966
            case '<a:lt2>':
4967
            case '</a:lt2>':
4968
            /* 20.1.4.1.1 accent1 (Accent 1) */
4969
            case '<a:accent1>':
4970
            case '</a:accent1>':
4971
            /* 20.1.4.1.2 accent2 (Accent 2) */
4972
            case '<a:accent2>':
4973
            case '</a:accent2>':
4974
            /* 20.1.4.1.3 accent3 (Accent 3) */
4975
            case '<a:accent3>':
4976
            case '</a:accent3>':
4977
            /* 20.1.4.1.4 accent4 (Accent 4) */
4978
            case '<a:accent4>':
4979
            case '</a:accent4>':
4980
            /* 20.1.4.1.5 accent5 (Accent 5) */
4981
            case '<a:accent5>':
4982
            case '</a:accent5>':
4983
            /* 20.1.4.1.6 accent6 (Accent 6) */
4984
            case '<a:accent6>':
4985
            case '</a:accent6>':
4986
            /* 20.1.4.1.19 hlink (Hyperlink) */
4987
            case '<a:hlink>':
4988
            case '</a:hlink>':
4989
            /* 20.1.4.1.15 folHlink (Followed Hyperlink) */
4990
            case '<a:folHlink>':
4991
            case '</a:folHlink>':
4992
                if (y[0][1] === '/') {
4993
                    themes.themeElements.clrScheme.push(color);
4994
                    color = {};
4995
                } else {
4996
                    color.name = y[0].substring(3, y[0].length - 1);
4997
                }
4998
                break;
4999
 
5000
            default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in clrScheme';
5001
        }
5002
    });
5003
}
5004
 
5005
/* 20.1.4.1.18 fontScheme CT_FontScheme */
5006
function parse_fontScheme(t, opts) { }
5007
 
5008
/* 20.1.4.1.15 fmtScheme CT_StyleMatrix */
5009
function parse_fmtScheme(t, opts) { }
5010
 
5011
var clrsregex = /<a:clrScheme([^>]*)>[^\u2603]*<\/a:clrScheme>/;
5012
var fntsregex = /<a:fontScheme([^>]*)>[^\u2603]*<\/a:fontScheme>/;
5013
var fmtsregex = /<a:fmtScheme([^>]*)>[^\u2603]*<\/a:fmtScheme>/;
5014
 
5015
/* 20.1.6.10 themeElements CT_BaseStyles */
5016
function parse_themeElements(data, opts) {
5017
    themes.themeElements = {};
5018
 
5019
    var t;
5020
 
5021
    [
5022
        /* clrScheme CT_ColorScheme */
5023
        ['clrScheme', clrsregex, parse_clrScheme],
5024
        /* fontScheme CT_FontScheme */
5025
        ['fontScheme', fntsregex, parse_fontScheme],
5026
        /* fmtScheme CT_StyleMatrix */
5027
        ['fmtScheme', fmtsregex, parse_fmtScheme]
5028
    ].forEach(function(m) {
5029
        if(!(t=data.match(m[1]))) throw m[0] + ' not found in themeElements';
5030
        m[2](t, opts);
5031
    });
5032
}
5033
 
5034
var themeltregex = /<a:themeElements([^>]*)>[^\u2603]*<\/a:themeElements>/;
5035
 
5036
/* 14.2.7 Theme Part */
5037
function parse_theme_xml(data, opts) {
5038
    /* 20.1.6.9 theme CT_OfficeStyleSheet */
5039
    if(!data || data.length === 0) return themes;
5040
 
5041
    var t;
5042
 
5043
    /* themeElements CT_BaseStyles */
5044
    if(!(t=data.match(themeltregex))) throw 'themeElements not found in theme';
5045
    parse_themeElements(t[0], opts);
5046
 
5047
    return themes;
5048
}
5049
 
5050
function write_theme() { return '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme"><a:themeElements><a:clrScheme name="Office"><a:dk1><a:sysClr val="windowText" lastClr="000000"/></a:dk1><a:lt1><a:sysClr val="window" lastClr="FFFFFF"/></a:lt1><a:dk2><a:srgbClr val="1F497D"/></a:dk2><a:lt2><a:srgbClr val="EEECE1"/></a:lt2><a:accent1><a:srgbClr val="4F81BD"/></a:accent1><a:accent2><a:srgbClr val="C0504D"/></a:accent2><a:accent3><a:srgbClr val="9BBB59"/></a:accent3><a:accent4><a:srgbClr val="8064A2"/></a:accent4><a:accent5><a:srgbClr val="4BACC6"/></a:accent5><a:accent6><a:srgbClr val="F79646"/></a:accent6><a:hlink><a:srgbClr val="0000FF"/></a:hlink><a:folHlink><a:srgbClr val="800080"/></a:folHlink></a:clrScheme><a:fontScheme name="Office"><a:majorFont><a:latin typeface="Cambria"/><a:ea typeface=""/><a:cs typeface=""/><a:font script="Jpan" typeface="MS Pゴシック"/><a:font script="Hang" typeface="맑은 고딕"/><a:font script="Hans" typeface="宋体"/><a:font script="Hant" typeface="新細明體"/><a:font script="Arab" typeface="Times New Roman"/><a:font script="Hebr" typeface="Times New Roman"/><a:font script="Thai" typeface="Tahoma"/><a:font script="Ethi" typeface="Nyala"/><a:font script="Beng" typeface="Vrinda"/><a:font script="Gujr" typeface="Shruti"/><a:font script="Khmr" typeface="MoolBoran"/><a:font script="Knda" typeface="Tunga"/><a:font script="Guru" typeface="Raavi"/><a:font script="Cans" typeface="Euphemia"/><a:font script="Cher" typeface="Plantagenet Cherokee"/><a:font script="Yiii" typeface="Microsoft Yi Baiti"/><a:font script="Tibt" typeface="Microsoft Himalaya"/><a:font script="Thaa" typeface="MV Boli"/><a:font script="Deva" typeface="Mangal"/><a:font script="Telu" typeface="Gautami"/><a:font script="Taml" typeface="Latha"/><a:font script="Syrc" typeface="Estrangelo Edessa"/><a:font script="Orya" typeface="Kalinga"/><a:font script="Mlym" typeface="Kartika"/><a:font script="Laoo" typeface="DokChampa"/><a:font script="Sinh" typeface="Iskoola Pota"/><a:font script="Mong" typeface="Mongolian Baiti"/><a:font script="Viet" typeface="Times New Roman"/><a:font script="Uigh" typeface="Microsoft Uighur"/><a:font script="Geor" typeface="Sylfaen"/></a:majorFont><a:minorFont><a:latin typeface="Calibri"/><a:ea typeface=""/><a:cs typeface=""/><a:font script="Jpan" typeface="MS Pゴシック"/><a:font script="Hang" typeface="맑은 고딕"/><a:font script="Hans" typeface="宋体"/><a:font script="Hant" typeface="新細明體"/><a:font script="Arab" typeface="Arial"/><a:font script="Hebr" typeface="Arial"/><a:font script="Thai" typeface="Tahoma"/><a:font script="Ethi" typeface="Nyala"/><a:font script="Beng" typeface="Vrinda"/><a:font script="Gujr" typeface="Shruti"/><a:font script="Khmr" typeface="DaunPenh"/><a:font script="Knda" typeface="Tunga"/><a:font script="Guru" typeface="Raavi"/><a:font script="Cans" typeface="Euphemia"/><a:font script="Cher" typeface="Plantagenet Cherokee"/><a:font script="Yiii" typeface="Microsoft Yi Baiti"/><a:font script="Tibt" typeface="Microsoft Himalaya"/><a:font script="Thaa" typeface="MV Boli"/><a:font script="Deva" typeface="Mangal"/><a:font script="Telu" typeface="Gautami"/><a:font script="Taml" typeface="Latha"/><a:font script="Syrc" typeface="Estrangelo Edessa"/><a:font script="Orya" typeface="Kalinga"/><a:font script="Mlym" typeface="Kartika"/><a:font script="Laoo" typeface="DokChampa"/><a:font script="Sinh" typeface="Iskoola Pota"/><a:font script="Mong" typeface="Mongolian Baiti"/><a:font script="Viet" typeface="Arial"/><a:font script="Uigh" typeface="Microsoft Uighur"/><a:font script="Geor" typeface="Sylfaen"/></a:minorFont></a:fontScheme><a:fmtScheme name="Office"><a:fillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="50000"/><a:satMod val="300000"/></a:schemeClr></a:gs><a:gs pos="35000"><a:schemeClr val="phClr"><a:tint val="37000"/><a:satMod val="300000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="15000"/><a:satMod val="350000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="16200000" scaled="1"/></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="100000"/><a:shade val="100000"/><a:satMod val="130000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="50000"/><a:shade val="100000"/><a:satMod val="350000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="16200000" scaled="0"/></a:gradFill></a:fillStyleLst><a:lnStyleLst><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><a:ln w="25400" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/></a:ln><a:ln w="38100" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/></a:ln></a:lnStyleLst><a:effectStyleLst><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="20000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="38000"/></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000"/></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000"/></a:srgbClr></a:outerShdw></a:effectLst><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><a:sp3d><a:bevelT w="63500" h="25400"/></a:sp3d></a:effectStyle></a:effectStyleLst><a:bgFillStyleLst><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="40000"/><a:satMod val="350000"/></a:schemeClr></a:gs><a:gs pos="40000"><a:schemeClr val="phClr"><a:tint val="45000"/><a:shade val="99000"/><a:satMod val="350000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="20000"/><a:satMod val="255000"/></a:schemeClr></a:gs></a:gsLst><a:path path="circle"><a:fillToRect l="50000" t="-80000" r="50000" b="180000"/></a:path></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="80000"/><a:satMod val="300000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="30000"/><a:satMod val="200000"/></a:schemeClr></a:gs></a:gsLst><a:path path="circle"><a:fillToRect l="50000" t="50000" r="50000" b="50000"/></a:path></a:gradFill></a:bgFillStyleLst></a:fmtScheme></a:themeElements><a:objectDefaults><a:spDef><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></a:spDef><a:lnDef><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></a:lnDef></a:objectDefaults><a:extraClrSchemeLst/></a:theme>'; }
5051
/* [MS-XLS] 2.4.326 TODO: payload is a zip file */
5052
function parse_Theme(blob, length) {
5053
    var dwThemeVersion = blob.read_shift(4);
5054
    if(dwThemeVersion === 124226) return;
5055
    blob.l += length-4;
5056
}
5057
 
5058
/* 2.5.49 */
5059
function parse_ColorTheme(blob, length) { return blob.read_shift(4); }
5060
 
5061
/* 2.5.155 */
5062
function parse_FullColorExt(blob, length) {
5063
    var o = {};
5064
    o.xclrType = blob.read_shift(2);
5065
    o.nTintShade = blob.read_shift(2);
5066
    switch(o.xclrType) {
5067
        case 0: blob.l += 4; break;
5068
        case 1: o.xclrValue = parse_IcvXF(blob, 4); break;
5069
        case 2: o.xclrValue = parse_LongRGBA(blob, 4); break;
5070
        case 3: o.xclrValue = parse_ColorTheme(blob, 4); break;
5071
        case 4: blob.l += 4; break;
5072
    }
5073
    blob.l += 8;
5074
    return o;
5075
}
5076
 
5077
/* 2.5.164 TODO: read 7 bits*/
5078
function parse_IcvXF(blob, length) {
5079
    return parsenoop(blob, length);
5080
}
5081
 
5082
/* 2.5.280 */
5083
function parse_XFExtGradient(blob, length) {
5084
    return parsenoop(blob, length);
5085
}
5086
 
5087
/* 2.5.108 */
5088
function parse_ExtProp(blob, length) {
5089
    var extType = blob.read_shift(2);
5090
    var cb = blob.read_shift(2);
5091
    var o = [extType];
5092
    switch(extType) {
5093
        case 0x04: case 0x05: case 0x07: case 0x08:
5094
        case 0x09: case 0x0A: case 0x0B: case 0x0D:
5095
            o[1] = parse_FullColorExt(blob, cb); break;
5096
        case 0x06: o[1] = parse_XFExtGradient(blob, cb); break;
5097
        case 0x0E: case 0x0F: o[1] = blob.read_shift(cb === 5 ? 1 : 2); break;
5098
        default: throw new Error("Unrecognized ExtProp type: " + extType + " " + cb);
5099
    }
5100
    return o;
5101
}
5102
 
5103
/* 2.4.355 */
5104
function parse_XFExt(blob, length) {
5105
    var end = blob.l + length;
5106
    blob.l += 2;
5107
    var ixfe = blob.read_shift(2);
5108
    blob.l += 2;
5109
    var cexts = blob.read_shift(2);
5110
    var ext = [];
5111
    while(cexts-- > 0) ext.push(parse_ExtProp(blob, end-blob.l));
5112
    return {ixfe:ixfe, ext:ext};
5113
}
5114
 
5115
/* xf is an XF, see parse_XFExt for xfext */
5116
function update_xfext(xf, xfext) {
5117
    xfext.forEach(function(xfe) {
5118
        switch(xfe[0]) { /* 2.5.108 extPropData */
5119
            case 0x04: break; /* foreground color */
5120
            case 0x05: break; /* background color */
5121
            case 0x07: case 0x08: case 0x09: case 0x0a: break;
5122
            case 0x0d: break; /* text color */
5123
            case 0x0e: break; /* font scheme */
5124
            default: throw "bafuq" + xfe[0].toString(16);
5125
        }
5126
    });
5127
}
5128
 
5129
/* 18.6 Calculation Chain */
5130
function parse_cc_xml(data, opts) {
5131
    var d = [];
5132
    var l = 0, i = 1;
5133
    (data.match(tagregex)||[]).forEach(function(x) {
5134
        var y = parsexmltag(x);
5135
        switch(y[0]) {
5136
            case '<?xml': break;
5137
            /* 18.6.2  calcChain CT_CalcChain 1 */
5138
            case '<calcChain': case '<calcChain>': case '</calcChain>': break;
5139
            /* 18.6.1  c CT_CalcCell 1 */
5140
            case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break;
5141
        }
5142
    });
5143
    return d;
5144
}
5145
 
5146
function write_cc_xml(data, opts) { }
5147
/* [MS-XLSB] 2.6.4.1 */
5148
function parse_BrtCalcChainItem$(data, length) {
5149
    var out = {};
5150
    out.i = data.read_shift(4);
5151
    var cell = {};
5152
    cell.r = data.read_shift(4);
5153
    cell.c = data.read_shift(4);
5154
    out.r = encode_cell(cell);
5155
    var flags = data.read_shift(1);
5156
    if(flags & 0x2) out.l = '1';
5157
    if(flags & 0x8) out.a = '1';
5158
    return out;
5159
}
5160
 
5161
/* 18.6 Calculation Chain */
5162
function parse_cc_bin(data, opts) {
5163
    var out = [];
5164
    var pass = false;
5165
    recordhopper(data, function hopper_cc(val, R, RT) {
5166
        switch(R.n) {
5167
            case 'BrtCalcChainItem$': out.push(val); break;
5168
            case 'BrtBeginCalcChain$': break;
5169
            case 'BrtEndCalcChain$': break;
5170
            default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
5171
        }
5172
    });
5173
    return out;
5174
}
5175
 
5176
function write_cc_bin(data, opts) { }
5177
 
5178
function parse_comments(zip, dirComments, sheets, sheetRels, opts) {
5179
    for(var i = 0; i != dirComments.length; ++i) {
5180
        var canonicalpath=dirComments[i];
5181
        var comments=parse_cmnt(getzipdata(zip, canonicalpath.replace(/^\//,''), true), canonicalpath, opts);
5182
        if(!comments || !comments.length) continue;
5183
        // find the sheets targeted by these comments
5184
        var sheetNames = keys(sheets);
5185
        for(var j = 0; j != sheetNames.length; ++j) {
5186
            var sheetName = sheetNames[j];
5187
            var rels = sheetRels[sheetName];
5188
            if(rels) {
5189
                var rel = rels[canonicalpath];
5190
                if(rel) insertCommentsIntoSheet(sheetName, sheets[sheetName], comments);
5191
            }
5192
        }
5193
    }
5194
}
5195
 
5196
function insertCommentsIntoSheet(sheetName, sheet, comments) {
5197
    comments.forEach(function(comment) {
5198
        var cell = sheet[comment.ref];
5199
        if (!cell) {
5200
            cell = {};
5201
            sheet[comment.ref] = cell;
5202
            var range = safe_decode_range(sheet["!ref"]||"BDWGO1000001:A1");
5203
            var thisCell = decode_cell(comment.ref);
5204
            if(range.s.r > thisCell.r) range.s.r = thisCell.r;
5205
            if(range.e.r < thisCell.r) range.e.r = thisCell.r;
5206
            if(range.s.c > thisCell.c) range.s.c = thisCell.c;
5207
            if(range.e.c < thisCell.c) range.e.c = thisCell.c;
5208
            var encoded = encode_range(range);
5209
            if (encoded !== sheet["!ref"]) sheet["!ref"] = encoded;
5210
        }
5211
 
5212
        if (!cell.c) cell.c = [];
5213
        var o = {a: comment.author, t: comment.t, r: comment.r};
5214
        if(comment.h) o.h = comment.h;
5215
        cell.c.push(o);
5216
    });
5217
}
5218
 
5219
/* 18.7.3 CT_Comment */
5220
function parse_comments_xml(data, opts) {
5221
    if(data.match(/<(?:\w+:)?comments *\/>/)) return [];
5222
    var authors = [];
5223
    var commentList = [];
5224
    data.match(/<(?:\w+:)?authors>([^\u2603]*)<\/(?:\w+:)?authors>/)[1].split(/<\/\w*:?author>/).forEach(function(x) {
5225
        if(x === "" || x.trim() === "") return;
5226
        authors.push(x.match(/<(?:\w+:)?author[^>]*>(.*)/)[1]);
5227
    });
5228
    (data.match(/<(?:\w+:)?commentList>([^\u2603]*)<\/(?:\w+:)?commentList>/)||["",""])[1].split(/<\/\w*:?comment>/).forEach(function(x, index) {
5229
        if(x === "" || x.trim() === "") return;
5230
        var y = parsexmltag(x.match(/<(?:\w+:)?comment[^>]*>/)[0]);
5231
        var comment = { author: y.authorId && authors[y.authorId] ? authors[y.authorId] : undefined, ref: y.ref, guid: y.guid };
5232
        var cell = decode_cell(y.ref);
5233
        if(opts.sheetRows && opts.sheetRows <= cell.r) return;
5234
        var textMatch = x.match(/<text>([^\u2603]*)<\/text>/);
5235
        if (!textMatch || !textMatch[1]) return; // a comment may contain an empty text tag.
5236
        var rt = parse_si(textMatch[1]);
5237
        comment.r = rt.r;
5238
        comment.t = rt.t;
5239
        if(opts.cellHTML) comment.h = rt.h;
5240
        commentList.push(comment);
5241
    });
5242
    return commentList;
5243
}
5244
 
5245
function write_comments_xml(data, opts) { }
5246
/* [MS-XLSB] 2.4.28 BrtBeginComment */
5247
function parse_BrtBeginComment(data, length) {
5248
    var out = {};
5249
    out.iauthor = data.read_shift(4);
5250
    var rfx = parse_UncheckedRfX(data, 16);
5251
    out.rfx = rfx.s;
5252
    out.ref = encode_cell(rfx.s);
5253
    data.l += 16; /*var guid = parse_GUID(data); */
5254
    return out;
5255
}
5256
 
5257
/* [MS-XLSB] 2.4.324 BrtCommentAuthor */
5258
var parse_BrtCommentAuthor = parse_XLWideString;
5259
 
5260
/* [MS-XLSB] 2.4.325 BrtCommentText */
5261
var parse_BrtCommentText = parse_RichStr;
5262
 
5263
/* [MS-XLSB] 2.1.7.8 Comments */
5264
function parse_comments_bin(data, opts) {
5265
    var out = [];
5266
    var authors = [];
5267
    var c = {};
5268
    var pass = false;
5269
    recordhopper(data, function hopper_cmnt(val, R, RT) {
5270
        switch(R.n) {
5271
            case 'BrtCommentAuthor': authors.push(val); break;
5272
            case 'BrtBeginComment': c = val; break;
5273
            case 'BrtCommentText': c.t = val.t; c.h = val.h; c.r = val.r; break;
5274
            case 'BrtEndComment':
5275
                c.author = authors[c.iauthor];
5276
                delete c.iauthor;
5277
                if(opts.sheetRows && opts.sheetRows <= c.rfx.r) break;
5278
                delete c.rfx; out.push(c); break;
5279
            case 'BrtBeginComments': break;
5280
            case 'BrtEndComments': break;
5281
            case 'BrtBeginCommentAuthors': break;
5282
            case 'BrtEndCommentAuthors': break;
5283
            case 'BrtBeginCommentList': break;
5284
            case 'BrtEndCommentList': break;
5285
            default: if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R.n);
5286
        }
5287
    });
5288
    return out;
5289
}
5290
 
5291
function write_comments_bin(data, opts) { }
5292
/* TODO: it will be useful to parse the function str */
5293
var rc_to_a1 = (function(){
5294
    var rcregex = /(^|[^A-Za-z])R(\[?)(-?\d+|)\]?C(\[?)(-?\d+|)\]?/g;
5295
    var rcbase;
5296
    function rcfunc($$,$1,$2,$3,$4,$5) {
5297
        var R = $3.length>0?parseInt($3,10)|0:0, C = $5.length>0?parseInt($5,10)|0:0;
5298
        if(C<0 && $4.length === 0) C=0;
5299
        if($4.length > 0) C += rcbase.c;
5300
        if($2.length > 0) R += rcbase.r;
5301
        return $1 + encode_col(C) + encode_row(R);
5302
    }
5303
    return function rc_to_a1(fstr, base) {
5304
        rcbase = base;
5305
        return fstr.replace(rcregex, rcfunc);
5306
    };
5307
})();
5308
 
5309
/* --- formula references point to MS-XLS --- */
5310
/* Small helpers */
5311
function parseread(l) { return function(blob, length) { blob.l+=l; return; }; }
5312
function parseread1(blob, length) { blob.l+=1; return; }
5313
 
5314
/* Rgce Helpers */
5315
 
5316
/* 2.5.51 */
5317
function parse_ColRelU(blob, length) {
5318
    var c = blob.read_shift(2);
5319
    return [c & 0x3FFF, (c >> 14) & 1, (c >> 15) & 1];
5320
}
5321
 
5322
/* 2.5.198.105 */
5323
function parse_RgceArea(blob, length) {
5324
    var r=blob.read_shift(2), R=blob.read_shift(2);
5325
    var c=parse_ColRelU(blob, 2);
5326
    var C=parse_ColRelU(blob, 2);
5327
    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]} };
5328
}
5329
 
5330
/* 2.5.198.105 TODO */
5331
function parse_RgceAreaRel(blob, length) {
5332
    var r=blob.read_shift(2), R=blob.read_shift(2);
5333
    var c=parse_ColRelU(blob, 2);
5334
    var C=parse_ColRelU(blob, 2);
5335
    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]} };
5336
}
5337
 
5338
/* 2.5.198.109 */
5339
function parse_RgceLoc(blob, length) {
5340
    var r = blob.read_shift(2);
5341
    var c = parse_ColRelU(blob, 2);
5342
    return {r:r, c:c[0], cRel:c[1], rRel:c[2]};
5343
}
5344
 
5345
/* 2.5.198.111 */
5346
function parse_RgceLocRel(blob, length) {
5347
    var r = blob.read_shift(2);
5348
    var cl = blob.read_shift(2);
5349
    var cRel = (cl & 0x8000) >> 15, rRel = (cl & 0x4000) >> 14;
5350
    cl &= 0x3FFF;
5351
    if(cRel !== 0) while(cl >= 0x100) cl -= 0x100;
5352
    return {r:r,c:cl,cRel:cRel,rRel:rRel};
5353
}
5354
 
5355
/* Ptg Tokens */
5356
 
5357
/* 2.5.198.27 */
5358
function parse_PtgArea(blob, length) {
5359
    var type = (blob[blob.l++] & 0x60) >> 5;
5360
    var area = parse_RgceArea(blob, 8);
5361
    return [type, area];
5362
}
5363
 
5364
/* 2.5.198.28 */
5365
function parse_PtgArea3d(blob, length) {
5366
    var type = (blob[blob.l++] & 0x60) >> 5;
5367
    var ixti = blob.read_shift(2);
5368
    var area = parse_RgceArea(blob, 8);
5369
    return [type, ixti, area];
5370
}
5371
 
5372
/* 2.5.198.29 */
5373
function parse_PtgAreaErr(blob, length) {
5374
    var type = (blob[blob.l++] & 0x60) >> 5;
5375
    blob.l += 8;
5376
    return [type];
5377
}
5378
/* 2.5.198.30 */
5379
function parse_PtgAreaErr3d(blob, length) {
5380
    var type = (blob[blob.l++] & 0x60) >> 5;
5381
    var ixti = blob.read_shift(2);
5382
    blob.l += 8;
5383
    return [type, ixti];
5384
}
5385
 
5386
/* 2.5.198.31 */
5387
function parse_PtgAreaN(blob, length) {
5388
    var type = (blob[blob.l++] & 0x60) >> 5;
5389
    var area = parse_RgceAreaRel(blob, 8);
5390
    return [type, area];
5391
}
5392
 
5393
/* 2.5.198.32 -- ignore this and look in PtgExtraArray for shape + values */
5394
function parse_PtgArray(blob, length) {
5395
    var type = (blob[blob.l++] & 0x60) >> 5;
5396
    blob.l += 7;
5397
    return [type];
5398
}
5399
 
5400
/* 2.5.198.33 */
5401
function parse_PtgAttrBaxcel(blob, length) {
5402
    var bitSemi = blob[blob.l+1] & 0x01; /* 1 = volatile */
5403
    var bitBaxcel = 1;
5404
    blob.l += 4;
5405
    return [bitSemi, bitBaxcel];
5406
}
5407
 
5408
/* 2.5.198.34 */
5409
function parse_PtgAttrChoose(blob, length) {
5410
    blob.l +=2;
5411
    var offset = blob.read_shift(2);
5412
    var o = [];
5413
    /* offset is 1 less than the number of elements */
5414
    for(var i = 0; i <= offset; ++i) o.push(blob.read_shift(2));
5415
    return o;
5416
}
5417
 
5418
/* 2.5.198.35 */
5419
function parse_PtgAttrGoto(blob, length) {
5420
    var bitGoto = (blob[blob.l+1] & 0xFF) ? 1 : 0;
5421
    blob.l += 2;
5422
    return [bitGoto, blob.read_shift(2)];
5423
}
5424
 
5425
/* 2.5.198.36 */
5426
function parse_PtgAttrIf(blob, length) {
5427
    var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0;
5428
    blob.l += 2;
5429
    return [bitIf, blob.read_shift(2)];
5430
}
5431
 
5432
/* 2.5.198.37 */
5433
function parse_PtgAttrSemi(blob, length) {
5434
    var bitSemi = (blob[blob.l+1] & 0xFF) ? 1 : 0;
5435
    blob.l += 4;
5436
    return [bitSemi];
5437
}
5438
 
5439
/* 2.5.198.40 (used by PtgAttrSpace and PtgAttrSpaceSemi) */
5440
function parse_PtgAttrSpaceType(blob, length) {
5441
    var type = blob.read_shift(1), cch = blob.read_shift(1);
5442
    return [type, cch];
5443
}
5444
 
5445
/* 2.5.198.38 */
5446
function parse_PtgAttrSpace(blob, length) {
5447
    blob.read_shift(2);
5448
    return parse_PtgAttrSpaceType(blob, 2);
5449
}
5450
 
5451
/* 2.5.198.39 */
5452
function parse_PtgAttrSpaceSemi(blob, length) {
5453
    blob.read_shift(2);
5454
    return parse_PtgAttrSpaceType(blob, 2);
5455
}
5456
 
5457
/* 2.5.198.84 TODO */
5458
function parse_PtgRef(blob, length) {
5459
    var ptg = blob[blob.l] & 0x1F;
5460
    var type = (blob[blob.l] & 0x60)>>5;
5461
    blob.l += 1;
5462
    var loc = parse_RgceLoc(blob,4);
5463
    return [type, loc];
5464
}
5465
 
5466
/* 2.5.198.88 TODO */
5467
function parse_PtgRefN(blob, length) {
5468
    var ptg = blob[blob.l] & 0x1F;
5469
    var type = (blob[blob.l] & 0x60)>>5;
5470
    blob.l += 1;
5471
    var loc = parse_RgceLocRel(blob,4);
5472
    return [type, loc];
5473
}
5474
 
5475
/* 2.5.198.85 TODO */
5476
function parse_PtgRef3d(blob, length) {
5477
    var ptg = blob[blob.l] & 0x1F;
5478
    var type = (blob[blob.l] & 0x60)>>5;
5479
    blob.l += 1;
5480
    var ixti = blob.read_shift(2); // XtiIndex
5481
    var loc = parse_RgceLoc(blob,4);
5482
    return [type, ixti, loc];
5483
}
5484
 
5485
 
5486
/* 2.5.198.62 TODO */
5487
function parse_PtgFunc(blob, length) {
5488
    var ptg = blob[blob.l] & 0x1F;
5489
    var type = (blob[blob.l] & 0x60)>>5;
5490
    blob.l += 1;
5491
    var iftab = blob.read_shift(2);
5492
    return [FtabArgc[iftab], Ftab[iftab]];
5493
}
5494
/* 2.5.198.63 TODO */
5495
function parse_PtgFuncVar(blob, length) {
5496
    blob.l++;
5497
    var cparams = blob.read_shift(1), tab = parsetab(blob);
5498
    return [cparams, (tab[0] === 0 ? Ftab : Cetab)[tab[1]]];
5499
}
5500
 
5501
function parsetab(blob, length) {
5502
    return [blob[blob.l+1]>>7, blob.read_shift(2) & 0x7FFF];
5503
}
5504
 
5505
/* 2.5.198.41 */
5506
var parse_PtgAttrSum = parseread(4);
5507
/* 2.5.198.43 */
5508
var parse_PtgConcat = parseread1;
5509
 
5510
/* 2.5.198.58 */
5511
function parse_PtgExp(blob, length) {
5512
    blob.l++;
5513
    var row = blob.read_shift(2);
5514
    var col = blob.read_shift(2);
5515
    return [row, col];
5516
}
5517
 
5518
/* 2.5.198.57 */
5519
function parse_PtgErr(blob, length) { blob.l++; return BErr[blob.read_shift(1)]; }
5520
 
5521
/* 2.5.198.66 TODO */
5522
function parse_PtgInt(blob, length) { blob.l++; return blob.read_shift(2); }
5523
 
5524
/* 2.5.198.42 */
5525
function parse_PtgBool(blob, length) { blob.l++; return blob.read_shift(1)!==0;}
5526
 
5527
/* 2.5.198.79 */
5528
function parse_PtgNum(blob, length) { blob.l++; return parse_Xnum(blob, 8); }
5529
 
5530
/* 2.5.198.89 */
5531
function parse_PtgStr(blob, length) { blob.l++; return parse_ShortXLUnicodeString(blob); }
5532
 
5533
/* 2.5.192.112 + 2.5.192.11{3,4,5,6,7} */
5534
function parse_SerAr(blob) {
5535
    var val = [];
5536
    switch((val[0] = blob.read_shift(1))) {
5537
        /* 2.5.192.113 */
5538
        case 0x04: /* SerBool -- boolean */
5539
            val[1] = parsebool(blob, 1) ? 'TRUE' : 'FALSE';
5540
            blob.l += 7; break;
5541
        /* 2.5.192.114 */
5542
        case 0x10: /* SerErr -- error */
5543
            val[1] = BErr[blob[blob.l]];
5544
            blob.l += 8; break;
5545
        /* 2.5.192.115 */
5546
        case 0x00: /* SerNil -- honestly, I'm not sure how to reproduce this */
5547
            blob.l += 8; break;
5548
        /* 2.5.192.116 */
5549
        case 0x01: /* SerNum -- Xnum */
5550
            val[1] = parse_Xnum(blob, 8); break;
5551
        /* 2.5.192.117 */
5552
        case 0x02: /* SerStr -- XLUnicodeString (<256 chars) */
5553
            val[1] = parse_XLUnicodeString(blob); break;
5554
        // default: throw "Bad SerAr: " + val[0]; /* Unreachable */
5555
    }
5556
    return val;
5557
}
5558
 
5559
/* 2.5.198.61 */
5560
function parse_PtgExtraMem(blob, cce) {
5561
    var count = blob.read_shift(2);
5562
    var out = [];
5563
    for(var i = 0; i != count; ++i) out.push(parse_Ref8U(blob, 8));
5564
    return out;
5565
}
5566
 
5567
/* 2.5.198.59 */
5568
function parse_PtgExtraArray(blob) {
5569
    var cols = 1 + blob.read_shift(1); //DColByteU
5570
    var rows = 1 + blob.read_shift(2); //DRw
5571
    for(var i = 0, o=[]; i != rows && (o[i] = []); ++i)
5572
        for(var j = 0; j != cols; ++j) o[i][j] = parse_SerAr(blob);
5573
    return o;
5574
}
5575
 
5576
/* 2.5.198.76 */
5577
function parse_PtgName(blob, length) {
5578
    var type = (blob.read_shift(1) >>> 5) & 0x03;
5579
    var nameindex = blob.read_shift(4);
5580
    return [type, 0, nameindex];
5581
}
5582
 
5583
/* 2.5.198.77 */
5584
function parse_PtgNameX(blob, length) {
5585
    var type = (blob.read_shift(1) >>> 5) & 0x03;
5586
    var ixti = blob.read_shift(2); // XtiIndex
5587
    var nameindex = blob.read_shift(4);
5588
    return [type, ixti, nameindex];
5589
}
5590
 
5591
/* 2.5.198.70 */
5592
function parse_PtgMemArea(blob, length) {
5593
    var type = (blob.read_shift(1) >>> 5) & 0x03;
5594
    blob.l += 4;
5595
    var cce = blob.read_shift(2);
5596
    return [type, cce];
5597
}
5598
 
5599
/* 2.5.198.72 */
5600
function parse_PtgMemFunc(blob, length) {
5601
    var type = (blob.read_shift(1) >>> 5) & 0x03;
5602
    var cce = blob.read_shift(2);
5603
    return [type, cce];
5604
}
5605
 
5606
 
5607
/* 2.5.198.86 */
5608
function parse_PtgRefErr(blob, length) {
5609
    var type = (blob.read_shift(1) >>> 5) & 0x03;
5610
    blob.l += 4;
5611
    return [type];
5612
}
5613
 
5614
/* 2.5.198.26 */
5615
var parse_PtgAdd = parseread1;
5616
/* 2.5.198.45 */
5617
var parse_PtgDiv = parseread1;
5618
/* 2.5.198.56 */
5619
var parse_PtgEq = parseread1;
5620
/* 2.5.198.64 */
5621
var parse_PtgGe = parseread1;
5622
/* 2.5.198.65 */
5623
var parse_PtgGt = parseread1;
5624
/* 2.5.198.67 */
5625
var parse_PtgIsect = parseread1;
5626
/* 2.5.198.68 */
5627
var parse_PtgLe = parseread1;
5628
/* 2.5.198.69 */
5629
var parse_PtgLt = parseread1;
5630
/* 2.5.198.74 */
5631
var parse_PtgMissArg = parseread1;
5632
/* 2.5.198.75 */
5633
var parse_PtgMul = parseread1;
5634
/* 2.5.198.78 */
5635
var parse_PtgNe = parseread1;
5636
/* 2.5.198.80 */
5637
var parse_PtgParen = parseread1;
5638
/* 2.5.198.81 */
5639
var parse_PtgPercent = parseread1;
5640
/* 2.5.198.82 */
5641
var parse_PtgPower = parseread1;
5642
/* 2.5.198.83 */
5643
var parse_PtgRange = parseread1;
5644
/* 2.5.198.90 */
5645
var parse_PtgSub = parseread1;
5646
/* 2.5.198.93 */
5647
var parse_PtgUminus = parseread1;
5648
/* 2.5.198.94 */
5649
var parse_PtgUnion = parseread1;
5650
/* 2.5.198.95 */
5651
var parse_PtgUplus = parseread1;
5652
 
5653
/* 2.5.198.71 */
5654
var parse_PtgMemErr = parsenoop;
5655
/* 2.5.198.73 */
5656
var parse_PtgMemNoMem = parsenoop;
5657
/* 2.5.198.87 */
5658
var parse_PtgRefErr3d = parsenoop;
5659
/* 2.5.198.92 */
5660
var parse_PtgTbl = parsenoop;
5661
 
5662
/* 2.5.198.25 */
5663
var PtgTypes = {
5664
    0x01: { n:'PtgExp', f:parse_PtgExp },
5665
    0x02: { n:'PtgTbl', f:parse_PtgTbl },
5666
    0x03: { n:'PtgAdd', f:parse_PtgAdd },
5667
    0x04: { n:'PtgSub', f:parse_PtgSub },
5668
    0x05: { n:'PtgMul', f:parse_PtgMul },
5669
    0x06: { n:'PtgDiv', f:parse_PtgDiv },
5670
    0x07: { n:'PtgPower', f:parse_PtgPower },
5671
    0x08: { n:'PtgConcat', f:parse_PtgConcat },
5672
    0x09: { n:'PtgLt', f:parse_PtgLt },
5673
    0x0A: { n:'PtgLe', f:parse_PtgLe },
5674
    0x0B: { n:'PtgEq', f:parse_PtgEq },
5675
    0x0C: { n:'PtgGe', f:parse_PtgGe },
5676
    0x0D: { n:'PtgGt', f:parse_PtgGt },
5677
    0x0E: { n:'PtgNe', f:parse_PtgNe },
5678
    0x0F: { n:'PtgIsect', f:parse_PtgIsect },
5679
    0x10: { n:'PtgUnion', f:parse_PtgUnion },
5680
    0x11: { n:'PtgRange', f:parse_PtgRange },
5681
    0x12: { n:'PtgUplus', f:parse_PtgUplus },
5682
    0x13: { n:'PtgUminus', f:parse_PtgUminus },
5683
    0x14: { n:'PtgPercent', f:parse_PtgPercent },
5684
    0x15: { n:'PtgParen', f:parse_PtgParen },
5685
    0x16: { n:'PtgMissArg', f:parse_PtgMissArg },
5686
    0x17: { n:'PtgStr', f:parse_PtgStr },
5687
    0x1C: { n:'PtgErr', f:parse_PtgErr },
5688
    0x1D: { n:'PtgBool', f:parse_PtgBool },
5689
    0x1E: { n:'PtgInt', f:parse_PtgInt },
5690
    0x1F: { n:'PtgNum', f:parse_PtgNum },
5691
    0x20: { n:'PtgArray', f:parse_PtgArray },
5692
    0x21: { n:'PtgFunc', f:parse_PtgFunc },
5693
    0x22: { n:'PtgFuncVar', f:parse_PtgFuncVar },
5694
    0x23: { n:'PtgName', f:parse_PtgName },
5695
    0x24: { n:'PtgRef', f:parse_PtgRef },
5696
    0x25: { n:'PtgArea', f:parse_PtgArea },
5697
    0x26: { n:'PtgMemArea', f:parse_PtgMemArea },
5698
    0x27: { n:'PtgMemErr', f:parse_PtgMemErr },
5699
    0x28: { n:'PtgMemNoMem', f:parse_PtgMemNoMem },
5700
    0x29: { n:'PtgMemFunc', f:parse_PtgMemFunc },
5701
    0x2A: { n:'PtgRefErr', f:parse_PtgRefErr },
5702
    0x2B: { n:'PtgAreaErr', f:parse_PtgAreaErr },
5703
    0x2C: { n:'PtgRefN', f:parse_PtgRefN },
5704
    0x2D: { n:'PtgAreaN', f:parse_PtgAreaN },
5705
    0x39: { n:'PtgNameX', f:parse_PtgNameX },
5706
    0x3A: { n:'PtgRef3d', f:parse_PtgRef3d },
5707
    0x3B: { n:'PtgArea3d', f:parse_PtgArea3d },
5708
    0x3C: { n:'PtgRefErr3d', f:parse_PtgRefErr3d },
5709
    0x3D: { n:'PtgAreaErr3d', f:parse_PtgAreaErr3d },
5710
    0xFF: {}
5711
};
5712
/* These are duplicated in the PtgTypes table */
5713
var PtgDupes = {
5714
    0x40: 0x20, 0x60: 0x20,
5715
    0x41: 0x21, 0x61: 0x21,
5716
    0x42: 0x22, 0x62: 0x22,
5717
    0x43: 0x23, 0x63: 0x23,
5718
    0x44: 0x24, 0x64: 0x24,
5719
    0x45: 0x25, 0x65: 0x25,
5720
    0x46: 0x26, 0x66: 0x26,
5721
    0x47: 0x27, 0x67: 0x27,
5722
    0x48: 0x28, 0x68: 0x28,
5723
    0x49: 0x29, 0x69: 0x29,
5724
    0x4A: 0x2A, 0x6A: 0x2A,
5725
    0x4B: 0x2B, 0x6B: 0x2B,
5726
    0x4C: 0x2C, 0x6C: 0x2C,
5727
    0x4D: 0x2D, 0x6D: 0x2D,
5728
    0x59: 0x39, 0x79: 0x39,
5729
    0x5A: 0x3A, 0x7A: 0x3A,
5730
    0x5B: 0x3B, 0x7B: 0x3B,
5731
    0x5C: 0x3C, 0x7C: 0x3C,
5732
    0x5D: 0x3D, 0x7D: 0x3D
5733
};
5734
(function(){for(var y in PtgDupes) PtgTypes[y] = PtgTypes[PtgDupes[y]];})();
5735
 
5736
var Ptg18 = {};
5737
var Ptg19 = {
5738
    0x01: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
5739
    0x02: { n:'PtgAttrIf', f:parse_PtgAttrIf },
5740
    0x04: { n:'PtgAttrChoose', f:parse_PtgAttrChoose },
5741
    0x08: { n:'PtgAttrGoto', f:parse_PtgAttrGoto },
5742
    0x10: { n:'PtgAttrSum', f:parse_PtgAttrSum },
5743
    0x20: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
5744
    0x40: { n:'PtgAttrSpace', f:parse_PtgAttrSpace },
5745
    0x41: { n:'PtgAttrSpaceSemi', f:parse_PtgAttrSpaceSemi },
5746
    0xFF: {}
5747
};
5748
 
5749
/* 2.4.127 TODO */
5750
function parse_Formula(blob, length, opts) {
5751
    var cell = parse_XLSCell(blob, 6);
5752
    var val = parse_FormulaValue(blob,8);
5753
    var flags = blob.read_shift(1);
5754
    blob.read_shift(1);
5755
    var chn = blob.read_shift(4);
5756
    var cbf = "";
5757
    if(opts.biff === 5) blob.l += length-20;
5758
    else cbf = parse_XLSCellParsedFormula(blob, length-20, opts);
5759
    return {cell:cell, val:val[0], formula:cbf, shared: (flags >> 3) & 1, tt:val[1]};
5760
}
5761
 
5762
/* 2.5.133 TODO: how to emit empty strings? */
5763
function parse_FormulaValue(blob) {
5764
    var b;
5765
    if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return [parse_Xnum(blob),'n'];
5766
    switch(blob[blob.l]) {
5767
        case 0x00: blob.l += 8; return ["String", 's'];
5768
        case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return [b,'b'];
5769
        case 0x02: b = blob[blob.l+2]; blob.l += 8; return [b,'e'];
5770
        case 0x03: blob.l += 8; return ["",'s'];
5771
    }
5772
}
5773
 
5774
/* 2.5.198.103 */
5775
function parse_RgbExtra(blob, length, rgce, opts) {
5776
    if(opts.biff < 8) return parsenoop(blob, length);
5777
    var target = blob.l + length;
5778
    var o = [];
5779
    for(var i = 0; i !== rgce.length; ++i) {
5780
        switch(rgce[i][0]) {
5781
            case 'PtgArray': /* PtgArray -> PtgExtraArray */
5782
                rgce[i][1] = parse_PtgExtraArray(blob);
5783
                o.push(rgce[i][1]);
5784
                break;
5785
            case 'PtgMemArea': /* PtgMemArea -> PtgExtraMem */
5786
                rgce[i][2] = parse_PtgExtraMem(blob, rgce[i][1]);
5787
                o.push(rgce[i][2]);
5788
                break;
5789
            default: break;
5790
        }
5791
    }
5792
    length = target - blob.l;
5793
    if(length !== 0) o.push(parsenoop(blob, length));
5794
    return o;
5795
}
5796
 
5797
/* 2.5.198.21 */
5798
function parse_NameParsedFormula(blob, length, opts, cce) {
5799
    var target = blob.l + length;
5800
    var rgce = parse_Rgce(blob, cce);
5801
    var rgcb;
5802
    if(target !== blob.l) rgcb = parse_RgbExtra(blob, target - blob.l, rgce, opts);
5803
    return [rgce, rgcb];
5804
}
5805
 
5806
/* 2.5.198.3 TODO */
5807
function parse_XLSCellParsedFormula(blob, length, opts) {
5808
    var target = blob.l + length;
5809
    var rgcb, cce = blob.read_shift(2); // length of rgce
5810
    if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
5811
    var rgce = parse_Rgce(blob, cce);
5812
    if(length !== cce + 2) rgcb = parse_RgbExtra(blob, length - cce - 2, rgce, opts);
5813
    return [rgce, rgcb];
5814
}
5815
 
5816
/* 2.5.198.118 TODO */
5817
function parse_SharedParsedFormula(blob, length, opts) {
5818
    var target = blob.l + length;
5819
    var rgcb, cce = blob.read_shift(2); // length of rgce
5820
    var rgce = parse_Rgce(blob, cce);
5821
    if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
5822
    if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
5823
    return [rgce, rgcb];
5824
}
5825
 
5826
/* 2.5.198.1 TODO */
5827
function parse_ArrayParsedFormula(blob, length, opts, ref) {
5828
    var target = blob.l + length;
5829
    var rgcb, cce = blob.read_shift(2); // length of rgce
5830
    if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
5831
    var rgce = parse_Rgce(blob, cce);
5832
    if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
5833
    return [rgce, rgcb];
5834
}
5835
 
5836
/* 2.5.198.104 */
5837
function parse_Rgce(blob, length) {
5838
    var target = blob.l + length;
5839
    var R, id, ptgs = [];
5840
    while(target != blob.l) {
5841
        length = target - blob.l;
5842
        id = blob[blob.l];
5843
        R = PtgTypes[id];
5844
        //console.log("ptg", id, R)
5845
        if(id === 0x18 || id === 0x19) {
5846
            id = blob[blob.l + 1];
5847
            R = (id === 0x18 ? Ptg18 : Ptg19)[id];
5848
        }
5849
        if(!R || !R.f) { ptgs.push(parsenoop(blob, length)); }
5850
        else { ptgs.push([R.n, R.f(blob, length)]); }
5851
    }
5852
    return ptgs;
5853
}
5854
 
5855
function mapper(x) { return x.map(function f2(y) { return y[1];}).join(",");}
5856
 
5857
/* 2.2.2 + Magic TODO */
5858
function stringify_formula(formula, range, cell, supbooks, opts) {
5859
    if(opts !== undefined && opts.biff === 5) return "BIFF5??";
5860
    var _range = range !== undefined ? range : {s:{c:0, r:0}};
5861
    var stack = [], e1, e2, type, c, ixti, nameidx, r;
5862
    if(!formula[0] || !formula[0][0]) return "";
5863
    //console.log("--",cell,formula[0])
5864
    for(var ff = 0, fflen = formula[0].length; ff < fflen; ++ff) {
5865
        var f = formula[0][ff];
5866
        //console.log("++",f, stack)
5867
        switch(f[0]) {
5868
        /* 2.2.2.1 Unary Operator Tokens */
5869
            /* 2.5.198.93 */
5870
            case 'PtgUminus': stack.push("-" + stack.pop()); break;
5871
            /* 2.5.198.95 */
5872
            case 'PtgUplus': stack.push("+" + stack.pop()); break;
5873
            /* 2.5.198.81 */
5874
            case 'PtgPercent': stack.push(stack.pop() + "%"); break;
5875
 
5876
        /* 2.2.2.1 Binary Value Operator Token */
5877
            /* 2.5.198.26 */
5878
            case 'PtgAdd':
5879
                e1 = stack.pop(); e2 = stack.pop();
5880
                stack.push(e2+"+"+e1);
5881
                break;
5882
            /* 2.5.198.90 */
5883
            case 'PtgSub':
5884
                e1 = stack.pop(); e2 = stack.pop();
5885
                stack.push(e2+"-"+e1);
5886
                break;
5887
            /* 2.5.198.75 */
5888
            case 'PtgMul':
5889
                e1 = stack.pop(); e2 = stack.pop();
5890
                stack.push(e2+"*"+e1);
5891
                break;
5892
            /* 2.5.198.45 */
5893
            case 'PtgDiv':
5894
                e1 = stack.pop(); e2 = stack.pop();
5895
                stack.push(e2+"/"+e1);
5896
                break;
5897
            /* 2.5.198.82 */
5898
            case 'PtgPower':
5899
                e1 = stack.pop(); e2 = stack.pop();
5900
                stack.push(e2+"^"+e1);
5901
                break;
5902
            /* 2.5.198.43 */
5903
            case 'PtgConcat':
5904
                e1 = stack.pop(); e2 = stack.pop();
5905
                stack.push(e2+"&"+e1);
5906
                break;
5907
            /* 2.5.198.69 */
5908
            case 'PtgLt':
5909
                e1 = stack.pop(); e2 = stack.pop();
5910
                stack.push(e2+"<"+e1);
5911
                break;
5912
            /* 2.5.198.68 */
5913
            case 'PtgLe':
5914
                e1 = stack.pop(); e2 = stack.pop();
5915
                stack.push(e2+"<="+e1);
5916
                break;
5917
            /* 2.5.198.56 */
5918
            case 'PtgEq':
5919
                e1 = stack.pop(); e2 = stack.pop();
5920
                stack.push(e2+"="+e1);
5921
                break;
5922
            /* 2.5.198.64 */
5923
            case 'PtgGe':
5924
                e1 = stack.pop(); e2 = stack.pop();
5925
                stack.push(e2+">="+e1);
5926
                break;
5927
            /* 2.5.198.65 */
5928
            case 'PtgGt':
5929
                e1 = stack.pop(); e2 = stack.pop();
5930
                stack.push(e2+">"+e1);
5931
                break;
5932
            /* 2.5.198.78 */
5933
            case 'PtgNe':
5934
                e1 = stack.pop(); e2 = stack.pop();
5935
                stack.push(e2+"<>"+e1);
5936
                break;
5937
 
5938
        /* 2.2.2.1 Binary Reference Operator Token */
5939
            /* 2.5.198.67 */
5940
            case 'PtgIsect':
5941
                e1 = stack.pop(); e2 = stack.pop();
5942
                stack.push(e2+" "+e1);
5943
                break;
5944
            case 'PtgUnion':
5945
                e1 = stack.pop(); e2 = stack.pop();
5946
                stack.push(e2+","+e1);
5947
                break;
5948
            case 'PtgRange': break;
5949
 
5950
        /* 2.2.2.3 Control Tokens "can be ignored" */
5951
            /* 2.5.198.34 */
5952
            case 'PtgAttrChoose': break;
5953
            /* 2.5.198.35 */
5954
            case 'PtgAttrGoto': break;
5955
            /* 2.5.198.36 */
5956
            case 'PtgAttrIf': break;
5957
 
5958
 
5959
            /* 2.5.198.84 */
5960
            case 'PtgRef':
5961
                type = f[1][0]; c = shift_cell_xls(decode_cell(encode_cell(f[1][1])), _range);
5962
                stack.push(encode_cell(c));
5963
                break;
5964
            /* 2.5.198.88 */
5965
            case 'PtgRefN':
5966
                type = f[1][0]; c = shift_cell_xls(decode_cell(encode_cell(f[1][1])), cell);
5967
                stack.push(encode_cell(c));
5968
                break;
5969
            case 'PtgRef3d': // TODO: lots of stuff
5970
                type = f[1][0]; ixti = f[1][1]; c = shift_cell_xls(f[1][2], _range);
5971
                stack.push(supbooks[1][ixti+1]+"!"+encode_cell(c));
5972
                break;
5973
 
5974
        /* Function Call */
5975
            /* 2.5.198.62 */
5976
            case 'PtgFunc':
5977
            /* 2.5.198.63 */
5978
            case 'PtgFuncVar':
5979
                /* f[1] = [argc, func] */
5980
                var argc = f[1][0], func = f[1][1];
5981
                if(!argc) argc = 0;
5982
                var args = stack.slice(-argc);
5983
                stack.length -= argc;
5984
                if(func === 'User') func = args.shift();
5985
                stack.push(func + "(" + args.join(",") + ")");
5986
                break;
5987
 
5988
            /* 2.5.198.42 */
5989
            case 'PtgBool': stack.push(f[1] ? "TRUE" : "FALSE"); break;
5990
            /* 2.5.198.66 */
5991
            case 'PtgInt': stack.push(f[1]); break;
5992
            /* 2.5.198.79 TODO: precision? */
5993
            case 'PtgNum': stack.push(String(f[1])); break;
5994
            /* 2.5.198.89 */
5995
            case 'PtgStr': stack.push('"' + f[1] + '"'); break;
5996
            /* 2.5.198.57 */
5997
            case 'PtgErr': stack.push(f[1]); break;
5998
            /* 2.5.198.27 TODO: fixed points */
5999
            case 'PtgArea':
6000
                type = f[1][0]; r = shift_range_xls(f[1][1], _range);
6001
                stack.push(encode_range(r));
6002
                break;
6003
            /* 2.5.198.28 */
6004
            case 'PtgArea3d': // TODO: lots of stuff
6005
                type = f[1][0]; ixti = f[1][1]; r = f[1][2];
6006
                stack.push(supbooks[1][ixti+1]+"!"+encode_range(r));
6007
                break;
6008
            /* 2.5.198.41 */
6009
            case 'PtgAttrSum':
6010
                stack.push("SUM(" + stack.pop() + ")");
6011
                break;
6012
 
6013
        /* Expression Prefixes */
6014
            /* 2.5.198.37 */
6015
            case 'PtgAttrSemi': break;
6016
 
6017
            /* 2.5.97.60 TODO: do something different for revisions */
6018
            case 'PtgName':
6019
                /* f[1] = type, 0, nameindex */
6020
                nameidx = f[1][2];
6021
                var lbl = supbooks[0][nameidx];
6022
                var name = lbl.Name;
6023
                if(name in XLSXFutureFunctions) name = XLSXFutureFunctions[name];
6024
                stack.push(name);
6025
                break;
6026
 
6027
            /* 2.5.97.61 TODO: do something different for revisions */
6028
            case 'PtgNameX':
6029
                /* f[1] = type, ixti, nameindex */
6030
                var bookidx = f[1][1]; nameidx = f[1][2]; var externbook;
6031
                /* TODO: Properly handle missing values */
6032
                if(supbooks[bookidx+1]) externbook = supbooks[bookidx+1][nameidx];
6033
                else if(supbooks[bookidx-1]) externbook = supbooks[bookidx-1][nameidx];
6034
                if(!externbook) externbook = {body: "??NAMEX??"};
6035
                stack.push(externbook.body);
6036
                break;
6037
 
6038
        /* 2.2.2.4 Display Tokens */
6039
            /* 2.5.198.80 */
6040
            case 'PtgParen': stack.push('(' + stack.pop() + ')'); break;
6041
 
6042
            /* 2.5.198.86 */
6043
            case 'PtgRefErr': stack.push('#REF!'); break;
6044
 
6045
        /* */
6046
            /* 2.5.198.58 TODO */
6047
            case 'PtgExp':
6048
                c = {c:f[1][1],r:f[1][0]};
6049
                var q = {c: cell.c, r:cell.r};
6050
                if(supbooks.sharedf[encode_cell(c)]) {
6051
                    var parsedf = (supbooks.sharedf[encode_cell(c)]);
6052
                    stack.push(stringify_formula(parsedf, _range, q, supbooks, opts));
6053
                }
6054
                else {
6055
                    var fnd = false;
6056
                    for(e1=0;e1!=supbooks.arrayf.length; ++e1) {
6057
                        /* TODO: should be something like range_has */
6058
                        e2 = supbooks.arrayf[e1];
6059
                        if(c.c < e2[0].s.c || c.c > e2[0].e.c) continue;
6060
                        if(c.r < e2[0].s.r || c.r > e2[0].e.r) continue;
6061
                        stack.push(stringify_formula(e2[1], _range, q, supbooks, opts));
6062
                    }
6063
                    if(!fnd) stack.push(f[1]);
6064
                }
6065
                break;
6066
 
6067
            /* 2.5.198.32 TODO */
6068
            case 'PtgArray':
6069
                stack.push("{" + f[1].map(mapper).join(";") + "}");
6070
                break;
6071
 
6072
        /* 2.2.2.5 Mem Tokens */
6073
            /* 2.5.198.70 TODO: confirm this is a non-display */
6074
            case 'PtgMemArea':
6075
                //stack.push("(" + f[2].map(encode_range).join(",") + ")");
6076
                break;
6077
 
6078
            /* 2.5.198.38 TODO */
6079
            case 'PtgAttrSpace': break;
6080
 
6081
            /* 2.5.198.92 TODO */
6082
            case 'PtgTbl': break;
6083
 
6084
            /* 2.5.198.71 */
6085
            case 'PtgMemErr': break;
6086
 
6087
            /* 2.5.198.74 */
6088
            case 'PtgMissArg':
6089
                stack.push("");
6090
                break;
6091
 
6092
            /* 2.5.198.29 TODO */
6093
            case 'PtgAreaErr': break;
6094
 
6095
            /* 2.5.198.31 TODO */
6096
            case 'PtgAreaN': stack.push(""); break;
6097
 
6098
            /* 2.5.198.87 TODO */
6099
            case 'PtgRefErr3d': break;
6100
 
6101
            /* 2.5.198.72 TODO */
6102
            case 'PtgMemFunc': break;
6103
 
6104
            default: throw 'Unrecognized Formula Token: ' + f;
6105
        }
6106
        //console.log("::",f, stack)
6107
    }
6108
    //console.log("--",stack);
6109
    return stack[0];
6110
}
6111
 
6112
/* [MS-XLSB] 2.5.97.4 CellParsedFormula TODO: use similar logic to js-xls */
6113
function parse_XLSBCellParsedFormula(data, length) {
6114
    var cce = data.read_shift(4);
6115
    return parsenoop(data, length-4);
6116
}
6117
/* [MS-XLS] 2.5.198.44 */
6118
var PtgDataType = {
6119
    0x1: "REFERENCE", // reference to range
6120
    0x2: "VALUE", // single value
6121
    0x3: "ARRAY" // array of values
6122
};
6123
 
6124
/* [MS-XLS] 2.5.198.4 */
6125
var Cetab = {
6126
    0x0000: 'BEEP',
6127
    0x0001: 'OPEN',
6128
    0x0002: 'OPEN.LINKS',
6129
    0x0003: 'CLOSE.ALL',
6130
    0x0004: 'SAVE',
6131
    0x0005: 'SAVE.AS',
6132
    0x0006: 'FILE.DELETE',
6133
    0x0007: 'PAGE.SETUP',
6134
    0x0008: 'PRINT',
6135
    0x0009: 'PRINTER.SETUP',
6136
    0x000A: 'QUIT',
6137
    0x000B: 'NEW.WINDOW',
6138
    0x000C: 'ARRANGE.ALL',
6139
    0x000D: 'WINDOW.SIZE',
6140
    0x000E: 'WINDOW.MOVE',
6141
    0x000F: 'FULL',
6142
    0x0010: 'CLOSE',
6143
    0x0011: 'RUN',
6144
    0x0016: 'SET.PRINT.AREA',
6145
    0x0017: 'SET.PRINT.TITLES',
6146
    0x0018: 'SET.PAGE.BREAK',
6147
    0x0019: 'REMOVE.PAGE.BREAK',
6148
    0x001A: 'FONT',
6149
    0x001B: 'DISPLAY',
6150
    0x001C: 'PROTECT.DOCUMENT',
6151
    0x001D: 'PRECISION',
6152
    0x001E: 'A1.R1C1',
6153
    0x001F: 'CALCULATE.NOW',
6154
    0x0020: 'CALCULATION',
6155
    0x0022: 'DATA.FIND',
6156
    0x0023: 'EXTRACT',
6157
    0x0024: 'DATA.DELETE',
6158
    0x0025: 'SET.DATABASE',
6159
    0x0026: 'SET.CRITERIA',
6160
    0x0027: 'SORT',
6161
    0x0028: 'DATA.SERIES',
6162
    0x0029: 'TABLE',
6163
    0x002A: 'FORMAT.NUMBER',
6164
    0x002B: 'ALIGNMENT',
6165
    0x002C: 'STYLE',
6166
    0x002D: 'BORDER',
6167
    0x002E: 'CELL.PROTECTION',
6168
    0x002F: 'COLUMN.WIDTH',
6169
    0x0030: 'UNDO',
6170
    0x0031: 'CUT',
6171
    0x0032: 'COPY',
6172
    0x0033: 'PASTE',
6173
    0x0034: 'CLEAR',
6174
    0x0035: 'PASTE.SPECIAL',
6175
    0x0036: 'EDIT.DELETE',
6176
    0x0037: 'INSERT',
6177
    0x0038: 'FILL.RIGHT',
6178
    0x0039: 'FILL.DOWN',
6179
    0x003D: 'DEFINE.NAME',
6180
    0x003E: 'CREATE.NAMES',
6181
    0x003F: 'FORMULA.GOTO',
6182
    0x0040: 'FORMULA.FIND',
6183
    0x0041: 'SELECT.LAST.CELL',
6184
    0x0042: 'SHOW.ACTIVE.CELL',
6185
    0x0043: 'GALLERY.AREA',
6186
    0x0044: 'GALLERY.BAR',
6187
    0x0045: 'GALLERY.COLUMN',
6188
    0x0046: 'GALLERY.LINE',
6189
    0x0047: 'GALLERY.PIE',
6190
    0x0048: 'GALLERY.SCATTER',
6191
    0x0049: 'COMBINATION',
6192
    0x004A: 'PREFERRED',
6193
    0x004B: 'ADD.OVERLAY',
6194
    0x004C: 'GRIDLINES',
6195
    0x004D: 'SET.PREFERRED',
6196
    0x004E: 'AXES',
6197
    0x004F: 'LEGEND',
6198
    0x0050: 'ATTACH.TEXT',
6199
    0x0051: 'ADD.ARROW',
6200
    0x0052: 'SELECT.CHART',
6201
    0x0053: 'SELECT.PLOT.AREA',
6202
    0x0054: 'PATTERNS',
6203
    0x0055: 'MAIN.CHART',
6204
    0x0056: 'OVERLAY',
6205
    0x0057: 'SCALE',
6206
    0x0058: 'FORMAT.LEGEND',
6207
    0x0059: 'FORMAT.TEXT',
6208
    0x005A: 'EDIT.REPEAT',
6209
    0x005B: 'PARSE',
6210
    0x005C: 'JUSTIFY',
6211
    0x005D: 'HIDE',
6212
    0x005E: 'UNHIDE',
6213
    0x005F: 'WORKSPACE',
6214
    0x0060: 'FORMULA',
6215
    0x0061: 'FORMULA.FILL',
6216
    0x0062: 'FORMULA.ARRAY',
6217
    0x0063: 'DATA.FIND.NEXT',
6218
    0x0064: 'DATA.FIND.PREV',
6219
    0x0065: 'FORMULA.FIND.NEXT',
6220
    0x0066: 'FORMULA.FIND.PREV',
6221
    0x0067: 'ACTIVATE',
6222
    0x0068: 'ACTIVATE.NEXT',
6223
    0x0069: 'ACTIVATE.PREV',
6224
    0x006A: 'UNLOCKED.NEXT',
6225
    0x006B: 'UNLOCKED.PREV',
6226
    0x006C: 'COPY.PICTURE',
6227
    0x006D: 'SELECT',
6228
    0x006E: 'DELETE.NAME',
6229
    0x006F: 'DELETE.FORMAT',
6230
    0x0070: 'VLINE',
6231
    0x0071: 'HLINE',
6232
    0x0072: 'VPAGE',
6233
    0x0073: 'HPAGE',
6234
    0x0074: 'VSCROLL',
6235
    0x0075: 'HSCROLL',
6236
    0x0076: 'ALERT',
6237
    0x0077: 'NEW',
6238
    0x0078: 'CANCEL.COPY',
6239
    0x0079: 'SHOW.CLIPBOARD',
6240
    0x007A: 'MESSAGE',
6241
    0x007C: 'PASTE.LINK',
6242
    0x007D: 'APP.ACTIVATE',
6243
    0x007E: 'DELETE.ARROW',
6244
    0x007F: 'ROW.HEIGHT',
6245
    0x0080: 'FORMAT.MOVE',
6246
    0x0081: 'FORMAT.SIZE',
6247
    0x0082: 'FORMULA.REPLACE',
6248
    0x0083: 'SEND.KEYS',
6249
    0x0084: 'SELECT.SPECIAL',
6250
    0x0085: 'APPLY.NAMES',
6251
    0x0086: 'REPLACE.FONT',
6252
    0x0087: 'FREEZE.PANES',
6253
    0x0088: 'SHOW.INFO',
6254
    0x0089: 'SPLIT',
6255
    0x008A: 'ON.WINDOW',
6256
    0x008B: 'ON.DATA',
6257
    0x008C: 'DISABLE.INPUT',
6258
    0x008E: 'OUTLINE',
6259
    0x008F: 'LIST.NAMES',
6260
    0x0090: 'FILE.CLOSE',
6261
    0x0091: 'SAVE.WORKBOOK',
6262
    0x0092: 'DATA.FORM',
6263
    0x0093: 'COPY.CHART',
6264
    0x0094: 'ON.TIME',
6265
    0x0095: 'WAIT',
6266
    0x0096: 'FORMAT.FONT',
6267
    0x0097: 'FILL.UP',
6268
    0x0098: 'FILL.LEFT',
6269
    0x0099: 'DELETE.OVERLAY',
6270
    0x009B: 'SHORT.MENUS',
6271
    0x009F: 'SET.UPDATE.STATUS',
6272
    0x00A1: 'COLOR.PALETTE',
6273
    0x00A2: 'DELETE.STYLE',
6274
    0x00A3: 'WINDOW.RESTORE',
6275
    0x00A4: 'WINDOW.MAXIMIZE',
6276
    0x00A6: 'CHANGE.LINK',
6277
    0x00A7: 'CALCULATE.DOCUMENT',
6278
    0x00A8: 'ON.KEY',
6279
    0x00A9: 'APP.RESTORE',
6280
    0x00AA: 'APP.MOVE',
6281
    0x00AB: 'APP.SIZE',
6282
    0x00AC: 'APP.MINIMIZE',
6283
    0x00AD: 'APP.MAXIMIZE',
6284
    0x00AE: 'BRING.TO.FRONT',
6285
    0x00AF: 'SEND.TO.BACK',
6286
    0x00B9: 'MAIN.CHART.TYPE',
6287
    0x00BA: 'OVERLAY.CHART.TYPE',
6288
    0x00BB: 'SELECT.END',
6289
    0x00BC: 'OPEN.MAIL',
6290
    0x00BD: 'SEND.MAIL',
6291
    0x00BE: 'STANDARD.FONT',
6292
    0x00BF: 'CONSOLIDATE',
6293
    0x00C0: 'SORT.SPECIAL',
6294
    0x00C1: 'GALLERY.3D.AREA',
6295
    0x00C2: 'GALLERY.3D.COLUMN',
6296
    0x00C3: 'GALLERY.3D.LINE',
6297
    0x00C4: 'GALLERY.3D.PIE',
6298
    0x00C5: 'VIEW.3D',
6299
    0x00C6: 'GOAL.SEEK',
6300
    0x00C7: 'WORKGROUP',
6301
    0x00C8: 'FILL.GROUP',
6302
    0x00C9: 'UPDATE.LINK',
6303
    0x00CA: 'PROMOTE',
6304
    0x00CB: 'DEMOTE',
6305
    0x00CC: 'SHOW.DETAIL',
6306
    0x00CE: 'UNGROUP',
6307
    0x00CF: 'OBJECT.PROPERTIES',
6308
    0x00D0: 'SAVE.NEW.OBJECT',
6309
    0x00D1: 'SHARE',
6310
    0x00D2: 'SHARE.NAME',
6311
    0x00D3: 'DUPLICATE',
6312
    0x00D4: 'APPLY.STYLE',
6313
    0x00D5: 'ASSIGN.TO.OBJECT',
6314
    0x00D6: 'OBJECT.PROTECTION',
6315
    0x00D7: 'HIDE.OBJECT',
6316
    0x00D8: 'SET.EXTRACT',
6317
    0x00D9: 'CREATE.PUBLISHER',
6318
    0x00DA: 'SUBSCRIBE.TO',
6319
    0x00DB: 'ATTRIBUTES',
6320
    0x00DC: 'SHOW.TOOLBAR',
6321
    0x00DE: 'PRINT.PREVIEW',
6322
    0x00DF: 'EDIT.COLOR',
6323
    0x00E0: 'SHOW.LEVELS',
6324
    0x00E1: 'FORMAT.MAIN',
6325
    0x00E2: 'FORMAT.OVERLAY',
6326
    0x00E3: 'ON.RECALC',
6327
    0x00E4: 'EDIT.SERIES',
6328
    0x00E5: 'DEFINE.STYLE',
6329
    0x00F0: 'LINE.PRINT',
6330
    0x00F3: 'ENTER.DATA',
6331
    0x00F9: 'GALLERY.RADAR',
6332
    0x00FA: 'MERGE.STYLES',
6333
    0x00FB: 'EDITION.OPTIONS',
6334
    0x00FC: 'PASTE.PICTURE',
6335
    0x00FD: 'PASTE.PICTURE.LINK',
6336
    0x00FE: 'SPELLING',
6337
    0x0100: 'ZOOM',
6338
    0x0103: 'INSERT.OBJECT',
6339
    0x0104: 'WINDOW.MINIMIZE',
6340
    0x0109: 'SOUND.NOTE',
6341
    0x010A: 'SOUND.PLAY',
6342
    0x010B: 'FORMAT.SHAPE',
6343
    0x010C: 'EXTEND.POLYGON',
6344
    0x010D: 'FORMAT.AUTO',
6345
    0x0110: 'GALLERY.3D.BAR',
6346
    0x0111: 'GALLERY.3D.SURFACE',
6347
    0x0112: 'FILL.AUTO',
6348
    0x0114: 'CUSTOMIZE.TOOLBAR',
6349
    0x0115: 'ADD.TOOL',
6350
    0x0116: 'EDIT.OBJECT',
6351
    0x0117: 'ON.DOUBLECLICK',
6352
    0x0118: 'ON.ENTRY',
6353
    0x0119: 'WORKBOOK.ADD',
6354
    0x011A: 'WORKBOOK.MOVE',
6355
    0x011B: 'WORKBOOK.COPY',
6356
    0x011C: 'WORKBOOK.OPTIONS',
6357
    0x011D: 'SAVE.WORKSPACE',
6358
    0x0120: 'CHART.WIZARD',
6359
    0x0121: 'DELETE.TOOL',
6360
    0x0122: 'MOVE.TOOL',
6361
    0x0123: 'WORKBOOK.SELECT',
6362
    0x0124: 'WORKBOOK.ACTIVATE',
6363
    0x0125: 'ASSIGN.TO.TOOL',
6364
    0x0127: 'COPY.TOOL',
6365
    0x0128: 'RESET.TOOL',
6366
    0x0129: 'CONSTRAIN.NUMERIC',
6367
    0x012A: 'PASTE.TOOL',
6368
    0x012E: 'WORKBOOK.NEW',
6369
    0x0131: 'SCENARIO.CELLS',
6370
    0x0132: 'SCENARIO.DELETE',
6371
    0x0133: 'SCENARIO.ADD',
6372
    0x0134: 'SCENARIO.EDIT',
6373
    0x0135: 'SCENARIO.SHOW',
6374
    0x0136: 'SCENARIO.SHOW.NEXT',
6375
    0x0137: 'SCENARIO.SUMMARY',
6376
    0x0138: 'PIVOT.TABLE.WIZARD',
6377
    0x0139: 'PIVOT.FIELD.PROPERTIES',
6378
    0x013A: 'PIVOT.FIELD',
6379
    0x013B: 'PIVOT.ITEM',
6380
    0x013C: 'PIVOT.ADD.FIELDS',
6381
    0x013E: 'OPTIONS.CALCULATION',
6382
    0x013F: 'OPTIONS.EDIT',
6383
    0x0140: 'OPTIONS.VIEW',
6384
    0x0141: 'ADDIN.MANAGER',
6385
    0x0142: 'MENU.EDITOR',
6386
    0x0143: 'ATTACH.TOOLBARS',
6387
    0x0144: 'VBAActivate',
6388
    0x0145: 'OPTIONS.CHART',
6389
    0x0148: 'VBA.INSERT.FILE',
6390
    0x014A: 'VBA.PROCEDURE.DEFINITION',
6391
    0x0150: 'ROUTING.SLIP',
6392
    0x0152: 'ROUTE.DOCUMENT',
6393
    0x0153: 'MAIL.LOGON',
6394
    0x0156: 'INSERT.PICTURE',
6395
    0x0157: 'EDIT.TOOL',
6396
    0x0158: 'GALLERY.DOUGHNUT',
6397
    0x015E: 'CHART.TREND',
6398
    0x0160: 'PIVOT.ITEM.PROPERTIES',
6399
    0x0162: 'WORKBOOK.INSERT',
6400
    0x0163: 'OPTIONS.TRANSITION',
6401
    0x0164: 'OPTIONS.GENERAL',
6402
    0x0172: 'FILTER.ADVANCED',
6403
    0x0175: 'MAIL.ADD.MAILER',
6404
    0x0176: 'MAIL.DELETE.MAILER',
6405
    0x0177: 'MAIL.REPLY',
6406
    0x0178: 'MAIL.REPLY.ALL',
6407
    0x0179: 'MAIL.FORWARD',
6408
    0x017A: 'MAIL.NEXT.LETTER',
6409
    0x017B: 'DATA.LABEL',
6410
    0x017C: 'INSERT.TITLE',
6411
    0x017D: 'FONT.PROPERTIES',
6412
    0x017E: 'MACRO.OPTIONS',
6413
    0x017F: 'WORKBOOK.HIDE',
6414
    0x0180: 'WORKBOOK.UNHIDE',
6415
    0x0181: 'WORKBOOK.DELETE',
6416
    0x0182: 'WORKBOOK.NAME',
6417
    0x0184: 'GALLERY.CUSTOM',
6418
    0x0186: 'ADD.CHART.AUTOFORMAT',
6419
    0x0187: 'DELETE.CHART.AUTOFORMAT',
6420
    0x0188: 'CHART.ADD.DATA',
6421
    0x0189: 'AUTO.OUTLINE',
6422
    0x018A: 'TAB.ORDER',
6423
    0x018B: 'SHOW.DIALOG',
6424
    0x018C: 'SELECT.ALL',
6425
    0x018D: 'UNGROUP.SHEETS',
6426
    0x018E: 'SUBTOTAL.CREATE',
6427
    0x018F: 'SUBTOTAL.REMOVE',
6428
    0x0190: 'RENAME.OBJECT',
6429
    0x019C: 'WORKBOOK.SCROLL',
6430
    0x019D: 'WORKBOOK.NEXT',
6431
    0x019E: 'WORKBOOK.PREV',
6432
    0x019F: 'WORKBOOK.TAB.SPLIT',
6433
    0x01A0: 'FULL.SCREEN',
6434
    0x01A1: 'WORKBOOK.PROTECT',
6435
    0x01A4: 'SCROLLBAR.PROPERTIES',
6436
    0x01A5: 'PIVOT.SHOW.PAGES',
6437
    0x01A6: 'TEXT.TO.COLUMNS',
6438
    0x01A7: 'FORMAT.CHARTTYPE',
6439
    0x01A8: 'LINK.FORMAT',
6440
    0x01A9: 'TRACER.DISPLAY',
6441
    0x01AE: 'TRACER.NAVIGATE',
6442
    0x01AF: 'TRACER.CLEAR',
6443
    0x01B0: 'TRACER.ERROR',
6444
    0x01B1: 'PIVOT.FIELD.GROUP',
6445
    0x01B2: 'PIVOT.FIELD.UNGROUP',
6446
    0x01B3: 'CHECKBOX.PROPERTIES',
6447
    0x01B4: 'LABEL.PROPERTIES',
6448
    0x01B5: 'LISTBOX.PROPERTIES',
6449
    0x01B6: 'EDITBOX.PROPERTIES',
6450
    0x01B7: 'PIVOT.REFRESH',
6451
    0x01B8: 'LINK.COMBO',
6452
    0x01B9: 'OPEN.TEXT',
6453
    0x01BA: 'HIDE.DIALOG',
6454
    0x01BB: 'SET.DIALOG.FOCUS',
6455
    0x01BC: 'ENABLE.OBJECT',
6456
    0x01BD: 'PUSHBUTTON.PROPERTIES',
6457
    0x01BE: 'SET.DIALOG.DEFAULT',
6458
    0x01BF: 'FILTER',
6459
    0x01C0: 'FILTER.SHOW.ALL',
6460
    0x01C1: 'CLEAR.OUTLINE',
6461
    0x01C2: 'FUNCTION.WIZARD',
6462
    0x01C3: 'ADD.LIST.ITEM',
6463
    0x01C4: 'SET.LIST.ITEM',
6464
    0x01C5: 'REMOVE.LIST.ITEM',
6465
    0x01C6: 'SELECT.LIST.ITEM',
6466
    0x01C7: 'SET.CONTROL.VALUE',
6467
    0x01C8: 'SAVE.COPY.AS',
6468
    0x01CA: 'OPTIONS.LISTS.ADD',
6469
    0x01CB: 'OPTIONS.LISTS.DELETE',
6470
    0x01CC: 'SERIES.AXES',
6471
    0x01CD: 'SERIES.X',
6472
    0x01CE: 'SERIES.Y',
6473
    0x01CF: 'ERRORBAR.X',
6474
    0x01D0: 'ERRORBAR.Y',
6475
    0x01D1: 'FORMAT.CHART',
6476
    0x01D2: 'SERIES.ORDER',
6477
    0x01D3: 'MAIL.LOGOFF',
6478
    0x01D4: 'CLEAR.ROUTING.SLIP',
6479
    0x01D5: 'APP.ACTIVATE.MICROSOFT',
6480
    0x01D6: 'MAIL.EDIT.MAILER',
6481
    0x01D7: 'ON.SHEET',
6482
    0x01D8: 'STANDARD.WIDTH',
6483
    0x01D9: 'SCENARIO.MERGE',
6484
    0x01DA: 'SUMMARY.INFO',
6485
    0x01DB: 'FIND.FILE',
6486
    0x01DC: 'ACTIVE.CELL.FONT',
6487
    0x01DD: 'ENABLE.TIPWIZARD',
6488
    0x01DE: 'VBA.MAKE.ADDIN',
6489
    0x01E0: 'INSERTDATATABLE',
6490
    0x01E1: 'WORKGROUP.OPTIONS',
6491
    0x01E2: 'MAIL.SEND.MAILER',
6492
    0x01E5: 'AUTOCORRECT',
6493
    0x01E9: 'POST.DOCUMENT',
6494
    0x01EB: 'PICKLIST',
6495
    0x01ED: 'VIEW.SHOW',
6496
    0x01EE: 'VIEW.DEFINE',
6497
    0x01EF: 'VIEW.DELETE',
6498
    0x01FD: 'SHEET.BACKGROUND',
6499
    0x01FE: 'INSERT.MAP.OBJECT',
6500
    0x01FF: 'OPTIONS.MENONO',
6501
    0x0205: 'MSOCHECKS',
6502
    0x0206: 'NORMAL',
6503
    0x0207: 'LAYOUT',
6504
    0x0208: 'RM.PRINT.AREA',
6505
    0x0209: 'CLEAR.PRINT.AREA',
6506
    0x020A: 'ADD.PRINT.AREA',
6507
    0x020B: 'MOVE.BRK',
6508
    0x0221: 'HIDECURR.NOTE',
6509
    0x0222: 'HIDEALL.NOTES',
6510
    0x0223: 'DELETE.NOTE',
6511
    0x0224: 'TRAVERSE.NOTES',
6512
    0x0225: 'ACTIVATE.NOTES',
6513
    0x026C: 'PROTECT.REVISIONS',
6514
    0x026D: 'UNPROTECT.REVISIONS',
6515
    0x0287: 'OPTIONS.ME',
6516
    0x028D: 'WEB.PUBLISH',
6517
    0x029B: 'NEWWEBQUERY',
6518
    0x02A1: 'PIVOT.TABLE.CHART',
6519
    0x02F1: 'OPTIONS.SAVE',
6520
    0x02F3: 'OPTIONS.SPELL',
6521
    0x0328: 'HIDEALL.INKANNOTS'
6522
};
6523
 
6524
/* [MS-XLS] 2.5.198.17 */
6525
var Ftab = {
6526
    0x0000: 'COUNT',
6527
    0x0001: 'IF',
6528
    0x0002: 'ISNA',
6529
    0x0003: 'ISERROR',
6530
    0x0004: 'SUM',
6531
    0x0005: 'AVERAGE',
6532
    0x0006: 'MIN',
6533
    0x0007: 'MAX',
6534
    0x0008: 'ROW',
6535
    0x0009: 'COLUMN',
6536
    0x000A: 'NA',
6537
    0x000B: 'NPV',
6538
    0x000C: 'STDEV',
6539
    0x000D: 'DOLLAR',
6540
    0x000E: 'FIXED',
6541
    0x000F: 'SIN',
6542
    0x0010: 'COS',
6543
    0x0011: 'TAN',
6544
    0x0012: 'ATAN',
6545
    0x0013: 'PI',
6546
    0x0014: 'SQRT',
6547
    0x0015: 'EXP',
6548
    0x0016: 'LN',
6549
    0x0017: 'LOG10',
6550
    0x0018: 'ABS',
6551
    0x0019: 'INT',
6552
    0x001A: 'SIGN',
6553
    0x001B: 'ROUND',
6554
    0x001C: 'LOOKUP',
6555
    0x001D: 'INDEX',
6556
    0x001E: 'REPT',
6557
    0x001F: 'MID',
6558
    0x0020: 'LEN',
6559
    0x0021: 'VALUE',
6560
    0x0022: 'TRUE',
6561
    0x0023: 'FALSE',
6562
    0x0024: 'AND',
6563
    0x0025: 'OR',
6564
    0x0026: 'NOT',
6565
    0x0027: 'MOD',
6566
    0x0028: 'DCOUNT',
6567
    0x0029: 'DSUM',
6568
    0x002A: 'DAVERAGE',
6569
    0x002B: 'DMIN',
6570
    0x002C: 'DMAX',
6571
    0x002D: 'DSTDEV',
6572
    0x002E: 'VAR',
6573
    0x002F: 'DVAR',
6574
    0x0030: 'TEXT',
6575
    0x0031: 'LINEST',
6576
    0x0032: 'TREND',
6577
    0x0033: 'LOGEST',
6578
    0x0034: 'GROWTH',
6579
    0x0035: 'GOTO',
6580
    0x0036: 'HALT',
6581
    0x0037: 'RETURN',
6582
    0x0038: 'PV',
6583
    0x0039: 'FV',
6584
    0x003A: 'NPER',
6585
    0x003B: 'PMT',
6586
    0x003C: 'RATE',
6587
    0x003D: 'MIRR',
6588
    0x003E: 'IRR',
6589
    0x003F: 'RAND',
6590
    0x0040: 'MATCH',
6591
    0x0041: 'DATE',
6592
    0x0042: 'TIME',
6593
    0x0043: 'DAY',
6594
    0x0044: 'MONTH',
6595
    0x0045: 'YEAR',
6596
    0x0046: 'WEEKDAY',
6597
    0x0047: 'HOUR',
6598
    0x0048: 'MINUTE',
6599
    0x0049: 'SECOND',
6600
    0x004A: 'NOW',
6601
    0x004B: 'AREAS',
6602
    0x004C: 'ROWS',
6603
    0x004D: 'COLUMNS',
6604
    0x004E: 'OFFSET',
6605
    0x004F: 'ABSREF',
6606
    0x0050: 'RELREF',
6607
    0x0051: 'ARGUMENT',
6608
    0x0052: 'SEARCH',
6609
    0x0053: 'TRANSPOSE',
6610
    0x0054: 'ERROR',
6611
    0x0055: 'STEP',
6612
    0x0056: 'TYPE',
6613
    0x0057: 'ECHO',
6614
    0x0058: 'SET.NAME',
6615
    0x0059: 'CALLER',
6616
    0x005A: 'DEREF',
6617
    0x005B: 'WINDOWS',
6618
    0x005C: 'SERIES',
6619
    0x005D: 'DOCUMENTS',
6620
    0x005E: 'ACTIVE.CELL',
6621
    0x005F: 'SELECTION',
6622
    0x0060: 'RESULT',
6623
    0x0061: 'ATAN2',
6624
    0x0062: 'ASIN',
6625
    0x0063: 'ACOS',
6626
    0x0064: 'CHOOSE',
6627
    0x0065: 'HLOOKUP',
6628
    0x0066: 'VLOOKUP',
6629
    0x0067: 'LINKS',
6630
    0x0068: 'INPUT',
6631
    0x0069: 'ISREF',
6632
    0x006A: 'GET.FORMULA',
6633
    0x006B: 'GET.NAME',
6634
    0x006C: 'SET.VALUE',
6635
    0x006D: 'LOG',
6636
    0x006E: 'EXEC',
6637
    0x006F: 'CHAR',
6638
    0x0070: 'LOWER',
6639
    0x0071: 'UPPER',
6640
    0x0072: 'PROPER',
6641
    0x0073: 'LEFT',
6642
    0x0074: 'RIGHT',
6643
    0x0075: 'EXACT',
6644
    0x0076: 'TRIM',
6645
    0x0077: 'REPLACE',
6646
    0x0078: 'SUBSTITUTE',
6647
    0x0079: 'CODE',
6648
    0x007A: 'NAMES',
6649
    0x007B: 'DIRECTORY',
6650
    0x007C: 'FIND',
6651
    0x007D: 'CELL',
6652
    0x007E: 'ISERR',
6653
    0x007F: 'ISTEXT',
6654
    0x0080: 'ISNUMBER',
6655
    0x0081: 'ISBLANK',
6656
    0x0082: 'T',
6657
    0x0083: 'N',
6658
    0x0084: 'FOPEN',
6659
    0x0085: 'FCLOSE',
6660
    0x0086: 'FSIZE',
6661
    0x0087: 'FREADLN',
6662
    0x0088: 'FREAD',
6663
    0x0089: 'FWRITELN',
6664
    0x008A: 'FWRITE',
6665
    0x008B: 'FPOS',
6666
    0x008C: 'DATEVALUE',
6667
    0x008D: 'TIMEVALUE',
6668
    0x008E: 'SLN',
6669
    0x008F: 'SYD',
6670
    0x0090: 'DDB',
6671
    0x0091: 'GET.DEF',
6672
    0x0092: 'REFTEXT',
6673
    0x0093: 'TEXTREF',
6674
    0x0094: 'INDIRECT',
6675
    0x0095: 'REGISTER',
6676
    0x0096: 'CALL',
6677
    0x0097: 'ADD.BAR',
6678
    0x0098: 'ADD.MENU',
6679
    0x0099: 'ADD.COMMAND',
6680
    0x009A: 'ENABLE.COMMAND',
6681
    0x009B: 'CHECK.COMMAND',
6682
    0x009C: 'RENAME.COMMAND',
6683
    0x009D: 'SHOW.BAR',
6684
    0x009E: 'DELETE.MENU',
6685
    0x009F: 'DELETE.COMMAND',
6686
    0x00A0: 'GET.CHART.ITEM',
6687
    0x00A1: 'DIALOG.BOX',
6688
    0x00A2: 'CLEAN',
6689
    0x00A3: 'MDETERM',
6690
    0x00A4: 'MINVERSE',
6691
    0x00A5: 'MMULT',
6692
    0x00A6: 'FILES',
6693
    0x00A7: 'IPMT',
6694
    0x00A8: 'PPMT',
6695
    0x00A9: 'COUNTA',
6696
    0x00AA: 'CANCEL.KEY',
6697
    0x00AB: 'FOR',
6698
    0x00AC: 'WHILE',
6699
    0x00AD: 'BREAK',
6700
    0x00AE: 'NEXT',
6701
    0x00AF: 'INITIATE',
6702
    0x00B0: 'REQUEST',
6703
    0x00B1: 'POKE',
6704
    0x00B2: 'EXECUTE',
6705
    0x00B3: 'TERMINATE',
6706
    0x00B4: 'RESTART',
6707
    0x00B5: 'HELP',
6708
    0x00B6: 'GET.BAR',
6709
    0x00B7: 'PRODUCT',
6710
    0x00B8: 'FACT',
6711
    0x00B9: 'GET.CELL',
6712
    0x00BA: 'GET.WORKSPACE',
6713
    0x00BB: 'GET.WINDOW',
6714
    0x00BC: 'GET.DOCUMENT',
6715
    0x00BD: 'DPRODUCT',
6716
    0x00BE: 'ISNONTEXT',
6717
    0x00BF: 'GET.NOTE',
6718
    0x00C0: 'NOTE',
6719
    0x00C1: 'STDEVP',
6720
    0x00C2: 'VARP',
6721
    0x00C3: 'DSTDEVP',
6722
    0x00C4: 'DVARP',
6723
    0x00C5: 'TRUNC',
6724
    0x00C6: 'ISLOGICAL',
6725
    0x00C7: 'DCOUNTA',
6726
    0x00C8: 'DELETE.BAR',
6727
    0x00C9: 'UNREGISTER',
6728
    0x00CC: 'USDOLLAR',
6729
    0x00CD: 'FINDB',
6730
    0x00CE: 'SEARCHB',
6731
    0x00CF: 'REPLACEB',
6732
    0x00D0: 'LEFTB',
6733
    0x00D1: 'RIGHTB',
6734
    0x00D2: 'MIDB',
6735
    0x00D3: 'LENB',
6736
    0x00D4: 'ROUNDUP',
6737
    0x00D5: 'ROUNDDOWN',
6738
    0x00D6: 'ASC',
6739
    0x00D7: 'DBCS',
6740
    0x00D8: 'RANK',
6741
    0x00DB: 'ADDRESS',
6742
    0x00DC: 'DAYS360',
6743
    0x00DD: 'TODAY',
6744
    0x00DE: 'VDB',
6745
    0x00DF: 'ELSE',
6746
    0x00E0: 'ELSE.IF',
6747
    0x00E1: 'END.IF',
6748
    0x00E2: 'FOR.CELL',
6749
    0x00E3: 'MEDIAN',
6750
    0x00E4: 'SUMPRODUCT',
6751
    0x00E5: 'SINH',
6752
    0x00E6: 'COSH',
6753
    0x00E7: 'TANH',
6754
    0x00E8: 'ASINH',
6755
    0x00E9: 'ACOSH',
6756
    0x00EA: 'ATANH',
6757
    0x00EB: 'DGET',
6758
    0x00EC: 'CREATE.OBJECT',
6759
    0x00ED: 'VOLATILE',
6760
    0x00EE: 'LAST.ERROR',
6761
    0x00EF: 'CUSTOM.UNDO',
6762
    0x00F0: 'CUSTOM.REPEAT',
6763
    0x00F1: 'FORMULA.CONVERT',
6764
    0x00F2: 'GET.LINK.INFO',
6765
    0x00F3: 'TEXT.BOX',
6766
    0x00F4: 'INFO',
6767
    0x00F5: 'GROUP',
6768
    0x00F6: 'GET.OBJECT',
6769
    0x00F7: 'DB',
6770
    0x00F8: 'PAUSE',
6771
    0x00FB: 'RESUME',
6772
    0x00FC: 'FREQUENCY',
6773
    0x00FD: 'ADD.TOOLBAR',
6774
    0x00FE: 'DELETE.TOOLBAR',
6775
    0x00FF: 'User',
6776
    0x0100: 'RESET.TOOLBAR',
6777
    0x0101: 'EVALUATE',
6778
    0x0102: 'GET.TOOLBAR',
6779
    0x0103: 'GET.TOOL',
6780
    0x0104: 'SPELLING.CHECK',
6781
    0x0105: 'ERROR.TYPE',
6782
    0x0106: 'APP.TITLE',
6783
    0x0107: 'WINDOW.TITLE',
6784
    0x0108: 'SAVE.TOOLBAR',
6785
    0x0109: 'ENABLE.TOOL',
6786
    0x010A: 'PRESS.TOOL',
6787
    0x010B: 'REGISTER.ID',
6788
    0x010C: 'GET.WORKBOOK',
6789
    0x010D: 'AVEDEV',
6790
    0x010E: 'BETADIST',
6791
    0x010F: 'GAMMALN',
6792
    0x0110: 'BETAINV',
6793
    0x0111: 'BINOMDIST',
6794
    0x0112: 'CHIDIST',
6795
    0x0113: 'CHIINV',
6796
    0x0114: 'COMBIN',
6797
    0x0115: 'CONFIDENCE',
6798
    0x0116: 'CRITBINOM',
6799
    0x0117: 'EVEN',
6800
    0x0118: 'EXPONDIST',
6801
    0x0119: 'FDIST',
6802
    0x011A: 'FINV',
6803
    0x011B: 'FISHER',
6804
    0x011C: 'FISHERINV',
6805
    0x011D: 'FLOOR',
6806
    0x011E: 'GAMMADIST',
6807
    0x011F: 'GAMMAINV',
6808
    0x0120: 'CEILING',
6809
    0x0121: 'HYPGEOMDIST',
6810
    0x0122: 'LOGNORMDIST',
6811
    0x0123: 'LOGINV',
6812
    0x0124: 'NEGBINOMDIST',
6813
    0x0125: 'NORMDIST',
6814
    0x0126: 'NORMSDIST',
6815
    0x0127: 'NORMINV',
6816
    0x0128: 'NORMSINV',
6817
    0x0129: 'STANDARDIZE',
6818
    0x012A: 'ODD',
6819
    0x012B: 'PERMUT',
6820
    0x012C: 'POISSON',
6821
    0x012D: 'TDIST',
6822
    0x012E: 'WEIBULL',
6823
    0x012F: 'SUMXMY2',
6824
    0x0130: 'SUMX2MY2',
6825
    0x0131: 'SUMX2PY2',
6826
    0x0132: 'CHITEST',
6827
    0x0133: 'CORREL',
6828
    0x0134: 'COVAR',
6829
    0x0135: 'FORECAST',
6830
    0x0136: 'FTEST',
6831
    0x0137: 'INTERCEPT',
6832
    0x0138: 'PEARSON',
6833
    0x0139: 'RSQ',
6834
    0x013A: 'STEYX',
6835
    0x013B: 'SLOPE',
6836
    0x013C: 'TTEST',
6837
    0x013D: 'PROB',
6838
    0x013E: 'DEVSQ',
6839
    0x013F: 'GEOMEAN',
6840
    0x0140: 'HARMEAN',
6841
    0x0141: 'SUMSQ',
6842
    0x0142: 'KURT',
6843
    0x0143: 'SKEW',
6844
    0x0144: 'ZTEST',
6845
    0x0145: 'LARGE',
6846
    0x0146: 'SMALL',
6847
    0x0147: 'QUARTILE',
6848
    0x0148: 'PERCENTILE',
6849
    0x0149: 'PERCENTRANK',
6850
    0x014A: 'MODE',
6851
    0x014B: 'TRIMMEAN',
6852
    0x014C: 'TINV',
6853
    0x014E: 'MOVIE.COMMAND',
6854
    0x014F: 'GET.MOVIE',
6855
    0x0150: 'CONCATENATE',
6856
    0x0151: 'POWER',
6857
    0x0152: 'PIVOT.ADD.DATA',
6858
    0x0153: 'GET.PIVOT.TABLE',
6859
    0x0154: 'GET.PIVOT.FIELD',
6860
    0x0155: 'GET.PIVOT.ITEM',
6861
    0x0156: 'RADIANS',
6862
    0x0157: 'DEGREES',
6863
    0x0158: 'SUBTOTAL',
6864
    0x0159: 'SUMIF',
6865
    0x015A: 'COUNTIF',
6866
    0x015B: 'COUNTBLANK',
6867
    0x015C: 'SCENARIO.GET',
6868
    0x015D: 'OPTIONS.LISTS.GET',
6869
    0x015E: 'ISPMT',
6870
    0x015F: 'DATEDIF',
6871
    0x0160: 'DATESTRING',
6872
    0x0161: 'NUMBERSTRING',
6873
    0x0162: 'ROMAN',
6874
    0x0163: 'OPEN.DIALOG',
6875
    0x0164: 'SAVE.DIALOG',
6876
    0x0165: 'VIEW.GET',
6877
    0x0166: 'GETPIVOTDATA',
6878
    0x0167: 'HYPERLINK',
6879
    0x0168: 'PHONETIC',
6880
    0x0169: 'AVERAGEA',
6881
    0x016A: 'MAXA',
6882
    0x016B: 'MINA',
6883
    0x016C: 'STDEVPA',
6884
    0x016D: 'VARPA',
6885
    0x016E: 'STDEVA',
6886
    0x016F: 'VARA',
6887
    0x0170: 'BAHTTEXT',
6888
    0x0171: 'THAIDAYOFWEEK',
6889
    0x0172: 'THAIDIGIT',
6890
    0x0173: 'THAIMONTHOFYEAR',
6891
    0x0174: 'THAINUMSOUND',
6892
    0x0175: 'THAINUMSTRING',
6893
    0x0176: 'THAISTRINGLENGTH',
6894
    0x0177: 'ISTHAIDIGIT',
6895
    0x0178: 'ROUNDBAHTDOWN',
6896
    0x0179: 'ROUNDBAHTUP',
6897
    0x017A: 'THAIYEAR',
6898
    0x017B: 'RTD'
6899
};
6900
var FtabArgc = {
6901
    0x0002: 1, /* ISNA */
6902
    0x0003: 1, /* ISERROR */
6903
    0x000F: 1, /* SIN */
6904
    0x0010: 1, /* COS */
6905
    0x0011: 1, /* TAN */
6906
    0x0012: 1, /* ATAN */
6907
    0x0014: 1, /* SQRT */
6908
    0x0015: 1, /* EXP */
6909
    0x0016: 1, /* LN */
6910
    0x0017: 1, /* LOG10 */
6911
    0x0018: 1, /* ABS */
6912
    0x0019: 1, /* INT */
6913
    0x001A: 1, /* SIGN */
6914
    0x001B: 2, /* ROUND */
6915
    0x001E: 2, /* REPT */
6916
    0x001F: 3, /* MID */
6917
    0x0020: 1, /* LEN */
6918
    0x0021: 1, /* VALUE */
6919
    0x0026: 1, /* NOT */
6920
    0x0027: 2, /* MOD */
6921
    0x0028: 3, /* DCOUNT */
6922
    0x0029: 3, /* DSUM */
6923
    0x002A: 3, /* DAVERAGE */
6924
    0x002B: 3, /* DMIN */
6925
    0x002C: 3, /* DMAX */
6926
    0x002D: 3, /* DSTDEV */
6927
    0x002F: 3, /* DVAR */
6928
    0x0030: 2, /* TEXT */
6929
    0x0035: 1, /* GOTO */
6930
    0x003D: 3, /* MIRR */
6931
    0x0041: 3, /* DATE */
6932
    0x0042: 3, /* TIME */
6933
    0x0043: 1, /* DAY */
6934
    0x0044: 1, /* MONTH */
6935
    0x0045: 1, /* YEAR */
6936
    0x0047: 1, /* HOUR */
6937
    0x0048: 1, /* MINUTE */
6938
    0x0049: 1, /* SECOND */
6939
    0x004B: 1, /* AREAS */
6940
    0x004C: 1, /* ROWS */
6941
    0x004D: 1, /* COLUMNS */
6942
    0x004F: 2, /* ABSREF */
6943
    0x0050: 2, /* RELREF */
6944
    0x0053: 1, /* TRANSPOSE */
6945
    0x0056: 1, /* TYPE */
6946
    0x005A: 1, /* DEREF */
6947
    0x0061: 2, /* ATAN2 */
6948
    0x0062: 1, /* ASIN */
6949
    0x0063: 1, /* ACOS */
6950
    0x0069: 1, /* ISREF */
6951
    0x006F: 1, /* CHAR */
6952
    0x0070: 1, /* LOWER */
6953
    0x0071: 1, /* UPPER */
6954
    0x0072: 1, /* PROPER */
6955
    0x0075: 2, /* EXACT */
6956
    0x0076: 1, /* TRIM */
6957
    0x0077: 4, /* REPLACE */
6958
    0x0079: 1, /* CODE */
6959
    0x007E: 1, /* ISERR */
6960
    0x007F: 1, /* ISTEXT */
6961
    0x0080: 1, /* ISNUMBER */
6962
    0x0081: 1, /* ISBLANK */
6963
    0x0082: 1, /* T */
6964
    0x0083: 1, /* N */
6965
    0x0085: 1, /* FCLOSE */
6966
    0x0086: 1, /* FSIZE */
6967
    0x0087: 1, /* FREADLN */
6968
    0x0088: 2, /* FREAD */
6969
    0x0089: 2, /* FWRITELN */
6970
    0x008A: 2, /* FWRITE */
6971
    0x008C: 1, /* DATEVALUE */
6972
    0x008D: 1, /* TIMEVALUE */
6973
    0x008E: 3, /* SLN */
6974
    0x008F: 4, /* SYD */
6975
    0x00A2: 1, /* CLEAN */
6976
    0x00A3: 1, /* MDETERM */
6977
    0x00A4: 1, /* MINVERSE */
6978
    0x00A5: 2, /* MMULT */
6979
    0x00AC: 1, /* WHILE */
6980
    0x00AF: 2, /* INITIATE */
6981
    0x00B0: 2, /* REQUEST */
6982
    0x00B1: 3, /* POKE */
6983
    0x00B2: 2, /* EXECUTE */
6984
    0x00B3: 1, /* TERMINATE */
6985
    0x00B8: 1, /* FACT */
6986
    0x00BD: 3, /* DPRODUCT */
6987
    0x00BE: 1, /* ISNONTEXT */
6988
    0x00C3: 3, /* DSTDEVP */
6989
    0x00C4: 3, /* DVARP */
6990
    0x00C6: 1, /* ISLOGICAL */
6991
    0x00C7: 3, /* DCOUNTA */
6992
    0x00C9: 1, /* UNREGISTER */
6993
    0x00CF: 4, /* REPLACEB */
6994
    0x00D2: 3, /* MIDB */
6995
    0x00D3: 1, /* LENB */
6996
    0x00D4: 2, /* ROUNDUP */
6997
    0x00D5: 2, /* ROUNDDOWN */
6998
    0x00D6: 1, /* ASC */
6999
    0x00D7: 1, /* DBCS */
7000
    0x00E5: 1, /* SINH */
7001
    0x00E6: 1, /* COSH */
7002
    0x00E7: 1, /* TANH */
7003
    0x00E8: 1, /* ASINH */
7004
    0x00E9: 1, /* ACOSH */
7005
    0x00EA: 1, /* ATANH */
7006
    0x00EB: 3, /* DGET */
7007
    0x00F4: 1, /* INFO */
7008
    0x00FC: 2, /* FREQUENCY */
7009
    0x0101: 1, /* EVALUATE */
7010
    0x0105: 1, /* ERROR.TYPE */
7011
    0x010F: 1, /* GAMMALN */
7012
    0x0111: 4, /* BINOMDIST */
7013
    0x0112: 2, /* CHIDIST */
7014
    0x0113: 2, /* CHIINV */
7015
    0x0114: 2, /* COMBIN */
7016
    0x0115: 3, /* CONFIDENCE */
7017
    0x0116: 3, /* CRITBINOM */
7018
    0x0117: 1, /* EVEN */
7019
    0x0118: 3, /* EXPONDIST */
7020
    0x0119: 3, /* FDIST */
7021
    0x011A: 3, /* FINV */
7022
    0x011B: 1, /* FISHER */
7023
    0x011C: 1, /* FISHERINV */
7024
    0x011D: 2, /* FLOOR */
7025
    0x011E: 4, /* GAMMADIST */
7026
    0x011F: 3, /* GAMMAINV */
7027
    0x0120: 2, /* CEILING */
7028
    0x0121: 4, /* HYPGEOMDIST */
7029
    0x0122: 3, /* LOGNORMDIST */
7030
    0x0123: 3, /* LOGINV */
7031
    0x0124: 3, /* NEGBINOMDIST */
7032
    0x0125: 4, /* NORMDIST */
7033
    0x0126: 1, /* NORMSDIST */
7034
    0x0127: 3, /* NORMINV */
7035
    0x0128: 1, /* NORMSINV */
7036
    0x0129: 3, /* STANDARDIZE */
7037
    0x012A: 1, /* ODD */
7038
    0x012B: 2, /* PERMUT */
7039
    0x012C: 3, /* POISSON */
7040
    0x012D: 3, /* TDIST */
7041
    0x012E: 4, /* WEIBULL */
7042
    0x012F: 2, /* SUMXMY2 */
7043
    0x0130: 2, /* SUMX2MY2 */
7044
    0x0131: 2, /* SUMX2PY2 */
7045
    0x0132: 2, /* CHITEST */
7046
    0x0133: 2, /* CORREL */
7047
    0x0134: 2, /* COVAR */
7048
    0x0135: 3, /* FORECAST */
7049
    0x0136: 2, /* FTEST */
7050
    0x0137: 2, /* INTERCEPT */
7051
    0x0138: 2, /* PEARSON */
7052
    0x0139: 2, /* RSQ */
7053
    0x013A: 2, /* STEYX */
7054
    0x013B: 2, /* SLOPE */
7055
    0x013C: 4, /* TTEST */
7056
    0x0145: 2, /* LARGE */
7057
    0x0146: 2, /* SMALL */
7058
    0x0147: 2, /* QUARTILE */
7059
    0x0148: 2, /* PERCENTILE */
7060
    0x014B: 2, /* TRIMMEAN */
7061
    0x014C: 2, /* TINV */
7062
    0x0151: 2, /* POWER */
7063
    0x0156: 1, /* RADIANS */
7064
    0x0157: 1, /* DEGREES */
7065
    0x015A: 2, /* COUNTIF */
7066
    0x015B: 1, /* COUNTBLANK */
7067
    0x015E: 4, /* ISPMT */
7068
    0x015F: 3, /* DATEDIF */
7069
    0x0160: 1, /* DATESTRING */
7070
    0x0161: 2, /* NUMBERSTRING */
7071
    0x0168: 1, /* PHONETIC */
7072
    0x0170: 1, /* BAHTTEXT */
7073
    0x0171: 1, /* THAIDAYOFWEEK */
7074
    0x0172: 1, /* THAIDIGIT */
7075
    0x0173: 1, /* THAIMONTHOFYEAR */
7076
    0x0174: 1, /* THAINUMSOUND */
7077
    0x0175: 1, /* THAINUMSTRING */
7078
    0x0176: 1, /* THAISTRINGLENGTH */
7079
    0x0177: 1, /* ISTHAIDIGIT */
7080
    0x0178: 1, /* ROUNDBAHTDOWN */
7081
    0x0179: 1, /* ROUNDBAHTUP */
7082
    0x017A: 1, /* THAIYEAR */
7083
    0xFFFF: 0
7084
};
7085
/* [MS-XLSX] 2.2.3 Functions */
7086
var XLSXFutureFunctions = {
7087
    "_xlfn.ACOT": "ACOT",
7088
    "_xlfn.ACOTH": "ACOTH",
7089
    "_xlfn.AGGREGATE": "AGGREGATE",
7090
    "_xlfn.ARABIC": "ARABIC",
7091
    "_xlfn.AVERAGEIF": "AVERAGEIF",
7092
    "_xlfn.AVERAGEIFS": "AVERAGEIFS",
7093
    "_xlfn.BASE": "BASE",
7094
    "_xlfn.BETA.DIST": "BETA.DIST",
7095
    "_xlfn.BETA.INV": "BETA.INV",
7096
    "_xlfn.BINOM.DIST": "BINOM.DIST",
7097
    "_xlfn.BINOM.DIST.RANGE": "BINOM.DIST.RANGE",
7098
    "_xlfn.BINOM.INV": "BINOM.INV",
7099
    "_xlfn.BITAND": "BITAND",
7100
    "_xlfn.BITLSHIFT": "BITLSHIFT",
7101
    "_xlfn.BITOR": "BITOR",
7102
    "_xlfn.BITRSHIFT": "BITRSHIFT",
7103
    "_xlfn.BITXOR": "BITXOR",
7104
    "_xlfn.CEILING.MATH": "CEILING.MATH",
7105
    "_xlfn.CEILING.PRECISE": "CEILING.PRECISE",
7106
    "_xlfn.CHISQ.DIST": "CHISQ.DIST",
7107
    "_xlfn.CHISQ.DIST.RT": "CHISQ.DIST.RT",
7108
    "_xlfn.CHISQ.INV": "CHISQ.INV",
7109
    "_xlfn.CHISQ.INV.RT": "CHISQ.INV.RT",
7110
    "_xlfn.CHISQ.TEST": "CHISQ.TEST",
7111
    "_xlfn.COMBINA": "COMBINA",
7112
    "_xlfn.CONFIDENCE.NORM": "CONFIDENCE.NORM",
7113
    "_xlfn.CONFIDENCE.T": "CONFIDENCE.T",
7114
    "_xlfn.COT": "COT",
7115
    "_xlfn.COTH": "COTH",
7116
    "_xlfn.COUNTIFS": "COUNTIFS",
7117
    "_xlfn.COVARIANCE.P": "COVARIANCE.P",
7118
    "_xlfn.COVARIANCE.S": "COVARIANCE.S",
7119
    "_xlfn.CSC": "CSC",
7120
    "_xlfn.CSCH": "CSCH",
7121
    "_xlfn.DAYS": "DAYS",
7122
    "_xlfn.DECIMAL": "DECIMAL",
7123
    "_xlfn.ECMA.CEILING": "ECMA.CEILING",
7124
    "_xlfn.ERF.PRECISE": "ERF.PRECISE",
7125
    "_xlfn.ERFC.PRECISE": "ERFC.PRECISE",
7126
    "_xlfn.EXPON.DIST": "EXPON.DIST",
7127
    "_xlfn.F.DIST": "F.DIST",
7128
    "_xlfn.F.DIST.RT": "F.DIST.RT",
7129
    "_xlfn.F.INV": "F.INV",
7130
    "_xlfn.F.INV.RT": "F.INV.RT",
7131
    "_xlfn.F.TEST": "F.TEST",
7132
    "_xlfn.FILTERXML": "FILTERXML",
7133
    "_xlfn.FLOOR.MATH": "FLOOR.MATH",
7134
    "_xlfn.FLOOR.PRECISE": "FLOOR.PRECISE",
7135
    "_xlfn.FORMULATEXT": "FORMULATEXT",
7136
    "_xlfn.GAMMA": "GAMMA",
7137
    "_xlfn.GAMMA.DIST": "GAMMA.DIST",
7138
    "_xlfn.GAMMA.INV": "GAMMA.INV",
7139
    "_xlfn.GAMMALN.PRECISE": "GAMMALN.PRECISE",
7140
    "_xlfn.GAUSS": "GAUSS",
7141
    "_xlfn.HYPGEOM.DIST": "HYPGEOM.DIST",
7142
    "_xlfn.IFNA": "IFNA",
7143
    "_xlfn.IFERROR": "IFERROR",
7144
    "_xlfn.IMCOSH": "IMCOSH",
7145
    "_xlfn.IMCOT": "IMCOT",
7146
    "_xlfn.IMCSC": "IMCSC",
7147
    "_xlfn.IMCSCH": "IMCSCH",
7148
    "_xlfn.IMSEC": "IMSEC",
7149
    "_xlfn.IMSECH": "IMSECH",
7150
    "_xlfn.IMSINH": "IMSINH",
7151
    "_xlfn.IMTAN": "IMTAN",
7152
    "_xlfn.ISFORMULA": "ISFORMULA",
7153
    "_xlfn.ISO.CEILING": "ISO.CEILING",
7154
    "_xlfn.ISOWEEKNUM": "ISOWEEKNUM",
7155
    "_xlfn.LOGNORM.DIST": "LOGNORM.DIST",
7156
    "_xlfn.LOGNORM.INV": "LOGNORM.INV",
7157
    "_xlfn.MODE.MULT": "MODE.MULT",
7158
    "_xlfn.MODE.SNGL": "MODE.SNGL",
7159
    "_xlfn.MUNIT": "MUNIT",
7160
    "_xlfn.NEGBINOM.DIST": "NEGBINOM.DIST",
7161
    "_xlfn.NETWORKDAYS.INTL": "NETWORKDAYS.INTL",
7162
    "_xlfn.NIGBINOM": "NIGBINOM",
7163
    "_xlfn.NORM.DIST": "NORM.DIST",
7164
    "_xlfn.NORM.INV": "NORM.INV",
7165
    "_xlfn.NORM.S.DIST": "NORM.S.DIST",
7166
    "_xlfn.NORM.S.INV": "NORM.S.INV",
7167
    "_xlfn.NUMBERVALUE": "NUMBERVALUE",
7168
    "_xlfn.PDURATION": "PDURATION",
7169
    "_xlfn.PERCENTILE.EXC": "PERCENTILE.EXC",
7170
    "_xlfn.PERCENTILE.INC": "PERCENTILE.INC",
7171
    "_xlfn.PERCENTRANK.EXC": "PERCENTRANK.EXC",
7172
    "_xlfn.PERCENTRANK.INC": "PERCENTRANK.INC",
7173
    "_xlfn.PERMUTATIONA": "PERMUTATIONA",
7174
    "_xlfn.PHI": "PHI",
7175
    "_xlfn.POISSON.DIST": "POISSON.DIST",
7176
    "_xlfn.QUARTILE.EXC": "QUARTILE.EXC",
7177
    "_xlfn.QUARTILE.INC": "QUARTILE.INC",
7178
    "_xlfn.QUERYSTRING": "QUERYSTRING",
7179
    "_xlfn.RANK.AVG": "RANK.AVG",
7180
    "_xlfn.RANK.EQ": "RANK.EQ",
7181
    "_xlfn.RRI": "RRI",
7182
    "_xlfn.SEC": "SEC",
7183
    "_xlfn.SECH": "SECH",
7184
    "_xlfn.SHEET": "SHEET",
7185
    "_xlfn.SHEETS": "SHEETS",
7186
    "_xlfn.SKEW.P": "SKEW.P",
7187
    "_xlfn.STDEV.P": "STDEV.P",
7188
    "_xlfn.STDEV.S": "STDEV.S",
7189
    "_xlfn.SUMIFS": "SUMIFS",
7190
    "_xlfn.T.DIST": "T.DIST",
7191
    "_xlfn.T.DIST.2T": "T.DIST.2T",
7192
    "_xlfn.T.DIST.RT": "T.DIST.RT",
7193
    "_xlfn.T.INV": "T.INV",
7194
    "_xlfn.T.INV.2T": "T.INV.2T",
7195
    "_xlfn.T.TEST": "T.TEST",
7196
    "_xlfn.UNICHAR": "UNICHAR",
7197
    "_xlfn.UNICODE": "UNICODE",
7198
    "_xlfn.VAR.P": "VAR.P",
7199
    "_xlfn.VAR.S": "VAR.S",
7200
    "_xlfn.WEBSERVICE": "WEBSERVICE",
7201
    "_xlfn.WEIBULL.DIST": "WEIBULL.DIST",
7202
    "_xlfn.WORKDAY.INTL": "WORKDAY.INTL",
7203
    "_xlfn.XOR": "XOR",
7204
    "_xlfn.Z.TEST": "Z.TEST"
7205
};
7206
 
7207
var strs = {}; // shared strings
7208
var _ssfopts = {}; // spreadsheet formatting options
7209
 
7210
RELS.WS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet";
7211
 
7212
function get_sst_id(sst, str) {
7213
    for(var i = 0, len = sst.length; i < len; ++i) if(sst[i].t === str) { sst.Count ++; return i; }
7214
    sst[len] = {t:str}; sst.Count ++; sst.Unique ++; return len;
7215
}
7216
 
7217
function get_cell_style(styles, cell, opts) {
7218
    var z = opts.revssf[cell.z != null ? cell.z : "General"];
7219
    for(var i = 0, len = styles.length; i != len; ++i) if(styles[i].numFmtId === z) return i;
7220
    styles[len] = {
7221
        numFmtId:z,
7222
        fontId:0,
7223
        fillId:0,
7224
        borderId:0,
7225
        xfId:0,
7226
        applyNumberFormat:1
7227
    };
7228
    return len;
7229
}
7230
 
7231
function safe_format(p, fmtid, fillid, opts) {
7232
    try {
7233
        if(p.t === 'e') p.w = p.w || BErr[p.v];
7234
        else if(fmtid === 0) {
7235
            if(p.t === 'n') {
7236
                if((p.v|0) === p.v) p.w = SSF._general_int(p.v,_ssfopts);
7237
                else p.w = SSF._general_num(p.v,_ssfopts);
7238
            }
7239
            else if(p.t === 'd') {
7240
                var dd = datenum(p.v);
7241
                if((dd|0) === dd) p.w = SSF._general_int(dd,_ssfopts);
7242
                else p.w = SSF._general_num(dd,_ssfopts);
7243
            }
7244
            else if(p.v === undefined) return "";
7245
            else p.w = SSF._general(p.v,_ssfopts);
7246
        }
7247
        else if(p.t === 'd') p.w = SSF.format(fmtid,datenum(p.v),_ssfopts);
7248
        else p.w = SSF.format(fmtid,p.v,_ssfopts);
7249
        if(opts.cellNF) p.z = SSF._table[fmtid];
7250
    } catch(e) { if(opts.WTF) throw e; }
7251
    if(fillid) try {
7252
        p.s = styles.Fills[fillid];
7253
        if (p.s.fgColor && p.s.fgColor.theme) {
7254
            p.s.fgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.fgColor.theme].rgb, p.s.fgColor.tint || 0);
7255
            if(opts.WTF) p.s.fgColor.raw_rgb = themes.themeElements.clrScheme[p.s.fgColor.theme].rgb;
7256
        }
7257
        if (p.s.bgColor && p.s.bgColor.theme) {
7258
            p.s.bgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.bgColor.theme].rgb, p.s.bgColor.tint || 0);
7259
            if(opts.WTF) p.s.bgColor.raw_rgb = themes.themeElements.clrScheme[p.s.bgColor.theme].rgb;
7260
        }
7261
    } catch(e) { if(opts.WTF) throw e; }
7262
}
7263
function parse_ws_xml_dim(ws, s) {
7264
    var d = safe_decode_range(s);
7265
    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);
7266
}
7267
var mergecregex = /<mergeCell ref="[A-Z0-9:]+"\s*\/>/g;
7268
var sheetdataregex = /<(?:\w+:)?sheetData>([^\u2603]*)<\/(?:\w+:)?sheetData>/;
7269
var hlinkregex = /<hyperlink[^>]*\/>/g;
7270
var dimregex = /"(\w*:\w*)"/;
7271
var colregex = /<col[^>]*\/>/g;
7272
/* 18.3 Worksheets */
7273
function parse_ws_xml(data, opts, rels) {
7274
    if(!data) return data;
7275
    /* 18.3.1.99 worksheet CT_Worksheet */
7276
    var s = {};
7277
 
7278
    /* 18.3.1.35 dimension CT_SheetDimension ? */
7279
    var ridx = data.indexOf("<dimension");
7280
    if(ridx > 0) {
7281
        var ref = data.substr(ridx,50).match(dimregex);
7282
        if(ref != null) parse_ws_xml_dim(s, ref[1]);
7283
    }
7284
 
7285
    /* 18.3.1.55 mergeCells CT_MergeCells */
7286
    var mergecells = [];
7287
    if(data.indexOf("</mergeCells>")!==-1) {
7288
        var merges = data.match(mergecregex);
7289
        for(ridx = 0; ridx != merges.length; ++ridx)
7290
            mergecells[ridx] = safe_decode_range(merges[ridx].substr(merges[ridx].indexOf("\"")+1));
7291
    }
7292
 
7293
    /* 18.3.1.17 cols CT_Cols */
7294
    var columns = [];
7295
    if(opts.cellStyles && data.indexOf("</cols>")!==-1) {
7296
        /* 18.3.1.13 col CT_Col */
7297
        var cols = data.match(colregex);
7298
        parse_ws_xml_cols(columns, cols);
7299
    }
7300
 
7301
    var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} };
7302
 
7303
    /* 18.3.1.80 sheetData CT_SheetData ? */
7304
    var mtch=data.match(sheetdataregex);
7305
    if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess);
7306
 
7307
    /* 18.3.1.48 hyperlinks CT_Hyperlinks */
7308
    if(data.indexOf("</hyperlinks>")!==-1) parse_ws_xml_hlinks(s, data.match(hlinkregex), rels);
7309
 
7310
    if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
7311
    if(opts.sheetRows > 0 && s["!ref"]) {
7312
        var tmpref = safe_decode_range(s["!ref"]);
7313
        if(opts.sheetRows < +tmpref.e.r) {
7314
            tmpref.e.r = opts.sheetRows - 1;
7315
            if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
7316
            if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
7317
            if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c;
7318
            if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c;
7319
            s["!fullref"] = s["!ref"];
7320
            s["!ref"] = encode_range(tmpref);
7321
        }
7322
    }
7323
    if(mergecells.length > 0) s["!merges"] = mergecells;
7324
    if(columns.length > 0) s["!cols"] = columns;
7325
    return s;
7326
}
7327
 
7328
function write_ws_xml_merges(merges) {
7329
    if(merges.length == 0) return "";
7330
    var o = '<mergeCells count="' + merges.length + '">';
7331
    for(var i = 0; i != merges.length; ++i) o += '<mergeCell ref="' + encode_range(merges[i]) + '"/>';
7332
    return o + '</mergeCells>';
7333
}
7334
 
7335
function parse_ws_xml_hlinks(s, data, rels) {
7336
    for(var i = 0; i != data.length; ++i) {
7337
        var val = parsexmltag(data[i], true);
7338
        if(!val.ref) return;
7339
        var rel = rels ? rels['!id'][val.id] : null;
7340
        if(rel) {
7341
            val.Target = rel.Target;
7342
            if(val.location) val.Target += "#"+val.location;
7343
            val.Rel = rel;
7344
        } else {
7345
            val.Target = val.location;
7346
            rel = {Target: val.location, TargetMode: 'Internal'};
7347
            val.Rel = rel;
7348
        }
7349
        var rng = safe_decode_range(val.ref);
7350
        for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
7351
            var addr = encode_cell({c:C,r:R});
7352
            if(!s[addr]) s[addr] = {t:"stub",v:undefined};
7353
            s[addr].l = val;
7354
        }
7355
    }
7356
}
7357
 
7358
function parse_ws_xml_cols(columns, cols) {
7359
    var seencol = false;
7360
    for(var coli = 0; coli != cols.length; ++coli) {
7361
        var coll = parsexmltag(cols[coli], true);
7362
        var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
7363
        delete coll.min; delete coll.max;
7364
        if(!seencol && coll.width) { seencol = true; find_mdw(+coll.width, coll); }
7365
        if(coll.width) {
7366
            coll.wpx = width2px(+coll.width);
7367
            coll.wch = px2char(coll.wpx);
7368
            coll.MDW = MDW;
7369
        }
7370
        while(colm <= colM) columns[colm++] = coll;
7371
    }
7372
}
7373
 
7374
function write_ws_xml_cols(ws, cols) {
7375
    var o = ["<cols>"], col, width;
7376
    for(var i = 0; i != cols.length; ++i) {
7377
        if(!(col = cols[i])) continue;
7378
        var p = {min:i+1,max:i+1};
7379
        /* wch (chars), wpx (pixels) */
7380
        width = -1;
7381
        if(col.wpx) width = px2char(col.wpx);
7382
        else if(col.wch) width = col.wch;
7383
        if(width > -1) { p.width = char2width(width); p.customWidth= 1; }
7384
        o[o.length] = (writextag('col', null, p));
7385
    }
7386
    o[o.length] = "</cols>";
7387
    return o.join("");
7388
}
7389
 
7390
function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
7391
    if(cell.v === undefined) return "";
7392
    var vv = "";
7393
    var oldt = cell.t, oldv = cell.v;
7394
    switch(cell.t) {
7395
        case 'b': vv = cell.v ? "1" : "0"; break;
7396
        case 'n': vv = ''+cell.v; break;
7397
        case 'e': vv = BErr[cell.v]; break;
7398
        case 'd':
7399
            if(opts.cellDates) vv = new Date(cell.v).toISOString();
7400
            else {
7401
                cell.t = 'n';
7402
                vv = ''+(cell.v = datenum(cell.v));
7403
                if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
7404
            }
7405
            break;
7406
        default: vv = cell.v; break;
7407
    }
7408
    var v = writetag('v', escapexml(vv)), o = {r:ref};
7409
    /* TODO: cell style */
7410
    var os = get_cell_style(opts.cellXfs, cell, opts);
7411
    if(os !== 0) o.s = os;
7412
    switch(cell.t) {
7413
        case 'n': break;
7414
        case 'd': o.t = "d"; break;
7415
        case 'b': o.t = "b"; break;
7416
        case 'e': o.t = "e"; break;
7417
        default:
7418
            if(opts.bookSST) {
7419
                v = writetag('v', ''+get_sst_id(opts.Strings, cell.v));
7420
                o.t = "s"; break;
7421
            }
7422
            o.t = "str"; break;
7423
    }
7424
    if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; }
7425
    return writextag('c', v, o);
7426
}
7427
 
7428
var parse_ws_xml_data = (function parse_ws_xml_data_factory() {
7429
    var cellregex = /<(?:\w+:)?c[ >]/, rowregex = /<\/(?:\w+:)?row>/;
7430
    var rregex = /r=["']([^"']*)["']/, isregex = /<is>([\S\s]*?)<\/is>/;
7431
    var match_v = matchtag("v"), match_f = matchtag("f");
7432
 
7433
return function parse_ws_xml_data(sdata, s, opts, guess) {
7434
    var ri = 0, x = "", cells = [], cref = [], idx = 0, i=0, cc=0, d="", p;
7435
    var tag, tagr = 0, tagc = 0;
7436
    var sstr;
7437
    var fmtid = 0, fillid = 0, do_format = Array.isArray(styles.CellXf), cf;
7438
    for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
7439
        x = marr[mt].trim();
7440
        var xlen = x.length;
7441
        if(xlen === 0) continue;
7442
 
7443
        /* 18.3.1.73 row CT_Row */
7444
        for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
7445
        tag = parsexmltag(x.substr(0,ri), true);
7446
        /* SpreadSheetGear uses implicit r/c */
7447
        tagr = typeof tag.r !== 'undefined' ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
7448
        if(opts.sheetRows && opts.sheetRows < tagr) continue;
7449
        if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
7450
        if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
7451
 
7452
        /* 18.3.1.4 c CT_Cell */
7453
        cells = x.substr(ri).split(cellregex);
7454
        for(ri = typeof tag.r === 'undefined' ? 0 : 1; ri != cells.length; ++ri) {
7455
            x = cells[ri].trim();
7456
            if(x.length === 0) continue;
7457
            cref = x.match(rregex); idx = ri; i=0; cc=0;
7458
            x = "<c " + (x.substr(0,1)=="<"?">":"") + x;
7459
            if(cref !== null && cref.length === 2) {
7460
                idx = 0; d=cref[1];
7461
                for(i=0; i != d.length; ++i) {
7462
                    if((cc=d.charCodeAt(i)-64) < 1 || cc > 26) break;
7463
                    idx = 26*idx + cc;
7464
                }
7465
                --idx;
7466
                tagc = idx;
7467
            } else ++tagc;
7468
            for(i = 0; i != x.length; ++i) if(x.charCodeAt(i) === 62) break; ++i;
7469
            tag = parsexmltag(x.substr(0,i), true);
7470
            if(!tag.r) tag.r = utils.encode_cell({r:tagr-1, c:tagc});
7471
            d = x.substr(i);
7472
            p = {t:""};
7473
 
7474
            if((cref=d.match(match_v))!== null && cref[1] !== '') p.v=unescapexml(cref[1]);
7475
            if(opts.cellFormula && (cref=d.match(match_f))!== null) p.f=unescapexml(cref[1]);
7476
 
7477
            /* SCHEMA IS ACTUALLY INCORRECT HERE.  IF A CELL HAS NO T, EMIT "" */
7478
            if(tag.t === undefined && p.v === undefined) {
7479
                if(!opts.sheetStubs) continue;
7480
                p.t = "stub";
7481
            }
7482
            else p.t = tag.t || "n";
7483
            if(guess.s.c > idx) guess.s.c = idx;
7484
            if(guess.e.c < idx) guess.e.c = idx;
7485
            /* 18.18.11 t ST_CellType */
7486
            switch(p.t) {
7487
                case 'n': p.v = parseFloat(p.v); break;
7488
                case 's':
7489
                    sstr = strs[parseInt(p.v, 10)];
7490
                    p.v = sstr.t;
7491
                    p.r = sstr.r;
7492
                    if(opts.cellHTML) p.h = sstr.h;
7493
                    break;
7494
                case 'str':
7495
                    p.t = "s";
7496
                    p.v = (p.v!=null) ? utf8read(p.v) : '';
7497
                    if(opts.cellHTML) p.h = p.v;
7498
                    break;
7499
                case 'inlineStr':
7500
                    cref = d.match(isregex);
7501
                    p.t = 's';
7502
                    if(cref !== null) { sstr = parse_si(cref[1]); p.v = sstr.t; } else p.v = "";
7503
                    break; // inline string
7504
                case 'b': p.v = parsexmlbool(p.v); break;
7505
                case 'd':
7506
                    if(!opts.cellDates) { p.v = datenum(p.v); p.t = 'n'; }
7507
                    break;
7508
                /* error string in .v, number in .v */
7509
                case 'e': p.w = p.v; p.v = RBErr[p.v]; break;
7510
            }
7511
            /* formatting */
7512
            fmtid = fillid = 0;
7513
            if(do_format && tag.s !== undefined) {
7514
                cf = styles.CellXf[tag.s];
7515
                if(cf != null) {
7516
                    if(cf.numFmtId != null) fmtid = cf.numFmtId;
7517
                    if(opts.cellStyles && cf.fillId != null) fillid = cf.fillId;
7518
                }
7519
            }
7520
            safe_format(p, fmtid, fillid, opts);
7521
            s[tag.r] = p;
7522
        }
7523
    }
7524
}; })();
7525
 
7526
function write_ws_xml_data(ws, opts, idx, wb) {
7527
    var o = [], r = [], range = safe_decode_range(ws['!ref']), cell, ref, rr = "", cols = [], R, C;
7528
    for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
7529
    for(R = range.s.r; R <= range.e.r; ++R) {
7530
        r = [];
7531
        rr = encode_row(R);
7532
        for(C = range.s.c; C <= range.e.c; ++C) {
7533
            ref = cols[C] + rr;
7534
            if(ws[ref] === undefined) continue;
7535
            if((cell = write_ws_xml_cell(ws[ref], ref, ws, opts, idx, wb)) != null) r.push(cell);
7536
        }
7537
        if(r.length > 0) o[o.length] = (writextag('row', r.join(""), {r:rr}));
7538
    }
7539
    return o.join("");
7540
}
7541
 
7542
var WS_XML_ROOT = writextag('worksheet', null, {
7543
    'xmlns': XMLNS.main[0],
7544
    'xmlns:r': XMLNS.r
7545
});
7546
 
7547
function write_ws_xml(idx, opts, wb) {
7548
    var o = [XML_HEADER, WS_XML_ROOT];
7549
    var s = wb.SheetNames[idx], sidx = 0, rdata = "";
7550
    var ws = wb.Sheets[s];
7551
    if(ws === undefined) ws = {};
7552
    var ref = ws['!ref']; if(ref === undefined) ref = 'A1';
7553
    o[o.length] = (writextag('dimension', null, {'ref': ref}));
7554
 
7555
    if(ws['!cols'] !== undefined && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols']));
7556
    o[sidx = o.length] = '<sheetData/>';
7557
    if(ws['!ref'] !== undefined) {
7558
        rdata = write_ws_xml_data(ws, opts, idx, wb);
7559
        if(rdata.length > 0) o[o.length] = (rdata);
7560
    }
7561
    if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
7562
 
7563
    if(ws['!merges'] !== undefined && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
7564
 
7565
    if(o.length>2) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
7566
    return o.join("");
7567
}
7568
 
7569
/* [MS-XLSB] 2.4.718 BrtRowHdr */
7570
function parse_BrtRowHdr(data, length) {
7571
    var z = [];
7572
    z.r = data.read_shift(4);
7573
    data.l += length-4;
7574
    return z;
7575
}
7576
 
7577
/* [MS-XLSB] 2.4.812 BrtWsDim */
7578
var parse_BrtWsDim = parse_UncheckedRfX;
7579
var write_BrtWsDim = write_UncheckedRfX;
7580
 
7581
/* [MS-XLSB] 2.4.815 BrtWsProp */
7582
function parse_BrtWsProp(data, length) {
7583
    var z = {};
7584
    /* TODO: pull flags */
7585
    data.l += 19;
7586
    z.name = parse_XLSBCodeName(data, length - 19);
7587
    return z;
7588
}
7589
 
7590
/* [MS-XLSB] 2.4.303 BrtCellBlank */
7591
function parse_BrtCellBlank(data, length) {
7592
    var cell = parse_XLSBCell(data);
7593
    return [cell];
7594
}
7595
function write_BrtCellBlank(cell, val, o) {
7596
    if(o == null) o = new_buf(8);
7597
    return write_XLSBCell(val, o);
7598
}
7599
 
7600
 
7601
/* [MS-XLSB] 2.4.304 BrtCellBool */
7602
function parse_BrtCellBool(data, length) {
7603
    var cell = parse_XLSBCell(data);
7604
    var fBool = data.read_shift(1);
7605
    return [cell, fBool, 'b'];
7606
}
7607
 
7608
/* [MS-XLSB] 2.4.305 BrtCellError */
7609
function parse_BrtCellError(data, length) {
7610
    var cell = parse_XLSBCell(data);
7611
    var fBool = data.read_shift(1);
7612
    return [cell, fBool, 'e'];
7613
}
7614
 
7615
/* [MS-XLSB] 2.4.308 BrtCellIsst */
7616
function parse_BrtCellIsst(data, length) {
7617
    var cell = parse_XLSBCell(data);
7618
    var isst = data.read_shift(4);
7619
    return [cell, isst, 's'];
7620
}
7621
 
7622
/* [MS-XLSB] 2.4.310 BrtCellReal */
7623
function parse_BrtCellReal(data, length) {
7624
    var cell = parse_XLSBCell(data);
7625
    var value = parse_Xnum(data);
7626
    return [cell, value, 'n'];
7627
}
7628
 
7629
/* [MS-XLSB] 2.4.311 BrtCellRk */
7630
function parse_BrtCellRk(data, length) {
7631
    var cell = parse_XLSBCell(data);
7632
    var value = parse_RkNumber(data);
7633
    return [cell, value, 'n'];
7634
}
7635
 
7636
/* [MS-XLSB] 2.4.314 BrtCellSt */
7637
function parse_BrtCellSt(data, length) {
7638
    var cell = parse_XLSBCell(data);
7639
    var value = parse_XLWideString(data);
7640
    return [cell, value, 'str'];
7641
}
7642
 
7643
/* [MS-XLSB] 2.4.647 BrtFmlaBool */
7644
function parse_BrtFmlaBool(data, length, opts) {
7645
    var cell = parse_XLSBCell(data);
7646
    var value = data.read_shift(1);
7647
    var o = [cell, value, 'b'];
7648
    if(opts.cellFormula) {
7649
        var formula = parse_XLSBCellParsedFormula(data, length-9);
7650
        o[3] = ""; /* TODO */
7651
    }
7652
    else data.l += length-9;
7653
    return o;
7654
}
7655
 
7656
/* [MS-XLSB] 2.4.648 BrtFmlaError */
7657
function parse_BrtFmlaError(data, length, opts) {
7658
    var cell = parse_XLSBCell(data);
7659
    var value = data.read_shift(1);
7660
    var o = [cell, value, 'e'];
7661
    if(opts.cellFormula) {
7662
        var formula = parse_XLSBCellParsedFormula(data, length-9);
7663
        o[3] = ""; /* TODO */
7664
    }
7665
    else data.l += length-9;
7666
    return o;
7667
}
7668
 
7669
/* [MS-XLSB] 2.4.649 BrtFmlaNum */
7670
function parse_BrtFmlaNum(data, length, opts) {
7671
    var cell = parse_XLSBCell(data);
7672
    var value = parse_Xnum(data);
7673
    var o = [cell, value, 'n'];
7674
    if(opts.cellFormula) {
7675
        var formula = parse_XLSBCellParsedFormula(data, length - 16);
7676
        o[3] = ""; /* TODO */
7677
    }
7678
    else data.l += length-16;
7679
    return o;
7680
}
7681
 
7682
/* [MS-XLSB] 2.4.650 BrtFmlaString */
7683
function parse_BrtFmlaString(data, length, opts) {
7684
    var start = data.l;
7685
    var cell = parse_XLSBCell(data);
7686
    var value = parse_XLWideString(data);
7687
    var o = [cell, value, 'str'];
7688
    if(opts.cellFormula) {
7689
        var formula = parse_XLSBCellParsedFormula(data, start + length - data.l);
7690
    }
7691
    else data.l = start + length;
7692
    return o;
7693
}
7694
 
7695
/* [MS-XLSB] 2.4.676 BrtMergeCell */
7696
var parse_BrtMergeCell = parse_UncheckedRfX;
7697
 
7698
/* [MS-XLSB] 2.4.656 BrtHLink */
7699
function parse_BrtHLink(data, length, opts) {
7700
    var end = data.l + length;
7701
    var rfx = parse_UncheckedRfX(data, 16);
7702
    var relId = parse_XLNullableWideString(data);
7703
    var loc = parse_XLWideString(data);
7704
    var tooltip = parse_XLWideString(data);
7705
    var display = parse_XLWideString(data);
7706
    data.l = end;
7707
    return {rfx:rfx, relId:relId, loc:loc, tooltip:tooltip, display:display};
7708
}
7709
 
7710
/* [MS-XLSB] 2.1.7.61 Worksheet */
7711
function parse_ws_bin(data, opts, rels) {
7712
    if(!data) return data;
7713
    if(!rels) rels = {'!id':{}};
7714
    var s = {};
7715
 
7716
    var ref;
7717
    var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} };
7718
 
7719
    var pass = false, end = false;
7720
    var row, p, cf, R, C, addr, sstr, rr;
7721
    var mergecells = [];
7722
    recordhopper(data, function ws_parse(val, R) {
7723
        if(end) return;
7724
        switch(R.n) {
7725
            case 'BrtWsDim': ref = val; break;
7726
            case 'BrtRowHdr':
7727
                row = val;
7728
                if(opts.sheetRows && opts.sheetRows <= row.r) end=true;
7729
                rr = encode_row(row.r);
7730
                break;
7731
 
7732
            case 'BrtFmlaBool':
7733
            case 'BrtFmlaError':
7734
            case 'BrtFmlaNum':
7735
            case 'BrtFmlaString':
7736
            case 'BrtCellBool':
7737
            case 'BrtCellError':
7738
            case 'BrtCellIsst':
7739
            case 'BrtCellReal':
7740
            case 'BrtCellRk':
7741
            case 'BrtCellSt':
7742
                p = {t:val[2]};
7743
                switch(val[2]) {
7744
                    case 'n': p.v = val[1]; break;
7745
                    case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
7746
                    case 'b': p.v = val[1] ? true : false; break;
7747
                    case 'e': p.v = val[1]; p.w = BErr[p.v]; break;
7748
                    case 'str': p.t = 's'; p.v = utf8read(val[1]); break;
7749
                }
7750
                if(opts.cellFormula && val.length > 3) p.f = val[3];
7751
                if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts);
7752
                s[encode_col(C=val[0].c) + rr] = p;
7753
                if(refguess.s.r > row.r) refguess.s.r = row.r;
7754
                if(refguess.s.c > C) refguess.s.c = C;
7755
                if(refguess.e.r < row.r) refguess.e.r = row.r;
7756
                if(refguess.e.c < C) refguess.e.c = C;
7757
                break;
7758
 
7759
            case 'BrtCellBlank': if(!opts.sheetStubs) break;
7760
                p = {t:'s',v:undefined};
7761
                s[encode_col(C=val[0].c) + rr] = p;
7762
                if(refguess.s.r > row.r) refguess.s.r = row.r;
7763
                if(refguess.s.c > C) refguess.s.c = C;
7764
                if(refguess.e.r < row.r) refguess.e.r = row.r;
7765
                if(refguess.e.c < C) refguess.e.c = C;
7766
                break;
7767
 
7768
            /* Merge Cells */
7769
            case 'BrtBeginMergeCells': break;
7770
            case 'BrtEndMergeCells': break;
7771
            case 'BrtMergeCell': mergecells.push(val); break;
7772
 
7773
            case 'BrtHLink':
7774
                var rel = rels['!id'][val.relId];
7775
                if(rel) {
7776
                    val.Target = rel.Target;
7777
                    if(val.loc) val.Target += "#"+val.loc;
7778
                    val.Rel = rel;
7779
                }
7780
                for(R=val.rfx.s.r;R<=val.rfx.e.r;++R) for(C=val.rfx.s.c;C<=val.rfx.e.c;++C) {
7781
                    addr = encode_cell({c:C,r:R});
7782
                    if(!s[addr]) s[addr] = {t:'s',v:undefined};
7783
                    s[addr].l = val;
7784
                }
7785
                break;
7786
 
7787
            case 'BrtArrFmla': break; // TODO
7788
            case 'BrtShrFmla': break; // TODO
7789
            case 'BrtBeginSheet': break;
7790
            case 'BrtWsProp': break; // TODO
7791
            case 'BrtSheetCalcProp': break; // TODO
7792
            case 'BrtBeginWsViews': break; // TODO
7793
            case 'BrtBeginWsView': break; // TODO
7794
            case 'BrtPane': break; // TODO
7795
            case 'BrtSel': break; // TODO
7796
            case 'BrtEndWsView': break; // TODO
7797
            case 'BrtEndWsViews': break; // TODO
7798
            case 'BrtACBegin': break; // TODO
7799
            case 'BrtRwDescent': break; // TODO
7800
            case 'BrtACEnd': break; // TODO
7801
            case 'BrtWsFmtInfoEx14': break; // TODO
7802
            case 'BrtWsFmtInfo': break; // TODO
7803
            case 'BrtBeginColInfos': break; // TODO
7804
            case 'BrtColInfo': break; // TODO
7805
            case 'BrtEndColInfos': break; // TODO
7806
            case 'BrtBeginSheetData': break; // TODO
7807
            case 'BrtEndSheetData': break; // TODO
7808
            case 'BrtSheetProtection': break; // TODO
7809
            case 'BrtPrintOptions': break; // TODO
7810
            case 'BrtMargins': break; // TODO
7811
            case 'BrtPageSetup': break; // TODO
7812
            case 'BrtFRTBegin': pass = true; break;
7813
            case 'BrtFRTEnd': pass = false; break;
7814
            case 'BrtEndSheet': break; // TODO
7815
            case 'BrtDrawing': break; // TODO
7816
            case 'BrtLegacyDrawing': break; // TODO
7817
            case 'BrtLegacyDrawingHF': break; // TODO
7818
            case 'BrtPhoneticInfo': break; // TODO
7819
            case 'BrtBeginHeaderFooter': break; // TODO
7820
            case 'BrtEndHeaderFooter': break; // TODO
7821
            case 'BrtBrk': break; // TODO
7822
            case 'BrtBeginRwBrk': break; // TODO
7823
            case 'BrtEndRwBrk': break; // TODO
7824
            case 'BrtBeginColBrk': break; // TODO
7825
            case 'BrtEndColBrk': break; // TODO
7826
            case 'BrtBeginUserShViews': break; // TODO
7827
            case 'BrtBeginUserShView': break; // TODO
7828
            case 'BrtEndUserShView': break; // TODO
7829
            case 'BrtEndUserShViews': break; // TODO
7830
            case 'BrtBkHim': break; // TODO
7831
            case 'BrtBeginOleObjects': break; // TODO
7832
            case 'BrtOleObject': break; // TODO
7833
            case 'BrtEndOleObjects': break; // TODO
7834
            case 'BrtBeginListParts': break; // TODO
7835
            case 'BrtListPart': break; // TODO
7836
            case 'BrtEndListParts': break; // TODO
7837
            case 'BrtBeginSortState': break; // TODO
7838
            case 'BrtBeginSortCond': break; // TODO
7839
            case 'BrtEndSortCond': break; // TODO
7840
            case 'BrtEndSortState': break; // TODO
7841
            case 'BrtBeginConditionalFormatting': break; // TODO
7842
            case 'BrtEndConditionalFormatting': break; // TODO
7843
            case 'BrtBeginCFRule': break; // TODO
7844
            case 'BrtEndCFRule': break; // TODO
7845
            case 'BrtBeginDVals': break; // TODO
7846
            case 'BrtDVal': break; // TODO
7847
            case 'BrtEndDVals': break; // TODO
7848
            case 'BrtRangeProtection': break; // TODO
7849
            case 'BrtBeginDCon': break; // TODO
7850
            case 'BrtEndDCon': break; // TODO
7851
            case 'BrtBeginDRefs': break;
7852
            case 'BrtDRef': break;
7853
            case 'BrtEndDRefs': break;
7854
 
7855
            /* ActiveX */
7856
            case 'BrtBeginActiveXControls': break;
7857
            case 'BrtActiveX': break;
7858
            case 'BrtEndActiveXControls': break;
7859
 
7860
            /* AutoFilter */
7861
            case 'BrtBeginAFilter': break;
7862
            case 'BrtEndAFilter': break;
7863
            case 'BrtBeginFilterColumn': break;
7864
            case 'BrtBeginFilters': break;
7865
            case 'BrtFilter': break;
7866
            case 'BrtEndFilters': break;
7867
            case 'BrtEndFilterColumn': break;
7868
            case 'BrtDynamicFilter': break;
7869
            case 'BrtTop10Filter': break;
7870
            case 'BrtBeginCustomFilters': break;
7871
            case 'BrtCustomFilter': break;
7872
            case 'BrtEndCustomFilters': break;
7873
 
7874
            /* Smart Tags */
7875
            case 'BrtBeginSmartTags': break;
7876
            case 'BrtBeginCellSmartTags': break;
7877
            case 'BrtBeginCellSmartTag': break;
7878
            case 'BrtCellSmartTagProperty': break;
7879
            case 'BrtEndCellSmartTag': break;
7880
            case 'BrtEndCellSmartTags': break;
7881
            case 'BrtEndSmartTags': break;
7882
 
7883
            /* Cell Watch */
7884
            case 'BrtBeginCellWatches': break;
7885
            case 'BrtCellWatch': break;
7886
            case 'BrtEndCellWatches': break;
7887
 
7888
            /* Table */
7889
            case 'BrtTable': break;
7890
 
7891
            /* Ignore Cell Errors */
7892
            case 'BrtBeginCellIgnoreECs': break;
7893
            case 'BrtCellIgnoreEC': break;
7894
            case 'BrtEndCellIgnoreECs': break;
7895
 
7896
            default: if(!pass || opts.WTF) throw new Error("Unexpected record " + R.n);
7897
        }
7898
    }, opts);
7899
    if(!s["!ref"] && (refguess.s.r < 1000000 || ref.e.r > 0 || ref.e.c > 0 || ref.s.r > 0 || ref.s.c > 0)) s["!ref"] = encode_range(ref);
7900
    if(opts.sheetRows && s["!ref"]) {
7901
        var tmpref = safe_decode_range(s["!ref"]);
7902
        if(opts.sheetRows < +tmpref.e.r) {
7903
            tmpref.e.r = opts.sheetRows - 1;
7904
            if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
7905
            if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
7906
            if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c;
7907
            if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c;
7908
            s["!fullref"] = s["!ref"];
7909
            s["!ref"] = encode_range(tmpref);
7910
        }
7911
    }
7912
    if(mergecells.length > 0) s["!merges"] = mergecells;
7913
    return s;
7914
}
7915
 
7916
/* TODO: something useful -- this is a stub */
7917
function write_ws_bin_cell(ba, cell, R, C, opts) {
7918
    if(cell.v === undefined) return "";
7919
    var vv = "";
7920
    switch(cell.t) {
7921
        case 'b': vv = cell.v ? "1" : "0"; break;
7922
        case 'n': case 'e': vv = ''+cell.v; break;
7923
        default: vv = cell.v; break;
7924
    }
7925
    var o = {r:R, c:C};
7926
    /* TODO: cell style */
7927
    o.s = get_cell_style(opts.cellXfs, cell, opts);
7928
    switch(cell.t) {
7929
        case 's': case 'str':
7930
            if(opts.bookSST) {
7931
                vv = get_sst_id(opts.Strings, cell.v);
7932
                o.t = "s"; break;
7933
            }
7934
            o.t = "str"; break;
7935
        case 'n': break;
7936
        case 'b': o.t = "b"; break;
7937
        case 'e': o.t = "e"; break;
7938
    }
7939
    write_record(ba, "BrtCellBlank", write_BrtCellBlank(cell, o));
7940
}
7941
 
7942
function write_CELLTABLE(ba, ws, idx, opts, wb) {
7943
    var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = [];
7944
    write_record(ba, 'BrtBeginSheetData');
7945
    for(var R = range.s.r; R <= range.e.r; ++R) {
7946
        rr = encode_row(R);
7947
        /* [ACCELLTABLE] */
7948
        /* BrtRowHdr */
7949
        for(var C = range.s.c; C <= range.e.c; ++C) {
7950
            /* *16384CELL */
7951
            if(R === range.s.r) cols[C] = encode_col(C);
7952
            ref = cols[C] + rr;
7953
            if(!ws[ref]) continue;
7954
            /* write cell */
7955
            write_ws_bin_cell(ba, ws[ref], R, C, opts);
7956
        }
7957
    }
7958
    write_record(ba, 'BrtEndSheetData');
7959
}
7960
 
7961
function write_ws_bin(idx, opts, wb) {
7962
    var ba = buf_array();
7963
    var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
7964
    var r = safe_decode_range(ws['!ref'] || "A1");
7965
    write_record(ba, "BrtBeginSheet");
7966
    /* [BrtWsProp] */
7967
    write_record(ba, "BrtWsDim", write_BrtWsDim(r));
7968
    /* [WSVIEWS2] */
7969
    /* [WSFMTINFO] */
7970
    /* *COLINFOS */
7971
    write_CELLTABLE(ba, ws, idx, opts, wb);
7972
    /* [BrtSheetCalcProp] */
7973
    /* [[BrtSheetProtectionIso] BrtSheetProtection] */
7974
    /* *([BrtRangeProtectionIso] BrtRangeProtection) */
7975
    /* [SCENMAN] */
7976
    /* [AUTOFILTER] */
7977
    /* [SORTSTATE] */
7978
    /* [DCON] */
7979
    /* [USERSHVIEWS] */
7980
    /* [MERGECELLS] */
7981
    /* [BrtPhoneticInfo] */
7982
    /* *CONDITIONALFORMATTING */
7983
    /* [DVALS] */
7984
    /* *BrtHLink */
7985
    /* [BrtPrintOptions] */
7986
    /* [BrtMargins] */
7987
    /* [BrtPageSetup] */
7988
    /* [HEADERFOOTER] */
7989
    /* [RWBRK] */
7990
    /* [COLBRK] */
7991
    /* *BrtBigName */
7992
    /* [CELLWATCHES] */
7993
    /* [IGNOREECS] */
7994
    /* [SMARTTAGS] */
7995
    /* [BrtDrawing] */
7996
    /* [BrtLegacyDrawing] */
7997
    /* [BrtLegacyDrawingHF] */
7998
    /* [BrtBkHim] */
7999
    /* [OLEOBJECTS] */
8000
    /* [ACTIVEXCONTROLS] */
8001
    /* [WEBPUBITEMS] */
8002
    /* [LISTPARTS] */
8003
    /* FRTWORKSHEET */
8004
    write_record(ba, "BrtEndSheet");
8005
    return ba.end();
8006
}
8007
/* 18.2.28 (CT_WorkbookProtection) Defaults */
8008
var WBPropsDef = [
8009
    ['allowRefreshQuery', '0'],
8010
    ['autoCompressPictures', '1'],
8011
    ['backupFile', '0'],
8012
    ['checkCompatibility', '0'],
8013
    ['codeName', ''],
8014
    ['date1904', '0'],
8015
    ['dateCompatibility', '1'],
8016
    //['defaultThemeVersion', '0'],
8017
    ['filterPrivacy', '0'],
8018
    ['hidePivotFieldList', '0'],
8019
    ['promptedSolutions', '0'],
8020
    ['publishItems', '0'],
8021
    ['refreshAllConnections', false],
8022
    ['saveExternalLinkValues', '1'],
8023
    ['showBorderUnselectedTables', '1'],
8024
    ['showInkAnnotation', '1'],
8025
    ['showObjects', 'all'],
8026
    ['showPivotChartFilter', '0']
8027
    //['updateLinks', 'userSet']
8028
];
8029
 
8030
/* 18.2.30 (CT_BookView) Defaults */
8031
var WBViewDef = [
8032
    ['activeTab', '0'],
8033
    ['autoFilterDateGrouping', '1'],
8034
    ['firstSheet', '0'],
8035
    ['minimized', '0'],
8036
    ['showHorizontalScroll', '1'],
8037
    ['showSheetTabs', '1'],
8038
    ['showVerticalScroll', '1'],
8039
    ['tabRatio', '600'],
8040
    ['visibility', 'visible']
8041
    //window{Height,Width}, {x,y}Window
8042
];
8043
 
8044
/* 18.2.19 (CT_Sheet) Defaults */
8045
var SheetDef = [
8046
    ['state', 'visible']
8047
];
8048
 
8049
/* 18.2.2  (CT_CalcPr) Defaults */
8050
var CalcPrDef = [
8051
    ['calcCompleted', 'true'],
8052
    ['calcMode', 'auto'],
8053
    ['calcOnSave', 'true'],
8054
    ['concurrentCalc', 'true'],
8055
    ['fullCalcOnLoad', 'false'],
8056
    ['fullPrecision', 'true'],
8057
    ['iterate', 'false'],
8058
    ['iterateCount', '100'],
8059
    ['iterateDelta', '0.001'],
8060
    ['refMode', 'A1']
8061
];
8062
 
8063
/* 18.2.3 (CT_CustomWorkbookView) Defaults */
8064
var CustomWBViewDef = [
8065
    ['autoUpdate', 'false'],
8066
    ['changesSavedWin', 'false'],
8067
    ['includeHiddenRowCol', 'true'],
8068
    ['includePrintSettings', 'true'],
8069
    ['maximized', 'false'],
8070
    ['minimized', 'false'],
8071
    ['onlySync', 'false'],
8072
    ['personalView', 'false'],
8073
    ['showComments', 'commIndicator'],
8074
    ['showFormulaBar', 'true'],
8075
    ['showHorizontalScroll', 'true'],
8076
    ['showObjects', 'all'],
8077
    ['showSheetTabs', 'true'],
8078
    ['showStatusbar', 'true'],
8079
    ['showVerticalScroll', 'true'],
8080
    ['tabRatio', '600'],
8081
    ['xWindow', '0'],
8082
    ['yWindow', '0']
8083
];
8084
 
8085
function push_defaults_array(target, defaults) {
8086
    for(var j = 0; j != target.length; ++j) { var w = target[j];
8087
        for(var i=0; i != defaults.length; ++i) { var z = defaults[i];
8088
            if(w[z[0]] == null) w[z[0]] = z[1];
8089
        }
8090
    }
8091
}
8092
function push_defaults(target, defaults) {
8093
    for(var i = 0; i != defaults.length; ++i) { var z = defaults[i];
8094
        if(target[z[0]] == null) target[z[0]] = z[1];
8095
    }
8096
}
8097
 
8098
function parse_wb_defaults(wb) {
8099
    push_defaults(wb.WBProps, WBPropsDef);
8100
    push_defaults(wb.CalcPr, CalcPrDef);
8101
 
8102
    push_defaults_array(wb.WBView, WBViewDef);
8103
    push_defaults_array(wb.Sheets, SheetDef);
8104
 
8105
    _ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904, 'date1904');
8106
}
8107
/* 18.2 Workbook */
8108
var wbnsregex = /<\w+:workbook/;
8109
function parse_wb_xml(data, opts) {
8110
    var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
8111
    var pass = false, xmlns = "xmlns";
8112
    data.match(tagregex).forEach(function xml_wb(x) {
8113
        var y = parsexmltag(x);
8114
        switch(strip_ns(y[0])) {
8115
            case '<?xml': break;
8116
 
8117
            /* 18.2.27 workbook CT_Workbook 1 */
8118
            case '<workbook':
8119
                if(x.match(wbnsregex)) xmlns = "xmlns" + x.match(/<(\w+):/)[1];
8120
                wb.xmlns = y[xmlns];
8121
                break;
8122
            case '</workbook>': break;
8123
 
8124
            /* 18.2.13 fileVersion CT_FileVersion ? */
8125
            case '<fileVersion': delete y[0]; wb.AppVersion = y; break;
8126
            case '<fileVersion/>': break;
8127
 
8128
            /* 18.2.12 fileSharing CT_FileSharing ? */
8129
            case '<fileSharing': case '<fileSharing/>': break;
8130
 
8131
            /* 18.2.28 workbookPr CT_WorkbookPr ? */
8132
            case '<workbookPr': delete y[0]; wb.WBProps = y; break;
8133
            case '<workbookPr/>': delete y[0]; wb.WBProps = y; break;
8134
 
8135
            /* 18.2.29 workbookProtection CT_WorkbookProtection ? */
8136
            case '<workbookProtection': break;
8137
            case '<workbookProtection/>': break;
8138
 
8139
            /* 18.2.1  bookViews CT_BookViews ? */
8140
            case '<bookViews>': case '</bookViews>': break;
8141
            /* 18.2.30   workbookView CT_BookView + */
8142
            case '<workbookView': delete y[0]; wb.WBView.push(y); break;
8143
 
8144
            /* 18.2.20 sheets CT_Sheets 1 */
8145
            case '<sheets>': case '</sheets>': break; // aggregate sheet
8146
            /* 18.2.19   sheet CT_Sheet + */
8147
            case '<sheet': delete y[0]; y.name = utf8read(y.name); wb.Sheets.push(y); break;
8148
 
8149
            /* 18.2.15 functionGroups CT_FunctionGroups ? */
8150
            case '<functionGroups': case '<functionGroups/>': break;
8151
            /* 18.2.14   functionGroup CT_FunctionGroup + */
8152
            case '<functionGroup': break;
8153
 
8154
            /* 18.2.9  externalReferences CT_ExternalReferences ? */
8155
            case '<externalReferences': case '</externalReferences>': case '<externalReferences>': break;
8156
            /* 18.2.8    externalReference CT_ExternalReference + */
8157
            case '<externalReference': break;
8158
 
8159
            /* 18.2.6  definedNames CT_DefinedNames ? */
8160
            case '<definedNames/>': break;
8161
            case '<definedNames>': case '<definedNames': pass=true; break;
8162
            case '</definedNames>': pass=false; break;
8163
            /* 18.2.5    definedName CT_DefinedName + */
8164
            case '<definedName': case '<definedName/>': case '</definedName>': break;
8165
 
8166
            /* 18.2.2  calcPr CT_CalcPr ? */
8167
            case '<calcPr': delete y[0]; wb.CalcPr = y; break;
8168
            case '<calcPr/>': delete y[0]; wb.CalcPr = y; break;
8169
 
8170
            /* 18.2.16 oleSize CT_OleSize ? (ref required) */
8171
            case '<oleSize': break;
8172
 
8173
            /* 18.2.4  customWorkbookViews CT_CustomWorkbookViews ? */
8174
            case '<customWorkbookViews>': case '</customWorkbookViews>': case '<customWorkbookViews': break;
8175
            /* 18.2.3    customWorkbookView CT_CustomWorkbookView + */
8176
            case '<customWorkbookView': case '</customWorkbookView>': break;
8177
 
8178
            /* 18.2.18 pivotCaches CT_PivotCaches ? */
8179
            case '<pivotCaches>': case '</pivotCaches>': case '<pivotCaches': break;
8180
            /* 18.2.17 pivotCache CT_PivotCache ? */
8181
            case '<pivotCache': break;
8182
 
8183
            /* 18.2.21 smartTagPr CT_SmartTagPr ? */
8184
            case '<smartTagPr': case '<smartTagPr/>': break;
8185
 
8186
            /* 18.2.23 smartTagTypes CT_SmartTagTypes ? */
8187
            case '<smartTagTypes': case '<smartTagTypes>': case '</smartTagTypes>': break;
8188
            /* 18.2.22   smartTagType CT_SmartTagType ? */
8189
            case '<smartTagType': break;
8190
 
8191
            /* 18.2.24 webPublishing CT_WebPublishing ? */
8192
            case '<webPublishing': case '<webPublishing/>': break;
8193
 
8194
            /* 18.2.11 fileRecoveryPr CT_FileRecoveryPr ? */
8195
            case '<fileRecoveryPr': case '<fileRecoveryPr/>': break;
8196
 
8197
            /* 18.2.26 webPublishObjects CT_WebPublishObjects ? */
8198
            case '<webPublishObjects>': case '<webPublishObjects': case '</webPublishObjects>': break;
8199
            /* 18.2.25 webPublishObject CT_WebPublishObject ? */
8200
            case '<webPublishObject': break;
8201
 
8202
            /* 18.2.10 extLst CT_ExtensionList ? */
8203
            case '<extLst>': case '</extLst>': case '<extLst/>': break;
8204
            /* 18.2.7    ext CT_Extension + */
8205
            case '<ext': pass=true; break; //TODO: check with versions of excel
8206
            case '</ext>': pass=false; break;
8207
 
8208
            /* Others */
8209
            case '<ArchID': break;
8210
            case '<AlternateContent': pass=true; break;
8211
            case '</AlternateContent>': pass=false; break;
8212
 
8213
            default: if(!pass && opts.WTF) throw 'unrecognized ' + y[0] + ' in workbook';
8214
        }
8215
    });
8216
    if(XMLNS.main.indexOf(wb.xmlns) === -1) throw new Error("Unknown Namespace: " + wb.xmlns);
8217
 
8218
    parse_wb_defaults(wb);
8219
 
8220
    return wb;
8221
}
8222
 
8223
var WB_XML_ROOT = writextag('workbook', null, {
8224
    'xmlns': XMLNS.main[0],
8225
    //'xmlns:mx': XMLNS.mx,
8226
    //'xmlns:s': XMLNS.main[0],
8227
    'xmlns:r': XMLNS.r
8228
});
8229
 
8230
function safe1904(wb) {
8231
    /* TODO: store date1904 somewhere else */
8232
    try { return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false"; } catch(e) { return "false"; }
8233
}
8234
 
8235
function write_wb_xml(wb, opts) {
8236
    var o = [XML_HEADER];
8237
    o[o.length] = WB_XML_ROOT;
8238
    o[o.length] = (writextag('workbookPr', null, {date1904:safe1904(wb)}));
8239
    o[o.length] = "<sheets>";
8240
    for(var i = 0; i != wb.SheetNames.length; ++i)
8241
        o[o.length] = (writextag('sheet',null,{name:wb.SheetNames[i].substr(0,31), sheetId:""+(i+1), "r:id":"rId"+(i+1)}));
8242
    o[o.length] = "</sheets>";
8243
    if(o.length>2){ o[o.length] = '</workbook>'; o[1]=o[1].replace("/>",">"); }
8244
    return o.join("");
8245
}
8246
/* [MS-XLSB] 2.4.301 BrtBundleSh */
8247
function parse_BrtBundleSh(data, length) {
8248
    var z = {};
8249
    z.hsState = data.read_shift(4); //ST_SheetState
8250
    z.iTabID = data.read_shift(4);
8251
    z.strRelID = parse_RelID(data,length-8);
8252
    z.name = parse_XLWideString(data);
8253
    return z;
8254
}
8255
function write_BrtBundleSh(data, o) {
8256
    if(!o) o = new_buf(127);
8257
    o.write_shift(4, data.hsState);
8258
    o.write_shift(4, data.iTabID);
8259
    write_RelID(data.strRelID, o);
8260
    write_XLWideString(data.name.substr(0,31), o);
8261
    return o;
8262
}
8263
 
8264
/* [MS-XLSB] 2.4.807 BrtWbProp */
8265
function parse_BrtWbProp(data, length) {
8266
    data.read_shift(4);
8267
    var dwThemeVersion = data.read_shift(4);
8268
    var strName = (length > 8) ? parse_XLWideString(data) : "";
8269
    return [dwThemeVersion, strName];
8270
}
8271
function write_BrtWbProp(data, o) {
8272
    if(!o) o = new_buf(8);
8273
    o.write_shift(4, 0);
8274
    o.write_shift(4, 0);
8275
    return o;
8276
}
8277
 
8278
function parse_BrtFRTArchID$(data, length) {
8279
    var o = {};
8280
    data.read_shift(4);
8281
    o.ArchID = data.read_shift(4);
8282
    data.l += length - 8;
8283
    return o;
8284
}
8285
 
8286
/* [MS-XLSB] 2.1.7.60 Workbook */
8287
function parse_wb_bin(data, opts) {
8288
    var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
8289
    var pass = false, z;
8290
 
8291
    recordhopper(data, function hopper_wb(val, R) {
8292
        switch(R.n) {
8293
            case 'BrtBundleSh': wb.Sheets.push(val); break;
8294
 
8295
            case 'BrtBeginBook': break;
8296
            case 'BrtFileVersion': break;
8297
            case 'BrtWbProp': break;
8298
            case 'BrtACBegin': break;
8299
            case 'BrtAbsPath15': break;
8300
            case 'BrtACEnd': break;
8301
            case 'BrtWbFactoid': break;
8302
            /*case 'BrtBookProtectionIso': break;*/
8303
            case 'BrtBookProtection': break;
8304
            case 'BrtBeginBookViews': break;
8305
            case 'BrtBookView': break;
8306
            case 'BrtEndBookViews': break;
8307
            case 'BrtBeginBundleShs': break;
8308
            case 'BrtEndBundleShs': break;
8309
            case 'BrtBeginFnGroup': break;
8310
            case 'BrtEndFnGroup': break;
8311
            case 'BrtBeginExternals': break;
8312
            case 'BrtSupSelf': break;
8313
            case 'BrtSupBookSrc': break;
8314
            case 'BrtExternSheet': break;
8315
            case 'BrtEndExternals': break;
8316
            case 'BrtName': break;
8317
            case 'BrtCalcProp': break;
8318
            case 'BrtUserBookView': break;
8319
            case 'BrtBeginPivotCacheIDs': break;
8320
            case 'BrtBeginPivotCacheID': break;
8321
            case 'BrtEndPivotCacheID': break;
8322
            case 'BrtEndPivotCacheIDs': break;
8323
            case 'BrtWebOpt': break;
8324
            case 'BrtFileRecover': break;
8325
            case 'BrtFileSharing': break;
8326
            /*case 'BrtBeginWebPubItems': break;
8327
            case 'BrtBeginWebPubItem': break;
8328
            case 'BrtEndWebPubItem': break;
8329
            case 'BrtEndWebPubItems': break;*/
8330
 
8331
            /* Smart Tags */
8332
            case 'BrtBeginSmartTagTypes': break;
8333
            case 'BrtSmartTagType': break;
8334
            case 'BrtEndSmartTagTypes': break;
8335
 
8336
            case 'BrtFRTBegin': pass = true; break;
8337
            case 'BrtFRTArchID$': break;
8338
            case 'BrtWorkBookPr15': break;
8339
            case 'BrtFRTEnd': pass = false; break;
8340
            case 'BrtEndBook': break;
8341
            default: if(!pass || opts.WTF) throw new Error("Unexpected record " + R.n);
8342
        }
8343
    });
8344
 
8345
    parse_wb_defaults(wb);
8346
 
8347
    return wb;
8348
}
8349
 
8350
/* [MS-XLSB] 2.1.7.60 Workbook */
8351
function write_BUNDLESHS(ba, wb, opts) {
8352
    write_record(ba, "BrtBeginBundleShs");
8353
    for(var idx = 0; idx != wb.SheetNames.length; ++idx) {
8354
        var d = { hsState: 0, iTabID: idx+1, strRelID: 'rId' + (idx+1), name: wb.SheetNames[idx] };
8355
        write_record(ba, "BrtBundleSh", write_BrtBundleSh(d));
8356
    }
8357
    write_record(ba, "BrtEndBundleShs");
8358
}
8359
 
8360
/* [MS-XLSB] 2.4.643 BrtFileVersion */
8361
function write_BrtFileVersion(data, o) {
8362
    if(!o) o = new_buf(127);
8363
    for(var i = 0; i != 4; ++i) o.write_shift(4, 0);
8364
    write_XLWideString("SheetJS", o);
8365
    write_XLWideString(XLSX.version, o);
8366
    write_XLWideString(XLSX.version, o);
8367
    write_XLWideString("7262", o);
8368
    o.length = o.l;
8369
    return o;
8370
}
8371
 
8372
/* [MS-XLSB] 2.1.7.60 Workbook */
8373
function write_BOOKVIEWS(ba, wb, opts) {
8374
    write_record(ba, "BrtBeginBookViews");
8375
    /* 1*(BrtBookView *FRT) */
8376
    write_record(ba, "BrtEndBookViews");
8377
}
8378
 
8379
/* [MS-XLSB] 2.4.302 BrtCalcProp */
8380
function write_BrtCalcProp(data, o) {
8381
    if(!o) o = new_buf(26);
8382
    o.write_shift(4,0); /* force recalc */
8383
    o.write_shift(4,1);
8384
    o.write_shift(4,0);
8385
    write_Xnum(0, o);
8386
    o.write_shift(-4, 1023);
8387
    o.write_shift(1, 0x33);
8388
    o.write_shift(1, 0x00);
8389
    return o;
8390
}
8391
 
8392
function write_BrtFileRecover(data, o) {
8393
    if(!o) o = new_buf(1);
8394
    o.write_shift(1,0);
8395
    return o;
8396
}
8397
 
8398
/* [MS-XLSB] 2.1.7.60 Workbook */
8399
function write_wb_bin(wb, opts) {
8400
    var ba = buf_array();
8401
    write_record(ba, "BrtBeginBook");
8402
    write_record(ba, "BrtFileVersion", write_BrtFileVersion());
8403
    /* [[BrtFileSharingIso] BrtFileSharing] */
8404
    write_record(ba, "BrtWbProp", write_BrtWbProp());
8405
    /* [ACABSPATH] */
8406
    /* [[BrtBookProtectionIso] BrtBookProtection] */
8407
    write_BOOKVIEWS(ba, wb, opts);
8408
    write_BUNDLESHS(ba, wb, opts);
8409
    /* [FNGROUP] */
8410
    /* [EXTERNALS] */
8411
    /* *BrtName */
8412
    write_record(ba, "BrtCalcProp", write_BrtCalcProp());
8413
    /* [BrtOleSize] */
8414
    /* *(BrtUserBookView *FRT) */
8415
    /* [PIVOTCACHEIDS] */
8416
    /* [BrtWbFactoid] */
8417
    /* [SMARTTAGTYPES] */
8418
    /* [BrtWebOpt] */
8419
    write_record(ba, "BrtFileRecover", write_BrtFileRecover());
8420
    /* [WEBPUBITEMS] */
8421
    /* [CRERRS] */
8422
    /* FRTWORKBOOK */
8423
    write_record(ba, "BrtEndBook");
8424
 
8425
    return ba.end();
8426
}
8427
function parse_wb(data, name, opts) {
8428
    return (name.substr(-4)===".bin" ? parse_wb_bin : parse_wb_xml)(data, opts);
8429
}
8430
 
8431
function parse_ws(data, name, opts, rels) {
8432
    return (name.substr(-4)===".bin" ? parse_ws_bin : parse_ws_xml)(data, opts, rels);
8433
}
8434
 
8435
function parse_sty(data, name, opts) {
8436
    return (name.substr(-4)===".bin" ? parse_sty_bin : parse_sty_xml)(data, opts);
8437
}
8438
 
8439
function parse_theme(data, name, opts) {
8440
    return parse_theme_xml(data, opts);
8441
}
8442
 
8443
function parse_sst(data, name, opts) {
8444
    return (name.substr(-4)===".bin" ? parse_sst_bin : parse_sst_xml)(data, opts);
8445
}
8446
 
8447
function parse_cmnt(data, name, opts) {
8448
    return (name.substr(-4)===".bin" ? parse_comments_bin : parse_comments_xml)(data, opts);
8449
}
8450
 
8451
function parse_cc(data, name, opts) {
8452
    return (name.substr(-4)===".bin" ? parse_cc_bin : parse_cc_xml)(data, opts);
8453
}
8454
 
8455
function write_wb(wb, name, opts) {
8456
    return (name.substr(-4)===".bin" ? write_wb_bin : write_wb_xml)(wb, opts);
8457
}
8458
 
8459
function write_ws(data, name, opts, wb) {
8460
    return (name.substr(-4)===".bin" ? write_ws_bin : write_ws_xml)(data, opts, wb);
8461
}
8462
 
8463
function write_sty(data, name, opts) {
8464
    return (name.substr(-4)===".bin" ? write_sty_bin : write_sty_xml)(data, opts);
8465
}
8466
 
8467
function write_sst(data, name, opts) {
8468
    return (name.substr(-4)===".bin" ? write_sst_bin : write_sst_xml)(data, opts);
8469
}
8470
/*
8471
function write_cmnt(data, name, opts) {
8472
    return (name.substr(-4)===".bin" ? write_comments_bin : write_comments_xml)(data, opts);
8473
}
8474
 
8475
function write_cc(data, name, opts) {
8476
    return (name.substr(-4)===".bin" ? write_cc_bin : write_cc_xml)(data, opts);
8477
}
8478
*/
8479
var attregexg2=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
8480
var attregex2=/([\w:]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;
8481
var _chr = function(c) { return String.fromCharCode(c); };
8482
function xlml_parsexmltag(tag, skip_root) {
8483
    var words = tag.split(/\s+/);
8484
    var z = []; if(!skip_root) z[0] = words[0];
8485
    if(words.length === 1) return z;
8486
    var m = tag.match(attregexg2), y, j, w, i;
8487
    if(m) for(i = 0; i != m.length; ++i) {
8488
        y = m[i].match(attregex2);
8489
        if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].substr(1,y[2].length-2);
8490
        else {
8491
            if(y[1].substr(0,6) === "xmlns:") w = "xmlns"+y[1].substr(6);
8492
            else w = y[1].substr(j+1);
8493
            z[w] = y[2].substr(1,y[2].length-2);
8494
        }
8495
    }
8496
    return z;
8497
}
8498
function xlml_parsexmltagobj(tag) {
8499
    var words = tag.split(/\s+/);
8500
    var z = {};
8501
    if(words.length === 1) return z;
8502
    var m = tag.match(attregexg2), y, j, w, i;
8503
    if(m) for(i = 0; i != m.length; ++i) {
8504
        y = m[i].match(attregex2);
8505
        if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].substr(1,y[2].length-2);
8506
        else {
8507
            if(y[1].substr(0,6) === "xmlns:") w = "xmlns"+y[1].substr(6);
8508
            else w = y[1].substr(j+1);
8509
            z[w] = y[2].substr(1,y[2].length-2);
8510
        }
8511
    }
8512
    return z;
8513
}
8514
 
8515
// ----
8516
 
8517
function xlml_format(format, value) {
8518
    var fmt = XLMLFormatMap[format] || unescapexml(format);
8519
    if(fmt === "General") return SSF._general(value);
8520
    return SSF.format(fmt, value);
8521
}
8522
 
8523
function xlml_set_custprop(Custprops, Rn, cp, val) {
8524
    switch((cp[0].match(/dt:dt="([\w.]+)"/)||["",""])[1]) {
8525
        case "boolean": val = parsexmlbool(val); break;
8526
        case "i2": case "int": val = parseInt(val, 10); break;
8527
        case "r4": case "float": val = parseFloat(val); break;
8528
        case "date": case "dateTime.tz": val = new Date(val); break;
8529
        case "i8": case "string": case "fixed": case "uuid": case "bin.base64": break;
8530
        default: throw "bad custprop:" + cp[0];
8531
    }
8532
    Custprops[unescapexml(Rn[3])] = val;
8533
}
8534
 
8535
function safe_format_xlml(cell, nf, o) {
8536
    try {
8537
        if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
8538
        else if(nf === "General") {
8539
            if(cell.t === 'n') {
8540
                if((cell.v|0) === cell.v) cell.w = SSF._general_int(cell.v);
8541
                else cell.w = SSF._general_num(cell.v);
8542
            }
8543
            else cell.w = SSF._general(cell.v);
8544
        }
8545
        else cell.w = xlml_format(nf||"General", cell.v);
8546
        if(o.cellNF) cell.z = XLMLFormatMap[nf]||nf||"General";
8547
    } catch(e) { if(o.WTF) throw e; }
8548
}
8549
 
8550
function process_style_xlml(styles, stag, opts) {
8551
    if(opts.cellStyles) {
8552
        if(stag.Interior) {
8553
            var I = stag.Interior;
8554
            if(I.Pattern) I.patternType = XLMLPatternTypeMap[I.Pattern] || I.Pattern;
8555
        }
8556
    }
8557
    styles[stag.ID] = stag;
8558
}
8559
 
8560
/* TODO: there must exist some form of OSP-blessed spec */
8561
function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, o) {
8562
    var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
8563
    var interiors = [];
8564
    if(sid === undefined && row) sid = row.StyleID;
8565
    if(sid === undefined && csty) sid = csty.StyleID;
8566
    while(styles[sid] !== undefined) {
8567
        if(styles[sid].nf) nf = styles[sid].nf;
8568
        if(styles[sid].Interior) interiors.push(styles[sid].Interior);
8569
        if(!styles[sid].Parent) break;
8570
        sid = styles[sid].Parent;
8571
    }
8572
    switch(data.Type) {
8573
        case 'Boolean':
8574
            cell.t = 'b';
8575
            cell.v = parsexmlbool(xml);
8576
            break;
8577
        case 'String':
8578
            cell.t = 's'; cell.r = xlml_fixstr(unescapexml(xml));
8579
            cell.v = xml.indexOf("<") > -1 ? ss : cell.r;
8580
            break;
8581
        case 'DateTime':
8582
            cell.v = (Date.parse(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
8583
            if(cell.v !== cell.v) cell.v = unescapexml(xml);
8584
            else if(cell.v >= 1 && cell.v<60) cell.v = cell.v -1;
8585
            if(!nf || nf == "General") nf = "yyyy-mm-dd";
8586
            /* falls through */
8587
        case 'Number':
8588
            if(cell.v === undefined) cell.v=+xml;
8589
            if(!cell.t) cell.t = 'n';
8590
            break;
8591
        case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; cell.w = xml; break;
8592
        default: cell.t = 's'; cell.v = xlml_fixstr(ss); break;
8593
    }
8594
    safe_format_xlml(cell, nf, o);
8595
    if(o.cellFormula != null && cell.Formula) {
8596
        cell.f = rc_to_a1(unescapexml(cell.Formula), base);
8597
        cell.Formula = undefined;
8598
    }
8599
    if(o.cellStyles) {
8600
        interiors.forEach(function(x) {
8601
            if(!S.patternType && x.patternType) S.patternType = x.patternType;
8602
        });
8603
        cell.s = S;
8604
    }
8605
    cell.ixfe = cell.StyleID !== undefined ? cell.StyleID : 'Default';
8606
}
8607
 
8608
function xlml_clean_comment(comment) {
8609
    comment.t = comment.v;
8610
    comment.v = comment.w = comment.ixfe = undefined;
8611
}
8612
 
8613
function xlml_normalize(d) {
8614
    if(has_buf && Buffer.isBuffer(d)) return d.toString('utf8');
8615
    if(typeof d === 'string') return d;
8616
    throw "badf";
8617
}
8618
 
8619
/* TODO: Everything */
8620
var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
8621
function parse_xlml_xml(d, opts) {
8622
    var str = xlml_normalize(d);
8623
    var Rn;
8624
    var state = [], tmp;
8625
    var sheets = {}, sheetnames = [], cursheet = {}, sheetname = "";
8626
    var table = {}, cell = {}, row = {}, dtag, didx;
8627
    var c = 0, r = 0;
8628
    var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} };
8629
    var styles = {}, stag = {};
8630
    var ss = "", fidx = 0;
8631
    var mergecells = [];
8632
    var Props = {}, Custprops = {}, pidx = 0, cp = {};
8633
    var comments = [], comment = {};
8634
    var cstys = [], csty;
8635
    xlmlregex.lastIndex = 0;
8636
    while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
8637
        case 'Data':
8638
            if(state[state.length-1][1]) break;
8639
            if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]=="Comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, opts);
8640
            else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; }
8641
            break;
8642
        case 'Cell':
8643
            if(Rn[1]==='/'){
8644
                if(comments.length > 0) cell.c = comments;
8645
                if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== undefined) cursheet[encode_col(c) + encode_row(r)] = cell;
8646
                if(cell.HRef) {
8647
                    cell.l = {Target:cell.HRef, tooltip:cell.HRefScreenTip};
8648
                    cell.HRef = cell.HRefScreenTip = undefined;
8649
                }
8650
                if(cell.MergeAcross || cell.MergeDown) {
8651
                    var cc = c + (parseInt(cell.MergeAcross,10)|0);
8652
                    var rr = r + (parseInt(cell.MergeDown,10)|0);
8653
                    mergecells.push({s:{c:c,r:r},e:{c:cc,r:rr}});
8654
                }
8655
                ++c;
8656
                if(cell.MergeAcross) c += +cell.MergeAcross;
8657
            } else {
8658
                cell = xlml_parsexmltagobj(Rn[0]);
8659
                if(cell.Index) c = +cell.Index - 1;
8660
                if(c < refguess.s.c) refguess.s.c = c;
8661
                if(c > refguess.e.c) refguess.e.c = c;
8662
                if(Rn[0].substr(-2) === "/>") ++c;
8663
                comments = [];
8664
            }
8665
            break;
8666
        case 'Row':
8667
            if(Rn[1]==='/' || Rn[0].substr(-2) === "/>") {
8668
                if(r < refguess.s.r) refguess.s.r = r;
8669
                if(r > refguess.e.r) refguess.e.r = r;
8670
                if(Rn[0].substr(-2) === "/>") {
8671
                    row = xlml_parsexmltag(Rn[0]);
8672
                    if(row.Index) r = +row.Index - 1;
8673
                }
8674
                c = 0; ++r;
8675
            } else {
8676
                row = xlml_parsexmltag(Rn[0]);
8677
                if(row.Index) r = +row.Index - 1;
8678
            }
8679
            break;
8680
        case 'Worksheet': /* TODO: read range from FullRows/FullColumns */
8681
            if(Rn[1]==='/'){
8682
                if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
8683
                sheetnames.push(sheetname);
8684
                if(refguess.s.r <= refguess.e.r && refguess.s.c <= refguess.e.c) cursheet["!ref"] = encode_range(refguess);
8685
                if(mergecells.length) cursheet["!merges"] = mergecells;
8686
                sheets[sheetname] = cursheet;
8687
            } else {
8688
                refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} };
8689
                r = c = 0;
8690
                state.push([Rn[3], false]);
8691
                tmp = xlml_parsexmltag(Rn[0]);
8692
                sheetname = tmp.Name;
8693
                cursheet = {};
8694
                mergecells = [];
8695
            }
8696
            break;
8697
        case 'Table':
8698
            if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
8699
            else if(Rn[0].slice(-2) == "/>") break;
8700
            else {
8701
                table = xlml_parsexmltag(Rn[0]);
8702
                state.push([Rn[3], false]);
8703
                cstys = [];
8704
            }
8705
            break;
8706
 
8707
        case 'Style':
8708
            if(Rn[1]==='/') process_style_xlml(styles, stag, opts);
8709
            else stag = xlml_parsexmltag(Rn[0]);
8710
            break;
8711
 
8712
        case 'NumberFormat':
8713
            stag.nf = xlml_parsexmltag(Rn[0]).Format || "General";
8714
            break;
8715
 
8716
        case 'Column':
8717
            if(state[state.length-1][0] !== 'Table') break;
8718
            csty = xlml_parsexmltag(Rn[0]);
8719
            cstys[(csty.Index-1||cstys.length)] = csty;
8720
            for(var i = 0; i < +csty.Span; ++i) cstys[cstys.length] = csty;
8721
            break;
8722
 
8723
        case 'NamedRange': break;
8724
        case 'NamedCell': break;
8725
        case 'B': break;
8726
        case 'I': break;
8727
        case 'U': break;
8728
        case 'S': break;
8729
        case 'Sub': break;
8730
        case 'Sup': break;
8731
        case 'Span': break;
8732
        case 'Border': break;
8733
        case 'Alignment': break;
8734
        case 'Borders': break;
8735
        case 'Font':
8736
            if(Rn[0].substr(-2) === "/>") break;
8737
            else if(Rn[1]==="/") ss += str.slice(fidx, Rn.index);
8738
            else fidx = Rn.index + Rn[0].length;
8739
            break;
8740
        case 'Interior':
8741
            if(!opts.cellStyles) break;
8742
            stag.Interior = xlml_parsexmltag(Rn[0]);
8743
            break;
8744
        case 'Protection': break;
8745
 
8746
        case 'Author':
8747
        case 'Title':
8748
        case 'Description':
8749
        case 'Created':
8750
        case 'Keywords':
8751
        case 'Subject':
8752
        case 'Category':
8753
        case 'Company':
8754
        case 'LastAuthor':
8755
        case 'LastSaved':
8756
        case 'LastPrinted':
8757
        case 'Version':
8758
        case 'Revision':
8759
        case 'TotalTime':
8760
        case 'HyperlinkBase':
8761
        case 'Manager':
8762
            if(Rn[0].substr(-2) === "/>") break;
8763
            else if(Rn[1]==="/") xlml_set_prop(Props, Rn[3], str.slice(pidx, Rn.index));
8764
            else pidx = Rn.index + Rn[0].length;
8765
            break;
8766
        case 'Paragraphs': break;
8767
 
8768
        case 'Styles':
8769
        case 'Workbook':
8770
            if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
8771
            else state.push([Rn[3], false]);
8772
            break;
8773
 
8774
        case 'Comment':
8775
            if(Rn[1]==='/'){
8776
                if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
8777
                xlml_clean_comment(comment);
8778
                comments.push(comment);
8779
            } else {
8780
                state.push([Rn[3], false]);
8781
                tmp = xlml_parsexmltag(Rn[0]);
8782
                comment = {a:tmp.Author};
8783
            }
8784
            break;
8785
 
8786
        case 'Name': break;
8787
 
8788
        case 'ComponentOptions':
8789
        case 'DocumentProperties':
8790
        case 'CustomDocumentProperties':
8791
        case 'OfficeDocumentSettings':
8792
        case 'PivotTable':
8793
        case 'PivotCache':
8794
        case 'Names':
8795
        case 'MapInfo':
8796
        case 'PageBreaks':
8797
        case 'QueryTable':
8798
        case 'DataValidation':
8799
        case 'AutoFilter':
8800
        case 'Sorting':
8801
        case 'Schema':
8802
        case 'data':
8803
        case 'ConditionalFormatting':
8804
        case 'SmartTagType':
8805
        case 'SmartTags':
8806
        case 'ExcelWorkbook':
8807
        case 'WorkbookOptions':
8808
        case 'WorksheetOptions':
8809
            if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
8810
            else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
8811
            break;
8812
 
8813
        default:
8814
            var seen = true;
8815
            switch(state[state.length-1][0]) {
8816
                /* OfficeDocumentSettings */
8817
                case 'OfficeDocumentSettings': switch(Rn[3]) {
8818
                    case 'AllowPNG': break;
8819
                    case 'RemovePersonalInformation': break;
8820
                    case 'DownloadComponents': break;
8821
                    case 'LocationOfComponents': break;
8822
                    case 'Colors': break;
8823
                    case 'Color': break;
8824
                    case 'Index': break;
8825
                    case 'RGB': break;
8826
                    case 'PixelsPerInch': break;
8827
                    case 'TargetScreenSize': break;
8828
                    case 'ReadOnlyRecommended': break;
8829
                    default: seen = false;
8830
                } break;
8831
 
8832
                /* ComponentOptions */
8833
                case 'ComponentOptions': switch(Rn[3]) {
8834
                    case 'Toolbar': break;
8835
                    case 'HideOfficeLogo': break;
8836
                    case 'SpreadsheetAutoFit': break;
8837
                    case 'Label': break;
8838
                    case 'Caption': break;
8839
                    case 'MaxHeight': break;
8840
                    case 'MaxWidth': break;
8841
                    case 'NextSheetNumber': break;
8842
                    default: seen = false;
8843
                } break;
8844
 
8845
                /* ExcelWorkbook */
8846
                case 'ExcelWorkbook': switch(Rn[3]) {
8847
                    case 'WindowHeight': break;
8848
                    case 'WindowWidth': break;
8849
                    case 'WindowTopX': break;
8850
                    case 'WindowTopY': break;
8851
                    case 'TabRatio': break;
8852
                    case 'ProtectStructure': break;
8853
                    case 'ProtectWindows': break;
8854
                    case 'ActiveSheet': break;
8855
                    case 'DisplayInkNotes': break;
8856
                    case 'FirstVisibleSheet': break;
8857
                    case 'SupBook': break;
8858
                    case 'SheetName': break;
8859
                    case 'SheetIndex': break;
8860
                    case 'SheetIndexFirst': break;
8861
                    case 'SheetIndexLast': break;
8862
                    case 'Dll': break;
8863
                    case 'AcceptLabelsInFormulas': break;
8864
                    case 'DoNotSaveLinkValues': break;
8865
                    case 'Date1904': break;
8866
                    case 'Iteration': break;
8867
                    case 'MaxIterations': break;
8868
                    case 'MaxChange': break;
8869
                    case 'Path': break;
8870
                    case 'Xct': break;
8871
                    case 'Count': break;
8872
                    case 'SelectedSheets': break;
8873
                    case 'Calculation': break;
8874
                    case 'Uncalced': break;
8875
                    case 'StartupPrompt': break;
8876
                    case 'Crn': break;
8877
                    case 'ExternName': break;
8878
                    case 'Formula': break;
8879
                    case 'ColFirst': break;
8880
                    case 'ColLast': break;
8881
                    case 'WantAdvise': break;
8882
                    case 'Boolean': break;
8883
                    case 'Error': break;
8884
                    case 'Text': break;
8885
                    case 'OLE': break;
8886
                    case 'NoAutoRecover': break;
8887
                    case 'PublishObjects': break;
8888
                    case 'DoNotCalculateBeforeSave': break;
8889
                    case 'Number': break;
8890
                    case 'RefModeR1C1': break;
8891
                    case 'EmbedSaveSmartTags': break;
8892
                    default: seen = false;
8893
                } break;
8894
 
8895
                /* WorkbookOptions */
8896
                case 'WorkbookOptions': switch(Rn[3]) {
8897
                    case 'OWCVersion': break;
8898
                    case 'Height': break;
8899
                    case 'Width': break;
8900
                    default: seen = false;
8901
                } break;
8902
 
8903
                /* WorksheetOptions */
8904
                case 'WorksheetOptions': switch(Rn[3]) {
8905
                    case 'Unsynced': break;
8906
                    case 'Visible': break;
8907
                    case 'Print': break;
8908
                    case 'Panes': break;
8909
                    case 'Scale': break;
8910
                    case 'Pane': break;
8911
                    case 'Number': break;
8912
                    case 'Layout': break;
8913
                    case 'Header': break;
8914
                    case 'Footer': break;
8915
                    case 'PageSetup': break;
8916
                    case 'PageMargins': break;
8917
                    case 'Selected': break;
8918
                    case 'ProtectObjects': break;
8919
                    case 'EnableSelection': break;
8920
                    case 'ProtectScenarios': break;
8921
                    case 'ValidPrinterInfo': break;
8922
                    case 'HorizontalResolution': break;
8923
                    case 'VerticalResolution': break;
8924
                    case 'NumberofCopies': break;
8925
                    case 'ActiveRow': break;
8926
                    case 'ActiveCol': break;
8927
                    case 'ActivePane': break;
8928
                    case 'TopRowVisible': break;
8929
                    case 'TopRowBottomPane': break;
8930
                    case 'LeftColumnVisible': break;
8931
                    case 'LeftColumnRightPane': break;
8932
                    case 'FitToPage': break;
8933
                    case 'RangeSelection': break;
8934
                    case 'PaperSizeIndex': break;
8935
                    case 'PageLayoutZoom': break;
8936
                    case 'PageBreakZoom': break;
8937
                    case 'FilterOn': break;
8938
                    case 'DoNotDisplayGridlines': break;
8939
                    case 'SplitHorizontal': break;
8940
                    case 'SplitVertical': break;
8941
                    case 'FreezePanes': break;
8942
                    case 'FrozenNoSplit': break;
8943
                    case 'FitWidth': break;
8944
                    case 'FitHeight': break;
8945
                    case 'CommentsLayout': break;
8946
                    case 'Zoom': break;
8947
                    case 'LeftToRight': break;
8948
                    case 'Gridlines': break;
8949
                    case 'AllowSort': break;
8950
                    case 'AllowFilter': break;
8951
                    case 'AllowInsertRows': break;
8952
                    case 'AllowDeleteRows': break;
8953
                    case 'AllowInsertCols': break;
8954
                    case 'AllowDeleteCols': break;
8955
                    case 'AllowInsertHyperlinks': break;
8956
                    case 'AllowFormatCells': break;
8957
                    case 'AllowSizeCols': break;
8958
                    case 'AllowSizeRows': break;
8959
                    case 'NoSummaryRowsBelowDetail': break;
8960
                    case 'TabColorIndex': break;
8961
                    case 'DoNotDisplayHeadings': break;
8962
                    case 'ShowPageLayoutZoom': break;
8963
                    case 'NoSummaryColumnsRightDetail': break;
8964
                    case 'BlackAndWhite': break;
8965
                    case 'DoNotDisplayZeros': break;
8966
                    case 'DisplayPageBreak': break;
8967
                    case 'RowColHeadings': break;
8968
                    case 'DoNotDisplayOutline': break;
8969
                    case 'NoOrientation': break;
8970
                    case 'AllowUsePivotTables': break;
8971
                    case 'ZeroHeight': break;
8972
                    case 'ViewableRange': break;
8973
                    case 'Selection': break;
8974
                    case 'ProtectContents': break;
8975
                    default: seen = false;
8976
                } break;
8977
 
8978
                /* PivotTable */
8979
                case 'PivotTable': case 'PivotCache': switch(Rn[3]) {
8980
                    case 'ImmediateItemsOnDrop': break;
8981
                    case 'ShowPageMultipleItemLabel': break;
8982
                    case 'CompactRowIndent': break;
8983
                    case 'Location': break;
8984
                    case 'PivotField': break;
8985
                    case 'Orientation': break;
8986
                    case 'LayoutForm': break;
8987
                    case 'LayoutSubtotalLocation': break;
8988
                    case 'LayoutCompactRow': break;
8989
                    case 'Position': break;
8990
                    case 'PivotItem': break;
8991
                    case 'DataType': break;
8992
                    case 'DataField': break;
8993
                    case 'SourceName': break;
8994
                    case 'ParentField': break;
8995
                    case 'PTLineItems': break;
8996
                    case 'PTLineItem': break;
8997
                    case 'CountOfSameItems': break;
8998
                    case 'Item': break;
8999
                    case 'ItemType': break;
9000
                    case 'PTSource': break;
9001
                    case 'CacheIndex': break;
9002
                    case 'ConsolidationReference': break;
9003
                    case 'FileName': break;
9004
                    case 'Reference': break;
9005
                    case 'NoColumnGrand': break;
9006
                    case 'NoRowGrand': break;
9007
                    case 'BlankLineAfterItems': break;
9008
                    case 'Hidden': break;
9009
                    case 'Subtotal': break;
9010
                    case 'BaseField': break;
9011
                    case 'MapChildItems': break;
9012
                    case 'Function': break;
9013
                    case 'RefreshOnFileOpen': break;
9014
                    case 'PrintSetTitles': break;
9015
                    case 'MergeLabels': break;
9016
                    case 'DefaultVersion': break;
9017
                    case 'RefreshName': break;
9018
                    case 'RefreshDate': break;
9019
                    case 'RefreshDateCopy': break;
9020
                    case 'VersionLastRefresh': break;
9021
                    case 'VersionLastUpdate': break;
9022
                    case 'VersionUpdateableMin': break;
9023
                    case 'VersionRefreshableMin': break;
9024
                    case 'Calculation': break;
9025
                    default: seen = false;
9026
                } break;
9027
 
9028
                /* PageBreaks */
9029
                case 'PageBreaks': switch(Rn[3]) {
9030
                    case 'ColBreaks': break;
9031
                    case 'ColBreak': break;
9032
                    case 'RowBreaks': break;
9033
                    case 'RowBreak': break;
9034
                    case 'ColStart': break;
9035
                    case 'ColEnd': break;
9036
                    case 'RowEnd': break;
9037
                    default: seen = false;
9038
                } break;
9039
 
9040
                /* AutoFilter */
9041
                case 'AutoFilter': switch(Rn[3]) {
9042
                    case 'AutoFilterColumn': break;
9043
                    case 'AutoFilterCondition': break;
9044
                    case 'AutoFilterAnd': break;
9045
                    case 'AutoFilterOr': break;
9046
                    default: seen = false;
9047
                } break;
9048
 
9049
                /* QueryTable */
9050
                case 'QueryTable': switch(Rn[3]) {
9051
                    case 'Id': break;
9052
                    case 'AutoFormatFont': break;
9053
                    case 'AutoFormatPattern': break;
9054
                    case 'QuerySource': break;
9055
                    case 'QueryType': break;
9056
                    case 'EnableRedirections': break;
9057
                    case 'RefreshedInXl9': break;
9058
                    case 'URLString': break;
9059
                    case 'HTMLTables': break;
9060
                    case 'Connection': break;
9061
                    case 'CommandText': break;
9062
                    case 'RefreshInfo': break;
9063
                    case 'NoTitles': break;
9064
                    case 'NextId': break;
9065
                    case 'ColumnInfo': break;
9066
                    case 'OverwriteCells': break;
9067
                    case 'DoNotPromptForFile': break;
9068
                    case 'TextWizardSettings': break;
9069
                    case 'Source': break;
9070
                    case 'Number': break;
9071
                    case 'Decimal': break;
9072
                    case 'ThousandSeparator': break;
9073
                    case 'TrailingMinusNumbers': break;
9074
                    case 'FormatSettings': break;
9075
                    case 'FieldType': break;
9076
                    case 'Delimiters': break;
9077
                    case 'Tab': break;
9078
                    case 'Comma': break;
9079
                    case 'AutoFormatName': break;
9080
                    case 'VersionLastEdit': break;
9081
                    case 'VersionLastRefresh': break;
9082
                    default: seen = false;
9083
                } break;
9084
 
9085
                /* Sorting */
9086
                case 'Sorting':
9087
                /* ConditionalFormatting */
9088
                case 'ConditionalFormatting':
9089
                /* DataValidation */
9090
                case 'DataValidation': switch(Rn[3]) {
9091
                    case 'Range': break;
9092
                    case 'Type': break;
9093
                    case 'Min': break;
9094
                    case 'Max': break;
9095
                    case 'Sort': break;
9096
                    case 'Descending': break;
9097
                    case 'Order': break;
9098
                    case 'CaseSensitive': break;
9099
                    case 'Value': break;
9100
                    case 'ErrorStyle': break;
9101
                    case 'ErrorMessage': break;
9102
                    case 'ErrorTitle': break;
9103
                    case 'CellRangeList': break;
9104
                    case 'InputMessage': break;
9105
                    case 'InputTitle': break;
9106
                    case 'ComboHide': break;
9107
                    case 'InputHide': break;
9108
                    case 'Condition': break;
9109
                    case 'Qualifier': break;
9110
                    case 'UseBlank': break;
9111
                    case 'Value1': break;
9112
                    case 'Value2': break;
9113
                    case 'Format': break;
9114
                    default: seen = false;
9115
                } break;
9116
 
9117
                /* MapInfo (schema) */
9118
                case 'MapInfo': case 'Schema': case 'data': switch(Rn[3]) {
9119
                    case 'Map': break;
9120
                    case 'Entry': break;
9121
                    case 'Range': break;
9122
                    case 'XPath': break;
9123
                    case 'Field': break;
9124
                    case 'XSDType': break;
9125
                    case 'FilterOn': break;
9126
                    case 'Aggregate': break;
9127
                    case 'ElementType': break;
9128
                    case 'AttributeType': break;
9129
                /* These are from xsd (XML Schema Definition) */
9130
                    case 'schema':
9131
                    case 'element':
9132
                    case 'complexType':
9133
                    case 'datatype':
9134
                    case 'all':
9135
                    case 'attribute':
9136
                    case 'extends': break;
9137
 
9138
                    case 'row': break;
9139
                    default: seen = false;
9140
                } break;
9141
 
9142
                /* SmartTags (can be anything) */
9143
                case 'SmartTags': break;
9144
 
9145
                default: seen = false; break;
9146
            }
9147
            if(seen) break;
9148
            /* CustomDocumentProperties */
9149
            if(!state[state.length-1][1]) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
9150
            if(state[state.length-1][0]==='CustomDocumentProperties') {
9151
                if(Rn[0].substr(-2) === "/>") break;
9152
                else if(Rn[1]==="/") xlml_set_custprop(Custprops, Rn, cp, str.slice(pidx, Rn.index));
9153
                else { cp = Rn; pidx = Rn.index + Rn[0].length; }
9154
                break;
9155
            }
9156
            if(opts.WTF) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
9157
    }
9158
    var out = {};
9159
    if(!opts.bookSheets && !opts.bookProps) out.Sheets = sheets;
9160
    out.SheetNames = sheetnames;
9161
    out.SSF = SSF.get_table();
9162
    out.Props = Props;
9163
    out.Custprops = Custprops;
9164
    return out;
9165
}
9166
 
9167
function parse_xlml(data, opts) {
9168
    fix_read_opts(opts=opts||{});
9169
    switch(opts.type||"base64") {
9170
        case "base64": return parse_xlml_xml(Base64.decode(data), opts);
9171
        case "binary": case "buffer": case "file": return parse_xlml_xml(data, opts);
9172
        case "array": return parse_xlml_xml(data.map(_chr).join(""), opts);
9173
    }
9174
}
9175
 
9176
function write_xlml(wb, opts) { }
9177
 
9178
/* [MS-OLEDS] 2.3.8 CompObjStream */
9179
function parse_compobj(obj) {
9180
    var v = {};
9181
    var o = obj.content;
9182
 
9183
    /* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
9184
    var l = 28, m;
9185
    m = __lpstr(o, l);
9186
    l += 4 + __readUInt32LE(o,l);
9187
    v.UserType = m;
9188
 
9189
    /* [MS-OLEDS] 2.3.1 ClipboardFormatOrAnsiString */
9190
    m = __readUInt32LE(o,l); l+= 4;
9191
    switch(m) {
9192
        case 0x00000000: break;
9193
        case 0xffffffff: case 0xfffffffe: l+=4; break;
9194
        default:
9195
            if(m > 0x190) throw new Error("Unsupported Clipboard: " + m.toString(16));
9196
            l += m;
9197
    }
9198
 
9199
    m = __lpstr(o, l); l += m.length === 0 ? 0 : 5 + m.length; v.Reserved1 = m;
9200
 
9201
    if((m = __readUInt32LE(o,l)) !== 0x71b2e9f4) return v;
9202
    throw "Unsupported Unicode Extension";
9203
}
9204
 
9205
/* 2.4.58 Continue logic */
9206
function slurp(R, blob, length, opts) {
9207
    var l = length;
9208
    var bufs = [];
9209
    var d = blob.slice(blob.l,blob.l+l);
9210
    if(opts && opts.enc && opts.enc.insitu_decrypt) switch(R.n) {
9211
    case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': break;
9212
    default:
9213
        if(d.length === 0) break;
9214
        opts.enc.insitu_decrypt(d);
9215
    }
9216
    bufs.push(d);
9217
    blob.l += l;
9218
    var next = (XLSRecordEnum[__readUInt16LE(blob,blob.l)]);
9219
    while(next != null && next.n === 'Continue') {
9220
        l = __readUInt16LE(blob,blob.l+2);
9221
        bufs.push(blob.slice(blob.l+4,blob.l+4+l));
9222
        blob.l += 4+l;
9223
        next = (XLSRecordEnum[__readUInt16LE(blob, blob.l)]);
9224
    }
9225
    var b = bconcat(bufs);
9226
    prep_blob(b, 0);
9227
    var ll = 0; b.lens = [];
9228
    for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; }
9229
    return R.f(b, b.length, opts);
9230
}
9231
 
9232
function safe_format_xf(p, opts, date1904) {
9233
    if(!p.XF) return;
9234
    try {
9235
        var fmtid = p.XF.ifmt||0;
9236
        if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
9237
        else if(fmtid === 0) {
9238
            if(p.t === 'n') {
9239
                if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
9240
                else p.w = SSF._general_num(p.v);
9241
            }
9242
            else p.w = SSF._general(p.v);
9243
        }
9244
        else p.w = SSF.format(fmtid,p.v, {date1904:date1904||false});
9245
        if(opts.cellNF) p.z = SSF._table[fmtid];
9246
    } catch(e) { if(opts.WTF) throw e; }
9247
}
9248
 
9249
function make_cell(val, ixfe, t) {
9250
    return {v:val, ixfe:ixfe, t:t};
9251
}
9252
 
9253
// 2.3.2
9254
function parse_workbook(blob, options) {
9255
    var wb = {opts:{}};
9256
    var Sheets = {};
9257
    var out = {};
9258
    var Directory = {};
9259
    var found_sheet = false;
9260
    var range = {};
9261
    var last_formula = null;
9262
    var sst = [];
9263
    var cur_sheet = "";
9264
    var Preamble = {};
9265
    var lastcell, last_cell, cc, cmnt, rng, rngC, rngR;
9266
    var shared_formulae = {};
9267
    var array_formulae = []; /* TODO: something more clever */
9268
    var temp_val;
9269
    var country;
9270
    var cell_valid = true;
9271
    var XFs = []; /* XF records */
9272
    var palette = [];
9273
    var get_rgb = function getrgb(icv) {
9274
        if(icv < 8) return XLSIcv[icv];
9275
        if(icv < 64) return palette[icv-8] || XLSIcv[icv];
9276
        return XLSIcv[icv];
9277
    };
9278
    var process_cell_style = function pcs(cell, line) {
9279
        var xfd = line.XF.data;
9280
        if(!xfd || !xfd.patternType) return;
9281
        line.s = {};
9282
        line.s.patternType = xfd.patternType;
9283
        var t;
9284
        if((t = rgb2Hex(get_rgb(xfd.icvFore)))) { line.s.fgColor = {rgb:t}; }
9285
        if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; }
9286
    };
9287
    var addcell = function addcell(cell, line, options) {
9288
        if(!cell_valid) return;
9289
        if(options.cellStyles && line.XF && line.XF.data) process_cell_style(cell, line);
9290
        lastcell = cell;
9291
        last_cell = encode_cell(cell);
9292
        if(range.s) {
9293
            if(cell.r < range.s.r) range.s.r = cell.r;
9294
            if(cell.c < range.s.c) range.s.c = cell.c;
9295
        }
9296
        if(range.e) {
9297
            if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1;
9298
            if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1;
9299
        }
9300
        if(options.sheetRows && lastcell.r >= options.sheetRows) cell_valid = false;
9301
        else out[last_cell] = line;
9302
    };
9303
    var opts = {
9304
        enc: false, // encrypted
9305
        sbcch: 0, // cch in the preceding SupBook
9306
        snames: [], // sheetnames
9307
        sharedf: shared_formulae, // shared formulae by address
9308
        arrayf: array_formulae, // array formulae array
9309
        rrtabid: [], // RRTabId
9310
        lastuser: "", // Last User from WriteAccess
9311
        biff: 8, // BIFF version
9312
        codepage: 0, // CP from CodePage record
9313
        winlocked: 0, // fLockWn from WinProtect
9314
        wtf: false
9315
    };
9316
    if(options.password) opts.password = options.password;
9317
    var mergecells = [];
9318
    var objects = [];
9319
    var supbooks = [[]]; // 1-indexed, will hold extern names
9320
    var sbc = 0, sbci = 0, sbcli = 0;
9321
    supbooks.SheetNames = opts.snames;
9322
    supbooks.sharedf = opts.sharedf;
9323
    supbooks.arrayf = opts.arrayf;
9324
    var last_Rn = '';
9325
    var file_depth = 0; /* TODO: make a real stack */
9326
 
9327
    /* explicit override for some broken writers */
9328
    opts.codepage = 1200;
9329
    set_cp(1200);
9330
 
9331
    while(blob.l < blob.length - 1) {
9332
        var s = blob.l;
9333
        var RecordType = blob.read_shift(2);
9334
        if(RecordType === 0 && last_Rn === 'EOF') break;
9335
        var length = (blob.l === blob.length ? 0 : blob.read_shift(2)), y;
9336
        var R = XLSRecordEnum[RecordType];
9337
        if(R && R.f) {
9338
            if(options.bookSheets) {
9339
                if(last_Rn === 'BoundSheet8' && R.n !== 'BoundSheet8') break;
9340
            }
9341
            last_Rn = R.n;
9342
            if(R.r === 2 || R.r == 12) {
9343
                var rt = blob.read_shift(2); length -= 2;
9344
                if(!opts.enc && rt !== RecordType) throw "rt mismatch";
9345
                if(R.r == 12){ blob.l += 10; length -= 10; } // skip FRT
9346
            }
9347
            //console.error(R,blob.l,length,blob.length);
9348
            var val;
9349
            if(R.n === 'EOF') val = R.f(blob, length, opts);
9350
            else val = slurp(R, blob, length, opts);
9351
            var Rn = R.n;
9352
            /* BIFF5 overrides */
9353
            if(opts.biff === 5 || opts.biff === 2) switch(Rn) {
9354
                case 'Lbl': Rn = 'Label'; break;
9355
            }
9356
            /* nested switch statements to workaround V8 128 limit */
9357
            switch(Rn) {
9358
                /* Workbook Options */
9359
                case 'Date1904': wb.opts.Date1904 = val; break;
9360
                case 'WriteProtect': wb.opts.WriteProtect = true; break;
9361
                case 'FilePass':
9362
                    if(!opts.enc) blob.l = 0;
9363
                    opts.enc = val;
9364
                    if(opts.WTF) console.error(val);
9365
                    if(!options.password) throw new Error("File is password-protected");
9366
                    if(val.Type !== 0) throw new Error("Encryption scheme unsupported");
9367
                    if(!val.valid) throw new Error("Password is incorrect");
9368
                    break;
9369
                case 'WriteAccess': opts.lastuser = val; break;
9370
                case 'FileSharing': break; //TODO
9371
                case 'CodePage':
9372
                    /* overrides based on test cases */
9373
                    if(val === 0x5212) val = 1200;
9374
                    else if(val === 0x8001) val = 1252;
9375
                    opts.codepage = val;
9376
                    set_cp(val);
9377
                    break;
9378
                case 'RRTabId': opts.rrtabid = val; break;
9379
                case 'WinProtect': opts.winlocked = val; break;
9380
                case 'Template': break; // TODO
9381
                case 'RefreshAll': wb.opts.RefreshAll = val; break;
9382
                case 'BookBool': break; // TODO
9383
                case 'UsesELFs': /* if(val) console.error("Unsupported ELFs"); */ break;
9384
                case 'MTRSettings': {
9385
                    if(val[0] && val[1]) throw "Unsupported threads: " + val;
9386
                } break; // TODO: actually support threads
9387
                case 'CalcCount': wb.opts.CalcCount = val; break;
9388
                case 'CalcDelta': wb.opts.CalcDelta = val; break;
9389
                case 'CalcIter': wb.opts.CalcIter = val; break;
9390
                case 'CalcMode': wb.opts.CalcMode = val; break;
9391
                case 'CalcPrecision': wb.opts.CalcPrecision = val; break;
9392
                case 'CalcSaveRecalc': wb.opts.CalcSaveRecalc = val; break;
9393
                case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
9394
                case 'Uncalced': break;
9395
                case 'ForceFullCalculation': wb.opts.FullCalc = val; break;
9396
                case 'WsBool': break; // TODO
9397
                case 'XF': XFs.push(val); break;
9398
                case 'ExtSST': break; // TODO
9399
                case 'BookExt': break; // TODO
9400
                case 'RichTextStream': break;
9401
                case 'BkHim': break;
9402
 
9403
                case 'SupBook': supbooks[++sbc] = [val]; sbci = 0; break;
9404
                case 'ExternName': supbooks[sbc][++sbci] = val; break;
9405
                case 'Index': break; // TODO
9406
                case 'Lbl': supbooks[0][++sbcli] = val; break;
9407
                case 'ExternSheet': supbooks[sbc] = supbooks[sbc].concat(val); sbci += val.length; break;
9408
 
9409
                case 'Protect': out["!protect"] = val; break; /* for sheet or book */
9410
                case 'Password': if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
9411
                case 'Prot4Rev': case 'Prot4RevPass': break; /*TODO: Revision Control*/
9412
 
9413
                case 'BoundSheet8': {
9414
                    Directory[val.pos] = val;
9415
                    opts.snames.push(val.name);
9416
                } break;
9417
                case 'EOF': {
9418
                    if(--file_depth) break;
9419
                    if(range.e) {
9420
                        out["!range"] = range;
9421
                        if(range.e.r > 0 && range.e.c > 0) {
9422
                            range.e.r--; range.e.c--;
9423
                            out["!ref"] = encode_range(range);
9424
                            range.e.r++; range.e.c++;
9425
                        }
9426
                        if(mergecells.length > 0) out["!merges"] = mergecells;
9427
                        if(objects.length > 0) out["!objects"] = objects;
9428
                    }
9429
                    if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out;
9430
                    out = {};
9431
                } break;
9432
                case 'BOF': {
9433
                    if(opts.biff !== 8);
9434
                    else if(val.BIFFVer === 0x0500) opts.biff = 5;
9435
                    else if(val.BIFFVer === 0x0002) opts.biff = 2;
9436
                    else if(val.BIFFVer === 0x0007) opts.biff = 2;
9437
                    if(file_depth++) break;
9438
                    cell_valid = true;
9439
                    out = {};
9440
                    if(opts.biff === 2) {
9441
                        if(cur_sheet === "") cur_sheet = "Sheet1";
9442
                        range = {s:{r:0,c:0},e:{r:0,c:0}};
9443
                    }
9444
                    else cur_sheet = (Directory[s] || {name:""}).name;
9445
                    mergecells = [];
9446
                    objects = [];
9447
                } break;
9448
                case 'Number': case 'BIFF2NUM': {
9449
                    temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:'n'};
9450
                    if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
9451
                    addcell({c:val.c, r:val.r}, temp_val, options);
9452
                } break;
9453
                case 'BoolErr': {
9454
                    temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t};
9455
                    if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
9456
                    addcell({c:val.c, r:val.r}, temp_val, options);
9457
                } break;
9458
                case 'RK': {
9459
                    temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'};
9460
                    if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
9461
                    addcell({c:val.c, r:val.r}, temp_val, options);
9462
                } break;
9463
                case 'MulRk': {
9464
                    for(var j = val.c; j <= val.C; ++j) {
9465
                        var ixfe = val.rkrec[j-val.c][0];
9466
                        temp_val= {ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'};
9467
                        if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
9468
                        addcell({c:j, r:val.r}, temp_val, options);
9469
                    }
9470
                } break;
9471
                case 'Formula': {
9472
                    switch(val.val) {
9473
                        case 'String': last_formula = val; break;
9474
                        case 'Array Formula': throw "Array Formula unsupported";
9475
                        default:
9476
                            temp_val = {v:val.val, ixfe:val.cell.ixfe, t:val.tt};
9477
                            temp_val.XF = XFs[temp_val.ixfe];
9478
                            if(options.cellFormula) temp_val.f = "="+stringify_formula(val.formula,range,val.cell,supbooks, opts);
9479
                            if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
9480
                            addcell(val.cell, temp_val, options);
9481
                            last_formula = val;
9482
                    }
9483
                } break;
9484
                case 'String': {
9485
                    if(last_formula) {
9486
                        last_formula.val = val;
9487
                        temp_val = {v:last_formula.val, ixfe:last_formula.cell.ixfe, t:'s'};
9488
                        temp_val.XF = XFs[temp_val.ixfe];
9489
                        if(options.cellFormula) temp_val.f = "="+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
9490
                        if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
9491
                        addcell(last_formula.cell, temp_val, options);
9492
                        last_formula = null;
9493
                    }
9494
                } break;
9495
                case 'Array': {
9496
                    array_formulae.push(val);
9497
                } break;
9498
                case 'ShrFmla': {
9499
                    if(!cell_valid) break;
9500
                    //if(options.cellFormula) out[last_cell].f = stringify_formula(val[0], range, lastcell, supbooks, opts);
9501
                    /* TODO: capture range */
9502
                    shared_formulae[encode_cell(last_formula.cell)]= val[0];
9503
                } break;
9504
                case 'LabelSst':
9505
                    //temp_val={v:sst[val.isst].t, ixfe:val.ixfe, t:'s'};
9506
                    temp_val=make_cell(sst[val.isst].t, val.ixfe, 's');
9507
                    temp_val.XF = XFs[temp_val.ixfe];
9508
                    if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
9509
                    addcell({c:val.c, r:val.r}, temp_val, options);
9510
                    break;
9511
                case 'Label': case 'BIFF2STR':
9512
                    /* Some writers erroneously write Label */
9513
                    temp_val=make_cell(val.val, val.ixfe, 's');
9514
                    temp_val.XF = XFs[temp_val.ixfe];
9515
                    if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
9516
                    addcell({c:val.c, r:val.r}, temp_val, options);
9517
                    break;
9518
                case 'Dimensions': {
9519
                    if(file_depth === 1) range = val; /* TODO: stack */
9520
                } break;
9521
                case 'SST': {
9522
                    sst = val;
9523
                } break;
9524
                case 'Format': { /* val = [id, fmt] */
9525
                    SSF.load(val[1], val[0]);
9526
                } break;
9527
 
9528
                case 'MergeCells': mergecells = mergecells.concat(val); break;
9529
 
9530
                case 'Obj': objects[val.cmo[0]] = opts.lastobj = val; break;
9531
                case 'TxO': opts.lastobj.TxO = val; break;
9532
 
9533
                case 'HLink': {
9534
                    for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
9535
                        for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC)
9536
                            if(out[encode_cell({c:rngC,r:rngR})])
9537
                                out[encode_cell({c:rngC,r:rngR})].l = val[1];
9538
                } break;
9539
                case 'HLinkTooltip': {
9540
                    for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
9541
                        for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC)
9542
                            if(out[encode_cell({c:rngC,r:rngR})])
9543
                                out[encode_cell({c:rngC,r:rngR})].l.tooltip = val[1];
9544
                } break;
9545
 
9546
                /* Comments */
9547
                case 'Note': {
9548
                    if(opts.biff <= 5 && opts.biff >= 2) break; /* TODO: BIFF5 */
9549
                    cc = out[encode_cell(val[0])];
9550
                    var noteobj = objects[val[2]];
9551
                    if(!cc) break;
9552
                    if(!cc.c) cc.c = [];
9553
                    cmnt = {a:val[1],t:noteobj.TxO.t};
9554
                    cc.c.push(cmnt);
9555
                } break;
9556
 
9557
                default: switch(R.n) { /* nested */
9558
                case 'ClrtClient': break;
9559
                case 'XFExt': update_xfext(XFs[val.ixfe], val.ext); break;
9560
 
9561
                case 'NameCmt': break;
9562
                case 'Header': break; // TODO
9563
                case 'Footer': break; // TODO
9564
                case 'HCenter': break; // TODO
9565
                case 'VCenter': break; // TODO
9566
                case 'Pls': break; // TODO
9567
                case 'Setup': break; // TODO
9568
                case 'DefColWidth': break; // TODO
9569
                case 'GCW': break;
9570
                case 'LHRecord': break;
9571
                case 'ColInfo': break; // TODO
9572
                case 'Row': break; // TODO
9573
                case 'DBCell': break; // TODO
9574
                case 'MulBlank': break; // TODO
9575
                case 'EntExU2': break; // TODO
9576
                case 'SxView': break; // TODO
9577
                case 'Sxvd': break; // TODO
9578
                case 'SXVI': break; // TODO
9579
                case 'SXVDEx': break; // TODO
9580
                case 'SxIvd': break; // TODO
9581
                case 'SXDI': break; // TODO
9582
                case 'SXLI': break; // TODO
9583
                case 'SXEx': break; // TODO
9584
                case 'QsiSXTag': break; // TODO
9585
                case 'Selection': break;
9586
                case 'Feat': break;
9587
                case 'FeatHdr': case 'FeatHdr11': break;
9588
                case 'Feature11': case 'Feature12': case 'List12': break;
9589
                case 'Blank': break;
9590
                case 'Country': country = val; break;
9591
                case 'RecalcId': break;
9592
                case 'DefaultRowHeight': case 'DxGCol': break; // TODO: htmlify
9593
                case 'Fbi': case 'Fbi2': case 'GelFrame': break;
9594
                case 'Font': break; // TODO
9595
                case 'XFCRC': break; // TODO
9596
                case 'Style': break; // TODO
9597
                case 'StyleExt': break; // TODO
9598
                case 'Palette': palette = val; break; // TODO
9599
                case 'Theme': break; // TODO
9600
                /* Protection */
9601
                case 'ScenarioProtect': break;
9602
                case 'ObjProtect': break;
9603
 
9604
                /* Conditional Formatting */
9605
                case 'CondFmt12': break;
9606
 
9607
                /* Table */
9608
                case 'Table': break; // TODO
9609
                case 'TableStyles': break; // TODO
9610
                case 'TableStyle': break; // TODO
9611
                case 'TableStyleElement': break; // TODO
9612
 
9613
                /* PivotTable */
9614
                case 'SXStreamID': break; // TODO
9615
                case 'SXVS': break; // TODO
9616
                case 'DConRef': break; // TODO
9617
                case 'SXAddl': break; // TODO
9618
                case 'DConBin': break; // TODO
9619
                case 'DConName': break; // TODO
9620
                case 'SXPI': break; // TODO
9621
                case 'SxFormat': break; // TODO
9622
                case 'SxSelect': break; // TODO
9623
                case 'SxRule': break; // TODO
9624
                case 'SxFilt': break; // TODO
9625
                case 'SxItm': break; // TODO
9626
                case 'SxDXF': break; // TODO
9627
 
9628
                /* Scenario Manager */
9629
                case 'ScenMan': break;
9630
 
9631
                /* Data Consolidation */
9632
                case 'DCon': break;
9633
 
9634
                /* Watched Cell */
9635
                case 'CellWatch': break;
9636
 
9637
                /* Print Settings */
9638
                case 'PrintRowCol': break;
9639
                case 'PrintGrid': break;
9640
                case 'PrintSize': break;
9641
 
9642
                case 'XCT': break;
9643
                case 'CRN': break;
9644
 
9645
                case 'Scl': {
9646
                    //console.log("Zoom Level:", val[0]/val[1],val);
9647
                } break;
9648
                case 'SheetExt': {
9649
 
9650
                } break;
9651
                case 'SheetExtOptional': {
9652
 
9653
                } break;
9654
 
9655
                /* VBA */
9656
                case 'ObNoMacros': {
9657
 
9658
                } break;
9659
                case 'ObProj': {
9660
 
9661
                } break;
9662
                case 'CodeName': {
9663
 
9664
                } break;
9665
                case 'GUIDTypeLib': {
9666
 
9667
                } break;
9668
 
9669
                case 'WOpt': break; // TODO: WTF?
9670
                case 'PhoneticInfo': break;
9671
 
9672
                case 'OleObjectSize': break;
9673
 
9674
                /* Differential Formatting */
9675
                case 'DXF': case 'DXFN': case 'DXFN12': case 'DXFN12List': case 'DXFN12NoCB': break;
9676
 
9677
                /* Data Validation */
9678
                case 'Dv': case 'DVal': break;
9679
 
9680
                /* Data Series */
9681
                case 'BRAI': case 'Series': case 'SeriesText': break;
9682
 
9683
                /* Data Connection */
9684
                case 'DConn': break;
9685
                case 'DbOrParamQry': break;
9686
                case 'DBQueryExt': break;
9687
 
9688
                /* Formatting */
9689
                case 'IFmtRecord': break;
9690
                case 'CondFmt': case 'CF': case 'CF12': case 'CFEx': break;
9691
 
9692
                /* Explicitly Ignored */
9693
                case 'Excel9File': break;
9694
                case 'Units': break;
9695
                case 'InterfaceHdr': case 'Mms': case 'InterfaceEnd': case 'DSF': case 'BuiltInFnGroupCount':
9696
                /* View Stuff */
9697
                case 'Window1': case 'Window2': case 'HideObj': case 'GridSet': case 'Guts':
9698
                case 'UserBView': case 'UserSViewBegin': case 'UserSViewEnd':
9699
                case 'Pane': break;
9700
                default: switch(R.n) { /* nested */
9701
                /* Chart */
9702
                case 'Dat':
9703
                case 'Begin': case 'End':
9704
                case 'StartBlock': case 'EndBlock':
9705
                case 'Frame': case 'Area':
9706
                case 'Axis': case 'AxisLine': case 'Tick': break;
9707
                case 'AxesUsed':
9708
                case 'CrtLayout12': case 'CrtLayout12A': case 'CrtLink': case 'CrtLine': case 'CrtMlFrt': case 'CrtMlFrtContinue': break;
9709
                case 'LineFormat': case 'AreaFormat':
9710
                case 'Chart': case 'Chart3d': case 'Chart3DBarShape': case 'ChartFormat': case 'ChartFrtInfo': break;
9711
                case 'PlotArea': case 'PlotGrowth': break;
9712
                case 'SeriesList': case 'SerParent': case 'SerAuxTrend': break;
9713
                case 'DataFormat': case 'SerToCrt': case 'FontX': break;
9714
                case 'CatSerRange': case 'AxcExt': case 'SerFmt': break;
9715
                case 'ShtProps': break;
9716
                case 'DefaultText': case 'Text': case 'CatLab': break;
9717
                case 'DataLabExtContents': break;
9718
                case 'Legend': case 'LegendException': break;
9719
                case 'Pie': case 'Scatter': break;
9720
                case 'PieFormat': case 'MarkerFormat': break;
9721
                case 'StartObject': case 'EndObject': break;
9722
                case 'AlRuns': case 'ObjectLink': break;
9723
                case 'SIIndex': break;
9724
                case 'AttachedLabel': case 'YMult': break;
9725
 
9726
                /* Chart Group */
9727
                case 'Line': case 'Bar': break;
9728
                case 'Surf': break;
9729
 
9730
                /* Axis Group */
9731
                case 'AxisParent': break;
9732
                case 'Pos': break;
9733
                case 'ValueRange': break;
9734
 
9735
                /* Pivot Chart */
9736
                case 'SXViewEx9': break; // TODO
9737
                case 'SXViewLink': break;
9738
                case 'PivotChartBits': break;
9739
                case 'SBaseRef': break;
9740
                case 'TextPropsStream': break;
9741
 
9742
                /* Chart Misc */
9743
                case 'LnExt': break;
9744
                case 'MkrExt': break;
9745
                case 'CrtCoopt': break;
9746
 
9747
                /* Query Table */
9748
                case 'Qsi': case 'Qsif': case 'Qsir': case 'QsiSXTag': break;
9749
                case 'TxtQry': break;
9750
 
9751
                /* Filter */
9752
                case 'FilterMode': break;
9753
                case 'AutoFilter': case 'AutoFilterInfo': break;
9754
                case 'AutoFilter12': break;
9755
                case 'DropDownObjIds': break;
9756
                case 'Sort': break;
9757
                case 'SortData': break;
9758
 
9759
                /* Drawing */
9760
                case 'ShapePropsStream': break;
9761
                case 'MsoDrawing': case 'MsoDrawingGroup': case 'MsoDrawingSelection': break;
9762
                case 'ImData': break;
9763
                /* Pub Stuff */
9764
                case 'WebPub': case 'AutoWebPub':
9765
 
9766
                /* Print Stuff */
9767
                case 'RightMargin': case 'LeftMargin': case 'TopMargin': case 'BottomMargin':
9768
                case 'HeaderFooter': case 'HFPicture': case 'PLV':
9769
                case 'HorizontalPageBreaks': case 'VerticalPageBreaks':
9770
                /* Behavioral */
9771
                case 'Backup': case 'CompressPictures': case 'Compat12': break;
9772
 
9773
                /* Should not Happen */
9774
                case 'Continue': case 'ContinueFrt12': break;
9775
 
9776
                /* Future Records */
9777
                case 'FrtFontList': case 'FrtWrapper': break;
9778
 
9779
                /* BIFF5 records */
9780
                case 'ExternCount': break;
9781
                case 'RString': break;
9782
                case 'TabIdConf': case 'Radar': case 'RadarArea': case 'DropBar': case 'Intl': case 'CoordList': case 'SerAuxErrBar': break;
9783
 
9784
                default: switch(R.n) { /* nested */
9785
                /* Miscellaneous */
9786
                case 'SCENARIO': case 'DConBin': case 'PicF': case 'DataLabExt':
9787
                case 'Lel': case 'BopPop': case 'BopPopCustom': case 'RealTimeData':
9788
                case 'Name': break;
9789
                default: if(options.WTF) throw 'Unrecognized Record ' + R.n;
9790
            }}}}
9791
        } else blob.l += length;
9792
    }
9793
    var sheetnamesraw = opts.biff === 2 ? ['Sheet1'] : Object.keys(Directory).sort(function(a,b) { return Number(a) - Number(b); }).map(function(x){return Directory[x].name;});
9794
    var sheetnames = sheetnamesraw.slice();
9795
    wb.Directory=sheetnamesraw;
9796
    wb.SheetNames=sheetnamesraw;
9797
    if(!options.bookSheets) wb.Sheets=Sheets;
9798
    wb.Preamble=Preamble;
9799
    wb.Strings = sst;
9800
    wb.SSF = SSF.get_table();
9801
    if(opts.enc) wb.Encryption = opts.enc;
9802
    wb.Metadata = {};
9803
    if(country !== undefined) wb.Metadata.Country = country;
9804
    return wb;
9805
}
9806
 
9807
function parse_xlscfb(cfb, options) {
9808
if(!options) options = {};
9809
fix_read_opts(options);
9810
reset_cp();
9811
var CompObj, Summary, Workbook;
9812
if(cfb.find) {
9813
    CompObj = cfb.find('!CompObj');
9814
    Summary = cfb.find('!SummaryInformation');
9815
    Workbook = cfb.find('/Workbook');
9816
} else {
9817
    prep_blob(cfb, 0);
9818
    Workbook = {content: cfb};
9819
}
9820
 
9821
if(!Workbook) Workbook = cfb.find('/Book');
9822
var CompObjP, SummaryP, WorkbookP;
9823
 
9824
if(CompObj) CompObjP = parse_compobj(CompObj);
9825
if(options.bookProps && !options.bookSheets) WorkbookP = {};
9826
else {
9827
    if(Workbook) WorkbookP = parse_workbook(Workbook.content, options, !!Workbook.find);
9828
    else throw new Error("Cannot find Workbook stream");
9829
}
9830
 
9831
if(cfb.find) parse_props(cfb);
9832
 
9833
var props = {};
9834
for(var y in cfb.Summary) props[y] = cfb.Summary[y];
9835
for(y in cfb.DocSummary) props[y] = cfb.DocSummary[y];
9836
WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
9837
if(options.bookFiles) WorkbookP.cfb = cfb;
9838
WorkbookP.CompObjP = CompObjP;
9839
return WorkbookP;
9840
}
9841
 
9842
/* TODO: WTF */
9843
function parse_props(cfb) {
9844
    /* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
9845
    var DSI = cfb.find('!DocumentSummaryInformation');
9846
    if(DSI) try { cfb.DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI); } catch(e) {}
9847
 
9848
    /* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
9849
    var SI = cfb.find('!SummaryInformation');
9850
    if(SI) try { cfb.Summary = parse_PropertySetStream(SI, SummaryPIDSI); } catch(e) {}
9851
}
9852
 
9853
/* [MS-XLSB] 2.3 Record Enumeration */
9854
var XLSBRecordEnum = {
9855
    0x0000: { n:"BrtRowHdr", f:parse_BrtRowHdr },
9856
    0x0001: { n:"BrtCellBlank", f:parse_BrtCellBlank },
9857
    0x0002: { n:"BrtCellRk", f:parse_BrtCellRk },
9858
    0x0003: { n:"BrtCellError", f:parse_BrtCellError },
9859
    0x0004: { n:"BrtCellBool", f:parse_BrtCellBool },
9860
    0x0005: { n:"BrtCellReal", f:parse_BrtCellReal },
9861
    0x0006: { n:"BrtCellSt", f:parse_BrtCellSt },
9862
    0x0007: { n:"BrtCellIsst", f:parse_BrtCellIsst },
9863
    0x0008: { n:"BrtFmlaString", f:parse_BrtFmlaString },
9864
    0x0009: { n:"BrtFmlaNum", f:parse_BrtFmlaNum },
9865
    0x000A: { n:"BrtFmlaBool", f:parse_BrtFmlaBool },
9866
    0x000B: { n:"BrtFmlaError", f:parse_BrtFmlaError },
9867
    0x0010: { n:"BrtFRTArchID$", f:parse_BrtFRTArchID$ },
9868
    0x0013: { n:"BrtSSTItem", f:parse_RichStr },
9869
    0x0014: { n:"BrtPCDIMissing", f:parsenoop },
9870
    0x0015: { n:"BrtPCDINumber", f:parsenoop },
9871
    0x0016: { n:"BrtPCDIBoolean", f:parsenoop },
9872
    0x0017: { n:"BrtPCDIError", f:parsenoop },
9873
    0x0018: { n:"BrtPCDIString", f:parsenoop },
9874
    0x0019: { n:"BrtPCDIDatetime", f:parsenoop },
9875
    0x001A: { n:"BrtPCDIIndex", f:parsenoop },
9876
    0x001B: { n:"BrtPCDIAMissing", f:parsenoop },
9877
    0x001C: { n:"BrtPCDIANumber", f:parsenoop },
9878
    0x001D: { n:"BrtPCDIABoolean", f:parsenoop },
9879
    0x001E: { n:"BrtPCDIAError", f:parsenoop },
9880
    0x001F: { n:"BrtPCDIAString", f:parsenoop },
9881
    0x0020: { n:"BrtPCDIADatetime", f:parsenoop },
9882
    0x0021: { n:"BrtPCRRecord", f:parsenoop },
9883
    0x0022: { n:"BrtPCRRecordDt", f:parsenoop },
9884
    0x0023: { n:"BrtFRTBegin", f:parsenoop },
9885
    0x0024: { n:"BrtFRTEnd", f:parsenoop },
9886
    0x0025: { n:"BrtACBegin", f:parsenoop },
9887
    0x0026: { n:"BrtACEnd", f:parsenoop },
9888
    0x0027: { n:"BrtName", f:parsenoop },
9889
    0x0028: { n:"BrtIndexRowBlock", f:parsenoop },
9890
    0x002A: { n:"BrtIndexBlock", f:parsenoop },
9891
    0x002B: { n:"BrtFont", f:parse_BrtFont },
9892
    0x002C: { n:"BrtFmt", f:parse_BrtFmt },
9893
    0x002D: { n:"BrtFill", f:parsenoop },
9894
    0x002E: { n:"BrtBorder", f:parsenoop },
9895
    0x002F: { n:"BrtXF", f:parse_BrtXF },
9896
    0x0030: { n:"BrtStyle", f:parsenoop },
9897
    0x0031: { n:"BrtCellMeta", f:parsenoop },
9898
    0x0032: { n:"BrtValueMeta", f:parsenoop },
9899
    0x0033: { n:"BrtMdb", f:parsenoop },
9900
    0x0034: { n:"BrtBeginFmd", f:parsenoop },
9901
    0x0035: { n:"BrtEndFmd", f:parsenoop },
9902
    0x0036: { n:"BrtBeginMdx", f:parsenoop },
9903
    0x0037: { n:"BrtEndMdx", f:parsenoop },
9904
    0x0038: { n:"BrtBeginMdxTuple", f:parsenoop },
9905
    0x0039: { n:"BrtEndMdxTuple", f:parsenoop },
9906
    0x003A: { n:"BrtMdxMbrIstr", f:parsenoop },
9907
    0x003B: { n:"BrtStr", f:parsenoop },
9908
    0x003C: { n:"BrtColInfo", f:parsenoop },
9909
    0x003E: { n:"BrtCellRString", f:parsenoop },
9910
    0x003F: { n:"BrtCalcChainItem$", f:parse_BrtCalcChainItem$ },
9911
    0x0040: { n:"BrtDVal", f:parsenoop },
9912
    0x0041: { n:"BrtSxvcellNum", f:parsenoop },
9913
    0x0042: { n:"BrtSxvcellStr", f:parsenoop },
9914
    0x0043: { n:"BrtSxvcellBool", f:parsenoop },
9915
    0x0044: { n:"BrtSxvcellErr", f:parsenoop },
9916
    0x0045: { n:"BrtSxvcellDate", f:parsenoop },
9917
    0x0046: { n:"BrtSxvcellNil", f:parsenoop },
9918
    0x0080: { n:"BrtFileVersion", f:parsenoop },
9919
    0x0081: { n:"BrtBeginSheet", f:parsenoop },
9920
    0x0082: { n:"BrtEndSheet", f:parsenoop },
9921
    0x0083: { n:"BrtBeginBook", f:parsenoop, p:0 },
9922
    0x0084: { n:"BrtEndBook", f:parsenoop },
9923
    0x0085: { n:"BrtBeginWsViews", f:parsenoop },
9924
    0x0086: { n:"BrtEndWsViews", f:parsenoop },
9925
    0x0087: { n:"BrtBeginBookViews", f:parsenoop },
9926
    0x0088: { n:"BrtEndBookViews", f:parsenoop },
9927
    0x0089: { n:"BrtBeginWsView", f:parsenoop },
9928
    0x008A: { n:"BrtEndWsView", f:parsenoop },
9929
    0x008B: { n:"BrtBeginCsViews", f:parsenoop },
9930
    0x008C: { n:"BrtEndCsViews", f:parsenoop },
9931
    0x008D: { n:"BrtBeginCsView", f:parsenoop },
9932
    0x008E: { n:"BrtEndCsView", f:parsenoop },
9933
    0x008F: { n:"BrtBeginBundleShs", f:parsenoop },
9934
    0x0090: { n:"BrtEndBundleShs", f:parsenoop },
9935
    0x0091: { n:"BrtBeginSheetData", f:parsenoop },
9936
    0x0092: { n:"BrtEndSheetData", f:parsenoop },
9937
    0x0093: { n:"BrtWsProp", f:parse_BrtWsProp },
9938
    0x0094: { n:"BrtWsDim", f:parse_BrtWsDim, p:16 },
9939
    0x0097: { n:"BrtPane", f:parsenoop },
9940
    0x0098: { n:"BrtSel", f:parsenoop },
9941
    0x0099: { n:"BrtWbProp", f:parse_BrtWbProp },
9942
    0x009A: { n:"BrtWbFactoid", f:parsenoop },
9943
    0x009B: { n:"BrtFileRecover", f:parsenoop },
9944
    0x009C: { n:"BrtBundleSh", f:parse_BrtBundleSh },
9945
    0x009D: { n:"BrtCalcProp", f:parsenoop },
9946
    0x009E: { n:"BrtBookView", f:parsenoop },
9947
    0x009F: { n:"BrtBeginSst", f:parse_BrtBeginSst },
9948
    0x00A0: { n:"BrtEndSst", f:parsenoop },
9949
    0x00A1: { n:"BrtBeginAFilter", f:parsenoop },
9950
    0x00A2: { n:"BrtEndAFilter", f:parsenoop },
9951
    0x00A3: { n:"BrtBeginFilterColumn", f:parsenoop },
9952
    0x00A4: { n:"BrtEndFilterColumn", f:parsenoop },
9953
    0x00A5: { n:"BrtBeginFilters", f:parsenoop },
9954
    0x00A6: { n:"BrtEndFilters", f:parsenoop },
9955
    0x00A7: { n:"BrtFilter", f:parsenoop },
9956
    0x00A8: { n:"BrtColorFilter", f:parsenoop },
9957
    0x00A9: { n:"BrtIconFilter", f:parsenoop },
9958
    0x00AA: { n:"BrtTop10Filter", f:parsenoop },
9959
    0x00AB: { n:"BrtDynamicFilter", f:parsenoop },
9960
    0x00AC: { n:"BrtBeginCustomFilters", f:parsenoop },
9961
    0x00AD: { n:"BrtEndCustomFilters", f:parsenoop },
9962
    0x00AE: { n:"BrtCustomFilter", f:parsenoop },
9963
    0x00AF: { n:"BrtAFilterDateGroupItem", f:parsenoop },
9964
    0x00B0: { n:"BrtMergeCell", f:parse_BrtMergeCell },
9965
    0x00B1: { n:"BrtBeginMergeCells", f:parsenoop },
9966
    0x00B2: { n:"BrtEndMergeCells", f:parsenoop },
9967
    0x00B3: { n:"BrtBeginPivotCacheDef", f:parsenoop },
9968
    0x00B4: { n:"BrtEndPivotCacheDef", f:parsenoop },
9969
    0x00B5: { n:"BrtBeginPCDFields", f:parsenoop },
9970
    0x00B6: { n:"BrtEndPCDFields", f:parsenoop },
9971
    0x00B7: { n:"BrtBeginPCDField", f:parsenoop },
9972
    0x00B8: { n:"BrtEndPCDField", f:parsenoop },
9973
    0x00B9: { n:"BrtBeginPCDSource", f:parsenoop },
9974
    0x00BA: { n:"BrtEndPCDSource", f:parsenoop },
9975
    0x00BB: { n:"BrtBeginPCDSRange", f:parsenoop },
9976
    0x00BC: { n:"BrtEndPCDSRange", f:parsenoop },
9977
    0x00BD: { n:"BrtBeginPCDFAtbl", f:parsenoop },
9978
    0x00BE: { n:"BrtEndPCDFAtbl", f:parsenoop },
9979
    0x00BF: { n:"BrtBeginPCDIRun", f:parsenoop },
9980
    0x00C0: { n:"BrtEndPCDIRun", f:parsenoop },
9981
    0x00C1: { n:"BrtBeginPivotCacheRecords", f:parsenoop },
9982
    0x00C2: { n:"BrtEndPivotCacheRecords", f:parsenoop },
9983
    0x00C3: { n:"BrtBeginPCDHierarchies", f:parsenoop },
9984
    0x00C4: { n:"BrtEndPCDHierarchies", f:parsenoop },
9985
    0x00C5: { n:"BrtBeginPCDHierarchy", f:parsenoop },
9986
    0x00C6: { n:"BrtEndPCDHierarchy", f:parsenoop },
9987
    0x00C7: { n:"BrtBeginPCDHFieldsUsage", f:parsenoop },
9988
    0x00C8: { n:"BrtEndPCDHFieldsUsage", f:parsenoop },
9989
    0x00C9: { n:"BrtBeginExtConnection", f:parsenoop },
9990
    0x00CA: { n:"BrtEndExtConnection", f:parsenoop },
9991
    0x00CB: { n:"BrtBeginECDbProps", f:parsenoop },
9992
    0x00CC: { n:"BrtEndECDbProps", f:parsenoop },
9993
    0x00CD: { n:"BrtBeginECOlapProps", f:parsenoop },
9994
    0x00CE: { n:"BrtEndECOlapProps", f:parsenoop },
9995
    0x00CF: { n:"BrtBeginPCDSConsol", f:parsenoop },
9996
    0x00D0: { n:"BrtEndPCDSConsol", f:parsenoop },
9997
    0x00D1: { n:"BrtBeginPCDSCPages", f:parsenoop },
9998
    0x00D2: { n:"BrtEndPCDSCPages", f:parsenoop },
9999
    0x00D3: { n:"BrtBeginPCDSCPage", f:parsenoop },
10000
    0x00D4: { n:"BrtEndPCDSCPage", f:parsenoop },
10001
    0x00D5: { n:"BrtBeginPCDSCPItem", f:parsenoop },
10002
    0x00D6: { n:"BrtEndPCDSCPItem", f:parsenoop },
10003
    0x00D7: { n:"BrtBeginPCDSCSets", f:parsenoop },
10004
    0x00D8: { n:"BrtEndPCDSCSets", f:parsenoop },
10005
    0x00D9: { n:"BrtBeginPCDSCSet", f:parsenoop },
10006
    0x00DA: { n:"BrtEndPCDSCSet", f:parsenoop },
10007
    0x00DB: { n:"BrtBeginPCDFGroup", f:parsenoop },
10008
    0x00DC: { n:"BrtEndPCDFGroup", f:parsenoop },
10009
    0x00DD: { n:"BrtBeginPCDFGItems", f:parsenoop },
10010
    0x00DE: { n:"BrtEndPCDFGItems", f:parsenoop },
10011
    0x00DF: { n:"BrtBeginPCDFGRange", f:parsenoop },
10012
    0x00E0: { n:"BrtEndPCDFGRange", f:parsenoop },
10013
    0x00E1: { n:"BrtBeginPCDFGDiscrete", f:parsenoop },
10014
    0x00E2: { n:"BrtEndPCDFGDiscrete", f:parsenoop },
10015
    0x00E3: { n:"BrtBeginPCDSDTupleCache", f:parsenoop },
10016
    0x00E4: { n:"BrtEndPCDSDTupleCache", f:parsenoop },
10017
    0x00E5: { n:"BrtBeginPCDSDTCEntries", f:parsenoop },
10018
    0x00E6: { n:"BrtEndPCDSDTCEntries", f:parsenoop },
10019
    0x00E7: { n:"BrtBeginPCDSDTCEMembers", f:parsenoop },
10020
    0x00E8: { n:"BrtEndPCDSDTCEMembers", f:parsenoop },
10021
    0x00E9: { n:"BrtBeginPCDSDTCEMember", f:parsenoop },
10022
    0x00EA: { n:"BrtEndPCDSDTCEMember", f:parsenoop },
10023
    0x00EB: { n:"BrtBeginPCDSDTCQueries", f:parsenoop },
10024
    0x00EC: { n:"BrtEndPCDSDTCQueries", f:parsenoop },
10025
    0x00ED: { n:"BrtBeginPCDSDTCQuery", f:parsenoop },
10026
    0x00EE: { n:"BrtEndPCDSDTCQuery", f:parsenoop },
10027
    0x00EF: { n:"BrtBeginPCDSDTCSets", f:parsenoop },
10028
    0x00F0: { n:"BrtEndPCDSDTCSets", f:parsenoop },
10029
    0x00F1: { n:"BrtBeginPCDSDTCSet", f:parsenoop },
10030
    0x00F2: { n:"BrtEndPCDSDTCSet", f:parsenoop },
10031
    0x00F3: { n:"BrtBeginPCDCalcItems", f:parsenoop },
10032
    0x00F4: { n:"BrtEndPCDCalcItems", f:parsenoop },
10033
    0x00F5: { n:"BrtBeginPCDCalcItem", f:parsenoop },
10034
    0x00F6: { n:"BrtEndPCDCalcItem", f:parsenoop },
10035
    0x00F7: { n:"BrtBeginPRule", f:parsenoop },
10036
    0x00F8: { n:"BrtEndPRule", f:parsenoop },
10037
    0x00F9: { n:"BrtBeginPRFilters", f:parsenoop },
10038
    0x00FA: { n:"BrtEndPRFilters", f:parsenoop },
10039
    0x00FB: { n:"BrtBeginPRFilter", f:parsenoop },
10040
    0x00FC: { n:"BrtEndPRFilter", f:parsenoop },
10041
    0x00FD: { n:"BrtBeginPNames", f:parsenoop },
10042
    0x00FE: { n:"BrtEndPNames", f:parsenoop },
10043
    0x00FF: { n:"BrtBeginPName", f:parsenoop },
10044
    0x0100: { n:"BrtEndPName", f:parsenoop },
10045
    0x0101: { n:"BrtBeginPNPairs", f:parsenoop },
10046
    0x0102: { n:"BrtEndPNPairs", f:parsenoop },
10047
    0x0103: { n:"BrtBeginPNPair", f:parsenoop },
10048
    0x0104: { n:"BrtEndPNPair", f:parsenoop },
10049
    0x0105: { n:"BrtBeginECWebProps", f:parsenoop },
10050
    0x0106: { n:"BrtEndECWebProps", f:parsenoop },
10051
    0x0107: { n:"BrtBeginEcWpTables", f:parsenoop },
10052
    0x0108: { n:"BrtEndECWPTables", f:parsenoop },
10053
    0x0109: { n:"BrtBeginECParams", f:parsenoop },
10054
    0x010A: { n:"BrtEndECParams", f:parsenoop },
10055
    0x010B: { n:"BrtBeginECParam", f:parsenoop },
10056
    0x010C: { n:"BrtEndECParam", f:parsenoop },
10057
    0x010D: { n:"BrtBeginPCDKPIs", f:parsenoop },
10058
    0x010E: { n:"BrtEndPCDKPIs", f:parsenoop },
10059
    0x010F: { n:"BrtBeginPCDKPI", f:parsenoop },
10060
    0x0110: { n:"BrtEndPCDKPI", f:parsenoop },
10061
    0x0111: { n:"BrtBeginDims", f:parsenoop },
10062
    0x0112: { n:"BrtEndDims", f:parsenoop },
10063
    0x0113: { n:"BrtBeginDim", f:parsenoop },
10064
    0x0114: { n:"BrtEndDim", f:parsenoop },
10065
    0x0115: { n:"BrtIndexPartEnd", f:parsenoop },
10066
    0x0116: { n:"BrtBeginStyleSheet", f:parsenoop },
10067
    0x0117: { n:"BrtEndStyleSheet", f:parsenoop },
10068
    0x0118: { n:"BrtBeginSXView", f:parsenoop },
10069
    0x0119: { n:"BrtEndSXVI", f:parsenoop },
10070
    0x011A: { n:"BrtBeginSXVI", f:parsenoop },
10071
    0x011B: { n:"BrtBeginSXVIs", f:parsenoop },
10072
    0x011C: { n:"BrtEndSXVIs", f:parsenoop },
10073
    0x011D: { n:"BrtBeginSXVD", f:parsenoop },
10074
    0x011E: { n:"BrtEndSXVD", f:parsenoop },
10075
    0x011F: { n:"BrtBeginSXVDs", f:parsenoop },
10076
    0x0120: { n:"BrtEndSXVDs", f:parsenoop },
10077
    0x0121: { n:"BrtBeginSXPI", f:parsenoop },
10078
    0x0122: { n:"BrtEndSXPI", f:parsenoop },
10079
    0x0123: { n:"BrtBeginSXPIs", f:parsenoop },
10080
    0x0124: { n:"BrtEndSXPIs", f:parsenoop },
10081
    0x0125: { n:"BrtBeginSXDI", f:parsenoop },
10082
    0x0126: { n:"BrtEndSXDI", f:parsenoop },
10083
    0x0127: { n:"BrtBeginSXDIs", f:parsenoop },
10084
    0x0128: { n:"BrtEndSXDIs", f:parsenoop },
10085
    0x0129: { n:"BrtBeginSXLI", f:parsenoop },
10086
    0x012A: { n:"BrtEndSXLI", f:parsenoop },
10087
    0x012B: { n:"BrtBeginSXLIRws", f:parsenoop },
10088
    0x012C: { n:"BrtEndSXLIRws", f:parsenoop },
10089
    0x012D: { n:"BrtBeginSXLICols", f:parsenoop },
10090
    0x012E: { n:"BrtEndSXLICols", f:parsenoop },
10091
    0x012F: { n:"BrtBeginSXFormat", f:parsenoop },
10092
    0x0130: { n:"BrtEndSXFormat", f:parsenoop },
10093
    0x0131: { n:"BrtBeginSXFormats", f:parsenoop },
10094
    0x0132: { n:"BrtEndSxFormats", f:parsenoop },
10095
    0x0133: { n:"BrtBeginSxSelect", f:parsenoop },
10096
    0x0134: { n:"BrtEndSxSelect", f:parsenoop },
10097
    0x0135: { n:"BrtBeginISXVDRws", f:parsenoop },
10098
    0x0136: { n:"BrtEndISXVDRws", f:parsenoop },
10099
    0x0137: { n:"BrtBeginISXVDCols", f:parsenoop },
10100
    0x0138: { n:"BrtEndISXVDCols", f:parsenoop },
10101
    0x0139: { n:"BrtEndSXLocation", f:parsenoop },
10102
    0x013A: { n:"BrtBeginSXLocation", f:parsenoop },
10103
    0x013B: { n:"BrtEndSXView", f:parsenoop },
10104
    0x013C: { n:"BrtBeginSXTHs", f:parsenoop },
10105
    0x013D: { n:"BrtEndSXTHs", f:parsenoop },
10106
    0x013E: { n:"BrtBeginSXTH", f:parsenoop },
10107
    0x013F: { n:"BrtEndSXTH", f:parsenoop },
10108
    0x0140: { n:"BrtBeginISXTHRws", f:parsenoop },
10109
    0x0141: { n:"BrtEndISXTHRws", f:parsenoop },
10110
    0x0142: { n:"BrtBeginISXTHCols", f:parsenoop },
10111
    0x0143: { n:"BrtEndISXTHCols", f:parsenoop },
10112
    0x0144: { n:"BrtBeginSXTDMPS", f:parsenoop },
10113
    0x0145: { n:"BrtEndSXTDMPs", f:parsenoop },
10114
    0x0146: { n:"BrtBeginSXTDMP", f:parsenoop },
10115
    0x0147: { n:"BrtEndSXTDMP", f:parsenoop },
10116
    0x0148: { n:"BrtBeginSXTHItems", f:parsenoop },
10117
    0x0149: { n:"BrtEndSXTHItems", f:parsenoop },
10118
    0x014A: { n:"BrtBeginSXTHItem", f:parsenoop },
10119
    0x014B: { n:"BrtEndSXTHItem", f:parsenoop },
10120
    0x014C: { n:"BrtBeginMetadata", f:parsenoop },
10121
    0x014D: { n:"BrtEndMetadata", f:parsenoop },
10122
    0x014E: { n:"BrtBeginEsmdtinfo", f:parsenoop },
10123
    0x014F: { n:"BrtMdtinfo", f:parsenoop },
10124
    0x0150: { n:"BrtEndEsmdtinfo", f:parsenoop },
10125
    0x0151: { n:"BrtBeginEsmdb", f:parsenoop },
10126
    0x0152: { n:"BrtEndEsmdb", f:parsenoop },
10127
    0x0153: { n:"BrtBeginEsfmd", f:parsenoop },
10128
    0x0154: { n:"BrtEndEsfmd", f:parsenoop },
10129
    0x0155: { n:"BrtBeginSingleCells", f:parsenoop },
10130
    0x0156: { n:"BrtEndSingleCells", f:parsenoop },
10131
    0x0157: { n:"BrtBeginList", f:parsenoop },
10132
    0x0158: { n:"BrtEndList", f:parsenoop },
10133
    0x0159: { n:"BrtBeginListCols", f:parsenoop },
10134
    0x015A: { n:"BrtEndListCols", f:parsenoop },
10135
    0x015B: { n:"BrtBeginListCol", f:parsenoop },
10136
    0x015C: { n:"BrtEndListCol", f:parsenoop },
10137
    0x015D: { n:"BrtBeginListXmlCPr", f:parsenoop },
10138
    0x015E: { n:"BrtEndListXmlCPr", f:parsenoop },
10139
    0x015F: { n:"BrtListCCFmla", f:parsenoop },
10140
    0x0160: { n:"BrtListTrFmla", f:parsenoop },
10141
    0x0161: { n:"BrtBeginExternals", f:parsenoop },
10142
    0x0162: { n:"BrtEndExternals", f:parsenoop },
10143
    0x0163: { n:"BrtSupBookSrc", f:parsenoop },
10144
    0x0165: { n:"BrtSupSelf", f:parsenoop },
10145
    0x0166: { n:"BrtSupSame", f:parsenoop },
10146
    0x0167: { n:"BrtSupTabs", f:parsenoop },
10147
    0x0168: { n:"BrtBeginSupBook", f:parsenoop },
10148
    0x0169: { n:"BrtPlaceholderName", f:parsenoop },
10149
    0x016A: { n:"BrtExternSheet", f:parsenoop },
10150
    0x016B: { n:"BrtExternTableStart", f:parsenoop },
10151
    0x016C: { n:"BrtExternTableEnd", f:parsenoop },
10152
    0x016E: { n:"BrtExternRowHdr", f:parsenoop },
10153
    0x016F: { n:"BrtExternCellBlank", f:parsenoop },
10154
    0x0170: { n:"BrtExternCellReal", f:parsenoop },
10155
    0x0171: { n:"BrtExternCellBool", f:parsenoop },
10156
    0x0172: { n:"BrtExternCellError", f:parsenoop },
10157
    0x0173: { n:"BrtExternCellString", f:parsenoop },
10158
    0x0174: { n:"BrtBeginEsmdx", f:parsenoop },
10159
    0x0175: { n:"BrtEndEsmdx", f:parsenoop },
10160
    0x0176: { n:"BrtBeginMdxSet", f:parsenoop },
10161
    0x0177: { n:"BrtEndMdxSet", f:parsenoop },
10162
    0x0178: { n:"BrtBeginMdxMbrProp", f:parsenoop },
10163
    0x0179: { n:"BrtEndMdxMbrProp", f:parsenoop },
10164
    0x017A: { n:"BrtBeginMdxKPI", f:parsenoop },
10165
    0x017B: { n:"BrtEndMdxKPI", f:parsenoop },
10166
    0x017C: { n:"BrtBeginEsstr", f:parsenoop },
10167
    0x017D: { n:"BrtEndEsstr", f:parsenoop },
10168
    0x017E: { n:"BrtBeginPRFItem", f:parsenoop },
10169
    0x017F: { n:"BrtEndPRFItem", f:parsenoop },
10170
    0x0180: { n:"BrtBeginPivotCacheIDs", f:parsenoop },
10171
    0x0181: { n:"BrtEndPivotCacheIDs", f:parsenoop },
10172
    0x0182: { n:"BrtBeginPivotCacheID", f:parsenoop },
10173
    0x0183: { n:"BrtEndPivotCacheID", f:parsenoop },
10174
    0x0184: { n:"BrtBeginISXVIs", f:parsenoop },
10175
    0x0185: { n:"BrtEndISXVIs", f:parsenoop },
10176
    0x0186: { n:"BrtBeginColInfos", f:parsenoop },
10177
    0x0187: { n:"BrtEndColInfos", f:parsenoop },
10178
    0x0188: { n:"BrtBeginRwBrk", f:parsenoop },
10179
    0x0189: { n:"BrtEndRwBrk", f:parsenoop },
10180
    0x018A: { n:"BrtBeginColBrk", f:parsenoop },
10181
    0x018B: { n:"BrtEndColBrk", f:parsenoop },
10182
    0x018C: { n:"BrtBrk", f:parsenoop },
10183
    0x018D: { n:"BrtUserBookView", f:parsenoop },
10184
    0x018E: { n:"BrtInfo", f:parsenoop },
10185
    0x018F: { n:"BrtCUsr", f:parsenoop },
10186
    0x0190: { n:"BrtUsr", f:parsenoop },
10187
    0x0191: { n:"BrtBeginUsers", f:parsenoop },
10188
    0x0193: { n:"BrtEOF", f:parsenoop },
10189
    0x0194: { n:"BrtUCR", f:parsenoop },
10190
    0x0195: { n:"BrtRRInsDel", f:parsenoop },
10191
    0x0196: { n:"BrtRREndInsDel", f:parsenoop },
10192
    0x0197: { n:"BrtRRMove", f:parsenoop },
10193
    0x0198: { n:"BrtRREndMove", f:parsenoop },
10194
    0x0199: { n:"BrtRRChgCell", f:parsenoop },
10195
    0x019A: { n:"BrtRREndChgCell", f:parsenoop },
10196
    0x019B: { n:"BrtRRHeader", f:parsenoop },
10197
    0x019C: { n:"BrtRRUserView", f:parsenoop },
10198
    0x019D: { n:"BrtRRRenSheet", f:parsenoop },
10199
    0x019E: { n:"BrtRRInsertSh", f:parsenoop },
10200
    0x019F: { n:"BrtRRDefName", f:parsenoop },
10201
    0x01A0: { n:"BrtRRNote", f:parsenoop },
10202
    0x01A1: { n:"BrtRRConflict", f:parsenoop },
10203
    0x01A2: { n:"BrtRRTQSIF", f:parsenoop },
10204
    0x01A3: { n:"BrtRRFormat", f:parsenoop },
10205
    0x01A4: { n:"BrtRREndFormat", f:parsenoop },
10206
    0x01A5: { n:"BrtRRAutoFmt", f:parsenoop },
10207
    0x01A6: { n:"BrtBeginUserShViews", f:parsenoop },
10208
    0x01A7: { n:"BrtBeginUserShView", f:parsenoop },
10209
    0x01A8: { n:"BrtEndUserShView", f:parsenoop },
10210
    0x01A9: { n:"BrtEndUserShViews", f:parsenoop },
10211
    0x01AA: { n:"BrtArrFmla", f:parsenoop },
10212
    0x01AB: { n:"BrtShrFmla", f:parsenoop },
10213
    0x01AC: { n:"BrtTable", f:parsenoop },
10214
    0x01AD: { n:"BrtBeginExtConnections", f:parsenoop },
10215
    0x01AE: { n:"BrtEndExtConnections", f:parsenoop },
10216
    0x01AF: { n:"BrtBeginPCDCalcMems", f:parsenoop },
10217
    0x01B0: { n:"BrtEndPCDCalcMems", f:parsenoop },
10218
    0x01B1: { n:"BrtBeginPCDCalcMem", f:parsenoop },
10219
    0x01B2: { n:"BrtEndPCDCalcMem", f:parsenoop },
10220
    0x01B3: { n:"BrtBeginPCDHGLevels", f:parsenoop },
10221
    0x01B4: { n:"BrtEndPCDHGLevels", f:parsenoop },
10222
    0x01B5: { n:"BrtBeginPCDHGLevel", f:parsenoop },
10223
    0x01B6: { n:"BrtEndPCDHGLevel", f:parsenoop },
10224
    0x01B7: { n:"BrtBeginPCDHGLGroups", f:parsenoop },
10225
    0x01B8: { n:"BrtEndPCDHGLGroups", f:parsenoop },
10226
    0x01B9: { n:"BrtBeginPCDHGLGroup", f:parsenoop },
10227
    0x01BA: { n:"BrtEndPCDHGLGroup", f:parsenoop },
10228
    0x01BB: { n:"BrtBeginPCDHGLGMembers", f:parsenoop },
10229
    0x01BC: { n:"BrtEndPCDHGLGMembers", f:parsenoop },
10230
    0x01BD: { n:"BrtBeginPCDHGLGMember", f:parsenoop },
10231
    0x01BE: { n:"BrtEndPCDHGLGMember", f:parsenoop },
10232
    0x01BF: { n:"BrtBeginQSI", f:parsenoop },
10233
    0x01C0: { n:"BrtEndQSI", f:parsenoop },
10234
    0x01C1: { n:"BrtBeginQSIR", f:parsenoop },
10235
    0x01C2: { n:"BrtEndQSIR", f:parsenoop },
10236
    0x01C3: { n:"BrtBeginDeletedNames", f:parsenoop },
10237
    0x01C4: { n:"BrtEndDeletedNames", f:parsenoop },
10238
    0x01C5: { n:"BrtBeginDeletedName", f:parsenoop },
10239
    0x01C6: { n:"BrtEndDeletedName", f:parsenoop },
10240
    0x01C7: { n:"BrtBeginQSIFs", f:parsenoop },
10241
    0x01C8: { n:"BrtEndQSIFs", f:parsenoop },
10242
    0x01C9: { n:"BrtBeginQSIF", f:parsenoop },
10243
    0x01CA: { n:"BrtEndQSIF", f:parsenoop },
10244
    0x01CB: { n:"BrtBeginAutoSortScope", f:parsenoop },
10245
    0x01CC: { n:"BrtEndAutoSortScope", f:parsenoop },
10246
    0x01CD: { n:"BrtBeginConditionalFormatting", f:parsenoop },
10247
    0x01CE: { n:"BrtEndConditionalFormatting", f:parsenoop },
10248
    0x01CF: { n:"BrtBeginCFRule", f:parsenoop },
10249
    0x01D0: { n:"BrtEndCFRule", f:parsenoop },
10250
    0x01D1: { n:"BrtBeginIconSet", f:parsenoop },
10251
    0x01D2: { n:"BrtEndIconSet", f:parsenoop },
10252
    0x01D3: { n:"BrtBeginDatabar", f:parsenoop },
10253
    0x01D4: { n:"BrtEndDatabar", f:parsenoop },
10254
    0x01D5: { n:"BrtBeginColorScale", f:parsenoop },
10255
    0x01D6: { n:"BrtEndColorScale", f:parsenoop },
10256
    0x01D7: { n:"BrtCFVO", f:parsenoop },
10257
    0x01D8: { n:"BrtExternValueMeta", f:parsenoop },
10258
    0x01D9: { n:"BrtBeginColorPalette", f:parsenoop },
10259
    0x01DA: { n:"BrtEndColorPalette", f:parsenoop },
10260
    0x01DB: { n:"BrtIndexedColor", f:parsenoop },
10261
    0x01DC: { n:"BrtMargins", f:parsenoop },
10262
    0x01DD: { n:"BrtPrintOptions", f:parsenoop },
10263
    0x01DE: { n:"BrtPageSetup", f:parsenoop },
10264
    0x01DF: { n:"BrtBeginHeaderFooter", f:parsenoop },
10265
    0x01E0: { n:"BrtEndHeaderFooter", f:parsenoop },
10266
    0x01E1: { n:"BrtBeginSXCrtFormat", f:parsenoop },
10267
    0x01E2: { n:"BrtEndSXCrtFormat", f:parsenoop },
10268
    0x01E3: { n:"BrtBeginSXCrtFormats", f:parsenoop },
10269
    0x01E4: { n:"BrtEndSXCrtFormats", f:parsenoop },
10270
    0x01E5: { n:"BrtWsFmtInfo", f:parsenoop },
10271
    0x01E6: { n:"BrtBeginMgs", f:parsenoop },
10272
    0x01E7: { n:"BrtEndMGs", f:parsenoop },
10273
    0x01E8: { n:"BrtBeginMGMaps", f:parsenoop },
10274
    0x01E9: { n:"BrtEndMGMaps", f:parsenoop },
10275
    0x01EA: { n:"BrtBeginMG", f:parsenoop },
10276
    0x01EB: { n:"BrtEndMG", f:parsenoop },
10277
    0x01EC: { n:"BrtBeginMap", f:parsenoop },
10278
    0x01ED: { n:"BrtEndMap", f:parsenoop },
10279
    0x01EE: { n:"BrtHLink", f:parse_BrtHLink },
10280
    0x01EF: { n:"BrtBeginDCon", f:parsenoop },
10281
    0x01F0: { n:"BrtEndDCon", f:parsenoop },
10282
    0x01F1: { n:"BrtBeginDRefs", f:parsenoop },
10283
    0x01F2: { n:"BrtEndDRefs", f:parsenoop },
10284
    0x01F3: { n:"BrtDRef", f:parsenoop },
10285
    0x01F4: { n:"BrtBeginScenMan", f:parsenoop },
10286
    0x01F5: { n:"BrtEndScenMan", f:parsenoop },
10287
    0x01F6: { n:"BrtBeginSct", f:parsenoop },
10288
    0x01F7: { n:"BrtEndSct", f:parsenoop },
10289
    0x01F8: { n:"BrtSlc", f:parsenoop },
10290
    0x01F9: { n:"BrtBeginDXFs", f:parsenoop },
10291
    0x01FA: { n:"BrtEndDXFs", f:parsenoop },
10292
    0x01FB: { n:"BrtDXF", f:parsenoop },
10293
    0x01FC: { n:"BrtBeginTableStyles", f:parsenoop },
10294
    0x01FD: { n:"BrtEndTableStyles", f:parsenoop },
10295
    0x01FE: { n:"BrtBeginTableStyle", f:parsenoop },
10296
    0x01FF: { n:"BrtEndTableStyle", f:parsenoop },
10297
    0x0200: { n:"BrtTableStyleElement", f:parsenoop },
10298
    0x0201: { n:"BrtTableStyleClient", f:parsenoop },
10299
    0x0202: { n:"BrtBeginVolDeps", f:parsenoop },
10300
    0x0203: { n:"BrtEndVolDeps", f:parsenoop },
10301
    0x0204: { n:"BrtBeginVolType", f:parsenoop },
10302
    0x0205: { n:"BrtEndVolType", f:parsenoop },
10303
    0x0206: { n:"BrtBeginVolMain", f:parsenoop },
10304
    0x0207: { n:"BrtEndVolMain", f:parsenoop },
10305
    0x0208: { n:"BrtBeginVolTopic", f:parsenoop },
10306
    0x0209: { n:"BrtEndVolTopic", f:parsenoop },
10307
    0x020A: { n:"BrtVolSubtopic", f:parsenoop },
10308
    0x020B: { n:"BrtVolRef", f:parsenoop },
10309
    0x020C: { n:"BrtVolNum", f:parsenoop },
10310
    0x020D: { n:"BrtVolErr", f:parsenoop },
10311
    0x020E: { n:"BrtVolStr", f:parsenoop },
10312
    0x020F: { n:"BrtVolBool", f:parsenoop },
10313
    0x0210: { n:"BrtBeginCalcChain$", f:parsenoop },
10314
    0x0211: { n:"BrtEndCalcChain$", f:parsenoop },
10315
    0x0212: { n:"BrtBeginSortState", f:parsenoop },
10316
    0x0213: { n:"BrtEndSortState", f:parsenoop },
10317
    0x0214: { n:"BrtBeginSortCond", f:parsenoop },
10318
    0x0215: { n:"BrtEndSortCond", f:parsenoop },
10319
    0x0216: { n:"BrtBookProtection", f:parsenoop },
10320
    0x0217: { n:"BrtSheetProtection", f:parsenoop },
10321
    0x0218: { n:"BrtRangeProtection", f:parsenoop },
10322
    0x0219: { n:"BrtPhoneticInfo", f:parsenoop },
10323
    0x021A: { n:"BrtBeginECTxtWiz", f:parsenoop },
10324
    0x021B: { n:"BrtEndECTxtWiz", f:parsenoop },
10325
    0x021C: { n:"BrtBeginECTWFldInfoLst", f:parsenoop },
10326
    0x021D: { n:"BrtEndECTWFldInfoLst", f:parsenoop },
10327
    0x021E: { n:"BrtBeginECTwFldInfo", f:parsenoop },
10328
    0x0224: { n:"BrtFileSharing", f:parsenoop },
10329
    0x0225: { n:"BrtOleSize", f:parsenoop },
10330
    0x0226: { n:"BrtDrawing", f:parsenoop },
10331
    0x0227: { n:"BrtLegacyDrawing", f:parsenoop },
10332
    0x0228: { n:"BrtLegacyDrawingHF", f:parsenoop },
10333
    0x0229: { n:"BrtWebOpt", f:parsenoop },
10334
    0x022A: { n:"BrtBeginWebPubItems", f:parsenoop },
10335
    0x022B: { n:"BrtEndWebPubItems", f:parsenoop },
10336
    0x022C: { n:"BrtBeginWebPubItem", f:parsenoop },
10337
    0x022D: { n:"BrtEndWebPubItem", f:parsenoop },
10338
    0x022E: { n:"BrtBeginSXCondFmt", f:parsenoop },
10339
    0x022F: { n:"BrtEndSXCondFmt", f:parsenoop },
10340
    0x0230: { n:"BrtBeginSXCondFmts", f:parsenoop },
10341
    0x0231: { n:"BrtEndSXCondFmts", f:parsenoop },
10342
    0x0232: { n:"BrtBkHim", f:parsenoop },
10343
    0x0234: { n:"BrtColor", f:parsenoop },
10344
    0x0235: { n:"BrtBeginIndexedColors", f:parsenoop },
10345
    0x0236: { n:"BrtEndIndexedColors", f:parsenoop },
10346
    0x0239: { n:"BrtBeginMRUColors", f:parsenoop },
10347
    0x023A: { n:"BrtEndMRUColors", f:parsenoop },
10348
    0x023C: { n:"BrtMRUColor", f:parsenoop },
10349
    0x023D: { n:"BrtBeginDVals", f:parsenoop },
10350
    0x023E: { n:"BrtEndDVals", f:parsenoop },
10351
    0x0241: { n:"BrtSupNameStart", f:parsenoop },
10352
    0x0242: { n:"BrtSupNameValueStart", f:parsenoop },
10353
    0x0243: { n:"BrtSupNameValueEnd", f:parsenoop },
10354
    0x0244: { n:"BrtSupNameNum", f:parsenoop },
10355
    0x0245: { n:"BrtSupNameErr", f:parsenoop },
10356
    0x0246: { n:"BrtSupNameSt", f:parsenoop },
10357
    0x0247: { n:"BrtSupNameNil", f:parsenoop },
10358
    0x0248: { n:"BrtSupNameBool", f:parsenoop },
10359
    0x0249: { n:"BrtSupNameFmla", f:parsenoop },
10360
    0x024A: { n:"BrtSupNameBits", f:parsenoop },
10361
    0x024B: { n:"BrtSupNameEnd", f:parsenoop },
10362
    0x024C: { n:"BrtEndSupBook", f:parsenoop },
10363
    0x024D: { n:"BrtCellSmartTagProperty", f:parsenoop },
10364
    0x024E: { n:"BrtBeginCellSmartTag", f:parsenoop },
10365
    0x024F: { n:"BrtEndCellSmartTag", f:parsenoop },
10366
    0x0250: { n:"BrtBeginCellSmartTags", f:parsenoop },
10367
    0x0251: { n:"BrtEndCellSmartTags", f:parsenoop },
10368
    0x0252: { n:"BrtBeginSmartTags", f:parsenoop },
10369
    0x0253: { n:"BrtEndSmartTags", f:parsenoop },
10370
    0x0254: { n:"BrtSmartTagType", f:parsenoop },
10371
    0x0255: { n:"BrtBeginSmartTagTypes", f:parsenoop },
10372
    0x0256: { n:"BrtEndSmartTagTypes", f:parsenoop },
10373
    0x0257: { n:"BrtBeginSXFilters", f:parsenoop },
10374
    0x0258: { n:"BrtEndSXFilters", f:parsenoop },
10375
    0x0259: { n:"BrtBeginSXFILTER", f:parsenoop },
10376
    0x025A: { n:"BrtEndSXFilter", f:parsenoop },
10377
    0x025B: { n:"BrtBeginFills", f:parsenoop },
10378
    0x025C: { n:"BrtEndFills", f:parsenoop },
10379
    0x025D: { n:"BrtBeginCellWatches", f:parsenoop },
10380
    0x025E: { n:"BrtEndCellWatches", f:parsenoop },
10381
    0x025F: { n:"BrtCellWatch", f:parsenoop },
10382
    0x0260: { n:"BrtBeginCRErrs", f:parsenoop },
10383
    0x0261: { n:"BrtEndCRErrs", f:parsenoop },
10384
    0x0262: { n:"BrtCrashRecErr", f:parsenoop },
10385
    0x0263: { n:"BrtBeginFonts", f:parsenoop },
10386
    0x0264: { n:"BrtEndFonts", f:parsenoop },
10387
    0x0265: { n:"BrtBeginBorders", f:parsenoop },
10388
    0x0266: { n:"BrtEndBorders", f:parsenoop },
10389
    0x0267: { n:"BrtBeginFmts", f:parsenoop },
10390
    0x0268: { n:"BrtEndFmts", f:parsenoop },
10391
    0x0269: { n:"BrtBeginCellXFs", f:parsenoop },
10392
    0x026A: { n:"BrtEndCellXFs", f:parsenoop },
10393
    0x026B: { n:"BrtBeginStyles", f:parsenoop },
10394
    0x026C: { n:"BrtEndStyles", f:parsenoop },
10395
    0x0271: { n:"BrtBigName", f:parsenoop },
10396
    0x0272: { n:"BrtBeginCellStyleXFs", f:parsenoop },
10397
    0x0273: { n:"BrtEndCellStyleXFs", f:parsenoop },
10398
    0x0274: { n:"BrtBeginComments", f:parsenoop },
10399
    0x0275: { n:"BrtEndComments", f:parsenoop },
10400
    0x0276: { n:"BrtBeginCommentAuthors", f:parsenoop },
10401
    0x0277: { n:"BrtEndCommentAuthors", f:parsenoop },
10402
    0x0278: { n:"BrtCommentAuthor", f:parse_BrtCommentAuthor },
10403
    0x0279: { n:"BrtBeginCommentList", f:parsenoop },
10404
    0x027A: { n:"BrtEndCommentList", f:parsenoop },
10405
    0x027B: { n:"BrtBeginComment", f:parse_BrtBeginComment},
10406
    0x027C: { n:"BrtEndComment", f:parsenoop },
10407
    0x027D: { n:"BrtCommentText", f:parse_BrtCommentText },
10408
    0x027E: { n:"BrtBeginOleObjects", f:parsenoop },
10409
    0x027F: { n:"BrtOleObject", f:parsenoop },
10410
    0x0280: { n:"BrtEndOleObjects", f:parsenoop },
10411
    0x0281: { n:"BrtBeginSxrules", f:parsenoop },
10412
    0x0282: { n:"BrtEndSxRules", f:parsenoop },
10413
    0x0283: { n:"BrtBeginActiveXControls", f:parsenoop },
10414
    0x0284: { n:"BrtActiveX", f:parsenoop },
10415
    0x0285: { n:"BrtEndActiveXControls", f:parsenoop },
10416
    0x0286: { n:"BrtBeginPCDSDTCEMembersSortBy", f:parsenoop },
10417
    0x0288: { n:"BrtBeginCellIgnoreECs", f:parsenoop },
10418
    0x0289: { n:"BrtCellIgnoreEC", f:parsenoop },
10419
    0x028A: { n:"BrtEndCellIgnoreECs", f:parsenoop },
10420
    0x028B: { n:"BrtCsProp", f:parsenoop },
10421
    0x028C: { n:"BrtCsPageSetup", f:parsenoop },
10422
    0x028D: { n:"BrtBeginUserCsViews", f:parsenoop },
10423
    0x028E: { n:"BrtEndUserCsViews", f:parsenoop },
10424
    0x028F: { n:"BrtBeginUserCsView", f:parsenoop },
10425
    0x0290: { n:"BrtEndUserCsView", f:parsenoop },
10426
    0x0291: { n:"BrtBeginPcdSFCIEntries", f:parsenoop },
10427
    0x0292: { n:"BrtEndPCDSFCIEntries", f:parsenoop },
10428
    0x0293: { n:"BrtPCDSFCIEntry", f:parsenoop },
10429
    0x0294: { n:"BrtBeginListParts", f:parsenoop },
10430
    0x0295: { n:"BrtListPart", f:parsenoop },
10431
    0x0296: { n:"BrtEndListParts", f:parsenoop },
10432
    0x0297: { n:"BrtSheetCalcProp", f:parsenoop },
10433
    0x0298: { n:"BrtBeginFnGroup", f:parsenoop },
10434
    0x0299: { n:"BrtFnGroup", f:parsenoop },
10435
    0x029A: { n:"BrtEndFnGroup", f:parsenoop },
10436
    0x029B: { n:"BrtSupAddin", f:parsenoop },
10437
    0x029C: { n:"BrtSXTDMPOrder", f:parsenoop },
10438
    0x029D: { n:"BrtCsProtection", f:parsenoop },
10439
    0x029F: { n:"BrtBeginWsSortMap", f:parsenoop },
10440
    0x02A0: { n:"BrtEndWsSortMap", f:parsenoop },
10441
    0x02A1: { n:"BrtBeginRRSort", f:parsenoop },
10442
    0x02A2: { n:"BrtEndRRSort", f:parsenoop },
10443
    0x02A3: { n:"BrtRRSortItem", f:parsenoop },
10444
    0x02A4: { n:"BrtFileSharingIso", f:parsenoop },
10445
    0x02A5: { n:"BrtBookProtectionIso", f:parsenoop },
10446
    0x02A6: { n:"BrtSheetProtectionIso", f:parsenoop },
10447
    0x02A7: { n:"BrtCsProtectionIso", f:parsenoop },
10448
    0x02A8: { n:"BrtRangeProtectionIso", f:parsenoop },
10449
    0x0400: { n:"BrtRwDescent", f:parsenoop },
10450
    0x0401: { n:"BrtKnownFonts", f:parsenoop },
10451
    0x0402: { n:"BrtBeginSXTupleSet", f:parsenoop },
10452
    0x0403: { n:"BrtEndSXTupleSet", f:parsenoop },
10453
    0x0404: { n:"BrtBeginSXTupleSetHeader", f:parsenoop },
10454
    0x0405: { n:"BrtEndSXTupleSetHeader", f:parsenoop },
10455
    0x0406: { n:"BrtSXTupleSetHeaderItem", f:parsenoop },
10456
    0x0407: { n:"BrtBeginSXTupleSetData", f:parsenoop },
10457
    0x0408: { n:"BrtEndSXTupleSetData", f:parsenoop },
10458
    0x0409: { n:"BrtBeginSXTupleSetRow", f:parsenoop },
10459
    0x040A: { n:"BrtEndSXTupleSetRow", f:parsenoop },
10460
    0x040B: { n:"BrtSXTupleSetRowItem", f:parsenoop },
10461
    0x040C: { n:"BrtNameExt", f:parsenoop },
10462
    0x040D: { n:"BrtPCDH14", f:parsenoop },
10463
    0x040E: { n:"BrtBeginPCDCalcMem14", f:parsenoop },
10464
    0x040F: { n:"BrtEndPCDCalcMem14", f:parsenoop },
10465
    0x0410: { n:"BrtSXTH14", f:parsenoop },
10466
    0x0411: { n:"BrtBeginSparklineGroup", f:parsenoop },
10467
    0x0412: { n:"BrtEndSparklineGroup", f:parsenoop },
10468
    0x0413: { n:"BrtSparkline", f:parsenoop },
10469
    0x0414: { n:"BrtSXDI14", f:parsenoop },
10470
    0x0415: { n:"BrtWsFmtInfoEx14", f:parsenoop },
10471
    0x0416: { n:"BrtBeginConditionalFormatting14", f:parsenoop },
10472
    0x0417: { n:"BrtEndConditionalFormatting14", f:parsenoop },
10473
    0x0418: { n:"BrtBeginCFRule14", f:parsenoop },
10474
    0x0419: { n:"BrtEndCFRule14", f:parsenoop },
10475
    0x041A: { n:"BrtCFVO14", f:parsenoop },
10476
    0x041B: { n:"BrtBeginDatabar14", f:parsenoop },
10477
    0x041C: { n:"BrtBeginIconSet14", f:parsenoop },
10478
    0x041D: { n:"BrtDVal14", f:parsenoop },
10479
    0x041E: { n:"BrtBeginDVals14", f:parsenoop },
10480
    0x041F: { n:"BrtColor14", f:parsenoop },
10481
    0x0420: { n:"BrtBeginSparklines", f:parsenoop },
10482
    0x0421: { n:"BrtEndSparklines", f:parsenoop },
10483
    0x0422: { n:"BrtBeginSparklineGroups", f:parsenoop },
10484
    0x0423: { n:"BrtEndSparklineGroups", f:parsenoop },
10485
    0x0425: { n:"BrtSXVD14", f:parsenoop },
10486
    0x0426: { n:"BrtBeginSxview14", f:parsenoop },
10487
    0x0427: { n:"BrtEndSxview14", f:parsenoop },
10488
    0x042A: { n:"BrtBeginPCD14", f:parsenoop },
10489
    0x042B: { n:"BrtEndPCD14", f:parsenoop },
10490
    0x042C: { n:"BrtBeginExtConn14", f:parsenoop },
10491
    0x042D: { n:"BrtEndExtConn14", f:parsenoop },
10492
    0x042E: { n:"BrtBeginSlicerCacheIDs", f:parsenoop },
10493
    0x042F: { n:"BrtEndSlicerCacheIDs", f:parsenoop },
10494
    0x0430: { n:"BrtBeginSlicerCacheID", f:parsenoop },
10495
    0x0431: { n:"BrtEndSlicerCacheID", f:parsenoop },
10496
    0x0433: { n:"BrtBeginSlicerCache", f:parsenoop },
10497
    0x0434: { n:"BrtEndSlicerCache", f:parsenoop },
10498
    0x0435: { n:"BrtBeginSlicerCacheDef", f:parsenoop },
10499
    0x0436: { n:"BrtEndSlicerCacheDef", f:parsenoop },
10500
    0x0437: { n:"BrtBeginSlicersEx", f:parsenoop },
10501
    0x0438: { n:"BrtEndSlicersEx", f:parsenoop },
10502
    0x0439: { n:"BrtBeginSlicerEx", f:parsenoop },
10503
    0x043A: { n:"BrtEndSlicerEx", f:parsenoop },
10504
    0x043B: { n:"BrtBeginSlicer", f:parsenoop },
10505
    0x043C: { n:"BrtEndSlicer", f:parsenoop },
10506
    0x043D: { n:"BrtSlicerCachePivotTables", f:parsenoop },
10507
    0x043E: { n:"BrtBeginSlicerCacheOlapImpl", f:parsenoop },
10508
    0x043F: { n:"BrtEndSlicerCacheOlapImpl", f:parsenoop },
10509
    0x0440: { n:"BrtBeginSlicerCacheLevelsData", f:parsenoop },
10510
    0x0441: { n:"BrtEndSlicerCacheLevelsData", f:parsenoop },
10511
    0x0442: { n:"BrtBeginSlicerCacheLevelData", f:parsenoop },
10512
    0x0443: { n:"BrtEndSlicerCacheLevelData", f:parsenoop },
10513
    0x0444: { n:"BrtBeginSlicerCacheSiRanges", f:parsenoop },
10514
    0x0445: { n:"BrtEndSlicerCacheSiRanges", f:parsenoop },
10515
    0x0446: { n:"BrtBeginSlicerCacheSiRange", f:parsenoop },
10516
    0x0447: { n:"BrtEndSlicerCacheSiRange", f:parsenoop },
10517
    0x0448: { n:"BrtSlicerCacheOlapItem", f:parsenoop },
10518
    0x0449: { n:"BrtBeginSlicerCacheSelections", f:parsenoop },
10519
    0x044A: { n:"BrtSlicerCacheSelection", f:parsenoop },
10520
    0x044B: { n:"BrtEndSlicerCacheSelections", f:parsenoop },
10521
    0x044C: { n:"BrtBeginSlicerCacheNative", f:parsenoop },
10522
    0x044D: { n:"BrtEndSlicerCacheNative", f:parsenoop },
10523
    0x044E: { n:"BrtSlicerCacheNativeItem", f:parsenoop },
10524
    0x044F: { n:"BrtRangeProtection14", f:parsenoop },
10525
    0x0450: { n:"BrtRangeProtectionIso14", f:parsenoop },
10526
    0x0451: { n:"BrtCellIgnoreEC14", f:parsenoop },
10527
    0x0457: { n:"BrtList14", f:parsenoop },
10528
    0x0458: { n:"BrtCFIcon", f:parsenoop },
10529
    0x0459: { n:"BrtBeginSlicerCachesPivotCacheIDs", f:parsenoop },
10530
    0x045A: { n:"BrtEndSlicerCachesPivotCacheIDs", f:parsenoop },
10531
    0x045B: { n:"BrtBeginSlicers", f:parsenoop },
10532
    0x045C: { n:"BrtEndSlicers", f:parsenoop },
10533
    0x045D: { n:"BrtWbProp14", f:parsenoop },
10534
    0x045E: { n:"BrtBeginSXEdit", f:parsenoop },
10535
    0x045F: { n:"BrtEndSXEdit", f:parsenoop },
10536
    0x0460: { n:"BrtBeginSXEdits", f:parsenoop },
10537
    0x0461: { n:"BrtEndSXEdits", f:parsenoop },
10538
    0x0462: { n:"BrtBeginSXChange", f:parsenoop },
10539
    0x0463: { n:"BrtEndSXChange", f:parsenoop },
10540
    0x0464: { n:"BrtBeginSXChanges", f:parsenoop },
10541
    0x0465: { n:"BrtEndSXChanges", f:parsenoop },
10542
    0x0466: { n:"BrtSXTupleItems", f:parsenoop },
10543
    0x0468: { n:"BrtBeginSlicerStyle", f:parsenoop },
10544
    0x0469: { n:"BrtEndSlicerStyle", f:parsenoop },
10545
    0x046A: { n:"BrtSlicerStyleElement", f:parsenoop },
10546
    0x046B: { n:"BrtBeginStyleSheetExt14", f:parsenoop },
10547
    0x046C: { n:"BrtEndStyleSheetExt14", f:parsenoop },
10548
    0x046D: { n:"BrtBeginSlicerCachesPivotCacheID", f:parsenoop },
10549
    0x046E: { n:"BrtEndSlicerCachesPivotCacheID", f:parsenoop },
10550
    0x046F: { n:"BrtBeginConditionalFormattings", f:parsenoop },
10551
    0x0470: { n:"BrtEndConditionalFormattings", f:parsenoop },
10552
    0x0471: { n:"BrtBeginPCDCalcMemExt", f:parsenoop },
10553
    0x0472: { n:"BrtEndPCDCalcMemExt", f:parsenoop },
10554
    0x0473: { n:"BrtBeginPCDCalcMemsExt", f:parsenoop },
10555
    0x0474: { n:"BrtEndPCDCalcMemsExt", f:parsenoop },
10556
    0x0475: { n:"BrtPCDField14", f:parsenoop },
10557
    0x0476: { n:"BrtBeginSlicerStyles", f:parsenoop },
10558
    0x0477: { n:"BrtEndSlicerStyles", f:parsenoop },
10559
    0x0478: { n:"BrtBeginSlicerStyleElements", f:parsenoop },
10560
    0x0479: { n:"BrtEndSlicerStyleElements", f:parsenoop },
10561
    0x047A: { n:"BrtCFRuleExt", f:parsenoop },
10562
    0x047B: { n:"BrtBeginSXCondFmt14", f:parsenoop },
10563
    0x047C: { n:"BrtEndSXCondFmt14", f:parsenoop },
10564
    0x047D: { n:"BrtBeginSXCondFmts14", f:parsenoop },
10565
    0x047E: { n:"BrtEndSXCondFmts14", f:parsenoop },
10566
    0x0480: { n:"BrtBeginSortCond14", f:parsenoop },
10567
    0x0481: { n:"BrtEndSortCond14", f:parsenoop },
10568
    0x0482: { n:"BrtEndDVals14", f:parsenoop },
10569
    0x0483: { n:"BrtEndIconSet14", f:parsenoop },
10570
    0x0484: { n:"BrtEndDatabar14", f:parsenoop },
10571
    0x0485: { n:"BrtBeginColorScale14", f:parsenoop },
10572
    0x0486: { n:"BrtEndColorScale14", f:parsenoop },
10573
    0x0487: { n:"BrtBeginSxrules14", f:parsenoop },
10574
    0x0488: { n:"BrtEndSxrules14", f:parsenoop },
10575
    0x0489: { n:"BrtBeginPRule14", f:parsenoop },
10576
    0x048A: { n:"BrtEndPRule14", f:parsenoop },
10577
    0x048B: { n:"BrtBeginPRFilters14", f:parsenoop },
10578
    0x048C: { n:"BrtEndPRFilters14", f:parsenoop },
10579
    0x048D: { n:"BrtBeginPRFilter14", f:parsenoop },
10580
    0x048E: { n:"BrtEndPRFilter14", f:parsenoop },
10581
    0x048F: { n:"BrtBeginPRFItem14", f:parsenoop },
10582
    0x0490: { n:"BrtEndPRFItem14", f:parsenoop },
10583
    0x0491: { n:"BrtBeginCellIgnoreECs14", f:parsenoop },
10584
    0x0492: { n:"BrtEndCellIgnoreECs14", f:parsenoop },
10585
    0x0493: { n:"BrtDxf14", f:parsenoop },
10586
    0x0494: { n:"BrtBeginDxF14s", f:parsenoop },
10587
    0x0495: { n:"BrtEndDxf14s", f:parsenoop },
10588
    0x0499: { n:"BrtFilter14", f:parsenoop },
10589
    0x049A: { n:"BrtBeginCustomFilters14", f:parsenoop },
10590
    0x049C: { n:"BrtCustomFilter14", f:parsenoop },
10591
    0x049D: { n:"BrtIconFilter14", f:parsenoop },
10592
    0x049E: { n:"BrtPivotCacheConnectionName", f:parsenoop },
10593
    0x0800: { n:"BrtBeginDecoupledPivotCacheIDs", f:parsenoop },
10594
    0x0801: { n:"BrtEndDecoupledPivotCacheIDs", f:parsenoop },
10595
    0x0802: { n:"BrtDecoupledPivotCacheID", f:parsenoop },
10596
    0x0803: { n:"BrtBeginPivotTableRefs", f:parsenoop },
10597
    0x0804: { n:"BrtEndPivotTableRefs", f:parsenoop },
10598
    0x0805: { n:"BrtPivotTableRef", f:parsenoop },
10599
    0x0806: { n:"BrtSlicerCacheBookPivotTables", f:parsenoop },
10600
    0x0807: { n:"BrtBeginSxvcells", f:parsenoop },
10601
    0x0808: { n:"BrtEndSxvcells", f:parsenoop },
10602
    0x0809: { n:"BrtBeginSxRow", f:parsenoop },
10603
    0x080A: { n:"BrtEndSxRow", f:parsenoop },
10604
    0x080C: { n:"BrtPcdCalcMem15", f:parsenoop },
10605
    0x0813: { n:"BrtQsi15", f:parsenoop },
10606
    0x0814: { n:"BrtBeginWebExtensions", f:parsenoop },
10607
    0x0815: { n:"BrtEndWebExtensions", f:parsenoop },
10608
    0x0816: { n:"BrtWebExtension", f:parsenoop },
10609
    0x0817: { n:"BrtAbsPath15", f:parsenoop },
10610
    0x0818: { n:"BrtBeginPivotTableUISettings", f:parsenoop },
10611
    0x0819: { n:"BrtEndPivotTableUISettings", f:parsenoop },
10612
    0x081B: { n:"BrtTableSlicerCacheIDs", f:parsenoop },
10613
    0x081C: { n:"BrtTableSlicerCacheID", f:parsenoop },
10614
    0x081D: { n:"BrtBeginTableSlicerCache", f:parsenoop },
10615
    0x081E: { n:"BrtEndTableSlicerCache", f:parsenoop },
10616
    0x081F: { n:"BrtSxFilter15", f:parsenoop },
10617
    0x0820: { n:"BrtBeginTimelineCachePivotCacheIDs", f:parsenoop },
10618
    0x0821: { n:"BrtEndTimelineCachePivotCacheIDs", f:parsenoop },
10619
    0x0822: { n:"BrtTimelineCachePivotCacheID", f:parsenoop },
10620
    0x0823: { n:"BrtBeginTimelineCacheIDs", f:parsenoop },
10621
    0x0824: { n:"BrtEndTimelineCacheIDs", f:parsenoop },
10622
    0x0825: { n:"BrtBeginTimelineCacheID", f:parsenoop },
10623
    0x0826: { n:"BrtEndTimelineCacheID", f:parsenoop },
10624
    0x0827: { n:"BrtBeginTimelinesEx", f:parsenoop },
10625
    0x0828: { n:"BrtEndTimelinesEx", f:parsenoop },
10626
    0x0829: { n:"BrtBeginTimelineEx", f:parsenoop },
10627
    0x082A: { n:"BrtEndTimelineEx", f:parsenoop },
10628
    0x082B: { n:"BrtWorkBookPr15", f:parsenoop },
10629
    0x082C: { n:"BrtPCDH15", f:parsenoop },
10630
    0x082D: { n:"BrtBeginTimelineStyle", f:parsenoop },
10631
    0x082E: { n:"BrtEndTimelineStyle", f:parsenoop },
10632
    0x082F: { n:"BrtTimelineStyleElement", f:parsenoop },
10633
    0x0830: { n:"BrtBeginTimelineStylesheetExt15", f:parsenoop },
10634
    0x0831: { n:"BrtEndTimelineStylesheetExt15", f:parsenoop },
10635
    0x0832: { n:"BrtBeginTimelineStyles", f:parsenoop },
10636
    0x0833: { n:"BrtEndTimelineStyles", f:parsenoop },
10637
    0x0834: { n:"BrtBeginTimelineStyleElements", f:parsenoop },
10638
    0x0835: { n:"BrtEndTimelineStyleElements", f:parsenoop },
10639
    0x0836: { n:"BrtDxf15", f:parsenoop },
10640
    0x0837: { n:"BrtBeginDxfs15", f:parsenoop },
10641
    0x0838: { n:"brtEndDxfs15", f:parsenoop },
10642
    0x0839: { n:"BrtSlicerCacheHideItemsWithNoData", f:parsenoop },
10643
    0x083A: { n:"BrtBeginItemUniqueNames", f:parsenoop },
10644
    0x083B: { n:"BrtEndItemUniqueNames", f:parsenoop },
10645
    0x083C: { n:"BrtItemUniqueName", f:parsenoop },
10646
    0x083D: { n:"BrtBeginExtConn15", f:parsenoop },
10647
    0x083E: { n:"BrtEndExtConn15", f:parsenoop },
10648
    0x083F: { n:"BrtBeginOledbPr15", f:parsenoop },
10649
    0x0840: { n:"BrtEndOledbPr15", f:parsenoop },
10650
    0x0841: { n:"BrtBeginDataFeedPr15", f:parsenoop },
10651
    0x0842: { n:"BrtEndDataFeedPr15", f:parsenoop },
10652
    0x0843: { n:"BrtTextPr15", f:parsenoop },
10653
    0x0844: { n:"BrtRangePr15", f:parsenoop },
10654
    0x0845: { n:"BrtDbCommand15", f:parsenoop },
10655
    0x0846: { n:"BrtBeginDbTables15", f:parsenoop },
10656
    0x0847: { n:"BrtEndDbTables15", f:parsenoop },
10657
    0x0848: { n:"BrtDbTable15", f:parsenoop },
10658
    0x0849: { n:"BrtBeginDataModel", f:parsenoop },
10659
    0x084A: { n:"BrtEndDataModel", f:parsenoop },
10660
    0x084B: { n:"BrtBeginModelTables", f:parsenoop },
10661
    0x084C: { n:"BrtEndModelTables", f:parsenoop },
10662
    0x084D: { n:"BrtModelTable", f:parsenoop },
10663
    0x084E: { n:"BrtBeginModelRelationships", f:parsenoop },
10664
    0x084F: { n:"BrtEndModelRelationships", f:parsenoop },
10665
    0x0850: { n:"BrtModelRelationship", f:parsenoop },
10666
    0x0851: { n:"BrtBeginECTxtWiz15", f:parsenoop },
10667
    0x0852: { n:"BrtEndECTxtWiz15", f:parsenoop },
10668
    0x0853: { n:"BrtBeginECTWFldInfoLst15", f:parsenoop },
10669
    0x0854: { n:"BrtEndECTWFldInfoLst15", f:parsenoop },
10670
    0x0855: { n:"BrtBeginECTWFldInfo15", f:parsenoop },
10671
    0x0856: { n:"BrtFieldListActiveItem", f:parsenoop },
10672
    0x0857: { n:"BrtPivotCacheIdVersion", f:parsenoop },
10673
    0x0858: { n:"BrtSXDI15", f:parsenoop },
10674
    0xFFFF: { n:"", f:parsenoop }
10675
};
10676
 
10677
var evert_RE = evert_key(XLSBRecordEnum, 'n');
10678
 
10679
/* [MS-XLS] 2.3 Record Enumeration */
10680
var XLSRecordEnum = {
10681
    0x0003: { n:"BIFF2NUM", f:parse_BIFF2NUM },
10682
    0x0004: { n:"BIFF2STR", f:parse_BIFF2STR },
10683
    0x0006: { n:"Formula", f:parse_Formula },
10684
    0x0009: { n:'BOF', f:parse_BOF },
10685
    0x000a: { n:'EOF', f:parse_EOF },
10686
    0x000c: { n:"CalcCount", f:parse_CalcCount },
10687
    0x000d: { n:"CalcMode", f:parse_CalcMode },
10688
    0x000e: { n:"CalcPrecision", f:parse_CalcPrecision },
10689
    0x000f: { n:"CalcRefMode", f:parse_CalcRefMode },
10690
    0x0010: { n:"CalcDelta", f:parse_CalcDelta },
10691
    0x0011: { n:"CalcIter", f:parse_CalcIter },
10692
    0x0012: { n:"Protect", f:parse_Protect },
10693
    0x0013: { n:"Password", f:parse_Password },
10694
    0x0014: { n:"Header", f:parse_Header },
10695
    0x0015: { n:"Footer", f:parse_Footer },
10696
    0x0017: { n:"ExternSheet", f:parse_ExternSheet },
10697
    0x0018: { n:"Lbl", f:parse_Lbl },
10698
    0x0019: { n:"WinProtect", f:parse_WinProtect },
10699
    0x001a: { n:"VerticalPageBreaks", f:parse_VerticalPageBreaks },
10700
    0x001b: { n:"HorizontalPageBreaks", f:parse_HorizontalPageBreaks },
10701
    0x001c: { n:"Note", f:parse_Note },
10702
    0x001d: { n:"Selection", f:parse_Selection },
10703
    0x0022: { n:"Date1904", f:parse_Date1904 },
10704
    0x0023: { n:"ExternName", f:parse_ExternName },
10705
    0x0026: { n:"LeftMargin", f:parse_LeftMargin },
10706
    0x0027: { n:"RightMargin", f:parse_RightMargin },
10707
    0x0028: { n:"TopMargin", f:parse_TopMargin },
10708
    0x0029: { n:"BottomMargin", f:parse_BottomMargin },
10709
    0x002a: { n:"PrintRowCol", f:parse_PrintRowCol },
10710
    0x002b: { n:"PrintGrid", f:parse_PrintGrid },
10711
    0x002f: { n:"FilePass", f:parse_FilePass },
10712
    0x0031: { n:"Font", f:parse_Font },
10713
    0x0033: { n:"PrintSize", f:parse_PrintSize },
10714
    0x003c: { n:"Continue", f:parse_Continue },
10715
    0x003d: { n:"Window1", f:parse_Window1 },
10716
    0x0040: { n:"Backup", f:parse_Backup },
10717
    0x0041: { n:"Pane", f:parse_Pane },
10718
    0x0042: { n:'CodePage', f:parse_CodePage },
10719
    0x004d: { n:"Pls", f:parse_Pls },
10720
    0x0050: { n:"DCon", f:parse_DCon },
10721
    0x0051: { n:"DConRef", f:parse_DConRef },
10722
    0x0052: { n:"DConName", f:parse_DConName },
10723
    0x0055: { n:"DefColWidth", f:parse_DefColWidth },
10724
    0x0059: { n:"XCT", f:parse_XCT },
10725
    0x005a: { n:"CRN", f:parse_CRN },
10726
    0x005b: { n:"FileSharing", f:parse_FileSharing },
10727
    0x005c: { n:'WriteAccess', f:parse_WriteAccess },
10728
    0x005d: { n:"Obj", f:parse_Obj },
10729
    0x005e: { n:"Uncalced", f:parse_Uncalced },
10730
    0x005f: { n:"CalcSaveRecalc", f:parse_CalcSaveRecalc },
10731
    0x0060: { n:"Template", f:parse_Template },
10732
    0x0061: { n:"Intl", f:parse_Intl },
10733
    0x0063: { n:"ObjProtect", f:parse_ObjProtect },
10734
    0x007d: { n:"ColInfo", f:parse_ColInfo },
10735
    0x0080: { n:"Guts", f:parse_Guts },
10736
    0x0081: { n:"WsBool", f:parse_WsBool },
10737
    0x0082: { n:"GridSet", f:parse_GridSet },
10738
    0x0083: { n:"HCenter", f:parse_HCenter },
10739
    0x0084: { n:"VCenter", f:parse_VCenter },
10740
    0x0085: { n:'BoundSheet8', f:parse_BoundSheet8 },
10741
    0x0086: { n:"WriteProtect", f:parse_WriteProtect },
10742
    0x008c: { n:"Country", f:parse_Country },
10743
    0x008d: { n:"HideObj", f:parse_HideObj },
10744
    0x0090: { n:"Sort", f:parse_Sort },
10745
    0x0092: { n:"Palette", f:parse_Palette },
10746
    0x0097: { n:"Sync", f:parse_Sync },
10747
    0x0098: { n:"LPr", f:parse_LPr },
10748
    0x0099: { n:"DxGCol", f:parse_DxGCol },
10749
    0x009a: { n:"FnGroupName", f:parse_FnGroupName },
10750
    0x009b: { n:"FilterMode", f:parse_FilterMode },
10751
    0x009c: { n:"BuiltInFnGroupCount", f:parse_BuiltInFnGroupCount },
10752
    0x009d: { n:"AutoFilterInfo", f:parse_AutoFilterInfo },
10753
    0x009e: { n:"AutoFilter", f:parse_AutoFilter },
10754
    0x00a0: { n:"Scl", f:parse_Scl },
10755
    0x00a1: { n:"Setup", f:parse_Setup },
10756
    0x00ae: { n:"ScenMan", f:parse_ScenMan },
10757
    0x00af: { n:"SCENARIO", f:parse_SCENARIO },
10758
    0x00b0: { n:"SxView", f:parse_SxView },
10759
    0x00b1: { n:"Sxvd", f:parse_Sxvd },
10760
    0x00b2: { n:"SXVI", f:parse_SXVI },
10761
    0x00b4: { n:"SxIvd", f:parse_SxIvd },
10762
    0x00b5: { n:"SXLI", f:parse_SXLI },
10763
    0x00b6: { n:"SXPI", f:parse_SXPI },
10764
    0x00b8: { n:"DocRoute", f:parse_DocRoute },
10765
    0x00b9: { n:"RecipName", f:parse_RecipName },
10766
    0x00bd: { n:"MulRk", f:parse_MulRk },
10767
    0x00be: { n:"MulBlank", f:parse_MulBlank },
10768
    0x00c1: { n:'Mms', f:parse_Mms },
10769
    0x00c5: { n:"SXDI", f:parse_SXDI },
10770
    0x00c6: { n:"SXDB", f:parse_SXDB },
10771
    0x00c7: { n:"SXFDB", f:parse_SXFDB },
10772
    0x00c8: { n:"SXDBB", f:parse_SXDBB },
10773
    0x00c9: { n:"SXNum", f:parse_SXNum },
10774
    0x00ca: { n:"SxBool", f:parse_SxBool },
10775
    0x00cb: { n:"SxErr", f:parse_SxErr },
10776
    0x00cc: { n:"SXInt", f:parse_SXInt },
10777
    0x00cd: { n:"SXString", f:parse_SXString },
10778
    0x00ce: { n:"SXDtr", f:parse_SXDtr },
10779
    0x00cf: { n:"SxNil", f:parse_SxNil },
10780
    0x00d0: { n:"SXTbl", f:parse_SXTbl },
10781
    0x00d1: { n:"SXTBRGIITM", f:parse_SXTBRGIITM },
10782
    0x00d2: { n:"SxTbpg", f:parse_SxTbpg },
10783
    0x00d3: { n:"ObProj", f:parse_ObProj },
10784
    0x00d5: { n:"SXStreamID", f:parse_SXStreamID },
10785
    0x00d7: { n:"DBCell", f:parse_DBCell },
10786
    0x00d8: { n:"SXRng", f:parse_SXRng },
10787
    0x00d9: { n:"SxIsxoper", f:parse_SxIsxoper },
10788
    0x00da: { n:"BookBool", f:parse_BookBool },
10789
    0x00dc: { n:"DbOrParamQry", f:parse_DbOrParamQry },
10790
    0x00dd: { n:"ScenarioProtect", f:parse_ScenarioProtect },
10791
    0x00de: { n:"OleObjectSize", f:parse_OleObjectSize },
10792
    0x00e0: { n:"XF", f:parse_XF },
10793
    0x00e1: { n:'InterfaceHdr', f:parse_InterfaceHdr },
10794
    0x00e2: { n:'InterfaceEnd', f:parse_InterfaceEnd },
10795
    0x00e3: { n:"SXVS", f:parse_SXVS },
10796
    0x00e5: { n:"MergeCells", f:parse_MergeCells },
10797
    0x00e9: { n:"BkHim", f:parse_BkHim },
10798
    0x00eb: { n:"MsoDrawingGroup", f:parse_MsoDrawingGroup },
10799
    0x00ec: { n:"MsoDrawing", f:parse_MsoDrawing },
10800
    0x00ed: { n:"MsoDrawingSelection", f:parse_MsoDrawingSelection },
10801
    0x00ef: { n:"PhoneticInfo", f:parse_PhoneticInfo },
10802
    0x00f0: { n:"SxRule", f:parse_SxRule },
10803
    0x00f1: { n:"SXEx", f:parse_SXEx },
10804
    0x00f2: { n:"SxFilt", f:parse_SxFilt },
10805
    0x00f4: { n:"SxDXF", f:parse_SxDXF },
10806
    0x00f5: { n:"SxItm", f:parse_SxItm },
10807
    0x00f6: { n:"SxName", f:parse_SxName },
10808
    0x00f7: { n:"SxSelect", f:parse_SxSelect },
10809
    0x00f8: { n:"SXPair", f:parse_SXPair },
10810
    0x00f9: { n:"SxFmla", f:parse_SxFmla },
10811
    0x00fb: { n:"SxFormat", f:parse_SxFormat },
10812
    0x00fc: { n:"SST", f:parse_SST },
10813
    0x00fd: { n:"LabelSst", f:parse_LabelSst },
10814
    0x00ff: { n:"ExtSST", f:parse_ExtSST },
10815
    0x0100: { n:"SXVDEx", f:parse_SXVDEx },
10816
    0x0103: { n:"SXFormula", f:parse_SXFormula },
10817
    0x0122: { n:"SXDBEx", f:parse_SXDBEx },
10818
    0x0137: { n:"RRDInsDel", f:parse_RRDInsDel },
10819
    0x0138: { n:"RRDHead", f:parse_RRDHead },
10820
    0x013b: { n:"RRDChgCell", f:parse_RRDChgCell },
10821
    0x013d: { n:"RRTabId", f:parse_RRTabId },
10822
    0x013e: { n:"RRDRenSheet", f:parse_RRDRenSheet },
10823
    0x013f: { n:"RRSort", f:parse_RRSort },
10824
    0x0140: { n:"RRDMove", f:parse_RRDMove },
10825
    0x014a: { n:"RRFormat", f:parse_RRFormat },
10826
    0x014b: { n:"RRAutoFmt", f:parse_RRAutoFmt },
10827
    0x014d: { n:"RRInsertSh", f:parse_RRInsertSh },
10828
    0x014e: { n:"RRDMoveBegin", f:parse_RRDMoveBegin },
10829
    0x014f: { n:"RRDMoveEnd", f:parse_RRDMoveEnd },
10830
    0x0150: { n:"RRDInsDelBegin", f:parse_RRDInsDelBegin },
10831
    0x0151: { n:"RRDInsDelEnd", f:parse_RRDInsDelEnd },
10832
    0x0152: { n:"RRDConflict", f:parse_RRDConflict },
10833
    0x0153: { n:"RRDDefName", f:parse_RRDDefName },
10834
    0x0154: { n:"RRDRstEtxp", f:parse_RRDRstEtxp },
10835
    0x015f: { n:"LRng", f:parse_LRng },
10836
    0x0160: { n:"UsesELFs", f:parse_UsesELFs },
10837
    0x0161: { n:"DSF", f:parse_DSF },
10838
    0x0191: { n:"CUsr", f:parse_CUsr },
10839
    0x0192: { n:"CbUsr", f:parse_CbUsr },
10840
    0x0193: { n:"UsrInfo", f:parse_UsrInfo },
10841
    0x0194: { n:"UsrExcl", f:parse_UsrExcl },
10842
    0x0195: { n:"FileLock", f:parse_FileLock },
10843
    0x0196: { n:"RRDInfo", f:parse_RRDInfo },
10844
    0x0197: { n:"BCUsrs", f:parse_BCUsrs },
10845
    0x0198: { n:"UsrChk", f:parse_UsrChk },
10846
    0x01a9: { n:"UserBView", f:parse_UserBView },
10847
    0x01aa: { n:"UserSViewBegin", f:parse_UserSViewBegin },
10848
    0x01ab: { n:"UserSViewEnd", f:parse_UserSViewEnd },
10849
    0x01ac: { n:"RRDUserView", f:parse_RRDUserView },
10850
    0x01ad: { n:"Qsi", f:parse_Qsi },
10851
    0x01ae: { n:"SupBook", f:parse_SupBook },
10852
    0x01af: { n:"Prot4Rev", f:parse_Prot4Rev },
10853
    0x01b0: { n:"CondFmt", f:parse_CondFmt },
10854
    0x01b1: { n:"CF", f:parse_CF },
10855
    0x01b2: { n:"DVal", f:parse_DVal },
10856
    0x01b5: { n:"DConBin", f:parse_DConBin },
10857
    0x01b6: { n:"TxO", f:parse_TxO },
10858
    0x01b7: { n:"RefreshAll", f:parse_RefreshAll },
10859
    0x01b8: { n:"HLink", f:parse_HLink },
10860
    0x01b9: { n:"Lel", f:parse_Lel },
10861
    0x01ba: { n:"CodeName", f:parse_XLSCodeName },
10862
    0x01bb: { n:"SXFDBType", f:parse_SXFDBType },
10863
    0x01bc: { n:"Prot4RevPass", f:parse_Prot4RevPass },
10864
    0x01bd: { n:"ObNoMacros", f:parse_ObNoMacros },
10865
    0x01be: { n:"Dv", f:parse_Dv },
10866
    0x01c0: { n:"Excel9File", f:parse_Excel9File },
10867
    0x01c1: { n:"RecalcId", f:parse_RecalcId, r:2},
10868
    0x01c2: { n:"EntExU2", f:parse_EntExU2 },
10869
    0x0200: { n:"Dimensions", f:parse_Dimensions },
10870
    0x0201: { n:"Blank", f:parse_Blank },
10871
    0x0203: { n:"Number", f:parse_Number },
10872
    0x0204: { n:"Label", f:parse_Label },
10873
    0x0205: { n:"BoolErr", f:parse_BoolErr },
10874
    0x0207: { n:"String", f:parse_String },
10875
    0x0208: { n:'Row', f:parse_Row },
10876
    0x020b: { n:"Index", f:parse_Index },
10877
    0x0221: { n:"Array", f:parse_Array },
10878
    0x0225: { n:"DefaultRowHeight", f:parse_DefaultRowHeight },
10879
    0x0236: { n:"Table", f:parse_Table },
10880
    0x023e: { n:"Window2", f:parse_Window2 },
10881
    0x027e: { n:"RK", f:parse_RK },
10882
    0x0293: { n:"Style", f:parse_Style },
10883
    0x0418: { n:"BigName", f:parse_BigName },
10884
    0x041e: { n:"Format", f:parse_Format },
10885
    0x043c: { n:"ContinueBigName", f:parse_ContinueBigName },
10886
    0x04bc: { n:"ShrFmla", f:parse_ShrFmla },
10887
    0x0800: { n:"HLinkTooltip", f:parse_HLinkTooltip },
10888
    0x0801: { n:"WebPub", f:parse_WebPub },
10889
    0x0802: { n:"QsiSXTag", f:parse_QsiSXTag },
10890
    0x0803: { n:"DBQueryExt", f:parse_DBQueryExt },
10891
    0x0804: { n:"ExtString", f:parse_ExtString },
10892
    0x0805: { n:"TxtQry", f:parse_TxtQry },
10893
    0x0806: { n:"Qsir", f:parse_Qsir },
10894
    0x0807: { n:"Qsif", f:parse_Qsif },
10895
    0x0808: { n:"RRDTQSIF", f:parse_RRDTQSIF },
10896
    0x0809: { n:'BOF', f:parse_BOF },
10897
    0x080a: { n:"OleDbConn", f:parse_OleDbConn },
10898
    0x080b: { n:"WOpt", f:parse_WOpt },
10899
    0x080c: { n:"SXViewEx", f:parse_SXViewEx },
10900
    0x080d: { n:"SXTH", f:parse_SXTH },
10901
    0x080e: { n:"SXPIEx", f:parse_SXPIEx },
10902
    0x080f: { n:"SXVDTEx", f:parse_SXVDTEx },
10903
    0x0810: { n:"SXViewEx9", f:parse_SXViewEx9 },
10904
    0x0812: { n:"ContinueFrt", f:parse_ContinueFrt },
10905
    0x0813: { n:"RealTimeData", f:parse_RealTimeData },
10906
    0x0850: { n:"ChartFrtInfo", f:parse_ChartFrtInfo },
10907
    0x0851: { n:"FrtWrapper", f:parse_FrtWrapper },
10908
    0x0852: { n:"StartBlock", f:parse_StartBlock },
10909
    0x0853: { n:"EndBlock", f:parse_EndBlock },
10910
    0x0854: { n:"StartObject", f:parse_StartObject },
10911
    0x0855: { n:"EndObject", f:parse_EndObject },
10912
    0x0856: { n:"CatLab", f:parse_CatLab },
10913
    0x0857: { n:"YMult", f:parse_YMult },
10914
    0x0858: { n:"SXViewLink", f:parse_SXViewLink },
10915
    0x0859: { n:"PivotChartBits", f:parse_PivotChartBits },
10916
    0x085a: { n:"FrtFontList", f:parse_FrtFontList },
10917
    0x0862: { n:"SheetExt", f:parse_SheetExt },
10918
    0x0863: { n:"BookExt", f:parse_BookExt, r:12},
10919
    0x0864: { n:"SXAddl", f:parse_SXAddl },
10920
    0x0865: { n:"CrErr", f:parse_CrErr },
10921
    0x0866: { n:"HFPicture", f:parse_HFPicture },
10922
    0x0867: { n:'FeatHdr', f:parse_FeatHdr },
10923
    0x0868: { n:"Feat", f:parse_Feat },
10924
    0x086a: { n:"DataLabExt", f:parse_DataLabExt },
10925
    0x086b: { n:"DataLabExtContents", f:parse_DataLabExtContents },
10926
    0x086c: { n:"CellWatch", f:parse_CellWatch },
10927
    0x0871: { n:"FeatHdr11", f:parse_FeatHdr11 },
10928
    0x0872: { n:"Feature11", f:parse_Feature11 },
10929
    0x0874: { n:"DropDownObjIds", f:parse_DropDownObjIds },
10930
    0x0875: { n:"ContinueFrt11", f:parse_ContinueFrt11 },
10931
    0x0876: { n:"DConn", f:parse_DConn },
10932
    0x0877: { n:"List12", f:parse_List12 },
10933
    0x0878: { n:"Feature12", f:parse_Feature12 },
10934
    0x0879: { n:"CondFmt12", f:parse_CondFmt12 },
10935
    0x087a: { n:"CF12", f:parse_CF12 },
10936
    0x087b: { n:"CFEx", f:parse_CFEx },
10937
    0x087c: { n:"XFCRC", f:parse_XFCRC, r:12 },
10938
    0x087d: { n:"XFExt", f:parse_XFExt, r:12 },
10939
    0x087e: { n:"AutoFilter12", f:parse_AutoFilter12 },
10940
    0x087f: { n:"ContinueFrt12", f:parse_ContinueFrt12 },
10941
    0x0884: { n:"MDTInfo", f:parse_MDTInfo },
10942
    0x0885: { n:"MDXStr", f:parse_MDXStr },
10943
    0x0886: { n:"MDXTuple", f:parse_MDXTuple },
10944
    0x0887: { n:"MDXSet", f:parse_MDXSet },
10945
    0x0888: { n:"MDXProp", f:parse_MDXProp },
10946
    0x0889: { n:"MDXKPI", f:parse_MDXKPI },
10947
    0x088a: { n:"MDB", f:parse_MDB },
10948
    0x088b: { n:"PLV", f:parse_PLV },
10949
    0x088c: { n:"Compat12", f:parse_Compat12, r:12 },
10950
    0x088d: { n:"DXF", f:parse_DXF },
10951
    0x088e: { n:"TableStyles", f:parse_TableStyles, r:12 },
10952
    0x088f: { n:"TableStyle", f:parse_TableStyle },
10953
    0x0890: { n:"TableStyleElement", f:parse_TableStyleElement },
10954
    0x0892: { n:"StyleExt", f:parse_StyleExt },
10955
    0x0893: { n:"NamePublish", f:parse_NamePublish },
10956
    0x0894: { n:"NameCmt", f:parse_NameCmt },
10957
    0x0895: { n:"SortData", f:parse_SortData },
10958
    0x0896: { n:"Theme", f:parse_Theme, r:12 },
10959
    0x0897: { n:"GUIDTypeLib", f:parse_GUIDTypeLib },
10960
    0x0898: { n:"FnGrp12", f:parse_FnGrp12 },
10961
    0x0899: { n:"NameFnGrp12", f:parse_NameFnGrp12 },
10962
    0x089a: { n:"MTRSettings", f:parse_MTRSettings, r:12 },
10963
    0x089b: { n:"CompressPictures", f:parse_CompressPictures },
10964
    0x089c: { n:"HeaderFooter", f:parse_HeaderFooter },
10965
    0x089d: { n:"CrtLayout12", f:parse_CrtLayout12 },
10966
    0x089e: { n:"CrtMlFrt", f:parse_CrtMlFrt },
10967
    0x089f: { n:"CrtMlFrtContinue", f:parse_CrtMlFrtContinue },
10968
    0x08a3: { n:"ForceFullCalculation", f:parse_ForceFullCalculation },
10969
    0x08a4: { n:"ShapePropsStream", f:parse_ShapePropsStream },
10970
    0x08a5: { n:"TextPropsStream", f:parse_TextPropsStream },
10971
    0x08a6: { n:"RichTextStream", f:parse_RichTextStream },
10972
    0x08a7: { n:"CrtLayout12A", f:parse_CrtLayout12A },
10973
    0x1001: { n:"Units", f:parse_Units },
10974
    0x1002: { n:"Chart", f:parse_Chart },
10975
    0x1003: { n:"Series", f:parse_Series },
10976
    0x1006: { n:"DataFormat", f:parse_DataFormat },
10977
    0x1007: { n:"LineFormat", f:parse_LineFormat },
10978
    0x1009: { n:"MarkerFormat", f:parse_MarkerFormat },
10979
    0x100a: { n:"AreaFormat", f:parse_AreaFormat },
10980
    0x100b: { n:"PieFormat", f:parse_PieFormat },
10981
    0x100c: { n:"AttachedLabel", f:parse_AttachedLabel },
10982
    0x100d: { n:"SeriesText", f:parse_SeriesText },
10983
    0x1014: { n:"ChartFormat", f:parse_ChartFormat },
10984
    0x1015: { n:"Legend", f:parse_Legend },
10985
    0x1016: { n:"SeriesList", f:parse_SeriesList },
10986
    0x1017: { n:"Bar", f:parse_Bar },
10987
    0x1018: { n:"Line", f:parse_Line },
10988
    0x1019: { n:"Pie", f:parse_Pie },
10989
    0x101a: { n:"Area", f:parse_Area },
10990
    0x101b: { n:"Scatter", f:parse_Scatter },
10991
    0x101c: { n:"CrtLine", f:parse_CrtLine },
10992
    0x101d: { n:"Axis", f:parse_Axis },
10993
    0x101e: { n:"Tick", f:parse_Tick },
10994
    0x101f: { n:"ValueRange", f:parse_ValueRange },
10995
    0x1020: { n:"CatSerRange", f:parse_CatSerRange },
10996
    0x1021: { n:"AxisLine", f:parse_AxisLine },
10997
    0x1022: { n:"CrtLink", f:parse_CrtLink },
10998
    0x1024: { n:"DefaultText", f:parse_DefaultText },
10999
    0x1025: { n:"Text", f:parse_Text },
11000
    0x1026: { n:"FontX", f:parse_FontX },
11001
    0x1027: { n:"ObjectLink", f:parse_ObjectLink },
11002
    0x1032: { n:"Frame", f:parse_Frame },
11003
    0x1033: { n:"Begin", f:parse_Begin },
11004
    0x1034: { n:"End", f:parse_End },
11005
    0x1035: { n:"PlotArea", f:parse_PlotArea },
11006
    0x103a: { n:"Chart3d", f:parse_Chart3d },
11007
    0x103c: { n:"PicF", f:parse_PicF },
11008
    0x103d: { n:"DropBar", f:parse_DropBar },
11009
    0x103e: { n:"Radar", f:parse_Radar },
11010
    0x103f: { n:"Surf", f:parse_Surf },
11011
    0x1040: { n:"RadarArea", f:parse_RadarArea },
11012
    0x1041: { n:"AxisParent", f:parse_AxisParent },
11013
    0x1043: { n:"LegendException", f:parse_LegendException },
11014
    0x1044: { n:"ShtProps", f:parse_ShtProps },
11015
    0x1045: { n:"SerToCrt", f:parse_SerToCrt },
11016
    0x1046: { n:"AxesUsed", f:parse_AxesUsed },
11017
    0x1048: { n:"SBaseRef", f:parse_SBaseRef },
11018
    0x104a: { n:"SerParent", f:parse_SerParent },
11019
    0x104b: { n:"SerAuxTrend", f:parse_SerAuxTrend },
11020
    0x104e: { n:"IFmtRecord", f:parse_IFmtRecord },
11021
    0x104f: { n:"Pos", f:parse_Pos },
11022
    0x1050: { n:"AlRuns", f:parse_AlRuns },
11023
    0x1051: { n:"BRAI", f:parse_BRAI },
11024
    0x105b: { n:"SerAuxErrBar", f:parse_SerAuxErrBar },
11025
    0x105c: { n:"ClrtClient", f:parse_ClrtClient },
11026
    0x105d: { n:"SerFmt", f:parse_SerFmt },
11027
    0x105f: { n:"Chart3DBarShape", f:parse_Chart3DBarShape },
11028
    0x1060: { n:"Fbi", f:parse_Fbi },
11029
    0x1061: { n:"BopPop", f:parse_BopPop },
11030
    0x1062: { n:"AxcExt", f:parse_AxcExt },
11031
    0x1063: { n:"Dat", f:parse_Dat },
11032
    0x1064: { n:"PlotGrowth", f:parse_PlotGrowth },
11033
    0x1065: { n:"SIIndex", f:parse_SIIndex },
11034
    0x1066: { n:"GelFrame", f:parse_GelFrame },
11035
    0x1067: { n:"BopPopCustom", f:parse_BopPopCustom },
11036
    0x1068: { n:"Fbi2", f:parse_Fbi2 },
11037
 
11038
    /* These are specified in an older version of the spec */
11039
    0x0016: { n:"ExternCount", f:parsenoop },
11040
    0x007e: { n:"RK", f:parsenoop }, /* Not necessarily same as 0x027e */
11041
    0x007f: { n:"ImData", f:parsenoop },
11042
    0x0087: { n:"Addin", f:parsenoop },
11043
    0x0088: { n:"Edg", f:parsenoop },
11044
    0x0089: { n:"Pub", f:parsenoop },
11045
    0x0091: { n:"Sub", f:parsenoop },
11046
    0x0094: { n:"LHRecord", f:parsenoop },
11047
    0x0095: { n:"LHNGraph", f:parsenoop },
11048
    0x0096: { n:"Sound", f:parsenoop },
11049
    0x00a9: { n:"CoordList", f:parsenoop },
11050
    0x00ab: { n:"GCW", f:parsenoop },
11051
    0x00bc: { n:"ShrFmla", f:parsenoop }, /* Not necessarily same as 0x04bc */
11052
    0x00c2: { n:"AddMenu", f:parsenoop },
11053
    0x00c3: { n:"DelMenu", f:parsenoop },
11054
    0x00d6: { n:"RString", f:parsenoop },
11055
    0x00df: { n:"UDDesc", f:parsenoop },
11056
    0x00ea: { n:"TabIdConf", f:parsenoop },
11057
    0x0162: { n:"XL5Modify", f:parsenoop },
11058
    0x01a5: { n:"FileSharing2", f:parsenoop },
11059
    0x0218: { n:"Name", f:parsenoop },
11060
    0x0223: { n:"ExternName", f:parse_ExternName },
11061
    0x0231: { n:"Font", f:parsenoop },
11062
    0x0406: { n:"Formula", f:parse_Formula },
11063
    0x086d: { n:"FeatInfo", f:parsenoop },
11064
    0x0873: { n:"FeatInfo11", f:parsenoop },
11065
    0x0881: { n:"SXAddl12", f:parsenoop },
11066
    0x08c0: { n:"AutoWebPub", f:parsenoop },
11067
    0x08c1: { n:"ListObj", f:parsenoop },
11068
    0x08c2: { n:"ListField", f:parsenoop },
11069
    0x08c3: { n:"ListDV", f:parsenoop },
11070
    0x08c4: { n:"ListCondFmt", f:parsenoop },
11071
    0x08c5: { n:"ListCF", f:parsenoop },
11072
    0x08c6: { n:"FMQry", f:parsenoop },
11073
    0x08c7: { n:"FMSQry", f:parsenoop },
11074
    0x08c8: { n:"PLV", f:parsenoop }, /* supposedly PLV for Excel 11 */
11075
    0x08c9: { n:"LnExt", f:parsenoop },
11076
    0x08ca: { n:"MkrExt", f:parsenoop },
11077
    0x08cb: { n:"CrtCoopt", f:parsenoop },
11078
 
11079
    0x0000: {}
11080
};
11081
 
11082
 
11083
/* Helper function to call out to ODS parser */
11084
function parse_ods(zip, opts) {
11085
    if(typeof module !== "undefined" && typeof require !== 'undefined' && typeof ODS === 'undefined') ODS = require('./od' + 's');
11086
    if(typeof ODS === 'undefined' || !ODS.parse_ods) throw new Error("Unsupported ODS");
11087
    return ODS.parse_ods(zip, opts);
11088
}
11089
function fix_opts_func(defaults) {
11090
    return function fix_opts(opts) {
11091
        for(var i = 0; i != defaults.length; ++i) {
11092
            var d = defaults[i];
11093
            if(opts[d[0]] === undefined) opts[d[0]] = d[1];
11094
            if(d[2] === 'n') opts[d[0]] = Number(opts[d[0]]);
11095
        }
11096
    };
11097
}
11098
 
11099
var fix_read_opts = fix_opts_func([
11100
    ['cellNF', false], /* emit cell number format string as .z */
11101
    ['cellHTML', true], /* emit html string as .h */
11102
    ['cellFormula', true], /* emit formulae as .f */
11103
    ['cellStyles', false], /* emits style/theme as .s */
11104
    ['cellDates', false], /* emit date cells with type `d` */
11105
 
11106
    ['sheetStubs', false], /* emit empty cells */
11107
    ['sheetRows', 0, 'n'], /* read n rows (0 = read all rows) */
11108
 
11109
    ['bookDeps', false], /* parse calculation chains */
11110
    ['bookSheets', false], /* only try to get sheet names (no Sheets) */
11111
    ['bookProps', false], /* only try to get properties (no Sheets) */
11112
    ['bookFiles', false], /* include raw file structure (keys, files, cfb) */
11113
    ['bookVBA', false], /* include vba raw data (vbaraw) */
11114
 
11115
    ['password',''], /* password */
11116
    ['WTF', false] /* WTF mode (throws errors) */
11117
]);
11118
 
11119
 
11120
var fix_write_opts = fix_opts_func([
11121
    ['cellDates', false], /* write date cells with type `d` */
11122
 
11123
    ['bookSST', false], /* Generate Shared String Table */
11124
 
11125
    ['bookType', 'xlsx'], /* Type of workbook (xlsx/m/b) */
11126
 
11127
    ['WTF', false] /* WTF mode (throws errors) */
11128
]);
11129
function safe_parse_wbrels(wbrels, sheets) {
11130
    if(!wbrels) return 0;
11131
    try {
11132
        wbrels = sheets.map(function pwbr(w) { return [w.name, wbrels['!id'][w.id].Target]; });
11133
    } catch(e) { return null; }
11134
    return !wbrels || wbrels.length === 0 ? null : wbrels;
11135
}
11136
 
11137
function safe_parse_ws(zip, path, relsPath, sheet, sheetRels, sheets, opts) {
11138
    try {
11139
        sheetRels[sheet]=parse_rels(getzipdata(zip, relsPath, true), path);
11140
        sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet]);
11141
    } catch(e) { if(opts.WTF) throw e; }
11142
}
11143
 
11144
var nodirs = function nodirs(x){return x.substr(-1) != '/';};
11145
function parse_zip(zip, opts) {
11146
    make_ssf(SSF);
11147
    opts = opts || {};
11148
    fix_read_opts(opts);
11149
    reset_cp();
11150
 
11151
    /* OpenDocument Part 3 Section 2.2.1 OpenDocument Package */
11152
    if(safegetzipfile(zip, 'META-INF/manifest.xml')) return parse_ods(zip, opts);
11153
 
11154
    var entries = keys(zip.files).filter(nodirs).sort();
11155
    var dir = parse_ct(getzipdata(zip, '[Content_Types].xml'), opts);
11156
    var xlsb = false;
11157
    var sheets, binname;
11158
    if(dir.workbooks.length === 0) {
11159
        binname = "xl/workbook.xml";
11160
        if(getzipdata(zip,binname, true)) dir.workbooks.push(binname);
11161
    }
11162
    if(dir.workbooks.length === 0) {
11163
        binname = "xl/workbook.bin";
11164
        if(!getzipfile(zip,binname,true)) throw new Error("Could not find workbook");
11165
        dir.workbooks.push(binname);
11166
        xlsb = true;
11167
    }
11168
    if(dir.workbooks[0].substr(-3) == "bin") xlsb = true;
11169
    if(xlsb) set_cp(1200);
11170
 
11171
    if(!opts.bookSheets && !opts.bookProps) {
11172
        strs = [];
11173
        if(dir.sst) strs=parse_sst(getzipdata(zip, dir.sst.replace(/^\//,'')), dir.sst, opts);
11174
 
11175
        styles = {};
11176
        if(dir.style) styles = parse_sty(getzipdata(zip, dir.style.replace(/^\//,'')),dir.style, opts);
11177
 
11178
        themes = {};
11179
        if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipdata(zip, dir.themes[0].replace(/^\//,''), true),dir.themes[0], opts);
11180
    }
11181
 
11182
    var wb = parse_wb(getzipdata(zip, dir.workbooks[0].replace(/^\//,'')), dir.workbooks[0], opts);
11183
 
11184
    var props = {}, propdata = "";
11185
 
11186
    if(dir.coreprops.length !== 0) {
11187
        propdata = getzipdata(zip, dir.coreprops[0].replace(/^\//,''), true);
11188
        if(propdata) props = parse_core_props(propdata);
11189
        if(dir.extprops.length !== 0) {
11190
            propdata = getzipdata(zip, dir.extprops[0].replace(/^\//,''), true);
11191
            if(propdata) parse_ext_props(propdata, props);
11192
        }
11193
    }
11194
 
11195
    var custprops = {};
11196
    if(!opts.bookSheets || opts.bookProps) {
11197
        if (dir.custprops.length !== 0) {
11198
            propdata = getzipdata(zip, dir.custprops[0].replace(/^\//,''), true);
11199
            if(propdata) custprops = parse_cust_props(propdata, opts);
11200
        }
11201
    }
11202
 
11203
    var out = {};
11204
    if(opts.bookSheets || opts.bookProps) {
11205
        if(props.Worksheets && props.SheetNames.length > 0) sheets=props.SheetNames;
11206
        else if(wb.Sheets) sheets = wb.Sheets.map(function pluck(x){ return x.name; });
11207
        if(opts.bookProps) { out.Props = props; out.Custprops = custprops; }
11208
        if(typeof sheets !== 'undefined') out.SheetNames = sheets;
11209
        if(opts.bookSheets ? out.SheetNames : opts.bookProps) return out;
11210
    }
11211
    sheets = {};
11212
 
11213
    var deps = {};
11214
    if(opts.bookDeps && dir.calcchain) deps=parse_cc(getzipdata(zip, dir.calcchain.replace(/^\//,'')),dir.calcchain,opts);
11215
 
11216
    var i=0;
11217
    var sheetRels = {};
11218
    var path, relsPath;
11219
    if(!props.Worksheets) {
11220
        var wbsheets = wb.Sheets;
11221
        props.Worksheets = wbsheets.length;
11222
        props.SheetNames = [];
11223
        for(var j = 0; j != wbsheets.length; ++j) {
11224
            props.SheetNames[j] = wbsheets[j].name;
11225
        }
11226
    }
11227
 
11228
    var wbext = xlsb ? "bin" : "xml";
11229
    var wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
11230
    var wbrels = parse_rels(getzipdata(zip, wbrelsfile, true), wbrelsfile);
11231
    if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
11232
    /* Numbers iOS hack */
11233
    var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
11234
    for(i = 0; i != props.Worksheets; ++i) {
11235
        if(wbrels) path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
11236
        else {
11237
            path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
11238
            path = path.replace(/sheet0\./,"sheet.");
11239
        }
11240
        relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
11241
        safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts);
11242
    }
11243
 
11244
    if(dir.comments) parse_comments(zip, dir.comments, sheets, sheetRels, opts);
11245
 
11246
    out = {
11247
        Directory: dir,
11248
        Workbook: wb,
11249
        Props: props,
11250
        Custprops: custprops,
11251
        Deps: deps,
11252
        Sheets: sheets,
11253
        SheetNames: props.SheetNames,
11254
        Strings: strs,
11255
        Styles: styles,
11256
        Themes: themes,
11257
        SSF: SSF.get_table()
11258
    };
11259
    if(opts.bookFiles) {
11260
        out.keys = entries;
11261
        out.files = zip.files;
11262
    }
11263
    if(opts.bookVBA) {
11264
        if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,dir.vba[0],true);
11265
        else if(dir.defaults.bin === 'application/vnd.ms-office.vbaProject') out.vbaraw = getzipdata(zip,'xl/vbaProject.bin',true);
11266
    }
11267
    return out;
11268
}
11269
function add_rels(rels, rId, f, type, relobj) {
11270
    if(!relobj) relobj = {};
11271
    if(!rels['!id']) rels['!id'] = {};
11272
    relobj.Id = 'rId' + rId;
11273
    relobj.Type = type;
11274
    relobj.Target = f;
11275
    if(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId);
11276
    rels['!id'][relobj.Id] = relobj;
11277
    rels[('/' + relobj.Target).replace("//","/")] = relobj;
11278
}
11279
 
11280
function write_zip(wb, opts) {
11281
    if(wb && !wb.SSF) {
11282
        wb.SSF = SSF.get_table();
11283
    }
11284
    if(wb && wb.SSF) {
11285
        make_ssf(SSF); SSF.load_table(wb.SSF);
11286
        opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
11287
    }
11288
    opts.rels = {}; opts.wbrels = {};
11289
    opts.Strings = []; opts.Strings.Count = 0; opts.Strings.Unique = 0;
11290
    var wbext = opts.bookType == "xlsb" ? "bin" : "xml";
11291
    var ct = { workbooks: [], sheets: [], calcchains: [], themes: [], styles: [],
11292
        coreprops: [], extprops: [], custprops: [], strs:[], comments: [], vba: [],
11293
        TODO:[], rels:[], xmlns: "" };
11294
    fix_write_opts(opts = opts || {});
11295
    var zip = new jszip();
11296
    var f = "", rId = 0;
11297
 
11298
    opts.cellXfs = [];
11299
    get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}});
11300
 
11301
    f = "docProps/core.xml";
11302
    zip.file(f, write_core_props(wb.Props, opts));
11303
    ct.coreprops.push(f);
11304
    add_rels(opts.rels, 2, f, RELS.CORE_PROPS);
11305
 
11306
    f = "docProps/app.xml";
11307
    if(!wb.Props) wb.Props = {};
11308
    wb.Props.SheetNames = wb.SheetNames;
11309
    wb.Props.Worksheets = wb.SheetNames.length;
11310
    zip.file(f, write_ext_props(wb.Props, opts));
11311
    ct.extprops.push(f);
11312
    add_rels(opts.rels, 3, f, RELS.EXT_PROPS);
11313
 
11314
    if(wb.Custprops !== wb.Props && keys(wb.Custprops||{}).length > 0) {
11315
        f = "docProps/custom.xml";
11316
        zip.file(f, write_cust_props(wb.Custprops, opts));
11317
        ct.custprops.push(f);
11318
        add_rels(opts.rels, 4, f, RELS.CUST_PROPS);
11319
    }
11320
 
11321
    f = "xl/workbook." + wbext;
11322
    zip.file(f, write_wb(wb, f, opts));
11323
    ct.workbooks.push(f);
11324
    add_rels(opts.rels, 1, f, RELS.WB);
11325
 
11326
    for(rId=1;rId <= wb.SheetNames.length; ++rId) {
11327
        f = "xl/worksheets/sheet" + rId + "." + wbext;
11328
        zip.file(f, write_ws(rId-1, f, opts, wb));
11329
        ct.sheets.push(f);
11330
        add_rels(opts.wbrels, rId, "worksheets/sheet" + rId + "." + wbext, RELS.WS);
11331
    }
11332
 
11333
    if(opts.Strings != null && opts.Strings.length > 0) {
11334
        f = "xl/sharedStrings." + wbext;
11335
        zip.file(f, write_sst(opts.Strings, f, opts));
11336
        ct.strs.push(f);
11337
        add_rels(opts.wbrels, ++rId, "sharedStrings." + wbext, RELS.SST);
11338
    }
11339
 
11340
    /* TODO: something more intelligent with themes */
11341
 
11342
    f = "xl/theme/theme1.xml";
11343
    zip.file(f, write_theme());
11344
    ct.themes.push(f);
11345
    add_rels(opts.wbrels, ++rId, "theme/theme1.xml", RELS.THEME);
11346
 
11347
    /* TODO: something more intelligent with styles */
11348
 
11349
    f = "xl/styles." + wbext;
11350
    zip.file(f, write_sty(wb, f, opts));
11351
    ct.styles.push(f);
11352
    add_rels(opts.wbrels, ++rId, "styles." + wbext, RELS.STY);
11353
 
11354
    zip.file("[Content_Types].xml", write_ct(ct, opts));
11355
    zip.file('_rels/.rels', write_rels(opts.rels));
11356
    zip.file('xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));
11357
    return zip;
11358
}
11359
function firstbyte(f,o) {
11360
    switch((o||{}).type || "base64") {
11361
        case 'buffer': return f[0];
11362
        case 'base64': return Base64.decode(f.substr(0,12)).charCodeAt(0);
11363
        case 'binary': return f.charCodeAt(0);
11364
        case 'array': return f[0];
11365
        default: throw new Error("Unrecognized type " + o.type);
11366
    }
11367
}
11368
 
11369
function read_zip(data, opts) {
11370
    var zip, d = data;
11371
    var o = opts||{};
11372
    if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
11373
    switch(o.type) {
11374
        case "base64": zip = new jszip(d, { base64:true }); break;
11375
        case "binary": case "array": zip = new jszip(d, { base64:false }); break;
11376
        case "buffer": zip = new jszip(d); break;
11377
        case "file": zip=new jszip(d=_fs.readFileSync(data)); break;
11378
        default: throw new Error("Unrecognized type " + o.type);
11379
    }
11380
    return parse_zip(zip, o);
11381
}
11382
 
11383
function readSync(data, opts) {
11384
    var zip, d = data, isfile = false, n;
11385
    var o = opts||{};
11386
    if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
11387
    if(o.type == "file") { isfile = true; o.type = "buffer"; d = _fs.readFileSync(data); }
11388
    switch((n = firstbyte(d, o))) {
11389
        case 0xD0:
11390
            if(isfile) o.type = "file";
11391
            return parse_xlscfb(CFB.read(data, o), o);
11392
        case 0x09: return parse_xlscfb(s2a(o.type === 'base64' ? Base64.decode(data) : data), o);
11393
        case 0x3C: return parse_xlml(d, o);
11394
        case 0x50:
11395
            if(isfile) o.type = "file";
11396
            return read_zip(data, opts);
11397
        default: throw new Error("Unsupported file " + n);
11398
    }
11399
}
11400
 
11401
function readFileSync(data, opts) {
11402
    var o = opts||{}; o.type = 'file';
11403
    return readSync(data, o);
11404
}
11405
function write_zip_type(wb, opts) {
11406
    var o = opts||{};
11407
    var z = write_zip(wb, o);
11408
    switch(o.type) {
11409
        case "base64": return z.generate({type:"base64"});
11410
        case "binary": return z.generate({type:"string"});
11411
        case "buffer": return z.generate({type:"nodebuffer"});
11412
        case "file": return _fs.writeFileSync(o.file, z.generate({type:"nodebuffer"}));
11413
        default: throw new Error("Unrecognized type " + o.type);
11414
    }
11415
}
11416
 
11417
function writeSync(wb, opts) {
11418
    var o = opts||{};
11419
    switch(o.bookType) {
11420
        case 'xml': return write_xlml(wb, o);
11421
        default: return write_zip_type(wb, o);
11422
    }
11423
}
11424
 
11425
function writeFileSync(wb, filename, opts) {
11426
    var o = opts||{}; o.type = 'file';
11427
    o.file = filename;
11428
    switch(o.file.substr(-5).toLowerCase()) {
11429
        case '.xlsx': o.bookType = 'xlsx'; break;
11430
        case '.xlsm': o.bookType = 'xlsm'; break;
11431
        case '.xlsb': o.bookType = 'xlsb'; break;
11432
    default: switch(o.file.substr(-4).toLowerCase()) {
11433
        case '.xls': o.bookType = 'xls'; break;
11434
        case '.xml': o.bookType = 'xml'; break;
11435
    }}
11436
    return writeSync(wb, o);
11437
}
11438
 
11439
function decode_row(rowstr) { return parseInt(unfix_row(rowstr),10) - 1; }
11440
function encode_row(row) { return "" + (row + 1); }
11441
function fix_row(cstr) { return cstr.replace(/([A-Z]|^)(\d+)$/,"$1$$$2"); }
11442
function unfix_row(cstr) { return cstr.replace(/\$(\d+)$/,"$1"); }
11443
 
11444
function decode_col(colstr) { var c = unfix_col(colstr), d = 0, i = 0; for(; i !== c.length; ++i) d = 26*d + c.charCodeAt(i) - 64; return d - 1; }
11445
function encode_col(col) { var s=""; for(++col; col; col=Math.floor((col-1)/26)) s = String.fromCharCode(((col-1)%26) + 65) + s; return s; }
11446
function fix_col(cstr) { return cstr.replace(/^([A-Z])/,"$$$1"); }
11447
function unfix_col(cstr) { return cstr.replace(/^\$([A-Z])/,"$1"); }
11448
 
11449
function split_cell(cstr) { return cstr.replace(/(\$?[A-Z]*)(\$?\d*)/,"$1,$2").split(","); }
11450
function decode_cell(cstr) { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; }
11451
function encode_cell(cell) { return encode_col(cell.c) + encode_row(cell.r); }
11452
function fix_cell(cstr) { return fix_col(fix_row(cstr)); }
11453
function unfix_cell(cstr) { return unfix_col(unfix_row(cstr)); }
11454
function decode_range(range) { var x =range.split(":").map(decode_cell); return {s:x[0],e:x[x.length-1]}; }
11455
function encode_range(cs,ce) {
11456
    if(ce === undefined || typeof ce === 'number') return encode_range(cs.s, cs.e);
11457
    if(typeof cs !== 'string') cs = encode_cell(cs); if(typeof ce !== 'string') ce = encode_cell(ce);
11458
    return cs == ce ? cs : cs + ":" + ce;
11459
}
11460
 
11461
function safe_decode_range(range) {
11462
    var o = {s:{c:0,r:0},e:{c:0,r:0}};
11463
    var idx = 0, i = 0, cc = 0;
11464
    var len = range.length;
11465
    for(idx = 0; i < len; ++i) {
11466
        if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
11467
        idx = 26*idx + cc;
11468
    }
11469
    o.s.c = --idx;
11470
 
11471
    for(idx = 0; i < len; ++i) {
11472
        if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
11473
        idx = 10*idx + cc;
11474
    }
11475
    o.s.r = --idx;
11476
 
11477
    if(i === len || range.charCodeAt(++i) === 58) { o.e.c=o.s.c; o.e.r=o.s.r; return o; }
11478
 
11479
    for(idx = 0; i != len; ++i) {
11480
        if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
11481
        idx = 26*idx + cc;
11482
    }
11483
    o.e.c = --idx;
11484
 
11485
    for(idx = 0; i != len; ++i) {
11486
        if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
11487
        idx = 10*idx + cc;
11488
    }
11489
    o.e.r = --idx;
11490
    return o;
11491
}
11492
 
11493
function safe_format_cell(cell, v) {
11494
    if(cell.z !== undefined) try { return (cell.w = SSF.format(cell.z, v)); } catch(e) { }
11495
    if(!cell.XF) return v;
11496
    try { return (cell.w = SSF.format(cell.XF.ifmt||0, v)); } catch(e) { return ''+v; }
11497
}
11498
 
11499
function format_cell(cell, v) {
11500
    if(cell == null || cell.t == null) return "";
11501
    if(cell.w !== undefined) return cell.w;
11502
    if(v === undefined) return safe_format_cell(cell, cell.v);
11503
    return safe_format_cell(cell, v);
11504
}
11505
 
11506
function sheet_to_json(sheet, opts){
11507
    var val, row, range, header = 0, offset = 1, r, hdr = [], isempty, R, C, v;
11508
    var o = opts != null ? opts : {};
11509
    var raw = o.raw;
11510
    if(sheet == null || sheet["!ref"] == null) return [];
11511
    range = o.range !== undefined ? o.range : sheet["!ref"];
11512
    if(o.header === 1) header = 1;
11513
    else if(o.header === "A") header = 2;
11514
    else if(Array.isArray(o.header)) header = 3;
11515
    switch(typeof range) {
11516
        case 'string': r = safe_decode_range(range); break;
11517
        case 'number': r = safe_decode_range(sheet["!ref"]); r.s.r = range; break;
11518
        default: r = range;
11519
    }
11520
    if(header > 0) offset = 0;
11521
    var rr = encode_row(r.s.r);
11522
    var cols = new Array(r.e.c-r.s.c+1);
11523
    var out = new Array(r.e.r-r.s.r-offset+1);
11524
    var outi = 0;
11525
    for(C = r.s.c; C <= r.e.c; ++C) {
11526
        cols[C] = encode_col(C);
11527
        val = sheet[cols[C] + rr];
11528
        switch(header) {
11529
            case 1: hdr[C] = C; break;
11530
            case 2: hdr[C] = cols[C]; break;
11531
            case 3: hdr[C] = o.header[C - r.s.c]; break;
11532
            default:
11533
                if(val === undefined) continue;
11534
                hdr[C] = format_cell(val);
11535
        }
11536
    }
11537
 
11538
    for (R = r.s.r + offset; R <= r.e.r; ++R) {
11539
        rr = encode_row(R);
11540
        isempty = true;
11541
        if(header === 1) row = [];
11542
        else {
11543
            row = {};
11544
            if(Object.defineProperty) Object.defineProperty(row, '__rowNum__', {value:R, enumerable:false});
11545
            else row.__rowNum__ = R;
11546
        }
11547
        for (C = r.s.c; C <= r.e.c; ++C) {
11548
            val = sheet[cols[C] + rr];
11549
            if(val === undefined || val.t === undefined) continue;
11550
            v = val.v;
11551
            switch(val.t){
11552
                case 'e': continue;
11553
                case 's': break;
11554
                case 'b': case 'n': break;
11555
                default: throw 'unrecognized type ' + val.t;
11556
            }
11557
            if(v !== undefined) {
11558
                row[hdr[C]] = raw ? v : format_cell(val,v);
11559
                isempty = false;
11560
            }
11561
        }
11562
        if(isempty === false || header === 1) out[outi++] = row;
11563
    }
11564
    out.length = outi;
11565
    return out;
11566
}
11567
 
11568
function sheet_to_row_object_array(sheet, opts) { return sheet_to_json(sheet, opts != null ? opts : {}); }
11569
 
11570
function sheet_to_csv(sheet, opts) {
11571
    var out = "", txt = "", qreg = /"/g;
11572
    var o = opts == null ? {} : opts;
11573
    if(sheet == null || sheet["!ref"] == null) return "";
11574
    var r = safe_decode_range(sheet["!ref"]);
11575
    var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
11576
    var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
11577
    var row = "", rr = "", cols = [];
11578
    var i = 0, cc = 0, val;
11579
    var R = 0, C = 0;
11580
    for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C);
11581
    for(R = r.s.r; R <= r.e.r; ++R) {
11582
        row = "";
11583
        rr = encode_row(R);
11584
        for(C = r.s.c; C <= r.e.c; ++C) {
11585
            val = sheet[cols[C] + rr];
11586
            txt = val !== undefined ? ''+format_cell(val) : "";
11587
            for(i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {
11588
                txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
11589
            row += (C === r.s.c ? "" : FS) + txt;
11590
        }
11591
        out += row + RS;
11592
    }
11593
    return out;
11594
}
11595
var make_csv = sheet_to_csv;
11596
 
11597
function sheet_to_formulae(sheet) {
11598
    var cmds, y = "", x, val="";
11599
    if(sheet == null || sheet["!ref"] == null) return "";
11600
    var r = safe_decode_range(sheet['!ref']), rr = "", cols = [], C;
11601
    cmds = new Array((r.e.r-r.s.r+1)*(r.e.c-r.s.c+1));
11602
    var i = 0;
11603
    for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C);
11604
    for(var R = r.s.r; R <= r.e.r; ++R) {
11605
        rr = encode_row(R);
11606
        for(C = r.s.c; C <= r.e.c; ++C) {
11607
            y = cols[C] + rr;
11608
            x = sheet[y];
11609
            val = "";
11610
            if(x === undefined) continue;
11611
            if(x.f != null) val = x.f;
11612
            else if(x.w !== undefined) val = "'" + x.w;
11613
            else if(x.v === undefined) continue;
11614
            else val = ""+x.v;
11615
            cmds[i++] = y + "=" + val;
11616
        }
11617
    }
11618
    cmds.length = i;
11619
    return cmds;
11620
}
11621
 
11622
var utils = {
11623
    encode_col: encode_col,
11624
    encode_row: encode_row,
11625
    encode_cell: encode_cell,
11626
    encode_range: encode_range,
11627
    decode_col: decode_col,
11628
    decode_row: decode_row,
11629
    split_cell: split_cell,
11630
    decode_cell: decode_cell,
11631
    decode_range: decode_range,
11632
    format_cell: format_cell,
11633
    get_formulae: sheet_to_formulae,
11634
    make_csv: sheet_to_csv,
11635
    make_json: sheet_to_json,
11636
    make_formulae: sheet_to_formulae,
11637
    sheet_to_csv: sheet_to_csv,
11638
    sheet_to_json: sheet_to_json,
11639
    sheet_to_formulae: sheet_to_formulae,
11640
    sheet_to_row_object_array: sheet_to_row_object_array
11641
};
11642
XLSX.parse_xlscfb = parse_xlscfb;
11643
XLSX.parse_zip = parse_zip;
11644
XLSX.read = readSync; //xlsread
11645
XLSX.readFile = readFileSync; //readFile
11646
XLSX.readFileSync = readFileSync;
11647
XLSX.write = writeSync;
11648
XLSX.writeFile = writeFileSync;
11649
XLSX.writeFileSync = writeFileSync;
11650
XLSX.utils = utils;
11651
XLSX.CFB = CFB;
11652
XLSX.SSF = SSF;
11653
})(typeof exports !== 'undefined' ? exports : XLSX);
11654
var XLS = XLSX;