js-xls-rails 0.5.0 → 0.6.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/js-xls-rails/version.rb +1 -1
- data/vendor/assets/javascripts/xls.js +414 -304
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92c7ac66d0955c7a92d4aaea434b283a4fac8171
|
4
|
+
data.tar.gz: 3a053528aeb1d0fca9665a906a8201dd23895db2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1967ca1d89c011d4677adb481e93382c06510124d239c67e55e8f30289a806d5806b649be57a566d7d175ce9b56f820e10da71a096624a62d214d71b343b79c4
|
7
|
+
data.tar.gz: f4f7741e282d3bd7446f6f64ee314a0e9cdc7dcc81bb43dc5c892034295a0fa34bb5d4fa3572ae3243e175e90633b00f2512f7d89b428ed8e8379eaf3a2fe5b0
|
data/lib/js-xls-rails/version.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
/* xls.js (C) 2013 SheetJS -- http://sheetjs.com */
|
1
|
+
/* xls.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
|
2
2
|
/* vim: set ts=2: */
|
3
3
|
/*jshint eqnull:true, funcscope:true */
|
4
4
|
var XLS = {};
|
5
5
|
(function(XLS){
|
6
|
+
XLS.version = '0.6.9';
|
6
7
|
if(typeof module !== "undefined" && typeof require !== 'undefined') {
|
7
8
|
if(typeof cptable === 'undefined') var cptable = require('codepage');
|
8
9
|
var current_codepage = 1252, current_cptable = cptable[1252];
|
@@ -12,41 +13,8 @@ function reset_cp() {
|
|
12
13
|
}
|
13
14
|
function _getchar(x) { return String.fromCharCode(x); }
|
14
15
|
|
15
|
-
/* Buffer.concat was added in the 0.8 series, so this is for older versions */
|
16
|
-
if(typeof Buffer !== "undefined" && !Buffer.concat)
|
17
|
-
Buffer.concat = function(list, length) {
|
18
|
-
if (!Array.isArray(list)) {
|
19
|
-
throw new TypeError('Usage: Buffer.concat(list, [length])');
|
20
|
-
}
|
21
|
-
|
22
|
-
if (list.length === 0) {
|
23
|
-
return new Buffer(0);
|
24
|
-
} else if (list.length === 1) {
|
25
|
-
return list[0];
|
26
|
-
}
|
27
|
-
var i, buf;
|
28
|
-
if (typeof length !== 'number') {
|
29
|
-
length = 0;
|
30
|
-
for (i = 0; i < list.length; i++) {
|
31
|
-
buf = list[i];
|
32
|
-
length += buf.length;
|
33
|
-
}
|
34
|
-
}
|
35
|
-
|
36
|
-
var buffer = new Buffer(length);
|
37
|
-
var pos = 0;
|
38
|
-
for (i = 0; i < list.length; i++) {
|
39
|
-
buf = list[i];
|
40
|
-
buf.copy(buffer, pos);
|
41
|
-
pos += buf.length;
|
42
|
-
}
|
43
|
-
return buffer;
|
44
|
-
};
|
45
|
-
|
46
|
-
var Buffers = Array;
|
47
|
-
|
48
16
|
function readIEEE754(buf, idx, isLE, nl, ml) {
|
49
|
-
if(isLE === undefined) isLE = true;
|
17
|
+
if(typeof isLE === 'undefined') isLE = true;
|
50
18
|
if(!nl) nl = 8;
|
51
19
|
if(!ml && nl === 8) ml = 52;
|
52
20
|
var e, m, el = nl * 8 - ml - 1, eMax = (1 << el) - 1, eBias = eMax >> 1;
|
@@ -111,6 +79,7 @@ function s2a(s) {
|
|
111
79
|
return w;
|
112
80
|
}
|
113
81
|
|
82
|
+
var __toBuffer;
|
114
83
|
if(typeof Buffer !== "undefined") {
|
115
84
|
Buffer.prototype.hexlify= function() { return this.toString('hex'); };
|
116
85
|
Buffer.prototype.utf16le= function(s,e){return this.toString('utf16le',s,e).replace(/\u0000/,'').replace(/[\u0001-\u0006]/,'!');};
|
@@ -122,7 +91,6 @@ if(typeof Buffer !== "undefined") {
|
|
122
91
|
if(len === 0) return "";
|
123
92
|
if(typeof current_cptable === "undefined") return this.utf8(i+4,i+4+len-1);
|
124
93
|
var t = Array(this.slice(i+4,i+4+len-1));
|
125
|
-
//1console.log("start", this.l, len, t);
|
126
94
|
var c, j = i+4, o = "", cc;
|
127
95
|
for(;j!=i+4+len;++j) {
|
128
96
|
c = this.readUInt8(j);
|
@@ -134,27 +102,33 @@ if(typeof Buffer !== "undefined") {
|
|
134
102
|
if(typeof cc === 'undefined') throw "Unrecognized character " + c.toString(16);
|
135
103
|
if(c === 0) break;
|
136
104
|
o += cc;
|
137
|
-
//1console.log(cc, cc.charCodeAt(0), o, this.l);
|
138
105
|
}
|
139
106
|
return o;
|
140
107
|
};
|
108
|
+
__toBuffer = function(bufs) { return Buffer.concat(bufs[0]); };
|
109
|
+
} else {
|
110
|
+
__toBuffer = function(bufs) {
|
111
|
+
var x = [];
|
112
|
+
for(var i = 0; i != bufs[0].length; ++i) { x = x.concat(bufs[0][i]); }
|
113
|
+
return x;
|
114
|
+
};
|
141
115
|
}
|
142
116
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
117
|
+
var __readUInt8 = function(b, idx) { return b.readUInt8 ? b.readUInt8(idx) : b[idx]; };
|
118
|
+
var __readUInt16LE = function(b, idx) { return b.readUInt16LE ? b.readUInt16LE(idx) : b[idx+1]*(1<<8)+b[idx]; };
|
119
|
+
var __readInt16LE = function(b, idx) { var u = __readUInt16LE(b,idx); if(!(u & 0x8000)) return u; return (0xffff - u + 1) * -1; };
|
120
|
+
var __readUInt32LE = function(b, idx) { return b.readUInt32LE ? b.readUInt32LE(idx) : b[idx+3]*(1<<24)+b[idx+2]*(1<<16)+b[idx+1]*(1<<8)+b[idx]; };
|
121
|
+
var __readInt32LE = function(b, idx) { if(b.readInt32LE) return b.readInt32LE(idx); var u = __readUInt32LE(b,idx); if(!(u & 0x80000000)) return u; return (0xffffffff - u + 1) * -1; };
|
122
|
+
var __readDoubleLE = function(b, idx) { return b.readDoubleLE ? b.readDoubleLE(idx) : readIEEE754(b, idx||0);};
|
149
123
|
|
150
|
-
|
124
|
+
var __hexlify = function(b) { return b.map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); };
|
151
125
|
|
152
|
-
|
126
|
+
var __utf16le = function(b,s,e) { if(b.utf16le) return b.utf16le(s,e); var str = ""; for(var i=s; i<e; i+=2) str += String.fromCharCode(__readUInt16LE(b,i)); return str.replace(/\u0000/,'').replace(/[\u0001-\u0006]/,'!'); };
|
153
127
|
|
154
|
-
|
128
|
+
var __utf8 = function(b,s,e) { if(b.utf8) return b.utf8(s,e); var str = ""; for(var i=s; i<e; i++) str += String.fromCharCode(__readUInt8(b,i)); return str; };
|
155
129
|
|
156
|
-
|
157
|
-
|
130
|
+
var __lpstr = function(b,i) { if(b.lpstr) return b.lpstr(i); var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
|
131
|
+
var __lpwstr = function(b,i) { if(b.lpwstr) return b.lpwstr(i); var len = 2*__readUInt32LE(b,i); return __utf8(b, i+4,i+4+len-1);};
|
158
132
|
|
159
133
|
function bconcat(bufs) { return (typeof Buffer !== 'undefined') ? Buffer.concat(bufs) : [].concat.apply([], bufs); }
|
160
134
|
|
@@ -162,69 +136,64 @@ function ReadShift(size, t) {
|
|
162
136
|
var o, w, vv, i, loc; t = t || 'u';
|
163
137
|
if(size === 'ieee754') { size = 8; t = 'f'; }
|
164
138
|
switch(size) {
|
165
|
-
case 1: o =
|
166
|
-
case 2: o=t==='u'?
|
167
|
-
case 4: o =
|
168
|
-
case 8: if(t === 'f') { o =
|
139
|
+
case 1: o = __readUInt8(this, this.l); break;
|
140
|
+
case 2: o=(t==='u' ? __readUInt16LE : __readInt16LE)(this, this.l); break;
|
141
|
+
case 4: o = __readUInt32LE(this, this.l); break;
|
142
|
+
case 8: if(t === 'f') { o = __readDoubleLE(this, this.l); break; }
|
169
143
|
/* falls through */
|
170
144
|
case 16: o = this.toString('hex', this.l,this.l+size); break;
|
171
145
|
|
172
|
-
case 'utf8': size = t; o =
|
173
|
-
case 'utf16le': size
|
146
|
+
case 'utf8': size = t; o = __utf8(this, this.l, this.l + size); break;
|
147
|
+
case 'utf16le': size=2*t; o = __utf16le(this, this.l, this.l + size); break;
|
174
148
|
|
175
149
|
/* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */
|
176
|
-
case 'lpstr': o =
|
150
|
+
case 'lpstr': o = __lpstr(this, this.l); size = 5 + o.length; break;
|
177
151
|
|
178
|
-
case 'lpwstr': o =
|
152
|
+
case 'lpwstr': o = __lpwstr(this, this.l); size = 5 + o.length; if(o[o.length-1] == '\u0000') size += 2; break;
|
179
153
|
|
180
154
|
/* sbcs and dbcs support continue records in the SST way TODO codepages */
|
181
155
|
/* TODO: DBCS http://msdn.microsoft.com/en-us/library/cc194788.aspx */
|
182
156
|
case 'dbcs': size = 2*t; o = ""; loc = this.l;
|
183
157
|
for(i = 0; i != t; ++i) {
|
184
158
|
if(this.lens && this.lens.indexOf(loc) !== -1) {
|
185
|
-
w = this
|
159
|
+
w = __readUInt8(this, loc);
|
186
160
|
this.l = loc + 1;
|
187
161
|
vv = ReadShift.call(this, w ? 'dbcs' : 'sbcs', t-i);
|
188
162
|
return o + vv;
|
189
163
|
}
|
190
|
-
o += _getchar(this
|
164
|
+
o += _getchar(__readUInt16LE(this, loc));
|
191
165
|
loc+=2;
|
192
166
|
} break;
|
193
167
|
|
194
168
|
case 'sbcs': size = t; o = ""; loc = this.l;
|
195
169
|
for(i = 0; i != t; ++i) {
|
196
170
|
if(this.lens && this.lens.indexOf(loc) !== -1) {
|
197
|
-
w = this
|
171
|
+
w = __readUInt8(this, loc);
|
198
172
|
this.l = loc + 1;
|
199
173
|
vv = ReadShift.call(this, w ? 'dbcs' : 'sbcs', t-i);
|
200
174
|
return o + vv;
|
201
175
|
}
|
202
|
-
o += _getchar(this
|
176
|
+
o += _getchar(__readUInt8(this, loc));
|
203
177
|
loc+=1;
|
204
178
|
} break;
|
205
179
|
|
206
180
|
case 'cstr': size = 0; o = "";
|
207
|
-
while((w=
|
181
|
+
while((w=__readUInt8(this, this.l + size++))!==0) o+= _getchar(w);
|
208
182
|
break;
|
209
183
|
case 'wstr': size = 0; o = "";
|
210
|
-
while((w=
|
184
|
+
while((w=__readUInt16LE(this,this.l +size))!==0){o+= _getchar(w);size+=2;}
|
211
185
|
size+=2; break;
|
212
186
|
}
|
213
187
|
this.l+=size; return o;
|
214
188
|
}
|
215
189
|
|
216
190
|
function CheckField(hexstr, fld) {
|
217
|
-
var
|
191
|
+
var b = this.slice(this.l, this.l+hexstr.length/2);
|
192
|
+
var m = b.hexlify ? b.hexlify() : __hexlify(b);
|
218
193
|
if(m !== hexstr) throw (fld||"") + 'Expected ' + hexstr + ' saw ' + m;
|
219
194
|
this.l += hexstr.length/2;
|
220
195
|
}
|
221
196
|
|
222
|
-
function WarnField(hexstr, fld) {
|
223
|
-
var m = this.slice(this.l, this.l+hexstr.length/2).hexlify('hex');
|
224
|
-
if(m !== hexstr) console.error((fld||"") + 'Expected ' + hexstr +' saw ' + m);
|
225
|
-
this.l += hexstr.length/2;
|
226
|
-
}
|
227
|
-
|
228
197
|
function prep_blob(blob, pos) {
|
229
198
|
blob.read_shift = ReadShift.bind(blob);
|
230
199
|
blob.chk = CheckField;
|
@@ -233,14 +202,14 @@ function prep_blob(blob, pos) {
|
|
233
202
|
return [read, chk];
|
234
203
|
}
|
235
204
|
|
236
|
-
/* ssf.js (C) 2013 SheetJS -- http://sheetjs.com */
|
205
|
+
/* ssf.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
|
237
206
|
var SSF = {};
|
238
207
|
var make_ssf = function(SSF){
|
239
|
-
|
240
|
-
var _strrev = function(x) { return String(x).reverse(); };
|
208
|
+
var _strrev = function(x) { return String(x).split("").reverse().join("");};
|
241
209
|
function fill(c,l) { return new Array(l+1).join(c); }
|
242
210
|
function pad(v,d,c){var t=String(v);return t.length>=d?t:(fill(c||0,d-t.length)+t);}
|
243
211
|
function rpad(v,d,c){var t=String(v);return t.length>=d?t:(t+fill(c||0,d-t.length));}
|
212
|
+
SSF.version = '0.5.8';
|
244
213
|
/* Options */
|
245
214
|
var opts_fmt = {};
|
246
215
|
function fixopts(o){for(var y in opts_fmt) if(o[y]===undefined) o[y]=opts_fmt[y];}
|
@@ -249,6 +218,7 @@ opts_fmt.date1904 = 0;
|
|
249
218
|
opts_fmt.output = "";
|
250
219
|
opts_fmt.mode = "";
|
251
220
|
var table_fmt = {
|
221
|
+
0: 'General',
|
252
222
|
1: '0',
|
253
223
|
2: '0.00',
|
254
224
|
3: '#,##0',
|
@@ -275,7 +245,9 @@ var table_fmt = {
|
|
275
245
|
46: '[h]:mm:ss',
|
276
246
|
47: 'mmss.0',
|
277
247
|
48: '##0.0E+0',
|
278
|
-
49: '@'
|
248
|
+
49: '@',
|
249
|
+
56: '"上午/下午 "hh"時"mm"分"ss"秒 "',
|
250
|
+
65535: 'General'
|
279
251
|
};
|
280
252
|
var days = [
|
281
253
|
['Sun', 'Sunday'],
|
@@ -305,12 +277,12 @@ var frac = function frac(x, D, mixed) {
|
|
305
277
|
var B = x * sgn;
|
306
278
|
var P_2 = 0, P_1 = 1, P = 0;
|
307
279
|
var Q_2 = 1, Q_1 = 0, Q = 0;
|
308
|
-
var A = B
|
280
|
+
var A = Math.floor(B);
|
309
281
|
while(Q_1 < D) {
|
310
|
-
A = B
|
282
|
+
A = Math.floor(B);
|
311
283
|
P = A * P_1 + P_2;
|
312
284
|
Q = A * Q_1 + Q_2;
|
313
|
-
if((B - A) < 0.
|
285
|
+
if((B - A) < 0.0000000005) break;
|
314
286
|
B = 1 / (B - A);
|
315
287
|
P_2 = P_1; P_1 = P;
|
316
288
|
Q_2 = Q_1; Q_1 = Q;
|
@@ -318,6 +290,7 @@ var frac = function frac(x, D, mixed) {
|
|
318
290
|
if(Q > D) { Q = Q_1; P = P_1; }
|
319
291
|
if(Q > D) { Q = Q_2; P = P_2; }
|
320
292
|
if(!mixed) return [0, sgn * P, Q];
|
293
|
+
if(Q===0) throw "Unexpected state: "+P+" "+P_1+" "+P_2+" "+Q+" "+Q_1+" "+Q_2;
|
321
294
|
var q = Math.floor(sgn * P/Q);
|
322
295
|
return [q, sgn*P - q*Q, Q];
|
323
296
|
};
|
@@ -331,25 +304,26 @@ var general_fmt = function(v) {
|
|
331
304
|
else if(V >= 0.0001 && V < 0.001) o = v.toPrecision(6);
|
332
305
|
else if(V >= Math.pow(10,10) && V < Math.pow(10,11)) o = v.toFixed(10).substr(0,12);
|
333
306
|
else if(V > Math.pow(10,-9) && V < Math.pow(10,11)) {
|
334
|
-
o = v.toFixed(12).replace(/(\.[0-9]*[1-9])0*$/,"$1").replace(/\.$/,"");
|
307
|
+
o = v.toFixed(12).replace(/(\.[0-9]*[1-9])0*$/,"$1").replace(/\.$/,"");
|
335
308
|
if(o.length > 11+(v<0?1:0)) o = v.toPrecision(10);
|
336
309
|
if(o.length > 11+(v<0?1:0)) o = v.toExponential(5);
|
337
310
|
}
|
338
311
|
else {
|
339
312
|
o = v.toFixed(11).replace(/(\.[0-9]*[1-9])0*$/,"$1");
|
340
|
-
if(o.length > 11 + (v<0?1:0)) o = v.toPrecision(6);
|
313
|
+
if(o.length > 11 + (v<0?1:0)) o = v.toPrecision(6);
|
341
314
|
}
|
342
315
|
o = o.replace(/(\.[0-9]*[1-9])0+e/,"$1e").replace(/\.0*e/,"e");
|
343
316
|
return o.replace("e","E").replace(/\.0*$/,"").replace(/\.([0-9]*[^0])0*$/,".$1").replace(/(E[+-])([0-9])$/,"$1"+"0"+"$2");
|
344
317
|
}
|
345
318
|
if(typeof v === 'string') return v;
|
346
|
-
throw "unsupported value in General format: " + v;
|
319
|
+
throw new Error("unsupported value in General format: " + v);
|
347
320
|
};
|
348
321
|
SSF._general = general_fmt;
|
349
322
|
var parse_date_code = function parse_date_code(v,opts) {
|
350
|
-
var date = Math.floor(v), time = Math.
|
323
|
+
var date = Math.floor(v), time = Math.floor(86400 * (v - date)+1e-6), dow=0;
|
351
324
|
var dout=[], out={D:date, T:time, u:86400*(v-date)-time}; fixopts(opts = (opts||{}));
|
352
325
|
if(opts.date1904) date += 1462;
|
326
|
+
if(date > 2958465) return null;
|
353
327
|
if(date === 60) {dout = [1900,2,29]; dow=3;}
|
354
328
|
else if(date === 0) {dout = [1900,1,0]; dow=6;}
|
355
329
|
else {
|
@@ -359,7 +333,7 @@ var parse_date_code = function parse_date_code(v,opts) {
|
|
359
333
|
d.setDate(d.getDate() + date - 1);
|
360
334
|
dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
|
361
335
|
dow = d.getDay();
|
362
|
-
if(opts.mode === 'excel' && date < 60) dow = (dow + 6) % 7;
|
336
|
+
if(/* opts.mode === 'excel' && */ date < 60) dow = (dow + 6) % 7;
|
363
337
|
}
|
364
338
|
out.y = dout[0]; out.m = dout[1]; out.d = dout[2];
|
365
339
|
out.S = time % 60; time = Math.floor(time / 60);
|
@@ -369,61 +343,63 @@ var parse_date_code = function parse_date_code(v,opts) {
|
|
369
343
|
return out;
|
370
344
|
};
|
371
345
|
SSF.parse_date_code = parse_date_code;
|
346
|
+
/*jshint -W086 */
|
372
347
|
var write_date = function(type, fmt, val) {
|
373
348
|
if(val < 0) return "";
|
349
|
+
var o;
|
374
350
|
switch(type) {
|
375
351
|
case 'y': switch(fmt) { /* year */
|
376
352
|
case 'y': case 'yy': return pad(val.y % 100,2);
|
377
|
-
default: return val.y;
|
378
|
-
}
|
353
|
+
default: return pad(val.y % 10000,4);
|
354
|
+
}
|
379
355
|
case 'm': switch(fmt) { /* month */
|
380
356
|
case 'm': return val.m;
|
381
357
|
case 'mm': return pad(val.m,2);
|
382
358
|
case 'mmm': return months[val.m-1][1];
|
383
|
-
case 'mmmm': return months[val.m-1][2];
|
384
359
|
case 'mmmmm': return months[val.m-1][0];
|
385
|
-
default:
|
386
|
-
}
|
360
|
+
default: return months[val.m-1][2];
|
361
|
+
}
|
387
362
|
case 'd': switch(fmt) { /* day */
|
388
363
|
case 'd': return val.d;
|
389
364
|
case 'dd': return pad(val.d,2);
|
390
365
|
case 'ddd': return days[val.q][0];
|
391
|
-
|
392
|
-
|
393
|
-
} break;
|
366
|
+
default: return days[val.q][1];
|
367
|
+
}
|
394
368
|
case 'h': switch(fmt) { /* 12-hour */
|
395
369
|
case 'h': return 1+(val.H+11)%12;
|
396
370
|
case 'hh': return pad(1+(val.H+11)%12, 2);
|
397
371
|
default: throw 'bad hour format: ' + fmt;
|
398
|
-
}
|
372
|
+
}
|
399
373
|
case 'H': switch(fmt) { /* 24-hour */
|
400
374
|
case 'h': return val.H;
|
401
375
|
case 'hh': return pad(val.H, 2);
|
402
376
|
default: throw 'bad hour format: ' + fmt;
|
403
|
-
}
|
377
|
+
}
|
404
378
|
case 'M': switch(fmt) { /* minutes */
|
405
379
|
case 'm': return val.M;
|
406
380
|
case 'mm': return pad(val.M, 2);
|
407
381
|
default: throw 'bad minute format: ' + fmt;
|
408
|
-
}
|
382
|
+
}
|
409
383
|
case 's': switch(fmt) { /* seconds */
|
410
|
-
case 's': return val.S;
|
411
|
-
case 'ss': return pad(val.S, 2);
|
412
|
-
case 'ss.0':
|
384
|
+
case 's': return Math.round(val.S+val.u);
|
385
|
+
case 'ss': return pad(Math.round(val.S+val.u), 2);
|
386
|
+
case 'ss.0': o = pad(Math.round(10*(val.S+val.u)),3); return o.substr(0,2)+"." + o.substr(2);
|
387
|
+
case 'ss.00': o = pad(Math.round(100*(val.S+val.u)),4); return o.substr(0,2)+"." + o.substr(2);
|
388
|
+
case 'ss.000': o = pad(Math.round(1000*(val.S+val.u)),5); return o.substr(0,2)+"." + o.substr(2);
|
413
389
|
default: throw 'bad second format: ' + fmt;
|
414
|
-
}
|
390
|
+
}
|
415
391
|
case 'Z': switch(fmt) {
|
416
|
-
case '[h]':
|
392
|
+
case '[h]': case '[hh]': o = val.D*24+val.H; break;
|
393
|
+
case '[m]': case '[mm]': o = (val.D*24+val.H)*60+val.M; break;
|
394
|
+
case '[s]': case '[ss]': o = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
|
417
395
|
default: throw 'bad abstime format: ' + fmt;
|
418
|
-
}
|
396
|
+
} return fmt.length === 3 ? o : pad(o, 2);
|
419
397
|
/* TODO: handle the ECMA spec format ee -> yy */
|
420
398
|
case 'e': { return val.y; } break;
|
421
|
-
case 'A': return (val.h>=12 ? 'P' : 'A') + fmt.substr(1);
|
422
|
-
default: throw 'bad format type ' + type + ' in ' + fmt;
|
423
399
|
}
|
424
400
|
};
|
425
|
-
|
426
|
-
var commaify = function(s) { return s
|
401
|
+
/*jshint +W086 */
|
402
|
+
var commaify = function(s) { return _strrev(_strrev(s).replace(/.../g,"$&,")).replace(/^,/,""); };
|
427
403
|
var write_num = function(type, fmt, val) {
|
428
404
|
if(type === '(') {
|
429
405
|
var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
|
@@ -435,37 +411,60 @@ var write_num = function(type, fmt, val) {
|
|
435
411
|
if(mul !== 0) return write_num(type, fmt, val * Math.pow(10,2*mul)) + fill("%",mul);
|
436
412
|
if(fmt.indexOf("E") > -1) {
|
437
413
|
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
|
438
|
-
if(fmt
|
439
|
-
var
|
440
|
-
|
414
|
+
if(fmt.match(/^#+0.0E\+0$/)) {
|
415
|
+
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
|
416
|
+
var ee = (Number(val.toExponential(0).substr(2+(val<0))))%period;
|
417
|
+
if(ee < 0) ee += period;
|
418
|
+
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
|
419
|
+
if(!o.match(/[Ee]/)) {
|
420
|
+
var fakee = (Number(val.toExponential(0).substr(2+(val<0))));
|
421
|
+
if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
|
422
|
+
else o += "E+" + (fakee - ee);
|
423
|
+
while(o.substr(0,2) === "0.") {
|
424
|
+
o = o[0] + o.substr(2,period) + "." + o.substr(2+period);
|
425
|
+
o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0.");
|
426
|
+
}
|
427
|
+
o = o.replace(/\+-/,"-");
|
428
|
+
}
|
429
|
+
o = o.replace(/^([+-]?)([0-9]*)\.([0-9]*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
|
441
430
|
} else o = val.toExponential(idx);
|
442
431
|
if(fmt.match(/E\+00$/) && o.match(/e[+-][0-9]$/)) o = o.substr(0,o.length-1) + "0" + o[o.length-1];
|
443
432
|
if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
|
444
433
|
return o.replace("e","E");
|
445
434
|
}
|
446
435
|
if(fmt[0] === "$") return "$"+write_num(type,fmt.substr(fmt[1]==' '?2:1),val);
|
447
|
-
var r, ff, aval = val < 0 ? -val : val, sign = val < 0 ? "-" : "";
|
448
|
-
if((r = fmt.match(/# (\?+) \/ (\d+)/))) {
|
449
|
-
var den = Number(r[
|
436
|
+
var r, rr, ff, aval = val < 0 ? -val : val, sign = val < 0 ? "-" : "";
|
437
|
+
if((r = fmt.match(/# (\?+)([ ]?)\/([ ]?)(\d+)/))) {
|
438
|
+
var den = Number(r[4]), rnd = Math.round(aval * den), base = Math.floor(rnd/den);
|
450
439
|
var myn = (rnd - base*den), myd = den;
|
451
|
-
return sign + (base?base:"") + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[
|
440
|
+
return sign + (base?base:"") + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad(myn,r[1].length," ") + r[2] + "/" + r[3] + pad(myd,r[4].length));
|
441
|
+
}
|
442
|
+
if(fmt.match(/^#+0+$/)) fmt = fmt.replace(/#/g,"");
|
443
|
+
if(fmt.match(/^00+$/)) return (val<0?"-":"")+pad(Math.round(aval),fmt.length);
|
444
|
+
if(fmt.match(/^[#?]+$/)) return String(Math.round(val)).replace(/^0$/,"");
|
445
|
+
if((r = fmt.match(/^#*0+\.(0+)/))) {
|
446
|
+
o = Math.round(val * Math.pow(10,r[1].length));
|
447
|
+
return String(o/Math.pow(10,r[1].length)).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.([0-9]*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
|
448
|
+
}
|
449
|
+
if((r = fmt.match(/^(0*)\.(#*)$/))) {
|
450
|
+
o = Math.round(val*Math.pow(10,r[2].length));
|
451
|
+
return String(o * Math.pow(10,-r[2].length)).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^([-]?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
|
452
|
+
}
|
453
|
+
if((r = fmt.match(/^#,##0([.]?)$/))) return sign + commaify(String(Math.round(aval)));
|
454
|
+
if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
|
455
|
+
rr = Math.round((val-Math.floor(val))*Math.pow(10,r[1].length));
|
456
|
+
return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + pad(rr,r[1].length,0);
|
457
|
+
}
|
458
|
+
if((r = fmt.match(/^# ([?]+)([ ]?)\/([ ]?)([?]+)/))) {
|
459
|
+
rr = Math.min(Math.max(r[1].length, r[4].length),7);
|
460
|
+
ff = frac(aval, Math.pow(10,rr)-1, true);
|
461
|
+
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad(ff[1],rr," ") + r[2] + "/" + r[3] + rpad(ff[2],rr," "): fill(" ", 2*rr+1 + r[2].length + r[3].length));
|
452
462
|
}
|
453
|
-
if(fmt.match(/^00*$/)) return (val<0?"-":"")+pad(Math.round(Math.abs(val)), fmt.length);
|
454
|
-
if(fmt.match(/^####*$/)) return "dafuq";
|
455
463
|
switch(fmt) {
|
456
|
-
case "0": return Math.round(val);
|
457
|
-
case "
|
458
|
-
return String(o/
|
459
|
-
case "
|
460
|
-
return String(o/100).replace(/^([^\.]+)$/,"$1.00").replace(/\.$/,".00").replace(/\.([0-9])$/,".$1"+"0");
|
461
|
-
case "0.000": o = Math.round(val*1000);
|
462
|
-
return String(o/1000).replace(/^([^\.]+)$/,"$1.000").replace(/\.$/,".000").replace(/\.([0-9])$/,".$1"+"00").replace(/\.([0-9][0-9])$/,".$1"+"0");
|
463
|
-
case "#,##0": return sign + commaify(String(Math.round(aval)));
|
464
|
-
case "#,##0.0": r = Math.round((val-Math.floor(val))*10); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + r;
|
465
|
-
case "#,##0.00": r = Math.round((val-Math.floor(val))*100); return val < 0 ? "-" + write_num(type, fmt, -val) : commaify(String(Math.floor(val))) + "." + (r < 10 ? "0"+r:r);
|
466
|
-
case "# ? / ?": ff = frac(aval, 9, true); return sign + (ff[0]||"") + " " + (ff[1] === 0 ? " " : ff[1] + "/" + ff[2]);
|
467
|
-
case "# ?? / ??": ff = frac(aval, 99, true); return sign + (ff[0]||"") + " " + (ff[1] ? pad(ff[1],2," ") + "/" + rpad(ff[2],2," ") : " ");
|
468
|
-
case "# ??? / ???": ff = frac(aval, 999, true); return sign + (ff[0]||"") + " " + (ff[1] ? pad(ff[1],3," ") + "/" + rpad(ff[2],3," ") : " ");
|
464
|
+
case "0": case "#0": return Math.round(val);
|
465
|
+
case "#.##": o = Math.round(val*100);
|
466
|
+
return String(o/100).replace(/^([^\.]+)$/,"$1.").replace(/^0\.$/,".");
|
467
|
+
case "#,###": var x = commaify(String(Math.round(aval))); return x !== "0" ? sign + x : "";
|
469
468
|
default:
|
470
469
|
}
|
471
470
|
throw new Error("unsupported format |" + fmt + "|");
|
@@ -482,7 +481,7 @@ function split_fmt(fmt) {
|
|
482
481
|
j = i+1;
|
483
482
|
}
|
484
483
|
out.push(fmt.slice(j));
|
485
|
-
if(in_str !=-1) throw "Format |" + fmt + "| unterminated string at " + in_str;
|
484
|
+
if(in_str !=-1) throw new Error("Format |" + fmt + "| unterminated string at " + in_str);
|
486
485
|
return out;
|
487
486
|
}
|
488
487
|
SSF._split = split_fmt;
|
@@ -493,6 +492,10 @@ function eval_fmt(fmt, v, opts, flen) {
|
|
493
492
|
/* Tokenize */
|
494
493
|
while(i < fmt.length) {
|
495
494
|
switch((c = fmt[i])) {
|
495
|
+
case 'G': /* General */
|
496
|
+
if(fmt.substr(i, i+6).toLowerCase() !== "general")
|
497
|
+
throw new Error('unrecognized character ' + fmt[i] + ' in ' +fmt);
|
498
|
+
out.push({t:'G',v:'General'}); i+=7; break;
|
496
499
|
case '"': /* Literal text */
|
497
500
|
for(o="";fmt[++i] !== '"' && i < fmt.length;) o += fmt[i];
|
498
501
|
out.push({t:'t', v:o}); ++i; break;
|
@@ -502,28 +505,39 @@ function eval_fmt(fmt, v, opts, flen) {
|
|
502
505
|
case '@': /* Text Placeholder */
|
503
506
|
out.push({t:'T', v:v}); ++i; break;
|
504
507
|
/* Dates */
|
508
|
+
case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
|
509
|
+
c = c.toLowerCase();
|
510
|
+
/* falls through */
|
505
511
|
case 'm': case 'd': case 'y': case 'h': case 's': case 'e':
|
506
512
|
if(v < 0) return "";
|
507
513
|
if(!dt) dt = parse_date_code(v, opts);
|
508
|
-
|
514
|
+
if(!dt) return "";
|
515
|
+
o = fmt[i]; while((fmt[++i]||"").toLowerCase() === c) o+=c;
|
509
516
|
if(c === 's' && fmt[i] === '.' && fmt[i+1] === '0') { o+='.'; while(fmt[++i] === '0') o+= '0'; }
|
510
517
|
if(c === 'm' && lst.toLowerCase() === 'h') c = 'M'; /* m = minute */
|
511
518
|
if(c === 'h') c = hr;
|
519
|
+
o = o.toLowerCase();
|
512
520
|
q={t:c, v:o}; out.push(q); lst = c; break;
|
513
521
|
case 'A':
|
514
522
|
if(!dt) dt = parse_date_code(v, opts);
|
523
|
+
if(!dt) return "";
|
515
524
|
q={t:c,v:"A"};
|
516
525
|
if(fmt.substr(i, 3) === "A/P") {q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;}
|
517
526
|
else if(fmt.substr(i,5) === "AM/PM") { q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; }
|
518
|
-
else q.t = "t";
|
527
|
+
else { q.t = "t"; i++; }
|
519
528
|
out.push(q); lst = c; break;
|
520
529
|
case '[': /* TODO: Fix this -- ignore all conditionals and formatting */
|
521
530
|
o = c;
|
522
|
-
while(fmt[i++] !== ']') o += fmt[i];
|
523
|
-
if(o
|
531
|
+
while(fmt[i++] !== ']' && i < fmt.length) o += fmt[i];
|
532
|
+
if(o.substr(-1) !== ']') throw 'unterminated "[" block: |' + o + '|';
|
533
|
+
if(o.match(/\[[HhMmSs]*\]/)) {
|
534
|
+
if(!dt) dt = parse_date_code(v, opts);
|
535
|
+
if(!dt) return "";
|
536
|
+
out.push({t:'Z', v:o.toLowerCase()});
|
537
|
+
} else { o=""; }
|
524
538
|
break;
|
525
539
|
/* Numbers */
|
526
|
-
case '0': case '#':
|
540
|
+
case '0': case '#': case '.':
|
527
541
|
o = c; while("0#?.,E+-%".indexOf(c=fmt[++i]) > -1) o += c;
|
528
542
|
out.push({t:'n', v:o}); break;
|
529
543
|
case '?':
|
@@ -536,7 +550,7 @@ function eval_fmt(fmt, v, opts, flen) {
|
|
536
550
|
out.push({t:'D', v:o}); break;
|
537
551
|
case ' ': out.push({t:c,v:c}); ++i; break;
|
538
552
|
default:
|
539
|
-
if("
|
553
|
+
if(",$-+/():!^&'~{}<>=€".indexOf(c) === -1)
|
540
554
|
throw 'unrecognized character ' + fmt[i] + ' in ' + fmt;
|
541
555
|
out.push({t:'t', v:c}); ++i; break;
|
542
556
|
}
|
@@ -554,45 +568,48 @@ function eval_fmt(fmt, v, opts, flen) {
|
|
554
568
|
/* replace fields */
|
555
569
|
for(i=0; i < out.length; ++i) {
|
556
570
|
switch(out[i].t) {
|
557
|
-
case 't': case 'T': case ' ': break;
|
558
|
-
case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case '
|
571
|
+
case 't': case 'T': case ' ': case 'D': break;
|
572
|
+
case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'Z':
|
559
573
|
out[i].v = write_date(out[i].t, out[i].v, dt);
|
560
574
|
out[i].t = 't'; break;
|
561
|
-
case 'n': case '(':
|
575
|
+
case 'n': case '(': case '?':
|
562
576
|
var jj = i+1;
|
563
|
-
while(out[jj] && ("?
|
564
|
-
|
577
|
+
while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (" t".indexOf(out[jj].t) > -1 && "?t".indexOf((out[jj+1]||{}).t)>-1 && (out[jj+1].t == '?' || out[jj+1].v == '/')) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || '$€'.indexOf(out[jj].v) > -1 || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) {
|
578
|
+
out[i].v += out[jj].v;
|
565
579
|
delete out[jj]; ++jj;
|
566
580
|
}
|
567
|
-
out[i].v = write_num(out[i].t, out[i].v, v);
|
581
|
+
out[i].v = write_num(out[i].t, out[i].v, (flen >1 && v < 0 && i>0 && out[i-1].v == "-" ? -v:v));
|
568
582
|
out[i].t = 't';
|
569
|
-
i = jj; break;
|
570
|
-
|
583
|
+
i = jj-1; break;
|
584
|
+
case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
|
571
585
|
}
|
572
586
|
}
|
573
|
-
|
574
587
|
return out.map(function(x){return x.v;}).join("");
|
575
588
|
}
|
576
589
|
SSF._eval = eval_fmt;
|
577
590
|
function choose_fmt(fmt, v, o) {
|
578
|
-
if(typeof fmt === 'number') fmt = table_fmt[fmt];
|
591
|
+
if(typeof fmt === 'number') fmt = ((o&&o.table) ? o.table : table_fmt)[fmt];
|
579
592
|
if(typeof fmt === "string") fmt = split_fmt(fmt);
|
580
593
|
var l = fmt.length;
|
594
|
+
if(l<4 && fmt[l-1].indexOf("@")>-1) --l;
|
581
595
|
switch(fmt.length) {
|
582
|
-
case 1: fmt = [fmt[0], fmt[0], fmt[0], "@"]; break;
|
583
|
-
case 2: fmt = [fmt[0], fmt[fmt[1]
|
596
|
+
case 1: fmt = fmt[0].indexOf("@")>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
|
597
|
+
case 2: fmt = fmt[1].indexOf("@")>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
|
598
|
+
case 3: fmt = fmt[2].indexOf("@")>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
|
584
599
|
case 4: break;
|
585
600
|
default: throw "cannot find right format for |" + fmt + "|";
|
586
601
|
}
|
587
602
|
if(typeof v !== "number") return [fmt.length, fmt[3]];
|
588
603
|
return [l, v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2]];
|
589
604
|
}
|
590
|
-
|
591
605
|
var format = function format(fmt,v,o) {
|
592
606
|
fixopts(o = (o||{}));
|
593
|
-
if(fmt ===
|
594
|
-
if(typeof fmt === 'number') fmt = table_fmt[fmt];
|
607
|
+
if(typeof fmt === "string" && fmt.toLowerCase() === "general") return general_fmt(v, o);
|
608
|
+
if(typeof fmt === 'number') fmt = (o.table || table_fmt)[fmt];
|
595
609
|
var f = choose_fmt(fmt, v, o);
|
610
|
+
if(f[1].toLowerCase() === "general") return general_fmt(v,o);
|
611
|
+
if(v === true) v = "TRUE"; if(v === false) v = "FALSE";
|
612
|
+
if(v === "" || typeof v === "undefined") return "";
|
596
613
|
return eval_fmt(f[1], v, o, f[0]);
|
597
614
|
};
|
598
615
|
|
@@ -600,6 +617,8 @@ SSF._choose = choose_fmt;
|
|
600
617
|
SSF._table = table_fmt;
|
601
618
|
SSF.load = function(fmt, idx) { table_fmt[idx] = fmt; };
|
602
619
|
SSF.format = format;
|
620
|
+
SSF.get_table = function() { return table_fmt; };
|
621
|
+
SSF.load_table = function(tbl) { for(var i=0; i!=0x0188; ++i) if(tbl[i]) SSF.load(tbl[i], i); };
|
603
622
|
};
|
604
623
|
make_ssf(SSF);
|
605
624
|
/* [MS-OLEPS] v20130118 */
|
@@ -746,7 +765,7 @@ function parse_VtStringBase(blob, stringType, pad) {
|
|
746
765
|
else return parse_VtStringBase(blob, blob.read_shift(2), pad);
|
747
766
|
}
|
748
767
|
|
749
|
-
function parse_VtString(blob, t, pad) { return parse_VtStringBase(blob, t, 4); }
|
768
|
+
function parse_VtString(blob, t, pad) { return parse_VtStringBase(blob, t, pad === false ? null : 4); }
|
750
769
|
function parse_VtUnalignedString(blob, t) { if(!t) throw new Error("dafuq?"); return parse_VtStringBase(blob, t, 0); }
|
751
770
|
|
752
771
|
/* [MS-OSHARED] 2.3.3.1.9 VtVecUnalignedLpstrValue */
|
@@ -802,7 +821,7 @@ function parse_dictionary(blob,CodePage) {
|
|
802
821
|
function parse_BLOB(blob) {
|
803
822
|
var size = blob.read_shift(4);
|
804
823
|
var bytes = blob.slice(blob.l,blob.l+size);
|
805
|
-
if(
|
824
|
+
if(size % 4 > 0) blob.l += (4 - (size % 4)) % 4;
|
806
825
|
return bytes;
|
807
826
|
}
|
808
827
|
|
@@ -828,14 +847,14 @@ function parse_VtVector(blob, cb) {
|
|
828
847
|
}
|
829
848
|
|
830
849
|
/* [MS-OLEPS] 2.15 TypedPropertyValue */
|
831
|
-
function parse_TypedPropertyValue(blob, type) {
|
850
|
+
function parse_TypedPropertyValue(blob, type, _opts) {
|
832
851
|
var read = ReadShift.bind(blob), chk = CheckField.bind(blob);
|
833
|
-
var t = read(2), ret;
|
852
|
+
var t = read(2), ret, opts = _opts||{};
|
834
853
|
read(2);
|
835
854
|
if(type !== VT_VARIANT)
|
836
855
|
if(t !== type && VT_CUSTOM.indexOf(type)===-1) throw new Error('Expected type ' + type + ' saw ' + t);
|
837
856
|
switch(type === VT_VARIANT ? t : type) {
|
838
|
-
case VT_I2: ret = read(2, 'i'); read(2); return ret;
|
857
|
+
case VT_I2: ret = read(2, 'i'); if(!opts.raw) read(2); return ret;
|
839
858
|
case VT_I4: ret = read(4, 'i'); return ret;
|
840
859
|
case VT_BOOL: return read(4) !== 0x0;
|
841
860
|
case VT_UI4: ret = read(4); return ret;
|
@@ -844,7 +863,7 @@ function parse_TypedPropertyValue(blob, type) {
|
|
844
863
|
case VT_FILETIME: return parse_FILETIME(blob);
|
845
864
|
case VT_BLOB: return parse_BLOB(blob);
|
846
865
|
case VT_CF: return parse_ClipboardData(blob);
|
847
|
-
case VT_STRING: return parse_VtString(blob, t, 4).replace(/\u0000/g,'');
|
866
|
+
case VT_STRING: return parse_VtString(blob, t, !opts.raw && 4).replace(/\u0000/g,'');
|
848
867
|
case VT_USTR: return parse_VtUnalignedString(blob, t, 4).replace(/\u0000/g,'');
|
849
868
|
case VT_VECTOR | VT_VARIANT: return parse_VtVecHeadingPair(blob);
|
850
869
|
case VT_VECTOR | VT_LPSTR: return parse_VtVecUnalignedLpstr(blob);
|
@@ -880,16 +899,25 @@ function parse_PropertySet(blob, PIDSI) {
|
|
880
899
|
var PropH = {};
|
881
900
|
for(i = 0; i != NumProps; ++i) {
|
882
901
|
if(blob.l !== Props[i][1]) {
|
883
|
-
|
902
|
+
var fail = true;
|
903
|
+
if(i>0 && PIDSI) switch(PIDSI[Props[i-1][0]].t) {
|
904
|
+
case VT_I2: if(blob.l +2 === Props[i][1]) { blob.l+=2; fail = false; } break;
|
905
|
+
case VT_STRING: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
|
906
|
+
case VT_VECTOR | VT_VARIANT: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
|
907
|
+
}
|
908
|
+
if(!PIDSI && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; }
|
909
|
+
if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i);
|
884
910
|
}
|
885
911
|
if(PIDSI) {
|
886
912
|
var piddsi = PIDSI[Props[i][0]];
|
887
|
-
PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t);
|
913
|
+
PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true});
|
888
914
|
if(piddsi.n == "CodePage") switch(PropH[piddsi.n]) {
|
889
915
|
/* TODO: Generate files under every codepage */
|
890
916
|
case 10000: break; // OSX Roman
|
891
917
|
case 1252: break; // Windows Latin
|
892
918
|
|
919
|
+
case 0: PropH[piddsi.n] = 1252; break; // Unknown -> default
|
920
|
+
|
893
921
|
case 874: // SB Windows Thai
|
894
922
|
case 1250: // SB Windows Central Europe
|
895
923
|
case 1251: // SB Windows Cyrillic
|
@@ -971,14 +999,16 @@ function parse_PropertySetStream(file, PIDSI) {
|
|
971
999
|
rval.FMTID = FMTID0;
|
972
1000
|
//rval.PSet0 = PSet0;
|
973
1001
|
if(NumSets === 1) return rval;
|
974
|
-
|
1002
|
+
if(blob.l !== Offset1) throw "Length mismatch 2: " + blob.l + " !== " + Offset1;
|
1003
|
+
var PSet1;
|
1004
|
+
try { PSet1 = parse_PropertySet(blob, null); } catch(e) { }
|
975
1005
|
for(y in PSet1) rval[y] = PSet1[y];
|
976
1006
|
rval.FMTID = [FMTID0, FMTID1]; // TODO: verify FMTID0/1
|
977
1007
|
return rval;
|
978
1008
|
}
|
979
1009
|
/* [MS-CFB] v20130118 */
|
980
|
-
if(typeof module !== "undefined" && typeof require !== 'undefined') CFB = require('cfb');
|
981
|
-
else var CFB = (function(){
|
1010
|
+
/*if(typeof module !== "undefined" && typeof require !== 'undefined') CFB = require('cfb');
|
1011
|
+
else*/ var CFB = (function(){
|
982
1012
|
var exports = {};
|
983
1013
|
function parse(file) {
|
984
1014
|
|
@@ -1004,7 +1034,6 @@ var fat_addrs = []; // locations of FAT sectors
|
|
1004
1034
|
var blob = file.slice(0,512);
|
1005
1035
|
prep_blob(blob);
|
1006
1036
|
var read = ReadShift.bind(blob), chk = CheckField.bind(blob);
|
1007
|
-
//var wrn = WarnField.bind(blob);
|
1008
1037
|
var j = 0, q;
|
1009
1038
|
|
1010
1039
|
// header signature 8
|
@@ -1014,7 +1043,6 @@ chk(HEADER_SIGNATURE, 'Header Signature: ');
|
|
1014
1043
|
chk(HEADER_CLSID, 'CLSID: ');
|
1015
1044
|
|
1016
1045
|
// minor version 2
|
1017
|
-
//wrn(HEADER_MINOR_VERSION, 'Minor Version: ');
|
1018
1046
|
read(2);
|
1019
1047
|
|
1020
1048
|
// major version 3
|
@@ -1100,10 +1128,10 @@ function sleuth_fat(idx, cnt) {
|
|
1100
1128
|
if(idx !== FREESECT) {
|
1101
1129
|
var sector = sectors[idx];
|
1102
1130
|
for(var i = 0; i != ssz/4-1; ++i) {
|
1103
|
-
if((q = sector
|
1131
|
+
if((q = __readUInt32LE(sector,i*4)) === ENDOFCHAIN) break;
|
1104
1132
|
fat_addrs.push(q);
|
1105
1133
|
}
|
1106
|
-
sleuth_fat(sector
|
1134
|
+
sleuth_fat(__readUInt32LE(sector,ssz-4),cnt - 1);
|
1107
1135
|
}
|
1108
1136
|
}
|
1109
1137
|
sleuth_fat(difat_start, ndfs);
|
@@ -1117,7 +1145,7 @@ function get_buffer(byte_addr, bytes) {
|
|
1117
1145
|
}
|
1118
1146
|
|
1119
1147
|
function get_buffer_u32(byte_addr) {
|
1120
|
-
return get_buffer(byte_addr,4)
|
1148
|
+
return __readUInt32LE(get_buffer(byte_addr,4), 0);
|
1121
1149
|
}
|
1122
1150
|
|
1123
1151
|
function get_next_sector(idx) { return get_buffer_u32(idx); }
|
@@ -1130,7 +1158,7 @@ for(i=0; i != sectors.length; ++i) {
|
|
1130
1158
|
if(chkd[k]) continue;
|
1131
1159
|
for(j=k; j<=MAXREGSECT; buf.push(j),j=get_next_sector(j)) chkd[j] = true;
|
1132
1160
|
sector_list[k] = {nodes: buf};
|
1133
|
-
sector_list[k].data =
|
1161
|
+
sector_list[k].data = __toBuffer(Array(buf.map(get_sector)));
|
1134
1162
|
}
|
1135
1163
|
sector_list[dir_start].name = "!Directory";
|
1136
1164
|
if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
|
@@ -1147,7 +1175,7 @@ function read_directory(idx) {
|
|
1147
1175
|
read = ReadShift.bind(blob);
|
1148
1176
|
var namelen = read(2);
|
1149
1177
|
if(namelen === 0) return;
|
1150
|
-
var name = blob
|
1178
|
+
var name = __utf16le(blob,0,namelen-(Paths.length?2:0)); // OLE
|
1151
1179
|
Paths.push(name);
|
1152
1180
|
var o = { name: name };
|
1153
1181
|
o.type = EntryTypes[read(1)];
|
@@ -1181,12 +1209,12 @@ function read_directory(idx) {
|
|
1181
1209
|
}
|
1182
1210
|
if(o.ctime) {
|
1183
1211
|
var ct = blob.slice(blob.l-24, blob.l-16);
|
1184
|
-
var c2 = (ct
|
1212
|
+
var c2 = (__readUInt32LE(ct,4)/1e7)*Math.pow(2,32)+__readUInt32LE(ct,0)/1e7;
|
1185
1213
|
o.ct = new Date((c2 - 11644473600)*1000);
|
1186
1214
|
}
|
1187
1215
|
if(o.mtime) {
|
1188
1216
|
var mt = blob.slice(blob.l-16, blob.l-8);
|
1189
|
-
var m2 = (mt
|
1217
|
+
var m2 = (__readUInt32LE(mt,4)/1e7)*Math.pow(2,32)+__readUInt32LE(mt,0)/1e7;
|
1190
1218
|
o.mt = new Date((m2 - 11644473600)*1000);
|
1191
1219
|
}
|
1192
1220
|
files[name] = o;
|
@@ -1248,16 +1276,16 @@ var rval = {
|
|
1248
1276
|
find: find_path
|
1249
1277
|
};
|
1250
1278
|
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1279
|
+
for(var name in files) {
|
1280
|
+
switch(name) {
|
1281
|
+
/* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
|
1282
|
+
case '!DocumentSummaryInformation':
|
1283
|
+
try { rval.DocSummary = parse_PropertySetStream(files[name], DocSummaryPIDDSI); } catch(e) { } break;
|
1284
|
+
/* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
|
1285
|
+
case '!SummaryInformation':
|
1286
|
+
try { rval.Summary = parse_PropertySetStream(files[name], SummaryPIDSI); } catch(e) { } break;
|
1287
|
+
}
|
1288
|
+
}
|
1261
1289
|
|
1262
1290
|
return rval;
|
1263
1291
|
} // parse
|
@@ -1304,10 +1332,6 @@ return exports;
|
|
1304
1332
|
}
|
1305
1333
|
|
1306
1334
|
if(typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
1307
|
-
Buffers = Array;
|
1308
|
-
Buffers.prototype.toBuffer = function() {
|
1309
|
-
return Buffer.concat(this[0]);
|
1310
|
-
};
|
1311
1335
|
var fs = require('fs');
|
1312
1336
|
//exports.read = CFB.read;
|
1313
1337
|
//exports.parse = CFB.parse;
|
@@ -1319,13 +1343,6 @@ if(typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
|
1319
1343
|
};
|
1320
1344
|
if(typeof module !== 'undefined' && require.main === module)
|
1321
1345
|
exports.main(process.argv.slice(2));
|
1322
|
-
} else {
|
1323
|
-
Buffers = Array;
|
1324
|
-
Buffers.prototype.toBuffer = function() {
|
1325
|
-
var x = [];
|
1326
|
-
for(var i = 0; i != this[0].length; ++i) { x = x.concat(this[0][i]); }
|
1327
|
-
return x;
|
1328
|
-
};
|
1329
1346
|
}
|
1330
1347
|
|
1331
1348
|
/* sections refer to MS-XLS unless otherwise stated */
|
@@ -1382,13 +1399,16 @@ function parse_XLUnicodeRichExtendedString(blob) {
|
|
1382
1399
|
var fHighByte = flags & 0x1, fExtSt = flags & 0x4, fRichSt = flags & 0x8;
|
1383
1400
|
var width = 1 + (flags & 0x1); // 0x0 -> utf8, 0x1 -> dbcs
|
1384
1401
|
var cRun, cbExtRst;
|
1402
|
+
var z = {};
|
1385
1403
|
if(fRichSt) cRun = read_shift(2);
|
1386
1404
|
if(fExtSt) cbExtRst = read_shift(4);
|
1387
1405
|
var encoding = (flags & 0x1) ? 'dbcs' : 'sbcs';
|
1388
1406
|
var msg = cch === 0 ? "" : read_shift(encoding, cch);
|
1389
1407
|
if(fRichSt) blob.l += 4 * cRun; //TODO: parse this
|
1390
1408
|
if(fExtSt) blob.l += cbExtRst; //TODO: parse this
|
1391
|
-
|
1409
|
+
z.t = msg;
|
1410
|
+
if(!fRichSt) { z.raw = "<t>" + z.t + "</t>"; z.r = z.t; }
|
1411
|
+
return z;
|
1392
1412
|
}
|
1393
1413
|
|
1394
1414
|
/* 2.5.296 XLUnicodeStringNoCch */
|
@@ -1396,7 +1416,7 @@ function parse_XLUnicodeStringNoCch(blob, cch) {
|
|
1396
1416
|
var read = blob.read_shift.bind(blob);
|
1397
1417
|
var fHighByte = read(1);
|
1398
1418
|
var retval;
|
1399
|
-
if(fHighByte===0) { retval =
|
1419
|
+
if(fHighByte===0) { retval = __utf8(blob,blob.l, blob.l+cch); blob.l += cch; }
|
1400
1420
|
else { retval = blob.read_shift('dbcs', cch); }
|
1401
1421
|
return retval;
|
1402
1422
|
}
|
@@ -1451,7 +1471,7 @@ function parse_RkNumber(blob) {
|
|
1451
1471
|
var fX100 = b[0] & 1, fInt = b[0] & 2;
|
1452
1472
|
blob.l+=4;
|
1453
1473
|
b[0] &= ~3;
|
1454
|
-
var RK = fInt === 0 ? [0,0,0,0,b[0],b[1],b[2],b[3]]
|
1474
|
+
var RK = fInt === 0 ? __readDoubleLE([0,0,0,0,b[0],b[1],b[2],b[3]],0) : __readInt32LE(b,0)>>2;
|
1455
1475
|
return fX100 ? RK/100 : RK;
|
1456
1476
|
}
|
1457
1477
|
|
@@ -1628,6 +1648,14 @@ function parse_LabelSst(blob, length) {
|
|
1628
1648
|
return cell;
|
1629
1649
|
}
|
1630
1650
|
|
1651
|
+
/* 2.4.148 */
|
1652
|
+
function parse_Label(blob, length) {
|
1653
|
+
var cell = parse_Cell(blob, 6);
|
1654
|
+
var str = parse_XLUnicodeString(blob, length-6);
|
1655
|
+
cell.val = str;
|
1656
|
+
return cell;
|
1657
|
+
}
|
1658
|
+
|
1631
1659
|
/* 2.4.126 Number Formats */
|
1632
1660
|
function parse_Format(blob, length) {
|
1633
1661
|
var ifmt = blob.read_shift(2);
|
@@ -1674,7 +1702,7 @@ function parse_XF(blob, length) {
|
|
1674
1702
|
o.ifnt = read(2); o.ifmt = read(2); o.flags = read(2);
|
1675
1703
|
o.fStyle = (o.flags >> 2) & 0x01;
|
1676
1704
|
length -= 6;
|
1677
|
-
o.data = o.fStyle ? parse_StyleXF(blob, length) : parse_CellXF(blob, length);
|
1705
|
+
o.data = o.fStyle ? parse_StyleXF(blob, length) : parse_CellXF(blob, length);
|
1678
1706
|
return o;
|
1679
1707
|
}
|
1680
1708
|
|
@@ -1734,7 +1762,7 @@ function parse_ExternName(blob, length, opts) {
|
|
1734
1762
|
};
|
1735
1763
|
if(opts.sbcch === 0x3A01) body = parse_AddinUdf(blob, length-2);
|
1736
1764
|
//else throw new Error("unsupported SupBook cch: " + opts.sbcch);
|
1737
|
-
o.body = blob.read_shift(length-2);
|
1765
|
+
o.body = body || blob.read_shift(length-2);
|
1738
1766
|
return o;
|
1739
1767
|
}
|
1740
1768
|
|
@@ -1792,6 +1820,21 @@ function parse_MTRSettings(blob, length) {
|
|
1792
1820
|
return [fMTREnabled, fUserSetThreadCount, cUserThreadCount];
|
1793
1821
|
}
|
1794
1822
|
|
1823
|
+
/* 2.5.186 */
|
1824
|
+
function parse_NoteSh(blob, length) {
|
1825
|
+
var row = blob.read_shift(2), col = blob.read_shift(2);
|
1826
|
+
var flags = blob.read_shift(2), idObj = blob.read_shift(2);
|
1827
|
+
var stAuthor = parse_XLUnicodeString(blob);
|
1828
|
+
blob.read_shift(1);
|
1829
|
+
return stAuthor;
|
1830
|
+
}
|
1831
|
+
|
1832
|
+
/* 2.4.179 */
|
1833
|
+
function parse_Note(blob, length) {
|
1834
|
+
/* TODO: Support revisions */
|
1835
|
+
return parse_NoteSh(blob, length);
|
1836
|
+
}
|
1837
|
+
|
1795
1838
|
var parse_Backup = parsebool; /* 2.4.14 */
|
1796
1839
|
var parse_Blank = parse_Cell; /* 2.4.20 Just the cell */
|
1797
1840
|
var parse_BottomMargin = parse_Xnum; /* 2.4.27 */
|
@@ -1847,7 +1890,6 @@ var parse_WriteProtect = parsenoop; /* 2.4.350 empty record */
|
|
1847
1890
|
/* ---- */
|
1848
1891
|
var parse_VerticalPageBreaks = parsenoop;
|
1849
1892
|
var parse_HorizontalPageBreaks = parsenoop;
|
1850
|
-
var parse_Note = parsenoop;
|
1851
1893
|
var parse_Selection = parsenoop;
|
1852
1894
|
var parse_Continue = parsenoop;
|
1853
1895
|
var parse_Pane = parsenoop;
|
@@ -1967,7 +2009,6 @@ var parse_CodeName = parse_XLUnicodeString;
|
|
1967
2009
|
var parse_SXFDBType = parsenoop;
|
1968
2010
|
var parse_ObNoMacros = parsenoop;
|
1969
2011
|
var parse_Dv = parsenoop;
|
1970
|
-
var parse_Label = parsenoop;
|
1971
2012
|
var parse_Index = parsenoop;
|
1972
2013
|
var parse_Table = parsenoop;
|
1973
2014
|
var parse_Window2 = parsenoop;
|
@@ -2292,8 +2333,8 @@ function parse_PtgArray(blob, length) {
|
|
2292
2333
|
|
2293
2334
|
/* 2.5.198.33 */
|
2294
2335
|
function parse_PtgAttrBaxcel(blob, length) {
|
2295
|
-
bitSemi = blob[blob.l+1] & 0x01; /* 1 = volatile */
|
2296
|
-
bitBaxcel = 1;
|
2336
|
+
var bitSemi = blob[blob.l+1] & 0x01; /* 1 = volatile */
|
2337
|
+
var bitBaxcel = 1;
|
2297
2338
|
blob.l += 4;
|
2298
2339
|
return [bitSemi, bitBaxcel];
|
2299
2340
|
}
|
@@ -2310,21 +2351,21 @@ function parse_PtgAttrChoose(blob, length) {
|
|
2310
2351
|
|
2311
2352
|
/* 2.5.198.35 */
|
2312
2353
|
function parse_PtgAttrGoto(blob, length) {
|
2313
|
-
bitGoto = (blob[blob.l+1] & 0xFF) ? 1 : 0;
|
2354
|
+
var bitGoto = (blob[blob.l+1] & 0xFF) ? 1 : 0;
|
2314
2355
|
blob.l += 2;
|
2315
2356
|
return [bitGoto, blob.read_shift(2)];
|
2316
2357
|
}
|
2317
2358
|
|
2318
2359
|
/* 2.5.198.36 */
|
2319
2360
|
function parse_PtgAttrIf(blob, length) {
|
2320
|
-
bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0;
|
2361
|
+
var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0;
|
2321
2362
|
blob.l += 2;
|
2322
2363
|
return [bitIf, blob.read_shift(2)];
|
2323
2364
|
}
|
2324
2365
|
|
2325
2366
|
/* 2.5.198.37 */
|
2326
2367
|
function parse_PtgAttrSemi(blob, length) {
|
2327
|
-
bitSemi = (blob[blob.l+1] & 0xFF) ? 1 : 0;
|
2368
|
+
var bitSemi = (blob[blob.l+1] & 0xFF) ? 1 : 0;
|
2328
2369
|
blob.l += 4;
|
2329
2370
|
return [bitSemi];
|
2330
2371
|
}
|
@@ -2654,7 +2695,7 @@ function parse_Formula(blob, length) {
|
|
2654
2695
|
/* 2.5.133 */
|
2655
2696
|
function parse_FormulaValue(blob) {
|
2656
2697
|
var b;
|
2657
|
-
if(
|
2698
|
+
if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return parse_Xnum(blob);
|
2658
2699
|
switch(blob[blob.l]) {
|
2659
2700
|
case 0x00: blob.l += 8; return "String";
|
2660
2701
|
case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return b;
|
@@ -4486,6 +4527,23 @@ var RecordEnum = {
|
|
4486
4527
|
0x0000: {}
|
4487
4528
|
};
|
4488
4529
|
|
4530
|
+
function fixopts(opts) {
|
4531
|
+
var defaults = [
|
4532
|
+
['cellNF', false], /* emit cell number format string as .z */
|
4533
|
+
['cellFormula', true], /* emit formulae as .f */
|
4534
|
+
|
4535
|
+
['sheetRows', 0, 'n'], /* read n rows (0 = read all rows) */
|
4536
|
+
|
4537
|
+
['bookSheets', false], /* only try to get sheet names (no Sheets) */
|
4538
|
+
['bookProps', false], /* only try to get properties (no Sheets) */
|
4539
|
+
|
4540
|
+
['WTF', false] /* WTF mode (throws errors) */
|
4541
|
+
];
|
4542
|
+
defaults.forEach(function(d) {
|
4543
|
+
if(typeof opts[d[0]] === 'undefined') opts[d[0]] = d[1];
|
4544
|
+
if(d[2] === 'n') opts[d[0]] = Number(opts[d[0]]);
|
4545
|
+
});
|
4546
|
+
}
|
4489
4547
|
/* [MS-OLEDS] 2.3.8 CompObjStream */
|
4490
4548
|
function parse_compobj(obj) {
|
4491
4549
|
var v = {};
|
@@ -4493,12 +4551,12 @@ function parse_compobj(obj) {
|
|
4493
4551
|
|
4494
4552
|
/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
|
4495
4553
|
var l = 28, m;
|
4496
|
-
m = o
|
4497
|
-
l += 4 + o
|
4554
|
+
m = __lpstr(o, l);
|
4555
|
+
l += 4 + __readUInt32LE(o,l);
|
4498
4556
|
v.UserType = m;
|
4499
4557
|
|
4500
4558
|
/* [MS-OLEDS] 2.3.1 ClipboardFormatOrAnsiString */
|
4501
|
-
m = o
|
4559
|
+
m = __readUInt32LE(o,l); l+= 4;
|
4502
4560
|
switch(m) {
|
4503
4561
|
case 0x00000000: break;
|
4504
4562
|
case 0xffffffff: case 0xfffffffe: l+=4; break;
|
@@ -4507,14 +4565,15 @@ function parse_compobj(obj) {
|
|
4507
4565
|
l += m;
|
4508
4566
|
}
|
4509
4567
|
|
4510
|
-
m = o
|
4568
|
+
m = __lpstr(o, l); l += m.length === 0 ? 0 : 5 + m.length; v.Reserved1 = m;
|
4511
4569
|
|
4512
|
-
if((m = o
|
4570
|
+
if((m = __readUInt32LE(o,l)) !== 0x71b2e9f4) return v;
|
4513
4571
|
throw "Unsupported Unicode Extension";
|
4514
4572
|
}
|
4515
4573
|
|
4516
|
-
|
4517
|
-
|
4574
|
+
function parse_xlscfb(cfb, options) {
|
4575
|
+
if(!options) options = {};
|
4576
|
+
fixopts(options);
|
4518
4577
|
reset_cp();
|
4519
4578
|
var CompObj = cfb.find('!CompObj');
|
4520
4579
|
var Summary = cfb.find('!SummaryInformation');
|
@@ -4529,12 +4588,12 @@ function slurp(R, blob, length, opts) {
|
|
4529
4588
|
var l = length;
|
4530
4589
|
var bufs = [blob.slice(blob.l,blob.l+l)];
|
4531
4590
|
blob.l += length;
|
4532
|
-
var next = (RecordEnum[
|
4591
|
+
var next = (RecordEnum[__readUInt16LE(blob,blob.l)]);
|
4533
4592
|
while(next && next.n === 'Continue') {
|
4534
|
-
l =
|
4593
|
+
l = __readUInt16LE(blob,blob.l+2);
|
4535
4594
|
bufs.push(blob.slice(blob.l+4,blob.l+4+l));
|
4536
4595
|
blob.l += 4+l;
|
4537
|
-
next = (RecordEnum[
|
4596
|
+
next = (RecordEnum[__readUInt16LE(blob, blob.l)]);
|
4538
4597
|
}
|
4539
4598
|
var b = bconcat(bufs);
|
4540
4599
|
prep_blob(b);
|
@@ -4544,7 +4603,7 @@ function slurp(R, blob, length, opts) {
|
|
4544
4603
|
}
|
4545
4604
|
|
4546
4605
|
// 2.3.2
|
4547
|
-
function parse_workbook(blob) {
|
4606
|
+
function parse_workbook(blob, options) {
|
4548
4607
|
var wb = {opts:{}};
|
4549
4608
|
var Sheets = {};
|
4550
4609
|
var out = [];
|
@@ -4560,11 +4619,13 @@ function parse_workbook(blob) {
|
|
4560
4619
|
var lastcell, last_cell;
|
4561
4620
|
var shared_formulae = {};
|
4562
4621
|
var temp_val;
|
4622
|
+
var cell_valid = true;
|
4563
4623
|
var XFs = []; /* XF records */
|
4564
|
-
function addline(cell, line) {
|
4624
|
+
function addline(cell, line, options) {
|
4565
4625
|
lastcell = cell;
|
4566
4626
|
last_cell = encode_cell(cell);
|
4567
|
-
|
4627
|
+
if(options.sheetRows && lastcell.r >= options.sheetRows) cell_valid = false;
|
4628
|
+
else out[last_cell] = line;
|
4568
4629
|
}
|
4569
4630
|
var opts = {
|
4570
4631
|
enc: false, // encrypted
|
@@ -4590,6 +4651,9 @@ function parse_workbook(blob) {
|
|
4590
4651
|
var length = (blob.l === blob.length ? 0 : read(2)), y;
|
4591
4652
|
var R = RecordEnum[RecordType];
|
4592
4653
|
if(R && R.f) {
|
4654
|
+
if(options.bookSheets) {
|
4655
|
+
if(last_Rn === 'BoundSheet8' && R.n !== 'BoundSheet8') break;
|
4656
|
+
}
|
4593
4657
|
last_Rn = R.n;
|
4594
4658
|
if(R.r === 2 || R.r == 12) {
|
4595
4659
|
var rt = read(2); length -= 2;
|
@@ -4745,39 +4809,72 @@ function parse_workbook(blob) {
|
|
4745
4809
|
} break;
|
4746
4810
|
case 'BOF': {
|
4747
4811
|
if(file_depth++) break;
|
4812
|
+
cell_valid = true;
|
4748
4813
|
out = {};
|
4749
4814
|
cur_sheet = (Directory[s] || {name:""}).name;
|
4750
4815
|
lst.push([R.n, s, val, Directory[s]]);
|
4751
4816
|
} break;
|
4752
4817
|
case 'Number': {
|
4753
4818
|
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:'n'};
|
4754
|
-
|
4819
|
+
if(temp_val.XF) try {
|
4820
|
+
temp_val.w=SSF.format(temp_val.XF.ifmt||0, temp_val.v);
|
4821
|
+
if(options.cellNF) temp_val.z = SSF._table[temp_val.XF.ifmt||0];
|
4822
|
+
} catch(e) { if(opts.WTF) throw e; }
|
4823
|
+
addline({c:val.c, r:val.r}, temp_val, options);
|
4755
4824
|
} break;
|
4756
4825
|
case 'BoolErr': {
|
4757
4826
|
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t};
|
4758
|
-
|
4827
|
+
if(temp_val.XF) try {
|
4828
|
+
temp_val.w=SSF.format(temp_val.XF.ifmt||0, temp_val.v);
|
4829
|
+
if(options.cellNF) temp_val.z = SSF._table[temp_val.XF.ifmt||0];
|
4830
|
+
} catch(e) { if(opts.WTF) throw e; }
|
4831
|
+
addline({c:val.c, r:val.r}, temp_val, options);
|
4759
4832
|
} break;
|
4760
4833
|
case 'RK': {
|
4761
|
-
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'};
|
4762
|
-
|
4834
|
+
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'};
|
4835
|
+
if(temp_val.XF) try {
|
4836
|
+
temp_val.w=SSF.format(temp_val.XF.ifmt||0, temp_val.v);
|
4837
|
+
if(options.cellNF) temp_val.z = SSF._table[temp_val.XF.ifmt||0];
|
4838
|
+
} catch(e) { if(opts.WTF) throw e; }
|
4839
|
+
addline({c:val.c, r:val.r}, temp_val, options);
|
4763
4840
|
} break;
|
4764
4841
|
case 'MulRk': {
|
4765
4842
|
for(var j = val.c; j <= val.C; ++j) {
|
4766
4843
|
var ixfe = val.rkrec[j-val.c][0];
|
4767
|
-
|
4844
|
+
temp_val= {ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'};
|
4845
|
+
if(temp_val.XF) try {
|
4846
|
+
temp_val.w=SSF.format(temp_val.XF.ifmt||0, temp_val.v);
|
4847
|
+
if(options.cellNF) temp_val.z = SSF._table[temp_val.XF.ifmt||0];
|
4848
|
+
} catch(e) { if(opts.WTF) throw e; }
|
4849
|
+
addline({c:j, r:val.r}, temp_val, options);
|
4768
4850
|
}
|
4769
4851
|
} break;
|
4770
4852
|
case 'Formula': {
|
4771
4853
|
switch(val.val) {
|
4772
4854
|
case 'String': last_formula = val; break;
|
4773
4855
|
case 'Array Formula': throw "Array Formula unsupported";
|
4774
|
-
default:
|
4856
|
+
default: // TODO: infer type from formula
|
4857
|
+
temp_val = {v:val.val, ixfe:val.cell.ixfe, t:'n'};
|
4858
|
+
temp_val.XF = XFs[temp_val.ixfe];
|
4859
|
+
if(options.cellFormula) temp_val.f = stringify_formula(val.formula,range,val.cell,supbooks);
|
4860
|
+
if(temp_val.XF) try {
|
4861
|
+
temp_val.w=SSF.format(temp_val.XF.ifmt||0, temp_val.v);
|
4862
|
+
if(options.cellNF) temp_val.z = SSF._table[temp_val.XF.ifmt||0];
|
4863
|
+
} catch(e) { if(opts.WTF) throw e; }
|
4864
|
+
addline(val.cell, temp_val, options);
|
4775
4865
|
}
|
4776
4866
|
} break;
|
4777
4867
|
case 'String': {
|
4778
4868
|
if(last_formula) {
|
4779
4869
|
last_formula.val = val;
|
4780
|
-
|
4870
|
+
temp_val = {v:last_formula.val, ixfe:last_formula.cell.ixfe, t:'s'};
|
4871
|
+
temp_val.XF = XFs[temp_val.ixfe];
|
4872
|
+
if(options.cellFormula) temp_val.f = stringify_formula(last_formula.formula, range, last_formula.cell, supbooks);
|
4873
|
+
if(temp_val.XF) try {
|
4874
|
+
temp_val.w=SSF.format(temp_val.XF.ifmt||0, temp_val.v);
|
4875
|
+
if(options.cellNF) temp_val.z = SSF._table[temp_val.XF.ifmt||0];
|
4876
|
+
} catch(e) { if(opts.WTF) throw e; }
|
4877
|
+
addline(last_formula.cell, temp_val, options);
|
4781
4878
|
last_formula = null;
|
4782
4879
|
}
|
4783
4880
|
} break;
|
@@ -4785,11 +4882,27 @@ function parse_workbook(blob) {
|
|
4785
4882
|
/* console.error(val); */
|
4786
4883
|
} break;
|
4787
4884
|
case 'ShrFmla': {
|
4788
|
-
|
4885
|
+
if(!cell_valid) break;
|
4886
|
+
if(options.cellFormula) out[last_cell].f = stringify_formula(val[0], range, lastcell, supbooks);
|
4789
4887
|
shared_formulae[last_cell] = val[0];
|
4790
4888
|
} break;
|
4791
4889
|
case 'LabelSst': {
|
4792
|
-
|
4890
|
+
temp_val={v:sst[val.isst].t, ixfe:val.ixfe, t:'s'};
|
4891
|
+
temp_val.XF = XFs[temp_val.ixfe];
|
4892
|
+
if(temp_val.XF) try {
|
4893
|
+
temp_val.w=SSF.format(temp_val.XF.ifmt||0, temp_val.v);
|
4894
|
+
if(options.cellNF) temp_val.z = SSF._table[temp_val.XF.ifmt||0];
|
4895
|
+
} catch(e) { if(opts.WTF) throw e; }
|
4896
|
+
addline({c:val.c, r:val.r}, temp_val, options);
|
4897
|
+
} break;
|
4898
|
+
case 'Label': {
|
4899
|
+
/* Some writers erroneously write Label */
|
4900
|
+
temp_val = {v:val.val, ixfe:val.ixfe, XF:XFs[val.ixfe], t:'s'};
|
4901
|
+
if(temp_val.XF) try {
|
4902
|
+
temp_val.w=SSF.format(temp_val.XF.ifmt||0, temp_val.v);
|
4903
|
+
if(options.cellNF) temp_val.z = SSF._table[temp_val.XF.ifmt||0];
|
4904
|
+
} catch(e) { if(opts.WTF) throw e; }
|
4905
|
+
addline({c:val.c, r:val.r}, temp_val, options);
|
4793
4906
|
} break;
|
4794
4907
|
case 'Dimensions': {
|
4795
4908
|
range = val;
|
@@ -4824,7 +4937,6 @@ function parse_workbook(blob) {
|
|
4824
4937
|
case 'GUIDTypeLib': {
|
4825
4938
|
|
4826
4939
|
} break;
|
4827
|
-
case 'Note': break;
|
4828
4940
|
|
4829
4941
|
case 'MergeCells': break;
|
4830
4942
|
|
@@ -4856,6 +4968,7 @@ function parse_workbook(blob) {
|
|
4856
4968
|
case 'CondFmt': case 'CF': case 'CF12': case 'CFEx': break;
|
4857
4969
|
|
4858
4970
|
/* Comments */
|
4971
|
+
case 'Note': break;
|
4859
4972
|
case 'NameCmt': break;
|
4860
4973
|
|
4861
4974
|
/* Chart */
|
@@ -4873,7 +4986,7 @@ function parse_workbook(blob) {
|
|
4873
4986
|
case 'DataFormat': case 'SerToCrt': case 'FontX': break;
|
4874
4987
|
case 'CatSerRange': case 'AxcExt': case 'SerFmt': break;
|
4875
4988
|
case 'ShtProps': break;
|
4876
|
-
case 'DefaultText': case 'Text': case '
|
4989
|
+
case 'DefaultText': case 'Text': case 'CatLab': break;
|
4877
4990
|
case 'DataLabExtContents': break;
|
4878
4991
|
case 'Legend': case 'LegendException': break;
|
4879
4992
|
case 'Pie': case 'Scatter': break;
|
@@ -4948,90 +5061,93 @@ function parse_workbook(blob) {
|
|
4948
5061
|
//lst.filter(function(x) { return x[0] === 'Formula';}).forEach(function(x){console.log(x[2].cell,x[2].formula);});
|
4949
5062
|
wb.Directory=sheetnamesraw;
|
4950
5063
|
wb.SheetNames=sheetnamesraw;
|
4951
|
-
wb.Sheets=Sheets;
|
5064
|
+
if(!options.bookSheets) wb.Sheets=Sheets;
|
4952
5065
|
wb.Preamble=Preamble;
|
4953
5066
|
wb.Strings = sst;
|
5067
|
+
wb.SSF = SSF.get_table();
|
4954
5068
|
if(opts.enc) wb.Encryption = opts.enc;
|
4955
5069
|
return wb;
|
4956
5070
|
}
|
4957
|
-
if(Workbook) WorkbookP = parse_workbook(Workbook.content);
|
4958
|
-
else throw new Error("Cannot find Workbook stream");
|
4959
5071
|
if(CompObj) CompObjP = parse_compobj(CompObj);
|
4960
|
-
|
5072
|
+
if(options.bookProps && !options.bookSheets) WorkbookP = {};
|
5073
|
+
else {
|
5074
|
+
if(Workbook) WorkbookP = parse_workbook(Workbook.content, options);
|
5075
|
+
else throw new Error("Cannot find Workbook stream");
|
5076
|
+
}
|
5077
|
+
|
5078
|
+
var props = {};
|
5079
|
+
for(var y in cfb.Summary) props[y] = cfb.Summary[y];
|
5080
|
+
for(y in cfb.DocSummary) props[y] = cfb.DocSummary[y];
|
5081
|
+
WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
|
5082
|
+
if(options.bookFiles) WorkbookP.cfb = cfb;
|
5083
|
+
WorkbookP.CompObjP = CompObjP;
|
4961
5084
|
return WorkbookP;
|
4962
5085
|
}
|
4963
5086
|
|
4964
|
-
function
|
4965
|
-
|
4966
|
-
|
4967
|
-
if
|
4968
|
-
|
4969
|
-
|
4970
|
-
|
4971
|
-
|
4972
|
-
val = sheet[encode_cell({
|
4973
|
-
c: C,
|
4974
|
-
r: range.s.r
|
4975
|
-
})];
|
4976
|
-
if(val){
|
4977
|
-
switch(val.t) {
|
4978
|
-
case 's': case 'str': columnHeaders[C] = JSON.parse(val.v); break;
|
4979
|
-
case 'n': columnHeaders[C] = val.v; break;
|
4980
|
-
}
|
4981
|
-
}
|
4982
|
-
}
|
5087
|
+
function format_cell(cell, v) {
|
5088
|
+
if(!cell) return "";
|
5089
|
+
if(typeof cell.w !== 'undefined') return cell.w;
|
5090
|
+
if(typeof v === 'undefined') v = cell.v;
|
5091
|
+
if(!cell.XF) return v;
|
5092
|
+
try { cell.w = SSF.format(cell.XF.ifmt||0, v); } catch(e) { return v; }
|
5093
|
+
return cell.w;
|
5094
|
+
}
|
4983
5095
|
|
4984
|
-
|
4985
|
-
|
4986
|
-
|
4987
|
-
|
4988
|
-
|
4989
|
-
|
4990
|
-
|
4991
|
-
|
4992
|
-
|
4993
|
-
|
4994
|
-
|
4995
|
-
|
4996
|
-
|
4997
|
-
|
4998
|
-
|
4999
|
-
|
5000
|
-
|
5001
|
-
|
5002
|
-
|
5003
|
-
|
5004
|
-
|
5005
|
-
|
5006
|
-
|
5007
|
-
|
5096
|
+
function sheet_to_row_object_array(sheet, opts){
|
5097
|
+
var val, row, r, hdr = {}, isempty, R, C, v;
|
5098
|
+
var out = [];
|
5099
|
+
opts = opts || {};
|
5100
|
+
if(!sheet || !sheet["!ref"]) return out;
|
5101
|
+
r = utils.decode_range(sheet["!ref"]);
|
5102
|
+
for(R=r.s.r, C = r.s.c; C <= r.e.c; ++C) {
|
5103
|
+
val = sheet[utils.encode_cell({c:C,r:R})];
|
5104
|
+
if(!val) continue;
|
5105
|
+
hdr[C] = format_cell(val);
|
5106
|
+
}
|
5107
|
+
|
5108
|
+
for (R = r.s.r + 1; R <= r.e.r; ++R) {
|
5109
|
+
isempty = true;
|
5110
|
+
/* row index available as __rowNum__ */
|
5111
|
+
row = Object.create({ __rowNum__ : R });
|
5112
|
+
for (C = r.s.c; C <= r.e.c; ++C) {
|
5113
|
+
val = sheet[utils.encode_cell({c: C,r: R})];
|
5114
|
+
if(!val || !val.t) continue;
|
5115
|
+
v = (val || {}).v;
|
5116
|
+
switch(val.t){
|
5117
|
+
case 'e': continue; /* TODO: emit error text? */
|
5118
|
+
case 's': case 'str': break;
|
5119
|
+
case 'b': case 'n': break;
|
5120
|
+
default: throw 'unrecognized type ' + val.t;
|
5008
5121
|
}
|
5009
|
-
if(
|
5010
|
-
|
5122
|
+
if(typeof v !== 'undefined') {
|
5123
|
+
row[hdr[C]] = opts.raw ? v||val.v : format_cell(val, v);
|
5124
|
+
isempty = false;
|
5011
5125
|
}
|
5012
5126
|
}
|
5127
|
+
if(!isempty) out.push(row);
|
5013
5128
|
}
|
5014
|
-
return
|
5015
|
-
}
|
5016
|
-
|
5017
|
-
function sheet_to_csv(sheet) {
|
5018
|
-
var out = "";
|
5019
|
-
|
5020
|
-
|
5021
|
-
|
5022
|
-
|
5023
|
-
|
5024
|
-
|
5025
|
-
|
5026
|
-
|
5027
|
-
|
5028
|
-
|
5029
|
-
|
5030
|
-
|
5031
|
-
|
5129
|
+
return out;
|
5130
|
+
}
|
5131
|
+
|
5132
|
+
function sheet_to_csv(sheet, opts) {
|
5133
|
+
var out = "", txt = "";
|
5134
|
+
opts = opts || {};
|
5135
|
+
if(!sheet || !sheet["!ref"]) return out;
|
5136
|
+
var r = utils.decode_range(sheet["!ref"]);
|
5137
|
+
var fs = opts.FS||",", rs = opts.RS||"\n";
|
5138
|
+
|
5139
|
+
for(var R = r.s.r; R <= r.e.r; ++R) {
|
5140
|
+
var row = [];
|
5141
|
+
for(var C = r.s.c; C <= r.e.c; ++C) {
|
5142
|
+
var val = sheet[utils.encode_cell({c:C,r:R})];
|
5143
|
+
if(!val) { row.push(""); continue; }
|
5144
|
+
txt = String(format_cell(val));
|
5145
|
+
if(txt.indexOf(fs) !== -1 || txt.indexOf(rs) !== -1 || txt.indexOf("\"") !== -1){
|
5146
|
+
txt = "\""+txt.replace(/"/g, '""') +"\"";
|
5032
5147
|
}
|
5033
|
-
|
5148
|
+
row.push(txt);
|
5034
5149
|
}
|
5150
|
+
out += row.join(fs) + (rs);
|
5035
5151
|
}
|
5036
5152
|
return out;
|
5037
5153
|
}
|
@@ -5043,7 +5159,8 @@ function get_formulae(ws) {
|
|
5043
5159
|
var x = ws[y];
|
5044
5160
|
var val = "";
|
5045
5161
|
if(x.f) val = x.f;
|
5046
|
-
else if(typeof x.
|
5162
|
+
else if(typeof x.w !== 'undefined') val = "'" + x.w;
|
5163
|
+
else if(typeof x.v === 'undefined') continue;
|
5047
5164
|
else val = x.v;
|
5048
5165
|
cmds.push(y + "=" + val);
|
5049
5166
|
}
|
@@ -5063,13 +5180,14 @@ var utils = {
|
|
5063
5180
|
sheet_to_csv: sheet_to_csv,
|
5064
5181
|
make_csv: sheet_to_csv,
|
5065
5182
|
get_formulae: get_formulae,
|
5183
|
+
format_cell: format_cell,
|
5066
5184
|
sheet_to_row_object_array: sheet_to_row_object_array
|
5067
5185
|
};
|
5068
5186
|
|
5069
5187
|
function xlsread(f, options) {
|
5070
|
-
return parse_xlscfb(CFB.read(f, options));
|
5188
|
+
return parse_xlscfb(CFB.read(f, options), options);
|
5071
5189
|
}
|
5072
|
-
var readFile = function(f)
|
5190
|
+
var readFile = function(f,o){return parse_xlscfb(CFB.read(f,{type:'file'}),o);};
|
5073
5191
|
function decode_row(rowstr) { return Number(unfix_row(rowstr)) - 1; }
|
5074
5192
|
function encode_row(row) { return "" + (row + 1); }
|
5075
5193
|
function fix_row(cstr) { return cstr.replace(/([A-Z]|^)([0-9]+)$/,"$1$$$2"); }
|
@@ -5121,13 +5239,5 @@ XLS.read = xlsread;
|
|
5121
5239
|
XLS.readFile = readFile;
|
5122
5240
|
XLS.utils = utils;
|
5123
5241
|
XLS.CFB = CFB;
|
5124
|
-
|
5125
|
-
var wb = readFile(process.argv[2] || 'Book1.xls');
|
5126
|
-
var target_sheet = process.argv[3] || '';
|
5127
|
-
if(target_sheet === '') target_sheet = wb.Directory[0];
|
5128
|
-
var ws = wb.Sheets[target_sheet];
|
5129
|
-
console.log(target_sheet);
|
5130
|
-
console.log(make_csv(ws));
|
5131
|
-
//console.log(get_formulae(ws));
|
5132
|
-
}
|
5242
|
+
XLS.SSF = SSF;
|
5133
5243
|
})(typeof exports !== 'undefined' ? exports : XLS);
|