version bump 0.12.11: file format range limits

This commit is contained in:
SheetJS 2018-04-27 16:11:18 -04:00
parent 75c49ddbe8
commit eb5fc87be4
26 changed files with 323 additions and 70 deletions

View File

@ -1,5 +1,6 @@
language: node_js
node_js:
- "10"
- "9"
- "8"
- "7"

View File

@ -4,6 +4,10 @@ This log is intended to keep track of backwards-incompatible changes, including
but not limited to API changes and file location changes. Minor behavioral
changes may not be included if they are not expected to break existing code.
## 0.12.11 (2018-04-27)
* XLS/XLSX/XLSB range truncation (errors in `WTF` mode)
## 0.12.4 (2018-03-04)
* `JSZip` renamed to `JSZipSync`

View File

@ -2286,6 +2286,20 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
| Rich Text Format tables (RTF) | | :o: |
| Ethercalc Record Format (ETH) | :o: | :o: |
Features not supported by a given file format will not be written. Formats with
range limits will be silently truncated:
| Format | Last Cell | Max Cols | Max Rows |
|:------------------------------------------|:-----------|---------:|---------:|
| Excel 2007+ XML Formats (XLSX/XLSM) | XFD1048576 | 16384 | 1048576 |
| Excel 2007+ Binary Format (XLSB BIFF12) | XFD1048576 | 16384 | 1048576 |
| Excel 97-2004 (XLS BIFF8) | IV65536 | 256 | 65536 |
| Excel 5.0/95 (XLS BIFF5) | IV16384 | 256 | 16384 |
| Excel 2.0/2.1 (XLS BIFF2) | IV16384 | 256 | 16384 |
Excel 2003 SpreadsheetML range limits are governed by the version of Excel and
are not enforced by the writer.
### Excel 2007+ XML (XLSX/XLSM)
<details>

View File

@ -1 +1 @@
XLSX.version = '0.12.10';
XLSX.version = '0.12.11';

View File

@ -99,3 +99,10 @@ function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, the
}
} catch(e) { if(opts.WTF && styles.Fills) throw e; }
}
function check_ws(ws/*:Worksheet*/, sname/*:string*/, i/*:number*/) {
if(ws && ws['!ref']) {
var range = safe_decode_range(ws['!ref']);
if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
}
}

View File

@ -469,7 +469,14 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
var s = wb.SheetNames[idx], sidx = 0, rdata = "";
var ws = wb.Sheets[s];
if(ws == null) ws = {};
var ref = ws['!ref']; if(ref == null) ref = 'A1';
var ref = ws['!ref'] || 'A1';
var range = safe_decode_range(ref);
if(range.e.c > 0x3FFF || range.e.r > 0xFFFFF) {
if(opts.WTF) throw new Error("Range " + ref + " exceeds format limit A1:XFD1048576");
range.e.c = Math.min(range.e.c, 0x3FFF);
range.e.r = Math.min(range.e.c, 0xFFFFF);
ref = encode_range(range);
}
if(!rels) rels = {};
ws['!comments'] = [];
ws['!drawing'] = [];

View File

@ -809,6 +809,11 @@ function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
var c/*:string*/ = s; try { if(wb && wb.Workbook) c = wb.Workbook.Sheets[idx].CodeName || c; } catch(e) {}
var r = safe_decode_range(ws['!ref'] || "A1");
if(r.e.c > 0x3FFF || r.e.r > 0xFFFFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:XFD1048576");
r.e.c = Math.min(r.e.c, 0x3FFF);
r.e.r = Math.min(r.e.c, 0xFFFFF);
}
ws['!links'] = [];
/* passed back to write_zip and removed there */
ws['!comments'] = [];

View File

@ -139,5 +139,6 @@ function check_wb(wb) {
if(!wb.SheetNames.length) throw new Error("Workbook is empty");
var Sheets = (wb.Workbook && wb.Workbook.Sheets) || [];
check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i);
/* TODO: validate workbook */
}

View File

@ -46,7 +46,7 @@ function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
/* 18.2.1 bookViews CT_BookViews ? */
case '<bookViews': case '<bookViews>': case '</bookViews>': break;
/* 18.2.30 workbookView CT_BookView + */
case '<workbookView': delete y[0]; wb.WBView.push(y); break;
case '<workbookView': case '<workbookView/>': delete y[0]; wb.WBView.push(y); break;
case '</workbookView>': break;
/* 18.2.20 sheets CT_Sheets 1 */

View File

@ -55,6 +55,12 @@ function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n
function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
var dense = Array.isArray(ws);
var range = safe_decode_range(ws['!ref'] || "A1"), ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
range.e.r = Math.min(range.e.c, 0x3FFF);
ref = encode_range(range);
}
for(var R = range.s.r; R <= range.e.r; ++R) {
rr = encode_row(R);
for(var C = range.s.c; C <= range.e.c; ++C) {
@ -159,9 +165,16 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
var _WB/*:WBWBProps*/ = ((wb||{}).Workbook||{}/*:any*/);
var _sheet/*:WBWSProp*/ = ((_WB.Sheets||[])[idx]||{}/*:any*/);
var dense = Array.isArray(ws);
var b8 = opts.biff == 8;
var ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
var range = safe_decode_range(ws['!ref'] || "A1");
var b8 = opts.biff == 8;
var MAX_ROWS = b8 ? 65536 : 16384;
if(range.e.c > 0xFF || range.e.r >= MAX_ROWS) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
range.e.r = Math.min(range.e.c, MAX_ROWS-1);
}
write_biff_rec(ba, 0x0809, write_BOF(wb, 0x10, opts));
/* ... */
write_biff_rec(ba, "CalcMode", writeuint16(1));

View File

@ -9,7 +9,8 @@ function get_data(req, res, type) {
var work = new Worker('worker.js');
work.onmessage = function(e) {
if(e.data.err) console.log(e.data.err);
return res(e.data.data);
var buf = new Buffer(e.data.data, "binary");
return res(buf);
};
work.postMessage({action:"write", type:type, data:data});
}

28
dist/xlsx.core.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.core.min.map generated vendored

File diff suppressed because one or more lines are too long

42
dist/xlsx.extendscript.js generated vendored
View File

@ -9147,7 +9147,7 @@ module.exports = ZStream;
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.12.10';
XLSX.version = '0.12.11';
var current_codepage = 1200, current_ansi = 1252;
/*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -13248,7 +13248,6 @@ function write_cust_props(cp) {
if(!cp) return o.join("");
var pid = 1;
keys(cp).forEach(function custprop(k) { ++pid;
// $FlowIgnore
o[o.length] = (writextag('property', write_vt(cp[k]), {
'fmtid': '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}',
'pid': pid,
@ -20971,6 +20970,13 @@ function safe_format(p, fmtid, fillid, opts, themes, styles) {
}
} catch(e) { if(opts.WTF && styles.Fills) throw e; }
}
function check_ws(ws, sname, i) {
if(ws && ws['!ref']) {
var range = safe_decode_range(ws['!ref']);
if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
}
}
function parse_ws_xml_dim(ws, s) {
var d = safe_decode_range(s);
if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d);
@ -21442,7 +21448,14 @@ function write_ws_xml(idx, opts, wb, rels) {
var s = wb.SheetNames[idx], sidx = 0, rdata = "";
var ws = wb.Sheets[s];
if(ws == null) ws = {};
var ref = ws['!ref']; if(ref == null) ref = 'A1';
var ref = ws['!ref'] || 'A1';
var range = safe_decode_range(ref);
if(range.e.c > 0x3FFF || range.e.r > 0xFFFFF) {
if(opts.WTF) throw new Error("Range " + ref + " exceeds format limit A1:XFD1048576");
range.e.c = Math.min(range.e.c, 0x3FFF);
range.e.r = Math.min(range.e.c, 0xFFFFF);
ref = encode_range(range);
}
if(!rels) rels = {};
ws['!comments'] = [];
ws['!drawing'] = [];
@ -22360,6 +22373,11 @@ function write_ws_bin(idx, opts, wb, rels) {
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
var c = s; try { if(wb && wb.Workbook) c = wb.Workbook.Sheets[idx].CodeName || c; } catch(e) {}
var r = safe_decode_range(ws['!ref'] || "A1");
if(r.e.c > 0x3FFF || r.e.r > 0xFFFFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:XFD1048576");
r.e.c = Math.min(r.e.c, 0x3FFF);
r.e.r = Math.min(r.e.c, 0xFFFFF);
}
ws['!links'] = [];
/* passed back to write_zip and removed there */
ws['!comments'] = [];
@ -22693,6 +22711,7 @@ function check_wb(wb) {
if(!wb.SheetNames.length) throw new Error("Workbook is empty");
var Sheets = (wb.Workbook && wb.Workbook.Sheets) || [];
check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i);
/* TODO: validate workbook */
}
/* 18.2 Workbook */
@ -22743,7 +22762,7 @@ function parse_wb_xml(data, opts) {
/* 18.2.1 bookViews CT_BookViews ? */
case '<bookViews': case '<bookViews>': case '</bookViews>': break;
/* 18.2.30 workbookView CT_BookView + */
case '<workbookView': delete y[0]; wb.WBView.push(y); break;
case '<workbookView': case '<workbookView/>': delete y[0]; wb.WBView.push(y); break;
case '</workbookView>': break;
/* 18.2.20 sheets CT_Sheets 1 */
@ -26689,6 +26708,12 @@ function write_ws_biff2_cell(ba, cell, R, C) {
function write_ws_biff2(ba, ws, idx, opts) {
var dense = Array.isArray(ws);
var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = [];
if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
range.e.r = Math.min(range.e.c, 0x3FFF);
ref = encode_range(range);
}
for(var R = range.s.r; R <= range.e.r; ++R) {
rr = encode_row(R);
for(var C = range.s.c; C <= range.e.c; ++C) {
@ -26792,9 +26817,16 @@ function write_ws_biff8(idx, opts, wb) {
var _WB = ((wb||{}).Workbook||{});
var _sheet = ((_WB.Sheets||[])[idx]||{});
var dense = Array.isArray(ws);
var b8 = opts.biff == 8;
var ref, rr = "", cols = [];
var range = safe_decode_range(ws['!ref'] || "A1");
var b8 = opts.biff == 8;
var MAX_ROWS = b8 ? 65536 : 16384;
if(range.e.c > 0xFF || range.e.r >= MAX_ROWS) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
range.e.r = Math.min(range.e.c, MAX_ROWS-1);
}
write_biff_rec(ba, 0x0809, write_BOF(wb, 0x10, opts));
/* ... */
write_biff_rec(ba, "CalcMode", writeuint16(1));

32
dist/xlsx.full.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.full.min.map generated vendored

File diff suppressed because one or more lines are too long

42
dist/xlsx.js generated vendored
View File

@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.12.10';
XLSX.version = '0.12.11';
var current_codepage = 1200, current_ansi = 1252;
/*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -4105,7 +4105,6 @@ function write_cust_props(cp) {
if(!cp) return o.join("");
var pid = 1;
keys(cp).forEach(function custprop(k) { ++pid;
// $FlowIgnore
o[o.length] = (writextag('property', write_vt(cp[k]), {
'fmtid': '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}',
'pid': pid,
@ -11828,6 +11827,13 @@ function safe_format(p, fmtid, fillid, opts, themes, styles) {
}
} catch(e) { if(opts.WTF && styles.Fills) throw e; }
}
function check_ws(ws, sname, i) {
if(ws && ws['!ref']) {
var range = safe_decode_range(ws['!ref']);
if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
}
}
function parse_ws_xml_dim(ws, s) {
var d = safe_decode_range(s);
if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d);
@ -12299,7 +12305,14 @@ function write_ws_xml(idx, opts, wb, rels) {
var s = wb.SheetNames[idx], sidx = 0, rdata = "";
var ws = wb.Sheets[s];
if(ws == null) ws = {};
var ref = ws['!ref']; if(ref == null) ref = 'A1';
var ref = ws['!ref'] || 'A1';
var range = safe_decode_range(ref);
if(range.e.c > 0x3FFF || range.e.r > 0xFFFFF) {
if(opts.WTF) throw new Error("Range " + ref + " exceeds format limit A1:XFD1048576");
range.e.c = Math.min(range.e.c, 0x3FFF);
range.e.r = Math.min(range.e.c, 0xFFFFF);
ref = encode_range(range);
}
if(!rels) rels = {};
ws['!comments'] = [];
ws['!drawing'] = [];
@ -13217,6 +13230,11 @@ function write_ws_bin(idx, opts, wb, rels) {
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
var c = s; try { if(wb && wb.Workbook) c = wb.Workbook.Sheets[idx].CodeName || c; } catch(e) {}
var r = safe_decode_range(ws['!ref'] || "A1");
if(r.e.c > 0x3FFF || r.e.r > 0xFFFFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:XFD1048576");
r.e.c = Math.min(r.e.c, 0x3FFF);
r.e.r = Math.min(r.e.c, 0xFFFFF);
}
ws['!links'] = [];
/* passed back to write_zip and removed there */
ws['!comments'] = [];
@ -13550,6 +13568,7 @@ function check_wb(wb) {
if(!wb.SheetNames.length) throw new Error("Workbook is empty");
var Sheets = (wb.Workbook && wb.Workbook.Sheets) || [];
check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i);
/* TODO: validate workbook */
}
/* 18.2 Workbook */
@ -13600,7 +13619,7 @@ function parse_wb_xml(data, opts) {
/* 18.2.1 bookViews CT_BookViews ? */
case '<bookViews': case '<bookViews>': case '</bookViews>': break;
/* 18.2.30 workbookView CT_BookView + */
case '<workbookView': delete y[0]; wb.WBView.push(y); break;
case '<workbookView': case '<workbookView/>': delete y[0]; wb.WBView.push(y); break;
case '</workbookView>': break;
/* 18.2.20 sheets CT_Sheets 1 */
@ -17546,6 +17565,12 @@ function write_ws_biff2_cell(ba, cell, R, C) {
function write_ws_biff2(ba, ws, idx, opts) {
var dense = Array.isArray(ws);
var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = [];
if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
range.e.r = Math.min(range.e.c, 0x3FFF);
ref = encode_range(range);
}
for(var R = range.s.r; R <= range.e.r; ++R) {
rr = encode_row(R);
for(var C = range.s.c; C <= range.e.c; ++C) {
@ -17649,9 +17674,16 @@ function write_ws_biff8(idx, opts, wb) {
var _WB = ((wb||{}).Workbook||{});
var _sheet = ((_WB.Sheets||[])[idx]||{});
var dense = Array.isArray(ws);
var b8 = opts.biff == 8;
var ref, rr = "", cols = [];
var range = safe_decode_range(ws['!ref'] || "A1");
var b8 = opts.biff == 8;
var MAX_ROWS = b8 ? 65536 : 16384;
if(range.e.c > 0xFF || range.e.r >= MAX_ROWS) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
range.e.r = Math.min(range.e.c, MAX_ROWS-1);
}
write_biff_rec(ba, 0x0809, write_BOF(wb, 0x10, opts));
/* ... */
write_biff_rec(ba, "CalcMode", writeuint16(1));

26
dist/xlsx.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.min.map generated vendored

File diff suppressed because one or more lines are too long

View File

@ -31,6 +31,20 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
| Rich Text Format tables (RTF) | | :o: |
| Ethercalc Record Format (ETH) | :o: | :o: |
Features not supported by a given file format will not be written. Formats with
range limits will be silently truncated:
| Format | Last Cell | Max Cols | Max Rows |
|:------------------------------------------|:-----------|---------:|---------:|
| Excel 2007+ XML Formats (XLSX/XLSM) | XFD1048576 | 16384 | 1048576 |
| Excel 2007+ Binary Format (XLSB BIFF12) | XFD1048576 | 16384 | 1048576 |
| Excel 97-2004 (XLS BIFF8) | IV65536 | 256 | 65536 |
| Excel 5.0/95 (XLS BIFF5) | IV16384 | 256 | 16384 |
| Excel 2.0/2.1 (XLS BIFF2) | IV16384 | 256 | 16384 |
Excel 2003 SpreadsheetML range limits are governed by the version of Excel and
are not enforced by the writer.
### Excel 2007+ XML (XLSX/XLSM)
<details>

View File

@ -2112,6 +2112,20 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
| Rich Text Format tables (RTF) | | :o: |
| Ethercalc Record Format (ETH) | :o: | :o: |
Features not supported by a given file format will not be written. Formats with
range limits will be silently truncated:
| Format | Last Cell | Max Cols | Max Rows |
|:------------------------------------------|:-----------|---------:|---------:|
| Excel 2007+ XML Formats (XLSX/XLSM) | XFD1048576 | 16384 | 1048576 |
| Excel 2007+ Binary Format (XLSB BIFF12) | XFD1048576 | 16384 | 1048576 |
| Excel 97-2004 (XLS BIFF8) | IV65536 | 256 | 65536 |
| Excel 5.0/95 (XLS BIFF5) | IV16384 | 256 | 16384 |
| Excel 2.0/2.1 (XLS BIFF2) | IV16384 | 256 | 16384 |
Excel 2003 SpreadsheetML range limits are governed by the version of Excel and
are not enforced by the writer.
### Excel 2007+ XML (XLSX/XLSM)

View File

@ -1,6 +1,6 @@
{
"name": "xlsx",
"version": "0.12.10",
"version": "0.12.11",
"author": "sheetjs",
"description": "SheetJS Spreadsheet data parser and writer",
"keywords": [

21
test.js
View File

@ -1326,6 +1326,27 @@ describe('write features', function() {
assert(str.indexOf("<b>abc</b>") > 0);
});
});
describe('sheet range limits', function() { [
["biff2", "IV16384"],
["biff5", "IV16384"],
["biff8", "IV65536"],
["xlsx", "XFD1048576"],
["xlsb", "XFD1048576"]
].forEach(function(r) { it(r[0], function() {
var C = X.utils.decode_cell(r[1]);
var wopts = {bookType:r[0], type:'binary', WTF:1};
var wb = { SheetNames: ["Sheet1"], Sheets: { Sheet1: {} } };
wb.Sheets.Sheet1['!ref'] = "A1:" + X.utils.encode_cell({r:0, c:C.c});
X.write(wb, wopts);
wb.Sheets.Sheet1['!ref'] = "A" + X.utils.encode_row(C.r - 5) + ":" + X.utils.encode_cell({r:C.r, c:0});
X.write(wb, wopts);
wb.Sheets.Sheet1['!ref'] = "A1:" + X.utils.encode_cell({r:0, c:C.c+1});
assert.throws(function() { X.write(wb, wopts); });
wb.Sheets.Sheet1['!ref'] = "A" + X.utils.encode_row(C.r - 5) + ":" + X.utils.encode_cell({r:C.r+1, c:0});
assert.throws(function() { X.write(wb, wopts); });
}); }); });
});
function seq(end/*:number*/, start/*:?number*/)/*:Array<number>*/ {

21
tests/core.js generated
View File

@ -1326,6 +1326,27 @@ describe('write features', function() {
assert(str.indexOf("<b>abc</b>") > 0);
});
});
describe('sheet range limits', function() { [
["biff2", "IV16384"],
["biff5", "IV16384"],
["biff8", "IV65536"],
["xlsx", "XFD1048576"],
["xlsb", "XFD1048576"]
].forEach(function(r) { it(r[0], function() {
var C = X.utils.decode_cell(r[1]);
var wopts = {bookType:r[0], type:'binary', WTF:1};
var wb = { SheetNames: ["Sheet1"], Sheets: { Sheet1: {} } };
wb.Sheets.Sheet1['!ref'] = "A1:" + X.utils.encode_cell({r:0, c:C.c});
X.write(wb, wopts);
wb.Sheets.Sheet1['!ref'] = "A" + X.utils.encode_row(C.r - 5) + ":" + X.utils.encode_cell({r:C.r, c:0});
X.write(wb, wopts);
wb.Sheets.Sheet1['!ref'] = "A1:" + X.utils.encode_cell({r:0, c:C.c+1});
assert.throws(function() { X.write(wb, wopts); });
wb.Sheets.Sheet1['!ref'] = "A" + X.utils.encode_row(C.r - 5) + ":" + X.utils.encode_cell({r:C.r+1, c:0});
assert.throws(function() { X.write(wb, wopts); });
}); }); });
});
function seq(end/*:number*/, start/*:?number*/)/*:Array<number>*/ {

View File

@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.12.10';
XLSX.version = '0.12.11';
var current_codepage = 1200, current_ansi = 1252;
/*:: declare var cptable:any; */
/*global cptable:true */
@ -11923,6 +11923,13 @@ function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, the
}
} catch(e) { if(opts.WTF && styles.Fills) throw e; }
}
function check_ws(ws/*:Worksheet*/, sname/*:string*/, i/*:number*/) {
if(ws && ws['!ref']) {
var range = safe_decode_range(ws['!ref']);
if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
}
}
function parse_ws_xml_dim(ws/*:Worksheet*/, s/*:string*/) {
var d = safe_decode_range(s);
if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d);
@ -12394,7 +12401,14 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
var s = wb.SheetNames[idx], sidx = 0, rdata = "";
var ws = wb.Sheets[s];
if(ws == null) ws = {};
var ref = ws['!ref']; if(ref == null) ref = 'A1';
var ref = ws['!ref'] || 'A1';
var range = safe_decode_range(ref);
if(range.e.c > 0x3FFF || range.e.r > 0xFFFFF) {
if(opts.WTF) throw new Error("Range " + ref + " exceeds format limit A1:XFD1048576");
range.e.c = Math.min(range.e.c, 0x3FFF);
range.e.r = Math.min(range.e.c, 0xFFFFF);
ref = encode_range(range);
}
if(!rels) rels = {};
ws['!comments'] = [];
ws['!drawing'] = [];
@ -13313,6 +13327,11 @@ function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
var c/*:string*/ = s; try { if(wb && wb.Workbook) c = wb.Workbook.Sheets[idx].CodeName || c; } catch(e) {}
var r = safe_decode_range(ws['!ref'] || "A1");
if(r.e.c > 0x3FFF || r.e.r > 0xFFFFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:XFD1048576");
r.e.c = Math.min(r.e.c, 0x3FFF);
r.e.r = Math.min(r.e.c, 0xFFFFF);
}
ws['!links'] = [];
/* passed back to write_zip and removed there */
ws['!comments'] = [];
@ -13646,6 +13665,7 @@ function check_wb(wb) {
if(!wb.SheetNames.length) throw new Error("Workbook is empty");
var Sheets = (wb.Workbook && wb.Workbook.Sheets) || [];
check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i);
/* TODO: validate workbook */
}
/* 18.2 Workbook */
@ -13696,7 +13716,7 @@ function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
/* 18.2.1 bookViews CT_BookViews ? */
case '<bookViews': case '<bookViews>': case '</bookViews>': break;
/* 18.2.30 workbookView CT_BookView + */
case '<workbookView': delete y[0]; wb.WBView.push(y); break;
case '<workbookView': case '<workbookView/>': delete y[0]; wb.WBView.push(y); break;
case '</workbookView>': break;
/* 18.2.20 sheets CT_Sheets 1 */
@ -17655,6 +17675,12 @@ function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n
function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
var dense = Array.isArray(ws);
var range = safe_decode_range(ws['!ref'] || "A1"), ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
range.e.r = Math.min(range.e.c, 0x3FFF);
ref = encode_range(range);
}
for(var R = range.s.r; R <= range.e.r; ++R) {
rr = encode_row(R);
for(var C = range.s.c; C <= range.e.c; ++C) {
@ -17759,9 +17785,16 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
var _WB/*:WBWBProps*/ = ((wb||{}).Workbook||{}/*:any*/);
var _sheet/*:WBWSProp*/ = ((_WB.Sheets||[])[idx]||{}/*:any*/);
var dense = Array.isArray(ws);
var b8 = opts.biff == 8;
var ref/*:string*/, rr = "", cols/*:Array<string>*/ = [];
var range = safe_decode_range(ws['!ref'] || "A1");
var b8 = opts.biff == 8;
var MAX_ROWS = b8 ? 65536 : 16384;
if(range.e.c > 0xFF || range.e.r >= MAX_ROWS) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
range.e.r = Math.min(range.e.c, MAX_ROWS-1);
}
write_biff_rec(ba, 0x0809, write_BOF(wb, 0x10, opts));
/* ... */
write_biff_rec(ba, "CalcMode", writeuint16(1));

41
xlsx.js generated
View File

@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.12.10';
XLSX.version = '0.12.11';
var current_codepage = 1200, current_ansi = 1252;
/*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -11827,6 +11827,13 @@ function safe_format(p, fmtid, fillid, opts, themes, styles) {
}
} catch(e) { if(opts.WTF && styles.Fills) throw e; }
}
function check_ws(ws, sname, i) {
if(ws && ws['!ref']) {
var range = safe_decode_range(ws['!ref']);
if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
}
}
function parse_ws_xml_dim(ws, s) {
var d = safe_decode_range(s);
if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d);
@ -12298,7 +12305,14 @@ function write_ws_xml(idx, opts, wb, rels) {
var s = wb.SheetNames[idx], sidx = 0, rdata = "";
var ws = wb.Sheets[s];
if(ws == null) ws = {};
var ref = ws['!ref']; if(ref == null) ref = 'A1';
var ref = ws['!ref'] || 'A1';
var range = safe_decode_range(ref);
if(range.e.c > 0x3FFF || range.e.r > 0xFFFFF) {
if(opts.WTF) throw new Error("Range " + ref + " exceeds format limit A1:XFD1048576");
range.e.c = Math.min(range.e.c, 0x3FFF);
range.e.r = Math.min(range.e.c, 0xFFFFF);
ref = encode_range(range);
}
if(!rels) rels = {};
ws['!comments'] = [];
ws['!drawing'] = [];
@ -13216,6 +13230,11 @@ function write_ws_bin(idx, opts, wb, rels) {
var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
var c = s; try { if(wb && wb.Workbook) c = wb.Workbook.Sheets[idx].CodeName || c; } catch(e) {}
var r = safe_decode_range(ws['!ref'] || "A1");
if(r.e.c > 0x3FFF || r.e.r > 0xFFFFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:XFD1048576");
r.e.c = Math.min(r.e.c, 0x3FFF);
r.e.r = Math.min(r.e.c, 0xFFFFF);
}
ws['!links'] = [];
/* passed back to write_zip and removed there */
ws['!comments'] = [];
@ -13549,6 +13568,7 @@ function check_wb(wb) {
if(!wb.SheetNames.length) throw new Error("Workbook is empty");
var Sheets = (wb.Workbook && wb.Workbook.Sheets) || [];
check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i);
/* TODO: validate workbook */
}
/* 18.2 Workbook */
@ -13599,7 +13619,7 @@ function parse_wb_xml(data, opts) {
/* 18.2.1 bookViews CT_BookViews ? */
case '<bookViews': case '<bookViews>': case '</bookViews>': break;
/* 18.2.30 workbookView CT_BookView + */
case '<workbookView': delete y[0]; wb.WBView.push(y); break;
case '<workbookView': case '<workbookView/>': delete y[0]; wb.WBView.push(y); break;
case '</workbookView>': break;
/* 18.2.20 sheets CT_Sheets 1 */
@ -17545,6 +17565,12 @@ function write_ws_biff2_cell(ba, cell, R, C) {
function write_ws_biff2(ba, ws, idx, opts) {
var dense = Array.isArray(ws);
var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = [];
if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
range.e.r = Math.min(range.e.c, 0x3FFF);
ref = encode_range(range);
}
for(var R = range.s.r; R <= range.e.r; ++R) {
rr = encode_row(R);
for(var C = range.s.c; C <= range.e.c; ++C) {
@ -17648,9 +17674,16 @@ function write_ws_biff8(idx, opts, wb) {
var _WB = ((wb||{}).Workbook||{});
var _sheet = ((_WB.Sheets||[])[idx]||{});
var dense = Array.isArray(ws);
var b8 = opts.biff == 8;
var ref, rr = "", cols = [];
var range = safe_decode_range(ws['!ref'] || "A1");
var b8 = opts.biff == 8;
var MAX_ROWS = b8 ? 65536 : 16384;
if(range.e.c > 0xFF || range.e.r >= MAX_ROWS) {
if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
range.e.c = Math.min(range.e.c, 0xFF);
range.e.r = Math.min(range.e.c, MAX_ROWS-1);
}
write_biff_rec(ba, 0x0809, write_BOF(wb, 0x10, opts));
/* ... */
write_biff_rec(ba, "CalcMode", writeuint16(1));