forked from sheetjs/sheetjs
version bump 0.11.17: sheet_add_{aoa,json}
- Skip extraneous trailing records (fixes #938 h/t @benjaminleetmaa) - XLS -> XLML oddities (fixes #678 h/t @buserror) - ionic demo - sheet_add_aoa and sheet_add_json Issues: - fixes #947 h/t @fpasxos - fixes #666 h/t @samuelkavin - fixes #301 h/t @acgentry - fixes #561 h/t @Ideandro
This commit is contained in:
parent
a7d3779724
commit
1d74977718
143
README.md
143
README.md
@ -190,7 +190,7 @@ The [`demos` directory](demos/) includes sample projects for:
|
||||
|
||||
**Frameworks and APIs**
|
||||
- [`angular 1.x`](demos/angular/)
|
||||
- [`angular 2.x / 4.x / 5.x`](demos/angular2/)
|
||||
- [`angular 2 / 4 / 5 and ionic`](demos/angular2/)
|
||||
- [`meteor`](demos/meteor/)
|
||||
- [`react and react-native`](demos/react/)
|
||||
- [`vue 2.x and weex`](demos/vue/)
|
||||
@ -721,6 +721,8 @@ Utilities are available in the `XLSX.utils` object and are described in the
|
||||
- `aoa_to_sheet` converts an array of arrays of JS data to a worksheet.
|
||||
- `json_to_sheet` converts an array of JS objects to a worksheet.
|
||||
- `table_to_sheet` converts a DOM TABLE element to a worksheet.
|
||||
- `sheet_add_aoa` adds an array of arrays of JS data to an existing worksheet.
|
||||
- `sheet_add_json` adds an array of JS objects to an existing worksheet.
|
||||
|
||||
|
||||
**Exporting:**
|
||||
@ -1742,6 +1744,61 @@ var ws = XLSX.utils.aoa_to_sheet([
|
||||
```
|
||||
</details>
|
||||
|
||||
`XLSX.utils.sheet_add_aoa` takes an array of arrays of JS values and updates an
|
||||
existing worksheet object. It follows the same process as `aoa_to_sheet` and
|
||||
accepts an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :------: | :-------------------------------------------------- |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`sheetStubs` | false | Create cell objects of type `z` for `null` values |
|
||||
|`origin` | | Use specified cell as starting point (see below) |
|
||||
|
||||
`origin` is expected to be one of:
|
||||
|
||||
| `origin` | Description |
|
||||
| :--------------- | :-------------------------------------------------------- |
|
||||
| (cell object) | Use specified cell (cell object) |
|
||||
| (string) | Use specified cell (A1-style cell) |
|
||||
| (number >= 0) | Start from the first column at specified row (0-indexed) |
|
||||
| -1 | Append to bottom of worksheet starting on first column |
|
||||
| (default) | Start from cell A1 |
|
||||
|
||||
|
||||
<details>
|
||||
<summary><b>Examples</b> (click to show)</summary>
|
||||
|
||||
Consider the worksheet:
|
||||
|
||||
```
|
||||
XXX| A | B | C | D | E | F | G |
|
||||
---+---+---+---+---+---+---+---+
|
||||
1 | S | h | e | e | t | J | S |
|
||||
2 | 1 | 2 | | | 5 | 6 | 7 |
|
||||
3 | 2 | 3 | | | 6 | 7 | 8 |
|
||||
4 | 3 | 4 | | | 7 | 8 | 9 |
|
||||
5 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |
|
||||
```
|
||||
|
||||
This worksheet can be built up in the order `A1:G1, A2:B4, E2:G4, A5:G5`:
|
||||
|
||||
```js
|
||||
/* Initial row */
|
||||
var ws = XLSX.utils.aoa_to_sheet([ "SheetJS".split("") ]);
|
||||
|
||||
/* Write data starting at A2 */
|
||||
XLSX.utils.sheet_add_aoa(ws, [[1,2], [2,3], [3,4]], {origin: "A2"});
|
||||
|
||||
/* Write data starting at E2 */
|
||||
XLSX.utils.sheet_add_aoa(ws, [[5,6,7], [6,7,8], [7,8,9]], {origin:{r:1, c:4}});
|
||||
|
||||
/* Append row */
|
||||
XLSX.utils.sheet_add_aoa(ws, [[4,5,6,7,8,9,0]], {origin: -1});
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Array of Objects Input
|
||||
|
||||
`XLSX.utils.json_to_sheet` takes an array of objects and returns a worksheet
|
||||
@ -1754,19 +1811,95 @@ default column order is determined by the first appearance of the field using
|
||||
|`header` | | Use specified column order (default `Object.keys`) |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`skipHeader` | false | If true, do not include header row in output |
|
||||
|
||||
<details>
|
||||
<summary><b>Examples</b> (click to show)</summary>
|
||||
|
||||
The original sheet cannot be reproduced because JS object keys must be unique.
|
||||
After replacing the second `e` and `S` with `e_1` and `S_1`:
|
||||
The original sheet cannot be reproduced in the obvious way since JS object keys
|
||||
must be unique. After replacing the second `e` and `S` with `e_1` and `S_1`:
|
||||
|
||||
```js
|
||||
var ws = XLSX.utils.json_to_sheet([
|
||||
{S:1,h:2,e:3,e_1:4,t:5,J:6,S_1:7},
|
||||
{S:2,h:3,e:4,e_1:5,t:6,J:7,S_1:8}
|
||||
{ S:1, h:2, e:3, e_1:4, t:5, J:6, S_1:7 },
|
||||
{ S:2, h:3, e:4, e_1:5, t:6, J:7, S_1:8 }
|
||||
], {header:["S","h","e","e_1","t","J","S_1"]});
|
||||
```
|
||||
|
||||
Alternatively, the header row can be skipped:
|
||||
|
||||
```js
|
||||
var ws = XLSX.utils.json_to_sheet([
|
||||
{ A:"S", B:"h", C:"e", D:"e", E:"t", F:"J", G:"S" },
|
||||
{ A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7 },
|
||||
{ A: 2, B: 3, C: 4, D: 5, E: 6, F: 7, G: 8 }
|
||||
], {header:["A","B","C","D","E","F","G"], skipHeader:true});
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
`XLSX.utils.sheet_add_json` takes an array of objects and updates an existing
|
||||
worksheet object. It follows the same process as `json_to_sheet` and accepts
|
||||
an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :------: | :-------------------------------------------------- |
|
||||
|`header` | | Use specified column order (default `Object.keys`) |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`skipHeader` | false | If true, do not include header row in output |
|
||||
|`origin` | | Use specified cell as starting point (see below) |
|
||||
|
||||
`origin` is expected to be one of:
|
||||
|
||||
| `origin` | Description |
|
||||
| :--------------- | :-------------------------------------------------------- |
|
||||
| (cell object) | Use specified cell (cell object) |
|
||||
| (string) | Use specified cell (A1-style cell) |
|
||||
| (number >= 0) | Start from the first column at specified row (0-indexed) |
|
||||
| -1 | Append to bottom of worksheet starting on first column |
|
||||
| (default) | Start from cell A1 |
|
||||
|
||||
|
||||
<details>
|
||||
<summary><b>Examples</b> (click to show)</summary>
|
||||
|
||||
Consider the worksheet:
|
||||
|
||||
```
|
||||
XXX| A | B | C | D | E | F | G |
|
||||
---+---+---+---+---+---+---+---+
|
||||
1 | S | h | e | e | t | J | S |
|
||||
2 | 1 | 2 | | | 5 | 6 | 7 |
|
||||
3 | 2 | 3 | | | 6 | 7 | 8 |
|
||||
4 | 3 | 4 | | | 7 | 8 | 9 |
|
||||
5 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |
|
||||
```
|
||||
|
||||
This worksheet can be built up in the order `A1:G1, A2:B4, E2:G4, A5:G5`:
|
||||
|
||||
```js
|
||||
/* Initial row */
|
||||
var ws = XLSX.utils.json_to_sheet([
|
||||
{ A: "S", B: "h", C: "e", D: "e", E: "t", F: "J", G: "S" }
|
||||
], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true});
|
||||
|
||||
/* Write data starting at A2 */
|
||||
XLSX.utils.sheet_add_json(ws, [
|
||||
{ A: 1, B: 2 }, { A: 2, B: 3 }, { A: 3, B: 4 }
|
||||
], {skipHeader: true, origin: "A2"});
|
||||
|
||||
/* Write data starting at E2 */
|
||||
XLSX.utils.sheet_add_json(ws, [
|
||||
{ A: 5, B: 6, C: 7 }, { A: 6, B: 7, C: 8 }, { A: 7, B: 8, C: 9 }
|
||||
], {skipHeader: true, origin: { r: 1, c: 4 }, header: [ "A", "B", "C" ]});
|
||||
|
||||
/* Append row */
|
||||
XLSX.utils.sheet_add_json(ws, [
|
||||
{ A: 4, B: 5, C: 6, D: 7, E: 8, F: 9, G: 0 }
|
||||
], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true, origin: -1});
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### HTML Table Input
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.11.16';
|
||||
XLSX.version = '0.11.17';
|
||||
|
@ -62,11 +62,16 @@ function escapexml(text/*:string*/, xml/*:?boolean*/)/*:string*/{
|
||||
function escapexmltag(text/*:string*/)/*:string*/{ return escapexml(text).replace(/ /g,"_x0020_"); }
|
||||
|
||||
var htmlcharegex = /[\u0000-\u001f]/g;
|
||||
function escapehtml(text){
|
||||
function escapehtml(text/*:string*/)/*:string*/{
|
||||
var s = text + '';
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; });
|
||||
}
|
||||
|
||||
function escapexlml(text/*:string*/)/*:string*/{
|
||||
var s = text + '';
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; });
|
||||
}
|
||||
|
||||
/* TODO: handle codepages */
|
||||
var xlml_fixstr/*:StringConv*/ = (function() {
|
||||
var entregex = /&#(\d+);/g;
|
||||
|
@ -5,8 +5,8 @@ function shift_cell_xls(cell/*:CellAddress*/, tgt/*:any*/, opts/*:?any*/)/*:Cell
|
||||
if(out.cRel) out.c += tgt.s.c;
|
||||
if(out.rRel) out.r += tgt.s.r;
|
||||
} else {
|
||||
out.c += tgt.c;
|
||||
out.r += tgt.r;
|
||||
if(out.cRel) out.c += tgt.c;
|
||||
if(out.rRel) out.r += tgt.r;
|
||||
}
|
||||
if(!opts || opts.biff < 12) {
|
||||
while(out.c >= 0x100) out.c -= 0x100;
|
||||
|
@ -80,20 +80,38 @@ function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ {
|
||||
return { SheetNames: [n], Sheets: sheets };
|
||||
}
|
||||
|
||||
function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
|
||||
function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
|
||||
var o = opts || {};
|
||||
if(DENSE != null && o.dense == null) o.dense = DENSE;
|
||||
var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/);
|
||||
var dense = _ws ? Array.isArray(_ws) : o.dense;
|
||||
if(DENSE != null && dense == null) dense = DENSE;
|
||||
var ws/*:Worksheet*/ = _ws || (dense ? ([]/*:any*/) : ({}/*:any*/));
|
||||
var _R = 0, _C = 0;
|
||||
if(ws && o.origin != null) {
|
||||
if(typeof o.origin == 'number') _R = o.origin;
|
||||
else {
|
||||
var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
|
||||
_R = _origin.r; _C = _origin.c;
|
||||
}
|
||||
}
|
||||
var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/);
|
||||
if(ws['!ref']) {
|
||||
var _range = safe_decode_range(ws['!ref']);
|
||||
range.s.c = _range.s.c;
|
||||
range.s.r = _range.s.r;
|
||||
range.e.c = Math.max(range.e.c, _range.e.c);
|
||||
range.e.r = Math.max(range.e.r, _range.e.r);
|
||||
if(_R == -1) range.e.r = _R = _range.e.r + 1;
|
||||
}
|
||||
for(var R = 0; R != data.length; ++R) {
|
||||
for(var C = 0; C != data[R].length; ++C) {
|
||||
if(typeof data[R][C] === 'undefined') continue;
|
||||
var cell/*:Cell*/ = ({v: data[R][C] }/*:any*/);
|
||||
if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
|
||||
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 __R = _R + R, __C = _C + 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;
|
||||
if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.cellStubs) continue; else cell.t = 'z'; }
|
||||
else if(typeof cell.v === 'number') cell.t = 'n';
|
||||
else if(typeof cell.v === 'boolean') cell.t = 'b';
|
||||
@ -103,11 +121,11 @@ function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
|
||||
else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); }
|
||||
}
|
||||
else cell.t = 's';
|
||||
if(o.dense) {
|
||||
if(!ws[R]) ws[R] = [];
|
||||
ws[R][C] = cell;
|
||||
if(dense) {
|
||||
if(!ws[__R]) ws[__R] = [];
|
||||
ws[__R][__C] = cell;
|
||||
} else {
|
||||
var cell_ref = encode_cell(({c:C,r:R}/*:any*/));
|
||||
var cell_ref = encode_cell(({c:__C,r:__R}/*:any*/));
|
||||
ws[cell_ref] = cell;
|
||||
}
|
||||
}
|
||||
@ -115,4 +133,5 @@ function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
|
||||
if(range.s.c < 10000000) ws['!ref'] = encode_range(range);
|
||||
return ws;
|
||||
}
|
||||
function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { return sheet_add_aoa(null, data, opts); }
|
||||
|
||||
|
@ -78,6 +78,7 @@ function xlml_write_custprops(Props, Custprops, opts) {
|
||||
if(Custprops) keys(Custprops).forEach(function(k) {
|
||||
/*:: if(!Custprops) return; */
|
||||
if(!Custprops.hasOwnProperty(k)) return;
|
||||
if(Props && Props.hasOwnProperty(k)) return;
|
||||
var m = Custprops[k];
|
||||
var t = "string";
|
||||
if(typeof m == 'number') { t = "float"; m = String(m); }
|
||||
|
@ -673,7 +673,7 @@ function parse_ShrFmla(blob, length, opts) {
|
||||
blob.l++;
|
||||
var cUse = blob.read_shift(1);
|
||||
length -= 8;
|
||||
return [parse_SharedParsedFormula(blob, length, opts), cUse];
|
||||
return [parse_SharedParsedFormula(blob, length, opts), cUse, ref];
|
||||
}
|
||||
|
||||
/* 2.4.4 TODO */
|
||||
|
@ -62,10 +62,8 @@ function parse_DataSpaceDefinition(blob, length)/*:Array<string>*/ {
|
||||
function parse_TransformInfoHeader(blob, length) {
|
||||
var o = {};
|
||||
var len = blob.read_shift(4);
|
||||
var tgt = blob.l + len - 4;
|
||||
blob.l += 4; // must be 0x1
|
||||
o.id = blob.read_shift(0, 'lpp4');
|
||||
if(tgt != blob.l) throw new Error("Bad TransformInfoHeader record: " + blob.l + " != " + tgt);
|
||||
o.name = blob.read_shift(0, 'lpp4');
|
||||
o.R = parse_CRYPTOVersion(blob, 4);
|
||||
o.U = parse_CRYPTOVersion(blob, 4);
|
||||
|
@ -18,12 +18,13 @@ var rc_to_a1 = (function(){
|
||||
|
||||
var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)([1-9]\d{0,5}|10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6])(?![_.\(A-Za-z0-9])/g;
|
||||
var a1_to_rc =(function(){
|
||||
return function a1_to_rc(fstr, base) {
|
||||
return function a1_to_rc(fstr/*:string*/, base/*:CellAddress*/) {
|
||||
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
|
||||
/* TODO: handle fixcol / fixrow */
|
||||
var c = decode_col($3) - base.c;
|
||||
var r = decode_row($5) - base.r;
|
||||
return $1 + "R" + (r == 0 ? "" : "[" + r + "]") + "C" + (c == 0 ? "" : "[" + c + "]");
|
||||
var c = decode_col($3) - ($2 ? 0 : base.c);
|
||||
var r = decode_row($5) - ($4 ? 0 : base.r);
|
||||
var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1));
|
||||
var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1));
|
||||
return $1 + "R" + R + "C" + C;
|
||||
});
|
||||
};
|
||||
})();
|
||||
|
@ -67,7 +67,7 @@ function parse_RgceLocRel(blob, length, opts) {
|
||||
if(biff >= 2 && biff <= 5) return parse_RgceLocRel_BIFF2(blob, length, opts);
|
||||
var r = blob.read_shift(biff >= 12 ? 4 : 2);
|
||||
var cl = blob.read_shift(2);
|
||||
var cRel = (cl & 0x8000) >> 15, rRel = (cl & 0x4000) >> 14;
|
||||
var cRel = (cl & 0x4000) >> 14, rRel = (cl & 0x8000) >> 15;
|
||||
cl &= 0x3FFF;
|
||||
if(rRel == 1) while(r > 0x7FFFF) r -= 0x100000;
|
||||
if(cRel == 1) while(cl > 0x1FFF) cl = cl - 0x4000;
|
||||
@ -840,7 +840,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
|
||||
case 'PtgErr': /* 2.5.198.57 */
|
||||
stack.push(/*::String(*/f[1]/*::)*/); break;
|
||||
case 'PtgAreaN': /* 2.5.198.31 TODO */
|
||||
type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts);
|
||||
type = f[1][0]; r = shift_range_xls(f[1][1], cell ? {s:cell} : _range, opts);
|
||||
stack.push(encode_range_xls((r/*:any*/), opts));
|
||||
break;
|
||||
case 'PtgArea': /* 2.5.198.27 TODO: fixed points */
|
||||
|
@ -334,7 +334,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
|
||||
var _NamedRange = parsexmltag(Rn[0]);
|
||||
var _DefinedName/*:DefinedName*/ = ({
|
||||
Name: _NamedRange.Name,
|
||||
Ref: rc_to_a1(_NamedRange.RefersTo.substr(1))
|
||||
Ref: rc_to_a1(_NamedRange.RefersTo.substr(1), {r:0, c:0})
|
||||
}/*:any*/);
|
||||
if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1;
|
||||
/*:: if(Workbook.Names) */Workbook.Names.push(_DefinedName);
|
||||
@ -864,6 +864,37 @@ function write_sty_xlml(wb, opts)/*:string*/ {
|
||||
});
|
||||
return writextag("Styles", styles.join(""));
|
||||
}
|
||||
function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); }
|
||||
function write_names_xlml(wb, opts)/*:string*/ {
|
||||
if(!((wb||{}).Workbook||{}).Names) return "";
|
||||
/*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */
|
||||
var names/*:Array<any>*/ = wb.Workbook.Names;
|
||||
var out/*:Array<string>*/ = [];
|
||||
for(var i = 0; i < names.length; ++i) {
|
||||
var n = names[i];
|
||||
if(n.Sheet != null) continue;
|
||||
if(n.Name.match(/^_xlfn\./)) continue;
|
||||
out.push(write_name_xlml(n));
|
||||
}
|
||||
return writextag("Names", out.join(""));
|
||||
}
|
||||
function write_ws_xlml_names(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
|
||||
if(!ws) return "";
|
||||
if(!((wb||{}).Workbook||{}).Names) return "";
|
||||
/*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */
|
||||
var names/*:Array<any>*/ = wb.Workbook.Names;
|
||||
var out/*:Array<string>*/ = [];
|
||||
outer: for(var i = 0; i < names.length; ++i) {
|
||||
var n = names[i];
|
||||
if(n.Sheet != idx) continue;
|
||||
/*switch(n.Name) {
|
||||
case "_": continue;
|
||||
}*/
|
||||
if(n.Name.match(/^_xlfn\./)) continue;
|
||||
out.push(write_name_xlml(n));
|
||||
}
|
||||
return out.join("");
|
||||
}
|
||||
/* WorksheetOptions */
|
||||
function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
|
||||
if(!ws) return "";
|
||||
@ -982,7 +1013,7 @@ function write_ws_xlml_comment(comments/*:Array<any>*/)/*:string*/ {
|
||||
}).join("");
|
||||
}
|
||||
function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, addr)/*:string*/{
|
||||
if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>";
|
||||
if(!cell || cell.v == undefined && cell.f == undefined) return "";
|
||||
|
||||
var attr = {};
|
||||
if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr));
|
||||
@ -1012,11 +1043,12 @@ function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb,
|
||||
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
|
||||
case 'e': t = 'Error'; p = BErr[cell.v]; break;
|
||||
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break;
|
||||
case 's': t = 'String'; p = escapexml(cell.v||""); break;
|
||||
case 's': t = 'String'; p = escapexlml(cell.v||""); break;
|
||||
}
|
||||
/* TODO: cell style */
|
||||
var os = get_cell_style(opts.cellXfs, cell, opts);
|
||||
attr["ss:StyleID"] = "s" + (21+os);
|
||||
attr["ss:Index"] = addr.c + 1;
|
||||
var _v = (cell.v != null ? p : "");
|
||||
var m = '<Data ss:Type="' + t + '">' + _v + '</Data>';
|
||||
|
||||
@ -1076,8 +1108,11 @@ function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ {
|
||||
var s = wb.SheetNames[idx];
|
||||
var ws = wb.Sheets[s];
|
||||
|
||||
var t/*:string*/ = ws ? write_ws_xlml_names(ws, opts, idx, wb) : "";
|
||||
if(t.length > 0) o.push("<Names>" + t + "</Names>");
|
||||
|
||||
/* Table */
|
||||
var t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
|
||||
t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
|
||||
if(t.length > 0) o.push("<Table>" + t + "</Table>");
|
||||
|
||||
/* WorksheetOptions */
|
||||
@ -1100,9 +1135,11 @@ function write_xlml(wb, opts)/*:string*/ {
|
||||
d.push(write_props_xlml(wb, opts));
|
||||
d.push(write_wb_xlml(wb, opts));
|
||||
d.push("");
|
||||
d.push("");
|
||||
for(var i = 0; i < wb.SheetNames.length; ++i)
|
||||
d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])}));
|
||||
d[2] = write_sty_xlml(wb, opts);
|
||||
d[3] = write_names_xlml(wb, opts);
|
||||
return XML_HEADER + writextag("Workbook", d.join(""), {
|
||||
'xmlns': XLMLNS.ss,
|
||||
'xmlns:o': XLMLNS.o,
|
||||
|
@ -105,7 +105,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
var cur_sheet = "";
|
||||
var Preamble = {};
|
||||
var lastcell, last_cell = "", cc, cmnt, rngC, rngR;
|
||||
var shared_formulae = {};
|
||||
var sharedf = {};
|
||||
var arrayf/*:Array<[Range, string]>*/ = [];
|
||||
var temp_val/*:Cell*/;
|
||||
var country;
|
||||
@ -144,13 +144,10 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
}
|
||||
if(options.cellFormula && line.f) {
|
||||
for(var afi = 0; afi < arrayf.length; ++afi) {
|
||||
if(arrayf[afi][0].s.c > cell.c) continue;
|
||||
if(arrayf[afi][0].s.r > cell.r) continue;
|
||||
if(arrayf[afi][0].e.c < cell.c) continue;
|
||||
if(arrayf[afi][0].e.r < cell.r) continue;
|
||||
if(arrayf[afi][0].s.c > cell.c || arrayf[afi][0].s.r > cell.r) continue;
|
||||
if(arrayf[afi][0].e.c < cell.c || arrayf[afi][0].e.r < cell.r) continue;
|
||||
line.F = encode_range(arrayf[afi][0]);
|
||||
if(arrayf[afi][0].s.c != cell.c) delete line.f;
|
||||
if(arrayf[afi][0].s.r != cell.r) delete line.f;
|
||||
if(arrayf[afi][0].s.c != cell.c || arrayf[afi][0].s.r != cell.r) delete line.f;
|
||||
if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts);
|
||||
break;
|
||||
}
|
||||
@ -167,7 +164,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
enc: false, // encrypted
|
||||
sbcch: 0, // cch in the preceding SupBook
|
||||
snames: [], // sheetnames
|
||||
sharedf: shared_formulae, // shared formulae by address
|
||||
sharedf: sharedf, // shared formulae by address
|
||||
arrayf: arrayf, // array formulae array
|
||||
rrtabid: [], // RRTabId
|
||||
lastuser: "", // Last User from WriteAccess
|
||||
@ -223,6 +220,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(R.n === 'EOF') val = R.f(blob, length, opts);
|
||||
else val = slurp(R, blob, length, opts);
|
||||
var Rn = R.n;
|
||||
if(file_depth == 0 && Rn != 'BOF') continue;
|
||||
/* nested switch statements to workaround V8 128 limit */
|
||||
switch(Rn) {
|
||||
/* Workbook Options */
|
||||
@ -253,16 +251,17 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
case 'RRTabId': opts.rrtabid = val; break;
|
||||
case 'WinProtect': opts.winlocked = val; break;
|
||||
case 'Template': break; // TODO
|
||||
case 'RefreshAll': wb.opts.RefreshAll = val; break;
|
||||
case 'BookBool': break; // TODO
|
||||
case 'UsesELFs': break;
|
||||
case 'MTRSettings': break;
|
||||
case 'CalcCount': wb.opts.CalcCount = val; break;
|
||||
case 'CalcDelta': wb.opts.CalcDelta = val; break;
|
||||
case 'CalcIter': wb.opts.CalcIter = val; break;
|
||||
case 'CalcMode': wb.opts.CalcMode = val; break;
|
||||
case 'CalcPrecision': wb.opts.CalcPrecision = val; break;
|
||||
case 'CalcSaveRecalc': wb.opts.CalcSaveRecalc = val; break;
|
||||
case 'RefreshAll':
|
||||
case 'CalcCount':
|
||||
case 'CalcDelta':
|
||||
case 'CalcIter':
|
||||
case 'CalcMode':
|
||||
case 'CalcPrecision':
|
||||
case 'CalcSaveRecalc':
|
||||
wb.opts[Rn] = val; break;
|
||||
case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
|
||||
case 'Uncalced': break;
|
||||
case 'ForceFullCalculation': wb.opts.FullCalc = val; break;
|
||||
@ -404,7 +403,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F;
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
@ -444,7 +443,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(last_cell) {
|
||||
/* TODO: capture range */
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
shared_formulae[encode_cell(last_formula.cell)]= val[0];
|
||||
sharedf[encode_cell(last_formula.cell)]= val[0];
|
||||
cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
|
||||
(cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
}
|
||||
|
@ -168,14 +168,29 @@ function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
|
||||
return cmds;
|
||||
}
|
||||
|
||||
function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ {
|
||||
function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet*/ {
|
||||
var o = opts || {};
|
||||
var ws = ({}/*:any*/);
|
||||
var offset = +!o.skipHeader;
|
||||
var ws/*:Worksheet*/ = _ws || ({}/*:any*/);
|
||||
var _R = 0, _C = 0;
|
||||
if(ws && o.origin != null) {
|
||||
if(typeof o.origin == 'number') _R = o.origin;
|
||||
else {
|
||||
var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
|
||||
_R = _origin.r; _C = _origin.c;
|
||||
}
|
||||
}
|
||||
var cell/*:Cell*/;
|
||||
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:js.length}}/*:any*/);
|
||||
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}}/*:any*/);
|
||||
if(ws['!ref']) {
|
||||
var _range = safe_decode_range(ws['!ref']);
|
||||
range.e.c = Math.max(range.e.c, _range.e.c);
|
||||
range.e.r = Math.max(range.e.r, _range.e.r);
|
||||
if(_R == -1) { _R = range.e.r + 1; range.e.r = _R + js.length - 1 + offset; }
|
||||
}
|
||||
var hdr/*:Array<string>*/ = o.header || [], C = 0;
|
||||
|
||||
js.forEach(function (JS, R) {
|
||||
js.forEach(function (JS, R/*:number*/) {
|
||||
keys(JS).filter(function(x) { return JS.hasOwnProperty(x); }).forEach(function(k) {
|
||||
if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k;
|
||||
var v = JS[k];
|
||||
@ -189,15 +204,17 @@ function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ {
|
||||
if(!o.cellDates) { t = 'n'; v = datenum(v); }
|
||||
z = o.dateNF || SSF._table[14];
|
||||
}
|
||||
ws[encode_cell({c:C,r:R+1})] = cell = ({t:t, v:v}/*:any*/);
|
||||
ws[encode_cell({c:_C + C,r:_R + R + offset})] = cell = ({t:t, v:v}/*:any*/);
|
||||
if(z) cell.z = z;
|
||||
});
|
||||
});
|
||||
range.e.c = hdr.length - 1;
|
||||
for(C = 0; C < hdr.length; ++C) ws[encode_col(C) + "1"] = {t:'s', v:hdr[C]};
|
||||
range.e.c = Math.max(range.e.c, _C + hdr.length - 1);
|
||||
var __R = encode_row(_R);
|
||||
if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]};
|
||||
ws['!ref'] = encode_range(range);
|
||||
return ws;
|
||||
}
|
||||
function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ { return sheet_add_json(null, js, opts); }
|
||||
|
||||
var utils/*:any*/ = {
|
||||
encode_col: encode_col,
|
||||
@ -214,6 +231,8 @@ var utils/*:any*/ = {
|
||||
make_csv: sheet_to_csv,
|
||||
make_json: sheet_to_json,
|
||||
make_formulae: sheet_to_formulae,
|
||||
sheet_add_aoa: sheet_add_aoa,
|
||||
sheet_add_json: sheet_add_json,
|
||||
aoa_to_sheet: aoa_to_sheet,
|
||||
json_to_sheet: json_to_sheet,
|
||||
table_to_sheet: parse_dom_table,
|
||||
|
@ -19,7 +19,7 @@ can be installed with Bash on Windows or with `cygwin`.
|
||||
|
||||
**Frameworks and APIs**
|
||||
- [`angular 1.x`](angular/)
|
||||
- [`angular 2.x / 4.x / 5.x`](angular2/)
|
||||
- [`angular 2 / 4 / 5 and ionic`](angular2/)
|
||||
- [`meteor`](meteor/)
|
||||
- [`react and react-native`](react/)
|
||||
- [`vue 2.x and weex`](vue/)
|
||||
|
1
demos/angular2/.gitignore
vendored
1
demos/angular2/.gitignore
vendored
@ -1 +1,2 @@
|
||||
dist
|
||||
SheetJSIonic
|
||||
|
@ -21,3 +21,11 @@ angular:
|
||||
if [ ! -e node_modules/xlsx ]; then cd node_modules; ln -s ../../../ xlsx; cd -; fi
|
||||
ng build
|
||||
|
||||
.PHONY: ionic
|
||||
ionic:
|
||||
bash ./ionic.sh
|
||||
|
||||
.PHONY: ios android browser
|
||||
ios android browser: ionic
|
||||
cd SheetJSIonic; ionic cordova emulate $@ </dev/null; cd -
|
||||
|
||||
|
@ -10,6 +10,9 @@ This demo uses an array of arrays (type `Array<Array<any>>`) as the core state.
|
||||
The component template includes a file input element, a table that updates with
|
||||
the data, and a button to export the data.
|
||||
|
||||
Other scripts in this demo show:
|
||||
- `ionic` deployment for iOS, android, and browser
|
||||
|
||||
## Array of Arrays
|
||||
|
||||
`Array<Array<any>>` neatly maps to a table with `ngFor`:
|
||||
@ -114,4 +117,39 @@ SystemJS.config({
|
||||
});
|
||||
```
|
||||
|
||||
## Ionic
|
||||
|
||||
<img src="screen.png" width="400px"/>
|
||||
|
||||
Reproducing the full project is a little bit tricky. The included `ionic.sh`
|
||||
script performs the necessary installation steps.
|
||||
|
||||
`Array<Array<any>>` neatly maps to a table with `ngFor`:
|
||||
|
||||
```html
|
||||
<ion-grid>
|
||||
<ion-row *ngFor="let row of data">
|
||||
<ion-col *ngFor="let val of row">
|
||||
{{val}}
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
```
|
||||
|
||||
|
||||
`@ionic-native/file` reads and writes files on devices. `readAsBinaryString`
|
||||
returns strings that can be parsed with the `binary` type, and `array` type can
|
||||
easily be converted to blobs that can be exported with `writeFile`:
|
||||
|
||||
```typescript
|
||||
/* read a workbook */
|
||||
const bstr: string = await this.file.readAsBinaryString(url, filename);
|
||||
const wb: XLSX.WorkBook = XLSX.read(bstr, {type: 'binary'});
|
||||
|
||||
/* write a workbook */
|
||||
const wbout: ArrayBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
|
||||
let blob = new Blob([wbout], {type: 'application/octet-stream'});
|
||||
this.file.writeFile(url, filename, blob, {replace: true});
|
||||
```
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
||||
|
17
demos/angular2/ionic.sh
Executable file
17
demos/angular2/ionic.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
if [ ! -e SheetJSIonic ]; then
|
||||
ionic start SheetJSIonic blank --cordova --no-git --no-link </dev/null
|
||||
cd SheetJSIonic
|
||||
ionic cordova platform add browser </dev/null
|
||||
ionic cordova platform add ios </dev/null
|
||||
ionic cordova plugin add cordova-plugin-file </dev/null
|
||||
npm install --save @ionic-native/file file-saver
|
||||
npm install --save xlsx
|
||||
|
||||
cp src/app/app.module.ts{,.bak}
|
||||
cat src/app/app.module.ts.bak | awk 'BEGIN{p=0} !/import/ && !p { ++p; print "import { File } from '"'"'@ionic-native/file'"'"';"; } 1; /providers: \[/ {print " File,"}' > src/app/app.module.ts
|
||||
cd -
|
||||
fi
|
||||
|
||||
cp ionic.ts SheetJSIonic/src/pages/home/home.ts
|
||||
rm -f SheetJSIonic/src/pages/home/home.html
|
109
demos/angular2/ionic.ts
Normal file
109
demos/angular2/ionic.ts
Normal file
@ -0,0 +1,109 @@
|
||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
/* vim: set ts=2: */
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import * as XLSX from 'xlsx';
|
||||
|
||||
import { File } from '@ionic-native/file';
|
||||
import { saveAs } from 'file-saver';
|
||||
|
||||
type AOA = any[][];
|
||||
|
||||
@Component({
|
||||
selector: 'page-home',
|
||||
template: `
|
||||
<ion-header><ion-navbar><ion-title>SheetJS Ionic Demo</ion-title></ion-navbar></ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
<ion-grid>
|
||||
<ion-row *ngFor="let row of data">
|
||||
<ion-col *ngFor="let val of row">
|
||||
{{val}}
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
</ion-content>
|
||||
|
||||
<ion-footer>
|
||||
<input type="file" (change)="onFileChange($event)" multiple="false" />
|
||||
<button ion-button color="secondary" (click)="import()">Import Data</button>
|
||||
<button ion-button color="secondary" (click)="export()">Export Data</button>
|
||||
</ion-footer>
|
||||
`
|
||||
})
|
||||
|
||||
export class HomePage {
|
||||
data: any[][] = [[1,2,3],[4,5,6]];
|
||||
constructor(public file: File) {};
|
||||
|
||||
read(bstr: string) {
|
||||
/* read workbook */
|
||||
const wb: XLSX.WorkBook = XLSX.read(bstr, {type: 'binary'});
|
||||
|
||||
/* grab first sheet */
|
||||
const wsname: string = wb.SheetNames[0];
|
||||
const ws: XLSX.WorkSheet = wb.Sheets[wsname];
|
||||
|
||||
/* save data */
|
||||
this.data = <AOA>(XLSX.utils.sheet_to_json(ws, {header: 1}));
|
||||
};
|
||||
|
||||
write(): ArrayBuffer {
|
||||
/* generate worksheet */
|
||||
const ws: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet(this.data);
|
||||
|
||||
/* generate workbook and add the worksheet */
|
||||
const wb: XLSX.WorkBook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, 'SheetJS');
|
||||
|
||||
/* save to ArrayBuffer */
|
||||
const wbout: ArrayBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
|
||||
return wbout;
|
||||
};
|
||||
|
||||
/* File Input element for browser */
|
||||
onFileChange(evt: any) {
|
||||
/* wire up file reader */
|
||||
const target: DataTransfer = <DataTransfer>(evt.target);
|
||||
if (target.files.length !== 1) throw new Error('Cannot use multiple files');
|
||||
const reader: FileReader = new FileReader();
|
||||
reader.onload = (e: any) => {
|
||||
const bstr: string = e.target.result;
|
||||
this.read(bstr);
|
||||
};
|
||||
reader.readAsBinaryString(target.files[0]);
|
||||
};
|
||||
|
||||
/* Import button for mobile */
|
||||
async import() {
|
||||
try {
|
||||
const target: string = this.file.documentsDirectory || this.file.externalDataDirectory || this.file.dataDirectory || '';
|
||||
const dentry = await this.file.resolveDirectoryUrl(target);
|
||||
const url: string = dentry.nativeURL || '';
|
||||
alert(`Attempting to read SheetJSIonic.xlsx from ${url}`)
|
||||
const bstr: string = await this.file.readAsBinaryString(url, "SheetJSIonic.xlsx");
|
||||
this.read(bstr);
|
||||
} catch(e) {
|
||||
const m: string = e.message;
|
||||
alert(m.match(/It was determined/) ? "Use File Input control" : `Error: ${m}`);
|
||||
}
|
||||
};
|
||||
|
||||
/* Export button */
|
||||
async export() {
|
||||
const wbout: ArrayBuffer = this.write();
|
||||
const filename: string = "SheetJSIonic.xlsx";
|
||||
const blob: Blob = new Blob([wbout], {type: 'application/octet-stream'});
|
||||
try {
|
||||
const target: string = this.file.documentsDirectory || this.file.externalDataDirectory || this.file.dataDirectory || '';
|
||||
const dentry = await this.file.resolveDirectoryUrl(target);
|
||||
const url: string = dentry.nativeURL || '';
|
||||
await this.file.writeFile(url, filename, blob, {replace: true});
|
||||
alert(`Wrote to SheetJSIonic.xlsx in ${url}`);
|
||||
} catch(e) {
|
||||
if(e.message.match(/It was determined/)) saveAs(blob, filename);
|
||||
else alert(`Error: ${e.message}`);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
BIN
demos/angular2/screen.png
Normal file
BIN
demos/angular2/screen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 94 KiB |
@ -6,7 +6,7 @@ import * as XLSX from 'xlsx';
|
||||
|
||||
import { saveAs } from 'file-saver';
|
||||
|
||||
type AOA = Array<Array<any>>;
|
||||
type AOA = any[][];
|
||||
|
||||
@Component({
|
||||
selector: 'sheetjs',
|
||||
|
30
dist/xlsx.core.min.js
generated
vendored
30
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
2
dist/xlsx.core.min.map
generated
vendored
File diff suppressed because one or more lines are too long
30
dist/xlsx.full.min.js
generated
vendored
30
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
2
dist/xlsx.full.min.map
generated
vendored
File diff suppressed because one or more lines are too long
179
dist/xlsx.js
generated
vendored
179
dist/xlsx.js
generated
vendored
@ -4,7 +4,7 @@
|
||||
/*global global, exports, module, require:false, process:false, Buffer:false */
|
||||
var XLSX = {};
|
||||
(function make_xlsx(XLSX){
|
||||
XLSX.version = '0.11.16';
|
||||
XLSX.version = '0.11.17';
|
||||
var current_codepage = 1200, current_ansi = 1252;
|
||||
/*global cptable:true */
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
|
||||
@ -2051,6 +2051,11 @@ function escapehtml(text){
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; });
|
||||
}
|
||||
|
||||
function escapexlml(text){
|
||||
var s = text + '';
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; });
|
||||
}
|
||||
|
||||
/* TODO: handle codepages */
|
||||
var xlml_fixstr = (function() {
|
||||
var entregex = /&#(\d+);/g;
|
||||
@ -2255,7 +2260,7 @@ function write_double_le(b, v, idx) {
|
||||
b[idx + 7] = (e >> 4) | bs;
|
||||
}
|
||||
|
||||
var __toBuffer = function(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; };
|
||||
var __toBuffer = function(bufs) { var x=[],w=10240; for(var i=0;i<bufs[0].length;++i) for(var j=0,L=bufs[0][i].length;j<L;j+=w) x.push.apply(x, bufs[0][i].slice(j,j+w)); return x; };
|
||||
var ___toBuffer = __toBuffer;
|
||||
var __utf16le = function(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join("").replace(chr0,''); };
|
||||
var ___utf16le = __utf16le;
|
||||
@ -2538,8 +2543,8 @@ function shift_cell_xls(cell, tgt, opts) {
|
||||
if(out.cRel) out.c += tgt.s.c;
|
||||
if(out.rRel) out.r += tgt.s.r;
|
||||
} else {
|
||||
out.c += tgt.c;
|
||||
out.r += tgt.r;
|
||||
if(out.cRel) out.c += tgt.c;
|
||||
if(out.rRel) out.r += tgt.r;
|
||||
}
|
||||
if(!opts || opts.biff < 12) {
|
||||
while(out.c >= 0x100) out.c -= 0x100;
|
||||
@ -2689,20 +2694,38 @@ function sheet_to_workbook(sheet, opts) {
|
||||
return { SheetNames: [n], Sheets: sheets };
|
||||
}
|
||||
|
||||
function aoa_to_sheet(data, opts) {
|
||||
function sheet_add_aoa(_ws, data, opts) {
|
||||
var o = opts || {};
|
||||
if(DENSE != null && o.dense == null) o.dense = DENSE;
|
||||
var ws = o.dense ? ([]) : ({});
|
||||
var dense = _ws ? Array.isArray(_ws) : o.dense;
|
||||
if(DENSE != null && dense == null) dense = DENSE;
|
||||
var ws = _ws || (dense ? ([]) : ({}));
|
||||
var _R = 0, _C = 0;
|
||||
if(ws && o.origin != null) {
|
||||
if(typeof o.origin == 'number') _R = o.origin;
|
||||
else {
|
||||
var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
|
||||
_R = _origin.r; _C = _origin.c;
|
||||
}
|
||||
}
|
||||
var range = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}});
|
||||
if(ws['!ref']) {
|
||||
var _range = safe_decode_range(ws['!ref']);
|
||||
range.s.c = _range.s.c;
|
||||
range.s.r = _range.s.r;
|
||||
range.e.c = Math.max(range.e.c, _range.e.c);
|
||||
range.e.r = Math.max(range.e.r, _range.e.r);
|
||||
if(_R == -1) range.e.r = _R = _range.e.r + 1;
|
||||
}
|
||||
for(var R = 0; R != data.length; ++R) {
|
||||
for(var C = 0; C != data[R].length; ++C) {
|
||||
if(typeof data[R][C] === 'undefined') continue;
|
||||
var cell = ({v: data[R][C] });
|
||||
if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
|
||||
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 __R = _R + R, __C = _C + 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;
|
||||
if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.cellStubs) continue; else cell.t = 'z'; }
|
||||
else if(typeof cell.v === 'number') cell.t = 'n';
|
||||
else if(typeof cell.v === 'boolean') cell.t = 'b';
|
||||
@ -2712,11 +2735,11 @@ function aoa_to_sheet(data, opts) {
|
||||
else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); }
|
||||
}
|
||||
else cell.t = 's';
|
||||
if(o.dense) {
|
||||
if(!ws[R]) ws[R] = [];
|
||||
ws[R][C] = cell;
|
||||
if(dense) {
|
||||
if(!ws[__R]) ws[__R] = [];
|
||||
ws[__R][__C] = cell;
|
||||
} else {
|
||||
var cell_ref = encode_cell(({c:C,r:R}));
|
||||
var cell_ref = encode_cell(({c:__C,r:__R}));
|
||||
ws[cell_ref] = cell;
|
||||
}
|
||||
}
|
||||
@ -2724,6 +2747,7 @@ function aoa_to_sheet(data, opts) {
|
||||
if(range.s.c < 10000000) ws['!ref'] = encode_range(range);
|
||||
return ws;
|
||||
}
|
||||
function aoa_to_sheet(data, opts) { return sheet_add_aoa(null, data, opts); }
|
||||
|
||||
function write_UInt32LE(x, o) {
|
||||
if(!o) o = new_buf(4);
|
||||
@ -4047,6 +4071,7 @@ if(!Props.hasOwnProperty(k)) return;
|
||||
});
|
||||
if(Custprops) keys(Custprops).forEach(function(k) {
|
||||
if(!Custprops.hasOwnProperty(k)) return;
|
||||
if(Props && Props.hasOwnProperty(k)) return;
|
||||
var m = Custprops[k];
|
||||
var t = "string";
|
||||
if(typeof m == 'number') { t = "float"; m = String(m); }
|
||||
@ -5224,7 +5249,7 @@ function parse_ShrFmla(blob, length, opts) {
|
||||
blob.l++;
|
||||
var cUse = blob.read_shift(1);
|
||||
length -= 8;
|
||||
return [parse_SharedParsedFormula(blob, length, opts), cUse];
|
||||
return [parse_SharedParsedFormula(blob, length, opts), cUse, ref];
|
||||
}
|
||||
|
||||
/* 2.4.4 TODO */
|
||||
@ -7097,10 +7122,8 @@ function parse_DataSpaceDefinition(blob, length) {
|
||||
function parse_TransformInfoHeader(blob, length) {
|
||||
var o = {};
|
||||
var len = blob.read_shift(4);
|
||||
var tgt = blob.l + len - 4;
|
||||
blob.l += 4; // must be 0x1
|
||||
o.id = blob.read_shift(0, 'lpp4');
|
||||
if(tgt != blob.l) throw new Error("Bad TransformInfoHeader record: " + blob.l + " != " + tgt);
|
||||
o.name = blob.read_shift(0, 'lpp4');
|
||||
o.R = parse_CRYPTOVersion(blob, 4);
|
||||
o.U = parse_CRYPTOVersion(blob, 4);
|
||||
@ -9089,10 +9112,11 @@ var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A
|
||||
var a1_to_rc =(function(){
|
||||
return function a1_to_rc(fstr, base) {
|
||||
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
|
||||
/* TODO: handle fixcol / fixrow */
|
||||
var c = decode_col($3) - base.c;
|
||||
var r = decode_row($5) - base.r;
|
||||
return $1 + "R" + (r == 0 ? "" : "[" + r + "]") + "C" + (c == 0 ? "" : "[" + c + "]");
|
||||
var c = decode_col($3) - ($2 ? 0 : base.c);
|
||||
var r = decode_row($5) - ($4 ? 0 : base.r);
|
||||
var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1));
|
||||
var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1));
|
||||
return $1 + "R" + R + "C" + C;
|
||||
});
|
||||
};
|
||||
})();
|
||||
@ -9188,7 +9212,7 @@ function parse_RgceLocRel(blob, length, opts) {
|
||||
if(biff >= 2 && biff <= 5) return parse_RgceLocRel_BIFF2(blob, length, opts);
|
||||
var r = blob.read_shift(biff >= 12 ? 4 : 2);
|
||||
var cl = blob.read_shift(2);
|
||||
var cRel = (cl & 0x8000) >> 15, rRel = (cl & 0x4000) >> 14;
|
||||
var cRel = (cl & 0x4000) >> 14, rRel = (cl & 0x8000) >> 15;
|
||||
cl &= 0x3FFF;
|
||||
if(rRel == 1) while(r > 0x7FFFF) r -= 0x100000;
|
||||
if(cRel == 1) while(cl > 0x1FFF) cl = cl - 0x4000;
|
||||
@ -9960,7 +9984,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell, supbooks, opts) {
|
||||
case 'PtgErr': /* 2.5.198.57 */
|
||||
stack.push(f[1]); break;
|
||||
case 'PtgAreaN': /* 2.5.198.31 TODO */
|
||||
type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts);
|
||||
type = f[1][0]; r = shift_range_xls(f[1][1], cell ? {s:cell} : _range, opts);
|
||||
stack.push(encode_range_xls((r), opts));
|
||||
break;
|
||||
case 'PtgArea': /* 2.5.198.27 TODO: fixed points */
|
||||
@ -14263,7 +14287,7 @@ for(var cma = c; cma <= cc; ++cma) {
|
||||
var _NamedRange = parsexmltag(Rn[0]);
|
||||
var _DefinedName = ({
|
||||
Name: _NamedRange.Name,
|
||||
Ref: rc_to_a1(_NamedRange.RefersTo.substr(1))
|
||||
Ref: rc_to_a1(_NamedRange.RefersTo.substr(1), {r:0, c:0})
|
||||
});
|
||||
if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1;
|
||||
Workbook.Names.push(_DefinedName);
|
||||
@ -14791,6 +14815,35 @@ function write_sty_xlml(wb, opts) {
|
||||
});
|
||||
return writextag("Styles", styles.join(""));
|
||||
}
|
||||
function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); }
|
||||
function write_names_xlml(wb, opts) {
|
||||
if(!((wb||{}).Workbook||{}).Names) return "";
|
||||
var names = wb.Workbook.Names;
|
||||
var out = [];
|
||||
for(var i = 0; i < names.length; ++i) {
|
||||
var n = names[i];
|
||||
if(n.Sheet != null) continue;
|
||||
if(n.Name.match(/^_xlfn\./)) continue;
|
||||
out.push(write_name_xlml(n));
|
||||
}
|
||||
return writextag("Names", out.join(""));
|
||||
}
|
||||
function write_ws_xlml_names(ws, opts, idx, wb) {
|
||||
if(!ws) return "";
|
||||
if(!((wb||{}).Workbook||{}).Names) return "";
|
||||
var names = wb.Workbook.Names;
|
||||
var out = [];
|
||||
outer: for(var i = 0; i < names.length; ++i) {
|
||||
var n = names[i];
|
||||
if(n.Sheet != idx) continue;
|
||||
/*switch(n.Name) {
|
||||
case "_": continue;
|
||||
}*/
|
||||
if(n.Name.match(/^_xlfn\./)) continue;
|
||||
out.push(write_name_xlml(n));
|
||||
}
|
||||
return out.join("");
|
||||
}
|
||||
/* WorksheetOptions */
|
||||
function write_ws_xlml_wsopts(ws, opts, idx, wb) {
|
||||
if(!ws) return "";
|
||||
@ -14909,7 +14962,7 @@ function write_ws_xlml_comment(comments) {
|
||||
}).join("");
|
||||
}
|
||||
function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){
|
||||
if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>";
|
||||
if(!cell || cell.v == undefined && cell.f == undefined) return "";
|
||||
|
||||
var attr = {};
|
||||
if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr));
|
||||
@ -14939,11 +14992,12 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){
|
||||
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
|
||||
case 'e': t = 'Error'; p = BErr[cell.v]; break;
|
||||
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break;
|
||||
case 's': t = 'String'; p = escapexml(cell.v||""); break;
|
||||
case 's': t = 'String'; p = escapexlml(cell.v||""); break;
|
||||
}
|
||||
/* TODO: cell style */
|
||||
var os = get_cell_style(opts.cellXfs, cell, opts);
|
||||
attr["ss:StyleID"] = "s" + (21+os);
|
||||
attr["ss:Index"] = addr.c + 1;
|
||||
var _v = (cell.v != null ? p : "");
|
||||
var m = '<Data ss:Type="' + t + '">' + _v + '</Data>';
|
||||
|
||||
@ -15003,8 +15057,11 @@ function write_ws_xlml(idx, opts, wb) {
|
||||
var s = wb.SheetNames[idx];
|
||||
var ws = wb.Sheets[s];
|
||||
|
||||
var t = ws ? write_ws_xlml_names(ws, opts, idx, wb) : "";
|
||||
if(t.length > 0) o.push("<Names>" + t + "</Names>");
|
||||
|
||||
/* Table */
|
||||
var t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
|
||||
t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
|
||||
if(t.length > 0) o.push("<Table>" + t + "</Table>");
|
||||
|
||||
/* WorksheetOptions */
|
||||
@ -15027,9 +15084,11 @@ function write_xlml(wb, opts) {
|
||||
d.push(write_props_xlml(wb, opts));
|
||||
d.push(write_wb_xlml(wb, opts));
|
||||
d.push("");
|
||||
d.push("");
|
||||
for(var i = 0; i < wb.SheetNames.length; ++i)
|
||||
d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])}));
|
||||
d[2] = write_sty_xlml(wb, opts);
|
||||
d[3] = write_names_xlml(wb, opts);
|
||||
return XML_HEADER + writextag("Workbook", d.join(""), {
|
||||
'xmlns': XLMLNS.ss,
|
||||
'xmlns:o': XLMLNS.o,
|
||||
@ -15144,7 +15203,7 @@ function parse_workbook(blob, options) {
|
||||
var cur_sheet = "";
|
||||
var Preamble = {};
|
||||
var lastcell, last_cell = "", cc, cmnt, rngC, rngR;
|
||||
var shared_formulae = {};
|
||||
var sharedf = {};
|
||||
var arrayf = [];
|
||||
var temp_val;
|
||||
var country;
|
||||
@ -15183,13 +15242,10 @@ function parse_workbook(blob, options) {
|
||||
}
|
||||
if(options.cellFormula && line.f) {
|
||||
for(var afi = 0; afi < arrayf.length; ++afi) {
|
||||
if(arrayf[afi][0].s.c > cell.c) continue;
|
||||
if(arrayf[afi][0].s.r > cell.r) continue;
|
||||
if(arrayf[afi][0].e.c < cell.c) continue;
|
||||
if(arrayf[afi][0].e.r < cell.r) continue;
|
||||
if(arrayf[afi][0].s.c > cell.c || arrayf[afi][0].s.r > cell.r) continue;
|
||||
if(arrayf[afi][0].e.c < cell.c || arrayf[afi][0].e.r < cell.r) continue;
|
||||
line.F = encode_range(arrayf[afi][0]);
|
||||
if(arrayf[afi][0].s.c != cell.c) delete line.f;
|
||||
if(arrayf[afi][0].s.r != cell.r) delete line.f;
|
||||
if(arrayf[afi][0].s.c != cell.c || arrayf[afi][0].s.r != cell.r) delete line.f;
|
||||
if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts);
|
||||
break;
|
||||
}
|
||||
@ -15206,7 +15262,7 @@ function parse_workbook(blob, options) {
|
||||
enc: false, // encrypted
|
||||
sbcch: 0, // cch in the preceding SupBook
|
||||
snames: [], // sheetnames
|
||||
sharedf: shared_formulae, // shared formulae by address
|
||||
sharedf: sharedf, // shared formulae by address
|
||||
arrayf: arrayf, // array formulae array
|
||||
rrtabid: [], // RRTabId
|
||||
lastuser: "", // Last User from WriteAccess
|
||||
@ -15262,6 +15318,7 @@ function parse_workbook(blob, options) {
|
||||
if(R.n === 'EOF') val = R.f(blob, length, opts);
|
||||
else val = slurp(R, blob, length, opts);
|
||||
var Rn = R.n;
|
||||
if(file_depth == 0 && Rn != 'BOF') continue;
|
||||
/* nested switch statements to workaround V8 128 limit */
|
||||
switch(Rn) {
|
||||
/* Workbook Options */
|
||||
@ -15291,16 +15348,17 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
|
||||
case 'RRTabId': opts.rrtabid = val; break;
|
||||
case 'WinProtect': opts.winlocked = val; break;
|
||||
case 'Template': break; // TODO
|
||||
case 'RefreshAll': wb.opts.RefreshAll = val; break;
|
||||
case 'BookBool': break; // TODO
|
||||
case 'UsesELFs': break;
|
||||
case 'MTRSettings': break;
|
||||
case 'CalcCount': wb.opts.CalcCount = val; break;
|
||||
case 'CalcDelta': wb.opts.CalcDelta = val; break;
|
||||
case 'CalcIter': wb.opts.CalcIter = val; break;
|
||||
case 'CalcMode': wb.opts.CalcMode = val; break;
|
||||
case 'CalcPrecision': wb.opts.CalcPrecision = val; break;
|
||||
case 'CalcSaveRecalc': wb.opts.CalcSaveRecalc = val; break;
|
||||
case 'RefreshAll':
|
||||
case 'CalcCount':
|
||||
case 'CalcDelta':
|
||||
case 'CalcIter':
|
||||
case 'CalcMode':
|
||||
case 'CalcPrecision':
|
||||
case 'CalcSaveRecalc':
|
||||
wb.opts[Rn] = val; break;
|
||||
case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
|
||||
case 'Uncalced': break;
|
||||
case 'ForceFullCalculation': wb.opts.FullCalc = val; break;
|
||||
@ -15442,7 +15500,7 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F;
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
@ -15482,7 +15540,7 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
|
||||
if(last_cell) {
|
||||
/* TODO: capture range */
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
shared_formulae[encode_cell(last_formula.cell)]= val[0];
|
||||
sharedf[encode_cell(last_formula.cell)]= val[0];
|
||||
cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
|
||||
(cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
}
|
||||
@ -19217,11 +19275,26 @@ function sheet_to_formulae(sheet) {
|
||||
return cmds;
|
||||
}
|
||||
|
||||
function json_to_sheet(js, opts) {
|
||||
function sheet_add_json(_ws, js, opts) {
|
||||
var o = opts || {};
|
||||
var ws = ({});
|
||||
var offset = +!o.skipHeader;
|
||||
var ws = _ws || ({});
|
||||
var _R = 0, _C = 0;
|
||||
if(ws && o.origin != null) {
|
||||
if(typeof o.origin == 'number') _R = o.origin;
|
||||
else {
|
||||
var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
|
||||
_R = _origin.r; _C = _origin.c;
|
||||
}
|
||||
}
|
||||
var cell;
|
||||
var range = ({s: {c:0, r:0}, e: {c:0, r:js.length}});
|
||||
var range = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}});
|
||||
if(ws['!ref']) {
|
||||
var _range = safe_decode_range(ws['!ref']);
|
||||
range.e.c = Math.max(range.e.c, _range.e.c);
|
||||
range.e.r = Math.max(range.e.r, _range.e.r);
|
||||
if(_R == -1) { _R = range.e.r + 1; range.e.r = _R + js.length - 1 + offset; }
|
||||
}
|
||||
var hdr = o.header || [], C = 0;
|
||||
|
||||
js.forEach(function (JS, R) {
|
||||
@ -19238,15 +19311,17 @@ function json_to_sheet(js, opts) {
|
||||
if(!o.cellDates) { t = 'n'; v = datenum(v); }
|
||||
z = o.dateNF || SSF._table[14];
|
||||
}
|
||||
ws[encode_cell({c:C,r:R+1})] = cell = ({t:t, v:v});
|
||||
ws[encode_cell({c:_C + C,r:_R + R + offset})] = cell = ({t:t, v:v});
|
||||
if(z) cell.z = z;
|
||||
});
|
||||
});
|
||||
range.e.c = hdr.length - 1;
|
||||
for(C = 0; C < hdr.length; ++C) ws[encode_col(C) + "1"] = {t:'s', v:hdr[C]};
|
||||
range.e.c = Math.max(range.e.c, _C + hdr.length - 1);
|
||||
var __R = encode_row(_R);
|
||||
if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]};
|
||||
ws['!ref'] = encode_range(range);
|
||||
return ws;
|
||||
}
|
||||
function json_to_sheet(js, opts) { return sheet_add_json(null, js, opts); }
|
||||
|
||||
var utils = {
|
||||
encode_col: encode_col,
|
||||
@ -19263,6 +19338,8 @@ var utils = {
|
||||
make_csv: sheet_to_csv,
|
||||
make_json: sheet_to_json,
|
||||
make_formulae: sheet_to_formulae,
|
||||
sheet_add_aoa: sheet_add_aoa,
|
||||
sheet_add_json: sheet_add_json,
|
||||
aoa_to_sheet: aoa_to_sheet,
|
||||
json_to_sheet: json_to_sheet,
|
||||
table_to_sheet: parse_dom_table,
|
||||
|
24
dist/xlsx.min.js
generated
vendored
24
dist/xlsx.min.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.min.map
generated
vendored
2
dist/xlsx.min.map
generated
vendored
File diff suppressed because one or more lines are too long
@ -4,7 +4,7 @@ The [`demos` directory](demos/) includes sample projects for:
|
||||
|
||||
**Frameworks and APIs**
|
||||
- [`angular 1.x`](demos/angular/)
|
||||
- [`angular 2.x / 4.x / 5.x`](demos/angular2/)
|
||||
- [`angular 2 / 4 / 5 and ionic`](demos/angular2/)
|
||||
- [`meteor`](demos/meteor/)
|
||||
- [`react and react-native`](demos/react/)
|
||||
- [`vue 2.x and weex`](demos/vue/)
|
||||
|
@ -37,6 +37,8 @@ Utilities are available in the `XLSX.utils` object and are described in the
|
||||
- `aoa_to_sheet` converts an array of arrays of JS data to a worksheet.
|
||||
- `json_to_sheet` converts an array of JS objects to a worksheet.
|
||||
- `table_to_sheet` converts a DOM TABLE element to a worksheet.
|
||||
- `sheet_add_aoa` adds an array of arrays of JS data to an existing worksheet.
|
||||
- `sheet_add_json` adds an array of JS objects to an existing worksheet.
|
||||
|
||||
|
||||
**Exporting:**
|
||||
|
@ -42,6 +42,61 @@ var ws = XLSX.utils.aoa_to_sheet([
|
||||
```
|
||||
</details>
|
||||
|
||||
`XLSX.utils.sheet_add_aoa` takes an array of arrays of JS values and updates an
|
||||
existing worksheet object. It follows the same process as `aoa_to_sheet` and
|
||||
accepts an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :------: | :-------------------------------------------------- |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`sheetStubs` | false | Create cell objects of type `z` for `null` values |
|
||||
|`origin` | | Use specified cell as starting point (see below) |
|
||||
|
||||
`origin` is expected to be one of:
|
||||
|
||||
| `origin` | Description |
|
||||
| :--------------- | :-------------------------------------------------------- |
|
||||
| (cell object) | Use specified cell (cell object) |
|
||||
| (string) | Use specified cell (A1-style cell) |
|
||||
| (number >= 0) | Start from the first column at specified row (0-indexed) |
|
||||
| -1 | Append to bottom of worksheet starting on first column |
|
||||
| (default) | Start from cell A1 |
|
||||
|
||||
|
||||
<details>
|
||||
<summary><b>Examples</b> (click to show)</summary>
|
||||
|
||||
Consider the worksheet:
|
||||
|
||||
```
|
||||
XXX| A | B | C | D | E | F | G |
|
||||
---+---+---+---+---+---+---+---+
|
||||
1 | S | h | e | e | t | J | S |
|
||||
2 | 1 | 2 | | | 5 | 6 | 7 |
|
||||
3 | 2 | 3 | | | 6 | 7 | 8 |
|
||||
4 | 3 | 4 | | | 7 | 8 | 9 |
|
||||
5 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |
|
||||
```
|
||||
|
||||
This worksheet can be built up in the order `A1:G1, A2:B4, E2:G4, A5:G5`:
|
||||
|
||||
```js
|
||||
/* Initial row */
|
||||
var ws = XLSX.utils.aoa_to_sheet([ "SheetJS".split("") ]);
|
||||
|
||||
/* Write data starting at A2 */
|
||||
XLSX.utils.sheet_add_aoa(ws, [[1,2], [2,3], [3,4]], {origin: "A2"});
|
||||
|
||||
/* Write data starting at E2 */
|
||||
XLSX.utils.sheet_add_aoa(ws, [[5,6,7], [6,7,8], [7,8,9]], {origin:{r:1, c:4}});
|
||||
|
||||
/* Append row */
|
||||
XLSX.utils.sheet_add_aoa(ws, [[4,5,6,7,8,9,0]], {origin: -1});
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Array of Objects Input
|
||||
|
||||
`XLSX.utils.json_to_sheet` takes an array of objects and returns a worksheet
|
||||
@ -54,19 +109,95 @@ default column order is determined by the first appearance of the field using
|
||||
|`header` | | Use specified column order (default `Object.keys`) |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`skipHeader` | false | If true, do not include header row in output |
|
||||
|
||||
<details>
|
||||
<summary><b>Examples</b> (click to show)</summary>
|
||||
|
||||
The original sheet cannot be reproduced because JS object keys must be unique.
|
||||
After replacing the second `e` and `S` with `e_1` and `S_1`:
|
||||
The original sheet cannot be reproduced in the obvious way since JS object keys
|
||||
must be unique. After replacing the second `e` and `S` with `e_1` and `S_1`:
|
||||
|
||||
```js
|
||||
var ws = XLSX.utils.json_to_sheet([
|
||||
{S:1,h:2,e:3,e_1:4,t:5,J:6,S_1:7},
|
||||
{S:2,h:3,e:4,e_1:5,t:6,J:7,S_1:8}
|
||||
{ S:1, h:2, e:3, e_1:4, t:5, J:6, S_1:7 },
|
||||
{ S:2, h:3, e:4, e_1:5, t:6, J:7, S_1:8 }
|
||||
], {header:["S","h","e","e_1","t","J","S_1"]});
|
||||
```
|
||||
|
||||
Alternatively, the header row can be skipped:
|
||||
|
||||
```js
|
||||
var ws = XLSX.utils.json_to_sheet([
|
||||
{ A:"S", B:"h", C:"e", D:"e", E:"t", F:"J", G:"S" },
|
||||
{ A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7 },
|
||||
{ A: 2, B: 3, C: 4, D: 5, E: 6, F: 7, G: 8 }
|
||||
], {header:["A","B","C","D","E","F","G"], skipHeader:true});
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
`XLSX.utils.sheet_add_json` takes an array of objects and updates an existing
|
||||
worksheet object. It follows the same process as `json_to_sheet` and accepts
|
||||
an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :------: | :-------------------------------------------------- |
|
||||
|`header` | | Use specified column order (default `Object.keys`) |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`skipHeader` | false | If true, do not include header row in output |
|
||||
|`origin` | | Use specified cell as starting point (see below) |
|
||||
|
||||
`origin` is expected to be one of:
|
||||
|
||||
| `origin` | Description |
|
||||
| :--------------- | :-------------------------------------------------------- |
|
||||
| (cell object) | Use specified cell (cell object) |
|
||||
| (string) | Use specified cell (A1-style cell) |
|
||||
| (number >= 0) | Start from the first column at specified row (0-indexed) |
|
||||
| -1 | Append to bottom of worksheet starting on first column |
|
||||
| (default) | Start from cell A1 |
|
||||
|
||||
|
||||
<details>
|
||||
<summary><b>Examples</b> (click to show)</summary>
|
||||
|
||||
Consider the worksheet:
|
||||
|
||||
```
|
||||
XXX| A | B | C | D | E | F | G |
|
||||
---+---+---+---+---+---+---+---+
|
||||
1 | S | h | e | e | t | J | S |
|
||||
2 | 1 | 2 | | | 5 | 6 | 7 |
|
||||
3 | 2 | 3 | | | 6 | 7 | 8 |
|
||||
4 | 3 | 4 | | | 7 | 8 | 9 |
|
||||
5 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |
|
||||
```
|
||||
|
||||
This worksheet can be built up in the order `A1:G1, A2:B4, E2:G4, A5:G5`:
|
||||
|
||||
```js
|
||||
/* Initial row */
|
||||
var ws = XLSX.utils.json_to_sheet([
|
||||
{ A: "S", B: "h", C: "e", D: "e", E: "t", F: "J", G: "S" }
|
||||
], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true});
|
||||
|
||||
/* Write data starting at A2 */
|
||||
XLSX.utils.sheet_add_json(ws, [
|
||||
{ A: 1, B: 2 }, { A: 2, B: 3 }, { A: 3, B: 4 }
|
||||
], {skipHeader: true, origin: "A2"});
|
||||
|
||||
/* Write data starting at E2 */
|
||||
XLSX.utils.sheet_add_json(ws, [
|
||||
{ A: 5, B: 6, C: 7 }, { A: 6, B: 7, C: 8 }, { A: 7, B: 8, C: 9 }
|
||||
], {skipHeader: true, origin: { r: 1, c: 4 }, header: [ "A", "B", "C" ]});
|
||||
|
||||
/* Append row */
|
||||
XLSX.utils.sheet_add_json(ws, [
|
||||
{ A: 4, B: 5, C: 6, D: 7, E: 8, F: 9, G: 0 }
|
||||
], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true, origin: -1});
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### HTML Table Input
|
||||
|
@ -181,7 +181,7 @@ The [`demos` directory](demos/) includes sample projects for:
|
||||
|
||||
**Frameworks and APIs**
|
||||
- [`angular 1.x`](demos/angular/)
|
||||
- [`angular 2.x / 4.x / 5.x`](demos/angular2/)
|
||||
- [`angular 2 / 4 / 5 and ionic`](demos/angular2/)
|
||||
- [`meteor`](demos/meteor/)
|
||||
- [`react and react-native`](demos/react/)
|
||||
- [`vue 2.x and weex`](demos/vue/)
|
||||
@ -658,6 +658,8 @@ Utilities are available in the `XLSX.utils` object and are described in the
|
||||
- `aoa_to_sheet` converts an array of arrays of JS data to a worksheet.
|
||||
- `json_to_sheet` converts an array of JS objects to a worksheet.
|
||||
- `table_to_sheet` converts a DOM TABLE element to a worksheet.
|
||||
- `sheet_add_aoa` adds an array of arrays of JS data to an existing worksheet.
|
||||
- `sheet_add_json` adds an array of JS objects to an existing worksheet.
|
||||
|
||||
|
||||
**Exporting:**
|
||||
@ -1604,6 +1606,58 @@ var ws = XLSX.utils.aoa_to_sheet([
|
||||
]);
|
||||
```
|
||||
|
||||
`XLSX.utils.sheet_add_aoa` takes an array of arrays of JS values and updates an
|
||||
existing worksheet object. It follows the same process as `aoa_to_sheet` and
|
||||
accepts an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :------: | :-------------------------------------------------- |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`sheetStubs` | false | Create cell objects of type `z` for `null` values |
|
||||
|`origin` | | Use specified cell as starting point (see below) |
|
||||
|
||||
`origin` is expected to be one of:
|
||||
|
||||
| `origin` | Description |
|
||||
| :--------------- | :-------------------------------------------------------- |
|
||||
| (cell object) | Use specified cell (cell object) |
|
||||
| (string) | Use specified cell (A1-style cell) |
|
||||
| (number >= 0) | Start from the first column at specified row (0-indexed) |
|
||||
| -1 | Append to bottom of worksheet starting on first column |
|
||||
| (default) | Start from cell A1 |
|
||||
|
||||
|
||||
|
||||
Consider the worksheet:
|
||||
|
||||
```
|
||||
XXX| A | B | C | D | E | F | G |
|
||||
---+---+---+---+---+---+---+---+
|
||||
1 | S | h | e | e | t | J | S |
|
||||
2 | 1 | 2 | | | 5 | 6 | 7 |
|
||||
3 | 2 | 3 | | | 6 | 7 | 8 |
|
||||
4 | 3 | 4 | | | 7 | 8 | 9 |
|
||||
5 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |
|
||||
```
|
||||
|
||||
This worksheet can be built up in the order `A1:G1, A2:B4, E2:G4, A5:G5`:
|
||||
|
||||
```js
|
||||
/* Initial row */
|
||||
var ws = XLSX.utils.aoa_to_sheet([ "SheetJS".split("") ]);
|
||||
|
||||
/* Write data starting at A2 */
|
||||
XLSX.utils.sheet_add_aoa(ws, [[1,2], [2,3], [3,4]], {origin: "A2"});
|
||||
|
||||
/* Write data starting at E2 */
|
||||
XLSX.utils.sheet_add_aoa(ws, [[5,6,7], [6,7,8], [7,8,9]], {origin:{r:1, c:4}});
|
||||
|
||||
/* Append row */
|
||||
XLSX.utils.sheet_add_aoa(ws, [[4,5,6,7,8,9,0]], {origin: -1});
|
||||
```
|
||||
|
||||
|
||||
### Array of Objects Input
|
||||
|
||||
`XLSX.utils.json_to_sheet` takes an array of objects and returns a worksheet
|
||||
@ -1616,18 +1670,91 @@ default column order is determined by the first appearance of the field using
|
||||
|`header` | | Use specified column order (default `Object.keys`) |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`skipHeader` | false | If true, do not include header row in output |
|
||||
|
||||
|
||||
The original sheet cannot be reproduced because JS object keys must be unique.
|
||||
After replacing the second `e` and `S` with `e_1` and `S_1`:
|
||||
The original sheet cannot be reproduced in the obvious way since JS object keys
|
||||
must be unique. After replacing the second `e` and `S` with `e_1` and `S_1`:
|
||||
|
||||
```js
|
||||
var ws = XLSX.utils.json_to_sheet([
|
||||
{S:1,h:2,e:3,e_1:4,t:5,J:6,S_1:7},
|
||||
{S:2,h:3,e:4,e_1:5,t:6,J:7,S_1:8}
|
||||
{ S:1, h:2, e:3, e_1:4, t:5, J:6, S_1:7 },
|
||||
{ S:2, h:3, e:4, e_1:5, t:6, J:7, S_1:8 }
|
||||
], {header:["S","h","e","e_1","t","J","S_1"]});
|
||||
```
|
||||
|
||||
Alternatively, the header row can be skipped:
|
||||
|
||||
```js
|
||||
var ws = XLSX.utils.json_to_sheet([
|
||||
{ A:"S", B:"h", C:"e", D:"e", E:"t", F:"J", G:"S" },
|
||||
{ A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7 },
|
||||
{ A: 2, B: 3, C: 4, D: 5, E: 6, F: 7, G: 8 }
|
||||
], {header:["A","B","C","D","E","F","G"], skipHeader:true});
|
||||
```
|
||||
|
||||
|
||||
`XLSX.utils.sheet_add_json` takes an array of objects and updates an existing
|
||||
worksheet object. It follows the same process as `json_to_sheet` and accepts
|
||||
an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :------: | :-------------------------------------------------- |
|
||||
|`header` | | Use specified column order (default `Object.keys`) |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`skipHeader` | false | If true, do not include header row in output |
|
||||
|`origin` | | Use specified cell as starting point (see below) |
|
||||
|
||||
`origin` is expected to be one of:
|
||||
|
||||
| `origin` | Description |
|
||||
| :--------------- | :-------------------------------------------------------- |
|
||||
| (cell object) | Use specified cell (cell object) |
|
||||
| (string) | Use specified cell (A1-style cell) |
|
||||
| (number >= 0) | Start from the first column at specified row (0-indexed) |
|
||||
| -1 | Append to bottom of worksheet starting on first column |
|
||||
| (default) | Start from cell A1 |
|
||||
|
||||
|
||||
|
||||
Consider the worksheet:
|
||||
|
||||
```
|
||||
XXX| A | B | C | D | E | F | G |
|
||||
---+---+---+---+---+---+---+---+
|
||||
1 | S | h | e | e | t | J | S |
|
||||
2 | 1 | 2 | | | 5 | 6 | 7 |
|
||||
3 | 2 | 3 | | | 6 | 7 | 8 |
|
||||
4 | 3 | 4 | | | 7 | 8 | 9 |
|
||||
5 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |
|
||||
```
|
||||
|
||||
This worksheet can be built up in the order `A1:G1, A2:B4, E2:G4, A5:G5`:
|
||||
|
||||
```js
|
||||
/* Initial row */
|
||||
var ws = XLSX.utils.json_to_sheet([
|
||||
{ A: "S", B: "h", C: "e", D: "e", E: "t", F: "J", G: "S" }
|
||||
], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true});
|
||||
|
||||
/* Write data starting at A2 */
|
||||
XLSX.utils.sheet_add_json(ws, [
|
||||
{ A: 1, B: 2 }, { A: 2, B: 3 }, { A: 3, B: 4 }
|
||||
], {skipHeader: true, origin: "A2"});
|
||||
|
||||
/* Write data starting at E2 */
|
||||
XLSX.utils.sheet_add_json(ws, [
|
||||
{ A: 5, B: 6, C: 7 }, { A: 6, B: 7, C: 8 }, { A: 7, B: 8, C: 9 }
|
||||
], {skipHeader: true, origin: { r: 1, c: 4 }, header: [ "A", "B", "C" ]});
|
||||
|
||||
/* Append row */
|
||||
XLSX.utils.sheet_add_json(ws, [
|
||||
{ A: 4, B: 5, C: 6, D: 7, E: 8, F: 9, G: 0 }
|
||||
], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true, origin: -1});
|
||||
```
|
||||
|
||||
|
||||
### HTML Table Input
|
||||
|
||||
`XLSX.utils.table_to_sheet` takes a table DOM element and returns a worksheet
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xlsx",
|
||||
"version": "0.11.16",
|
||||
"version": "0.11.17",
|
||||
"author": "sheetjs",
|
||||
"description": "SheetJS Spreadsheet data parser and writer",
|
||||
"keywords": [
|
||||
|
14
test.js
14
test.js
@ -675,6 +675,20 @@ describe('API', function() {
|
||||
X.utils.book_append_sheet(wb, X.utils.aoa_to_sheet([[1,2,3],[4],[5]]));
|
||||
eqarr(wb.SheetNames, ["A","Sheet1","Sheet2","B","Sheet3"]);
|
||||
});
|
||||
it('sheet_add_json', function() {
|
||||
var ws = X.utils.json_to_sheet([{A:"S", B:"h", C:"e", D:"e", E:"t", F:"J", G:"S"}], {header:["A","B","C","D","E","F","G"], skipHeader:true});
|
||||
X.utils.sheet_add_json(ws, [{A:1, B:2}, {A:2, B:3}, {A:3, B:4}], {skipHeader:true, origin:"A2"});
|
||||
X.utils.sheet_add_json(ws, [{A:5, B:6, C:7}, {A:6, B:7, C:8}, {A:7, B:8, C:9}], {skipHeader:true, origin:{r:1, c:4}, header:["A","B","C"]});
|
||||
X.utils.sheet_add_json(ws, [{A:4, B:5, C:6, D:7, E:8, F:9, G:0}], {header:["A","B","C","D","E","F","G"], skipHeader:true, origin:-1});
|
||||
assert.equal(X.utils.sheet_to_csv(ws).trim(), "S,h,e,e,t,J,S\n1,2,,,5,6,7\n2,3,,,6,7,8\n3,4,,,7,8,9\n4,5,6,7,8,9,0");
|
||||
});
|
||||
it('sheet_add_aoa', function() {
|
||||
var ws = X.utils.aoa_to_sheet([ "SheetJS".split("") ]);
|
||||
X.utils.sheet_add_aoa(ws, [[1,2], [2,3], [3,4]], {origin: "A2"});
|
||||
X.utils.sheet_add_aoa(ws, [[5,6,7], [6,7,8], [7,8,9]], {origin:{r:1, c:4}});
|
||||
X.utils.sheet_add_aoa(ws, [[4,5,6,7,8,9,0]], {origin: -1});
|
||||
assert.equal(X.utils.sheet_to_csv(ws).trim(), "S,h,e,e,t,J,S\n1,2,,,5,6,7\n2,3,,,6,7,8\n3,4,,,7,8,9\n4,5,6,7,8,9,0");
|
||||
});
|
||||
});
|
||||
|
||||
function coreprop(props) {
|
||||
|
14
tests/core.js
generated
14
tests/core.js
generated
@ -675,6 +675,20 @@ describe('API', function() {
|
||||
X.utils.book_append_sheet(wb, X.utils.aoa_to_sheet([[1,2,3],[4],[5]]));
|
||||
eqarr(wb.SheetNames, ["A","Sheet1","Sheet2","B","Sheet3"]);
|
||||
});
|
||||
it('sheet_add_json', function() {
|
||||
var ws = X.utils.json_to_sheet([{A:"S", B:"h", C:"e", D:"e", E:"t", F:"J", G:"S"}], {header:["A","B","C","D","E","F","G"], skipHeader:true});
|
||||
X.utils.sheet_add_json(ws, [{A:1, B:2}, {A:2, B:3}, {A:3, B:4}], {skipHeader:true, origin:"A2"});
|
||||
X.utils.sheet_add_json(ws, [{A:5, B:6, C:7}, {A:6, B:7, C:8}, {A:7, B:8, C:9}], {skipHeader:true, origin:{r:1, c:4}, header:["A","B","C"]});
|
||||
X.utils.sheet_add_json(ws, [{A:4, B:5, C:6, D:7, E:8, F:9, G:0}], {header:["A","B","C","D","E","F","G"], skipHeader:true, origin:-1});
|
||||
assert.equal(X.utils.sheet_to_csv(ws).trim(), "S,h,e,e,t,J,S\n1,2,,,5,6,7\n2,3,,,6,7,8\n3,4,,,7,8,9\n4,5,6,7,8,9,0");
|
||||
});
|
||||
it('sheet_add_aoa', function() {
|
||||
var ws = X.utils.aoa_to_sheet([ "SheetJS".split("") ]);
|
||||
X.utils.sheet_add_aoa(ws, [[1,2], [2,3], [3,4]], {origin: "A2"});
|
||||
X.utils.sheet_add_aoa(ws, [[5,6,7], [6,7,8], [7,8,9]], {origin:{r:1, c:4}});
|
||||
X.utils.sheet_add_aoa(ws, [[4,5,6,7,8,9,0]], {origin: -1});
|
||||
assert.equal(X.utils.sheet_to_csv(ws).trim(), "S,h,e,e,t,J,S\n1,2,,,5,6,7\n2,3,,,6,7,8\n3,4,,,7,8,9\n4,5,6,7,8,9,0");
|
||||
});
|
||||
});
|
||||
|
||||
function coreprop(props) {
|
||||
|
24
types/doc.ts
24
types/doc.ts
@ -64,6 +64,11 @@ const ws1 = XLSX.utils.aoa_to_sheet([
|
||||
sheetStubs: false
|
||||
});
|
||||
|
||||
const ws1b = XLSX.utils.aoa_to_sheet([ "SheetJS".split("") ]);
|
||||
XLSX.utils.sheet_add_aoa(ws1b, [[1,2], [2,3], [3,4]], {origin: "A2"});
|
||||
XLSX.utils.sheet_add_aoa(ws1b, [[5,6,7], [6,7,8], [7,8,9]], {origin:{r:1, c:4}});
|
||||
XLSX.utils.sheet_add_aoa(ws1b, [[4,5,6,7,8,9,0]], {origin: -1});
|
||||
|
||||
const ws2 = XLSX.utils.json_to_sheet([
|
||||
{S:1,h:2,e:3,e_1:4,t:5,J:6,S_1:7},
|
||||
{S:2,h:3,e:4,e_1:5,t:6,J:7,S_1:8}
|
||||
@ -73,6 +78,25 @@ const ws2 = XLSX.utils.json_to_sheet([
|
||||
dateNF: "yyyy-mm-dd"
|
||||
});
|
||||
|
||||
const ws2b = XLSX.utils.json_to_sheet([
|
||||
{ A:"S", B:"h", C:"e", D:"e", E:"t", F:"J", G:"S" },
|
||||
{ A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7 },
|
||||
{ A: 2, B: 3, C: 4, D: 5, E: 6, F: 7, G: 8 }
|
||||
], {header:["A","B","C","D","E","F","G"], skipHeader:true});
|
||||
|
||||
const ws2c = XLSX.utils.json_to_sheet([
|
||||
{ A: "S", B: "h", C: "e", D: "e", E: "t", F: "J", G: "S" }
|
||||
], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true});
|
||||
XLSX.utils.sheet_add_json(ws2c, [
|
||||
{ A: 1, B: 2 }, { A: 2, B: 3 }, { A: 3, B: 4 }
|
||||
], {skipHeader: true, origin: "A2"});
|
||||
XLSX.utils.sheet_add_json(ws2c, [
|
||||
{ A: 5, B: 6, C: 7 }, { A: 6, B: 7, C: 8 }, { A: 7, B: 8, C: 9 }
|
||||
], {skipHeader: true, origin: { r: 1, c: 4 }, header: [ "A", "B", "C" ]});
|
||||
XLSX.utils.sheet_add_json(ws2c, [
|
||||
{ A: 4, B: 5, C: 6, D: 7, E: 8, F: 9, G: 0 }
|
||||
], {header: ["A", "B", "C", "D", "E", "F", "G"], skipHeader: true, origin: -1});
|
||||
|
||||
const tbl = {}; /* document.getElementById('table'); */
|
||||
const ws3 = XLSX.utils.table_to_sheet(tbl, {
|
||||
raw: true,
|
||||
|
21
types/index.d.ts
vendored
21
types/index.d.ts
vendored
@ -596,6 +596,11 @@ export interface Sheet2CSVOpts extends DateNFOption {
|
||||
skipHidden?: boolean;
|
||||
}
|
||||
|
||||
export interface OriginOption {
|
||||
/** Top-Left cell for operation (CellAddress or A1 string or row) */
|
||||
origin?: number | string | CellAddress;
|
||||
}
|
||||
|
||||
export interface Sheet2HTMLOpts {
|
||||
/** Add contenteditable to every cell */
|
||||
editable?: boolean;
|
||||
@ -632,11 +637,18 @@ export interface AOA2SheetOpts extends CommonOptions, DateNFOption {
|
||||
sheetStubs?: boolean;
|
||||
}
|
||||
|
||||
export interface SheetAOAOpts extends AOA2SheetOpts, OriginOption {}
|
||||
|
||||
export interface JSON2SheetOpts extends CommonOptions, DateNFOption {
|
||||
/** Use specified column order */
|
||||
header?: string[];
|
||||
|
||||
/** Skip header row in generated sheet */
|
||||
skipHeader?: boolean;
|
||||
}
|
||||
|
||||
export interface SheetJSONOpts extends JSON2SheetOpts, OriginOption {}
|
||||
|
||||
export interface Table2SheetOpts extends CommonOptions, DateNFOption {
|
||||
/* If true, plaintext parsing will not parse values */
|
||||
raw?: boolean;
|
||||
@ -739,6 +751,15 @@ export interface XLSX$Utils {
|
||||
/** Assign an Array Formula to a range */
|
||||
sheet_set_array_formula(ws: WorkSheet, range: Range|string, formula: string): WorkSheet;
|
||||
|
||||
/** Add an array of arrays of JS data to a worksheet */
|
||||
sheet_add_aoa<T>(ws: WorkSheet, data: T[][], opts?: SheetAOAOpts): WorkSheet;
|
||||
sheet_add_aoa(ws: WorkSheet, data: any[][], opts?: SheetAOAOpts): WorkSheet;
|
||||
|
||||
/** Add an array of JS objects to a worksheet */
|
||||
sheet_add_json(ws: WorkSheet, data: any[], opts?: SheetJSONOpts): WorkSheet;
|
||||
sheet_add_json<T>(ws: WorkSheet, data: T[], opts?: SheetJSONOpts): WorkSheet;
|
||||
|
||||
|
||||
consts: XLSX$Consts;
|
||||
}
|
||||
|
||||
|
185
xlsx.flow.js
185
xlsx.flow.js
@ -4,7 +4,7 @@
|
||||
/*global global, exports, module, require:false, process:false, Buffer:false */
|
||||
var XLSX = {};
|
||||
(function make_xlsx(XLSX){
|
||||
XLSX.version = '0.11.16';
|
||||
XLSX.version = '0.11.17';
|
||||
var current_codepage = 1200, current_ansi = 1252;
|
||||
/*:: declare var cptable:any; */
|
||||
/*global cptable:true */
|
||||
@ -2118,11 +2118,16 @@ function escapexml(text/*:string*/, xml/*:?boolean*/)/*:string*/{
|
||||
function escapexmltag(text/*:string*/)/*:string*/{ return escapexml(text).replace(/ /g,"_x0020_"); }
|
||||
|
||||
var htmlcharegex = /[\u0000-\u001f]/g;
|
||||
function escapehtml(text){
|
||||
function escapehtml(text/*:string*/)/*:string*/{
|
||||
var s = text + '';
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; });
|
||||
}
|
||||
|
||||
function escapexlml(text/*:string*/)/*:string*/{
|
||||
var s = text + '';
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; });
|
||||
}
|
||||
|
||||
/* TODO: handle codepages */
|
||||
var xlml_fixstr/*:StringConv*/ = (function() {
|
||||
var entregex = /&#(\d+);/g;
|
||||
@ -2615,8 +2620,8 @@ function shift_cell_xls(cell/*:CellAddress*/, tgt/*:any*/, opts/*:?any*/)/*:Cell
|
||||
if(out.cRel) out.c += tgt.s.c;
|
||||
if(out.rRel) out.r += tgt.s.r;
|
||||
} else {
|
||||
out.c += tgt.c;
|
||||
out.r += tgt.r;
|
||||
if(out.cRel) out.c += tgt.c;
|
||||
if(out.rRel) out.r += tgt.r;
|
||||
}
|
||||
if(!opts || opts.biff < 12) {
|
||||
while(out.c >= 0x100) out.c -= 0x100;
|
||||
@ -2772,20 +2777,38 @@ function sheet_to_workbook(sheet/*:Worksheet*/, opts)/*:Workbook*/ {
|
||||
return { SheetNames: [n], Sheets: sheets };
|
||||
}
|
||||
|
||||
function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
|
||||
function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
|
||||
var o = opts || {};
|
||||
if(DENSE != null && o.dense == null) o.dense = DENSE;
|
||||
var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/);
|
||||
var dense = _ws ? Array.isArray(_ws) : o.dense;
|
||||
if(DENSE != null && dense == null) dense = DENSE;
|
||||
var ws/*:Worksheet*/ = _ws || (dense ? ([]/*:any*/) : ({}/*:any*/));
|
||||
var _R = 0, _C = 0;
|
||||
if(ws && o.origin != null) {
|
||||
if(typeof o.origin == 'number') _R = o.origin;
|
||||
else {
|
||||
var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
|
||||
_R = _origin.r; _C = _origin.c;
|
||||
}
|
||||
}
|
||||
var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/);
|
||||
if(ws['!ref']) {
|
||||
var _range = safe_decode_range(ws['!ref']);
|
||||
range.s.c = _range.s.c;
|
||||
range.s.r = _range.s.r;
|
||||
range.e.c = Math.max(range.e.c, _range.e.c);
|
||||
range.e.r = Math.max(range.e.r, _range.e.r);
|
||||
if(_R == -1) range.e.r = _R = _range.e.r + 1;
|
||||
}
|
||||
for(var R = 0; R != data.length; ++R) {
|
||||
for(var C = 0; C != data[R].length; ++C) {
|
||||
if(typeof data[R][C] === 'undefined') continue;
|
||||
var cell/*:Cell*/ = ({v: data[R][C] }/*:any*/);
|
||||
if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
|
||||
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 __R = _R + R, __C = _C + 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;
|
||||
if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.cellStubs) continue; else cell.t = 'z'; }
|
||||
else if(typeof cell.v === 'number') cell.t = 'n';
|
||||
else if(typeof cell.v === 'boolean') cell.t = 'b';
|
||||
@ -2795,11 +2818,11 @@ function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
|
||||
else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); }
|
||||
}
|
||||
else cell.t = 's';
|
||||
if(o.dense) {
|
||||
if(!ws[R]) ws[R] = [];
|
||||
ws[R][C] = cell;
|
||||
if(dense) {
|
||||
if(!ws[__R]) ws[__R] = [];
|
||||
ws[__R][__C] = cell;
|
||||
} else {
|
||||
var cell_ref = encode_cell(({c:C,r:R}/*:any*/));
|
||||
var cell_ref = encode_cell(({c:__C,r:__R}/*:any*/));
|
||||
ws[cell_ref] = cell;
|
||||
}
|
||||
}
|
||||
@ -2807,6 +2830,7 @@ function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ {
|
||||
if(range.s.c < 10000000) ws['!ref'] = encode_range(range);
|
||||
return ws;
|
||||
}
|
||||
function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { return sheet_add_aoa(null, data, opts); }
|
||||
|
||||
function write_UInt32LE(x/*:number*/, o) {
|
||||
if(!o) o = new_buf(4);
|
||||
@ -4132,6 +4156,7 @@ function xlml_write_custprops(Props, Custprops, opts) {
|
||||
if(Custprops) keys(Custprops).forEach(function(k) {
|
||||
/*:: if(!Custprops) return; */
|
||||
if(!Custprops.hasOwnProperty(k)) return;
|
||||
if(Props && Props.hasOwnProperty(k)) return;
|
||||
var m = Custprops[k];
|
||||
var t = "string";
|
||||
if(typeof m == 'number') { t = "float"; m = String(m); }
|
||||
@ -5309,7 +5334,7 @@ function parse_ShrFmla(blob, length, opts) {
|
||||
blob.l++;
|
||||
var cUse = blob.read_shift(1);
|
||||
length -= 8;
|
||||
return [parse_SharedParsedFormula(blob, length, opts), cUse];
|
||||
return [parse_SharedParsedFormula(blob, length, opts), cUse, ref];
|
||||
}
|
||||
|
||||
/* 2.4.4 TODO */
|
||||
@ -7184,10 +7209,8 @@ function parse_DataSpaceDefinition(blob, length)/*:Array<string>*/ {
|
||||
function parse_TransformInfoHeader(blob, length) {
|
||||
var o = {};
|
||||
var len = blob.read_shift(4);
|
||||
var tgt = blob.l + len - 4;
|
||||
blob.l += 4; // must be 0x1
|
||||
o.id = blob.read_shift(0, 'lpp4');
|
||||
if(tgt != blob.l) throw new Error("Bad TransformInfoHeader record: " + blob.l + " != " + tgt);
|
||||
o.name = blob.read_shift(0, 'lpp4');
|
||||
o.R = parse_CRYPTOVersion(blob, 4);
|
||||
o.U = parse_CRYPTOVersion(blob, 4);
|
||||
@ -9176,12 +9199,13 @@ var rc_to_a1 = (function(){
|
||||
|
||||
var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)([1-9]\d{0,5}|10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6])(?![_.\(A-Za-z0-9])/g;
|
||||
var a1_to_rc =(function(){
|
||||
return function a1_to_rc(fstr, base) {
|
||||
return function a1_to_rc(fstr/*:string*/, base/*:CellAddress*/) {
|
||||
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
|
||||
/* TODO: handle fixcol / fixrow */
|
||||
var c = decode_col($3) - base.c;
|
||||
var r = decode_row($5) - base.r;
|
||||
return $1 + "R" + (r == 0 ? "" : "[" + r + "]") + "C" + (c == 0 ? "" : "[" + c + "]");
|
||||
var c = decode_col($3) - ($2 ? 0 : base.c);
|
||||
var r = decode_row($5) - ($4 ? 0 : base.r);
|
||||
var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1));
|
||||
var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1));
|
||||
return $1 + "R" + R + "C" + C;
|
||||
});
|
||||
};
|
||||
})();
|
||||
@ -9277,7 +9301,7 @@ function parse_RgceLocRel(blob, length, opts) {
|
||||
if(biff >= 2 && biff <= 5) return parse_RgceLocRel_BIFF2(blob, length, opts);
|
||||
var r = blob.read_shift(biff >= 12 ? 4 : 2);
|
||||
var cl = blob.read_shift(2);
|
||||
var cRel = (cl & 0x8000) >> 15, rRel = (cl & 0x4000) >> 14;
|
||||
var cRel = (cl & 0x4000) >> 14, rRel = (cl & 0x8000) >> 15;
|
||||
cl &= 0x3FFF;
|
||||
if(rRel == 1) while(r > 0x7FFFF) r -= 0x100000;
|
||||
if(cRel == 1) while(cl > 0x1FFF) cl = cl - 0x4000;
|
||||
@ -10050,7 +10074,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks,
|
||||
case 'PtgErr': /* 2.5.198.57 */
|
||||
stack.push(/*::String(*/f[1]/*::)*/); break;
|
||||
case 'PtgAreaN': /* 2.5.198.31 TODO */
|
||||
type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts);
|
||||
type = f[1][0]; r = shift_range_xls(f[1][1], cell ? {s:cell} : _range, opts);
|
||||
stack.push(encode_range_xls((r/*:any*/), opts));
|
||||
break;
|
||||
case 'PtgArea': /* 2.5.198.27 TODO: fixed points */
|
||||
@ -14359,7 +14383,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
|
||||
var _NamedRange = parsexmltag(Rn[0]);
|
||||
var _DefinedName/*:DefinedName*/ = ({
|
||||
Name: _NamedRange.Name,
|
||||
Ref: rc_to_a1(_NamedRange.RefersTo.substr(1))
|
||||
Ref: rc_to_a1(_NamedRange.RefersTo.substr(1), {r:0, c:0})
|
||||
}/*:any*/);
|
||||
if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1;
|
||||
/*:: if(Workbook.Names) */Workbook.Names.push(_DefinedName);
|
||||
@ -14889,6 +14913,37 @@ function write_sty_xlml(wb, opts)/*:string*/ {
|
||||
});
|
||||
return writextag("Styles", styles.join(""));
|
||||
}
|
||||
function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); }
|
||||
function write_names_xlml(wb, opts)/*:string*/ {
|
||||
if(!((wb||{}).Workbook||{}).Names) return "";
|
||||
/*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */
|
||||
var names/*:Array<any>*/ = wb.Workbook.Names;
|
||||
var out/*:Array<string>*/ = [];
|
||||
for(var i = 0; i < names.length; ++i) {
|
||||
var n = names[i];
|
||||
if(n.Sheet != null) continue;
|
||||
if(n.Name.match(/^_xlfn\./)) continue;
|
||||
out.push(write_name_xlml(n));
|
||||
}
|
||||
return writextag("Names", out.join(""));
|
||||
}
|
||||
function write_ws_xlml_names(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
|
||||
if(!ws) return "";
|
||||
if(!((wb||{}).Workbook||{}).Names) return "";
|
||||
/*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */
|
||||
var names/*:Array<any>*/ = wb.Workbook.Names;
|
||||
var out/*:Array<string>*/ = [];
|
||||
outer: for(var i = 0; i < names.length; ++i) {
|
||||
var n = names[i];
|
||||
if(n.Sheet != idx) continue;
|
||||
/*switch(n.Name) {
|
||||
case "_": continue;
|
||||
}*/
|
||||
if(n.Name.match(/^_xlfn\./)) continue;
|
||||
out.push(write_name_xlml(n));
|
||||
}
|
||||
return out.join("");
|
||||
}
|
||||
/* WorksheetOptions */
|
||||
function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
|
||||
if(!ws) return "";
|
||||
@ -15007,7 +15062,7 @@ function write_ws_xlml_comment(comments/*:Array<any>*/)/*:string*/ {
|
||||
}).join("");
|
||||
}
|
||||
function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, addr)/*:string*/{
|
||||
if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>";
|
||||
if(!cell || cell.v == undefined && cell.f == undefined) return "";
|
||||
|
||||
var attr = {};
|
||||
if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr));
|
||||
@ -15037,11 +15092,12 @@ function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb,
|
||||
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
|
||||
case 'e': t = 'Error'; p = BErr[cell.v]; break;
|
||||
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break;
|
||||
case 's': t = 'String'; p = escapexml(cell.v||""); break;
|
||||
case 's': t = 'String'; p = escapexlml(cell.v||""); break;
|
||||
}
|
||||
/* TODO: cell style */
|
||||
var os = get_cell_style(opts.cellXfs, cell, opts);
|
||||
attr["ss:StyleID"] = "s" + (21+os);
|
||||
attr["ss:Index"] = addr.c + 1;
|
||||
var _v = (cell.v != null ? p : "");
|
||||
var m = '<Data ss:Type="' + t + '">' + _v + '</Data>';
|
||||
|
||||
@ -15101,8 +15157,11 @@ function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ {
|
||||
var s = wb.SheetNames[idx];
|
||||
var ws = wb.Sheets[s];
|
||||
|
||||
var t/*:string*/ = ws ? write_ws_xlml_names(ws, opts, idx, wb) : "";
|
||||
if(t.length > 0) o.push("<Names>" + t + "</Names>");
|
||||
|
||||
/* Table */
|
||||
var t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
|
||||
t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
|
||||
if(t.length > 0) o.push("<Table>" + t + "</Table>");
|
||||
|
||||
/* WorksheetOptions */
|
||||
@ -15125,9 +15184,11 @@ function write_xlml(wb, opts)/*:string*/ {
|
||||
d.push(write_props_xlml(wb, opts));
|
||||
d.push(write_wb_xlml(wb, opts));
|
||||
d.push("");
|
||||
d.push("");
|
||||
for(var i = 0; i < wb.SheetNames.length; ++i)
|
||||
d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])}));
|
||||
d[2] = write_sty_xlml(wb, opts);
|
||||
d[3] = write_names_xlml(wb, opts);
|
||||
return XML_HEADER + writextag("Workbook", d.join(""), {
|
||||
'xmlns': XLMLNS.ss,
|
||||
'xmlns:o': XLMLNS.o,
|
||||
@ -15244,7 +15305,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
var cur_sheet = "";
|
||||
var Preamble = {};
|
||||
var lastcell, last_cell = "", cc, cmnt, rngC, rngR;
|
||||
var shared_formulae = {};
|
||||
var sharedf = {};
|
||||
var arrayf/*:Array<[Range, string]>*/ = [];
|
||||
var temp_val/*:Cell*/;
|
||||
var country;
|
||||
@ -15283,13 +15344,10 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
}
|
||||
if(options.cellFormula && line.f) {
|
||||
for(var afi = 0; afi < arrayf.length; ++afi) {
|
||||
if(arrayf[afi][0].s.c > cell.c) continue;
|
||||
if(arrayf[afi][0].s.r > cell.r) continue;
|
||||
if(arrayf[afi][0].e.c < cell.c) continue;
|
||||
if(arrayf[afi][0].e.r < cell.r) continue;
|
||||
if(arrayf[afi][0].s.c > cell.c || arrayf[afi][0].s.r > cell.r) continue;
|
||||
if(arrayf[afi][0].e.c < cell.c || arrayf[afi][0].e.r < cell.r) continue;
|
||||
line.F = encode_range(arrayf[afi][0]);
|
||||
if(arrayf[afi][0].s.c != cell.c) delete line.f;
|
||||
if(arrayf[afi][0].s.r != cell.r) delete line.f;
|
||||
if(arrayf[afi][0].s.c != cell.c || arrayf[afi][0].s.r != cell.r) delete line.f;
|
||||
if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts);
|
||||
break;
|
||||
}
|
||||
@ -15306,7 +15364,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
enc: false, // encrypted
|
||||
sbcch: 0, // cch in the preceding SupBook
|
||||
snames: [], // sheetnames
|
||||
sharedf: shared_formulae, // shared formulae by address
|
||||
sharedf: sharedf, // shared formulae by address
|
||||
arrayf: arrayf, // array formulae array
|
||||
rrtabid: [], // RRTabId
|
||||
lastuser: "", // Last User from WriteAccess
|
||||
@ -15362,6 +15420,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(R.n === 'EOF') val = R.f(blob, length, opts);
|
||||
else val = slurp(R, blob, length, opts);
|
||||
var Rn = R.n;
|
||||
if(file_depth == 0 && Rn != 'BOF') continue;
|
||||
/* nested switch statements to workaround V8 128 limit */
|
||||
switch(Rn) {
|
||||
/* Workbook Options */
|
||||
@ -15392,16 +15451,17 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
case 'RRTabId': opts.rrtabid = val; break;
|
||||
case 'WinProtect': opts.winlocked = val; break;
|
||||
case 'Template': break; // TODO
|
||||
case 'RefreshAll': wb.opts.RefreshAll = val; break;
|
||||
case 'BookBool': break; // TODO
|
||||
case 'UsesELFs': break;
|
||||
case 'MTRSettings': break;
|
||||
case 'CalcCount': wb.opts.CalcCount = val; break;
|
||||
case 'CalcDelta': wb.opts.CalcDelta = val; break;
|
||||
case 'CalcIter': wb.opts.CalcIter = val; break;
|
||||
case 'CalcMode': wb.opts.CalcMode = val; break;
|
||||
case 'CalcPrecision': wb.opts.CalcPrecision = val; break;
|
||||
case 'CalcSaveRecalc': wb.opts.CalcSaveRecalc = val; break;
|
||||
case 'RefreshAll':
|
||||
case 'CalcCount':
|
||||
case 'CalcDelta':
|
||||
case 'CalcIter':
|
||||
case 'CalcMode':
|
||||
case 'CalcPrecision':
|
||||
case 'CalcSaveRecalc':
|
||||
wb.opts[Rn] = val; break;
|
||||
case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
|
||||
case 'Uncalced': break;
|
||||
case 'ForceFullCalculation': wb.opts.FullCalc = val; break;
|
||||
@ -15543,7 +15603,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F;
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
@ -15583,7 +15643,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(last_cell) {
|
||||
/* TODO: capture range */
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
shared_formulae[encode_cell(last_formula.cell)]= val[0];
|
||||
sharedf[encode_cell(last_formula.cell)]= val[0];
|
||||
cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
|
||||
(cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
}
|
||||
@ -19325,14 +19385,29 @@ function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
|
||||
return cmds;
|
||||
}
|
||||
|
||||
function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ {
|
||||
function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet*/ {
|
||||
var o = opts || {};
|
||||
var ws = ({}/*:any*/);
|
||||
var offset = +!o.skipHeader;
|
||||
var ws/*:Worksheet*/ = _ws || ({}/*:any*/);
|
||||
var _R = 0, _C = 0;
|
||||
if(ws && o.origin != null) {
|
||||
if(typeof o.origin == 'number') _R = o.origin;
|
||||
else {
|
||||
var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
|
||||
_R = _origin.r; _C = _origin.c;
|
||||
}
|
||||
}
|
||||
var cell/*:Cell*/;
|
||||
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:js.length}}/*:any*/);
|
||||
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}}/*:any*/);
|
||||
if(ws['!ref']) {
|
||||
var _range = safe_decode_range(ws['!ref']);
|
||||
range.e.c = Math.max(range.e.c, _range.e.c);
|
||||
range.e.r = Math.max(range.e.r, _range.e.r);
|
||||
if(_R == -1) { _R = range.e.r + 1; range.e.r = _R + js.length - 1 + offset; }
|
||||
}
|
||||
var hdr/*:Array<string>*/ = o.header || [], C = 0;
|
||||
|
||||
js.forEach(function (JS, R) {
|
||||
js.forEach(function (JS, R/*:number*/) {
|
||||
keys(JS).filter(function(x) { return JS.hasOwnProperty(x); }).forEach(function(k) {
|
||||
if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k;
|
||||
var v = JS[k];
|
||||
@ -19346,15 +19421,17 @@ function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ {
|
||||
if(!o.cellDates) { t = 'n'; v = datenum(v); }
|
||||
z = o.dateNF || SSF._table[14];
|
||||
}
|
||||
ws[encode_cell({c:C,r:R+1})] = cell = ({t:t, v:v}/*:any*/);
|
||||
ws[encode_cell({c:_C + C,r:_R + R + offset})] = cell = ({t:t, v:v}/*:any*/);
|
||||
if(z) cell.z = z;
|
||||
});
|
||||
});
|
||||
range.e.c = hdr.length - 1;
|
||||
for(C = 0; C < hdr.length; ++C) ws[encode_col(C) + "1"] = {t:'s', v:hdr[C]};
|
||||
range.e.c = Math.max(range.e.c, _C + hdr.length - 1);
|
||||
var __R = encode_row(_R);
|
||||
if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]};
|
||||
ws['!ref'] = encode_range(range);
|
||||
return ws;
|
||||
}
|
||||
function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ { return sheet_add_json(null, js, opts); }
|
||||
|
||||
var utils/*:any*/ = {
|
||||
encode_col: encode_col,
|
||||
@ -19371,6 +19448,8 @@ var utils/*:any*/ = {
|
||||
make_csv: sheet_to_csv,
|
||||
make_json: sheet_to_json,
|
||||
make_formulae: sheet_to_formulae,
|
||||
sheet_add_aoa: sheet_add_aoa,
|
||||
sheet_add_json: sheet_add_json,
|
||||
aoa_to_sheet: aoa_to_sheet,
|
||||
json_to_sheet: json_to_sheet,
|
||||
table_to_sheet: parse_dom_table,
|
||||
|
177
xlsx.js
generated
177
xlsx.js
generated
@ -4,7 +4,7 @@
|
||||
/*global global, exports, module, require:false, process:false, Buffer:false */
|
||||
var XLSX = {};
|
||||
(function make_xlsx(XLSX){
|
||||
XLSX.version = '0.11.16';
|
||||
XLSX.version = '0.11.17';
|
||||
var current_codepage = 1200, current_ansi = 1252;
|
||||
/*global cptable:true */
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
|
||||
@ -2051,6 +2051,11 @@ function escapehtml(text){
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; });
|
||||
}
|
||||
|
||||
function escapexlml(text){
|
||||
var s = text + '';
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; });
|
||||
}
|
||||
|
||||
/* TODO: handle codepages */
|
||||
var xlml_fixstr = (function() {
|
||||
var entregex = /&#(\d+);/g;
|
||||
@ -2538,8 +2543,8 @@ function shift_cell_xls(cell, tgt, opts) {
|
||||
if(out.cRel) out.c += tgt.s.c;
|
||||
if(out.rRel) out.r += tgt.s.r;
|
||||
} else {
|
||||
out.c += tgt.c;
|
||||
out.r += tgt.r;
|
||||
if(out.cRel) out.c += tgt.c;
|
||||
if(out.rRel) out.r += tgt.r;
|
||||
}
|
||||
if(!opts || opts.biff < 12) {
|
||||
while(out.c >= 0x100) out.c -= 0x100;
|
||||
@ -2689,20 +2694,38 @@ function sheet_to_workbook(sheet, opts) {
|
||||
return { SheetNames: [n], Sheets: sheets };
|
||||
}
|
||||
|
||||
function aoa_to_sheet(data, opts) {
|
||||
function sheet_add_aoa(_ws, data, opts) {
|
||||
var o = opts || {};
|
||||
if(DENSE != null && o.dense == null) o.dense = DENSE;
|
||||
var ws = o.dense ? ([]) : ({});
|
||||
var dense = _ws ? Array.isArray(_ws) : o.dense;
|
||||
if(DENSE != null && dense == null) dense = DENSE;
|
||||
var ws = _ws || (dense ? ([]) : ({}));
|
||||
var _R = 0, _C = 0;
|
||||
if(ws && o.origin != null) {
|
||||
if(typeof o.origin == 'number') _R = o.origin;
|
||||
else {
|
||||
var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
|
||||
_R = _origin.r; _C = _origin.c;
|
||||
}
|
||||
}
|
||||
var range = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}});
|
||||
if(ws['!ref']) {
|
||||
var _range = safe_decode_range(ws['!ref']);
|
||||
range.s.c = _range.s.c;
|
||||
range.s.r = _range.s.r;
|
||||
range.e.c = Math.max(range.e.c, _range.e.c);
|
||||
range.e.r = Math.max(range.e.r, _range.e.r);
|
||||
if(_R == -1) range.e.r = _R = _range.e.r + 1;
|
||||
}
|
||||
for(var R = 0; R != data.length; ++R) {
|
||||
for(var C = 0; C != data[R].length; ++C) {
|
||||
if(typeof data[R][C] === 'undefined') continue;
|
||||
var cell = ({v: data[R][C] });
|
||||
if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
|
||||
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 __R = _R + R, __C = _C + 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;
|
||||
if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.cellStubs) continue; else cell.t = 'z'; }
|
||||
else if(typeof cell.v === 'number') cell.t = 'n';
|
||||
else if(typeof cell.v === 'boolean') cell.t = 'b';
|
||||
@ -2712,11 +2735,11 @@ function aoa_to_sheet(data, opts) {
|
||||
else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); }
|
||||
}
|
||||
else cell.t = 's';
|
||||
if(o.dense) {
|
||||
if(!ws[R]) ws[R] = [];
|
||||
ws[R][C] = cell;
|
||||
if(dense) {
|
||||
if(!ws[__R]) ws[__R] = [];
|
||||
ws[__R][__C] = cell;
|
||||
} else {
|
||||
var cell_ref = encode_cell(({c:C,r:R}));
|
||||
var cell_ref = encode_cell(({c:__C,r:__R}));
|
||||
ws[cell_ref] = cell;
|
||||
}
|
||||
}
|
||||
@ -2724,6 +2747,7 @@ function aoa_to_sheet(data, opts) {
|
||||
if(range.s.c < 10000000) ws['!ref'] = encode_range(range);
|
||||
return ws;
|
||||
}
|
||||
function aoa_to_sheet(data, opts) { return sheet_add_aoa(null, data, opts); }
|
||||
|
||||
function write_UInt32LE(x, o) {
|
||||
if(!o) o = new_buf(4);
|
||||
@ -4047,6 +4071,7 @@ if(!Props.hasOwnProperty(k)) return;
|
||||
});
|
||||
if(Custprops) keys(Custprops).forEach(function(k) {
|
||||
if(!Custprops.hasOwnProperty(k)) return;
|
||||
if(Props && Props.hasOwnProperty(k)) return;
|
||||
var m = Custprops[k];
|
||||
var t = "string";
|
||||
if(typeof m == 'number') { t = "float"; m = String(m); }
|
||||
@ -5224,7 +5249,7 @@ function parse_ShrFmla(blob, length, opts) {
|
||||
blob.l++;
|
||||
var cUse = blob.read_shift(1);
|
||||
length -= 8;
|
||||
return [parse_SharedParsedFormula(blob, length, opts), cUse];
|
||||
return [parse_SharedParsedFormula(blob, length, opts), cUse, ref];
|
||||
}
|
||||
|
||||
/* 2.4.4 TODO */
|
||||
@ -7097,10 +7122,8 @@ function parse_DataSpaceDefinition(blob, length) {
|
||||
function parse_TransformInfoHeader(blob, length) {
|
||||
var o = {};
|
||||
var len = blob.read_shift(4);
|
||||
var tgt = blob.l + len - 4;
|
||||
blob.l += 4; // must be 0x1
|
||||
o.id = blob.read_shift(0, 'lpp4');
|
||||
if(tgt != blob.l) throw new Error("Bad TransformInfoHeader record: " + blob.l + " != " + tgt);
|
||||
o.name = blob.read_shift(0, 'lpp4');
|
||||
o.R = parse_CRYPTOVersion(blob, 4);
|
||||
o.U = parse_CRYPTOVersion(blob, 4);
|
||||
@ -9089,10 +9112,11 @@ var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A
|
||||
var a1_to_rc =(function(){
|
||||
return function a1_to_rc(fstr, base) {
|
||||
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
|
||||
/* TODO: handle fixcol / fixrow */
|
||||
var c = decode_col($3) - base.c;
|
||||
var r = decode_row($5) - base.r;
|
||||
return $1 + "R" + (r == 0 ? "" : "[" + r + "]") + "C" + (c == 0 ? "" : "[" + c + "]");
|
||||
var c = decode_col($3) - ($2 ? 0 : base.c);
|
||||
var r = decode_row($5) - ($4 ? 0 : base.r);
|
||||
var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1));
|
||||
var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1));
|
||||
return $1 + "R" + R + "C" + C;
|
||||
});
|
||||
};
|
||||
})();
|
||||
@ -9188,7 +9212,7 @@ function parse_RgceLocRel(blob, length, opts) {
|
||||
if(biff >= 2 && biff <= 5) return parse_RgceLocRel_BIFF2(blob, length, opts);
|
||||
var r = blob.read_shift(biff >= 12 ? 4 : 2);
|
||||
var cl = blob.read_shift(2);
|
||||
var cRel = (cl & 0x8000) >> 15, rRel = (cl & 0x4000) >> 14;
|
||||
var cRel = (cl & 0x4000) >> 14, rRel = (cl & 0x8000) >> 15;
|
||||
cl &= 0x3FFF;
|
||||
if(rRel == 1) while(r > 0x7FFFF) r -= 0x100000;
|
||||
if(cRel == 1) while(cl > 0x1FFF) cl = cl - 0x4000;
|
||||
@ -9960,7 +9984,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell, supbooks, opts) {
|
||||
case 'PtgErr': /* 2.5.198.57 */
|
||||
stack.push(f[1]); break;
|
||||
case 'PtgAreaN': /* 2.5.198.31 TODO */
|
||||
type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts);
|
||||
type = f[1][0]; r = shift_range_xls(f[1][1], cell ? {s:cell} : _range, opts);
|
||||
stack.push(encode_range_xls((r), opts));
|
||||
break;
|
||||
case 'PtgArea': /* 2.5.198.27 TODO: fixed points */
|
||||
@ -14263,7 +14287,7 @@ for(var cma = c; cma <= cc; ++cma) {
|
||||
var _NamedRange = parsexmltag(Rn[0]);
|
||||
var _DefinedName = ({
|
||||
Name: _NamedRange.Name,
|
||||
Ref: rc_to_a1(_NamedRange.RefersTo.substr(1))
|
||||
Ref: rc_to_a1(_NamedRange.RefersTo.substr(1), {r:0, c:0})
|
||||
});
|
||||
if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1;
|
||||
Workbook.Names.push(_DefinedName);
|
||||
@ -14791,6 +14815,35 @@ function write_sty_xlml(wb, opts) {
|
||||
});
|
||||
return writextag("Styles", styles.join(""));
|
||||
}
|
||||
function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); }
|
||||
function write_names_xlml(wb, opts) {
|
||||
if(!((wb||{}).Workbook||{}).Names) return "";
|
||||
var names = wb.Workbook.Names;
|
||||
var out = [];
|
||||
for(var i = 0; i < names.length; ++i) {
|
||||
var n = names[i];
|
||||
if(n.Sheet != null) continue;
|
||||
if(n.Name.match(/^_xlfn\./)) continue;
|
||||
out.push(write_name_xlml(n));
|
||||
}
|
||||
return writextag("Names", out.join(""));
|
||||
}
|
||||
function write_ws_xlml_names(ws, opts, idx, wb) {
|
||||
if(!ws) return "";
|
||||
if(!((wb||{}).Workbook||{}).Names) return "";
|
||||
var names = wb.Workbook.Names;
|
||||
var out = [];
|
||||
outer: for(var i = 0; i < names.length; ++i) {
|
||||
var n = names[i];
|
||||
if(n.Sheet != idx) continue;
|
||||
/*switch(n.Name) {
|
||||
case "_": continue;
|
||||
}*/
|
||||
if(n.Name.match(/^_xlfn\./)) continue;
|
||||
out.push(write_name_xlml(n));
|
||||
}
|
||||
return out.join("");
|
||||
}
|
||||
/* WorksheetOptions */
|
||||
function write_ws_xlml_wsopts(ws, opts, idx, wb) {
|
||||
if(!ws) return "";
|
||||
@ -14909,7 +14962,7 @@ function write_ws_xlml_comment(comments) {
|
||||
}).join("");
|
||||
}
|
||||
function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){
|
||||
if(!cell || cell.v == undefined && cell.f == undefined) return "<Cell></Cell>";
|
||||
if(!cell || cell.v == undefined && cell.f == undefined) return "";
|
||||
|
||||
var attr = {};
|
||||
if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr));
|
||||
@ -14939,11 +14992,12 @@ function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){
|
||||
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
|
||||
case 'e': t = 'Error'; p = BErr[cell.v]; break;
|
||||
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break;
|
||||
case 's': t = 'String'; p = escapexml(cell.v||""); break;
|
||||
case 's': t = 'String'; p = escapexlml(cell.v||""); break;
|
||||
}
|
||||
/* TODO: cell style */
|
||||
var os = get_cell_style(opts.cellXfs, cell, opts);
|
||||
attr["ss:StyleID"] = "s" + (21+os);
|
||||
attr["ss:Index"] = addr.c + 1;
|
||||
var _v = (cell.v != null ? p : "");
|
||||
var m = '<Data ss:Type="' + t + '">' + _v + '</Data>';
|
||||
|
||||
@ -15003,8 +15057,11 @@ function write_ws_xlml(idx, opts, wb) {
|
||||
var s = wb.SheetNames[idx];
|
||||
var ws = wb.Sheets[s];
|
||||
|
||||
var t = ws ? write_ws_xlml_names(ws, opts, idx, wb) : "";
|
||||
if(t.length > 0) o.push("<Names>" + t + "</Names>");
|
||||
|
||||
/* Table */
|
||||
var t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
|
||||
t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
|
||||
if(t.length > 0) o.push("<Table>" + t + "</Table>");
|
||||
|
||||
/* WorksheetOptions */
|
||||
@ -15027,9 +15084,11 @@ function write_xlml(wb, opts) {
|
||||
d.push(write_props_xlml(wb, opts));
|
||||
d.push(write_wb_xlml(wb, opts));
|
||||
d.push("");
|
||||
d.push("");
|
||||
for(var i = 0; i < wb.SheetNames.length; ++i)
|
||||
d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])}));
|
||||
d[2] = write_sty_xlml(wb, opts);
|
||||
d[3] = write_names_xlml(wb, opts);
|
||||
return XML_HEADER + writextag("Workbook", d.join(""), {
|
||||
'xmlns': XLMLNS.ss,
|
||||
'xmlns:o': XLMLNS.o,
|
||||
@ -15144,7 +15203,7 @@ function parse_workbook(blob, options) {
|
||||
var cur_sheet = "";
|
||||
var Preamble = {};
|
||||
var lastcell, last_cell = "", cc, cmnt, rngC, rngR;
|
||||
var shared_formulae = {};
|
||||
var sharedf = {};
|
||||
var arrayf = [];
|
||||
var temp_val;
|
||||
var country;
|
||||
@ -15183,13 +15242,10 @@ function parse_workbook(blob, options) {
|
||||
}
|
||||
if(options.cellFormula && line.f) {
|
||||
for(var afi = 0; afi < arrayf.length; ++afi) {
|
||||
if(arrayf[afi][0].s.c > cell.c) continue;
|
||||
if(arrayf[afi][0].s.r > cell.r) continue;
|
||||
if(arrayf[afi][0].e.c < cell.c) continue;
|
||||
if(arrayf[afi][0].e.r < cell.r) continue;
|
||||
if(arrayf[afi][0].s.c > cell.c || arrayf[afi][0].s.r > cell.r) continue;
|
||||
if(arrayf[afi][0].e.c < cell.c || arrayf[afi][0].e.r < cell.r) continue;
|
||||
line.F = encode_range(arrayf[afi][0]);
|
||||
if(arrayf[afi][0].s.c != cell.c) delete line.f;
|
||||
if(arrayf[afi][0].s.r != cell.r) delete line.f;
|
||||
if(arrayf[afi][0].s.c != cell.c || arrayf[afi][0].s.r != cell.r) delete line.f;
|
||||
if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts);
|
||||
break;
|
||||
}
|
||||
@ -15206,7 +15262,7 @@ function parse_workbook(blob, options) {
|
||||
enc: false, // encrypted
|
||||
sbcch: 0, // cch in the preceding SupBook
|
||||
snames: [], // sheetnames
|
||||
sharedf: shared_formulae, // shared formulae by address
|
||||
sharedf: sharedf, // shared formulae by address
|
||||
arrayf: arrayf, // array formulae array
|
||||
rrtabid: [], // RRTabId
|
||||
lastuser: "", // Last User from WriteAccess
|
||||
@ -15262,6 +15318,7 @@ function parse_workbook(blob, options) {
|
||||
if(R.n === 'EOF') val = R.f(blob, length, opts);
|
||||
else val = slurp(R, blob, length, opts);
|
||||
var Rn = R.n;
|
||||
if(file_depth == 0 && Rn != 'BOF') continue;
|
||||
/* nested switch statements to workaround V8 128 limit */
|
||||
switch(Rn) {
|
||||
/* Workbook Options */
|
||||
@ -15291,16 +15348,17 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
|
||||
case 'RRTabId': opts.rrtabid = val; break;
|
||||
case 'WinProtect': opts.winlocked = val; break;
|
||||
case 'Template': break; // TODO
|
||||
case 'RefreshAll': wb.opts.RefreshAll = val; break;
|
||||
case 'BookBool': break; // TODO
|
||||
case 'UsesELFs': break;
|
||||
case 'MTRSettings': break;
|
||||
case 'CalcCount': wb.opts.CalcCount = val; break;
|
||||
case 'CalcDelta': wb.opts.CalcDelta = val; break;
|
||||
case 'CalcIter': wb.opts.CalcIter = val; break;
|
||||
case 'CalcMode': wb.opts.CalcMode = val; break;
|
||||
case 'CalcPrecision': wb.opts.CalcPrecision = val; break;
|
||||
case 'CalcSaveRecalc': wb.opts.CalcSaveRecalc = val; break;
|
||||
case 'RefreshAll':
|
||||
case 'CalcCount':
|
||||
case 'CalcDelta':
|
||||
case 'CalcIter':
|
||||
case 'CalcMode':
|
||||
case 'CalcPrecision':
|
||||
case 'CalcSaveRecalc':
|
||||
wb.opts[Rn] = val; break;
|
||||
case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
|
||||
case 'Uncalced': break;
|
||||
case 'ForceFullCalculation': wb.opts.FullCalc = val; break;
|
||||
@ -15442,7 +15500,7 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F;
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
@ -15482,7 +15540,7 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
|
||||
if(last_cell) {
|
||||
/* TODO: capture range */
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
shared_formulae[encode_cell(last_formula.cell)]= val[0];
|
||||
sharedf[encode_cell(last_formula.cell)]= val[0];
|
||||
cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
|
||||
(cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
}
|
||||
@ -19217,11 +19275,26 @@ function sheet_to_formulae(sheet) {
|
||||
return cmds;
|
||||
}
|
||||
|
||||
function json_to_sheet(js, opts) {
|
||||
function sheet_add_json(_ws, js, opts) {
|
||||
var o = opts || {};
|
||||
var ws = ({});
|
||||
var offset = +!o.skipHeader;
|
||||
var ws = _ws || ({});
|
||||
var _R = 0, _C = 0;
|
||||
if(ws && o.origin != null) {
|
||||
if(typeof o.origin == 'number') _R = o.origin;
|
||||
else {
|
||||
var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
|
||||
_R = _origin.r; _C = _origin.c;
|
||||
}
|
||||
}
|
||||
var cell;
|
||||
var range = ({s: {c:0, r:0}, e: {c:0, r:js.length}});
|
||||
var range = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}});
|
||||
if(ws['!ref']) {
|
||||
var _range = safe_decode_range(ws['!ref']);
|
||||
range.e.c = Math.max(range.e.c, _range.e.c);
|
||||
range.e.r = Math.max(range.e.r, _range.e.r);
|
||||
if(_R == -1) { _R = range.e.r + 1; range.e.r = _R + js.length - 1 + offset; }
|
||||
}
|
||||
var hdr = o.header || [], C = 0;
|
||||
|
||||
js.forEach(function (JS, R) {
|
||||
@ -19238,15 +19311,17 @@ function json_to_sheet(js, opts) {
|
||||
if(!o.cellDates) { t = 'n'; v = datenum(v); }
|
||||
z = o.dateNF || SSF._table[14];
|
||||
}
|
||||
ws[encode_cell({c:C,r:R+1})] = cell = ({t:t, v:v});
|
||||
ws[encode_cell({c:_C + C,r:_R + R + offset})] = cell = ({t:t, v:v});
|
||||
if(z) cell.z = z;
|
||||
});
|
||||
});
|
||||
range.e.c = hdr.length - 1;
|
||||
for(C = 0; C < hdr.length; ++C) ws[encode_col(C) + "1"] = {t:'s', v:hdr[C]};
|
||||
range.e.c = Math.max(range.e.c, _C + hdr.length - 1);
|
||||
var __R = encode_row(_R);
|
||||
if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]};
|
||||
ws['!ref'] = encode_range(range);
|
||||
return ws;
|
||||
}
|
||||
function json_to_sheet(js, opts) { return sheet_add_json(null, js, opts); }
|
||||
|
||||
var utils = {
|
||||
encode_col: encode_col,
|
||||
@ -19263,6 +19338,8 @@ var utils = {
|
||||
make_csv: sheet_to_csv,
|
||||
make_json: sheet_to_json,
|
||||
make_formulae: sheet_to_formulae,
|
||||
sheet_add_aoa: sheet_add_aoa,
|
||||
sheet_add_json: sheet_add_json,
|
||||
aoa_to_sheet: aoa_to_sheet,
|
||||
json_to_sheet: json_to_sheet,
|
||||
table_to_sheet: parse_dom_table,
|
||||
|
Loading…
Reference in New Issue
Block a user