version bump 0.9.7: write features
- write !cols widths : XLSX XLSB XLML - write hyperlinks : XLML - XLSB convert date cell to numeric on write - fixed issue with assigning self in jszip issues: - closes #607 h/t @jscheid - closes #195 h/t @asfman
This commit is contained in:
parent
085150db3b
commit
b89a876076
|
@ -8,6 +8,7 @@ changes may not be included if they are not expected to break existing code.
|
|||
## Unreleased
|
||||
|
||||
* XLS legacy `!range` field removed
|
||||
* Hyperlink tooltip is stored in the `Tooltip` field
|
||||
|
||||
## 0.9.6 (2017-03-25)
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
XLSX.version = '0.9.6';
|
||||
XLSX.version = '0.9.7';
|
||||
|
|
|
@ -95,7 +95,7 @@ function ReadShift(size/*:number*/, t/*:?string*/) {
|
|||
case 'cstr': size = 0; o = "";
|
||||
while((w=__readUInt8(this, this.l + size++))!==0) oo.push(_getchar(w));
|
||||
o = oo.join(""); break;
|
||||
case 'wstr': size = 0; o = "";
|
||||
case '_wstr': size = 0; o = "";
|
||||
while((w=__readUInt16LE(this,this.l +size))!==0){oo.push(_getchar(w));size+=2;}
|
||||
size+=2; o = oo.join(""); break;
|
||||
|
||||
|
|
|
@ -226,6 +226,15 @@ var CTYPE_XML_ROOT = writextag('Types', null, {
|
|||
var CTYPE_DEFAULTS = [
|
||||
['xml', 'application/xml'],
|
||||
['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
|
||||
/* from test files */
|
||||
['bmp', 'image/bmp'],
|
||||
['png', 'image/png'],
|
||||
['gif', 'image/gif'],
|
||||
['emf', 'image/x-emf'],
|
||||
['wmf', 'image/x-wmf'],
|
||||
['jpg', 'image/jpeg'], ['jpeg', 'image/jpeg'],
|
||||
['tif', 'image/tiff'], ['tiff', 'image/tiff'],
|
||||
['pdf', 'application/pdf'],
|
||||
['rels', type2ct.rels[0]]
|
||||
].map(function(x) {
|
||||
return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
|
||||
|
@ -267,6 +276,7 @@ function write_ct(ct, opts)/*:string*/ {
|
|||
['strs', 'styles'].forEach(f1);
|
||||
['coreprops', 'extprops', 'custprops'].forEach(f3);
|
||||
f3('vba');
|
||||
f3('comments');
|
||||
if(o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
|
||||
return o.join("");
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ function parse_cust_props(data/*:string*/, opts) {
|
|||
var type = toks[0].substring(4), text = toks[1];
|
||||
/* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */
|
||||
switch(type) {
|
||||
case 'lpstr': case 'lpwstr': case 'bstr': case 'lpwstr':
|
||||
case 'lpstr': case 'bstr': case 'lpwstr':
|
||||
p[name] = unescapexml(text);
|
||||
break;
|
||||
case 'bool':
|
||||
|
|
|
@ -51,7 +51,7 @@ function rgb_tint(hex, tint) {
|
|||
|
||||
/* 18.3.1.13 width calculations */
|
||||
/* [MS-OI29500] 2.1.595 Column Width & Formatting */
|
||||
var DEF_MDW = 7, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
|
||||
var DEF_MDW = 6, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
|
||||
function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); }
|
||||
function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; }
|
||||
function char2width(chr) { return (Math.round((chr * MDW + 5)/MDW*256))/256; }
|
||||
|
|
|
@ -75,8 +75,8 @@ function parse_fills(t, styles, themes, opts) {
|
|||
case '</fill>': styles.Fills.push(fill); fill = {}; break;
|
||||
|
||||
/* 18.8.24 gradientFill CT_GradientFill */
|
||||
case '<fill>': break;
|
||||
case '</fill>': styles.Fills.push(fill); fill = {}; break;
|
||||
case '<gradientFill>': break;
|
||||
case '</gradientFill>': styles.Fills.push(fill); fill = {}; break;
|
||||
|
||||
/* 18.8.32 patternFill CT_PatternFill */
|
||||
case '<patternFill': case '<patternFill>':
|
||||
|
|
|
@ -11,6 +11,18 @@ function get_sst_id(sst/*:SST*/, str/*:string*/)/*:number*/ {
|
|||
sst[len] = {t:str}; sst.Count ++; sst.Unique ++; return len;
|
||||
}
|
||||
|
||||
function col_obj_w(C/*:number*/, col) {
|
||||
var p = ({min:C+1,max:C+1}/*:any*/);
|
||||
/* wch (chars), wpx (pixels) */
|
||||
var width = -1;
|
||||
if(col.MDW) MDW = col.MDW;
|
||||
if(col.width != null) p.customWidth = 1;
|
||||
else if(col.wpx != null) width = px2char(col.wpx);
|
||||
else if(col.wch != null) width = col.wch;
|
||||
if(width > -1) { p.width = char2width(width); p.customWidth = 1; }
|
||||
return p;
|
||||
}
|
||||
|
||||
function get_cell_style(styles, cell, opts) {
|
||||
var z = opts.revssf[cell.z != null ? cell.z : "General"];
|
||||
for(var i = 0, len = styles.length; i != len; ++i) if(styles[i].numFmtId === z) return i;
|
||||
|
|
|
@ -70,7 +70,7 @@ function write_ws_xml_merges(merges) {
|
|||
return o + '</mergeCells>';
|
||||
}
|
||||
|
||||
function parse_ws_xml_hlinks(s, data, rels) {
|
||||
function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
|
||||
for(var i = 0; i != data.length; ++i) {
|
||||
var val = parsexmltag(data[i], true);
|
||||
if(!val.ref) return;
|
||||
|
@ -84,6 +84,7 @@ function parse_ws_xml_hlinks(s, data, rels) {
|
|||
rel = {Target: val.location, TargetMode: 'Internal'};
|
||||
val.Rel = rel;
|
||||
}
|
||||
if(val.tooltip) { val.Tooltip = val.tooltip; delete val.tooltip; }
|
||||
var rng = safe_decode_range(val.ref);
|
||||
for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
|
||||
var addr = encode_cell({c:C,r:R});
|
||||
|
@ -109,15 +110,7 @@ function write_ws_xml_cols(ws, cols)/*:string*/ {
|
|||
var o = ["<cols>"], col, width;
|
||||
for(var i = 0; i != cols.length; ++i) {
|
||||
if(!(col = cols[i])) continue;
|
||||
var p = ({min:i+1,max:i+1}/*:any*/);
|
||||
/* wch (chars), wpx (pixels) */
|
||||
width = -1;
|
||||
if(col.MDW) MDW = col.MDW;
|
||||
if(col.width);
|
||||
else if(col.wpx) width = px2char(col.wpx);
|
||||
else if(col.wch) width = col.wch;
|
||||
if(width > -1) { p.width = char2width(width); p.customWidth= 1; }
|
||||
o[o.length] = (writextag('col', null, p));
|
||||
o[o.length] = (writextag('col', null, col_obj_w(i, col)));
|
||||
}
|
||||
o[o.length] = "</cols>";
|
||||
return o.join("");
|
||||
|
@ -328,14 +321,16 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ {
|
|||
|
||||
if(ws['!cols'] !== undefined && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols']));
|
||||
o[sidx = o.length] = '<sheetData/>';
|
||||
if(ws['!ref'] !== undefined) {
|
||||
if(ws['!ref'] != null) {
|
||||
rdata = write_ws_xml_data(ws, opts, idx, wb);
|
||||
if(rdata.length > 0) o[o.length] = (rdata);
|
||||
}
|
||||
if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
|
||||
|
||||
if(ws['!merges'] !== undefined && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
|
||||
if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
|
||||
|
||||
if(o.length>2) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
|
||||
|
||||
delete ws['!links'];
|
||||
return o.join("");
|
||||
}
|
||||
|
|
|
@ -226,7 +226,7 @@ function parse_BrtHLink(data, length, opts) {
|
|||
var tooltip = parse_XLWideString(data);
|
||||
var display = parse_XLWideString(data);
|
||||
data.l = end;
|
||||
return {rfx:rfx, relId:relId, loc:loc, tooltip:tooltip, display:display};
|
||||
return {rfx:rfx, relId:relId, loc:loc, Tooltip:tooltip, display:display};
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.6 BrtArrFmla */
|
||||
|
@ -255,6 +255,20 @@ function parse_BrtShrFmla(data, length, opts) {
|
|||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.323 BrtColInfo */
|
||||
/* TODO: once XLS ColInfo is set, combine the functions */
|
||||
function write_BrtColInfo(C/*:number*/, col, o) {
|
||||
if(o == null) o = new_buf(18);
|
||||
var p = col_obj_w(C, col);
|
||||
o.write_shift(-4, C);
|
||||
o.write_shift(-4, C);
|
||||
o.write_shift(4, p.width * 256);
|
||||
o.write_shift(4, 0/*ixfe*/); // style
|
||||
o.write_shift(1, 2); // bit flag
|
||||
o.write_shift(1, 0); // bit flag
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.61 Worksheet */
|
||||
function parse_ws_bin(data, opts, rels, wb, themes, styles)/*:Worksheet*/ {
|
||||
if(!data) return data;
|
||||
|
@ -521,9 +535,15 @@ function parse_ws_bin(data, opts, rels, wb, themes, styles)/*:Worksheet*/ {
|
|||
/* TODO: something useful -- this is a stub */
|
||||
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) {
|
||||
if(cell.v === undefined) return "";
|
||||
var vv = "";
|
||||
var vv = ""; var olddate = null;
|
||||
switch(cell.t) {
|
||||
case 'b': vv = cell.v ? "1" : "0"; break;
|
||||
case 'd': // no BrtCellDate :(
|
||||
cell.z = cell.z || SSF._table[14];
|
||||
olddate = cell.v;
|
||||
cell.v = datenum((cell.v/*:any*/)); cell.t = 'n';
|
||||
break;
|
||||
/* falls through */
|
||||
case 'n': case 'e': vv = ''+cell.v; break;
|
||||
default: vv = cell.v; break;
|
||||
}
|
||||
|
@ -533,7 +553,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
|
|||
switch(cell.t) {
|
||||
case 's': case 'str':
|
||||
if(opts.bookSST) {
|
||||
vv = get_sst_id(opts.Strings, cell.v);
|
||||
vv = get_sst_id(opts.Strings, (cell.v/*:any*/));
|
||||
o.t = "s"; o.v = vv;
|
||||
write_record(ba, "BrtCellIsst", write_BrtCellIsst(cell, o));
|
||||
} else {
|
||||
|
@ -545,6 +565,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
|
|||
/* TODO: determine threshold for Real vs RK */
|
||||
if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o));
|
||||
else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o));
|
||||
if(olddate) { cell.t = 'd'; cell.v = olddate; }
|
||||
return;
|
||||
case 'b':
|
||||
o.t = "b";
|
||||
|
@ -555,7 +576,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
|
|||
write_record(ba, "BrtCellBlank", write_BrtCellBlank(cell, o));
|
||||
}
|
||||
|
||||
function write_CELLTABLE(ba, ws, idx, opts, wb) {
|
||||
function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = [];
|
||||
write_record(ba, 'BrtBeginSheetData');
|
||||
for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
|
@ -582,6 +603,13 @@ function write_MERGECELLS(ba, ws/*:Worksheet*/) {
|
|||
write_record(ba, 'BrtEndMergeCells');
|
||||
}
|
||||
|
||||
function write_COLINFOS(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
if(!ws || !ws['!cols']) return;
|
||||
write_record(ba, 'BrtBeginColInfos');
|
||||
ws['!cols'].forEach(function(m, i) { if(m) write_record(ba, 'BrtColInfo', write_BrtColInfo(i, m)); });
|
||||
write_record(ba, 'BrtEndColInfos');
|
||||
}
|
||||
|
||||
function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
var ba = buf_array();
|
||||
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
|
||||
|
@ -591,7 +619,7 @@ function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/) {
|
|||
write_record(ba, "BrtWsDim", write_BrtWsDim(r));
|
||||
/* [WSVIEWS2] */
|
||||
/* [WSFMTINFO] */
|
||||
/* *COLINFOS */
|
||||
write_COLINFOS(ba, ws, idx, opts, wb);
|
||||
write_CELLTABLE(ba, ws, idx, opts, wb);
|
||||
/* [BrtSheetCalcProp] */
|
||||
/* [[BrtSheetProtectionIso] BrtSheetProtection] */
|
||||
|
|
|
@ -199,8 +199,8 @@ function parse_xlml_xml(d, opts)/*:Workbook*/ {
|
|||
if(comments.length > 0) cell.c = comments;
|
||||
if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== undefined) cursheet[encode_col(c) + encode_row(r)] = cell;
|
||||
if(cell.HRef) {
|
||||
cell.l = {Target:cell.HRef, tooltip:cell.HRefScreenTip};
|
||||
cell.HRef = cell.HRefScreenTip = undefined;
|
||||
cell.l = {Target:cell.HRef, Tooltip:cell.HRefScreenTip};
|
||||
delete cell.HRef; delete cell.HRefScreenTip;
|
||||
}
|
||||
if(cell.MergeAcross || cell.MergeDown) {
|
||||
var cc = c + (parseInt(cell.MergeAcross,10)|0);
|
||||
|
@ -787,6 +787,11 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
|
|||
attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]");
|
||||
}
|
||||
|
||||
if(cell.l && cell.l.Target) {
|
||||
attr["ss:HRef"] = escapexml(cell.l.Target);
|
||||
if(cell.l.Tooltip) attr["x:HRefScreenTip"] = escapexml(cell.l.Tooltip);
|
||||
}
|
||||
|
||||
if(ws['!merges']) {
|
||||
var marr = ws['!merges'];
|
||||
for(var mi = 0; mi != marr.length; ++mi) {
|
||||
|
@ -822,6 +827,10 @@ function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbo
|
|||
var range = safe_decode_range(ws['!ref']);
|
||||
var marr = ws['!merges'] || [], mi = 0;
|
||||
var o = [];
|
||||
if(ws['!cols']) ws['!cols'].forEach(function(n, i) {
|
||||
var p = col_obj_w(i, n);
|
||||
o.push(writextag("Column",null, {"ss:Index":i+1, "ss:Width":width2px(p.width)}));
|
||||
});
|
||||
for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
var row = ['<Row ss:Index="' + (R+1) + '">'];
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) {
|
||||
|
|
|
@ -432,7 +432,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
|||
for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
|
||||
for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC)
|
||||
if(out[encode_cell({c:rngC,r:rngR})])
|
||||
out[encode_cell({c:rngC,r:rngR})].l.tooltip = val[1];
|
||||
out[encode_cell({c:rngC,r:rngR})].l.Tooltip = val[1];
|
||||
} break;
|
||||
|
||||
/* Comments */
|
||||
|
|
|
@ -13,7 +13,6 @@ https://github.com/nodeca/pako/blob/master/LICENSE
|
|||
if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();
|
||||
else if("function"==typeof define&&define.amd){JSZip=e();define([],e);}
|
||||
else{
|
||||
if(typeof self == 'undefined' && typeof app != 'undefined') self = app;
|
||||
var f;
|
||||
"undefined"!=typeof window?f=window:
|
||||
"undefined"!=typeof global?f=global:
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -11,7 +11,7 @@
|
|||
| `h` | HTML rendering of the rich text (if applicable) |
|
||||
| `c` | comments associated with the cell |
|
||||
| `z` | number format string associated with the cell (if requested) |
|
||||
| `l` | cell hyperlink object (.Target holds link, .tooltip is tooltip) |
|
||||
| `l` | cell hyperlink object (.Target holds link, .Tooltip is tooltip) |
|
||||
| `s` | the style/theme of the cell (if applicable) |
|
||||
|
||||
Built-in export utilities (such as the CSV exporter) will use the `w` text if it
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#### Hyperlinks
|
||||
|
||||
Hyperlinks are stored in the `l` key of cell objects. The `Target` field of the
|
||||
hyperlink object is the target of the link, including the URI fragment. Tooltips
|
||||
are stored in the `Tooltip` field and are displayed when you move your mouse
|
||||
over the text.
|
||||
|
||||
For example, the following snippet creates a link from cell `A3` to
|
||||
<http://sheetjs.com> with the tip `"Find us @ SheetJS.com!"`:
|
||||
|
||||
```js
|
||||
ws['A3'].l = { Target:"http://sheetjs.com", Tooltip:"Find us @ SheetJS.com!" };
|
||||
```
|
||||
|
||||
Note that Excel does not automatically style hyperlinks -- they will generally
|
||||
be displayed as normal text.
|
||||
|
1
jszip.js
1
jszip.js
|
@ -13,7 +13,6 @@ https://github.com/nodeca/pako/blob/master/LICENSE
|
|||
if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();
|
||||
else if("function"==typeof define&&define.amd){JSZip=e();define([],e);}
|
||||
else{
|
||||
if(typeof self == 'undefined' && typeof app != 'undefined') self = app;
|
||||
var f;
|
||||
"undefined"!=typeof window?f=window:
|
||||
"undefined"!=typeof global?f=global:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "xlsx",
|
||||
"version": "0.9.6",
|
||||
"version": "0.9.7",
|
||||
"author": "sheetjs",
|
||||
"description": "Excel (XLSB/XLSX/XLSM/XLS/XML) and ODS (ODS/FODS/UOS) spreadsheet parser and writer",
|
||||
"keywords": [ "excel", "xls", "xlsx", "xlsb", "xlsm", "ods", "office", "spreadsheet" ],
|
||||
|
|
41
test.js
41
test.js
|
@ -602,6 +602,19 @@ function diffsty(ws, r1,r2) {
|
|||
});
|
||||
}
|
||||
|
||||
function hlink(wb) {
|
||||
var ws = wb.Sheets.Sheet1;
|
||||
assert.equal(ws.A1.l.Target, "http://www.sheetjs.com");
|
||||
assert.equal(ws.A2.l.Target, "http://oss.sheetjs.com");
|
||||
assert.equal(ws.A3.l.Target, "http://oss.sheetjs.com#foo");
|
||||
assert.equal(ws.A4.l.Target, "mailto:dev@sheetjs.com");
|
||||
assert.equal(ws.A5.l.Target, "mailto:dev@sheetjs.com?subject=hyperlink");
|
||||
assert.equal(ws.A6.l.Target, "../../sheetjs/Documents/Test.xlsx");
|
||||
assert.equal(ws.A7.l.Target, "http://sheetjs.com");
|
||||
assert.equal(ws.A7.l.Tooltip, "foo bar baz");
|
||||
}
|
||||
|
||||
|
||||
describe('parse features', function() {
|
||||
if(fs.existsSync(paths.swcxlsx)) it('should have comment as part of cell properties', function(){
|
||||
var X = require(modp);
|
||||
|
@ -760,17 +773,6 @@ describe('parse features', function() {
|
|||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
|
||||
function hlink(wb) {
|
||||
var ws = wb.Sheets.Sheet1;
|
||||
assert.equal(ws.A1.l.Target, "http://www.sheetjs.com");
|
||||
assert.equal(ws.A2.l.Target, "http://oss.sheetjs.com");
|
||||
assert.equal(ws.A3.l.Target, "http://oss.sheetjs.com#foo");
|
||||
assert.equal(ws.A4.l.Target, "mailto:dev@sheetjs.com");
|
||||
assert.equal(ws.A5.l.Target, "mailto:dev@sheetjs.com?subject=hyperlink");
|
||||
assert.equal(ws.A6.l.Target, "../../sheetjs/Documents/Test.xlsx");
|
||||
assert.equal(ws.A7.l.Target, "http://sheetjs.com");
|
||||
}
|
||||
|
||||
it(N1, function() { hlink(wb1); });
|
||||
it(N2, function() { hlink(wb2); });
|
||||
it(N3, function() { hlink(wb3); });
|
||||
|
@ -977,14 +979,27 @@ describe('roundtrip features', function() {
|
|||
].forEach(function(w) {
|
||||
it(w[0], function() {
|
||||
var wb1 = X.readFile(w[1], {cellFormula:true});
|
||||
if(w[0] == 'ods') X.writeFile(wb1, "./tmp/_.ods", {bookType:"ods"});
|
||||
var wb2 = X.read(X.write(wb1, {bookType:w[0], type:"buffer"}), {cellFormula:true, type:"buffer"});
|
||||
var wb2 = X.read(X.write(wb1, {bookType:w[0], type:"buffer"}), {type:"buffer"});
|
||||
wb1.SheetNames.forEach(function(n) {
|
||||
assert.equal( X.utils.sheet_to_formulae(wb1.Sheets[n]).sort().join("\n"), X.utils.sheet_to_formulae(wb2.Sheets[n]).sort().join("\n") );
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('should preserve hyperlink', function() { [
|
||||
['xlml', paths.hlxml],
|
||||
//['xlsx', paths.hlxlsx], // TODO
|
||||
//['xlsb', paths.hlxlsb] // TODO
|
||||
].forEach(function(w) {
|
||||
it(w[0], function() {
|
||||
var wb1 = X.readFile(w[1]);
|
||||
var wb2 = X.read(X.write(wb1, {bookType:w[0], type:"buffer"}), {type:"buffer"});
|
||||
hlink(wb1);
|
||||
hlink(wb2);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function password_file(x){return x.match(/^password.*\.xls$/); }
|
||||
|
|
|
@ -444,6 +444,19 @@ function diffsty(ws, r1,r2) {
|
|||
});
|
||||
}
|
||||
|
||||
function hlink(wb) {
|
||||
var ws = wb.Sheets.Sheet1;
|
||||
assert.equal(ws.A1.l.Target, "http://www.sheetjs.com");
|
||||
assert.equal(ws.A2.l.Target, "http://oss.sheetjs.com");
|
||||
assert.equal(ws.A3.l.Target, "http://oss.sheetjs.com#foo");
|
||||
assert.equal(ws.A4.l.Target, "mailto:dev@sheetjs.com");
|
||||
assert.equal(ws.A5.l.Target, "mailto:dev@sheetjs.com?subject=hyperlink");
|
||||
assert.equal(ws.A6.l.Target, "../../sheetjs/Documents/Test.xlsx");
|
||||
assert.equal(ws.A7.l.Target, "http://sheetjs.com");
|
||||
assert.equal(ws.A7.l.Tooltip, "foo bar baz");
|
||||
}
|
||||
|
||||
|
||||
describe('parse features', function() {
|
||||
if(fs.existsSync(paths.swcxlsx)) it('should have comment as part of cell properties', function(){
|
||||
var X = require(modp);
|
||||
|
@ -602,17 +615,6 @@ describe('parse features', function() {
|
|||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
|
||||
function hlink(wb) {
|
||||
var ws = wb.Sheets.Sheet1;
|
||||
assert.equal(ws.A1.l.Target, "http://www.sheetjs.com");
|
||||
assert.equal(ws.A2.l.Target, "http://oss.sheetjs.com");
|
||||
assert.equal(ws.A3.l.Target, "http://oss.sheetjs.com#foo");
|
||||
assert.equal(ws.A4.l.Target, "mailto:dev@sheetjs.com");
|
||||
assert.equal(ws.A5.l.Target, "mailto:dev@sheetjs.com?subject=hyperlink");
|
||||
assert.equal(ws.A6.l.Target, "../../sheetjs/Documents/Test.xlsx");
|
||||
assert.equal(ws.A7.l.Target, "http://sheetjs.com");
|
||||
}
|
||||
|
||||
it(N1, function() { hlink(wb1); });
|
||||
it(N2, function() { hlink(wb2); });
|
||||
it(N3, function() { hlink(wb3); });
|
||||
|
@ -825,6 +827,20 @@ describe('roundtrip features', function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('should preserve hyperlink', function() { [
|
||||
['xlml', paths.hlxml],
|
||||
//['xlsx', paths.hlxlsx], // TODO
|
||||
//['xlsb', paths.hlxlsb] // TODO
|
||||
].forEach(function(w) {
|
||||
it(w[0], function() {
|
||||
var wb1 = X.read(fs.readFileSync(w[1]), {type:"binary"});
|
||||
var wb2 = X.read(X.write(wb1, {bookType:w[0], type:"binary"}), {type:"binary"});
|
||||
hlink(wb1);
|
||||
hlink(wb2);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function password_file(x){return x.match(/^password.*\.xls$/); }
|
||||
|
|
|
@ -12,10 +12,10 @@ var data = [
|
|||
var ws_name = "SheetJS";
|
||||
|
||||
var wscols = [
|
||||
{wch:6},
|
||||
{wch:7},
|
||||
{wch:6}, // "characters"
|
||||
{wpx:50}, // "pixels"
|
||||
{wch:10},
|
||||
{wch:20}
|
||||
{wpx:125}
|
||||
];
|
||||
|
||||
|
||||
|
@ -28,52 +28,11 @@ console.log("Columns :"); for(i=0; i!=wscols.length;++i) console.log(wscols[i]);
|
|||
/* require XLSX */
|
||||
if(typeof XLSX === "undefined") { try { XLSX = require('./'); } catch(e) { XLSX = require('../'); } }
|
||||
|
||||
/* dummy workbook constructor */
|
||||
function Workbook() {
|
||||
if(!(this instanceof Workbook)) return new Workbook();
|
||||
this.SheetNames = [];
|
||||
this.Sheets = {};
|
||||
}
|
||||
var wb = new Workbook();
|
||||
|
||||
|
||||
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
|
||||
var epoch = v.getTime();
|
||||
if(date1904) epoch += 1462*24*60*60*1000;
|
||||
return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
|
||||
}
|
||||
/* blank workbook constructor */
|
||||
var wb = { SheetNames: [], Sheets: {} };
|
||||
|
||||
/* convert an array of arrays in JS to a CSF spreadsheet */
|
||||
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 = XLSX.utils.encode_cell({c:C,r:R});
|
||||
|
||||
/* TEST: proper cell types and value handling */
|
||||
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 = XLSX.SSF._table[14];
|
||||
cell.v = datenum(cell.v);
|
||||
}
|
||||
else cell.t = 's';
|
||||
ws[cell_ref] = cell;
|
||||
}
|
||||
}
|
||||
|
||||
/* TEST: proper range */
|
||||
if(range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
|
||||
return ws;
|
||||
}
|
||||
var ws = sheet_from_array_of_arrays(data);
|
||||
var ws = XLSX.utils.aoa_to_sheet(data, {cellDates:true});
|
||||
|
||||
/* TEST: add worksheet to workbook */
|
||||
wb.SheetNames.push(ws_name);
|
||||
|
@ -96,8 +55,18 @@ ws["!ref"] = "A1:E4";
|
|||
/* TEST: column widths */
|
||||
ws['!cols'] = wscols;
|
||||
|
||||
/* TEST: hyperlink note: Excel does not automatically style hyperlinks */
|
||||
ws['A3'].l = { Target: "http://sheetjs.com", Tooltip: "Visit us <SheetJS.com!>" };
|
||||
|
||||
/* TEST: built-in format */
|
||||
//ws['A1'].z = "0%"; wb.SSF[9] = "0%"; // Format Code 9
|
||||
|
||||
/* TEST: custom format */
|
||||
//ws['B2'].z = "0.0"; wb.SSF[60] = "0.0"; // Custom
|
||||
console.log("JSON Data: "); console.log(XLSX.utils.sheet_to_json(ws, {header:1}));
|
||||
|
||||
console.log("Worksheet Model:")
|
||||
console.log(ws);
|
||||
|
||||
/* write file */
|
||||
XLSX.writeFile(wb, 'sheetjs.xlsx', {bookSST:true});
|
||||
|
|
106
xlsx.flow.js
106
xlsx.flow.js
|
@ -5,7 +5,7 @@
|
|||
/*exported XLSX */
|
||||
var XLSX = {};
|
||||
(function make_xlsx(XLSX){
|
||||
XLSX.version = '0.9.6';
|
||||
XLSX.version = '0.9.7';
|
||||
var current_codepage = 1200, current_cptable;
|
||||
/*:: declare var cptable:any; */
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
|
||||
|
@ -1830,7 +1830,7 @@ function ReadShift(size/*:number*/, t/*:?string*/) {
|
|||
case 'cstr': size = 0; o = "";
|
||||
while((w=__readUInt8(this, this.l + size++))!==0) oo.push(_getchar(w));
|
||||
o = oo.join(""); break;
|
||||
case 'wstr': size = 0; o = "";
|
||||
case '_wstr': size = 0; o = "";
|
||||
while((w=__readUInt16LE(this,this.l +size))!==0){oo.push(_getchar(w));size+=2;}
|
||||
size+=2; o = oo.join(""); break;
|
||||
|
||||
|
@ -2780,6 +2780,15 @@ var CTYPE_XML_ROOT = writextag('Types', null, {
|
|||
var CTYPE_DEFAULTS = [
|
||||
['xml', 'application/xml'],
|
||||
['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
|
||||
/* from test files */
|
||||
['bmp', 'image/bmp'],
|
||||
['png', 'image/png'],
|
||||
['gif', 'image/gif'],
|
||||
['emf', 'image/x-emf'],
|
||||
['wmf', 'image/x-wmf'],
|
||||
['jpg', 'image/jpeg'], ['jpeg', 'image/jpeg'],
|
||||
['tif', 'image/tiff'], ['tiff', 'image/tiff'],
|
||||
['pdf', 'application/pdf'],
|
||||
['rels', type2ct.rels[0]]
|
||||
].map(function(x) {
|
||||
return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
|
||||
|
@ -2821,6 +2830,7 @@ function write_ct(ct, opts)/*:string*/ {
|
|||
['strs', 'styles'].forEach(f1);
|
||||
['coreprops', 'extprops', 'custprops'].forEach(f3);
|
||||
f3('vba');
|
||||
f3('comments');
|
||||
if(o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
|
||||
return o.join("");
|
||||
}
|
||||
|
@ -3128,7 +3138,7 @@ function parse_cust_props(data/*:string*/, opts) {
|
|||
var type = toks[0].substring(4), text = toks[1];
|
||||
/* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */
|
||||
switch(type) {
|
||||
case 'lpstr': case 'lpwstr': case 'bstr': case 'lpwstr':
|
||||
case 'lpstr': case 'bstr': case 'lpwstr':
|
||||
p[name] = unescapexml(text);
|
||||
break;
|
||||
case 'bool':
|
||||
|
@ -5393,7 +5403,7 @@ function rgb_tint(hex, tint) {
|
|||
|
||||
/* 18.3.1.13 width calculations */
|
||||
/* [MS-OI29500] 2.1.595 Column Width & Formatting */
|
||||
var DEF_MDW = 7, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
|
||||
var DEF_MDW = 6, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
|
||||
function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); }
|
||||
function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; }
|
||||
function char2width(chr) { return (Math.round((chr * MDW + 5)/MDW*256))/256; }
|
||||
|
@ -5527,8 +5537,8 @@ function parse_fills(t, styles, themes, opts) {
|
|||
case '</fill>': styles.Fills.push(fill); fill = {}; break;
|
||||
|
||||
/* 18.8.24 gradientFill CT_GradientFill */
|
||||
case '<fill>': break;
|
||||
case '</fill>': styles.Fills.push(fill); fill = {}; break;
|
||||
case '<gradientFill>': break;
|
||||
case '</gradientFill>': styles.Fills.push(fill); fill = {}; break;
|
||||
|
||||
/* 18.8.32 patternFill CT_PatternFill */
|
||||
case '<patternFill': case '<patternFill>':
|
||||
|
@ -8812,6 +8822,18 @@ function get_sst_id(sst/*:SST*/, str/*:string*/)/*:number*/ {
|
|||
sst[len] = {t:str}; sst.Count ++; sst.Unique ++; return len;
|
||||
}
|
||||
|
||||
function col_obj_w(C/*:number*/, col) {
|
||||
var p = ({min:C+1,max:C+1}/*:any*/);
|
||||
/* wch (chars), wpx (pixels) */
|
||||
var width = -1;
|
||||
if(col.MDW) MDW = col.MDW;
|
||||
if(col.width != null) p.customWidth = 1;
|
||||
else if(col.wpx != null) width = px2char(col.wpx);
|
||||
else if(col.wch != null) width = col.wch;
|
||||
if(width > -1) { p.width = char2width(width); p.customWidth = 1; }
|
||||
return p;
|
||||
}
|
||||
|
||||
function get_cell_style(styles, cell, opts) {
|
||||
var z = opts.revssf[cell.z != null ? cell.z : "General"];
|
||||
for(var i = 0, len = styles.length; i != len; ++i) if(styles[i].numFmtId === z) return i;
|
||||
|
@ -8932,7 +8954,7 @@ function write_ws_xml_merges(merges) {
|
|||
return o + '</mergeCells>';
|
||||
}
|
||||
|
||||
function parse_ws_xml_hlinks(s, data, rels) {
|
||||
function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
|
||||
for(var i = 0; i != data.length; ++i) {
|
||||
var val = parsexmltag(data[i], true);
|
||||
if(!val.ref) return;
|
||||
|
@ -8946,6 +8968,7 @@ function parse_ws_xml_hlinks(s, data, rels) {
|
|||
rel = {Target: val.location, TargetMode: 'Internal'};
|
||||
val.Rel = rel;
|
||||
}
|
||||
if(val.tooltip) { val.Tooltip = val.tooltip; delete val.tooltip; }
|
||||
var rng = safe_decode_range(val.ref);
|
||||
for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
|
||||
var addr = encode_cell({c:C,r:R});
|
||||
|
@ -8971,15 +8994,7 @@ function write_ws_xml_cols(ws, cols)/*:string*/ {
|
|||
var o = ["<cols>"], col, width;
|
||||
for(var i = 0; i != cols.length; ++i) {
|
||||
if(!(col = cols[i])) continue;
|
||||
var p = ({min:i+1,max:i+1}/*:any*/);
|
||||
/* wch (chars), wpx (pixels) */
|
||||
width = -1;
|
||||
if(col.MDW) MDW = col.MDW;
|
||||
if(col.width);
|
||||
else if(col.wpx) width = px2char(col.wpx);
|
||||
else if(col.wch) width = col.wch;
|
||||
if(width > -1) { p.width = char2width(width); p.customWidth= 1; }
|
||||
o[o.length] = (writextag('col', null, p));
|
||||
o[o.length] = (writextag('col', null, col_obj_w(i, col)));
|
||||
}
|
||||
o[o.length] = "</cols>";
|
||||
return o.join("");
|
||||
|
@ -9190,15 +9205,17 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ {
|
|||
|
||||
if(ws['!cols'] !== undefined && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols']));
|
||||
o[sidx = o.length] = '<sheetData/>';
|
||||
if(ws['!ref'] !== undefined) {
|
||||
if(ws['!ref'] != null) {
|
||||
rdata = write_ws_xml_data(ws, opts, idx, wb);
|
||||
if(rdata.length > 0) o[o.length] = (rdata);
|
||||
}
|
||||
if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
|
||||
|
||||
if(ws['!merges'] !== undefined && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
|
||||
if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
|
||||
|
||||
if(o.length>2) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
|
||||
|
||||
delete ws['!links'];
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
|
@ -9429,7 +9446,7 @@ function parse_BrtHLink(data, length, opts) {
|
|||
var tooltip = parse_XLWideString(data);
|
||||
var display = parse_XLWideString(data);
|
||||
data.l = end;
|
||||
return {rfx:rfx, relId:relId, loc:loc, tooltip:tooltip, display:display};
|
||||
return {rfx:rfx, relId:relId, loc:loc, Tooltip:tooltip, display:display};
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.6 BrtArrFmla */
|
||||
|
@ -9458,6 +9475,20 @@ function parse_BrtShrFmla(data, length, opts) {
|
|||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.323 BrtColInfo */
|
||||
/* TODO: once XLS ColInfo is set, combine the functions */
|
||||
function write_BrtColInfo(C/*:number*/, col, o) {
|
||||
if(o == null) o = new_buf(18);
|
||||
var p = col_obj_w(C, col);
|
||||
o.write_shift(-4, C);
|
||||
o.write_shift(-4, C);
|
||||
o.write_shift(4, p.width * 256);
|
||||
o.write_shift(4, 0/*ixfe*/); // style
|
||||
o.write_shift(1, 2); // bit flag
|
||||
o.write_shift(1, 0); // bit flag
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.61 Worksheet */
|
||||
function parse_ws_bin(data, opts, rels, wb, themes, styles)/*:Worksheet*/ {
|
||||
if(!data) return data;
|
||||
|
@ -9724,9 +9755,15 @@ function parse_ws_bin(data, opts, rels, wb, themes, styles)/*:Worksheet*/ {
|
|||
/* TODO: something useful -- this is a stub */
|
||||
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) {
|
||||
if(cell.v === undefined) return "";
|
||||
var vv = "";
|
||||
var vv = ""; var olddate = null;
|
||||
switch(cell.t) {
|
||||
case 'b': vv = cell.v ? "1" : "0"; break;
|
||||
case 'd': // no BrtCellDate :(
|
||||
cell.z = cell.z || SSF._table[14];
|
||||
olddate = cell.v;
|
||||
cell.v = datenum((cell.v/*:any*/)); cell.t = 'n';
|
||||
break;
|
||||
/* falls through */
|
||||
case 'n': case 'e': vv = ''+cell.v; break;
|
||||
default: vv = cell.v; break;
|
||||
}
|
||||
|
@ -9736,7 +9773,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
|
|||
switch(cell.t) {
|
||||
case 's': case 'str':
|
||||
if(opts.bookSST) {
|
||||
vv = get_sst_id(opts.Strings, cell.v);
|
||||
vv = get_sst_id(opts.Strings, (cell.v/*:any*/));
|
||||
o.t = "s"; o.v = vv;
|
||||
write_record(ba, "BrtCellIsst", write_BrtCellIsst(cell, o));
|
||||
} else {
|
||||
|
@ -9748,6 +9785,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
|
|||
/* TODO: determine threshold for Real vs RK */
|
||||
if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o));
|
||||
else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o));
|
||||
if(olddate) { cell.t = 'd'; cell.v = olddate; }
|
||||
return;
|
||||
case 'b':
|
||||
o.t = "b";
|
||||
|
@ -9758,7 +9796,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
|
|||
write_record(ba, "BrtCellBlank", write_BrtCellBlank(cell, o));
|
||||
}
|
||||
|
||||
function write_CELLTABLE(ba, ws, idx, opts, wb) {
|
||||
function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = [];
|
||||
write_record(ba, 'BrtBeginSheetData');
|
||||
for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
|
@ -9785,6 +9823,13 @@ function write_MERGECELLS(ba, ws/*:Worksheet*/) {
|
|||
write_record(ba, 'BrtEndMergeCells');
|
||||
}
|
||||
|
||||
function write_COLINFOS(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
if(!ws || !ws['!cols']) return;
|
||||
write_record(ba, 'BrtBeginColInfos');
|
||||
ws['!cols'].forEach(function(m, i) { if(m) write_record(ba, 'BrtColInfo', write_BrtColInfo(i, m)); });
|
||||
write_record(ba, 'BrtEndColInfos');
|
||||
}
|
||||
|
||||
function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
var ba = buf_array();
|
||||
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
|
||||
|
@ -9794,7 +9839,7 @@ function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/) {
|
|||
write_record(ba, "BrtWsDim", write_BrtWsDim(r));
|
||||
/* [WSVIEWS2] */
|
||||
/* [WSFMTINFO] */
|
||||
/* *COLINFOS */
|
||||
write_COLINFOS(ba, ws, idx, opts, wb);
|
||||
write_CELLTABLE(ba, ws, idx, opts, wb);
|
||||
/* [BrtSheetCalcProp] */
|
||||
/* [[BrtSheetProtectionIso] BrtSheetProtection] */
|
||||
|
@ -10674,8 +10719,8 @@ function parse_xlml_xml(d, opts)/*:Workbook*/ {
|
|||
if(comments.length > 0) cell.c = comments;
|
||||
if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== undefined) cursheet[encode_col(c) + encode_row(r)] = cell;
|
||||
if(cell.HRef) {
|
||||
cell.l = {Target:cell.HRef, tooltip:cell.HRefScreenTip};
|
||||
cell.HRef = cell.HRefScreenTip = undefined;
|
||||
cell.l = {Target:cell.HRef, Tooltip:cell.HRefScreenTip};
|
||||
delete cell.HRef; delete cell.HRefScreenTip;
|
||||
}
|
||||
if(cell.MergeAcross || cell.MergeDown) {
|
||||
var cc = c + (parseInt(cell.MergeAcross,10)|0);
|
||||
|
@ -11262,6 +11307,11 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
|
|||
attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]");
|
||||
}
|
||||
|
||||
if(cell.l && cell.l.Target) {
|
||||
attr["ss:HRef"] = escapexml(cell.l.Target);
|
||||
if(cell.l.Tooltip) attr["x:HRefScreenTip"] = escapexml(cell.l.Tooltip);
|
||||
}
|
||||
|
||||
if(ws['!merges']) {
|
||||
var marr = ws['!merges'];
|
||||
for(var mi = 0; mi != marr.length; ++mi) {
|
||||
|
@ -11297,6 +11347,10 @@ function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbo
|
|||
var range = safe_decode_range(ws['!ref']);
|
||||
var marr = ws['!merges'] || [], mi = 0;
|
||||
var o = [];
|
||||
if(ws['!cols']) ws['!cols'].forEach(function(n, i) {
|
||||
var p = col_obj_w(i, n);
|
||||
o.push(writextag("Column",null, {"ss:Index":i+1, "ss:Width":width2px(p.width)}));
|
||||
});
|
||||
for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
var row = ['<Row ss:Index="' + (R+1) + '">'];
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) {
|
||||
|
@ -11780,7 +11834,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
|||
for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
|
||||
for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC)
|
||||
if(out[encode_cell({c:rngC,r:rngR})])
|
||||
out[encode_cell({c:rngC,r:rngR})].l.tooltip = val[1];
|
||||
out[encode_cell({c:rngC,r:rngR})].l.Tooltip = val[1];
|
||||
} break;
|
||||
|
||||
/* Comments */
|
||||
|
|
102
xlsx.js
102
xlsx.js
|
@ -5,7 +5,7 @@
|
|||
/*exported XLSX */
|
||||
var XLSX = {};
|
||||
(function make_xlsx(XLSX){
|
||||
XLSX.version = '0.9.6';
|
||||
XLSX.version = '0.9.7';
|
||||
var current_codepage = 1200, current_cptable;
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
|
||||
if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel.js');
|
||||
|
@ -1781,7 +1781,7 @@ function ReadShift(size, t) {
|
|||
case 'cstr': size = 0; o = "";
|
||||
while((w=__readUInt8(this, this.l + size++))!==0) oo.push(_getchar(w));
|
||||
o = oo.join(""); break;
|
||||
case 'wstr': size = 0; o = "";
|
||||
case '_wstr': size = 0; o = "";
|
||||
while((w=__readUInt16LE(this,this.l +size))!==0){oo.push(_getchar(w));size+=2;}
|
||||
size+=2; o = oo.join(""); break;
|
||||
|
||||
|
@ -2728,6 +2728,15 @@ var CTYPE_XML_ROOT = writextag('Types', null, {
|
|||
var CTYPE_DEFAULTS = [
|
||||
['xml', 'application/xml'],
|
||||
['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
|
||||
/* from test files */
|
||||
['bmp', 'image/bmp'],
|
||||
['png', 'image/png'],
|
||||
['gif', 'image/gif'],
|
||||
['emf', 'image/x-emf'],
|
||||
['wmf', 'image/x-wmf'],
|
||||
['jpg', 'image/jpeg'], ['jpeg', 'image/jpeg'],
|
||||
['tif', 'image/tiff'], ['tiff', 'image/tiff'],
|
||||
['pdf', 'application/pdf'],
|
||||
['rels', type2ct.rels[0]]
|
||||
].map(function(x) {
|
||||
return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
|
||||
|
@ -2769,6 +2778,7 @@ function write_ct(ct, opts) {
|
|||
['strs', 'styles'].forEach(f1);
|
||||
['coreprops', 'extprops', 'custprops'].forEach(f3);
|
||||
f3('vba');
|
||||
f3('comments');
|
||||
if(o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
|
||||
return o.join("");
|
||||
}
|
||||
|
@ -3076,7 +3086,7 @@ function parse_cust_props(data, opts) {
|
|||
var type = toks[0].substring(4), text = toks[1];
|
||||
/* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */
|
||||
switch(type) {
|
||||
case 'lpstr': case 'lpwstr': case 'bstr': case 'lpwstr':
|
||||
case 'lpstr': case 'bstr': case 'lpwstr':
|
||||
p[name] = unescapexml(text);
|
||||
break;
|
||||
case 'bool':
|
||||
|
@ -5339,7 +5349,7 @@ function rgb_tint(hex, tint) {
|
|||
|
||||
/* 18.3.1.13 width calculations */
|
||||
/* [MS-OI29500] 2.1.595 Column Width & Formatting */
|
||||
var DEF_MDW = 7, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
|
||||
var DEF_MDW = 6, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
|
||||
function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); }
|
||||
function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; }
|
||||
function char2width(chr) { return (Math.round((chr * MDW + 5)/MDW*256))/256; }
|
||||
|
@ -5473,8 +5483,8 @@ function parse_fills(t, styles, themes, opts) {
|
|||
case '</fill>': styles.Fills.push(fill); fill = {}; break;
|
||||
|
||||
/* 18.8.24 gradientFill CT_GradientFill */
|
||||
case '<fill>': break;
|
||||
case '</fill>': styles.Fills.push(fill); fill = {}; break;
|
||||
case '<gradientFill>': break;
|
||||
case '</gradientFill>': styles.Fills.push(fill); fill = {}; break;
|
||||
|
||||
/* 18.8.32 patternFill CT_PatternFill */
|
||||
case '<patternFill': case '<patternFill>':
|
||||
|
@ -8757,6 +8767,18 @@ function get_sst_id(sst, str) {
|
|||
sst[len] = {t:str}; sst.Count ++; sst.Unique ++; return len;
|
||||
}
|
||||
|
||||
function col_obj_w(C, col) {
|
||||
var p = ({min:C+1,max:C+1});
|
||||
/* wch (chars), wpx (pixels) */
|
||||
var width = -1;
|
||||
if(col.MDW) MDW = col.MDW;
|
||||
if(col.width != null) p.customWidth = 1;
|
||||
else if(col.wpx != null) width = px2char(col.wpx);
|
||||
else if(col.wch != null) width = col.wch;
|
||||
if(width > -1) { p.width = char2width(width); p.customWidth = 1; }
|
||||
return p;
|
||||
}
|
||||
|
||||
function get_cell_style(styles, cell, opts) {
|
||||
var z = opts.revssf[cell.z != null ? cell.z : "General"];
|
||||
for(var i = 0, len = styles.length; i != len; ++i) if(styles[i].numFmtId === z) return i;
|
||||
|
@ -8891,6 +8913,7 @@ function parse_ws_xml_hlinks(s, data, rels) {
|
|||
rel = {Target: val.location, TargetMode: 'Internal'};
|
||||
val.Rel = rel;
|
||||
}
|
||||
if(val.tooltip) { val.Tooltip = val.tooltip; delete val.tooltip; }
|
||||
var rng = safe_decode_range(val.ref);
|
||||
for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
|
||||
var addr = encode_cell({c:C,r:R});
|
||||
|
@ -8916,15 +8939,7 @@ function write_ws_xml_cols(ws, cols) {
|
|||
var o = ["<cols>"], col, width;
|
||||
for(var i = 0; i != cols.length; ++i) {
|
||||
if(!(col = cols[i])) continue;
|
||||
var p = ({min:i+1,max:i+1});
|
||||
/* wch (chars), wpx (pixels) */
|
||||
width = -1;
|
||||
if(col.MDW) MDW = col.MDW;
|
||||
if(col.width);
|
||||
else if(col.wpx) width = px2char(col.wpx);
|
||||
else if(col.wch) width = col.wch;
|
||||
if(width > -1) { p.width = char2width(width); p.customWidth= 1; }
|
||||
o[o.length] = (writextag('col', null, p));
|
||||
o[o.length] = (writextag('col', null, col_obj_w(i, col)));
|
||||
}
|
||||
o[o.length] = "</cols>";
|
||||
return o.join("");
|
||||
|
@ -9135,15 +9150,17 @@ function write_ws_xml(idx, opts, wb) {
|
|||
|
||||
if(ws['!cols'] !== undefined && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols']));
|
||||
o[sidx = o.length] = '<sheetData/>';
|
||||
if(ws['!ref'] !== undefined) {
|
||||
if(ws['!ref'] != null) {
|
||||
rdata = write_ws_xml_data(ws, opts, idx, wb);
|
||||
if(rdata.length > 0) o[o.length] = (rdata);
|
||||
}
|
||||
if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
|
||||
|
||||
if(ws['!merges'] !== undefined && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
|
||||
if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
|
||||
|
||||
if(o.length>2) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
|
||||
|
||||
delete ws['!links'];
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
|
@ -9374,7 +9391,7 @@ function parse_BrtHLink(data, length, opts) {
|
|||
var tooltip = parse_XLWideString(data);
|
||||
var display = parse_XLWideString(data);
|
||||
data.l = end;
|
||||
return {rfx:rfx, relId:relId, loc:loc, tooltip:tooltip, display:display};
|
||||
return {rfx:rfx, relId:relId, loc:loc, Tooltip:tooltip, display:display};
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.6 BrtArrFmla */
|
||||
|
@ -9403,6 +9420,20 @@ function parse_BrtShrFmla(data, length, opts) {
|
|||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.323 BrtColInfo */
|
||||
/* TODO: once XLS ColInfo is set, combine the functions */
|
||||
function write_BrtColInfo(C, col, o) {
|
||||
if(o == null) o = new_buf(18);
|
||||
var p = col_obj_w(C, col);
|
||||
o.write_shift(-4, C);
|
||||
o.write_shift(-4, C);
|
||||
o.write_shift(4, p.width * 256);
|
||||
o.write_shift(4, 0/*ixfe*/); // style
|
||||
o.write_shift(1, 2); // bit flag
|
||||
o.write_shift(1, 0); // bit flag
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.61 Worksheet */
|
||||
function parse_ws_bin(data, opts, rels, wb, themes, styles) {
|
||||
if(!data) return data;
|
||||
|
@ -9669,9 +9700,15 @@ function parse_ws_bin(data, opts, rels, wb, themes, styles) {
|
|||
/* TODO: something useful -- this is a stub */
|
||||
function write_ws_bin_cell(ba, cell, R, C, opts) {
|
||||
if(cell.v === undefined) return "";
|
||||
var vv = "";
|
||||
var vv = ""; var olddate = null;
|
||||
switch(cell.t) {
|
||||
case 'b': vv = cell.v ? "1" : "0"; break;
|
||||
case 'd': // no BrtCellDate :(
|
||||
cell.z = cell.z || SSF._table[14];
|
||||
olddate = cell.v;
|
||||
cell.v = datenum((cell.v)); cell.t = 'n';
|
||||
break;
|
||||
/* falls through */
|
||||
case 'n': case 'e': vv = ''+cell.v; break;
|
||||
default: vv = cell.v; break;
|
||||
}
|
||||
|
@ -9681,7 +9718,7 @@ function write_ws_bin_cell(ba, cell, R, C, opts) {
|
|||
switch(cell.t) {
|
||||
case 's': case 'str':
|
||||
if(opts.bookSST) {
|
||||
vv = get_sst_id(opts.Strings, cell.v);
|
||||
vv = get_sst_id(opts.Strings, (cell.v));
|
||||
o.t = "s"; o.v = vv;
|
||||
write_record(ba, "BrtCellIsst", write_BrtCellIsst(cell, o));
|
||||
} else {
|
||||
|
@ -9693,6 +9730,7 @@ function write_ws_bin_cell(ba, cell, R, C, opts) {
|
|||
/* TODO: determine threshold for Real vs RK */
|
||||
if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o));
|
||||
else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o));
|
||||
if(olddate) { cell.t = 'd'; cell.v = olddate; }
|
||||
return;
|
||||
case 'b':
|
||||
o.t = "b";
|
||||
|
@ -9730,6 +9768,13 @@ function write_MERGECELLS(ba, ws) {
|
|||
write_record(ba, 'BrtEndMergeCells');
|
||||
}
|
||||
|
||||
function write_COLINFOS(ba, ws, idx, opts, wb) {
|
||||
if(!ws || !ws['!cols']) return;
|
||||
write_record(ba, 'BrtBeginColInfos');
|
||||
ws['!cols'].forEach(function(m, i) { if(m) write_record(ba, 'BrtColInfo', write_BrtColInfo(i, m)); });
|
||||
write_record(ba, 'BrtEndColInfos');
|
||||
}
|
||||
|
||||
function write_ws_bin(idx, opts, wb) {
|
||||
var ba = buf_array();
|
||||
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
|
||||
|
@ -9739,7 +9784,7 @@ function write_ws_bin(idx, opts, wb) {
|
|||
write_record(ba, "BrtWsDim", write_BrtWsDim(r));
|
||||
/* [WSVIEWS2] */
|
||||
/* [WSFMTINFO] */
|
||||
/* *COLINFOS */
|
||||
write_COLINFOS(ba, ws, idx, opts, wb);
|
||||
write_CELLTABLE(ba, ws, idx, opts, wb);
|
||||
/* [BrtSheetCalcProp] */
|
||||
/* [[BrtSheetProtectionIso] BrtSheetProtection] */
|
||||
|
@ -10617,8 +10662,8 @@ function parse_xlml_xml(d, opts) {
|
|||
if(comments.length > 0) cell.c = comments;
|
||||
if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== undefined) cursheet[encode_col(c) + encode_row(r)] = cell;
|
||||
if(cell.HRef) {
|
||||
cell.l = {Target:cell.HRef, tooltip:cell.HRefScreenTip};
|
||||
cell.HRef = cell.HRefScreenTip = undefined;
|
||||
cell.l = {Target:cell.HRef, Tooltip:cell.HRefScreenTip};
|
||||
delete cell.HRef; delete cell.HRefScreenTip;
|
||||
}
|
||||
if(cell.MergeAcross || cell.MergeDown) {
|
||||
var cc = c + (parseInt(cell.MergeAcross,10)|0);
|
||||
|
@ -11203,6 +11248,11 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){
|
|||
attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]");
|
||||
}
|
||||
|
||||
if(cell.l && cell.l.Target) {
|
||||
attr["ss:HRef"] = escapexml(cell.l.Target);
|
||||
if(cell.l.Tooltip) attr["x:HRefScreenTip"] = escapexml(cell.l.Tooltip);
|
||||
}
|
||||
|
||||
if(ws['!merges']) {
|
||||
var marr = ws['!merges'];
|
||||
for(var mi = 0; mi != marr.length; ++mi) {
|
||||
|
@ -11238,6 +11288,10 @@ function write_ws_xlml_table(ws, opts, idx, wb) {
|
|||
var range = safe_decode_range(ws['!ref']);
|
||||
var marr = ws['!merges'] || [], mi = 0;
|
||||
var o = [];
|
||||
if(ws['!cols']) ws['!cols'].forEach(function(n, i) {
|
||||
var p = col_obj_w(i, n);
|
||||
o.push(writextag("Column",null, {"ss:Index":i+1, "ss:Width":width2px(p.width)}));
|
||||
});
|
||||
for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
var row = ['<Row ss:Index="' + (R+1) + '">'];
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) {
|
||||
|
@ -11721,7 +11775,7 @@ function parse_workbook(blob, options) {
|
|||
for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
|
||||
for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC)
|
||||
if(out[encode_cell({c:rngC,r:rngR})])
|
||||
out[encode_cell({c:rngC,r:rngR})].l.tooltip = val[1];
|
||||
out[encode_cell({c:rngC,r:rngR})].l.Tooltip = val[1];
|
||||
} break;
|
||||
|
||||
/* Comments */
|
||||
|
|
Loading…
Reference in New Issue