version bump 0.11.16: refresh

- HTML whitespace (fixes #849 h/t @laurentauthier)
- XLML number format write (fixes #904 h/t @james-boswell)
- XLAM/XLA write
- 'array' write type
- XLSX/XLSB/XLS/XLML RTL read/write
- XLS merge cells write
- demo and typing refresh
This commit is contained in:
SheetJS 2017-12-30 00:40:35 -05:00
parent 33f96fc6ae
commit f277ebe140
90 changed files with 1977 additions and 1389 deletions

@ -14,8 +14,8 @@ tmp
*.[pP][rR][nN]
*.[sS][lL][kK]
*.socialcalc
*.[xX][lL][sSwWcC]
*.[xX][lL][sS][xXmMbB]
*.[xX][lL][sSwWcCaAtT]
*.[xX][lL][sSaAtT][xXmMbB]
*.[oO][dD][sS]
*.[fF][oO][dD][sS]
*.[xX][mM][lL]

@ -53,6 +53,7 @@ weex
# Other terms
APIs
ArrayBuffer
Base64
Booleans
JS

@ -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.16 (2017-12-30)
* XLS ANSI/CP separation
* 'array' write type and ArrayBuffer processing
## 0.11.6 (2017-10-16)
* Semicolon-delimited files are detected

@ -84,6 +84,7 @@ enhancements, additional features by request, and dedicated support.
+ [Workbook File Properties](#workbook-file-properties)
* [Workbook-Level Attributes](#workbook-level-attributes)
+ [Defined Names](#defined-names)
+ [Workbook Views](#workbook-views)
+ [Miscellaneous Workbook Properties](#miscellaneous-workbook-properties)
* [Document Features](#document-features)
+ [Formulae](#formulae)
@ -621,19 +622,12 @@ example uses [FileSaver](https://github.com/eligrey/FileSaver.js/):
```js
/* bookType can be any supported output type */
var wopts = { bookType:'xlsx', bookSST:false, type:'binary' };
var wopts = { bookType:'xlsx', bookSST:false, type:'array' };
var wbout = XLSX.write(workbook,wopts);
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
/* the saveAs call downloads a file on the local machine */
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx");
saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx");
```
</details>
@ -1081,6 +1075,14 @@ Excel allows two sheet-scoped defined names to share the same name. However, a
sheet-scoped name cannot collide with a workbook-scope name. Workbook writers
may not enforce this constraint.
#### Workbook Views
`wb.Workbook.Views` is an array of workbook view objects which have the keys:
| Key | Description |
|:----------------|:----------------------------------------------------|
| `RTL` | If true, display right-to-left |
#### Miscellaneous Workbook Properties
`wb.Workbook.WBProps` holds other workbook properties:
@ -1693,6 +1695,7 @@ The `type` argument for `write` mirrors the `type` argument for `read`:
| `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) |
| `"string"` | string: JS string (characters interpreted as UTF8) |
| `"buffer"` | nodejs Buffer |
| `"array"` | ArrayBuffer, fallback array of 8-bit unsigned int |
| `"file"` | string: path of file that will be created (nodejs only) |
## Utility Functions

@ -19,12 +19,14 @@ program
.option('-B, --xlsb', 'emit XLSB to <sheetname> or <file>.xlsb')
.option('-M, --xlsm', 'emit XLSM to <sheetname> or <file>.xlsm')
.option('-X, --xlsx', 'emit XLSX to <sheetname> or <file>.xlsx')
.option('-I, --xlam', 'emit XLAM to <sheetname> or <file>.xlam')
.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('-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)')
.option('-i, --xla', 'emit XLA to <sheetname> or <file>.xla')
.option('-6, --xlml', 'emit SSML to <sheetname> or <file>.xls (2003 XML)')
.option('-T, --fods', 'emit FODS to <sheetname> or <file>.fods (Flat ODS)')
@ -65,8 +67,10 @@ program.on('--help', function() {
var workbook_formats = [
['xlsx', 'xlsx', 'xlsx'],
['xlsm', 'xlsm', 'xlsm'],
['xlam', 'xlam', 'xlam'],
['xlsb', 'xlsb', 'xlsb'],
['xls', 'xls', 'xls'],
['xla', 'xla', 'xla'],
['biff5', 'biff5', 'xls'],
['ods', 'ods', 'ods'],
['fods', 'fods', 'fods']

@ -1 +1 @@
XLSX.version = '0.11.15';
XLSX.version = '0.11.16';

@ -1,21 +1,51 @@
var current_codepage = 1200;
var current_codepage = 1200, current_ansi = 1252;
/*:: declare var cptable:any; */
/*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
if(typeof cptable === 'undefined') global.cptable = require('./dist/cpexcel.js');
}
function reset_cp() { set_cp(1200); }
var set_cp = function(cp) { current_codepage = cp; };
function char_codes(data) { var o = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; }
var VALID_ANSI = [ 874, 932, 936, 949, 950 ];
for(var i = 0; i <= 8; ++i) VALID_ANSI.push(1250 + i);
/* ECMA-376 Part I 18.4.1 charset to codepage mapping */
var CS2CP = ({
/*::[*/0/*::]*/: 1252, /* ANSI */
/*::[*/1/*::]*/: 65001, /* DEFAULT */
/*::[*/2/*::]*/: 65001, /* SYMBOL */
/*::[*/77/*::]*/: 10000, /* MAC */
/*::[*/128/*::]*/: 932, /* SHIFTJIS */
/*::[*/129/*::]*/: 949, /* HANGUL */
/*::[*/130/*::]*/: 1361, /* JOHAB */
/*::[*/134/*::]*/: 936, /* GB2312 */
/*::[*/136/*::]*/: 950, /* CHINESEBIG5 */
/*::[*/161/*::]*/: 1253, /* GREEK */
/*::[*/162/*::]*/: 1254, /* TURKISH */
/*::[*/163/*::]*/: 1258, /* VIETNAMESE */
/*::[*/177/*::]*/: 1255, /* HEBREW */
/*::[*/178/*::]*/: 1256, /* ARABIC */
/*::[*/186/*::]*/: 1257, /* BALTIC */
/*::[*/204/*::]*/: 1251, /* RUSSIAN */
/*::[*/222/*::]*/: 874, /* THAI */
/*::[*/238/*::]*/: 1250, /* EASTEUROPE */
/*::[*/255/*::]*/: 1252, /* OEM */
/*::[*/69/*::]*/: 6969 /* MISC */
}/*:any*/);
var set_ansi = function(cp/*:number*/) { if(VALID_ANSI.indexOf(cp) == -1) return; current_ansi = CS2CP[0] = cp; };
function reset_ansi() { set_ansi(1252); }
var set_cp = function(cp/*:number*/) { current_codepage = cp; set_ansi(cp); };
function reset_cp() { set_cp(1200); reset_ansi(); }
function char_codes(data/*:string*/)/*:Array<number>*/ { var o/*:Array<number>*/ = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; }
function utf16leread(data/*:string*/)/*:string*/ {
var o = [];
var o/*:Array<string>*/ = [];
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i) + (data.charCodeAt(2*i+1)<<8));
return o.join("");
}
function utf16beread(data/*:string*/)/*:string*/ {
var o = [];
var o/*:Array<string>*/ = [];
for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i+1) + (data.charCodeAt(2*i)<<8));
return o.join("");
}

@ -12,6 +12,18 @@ function s2a(s/*:string*/) {
return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; });
}
function s2ab(s/*:string*/) {
if(typeof ArrayBuffer === 'undefined') return s2a(s);
var buf = new ArrayBuffer(s.length), view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
function arr2str(data/*:any*/)/*:string*/ {
if(Array.isArray(data)) return data.map(_chr).join("");
var o/*:Array<string>*/ = []; for(var i = 0; i < data.length; ++i) o[i] = _chr(data[i]); return o.join("");
}
var bconcat = function(bufs) { return [].concat.apply([], bufs); };
var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/g;

@ -1,5 +1,3 @@
function isval(x/*:?any*/)/*:boolean*/ { return x !== undefined && x !== null; }
function keys(o/*:any*/)/*:Array<any>*/ { return Object.keys(o); }
function evert_key(obj/*:any*/, key/*:string*/)/*:EvertType*/ {
@ -99,12 +97,6 @@ function cc2str(arr/*:Array<number>*/)/*:string*/ {
return o;
}
function str2cc(str) {
var o = [];
for(var i = 0; i != str.length; ++i) o.push(str.charCodeAt(i));
return o;
}
function dup(o/*:any*/)/*:any*/ {
if(typeof JSON != 'undefined' && !Array.isArray(o)) return JSON.parse(JSON.stringify(o));
if(typeof o != 'object' || o == null) return o;

@ -13,7 +13,7 @@ function getdatabin(data) {
if(data.asNodeBuffer && has_buf) return data.asNodeBuffer();
if(data._data && data._data.getContent) {
var o = data._data.getContent();
if(typeof o == "string") return str2cc(o);
if(typeof o == "string") return char_codes(o);
return Array.prototype.slice.call(o);
}
return null;

@ -1,6 +1,6 @@
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
var attregexg=/([^"\s?>\/]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex=/<[\/\?]?[a-zA-Z0-9:]+(?:\s+[^"\s?>\/]+=(?:"[^"]*"|'[^']*'|[^'">\s]+))*\s?[\/\?]?>/g;
var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex=/<[\/\?]?[a-zA-Z0-9:]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s]+))*\s?[\/\?]?>/g;
if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/)/*:any*/ {
@ -13,7 +13,8 @@ function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/)/*:any*/ {
if(m) for(i = 0; i != m.length; ++i) {
cc = m[i];
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
q = cc.substr(0,c);
q = cc.substr(0,c).trim();
while(cc.charCodeAt(c+1) == 32) ++c;
quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0;
v = cc.substring(c+1+quot, cc.length-quot);
for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
@ -84,7 +85,7 @@ function parsexmlbool(value/*:any*/, tag/*:?string*/)/*:boolean*/ {
}
}
var utf8read/*:StringConv*/ = function utf8reada(orig) {
var utf8read/*:StringConv*/ = function utf8reada(orig/*:string*/)/*:string*/ {
var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
while (i < orig.length) {
c = orig.charCodeAt(i++);
@ -101,7 +102,7 @@ var utf8read/*:StringConv*/ = function utf8reada(orig) {
return out;
};
var utf8write/*:StringConv*/ = function(orig) {
var utf8write/*:StringConv*/ = function(orig/*:string*/)/*:string*/ {
var out/*:Array<string>*/ = [], i = 0, c = 0, d = 0;
while(i < orig.length) {
c = orig.charCodeAt(i++);
@ -156,18 +157,18 @@ if(has_buf) {
// matches <foo>...</foo> extracts content
var matchtag = (function() {
var mtcache/*:{[k:string]:RegExp}*/ = ({}/*:any*/);
return function matchtag(f,g/*:?string*/)/*:RegExp*/ {
return function matchtag(f/*:string*/,g/*:?string*/)/*:RegExp*/ {
var t = f+"|"+(g||"");
if(mtcache[t]) return mtcache[t];
return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([\\s\\S]*?)</(?:\\w+:)?'+f+'>',((g||"")/*:any*/)));
};
})();
var htmldecode = (function() {
var entities = [
var htmldecode/*:{(s:string):string}*/ = (function() {
var entities/*:Array<[RegExp, string]>*/ = [
['nbsp', ' '], ['middot', '·'],
['quot', '"'], ['apos', "'"], ['gt', '>'], ['lt', '<'], ['amp', '&']
].map(function(x) { return [new RegExp('&' + x[0] + ';', "g"), x[1]]; });
].map(function(x/*:[string, string]*/) { return [new RegExp('&' + x[0] + ';', "g"), x[1]]; });
return function htmldecode(str/*:string*/)/*:string*/ {
var o = str.trim().replace(/\s+/g, " ").replace(/<\s*[bB][rR]\s*\/?>/g,"\n").replace(/<[^>]*>/g,"");
for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]);
@ -181,27 +182,27 @@ var vtregex = (function(){ var vt_cache = {};
return (vt_cache[bt] = new RegExp("<(?:vt:)?" + bt + ">([\\s\\S]*?)</(?:vt:)?" + bt + ">", 'g') );
};})();
var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^>]*)>([\s\S]*)</;
function parseVector(data, opts) {
function parseVector(data/*:string*/, opts)/*:Array<{v:string,t:string}>*/ {
var h = parsexmltag(data);
var matches = data.match(vtregex(h.baseType))||[];
var res = [];
var matches/*:Array<string>*/ = data.match(vtregex(h.baseType))||[];
var res/*:Array<any>*/ = [];
if(matches.length != h.size) {
if(opts.WTF) throw new Error("unexpected vector length " + matches.length + " != " + h.size);
return res;
}
matches.forEach(function(x) {
matches.forEach(function(x/*:string*/) {
var v = x.replace(vtvregex,"").match(vtmregex);
res.push({v:utf8read(v[2]), t:v[1]});
if(v) res.push({v:utf8read(v[2]), t:v[1]});
});
return res;
}
var wtregex = /(^\s|\s$|\n)/;
function writetag(f,g) {return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>';}
function writetag(f/*:string*/,g/*:string*/)/*:string*/ { return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>'; }
function wxt_helper(h)/*:string*/ { return keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join(""); }
function writextag(f,g,h) { return '<' + f + (isval(h) /*:: && h */? wxt_helper(h) : "") + (isval(g) /*:: && g */? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';}
function writextag(f/*:string*/,g/*:?string*/,h) { return '<' + f + ((h != null) ? wxt_helper(h) : "") + ((g != null) ? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';}
function write_w3cdtf(d/*:Date*/, t/*:?boolean*/)/*:string*/ { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } return ""; }

@ -35,6 +35,8 @@ var __utf8 = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { var ss=
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 __cpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var ___cpstr = __cpstr;
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;
@ -49,6 +51,7 @@ 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).replace(chr0,'')/*.replace(chr1,'!')*/; };
__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) : "";};
__cpstr = function cpstr_b(b/*:RawBytes|CFBlob*/, i/*:number*/) { if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___cpstr(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);};
@ -63,7 +66,8 @@ if(has_buf/*:: && typeof Buffer !== 'undefined'*/) {
if(typeof cptable !== 'undefined') {
__utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/) { return cptable.utils.decode(1200, b.slice(s,e)).replace(chr0, ''); };
__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)) : "";};
__lpstr = function(b/*:RawBytes|CFBlob*/,i/*:number*/) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_ansi, b.slice(i+4, i+4+len-1)) : "";};
__cpstr = 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)) : "";};
@ -98,9 +102,10 @@ function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
size = 2 * size; break;
/* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */
case 'lpstr': o = __lpstr(this, this.l); size = 5 + o.length; break;
case 'lpstr-ansi': o = __lpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break;
case 'lpstr-cp': o = __cpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break;
/* [MS-OLEDS] 2.1.5 LengthPrefixedUnicodeString */
case 'lpwstr': o = __lpwstr(this, this.l); size = 5 + o.length; if(o[o.length-1] == '\u0000') size += 2; break;
case 'lpwstr': o = __lpwstr(this, this.l); size = 4 + 2 * __readUInt32LE(this, this.l); break;
/* [MS-OFFCRYPTO] 2.1.2 Length-Prefixed Padded Unicode String (UNICODE-LP-P4) */
case 'lpp4': size = 4 + __readUInt32LE(this, this.l); o = __lpp4(this, this.l); if(size & 0x02) size += 2; break;
/* [MS-OFFCRYPTO] 2.1.3 Length-Prefixed UTF-8 String (UTF-8-LP-P4) */
@ -222,9 +227,6 @@ function prep_blob(blob, pos/*:number*/)/*:void*/ {
}
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; }
function new_buf(sz/*:number*/)/*:Block*/ {
var o = new_raw_buf(sz);

@ -20,14 +20,14 @@ function recordhopper(data, cb/*:RecordHopperCB*/, opts/*:?any*/) {
/* control buffer usage for fixed-length buffers */
function buf_array()/*:BufArray*/ {
var bufs = [], blksz = has_buf ? 256 : 2048;
var newblk = function ba_newblk(sz) {
var bufs/*:Array<Block>*/ = [], blksz = has_buf ? 256 : 2048;
var newblk = function ba_newblk(sz/*:number*/)/*:Block*/ {
var o/*:Block*/ = (new_buf(sz)/*:any*/);
prep_blob(o, 0);
return o;
};
var curbuf = newblk(blksz);
var curbuf/*:Block*/ = newblk(blksz);
var endbuf = function ba_endbuf() {
if(!curbuf) return;
@ -36,7 +36,7 @@ function buf_array()/*:BufArray*/ {
curbuf = null;
};
var next = function ba_next(sz) {
var next = function ba_next(sz/*:number*/)/*:Block*/ {
if(curbuf && sz < curbuf.length - curbuf.l) return curbuf;
endbuf();
return (curbuf = newblk(Math.max(sz+1, blksz)));
@ -56,7 +56,7 @@ function write_record(ba/*:BufArray*/, type/*:string*/, payload, length/*:?numbe
var t/*:number*/ = +XLSBRE[type], l;
if(isNaN(t)) return; // TODO: throw something here?
if(!length) length = XLSBRecordEnum[t].p || (payload||[]).length || 0;
l = 1 + (t >= 0x80 ? 1 : 0) + 1 + length;
l = 1 + (t >= 0x80 ? 1 : 0) + 1/* + length*/;
if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l;
var o = ba.next(l);
if(t <= 0x7F) o.write_shift(1, t);

@ -265,3 +265,19 @@ function write_FontFlags(font, o) {
return o;
}
/* [MS-OLEDS] 2.3.1 and 2.3.2 */
function parse_ClipboardFormatOrString(o, w/*:number*/)/*:string*/ {
// $FlowIgnore
var ClipFmt = {2:"BITMAP",3:"METAFILEPICT",8:"DIB",14:"ENHMETAFILE"};
var m/*:number*/ = o.read_shift(4);
switch(m) {
case 0x00000000: return "";
case 0xffffffff: case 0xfffffffe: return ClipFmt[o.read_shift(4)]||"";
}
if(m > 0x190) throw new Error("Unsupported Clipboard: " + m.toString(16));
o.l -= 4;
return o.read_shift(0, w == 1 ? "lpstr" : "lpwstr");
}
function parse_ClipboardFormatOrAnsiString(o) { return parse_ClipboardFormatOrString(o, 1); }
function parse_ClipboardFormatOrUnicodeString(o) { return parse_ClipboardFormatOrString(o, 2); }

@ -87,7 +87,7 @@ var SummaryPIDSI = {
/*::[*/0x0F/*::]*/: { n: 'WordCount', t: VT_I4 },
/*::[*/0x10/*::]*/: { n: 'CharCount', t: VT_I4 },
/*::[*/0x11/*::]*/: { n: 'Thumbnail', t: VT_CF },
/*::[*/0x12/*::]*/: { n: 'ApplicationName', t: VT_LPSTR },
/*::[*/0x12/*::]*/: { n: 'ApplicationName', t: VT_STRING },
/*::[*/0x13/*::]*/: { n: 'DocumentSecurity', t: VT_I4 },
/*::[*/0xFF/*::]*/: {}
};

@ -180,7 +180,7 @@ var CT_LIST = (function(){
xlsb: "application/vnd.ms-excel.styles"
}
};
keys(o).forEach(function(k) { if(!o[k].xlsm) o[k].xlsm = o[k].xlsx; });
keys(o).forEach(function(k) { ["xlsm", "xlam"].forEach(function(v) { if(!o[k][v]) o[k][v] = o[k].xlsx; }); });
keys(o).forEach(function(k){ keys(o[k]).forEach(function(v) { ct2type[o[k][v]] = k; }); });
return o;
})();

@ -84,7 +84,7 @@ var EXT_PROPS_XML_ROOT = writextag('Properties', null, {
});
function write_ext_props(cp, opts)/*:string*/ {
var o = [], p = {}, W = writextag;
var o/*:Array<string>*/ = [], p = {}, W = writextag;
if(!cp) cp = {};
cp.Application = "SheetJS";
o[o.length] = (XML_HEADER);

@ -39,7 +39,7 @@ function xlml_set_prop(Props, tag/*:string*/, val) {
}
function xlml_write_docprops(Props, opts) {
var o = [];
var o/*:Array<string>*/ = [];
keys(XLMLDocPropsMap).map(function(m) {
for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i];
for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i];
@ -60,7 +60,7 @@ function xlml_write_docprops(Props, opts) {
function xlml_write_custprops(Props, Custprops, opts) {
var BLACKLIST = ["Worksheets","SheetNames"];
var T = 'CustomDocumentProperties';
var o = [];
var o/*:Array<string>*/ = [];
if(Props) keys(Props).forEach(function(k) {
/*:: if(!Props) return; */
if(!Props.hasOwnProperty(k)) return;

@ -8,8 +8,9 @@ function parse_FILETIME(blob) {
/* [MS-OSHARED] 2.3.3.1.4 Lpstr */
function parse_lpstr(blob, type, pad/*:?number*/) {
var str = blob.read_shift(0, 'lpstr');
if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3;
var start = blob.l;
var str = blob.read_shift(0, 'lpstr-cp');
if(pad) while((blob.l - start) & 3) ++blob.l;
return str;
}
@ -32,15 +33,15 @@ function parse_VtString(blob, t/*:number*/, pad/*:?boolean*/) { return parse_VtS
function parse_VtUnalignedString(blob, t/*:number*/) { if(!t) throw new Error("VtUnalignedString must have positive length"); return parse_VtStringBase(blob, t, 0); }
/* [MS-OSHARED] 2.3.3.1.9 VtVecUnalignedLpstrValue */
function parse_VtVecUnalignedLpstrValue(blob) {
function parse_VtVecUnalignedLpstrValue(blob)/*:Array<string>*/ {
var length = blob.read_shift(4);
var ret = [];
for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr');
var ret/*:Array<string>*/ = [];
for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr-cp').replace(chr0,'');
return ret;
}
/* [MS-OSHARED] 2.3.3.1.10 VtVecUnalignedLpstr */
function parse_VtVecUnalignedLpstr(blob) {
function parse_VtVecUnalignedLpstr(blob)/*:Array<string>*/ {
return parse_VtVecUnalignedLpstrValue(blob);
}
@ -155,16 +156,17 @@ function parse_PropertySet(blob, PIDSI) {
var Offset = blob.read_shift(4);
Props[i] = [PropID, Offset + start_addr];
}
Props.sort(function(x,y) { return x[1] - y[1]; });
var PropH = {};
for(i = 0; i != NumProps; ++i) {
if(blob.l !== Props[i][1]) {
var fail = true;
if(i>0 && PIDSI) switch(PIDSI[Props[i-1][0]].t) {
case 0x02 /*VT_I2*/: if(blob.l +2 === Props[i][1]) { blob.l+=2; fail = false; } break;
case 0x02 /*VT_I2*/: if(blob.l+2 === Props[i][1]) { blob.l+=2; fail = false; } break;
case 0x50 /*VT_STRING*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
case 0x100C /*VT_VECTOR|VT_VARIANT*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
}
if(!PIDSI && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; }
if((!PIDSI||i==0) && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; }
if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i);
}
if(PIDSI) {
@ -326,7 +328,7 @@ function parse_XLUnicodeRichExtendedString(blob) {
var z = {};
if(fRichSt) cRun = blob.read_shift(2);
if(fExtSt) cbExtRst = blob.read_shift(4);
var encoding = (flags & 0x1) ? 'dbcs-cont' : 'sbcs-cont';
var encoding = width == 2 ? 'dbcs-cont' : 'sbcs-cont';
var msg = cch === 0 ? "" : blob.read_shift(cch, encoding);
if(fRichSt) blob.l += 4 * cRun; //TODO: parse this
if(fExtSt) blob.l += cbExtRst; //TODO: parse this
@ -398,15 +400,14 @@ function parse_URLMoniker(blob/*::, length, opts*/) {
/* [MS-OSHARED] 2.3.7.8 FileMoniker TODO: all fields */
function parse_FileMoniker(blob, length) {
var cAnti = blob.read_shift(2);
var ansiLength = blob.read_shift(4);
var ansiPath = blob.read_shift(ansiLength, 'cstr');
var ansiPath = blob.read_shift(0, 'lpstr-ansi');
var endServer = blob.read_shift(2);
var versionNumber = blob.read_shift(2);
var cbUnicodePathSize = blob.read_shift(4);
if(cbUnicodePathSize === 0) return ansiPath.replace(/\\/g,"/");
var cbUnicodePathBytes = blob.read_shift(4);
var usKeyValue = blob.read_shift(2);
var unicodePath = blob.read_shift(cbUnicodePathBytes>>1, 'utf16le').replace(chr0,"");
if(blob.read_shift(2) != 0xDEAD) throw new Error("Bad FileMoniker");
var sz = blob.read_shift(4);
if(sz === 0) return ansiPath.replace(/\\/g,"/");
var bytes = blob.read_shift(4);
if(blob.read_shift(2) != 3) throw new Error("Bad FileMoniker");
var unicodePath = blob.read_shift(bytes>>1, 'utf16le').replace(chr0,"");
return unicodePath;
}

@ -61,6 +61,14 @@ function parse_Ref8U(blob, length) {
var colLast = blob.read_shift(2);
return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}};
}
function write_Ref8U(r/*:Range*/, o) {
if(!o) o = new_buf(8);
o.write_shift(2, r.s.r);
o.write_shift(2, r.e.r);
o.write_shift(2, r.s.c);
o.write_shift(2, r.e.c);
return o;
}
/* 2.5.211 */
function parse_RefU(blob, length) {
@ -165,6 +173,7 @@ function write_BOF(wb/*:Workbook*/, t/*:number*/, o) {
case 'biff4': h = 0x0004; w = 6; break;
case 'biff3': h = 0x0003; w = 6; break;
case 'biff2': h = 0x0002; w = 4; break;
case 'xla': break;
default: throw new Error("unsupported BIFF version");
}
var out = new_buf(w);
@ -337,6 +346,22 @@ function write_Window1(opts) {
o.write_shift(2, 0x01f4);
return o;
}
/* 2.4.346 TODO */
function parse_Window2(blob, length, opts) {
if(opts && opts.biff >= 2 && opts.biff < 8) return {};
var f = blob.read_shift(2);
return { RTL: f & 0x40 };
}
function write_Window2(view) {
var o = new_buf(18), f = 0x6b6;
if(view && view.RTL) f |= 0x40;
o.write_shift(2, f);
o.write_shift(4, 0);
o.write_shift(4, 64);
o.write_shift(4, 0);
o.write_shift(4, 0);
return o;
}
/* 2.4.122 TODO */
function parse_Font(blob, length, opts) {
@ -624,7 +649,6 @@ function parse_ExternSheet(blob, length, opts) {
var o = [], target = blob.l + length, len = blob.read_shift(opts.biff > 8 ? 4 : 2);
while(len-- !== 0) o.push(parse_XTI(blob, opts.biff > 8 ? 12 : 6, opts));
// [iSupBook, itabFirst, itabLast];
var oo = [];
return o;
}
function parse_BIFF5ExternSheet(blob, length, opts) {
@ -689,12 +713,18 @@ function parse_Note(blob, length, opts) {
}
/* 2.4.168 */
function parse_MergeCells(blob, length) {
var merges = [];
function parse_MergeCells(blob, length)/*:Array<Range>*/ {
var merges/*:Array<Range>*/ = [];
var cmcs = blob.read_shift(2);
while (cmcs--) merges.push(parse_Ref8U(blob,length));
return merges;
}
function write_MergeCells(merges/*:Array<Range>*/) {
var o = new_buf(2 + merges.length * 8);
o.write_shift(2, merges.length);
for(var i = 0; i < merges.length; ++i) write_Ref8U(merges[i], o);
return o;
}
/* 2.4.181 TODO: parse all the things! */
function parse_Obj(blob, length, opts) {
@ -821,8 +851,8 @@ function write_HLinkTooltip(hl) {
}
/* 2.4.63 */
function parse_Country(blob, length) {
var o = [], d;
function parse_Country(blob, length)/*:[string|number, string|number]*/ {
var o = [0,0], d;
d = blob.read_shift(2); o[0] = CountryEnum[d] || d;
d = blob.read_shift(2); o[1] = CountryEnum[d] || d;
return o;

@ -86,10 +86,11 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
d.l+=2;
}
if(l7) d.l += 36;
var fields = [], field = {};
/*:: type DBFField = { name:string; len:number; type:string; } */
var fields/*:Array<DBFField>*/ = [], field/*:DBFField*/ = ({}/*:any*/);
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 = ({}/*:any*/);
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));
@ -210,7 +211,7 @@ function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
if(headers.indexOf(headers[i] + "_" + j) == -1) { headers[i] += "_" + j; break; }
}
var range = safe_decode_range(ws['!ref']);
var coltypes = [];
var coltypes/*:Array<string>*/ = [];
for(i = 0; i <= range.e.c - range.s.c; ++i) {
var col/*:Array<any>*/ = [];
for(j=0; j < data.length; ++j) {
@ -307,10 +308,10 @@ var SYLK = (function() {
throw new Error("Unrecognized type " + opts.type);
}
function sylk_to_aoa_str(str/*:string*/, opts)/*:[AOA, Worksheet]*/ {
var records = str.split(/[\n\r]+/), R = -1, C = -1, ri = 0, rj = 0, arr = [];
var formats = [];
var next_cell_format = null;
var sht = {}, rowinfo = [], colinfo = [], cw = [];
var records = str.split(/[\n\r]+/), R = -1, C = -1, ri = 0, rj = 0, arr/*:AOA*/ = [];
var formats/*:Array<string>*/ = [];
var next_cell_format/*:string|null*/ = null;
var sht = {}, rowinfo/*:Array<RowInfo>*/ = [], colinfo/*:Array<ColInfo>*/ = [], cw/*:Array<string>*/ = [];
var Mval = 0, j;
for (; ri !== records.length; ++ri) {
Mval = 0;
@ -484,7 +485,7 @@ var DIF = (function() {
throw new Error("Unrecognized type " + opts.type);
}
function dif_to_aoa_str(str/*:string*/, opts)/*:AOA*/ {
var records = str.split('\n'), R = -1, C = -1, ri = 0, arr = [];
var records = str.split('\n'), R = -1, C = -1, ri = 0, arr/*:AOA*/ = [];
for (; ri !== records.length; ++ri) {
if (records[ri].trim() === 'BOT') { arr[++R] = []; C = 0; continue; }
if (R < 0) continue;
@ -585,7 +586,7 @@ var ETH = (function() {
function encode(s/*:string*/)/*:string*/ { return s.replace(/\\/g, "\\b").replace(/:/g, "\\c").replace(/\n/g,"\\n"); }
function eth_to_aoa(str/*:string*/, opts)/*:AOA*/ {
var records = str.split('\n'), R = -1, C = -1, ri = 0, arr = [];
var records = str.split('\n'), R = -1, C = -1, ri = 0, arr/*:AOA*/ = [];
for (; ri !== records.length; ++ri) {
var record = records[ri].trim().split(":");
if(record[0] !== 'cell') continue;
@ -632,7 +633,7 @@ var ETH = (function() {
function sheet_to_eth_data(ws/*:Worksheet*/)/*:string*/ {
if(!ws || !ws['!ref']) return "";
var o = [], oo = [], cell, coord;
var o/*:Array<string>*/ = [], oo/*:Array<string>*/ = [], cell, coord = "";
var r = decode_range(ws['!ref']);
var dense = Array.isArray(ws);
for(var R = r.s.r; R <= r.e.r; ++R) {
@ -648,12 +649,12 @@ var ETH = (function() {
else { oo[2]='vtf'; oo[3]='n'; oo[4]=cell.v; oo[5]=encode(cell.f); }
break;
case 'b':
oo[2] = 'vt'+(cell.f?'f':'c'); oo[3]='nl'; oo[4]=+!!cell.v;
oo[2] = 'vt'+(cell.f?'f':'c'); oo[3]='nl'; oo[4]=cell.v?"1":"0";
oo[5] = encode(cell.f||(cell.v?'TRUE':'FALSE'));
break;
case 'd':
var t = datenum(parseDate(cell.v));
oo[2] = 'vtc'; oo[3] = 'nd'; oo[4] = t;
oo[2] = 'vtc'; oo[3] = 'nd'; oo[4] = ""+t;
oo[5] = cell.w || SSF.format(cell.z || SSF._table[14], t);
break;
case 'e': continue;
@ -840,7 +841,7 @@ var PRN = (function() {
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 = [];
var oo/*:Array<string>*/ = [];
for(var C = r.s.c; C <= r.e.c; ++C) {
var coord = encode_cell({r:R,c:C});
cell = dense ? (ws[R]||[])[C] : ws[coord];

@ -1,27 +1,3 @@
/* 18.4.1 charset to codepage mapping */
var CS2CP = ({
/*::[*/0/*::]*/: 1252, /* ANSI */
/*::[*/1/*::]*/: 65001, /* DEFAULT */
/*::[*/2/*::]*/: 65001, /* SYMBOL */
/*::[*/77/*::]*/: 10000, /* MAC */
/*::[*/128/*::]*/: 932, /* SHIFTJIS */
/*::[*/129/*::]*/: 949, /* HANGUL */
/*::[*/130/*::]*/: 1361, /* JOHAB */
/*::[*/134/*::]*/: 936, /* GB2312 */
/*::[*/136/*::]*/: 950, /* CHINESEBIG5 */
/*::[*/161/*::]*/: 1253, /* GREEK */
/*::[*/162/*::]*/: 1254, /* TURKISH */
/*::[*/163/*::]*/: 1258, /* VIETNAMESE */
/*::[*/177/*::]*/: 1255, /* HEBREW */
/*::[*/178/*::]*/: 1256, /* ARABIC */
/*::[*/186/*::]*/: 1257, /* BALTIC */
/*::[*/204/*::]*/: 1251, /* RUSSIAN */
/*::[*/222/*::]*/: 874, /* THAI */
/*::[*/238/*::]*/: 1250, /* EASTEUROPE */
/*::[*/255/*::]*/: 1252, /* OEM */
/*::[*/69/*::]*/: 6969 /* MISC */
}/*:any*/);
/* Parse a list of <r> tags */
var parse_rs = (function parse_rs_factory() {
var tregex = matchtag("t"), rpregex = matchtag("rPr"), rregex = /<(?:\w+:)?r>/g, rend = /<\/(?:\w+:)?r>/, nlregex = /\r\n/g;
@ -122,7 +98,7 @@ var parse_rs = (function parse_rs_factory() {
if(y[0].charCodeAt(1) !== 47) throw 'Unrecognized rich format ' + y[0];
}
}
var style = [];
var style/*:Array<string>*/ = [];
if(font.u) style.push("text-decoration: underline;");
if(font.uval) style.push("text-underline-style:" + font.uval + ";");
@ -145,14 +121,14 @@ var parse_rs = (function parse_rs_factory() {
/* 18.4.4 r CT_RElt */
function parse_r(r) {
var terms = [[],"",[]];
var terms/*:[Array<string>, string, Array<string>]*/ = [[],"",[]];
/* 18.4.12 t ST_Xstring */
var t = r.match(tregex), cp = 65001;
if(!isval(t)/*:: || !t*/) return "";
if(!t) return "";
terms[1] = t[1];
var rpr = r.match(rpregex);
if(isval(rpr)/*:: && rpr*/) cp = parse_rpr(rpr[1], terms[0], terms[2]);
if(rpr) cp = parse_rpr(rpr[1], terms[0], terms[2]);
return terms[0].join("") + terms[1].replace(nlregex,'<br/>') + terms[2].join("");
}
@ -196,7 +172,7 @@ function parse_sst_xml(data/*:string*/, opts)/*:SST*/ {
if(!data) return s;
/* 18.4.9 sst CT_Sst */
var sst = data.match(sstr0);
if(isval(sst)/*:: && sst*/) {
if(sst) {
ss = sst[2].replace(sstr1,"").split(sstr2);
for(var i = 0; i != ss.length; ++i) {
var o = parse_si(ss[i].trim(), opts);

@ -1,6 +1,6 @@
function _JS2ANSI(str/*:string*/)/*:Array<number>*/ {
if(typeof cptable !== 'undefined') return cptable.utils.encode(1252, str);
var o = [], oo = str.split("");
if(typeof cptable !== 'undefined') return cptable.utils.encode(current_ansi, str);
var o/*:Array<number>*/ = [], oo = str.split("");
for(var i = 0; i < oo.length; ++i) o[i] = oo[i].charCodeAt(0);
return o;
}
@ -31,14 +31,9 @@ function parse_DataSpaceMapEntry(blob) {
var end = blob.l + len - 4;
var o = {};
var cnt = blob.read_shift(4);
var comps = [];
while(cnt-- > 0) {
/* [MS-OFFCRYPTO] 2.1.6.2 DataSpaceReferenceComponent Structure */
var rc = {};
rc.t = blob.read_shift(4);
rc.v = blob.read_shift(0, 'lpp4');
comps.push(rc);
}
var comps/*:Array<{t:number, v:string}>*/ = [];
/* [MS-OFFCRYPTO] 2.1.6.2 DataSpaceReferenceComponent Structure */
while(cnt-- > 0) comps.push({ t: blob.read_shift(4), v: blob.read_shift(0, 'lpp4') });
o.name = blob.read_shift(0, 'lpp4');
o.comps = comps;
if(blob.l != end) throw new Error("Bad DataSpaceMapEntry: " + blob.l + " != " + end);
@ -55,8 +50,8 @@ function parse_DataSpaceMap(blob, length) {
}
/* [MS-OFFCRYPTO] 2.1.7 DataSpaceDefinition */
function parse_DataSpaceDefinition(blob, length) {
var o = [];
function parse_DataSpaceDefinition(blob, length)/*:Array<string>*/ {
var o/*:Array<string>*/ = [];
blob.l += 4; // must be 0x8
var cnt = blob.read_shift(4);
while(cnt-- > 0) o.push(blob.read_shift(0, 'lpp4'));

@ -321,7 +321,7 @@ function parse_cellXfs(t, styles, opts) {
}
function write_cellXfs(cellXfs)/*:string*/ {
var o = [];
var o/*:Array<string>*/ = [];
o[o.length] = (writextag('cellXfs',null));
cellXfs.forEach(function(c) { o[o.length] = (writextag('xf', null, c)); });
o[o.length] = ("</cellXfs>");

@ -206,7 +206,7 @@ function parse_sty_bin(data, themes, opts) {
styles.CellXf = [];
styles.Fonts = [];
var state = [];
var state/*:Array<string>*/ = [];
var pass = false;
recordhopper(data, function hopper_sty(val, R_n, RT) {
switch(RT) {

@ -1,8 +1,15 @@
/* [MS-XLS] 2.4.326 TODO: payload is a zip file */
function parse_Theme(blob, length, opts) {
var end = blob.l + length;
var dwThemeVersion = blob.read_shift(4);
if(dwThemeVersion === 124226) return;
blob.l += length-4;
if(!opts.cellStyles || !jszip) { blob.l = end; return; }
var data = blob.slice(blob.l);
blob.l = end;
var zip; try { zip = new jszip(data); } catch(e) { return; }
var themeXML = getzipstr(zip, "theme/theme/theme1.xml", true);
if(!themeXML) return;
return parse_theme_xml(themeXML, opts);
}
/* 2.5.49 */
@ -35,7 +42,7 @@ function parse_XFExtGradient(blob, length) {
}
/* 2.5.108 */
function parse_ExtProp(blob, length) {
function parse_ExtProp(blob, length)/*:Array<any>*/ {
var extType = blob.read_shift(2);
var cb = blob.read_shift(2);
var o = [extType];
@ -57,7 +64,7 @@ function parse_XFExt(blob, length) {
var ixfe = blob.read_shift(2);
blob.l += 2;
var cexts = blob.read_shift(2);
var ext = [];
var ext/*:AOA*/ = [];
while(cexts-- > 0) ext.push(parse_ExtProp(blob, end-blob.l));
return {ixfe:ixfe, ext:ext};
}

@ -18,9 +18,9 @@ function parse_comments(zip, dirComments, sheets, sheetRels, opts) {
}
}
function insertCommentsIntoSheet(sheetName, sheet, comments) {
function insertCommentsIntoSheet(sheetName, sheet, comments/*:Array<RawComment>*/) {
var dense = Array.isArray(sheet);
var cell, r;
var cell/*:Cell*/, r;
comments.forEach(function(comment) {
if(dense) {
r = decode_cell(comment.ref);
@ -42,7 +42,7 @@ function insertCommentsIntoSheet(sheetName, sheet, comments) {
}
if (!cell.c) cell.c = [];
var o = ({a: comment.author, t: comment.t, r: comment.r}/*:any*/);
var o/*:Comment*/ = ({a: comment.author, t: comment.t, r: comment.r});
if(comment.h) o.h = comment.h;
cell.c.push(o);
});

@ -1,9 +1,9 @@
/* 18.7 Comments */
function parse_comments_xml(data/*:string*/, opts)/*:Array<Comment>*/ {
function parse_comments_xml(data/*:string*/, opts)/*:Array<RawComment>*/ {
/* 18.7.6 CT_Comments */
if(data.match(/<(?:\w+:)?comments *\/>/)) return [];
var authors = [];
var commentList = [];
var authors/*:Array<string>*/ = [];
var commentList/*:Array<RawComment>*/ = [];
var authtag = data.match(/<(?:\w+:)?authors>([\s\S]*)<\/(?:\w+:)?authors>/);
if(authtag && authtag[1]) authtag[1].split(/<\/\w*:?author>/).forEach(function(x) {
if(x === "" || x.trim() === "") return;
@ -16,7 +16,7 @@ function parse_comments_xml(data/*:string*/, opts)/*:Array<Comment>*/ {
var cm = x.match(/<(?:\w+:)?comment[^>]*>/);
if(!cm) return;
var y = parsexmltag(cm[0]);
var comment/*:Comment*/ = ({ author: y.authorId && authors[y.authorId] || "sheetjsghost", ref: y.ref, guid: y.guid }/*:any*/);
var comment/*:RawComment*/ = ({ author: y.authorId && authors[y.authorId] || "sheetjsghost", ref: y.ref, guid: y.guid }/*:any*/);
var cell = decode_cell(y.ref);
if(opts.sheetRows && opts.sheetRows <= cell.r) return;
var textMatch = x.match(/<(?:\w+:)?text>([\s\S]*)<\/(?:\w+:)?text>/);
@ -34,7 +34,7 @@ var CMNT_XML_ROOT = writextag('comments', null, { 'xmlns': XMLNS.main[0] });
function write_comments_xml(data, opts) {
var o = [XML_HEADER, CMNT_XML_ROOT];
var iauthor = [];
var iauthor/*:Array<string>*/ = [];
o.push("<authors>");
data.map(function(x) { return x[1]; }).forEach(function(comment) {
comment.map(function(x) { return escapexml(x.a); }).forEach(function(a) {

@ -24,9 +24,9 @@ var parse_BrtCommentAuthor = parse_XLWideString;
function write_BrtCommentAuthor(data) { return write_XLWideString(data.slice(0, 54)); }
/* [MS-XLSB] 2.1.7.8 Comments */
function parse_comments_bin(data, opts) {
var out = [];
var authors = [];
function parse_comments_bin(data, opts)/*:Array<RawComment>*/ {
var out/*:Array<RawComment>*/ = [];
var authors/*:Array<string>*/ = [];
var c = {};
var pass = false;
recordhopper(data, function hopper_cmnt(val, R_n, RT) {
@ -65,33 +65,32 @@ function parse_comments_bin(data, opts) {
function write_comments_bin(data, opts) {
var ba = buf_array();
var iauthor = [];
var iauthor/*:Array<string>*/ = [];
write_record(ba, "BrtBeginComments");
{ /* COMMENTAUTHORS */
write_record(ba, "BrtBeginCommentAuthors");
data.forEach(function(comment) {
comment[1].forEach(function(c) {
if(iauthor.indexOf(c.a) > -1) return;
iauthor.push(c.a.slice(0,54));
write_record(ba, "BrtCommentAuthor", write_BrtCommentAuthor(c.a));
});
write_record(ba, "BrtBeginCommentAuthors");
data.forEach(function(comment) {
comment[1].forEach(function(c) {
if(iauthor.indexOf(c.a) > -1) return;
iauthor.push(c.a.slice(0,54));
write_record(ba, "BrtCommentAuthor", write_BrtCommentAuthor(c.a));
});
write_record(ba, "BrtEndCommentAuthors");
}
{ /* COMMENTLIST */
write_record(ba, "BrtBeginCommentList");
data.forEach(function(comment) {
comment[1].forEach(function(c) {
c.iauthor = iauthor.indexOf(c.a);
var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])};
write_record(ba, "BrtBeginComment", write_BrtBeginComment([range, c]));
if(c.t && c.t.length > 0) write_record(ba, "BrtCommentText", write_BrtCommentText(c));
write_record(ba, "BrtEndComment");
delete c.iauthor;
});
});
write_record(ba, "BrtEndCommentAuthors");
write_record(ba, "BrtBeginCommentList");
data.forEach(function(comment) {
comment[1].forEach(function(c) {
c.iauthor = iauthor.indexOf(c.a);
var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])};
write_record(ba, "BrtBeginComment", write_BrtBeginComment([range, c]));
if(c.t && c.t.length > 0) write_record(ba, "BrtCommentText", write_BrtCommentText(c));
write_record(ba, "BrtEndComment");
delete c.iauthor;
});
write_record(ba, "BrtEndCommentList");
}
});
write_record(ba, "BrtEndCommentList");
write_record(ba, "BrtEndComments");
return ba.end();
}

@ -16,3 +16,5 @@ function fill_vba_xls(cfb/*:CFBContainer*/, vba/*:CFBContainer*/)/*:void*/ {
});
}
var VBAFMTS = [ "xlsb", "xlsm", "xlam", "biff8", "xla" ];

@ -46,3 +46,7 @@ function fuzzyfmla(f/*:string*/)/*:boolean*/ {
if(f.length == 1) return false;
return true;
}
function _xlfn(f/*:string*/)/*:string*/ {
return f.replace(/_xlfn\./g,"");
}

@ -149,10 +149,10 @@ function parse_PtgAttrBaxcel(blob, length) {
}
/* 2.5.198.34 */
function parse_PtgAttrChoose(blob, length, opts) {
function parse_PtgAttrChoose(blob, length, opts)/*:Array<number>*/ {
blob.l +=2;
var offset = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
var o = [];
var o/*:Array<number>*/ = [];
/* offset is 1 less than the number of elements */
for(var i = 0; i <= offset; ++i) o.push(blob.read_shift(opts && opts.biff == 2 ? 1 : 2));
return o;
@ -318,7 +318,7 @@ function parse_SerAr(blob, biff/*:number*/) {
/* 2.5.198.61 */
function parse_PtgExtraMem(blob, cce) {
var count = blob.read_shift(2);
var out = [];
var out/*:Array<Range>*/ = [];
for(var i = 0; i != count; ++i) out.push(parse_Ref8U(blob, 8));
return out;
}
@ -335,7 +335,7 @@ function parse_PtgExtraArray(blob, length, opts) {
}
if(opts.biff >= 2 && opts.biff < 8) { --rows; if(--cols == 0) cols = 0x100; }
// $FlowIgnore
for(var i = 0, o/*:Array<Array<any> >*/=[]; i != rows && (o[i] = []); ++i)
for(var i = 0, o/*:Array<Array<any>>*/ = []; i != rows && (o[i] = []); ++i)
for(var j = 0; j != cols; ++j) o[i][j] = parse_SerAr(blob, opts.biff);
return o;
}
@ -655,10 +655,10 @@ function parse_Rgce(blob, length, opts) {
return ptgs;
}
function stringify_array(f/*:Array<Array<any>>*/)/*:string*/ {
var o = [];
function stringify_array(f/*:Array<Array<string>>*/)/*:string*/ {
var o/*:Array<string>*/ = [];
for(var i = 0; i < f.length; ++i) {
var x = f[i], r = [];
var x = f[i], r/*:Array<string>*/ = [];
for(var j = 0; j < x.length; ++j) {
var y = x[j];
if(y) switch(y[0]) {
@ -713,10 +713,10 @@ function get_ixti_raw(supbooks, ixti/*:number*/, opts)/*:string*/ {
return XTI[1] == XTI[2] ? o : o + ":" + supbooks.SheetNames[XTI[2]];
case 0x0166: /* 'BrtSupSame' */
if(opts.SID != null) return supbooks.SheetNames[opts.SID];
return "SH33TJSERR" + supbooks[XTI[0]][0];
return "SH33TJSSAME" + supbooks[XTI[0]][0];
case 0x0163: /* 'BrtSupBookSrc' */
/* falls through */
default: return "SH33TJSERR" + supbooks[XTI[0]][0];
default: return "SH33TJSSRC" + supbooks[XTI[0]][0];
}
switch(supbooks[XTI[0]][0][0]) {
case 0x0401:
@ -863,7 +863,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
/* f[1] = type, 0, nameindex */
nameidx = (f[1][2]/*:any*/);
var lbl = (supbooks.names||[])[nameidx-1] || (supbooks[0]||[])[nameidx];
var name = lbl ? lbl.Name : "SH33TJSERR7" + String(nameidx);
var name = lbl ? lbl.Name : "SH33TJSNAME" + String(nameidx);
if(name in XLSXFutureFunctions) name = XLSXFutureFunctions[name];
stack.push(name);
break;
@ -944,7 +944,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
break;
case 'PtgArray': /* 2.5.198.32 TODO */
stack.push("{" + stringify_array(f[1]) + "}");
stack.push("{" + stringify_array(/*::(*/f[1]/*:: :any)*/) + "}");
break;
case 'PtgMemArea': /* 2.5.198.70 TODO: confirm this is a non-display */

@ -1158,6 +1158,7 @@ var XLSXFutureFunctions = {
"_xlfn.CHISQ.INV.RT": "CHISQ.INV.RT",
"_xlfn.CHISQ.TEST": "CHISQ.TEST",
"_xlfn.COMBINA": "COMBINA",
"_xlfn.CONCAT": "CONCAT",
"_xlfn.CONFIDENCE.NORM": "CONFIDENCE.NORM",
"_xlfn.CONFIDENCE.T": "CONFIDENCE.T",
"_xlfn.COT": "COT",
@ -1181,6 +1182,11 @@ var XLSXFutureFunctions = {
"_xlfn.FILTERXML": "FILTERXML",
"_xlfn.FLOOR.MATH": "FLOOR.MATH",
"_xlfn.FLOOR.PRECISE": "FLOOR.PRECISE",
"_xlfn.FORECAST.ETS": "FORECAST.ETS",
"_xlfn.FORECAST.ETS.CONFINT": "FORECAST.ETS.CONFINT",
"_xlfn.FORECAST.ETS.SEASONALITY": "FORECAST.ETS.SEASONALITY",
"_xlfn.FORECAST.ETS.STAT": "FORECAST.ETS.STAT",
"_xlfn.FORECAST.LINEAR": "FORECAST.LINEAR",
"_xlfn.FORMULATEXT": "FORMULATEXT",
"_xlfn.GAMMA": "GAMMA",
"_xlfn.GAMMA.DIST": "GAMMA.DIST",
@ -1188,8 +1194,8 @@ var XLSXFutureFunctions = {
"_xlfn.GAMMALN.PRECISE": "GAMMALN.PRECISE",
"_xlfn.GAUSS": "GAUSS",
"_xlfn.HYPGEOM.DIST": "HYPGEOM.DIST",
"_xlfn.IFNA": "IFNA",
"_xlfn.IFERROR": "IFERROR",
"_xlfn.IFNA": "IFNA",
"_xlfn.IMCOSH": "IMCOSH",
"_xlfn.IMCOT": "IMCOT",
"_xlfn.IMCSC": "IMCSC",
@ -1203,6 +1209,8 @@ var XLSXFutureFunctions = {
"_xlfn.ISOWEEKNUM": "ISOWEEKNUM",
"_xlfn.LOGNORM.DIST": "LOGNORM.DIST",
"_xlfn.LOGNORM.INV": "LOGNORM.INV",
"_xlfn.MAXIFS": "MAXIFS",
"_xlfn.MINIFS": "MINIFS",
"_xlfn.MODE.MULT": "MODE.MULT",
"_xlfn.MODE.SNGL": "MODE.SNGL",
"_xlfn.MUNIT": "MUNIT",
@ -1242,6 +1250,7 @@ var XLSXFutureFunctions = {
"_xlfn.T.INV": "T.INV",
"_xlfn.T.INV.2T": "T.INV.2T",
"_xlfn.T.TEST": "T.TEST",
"_xlfn.TEXTJOIN": "TEXTJOIN",
"_xlfn.UNICHAR": "UNICHAR",
"_xlfn.UNICODE": "UNICODE",
"_xlfn.VAR.P": "VAR.P",

@ -37,12 +37,13 @@ function default_margins(margins/*:Margins*/, mode/*:?string*/) {
if(margins.footer == null) margins.footer = defs[5];
}
function get_cell_style(styles, cell, opts) {
function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) {
var z = opts.revssf[cell.z != null ? cell.z : "General"];
var i = 0x3c, len = styles.length;
if(z == null && opts.ssf) {
for(; i < 0x188; ++i) if(opts.ssf[i] == null) {
SSF.load(cell.z, i);
// $FlowIgnore
opts.ssf[i] = cell.z;
opts.revssf[cell.z] = z = i;
break;
@ -60,7 +61,7 @@ function get_cell_style(styles, cell, opts) {
return len;
}
function safe_format(p, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) {
function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) {
if(p.t === 'z') return;
if(p.t === 'd' && typeof p.v === 'string') p.v = parseDate(p.v);
try {

@ -1,4 +1,4 @@
function parse_ws_xml_dim(ws, s) {
function parse_ws_xml_dim(ws/*:Worksheet*/, s/*:string*/) {
var d = safe_decode_range(s);
if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d);
}
@ -10,8 +10,9 @@ var colregex = /<(?:\w:)?col[^>]*[\/]?>/g;
var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g;
var sheetprregex = /<(?:\w:)?sheetPr(?:[^>a-z][^>]*)?\/>/;
var svsregex = /<(?:\w:)?sheetViews[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetViews)>/;
/* 18.3 Worksheets */
function parse_ws_xml(data/*:?string*/, opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ {
function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ {
if(!data) return data;
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
@ -30,7 +31,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx, rels, wb/*:WBWBProps*/, theme
var sheetPr = data1.match(sheetprregex);
if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
/* 18.3.1.35 dimension CT_SheetDimension ? */
/* 18.3.1.35 dimension CT_SheetDimension */
// $FlowIgnore
var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
if(ridx > 0) {
@ -38,8 +39,12 @@ function parse_ws_xml(data/*:?string*/, opts, idx, rels, wb/*:WBWBProps*/, theme
if(ref) parse_ws_xml_dim(s, ref[1]);
}
/* 18.3.1.88 sheetViews CT_SheetViews */
var svs = data1.match(svsregex);
if(svs && svs[1]) parse_ws_xml_sheetviews(svs[1], wb);
/* 18.3.1.17 cols CT_Cols */
var columns = [];
var columns/*:Array<ColInfo>*/ = [];
if(opts.cellStyles) {
/* 18.3.1.13 col CT_Col */
var cols = data1.match(colregex);
@ -54,10 +59,10 @@ function parse_ws_xml(data/*:?string*/, opts, idx, rels, wb/*:WBWBProps*/, theme
if(afilter) s['!autofilter'] = parse_ws_xml_autofilter(afilter[0]);
/* 18.3.1.55 mergeCells CT_MergeCells */
var mergecells = [];
var merges = data2.match(mergecregex);
if(merges) for(ridx = 0; ridx != merges.length; ++ridx)
mergecells[ridx] = safe_decode_range(merges[ridx].substr(merges[ridx].indexOf("\"")+1));
var merges/*:Array<Range>*/ = [];
var _merge = data2.match(mergecregex);
if(_merge) for(ridx = 0; ridx != _merge.length; ++ridx)
merges[ridx] = safe_decode_range(_merge[ridx].substr(_merge[ridx].indexOf("\"")+1));
/* 18.3.1.48 hyperlinks CT_Hyperlinks */
var hlink = data2.match(hlinkregex);
@ -81,11 +86,11 @@ function parse_ws_xml(data/*:?string*/, opts, idx, rels, wb/*:WBWBProps*/, theme
}
}
if(columns.length > 0) s["!cols"] = columns;
if(mergecells.length > 0) s["!merges"] = mergecells;
if(merges.length > 0) s["!merges"] = merges;
return s;
}
function write_ws_xml_merges(merges) {
function write_ws_xml_merges(merges/*:Array<Range>*/)/*:string*/ {
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]) + '"/>';
@ -154,7 +159,7 @@ function parse_ws_xml_margins(margin) {
});
return o;
}
function write_ws_xml_margins(margin) {
function write_ws_xml_margins(margin)/*:string*/ {
default_margins(margin);
return writextag('pageMargins', null, margin);
}
@ -182,7 +187,7 @@ function write_ws_xml_cols(ws, cols)/*:string*/ {
return o.join("");
}
function parse_ws_xml_autofilter(data) {
function parse_ws_xml_autofilter(data/*:string*/) {
var o = { ref: (data.match(/ref="([^"]*)"/)||[])[1]};
return o;
}
@ -192,6 +197,17 @@ function write_ws_xml_autofilter(data)/*:string*/ {
/* 18.3.1.88 sheetViews CT_SheetViews */
/* 18.3.1.87 sheetView CT_SheetView */
var sviewregex = /<(?:\w:)?sheetView(?:[^>a-z][^>]*)?\/>/;
function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) {
(data.match(sviewregex)||[]).forEach(function(r/*:string*/) {
var tag = parsexmltag(r);
if(parsexmlbool(tag.rightToLeft)) {
if(!wb.Views) wb.Views = [{}];
if(!wb.Views[0]) wb.Views[0] = {};
wb.Views[0].RTL = true;
}
});
}
function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
var sview = {workbookViewId:"0"};
// $FlowIgnore
@ -199,7 +215,7 @@ function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
return writextag("sheetViews", writextag("sheetView", null, sview), {});
}
function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb)/*:string*/ {
if(cell.v === undefined && cell.f === undefined || cell.t === 'z') return "";
var vv = "";
var oldt = cell.t, oldv = cell.v;
@ -244,22 +260,22 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
return writextag('c', v, o);
}
var parse_ws_xml_data = (function parse_ws_xml_data_factory() {
var parse_ws_xml_data = (function() {
var cellregex = /<(?:\w+:)?c[ >]/, rowregex = /<\/(?:\w+:)?row>/;
var rregex = /r=["']([^"']*)["']/, isregex = /<(?:\w+:)?is>([\S\s]*?)<\/(?:\w+:)?is>/;
var refregex = /ref=["']([^"']*)["']/;
var match_v = matchtag("v"), match_f = matchtag("f");
return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
var ri = 0, x = "", cells = [], cref = [], idx=0, i=0, cc=0, d="", p/*:any*/;
return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles) {
var ri = 0, x = "", cells/*:Array<string>*/ = [], cref/*:?Array<string>*/ = [], idx=0, i=0, cc=0, d="", p/*:any*/;
var tag, tagr = 0, tagc = 0;
var sstr, ftag;
var fmtid = 0, fillid = 0;
var do_format = Array.isArray(styles.CellXf), cf;
var arrayf = [];
var arrayf/*:Array<[Range, string]>*/ = [];
var sharedf = [];
var dense = Array.isArray(s);
var rows = [], rowobj = {}, rowrite = false;
var rows/*:Array<RowInfo>*/ = [], rowobj = {}, rowrite = false;
for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
x = marr[mt].trim();
var xlen = x.length;
@ -307,14 +323,14 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
if(opts.cellFormula) {
if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') {
/* TODO: match against XLSXFutureFunctions */
p.f=unescapexml(utf8read(cref[1])).replace(/_xlfn\./,"");
p.f=_xlfn(unescapexml(utf8read(cref[1])));
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
p.F = (d.match(refregex)||[])[1];
if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
} else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
// TODO: parse formula
ftag = parsexmltag(cref[0]);
sharedf[parseInt(ftag.si, 10)] = [ftag, unescapexml(utf8read(cref[1]))];
sharedf[parseInt(ftag.si, 10)] = [ftag, _xlfn(unescapexml(utf8read(cref[1])))];
}
} else if((cref=d.match(/<f[^>]*\/>/))) {
ftag = parsexmltag(cref[0]);
@ -400,7 +416,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 o/*:Array<string>*/ = [], r/*:Array<string>*/ = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols/*:Array<string>*/ = [], 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);

@ -335,6 +335,11 @@ function write_BrtMargins(margins/*:Margins*/, o) {
}
/* [MS-XLSB] 2.4.292 BrtBeginWsView */
function parse_BrtBeginWsView(data, length, opts) {
var f = data.read_shift(2);
data.l += 28;
return { RTL: f & 0x20 };
}
function write_BrtBeginWsView(ws, Workbook, o) {
if(o == null) o = new_buf(30);
var f = 0x39c;
@ -385,7 +390,7 @@ function write_BrtSheetProtection(sp, o) {
}
/* [MS-XLSB] 2.1.7.61 Worksheet */
function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles)/*:Worksheet*/ {
function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/*:Worksheet*/ {
if(!data) return data;
var opts = _opts || {};
if(!rels) rels = {'!id':{}};
@ -397,24 +402,24 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles)/*:Worksheet*/
var pass = false, end = false;
var row, p, cf, R, C, addr, sstr, rr, cell/*:Cell*/;
var mergecells = [];
var merges/*:Array<Range>*/ = [];
opts.biff = 12;
opts['!row'] = 0;
var ai = 0, af = false;
var array_formulae = [];
var shared_formulae = {};
var arrayf/*:Array<[Range, string]>*/ = [];
var sharedf = {};
var supbooks = opts.supbooks || ([[]]/*:any*/);
supbooks.sharedf = shared_formulae;
supbooks.arrayf = array_formulae;
supbooks.sharedf = sharedf;
supbooks.arrayf = arrayf;
supbooks.SheetNames = wb.SheetNames || wb.Sheets.map(function(x) { return x.name; });
if(!opts.supbooks) {
opts.supbooks = supbooks;
for(var i = 0; i < wb.Names.length; ++i) supbooks[0][i+1] = wb.Names[i];
if(wb.Names) for(var i = 0; i < wb.Names.length; ++i) supbooks[0][i+1] = wb.Names[i];
}
var colinfo = [], rowinfo = [];
var colinfo/*:Array<ColInfo>*/ = [], rowinfo/*:Array<RowInfo>*/ = [];
var seencol = false;
recordhopper(data, function ws_parse(val, R_n, RT) {
@ -457,8 +462,8 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles)/*:Worksheet*/
else s[encode_col(C) + rr] = p;
if(opts.cellFormula) {
af = false;
for(ai = 0; ai < array_formulae.length; ++ai) {
var aii = array_formulae[ai];
for(ai = 0; ai < arrayf.length; ++ai) {
var aii = arrayf[ai];
if(row.r >= aii[0].s.r && row.r <= aii[0].e.r)
if(C >= aii[0].s.c && C <= aii[0].e.c) {
p.F = encode_range(aii[0]); af = true;
@ -488,7 +493,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles)/*:Worksheet*/
break;
case 0x00B0: /* 'BrtMergeCell' */
mergecells.push(val); break;
merges.push(val); break;
case 0x01EE: /* 'BrtHLink' */
var rel = rels['!id'][val.relId];
@ -514,14 +519,14 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles)/*:Worksheet*/
case 0x01AA: /* 'BrtArrFmla' */
if(!opts.cellFormula) break;
array_formulae.push(val);
arrayf.push(val);
cell = ((opts.dense ? s[R][C] : s[encode_col(C) + rr])/*:any*/);
cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
cell.F = encode_range(val[0]);
break;
case 0x01AB: /* 'BrtShrFmla' */
if(!opts.cellFormula) break;
shared_formulae[encode_cell(val[0].s)] = val[1];
sharedf[encode_cell(val[0].s)] = val[1];
cell = (opts.dense ? s[R][C] : s[encode_col(C) + rr]);
cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
break;
@ -549,6 +554,12 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles)/*:Worksheet*/
if(val.name) wb.Sheets[idx].CodeName = val.name;
break;
case 0x0089: /* 'BrtBeginWsView' */
if(!wb.Views) wb.Views = [{}];
if(!wb.Views[0]) wb.Views[0] = {};
if(val.RTL) wb.Views[0].RTL = true;
break;
case 0x01E5: /* 'BrtWsFmtInfo' */
/* case 'BrtUid' */
case 0x00AF: /* 'BrtAFilterDateGroupItem' */
@ -635,7 +646,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles)/*:Worksheet*/
s["!ref"] = encode_range(tmpref);
}
}
if(mergecells.length > 0) s["!merges"] = mergecells;
if(merges.length > 0) s["!merges"] = merges;
if(colinfo.length > 0) s["!cols"] = colinfo;
if(rowinfo.length > 0) s["!rows"] = rowinfo;
return s;
@ -687,7 +698,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
}
function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = [];
var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols/*:Array<string>*/ = [];
write_record(ba, 'BrtBeginSheetData');
var dense = Array.isArray(ws);
var cap = range.e.r;

@ -1,5 +1,5 @@
function parse_numCache(data) {
var col = [];
function parse_numCache(data/*:string*/)/*:[Array<number>, string]*/ {
var col/*:Array<number>*/ = [];
/* 21.2.2.150 pt CT_NumVal */
(data.match(/<c:pt idx="(\d*)">(.*?)<\/c:pt>/mg)||[]).forEach(function(pt) {
@ -15,8 +15,8 @@ function parse_numCache(data) {
}
/* 21.2 DrawingML - Charts */
function parse_chart(data, name/*:string*/, opts, rels, wb, csheet) {
var cs = ((csheet || {"!type":"chart"})/*:any*/);
function parse_chart(data/*:?string*/, name/*:string*/, opts, rels, wb, csheet) {
var cs/*:Worksheet*/ = ((csheet || {"!type":"chart"})/*:any*/);
if(!data) return csheet;
/* 21.2.2.27 chart CT_Chart */

@ -43,7 +43,7 @@ function parse_cs_bin(data, opts, idx/*:number*/, rels, wb, themes, styles)/*:Wo
if(!data) return data;
if(!rels) rels = {'!id':{}};
var s = {'!type':"chart", '!chart':null, '!rel':""};
var state = [];
var state/*:Array<string>*/ = [];
var pass = false;
recordhopper(data, function cs_parse(val, R_n, RT) {
switch(RT) {

@ -5,7 +5,6 @@ function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, Names:[], xmlns: "" };
var pass = false, xmlns = "xmlns";
var dname = {}, dnstart = 0;
/*(data.match(tagregex)||[]).forEach */
data.replace(tagregex, function xml_wb(x, idx) {
var y/*:any*/ = parsexmltag(x);
switch(strip_ns(y[0])) {

@ -37,7 +37,7 @@ function parse_sst(data, name/*:string*/, opts)/*:SST*/ {
return parse_sst_xml((data/*:any*/), opts);
}
function parse_cmnt(data, name/*:string*/, opts) {
function parse_cmnt(data, name/*:string*/, opts)/*:Array<RawComment>*/ {
if(name.slice(-4)===".bin") return parse_comments_bin((data/*:any*/), opts);
return parse_comments_xml((data/*:any*/), opts);
}

@ -44,7 +44,7 @@ function xlml_format(format, value)/*:string*/ {
return SSF.format(fmt, value);
}
function xlml_set_custprop(Custprops, Rn, cp, val/*:string*/) {
function xlml_set_custprop(Custprops, key, cp, val/*:string*/) {
var oval/*:any*/ = val;
switch((cp[0].match(/dt:dt="([\w.]+)"/)||["",""])[1]) {
case "boolean": oval = parsexmlbool(val); break;
@ -54,7 +54,7 @@ function xlml_set_custprop(Custprops, Rn, cp, val/*:string*/) {
case "i8": case "string": case "fixed": case "uuid": case "bin.base64": break;
default: throw new Error("bad custprop:" + cp[0]);
}
Custprops[unescapexml(Rn[3])] = oval;
Custprops[unescapexml(key)] = oval;
}
function safe_format_xlml(cell/*:Cell*/, nf, o) {
@ -174,7 +174,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
var opts = _opts || {};
make_ssf(SSF);
var str = debom(xlml_normalize(d));
if(opts.type == 'binary' || opts.type == 'base64') {
if(opts.type == 'binary' || opts.type == 'array' || opts.type == 'base64') {
if(typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str));
else str = utf8read(str);
}
@ -184,19 +184,19 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
var Rn;
var state = [], tmp;
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
var sheets = {}, sheetnames = [], cursheet/*:Worksheet*/ = (opts.dense ? [] : {}), sheetname = "";
var sheets = {}, sheetnames/*:Array<string>*/ = [], cursheet/*:Worksheet*/ = (opts.dense ? [] : {}), sheetname = "";
var table = {}, cell = ({}/*:any*/), row = {};
var dtag = xlml_parsexmltag('<Data ss:Type="String">'), didx = 0;
var c = 0, r = 0;
var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
var refguess/*:Range*/ = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
var styles = {}, stag = {};
var ss = "", fidx = 0;
var mergecells = [];
var Props = {}, Custprops = {}, pidx = 0, cp = {};
var comments = [], comment = {};
var merges/*:Array<Range>*/ = [];
var Props = {}, Custprops = {}, pidx = 0, cp = [];
var comments/*:Array<Comment>*/ = [], comment/*:Comment*/ = ({}/*:any*/);
var cstys = [], csty, seencol = false;
var arrayf = [];
var rowinfo = [], rowobj = {}, cc = 0, rr = 0;
var arrayf/*:Array<[Range, string]>*/ = [];
var rowinfo/*:Array<RowInfo>*/ = [], rowobj = {}, cc = 0, rr = 0;
var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false} }/*:any*/), wsprops = {};
xlmlregex.lastIndex = 0;
str = str.replace(/<!--([\s\S]*?)-->/mg,"");
@ -223,7 +223,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
if(cell.MergeAcross || cell.MergeDown) {
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}});
merges.push({s:{c:c,r:r},e:{c:cc,r:rr}});
}
if(!opts.sheetStubs) { if(cell.MergeAcross) c = cc + 1; else ++c; }
else if(cell.MergeAcross || cell.MergeDown) {
@ -275,7 +275,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
sheetnames.push(sheetname);
if(refguess.s.r <= refguess.e.r && refguess.s.c <= refguess.e.c) cursheet["!ref"] = encode_range(refguess);
if(mergecells.length) cursheet["!merges"] = mergecells;
if(merges.length) cursheet["!merges"] = merges;
if(cstys.length > 0) cursheet["!cols"] = cstys;
if(rowinfo.length > 0) cursheet["!rows"] = rowinfo;
sheets[sheetname] = cursheet;
@ -286,7 +286,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
tmp = xlml_parsexmltag(Rn[0]);
sheetname = unescapexml(tmp.Name);
cursheet = (opts.dense ? [] : {});
mergecells = [];
merges = [];
arrayf = [];
rowinfo = [];
wsprops = {name:sheetname, Hidden:0};
@ -402,7 +402,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
} else {
state.push([Rn[3], false]);
tmp = xlml_parsexmltag(Rn[0]);
comment = {a:tmp.Author};
comment = ({a:tmp.Author}/*:any*/);
}
break;
@ -565,6 +565,12 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
if(pagemargins.Right) cursheet['!margins'].right = pagemargins.Right;
if(pagemargins.Bottom) cursheet['!margins'].bottom = pagemargins.Bottom;
break;
case 'DisplayRightToLeft':
if(!Workbook.Views) Workbook.Views = [];
if(!Workbook.Views[0]) Workbook.Views[0] = {};
Workbook.Views[0].RTL = true;
break;
case 'Unsynced': break;
case 'Print': break;
case 'Panes': break;
@ -806,7 +812,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
if(!state[state.length-1][1]) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
if(state[state.length-1][0]==='CustomDocumentProperties') {
if(Rn[0].slice(-2) === "/>") break;
else if(Rn[1]==="/") xlml_set_custprop(Custprops, Rn, cp, str.slice(pidx, Rn.index));
else if(Rn[1]==="/") xlml_set_custprop(Custprops, Rn[3], cp, str.slice(pidx, Rn.index));
else { cp = Rn; pidx = Rn.index + Rn[0].length; }
break;
}
@ -822,11 +828,6 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
return out;
}
function arr2str(data/*:any*/)/*:string*/ {
if(Array.isArray(data)) return data.map(_chr).join("");
var o = []; for(var i = 0; i < data.length; ++i) o[i] = _chr(data[i]); return o.join("");
}
function parse_xlml(data/*:RawBytes|string*/, opts)/*:Workbook*/ {
fix_read_opts(opts=opts||{});
switch(opts.type||"base64") {
@ -838,8 +839,8 @@ function parse_xlml(data/*:RawBytes|string*/, opts)/*:Workbook*/ {
}
/* TODO */
function write_props_xlml(wb, opts) {
var o = [];
function write_props_xlml(wb/*:Workbook*/, opts)/*:string*/ {
var o/*:Array<string>*/ = [];
/* DocumentProperties */
if(wb.Props) o.push(xlml_write_docprops(wb.Props, opts));
/* CustomDocumentProperties */
@ -847,7 +848,7 @@ function write_props_xlml(wb, opts) {
return o.join("");
}
/* TODO */
function write_wb_xlml(wb, opts) {
function write_wb_xlml(wb, opts)/*:string*/ {
/* OfficeDocumentSettings */
/* ExcelWorkbook */
return "";
@ -855,12 +856,18 @@ function write_wb_xlml(wb, opts) {
/* TODO */
function write_sty_xlml(wb, opts)/*:string*/ {
/* Styles */
return "";
var styles/*:Array<string>*/ = ['<Style ss:ID="Default" ss:Name="Normal"><NumberFormat/></Style>'];
opts.cellXfs.forEach(function(xf, id) {
var payload/*:Array<string>*/ = [];
payload.push(writextag('NumberFormat', null, {"ss:Format": escapexml(SSF._table[xf.numFmtId])}));
styles.push(writextag('Style', payload.join(""), {"ss:ID": "s" + (21+id)}));
});
return writextag("Styles", styles.join(""));
}
/* WorksheetOptions */
function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
if(!ws) return "";
var o = [];
var o/*:Array<string>*/ = [];
/* NOTE: spec technically allows any order, but stick with implied order */
/* FitToPage */
@ -913,7 +920,10 @@ function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workb
}
/* LeftColumnVisible */
/* DisplayRightToLeft */
// $FlowIgnore
if(((((wb||{}).Workbook||{}).Views||[])[0]||{}).RTL) o.push("<DisplayRightToLeft/>");
/* GridlineColorIndex */
/* DisplayFormulas */
/* DoNotDisplayGridlines */
@ -1001,9 +1011,12 @@ function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb,
case 'n': t = 'Number'; p = String(cell.v); break;
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
case 'e': t = 'Error'; p = BErr[cell.v]; break;
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); break;
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break;
case 's': t = 'String'; p = escapexml(cell.v||""); break;
}
/* TODO: cell style */
var os = get_cell_style(opts.cellXfs, cell, opts);
attr["ss:StyleID"] = "s" + (21+os);
var _v = (cell.v != null ? p : "");
var m = '<Data ss:Type="' + t + '">' + _v + '</Data>';
@ -1023,9 +1036,9 @@ function write_ws_xlml_row(R/*:number*/, row)/*:string*/ {
/* TODO */
function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
if(!ws['!ref']) return "";
var range = safe_decode_range(ws['!ref']);
var marr = ws['!merges'] || [], mi = 0;
var o = [];
var range/*:Range*/ = safe_decode_range(ws['!ref']);
var marr/*:Array<Range>*/ = ws['!merges'] || [], mi = 0;
var o/*:Array<string>*/ = [];
if(ws['!cols']) ws['!cols'].forEach(function(n, i) {
process_col(n);
var w = !!n.width;
@ -1059,7 +1072,7 @@ function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbo
return o.join("");
}
function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ {
var o = [];
var o/*:Array<string>*/ = [];
var s = wb.SheetNames[idx];
var ws = wb.Sheets[s];
@ -1073,12 +1086,23 @@ function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ {
return o.join("");
}
function write_xlml(wb, opts)/*:string*/ {
var d = [];
if(!opts) opts = {};
if(!wb.SSF) wb.SSF = SSF.get_table();
if(wb.SSF) {
make_ssf(SSF); SSF.load_table(wb.SSF);
// $FlowIgnore
opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
opts.ssf = wb.SSF;
opts.cellXfs = [];
get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}});
}
var d/*:Array<string>*/ = [];
d.push(write_props_xlml(wb, opts));
d.push(write_wb_xlml(wb, opts));
d.push(write_sty_xlml(wb, opts));
d.push("");
for(var i = 0; i < wb.SheetNames.length; ++i)
d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])}));
d[2] = write_sty_xlml(wb, opts);
return XML_HEADER + writextag("Workbook", d.join(""), {
'xmlns': XLMLNS.ss,
'xmlns:o': XLMLNS.o,

@ -5,25 +5,25 @@ function parse_compobj(obj/*:CFBEntry*/) {
/*:: if(o == null) return; */
/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
var l = 28, m;
m = __lpstr(o, l);
l += 4 + __readUInt32LE(o,l);
v.UserType = m;
o.l = 28;
/* [MS-OLEDS] 2.3.1 ClipboardFormatOrAnsiString */
m = __readUInt32LE(o,l); l+= 4;
switch(m) {
case 0x00000000: break;
case 0xffffffff: case 0xfffffffe: l+=4; break;
default:
if(m > 0x190) throw new Error("Unsupported Clipboard: " + m.toString(16));
l += m;
}
v.AnsiUserType = o.read_shift(0, "lpstr-ansi");
v.AnsiClipboardFormat = parse_ClipboardFormatOrAnsiString(o);
m = __lpstr(o, l); l += m.length === 0 ? 0 : 5 + m.length; v.Reserved1 = m;
if(o.length - o.l <= 4) return v;
if((m = __readUInt32LE(o,l)) !== 0x71b2e9f4) return v;
throw new Error("Unsupported Unicode Extension");
var m/*:number*/ = o.read_shift(4);
if(m == 0 || m > 40) return v;
o.l-=4; v.Reserved1 = o.read_shift(0, "lpstr-ansi");
if(o.length - o.l <= 4) return v;
m = o.read_shift(4);
if(m !== 0x71b239f4) return v;
v.UnicodeClipboardFormat = parse_ClipboardFormatOrUnicodeString(o);
m = o.read_shift(4);
if(m == 0 || m > 40) return v;
o.l-=4; v.Reserved2 = o.read_shift(0, "lpwstr");
}
/*
@ -99,21 +99,20 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
if(DENSE != null && options.dense == null) options.dense = DENSE;
var out/*:Worksheet*/ = ((options.dense ? [] : {})/*:any*/);
var Directory = {};
var found_sheet = false;
var range/*:Range*/ = ({}/*:any*/);
var last_formula = null;
var sst = [];
var sst/*:SST*/ = ([]/*:any*/);
var cur_sheet = "";
var Preamble = {};
var lastcell, last_cell = "", cc, cmnt, rng, rngC, rngR;
var lastcell, last_cell = "", cc, cmnt, rngC, rngR;
var shared_formulae = {};
var array_formulae = []; /* TODO: something more clever */
var arrayf/*:Array<[Range, string]>*/ = [];
var temp_val/*:Cell*/;
var country;
var cell_valid = true;
var XFs = []; /* XF records */
var palette = [];
var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false} }/*:any*/), wsprops = {};
var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false}, Views:[{}] }/*:any*/), wsprops = {};
var get_rgb = function getrgb(icv) {
if(icv < 8) return XLSIcv[icv];
if(icv < 64) return palette[icv-8] || XLSIcv[icv];
@ -144,15 +143,15 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1;
}
if(options.cellFormula && line.f) {
for(var afi = 0; afi < array_formulae.length; ++afi) {
if(array_formulae[afi][0].s.c > cell.c) continue;
if(array_formulae[afi][0].s.r > cell.r) continue;
if(array_formulae[afi][0].e.c < cell.c) continue;
if(array_formulae[afi][0].e.r < cell.r) continue;
line.F = encode_range(array_formulae[afi][0]);
if(array_formulae[afi][0].s.c != cell.c) delete line.f;
if(array_formulae[afi][0].s.r != cell.r) delete line.f;
if(line.f) line.f = "" + stringify_formula(array_formulae[afi][1], range, cell, supbooks, opts);
for(var afi = 0; afi < arrayf.length; ++afi) {
if(arrayf[afi][0].s.c > cell.c) continue;
if(arrayf[afi][0].s.r > cell.r) continue;
if(arrayf[afi][0].e.c < cell.c) continue;
if(arrayf[afi][0].e.r < cell.r) continue;
line.F = encode_range(arrayf[afi][0]);
if(arrayf[afi][0].s.c != cell.c) delete line.f;
if(arrayf[afi][0].s.r != cell.r) delete line.f;
if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts);
break;
}
}
@ -169,7 +168,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
sbcch: 0, // cch in the preceding SupBook
snames: [], // sheetnames
sharedf: shared_formulae, // shared formulae by address
arrayf: array_formulae, // array formulae array
arrayf: arrayf, // array formulae array
rrtabid: [], // RRTabId
lastuser: "", // Last User from WriteAccess
biff: 8, // BIFF version
@ -179,9 +178,10 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
WTF: !!options && !!options.wtf
}/*:any*/);
if(options.password) opts.password = options.password;
var mergecells = [];
var themes;
var merges/*:Array<Range>*/ = [];
var objects = [];
var colinfo = [], rowinfo = [];
var colinfo/*:Array<ColInfo>*/ = [], rowinfo/*:Array<RowInfo>*/ = [];
var defwidth = 0, defheight = 0; // twips / MDW respectively
var seencol = false;
var supbooks = ([]/*:any*/); // 1-indexed, will hold extern names
@ -192,8 +192,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
supbooks.XTI = [];
var last_Rn = '';
var file_depth = 0; /* TODO: make a real stack */
var BIFF2Fmt = 0;
var BIFF2FmtTable/*:Array<string>*/ = [];
var BIFF2Fmt = 0, BIFF2FmtTable/*:Array<string>*/ = [];
var FilterDatabases = []; /* TODO: sort out supbooks and process elsewhere */
var last_lbl/*:?DefinedName*/;
@ -291,7 +290,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
}/*:DefinedName*/);
if(val.itab > 0) last_lbl.Sheet = val.itab - 1;
supbooks.names.push(last_lbl);
if(!supbooks[0]) supbooks[0] = [];
if(!supbooks[0]) { supbooks[0] = []; supbooks[0].XTI = []; }
supbooks[supbooks.length-1].push(val);
if(val.Name == "_xlnm._FilterDatabase" && val.itab > 0)
if(val.rgce && val.rgce[0] && val.rgce[0][0] && val.rgce[0][0][0] == 'PtgArea3d')
@ -323,7 +322,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
out["!ref"] = encode_range(range);
range.e.r++; range.e.c++;
}
if(mergecells.length > 0) out["!merges"] = mergecells;
if(merges.length > 0) out["!merges"] = merges;
if(objects.length > 0) out["!objects"] = objects;
if(colinfo.length > 0) out["!cols"] = colinfo;
if(rowinfo.length > 0) out["!rows"] = rowinfo;
@ -333,16 +332,16 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
out = ((options.dense ? [] : {})/*:any*/);
} break;
case 'BOF': {
if(opts.biff === 8) switch(RecordType) {
case 0x0009: opts.biff = 2; break;
case 0x0209: opts.biff = 3; break;
case 0x0409: opts.biff = 4; break;
default: switch(val.BIFFVer) {
case 0x0500: opts.biff = 5; break;
case 0x0600: opts.biff = 8; break;
case 0x0002: opts.biff = 2; break;
case 0x0007: opts.biff = 2; break;
}}
if(opts.biff === 8) opts.biff = {
/*::[*/0x0009/*::]*/:2,
/*::[*/0x0209/*::]*/:3,
/*::[*/0x0409/*::]*/:4
}[RecordType] || {
/*::[*/0x0500/*::]*/:5,
/*::[*/0x0600/*::]*/:8,
/*::[*/0x0002/*::]*/:2,
/*::[*/0x0007/*::]*/:2
}[val.BIFFVer] || 8;
if(file_depth++) break;
cell_valid = true;
out = ((options.dense ? [] : {})/*:any*/);
@ -359,9 +358,9 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
else cur_sheet = (Directory[s] || {name:""}).name;
if(val.dt == 0x20) out["!type"] = "chart";
if(val.dt == 0x40) out["!type"] = "macro";
mergecells = [];
merges = [];
objects = [];
array_formulae = []; opts.arrayf = array_formulae;
opts.arrayf = arrayf = [];
colinfo = []; rowinfo = [];
defwidth = defheight = 0;
seencol = false;
@ -429,7 +428,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
} else throw new Error("String record expects Formula");
} break;
case 'Array': {
array_formulae.push(val);
arrayf.push(val);
var _arraystart = encode_cell(val[0].s);
cc = options.dense ? (out[val[0].s.r]||[])[val[0].s.c] : out[_arraystart];
if(options.cellFormula && cc) {
@ -501,7 +500,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
if(b2idx >= 163) SSF.load(val, BIFF2Fmt + 163);
} break;
case 'MergeCells': mergecells = mergecells.concat(val); break;
case 'MergeCells': merges = merges.concat(val); break;
case 'Obj': objects[val.cmo[0]] = opts.lastobj = val; break;
case 'TxO': opts.lastobj.TxO = val; break;
@ -572,6 +571,11 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
out['!margins'].footer = val.footer;
break;
case 'Window2': // TODO
// $FlowIgnore
if(val.RTL) Workbook.Views[0].RTL = true;
break;
case 'Header': break; // TODO
case 'Footer': break; // TODO
case 'HCenter': break; // TODO
@ -605,8 +609,8 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
case 'XFCRC': break; // TODO
case 'Style': break; // TODO
case 'StyleExt': break; // TODO
case 'Palette': palette = val; break; // TODO
case 'Theme': break; // TODO
case 'Palette': palette = val; break;
case 'Theme': themes = val; break;
/* Protection */
case 'ScenarioProtect': break;
case 'ObjProtect': break;
@ -710,7 +714,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
case 'InterfaceHdr': case 'Mms': case 'InterfaceEnd': case 'DSF': break;
case 'BuiltInFnGroupCount': /* 2.4.30 0x0E or 0x10 but excel 2011 generates 0x11? */ break;
/* View Stuff */
case 'Window1': case 'Window2': case 'HideObj': case 'GridSet': case 'Guts':
case 'Window1': case 'HideObj': case 'GridSet': case 'Guts':
case 'UserBView': case 'UserSViewBegin': case 'UserSViewEnd':
case 'Pane': break;
default: switch(R.n) { /* nested */
@ -824,6 +828,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
wb.Strings = sst;
wb.SSF = SSF.get_table();
if(opts.enc) wb.Encryption = opts.enc;
if(themes) wb.Themes = themes;
wb.Metadata = {};
if(country !== undefined) wb.Metadata.Country = country;
if(supbooks.names.length > 0) Workbook.Names = supbooks.names;
@ -838,22 +843,24 @@ function parse_props(cfb/*:CFBContainer*/, props, o) {
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 */}
} catch(e) {if(o.WTF) throw e;/* empty */}
/* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
var SI = CFB.find(cfb, '!SummaryInformation');
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 */}
} catch(e) {if(o.WTF) throw e;/* empty */}
}
function parse_xlscfb(cfb/*:any*/, options/*:?ParseOpts*/)/*:Workbook*/ {
if(!options) options = {};
fix_read_opts(options);
reset_cp();
if(options.codepage) set_ansi(options.codepage);
var CompObj/*:?CFBEntry*/, Summary, WB/*:?any*/;
if(cfb.FullPaths) {
if(CFB.find(cfb, '/encryption')) throw new Error("File is password-protected");
CompObj = CFB.find(cfb, '!CompObj');
Summary = CFB.find(cfb, '!SummaryInformation');
WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
@ -900,6 +907,8 @@ function write_xlscfb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:CFBContainer*/ {
switch(o.bookType || "xls") {
case "xls": o.bookType = "biff8";
/* falls through */
case "xla": if(!o.bookType) o.bookType = "xla";
/* falls through */
case "biff8": wbpath = "/Workbook"; o.biff = 8; break;
case "biff5": wbpath = "/Book"; o.biff = 5; break;
default: throw new Error("invalid type " + o.bookType + " for XLS CFB");

@ -72,7 +72,7 @@ var XLSBRecordEnum = {
/*::[*/0x0086/*::]*/: { n:"BrtEndWsViews" },
/*::[*/0x0087/*::]*/: { n:"BrtBeginBookViews" },
/*::[*/0x0088/*::]*/: { n:"BrtEndBookViews" },
/*::[*/0x0089/*::]*/: { n:"BrtBeginWsView" },
/*::[*/0x0089/*::]*/: { n:"BrtBeginWsView", f:parse_BrtBeginWsView },
/*::[*/0x008A/*::]*/: { n:"BrtEndWsView" },
/*::[*/0x008B/*::]*/: { n:"BrtBeginCsViews" },
/*::[*/0x008C/*::]*/: { n:"BrtEndCsViews" },
@ -1026,7 +1026,7 @@ var XLSRecordEnum = {
/*::[*/0x0221/*::]*/: { n:"Array", f:parse_Array },
/*::[*/0x0225/*::]*/: { n:"DefaultRowHeight", f:parse_DefaultRowHeight },
/*::[*/0x0236/*::]*/: { n:"Table" },
/*::[*/0x023e/*::]*/: { n:"Window2" },
/*::[*/0x023e/*::]*/: { n:"Window2", f:parse_Window2 },
/*::[*/0x027e/*::]*/: { n:"RK", f:parse_RK },
/*::[*/0x0293/*::]*/: { n:"Style" },
/*::[*/0x0406/*::]*/: { n:"Formula", f:parse_Formula },

@ -1,8 +1,8 @@
function write_biff_rec(ba/*:BufArray*/, type/*:number|string*/, payload, length/*:?number*/) {
function write_biff_rec(ba/*:BufArray*/, type/*:number|string*/, payload, length/*:?number*/)/*:void*/ {
var t/*:number*/ = +type || +XLSRE[/*::String(*/type/*::)*/];
if(isNaN(t)) return;
var len = length || (payload||[]).length || 0;
var o = ba.next(4 + len);
var o = ba.next(4);
o.write_shift(2, t);
o.write_shift(2, len);
if(/*:: len != null &&*/len > 0 && is_buf(payload)) ba.push(payload);
@ -12,8 +12,7 @@ function write_BIFF2Cell(out, r/*:number*/, c/*:number*/) {
if(!out) out = new_buf(7);
out.write_shift(2, r);
out.write_shift(2, c);
out.write_shift(1, 0);
out.write_shift(1, 0);
out.write_shift(2, 0);
out.write_shift(1, 0);
return out;
}
@ -114,7 +113,8 @@ function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n
function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
var ba = buf_array();
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
var _sheet/*:WBWSProp*/ = ((((wb||{}).Workbook||{}).Sheets||[])[idx]||{}/*:any*/);
var _WB/*:WBWBProps*/ = ((wb||{}).Workbook||{}/*:any*/);
var _sheet/*:WBWSProp*/ = ((_WB.Sheets||[])[idx]||{}/*:any*/);
var dense = Array.isArray(ws);
var ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
var range = safe_decode_range(ws['!ref'] || "A1");
@ -153,6 +153,10 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
}
var cname/*:string*/ = _sheet.CodeName || _sheet.name || s;
/* ... */
if(b8 && _WB.Views) write_biff_rec(ba, "Window2", write_Window2(_WB.Views[0]));
/* ... */
if(b8) write_biff_rec(ba, "MergeCells", write_MergeCells(ws['!merges']||[]));
/* ... */
if(b8) write_ws_biff8_hlinks(ba, ws);
/* ... */
write_biff_rec(ba, "CodeName", write_XLUnicodeString(cname, opts));
@ -167,6 +171,7 @@ function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) {
var _wb/*:WBWBProps*/ = /*::((*/(wb.Workbook||{}).WBProps||{/*::CodeName:"ThisWorkbook"*/}/*:: ):any)*/;
var b8 = opts.biff == 8, b5 = opts.biff == 5;
write_biff_rec(A, 0x0809, write_BOF(wb, 0x05, opts));
if(opts.bookType == "xla") write_biff_rec(A, "Addin");
write_biff_rec(A, "InterfaceHdr", b8 ? writeuint16(0x04b0) : null);
write_biff_rec(A, "Mms", writezeroes(2));
if(b5) write_biff_rec(A, "ToolbarHdr");

@ -10,8 +10,8 @@ var HTML_ = (function() {
var i/*:number*/ = mtch.index, j/*:number*/ = mtch2 && mtch2.index || str.length;
var rows = split_regex(str.slice(i, j), /(:?<tr[^>]*>)/i, "<tr>");
var R = -1, C = 0, RS = 0, CS = 0;
var range = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
var merges = [], midx = 0;
var range/*:Range*/ = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
var merges/*:Array<Range>*/ = [], midx = 0;
for(i = 0; i < rows.length; ++i) {
var row = rows[i].trim();
var hd = row.substr(0,3).toLowerCase();
@ -56,8 +56,8 @@ var HTML_ = (function() {
return sheet_to_workbook(html_to_sheet(str, opts), opts);
}
function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
var M = (ws['!merges'] ||[]);
var oo = [];
var M/*:Array<Range>*/ = (ws['!merges'] ||[]);
var oo/*:Array<string>*/ = [];
var nullcell = "<td>" + (o.editable ? '<span contenteditable="true"></span>' : "" ) + "</td>";
for(var C = r.s.c; C <= r.e.c; ++C) {
var RS = 0, CS = 0;
@ -85,7 +85,7 @@ var HTML_ = (function() {
return preamble + oo.join("") + "</tr>";
}
function make_html_preamble(ws/*:Worksheet*/, R/*:Range*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
var out = [];
var out/*:Array<string>*/ = [];
return out.join("") + '<table>';
}
var _BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
@ -118,17 +118,17 @@ function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
var opts = _opts || {};
if(DENSE != null) opts.dense = DENSE;
var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
var rows = table.getElementsByTagName('tr');
var range = {s:{r:0,c:0},e:{r:rows.length - 1,c:0}};
var merges = [], midx = 0;
var rows/*:HTMLCollection<HTMLTableRowElement>*/ = table.getElementsByTagName('tr');
var range/*:Range*/ = {s:{r:0,c:0},e:{r:rows.length - 1,c:0}};
var merges/*:Array<Range>*/ = [], midx = 0;
var R = 0, _C = 0, C = 0, RS = 0, CS = 0;
for(; R < rows.length; ++R) {
var row = rows[R];
var elts = row.children;
var row/*:HTMLTableRowElement*/ = rows[R];
var elts/*:HTMLCollection<HTMLTableCellElement>*/ = (row.children/*:any*/);
for(_C = C = 0; _C < elts.length; ++_C) {
var elt = elts[_C], v = htmldecode(elts[_C].innerHTML);
var elt/*:HTMLTableCellElement*/ = elts[_C], v = htmldecode(elts[_C].innerHTML);
for(midx = 0; midx < merges.length; ++midx) {
var m = merges[midx];
var m/*:Range*/ = merges[midx];
if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; }
}
/* TODO: figure out how to extract nonstandard mso- style */

@ -45,13 +45,13 @@ var parse_content_xml = (function() {
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 merges/*:Array<Range>*/ = [], mrange = {}, mR = 0, mC = 0;
var rowinfo/*:Array<RowInfo>*/ = [], rowpeat = 1, colpeat = 1;
var arrayf/*:Array<[Range, string]>*/ = [];
var WB = {Names:[]};
var atag = ({}/*:any*/);
var _Ref/*:[string, string]*/ = ["", ""];
var comments = [], comment = {};
var comments/*:Array<Comment>*/ = [], comment/*:Comment*/ = ({}/*:any*/);
var creator = "", creatoridx = 0;
var isstub = false, intable = false;
var i = 0;
@ -122,7 +122,7 @@ var parse_content_xml = (function() {
if(C < range.s.c) range.s.c = C;
if(R < range.s.r) range.s.r = R;
ctag = parsexmltag(Rn[0], false);
comments = []; comment = {};
comments = []; comment = ({}/*:any*/);
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:"",c:[]*/}/*:any*/);
if(opts.cellFormula) {
if(ctag.formula) ctag.formula = unescapexml(ctag.formula);

@ -32,10 +32,10 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
var covered_cell_xml = ' <table:covered-table-cell/>\n';
var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts)/*:string*/ {
/* Section 9 Tables */
var o = [];
var o/*:Array<string>*/ = [];
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n');
var R=0,C=0, range = decode_range(ws['!ref']);
var marr = ws['!merges'] || [], mi = 0;
var marr/*:Array<Range>*/ = ws['!merges'] || [], mi = 0;
var dense = Array.isArray(ws);
for(R = 0; R < range.s.r; ++R) o.push(' <table:table-row></table:table-row>\n');
for(; R <= range.e.r; ++R) {
@ -186,7 +186,7 @@ function write_ods(wb/*:any*/, opts/*:any*/) {
var f = "";
var manifest/*:Array<Array<string> >*/ = [];
var rdf = [];
var rdf/*:Array<[string, string]>*/ = [];
/* Part 3 Section 3.3 MIME Media Type */
f = "mimetype";

@ -43,7 +43,6 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
make_ssf(SSF);
opts = opts || {};
fix_read_opts(opts);
reset_cp();
/* OpenDocument Part 3 Section 2.2.1 OpenDocument Package */
if(safegetzipfile(zip, 'META-INF/manifest.xml')) return parse_ods(zip, opts);
@ -67,7 +66,6 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
xlsb = true;
}
if(dir.workbooks[0].slice(-3) == "bin") xlsb = true;
if(xlsb) set_cp(1200);
var themes = ({}/*:any*/);
var styles = ({}/*:any*/);

@ -13,7 +13,7 @@ function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
opts.rels = {}; opts.wbrels = {};
opts.Strings = /*::((*/[]/*:: :any):SST)*/; opts.Strings.Count = 0; opts.Strings.Unique = 0;
var wbext = opts.bookType == "xlsb" ? "bin" : "xml";
var vbafmt = opts.bookType == "xlsb" || opts.bookType == "xlsm";
var vbafmt = VBAFMTS.indexOf(opts.bookType) > -1;
var ct = new_ct();
fix_write_opts(opts = opts || {});
/*:: if(!jszip) throw new Error("JSZip is not available"); */

@ -70,7 +70,9 @@ function read_prn(data, d, o, str) {
}
function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
var zip, d = data, n = [0,0,0,0], str = false;
reset_cp();
if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), opts);
var d = data, n = [0,0,0,0], str = false;
var o = opts||{};
_ssfopts = {};
if(o.dateNF) _ssfopts.dateNF = o.dateNF;

@ -79,6 +79,7 @@ function write_binary_type(out, opts/*:WriteOpts*/)/*:any*/ {
function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
check_wb(wb);
var o = opts||{};
if(o.type == "array") { o.type = "binary"; var out/*:string*/ = (writeSync(wb, o)/*:any*/); o.type = "array"; return s2ab(out); }
switch(o.bookType || 'xlsb') {
case 'xml':
case 'xlml': return write_string_type(write_xlml(wb, o), o);
@ -99,9 +100,11 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
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; /* falls through */
case 'biff8':
case 'xla':
case 'xls': if(!o.biff) o.biff = 8; return write_cfb_type(wb, o);
case 'xlsx':
case 'xlsm':
case 'xlam':
case 'xlsb':
case 'ods': return write_zip_type(wb, o);
default: throw new Error ("Unrecognized bookType |" + o.bookType + "|");

@ -103,20 +103,20 @@ function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Arr
}
function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ {
var out = [];
var out/*:Array<string>*/ = [];
var o = opts == null ? {} : opts;
if(sheet == null || sheet["!ref"] == null) return "";
var r = safe_decode_range(sheet["!ref"]);
var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
var row = "", cols = [];
var row = "", cols/*:Array<string>*/ = [];
o.dense = Array.isArray(sheet);
var colInfos = o.skipHidden && sheet["!cols"] || [];
var rowInfos = o.skipHidden && sheet["!rows"] || [];
for(var C = r.s.c; C <= r.e.c; ++C) if (!((colInfos[C]||{}).hidden)) cols[C] = encode_col(C);
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
var rowinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!rows"] || [];
for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
for(var R = r.s.r; R <= r.e.r; ++R) {
if ((rowInfos[R]||{}).hidden) continue;
if ((rowinfo[R]||{}).hidden) continue;
row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o);
if(row == null) { continue; }
if(o.strip) row = row.replace(endregex,"");
@ -137,7 +137,7 @@ function sheet_to_txt(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
var y = "", x, val="";
if(sheet == null || sheet["!ref"] == null) return [];
var r = safe_decode_range(sheet['!ref']), rr = "", cols = [], C;
var r = safe_decode_range(sheet['!ref']), rr = "", cols/*:Array<string>*/ = [], C;
var cmds/*:Array<string>*/ = [];
var dense = Array.isArray(sheet);
for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C);
@ -173,7 +173,7 @@ function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ {
var ws = ({}/*:any*/);
var cell/*:Cell*/;
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:js.length}}/*:any*/);
var hdr = o.header || [], C = 0;
var hdr/*:Array<string>*/ = o.header || [], C = 0;
js.forEach(function (JS, R) {
keys(JS).filter(function(x) { return JS.hasOwnProperty(x); }).forEach(function(k) {

@ -10,17 +10,17 @@ if(has_buf && typeof require != 'undefined') (function() {
var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
var row/*:?string*/ = "", cols = [];
var row/*:?string*/ = "", cols/*:Array<string>*/ = [];
o.dense = Array.isArray(sheet);
var colInfos = o.skipHidden && sheet["!cols"] || [];
var rowInfos = o.skipHidden && sheet["!rows"] || [];
for(var C = r.s.c; C <= r.e.c; ++C) if (!((colInfos[C]||{}).hidden)) cols[C] = encode_col(C);
var colinfo/*:Array<ColInfo>*/ = o.skipHidden && sheet["!cols"] || [];
var rowinfo/*:Array<RowInfo>*/ = o.skipHidden && sheet["!rows"] || [];
for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
var R = r.s.r;
stream._read = function() {
if(R > r.e.r) return stream.push(null);
while(R <= r.e.r) {
++R;
if ((rowInfos[R-1]||{}).hidden) continue;
if ((rowinfo[R-1]||{}).hidden) continue;
row = make_csv_row(sheet, r, R-1, cols, fs, rs, FS, o);
if(row != null) {
if(o.strip) row = row.replace(endregex,"");

@ -1,5 +1,3 @@
})(typeof exports !== 'undefined' ? exports : XLSX);
/*exported XLS */
var XLS = XLSX;
/*exported ODS */
var ODS = XLSX;
/*exported XLS, ODS */
var XLS = XLSX, ODS = XLSX;

@ -81,18 +81,11 @@ var ws = XLSX.utils.json_to_sheet(data);
var wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "Presidents");
/* write workbook (use type 'binary') */
var wbout = XLSX.write(wb, {bookType:'xlsx', type:'binary'});
/* write workbook (use type 'array' for ArrayBuffer) */
var wbout = XLSX.write(wb, {bookType:'xlsx', type:'array'});
/* generate a download */
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "sheetjs.xlsx");
saveAs(new Blob([wbout],{type:"application/octet-stream"}), "sheetjs.xlsx");
```

@ -13,12 +13,12 @@ function SheetJSExportService(uiGridExporterService) {
var wb = XLSX.utils.book_new(), ws = uigrid_to_sheet(data, columns);
XLSX.utils.book_append_sheet(wb, ws, sheetName);
var wbout = XLSX.write(wb, wopts);
saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), fileName);
saveAs(new Blob([wbout], { type: 'application/octet-stream' }), fileName);
}
var service = {};
service.exportXLSB = function exportXLSB(gridApi) { return exportSheetJS(gridApi, { bookType: 'xlsb', bookSST: true, type: 'binary' }); };
service.exportXLSX = function exportXLSX(gridApi) { return exportSheetJS(gridApi, { bookType: 'xlsx', bookSST: true, type: 'binary' }); }
service.exportXLSB = function exportXLSB(gridApi) { return exportSheetJS(gridApi, { bookType: 'xlsb', bookSST: true, type: 'array' }); };
service.exportXLSX = function exportXLSX(gridApi) { return exportSheetJS(gridApi, { bookType: 'xlsx', bookSST: true, type: 'array' }); }
return service;
@ -47,19 +47,6 @@ function SheetJSExportService(uiGridExporterService) {
if(col.name) return col.name;
return null;
}
function s2ab(s) {
if(typeof ArrayBuffer !== 'undefined') {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
} else {
var buf = new Array(s.length);
for (var i=0; i!=s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
}
}
var SheetJSImportDirective = function() {

@ -35,8 +35,8 @@ const wb: XLSX.WorkBook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
/* save to file */
const wbout: string = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });
saveAs(new Blob([s2ab(wbout)]), 'SheetJS.xlsx');
const wbout: string = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
saveAs(new Blob([wbout]), 'SheetJS.xlsx');
```
`sheet_to_json` with the option `header:1` makes importing simple:

@ -8,13 +8,6 @@ import { saveAs } from 'file-saver';
type AOA = Array<Array<any>>;
function s2ab(s: string): ArrayBuffer {
const buf: ArrayBuffer = new ArrayBuffer(s.length);
const view: Uint8Array = new Uint8Array(buf);
for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
@Component({
selector: 'sheetjs',
template: `
@ -32,7 +25,7 @@ function s2ab(s: string): ArrayBuffer {
export class SheetJSComponent {
data: AOA = [ [1, 2], [3, 4] ];
wopts: XLSX.WritingOptions = { bookType: 'xlsx', type: 'binary' };
wopts: XLSX.WritingOptions = { bookType: 'xlsx', type: 'array' };
fileName: string = 'SheetJS.xlsx';
onFileChange(evt: any) {
@ -64,7 +57,7 @@ export class SheetJSComponent {
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
/* save to file */
const wbout: string = XLSX.write(wb, this.wopts);
saveAs(new Blob([s2ab(wbout)]), this.fileName);
const wbout: ArrayBuffer = XLSX.write(wb, this.wopts);
saveAs(new Blob([wbout], { type: 'application/octet-stream' }), this.fileName);
}
}

@ -71,6 +71,9 @@ var process_wb = (function() {
var range = XLSX.utils.decode_range(ws['!ref']);
for(var i = range.s.c; i <= range.e.c; ++i) cDg.schema[i - range.s.c].title = XLSX.utils.encode_col(i);
HTMLOUT.style.height = (window.innerHeight - 400) + "px";
HTMLOUT.style.width = (window.innerWidth - 50) + "px";
if(typeof console !== 'undefined') console.log("output", new Date());
};
})();
@ -136,12 +139,6 @@ var export_xlsx = (function() {
return out;
}
function s2ab(s) {
var b = new ArrayBuffer(s.length), v = new Uint8Array(b);
for (var i=0; i != s.length; ++i) v[i] = s.charCodeAt(i) & 0xFF;
return b;
}
return function export_xlsx() {
if(!cDg) return;
/* convert canvas-datagrid data to worksheet */
@ -152,10 +149,10 @@ var export_xlsx = (function() {
XLSX.utils.book_append_sheet(new_wb, new_ws, 'SheetJS');
/* write file and trigger a download */
var wbout = XLSX.write(new_wb, {bookType:'xlsx', bookSST:true, type:'binary'});
var wbout = XLSX.write(new_wb, {bookType:'xlsx', bookSST:true, type:'array'});
var fname = 'sheetjs.xlsx';
try {
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), fname);
saveAs(new Blob([wbout],{type:"application/octet-stream"}), fname);
} catch(e) { if(typeof console != 'undefined') console.log(e, wbout); }
};
})();

@ -61,8 +61,8 @@ const html = document.getElementById('out').innerHTML;
// SERVER SIDE
const wb = XLSX.read(html, { type: 'binary' });
// CLIENT SIDE
const o = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });
saveAs(new Blob([s2ab(o)], {type:'application/octet-stream'}), 'sheetjs.xlsx');
const o = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
saveAs(new Blob([o], {type:'application/octet-stream'}), 'sheetjs.xlsx');
```
This demo uses the FileSaver library for writing files, installed through the

@ -34,16 +34,9 @@ Template.sheetjs.events({
Meteor.call('download', html, function(err, wb) {
if (err) throw err;
/* "Browser download file" from SheetJS README */
const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });
saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), 'sheetjs.xlsx');
const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
saveAs(new Blob([wbout], { type: 'application/octet-stream' }), 'sheetjs.xlsx');
});
},
});
/* eslint no-bitwise:0, no-plusplus:0 */
function s2ab(s) {
const buf = new ArrayBuffer(s.length);
const view = new Uint8Array(buf);
for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}

@ -9,7 +9,7 @@
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js"></script>
<script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
<script src="node_modules/xlsx/dist/xlsx.full.min.js"></script>
<script src="https://unpkg.com/file-saver/FileSaver.js"></script>
<style>body, #app { height: 100%; };</style>
</head>

@ -38,9 +38,9 @@ class SheetJSApp extends React.Component {
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "SheetJS");
/* generate XLSX file */
const wbout = XLSX.write(wb, {type:"binary", bookType:"xlsx"});
const wbout = XLSX.write(wb, {type:"array", bookType:"xlsx"});
/* send to client */
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "sheetjs.xlsx");
saveAs(new Blob([wbout],{type:"application/octet-stream"}), "sheetjs.xlsx");
};
render() { return (
<DragDropFile handleFile={this.handleFile}>
@ -136,13 +136,5 @@ const SheetJSFT = [
"xlsx", "xlsb", "xlsm", "xls", "xml", "csv", "txt", "ods", "fods", "uos", "sylk", "dif", "dbf", "prn", "qpw", "123", "wb*", "wq*", "html", "htm"
].map(function(x) { return "." + x; }).join(",");
/* see Browser download file example in docs */
function s2ab(s/*:string*/)/*:ArrayBuffer*/ {
const buf = new ArrayBuffer(s.length);
const view = new Uint8Array(buf);
for (let i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
/* generate an array of column objects */
const make_cols = refstr => Array(XLSX.utils.decode_range(refstr).e.c + 1).fill(0).map((x,i) => ({name:XLSX.utils.encode_col(i), key:i}));

@ -95,13 +95,17 @@ fs.writeFileSync("sheetjs.xls", new Buffer(str, "base64"));
#### Server-Rendered VueJS Components with Nuxt.js
Due to webpack configuration issues on client/server bundles, the library should
be explicitly included in the layout HTML (as script tag) and in the component:
The scripts should be treated as external resources in `nuxt.config.js`:
```js
const _XLSX = require('xlsx');
const X = typeof XLSX !== 'undefined' ? XLSX : _XLSX;
/* use the variable X rather than XLSX in the component */
module.exports = {
head: {
script: [
{ src: "https://unpkg.com/xlsx/dist/xlsx.full.min.js" }, // library
{ src: "https://unpkg.com/file-saver/FileSaver.js" } // saveAs shim
]
}
};
```
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -13,19 +13,6 @@ var SJSTemplate = [
'</div>'
].join("");
function s2ab(s) {
if(typeof ArrayBuffer !== 'undefined') {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
} else {
var buf = new Array(s.length);
for (var i=0; i!=s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
}
Vue.component('html-preview', {
template: SJSTemplate,
methods: {
@ -69,10 +56,10 @@ Vue.component('html-preview', {
/* generate workbook object from table */
var wb = XLSX.utils.table_to_book(document.getElementById('out-table'));
/* get binary string as output */
var wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });
var wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
/* force a download */
saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), "sheetjs.xlsx");
saveAs(new Blob([wbout], { type: 'application/octet-stream' }), "sheetjs.xlsx");
}
}
});

9
demos/vue/nuxt.config.js Normal file

@ -0,0 +1,9 @@
module.exports = {
head: {
script: [
// { src: "https://unpkg.com/xlsx/dist/xlsx.full.min.js" }, // CDN
{ src: "xlsx.full.min.js" }, // development
{ src: "https://unpkg.com/file-saver/FileSaver.js" }
]
}
};

@ -30,17 +30,7 @@
</template>
<script>
const _XLSX = require('xlsx');
const X = typeof XLSX !== 'undefined' ? XLSX : _XLSX;
const make_cols = refstr => Array(X.utils.decode_range(refstr).e.c + 1).fill(0).map((x,i) => ({name:X.utils.encode_col(i), key:i}));
/* see Browser download file example in docs */
function s2ab(s) {
const buf = new ArrayBuffer(s.length);
const view = new Uint8Array(buf);
for (let i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
const make_cols = refstr => Array(XLSX.utils.decode_range(refstr).e.c + 1).fill(0).map((x,i) => ({name:XLSX.utils.encode_col(i), key:i}));
const _SheetJSFT = [
"xlsx", "xlsb", "xlsm", "xls", "xml", "csv", "txt", "ods", "fods", "uos", "sylk", "dif", "dbf", "prn", "qpw", "123", "wb*", "wq*", "html", "htm"
@ -73,13 +63,13 @@ export default {
},
_export(evt) {
/* convert state to workbook */
const ws = X.utils.aoa_to_sheet(this.data);
const wb = X.utils.book_new();
X.utils.book_append_sheet(wb, ws, "SheetJS");
const ws = XLSX.utils.aoa_to_sheet(this.data);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "SheetJS");
/* generate X file */
const wbout = X.write(wb, {type:"binary", bookType:"xlsx"});
const wbout = XLSX.write(wb, {type:"array", bookType:"xlsx"});
/* send to client */
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "sheetjs.xlsx");
saveAs(new Blob([wbout],{type:"application/octet-stream"}), "sheetjs.xlsx");
},
_file(file) {
/* Boilerplate to set up FileReader */
@ -87,12 +77,12 @@ export default {
reader.onload = (e) => {
/* Parse data */
const bstr = e.target.result;
const wb = X.read(bstr, {type:'binary'});
const wb = XLSX.read(bstr, {type:'binary'});
/* Get first worksheet */
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
/* Convert array of arrays */
const data = X.utils.sheet_to_json(ws, {header:1});
const data = XLSX.utils.sheet_to_json(ws, {header:1});
/* Update state */
this.data = data;
this.cols = make_cols(ws['!ref']);

30
dist/xlsx.core.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.core.min.map generated vendored

File diff suppressed because one or more lines are too long

32
dist/xlsx.full.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.full.min.map generated vendored

File diff suppressed because one or more lines are too long

614
dist/xlsx.js generated vendored

File diff suppressed because it is too large Load Diff

24
dist/xlsx.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.min.map generated vendored

File diff suppressed because one or more lines are too long

@ -43,19 +43,12 @@ example uses [FileSaver](https://github.com/eligrey/FileSaver.js/):
```js
/* bookType can be any supported output type */
var wopts = { bookType:'xlsx', bookSST:false, type:'binary' };
var wopts = { bookType:'xlsx', bookSST:false, type:'array' };
var wbout = XLSX.write(workbook,wopts);
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
/* the saveAs call downloads a file on the local machine */
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx");
saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx");
```
</details>

@ -22,6 +22,14 @@ Excel allows two sheet-scoped defined names to share the same name. However, a
sheet-scoped name cannot collide with a workbook-scope name. Workbook writers
may not enforce this constraint.
#### Workbook Views
`wb.Workbook.Views` is an array of workbook view objects which have the keys:
| Key | Description |
|:----------------|:----------------------------------------------------|
| `RTL` | If true, display right-to-left |
#### Miscellaneous Workbook Properties
`wb.Workbook.WBProps` holds other workbook properties:

@ -68,5 +68,6 @@ The `type` argument for `write` mirrors the `type` argument for `read`:
| `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) |
| `"string"` | string: JS string (characters interpreted as UTF8) |
| `"buffer"` | nodejs Buffer |
| `"array"` | ArrayBuffer, fallback array of 8-bit unsigned int |
| `"file"` | string: path of file that will be created (nodejs only) |

@ -79,6 +79,7 @@ enhancements, additional features by request, and dedicated support.
+ [Workbook File Properties](#workbook-file-properties)
* [Workbook-Level Attributes](#workbook-level-attributes)
+ [Defined Names](#defined-names)
+ [Workbook Views](#workbook-views)
+ [Miscellaneous Workbook Properties](#miscellaneous-workbook-properties)
* [Document Features](#document-features)
+ [Formulae](#formulae)
@ -565,19 +566,12 @@ example uses [FileSaver](https://github.com/eligrey/FileSaver.js/):
```js
/* bookType can be any supported output type */
var wopts = { bookType:'xlsx', bookSST:false, type:'binary' };
var wopts = { bookType:'xlsx', bookSST:false, type:'array' };
var wbout = XLSX.write(workbook,wopts);
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
/* the saveAs call downloads a file on the local machine */
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx");
saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx");
```
@ -994,6 +988,14 @@ Excel allows two sheet-scoped defined names to share the same name. However, a
sheet-scoped name cannot collide with a workbook-scope name. Workbook writers
may not enforce this constraint.
#### Workbook Views
`wb.Workbook.Views` is an array of workbook view objects which have the keys:
| Key | Description |
|:----------------|:----------------------------------------------------|
| `RTL` | If true, display right-to-left |
#### Miscellaneous Workbook Properties
`wb.Workbook.WBProps` holds other workbook properties:
@ -1558,6 +1560,7 @@ The `type` argument for `write` mirrors the `type` argument for `read`:
| `"binary"` | string: binary string (byte `n` is `data.charCodeAt(n)`) |
| `"string"` | string: JS string (characters interpreted as UTF8) |
| `"buffer"` | nodejs Buffer |
| `"array"` | ArrayBuffer, fallback array of 8-bit unsigned int |
| `"file"` | string: path of file that will be created (nodejs only) |
## Utility Functions

@ -32,6 +32,7 @@
+ [Workbook File Properties](README.md#workbook-file-properties)
* [Workbook-Level Attributes](README.md#workbook-level-attributes)
+ [Defined Names](README.md#defined-names)
+ [Workbook Views](README.md#workbook-views)
+ [Miscellaneous Workbook Properties](README.md#miscellaneous-workbook-properties)
* [Document Features](README.md#document-features)
+ [Formulae](README.md#formulae)

@ -27,6 +27,7 @@ type Workbook = {
type WBWBProps = {
Sheets: Array<WBWSProp>;
Names?: Array<any>;
Views?: Array<any>;
WBProps?: WBProps;
};
@ -96,7 +97,14 @@ type SST = {
length:number;
};
type Comment = any;
type Comment = {
t:string;
a?:string;
r?:string;
h?:string;
};
type RawComment = any;
type RowInfo = {
hidden?:boolean; // if true, the row is hidden

@ -1,6 +1,6 @@
{
"name": "xlsx",
"version": "0.11.15",
"version": "0.11.16",
"author": "sheetjs",
"description": "SheetJS Spreadsheet data parser and writer",
"keywords": [

22
test.js

@ -655,6 +655,7 @@ describe('output formats', function() {
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(typeof ArrayBuffer !== 'undefined' && (typeof process == 'undefined' || !process.version.match(/v0.12/))) it('should write array buffers', function() { RT('array'); });
if(!browser) it('should write buffers', function() { RT('buffer'); });
it('should throw if format is unknown', function() { assert.throws(function() { RT('dafuq'); }); });
});
@ -819,10 +820,10 @@ describe('parse features', function() {
var wbs=[];
var bef = (function() {
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})
X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE, WTF:1}),
X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE, WTF:1}),
X.read(fs.readFileSync(paths.cpxls), {type:TYPE, WTF:1}),
X.read(fs.readFileSync(paths.cpxml), {type:TYPE, WTF:1})
];
});
if(typeof before != 'undefined') before(bef);
@ -1319,7 +1320,7 @@ describe('roundtrip features', function() {
}); });
describe('should preserve merge cells', function() {
["xlsx", "xlsb", "xlml", "ods"].forEach(function(f) { it(f, function() {
["xlsx", "xlsb", "xlml", "ods", "biff8"].forEach(function(f) { it(f, function() {
var wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE});
var wb2 = X.read(X.write(wb1,{bookType:f,type:'binary'}),{type:'binary'});
var m1 = wb1.Sheets.Merge['!merges'].map(X.utils.encode_range);
@ -1911,8 +1912,15 @@ describe('HTML', function() {
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); });
it('should handle newlines correctly', function() {
var table = get_dom_element("<table><tr><td>foo<br/>bar</td><td>baz</td></tr></table>");
var wb = X.utils.table_to_book(table);
assert.equal(get_cell(wb.Sheets.Sheet1, "A1").v, "foo\nbar");
var ws = X.utils.table_to_sheet(table);
assert.equal(get_cell(ws, "A1").v, "foo\nbar");
});
it('should trim whitespace', function() {
if(get_dom_element("foo <br> bar").innerHTML != "foo <br> bar") return;
var table = get_dom_element("<table><tr><td> foo <br/> bar </td><td> baz qux </td></tr></table>");
var ws = X.utils.table_to_sheet(table);
assert.equal(get_cell(ws, "A1").v.replace(/\n/g, "|"), "foo | bar");
assert.equal(get_cell(ws, "B1").v, "baz qux");
});
});
if(domtest) it('should handle entities', function() {

22
tests/core.js generated

@ -655,6 +655,7 @@ describe('output formats', function() {
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(typeof ArrayBuffer !== 'undefined' && (typeof process == 'undefined' || !process.version.match(/v0.12/))) it('should write array buffers', function() { RT('array'); });
if(!browser) it('should write buffers', function() { RT('buffer'); });
it('should throw if format is unknown', function() { assert.throws(function() { RT('dafuq'); }); });
});
@ -819,10 +820,10 @@ describe('parse features', function() {
var wbs=[];
var bef = (function() {
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})
X.read(fs.readFileSync(paths.cpxlsx), {type:TYPE, WTF:1}),
X.read(fs.readFileSync(paths.cpxlsb), {type:TYPE, WTF:1}),
X.read(fs.readFileSync(paths.cpxls), {type:TYPE, WTF:1}),
X.read(fs.readFileSync(paths.cpxml), {type:TYPE, WTF:1})
];
});
if(typeof before != 'undefined') before(bef);
@ -1319,7 +1320,7 @@ describe('roundtrip features', function() {
}); });
describe('should preserve merge cells', function() {
["xlsx", "xlsb", "xlml", "ods"].forEach(function(f) { it(f, function() {
["xlsx", "xlsb", "xlml", "ods", "biff8"].forEach(function(f) { it(f, function() {
var wb1 = X.read(fs.readFileSync(paths.mcxlsx), {type:TYPE});
var wb2 = X.read(X.write(wb1,{bookType:f,type:'binary'}),{type:'binary'});
var m1 = wb1.Sheets.Merge['!merges'].map(X.utils.encode_range);
@ -1911,8 +1912,15 @@ describe('HTML', function() {
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); });
it('should handle newlines correctly', function() {
var table = get_dom_element("<table><tr><td>foo<br/>bar</td><td>baz</td></tr></table>");
var wb = X.utils.table_to_book(table);
assert.equal(get_cell(wb.Sheets.Sheet1, "A1").v, "foo\nbar");
var ws = X.utils.table_to_sheet(table);
assert.equal(get_cell(ws, "A1").v, "foo\nbar");
});
it('should trim whitespace', function() {
if(get_dom_element("foo <br> bar").innerHTML != "foo <br> bar") return;
var table = get_dom_element("<table><tr><td> foo <br/> bar </td><td> baz qux </td></tr></table>");
var ws = X.utils.table_to_sheet(table);
assert.equal(get_cell(ws, "A1").v.replace(/\n/g, "|"), "foo | bar");
assert.equal(get_cell(ws, "B1").v, "baz qux");
});
});
if(domtest) it('should handle entities', function() {

@ -1,6 +1,8 @@
/* writing feature test -- look for TEST: in comments */
/* vim: set ts=2 ft=javascript: */
var ext = !!process.argv[2];
/* original data */
var data = [
[1, 2, 3],
@ -108,6 +110,9 @@ XLSX.utils.cell_set_number_format(ws['C2'], custfmt);
/* TEST: page margins */
ws['!margins'] = { left:1.0, right:1.0, top:1.0, bottom:1.0, header:0.5, footer:0.5 };
/* TEST: merge cells */
ws['!merges'] = [ XLSX.utils.decode_range("A6:C6") ];
console.log("JSON Data:");
console.log(XLSX.utils.sheet_to_json(ws, {header:1}));
@ -158,7 +163,7 @@ ws['!protect'] = {
if(!wb.Workbook) wb.Workbook = {Sheets:[], WBProps:{}};
if(!wb.Workbook.WBProps) wb.Workbook.WBProps = {};
wb.Workbook.WBProps.filterPrivacy = true;
//wb.Workbook.Views = [{RTL:true}];
if(ext) wb.Workbook.Views = [{RTL:true}];
console.log("Worksheet Model:");
console.log(ws);
@ -167,10 +172,12 @@ var filenames = [
['sheetjs.xlsx', {bookSST:true}],
['sheetjs.xlsm'],
['sheetjs.xlsb'],
['sheetjs.xlam'],
['sheetjs.biff8.xls', {bookType:'xls'}],
['sheetjs.biff5.xls', {bookType:'biff5'}],
['sheetjs.biff2.xls', {bookType:'biff2'}],
['sheetjs.xml.xls', {bookType:'xlml'}],
['sheetjs.xla'],
['sheetjs.ods'],
['sheetjs.fods'],
['sheetjs.csv'],

@ -19,10 +19,12 @@ program
.option('-B, --xlsb', 'emit XLSB to <sheetname> or <file>.xlsb')
.option('-M, --xlsm', 'emit XLSM to <sheetname> or <file>.xlsm')
.option('-X, --xlsx', 'emit XLSX to <sheetname> or <file>.xlsx')
.option('-I, --xlam', 'emit XLAM to <sheetname> or <file>.xlam')
.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('-2, --biff2','emit XLS to <sheetname> or <file>.xls (BIFF2)')
.option('-i, --xla', 'emit XLA to <sheetname> or <file>.xla')
.option('-6, --xlml', 'emit SSML to <sheetname> or <file>.xls (2003 XML)')
.option('-T, --fods', 'emit FODS to <sheetname> or <file>.fods (Flat ODS)')
@ -42,6 +44,8 @@ program
.option('-F, --field-sep <sep>', 'CSV field separator', ",")
.option('-R, --row-sep <sep>', 'CSV row separator', "\n")
.option('-n, --sheet-rows <num>', 'Number of rows to process (0=all rows)')
.option('--codepage <cp>', 'default to specified codepage when ambiguous')
.option('--req <module>', 'require module before processing')
.option('--sst', 'generate shared string table for XLS* formats')
.option('--compress', 'use compression when writing XLSX/M/B and ODS')
.option('--read', 'read but do not generate output')
@ -61,8 +65,10 @@ program.on('--help', function() {
const workbook_formats = [
['xlsx', 'xlsx', 'xlsx'],
['xlsm', 'xlsm', 'xlsm'],
['xlam', 'xlam', 'xlam'],
['xlsb', 'xlsb', 'xlsb'],
['xls', 'xls', 'xls'],
['xla', 'xla', 'xla'],
['biff5', 'biff5', 'xls'],
['ods', 'ods', 'ods'],
['fods', 'fods', 'fods']
@ -126,6 +132,7 @@ if(program.all) {
wopts.bookVBA = true;
}
if(program.sparse) opts.dense = false; else opts.dense = true;
if(program.codepage) opts.codepage = +program.codepage;
if(program.dev) {
opts.WTF = true;

@ -51,6 +51,8 @@ read_opts.type = "buffer";
const wb3 = XLSX.read(fs.readFileSync("sheetjs.xlsx"), read_opts);
write_opts.type = "base64";
const out3 = XLSX.write(wb3, write_opts);
write_opts.type = "array";
const out4 = XLSX.write(wb3, write_opts);
const ws1 = XLSX.utils.aoa_to_sheet([
"SheetJS".split(""),

15
types/index.d.ts vendored

@ -110,6 +110,9 @@ export interface ParsingOptions extends CommonOptions {
/** Input data encoding */
type?: 'base64' | 'binary' | 'buffer' | 'file' | 'array';
/** Default codepage */
codepage?: number;
/**
* Save formulae to the .f field
* @default true
@ -188,7 +191,7 @@ export interface ParsingOptions extends CommonOptions {
/** Options for write and writeFile */
export interface WritingOptions extends CommonOptions {
/** Output data encoding */
type?: 'base64' | 'binary' | 'buffer' | 'file';
type?: 'base64' | 'binary' | 'buffer' | 'file' | 'array';
/**
* Generate Shared String Table
@ -272,12 +275,18 @@ export interface WBProps {
Names?: DefinedName[];
/** Workbook Views */
Views?: any[];
Views?: WBView[];
/** Other Workbook Properties */
WBProps?: WorkbookProperties;
}
/** Workbook View */
export interface WBView {
/** Right-to-left mode */
RTL?: boolean;
}
/** Other Workbook Properties */
export interface WorkbookProperties {
/** Worksheet Epoch (1904 if true, 1900 if false) */
@ -493,7 +502,7 @@ export type ExcelDataType = 'b' | 'n' | 'e' | 's' | 'd' | 'z';
* Type of generated workbook
* @default 'xlsx'
*/
export type BookType = 'xlsx' | 'xlsm' | 'xlsb' | 'xls' | 'biff8' | 'biff5' | 'biff2' | 'xlml' | 'ods' | 'fods' | 'csv' | 'txt' | 'sylk' | 'html' | 'dif' | 'rtf' | 'prn' | 'eth';
export type BookType = 'xlsx' | 'xlsm' | 'xlsb' | 'xls' | 'xla' | 'biff8' | 'biff5' | 'biff2' | 'xlml' | 'ods' | 'fods' | 'csv' | 'txt' | 'sylk' | 'html' | 'dif' | 'rtf' | 'prn' | 'eth';
/** Comment element */
export interface Comment {

@ -96,6 +96,9 @@ XLSX.utils.cell_set_number_format(ws['C2'], custfmt);
/* TEST: page margins */
ws['!margins'] = { left:1.0, right:1.0, top:1.0, bottom:1.0, header:0.5, footer:0.5 };
/* TEST: merge cells */
ws['!merges'] = [ XLSX.utils.decode_range("A6:C6") ];
console.log("JSON Data:");
console.log(XLSX.utils.sheet_to_json(ws, {header:1}));
@ -153,10 +156,12 @@ const filenames: Array<[string]|[string, XLSX.WritingOptions]> = [
['sheetjs.xlsx', {bookSST:true}],
['sheetjs.xlsm'],
['sheetjs.xlsb'],
['sheetjs.xlam'],
['sheetjs.biff8.xls', {bookType:'xls'}],
['sheetjs.biff5.xls', {bookType:'biff5'}],
['sheetjs.biff2.xls', {bookType:'biff2'}],
['sheetjs.xml.xls', {bookType:'xlml'}],
['sheetjs.xla'],
['sheetjs.ods'],
['sheetjs.fods'],
['sheetjs.csv'],

File diff suppressed because it is too large Load Diff

614
xlsx.js generated

File diff suppressed because it is too large Load Diff