version bump 0.11.6: ancillary format update

- BIFF5 XLS write (bookType "biff5")
- DBF Level 7 read
- ODS whitespace and repeated rows
- flow and lint cleanup
This commit is contained in:
SheetJS 2017-10-16 20:14:32 -04:00
parent ef9f3f9ca5
commit f968dfe4ed
63 changed files with 2867 additions and 2261 deletions

@ -2,7 +2,6 @@
.*/node_modules/.*
.*/dist/.*
.*/tmp/.*
.*/test.js
.*/bits/.*
.*/ctest/.*
@ -25,6 +24,7 @@ xlsxworker.flow.js
xlsx.flow.js
.*/bin/.*.njs
.*/demo/browser.flow.js
test.js
[libs]
bits/09_types.js

1
.gitignore vendored

@ -27,3 +27,4 @@ tmp
*.html
*.sheetjs
*.exe
*.img

@ -29,6 +29,7 @@ tmp
*.html
*.sheetjs
*.exe
*.img
.gitignore
.fossaignore
.spelling

@ -70,6 +70,8 @@ filesystem
javascript
metadata
natively
pre-built
pre-generated
prepend
prepended
repo

@ -4,6 +4,10 @@ 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.6 (2017-10-16)
* Semicolon-delimited files are detected
## 0.11.5 (2017-09-30)
* Bower main script shifted to full version

@ -213,7 +213,7 @@ book: readme graph ## Update summary for documentation
<README.md grep -vE "(details|summary)>" > misc/docs/README.md
DEMOMDS=$(sort $(wildcard demos/*/README.md))
MDLINT=$(DEMODS) $(READEPS) demos/README.md
MDLINT=$(DEMOMDS) $(READEPS) demos/README.md
.PHONY: mdlint
mdlint: $(MDLINT) ## Check markdown documents
alex $^

@ -1565,8 +1565,9 @@ Plain text format guessing follows the priority order:
| XML | starts with `<` |
| RTF | starts with `{\rt` |
| DSV | starts with `/sep=.$/`, separator is the specified character |
| CSV | more unquoted `","` characters than `"\t"` chars in the first 1024 |
| TSV | one of the first 1024 characters is a tab char `"\t"` |
| DSV | more unquoted `";"` chars than `"\t"` or `","` in the first 1024 |
| TSV | more unquoted `"\t"` chars than `","` chars in the first 1024 |
| CSV | one of the first 1024 characters is a comma `","` |
| PRN | (default) |
- HTML tags include: `html`, `table`, `head`, `meta`, `script`, `style`, `div`
@ -1629,6 +1630,7 @@ output formats. The specific file type is controlled with `bookType` option:
| `xlsm` | `.xlsm` | ZIP | multi | Excel 2007+ Macro XML Format |
| `xlsb` | `.xlsb` | ZIP | multi | Excel 2007+ Binary Format |
| `biff8` | `.xls` | CFB | multi | Excel 97-2004 Workbook Format |
| `biff5` | `.xls` | CFB | multi | Excel 5.0/95 Workbook Format |
| `biff2` | `.xls` | none | single | Excel 2.0 Worksheet Format |
| `xlml` | `.xls` | none | multi | Excel 2003-2004 (SpreadsheetML) |
| `ods` | `.ods` | ZIP | multi | OpenDocument Spreadsheet |
@ -1638,7 +1640,7 @@ output formats. The specific file type is controlled with `bookType` option:
| `sylk` | `.sylk` | none | single | Symbolic Link (SYLK) |
| `html` | `.html` | none | single | HTML Document |
| `dif` | `.dif` | none | single | Data Interchange Format (DIF) |
| `rtf` | `.rtf` | none | single | Rich Text Format |
| `rtf` | `.rtf` | none | single | Rich Text Format (RTF) |
| `prn` | `.prn` | none | single | Lotus Formatted Text |
- `compression` only applies to formats with ZIP containers.
@ -1957,7 +1959,7 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
| Excel 2007+ Binary Format (XLSB BIFF12) | :o: | :o: |
| Excel 2003-2004 XML Format (XML "SpreadsheetML") | :o: | :o: |
| Excel 97-2004 (XLS BIFF8) | :o: | :o: |
| Excel 5.0/95 (XLS BIFF5) | :o: | |
| Excel 5.0/95 (XLS BIFF5) | :o: | :o: |
| Excel 4.0 (XLS/XLW BIFF4) | :o: | |
| Excel 3.0 (XLS BIFF3) | :o: | |
| Excel 2.0/2.1 (XLS BIFF2) | :o: | :o: |
@ -1976,7 +1978,7 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
| Quattro Pro Spreadsheet (WQ1/WQ2/WB1/WB2/WB3/QPW) | :o: | |
| **Other Common Spreadsheet Output Formats** |:-----:|:-----:|
| HTML Tables | :o: | :o: |
| RTF Tables | | :o: |
| Rich Text Format tables (RTF) | | :o: |
### Excel 2007+ XML (XLSX/XLSM)

@ -21,7 +21,7 @@ program
.option('-X, --xlsx', 'emit XLSX to <sheetname> or <file>.xlsx')
.option('-Y, --ods', 'emit ODS to <sheetname> or <file>.ods')
.option('-8, --xls', 'emit XLS to <sheetname> or <file>.xls (BIFF8)')
//.option('-5, --biff5','emit XLS to <sheetname> or <file>.xls (BIFF5)')
.option('-5, --biff5','emit XLS to <sheetname> or <file>.xls (BIFF5)')
//.option('-4, --biff4','emit XLS to <sheetname> or <file>.xls (BIFF4)')
//.option('-3, --biff3','emit XLS to <sheetname> or <file>.xls (BIFF3)')
.option('-2, --biff2','emit XLS to <sheetname> or <file>.xls (BIFF2)')
@ -44,11 +44,10 @@ program
.option('-n, --sheet-rows <num>', 'Number of rows to process (0=all rows)')
.option('--sst', 'generate shared string table for XLS* formats')
.option('--compress', 'use compression when writing XLSX/M/B and ODS')
.option('--read-only', 'do not generate output')
.option('--read', 'read but do not generate output')
.option('--all', 'parse everything; write as much as possible')
.option('--dev', 'development mode')
.option('--sparse', 'sparse mode')
.option('--read', 'read but do not print out contents')
.option('-q, --quiet', 'quiet mode');
program.on('--help', function() {
@ -176,9 +175,8 @@ try {
process.exit(4);
}
if(program.readOnly) process.exit(0);
/* single worksheet formats */
/* single worksheet file formats */
[
['biff2', '.xls'],
['biff3', '.xls'],

@ -1,7 +1,5 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*jshint -W041 */
/*jshint funcscope:true, eqnull:true, loopfunc:true */
/*exported XLSX */
/*global global, exports, module, require:false, process:false, Buffer:false */
var XLSX = {};

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

@ -28,14 +28,14 @@ var debom = function(data/*:string*/)/*:string*/ {
return data;
};
var _getchar = function _gc1(x) { return String.fromCharCode(x); };
var _getchar = function _gc1(x/*:number*/)/*:string*/ { return String.fromCharCode(x); };
if(typeof cptable !== 'undefined') {
set_cp = function(cp) { current_codepage = cp; };
debom = function(data) {
set_cp = function(cp/*:number*/) { current_codepage = cp; };
debom = function(data/*:string*/) {
if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.substr(2))); }
return data;
};
_getchar = function _gc2(x) {
_getchar = function _gc2(x/*:number*/)/*:string*/ {
if(current_codepage === 1200) return String.fromCharCode(x);
return cptable.utils.decode(current_codepage, [x&255,x>>8])[0];
};

@ -102,7 +102,7 @@ var utf8read/*:StringConv*/ = function utf8reada(orig) {
};
var utf8write/*:StringConv*/ = function(orig) {
var out = [], i = 0, c = 0, d = 0;
var out/*:Array<string>*/ = [], i = 0, c = 0, d = 0;
while(i < orig.length) {
c = orig.charCodeAt(i++);
switch(true) {
@ -197,7 +197,7 @@ function writextag(f,g,h) { return '<' + f + (isval(h) /*:: && h */? wxt_helper(
function write_w3cdtf(d/*:Date*/, t/*:?boolean*/)/*:string*/ { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } return ""; }
function write_vt(s) {
function write_vt(s)/*:string*/ {
switch(typeof s) {
case 'string': return writextag('vt:lpwstr', s);
case 'number': return writextag((s|0)==s?'vt:i4':'vt:r8', String(s));

@ -74,6 +74,7 @@ var __readUInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/
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 __readInt32BE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx]<<24)|(b[idx+1]<<16)|(b[idx+2]<<8)|b[idx+3]; };
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;
@ -141,10 +142,15 @@ function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
switch(size) {
case 1: oI = __readUInt8(this, this.l); this.l++; return oI;
case 2: oI = (t === 'i' ? __readInt16LE : __readUInt16LE)(this, this.l); this.l += 2; return oI;
case 4:
if(t === 'i' || (this[this.l+3] & 0x80)===0) { oI = __readInt32LE(this, this.l); this.l += 4; return oI; }
case 4: case -4:
if(t === 'i' || (this[this.l+3] & 0x80)===0) { oI = (size > 0 ? __readInt32LE : __readInt32BE)(this, this.l); this.l += 4; return oI; }
else { oR = __readUInt32LE(this, this.l); this.l += 4; } return oR;
case 8: if(t === 'f') { oR = __double(this, this.l); this.l += 8; return oR; }
case 8: case -8:
if(t === 'f') {
if(size == 8) oR = __double(this, this.l);
else oR = __double([this[this.l+7],this[this.l+6],this[this.l+5],this[this.l+4],this[this.l+3],this[this.l+2],this[this.l+1],this[this.l+0]], 0);
this.l += 8; return oR;
} else size = 8;
/* falls through */
case 16: o = __hexlify(this, this.l, size); break;
}}
@ -162,6 +168,9 @@ function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/)/*:any*/
for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i);
size = 2 * val.length;
} else if(f === 'sbcs') {
/* TODO: codepage */
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
val = val.replace(/[^\x00-\x7F]/g, "_");
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
for(i = 0; i != val.length; ++i) this[this.l + i] = val.charCodeAt(i) & 0xFF;
size = val.length;

@ -1,45 +1,43 @@
/* [MS-OLEPS] 2.2 PropertyType */
{
//var VT_EMPTY = 0x0000;
//var VT_NULL = 0x0001;
var VT_I2 = 0x0002;
var VT_I4 = 0x0003;
//var VT_R4 = 0x0004;
//var VT_R8 = 0x0005;
//var VT_CY = 0x0006;
//var VT_DATE = 0x0007;
//var VT_BSTR = 0x0008;
//var VT_ERROR = 0x000A;
var VT_BOOL = 0x000B;
var VT_VARIANT = 0x000C;
//var VT_DECIMAL = 0x000E;
//var VT_I1 = 0x0010;
//var VT_UI1 = 0x0011;
//var VT_UI2 = 0x0012;
var VT_UI4 = 0x0013;
//var VT_I8 = 0x0014;
var VT_UI8 = 0x0015;
//var VT_INT = 0x0016;
//var VT_UINT = 0x0017;
var VT_LPSTR = 0x001E;
//var VT_LPWSTR = 0x001F;
var VT_FILETIME = 0x0040;
//var VT_BLOB = 0x0041;
//var VT_STREAM = 0x0042;
//var VT_STORAGE = 0x0043;
//var VT_STREAMED_Object = 0x0044;
//var VT_STORED_Object = 0x0045;
//var VT_BLOB_Object = 0x0046;
var VT_CF = 0x0047;
//var VT_CLSID = 0x0048;
//var VT_VERSIONED_STREAM = 0x0049;
var VT_VECTOR = 0x1000;
//var VT_ARRAY = 0x2000;
//var VT_EMPTY = 0x0000;
//var VT_NULL = 0x0001;
var VT_I2 = 0x0002;
var VT_I4 = 0x0003;
//var VT_R4 = 0x0004;
//var VT_R8 = 0x0005;
//var VT_CY = 0x0006;
//var VT_DATE = 0x0007;
//var VT_BSTR = 0x0008;
//var VT_ERROR = 0x000A;
var VT_BOOL = 0x000B;
var VT_VARIANT = 0x000C;
//var VT_DECIMAL = 0x000E;
//var VT_I1 = 0x0010;
//var VT_UI1 = 0x0011;
//var VT_UI2 = 0x0012;
var VT_UI4 = 0x0013;
//var VT_I8 = 0x0014;
var VT_UI8 = 0x0015;
//var VT_INT = 0x0016;
//var VT_UINT = 0x0017;
var VT_LPSTR = 0x001E;
//var VT_LPWSTR = 0x001F;
var VT_FILETIME = 0x0040;
//var VT_BLOB = 0x0041;
//var VT_STREAM = 0x0042;
//var VT_STORAGE = 0x0043;
//var VT_STREAMED_Object = 0x0044;
//var VT_STORED_Object = 0x0045;
//var VT_BLOB_Object = 0x0046;
var VT_CF = 0x0047;
//var VT_CLSID = 0x0048;
//var VT_VERSIONED_STREAM = 0x0049;
var VT_VECTOR = 0x1000;
//var VT_ARRAY = 0x2000;
var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString
var VT_CUSTOM = [VT_STRING, VT_USTR];
}
var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString
var VT_CUSTOM = [VT_STRING, VT_USTR];
/* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */
var DocSummaryPIDDSI = {

@ -56,9 +56,9 @@ function write_rdf(rdf, opts) {
return o.join("");
}
/* TODO: pull properties */
var write_meta_ods/*:{(wb:any, opts:any):string}*/ = (function() {
var write_meta_ods/*:{(wb:Workbook, opts:any):string}*/ = (function() {
var payload = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
return function wmo(wb, opts) {
return function wmo(wb/*:Workbook*/, opts) {
return payload;
};
})();

@ -108,7 +108,7 @@ function parse_VtVector(blob, cb) {
}
/* [MS-OLEPS] 2.15 TypedPropertyValue */
function parse_TypedPropertyValue(blob, type/*:number*/, _opts) {
function parse_TypedPropertyValue(blob, type/*:number*/, _opts)/*:any*/ {
var t = blob.read_shift(2), ret, opts = _opts||{};
blob.l += 2;
if(type !== VT_VARIANT)
@ -193,12 +193,12 @@ function parse_PropertySet(blob, PIDSI) {
case 1252:
case 65000: case -536:
case 65001: case -535:
set_cp(CodePage = PropH[piddsi.n]>>>0 & 0xFFFF); break;
set_cp(CodePage = (PropH[piddsi.n]>>>0) & 0xFFFF); break;
default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
}
} else {
if(Props[i][0] === 0x1) {
CodePage = PropH.CodePage = parse_TypedPropertyValue(blob, VT_I2);
CodePage = PropH.CodePage = (parse_TypedPropertyValue(blob, VT_I2)/*:number*/);
set_cp(CodePage);
if(Dictionary !== -1) {
var oldpos = blob.l;

@ -201,7 +201,8 @@ function parse_WriteAccess(blob, length, opts) {
return UserName;
}
function write_WriteAccess(s/*:string*/, opts) {
var o = new_buf(112);
var b8 = !opts || opts.biff == 8;
var o = new_buf(b8 ? 112 : 54);
o.write_shift(opts.biff == 8 ? 2 : 1, 7);
o.write_shift(1, 0);
o.write_shift(4, 0x33336853);
@ -226,14 +227,15 @@ function parse_BoundSheet8(blob, length, opts) {
return { pos:pos, hs:hidden, dt:dt, name:name };
}
function write_BoundSheet8(data, opts) {
var o = new_buf(8 + 2 * data.name.length);
var w = (!opts || opts.biff >= 8 ? 2 : 1);
var o = new_buf(8 + w * data.name.length);
o.write_shift(4, data.pos);
o.write_shift(1, data.hs || 0);
o.write_shift(1, data.dt);
o.write_shift(1, data.name.length);
o.write_shift(1, 1);
o.write_shift(2 * data.name.length, data.name, 'utf16le');
return o;
if(opts.biff >= 8) o.write_shift(1, 1);
o.write_shift(w * data.name.length, data.name, opts.biff < 8 ? 'sbcs' : 'utf16le');
return o.slice(0, o.l);
}
/* 2.4.265 TODO */
@ -362,11 +364,12 @@ function parse_Label(blob, length, opts) {
return cell;
}
function write_Label(R/*:number*/, C/*:number*/, v/*:string*/, opts) {
var o = new_buf(6 + 3 + 2 * v.length);
var b8 = !opts || opts.biff == 8;
var o = new_buf(6 + 2 + (+b8) + (1 + b8) * v.length);
write_XLSCell(R, C, 0, o);
o.write_shift(2, v.length);
o.write_shift(1, 1);
o.write_shift(2 * v.length, v, 'utf16le');
if(b8) o.write_shift(1, 1);
o.write_shift((1 + b8) * v.length, v, b8 ? 'utf16le' : 'sbcs');
return o;
}
@ -389,9 +392,10 @@ function parse_Dimensions(blob, length, opts) {
return {s: {r:r, c:c}, e: {r:R, c:C}};
}
function write_Dimensions(range, opts) {
var o = new_buf(14);
o.write_shift(4, range.s.r);
o.write_shift(4, range.e.r + 1);
var w = opts.biff == 8 || !opts.biff ? 4 : 2;
var o = new_buf(2*w + 6);
o.write_shift(w, range.s.r);
o.write_shift(w, range.e.r + 1);
o.write_shift(2, range.s.c);
o.write_shift(2, range.e.c + 1);
o.write_shift(2, 0);
@ -598,7 +602,7 @@ function parse_Lbl(blob, length, opts) {
var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
if(flags & 0x20) name = XLSLblBuiltIn[name.charCodeAt(0)];
var npflen = target - blob.l; if(opts && opts.biff == 2) --npflen;
var rgce = target == blob.l || cce == 0 ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
var rgce = target == blob.l || cce === 0 ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
return {
chKey: chKey,
Name: name,

@ -55,13 +55,14 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
/* header */
var ft = d.read_shift(1);
var memo = false;
var vfp = false;
var vfp = false, l7 = false;
switch(ft) {
case 0x02: case 0x03: break;
case 0x30: vfp = true; memo = true; break;
case 0x31: vfp = true; break;
case 0x83: memo = true; break;
case 0x8B: memo = true; break;
case 0x8C: memo = true; l7 = true; break;
case 0xF5: memo = true; break;
default: throw new Error("DBF Unsupported Version: " + ft.toString(16));
}
@ -84,36 +85,42 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
d.l+=2;
}
if(l7) d.l += 36;
var fields = [], field = {};
var hend = fpos - 10 - (vfp ? 264 : 0);
var hend = fpos - 10 - (vfp ? 264 : 0), ww = l7 ? 32 : 11;
while(ft == 0x02 ? d.l < d.length && d[d.l] != 0x0d: d.l < hend) {
field = {};
field.name = cptable.utils.decode(current_cp, d.slice(d.l, d.l+10)).replace(/[\u0000\r\n].*$/g,"");
d.l += 11;
field.name = cptable.utils.decode(current_cp, d.slice(d.l, d.l+ww)).replace(/[\u0000\r\n].*$/g,"");
d.l += ww;
field.type = String.fromCharCode(d.read_shift(1));
if(ft != 0x02) field.offset = d.read_shift(4);
if(ft != 0x02 && !l7) field.offset = d.read_shift(4);
field.len = d.read_shift(1);
if(ft == 0x02) field.offset = d.read_shift(2);
field.dec = d.read_shift(1);
if(field.name.length) fields.push(field);
if(ft != 0x02) d.l += 14;
if(ft != 0x02) d.l += l7 ? 13 : 14;
switch(field.type) {
// case 'B': break; // Binary
case 'C': break; // character
case 'D': break; // date
case 'F': break; // floating point
// case 'G': break; // General
case 'I': break; // long
case 'L': break; // boolean
case 'M': break; // memo
case 'N': break; // number
// case 'O': break; // double
// case 'P': break; // Picture
case 'T': break; // datetime
case 'Y': break; // currency
case '0': break; // null ?
case '+': break; // autoincrement
case '@': break; // timestamp
case 'B': // VFP Double
if((!vfp || field.len != 8) && opts.WTF) console.log('Skipping ' + field.name + ':' + field.type);
break;
case 'G': // General
case 'P': // Picture
if(opts.WTF) console.log('Skipping ' + field.name + ':' + field.type);
break;
case 'C': // character
case 'D': // date
case 'F': // floating point
case 'I': // long
case 'L': // boolean
case 'M': // memo
case 'N': // number
case 'O': // double
case 'T': // datetime
case 'Y': // currency
case '0': // VFP _NullFlags
case '@': // timestamp
case '+': // autoincrement
break;
default: throw new Error('Unknown Field Type: ' + field.type);
}
}
@ -145,7 +152,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
else out[R][C] = s;
break;
case 'F': out[R][C] = parseFloat(s.trim()); break;
case 'I': out[R][C] = dd.read_shift(4, 'i'); break;
case '+': case 'I': out[R][C] = l7 ? dd.read_shift(-4, 'i') ^ 0x80000000 : dd.read_shift(4, 'i'); break;
case 'L': switch(s.toUpperCase()) {
case 'Y': case 'T': out[R][C] = true; break;
case 'N': case 'F': out[R][C] = false; break;
@ -154,15 +161,16 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
} break;
case 'M': /* TODO: handle memo files */
if(!memo) throw new Error("DBF Unexpected MEMO for type " + ft.toString(16));
out[R][C] = "##MEMO##" + dd.read_shift(4);
out[R][C] = "##MEMO##" + (l7 ? parseInt(s.trim(), 10): dd.read_shift(4));
break;
case 'N': out[R][C] = +s.replace(/\u0000/g,"").trim(); break;
case 'T':
var day = dd.read_shift(4), ms = dd.read_shift(4);
throw new Error(day + " | " + ms);
//out[R][C] = new Date(); // TODO
//break;
case 'Y': out[R][C] = dd.read(4,'i')/1e4; break;
case '@': out[R][C] = new Date(dd.read_shift(-8, 'f') - 0x388317533400); break;
case 'T': out[R][C] = new Date((dd.read_shift(4) - 0x253D8C) * 0x5265C00 + dd.read_shift(4)); break;
case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4; break;
case 'O': out[R][C] = -dd.read_shift(-8, 'f'); break;
case 'B': if(vfp && fields[C].len == 8) { out[R][C] = dd.read_shift(8,'f'); break; }
/* falls through */
case 'G': case 'P': dd.l += fields[C].len; break;
case '0':
if(fields[C].name === '_NullFlags') break;
/* falls through */
@ -269,7 +277,7 @@ var SYLK = (function() {
cw = record[rj].substr(1).split(" ");
for(j = parseInt(cw[0], 10); j <= parseInt(cw[1], 10); ++j) {
Mval = parseInt(cw[2], 10);
colinfo[j-1] = Mval == 0 ? {hidden:true}: {wch:Mval}; process_col(colinfo[j-1]);
colinfo[j-1] = Mval === 0 ? {hidden:true}: {wch:Mval}; process_col(colinfo[j-1]);
} break;
case 'C': /* default column format */
C = parseInt(record[rj].substr(1))-1;
@ -279,7 +287,7 @@ var SYLK = (function() {
R = parseInt(record[rj].substr(1))-1;
if(!rowinfo[R]) rowinfo[R] = {};
if(Mval > 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); }
else if(Mval == 0) rowinfo[R].hidden = true;
else if(Mval === 0) rowinfo[R].hidden = true;
break;
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
}
@ -514,16 +522,16 @@ var PRN = (function() {
// List of accepted CSV separators
var guess_seps = {
0x2C: ',',
0x09: "\t",
0x3B: ';'
/*::[*/0x2C/*::]*/: ',',
/*::[*/0x09/*::]*/: "\t",
/*::[*/0x3B/*::]*/: ';'
};
// CSV separator weights to be used in case of equal numbers
var guess_sep_weights = {
0x2C: 3,
0x09: 2,
0x3B: 1
/*::[*/0x2C/*::]*/: 3,
/*::[*/0x09/*::]*/: 2,
/*::[*/0x3B/*::]*/: 1
};
function guess_sep(str) {
@ -567,9 +575,9 @@ var PRN = (function() {
var s = str.slice(start, end);
var cell = ({}/*:any*/);
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
if(s.length == 0) cell.t = 'z';
if(s.length === 0) cell.t = 'z';
else if(o.raw) { cell.t = 's'; cell.v = s; }
else if(s.trim().length == 0) { 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); }
@ -642,7 +650,7 @@ var PRN = (function() {
if(!cell || cell.v == null) { oo.push(" "); continue; }
var w = (cell.w || (format_cell(cell), cell.w) || "").substr(0,10);
while(w.length < 10) w += " ";
oo.push(w + (C == 0 ? " " : ""));
oo.push(w + (C === 0 ? " " : ""));
}
o.push(oo.join(""));
}

@ -127,9 +127,9 @@ function parse_EncryptionVerifier(blob, length/*:number*/) {
function parse_EncryptionInfo(blob, length/*:?number*/) {
var vers = parse_CRYPTOVersion(blob);
switch(vers.Minor) {
case 0x02: return parse_EncInfoStd(blob, vers);
case 0x03: return parse_EncInfoExt(blob, vers);
case 0x04: return parse_EncInfoAgl(blob, vers);
case 0x02: return [vers.Minor, parse_EncInfoStd(blob, vers)];
case 0x03: return [vers.Minor, parse_EncInfoExt(blob, vers)];
case 0x04: return [vers.Minor, parse_EncInfoAgl(blob, vers)];
}
throw new Error("ECMA-376 Encrypted file unrecognized Version: " + vers.Minor);
}
@ -147,7 +147,10 @@ function parse_EncInfoStd(blob, vers) {
/* [MS-OFFCRYPTO] 2.3.4.6 EncryptionInfo Stream (Extensible Encryption) */
function parse_EncInfoExt(blob, vers) { throw new Error("File is password-protected: ECMA-376 Extensible"); }
/* [MS-OFFCRYPTO] 2.3.4.10 EncryptionInfo Stream (Agile Encryption) */
function parse_EncInfoAgl(blob, vers) { throw new Error("File is password-protected: ECMA-376 Agile"); }
function parse_EncInfoAgl(blob, vers) {
blob.l+=4;
return blob.read_shift(blob.length - blob.l, 'utf8');
}
@ -282,7 +285,7 @@ function parse_XORObfuscation(blob, length, opts, out) {
var o = ({ key: parseuint16(blob), verificationBytes: parseuint16(blob) }/*:any*/);
if(opts.password) o.verifier = crypto_CreatePasswordVerifier_Method1(opts.password);
out.valid = o.verificationBytes === o.verifier;
if(out.valid) out.insitu_decrypt = crypto_MakeXorDecryptor(opts.password);
if(out.valid) out.insitu = crypto_MakeXorDecryptor(opts.password);
return o;
}

@ -53,6 +53,13 @@ function parse_RgceLoc_BIFF2(blob, length, opts) {
return {r:r[0], c:c, cRel:r[1], rRel:r[2]};
}
/* 2.5.198.107 , 2.5.47 */
function parse_RgceElfLoc(blob, length, opts) {
var r = blob.read_shift(2);
var c = blob.read_shift(2);
return {r:r, c:c & 0xFF, fQuoted:!!(c & 0x4000), cRel:c>>15, rRel:c>>15 };
}
/* [MS-XLS] 2.5.198.111 TODO */
/* [MS-XLSB] 2.5.97.92 TODO */
function parse_RgceLocRel(blob, length, opts) {
@ -446,6 +453,51 @@ var parse_PtgMemNoMem = parsenoop;
/* 2.5.198.92 */
var parse_PtgTbl = parsenoop;
function parse_PtgElfLoc(blob, length, opts) {
blob.l += 2;
return [parse_RgceElfLoc(blob, 4, opts)];
}
function parse_PtgElfNoop(blob, length, opts) {
blob.l += 6;
return [];
}
/* 2.5.198.46 */
var parse_PtgElfCol = parse_PtgElfLoc;
/* 2.5.198.47 */
var parse_PtgElfColS = parse_PtgElfNoop;
/* 2.5.198.48 */
var parse_PtgElfColSV = parse_PtgElfNoop;
/* 2.5.198.49 */
var parse_PtgElfColV = parse_PtgElfLoc;
/* 2.5.198.50 */
function parse_PtgElfLel(blob, length, opts) {
blob.l += 2;
return [parseuint16(blob), blob.read_shift(2) & 0x01];
}
/* 2.5.198.51 */
var parse_PtgElfRadical = parse_PtgElfLoc;
/* 2.5.198.52 */
var parse_PtgElfRadicalLel = parse_PtgElfLel;
/* 2.5.198.53 */
var parse_PtgElfRadicalS = parse_PtgElfNoop;
/* 2.5.198.54 */
var parse_PtgElfRw = parse_PtgElfLoc;
/* 2.5.198.55 */
var parse_PtgElfRwV = parse_PtgElfLoc;
/* [MS-XLSB] 2.5.97.52 */
function parse_PtgList(blob, length, opts) {
blob.l += 2;
var ixti = blob.read_shift(2);
blob.l += 10;
return {};
}
/* 2.5.198.91 */
function parse_PtgSxName(blob, length, opts) {
blob.l += 2;
return [blob.read_shift(4)];
}
/* 2.5.198.25 */
var PtgTypes = {
/*::[*/0x01/*::]*/: { n:'PtgExp', f:parse_PtgExp },
@ -521,8 +573,19 @@ var PtgDupes = {
(function(){for(var y in PtgDupes) PtgTypes[y] = PtgTypes[PtgDupes[y]];})();
var Ptg18 = {
// /*::[*/0x19/*::]*/: { n:'PtgList', f:parse_PtgList }, // TODO
// /*::[*/0x1D/*::]*/: { n:'PtgSxName', f:parse_PtgSxName }, // TODO
/*::[*/0x01/*::]*/: { n:'PtgElfLel', f:parse_PtgElfLel },
/*::[*/0x02/*::]*/: { n:'PtgElfRw', f:parse_PtgElfRw },
/*::[*/0x03/*::]*/: { n:'PtgElfCol', f:parse_PtgElfCol },
/*::[*/0x06/*::]*/: { n:'PtgElfRwV', f:parse_PtgElfRwV },
/*::[*/0x07/*::]*/: { n:'PtgElfColV', f:parse_PtgElfColV },
/*::[*/0x0A/*::]*/: { n:'PtgElfRadical', f:parse_PtgElfRadical },
/*::[*/0x0B/*::]*/: { n:'PtgElfRadicalS', f:parse_PtgElfRadicalS },
/*::[*/0x0D/*::]*/: { n:'PtgElfColS', f:parse_PtgElfColS },
/*::[*/0x0F/*::]*/: { n:'PtgElfColSV', f:parse_PtgElfColSV },
/*::[*/0x10/*::]*/: { n:'PtgElfRadicalLel', f:parse_PtgElfRadicalLel },
/*::[*/0x19/*::]*/: { n:'PtgList', f:parse_PtgList },
/*::[*/0x1D/*::]*/: { n:'PtgSxName', f:parse_PtgSxName },
/*::[*/0xFF/*::]*/: {}
};
var Ptg19 = {
/*::[*/0x01/*::]*/: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
@ -536,36 +599,7 @@ var Ptg19 = {
/*::[*/0x80/*::]*/: { n:'PtgAttrIfError', f:parse_PtgAttrIfError },
/*::[*/0xFF/*::]*/: {}
};
/* 2.4.127 TODO */
function parse_Formula(blob, length, opts) {
var end = blob.l + length;
var cell = parse_XLSCell(blob, 6);
if(opts.biff == 2) ++blob.l;
var val = parse_FormulaValue(blob,8);
var flags = blob.read_shift(1);
if(opts.biff != 2) {
blob.read_shift(1);
if(opts.biff >= 5) {
var chn = blob.read_shift(4);
}
}
var cbf = parse_XLSCellParsedFormula(blob, end - blob.l, opts);
return {cell:cell, val:val[0], formula:cbf, shared: (flags >> 3) & 1, tt:val[1]};
}
/* 2.5.133 TODO: how to emit empty strings? */
function parse_FormulaValue(blob/*::, length*/) {
var b;
if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return [parse_Xnum(blob),'n'];
switch(blob[blob.l]) {
case 0x00: blob.l += 8; return ["String", 's'];
case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return [b,'b'];
case 0x02: b = blob[blob.l+2]; blob.l += 8; return [b,'e'];
case 0x03: blob.l += 8; return ["",'s'];
}
return [];
}
Ptg19[0x21] = Ptg19[0x20];
/* 2.5.198.103 */
function parse_RgbExtra(blob, length, rgce, opts) {
@ -587,6 +621,11 @@ function parse_RgbExtra(blob, length, rgce, opts) {
rgce[i][1][1] = blob.read_shift(4);
o.push(rgce[i][1]);
} break;
case 'PtgList': /* TODO: PtgList -> PtgExtraList */
case 'PtgElfRadicalS': /* TODO: PtgElfRadicalS -> PtgExtraElf */
case 'PtgElfColS': /* TODO: PtgElfColS -> PtgExtraElf */
case 'PtgElfColSV': /* TODO: PtgElfColSV -> PtgExtraElf */
throw "Unsupported " + rgce[i][0];
default: break;
}
}
@ -597,45 +636,6 @@ function parse_RgbExtra(blob, length, rgce, opts) {
return o;
}
/* 2.5.198.21 */
function parse_NameParsedFormula(blob, length, opts, cce) {
var target = blob.l + length;
var rgce = parse_Rgce(blob, cce, opts);
var rgcb;
if(target !== blob.l) rgcb = parse_RgbExtra(blob, target - blob.l, rgce, opts);
return [rgce, rgcb];
}
/* 2.5.198.3 TODO */
function parse_XLSCellParsedFormula(blob, length, opts) {
var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
var rgcb, cce = blob.read_shift(len); // length of rgce
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
var rgce = parse_Rgce(blob, cce, opts);
if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
return [rgce, rgcb];
}
/* 2.5.198.118 TODO */
function parse_SharedParsedFormula(blob, length, opts) {
var target = blob.l + length;
var rgcb, cce = blob.read_shift(2); // length of rgce
var rgce = parse_Rgce(blob, cce, opts);
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
return [rgce, rgcb];
}
/* 2.5.198.1 TODO */
function parse_ArrayParsedFormula(blob, length, opts, ref) {
var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
var rgcb, cce = blob.read_shift(len); // length of rgce
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
var rgce = parse_Rgce(blob, cce, opts);
if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
return [rgce, rgcb];
}
/* 2.5.198.104 */
function parse_Rgce(blob, length, opts) {
var target = blob.l + length;
@ -655,7 +655,7 @@ function parse_Rgce(blob, length, opts) {
return ptgs;
}
function stringify_array(f)/*:string*/ {
function stringify_array(f/*:Array<Array<any>>*/)/*:string*/ {
var o = [];
for(var i = 0; i < f.length; ++i) {
var x = f[i], r = [];
@ -702,15 +702,12 @@ 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)/*: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="";
if(!formula[0] || !formula[0][0]) return "";
var last_sp = -1, sp = "";
//console.log("--",cell,formula[0])
for(var ff = 0, fflen = formula[0].length; ff < fflen; ++ff) {
var f = formula[0][ff];
//console.log("++",f, stack)
switch(f[0]) {
case 'PtgUminus': /* 2.5.198.93 */
stack.push("-" + stack.pop()); break;
@ -791,7 +788,6 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
case 'PtgFunc': /* 2.5.198.62 */
case 'PtgFuncVar': /* 2.5.198.63 */
//console.log(f[1]);
/* f[1] = [argc, func, type] */
var argc/*:number*/ = (f[1][0]/*:any*/), func/*:string*/ = (f[1][1]/*:any*/);
if(!argc) argc = 0;
@ -845,7 +841,6 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
/* f[1] = type, ixti, nameindex */
var bookidx/*:number*/ = (f[1][1]/*:any*/); nameidx = (f[1][2]/*:any*/); var externbook;
/* TODO: Properly handle missing values */
//console.log(bookidx, supbooks);
if(opts.biff <= 5) {
if(bookidx < 0) bookidx = -bookidx;
if(supbooks[bookidx]) externbook = supbooks[bookidx][nameidx];
@ -949,6 +944,27 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
case 'PtgMemFunc': /* 2.5.198.72 TODO */
break;
case 'PtgMemNoMem': /* 2.5.198.73 TODO -- find a test case */
throw new Error('Unrecognized Formula Token: ' + String(f));
case 'PtgElfCol': /* 2.5.198.46 */
case 'PtgElfColS': /* 2.5.198.47 */
case 'PtgElfColSV': /* 2.5.198.48 */
case 'PtgElfColV': /* 2.5.198.49 */
case 'PtgElfLel': /* 2.5.198.50 */
case 'PtgElfRadical': /* 2.5.198.51 */
case 'PtgElfRadicalLel': /* 2.5.198.52 */
case 'PtgElfRadicalS': /* 2.5.198.53 */
case 'PtgElfRw': /* 2.5.198.54 */
case 'PtgElfRwV': /* 2.5.198.55 */
throw new Error("Unsupported ELFs");
case 'PtgAttrBaxcel': /* 2.5.198.33 TODO -- find a test case*/
throw new Error('Unrecognized Formula Token: ' + String(f));
case 'PtgSxName': /* 2.5.198.91 TODO -- find a test case */
throw new Error('Unrecognized Formula Token: ' + String(f));
case 'PtgList': /* [MS-XLSB] 2.5.97.52 TODO -- find a test case */
throw new Error('Unrecognized Formula Token: ' + String(f));
default: throw new Error('Unrecognized Formula Token: ' + String(f));
}
@ -976,9 +992,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
stack.push((_left ? sp : "") + stack.pop() + (_left ? "" : sp));
last_sp = -1;
}
//console.log("::",f, stack)
}
//console.log("--",stack);
if(stack.length > 1 && opts.WTF) throw new Error("bad formula stack");
return stack[0];
}

@ -1,3 +1,72 @@
/* [MS-XLS] 2.5.198.1 TODO */
function parse_ArrayParsedFormula(blob, length, opts, ref) {
var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
var rgcb, cce = blob.read_shift(len); // length of rgce
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
var rgce = parse_Rgce(blob, cce, opts);
if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
return [rgce, rgcb];
}
/* [MS-XLS] 2.5.198.3 TODO */
function parse_XLSCellParsedFormula(blob, length, opts) {
var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
var rgcb, cce = blob.read_shift(len); // length of rgce
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
var rgce = parse_Rgce(blob, cce, opts);
if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
return [rgce, rgcb];
}
/* [MS-XLS] 2.5.198.21 */
function parse_NameParsedFormula(blob, length, opts, cce) {
var target = blob.l + length;
var rgce = parse_Rgce(blob, cce, opts);
var rgcb;
if(target !== blob.l) rgcb = parse_RgbExtra(blob, target - blob.l, rgce, opts);
return [rgce, rgcb];
}
/* [MS-XLS] 2.5.198.118 TODO */
function parse_SharedParsedFormula(blob, length, opts) {
var target = blob.l + length;
var rgcb, cce = blob.read_shift(2); // length of rgce
var rgce = parse_Rgce(blob, cce, opts);
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
return [rgce, rgcb];
}
/* [MS-XLS] 2.5.133 TODO: how to emit empty strings? */
function parse_FormulaValue(blob/*::, length*/) {
var b;
if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return [parse_Xnum(blob),'n'];
switch(blob[blob.l]) {
case 0x00: blob.l += 8; return ["String", 's'];
case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return [b,'b'];
case 0x02: b = blob[blob.l+2]; blob.l += 8; return [b,'e'];
case 0x03: blob.l += 8; return ["",'s'];
}
return [];
}
/* [MS-XLS] 2.4.127 TODO */
function parse_Formula(blob, length, opts) {
var end = blob.l + length;
var cell = parse_XLSCell(blob, 6);
if(opts.biff == 2) ++blob.l;
var val = parse_FormulaValue(blob,8);
var flags = blob.read_shift(1);
if(opts.biff != 2) {
blob.read_shift(1);
if(opts.biff >= 5) {
var chn = blob.read_shift(4);
}
}
var cbf = parse_XLSCellParsedFormula(blob, end - blob.l, opts);
return {cell:cell, val:val[0], formula:cbf, shared: (flags >> 3) & 1, tt:val[1]};
}
/* XLSB Parsed Formula records have the same shape */
function parse_XLSBParsedFormula(data, length, opts) {
var end = data.l + length;

@ -81,7 +81,7 @@ function parse_ws_xml(data/*:?string*/, opts, rels, wb, themes, styles)/*:Worksh
}
function write_ws_xml_merges(merges) {
if(merges.length == 0) return "";
if(merges.length === 0) return "";
var o = '<mergeCells count="' + merges.length + '">';
for(var i = 0; i != merges.length; ++i) o += '<mergeCell ref="' + encode_range(merges[i]) + '"/>';
return o + '</mergeCells>';
@ -196,6 +196,7 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
case 'd':
if(opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
else {
cell = dup(cell);
cell.t = 'n';
vv = ''+(cell.v = datenum(parseDate(cell.v)));
}
@ -384,6 +385,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/, rels)/*:string*/ {
var o = [], r = [], range = safe_decode_range(ws['!ref']), cell, ref, rr = "", cols = [], R=0, C=0, rows = ws['!rows'];
var dense = Array.isArray(ws);
var params = ({r:rr}/*:any*/), row/*:RowInfo*/, height = -1;
for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
for(R = range.s.r; R <= range.e.r; ++R) {
r = [];
@ -395,11 +397,11 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
}
if(r.length > 0 || rows && rows[R]) {
var params = ({r:rr}/*:any*/);
params = ({r:rr}/*:any*/);
if(rows && rows[R]) {
var row = rows[R];
row = rows[R];
if(row.hidden) params.hidden = 1;
var height = -1;
height = -1;
if (row.hpx) height = px2pt(row.hpx);
else if (row.hpt) height = row.hpt;
if (height > -1) { params.ht = height; params.customHeight = 1; }

@ -261,7 +261,9 @@ function parse_BrtHLink(data, length, opts) {
var tooltip = parse_XLWideString(data);
var display = parse_XLWideString(data);
data.l = end;
return {rfx:rfx, relId:relId, loc:loc, Tooltip:tooltip, display:display};
var o = ({rfx:rfx, relId:relId, loc:loc, display:display}/*:any*/);
if(tooltip) o.Tooltip = tooltip;
return o;
}
function write_BrtHLink(l, rId, o) {
if(o == null) o = new_buf(50+4*l[1].Target.length);
@ -319,25 +321,16 @@ function write_BrtColInfo(C/*:number*/, col, o) {
}
/* [MS-XLSB] 2.4.672 BrtMargins */
function parse_BrtMargins(data, length, opts) {
return {
left: parse_Xnum(data, 8),
right: parse_Xnum(data, 8),
top: parse_Xnum(data, 8),
bottom: parse_Xnum(data, 8),
header: parse_Xnum(data, 8),
footer: parse_Xnum(data, 8)
};
var BrtMarginKeys = ["left","right","top","bottom","header","footer"];
function parse_BrtMargins(data, length, opts)/*:Margins*/ {
var margins = ({}/*:any*/);
BrtMarginKeys.forEach(function(k) { margins[k] = parse_Xnum(data, 8); });
return margins;
}
function write_BrtMargins(margins, o) {
function write_BrtMargins(margins/*:Margins*/, o) {
if(o == null) o = new_buf(6*8);
default_margins(margins);
write_Xnum(margins.left, o);
write_Xnum(margins.right, o);
write_Xnum(margins.top, o);
write_Xnum(margins.bottom, o);
write_Xnum(margins.header, o);
write_Xnum(margins.footer, o);
BrtMarginKeys.forEach(function(k) { write_Xnum((margins/*:any*/)[k], o); });
return o;
}
@ -641,13 +634,13 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ {
/* TODO: something useful -- this is a stub */
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/) {
if(cell.v === undefined) return "";
var vv = ""; var olddate = null;
var vv = "";
switch(cell.t) {
case 'b': vv = cell.v ? "1" : "0"; break;
case 'd': // no BrtCellDate :(
cell = dup(cell);
cell.z = cell.z || SSF._table[14];
olddate = cell.v;
cell.v = datenum((cell.v/*:any*/)); cell.t = 'n';
cell.v = datenum(parseDate(cell.v)); cell.t = 'n';
break;
/* falls through */
case 'n': case 'e': vv = ''+cell.v; break;
@ -673,7 +666,6 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
/* TODO: determine threshold for Real vs RK */
if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o));
else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o));
if(olddate) { cell.t = 'd'; cell.v = olddate; }
return;
case 'b':
o.t = "b";

@ -196,7 +196,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
var comments = [], comment = {};
var cstys = [], csty, seencol = false;
var arrayf = [];
var rowinfo = [], rowobj = {};
var rowinfo = [], rowobj = {}, cc = 0, rr = 0;
var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false} }/*:any*/), wsprops = {};
xlmlregex.lastIndex = 0;
str = str.replace(/<!--([\s\S]*?)-->/mg,"");
@ -220,8 +220,8 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
delete cell.HRef; delete cell.HRefScreenTip;
}
if(cell.MergeAcross || cell.MergeDown) {
var cc = c + (parseInt(cell.MergeAcross,10)|0);
var rr = r + (parseInt(cell.MergeDown,10)|0);
cc = c + (parseInt(cell.MergeAcross,10)|0);
rr = r + (parseInt(cell.MergeDown,10)|0);
mergecells.push({s:{c:c,r:r},e:{c:cc,r:rr}});
}
if(!opts.sheetStubs) { if(cell.MergeAcross) c = cc + 1; else ++c; }

@ -38,11 +38,11 @@ function slurp(R, blob, length/*:number*/, opts) {
var l = length;
var bufs = [];
var d = blob.slice(blob.l,blob.l+l);
if(opts && opts.enc && opts.enc.insitu_decrypt) switch(R.n) {
if(opts && opts.enc && opts.enc.insitu) switch(R.n) {
case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': break;
default:
if(d.length === 0) break;
opts.enc.insitu_decrypt(d);
opts.enc.insitu(d);
}
bufs.push(d);
blob.l += l;

@ -38,7 +38,7 @@ function write_BIFF2LABEL(r/*:number*/, c/*:number*/, val) {
function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) {
if(cell.v != null) switch(cell.t) {
case 'd': case 'n':
var v = cell.t == 'd' ? datenum(cell.v) : cell.v;
var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
if((v == (v|0)) && (v >= 0) && (v < 65536))
write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v));
else
@ -88,7 +88,7 @@ function write_biff2_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) {
if(cell.v != null) switch(cell.t) {
case 'd': case 'n':
var v = cell.t == 'd' ? datenum(cell.v) : cell.v;
var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
/* TODO: emit RK as appropriate */
write_biff_rec(ba, "Number", write_Number(R, C, v, opts));
return;
@ -148,16 +148,16 @@ function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) {
var A = buf_array();
var b8 = opts.biff == 8, b5 = opts.biff == 5;
write_biff_rec(A, 0x0809, write_BOF(wb, 0x05, opts));
write_biff_rec(A, "InterfaceHdr", writeuint16(0x04b0));
write_biff_rec(A, "InterfaceHdr", b8 ? writeuint16(0x04b0) : null);
write_biff_rec(A, "Mms", writezeroes(2));
if(b5) write_biff_rec(A, "ToolbarHdr");
if(b5) write_biff_rec(A, "ToolbarEnd");
write_biff_rec(A, "InterfaceEnd");
write_biff_rec(A, "WriteAccess", write_WriteAccess("SheetJS", opts));
write_biff_rec(A, "CodePage", writeuint16(0x04b0));
write_biff_rec(A, "CodePage", writeuint16(b8 ? 0x04b0 : 0x04E4));
if(b8) write_biff_rec(A, "DSF", writeuint16(0));
if(b8) write_biff_rec(A, "RRTabId", write_RRTabId(wb.SheetNames.length));
if(b8) write_biff_rec(A, "BuiltInFnGroupCount", writeuint16(0x11));
write_biff_rec(A, "RRTabId", write_RRTabId(wb.SheetNames.length));
write_biff_rec(A, "BuiltInFnGroupCount", writeuint16(0x11));
write_biff_rec(A, "WinProtect", writebool(false));
write_biff_rec(A, "Protect", writebool(false));
write_biff_rec(A, "Password", writeuint16(0));
@ -168,21 +168,21 @@ function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) {
write_biff_rec(A, "HideObj", writeuint16(0));
write_biff_rec(A, "Date1904", writebool(safe1904(wb)=="true"));
write_biff_rec(A, "CalcPrecision", writebool(true));
write_biff_rec(A, "RefreshAll", writebool(false));
if(b8) write_biff_rec(A, "RefreshAll", writebool(false));
write_biff_rec(A, "BookBool", writeuint16(0));
/* ... */
write_biff_rec(A, "UsesELFs", writebool(false));
if(b8) write_biff_rec(A, "UsesELFs", writebool(false));
var a = A.end();
var C = buf_array();
write_biff_rec(C, "Country", write_Country());
if(b8) write_biff_rec(C, "Country", write_Country());
/* BIFF8: [SST *Continue] ExtSST */
write_biff_rec(C, "EOF");
var c = C.end();
var B = buf_array();
var blen = 0, j = 0;
for(j = 0; j < wb.SheetNames.length; ++j) blen += 12 + (b8 ? 2 : 1) * wb.SheetNames[j].length;
for(j = 0; j < wb.SheetNames.length; ++j) blen += (b8 ? 12 : 11) + (b8 ? 2 : 1) * wb.SheetNames[j].length;
var start = a.length + blen + c.length;
for(j = 0; j < wb.SheetNames.length; ++j) {
write_biff_rec(B, "BoundSheet8", write_BoundSheet8({pos:start, hs:0, dt:0, name:wb.SheetNames[j]}, opts));

@ -1,20 +1,31 @@
/* OpenDocument */
var parse_content_xml = (function() {
var parse_text_p = function(text, tag) {
return unescapexml(text.replace(/<text:s\/>/g," ").replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1)+1).join(" "); }).replace(/<[^>]*>/g,""));
/* 6.1.2 White Space Characters */
var parse_text_p = function(text/*:string*/, tag)/*:string*/ {
return unescapexml(text
.replace(/[\t\r\n]/g, " ").trim().replace(/ +/g, " ")
.replace(/<text:s\/>/g," ")
.replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); })
.replace(/<text:tab[^>]*\/>/g,"\t")
.replace(/<text:line-break\/>/g,"\n")
.replace(/<[^>]*>/g,"")
);
};
var number_formats = {
/* ods name: [short ssf fmt, long ssf fmt] */
day: ["d", "dd"],
month: ["m", "mm"],
year: ["y", "yy"],
hours: ["h", "hh"],
minutes: ["m", "mm"],
seconds: ["s", "ss"],
"am-pm": ["A/P", "AM/PM"],
"day-of-week": ["ddd", "dddd"]
day: ["d", "dd"],
month: ["m", "mm"],
year: ["y", "yy"],
hours: ["h", "hh"],
minutes: ["m", "mm"],
seconds: ["s", "ss"],
"am-pm": ["A/P", "AM/PM"],
"day-of-week": ["ddd", "dddd"],
era: ["e", "ee"],
/* there is no native representation of LO "Q" format */
quarter: ["\\Qm", "m\\\"th quarter\""]
};
return function pcx(d/*:string*/, _opts)/*:Workbook*/ {
@ -29,15 +40,17 @@ var parse_content_xml = (function() {
var Sheets = {}, SheetNames/*:Array<string>*/ = [];
var ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
var Rn, q/*:: = ({t:"", v:null, z:null, w:"",c:[]}:any)*/;
var ctag = {value:""};
var ctag = ({value:""}/*:any*/);
var textp = "", textpidx = 0, textptag/*:: = {}*/;
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
var row_ol = 0;
var number_format_map = {};
var merges = [], mrange = {}, mR = 0, mC = 0;
var rowinfo = [], rowpeat = 1, colpeat = 1;
var arrayf = [];
var comments = [], comment = {};
var creator = "", creatoridx = 0;
var rept = 1, isstub = false;
var isstub = false;
var i = 0;
xlmlregex.lastIndex = 0;
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
@ -47,6 +60,7 @@ var parse_content_xml = (function() {
if(Rn[1]==='/') {
if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = encode_range(range);
if(merges.length) ws['!merges'] = merges;
if(rowinfo.length) ws["!rows"] = rowinfo;
sheetag.name = utf8read(sheetag['名称'] || sheetag.name);
SheetNames.push(sheetag.name);
Sheets[sheetag.name] = ws;
@ -56,13 +70,20 @@ var parse_content_xml = (function() {
R = C = -1;
range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0;
ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/); merges = [];
rowinfo = [];
}
break;
case 'table-row-group': // 9.1.9 <table:table-row-group>
if(Rn[1] === "/") --row_ol; else ++row_ol;
break;
case 'table-row': case '行': // 9.1.3 <table:table-row>
if(Rn[1] === '/') break;
if(Rn[1] === '/') { R+=rowpeat; rowpeat = 1; break; }
rowtag = parsexmltag(Rn[0], false);
if(rowtag['行号']) R = rowtag['行号'] - 1; else ++R;
if(rowtag['行号']) R = rowtag['行号'] - 1; else if(R == -1) R = 0;
rowpeat = +rowtag['number-rows-repeated'] || 1;
/* TODO: remove magic */
if(rowpeat < 10) for(i = 0; i < rowpeat; ++i) if(row_ol > 0) rowinfo[R + i] = {level: row_ol};
C = -1; break;
case 'covered-table-cell': // 9.1.5 <table:covered-table-cell>
++C;
@ -73,13 +94,24 @@ var parse_content_xml = (function() {
break; /* stub */
case 'table-cell': case '数据':
if(Rn[0].charAt(Rn[0].length-2) === '/') {
ctag = parsexmltag(Rn[0], false);
if(ctag['number-columns-repeated']) C+= parseInt(ctag['number-columns-repeated'], 10);
else ++C;
}
else if(Rn[1]!=='/') {
++C;
rept = 1;
ctag = parsexmltag(Rn[0], false);
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
q = ({t:'z', v:null/*:: , z:null, w:"",c:[]*/}/*:any*/);
if(ctag.formula && opts.cellFormula != false) q.f = ods_to_csf_formula(unescapexml(ctag.formula));
if((ctag['数据类型'] || ctag['value-type']) == "string") {
q.t = "s"; q.v = unescapexml(ctag['string-value'] || "");
if(opts.dense) {
if(!ws[R]) ws[R] = [];
ws[R][C] = q;
} else {
ws[encode_cell({r:R,c:C})] = q;
}
}
C+= colpeat-1;
} else if(Rn[1]!=='/') {
++C;
colpeat = 1;
if(C > range.e.c) range.e.c = C;
if(R > range.e.r) range.e.r = R;
if(C < range.s.c) range.s.c = C;
@ -110,7 +142,7 @@ var parse_content_xml = (function() {
}
/* 19.675.2 table:number-columns-repeated */
if(ctag['number-columns-repeated']) rept = parseInt(ctag['number-columns-repeated'], 10);
if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10);
/* 19.385 office:value-type */
switch(q.t) {
@ -139,17 +171,22 @@ var parse_content_xml = (function() {
if(textp && opts.cellText !== false) q.w = textp;
if(!isstub || opts.sheetStubs) {
if(!(opts.sheetRows && opts.sheetRows < R)) {
if(opts.dense) {
if(!ws[R]) ws[R] = [];
ws[R][C] = q;
while(--rept > 0) ws[R][++C] = dup(q);
} else {
ws[encode_cell({r:R,c:C})] = q;
while(--rept > 0) ws[encode_cell({r:R,c:++C})] = dup(q);
for(var rpt = 0; rpt < rowpeat; ++rpt) {
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
if(opts.dense) {
if(!ws[R + rpt]) ws[R + rpt] = [];
ws[R + rpt][C] = rpt == 0 ? q : dup(q);
while(--colpeat > 0) ws[R + rpt][C + colpeat] = dup(q);
} else {
ws[encode_cell({r:R + rpt,c:C})] = q;
while(--colpeat > 0) ws[encode_cell({r:R + rpt,c:C + colpeat})] = dup(q);
}
if(range.e.c <= C) range.e.c = C;
}
if(range.e.c <= C) range.e.c = C;
}
} else { C += rept; rept = 0; }
}
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
C += colpeat-1; colpeat = 0;
q = {/*:: t:"", v:null, z:null, w:"",c:[]*/};
textp = "";
}
@ -199,6 +236,7 @@ var parse_content_xml = (function() {
case 'form': // 13.13 <form:form>
case 'dde-links': // 9.8 <table:dde-links>
case 'event-listeners': // TODO
case 'chart': // TODO
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]);
textp = ""; textpidx = 0;
@ -226,7 +264,7 @@ var parse_content_xml = (function() {
case 'script': break; // 3.13 <office:script>
case 'libraries': break; // TODO: <ooo:libraries>
case 'automatic-styles': break; // 3.15.3 <office:automatic-styles>
case 'master-styles': break; // TODO: <office:automatic-styles>
case 'master-styles': break; // TODO: <office:master-styles>
case 'default-style': // TODO: <style:default-style>
case 'page-layout': break; // TODO: <style:page-layout>
@ -284,16 +322,18 @@ var parse_content_xml = (function() {
break;
case 'text-content': break; // 16.27.27 <number:text-content>
case 'text-properties': break; // 16.27.27 <style:text-properties>
case 'embedded-text': break; // 16.27.4 <number:embedded-text>
case 'body': case '电子表格': break; // 3.3 16.9.6 19.726.3
case 'forms': break; // 12.25.2 13.2
case 'table-column': break; // 9.1.6 <table:table-column>
case 'table-header-rows': break; // 9.1.7 <table:table-header-rows>
case 'table-rows': break; // 9.1.12 <table:table-rows>
/* TODO: outline levels */
case 'table-row-group': break; // 9.1.9 <table:table-row-group>
case 'table-column-group': break; // 9.1.10 <table:table-column-group>
case 'table-header-columns': break; // 9.1.11 <table:table-header-columns>
case 'table-columns': break; // 9.1.12 <table:table-columns>
case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
@ -312,9 +352,10 @@ var parse_content_xml = (function() {
case 'line-break': break; // 6.1.5 <text:line-break>
case 'span': break; // 6.1.7 <text:span>
case 'p': case '文本串': // 5.1.3 <text:p>
if(Rn[1]==='/') textp = (textp.length > 0 ? textp + "\n" : "") + parse_text_p(str.slice(textpidx,Rn.index), textptag);
if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) textp = (textp.length > 0 ? textp + "\n" : "") + parse_text_p(str.slice(textpidx,Rn.index), textptag);
else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
break; // <text:p>
case 's': break; // <text:s>
case 'database-range': // 9.4.15 <table:database-range>
if(Rn[1]==='/') break;
@ -324,12 +365,12 @@ var parse_content_xml = (function() {
} catch(e) {/* empty */}
break;
case 's': break; // <text:s>
case 'date': break; // <*:date>
case 'object': break; // 10.4.6.2 <draw:object>
case 'title': case '标题': break; // <*:title> OR <uof:标题>
case 'desc': break; // <*:desc>
case 'binary-data': break; // 10.4.5 TODO: b64 blob
/* 9.2 Advanced Tables */
case 'table-source': break; // 9.2.6
@ -379,9 +420,12 @@ var parse_content_xml = (function() {
/* TODO: FODS Properties */
case 'initial-creator':
case 'creation-date':
case 'print-date':
case 'generator':
case 'document-statistic':
case 'user-defined':
case 'editing-duration':
case 'editing-cycles':
break;
/* TODO: FODS Config */
@ -438,27 +482,33 @@ var parse_content_xml = (function() {
case 'table-protection': break;
case 'data-pilot-grand-total': break; // <table:
case 'office-document-common-attrs': break; // bare
default:
if(Rn[2] === 'dc:') break; // TODO: properties
if(Rn[2] === 'draw:') break; // TODO: drawing
if(Rn[2] === 'style:') break; // TODO: styles
if(Rn[2] === 'form:') break; // TODO: forms
if(Rn[2] === 'calcext:') break; // ignore undocumented extensions
if(Rn[2] === 'loext:') break; // ignore undocumented extensions
if(Rn[2] === 'uof:') break; // TODO: uof
if(Rn[2] === '表:') break; // TODO: uof
if(Rn[2] === '字:') break; // TODO: uof
if(opts.WTF) throw new Error(Rn);
default: switch(Rn[2]) {
case 'dc:': // TODO: properties
case 'calcext:': // ignore undocumented extensions
case 'loext:': // ignore undocumented extensions
case 'ooo:': // ignore undocumented extensions
case 'chartooo:': // ignore undocumented extensions
case 'draw:': // TODO: drawing
case 'style:': // TODO: styles
case 'chart:': // TODO: charts
case 'form:': // TODO: forms
case 'uof:': // TODO: uof
case '表:': // TODO: uof
case '字:': // TODO: uof
break;
default: if(opts.WTF) throw new Error(Rn);
}
}
var out = {
Sheets: Sheets,
SheetNames: SheetNames
};
if(opts.bookSheets) delete out.Sheets;
return out;
};
})();
function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
opts = opts || ({}/*:any*/);
var ods = !!safegetzipfile(zip, 'objectdata');
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
@ -468,7 +518,7 @@ function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
if(safegetzipfile(zip, 'meta.xml')) wb.Props = parse_core_props(getzipdata(zip, 'meta.xml'));
return wb;
}
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) {
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
return parse_content_xml(data, opts);
}

@ -1,14 +1,36 @@
/* OpenDocument */
var write_styles_ods/*:{(wb:any, opts:any):string}*/ = (function() {
var payload = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><office:document-styles xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" office:version="1.2"></office:document-styles>';
var payload = '<office:document-styles ' + wxt_helper({
'xmlns:office': "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
'xmlns:table': "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
'xmlns:style': "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
'xmlns:text': "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
'xmlns:draw': "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
'xmlns:fo': "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
'xmlns:xlink': "http://www.w3.org/1999/xlink",
'xmlns:dc': "http://purl.org/dc/elements/1.1/",
'xmlns:number': "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
'xmlns:svg': "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
'xmlns:of': "urn:oasis:names:tc:opendocument:xmlns:of:1.2",
'office:version': "1.2"
}) + '></office:document-styles>';
return function wso(wb, opts) {
return payload;
return XML_HEADER + payload;
};
})();
var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
/* 6.1.2 White Space Characters */
var write_text_p = function(text/*:string*/)/*:string*/ {
return escapexml(text)
.replace(/ +/g, function($$){return '<text:s text:c="'+$$.length+'"/>';})
.replace(/\t/g, "<text:tab/>")
.replace(/\n/g, "<text:line-break/>")
.replace(/^ /, "<text:s/>").replace(/ $/, "<text:s/>");
};
var null_cell_xml = ' <table:table-cell />\n';
var covered_cell_xml = ' <table:covered-table-cell/>\n';
var write_ws = function(ws, wb, i/*:number*/, opts)/*:string*/ {
var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts)/*:string*/ {
/* Section 9 Tables */
var o = [];
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n');
@ -56,7 +78,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
ct['office:value'] = (cell.v||0);
break;
case 's': case 'str':
textp = escapexml(cell.v);
textp = cell.v;
ct['office:value-type'] = "string";
break;
case 'd':
@ -68,7 +90,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
//case 'e':
default: o.push(null_cell_xml); continue;
}
o.push(' ' + writextag('table:table-cell', writextag('text:p', textp, {}), ct) + '\n');
o.push(' ' + writextag('table:table-cell', writextag('text:p', write_text_p(textp), {}), ct) + '\n');
}
o.push(' </table:table-row>\n');
}
@ -133,8 +155,8 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
});
var fods = wxt_helper({
'xmlns:config':"urn:oasis:names:tc:opendocument:xmlns:config:1.0",
'office:mimetype':"application/vnd.oasis.opendocument.spreadsheet"
'xmlns:config': "urn:oasis:names:tc:opendocument:xmlns:config:1.0",
'office:mimetype': "application/vnd.oasis.opendocument.spreadsheet"
});
if(opts.bookType == "fods") o.push('<office:document' + attr + fods + '>\n');
@ -161,7 +183,7 @@ function write_ods(wb/*:any*/, opts/*:any*/) {
var manifest/*:Array<Array<string> >*/ = [];
var rdf = [];
/* 3:3.3 and 2:2.2.4 */
/* Part 3 Section 3.3 MIME Media Type */
f = "mimetype";
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
@ -177,17 +199,17 @@ function write_ods(wb/*:any*/, opts/*:any*/) {
manifest.push([f, "text/xml"]);
rdf.push([f, "StylesFile"]);
/* Part 3 Section 6 Metadata Manifest File */
f = "manifest.rdf";
zip.file(f, write_rdf(rdf, opts));
manifest.push([f, "application/rdf+xml"]);
/* TODO: this is hard-coded to satiate excel */
f = "meta.xml";
zip.file(f, write_meta_ods(wb, opts));
manifest.push([f, "text/xml"]);
rdf.push([f, "MetadataFile"]);
/* Part 3 Section 6 Metadata Manifest File */
f = "manifest.rdf";
zip.file(f, write_rdf(rdf, opts));
manifest.push([f, "application/rdf+xml"]);
/* Part 3 Section 4 Manifest File */
f = "META-INF/manifest.xml";
zip.file(f, write_manifest(manifest, opts));

@ -49,6 +49,8 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
if(safegetzipfile(zip, 'META-INF/manifest.xml')) return parse_ods(zip, opts);
/* UOC */
if(safegetzipfile(zip, 'objectdata.xml')) return parse_ods(zip, opts);
/* Numbers */
if(safegetzipfile(zip, 'Index/Document.iwa')) throw new Error('Unsupported NUMBERS file');
var entries = keys(zip.files).filter(nodirs).sort();
var dir = parse_ct((getzipstr(zip, '[Content_Types].xml')/*:?any*/), opts);
@ -186,7 +188,7 @@ function parse_xlsxcfb(cfb, opts/*:?ParseOpts*/)/*:Workbook*/ {
data = CFB.find(cfb, f);
if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
var dsm = parse_DataSpaceMap(data.content);
if(dsm.length != 1 || dsm[0].comps.length != 1 || dsm[0].comps[0].t != 0 || dsm[0].name != "StrongEncryptionDataSpace" || dsm[0].comps[0].v != "EncryptedPackage")
if(dsm.length !== 1 || dsm[0].comps.length !== 1 || dsm[0].comps[0].t !== 0 || dsm[0].name !== "StrongEncryptionDataSpace" || dsm[0].comps[0].v !== "EncryptedPackage")
throw new Error("ECMA-376 Encrypted file bad " + f);
f = 'StrongEncryptionDataSpace';
@ -207,6 +209,7 @@ function parse_xlsxcfb(cfb, opts/*:?ParseOpts*/)/*:Workbook*/ {
if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
var einfo = parse_EncryptionInfo(data.content);
if(einfo[0] == 0x04) throw new Error("File is password-protected: ECMA-376 Agile");
throw new Error("File is password-protected");
}

@ -70,7 +70,7 @@ function read_prn(data, d, o, str) {
}
function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
var zip, d = data, n=[0], str = false;
var zip, d = data, n = [0,0,0,0], str = false;
var o = opts||{};
_ssfopts = {};
if(o.dateNF) _ssfopts.dateNF = o.dateNF;
@ -81,14 +81,14 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
case 0xD0: return read_cfb(CFB.read(d, o), o);
case 0x09: return parse_xlscfb(d, o);
case 0x3C: return parse_xlml(d, o);
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) : 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);
case 0x7B: if(n[1] == 0x5C && n[2] == 0x72 && n[3] == 0x74) return RTF.to_workbook(d, o); break;
case 0x49: if(n[1] === 0x44) return read_wb_ID(d, o); break;
case 0x54: if(n[1] === 0x41 && n[2] === 0x42 && n[3] === 0x4C) return DIF.to_workbook(d, o); break;
case 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) : 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: case 0x8C: return DBF.to_workbook(d, o);
case 0x7B: if(n[1] === 0x5C && n[2] === 0x72 && n[3] === 0x74) return RTF.to_workbook(d, o); break;
case 0x0A: case 0x0D: case 0x20: return read_plaintext_raw(d, o);
}
if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);

@ -175,10 +175,10 @@ function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ {
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:js.length}}/*:any*/);
var hdr = o.header || [], C = 0;
for(var R = 0; R != js.length; ++R) {
Object.keys(js[R]).filter(function(x) { return js[R].hasOwnProperty(x); }).forEach(function(k) {
js.forEach(function (JS, R) {
keys(JS).filter(function(x) { return JS.hasOwnProperty(x); }).forEach(function(k) {
if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k;
var v = js[R][k];
var v = JS[k];
var t = 'z';
var z = "";
if(typeof v == 'number') t = 'n';
@ -192,7 +192,7 @@ function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ {
ws[encode_cell({c:C,r:R+1})] = cell = ({t:t, v:v}/*:any*/);
if(z) cell.z = z;
});
}
});
range.e.c = hdr.length - 1;
for(C = 0; C < hdr.length; ++C) ws[encode_col(C) + "1"] = {t:'s', v:hdr[C]};
ws['!ref'] = encode_range(range);

@ -11,7 +11,7 @@
<!-- ui-grid -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.0.0/ui-grid.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.0.0/ui-grid.css"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.0.0/ui-grid.css"/>
<!-- FileSaver shim for exporting files -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js"></script>

28
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

25
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

836
dist/xlsx.js vendored

File diff suppressed because it is too large Load Diff

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

@ -36,76 +36,3 @@ With [bower](http://bower.io/search/?q=js-xlsx):
$ bower install js-xlsx
```
### JS Ecosystem Demos
The [`demos` directory](demos/) includes sample projects for:
**Frameworks and APIs**
- [`angular 1.x`](demos/angular/)
- [`angular 2.x / 4.x`](demos/angular2/)
- [`meteor`](demos/meteor/)
- [`react and react-native`](demos/react/)
- [`vue 2.x and weex`](demos/vue/)
- [`XMLHttpRequest and fetch`](demos/xhr/)
- [`nodejs server`](demos/server/)
**Bundlers and Tooling**
- [`browserify`](demos/browserify/)
- [`requirejs`](demos/requirejs/)
- [`rollup`](demos/rollup/)
- [`systemjs`](demos/systemjs/)
- [`webpack 2.x`](demos/webpack/)
**Platforms and Integrations**
- [`electron application`](demos/electron/)
- [`nw.js application`](demos/nwjs/)
- [`Adobe ExtendScript`](demos/extendscript/)
- [`Headless Browsers`](demos/headless/)
- [`canvas-datagrid`](demos/datagrid/)
- [`Swift JSC and other engines`](demos/altjs/)
### Optional Modules
<details>
<summary><b>Optional features</b> (click to show)</summary>
The node version automatically requires modules for additional features. Some
of these modules are rather large in size and are only needed in special
circumstances, so they do not ship with the core. For browser use, they must
be included directly:
```html
<!-- international support from js-codepage -->
<script src="dist/cpexcel.js"></script>
```
An appropriate version for each dependency is included in the dist/ directory.
The complete single-file version is generated at `dist/xlsx.full.min.js`
Webpack and Browserify builds include optional modules by default. Webpack can
be configured to remove support with `resolve.alias`:
```js
/* uncomment the lines below to remove support */
resolve: {
alias: { "./dist/cpexcel.js": "" } // <-- omit international support
}
```
</details>
### ECMAScript 5 Compatibility
Since the library uses functions like `Array#forEach`, older browsers require
[shims to provide missing functions](http://oss.sheetjs.com/js-xlsx/shim.js).
To use the shim, add the shim before the script tag that loads `xlsx.js`:
```html
<!-- add the shim first -->
<script type="text/javascript" src="shim.js"></script>
<!-- after the shim is referenced, add the library -->
<script type="text/javascript" src="xlsx.full.min.js"></script>
```

28
docbits/11_demos.md Normal file

@ -0,0 +1,28 @@
### JS Ecosystem Demos
The [`demos` directory](demos/) includes sample projects for:
**Frameworks and APIs**
- [`angular 1.x`](demos/angular/)
- [`angular 2.x / 4.x`](demos/angular2/)
- [`meteor`](demos/meteor/)
- [`react and react-native`](demos/react/)
- [`vue 2.x and weex`](demos/vue/)
- [`XMLHttpRequest and fetch`](demos/xhr/)
- [`nodejs server`](demos/server/)
**Bundlers and Tooling**
- [`browserify`](demos/browserify/)
- [`requirejs`](demos/requirejs/)
- [`rollup`](demos/rollup/)
- [`systemjs`](demos/systemjs/)
- [`webpack 2.x`](demos/webpack/)
**Platforms and Integrations**
- [`electron application`](demos/electron/)
- [`nw.js application`](demos/nwjs/)
- [`Adobe ExtendScript`](demos/extendscript/)
- [`Headless Browsers`](demos/headless/)
- [`canvas-datagrid`](demos/datagrid/)
- [`Swift JSC and other engines`](demos/altjs/)

45
docbits/12_optional.md Normal file

@ -0,0 +1,45 @@
### Optional Modules
<details>
<summary><b>Optional features</b> (click to show)</summary>
The node version automatically requires modules for additional features. Some
of these modules are rather large in size and are only needed in special
circumstances, so they do not ship with the core. For browser use, they must
be included directly:
```html
<!-- international support from js-codepage -->
<script src="dist/cpexcel.js"></script>
```
An appropriate version for each dependency is included in the dist/ directory.
The complete single-file version is generated at `dist/xlsx.full.min.js`
Webpack and Browserify builds include optional modules by default. Webpack can
be configured to remove support with `resolve.alias`:
```js
/* uncomment the lines below to remove support */
resolve: {
alias: { "./dist/cpexcel.js": "" } // <-- omit international support
}
```
</details>
### ECMAScript 5 Compatibility
Since the library uses functions like `Array#forEach`, older browsers require
[shims to provide missing functions](http://oss.sheetjs.com/js-xlsx/shim.js).
To use the shim, add the shim before the script tag that loads `xlsx.js`:
```html
<!-- add the shim first -->
<script type="text/javascript" src="shim.js"></script>
<!-- after the shim is referenced, add the library -->
<script type="text/javascript" src="xlsx.full.min.js"></script>
```

@ -97,8 +97,9 @@ Plain text format guessing follows the priority order:
| XML | starts with `<` |
| RTF | starts with `{\rt` |
| DSV | starts with `/sep=.$/`, separator is the specified character |
| CSV | more unquoted `","` characters than `"\t"` chars in the first 1024 |
| TSV | one of the first 1024 characters is a tab char `"\t"` |
| DSV | more unquoted `";"` chars than `"\t"` or `","` in the first 1024 |
| TSV | more unquoted `"\t"` chars than `","` chars in the first 1024 |
| CSV | one of the first 1024 characters is a comma `","` |
| PRN | (default) |
- HTML tags include: `html`, `table`, `head`, `meta`, `script`, `style`, `div`

@ -36,6 +36,7 @@ output formats. The specific file type is controlled with `bookType` option:
| `xlsm` | `.xlsm` | ZIP | multi | Excel 2007+ Macro XML Format |
| `xlsb` | `.xlsb` | ZIP | multi | Excel 2007+ Binary Format |
| `biff8` | `.xls` | CFB | multi | Excel 97-2004 Workbook Format |
| `biff5` | `.xls` | CFB | multi | Excel 5.0/95 Workbook Format |
| `biff2` | `.xls` | none | single | Excel 2.0 Worksheet Format |
| `xlml` | `.xls` | none | multi | Excel 2003-2004 (SpreadsheetML) |
| `ods` | `.ods` | ZIP | multi | OpenDocument Spreadsheet |
@ -45,7 +46,7 @@ output formats. The specific file type is controlled with `bookType` option:
| `sylk` | `.sylk` | none | single | Symbolic Link (SYLK) |
| `html` | `.html` | none | single | HTML Document |
| `dif` | `.dif` | none | single | Data Interchange Format (DIF) |
| `rtf` | `.rtf` | none | single | Rich Text Format |
| `rtf` | `.rtf` | none | single | Rich Text Format (RTF) |
| `prn` | `.prn` | none | single | Lotus Formatted Text |
- `compression` only applies to formats with ZIP containers.

@ -9,7 +9,7 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
| Excel 2007+ Binary Format (XLSB BIFF12) | :o: | :o: |
| Excel 2003-2004 XML Format (XML "SpreadsheetML") | :o: | :o: |
| Excel 97-2004 (XLS BIFF8) | :o: | :o: |
| Excel 5.0/95 (XLS BIFF5) | :o: | |
| Excel 5.0/95 (XLS BIFF5) | :o: | :o: |
| Excel 4.0 (XLS/XLW BIFF4) | :o: | |
| Excel 3.0 (XLS BIFF3) | :o: | |
| Excel 2.0/2.1 (XLS BIFF2) | :o: | :o: |
@ -28,7 +28,7 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
| Quattro Pro Spreadsheet (WQ1/WQ2/WB1/WB2/WB3/QPW) | :o: | |
| **Other Common Spreadsheet Output Formats** |:-----:|:-----:|
| HTML Tables | :o: | :o: |
| RTF Tables | | :o: |
| Rich Text Format tables (RTF) | | :o: |
### Excel 2007+ XML (XLSX/XLSM)

@ -40,6 +40,7 @@ digraph G {
xlsb -> csf
csf -> xlml
xlml -> csf
csf -> xls5
xls5 -> csf
csf -> xls8
xls8 -> csf

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 181 KiB

@ -54,7 +54,7 @@ Use readAsBinaryString: (when available) <input type="checkbox" name="userabs" c
<script>
/*jshint browser:true */
/* eslint-env browser */
/*global Uint8Array, Uint16Array, ArrayBuffer */
/*global Uint8Array, console */
/*global XLSX */
var X = XLSX;
var XW = {

@ -1437,8 +1437,9 @@ Plain text format guessing follows the priority order:
| XML | starts with `<` |
| RTF | starts with `{\rt` |
| DSV | starts with `/sep=.$/`, separator is the specified character |
| CSV | more unquoted `","` characters than `"\t"` chars in the first 1024 |
| TSV | one of the first 1024 characters is a tab char `"\t"` |
| DSV | more unquoted `";"` chars than `"\t"` or `","` in the first 1024 |
| TSV | more unquoted `"\t"` chars than `","` chars in the first 1024 |
| CSV | one of the first 1024 characters is a comma `","` |
| PRN | (default) |
- HTML tags include: `html`, `table`, `head`, `meta`, `script`, `style`, `div`
@ -1497,6 +1498,7 @@ output formats. The specific file type is controlled with `bookType` option:
| `xlsm` | `.xlsm` | ZIP | multi | Excel 2007+ Macro XML Format |
| `xlsb` | `.xlsb` | ZIP | multi | Excel 2007+ Binary Format |
| `biff8` | `.xls` | CFB | multi | Excel 97-2004 Workbook Format |
| `biff5` | `.xls` | CFB | multi | Excel 5.0/95 Workbook Format |
| `biff2` | `.xls` | none | single | Excel 2.0 Worksheet Format |
| `xlml` | `.xls` | none | multi | Excel 2003-2004 (SpreadsheetML) |
| `ods` | `.ods` | ZIP | multi | OpenDocument Spreadsheet |
@ -1506,7 +1508,7 @@ output formats. The specific file type is controlled with `bookType` option:
| `sylk` | `.sylk` | none | single | Symbolic Link (SYLK) |
| `html` | `.html` | none | single | HTML Document |
| `dif` | `.dif` | none | single | Data Interchange Format (DIF) |
| `rtf` | `.rtf` | none | single | Rich Text Format |
| `rtf` | `.rtf` | none | single | Rich Text Format (RTF) |
| `prn` | `.prn` | none | single | Lotus Formatted Text |
- `compression` only applies to formats with ZIP containers.
@ -1804,7 +1806,7 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
| Excel 2007+ Binary Format (XLSB BIFF12) | :o: | :o: |
| Excel 2003-2004 XML Format (XML "SpreadsheetML") | :o: | :o: |
| Excel 97-2004 (XLS BIFF8) | :o: | :o: |
| Excel 5.0/95 (XLS BIFF5) | :o: | |
| Excel 5.0/95 (XLS BIFF5) | :o: | :o: |
| Excel 4.0 (XLS/XLW BIFF4) | :o: | |
| Excel 3.0 (XLS BIFF3) | :o: | |
| Excel 2.0/2.1 (XLS BIFF2) | :o: | :o: |
@ -1823,7 +1825,7 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
| Quattro Pro Spreadsheet (WQ1/WQ2/WB1/WB2/WB3/QPW) | :o: | |
| **Other Common Spreadsheet Output Formats** |:-----:|:-----:|
| HTML Tables | :o: | :o: |
| RTF Tables | | :o: |
| Rich Text Format tables (RTF) | | :o: |
### Excel 2007+ XML (XLSX/XLSM)

@ -2,25 +2,26 @@
# vim: set ts=4:
# Format: <basename> <ext> <ext> [ext..]
# yes-formula
# note: Excel ODS converter does not support spaces in Sheet Names
AutoFilter .xls .xlsb .xlsx .xml
# note: XLML only supports sheets, ods does not support dialog
BlankSheetTypes .xls .xlsb .xlsm
NumberFormatCondition .xls .xlsb .xlsm .xml
RkNumber .xls .xlsb .xlsx .xls.xml
#calendar_stress_test .xls .xlsb .xlsx .xml
cell_style_simple .xls .xlsb .xlsx .xml
cell_style_simple .xls .xlsb .xlsx .xml .ods
# no-csv (newline character \r vs \n)
comments_stress_test .xls .xlsb .xlsx .xls.xml
comments_stress_test .xls .xlsb .xlsx .xls.xml .ods
# yes-csv
custom_properties .xls .xlsb .xlsx .xls.xml
defined_names_simple .xls .xlsb .xlsx .xml
# no-csv (randbetween) note: ODS does not support many XLSX functions
# no-csv (randbetween) note: ODS does not support many XLSX functions
formula_stress_test .xls .xlsb .xlsx .xls.xml
# yes-csv
formulae_test_simple .xls .xlsb .xlsx .xml
hyperlink_stress_test_2011 .xls .xlsb .xlsx .xml
#large_strings .xls .xlsb .xlsx .xls.xml .xlsb.xml .xlsx.xml
merge_cells .xls .xlsb .xlsx .xls.xml
merge_cells .xls .xlsb .xlsx .xls.xml .ods
# no-formula (filename-references in XLSX encoding as [0])
named_ranges_2011 .xls .xlsb .xlsx .xls.xml
# yes-formula
@ -34,7 +35,7 @@ pivot_table_named_range .xls .xlsb .xlsx .xml
pivot_table_test .xls .xlsb .xlsm
rich_text_stress .xls .xlsb .xlsx .xls.xml
smart_tags_2007 .xls .xlsb .xlsx .xml
sushi .xls .xlsb .xlsx .xml
sushi .xls .xlsb .xlsx .xml .ods
text_and_numbers .xls .xlsb .xlsx .xml
#time_stress_test_1 .xls .xlsb .xlsx .xml
# no-formula (rounding issue in IE8)

@ -1,8 +1,8 @@
{
"name": "xlsx",
"version": "0.11.5",
"version": "0.11.6",
"author": "sheetjs",
"description": "Excel (XLSB/XLSX/XLS/XML) ODS and other spreadsheet format (CSV/DIF/DBF/SYLK) parser and writer",
"description": "SheetJS Spreadsheet data parser and writer",
"keywords": [ "excel", "xls", "xlsx", "xlsb", "xlsm", "ods", "csv", "dbf", "dif", "sylk", "office", "spreadsheet" ],
"bin": {
"xlsx": "./bin/xlsx.njs"
@ -17,20 +17,20 @@
"fs": false
},
"dependencies": {
"exit-on-epipe":"~1.0.1",
"ssf":"~0.10.1",
"codepage":"~1.11.0",
"cfb":"~0.13.1",
"crc-32":"~1.1.1",
"adler-32":"~1.1.0",
"commander":"~2.11.0"
"exit-on-epipe": "~1.0.1",
"ssf": "~0.10.1",
"codepage": "~1.11.0",
"cfb": "~0.13.1",
"crc-32": "~1.1.1",
"adler-32": "~1.1.0",
"commander": "~2.11.0"
},
"devDependencies": {
"mocha":"~2.5.3",
"mocha": "~2.5.3",
"blanket": "~1.2.3",
"@sheetjs/uglify-js":"~2.7.3",
"@types/node":"^8.0.7",
"@types/commander":"^2.9.0",
"@sheetjs/uglify-js": "~2.7.3",
"@types/node": "^8.0.7",
"@types/commander": "^2.9.0",
"jsdom": "~11.1.0",
"dtslint": "^0.1.2",
"typescript": "2.2.0"
@ -39,6 +39,8 @@
"scripts": {
"pretest": "git submodule init && git submodule update",
"test": "make travis",
"build": "make",
"lint": "make fullint",
"dtslint": "dtslint types"
},
"config": {

797
test.js

File diff suppressed because it is too large Load Diff

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

@ -1441,3 +1441,5 @@ artifacts/wps/write.et
# artifacts/wps/write.xls ## bad sheet name
artifacts/wps/write.xlsx
artifacts/wps/write.xml
dbf/d11.dbf
dbf/vfp3.dbf

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -39,6 +39,7 @@
./test_files/custom_properties.xlsb
./test_files/cell_style_simple.xls
./test_files/cell_style_simple.xml
./test_files/cell_style_simple.ods
./test_files/cell_style_simple.xlsx
./test_files/cell_style_simple.xlsb
./test_files/comments_stress_test.xls
@ -106,3 +107,5 @@
./test_files/apachepoi_SimpleWithComments.xlsx
./test_files/2013/apachepoi_SimpleWithComments.xlsx.xlsb
./test_files/password_2002_40_xor.xls
./test_files/dbf/d11.dbf
./test_files/dbf/vfp3.dbf

@ -5,7 +5,7 @@
var data = [
[1, 2, 3],
[true, false, null, "sheetjs"],
["foo", "bar", new Date("2014-02-19T14:30Z"), "0.3"],
["foo bar", "baz", new Date("2014-02-19T14:30Z"), "0.3"],
["baz", null, "\u0BEE", 3.14159],
["hidden"],
["visible"]
@ -162,8 +162,9 @@ var filenames = [
['sheetjs.xlsx', {bookSST:true}],
['sheetjs.xlsm'],
['sheetjs.xlsb'],
['sheetjs.xls', {bookType:'xls'}],
['sheetjs.biff2', {bookType:'biff2'}],
['sheetjs.biff8.xls', {bookType:'xls'}],
['sheetjs.biff5.xls', {bookType:'biff5'}],
['sheetjs.biff2.xls', {bookType:'biff2'}],
['sheetjs.xml.xls', {bookType:'xlml'}],
['sheetjs.ods'],
['sheetjs.fods'],

2
types/index.d.ts vendored

@ -477,7 +477,7 @@ export type ExcelDataType = 'b' | 'n' | 'e' | 's' | 'd' | 'z';
* Type of generated workbook
* @default 'xlsx'
*/
export type BookType = 'xlsx' | 'xlsm' | 'xlsb' | 'xls' | 'biff8' | 'biff2' | 'xlml' | 'ods' | 'fods' | 'csv' | 'txt' | 'sylk' | 'html' | 'dif' | 'rtf' | 'prn';
export type BookType = 'xlsx' | 'xlsm' | 'xlsb' | 'xls' | 'biff8' | 'biff5' | 'biff2' | 'xlml' | 'ods' | 'fods' | 'csv' | 'txt' | 'sylk' | 'html' | 'dif' | 'rtf' | 'prn';
/** Comment element */
export interface Comment {

@ -5,7 +5,7 @@
let data: any[][] = [
[1, 2, 3],
[true, false, null, "sheetjs"],
["foo", "bar", new Date("2014-02-19T14:30Z"), "0.3"],
["foo bar", "baz", new Date("2014-02-19T14:30Z"), "0.3"],
["baz", null, "qux", 3.14159],
["hidden"],
["visible"]
@ -150,8 +150,9 @@ const filenames: Array<[string]|[string, XLSX.WritingOptions]> = [
['sheetjs.xlsx', {bookSST:true}],
['sheetjs.xlsm'],
['sheetjs.xlsb'],
['sheetjs.xls', {bookType:'xls'}],
['sheetjs.biff2', {bookType:'biff2'}],
['sheetjs.biff8.xls', {bookType:'xls'}],
['sheetjs.biff5.xls', {bookType:'biff5'}],
['sheetjs.biff2.xls', {bookType:'biff2'}],
['sheetjs.xml.xls', {bookType:'xlml'}],
['sheetjs.ods'],
['sheetjs.fods'],
@ -160,6 +161,7 @@ const filenames: Array<[string]|[string, XLSX.WritingOptions]> = [
['sheetjs.slk'],
['sheetjs.htm'],
['sheetjs.dif'],
['sheetjs.rtf'],
['sheetjs.prn']
];

@ -10,9 +10,7 @@ const otherworkbook: XLSX.WorkBook = XLSX.readFile('test.xlsx', {type: 'file'});
const author: string = workbook.Props.Author;
const firstsheet: string = workbook.SheetNames[0];
const firstworksheet: XLSX.WorkSheet = workbook.Sheets[firstsheet];
const WB1A1: XLSX.CellObject = (firstworksheet["A1"]);
interface Tester {
@ -41,3 +39,8 @@ const WBSheet0 = WBSheets[0];
console.log(WBSheet0.Hidden);
const fmt14 = XLSX.SSF._table[14];
const newwb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(newwb, aoa2, "AOA");
XLSX.utils.book_append_sheet(newwb, js2ws, "JSON");
const bstrxlsx: string = XLSX.write(newwb, {type: "binary", bookType: "xlsx" });

File diff suppressed because it is too large Load Diff

755
xlsx.js

File diff suppressed because it is too large Load Diff