forked from sheetjs/sheetjs
version bump 0.8.4: formula parsing
- BIFF 2-12 formula parsing - more content type coverage - unified `.f` form: A1-style string - `.F` field for array formulae - formula output groups array formulae - bin script -A --arrays output JS row objects - whitespace robustness in inline string xml - UTF-8 parsing in rich text runs (fixes #505 h/t @fuchsc) - bold/italic/underline accept null val attr (h/t @qqilihq) - sst trimming (fixes #176 h/t @shakhal @oising)
This commit is contained in:
parent
ab2ecebac9
commit
d7ecca0e8b
18
.gitignore
vendored
18
.gitignore
vendored
@ -4,17 +4,15 @@ misc/prof.js
|
||||
v8.log
|
||||
tmp
|
||||
*.txt
|
||||
*.csv
|
||||
*.dif
|
||||
*.prn
|
||||
*.slk
|
||||
*.[cC][sS][vV]
|
||||
*.[dD][iI][fF]
|
||||
*.[pP][rR][nN]
|
||||
*.[sS][lL][kK]
|
||||
*.socialcalc
|
||||
*.xls
|
||||
*.xlsb
|
||||
*.xlsm
|
||||
*.xlsx
|
||||
*.ods
|
||||
*.xml
|
||||
*.[xX][lL][sSwW]
|
||||
*.[xX][lL][sS][xXmMbB]
|
||||
*.[oO][dD][sS]
|
||||
*.[xX][mM][lL]
|
||||
*.htm
|
||||
*.html
|
||||
*.sheetjs
|
||||
|
19
.npmignore
19
.npmignore
@ -5,18 +5,15 @@ misc/
|
||||
node_modules
|
||||
tmp
|
||||
*.txt
|
||||
*.csv
|
||||
*.dif
|
||||
*.prn
|
||||
*.slk
|
||||
*.[cC][sS][vV]
|
||||
*.[dD][iI][fF]
|
||||
*.[pP][rR][nN]
|
||||
*.[sS][lL][kK]
|
||||
*.socialcalc
|
||||
*.XLS
|
||||
*.xls
|
||||
*.xlsb
|
||||
*.xlsm
|
||||
*.xlsx
|
||||
*.ods
|
||||
*.xml
|
||||
*.[xX][lL][sSwW]
|
||||
*.[xX][lL][sS][xXmMbB]
|
||||
*.[oO][dD][sS]
|
||||
*.[xX][mM][lL]
|
||||
*.htm
|
||||
*.html
|
||||
*.sheetjs
|
||||
|
@ -3,7 +3,7 @@ node_js:
|
||||
- "7"
|
||||
- "6"
|
||||
- "5"
|
||||
- "4.2"
|
||||
- "4"
|
||||
- "0.12"
|
||||
- "0.10"
|
||||
- "0.9"
|
||||
|
44
README.md
44
README.md
@ -366,24 +366,28 @@ for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
|
||||
### Cell Object
|
||||
|
||||
| Key | Description |
|
||||
| --- | ----------- |
|
||||
| `v` | raw value (see Data Types section for more info) |
|
||||
| `w` | formatted text (if applicable) |
|
||||
| `t` | cell type: `b` Boolean, `n` Number, `e` error, `s` String, `d` Date |
|
||||
| `f` | cell formula (if applicable) |
|
||||
| `r` | rich text encoding (if applicable) |
|
||||
| `h` | HTML rendering of the rich text (if applicable) |
|
||||
| `c` | comments associated with the cell ** |
|
||||
| `z` | number format string associated with the cell (if requested) |
|
||||
| `l` | cell hyperlink object (.Target holds link, .tooltip is tooltip) |
|
||||
| `s` | the style/theme of the cell (if applicable) |
|
||||
| Key | Description |
|
||||
| --- | ---------------------------------------------------------------------- |
|
||||
| `v` | raw value (see Data Types section for more info) |
|
||||
| `w` | formatted text (if applicable) |
|
||||
| `t` | cell type: `b` Boolean, `n` Number, `e` error, `s` String, `d` Date |
|
||||
| `f` | cell formula encoded as an A1-style string (if applicable) |
|
||||
| `F` | range of enclosing array if formula is array formula (if applicable) |
|
||||
| `r` | rich text encoding (if applicable) |
|
||||
| `h` | HTML rendering of the rich text (if applicable) |
|
||||
| `c` | comments associated with the cell |
|
||||
| `z` | number format string associated with the cell (if requested) |
|
||||
| `l` | cell hyperlink object (.Target holds link, .tooltip is tooltip) |
|
||||
| `s` | the style/theme of the cell (if applicable) |
|
||||
|
||||
Built-in export utilities (such as the CSV exporter) will use the `w` text if it
|
||||
is available. To change a value, be sure to delete `cell.w` (or set it to
|
||||
`undefined`) before attempting to export. The utilities will regenerate the `w`
|
||||
text from the number format (`cell.z`) and the raw value if possible.
|
||||
|
||||
The actual array formula is stored in the `f` field of the first cell in the
|
||||
array range. Other cells in the range will omit the `f` field.
|
||||
|
||||
### Data Types
|
||||
|
||||
The raw value is stored in the `v` field, interpreted based on the `t` field.
|
||||
@ -418,6 +422,20 @@ dates in the local timezone. js-xlsx does not correct for this error.
|
||||
Type `s` is the String type. `v` should be explicitly stored as a string to
|
||||
avoid possible confusion.
|
||||
|
||||
### Formulae
|
||||
|
||||
The A1-style formula string is stored in the `f` field. Even though different
|
||||
file formats store the formulae in different ways, the formats are converted.
|
||||
|
||||
Shared formulae are decompressed and each cell has the correct formula.
|
||||
|
||||
Array formulae are stored in the top-left cell of the array block. All cells
|
||||
of an array formula have a `F` field corresponding to the range. A single-cell
|
||||
formula can be distinguished from a plain formula by the presence of `F` field.
|
||||
|
||||
The `sheet_to_formulae` method generates one line per formula or array formula.
|
||||
Array formulae are rendered in the form `range=formula` while plain cells are
|
||||
rendered in the form `cell=formula or value`.
|
||||
|
||||
### Worksheet Object
|
||||
|
||||
@ -619,6 +637,8 @@ OSP-covered specifications:
|
||||
- [MS-OLEDS]: Object Linking and Embedding (OLE) Data Structures
|
||||
- [MS-OLEPS]: Object Linking and Embedding (OLE) Property Set Data Structures
|
||||
- [MS-OSHARED]: Office Common Data Types and Objects Structures
|
||||
- [MS-ODRAW]: Office Drawing Binary File Format
|
||||
- [MS-ODRAWXML]: Office Drawing Extensions to Office Open XML Structure
|
||||
- [MS-OVBA]: Office VBA File Format Structure
|
||||
- [MS-CTXLS]: Excel Custom Toolbar Binary File Format
|
||||
- [MS-XLDM]: Spreadsheet Data Model File Format
|
||||
|
@ -21,6 +21,7 @@ program
|
||||
.option('-S, --formulae', 'print formulae')
|
||||
.option('-j, --json', 'emit formatted JSON (all fields text)')
|
||||
.option('-J, --raw-js', 'emit raw JS object (raw numbers)')
|
||||
.option('-A, --arrays', 'emit rows as JS objects (raw numbers)')
|
||||
.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)')
|
||||
@ -77,7 +78,7 @@ if(program.xlsx || program.xlsm || program.xlsb) {
|
||||
opts.cellNF = true;
|
||||
if(program.output) sheetname = program.output;
|
||||
}
|
||||
else if(program.formulae);
|
||||
else if(program.formulae) opts.cellFormula = true;
|
||||
else opts.cellFormula = false;
|
||||
|
||||
if(program.all) {
|
||||
@ -142,6 +143,7 @@ if(!program.quiet) console.error(target_sheet);
|
||||
if(program.formulae) oo = X.utils.get_formulae(ws).join("\n");
|
||||
else if(program.json) oo = JSON.stringify(X.utils.sheet_to_row_object_array(ws));
|
||||
else if(program.rawJs) oo = JSON.stringify(X.utils.sheet_to_row_object_array(ws,{raw:true}));
|
||||
else if(program.arrays) oo = JSON.stringify(X.utils.sheet_to_row_object_array(ws,{raw:true, header:1}));
|
||||
else oo = X.utils.make_csv(ws, {FS:program.fieldSep, RS:program.rowSep});
|
||||
|
||||
if(program.output) fs.writeFileSync(program.output, oo);
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.8.3';
|
||||
XLSX.version = '0.8.4';
|
||||
|
@ -42,3 +42,12 @@ function cc2str(arr/*:Array<number>*/)/*:string*/ {
|
||||
return o;
|
||||
}
|
||||
|
||||
function dup(o/*:any*/)/*:any*/ {
|
||||
if(typeof JSON != 'undefined') return JSON.parse(JSON.stringify(o));
|
||||
if(typeof o != 'object' || !o) return o;
|
||||
var out = {};
|
||||
for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]);
|
||||
return out;
|
||||
}
|
||||
|
||||
function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; }
|
||||
|
@ -115,9 +115,9 @@ var matchtag = (function() {
|
||||
var vtregex = (function(){ var vt_cache = {};
|
||||
return function vt_regex(bt) {
|
||||
if(vt_cache[bt] !== undefined) return vt_cache[bt];
|
||||
return (vt_cache[bt] = new RegExp("<vt:" + bt + ">(.*?)</vt:" + bt + ">", 'g') );
|
||||
return (vt_cache[bt] = new RegExp("<(?:vt:)?" + bt + ">(.*?)</(?:vt:)?" + bt + ">", 'g') );
|
||||
};})();
|
||||
var vtvregex = /<\/?vt:variant>/g, vtmregex = /<vt:([^>]*)>(.*)</;
|
||||
var vtvregex = /<\/?(:?vt:)?variant>/g, vtmregex = /<(:?vt:)?([^>]*)>(.*)</;
|
||||
function parseVector(data) {
|
||||
var h = parsexmltag(data);
|
||||
|
||||
|
@ -82,6 +82,8 @@ function ReadShift(size, t) {
|
||||
case 'utf8': o = __utf8(this, this.l, this.l + size); break;
|
||||
case 'utf16le': size *= 2; o = __utf16le(this, this.l, this.l + size); break;
|
||||
|
||||
case 'wstr': o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l+2*size)); size = 2 * size; break;
|
||||
|
||||
/* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */
|
||||
case 'lpstr': o = __lpstr(this, this.l); size = 5 + o.length; break;
|
||||
/* [MS-OLEDS] 2.1.5 LengthPrefixedUnicodeString */
|
||||
|
@ -1,16 +1,18 @@
|
||||
/* XLS ranges enforced */
|
||||
function shift_cell_xls(cell, tgt) {
|
||||
function shift_cell_xls(cell, tgt, opts) {
|
||||
var out = dup(cell);
|
||||
if(tgt.s) {
|
||||
if(cell.cRel) cell.c += tgt.s.c;
|
||||
if(cell.rRel) cell.r += tgt.s.r;
|
||||
if(out.cRel) out.c += tgt.s.c;
|
||||
if(out.rRel) out.r += tgt.s.r;
|
||||
} else {
|
||||
cell.c += tgt.c;
|
||||
cell.r += tgt.r;
|
||||
out.c += tgt.c;
|
||||
out.r += tgt.r;
|
||||
}
|
||||
cell.cRel = cell.rRel = 0;
|
||||
while(cell.c >= 0x100) cell.c -= 0x100;
|
||||
while(cell.r >= 0x10000) cell.r -= 0x10000;
|
||||
return cell;
|
||||
if(!opts || opts.biff < 12) {
|
||||
while(out.c >= 0x100) out.c -= 0x100;
|
||||
while(out.r >= 0x10000) out.r -= 0x10000;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function shift_range_xls(cell, range) {
|
||||
@ -19,3 +21,13 @@ function shift_range_xls(cell, range) {
|
||||
return cell;
|
||||
}
|
||||
|
||||
function encode_cell_xls(c)/*:string*/ {
|
||||
var s = encode_cell(c);
|
||||
if(c.cRel === 0) s = fix_col(s);
|
||||
if(c.rRel === 0) s = fix_row(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
function encode_range_xls(r)/*:string*/ {
|
||||
return encode_cell_xls(r.s) + ":" + encode_cell_xls(r.e);
|
||||
}
|
||||
|
@ -76,6 +76,10 @@ function write_XLWideString(data/*:string*/, o) {
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.165 */
|
||||
var parse_XLNameWideString = parse_XLWideString;
|
||||
var write_XLNameWideString = write_XLWideString;
|
||||
|
||||
/* [MS-XLSB] 2.5.114 */
|
||||
var parse_RelID = parse_XLNullableWideString;
|
||||
var write_RelID = write_XLNullableWideString;
|
||||
@ -101,8 +105,8 @@ function write_RkNumber(data/*:number*/, o) {
|
||||
}
|
||||
|
||||
|
||||
/* [MS-XLSB] 2.5.153 */
|
||||
function parse_UncheckedRfX(data)/*:Range*/ {
|
||||
/* [MS-XLSB] 2.5.117 RfX */
|
||||
function parse_RfX(data)/*:Range*/ {
|
||||
var cell/*:Range*/ = ({s: {}, e: {}}/*:any*/);
|
||||
cell.s.r = data.read_shift(4);
|
||||
cell.e.r = data.read_shift(4);
|
||||
@ -111,7 +115,7 @@ function parse_UncheckedRfX(data)/*:Range*/ {
|
||||
return cell;
|
||||
}
|
||||
|
||||
function write_UncheckedRfX(r/*:Range*/, o) {
|
||||
function write_RfX(r/*:Range*/, o) {
|
||||
if(!o) o = new_buf(16);
|
||||
o.write_shift(4, r.s.r);
|
||||
o.write_shift(4, r.e.r);
|
||||
@ -120,6 +124,10 @@ function write_UncheckedRfX(r/*:Range*/, o) {
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.153 UncheckedRfX */
|
||||
var parse_UncheckedRfX = parse_RfX;
|
||||
var write_UncheckedRfX = write_RfX;
|
||||
|
||||
/* [MS-XLSB] 2.5.171 */
|
||||
/* [MS-XLS] 2.5.342 */
|
||||
/* TODO: error checking, NaN and Infinity values are not valid Xnum */
|
||||
|
@ -40,6 +40,12 @@ var ct2type/*{[string]:string}*/ = ({
|
||||
"application/vnd.ms-excel.pivotTable": "TODO",
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml": "TODO",
|
||||
|
||||
/* Chart Colors */
|
||||
"application/vnd.ms-office.chartcolorstyle+xml": "TODO",
|
||||
|
||||
/* Chart Style */
|
||||
"application/vnd.ms-office.chartstyle+xml": "TODO",
|
||||
|
||||
/* Calculation Chain */
|
||||
"application/vnd.ms-excel.calcChain": "calcchains",
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains",
|
||||
|
@ -10,10 +10,7 @@ function parse_cust_props(data/*:string*/, opts) {
|
||||
var x = m[i], y = parsexmltag(x);
|
||||
switch(y[0]) {
|
||||
case '<?xml': break;
|
||||
case '<Properties':
|
||||
if(y.xmlns !== XMLNS.CUST_PROPS) throw "unrecognized xmlns " + y.xmlns;
|
||||
if(y.xmlnsvt && y.xmlnsvt !== XMLNS.vt) throw "unrecognized vt " + y.xmlnsvt;
|
||||
break;
|
||||
case '<Properties': break;
|
||||
case '<property': name = y.name; break;
|
||||
case '</property>': name = null; break;
|
||||
default: if (x.indexOf('<vt:') === 0) {
|
||||
|
@ -303,13 +303,15 @@ function parse_Bes(blob) {
|
||||
|
||||
/* [MS-XLS] 2.5.240 ShortXLUnicodeString */
|
||||
function parse_ShortXLUnicodeString(blob, length, opts) {
|
||||
var cch = blob.read_shift(1);
|
||||
var cch = blob.read_shift(opts && opts.biff >= 12 ? 2 : 1);
|
||||
var width = 1, encoding = 'sbcs-cont';
|
||||
var cp = current_codepage;
|
||||
if(opts && opts.biff >= 8) current_codepage = 1200;
|
||||
if(opts === undefined || opts.biff !== 5) {
|
||||
if(!opts || opts.biff == 8 ) {
|
||||
var fHighByte = blob.read_shift(1);
|
||||
if(fHighByte) { width = 2; encoding = 'dbcs-cont'; }
|
||||
} else if(opts.biff == 12) {
|
||||
width = 2; encoding = 'wstr';
|
||||
}
|
||||
var o = cch ? blob.read_shift(cch, encoding) : "";
|
||||
current_codepage = cp;
|
||||
@ -340,6 +342,10 @@ function parse_XLUnicodeRichExtendedString(blob) {
|
||||
/* 2.5.296 XLUnicodeStringNoCch */
|
||||
function parse_XLUnicodeStringNoCch(blob, cch, opts) {
|
||||
var retval;
|
||||
if(opts) {
|
||||
if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'sbcs-cont');
|
||||
if(opts.biff >= 12) return blob.read_shift(cch, 'dbcs-cont');
|
||||
}
|
||||
var fHighByte = blob.read_shift(1);
|
||||
if(fHighByte===0) { retval = blob.read_shift(cch, 'sbcs-cont'); }
|
||||
else { retval = blob.read_shift(cch, 'dbcs-cont'); }
|
||||
@ -348,7 +354,7 @@ function parse_XLUnicodeStringNoCch(blob, cch, opts) {
|
||||
|
||||
/* 2.5.294 XLUnicodeString */
|
||||
function parse_XLUnicodeString(blob, length, opts) {
|
||||
var cch = blob.read_shift(opts !== undefined && opts.biff > 0 && opts.biff < 8 ? 1 : 2);
|
||||
var cch = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
|
||||
if(cch === 0) { blob.l++; return ""; }
|
||||
return parse_XLUnicodeStringNoCch(blob, cch, opts);
|
||||
}
|
||||
|
@ -39,10 +39,10 @@ function parse_RkRec(blob, length) {
|
||||
}
|
||||
|
||||
/* 2.5.1 */
|
||||
function parse_AddinUdf(blob, length) {
|
||||
function parse_AddinUdf(blob, length, opts) {
|
||||
blob.l += 4; length -= 4;
|
||||
var l = blob.l + length;
|
||||
var udfName = parse_ShortXLUnicodeString(blob, length);
|
||||
var udfName = parse_ShortXLUnicodeString(blob, length, opts);
|
||||
var cb = blob.read_shift(2);
|
||||
l -= blob.l;
|
||||
if(cb !== l) throw "Malformed AddinUdf: padding = " + l + " != " + cb;
|
||||
@ -272,8 +272,10 @@ function parse_LabelSst(blob, length) {
|
||||
|
||||
/* 2.4.148 */
|
||||
function parse_Label(blob, length, opts) {
|
||||
var target = blob.l + length;
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
var str = parse_XLUnicodeString(blob, length-6, opts);
|
||||
if(opts.biff == 2) blob.l++;
|
||||
var str = parse_XLUnicodeString(blob, target - blob.l, opts);
|
||||
cell.val = str;
|
||||
return cell;
|
||||
}
|
||||
@ -287,11 +289,12 @@ function parse_Format(blob, length, opts) {
|
||||
var parse_BIFF2Format = parse_XLUnicodeString2;
|
||||
|
||||
/* 2.4.90 */
|
||||
function parse_Dimensions(blob, length) {
|
||||
var w = length === 10 ? 2 : 4;
|
||||
function parse_Dimensions(blob, length, opts) {
|
||||
var end = blob.l + length;
|
||||
var w = opts.biff == 8 || !opts.biff ? 4 : 2;
|
||||
var r = blob.read_shift(w), R = blob.read_shift(w),
|
||||
c = blob.read_shift(2), C = blob.read_shift(2);
|
||||
blob.l += 2;
|
||||
blob.l = end;
|
||||
return {s: {r:r, c:c}, e: {r:R, c:C}};
|
||||
}
|
||||
|
||||
@ -392,7 +395,7 @@ function parse_ExternName(blob, length, opts) {
|
||||
cf: (flags >>> 5) & 0x3FF,
|
||||
fIcon: flags >>> 15 & 0x01
|
||||
}/*:any*/);
|
||||
if(opts.sbcch === 0x3A01) body = parse_AddinUdf(blob, length-2);
|
||||
if(opts.sbcch === 0x3A01) body = parse_AddinUdf(blob, length-2, opts);
|
||||
//else throw new Error("unsupported SupBook cch: " + opts.sbcch);
|
||||
o.body = body || blob.read_shift(length-2);
|
||||
return o;
|
||||
@ -404,12 +407,15 @@ function parse_Lbl(blob, length, opts) {
|
||||
var flags = blob.read_shift(2);
|
||||
var chKey = blob.read_shift(1);
|
||||
var cch = blob.read_shift(1);
|
||||
var cce = blob.read_shift(2);
|
||||
blob.l += 2;
|
||||
var itab = blob.read_shift(2);
|
||||
blob.l += 4;
|
||||
var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
|
||||
if(!opts || opts.biff >= 5) {
|
||||
blob.l += 2;
|
||||
var itab = blob.read_shift(2);
|
||||
blob.l += 4;
|
||||
}
|
||||
var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
|
||||
var rgce = parse_NameParsedFormula(blob, target - blob.l, opts, cce);
|
||||
var npflen = target - blob.l; if(opts && opts.biff == 2) --npflen;
|
||||
var rgce = target == blob.l || cce == 0 ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
|
||||
return {
|
||||
chKey: chKey,
|
||||
Name: name,
|
||||
@ -441,7 +447,12 @@ function parse_ShrFmla(blob, length, opts) {
|
||||
/* 2.4.4 TODO */
|
||||
function parse_Array(blob, length, opts) {
|
||||
var ref = parse_Ref(blob, 6);
|
||||
blob.l += 6; length -= 12; /* TODO: fAlwaysCalc */
|
||||
/* TODO: fAlwaysCalc */
|
||||
switch(opts.biff) {
|
||||
case 2: blob.l ++; length -= 7; break;
|
||||
case 3: case 4: blob.l += 2; length -= 8; break;
|
||||
default: blob.l += 6; length -= 12;
|
||||
}
|
||||
return [ref, parse_ArrayParsedFormula(blob, length, opts, ref)];
|
||||
}
|
||||
|
||||
@ -904,6 +915,7 @@ function parse_BIFF2STR(blob, length, opts) {
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
++blob.l;
|
||||
var str = parse_XLUnicodeString2(blob, length-7, opts);
|
||||
cell.t = 'str';
|
||||
cell.val = str;
|
||||
return cell;
|
||||
}
|
||||
@ -912,6 +924,7 @@ function parse_BIFF2NUM(blob, length, opts) {
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
++blob.l;
|
||||
var num = parse_Xnum(blob, 8);
|
||||
cell.t = 'n';
|
||||
cell.val = num;
|
||||
return cell;
|
||||
}
|
||||
@ -920,6 +933,7 @@ function parse_BIFF2INT(blob, length) {
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
++blob.l;
|
||||
var num = blob.read_shift(2);
|
||||
cell.t = 'n';
|
||||
cell.val = num;
|
||||
return cell;
|
||||
}
|
||||
@ -939,3 +953,15 @@ function parse_BIFF2FONTXTRA(blob, length) {
|
||||
blob.l += 1; // font family
|
||||
blob.l += length - 9;
|
||||
}
|
||||
|
||||
/* TODO: parse rich text runs */
|
||||
function parse_RString(blob, length, opts) {
|
||||
var end = blob.l + length;
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
var cch = blob.read_shift(2);
|
||||
var str = parse_XLUnicodeStringNoCch(blob, cch, opts);
|
||||
blob.l = end;
|
||||
cell.t = 'str';
|
||||
cell.val = str;
|
||||
return cell;
|
||||
}
|
||||
|
@ -70,21 +70,21 @@ var parse_rs = (function parse_rs_factory() {
|
||||
|
||||
/* 18.4.13 u CT_UnderlineProperty */
|
||||
case '<u':
|
||||
if(!y.val) break;
|
||||
if(y.val == '0') break;
|
||||
/* falls through */
|
||||
case '<u/>': font.u = 1; break;
|
||||
case '</u>': break;
|
||||
|
||||
/* 18.8.2 b */
|
||||
case '<b':
|
||||
if(!y.val) break;
|
||||
if(y.val == '0') break;
|
||||
/* falls through */
|
||||
case '<b/>': font.b = 1; break;
|
||||
case '</b>': break;
|
||||
|
||||
/* 18.8.26 i */
|
||||
case '<i':
|
||||
if(!y.val) break;
|
||||
if(y.val == '0') break;
|
||||
/* falls through */
|
||||
case '<i/>': font.i = 1; break;
|
||||
case '</i>': break;
|
||||
@ -142,16 +142,17 @@ function parse_si(x, opts) {
|
||||
if(!x) return null;
|
||||
var y;
|
||||
/* 18.4.12 t ST_Xstring (Plaintext String) */
|
||||
if(x.match(/^<(?:\w+:)?t[^>]*>/)) {
|
||||
// TODO: is whitespace actually valid here?
|
||||
if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) {
|
||||
z.t = utf8read(unescapexml(x.substr(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]));
|
||||
z.r = x;
|
||||
z.r = utf8read(x);
|
||||
if(html) z.h = z.t;
|
||||
}
|
||||
/* 18.4.4 r CT_RElt (Rich Text Run) */
|
||||
else if((y = x.match(sirregex))) {
|
||||
z.r = x;
|
||||
z.r = utf8read(x);
|
||||
z.t = utf8read(unescapexml((x.match(sitregex)||[]).join("").replace(tagregex,"")));
|
||||
if(html) z.h = parse_rs(x);
|
||||
if(html) z.h = parse_rs(z.r);
|
||||
}
|
||||
/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
|
||||
/* 18.4.6 rPh CT_PhoneticRun (TODO: needed for Asian support) */
|
||||
@ -170,7 +171,7 @@ function parse_sst_xml(data/*:string*/, opts)/*:SST*/ {
|
||||
if(isval(sst)/*:: && sst*/) {
|
||||
ss = sst[2].replace(sstr1,"").split(sstr2);
|
||||
for(var i = 0; i != ss.length; ++i) {
|
||||
var o = parse_si(ss[i], opts);
|
||||
var o = parse_si(ss[i].trim(), opts);
|
||||
if(o != null) s[s.length] = o;
|
||||
}
|
||||
sst = parsexmltag(sst[1]); s.Count = sst.count; s.Unique = sst.uniqueCount;
|
||||
|
@ -5,9 +5,10 @@ var rc_to_a1 = (function(){
|
||||
function rcfunc($$,$1,$2,$3,$4,$5) {
|
||||
var R = $3.length>0?parseInt($3,10)|0:0, C = $5.length>0?parseInt($5,10)|0:0;
|
||||
if(C<0 && $4.length === 0) C=0;
|
||||
if($4.length > 0) C += rcbase.c;
|
||||
if($2.length > 0) R += rcbase.r;
|
||||
return $1 + encode_col(C) + encode_row(R);
|
||||
var cRel = false, rRel = false;
|
||||
if($4.length > 0 || $5.length == 0) cRel = true; if(cRel) C += rcbase.c; else --C;
|
||||
if($2.length > 0 || $3.length == 0) rRel = true; if(rRel) R += rcbase.r; else --R;
|
||||
return $1 + (cRel ? "" : "$") + encode_col(C) + (rRel ? "" : "$") + encode_row(R);
|
||||
}
|
||||
return function rc_to_a1(fstr, base) {
|
||||
rcbase = base;
|
||||
@ -15,3 +16,15 @@ var rc_to_a1 = (function(){
|
||||
};
|
||||
})();
|
||||
|
||||
/* TODO actually parse the formula */
|
||||
function shift_formula_str(f/*:string*/, delta/*:Cell*/)/*:string*/ {
|
||||
return f.replace(/(^|[^A-Z0-9])([$]?)([A-Z]+)([$]?)(\d+)/g, function($0, $1, $2, $3, $4, $5, off, str) {
|
||||
return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
|
||||
});
|
||||
}
|
||||
|
||||
function shift_formula_xlsx(f/*:string*/, range/*:string*/, cell/*:string*/)/*:string*/ {
|
||||
var r = decode_range(range), s = r.s, c = decode_cell(cell);
|
||||
var delta = {r:c.r - s.r, c:c.c - s.c};
|
||||
return shift_formula_str(f, delta);
|
||||
}
|
||||
|
465
bits/62_fxls.js
465
bits/62_fxls.js
@ -7,17 +7,30 @@ function parseread1(blob, length) { blob.l+=1; return; }
|
||||
|
||||
/* 2.5.51 */
|
||||
function parse_ColRelU(blob, length) {
|
||||
var c = blob.read_shift(2);
|
||||
var c = blob.read_shift(length == 1 ? 1 : 2);
|
||||
return [c & 0x3FFF, (c >> 14) & 1, (c >> 15) & 1];
|
||||
}
|
||||
|
||||
/* 2.5.198.105 */
|
||||
function parse_RgceArea(blob, length) {
|
||||
var r=blob.read_shift(2), R=blob.read_shift(2);
|
||||
/* [MS-XLS] 2.5.198.105 */
|
||||
/* [MS-XLSB] 2.5.97.89 */
|
||||
function parse_RgceArea(blob, length, opts) {
|
||||
var w = 2;
|
||||
if(opts) {
|
||||
if(opts.biff >= 2 && opts.biff <= 5) return parse_RgceArea_BIFF2(blob, length, opts);
|
||||
else if(opts.biff == 12) w = 4;
|
||||
}
|
||||
var r=blob.read_shift(w), R=blob.read_shift(w);
|
||||
var c=parse_ColRelU(blob, 2);
|
||||
var C=parse_ColRelU(blob, 2);
|
||||
return { s:{r:r, c:c[0], cRel:c[1], rRel:c[2]}, e:{r:R, c:C[0], cRel:C[1], rRel:C[2]} };
|
||||
}
|
||||
/* BIFF 2-5 encodes flags in the row field */
|
||||
function parse_RgceArea_BIFF2(blob, length, opts) {
|
||||
var r=parse_ColRelU(blob, 2), R=parse_ColRelU(blob, 2);
|
||||
var c=blob.read_shift(1);
|
||||
var C=blob.read_shift(1);
|
||||
return { s:{r:r[0], c:c, cRel:r[1], rRel:r[2]}, e:{r:R[0], c:C, cRel:R[1], rRel:R[2]} };
|
||||
}
|
||||
|
||||
/* 2.5.198.105 TODO */
|
||||
function parse_RgceAreaRel(blob, length) {
|
||||
@ -28,36 +41,61 @@ function parse_RgceAreaRel(blob, length) {
|
||||
}
|
||||
|
||||
/* 2.5.198.109 */
|
||||
function parse_RgceLoc(blob, length) {
|
||||
var r = blob.read_shift(2);
|
||||
function parse_RgceLoc(blob, length, opts) {
|
||||
if(opts && opts.biff >= 2 && opts.biff <= 5) return parse_RgceLoc_BIFF2(blob, length, opts);
|
||||
var r = blob.read_shift(opts && opts.biff == 12 ? 4 : 2);
|
||||
var c = parse_ColRelU(blob, 2);
|
||||
return {r:r, c:c[0], cRel:c[1], rRel:c[2]};
|
||||
}
|
||||
function parse_RgceLoc_BIFF2(blob, length, opts) {
|
||||
var r = parse_ColRelU(blob, 2);
|
||||
var c = blob.read_shift(1);
|
||||
return {r:r[0], c:c, cRel:r[1], rRel:r[2]};
|
||||
}
|
||||
|
||||
/* 2.5.198.111 */
|
||||
function parse_RgceLocRel(blob, length) {
|
||||
var r = blob.read_shift(2);
|
||||
/* [MS-XLS] 2.5.198.111 TODO */
|
||||
/* [MS-XLSB] 2.5.97.92 TODO */
|
||||
function parse_RgceLocRel(blob, length, opts) {
|
||||
var biff = opts && opts.biff ? opts.biff : 8;
|
||||
if(biff >= 2 && biff <= 5) return parse_RgceLocRel_BIFF2(blob, length, opts);
|
||||
var r = blob.read_shift(biff >= 12 ? 4 : 2);
|
||||
var cl = blob.read_shift(2);
|
||||
var cRel = (cl & 0x8000) >> 15, rRel = (cl & 0x4000) >> 14;
|
||||
cl &= 0x3FFF;
|
||||
if(cRel !== 0) while(cl >= 0x100) cl -= 0x100;
|
||||
if(rRel == 1) while(r > 0x7FFFF) r -= 0x100000;
|
||||
if(cRel == 1) while(cl > 0x1FFF) cl = cl - 0x4000;
|
||||
return {r:r,c:cl,cRel:cRel,rRel:rRel};
|
||||
}
|
||||
function parse_RgceLocRel_BIFF2(blob, length) {
|
||||
var rl = blob.read_shift(2);
|
||||
var c = blob.read_shift(1);
|
||||
var rRel = (rl & 0x8000) >> 15, cRel = (rl & 0x4000) >> 14;
|
||||
rl &= 0x3FFF;
|
||||
if(rRel == 1 && rl >= 0x2000) rl = rl - 0x4000;
|
||||
if(cRel == 1 && c >= 0x80) c = c - 0x100;
|
||||
return {r:rl,c:c,cRel:cRel,rRel:rRel};
|
||||
}
|
||||
|
||||
/* Ptg Tokens */
|
||||
|
||||
/* 2.5.198.27 */
|
||||
function parse_PtgArea(blob, length) {
|
||||
function parse_PtgArea(blob, length, opts) {
|
||||
var type = (blob[blob.l++] & 0x60) >> 5;
|
||||
var area = parse_RgceArea(blob, 8);
|
||||
var area = parse_RgceArea(blob, opts.biff >= 2 && opts.biff <= 5 ? 6 : 8, opts);
|
||||
return [type, area];
|
||||
}
|
||||
|
||||
/* 2.5.198.28 */
|
||||
function parse_PtgArea3d(blob, length) {
|
||||
/* [MS-XLS] 2.5.198.28 */
|
||||
/* [MS-XLSB] 2.5.97.19 */
|
||||
function parse_PtgArea3d(blob, length, opts) {
|
||||
var type = (blob[blob.l++] & 0x60) >> 5;
|
||||
var ixti = blob.read_shift(2);
|
||||
var area = parse_RgceArea(blob, 8);
|
||||
var ixti = blob.read_shift(2, 'i');
|
||||
var w = 8;
|
||||
if(opts) switch(opts.biff) {
|
||||
case 5: blob.l += 12; w = 6; break;
|
||||
case 12: w = 12; break;
|
||||
}
|
||||
var area = parse_RgceArea(blob, w, opts);
|
||||
return [type, ixti, area];
|
||||
}
|
||||
|
||||
@ -68,10 +106,15 @@ function parse_PtgAreaErr(blob, length) {
|
||||
return [type];
|
||||
}
|
||||
/* 2.5.198.30 */
|
||||
function parse_PtgAreaErr3d(blob, length) {
|
||||
function parse_PtgAreaErr3d(blob, length, opts) {
|
||||
var type = (blob[blob.l++] & 0x60) >> 5;
|
||||
var ixti = blob.read_shift(2);
|
||||
blob.l += 8;
|
||||
var w = 8;
|
||||
if(opts) switch(opts.biff) {
|
||||
case 5: blob.l += 12; w = 6; break;
|
||||
case 12: w = 12; break;
|
||||
}
|
||||
blob.l += w;
|
||||
return [type, ixti];
|
||||
}
|
||||
|
||||
@ -82,10 +125,11 @@ function parse_PtgAreaN(blob, length) {
|
||||
return [type, area];
|
||||
}
|
||||
|
||||
/* 2.5.198.32 -- ignore this and look in PtgExtraArray for shape + values */
|
||||
function parse_PtgArray(blob, length) {
|
||||
/* [MS-XLS] 2.5.198.32 */
|
||||
/* [MS-XLSB] 2.5.97.23 */
|
||||
function parse_PtgArray(blob, length, opts) {
|
||||
var type = (blob[blob.l++] & 0x60) >> 5;
|
||||
blob.l += 7;
|
||||
blob.l += opts.biff == 2 ? 6 : opts.biff == 12 ? 14 : 7;
|
||||
return [type];
|
||||
}
|
||||
|
||||
@ -98,33 +142,40 @@ function parse_PtgAttrBaxcel(blob, length) {
|
||||
}
|
||||
|
||||
/* 2.5.198.34 */
|
||||
function parse_PtgAttrChoose(blob, length) {
|
||||
function parse_PtgAttrChoose(blob, length, opts) {
|
||||
blob.l +=2;
|
||||
var offset = blob.read_shift(2);
|
||||
var offset = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
|
||||
var o = [];
|
||||
/* offset is 1 less than the number of elements */
|
||||
for(var i = 0; i <= offset; ++i) o.push(blob.read_shift(2));
|
||||
for(var i = 0; i <= offset; ++i) o.push(blob.read_shift(opts && opts.biff == 2 ? 1 : 2));
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.5.198.35 */
|
||||
function parse_PtgAttrGoto(blob, length) {
|
||||
function parse_PtgAttrGoto(blob, length, opts) {
|
||||
var bitGoto = (blob[blob.l+1] & 0xFF) ? 1 : 0;
|
||||
blob.l += 2;
|
||||
return [bitGoto, blob.read_shift(2)];
|
||||
return [bitGoto, blob.read_shift(opts && opts.biff == 2 ? 1 : 2)];
|
||||
}
|
||||
|
||||
/* 2.5.198.36 */
|
||||
function parse_PtgAttrIf(blob, length) {
|
||||
function parse_PtgAttrIf(blob, length, opts) {
|
||||
var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0;
|
||||
blob.l += 2;
|
||||
return [bitIf, blob.read_shift(opts && opts.biff == 2 ? 1 : 2)];
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.97.28 */
|
||||
function parse_PtgAttrIfError(blob, length) {
|
||||
var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0;
|
||||
blob.l += 2;
|
||||
return [bitIf, blob.read_shift(2)];
|
||||
}
|
||||
|
||||
/* 2.5.198.37 */
|
||||
function parse_PtgAttrSemi(blob, length) {
|
||||
function parse_PtgAttrSemi(blob, length, opts) {
|
||||
var bitSemi = (blob[blob.l+1] & 0xFF) ? 1 : 0;
|
||||
blob.l += 4;
|
||||
blob.l += opts && opts.biff == 2 ? 3 : 4;
|
||||
return [bitSemi];
|
||||
}
|
||||
|
||||
@ -147,46 +198,44 @@ function parse_PtgAttrSpaceSemi(blob, length) {
|
||||
}
|
||||
|
||||
/* 2.5.198.84 TODO */
|
||||
function parse_PtgRef(blob, length) {
|
||||
function parse_PtgRef(blob, length, opts) {
|
||||
var ptg = blob[blob.l] & 0x1F;
|
||||
var type = (blob[blob.l] & 0x60)>>5;
|
||||
blob.l += 1;
|
||||
var loc = parse_RgceLoc(blob,4);
|
||||
var loc = parse_RgceLoc(blob, 0, opts);
|
||||
return [type, loc];
|
||||
}
|
||||
|
||||
/* 2.5.198.88 TODO */
|
||||
function parse_PtgRefN(blob, length) {
|
||||
var ptg = blob[blob.l] & 0x1F;
|
||||
function parse_PtgRefN(blob, length, opts) {
|
||||
var type = (blob[blob.l] & 0x60)>>5;
|
||||
blob.l += 1;
|
||||
var loc = parse_RgceLocRel(blob,4);
|
||||
var loc = parse_RgceLocRel(blob, 0, opts);
|
||||
return [type, loc];
|
||||
}
|
||||
|
||||
/* 2.5.198.85 TODO */
|
||||
function parse_PtgRef3d(blob, length) {
|
||||
var ptg = blob[blob.l] & 0x1F;
|
||||
function parse_PtgRef3d(blob, length, opts) {
|
||||
var type = (blob[blob.l] & 0x60)>>5;
|
||||
blob.l += 1;
|
||||
var ixti = blob.read_shift(2); // XtiIndex
|
||||
var loc = parse_RgceLoc(blob,4);
|
||||
var loc = parse_RgceLoc(blob, 0, opts); // TODO: or RgceLocRel
|
||||
return [type, ixti, loc];
|
||||
}
|
||||
|
||||
|
||||
/* 2.5.198.62 TODO */
|
||||
function parse_PtgFunc(blob, length) {
|
||||
function parse_PtgFunc(blob, length, opts) {
|
||||
var ptg = blob[blob.l] & 0x1F;
|
||||
var type = (blob[blob.l] & 0x60)>>5;
|
||||
blob.l += 1;
|
||||
var iftab = blob.read_shift(2);
|
||||
return [FtabArgc[iftab], Ftab[iftab]];
|
||||
var iftab = blob.read_shift(opts && opts.biff <= 3 ? 1 : 2);
|
||||
return [FtabArgc[iftab], Ftab[iftab], type];
|
||||
}
|
||||
/* 2.5.198.63 TODO */
|
||||
function parse_PtgFuncVar(blob, length) {
|
||||
function parse_PtgFuncVar(blob, length, opts) {
|
||||
blob.l++;
|
||||
var cparams = blob.read_shift(1), tab = parsetab(blob);
|
||||
var cparams = blob.read_shift(1), tab = opts && opts.biff <= 3 ? [0, blob.read_shift(1)]: parsetab(blob);
|
||||
return [cparams, (tab[0] === 0 ? Ftab : Cetab)[tab[1]]];
|
||||
}
|
||||
|
||||
@ -195,22 +244,26 @@ function parsetab(blob, length) {
|
||||
}
|
||||
|
||||
/* 2.5.198.41 */
|
||||
var parse_PtgAttrSum = parseread(4);
|
||||
function parse_PtgAttrSum(blob, length, opts) {
|
||||
blob.l += opts && opts.biff == 2 ? 3 : 4; return;
|
||||
}
|
||||
|
||||
/* 2.5.198.43 */
|
||||
var parse_PtgConcat = parseread1;
|
||||
|
||||
/* 2.5.198.58 */
|
||||
function parse_PtgExp(blob, length) {
|
||||
function parse_PtgExp(blob, length, opts) {
|
||||
blob.l++;
|
||||
if(opts && opts.biff == 12) return [blob.read_shift(4, 'i'), 0];
|
||||
var row = blob.read_shift(2);
|
||||
var col = blob.read_shift(2);
|
||||
var col = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
|
||||
return [row, col];
|
||||
}
|
||||
|
||||
/* 2.5.198.57 */
|
||||
function parse_PtgErr(blob, length) { blob.l++; return BErr[blob.read_shift(1)]; }
|
||||
|
||||
/* 2.5.198.66 TODO */
|
||||
/* 2.5.198.66 */
|
||||
function parse_PtgInt(blob, length) { blob.l++; return blob.read_shift(2); }
|
||||
|
||||
/* 2.5.198.42 */
|
||||
@ -220,12 +273,19 @@ function parse_PtgBool(blob, length) { blob.l++; return blob.read_shift(1)!==0;}
|
||||
function parse_PtgNum(blob, length) { blob.l++; return parse_Xnum(blob, 8); }
|
||||
|
||||
/* 2.5.198.89 */
|
||||
function parse_PtgStr(blob, length) { blob.l++; return parse_ShortXLUnicodeString(blob); }
|
||||
function parse_PtgStr(blob, length, opts) { blob.l++; return parse_ShortXLUnicodeString(blob, length-1, opts); }
|
||||
|
||||
/* 2.5.192.112 + 2.5.192.11{3,4,5,6,7} */
|
||||
function parse_SerAr(blob) {
|
||||
var val = [];
|
||||
switch((val[0] = blob.read_shift(1))) {
|
||||
/* [MS-XLS] 2.5.192.112 + 2.5.192.11{3,4,5,6,7} */
|
||||
/* [MS-XLSB] 2.5.97.93 + 2.5.97.9{4,5,6,7} */
|
||||
function parse_SerAr(blob, biff/*:number*/) {
|
||||
var val = [blob.read_shift(1)];
|
||||
if(biff == 12) switch(val[0]) {
|
||||
case 0x02: val[0] = 0x04; break; /* SerBool */
|
||||
case 0x04: val[0] = 0x10; break; /* SerErr */
|
||||
case 0x00: val[0] = 0x01; break; /* SerNum */
|
||||
case 0x01: val[0] = 0x02; break; /* SerStr */
|
||||
}
|
||||
switch(val[0]) {
|
||||
/* 2.5.192.113 */
|
||||
case 0x04: /* SerBool -- boolean */
|
||||
val[1] = parsebool(blob, 1) ? 'TRUE' : 'FALSE';
|
||||
@ -242,7 +302,7 @@ function parse_SerAr(blob) {
|
||||
val[1] = parse_Xnum(blob, 8); break;
|
||||
/* 2.5.192.117 */
|
||||
case 0x02: /* SerStr -- XLUnicodeString (<256 chars) */
|
||||
val[1] = parse_XLUnicodeString(blob); break;
|
||||
val[1] = parse_XLUnicodeString2(blob, 0, {biff:biff > 0 && biff < 8 ? 2 : biff}); break;
|
||||
// default: throw "Bad SerAr: " + val[0]; /* Unreachable */
|
||||
}
|
||||
return val;
|
||||
@ -257,49 +317,72 @@ function parse_PtgExtraMem(blob, cce) {
|
||||
}
|
||||
|
||||
/* 2.5.198.59 */
|
||||
function parse_PtgExtraArray(blob) {
|
||||
var cols = 1 + blob.read_shift(1); //DColByteU
|
||||
var rows = 1 + blob.read_shift(2); //DRw
|
||||
function parse_PtgExtraArray(blob, length, opts) {
|
||||
var rows = 0, cols = 0;
|
||||
if(opts.biff == 12) {
|
||||
rows = blob.read_shift(4); // DRw
|
||||
cols = blob.read_shift(4); // DCol
|
||||
} else {
|
||||
cols = 1 + blob.read_shift(1); //DColByteU
|
||||
rows = 1 + blob.read_shift(2); //DRw
|
||||
}
|
||||
if(opts.biff >= 2 && opts.biff < 8) { --rows; if(--cols == 0) cols = 0x100; }
|
||||
for(var i = 0, o=[]; i != rows && (o[i] = []); ++i)
|
||||
for(var j = 0; j != cols; ++j) o[i][j] = parse_SerAr(blob);
|
||||
for(var j = 0; j != cols; ++j) o[i][j] = parse_SerAr(blob, opts.biff);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.5.198.76 */
|
||||
function parse_PtgName(blob, length) {
|
||||
function parse_PtgName(blob, length, opts) {
|
||||
var type = (blob.read_shift(1) >>> 5) & 0x03;
|
||||
var nameindex = blob.read_shift(4);
|
||||
var w = (!opts || (opts.biff >= 8)) ? 4 : 2;
|
||||
var nameindex = blob.read_shift(w);
|
||||
switch(opts.biff) {
|
||||
case 2: blob.l += 5; break;
|
||||
case 3: case 4: blob.l += 8; break;
|
||||
case 5: blob.l += 12; break;
|
||||
}
|
||||
return [type, 0, nameindex];
|
||||
}
|
||||
|
||||
/* 2.5.198.77 */
|
||||
function parse_PtgNameX(blob, length) {
|
||||
function parse_PtgNameX(blob, length, opts) {
|
||||
if(opts.biff == 5) return parse_PtgNameX_BIFF5(blob, length, opts);
|
||||
var type = (blob.read_shift(1) >>> 5) & 0x03;
|
||||
var ixti = blob.read_shift(2); // XtiIndex
|
||||
var nameindex = blob.read_shift(4);
|
||||
return [type, ixti, nameindex];
|
||||
}
|
||||
function parse_PtgNameX_BIFF5(blob, length, opts) {
|
||||
var type = (blob.read_shift(1) >>> 5) & 0x03;
|
||||
var ixti = blob.read_shift(2, 'i'); // XtiIndex
|
||||
blob.l += 8;
|
||||
var nameindex = blob.read_shift(2);
|
||||
blob.l += 12;
|
||||
return [type, ixti, nameindex];
|
||||
}
|
||||
|
||||
/* 2.5.198.70 */
|
||||
function parse_PtgMemArea(blob, length) {
|
||||
function parse_PtgMemArea(blob, length, opts) {
|
||||
var type = (blob.read_shift(1) >>> 5) & 0x03;
|
||||
blob.l += 4;
|
||||
var cce = blob.read_shift(2);
|
||||
blob.l += (opts && opts.biff == 2 ? 3 : 4);
|
||||
var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
|
||||
return [type, cce];
|
||||
}
|
||||
|
||||
/* 2.5.198.72 */
|
||||
function parse_PtgMemFunc(blob, length) {
|
||||
function parse_PtgMemFunc(blob, length, opts) {
|
||||
var type = (blob.read_shift(1) >>> 5) & 0x03;
|
||||
var cce = blob.read_shift(2);
|
||||
var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
|
||||
return [type, cce];
|
||||
}
|
||||
|
||||
|
||||
/* 2.5.198.86 */
|
||||
function parse_PtgRefErr(blob, length) {
|
||||
function parse_PtgRefErr(blob, length, opts) {
|
||||
var type = (blob.read_shift(1) >>> 5) & 0x03;
|
||||
blob.l += 4;
|
||||
if(opts.biff == 12) blob.l += 2;
|
||||
return [type];
|
||||
}
|
||||
|
||||
@ -425,7 +508,10 @@ var PtgDupes = {
|
||||
};
|
||||
(function(){for(var y in PtgDupes) PtgTypes[y] = PtgTypes[PtgDupes[y]];})();
|
||||
|
||||
var Ptg18 = {};
|
||||
var Ptg18 = {
|
||||
// /*::[*/0x19/*::]*/: { n:'PtgList', f:parse_PtgList }, // TODO
|
||||
// /*::[*/0x1D/*::]*/: { n:'PtgSxName', f:parse_PtgSxName }, // TODO
|
||||
};
|
||||
var Ptg19 = {
|
||||
/*::[*/0x01/*::]*/: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
|
||||
/*::[*/0x02/*::]*/: { n:'PtgAttrIf', f:parse_PtgAttrIf },
|
||||
@ -435,11 +521,13 @@ var Ptg19 = {
|
||||
/*::[*/0x20/*::]*/: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
|
||||
/*::[*/0x40/*::]*/: { n:'PtgAttrSpace', f:parse_PtgAttrSpace },
|
||||
/*::[*/0x41/*::]*/: { n:'PtgAttrSpaceSemi', f:parse_PtgAttrSpaceSemi },
|
||||
/*::[*/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);
|
||||
@ -450,10 +538,7 @@ function parse_Formula(blob, length, opts) {
|
||||
var chn = blob.read_shift(4);
|
||||
}
|
||||
}
|
||||
var cbf = "";
|
||||
if(opts.biff < 5) blob.l += length-16;
|
||||
else if(opts.biff === 5) blob.l += length-20;
|
||||
else cbf = parse_XLSCellParsedFormula(blob, length-20, opts);
|
||||
var cbf = parse_XLSCellParsedFormula(blob, end - blob.l, opts);
|
||||
return {cell:cell, val:val[0], formula:cbf, shared: (flags >> 3) & 1, tt:val[1]};
|
||||
}
|
||||
|
||||
@ -472,23 +557,29 @@ function parse_FormulaValue(blob) {
|
||||
|
||||
/* 2.5.198.103 */
|
||||
function parse_RgbExtra(blob, length, rgce, opts) {
|
||||
if(opts.biff < 8) return parsenoop(blob, length);
|
||||
var target = blob.l + length;
|
||||
var o = [];
|
||||
for(var i = 0; i !== rgce.length; ++i) {
|
||||
switch(rgce[i][0]) {
|
||||
case 'PtgArray': /* PtgArray -> PtgExtraArray */
|
||||
rgce[i][1] = parse_PtgExtraArray(blob);
|
||||
rgce[i][1] = parse_PtgExtraArray(blob, 0, opts);
|
||||
o.push(rgce[i][1]);
|
||||
break;
|
||||
case 'PtgMemArea': /* PtgMemArea -> PtgExtraMem */
|
||||
rgce[i][2] = parse_PtgExtraMem(blob, rgce[i][1]);
|
||||
o.push(rgce[i][2]);
|
||||
break;
|
||||
case 'PtgExp': /* PtgExp -> PtgExtraCol */
|
||||
if(opts && opts.biff == 12) {
|
||||
rgce[i][1][1] = blob.read_shift(4);
|
||||
o.push(rgce[i][1]);
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
length = target - blob.l;
|
||||
/* note: this is technically an error but Excel disregards */
|
||||
//if(target !== blob.l && blob.l !== target - length) throw new Error(target + " != " + blob.l);
|
||||
if(length !== 0) o.push(parsenoop(blob, length));
|
||||
return o;
|
||||
}
|
||||
@ -496,7 +587,7 @@ function parse_RgbExtra(blob, length, rgce, opts) {
|
||||
/* 2.5.198.21 */
|
||||
function parse_NameParsedFormula(blob, length, opts, cce) {
|
||||
var target = blob.l + length;
|
||||
var rgce = parse_Rgce(blob, cce);
|
||||
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];
|
||||
@ -504,11 +595,11 @@ function parse_NameParsedFormula(blob, length, opts, cce) {
|
||||
|
||||
/* 2.5.198.3 TODO */
|
||||
function parse_XLSCellParsedFormula(blob, length, opts) {
|
||||
var target = blob.l + length;
|
||||
var rgcb, cce = blob.read_shift(2); // length of rgce
|
||||
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);
|
||||
if(length !== cce + 2) rgcb = parse_RgbExtra(blob, length - cce - 2, rgce, opts);
|
||||
var rgce = parse_Rgce(blob, cce, opts);
|
||||
if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
@ -516,7 +607,7 @@ function parse_XLSCellParsedFormula(blob, length, opts) {
|
||||
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);
|
||||
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];
|
||||
@ -524,41 +615,71 @@ function parse_SharedParsedFormula(blob, length, opts) {
|
||||
|
||||
/* 2.5.198.1 TODO */
|
||||
function parse_ArrayParsedFormula(blob, length, opts, ref) {
|
||||
var target = blob.l + length;
|
||||
var rgcb, cce = blob.read_shift(2); // length of rgce
|
||||
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);
|
||||
if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
|
||||
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) {
|
||||
var gcnt = 0;
|
||||
function parse_Rgce(blob, length, opts) {
|
||||
var target = blob.l + length;
|
||||
var R, id, ptgs = [];
|
||||
while(target != blob.l) {
|
||||
length = target - blob.l;
|
||||
id = blob[blob.l];
|
||||
R = PtgTypes[id];
|
||||
//console.log("ptg", id, R)
|
||||
if(id === 0x18 || id === 0x19) {
|
||||
id = blob[blob.l + 1];
|
||||
R = (id === 0x18 ? Ptg18 : Ptg19)[id];
|
||||
}
|
||||
if(!R || !R.f) { ptgs.push(parsenoop(blob, length)); }
|
||||
else { ptgs.push([R.n, R.f(blob, length)]); }
|
||||
else { ptgs.push([R.n, R.f(blob, length, opts)]); }
|
||||
}
|
||||
return ptgs;
|
||||
}
|
||||
|
||||
function mapper(x) { return x.map(function f2(y) { return y[1];}).join(",");}
|
||||
function stringify_array(f) {
|
||||
var o = [];
|
||||
for(var i = 0; i < f.length; ++i) {
|
||||
var x = f[i], r = [];
|
||||
for(var j = 0; j < x.length; ++j) {
|
||||
var y = x[j];
|
||||
if(y) switch(y[0]) {
|
||||
// TODO: handle embedded quotes
|
||||
case 0x02: r.push('"' + y[1].replace(/"/g,'""') + '"'); break;
|
||||
default: r.push(y[1]);
|
||||
} else r.push("");
|
||||
}
|
||||
o.push(r.join(","));
|
||||
}
|
||||
return o.join(";");
|
||||
}
|
||||
|
||||
/* 2.2.2 + Magic TODO */
|
||||
/* [MS-XLS] 2.2.2 TODO */
|
||||
/* [MS-XLSB] 2.2.2 */
|
||||
var PtgBinOp = {
|
||||
PtgAdd: "+",
|
||||
PtgConcat: "&",
|
||||
PtgDiv: "/",
|
||||
PtgEq: "=",
|
||||
PtgGe: ">=",
|
||||
PtgGt: ">",
|
||||
PtgLe: "<=",
|
||||
PtgLt: "<",
|
||||
PtgMul: "*",
|
||||
PtgNe: "<>",
|
||||
PtgPower: "^",
|
||||
PtgSub: "-"
|
||||
};
|
||||
function stringify_formula(formula, range, cell, supbooks, opts) {
|
||||
if(opts !== undefined && opts.biff === 5) return "BIFF5??";
|
||||
var _range = range !== undefined ? range : {s:{c:0, r:0}};
|
||||
var stack = [], e1, e2, type, c, ixti, nameidx, r;
|
||||
var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}};
|
||||
var stack = [], e1, e2, type, c, ixti, nameidx, 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];
|
||||
@ -573,65 +694,31 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
|
||||
case 'PtgPercent': stack.push(stack.pop() + "%"); break;
|
||||
|
||||
/* 2.2.2.1 Binary Value Operator Token */
|
||||
/* 2.5.198.26 */
|
||||
case 'PtgAdd':
|
||||
case 'PtgAdd': /* 2.5.198.26 */
|
||||
case 'PtgConcat': /* 2.5.198.43 */
|
||||
case 'PtgDiv': /* 2.5.198.45 */
|
||||
case 'PtgEq': /* 2.5.198.56 */
|
||||
case 'PtgGe': /* 2.5.198.64 */
|
||||
case 'PtgGt': /* 2.5.198.65 */
|
||||
case 'PtgLe': /* 2.5.198.68 */
|
||||
case 'PtgLt': /* 2.5.198.69 */
|
||||
case 'PtgMul': /* 2.5.198.75 */
|
||||
case 'PtgNe': /* 2.5.198.78 */
|
||||
case 'PtgPower': /* 2.5.198.82 */
|
||||
case 'PtgSub': /* 2.5.198.90 */
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"+"+e1);
|
||||
break;
|
||||
/* 2.5.198.90 */
|
||||
case 'PtgSub':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"-"+e1);
|
||||
break;
|
||||
/* 2.5.198.75 */
|
||||
case 'PtgMul':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"*"+e1);
|
||||
break;
|
||||
/* 2.5.198.45 */
|
||||
case 'PtgDiv':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"/"+e1);
|
||||
break;
|
||||
/* 2.5.198.82 */
|
||||
case 'PtgPower':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"^"+e1);
|
||||
break;
|
||||
/* 2.5.198.43 */
|
||||
case 'PtgConcat':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"&"+e1);
|
||||
break;
|
||||
/* 2.5.198.69 */
|
||||
case 'PtgLt':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"<"+e1);
|
||||
break;
|
||||
/* 2.5.198.68 */
|
||||
case 'PtgLe':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"<="+e1);
|
||||
break;
|
||||
/* 2.5.198.56 */
|
||||
case 'PtgEq':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"="+e1);
|
||||
break;
|
||||
/* 2.5.198.64 */
|
||||
case 'PtgGe':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+">="+e1);
|
||||
break;
|
||||
/* 2.5.198.65 */
|
||||
case 'PtgGt':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+">"+e1);
|
||||
break;
|
||||
/* 2.5.198.78 */
|
||||
case 'PtgNe':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"<>"+e1);
|
||||
if(last_sp >= 0) {
|
||||
switch(formula[0][last_sp][1][0]) {
|
||||
case 0: sp = fill(" ", formula[0][last_sp][1][1]); break;
|
||||
case 1: sp = fill("\r", formula[0][last_sp][1][1]); break;
|
||||
default:
|
||||
sp = "";
|
||||
if(opts.WTF) throw new Error("Unexpected PtgSpace type " + formula[0][last_sp][1][0]);
|
||||
}
|
||||
e2 = e2 + sp;
|
||||
last_sp = -1;
|
||||
}
|
||||
stack.push(e2+PtgBinOp[f[0]]+e1);
|
||||
break;
|
||||
|
||||
/* 2.2.2.1 Binary Reference Operator Token */
|
||||
@ -644,7 +731,10 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+","+e1);
|
||||
break;
|
||||
case 'PtgRange': break;
|
||||
case 'PtgRange':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+":"+e1);
|
||||
break;
|
||||
|
||||
/* 2.2.2.3 Control Tokens "can be ignored" */
|
||||
/* 2.5.198.34 */
|
||||
@ -653,21 +743,24 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
|
||||
case 'PtgAttrGoto': break;
|
||||
/* 2.5.198.36 */
|
||||
case 'PtgAttrIf': break;
|
||||
/* [MS-XLSB] 2.5.97.28 */
|
||||
case 'PtgAttrIfError': break;
|
||||
|
||||
|
||||
/* 2.5.198.84 */
|
||||
case 'PtgRef':
|
||||
type = f[1][0]; c = shift_cell_xls(decode_cell(encode_cell(f[1][1])), _range);
|
||||
stack.push(encode_cell(c));
|
||||
type = f[1][0]; c = shift_cell_xls(f[1][1], _range, opts);
|
||||
stack.push(encode_cell_xls(c));
|
||||
break;
|
||||
/* 2.5.198.88 */
|
||||
case 'PtgRefN':
|
||||
type = f[1][0]; c = shift_cell_xls(decode_cell(encode_cell(f[1][1])), cell);
|
||||
stack.push(encode_cell(c));
|
||||
type = f[1][0]; c = shift_cell_xls(f[1][1], cell, opts);
|
||||
stack.push(encode_cell_xls(c));
|
||||
break;
|
||||
case 'PtgRef3d': // TODO: lots of stuff
|
||||
type = f[1][0]; ixti = f[1][1]; c = shift_cell_xls(f[1][2], _range);
|
||||
stack.push(supbooks[1][ixti+1]+"!"+encode_cell(c));
|
||||
type = f[1][0]; ixti = f[1][1]; c = shift_cell_xls(f[1][2], _range, opts);
|
||||
sname = (supbooks && supbooks[1] ? supbooks[1][ixti+1] : "**MISSING**");
|
||||
stack.push(sname + "!" + encode_cell(c));
|
||||
break;
|
||||
|
||||
/* Function Call */
|
||||
@ -675,10 +768,10 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
|
||||
case 'PtgFunc':
|
||||
/* 2.5.198.63 */
|
||||
case 'PtgFuncVar':
|
||||
/* f[1] = [argc, func] */
|
||||
/* f[1] = [argc, func, type] */
|
||||
var argc = f[1][0], func = f[1][1];
|
||||
if(!argc) argc = 0;
|
||||
var args = stack.slice(-argc);
|
||||
var args = argc == 0 ? [] : stack.slice(-argc);
|
||||
stack.length -= argc;
|
||||
if(func === 'User') func = args.shift();
|
||||
stack.push(func + "(" + args.join(",") + ")");
|
||||
@ -697,12 +790,13 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
|
||||
/* 2.5.198.27 TODO: fixed points */
|
||||
case 'PtgArea':
|
||||
type = f[1][0]; r = shift_range_xls(f[1][1], _range);
|
||||
stack.push(encode_range(r));
|
||||
stack.push(encode_range_xls(r));
|
||||
break;
|
||||
/* 2.5.198.28 */
|
||||
case 'PtgArea3d': // TODO: lots of stuff
|
||||
type = f[1][0]; ixti = f[1][1]; r = f[1][2];
|
||||
stack.push(supbooks[1][ixti+1]+"!"+encode_range(r));
|
||||
sname = (supbooks && supbooks[1] ? supbooks[1][ixti+1] : "**MISSING**");
|
||||
stack.push(sname + "!" + encode_range(r));
|
||||
break;
|
||||
/* 2.5.198.41 */
|
||||
case 'PtgAttrSum':
|
||||
@ -718,7 +812,7 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
|
||||
/* f[1] = type, 0, nameindex */
|
||||
nameidx = f[1][2];
|
||||
var lbl = supbooks[0][nameidx];
|
||||
var name = lbl.Name;
|
||||
var name = lbl ? lbl.Name : "**MISSING**" + nameidx;
|
||||
if(name in XLSXFutureFunctions) name = XLSXFutureFunctions[name];
|
||||
stack.push(name);
|
||||
break;
|
||||
@ -728,15 +822,35 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
|
||||
/* f[1] = type, ixti, nameindex */
|
||||
var bookidx = f[1][1]; nameidx = f[1][2]; var externbook;
|
||||
/* TODO: Properly handle missing values */
|
||||
if(supbooks[bookidx+1]) externbook = supbooks[bookidx+1][nameidx];
|
||||
else if(supbooks[bookidx-1]) externbook = supbooks[bookidx-1][nameidx];
|
||||
//console.log(bookidx, supbooks);
|
||||
if(opts.biff == 5) {
|
||||
if(bookidx < 0) bookidx = -bookidx;
|
||||
if(supbooks[bookidx]) externbook = supbooks[bookidx][nameidx];
|
||||
} else {
|
||||
if(supbooks[bookidx+1]) externbook = supbooks[bookidx+1][nameidx];
|
||||
else if(supbooks[bookidx-1]) externbook = supbooks[bookidx-1][nameidx];
|
||||
}
|
||||
if(!externbook) externbook = {body: "??NAMEX??"};
|
||||
stack.push(externbook.body);
|
||||
break;
|
||||
|
||||
/* 2.2.2.4 Display Tokens */
|
||||
/* 2.5.198.80 */
|
||||
case 'PtgParen': stack.push('(' + stack.pop() + ')'); break;
|
||||
case 'PtgParen':
|
||||
var lp = '(', rp = ')';
|
||||
if(last_sp >= 0) {
|
||||
sp = "";
|
||||
switch(formula[0][last_sp][1][0]) {
|
||||
case 2: lp = fill(" ", formula[0][last_sp][1][1]) + lp; break;
|
||||
case 3: lp = fill("\r", formula[0][last_sp][1][1]) + lp; break;
|
||||
case 4: rp = fill(" ", formula[0][last_sp][1][1]) + lp; break;
|
||||
case 5: rp = fill("\r", formula[0][last_sp][1][1]) + lp; break;
|
||||
default:
|
||||
if(opts.WTF) throw new Error("Unexpected PtgSpace type " + formula[0][last_sp][1][0]);
|
||||
}
|
||||
last_sp = -1;
|
||||
}
|
||||
stack.push(lp + stack.pop() + rp); break;
|
||||
|
||||
/* 2.5.198.86 */
|
||||
case 'PtgRefErr': stack.push('#REF!'); break;
|
||||
@ -758,6 +872,8 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
|
||||
if(c.c < e2[0].s.c || c.c > e2[0].e.c) continue;
|
||||
if(c.r < e2[0].s.r || c.r > e2[0].e.r) continue;
|
||||
stack.push(stringify_formula(e2[1], _range, q, supbooks, opts));
|
||||
fnd = true;
|
||||
break;
|
||||
}
|
||||
if(!fnd) stack.push(f[1]);
|
||||
}
|
||||
@ -765,7 +881,7 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
|
||||
|
||||
/* 2.5.198.32 TODO */
|
||||
case 'PtgArray':
|
||||
stack.push("{" + f[1].map(mapper).join(";") + "}");
|
||||
stack.push("{" + stringify_array(f[1]) + "}");
|
||||
break;
|
||||
|
||||
/* 2.2.2.5 Mem Tokens */
|
||||
@ -774,8 +890,11 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
|
||||
//stack.push("(" + f[2].map(encode_range).join(",") + ")");
|
||||
break;
|
||||
|
||||
/* 2.5.198.38 TODO */
|
||||
case 'PtgAttrSpace': break;
|
||||
/* 2.5.198.38 */
|
||||
case 'PtgAttrSpace':
|
||||
case 'PtgAttrSpaceSemi':
|
||||
last_sp = ff;
|
||||
break;
|
||||
|
||||
/* 2.5.198.92 TODO */
|
||||
case 'PtgTbl': break;
|
||||
@ -802,9 +921,23 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
|
||||
|
||||
default: throw 'Unrecognized Formula Token: ' + f;
|
||||
}
|
||||
var PtgNonDisp = ['PtgAttrSpace', 'PtgAttrSpaceSemi', 'PtgAttrGoto'];
|
||||
if(last_sp >= 0 && PtgNonDisp.indexOf(formula[0][ff][0]) == -1) {
|
||||
f = formula[0][last_sp];
|
||||
switch(f[1][0]) {
|
||||
case 0: sp = fill(" ", f[1][1]); break;
|
||||
case 1: sp = fill("\r", f[1][1]); break;
|
||||
default:
|
||||
sp = "";
|
||||
if(opts.WTF) throw new Error("Unexpected PtgSpace type " + f[1][0]);
|
||||
}
|
||||
stack.push(sp + stack.pop());
|
||||
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,5 +1,18 @@
|
||||
/* [MS-XLSB] 2.5.97.4 CellParsedFormula TODO: use similar logic to js-xls */
|
||||
function parse_XLSBCellParsedFormula(data, length) {
|
||||
/* XLSB Parsed Formula records have the same shape */
|
||||
function parse_XLSBParsedFormula(data, length, opts) {
|
||||
var end = data.l + length;
|
||||
var cce = data.read_shift(4);
|
||||
return parsenoop(data, length-4);
|
||||
var rgce = parse_Rgce(data, cce, opts);
|
||||
var cb = data.read_shift(4);
|
||||
var rgcb = cb > 0 ? parse_RgbExtra(data, cb, rgce, opts) : null;
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.97.1 ArrayParsedFormula */
|
||||
var parse_XLSBArrayParsedFormula = parse_XLSBParsedFormula;
|
||||
/* [MS-XLSB] 2.5.97.4 CellParsedFormula */
|
||||
var parse_XLSBCellParsedFormula = parse_XLSBParsedFormula;
|
||||
/* [MS-XLSB] 2.5.97.12 NameParsedFormula */
|
||||
var parse_XLSBNameParsedFormula = parse_XLSBParsedFormula;
|
||||
/* [MS-XLSB] 2.5.97.98 SharedParsedFormula */
|
||||
var parse_XLSBSharedParsedFormula = parse_XLSBParsedFormula;
|
||||
|
121
bits/64_ftab.js
121
bits/64_ftab.js
@ -406,6 +406,7 @@ var Cetab = {
|
||||
};
|
||||
|
||||
/* [MS-XLS] 2.5.198.17 */
|
||||
/* [MS-XLSB] 2.5.97.10 */
|
||||
var Ftab = {
|
||||
/*::[*/0x0000/*::]*/: 'COUNT',
|
||||
/*::[*/0x0001/*::]*/: 'IF',
|
||||
@ -779,7 +780,113 @@ var Ftab = {
|
||||
/*::[*/0x0178/*::]*/: 'ROUNDBAHTDOWN',
|
||||
/*::[*/0x0179/*::]*/: 'ROUNDBAHTUP',
|
||||
/*::[*/0x017A/*::]*/: 'THAIYEAR',
|
||||
/*::[*/0x017B/*::]*/: 'RTD'
|
||||
/*::[*/0x017B/*::]*/: 'RTD',
|
||||
|
||||
/*::[*/0x017C/*::]*/: 'CUBEVALUE',
|
||||
/*::[*/0x017D/*::]*/: 'CUBEMEMBER',
|
||||
/*::[*/0x017E/*::]*/: 'CUBEMEMBERPROPERTY',
|
||||
/*::[*/0x017F/*::]*/: 'CUBERANKEDMEMBER',
|
||||
/*::[*/0x0180/*::]*/: 'HEX2BIN',
|
||||
/*::[*/0x0181/*::]*/: 'HEX2DEC',
|
||||
/*::[*/0x0182/*::]*/: 'HEX2OCT',
|
||||
/*::[*/0x0183/*::]*/: 'DEC2BIN',
|
||||
/*::[*/0x0184/*::]*/: 'DEC2HEX',
|
||||
/*::[*/0x0185/*::]*/: 'DEC2OCT',
|
||||
/*::[*/0x0186/*::]*/: 'OCT2BIN',
|
||||
/*::[*/0x0187/*::]*/: 'OCT2HEX',
|
||||
/*::[*/0x0188/*::]*/: 'OCT2DEC',
|
||||
/*::[*/0x0189/*::]*/: 'BIN2DEC',
|
||||
/*::[*/0x018A/*::]*/: 'BIN2OCT',
|
||||
/*::[*/0x018B/*::]*/: 'BIN2HEX',
|
||||
/*::[*/0x018C/*::]*/: 'IMSUB',
|
||||
/*::[*/0x018D/*::]*/: 'IMDIV',
|
||||
/*::[*/0x018E/*::]*/: 'IMPOWER',
|
||||
/*::[*/0x018F/*::]*/: 'IMABS',
|
||||
/*::[*/0x0190/*::]*/: 'IMSQRT',
|
||||
/*::[*/0x0191/*::]*/: 'IMLN',
|
||||
/*::[*/0x0192/*::]*/: 'IMLOG2',
|
||||
/*::[*/0x0193/*::]*/: 'IMLOG10',
|
||||
/*::[*/0x0194/*::]*/: 'IMSIN',
|
||||
/*::[*/0x0195/*::]*/: 'IMCOS',
|
||||
/*::[*/0x0196/*::]*/: 'IMEXP',
|
||||
/*::[*/0x0197/*::]*/: 'IMARGUMENT',
|
||||
/*::[*/0x0198/*::]*/: 'IMCONJUGATE',
|
||||
/*::[*/0x0199/*::]*/: 'IMAGINARY',
|
||||
/*::[*/0x019A/*::]*/: 'IMREAL',
|
||||
/*::[*/0x019B/*::]*/: 'COMPLEX',
|
||||
/*::[*/0x019C/*::]*/: 'IMSUM',
|
||||
/*::[*/0x019D/*::]*/: 'IMPRODUCT',
|
||||
/*::[*/0x019E/*::]*/: 'SERIESSUM',
|
||||
/*::[*/0x019F/*::]*/: 'FACTDOUBLE',
|
||||
/*::[*/0x01A0/*::]*/: 'SQRTPI',
|
||||
/*::[*/0x01A1/*::]*/: 'QUOTIENT',
|
||||
/*::[*/0x01A2/*::]*/: 'DELTA',
|
||||
/*::[*/0x01A3/*::]*/: 'GESTEP',
|
||||
/*::[*/0x01A4/*::]*/: 'ISEVEN',
|
||||
/*::[*/0x01A5/*::]*/: 'ISODD',
|
||||
/*::[*/0x01A6/*::]*/: 'MROUND',
|
||||
/*::[*/0x01A7/*::]*/: 'ERF',
|
||||
/*::[*/0x01A8/*::]*/: 'ERFC',
|
||||
/*::[*/0x01A9/*::]*/: 'BESSELJ',
|
||||
/*::[*/0x01AA/*::]*/: 'BESSELK',
|
||||
/*::[*/0x01AB/*::]*/: 'BESSELY',
|
||||
/*::[*/0x01AC/*::]*/: 'BESSELI',
|
||||
/*::[*/0x01AD/*::]*/: 'XIRR',
|
||||
/*::[*/0x01AE/*::]*/: 'XNPV',
|
||||
/*::[*/0x01AF/*::]*/: 'PRICEMAT',
|
||||
/*::[*/0x01B0/*::]*/: 'YIELDMAT',
|
||||
/*::[*/0x01B1/*::]*/: 'INTRATE',
|
||||
/*::[*/0x01B2/*::]*/: 'RECEIVED',
|
||||
/*::[*/0x01B3/*::]*/: 'DISC',
|
||||
/*::[*/0x01B4/*::]*/: 'PRICEDISC',
|
||||
/*::[*/0x01B5/*::]*/: 'YIELDDISC',
|
||||
/*::[*/0x01B6/*::]*/: 'TBILLEQ',
|
||||
/*::[*/0x01B7/*::]*/: 'TBILLPRICE',
|
||||
/*::[*/0x01B8/*::]*/: 'TBILLYIELD',
|
||||
/*::[*/0x01B9/*::]*/: 'PRICE',
|
||||
/*::[*/0x01BA/*::]*/: 'YIELD',
|
||||
/*::[*/0x01BB/*::]*/: 'DOLLARDE',
|
||||
/*::[*/0x01BC/*::]*/: 'DOLLARFR',
|
||||
/*::[*/0x01BD/*::]*/: 'NOMINAL',
|
||||
/*::[*/0x01BE/*::]*/: 'EFFECT',
|
||||
/*::[*/0x01BF/*::]*/: 'CUMPRINC',
|
||||
/*::[*/0x01C0/*::]*/: 'CUMIPMT',
|
||||
/*::[*/0x01C1/*::]*/: 'EDATE',
|
||||
/*::[*/0x01C2/*::]*/: 'EOMONTH',
|
||||
/*::[*/0x01C3/*::]*/: 'YEARFRAC',
|
||||
/*::[*/0x01C4/*::]*/: 'COUPDAYBS',
|
||||
/*::[*/0x01C5/*::]*/: 'COUPDAYS',
|
||||
/*::[*/0x01C6/*::]*/: 'COUPDAYSNC',
|
||||
/*::[*/0x01C7/*::]*/: 'COUPNCD',
|
||||
/*::[*/0x01C8/*::]*/: 'COUPNUM',
|
||||
/*::[*/0x01C9/*::]*/: 'COUPPCD',
|
||||
/*::[*/0x01CA/*::]*/: 'DURATION',
|
||||
/*::[*/0x01CB/*::]*/: 'MDURATION',
|
||||
/*::[*/0x01CC/*::]*/: 'ODDLPRICE',
|
||||
/*::[*/0x01CD/*::]*/: 'ODDLYIELD',
|
||||
/*::[*/0x01CE/*::]*/: 'ODDFPRICE',
|
||||
/*::[*/0x01CF/*::]*/: 'ODDFYIELD',
|
||||
/*::[*/0x01D0/*::]*/: 'RANDBETWEEN',
|
||||
/*::[*/0x01D1/*::]*/: 'WEEKNUM',
|
||||
/*::[*/0x01D2/*::]*/: 'AMORDEGRC',
|
||||
/*::[*/0x01D3/*::]*/: 'AMORLINC',
|
||||
/*::[*/0x01D4/*::]*/: 'SHEETJS',
|
||||
/*::[*/0x01D5/*::]*/: 'ACCRINT',
|
||||
/*::[*/0x01D6/*::]*/: 'ACCRINTM',
|
||||
/*::[*/0x01D7/*::]*/: 'WORKDAY',
|
||||
/*::[*/0x01D8/*::]*/: 'NETWORKDAYS',
|
||||
/*::[*/0x01D9/*::]*/: 'GCD',
|
||||
/*::[*/0x01DA/*::]*/: 'MULTINOMIAL',
|
||||
/*::[*/0x01DB/*::]*/: 'LCM',
|
||||
/*::[*/0x01DC/*::]*/: 'FVSCHEDULE',
|
||||
/*::[*/0x01DD/*::]*/: 'CUBEKPIMEMBER',
|
||||
/*::[*/0x01DE/*::]*/: 'CUBESET',
|
||||
/*::[*/0x01DF/*::]*/: 'CUBESETCOUNT',
|
||||
/*::[*/0x01E0/*::]*/: 'IFERROR',
|
||||
/*::[*/0x01E1/*::]*/: 'COUNTIFS',
|
||||
/*::[*/0x01E2/*::]*/: 'SUMIFS',
|
||||
/*::[*/0x01E3/*::]*/: 'AVERAGEIF',
|
||||
/*::[*/0x01E4/*::]*/: 'AVERAGEIFS'
|
||||
};
|
||||
var FtabArgc = {
|
||||
/*::[*/0x0002/*::]*/: 1, /* ISNA */
|
||||
@ -788,6 +895,7 @@ var FtabArgc = {
|
||||
/*::[*/0x0010/*::]*/: 1, /* COS */
|
||||
/*::[*/0x0011/*::]*/: 1, /* TAN */
|
||||
/*::[*/0x0012/*::]*/: 1, /* ATAN */
|
||||
/*::[*/0x0013/*::]*/: 0, /* PI */
|
||||
/*::[*/0x0014/*::]*/: 1, /* SQRT */
|
||||
/*::[*/0x0015/*::]*/: 1, /* EXP */
|
||||
/*::[*/0x0016/*::]*/: 1, /* LN */
|
||||
@ -817,6 +925,7 @@ var FtabArgc = {
|
||||
/*::[*/0x0043/*::]*/: 1, /* DAY */
|
||||
/*::[*/0x0044/*::]*/: 1, /* MONTH */
|
||||
/*::[*/0x0045/*::]*/: 1, /* YEAR */
|
||||
/*::[*/0x0046/*::]*/: 1, /* WEEKDAY */
|
||||
/*::[*/0x0047/*::]*/: 1, /* HOUR */
|
||||
/*::[*/0x0048/*::]*/: 1, /* MINUTE */
|
||||
/*::[*/0x0049/*::]*/: 1, /* SECOND */
|
||||
@ -826,11 +935,14 @@ var FtabArgc = {
|
||||
/*::[*/0x004F/*::]*/: 2, /* ABSREF */
|
||||
/*::[*/0x0050/*::]*/: 2, /* RELREF */
|
||||
/*::[*/0x0053/*::]*/: 1, /* TRANSPOSE */
|
||||
/*::[*/0x0055/*::]*/: 0, /* STEP */
|
||||
/*::[*/0x0056/*::]*/: 1, /* TYPE */
|
||||
/*::[*/0x005A/*::]*/: 1, /* DEREF */
|
||||
/*::[*/0x0061/*::]*/: 2, /* ATAN2 */
|
||||
/*::[*/0x0062/*::]*/: 1, /* ASIN */
|
||||
/*::[*/0x0063/*::]*/: 1, /* ACOS */
|
||||
/*::[*/0x0065/*::]*/: 3, /* HLOOKUP */
|
||||
/*::[*/0x0066/*::]*/: 3, /* VLOOKUP */
|
||||
/*::[*/0x0069/*::]*/: 1, /* ISREF */
|
||||
/*::[*/0x006F/*::]*/: 1, /* CHAR */
|
||||
/*::[*/0x0070/*::]*/: 1, /* LOWER */
|
||||
@ -856,6 +968,7 @@ var FtabArgc = {
|
||||
/*::[*/0x008D/*::]*/: 1, /* TIMEVALUE */
|
||||
/*::[*/0x008E/*::]*/: 3, /* SLN */
|
||||
/*::[*/0x008F/*::]*/: 4, /* SYD */
|
||||
/*::[*/0x0090/*::]*/: 4, /* DDB */
|
||||
/*::[*/0x00A2/*::]*/: 1, /* CLEAN */
|
||||
/*::[*/0x00A3/*::]*/: 1, /* MDETERM */
|
||||
/*::[*/0x00A4/*::]*/: 1, /* MINVERSE */
|
||||
@ -871,6 +984,7 @@ var FtabArgc = {
|
||||
/*::[*/0x00BE/*::]*/: 1, /* ISNONTEXT */
|
||||
/*::[*/0x00C3/*::]*/: 3, /* DSTDEVP */
|
||||
/*::[*/0x00C4/*::]*/: 3, /* DVARP */
|
||||
/*::[*/0x00C5/*::]*/: 1, /* TRUNC */
|
||||
/*::[*/0x00C6/*::]*/: 1, /* ISLOGICAL */
|
||||
/*::[*/0x00C7/*::]*/: 3, /* DCOUNTA */
|
||||
/*::[*/0x00C9/*::]*/: 1, /* UNREGISTER */
|
||||
@ -889,6 +1003,7 @@ var FtabArgc = {
|
||||
/*::[*/0x00EA/*::]*/: 1, /* ATANH */
|
||||
/*::[*/0x00EB/*::]*/: 3, /* DGET */
|
||||
/*::[*/0x00F4/*::]*/: 1, /* INFO */
|
||||
/*::[*/0x00F7/*::]*/: 4, /* DB */
|
||||
/*::[*/0x00FC/*::]*/: 2, /* FREQUENCY */
|
||||
/*::[*/0x0101/*::]*/: 1, /* EVALUATE */
|
||||
/*::[*/0x0105/*::]*/: 1, /* ERROR.TYPE */
|
||||
@ -964,9 +1079,13 @@ var FtabArgc = {
|
||||
/*::[*/0x0178/*::]*/: 1, /* ROUNDBAHTDOWN */
|
||||
/*::[*/0x0179/*::]*/: 1, /* ROUNDBAHTUP */
|
||||
/*::[*/0x017A/*::]*/: 1, /* THAIYEAR */
|
||||
/*::[*/0x01A0/*::]*/: 1, /* SQRTPI */
|
||||
/*::[*/0x01C1/*::]*/: 2, /* EDATE */
|
||||
/*::[*/0x01C2/*::]*/: 2, /* EOMONTH */
|
||||
/*::[*/0xFFFF/*::]*/: 0
|
||||
};
|
||||
/* [MS-XLSX] 2.2.3 Functions */
|
||||
/* [MS-XLSB] 2.5.97.10 Ftab */
|
||||
var XLSXFutureFunctions = {
|
||||
"_xlfn.ACOT": "ACOT",
|
||||
"_xlfn.ACOTH": "ACOTH",
|
||||
|
@ -8,10 +8,10 @@ var hlinkregex = /<(?:\w*:)?hyperlink[^>]*\/>/g;
|
||||
var dimregex = /"(\w*:\w*)"/;
|
||||
var colregex = /<(?:\w*:)?col[^>]*\/>/g;
|
||||
/* 18.3 Worksheets */
|
||||
function parse_ws_xml(data/*:?string*/, opts, rels) {
|
||||
function parse_ws_xml(data/*:?string*/, opts, rels)/*:Worksheet*/ {
|
||||
if(!data) return data;
|
||||
/* 18.3.1.99 worksheet CT_Worksheet */
|
||||
var s = {};
|
||||
var s = ({}/*:any*/);
|
||||
|
||||
/* 18.3.1.35 dimension CT_SheetDimension ? */
|
||||
// $FlowIgnore
|
||||
@ -166,13 +166,16 @@ function write_ws_xml_cell(cell, ref, ws, opts, idx, wb) {
|
||||
var parse_ws_xml_data = (function parse_ws_xml_data_factory() {
|
||||
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) {
|
||||
var ri = 0, x = "", cells = [], cref = [], idx = 0, i=0, cc=0, d="", p/*:any*/;
|
||||
var tag, tagr = 0, tagc = 0;
|
||||
var sstr;
|
||||
var sstr, ftag;
|
||||
var fmtid = 0, fillid = 0, do_format = Array.isArray(styles.CellXf), cf;
|
||||
var arrayf = [];
|
||||
var sharedf = [];
|
||||
for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
|
||||
x = marr[mt].trim();
|
||||
var xlen = x.length;
|
||||
@ -209,10 +212,29 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
|
||||
d = x.substr(i);
|
||||
p = ({t:""}/*:any*/);
|
||||
|
||||
// $FlowIgnore
|
||||
if((cref=d.match(match_v))!= null && cref[1] !== '') p.v=unescapexml(cref[1]);
|
||||
// $FlowIgnore
|
||||
if(opts.cellFormula && (cref=d.match(match_f))!= null && cref[1] !== '') p.f=unescapexml(cref[1]);
|
||||
if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
|
||||
if(opts.cellFormula) {
|
||||
if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') {
|
||||
p.f=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]))];
|
||||
}
|
||||
} else if((cref=d.match(/<f[^>]*\/>/))) {
|
||||
ftag = parsexmltag(cref[0]);
|
||||
if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][0].ref, tag.r);
|
||||
}
|
||||
/* TODO: factor out contains logic */
|
||||
var _tag = decode_cell(tag.r);
|
||||
for(i = 0; i < arrayf.length; ++i)
|
||||
if(_tag.r >= arrayf[i][0].s.r && _tag.r <= arrayf[i][0].e.r)
|
||||
if(_tag.c >= arrayf[i][0].s.c && _tag.c <= arrayf[i][0].e.c)
|
||||
p.F = arrayf[i][1];
|
||||
}
|
||||
|
||||
/* SCHEMA IS ACTUALLY INCORRECT HERE. IF A CELL HAS NO T, EMIT "" */
|
||||
if(tag.t === undefined && p.v === undefined) {
|
||||
|
110
bits/68_wsbin.js
110
bits/68_wsbin.js
@ -145,53 +145,65 @@ function write_BrtCellSt(cell, ncell, o) {
|
||||
|
||||
/* [MS-XLSB] 2.4.647 BrtFmlaBool */
|
||||
function parse_BrtFmlaBool(data, length, opts) {
|
||||
var end = data.l + length;
|
||||
var cell = parse_XLSBCell(data);
|
||||
cell.r = opts['!row'];
|
||||
var value = data.read_shift(1);
|
||||
var o = [cell, value, 'b'];
|
||||
if(opts.cellFormula) {
|
||||
var formula = parse_XLSBCellParsedFormula(data, length-9);
|
||||
o[3] = ""; /* TODO */
|
||||
data.l += 2;
|
||||
var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
|
||||
o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
|
||||
}
|
||||
else data.l += length-9;
|
||||
else data.l = end;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.648 BrtFmlaError */
|
||||
function parse_BrtFmlaError(data, length, opts) {
|
||||
var end = data.l + length;
|
||||
var cell = parse_XLSBCell(data);
|
||||
cell.r = opts['!row'];
|
||||
var value = data.read_shift(1);
|
||||
var o = [cell, value, 'e'];
|
||||
if(opts.cellFormula) {
|
||||
var formula = parse_XLSBCellParsedFormula(data, length-9);
|
||||
o[3] = ""; /* TODO */
|
||||
data.l += 2;
|
||||
var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
|
||||
o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
|
||||
}
|
||||
else data.l += length-9;
|
||||
else data.l = end;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.649 BrtFmlaNum */
|
||||
function parse_BrtFmlaNum(data, length, opts) {
|
||||
var end = data.l + length;
|
||||
var cell = parse_XLSBCell(data);
|
||||
cell.r = opts['!row'];
|
||||
var value = parse_Xnum(data);
|
||||
var o = [cell, value, 'n'];
|
||||
if(opts.cellFormula) {
|
||||
var formula = parse_XLSBCellParsedFormula(data, length - 16);
|
||||
o[3] = ""; /* TODO */
|
||||
data.l += 2;
|
||||
var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
|
||||
o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
|
||||
}
|
||||
else data.l += length-16;
|
||||
else data.l = end;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.650 BrtFmlaString */
|
||||
function parse_BrtFmlaString(data, length, opts) {
|
||||
var start = data.l;
|
||||
var end = data.l + length;
|
||||
var cell = parse_XLSBCell(data);
|
||||
cell.r = opts['!row'];
|
||||
var value = parse_XLWideString(data);
|
||||
var o = [cell, value, 'str'];
|
||||
if(opts.cellFormula) {
|
||||
var formula = parse_XLSBCellParsedFormula(data, start + length - data.l);
|
||||
data.l += 2;
|
||||
var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
|
||||
o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
|
||||
}
|
||||
else data.l = start + length;
|
||||
else data.l = end;
|
||||
return o;
|
||||
}
|
||||
|
||||
@ -210,8 +222,34 @@ function parse_BrtHLink(data, length, opts) {
|
||||
return {rfx:rfx, relId:relId, loc:loc, tooltip:tooltip, display:display};
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.6 BrtArrFmla */
|
||||
function parse_BrtArrFmla(data, length, opts) {
|
||||
var end = data.l + length;
|
||||
var rfx = parse_RfX(data, 16);
|
||||
var fAlwaysCalc = data.read_shift(1);
|
||||
var o = [rfx, null, fAlwaysCalc];
|
||||
if(opts.cellFormula) {
|
||||
var formula = parse_XLSBArrayParsedFormula(data, end - data.l, opts);
|
||||
o[1] = formula;
|
||||
} else data.l = end;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.742 BrtShrFmla */
|
||||
function parse_BrtShrFmla(data, length, opts) {
|
||||
var end = data.l + length;
|
||||
var rfx = parse_UncheckedRfX(data, 16);
|
||||
var o = [rfx, null];
|
||||
if(opts.cellFormula) {
|
||||
var formula = parse_XLSBSharedParsedFormula(data, end - data.l, opts);
|
||||
o[1] = formula;
|
||||
data.l = end;
|
||||
} else data.l = end;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.61 Worksheet */
|
||||
function parse_ws_bin(data, opts, rels) {
|
||||
function parse_ws_bin(data, opts, rels, wb)/*:Worksheet*/ {
|
||||
if(!data) return data;
|
||||
if(!rels) rels = {'!id':{}};
|
||||
var s = {};
|
||||
@ -222,8 +260,22 @@ function parse_ws_bin(data, opts, rels) {
|
||||
var pass = false, end = false;
|
||||
var row, p, cf, R, C, addr, sstr, rr;
|
||||
var mergecells = [];
|
||||
if(!opts) opts = {};
|
||||
opts.biff = 12;
|
||||
opts['!row'] = 0;
|
||||
|
||||
var ai = 0, af = false;
|
||||
|
||||
var array_formulae = [];
|
||||
var shared_formulae = {};
|
||||
var supbooks = ([[]]/*:any*/);
|
||||
supbooks.sharedf = shared_formulae;
|
||||
supbooks.arrayf = array_formulae;
|
||||
opts.supbooks = supbooks;
|
||||
|
||||
for(var i = 0; i < wb.Names['!names'].length; ++i) supbooks[0][i+1] = wb.Names[wb.Names['!names'][i]];
|
||||
|
||||
recordhopper(data, function ws_parse(val, Record) {
|
||||
//console.log(Record);
|
||||
if(end) return;
|
||||
switch(Record.n) {
|
||||
case 'BrtWsDim': ref = val; break;
|
||||
@ -231,6 +283,7 @@ function parse_ws_bin(data, opts, rels) {
|
||||
row = val;
|
||||
if(opts.sheetRows && opts.sheetRows <= row.r) end=true;
|
||||
rr = encode_row(row.r);
|
||||
opts['!row'] = row.r;
|
||||
break;
|
||||
|
||||
case 'BrtFmlaBool':
|
||||
@ -251,9 +304,19 @@ function parse_ws_bin(data, opts, rels) {
|
||||
case 'e': p.v = val[1]; p.w = BErr[p.v]; break;
|
||||
case 'str': p.t = 's'; p.v = utf8read(val[1]); break;
|
||||
}
|
||||
if(opts.cellFormula && val.length > 3) p.f = val[3];
|
||||
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts);
|
||||
s[encode_col(C=val[0].c) + rr] = p;
|
||||
if(opts.cellFormula) {
|
||||
af = false;
|
||||
for(ai = 0; ai < array_formulae.length; ++ai) {
|
||||
var aii = array_formulae[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;
|
||||
}
|
||||
}
|
||||
if(!af && val.length > 3) p.f = val[3];
|
||||
}
|
||||
if(refguess.s.r > row.r) refguess.s.r = row.r;
|
||||
if(refguess.s.c > C) refguess.s.c = C;
|
||||
if(refguess.e.r < row.r) refguess.e.r = row.r;
|
||||
@ -288,8 +351,17 @@ function parse_ws_bin(data, opts, rels) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'BrtArrFmla': break; // TODO
|
||||
case 'BrtShrFmla': break; // TODO
|
||||
case 'BrtArrFmla': if(!opts.cellFormula) break;
|
||||
array_formulae.push(val);
|
||||
s[encode_col(C) + rr].f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
|
||||
s[encode_col(C) + rr].F = encode_range(val[0]);
|
||||
break;
|
||||
case 'BrtShrFmla': if(!opts.cellFormula) break;
|
||||
// TODO
|
||||
shared_formulae[encode_cell(val[0].s)] = val[1];
|
||||
s[encode_col(C) + rr].f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
|
||||
break;
|
||||
|
||||
case 'BrtBeginSheet': break;
|
||||
case 'BrtWsProp': break; // TODO
|
||||
case 'BrtSheetCalcProp': break; // TODO
|
||||
@ -400,6 +472,10 @@ function parse_ws_bin(data, opts, rels) {
|
||||
default: if(!pass || opts.WTF) throw new Error("Unexpected record " + Record.n);
|
||||
}
|
||||
}, opts);
|
||||
|
||||
delete opts.supbooks;
|
||||
delete opts['!row'];
|
||||
|
||||
if(!s["!ref"] && (refguess.s.r < 2000000 || ref && (ref.e.r > 0 || ref.e.c > 0 || ref.s.r > 0 || ref.s.c > 0))) s["!ref"] = encode_range(ref || refguess);
|
||||
if(opts.sheetRows && s["!ref"]) {
|
||||
var tmpref = safe_decode_range(s["!ref"]);
|
||||
|
@ -38,15 +38,43 @@ function parse_BrtFRTArchID$(data, length) {
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.680 BrtName */
|
||||
function parse_BrtName(data, length, opts) {
|
||||
var end = data.l + length;
|
||||
var flags = data.read_shift(4);
|
||||
var chKey = data.read_shift(1);
|
||||
var itab = data.read_shift(4);
|
||||
var name = parse_XLNameWideString(data);
|
||||
var formula = parse_XLSBNameParsedFormula(data, 0, opts);
|
||||
var comment = parse_XLNullableWideString(data);
|
||||
if(0 /* fProc */) {
|
||||
// unusedstring1: XLNullableWideString
|
||||
// description: XLNullableWideString
|
||||
// helpTopic: XLNullableWideString
|
||||
// unusedstring2: XLNullableWideString
|
||||
}
|
||||
data.l = end;
|
||||
return {Name:name, Ptg:formula, Comment:comment};
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.60 Workbook */
|
||||
function parse_wb_bin(data, opts) {
|
||||
var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
|
||||
var pass = false, z;
|
||||
|
||||
if(!opts) opts = {};
|
||||
opts.biff = 12;
|
||||
|
||||
var Names = {}, NameList = [];
|
||||
|
||||
recordhopper(data, function hopper_wb(val, R) {
|
||||
switch(R.n) {
|
||||
case 'BrtBundleSh': wb.Sheets.push(val); break;
|
||||
|
||||
case 'BrtName':
|
||||
Names[val.Name] = val; NameList.push(val.Name);
|
||||
break;
|
||||
|
||||
case 'BrtBeginBook': break;
|
||||
case 'BrtFileVersion': break;
|
||||
case 'BrtWbProp14': case 'BrtWbProp': break;
|
||||
@ -68,7 +96,6 @@ function parse_wb_bin(data, opts) {
|
||||
case 'BrtSupBookSrc': break;
|
||||
case 'BrtExternSheet': break;
|
||||
case 'BrtEndExternals': break;
|
||||
case 'BrtName': break;
|
||||
case 'BrtCalcProp': break;
|
||||
case 'BrtUserBookView': break;
|
||||
case 'BrtBeginPivotCacheIDs': break;
|
||||
@ -95,10 +122,13 @@ function parse_wb_bin(data, opts) {
|
||||
case 'BrtEndBook': break;
|
||||
default: if(!pass || opts.WTF) throw new Error("Unexpected record " + R.n);
|
||||
}
|
||||
});
|
||||
}, opts);
|
||||
|
||||
parse_wb_defaults(wb);
|
||||
|
||||
Names['!names'] = NameList;
|
||||
wb.Names = Names;
|
||||
|
||||
return wb;
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,9 @@ function parse_wb(data, name/*:string*/, opts)/*:Workbook*/ {
|
||||
return parse_wb_xml((data/*:any*/), opts);
|
||||
}
|
||||
|
||||
function parse_ws(data, name/*:string*/, opts, rels)/*:Worksheet*/ {
|
||||
if(name.substr(name.length-4)===".bin") return parse_ws_bin((data/*:any*/), opts, rels);
|
||||
return parse_ws_xml((data/*:any*/), opts, rels);
|
||||
function parse_ws(data, name/*:string*/, opts, rels, wb)/*:Worksheet*/ {
|
||||
if(name.substr(name.length-4)===".bin") return parse_ws_bin((data/*:any*/), opts, rels, wb);
|
||||
return parse_ws_xml((data/*:any*/), opts, rels, wb);
|
||||
}
|
||||
|
||||
function parse_sty(data, name/*:string*/, opts) {
|
||||
|
@ -82,7 +82,7 @@ function process_style_xlml(styles, stag, opts) {
|
||||
}
|
||||
|
||||
/* TODO: there must exist some form of OSP-blessed spec */
|
||||
function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, o)/*:Workbook*/ {
|
||||
function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o)/*:Workbook*/ {
|
||||
var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
|
||||
var interiors = [];
|
||||
if(sid === undefined && row) sid = row.StyleID;
|
||||
@ -100,7 +100,7 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, o
|
||||
break;
|
||||
case 'String':
|
||||
cell.t = 's'; cell.r = xlml_fixstr(unescapexml(xml));
|
||||
cell.v = xml.indexOf("<") > -1 ? ss : cell.r;
|
||||
cell.v = xml.indexOf("<") > -1 ? unescapexml(ss) : cell.r;
|
||||
break;
|
||||
case 'DateTime':
|
||||
cell.v = (Date.parse(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
|
||||
@ -116,9 +116,24 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, o
|
||||
default: cell.t = 's'; cell.v = xlml_fixstr(ss); break;
|
||||
}
|
||||
safe_format_xlml(cell, nf, o);
|
||||
if(o.cellFormula != null && cell.Formula) {
|
||||
cell.f = rc_to_a1(unescapexml(cell.Formula), base);
|
||||
cell.Formula = undefined;
|
||||
if(o.cellFormula != null) {
|
||||
if(cell.Formula) {
|
||||
var fstr = unescapexml(cell.Formula);
|
||||
/* strictly speaking, the leading = is required but some writers omit */
|
||||
if(fstr.charCodeAt(0) == 61 /* = */) fstr = fstr.substr(1);
|
||||
cell.f = rc_to_a1(fstr, base);
|
||||
cell.Formula = undefined;
|
||||
if(cell.ArrayRange == "RC") cell.F = rc_to_a1("RC:RC", base);
|
||||
else if(cell.ArrayRange) {
|
||||
cell.F = rc_to_a1(cell.ArrayRange, base);
|
||||
arrayf.push([safe_decode_range(cell.F), cell.F]);
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < arrayf.length; ++i)
|
||||
if(base.r >= arrayf[i][0].s.r && base.r <= arrayf[i][0].e.r)
|
||||
if(base.c >= arrayf[i][0].s.c && base.c <= arrayf[i][0].e.c)
|
||||
cell.F = arrayf[i][1];
|
||||
}
|
||||
}
|
||||
if(o.cellStyles) {
|
||||
interiors.forEach(function(x) {
|
||||
@ -157,11 +172,12 @@ function parse_xlml_xml(d, opts) {
|
||||
var Props = {}, Custprops = {}, pidx = 0, cp = {};
|
||||
var comments = [], comment = {};
|
||||
var cstys = [], csty;
|
||||
var arrayf = [];
|
||||
xlmlregex.lastIndex = 0;
|
||||
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
|
||||
case 'Data':
|
||||
if(state[state.length-1][1]) break;
|
||||
if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]=="Comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, opts);
|
||||
if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]=="Comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts);
|
||||
else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; }
|
||||
break;
|
||||
case 'Cell':
|
||||
|
@ -304,7 +304,15 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
default:
|
||||
temp_val = ({v:val.val, ixfe:val.cell.ixfe, t:val.tt}/*:any*/);
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) temp_val.f = "="+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
if(options.cellFormula) {
|
||||
var _f = val.formula;
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(shared_formulae[_fe]) temp_val.f = stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = (out[_fe] || {}).F;
|
||||
} else temp_val.f = stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(val.cell, temp_val, options);
|
||||
last_formula = val;
|
||||
@ -315,7 +323,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
last_formula.val = val;
|
||||
temp_val = ({v:last_formula.val, ixfe:last_formula.cell.ixfe, t:'s'}/*:any*/);
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) temp_val.f = "="+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
if(options.cellFormula) temp_val.f = stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(last_formula.cell, temp_val, options);
|
||||
last_formula = null;
|
||||
@ -323,12 +331,19 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
} break;
|
||||
case 'Array': {
|
||||
array_formulae.push(val);
|
||||
if(options.cellFormula && out[last_cell]) {
|
||||
out[last_cell].f = stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
out[last_cell].F = encode_range(val[0]);
|
||||
}
|
||||
} break;
|
||||
case 'ShrFmla': {
|
||||
if(!cell_valid) break;
|
||||
//if(options.cellFormula) out[last_cell].f = stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
/* TODO: capture range */
|
||||
if(last_formula) shared_formulae[encode_cell(last_formula.cell)]= val[0];
|
||||
if(!options.cellFormula) break;
|
||||
if(last_cell) {
|
||||
/* TODO: capture range */
|
||||
shared_formulae[encode_cell(last_formula.cell)]= val[0];
|
||||
(out[encode_cell(last_formula.cell)]||{}).f = stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
}
|
||||
} break;
|
||||
case 'LabelSst':
|
||||
temp_val=make_cell(sst[val.isst].t, val.ixfe, 's');
|
||||
@ -336,6 +351,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
break;
|
||||
case 'RString':
|
||||
case 'Label': case 'BIFF2STR':
|
||||
temp_val=make_cell(val.val, val.ixfe, 's');
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
@ -609,14 +625,12 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
default: switch(R.n) { /* nested */
|
||||
/* BIFF5 records */
|
||||
case 'ExternCount': break;
|
||||
case 'RString': break;
|
||||
case 'TabIdConf': case 'Radar': case 'RadarArea': case 'DropBar': case 'Intl': case 'CoordList': case 'SerAuxErrBar': break;
|
||||
|
||||
/* BIFF2-4 records */
|
||||
case 'BIFF2FONTCLR': case 'BIFF2FMTCNT': break;
|
||||
case 'BIFF2FONTCLR': case 'BIFF2FMTCNT': case 'BIFF2FONTXTRA': break;
|
||||
case 'BIFF2XF': case 'BIFF3XF': case 'BIFF4XF': break;
|
||||
case 'BIFF4FMTCNT': case 'BIFF2ROW': case 'BIFF2WINDOW2': break;
|
||||
case 'Dimension': break;
|
||||
|
||||
/* Miscellaneous */
|
||||
case 'SCENARIO': case 'DConBin': case 'PicF': case 'DataLabExt':
|
||||
|
@ -33,7 +33,7 @@ var XLSBRecordEnum = {
|
||||
/*::[*/0x0024/*::]*/: { n:"BrtFRTEnd", f:parsenoop },
|
||||
/*::[*/0x0025/*::]*/: { n:"BrtACBegin", f:parsenoop },
|
||||
/*::[*/0x0026/*::]*/: { n:"BrtACEnd", f:parsenoop },
|
||||
/*::[*/0x0027/*::]*/: { n:"BrtName", f:parsenoop },
|
||||
/*::[*/0x0027/*::]*/: { n:"BrtName", f:parse_BrtName },
|
||||
/*::[*/0x0028/*::]*/: { n:"BrtIndexRowBlock", f:parsenoop },
|
||||
/*::[*/0x002A/*::]*/: { n:"BrtIndexBlock", f:parsenoop },
|
||||
/*::[*/0x002B/*::]*/: { n:"BrtFont", f:parse_BrtFont },
|
||||
@ -356,8 +356,8 @@ var XLSBRecordEnum = {
|
||||
/*::[*/0x01A7/*::]*/: { n:"BrtBeginUserShView", f:parsenoop },
|
||||
/*::[*/0x01A8/*::]*/: { n:"BrtEndUserShView", f:parsenoop },
|
||||
/*::[*/0x01A9/*::]*/: { n:"BrtEndUserShViews", f:parsenoop },
|
||||
/*::[*/0x01AA/*::]*/: { n:"BrtArrFmla", f:parsenoop },
|
||||
/*::[*/0x01AB/*::]*/: { n:"BrtShrFmla", f:parsenoop },
|
||||
/*::[*/0x01AA/*::]*/: { n:"BrtArrFmla", f:parse_BrtArrFmla },
|
||||
/*::[*/0x01AB/*::]*/: { n:"BrtShrFmla", f:parse_BrtShrFmla },
|
||||
/*::[*/0x01AC/*::]*/: { n:"BrtTable", f:parsenoop },
|
||||
/*::[*/0x01AD/*::]*/: { n:"BrtBeginExtConnections", f:parsenoop },
|
||||
/*::[*/0x01AE/*::]*/: { n:"BrtEndExtConnections", f:parsenoop },
|
||||
@ -1019,6 +1019,7 @@ var XLSRecordEnum = {
|
||||
/*::[*/0x0203/*::]*/: { n:"Number", f:parse_Number },
|
||||
/*::[*/0x0204/*::]*/: { n:"Label", f:parse_Label },
|
||||
/*::[*/0x0205/*::]*/: { n:"BoolErr", f:parse_BoolErr },
|
||||
/*::[*/0x0206/*::]*/: { n:"Formula", f:parse_Formula },
|
||||
/*::[*/0x0207/*::]*/: { n:"String", f:parse_String },
|
||||
/*::[*/0x0208/*::]*/: { n:'Row', f:parse_Row },
|
||||
/*::[*/0x020b/*::]*/: { n:"Index", f:parse_Index },
|
||||
@ -1028,6 +1029,7 @@ var XLSRecordEnum = {
|
||||
/*::[*/0x023e/*::]*/: { n:"Window2", f:parse_Window2 },
|
||||
/*::[*/0x027e/*::]*/: { n:"RK", f:parse_RK },
|
||||
/*::[*/0x0293/*::]*/: { n:"Style", f:parse_Style },
|
||||
/*::[*/0x0406/*::]*/: { n:"Formula", f:parse_Formula },
|
||||
/*::[*/0x0418/*::]*/: { n:"BigName", f:parse_BigName },
|
||||
/*::[*/0x041e/*::]*/: { n:"Format", f:parse_Format },
|
||||
/*::[*/0x043c/*::]*/: { n:"ContinueBigName", f:parse_ContinueBigName },
|
||||
@ -1184,7 +1186,7 @@ var XLSRecordEnum = {
|
||||
/*::[*/0x1068/*::]*/: { n:"Fbi2", f:parse_Fbi2 },
|
||||
|
||||
/* These are specified in an older version of the spec */
|
||||
/*::[*/0x0000/*::]*/: { n:"Dimension", f:parsenoop },
|
||||
/*::[*/0x0000/*::]*/: { n:"Dimensions", f:parse_Dimensions },
|
||||
/*::[*/0x0002/*::]*/: { n:"BIFF2INT", f:parse_BIFF2INT },
|
||||
/*::[*/0x0005/*::]*/: { n:"BoolErr", f:parse_BoolErr },
|
||||
/*::[*/0x0007/*::]*/: { n:"String", f:parse_BIFF2STRING },
|
||||
@ -1193,6 +1195,7 @@ var XLSRecordEnum = {
|
||||
/*::[*/0x001e/*::]*/: { n:"BIFF2FORMAT", f:parse_BIFF2Format },
|
||||
/*::[*/0x001f/*::]*/: { n:"BIFF2FMTCNT", f:parsenoop }, /* 16-bit cnt of BIFF2FORMAT records */
|
||||
/*::[*/0x0016/*::]*/: { n:"ExternCount", f:parsenoop },
|
||||
/*::[*/0x0021/*::]*/: { n:"Array", f:parse_Array },
|
||||
/*::[*/0x0025/*::]*/: { n:"DefaultRowHeight", f:parse_DefaultRowHeight },
|
||||
/*::[*/0x0032/*::]*/: { n:"BIFF2FONTXTRA", f:parse_BIFF2FONTXTRA },
|
||||
/*::[*/0x003e/*::]*/: { n:"BIFF2WINDOW2", f:parsenoop },
|
||||
@ -1212,7 +1215,7 @@ var XLSRecordEnum = {
|
||||
/*::[*/0x00bc/*::]*/: { n:"ShrFmla", f:parsenoop }, /* Not necessarily same as 0x04bc */
|
||||
/*::[*/0x00c2/*::]*/: { n:"AddMenu", f:parsenoop },
|
||||
/*::[*/0x00c3/*::]*/: { n:"DelMenu", f:parsenoop },
|
||||
/*::[*/0x00d6/*::]*/: { n:"RString", f:parsenoop },
|
||||
/*::[*/0x00d6/*::]*/: { n:"RString", f:parse_RString },
|
||||
/*::[*/0x00df/*::]*/: { n:"UDDesc", f:parsenoop },
|
||||
/*::[*/0x00ea/*::]*/: { n:"TabIdConf", f:parsenoop },
|
||||
/*::[*/0x0162/*::]*/: { n:"XL5Modify", f:parsenoop },
|
||||
@ -1221,7 +1224,6 @@ var XLSRecordEnum = {
|
||||
/*::[*/0x0218/*::]*/: { n:"Lbl", f:parse_Lbl },
|
||||
/*::[*/0x0223/*::]*/: { n:"ExternName", f:parse_ExternName },
|
||||
/*::[*/0x0231/*::]*/: { n:"Font", f:parsenoop },
|
||||
/*::[*/0x0406/*::]*/: { n:"Formula", f:parse_Formula },
|
||||
/*::[*/0x0409/*::]*/: { n:'BOF', f:parse_BOF },
|
||||
/*::[*/0x086d/*::]*/: { n:"FeatInfo", f:parsenoop },
|
||||
/*::[*/0x0873/*::]*/: { n:"FeatInfo11", f:parsenoop },
|
||||
|
@ -6,10 +6,10 @@ function safe_parse_wbrels(wbrels, sheets) {
|
||||
return !wbrels || wbrels.length === 0 ? null : wbrels;
|
||||
}
|
||||
|
||||
function safe_parse_ws(zip, path/*:string*/, relsPath/*:string*/, sheet, sheetRels, sheets, opts) {
|
||||
function safe_parse_ws(zip, path/*:string*/, relsPath/*:string*/, sheet, sheetRels, sheets, opts, wb) {
|
||||
try {
|
||||
sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
|
||||
sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet]);
|
||||
sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet], wb);
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
|
||||
path = path.replace(/sheet0\./,"sheet.");
|
||||
}
|
||||
relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
|
||||
safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts);
|
||||
safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts, wb);
|
||||
}
|
||||
|
||||
if(dir.comments) parse_comments(zip, dir.comments, sheets, sheetRels, opts);
|
||||
|
@ -156,11 +156,11 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
|
||||
}
|
||||
var make_csv = sheet_to_csv;
|
||||
|
||||
function sheet_to_formulae(sheet/*:Worksheet*/) {
|
||||
var cmds, y = "", x, val="";
|
||||
if(sheet == null || sheet["!ref"] == null) return "";
|
||||
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;
|
||||
cmds = new Array((r.e.r-r.s.r+1)*(r.e.c-r.s.c+1));
|
||||
var cmds = new Array((r.e.r-r.s.r+1)*(r.e.c-r.s.c+1));
|
||||
var i = 0;
|
||||
for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C);
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) {
|
||||
@ -170,9 +170,18 @@ function sheet_to_formulae(sheet/*:Worksheet*/) {
|
||||
x = sheet[y];
|
||||
val = "";
|
||||
if(x === undefined) continue;
|
||||
else if(x.F != null) {
|
||||
y = x.F;
|
||||
if(!x.f) continue;
|
||||
val = x.f;
|
||||
if(y.indexOf(":") == -1) y = y + ":" + y;
|
||||
}
|
||||
if(x.f != null) val = x.f;
|
||||
else if(x.t == 'n' && x.v != null) val = "" + x.v;
|
||||
else if(x.t == 'b') val = x.v ? "TRUE" : "FALSE";
|
||||
else if(x.w !== undefined) val = "'" + x.w;
|
||||
else if(x.v === undefined) continue;
|
||||
else if(x.t == 's') val = "'" + x.v;
|
||||
else val = ""+x.v;
|
||||
cmds[i++] = y + "=" + val;
|
||||
}
|
||||
|
52
dist/ods.js
vendored
52
dist/ods.js
vendored
@ -239,6 +239,17 @@ var utf8read = function utf8reada(orig) {
|
||||
}
|
||||
return out;
|
||||
};
|
||||
/* Part 3 TODO: actually parse formulae */
|
||||
function ods_to_csf_formula(f) {
|
||||
if(f.substr(0,3) == "of:") f = f.substr(3);
|
||||
/* 5.2 Basic Expressions */
|
||||
if(f.charCodeAt(0) == 61) {
|
||||
f = f.substr(1);
|
||||
if(f.charCodeAt(0) == 61) f = f.substr(1);
|
||||
}
|
||||
/* Part 3 Section 5.8 References */
|
||||
return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, "");
|
||||
}
|
||||
var parse_content_xml = (function() {
|
||||
|
||||
var number_formats = {
|
||||
@ -266,7 +277,9 @@ var parse_content_xml = (function() {
|
||||
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
|
||||
var number_format_map = {};
|
||||
var merges = [], mrange = {}, mR = 0, mC = 0;
|
||||
var rept = 1;
|
||||
var arrayf = [];
|
||||
var rept = 1, isstub = false;
|
||||
var i = 0;
|
||||
xlmlregex.lastIndex = 0;
|
||||
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
|
||||
|
||||
@ -305,7 +318,21 @@ 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);
|
||||
q = {t:ctag['value-type'], v:null};
|
||||
q = ({t:ctag['value-type'], v:null});
|
||||
if(opts.cellFormula) {
|
||||
if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
|
||||
mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
|
||||
mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
|
||||
mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
|
||||
q.F = get_utils().encode_range(mrange);
|
||||
arrayf.push([mrange, q.F]);
|
||||
}
|
||||
if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula);
|
||||
else for(i = 0; i < arrayf.length; ++i)
|
||||
if(R >= arrayf[i][0].s.r && R <= arrayf[i][0].e.r)
|
||||
if(C >= arrayf[i][0].s.c && C <= arrayf[i][0].e.c)
|
||||
q.F = arrayf[i][1];
|
||||
}
|
||||
if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) {
|
||||
mR = parseInt(ctag['number-rows-spanned'],10) || 0;
|
||||
mC = parseInt(ctag['number-columns-spanned'],10) || 0;
|
||||
@ -331,13 +358,19 @@ var parse_content_xml = (function() {
|
||||
} else throw new Error('Unsupported value type ' + q.t);
|
||||
}
|
||||
} else {
|
||||
if(q.t === 's') q.v = textp || '';
|
||||
if(textp) q.w = textp;
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[get_utils().encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
isstub = false;
|
||||
if(q.t === 's') {
|
||||
q.v = textp || '';
|
||||
isstub = textpidx == 0;
|
||||
}
|
||||
if(textp) q.w = textp;
|
||||
if(!isstub || opts.cellStubs) {
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[get_utils().encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
}
|
||||
} else { C += rept; rept = 0; }
|
||||
q = {};
|
||||
textp = "";
|
||||
}
|
||||
@ -364,6 +397,7 @@ var parse_content_xml = (function() {
|
||||
case 'annotation': // 14.1 <office:annotation>
|
||||
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
|
||||
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]);
|
||||
textp = ""; textpidx = 0;
|
||||
break;
|
||||
|
||||
case 'number-style': // 16.27.2 <number:number-style>
|
||||
@ -616,7 +650,7 @@ var zip = new jszip();
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 2 Section 2.2 Documents */
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
|
2
dist/ods.min.js
vendored
2
dist/ods.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/ods.min.map
vendored
2
dist/ods.min.map
vendored
File diff suppressed because one or more lines are too long
21
dist/xlsx.core.min.js
vendored
21
dist/xlsx.core.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.core.min.map
vendored
2
dist/xlsx.core.min.map
vendored
File diff suppressed because one or more lines are too long
22
dist/xlsx.full.min.js
vendored
22
dist/xlsx.full.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.full.min.map
vendored
2
dist/xlsx.full.min.map
vendored
File diff suppressed because one or more lines are too long
1052
dist/xlsx.js
vendored
1052
dist/xlsx.js
vendored
File diff suppressed because it is too large
Load Diff
20
dist/xlsx.min.js
vendored
20
dist/xlsx.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.min.map
vendored
2
dist/xlsx.min.map
vendored
File diff suppressed because one or more lines are too long
54
ods.flow.js
54
ods.flow.js
@ -241,6 +241,17 @@ var utf8read = function utf8reada(orig) {
|
||||
}
|
||||
return out;
|
||||
};
|
||||
/* Part 3 TODO: actually parse formulae */
|
||||
function ods_to_csf_formula(f/*:string*/)/*:string*/ {
|
||||
if(f.substr(0,3) == "of:") f = f.substr(3);
|
||||
/* 5.2 Basic Expressions */
|
||||
if(f.charCodeAt(0) == 61) {
|
||||
f = f.substr(1);
|
||||
if(f.charCodeAt(0) == 61) f = f.substr(1);
|
||||
}
|
||||
/* Part 3 Section 5.8 References */
|
||||
return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, "");
|
||||
}
|
||||
var parse_content_xml = (function() {
|
||||
|
||||
var number_formats = {
|
||||
@ -262,13 +273,15 @@ var parse_content_xml = (function() {
|
||||
var NFtag = {name:""}, NF = "", pidx = 0;
|
||||
var sheetag/*:: = {name:""}*/;
|
||||
var Sheets = {}, SheetNames/*:Array<string>*/ = [], ws = {};
|
||||
var Rn, q/*:: = {t:"", v:null, z:null, w:""}*/;
|
||||
var Rn, q/*:: = ({t:"", v:null, z:null, w:""}:any)*/;
|
||||
var ctag = {value:""};
|
||||
var textp = "", textpidx = 0, textptag/*:: = {}*/;
|
||||
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
|
||||
var number_format_map = {};
|
||||
var merges = [], mrange = {}, mR = 0, mC = 0;
|
||||
var rept = 1;
|
||||
var arrayf = [];
|
||||
var rept = 1, isstub = false;
|
||||
var i = 0;
|
||||
xlmlregex.lastIndex = 0;
|
||||
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
|
||||
|
||||
@ -307,7 +320,21 @@ 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);
|
||||
q = {t:ctag['value-type'], v:null/*:: , z:null, w:""*/};
|
||||
q = ({t:ctag['value-type'], v:null/*:: , z:null, w:""*/}/*:any*/);
|
||||
if(opts.cellFormula) {
|
||||
if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
|
||||
mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
|
||||
mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
|
||||
mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
|
||||
q.F = get_utils().encode_range(mrange);
|
||||
arrayf.push([mrange, q.F]);
|
||||
}
|
||||
if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula);
|
||||
else for(i = 0; i < arrayf.length; ++i)
|
||||
if(R >= arrayf[i][0].s.r && R <= arrayf[i][0].e.r)
|
||||
if(C >= arrayf[i][0].s.c && C <= arrayf[i][0].e.c)
|
||||
q.F = arrayf[i][1];
|
||||
}
|
||||
if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) {
|
||||
mR = parseInt(ctag['number-rows-spanned'],10) || 0;
|
||||
mC = parseInt(ctag['number-columns-spanned'],10) || 0;
|
||||
@ -333,13 +360,19 @@ var parse_content_xml = (function() {
|
||||
} else throw new Error('Unsupported value type ' + q.t);
|
||||
}
|
||||
} else {
|
||||
if(q.t === 's') q.v = textp || '';
|
||||
if(textp) q.w = textp;
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[get_utils().encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
isstub = false;
|
||||
if(q.t === 's') {
|
||||
q.v = textp || '';
|
||||
isstub = textpidx == 0;
|
||||
}
|
||||
if(textp) q.w = textp;
|
||||
if(!isstub || opts.cellStubs) {
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[get_utils().encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
}
|
||||
} else { C += rept; rept = 0; }
|
||||
q = {/*:: t:"", v:null, z:null, w:""*/};
|
||||
textp = "";
|
||||
}
|
||||
@ -366,6 +399,7 @@ var parse_content_xml = (function() {
|
||||
case 'annotation': // 14.1 <office:annotation>
|
||||
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
|
||||
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]);
|
||||
textp = ""; textpidx = 0;
|
||||
break;
|
||||
|
||||
case 'number-style': // 16.27.2 <number:number-style>
|
||||
@ -619,7 +653,7 @@ function write_ods(wb/*:any*/, opts/*:any*/) {
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 2 Section 2.2 Documents */
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
|
52
ods.js
52
ods.js
@ -239,6 +239,17 @@ var utf8read = function utf8reada(orig) {
|
||||
}
|
||||
return out;
|
||||
};
|
||||
/* Part 3 TODO: actually parse formulae */
|
||||
function ods_to_csf_formula(f) {
|
||||
if(f.substr(0,3) == "of:") f = f.substr(3);
|
||||
/* 5.2 Basic Expressions */
|
||||
if(f.charCodeAt(0) == 61) {
|
||||
f = f.substr(1);
|
||||
if(f.charCodeAt(0) == 61) f = f.substr(1);
|
||||
}
|
||||
/* Part 3 Section 5.8 References */
|
||||
return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, "");
|
||||
}
|
||||
var parse_content_xml = (function() {
|
||||
|
||||
var number_formats = {
|
||||
@ -266,7 +277,9 @@ var parse_content_xml = (function() {
|
||||
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
|
||||
var number_format_map = {};
|
||||
var merges = [], mrange = {}, mR = 0, mC = 0;
|
||||
var rept = 1;
|
||||
var arrayf = [];
|
||||
var rept = 1, isstub = false;
|
||||
var i = 0;
|
||||
xlmlregex.lastIndex = 0;
|
||||
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
|
||||
|
||||
@ -305,7 +318,21 @@ 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);
|
||||
q = {t:ctag['value-type'], v:null};
|
||||
q = ({t:ctag['value-type'], v:null});
|
||||
if(opts.cellFormula) {
|
||||
if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
|
||||
mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
|
||||
mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
|
||||
mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
|
||||
q.F = get_utils().encode_range(mrange);
|
||||
arrayf.push([mrange, q.F]);
|
||||
}
|
||||
if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula);
|
||||
else for(i = 0; i < arrayf.length; ++i)
|
||||
if(R >= arrayf[i][0].s.r && R <= arrayf[i][0].e.r)
|
||||
if(C >= arrayf[i][0].s.c && C <= arrayf[i][0].e.c)
|
||||
q.F = arrayf[i][1];
|
||||
}
|
||||
if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) {
|
||||
mR = parseInt(ctag['number-rows-spanned'],10) || 0;
|
||||
mC = parseInt(ctag['number-columns-spanned'],10) || 0;
|
||||
@ -331,13 +358,19 @@ var parse_content_xml = (function() {
|
||||
} else throw new Error('Unsupported value type ' + q.t);
|
||||
}
|
||||
} else {
|
||||
if(q.t === 's') q.v = textp || '';
|
||||
if(textp) q.w = textp;
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[get_utils().encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
isstub = false;
|
||||
if(q.t === 's') {
|
||||
q.v = textp || '';
|
||||
isstub = textpidx == 0;
|
||||
}
|
||||
if(textp) q.w = textp;
|
||||
if(!isstub || opts.cellStubs) {
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[get_utils().encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
}
|
||||
} else { C += rept; rept = 0; }
|
||||
q = {};
|
||||
textp = "";
|
||||
}
|
||||
@ -364,6 +397,7 @@ var parse_content_xml = (function() {
|
||||
case 'annotation': // 14.1 <office:annotation>
|
||||
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
|
||||
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]);
|
||||
textp = ""; textpidx = 0;
|
||||
break;
|
||||
|
||||
case 'number-style': // 16.27.2 <number:number-style>
|
||||
@ -616,7 +650,7 @@ var zip = new jszip();
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 2 Section 2.2 Documents */
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
|
11
odsbits/50_formula.js
Normal file
11
odsbits/50_formula.js
Normal file
@ -0,0 +1,11 @@
|
||||
/* Part 3 TODO: actually parse formulae */
|
||||
function ods_to_csf_formula(f/*:string*/)/*:string*/ {
|
||||
if(f.substr(0,3) == "of:") f = f.substr(3);
|
||||
/* 5.2 Basic Expressions */
|
||||
if(f.charCodeAt(0) == 61) {
|
||||
f = f.substr(1);
|
||||
if(f.charCodeAt(0) == 61) f = f.substr(1);
|
||||
}
|
||||
/* Part 3 Section 5.8 References */
|
||||
return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, "");
|
||||
}
|
@ -19,13 +19,15 @@ var parse_content_xml = (function() {
|
||||
var NFtag = {name:""}, NF = "", pidx = 0;
|
||||
var sheetag/*:: = {name:""}*/;
|
||||
var Sheets = {}, SheetNames/*:Array<string>*/ = [], ws = {};
|
||||
var Rn, q/*:: = {t:"", v:null, z:null, w:""}*/;
|
||||
var Rn, q/*:: = ({t:"", v:null, z:null, w:""}:any)*/;
|
||||
var ctag = {value:""};
|
||||
var textp = "", textpidx = 0, textptag/*:: = {}*/;
|
||||
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
|
||||
var number_format_map = {};
|
||||
var merges = [], mrange = {}, mR = 0, mC = 0;
|
||||
var rept = 1;
|
||||
var arrayf = [];
|
||||
var rept = 1, isstub = false;
|
||||
var i = 0;
|
||||
xlmlregex.lastIndex = 0;
|
||||
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
|
||||
|
||||
@ -64,7 +66,21 @@ 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);
|
||||
q = {t:ctag['value-type'], v:null/*:: , z:null, w:""*/};
|
||||
q = ({t:ctag['value-type'], v:null/*:: , z:null, w:""*/}/*:any*/);
|
||||
if(opts.cellFormula) {
|
||||
if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
|
||||
mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
|
||||
mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
|
||||
mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
|
||||
q.F = get_utils().encode_range(mrange);
|
||||
arrayf.push([mrange, q.F]);
|
||||
}
|
||||
if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula);
|
||||
else for(i = 0; i < arrayf.length; ++i)
|
||||
if(R >= arrayf[i][0].s.r && R <= arrayf[i][0].e.r)
|
||||
if(C >= arrayf[i][0].s.c && C <= arrayf[i][0].e.c)
|
||||
q.F = arrayf[i][1];
|
||||
}
|
||||
if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) {
|
||||
mR = parseInt(ctag['number-rows-spanned'],10) || 0;
|
||||
mC = parseInt(ctag['number-columns-spanned'],10) || 0;
|
||||
@ -90,13 +106,19 @@ var parse_content_xml = (function() {
|
||||
} else throw new Error('Unsupported value type ' + q.t);
|
||||
}
|
||||
} else {
|
||||
if(q.t === 's') q.v = textp || '';
|
||||
if(textp) q.w = textp;
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[get_utils().encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
isstub = false;
|
||||
if(q.t === 's') {
|
||||
q.v = textp || '';
|
||||
isstub = textpidx == 0;
|
||||
}
|
||||
if(textp) q.w = textp;
|
||||
if(!isstub || opts.cellStubs) {
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[get_utils().encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
}
|
||||
} else { C += rept; rept = 0; }
|
||||
q = {/*:: t:"", v:null, z:null, w:""*/};
|
||||
textp = "";
|
||||
}
|
||||
@ -123,6 +145,7 @@ var parse_content_xml = (function() {
|
||||
case 'annotation': // 14.1 <office:annotation>
|
||||
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
|
||||
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]);
|
||||
textp = ""; textpidx = 0;
|
||||
break;
|
||||
|
||||
case 'number-style': // 16.27.2 <number:number-style>
|
||||
|
@ -10,7 +10,7 @@ function write_ods(wb/*:any*/, opts/*:any*/) {
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 2 Section 2.2 Documents */
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xlsx",
|
||||
"version": "0.8.3",
|
||||
"version": "0.8.4",
|
||||
"author": "sheetjs",
|
||||
"description": "Excel (XLSB/XLSX/XLSM/XLS/XML) and ODS spreadsheet parser and writer",
|
||||
"keywords": [ "excel", "xls", "xlsx", "xlsb", "xlsm", "ods", "office", "spreadsheet" ],
|
||||
|
1058
xlsx.flow.js
1058
xlsx.flow.js
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user