version bump 0.11.5: "string" type

- proper JS string input / output type
- bower main now uses full version (fixes  h/t @newmesiss)
- DOM parse directly acts on innerHTML (see  h/t @danxfisher)
- unicode core props and ext props (fixes  h/t @fureweb-com)
- shim update for IE10/11
- test refresh and flow checks
This commit is contained in:
SheetJS 2017-09-30 02:18:11 -04:00
parent 1a8f97269e
commit af3df44633
49 changed files with 1388 additions and 915 deletions

@ -4,6 +4,11 @@ This log is intended to keep track of backwards-incompatible changes, including
but not limited to API changes and file location changes. Minor behavioral but not limited to API changes and file location changes. Minor behavioral
changes may not be included if they are not expected to break existing code. changes may not be included if they are not expected to break existing code.
## 0.11.5 (2017-09-30)
* Bower main script shifted to full version
* 'binary' / 'string' encoding
## 0.11.3 (2017-08-19) ## 0.11.3 (2017-08-19)
* XLS cell ixfe/XF removed * XLS cell ixfe/XF removed

@ -156,6 +156,9 @@ demo-systemjs: ## Run systemjs demo build
## Code Checking ## Code Checking
.PHONY: fullint
fullint: lint old-lint tslint flow mdlint ## Run all checks
.PHONY: lint .PHONY: lint
lint: $(TARGET) $(AUXTARGETS) ## Run eslint checks lint: $(TARGET) $(AUXTARGETS) ## Run eslint checks
@eslint --ext .js,.njs,.json,.html,.htm $(TARGET) $(AUXTARGETS) $(CMDS) $(HTMLLINT) package.json bower.json @eslint --ext .js,.njs,.json,.html,.htm $(TARGET) $(AUXTARGETS) $(CMDS) $(HTMLLINT) package.json bower.json
@ -165,9 +168,9 @@ lint: $(TARGET) $(AUXTARGETS) ## Run eslint checks
old-lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks old-lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks
@jshint --show-non-errors $(TARGET) $(AUXTARGETS) @jshint --show-non-errors $(TARGET) $(AUXTARGETS)
@jshint --show-non-errors $(CMDS) @jshint --show-non-errors $(CMDS)
@jshint --show-non-errors package.json bower.json @jshint --show-non-errors package.json bower.json test.js
@jshint --show-non-errors --extract=always $(HTMLLINT) @jshint --show-non-errors --extract=always $(HTMLLINT)
@jscs $(TARGET) $(AUXTARGETS) @jscs $(TARGET) $(AUXTARGETS) test.js
if [ -e $(CLOSURE) ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi if [ -e $(CLOSURE) ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi
.PHONY: tslint .PHONY: tslint

@ -294,6 +294,9 @@ data and feeding it into the library. Here are a few common scenarios:
<details> <details>
<summary><b>nodejs read a file</b> (click to show)</summary> <summary><b>nodejs read a file</b> (click to show)</summary>
`readFile` is only available in server environments. Browsers have no API for
reading arbitrary files given a path, so another strategy must be used.
```js ```js
if(typeof require !== 'undefined') XLSX = require('xlsx'); if(typeof require !== 'undefined') XLSX = require('xlsx');
var workbook = XLSX.readFile('test.xlsx'); var workbook = XLSX.readFile('test.xlsx');
@ -305,11 +308,21 @@ var workbook = XLSX.readFile('test.xlsx');
<details> <details>
<summary><b>Browser read TABLE element from page</b> (click to show)</summary> <summary><b>Browser read TABLE element from page</b> (click to show)</summary>
The `table_to_book` and `table_to_sheet` utility functions take a DOM TABLE
element and iterate through the child nodes.
```js ```js
var worksheet = XLSX.utils.table_to_book(document.getElementById('tableau')); var worksheet = XLSX.utils.table_to_book(document.getElementById('tableau'));
/* DO SOMETHING WITH workbook HERE */ /* DO SOMETHING WITH workbook HERE */
``` ```
Alternatively, the HTML code can be extracted and parsed:
```js
var htmlstr = document.getElementById('tableau').outerHTML;
var worksheet = XLSX.read(htmlstr, {type:'string'});
```
</details> </details>
<details> <details>
@ -566,16 +579,35 @@ Assuming `workbook` is a workbook object:
<details> <details>
<summary><b>nodejs write a file</b> (click to show)</summary> <summary><b>nodejs write a file</b> (click to show)</summary>
`writeFile` is only available in server environments. Browsers have no API for
writing arbitrary files given a path, so another strategy must be used.
```js ```js
if(typeof require !== 'undefined') XLSX = require('xlsx');
/* output format determined by filename */ /* output format determined by filename */
XLSX.writeFile(workbook, 'out.xlsx'); XLSX.writeFile(workbook, 'out.xlsb');
/* at this point, out.xlsx is a file that you can distribute */ /* at this point, out.xlsb is a file that you can distribute */
``` ```
</details> </details>
<details> <details>
<summary><b>Browser download file</b> (click to show)</summary> <summary><b>Browser add to web page</b> (click to show)</summary>
The `sheet_to_html` utility function generates HTML code that can be added to
any DOM element.
```js
var worksheet = workbook.Sheets[workbook.SheetNames[0]];
var container = document.getElementById('tableau');
container.innerHTML = XLSX.utils.sheet_to_html(worksheet);
```
</details>
<details>
<summary><b>Browser save file</b> (click to show)</summary>
Note: browser generates binary blob and forces a "download" to client. This Note: browser generates binary blob and forces a "download" to client. This
example uses [FileSaver](https://github.com/eligrey/FileSaver.js/): example uses [FileSaver](https://github.com/eligrey/FileSaver.js/):
@ -596,6 +628,7 @@ function s2ab(s) {
/* the saveAs call downloads a file on the local machine */ /* the saveAs call downloads a file on the local machine */
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx"); saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx");
``` ```
</details> </details>
<details> <details>
@ -1442,6 +1475,7 @@ tells the library how to parse the data argument:
|------------|-----------------------------------------------------------------| |------------|-----------------------------------------------------------------|
| `"base64"` | string: Base64 encoding of the file | | `"base64"` | string: Base64 encoding of the file |
| `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) | | `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) |
| `"string"` | string: JS string (characters interpreted as UTF8) |
| `"buffer"` | nodejs Buffer | | `"buffer"` | nodejs Buffer |
| `"array"` | array: array of 8-bit unsigned int (byte `n` is `data[n]`) | | `"array"` | array: array of 8-bit unsigned int (byte `n` is `data[n]`) |
| `"file"` | string: path of file that will be read (nodejs only) | | `"file"` | string: path of file that will be read (nodejs only) |
@ -1574,10 +1608,10 @@ The `type` argument for `write` mirrors the `type` argument for `read`:
|------------|-----------------------------------------------------------------| |------------|-----------------------------------------------------------------|
| `"base64"` | string: Base64 encoding of the file | | `"base64"` | string: Base64 encoding of the file |
| `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) | | `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) |
| `"string"` | string: JS string (characters interpreted as UTF8) |
| `"buffer"` | nodejs Buffer | | `"buffer"` | nodejs Buffer |
| `"file"` | string: path of file that will be created (nodejs only) | | `"file"` | string: path of file that will be created (nodejs only) |
## Utility Functions ## Utility Functions
The `sheet_to_*` functions accept a worksheet and an optional options object. The `sheet_to_*` functions accept a worksheet and an optional options object.

@ -1 +1 @@
XLSX.version = '0.11.4'; XLSX.version = '0.11.5';

@ -39,7 +39,7 @@ function getzipfile(zip, file/*:string*/) {
return o; return o;
} }
function getzipdata(zip, file/*:string*/, safe/*:?boolean*/) { function getzipdata(zip, file/*:string*/, safe/*:?boolean*/)/*:any*/ {
if(!safe) return getdata(getzipfile(zip, file)); if(!safe) return getdata(getzipfile(zip, file));
if(!file) return null; if(!file) return null;
try { return getzipdata(zip, file); } catch(e) { return null; } try { return getzipdata(zip, file); } catch(e) { return null; }

@ -101,6 +101,31 @@ var utf8read/*:StringConv*/ = function utf8reada(orig) {
return out; return out;
}; };
var utf8write/*:StringConv*/ = function(orig) {
var out = [], i = 0, c = 0, d = 0;
while(i < orig.length) {
c = orig.charCodeAt(i++);
switch(true) {
case c < 128: out.push(String.fromCharCode(c)); break;
case c < 2048:
out.push(String.fromCharCode(192 + (c >> 6)));
out.push(String.fromCharCode(128 + (c & 63)));
break;
case c >= 55296 && c < 57344:
c -= 55296; d = orig.charCodeAt(i++) - 56320 + (c<<10);
out.push(String.fromCharCode(240 + ((d >>18) & 7)));
out.push(String.fromCharCode(144 + ((d >>12) & 63)));
out.push(String.fromCharCode(128 + ((d >> 6) & 63)));
out.push(String.fromCharCode(128 + (d & 63)));
break;
default:
out.push(String.fromCharCode(224 + (c >> 12)));
out.push(String.fromCharCode(128 + ((c >> 6) & 63)));
out.push(String.fromCharCode(128 + (c & 63)));
}
}
return out.join("");
};
if(has_buf) { if(has_buf) {
var utf8readb = function utf8readb(data) { var utf8readb = function utf8readb(data) {
@ -124,6 +149,8 @@ if(has_buf) {
// $FlowIgnore // $FlowIgnore
var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); }; var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc; if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
utf8write = function(data) { return new Buffer(data, 'utf8').toString("binary"); };
} }
// matches <foo>...</foo> extracts content // matches <foo>...</foo> extracts content
@ -136,6 +163,10 @@ var matchtag = (function() {
}; };
})(); })();
function htmldecode(str/*:string*/)/*:string*/ {
return str.trim().replace(/\s+/g, " ").replace(/<\s*[bB][rR]\s*\/?/g,"\n").replace(/<[^>]*>/g,"").replace(/&nbsp;/g, " ");
}
var vtregex = (function(){ var vt_cache = {}; var vtregex = (function(){ var vt_cache = {};
return function vt_regex(bt) { return function vt_regex(bt) {
if(vt_cache[bt] !== undefined) return vt_cache[bt]; if(vt_cache[bt] !== undefined) return vt_cache[bt];

@ -1,4 +1,4 @@
function read_double_le(b, idx/*:number*/)/*:number*/ { function read_double_le(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ {
var s = 1 - 2 * (b[idx + 7] >>> 7); var s = 1 - 2 * (b[idx + 7] >>> 7);
var e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 0x0f); var e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 0x0f);
var m = (b[idx+6]&0x0f); var m = (b[idx+6]&0x0f);
@ -9,7 +9,7 @@ function read_double_le(b, idx/*:number*/)/*:number*/ {
return s * Math.pow(2, e - 52) * m; return s * Math.pow(2, e - 52) * m;
} }
function write_double_le(b, v/*:number*/, idx/*:number*/) { function write_double_le(b/*:RawBytes|CFBlob*/, v/*:number*/, idx/*:number*/) {
var bs = ((v < 0 || 1/v == -Infinity) ? 1 : 0) << 7, e = 0, m = 0; var bs = ((v < 0 || 1/v == -Infinity) ? 1 : 0) << 7, e = 0, m = 0;
var av = bs ? -v : v; var av = bs ? -v : v;
if(!isFinite(av)) { e = 0x7ff; m = isNaN(v) ? 0x6969 : 0; } if(!isFinite(av)) { e = 0x7ff; m = isNaN(v) ? 0x6969 : 0; }
@ -25,61 +25,61 @@ function write_double_le(b, v/*:number*/, idx/*:number*/) {
b[idx + 7] = (e >> 4) | bs; b[idx + 7] = (e >> 4) | bs;
} }
var __toBuffer, ___toBuffer; var __toBuffer = function(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; };
__toBuffer = ___toBuffer = function toBuffer_(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; }; var ___toBuffer = __toBuffer;
var __utf16le, ___utf16le; var __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join(""); };
__utf16le = ___utf16le = function utf16le_(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join(""); }; var ___utf16le = __utf16le;
var __hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); }; var __hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); };
var ___hexlify = __hexlify; var ___hexlify = __hexlify;
var __utf8, ___utf8; var __utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
__utf8 = ___utf8 = function(b,s,e) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); }; var ___utf8 = __utf8;
var __lpstr, ___lpstr; var __lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
__lpstr = ___lpstr = function lpstr_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";}; var ___lpstr = __lpstr;
var __lpwstr, ___lpwstr; var __lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
__lpwstr = ___lpwstr = function lpwstr_(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";}; var ___lpwstr = __lpwstr;
var __lpp4, ___lpp4; var __lpp4, ___lpp4;
__lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";}; __lpp4 = ___lpp4 = function lpp4_(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
var __8lpp4, ___8lpp4; var __8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
__8lpp4 = ___8lpp4 = function lpp4_8(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";}; var ___8lpp4 = __8lpp4;
var __double, ___double; var __double, ___double;
__double = ___double = function(b, idx) { return read_double_le(b, idx);}; __double = ___double = function(b/*:RawBytes|CFBlob*/, idx/*:number*/) { return read_double_le(b, idx);};
var is_buf = function is_buf_a(a) { return Array.isArray(a); }; var is_buf = function is_buf_a(a) { return Array.isArray(a); };
if(has_buf/*:: && typeof Buffer != 'undefined'*/) {
__utf16le = function utf16le_b(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e); }; if(has_buf/*:: && typeof Buffer !== 'undefined'*/) {
__hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); }; __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___utf16le(b,s,e); return b.toString('utf16le',s,e); };
__lpstr = function lpstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";}; __hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { return Buffer.isBuffer(b)/*:: && b instanceof Buffer*/ ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
__lpwstr = function lpwstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);}; __lpstr = function lpstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
__lpp4 = function lpp4_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);}; __lpwstr = function lpwstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
__8lpp4 = function lpp4_8b(b,i) { if(!Buffer.isBuffer(b)) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);}; __lpp4 = function lpp4_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);};
__utf8 = function utf8_b(b, s,e) { return b.toString('utf8',s,e); }; __8lpp4 = function lpp4_8b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);};
__utf8 = function utf8_b(b/*:RawBytes|CFBlob*/, s/*:number*/, e/*:number*/) { return (Buffer.isBuffer(b)/*:: && (b instanceof Buffer)*/) ? b.toString('utf8',s,e) : __utf8(b,s,e); };
__toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);}; __toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);};
bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); }; bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); };
__double = function double_(b,i) { if(Buffer.isBuffer(b)/*::&& b instanceof Buffer*/) return b.readDoubleLE(i); return ___double(b,i); }; __double = function double_(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(Buffer.isBuffer(b)/*::&& b instanceof Buffer*/) return b.readDoubleLE(i); return ___double(b,i); };
is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); }; is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); };
} }
/* from js-xls */ /* from js-xls */
if(typeof cptable !== 'undefined') { if(typeof cptable !== 'undefined') {
__utf16le = function(b,s,e) { return cptable.utils.decode(1200, b.slice(s,e)); }; __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(1200, b.slice(s,e)); };
__utf8 = function(b,s,e) { return cptable.utils.decode(65001, b.slice(s,e)); }; __utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(65001, b.slice(s,e)); };
__lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";}; __lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";};
__lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";}; __lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";};
__lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";}; __lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";};
__8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";}; __8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";};
} }
var __readUInt8 = function(b, idx/*:number*/)/*:number*/ { return b[idx]; }; var __readUInt8 = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx]; };
var __readUInt16LE = function(b, idx/*:number*/)/*:number*/ { return b[idx+1]*(1<<8)+b[idx]; }; var __readUInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+1]*(1<<8)+b[idx]; };
var __readInt16LE = function(b, idx/*:number*/)/*:number*/ { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; }; var __readInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; };
var __readUInt32LE = function(b, idx/*:number*/)/*:number*/ { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; }; var __readUInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
var __readInt32LE = function(b, idx/*:number*/)/*:number*/ { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; }; var __readInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
var ___unhexlify = function(s) { return s.match(/../g).map(function(x) { return parseInt(x,16);}); }; var ___unhexlify = function(s/*:string*/)/*:Array<number>*/ { return (s.match(/../g)||[]).map(function(x) { return parseInt(x,16);}); };
var __unhexlify = typeof Buffer !== "undefined" ? function(s) { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify; var __unhexlify = typeof Buffer !== "undefined" ? function(s/*:string*/)/*:Array<number>|Buffer*/ { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;
function ReadShift(size/*:number*/, t/*:?string*/) { function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
var o="", oI, oR, oo=[], w, vv, i, loc; var o="", oI/*:: :number = 0*/, oR, oo=[], w, vv, i, loc;
switch(t) { switch(t) {
case 'dbcs': case 'dbcs':
loc = this.l; loc = this.l;
@ -151,11 +151,11 @@ function ReadShift(size/*:number*/, t/*:?string*/) {
this.l+=size; return o; this.l+=size; return o;
} }
var __writeUInt16LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); }; var __writeUInt32LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); b[idx+2] = ((val >>> 16) & 0xFF); b[idx+3] = ((val >>> 24) & 0xFF); };
var __writeUInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); b[idx+2] = ((val >>> 16) & 0xFF); b[idx+3] = ((val >>> 24) & 0xFF); }; var __writeInt32LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); };
var __writeInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); }; var __writeUInt16LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); };
function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/) { function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/)/*:any*/ {
var size = 0, i = 0; var size = 0, i = 0;
if(f === 'dbcs') { if(f === 'dbcs') {
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */ /*:: if(typeof val !== 'string') throw new Error("unreachable"); */
@ -171,6 +171,7 @@ function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/) {
this[this.l++] = parseInt(val.slice(2*i, 2*i+2), 16)||0; this[this.l++] = parseInt(val.slice(2*i, 2*i+2), 16)||0;
} return this; } return this;
} else if(f === 'utf16le') { } else if(f === 'utf16le') {
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
var end/*:number*/ = this.l + t; var end/*:number*/ = this.l + t;
for(i = 0; i < Math.min(val.length, t); ++i) { for(i = 0; i < Math.min(val.length, t); ++i) {
var cc = val.charCodeAt(i); var cc = val.charCodeAt(i);
@ -192,20 +193,20 @@ function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/) {
this.l += size; return this; this.l += size; return this;
} }
function CheckField(hexstr, fld) { function CheckField(hexstr/*:string*/, fld/*:string*/)/*:void*/ {
var m = __hexlify(this,this.l,hexstr.length>>1); var m = __hexlify(this,this.l,hexstr.length>>1);
if(m !== hexstr) throw fld + 'Expected ' + hexstr + ' saw ' + m; if(m !== hexstr) throw new Error(fld + 'Expected ' + hexstr + ' saw ' + m);
this.l += hexstr.length>>1; this.l += hexstr.length>>1;
} }
function prep_blob(blob, pos/*:number*/) { function prep_blob(blob, pos/*:number*/)/*:void*/ {
blob.l = pos; blob.l = pos;
blob.read_shift = ReadShift; blob.read_shift = /*::(*/ReadShift/*:: :any)*/;
blob.chk = CheckField; blob.chk = CheckField;
blob.write_shift = WriteShift; blob.write_shift = WriteShift;
} }
function parsenoop(blob, length/*:number*/) { blob.l += length; } function parsenoop(blob, length/*:: :number, opts?:any */) { blob.l += length; }
function parsenooplog(blob, length/*:number*/) { if(typeof console != 'undefined') console.log(blob.slice(blob.l, blob.l + length)); blob.l += length; } function parsenooplog(blob, length/*:number*/) { if(typeof console != 'undefined') console.log(blob.slice(blob.l, blob.l + length)); blob.l += length; }
function writenoop(blob, length/*:number*/) { blob.l += length; } function writenoop(blob, length/*:number*/) { blob.l += length; }

@ -33,6 +33,7 @@ var CORE_PROPS_REGEX/*:Array<RegExp>*/ = (function() {
function parse_core_props(data) { function parse_core_props(data) {
var p = {}; var p = {};
data = utf8read(data);
for(var i = 0; i < CORE_PROPS.length; ++i) { for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]); var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);

@ -19,6 +19,7 @@ RELS.EXT_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relatio
function parse_ext_props(data, p, opts) { function parse_ext_props(data, p, opts) {
var q = {}; if(!p) p = {}; var q = {}; if(!p) p = {};
data = utf8read(data);
EXT_PROPS.forEach(function(f) { EXT_PROPS.forEach(function(f) {
switch(f[2]) { switch(f[2]) {

@ -193,7 +193,7 @@ function parse_PropertySet(blob, PIDSI) {
case 1252: case 1252:
case 65000: case -536: case 65000: case -536:
case 65001: case -535: case 65001: case -535:
set_cp(CodePage = PropH[piddsi.n]); break; set_cp(CodePage = PropH[piddsi.n]>>>0 & 0xFFFF); break;
default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]); default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
} }
} else { } else {
@ -235,6 +235,7 @@ function parse_PropertySet(blob, PIDSI) {
/* [MS-OLEPS] 2.21 PropertySetStream */ /* [MS-OLEPS] 2.21 PropertySetStream */
function parse_PropertySetStream(file, PIDSI) { function parse_PropertySetStream(file, PIDSI) {
var blob = file.content; var blob = file.content;
if(!blob) return ({}/*:any*/);
prep_blob(blob, 0); prep_blob(blob, 0);
var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0; var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;

@ -7,7 +7,7 @@ function parse_XLSCell(blob, length)/*:Cell*/ {
var ixfe = blob.read_shift(2); var ixfe = blob.read_shift(2);
return ({r:rw, c:col, ixfe:ixfe}/*:any*/); return ({r:rw, c:col, ixfe:ixfe}/*:any*/);
} }
function write_XLSCell(R/*:number*/, C/*:number*/, ixfe/*:number*/, o) { function write_XLSCell(R/*:number*/, C/*:number*/, ixfe/*:?number*/, o) {
if(!o) o = new_buf(6); if(!o) o = new_buf(6);
o.write_shift(2, R); o.write_shift(2, R);
o.write_shift(2, C); o.write_shift(2, C);

@ -341,7 +341,7 @@ var SYLK = (function() {
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ { function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
var preamble/*:Array<string>*/ = ["ID;PWXL;N;E"], o/*:Array<string>*/ = []; var preamble/*:Array<string>*/ = ["ID;PWXL;N;E"], o/*:Array<string>*/ = [];
var r = decode_range(ws['!ref']), cell/*:Cell*/; var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = Array.isArray(ws); var dense = Array.isArray(ws);
var RS = "\r\n"; var RS = "\r\n";
@ -425,7 +425,7 @@ var DIF = (function() {
}; };
return function sheet_to_dif(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ { return function sheet_to_dif(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
var o/*:Array<string>*/ = []; var o/*:Array<string>*/ = [];
var r = decode_range(ws['!ref']), cell/*:Cell*/; var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = Array.isArray(ws); var dense = Array.isArray(ws);
push_field(o, "TABLE", 0, 1, "sheetjs"); push_field(o, "TABLE", 0, 1, "sheetjs");
push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,""); push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,"");
@ -541,6 +541,7 @@ var PRN = (function() {
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"'); if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
if(s.length == 0) cell.t = 'z'; if(s.length == 0) cell.t = 'z';
else if(o.raw) { cell.t = 's'; cell.v = s; } else if(o.raw) { cell.t = 's'; cell.v = s; }
else if(s.trim().length == 0) { cell.t = 's'; cell.v = s; }
else if(s.charCodeAt(0) == 0x3D) { else if(s.charCodeAt(0) == 0x3D) {
if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); } if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); }
else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.substr(1); } else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.substr(1); }
@ -586,12 +587,13 @@ var PRN = (function() {
} }
function prn_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ { function prn_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
var str = "", bytes = firstbyte(d, opts); var str = "", bytes = opts.type == 'string' ? [0,0,0,0] : firstbyte(d, opts);
switch(opts.type) { switch(opts.type) {
case 'base64': str = Base64.decode(d); break; case 'base64': str = Base64.decode(d); break;
case 'binary': str = d; break; case 'binary': str = d; break;
case 'buffer': str = d.toString('binary'); break; case 'buffer': str = d.toString('binary'); break;
case 'array': str = cc2str(d); break; case 'array': str = cc2str(d); break;
case 'string': str = d; break;
default: throw new Error("Unrecognized type " + opts.type); default: throw new Error("Unrecognized type " + opts.type);
} }
if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str.slice(3)); if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str.slice(3));
@ -602,7 +604,7 @@ var PRN = (function() {
function sheet_to_prn(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ { function sheet_to_prn(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
var o/*:Array<string>*/ = []; var o/*:Array<string>*/ = [];
var r = decode_range(ws['!ref']), cell/*:Cell*/; var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = Array.isArray(ws); var dense = Array.isArray(ws);
for(var R = r.s.r; R <= r.e.r; ++R) { for(var R = r.s.r; R <= r.e.r; ++R) {
var oo = []; var oo = [];

@ -655,7 +655,7 @@ function parse_Rgce(blob, length, opts) {
return ptgs; return ptgs;
} }
function stringify_array(f) { function stringify_array(f)/*:string*/ {
var o = []; var o = [];
for(var i = 0; i < f.length; ++i) { for(var i = 0; i < f.length; ++i) {
var x = f[i], r = []; var x = f[i], r = [];
@ -701,7 +701,7 @@ function get_ixti_raw(supbooks, ixti/*:number*/, opts)/*:string*/ {
function get_ixti(supbooks, ixti/*:number*/, opts)/*:string*/ { function get_ixti(supbooks, ixti/*:number*/, opts)/*:string*/ {
return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts)); return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts));
} }
function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, opts) { function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, opts)/*:string*/ {
//console.log(formula); //console.log(formula);
var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}}; var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}};
var stack/*:Array<string>*/ = [], e1, e2, type, c/*:CellAddress*/, ixti=0, nameidx=0, r, sname=""; var stack/*:Array<string>*/ = [], e1, e2, type, c/*:CellAddress*/, ixti=0, nameidx=0, r, sname="";
@ -793,7 +793,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
case 'PtgFuncVar': /* 2.5.198.63 */ case 'PtgFuncVar': /* 2.5.198.63 */
//console.log(f[1]); //console.log(f[1]);
/* f[1] = [argc, func, type] */ /* f[1] = [argc, func, type] */
var argc/*:number*/ = f[1][0], func/*:string*/ = f[1][1]; var argc/*:number*/ = (f[1][0]/*:any*/), func/*:string*/ = (f[1][1]/*:any*/);
if(!argc) argc = 0; if(!argc) argc = 0;
var args = argc == 0 ? [] : stack.slice(-argc); var args = argc == 0 ? [] : stack.slice(-argc);
stack.length -= argc; stack.length -= argc;

@ -452,7 +452,7 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ {
case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break; case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
case 'b': p.v = val[1] ? true : false; break; case 'b': p.v = val[1] ? true : false; break;
case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break; case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break;
case 'str': p.t = 's'; p.v = utf8read(val[1]); break; case 'str': p.t = 's'; p.v = val[1]; break;
} }
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles); if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
C = val[0].c; C = val[0].c;

@ -174,7 +174,10 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
var opts = _opts || {}; var opts = _opts || {};
make_ssf(SSF); make_ssf(SSF);
var str = debom(xlml_normalize(d)); var str = debom(xlml_normalize(d));
if(opts && opts.type == 'binary' && typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str)); if(opts.type == 'binary' || opts.type == 'base64') {
if(typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str));
else str = utf8read(str);
}
var opening = str.slice(0, 1024).toLowerCase(), ishtml = false; var opening = str.slice(0, 1024).toLowerCase(), ishtml = false;
if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; }); if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; });
if(ishtml) return HTML_.to_workbook(str, opts); if(ishtml) return HTML_.to_workbook(str, opts);
@ -1001,12 +1004,6 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
case 's': t = 'String'; p = escapexml(cell.v||""); break; case 's': t = 'String'; p = escapexml(cell.v||""); break;
} }
var _v = (cell.v != null ? p : ""); var _v = (cell.v != null ? p : "");
if(opts && opts.type == 'binary' && typeof cptable !== 'undefined' && cell.t == 's') {
_v = cptable.utils.encode(65001, _v);
var __v = "";
for(var __i = 0; __i < _v.length; ++__i) __v += String.fromCharCode(_v[__i]);
_v = __v;
}
var m = '<Data ss:Type="' + t + '">' + _v + '</Data>'; var m = '<Data ss:Type="' + t + '">' + _v + '</Data>';
if((cell.c||[]).length > 0) m += write_ws_xlml_comment(cell.c); if((cell.c||[]).length > 0) m += write_ws_xlml_comment(cell.c);

@ -1,7 +1,8 @@
/* [MS-OLEDS] 2.3.8 CompObjStream */ /* [MS-OLEDS] 2.3.8 CompObjStream */
function parse_compobj(obj) { function parse_compobj(obj/*:CFBEntry*/) {
var v = {}; var v = {};
var o = obj.content; var o = obj.content;
/*:: if(o == null) return; */
/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */ /* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
var l = 28, m; var l = 28, m;
@ -819,25 +820,31 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
} }
/* TODO: WTF */ /* TODO: WTF */
function parse_props(cfb) { function parse_props(cfb/*:CFBContainer*/, props, o) {
/* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */ /* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
var DSI = CFB.find(cfb, '!DocumentSummaryInformation'); var DSI = CFB.find(cfb, '!DocumentSummaryInformation');
if(DSI) try { cfb.DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI); } catch(e) {/* empty */} if(DSI) try {
var DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI);
for(var d in DocSummary) props[d] = DocSummary[d];
} catch(e) {if(o.WTF == 2) throw e;/* empty */}
/* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/ /* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
var SI = CFB.find(cfb, '!SummaryInformation'); var SI = CFB.find(cfb, '!SummaryInformation');
if(SI) try { cfb.Summary = parse_PropertySetStream(SI, SummaryPIDSI); } catch(e) {/* empty */} if(SI) try {
var Summary = parse_PropertySetStream(SI, SummaryPIDSI);
for(var s in Summary) if(props[s] == null) props[s] = Summary[s];
} catch(e) {if(o.WTF == 2) throw e;/* empty */}
} }
function parse_xlscfb(cfb/*:any*/, options/*:?ParseOpts*/)/*:Workbook*/ { function parse_xlscfb(cfb/*:any*/, options/*:?ParseOpts*/)/*:Workbook*/ {
if(!options) options = {}; if(!options) options = {};
fix_read_opts(options); fix_read_opts(options);
reset_cp(); reset_cp();
var CompObj, Summary, WB/*:?any*/; var CompObj/*:?CFBEntry*/, Summary, WB/*:?any*/;
if(cfb.FullPaths) { if(cfb.FullPaths) {
CompObj = CFB.find(cfb, '!CompObj'); CompObj = CFB.find(cfb, '!CompObj');
Summary = CFB.find(cfb, '!SummaryInformation'); Summary = CFB.find(cfb, '!SummaryInformation');
WB = CFB.find(cfb, '/Workbook'); WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
} else { } else {
switch(options.type) { switch(options.type) {
case 'base64': cfb = s2a(Base64.decode(cfb)); break; case 'base64': cfb = s2a(Base64.decode(cfb)); break;
@ -848,26 +855,24 @@ if(cfb.FullPaths) {
prep_blob(cfb, 0); prep_blob(cfb, 0);
WB = ({content: cfb}/*:any*/); WB = ({content: cfb}/*:any*/);
} }
if(!WB) WB = CFB.find(cfb, '/Book'); var CompObjP, SummaryP, WorkbookP/*:: :Workbook = XLSX.utils.book_new(); */;
var CompObjP, SummaryP, WorkbookP/*:Workbook*/;
var _data/*:?any*/; var _data/*:?any*/;
if(CompObj) CompObjP = parse_compobj(CompObj); if(CompObj) CompObjP = parse_compobj(CompObj);
if(options.bookProps && !options.bookSheets) WorkbookP = ({}/*:any*/); if(options.bookProps && !options.bookSheets) WorkbookP = ({}/*:any*/);
else { else/*:: if(cfb instanceof CFBContainer) */ {
var T = has_buf ? 'buffer' : 'array';
if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options); if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options);
/* Quattro Pro 7-8 */ /* Quattro Pro 7-8 */
else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, options); else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
/* Quattro Pro 9 */ /* Quattro Pro 9 */
else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, options); else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
else throw new Error("Cannot find Workbook stream"); else throw new Error("Cannot find Workbook stream");
} }
if(cfb.FullPaths) parse_props(cfb);
var props = {}; var props = {};
for(var y in cfb.Summary) props[y] = cfb.Summary[y]; if(cfb.FullPaths) parse_props(/*::((*/cfb/*:: :any):CFBContainer)*/, props, options);
for(y in cfb.DocSummary) props[y] = cfb.DocSummary[y];
WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */ WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
if(options.bookFiles) WorkbookP.cfb = cfb; if(options.bookFiles) WorkbookP.cfb = cfb;
/*WorkbookP.CompObjP = CompObjP; // TODO: storage? */ /*WorkbookP.CompObjP = CompObjP; // TODO: storage? */

@ -1,5 +1,5 @@
function write_biff_rec(ba/*:BufArray*/, type/*:number|string*/, payload, length/*:?number*/) { function write_biff_rec(ba/*:BufArray*/, type/*:number|string*/, payload, length/*:?number*/) {
var t/*:number*/ = +type || +XLSRE[type]; var t/*:number*/ = +type || +XLSRE[/*::String(*/type/*::)*/];
if(isNaN(t)) return; if(isNaN(t)) return;
var len = length || (payload||[]).length || 0; var len = length || (payload||[]).length || 0;
var o = ba.next(4 + len); var o = ba.next(4 + len);

@ -30,7 +30,7 @@ var HTML_ = (function() {
if((RS = +tag.rowspan)>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}}); if((RS = +tag.rowspan)>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
/* TODO: generate stub cells */ /* TODO: generate stub cells */
if(!m.length) { C += CS; continue; } if(!m.length) { C += CS; continue; }
m = unescapexml(m).replace(/[\r\n]/g,""); m = htmldecode(unescapexml(m));
if(range.s.r > R) range.s.r = R; if(range.s.r > R) range.s.r = R;
if(range.e.r < R) range.e.r = R; if(range.e.r < R) range.e.r = R;
if(range.s.c > C) range.s.c = C; if(range.s.c > C) range.s.c = C;
@ -38,7 +38,7 @@ var HTML_ = (function() {
if(opts.dense) { if(opts.dense) {
if(!ws[R]) ws[R] = []; if(!ws[R]) ws[R] = [];
if(!m.length){} if(!m.length){}
else if(opts.raw) ws[R][C] = {t:'s', v:m}; else if(opts.raw || !m.trim().length) ws[R][C] = {t:'s', v:m};
else if(m === 'TRUE') ws[R][C] = {t:'b', v:true}; else if(m === 'TRUE') ws[R][C] = {t:'b', v:true};
else if(m === 'FALSE') ws[R][C] = {t:'b', v:false}; else if(m === 'FALSE') ws[R][C] = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)}; else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)};
@ -48,6 +48,7 @@ var HTML_ = (function() {
/* TODO: value parsing */ /* TODO: value parsing */
if(!m.length){} if(!m.length){}
else if(opts.raw) ws[coord] = {t:'s', v:m}; else if(opts.raw) ws[coord] = {t:'s', v:m};
else if(opts.raw || !m.trim().length) ws[coord] = {t:'s', v:m};
else if(m === 'TRUE') ws[coord] = {t:'b', v:true}; else if(m === 'TRUE') ws[coord] = {t:'b', v:true};
else if(m === 'FALSE') ws[coord] = {t:'b', v:false}; else if(m === 'FALSE') ws[coord] = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) ws[coord] = {t:'n', v:fuzzynum(m)}; else if(!isNaN(fuzzynum(m))) ws[coord] = {t:'n', v:fuzzynum(m)};
@ -132,7 +133,7 @@ function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
var row = rows[R]; var row = rows[R];
var elts = row.children; var elts = row.children;
for(_C = C = 0; _C < elts.length; ++_C) { for(_C = C = 0; _C < elts.length; ++_C) {
var elt = elts[_C], v = elts[_C].innerText || elts[_C].textContent || ""; var elt = elts[_C], v = htmldecode(elts[_C].innerHTML);
for(midx = 0; midx < merges.length; ++midx) { for(midx = 0; midx < merges.length; ++midx) {
var m = merges[midx]; var m = merges[midx];
if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; } if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; }
@ -144,6 +145,7 @@ function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
if(v != null) { if(v != null) {
if(v.length == 0) o.t = 'z'; if(v.length == 0) o.t = 'z';
else if(opts.raw){} else if(opts.raw){}
else if(v.trim().length == 0) o.t = 's';
else if(v === 'TRUE') o = {t:'b', v:true}; else if(v === 'TRUE') o = {t:'b', v:true};
else if(v === 'FALSE') o = {t:'b', v:false}; else if(v === 'FALSE') o = {t:'b', v:false};
else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)}; else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};

@ -464,7 +464,9 @@ function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts); if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
var content = getzipstr(zip, 'content.xml'); var content = getzipstr(zip, 'content.xml');
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file"); if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
return parse_content_xml(ods ? content : utf8read(content), opts); var wb = parse_content_xml(ods ? content : utf8read(content), opts);
if(safegetzipfile(zip, 'meta.xml')) wb.Props = parse_core_props(getzipdata(zip, 'meta.xml'));
return wb;
} }
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) { function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) {
return parse_content_xml(data, opts); return parse_content_xml(data, opts);

@ -3,8 +3,7 @@ function get_sheet_type(n/*:string*/)/*:string*/ {
if(RELS.CS && n == RELS.CS) return "chart"; if(RELS.CS && n == RELS.CS) return "chart";
if(RELS.DS && n == RELS.DS) return "dialog"; if(RELS.DS && n == RELS.DS) return "dialog";
if(RELS.MS && n == RELS.MS) return "macro"; if(RELS.MS && n == RELS.MS) return "macro";
if(!n || !n.length) return "sheet"; return (n && n.length) ? n : "sheet";
return n;
} }
function safe_parse_wbrels(wbrels, sheets) { function safe_parse_wbrels(wbrels, sheets) {
if(!wbrels) return 0; if(!wbrels) return 0;
@ -88,10 +87,10 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
var props = {}, propdata = ""; var props = {}, propdata = "";
if(dir.coreprops.length) { if(dir.coreprops.length) {
propdata = getzipstr(zip, strip_front_slash(dir.coreprops[0]), true); propdata = getzipdata(zip, strip_front_slash(dir.coreprops[0]), true);
if(propdata) props = parse_core_props(propdata); if(propdata) props = parse_core_props(propdata);
if(dir.extprops.length !== 0) { if(dir.extprops.length !== 0) {
propdata = getzipstr(zip, strip_front_slash(dir.extprops[0]), true); propdata = getzipdata(zip, strip_front_slash(dir.extprops[0]), true);
if(propdata) parse_ext_props(propdata, props, opts); if(propdata) parse_ext_props(propdata, props, opts);
} }
} }

@ -60,13 +60,23 @@ function read_utf16(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
return read_plaintext(d, o); return read_plaintext(d, o);
} }
function bstrify(data/*:string*/)/*:string*/ {
return !data.match(/[^\x00-\x7F]/) ? data : utf8write(data);
}
function read_prn(data, d, o, str) {
if(str) { o.type = "string"; return PRN.to_workbook(data, o); }
return PRN.to_workbook(d, o);
}
function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ { function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
var zip, d = data, n=[0]; var zip, d = data, n=[0], str = false;
var o = opts||{}; var o = opts||{};
_ssfopts = {}; _ssfopts = {};
if(o.dateNF) _ssfopts.dateNF = o.dateNF; if(o.dateNF) _ssfopts.dateNF = o.dateNF;
if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64"; if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
if(o.type == "file") { o.type = "buffer"; d = _fs.readFileSync(data); } if(o.type == "file") { o.type = "buffer"; d = _fs.readFileSync(data); }
if(o.type == "string") { str = true; o.type = "binary"; d = bstrify(data); }
switch((n = firstbyte(d, o))[0]) { switch((n = firstbyte(d, o))[0]) {
case 0xD0: return read_cfb(CFB.read(d, o), o); case 0xD0: return read_cfb(CFB.read(d, o), o);
case 0x09: return parse_xlscfb(d, o); case 0x09: return parse_xlscfb(d, o);
@ -74,7 +84,7 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
case 0x49: if(n[1] == 0x44) return read_wb_ID(d, o); break; case 0x49: if(n[1] == 0x44) return read_wb_ID(d, o); break;
case 0x54: if(n[1] == 0x41 && n[2] == 0x42 && n[3] == 0x4C) return DIF.to_workbook(d, o); break; case 0x54: if(n[1] == 0x41 && n[2] == 0x42 && n[3] == 0x4C) return DIF.to_workbook(d, o); break;
case 0x50: if(n[1] == 0x4B && n[2] < 0x20 && n[3] < 0x20) return read_zip(d, o); break; case 0x50: if(n[1] == 0x4B && n[2] < 0x20 && n[3] < 0x20) return read_zip(d, o); break;
case 0xEF: return n[3] == 0x3C ? parse_xlml(d, o) : PRN.to_workbook(d,o); case 0xEF: return n[3] == 0x3C ? parse_xlml(d, o) : read_prn(data, d, o, str);
case 0xFF: if(n[1] == 0xFE){ return read_utf16(d, o); } break; case 0xFF: if(n[1] == 0xFE){ return read_utf16(d, o); } break;
case 0x00: if(n[1] == 0x00 && n[2] >= 0x02 && n[3] == 0x00) return WK_.to_workbook(d, o); break; case 0x00: if(n[1] == 0x00 && n[2] >= 0x02 && n[3] == 0x00) return WK_.to_workbook(d, o); break;
case 0x03: case 0x83: case 0x8B: return DBF.to_workbook(d, o); case 0x03: case 0x83: case 0x8B: return DBF.to_workbook(d, o);
@ -83,7 +93,7 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
} }
if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o); if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
if(0x20>n[0]||n[0]>0x7F) throw new Error("Unsupported file " + n.join("|")); if(0x20>n[0]||n[0]>0x7F) throw new Error("Unsupported file " + n.join("|"));
return PRN.to_workbook(d, o); return read_prn(data, d, o, str);
} }
function readFileSync(filename/*:string*/, opts/*:?ParseOpts*/)/*:Workbook*/ { function readFileSync(filename/*:string*/, opts/*:?ParseOpts*/)/*:Workbook*/ {

@ -1,4 +1,4 @@
function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/) { function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:any*/ {
var o = opts||{}; var o = opts||{};
var z = write_zip(wb, o); var z = write_zip(wb, o);
var oopts = {}; var oopts = {};
@ -6,31 +6,51 @@ function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
switch(o.type) { switch(o.type) {
case "base64": oopts.type = "base64"; break; case "base64": oopts.type = "base64"; break;
case "binary": oopts.type = "string"; break; case "binary": oopts.type = "string"; break;
case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
case "buffer": case "buffer":
case "file": oopts.type = "nodebuffer"; break; case "file": oopts.type = "nodebuffer"; break;
default: throw new Error("Unrecognized type " + o.type); default: throw new Error("Unrecognized type " + o.type);
} }
if(o.type === "file") return _fs.writeFileSync(o.file, z.generate(oopts)); if(o.type === "file") return _fs.writeFileSync(o.file, z.generate(oopts));
return z.generate(oopts); var out = z.generate(oopts);
// $FlowIgnore
return o.type == "string" ? utf8read(out) : out;
} }
function write_cfb_type(wb/*:Workbook*/, opts/*:?WriteOpts*/) { function write_cfb_type(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:any*/ {
var o = opts||{}; var o = opts||{};
var cfb/*:CFBContainer*/ = write_xlscfb(wb, o); var cfb/*:CFBContainer*/ = write_xlscfb(wb, o);
switch(o.type) { switch(o.type) {
case "base64": case "binary": break; case "base64": case "binary": break;
case "buffer": case "array": o.type = ""; break; case "buffer": case "array": o.type = ""; break;
case "file": return _fs.writeFileSync(o.file, CFB.write(cfb, {type:'buffer'})); case "file": return _fs.writeFileSync(o.file, CFB.write(cfb, {type:'buffer'}));
case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
default: throw new Error("Unrecognized type " + o.type); default: throw new Error("Unrecognized type " + o.type);
} }
return CFB.write(cfb, o); return CFB.write(cfb, o);
} }
/* TODO: test consistency */ function write_string_type(out/*:string*/, opts/*:WriteOpts*/, bom/*:?string*/)/*:any*/ {
function write_bstr_type(out/*:string*/, opts/*:WriteOpts*/) { if(!bom) bom = "";
var o = bom + out;
switch(opts.type) {
case "base64": return Base64.encode(utf8write(o));
case "binary": return utf8write(o);
case "string": return out;
case "file": return _fs.writeFileSync(opts.file, o, 'utf8');
case "buffer": {
if(has_buf) return new Buffer(o, 'utf8');
else return write_string_type(o, {type:'binary'}).split("").map(function(c) { return c.charCodeAt(0); });
}
}
throw new Error("Unrecognized type " + opts.type);
}
function write_stxt_type(out/*:string*/, opts/*:WriteOpts*/)/*:any*/ {
switch(opts.type) { switch(opts.type) {
case "base64": return Base64.encode(out); case "base64": return Base64.encode(out);
case "binary": return out; case "binary": return out;
case "string": return out; /* override in sheet_to_txt */
case "file": return _fs.writeFileSync(opts.file, out, 'binary'); case "file": return _fs.writeFileSync(opts.file, out, 'binary');
case "buffer": { case "buffer": {
if(has_buf) return new Buffer(out, 'binary'); if(has_buf) return new Buffer(out, 'binary');
@ -41,27 +61,14 @@ function write_bstr_type(out/*:string*/, opts/*:WriteOpts*/) {
} }
/* TODO: test consistency */ /* TODO: test consistency */
function write_string_type(out/*:string*/, opts/*:WriteOpts*/) { function write_binary_type(out, opts/*:WriteOpts*/)/*:any*/ {
switch(opts.type) {
case "base64": return Base64.encode(out);
case "binary": return out;
case "file": return _fs.writeFileSync(opts.file, out, 'utf8');
case "buffer": {
if(has_buf) return new Buffer(out, 'utf8');
else return out.split("").map(function(c) { return c.charCodeAt(0); });
}
}
throw new Error("Unrecognized type " + opts.type);
}
/* TODO: test consistency */
function write_binary_type(out, opts/*:WriteOpts*/) {
switch(opts.type) { switch(opts.type) {
case "string":
case "base64": case "base64":
case "binary": case "binary":
var bstr = ""; var bstr = "";
for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]); for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]);
return opts.type == 'base64' ? Base64.encode(bstr) : bstr; return opts.type == 'base64' ? Base64.encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr;
case "file": return _fs.writeFileSync(opts.file, out); case "file": return _fs.writeFileSync(opts.file, out);
case "buffer": return out; case "buffer": return out;
default: throw new Error("Unrecognized type " + opts.type); default: throw new Error("Unrecognized type " + opts.type);
@ -77,14 +84,14 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
case 'slk': case 'slk':
case 'sylk': return write_string_type(write_slk_str(wb, o), o); case 'sylk': return write_string_type(write_slk_str(wb, o), o);
case 'html': return write_string_type(write_htm_str(wb, o), o); case 'html': return write_string_type(write_htm_str(wb, o), o);
case 'txt': return write_bstr_type(write_txt_str(wb, o), o); case 'txt': return write_stxt_type(write_txt_str(wb, o), o);
case 'csv': return write_string_type(write_csv_str(wb, o), o); case 'csv': return write_string_type(write_csv_str(wb, o), o, "\ufeff");
case 'dif': return write_string_type(write_dif_str(wb, o), o); case 'dif': return write_string_type(write_dif_str(wb, o), o);
case 'prn': return write_string_type(write_prn_str(wb, o), o); case 'prn': return write_string_type(write_prn_str(wb, o), o);
case 'rtf': return write_string_type(write_rtf_str(wb, o), o); case 'rtf': return write_string_type(write_rtf_str(wb, o), o);
case 'fods': return write_string_type(write_ods(wb, o), o); case 'fods': return write_string_type(write_ods(wb, o), o);
case 'biff2': if(!o.biff) o.biff = 2; return write_binary_type(write_biff_buf(wb, o), o); case 'biff2': if(!o.biff) o.biff = 2; /* falls through */
case 'biff3': if(!o.biff) o.biff = 3; return write_binary_type(write_biff_buf(wb, o), o); case 'biff3': if(!o.biff) o.biff = 3; /* falls through */
case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o); case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o);
case 'biff5': if(!o.biff) o.biff = 5; return write_cfb_type(wb, o); case 'biff5': if(!o.biff) o.biff = 5; return write_cfb_type(wb, o);
case 'biff8': case 'biff8':

@ -129,8 +129,8 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ {
function sheet_to_txt(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { function sheet_to_txt(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n"; if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n";
var s = sheet_to_csv(sheet, opts); var s = sheet_to_csv(sheet, opts);
if(typeof cptable == 'undefined') return s; if(typeof cptable == 'undefined' || opts.type == 'string') return s;
var o = cptable.utils.encode(1200, s); var o = cptable.utils.encode(1200, s, 'str');
return "\xff\xfe" + o; return "\xff\xfe" + o;
} }

@ -1,7 +1,7 @@
{ {
"name": "js-xlsx", "name": "js-xlsx",
"homepage": "https://github.com/SheetJS/js-xlsx", "homepage": "https://github.com/SheetJS/js-xlsx",
"main": "dist/xlsx.core.min.js", "main": "dist/xlsx.full.min.js",
"ignore": [ "ignore": [
"bin", "bin",
"bits", "bits",

24
dist/xlsx.core.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

30
dist/xlsx.full.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

230
dist/xlsx.js vendored

@ -6,7 +6,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false */ /*global global, exports, module, require:false, process:false, Buffer:false */
var XLSX = {}; var XLSX = {};
(function make_xlsx(XLSX){ (function make_xlsx(XLSX){
XLSX.version = '0.11.4'; XLSX.version = '0.11.5';
var current_codepage = 1200; var current_codepage = 1200;
/*global cptable:true */ /*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') { if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -2039,6 +2039,31 @@ var utf8read = function utf8reada(orig) {
return out; return out;
}; };
var utf8write = function(orig) {
var out = [], i = 0, c = 0, d = 0;
while(i < orig.length) {
c = orig.charCodeAt(i++);
switch(true) {
case c < 128: out.push(String.fromCharCode(c)); break;
case c < 2048:
out.push(String.fromCharCode(192 + (c >> 6)));
out.push(String.fromCharCode(128 + (c & 63)));
break;
case c >= 55296 && c < 57344:
c -= 55296; d = orig.charCodeAt(i++) - 56320 + (c<<10);
out.push(String.fromCharCode(240 + ((d >>18) & 7)));
out.push(String.fromCharCode(144 + ((d >>12) & 63)));
out.push(String.fromCharCode(128 + ((d >> 6) & 63)));
out.push(String.fromCharCode(128 + (d & 63)));
break;
default:
out.push(String.fromCharCode(224 + (c >> 12)));
out.push(String.fromCharCode(128 + ((c >> 6) & 63)));
out.push(String.fromCharCode(128 + (c & 63)));
}
}
return out.join("");
};
if(has_buf) { if(has_buf) {
var utf8readb = function utf8readb(data) { var utf8readb = function utf8readb(data) {
@ -2062,6 +2087,8 @@ if(has_buf) {
// $FlowIgnore // $FlowIgnore
var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); }; var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc; if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
utf8write = function(data) { return new Buffer(data, 'utf8').toString("binary"); };
} }
// matches <foo>...</foo> extracts content // matches <foo>...</foo> extracts content
@ -2074,6 +2101,10 @@ var matchtag = (function() {
}; };
})(); })();
function htmldecode(str) {
return str.trim().replace(/\s+/g, " ").replace(/<\s*[bB][rR]\s*\/?/g,"\n").replace(/<[^>]*>/g,"").replace(/&nbsp;/g, " ");
}
var vtregex = (function(){ var vt_cache = {}; var vtregex = (function(){ var vt_cache = {};
return function vt_regex(bt) { return function vt_regex(bt) {
if(vt_cache[bt] !== undefined) return vt_cache[bt]; if(vt_cache[bt] !== undefined) return vt_cache[bt];
@ -2169,37 +2200,37 @@ function write_double_le(b, v, idx) {
b[idx + 7] = (e >> 4) | bs; b[idx + 7] = (e >> 4) | bs;
} }
var __toBuffer, ___toBuffer; var __toBuffer = function(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; };
__toBuffer = ___toBuffer = function toBuffer_(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; }; var ___toBuffer = __toBuffer;
var __utf16le, ___utf16le; var __utf16le = function(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join(""); };
__utf16le = ___utf16le = function utf16le_(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join(""); }; var ___utf16le = __utf16le;
var __hexlify = function(b,s,l) { var ss=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); }; var __hexlify = function(b,s,l) { var ss=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); };
var ___hexlify = __hexlify; var ___hexlify = __hexlify;
var __utf8, ___utf8; var __utf8 = function(b,s,e) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
__utf8 = ___utf8 = function(b,s,e) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); }; var ___utf8 = __utf8;
var __lpstr, ___lpstr; var __lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
__lpstr = ___lpstr = function lpstr_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";}; var ___lpstr = __lpstr;
var __lpwstr, ___lpwstr; var __lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
__lpwstr = ___lpwstr = function lpwstr_(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";}; var ___lpwstr = __lpwstr;
var __lpp4, ___lpp4; var __lpp4, ___lpp4;
__lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";}; __lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
var __8lpp4, ___8lpp4; var __8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
__8lpp4 = ___8lpp4 = function lpp4_8(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";}; var ___8lpp4 = __8lpp4;
var __double, ___double; var __double, ___double;
__double = ___double = function(b, idx) { return read_double_le(b, idx);}; __double = ___double = function(b, idx) { return read_double_le(b, idx);};
var is_buf = function is_buf_a(a) { return Array.isArray(a); }; var is_buf = function is_buf_a(a) { return Array.isArray(a); };
if(has_buf) { if(has_buf) {
__utf16le = function utf16le_b(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e); }; __utf16le = function(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e); };
__hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); }; __hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
__lpstr = function lpstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";}; __lpstr = function lpstr_b(b, i) { if(!Buffer.isBuffer(b)) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
__lpwstr = function lpwstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);}; __lpwstr = function lpwstr_b(b, i) { if(!Buffer.isBuffer(b)) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
__lpp4 = function lpp4_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);}; __lpp4 = function lpp4_b(b, i) { if(!Buffer.isBuffer(b)) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);};
__8lpp4 = function lpp4_8b(b,i) { if(!Buffer.isBuffer(b)) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);}; __8lpp4 = function lpp4_8b(b, i) { if(!Buffer.isBuffer(b)) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);};
__utf8 = function utf8_b(b, s,e) { return b.toString('utf8',s,e); }; __utf8 = function utf8_b(b, s, e) { return (Buffer.isBuffer(b)) ? b.toString('utf8',s,e) : __utf8(b,s,e); };
__toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);}; __toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);};
bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); }; bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); };
__double = function double_(b,i) { if(Buffer.isBuffer(b)) return b.readDoubleLE(i); return ___double(b,i); }; __double = function double_(b, i) { if(Buffer.isBuffer(b)) return b.readDoubleLE(i); return ___double(b,i); };
is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); }; is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); };
} }
@ -2219,7 +2250,7 @@ var __readInt16LE = function(b, idx) { var u = b[idx+1]*(1<<8)+b[idx]; return (u
var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; }; var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; }; var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
var ___unhexlify = function(s) { return s.match(/../g).map(function(x) { return parseInt(x,16);}); }; var ___unhexlify = function(s) { return (s.match(/../g)||[]).map(function(x) { return parseInt(x,16);}); };
var __unhexlify = typeof Buffer !== "undefined" ? function(s) { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify; var __unhexlify = typeof Buffer !== "undefined" ? function(s) { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;
function ReadShift(size, t) { function ReadShift(size, t) {
@ -2295,9 +2326,9 @@ function ReadShift(size, t) {
this.l+=size; return o; this.l+=size; return o;
} }
var __writeUInt16LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); };
var __writeUInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); b[idx+2] = ((val >>> 16) & 0xFF); b[idx+3] = ((val >>> 24) & 0xFF); }; var __writeUInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); b[idx+2] = ((val >>> 16) & 0xFF); b[idx+3] = ((val >>> 24) & 0xFF); };
var __writeInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); }; var __writeInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); };
var __writeUInt16LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); };
function WriteShift(t, val, f) { function WriteShift(t, val, f) {
var size = 0, i = 0; var size = 0, i = 0;
@ -2312,7 +2343,7 @@ for(i = 0; i != val.length; ++i) this[this.l + i] = val.charCodeAt(i) & 0xFF;
this[this.l++] = parseInt(val.slice(2*i, 2*i+2), 16)||0; this[this.l++] = parseInt(val.slice(2*i, 2*i+2), 16)||0;
} return this; } return this;
} else if(f === 'utf16le') { } else if(f === 'utf16le') {
var end = this.l + t; var end = this.l + t;
for(i = 0; i < Math.min(val.length, t); ++i) { for(i = 0; i < Math.min(val.length, t); ++i) {
var cc = val.charCodeAt(i); var cc = val.charCodeAt(i);
this[this.l++] = cc & 0xff; this[this.l++] = cc & 0xff;
@ -2335,7 +2366,7 @@ this[this.l++] = parseInt(val.slice(2*i, 2*i+2), 16)||0;
function CheckField(hexstr, fld) { function CheckField(hexstr, fld) {
var m = __hexlify(this,this.l,hexstr.length>>1); var m = __hexlify(this,this.l,hexstr.length>>1);
if(m !== hexstr) throw fld + 'Expected ' + hexstr + ' saw ' + m; if(m !== hexstr) throw new Error(fld + 'Expected ' + hexstr + ' saw ' + m);
this.l += hexstr.length>>1; this.l += hexstr.length>>1;
} }
@ -3628,6 +3659,7 @@ var CORE_PROPS_REGEX = (function() {
function parse_core_props(data) { function parse_core_props(data) {
var p = {}; var p = {};
data = utf8read(data);
for(var i = 0; i < CORE_PROPS.length; ++i) { for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]); var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
@ -3695,6 +3727,7 @@ RELS.EXT_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relatio
function parse_ext_props(data, p, opts) { function parse_ext_props(data, p, opts) {
var q = {}; if(!p) p = {}; var q = {}; if(!p) p = {};
data = utf8read(data);
EXT_PROPS.forEach(function(f) { EXT_PROPS.forEach(function(f) {
switch(f[2]) { switch(f[2]) {
@ -4133,7 +4166,7 @@ function parse_PropertySet(blob, PIDSI) {
case 1252: case 1252:
case 65000: case -536: case 65000: case -536:
case 65001: case -535: case 65001: case -535:
set_cp(CodePage = PropH[piddsi.n]); break; set_cp(CodePage = PropH[piddsi.n]>>>0 & 0xFFFF); break;
default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]); default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
} }
} else { } else {
@ -4175,6 +4208,7 @@ function parse_PropertySet(blob, PIDSI) {
/* [MS-OLEPS] 2.21 PropertySetStream */ /* [MS-OLEPS] 2.21 PropertySetStream */
function parse_PropertySetStream(file, PIDSI) { function parse_PropertySetStream(file, PIDSI) {
var blob = file.content; var blob = file.content;
if(!blob) return ({});
prep_blob(blob, 0); prep_blob(blob, 0);
var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0; var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;
@ -5685,7 +5719,7 @@ var SYLK = (function() {
function sheet_to_sylk(ws, opts) { function sheet_to_sylk(ws, opts) {
var preamble = ["ID;PWXL;N;E"], o = []; var preamble = ["ID;PWXL;N;E"], o = [];
var r = decode_range(ws['!ref']), cell; var r = safe_decode_range(ws['!ref']), cell;
var dense = Array.isArray(ws); var dense = Array.isArray(ws);
var RS = "\r\n"; var RS = "\r\n";
@ -5769,7 +5803,7 @@ var DIF = (function() {
}; };
return function sheet_to_dif(ws, opts) { return function sheet_to_dif(ws, opts) {
var o = []; var o = [];
var r = decode_range(ws['!ref']), cell; var r = safe_decode_range(ws['!ref']), cell;
var dense = Array.isArray(ws); var dense = Array.isArray(ws);
push_field(o, "TABLE", 0, 1, "sheetjs"); push_field(o, "TABLE", 0, 1, "sheetjs");
push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,""); push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,"");
@ -5885,6 +5919,7 @@ var PRN = (function() {
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"'); if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
if(s.length == 0) cell.t = 'z'; if(s.length == 0) cell.t = 'z';
else if(o.raw) { cell.t = 's'; cell.v = s; } else if(o.raw) { cell.t = 's'; cell.v = s; }
else if(s.trim().length == 0) { cell.t = 's'; cell.v = s; }
else if(s.charCodeAt(0) == 0x3D) { else if(s.charCodeAt(0) == 0x3D) {
if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); } if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); }
else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.substr(1); } else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.substr(1); }
@ -5930,12 +5965,13 @@ var PRN = (function() {
} }
function prn_to_sheet(d, opts) { function prn_to_sheet(d, opts) {
var str = "", bytes = firstbyte(d, opts); var str = "", bytes = opts.type == 'string' ? [0,0,0,0] : firstbyte(d, opts);
switch(opts.type) { switch(opts.type) {
case 'base64': str = Base64.decode(d); break; case 'base64': str = Base64.decode(d); break;
case 'binary': str = d; break; case 'binary': str = d; break;
case 'buffer': str = d.toString('binary'); break; case 'buffer': str = d.toString('binary'); break;
case 'array': str = cc2str(d); break; case 'array': str = cc2str(d); break;
case 'string': str = d; break;
default: throw new Error("Unrecognized type " + opts.type); default: throw new Error("Unrecognized type " + opts.type);
} }
if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str.slice(3)); if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str.slice(3));
@ -5946,7 +5982,7 @@ var PRN = (function() {
function sheet_to_prn(ws, opts) { function sheet_to_prn(ws, opts) {
var o = []; var o = [];
var r = decode_range(ws['!ref']), cell; var r = safe_decode_range(ws['!ref']), cell;
var dense = Array.isArray(ws); var dense = Array.isArray(ws);
for(var R = r.s.r; R <= r.e.r; ++R) { for(var R = r.s.r; R <= r.e.r; ++R) {
var oo = []; var oo = [];
@ -9400,7 +9436,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell, supbooks, opts) {
case 'PtgFuncVar': /* 2.5.198.63 */ case 'PtgFuncVar': /* 2.5.198.63 */
//console.log(f[1]); //console.log(f[1]);
/* f[1] = [argc, func, type] */ /* f[1] = [argc, func, type] */
var argc = f[1][0], func = f[1][1]; var argc = (f[1][0]), func = (f[1][1]);
if(!argc) argc = 0; if(!argc) argc = 0;
var args = argc == 0 ? [] : stack.slice(-argc); var args = argc == 0 ? [] : stack.slice(-argc);
stack.length -= argc; stack.length -= argc;
@ -11977,7 +12013,7 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles) {
case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break; case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
case 'b': p.v = val[1] ? true : false; break; case 'b': p.v = val[1] ? true : false; break;
case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break; case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break;
case 'str': p.t = 's'; p.v = utf8read(val[1]); break; case 'str': p.t = 's'; p.v = val[1]; break;
} }
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles); if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
C = val[0].c; C = val[0].c;
@ -13380,7 +13416,10 @@ function parse_xlml_xml(d, _opts) {
var opts = _opts || {}; var opts = _opts || {};
make_ssf(SSF); make_ssf(SSF);
var str = debom(xlml_normalize(d)); var str = debom(xlml_normalize(d));
if(opts && opts.type == 'binary' && typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str)); if(opts.type == 'binary' || opts.type == 'base64') {
if(typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str));
else str = utf8read(str);
}
var opening = str.slice(0, 1024).toLowerCase(), ishtml = false; var opening = str.slice(0, 1024).toLowerCase(), ishtml = false;
if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; }); if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; });
if(ishtml) return HTML_.to_workbook(str, opts); if(ishtml) return HTML_.to_workbook(str, opts);
@ -14204,12 +14243,6 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){
case 's': t = 'String'; p = escapexml(cell.v||""); break; case 's': t = 'String'; p = escapexml(cell.v||""); break;
} }
var _v = (cell.v != null ? p : ""); var _v = (cell.v != null ? p : "");
if(opts && opts.type == 'binary' && typeof cptable !== 'undefined' && cell.t == 's') {
_v = cptable.utils.encode(65001, _v);
var __v = "";
for(var __i = 0; __i < _v.length; ++__i) __v += String.fromCharCode(_v[__i]);
_v = __v;
}
var m = '<Data ss:Type="' + t + '">' + _v + '</Data>'; var m = '<Data ss:Type="' + t + '">' + _v + '</Data>';
if((cell.c||[]).length > 0) m += write_ws_xlml_comment(cell.c); if((cell.c||[]).length > 0) m += write_ws_xlml_comment(cell.c);
@ -14297,8 +14330,7 @@ function write_xlml(wb, opts) {
function parse_compobj(obj) { function parse_compobj(obj) {
var v = {}; var v = {};
var o = obj.content; var o = obj.content;
/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
var l = 28, m; var l = 28, m;
m = __lpstr(o, l); m = __lpstr(o, l);
l += 4 + __readUInt32LE(o,l); l += 4 + __readUInt32LE(o,l);
@ -15113,14 +15145,20 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
} }
/* TODO: WTF */ /* TODO: WTF */
function parse_props(cfb) { function parse_props(cfb, props, o) {
/* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */ /* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
var DSI = CFB.find(cfb, '!DocumentSummaryInformation'); var DSI = CFB.find(cfb, '!DocumentSummaryInformation');
if(DSI) try { cfb.DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI); } catch(e) {/* empty */} if(DSI) try {
var DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI);
for(var d in DocSummary) props[d] = DocSummary[d];
} catch(e) {if(o.WTF == 2) throw e;/* empty */}
/* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/ /* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
var SI = CFB.find(cfb, '!SummaryInformation'); var SI = CFB.find(cfb, '!SummaryInformation');
if(SI) try { cfb.Summary = parse_PropertySetStream(SI, SummaryPIDSI); } catch(e) {/* empty */} if(SI) try {
var Summary = parse_PropertySetStream(SI, SummaryPIDSI);
for(var s in Summary) if(props[s] == null) props[s] = Summary[s];
} catch(e) {if(o.WTF == 2) throw e;/* empty */}
} }
function parse_xlscfb(cfb, options) { function parse_xlscfb(cfb, options) {
@ -15131,7 +15169,7 @@ var CompObj, Summary, WB;
if(cfb.FullPaths) { if(cfb.FullPaths) {
CompObj = CFB.find(cfb, '!CompObj'); CompObj = CFB.find(cfb, '!CompObj');
Summary = CFB.find(cfb, '!SummaryInformation'); Summary = CFB.find(cfb, '!SummaryInformation');
WB = CFB.find(cfb, '/Workbook'); WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
} else { } else {
switch(options.type) { switch(options.type) {
case 'base64': cfb = s2a(Base64.decode(cfb)); break; case 'base64': cfb = s2a(Base64.decode(cfb)); break;
@ -15142,26 +15180,24 @@ if(cfb.FullPaths) {
prep_blob(cfb, 0); prep_blob(cfb, 0);
WB = ({content: cfb}); WB = ({content: cfb});
} }
if(!WB) WB = CFB.find(cfb, '/Book');
var CompObjP, SummaryP, WorkbookP; var CompObjP, SummaryP, WorkbookP;
var _data; var _data;
if(CompObj) CompObjP = parse_compobj(CompObj); if(CompObj) CompObjP = parse_compobj(CompObj);
if(options.bookProps && !options.bookSheets) WorkbookP = ({}); if(options.bookProps && !options.bookSheets) WorkbookP = ({});
else { else {
var T = has_buf ? 'buffer' : 'array';
if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options); if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options);
/* Quattro Pro 7-8 */ /* Quattro Pro 7-8 */
else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, options); else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
/* Quattro Pro 9 */ /* Quattro Pro 9 */
else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, options); else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
else throw new Error("Cannot find Workbook stream"); else throw new Error("Cannot find Workbook stream");
} }
if(cfb.FullPaths) parse_props(cfb);
var props = {}; var props = {};
for(var y in cfb.Summary) props[y] = cfb.Summary[y]; if(cfb.FullPaths) parse_props(cfb, props, options);
for(y in cfb.DocSummary) props[y] = cfb.DocSummary[y];
WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */ WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
if(options.bookFiles) WorkbookP.cfb = cfb; if(options.bookFiles) WorkbookP.cfb = cfb;
/*WorkbookP.CompObjP = CompObjP; // TODO: storage? */ /*WorkbookP.CompObjP = CompObjP; // TODO: storage? */
@ -16688,7 +16724,7 @@ var HTML_ = (function() {
if((RS = +tag.rowspan)>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}}); if((RS = +tag.rowspan)>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
/* TODO: generate stub cells */ /* TODO: generate stub cells */
if(!m.length) { C += CS; continue; } if(!m.length) { C += CS; continue; }
m = unescapexml(m).replace(/[\r\n]/g,""); m = htmldecode(unescapexml(m));
if(range.s.r > R) range.s.r = R; if(range.s.r > R) range.s.r = R;
if(range.e.r < R) range.e.r = R; if(range.e.r < R) range.e.r = R;
if(range.s.c > C) range.s.c = C; if(range.s.c > C) range.s.c = C;
@ -16696,7 +16732,7 @@ var HTML_ = (function() {
if(opts.dense) { if(opts.dense) {
if(!ws[R]) ws[R] = []; if(!ws[R]) ws[R] = [];
if(!m.length){} if(!m.length){}
else if(opts.raw) ws[R][C] = {t:'s', v:m}; else if(opts.raw || !m.trim().length) ws[R][C] = {t:'s', v:m};
else if(m === 'TRUE') ws[R][C] = {t:'b', v:true}; else if(m === 'TRUE') ws[R][C] = {t:'b', v:true};
else if(m === 'FALSE') ws[R][C] = {t:'b', v:false}; else if(m === 'FALSE') ws[R][C] = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)}; else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)};
@ -16706,6 +16742,7 @@ var HTML_ = (function() {
/* TODO: value parsing */ /* TODO: value parsing */
if(!m.length){} if(!m.length){}
else if(opts.raw) ws[coord] = {t:'s', v:m}; else if(opts.raw) ws[coord] = {t:'s', v:m};
else if(opts.raw || !m.trim().length) ws[coord] = {t:'s', v:m};
else if(m === 'TRUE') ws[coord] = {t:'b', v:true}; else if(m === 'TRUE') ws[coord] = {t:'b', v:true};
else if(m === 'FALSE') ws[coord] = {t:'b', v:false}; else if(m === 'FALSE') ws[coord] = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) ws[coord] = {t:'n', v:fuzzynum(m)}; else if(!isNaN(fuzzynum(m))) ws[coord] = {t:'n', v:fuzzynum(m)};
@ -16790,7 +16827,7 @@ function parse_dom_table(table, _opts) {
var row = rows[R]; var row = rows[R];
var elts = row.children; var elts = row.children;
for(_C = C = 0; _C < elts.length; ++_C) { for(_C = C = 0; _C < elts.length; ++_C) {
var elt = elts[_C], v = elts[_C].innerText || elts[_C].textContent || ""; var elt = elts[_C], v = htmldecode(elts[_C].innerHTML);
for(midx = 0; midx < merges.length; ++midx) { for(midx = 0; midx < merges.length; ++midx) {
var m = merges[midx]; var m = merges[midx];
if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; } if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; }
@ -16802,6 +16839,7 @@ function parse_dom_table(table, _opts) {
if(v != null) { if(v != null) {
if(v.length == 0) o.t = 'z'; if(v.length == 0) o.t = 'z';
else if(opts.raw){} else if(opts.raw){}
else if(v.trim().length == 0) o.t = 's';
else if(v === 'TRUE') o = {t:'b', v:true}; else if(v === 'TRUE') o = {t:'b', v:true};
else if(v === 'FALSE') o = {t:'b', v:false}; else if(v === 'FALSE') o = {t:'b', v:false};
else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)}; else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
@ -17291,7 +17329,9 @@ function parse_ods(zip, opts) {
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts); if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
var content = getzipstr(zip, 'content.xml'); var content = getzipstr(zip, 'content.xml');
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file"); if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
return parse_content_xml(ods ? content : utf8read(content), opts); var wb = parse_content_xml(ods ? content : utf8read(content), opts);
if(safegetzipfile(zip, 'meta.xml')) wb.Props = parse_core_props(getzipdata(zip, 'meta.xml'));
return wb;
} }
function parse_fods(data, opts) { function parse_fods(data, opts) {
return parse_content_xml(data, opts); return parse_content_xml(data, opts);
@ -17558,8 +17598,7 @@ function get_sheet_type(n) {
if(RELS.CS && n == RELS.CS) return "chart"; if(RELS.CS && n == RELS.CS) return "chart";
if(RELS.DS && n == RELS.DS) return "dialog"; if(RELS.DS && n == RELS.DS) return "dialog";
if(RELS.MS && n == RELS.MS) return "macro"; if(RELS.MS && n == RELS.MS) return "macro";
if(!n || !n.length) return "sheet"; return (n && n.length) ? n : "sheet";
return n;
} }
function safe_parse_wbrels(wbrels, sheets) { function safe_parse_wbrels(wbrels, sheets) {
if(!wbrels) return 0; if(!wbrels) return 0;
@ -17643,10 +17682,10 @@ function parse_zip(zip, opts) {
var props = {}, propdata = ""; var props = {}, propdata = "";
if(dir.coreprops.length) { if(dir.coreprops.length) {
propdata = getzipstr(zip, strip_front_slash(dir.coreprops[0]), true); propdata = getzipdata(zip, strip_front_slash(dir.coreprops[0]), true);
if(propdata) props = parse_core_props(propdata); if(propdata) props = parse_core_props(propdata);
if(dir.extprops.length !== 0) { if(dir.extprops.length !== 0) {
propdata = getzipstr(zip, strip_front_slash(dir.extprops[0]), true); propdata = getzipdata(zip, strip_front_slash(dir.extprops[0]), true);
if(propdata) parse_ext_props(propdata, props, opts); if(propdata) parse_ext_props(propdata, props, opts);
} }
} }
@ -17952,13 +17991,23 @@ function read_utf16(data, o) {
return read_plaintext(d, o); return read_plaintext(d, o);
} }
function bstrify(data) {
return !data.match(/[^\x00-\x7F]/) ? data : utf8write(data);
}
function read_prn(data, d, o, str) {
if(str) { o.type = "string"; return PRN.to_workbook(data, o); }
return PRN.to_workbook(d, o);
}
function readSync(data, opts) { function readSync(data, opts) {
var zip, d = data, n=[0]; var zip, d = data, n=[0], str = false;
var o = opts||{}; var o = opts||{};
_ssfopts = {}; _ssfopts = {};
if(o.dateNF) _ssfopts.dateNF = o.dateNF; if(o.dateNF) _ssfopts.dateNF = o.dateNF;
if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64"; if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
if(o.type == "file") { o.type = "buffer"; d = _fs.readFileSync(data); } if(o.type == "file") { o.type = "buffer"; d = _fs.readFileSync(data); }
if(o.type == "string") { str = true; o.type = "binary"; d = bstrify(data); }
switch((n = firstbyte(d, o))[0]) { switch((n = firstbyte(d, o))[0]) {
case 0xD0: return read_cfb(CFB.read(d, o), o); case 0xD0: return read_cfb(CFB.read(d, o), o);
case 0x09: return parse_xlscfb(d, o); case 0x09: return parse_xlscfb(d, o);
@ -17966,7 +18015,7 @@ function readSync(data, opts) {
case 0x49: if(n[1] == 0x44) return read_wb_ID(d, o); break; case 0x49: if(n[1] == 0x44) return read_wb_ID(d, o); break;
case 0x54: if(n[1] == 0x41 && n[2] == 0x42 && n[3] == 0x4C) return DIF.to_workbook(d, o); break; case 0x54: if(n[1] == 0x41 && n[2] == 0x42 && n[3] == 0x4C) return DIF.to_workbook(d, o); break;
case 0x50: if(n[1] == 0x4B && n[2] < 0x20 && n[3] < 0x20) return read_zip(d, o); break; case 0x50: if(n[1] == 0x4B && n[2] < 0x20 && n[3] < 0x20) return read_zip(d, o); break;
case 0xEF: return n[3] == 0x3C ? parse_xlml(d, o) : PRN.to_workbook(d,o); case 0xEF: return n[3] == 0x3C ? parse_xlml(d, o) : read_prn(data, d, o, str);
case 0xFF: if(n[1] == 0xFE){ return read_utf16(d, o); } break; case 0xFF: if(n[1] == 0xFE){ return read_utf16(d, o); } break;
case 0x00: if(n[1] == 0x00 && n[2] >= 0x02 && n[3] == 0x00) return WK_.to_workbook(d, o); break; case 0x00: if(n[1] == 0x00 && n[2] >= 0x02 && n[3] == 0x00) return WK_.to_workbook(d, o); break;
case 0x03: case 0x83: case 0x8B: return DBF.to_workbook(d, o); case 0x03: case 0x83: case 0x8B: return DBF.to_workbook(d, o);
@ -17975,7 +18024,7 @@ function readSync(data, opts) {
} }
if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o); if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
if(0x20>n[0]||n[0]>0x7F) throw new Error("Unsupported file " + n.join("|")); if(0x20>n[0]||n[0]>0x7F) throw new Error("Unsupported file " + n.join("|"));
return PRN.to_workbook(d, o); return read_prn(data, d, o, str);
} }
function readFileSync(filename, opts) { function readFileSync(filename, opts) {
@ -17990,12 +18039,15 @@ function write_zip_type(wb, opts) {
switch(o.type) { switch(o.type) {
case "base64": oopts.type = "base64"; break; case "base64": oopts.type = "base64"; break;
case "binary": oopts.type = "string"; break; case "binary": oopts.type = "string"; break;
case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
case "buffer": case "buffer":
case "file": oopts.type = "nodebuffer"; break; case "file": oopts.type = "nodebuffer"; break;
default: throw new Error("Unrecognized type " + o.type); default: throw new Error("Unrecognized type " + o.type);
} }
if(o.type === "file") return _fs.writeFileSync(o.file, z.generate(oopts)); if(o.type === "file") return _fs.writeFileSync(o.file, z.generate(oopts));
return z.generate(oopts); var out = z.generate(oopts);
// $FlowIgnore
return o.type == "string" ? utf8read(out) : out;
} }
function write_cfb_type(wb, opts) { function write_cfb_type(wb, opts) {
@ -18005,16 +18057,33 @@ function write_cfb_type(wb, opts) {
case "base64": case "binary": break; case "base64": case "binary": break;
case "buffer": case "array": o.type = ""; break; case "buffer": case "array": o.type = ""; break;
case "file": return _fs.writeFileSync(o.file, CFB.write(cfb, {type:'buffer'})); case "file": return _fs.writeFileSync(o.file, CFB.write(cfb, {type:'buffer'}));
case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
default: throw new Error("Unrecognized type " + o.type); default: throw new Error("Unrecognized type " + o.type);
} }
return CFB.write(cfb, o); return CFB.write(cfb, o);
} }
/* TODO: test consistency */ function write_string_type(out, opts, bom) {
function write_bstr_type(out, opts) { if(!bom) bom = "";
var o = bom + out;
switch(opts.type) {
case "base64": return Base64.encode(utf8write(o));
case "binary": return utf8write(o);
case "string": return out;
case "file": return _fs.writeFileSync(opts.file, o, 'utf8');
case "buffer": {
if(has_buf) return new Buffer(o, 'utf8');
else return write_string_type(o, {type:'binary'}).split("").map(function(c) { return c.charCodeAt(0); });
}
}
throw new Error("Unrecognized type " + opts.type);
}
function write_stxt_type(out, opts) {
switch(opts.type) { switch(opts.type) {
case "base64": return Base64.encode(out); case "base64": return Base64.encode(out);
case "binary": return out; case "binary": return out;
case "string": return out; /* override in sheet_to_txt */
case "file": return _fs.writeFileSync(opts.file, out, 'binary'); case "file": return _fs.writeFileSync(opts.file, out, 'binary');
case "buffer": { case "buffer": {
if(has_buf) return new Buffer(out, 'binary'); if(has_buf) return new Buffer(out, 'binary');
@ -18024,28 +18093,15 @@ function write_bstr_type(out, opts) {
throw new Error("Unrecognized type " + opts.type); throw new Error("Unrecognized type " + opts.type);
} }
/* TODO: test consistency */
function write_string_type(out, opts) {
switch(opts.type) {
case "base64": return Base64.encode(out);
case "binary": return out;
case "file": return _fs.writeFileSync(opts.file, out, 'utf8');
case "buffer": {
if(has_buf) return new Buffer(out, 'utf8');
else return out.split("").map(function(c) { return c.charCodeAt(0); });
}
}
throw new Error("Unrecognized type " + opts.type);
}
/* TODO: test consistency */ /* TODO: test consistency */
function write_binary_type(out, opts) { function write_binary_type(out, opts) {
switch(opts.type) { switch(opts.type) {
case "string":
case "base64": case "base64":
case "binary": case "binary":
var bstr = ""; var bstr = "";
for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]); for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]);
return opts.type == 'base64' ? Base64.encode(bstr) : bstr; return opts.type == 'base64' ? Base64.encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr;
case "file": return _fs.writeFileSync(opts.file, out); case "file": return _fs.writeFileSync(opts.file, out);
case "buffer": return out; case "buffer": return out;
default: throw new Error("Unrecognized type " + opts.type); default: throw new Error("Unrecognized type " + opts.type);
@ -18061,14 +18117,14 @@ function writeSync(wb, opts) {
case 'slk': case 'slk':
case 'sylk': return write_string_type(write_slk_str(wb, o), o); case 'sylk': return write_string_type(write_slk_str(wb, o), o);
case 'html': return write_string_type(write_htm_str(wb, o), o); case 'html': return write_string_type(write_htm_str(wb, o), o);
case 'txt': return write_bstr_type(write_txt_str(wb, o), o); case 'txt': return write_stxt_type(write_txt_str(wb, o), o);
case 'csv': return write_string_type(write_csv_str(wb, o), o); case 'csv': return write_string_type(write_csv_str(wb, o), o, "\ufeff");
case 'dif': return write_string_type(write_dif_str(wb, o), o); case 'dif': return write_string_type(write_dif_str(wb, o), o);
case 'prn': return write_string_type(write_prn_str(wb, o), o); case 'prn': return write_string_type(write_prn_str(wb, o), o);
case 'rtf': return write_string_type(write_rtf_str(wb, o), o); case 'rtf': return write_string_type(write_rtf_str(wb, o), o);
case 'fods': return write_string_type(write_ods(wb, o), o); case 'fods': return write_string_type(write_ods(wb, o), o);
case 'biff2': if(!o.biff) o.biff = 2; return write_binary_type(write_biff_buf(wb, o), o); case 'biff2': if(!o.biff) o.biff = 2; /* falls through */
case 'biff3': if(!o.biff) o.biff = 3; return write_binary_type(write_biff_buf(wb, o), o); case 'biff3': if(!o.biff) o.biff = 3; /* falls through */
case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o); case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o);
case 'biff5': if(!o.biff) o.biff = 5; return write_cfb_type(wb, o); case 'biff5': if(!o.biff) o.biff = 5; return write_cfb_type(wb, o);
case 'biff8': case 'biff8':
@ -18249,8 +18305,8 @@ function sheet_to_csv(sheet, opts) {
function sheet_to_txt(sheet, opts) { function sheet_to_txt(sheet, opts) {
if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n"; if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n";
var s = sheet_to_csv(sheet, opts); var s = sheet_to_csv(sheet, opts);
if(typeof cptable == 'undefined') return s; if(typeof cptable == 'undefined' || opts.type == 'string') return s;
var o = cptable.utils.encode(1200, s); var o = cptable.utils.encode(1200, s, 'str');
return "\xff\xfe" + o; return "\xff\xfe" + o;
} }

24
dist/xlsx.min.js vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.min.map vendored

File diff suppressed because one or more lines are too long

@ -6,6 +6,9 @@ data and feeding it into the library. Here are a few common scenarios:
<details> <details>
<summary><b>nodejs read a file</b> (click to show)</summary> <summary><b>nodejs read a file</b> (click to show)</summary>
`readFile` is only available in server environments. Browsers have no API for
reading arbitrary files given a path, so another strategy must be used.
```js ```js
if(typeof require !== 'undefined') XLSX = require('xlsx'); if(typeof require !== 'undefined') XLSX = require('xlsx');
var workbook = XLSX.readFile('test.xlsx'); var workbook = XLSX.readFile('test.xlsx');
@ -17,11 +20,21 @@ var workbook = XLSX.readFile('test.xlsx');
<details> <details>
<summary><b>Browser read TABLE element from page</b> (click to show)</summary> <summary><b>Browser read TABLE element from page</b> (click to show)</summary>
The `table_to_book` and `table_to_sheet` utility functions take a DOM TABLE
element and iterate through the child nodes.
```js ```js
var worksheet = XLSX.utils.table_to_book(document.getElementById('tableau')); var worksheet = XLSX.utils.table_to_book(document.getElementById('tableau'));
/* DO SOMETHING WITH workbook HERE */ /* DO SOMETHING WITH workbook HERE */
``` ```
Alternatively, the HTML code can be extracted and parsed:
```js
var htmlstr = document.getElementById('tableau').outerHTML;
var worksheet = XLSX.read(htmlstr, {type:'string'});
```
</details> </details>
<details> <details>

@ -8,16 +8,35 @@ Assuming `workbook` is a workbook object:
<details> <details>
<summary><b>nodejs write a file</b> (click to show)</summary> <summary><b>nodejs write a file</b> (click to show)</summary>
`writeFile` is only available in server environments. Browsers have no API for
writing arbitrary files given a path, so another strategy must be used.
```js ```js
if(typeof require !== 'undefined') XLSX = require('xlsx');
/* output format determined by filename */ /* output format determined by filename */
XLSX.writeFile(workbook, 'out.xlsx'); XLSX.writeFile(workbook, 'out.xlsb');
/* at this point, out.xlsx is a file that you can distribute */ /* at this point, out.xlsb is a file that you can distribute */
``` ```
</details> </details>
<details> <details>
<summary><b>Browser download file</b> (click to show)</summary> <summary><b>Browser add to web page</b> (click to show)</summary>
The `sheet_to_html` utility function generates HTML code that can be added to
any DOM element.
```js
var worksheet = workbook.Sheets[workbook.SheetNames[0]];
var container = document.getElementById('tableau');
container.innerHTML = XLSX.utils.sheet_to_html(worksheet);
```
</details>
<details>
<summary><b>Browser save file</b> (click to show)</summary>
Note: browser generates binary blob and forces a "download" to client. This Note: browser generates binary blob and forces a "download" to client. This
example uses [FileSaver](https://github.com/eligrey/FileSaver.js/): example uses [FileSaver](https://github.com/eligrey/FileSaver.js/):
@ -38,6 +57,7 @@ function s2ab(s) {
/* the saveAs call downloads a file on the local machine */ /* the saveAs call downloads a file on the local machine */
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx"); saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx");
``` ```
</details> </details>
<details> <details>

@ -52,6 +52,7 @@ tells the library how to parse the data argument:
|------------|-----------------------------------------------------------------| |------------|-----------------------------------------------------------------|
| `"base64"` | string: Base64 encoding of the file | | `"base64"` | string: Base64 encoding of the file |
| `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) | | `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) |
| `"string"` | string: JS string (characters interpreted as UTF8) |
| `"buffer"` | nodejs Buffer | | `"buffer"` | nodejs Buffer |
| `"array"` | array: array of 8-bit unsigned int (byte `n` is `data[n]`) | | `"array"` | array: array of 8-bit unsigned int (byte `n` is `data[n]`) |
| `"file"` | string: path of file that will be read (nodejs only) | | `"file"` | string: path of file that will be read (nodejs only) |

@ -62,7 +62,7 @@ The `type` argument for `write` mirrors the `type` argument for `read`:
|------------|-----------------------------------------------------------------| |------------|-----------------------------------------------------------------|
| `"base64"` | string: Base64 encoding of the file | | `"base64"` | string: Base64 encoding of the file |
| `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) | | `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) |
| `"string"` | string: JS string (characters interpreted as UTF8) |
| `"buffer"` | nodejs Buffer | | `"buffer"` | nodejs Buffer |
| `"file"` | string: path of file that will be created (nodejs only) | | `"file"` | string: path of file that will be created (nodejs only) |

@ -277,6 +277,9 @@ For parsing, the first step is to read the file. This involves acquiring the
data and feeding it into the library. Here are a few common scenarios: data and feeding it into the library. Here are a few common scenarios:
`readFile` is only available in server environments. Browsers have no API for
reading arbitrary files given a path, so another strategy must be used.
```js ```js
if(typeof require !== 'undefined') XLSX = require('xlsx'); if(typeof require !== 'undefined') XLSX = require('xlsx');
var workbook = XLSX.readFile('test.xlsx'); var workbook = XLSX.readFile('test.xlsx');
@ -285,11 +288,21 @@ var workbook = XLSX.readFile('test.xlsx');
The `table_to_book` and `table_to_sheet` utility functions take a DOM TABLE
element and iterate through the child nodes.
```js ```js
var worksheet = XLSX.utils.table_to_book(document.getElementById('tableau')); var worksheet = XLSX.utils.table_to_book(document.getElementById('tableau'));
/* DO SOMETHING WITH workbook HERE */ /* DO SOMETHING WITH workbook HERE */
``` ```
Alternatively, the HTML code can be extracted and parsed:
```js
var htmlstr = document.getElementById('tableau').outerHTML;
var worksheet = XLSX.read(htmlstr, {type:'string'});
```
Note: for a more complete example that works in older browsers, check the demo Note: for a more complete example that works in older browsers, check the demo
@ -516,14 +529,30 @@ dissemination. The second step is to actual share the data with the end point.
Assuming `workbook` is a workbook object: Assuming `workbook` is a workbook object:
`writeFile` is only available in server environments. Browsers have no API for
writing arbitrary files given a path, so another strategy must be used.
```js ```js
if(typeof require !== 'undefined') XLSX = require('xlsx');
/* output format determined by filename */ /* output format determined by filename */
XLSX.writeFile(workbook, 'out.xlsx'); XLSX.writeFile(workbook, 'out.xlsb');
/* at this point, out.xlsx is a file that you can distribute */ /* at this point, out.xlsb is a file that you can distribute */
``` ```
The `sheet_to_html` utility function generates HTML code that can be added to
any DOM element.
```js
var worksheet = workbook.Sheets[workbook.SheetNames[0]];
var container = document.getElementById('tableau');
container.innerHTML = XLSX.utils.sheet_to_html(worksheet);
```
Note: browser generates binary blob and forces a "download" to client. This Note: browser generates binary blob and forces a "download" to client. This
example uses [FileSaver](https://github.com/eligrey/FileSaver.js/): example uses [FileSaver](https://github.com/eligrey/FileSaver.js/):
@ -545,6 +574,7 @@ saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx");
``` ```
A complete example using XHR is [included in the XHR demo](demos/xhr/), along A complete example using XHR is [included in the XHR demo](demos/xhr/), along
with examples for fetch and wrapper libraries. This example assumes the server with examples for fetch and wrapper libraries. This example assumes the server
can handle Base64-encoded files (see the demo for a basic nodejs server): can handle Base64-encoded files (see the demo for a basic nodejs server):
@ -1325,6 +1355,7 @@ tells the library how to parse the data argument:
|------------|-----------------------------------------------------------------| |------------|-----------------------------------------------------------------|
| `"base64"` | string: Base64 encoding of the file | | `"base64"` | string: Base64 encoding of the file |
| `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) | | `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) |
| `"string"` | string: JS string (characters interpreted as UTF8) |
| `"buffer"` | nodejs Buffer | | `"buffer"` | nodejs Buffer |
| `"array"` | array: array of 8-bit unsigned int (byte `n` is `data[n]`) | | `"array"` | array: array of 8-bit unsigned int (byte `n` is `data[n]`) |
| `"file"` | string: path of file that will be read (nodejs only) | | `"file"` | string: path of file that will be read (nodejs only) |
@ -1451,10 +1482,10 @@ The `type` argument for `write` mirrors the `type` argument for `read`:
|------------|-----------------------------------------------------------------| |------------|-----------------------------------------------------------------|
| `"base64"` | string: Base64 encoding of the file | | `"base64"` | string: Base64 encoding of the file |
| `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) | | `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) |
| `"string"` | string: JS string (characters interpreted as UTF8) |
| `"buffer"` | nodejs Buffer | | `"buffer"` | nodejs Buffer |
| `"file"` | string: path of file that will be created (nodejs only) | | `"file"` | string: path of file that will be created (nodejs only) |
## Utility Functions ## Utility Functions
The `sheet_to_*` functions accept a worksheet and an optional options object. The `sheet_to_*` functions accept a worksheet and an optional options object.

@ -42,11 +42,15 @@ type SSFModule = {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Note: The following override is needed because ReadShift includes more cases // Note: The following override is needed because ReadShift includes more cases
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
type ReadShiftFunc = any;
type WriteShiftFunc = any;
type CFBModule = { type CFBModule = {
version:string; version:string;
find:(cfb:CFBContainer, path:string)=>?CFBEntry; find:(cfb:CFBContainer, path:string)=>?CFBEntry;
read:(blob:RawBytes|string, opts:CFBReadOpts)=>CFBContainer; read:(blob:RawBytes|string, opts:CFBReadOpts)=>CFBContainer;
write:(cfb:CFBContainer, opts:CFBWriteOpts)=>RawBytes|string;
writeFile:(cfb:CFBContainer, filename:string, opts:CFBWriteOpts)=>void;
parse:(file:RawBytes, opts:CFBReadOpts)=>CFBContainer; parse:(file:RawBytes, opts:CFBReadOpts)=>CFBContainer;
utils:CFBUtils; utils:CFBUtils;
}; };
@ -63,18 +67,21 @@ type RawBytes = Array<number> | Buffer | Uint8Array;
class CFBlobArray extends Array<number> { class CFBlobArray extends Array<number> {
l:number; l:number;
write_shift:WriteShiftFunc;
read_shift:ReadShiftFunc; read_shift:ReadShiftFunc;
chk:CheckFieldFunc; chk:CheckFieldFunc;
}; };
interface CFBlobBuffer extends Buffer { interface CFBlobBuffer extends Buffer {
l:number; l:number;
slice:(start:number, end:?number)=>Buffer; slice:(start?:number, end:?number)=>Buffer;
write_shift:WriteShiftFunc;
read_shift:ReadShiftFunc; read_shift:ReadShiftFunc;
chk:CheckFieldFunc; chk:CheckFieldFunc;
}; };
interface CFBlobUint8 extends Uint8Array { interface CFBlobUint8 extends Uint8Array {
l:number; l:number;
slice:(start:number, end:?number)=>Uint8Array; slice:(start?:number, end:?number)=>Uint8Array;
write_shift:WriteShiftFunc;
read_shift:ReadShiftFunc; read_shift:ReadShiftFunc;
chk:CheckFieldFunc; chk:CheckFieldFunc;
}; };
@ -83,13 +90,16 @@ interface CFBlobber {
[n:number]:number; [n:number]:number;
l:number; l:number;
length:number; length:number;
slice:(start:number, end:?number)=>RawBytes; slice:(start:?number, end:?number)=>RawBytes;
write_shift:WriteShiftFunc;
read_shift:ReadShiftFunc; read_shift:ReadShiftFunc;
chk:CheckFieldFunc; chk:CheckFieldFunc;
}; };
type CFBlob = CFBlobArray | CFBlobBuffer | CFBlobUint8; type CFBlob = CFBlobArray | CFBlobBuffer | CFBlobUint8;
type CFBWriteOpts = any;
interface CFBReadOpts { interface CFBReadOpts {
type?:string; type?:string;
}; };
@ -99,14 +109,13 @@ type CFBFileIndex = Array<CFBEntry>;
type CFBFindPath = (n:string)=>?CFBEntry; type CFBFindPath = (n:string)=>?CFBEntry;
type CFBContainer = { type CFBContainer = {
raw:{ raw?:{
header:any; header:any;
sectors:Array<any>; sectors:Array<any>;
}; };
FileIndex:CFBFileIndex; FileIndex:CFBFileIndex;
FullPathDir:CFBDirectory; FullPathDir:CFBFullPathDir;
FullPaths:Array<string>; FullPaths:Array<string>;
find:CFBFindPath;
} }
type CFBEntry = { type CFBEntry = {

@ -1,6 +1,6 @@
{ {
"name": "xlsx", "name": "xlsx",
"version": "0.11.4", "version": "0.11.5",
"author": "sheetjs", "author": "sheetjs",
"description": "Excel (XLSB/XLSX/XLS/XML) ODS and other spreadsheet format (CSV/DIF/DBF/SYLK) parser and writer", "description": "Excel (XLSB/XLSX/XLS/XML) ODS and other spreadsheet format (CSV/DIF/DBF/SYLK) parser and writer",
"keywords": [ "excel", "xls", "xlsx", "xlsb", "xlsm", "ods", "csv", "dbf", "dif", "sylk", "office", "spreadsheet" ], "keywords": [ "excel", "xls", "xlsx", "xlsb", "xlsm", "ods", "csv", "dbf", "dif", "sylk", "office", "spreadsheet" ],

11
shim.js

@ -330,3 +330,14 @@ if (!Date.prototype.toISOString) {
}()); }());
} }
// note: MDN shim will not work in IE
if(typeof Uint8Array !== 'undefined' && !Uint8Array.prototype.slice) Uint8Array.prototype.slice = function(start, end) {
if(start < 0) { start += this.length; if(start < 0) start = 0; }
if(start >= this.length) return new Uint8Array(0);
if(end == null) end = this.length;
if(end < 0) { end += this.length; if(end < 0) end = 0; }
if(end > this.length) end = this.length;
var out = new Uint8Array(end - start);
while(start <= --end) out[end - start] = this[end];
return out;
};

457
test.js

@ -1,5 +1,6 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */ /* vim: set ts=2: */
/*jshint loopfunc:true, eqnull:true */ /*jshint -W069, loopfunc:true, mocha:true */
var X; var X;
var modp = './'; var modp = './';
//var modp = 'xlsx'; //var modp = 'xlsx';
@ -7,7 +8,7 @@ var fs = require('fs'), assert = require('assert');
describe('source',function(){it('should load',function(){X=require(modp);});}); describe('source',function(){it('should load',function(){X=require(modp);});});
var DIF_XL = true; var DIF_XL = true;
var browser = false; var browser = typeof document !== 'undefined';
var opts = {cellNF: true}; var opts = {cellNF: true};
var TYPE = browser ? "binary" : "buffer"; var TYPE = browser ? "binary" : "buffer";
@ -36,15 +37,48 @@ function fixjson(x) { return x.replace(/[\r\n]+$/,""); }
var dir = "./test_files/"; var dir = "./test_files/";
var dirwp = dir + "artifacts/wps/", dirqp = dir + "artifacts/quattro/";
var paths = { var paths = {
afxls: dir + 'AutoFilter.xls', aadbf: dirwp + 'write.dbf',
afxml: dir + 'AutoFilter.xml', aadif: dirwp + 'write.dif',
afods: dir + 'AutoFilter.ods', aaxls: dirwp + 'write.xls',
aaxlsx: dirwp + 'write.xlsx',
aaxml: dirwp + 'write.xml',
abcsv: dirqp + 'write_.csv',
abdif: dirqp + 'write_.dif',
abslk: dirqp + 'write_.slk',
abx57: dirqp + 'write_57.xls',
abwb2: dirqp + 'write_6.wb2',
abwb2b: dirqp + 'write_6b.wb2',
abwb3: dirqp + 'write_8.wb3',
abqpw: dirqp + 'write_9.qpw',
abx97: dirqp + 'write_97.xls',
abwks: dirqp + 'write_L1.wks',
abwk1: dirqp + 'write_L2.wk1',
abwk3: dirqp + 'write_L3.wk3',
abwk4: dirqp + 'write_L45.wk4',
ab123: dirqp + 'write_L9.123',
ab124: dirqp + 'write_L97.123',
abwke2: dirqp + 'write_Led.wke',
abwq1: dirqp + 'write_qpdos.wq1',
abwb1: dirqp + 'write_qpw.wb1',
afxls: dir + 'AutoFilter.xls',
afxml: dir + 'AutoFilter.xml',
afods: dir + 'AutoFilter.ods',
afxlsx: dir + 'AutoFilter.xlsx', afxlsx: dir + 'AutoFilter.xlsx',
afxlsb: dir + 'AutoFilter.xlsb', afxlsb: dir + 'AutoFilter.xlsb',
cpxls: dir + 'custom_properties.xls', asxls: dir + 'author_snowman.xls',
cpxml: dir + 'custom_properties.xls.xml', asxls5: dir + 'author_snowman.xls5',
asxml: dir + 'author_snowman.xml',
asods: dir + 'author_snowman.ods',
asxlsx: dir + 'author_snowman.xlsx',
asxlsb: dir + 'author_snowman.xlsb',
cpxls: dir + 'custom_properties.xls',
cpxml: dir + 'custom_properties.xls.xml',
cpxlsx: dir + 'custom_properties.xlsx', cpxlsx: dir + 'custom_properties.xlsx',
cpxlsb: dir + 'custom_properties.xlsb', cpxlsb: dir + 'custom_properties.xlsb',
@ -226,19 +260,19 @@ function parsetest(x, wb, full, ext) {
if(fs.existsSync(dir + '2011/' + x + '.xml')) if(fs.existsSync(dir + '2011/' + x + '.xml'))
describe(x + ext + '.xml from 2011', function() { describe(x + ext + '.xml from 2011', function() {
it('should parse', function() { it('should parse', function() {
var wb = X.readFile(dir + '2011/' + x + '.xml', opts); /*var wb = */X.readFile(dir + '2011/' + x + '.xml', opts);
}); });
}); });
if(fs.existsSync(dir + '2013/' + x + '.xlsb')) if(fs.existsSync(dir + '2013/' + x + '.xlsb'))
describe(x + ext + '.xlsb from 2013', function() { describe(x + ext + '.xlsb from 2013', function() {
it('should parse', function() { it('should parse', function() {
var wb = X.readFile(dir + '2013/' + x + '.xlsb', opts); /*var wb = */X.readFile(dir + '2013/' + x + '.xlsb', opts);
}); });
}); });
if(fs.existsSync(dir + x + '.xml' + ext)) if(fs.existsSync(dir + x + '.xml' + ext))
describe(x + '.xml', function() { describe(x + '.xml', function() {
it('should parse', function() { it('should parse', function() {
var wb = X.readFile(dir + x + '.xml', opts); /*var wb = */X.readFile(dir + x + '.xml', opts);
}); });
}); });
} }
@ -553,121 +587,94 @@ describe('parse options', function() {
}); });
describe('input formats', function() { describe('input formats', function() {
var _paths = [
"cstods", "cstxls", "cstxlsb", "cstxlsb", "cstxml", "aadbf", "aadif",
"aaxls", "aaxml", "aaxlsx", "ab123", "ab124", "abcsv", "abdif", "abqpw",
"abslk", "abwb1", "abwb2", "abwb3", "abwk1", "abwk3", "abwk4", "abwks",
"abwq1", "abx57", "abx97", "abwke2", "abwb2b"
].map(function(x) { return paths[x]; });
it('should read binary strings', function() { it('should read binary strings', function() {
X.read(fs.readFileSync(paths.cstxlsx, 'binary'), {type: 'binary'}); _paths.forEach(function(pth) {
X.read(fs.readFileSync(paths.cstxlsb, 'binary'), {type: 'binary'}); X.read(fs.readFileSync(pth, 'binary'), {type: 'binary'});
X.read(fs.readFileSync(paths.cstxls, 'binary'), {type: 'binary'}); });
X.read(fs.readFileSync(paths.cstxml, 'binary'), {type: 'binary'});
X.read(fs.readFileSync(paths.cstods, 'binary'), {type: 'binary'});
}); });
it('should read base64 strings', function() { it('should read base64 strings', function() {
X.read(fs.readFileSync(paths.cstxls, 'base64'), {type: 'base64'}); _paths.forEach(function(pth) {
X.read(fs.readFileSync(paths.cstxml, 'base64'), {type: 'base64'}); X.read(fs.readFileSync(pth, 'base64'), {type: 'base64'});
X.read(fs.readFileSync(paths.cstods, 'base64'), {type: 'base64'}); });
X.read(fs.readFileSync(paths.cstxlsx, 'base64'), {type: 'base64'});
X.read(fs.readFileSync(paths.cstxlsb, 'base64'), {type: 'base64'});
}); });
var k = browser ? 'array' : 'buffer'; var k = browser ? 'array' : 'buffer';
(typeof Uint8Array !== 'undefined' ? it : it.skip)('should read ' + k + 's', function() { (typeof Uint8Array !== 'undefined' ? it : it.skip)('should read ' + k + 's', function() {
X.read(fs.readFileSync(paths.cstxls, browser ? 'buffer' : null), {type: k}); _paths.forEach(function(pth) {
X.read(fs.readFileSync(paths.cstxml, browser ? 'buffer' : null), {type: k}); X.read(fs.readFileSync(pth, browser ? 'buffer' : null), {type: k});
X.read(fs.readFileSync(paths.cstods, browser ? 'buffer' : null), {type: k}); });
X.read(fs.readFileSync(paths.cstxlsx, browser ? 'buffer' : null), {type: k});
X.read(fs.readFileSync(paths.cstxlsb, browser ? 'buffer' : null), {type: k});
}); });
(typeof Uint8Array !== 'undefined' ? it : it.skip)('should read array', function() { (typeof Uint8Array !== 'undefined' ? it : it.skip)('should read array', function() {
X.read(fs.readFileSync(paths.cstxls, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'}); _paths.forEach(function(pth) {
X.read(fs.readFileSync(paths.cstxml, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'}); X.read(fs.readFileSync(pth, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
X.read(fs.readFileSync(paths.cstxlsx, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'}); });
X.read(fs.readFileSync(paths.cstxlsb, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
X.read(fs.readFileSync(paths.cstods, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
}); });
it('should throw if format is unknown', function() { it('should throw if format is unknown', function() {
assert.throws(function() { X.read(fs.readFileSync(paths.cstxls), {type: 'dafuq'}); }); _paths.forEach(function(pth) {
assert.throws(function() { X.read(fs.readFileSync(paths.cstxml), {type: 'dafuq'}); }); assert.throws(function() { X.read(fs.readFileSync(pth), {type: 'dafuq'}); });
assert.throws(function() { X.read(fs.readFileSync(paths.cstods), {type: 'dafuq'}); }); });
assert.throws(function() { X.read(fs.readFileSync(paths.cstxlsx), {type: 'dafuq'}); });
assert.throws(function() { X.read(fs.readFileSync(paths.cstxlsb), {type: 'dafuq'}); });
}); });
if(browser) it('should default to base64 type', function() { if(browser) it('should default to base64 type', function() {
X.read(fs.readFileSync(paths.cstxls, 'base64')); _paths.forEach(function(pth) {
X.read(fs.readFileSync(paths.cstxml, 'base64')); X.read(fs.readFileSync(pth, 'base64'));
X.read(fs.readFileSync(paths.cstods, 'base64')); });
X.read(fs.readFileSync(paths.cstxlsx, 'base64'));
X.read(fs.readFileSync(paths.cstxlsb, 'base64'));
}); });
else { else {
it('should infer buffer type', function() { it('should infer buffer type', function() {
X.read(fs.readFileSync(paths.cstxls)); _paths.forEach(function(pth) {
X.read(fs.readFileSync(paths.cstxml)); X.read(fs.readFileSync(pth));
X.read(fs.readFileSync(paths.cstods)); });
X.read(fs.readFileSync(paths.cstxlsx));
X.read(fs.readFileSync(paths.cstxlsb));
}); });
it('should read files', function() { it('should read files', function() {
X.readFile(paths.cstxls); _paths.forEach(function(pth) {
X.readFile(paths.cstxml); X.readFile(pth);
X.readFile(paths.cstods); });
X.readFile(paths.cstxlsx);
X.readFile(paths.cstxlsb);
}); });
} }
}); });
describe('output formats', function() { describe('output formats', function() {
var wb1, wb2, wb3, wb4; var fmts = [
var bef = (function() { /* fmt unicode str */
X = require(modp); ["xlsx", true, false],
wb1 = X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE}); ["xlsb", true, false],
wb2 = X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE}); ["xls", true, false],
wb3 = X.read(fs.readFileSync(paths.cpxls), {type:TYPE}); ["xlml", true, true],
wb4 = X.read(fs.readFileSync(paths.cpxml), {type:TYPE}); ["ods", true, false],
}); ["fods", true, true],
if(typeof before != 'undefined') before(bef); ["csv", true, true],
else it('before', bef); ["txt", true, true],
it('should write binary strings', function() { ["sylk", false, true],
if(!wb1) { ["html", true, true],
wb1 = X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE}); ["dif", false, true],
wb2 = X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE}); ["prn", false, true]
wb3 = X.read(fs.readFileSync(paths.cpxls), {type:TYPE}); ];
wb4 = X.read(fs.readFileSync(paths.cpxml), {type:TYPE}); function RT(T) {
} if(!X) X = require(modp);
X.write(wb1, {type: 'binary'}); fmts.forEach(function(fmt) {
X.write(wb2, {type: 'binary'}); var wb = X.utils.book_new();
X.write(wb3, {type: 'binary'}); X.utils.book_append_sheet(wb, X.utils.aoa_to_sheet([['R',"\u2603"],["\u0BEE",2]]), "Sheet1");
X.write(wb4, {type: 'binary'}); if(T == 'string' && !fmt[2]) return assert.throws(function() {X.write(wb, {type: T, bookType:fmt[0], WTF:1});});
X.read(X.write(wb1, {type: 'binary'}), {type: 'binary'}); var out = X.write(wb, {type: T, bookType:fmt[0], WTF:1});
X.read(X.write(wb2, {type: 'binary'}), {type: 'binary'}); var nwb = X.read(out, {type: T, WTF:1});
X.read(X.write(wb3, {type: 'binary'}), {type: 'binary'}); var nws = nwb.Sheets[nwb.SheetNames[0]];
X.read(X.write(wb4, {type: 'binary'}), {type: 'binary'}); assert.equal(get_cell(nws, "B2").v, 2);
}); assert.equal(get_cell(nws, "A1").v, "R");
it('should write base64 strings', function() { if(fmt[1]) assert.equal(get_cell(nws, "A2").v, "\u0BEE");
X.write(wb1, {type: 'base64'}); if(fmt[1]) assert.equal(get_cell(nws, "B1").v, "\u2603");
X.write(wb2, {type: 'base64'}); });
X.write(wb3, {type: 'base64'}); }
X.write(wb4, {type: 'base64'}); it('should write binary strings', function() { RT('binary'); });
X.read(X.write(wb1, {type: 'base64'}), {type: 'base64'}); it('should write base64 strings', function() { RT('base64'); });
X.read(X.write(wb2, {type: 'base64'}), {type: 'base64'}); it('should write JS strings', function() { RT('string'); });
X.read(X.write(wb3, {type: 'base64'}), {type: 'base64'}); if(!browser) it('should write buffers', function() { RT('buffer'); });
X.read(X.write(wb4, {type: 'base64'}), {type: 'base64'}); it('should throw if format is unknown', function() { assert.throws(function() { RT('dafuq'); }); });
});
if(!browser) it('should write buffers', function() {
X.write(wb1, {type: 'buffer'});
X.write(wb2, {type: 'buffer'});
X.write(wb3, {type: 'buffer'});
X.write(wb4, {type: 'buffer'});
X.read(X.write(wb1, {type: 'buffer'}), {type: 'buffer'});
X.read(X.write(wb2, {type: 'buffer'}), {type: 'buffer'});
X.read(X.write(wb3, {type: 'buffer'}), {type: 'buffer'});
X.read(X.write(wb4, {type: 'buffer'}), {type: 'buffer'});
});
it('should throw if format is unknown', function() {
assert.throws(function() { X.write(wb1, {type: 'dafuq'}); });
assert.throws(function() { X.write(wb2, {type: 'dafuq'}); });
assert.throws(function() { X.write(wb3, {type: 'dafuq'}); });
assert.throws(function() { X.write(wb4, {type: 'dafuq'}); });
});
}); });
function eqarr(a,b) { function eqarr(a,b) {
@ -756,30 +763,32 @@ function check_margin(margins, exp) {
describe('parse features', function() { describe('parse features', function() {
describe('sheet visibility', function() { describe('sheet visibility', function() {
var wb1, wb2, wb3, wb4, wb5; var wbs = [];
var bef = (function() { var bef = (function() {
wb1 = X.read(fs.readFileSync(paths.svxls), {type:TYPE}); wbs = [
wb2 = X.read(fs.readFileSync(paths.svxls5), {type:TYPE}); X.read(fs.readFileSync(paths.svxls), {type:TYPE}),
wb3 = X.read(fs.readFileSync(paths.svxml), {type:TYPE}); X.read(fs.readFileSync(paths.svxls5), {type:TYPE}),
wb4 = X.read(fs.readFileSync(paths.svxlsx), {type:TYPE}); X.read(fs.readFileSync(paths.svxml), {type:TYPE}),
wb5 = X.read(fs.readFileSync(paths.svxlsb), {type:TYPE}); X.read(fs.readFileSync(paths.svxlsx), {type:TYPE}),
X.read(fs.readFileSync(paths.svxlsb), {type:TYPE})
];
}); });
if(typeof before != 'undefined') before(bef); if(typeof before != 'undefined') before(bef);
else it('before', bef); else it('before', bef);
it('should detect visible sheets', function() { it('should detect visible sheets', function() {
[wb1, wb2, wb3, wb4, wb5].forEach(function(wb) { wbs.forEach(function(wb) {
assert(!wb.Workbook.Sheets[0].Hidden); assert(!wb.Workbook.Sheets[0].Hidden);
}); });
}); });
it('should detect all hidden sheets', function() { it('should detect all hidden sheets', function() {
[wb1, wb2, wb3, wb4, wb5].forEach(function(wb) { wbs.forEach(function(wb) {
assert(wb.Workbook.Sheets[1].Hidden); assert(wb.Workbook.Sheets[1].Hidden);
assert(wb.Workbook.Sheets[2].Hidden); assert(wb.Workbook.Sheets[2].Hidden);
}); });
}); });
it('should distinguish very hidden sheets', function() { it('should distinguish very hidden sheets', function() {
[wb1, wb2, wb3, wb4, wb5].forEach(function(wb) { wbs.forEach(function(wb) {
assert.equal(wb.Workbook.Sheets[1].Hidden,1); assert.equal(wb.Workbook.Sheets[1].Hidden,1);
assert.equal(wb.Workbook.Sheets[2].Hidden,2); assert.equal(wb.Workbook.Sheets[2].Hidden,2);
}); });
@ -822,24 +831,44 @@ describe('parse features', function() {
}); });
describe('should parse core properties and custom properties', function() { describe('should parse core properties and custom properties', function() {
var wb1, wb2, wb3, wb4; var wbs=[];
var bef = (function() { var bef = (function() {
wb1 = X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE}); wbs = [
wb2 = X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE}); X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE}),
wb3 = X.read(fs.readFileSync(paths.cpxls), {type:TYPE}); X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE}),
wb4 = X.read(fs.readFileSync(paths.cpxml), {type:TYPE}); X.read(fs.readFileSync(paths.cpxls), {type:TYPE}),
X.read(fs.readFileSync(paths.cpxml), {type:TYPE})
];
}); });
if(typeof before != 'undefined') before(bef); if(typeof before != 'undefined') before(bef);
else it('before', bef); else it('before', bef);
it(N1 + ' should parse core properties', function() { coreprop(wb1); }); [N1, N2, N3, N4].forEach(function(x, i) {
it(N2 + ' should parse core properties', function() { coreprop(wb2); }); it(x + ' should parse core properties', function() { coreprop(wbs[i]); });
it(N3 + ' should parse core properties', function() { coreprop(wb3); }); it(x + ' should parse custom properties', function() { custprop(wbs[i]); });
it(N4 + ' should parse core properties', function() { coreprop(wb4); }); });
it(N1 + ' should parse custom properties', function() { custprop(wb1); }); [
it(N2 + ' should parse custom properties', function() { custprop(wb2); }); ["asxls", "BIFF8", "\u2603"],
it(N3 + ' should parse custom properties', function() { custprop(wb3); }); ["asxls5", "BIFF5", "_"],
it(N4 + ' should parse custom properties', function() { custprop(wb4); }); ["asxml", "XLML", "\u2603"],
["asods", "ODS", "God"],
["asxlsx", "XLSX", "\u2603"],
["asxlsb", "XLSB", "\u2603"]
].forEach(function(x) {
(fs.existsSync(paths[x[0]]) ? it : it.skip)(x[1] + ' should read unicode author', function() {
var wb = X.read(fs.readFileSync(paths[x[0]]), {type:TYPE});
assert.equal(wb.Props.Author, x[2]);
}); });
var BASE = "இராமா";
[ "xlsx", "xlsb", "xlml"/*, "ods", "xls" */].forEach(function(n) {
it(n + ' should round-trip unicode category', function() {
var wb = X.utils.book_new();
X.utils.book_append_sheet(wb, X.utils.aoa_to_sheet([["a"]]), "Sheet1");
if(!wb.Props) wb.Props = {};
wb.Props.Category = BASE;
var wb2 = X.read(X.write(wb, {bookType:n, type:TYPE}), {type:TYPE});
assert.equal(wb2.Props.Category,BASE);
}); });
}); });
describe('sheetRows', function() { describe('sheetRows', function() {
@ -930,6 +959,7 @@ describe('parse features', function() {
describe('row properties', function() { describe('row properties', function() {
var wb1, wb2, wb3, wb4, wb5, wb6; var wb1, wb2, wb3, wb4, wb5, wb6;
var ol1, ol2, ol3, ol4, ol5; var ol1, ol2, ol3, ol4, ol5;
var ol = fs.existsSync(paths.olxls);
var bef = (function() { var bef = (function() {
X = require(modp); X = require(modp);
wb1 = X.read(fs.readFileSync(paths.rhxlsx), {type:TYPE, cellStyles:true}); wb1 = X.read(fs.readFileSync(paths.rhxlsx), {type:TYPE, cellStyles:true});
@ -938,6 +968,8 @@ describe('parse features', function() {
wb4 = X.read(fs.readFileSync(paths.rhxls5), {type:TYPE, cellStyles:true}); wb4 = X.read(fs.readFileSync(paths.rhxls5), {type:TYPE, cellStyles:true});
wb5 = X.read(fs.readFileSync(paths.rhxml), {type:TYPE, cellStyles:true}); wb5 = X.read(fs.readFileSync(paths.rhxml), {type:TYPE, cellStyles:true});
wb6 = X.read(fs.readFileSync(paths.rhslk), {type:TYPE, cellStyles:true}); wb6 = X.read(fs.readFileSync(paths.rhslk), {type:TYPE, cellStyles:true});
/* */
if(!ol) return;
ol1 = X.read(fs.readFileSync(paths.olxlsx), {type:TYPE, cellStyles:true}); ol1 = X.read(fs.readFileSync(paths.olxlsx), {type:TYPE, cellStyles:true});
ol2 = X.read(fs.readFileSync(paths.olxlsb), {type:TYPE, cellStyles:true}); ol2 = X.read(fs.readFileSync(paths.olxlsb), {type:TYPE, cellStyles:true});
ol3 = X.read(fs.readFileSync(paths.olxls), {type:TYPE, cellStyles:true}); ol3 = X.read(fs.readFileSync(paths.olxls), {type:TYPE, cellStyles:true});
@ -964,7 +996,7 @@ describe('parse features', function() {
assert.equal(x[3].hpx, 100); assert.equal(x[3].hpx, 100);
}); });
}); });
it('should have correct outline levels', function() { (ol ? it : it.skip)('should have correct outline levels', function() {
/* TODO: ODS */ /* TODO: ODS */
[ol1, ol2, ol3, ol4/*, ol5*/].map(function(x) { return x.Sheets.Sheet1; }).forEach(function(ws) { [ol1, ol2, ol3, ol4/*, ol5*/].map(function(x) { return x.Sheets.Sheet1; }).forEach(function(ws) {
var rows = ws['!rows']; var rows = ws['!rows'];
@ -973,7 +1005,7 @@ describe('parse features', function() {
var lvl = (rows[i]||{}).level||0; var lvl = (rows[i]||{}).level||0;
if(!cell || cell.t == 's') assert.equal(lvl, 0); if(!cell || cell.t == 's') assert.equal(lvl, 0);
else if(cell.t == 'n') { else if(cell.t == 'n') {
if(cell.v == 0) assert.equal(lvl, 0); if(cell.v === 0) assert.equal(lvl, 0);
else assert.equal(lvl, cell.v); else assert.equal(lvl, cell.v);
} }
} }
@ -983,47 +1015,47 @@ describe('parse features', function() {
}); });
describe('merge cells',function() { describe('merge cells',function() {
var wb1, wb2, wb3, wb4, wb5; var wbs=[];
var bef = (function() { var bef = (function() {
X = require(modp); X = require(modp);
wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE}); wbs = [
wb2 = X.read(fs.readFileSync(paths.mcxlsb), {type:TYPE}); X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE}),
wb3 = X.read(fs.readFileSync(paths.mcods), {type:TYPE}); X.read(fs.readFileSync(paths.mcxlsb), {type:TYPE}),
wb4 = X.read(fs.readFileSync(paths.mcxls), {type:TYPE}); X.read(fs.readFileSync(paths.mcods), {type:TYPE}),
wb5 = X.read(fs.readFileSync(paths.mcxml), {type:TYPE}); X.read(fs.readFileSync(paths.mcxls), {type:TYPE}),
X.read(fs.readFileSync(paths.mcxml), {type:TYPE})
];
}); });
if(typeof before != 'undefined') before(bef); if(typeof before != 'undefined') before(bef);
else it('before', bef); else it('before', bef);
it('should have !merges', function() { it('should have !merges', function() {
assert(wb1.Sheets.Merge['!merges']); wbs.forEach(function(wb) {
assert(wb2.Sheets.Merge['!merges']); assert(wb.Sheets.Merge['!merges']);
assert(wb3.Sheets.Merge['!merges']); });
assert(wb4.Sheets.Merge['!merges']); var m = wbs.map(function(x) { return x.Sheets.Merge['!merges'].map(function(y) { return X.utils.encode_range(y); });});
assert(wb5.Sheets.Merge['!merges']); m.slice(1).forEach(function(x) {
var m = [wb1, wb2, wb3, wb4, wb5].map(function(x) { return x.Sheets.Merge['!merges'].map(function(y) { return X.utils.encode_range(y); });}); assert.deepEqual(m[0].sort(),x.sort());
assert.deepEqual(m[0].sort(),m[1].sort()); });
assert.deepEqual(m[0].sort(),m[2].sort());
assert.deepEqual(m[0].sort(),m[3].sort());
assert.deepEqual(m[0].sort(),m[4].sort());
}); });
}); });
describe('should find hyperlinks', function() { describe('should find hyperlinks', function() {
var wb1, wb2, wb3, wb4; var wbs;
var bef = (function() { var bef = (function() {
X = require(modp); X = require(modp);
wb1 = X.read(fs.readFileSync(paths.hlxlsx), {type:TYPE}); wbs = [
wb2 = X.read(fs.readFileSync(paths.hlxlsb), {type:TYPE}); X.read(fs.readFileSync(paths.hlxlsx), {type:TYPE}),
wb3 = X.read(fs.readFileSync(paths.hlxls), {type:TYPE}); X.read(fs.readFileSync(paths.hlxlsb), {type:TYPE}),
wb4 = X.read(fs.readFileSync(paths.hlxml), {type:TYPE}); X.read(fs.readFileSync(paths.hlxls), {type:TYPE}),
X.read(fs.readFileSync(paths.hlxml), {type:TYPE})
];
}); });
if(typeof before != 'undefined') before(bef); if(typeof before != 'undefined') before(bef);
else it('before', bef); else it('before', bef);
it(N1, function() { hlink(wb1); }); [N1, N2, N3, N4].forEach(function(x, i) {
it(N2, function() { hlink(wb2); }); it(x, function() { hlink(wbs[i]); });
it(N3, function() { hlink(wb3); }); });
it(N4, function() { hlink(wb4); });
}); });
describe('should parse cells with date type (XLSX/XLSM)', function() { describe('should parse cells with date type (XLSX/XLSM)', function() {
@ -1077,7 +1109,7 @@ describe('parse features', function() {
['xlsx', paths.dnsxlsx, true], ['xlsx', paths.dnsxlsx, true],
['xlsb', paths.dnsxlsb, true], ['xlsb', paths.dnsxlsb, true],
['xls', paths.dnsxls, true], ['xls', paths.dnsxls, true],
['xlml', paths.dnsxml, false], ['xlml', paths.dnsxml, false]
].forEach(function(m) { it(m[0], function() { ].forEach(function(m) { it(m[0], function() {
var wb = X.read(fs.readFileSync(m[1]), {type:TYPE}); var wb = X.read(fs.readFileSync(m[1]), {type:TYPE});
var names = wb.Workbook.Names; var names = wb.Workbook.Names;
@ -1103,9 +1135,9 @@ describe('parse features', function() {
['ods', paths.afods] ['ods', paths.afods]
].forEach(function(m) { it(m[0], function() { ].forEach(function(m) { it(m[0], function() {
var wb = X.read(fs.readFileSync(m[1]), {type:TYPE}); var wb = X.read(fs.readFileSync(m[1]), {type:TYPE});
assert(wb.Sheets[wb.SheetNames[0]]['!autofilter'] == null); assert(!wb.Sheets[wb.SheetNames[0]]['!autofilter']);
for(var i = 1; i < wb.SheetNames.length; ++i) { for(var i = 1; i < wb.SheetNames.length; ++i) {
assert(wb.Sheets[wb.SheetNames[i]]['!autofilter'] != null); assert(wb.Sheets[wb.SheetNames[i]]['!autofilter']);
assert.equal(wb.Sheets[wb.SheetNames[i]]['!autofilter'].ref,"A1:E22"); assert.equal(wb.Sheets[wb.SheetNames[i]]['!autofilter'].ref,"A1:E22");
} }
}); }); }); });
@ -1132,15 +1164,16 @@ describe('parse features', function() {
}); });
describe('page margins', function() { describe('page margins', function() {
var wb1, wb2, wb3, wb4, wb5, wbs; var wbs=[];
var bef = (function() { var bef = (function() {
if(!fs.existsSync(paths.pmxls)) return wbs=[]; if(!fs.existsSync(paths.pmxls)) return;
wb1 = X.read(fs.readFileSync(paths.pmxls), {type:TYPE}); wbs = [
wb2 = X.read(fs.readFileSync(paths.pmxls5), {type:TYPE}); X.read(fs.readFileSync(paths.pmxls), {type:TYPE}),
wb3 = X.read(fs.readFileSync(paths.pmxml), {type:TYPE}); X.read(fs.readFileSync(paths.pmxls5), {type:TYPE}),
wb4 = X.read(fs.readFileSync(paths.pmxlsx), {type:TYPE}); X.read(fs.readFileSync(paths.pmxml), {type:TYPE}),
wb5 = X.read(fs.readFileSync(paths.pmxlsb), {type:TYPE}); X.read(fs.readFileSync(paths.pmxlsx), {type:TYPE}),
wbs = [wb1, wb2, wb3, wb4, wb5]; X.read(fs.readFileSync(paths.pmxlsb), {type:TYPE})
];
}); });
if(typeof before != 'undefined') before(bef); if(typeof before != 'undefined') before(bef);
else it('before', bef); else it('before', bef);
@ -1149,17 +1182,17 @@ describe('parse features', function() {
check_margin(wb.Sheets["Normal"]["!margins"], [0.7, 0.7, 0.75, 0.75, 0.3, 0.3]); check_margin(wb.Sheets["Normal"]["!margins"], [0.7, 0.7, 0.75, 0.75, 0.3, 0.3]);
}); });
}); });
it('should parse wide margins ', function() { it('should parse wide margins', function() {
wbs.forEach(function(wb) { wbs.forEach(function(wb) {
check_margin(wb.Sheets["Wide"]["!margins"], [1, 1, 1, 1, 0.5, 0.5]); check_margin(wb.Sheets["Wide"]["!margins"], [1, 1, 1, 1, 0.5, 0.5]);
}); });
}); });
it('should parse narrow margins ', function() { it('should parse narrow margins', function() {
wbs.forEach(function(wb) { wbs.forEach(function(wb) {
check_margin(wb.Sheets["Narrow"]["!margins"], [0.25, 0.25, 0.75, 0.75, 0.3, 0.3]); check_margin(wb.Sheets["Narrow"]["!margins"], [0.25, 0.25, 0.75, 0.75, 0.3, 0.3]);
}); });
}); });
it('should parse custom margins ', function() { it('should parse custom margins', function() {
wbs.forEach(function(wb) { wbs.forEach(function(wb) {
check_margin(wb.Sheets["Custom 1 Inch Centered"]["!margins"], [1, 1, 1, 1, 0.3, 0.3]); check_margin(wb.Sheets["Custom 1 Inch Centered"]["!margins"], [1, 1, 1, 1, 0.3, 0.3]);
check_margin(wb.Sheets["1 Inch HF"]["!margins"], [0.7, 0.7, 0.75, 0.75, 1, 1]); check_margin(wb.Sheets["1 Inch HF"]["!margins"], [0.7, 0.7, 0.75, 0.75, 1, 1]);
@ -1255,7 +1288,7 @@ describe('write features', function() {
baseprops = { baseprops = {
Category: "Newspaper", Category: "Newspaper",
ContentStatus: "Published", ContentStatus: "Published",
Keywords: "print", Keywords: "",
LastAuthor: "Perry White", LastAuthor: "Perry White",
LastPrinted: "1978-12-15", LastPrinted: "1978-12-15",
RevNumber: 6969, RevNumber: 6969,
@ -1271,7 +1304,7 @@ describe('write features', function() {
if(typeof before != 'undefined') before(bef); if(typeof before != 'undefined') before(bef);
else it('before', bef); else it('before', bef);
['xlml', 'xlsx', 'xlsb'].forEach(function(w) { it(w, function() { ['xlml', 'xlsx', 'xlsb'].forEach(function(w) { it(w, function() {
wb = { var wb = {
Props: {}, Props: {},
SheetNames: ["Sheet1"], SheetNames: ["Sheet1"],
Sheets: {Sheet1: ws} Sheets: {Sheet1: ws}
@ -1389,7 +1422,7 @@ describe('roundtrip features', function() {
if(m[0].t === 'n' && m[1].t === 'n') assert.equal(m[0].v, m[1].v); if(m[0].t === 'n' && m[1].t === 'n') assert.equal(m[0].v, m[1].v);
else if(m[0].t === 'd' && m[1].t === 'd') assert.equal(m[0].v.toString(), m[1].v.toString()); else if(m[0].t === 'd' && m[1].t === 'd') assert.equal(m[0].v.toString(), m[1].v.toString());
else if(m[1].t === 'n') assert(Math.abs(datenum(new Date(m[0].v)) - m[1].v) < 0.01); else if(m[1].t === 'n') assert(Math.abs(datenum(browser ? parseDate(m[0].v) : new Date(m[0].v)) - m[1].v) < 0.01);
}); });
}); });
}); });
@ -1543,10 +1576,9 @@ describe('invalid files', function() {
}); });
describe('write', function() { describe('write', function() {
it('should pass -> XLSX', function() { it('should pass -> XLSX', function() {
X.write(X.read(fs.readFileSync(paths.fstxlsb), {type:TYPE}), {type:TYPE}); ["fstxlsb", "fstxlsx", "fstxls", "fstxml"].forEach(function(n) {
X.write(X.read(fs.readFileSync(paths.fstxlsx), {type:TYPE}), {type:TYPE}); X.write(X.read(fs.readFileSync(paths[n]), {type:TYPE}), {type:TYPE});
X.write(X.read(fs.readFileSync(paths.fstxls), {type:TYPE}), {type:TYPE}); });
X.write(X.read(fs.readFileSync(paths.fstxml), {type:TYPE}), {type:TYPE});
}); });
it('should pass if a sheet is missing', function() { it('should pass if a sheet is missing', function() {
var wb = X.read(fs.readFileSync(paths.fstxlsx), {type:TYPE}); delete wb.Sheets[wb.SheetNames[0]]; var wb = X.read(fs.readFileSync(paths.fstxlsx), {type:TYPE}); delete wb.Sheets[wb.SheetNames[0]];
@ -1700,16 +1732,16 @@ describe('json output', function() {
var _data = [["S","h","e","e","t","J","S"],[1,2,3,4,5,6,7],[],[2,3,4,5,6,7,8]]; var _data = [["S","h","e","e","t","J","S"],[1,2,3,4,5,6,7],[],[2,3,4,5,6,7,8]];
var _ws = X.utils.aoa_to_sheet(_data); var _ws = X.utils.aoa_to_sheet(_data);
var json1 = X.utils.sheet_to_json(_ws); var json1 = X.utils.sheet_to_json(_ws);
var json2 = X.utils.sheet_to_json(_ws, {header:1});
var json3 = X.utils.sheet_to_json(_ws, {blankrows:true});
var json4 = X.utils.sheet_to_json(_ws, {blankrows:true, header:1});
var json5 = X.utils.sheet_to_json(_ws, {blankrows:false});
var json6 = X.utils.sheet_to_json(_ws, {blankrows:false, header:1});
assert.equal(json1.length, 2); // = 2 non-empty records assert.equal(json1.length, 2); // = 2 non-empty records
var json2 = X.utils.sheet_to_json(_ws, {header:1});
assert.equal(json2.length, 4); // = 4 sheet rows assert.equal(json2.length, 4); // = 4 sheet rows
var json3 = X.utils.sheet_to_json(_ws, {blankrows:true});
assert.equal(json3.length, 3); // = 2 records + 1 blank row assert.equal(json3.length, 3); // = 2 records + 1 blank row
var json4 = X.utils.sheet_to_json(_ws, {blankrows:true, header:1});
assert.equal(json4.length, 4); // = 4 sheet rows assert.equal(json4.length, 4); // = 4 sheet rows
var json5 = X.utils.sheet_to_json(_ws, {blankrows:false});
assert.equal(json5.length, 2); // = 2 records assert.equal(json5.length, 2); // = 2 records
var json6 = X.utils.sheet_to_json(_ws, {blankrows:false, header:1});
assert.equal(json6.length, 3); // = 4 sheet rows - 1 blank row assert.equal(json6.length, 3); // = 4 sheet rows - 1 blank row
}); });
it('should have an index that starts with zero when selecting range', function() { it('should have an index that starts with zero when selecting range', function() {
@ -1724,36 +1756,40 @@ describe('json output', function() {
}); });
var codes = [["あ 1", "\u00E3\u0081\u0082 1"]] var codes = [["あ 1", "\u00E3\u0081\u0082 1"]];
var plaintext_val = [ var plaintext_val = [
["A1", 'n', -0.08, "-0.08"], ["A1", 'n', -0.08, "-0.08"],
["B1", 'n', 4001, "4,001"], ["B1", 'n', 4001, "4,001"],
["C1", 's', "あ 1", "あ 1"], ["C1", 's', "あ 1", "あ 1"],
["A2", 'n', 41.08, "$41.08"], ["A2", 'n', 41.08, "$41.08"],
["B2", 'n', 0.11, "11%"], ["B2", 'n', 0.11, "11%"],
["B3", 'b', true, "TRUE"], ["C3", 'b', true, "TRUE"],
["C3", 'b', false, "FALSE"], ["D3", 'b', false, "FALSE"],
["A3"]]; ["B3", 's', " ", " "],
function plaintext_test(wb, raw, sn) { ["A3"]
var sheet = wb.Sheets[sn || wb.SheetNames[0]]; ];
function plaintext_test(wb, raw, t) {
var sheet = wb.Sheets[wb.SheetNames[0]];
plaintext_val.forEach(function(x) { plaintext_val.forEach(function(x) {
var cell = get_cell(sheet, x[0]); var cell = get_cell(sheet, x[0]);
var tcval = x[2+!!raw];
var type = raw ? 's' : x[1]; // != 's' ? x[1] : tcval.length === 0 ? 'z' : 's';
if(x.length == 1) { if(cell) { assert.equal(cell.t, 'z'); assert(!cell.v); } return; } if(x.length == 1) { if(cell) { assert.equal(cell.t, 'z'); assert(!cell.v); } return; }
assert.equal(cell.v, x[2+!!raw]); assert.equal(cell.t, raw ? 's' : x[1]); assert.equal(cell.v, tcval); assert.equal(cell.t, type);
}); });
} }
function make_html_str(idx) { return ["<table>", function make_html_str(idx) { return ["<table>",
"<tr><td>-0.08</td><td>4,001</td><td>", codes[0][idx], "</td></tr>", "<tr><td>-0.08</td><td>4,001</td><td>", codes[0][idx], "</td></tr>",
"<tr><td>$41.08</td><td>11%</td></tr>", "<tr><td>$41.08</td><td>11%</td></tr>",
"<tr><td></td><td>TRUE</td><td>FALSE</td></tr>", "<tr><td></td><td> \n&nbsp;</td><td>TRUE</td><td>FALSE</td></tr>",
"</table>" ].join(""); } "</table>" ].join(""); }
function make_csv_str(idx) { return [ '\u00EF\u00BB\u00BF' + function make_csv_str(idx) { return [ (idx == 1 ? '\u00EF\u00BB\u00BF' : "") +
'-0.08,"4,001",' + codes[0][idx] + '', '-0.08,"4,001",' + codes[0][idx] + '',
'$41.08,11%', '$41.08,11%',
',TRUE,FALSE' ', ,TRUE,FALSE'
].join("\n"); } ].join("\n"); }
var html_bstr = make_html_str(1), html_str = make_html_str(0); var html_bstr = make_html_str(1), html_str = make_html_str(0);
var csv_bstr = make_csv_str(1); var csv_bstr = make_csv_str(1), csv_str = make_csv_str(0);
describe('csv', function() { describe('csv', function() {
@ -1779,7 +1815,7 @@ describe('csv', function() {
var cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3"); var cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3");
assert.equal(cell.w, '2/19/14'); assert.equal(cell.w, '2/19/14');
opts.cellDates = true; opts.cellDates = true;
var cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3"); cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3");
assert.equal(cell.w, '2/19/14'); assert.equal(cell.w, '2/19/14');
}); });
it('should honor dateNF override', function() { it('should honor dateNF override', function() {
@ -1788,7 +1824,7 @@ describe('csv', function() {
/* NOTE: IE interprets 2-digit years as 19xx */ /* NOTE: IE interprets 2-digit years as 19xx */
assert(cell.w == '2014-02-19' || cell.w == '1914-02-19'); assert(cell.w == '2014-02-19' || cell.w == '1914-02-19');
opts.cellDates = true; opts.dateNF = "YY-MM-DD"; opts.cellDates = true; opts.dateNF = "YY-MM-DD";
var cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3"); cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3");
assert.equal(cell.w, '14-02-19'); assert.equal(cell.w, '14-02-19');
}); });
it('should interpret dateNF', function() { it('should interpret dateNF', function() {
@ -1802,8 +1838,8 @@ describe('csv', function() {
assert.equal(cell.v.getMonth(), 2); assert.equal(cell.v.getMonth(), 2);
assert.equal(cell.w, "2/3/14"); assert.equal(cell.w, "2/3/14");
}); });
it('should interpret values by default', function() { plaintext_test(X.read(csv_bstr, {type:"binary"}), false); }); it('should interpret values by default', function() { plaintext_test(X.read(csv_bstr, {type:"binary"}), false, false); });
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(csv_bstr, {type:"binary", raw:true}), true); }); it('should generate strings if raw option is passed', function() { plaintext_test(X.read(csv_bstr, {type:"binary", raw:true}), true, false); });
it('should handle formulae', function() { it('should handle formulae', function() {
var bb = '=,=1+1,="100"'; var bb = '=,=1+1,="100"';
var sheet = X.read(bb, {type:"binary"}).Sheets.Sheet1; var sheet = X.read(bb, {type:"binary"}).Sheets.Sheet1;
@ -1903,12 +1939,13 @@ function get_dom_element(html) {
describe('HTML', function() { describe('HTML', function() {
describe('input string', function(){ describe('input string', function(){
it('should interpret values by default', function() { plaintext_test(X.read(html_bstr, {type:"binary"}), false); }); it('should interpret values by default', function() { plaintext_test(X.read(html_bstr, {type:"binary"}), false, false); });
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(html_bstr, {type:"binary", raw:true}), true); }); it('should generate strings if raw option is passed', function() { plaintext_test(X.read(html_bstr, {type:"binary", raw:true}), true, false); });
it('should handle "string" type', function() { plaintext_test(X.read(html_str, {type:"string"}), false, false); });
}); });
(domtest ? describe : describe.skip)('input DOM', function() { (domtest ? describe : describe.skip)('input DOM', function() {
it('should interpret values by default', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str)), false); }); it('should interpret values by default', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str)), false, true); });
it('should generate strings if raw option is passed', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str), {raw:true}), true); }); it('should generate strings if raw option is passed', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str), {raw:true}), true, true); });
}); });
}); });
@ -1933,25 +1970,14 @@ describe('js -> file -> js', function() {
ofmt.forEach(function(f) { ofmt.forEach(function(f) {
it(f, function() { it(f, function() {
var newwb = X.read(X.write(wb, {type:BIN, bookType: f}), {type:BIN}); var newwb = X.read(X.write(wb, {type:BIN, bookType: f}), {type:BIN});
/* int */ var cb = function(cell) { eqcell(wb, newwb, 'Sheet1', cell); };
eqcell(wb, newwb, 'Sheet1', 'A1'); ['A1', 'B1', 'C1'].forEach(cb); /* int */
eqcell(wb, newwb, 'Sheet1', 'B1'); ['B4'].forEach(cb); /* double */
eqcell(wb, newwb, 'Sheet1', 'C1'); ['A2', 'B2'].forEach(cb); /* bool */
/* double */ ['D2', 'A3', 'B3', 'A4', 'C4'].forEach(cb); /* string */
eqcell(wb, newwb, 'Sheet1', 'B4'); if(!DIF_XL) cb('C3'); /* date */
/* bool */
eqcell(wb, newwb, 'Sheet1', 'A2');
eqcell(wb, newwb, 'Sheet1', 'B2');
/* string */
eqcell(wb, newwb, 'Sheet1', 'D2');
eqcell(wb, newwb, 'Sheet1', 'A3');
eqcell(wb, newwb, 'Sheet1', 'B3');
eqcell(wb, newwb, 'Sheet1', 'A4');
eqcell(wb, newwb, 'Sheet1', 'C4');
if(DIF_XL && f == "dif") assert.equal(get_cell(newwb.Sheets["Sheet1"], 'D3').v, '=""0.3""');// dif forces string formula if(DIF_XL && f == "dif") assert.equal(get_cell(newwb.Sheets["Sheet1"], 'D3').v, '=""0.3""');// dif forces string formula
else eqcell(wb, newwb, 'Sheet1', 'D3'); else eqcell(wb, newwb, 'Sheet1', 'D3');
/* date */
if(!DIF_XL) eqcell(wb, newwb, 'Sheet1', 'C3');
}); });
}); });
}); });
@ -1997,12 +2023,13 @@ describe('corner cases', function() {
}); });
it('SSF oddities', function() { it('SSF oddities', function() {
var ssfdata = require('./misc/ssf.json'); var ssfdata = require('./misc/ssf.json');
var cb = function(d, j) { return function() { return X.SSF.format(d[0], d[j][0]); }; };
ssfdata.forEach(function(d) { ssfdata.forEach(function(d) {
for(var j=1;j<d.length;++j) { for(var j=1;j<d.length;++j) {
if(d[j].length == 2) { if(d[j].length == 2) {
var expected = d[j][1], actual = X.SSF.format(d[0], d[j][0], {}); var expected = d[j][1], actual = X.SSF.format(d[0], d[j][0], {});
assert.equal(actual, expected); assert.equal(actual, expected);
} else if(d[j][2] !== "#") assert.throws(function() { SSF.format(d[0], d[j][0]); }); } else if(d[j][2] !== "#") assert.throws(cb(d, j));
} }
}); });
}); });
@ -2031,7 +2058,7 @@ describe('encryption', function() {
} }
}); });
it.skip('should decrypt file', function() { it.skip('should decrypt file', function() {
var wb = X.read(fs.readFileSync(dir + x), {type:TYPE,password:'password',WTF:opts.WTF}); /*var wb = */X.read(fs.readFileSync(dir + x), {type:TYPE,password:'password',WTF:opts.WTF});
}); });
}); });
}); });

@ -1 +1 @@
Subproject commit a9c6bbb161ca45a077779ecbe434d8c5d614ee37 Subproject commit 936478fc713e5ee59c35a49bce4f61ea397284e5

@ -1,5 +1,6 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */ /* vim: set ts=2: */
/*jshint loopfunc:true, eqnull:true */ /*jshint -W069, loopfunc:true, mocha:true */
var X; var X;
var modp = './'; var modp = './';
//var modp = 'xlsx'; //var modp = 'xlsx';
@ -7,7 +8,7 @@ var fs = require('fs'), assert = require('assert');
describe('source',function(){it('should load',function(){X=require(modp);});}); describe('source',function(){it('should load',function(){X=require(modp);});});
var DIF_XL = true; var DIF_XL = true;
var browser = true; var browser = typeof document !== 'undefined';
var opts = {cellNF: true}; var opts = {cellNF: true};
var TYPE = browser ? "binary" : "buffer"; var TYPE = browser ? "binary" : "buffer";
@ -36,15 +37,48 @@ function fixjson(x) { return x.replace(/[\r\n]+$/,""); }
var dir = "./test_files/"; var dir = "./test_files/";
var dirwp = dir + "artifacts/wps/", dirqp = dir + "artifacts/quattro/";
var paths = { var paths = {
afxls: dir + 'AutoFilter.xls', aadbf: dirwp + 'write.dbf',
afxml: dir + 'AutoFilter.xml', aadif: dirwp + 'write.dif',
afods: dir + 'AutoFilter.ods', aaxls: dirwp + 'write.xls',
aaxlsx: dirwp + 'write.xlsx',
aaxml: dirwp + 'write.xml',
abcsv: dirqp + 'write_.csv',
abdif: dirqp + 'write_.dif',
abslk: dirqp + 'write_.slk',
abx57: dirqp + 'write_57.xls',
abwb2: dirqp + 'write_6.wb2',
abwb2b: dirqp + 'write_6b.wb2',
abwb3: dirqp + 'write_8.wb3',
abqpw: dirqp + 'write_9.qpw',
abx97: dirqp + 'write_97.xls',
abwks: dirqp + 'write_L1.wks',
abwk1: dirqp + 'write_L2.wk1',
abwk3: dirqp + 'write_L3.wk3',
abwk4: dirqp + 'write_L45.wk4',
ab123: dirqp + 'write_L9.123',
ab124: dirqp + 'write_L97.123',
abwke2: dirqp + 'write_Led.wke',
abwq1: dirqp + 'write_qpdos.wq1',
abwb1: dirqp + 'write_qpw.wb1',
afxls: dir + 'AutoFilter.xls',
afxml: dir + 'AutoFilter.xml',
afods: dir + 'AutoFilter.ods',
afxlsx: dir + 'AutoFilter.xlsx', afxlsx: dir + 'AutoFilter.xlsx',
afxlsb: dir + 'AutoFilter.xlsb', afxlsb: dir + 'AutoFilter.xlsb',
cpxls: dir + 'custom_properties.xls', asxls: dir + 'author_snowman.xls',
cpxml: dir + 'custom_properties.xls.xml', asxls5: dir + 'author_snowman.xls5',
asxml: dir + 'author_snowman.xml',
asods: dir + 'author_snowman.ods',
asxlsx: dir + 'author_snowman.xlsx',
asxlsb: dir + 'author_snowman.xlsb',
cpxls: dir + 'custom_properties.xls',
cpxml: dir + 'custom_properties.xls.xml',
cpxlsx: dir + 'custom_properties.xlsx', cpxlsx: dir + 'custom_properties.xlsx',
cpxlsb: dir + 'custom_properties.xlsb', cpxlsb: dir + 'custom_properties.xlsb',
@ -226,19 +260,19 @@ function parsetest(x, wb, full, ext) {
if(fs.existsSync(dir + '2011/' + x + '.xml')) if(fs.existsSync(dir + '2011/' + x + '.xml'))
describe(x + ext + '.xml from 2011', function() { describe(x + ext + '.xml from 2011', function() {
it('should parse', function() { it('should parse', function() {
var wb = X.readFile(dir + '2011/' + x + '.xml', opts); /*var wb = */X.readFile(dir + '2011/' + x + '.xml', opts);
}); });
}); });
if(fs.existsSync(dir + '2013/' + x + '.xlsb')) if(fs.existsSync(dir + '2013/' + x + '.xlsb'))
describe(x + ext + '.xlsb from 2013', function() { describe(x + ext + '.xlsb from 2013', function() {
it('should parse', function() { it('should parse', function() {
var wb = X.readFile(dir + '2013/' + x + '.xlsb', opts); /*var wb = */X.readFile(dir + '2013/' + x + '.xlsb', opts);
}); });
}); });
if(fs.existsSync(dir + x + '.xml' + ext)) if(fs.existsSync(dir + x + '.xml' + ext))
describe(x + '.xml', function() { describe(x + '.xml', function() {
it('should parse', function() { it('should parse', function() {
var wb = X.readFile(dir + x + '.xml', opts); /*var wb = */X.readFile(dir + x + '.xml', opts);
}); });
}); });
} }
@ -553,121 +587,94 @@ describe('parse options', function() {
}); });
describe('input formats', function() { describe('input formats', function() {
var _paths = [
"cstods", "cstxls", "cstxlsb", "cstxlsb", "cstxml", "aadbf", "aadif",
"aaxls", "aaxml", "aaxlsx", "ab123", "ab124", "abcsv", "abdif", "abqpw",
"abslk", "abwb1", "abwb2", "abwb3", "abwk1", "abwk3", "abwk4", "abwks",
"abwq1", "abx57", "abx97", "abwke2", "abwb2b"
].map(function(x) { return paths[x]; });
it('should read binary strings', function() { it('should read binary strings', function() {
X.read(fs.readFileSync(paths.cstxlsx, 'binary'), {type: 'binary'}); _paths.forEach(function(pth) {
X.read(fs.readFileSync(paths.cstxlsb, 'binary'), {type: 'binary'}); X.read(fs.readFileSync(pth, 'binary'), {type: 'binary'});
X.read(fs.readFileSync(paths.cstxls, 'binary'), {type: 'binary'}); });
X.read(fs.readFileSync(paths.cstxml, 'binary'), {type: 'binary'});
X.read(fs.readFileSync(paths.cstods, 'binary'), {type: 'binary'});
}); });
it('should read base64 strings', function() { it('should read base64 strings', function() {
X.read(fs.readFileSync(paths.cstxls, 'base64'), {type: 'base64'}); _paths.forEach(function(pth) {
X.read(fs.readFileSync(paths.cstxml, 'base64'), {type: 'base64'}); X.read(fs.readFileSync(pth, 'base64'), {type: 'base64'});
X.read(fs.readFileSync(paths.cstods, 'base64'), {type: 'base64'}); });
X.read(fs.readFileSync(paths.cstxlsx, 'base64'), {type: 'base64'});
X.read(fs.readFileSync(paths.cstxlsb, 'base64'), {type: 'base64'});
}); });
var k = browser ? 'array' : 'buffer'; var k = browser ? 'array' : 'buffer';
(typeof Uint8Array !== 'undefined' ? it : it.skip)('should read ' + k + 's', function() { (typeof Uint8Array !== 'undefined' ? it : it.skip)('should read ' + k + 's', function() {
X.read(fs.readFileSync(paths.cstxls, browser ? 'buffer' : null), {type: k}); _paths.forEach(function(pth) {
X.read(fs.readFileSync(paths.cstxml, browser ? 'buffer' : null), {type: k}); X.read(fs.readFileSync(pth, browser ? 'buffer' : null), {type: k});
X.read(fs.readFileSync(paths.cstods, browser ? 'buffer' : null), {type: k}); });
X.read(fs.readFileSync(paths.cstxlsx, browser ? 'buffer' : null), {type: k});
X.read(fs.readFileSync(paths.cstxlsb, browser ? 'buffer' : null), {type: k});
}); });
(typeof Uint8Array !== 'undefined' ? it : it.skip)('should read array', function() { (typeof Uint8Array !== 'undefined' ? it : it.skip)('should read array', function() {
X.read(fs.readFileSync(paths.cstxls, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'}); _paths.forEach(function(pth) {
X.read(fs.readFileSync(paths.cstxml, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'}); X.read(fs.readFileSync(pth, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
X.read(fs.readFileSync(paths.cstxlsx, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'}); });
X.read(fs.readFileSync(paths.cstxlsb, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
X.read(fs.readFileSync(paths.cstods, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
}); });
it('should throw if format is unknown', function() { it('should throw if format is unknown', function() {
assert.throws(function() { X.read(fs.readFileSync(paths.cstxls), {type: 'dafuq'}); }); _paths.forEach(function(pth) {
assert.throws(function() { X.read(fs.readFileSync(paths.cstxml), {type: 'dafuq'}); }); assert.throws(function() { X.read(fs.readFileSync(pth), {type: 'dafuq'}); });
assert.throws(function() { X.read(fs.readFileSync(paths.cstods), {type: 'dafuq'}); }); });
assert.throws(function() { X.read(fs.readFileSync(paths.cstxlsx), {type: 'dafuq'}); });
assert.throws(function() { X.read(fs.readFileSync(paths.cstxlsb), {type: 'dafuq'}); });
}); });
if(browser) it('should default to base64 type', function() { if(browser) it('should default to base64 type', function() {
X.read(fs.readFileSync(paths.cstxls, 'base64')); _paths.forEach(function(pth) {
X.read(fs.readFileSync(paths.cstxml, 'base64')); X.read(fs.readFileSync(pth, 'base64'));
X.read(fs.readFileSync(paths.cstods, 'base64')); });
X.read(fs.readFileSync(paths.cstxlsx, 'base64'));
X.read(fs.readFileSync(paths.cstxlsb, 'base64'));
}); });
else { else {
it('should infer buffer type', function() { it('should infer buffer type', function() {
X.read(fs.readFileSync(paths.cstxls)); _paths.forEach(function(pth) {
X.read(fs.readFileSync(paths.cstxml)); X.read(fs.readFileSync(pth));
X.read(fs.readFileSync(paths.cstods)); });
X.read(fs.readFileSync(paths.cstxlsx));
X.read(fs.readFileSync(paths.cstxlsb));
}); });
it('should read files', function() { it('should read files', function() {
X.readFile(paths.cstxls); _paths.forEach(function(pth) {
X.readFile(paths.cstxml); X.readFile(pth);
X.readFile(paths.cstods); });
X.readFile(paths.cstxlsx);
X.readFile(paths.cstxlsb);
}); });
} }
}); });
describe('output formats', function() { describe('output formats', function() {
var wb1, wb2, wb3, wb4; var fmts = [
var bef = (function() { /* fmt unicode str */
X = require(modp); ["xlsx", true, false],
wb1 = X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE}); ["xlsb", true, false],
wb2 = X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE}); ["xls", true, false],
wb3 = X.read(fs.readFileSync(paths.cpxls), {type:TYPE}); ["xlml", true, true],
wb4 = X.read(fs.readFileSync(paths.cpxml), {type:TYPE}); ["ods", true, false],
}); ["fods", true, true],
if(typeof before != 'undefined') before(bef); ["csv", true, true],
else it('before', bef); ["txt", true, true],
it('should write binary strings', function() { ["sylk", false, true],
if(!wb1) { ["html", true, true],
wb1 = X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE}); ["dif", false, true],
wb2 = X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE}); ["prn", false, true]
wb3 = X.read(fs.readFileSync(paths.cpxls), {type:TYPE}); ];
wb4 = X.read(fs.readFileSync(paths.cpxml), {type:TYPE}); function RT(T) {
} if(!X) X = require(modp);
X.write(wb1, {type: 'binary'}); fmts.forEach(function(fmt) {
X.write(wb2, {type: 'binary'}); var wb = X.utils.book_new();
X.write(wb3, {type: 'binary'}); X.utils.book_append_sheet(wb, X.utils.aoa_to_sheet([['R',"\u2603"],["\u0BEE",2]]), "Sheet1");
X.write(wb4, {type: 'binary'}); if(T == 'string' && !fmt[2]) return assert.throws(function() {X.write(wb, {type: T, bookType:fmt[0], WTF:1});});
X.read(X.write(wb1, {type: 'binary'}), {type: 'binary'}); var out = X.write(wb, {type: T, bookType:fmt[0], WTF:1});
X.read(X.write(wb2, {type: 'binary'}), {type: 'binary'}); var nwb = X.read(out, {type: T, WTF:1});
X.read(X.write(wb3, {type: 'binary'}), {type: 'binary'}); var nws = nwb.Sheets[nwb.SheetNames[0]];
X.read(X.write(wb4, {type: 'binary'}), {type: 'binary'}); assert.equal(get_cell(nws, "B2").v, 2);
}); assert.equal(get_cell(nws, "A1").v, "R");
it('should write base64 strings', function() { if(fmt[1]) assert.equal(get_cell(nws, "A2").v, "\u0BEE");
X.write(wb1, {type: 'base64'}); if(fmt[1]) assert.equal(get_cell(nws, "B1").v, "\u2603");
X.write(wb2, {type: 'base64'}); });
X.write(wb3, {type: 'base64'}); }
X.write(wb4, {type: 'base64'}); it('should write binary strings', function() { RT('binary'); });
X.read(X.write(wb1, {type: 'base64'}), {type: 'base64'}); it('should write base64 strings', function() { RT('base64'); });
X.read(X.write(wb2, {type: 'base64'}), {type: 'base64'}); it('should write JS strings', function() { RT('string'); });
X.read(X.write(wb3, {type: 'base64'}), {type: 'base64'}); if(!browser) it('should write buffers', function() { RT('buffer'); });
X.read(X.write(wb4, {type: 'base64'}), {type: 'base64'}); it('should throw if format is unknown', function() { assert.throws(function() { RT('dafuq'); }); });
});
if(!browser) it('should write buffers', function() {
X.write(wb1, {type: 'buffer'});
X.write(wb2, {type: 'buffer'});
X.write(wb3, {type: 'buffer'});
X.write(wb4, {type: 'buffer'});
X.read(X.write(wb1, {type: 'buffer'}), {type: 'buffer'});
X.read(X.write(wb2, {type: 'buffer'}), {type: 'buffer'});
X.read(X.write(wb3, {type: 'buffer'}), {type: 'buffer'});
X.read(X.write(wb4, {type: 'buffer'}), {type: 'buffer'});
});
it('should throw if format is unknown', function() {
assert.throws(function() { X.write(wb1, {type: 'dafuq'}); });
assert.throws(function() { X.write(wb2, {type: 'dafuq'}); });
assert.throws(function() { X.write(wb3, {type: 'dafuq'}); });
assert.throws(function() { X.write(wb4, {type: 'dafuq'}); });
});
}); });
function eqarr(a,b) { function eqarr(a,b) {
@ -756,30 +763,32 @@ function check_margin(margins, exp) {
describe('parse features', function() { describe('parse features', function() {
describe('sheet visibility', function() { describe('sheet visibility', function() {
var wb1, wb2, wb3, wb4, wb5; var wbs = [];
var bef = (function() { var bef = (function() {
wb1 = X.read(fs.readFileSync(paths.svxls), {type:TYPE}); wbs = [
wb2 = X.read(fs.readFileSync(paths.svxls5), {type:TYPE}); X.read(fs.readFileSync(paths.svxls), {type:TYPE}),
wb3 = X.read(fs.readFileSync(paths.svxml), {type:TYPE}); X.read(fs.readFileSync(paths.svxls5), {type:TYPE}),
wb4 = X.read(fs.readFileSync(paths.svxlsx), {type:TYPE}); X.read(fs.readFileSync(paths.svxml), {type:TYPE}),
wb5 = X.read(fs.readFileSync(paths.svxlsb), {type:TYPE}); X.read(fs.readFileSync(paths.svxlsx), {type:TYPE}),
X.read(fs.readFileSync(paths.svxlsb), {type:TYPE})
];
}); });
if(typeof before != 'undefined') before(bef); if(typeof before != 'undefined') before(bef);
else it('before', bef); else it('before', bef);
it('should detect visible sheets', function() { it('should detect visible sheets', function() {
[wb1, wb2, wb3, wb4, wb5].forEach(function(wb) { wbs.forEach(function(wb) {
assert(!wb.Workbook.Sheets[0].Hidden); assert(!wb.Workbook.Sheets[0].Hidden);
}); });
}); });
it('should detect all hidden sheets', function() { it('should detect all hidden sheets', function() {
[wb1, wb2, wb3, wb4, wb5].forEach(function(wb) { wbs.forEach(function(wb) {
assert(wb.Workbook.Sheets[1].Hidden); assert(wb.Workbook.Sheets[1].Hidden);
assert(wb.Workbook.Sheets[2].Hidden); assert(wb.Workbook.Sheets[2].Hidden);
}); });
}); });
it('should distinguish very hidden sheets', function() { it('should distinguish very hidden sheets', function() {
[wb1, wb2, wb3, wb4, wb5].forEach(function(wb) { wbs.forEach(function(wb) {
assert.equal(wb.Workbook.Sheets[1].Hidden,1); assert.equal(wb.Workbook.Sheets[1].Hidden,1);
assert.equal(wb.Workbook.Sheets[2].Hidden,2); assert.equal(wb.Workbook.Sheets[2].Hidden,2);
}); });
@ -822,24 +831,44 @@ describe('parse features', function() {
}); });
describe('should parse core properties and custom properties', function() { describe('should parse core properties and custom properties', function() {
var wb1, wb2, wb3, wb4; var wbs=[];
var bef = (function() { var bef = (function() {
wb1 = X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE}); wbs = [
wb2 = X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE}); X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE}),
wb3 = X.read(fs.readFileSync(paths.cpxls), {type:TYPE}); X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE}),
wb4 = X.read(fs.readFileSync(paths.cpxml), {type:TYPE}); X.read(fs.readFileSync(paths.cpxls), {type:TYPE}),
X.read(fs.readFileSync(paths.cpxml), {type:TYPE})
];
}); });
if(typeof before != 'undefined') before(bef); if(typeof before != 'undefined') before(bef);
else it('before', bef); else it('before', bef);
it(N1 + ' should parse core properties', function() { coreprop(wb1); }); [N1, N2, N3, N4].forEach(function(x, i) {
it(N2 + ' should parse core properties', function() { coreprop(wb2); }); it(x + ' should parse core properties', function() { coreprop(wbs[i]); });
it(N3 + ' should parse core properties', function() { coreprop(wb3); }); it(x + ' should parse custom properties', function() { custprop(wbs[i]); });
it(N4 + ' should parse core properties', function() { coreprop(wb4); }); });
it(N1 + ' should parse custom properties', function() { custprop(wb1); }); [
it(N2 + ' should parse custom properties', function() { custprop(wb2); }); ["asxls", "BIFF8", "\u2603"],
it(N3 + ' should parse custom properties', function() { custprop(wb3); }); ["asxls5", "BIFF5", "_"],
it(N4 + ' should parse custom properties', function() { custprop(wb4); }); ["asxml", "XLML", "\u2603"],
["asods", "ODS", "God"],
["asxlsx", "XLSX", "\u2603"],
["asxlsb", "XLSB", "\u2603"]
].forEach(function(x) {
(fs.existsSync(paths[x[0]]) ? it : it.skip)(x[1] + ' should read unicode author', function() {
var wb = X.read(fs.readFileSync(paths[x[0]]), {type:TYPE});
assert.equal(wb.Props.Author, x[2]);
}); });
var BASE = "இராமா";
[ "xlsx", "xlsb", "xlml"/*, "ods", "xls" */].forEach(function(n) {
it(n + ' should round-trip unicode category', function() {
var wb = X.utils.book_new();
X.utils.book_append_sheet(wb, X.utils.aoa_to_sheet([["a"]]), "Sheet1");
if(!wb.Props) wb.Props = {};
wb.Props.Category = BASE;
var wb2 = X.read(X.write(wb, {bookType:n, type:TYPE}), {type:TYPE});
assert.equal(wb2.Props.Category,BASE);
}); });
}); });
describe('sheetRows', function() { describe('sheetRows', function() {
@ -930,6 +959,7 @@ describe('parse features', function() {
describe('row properties', function() { describe('row properties', function() {
var wb1, wb2, wb3, wb4, wb5, wb6; var wb1, wb2, wb3, wb4, wb5, wb6;
var ol1, ol2, ol3, ol4, ol5; var ol1, ol2, ol3, ol4, ol5;
var ol = fs.existsSync(paths.olxls);
var bef = (function() { var bef = (function() {
X = require(modp); X = require(modp);
wb1 = X.read(fs.readFileSync(paths.rhxlsx), {type:TYPE, cellStyles:true}); wb1 = X.read(fs.readFileSync(paths.rhxlsx), {type:TYPE, cellStyles:true});
@ -938,6 +968,8 @@ describe('parse features', function() {
wb4 = X.read(fs.readFileSync(paths.rhxls5), {type:TYPE, cellStyles:true}); wb4 = X.read(fs.readFileSync(paths.rhxls5), {type:TYPE, cellStyles:true});
wb5 = X.read(fs.readFileSync(paths.rhxml), {type:TYPE, cellStyles:true}); wb5 = X.read(fs.readFileSync(paths.rhxml), {type:TYPE, cellStyles:true});
wb6 = X.read(fs.readFileSync(paths.rhslk), {type:TYPE, cellStyles:true}); wb6 = X.read(fs.readFileSync(paths.rhslk), {type:TYPE, cellStyles:true});
/* */
if(!ol) return;
ol1 = X.read(fs.readFileSync(paths.olxlsx), {type:TYPE, cellStyles:true}); ol1 = X.read(fs.readFileSync(paths.olxlsx), {type:TYPE, cellStyles:true});
ol2 = X.read(fs.readFileSync(paths.olxlsb), {type:TYPE, cellStyles:true}); ol2 = X.read(fs.readFileSync(paths.olxlsb), {type:TYPE, cellStyles:true});
ol3 = X.read(fs.readFileSync(paths.olxls), {type:TYPE, cellStyles:true}); ol3 = X.read(fs.readFileSync(paths.olxls), {type:TYPE, cellStyles:true});
@ -964,7 +996,7 @@ describe('parse features', function() {
assert.equal(x[3].hpx, 100); assert.equal(x[3].hpx, 100);
}); });
}); });
it('should have correct outline levels', function() { (ol ? it : it.skip)('should have correct outline levels', function() {
/* TODO: ODS */ /* TODO: ODS */
[ol1, ol2, ol3, ol4/*, ol5*/].map(function(x) { return x.Sheets.Sheet1; }).forEach(function(ws) { [ol1, ol2, ol3, ol4/*, ol5*/].map(function(x) { return x.Sheets.Sheet1; }).forEach(function(ws) {
var rows = ws['!rows']; var rows = ws['!rows'];
@ -973,7 +1005,7 @@ describe('parse features', function() {
var lvl = (rows[i]||{}).level||0; var lvl = (rows[i]||{}).level||0;
if(!cell || cell.t == 's') assert.equal(lvl, 0); if(!cell || cell.t == 's') assert.equal(lvl, 0);
else if(cell.t == 'n') { else if(cell.t == 'n') {
if(cell.v == 0) assert.equal(lvl, 0); if(cell.v === 0) assert.equal(lvl, 0);
else assert.equal(lvl, cell.v); else assert.equal(lvl, cell.v);
} }
} }
@ -983,47 +1015,47 @@ describe('parse features', function() {
}); });
describe('merge cells',function() { describe('merge cells',function() {
var wb1, wb2, wb3, wb4, wb5; var wbs=[];
var bef = (function() { var bef = (function() {
X = require(modp); X = require(modp);
wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE}); wbs = [
wb2 = X.read(fs.readFileSync(paths.mcxlsb), {type:TYPE}); X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE}),
wb3 = X.read(fs.readFileSync(paths.mcods), {type:TYPE}); X.read(fs.readFileSync(paths.mcxlsb), {type:TYPE}),
wb4 = X.read(fs.readFileSync(paths.mcxls), {type:TYPE}); X.read(fs.readFileSync(paths.mcods), {type:TYPE}),
wb5 = X.read(fs.readFileSync(paths.mcxml), {type:TYPE}); X.read(fs.readFileSync(paths.mcxls), {type:TYPE}),
X.read(fs.readFileSync(paths.mcxml), {type:TYPE})
];
}); });
if(typeof before != 'undefined') before(bef); if(typeof before != 'undefined') before(bef);
else it('before', bef); else it('before', bef);
it('should have !merges', function() { it('should have !merges', function() {
assert(wb1.Sheets.Merge['!merges']); wbs.forEach(function(wb) {
assert(wb2.Sheets.Merge['!merges']); assert(wb.Sheets.Merge['!merges']);
assert(wb3.Sheets.Merge['!merges']); });
assert(wb4.Sheets.Merge['!merges']); var m = wbs.map(function(x) { return x.Sheets.Merge['!merges'].map(function(y) { return X.utils.encode_range(y); });});
assert(wb5.Sheets.Merge['!merges']); m.slice(1).forEach(function(x) {
var m = [wb1, wb2, wb3, wb4, wb5].map(function(x) { return x.Sheets.Merge['!merges'].map(function(y) { return X.utils.encode_range(y); });}); assert.deepEqual(m[0].sort(),x.sort());
assert.deepEqual(m[0].sort(),m[1].sort()); });
assert.deepEqual(m[0].sort(),m[2].sort());
assert.deepEqual(m[0].sort(),m[3].sort());
assert.deepEqual(m[0].sort(),m[4].sort());
}); });
}); });
describe('should find hyperlinks', function() { describe('should find hyperlinks', function() {
var wb1, wb2, wb3, wb4; var wbs;
var bef = (function() { var bef = (function() {
X = require(modp); X = require(modp);
wb1 = X.read(fs.readFileSync(paths.hlxlsx), {type:TYPE}); wbs = [
wb2 = X.read(fs.readFileSync(paths.hlxlsb), {type:TYPE}); X.read(fs.readFileSync(paths.hlxlsx), {type:TYPE}),
wb3 = X.read(fs.readFileSync(paths.hlxls), {type:TYPE}); X.read(fs.readFileSync(paths.hlxlsb), {type:TYPE}),
wb4 = X.read(fs.readFileSync(paths.hlxml), {type:TYPE}); X.read(fs.readFileSync(paths.hlxls), {type:TYPE}),
X.read(fs.readFileSync(paths.hlxml), {type:TYPE})
];
}); });
if(typeof before != 'undefined') before(bef); if(typeof before != 'undefined') before(bef);
else it('before', bef); else it('before', bef);
it(N1, function() { hlink(wb1); }); [N1, N2, N3, N4].forEach(function(x, i) {
it(N2, function() { hlink(wb2); }); it(x, function() { hlink(wbs[i]); });
it(N3, function() { hlink(wb3); }); });
it(N4, function() { hlink(wb4); });
}); });
describe('should parse cells with date type (XLSX/XLSM)', function() { describe('should parse cells with date type (XLSX/XLSM)', function() {
@ -1077,7 +1109,7 @@ describe('parse features', function() {
['xlsx', paths.dnsxlsx, true], ['xlsx', paths.dnsxlsx, true],
['xlsb', paths.dnsxlsb, true], ['xlsb', paths.dnsxlsb, true],
['xls', paths.dnsxls, true], ['xls', paths.dnsxls, true],
['xlml', paths.dnsxml, false], ['xlml', paths.dnsxml, false]
].forEach(function(m) { it(m[0], function() { ].forEach(function(m) { it(m[0], function() {
var wb = X.read(fs.readFileSync(m[1]), {type:TYPE}); var wb = X.read(fs.readFileSync(m[1]), {type:TYPE});
var names = wb.Workbook.Names; var names = wb.Workbook.Names;
@ -1103,9 +1135,9 @@ describe('parse features', function() {
['ods', paths.afods] ['ods', paths.afods]
].forEach(function(m) { it(m[0], function() { ].forEach(function(m) { it(m[0], function() {
var wb = X.read(fs.readFileSync(m[1]), {type:TYPE}); var wb = X.read(fs.readFileSync(m[1]), {type:TYPE});
assert(wb.Sheets[wb.SheetNames[0]]['!autofilter'] == null); assert(!wb.Sheets[wb.SheetNames[0]]['!autofilter']);
for(var i = 1; i < wb.SheetNames.length; ++i) { for(var i = 1; i < wb.SheetNames.length; ++i) {
assert(wb.Sheets[wb.SheetNames[i]]['!autofilter'] != null); assert(wb.Sheets[wb.SheetNames[i]]['!autofilter']);
assert.equal(wb.Sheets[wb.SheetNames[i]]['!autofilter'].ref,"A1:E22"); assert.equal(wb.Sheets[wb.SheetNames[i]]['!autofilter'].ref,"A1:E22");
} }
}); }); }); });
@ -1132,15 +1164,16 @@ describe('parse features', function() {
}); });
describe('page margins', function() { describe('page margins', function() {
var wb1, wb2, wb3, wb4, wb5, wbs; var wbs=[];
var bef = (function() { var bef = (function() {
if(!fs.existsSync(paths.pmxls)) return wbs=[]; if(!fs.existsSync(paths.pmxls)) return;
wb1 = X.read(fs.readFileSync(paths.pmxls), {type:TYPE}); wbs = [
wb2 = X.read(fs.readFileSync(paths.pmxls5), {type:TYPE}); X.read(fs.readFileSync(paths.pmxls), {type:TYPE}),
wb3 = X.read(fs.readFileSync(paths.pmxml), {type:TYPE}); X.read(fs.readFileSync(paths.pmxls5), {type:TYPE}),
wb4 = X.read(fs.readFileSync(paths.pmxlsx), {type:TYPE}); X.read(fs.readFileSync(paths.pmxml), {type:TYPE}),
wb5 = X.read(fs.readFileSync(paths.pmxlsb), {type:TYPE}); X.read(fs.readFileSync(paths.pmxlsx), {type:TYPE}),
wbs = [wb1, wb2, wb3, wb4, wb5]; X.read(fs.readFileSync(paths.pmxlsb), {type:TYPE})
];
}); });
if(typeof before != 'undefined') before(bef); if(typeof before != 'undefined') before(bef);
else it('before', bef); else it('before', bef);
@ -1149,17 +1182,17 @@ describe('parse features', function() {
check_margin(wb.Sheets["Normal"]["!margins"], [0.7, 0.7, 0.75, 0.75, 0.3, 0.3]); check_margin(wb.Sheets["Normal"]["!margins"], [0.7, 0.7, 0.75, 0.75, 0.3, 0.3]);
}); });
}); });
it('should parse wide margins ', function() { it('should parse wide margins', function() {
wbs.forEach(function(wb) { wbs.forEach(function(wb) {
check_margin(wb.Sheets["Wide"]["!margins"], [1, 1, 1, 1, 0.5, 0.5]); check_margin(wb.Sheets["Wide"]["!margins"], [1, 1, 1, 1, 0.5, 0.5]);
}); });
}); });
it('should parse narrow margins ', function() { it('should parse narrow margins', function() {
wbs.forEach(function(wb) { wbs.forEach(function(wb) {
check_margin(wb.Sheets["Narrow"]["!margins"], [0.25, 0.25, 0.75, 0.75, 0.3, 0.3]); check_margin(wb.Sheets["Narrow"]["!margins"], [0.25, 0.25, 0.75, 0.75, 0.3, 0.3]);
}); });
}); });
it('should parse custom margins ', function() { it('should parse custom margins', function() {
wbs.forEach(function(wb) { wbs.forEach(function(wb) {
check_margin(wb.Sheets["Custom 1 Inch Centered"]["!margins"], [1, 1, 1, 1, 0.3, 0.3]); check_margin(wb.Sheets["Custom 1 Inch Centered"]["!margins"], [1, 1, 1, 1, 0.3, 0.3]);
check_margin(wb.Sheets["1 Inch HF"]["!margins"], [0.7, 0.7, 0.75, 0.75, 1, 1]); check_margin(wb.Sheets["1 Inch HF"]["!margins"], [0.7, 0.7, 0.75, 0.75, 1, 1]);
@ -1255,7 +1288,7 @@ describe('write features', function() {
baseprops = { baseprops = {
Category: "Newspaper", Category: "Newspaper",
ContentStatus: "Published", ContentStatus: "Published",
Keywords: "print", Keywords: "",
LastAuthor: "Perry White", LastAuthor: "Perry White",
LastPrinted: "1978-12-15", LastPrinted: "1978-12-15",
RevNumber: 6969, RevNumber: 6969,
@ -1271,7 +1304,7 @@ describe('write features', function() {
if(typeof before != 'undefined') before(bef); if(typeof before != 'undefined') before(bef);
else it('before', bef); else it('before', bef);
['xlml', 'xlsx', 'xlsb'].forEach(function(w) { it(w, function() { ['xlml', 'xlsx', 'xlsb'].forEach(function(w) { it(w, function() {
wb = { var wb = {
Props: {}, Props: {},
SheetNames: ["Sheet1"], SheetNames: ["Sheet1"],
Sheets: {Sheet1: ws} Sheets: {Sheet1: ws}
@ -1389,7 +1422,7 @@ describe('roundtrip features', function() {
if(m[0].t === 'n' && m[1].t === 'n') assert.equal(m[0].v, m[1].v); if(m[0].t === 'n' && m[1].t === 'n') assert.equal(m[0].v, m[1].v);
else if(m[0].t === 'd' && m[1].t === 'd') assert.equal(m[0].v.toString(), m[1].v.toString()); else if(m[0].t === 'd' && m[1].t === 'd') assert.equal(m[0].v.toString(), m[1].v.toString());
else if(m[1].t === 'n') assert(Math.abs(datenum(parseDate(m[0].v)) - m[1].v) < 0.01); else if(m[1].t === 'n') assert(Math.abs(datenum(browser ? parseDate(m[0].v) : new Date(m[0].v)) - m[1].v) < 0.01);
}); });
}); });
}); });
@ -1543,10 +1576,9 @@ describe('invalid files', function() {
}); });
describe('write', function() { describe('write', function() {
it('should pass -> XLSX', function() { it('should pass -> XLSX', function() {
X.write(X.read(fs.readFileSync(paths.fstxlsb), {type:TYPE}), {type:TYPE}); ["fstxlsb", "fstxlsx", "fstxls", "fstxml"].forEach(function(n) {
X.write(X.read(fs.readFileSync(paths.fstxlsx), {type:TYPE}), {type:TYPE}); X.write(X.read(fs.readFileSync(paths[n]), {type:TYPE}), {type:TYPE});
X.write(X.read(fs.readFileSync(paths.fstxls), {type:TYPE}), {type:TYPE}); });
X.write(X.read(fs.readFileSync(paths.fstxml), {type:TYPE}), {type:TYPE});
}); });
it('should pass if a sheet is missing', function() { it('should pass if a sheet is missing', function() {
var wb = X.read(fs.readFileSync(paths.fstxlsx), {type:TYPE}); delete wb.Sheets[wb.SheetNames[0]]; var wb = X.read(fs.readFileSync(paths.fstxlsx), {type:TYPE}); delete wb.Sheets[wb.SheetNames[0]];
@ -1700,16 +1732,16 @@ describe('json output', function() {
var _data = [["S","h","e","e","t","J","S"],[1,2,3,4,5,6,7],[],[2,3,4,5,6,7,8]]; var _data = [["S","h","e","e","t","J","S"],[1,2,3,4,5,6,7],[],[2,3,4,5,6,7,8]];
var _ws = X.utils.aoa_to_sheet(_data); var _ws = X.utils.aoa_to_sheet(_data);
var json1 = X.utils.sheet_to_json(_ws); var json1 = X.utils.sheet_to_json(_ws);
var json2 = X.utils.sheet_to_json(_ws, {header:1});
var json3 = X.utils.sheet_to_json(_ws, {blankrows:true});
var json4 = X.utils.sheet_to_json(_ws, {blankrows:true, header:1});
var json5 = X.utils.sheet_to_json(_ws, {blankrows:false});
var json6 = X.utils.sheet_to_json(_ws, {blankrows:false, header:1});
assert.equal(json1.length, 2); // = 2 non-empty records assert.equal(json1.length, 2); // = 2 non-empty records
var json2 = X.utils.sheet_to_json(_ws, {header:1});
assert.equal(json2.length, 4); // = 4 sheet rows assert.equal(json2.length, 4); // = 4 sheet rows
var json3 = X.utils.sheet_to_json(_ws, {blankrows:true});
assert.equal(json3.length, 3); // = 2 records + 1 blank row assert.equal(json3.length, 3); // = 2 records + 1 blank row
var json4 = X.utils.sheet_to_json(_ws, {blankrows:true, header:1});
assert.equal(json4.length, 4); // = 4 sheet rows assert.equal(json4.length, 4); // = 4 sheet rows
var json5 = X.utils.sheet_to_json(_ws, {blankrows:false});
assert.equal(json5.length, 2); // = 2 records assert.equal(json5.length, 2); // = 2 records
var json6 = X.utils.sheet_to_json(_ws, {blankrows:false, header:1});
assert.equal(json6.length, 3); // = 4 sheet rows - 1 blank row assert.equal(json6.length, 3); // = 4 sheet rows - 1 blank row
}); });
it('should have an index that starts with zero when selecting range', function() { it('should have an index that starts with zero when selecting range', function() {
@ -1724,36 +1756,40 @@ describe('json output', function() {
}); });
var codes = [["あ 1", "\u00E3\u0081\u0082 1"]] var codes = [["あ 1", "\u00E3\u0081\u0082 1"]];
var plaintext_val = [ var plaintext_val = [
["A1", 'n', -0.08, "-0.08"], ["A1", 'n', -0.08, "-0.08"],
["B1", 'n', 4001, "4,001"], ["B1", 'n', 4001, "4,001"],
["C1", 's', "あ 1", "あ 1"], ["C1", 's', "あ 1", "あ 1"],
["A2", 'n', 41.08, "$41.08"], ["A2", 'n', 41.08, "$41.08"],
["B2", 'n', 0.11, "11%"], ["B2", 'n', 0.11, "11%"],
["B3", 'b', true, "TRUE"], ["C3", 'b', true, "TRUE"],
["C3", 'b', false, "FALSE"], ["D3", 'b', false, "FALSE"],
["A3"]]; ["B3", 's', " ", " "],
function plaintext_test(wb, raw, sn) { ["A3"]
var sheet = wb.Sheets[sn || wb.SheetNames[0]]; ];
function plaintext_test(wb, raw, t) {
var sheet = wb.Sheets[wb.SheetNames[0]];
plaintext_val.forEach(function(x) { plaintext_val.forEach(function(x) {
var cell = get_cell(sheet, x[0]); var cell = get_cell(sheet, x[0]);
var tcval = x[2+!!raw];
var type = raw ? 's' : x[1]; // != 's' ? x[1] : tcval.length === 0 ? 'z' : 's';
if(x.length == 1) { if(cell) { assert.equal(cell.t, 'z'); assert(!cell.v); } return; } if(x.length == 1) { if(cell) { assert.equal(cell.t, 'z'); assert(!cell.v); } return; }
assert.equal(cell.v, x[2+!!raw]); assert.equal(cell.t, raw ? 's' : x[1]); assert.equal(cell.v, tcval); assert.equal(cell.t, type);
}); });
} }
function make_html_str(idx) { return ["<table>", function make_html_str(idx) { return ["<table>",
"<tr><td>-0.08</td><td>4,001</td><td>", codes[0][idx], "</td></tr>", "<tr><td>-0.08</td><td>4,001</td><td>", codes[0][idx], "</td></tr>",
"<tr><td>$41.08</td><td>11%</td></tr>", "<tr><td>$41.08</td><td>11%</td></tr>",
"<tr><td></td><td>TRUE</td><td>FALSE</td></tr>", "<tr><td></td><td> \n&nbsp;</td><td>TRUE</td><td>FALSE</td></tr>",
"</table>" ].join(""); } "</table>" ].join(""); }
function make_csv_str(idx) { return [ '\u00EF\u00BB\u00BF' + function make_csv_str(idx) { return [ (idx == 1 ? '\u00EF\u00BB\u00BF' : "") +
'-0.08,"4,001",' + codes[0][idx] + '', '-0.08,"4,001",' + codes[0][idx] + '',
'$41.08,11%', '$41.08,11%',
',TRUE,FALSE' ', ,TRUE,FALSE'
].join("\n"); } ].join("\n"); }
var html_bstr = make_html_str(1), html_str = make_html_str(0); var html_bstr = make_html_str(1), html_str = make_html_str(0);
var csv_bstr = make_csv_str(1); var csv_bstr = make_csv_str(1), csv_str = make_csv_str(0);
describe('csv', function() { describe('csv', function() {
@ -1779,7 +1815,7 @@ describe('csv', function() {
var cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3"); var cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3");
assert.equal(cell.w, '2/19/14'); assert.equal(cell.w, '2/19/14');
opts.cellDates = true; opts.cellDates = true;
var cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3"); cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3");
assert.equal(cell.w, '2/19/14'); assert.equal(cell.w, '2/19/14');
}); });
it('should honor dateNF override', function() { it('should honor dateNF override', function() {
@ -1788,7 +1824,7 @@ describe('csv', function() {
/* NOTE: IE interprets 2-digit years as 19xx */ /* NOTE: IE interprets 2-digit years as 19xx */
assert(cell.w == '2014-02-19' || cell.w == '1914-02-19'); assert(cell.w == '2014-02-19' || cell.w == '1914-02-19');
opts.cellDates = true; opts.dateNF = "YY-MM-DD"; opts.cellDates = true; opts.dateNF = "YY-MM-DD";
var cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3"); cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3");
assert.equal(cell.w, '14-02-19'); assert.equal(cell.w, '14-02-19');
}); });
it('should interpret dateNF', function() { it('should interpret dateNF', function() {
@ -1802,8 +1838,8 @@ describe('csv', function() {
assert.equal(cell.v.getMonth(), 2); assert.equal(cell.v.getMonth(), 2);
assert.equal(cell.w, "2/3/14"); assert.equal(cell.w, "2/3/14");
}); });
it('should interpret values by default', function() { plaintext_test(X.read(csv_bstr, {type:"binary"}), false); }); it('should interpret values by default', function() { plaintext_test(X.read(csv_bstr, {type:"binary"}), false, false); });
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(csv_bstr, {type:"binary", raw:true}), true); }); it('should generate strings if raw option is passed', function() { plaintext_test(X.read(csv_bstr, {type:"binary", raw:true}), true, false); });
it('should handle formulae', function() { it('should handle formulae', function() {
var bb = '=,=1+1,="100"'; var bb = '=,=1+1,="100"';
var sheet = X.read(bb, {type:"binary"}).Sheets.Sheet1; var sheet = X.read(bb, {type:"binary"}).Sheets.Sheet1;
@ -1903,12 +1939,13 @@ function get_dom_element(html) {
describe('HTML', function() { describe('HTML', function() {
describe('input string', function(){ describe('input string', function(){
it('should interpret values by default', function() { plaintext_test(X.read(html_bstr, {type:"binary"}), false); }); it('should interpret values by default', function() { plaintext_test(X.read(html_bstr, {type:"binary"}), false, false); });
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(html_bstr, {type:"binary", raw:true}), true); }); it('should generate strings if raw option is passed', function() { plaintext_test(X.read(html_bstr, {type:"binary", raw:true}), true, false); });
it('should handle "string" type', function() { plaintext_test(X.read(html_str, {type:"string"}), false, false); });
}); });
(domtest ? describe : describe.skip)('input DOM', function() { (domtest ? describe : describe.skip)('input DOM', function() {
it('should interpret values by default', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str)), false); }); it('should interpret values by default', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str)), false, true); });
it('should generate strings if raw option is passed', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str), {raw:true}), true); }); it('should generate strings if raw option is passed', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str), {raw:true}), true, true); });
}); });
}); });
@ -1933,25 +1970,14 @@ describe('js -> file -> js', function() {
ofmt.forEach(function(f) { ofmt.forEach(function(f) {
it(f, function() { it(f, function() {
var newwb = X.read(X.write(wb, {type:BIN, bookType: f}), {type:BIN}); var newwb = X.read(X.write(wb, {type:BIN, bookType: f}), {type:BIN});
/* int */ var cb = function(cell) { eqcell(wb, newwb, 'Sheet1', cell); };
eqcell(wb, newwb, 'Sheet1', 'A1'); ['A1', 'B1', 'C1'].forEach(cb); /* int */
eqcell(wb, newwb, 'Sheet1', 'B1'); ['B4'].forEach(cb); /* double */
eqcell(wb, newwb, 'Sheet1', 'C1'); ['A2', 'B2'].forEach(cb); /* bool */
/* double */ ['D2', 'A3', 'B3', 'A4', 'C4'].forEach(cb); /* string */
eqcell(wb, newwb, 'Sheet1', 'B4'); if(!DIF_XL) cb('C3'); /* date */
/* bool */
eqcell(wb, newwb, 'Sheet1', 'A2');
eqcell(wb, newwb, 'Sheet1', 'B2');
/* string */
eqcell(wb, newwb, 'Sheet1', 'D2');
eqcell(wb, newwb, 'Sheet1', 'A3');
eqcell(wb, newwb, 'Sheet1', 'B3');
eqcell(wb, newwb, 'Sheet1', 'A4');
eqcell(wb, newwb, 'Sheet1', 'C4');
if(DIF_XL && f == "dif") assert.equal(get_cell(newwb.Sheets["Sheet1"], 'D3').v, '=""0.3""');// dif forces string formula if(DIF_XL && f == "dif") assert.equal(get_cell(newwb.Sheets["Sheet1"], 'D3').v, '=""0.3""');// dif forces string formula
else eqcell(wb, newwb, 'Sheet1', 'D3'); else eqcell(wb, newwb, 'Sheet1', 'D3');
/* date */
if(!DIF_XL) eqcell(wb, newwb, 'Sheet1', 'C3');
}); });
}); });
}); });
@ -1997,12 +2023,13 @@ describe('corner cases', function() {
}); });
it('SSF oddities', function() { it('SSF oddities', function() {
var ssfdata = require('./misc/ssf.json'); var ssfdata = require('./misc/ssf.json');
var cb = function(d, j) { return function() { return X.SSF.format(d[0], d[j][0]); }; };
ssfdata.forEach(function(d) { ssfdata.forEach(function(d) {
for(var j=1;j<d.length;++j) { for(var j=1;j<d.length;++j) {
if(d[j].length == 2) { if(d[j].length == 2) {
var expected = d[j][1], actual = X.SSF.format(d[0], d[j][0], {}); var expected = d[j][1], actual = X.SSF.format(d[0], d[j][0], {});
assert.equal(actual, expected); assert.equal(actual, expected);
} else if(d[j][2] !== "#") assert.throws(function() { SSF.format(d[0], d[j][0]); }); } else if(d[j][2] !== "#") assert.throws(cb(d, j));
} }
}); });
}); });
@ -2031,7 +2058,7 @@ describe('encryption', function() {
} }
}); });
it.skip('should decrypt file', function() { it.skip('should decrypt file', function() {
var wb = X.read(fs.readFileSync(dir + x), {type:TYPE,password:'password',WTF:opts.WTF}); /*var wb = */X.read(fs.readFileSync(dir + x), {type:TYPE,password:'password',WTF:opts.WTF});
}); });
}); });
}); });

File diff suppressed because one or more lines are too long

@ -1,3 +1,33 @@
./test_files/artifacts/quattro/write_.csv
./test_files/artifacts/quattro/write_.dif
./test_files/artifacts/quattro/write_.slk
./test_files/artifacts/quattro/write_57.xls
./test_files/artifacts/quattro/write_6.wb2
./test_files/artifacts/quattro/write_6b.wb2
./test_files/artifacts/quattro/write_8.wb3
./test_files/artifacts/quattro/write_9.qpw
./test_files/artifacts/quattro/write_97.xls
./test_files/artifacts/quattro/write_L1.wks
./test_files/artifacts/quattro/write_L2.wk1
./test_files/artifacts/quattro/write_L3.wk3
./test_files/artifacts/quattro/write_L45.wk4
./test_files/artifacts/quattro/write_L9.123
./test_files/artifacts/quattro/write_L97.123
./test_files/artifacts/quattro/write_Led.wke
./test_files/artifacts/quattro/write_qpdos.wq1
./test_files/artifacts/quattro/write_qpw.wb1
./test_files/artifacts/wps/write.dbf
./test_files/artifacts/wps/write.dif
./test_files/artifacts/wps/write.et
./test_files/artifacts/wps/write.xls
./test_files/artifacts/wps/write.xlsx
./test_files/artifacts/wps/write.xml
./test_files/author_snowman.xls
./test_files/author_snowman.xls5
./test_files/author_snowman.xlsb
./test_files/author_snowman.xlsx
./test_files/author_snowman.xml
./test_files/author_snowman.ods
./test_files/AutoFilter.xls ./test_files/AutoFilter.xls
./test_files/AutoFilter.xml ./test_files/AutoFilter.xml
./test_files/AutoFilter.ods ./test_files/AutoFilter.ods

@ -6,7 +6,7 @@ var data = [
[1, 2, 3], [1, 2, 3],
[true, false, null, "sheetjs"], [true, false, null, "sheetjs"],
["foo", "bar", new Date("2014-02-19T14:30Z"), "0.3"], ["foo", "bar", new Date("2014-02-19T14:30Z"), "0.3"],
["baz", null, "qux", 3.14159], ["baz", null, "\u0BEE", 3.14159],
["hidden"], ["hidden"],
["visible"] ["visible"]
]; ];

@ -6,7 +6,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false */ /*global global, exports, module, require:false, process:false, Buffer:false */
var XLSX = {}; var XLSX = {};
(function make_xlsx(XLSX){ (function make_xlsx(XLSX){
XLSX.version = '0.11.4'; XLSX.version = '0.11.5';
var current_codepage = 1200; var current_codepage = 1200;
/*:: declare var cptable:any; */ /*:: declare var cptable:any; */
/*global cptable:true */ /*global cptable:true */
@ -1974,7 +1974,7 @@ function getzipfile(zip, file/*:string*/) {
return o; return o;
} }
function getzipdata(zip, file/*:string*/, safe/*:?boolean*/) { function getzipdata(zip, file/*:string*/, safe/*:?boolean*/)/*:any*/ {
if(!safe) return getdata(getzipfile(zip, file)); if(!safe) return getdata(getzipfile(zip, file));
if(!file) return null; if(!file) return null;
try { return getzipdata(zip, file); } catch(e) { return null; } try { return getzipdata(zip, file); } catch(e) { return null; }
@ -2111,6 +2111,31 @@ var utf8read/*:StringConv*/ = function utf8reada(orig) {
return out; return out;
}; };
var utf8write/*:StringConv*/ = function(orig) {
var out = [], i = 0, c = 0, d = 0;
while(i < orig.length) {
c = orig.charCodeAt(i++);
switch(true) {
case c < 128: out.push(String.fromCharCode(c)); break;
case c < 2048:
out.push(String.fromCharCode(192 + (c >> 6)));
out.push(String.fromCharCode(128 + (c & 63)));
break;
case c >= 55296 && c < 57344:
c -= 55296; d = orig.charCodeAt(i++) - 56320 + (c<<10);
out.push(String.fromCharCode(240 + ((d >>18) & 7)));
out.push(String.fromCharCode(144 + ((d >>12) & 63)));
out.push(String.fromCharCode(128 + ((d >> 6) & 63)));
out.push(String.fromCharCode(128 + (d & 63)));
break;
default:
out.push(String.fromCharCode(224 + (c >> 12)));
out.push(String.fromCharCode(128 + ((c >> 6) & 63)));
out.push(String.fromCharCode(128 + (c & 63)));
}
}
return out.join("");
};
if(has_buf) { if(has_buf) {
var utf8readb = function utf8readb(data) { var utf8readb = function utf8readb(data) {
@ -2134,6 +2159,8 @@ if(has_buf) {
// $FlowIgnore // $FlowIgnore
var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); }; var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc; if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
utf8write = function(data) { return new Buffer(data, 'utf8').toString("binary"); };
} }
// matches <foo>...</foo> extracts content // matches <foo>...</foo> extracts content
@ -2146,6 +2173,10 @@ var matchtag = (function() {
}; };
})(); })();
function htmldecode(str/*:string*/)/*:string*/ {
return str.trim().replace(/\s+/g, " ").replace(/<\s*[bB][rR]\s*\/?/g,"\n").replace(/<[^>]*>/g,"").replace(/&nbsp;/g, " ");
}
var vtregex = (function(){ var vt_cache = {}; var vtregex = (function(){ var vt_cache = {};
return function vt_regex(bt) { return function vt_regex(bt) {
if(vt_cache[bt] !== undefined) return vt_cache[bt]; if(vt_cache[bt] !== undefined) return vt_cache[bt];
@ -2214,7 +2245,7 @@ var XLMLNS = ({
'v': 'urn:schemas-microsoft-com:vml', 'v': 'urn:schemas-microsoft-com:vml',
'html': 'http://www.w3.org/TR/REC-html40' 'html': 'http://www.w3.org/TR/REC-html40'
}/*:any*/); }/*:any*/);
function read_double_le(b, idx/*:number*/)/*:number*/ { function read_double_le(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ {
var s = 1 - 2 * (b[idx + 7] >>> 7); var s = 1 - 2 * (b[idx + 7] >>> 7);
var e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 0x0f); var e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 0x0f);
var m = (b[idx+6]&0x0f); var m = (b[idx+6]&0x0f);
@ -2225,7 +2256,7 @@ function read_double_le(b, idx/*:number*/)/*:number*/ {
return s * Math.pow(2, e - 52) * m; return s * Math.pow(2, e - 52) * m;
} }
function write_double_le(b, v/*:number*/, idx/*:number*/) { function write_double_le(b/*:RawBytes|CFBlob*/, v/*:number*/, idx/*:number*/) {
var bs = ((v < 0 || 1/v == -Infinity) ? 1 : 0) << 7, e = 0, m = 0; var bs = ((v < 0 || 1/v == -Infinity) ? 1 : 0) << 7, e = 0, m = 0;
var av = bs ? -v : v; var av = bs ? -v : v;
if(!isFinite(av)) { e = 0x7ff; m = isNaN(v) ? 0x6969 : 0; } if(!isFinite(av)) { e = 0x7ff; m = isNaN(v) ? 0x6969 : 0; }
@ -2241,61 +2272,61 @@ function write_double_le(b, v/*:number*/, idx/*:number*/) {
b[idx + 7] = (e >> 4) | bs; b[idx + 7] = (e >> 4) | bs;
} }
var __toBuffer, ___toBuffer; var __toBuffer = function(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; };
__toBuffer = ___toBuffer = function toBuffer_(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; }; var ___toBuffer = __toBuffer;
var __utf16le, ___utf16le; var __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join(""); };
__utf16le = ___utf16le = function utf16le_(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join(""); }; var ___utf16le = __utf16le;
var __hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); }; var __hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { var ss/*:Array<string>*/=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); };
var ___hexlify = __hexlify; var ___hexlify = __hexlify;
var __utf8, ___utf8; var __utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
__utf8 = ___utf8 = function(b,s,e) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); }; var ___utf8 = __utf8;
var __lpstr, ___lpstr; var __lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
__lpstr = ___lpstr = function lpstr_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";}; var ___lpstr = __lpstr;
var __lpwstr, ___lpwstr; var __lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
__lpwstr = ___lpwstr = function lpwstr_(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";}; var ___lpwstr = __lpwstr;
var __lpp4, ___lpp4; var __lpp4, ___lpp4;
__lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";}; __lpp4 = ___lpp4 = function lpp4_(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
var __8lpp4, ___8lpp4; var __8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
__8lpp4 = ___8lpp4 = function lpp4_8(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";}; var ___8lpp4 = __8lpp4;
var __double, ___double; var __double, ___double;
__double = ___double = function(b, idx) { return read_double_le(b, idx);}; __double = ___double = function(b/*:RawBytes|CFBlob*/, idx/*:number*/) { return read_double_le(b, idx);};
var is_buf = function is_buf_a(a) { return Array.isArray(a); }; var is_buf = function is_buf_a(a) { return Array.isArray(a); };
if(has_buf/*:: && typeof Buffer != 'undefined'*/) {
__utf16le = function utf16le_b(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e); }; if(has_buf/*:: && typeof Buffer !== 'undefined'*/) {
__hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); }; __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___utf16le(b,s,e); return b.toString('utf16le',s,e); };
__lpstr = function lpstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";}; __hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { return Buffer.isBuffer(b)/*:: && b instanceof Buffer*/ ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
__lpwstr = function lpwstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);}; __lpstr = function lpstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
__lpp4 = function lpp4_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);}; __lpwstr = function lpwstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
__8lpp4 = function lpp4_8b(b,i) { if(!Buffer.isBuffer(b)) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);}; __lpp4 = function lpp4_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);};
__utf8 = function utf8_b(b, s,e) { return b.toString('utf8',s,e); }; __8lpp4 = function lpp4_8b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);};
__utf8 = function utf8_b(b/*:RawBytes|CFBlob*/, s/*:number*/, e/*:number*/) { return (Buffer.isBuffer(b)/*:: && (b instanceof Buffer)*/) ? b.toString('utf8',s,e) : __utf8(b,s,e); };
__toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);}; __toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);};
bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); }; bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); };
__double = function double_(b,i) { if(Buffer.isBuffer(b)/*::&& b instanceof Buffer*/) return b.readDoubleLE(i); return ___double(b,i); }; __double = function double_(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(Buffer.isBuffer(b)/*::&& b instanceof Buffer*/) return b.readDoubleLE(i); return ___double(b,i); };
is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); }; is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); };
} }
/* from js-xls */ /* from js-xls */
if(typeof cptable !== 'undefined') { if(typeof cptable !== 'undefined') {
__utf16le = function(b,s,e) { return cptable.utils.decode(1200, b.slice(s,e)); }; __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(1200, b.slice(s,e)); };
__utf8 = function(b,s,e) { return cptable.utils.decode(65001, b.slice(s,e)); }; __utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(65001, b.slice(s,e)); };
__lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";}; __lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";};
__lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";}; __lpwstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = 2*__readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";};
__lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";}; __lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";};
__8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";}; __8lpp4 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";};
} }
var __readUInt8 = function(b, idx/*:number*/)/*:number*/ { return b[idx]; }; var __readUInt8 = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx]; };
var __readUInt16LE = function(b, idx/*:number*/)/*:number*/ { return b[idx+1]*(1<<8)+b[idx]; }; var __readUInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+1]*(1<<8)+b[idx]; };
var __readInt16LE = function(b, idx/*:number*/)/*:number*/ { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; }; var __readInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; };
var __readUInt32LE = function(b, idx/*:number*/)/*:number*/ { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; }; var __readUInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
var __readInt32LE = function(b, idx/*:number*/)/*:number*/ { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; }; var __readInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
var ___unhexlify = function(s) { return s.match(/../g).map(function(x) { return parseInt(x,16);}); }; var ___unhexlify = function(s/*:string*/)/*:Array<number>*/ { return (s.match(/../g)||[]).map(function(x) { return parseInt(x,16);}); };
var __unhexlify = typeof Buffer !== "undefined" ? function(s) { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify; var __unhexlify = typeof Buffer !== "undefined" ? function(s/*:string*/)/*:Array<number>|Buffer*/ { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;
function ReadShift(size/*:number*/, t/*:?string*/) { function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
var o="", oI, oR, oo=[], w, vv, i, loc; var o="", oI/*:: :number = 0*/, oR, oo=[], w, vv, i, loc;
switch(t) { switch(t) {
case 'dbcs': case 'dbcs':
loc = this.l; loc = this.l;
@ -2367,11 +2398,11 @@ function ReadShift(size/*:number*/, t/*:?string*/) {
this.l+=size; return o; this.l+=size; return o;
} }
var __writeUInt16LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); }; var __writeUInt32LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); b[idx+2] = ((val >>> 16) & 0xFF); b[idx+3] = ((val >>> 24) & 0xFF); };
var __writeUInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); b[idx+2] = ((val >>> 16) & 0xFF); b[idx+3] = ((val >>> 24) & 0xFF); }; var __writeInt32LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); };
var __writeInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); }; var __writeUInt16LE = function(b/*:RawBytes|CFBlob*/, val/*:number*/, idx/*:number*/)/*:void*/ { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); };
function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/) { function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/)/*:any*/ {
var size = 0, i = 0; var size = 0, i = 0;
if(f === 'dbcs') { if(f === 'dbcs') {
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */ /*:: if(typeof val !== 'string') throw new Error("unreachable"); */
@ -2387,6 +2418,7 @@ function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/) {
this[this.l++] = parseInt(val.slice(2*i, 2*i+2), 16)||0; this[this.l++] = parseInt(val.slice(2*i, 2*i+2), 16)||0;
} return this; } return this;
} else if(f === 'utf16le') { } else if(f === 'utf16le') {
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
var end/*:number*/ = this.l + t; var end/*:number*/ = this.l + t;
for(i = 0; i < Math.min(val.length, t); ++i) { for(i = 0; i < Math.min(val.length, t); ++i) {
var cc = val.charCodeAt(i); var cc = val.charCodeAt(i);
@ -2408,20 +2440,20 @@ function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/) {
this.l += size; return this; this.l += size; return this;
} }
function CheckField(hexstr, fld) { function CheckField(hexstr/*:string*/, fld/*:string*/)/*:void*/ {
var m = __hexlify(this,this.l,hexstr.length>>1); var m = __hexlify(this,this.l,hexstr.length>>1);
if(m !== hexstr) throw fld + 'Expected ' + hexstr + ' saw ' + m; if(m !== hexstr) throw new Error(fld + 'Expected ' + hexstr + ' saw ' + m);
this.l += hexstr.length>>1; this.l += hexstr.length>>1;
} }
function prep_blob(blob, pos/*:number*/) { function prep_blob(blob, pos/*:number*/)/*:void*/ {
blob.l = pos; blob.l = pos;
blob.read_shift = ReadShift; blob.read_shift = /*::(*/ReadShift/*:: :any)*/;
blob.chk = CheckField; blob.chk = CheckField;
blob.write_shift = WriteShift; blob.write_shift = WriteShift;
} }
function parsenoop(blob, length/*:number*/) { blob.l += length; } function parsenoop(blob, length/*:: :number, opts?:any */) { blob.l += length; }
function parsenooplog(blob, length/*:number*/) { if(typeof console != 'undefined') console.log(blob.slice(blob.l, blob.l + length)); blob.l += length; } function parsenooplog(blob, length/*:number*/) { if(typeof console != 'undefined') console.log(blob.slice(blob.l, blob.l + length)); blob.l += length; }
function writenoop(blob, length/*:number*/) { blob.l += length; } function writenoop(blob, length/*:number*/) { blob.l += length; }
@ -3709,6 +3741,7 @@ var CORE_PROPS_REGEX/*:Array<RegExp>*/ = (function() {
function parse_core_props(data) { function parse_core_props(data) {
var p = {}; var p = {};
data = utf8read(data);
for(var i = 0; i < CORE_PROPS.length; ++i) { for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]); var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
@ -3776,6 +3809,7 @@ RELS.EXT_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relatio
function parse_ext_props(data, p, opts) { function parse_ext_props(data, p, opts) {
var q = {}; if(!p) p = {}; var q = {}; if(!p) p = {};
data = utf8read(data);
EXT_PROPS.forEach(function(f) { EXT_PROPS.forEach(function(f) {
switch(f[2]) { switch(f[2]) {
@ -4216,7 +4250,7 @@ function parse_PropertySet(blob, PIDSI) {
case 1252: case 1252:
case 65000: case -536: case 65000: case -536:
case 65001: case -535: case 65001: case -535:
set_cp(CodePage = PropH[piddsi.n]); break; set_cp(CodePage = PropH[piddsi.n]>>>0 & 0xFFFF); break;
default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]); default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
} }
} else { } else {
@ -4258,6 +4292,7 @@ function parse_PropertySet(blob, PIDSI) {
/* [MS-OLEPS] 2.21 PropertySetStream */ /* [MS-OLEPS] 2.21 PropertySetStream */
function parse_PropertySetStream(file, PIDSI) { function parse_PropertySetStream(file, PIDSI) {
var blob = file.content; var blob = file.content;
if(!blob) return ({}/*:any*/);
prep_blob(blob, 0); prep_blob(blob, 0);
var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0; var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;
@ -4478,7 +4513,7 @@ function parse_XLSCell(blob, length)/*:Cell*/ {
var ixfe = blob.read_shift(2); var ixfe = blob.read_shift(2);
return ({r:rw, c:col, ixfe:ixfe}/*:any*/); return ({r:rw, c:col, ixfe:ixfe}/*:any*/);
} }
function write_XLSCell(R/*:number*/, C/*:number*/, ixfe/*:number*/, o) { function write_XLSCell(R/*:number*/, C/*:number*/, ixfe/*:?number*/, o) {
if(!o) o = new_buf(6); if(!o) o = new_buf(6);
o.write_shift(2, R); o.write_shift(2, R);
o.write_shift(2, C); o.write_shift(2, C);
@ -5768,7 +5803,7 @@ var SYLK = (function() {
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ { function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
var preamble/*:Array<string>*/ = ["ID;PWXL;N;E"], o/*:Array<string>*/ = []; var preamble/*:Array<string>*/ = ["ID;PWXL;N;E"], o/*:Array<string>*/ = [];
var r = decode_range(ws['!ref']), cell/*:Cell*/; var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = Array.isArray(ws); var dense = Array.isArray(ws);
var RS = "\r\n"; var RS = "\r\n";
@ -5852,7 +5887,7 @@ var DIF = (function() {
}; };
return function sheet_to_dif(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ { return function sheet_to_dif(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
var o/*:Array<string>*/ = []; var o/*:Array<string>*/ = [];
var r = decode_range(ws['!ref']), cell/*:Cell*/; var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = Array.isArray(ws); var dense = Array.isArray(ws);
push_field(o, "TABLE", 0, 1, "sheetjs"); push_field(o, "TABLE", 0, 1, "sheetjs");
push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,""); push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,"");
@ -5968,6 +6003,7 @@ var PRN = (function() {
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"'); if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
if(s.length == 0) cell.t = 'z'; if(s.length == 0) cell.t = 'z';
else if(o.raw) { cell.t = 's'; cell.v = s; } else if(o.raw) { cell.t = 's'; cell.v = s; }
else if(s.trim().length == 0) { cell.t = 's'; cell.v = s; }
else if(s.charCodeAt(0) == 0x3D) { else if(s.charCodeAt(0) == 0x3D) {
if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); } if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); }
else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.substr(1); } else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.substr(1); }
@ -6013,12 +6049,13 @@ var PRN = (function() {
} }
function prn_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ { function prn_to_sheet(d/*:RawData*/, opts)/*:Worksheet*/ {
var str = "", bytes = firstbyte(d, opts); var str = "", bytes = opts.type == 'string' ? [0,0,0,0] : firstbyte(d, opts);
switch(opts.type) { switch(opts.type) {
case 'base64': str = Base64.decode(d); break; case 'base64': str = Base64.decode(d); break;
case 'binary': str = d; break; case 'binary': str = d; break;
case 'buffer': str = d.toString('binary'); break; case 'buffer': str = d.toString('binary'); break;
case 'array': str = cc2str(d); break; case 'array': str = cc2str(d); break;
case 'string': str = d; break;
default: throw new Error("Unrecognized type " + opts.type); default: throw new Error("Unrecognized type " + opts.type);
} }
if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str.slice(3)); if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str.slice(3));
@ -6029,7 +6066,7 @@ var PRN = (function() {
function sheet_to_prn(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ { function sheet_to_prn(ws/*:Worksheet*/, opts/*:?any*/)/*:string*/ {
var o/*:Array<string>*/ = []; var o/*:Array<string>*/ = [];
var r = decode_range(ws['!ref']), cell/*:Cell*/; var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
var dense = Array.isArray(ws); var dense = Array.isArray(ws);
for(var R = r.s.r; R <= r.e.r; ++R) { for(var R = r.s.r; R <= r.e.r; ++R) {
var oo = []; var oo = [];
@ -9349,7 +9386,7 @@ function parse_Rgce(blob, length, opts) {
return ptgs; return ptgs;
} }
function stringify_array(f) { function stringify_array(f)/*:string*/ {
var o = []; var o = [];
for(var i = 0; i < f.length; ++i) { for(var i = 0; i < f.length; ++i) {
var x = f[i], r = []; var x = f[i], r = [];
@ -9395,7 +9432,7 @@ function get_ixti_raw(supbooks, ixti/*:number*/, opts)/*:string*/ {
function get_ixti(supbooks, ixti/*:number*/, opts)/*:string*/ { function get_ixti(supbooks, ixti/*:number*/, opts)/*:string*/ {
return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts)); return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts));
} }
function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, opts) { function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, opts)/*:string*/ {
//console.log(formula); //console.log(formula);
var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}}; var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}};
var stack/*:Array<string>*/ = [], e1, e2, type, c/*:CellAddress*/, ixti=0, nameidx=0, r, sname=""; var stack/*:Array<string>*/ = [], e1, e2, type, c/*:CellAddress*/, ixti=0, nameidx=0, r, sname="";
@ -9487,7 +9524,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
case 'PtgFuncVar': /* 2.5.198.63 */ case 'PtgFuncVar': /* 2.5.198.63 */
//console.log(f[1]); //console.log(f[1]);
/* f[1] = [argc, func, type] */ /* f[1] = [argc, func, type] */
var argc/*:number*/ = f[1][0], func/*:string*/ = f[1][1]; var argc/*:number*/ = (f[1][0]/*:any*/), func/*:string*/ = (f[1][1]/*:any*/);
if(!argc) argc = 0; if(!argc) argc = 0;
var args = argc == 0 ? [] : stack.slice(-argc); var args = argc == 0 ? [] : stack.slice(-argc);
stack.length -= argc; stack.length -= argc;
@ -12065,7 +12102,7 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ {
case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break; case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
case 'b': p.v = val[1] ? true : false; break; case 'b': p.v = val[1] ? true : false; break;
case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break; case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break;
case 'str': p.t = 's'; p.v = utf8read(val[1]); break; case 'str': p.t = 's'; p.v = val[1]; break;
} }
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles); if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
C = val[0].c; C = val[0].c;
@ -13471,7 +13508,10 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
var opts = _opts || {}; var opts = _opts || {};
make_ssf(SSF); make_ssf(SSF);
var str = debom(xlml_normalize(d)); var str = debom(xlml_normalize(d));
if(opts && opts.type == 'binary' && typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str)); if(opts.type == 'binary' || opts.type == 'base64') {
if(typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str));
else str = utf8read(str);
}
var opening = str.slice(0, 1024).toLowerCase(), ishtml = false; var opening = str.slice(0, 1024).toLowerCase(), ishtml = false;
if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; }); if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; });
if(ishtml) return HTML_.to_workbook(str, opts); if(ishtml) return HTML_.to_workbook(str, opts);
@ -14298,12 +14338,6 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
case 's': t = 'String'; p = escapexml(cell.v||""); break; case 's': t = 'String'; p = escapexml(cell.v||""); break;
} }
var _v = (cell.v != null ? p : ""); var _v = (cell.v != null ? p : "");
if(opts && opts.type == 'binary' && typeof cptable !== 'undefined' && cell.t == 's') {
_v = cptable.utils.encode(65001, _v);
var __v = "";
for(var __i = 0; __i < _v.length; ++__i) __v += String.fromCharCode(_v[__i]);
_v = __v;
}
var m = '<Data ss:Type="' + t + '">' + _v + '</Data>'; var m = '<Data ss:Type="' + t + '">' + _v + '</Data>';
if((cell.c||[]).length > 0) m += write_ws_xlml_comment(cell.c); if((cell.c||[]).length > 0) m += write_ws_xlml_comment(cell.c);
@ -14388,9 +14422,10 @@ function write_xlml(wb, opts)/*:string*/ {
}); });
} }
/* [MS-OLEDS] 2.3.8 CompObjStream */ /* [MS-OLEDS] 2.3.8 CompObjStream */
function parse_compobj(obj) { function parse_compobj(obj/*:CFBEntry*/) {
var v = {}; var v = {};
var o = obj.content; var o = obj.content;
/*:: if(o == null) return; */
/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */ /* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
var l = 28, m; var l = 28, m;
@ -15208,25 +15243,31 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
} }
/* TODO: WTF */ /* TODO: WTF */
function parse_props(cfb) { function parse_props(cfb/*:CFBContainer*/, props, o) {
/* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */ /* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
var DSI = CFB.find(cfb, '!DocumentSummaryInformation'); var DSI = CFB.find(cfb, '!DocumentSummaryInformation');
if(DSI) try { cfb.DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI); } catch(e) {/* empty */} if(DSI) try {
var DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI);
for(var d in DocSummary) props[d] = DocSummary[d];
} catch(e) {if(o.WTF == 2) throw e;/* empty */}
/* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/ /* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
var SI = CFB.find(cfb, '!SummaryInformation'); var SI = CFB.find(cfb, '!SummaryInformation');
if(SI) try { cfb.Summary = parse_PropertySetStream(SI, SummaryPIDSI); } catch(e) {/* empty */} if(SI) try {
var Summary = parse_PropertySetStream(SI, SummaryPIDSI);
for(var s in Summary) if(props[s] == null) props[s] = Summary[s];
} catch(e) {if(o.WTF == 2) throw e;/* empty */}
} }
function parse_xlscfb(cfb/*:any*/, options/*:?ParseOpts*/)/*:Workbook*/ { function parse_xlscfb(cfb/*:any*/, options/*:?ParseOpts*/)/*:Workbook*/ {
if(!options) options = {}; if(!options) options = {};
fix_read_opts(options); fix_read_opts(options);
reset_cp(); reset_cp();
var CompObj, Summary, WB/*:?any*/; var CompObj/*:?CFBEntry*/, Summary, WB/*:?any*/;
if(cfb.FullPaths) { if(cfb.FullPaths) {
CompObj = CFB.find(cfb, '!CompObj'); CompObj = CFB.find(cfb, '!CompObj');
Summary = CFB.find(cfb, '!SummaryInformation'); Summary = CFB.find(cfb, '!SummaryInformation');
WB = CFB.find(cfb, '/Workbook'); WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
} else { } else {
switch(options.type) { switch(options.type) {
case 'base64': cfb = s2a(Base64.decode(cfb)); break; case 'base64': cfb = s2a(Base64.decode(cfb)); break;
@ -15237,26 +15278,24 @@ if(cfb.FullPaths) {
prep_blob(cfb, 0); prep_blob(cfb, 0);
WB = ({content: cfb}/*:any*/); WB = ({content: cfb}/*:any*/);
} }
if(!WB) WB = CFB.find(cfb, '/Book'); var CompObjP, SummaryP, WorkbookP/*:: :Workbook = XLSX.utils.book_new(); */;
var CompObjP, SummaryP, WorkbookP/*:Workbook*/;
var _data/*:?any*/; var _data/*:?any*/;
if(CompObj) CompObjP = parse_compobj(CompObj); if(CompObj) CompObjP = parse_compobj(CompObj);
if(options.bookProps && !options.bookSheets) WorkbookP = ({}/*:any*/); if(options.bookProps && !options.bookSheets) WorkbookP = ({}/*:any*/);
else { else/*:: if(cfb instanceof CFBContainer) */ {
var T = has_buf ? 'buffer' : 'array';
if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options); if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options);
/* Quattro Pro 7-8 */ /* Quattro Pro 7-8 */
else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, options); else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
/* Quattro Pro 9 */ /* Quattro Pro 9 */
else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, options); else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
else throw new Error("Cannot find Workbook stream"); else throw new Error("Cannot find Workbook stream");
} }
if(cfb.FullPaths) parse_props(cfb);
var props = {}; var props = {};
for(var y in cfb.Summary) props[y] = cfb.Summary[y]; if(cfb.FullPaths) parse_props(/*::((*/cfb/*:: :any):CFBContainer)*/, props, options);
for(y in cfb.DocSummary) props[y] = cfb.DocSummary[y];
WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */ WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
if(options.bookFiles) WorkbookP.cfb = cfb; if(options.bookFiles) WorkbookP.cfb = cfb;
/*WorkbookP.CompObjP = CompObjP; // TODO: storage? */ /*WorkbookP.CompObjP = CompObjP; // TODO: storage? */
@ -16534,7 +16573,7 @@ var XLSRecordEnum = {
var XLSRE = evert_key(XLSRecordEnum, 'n'); var XLSRE = evert_key(XLSRecordEnum, 'n');
function write_biff_rec(ba/*:BufArray*/, type/*:number|string*/, payload, length/*:?number*/) { function write_biff_rec(ba/*:BufArray*/, type/*:number|string*/, payload, length/*:?number*/) {
var t/*:number*/ = +type || +XLSRE[type]; var t/*:number*/ = +type || +XLSRE[/*::String(*/type/*::)*/];
if(isNaN(t)) return; if(isNaN(t)) return;
var len = length || (payload||[]).length || 0; var len = length || (payload||[]).length || 0;
var o = ba.next(4 + len); var o = ba.next(4 + len);
@ -16783,7 +16822,7 @@ var HTML_ = (function() {
if((RS = +tag.rowspan)>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}}); if((RS = +tag.rowspan)>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
/* TODO: generate stub cells */ /* TODO: generate stub cells */
if(!m.length) { C += CS; continue; } if(!m.length) { C += CS; continue; }
m = unescapexml(m).replace(/[\r\n]/g,""); m = htmldecode(unescapexml(m));
if(range.s.r > R) range.s.r = R; if(range.s.r > R) range.s.r = R;
if(range.e.r < R) range.e.r = R; if(range.e.r < R) range.e.r = R;
if(range.s.c > C) range.s.c = C; if(range.s.c > C) range.s.c = C;
@ -16791,7 +16830,7 @@ var HTML_ = (function() {
if(opts.dense) { if(opts.dense) {
if(!ws[R]) ws[R] = []; if(!ws[R]) ws[R] = [];
if(!m.length){} if(!m.length){}
else if(opts.raw) ws[R][C] = {t:'s', v:m}; else if(opts.raw || !m.trim().length) ws[R][C] = {t:'s', v:m};
else if(m === 'TRUE') ws[R][C] = {t:'b', v:true}; else if(m === 'TRUE') ws[R][C] = {t:'b', v:true};
else if(m === 'FALSE') ws[R][C] = {t:'b', v:false}; else if(m === 'FALSE') ws[R][C] = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)}; else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)};
@ -16801,6 +16840,7 @@ var HTML_ = (function() {
/* TODO: value parsing */ /* TODO: value parsing */
if(!m.length){} if(!m.length){}
else if(opts.raw) ws[coord] = {t:'s', v:m}; else if(opts.raw) ws[coord] = {t:'s', v:m};
else if(opts.raw || !m.trim().length) ws[coord] = {t:'s', v:m};
else if(m === 'TRUE') ws[coord] = {t:'b', v:true}; else if(m === 'TRUE') ws[coord] = {t:'b', v:true};
else if(m === 'FALSE') ws[coord] = {t:'b', v:false}; else if(m === 'FALSE') ws[coord] = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) ws[coord] = {t:'n', v:fuzzynum(m)}; else if(!isNaN(fuzzynum(m))) ws[coord] = {t:'n', v:fuzzynum(m)};
@ -16885,7 +16925,7 @@ function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
var row = rows[R]; var row = rows[R];
var elts = row.children; var elts = row.children;
for(_C = C = 0; _C < elts.length; ++_C) { for(_C = C = 0; _C < elts.length; ++_C) {
var elt = elts[_C], v = elts[_C].innerText || elts[_C].textContent || ""; var elt = elts[_C], v = htmldecode(elts[_C].innerHTML);
for(midx = 0; midx < merges.length; ++midx) { for(midx = 0; midx < merges.length; ++midx) {
var m = merges[midx]; var m = merges[midx];
if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; } if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; }
@ -16897,6 +16937,7 @@ function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
if(v != null) { if(v != null) {
if(v.length == 0) o.t = 'z'; if(v.length == 0) o.t = 'z';
else if(opts.raw){} else if(opts.raw){}
else if(v.trim().length == 0) o.t = 's';
else if(v === 'TRUE') o = {t:'b', v:true}; else if(v === 'TRUE') o = {t:'b', v:true};
else if(v === 'FALSE') o = {t:'b', v:false}; else if(v === 'FALSE') o = {t:'b', v:false};
else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)}; else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
@ -17386,7 +17427,9 @@ function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts); if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
var content = getzipstr(zip, 'content.xml'); var content = getzipstr(zip, 'content.xml');
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file"); if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
return parse_content_xml(ods ? content : utf8read(content), opts); var wb = parse_content_xml(ods ? content : utf8read(content), opts);
if(safegetzipfile(zip, 'meta.xml')) wb.Props = parse_core_props(getzipdata(zip, 'meta.xml'));
return wb;
} }
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) { function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) {
return parse_content_xml(data, opts); return parse_content_xml(data, opts);
@ -17654,8 +17697,7 @@ function get_sheet_type(n/*:string*/)/*:string*/ {
if(RELS.CS && n == RELS.CS) return "chart"; if(RELS.CS && n == RELS.CS) return "chart";
if(RELS.DS && n == RELS.DS) return "dialog"; if(RELS.DS && n == RELS.DS) return "dialog";
if(RELS.MS && n == RELS.MS) return "macro"; if(RELS.MS && n == RELS.MS) return "macro";
if(!n || !n.length) return "sheet"; return (n && n.length) ? n : "sheet";
return n;
} }
function safe_parse_wbrels(wbrels, sheets) { function safe_parse_wbrels(wbrels, sheets) {
if(!wbrels) return 0; if(!wbrels) return 0;
@ -17739,10 +17781,10 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
var props = {}, propdata = ""; var props = {}, propdata = "";
if(dir.coreprops.length) { if(dir.coreprops.length) {
propdata = getzipstr(zip, strip_front_slash(dir.coreprops[0]), true); propdata = getzipdata(zip, strip_front_slash(dir.coreprops[0]), true);
if(propdata) props = parse_core_props(propdata); if(propdata) props = parse_core_props(propdata);
if(dir.extprops.length !== 0) { if(dir.extprops.length !== 0) {
propdata = getzipstr(zip, strip_front_slash(dir.extprops[0]), true); propdata = getzipdata(zip, strip_front_slash(dir.extprops[0]), true);
if(propdata) parse_ext_props(propdata, props, opts); if(propdata) parse_ext_props(propdata, props, opts);
} }
} }
@ -18051,13 +18093,23 @@ function read_utf16(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
return read_plaintext(d, o); return read_plaintext(d, o);
} }
function bstrify(data/*:string*/)/*:string*/ {
return !data.match(/[^\x00-\x7F]/) ? data : utf8write(data);
}
function read_prn(data, d, o, str) {
if(str) { o.type = "string"; return PRN.to_workbook(data, o); }
return PRN.to_workbook(d, o);
}
function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ { function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
var zip, d = data, n=[0]; var zip, d = data, n=[0], str = false;
var o = opts||{}; var o = opts||{};
_ssfopts = {}; _ssfopts = {};
if(o.dateNF) _ssfopts.dateNF = o.dateNF; if(o.dateNF) _ssfopts.dateNF = o.dateNF;
if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64"; if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
if(o.type == "file") { o.type = "buffer"; d = _fs.readFileSync(data); } if(o.type == "file") { o.type = "buffer"; d = _fs.readFileSync(data); }
if(o.type == "string") { str = true; o.type = "binary"; d = bstrify(data); }
switch((n = firstbyte(d, o))[0]) { switch((n = firstbyte(d, o))[0]) {
case 0xD0: return read_cfb(CFB.read(d, o), o); case 0xD0: return read_cfb(CFB.read(d, o), o);
case 0x09: return parse_xlscfb(d, o); case 0x09: return parse_xlscfb(d, o);
@ -18065,7 +18117,7 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
case 0x49: if(n[1] == 0x44) return read_wb_ID(d, o); break; case 0x49: if(n[1] == 0x44) return read_wb_ID(d, o); break;
case 0x54: if(n[1] == 0x41 && n[2] == 0x42 && n[3] == 0x4C) return DIF.to_workbook(d, o); break; case 0x54: if(n[1] == 0x41 && n[2] == 0x42 && n[3] == 0x4C) return DIF.to_workbook(d, o); break;
case 0x50: if(n[1] == 0x4B && n[2] < 0x20 && n[3] < 0x20) return read_zip(d, o); break; case 0x50: if(n[1] == 0x4B && n[2] < 0x20 && n[3] < 0x20) return read_zip(d, o); break;
case 0xEF: return n[3] == 0x3C ? parse_xlml(d, o) : PRN.to_workbook(d,o); case 0xEF: return n[3] == 0x3C ? parse_xlml(d, o) : read_prn(data, d, o, str);
case 0xFF: if(n[1] == 0xFE){ return read_utf16(d, o); } break; case 0xFF: if(n[1] == 0xFE){ return read_utf16(d, o); } break;
case 0x00: if(n[1] == 0x00 && n[2] >= 0x02 && n[3] == 0x00) return WK_.to_workbook(d, o); break; case 0x00: if(n[1] == 0x00 && n[2] >= 0x02 && n[3] == 0x00) return WK_.to_workbook(d, o); break;
case 0x03: case 0x83: case 0x8B: return DBF.to_workbook(d, o); case 0x03: case 0x83: case 0x8B: return DBF.to_workbook(d, o);
@ -18074,14 +18126,14 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
} }
if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o); if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
if(0x20>n[0]||n[0]>0x7F) throw new Error("Unsupported file " + n.join("|")); if(0x20>n[0]||n[0]>0x7F) throw new Error("Unsupported file " + n.join("|"));
return PRN.to_workbook(d, o); return read_prn(data, d, o, str);
} }
function readFileSync(filename/*:string*/, opts/*:?ParseOpts*/)/*:Workbook*/ { function readFileSync(filename/*:string*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
var o = opts||{}; o.type = 'file'; var o = opts||{}; o.type = 'file';
return readSync(filename, o); return readSync(filename, o);
} }
function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/) { function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:any*/ {
var o = opts||{}; var o = opts||{};
var z = write_zip(wb, o); var z = write_zip(wb, o);
var oopts = {}; var oopts = {};
@ -18089,31 +18141,51 @@ function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
switch(o.type) { switch(o.type) {
case "base64": oopts.type = "base64"; break; case "base64": oopts.type = "base64"; break;
case "binary": oopts.type = "string"; break; case "binary": oopts.type = "string"; break;
case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
case "buffer": case "buffer":
case "file": oopts.type = "nodebuffer"; break; case "file": oopts.type = "nodebuffer"; break;
default: throw new Error("Unrecognized type " + o.type); default: throw new Error("Unrecognized type " + o.type);
} }
if(o.type === "file") return _fs.writeFileSync(o.file, z.generate(oopts)); if(o.type === "file") return _fs.writeFileSync(o.file, z.generate(oopts));
return z.generate(oopts); var out = z.generate(oopts);
// $FlowIgnore
return o.type == "string" ? utf8read(out) : out;
} }
function write_cfb_type(wb/*:Workbook*/, opts/*:?WriteOpts*/) { function write_cfb_type(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:any*/ {
var o = opts||{}; var o = opts||{};
var cfb/*:CFBContainer*/ = write_xlscfb(wb, o); var cfb/*:CFBContainer*/ = write_xlscfb(wb, o);
switch(o.type) { switch(o.type) {
case "base64": case "binary": break; case "base64": case "binary": break;
case "buffer": case "array": o.type = ""; break; case "buffer": case "array": o.type = ""; break;
case "file": return _fs.writeFileSync(o.file, CFB.write(cfb, {type:'buffer'})); case "file": return _fs.writeFileSync(o.file, CFB.write(cfb, {type:'buffer'}));
case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
default: throw new Error("Unrecognized type " + o.type); default: throw new Error("Unrecognized type " + o.type);
} }
return CFB.write(cfb, o); return CFB.write(cfb, o);
} }
/* TODO: test consistency */ function write_string_type(out/*:string*/, opts/*:WriteOpts*/, bom/*:?string*/)/*:any*/ {
function write_bstr_type(out/*:string*/, opts/*:WriteOpts*/) { if(!bom) bom = "";
var o = bom + out;
switch(opts.type) {
case "base64": return Base64.encode(utf8write(o));
case "binary": return utf8write(o);
case "string": return out;
case "file": return _fs.writeFileSync(opts.file, o, 'utf8');
case "buffer": {
if(has_buf) return new Buffer(o, 'utf8');
else return write_string_type(o, {type:'binary'}).split("").map(function(c) { return c.charCodeAt(0); });
}
}
throw new Error("Unrecognized type " + opts.type);
}
function write_stxt_type(out/*:string*/, opts/*:WriteOpts*/)/*:any*/ {
switch(opts.type) { switch(opts.type) {
case "base64": return Base64.encode(out); case "base64": return Base64.encode(out);
case "binary": return out; case "binary": return out;
case "string": return out; /* override in sheet_to_txt */
case "file": return _fs.writeFileSync(opts.file, out, 'binary'); case "file": return _fs.writeFileSync(opts.file, out, 'binary');
case "buffer": { case "buffer": {
if(has_buf) return new Buffer(out, 'binary'); if(has_buf) return new Buffer(out, 'binary');
@ -18124,27 +18196,14 @@ function write_bstr_type(out/*:string*/, opts/*:WriteOpts*/) {
} }
/* TODO: test consistency */ /* TODO: test consistency */
function write_string_type(out/*:string*/, opts/*:WriteOpts*/) { function write_binary_type(out, opts/*:WriteOpts*/)/*:any*/ {
switch(opts.type) {
case "base64": return Base64.encode(out);
case "binary": return out;
case "file": return _fs.writeFileSync(opts.file, out, 'utf8');
case "buffer": {
if(has_buf) return new Buffer(out, 'utf8');
else return out.split("").map(function(c) { return c.charCodeAt(0); });
}
}
throw new Error("Unrecognized type " + opts.type);
}
/* TODO: test consistency */
function write_binary_type(out, opts/*:WriteOpts*/) {
switch(opts.type) { switch(opts.type) {
case "string":
case "base64": case "base64":
case "binary": case "binary":
var bstr = ""; var bstr = "";
for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]); for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]);
return opts.type == 'base64' ? Base64.encode(bstr) : bstr; return opts.type == 'base64' ? Base64.encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr;
case "file": return _fs.writeFileSync(opts.file, out); case "file": return _fs.writeFileSync(opts.file, out);
case "buffer": return out; case "buffer": return out;
default: throw new Error("Unrecognized type " + opts.type); default: throw new Error("Unrecognized type " + opts.type);
@ -18160,14 +18219,14 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
case 'slk': case 'slk':
case 'sylk': return write_string_type(write_slk_str(wb, o), o); case 'sylk': return write_string_type(write_slk_str(wb, o), o);
case 'html': return write_string_type(write_htm_str(wb, o), o); case 'html': return write_string_type(write_htm_str(wb, o), o);
case 'txt': return write_bstr_type(write_txt_str(wb, o), o); case 'txt': return write_stxt_type(write_txt_str(wb, o), o);
case 'csv': return write_string_type(write_csv_str(wb, o), o); case 'csv': return write_string_type(write_csv_str(wb, o), o, "\ufeff");
case 'dif': return write_string_type(write_dif_str(wb, o), o); case 'dif': return write_string_type(write_dif_str(wb, o), o);
case 'prn': return write_string_type(write_prn_str(wb, o), o); case 'prn': return write_string_type(write_prn_str(wb, o), o);
case 'rtf': return write_string_type(write_rtf_str(wb, o), o); case 'rtf': return write_string_type(write_rtf_str(wb, o), o);
case 'fods': return write_string_type(write_ods(wb, o), o); case 'fods': return write_string_type(write_ods(wb, o), o);
case 'biff2': if(!o.biff) o.biff = 2; return write_binary_type(write_biff_buf(wb, o), o); case 'biff2': if(!o.biff) o.biff = 2; /* falls through */
case 'biff3': if(!o.biff) o.biff = 3; return write_binary_type(write_biff_buf(wb, o), o); case 'biff3': if(!o.biff) o.biff = 3; /* falls through */
case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o); case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o);
case 'biff5': if(!o.biff) o.biff = 5; return write_cfb_type(wb, o); case 'biff5': if(!o.biff) o.biff = 5; return write_cfb_type(wb, o);
case 'biff8': case 'biff8':
@ -18348,8 +18407,8 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ {
function sheet_to_txt(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) { function sheet_to_txt(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n"; if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n";
var s = sheet_to_csv(sheet, opts); var s = sheet_to_csv(sheet, opts);
if(typeof cptable == 'undefined') return s; if(typeof cptable == 'undefined' || opts.type == 'string') return s;
var o = cptable.utils.encode(1200, s); var o = cptable.utils.encode(1200, s, 'str');
return "\xff\xfe" + o; return "\xff\xfe" + o;
} }

230
xlsx.js

@ -6,7 +6,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false */ /*global global, exports, module, require:false, process:false, Buffer:false */
var XLSX = {}; var XLSX = {};
(function make_xlsx(XLSX){ (function make_xlsx(XLSX){
XLSX.version = '0.11.4'; XLSX.version = '0.11.5';
var current_codepage = 1200; var current_codepage = 1200;
/*global cptable:true */ /*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') { if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -2039,6 +2039,31 @@ var utf8read = function utf8reada(orig) {
return out; return out;
}; };
var utf8write = function(orig) {
var out = [], i = 0, c = 0, d = 0;
while(i < orig.length) {
c = orig.charCodeAt(i++);
switch(true) {
case c < 128: out.push(String.fromCharCode(c)); break;
case c < 2048:
out.push(String.fromCharCode(192 + (c >> 6)));
out.push(String.fromCharCode(128 + (c & 63)));
break;
case c >= 55296 && c < 57344:
c -= 55296; d = orig.charCodeAt(i++) - 56320 + (c<<10);
out.push(String.fromCharCode(240 + ((d >>18) & 7)));
out.push(String.fromCharCode(144 + ((d >>12) & 63)));
out.push(String.fromCharCode(128 + ((d >> 6) & 63)));
out.push(String.fromCharCode(128 + (d & 63)));
break;
default:
out.push(String.fromCharCode(224 + (c >> 12)));
out.push(String.fromCharCode(128 + ((c >> 6) & 63)));
out.push(String.fromCharCode(128 + (c & 63)));
}
}
return out.join("");
};
if(has_buf) { if(has_buf) {
var utf8readb = function utf8readb(data) { var utf8readb = function utf8readb(data) {
@ -2062,6 +2087,8 @@ if(has_buf) {
// $FlowIgnore // $FlowIgnore
var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); }; var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc; if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
utf8write = function(data) { return new Buffer(data, 'utf8').toString("binary"); };
} }
// matches <foo>...</foo> extracts content // matches <foo>...</foo> extracts content
@ -2074,6 +2101,10 @@ var matchtag = (function() {
}; };
})(); })();
function htmldecode(str) {
return str.trim().replace(/\s+/g, " ").replace(/<\s*[bB][rR]\s*\/?/g,"\n").replace(/<[^>]*>/g,"").replace(/&nbsp;/g, " ");
}
var vtregex = (function(){ var vt_cache = {}; var vtregex = (function(){ var vt_cache = {};
return function vt_regex(bt) { return function vt_regex(bt) {
if(vt_cache[bt] !== undefined) return vt_cache[bt]; if(vt_cache[bt] !== undefined) return vt_cache[bt];
@ -2169,37 +2200,37 @@ function write_double_le(b, v, idx) {
b[idx + 7] = (e >> 4) | bs; b[idx + 7] = (e >> 4) | bs;
} }
var __toBuffer, ___toBuffer; var __toBuffer = function(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; };
__toBuffer = ___toBuffer = function toBuffer_(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; }; var ___toBuffer = __toBuffer;
var __utf16le, ___utf16le; var __utf16le = function(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join(""); };
__utf16le = ___utf16le = function utf16le_(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join(""); }; var ___utf16le = __utf16le;
var __hexlify = function(b,s,l) { var ss=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); }; var __hexlify = function(b,s,l) { var ss=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); };
var ___hexlify = __hexlify; var ___hexlify = __hexlify;
var __utf8, ___utf8; var __utf8 = function(b,s,e) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
__utf8 = ___utf8 = function(b,s,e) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); }; var ___utf8 = __utf8;
var __lpstr, ___lpstr; var __lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
__lpstr = ___lpstr = function lpstr_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";}; var ___lpstr = __lpstr;
var __lpwstr, ___lpwstr; var __lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
__lpwstr = ___lpwstr = function lpwstr_(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";}; var ___lpwstr = __lpwstr;
var __lpp4, ___lpp4; var __lpp4, ___lpp4;
__lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";}; __lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
var __8lpp4, ___8lpp4; var __8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
__8lpp4 = ___8lpp4 = function lpp4_8(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";}; var ___8lpp4 = __8lpp4;
var __double, ___double; var __double, ___double;
__double = ___double = function(b, idx) { return read_double_le(b, idx);}; __double = ___double = function(b, idx) { return read_double_le(b, idx);};
var is_buf = function is_buf_a(a) { return Array.isArray(a); }; var is_buf = function is_buf_a(a) { return Array.isArray(a); };
if(has_buf) { if(has_buf) {
__utf16le = function utf16le_b(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e); }; __utf16le = function(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e); };
__hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); }; __hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
__lpstr = function lpstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";}; __lpstr = function lpstr_b(b, i) { if(!Buffer.isBuffer(b)) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
__lpwstr = function lpwstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);}; __lpwstr = function lpwstr_b(b, i) { if(!Buffer.isBuffer(b)) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
__lpp4 = function lpp4_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);}; __lpp4 = function lpp4_b(b, i) { if(!Buffer.isBuffer(b)) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);};
__8lpp4 = function lpp4_8b(b,i) { if(!Buffer.isBuffer(b)) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);}; __8lpp4 = function lpp4_8b(b, i) { if(!Buffer.isBuffer(b)) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);};
__utf8 = function utf8_b(b, s,e) { return b.toString('utf8',s,e); }; __utf8 = function utf8_b(b, s, e) { return (Buffer.isBuffer(b)) ? b.toString('utf8',s,e) : __utf8(b,s,e); };
__toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);}; __toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);};
bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); }; bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); };
__double = function double_(b,i) { if(Buffer.isBuffer(b)) return b.readDoubleLE(i); return ___double(b,i); }; __double = function double_(b, i) { if(Buffer.isBuffer(b)) return b.readDoubleLE(i); return ___double(b,i); };
is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); }; is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); };
} }
@ -2219,7 +2250,7 @@ var __readInt16LE = function(b, idx) { var u = b[idx+1]*(1<<8)+b[idx]; return (u
var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; }; var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; }; var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
var ___unhexlify = function(s) { return s.match(/../g).map(function(x) { return parseInt(x,16);}); }; var ___unhexlify = function(s) { return (s.match(/../g)||[]).map(function(x) { return parseInt(x,16);}); };
var __unhexlify = typeof Buffer !== "undefined" ? function(s) { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify; var __unhexlify = typeof Buffer !== "undefined" ? function(s) { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;
function ReadShift(size, t) { function ReadShift(size, t) {
@ -2295,9 +2326,9 @@ function ReadShift(size, t) {
this.l+=size; return o; this.l+=size; return o;
} }
var __writeUInt16LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); };
var __writeUInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); b[idx+2] = ((val >>> 16) & 0xFF); b[idx+3] = ((val >>> 24) & 0xFF); }; var __writeUInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); b[idx+2] = ((val >>> 16) & 0xFF); b[idx+3] = ((val >>> 24) & 0xFF); };
var __writeInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); }; var __writeInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); };
var __writeUInt16LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); };
function WriteShift(t, val, f) { function WriteShift(t, val, f) {
var size = 0, i = 0; var size = 0, i = 0;
@ -2312,7 +2343,7 @@ for(i = 0; i != val.length; ++i) this[this.l + i] = val.charCodeAt(i) & 0xFF;
this[this.l++] = parseInt(val.slice(2*i, 2*i+2), 16)||0; this[this.l++] = parseInt(val.slice(2*i, 2*i+2), 16)||0;
} return this; } return this;
} else if(f === 'utf16le') { } else if(f === 'utf16le') {
var end = this.l + t; var end = this.l + t;
for(i = 0; i < Math.min(val.length, t); ++i) { for(i = 0; i < Math.min(val.length, t); ++i) {
var cc = val.charCodeAt(i); var cc = val.charCodeAt(i);
this[this.l++] = cc & 0xff; this[this.l++] = cc & 0xff;
@ -2335,7 +2366,7 @@ this[this.l++] = parseInt(val.slice(2*i, 2*i+2), 16)||0;
function CheckField(hexstr, fld) { function CheckField(hexstr, fld) {
var m = __hexlify(this,this.l,hexstr.length>>1); var m = __hexlify(this,this.l,hexstr.length>>1);
if(m !== hexstr) throw fld + 'Expected ' + hexstr + ' saw ' + m; if(m !== hexstr) throw new Error(fld + 'Expected ' + hexstr + ' saw ' + m);
this.l += hexstr.length>>1; this.l += hexstr.length>>1;
} }
@ -3628,6 +3659,7 @@ var CORE_PROPS_REGEX = (function() {
function parse_core_props(data) { function parse_core_props(data) {
var p = {}; var p = {};
data = utf8read(data);
for(var i = 0; i < CORE_PROPS.length; ++i) { for(var i = 0; i < CORE_PROPS.length; ++i) {
var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]); var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
@ -3695,6 +3727,7 @@ RELS.EXT_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relatio
function parse_ext_props(data, p, opts) { function parse_ext_props(data, p, opts) {
var q = {}; if(!p) p = {}; var q = {}; if(!p) p = {};
data = utf8read(data);
EXT_PROPS.forEach(function(f) { EXT_PROPS.forEach(function(f) {
switch(f[2]) { switch(f[2]) {
@ -4133,7 +4166,7 @@ function parse_PropertySet(blob, PIDSI) {
case 1252: case 1252:
case 65000: case -536: case 65000: case -536:
case 65001: case -535: case 65001: case -535:
set_cp(CodePage = PropH[piddsi.n]); break; set_cp(CodePage = PropH[piddsi.n]>>>0 & 0xFFFF); break;
default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]); default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
} }
} else { } else {
@ -4175,6 +4208,7 @@ function parse_PropertySet(blob, PIDSI) {
/* [MS-OLEPS] 2.21 PropertySetStream */ /* [MS-OLEPS] 2.21 PropertySetStream */
function parse_PropertySetStream(file, PIDSI) { function parse_PropertySetStream(file, PIDSI) {
var blob = file.content; var blob = file.content;
if(!blob) return ({});
prep_blob(blob, 0); prep_blob(blob, 0);
var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0; var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;
@ -5685,7 +5719,7 @@ var SYLK = (function() {
function sheet_to_sylk(ws, opts) { function sheet_to_sylk(ws, opts) {
var preamble = ["ID;PWXL;N;E"], o = []; var preamble = ["ID;PWXL;N;E"], o = [];
var r = decode_range(ws['!ref']), cell; var r = safe_decode_range(ws['!ref']), cell;
var dense = Array.isArray(ws); var dense = Array.isArray(ws);
var RS = "\r\n"; var RS = "\r\n";
@ -5769,7 +5803,7 @@ var DIF = (function() {
}; };
return function sheet_to_dif(ws, opts) { return function sheet_to_dif(ws, opts) {
var o = []; var o = [];
var r = decode_range(ws['!ref']), cell; var r = safe_decode_range(ws['!ref']), cell;
var dense = Array.isArray(ws); var dense = Array.isArray(ws);
push_field(o, "TABLE", 0, 1, "sheetjs"); push_field(o, "TABLE", 0, 1, "sheetjs");
push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,""); push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,"");
@ -5885,6 +5919,7 @@ var PRN = (function() {
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"'); if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
if(s.length == 0) cell.t = 'z'; if(s.length == 0) cell.t = 'z';
else if(o.raw) { cell.t = 's'; cell.v = s; } else if(o.raw) { cell.t = 's'; cell.v = s; }
else if(s.trim().length == 0) { cell.t = 's'; cell.v = s; }
else if(s.charCodeAt(0) == 0x3D) { else if(s.charCodeAt(0) == 0x3D) {
if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); } if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); }
else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.substr(1); } else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.substr(1); }
@ -5930,12 +5965,13 @@ var PRN = (function() {
} }
function prn_to_sheet(d, opts) { function prn_to_sheet(d, opts) {
var str = "", bytes = firstbyte(d, opts); var str = "", bytes = opts.type == 'string' ? [0,0,0,0] : firstbyte(d, opts);
switch(opts.type) { switch(opts.type) {
case 'base64': str = Base64.decode(d); break; case 'base64': str = Base64.decode(d); break;
case 'binary': str = d; break; case 'binary': str = d; break;
case 'buffer': str = d.toString('binary'); break; case 'buffer': str = d.toString('binary'); break;
case 'array': str = cc2str(d); break; case 'array': str = cc2str(d); break;
case 'string': str = d; break;
default: throw new Error("Unrecognized type " + opts.type); default: throw new Error("Unrecognized type " + opts.type);
} }
if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str.slice(3)); if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str.slice(3));
@ -5946,7 +5982,7 @@ var PRN = (function() {
function sheet_to_prn(ws, opts) { function sheet_to_prn(ws, opts) {
var o = []; var o = [];
var r = decode_range(ws['!ref']), cell; var r = safe_decode_range(ws['!ref']), cell;
var dense = Array.isArray(ws); var dense = Array.isArray(ws);
for(var R = r.s.r; R <= r.e.r; ++R) { for(var R = r.s.r; R <= r.e.r; ++R) {
var oo = []; var oo = [];
@ -9400,7 +9436,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell, supbooks, opts) {
case 'PtgFuncVar': /* 2.5.198.63 */ case 'PtgFuncVar': /* 2.5.198.63 */
//console.log(f[1]); //console.log(f[1]);
/* f[1] = [argc, func, type] */ /* f[1] = [argc, func, type] */
var argc = f[1][0], func = f[1][1]; var argc = (f[1][0]), func = (f[1][1]);
if(!argc) argc = 0; if(!argc) argc = 0;
var args = argc == 0 ? [] : stack.slice(-argc); var args = argc == 0 ? [] : stack.slice(-argc);
stack.length -= argc; stack.length -= argc;
@ -11977,7 +12013,7 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles) {
case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break; case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
case 'b': p.v = val[1] ? true : false; break; case 'b': p.v = val[1] ? true : false; break;
case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break; case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break;
case 'str': p.t = 's'; p.v = utf8read(val[1]); break; case 'str': p.t = 's'; p.v = val[1]; break;
} }
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles); if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
C = val[0].c; C = val[0].c;
@ -13380,7 +13416,10 @@ function parse_xlml_xml(d, _opts) {
var opts = _opts || {}; var opts = _opts || {};
make_ssf(SSF); make_ssf(SSF);
var str = debom(xlml_normalize(d)); var str = debom(xlml_normalize(d));
if(opts && opts.type == 'binary' && typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str)); if(opts.type == 'binary' || opts.type == 'base64') {
if(typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str));
else str = utf8read(str);
}
var opening = str.slice(0, 1024).toLowerCase(), ishtml = false; var opening = str.slice(0, 1024).toLowerCase(), ishtml = false;
if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; }); if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; });
if(ishtml) return HTML_.to_workbook(str, opts); if(ishtml) return HTML_.to_workbook(str, opts);
@ -14204,12 +14243,6 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){
case 's': t = 'String'; p = escapexml(cell.v||""); break; case 's': t = 'String'; p = escapexml(cell.v||""); break;
} }
var _v = (cell.v != null ? p : ""); var _v = (cell.v != null ? p : "");
if(opts && opts.type == 'binary' && typeof cptable !== 'undefined' && cell.t == 's') {
_v = cptable.utils.encode(65001, _v);
var __v = "";
for(var __i = 0; __i < _v.length; ++__i) __v += String.fromCharCode(_v[__i]);
_v = __v;
}
var m = '<Data ss:Type="' + t + '">' + _v + '</Data>'; var m = '<Data ss:Type="' + t + '">' + _v + '</Data>';
if((cell.c||[]).length > 0) m += write_ws_xlml_comment(cell.c); if((cell.c||[]).length > 0) m += write_ws_xlml_comment(cell.c);
@ -14297,8 +14330,7 @@ function write_xlml(wb, opts) {
function parse_compobj(obj) { function parse_compobj(obj) {
var v = {}; var v = {};
var o = obj.content; var o = obj.content;
/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
var l = 28, m; var l = 28, m;
m = __lpstr(o, l); m = __lpstr(o, l);
l += 4 + __readUInt32LE(o,l); l += 4 + __readUInt32LE(o,l);
@ -15113,14 +15145,20 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
} }
/* TODO: WTF */ /* TODO: WTF */
function parse_props(cfb) { function parse_props(cfb, props, o) {
/* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */ /* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
var DSI = CFB.find(cfb, '!DocumentSummaryInformation'); var DSI = CFB.find(cfb, '!DocumentSummaryInformation');
if(DSI) try { cfb.DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI); } catch(e) {/* empty */} if(DSI) try {
var DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI);
for(var d in DocSummary) props[d] = DocSummary[d];
} catch(e) {if(o.WTF == 2) throw e;/* empty */}
/* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/ /* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
var SI = CFB.find(cfb, '!SummaryInformation'); var SI = CFB.find(cfb, '!SummaryInformation');
if(SI) try { cfb.Summary = parse_PropertySetStream(SI, SummaryPIDSI); } catch(e) {/* empty */} if(SI) try {
var Summary = parse_PropertySetStream(SI, SummaryPIDSI);
for(var s in Summary) if(props[s] == null) props[s] = Summary[s];
} catch(e) {if(o.WTF == 2) throw e;/* empty */}
} }
function parse_xlscfb(cfb, options) { function parse_xlscfb(cfb, options) {
@ -15131,7 +15169,7 @@ var CompObj, Summary, WB;
if(cfb.FullPaths) { if(cfb.FullPaths) {
CompObj = CFB.find(cfb, '!CompObj'); CompObj = CFB.find(cfb, '!CompObj');
Summary = CFB.find(cfb, '!SummaryInformation'); Summary = CFB.find(cfb, '!SummaryInformation');
WB = CFB.find(cfb, '/Workbook'); WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
} else { } else {
switch(options.type) { switch(options.type) {
case 'base64': cfb = s2a(Base64.decode(cfb)); break; case 'base64': cfb = s2a(Base64.decode(cfb)); break;
@ -15142,26 +15180,24 @@ if(cfb.FullPaths) {
prep_blob(cfb, 0); prep_blob(cfb, 0);
WB = ({content: cfb}); WB = ({content: cfb});
} }
if(!WB) WB = CFB.find(cfb, '/Book');
var CompObjP, SummaryP, WorkbookP; var CompObjP, SummaryP, WorkbookP;
var _data; var _data;
if(CompObj) CompObjP = parse_compobj(CompObj); if(CompObj) CompObjP = parse_compobj(CompObj);
if(options.bookProps && !options.bookSheets) WorkbookP = ({}); if(options.bookProps && !options.bookSheets) WorkbookP = ({});
else { else {
var T = has_buf ? 'buffer' : 'array';
if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options); if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options);
/* Quattro Pro 7-8 */ /* Quattro Pro 7-8 */
else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, options); else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
/* Quattro Pro 9 */ /* Quattro Pro 9 */
else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, options); else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
else throw new Error("Cannot find Workbook stream"); else throw new Error("Cannot find Workbook stream");
} }
if(cfb.FullPaths) parse_props(cfb);
var props = {}; var props = {};
for(var y in cfb.Summary) props[y] = cfb.Summary[y]; if(cfb.FullPaths) parse_props(cfb, props, options);
for(y in cfb.DocSummary) props[y] = cfb.DocSummary[y];
WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */ WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
if(options.bookFiles) WorkbookP.cfb = cfb; if(options.bookFiles) WorkbookP.cfb = cfb;
/*WorkbookP.CompObjP = CompObjP; // TODO: storage? */ /*WorkbookP.CompObjP = CompObjP; // TODO: storage? */
@ -16688,7 +16724,7 @@ var HTML_ = (function() {
if((RS = +tag.rowspan)>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}}); if((RS = +tag.rowspan)>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
/* TODO: generate stub cells */ /* TODO: generate stub cells */
if(!m.length) { C += CS; continue; } if(!m.length) { C += CS; continue; }
m = unescapexml(m).replace(/[\r\n]/g,""); m = htmldecode(unescapexml(m));
if(range.s.r > R) range.s.r = R; if(range.s.r > R) range.s.r = R;
if(range.e.r < R) range.e.r = R; if(range.e.r < R) range.e.r = R;
if(range.s.c > C) range.s.c = C; if(range.s.c > C) range.s.c = C;
@ -16696,7 +16732,7 @@ var HTML_ = (function() {
if(opts.dense) { if(opts.dense) {
if(!ws[R]) ws[R] = []; if(!ws[R]) ws[R] = [];
if(!m.length){} if(!m.length){}
else if(opts.raw) ws[R][C] = {t:'s', v:m}; else if(opts.raw || !m.trim().length) ws[R][C] = {t:'s', v:m};
else if(m === 'TRUE') ws[R][C] = {t:'b', v:true}; else if(m === 'TRUE') ws[R][C] = {t:'b', v:true};
else if(m === 'FALSE') ws[R][C] = {t:'b', v:false}; else if(m === 'FALSE') ws[R][C] = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)}; else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)};
@ -16706,6 +16742,7 @@ var HTML_ = (function() {
/* TODO: value parsing */ /* TODO: value parsing */
if(!m.length){} if(!m.length){}
else if(opts.raw) ws[coord] = {t:'s', v:m}; else if(opts.raw) ws[coord] = {t:'s', v:m};
else if(opts.raw || !m.trim().length) ws[coord] = {t:'s', v:m};
else if(m === 'TRUE') ws[coord] = {t:'b', v:true}; else if(m === 'TRUE') ws[coord] = {t:'b', v:true};
else if(m === 'FALSE') ws[coord] = {t:'b', v:false}; else if(m === 'FALSE') ws[coord] = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) ws[coord] = {t:'n', v:fuzzynum(m)}; else if(!isNaN(fuzzynum(m))) ws[coord] = {t:'n', v:fuzzynum(m)};
@ -16790,7 +16827,7 @@ function parse_dom_table(table, _opts) {
var row = rows[R]; var row = rows[R];
var elts = row.children; var elts = row.children;
for(_C = C = 0; _C < elts.length; ++_C) { for(_C = C = 0; _C < elts.length; ++_C) {
var elt = elts[_C], v = elts[_C].innerText || elts[_C].textContent || ""; var elt = elts[_C], v = htmldecode(elts[_C].innerHTML);
for(midx = 0; midx < merges.length; ++midx) { for(midx = 0; midx < merges.length; ++midx) {
var m = merges[midx]; var m = merges[midx];
if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; } if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; }
@ -16802,6 +16839,7 @@ function parse_dom_table(table, _opts) {
if(v != null) { if(v != null) {
if(v.length == 0) o.t = 'z'; if(v.length == 0) o.t = 'z';
else if(opts.raw){} else if(opts.raw){}
else if(v.trim().length == 0) o.t = 's';
else if(v === 'TRUE') o = {t:'b', v:true}; else if(v === 'TRUE') o = {t:'b', v:true};
else if(v === 'FALSE') o = {t:'b', v:false}; else if(v === 'FALSE') o = {t:'b', v:false};
else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)}; else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
@ -17291,7 +17329,9 @@ function parse_ods(zip, opts) {
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts); if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
var content = getzipstr(zip, 'content.xml'); var content = getzipstr(zip, 'content.xml');
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file"); if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
return parse_content_xml(ods ? content : utf8read(content), opts); var wb = parse_content_xml(ods ? content : utf8read(content), opts);
if(safegetzipfile(zip, 'meta.xml')) wb.Props = parse_core_props(getzipdata(zip, 'meta.xml'));
return wb;
} }
function parse_fods(data, opts) { function parse_fods(data, opts) {
return parse_content_xml(data, opts); return parse_content_xml(data, opts);
@ -17558,8 +17598,7 @@ function get_sheet_type(n) {
if(RELS.CS && n == RELS.CS) return "chart"; if(RELS.CS && n == RELS.CS) return "chart";
if(RELS.DS && n == RELS.DS) return "dialog"; if(RELS.DS && n == RELS.DS) return "dialog";
if(RELS.MS && n == RELS.MS) return "macro"; if(RELS.MS && n == RELS.MS) return "macro";
if(!n || !n.length) return "sheet"; return (n && n.length) ? n : "sheet";
return n;
} }
function safe_parse_wbrels(wbrels, sheets) { function safe_parse_wbrels(wbrels, sheets) {
if(!wbrels) return 0; if(!wbrels) return 0;
@ -17643,10 +17682,10 @@ function parse_zip(zip, opts) {
var props = {}, propdata = ""; var props = {}, propdata = "";
if(dir.coreprops.length) { if(dir.coreprops.length) {
propdata = getzipstr(zip, strip_front_slash(dir.coreprops[0]), true); propdata = getzipdata(zip, strip_front_slash(dir.coreprops[0]), true);
if(propdata) props = parse_core_props(propdata); if(propdata) props = parse_core_props(propdata);
if(dir.extprops.length !== 0) { if(dir.extprops.length !== 0) {
propdata = getzipstr(zip, strip_front_slash(dir.extprops[0]), true); propdata = getzipdata(zip, strip_front_slash(dir.extprops[0]), true);
if(propdata) parse_ext_props(propdata, props, opts); if(propdata) parse_ext_props(propdata, props, opts);
} }
} }
@ -17952,13 +17991,23 @@ function read_utf16(data, o) {
return read_plaintext(d, o); return read_plaintext(d, o);
} }
function bstrify(data) {
return !data.match(/[^\x00-\x7F]/) ? data : utf8write(data);
}
function read_prn(data, d, o, str) {
if(str) { o.type = "string"; return PRN.to_workbook(data, o); }
return PRN.to_workbook(d, o);
}
function readSync(data, opts) { function readSync(data, opts) {
var zip, d = data, n=[0]; var zip, d = data, n=[0], str = false;
var o = opts||{}; var o = opts||{};
_ssfopts = {}; _ssfopts = {};
if(o.dateNF) _ssfopts.dateNF = o.dateNF; if(o.dateNF) _ssfopts.dateNF = o.dateNF;
if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64"; if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
if(o.type == "file") { o.type = "buffer"; d = _fs.readFileSync(data); } if(o.type == "file") { o.type = "buffer"; d = _fs.readFileSync(data); }
if(o.type == "string") { str = true; o.type = "binary"; d = bstrify(data); }
switch((n = firstbyte(d, o))[0]) { switch((n = firstbyte(d, o))[0]) {
case 0xD0: return read_cfb(CFB.read(d, o), o); case 0xD0: return read_cfb(CFB.read(d, o), o);
case 0x09: return parse_xlscfb(d, o); case 0x09: return parse_xlscfb(d, o);
@ -17966,7 +18015,7 @@ function readSync(data, opts) {
case 0x49: if(n[1] == 0x44) return read_wb_ID(d, o); break; case 0x49: if(n[1] == 0x44) return read_wb_ID(d, o); break;
case 0x54: if(n[1] == 0x41 && n[2] == 0x42 && n[3] == 0x4C) return DIF.to_workbook(d, o); break; case 0x54: if(n[1] == 0x41 && n[2] == 0x42 && n[3] == 0x4C) return DIF.to_workbook(d, o); break;
case 0x50: if(n[1] == 0x4B && n[2] < 0x20 && n[3] < 0x20) return read_zip(d, o); break; case 0x50: if(n[1] == 0x4B && n[2] < 0x20 && n[3] < 0x20) return read_zip(d, o); break;
case 0xEF: return n[3] == 0x3C ? parse_xlml(d, o) : PRN.to_workbook(d,o); case 0xEF: return n[3] == 0x3C ? parse_xlml(d, o) : read_prn(data, d, o, str);
case 0xFF: if(n[1] == 0xFE){ return read_utf16(d, o); } break; case 0xFF: if(n[1] == 0xFE){ return read_utf16(d, o); } break;
case 0x00: if(n[1] == 0x00 && n[2] >= 0x02 && n[3] == 0x00) return WK_.to_workbook(d, o); break; case 0x00: if(n[1] == 0x00 && n[2] >= 0x02 && n[3] == 0x00) return WK_.to_workbook(d, o); break;
case 0x03: case 0x83: case 0x8B: return DBF.to_workbook(d, o); case 0x03: case 0x83: case 0x8B: return DBF.to_workbook(d, o);
@ -17975,7 +18024,7 @@ function readSync(data, opts) {
} }
if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o); if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
if(0x20>n[0]||n[0]>0x7F) throw new Error("Unsupported file " + n.join("|")); if(0x20>n[0]||n[0]>0x7F) throw new Error("Unsupported file " + n.join("|"));
return PRN.to_workbook(d, o); return read_prn(data, d, o, str);
} }
function readFileSync(filename, opts) { function readFileSync(filename, opts) {
@ -17990,12 +18039,15 @@ function write_zip_type(wb, opts) {
switch(o.type) { switch(o.type) {
case "base64": oopts.type = "base64"; break; case "base64": oopts.type = "base64"; break;
case "binary": oopts.type = "string"; break; case "binary": oopts.type = "string"; break;
case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
case "buffer": case "buffer":
case "file": oopts.type = "nodebuffer"; break; case "file": oopts.type = "nodebuffer"; break;
default: throw new Error("Unrecognized type " + o.type); default: throw new Error("Unrecognized type " + o.type);
} }
if(o.type === "file") return _fs.writeFileSync(o.file, z.generate(oopts)); if(o.type === "file") return _fs.writeFileSync(o.file, z.generate(oopts));
return z.generate(oopts); var out = z.generate(oopts);
// $FlowIgnore
return o.type == "string" ? utf8read(out) : out;
} }
function write_cfb_type(wb, opts) { function write_cfb_type(wb, opts) {
@ -18005,16 +18057,33 @@ function write_cfb_type(wb, opts) {
case "base64": case "binary": break; case "base64": case "binary": break;
case "buffer": case "array": o.type = ""; break; case "buffer": case "array": o.type = ""; break;
case "file": return _fs.writeFileSync(o.file, CFB.write(cfb, {type:'buffer'})); case "file": return _fs.writeFileSync(o.file, CFB.write(cfb, {type:'buffer'}));
case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
default: throw new Error("Unrecognized type " + o.type); default: throw new Error("Unrecognized type " + o.type);
} }
return CFB.write(cfb, o); return CFB.write(cfb, o);
} }
/* TODO: test consistency */ function write_string_type(out, opts, bom) {
function write_bstr_type(out, opts) { if(!bom) bom = "";
var o = bom + out;
switch(opts.type) {
case "base64": return Base64.encode(utf8write(o));
case "binary": return utf8write(o);
case "string": return out;
case "file": return _fs.writeFileSync(opts.file, o, 'utf8');
case "buffer": {
if(has_buf) return new Buffer(o, 'utf8');
else return write_string_type(o, {type:'binary'}).split("").map(function(c) { return c.charCodeAt(0); });
}
}
throw new Error("Unrecognized type " + opts.type);
}
function write_stxt_type(out, opts) {
switch(opts.type) { switch(opts.type) {
case "base64": return Base64.encode(out); case "base64": return Base64.encode(out);
case "binary": return out; case "binary": return out;
case "string": return out; /* override in sheet_to_txt */
case "file": return _fs.writeFileSync(opts.file, out, 'binary'); case "file": return _fs.writeFileSync(opts.file, out, 'binary');
case "buffer": { case "buffer": {
if(has_buf) return new Buffer(out, 'binary'); if(has_buf) return new Buffer(out, 'binary');
@ -18024,28 +18093,15 @@ function write_bstr_type(out, opts) {
throw new Error("Unrecognized type " + opts.type); throw new Error("Unrecognized type " + opts.type);
} }
/* TODO: test consistency */
function write_string_type(out, opts) {
switch(opts.type) {
case "base64": return Base64.encode(out);
case "binary": return out;
case "file": return _fs.writeFileSync(opts.file, out, 'utf8');
case "buffer": {
if(has_buf) return new Buffer(out, 'utf8');
else return out.split("").map(function(c) { return c.charCodeAt(0); });
}
}
throw new Error("Unrecognized type " + opts.type);
}
/* TODO: test consistency */ /* TODO: test consistency */
function write_binary_type(out, opts) { function write_binary_type(out, opts) {
switch(opts.type) { switch(opts.type) {
case "string":
case "base64": case "base64":
case "binary": case "binary":
var bstr = ""; var bstr = "";
for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]); for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]);
return opts.type == 'base64' ? Base64.encode(bstr) : bstr; return opts.type == 'base64' ? Base64.encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr;
case "file": return _fs.writeFileSync(opts.file, out); case "file": return _fs.writeFileSync(opts.file, out);
case "buffer": return out; case "buffer": return out;
default: throw new Error("Unrecognized type " + opts.type); default: throw new Error("Unrecognized type " + opts.type);
@ -18061,14 +18117,14 @@ function writeSync(wb, opts) {
case 'slk': case 'slk':
case 'sylk': return write_string_type(write_slk_str(wb, o), o); case 'sylk': return write_string_type(write_slk_str(wb, o), o);
case 'html': return write_string_type(write_htm_str(wb, o), o); case 'html': return write_string_type(write_htm_str(wb, o), o);
case 'txt': return write_bstr_type(write_txt_str(wb, o), o); case 'txt': return write_stxt_type(write_txt_str(wb, o), o);
case 'csv': return write_string_type(write_csv_str(wb, o), o); case 'csv': return write_string_type(write_csv_str(wb, o), o, "\ufeff");
case 'dif': return write_string_type(write_dif_str(wb, o), o); case 'dif': return write_string_type(write_dif_str(wb, o), o);
case 'prn': return write_string_type(write_prn_str(wb, o), o); case 'prn': return write_string_type(write_prn_str(wb, o), o);
case 'rtf': return write_string_type(write_rtf_str(wb, o), o); case 'rtf': return write_string_type(write_rtf_str(wb, o), o);
case 'fods': return write_string_type(write_ods(wb, o), o); case 'fods': return write_string_type(write_ods(wb, o), o);
case 'biff2': if(!o.biff) o.biff = 2; return write_binary_type(write_biff_buf(wb, o), o); case 'biff2': if(!o.biff) o.biff = 2; /* falls through */
case 'biff3': if(!o.biff) o.biff = 3; return write_binary_type(write_biff_buf(wb, o), o); case 'biff3': if(!o.biff) o.biff = 3; /* falls through */
case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o); case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o);
case 'biff5': if(!o.biff) o.biff = 5; return write_cfb_type(wb, o); case 'biff5': if(!o.biff) o.biff = 5; return write_cfb_type(wb, o);
case 'biff8': case 'biff8':
@ -18249,8 +18305,8 @@ function sheet_to_csv(sheet, opts) {
function sheet_to_txt(sheet, opts) { function sheet_to_txt(sheet, opts) {
if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n"; if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n";
var s = sheet_to_csv(sheet, opts); var s = sheet_to_csv(sheet, opts);
if(typeof cptable == 'undefined') return s; if(typeof cptable == 'undefined' || opts.type == 'string') return s;
var o = cptable.utils.encode(1200, s); var o = cptable.utils.encode(1200, s, 'str');
return "\xff\xfe" + o; return "\xff\xfe" + o;
} }

@ -1,6 +1,7 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ /* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/*:: declare var XLSX: XLSXModule; */ /*:: declare var XLSX: XLSXModule; */
/*:: declare var self: DedicatedWorkerGlobalScope; */ /*:: declare var self: DedicatedWorkerGlobalScope; */
importScripts('shim.js');
/* uncomment the next line for encoding support */ /* uncomment the next line for encoding support */
importScripts('dist/cpexcel.js'); importScripts('dist/cpexcel.js');
importScripts('jszip.js'); importScripts('jszip.js');

@ -1,4 +1,5 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ /* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
importScripts('shim.js');
/* uncomment the next line for encoding support */ /* uncomment the next line for encoding support */
importScripts('dist/cpexcel.js'); importScripts('dist/cpexcel.js');
importScripts('jszip.js'); importScripts('jszip.js');