version bump 0.9.2: more bugfixes

- decode sheet name for XLSX and XLML (fixes #203 h/t @rocketmonkeys)
- XFExt (fixes #298 h/t @aetna-softwares @aimcom @baharudinafif)
- handle truly empty `<is>` elements (fixes #506 h/t @asksahil)
- pin version numbers for dependencies (fixes #469 h/t @nhtera)
- sed usage fix (see #572 h/t @liryna)
- fix hex2RGB substr indices (fixes #294 h/t @kamorahul)
- removed stale typescript files (see #442)
- reworked shift formula regex (fixed #551 h/t @SheetJSDev)
- README note on webpack codepage suppression (fixes #438 h/t @rusty1s)
- README note on WTF (fixes #487 h/t @livesoftware)
This commit is contained in:
SheetJS 2017-03-13 02:46:37 -04:00
parent 8cd9e81569
commit 456ab63dc4
29 changed files with 421 additions and 530 deletions

1
.gitignore vendored

@ -1,4 +1,5 @@
node_modules
*.tgz
misc/coverage.html
misc/prof.js
v8.log

@ -4,6 +4,7 @@ demos/
index.html
misc/
node_modules
*.tgz
tmp
*.txt
*.[cC][sS][vV]
@ -20,6 +21,7 @@ tmp
*.htm
*.html
*.sheetjs
*.exe
.gitignore
.jshintrc
CONTRIBUTING.md

@ -5,6 +5,18 @@ but not limited to API changes and file location changes. Minor behavioral
changes may not be included if they are not expected to break existing code.
## 0.9.2 (2017-03-13)
* Removed stale TypeScript definition files. Flowtype comments are used in the
`xlsx.flow.js` source and stripped to produce `xlsx.js`.
* sed usage reworked to support GNU sed in-place form. BSD sed seems to work,
but the build script has not been tested on other sed variants:
```bash
$ sed -i.ext [...] # GNU
$ sed -i .ext [...] # bsd
```
## 0.9.0 (2017-03-09)
* Removed ods.js source. The xlsx.js source absorbed the ODS logic and exposes

180
README.md

@ -5,36 +5,68 @@ implementation from official specifications, related documents, and test files.
Emphasis on parsing and writing robustness, cross-format feature compatibility
with a unified JS representation, and ES3/ES5 browser compatibility back to IE6.
File format support for known spreadsheet data formats:
[**In-Browser Demo**](http://oss.sheetjs.com/js-xlsx)
| Format | Read | Write |
|:-------------------------------------------------------------|:-----:|:-----:|
| **Excel Worksheet/Workbook Formats** |:-----:|:-----:|
| Excel 2007+ XML Formats (XLSX/XLSM) | :o: | :o: |
| Excel 2007+ Binary Format (XLSB BIFF12) | :o: | :o: |
| Excel 2003-2004 XML Format (XML "SpreadsheetML") | :o: | |
| Excel 97-2004 (XLS BIFF8) | :o: | |
| Excel 5.0/95 (XLS BIFF5) | :o: | |
| Excel 4.0 (XLS/XLW BIFF4) | :o: | |
| Excel 3.0 (XLS BIFF3) | :o: | |
| Excel 2.0/2.1 (XLS BIFF2) | :o: | :o: |
| **Excel Supported Text Formats** |:-----:|:-----:|
| Delimiter-Separated Values (CSV/TSV/DSV) | | :o: |
| **Other Workbook/Worksheet Formats** |:-----:|:-----:|
| OpenDocument Spreadsheet (ODS) | :o: | :o: |
| Flat XML ODF Spreadsheet (FODS) | :o: | :o: |
| Uniform Office Format Spreadsheet (标文通 UOS1/UOS2) | :o: | |
| **Other Common Spreadsheet Output Formats** |:-----:|:-----:|
| HTML Tables | :o: | |
[**Source Code**](http://git.io/xlsx)
[**Commercial Support**](http://sheetjs.com/reinforcements)
[**File format support for known spreadsheet data formats:**](#file-formats)
![circo graph of format support](formats.png)
Demo: <http://oss.sheetjs.com/js-xlsx>
Source: <http://git.io/xlsx>
Paid support available through the [reinforcements program](http://sheetjs.com/reinforcements)
## Table of Contents
<!-- toc -->
- [Installation](#installation)
* [JS Ecosystem Demos](#js-ecosystem-demos)
* [Optional Modules](#optional-modules)
* [ECMAScript 5 Compatibility](#ecmascript-5-compatibility)
- [Parsing Workbooks](#parsing-workbooks)
- [Working with the Workbook](#working-with-the-workbook)
- [Writing Workbooks](#writing-workbooks)
- [Interface](#interface)
* [Parsing functions](#parsing-functions)
* [Writing functions](#writing-functions)
* [Utilities](#utilities)
- [Workbook / Worksheet / Cell Object Description](#workbook--worksheet--cell-object-description)
* [General Structures](#general-structures)
* [Cell Object](#cell-object)
* [Data Types](#data-types)
* [Formulae](#formulae)
* [Worksheet Object](#worksheet-object)
* [Workbook Object](#workbook-object)
- [Parsing Options](#parsing-options)
* [Input Type](#input-type)
* [Guessing File Type](#guessing-file-type)
- [Writing Options](#writing-options)
* [Supported Output Formats](#supported-output-formats)
* [Output Type](#output-type)
- [Utility Functions](#utility-functions)
* [Formulae Output](#formulae-output)
* [CSV and general DSV Output](#csv-and-general-dsv-output)
* [JSON](#json)
- [File Formats](#file-formats)
* [Excel 2007+ XML (XLSX/XLSM)](#excel-2007-xml-xlsxxlsm)
* [Excel 2.0-95 (BIFF2/BIFF3/BIFF4/BIFF5)](#excel-20-95-biff2biff3biff4biff5)
* [Excel 97-2004 Binary (BIFF8)](#excel-97-2004-binary-biff8)
* [Excel 2003-2004 (SpreadsheetML)](#excel-2003-2004-spreadsheetml)
* [Excel 2007+ Binary (XLSB, BIFF12)](#excel-2007-binary-xlsb-biff12)
* [OpenDocument Spreadsheet (ODS/FODS) and Uniform Office Spreadsheet (UOS1/2)](#opendocument-spreadsheet-odsfods-and-uniform-office-spreadsheet-uos12)
* [Comma-Separated Values](#comma-separated-values)
* [HTML](#html)
- [Testing](#testing)
* [Tested Environments](#tested-environments)
* [Test Files](#test-files)
- [Contributing](#contributing)
- [License](#license)
- [References](#references)
- [Badges](#badges)
<!-- tocstop -->
## Installation
@ -83,6 +115,17 @@ An appropriate version for each dependency is included in the dist/ directory.
The complete single-file version is generated at `dist/xlsx.full.min.js`
Webpack and browserify builds include optional modules by default. Webpack can
be configured to remove support with `resolve.alias`:
```js
/* uncomment the lines below to remove support */
resolve: {
alias: { "./dist/cpexcel.js": "" } // <-- omit international support
}
```
### ECMAScript 5 Compatibility
Since xlsx.js uses ES5 functions like `Array#forEach`, older browsers require
@ -143,10 +186,10 @@ oReq.send();
```js
/* processing array buffers, only required for readAsArrayBuffer */
function fixdata(data) {
var o = "", l = 0, w = 10240;
for(; l<data.byteLength/w; ++l) o+=String.fromCharCode.apply(null,new Uint8Array(data.slice(l*w,l*w+w)));
o+=String.fromCharCode.apply(null, new Uint8Array(data.slice(l*w)));
return o;
var o = "", l = 0, w = 10240;
for(; l<data.byteLength/w; ++l) o+=String.fromCharCode.apply(null,new Uint8Array(data.slice(l*w,l*w+w)));
o+=String.fromCharCode.apply(null, new Uint8Array(data.slice(l*w)));
return o;
}
var rABS = true; // true: readAsBinaryString ; false: readAsArrayBuffer
@ -528,6 +571,7 @@ The exported `read` and `readFile` functions accept an options argument:
| bookSheets | false | If true, only parse enough to get the sheet names |
| bookVBA | false | If true, expose vbaProject.bin to `vbaraw` field ** |
| password | "" | If defined and file is encrypted, use password ** |
| WTF | false | If true, throw errors on unexpected file features ** |
- `cellFormula` option only applies to formats that require extra processing to
parse formulae (XLS/XLSB).
@ -545,6 +589,9 @@ The exported `read` and `readFile` functions accept an options argument:
- `cellDates` currently does not convert numerical dates to JS dates.
- Currently only XOR encryption is supported. Unsupported error will be thrown
for files employing other encryption methods.
- WTF is mainly for development. By default, the parser will suppress read
errors on single worksheets, allowing you to read from the worksheets that do
parse properly. Setting `WTF:1` forces those errors to be thrown.
The defaults are enumerated in bits/84\_defaults.js
@ -754,8 +801,37 @@ Example showing the effect of `raw`:
## File Formats
Despite the fact that the name of the library is `xlsx`, it supports numerous
non-XLSX file formats:
Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
| Format | Read | Write |
|:-------------------------------------------------------------|:-----:|:-----:|
| **Excel Worksheet/Workbook Formats** |:-----:|:-----:|
| Excel 2007+ XML Formats (XLSX/XLSM) | :o: | :o: |
| Excel 2007+ Binary Format (XLSB BIFF12) | :o: | :o: |
| Excel 2003-2004 XML Format (XML "SpreadsheetML") | :o: | |
| Excel 97-2004 (XLS BIFF8) | :o: | |
| Excel 5.0/95 (XLS BIFF5) | :o: | |
| Excel 4.0 (XLS/XLW BIFF4) | :o: | |
| Excel 3.0 (XLS BIFF3) | :o: | |
| Excel 2.0/2.1 (XLS BIFF2) | :o: | :o: |
| **Excel Supported Text Formats** |:-----:|:-----:|
| Delimiter-Separated Values (CSV/TSV/DSV) | | :o: |
| **Other Workbook/Worksheet Formats** |:-----:|:-----:|
| OpenDocument Spreadsheet (ODS) | :o: | :o: |
| Flat XML ODF Spreadsheet (FODS) | :o: | :o: |
| Uniform Office Format Spreadsheet (标文通 UOS1/UOS2) | :o: | |
| **Other Common Spreadsheet Output Formats** |:-----:|:-----:|
| HTML Tables | :o: | |
### Excel 2007+ XML (XLSX/XLSM)
XLSX and XLSM files are ZIP containers containing a series of XML files in
accordance with the Open Packaging Conventions (OPC). The XLSM filetype, almost
identical to XLSX, is used for files containing macros.
The format is standardized in ECMA-376 and later in ISO/IEC 29500. Excel does
not follow the specification, and there are additional documents discussing how
Excel deviates from the specification.
### Excel 2.0-95 (BIFF2/BIFF3/BIFF4/BIFF5)
@ -816,26 +892,6 @@ Excel HTML worksheets include special metadata encoded in styles. For example,
`mso-number-format` is a localized string containing the number format. Despite
the metadata the output is valid HTML, although it does accept bare `&` symbols.
## Tested Environments
- NodeJS 0.8, 0.9, 0.10, 0.11, 0.12, 4.x, 5.x, 6.x, 7.x
- IE 6/7/8/9/10/11 (IE6-9 browsers require shims for interacting with client)
- Chrome 24+
- Safari 6+
- FF 18+
Tests utilize the mocha testing framework. Travis-CI and Sauce Labs links:
- <https://travis-ci.org/SheetJS/js-xlsx> for XLSX module in nodejs
- <https://travis-ci.org/SheetJS/SheetJS.github.io> for XLS\* modules
- <https://saucelabs.com/u/sheetjs> for XLS\* modules using Sauce Labs
## Test Files
Test files are housed in [another repo](https://github.com/SheetJS/test_files).
Running `make init` will refresh the `test_files` submodule and get the files.
## Testing
`make test` will run the node-based tests. By default it runs tests on files in
@ -865,9 +921,9 @@ $ make lint # JSHint and JSCS checks
$ make flow # make lint + Flow checking
```
To run the in-browser tests, clone
[The oss.sheetjs.com repo](https://github.com/SheetJS/SheetJS.github.io) and
replace the xlsx.js file (then fire up the browser and go to `stress.html`):
To run the in-browser tests, clone the repo for
[oss.sheetjs.com](https://github.com/SheetJS/SheetJS.github.io) and replace
the xlsx.js file (then fire up the browser and go to `stress.html`):
```bash
$ cp xlsx.js ../SheetJS.github.io
@ -875,6 +931,26 @@ $ cd ../SheetJS.github.io
$ simplehttpserver # or "python -mSimpleHTTPServer" or "serve"
$ open -a Chromium.app http://localhost:8000/stress.html
```
### Tested Environments
- NodeJS 0.8, 0.9, 0.10, 0.11, 0.12, 4.x, 5.x, 6.x, 7.x
- IE 6/7/8/9/10/11 (IE6-9 browsers require shims for interacting with client)
- Chrome 24+
- Safari 6+
- FF 18+
Tests utilize the mocha testing framework. Travis-CI and Sauce Labs links:
- <https://travis-ci.org/SheetJS/js-xlsx> for XLSX module in nodejs
- <https://travis-ci.org/SheetJS/SheetJS.github.io> for XLS\* modules
- <https://saucelabs.com/u/sheetjs> for XLS\* modules using Sauce Labs
### Test Files
Test files are housed in [another repo](https://github.com/SheetJS/test_files).
Running `make init` will refresh the `test_files` submodule and get the files.
## Contributing

@ -1 +1 @@
XLSX.version = '0.9.1';
XLSX.version = '0.9.2';

@ -193,7 +193,6 @@ function parse_ct(data/*:?string*/, opts) {
case '<Default': ctext[y.Extension] = y.ContentType; break;
case '<Override':
if(ct[ct2type[y.ContentType]] !== undefined) ct[ct2type[y.ContentType]].push(y.PartName);
else if(opts.WTF) console.error(y);
break;
}
});

@ -70,7 +70,7 @@ function write_ext_props(cp, opts)/*:string*/ {
/* TODO: HeadingPairs, TitlesOfParts */
o[o.length] = (W('HeadingPairs', W('vt:vector', W('vt:variant', '<vt:lpstr>Worksheets</vt:lpstr>')+W('vt:variant', W('vt:i4', String(cp.Worksheets))), {size:2, baseType:"variant"})));
o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + s + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + escapexml(s) + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
if(o.length>2){ o[o.length] = ('</Properties>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}

@ -34,7 +34,6 @@ function parse_XTI(blob, length) {
function parse_RkRec(blob, length) {
var ixfe = blob.read_shift(2);
var RK = parse_RkNumber(blob);
//console.log("::", ixfe, RK,";;");
return [ixfe, RK];
}

@ -1,6 +1,6 @@
function hex2RGB(h) {
var o = h.substr(h[0]==="#"?1:0,6);
return [parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16)];
return [parseInt(o.substr(0,2),16),parseInt(o.substr(2,2),16),parseInt(o.substr(4,2),16)];
}
function rgb2Hex(rgb) {
for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);

@ -68,10 +68,15 @@ function update_xfext(xf, xfext) {
switch(xfe[0]) { /* 2.5.108 extPropData */
case 0x04: break; /* foreground color */
case 0x05: break; /* background color */
case 0x07: case 0x08: case 0x09: case 0x0a: break;
case 0x06: break; /* gradient fill */
case 0x07: break; /* top cell border color */
case 0x08: break; /* bottom cell border color */
case 0x09: break; /* left cell border color */
case 0x0a: break; /* right cell border color */
case 0x0b: break; /* diagonal cell border color */
case 0x0d: break; /* text color */
case 0x0e: break; /* font scheme */
default: throw "bafuq" + xfe[0].toString(16);
case 0x0f: break; /* indentation level */
}
});
}

@ -16,9 +16,10 @@ var rc_to_a1 = (function(){
};
})();
/* TODO actually parse the formula */
/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
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;
function shift_formula_str(f/*:string*/, delta/*:Cell*/)/*:string*/ {
return f.replace(/(^|[^A-Z0-9])([$]?)([A-Z]+)([$]?)(\d+)/g, function($0, $1, $2, $3, $4, $5, off, str) {
return f.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
});
}

@ -265,7 +265,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
case 'inlineStr':
cref = d.match(isregex);
p.t = 's';
if(cref != null) { if((sstr = parse_si(cref[1]))) p.v = sstr.t; } else p.v = "";
if(cref != null && (sstr = parse_si(cref[1]))) p.v = sstr.t; else p.v = "";
break; // inline string
case 'b': p.v = parsexmlbool(p.v); break;
case 'd':

@ -41,7 +41,7 @@ function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
/* 18.2.20 sheets CT_Sheets 1 */
case '<sheets>': case '</sheets>': break; // aggregate sheet
/* 18.2.19 sheet CT_Sheet + */
case '<sheet': delete y[0]; y.name = utf8read(y.name); wb.Sheets.push(y); break;
case '<sheet': delete y[0]; y.name = unescapexml(utf8read(y.name)); wb.Sheets.push(y); break;
case '</sheet>': break;
/* 18.2.15 functionGroups CT_FunctionGroups ? */
@ -140,7 +140,7 @@ function write_wb_xml(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:string*/ {
o[o.length] = (writextag('workbookPr', null, {date1904:safe1904(wb)}));
o[o.length] = "<sheets>";
for(var i = 0; i != wb.SheetNames.length; ++i)
o[o.length] = (writextag('sheet',null,{name:wb.SheetNames[i].substr(0,31), sheetId:""+(i+1), "r:id":"rId"+(i+1)}));
o[o.length] = (writextag('sheet',null,{name:escapexml(wb.SheetNames[i].substr(0,31)), sheetId:""+(i+1), "r:id":"rId"+(i+1)}));
o[o.length] = "</sheets>";
if(o.length>2){ o[o.length] = '</workbook>'; o[1]=o[1].replace("/>",">"); }
return o.join("");

@ -237,7 +237,7 @@ function parse_xlml_xml(d, opts)/*:Workbook*/ {
r = c = 0;
state.push([Rn[3], false]);
tmp = xlml_parsexmltag(Rn[0]);
sheetname = tmp.Name;
sheetname = unescapexml(tmp.Name);
cursheet = {};
mergecells = [];
}

22
dist/xlsx.core.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

24
dist/xlsx.full.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

332
dist/xlsx.js vendored

@ -5,7 +5,7 @@
/*exported XLSX */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.9.1';
XLSX.version = '0.9.2';
var current_codepage = 1200, current_cptable;
if(typeof module !== "undefined" && typeof require !== 'undefined') {
if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel.js');
@ -92,7 +92,7 @@ function s2a(s) {
var bconcat = function(bufs) { return [].concat.apply([], bufs); };
var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/;
/* ssf.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
/* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */
/*jshint -W041 */
var SSF = {};
var make_ssf = function make_ssf(SSF){
@ -106,7 +106,7 @@ function pad0r1(v,d){var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.l
function pad0r2(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
var p2_32 = Math.pow(2,32);
function pad0r(v,d){if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); }
function isgeneral(s, i) { return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; }
function isgeneral(s, i) { i = i || 0; return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; }
/* Options */
var opts_fmt = [
["date1904", 0],
@ -118,36 +118,36 @@ function fixopts(o){
}
SSF.opts = opts_fmt;
var table_fmt = {
0: 'General',
1: '0',
2: '0.00',
3: '#,##0',
4: '#,##0.00',
9: '0%',
10: '0.00%',
11: '0.00E+00',
12: '# ?/?',
13: '# ??/??',
14: 'm/d/yy',
15: 'd-mmm-yy',
16: 'd-mmm',
17: 'mmm-yy',
18: 'h:mm AM/PM',
19: 'h:mm:ss AM/PM',
20: 'h:mm',
21: 'h:mm:ss',
22: 'm/d/yy h:mm',
37: '#,##0 ;(#,##0)',
38: '#,##0 ;[Red](#,##0)',
39: '#,##0.00;(#,##0.00)',
40: '#,##0.00;[Red](#,##0.00)',
45: 'mm:ss',
46: '[h]:mm:ss',
47: 'mmss.0',
48: '##0.0E+0',
49: '@',
56: '"上午/下午 "hh"時"mm"分"ss"秒 "',
65535: 'General'
0: 'General',
1: '0',
2: '0.00',
3: '#,##0',
4: '#,##0.00',
9: '0%',
10: '0.00%',
11: '0.00E+00',
12: '# ?/?',
13: '# ??/??',
14: 'm/d/yy',
15: 'd-mmm-yy',
16: 'd-mmm',
17: 'mmm-yy',
18: 'h:mm AM/PM',
19: 'h:mm:ss AM/PM',
20: 'h:mm',
21: 'h:mm:ss',
22: 'm/d/yy h:mm',
37: '#,##0 ;(#,##0)',
38: '#,##0 ;[Red](#,##0)',
39: '#,##0.00;(#,##0.00)',
40: '#,##0.00;[Red](#,##0.00)',
45: 'mm:ss',
46: '[h]:mm:ss',
47: 'mmss.0',
48: '##0.0E+0',
49: '@',
56: '"上午/下午 "hh"時"mm"分"ss"秒 "',
65535: 'General'
};
var days = [
['Sun', 'Sunday'],
@ -253,8 +253,8 @@ function parse_date_code(v,opts,b2) {
else if(date === 0) {dout = b2 ? [1317,8,29] : [1900,1,0]; dow=6;}
else {
if(date > 60) --date;
/* 1 = Jan 1 1900 */
var d = new Date(1900,0,1);
/* 1 = Jan 1 1900 in Gregorian */
var d = new Date(1900, 0, 1);
d.setDate(d.getDate() + date - 1);
dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
dow = d.getDay();
@ -316,7 +316,7 @@ function write_date(type, fmt, val, ss0) {
}
switch(fmt) {
case 's': case 'ss': case '.0': case '.00': case '.000':
if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100;
if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100;
else tt = ss0 === 1 ? 10 : 1;
ss = Math.round((tt)*(val.S + val.u));
if(ss >= 60*tt) ss = 0;
@ -366,23 +366,23 @@ function write_num_exp(fmt, val){
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
if(o.indexOf("e") === -1) {
var fakee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E);
if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
else o += "E+" + (fakee - ee);
while(o.substr(0,2) === "0.") {
o = o[0] + o.substr(2,period) + "." + o.substr(2+period);
o = o.charAt(0) + o.substr(2,period) + "." + o.substr(2+period);
o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0.");
}
o = o.replace(/\+-/,"-");
}
o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
} else o = val.toExponential(idx);
if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o[o.length-1];
if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
return o.replace("e","E");
}
var frac1 = /# (\?+)( ?)\/( ?)(\d+)/;
function write_num_f1(r, aval, sign) {
var den = parseInt(r[4]), rr = Math.round(aval * den), base = Math.floor(rr/den);
var den = parseInt(r[4],10), rr = Math.round(aval * den), base = Math.floor(rr/den);
var myn = (rr - base*den), myd = den;
return sign + (base === 0 ? "" : ""+base) + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad_(myn,r[1].length) + r[2] + "/" + r[3] + pad0(myd,r[4].length));
}
@ -415,39 +415,40 @@ function write_num_flt(type, fmt, val) {
if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val);
if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val);
if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt[1]==' '?2:1),val);
var o, oo;
var o;
var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length);
if(fmt.match(/^[#?]+$/)) {
o = pad0r(val,0); if(o === "0") o = "";
return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
}
if((r = fmt.match(frac1)) !== null) return write_num_f1(r, aval, sign);
if(fmt.match(/^#+0+$/) !== null) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
if((r = fmt.match(dec1)) !== null) {
if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign);
if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
if((r = fmt.match(dec1))) {
// $FlowIgnore
o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
}
fmt = fmt.replace(/^#+([0.])/, "$1");
if((r = fmt.match(/^(0*)\.(#*)$/)) !== null) {
if((r = fmt.match(/^(0*)\.(#*)$/))) {
return sign + rnd(aval, r[2].length).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
}
if((r = fmt.match(/^#,##0(\.?)$/)) !== null) return sign + commaify(pad0r(aval,0));
if((r = fmt.match(/^#,##0\.([#0]*0)$/)) !== null) {
if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify(pad0r(aval,0));
if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val))) + "." + pad0(dec(val, r[1].length),r[1].length);
}
if((r = fmt.match(/^#,#*,#0/)) !== null) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/)) !== null) {
if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val));
ri = 0;
return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==='0'?'0':"";}));
}
if(fmt.match(phone) !== null) {
if(fmt.match(phone)) {
o = write_num_flt(type, "##########", val);
return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
}
var oa = "";
if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/)) !== null) {
if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
ri = Math.min(r[4].length,7);
ff = frac(aval, Math.pow(10,ri)-1, false);
o = "" + sign;
@ -459,23 +460,23 @@ function write_num_flt(type, fmt, val) {
o += oa;
return o;
}
if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/)) !== null) {
if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
ri = Math.min(Math.max(r[1].length, r[4].length),7);
ff = frac(aval, Math.pow(10,ri)-1, true);
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
}
if((r = fmt.match(/^[#0?]+$/)) !== null) {
if((r = fmt.match(/^[#0?]+$/))) {
o = pad0r(val, 0);
if(fmt.length <= o.length) return o;
return hashq(fmt.substr(0,fmt.length-o.length)) + o;
}
if((r = fmt.match(/^([#0?]+)\.([#0]+)$/)) !== null) {
if((r = fmt.match(/^([#0?]+)\.([#0]+)$/))) {
o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
ri = o.indexOf(".");
var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
}
if((r = fmt.match(/^00,000\.([#0]*0)$/)) !== null) {
if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
ri = dec(val, r[1].length);
return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(flr(val)).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(ri,r[1].length);
}
@ -504,13 +505,13 @@ function write_num_exp2(fmt, val){
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
if(!o.match(/[Ee]/)) {
var fakee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E);
if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
else o += "E+" + (fakee - ee);
o = o.replace(/\+-/,"-");
}
o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
} else o = val.toExponential(idx);
if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o[o.length-1];
if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
return o.replace("e","E");
}
@ -531,32 +532,33 @@ function write_num_int(type, fmt, val) {
o = (""+val); if(val === 0) o = "";
return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
}
if((r = fmt.match(frac1)) !== null) return write_num_f2(r, aval, sign);
if(fmt.match(/^#+0+$/) !== null) return sign + pad0(aval,fmt.length - fmt.indexOf("0"));
if((r = fmt.match(dec1)) !== null) {
if((r = fmt.match(frac1))) return write_num_f2(r, aval, sign);
if(fmt.match(/^#+0+$/)) return sign + pad0(aval,fmt.length - fmt.indexOf("0"));
if((r = fmt.match(dec1))) {
// $FlowIgnore
o = (""+val).replace(/^([^\.]+)$/,"$1."+r[1]).replace(/\.$/,"."+r[1]).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", r[1].length-$1.length); });
return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
}
fmt = fmt.replace(/^#+([0.])/, "$1");
if((r = fmt.match(/^(0*)\.(#*)$/)) !== null) {
if((r = fmt.match(/^(0*)\.(#*)$/))) {
return sign + (""+aval).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
}
if((r = fmt.match(/^#,##0(\.?)$/)) !== null) return sign + commaify((""+aval));
if((r = fmt.match(/^#,##0\.([#0]*0)$/)) !== null) {
if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify((""+aval));
if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify((""+val)) + "." + fill('0',r[1].length);
}
if((r = fmt.match(/^#,#*,#0/)) !== null) return write_num_int(type,fmt.replace(/^#,#*,/,""),val);
if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/)) !== null) {
if((r = fmt.match(/^#,#*,#0/))) return write_num_int(type,fmt.replace(/^#,#*,/,""),val);
if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val));
ri = 0;
return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o[ri++]:x==='0'?'0':"";}));
}
if(fmt.match(phone) !== null) {
if(fmt.match(phone)) {
o = write_num_int(type, "##########", val);
return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
}
var oa = "";
if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/)) !== null) {
if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
ri = Math.min(r[4].length,7);
ff = frac(aval, Math.pow(10,ri)-1, false);
o = "" + sign;
@ -568,23 +570,23 @@ function write_num_int(type, fmt, val) {
o += oa;
return o;
}
if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/)) !== null) {
if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
ri = Math.min(Math.max(r[1].length, r[4].length),7);
ff = frac(aval, Math.pow(10,ri)-1, true);
return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
}
if((r = fmt.match(/^[#0?]+$/)) !== null) {
if((r = fmt.match(/^[#0?]+$/))) {
o = "" + val;
if(fmt.length <= o.length) return o;
return hashq(fmt.substr(0,fmt.length-o.length)) + o;
}
if((r = fmt.match(/^([#0]+)\.([#0]+)$/)) !== null) {
if((r = fmt.match(/^([#0]+)\.([#0]+)$/))) {
o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
ri = o.indexOf(".");
var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
}
if((r = fmt.match(/^00,000\.([#0]*0)$/)) !== null) {
if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify(""+val).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(0,r[1].length);
}
switch(fmt) {
@ -619,7 +621,7 @@ function eval_fmt(fmt, v, opts, flen) {
var hr='H';
/* Tokenize */
while(i < fmt.length) {
switch((c = fmt[i])) {
switch((c = fmt.charAt(i))) {
case 'G': /* General */
if(!isgeneral(fmt, i)) throw new Error('unrecognized character ' + c + ' in ' +fmt);
out[out.length] = {t:'G', v:'General'}; i+=7; break;
@ -633,7 +635,7 @@ function eval_fmt(fmt, v, opts, flen) {
out[out.length] = {t:'T', v:v}; ++i; break;
case 'B': case 'b':
if(fmt[i+1] === "1" || fmt[i+1] === "2") {
if(dt==null) { dt=parse_date_code(v, opts, fmt[i+1] === "2"); if(dt==null) return ""; }
if(dt==null) { dt=parse_date_code(v, opts, fmt[i+1] === "2"); if(dt==null) return ""; }
out[out.length] = {t:'X', v:fmt.substr(i,2)}; lst = c; i+=2; break;
}
/* falls through */
@ -650,15 +652,15 @@ function eval_fmt(fmt, v, opts, flen) {
case 'A':
q={t:c, v:"A"};
if(dt==null) dt=parse_date_code(v, opts);
if(fmt.substr(i, 3) === "A/P") { if(dt!=null) q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;}
else if(fmt.substr(i,5) === "AM/PM") { if(dt!=null) q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; }
if(fmt.substr(i, 3) === "A/P") { if(dt!=null) q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;}
else if(fmt.substr(i,5) === "AM/PM") { if(dt!=null) q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; }
else { q.t = "t"; ++i; }
if(dt==null && q.t === 'T') return "";
out[out.length] = q; lst = c; break;
case '[':
o = c;
while(fmt[i++] !== ']' && i < fmt.length) o += fmt[i];
if(o.slice(-1) !== ']') throw 'unterminated "[" block: |' + o + '|';
if(o.substr(-1) !== ']') throw 'unterminated "[" block: |' + o + '|';
if(o.match(abstime)) {
if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
out[out.length] = {t:'Z', v:o.toLowerCase()};
@ -709,12 +711,12 @@ function eval_fmt(fmt, v, opts, flen) {
switch(bt) {
case 0: break;
case 1:
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
if(dt.M >= 60) { dt.M = 0; ++dt.H; }
break;
case 2:
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
if(dt.S >= 60) { dt.S = 0; ++dt.M; }
break;
}
@ -723,9 +725,9 @@ function eval_fmt(fmt, v, opts, flen) {
for(i=0; i < out.length; ++i) {
switch(out[i].t) {
case 't': case 'T': case ' ': case 'D': break;
case 'X': out[i] = undefined; break;
case 'X': out[i].v = ""; out[i].t = ";"; break;
case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'b': case 'Z':
out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
out[i].t = 't'; break;
case 'n': case '(': case '?':
jj = i+1;
@ -736,7 +738,7 @@ function eval_fmt(fmt, v, opts, flen) {
c === 't' && (out[jj].v === '/' || '$€'.indexOf(out[jj].v) > -1 || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?')
)) {
out[i].v += out[jj].v;
out[jj] = undefined; ++jj;
out[jj] = {v:"", t:";"}; ++jj;
}
nstr += out[i].v;
i = jj-1; break;
@ -819,7 +821,7 @@ function choose_fmt(f, v) {
var fmt = split_fmt(f);
var l = fmt.length, lat = fmt[l-1].indexOf("@");
if(l<4 && lat>-1) --l;
if(fmt.length > 4) throw "cannot find right format for |" + fmt + "|";
if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
switch(fmt.length) {
case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
@ -841,7 +843,7 @@ function format(fmt,v,o) {
var sfmt = "";
switch(typeof fmt) {
case "string": sfmt = fmt; break;
case "number": sfmt = (o.table != null ? o.table : table_fmt)[fmt]; break;
case "number": sfmt = (o.table != null ? (o.table) : table_fmt)[fmt]; break;
}
if(isgeneral(sfmt,0)) return general_fmt(v, o);
var f = choose_fmt(sfmt, v);
@ -1425,12 +1427,12 @@ function parsexmltag(tag, skip_root) {
q = cc.substr(0,c); v = cc.substring(c+2, cc.length-1);
for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
if(j===q.length) {
//if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_")); // from ods
if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_")); // from ods
z[q] = v;
}
else {
var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1);
//if(z[k] && q.substr(j-3,3) == "ext") continue; // from ods
if(z[k] && q.substr(j-3,3) == "ext") continue; // from ods
z[k] = v;
}
}
@ -1517,17 +1519,18 @@ if(has_buf) {
};
var corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3";
if(utf8read(corpus) == utf8readb(corpus)) utf8read = utf8readb;
// $FlowIgnore
var utf8readc = function utf8readc(data) { return Buffer(data, 'binary').toString('utf8'); };
if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
}
// matches <foo>...</foo> extracts content
var matchtag = (function() {
var mtcache = {};
var mtcache = ({});
return function matchtag(f,g) {
var t = f+"|"+(g||"");
if(mtcache[t] !== undefined) return mtcache[t];
return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([^\u2603]*)</(?:\\w+:)?'+f+'>',(g||"")));
if(mtcache[t]) return mtcache[t];
return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([^\u2603]*)</(?:\\w+:)?'+f+'>',((g||""))));
};
})();
@ -1720,7 +1723,7 @@ function ReadShift(size, t) {
case 2: oI = (t === 'i' ? __readInt16LE : __readUInt16LE)(this, this.l); this.l += 2; return oI;
case 4:
if(t === 'i' || (this[this.l+3] & 0x80)===0) { oI = __readInt32LE(this, this.l); this.l += 4; return oI; }
else { oR = __readUInt32LE(this, this.l); this.l += 4; return oR; } break;
else { oR = __readUInt32LE(this, this.l); this.l += 4; } return oR;
case 8: if(t === 'f') { oR = __double(this, this.l); this.l += 8; return oR; }
/* falls through */
case 16: o = __hexlify(this, this.l, size); break;
@ -1733,14 +1736,14 @@ var __writeUInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] =
var __writeInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); };
function WriteShift(t, val, f) {
var size, i;
var size = 0, i = 0;
if(f === 'dbcs') {
for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i);
for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i);
size = 2 * val.length;
} else if(f === 'sbcs') {
for(i = 0; i != val.length; ++i) this[this.l + i] = val.charCodeAt(i) & 0xFF;
for(i = 0; i != val.length; ++i) this[this.l + i] = val.charCodeAt(i) & 0xFF;
size = val.length;
} else switch(t) {
} else switch(t) {
case 1: size = 1; this[this.l] = val&0xFF; break;
case 2: size = 2; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; break;
case 3: size = 3; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; val >>>= 8; this[this.l+2] = val&0xFF; break;
@ -1797,7 +1800,7 @@ function recordhopper(data, cb, opts) {
function buf_array() {
var bufs = [], blksz = 2048;
var newblk = function ba_newblk(sz) {
var o = new_buf(sz);
var o = (new_buf(sz));
prep_blob(o, 0);
return o;
};
@ -1890,6 +1893,7 @@ function encode_range_xls(r, opts) {
return encode_cell_xls(r.s) + ":" + encode_cell_xls(r.e);
}
var OFFCRYPTO = {};
var make_offcrypto = function(O, _crypto) {
var crypto;
if(typeof _crypto !== 'undefined') crypto = _crypto;
@ -1906,7 +1910,8 @@ var make_offcrypto = function(O, _crypto) {
j = (j + S[i] + (key[i%key.length]).charCodeAt(0))&255;
t = S[i]; S[i] = S[j]; S[j] = t;
}
i = j = 0; out = Buffer(data.length);
// $FlowIgnore
i = j = 0; var out = Buffer(data.length);
for(c = 0; c != data.length; ++c) {
i = (i + 1)&255;
j = (j + S[i])%256;
@ -2561,7 +2566,6 @@ function parse_ct(data, opts) {
case '<Default': ctext[y.Extension] = y.ContentType; break;
case '<Override':
if(ct[ct2type[y.ContentType]] !== undefined) ct[ct2type[y.ContentType]].push(y.PartName);
else if(opts.WTF) console.error(y);
break;
}
});
@ -2888,7 +2892,7 @@ function write_ext_props(cp, opts) {
/* TODO: HeadingPairs, TitlesOfParts */
o[o.length] = (W('HeadingPairs', W('vt:vector', W('vt:variant', '<vt:lpstr>Worksheets</vt:lpstr>')+W('vt:variant', W('vt:i4', String(cp.Worksheets))), {size:2, baseType:"variant"})));
o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + s + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + escapexml(s) + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
if(o.length>2){ o[o.length] = ('</Properties>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}
@ -2950,6 +2954,7 @@ function write_cust_props(cp, opts) {
if(!cp) return o.join("");
var pid = 1;
keys(cp).forEach(function custprop(k) { ++pid;
// $FlowIgnore
o[o.length] = (writextag('property', write_vt(cp[k]), {
'fmtid': '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}',
'pid': pid,
@ -3449,7 +3454,6 @@ function parse_XTI(blob, length) {
function parse_RkRec(blob, length) {
var ixfe = blob.read_shift(2);
var RK = parse_RkNumber(blob);
//console.log("::", ixfe, RK,";;");
return [ixfe, RK];
}
@ -3607,7 +3611,7 @@ function parse_BoundSheet8(blob, length, opts) {
function parse_SST(blob, length) {
var cnt = blob.read_shift(4);
var ucnt = blob.read_shift(4);
var strs = [];
var strs = ([]);
for(var i = 0; i != ucnt; ++i) {
strs.push(parse_XLUnicodeRichExtendedString(blob));
}
@ -4524,6 +4528,7 @@ var parse_rs = (function parse_rs_factory() {
/* 18.4.8 si CT_Rst */
var sitregex = /<(?:\w+:)?t[^>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r>/;
var sirphregex = /<(?:\w+:)?rPh.*?>(.*?)<\/(?:\w+:)?rPh>/g;
function parse_si(x, opts) {
var html = opts ? opts.cellHTML : true;
var z = {};
@ -4539,7 +4544,7 @@ function parse_si(x, opts) {
/* 18.4.4 r CT_RElt (Rich Text Run) */
else if((y = x.match(sirregex))) {
z.r = utf8read(x);
z.t = utf8read(unescapexml((x.replace(/<rPh.*?>(.*?)<\/rPh>/g, '').match(sitregex)||[]).join("").replace(tagregex,"")));
z.t = utf8read(unescapexml((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")));
if(html) z.h = parse_rs(z.r);
}
/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
@ -4599,7 +4604,7 @@ function parse_BrtBeginSst(data, length) {
/* [MS-XLSB] 2.1.7.45 Shared Strings */
function parse_sst_bin(data, opts) {
var s = [];
var s = ([]);
var pass = false;
recordhopper(data, function hopper_sst(val, R, RT) {
switch(R.n) {
@ -4818,7 +4823,7 @@ function parse_FilePass(blob, length, opts) {
function hex2RGB(h) {
var o = h.substr(h[0]==="#"?1:0,6);
return [parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16)];
return [parseInt(o.substr(0,2),16),parseInt(o.substr(2,2),16),parseInt(o.substr(4,2),16)];
}
function rgb2Hex(rgb) {
for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);
@ -4974,7 +4979,7 @@ function parse_numFmts(t, opts) {
function write_numFmts(NF, opts) {
var o = ["<numFmts>"];
[[5,8],[23,26],[41,44],[63,66],[164,392]].forEach(function(r) {
for(var i = r[0]; i <= r[1]; ++i) if(NF[i] !== undefined) o[o.length] = (writextag('numFmt',null,{numFmtId:i,formatCode:escapexml(NF[i])}));
for(var i = r[0]; i <= r[1]; ++i) if(NF[i]) o[o.length] = (writextag('numFmt',null,{numFmtId:i,formatCode:escapexml(NF[i])}));
});
if(o.length === 1) return "";
o[o.length] = ("</numFmts>");
@ -5064,7 +5069,7 @@ RELS.STY = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/
function write_sty_xml(wb, opts) {
var o = [XML_HEADER, STYLES_XML_ROOT], w;
if((w = write_numFmts(wb.SSF)) != null) o[o.length] = w;
if(wb.SSF && (w = write_numFmts(wb.SSF)) != null) o[o.length] = w;
o[o.length] = ('<fonts count="1"><font><sz val="12"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font></fonts>');
o[o.length] = ('<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
o[o.length] = ('<borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>');
@ -5560,10 +5565,15 @@ function update_xfext(xf, xfext) {
switch(xfe[0]) { /* 2.5.108 extPropData */
case 0x04: break; /* foreground color */
case 0x05: break; /* background color */
case 0x07: case 0x08: case 0x09: case 0x0a: break;
case 0x06: break; /* gradient fill */
case 0x07: break; /* top cell border color */
case 0x08: break; /* bottom cell border color */
case 0x09: break; /* left cell border color */
case 0x0a: break; /* right cell border color */
case 0x0b: break; /* diagonal cell border color */
case 0x0d: break; /* text color */
case 0x0e: break; /* font scheme */
default: throw "bafuq" + xfe[0].toString(16);
case 0x0f: break; /* indentation level */
}
});
}
@ -5756,9 +5766,10 @@ var rc_to_a1 = (function(){
};
})();
/* TODO actually parse the formula */
/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
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;
function shift_formula_str(f, delta) {
return f.replace(/(^|[^A-Z0-9])([$]?)([A-Z]+)([$]?)(\d+)/g, function($0, $1, $2, $3, $4, $5, off, str) {
return f.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
});
}
@ -6097,6 +6108,7 @@ function parse_PtgExtraArray(blob, length, opts) {
rows = 1 + blob.read_shift(2); //DRw
}
if(opts.biff >= 2 && opts.biff < 8) { --rows; if(--cols == 0) cols = 0x100; }
// $FlowIgnore
for(var i = 0, o=[]; i != rows && (o[i] = []); ++i)
for(var j = 0; j != cols; ++j) o[i][j] = parse_SerAr(blob, opts.biff);
return o;
@ -6417,7 +6429,8 @@ function parse_Rgce(blob, length, opts) {
id = blob[blob.l + 1];
R = (id === 0x18 ? Ptg18 : Ptg19)[id];
}
if(!R || !R.f) { ptgs.push(parsenoop(blob, length)); }
if(!R || !R.f) { /*ptgs.push*/(parsenoop(blob, length)); }
// $FlowIgnore
else { ptgs.push([R.n, R.f(blob, length, opts)]); }
}
return ptgs;
@ -6431,7 +6444,8 @@ function stringify_array(f) {
var y = x[j];
if(y) switch(y[0]) {
// TODO: handle embedded quotes
case 0x02: r.push('"' + y[1].replace(/"/g,'""') + '"'); break;
case 0x02:
r.push('"' + y[1].replace(/"/g,'""') + '"'); break;
default: r.push(y[1]);
} else r.push("");
}
@ -6456,10 +6470,10 @@ var PtgBinOp = {
PtgPower: "^",
PtgSub: "-"
};
function stringify_formula(formula, range, cell, supbooks, opts) {
function stringify_formula(formula/*Array<any>*/, range, cell, supbooks, opts) {
//console.log(formula);
var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}};
var stack = [], e1, e2, type, c, ixti, nameidx, r, sname="";
var stack = [], e1, e2, type, c, ixti=0, nameidx=0, r, sname="";
if(!formula[0] || !formula[0][0]) return "";
var last_sp = -1, sp = "";
//console.log("--",cell,formula[0])
@ -6489,10 +6503,13 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
e1 = stack.pop(); e2 = stack.pop();
if(last_sp >= 0) {
switch(formula[0][last_sp][1][0]) {
// $FlowIgnore
case 0: sp = fill(" ", formula[0][last_sp][1][1]); break;
// $FlowIgnore
case 1: sp = fill("\r", formula[0][last_sp][1][1]); break;
default:
sp = "";
// $FlowIgnore
if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + formula[0][last_sp][1][0]);
}
e2 = e2 + sp;
@ -6562,6 +6579,7 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
/* 2.5.198.79 TODO: precision? */
case 'PtgNum': stack.push(String(f[1])); break;
/* 2.5.198.89 */
// $FlowIgnore
case 'PtgStr': stack.push('"' + f[1] + '"'); break;
/* 2.5.198.57 */
case 'PtgErr': stack.push(f[1]); break;
@ -6594,7 +6612,7 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
/* f[1] = type, 0, nameindex */
nameidx = f[1][2];
var lbl = supbooks[0][nameidx];
var name = lbl ? lbl.Name : "**MISSING**" + nameidx;
var name = lbl ? lbl.Name : "**MISSING**" + String(nameidx);
if(name in XLSXFutureFunctions) name = XLSXFutureFunctions[name];
stack.push(name);
break;
@ -6602,7 +6620,7 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
/* 2.5.97.61 TODO: do something different for revisions */
case 'PtgNameX':
/* f[1] = type, ixti, nameindex */
var bookidx = f[1][1]; nameidx = f[1][2]; var externbook;
var bookidx = (f[1][1]); nameidx = f[1][2]; var externbook;
/* TODO: Properly handle missing values */
//console.log(bookidx, supbooks);
if(opts.biff == 5) {
@ -6622,11 +6640,16 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
if(last_sp >= 0) {
sp = "";
switch(formula[0][last_sp][1][0]) {
// $FlowIgnore
case 2: lp = fill(" ", formula[0][last_sp][1][1]) + lp; break;
// $FlowIgnore
case 3: lp = fill("\r", formula[0][last_sp][1][1]) + lp; break;
// $FlowIgnore
case 4: rp = fill(" ", formula[0][last_sp][1][1]) + rp; break;
// $FlowIgnore
case 5: rp = fill("\r", formula[0][last_sp][1][1]) + rp; break;
default:
// $FlowIgnore
if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + formula[0][last_sp][1][0]);
}
last_sp = -1;
@ -6643,7 +6666,7 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
/* 2.5.198.58 TODO */
case 'PtgExp':
c = {c:f[1][1],r:f[1][0]};
var q = {c: cell.c, r:cell.r};
var q = ({c: cell.c, r:cell.r});
if(supbooks.sharedf[encode_cell(c)]) {
var parsedf = (supbooks.sharedf[encode_cell(c)]);
stack.push(stringify_formula(parsedf, _range, q, supbooks, opts));
@ -6697,7 +6720,7 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
/* 2.5.198.72 TODO */
case 'PtgMemFunc': break;
default: throw new Error('Unrecognized Formula Token: ' + f);
default: throw new Error('Unrecognized Formula Token: ' + String(f));
}
var PtgNonDisp = ['PtgAttrSpace', 'PtgAttrSpaceSemi', 'PtgAttrGoto'];
if(last_sp >= 0 && PtgNonDisp.indexOf(formula[0][ff][0]) == -1) {
@ -6707,12 +6730,15 @@ function stringify_formula(formula, range, cell, supbooks, opts) {
/* note: some bad XLSB files omit the PtgParen */
case 4: _left = false;
/* falls through */
// $FlowIgnore
case 0: sp = fill(" ", f[1][1]); break;
case 5: _left = false;
/* falls through */
// $FlowIgnore
case 1: sp = fill("\r", f[1][1]); break;
default:
sp = "";
// $FlowIgnore
if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + f[1][0]);
}
stack.push((_left ? sp : "") + stack.pop() + (_left ? "" : sp));
@ -8333,7 +8359,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
case 'inlineStr':
cref = d.match(isregex);
p.t = 's';
if(cref != null) { if((sstr = parse_si(cref[1]))) p.v = sstr.t; } else p.v = "";
if(cref != null && (sstr = parse_si(cref[1]))) p.v = sstr.t; else p.v = "";
break; // inline string
case 'b': p.v = parsexmlbool(p.v); break;
case 'd':
@ -8402,7 +8428,7 @@ function write_ws_xml(idx, opts, wb) {
/* [MS-XLSB] 2.4.718 BrtRowHdr */
function parse_BrtRowHdr(data, length) {
var z = [];
var z = ([]);
z.r = data.read_shift(4);
data.l += length-4;
return z;
@ -8628,7 +8654,7 @@ function parse_BrtArrFmla(data, length, opts) {
var end = data.l + length;
var rfx = parse_RfX(data, 16);
var fAlwaysCalc = data.read_shift(1);
var o = [rfx, null, fAlwaysCalc];
var o = [rfx]; o[2] = fAlwaysCalc;
if(opts.cellFormula) {
var formula = parse_XLSBArrayParsedFormula(data, end - data.l, opts);
o[1] = formula;
@ -8640,7 +8666,7 @@ function parse_BrtArrFmla(data, length, opts) {
function parse_BrtShrFmla(data, length, opts) {
var end = data.l + length;
var rfx = parse_UncheckedRfX(data, 16);
var o = [rfx, null];
var o = [rfx];
if(opts.cellFormula) {
var formula = parse_XLSBSharedParsedFormula(data, end - data.l, opts);
o[1] = formula;
@ -9147,7 +9173,7 @@ function parse_wb_xml(data, opts) {
/* 18.2.20 sheets CT_Sheets 1 */
case '<sheets>': case '</sheets>': break; // aggregate sheet
/* 18.2.19 sheet CT_Sheet + */
case '<sheet': delete y[0]; y.name = utf8read(y.name); wb.Sheets.push(y); break;
case '<sheet': delete y[0]; y.name = unescapexml(utf8read(y.name)); wb.Sheets.push(y); break;
case '</sheet>': break;
/* 18.2.15 functionGroups CT_FunctionGroups ? */
@ -9234,7 +9260,10 @@ var WB_XML_ROOT = writextag('workbook', null, {
function safe1904(wb) {
/* TODO: store date1904 somewhere else */
try { return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false"; } catch(e) { return "false"; }
if(!wb.Workbook) return "false";
if(!wb.Workbook.WBProps) return "false";
// $FlowIgnore
return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false";
}
function write_wb_xml(wb, opts) {
@ -9243,7 +9272,7 @@ function write_wb_xml(wb, opts) {
o[o.length] = (writextag('workbookPr', null, {date1904:safe1904(wb)}));
o[o.length] = "<sheets>";
for(var i = 0; i != wb.SheetNames.length; ++i)
o[o.length] = (writextag('sheet',null,{name:wb.SheetNames[i].substr(0,31), sheetId:""+(i+1), "r:id":"rId"+(i+1)}));
o[o.length] = (writextag('sheet',null,{name:escapexml(wb.SheetNames[i].substr(0,31)), sheetId:""+(i+1), "r:id":"rId"+(i+1)}));
o[o.length] = "</sheets>";
if(o.length>2){ o[o.length] = '</workbook>'; o[1]=o[1].replace("/>",">"); }
return o.join("");
@ -9377,6 +9406,7 @@ function parse_wb_bin(data, opts) {
parse_wb_defaults(wb);
Names['!names'] = NameList;
// $FlowIgnore
wb.Names = Names;
return wb;
@ -9563,15 +9593,16 @@ function xlml_format(format, value) {
}
function xlml_set_custprop(Custprops, Rn, cp, val) {
var oval = val;
switch((cp[0].match(/dt:dt="([\w.]+)"/)||["",""])[1]) {
case "boolean": val = parsexmlbool(val); break;
case "i2": case "int": val = parseInt(val, 10); break;
case "r4": case "float": val = parseFloat(val); break;
case "date": case "dateTime.tz": val = new Date(val); break;
case "boolean": oval = parsexmlbool(val); break;
case "i2": case "int": oval = parseInt(val, 10); break;
case "r4": case "float": oval = parseFloat(val); break;
case "date": case "dateTime.tz": oval = new Date(val); break;
case "i8": case "string": case "fixed": case "uuid": case "bin.base64": break;
default: throw "bad custprop:" + cp[0];
default: throw new Error("bad custprop:" + cp[0]);
}
Custprops[unescapexml(Rn[3])] = val;
Custprops[unescapexml(Rn[3])] = oval;
}
function safe_format_xlml(cell, nf, o) {
@ -9744,7 +9775,7 @@ function parse_xlml_xml(d, opts) {
break;
case 'Worksheet': /* TODO: read range from FullRows/FullColumns */
if(Rn[1]==='/'){
if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
sheetnames.push(sheetname);
if(refguess.s.r <= refguess.e.r && refguess.s.c <= refguess.e.c) cursheet["!ref"] = encode_range(refguess);
if(mergecells.length) cursheet["!merges"] = mergecells;
@ -9754,13 +9785,13 @@ function parse_xlml_xml(d, opts) {
r = c = 0;
state.push([Rn[3], false]);
tmp = xlml_parsexmltag(Rn[0]);
sheetname = tmp.Name;
sheetname = unescapexml(tmp.Name);
cursheet = {};
mergecells = [];
}
break;
case 'Table':
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
else if(Rn[0].slice(-2) == "/>") break;
else {
table = xlml_parsexmltag(Rn[0]);
@ -9832,13 +9863,13 @@ function parse_xlml_xml(d, opts) {
case 'Styles':
case 'Workbook':
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
else state.push([Rn[3], false]);
break;
case 'Comment':
if(Rn[1]==='/'){
if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
xlml_clean_comment(comment);
comments.push(comment);
} else {
@ -9871,7 +9902,7 @@ function parse_xlml_xml(d, opts) {
case 'ExcelWorkbook':
case 'WorkbookOptions':
case 'WorksheetOptions':
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
break;
@ -10315,7 +10346,7 @@ function safe_format_xf(p, opts, date1904) {
}
else p.w = SSF._general(p.v);
}
else p.w = SSF.format(fmtid,p.v, {date1904:date1904||false});
else p.w = SSF.format(fmtid,p.v, {date1904:!!date1904});
if(opts.cellNF) p.z = SSF._table[fmtid];
} catch(e) { if(opts.WTF) throw e; }
}
@ -10336,7 +10367,7 @@ function parse_workbook(blob, options) {
var sst = [];
var cur_sheet = "";
var Preamble = {};
var lastcell, last_cell, cc, cmnt, rng, rngC, rngR;
var lastcell, last_cell = "", cc, cmnt, rng, rngC, rngR;
var shared_formulae = {};
var array_formulae = []; /* TODO: something more clever */
var temp_val;
@ -10352,7 +10383,7 @@ function parse_workbook(blob, options) {
var process_cell_style = function pcs(cell, line) {
var xfd = line.XF.data;
if(!xfd || !xfd.patternType) return;
line.s = {};
line.s = ({});
line.s.patternType = xfd.patternType;
var t;
if((t = rgb2Hex(get_rgb(xfd.icvFore)))) { line.s.fgColor = {rgb:t}; }
@ -10582,6 +10613,8 @@ function parse_workbook(blob, options) {
case 'Array': {
array_formulae.push(val);
if(options.cellFormula && out[last_cell]) {
if(!last_formula) break; /* technically unreachable */
if(!last_cell || !out[last_cell]) break; /* technically unreachable */
out[last_cell].f = stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
out[last_cell].F = encode_range(val[0]);
}
@ -10591,6 +10624,7 @@ function parse_workbook(blob, options) {
if(!options.cellFormula) break;
if(last_cell) {
/* TODO: capture range */
if(!last_formula) break; /* technically unreachable */
shared_formulae[encode_cell(last_formula.cell)]= val[0];
(out[encode_cell(last_formula.cell)]||{}).f = stringify_formula(val[0], range, lastcell, supbooks, opts);
}
@ -10922,7 +10956,7 @@ if(!Workbook) Workbook = cfb.find('/Book');
var CompObjP, SummaryP, WorkbookP;
if(CompObj) CompObjP = parse_compobj(CompObj);
if(options.bookProps && !options.bookSheets) WorkbookP = {};
if(options.bookProps && !options.bookSheets) WorkbookP = ({});
else {
if(Workbook) WorkbookP = parse_workbook(Workbook.content, options, !!Workbook.find);
else throw new Error("Cannot find Workbook stream");
@ -10935,7 +10969,7 @@ for(var y in cfb.Summary) props[y] = cfb.Summary[y];
for(y in cfb.DocSummary) props[y] = cfb.DocSummary[y];
WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
if(options.bookFiles) WorkbookP.cfb = cfb;
WorkbookP.CompObjP = CompObjP;
/*WorkbookP.CompObjP = CompObjP; // TODO: storage? */
return WorkbookP;
}
@ -12331,7 +12365,7 @@ function parse_html(str, opts) {
if(range.e.c < C) range.e.c = C;
var coord = encode_cell({r:R, c:C});
/* TODO: value parsing */
if(m == +m) ws[coord] = {t:'n', v:+m};
if(Number(m) == Number(m)) ws[coord] = {t:'n', v:+m};
else ws[coord] = {t:'s', v:m};
}
++R; C = 0;
@ -12788,7 +12822,7 @@ function parse_ods(zip, opts) {
opts = opts || ({});
var ods = !!safegetzipfile(zip, 'objectdata');
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
var content = getzipdata(zip, 'content.xml');
var content = getzipstr(zip, 'content.xml');
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
return parse_content_xml(ods ? content : utf8read(content), opts);
}
@ -12920,7 +12954,7 @@ function parse_zip(zip, opts) {
if(dir.style) styles = parse_sty(getzipdata(zip, dir.style.replace(/^\//,'')),dir.style, opts);
themes = {};
if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipdata(zip, dir.themes[0].replace(/^\//,''), true),dir.themes[0], opts);
if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts);
}
var wb = parse_wb(getzipdata(zip, dir.workbooks[0].replace(/^\//,'')), dir.workbooks[0], opts);
@ -12944,12 +12978,12 @@ function parse_zip(zip, opts) {
}
}
var out = {};
var out = ({});
if(opts.bookSheets || opts.bookProps) {
if(props.Worksheets && props.SheetNames.length > 0) sheets=props.SheetNames;
else if(wb.Sheets) sheets = wb.Sheets.map(function pluck(x){ return x.name; });
if(opts.bookProps) { out.Props = props; out.Custprops = custprops; }
if(typeof sheets !== 'undefined') out.SheetNames = sheets;
if(opts.bookSheets && typeof sheets !== 'undefined') out.SheetNames = sheets;
if(opts.bookSheets ? out.SheetNames : opts.bookProps) return out;
}
sheets = {};
@ -13027,7 +13061,9 @@ function write_zip(wb, opts) {
wb.SSF = SSF.get_table();
}
if(wb && wb.SSF) {
// $FlowIgnore
make_ssf(SSF); SSF.load_table(wb.SSF);
// $FlowIgnore
opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
}
opts.rels = {}; opts.wbrels = {};
@ -13050,7 +13086,7 @@ var zip = new jszip();
ct.coreprops.push(f);
add_rels(opts.rels, 2, f, RELS.CORE_PROPS);
f = "docProps/app.xml";
f = "docProps/app.xml";
wb.Props.SheetNames = wb.SheetNames;
wb.Props.Worksheets = wb.SheetNames.length;
zip.file(f, write_ext_props(wb.Props, opts));
@ -13169,9 +13205,9 @@ function write_string_type(out, opts) {
case "buffer": {
if(has_buf) return new Buffer(out, 'utf8');
else return out.split("").map(function(c) { return c.charCodeAt(0); });
} break;
default: throw new Error("Unrecognized type " + opts.type);
}
}
throw new Error("Unrecognized type " + opts.type);
}
/* TODO: test consistency */

22
dist/xlsx.min.js vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.min.map vendored

File diff suppressed because one or more lines are too long

104
misc/cfb.d.ts vendored

@ -1,104 +0,0 @@
declare enum CFBEntryType { unknown, storage, stream, lockbytes, property, root }
declare enum CFBStorageType { fat, minifat }
/* CFB Entry Object demanded by write functions */
interface CFBEntryMin {
/* Raw Content (Buffer when available, Array of bytes otherwise) */
content:any;
}
/* CFB Entry Object returned by parse functions */
interface CFBEntry extends CFBEntryMin {
/* Case-sensitive internal name */
name:string;
/* CFB type (salient types: stream, storage) -- see CFBEntryType */
type:string;
/* Creation Time */
ct:Date;
/* Modification Time */
mt:Date;
/* Raw creation time -- see [MS-DTYP] 2.3.3 FILETIME */
mtime:string;
/* Raw modification time -- see [MS-DTYP] 2.3.3 FILETIME */
ctime:string;
/* RBT color: 0 = red, 1 = black */
color:number;
/* Class ID represented as hex string */
clsid:string;
/* User-Defined State Bits */
state:number;
/* Starting Sector */
start:number;
/* Data Size */
size:number;
/* Storage location -- see CFBStorageType */
storage:string;
}
/* cfb.FullPathDir as demanded by write functions */
interface CFBDirectoryMin {
/* keys are unix-style paths */
[key:string]: CFBEntryMin;
}
/* cfb.FullPathDir Directory object */
interface CFBDirectory extends CFBDirectoryMin {
/* cfb.FullPathDir keys are paths; cfb.Directory keys are file names */
[key:string]: CFBEntry;
}
/* cfb object demanded by write functions */
interface CFBContainerMin {
/* Path -> CFB object mapping */
FullPathDir:CFBDirectoryMin;
}
/* cfb object returned by read and parse functions */
interface CFBContainer extends CFBContainerMin {
/* search by path or file name */
find(string):CFBEntry;
/* list of streams and storages */
FullPaths:string[];
/* Path -> CFB object mapping */
FullPathDir:CFBDirectory;
/* Array of entries in the same order as FullPaths */
FileIndex:CFBEntry[];
/* Raw Content, in chunks (Buffer when available, Array of bytes otherwise) */
raw:any[];
}
interface CFB {
read(f:any, options:any):CFBContainer;
parse(f:any):CFBContainer;
utils: {
ReadShift(size:any,t?:any):any;
WarnField(hexstr:string,fld?:string);
CheckField(hexstr:string,fld?:string);
prep_blob(blob:any, pos?:number):any;
bconcat(bufs:any[]):any;
};
main;
}

8
misc/node.d.ts vendored

@ -1,8 +0,0 @@
declare var require: {
(id: string): any;
}
declare var process: {
argv: string[];
exit(status: number): void;
}

@ -4,7 +4,7 @@
if [ $# -gt 0 ]; then
if [ -e "$1" ]; then
sed -i .sheetjs '/sourceMappingURL/d' "$1"
sed -i.sheetjs '/sourceMappingURL/d' "$1"
fi
else
cat - | sed '/sourceMappingURL/d'

65
misc/xl.d.ts vendored

@ -1,65 +0,0 @@
///<reference path='cfb.d.ts'/>
interface Cell {
v;
w?: string;
t?: string;
f?: string;
r?: string;
h?: string;
c?: any;
z?: string;
ixfe?: number;
}
interface CellAddress {
c: number;
r: number;
}
interface CellRange {
s: CellAddress;
e: CellAddress;
}
interface WorksheetBase {
'!range':CellRange;
'!ref':string;
}
interface Worksheet extends WorksheetBase {
[key: string]: Cell;
}
interface Worksheets {
[key: string]: Worksheet;
}
interface Workbook {
SheetNames: string[];
Sheets: Worksheets;
}
interface XLSX {
parse_xlscfb(cfb:CFBContainer): Workbook;
read;
readFile(filename: string): Workbook;
utils: {
encode_col(col: number): string;
encode_row(row: number): string;
encode_cell(cell: CellAddress): string;
encode_range;
decode_col(col: string): number;
decode_row(row: string): number;
split_cell(cell: string): string[];
decode_cell(cell: string): CellAddress;
decode_range(cell: string): CellRange;
sheet_to_csv(worksheet: Worksheet): string;
get_formulae(worksheet: Worksheet): string[];
make_csv(worksheet: Worksheet): string;
sheet_to_row_object_array(worksheet: Worksheet): Object[];
};
verbose: Number;
CFB:CFB;
main;
}

@ -1,71 +0,0 @@
///<reference path='node.d.ts'/>
///<reference path='xl.d.ts'/>
/* vim: set ts=2: */
var XLSX = <XLSX>require('xlsx');
var fs = require('fs'), program = require('commander');
program
.version('0.3.1')
.usage('[options] <file> [sheetname]')
.option('-f, --file <file>', 'use specified workbook')
.option('-s, --sheet <sheet>', 'print specified sheet (default first sheet)')
.option('-l, --list-sheets', 'list sheet names and exit')
.option('-F, --formulae', 'print formulae')
.option('--dev', 'development mode')
.option('--read', 'read but do not print out contents')
.option('-q, --quiet', 'quiet mode')
.parse(process.argv);
var filename:string, sheetname:string = '';
if(program.args[0]) {
filename = program.args[0];
if(program.args[1]) sheetname = program.args[1];
}
if(program.sheet) sheetname = program.sheet;
if(program.file) filename = program.file;
if(!filename) {
console.error("xlsx2csv: must specify a filename");
process.exit(1);
}
if(!fs.existsSync(filename)) {
console.error("xlsx2csv: " + filename + ": No such file or directory");
process.exit(2);
}
if(program.dev) XLSX.verbose = 2;
var wb:Workbook;
if(program.dev) wb = XLSX.readFile(filename);
else try {
wb = XLSX.readFile(filename);
} catch(e) {
var msg:string = (program.quiet) ? "" : "xlsx2csv: error parsing ";
msg += filename + ": " + e;
console.error(msg);
process.exit(3);
}
if(program.read) process.exit(0);
if(program.listSheets) {
console.log(wb.SheetNames.join("\n"));
process.exit(0);
}
var target_sheet:string = sheetname || '';
if(target_sheet === '') target_sheet = wb.SheetNames[0];
var ws:Worksheet;
try {
ws = wb.Sheets[target_sheet];
if(!ws) throw "Sheet " + target_sheet + " cannot be found";
} catch(e) {
console.error("xlsx2csv: error parsing "+filename+" "+target_sheet+": " + e);
process.exit(4);
}
if(!program.quiet) console.error(target_sheet);
if(program.formulae) console.log(XLSX.utils.get_formulae(ws).join("\n"));
else console.log(XLSX.utils.make_csv(ws));
console.log(ws["C2"]);

@ -1,6 +1,6 @@
{
"name": "xlsx",
"version": "0.9.1",
"version": "0.9.2",
"author": "sheetjs",
"description": "Excel (XLSB/XLSX/XLSM/XLS/XML) and ODS (ODS/FODS/UOS) spreadsheet parser and writer",
"keywords": [ "excel", "xls", "xlsx", "xlsb", "xlsm", "ods", "office", "spreadsheet" ],
@ -14,13 +14,13 @@
"fs": false
},
"dependencies": {
"exit-on-epipe":"",
"exit-on-epipe":"~1.0.0",
"ssf":"~0.8.1",
"codepage":"~1.7.0",
"cfb":"~0.11.0",
"crc-32":"",
"adler-32":"",
"commander":""
"crc-32":"~1.0.0",
"adler-32":"~1.0.0",
"commander":"~2.9.0"
},
"devDependencies": {
"mocha":"",

@ -5,7 +5,7 @@
/*exported XLSX */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.9.1';
XLSX.version = '0.9.2';
var current_codepage = 1200, current_cptable;
/*:: declare var cptable:any; */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -2616,7 +2616,6 @@ function parse_ct(data/*:?string*/, opts) {
case '<Default': ctext[y.Extension] = y.ContentType; break;
case '<Override':
if(ct[ct2type[y.ContentType]] !== undefined) ct[ct2type[y.ContentType]].push(y.PartName);
else if(opts.WTF) console.error(y);
break;
}
});
@ -2943,7 +2942,7 @@ function write_ext_props(cp, opts)/*:string*/ {
/* TODO: HeadingPairs, TitlesOfParts */
o[o.length] = (W('HeadingPairs', W('vt:vector', W('vt:variant', '<vt:lpstr>Worksheets</vt:lpstr>')+W('vt:variant', W('vt:i4', String(cp.Worksheets))), {size:2, baseType:"variant"})));
o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + s + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + escapexml(s) + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
if(o.length>2){ o[o.length] = ('</Properties>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}
@ -3505,7 +3504,6 @@ function parse_XTI(blob, length) {
function parse_RkRec(blob, length) {
var ixfe = blob.read_shift(2);
var RK = parse_RkNumber(blob);
//console.log("::", ixfe, RK,";;");
return [ixfe, RK];
}
@ -4875,7 +4873,7 @@ function parse_FilePass(blob, length/*:number*/, opts) {
function hex2RGB(h) {
var o = h.substr(h[0]==="#"?1:0,6);
return [parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16)];
return [parseInt(o.substr(0,2),16),parseInt(o.substr(2,2),16),parseInt(o.substr(4,2),16)];
}
function rgb2Hex(rgb) {
for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);
@ -5617,10 +5615,15 @@ function update_xfext(xf, xfext) {
switch(xfe[0]) { /* 2.5.108 extPropData */
case 0x04: break; /* foreground color */
case 0x05: break; /* background color */
case 0x07: case 0x08: case 0x09: case 0x0a: break;
case 0x06: break; /* gradient fill */
case 0x07: break; /* top cell border color */
case 0x08: break; /* bottom cell border color */
case 0x09: break; /* left cell border color */
case 0x0a: break; /* right cell border color */
case 0x0b: break; /* diagonal cell border color */
case 0x0d: break; /* text color */
case 0x0e: break; /* font scheme */
default: throw "bafuq" + xfe[0].toString(16);
case 0x0f: break; /* indentation level */
}
});
}
@ -5813,9 +5816,10 @@ var rc_to_a1 = (function(){
};
})();
/* TODO actually parse the formula */
/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
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;
function shift_formula_str(f/*:string*/, delta/*:Cell*/)/*:string*/ {
return f.replace(/(^|[^A-Z0-9])([$]?)([A-Z]+)([$]?)(\d+)/g, function($0, $1, $2, $3, $4, $5, off, str) {
return f.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
});
}
@ -8406,7 +8410,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
case 'inlineStr':
cref = d.match(isregex);
p.t = 's';
if(cref != null) { if((sstr = parse_si(cref[1]))) p.v = sstr.t; } else p.v = "";
if(cref != null && (sstr = parse_si(cref[1]))) p.v = sstr.t; else p.v = "";
break; // inline string
case 'b': p.v = parsexmlbool(p.v); break;
case 'd':
@ -9220,7 +9224,7 @@ function parse_wb_xml(data, opts)/*:WorkbookFile*/ {
/* 18.2.20 sheets CT_Sheets 1 */
case '<sheets>': case '</sheets>': break; // aggregate sheet
/* 18.2.19 sheet CT_Sheet + */
case '<sheet': delete y[0]; y.name = utf8read(y.name); wb.Sheets.push(y); break;
case '<sheet': delete y[0]; y.name = unescapexml(utf8read(y.name)); wb.Sheets.push(y); break;
case '</sheet>': break;
/* 18.2.15 functionGroups CT_FunctionGroups ? */
@ -9319,7 +9323,7 @@ function write_wb_xml(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:string*/ {
o[o.length] = (writextag('workbookPr', null, {date1904:safe1904(wb)}));
o[o.length] = "<sheets>";
for(var i = 0; i != wb.SheetNames.length; ++i)
o[o.length] = (writextag('sheet',null,{name:wb.SheetNames[i].substr(0,31), sheetId:""+(i+1), "r:id":"rId"+(i+1)}));
o[o.length] = (writextag('sheet',null,{name:escapexml(wb.SheetNames[i].substr(0,31)), sheetId:""+(i+1), "r:id":"rId"+(i+1)}));
o[o.length] = "</sheets>";
if(o.length>2){ o[o.length] = '</workbook>'; o[1]=o[1].replace("/>",">"); }
return o.join("");
@ -9834,7 +9838,7 @@ function parse_xlml_xml(d, opts)/*:Workbook*/ {
r = c = 0;
state.push([Rn[3], false]);
tmp = xlml_parsexmltag(Rn[0]);
sheetname = tmp.Name;
sheetname = unescapexml(tmp.Name);
cursheet = {};
mergecells = [];
}

30
xlsx.js

@ -5,7 +5,7 @@
/*exported XLSX */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.9.1';
XLSX.version = '0.9.2';
var current_codepage = 1200, current_cptable;
if(typeof module !== "undefined" && typeof require !== 'undefined') {
if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel.js');
@ -2566,7 +2566,6 @@ function parse_ct(data, opts) {
case '<Default': ctext[y.Extension] = y.ContentType; break;
case '<Override':
if(ct[ct2type[y.ContentType]] !== undefined) ct[ct2type[y.ContentType]].push(y.PartName);
else if(opts.WTF) console.error(y);
break;
}
});
@ -2893,7 +2892,7 @@ function write_ext_props(cp, opts) {
/* TODO: HeadingPairs, TitlesOfParts */
o[o.length] = (W('HeadingPairs', W('vt:vector', W('vt:variant', '<vt:lpstr>Worksheets</vt:lpstr>')+W('vt:variant', W('vt:i4', String(cp.Worksheets))), {size:2, baseType:"variant"})));
o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + s + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + escapexml(s) + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
if(o.length>2){ o[o.length] = ('</Properties>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}
@ -3455,7 +3454,6 @@ function parse_XTI(blob, length) {
function parse_RkRec(blob, length) {
var ixfe = blob.read_shift(2);
var RK = parse_RkNumber(blob);
//console.log("::", ixfe, RK,";;");
return [ixfe, RK];
}
@ -4825,7 +4823,7 @@ function parse_FilePass(blob, length, opts) {
function hex2RGB(h) {
var o = h.substr(h[0]==="#"?1:0,6);
return [parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16)];
return [parseInt(o.substr(0,2),16),parseInt(o.substr(2,2),16),parseInt(o.substr(4,2),16)];
}
function rgb2Hex(rgb) {
for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);
@ -5567,10 +5565,15 @@ function update_xfext(xf, xfext) {
switch(xfe[0]) { /* 2.5.108 extPropData */
case 0x04: break; /* foreground color */
case 0x05: break; /* background color */
case 0x07: case 0x08: case 0x09: case 0x0a: break;
case 0x06: break; /* gradient fill */
case 0x07: break; /* top cell border color */
case 0x08: break; /* bottom cell border color */
case 0x09: break; /* left cell border color */
case 0x0a: break; /* right cell border color */
case 0x0b: break; /* diagonal cell border color */
case 0x0d: break; /* text color */
case 0x0e: break; /* font scheme */
default: throw "bafuq" + xfe[0].toString(16);
case 0x0f: break; /* indentation level */
}
});
}
@ -5763,9 +5766,10 @@ var rc_to_a1 = (function(){
};
})();
/* TODO actually parse the formula */
/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
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;
function shift_formula_str(f, delta) {
return f.replace(/(^|[^A-Z0-9])([$]?)([A-Z]+)([$]?)(\d+)/g, function($0, $1, $2, $3, $4, $5, off, str) {
return f.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
});
}
@ -8355,7 +8359,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
case 'inlineStr':
cref = d.match(isregex);
p.t = 's';
if(cref != null) { if((sstr = parse_si(cref[1]))) p.v = sstr.t; } else p.v = "";
if(cref != null && (sstr = parse_si(cref[1]))) p.v = sstr.t; else p.v = "";
break; // inline string
case 'b': p.v = parsexmlbool(p.v); break;
case 'd':
@ -9169,7 +9173,7 @@ function parse_wb_xml(data, opts) {
/* 18.2.20 sheets CT_Sheets 1 */
case '<sheets>': case '</sheets>': break; // aggregate sheet
/* 18.2.19 sheet CT_Sheet + */
case '<sheet': delete y[0]; y.name = utf8read(y.name); wb.Sheets.push(y); break;
case '<sheet': delete y[0]; y.name = unescapexml(utf8read(y.name)); wb.Sheets.push(y); break;
case '</sheet>': break;
/* 18.2.15 functionGroups CT_FunctionGroups ? */
@ -9268,7 +9272,7 @@ function write_wb_xml(wb, opts) {
o[o.length] = (writextag('workbookPr', null, {date1904:safe1904(wb)}));
o[o.length] = "<sheets>";
for(var i = 0; i != wb.SheetNames.length; ++i)
o[o.length] = (writextag('sheet',null,{name:wb.SheetNames[i].substr(0,31), sheetId:""+(i+1), "r:id":"rId"+(i+1)}));
o[o.length] = (writextag('sheet',null,{name:escapexml(wb.SheetNames[i].substr(0,31)), sheetId:""+(i+1), "r:id":"rId"+(i+1)}));
o[o.length] = "</sheets>";
if(o.length>2){ o[o.length] = '</workbook>'; o[1]=o[1].replace("/>",">"); }
return o.join("");
@ -9781,7 +9785,7 @@ function parse_xlml_xml(d, opts) {
r = c = 0;
state.push([Rn[3], false]);
tmp = xlml_parsexmltag(Rn[0]);
sheetname = tmp.Name;
sheetname = unescapexml(tmp.Name);
cursheet = {};
mergecells = [];
}