js-xls-rails 0.5.0 → 0.6.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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);
|