version bump 0.11.5: "string" type

- proper JS string input / output type
- bower main now uses full version (fixes #820 h/t @newmesiss)
- DOM parse directly acts on innerHTML (see #779 h/t @danxfisher)
- unicode core props and ext props (fixes #822 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

View File

@ -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
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)
* XLS cell ixfe/XF removed

View File

@ -156,6 +156,9 @@ demo-systemjs: ## Run systemjs demo build
## Code Checking
.PHONY: fullint
fullint: lint old-lint tslint flow mdlint ## Run all checks
.PHONY: lint
lint: $(TARGET) $(AUXTARGETS) ## Run eslint checks
@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
@jshint --show-non-errors $(TARGET) $(AUXTARGETS)
@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)
@jscs $(TARGET) $(AUXTARGETS)
@jscs $(TARGET) $(AUXTARGETS) test.js
if [ -e $(CLOSURE) ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi
.PHONY: tslint

View File

@ -294,6 +294,9 @@ data and feeding it into the library. Here are a few common scenarios:
<details>
<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
if(typeof require !== 'undefined') XLSX = require('xlsx');
var workbook = XLSX.readFile('test.xlsx');
@ -305,11 +308,21 @@ var workbook = XLSX.readFile('test.xlsx');
<details>
<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
var worksheet = XLSX.utils.table_to_book(document.getElementById('tableau'));
/* 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>
@ -566,16 +579,35 @@ Assuming `workbook` is a workbook object:
<details>
<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
if(typeof require !== 'undefined') XLSX = require('xlsx');
/* output format determined by filename */
XLSX.writeFile(workbook, 'out.xlsx');
/* at this point, out.xlsx is a file that you can distribute */
XLSX.writeFile(workbook, 'out.xlsb');
/* at this point, out.xlsb is a file that you can distribute */
```
</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
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 */
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx");
```
</details>
<details>
@ -1442,6 +1475,7 @@ tells the library how to parse the data argument:
|------------|-----------------------------------------------------------------|
| `"base64"` | string: Base64 encoding of the file |
| `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) |
| `"string"` | string: JS string (characters interpreted as UTF8) |
| `"buffer"` | nodejs Buffer |
| `"array"` | array: array of 8-bit unsigned int (byte `n` is `data[n]`) |
| `"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 |
| `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) |
| `"string"` | string: JS string (characters interpreted as UTF8) |
| `"buffer"` | nodejs Buffer |
| `"file"` | string: path of file that will be created (nodejs only) |
## Utility Functions
The `sheet_to_*` functions accept a worksheet and an optional options object.

View File

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

View File

@ -39,7 +39,7 @@ function getzipfile(zip, file/*:string*/) {
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(!file) return null;
try { return getzipdata(zip, file); } catch(e) { return null; }

View File

@ -101,6 +101,31 @@ var utf8read/*:StringConv*/ = function utf8reada(orig) {
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) {
var utf8readb = function utf8readb(data) {
@ -124,6 +149,8 @@ if(has_buf) {
// $FlowIgnore
var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
utf8write = function(data) { return new Buffer(data, 'utf8').toString("binary"); };
}
// 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 = {};
return function vt_regex(bt) {
if(vt_cache[bt] !== undefined) return vt_cache[bt];

View File

@ -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 e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 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;
}
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 av = bs ? -v : v;
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;
}
var __toBuffer, ___toBuffer;
__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 __utf16le, ___utf16le;
__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 __toBuffer = function(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 = 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(""); };
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 = __hexlify;
var __utf8, ___utf8;
__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 __lpstr, ___lpstr;
__lpstr = ___lpstr = function lpstr_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var __lpwstr, ___lpwstr;
__lpwstr = ___lpwstr = function lpwstr_(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
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(""); };
var ___utf8 = __utf8;
var __lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var ___lpstr = __lpstr;
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) : "";};
var ___lpwstr = __lpwstr;
var __lpp4, ___lpp4;
__lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
var __8lpp4, ___8lpp4;
__8lpp4 = ___8lpp4 = function lpp4_8(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(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 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
var ___8lpp4 = __8lpp4;
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); };
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); };
__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) : "";};
__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);};
__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); };
if(has_buf/*:: && typeof Buffer !== 'undefined'*/) {
__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); };
__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); };
__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) : "";};
__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);};
__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);};
__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);};
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); };
}
/* from js-xls */
if(typeof cptable !== 'undefined') {
__utf16le = function(b,s,e) { return cptable.utils.decode(1200, b.slice(s,e)); };
__utf8 = function(b,s,e) { 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)) : "";};
__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)) : "";};
__lpp4 = function(b,i) { 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)) : "";};
__utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(1200, 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/*: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/*: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/*: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/*: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 __readUInt16LE = function(b, 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 __readUInt32LE = function(b, 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 __readUInt8 = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx]; };
var __readUInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+1]*(1<<8)+b[idx]; };
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/*: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/*: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 = typeof Buffer !== "undefined" ? function(s) { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;
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/*:string*/)/*:Array<number>|Buffer*/ { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;
function ReadShift(size/*:number*/, t/*:?string*/) {
var o="", oI, oR, oo=[], w, vv, i, loc;
function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
var o="", oI/*:: :number = 0*/, oR, oo=[], w, vv, i, loc;
switch(t) {
case 'dbcs':
loc = this.l;
@ -151,11 +151,11 @@ function ReadShift(size/*:number*/, t/*:?string*/) {
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 __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 __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 __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 __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;
if(f === 'dbcs') {
/*:: 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;
} return this;
} else if(f === 'utf16le') {
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
var end/*:number*/ = this.l + t;
for(i = 0; i < Math.min(val.length, t); ++i) {
var cc = val.charCodeAt(i);
@ -192,20 +193,20 @@ function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/) {
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);
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;
}
function prep_blob(blob, pos/*:number*/) {
function prep_blob(blob, pos/*:number*/)/*:void*/ {
blob.l = pos;
blob.read_shift = ReadShift;
blob.read_shift = /*::(*/ReadShift/*:: :any)*/;
blob.chk = CheckField;
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 writenoop(blob, length/*:number*/) { blob.l += length; }

View File

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

View File

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

View File

@ -193,7 +193,7 @@ function parse_PropertySet(blob, PIDSI) {
case 1252:
case 65000: case -536:
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]);
}
} else {
@ -235,6 +235,7 @@ function parse_PropertySet(blob, PIDSI) {
/* [MS-OLEPS] 2.21 PropertySetStream */
function parse_PropertySetStream(file, PIDSI) {
var blob = file.content;
if(!blob) return ({}/*:any*/);
prep_blob(blob, 0);
var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;

View File

@ -7,7 +7,7 @@ function parse_XLSCell(blob, length)/*:Cell*/ {
var ixfe = blob.read_shift(2);
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);
o.write_shift(2, R);
o.write_shift(2, C);

View File

@ -341,7 +341,7 @@ var SYLK = (function() {
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/)/*: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 RS = "\r\n";
@ -425,7 +425,7 @@ var DIF = (function() {
};
return function sheet_to_dif(ws/*:Worksheet*/, opts/*:?any*/)/*: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);
push_field(o, "TABLE", 0, 1, "sheetjs");
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.length == 0) cell.t = 'z';
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) {
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); }
@ -586,12 +587,13 @@ var PRN = (function() {
}
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) {
case 'base64': str = Base64.decode(d); break;
case 'binary': str = d; break;
case 'buffer': str = d.toString('binary'); break;
case 'array': str = cc2str(d); break;
case 'string': str = d; break;
default: throw new Error("Unrecognized type " + opts.type);
}
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*/ {
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);
for(var R = r.s.r; R <= r.e.r; ++R) {
var oo = [];

View File

@ -655,7 +655,7 @@ function parse_Rgce(blob, length, opts) {
return ptgs;
}
function stringify_array(f) {
function stringify_array(f)/*:string*/ {
var o = [];
for(var i = 0; i < f.length; ++i) {
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*/ {
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);
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="";
@ -793,7 +793,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
case 'PtgFuncVar': /* 2.5.198.63 */
//console.log(f[1]);
/* 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;
var args = argc == 0 ? [] : stack.slice(-argc);
stack.length -= argc;

View File

@ -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 '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 '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);
C = val[0].c;

View File

@ -174,7 +174,10 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
var opts = _opts || {};
make_ssf(SSF);
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;
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);
@ -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;
}
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>';
if((cell.c||[]).length > 0) m += write_ws_xlml_comment(cell.c);

View File

@ -1,7 +1,8 @@
/* [MS-OLEDS] 2.3.8 CompObjStream */
function parse_compobj(obj) {
function parse_compobj(obj/*:CFBEntry*/) {
var v = {};
var o = obj.content;
/*:: if(o == null) return; */
/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
var l = 28, m;
@ -819,25 +820,31 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
}
/* 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 */
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*/
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*/ {
if(!options) options = {};
fix_read_opts(options);
reset_cp();
var CompObj, Summary, WB/*:?any*/;
var CompObj/*:?CFBEntry*/, Summary, WB/*:?any*/;
if(cfb.FullPaths) {
CompObj = CFB.find(cfb, '!CompObj');
Summary = CFB.find(cfb, '!SummaryInformation');
WB = CFB.find(cfb, '/Workbook');
WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
} else {
switch(options.type) {
case 'base64': cfb = s2a(Base64.decode(cfb)); break;
@ -848,26 +855,24 @@ if(cfb.FullPaths) {
prep_blob(cfb, 0);
WB = ({content: cfb}/*:any*/);
}
if(!WB) WB = CFB.find(cfb, '/Book');
var CompObjP, SummaryP, WorkbookP/*:Workbook*/;
var CompObjP, SummaryP, WorkbookP/*:: :Workbook = XLSX.utils.book_new(); */;
var _data/*:?any*/;
if(CompObj) CompObjP = parse_compobj(CompObj);
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);
/* 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 */
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");
}
if(cfb.FullPaths) parse_props(cfb);
var props = {};
for(var y in cfb.Summary) props[y] = cfb.Summary[y];
for(y in cfb.DocSummary) props[y] = cfb.DocSummary[y];
if(cfb.FullPaths) parse_props(/*::((*/cfb/*:: :any):CFBContainer)*/, props, options);
WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
if(options.bookFiles) WorkbookP.cfb = cfb;
/*WorkbookP.CompObjP = CompObjP; // TODO: storage? */

View File

@ -1,5 +1,5 @@
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;
var len = length || (payload||[]).length || 0;
var o = ba.next(4 + len);

View File

@ -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}});
/* TODO: generate stub cells */
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.e.r < R) range.e.r = R;
if(range.s.c > C) range.s.c = C;
@ -38,7 +38,7 @@ var HTML_ = (function() {
if(opts.dense) {
if(!ws[R]) ws[R] = [];
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 === 'FALSE') ws[R][C] = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)};
@ -48,6 +48,7 @@ var HTML_ = (function() {
/* TODO: value parsing */
if(!m.length){}
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 === 'FALSE') ws[coord] = {t:'b', v:false};
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 elts = row.children;
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) {
var m = merges[midx];
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.length == 0) o.t = 'z';
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 === 'FALSE') o = {t:'b', v:false};
else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};

View File

@ -464,7 +464,9 @@ function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
var content = getzipstr(zip, 'content.xml');
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*/) {
return parse_content_xml(data, opts);

View File

@ -3,8 +3,7 @@ function get_sheet_type(n/*:string*/)/*:string*/ {
if(RELS.CS && n == RELS.CS) return "chart";
if(RELS.DS && n == RELS.DS) return "dialog";
if(RELS.MS && n == RELS.MS) return "macro";
if(!n || !n.length) return "sheet";
return n;
return (n && n.length) ? n : "sheet";
}
function safe_parse_wbrels(wbrels, sheets) {
if(!wbrels) return 0;
@ -88,10 +87,10 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
var props = {}, propdata = "";
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(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);
}
}

View File

@ -60,13 +60,23 @@ function read_utf16(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
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*/ {
var zip, d = data, n=[0];
var zip, d = data, n=[0], str = false;
var o = opts||{};
_ssfopts = {};
if(o.dateNF) _ssfopts.dateNF = o.dateNF;
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 == "string") { str = true; o.type = "binary"; d = bstrify(data); }
switch((n = firstbyte(d, o))[0]) {
case 0xD0: return read_cfb(CFB.read(d, o), 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 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 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 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);
@ -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(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*/ {

View File

@ -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 z = write_zip(wb, o);
var oopts = {};
@ -6,31 +6,51 @@ function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
switch(o.type) {
case "base64": oopts.type = "base64"; break;
case "binary": oopts.type = "string"; break;
case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
case "buffer":
case "file": oopts.type = "nodebuffer"; break;
default: throw new Error("Unrecognized type " + o.type);
}
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 cfb/*:CFBContainer*/ = write_xlscfb(wb, o);
switch(o.type) {
case "base64": case "binary": break;
case "buffer": case "array": o.type = ""; break;
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);
}
return CFB.write(cfb, o);
}
/* TODO: test consistency */
function write_bstr_type(out/*:string*/, opts/*:WriteOpts*/) {
function write_string_type(out/*:string*/, opts/*:WriteOpts*/, bom/*:?string*/)/*:any*/ {
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) {
case "base64": return Base64.encode(out);
case "binary": return out;
case "string": return out; /* override in sheet_to_txt */
case "file": return _fs.writeFileSync(opts.file, out, 'binary');
case "buffer": {
if(has_buf) return new Buffer(out, 'binary');
@ -41,27 +61,14 @@ function write_bstr_type(out/*:string*/, opts/*:WriteOpts*/) {
}
/* TODO: test consistency */
function write_string_type(out/*:string*/, opts/*:WriteOpts*/) {
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*/) {
function write_binary_type(out, opts/*:WriteOpts*/)/*:any*/ {
switch(opts.type) {
case "string":
case "base64":
case "binary":
var bstr = "";
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 "buffer": return out;
default: throw new Error("Unrecognized type " + opts.type);
@ -77,14 +84,14 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
case 'slk':
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 'txt': return write_bstr_type(write_txt_str(wb, o), o);
case 'csv': return write_string_type(write_csv_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, "\ufeff");
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 'rtf': return write_string_type(write_rtf_str(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 'biff3': if(!o.biff) o.biff = 3; 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; /* falls through */
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 'biff8':

View File

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

View File

@ -1,7 +1,7 @@
{
"name": "js-xlsx",
"homepage": "https://github.com/SheetJS/js-xlsx",
"main": "dist/xlsx.core.min.js",
"main": "dist/xlsx.full.min.js",
"ignore": [
"bin",
"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
View File

@ -6,7 +6,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.11.4';
XLSX.version = '0.11.5';
var current_codepage = 1200;
/*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -2039,6 +2039,31 @@ var utf8read = function utf8reada(orig) {
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) {
var utf8readb = function utf8readb(data) {
@ -2062,6 +2087,8 @@ if(has_buf) {
// $FlowIgnore
var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
utf8write = function(data) { return new Buffer(data, 'utf8').toString("binary"); };
}
// 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 = {};
return function vt_regex(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;
}
var __toBuffer, ___toBuffer;
__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 __utf16le, ___utf16le;
__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 __toBuffer = function(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 = function(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 = __hexlify;
var __utf8, ___utf8;
__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 __lpstr, ___lpstr;
__lpstr = ___lpstr = function lpstr_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var __lpwstr, ___lpwstr;
__lpwstr = ___lpwstr = function lpwstr_(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
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(""); };
var ___utf8 = __utf8;
var __lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var ___lpstr = __lpstr;
var __lpwstr = function(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;
__lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
var __8lpp4, ___8lpp4;
__8lpp4 = ___8lpp4 = function lpp4_8(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
var __8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
var ___8lpp4 = __8lpp4;
var __double, ___double;
__double = ___double = function(b, idx) { return read_double_le(b, idx);};
var is_buf = function is_buf_a(a) { return Array.isArray(a); };
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); };
__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);};
__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);};
__utf8 = function utf8_b(b, s,e) { return b.toString('utf8',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) : "";};
__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);};
__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 (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);};
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); };
}
@ -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 __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;
function ReadShift(size, t) {
@ -2295,9 +2326,9 @@ function ReadShift(size, t) {
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 __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) {
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;
} return this;
} else if(f === 'utf16le') {
var end = this.l + t;
var end = this.l + t;
for(i = 0; i < Math.min(val.length, t); ++i) {
var cc = val.charCodeAt(i);
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) {
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;
}
@ -3628,6 +3659,7 @@ var CORE_PROPS_REGEX = (function() {
function parse_core_props(data) {
var p = {};
data = utf8read(data);
for(var i = 0; i < CORE_PROPS.length; ++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) {
var q = {}; if(!p) p = {};
data = utf8read(data);
EXT_PROPS.forEach(function(f) {
switch(f[2]) {
@ -4133,7 +4166,7 @@ function parse_PropertySet(blob, PIDSI) {
case 1252:
case 65000: case -536:
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]);
}
} else {
@ -4175,6 +4208,7 @@ function parse_PropertySet(blob, PIDSI) {
/* [MS-OLEPS] 2.21 PropertySetStream */
function parse_PropertySetStream(file, PIDSI) {
var blob = file.content;
if(!blob) return ({});
prep_blob(blob, 0);
var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;
@ -5685,7 +5719,7 @@ var SYLK = (function() {
function sheet_to_sylk(ws, opts) {
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 RS = "\r\n";
@ -5769,7 +5803,7 @@ var DIF = (function() {
};
return function sheet_to_dif(ws, opts) {
var o = [];
var r = decode_range(ws['!ref']), cell;
var r = safe_decode_range(ws['!ref']), cell;
var dense = Array.isArray(ws);
push_field(o, "TABLE", 0, 1, "sheetjs");
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.length == 0) cell.t = 'z';
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) {
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); }
@ -5930,12 +5965,13 @@ var PRN = (function() {
}
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) {
case 'base64': str = Base64.decode(d); break;
case 'binary': str = d; break;
case 'buffer': str = d.toString('binary'); break;
case 'array': str = cc2str(d); break;
case 'string': str = d; break;
default: throw new Error("Unrecognized type " + opts.type);
}
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) {
var o = [];
var r = decode_range(ws['!ref']), cell;
var r = safe_decode_range(ws['!ref']), cell;
var dense = Array.isArray(ws);
for(var R = r.s.r; R <= r.e.r; ++R) {
var oo = [];
@ -9400,7 +9436,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell, supbooks, opts) {
case 'PtgFuncVar': /* 2.5.198.63 */
//console.log(f[1]);
/* 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;
var args = argc == 0 ? [] : stack.slice(-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 '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 '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);
C = val[0].c;
@ -13380,7 +13416,10 @@ function parse_xlml_xml(d, _opts) {
var opts = _opts || {};
make_ssf(SSF);
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;
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);
@ -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;
}
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>';
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) {
var v = {};
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;
m = __lpstr(o, l);
l += 4 + __readUInt32LE(o,l);
@ -15113,14 +15145,20 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
}
/* TODO: WTF */
function parse_props(cfb) {
function parse_props(cfb, props, o) {
/* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
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*/
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) {
@ -15131,7 +15169,7 @@ var CompObj, Summary, WB;
if(cfb.FullPaths) {
CompObj = CFB.find(cfb, '!CompObj');
Summary = CFB.find(cfb, '!SummaryInformation');
WB = CFB.find(cfb, '/Workbook');
WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
} else {
switch(options.type) {
case 'base64': cfb = s2a(Base64.decode(cfb)); break;
@ -15142,26 +15180,24 @@ if(cfb.FullPaths) {
prep_blob(cfb, 0);
WB = ({content: cfb});
}
if(!WB) WB = CFB.find(cfb, '/Book');
var CompObjP, SummaryP, WorkbookP;
var _data;
if(CompObj) CompObjP = parse_compobj(CompObj);
if(options.bookProps && !options.bookSheets) WorkbookP = ({});
else {
var T = has_buf ? 'buffer' : 'array';
if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options);
/* 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 */
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");
}
if(cfb.FullPaths) parse_props(cfb);
var props = {};
for(var y in cfb.Summary) props[y] = cfb.Summary[y];
for(y in cfb.DocSummary) props[y] = cfb.DocSummary[y];
if(cfb.FullPaths) parse_props(cfb, props, options);
WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
if(options.bookFiles) WorkbookP.cfb = cfb;
/*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}});
/* TODO: generate stub cells */
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.e.r < R) range.e.r = R;
if(range.s.c > C) range.s.c = C;
@ -16696,7 +16732,7 @@ var HTML_ = (function() {
if(opts.dense) {
if(!ws[R]) ws[R] = [];
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 === 'FALSE') ws[R][C] = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)};
@ -16706,6 +16742,7 @@ var HTML_ = (function() {
/* TODO: value parsing */
if(!m.length){}
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 === 'FALSE') ws[coord] = {t:'b', v:false};
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 elts = row.children;
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) {
var m = merges[midx];
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.length == 0) o.t = 'z';
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 === 'FALSE') o = {t:'b', v:false};
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);
var content = getzipstr(zip, 'content.xml');
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) {
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.DS && n == RELS.DS) return "dialog";
if(RELS.MS && n == RELS.MS) return "macro";
if(!n || !n.length) return "sheet";
return n;
return (n && n.length) ? n : "sheet";
}
function safe_parse_wbrels(wbrels, sheets) {
if(!wbrels) return 0;
@ -17643,10 +17682,10 @@ function parse_zip(zip, opts) {
var props = {}, propdata = "";
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(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);
}
}
@ -17952,13 +17991,23 @@ function read_utf16(data, 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) {
var zip, d = data, n=[0];
var zip, d = data, n=[0], str = false;
var o = opts||{};
_ssfopts = {};
if(o.dateNF) _ssfopts.dateNF = o.dateNF;
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 == "string") { str = true; o.type = "binary"; d = bstrify(data); }
switch((n = firstbyte(d, o))[0]) {
case 0xD0: return read_cfb(CFB.read(d, o), 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 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 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 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);
@ -17975,7 +18024,7 @@ function readSync(data, opts) {
}
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("|"));
return PRN.to_workbook(d, o);
return read_prn(data, d, o, str);
}
function readFileSync(filename, opts) {
@ -17990,12 +18039,15 @@ function write_zip_type(wb, opts) {
switch(o.type) {
case "base64": oopts.type = "base64"; break;
case "binary": oopts.type = "string"; break;
case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
case "buffer":
case "file": oopts.type = "nodebuffer"; break;
default: throw new Error("Unrecognized type " + o.type);
}
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) {
@ -18005,16 +18057,33 @@ function write_cfb_type(wb, opts) {
case "base64": case "binary": break;
case "buffer": case "array": o.type = ""; break;
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);
}
return CFB.write(cfb, o);
}
/* TODO: test consistency */
function write_bstr_type(out, opts) {
function write_string_type(out, opts, bom) {
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) {
case "base64": return Base64.encode(out);
case "binary": return out;
case "string": return out; /* override in sheet_to_txt */
case "file": return _fs.writeFileSync(opts.file, out, 'binary');
case "buffer": {
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);
}
/* 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 */
function write_binary_type(out, opts) {
switch(opts.type) {
case "string":
case "base64":
case "binary":
var bstr = "";
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 "buffer": return out;
default: throw new Error("Unrecognized type " + opts.type);
@ -18061,14 +18117,14 @@ function writeSync(wb, opts) {
case 'slk':
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 'txt': return write_bstr_type(write_txt_str(wb, o), o);
case 'csv': return write_string_type(write_csv_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, "\ufeff");
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 'rtf': return write_string_type(write_rtf_str(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 'biff3': if(!o.biff) o.biff = 3; 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; /* falls through */
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 'biff8':
@ -18249,8 +18305,8 @@ function sheet_to_csv(sheet, opts) {
function sheet_to_txt(sheet, opts) {
if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n";
var s = sheet_to_csv(sheet, opts);
if(typeof cptable == 'undefined') return s;
var o = cptable.utils.encode(1200, s);
if(typeof cptable == 'undefined' || opts.type == 'string') return s;
var o = cptable.utils.encode(1200, s, 'str');
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

View File

@ -6,6 +6,9 @@ data and feeding it into the library. Here are a few common scenarios:
<details>
<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
if(typeof require !== 'undefined') XLSX = require('xlsx');
var workbook = XLSX.readFile('test.xlsx');
@ -17,11 +20,21 @@ var workbook = XLSX.readFile('test.xlsx');
<details>
<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
var worksheet = XLSX.utils.table_to_book(document.getElementById('tableau'));
/* 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>

View File

@ -8,16 +8,35 @@ Assuming `workbook` is a workbook object:
<details>
<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
if(typeof require !== 'undefined') XLSX = require('xlsx');
/* output format determined by filename */
XLSX.writeFile(workbook, 'out.xlsx');
/* at this point, out.xlsx is a file that you can distribute */
XLSX.writeFile(workbook, 'out.xlsb');
/* at this point, out.xlsb is a file that you can distribute */
```
</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
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 */
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx");
```
</details>
<details>

View File

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

View File

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

View File

@ -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:
`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
if(typeof require !== 'undefined') XLSX = require('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
var worksheet = XLSX.utils.table_to_book(document.getElementById('tableau'));
/* 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
@ -516,14 +529,30 @@ dissemination. The second step is to actual share the data with the end point.
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
if(typeof require !== 'undefined') XLSX = require('xlsx');
/* output format determined by filename */
XLSX.writeFile(workbook, 'out.xlsx');
/* at this point, out.xlsx is a file that you can distribute */
XLSX.writeFile(workbook, 'out.xlsb');
/* 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
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
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):
@ -1325,6 +1355,7 @@ tells the library how to parse the data argument:
|------------|-----------------------------------------------------------------|
| `"base64"` | string: Base64 encoding of the file |
| `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) |
| `"string"` | string: JS string (characters interpreted as UTF8) |
| `"buffer"` | nodejs Buffer |
| `"array"` | array: array of 8-bit unsigned int (byte `n` is `data[n]`) |
| `"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 |
| `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) |
| `"string"` | string: JS string (characters interpreted as UTF8) |
| `"buffer"` | nodejs Buffer |
| `"file"` | string: path of file that will be created (nodejs only) |
## Utility Functions
The `sheet_to_*` functions accept a worksheet and an optional options object.

View File

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

View File

@ -1,6 +1,6 @@
{
"name": "xlsx",
"version": "0.11.4",
"version": "0.11.5",
"author": "sheetjs",
"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" ],

11
shim.js
View File

@ -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
View File

@ -1,5 +1,6 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*jshint loopfunc:true, eqnull:true */
/*jshint -W069, loopfunc:true, mocha:true */
var X;
var modp = './';
//var modp = 'xlsx';
@ -7,7 +8,7 @@ var fs = require('fs'), assert = require('assert');
describe('source',function(){it('should load',function(){X=require(modp);});});
var DIF_XL = true;
var browser = false;
var browser = typeof document !== 'undefined';
var opts = {cellNF: true};
var TYPE = browser ? "binary" : "buffer";
@ -36,15 +37,48 @@ function fixjson(x) { return x.replace(/[\r\n]+$/,""); }
var dir = "./test_files/";
var dirwp = dir + "artifacts/wps/", dirqp = dir + "artifacts/quattro/";
var paths = {
afxls: dir + 'AutoFilter.xls',
afxml: dir + 'AutoFilter.xml',
afods: dir + 'AutoFilter.ods',
aadbf: dirwp + 'write.dbf',
aadif: dirwp + 'write.dif',
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',
afxlsb: dir + 'AutoFilter.xlsb',
cpxls: dir + 'custom_properties.xls',
cpxml: dir + 'custom_properties.xls.xml',
asxls: dir + 'author_snowman.xls',
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',
cpxlsb: dir + 'custom_properties.xlsb',
@ -226,19 +260,19 @@ function parsetest(x, wb, full, ext) {
if(fs.existsSync(dir + '2011/' + x + '.xml'))
describe(x + ext + '.xml from 2011', 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'))
describe(x + ext + '.xlsb from 2013', 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))
describe(x + '.xml', 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() {
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() {
X.read(fs.readFileSync(paths.cstxlsx, 'binary'), {type: 'binary'});
X.read(fs.readFileSync(paths.cstxlsb, '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'});
_paths.forEach(function(pth) {
X.read(fs.readFileSync(pth, 'binary'), {type: 'binary'});
});
});
it('should read base64 strings', function() {
X.read(fs.readFileSync(paths.cstxls, 'base64'), {type: 'base64'});
X.read(fs.readFileSync(paths.cstxml, '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'});
_paths.forEach(function(pth) {
X.read(fs.readFileSync(pth, 'base64'), {type: 'base64'});
});
});
var k = browser ? 'array' : 'buffer';
(typeof Uint8Array !== 'undefined' ? it : it.skip)('should read ' + k + 's', function() {
X.read(fs.readFileSync(paths.cstxls, browser ? 'buffer' : null), {type: k});
X.read(fs.readFileSync(paths.cstxml, 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});
_paths.forEach(function(pth) {
X.read(fs.readFileSync(pth, browser ? 'buffer' : null), {type: k});
});
});
(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'});
X.read(fs.readFileSync(paths.cstxml, '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'});
_paths.forEach(function(pth) {
X.read(fs.readFileSync(pth, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
});
});
it('should throw if format is unknown', function() {
assert.throws(function() { X.read(fs.readFileSync(paths.cstxls), {type: 'dafuq'}); });
assert.throws(function() { X.read(fs.readFileSync(paths.cstxml), {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'}); });
_paths.forEach(function(pth) {
assert.throws(function() { X.read(fs.readFileSync(pth), {type: 'dafuq'}); });
});
});
if(browser) it('should default to base64 type', function() {
X.read(fs.readFileSync(paths.cstxls, 'base64'));
X.read(fs.readFileSync(paths.cstxml, 'base64'));
X.read(fs.readFileSync(paths.cstods, 'base64'));
X.read(fs.readFileSync(paths.cstxlsx, 'base64'));
X.read(fs.readFileSync(paths.cstxlsb, 'base64'));
_paths.forEach(function(pth) {
X.read(fs.readFileSync(pth, 'base64'));
});
});
else {
it('should infer buffer type', function() {
X.read(fs.readFileSync(paths.cstxls));
X.read(fs.readFileSync(paths.cstxml));
X.read(fs.readFileSync(paths.cstods));
X.read(fs.readFileSync(paths.cstxlsx));
X.read(fs.readFileSync(paths.cstxlsb));
_paths.forEach(function(pth) {
X.read(fs.readFileSync(pth));
});
});
it('should read files', function() {
X.readFile(paths.cstxls);
X.readFile(paths.cstxml);
X.readFile(paths.cstods);
X.readFile(paths.cstxlsx);
X.readFile(paths.cstxlsb);
_paths.forEach(function(pth) {
X.readFile(pth);
});
});
}
});
describe('output formats', function() {
var wb1, wb2, wb3, wb4;
var bef = (function() {
X = require(modp);
wb1 = X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE});
wb2 = X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE});
wb3 = X.read(fs.readFileSync(paths.cpxls), {type:TYPE});
wb4 = X.read(fs.readFileSync(paths.cpxml), {type:TYPE});
});
if(typeof before != 'undefined') before(bef);
else it('before', bef);
it('should write binary strings', function() {
if(!wb1) {
wb1 = X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE});
wb2 = X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE});
wb3 = X.read(fs.readFileSync(paths.cpxls), {type:TYPE});
wb4 = X.read(fs.readFileSync(paths.cpxml), {type:TYPE});
}
X.write(wb1, {type: 'binary'});
X.write(wb2, {type: 'binary'});
X.write(wb3, {type: 'binary'});
X.write(wb4, {type: 'binary'});
X.read(X.write(wb1, {type: 'binary'}), {type: 'binary'});
X.read(X.write(wb2, {type: 'binary'}), {type: 'binary'});
X.read(X.write(wb3, {type: 'binary'}), {type: 'binary'});
X.read(X.write(wb4, {type: 'binary'}), {type: 'binary'});
});
it('should write base64 strings', function() {
X.write(wb1, {type: 'base64'});
X.write(wb2, {type: 'base64'});
X.write(wb3, {type: 'base64'});
X.write(wb4, {type: 'base64'});
X.read(X.write(wb1, {type: 'base64'}), {type: 'base64'});
X.read(X.write(wb2, {type: 'base64'}), {type: 'base64'});
X.read(X.write(wb3, {type: 'base64'}), {type: 'base64'});
X.read(X.write(wb4, {type: 'base64'}), {type: 'base64'});
});
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'}); });
});
var fmts = [
/* fmt unicode str */
["xlsx", true, false],
["xlsb", true, false],
["xls", true, false],
["xlml", true, true],
["ods", true, false],
["fods", true, true],
["csv", true, true],
["txt", true, true],
["sylk", false, true],
["html", true, true],
["dif", false, true],
["prn", false, true]
];
function RT(T) {
if(!X) X = require(modp);
fmts.forEach(function(fmt) {
var wb = X.utils.book_new();
X.utils.book_append_sheet(wb, X.utils.aoa_to_sheet([['R',"\u2603"],["\u0BEE",2]]), "Sheet1");
if(T == 'string' && !fmt[2]) return assert.throws(function() {X.write(wb, {type: T, bookType:fmt[0], WTF:1});});
var out = X.write(wb, {type: T, bookType:fmt[0], WTF:1});
var nwb = X.read(out, {type: T, WTF:1});
var nws = nwb.Sheets[nwb.SheetNames[0]];
assert.equal(get_cell(nws, "B2").v, 2);
assert.equal(get_cell(nws, "A1").v, "R");
if(fmt[1]) assert.equal(get_cell(nws, "A2").v, "\u0BEE");
if(fmt[1]) assert.equal(get_cell(nws, "B1").v, "\u2603");
});
}
it('should write binary strings', function() { RT('binary'); });
it('should write base64 strings', function() { RT('base64'); });
it('should write JS strings', function() { RT('string'); });
if(!browser) it('should write buffers', function() { RT('buffer'); });
it('should throw if format is unknown', function() { assert.throws(function() { RT('dafuq'); }); });
});
function eqarr(a,b) {
@ -756,30 +763,32 @@ function check_margin(margins, exp) {
describe('parse features', function() {
describe('sheet visibility', function() {
var wb1, wb2, wb3, wb4, wb5;
var wbs = [];
var bef = (function() {
wb1 = X.read(fs.readFileSync(paths.svxls), {type:TYPE});
wb2 = X.read(fs.readFileSync(paths.svxls5), {type:TYPE});
wb3 = X.read(fs.readFileSync(paths.svxml), {type:TYPE});
wb4 = X.read(fs.readFileSync(paths.svxlsx), {type:TYPE});
wb5 = X.read(fs.readFileSync(paths.svxlsb), {type:TYPE});
wbs = [
X.read(fs.readFileSync(paths.svxls), {type:TYPE}),
X.read(fs.readFileSync(paths.svxls5), {type:TYPE}),
X.read(fs.readFileSync(paths.svxml), {type:TYPE}),
X.read(fs.readFileSync(paths.svxlsx), {type:TYPE}),
X.read(fs.readFileSync(paths.svxlsb), {type:TYPE})
];
});
if(typeof before != 'undefined') before(bef);
else it('before', bef);
it('should detect visible sheets', function() {
[wb1, wb2, wb3, wb4, wb5].forEach(function(wb) {
wbs.forEach(function(wb) {
assert(!wb.Workbook.Sheets[0].Hidden);
});
});
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[2].Hidden);
});
});
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[2].Hidden,2);
});
@ -822,24 +831,44 @@ describe('parse features', function() {
});
describe('should parse core properties and custom properties', function() {
var wb1, wb2, wb3, wb4;
var wbs=[];
var bef = (function() {
wb1 = X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE});
wb2 = X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE});
wb3 = X.read(fs.readFileSync(paths.cpxls), {type:TYPE});
wb4 = X.read(fs.readFileSync(paths.cpxml), {type:TYPE});
wbs = [
X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE}),
X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE}),
X.read(fs.readFileSync(paths.cpxls), {type:TYPE}),
X.read(fs.readFileSync(paths.cpxml), {type:TYPE})
];
});
if(typeof before != 'undefined') before(bef);
else it('before', bef);
it(N1 + ' should parse core properties', function() { coreprop(wb1); });
it(N2 + ' should parse core properties', function() { coreprop(wb2); });
it(N3 + ' should parse core properties', function() { coreprop(wb3); });
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); });
it(N3 + ' should parse custom properties', function() { custprop(wb3); });
it(N4 + ' should parse custom properties', function() { custprop(wb4); });
[N1, N2, N3, N4].forEach(function(x, i) {
it(x + ' should parse core properties', function() { coreprop(wbs[i]); });
it(x + ' should parse custom properties', function() { custprop(wbs[i]); });
});
[
["asxls", "BIFF8", "\u2603"],
["asxls5", "BIFF5", "_"],
["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() {
@ -930,6 +959,7 @@ describe('parse features', function() {
describe('row properties', function() {
var wb1, wb2, wb3, wb4, wb5, wb6;
var ol1, ol2, ol3, ol4, ol5;
var ol = fs.existsSync(paths.olxls);
var bef = (function() {
X = require(modp);
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});
wb5 = X.read(fs.readFileSync(paths.rhxml), {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});
ol2 = X.read(fs.readFileSync(paths.olxlsb), {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);
});
});
it('should have correct outline levels', function() {
(ol ? it : it.skip)('should have correct outline levels', function() {
/* TODO: ODS */
[ol1, ol2, ol3, ol4/*, ol5*/].map(function(x) { return x.Sheets.Sheet1; }).forEach(function(ws) {
var rows = ws['!rows'];
@ -973,7 +1005,7 @@ describe('parse features', function() {
var lvl = (rows[i]||{}).level||0;
if(!cell || cell.t == 's') assert.equal(lvl, 0);
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);
}
}
@ -983,47 +1015,47 @@ describe('parse features', function() {
});
describe('merge cells',function() {
var wb1, wb2, wb3, wb4, wb5;
var wbs=[];
var bef = (function() {
X = require(modp);
wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE});
wb2 = X.read(fs.readFileSync(paths.mcxlsb), {type:TYPE});
wb3 = X.read(fs.readFileSync(paths.mcods), {type:TYPE});
wb4 = X.read(fs.readFileSync(paths.mcxls), {type:TYPE});
wb5 = X.read(fs.readFileSync(paths.mcxml), {type:TYPE});
wbs = [
X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE}),
X.read(fs.readFileSync(paths.mcxlsb), {type:TYPE}),
X.read(fs.readFileSync(paths.mcods), {type:TYPE}),
X.read(fs.readFileSync(paths.mcxls), {type:TYPE}),
X.read(fs.readFileSync(paths.mcxml), {type:TYPE})
];
});
if(typeof before != 'undefined') before(bef);
else it('before', bef);
it('should have !merges', function() {
assert(wb1.Sheets.Merge['!merges']);
assert(wb2.Sheets.Merge['!merges']);
assert(wb3.Sheets.Merge['!merges']);
assert(wb4.Sheets.Merge['!merges']);
assert(wb5.Sheets.Merge['!merges']);
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(),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());
wbs.forEach(function(wb) {
assert(wb.Sheets.Merge['!merges']);
});
var m = wbs.map(function(x) { return x.Sheets.Merge['!merges'].map(function(y) { return X.utils.encode_range(y); });});
m.slice(1).forEach(function(x) {
assert.deepEqual(m[0].sort(),x.sort());
});
});
});
describe('should find hyperlinks', function() {
var wb1, wb2, wb3, wb4;
var wbs;
var bef = (function() {
X = require(modp);
wb1 = X.read(fs.readFileSync(paths.hlxlsx), {type:TYPE});
wb2 = X.read(fs.readFileSync(paths.hlxlsb), {type:TYPE});
wb3 = X.read(fs.readFileSync(paths.hlxls), {type:TYPE});
wb4 = X.read(fs.readFileSync(paths.hlxml), {type:TYPE});
wbs = [
X.read(fs.readFileSync(paths.hlxlsx), {type:TYPE}),
X.read(fs.readFileSync(paths.hlxlsb), {type:TYPE}),
X.read(fs.readFileSync(paths.hlxls), {type:TYPE}),
X.read(fs.readFileSync(paths.hlxml), {type:TYPE})
];
});
if(typeof before != 'undefined') before(bef);
else it('before', bef);
it(N1, function() { hlink(wb1); });
it(N2, function() { hlink(wb2); });
it(N3, function() { hlink(wb3); });
it(N4, function() { hlink(wb4); });
[N1, N2, N3, N4].forEach(function(x, i) {
it(x, function() { hlink(wbs[i]); });
});
});
describe('should parse cells with date type (XLSX/XLSM)', function() {
@ -1077,7 +1109,7 @@ describe('parse features', function() {
['xlsx', paths.dnsxlsx, true],
['xlsb', paths.dnsxlsb, true],
['xls', paths.dnsxls, true],
['xlml', paths.dnsxml, false],
['xlml', paths.dnsxml, false]
].forEach(function(m) { it(m[0], function() {
var wb = X.read(fs.readFileSync(m[1]), {type:TYPE});
var names = wb.Workbook.Names;
@ -1103,9 +1135,9 @@ describe('parse features', function() {
['ods', paths.afods]
].forEach(function(m) { it(m[0], function() {
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) {
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");
}
}); });
@ -1132,15 +1164,16 @@ describe('parse features', function() {
});
describe('page margins', function() {
var wb1, wb2, wb3, wb4, wb5, wbs;
var wbs=[];
var bef = (function() {
if(!fs.existsSync(paths.pmxls)) return wbs=[];
wb1 = X.read(fs.readFileSync(paths.pmxls), {type:TYPE});
wb2 = X.read(fs.readFileSync(paths.pmxls5), {type:TYPE});
wb3 = X.read(fs.readFileSync(paths.pmxml), {type:TYPE});
wb4 = X.read(fs.readFileSync(paths.pmxlsx), {type:TYPE});
wb5 = X.read(fs.readFileSync(paths.pmxlsb), {type:TYPE});
wbs = [wb1, wb2, wb3, wb4, wb5];
if(!fs.existsSync(paths.pmxls)) return;
wbs = [
X.read(fs.readFileSync(paths.pmxls), {type:TYPE}),
X.read(fs.readFileSync(paths.pmxls5), {type:TYPE}),
X.read(fs.readFileSync(paths.pmxml), {type:TYPE}),
X.read(fs.readFileSync(paths.pmxlsx), {type:TYPE}),
X.read(fs.readFileSync(paths.pmxlsb), {type:TYPE})
];
});
if(typeof before != 'undefined') 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]);
});
});
it('should parse wide margins ', function() {
it('should parse wide margins', function() {
wbs.forEach(function(wb) {
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) {
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) {
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]);
@ -1255,7 +1288,7 @@ describe('write features', function() {
baseprops = {
Category: "Newspaper",
ContentStatus: "Published",
Keywords: "print",
Keywords: "",
LastAuthor: "Perry White",
LastPrinted: "1978-12-15",
RevNumber: 6969,
@ -1271,7 +1304,7 @@ describe('write features', function() {
if(typeof before != 'undefined') before(bef);
else it('before', bef);
['xlml', 'xlsx', 'xlsb'].forEach(function(w) { it(w, function() {
wb = {
var wb = {
Props: {},
SheetNames: ["Sheet1"],
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);
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() {
it('should pass -> XLSX', function() {
X.write(X.read(fs.readFileSync(paths.fstxlsb), {type:TYPE}), {type:TYPE});
X.write(X.read(fs.readFileSync(paths.fstxlsx), {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});
["fstxlsb", "fstxlsx", "fstxls", "fstxml"].forEach(function(n) {
X.write(X.read(fs.readFileSync(paths[n]), {type:TYPE}), {type:TYPE});
});
});
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]];
@ -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 _ws = X.utils.aoa_to_sheet(_data);
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
var json2 = X.utils.sheet_to_json(_ws, {header:1});
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
var json4 = X.utils.sheet_to_json(_ws, {blankrows:true, header:1});
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
var json6 = X.utils.sheet_to_json(_ws, {blankrows:false, header:1});
assert.equal(json6.length, 3); // = 4 sheet rows - 1 blank row
});
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 = [
["A1", 'n', -0.08, "-0.08"],
["B1", 'n', 4001, "4,001"],
["C1", 's', "あ 1", "あ 1"],
["A2", 'n', 41.08, "$41.08"],
["B2", 'n', 0.11, "11%"],
["B3", 'b', true, "TRUE"],
["C3", 'b', false, "FALSE"],
["A3"]];
function plaintext_test(wb, raw, sn) {
var sheet = wb.Sheets[sn || wb.SheetNames[0]];
["C3", 'b', true, "TRUE"],
["D3", 'b', false, "FALSE"],
["B3", 's', " ", " "],
["A3"]
];
function plaintext_test(wb, raw, t) {
var sheet = wb.Sheets[wb.SheetNames[0]];
plaintext_val.forEach(function(x) {
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; }
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>",
"<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></td><td>TRUE</td><td>FALSE</td></tr>",
"<tr><td></td><td> \n&nbsp;</td><td>TRUE</td><td>FALSE</td></tr>",
"</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] + '',
'$41.08,11%',
',TRUE,FALSE'
', ,TRUE,FALSE'
].join("\n"); }
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() {
@ -1779,7 +1815,7 @@ describe('csv', function() {
var cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3");
assert.equal(cell.w, '2/19/14');
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');
});
it('should honor dateNF override', function() {
@ -1788,7 +1824,7 @@ describe('csv', function() {
/* NOTE: IE interprets 2-digit years as 19xx */
assert(cell.w == '2014-02-19' || cell.w == '1914-02-19');
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');
});
it('should interpret dateNF', function() {
@ -1802,8 +1838,8 @@ describe('csv', function() {
assert.equal(cell.v.getMonth(), 2);
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 generate strings if raw option is passed', function() { plaintext_test(X.read(csv_bstr, {type:"binary", raw:true}), true); });
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, false); });
it('should handle formulae', function() {
var bb = '=,=1+1,="100"';
var sheet = X.read(bb, {type:"binary"}).Sheets.Sheet1;
@ -1903,12 +1939,13 @@ function get_dom_element(html) {
describe('HTML', function() {
describe('input string', function(){
it('should interpret values by default', function() { plaintext_test(X.read(html_bstr, {type:"binary"}), false); });
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(html_bstr, {type:"binary", raw:true}), true); });
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, false); });
it('should handle "string" type', function() { plaintext_test(X.read(html_str, {type:"string"}), false, false); });
});
(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 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 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, true); });
});
});
@ -1933,25 +1970,14 @@ describe('js -> file -> js', function() {
ofmt.forEach(function(f) {
it(f, function() {
var newwb = X.read(X.write(wb, {type:BIN, bookType: f}), {type:BIN});
/* int */
eqcell(wb, newwb, 'Sheet1', 'A1');
eqcell(wb, newwb, 'Sheet1', 'B1');
eqcell(wb, newwb, 'Sheet1', 'C1');
/* double */
eqcell(wb, newwb, 'Sheet1', 'B4');
/* 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');
var cb = function(cell) { eqcell(wb, newwb, 'Sheet1', cell); };
['A1', 'B1', 'C1'].forEach(cb); /* int */
['B4'].forEach(cb); /* double */
['A2', 'B2'].forEach(cb); /* bool */
['D2', 'A3', 'B3', 'A4', 'C4'].forEach(cb); /* string */
if(!DIF_XL) cb('C3'); /* date */
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');
/* date */
if(!DIF_XL) eqcell(wb, newwb, 'Sheet1', 'C3');
});
});
});
@ -1997,12 +2023,13 @@ describe('corner cases', function() {
});
it('SSF oddities', function() {
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) {
for(var j=1;j<d.length;++j) {
if(d[j].length == 2) {
var expected = d[j][1], actual = X.SSF.format(d[0], d[j][0], {});
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() {
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

View File

@ -1,5 +1,6 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*jshint loopfunc:true, eqnull:true */
/*jshint -W069, loopfunc:true, mocha:true */
var X;
var modp = './';
//var modp = 'xlsx';
@ -7,7 +8,7 @@ var fs = require('fs'), assert = require('assert');
describe('source',function(){it('should load',function(){X=require(modp);});});
var DIF_XL = true;
var browser = true;
var browser = typeof document !== 'undefined';
var opts = {cellNF: true};
var TYPE = browser ? "binary" : "buffer";
@ -36,15 +37,48 @@ function fixjson(x) { return x.replace(/[\r\n]+$/,""); }
var dir = "./test_files/";
var dirwp = dir + "artifacts/wps/", dirqp = dir + "artifacts/quattro/";
var paths = {
afxls: dir + 'AutoFilter.xls',
afxml: dir + 'AutoFilter.xml',
afods: dir + 'AutoFilter.ods',
aadbf: dirwp + 'write.dbf',
aadif: dirwp + 'write.dif',
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',
afxlsb: dir + 'AutoFilter.xlsb',
cpxls: dir + 'custom_properties.xls',
cpxml: dir + 'custom_properties.xls.xml',
asxls: dir + 'author_snowman.xls',
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',
cpxlsb: dir + 'custom_properties.xlsb',
@ -226,19 +260,19 @@ function parsetest(x, wb, full, ext) {
if(fs.existsSync(dir + '2011/' + x + '.xml'))
describe(x + ext + '.xml from 2011', 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'))
describe(x + ext + '.xlsb from 2013', 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))
describe(x + '.xml', 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() {
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() {
X.read(fs.readFileSync(paths.cstxlsx, 'binary'), {type: 'binary'});
X.read(fs.readFileSync(paths.cstxlsb, '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'});
_paths.forEach(function(pth) {
X.read(fs.readFileSync(pth, 'binary'), {type: 'binary'});
});
});
it('should read base64 strings', function() {
X.read(fs.readFileSync(paths.cstxls, 'base64'), {type: 'base64'});
X.read(fs.readFileSync(paths.cstxml, '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'});
_paths.forEach(function(pth) {
X.read(fs.readFileSync(pth, 'base64'), {type: 'base64'});
});
});
var k = browser ? 'array' : 'buffer';
(typeof Uint8Array !== 'undefined' ? it : it.skip)('should read ' + k + 's', function() {
X.read(fs.readFileSync(paths.cstxls, browser ? 'buffer' : null), {type: k});
X.read(fs.readFileSync(paths.cstxml, 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});
_paths.forEach(function(pth) {
X.read(fs.readFileSync(pth, browser ? 'buffer' : null), {type: k});
});
});
(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'});
X.read(fs.readFileSync(paths.cstxml, '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'});
_paths.forEach(function(pth) {
X.read(fs.readFileSync(pth, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
});
});
it('should throw if format is unknown', function() {
assert.throws(function() { X.read(fs.readFileSync(paths.cstxls), {type: 'dafuq'}); });
assert.throws(function() { X.read(fs.readFileSync(paths.cstxml), {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'}); });
_paths.forEach(function(pth) {
assert.throws(function() { X.read(fs.readFileSync(pth), {type: 'dafuq'}); });
});
});
if(browser) it('should default to base64 type', function() {
X.read(fs.readFileSync(paths.cstxls, 'base64'));
X.read(fs.readFileSync(paths.cstxml, 'base64'));
X.read(fs.readFileSync(paths.cstods, 'base64'));
X.read(fs.readFileSync(paths.cstxlsx, 'base64'));
X.read(fs.readFileSync(paths.cstxlsb, 'base64'));
_paths.forEach(function(pth) {
X.read(fs.readFileSync(pth, 'base64'));
});
});
else {
it('should infer buffer type', function() {
X.read(fs.readFileSync(paths.cstxls));
X.read(fs.readFileSync(paths.cstxml));
X.read(fs.readFileSync(paths.cstods));
X.read(fs.readFileSync(paths.cstxlsx));
X.read(fs.readFileSync(paths.cstxlsb));
_paths.forEach(function(pth) {
X.read(fs.readFileSync(pth));
});
});
it('should read files', function() {
X.readFile(paths.cstxls);
X.readFile(paths.cstxml);
X.readFile(paths.cstods);
X.readFile(paths.cstxlsx);
X.readFile(paths.cstxlsb);
_paths.forEach(function(pth) {
X.readFile(pth);
});
});
}
});
describe('output formats', function() {
var wb1, wb2, wb3, wb4;
var bef = (function() {
X = require(modp);
wb1 = X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE});
wb2 = X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE});
wb3 = X.read(fs.readFileSync(paths.cpxls), {type:TYPE});
wb4 = X.read(fs.readFileSync(paths.cpxml), {type:TYPE});
});
if(typeof before != 'undefined') before(bef);
else it('before', bef);
it('should write binary strings', function() {
if(!wb1) {
wb1 = X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE});
wb2 = X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE});
wb3 = X.read(fs.readFileSync(paths.cpxls), {type:TYPE});
wb4 = X.read(fs.readFileSync(paths.cpxml), {type:TYPE});
}
X.write(wb1, {type: 'binary'});
X.write(wb2, {type: 'binary'});
X.write(wb3, {type: 'binary'});
X.write(wb4, {type: 'binary'});
X.read(X.write(wb1, {type: 'binary'}), {type: 'binary'});
X.read(X.write(wb2, {type: 'binary'}), {type: 'binary'});
X.read(X.write(wb3, {type: 'binary'}), {type: 'binary'});
X.read(X.write(wb4, {type: 'binary'}), {type: 'binary'});
});
it('should write base64 strings', function() {
X.write(wb1, {type: 'base64'});
X.write(wb2, {type: 'base64'});
X.write(wb3, {type: 'base64'});
X.write(wb4, {type: 'base64'});
X.read(X.write(wb1, {type: 'base64'}), {type: 'base64'});
X.read(X.write(wb2, {type: 'base64'}), {type: 'base64'});
X.read(X.write(wb3, {type: 'base64'}), {type: 'base64'});
X.read(X.write(wb4, {type: 'base64'}), {type: 'base64'});
});
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'}); });
});
var fmts = [
/* fmt unicode str */
["xlsx", true, false],
["xlsb", true, false],
["xls", true, false],
["xlml", true, true],
["ods", true, false],
["fods", true, true],
["csv", true, true],
["txt", true, true],
["sylk", false, true],
["html", true, true],
["dif", false, true],
["prn", false, true]
];
function RT(T) {
if(!X) X = require(modp);
fmts.forEach(function(fmt) {
var wb = X.utils.book_new();
X.utils.book_append_sheet(wb, X.utils.aoa_to_sheet([['R',"\u2603"],["\u0BEE",2]]), "Sheet1");
if(T == 'string' && !fmt[2]) return assert.throws(function() {X.write(wb, {type: T, bookType:fmt[0], WTF:1});});
var out = X.write(wb, {type: T, bookType:fmt[0], WTF:1});
var nwb = X.read(out, {type: T, WTF:1});
var nws = nwb.Sheets[nwb.SheetNames[0]];
assert.equal(get_cell(nws, "B2").v, 2);
assert.equal(get_cell(nws, "A1").v, "R");
if(fmt[1]) assert.equal(get_cell(nws, "A2").v, "\u0BEE");
if(fmt[1]) assert.equal(get_cell(nws, "B1").v, "\u2603");
});
}
it('should write binary strings', function() { RT('binary'); });
it('should write base64 strings', function() { RT('base64'); });
it('should write JS strings', function() { RT('string'); });
if(!browser) it('should write buffers', function() { RT('buffer'); });
it('should throw if format is unknown', function() { assert.throws(function() { RT('dafuq'); }); });
});
function eqarr(a,b) {
@ -756,30 +763,32 @@ function check_margin(margins, exp) {
describe('parse features', function() {
describe('sheet visibility', function() {
var wb1, wb2, wb3, wb4, wb5;
var wbs = [];
var bef = (function() {
wb1 = X.read(fs.readFileSync(paths.svxls), {type:TYPE});
wb2 = X.read(fs.readFileSync(paths.svxls5), {type:TYPE});
wb3 = X.read(fs.readFileSync(paths.svxml), {type:TYPE});
wb4 = X.read(fs.readFileSync(paths.svxlsx), {type:TYPE});
wb5 = X.read(fs.readFileSync(paths.svxlsb), {type:TYPE});
wbs = [
X.read(fs.readFileSync(paths.svxls), {type:TYPE}),
X.read(fs.readFileSync(paths.svxls5), {type:TYPE}),
X.read(fs.readFileSync(paths.svxml), {type:TYPE}),
X.read(fs.readFileSync(paths.svxlsx), {type:TYPE}),
X.read(fs.readFileSync(paths.svxlsb), {type:TYPE})
];
});
if(typeof before != 'undefined') before(bef);
else it('before', bef);
it('should detect visible sheets', function() {
[wb1, wb2, wb3, wb4, wb5].forEach(function(wb) {
wbs.forEach(function(wb) {
assert(!wb.Workbook.Sheets[0].Hidden);
});
});
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[2].Hidden);
});
});
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[2].Hidden,2);
});
@ -822,24 +831,44 @@ describe('parse features', function() {
});
describe('should parse core properties and custom properties', function() {
var wb1, wb2, wb3, wb4;
var wbs=[];
var bef = (function() {
wb1 = X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE});
wb2 = X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE});
wb3 = X.read(fs.readFileSync(paths.cpxls), {type:TYPE});
wb4 = X.read(fs.readFileSync(paths.cpxml), {type:TYPE});
wbs = [
X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE}),
X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE}),
X.read(fs.readFileSync(paths.cpxls), {type:TYPE}),
X.read(fs.readFileSync(paths.cpxml), {type:TYPE})
];
});
if(typeof before != 'undefined') before(bef);
else it('before', bef);
it(N1 + ' should parse core properties', function() { coreprop(wb1); });
it(N2 + ' should parse core properties', function() { coreprop(wb2); });
it(N3 + ' should parse core properties', function() { coreprop(wb3); });
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); });
it(N3 + ' should parse custom properties', function() { custprop(wb3); });
it(N4 + ' should parse custom properties', function() { custprop(wb4); });
[N1, N2, N3, N4].forEach(function(x, i) {
it(x + ' should parse core properties', function() { coreprop(wbs[i]); });
it(x + ' should parse custom properties', function() { custprop(wbs[i]); });
});
[
["asxls", "BIFF8", "\u2603"],
["asxls5", "BIFF5", "_"],
["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() {
@ -930,6 +959,7 @@ describe('parse features', function() {
describe('row properties', function() {
var wb1, wb2, wb3, wb4, wb5, wb6;
var ol1, ol2, ol3, ol4, ol5;
var ol = fs.existsSync(paths.olxls);
var bef = (function() {
X = require(modp);
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});
wb5 = X.read(fs.readFileSync(paths.rhxml), {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});
ol2 = X.read(fs.readFileSync(paths.olxlsb), {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);
});
});
it('should have correct outline levels', function() {
(ol ? it : it.skip)('should have correct outline levels', function() {
/* TODO: ODS */
[ol1, ol2, ol3, ol4/*, ol5*/].map(function(x) { return x.Sheets.Sheet1; }).forEach(function(ws) {
var rows = ws['!rows'];
@ -973,7 +1005,7 @@ describe('parse features', function() {
var lvl = (rows[i]||{}).level||0;
if(!cell || cell.t == 's') assert.equal(lvl, 0);
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);
}
}
@ -983,47 +1015,47 @@ describe('parse features', function() {
});
describe('merge cells',function() {
var wb1, wb2, wb3, wb4, wb5;
var wbs=[];
var bef = (function() {
X = require(modp);
wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE});
wb2 = X.read(fs.readFileSync(paths.mcxlsb), {type:TYPE});
wb3 = X.read(fs.readFileSync(paths.mcods), {type:TYPE});
wb4 = X.read(fs.readFileSync(paths.mcxls), {type:TYPE});
wb5 = X.read(fs.readFileSync(paths.mcxml), {type:TYPE});
wbs = [
X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE}),
X.read(fs.readFileSync(paths.mcxlsb), {type:TYPE}),
X.read(fs.readFileSync(paths.mcods), {type:TYPE}),
X.read(fs.readFileSync(paths.mcxls), {type:TYPE}),
X.read(fs.readFileSync(paths.mcxml), {type:TYPE})
];
});
if(typeof before != 'undefined') before(bef);
else it('before', bef);
it('should have !merges', function() {
assert(wb1.Sheets.Merge['!merges']);
assert(wb2.Sheets.Merge['!merges']);
assert(wb3.Sheets.Merge['!merges']);
assert(wb4.Sheets.Merge['!merges']);
assert(wb5.Sheets.Merge['!merges']);
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(),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());
wbs.forEach(function(wb) {
assert(wb.Sheets.Merge['!merges']);
});
var m = wbs.map(function(x) { return x.Sheets.Merge['!merges'].map(function(y) { return X.utils.encode_range(y); });});
m.slice(1).forEach(function(x) {
assert.deepEqual(m[0].sort(),x.sort());
});
});
});
describe('should find hyperlinks', function() {
var wb1, wb2, wb3, wb4;
var wbs;
var bef = (function() {
X = require(modp);
wb1 = X.read(fs.readFileSync(paths.hlxlsx), {type:TYPE});
wb2 = X.read(fs.readFileSync(paths.hlxlsb), {type:TYPE});
wb3 = X.read(fs.readFileSync(paths.hlxls), {type:TYPE});
wb4 = X.read(fs.readFileSync(paths.hlxml), {type:TYPE});
wbs = [
X.read(fs.readFileSync(paths.hlxlsx), {type:TYPE}),
X.read(fs.readFileSync(paths.hlxlsb), {type:TYPE}),
X.read(fs.readFileSync(paths.hlxls), {type:TYPE}),
X.read(fs.readFileSync(paths.hlxml), {type:TYPE})
];
});
if(typeof before != 'undefined') before(bef);
else it('before', bef);
it(N1, function() { hlink(wb1); });
it(N2, function() { hlink(wb2); });
it(N3, function() { hlink(wb3); });
it(N4, function() { hlink(wb4); });
[N1, N2, N3, N4].forEach(function(x, i) {
it(x, function() { hlink(wbs[i]); });
});
});
describe('should parse cells with date type (XLSX/XLSM)', function() {
@ -1077,7 +1109,7 @@ describe('parse features', function() {
['xlsx', paths.dnsxlsx, true],
['xlsb', paths.dnsxlsb, true],
['xls', paths.dnsxls, true],
['xlml', paths.dnsxml, false],
['xlml', paths.dnsxml, false]
].forEach(function(m) { it(m[0], function() {
var wb = X.read(fs.readFileSync(m[1]), {type:TYPE});
var names = wb.Workbook.Names;
@ -1103,9 +1135,9 @@ describe('parse features', function() {
['ods', paths.afods]
].forEach(function(m) { it(m[0], function() {
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) {
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");
}
}); });
@ -1132,15 +1164,16 @@ describe('parse features', function() {
});
describe('page margins', function() {
var wb1, wb2, wb3, wb4, wb5, wbs;
var wbs=[];
var bef = (function() {
if(!fs.existsSync(paths.pmxls)) return wbs=[];
wb1 = X.read(fs.readFileSync(paths.pmxls), {type:TYPE});
wb2 = X.read(fs.readFileSync(paths.pmxls5), {type:TYPE});
wb3 = X.read(fs.readFileSync(paths.pmxml), {type:TYPE});
wb4 = X.read(fs.readFileSync(paths.pmxlsx), {type:TYPE});
wb5 = X.read(fs.readFileSync(paths.pmxlsb), {type:TYPE});
wbs = [wb1, wb2, wb3, wb4, wb5];
if(!fs.existsSync(paths.pmxls)) return;
wbs = [
X.read(fs.readFileSync(paths.pmxls), {type:TYPE}),
X.read(fs.readFileSync(paths.pmxls5), {type:TYPE}),
X.read(fs.readFileSync(paths.pmxml), {type:TYPE}),
X.read(fs.readFileSync(paths.pmxlsx), {type:TYPE}),
X.read(fs.readFileSync(paths.pmxlsb), {type:TYPE})
];
});
if(typeof before != 'undefined') 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]);
});
});
it('should parse wide margins ', function() {
it('should parse wide margins', function() {
wbs.forEach(function(wb) {
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) {
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) {
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]);
@ -1255,7 +1288,7 @@ describe('write features', function() {
baseprops = {
Category: "Newspaper",
ContentStatus: "Published",
Keywords: "print",
Keywords: "",
LastAuthor: "Perry White",
LastPrinted: "1978-12-15",
RevNumber: 6969,
@ -1271,7 +1304,7 @@ describe('write features', function() {
if(typeof before != 'undefined') before(bef);
else it('before', bef);
['xlml', 'xlsx', 'xlsb'].forEach(function(w) { it(w, function() {
wb = {
var wb = {
Props: {},
SheetNames: ["Sheet1"],
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);
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() {
it('should pass -> XLSX', function() {
X.write(X.read(fs.readFileSync(paths.fstxlsb), {type:TYPE}), {type:TYPE});
X.write(X.read(fs.readFileSync(paths.fstxlsx), {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});
["fstxlsb", "fstxlsx", "fstxls", "fstxml"].forEach(function(n) {
X.write(X.read(fs.readFileSync(paths[n]), {type:TYPE}), {type:TYPE});
});
});
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]];
@ -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 _ws = X.utils.aoa_to_sheet(_data);
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
var json2 = X.utils.sheet_to_json(_ws, {header:1});
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
var json4 = X.utils.sheet_to_json(_ws, {blankrows:true, header:1});
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
var json6 = X.utils.sheet_to_json(_ws, {blankrows:false, header:1});
assert.equal(json6.length, 3); // = 4 sheet rows - 1 blank row
});
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 = [
["A1", 'n', -0.08, "-0.08"],
["B1", 'n', 4001, "4,001"],
["C1", 's', "あ 1", "あ 1"],
["A2", 'n', 41.08, "$41.08"],
["B2", 'n', 0.11, "11%"],
["B3", 'b', true, "TRUE"],
["C3", 'b', false, "FALSE"],
["A3"]];
function plaintext_test(wb, raw, sn) {
var sheet = wb.Sheets[sn || wb.SheetNames[0]];
["C3", 'b', true, "TRUE"],
["D3", 'b', false, "FALSE"],
["B3", 's', " ", " "],
["A3"]
];
function plaintext_test(wb, raw, t) {
var sheet = wb.Sheets[wb.SheetNames[0]];
plaintext_val.forEach(function(x) {
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; }
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>",
"<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></td><td>TRUE</td><td>FALSE</td></tr>",
"<tr><td></td><td> \n&nbsp;</td><td>TRUE</td><td>FALSE</td></tr>",
"</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] + '',
'$41.08,11%',
',TRUE,FALSE'
', ,TRUE,FALSE'
].join("\n"); }
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() {
@ -1779,7 +1815,7 @@ describe('csv', function() {
var cell = get_cell(X.read(b, opts).Sheets.Sheet1, "C3");
assert.equal(cell.w, '2/19/14');
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');
});
it('should honor dateNF override', function() {
@ -1788,7 +1824,7 @@ describe('csv', function() {
/* NOTE: IE interprets 2-digit years as 19xx */
assert(cell.w == '2014-02-19' || cell.w == '1914-02-19');
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');
});
it('should interpret dateNF', function() {
@ -1802,8 +1838,8 @@ describe('csv', function() {
assert.equal(cell.v.getMonth(), 2);
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 generate strings if raw option is passed', function() { plaintext_test(X.read(csv_bstr, {type:"binary", raw:true}), true); });
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, false); });
it('should handle formulae', function() {
var bb = '=,=1+1,="100"';
var sheet = X.read(bb, {type:"binary"}).Sheets.Sheet1;
@ -1903,12 +1939,13 @@ function get_dom_element(html) {
describe('HTML', function() {
describe('input string', function(){
it('should interpret values by default', function() { plaintext_test(X.read(html_bstr, {type:"binary"}), false); });
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(html_bstr, {type:"binary", raw:true}), true); });
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, false); });
it('should handle "string" type', function() { plaintext_test(X.read(html_str, {type:"string"}), false, false); });
});
(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 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 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, true); });
});
});
@ -1933,25 +1970,14 @@ describe('js -> file -> js', function() {
ofmt.forEach(function(f) {
it(f, function() {
var newwb = X.read(X.write(wb, {type:BIN, bookType: f}), {type:BIN});
/* int */
eqcell(wb, newwb, 'Sheet1', 'A1');
eqcell(wb, newwb, 'Sheet1', 'B1');
eqcell(wb, newwb, 'Sheet1', 'C1');
/* double */
eqcell(wb, newwb, 'Sheet1', 'B4');
/* 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');
var cb = function(cell) { eqcell(wb, newwb, 'Sheet1', cell); };
['A1', 'B1', 'C1'].forEach(cb); /* int */
['B4'].forEach(cb); /* double */
['A2', 'B2'].forEach(cb); /* bool */
['D2', 'A3', 'B3', 'A4', 'C4'].forEach(cb); /* string */
if(!DIF_XL) cb('C3'); /* date */
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');
/* date */
if(!DIF_XL) eqcell(wb, newwb, 'Sheet1', 'C3');
});
});
});
@ -1997,12 +2023,13 @@ describe('corner cases', function() {
});
it('SSF oddities', function() {
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) {
for(var j=1;j<d.length;++j) {
if(d[j].length == 2) {
var expected = d[j][1], actual = X.SSF.format(d[0], d[j][0], {});
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() {
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

View File

@ -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.xml
./test_files/AutoFilter.ods

View File

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

View File

@ -6,7 +6,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.11.4';
XLSX.version = '0.11.5';
var current_codepage = 1200;
/*:: declare var cptable:any; */
/*global cptable:true */
@ -1974,7 +1974,7 @@ function getzipfile(zip, file/*:string*/) {
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(!file) return null;
try { return getzipdata(zip, file); } catch(e) { return null; }
@ -2111,6 +2111,31 @@ var utf8read/*:StringConv*/ = function utf8reada(orig) {
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) {
var utf8readb = function utf8readb(data) {
@ -2134,6 +2159,8 @@ if(has_buf) {
// $FlowIgnore
var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
utf8write = function(data) { return new Buffer(data, 'utf8').toString("binary"); };
}
// 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 = {};
return function vt_regex(bt) {
if(vt_cache[bt] !== undefined) return vt_cache[bt];
@ -2214,7 +2245,7 @@ var XLMLNS = ({
'v': 'urn:schemas-microsoft-com:vml',
'html': 'http://www.w3.org/TR/REC-html40'
}/*: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 e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 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;
}
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 av = bs ? -v : v;
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;
}
var __toBuffer, ___toBuffer;
__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 __utf16le, ___utf16le;
__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 __toBuffer = function(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 = 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(""); };
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 = __hexlify;
var __utf8, ___utf8;
__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 __lpstr, ___lpstr;
__lpstr = ___lpstr = function lpstr_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var __lpwstr, ___lpwstr;
__lpwstr = ___lpwstr = function lpwstr_(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
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(""); };
var ___utf8 = __utf8;
var __lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var ___lpstr = __lpstr;
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) : "";};
var ___lpwstr = __lpwstr;
var __lpp4, ___lpp4;
__lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
var __8lpp4, ___8lpp4;
__8lpp4 = ___8lpp4 = function lpp4_8(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(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 = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
var ___8lpp4 = __8lpp4;
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); };
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); };
__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) : "";};
__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);};
__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); };
if(has_buf/*:: && typeof Buffer !== 'undefined'*/) {
__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); };
__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); };
__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) : "";};
__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);};
__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);};
__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);};
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); };
}
/* from js-xls */
if(typeof cptable !== 'undefined') {
__utf16le = function(b,s,e) { return cptable.utils.decode(1200, b.slice(s,e)); };
__utf8 = function(b,s,e) { 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)) : "";};
__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)) : "";};
__lpp4 = function(b,i) { 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)) : "";};
__utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(1200, 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/*: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/*: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/*: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/*: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 __readUInt16LE = function(b, 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 __readUInt32LE = function(b, 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 __readUInt8 = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx]; };
var __readUInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+1]*(1<<8)+b[idx]; };
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/*: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/*: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 = typeof Buffer !== "undefined" ? function(s) { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;
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/*:string*/)/*:Array<number>|Buffer*/ { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;
function ReadShift(size/*:number*/, t/*:?string*/) {
var o="", oI, oR, oo=[], w, vv, i, loc;
function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
var o="", oI/*:: :number = 0*/, oR, oo=[], w, vv, i, loc;
switch(t) {
case 'dbcs':
loc = this.l;
@ -2367,11 +2398,11 @@ function ReadShift(size/*:number*/, t/*:?string*/) {
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 __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 __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 __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 __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;
if(f === 'dbcs') {
/*:: 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;
} return this;
} else if(f === 'utf16le') {
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
var end/*:number*/ = this.l + t;
for(i = 0; i < Math.min(val.length, t); ++i) {
var cc = val.charCodeAt(i);
@ -2408,20 +2440,20 @@ function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/) {
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);
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;
}
function prep_blob(blob, pos/*:number*/) {
function prep_blob(blob, pos/*:number*/)/*:void*/ {
blob.l = pos;
blob.read_shift = ReadShift;
blob.read_shift = /*::(*/ReadShift/*:: :any)*/;
blob.chk = CheckField;
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 writenoop(blob, length/*:number*/) { blob.l += length; }
@ -3709,6 +3741,7 @@ var CORE_PROPS_REGEX/*:Array<RegExp>*/ = (function() {
function parse_core_props(data) {
var p = {};
data = utf8read(data);
for(var i = 0; i < CORE_PROPS.length; ++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) {
var q = {}; if(!p) p = {};
data = utf8read(data);
EXT_PROPS.forEach(function(f) {
switch(f[2]) {
@ -4216,7 +4250,7 @@ function parse_PropertySet(blob, PIDSI) {
case 1252:
case 65000: case -536:
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]);
}
} else {
@ -4258,6 +4292,7 @@ function parse_PropertySet(blob, PIDSI) {
/* [MS-OLEPS] 2.21 PropertySetStream */
function parse_PropertySetStream(file, PIDSI) {
var blob = file.content;
if(!blob) return ({}/*:any*/);
prep_blob(blob, 0);
var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;
@ -4478,7 +4513,7 @@ function parse_XLSCell(blob, length)/*:Cell*/ {
var ixfe = blob.read_shift(2);
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);
o.write_shift(2, R);
o.write_shift(2, C);
@ -5768,7 +5803,7 @@ var SYLK = (function() {
function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/)/*: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 RS = "\r\n";
@ -5852,7 +5887,7 @@ var DIF = (function() {
};
return function sheet_to_dif(ws/*:Worksheet*/, opts/*:?any*/)/*: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);
push_field(o, "TABLE", 0, 1, "sheetjs");
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.length == 0) cell.t = 'z';
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) {
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); }
@ -6013,12 +6049,13 @@ var PRN = (function() {
}
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) {
case 'base64': str = Base64.decode(d); break;
case 'binary': str = d; break;
case 'buffer': str = d.toString('binary'); break;
case 'array': str = cc2str(d); break;
case 'string': str = d; break;
default: throw new Error("Unrecognized type " + opts.type);
}
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*/ {
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);
for(var R = r.s.r; R <= r.e.r; ++R) {
var oo = [];
@ -9349,7 +9386,7 @@ function parse_Rgce(blob, length, opts) {
return ptgs;
}
function stringify_array(f) {
function stringify_array(f)/*:string*/ {
var o = [];
for(var i = 0; i < f.length; ++i) {
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*/ {
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);
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="";
@ -9487,7 +9524,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
case 'PtgFuncVar': /* 2.5.198.63 */
//console.log(f[1]);
/* 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;
var args = argc == 0 ? [] : stack.slice(-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 '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 '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);
C = val[0].c;
@ -13471,7 +13508,10 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
var opts = _opts || {};
make_ssf(SSF);
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;
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);
@ -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;
}
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>';
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 */
function parse_compobj(obj) {
function parse_compobj(obj/*:CFBEntry*/) {
var v = {};
var o = obj.content;
/*:: if(o == null) return; */
/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
var l = 28, m;
@ -15208,25 +15243,31 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
}
/* 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 */
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*/
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*/ {
if(!options) options = {};
fix_read_opts(options);
reset_cp();
var CompObj, Summary, WB/*:?any*/;
var CompObj/*:?CFBEntry*/, Summary, WB/*:?any*/;
if(cfb.FullPaths) {
CompObj = CFB.find(cfb, '!CompObj');
Summary = CFB.find(cfb, '!SummaryInformation');
WB = CFB.find(cfb, '/Workbook');
WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
} else {
switch(options.type) {
case 'base64': cfb = s2a(Base64.decode(cfb)); break;
@ -15237,26 +15278,24 @@ if(cfb.FullPaths) {
prep_blob(cfb, 0);
WB = ({content: cfb}/*:any*/);
}
if(!WB) WB = CFB.find(cfb, '/Book');
var CompObjP, SummaryP, WorkbookP/*:Workbook*/;
var CompObjP, SummaryP, WorkbookP/*:: :Workbook = XLSX.utils.book_new(); */;
var _data/*:?any*/;
if(CompObj) CompObjP = parse_compobj(CompObj);
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);
/* 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 */
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");
}
if(cfb.FullPaths) parse_props(cfb);
var props = {};
for(var y in cfb.Summary) props[y] = cfb.Summary[y];
for(y in cfb.DocSummary) props[y] = cfb.DocSummary[y];
if(cfb.FullPaths) parse_props(/*::((*/cfb/*:: :any):CFBContainer)*/, props, options);
WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
if(options.bookFiles) WorkbookP.cfb = cfb;
/*WorkbookP.CompObjP = CompObjP; // TODO: storage? */
@ -16534,7 +16573,7 @@ var XLSRecordEnum = {
var XLSRE = evert_key(XLSRecordEnum, 'n');
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;
var len = length || (payload||[]).length || 0;
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}});
/* TODO: generate stub cells */
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.e.r < R) range.e.r = R;
if(range.s.c > C) range.s.c = C;
@ -16791,7 +16830,7 @@ var HTML_ = (function() {
if(opts.dense) {
if(!ws[R]) ws[R] = [];
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 === 'FALSE') ws[R][C] = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)};
@ -16801,6 +16840,7 @@ var HTML_ = (function() {
/* TODO: value parsing */
if(!m.length){}
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 === 'FALSE') ws[coord] = {t:'b', v:false};
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 elts = row.children;
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) {
var m = merges[midx];
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.length == 0) o.t = 'z';
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 === 'FALSE') o = {t:'b', v:false};
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);
var content = getzipstr(zip, 'content.xml');
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*/) {
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.DS && n == RELS.DS) return "dialog";
if(RELS.MS && n == RELS.MS) return "macro";
if(!n || !n.length) return "sheet";
return n;
return (n && n.length) ? n : "sheet";
}
function safe_parse_wbrels(wbrels, sheets) {
if(!wbrels) return 0;
@ -17739,10 +17781,10 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
var props = {}, propdata = "";
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(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);
}
}
@ -18051,13 +18093,23 @@ function read_utf16(data/*:RawData*/, o/*:ParseOpts*/)/*:Workbook*/ {
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*/ {
var zip, d = data, n=[0];
var zip, d = data, n=[0], str = false;
var o = opts||{};
_ssfopts = {};
if(o.dateNF) _ssfopts.dateNF = o.dateNF;
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 == "string") { str = true; o.type = "binary"; d = bstrify(data); }
switch((n = firstbyte(d, o))[0]) {
case 0xD0: return read_cfb(CFB.read(d, o), 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 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 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 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);
@ -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(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*/ {
var o = opts||{}; o.type = 'file';
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 z = write_zip(wb, o);
var oopts = {};
@ -18089,31 +18141,51 @@ function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
switch(o.type) {
case "base64": oopts.type = "base64"; break;
case "binary": oopts.type = "string"; break;
case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
case "buffer":
case "file": oopts.type = "nodebuffer"; break;
default: throw new Error("Unrecognized type " + o.type);
}
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 cfb/*:CFBContainer*/ = write_xlscfb(wb, o);
switch(o.type) {
case "base64": case "binary": break;
case "buffer": case "array": o.type = ""; break;
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);
}
return CFB.write(cfb, o);
}
/* TODO: test consistency */
function write_bstr_type(out/*:string*/, opts/*:WriteOpts*/) {
function write_string_type(out/*:string*/, opts/*:WriteOpts*/, bom/*:?string*/)/*:any*/ {
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) {
case "base64": return Base64.encode(out);
case "binary": return out;
case "string": return out; /* override in sheet_to_txt */
case "file": return _fs.writeFileSync(opts.file, out, 'binary');
case "buffer": {
if(has_buf) return new Buffer(out, 'binary');
@ -18124,27 +18196,14 @@ function write_bstr_type(out/*:string*/, opts/*:WriteOpts*/) {
}
/* TODO: test consistency */
function write_string_type(out/*:string*/, opts/*:WriteOpts*/) {
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*/) {
function write_binary_type(out, opts/*:WriteOpts*/)/*:any*/ {
switch(opts.type) {
case "string":
case "base64":
case "binary":
var bstr = "";
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 "buffer": return out;
default: throw new Error("Unrecognized type " + opts.type);
@ -18160,14 +18219,14 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
case 'slk':
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 'txt': return write_bstr_type(write_txt_str(wb, o), o);
case 'csv': return write_string_type(write_csv_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, "\ufeff");
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 'rtf': return write_string_type(write_rtf_str(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 'biff3': if(!o.biff) o.biff = 3; 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; /* falls through */
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 'biff8':
@ -18348,8 +18407,8 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ {
function sheet_to_txt(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n";
var s = sheet_to_csv(sheet, opts);
if(typeof cptable == 'undefined') return s;
var o = cptable.utils.encode(1200, s);
if(typeof cptable == 'undefined' || opts.type == 'string') return s;
var o = cptable.utils.encode(1200, s, 'str');
return "\xff\xfe" + o;
}

230
xlsx.js
View File

@ -6,7 +6,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.11.4';
XLSX.version = '0.11.5';
var current_codepage = 1200;
/*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -2039,6 +2039,31 @@ var utf8read = function utf8reada(orig) {
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) {
var utf8readb = function utf8readb(data) {
@ -2062,6 +2087,8 @@ if(has_buf) {
// $FlowIgnore
var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
utf8write = function(data) { return new Buffer(data, 'utf8').toString("binary"); };
}
// 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 = {};
return function vt_regex(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;
}
var __toBuffer, ___toBuffer;
__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 __utf16le, ___utf16le;
__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 __toBuffer = function(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 = function(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 = __hexlify;
var __utf8, ___utf8;
__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 __lpstr, ___lpstr;
__lpstr = ___lpstr = function lpstr_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var __lpwstr, ___lpwstr;
__lpwstr = ___lpwstr = function lpwstr_(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
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(""); };
var ___utf8 = __utf8;
var __lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var ___lpstr = __lpstr;
var __lpwstr = function(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;
__lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
var __8lpp4, ___8lpp4;
__8lpp4 = ___8lpp4 = function lpp4_8(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
var __8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
var ___8lpp4 = __8lpp4;
var __double, ___double;
__double = ___double = function(b, idx) { return read_double_le(b, idx);};
var is_buf = function is_buf_a(a) { return Array.isArray(a); };
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); };
__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);};
__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);};
__utf8 = function utf8_b(b, s,e) { return b.toString('utf8',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) : "";};
__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);};
__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 (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);};
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); };
}
@ -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 __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;
function ReadShift(size, t) {
@ -2295,9 +2326,9 @@ function ReadShift(size, t) {
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 __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) {
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;
} return this;
} else if(f === 'utf16le') {
var end = this.l + t;
var end = this.l + t;
for(i = 0; i < Math.min(val.length, t); ++i) {
var cc = val.charCodeAt(i);
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) {
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;
}
@ -3628,6 +3659,7 @@ var CORE_PROPS_REGEX = (function() {
function parse_core_props(data) {
var p = {};
data = utf8read(data);
for(var i = 0; i < CORE_PROPS.length; ++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) {
var q = {}; if(!p) p = {};
data = utf8read(data);
EXT_PROPS.forEach(function(f) {
switch(f[2]) {
@ -4133,7 +4166,7 @@ function parse_PropertySet(blob, PIDSI) {
case 1252:
case 65000: case -536:
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]);
}
} else {
@ -4175,6 +4208,7 @@ function parse_PropertySet(blob, PIDSI) {
/* [MS-OLEPS] 2.21 PropertySetStream */
function parse_PropertySetStream(file, PIDSI) {
var blob = file.content;
if(!blob) return ({});
prep_blob(blob, 0);
var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;
@ -5685,7 +5719,7 @@ var SYLK = (function() {
function sheet_to_sylk(ws, opts) {
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 RS = "\r\n";
@ -5769,7 +5803,7 @@ var DIF = (function() {
};
return function sheet_to_dif(ws, opts) {
var o = [];
var r = decode_range(ws['!ref']), cell;
var r = safe_decode_range(ws['!ref']), cell;
var dense = Array.isArray(ws);
push_field(o, "TABLE", 0, 1, "sheetjs");
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.length == 0) cell.t = 'z';
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) {
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); }
@ -5930,12 +5965,13 @@ var PRN = (function() {
}
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) {
case 'base64': str = Base64.decode(d); break;
case 'binary': str = d; break;
case 'buffer': str = d.toString('binary'); break;
case 'array': str = cc2str(d); break;
case 'string': str = d; break;
default: throw new Error("Unrecognized type " + opts.type);
}
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) {
var o = [];
var r = decode_range(ws['!ref']), cell;
var r = safe_decode_range(ws['!ref']), cell;
var dense = Array.isArray(ws);
for(var R = r.s.r; R <= r.e.r; ++R) {
var oo = [];
@ -9400,7 +9436,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell, supbooks, opts) {
case 'PtgFuncVar': /* 2.5.198.63 */
//console.log(f[1]);
/* 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;
var args = argc == 0 ? [] : stack.slice(-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 '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 '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);
C = val[0].c;
@ -13380,7 +13416,10 @@ function parse_xlml_xml(d, _opts) {
var opts = _opts || {};
make_ssf(SSF);
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;
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);
@ -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;
}
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>';
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) {
var v = {};
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;
m = __lpstr(o, l);
l += 4 + __readUInt32LE(o,l);
@ -15113,14 +15145,20 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
}
/* TODO: WTF */
function parse_props(cfb) {
function parse_props(cfb, props, o) {
/* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
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*/
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) {
@ -15131,7 +15169,7 @@ var CompObj, Summary, WB;
if(cfb.FullPaths) {
CompObj = CFB.find(cfb, '!CompObj');
Summary = CFB.find(cfb, '!SummaryInformation');
WB = CFB.find(cfb, '/Workbook');
WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
} else {
switch(options.type) {
case 'base64': cfb = s2a(Base64.decode(cfb)); break;
@ -15142,26 +15180,24 @@ if(cfb.FullPaths) {
prep_blob(cfb, 0);
WB = ({content: cfb});
}
if(!WB) WB = CFB.find(cfb, '/Book');
var CompObjP, SummaryP, WorkbookP;
var _data;
if(CompObj) CompObjP = parse_compobj(CompObj);
if(options.bookProps && !options.bookSheets) WorkbookP = ({});
else {
var T = has_buf ? 'buffer' : 'array';
if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options);
/* 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 */
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");
}
if(cfb.FullPaths) parse_props(cfb);
var props = {};
for(var y in cfb.Summary) props[y] = cfb.Summary[y];
for(y in cfb.DocSummary) props[y] = cfb.DocSummary[y];
if(cfb.FullPaths) parse_props(cfb, props, options);
WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
if(options.bookFiles) WorkbookP.cfb = cfb;
/*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}});
/* TODO: generate stub cells */
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.e.r < R) range.e.r = R;
if(range.s.c > C) range.s.c = C;
@ -16696,7 +16732,7 @@ var HTML_ = (function() {
if(opts.dense) {
if(!ws[R]) ws[R] = [];
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 === 'FALSE') ws[R][C] = {t:'b', v:false};
else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)};
@ -16706,6 +16742,7 @@ var HTML_ = (function() {
/* TODO: value parsing */
if(!m.length){}
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 === 'FALSE') ws[coord] = {t:'b', v:false};
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 elts = row.children;
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) {
var m = merges[midx];
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.length == 0) o.t = 'z';
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 === 'FALSE') o = {t:'b', v:false};
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);
var content = getzipstr(zip, 'content.xml');
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) {
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.DS && n == RELS.DS) return "dialog";
if(RELS.MS && n == RELS.MS) return "macro";
if(!n || !n.length) return "sheet";
return n;
return (n && n.length) ? n : "sheet";
}
function safe_parse_wbrels(wbrels, sheets) {
if(!wbrels) return 0;
@ -17643,10 +17682,10 @@ function parse_zip(zip, opts) {
var props = {}, propdata = "";
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(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);
}
}
@ -17952,13 +17991,23 @@ function read_utf16(data, 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) {
var zip, d = data, n=[0];
var zip, d = data, n=[0], str = false;
var o = opts||{};
_ssfopts = {};
if(o.dateNF) _ssfopts.dateNF = o.dateNF;
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 == "string") { str = true; o.type = "binary"; d = bstrify(data); }
switch((n = firstbyte(d, o))[0]) {
case 0xD0: return read_cfb(CFB.read(d, o), 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 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 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 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);
@ -17975,7 +18024,7 @@ function readSync(data, opts) {
}
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("|"));
return PRN.to_workbook(d, o);
return read_prn(data, d, o, str);
}
function readFileSync(filename, opts) {
@ -17990,12 +18039,15 @@ function write_zip_type(wb, opts) {
switch(o.type) {
case "base64": oopts.type = "base64"; break;
case "binary": oopts.type = "string"; break;
case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
case "buffer":
case "file": oopts.type = "nodebuffer"; break;
default: throw new Error("Unrecognized type " + o.type);
}
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) {
@ -18005,16 +18057,33 @@ function write_cfb_type(wb, opts) {
case "base64": case "binary": break;
case "buffer": case "array": o.type = ""; break;
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);
}
return CFB.write(cfb, o);
}
/* TODO: test consistency */
function write_bstr_type(out, opts) {
function write_string_type(out, opts, bom) {
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) {
case "base64": return Base64.encode(out);
case "binary": return out;
case "string": return out; /* override in sheet_to_txt */
case "file": return _fs.writeFileSync(opts.file, out, 'binary');
case "buffer": {
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);
}
/* 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 */
function write_binary_type(out, opts) {
switch(opts.type) {
case "string":
case "base64":
case "binary":
var bstr = "";
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 "buffer": return out;
default: throw new Error("Unrecognized type " + opts.type);
@ -18061,14 +18117,14 @@ function writeSync(wb, opts) {
case 'slk':
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 'txt': return write_bstr_type(write_txt_str(wb, o), o);
case 'csv': return write_string_type(write_csv_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, "\ufeff");
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 'rtf': return write_string_type(write_rtf_str(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 'biff3': if(!o.biff) o.biff = 3; 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; /* falls through */
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 'biff8':
@ -18249,8 +18305,8 @@ function sheet_to_csv(sheet, opts) {
function sheet_to_txt(sheet, opts) {
if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n";
var s = sheet_to_csv(sheet, opts);
if(typeof cptable == 'undefined') return s;
var o = cptable.utils.encode(1200, s);
if(typeof cptable == 'undefined' || opts.type == 'string') return s;
var o = cptable.utils.encode(1200, s, 'str');
return "\xff\xfe" + o;
}

View File

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

View File

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