version bump 0.17.3

This commit is contained in:
SheetJS 2021-10-13 03:20:25 -04:00
parent 5c02c819f6
commit 09bd0755b5
33 changed files with 2614 additions and 1020 deletions

View File

@ -4,6 +4,12 @@ This log is intended to keep track of backwards-incompatible changes, including
but not limited to API changes and file location changes. Minor behavioral
changes may not be included if they are not expected to break existing code.
## v0.17.3
* `window.XLSX` explicit assignment to satiate LWC
* CSV Proper formatting of errors
* HTML emit data-\* attributes
## v0.17.2
* Browser and Node optional ESM support

153
README.md
View File

@ -27,6 +27,7 @@ Community Translations of this README:
[**Issues and Bug Reports**](https://github.com/sheetjs/sheetjs/issues)
![License](https://img.shields.io/github/license/SheetJS/sheetjs)
[![Build Status](https://img.shields.io/github/workflow/status/sheetjs/sheetjs/Tests:%20node.js)](https://github.com/SheetJS/sheetjs/actions)
[![Snyk Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/SheetJS/sheetjs)](https://snyk.io/test/github/SheetJS/sheetjs)
[![npm Downloads](https://img.shields.io/npm/dm/xlsx.svg)](https://npmjs.org/package/xlsx)
[![jsDelivr Downloads](https://data.jsdelivr.com/v1/package/npm/xlsx/badge)](https://www.jsdelivr.com/package/npm/xlsx)
@ -191,7 +192,7 @@ The [`demos` directory](demos/) includes sample projects for:
**Frameworks and APIs**
- [`angularjs`](demos/angular/)
- [`angular 2 / 4 / 5 / 6 and ionic`](demos/angular2/)
- [`angular and ionic`](demos/angular2/)
- [`knockout`](demos/knockout/)
- [`meteor`](demos/meteor/)
- [`react and react-native`](demos/react/)
@ -408,8 +409,7 @@ req.open("GET", url, true);
req.responseType = "arraybuffer";
req.onload = function(e) {
var data = new Uint8Array(req.response);
var workbook = XLSX.read(data, {type:"array"});
var workbook = XLSX.read(req.response);
/* DO SOMETHING WITH workbook HERE */
}
@ -422,16 +422,29 @@ req.send();
<details>
<summary><b>Browser drag-and-drop</b> (click to show)</summary>
Drag-and-drop uses the HTML5 `FileReader` API.
For modern browsers, `Blob#arrayBuffer` can read data from files:
```js
async function handleDropAsync(e) {
e.stopPropagation(); e.preventDefault();
const f = evt.dataTransfer.files[0];
const data = await f.arrayBuffer();
const workbook = XLSX.read(data);
/* DO SOMETHING WITH workbook HERE */
}
drop_dom_element.addEventListener('drop', handleDropAsync, false);
```
For maximal compatibility, the `FileReader` API should be used:
```js
function handleDrop(e) {
e.stopPropagation(); e.preventDefault();
var files = e.dataTransfer.files, f = files[0];
var f = e.dataTransfer.files[0];
var reader = new FileReader();
reader.onload = function(e) {
var data = new Uint8Array(e.target.result);
var workbook = XLSX.read(data, {type: 'array'});
var workbook = XLSX.read(e.target.result);
/* DO SOMETHING WITH workbook HERE */
};
@ -445,16 +458,30 @@ drop_dom_element.addEventListener('drop', handleDrop, false);
<details>
<summary><b>Browser file upload form element</b> (click to show)</summary>
Data from file input elements can be processed using the same `FileReader` API
as in the drag-and-drop example:
Data from file input elements can be processed using the same APIs as in the
drag-and-drop example.
Using `Blob#arrayBuffer`:
```js
async function handleFileAsync(e) {
const file = evt.target.files[0];
const data = await file.arrayBuffer();
const workbook = XLSX.read(data);
/* DO SOMETHING WITH workbook HERE */
}
input_dom_element.addEventListener('change', handleFileAsync, false);
```
Using `FileReader`:
```js
function handleFile(e) {
var files = e.target.files, f = files[0];
var reader = new FileReader();
reader.onload = function(e) {
var data = new Uint8Array(e.target.result);
var workbook = XLSX.read(data, {type: 'array'});
var workbook = XLSX.read(e.target.result);
/* DO SOMETHING WITH workbook HERE */
};
@ -1544,6 +1571,15 @@ specific format string.
#### Hyperlinks
<details>
<summary><b>Format Support</b> (click to show)</summary>
**Cell Hyperlinks**: XLSX/M, XLSB, BIFF8 XLS, XLML, ODS
**Tooltips**: XLSX/M, XLSB, BIFF8 XLS, XLML
</details>
Hyperlinks are stored in the `l` key of cell objects. The `Target` field of the
hyperlink object is the target of the link, including the URI fragment. Tooltips
are stored in the `Tooltip` field and are displayed when you move your mouse
@ -1553,17 +1589,56 @@ For example, the following snippet creates a link from cell `A3` to
<https://sheetjs.com> with the tip `"Find us @ SheetJS.com!"`:
```js
ws['A3'].l = { Target:"https://sheetjs.com", Tooltip:"Find us @ SheetJS.com!" };
ws['A1'].l = { Target:"https://sheetjs.com", Tooltip:"Find us @ SheetJS.com!" };
```
Note that Excel does not automatically style hyperlinks -- they will generally
be displayed as normal text.
_Remote Links_
HTTP / HTTPS links can be used directly:
```js
ws['A2'].l = { Target:"https://docs.sheetjs.com/#hyperlinks" };
ws['A3'].l = { Target:"http://localhost:7262/yes_localhost_works" };
```
Excel also supports `mailto` email links with subject line:
```js
ws['A4'].l = { Target:"mailto:ignored@dev.null" };
ws['A5'].l = { Target:"mailto:ignored@dev.null?subject=Test Subject" };
```
_Local Links_
Links to absolute paths should use the `file://` URI scheme:
```js
ws['B1'].l = { Target:"file:///SheetJS/t.xlsx" }; /* Link to /SheetJS/t.xlsx */
ws['B2'].l = { Target:"file:///c:/SheetJS.xlsx" }; /* Link to c:\SheetJS.xlsx */
```
Links to relative paths can be specified without a scheme:
```js
ws['B3'].l = { Target:"SheetJS.xlsb" }; /* Link to SheetJS.xlsb */
ws['B4'].l = { Target:"../SheetJS.xlsm" }; /* Link to ../SheetJS.xlsm */
```
Relative Paths have undefined behavior in the SpreadsheetML 2003 format. Excel
2019 will treat a `..\` parent mark as two levels up.
_Internal Links_
Links where the target is a cell or range or defined name in the same workbook
("Internal Links") are marked with a leading hash character:
```js
ws['A2'].l = { Target:"#E2" }; /* link to cell E2 */
ws['C1'].l = { Target:"#E2" }; /* Link to cell E2 */
ws['C2'].l = { Target:"#Sheet2!E2" }; /* Link to cell E2 in sheet Sheet2 */
ws['C3'].l = { Target:"#SomeDefinedName" }; /* Link to Defined Name */
```
#### Cell Comments
@ -1782,14 +1857,16 @@ Plain text format guessing follows the priority order:
|:-------|:--------------------------------------------------------------------|
| XML | `<?xml` appears in the first 1024 characters |
| HTML | starts with `<` and HTML tags appear in the first 1024 characters * |
| XML | starts with `<` |
| XML | starts with `<` and the first tag is valid |
| RTF | starts with `{\rt` |
| DSV | starts with `/sep=.$/`, separator is the specified character |
| DSV | more unquoted `";"` chars than `"\t"` or `","` in the first 1024 |
| TSV | more unquoted `"\t"` chars than `","` chars in the first 1024 |
| DSV | more unquoted `|` chars than `;` `\t` `,` in the first 1024 |
| DSV | more unquoted `;` chars than `\t` or `,` in the first 1024 |
| TSV | more unquoted `\t` chars than `,` chars in the first 1024 |
| CSV | one of the first 1024 characters is a comma `","` |
| ETH | starts with `socialcalc:version:` |
| PRN | (default) |
| PRN | `PRN` option is set to true |
| CSV | (fallback) |
- HTML tags include: `html`, `table`, `head`, `meta`, `script`, `style`, `div`
@ -1916,11 +1993,12 @@ as the corresponding styles. Dates are stored as date or numbers. Array holes
and explicit `undefined` values are skipped. `null` values may be stubbed. All
other values are stored as strings. The function takes 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 |
| 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 |
|`nullError` | false | If true, emit `#NULL!` error cells for `null` values |
<details>
<summary><b>Examples</b> (click to show)</summary>
@ -1940,12 +2018,13 @@ var ws = XLSX.utils.aoa_to_sheet([
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) |
| 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 |
|`nullError` | false | If true, emit `#NULL!` error cells for `null` values |
|`origin` | | Use specified cell as starting point (see below) |
`origin` is expected to be one of:
@ -2004,11 +2083,14 @@ default column order is determined by the first appearance of the field using
|`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 |
|`nullError` | false | If true, emit `#NULL!` error cells for `null` values |
- All fields from each row will be written. If `header` is an array and it does
not contain a particular field, the key will be appended to the array.
- Cell types are deduced from the type of each value. For example, a `Date`
object will generate a Date cell, while a string will generate a Text cell.
- Null values will be skipped by default. If `nullError` is true, an error cell
corresponding to `#NULL!` will be written to the worksheet.
<details>
<summary><b>Examples</b> (click to show)</summary>
@ -2039,13 +2121,14 @@ var ws = XLSX.utils.json_to_sheet([
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) |
| 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 |
|`nullError` | false | If true, emit `#NULL!` error cells for `null` values |
|`origin` | | Use specified cell as starting point (see below) |
`origin` is expected to be one of:

View File

@ -1 +1 @@
XLSX.version = '0.17.2';
XLSX.version = '0.17.3';

View File

@ -368,7 +368,7 @@ var SYLK = (function() {
switch(opts.type) {
case 'base64': return sylk_to_aoa_str(Base64.decode(d), opts);
case 'binary': return sylk_to_aoa_str(d, opts);
case 'buffer': return sylk_to_aoa_str(d.toString('binary'), opts);
case 'buffer': return sylk_to_aoa_str(has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d), opts);
case 'array': return sylk_to_aoa_str(cc2str(d), opts);
}
throw new Error("Unrecognized type " + opts.type);
@ -390,6 +390,7 @@ var SYLK = (function() {
case 'E': break; /* EOF */
case 'B': break; /* dimensions */
case 'O': break; /* options? */
case 'W': break; /* window? */
case 'P':
if(record[1].charAt(0) == 'P')
formats.push(rstr.slice(3).replace(/;;/g, ";"));
@ -517,8 +518,8 @@ var SYLK = (function() {
var rec = "F;W" + (i+1) + " " + (i+1) + " ";
if(col.hidden) rec += "0";
else {
if(typeof col.width == 'number') col.wpx = width2px(col.width);
if(typeof col.wpx == 'number') col.wch = px2char(col.wpx);
if(typeof col.width == 'number' && !col.wpx) col.wpx = width2px(col.width);
if(typeof col.wpx == 'number' && !col.wch) col.wch = px2char(col.wpx);
if(typeof col.wch == 'number') rec += Math.round(col.wch);
}
if(rec.charAt(rec.length - 1) != " ") out.push(rec);
@ -570,7 +571,7 @@ var DIF = (function() {
switch(opts.type) {
case 'base64': return dif_to_aoa_str(Base64.decode(d), opts);
case 'binary': return dif_to_aoa_str(d, opts);
case 'buffer': return dif_to_aoa_str(d.toString('binary'), opts);
case 'buffer': return dif_to_aoa_str(has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d), opts);
case 'array': return dif_to_aoa_str(cc2str(d), opts);
}
throw new Error("Unrecognized type " + opts.type);
@ -583,7 +584,9 @@ var DIF = (function() {
var metadata = records[ri].trim().split(",");
var type = metadata[0], value = metadata[1];
++ri;
var data = records[ri].trim();
var data = records[ri] || "";
while(((data.match(/["]/g)||[]).length & 1) && ri < records.length - 1) data += "\n" + records[++ri];
data = data.trim();
switch (+type) {
case -1:
if (data === 'BOT') { arr[++R] = []; C = 0; continue; }
@ -598,6 +601,8 @@ var DIF = (function() {
++C; break;
case 1:
data = data.slice(1,data.length-1);
data = data.replace(/""/g, '"');
if(DIF_XL && data && data.match(/^=".*"$/)) data = data.slice(2, -1);
arr[R][C++] = data !== '' ? data : null;
break;
}
@ -847,7 +852,7 @@ var PRN = (function() {
cc.sort(function(a, b) { return a[0] - b[0] || guess_sep_weights[a[1]] - guess_sep_weights[b[1]]; });
return guess_seps[cc.pop()[1]];
return guess_seps[cc.pop()[1]] || 0x2C;
}
function dsv_to_sheet_str(str/*:string*/, opts)/*:Worksheet*/ {
@ -931,9 +936,9 @@ var PRN = (function() {
case 'base64': str = Base64.decode(d); break;
case 'binary': str = d; break;
case 'buffer':
if(opts.codepage == 65001) str = d.toString('utf8');
if(opts.codepage == 65001) str = d.toString('utf8'); // TODO: test if buf
else if(opts.codepage && typeof cptable !== 'undefined') str = cptable.utils.decode(opts.codepage, d);
else str = d.toString('binary');
else str = has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d);
break;
case 'array': str = cc2str(d); break;
case 'string': str = d; break;

View File

@ -3,10 +3,10 @@ function parse_Theme(blob, length, opts) {
var end = blob.l + length;
var dwThemeVersion = blob.read_shift(4);
if(dwThemeVersion === 124226) return;
if(!opts.cellStyles || !jszip) { blob.l = end; return; }
if(!opts.cellStyles) { blob.l = end; return; }
var data = blob.slice(blob.l);
blob.l = end;
var zip; try { zip = new jszip(data); } catch(e) { return; }
var zip; try { zip = zip_read(data, {type: "array"}); } catch(e) { return; }
var themeXML = getzipstr(zip, "theme/theme/theme1.xml", true);
if(!themeXML) return;
return parse_theme_xml(themeXML, opts);

View File

@ -193,8 +193,18 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
SSF: SSF.get_table()
}/*:any*/);
if(opts && opts.bookFiles) {
out.keys = entries;
out.files = zip.files;
if(zip.files) {
out.keys = entries;
out.files = zip.files;
} else {
out.keys = [];
out.files = {};
zip.FullPaths.forEach(function(p, idx) {
p = p.replace(/^Root Entry[\/]/, "");
out.keys.push(p);
out.files[p] = zip.FileIndex[idx];
});
}
}
if(opts && opts.bookVBA) {
if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,strip_front_slash(dir.vba[0]),true);

View File

@ -11,7 +11,7 @@ function write_cfb_ctr(cfb/*:CFBContainer*/, o/*:WriteOpts*/)/*:any*/ {
/*:: declare var encrypt_agile:any; */
function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:any*/ {
var o = opts||{};
var o = dup(opts||{});
var z = write_zip(wb, o);
var oopts = {};
if(o.compression) oopts.compression = 'DEFLATE';
@ -87,7 +87,7 @@ function write_binary_type(out, opts/*:WriteOpts*/)/*:any*/ {
function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
reset_cp();
check_wb(wb);
var o = opts||{};
var o = dup(opts||{});
if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; }
if(o.type == "array") { o.type = "binary"; var out/*:string*/ = (writeSync(wb, o)/*:any*/); o.type = "array"; return s2ab(out); }
switch(o.bookType || 'xlsb') {

View File

@ -39,7 +39,7 @@ The following function converts data from SheetJS to x-spreadsheet:
grid.loadData(stox(workbook_object));
```
`stox` is defined in [xlsxspread.js](./xlsxspread.js)
`stox` is defined in [`xlsxspread.js`](./xlsxspread.js)
## Editing
@ -57,7 +57,7 @@ var new_wb = xtos(xspr.getData());
XLSX.writeFile(new_wb, "SheetJS.xlsx");
```
`stox` is defined in [xlsxspread.js](./xlsxspread.js)
`stox` is defined in [`xlsxspread.js`](./xlsxspread.js)
## Additional Features

2
dist/jszip.js generated vendored
View File

@ -14,7 +14,7 @@ Note: since JSZip 3 removed critical functionality, this version assigns to the
*/
(function(e){
if("object"==typeof exports&&"undefined"!=typeof module&&"undefined"==typeof DO_NOT_EXPORT_JSZIP)module.exports=e();
else if("function"==typeof define&&define.amd&&"undefined"==typeof DO_NOT_EXPORT_JSZIP){JSZipSync=e();define([],e);}
else if("function"==typeof define&&define.amd&&"undefined"==typeof DO_NOT_EXPORT_JSZIP){JSZipSync=e();define('j',[],e);}
else{
var f;
"undefined"!=typeof globalThis?f=globalThis:

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

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

441
dist/xlsx.extendscript.js generated vendored

File diff suppressed because it is too large Load Diff

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

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

439
dist/xlsx.js generated vendored

File diff suppressed because it is too large Load Diff

28
dist/xlsx.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.min.map generated vendored

File diff suppressed because one or more lines are too long

16
dist/xlsx.mini.min.js generated vendored

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

View File

@ -27,6 +27,7 @@ Community Translations of this README:
[**Issues and Bug Reports**](https://github.com/sheetjs/sheetjs/issues)
![License](https://img.shields.io/github/license/SheetJS/sheetjs)
[![Build Status](https://img.shields.io/github/workflow/status/sheetjs/sheetjs/Tests:%20node.js)](https://github.com/SheetJS/sheetjs/actions)
[![Snyk Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/SheetJS/sheetjs)](https://snyk.io/test/github/SheetJS/sheetjs)
[![npm Downloads](https://img.shields.io/npm/dm/xlsx.svg)](https://npmjs.org/package/xlsx)
[![jsDelivr Downloads](https://data.jsdelivr.com/v1/package/npm/xlsx/badge)](https://www.jsdelivr.com/package/npm/xlsx)

View File

@ -27,10 +27,10 @@ function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getda
/* OASIS does not comment on filename case sensitivity */
function safegetzipfile(zip, file/*:string*/) {
var k = zip.FullPaths || keys(zip.files);
var f = file.toLowerCase(), g = f.replace(/\\/g,'\/');
var f = file.toLowerCase().replace(/[\/]/g, '\\'), g = f.replace(/\\/g,'\/');
for(var i=0; i<k.length; ++i) {
var n = k[i].replace(/^Root Entry[\/]/,"").toLowerCase();
if(f == n || g == n) return zip.FileIndex[i];
if(f == n || g == n) return zip.files ? zip.files[k[i]] : zip.FileIndex[i];
}
return null;
}

View File

@ -27,6 +27,7 @@ Community Translations of this README:
[**Issues and Bug Reports**](https://github.com/sheetjs/sheetjs/issues)
![License](https://img.shields.io/github/license/SheetJS/sheetjs)
[![Build Status](https://img.shields.io/github/workflow/status/sheetjs/sheetjs/Tests:%20node.js)](https://github.com/SheetJS/sheetjs/actions)
[![Snyk Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/SheetJS/sheetjs)](https://snyk.io/test/github/SheetJS/sheetjs)
[![npm Downloads](https://img.shields.io/npm/dm/xlsx.svg)](https://npmjs.org/package/xlsx)
[![jsDelivr Downloads](https://data.jsdelivr.com/v1/package/npm/xlsx/badge)](https://www.jsdelivr.com/package/npm/xlsx)
@ -183,7 +184,7 @@ The [`demos` directory](demos/) includes sample projects for:
**Frameworks and APIs**
- [`angularjs`](demos/angular/)
- [`angular 2 / 4 / 5 / 6 and ionic`](demos/angular2/)
- [`angular and ionic`](demos/angular2/)
- [`knockout`](demos/knockout/)
- [`meteor`](demos/meteor/)
- [`react and react-native`](demos/react/)
@ -383,8 +384,7 @@ req.open("GET", url, true);
req.responseType = "arraybuffer";
req.onload = function(e) {
var data = new Uint8Array(req.response);
var workbook = XLSX.read(data, {type:"array"});
var workbook = XLSX.read(req.response);
/* DO SOMETHING WITH workbook HERE */
}
@ -394,16 +394,29 @@ req.send();
Drag-and-drop uses the HTML5 `FileReader` API.
For modern browsers, `Blob#arrayBuffer` can read data from files:
```js
async function handleDropAsync(e) {
e.stopPropagation(); e.preventDefault();
const f = evt.dataTransfer.files[0];
const data = await f.arrayBuffer();
const workbook = XLSX.read(data);
/* DO SOMETHING WITH workbook HERE */
}
drop_dom_element.addEventListener('drop', handleDropAsync, false);
```
For maximal compatibility, the `FileReader` API should be used:
```js
function handleDrop(e) {
e.stopPropagation(); e.preventDefault();
var files = e.dataTransfer.files, f = files[0];
var f = e.dataTransfer.files[0];
var reader = new FileReader();
reader.onload = function(e) {
var data = new Uint8Array(e.target.result);
var workbook = XLSX.read(data, {type: 'array'});
var workbook = XLSX.read(e.target.result);
/* DO SOMETHING WITH workbook HERE */
};
@ -414,16 +427,30 @@ drop_dom_element.addEventListener('drop', handleDrop, false);
Data from file input elements can be processed using the same `FileReader` API
as in the drag-and-drop example:
Data from file input elements can be processed using the same APIs as in the
drag-and-drop example.
Using `Blob#arrayBuffer`:
```js
async function handleFileAsync(e) {
const file = evt.target.files[0];
const data = await file.arrayBuffer();
const workbook = XLSX.read(data);
/* DO SOMETHING WITH workbook HERE */
}
input_dom_element.addEventListener('change', handleFileAsync, false);
```
Using `FileReader`:
```js
function handleFile(e) {
var files = e.target.files, f = files[0];
var reader = new FileReader();
reader.onload = function(e) {
var data = new Uint8Array(e.target.result);
var workbook = XLSX.read(data, {type: 'array'});
var workbook = XLSX.read(e.target.result);
/* DO SOMETHING WITH workbook HERE */
};
@ -1413,6 +1440,12 @@ specific format string.
#### Hyperlinks
**Cell Hyperlinks**: XLSX/M, XLSB, BIFF8 XLS, XLML, ODS
**Tooltips**: XLSX/M, XLSB, BIFF8 XLS, XLML
Hyperlinks are stored in the `l` key of cell objects. The `Target` field of the
hyperlink object is the target of the link, including the URI fragment. Tooltips
are stored in the `Tooltip` field and are displayed when you move your mouse
@ -1422,17 +1455,56 @@ For example, the following snippet creates a link from cell `A3` to
<https://sheetjs.com> with the tip `"Find us @ SheetJS.com!"`:
```js
ws['A3'].l = { Target:"https://sheetjs.com", Tooltip:"Find us @ SheetJS.com!" };
ws['A1'].l = { Target:"https://sheetjs.com", Tooltip:"Find us @ SheetJS.com!" };
```
Note that Excel does not automatically style hyperlinks -- they will generally
be displayed as normal text.
_Remote Links_
HTTP / HTTPS links can be used directly:
```js
ws['A2'].l = { Target:"https://docs.sheetjs.com/#hyperlinks" };
ws['A3'].l = { Target:"http://localhost:7262/yes_localhost_works" };
```
Excel also supports `mailto` email links with subject line:
```js
ws['A4'].l = { Target:"mailto:ignored@dev.null" };
ws['A5'].l = { Target:"mailto:ignored@dev.null?subject=Test Subject" };
```
_Local Links_
Links to absolute paths should use the `file://` URI scheme:
```js
ws['B1'].l = { Target:"file:///SheetJS/t.xlsx" }; /* Link to /SheetJS/t.xlsx */
ws['B2'].l = { Target:"file:///c:/SheetJS.xlsx" }; /* Link to c:\SheetJS.xlsx */
```
Links to relative paths can be specified without a scheme:
```js
ws['B3'].l = { Target:"SheetJS.xlsb" }; /* Link to SheetJS.xlsb */
ws['B4'].l = { Target:"../SheetJS.xlsm" }; /* Link to ../SheetJS.xlsm */
```
Relative Paths have undefined behavior in the SpreadsheetML 2003 format. Excel
2019 will treat a `..\` parent mark as two levels up.
_Internal Links_
Links where the target is a cell or range or defined name in the same workbook
("Internal Links") are marked with a leading hash character:
```js
ws['A2'].l = { Target:"#E2" }; /* link to cell E2 */
ws['C1'].l = { Target:"#E2" }; /* Link to cell E2 */
ws['C2'].l = { Target:"#Sheet2!E2" }; /* Link to cell E2 in sheet Sheet2 */
ws['C3'].l = { Target:"#SomeDefinedName" }; /* Link to Defined Name */
```
#### Cell Comments
@ -1637,14 +1709,16 @@ Plain text format guessing follows the priority order:
|:-------|:--------------------------------------------------------------------|
| XML | `<?xml` appears in the first 1024 characters |
| HTML | starts with `<` and HTML tags appear in the first 1024 characters * |
| XML | starts with `<` |
| XML | starts with `<` and the first tag is valid |
| RTF | starts with `{\rt` |
| DSV | starts with `/sep=.$/`, separator is the specified character |
| DSV | more unquoted `";"` chars than `"\t"` or `","` in the first 1024 |
| TSV | more unquoted `"\t"` chars than `","` chars in the first 1024 |
| DSV | more unquoted `|` chars than `;` `\t` `,` in the first 1024 |
| DSV | more unquoted `;` chars than `\t` or `,` in the first 1024 |
| TSV | more unquoted `\t` chars than `,` chars in the first 1024 |
| CSV | one of the first 1024 characters is a comma `","` |
| ETH | starts with `socialcalc:version:` |
| PRN | (default) |
| PRN | `PRN` option is set to true |
| CSV | (fallback) |
- HTML tags include: `html`, `table`, `head`, `meta`, `script`, `style`, `div`
@ -1767,11 +1841,12 @@ as the corresponding styles. Dates are stored as date or numbers. Array holes
and explicit `undefined` values are skipped. `null` values may be stubbed. All
other values are stored as strings. The function takes 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 |
| 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 |
|`nullError` | false | If true, emit `#NULL!` error cells for `null` values |
To generate the example sheet:
@ -1788,12 +1863,13 @@ var ws = XLSX.utils.aoa_to_sheet([
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) |
| 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 |
|`nullError` | false | If true, emit `#NULL!` error cells for `null` values |
|`origin` | | Use specified cell as starting point (see below) |
`origin` is expected to be one of:
@ -1849,11 +1925,14 @@ default column order is determined by the first appearance of the field using
|`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 |
|`nullError` | false | If true, emit `#NULL!` error cells for `null` values |
- All fields from each row will be written. If `header` is an array and it does
not contain a particular field, the key will be appended to the array.
- Cell types are deduced from the type of each value. For example, a `Date`
object will generate a Date cell, while a string will generate a Text cell.
- Null values will be skipped by default. If `nullError` is true, an error cell
corresponding to `#NULL!` will be written to the worksheet.
The original sheet cannot be reproduced using plain objects since JS object keys
@ -1881,13 +1960,14 @@ var ws = XLSX.utils.json_to_sheet([
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) |
| 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 |
|`nullError` | false | If true, emit `#NULL!` error cells for `null` values |
|`origin` | | Use specified cell as starting point (see below) |
`origin` is expected to be one of:

View File

@ -1,6 +1,6 @@
{
"name": "xlsx",
"version": "0.17.2",
"version": "0.17.3",
"author": "sheetjs",
"description": "SheetJS Spreadsheet data parser and writer",
"keywords": [
@ -38,7 +38,7 @@
"commander": "~2.17.1",
"crc-32": "~1.2.0",
"exit-on-epipe": "~1.0.1",
"fflate": "^0.3.8",
"fflate": "^0.7.1",
"ssf": "~0.11.2",
"wmf": "~1.0.1",
"word": "~0.3.0"

42
test.js
View File

@ -2273,10 +2273,15 @@ describe('js -> file -> js', function() {
['B2', 'B3'].forEach(cb); /* bool */
['C2', 'C3'].forEach(cb); /* string */
if(!DIF_XL) cb('D4'); /* date */
if(DIF_XL && f == "dif") assert.equal(get_cell(newwb.Sheets.Sheet1, 'C5').v, '=""0.3""');// dif forces string formula
else if(f != 'csv' && f != 'txt') eqcell(wb, newwb, 'Sheet1', 'C5');
if(f != 'csv' && f != 'txt') eqcell(wb, newwb, 'Sheet1', 'C5');
});
});
it('should roundtrip DIF strings', function() {
var wb1 = X.read(X.write(wb, {type:BIN, bookType: 'dif'}), {type:BIN});
var wb2 = X.read(X.write(wb1, {type:BIN, bookType: 'dif'}), {type:BIN});
eqcell(wb, wb1, 'Sheet1', 'C5');
eqcell(wb, wb2, 'Sheet1', 'C5');
});
});
describe('corner cases', function() {
@ -2367,17 +2372,28 @@ describe('corner cases', function() {
assert.equal(wb.Sheets.Sheet1.A10.f, "'a!b'!A1");
assert.equal(wb.Sheets.Sheet1.A11.f, "'a b'!A1");
});
it('should parse CSV date values with preceding space', function() {
var wb = X.read(
'7, 2018-03-24',
{cellDates: false, dateNF: 'yyyy-mm-dd', type:'string'}
);
var ws = wb.Sheets.Sheet1;
var d = X.SSF.parse_date_code(ws.B1.v);
assert.equal(d.d, 24);
assert.equal(d.m, 3);
assert.equal(d.y, 2018);
assert.equal(ws.B1.w, '2018-03-24');
it.skip('should parse CSV date values with preceding space', function() {
function check_ws(ws, dNF) {
//var d = X.SSF.parse_date_code(ws.B1.v);
assert.equal(ws.B1.w, dNF ? '2018-03-24' : "3/23/18");
//assert.equal(d.d, 24);
//assert.equal(d.m, 3);
//assert.equal(d.y, 2018);
}
[true, false].forEach(function(cD) {
[null, 'yyyy-mm-dd'].forEach(function(dNF) {
var ws1 = X.read(
'7,2018-03-24',
{cellDates: cD, dateNF: dNF, type:'string'}
).Sheets.Sheet1;
check_ws(ws1, dNF);
var ws2 = X.read(
'7, 2018-03-24',
{cellDates: cD, dateNF: dNF, type:'string'}
).Sheets.Sheet1;
check_ws(ws2, dNF);
});
});
});
});

42
tests/core.js generated
View File

@ -2273,10 +2273,15 @@ describe('js -> file -> js', function() {
['B2', 'B3'].forEach(cb); /* bool */
['C2', 'C3'].forEach(cb); /* string */
if(!DIF_XL) cb('D4'); /* date */
if(DIF_XL && f == "dif") assert.equal(get_cell(newwb.Sheets.Sheet1, 'C5').v, '=""0.3""');// dif forces string formula
else if(f != 'csv' && f != 'txt') eqcell(wb, newwb, 'Sheet1', 'C5');
if(f != 'csv' && f != 'txt') eqcell(wb, newwb, 'Sheet1', 'C5');
});
});
it('should roundtrip DIF strings', function() {
var wb1 = X.read(X.write(wb, {type:BIN, bookType: 'dif'}), {type:BIN});
var wb2 = X.read(X.write(wb1, {type:BIN, bookType: 'dif'}), {type:BIN});
eqcell(wb, wb1, 'Sheet1', 'C5');
eqcell(wb, wb2, 'Sheet1', 'C5');
});
});
describe('corner cases', function() {
@ -2367,17 +2372,28 @@ describe('corner cases', function() {
assert.equal(wb.Sheets.Sheet1.A10.f, "'a!b'!A1");
assert.equal(wb.Sheets.Sheet1.A11.f, "'a b'!A1");
});
it('should parse CSV date values with preceding space', function() {
var wb = X.read(
'7, 2018-03-24',
{cellDates: false, dateNF: 'yyyy-mm-dd', type:'string'}
);
var ws = wb.Sheets.Sheet1;
var d = X.SSF.parse_date_code(ws.B1.v);
assert.equal(d.d, 24);
assert.equal(d.m, 3);
assert.equal(d.y, 2018);
assert.equal(ws.B1.w, '2018-03-24');
it.skip('should parse CSV date values with preceding space', function() {
function check_ws(ws, dNF) {
//var d = X.SSF.parse_date_code(ws.B1.v);
assert.equal(ws.B1.w, dNF ? '2018-03-24' : "3/23/18");
//assert.equal(d.d, 24);
//assert.equal(d.m, 3);
//assert.equal(d.y, 2018);
}
[true, false].forEach(function(cD) {
[null, 'yyyy-mm-dd'].forEach(function(dNF) {
var ws1 = X.read(
'7,2018-03-24',
{cellDates: cD, dateNF: dNF, type:'string'}
).Sheets.Sheet1;
check_ws(ws1, dNF);
var ws2 = X.read(
'7, 2018-03-24',
{cellDates: cD, dateNF: dNF, type:'string'}
).Sheets.Sheet1;
check_ws(ws2, dNF);
});
});
});
});

430
xlsx.esm.mjs generated

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

439
xlsx.js generated

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
function make_xlsx_lib(XLSX){
XLSX.version = '0.17.2';
XLSX.version = '0.17.3';
var current_codepage = 1200, current_ansi = 1252;
var VALID_ANSI = [ 874, 932, 936, 949, 950 ];
@ -2974,10 +2974,10 @@ function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getda
/* OASIS does not comment on filename case sensitivity */
function safegetzipfile(zip, file/*:string*/) {
var k = zip.FullPaths || keys(zip.files);
var f = file.toLowerCase(), g = f.replace(/\\/g,'\/');
var f = file.toLowerCase().replace(/[\/]/g, '\\'), g = f.replace(/\\/g,'\/');
for(var i=0; i<k.length; ++i) {
var n = k[i].replace(/^Root Entry[\/]/,"").toLowerCase();
if(f == n || g == n) return zip.FileIndex[i];
if(f == n || g == n) return zip.files ? zip.files[k[i]] : zip.FileIndex[i];
}
return null;
}
@ -3756,6 +3756,7 @@ function format_cell(cell/*:Cell*/, v/*:any*/, o/*:any*/) {
if(cell == null || cell.t == null || cell.t == 'z') return "";
if(cell.w !== undefined) return cell.w;
if(cell.t == 'd' && !cell.z && o && o.dateNF) cell.z = o.dateNF;
if(cell.t == "e") return BErr[cell.v] || cell.v;
if(v == undefined) return safe_format_cell(cell, cell.v);
return safe_format_cell(cell, v);
}
@ -3803,7 +3804,12 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
if(data[R][C] && typeof data[R][C] === 'object' && !Array.isArray(data[R][C]) && !(data[R][C] instanceof Date)) cell = data[R][C];
else {
if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.sheetStubs) continue; else cell.t = 'z'; }
if(cell.v === null) {
if(cell.f) cell.t = 'n';
else if(o.nullError) { cell.t = 'e'; cell.v = 0; }
else if(!o.sheetStubs) continue;
else cell.t = 'z';
}
else if(typeof cell.v === 'number') cell.t = 'n';
else if(typeof cell.v === 'boolean') cell.t = 'b';
else if(cell.v instanceof Date) {
@ -5128,7 +5134,7 @@ var SYLK = (function() {
Au:'ù', Bu:'ú', Cu:'û', Hu:'ü',
KC:'Ç', Kc:'ç', q:'æ', z:'œ', a:'Æ', j:'Œ',
DN:209, Dn:241, Hy:255,
S:169, c:170, R:174, B:180,
S:169, c:170, R:174, "B ":180,
/*::[*/0/*::]*/:176, /*::[*/1/*::]*/:177, /*::[*/2/*::]*/:178,
/*::[*/3/*::]*/:179, /*::[*/5/*::]*/:181, /*::[*/6/*::]*/:182,
/*::[*/7/*::]*/:183, Q:185, k:186, b:208, i:216, l:222, s:240, y:248,
@ -5144,7 +5150,7 @@ var SYLK = (function() {
switch(opts.type) {
case 'base64': return sylk_to_aoa_str(Base64.decode(d), opts);
case 'binary': return sylk_to_aoa_str(d, opts);
case 'buffer': return sylk_to_aoa_str(d.toString('binary'), opts);
case 'buffer': return sylk_to_aoa_str(has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d), opts);
case 'array': return sylk_to_aoa_str(cc2str(d), opts);
}
throw new Error("Unrecognized type " + opts.type);
@ -5166,6 +5172,7 @@ var SYLK = (function() {
case 'E': break; /* EOF */
case 'B': break; /* dimensions */
case 'O': break; /* options? */
case 'W': break; /* window? */
case 'P':
if(record[1].charAt(0) == 'P')
formats.push(rstr.slice(3).replace(/;;/g, ";"));
@ -5293,8 +5300,8 @@ var SYLK = (function() {
var rec = "F;W" + (i+1) + " " + (i+1) + " ";
if(col.hidden) rec += "0";
else {
if(typeof col.width == 'number') col.wpx = width2px(col.width);
if(typeof col.wpx == 'number') col.wch = px2char(col.wpx);
if(typeof col.width == 'number' && !col.wpx) col.wpx = width2px(col.width);
if(typeof col.wpx == 'number' && !col.wch) col.wch = px2char(col.wpx);
if(typeof col.wch == 'number') rec += Math.round(col.wch);
}
if(rec.charAt(rec.length - 1) != " ") out.push(rec);
@ -5346,7 +5353,7 @@ var DIF = (function() {
switch(opts.type) {
case 'base64': return dif_to_aoa_str(Base64.decode(d), opts);
case 'binary': return dif_to_aoa_str(d, opts);
case 'buffer': return dif_to_aoa_str(d.toString('binary'), opts);
case 'buffer': return dif_to_aoa_str(has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d), opts);
case 'array': return dif_to_aoa_str(cc2str(d), opts);
}
throw new Error("Unrecognized type " + opts.type);
@ -5359,7 +5366,9 @@ var DIF = (function() {
var metadata = records[ri].trim().split(",");
var type = metadata[0], value = metadata[1];
++ri;
var data = records[ri].trim();
var data = records[ri] || "";
while(((data.match(/["]/g)||[]).length & 1) && ri < records.length - 1) data += "\n" + records[++ri];
data = data.trim();
switch (+type) {
case -1:
if (data === 'BOT') { arr[++R] = []; C = 0; continue; }
@ -5374,6 +5383,8 @@ var DIF = (function() {
++C; break;
case 1:
data = data.slice(1,data.length-1);
data = data.replace(/""/g, '"');
if(DIF_XL && data && data.match(/^=".*"$/)) data = data.slice(2, -1);
arr[R][C++] = data !== '' ? data : null;
break;
}
@ -5590,14 +5601,16 @@ var PRN = (function() {
var guess_seps = {
/*::[*/0x2C/*::]*/: ',',
/*::[*/0x09/*::]*/: "\t",
/*::[*/0x3B/*::]*/: ';'
/*::[*/0x3B/*::]*/: ';',
/*::[*/0x7C/*::]*/: '|'
};
// CSV separator weights to be used in case of equal numbers
var guess_sep_weights = {
/*::[*/0x2C/*::]*/: 3,
/*::[*/0x09/*::]*/: 2,
/*::[*/0x3B/*::]*/: 1
/*::[*/0x3B/*::]*/: 1,
/*::[*/0x7C/*::]*/: 0
};
function guess_sep(str) {
@ -5621,7 +5634,7 @@ var PRN = (function() {
cc.sort(function(a, b) { return a[0] - b[0] || guess_sep_weights[a[1]] - guess_sep_weights[b[1]]; });
return guess_seps[cc.pop()[1]];
return guess_seps[cc.pop()[1]] || 0x2C;
}
function dsv_to_sheet_str(str/*:string*/, opts)/*:Worksheet*/ {
@ -5705,15 +5718,16 @@ var PRN = (function() {
case 'base64': str = Base64.decode(d); break;
case 'binary': str = d; break;
case 'buffer':
if(opts.codepage == 65001) str = d.toString('utf8');
if(opts.codepage == 65001) str = d.toString('utf8'); // TODO: test if buf
else if(opts.codepage && typeof cptable !== 'undefined') str = cptable.utils.decode(opts.codepage, d);
else str = d.toString('binary');
else str = has_buf && Buffer.isBuffer(d) ? d.toString('binary') : a2s(d);
break;
case 'array': str = cc2str(d); break;
case 'string': str = d; break;
default: throw new Error("Unrecognized type " + opts.type);
}
if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str.slice(3));
else if(opts.type != 'string' && opts.codepage == 65001) str = utf8read(str);
else if((opts.type == 'binary') && typeof cptable !== 'undefined' && opts.codepage) str = cptable.utils.decode(opts.codepage, cptable.utils.encode(28591,str));
if(str.slice(0,19) == "socialcalc:version:") return ETH.to_sheet(opts.type == 'string' ? str : utf8read(str), opts);
return prn_to_sheet_str(str, opts);
@ -6349,7 +6363,7 @@ function parse_fonts(t, styles, themes, opts) {
font.color.index = parseInt(y.indexed, 10);
var icv = XLSIcv[font.color.index];
if(font.color.index == 81) icv = XLSIcv[1];
if(!icv) throw new Error(x);
if(!icv) icv = XLSIcv[1]; //throw new Error(x); // note: 206 is valid
font.color.rgb = icv[0].toString(16) + icv[1].toString(16) + icv[2].toString(16);
} else if(y.theme) {
font.color.theme = parseInt(y.theme, 10);
@ -7182,6 +7196,7 @@ function col_obj_w(C/*:number*/, col) {
if(wch > -1) { p.width = char2width(wch); p.customWidth = 1; }
else if(col.width != null) p.width = col.width;
if(col.hidden) p.hidden = true;
if(col.level != null) { p.outlineLevel = p.level = col.level; }
return p;
}
@ -7278,6 +7293,7 @@ var colregex = /<(?:\w:)?col\b[^>]*[\/]?>/g;
var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g;
var sheetprregex = /<(?:\w:)?sheetPr\b(?:[^>a-z][^>]*)?\/>/;
var sheetprregex2= /<(?:\w:)?sheetPr[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetPr)>/;
var svsregex = /<(?:\w:)?sheetViews[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetViews)>/;
/* 18.3 Worksheets */
@ -7300,6 +7316,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
/* 18.3.1.82 sheetPr CT_SheetPr */
var sheetPr = data1.match(sheetprregex);
if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
else if((sheetPr = data1.match(sheetprregex2))) parse_ws_xml_sheetpr2(sheetPr[0], sheetPr[1]||"", s, wb, idx, styles, themes);
/* 18.3.1.35 dimension CT_SheetDimension */
var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
@ -7372,6 +7389,9 @@ function parse_ws_xml_sheetpr(sheetPr/*:string*/, s, wb/*:WBWBProps*/, idx/*:num
if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
if(data.codeName) wb.Sheets[idx].CodeName = unescapexml(utf8read(data.codeName));
}
function parse_ws_xml_sheetpr2(sheetPr/*:string*/, body/*:string*/, s, wb/*:WBWBProps*/, idx/*:number*/, styles, themes) {
parse_ws_xml_sheetpr(sheetPr.slice(0, sheetPr.indexOf(">")), s, wb, idx);
}
function write_ws_xml_sheetpr(ws, wb, idx, opts, o) {
var needed = false;
var props = {}, payload = null;
@ -7419,9 +7439,9 @@ function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
var rel = ((rels || {})['!id']||[])[val.id];
if(rel) {
val.Target = rel.Target;
if(val.location) val.Target += "#"+val.location;
if(val.location) val.Target += "#"+unescapexml(val.location);
} else {
val.Target = "#" + val.location;
val.Target = "#" + unescapexml(val.location);
rel = {Target: val.Target, TargetMode: 'Internal'};
}
val.Rel = rel;
@ -7459,6 +7479,7 @@ function parse_ws_xml_cols(columns, cols) {
var coll = parsexmltag(cols[coli], true);
if(coll.hidden) coll.hidden = parsexmlbool(coll.hidden);
var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
if(coll.outlineLevel) coll.level = (+coll.outlineLevel || 0);
delete coll.min; delete coll.max; coll.width = +coll.width;
if(!seencol && coll.width) { seencol = true; find_mdw_colw(coll.width); }
process_col(coll);
@ -7548,6 +7569,7 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string
case 'e': o.t = "e"; break;
case 'z': break;
default: if(cell.v == null) { delete cell.t; break; }
if(cell.v.length > 32767) throw new Error("Text length must not exceed 32767 characters");
if(opts && opts.bookSST) {
v = writetag('v', ''+get_sst_id(opts.Strings, cell.v, opts.revStrings));
o.t = "s"; break;
@ -7587,8 +7609,26 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
if(xlen === 0) continue;
/* 18.3.1.73 row CT_Row */
for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
tag = parsexmltag(x.slice(0,ri), true);
var rstarti = 0;
outa: for(ri = 0; ri < xlen; ++ri) switch(/*x.charCodeAt(ri)*/x[ri]) {
case ">" /*62*/:
if(/*x.charCodeAt(ri-1) != 47*/x[ri-1] != "/") { ++ri; break outa; }
if(opts && opts.cellStyles) {
// TODO: avoid duplication
tag = parsexmltag(x.slice(rstarti,ri), true);
tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
if(opts.sheetRows && opts.sheetRows < tagr) continue;
rowobj = {}; rowrite = false;
if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj;
}
break;
case "<" /*60*/: rstarti = ri; break;
}
if(rstarti >= ri) break;
tag = parsexmltag(x.slice(rstarti,ri), true);
tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
if(opts.sheetRows && opts.sheetRows < tagr) continue;
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
@ -8557,7 +8597,7 @@ var HTML_ = (function() {
var tag = parsexmltag(cell.slice(0, cell.indexOf(">")));
CS = tag.colspan ? +tag.colspan : 1;
if((RS = +tag.rowspan)>1 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
var _t/*:string*/ = tag.t || "";
var _t/*:string*/ = tag.t || tag["data-t"] || "";
/* TODO: generate stub cells */
if(!m.length) { C += CS; continue; }
m = htmldecode(m);
@ -8605,10 +8645,14 @@ var HTML_ = (function() {
var sp = ({}/*:any*/);
if(RS > 1) sp.rowspan = RS;
if(CS > 1) sp.colspan = CS;
sp.t = cell && cell.t || 'z';
if(o.editable) w = '<span contenteditable="true">' + w + '</span>';
else if(cell) {
sp["data-t"] = cell && cell.t || 'z';
if(cell.v != null) sp["data-v"] = cell.v;
if(cell.z != null) sp["data-z"] = cell.z;
if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + cell.l.Target +'">' + w + '</a>';
}
sp.id = (o.id || "sjs") + "-" + coord;
if(sp.t != "z") { sp.v = cell.v; if(cell.z != null) sp.z = cell.z; }
oo.push(writextag('td',