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