Skip to content

Commit

Permalink
version bump 0.7.4: I/O improvements
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
SheetJSDev committed May 29, 2014
1 parent c91e94d commit a3d9c4d
Show file tree
Hide file tree
Showing 34 changed files with 1,556 additions and 218 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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}'`"';" > $@
Expand Down
2 changes: 1 addition & 1 deletion bin/xlsx.njs
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down
2 changes: 1 addition & 1 deletion bits/01_version.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
XLSX.version = '0.7.3';
XLSX.version = '0.7.4';
1 change: 1 addition & 0 deletions bits/30_jsutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
Expand Down
5 changes: 2 additions & 3 deletions bits/36_xmlutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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; } }

Expand Down
68 changes: 48 additions & 20 deletions bits/37_binutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]; };
Expand All @@ -35,38 +34,67 @@ 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;
case 2: o=(t==='u' ? __readUInt16LE : __readInt16LE)(this, this.l); break;
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); };
50 changes: 48 additions & 2 deletions bits/38_hoppers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
48 changes: 36 additions & 12 deletions bits/39_parsestructs.js → bits/39_binstructs.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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 = {
Expand Down Expand Up @@ -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++;
Expand Down
1 change: 1 addition & 0 deletions bits/40_ctype.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]});
Expand Down
10 changes: 5 additions & 5 deletions bits/57_styxml.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ 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':
if(!fill.bgColor) fill.bgColor = {};
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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions bits/58_stybin.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -115,3 +113,5 @@ function parse_sty_bin(data, opts) {
});
return styles;
}

function write_sty_bin(data, opts) { }
2 changes: 1 addition & 1 deletion bits/59_theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions bits/61_ccxml.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ function parse_cc_xml(data, opts) {
return d;
}

function write_cc_xml(data, opts) { }
2 changes: 2 additions & 0 deletions bits/62_ccbin.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ function parse_cc_bin(data, opts) {
});
return out;
}

function write_cc_bin(data, opts) { }
2 changes: 2 additions & 0 deletions bits/63_cmntxml.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ function parse_comments_xml(data, opts) {
});
return commentList;
}

function write_comments_xml(data, opts) { }
2 changes: 2 additions & 0 deletions bits/64_cmntbin.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ function parse_comments_bin(data, opts) {
});
return out;
}

function write_comments_bin(data, opts) { }
Loading

0 comments on commit a3d9c4d

Please sign in to comment.