forked from sheetjs/sheetjs
version bump 0.11.6: ancillary format update
- BIFF5 XLS write (bookType "biff5") - DBF Level 7 read - ODS whitespace and repeated rows - flow and lint cleanup
This commit is contained in:
parent
ef9f3f9ca5
commit
f968dfe4ed
@ -2,7 +2,6 @@
|
||||
.*/node_modules/.*
|
||||
.*/dist/.*
|
||||
.*/tmp/.*
|
||||
.*/test.js
|
||||
|
||||
.*/bits/.*
|
||||
.*/ctest/.*
|
||||
@ -25,6 +24,7 @@ xlsxworker.flow.js
|
||||
xlsx.flow.js
|
||||
.*/bin/.*.njs
|
||||
.*/demo/browser.flow.js
|
||||
test.js
|
||||
|
||||
[libs]
|
||||
bits/09_types.js
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -27,3 +27,4 @@ tmp
|
||||
*.html
|
||||
*.sheetjs
|
||||
*.exe
|
||||
*.img
|
||||
|
@ -29,6 +29,7 @@ tmp
|
||||
*.html
|
||||
*.sheetjs
|
||||
*.exe
|
||||
*.img
|
||||
.gitignore
|
||||
.fossaignore
|
||||
.spelling
|
||||
|
@ -70,6 +70,8 @@ filesystem
|
||||
javascript
|
||||
metadata
|
||||
natively
|
||||
pre-built
|
||||
pre-generated
|
||||
prepend
|
||||
prepended
|
||||
repo
|
||||
|
@ -4,6 +4,10 @@ This log is intended to keep track of backwards-incompatible changes, including
|
||||
but not limited to API changes and file location changes. Minor behavioral
|
||||
changes may not be included if they are not expected to break existing code.
|
||||
|
||||
## 0.11.6 (2017-10-16)
|
||||
|
||||
* Semicolon-delimited files are detected
|
||||
|
||||
## 0.11.5 (2017-09-30)
|
||||
|
||||
* Bower main script shifted to full version
|
||||
|
2
Makefile
2
Makefile
@ -213,7 +213,7 @@ book: readme graph ## Update summary for documentation
|
||||
<README.md grep -vE "(details|summary)>" > misc/docs/README.md
|
||||
|
||||
DEMOMDS=$(sort $(wildcard demos/*/README.md))
|
||||
MDLINT=$(DEMODS) $(READEPS) demos/README.md
|
||||
MDLINT=$(DEMOMDS) $(READEPS) demos/README.md
|
||||
.PHONY: mdlint
|
||||
mdlint: $(MDLINT) ## Check markdown documents
|
||||
alex $^
|
||||
|
12
README.md
12
README.md
@ -1565,8 +1565,9 @@ Plain text format guessing follows the priority order:
|
||||
| XML | starts with `<` |
|
||||
| RTF | starts with `{\rt` |
|
||||
| DSV | starts with `/sep=.$/`, separator is the specified character |
|
||||
| CSV | more unquoted `","` characters than `"\t"` chars in the first 1024 |
|
||||
| TSV | one of the first 1024 characters is a tab char `"\t"` |
|
||||
| DSV | more unquoted `";"` chars than `"\t"` or `","` in the first 1024 |
|
||||
| TSV | more unquoted `"\t"` chars than `","` chars in the first 1024 |
|
||||
| CSV | one of the first 1024 characters is a comma `","` |
|
||||
| PRN | (default) |
|
||||
|
||||
- HTML tags include: `html`, `table`, `head`, `meta`, `script`, `style`, `div`
|
||||
@ -1629,6 +1630,7 @@ output formats. The specific file type is controlled with `bookType` option:
|
||||
| `xlsm` | `.xlsm` | ZIP | multi | Excel 2007+ Macro XML Format |
|
||||
| `xlsb` | `.xlsb` | ZIP | multi | Excel 2007+ Binary Format |
|
||||
| `biff8` | `.xls` | CFB | multi | Excel 97-2004 Workbook Format |
|
||||
| `biff5` | `.xls` | CFB | multi | Excel 5.0/95 Workbook Format |
|
||||
| `biff2` | `.xls` | none | single | Excel 2.0 Worksheet Format |
|
||||
| `xlml` | `.xls` | none | multi | Excel 2003-2004 (SpreadsheetML) |
|
||||
| `ods` | `.ods` | ZIP | multi | OpenDocument Spreadsheet |
|
||||
@ -1638,7 +1640,7 @@ output formats. The specific file type is controlled with `bookType` option:
|
||||
| `sylk` | `.sylk` | none | single | Symbolic Link (SYLK) |
|
||||
| `html` | `.html` | none | single | HTML Document |
|
||||
| `dif` | `.dif` | none | single | Data Interchange Format (DIF) |
|
||||
| `rtf` | `.rtf` | none | single | Rich Text Format |
|
||||
| `rtf` | `.rtf` | none | single | Rich Text Format (RTF) |
|
||||
| `prn` | `.prn` | none | single | Lotus Formatted Text |
|
||||
|
||||
- `compression` only applies to formats with ZIP containers.
|
||||
@ -1957,7 +1959,7 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
|
||||
| Excel 2007+ Binary Format (XLSB BIFF12) | :o: | :o: |
|
||||
| Excel 2003-2004 XML Format (XML "SpreadsheetML") | :o: | :o: |
|
||||
| Excel 97-2004 (XLS BIFF8) | :o: | :o: |
|
||||
| Excel 5.0/95 (XLS BIFF5) | :o: | |
|
||||
| Excel 5.0/95 (XLS BIFF5) | :o: | :o: |
|
||||
| Excel 4.0 (XLS/XLW BIFF4) | :o: | |
|
||||
| Excel 3.0 (XLS BIFF3) | :o: | |
|
||||
| Excel 2.0/2.1 (XLS BIFF2) | :o: | :o: |
|
||||
@ -1976,7 +1978,7 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
|
||||
| Quattro Pro Spreadsheet (WQ1/WQ2/WB1/WB2/WB3/QPW) | :o: | |
|
||||
| **Other Common Spreadsheet Output Formats** |:-----:|:-----:|
|
||||
| HTML Tables | :o: | :o: |
|
||||
| RTF Tables | | :o: |
|
||||
| Rich Text Format tables (RTF) | | :o: |
|
||||
|
||||
### Excel 2007+ XML (XLSX/XLSM)
|
||||
|
||||
|
@ -21,7 +21,7 @@ program
|
||||
.option('-X, --xlsx', 'emit XLSX to <sheetname> or <file>.xlsx')
|
||||
.option('-Y, --ods', 'emit ODS to <sheetname> or <file>.ods')
|
||||
.option('-8, --xls', 'emit XLS to <sheetname> or <file>.xls (BIFF8)')
|
||||
//.option('-5, --biff5','emit XLS to <sheetname> or <file>.xls (BIFF5)')
|
||||
.option('-5, --biff5','emit XLS to <sheetname> or <file>.xls (BIFF5)')
|
||||
//.option('-4, --biff4','emit XLS to <sheetname> or <file>.xls (BIFF4)')
|
||||
//.option('-3, --biff3','emit XLS to <sheetname> or <file>.xls (BIFF3)')
|
||||
.option('-2, --biff2','emit XLS to <sheetname> or <file>.xls (BIFF2)')
|
||||
@ -44,11 +44,10 @@ program
|
||||
.option('-n, --sheet-rows <num>', 'Number of rows to process (0=all rows)')
|
||||
.option('--sst', 'generate shared string table for XLS* formats')
|
||||
.option('--compress', 'use compression when writing XLSX/M/B and ODS')
|
||||
.option('--read-only', 'do not generate output')
|
||||
.option('--read', 'read but do not generate output')
|
||||
.option('--all', 'parse everything; write as much as possible')
|
||||
.option('--dev', 'development mode')
|
||||
.option('--sparse', 'sparse mode')
|
||||
.option('--read', 'read but do not print out contents')
|
||||
.option('-q, --quiet', 'quiet mode');
|
||||
|
||||
program.on('--help', function() {
|
||||
@ -176,9 +175,8 @@ try {
|
||||
process.exit(4);
|
||||
}
|
||||
|
||||
if(program.readOnly) process.exit(0);
|
||||
|
||||
/* single worksheet formats */
|
||||
/* single worksheet file formats */
|
||||
[
|
||||
['biff2', '.xls'],
|
||||
['biff3', '.xls'],
|
||||
|
@ -1,7 +1,5 @@
|
||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
/* vim: set ts=2: */
|
||||
/*jshint -W041 */
|
||||
/*jshint funcscope:true, eqnull:true, loopfunc:true */
|
||||
/*exported XLSX */
|
||||
/*global global, exports, module, require:false, process:false, Buffer:false */
|
||||
var XLSX = {};
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.11.5';
|
||||
XLSX.version = '0.11.6';
|
||||
|
@ -28,14 +28,14 @@ var debom = function(data/*:string*/)/*:string*/ {
|
||||
return data;
|
||||
};
|
||||
|
||||
var _getchar = function _gc1(x) { return String.fromCharCode(x); };
|
||||
var _getchar = function _gc1(x/*:number*/)/*:string*/ { return String.fromCharCode(x); };
|
||||
if(typeof cptable !== 'undefined') {
|
||||
set_cp = function(cp) { current_codepage = cp; };
|
||||
debom = function(data) {
|
||||
set_cp = function(cp/*:number*/) { current_codepage = cp; };
|
||||
debom = function(data/*:string*/) {
|
||||
if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.substr(2))); }
|
||||
return data;
|
||||
};
|
||||
_getchar = function _gc2(x) {
|
||||
_getchar = function _gc2(x/*:number*/)/*:string*/ {
|
||||
if(current_codepage === 1200) return String.fromCharCode(x);
|
||||
return cptable.utils.decode(current_codepage, [x&255,x>>8])[0];
|
||||
};
|
||||
|
@ -102,7 +102,7 @@ var utf8read/*:StringConv*/ = function utf8reada(orig) {
|
||||
};
|
||||
|
||||
var utf8write/*:StringConv*/ = function(orig) {
|
||||
var out = [], i = 0, c = 0, d = 0;
|
||||
var out/*:Array<string>*/ = [], i = 0, c = 0, d = 0;
|
||||
while(i < orig.length) {
|
||||
c = orig.charCodeAt(i++);
|
||||
switch(true) {
|
||||
@ -197,7 +197,7 @@ function writextag(f,g,h) { return '<' + f + (isval(h) /*:: && h */? wxt_helper(
|
||||
|
||||
function write_w3cdtf(d/*:Date*/, t/*:?boolean*/)/*:string*/ { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } return ""; }
|
||||
|
||||
function write_vt(s) {
|
||||
function write_vt(s)/*:string*/ {
|
||||
switch(typeof s) {
|
||||
case 'string': return writextag('vt:lpwstr', s);
|
||||
case 'number': return writextag((s|0)==s?'vt:i4':'vt:r8', String(s));
|
||||
|
@ -74,6 +74,7 @@ var __readUInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/
|
||||
var __readInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; };
|
||||
var __readUInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
|
||||
var __readInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
|
||||
var __readInt32BE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx]<<24)|(b[idx+1]<<16)|(b[idx+2]<<8)|b[idx+3]; };
|
||||
|
||||
var ___unhexlify = function(s/*:string*/)/*:Array<number>*/ { return (s.match(/../g)||[]).map(function(x) { return parseInt(x,16);}); };
|
||||
var __unhexlify = typeof Buffer !== "undefined" ? function(s/*:string*/)/*:Array<number>|Buffer*/ { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;
|
||||
@ -141,10 +142,15 @@ function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ {
|
||||
switch(size) {
|
||||
case 1: oI = __readUInt8(this, this.l); this.l++; return oI;
|
||||
case 2: oI = (t === 'i' ? __readInt16LE : __readUInt16LE)(this, this.l); this.l += 2; return oI;
|
||||
case 4:
|
||||
if(t === 'i' || (this[this.l+3] & 0x80)===0) { oI = __readInt32LE(this, this.l); this.l += 4; return oI; }
|
||||
case 4: case -4:
|
||||
if(t === 'i' || (this[this.l+3] & 0x80)===0) { oI = (size > 0 ? __readInt32LE : __readInt32BE)(this, this.l); this.l += 4; return oI; }
|
||||
else { oR = __readUInt32LE(this, this.l); this.l += 4; } return oR;
|
||||
case 8: if(t === 'f') { oR = __double(this, this.l); this.l += 8; return oR; }
|
||||
case 8: case -8:
|
||||
if(t === 'f') {
|
||||
if(size == 8) oR = __double(this, this.l);
|
||||
else oR = __double([this[this.l+7],this[this.l+6],this[this.l+5],this[this.l+4],this[this.l+3],this[this.l+2],this[this.l+1],this[this.l+0]], 0);
|
||||
this.l += 8; return oR;
|
||||
} else size = 8;
|
||||
/* falls through */
|
||||
case 16: o = __hexlify(this, this.l, size); break;
|
||||
}}
|
||||
@ -162,6 +168,9 @@ function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/)/*:any*/
|
||||
for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i);
|
||||
size = 2 * val.length;
|
||||
} else if(f === 'sbcs') {
|
||||
/* TODO: codepage */
|
||||
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
|
||||
val = val.replace(/[^\x00-\x7F]/g, "_");
|
||||
/*:: if(typeof val !== 'string') throw new Error("unreachable"); */
|
||||
for(i = 0; i != val.length; ++i) this[this.l + i] = val.charCodeAt(i) & 0xFF;
|
||||
size = val.length;
|
||||
|
@ -1,45 +1,43 @@
|
||||
/* [MS-OLEPS] 2.2 PropertyType */
|
||||
{
|
||||
//var VT_EMPTY = 0x0000;
|
||||
//var VT_NULL = 0x0001;
|
||||
var VT_I2 = 0x0002;
|
||||
var VT_I4 = 0x0003;
|
||||
//var VT_R4 = 0x0004;
|
||||
//var VT_R8 = 0x0005;
|
||||
//var VT_CY = 0x0006;
|
||||
//var VT_DATE = 0x0007;
|
||||
//var VT_BSTR = 0x0008;
|
||||
//var VT_ERROR = 0x000A;
|
||||
var VT_BOOL = 0x000B;
|
||||
var VT_VARIANT = 0x000C;
|
||||
//var VT_DECIMAL = 0x000E;
|
||||
//var VT_I1 = 0x0010;
|
||||
//var VT_UI1 = 0x0011;
|
||||
//var VT_UI2 = 0x0012;
|
||||
var VT_UI4 = 0x0013;
|
||||
//var VT_I8 = 0x0014;
|
||||
var VT_UI8 = 0x0015;
|
||||
//var VT_INT = 0x0016;
|
||||
//var VT_UINT = 0x0017;
|
||||
var VT_LPSTR = 0x001E;
|
||||
//var VT_LPWSTR = 0x001F;
|
||||
var VT_FILETIME = 0x0040;
|
||||
//var VT_BLOB = 0x0041;
|
||||
//var VT_STREAM = 0x0042;
|
||||
//var VT_STORAGE = 0x0043;
|
||||
//var VT_STREAMED_Object = 0x0044;
|
||||
//var VT_STORED_Object = 0x0045;
|
||||
//var VT_BLOB_Object = 0x0046;
|
||||
var VT_CF = 0x0047;
|
||||
//var VT_CLSID = 0x0048;
|
||||
//var VT_VERSIONED_STREAM = 0x0049;
|
||||
var VT_VECTOR = 0x1000;
|
||||
//var VT_ARRAY = 0x2000;
|
||||
//var VT_EMPTY = 0x0000;
|
||||
//var VT_NULL = 0x0001;
|
||||
var VT_I2 = 0x0002;
|
||||
var VT_I4 = 0x0003;
|
||||
//var VT_R4 = 0x0004;
|
||||
//var VT_R8 = 0x0005;
|
||||
//var VT_CY = 0x0006;
|
||||
//var VT_DATE = 0x0007;
|
||||
//var VT_BSTR = 0x0008;
|
||||
//var VT_ERROR = 0x000A;
|
||||
var VT_BOOL = 0x000B;
|
||||
var VT_VARIANT = 0x000C;
|
||||
//var VT_DECIMAL = 0x000E;
|
||||
//var VT_I1 = 0x0010;
|
||||
//var VT_UI1 = 0x0011;
|
||||
//var VT_UI2 = 0x0012;
|
||||
var VT_UI4 = 0x0013;
|
||||
//var VT_I8 = 0x0014;
|
||||
var VT_UI8 = 0x0015;
|
||||
//var VT_INT = 0x0016;
|
||||
//var VT_UINT = 0x0017;
|
||||
var VT_LPSTR = 0x001E;
|
||||
//var VT_LPWSTR = 0x001F;
|
||||
var VT_FILETIME = 0x0040;
|
||||
//var VT_BLOB = 0x0041;
|
||||
//var VT_STREAM = 0x0042;
|
||||
//var VT_STORAGE = 0x0043;
|
||||
//var VT_STREAMED_Object = 0x0044;
|
||||
//var VT_STORED_Object = 0x0045;
|
||||
//var VT_BLOB_Object = 0x0046;
|
||||
var VT_CF = 0x0047;
|
||||
//var VT_CLSID = 0x0048;
|
||||
//var VT_VERSIONED_STREAM = 0x0049;
|
||||
var VT_VECTOR = 0x1000;
|
||||
//var VT_ARRAY = 0x2000;
|
||||
|
||||
var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
|
||||
var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString
|
||||
var VT_CUSTOM = [VT_STRING, VT_USTR];
|
||||
}
|
||||
var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
|
||||
var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString
|
||||
var VT_CUSTOM = [VT_STRING, VT_USTR];
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */
|
||||
var DocSummaryPIDDSI = {
|
||||
|
@ -56,9 +56,9 @@ function write_rdf(rdf, opts) {
|
||||
return o.join("");
|
||||
}
|
||||
/* TODO: pull properties */
|
||||
var write_meta_ods/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
var write_meta_ods/*:{(wb:Workbook, opts:any):string}*/ = (function() {
|
||||
var payload = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
|
||||
return function wmo(wb, opts) {
|
||||
return function wmo(wb/*:Workbook*/, opts) {
|
||||
return payload;
|
||||
};
|
||||
})();
|
||||
|
@ -108,7 +108,7 @@ function parse_VtVector(blob, cb) {
|
||||
}
|
||||
|
||||
/* [MS-OLEPS] 2.15 TypedPropertyValue */
|
||||
function parse_TypedPropertyValue(blob, type/*:number*/, _opts) {
|
||||
function parse_TypedPropertyValue(blob, type/*:number*/, _opts)/*:any*/ {
|
||||
var t = blob.read_shift(2), ret, opts = _opts||{};
|
||||
blob.l += 2;
|
||||
if(type !== VT_VARIANT)
|
||||
@ -193,12 +193,12 @@ function parse_PropertySet(blob, PIDSI) {
|
||||
case 1252:
|
||||
case 65000: case -536:
|
||||
case 65001: case -535:
|
||||
set_cp(CodePage = PropH[piddsi.n]>>>0 & 0xFFFF); break;
|
||||
set_cp(CodePage = (PropH[piddsi.n]>>>0) & 0xFFFF); break;
|
||||
default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
|
||||
}
|
||||
} else {
|
||||
if(Props[i][0] === 0x1) {
|
||||
CodePage = PropH.CodePage = parse_TypedPropertyValue(blob, VT_I2);
|
||||
CodePage = PropH.CodePage = (parse_TypedPropertyValue(blob, VT_I2)/*:number*/);
|
||||
set_cp(CodePage);
|
||||
if(Dictionary !== -1) {
|
||||
var oldpos = blob.l;
|
||||
|
@ -201,7 +201,8 @@ function parse_WriteAccess(blob, length, opts) {
|
||||
return UserName;
|
||||
}
|
||||
function write_WriteAccess(s/*:string*/, opts) {
|
||||
var o = new_buf(112);
|
||||
var b8 = !opts || opts.biff == 8;
|
||||
var o = new_buf(b8 ? 112 : 54);
|
||||
o.write_shift(opts.biff == 8 ? 2 : 1, 7);
|
||||
o.write_shift(1, 0);
|
||||
o.write_shift(4, 0x33336853);
|
||||
@ -226,14 +227,15 @@ function parse_BoundSheet8(blob, length, opts) {
|
||||
return { pos:pos, hs:hidden, dt:dt, name:name };
|
||||
}
|
||||
function write_BoundSheet8(data, opts) {
|
||||
var o = new_buf(8 + 2 * data.name.length);
|
||||
var w = (!opts || opts.biff >= 8 ? 2 : 1);
|
||||
var o = new_buf(8 + w * data.name.length);
|
||||
o.write_shift(4, data.pos);
|
||||
o.write_shift(1, data.hs || 0);
|
||||
o.write_shift(1, data.dt);
|
||||
o.write_shift(1, data.name.length);
|
||||
o.write_shift(1, 1);
|
||||
o.write_shift(2 * data.name.length, data.name, 'utf16le');
|
||||
return o;
|
||||
if(opts.biff >= 8) o.write_shift(1, 1);
|
||||
o.write_shift(w * data.name.length, data.name, opts.biff < 8 ? 'sbcs' : 'utf16le');
|
||||
return o.slice(0, o.l);
|
||||
}
|
||||
|
||||
/* 2.4.265 TODO */
|
||||
@ -362,11 +364,12 @@ function parse_Label(blob, length, opts) {
|
||||
return cell;
|
||||
}
|
||||
function write_Label(R/*:number*/, C/*:number*/, v/*:string*/, opts) {
|
||||
var o = new_buf(6 + 3 + 2 * v.length);
|
||||
var b8 = !opts || opts.biff == 8;
|
||||
var o = new_buf(6 + 2 + (+b8) + (1 + b8) * v.length);
|
||||
write_XLSCell(R, C, 0, o);
|
||||
o.write_shift(2, v.length);
|
||||
o.write_shift(1, 1);
|
||||
o.write_shift(2 * v.length, v, 'utf16le');
|
||||
if(b8) o.write_shift(1, 1);
|
||||
o.write_shift((1 + b8) * v.length, v, b8 ? 'utf16le' : 'sbcs');
|
||||
return o;
|
||||
}
|
||||
|
||||
@ -389,9 +392,10 @@ function parse_Dimensions(blob, length, opts) {
|
||||
return {s: {r:r, c:c}, e: {r:R, c:C}};
|
||||
}
|
||||
function write_Dimensions(range, opts) {
|
||||
var o = new_buf(14);
|
||||
o.write_shift(4, range.s.r);
|
||||
o.write_shift(4, range.e.r + 1);
|
||||
var w = opts.biff == 8 || !opts.biff ? 4 : 2;
|
||||
var o = new_buf(2*w + 6);
|
||||
o.write_shift(w, range.s.r);
|
||||
o.write_shift(w, range.e.r + 1);
|
||||
o.write_shift(2, range.s.c);
|
||||
o.write_shift(2, range.e.c + 1);
|
||||
o.write_shift(2, 0);
|
||||
@ -598,7 +602,7 @@ function parse_Lbl(blob, length, opts) {
|
||||
var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
|
||||
if(flags & 0x20) name = XLSLblBuiltIn[name.charCodeAt(0)];
|
||||
var npflen = target - blob.l; if(opts && opts.biff == 2) --npflen;
|
||||
var rgce = target == blob.l || cce == 0 ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
|
||||
var rgce = target == blob.l || cce === 0 ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
|
||||
return {
|
||||
chKey: chKey,
|
||||
Name: name,
|
||||
|
@ -55,13 +55,14 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
|
||||
/* header */
|
||||
var ft = d.read_shift(1);
|
||||
var memo = false;
|
||||
var vfp = false;
|
||||
var vfp = false, l7 = false;
|
||||
switch(ft) {
|
||||
case 0x02: case 0x03: break;
|
||||
case 0x30: vfp = true; memo = true; break;
|
||||
case 0x31: vfp = true; break;
|
||||
case 0x83: memo = true; break;
|
||||
case 0x8B: memo = true; break;
|
||||
case 0x8C: memo = true; l7 = true; break;
|
||||
case 0xF5: memo = true; break;
|
||||
default: throw new Error("DBF Unsupported Version: " + ft.toString(16));
|
||||
}
|
||||
@ -84,36 +85,42 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
|
||||
|
||||
d.l+=2;
|
||||
}
|
||||
if(l7) d.l += 36;
|
||||
var fields = [], field = {};
|
||||
var hend = fpos - 10 - (vfp ? 264 : 0);
|
||||
var hend = fpos - 10 - (vfp ? 264 : 0), ww = l7 ? 32 : 11;
|
||||
while(ft == 0x02 ? d.l < d.length && d[d.l] != 0x0d: d.l < hend) {
|
||||
field = {};
|
||||
field.name = cptable.utils.decode(current_cp, d.slice(d.l, d.l+10)).replace(/[\u0000\r\n].*$/g,"");
|
||||
d.l += 11;
|
||||
field.name = cptable.utils.decode(current_cp, d.slice(d.l, d.l+ww)).replace(/[\u0000\r\n].*$/g,"");
|
||||
d.l += ww;
|
||||
field.type = String.fromCharCode(d.read_shift(1));
|
||||
if(ft != 0x02) field.offset = d.read_shift(4);
|
||||
if(ft != 0x02 && !l7) field.offset = d.read_shift(4);
|
||||
field.len = d.read_shift(1);
|
||||
if(ft == 0x02) field.offset = d.read_shift(2);
|
||||
field.dec = d.read_shift(1);
|
||||
if(field.name.length) fields.push(field);
|
||||
if(ft != 0x02) d.l += 14;
|
||||
if(ft != 0x02) d.l += l7 ? 13 : 14;
|
||||
switch(field.type) {
|
||||
// case 'B': break; // Binary
|
||||
case 'C': break; // character
|
||||
case 'D': break; // date
|
||||
case 'F': break; // floating point
|
||||
// case 'G': break; // General
|
||||
case 'I': break; // long
|
||||
case 'L': break; // boolean
|
||||
case 'M': break; // memo
|
||||
case 'N': break; // number
|
||||
// case 'O': break; // double
|
||||
// case 'P': break; // Picture
|
||||
case 'T': break; // datetime
|
||||
case 'Y': break; // currency
|
||||
case '0': break; // null ?
|
||||
case '+': break; // autoincrement
|
||||
case '@': break; // timestamp
|
||||
case 'B': // VFP Double
|
||||
if((!vfp || field.len != 8) && opts.WTF) console.log('Skipping ' + field.name + ':' + field.type);
|
||||
break;
|
||||
case 'G': // General
|
||||
case 'P': // Picture
|
||||
if(opts.WTF) console.log('Skipping ' + field.name + ':' + field.type);
|
||||
break;
|
||||
case 'C': // character
|
||||
case 'D': // date
|
||||
case 'F': // floating point
|
||||
case 'I': // long
|
||||
case 'L': // boolean
|
||||
case 'M': // memo
|
||||
case 'N': // number
|
||||
case 'O': // double
|
||||
case 'T': // datetime
|
||||
case 'Y': // currency
|
||||
case '0': // VFP _NullFlags
|
||||
case '@': // timestamp
|
||||
case '+': // autoincrement
|
||||
break;
|
||||
default: throw new Error('Unknown Field Type: ' + field.type);
|
||||
}
|
||||
}
|
||||
@ -145,7 +152,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
|
||||
else out[R][C] = s;
|
||||
break;
|
||||
case 'F': out[R][C] = parseFloat(s.trim()); break;
|
||||
case 'I': out[R][C] = dd.read_shift(4, 'i'); break;
|
||||
case '+': case 'I': out[R][C] = l7 ? dd.read_shift(-4, 'i') ^ 0x80000000 : dd.read_shift(4, 'i'); break;
|
||||
case 'L': switch(s.toUpperCase()) {
|
||||
case 'Y': case 'T': out[R][C] = true; break;
|
||||
case 'N': case 'F': out[R][C] = false; break;
|
||||
@ -154,15 +161,16 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
|
||||
} break;
|
||||
case 'M': /* TODO: handle memo files */
|
||||
if(!memo) throw new Error("DBF Unexpected MEMO for type " + ft.toString(16));
|
||||
out[R][C] = "##MEMO##" + dd.read_shift(4);
|
||||
out[R][C] = "##MEMO##" + (l7 ? parseInt(s.trim(), 10): dd.read_shift(4));
|
||||
break;
|
||||
case 'N': out[R][C] = +s.replace(/\u0000/g,"").trim(); break;
|
||||
case 'T':
|
||||
var day = dd.read_shift(4), ms = dd.read_shift(4);
|
||||
throw new Error(day + " | " + ms);
|
||||
//out[R][C] = new Date(); // TODO
|
||||
//break;
|
||||
case 'Y': out[R][C] = dd.read(4,'i')/1e4; break;
|
||||
case '@': out[R][C] = new Date(dd.read_shift(-8, 'f') - 0x388317533400); break;
|
||||
case 'T': out[R][C] = new Date((dd.read_shift(4) - 0x253D8C) * 0x5265C00 + dd.read_shift(4)); break;
|
||||
case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4; break;
|
||||
case 'O': out[R][C] = -dd.read_shift(-8, 'f'); break;
|
||||
case 'B': if(vfp && fields[C].len == 8) { out[R][C] = dd.read_shift(8,'f'); break; }
|
||||
/* falls through */
|
||||
case 'G': case 'P': dd.l += fields[C].len; break;
|
||||
case '0':
|
||||
if(fields[C].name === '_NullFlags') break;
|
||||
/* falls through */
|
||||
@ -269,7 +277,7 @@ var SYLK = (function() {
|
||||
cw = record[rj].substr(1).split(" ");
|
||||
for(j = parseInt(cw[0], 10); j <= parseInt(cw[1], 10); ++j) {
|
||||
Mval = parseInt(cw[2], 10);
|
||||
colinfo[j-1] = Mval == 0 ? {hidden:true}: {wch:Mval}; process_col(colinfo[j-1]);
|
||||
colinfo[j-1] = Mval === 0 ? {hidden:true}: {wch:Mval}; process_col(colinfo[j-1]);
|
||||
} break;
|
||||
case 'C': /* default column format */
|
||||
C = parseInt(record[rj].substr(1))-1;
|
||||
@ -279,7 +287,7 @@ var SYLK = (function() {
|
||||
R = parseInt(record[rj].substr(1))-1;
|
||||
if(!rowinfo[R]) rowinfo[R] = {};
|
||||
if(Mval > 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); }
|
||||
else if(Mval == 0) rowinfo[R].hidden = true;
|
||||
else if(Mval === 0) rowinfo[R].hidden = true;
|
||||
break;
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
}
|
||||
@ -514,16 +522,16 @@ var PRN = (function() {
|
||||
|
||||
// List of accepted CSV separators
|
||||
var guess_seps = {
|
||||
0x2C: ',',
|
||||
0x09: "\t",
|
||||
0x3B: ';'
|
||||
/*::[*/0x2C/*::]*/: ',',
|
||||
/*::[*/0x09/*::]*/: "\t",
|
||||
/*::[*/0x3B/*::]*/: ';'
|
||||
};
|
||||
|
||||
// CSV separator weights to be used in case of equal numbers
|
||||
var guess_sep_weights = {
|
||||
0x2C: 3,
|
||||
0x09: 2,
|
||||
0x3B: 1
|
||||
/*::[*/0x2C/*::]*/: 3,
|
||||
/*::[*/0x09/*::]*/: 2,
|
||||
/*::[*/0x3B/*::]*/: 1
|
||||
};
|
||||
|
||||
function guess_sep(str) {
|
||||
@ -567,9 +575,9 @@ var PRN = (function() {
|
||||
var s = str.slice(start, end);
|
||||
var cell = ({}/*:any*/);
|
||||
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
|
||||
if(s.length == 0) cell.t = 'z';
|
||||
if(s.length === 0) cell.t = 'z';
|
||||
else if(o.raw) { cell.t = 's'; cell.v = s; }
|
||||
else if(s.trim().length == 0) { cell.t = 's'; cell.v = s; }
|
||||
else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; }
|
||||
else if(s.charCodeAt(0) == 0x3D) {
|
||||
if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); }
|
||||
else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.substr(1); }
|
||||
@ -642,7 +650,7 @@ var PRN = (function() {
|
||||
if(!cell || cell.v == null) { oo.push(" "); continue; }
|
||||
var w = (cell.w || (format_cell(cell), cell.w) || "").substr(0,10);
|
||||
while(w.length < 10) w += " ";
|
||||
oo.push(w + (C == 0 ? " " : ""));
|
||||
oo.push(w + (C === 0 ? " " : ""));
|
||||
}
|
||||
o.push(oo.join(""));
|
||||
}
|
||||
|
@ -127,9 +127,9 @@ function parse_EncryptionVerifier(blob, length/*:number*/) {
|
||||
function parse_EncryptionInfo(blob, length/*:?number*/) {
|
||||
var vers = parse_CRYPTOVersion(blob);
|
||||
switch(vers.Minor) {
|
||||
case 0x02: return parse_EncInfoStd(blob, vers);
|
||||
case 0x03: return parse_EncInfoExt(blob, vers);
|
||||
case 0x04: return parse_EncInfoAgl(blob, vers);
|
||||
case 0x02: return [vers.Minor, parse_EncInfoStd(blob, vers)];
|
||||
case 0x03: return [vers.Minor, parse_EncInfoExt(blob, vers)];
|
||||
case 0x04: return [vers.Minor, parse_EncInfoAgl(blob, vers)];
|
||||
}
|
||||
throw new Error("ECMA-376 Encrypted file unrecognized Version: " + vers.Minor);
|
||||
}
|
||||
@ -147,7 +147,10 @@ function parse_EncInfoStd(blob, vers) {
|
||||
/* [MS-OFFCRYPTO] 2.3.4.6 EncryptionInfo Stream (Extensible Encryption) */
|
||||
function parse_EncInfoExt(blob, vers) { throw new Error("File is password-protected: ECMA-376 Extensible"); }
|
||||
/* [MS-OFFCRYPTO] 2.3.4.10 EncryptionInfo Stream (Agile Encryption) */
|
||||
function parse_EncInfoAgl(blob, vers) { throw new Error("File is password-protected: ECMA-376 Agile"); }
|
||||
function parse_EncInfoAgl(blob, vers) {
|
||||
blob.l+=4;
|
||||
return blob.read_shift(blob.length - blob.l, 'utf8');
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -282,7 +285,7 @@ function parse_XORObfuscation(blob, length, opts, out) {
|
||||
var o = ({ key: parseuint16(blob), verificationBytes: parseuint16(blob) }/*:any*/);
|
||||
if(opts.password) o.verifier = crypto_CreatePasswordVerifier_Method1(opts.password);
|
||||
out.valid = o.verificationBytes === o.verifier;
|
||||
if(out.valid) out.insitu_decrypt = crypto_MakeXorDecryptor(opts.password);
|
||||
if(out.valid) out.insitu = crypto_MakeXorDecryptor(opts.password);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
172
bits/62_fxls.js
172
bits/62_fxls.js
@ -53,6 +53,13 @@ function parse_RgceLoc_BIFF2(blob, length, opts) {
|
||||
return {r:r[0], c:c, cRel:r[1], rRel:r[2]};
|
||||
}
|
||||
|
||||
/* 2.5.198.107 , 2.5.47 */
|
||||
function parse_RgceElfLoc(blob, length, opts) {
|
||||
var r = blob.read_shift(2);
|
||||
var c = blob.read_shift(2);
|
||||
return {r:r, c:c & 0xFF, fQuoted:!!(c & 0x4000), cRel:c>>15, rRel:c>>15 };
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.5.198.111 TODO */
|
||||
/* [MS-XLSB] 2.5.97.92 TODO */
|
||||
function parse_RgceLocRel(blob, length, opts) {
|
||||
@ -446,6 +453,51 @@ var parse_PtgMemNoMem = parsenoop;
|
||||
/* 2.5.198.92 */
|
||||
var parse_PtgTbl = parsenoop;
|
||||
|
||||
function parse_PtgElfLoc(blob, length, opts) {
|
||||
blob.l += 2;
|
||||
return [parse_RgceElfLoc(blob, 4, opts)];
|
||||
}
|
||||
function parse_PtgElfNoop(blob, length, opts) {
|
||||
blob.l += 6;
|
||||
return [];
|
||||
}
|
||||
/* 2.5.198.46 */
|
||||
var parse_PtgElfCol = parse_PtgElfLoc;
|
||||
/* 2.5.198.47 */
|
||||
var parse_PtgElfColS = parse_PtgElfNoop;
|
||||
/* 2.5.198.48 */
|
||||
var parse_PtgElfColSV = parse_PtgElfNoop;
|
||||
/* 2.5.198.49 */
|
||||
var parse_PtgElfColV = parse_PtgElfLoc;
|
||||
/* 2.5.198.50 */
|
||||
function parse_PtgElfLel(blob, length, opts) {
|
||||
blob.l += 2;
|
||||
return [parseuint16(blob), blob.read_shift(2) & 0x01];
|
||||
}
|
||||
/* 2.5.198.51 */
|
||||
var parse_PtgElfRadical = parse_PtgElfLoc;
|
||||
/* 2.5.198.52 */
|
||||
var parse_PtgElfRadicalLel = parse_PtgElfLel;
|
||||
/* 2.5.198.53 */
|
||||
var parse_PtgElfRadicalS = parse_PtgElfNoop;
|
||||
/* 2.5.198.54 */
|
||||
var parse_PtgElfRw = parse_PtgElfLoc;
|
||||
/* 2.5.198.55 */
|
||||
var parse_PtgElfRwV = parse_PtgElfLoc;
|
||||
|
||||
/* [MS-XLSB] 2.5.97.52 */
|
||||
function parse_PtgList(blob, length, opts) {
|
||||
blob.l += 2;
|
||||
var ixti = blob.read_shift(2);
|
||||
blob.l += 10;
|
||||
return {};
|
||||
}
|
||||
/* 2.5.198.91 */
|
||||
function parse_PtgSxName(blob, length, opts) {
|
||||
blob.l += 2;
|
||||
return [blob.read_shift(4)];
|
||||
}
|
||||
|
||||
/* 2.5.198.25 */
|
||||
var PtgTypes = {
|
||||
/*::[*/0x01/*::]*/: { n:'PtgExp', f:parse_PtgExp },
|
||||
@ -521,8 +573,19 @@ var PtgDupes = {
|
||||
(function(){for(var y in PtgDupes) PtgTypes[y] = PtgTypes[PtgDupes[y]];})();
|
||||
|
||||
var Ptg18 = {
|
||||
// /*::[*/0x19/*::]*/: { n:'PtgList', f:parse_PtgList }, // TODO
|
||||
// /*::[*/0x1D/*::]*/: { n:'PtgSxName', f:parse_PtgSxName }, // TODO
|
||||
/*::[*/0x01/*::]*/: { n:'PtgElfLel', f:parse_PtgElfLel },
|
||||
/*::[*/0x02/*::]*/: { n:'PtgElfRw', f:parse_PtgElfRw },
|
||||
/*::[*/0x03/*::]*/: { n:'PtgElfCol', f:parse_PtgElfCol },
|
||||
/*::[*/0x06/*::]*/: { n:'PtgElfRwV', f:parse_PtgElfRwV },
|
||||
/*::[*/0x07/*::]*/: { n:'PtgElfColV', f:parse_PtgElfColV },
|
||||
/*::[*/0x0A/*::]*/: { n:'PtgElfRadical', f:parse_PtgElfRadical },
|
||||
/*::[*/0x0B/*::]*/: { n:'PtgElfRadicalS', f:parse_PtgElfRadicalS },
|
||||
/*::[*/0x0D/*::]*/: { n:'PtgElfColS', f:parse_PtgElfColS },
|
||||
/*::[*/0x0F/*::]*/: { n:'PtgElfColSV', f:parse_PtgElfColSV },
|
||||
/*::[*/0x10/*::]*/: { n:'PtgElfRadicalLel', f:parse_PtgElfRadicalLel },
|
||||
/*::[*/0x19/*::]*/: { n:'PtgList', f:parse_PtgList },
|
||||
/*::[*/0x1D/*::]*/: { n:'PtgSxName', f:parse_PtgSxName },
|
||||
/*::[*/0xFF/*::]*/: {}
|
||||
};
|
||||
var Ptg19 = {
|
||||
/*::[*/0x01/*::]*/: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
|
||||
@ -536,36 +599,7 @@ var Ptg19 = {
|
||||
/*::[*/0x80/*::]*/: { n:'PtgAttrIfError', f:parse_PtgAttrIfError },
|
||||
/*::[*/0xFF/*::]*/: {}
|
||||
};
|
||||
|
||||
/* 2.4.127 TODO */
|
||||
function parse_Formula(blob, length, opts) {
|
||||
var end = blob.l + length;
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
if(opts.biff == 2) ++blob.l;
|
||||
var val = parse_FormulaValue(blob,8);
|
||||
var flags = blob.read_shift(1);
|
||||
if(opts.biff != 2) {
|
||||
blob.read_shift(1);
|
||||
if(opts.biff >= 5) {
|
||||
var chn = blob.read_shift(4);
|
||||
}
|
||||
}
|
||||
var cbf = parse_XLSCellParsedFormula(blob, end - blob.l, opts);
|
||||
return {cell:cell, val:val[0], formula:cbf, shared: (flags >> 3) & 1, tt:val[1]};
|
||||
}
|
||||
|
||||
/* 2.5.133 TODO: how to emit empty strings? */
|
||||
function parse_FormulaValue(blob/*::, length*/) {
|
||||
var b;
|
||||
if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return [parse_Xnum(blob),'n'];
|
||||
switch(blob[blob.l]) {
|
||||
case 0x00: blob.l += 8; return ["String", 's'];
|
||||
case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return [b,'b'];
|
||||
case 0x02: b = blob[blob.l+2]; blob.l += 8; return [b,'e'];
|
||||
case 0x03: blob.l += 8; return ["",'s'];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
Ptg19[0x21] = Ptg19[0x20];
|
||||
|
||||
/* 2.5.198.103 */
|
||||
function parse_RgbExtra(blob, length, rgce, opts) {
|
||||
@ -587,6 +621,11 @@ function parse_RgbExtra(blob, length, rgce, opts) {
|
||||
rgce[i][1][1] = blob.read_shift(4);
|
||||
o.push(rgce[i][1]);
|
||||
} break;
|
||||
case 'PtgList': /* TODO: PtgList -> PtgExtraList */
|
||||
case 'PtgElfRadicalS': /* TODO: PtgElfRadicalS -> PtgExtraElf */
|
||||
case 'PtgElfColS': /* TODO: PtgElfColS -> PtgExtraElf */
|
||||
case 'PtgElfColSV': /* TODO: PtgElfColSV -> PtgExtraElf */
|
||||
throw "Unsupported " + rgce[i][0];
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@ -597,45 +636,6 @@ function parse_RgbExtra(blob, length, rgce, opts) {
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.5.198.21 */
|
||||
function parse_NameParsedFormula(blob, length, opts, cce) {
|
||||
var target = blob.l + length;
|
||||
var rgce = parse_Rgce(blob, cce, opts);
|
||||
var rgcb;
|
||||
if(target !== blob.l) rgcb = parse_RgbExtra(blob, target - blob.l, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* 2.5.198.3 TODO */
|
||||
function parse_XLSCellParsedFormula(blob, length, opts) {
|
||||
var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
|
||||
var rgcb, cce = blob.read_shift(len); // length of rgce
|
||||
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
|
||||
var rgce = parse_Rgce(blob, cce, opts);
|
||||
if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* 2.5.198.118 TODO */
|
||||
function parse_SharedParsedFormula(blob, length, opts) {
|
||||
var target = blob.l + length;
|
||||
var rgcb, cce = blob.read_shift(2); // length of rgce
|
||||
var rgce = parse_Rgce(blob, cce, opts);
|
||||
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
|
||||
if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* 2.5.198.1 TODO */
|
||||
function parse_ArrayParsedFormula(blob, length, opts, ref) {
|
||||
var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
|
||||
var rgcb, cce = blob.read_shift(len); // length of rgce
|
||||
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
|
||||
var rgce = parse_Rgce(blob, cce, opts);
|
||||
if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* 2.5.198.104 */
|
||||
function parse_Rgce(blob, length, opts) {
|
||||
var target = blob.l + length;
|
||||
@ -655,7 +655,7 @@ function parse_Rgce(blob, length, opts) {
|
||||
return ptgs;
|
||||
}
|
||||
|
||||
function stringify_array(f)/*:string*/ {
|
||||
function stringify_array(f/*:Array<Array<any>>*/)/*:string*/ {
|
||||
var o = [];
|
||||
for(var i = 0; i < f.length; ++i) {
|
||||
var x = f[i], r = [];
|
||||
@ -702,15 +702,12 @@ function get_ixti(supbooks, ixti/*:number*/, opts)/*:string*/ {
|
||||
return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts));
|
||||
}
|
||||
function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, opts)/*:string*/ {
|
||||
//console.log(formula);
|
||||
var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}};
|
||||
var stack/*:Array<string>*/ = [], e1, e2, type, c/*:CellAddress*/, ixti=0, nameidx=0, r, sname="";
|
||||
if(!formula[0] || !formula[0][0]) return "";
|
||||
var last_sp = -1, sp = "";
|
||||
//console.log("--",cell,formula[0])
|
||||
for(var ff = 0, fflen = formula[0].length; ff < fflen; ++ff) {
|
||||
var f = formula[0][ff];
|
||||
//console.log("++",f, stack)
|
||||
switch(f[0]) {
|
||||
case 'PtgUminus': /* 2.5.198.93 */
|
||||
stack.push("-" + stack.pop()); break;
|
||||
@ -791,7 +788,6 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
|
||||
|
||||
case 'PtgFunc': /* 2.5.198.62 */
|
||||
case 'PtgFuncVar': /* 2.5.198.63 */
|
||||
//console.log(f[1]);
|
||||
/* f[1] = [argc, func, type] */
|
||||
var argc/*:number*/ = (f[1][0]/*:any*/), func/*:string*/ = (f[1][1]/*:any*/);
|
||||
if(!argc) argc = 0;
|
||||
@ -845,7 +841,6 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
|
||||
/* f[1] = type, ixti, nameindex */
|
||||
var bookidx/*:number*/ = (f[1][1]/*:any*/); nameidx = (f[1][2]/*:any*/); var externbook;
|
||||
/* TODO: Properly handle missing values */
|
||||
//console.log(bookidx, supbooks);
|
||||
if(opts.biff <= 5) {
|
||||
if(bookidx < 0) bookidx = -bookidx;
|
||||
if(supbooks[bookidx]) externbook = supbooks[bookidx][nameidx];
|
||||
@ -949,6 +944,27 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
|
||||
|
||||
case 'PtgMemFunc': /* 2.5.198.72 TODO */
|
||||
break;
|
||||
case 'PtgMemNoMem': /* 2.5.198.73 TODO -- find a test case */
|
||||
throw new Error('Unrecognized Formula Token: ' + String(f));
|
||||
|
||||
case 'PtgElfCol': /* 2.5.198.46 */
|
||||
case 'PtgElfColS': /* 2.5.198.47 */
|
||||
case 'PtgElfColSV': /* 2.5.198.48 */
|
||||
case 'PtgElfColV': /* 2.5.198.49 */
|
||||
case 'PtgElfLel': /* 2.5.198.50 */
|
||||
case 'PtgElfRadical': /* 2.5.198.51 */
|
||||
case 'PtgElfRadicalLel': /* 2.5.198.52 */
|
||||
case 'PtgElfRadicalS': /* 2.5.198.53 */
|
||||
case 'PtgElfRw': /* 2.5.198.54 */
|
||||
case 'PtgElfRwV': /* 2.5.198.55 */
|
||||
throw new Error("Unsupported ELFs");
|
||||
|
||||
case 'PtgAttrBaxcel': /* 2.5.198.33 TODO -- find a test case*/
|
||||
throw new Error('Unrecognized Formula Token: ' + String(f));
|
||||
case 'PtgSxName': /* 2.5.198.91 TODO -- find a test case */
|
||||
throw new Error('Unrecognized Formula Token: ' + String(f));
|
||||
case 'PtgList': /* [MS-XLSB] 2.5.97.52 TODO -- find a test case */
|
||||
throw new Error('Unrecognized Formula Token: ' + String(f));
|
||||
|
||||
default: throw new Error('Unrecognized Formula Token: ' + String(f));
|
||||
}
|
||||
@ -976,9 +992,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
|
||||
stack.push((_left ? sp : "") + stack.pop() + (_left ? "" : sp));
|
||||
last_sp = -1;
|
||||
}
|
||||
//console.log("::",f, stack)
|
||||
}
|
||||
//console.log("--",stack);
|
||||
if(stack.length > 1 && opts.WTF) throw new Error("bad formula stack");
|
||||
return stack[0];
|
||||
}
|
||||
|
@ -1,3 +1,72 @@
|
||||
/* [MS-XLS] 2.5.198.1 TODO */
|
||||
function parse_ArrayParsedFormula(blob, length, opts, ref) {
|
||||
var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
|
||||
var rgcb, cce = blob.read_shift(len); // length of rgce
|
||||
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
|
||||
var rgce = parse_Rgce(blob, cce, opts);
|
||||
if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.5.198.3 TODO */
|
||||
function parse_XLSCellParsedFormula(blob, length, opts) {
|
||||
var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
|
||||
var rgcb, cce = blob.read_shift(len); // length of rgce
|
||||
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
|
||||
var rgce = parse_Rgce(blob, cce, opts);
|
||||
if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.5.198.21 */
|
||||
function parse_NameParsedFormula(blob, length, opts, cce) {
|
||||
var target = blob.l + length;
|
||||
var rgce = parse_Rgce(blob, cce, opts);
|
||||
var rgcb;
|
||||
if(target !== blob.l) rgcb = parse_RgbExtra(blob, target - blob.l, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.5.198.118 TODO */
|
||||
function parse_SharedParsedFormula(blob, length, opts) {
|
||||
var target = blob.l + length;
|
||||
var rgcb, cce = blob.read_shift(2); // length of rgce
|
||||
var rgce = parse_Rgce(blob, cce, opts);
|
||||
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
|
||||
if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.5.133 TODO: how to emit empty strings? */
|
||||
function parse_FormulaValue(blob/*::, length*/) {
|
||||
var b;
|
||||
if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return [parse_Xnum(blob),'n'];
|
||||
switch(blob[blob.l]) {
|
||||
case 0x00: blob.l += 8; return ["String", 's'];
|
||||
case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return [b,'b'];
|
||||
case 0x02: b = blob[blob.l+2]; blob.l += 8; return [b,'e'];
|
||||
case 0x03: blob.l += 8; return ["",'s'];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.4.127 TODO */
|
||||
function parse_Formula(blob, length, opts) {
|
||||
var end = blob.l + length;
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
if(opts.biff == 2) ++blob.l;
|
||||
var val = parse_FormulaValue(blob,8);
|
||||
var flags = blob.read_shift(1);
|
||||
if(opts.biff != 2) {
|
||||
blob.read_shift(1);
|
||||
if(opts.biff >= 5) {
|
||||
var chn = blob.read_shift(4);
|
||||
}
|
||||
}
|
||||
var cbf = parse_XLSCellParsedFormula(blob, end - blob.l, opts);
|
||||
return {cell:cell, val:val[0], formula:cbf, shared: (flags >> 3) & 1, tt:val[1]};
|
||||
}
|
||||
|
||||
/* XLSB Parsed Formula records have the same shape */
|
||||
function parse_XLSBParsedFormula(data, length, opts) {
|
||||
var end = data.l + length;
|
||||
|
@ -81,7 +81,7 @@ function parse_ws_xml(data/*:?string*/, opts, rels, wb, themes, styles)/*:Worksh
|
||||
}
|
||||
|
||||
function write_ws_xml_merges(merges) {
|
||||
if(merges.length == 0) return "";
|
||||
if(merges.length === 0) return "";
|
||||
var o = '<mergeCells count="' + merges.length + '">';
|
||||
for(var i = 0; i != merges.length; ++i) o += '<mergeCell ref="' + encode_range(merges[i]) + '"/>';
|
||||
return o + '</mergeCells>';
|
||||
@ -196,6 +196,7 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
case 'd':
|
||||
if(opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
|
||||
else {
|
||||
cell = dup(cell);
|
||||
cell.t = 'n';
|
||||
vv = ''+(cell.v = datenum(parseDate(cell.v)));
|
||||
}
|
||||
@ -384,6 +385,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
||||
function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/, rels)/*:string*/ {
|
||||
var o = [], r = [], range = safe_decode_range(ws['!ref']), cell, ref, rr = "", cols = [], R=0, C=0, rows = ws['!rows'];
|
||||
var dense = Array.isArray(ws);
|
||||
var params = ({r:rr}/*:any*/), row/*:RowInfo*/, height = -1;
|
||||
for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
|
||||
for(R = range.s.r; R <= range.e.r; ++R) {
|
||||
r = [];
|
||||
@ -395,11 +397,11 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
|
||||
if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
|
||||
}
|
||||
if(r.length > 0 || rows && rows[R]) {
|
||||
var params = ({r:rr}/*:any*/);
|
||||
params = ({r:rr}/*:any*/);
|
||||
if(rows && rows[R]) {
|
||||
var row = rows[R];
|
||||
row = rows[R];
|
||||
if(row.hidden) params.hidden = 1;
|
||||
var height = -1;
|
||||
height = -1;
|
||||
if (row.hpx) height = px2pt(row.hpx);
|
||||
else if (row.hpt) height = row.hpt;
|
||||
if (height > -1) { params.ht = height; params.customHeight = 1; }
|
||||
|
@ -261,7 +261,9 @@ function parse_BrtHLink(data, length, opts) {
|
||||
var tooltip = parse_XLWideString(data);
|
||||
var display = parse_XLWideString(data);
|
||||
data.l = end;
|
||||
return {rfx:rfx, relId:relId, loc:loc, Tooltip:tooltip, display:display};
|
||||
var o = ({rfx:rfx, relId:relId, loc:loc, display:display}/*:any*/);
|
||||
if(tooltip) o.Tooltip = tooltip;
|
||||
return o;
|
||||
}
|
||||
function write_BrtHLink(l, rId, o) {
|
||||
if(o == null) o = new_buf(50+4*l[1].Target.length);
|
||||
@ -319,25 +321,16 @@ function write_BrtColInfo(C/*:number*/, col, o) {
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.672 BrtMargins */
|
||||
function parse_BrtMargins(data, length, opts) {
|
||||
return {
|
||||
left: parse_Xnum(data, 8),
|
||||
right: parse_Xnum(data, 8),
|
||||
top: parse_Xnum(data, 8),
|
||||
bottom: parse_Xnum(data, 8),
|
||||
header: parse_Xnum(data, 8),
|
||||
footer: parse_Xnum(data, 8)
|
||||
};
|
||||
var BrtMarginKeys = ["left","right","top","bottom","header","footer"];
|
||||
function parse_BrtMargins(data, length, opts)/*:Margins*/ {
|
||||
var margins = ({}/*:any*/);
|
||||
BrtMarginKeys.forEach(function(k) { margins[k] = parse_Xnum(data, 8); });
|
||||
return margins;
|
||||
}
|
||||
function write_BrtMargins(margins, o) {
|
||||
function write_BrtMargins(margins/*:Margins*/, o) {
|
||||
if(o == null) o = new_buf(6*8);
|
||||
default_margins(margins);
|
||||
write_Xnum(margins.left, o);
|
||||
write_Xnum(margins.right, o);
|
||||
write_Xnum(margins.top, o);
|
||||
write_Xnum(margins.bottom, o);
|
||||
write_Xnum(margins.header, o);
|
||||
write_Xnum(margins.footer, o);
|
||||
BrtMarginKeys.forEach(function(k) { write_Xnum((margins/*:any*/)[k], o); });
|
||||
return o;
|
||||
}
|
||||
|
||||
@ -641,13 +634,13 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ {
|
||||
/* TODO: something useful -- this is a stub */
|
||||
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/) {
|
||||
if(cell.v === undefined) return "";
|
||||
var vv = ""; var olddate = null;
|
||||
var vv = "";
|
||||
switch(cell.t) {
|
||||
case 'b': vv = cell.v ? "1" : "0"; break;
|
||||
case 'd': // no BrtCellDate :(
|
||||
cell = dup(cell);
|
||||
cell.z = cell.z || SSF._table[14];
|
||||
olddate = cell.v;
|
||||
cell.v = datenum((cell.v/*:any*/)); cell.t = 'n';
|
||||
cell.v = datenum(parseDate(cell.v)); cell.t = 'n';
|
||||
break;
|
||||
/* falls through */
|
||||
case 'n': case 'e': vv = ''+cell.v; break;
|
||||
@ -673,7 +666,6 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
|
||||
/* TODO: determine threshold for Real vs RK */
|
||||
if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o));
|
||||
else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o));
|
||||
if(olddate) { cell.t = 'd'; cell.v = olddate; }
|
||||
return;
|
||||
case 'b':
|
||||
o.t = "b";
|
||||
|
@ -196,7 +196,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
|
||||
var comments = [], comment = {};
|
||||
var cstys = [], csty, seencol = false;
|
||||
var arrayf = [];
|
||||
var rowinfo = [], rowobj = {};
|
||||
var rowinfo = [], rowobj = {}, cc = 0, rr = 0;
|
||||
var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false} }/*:any*/), wsprops = {};
|
||||