forked from sheetjs/sheetjs
version bump 0.7.4: I/O improvements
- basic style + theme parsing, option .cellStyles (h/t @eladxxx) - more XLSB writing stubs - correct resolution of .xml/.bin files - sheet_to_json improvements from js-xls o opts.header = 1 for array of arrays o opts.header = 'A' for spreadsheet column labels o custom opts.header array for custom labels o opts.range = n starts from row n o opts.range = range restricts writer to work within the specified range - Makefile adapted to work with cygwin on windows
This commit is contained in:
parent
c91e94dbbb
commit
a3d9c4d9ac
4
Makefile
4
Makefile
@ -1,12 +1,12 @@
|
||||
LIB=xlsx
|
||||
DEPS=$(wildcard bits/*.js)
|
||||
DEPS=$(sort $(wildcard bits/*.js))
|
||||
TARGET=$(LIB).js
|
||||
FMT=xlsx xlsm xlsb misc full
|
||||
REQS=jszip.js
|
||||
ADDONS=dist/cpexcel.js
|
||||
|
||||
$(TARGET): $(DEPS)
|
||||
cat $^ > $@
|
||||
cat $^ | tr -d '\15\32' > $@
|
||||
|
||||
bits/01_version.js: package.json
|
||||
echo "XLSX.version = '"`grep version package.json | awk '{gsub(/[^0-9a-z\.-]/,"",$$2); print $$2}'`"';" > $@
|
||||
|
@ -11,7 +11,7 @@ program
|
||||
.option('-s, --sheet <sheet>', 'print specified sheet (default first sheet)')
|
||||
.option('-l, --list-sheets', 'list sheet names and exit')
|
||||
.option('-o, --output <file>', 'output to specified file')
|
||||
/*.option('-B, --xlsb', 'emit XLSB to <sheetname> or <file>.xlsb') */
|
||||
.option('-B, --xlsb', 'emit XLSB to <sheetname> or <file>.xlsb')
|
||||
.option('-M, --xlsm', 'emit XLSM to <sheetname> or <file>.xlsm')
|
||||
.option('-X, --xlsx', 'emit XLSX to <sheetname> or <file>.xlsx')
|
||||
.option('-S, --formulae', 'print formulae')
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.7.3';
|
||||
XLSX.version = '0.7.4';
|
||||
|
@ -6,6 +6,7 @@ function evert(obj, arr) {
|
||||
var o = {};
|
||||
keys(obj).forEach(function(k) {
|
||||
if(!obj.hasOwnProperty(k)) return;
|
||||
if(arr && typeof arr === "string") o[obj[k][arr]] = k;
|
||||
if(!arr) o[obj[k]] = k;
|
||||
else (o[obj[k]]=o[obj[k]]||[]).push(k);
|
||||
});
|
||||
|
@ -34,7 +34,7 @@ function unescapexml(text){
|
||||
function escapexml(text){
|
||||
var s = text + '';
|
||||
rencstr.forEach(function(y){s=s.replace(new RegExp(y,'g'), rencoding[y]);});
|
||||
s = s.replace(/[\u0000-\u0007]/g,function(s) { return "_x" + ("0000"+_ord(s).toString(16)).substr(-4) + "_";}); /* TODO: verify range */
|
||||
s = s.replace(/[\u0000-\u0008\u000b-\u001f]/g,function(s) { return "_x" + ("0000"+_ord(s).toString(16)).substr(-4) + "_";});
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -83,8 +83,7 @@ function parseVector(data) {
|
||||
|
||||
function writetag(f,g) {return '<' + f + (g.match(/(^\s|\s$|\n)/)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>';}
|
||||
|
||||
/*jshint -W041 */
|
||||
function writextag(f,g,h) { return '<' + f + (h != null ? keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join("") : "") + (g == null ? "/" : (g.match(/(^\s|\s$|\n)/)?' xml:space="preserve"' : "") + '>' + g + '</' + f) + '>';}
|
||||
function writextag(f,g,h) { return '<' + f + (h !== null && h !== undefined ? keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join("") : "") + (g === null || g === undefined ? "/" : (g.match(/(^\s|\s$|\n)/)?' xml:space="preserve"' : "") + '>' + g + '</' + f) + '>';}
|
||||
|
||||
function write_w3cdtf(d, t) { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } }
|
||||
|
||||
|
@ -16,16 +16,15 @@ function readIEEE754(buf, idx, isLE, nl, ml) {
|
||||
return (s ? -1 : 1) * m * Math.pow(2, e - ml);
|
||||
}
|
||||
|
||||
var __toBuffer;
|
||||
var __toBuffer, ___toBuffer;
|
||||
__toBuffer = ___toBuffer = function(bufs) {
|
||||
var x = [];
|
||||
for(var i = 0; i != bufs[0].length; ++i) { x = x.concat(bufs[0][i]); }
|
||||
return x;
|
||||
};
|
||||
if(typeof Buffer !== "undefined") {
|
||||
Buffer.prototype.hexlify= function() { return this.toString('hex'); };
|
||||
__toBuffer = function(bufs) { return Buffer.concat(bufs[0]); };
|
||||
} else {
|
||||
__toBuffer = function(bufs) {
|
||||
var x = [];
|
||||
for(var i = 0; i != bufs[0].length; ++i) { x = x.concat(bufs[0][i]); }
|
||||
return x;
|
||||
};
|
||||
__toBuffer = function(bufs) { try { return Buffer.concat(bufs[0]); } catch(e) { return ___toBuffer(bufs);} };
|
||||
}
|
||||
|
||||
var __readUInt8 = function(b, idx) { return b.readUInt8 ? b.readUInt8(idx) : b[idx]; };
|
||||
@ -35,9 +34,10 @@ var __readUInt32LE = function(b, idx) { return b.readUInt32LE ? b.readUInt32LE(i
|
||||
var __readInt32LE = function(b, idx) { if(b.readInt32LE) return b.readInt32LE(idx); var u = __readUInt32LE(b,idx); if(!(u & 0x80000000)) return u; return (0xffffffff - u + 1) * -1; };
|
||||
var __readDoubleLE = function(b, idx) { return b.readDoubleLE ? b.readDoubleLE(idx) : readIEEE754(b, idx||0);};
|
||||
|
||||
var __hexlify = function(b,l) { if(b.hexlify) return b.hexlify((b.l||0), (b.l||0)+l); return b.slice(b.l||0,(b.l||0)+16).map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); };
|
||||
|
||||
function ReadShift(size, t) {
|
||||
var o = "", oo = [], w, vv, i, loc; t = t || 'u';
|
||||
var o="", oo=[], w, vv, i, loc; t = t || 'u';
|
||||
if(size === 'ieee754') { size = 8; t = 'f'; }
|
||||
switch(size) {
|
||||
case 1: o = __readUInt8(this, this.l); break;
|
||||
@ -45,28 +45,56 @@ function ReadShift(size, t) {
|
||||
case 4: o = __readUInt32LE(this, this.l); break;
|
||||
case 8: if(t === 'f') { o = __readDoubleLE(this, this.l); break; }
|
||||
/* falls through */
|
||||
case 16: o = this.toString('hex', this.l,this.l+size); break;
|
||||
case 16: o = __hexlify(this, 16); break;
|
||||
|
||||
case 'dbcs': size = 2*t; loc = this.l;
|
||||
for(i = 0; i != t; ++i) {
|
||||
oo.push(_getchar(__readUInt16LE(this, loc)));
|
||||
loc+=2;
|
||||
} o = oo.join(""); break;
|
||||
|
||||
case 'sbcs': size = t; o = ""; loc = this.l;
|
||||
for(i = 0; i != t; ++i) {
|
||||
o += _getchar(__readUInt8(this, loc));
|
||||
loc+=1;
|
||||
} break;
|
||||
}
|
||||
this.l+=size; return o;
|
||||
}
|
||||
|
||||
function prep_blob(blob, pos) {
|
||||
blob.read_shift = ReadShift.bind(blob);
|
||||
function WriteShift(t, val, f) {
|
||||
var size, i;
|
||||
if(t === 'ieee754') { f = 'f'; t = 8; }
|
||||
switch(t) {
|
||||
case 1: size = 1; this.writeUInt8(val, this.l); break;
|
||||
case 4: size = 4; this.writeUInt32LE(val, this.l); break;
|
||||
case 8: size = 8; if(f === 'f') { this.writeDoubleLE(val, this.l); break; }
|
||||
/* falls through */
|
||||
case 16: break;
|
||||
case -4: size = 4; this.writeInt32LE(val, this.l); break;
|
||||
case 'dbcs':
|
||||
for(i = 0; i != val.length; ++i) this.writeUInt16LE(val.charCodeAt(i), this.l + 2 * i);
|
||||
size = 2 * val.length;
|
||||
break;
|
||||
}
|
||||
this.l += size; return this;
|
||||
}
|
||||
|
||||
function prep_blob(blob, pos, w) {
|
||||
blob.l = pos || 0;
|
||||
var read = ReadShift.bind(blob);
|
||||
return [read];
|
||||
if(w) {
|
||||
var write = WriteShift.bind(blob);
|
||||
blob.write_shift = write;
|
||||
return [write];
|
||||
} else {
|
||||
var read = ReadShift.bind(blob);
|
||||
blob.read_shift = read;
|
||||
return [read];
|
||||
}
|
||||
}
|
||||
|
||||
function parsenoop(blob, length) { blob.l += length; }
|
||||
|
||||
function writenoop(blob, length) { blob.l += length; }
|
||||
|
||||
var new_buf = function(sz) {
|
||||
var o = typeof Buffer !== 'undefined' ? new Buffer(sz) : new Array(sz);
|
||||
prep_blob(o, 0, true);
|
||||
return o;
|
||||
};
|
||||
|
||||
var is_buf = function(a) { return (typeof Buffer !== 'undefined' && a instanceof Buffer) || Array.isArray(a); };
|
||||
|
@ -15,6 +15,52 @@ var recordhopper = function(data, cb, opts) {
|
||||
};
|
||||
|
||||
/* control buffer usage for fixed-length buffers */
|
||||
var blobhopper = function() {
|
||||
var bufs = [];
|
||||
var buf_array = function() {
|
||||
var bufs = [], blksz = 2048;
|
||||
var newblk = function(sz) {
|
||||
var o = new_buf(sz || blksz);
|
||||
prep_blob(o, 0, true);
|
||||
return o;
|
||||
};
|
||||
|
||||
var curbuf = newblk();
|
||||
|
||||
var endbuf = function() {
|
||||
curbuf.length = curbuf.l;
|
||||
if(curbuf.length > 0) bufs.push(curbuf);
|
||||
curbuf = null;
|
||||
};
|
||||
|
||||
var next = function(sz) {
|
||||
if(sz < curbuf.length - curbuf.l) return curbuf;
|
||||
endbuf();
|
||||
return (curbuf = newblk(Math.max(sz+1, blksz)));
|
||||
};
|
||||
|
||||
var end = function() {
|
||||
endbuf();
|
||||
return __toBuffer([bufs]);
|
||||
};
|
||||
|
||||
var push = function(buf) { endbuf(); curbuf = buf; next(); };
|
||||
|
||||
return { next:next, push:push, end:end, _bufs:bufs };
|
||||
};
|
||||
|
||||
var write_record = function(ba, type, payload, length) {
|
||||
var t = evert_RE[type], l;
|
||||
if(!length) length = RecordEnum[t].p || (payload||[]).length || 0;
|
||||
l = 1 + (t >= 0x80 ? 1 : 0) + 1 + length;
|
||||
if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l;
|
||||
var o = ba.next(l);
|
||||
if(t <= 0x7F) o.write_shift(1, t);
|
||||
else {
|
||||
o.write_shift(1, (t & 0x7F) + 0x80);
|
||||
o.write_shift(1, (t >> 7));
|
||||
}
|
||||
for(var i = 0; i != 4; ++i) {
|
||||
if(length >= 0x80) { o.write_shift(1, (length & 0x7F)+0x80); length >>= 7; }
|
||||
else { o.write_shift(1, length); break; }
|
||||
}
|
||||
if(length > 0 && is_buf(payload)) ba.push(payload);
|
||||
};
|
||||
|
@ -41,8 +41,34 @@ function parse_Cell(data) {
|
||||
/* [MS-XLSB] 2.5.21 */
|
||||
var parse_CodeName = function(data, length) { return parse_XLWideString(data, length); };
|
||||
|
||||
/* [MS-XLSB] 2.5.166 */
|
||||
var parse_XLNullableWideString = function(data) {
|
||||
var cchCharacters = data.read_shift(4);
|
||||
return cchCharacters === 0 || cchCharacters === 0xFFFFFFFF ? "" : data.read_shift('dbcs', cchCharacters);
|
||||
};
|
||||
var write_XLNullableWideString = function(data, o) {
|
||||
if(!o) o = new_buf(127);
|
||||
o.write_shift(4, data.length || 0xFFFFFFFF);
|
||||
if(data.length > 0) o.write_shift('dbcs', data);
|
||||
return o;
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.5.168 */
|
||||
var parse_XLWideString = function(data) {
|
||||
var cchCharacters = data.read_shift(4);
|
||||
return cchCharacters === 0 ? "" : data.read_shift('dbcs', cchCharacters);
|
||||
};
|
||||
var write_XLWideString = function(data, o) {
|
||||
if(!o) o = new_buf(127);
|
||||
o.write_shift(4, data.length);
|
||||
if(data.length > 0) o.write_shift('dbcs', data);
|
||||
return o;
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.5.114 */
|
||||
var parse_RelID = function(data, length) { return parse_XLNullableWideString(data, length); };
|
||||
var parse_RelID = parse_XLNullableWideString;
|
||||
var write_RelID = write_XLNullableWideString;
|
||||
|
||||
|
||||
/* [MS-XLSB] 2.5.122 */
|
||||
function parse_RkNumber(data) {
|
||||
@ -64,20 +90,18 @@ var parse_UncheckedRfX = function(data) {
|
||||
return cell;
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.5.166 */
|
||||
var parse_XLNullableWideString = function(data) {
|
||||
var cchCharacters = data.read_shift(4);
|
||||
return cchCharacters === 0 || cchCharacters === 0xFFFFFFFF ? "" : data.read_shift('dbcs', cchCharacters);
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.5.168 */
|
||||
var parse_XLWideString = function(data) {
|
||||
var cchCharacters = data.read_shift(4);
|
||||
return cchCharacters === 0 ? "" : data.read_shift('dbcs', cchCharacters);
|
||||
var write_UncheckedRfX = function(r, o) {
|
||||
if(!o) o = new_buf(16);
|
||||
o.write_shift(4, r.s.r);
|
||||
o.write_shift(4, r.e.r);
|
||||
o.write_shift(4, r.s.c);
|
||||
o.write_shift(4, r.e.c);
|
||||
return o;
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.5.171 */
|
||||
function parse_Xnum(data, length) { return data.read_shift('ieee754'); }
|
||||
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift('ieee754', data); }
|
||||
|
||||
/* [MS-XLSB] 2.5.198.2 */
|
||||
var BErr = {
|
||||
@ -108,7 +132,7 @@ function parse_BrtColor(data, length) {
|
||||
out.bAlpha = read(1);
|
||||
}
|
||||
|
||||
/* [MS-XLSB 2.5.52 */
|
||||
/* [MS-XLSB] 2.5.52 */
|
||||
function parse_FontFlags(data, length) {
|
||||
var d = data.read_shift(1);
|
||||
data.l++;
|
@ -208,6 +208,7 @@ var CTYPE_XML_ROOT = writextag('Types', null, {
|
||||
|
||||
var CTYPE_DEFAULTS = [
|
||||
['xml', 'application/xml'],
|
||||
['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
|
||||
['rels', type2ct.rels[0]]
|
||||
].map(function(x) {
|
||||
return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
|
||||
|
@ -15,7 +15,7 @@ function parse_fills(t, opts) {
|
||||
case '<patternFill':
|
||||
if(y.patternType) fill.patternType = y.patternType;
|
||||
break;
|
||||
case '<patternFill/>': break;
|
||||
case '<patternFill/>': case '</patternFill>': break;
|
||||
|
||||
/* 18.8.3 bgColor CT_Color */
|
||||
case '<bgColor':
|
||||
@ -23,7 +23,7 @@ function parse_fills(t, opts) {
|
||||
if(y.indexed) fill.bgColor.indexed = parseInt(y.indexed);
|
||||
if(y.theme) fill.bgColor.theme = parseInt(y.theme);
|
||||
if(y.tint) fill.bgColor.tint = Number(y.tint);
|
||||
/* Excel uses 8 character RGB strings? */
|
||||
/* Excel uses ARGB strings */
|
||||
if(y.rgb) fill.bgColor.rgb = y.rgb.substring(y.rgb.length - 6);
|
||||
break;
|
||||
case '</bgColor>': break;
|
||||
@ -33,7 +33,7 @@ function parse_fills(t, opts) {
|
||||
if(!fill.fgColor) fill.fgColor = {};
|
||||
if(y.theme) fill.fgColor.theme = parseInt(y.theme);
|
||||
if(y.tint) fill.fgColor.tint = Number(y.tint);
|
||||
/* Excel uses 8 character RGB strings? */
|
||||
/* Excel uses ARGB strings */
|
||||
if(y.rgb) fill.fgColor.rgb = y.rgb.substring(y.rgb.length - 6);
|
||||
break;
|
||||
case '</fgColor>': break;
|
||||
@ -149,8 +149,8 @@ function write_sty_xml(wb, opts) {
|
||||
o.push(XML_HEADER);
|
||||
o.push(STYLES_XML_ROOT);
|
||||
if((w = write_numFmts(wb.SSF))) o.push(w);
|
||||
o.push('<fonts count="1"><font><sz val="12"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font></fonts>');
|
||||
o.push('<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
|
||||
o.push('<fonts count="1"><font><sz val="12"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font></fonts>');
|
||||
o.push('<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
|
||||
o.push('<borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>');
|
||||
o.push('<cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>');
|
||||
if((w = write_cellXfs(opts.cellXfs))) o.push(w);
|
||||
|
@ -64,8 +64,6 @@ function parse_sty_bin(data, opts) {
|
||||
}
|
||||
break; /* TODO */
|
||||
case 'BrtStyle': break; /* TODO */
|
||||
case 'BrtRowHdr': break; /* TODO */
|
||||
case 'BrtCellMeta': break; /* ?? */
|
||||
case 'BrtDXF': break; /* TODO */
|
||||
case 'BrtMRUColor': break; /* TODO */
|
||||
case 'BrtIndexedColor': break; /* TODO */
|
||||
@ -115,3 +113,5 @@ function parse_sty_bin(data, opts) {
|
||||
});
|
||||
return styles;
|
||||
}
|
||||
|
||||
function write_sty_bin(data, opts) { }
|
||||
|
@ -113,7 +113,7 @@ function parse_clrScheme(t, opts) {
|
||||
t[0].match(/<[^>]*>/g).forEach(function(x) {
|
||||
var y = parsexmltag(x);
|
||||
switch(y[0]) {
|
||||
case '<a:clrScheme': case '<<a:clrScheme>': case '</<a:clrScheme>': break;
|
||||
case '<a:clrScheme': case '</a:clrScheme>': break;
|
||||
|
||||
/* 20.1.2.3.32 srgbClr CT_SRgbColor */
|
||||
case '<a:srgbClr': color.rgb = y.val; break;
|
||||
|
@ -15,3 +15,4 @@ function parse_cc_xml(data, opts) {
|
||||
return d;
|
||||
}
|
||||
|
||||
function write_cc_xml(data, opts) { }
|
||||
|
@ -26,3 +26,5 @@ function parse_cc_bin(data, opts) {
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
function write_cc_bin(data, opts) { }
|
||||
|
@ -23,3 +23,5 @@ function parse_comments_xml(data, opts) {
|
||||
});
|
||||
return commentList;
|
||||
}
|
||||
|
||||
function write_comments_xml(data, opts) { }
|
||||
|
@ -42,3 +42,5 @@ function parse_comments_bin(data, opts) {
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
function write_comments_bin(data, opts) { }
|
||||
|
@ -9,6 +9,7 @@ var parse_BrtRowHdr = function(data, length) {
|
||||
|
||||
/* [MS-XLSB] 2.4.812 BrtWsDim */
|
||||
var parse_BrtWsDim = parse_UncheckedRfX;
|
||||
var write_BrtWsDim = write_UncheckedRfX;
|
||||
|
||||
/* [MS-XLSB] 2.4.815 BrtWsProp */
|
||||
var parse_BrtWsProp = function(data, length) {
|
||||
@ -334,4 +335,61 @@ var parse_ws_bin = function(data, opts, rels) {
|
||||
return s;
|
||||
};
|
||||
|
||||
var write_ws_bin = function(wb, opts, rels) {};
|
||||
function write_CELLTABLE(ba, ws, idx, opts, wb) {
|
||||
var r = decode_range(ws['!ref'] || "A1");
|
||||
write_record(ba, 'BrtBeginSheetData');
|
||||
for(var i = r.s.r; i <= r.e.r; ++i) {
|
||||
/* [ACCELLTABLE] */
|
||||
/* BrtRowHdr */
|
||||
|
||||
/* *16384CELL */
|
||||
}
|
||||
write_record(ba, 'BrtEndSheetData');
|
||||
}
|
||||
|
||||
var write_ws_bin = function(idx, opts, wb) {
|
||||
var ba = buf_array();
|
||||
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
|
||||
var r = decode_range(ws['!ref'] || "A1");
|
||||
write_record(ba, "BrtBeginSheet");
|
||||
/* [BrtWsProp] */
|
||||
write_record(ba, "BrtWsDim", write_BrtWsDim(r));
|
||||
/* [WSVIEWS2] */
|
||||
/* [WSFMTINFO] */
|
||||
/* *COLINFOS */
|
||||
write_CELLTABLE(ba, ws, idx, opts, wb);
|
||||
/* [BrtSheetCalcProp] */
|
||||
/* [[BrtSheetProtectionIso] BrtSheetProtection] */
|
||||
/* *([BrtRangeProtectionIso] BrtRangeProtection) */
|
||||
/* [SCENMAN] */
|
||||
/* [AUTOFILTER] */
|
||||
/* [SORTSTATE] */
|
||||
/* [DCON] */
|
||||
/* [USERSHVIEWS] */
|
||||
/* [MERGECELLS] */
|
||||
/* [BrtPhoneticInfo] */
|
||||
/* *CONDITIONALFORMATTING */
|
||||
/* [DVALS] */
|
||||
/* *BrtHLink */
|
||||
/* [BrtPrintOptions] */
|
||||
/* [BrtMargins] */
|
||||
/* [BrtPageSetup] */
|
||||
/* [HEADERFOOTER] */
|
||||
/* [RWBRK] */
|
||||
/* [COLBRK] */
|
||||
/* *BrtBigName */
|
||||
/* [CELLWATCHES] */
|
||||
/* [IGNOREECS] */
|
||||
/* [SMARTTAGS] */
|
||||
/* [BrtDrawing] */
|
||||
/* [BrtLegacyDrawing] */
|
||||
/* [BrtLegacyDrawingHF] */
|
||||
/* [BrtBkHim] */
|
||||
/* [OLEOBJECTS] */
|
||||
/* [ACTIVEXCONTROLS] */
|
||||
/* [WEBPUBITEMS] */
|
||||
/* [LISTPARTS] */
|
||||
/* FRTWORKSHEET */
|
||||
write_record(ba, "BrtEndSheet");
|
||||
return ba.end();
|
||||
};
|
||||
|
107
bits/78_wbbin.js
107
bits/78_wbbin.js
@ -7,6 +7,36 @@ var parse_BrtBundleSh = function(data, length) {
|
||||
z.name = parse_XLWideString(data);
|
||||
return z;
|
||||
};
|
||||
var write_BrtBundleSh = function(data, o) {
|
||||
if(!o) o = new_buf(127);
|
||||
o.write_shift(4, data.hsState);
|
||||
o.write_shift(4, data.iTabID);
|
||||
write_RelID(data.strRelID, o);
|
||||
write_XLWideString(data.name, o);
|
||||
return o;
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.4.807 BrtWbProp */
|
||||
var parse_BrtWbProp = function(data, length) {
|
||||
data.read_shift(4);
|
||||
var dwThemeVersion = data.read_shift(4);
|
||||
var strName = (length > 8) ? parse_XLWideString(data) : "";
|
||||
return [dwThemeVersion, strName];
|
||||
};
|
||||
var write_BrtWbProp = function(data, o) {
|
||||
if(!o) o = new_buf(8);
|
||||
o.write_shift(4, 0);
|
||||
o.write_shift(4, 0);
|
||||
return o;
|
||||
};
|
||||
|
||||
var parse_BrtFRTArchID$ = function(data, length) {
|
||||
var o = {};
|
||||
data.read_shift(4);
|
||||
o.ArchID = data.read_shift(4);
|
||||
data.l += length - 8;
|
||||
return o;
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.1.7.60 Workbook */
|
||||
var parse_wb_bin = function(data, opts) {
|
||||
@ -52,6 +82,7 @@ var parse_wb_bin = function(data, opts) {
|
||||
case 'BrtEndWebPubItem': break;
|
||||
case 'BrtEndWebPubItems': break;*/
|
||||
case 'BrtFRTBegin': pass = true; break;
|
||||
case 'BrtFRTArchID$': break;
|
||||
case 'BrtFRTEnd': pass = false; break;
|
||||
case 'BrtEndBook': break;
|
||||
default: if(!pass) throw new Error("Unexpected record " + R.n);
|
||||
@ -70,6 +101,80 @@ var parse_wb_bin = function(data, opts) {
|
||||
return wb;
|
||||
};
|
||||
|
||||
var write_wb_bin = function(wb, opts) {
|
||||
/* [MS-XLSB] 2.1.7.60 Workbook */
|
||||
function write_BUNDLESHS(ba, wb, opts) {
|
||||
write_record(ba, "BrtBeginBundleShs");
|
||||
wb.SheetNames.forEach(function(s, idx) {
|
||||
var d = { hsState: 0, iTabID: idx+1, strRelID: 'rId' + (idx+1), name: s };
|
||||
write_record(ba, "BrtBundleSh", write_BrtBundleSh(d));
|
||||
});
|
||||
write_record(ba, "BrtEndBundleShs");
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.643 BrtFileVersion */
|
||||
function write_BrtFileVersion(data, o) {
|
||||
if(!o) o = new_buf(127);
|
||||
for(var i = 0; i != 4; ++i) o.write_shift(4, 0);
|
||||
write_XLWideString("SheetJS", o);
|
||||
write_XLWideString(XLSX.version, o);
|
||||
write_XLWideString(XLSX.version, o);
|
||||
write_XLWideString("7262", o);
|
||||
o.length = o.l;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.60 Workbook */
|
||||
function write_BOOKVIEWS(ba, wb, opts) {
|
||||
write_record(ba, "BrtBeginBookViews");
|
||||
/* 1*(BrtBookView *FRT) */
|
||||
write_record(ba, "BrtEndBookViews");
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.302 BrtCalcProp */
|
||||
function write_BrtCalcProp(data, o) {
|
||||
if(!o) o = new_buf(26);
|
||||
o.write_shift(4,0); /* force recalc */
|
||||
o.write_shift(4,1);
|
||||
o.write_shift(4,0);
|
||||
write_Xnum(0, o);
|
||||
o.write_shift(-4, 1023);
|
||||
o.write_shift(1, 0x33);
|
||||
o.write_shift(1, 0x00);
|
||||
return o;
|
||||
}
|
||||
|
||||
function write_BrtFileRecover(data, o) {
|
||||
if(!o) o = new_buf(1);
|
||||
o.write_shift(1,0);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.60 Workbook */
|
||||
var write_wb_bin = function(wb, opts) {
|
||||
var ba = buf_array();
|
||||
write_record(ba, "BrtBeginBook");
|
||||
write_record(ba, "BrtFileVersion", write_BrtFileVersion());
|
||||
/* [[BrtFileSharingIso] BrtFileSharing] */
|
||||
write_record(ba, "BrtWbProp", write_BrtWbProp());
|
||||
/* [ACABSPATH] */
|
||||
/* [[BrtBookProtectionIso] BrtBookProtection] */
|
||||
write_BOOKVIEWS(ba, wb, opts);
|
||||
write_BUNDLESHS(ba, wb, opts);
|
||||
/* [FNGROUP] */
|
||||
/* [EXTERNALS] */
|
||||
/* *BrtName */
|
||||
write_record(ba, "BrtCalcProp", write_BrtCalcProp());
|
||||
/* [BrtOleSize] */
|
||||
/* *(BrtUserBookView *FRT) */
|
||||
/* [PIVOTCACHEIDS] */
|
||||
/* [BrtWbFactoid] */
|
||||
/* [SMARTTAGTYPES] */
|
||||
/* [BrtWebOpt] */
|
||||
write_record(ba, "BrtFileRecover", write_BrtFileRecover());
|
||||
/* [WEBPUBITEMS] */
|
||||
/* [CRERRS] */
|
||||
/* FRTWORKBOOK */
|
||||
write_record(ba, "BrtEndBook");
|
||||
|
||||
return ba.end();
|
||||
};
|
||||
|
@ -12,6 +12,7 @@ var RecordEnum = {
|
||||
0x0009: { n:"BrtFmlaNum", f:parse_BrtFmlaNum },
|
||||
0x000A: { n:"BrtFmlaBool", f:parse_BrtFmlaBool },
|
||||
0x000B: { n:"BrtFmlaError", f:parse_BrtFmlaError },
|
||||
0x0010: { n:"BrtFRTArchID$", f:parse_BrtFRTArchID$ },
|
||||
0x0013: { n:"BrtSSTItem", f:parse_RichStr },
|
||||
0x0014: { n:"BrtPCDIMissing", f:parsenoop },
|
||||
0x0015: { n:"BrtPCDINumber", f:parsenoop },
|
||||
@ -65,7 +66,7 @@ var RecordEnum = {
|
||||
0x0080: { n:"BrtFileVersion", f:parsenoop },
|
||||
0x0081: { n:"BrtBeginSheet", f:parsenoop },
|
||||
0x0082: { n:"BrtEndSheet", f:parsenoop },
|
||||
0x0083: { n:"BrtBeginBook", f:parsenoop },
|
||||
0x0083: { n:"BrtBeginBook", f:parsenoop, p:0 },
|
||||
0x0084: { n:"BrtEndBook", f:parsenoop },
|
||||
0x0085: { n:"BrtBeginWsViews", f:parsenoop },
|
||||
0x0086: { n:"BrtEndWsViews", f:parsenoop },
|
||||
@ -82,10 +83,10 @@ var RecordEnum = {
|
||||
0x0091: { n:"BrtBeginSheetData", f:parsenoop },
|
||||
0x0092: { n:"BrtEndSheetData", f:parsenoop },
|
||||
0x0093: { n:"BrtWsProp", f:parse_BrtWsProp },
|
||||
0x0094: { n:"BrtWsDim", f:parse_BrtWsDim },
|
||||
0x0094: { n:"BrtWsDim", f:parse_BrtWsDim, p:16 },
|
||||
0x0097: { n:"BrtPane", f:parsenoop },
|
||||
0x0098: { n:"BrtSel", f:parsenoop },
|
||||
0x0099: { n:"BrtWbProp", f:parsenoop },
|
||||
0x0099: { n:"BrtWbProp", f:parse_BrtWbProp },
|
||||
0x009A: { n:"BrtWbFactoid", f:parsenoop },
|
||||
0x009B: { n:"BrtFileRecover", f:parsenoop },
|
||||
0x009C: { n:"BrtBundleSh", f:parse_BrtBundleSh },
|
||||
@ -821,3 +822,4 @@ var RecordEnum = {
|
||||
0xFFFF: { n:"", f:parsenoop }
|
||||
};
|
||||
|
||||
var evert_RE = evert(RecordEnum, 'n');
|
||||
|
@ -17,6 +17,7 @@ function parse_zip(zip, opts) {
|
||||
dir.workbooks.push(binname);
|
||||
xlsb = true;
|
||||
}
|
||||
if(dir.workbooks[0].substr(-3) == "bin") xlsb = true;
|
||||
if(xlsb) set_cp(1200);
|
||||
|
||||
if(!opts.bookSheets && !opts.bookProps) {
|
||||
@ -27,7 +28,7 @@ function parse_zip(zip, opts) {
|
||||
if(dir.style) styles = parse_sty(getzipdata(zip, dir.style.replace(/^\//,'')),dir.style, opts);
|
||||
|
||||
themes = {};
|
||||
if(opts.cellStyles && dir.themes) themes = parse_theme(getzipdata(zip, dir.themes[0].replace(/^\//,'')),dir.themes[0], opts);
|
||||
if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipdata(zip, dir.themes[0].replace(/^\//,'')),dir.themes[0], opts);
|
||||
}
|
||||
|
||||
var wb = parse_wb(getzipdata(zip, dir.workbooks[0].replace(/^\//,'')), dir.workbooks[0], opts);
|
||||
@ -76,18 +77,20 @@ function parse_zip(zip, opts) {
|
||||
}
|
||||
}
|
||||
|
||||
var wbrelsfile = 'xl/_rels/workbook.xml.rels';
|
||||
var wbext = xlsb ? "bin" : "xml";
|
||||
var wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
|
||||
var wbrels = parse_rels(getzipdata(zip, wbrelsfile, true), wbrelsfile);
|
||||
if(wbrels) try {
|
||||
wbrels = wb.Sheets.map(function(w) { return [w.name, wbrels['!id'][w.id].Target]; });
|
||||
} catch(e) { wbrels = null; }
|
||||
if(wbrels && wbrels.length === 0) wbrels = null;
|
||||
/* Numbers iOS hack */
|
||||
var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
|
||||
for(i = 0; i != props.Worksheets; ++i) {
|
||||
try {
|
||||
if(wbrels) path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
|
||||
else {
|
||||
path = 'xl/worksheets/sheet'+(i+1-nmode)+(xlsb?'.bin':'.xml');
|
||||
path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
|
||||
path = path.replace(/sheet0\./,"sheet.");
|
||||
}
|
||||
relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
|
||||
|
@ -43,7 +43,7 @@ function write_zip(wb, opts) {
|
||||
ct.extprops.push(f);
|
||||
add_rels(opts.rels, 3, f, RELS.EXT_PROPS);
|
||||
|
||||
if(wb.Custprops !== wb.Props) { /* TODO: fix xlsjs */
|
||||
if(wb.Custprops !== wb.Props && keys(wb.Custprops||{}).length > 0) {
|
||||
f = "docProps/custom.xml";
|
||||
zip.file(f, write_cust_props(wb.Custprops, opts));
|
||||
ct.custprops.push(f);
|
||||
@ -78,13 +78,13 @@ function write_zip(wb, opts) {
|
||||
|
||||
/* TODO: something more intelligent with styles */
|
||||
|
||||
f = "xl/styles.xml";
|
||||
f = "xl/styles." + wbext;
|
||||
zip.file(f, write_sty(wb, f, opts));
|
||||
ct.styles.push(f);
|
||||
add_rels(opts.wbrels, ++rId, "styles." + wbext, RELS.STY);
|
||||
|
||||
zip.file("[Content_Types].xml", write_ct(ct, opts));
|
||||
zip.file('_rels/.rels', write_rels(opts.rels));
|
||||
zip.file('xl/_rels/workbook.xml.rels', write_rels(opts.wbrels));
|
||||
zip.file('xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));
|
||||
return zip;
|
||||
}
|
||||
|
@ -29,22 +29,31 @@ function format_cell(cell, v) {
|
||||
try { return (cell.w = SSF.format(cell.XF.ifmt||0, v)); } catch(e) { return v; }
|
||||
}
|
||||
|
||||
function sheet_to_row_object_array(sheet, opts){
|
||||
var val, row, r, hdr = {}, isempty, R, C, v;
|
||||
function sheet_to_json(sheet, opts){
|
||||
var val, row, range, header, offset = 1, r, hdr = {}, isempty, R, C, v;
|
||||
var out = [];
|
||||
opts = opts || {};
|
||||
if(!sheet || !sheet["!ref"]) return out;
|
||||
r = decode_range(sheet["!ref"]);
|
||||
range = opts.range || sheet["!ref"];
|
||||
header = opts.header || "";
|
||||
switch(typeof range) {
|
||||
case 'string': r = decode_range(range); break;
|
||||
case 'number': r = decode_range(sheet["!ref"]); r.s.r = range; break;
|
||||
default: r = range;
|
||||
}
|
||||
if(header) offset = 0;
|
||||
for(R=r.s.r, C = r.s.c; C <= r.e.c; ++C) {
|
||||
val = sheet[encode_cell({c:C,r:R})];
|
||||
if(!val) continue;
|
||||
hdr[C] = format_cell(val);
|
||||
if(header === "A") hdr[C] = encode_col(C);
|
||||
else if(header === 1) hdr[C] = C;
|
||||
else if(Array.isArray(header)) hdr[C] = header[C - r.s.c];
|
||||
else if(!val) continue;
|
||||
else hdr[C] = format_cell(val);
|
||||
}
|
||||
|
||||
for (R = r.s.r + 1; R <= r.e.r; ++R) {
|
||||
for (R = r.s.r + offset; R <= r.e.r; ++R) {
|
||||
isempty = true;
|
||||
/* row index available as __rowNum__ */
|
||||
row = Object.create({ __rowNum__ : R });
|
||||
row = header === 1 ? [] : Object.create({ __rowNum__ : R });
|
||||
for (C = r.s.c; C <= r.e.c; ++C) {
|
||||
val = sheet[encode_cell({c: C,r: R})];
|
||||
if(!val || !val.t) continue;
|
||||
@ -65,6 +74,8 @@ function sheet_to_row_object_array(sheet, opts){
|
||||
return out;
|
||||
}
|
||||
|
||||
function sheet_to_row_object_array(sheet, opts) { if(!opts) opts = {}; delete opts.range; return sheet_to_json(sheet, opts); }
|
||||
|
||||
function sheet_to_csv(sheet, opts) {
|
||||
var out = [], txt = "";
|
||||
opts = opts || {};
|
||||
@ -114,8 +125,9 @@ var utils = {
|
||||
decode_range: decode_range,
|
||||
sheet_to_csv: sheet_to_csv,
|
||||
make_csv: sheet_to_csv,
|
||||
make_json: sheet_to_row_object_array,
|
||||
make_json: sheet_to_json,
|
||||
get_formulae: get_formulae,
|
||||
format_cell: format_cell,
|
||||
sheet_to_json: sheet_to_json,
|
||||
sheet_to_row_object_array: sheet_to_row_object_array
|
||||
};
|
||||
|
10
dist/xlsx.core.min.js
vendored
10
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
10
dist/xlsx.full.min.js
vendored
10
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
664
dist/xlsx.js
vendored
664
dist/xlsx.js
vendored
File diff suppressed because one or more lines are too long
8
dist/xlsx.min.js
vendored
8
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
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xlsx",
|
||||
"version": "0.7.3",
|
||||
"version": "0.7.4",
|
||||
"author": "sheetjs",
|
||||
"description": "XLSB/XLSX/XLSM (Excel 2007+ Spreadsheet) parser and writer",
|
||||
"keywords": [ "xlsx", "xlsb", "xlsm", "office", "excel", "spreadsheet" ],
|
||||
|
228
test.js
228
test.js
@ -26,6 +26,8 @@ var dir = "./test_files/";
|
||||
var paths = {
|
||||
cp1: dir + 'custom_properties.xlsx',
|
||||
cp2: dir + 'custom_properties.xlsb',
|
||||
css1: dir + 'cell_style_simple.xlsx',
|
||||
css2: dir + 'cell_style_simple.xlsb',
|
||||
cst1: dir + 'comments_stress_test.xlsx',
|
||||
cst2: dir + 'comments_stress_test.xlsb',
|
||||
fst1: dir + 'formula_stress_test.xlsx',
|
||||
@ -47,6 +49,7 @@ var N2 = 'XLSB';
|
||||
|
||||
function parsetest(x, wb, full, ext) {
|
||||
ext = (ext ? " [" + ext + "]": "");
|
||||
if(!full && ext) return;
|
||||
describe(x + ext + ' should have all bits', function() {
|
||||
var sname = dir + '2011/' + x + '.sheetnames';
|
||||
it('should have all sheets', function() {
|
||||
@ -125,14 +128,21 @@ function parsetest(x, wb, full, ext) {
|
||||
});
|
||||
}
|
||||
|
||||
var wbtable = {};
|
||||
|
||||
describe('should parse test files', function() {
|
||||
files.forEach(function(x) {
|
||||
if(!fs.existsSync(dir + x)) return;
|
||||
it(x, x.substr(-8) == ".pending" ? null : function() {
|
||||
var wb = X.readFile(dir + x, opts);
|
||||
wbtable[dir + x] = wb;
|
||||
parsetest(x, wb, true);
|
||||
['.xlsx', '.xlsm'].forEach(function(ext, idx) {
|
||||
parsetest(x, X.read(X.write(wb, {type:"buffer", bookType:ext.replace(/\./,""), bookSST: idx != 1})), true, ext);
|
||||
});
|
||||
fullex.forEach(function(ext, idx) {
|
||||
it(x + ' [' + ext + ']', function(){
|
||||
var wb = wbtable[dir + x];
|
||||
if(!wb) wb = X.readFile(dir + x, opts);
|
||||
parsetest(x, X.read(X.write(wb, {type:"buffer", bookType:ext.replace(/\./,""), bookSST: idx != 1}), {WTF:opts.WTF}), ext.replace(/\./,"") !== "xlsb", ext);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -209,6 +219,28 @@ describe('parse options', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
it('should not generate cell styles by default', function() {
|
||||
var wb = X.readFile(paths.css1);
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
assert(typeof ws[addr].s === 'undefined');
|
||||
});
|
||||
});
|
||||
});
|
||||
it('XLSX should generate cell styles when requested', function() {
|
||||
var wb = X.readFile(paths.css1, {cellStyles:true});
|
||||
var found = false;
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
if(typeof ws[addr].s !== 'undefined') return found = true;
|
||||
});
|
||||
});
|
||||
assert(found);
|
||||
});
|
||||
});
|
||||
describe('sheet', function() {
|
||||
it('should not generate sheet stubs by default', function() {
|
||||
@ -385,6 +417,34 @@ function custprop(wb) {
|
||||
assert.equal(wb.Custprops.Counter, -3.14);
|
||||
}
|
||||
|
||||
function cmparr(x){ for(var i=1;i!=x.length;++i) assert.deepEqual(x[0], x[i]); }
|
||||
|
||||
function deepcmp(x,y,k,m,c) {
|
||||
var s = k.indexOf(".");
|
||||
m = (m||"") + "|" + (s > -1 ? k.substr(0,s) : k);
|
||||
if(s < 0) return assert[c<0?'notEqual':'equal'](x[k], y[k], m);
|
||||
return deepcmp(x[k.substr(0,s)],y[k.substr(0,s)],k.substr(s+1),m,c)
|
||||
}
|
||||
|
||||
var styexc = [
|
||||
'A2|H10|bgColor.rgb',
|
||||
'F6|H1|patternType'
|
||||
]
|
||||
var stykeys = [
|
||||
"patternType",
|
||||
"fgColor.rgb",
|
||||
"bgColor.rgb"
|
||||
];
|
||||
function diffsty(ws, r1,r2) {
|
||||
var c1 = ws[r1].s, c2 = ws[r2].s;
|
||||
stykeys.forEach(function(m) {
|
||||
var c = -1;
|
||||
if(styexc.indexOf(r1+"|"+r2+"|"+m) > -1) c = 1;
|
||||
else if(styexc.indexOf(r2+"|"+r1+"|"+m) > -1) c = 1;
|
||||
deepcmp(c1,c2,m,r1+","+r2,c);
|
||||
});
|
||||
}
|
||||
|
||||
describe('parse features', function() {
|
||||
it('should have comment as part of cell properties', function(){
|
||||
var X = require('./');
|
||||
@ -496,6 +556,36 @@ describe('parse features', function() {
|
||||
assert.equal(sheet[3]['てすと'], '2/14/14');
|
||||
});
|
||||
});
|
||||
|
||||
describe('should correctly handle styles', function() {
|
||||
var ws, rn, rn2;
|
||||
before(function() {
|
||||
ws=X.readFile(paths.css1, {cellStyles:true}).Sheets.Sheet1;
|
||||
rn = function(range) {
|
||||
var r = X.utils.decode_range(range);
|
||||
var out = [];
|
||||
for(var R = r.s.r; R <= r.e.r; ++R) for(var C = r.s.c; C <= r.e.c; ++C)
|
||||
out.push(X.utils.encode_cell({c:C,r:R}));
|
||||
return out;
|
||||
};
|
||||
rn2 = function(r) { return [].concat.apply([], r.split(",").map(rn)); };
|
||||
});
|
||||
var ranges = [
|
||||
'A1:D1,F1:G1', 'A2:D2,F2:G2', /* rows */
|
||||
'A3:A10', 'B3:B10', 'E1:E10', 'F6:F8', /* cols */
|
||||
'H1:J4', 'H10' /* blocks */
|
||||
]
|
||||
ranges.forEach(function(rng) {
|
||||
it(rng,function(){cmparr(rn2(rng).map(function(x){ return ws[x].s; }));});
|
||||
});
|
||||
it('different styles', function() {
|
||||
for(var i = 0; i != ranges.length-1; ++i) {
|
||||
for(var j = i+1; j != ranges.length; ++j) {
|
||||
diffsty(ws, rn2(ranges[i])[0], rn2(ranges[j])[0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('roundtrip features', function() {
|
||||
@ -577,3 +667,137 @@ describe('invalid files', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function datenum(v, date1904) {
|
||||
if(date1904) v+=1462;
|
||||
var epoch = Date.parse(v);
|
||||
return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
|
||||
}
|
||||
function sheet_from_array_of_arrays(data, opts) {
|
||||
var ws = {};
|
||||
var range = {s: {c:10000000, r:10000000}, e: {c:0, r:0 }};
|
||||
for(var R = 0; R != data.length; ++R) {
|
||||
for(var C = 0; C != data[R].length; ++C) {
|
||||
if(range.s.r > R) range.s.r = R;
|
||||
if(range.s.c > C) range.s.c = C;
|
||||
if(range.e.r < R) range.e.r = R;
|
||||
if(range.e.c < C) range.e.c = C;
|
||||
var cell = {v: data[R][C] };
|
||||
if(cell.v == null) continue;
|
||||
var cell_ref = X.utils.encode_cell({c:C,r:R});
|
||||
if(typeof cell.v === 'number') cell.t = 'n';
|
||||
else if(typeof cell.v === 'boolean') cell.t = 'b';
|
||||
else if(cell.v instanceof Date) {
|
||||
cell.t = 'n'; cell.z = X.SSF._table[14];
|
||||
cell.v = datenum(cell.v);
|
||||
}
|
||||
else cell.t = 's';
|
||||
ws[cell_ref] = cell;
|
||||
}
|
||||
}
|
||||
if(range.s.c < 10000000) ws['!ref'] = X.utils.encode_range(range);
|
||||
return ws;
|
||||
}
|
||||
|
||||
describe('json output', function() {
|
||||
function seeker(json, keys, val) {
|
||||
for(var i = 0; i != json.length; ++i) {
|
||||
for(var j = 0; j != keys.length; ++j) {
|
||||
if(json[i][keys[j]] === val) throw new Error("found " + val + " in row " + i + " key " + keys[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
var data, ws;
|
||||
before(function() {
|
||||
data = [
|
||||
[1,2,3],
|
||||
[true, false, null, "sheetjs"],
|
||||
["foo","bar",new Date("2014-02-19T14:30Z"), "0.3"],
|
||||
["baz", null, "qux"]
|
||||
];
|
||||
ws = sheet_from_array_of_arrays(data);
|
||||
});
|
||||
it('should use first-row headers and full sheet by default', function() {
|
||||
var json = X.utils.sheet_to_json(ws);
|
||||
assert.equal(json.length, data.length - 1);
|
||||
assert.equal(json[0][1], true);
|
||||
assert.equal(json[1][2], "bar");
|
||||
assert.equal(json[2][3], "qux");
|
||||
assert.doesNotThrow(function() { seeker(json, [1,2,3], "sheetjs"); });
|
||||
assert.throws(function() { seeker(json, [1,2,3], "baz"); });
|
||||
});
|
||||
it('should create array of arrays if header == 1', function() {
|
||||
var json = X.utils.sheet_to_json(ws, {header:1});
|
||||
assert.equal(json.length, data.length);
|
||||
assert.equal(json[1][0], true);
|
||||
assert.equal(json[2][1], "bar");
|
||||
assert.equal(json[3][2], "qux");
|
||||
assert.doesNotThrow(function() { seeker(json, [0,1,2], "sheetjs"); });
|
||||
assert.throws(function() { seeker(json, [0,1,2,3], "sheetjs"); });
|
||||
assert.throws(function() { seeker(json, [0,1,2], "baz"); });
|
||||
});
|
||||
it('should use column names if header == "A"', function() {
|
||||
var json = X.utils.sheet_to_json(ws, {header:'A'});
|
||||
assert.equal(json.length, data.length);
|
||||
assert.equal(json[1]['A'], true);
|
||||
assert.equal(json[2]['B'], "bar");
|
||||
assert.equal(json[3]['C'], "qux");
|
||||
assert.doesNotThrow(function() { seeker(json, "ABC", "sheetjs"); });
|
||||
assert.throws(function() { seeker(json, "ABCD", "sheetjs"); });
|
||||
assert.throws(function() { seeker(json, "ABC", "baz"); });
|
||||
});
|
||||
it('should use column labels if specified', function() {
|
||||
var json = X.utils.sheet_to_json(ws, {header:["O","D","I","N"]});
|
||||
assert.equal(json.length, data.length);
|
||||
assert.equal(json[1]['O'], true);
|
||||
assert.equal(json[2]['D'], "bar");
|
||||
assert.equal(json[3]['I'], "qux");
|
||||
assert.doesNotThrow(function() { seeker(json, "ODI", "sheetjs"); });
|
||||
assert.throws(function() { seeker(json, "ODIN", "sheetjs"); });
|
||||
assert.throws(function() { seeker(json, "ODIN", "baz"); });
|
||||
});
|
||||
[["string", "A2:D4"], ["numeric", 1], ["object", {s:{r:1,c:0},e:{r:3,c:3}}]].forEach(function(w) {
|
||||
it('should accept custom ' + w[0] + ' range', function() {
|
||||
var json = X.utils.sheet_to_json(ws, {header:1, range:w[1]});
|
||||
assert.equal(json.length, 3);
|
||||
assert.equal(json[0][0], true);
|
||||
assert.equal(json[1][1], "bar");
|
||||
assert.equal(json[2][2], "qux");
|
||||
assert.doesNotThrow(function() { seeker(json, [0,1,2], "sheetjs"); });
|
||||
assert.throws(function() { seeker(json, [0,1,2,3], "sheetjs"); });
|
||||
assert.throws(function() { seeker(json, [0,1,2], "baz"); });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('corner cases', function() {
|
||||
it('output functions', function() {
|
||||
var data = [
|
||||
[1,2,3],
|
||||
[true, false, null, "sheetjs"],
|
||||
["foo","bar",new Date("2014-02-19T14:30Z"), "0.3"],
|
||||
["baz", null, "q\"ux"]
|
||||
];
|
||||
ws = sheet_from_array_of_arrays(data);
|
||||
ws.A1.f = ""; ws.A1.w = "";
|
||||
delete ws.C3.w; delete ws.C3.z; ws.C3.XF = {ifmt:14};
|
||||
ws.A4.t = "e";
|
||||
X.utils.get_formulae(ws);
|
||||
X.utils.make_csv(ws);
|
||||
X.utils.make_json(ws);
|
||||
ws.A2.t = "f";
|
||||
assert.throws(function() { X.utils.make_json(ws); });
|
||||
});
|
||||
it('SSF', function() {
|
||||
X.SSF.format("General", "dafuq");
|
||||
assert.throws(function(x) { return X.SSF.format("General", {sheet:"js"});});
|
||||
X.SSF.format("b e ddd hh AM/PM", 41722.4097222222);
|
||||
X.SSF.format("b ddd hh m", 41722.4097222222);
|
||||
["hhh","hhh A/P","hhmmm","sss","[hhh]","G eneral"].forEach(function(f) {
|
||||
assert.throws(function(x) { return X.SSF.format(f, 12345.6789);});
|
||||
});
|
||||
["[m]","[s]"].forEach(function(f) {
|
||||
assert.doesNotThrow(function(x) { return X.SSF.format(f, 12345.6789);});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 43c63e345c81a1fa3145777fe79a79e9b1cc04ee
|
||||
Subproject commit 5561c42b441a7593092652d7acde8f4ed9caff33
|
@ -3,9 +3,11 @@ BlankSheetTypes.xlsb.pending
|
||||
NumberFormatCondition.xlsb
|
||||
RkNumber.xlsb
|
||||
calendar_stress_test.xlsb.pending
|
||||
cell_style_simple.xlsb
|
||||
comments_stress_test.xlsb
|
||||
custom_properties.xlsb
|
||||
formula_stress_test.xlsb
|
||||
formulae_test_simple.xlsb
|
||||
hyperlink_stress_test_2011.xlsb
|
||||
merge_cells.xlsb
|
||||
named_ranges_2011.xlsb
|
||||
@ -167,6 +169,7 @@ apachepoi_workbookProtection_workbook_windows_protected.xlsx
|
||||
apachepoi_workbookProtection_worksheet_protected.xlsx
|
||||
apachepoi_xlsx-jdbc.xlsx
|
||||
calendar_stress_test.xlsx.pending
|
||||
cell_style_simple.xlsx
|
||||
comments_stress_test.xlsx
|
||||
custom_properties.xlsx
|
||||
excel-reader-xlsx_data01.xlsx
|
||||
@ -181,6 +184,7 @@ excel-reader-xlsx_error08.xlsx.pending
|
||||
excel-reader-xlsx_inline01.xlsx
|
||||
excel-reader-xlsx_libre01.xlsx
|
||||
formula_stress_test.xlsx
|
||||
formulae_test_simple.xlsx
|
||||
hyperlink_stress_test_2011.xlsx
|
||||
interview.xlsx
|
||||
issue.xlsx
|
||||
|
418
xlsx.js
418
xlsx.js
@ -2,7 +2,7 @@
|
||||
/* vim: set ts=2: */
|
||||
var XLSX = {};
|
||||
(function(XLSX){
|
||||
XLSX.version = '0.7.3';
|
||||
XLSX.version = '0.7.4';
|
||||
var current_codepage = 1252, current_cptable;
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
|
||||
if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel');
|
||||
@ -599,6 +599,7 @@ function evert(obj, arr) {
|
||||
var o = {};
|
||||
keys(obj).forEach(function(k) {
|
||||
if(!obj.hasOwnProperty(k)) return;
|
||||
if(arr && typeof arr === "string") o[obj[k][arr]] = k;
|
||||
if(!arr) o[obj[k]] = k;
|
||||
else (o[obj[k]]=o[obj[k]]||[]).push(k);
|
||||
});
|
||||
@ -682,7 +683,7 @@ function unescapexml(text){
|
||||
function escapexml(text){
|
||||
var s = text + '';
|
||||
rencstr.forEach(function(y){s=s.replace(new RegExp(y,'g'), rencoding[y]);});
|
||||
s = s.replace(/[\u0000-\u0007]/g,function(s) { return "_x" + ("0000"+_ord(s).toString(16)).substr(-4) + "_";}); /* TODO: verify range */
|
||||
s = s.replace(/[\u0000-\u0008\u000b-\u001f]/g,function(s) { return "_x" + ("0000"+_ord(s).toString(16)).substr(-4) + "_";});
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -731,8 +732,7 @@ function parseVector(data) {
|
||||
|
||||
function writetag(f,g) {return '<' + f + (g.match(/(^\s|\s$|\n)/)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>';}
|
||||
|
||||
/*jshint -W041 */
|
||||
function writextag(f,g,h) { return '<' + f + (h != null ? keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join("") : "") + (g == null ? "/" : (g.match(/(^\s|\s$|\n)/)?' xml:space="preserve"' : "") + '>' + g + '</' + f) + '>';}
|
||||
function writextag(f,g,h) { return '<' + f + (h !== null && h !== undefined ? keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join("") : "") + (g === null || g === undefined ? "/" : (g.match(/(^\s|\s$|\n)/)?' xml:space="preserve"' : "") + '>' + g + '</' + f) + '>';}
|
||||
|
||||
function write_w3cdtf(d, t) { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } }
|
||||
|
||||
@ -781,16 +781,15 @@ function readIEEE754(buf, idx, isLE, nl, ml) {
|
||||
return (s ? -1 : 1) * m * Math.pow(2, e - ml);
|
||||
}
|
||||
|
||||
var __toBuffer;
|
||||
var __toBuffer, ___toBuffer;
|
||||
__toBuffer = ___toBuffer = function(bufs) {
|
||||
var x = [];
|
||||
for(var i = 0; i != bufs[0].length; ++i) { x = x.concat(bufs[0][i]); }
|
||||
return x;
|
||||
};
|
||||
if(typeof Buffer !== "undefined") {
|
||||
Buffer.prototype.hexlify= function() { return this.toString('hex'); };
|
||||
__toBuffer = function(bufs) { return Buffer.concat(bufs[0]); };
|
||||
} else {
|
||||
__toBuffer = function(bufs) {
|
||||
var x = [];
|
||||
for(var i = 0; i != bufs[0].length; ++i) { x = x.concat(bufs[0][i]); }
|
||||
return x;
|
||||
};
|
||||
__toBuffer = function(bufs) { try { return Buffer.concat(bufs[0]); } catch(e) { return ___toBuffer(bufs);} };
|
||||
}
|
||||
|
||||
var __readUInt8 = function(b, idx) { return b.readUInt8 ? b.readUInt8(idx) : b[idx]; };
|
||||
@ -800,9 +799,10 @@ var __readUInt32LE = function(b, idx) { return b.readUInt32LE ? b.readUInt32LE(i
|
||||
var __readInt32LE = function(b, idx) { if(b.readInt32LE) return b.readInt32LE(idx); var u = __readUInt32LE(b,idx); if(!(u & 0x80000000)) return u; return (0xffffffff - u + 1) * -1; };
|
||||
var __readDoubleLE = function(b, idx) { return b.readDoubleLE ? b.readDoubleLE(idx) : readIEEE754(b, idx||0);};
|
||||
|
||||
var __hexlify = function(b,l) { if(b.hexlify) return b.hexlify((b.l||0), (b.l||0)+l); return b.slice(b.l||0,(b.l||0)+16).map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); };
|
||||
|
||||
function ReadShift(size, t) {
|
||||
var o = "", oo = [], w, vv, i, loc; t = t || 'u';
|
||||
var o="", oo=[], w, vv, i, loc; t = t || 'u';
|
||||
if(size === 'ieee754') { size = 8; t = 'f'; }
|
||||
switch(size) {
|
||||
case 1: o = __readUInt8(this, this.l); break;
|
||||
@ -810,31 +810,59 @@ function ReadShift(size, t) {
|
||||
case 4: o = __readUInt32LE(this, this.l); break;
|
||||
case 8: if(t === 'f') { o = __readDoubleLE(this, this.l); break; }
|
||||
/* falls through */
|
||||
case 16: o = this.toString('hex', this.l,this.l+size); break;
|
||||
case 16: o = __hexlify(this, 16); break;
|
||||
|
||||
case 'dbcs': size = 2*t; loc = this.l;
|
||||
for(i = 0; i != t; ++i) {
|
||||
oo.push(_getchar(__readUInt16LE(this, loc)));
|
||||
loc+=2;
|
||||
} o = oo.join(""); break;
|
||||
|
||||
case 'sbcs': size = t; o = ""; loc = this.l;
|
||||
for(i = 0; i != t; ++i) {
|
||||
o += _getchar(__readUInt8(this, loc));
|
||||
loc+=1;
|
||||
} break;
|
||||
}
|
||||
this.l+=size; return o;
|
||||
}
|
||||
|
||||
function prep_blob(blob, pos) {
|
||||
blob.read_shift = ReadShift.bind(blob);
|
||||
function WriteShift(t, val, f) {
|
||||
var size, i;
|
||||
if(t === 'ieee754') { f = 'f'; t = 8; }
|
||||
switch(t) {
|
||||
case 1: size = 1; this.writeUInt8(val, this.l); break;
|
||||
case 4: size = 4; this.writeUInt32LE(val, this.l); break;
|
||||
case 8: size = 8; if(f === 'f') { this.writeDoubleLE(val, this.l); break; }
|
||||
/* falls through */
|
||||
case 16: break;
|
||||
case -4: size = 4; this.writeInt32LE(val, this.l); break;
|
||||
case 'dbcs':
|
||||
for(i = 0; i != val.length; ++i) this.writeUInt16LE(val.charCodeAt(i), this.l + 2 * i);
|
||||
size = 2 * val.length;
|
||||
break;
|
||||
}
|
||||
this.l += size; return this;
|
||||
}
|
||||
|
||||
function prep_blob(blob, pos, w) {
|
||||
blob.l = pos || 0;
|
||||
var read = ReadShift.bind(blob);
|
||||
return [read];
|
||||
if(w) {
|
||||
var write = WriteShift.bind(blob);
|
||||
blob.write_shift = write;
|
||||
return [write];
|
||||
} else {
|
||||
var read = ReadShift.bind(blob);
|
||||
blob.read_shift = read;
|
||||
return [read];
|
||||
}
|
||||
}
|
||||
|
||||
function parsenoop(blob, length) { blob.l += length; }
|
||||
|
||||
function writenoop(blob, length) { blob.l += length; }
|
||||
|
||||
var new_buf = function(sz) {
|
||||
var o = typeof Buffer !== 'undefined' ? new Buffer(sz) : new Array(sz);
|
||||
prep_blob(o, 0, true);
|
||||
return o;
|
||||
};
|
||||
|
||||
var is_buf = function(a) { return (typeof Buffer !== 'undefined' && a instanceof Buffer) || Array.isArray(a); };
|
||||
/* [MS-XLSB] 2.1.4 Record */
|
||||
var recordhopper = function(data, cb, opts) {
|
||||
var tmpbyte, cntbyte, length;
|
||||
@ -852,8 +880,54 @@ var recordhopper = function(data, cb, opts) {
|
||||
};
|
||||
|
||||
/* control buffer usage for fixed-length buffers */
|
||||
var blobhopper = function() {
|
||||
var bufs = [];
|
||||
var buf_array = function() {
|
||||
var bufs = [], blksz = 2048;
|
||||
var newblk = function(sz) {
|
||||
var o = new_buf(sz || blksz);
|
||||
prep_blob(o, 0, true);
|
||||
return o;
|
||||
};
|
||||
|
||||
var curbuf = newblk();
|
||||
|
||||
var endbuf = function() {
|
||||
curbuf.length = curbuf.l;
|
||||
if(curbuf.length > 0) bufs.push(curbuf);
|
||||
curbuf = null;
|
||||
};
|
||||
|
||||
var next = function(sz) {
|
||||
if(sz < curbuf.length - curbuf.l) return curbuf;
|
||||
endbuf();
|
||||
return (curbuf = newblk(Math.max(sz+1, blksz)));
|
||||
};
|
||||
|
||||
var end = function() {
|
||||
endbuf();
|
||||
return __toBuffer([bufs]);
|
||||
};
|
||||
|
||||
var push = function(buf) { endbuf(); curbuf = buf; next(); };
|
||||
|
||||
return { next:next, push:push, end:end, _bufs:bufs };
|
||||
};
|
||||
|
||||
var write_record = function(ba, type, payload, length) {
|
||||
var t = evert_RE[type], l;
|
||||
if(!length) length = RecordEnum[t].p || (payload||[]).length || 0;
|
||||
l = 1 + (t >= 0x80 ? 1 : 0) + 1 + length;
|
||||
if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l;
|
||||
var o = ba.next(l);
|
||||
if(t <= 0x7F) o.write_shift(1, t);
|
||||
else {
|
||||
o.write_shift(1, (t & 0x7F) + 0x80);
|
||||
o.write_shift(1, (t >> 7));
|
||||
}
|
||||
for(var i = 0; i != 4; ++i) {
|
||||
if(length >= 0x80) { o.write_shift(1, (length & 0x7F)+0x80); length >>= 7; }
|
||||
else { o.write_shift(1, length); break; }
|
||||
}
|
||||
if(length > 0 && is_buf(payload)) ba.push(payload);
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.5.143 */
|
||||
@ -898,8 +972,34 @@ function parse_Cell(data) {
|
||||
/* [MS-XLSB] 2.5.21 */
|
||||
var parse_CodeName = function(data, length) { return parse_XLWideString(data, length); };
|
||||
|
||||
/* [MS-XLSB] 2.5.166 */
|
||||
var parse_XLNullableWideString = function(data) {
|
||||
var cchCharacters = data.read_shift(4);
|
||||
return cchCharacters === 0 || cchCharacters === 0xFFFFFFFF ? "" : data.read_shift('dbcs', cchCharacters);
|
||||
};
|
||||
var write_XLNullableWideString = function(data, o) {
|
||||
if(!o) o = new_buf(127);
|
||||
o.write_shift(4, data.length || 0xFFFFFFFF);
|
||||
if(data.length > 0) o.write_shift('dbcs', data);
|
||||
return o;
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.5.168 */
|
||||
var parse_XLWideString = function(data) {
|
||||
var cchCharacters = data.read_shift(4);
|
||||
return cchCharacters === 0 ? "" : data.read_shift('dbcs', cchCharacters);
|
||||
};
|
||||
var write_XLWideString = function(data, o) {
|
||||
if(!o) o = new_buf(127);
|
||||
o.write_shift(4, data.length);
|
||||
if(data.length > 0) o.write_shift('dbcs', data);
|
||||
return o;
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.5.114 */
|
||||
var parse_RelID = function(data, length) { return parse_XLNullableWideString(data, length); };
|
||||
var parse_RelID = parse_XLNullableWideString;
|
||||
var write_RelID = write_XLNullableWideString;
|
||||
|
||||
|
||||
/* [MS-XLSB] 2.5.122 */
|
||||
function parse_RkNumber(data) {
|
||||
@ -921,20 +1021,18 @@ var parse_UncheckedRfX = function(data) {
|
||||
return cell;
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.5.166 */
|
||||
var parse_XLNullableWideString = function(data) {
|
||||
var cchCharacters = data.read_shift(4);
|
||||
return cchCharacters === 0 || cchCharacters === 0xFFFFFFFF ? "" : data.read_shift('dbcs', cchCharacters);
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.5.168 */
|
||||
var parse_XLWideString = function(data) {
|
||||
var cchCharacters = data.read_shift(4);
|
||||
return cchCharacters === 0 ? "" : data.read_shift('dbcs', cchCharacters);
|
||||
var write_UncheckedRfX = function(r, o) {
|
||||
if(!o) o = new_buf(16);
|
||||
o.write_shift(4, r.s.r);
|
||||
o.write_shift(4, r.e.r);
|
||||
o.write_shift(4, r.s.c);
|
||||
o.write_shift(4, r.e.c);
|
||||
return o;
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.5.171 */
|
||||
function parse_Xnum(data, length) { return data.read_shift('ieee754'); }
|
||||
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift('ieee754', data); }
|
||||
|
||||
/* [MS-XLSB] 2.5.198.2 */
|
||||
var BErr = {
|
||||
@ -965,7 +1063,7 @@ function parse_BrtColor(data, length) {
|
||||
out.bAlpha = read(1);
|
||||
}
|
||||
|
||||
/* [MS-XLSB 2.5.52 */
|
||||
/* [MS-XLSB] 2.5.52 */
|
||||
function parse_FontFlags(data, length) {
|
||||
var d = data.read_shift(1);
|
||||
data.l++;
|
||||
@ -1189,6 +1287,7 @@ var CTYPE_XML_ROOT = writextag('Types', null, {
|
||||
|
||||
var CTYPE_DEFAULTS = [
|
||||
['xml', 'application/xml'],
|
||||
['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
|
||||
['rels', type2ct.rels[0]]
|
||||
].map(function(x) {
|
||||
return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
|
||||
@ -1748,7 +1847,7 @@ function parse_fills(t, opts) {
|
||||
case '<patternFill':
|
||||
if(y.patternType) fill.patternType = y.patternType;
|
||||
break;
|
||||
case '<patternFill/>': break;
|
||||
case '<patternFill/>': case '</patternFill>': break;
|
||||
|
||||
/* 18.8.3 bgColor CT_Color */
|
||||
case '<bgColor':
|
||||
@ -1756,7 +1855,7 @@ function parse_fills(t, opts) {
|
||||
if(y.indexed) fill.bgColor.indexed = parseInt(y.indexed);
|
||||
if(y.theme) fill.bgColor.theme = parseInt(y.theme);
|
||||
if(y.tint) fill.bgColor.tint = Number(y.tint);
|
||||
/* Excel uses 8 character RGB strings? */
|
||||
/* Excel uses ARGB strings */
|
||||
if(y.rgb) fill.bgColor.rgb = y.rgb.substring(y.rgb.length - 6);
|
||||
break;
|
||||
case '</bgColor>': break;
|
||||
@ -1766,7 +1865,7 @@ function parse_fills(t, opts) {
|
||||
if(!fill.fgColor) fill.fgColor = {};
|
||||
if(y.theme) fill.fgColor.theme = parseInt(y.theme);
|
||||
if(y.tint) fill.fgColor.tint = Number(y.tint);
|
||||
/* Excel uses 8 character RGB strings? */
|
||||
/* Excel uses ARGB strings */
|
||||
if(y.rgb) fill.fgColor.rgb = y.rgb.substring(y.rgb.length - 6);
|
||||
break;
|
||||
case '</fgColor>': break;
|
||||
@ -1882,8 +1981,8 @@ function write_sty_xml(wb, opts) {
|
||||
o.push(XML_HEADER);
|
||||
o.push(STYLES_XML_ROOT);
|
||||
if((w = write_numFmts(wb.SSF))) o.push(w);
|
||||
o.push('<fonts count="1"><font><sz val="12"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font></fonts>');
|
||||
o.push('<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
|
||||
o.push('<fonts count="1"><font><sz val="12"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font></fonts>');
|
||||
o.push('<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
|
||||
o.push('<borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>');
|
||||
o.push('<cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>');
|
||||
if((w = write_cellXfs(opts.cellXfs))) o.push(w);
|
||||
@ -1960,8 +2059,6 @@ function parse_sty_bin(data, opts) {
|
||||
}
|
||||
break; /* TODO */
|
||||
case 'BrtStyle': break; /* TODO */
|
||||
case 'BrtRowHdr': break; /* TODO */
|
||||
case 'BrtCellMeta': break; /* ?? */
|
||||
case 'BrtDXF': break; /* TODO */
|
||||
case 'BrtMRUColor': break; /* TODO */
|
||||
case 'BrtIndexedColor': break; /* TODO */
|
||||
@ -2011,6 +2108,8 @@ function parse_sty_bin(data, opts) {
|
||||
});
|
||||
return styles;
|
||||
}
|
||||
|
||||
function write_sty_bin(data, opts) { }
|
||||
RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
|
||||
|
||||
/* Various RGB/HSL utility functions - might want to put these elsewhere. */
|
||||
@ -2126,7 +2225,7 @@ function parse_clrScheme(t, opts) {
|
||||
t[0].match(/<[^>]*>/g).forEach(function(x) {
|
||||
var y = parsexmltag(x);
|
||||
switch(y[0]) {
|
||||
case '<a:clrScheme': case '<<a:clrScheme>': case '</<a:clrScheme>': break;
|
||||
case '<a:clrScheme': case '</a:clrScheme>': break;
|
||||
|
||||
/* 20.1.2.3.32 srgbClr CT_SRgbColor */
|
||||
case '<a:srgbClr': color.rgb = y.val; break;
|
||||
@ -2213,6 +2312,7 @@ function parse_cc_xml(data, opts) {
|
||||
return d;
|
||||
}
|
||||
|
||||
function write_cc_xml(data, opts) { }
|
||||
/* [MS-XLSB] 2.6.4.1 */
|
||||
var parse_BrtCalcChainItem$ = function(data, length) {
|
||||
var out = {};
|
||||
@ -2241,6 +2341,8 @@ function parse_cc_bin(data, opts) {
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
function write_cc_bin(data, opts) { }
|
||||
/* 18.7.3 CT_Comment */
|
||||
function parse_comments_xml(data, opts) {
|
||||
if(data.match(/<(?:\w+:)?comments *\/>/)) return [];
|
||||
@ -2266,6 +2368,8 @@ function parse_comments_xml(data, opts) {
|
||||
});
|
||||
return commentList;
|
||||
}
|
||||
|
||||
function write_comments_xml(data, opts) { }
|
||||
/* [MS-XLSB] 2.4.28 BrtBeginComment */
|
||||
var parse_BrtBeginComment = function(data, length) {
|
||||
var out = {};
|
||||
@ -2311,6 +2415,8 @@ function parse_comments_bin(data, opts) {
|
||||
return out;
|
||||
}
|
||||
|
||||
function write_comments_bin(data, opts) { }
|
||||
|
||||
function parse_comments(zip, dirComments, sheets, sheetRels, opts) {
|
||||
for(var i = 0; i != dirComments.length; ++i) {
|
||||
var canonicalpath=dirComments[i];
|
||||
@ -2578,6 +2684,7 @@ var parse_BrtRowHdr = function(data, length) {
|
||||
|
||||
/* [MS-XLSB] 2.4.812 BrtWsDim */
|
||||
var parse_BrtWsDim = parse_UncheckedRfX;
|
||||
var write_BrtWsDim = write_UncheckedRfX;
|
||||
|
||||
/* [MS-XLSB] 2.4.815 BrtWsProp */
|
||||
var parse_BrtWsProp = function(data, length) {
|
||||
@ -2903,7 +3010,64 @@ var parse_ws_bin = function(data, opts, rels) {
|
||||
return s;
|
||||
};
|
||||
|
||||
var write_ws_bin = function(wb, opts, rels) {};
|
||||
function write_CELLTABLE(ba, ws, idx, opts, wb) {
|
||||
var r = decode_range(ws['!ref'] || "A1");
|
||||
write_record(ba, 'BrtBeginSheetData');
|
||||
for(var i = r.s.r; i <= r.e.r; ++i) {
|
||||
/* [ACCELLTABLE] */
|
||||
/* BrtRowHdr */
|
||||
|
||||
/* *16384CELL */
|
||||
}
|
||||
write_record(ba, 'BrtEndSheetData');
|
||||
}
|
||||
|
||||
var write_ws_bin = function(idx, opts, wb) {
|
||||
var ba = buf_array();
|
||||
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
|
||||
var r = decode_range(ws['!ref'] || "A1");
|
||||
write_record(ba, "BrtBeginSheet");
|
||||
/* [BrtWsProp] */
|
||||
write_record(ba, "BrtWsDim", write_BrtWsDim(r));
|
||||
/* [WSVIEWS2] */
|
||||
/* [WSFMTINFO] */
|
||||
/* *COLINFOS */
|
||||
write_CELLTABLE(ba, ws, idx, opts, wb);
|
||||
/* [BrtSheetCalcProp] */
|
||||
/* [[BrtSheetProtectionIso] BrtSheetProtection] */
|
||||
/* *([BrtRangeProtectionIso] BrtRangeProtection) */
|
||||
/* [SCENMAN] */
|
||||
/* [AUTOFILTER] */
|
||||
/* [SORTSTATE] */
|
||||
/* [DCON] */
|
||||
/* [USERSHVIEWS] */
|
||||
/* [MERGECELLS] */
|
||||
/* [BrtPhoneticInfo] */
|
||||
/* *CONDITIONALFORMATTING */
|
||||
/* [DVALS] */
|
||||
/* *BrtHLink */
|
||||
/* [BrtPrintOptions] */
|
||||
/* [BrtMargins] */
|
||||
/* [BrtPageSetup] */
|
||||
/* [HEADERFOOTER] */
|
||||
/* [RWBRK] */
|
||||
/* [COLBRK] */
|
||||
/* *BrtBigName */
|
||||
/* [CELLWATCHES] */
|
||||
/* [IGNOREECS] */
|
||||
/* [SMARTTAGS] */
|
||||
/* [BrtDrawing] */
|
||||
/* [BrtLegacyDrawing] */
|
||||
/* [BrtLegacyDrawingHF] */
|
||||
/* [BrtBkHim] */
|
||||
/* [OLEOBJECTS] */
|
||||
/* [ACTIVEXCONTROLS] */
|
||||
/* [WEBPUBITEMS] */
|
||||
/* [LISTPARTS] */
|
||||
/* FRTWORKSHEET */
|
||||
write_record(ba, "BrtEndSheet");
|
||||
return ba.end();
|
||||
};
|
||||
/* 18.2.28 (CT_WorkbookProtection) Defaults */
|
||||
var WBPropsDef = {
|
||||
allowRefreshQuery: '0',
|
||||
@ -3135,6 +3299,36 @@ var parse_BrtBundleSh = function(data, length) {
|
||||
z.name = parse_XLWideString(data);
|
||||
return z;
|
||||
};
|
||||
var write_BrtBundleSh = function(data, o) {
|
||||
if(!o) o = new_buf(127);
|
||||
o.write_shift(4, data.hsState);
|
||||
o.write_shift(4, data.iTabID);
|
||||
write_RelID(data.strRelID, o);
|
||||
write_XLWideString(data.name, o);
|
||||
return o;
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.4.807 BrtWbProp */
|
||||
var parse_BrtWbProp = function(data, length) {
|
||||
data.read_shift(4);
|
||||
var dwThemeVersion = data.read_shift(4);
|
||||
var strName = (length > 8) ? parse_XLWideString(data) : "";
|
||||
return [dwThemeVersion, strName];
|
||||
};
|
||||
var write_BrtWbProp = function(data, o) {
|
||||
if(!o) o = new_buf(8);
|
||||
o.write_shift(4, 0);
|
||||
o.write_shift(4, 0);
|
||||
return o;
|
||||
};
|
||||
|
||||
var parse_BrtFRTArchID$ = function(data, length) {
|
||||
var o = {};
|
||||
data.read_shift(4);
|
||||
o.ArchID = data.read_shift(4);
|
||||
data.l += length - 8;
|
||||
return o;
|
||||
};
|
||||
|
||||
/* [MS-XLSB] 2.1.7.60 Workbook */
|
||||
var parse_wb_bin = function(data, opts) {
|
||||
@ -3180,6 +3374,7 @@ var parse_wb_bin = function(data, opts) {
|
||||
case 'BrtEndWebPubItem': break;
|
||||
case 'BrtEndWebPubItems': break;*/
|
||||
case 'BrtFRTBegin': pass = true; break;
|
||||
case 'BrtFRTArchID$': break;
|
||||
case 'BrtFRTEnd': pass = false; break;
|
||||
case 'BrtEndBook': break;
|
||||
default: if(!pass) throw new Error("Unexpected record " + R.n);
|
||||
@ -3198,8 +3393,82 @@ var parse_wb_bin = function(data, opts) {
|
||||
return wb;
|
||||
};
|
||||
|
||||
var write_wb_bin = function(wb, opts) {
|
||||
/* [MS-XLSB] 2.1.7.60 Workbook */
|
||||
function write_BUNDLESHS(ba, wb, opts) {
|
||||
write_record(ba, "BrtBeginBundleShs");
|
||||
wb.SheetNames.forEach(function(s, idx) {
|
||||
var d = { hsState: 0, iTabID: idx+1, strRelID: 'rId' + (idx+1), name: s };
|
||||
write_record(ba, "BrtBundleSh", write_BrtBundleSh(d));
|
||||
});
|
||||
write_record(ba, "BrtEndBundleShs");
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.643 BrtFileVersion */
|
||||
function write_BrtFileVersion(data, o) {
|
||||
if(!o) o = new_buf(127);
|
||||
for(var i = 0; i != 4; ++i) o.write_shift(4, 0);
|
||||
write_XLWideString("SheetJS", o);
|
||||
write_XLWideString(XLSX.version, o);
|
||||
write_XLWideString(XLSX.version, o);
|
||||
write_XLWideString("7262", o);
|
||||
o.length = o.l;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.60 Workbook */
|
||||
function write_BOOKVIEWS(ba, wb, opts) {
|
||||
write_record(ba, "BrtBeginBookViews");
|
||||
/* 1*(BrtBookView *FRT) */
|
||||
write_record(ba, "BrtEndBookViews");
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.302 BrtCalcProp */
|
||||
function write_BrtCalcProp(data, o) {
|
||||
if(!o) o = new_buf(26);
|
||||
o.write_shift(4,0); /* force recalc */
|
||||
o.write_shift(4,1);
|
||||
o.write_shift(4,0);
|
||||
write_Xnum(0, o);
|
||||
o.write_shift(-4, 1023);
|
||||
o.write_shift(1, 0x33);
|
||||
o.write_shift(1, 0x00);
|
||||
return o;
|
||||
}
|
||||
|
||||
function write_BrtFileRecover(data, o) {
|
||||
if(!o) o = new_buf(1);
|
||||
o.write_shift(1,0);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.60 Workbook */
|
||||
var write_wb_bin = function(wb, opts) {
|
||||
var ba = buf_array();
|
||||
write_record(ba, "BrtBeginBook");
|
||||
write_record(ba, "BrtFileVersion", write_BrtFileVersion());
|
||||
/* [[BrtFileSharingIso] BrtFileSharing] */
|
||||
write_record(ba, "BrtWbProp", write_BrtWbProp());
|
||||
/* [ACABSPATH] */
|
||||
/* [[BrtBookProtectionIso] BrtBookProtection] */
|
||||
write_BOOKVIEWS(ba, wb, opts);
|
||||
write_BUNDLESHS(ba, wb, opts);
|
||||
/* [FNGROUP] */
|
||||
/* [EXTERNALS] */
|
||||
/* *BrtName */
|
||||
write_record(ba, "BrtCalcProp", write_BrtCalcProp());
|
||||
/* [BrtOleSize] */
|
||||
/* *(BrtUserBookView *FRT) */
|
||||
/* [PIVOTCACHEIDS] */
|
||||
/* [BrtWbFactoid] */
|
||||
/* [SMARTTAGTYPES] */
|
||||
/* [BrtWebOpt] */
|
||||
write_record(ba, "BrtFileRecover", write_BrtFileRecover());
|
||||
/* [WEBPUBITEMS] */
|
||||
/* [CRERRS] */
|
||||
/* FRTWORKBOOK */
|
||||
write_record(ba, "BrtEndBook");
|
||||
|
||||
return ba.end();
|
||||
};
|
||||
function parse_wb(data, name, opts) {
|
||||
return (name.substr(-4)===".bin" ? parse_wb_bin : parse_wb_xml)(data, opts);
|
||||
@ -3267,6 +3536,7 @@ var RecordEnum = {
|
||||
0x0009: { n:"BrtFmlaNum", f:parse_BrtFmlaNum },
|
||||
0x000A: { n:"BrtFmlaBool", f:parse_BrtFmlaBool },
|
||||
0x000B: { n:"BrtFmlaError", f:parse_BrtFmlaError },
|
||||
0x0010: { n:"BrtFRTArchID$", f:parse_BrtFRTArchID$ },
|
||||
0x0013: { n:"BrtSSTItem", f:parse_RichStr },
|
||||
0x0014: { n:"BrtPCDIMissing", f:parsenoop },
|
||||
0x0015: { n:"BrtPCDINumber", f:parsenoop },
|
||||
@ -3320,7 +3590,7 @@ var RecordEnum = {
|
||||
0x0080: { n:"BrtFileVersion", f:parsenoop },
|
||||
0x0081: { n:"BrtBeginSheet", f:parsenoop },
|
||||
0x0082: { n:"BrtEndSheet", f:parsenoop },
|
||||
0x0083: { n:"BrtBeginBook", f:parsenoop },
|
||||
0x0083: { n:"BrtBeginBook", f:parsenoop, p:0 },
|
||||
0x0084: { n:"BrtEndBook", f:parsenoop },
|
||||
0x0085: { n:"BrtBeginWsViews", f:parsenoop },
|
||||
0x0086: { n:"BrtEndWsViews", f:parsenoop },
|
||||
@ -3337,10 +3607,10 @@ var RecordEnum = {
|
||||
0x0091: { n:"BrtBeginSheetData", f:parsenoop },
|
||||
0x0092: { n:"BrtEndSheetData", f:parsenoop },
|
||||
0x0093: { n:"BrtWsProp", f:parse_BrtWsProp },
|
||||
0x0094: { n:"BrtWsDim", f:parse_BrtWsDim },
|
||||
0x0094: { n:"BrtWsDim", f:parse_BrtWsDim, p:16 },
|
||||
0x0097: { n:"BrtPane", f:parsenoop },
|
||||
0x0098: { n:"BrtSel", f:parsenoop },
|
||||
0x0099: { n:"BrtWbProp", f:parsenoop },
|
||||
0x0099: { n:"BrtWbProp", f:parse_BrtWbProp },
|
||||
0x009A: { n:"BrtWbFactoid", f:parsenoop },
|
||||
0x009B: { n:"BrtFileRecover", f:parsenoop },
|
||||
0x009C: { n:"BrtBundleSh", f:parse_BrtBundleSh },
|
||||
@ -4076,6 +4346,7 @@ var RecordEnum = {
|
||||
0xFFFF: { n:"", f:parsenoop }
|
||||
};
|
||||
|
||||
var evert_RE = evert(RecordEnum, 'n');
|
||||
function fix_opts(defaults) {
|
||||
return function(opts) {
|
||||
defaults.forEach(function(d) {
|
||||
@ -4130,6 +4401,7 @@ function parse_zip(zip, opts) {
|
||||
dir.workbooks.push(binname);
|
||||
xlsb = true;
|
||||
}
|
||||
if(dir.workbooks[0].substr(-3) == "bin") xlsb = true;
|
||||
if(xlsb) set_cp(1200);
|
||||
|
||||
if(!opts.bookSheets && !opts.bookProps) {
|
||||
@ -4140,7 +4412,7 @@ function parse_zip(zip, opts) {
|
||||
if(dir.style) styles = parse_sty(getzipdata(zip, dir.style.replace(/^\//,'')),dir.style, opts);
|
||||
|
||||
themes = {};
|
||||
if(opts.cellStyles && dir.themes) themes = parse_theme(getzipdata(zip, dir.themes[0].replace(/^\//,'')),dir.themes[0], opts);
|
||||
if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipdata(zip, dir.themes[0].replace(/^\//,'')),dir.themes[0], opts);
|
||||
}
|
||||
|
||||
var wb = parse_wb(getzipdata(zip, dir.workbooks[0].replace(/^\//,'')), dir.workbooks[0], opts);
|
||||
@ -4189,18 +4461,20 @@ function parse_zip(zip, opts) {
|
||||
}
|
||||
}
|
||||
|
||||
var wbrelsfile = 'xl/_rels/workbook.xml.rels';
|
||||
var wbext = xlsb ? "bin" : "xml";
|
||||
var wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
|
||||
var wbrels = parse_rels(getzipdata(zip, wbrelsfile, true), wbrelsfile);
|
||||
if(wbrels) try {
|
||||
wbrels = wb.Sheets.map(function(w) { return [w.name, wbrels['!id'][w.id].Target]; });
|
||||
} catch(e) { wbrels = null; }
|
||||
if(wbrels && wbrels.length === 0) wbrels = null;
|
||||
/* Numbers iOS hack */
|
||||
var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
|
||||
for(i = 0; i != props.Worksheets; ++i) {
|
||||
try {
|
||||
if(wbrels) path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
|
||||
else {
|
||||
path = 'xl/worksheets/sheet'+(i+1-nmode)+(xlsb?'.bin':'.xml');
|
||||
path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
|
||||
path = path.replace(/sheet0\./,"sheet.");
|
||||
}
|
||||
relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
|
||||
@ -4279,7 +4553,7 @@ function write_zip(wb, opts) {
|
||||
ct.extprops.push(f);
|
||||
add_rels(opts.rels, 3, f, RELS.EXT_PROPS);
|
||||
|
||||
if(wb.Custprops !== wb.Props) { /* TODO: fix xlsjs */
|
||||
if(wb.Custprops !== wb.Props && keys(wb.Custprops||{}).length > 0) {
|
||||
f = "docProps/custom.xml";
|
||||
zip.file(f, write_cust_props(wb.Custprops, opts));
|
||||
ct.custprops.push(f);
|
||||
@ -4314,14 +4588,14 @@ function write_zip(wb, opts) {
|
||||
|
||||
/* TODO: something more intelligent with styles */
|
||||
|
||||
f = "xl/styles.xml";
|
||||
f = "xl/styles." + wbext;
|
||||
zip.file(f, write_sty(wb, f, opts));
|
||||
ct.styles.push(f);
|
||||
add_rels(opts.wbrels, ++rId, "styles." + wbext, RELS.STY);
|
||||
|
||||
zip.file("[Content_Types].xml", write_ct(ct, opts));
|
||||
zip.file('_rels/.rels', write_rels(opts.rels));
|
||||
zip.file('xl/_rels/workbook.xml.rels', write_rels(opts.wbrels));
|
||||
zip.file('xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));
|
||||
return zip;
|
||||
}
|
||||
function readSync(data, opts) {
|
||||
@ -4396,22 +4670,31 @@ function format_cell(cell, v) {
|
||||
try { return (cell.w = SSF.format(cell.XF.ifmt||0, v)); } catch(e) { return v; }
|
||||
}
|
||||
|
||||
function sheet_to_row_object_array(sheet, opts){
|
||||
var val, row, r, hdr = {}, isempty, R, C, v;
|
||||
function sheet_to_json(sheet, opts){
|
||||
var val, row, range, header, offset = 1, r, hdr = {}, isempty, R, C, v;
|
||||
var out = [];
|
||||
opts = opts || {};
|
||||
if(!sheet || !sheet["!ref"]) return out;
|
||||
r = decode_range(sheet["!ref"]);
|
||||
range = opts.range || sheet["!ref"];
|
||||
header = opts.header || "";
|
||||
switch(typeof range) {
|
||||
case 'string': r = decode_range(range); break;
|
||||
case 'number': r = decode_range(sheet["!ref"]); r.s.r = range; break;
|
||||
default: r = range;
|
||||
}
|
||||
if(header) offset = 0;
|
||||
for(R=r.s.r, C = r.s.c; C <= r.e.c; ++C) {
|
||||
val = sheet[encode_cell({c:C,r:R})];
|
||||
if(!val) continue;
|
||||
hdr[C] = format_cell(val);
|
||||
if(header === "A") hdr[C] = encode_col(C);
|
||||
else if(header === 1) hdr[C] = C;
|
||||
else if(Array.isArray(header)) hdr[C] = header[C - r.s.c];
|
||||
else if(!val) continue;
|
||||
else hdr[C] = format_cell(val);
|
||||
}
|
||||
|
||||
for (R = r.s.r + 1; R <= r.e.r; ++R) {
|
||||
for (R = r.s.r + offset; R <= r.e.r; ++R) {
|
||||
isempty = true;
|
||||
/* row index available as __rowNum__ */
|
||||
row = Object.create({ __rowNum__ : R });
|
||||
row = header === 1 ? [] : Object.create({ __rowNum__ : R });
|
||||
for (C = r.s.c; C <= r.e.c; ++C) {
|
||||
val = sheet[encode_cell({c: C,r: R})];
|
||||
if(!val || !val.t) continue;
|
||||
@ -4432,6 +4715,8 @@ function sheet_to_row_object_array(sheet, opts){
|
||||
return out;
|
||||
}
|
||||
|
||||
function sheet_to_row_object_array(sheet, opts) { if(!opts) opts = {}; delete opts.range; return sheet_to_json(sheet, opts); }
|
||||
|
||||
function sheet_to_csv(sheet, opts) {
|
||||
var out = [], txt = "";
|
||||
opts = opts || {};
|
||||
@ -4481,9 +4766,10 @@ var utils = {
|
||||
decode_range: decode_range,
|
||||
sheet_to_csv: sheet_to_csv,
|
||||
make_csv: sheet_to_csv,
|
||||
make_json: sheet_to_row_object_array,
|
||||
make_json: sheet_to_json,
|
||||
get_formulae: get_formulae,
|
||||
format_cell: format_cell,
|
||||
sheet_to_json: sheet_to_json,
|
||||
sheet_to_row_object_array: sheet_to_row_object_array
|
||||
};
|
||||
XLSX.parseZip = parse_zip;
|
||||
|
Loading…
Reference in New Issue
Block a user