version bump 0.10.0: cleanup
- updated SSF to 0.9.2 - XLSB style records and number format writing - CSV avoid parseFloat (fixes #646 h/t @jabbermarky) - CSV recognize mac line ending (fixes #648 h/t @charlesread) - BIFF2 format table refactored to align with SSF - BIFF5 image data exposure - SSF custom format auto table update (fixes #267 h/t @Fangmingdu) - eslint more checks - browser test timeout extended to 10 seconds
This commit is contained in:
parent
810c447bf9
commit
a8736580a5
@ -5,10 +5,12 @@
|
||||
"ecmaVersion": 3,
|
||||
},
|
||||
"plugins": [ "html", "json" ],
|
||||
"!extends": "eslint:recommended",
|
||||
"rules": {
|
||||
"no-use-before-define": [ 1, {
|
||||
"functions":false, "classes":true, "variables":false
|
||||
}],
|
||||
"no-console": 0,
|
||||
"no-bitwise": 0,
|
||||
"curly": 0,
|
||||
"comma-style": [ 2, "last" ],
|
||||
|
110
README.md
110
README.md
@ -6,7 +6,8 @@ Emphasis on parsing and writing robustness, cross-format feature compatibility
|
||||
with a unified JS representation, and ES3/ES5 browser compatibility back to IE6.
|
||||
|
||||
This is the community version. We also offer a pro version with performance
|
||||
enhancements and additional features by request.
|
||||
enhancements, additional features by request, and dedicated support.
|
||||
|
||||
|
||||
[**Pro Version**](http://sheetjs.com/pro)
|
||||
|
||||
@ -18,17 +19,33 @@ enhancements and additional features by request.
|
||||
|
||||
[**Source Code**](http://git.io/xlsx)
|
||||
|
||||
[**Issues and Bug Reports**](https://github.com/sheetjs/js-xlsx/issues)
|
||||
|
||||
[**Other General Support Issues**](https://discourse.sheetjs.com)
|
||||
|
||||
[**File format support for known spreadsheet data formats:**](#file-formats)
|
||||
|
||||
![circo graph of format support](formats.png)
|
||||
|
||||
<details>
|
||||
<summary>Graph Legend</summary>
|
||||
<summary><b>Graph of supported formats</b> (click to show)</summary>
|
||||
|
||||
![circo graph of format support](formats.png)
|
||||
|
||||
![graph legend](legend.png)
|
||||
|
||||
</details>
|
||||
|
||||
[**Browser Test**](http://oss.sheetjs.com/js-xlsx/tests/)
|
||||
|
||||
[![Build Status](https://saucelabs.com/browser-matrix/sheetjs.svg)](https://saucelabs.com/u/sheetjs)
|
||||
|
||||
[![Build Status](https://travis-ci.org/SheetJS/js-xlsx.svg?branch=master)](https://travis-ci.org/SheetJS/js-xlsx)
|
||||
[![Build Status](https://semaphoreci.com/api/v1/sheetjs/js-xlsx/branches/master/shields_badge.svg)](https://semaphoreci.com/sheetjs/js-xlsx)
|
||||
[![Coverage Status](http://img.shields.io/coveralls/SheetJS/js-xlsx/master.svg)](https://coveralls.io/r/SheetJS/js-xlsx?branch=master)
|
||||
[![Dependencies Status](https://david-dm.org/sheetjs/js-xlsx/status.svg)](https://david-dm.org/sheetjs/js-xlsx)
|
||||
[![NPM Downloads](https://img.shields.io/npm/dt/xlsx.svg)](https://npmjs.org/package/xlsx)
|
||||
[![ghit.me](https://ghit.me/badge.svg?repo=sheetjs/js-xlsx)](https://ghit.me/repo/sheetjs/js-xlsx)
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
||||
|
||||
## Table of Contents
|
||||
|
||||
<details>
|
||||
@ -40,6 +57,7 @@ enhancements and additional features by request.
|
||||
* [JS Ecosystem Demos](#js-ecosystem-demos)
|
||||
* [Optional Modules](#optional-modules)
|
||||
* [ECMAScript 5 Compatibility](#ecmascript-5-compatibility)
|
||||
- [Philosophy](#philosophy)
|
||||
- [Parsing Workbooks](#parsing-workbooks)
|
||||
* [Complete Examples](#complete-examples)
|
||||
* [Note on Streaming Read](#note-on-streaming-read)
|
||||
@ -114,7 +132,6 @@ enhancements and additional features by request.
|
||||
* [Windows](#windows)
|
||||
- [License](#license)
|
||||
- [References](#references)
|
||||
- [Badges](#badges)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
@ -122,18 +139,18 @@ enhancements and additional features by request.
|
||||
|
||||
## Installation
|
||||
|
||||
In the browser, just add a script tag:
|
||||
|
||||
```html
|
||||
<script lang="javascript" src="dist/xlsx.full.min.js"></script>
|
||||
```
|
||||
|
||||
With [npm](https://www.npmjs.org/package/xlsx):
|
||||
|
||||
```bash
|
||||
$ npm install xlsx
|
||||
```
|
||||
|
||||
In the browser:
|
||||
|
||||
```html
|
||||
<script lang="javascript" src="dist/xlsx.core.min.js"></script>
|
||||
```
|
||||
|
||||
With [bower](http://bower.io/search/?q=js-xlsx):
|
||||
|
||||
```bash
|
||||
@ -194,6 +211,41 @@ To use the shim, add the shim before the script tag that loads xlsx.js:
|
||||
<script type="text/javascript" src="/path/to/shim.js"></script>
|
||||
```
|
||||
|
||||
## Philosophy
|
||||
|
||||
<details>
|
||||
<summary><b>Philosophy</b> (click to show)</summary>
|
||||
|
||||
Prior to SheetJS, APIs for processing spreadsheet files were format-specific.
|
||||
Third-party libraries either supported one format, or they involved a separate
|
||||
set of classes for each supported file type. Even though XLSB was introduced in
|
||||
Excel 2007, nothing outside of SheetJS or Excel supported the format.
|
||||
|
||||
To promote a format-agnostic view, js-xlsx starts from a pure-JS representation
|
||||
that we call the ["Common Spreadsheet Format"](#common-spreadsheet-format).
|
||||
Emphasizing a uniform object representation enables radical features like format
|
||||
conversion (e.g. reading an XLSX template and saving as XLS) and circumvents the
|
||||
"class trap". By abstracting the complexities of the various formats, tools
|
||||
need not worry about the specific file type!
|
||||
|
||||
A simple object representation combined with careful coding practices enables
|
||||
use cases in older browsers and in alternative environments like ExtendScript
|
||||
and Web Workers. It is always tempting to use the latest and greatest features,
|
||||
but they tend to require the latest versions of browsers, limiting usability.
|
||||
|
||||
Utility functions capture common use cases like generating JS objects or HTML.
|
||||
Most simple operations should only require a few lines of code. More complex
|
||||
operations generally should be straightforward to implement.
|
||||
|
||||
Excel pushes the XLSX format as default starting in Excel 2007. However, there
|
||||
are other formats with more appealing properties. For example, the XLSB format
|
||||
is spiritually similar to XLSX but files often tend up taking less than half the
|
||||
space and open much faster! Even though an XLSX writer is available, other
|
||||
format writers are available so users can take advantage of the unique
|
||||
characteristics of each format.
|
||||
|
||||
</details>
|
||||
|
||||
## Parsing Workbooks
|
||||
|
||||
For parsing, the first step is to read the file. This involves acquiring the
|
||||
@ -505,7 +557,6 @@ Utilities are available in the `XLSX.utils` object:
|
||||
**Exporting:**
|
||||
|
||||
- `sheet_to_json` converts a worksheet object to an array of JSON objects.
|
||||
`sheet_to_row_object_array` is an alias that will be removed in the future.
|
||||
- `sheet_to_csv` generates delimiter-separated-values output.
|
||||
- `sheet_to_formulae` generates a list of the formulae (with value fallbacks).
|
||||
|
||||
@ -1008,17 +1059,14 @@ at index 164. The following example creates a custom format from scratch:
|
||||
|
||||
```js
|
||||
var tbl = {};
|
||||
XLSX.SSF.init_table(tbl); // <-- load builtin formats
|
||||
tbl[164] = "\"T\"\ #0.00";
|
||||
var wb = {
|
||||
SSF: tbl,
|
||||
SheetNames: ["Sheet1"],
|
||||
Sheets: {
|
||||
Sheet1: {
|
||||
"!ref":"A1:C1",
|
||||
A1: { t:"n", v:10000 }, // <-- General format
|
||||
B1: { t:"n", v:10000, z: tbl[4] }, // <-- Builtin format
|
||||
C1: { t:"n", v:10000, z: tbl[164] } // <-- Custom format
|
||||
A1: { t:"n", v:10000 }, // <-- General format
|
||||
B1: { t:"n", v:10000, z: "0%" }, // <-- Builtin format
|
||||
C1: { t:"n", v:10000, z: "\"T\"\ #0.00" } // <-- Custom format
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1439,8 +1487,8 @@ the output will be encoded in codepage `1200` and the BOM will be prepended.
|
||||
|
||||
### JSON
|
||||
|
||||
`XLSX.utils.sheet_to_json` and the alias `XLSX.utils.sheet_to_row_object_array`
|
||||
generate different types of JS objects. The function takes an options argument:
|
||||
`XLSX.utils.sheet_to_json` generates different types of JS objects. The function
|
||||
takes an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :------: | :-------------------------------------------------- |
|
||||
@ -1834,6 +1882,9 @@ $ open -a Chromium.app http://localhost:8000/stress.html
|
||||
|
||||
### Tested Environments
|
||||
|
||||
<details>
|
||||
<summary>(click to show)</summary>
|
||||
|
||||
- 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+
|
||||
@ -1847,6 +1898,8 @@ Tests utilize the mocha testing framework. Travis-CI and Sauce Labs links:
|
||||
- <https://travis-ci.org/SheetJS/SheetJS.github.io> for XLS\* modules
|
||||
- <https://saucelabs.com/u/sheetjs> for XLS\* modules using Sauce Labs
|
||||
|
||||
</details>
|
||||
|
||||
### Test Files
|
||||
|
||||
Test files are housed in [another repo](https://github.com/SheetJS/test_files).
|
||||
@ -1980,20 +2033,3 @@ granted by the Apache 2.0 License are reserved by the Original Author.
|
||||
- Worksheet File Format (From Lotus) December 1984
|
||||
|
||||
|
||||
## Badges
|
||||
|
||||
[![Build Status](https://saucelabs.com/browser-matrix/sheetjs.svg)](https://saucelabs.com/u/sheetjs)
|
||||
|
||||
[![Build Status](https://travis-ci.org/SheetJS/js-xlsx.svg?branch=master)](https://travis-ci.org/SheetJS/js-xlsx)
|
||||
|
||||
[![Build Status](https://semaphoreci.com/api/v1/sheetjs/js-xlsx/branches/master/shields_badge.svg)](https://semaphoreci.com/sheetjs/js-xlsx)
|
||||
|
||||
[![Coverage Status](http://img.shields.io/coveralls/SheetJS/js-xlsx/master.svg)](https://coveralls.io/r/SheetJS/js-xlsx?branch=master)
|
||||
|
||||
[![NPM Downloads](https://img.shields.io/npm/dt/xlsx.svg)](https://npmjs.org/package/xlsx)
|
||||
|
||||
[![Dependencies Status](https://david-dm.org/sheetjs/js-xlsx/status.svg)](https://david-dm.org/sheetjs/js-xlsx)
|
||||
|
||||
[![ghit.me](https://ghit.me/badge.svg?repo=sheetjs/js-xlsx)](https://ghit.me/repo/sheetjs/js-xlsx)
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
/* eslint-env node */
|
||||
var n = "xlsx";
|
||||
/* vim: set ts=2 ft=javascript: */
|
||||
var X = require('../');
|
||||
@ -176,9 +177,9 @@ var oo = "";
|
||||
var strm = false;
|
||||
if(!program.quiet) console.error(target_sheet);
|
||||
if(program.formulae) oo = X.utils.get_formulae(ws).join("\n");
|
||||
else if(program.json) oo = JSON.stringify(X.utils.sheet_to_row_object_array(ws));
|
||||
else if(program.rawJs) oo = JSON.stringify(X.utils.sheet_to_row_object_array(ws,{raw:true}));
|
||||
else if(program.arrays) oo = JSON.stringify(X.utils.sheet_to_row_object_array(ws,{raw:true, header:1}));
|
||||
else if(program.json) oo = JSON.stringify(X.utils.sheet_to_json(ws));
|
||||
else if(program.rawJs) oo = JSON.stringify(X.utils.sheet_to_json(ws,{raw:true}));
|
||||
else if(program.arrays) oo = JSON.stringify(X.utils.sheet_to_json(ws,{raw:true, header:1}));
|
||||
else {
|
||||
strm = true;
|
||||
var stream = X.stream.to_csv(ws, {FS:program.fieldSep, RS:program.rowSep});
|
||||
|
@ -3,5 +3,6 @@
|
||||
/*jshint -W041 */
|
||||
/*jshint funcscope:true, eqnull:true */
|
||||
/*exported XLSX */
|
||||
/*global exports, module, require:false, process:false, Buffer:false */
|
||||
var XLSX = {};
|
||||
(function make_xlsx(XLSX){
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.9.13';
|
||||
XLSX.version = '0.10.0';
|
||||
|
@ -1,8 +1,8 @@
|
||||
var current_codepage = 1200, current_cptable;
|
||||
var current_codepage = 1200;
|
||||
/*:: declare var cptable:any; */
|
||||
/*global cptable:true */
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
|
||||
if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel.js');
|
||||
current_cptable = cptable[current_codepage];
|
||||
}
|
||||
function reset_cp() { set_cp(1200); }
|
||||
var set_cp = function(cp) { current_codepage = cp; };
|
||||
@ -18,7 +18,7 @@ var debom = function(data/*:string*/)/*:string*/ {
|
||||
|
||||
var _getchar = function _gc1(x) { return String.fromCharCode(x); };
|
||||
if(typeof cptable !== 'undefined') {
|
||||
set_cp = function(cp) { current_codepage = cp; current_cptable = cptable[cp]; };
|
||||
set_cp = function(cp) { current_codepage = cp; };
|
||||
debom = function(data) {
|
||||
if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.substr(2))); }
|
||||
return data;
|
||||
|
@ -1,7 +1,7 @@
|
||||
var Base64 = (function make_b64(){
|
||||
var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
return {
|
||||
encode: function(input/*:string*/, utf8)/*:string*/ {
|
||||
encode: function(input/*:string*/)/*:string*/ {
|
||||
var o = "";
|
||||
var c1, c2, c3, e1, e2, e3, e4;
|
||||
for(var i = 0; i < input.length; ) {
|
||||
@ -18,7 +18,7 @@ var Base64 = (function make_b64(){
|
||||
}
|
||||
return o;
|
||||
},
|
||||
decode: function b64_decode(input/*:string*/, utf8)/*:string*/ {
|
||||
decode: function b64_decode(input/*:string*/)/*:string*/ {
|
||||
var o = "";
|
||||
var c1, c2, c3;
|
||||
var e1, e2, e3, e4;
|
||||
|
@ -2,7 +2,7 @@
|
||||
/*jshint -W041 */
|
||||
var SSF = {};
|
||||
var make_ssf = function make_ssf(SSF){
|
||||
SSF.version = '0.9.1';
|
||||
SSF.version = '0.9.2';
|
||||
function _strrev(x/*:string*/)/*:string*/ { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; }
|
||||
function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; }
|
||||
function pad0(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
|
||||
@ -270,12 +270,14 @@ function write_num_exp(fmt/*:string*/, val/*:number*/)/*:string*/{
|
||||
var o/*:string*/;
|
||||
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
|
||||
if(fmt.match(/^#+0.0E\+0$/)) {
|
||||
if(val == 0) return "0.0E+0";
|
||||
else if(val < 0) return "-" + write_num_exp(fmt, -val);
|
||||
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
|
||||
var ee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E)%period;
|
||||
var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
|
||||
if(ee < 0) ee += period;
|
||||
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);
|
||||
var fakee = Math.floor(Math.log(val)*Math.LOG10E);
|
||||
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.") {
|
||||
@ -353,7 +355,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
|
||||
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(\.?)$/))) return sign + commaify(pad0r(aval,0));
|
||||
if((r = fmt.match(/^#{1,3},##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) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length);
|
||||
}
|
||||
@ -401,7 +403,12 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
|
||||
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);
|
||||
}
|
||||
switch(fmt) {
|
||||
case "###,##0.00": return write_num_flt(type, "#,##0.00", val);
|
||||
case "###,###":
|
||||
case "##,###":
|
||||
case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : "";
|
||||
case "###,###.00": return write_num_flt(type, "###,##0.00",val).replace(/^0\./,".");
|
||||
case "#,###.00": return write_num_flt(type, "#,##0.00",val).replace(/^0\./,".");
|
||||
default:
|
||||
}
|
||||
throw new Error("unsupported format |" + fmt + "|");
|
||||
@ -419,12 +426,14 @@ function write_num_exp2(fmt/*:string*/, val/*:number*/)/*:string*/{
|
||||
var o/*:string*/;
|
||||
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
|
||||
if(fmt.match(/^#+0.0E\+0$/)) {
|
||||
if(val == 0) return "0.0E+0";
|
||||
else if(val < 0) return "-" + write_num_exp2(fmt, -val);
|
||||
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
|
||||
var ee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E)%period;
|
||||
var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
|
||||
if(ee < 0) ee += period;
|
||||
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);
|
||||
var fakee = Math.floor(Math.log(val)*Math.LOG10E);
|
||||
if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
|
||||
else o += "E+" + (fakee - ee);
|
||||
o = o.replace(/\+-/,"-");
|
||||
@ -446,7 +455,7 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
|
||||
if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val);
|
||||
if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
|
||||
var o;
|
||||
var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
|
||||
var r/*:?Array<string>*/, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
|
||||
if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length);
|
||||
if(fmt.match(/^[#?]+$/)) {
|
||||
o = (""+val); if(val === 0) o = "";
|
||||
@ -466,7 +475,7 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
|
||||
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(\.?)$/))) return sign + commaify((""+aval));
|
||||
if((r = fmt.match(/^#{1,3},##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);
|
||||
}
|
||||
@ -482,12 +491,12 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
|
||||
}
|
||||
var oa = "";
|
||||
if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
|
||||
ri = Math.min(r[4].length,7);
|
||||
ri = Math.min(/*::String(*/r[4]/*::)*/.length,7);
|
||||
ff = frac(aval, Math.pow(10,ri)-1, false);
|
||||
o = "" + sign;
|
||||
oa = write_num("n", r[1], ff[1]);
|
||||
oa = write_num("n", /*::String(*/r[1]/*::)*/, ff[1]);
|
||||
if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
|
||||
o += oa + r[2] + "/" + r[3];
|
||||
o += oa + /*::String(*/r[2]/*::)*/ + "/" + /*::String(*/r[3]/*::)*/;
|
||||
oa = rpad_(ff[2],ri);
|
||||
if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
|
||||
o += oa;
|
||||
@ -513,8 +522,12 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string
|
||||
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) {
|
||||
case "###,###":
|
||||
case "##,###":
|
||||
case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
|
||||
default:
|
||||
if(fmt.slice(-3) == ".00") return write_num_int(type, fmt.slice(0,-3), val) + ".00";
|
||||
if(fmt.slice(-2) == ".0") return write_num_int(type, fmt.slice(0,-2), val) + ".0";
|
||||
}
|
||||
throw new Error("unsupported format |" + fmt + "|");
|
||||
}
|
||||
@ -610,7 +623,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
if(v < 0) return "";
|
||||
if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
|
||||
o = c; while(++i<fmt.length && fmt.charAt(i).toLowerCase() === c) o+=c;
|
||||
if(c === 'm' && lst.toLowerCase() === 'h') c = 'M'; /* m = minute */
|
||||
if(c === 'm' && lst.toLowerCase() === 'h') c = 'M';
|
||||
if(c === 'h') c = hr;
|
||||
out[out.length] = {t:c, v:o}; lst = c; break;
|
||||
case 'A':
|
||||
@ -628,6 +641,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
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()};
|
||||
lst = o.charAt(1);
|
||||
} else if(o.indexOf("$") > -1) {
|
||||
o = (o.match(/\$([^-\[\]]*)/)||[])[1]||"$";
|
||||
if(!fmt_is_date(fmt)) out[out.length] = {t:'t',v:o};
|
||||
@ -641,7 +655,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
}
|
||||
/* falls through */
|
||||
case '0': case '#':
|
||||
o = c; while(++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1) o += c;
|
||||
o = c; while(++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && i < fmt.length - 2 && "0#".indexOf(fmt.charAt(i+2))>-1) o += c;
|
||||
out[out.length] = {t:'n', v:o}; break;
|
||||
case '?':
|
||||
o = c; while(fmt.charAt(++i) === c) o+=c;
|
||||
@ -705,7 +719,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) {
|
||||
(c=out[jj].t) === "?" || c === "D" ||
|
||||
(c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/') ||
|
||||
out[i].t === '(' && (c === ' ' || c === 'n' || c === ')') ||
|
||||
c === 't' && (out[jj].v === '/' || '$€'.indexOf(out[jj].v) > -1 || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?')
|
||||
c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?')
|
||||
)) {
|
||||
out[i].v += out[jj].v;
|
||||
out[jj] = {v:"", t:";"}; ++jj;
|
||||
@ -819,7 +833,6 @@ function choose_fmt(f/*:string*/, v) {
|
||||
}
|
||||
function format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
|
||||
if(o == null) o = {};
|
||||
//fixopts(o != null ? o : (o=[]));
|
||||
var sfmt = "";
|
||||
switch(typeof fmt) {
|
||||
case "string":
|
||||
|
@ -53,6 +53,7 @@ function getzipstr(zip, file/*:string*/, safe/*:?boolean*/)/*:?string*/ {
|
||||
|
||||
var _fs, jszip;
|
||||
/*:: declare var JSZip:any; */
|
||||
/*global JSZip:true */
|
||||
if(typeof JSZip !== 'undefined') jszip = JSZip;
|
||||
if (typeof exports !== 'undefined') {
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
|
@ -37,7 +37,7 @@ var encodings = {
|
||||
'&': '&'
|
||||
};
|
||||
var rencoding = evert(encodings);
|
||||
var rencstr = "&<>'\"".split("");
|
||||
//var rencstr = "&<>'\"".split("");
|
||||
|
||||
// TODO: CP remap (need to read file version to determine OS)
|
||||
var unescapexml/*:StringConv*/ = (function() {
|
||||
|
@ -33,5 +33,6 @@ var make_offcrypto = function(O, _crypto) {
|
||||
};
|
||||
};
|
||||
/*:: declare var crypto:any; */
|
||||
/*global crypto:true */
|
||||
make_offcrypto(OFFCRYPTO, typeof crypto !== "undefined" ? crypto : undefined);
|
||||
|
||||
|
@ -1,8 +1,31 @@
|
||||
function write_UInt32LE(x/*:number*/, o) {
|
||||
if(!o) o = new_buf(4);
|
||||
o.write_shift(4, x);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.168 */
|
||||
function parse_XLWideString(data)/*:string*/ {
|
||||
var cchCharacters = data.read_shift(4);
|
||||
return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, 'dbcs');
|
||||
}
|
||||
function write_XLWideString(data/*:string*/, o) {
|
||||
var _null = false; if(o == null) { _null = true; o = new_buf(4+2*data.length); }
|
||||
o.write_shift(4, data.length);
|
||||
if(data.length > 0) o.write_shift(0, data, 'dbcs');
|
||||
return _null ? o.slice(0, o.l) : o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.143 */
|
||||
function parse_StrRun(data, length/*:?number*/) {
|
||||
return { ich: data.read_shift(2), ifnt: data.read_shift(2) };
|
||||
}
|
||||
function write_StrRun(run, o) {
|
||||
if(!o) o = new_buf(4);
|
||||
o.write_shift(2, run.ich || 0);
|
||||
o.write_shift(2, run.ifnt || 0);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.1.7.121 */
|
||||
function parse_RichStr(data, length/*:number*/)/*:XLString*/ {
|
||||
@ -31,6 +54,17 @@ function write_RichStr(str/*:XLString*/, o/*:?Block*/)/*:Block*/ {
|
||||
write_XLWideString(str.t, o);
|
||||
return _null ? o.slice(0, o.l) : o;
|
||||
}
|
||||
/* [MS-XLSB] 2.4.325 BrtCommentText (RichStr w/1 run) */
|
||||
var parse_BrtCommentText = parse_RichStr;
|
||||
function write_BrtCommentText(str/*:XLString*/, o/*:?Block*/)/*:Block*/ {
|
||||
/* TODO: formatted string */
|
||||
var _null = false; if(o == null) { _null = true; o = new_buf(23+4*str.t.length); }
|
||||
o.write_shift(1,1);
|
||||
write_XLWideString(str.t, o);
|
||||
o.write_shift(4,1);
|
||||
write_StrRun({ich:0,ifnt:0}, o);
|
||||
return _null ? o.slice(0, o.l) : o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.9 */
|
||||
function parse_XLSBCell(data)/*:any*/ {
|
||||
@ -65,18 +99,6 @@ function write_XLNullableWideString(data/*:string*/, o) {
|
||||
return _null ? o.slice(0, o.l) : o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.168 */
|
||||
function parse_XLWideString(data)/*:string*/ {
|
||||
var cchCharacters = data.read_shift(4);
|
||||
return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, 'dbcs');
|
||||
}
|
||||
function write_XLWideString(data/*:string*/, o) {
|
||||
var _null = false; if(o == null) { _null = true; o = new_buf(4+2*data.length); }
|
||||
o.write_shift(4, data.length);
|
||||
if(data.length > 0) o.write_shift(0, data, 'dbcs');
|
||||
return _null ? o.slice(0, o.l) : o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.165 */
|
||||
var parse_XLNameWideString = parse_XLWideString;
|
||||
var write_XLNameWideString = write_XLWideString;
|
||||
@ -153,23 +175,75 @@ var RBErr = evert_num(BErr);
|
||||
function parse_BrtColor(data, length/*:number*/) {
|
||||
var out = {};
|
||||
var d = data.read_shift(1);
|
||||
out.fValidRGB = d & 1;
|
||||
out.xColorType = d >>> 1;
|
||||
out.index = data.read_shift(1);
|
||||
out.nTintAndShade = data.read_shift(2, 'i');
|
||||
out.bRed = data.read_shift(1);
|
||||
out.bGreen = data.read_shift(1);
|
||||
out.bBlue = data.read_shift(1);
|
||||
out.bAlpha = data.read_shift(1);
|
||||
|
||||
var fValidRGB = d & 1;
|
||||
var xColorType = d >>> 1;
|
||||
|
||||
var index = data.read_shift(1);
|
||||
var nTS = data.read_shift(2, 'i');
|
||||
var bR = data.read_shift(1);
|
||||
var bG = data.read_shift(1);
|
||||
var bB = data.read_shift(1);
|
||||
var bAlpha = data.read_shift(1);
|
||||
|
||||
switch(xColorType) {
|
||||
case 0: out.auto = 1; break;
|
||||
case 1:
|
||||
out.index = index;
|
||||
var icv = XLSIcv[index];
|
||||
/* automatic pseudo index 81 */
|
||||
if(icv) out.rgb = icv[0].toString(16) + icv[1].toString(16) + icv[2].toString(16);
|
||||
break;
|
||||
case 2:
|
||||
/* if(!fValidRGB) throw new Error("invalid"); */
|
||||
out.rgb = bR.toString(16) + bG.toString(16) + bB.toString(16);
|
||||
break;
|
||||
case 3: out.theme = index; break;
|
||||
}
|
||||
if(nTS != 0) out.tint = nTS > 0 ? nTS / 32767 : nTS / 32768;
|
||||
|
||||
return out;
|
||||
}
|
||||
function write_BrtColor(color, o) {
|
||||
if(!o) o = new_buf(8);
|
||||
if(!color||color.auto) { o.write_shift(4, 0); o.write_shift(4, 0); return o; }
|
||||
if(color.index) {
|
||||
o.write_shift(1, 0x02);
|
||||
o.write_shift(1, color.index);
|
||||
} else if(color.theme) {
|
||||
o.write_shift(1, 0x06);
|
||||
o.write_shift(1, color.theme);
|
||||
} else {
|
||||
o.write_shift(1, 0x05);
|
||||
o.write_shift(1, 0);
|
||||
}
|
||||
var nTS = color.tint || 0;
|
||||
if(nTS > 0) nTS *= 32767;
|
||||
else if(nTS < 0) nTS *= 32768;
|
||||
o.write_shift(2, nTS);
|
||||
if(!color.rgb) {
|
||||
o.write_shift(2, 0);
|
||||
o.write_shift(1, 0);
|
||||
o.write_shift(1, 0);
|
||||
} else {
|
||||
var rgb = (color.rgb || 'FFFFFF');
|
||||
o.write_shift(1, parseInt(rgb.substr(0,2),16));
|
||||
o.write_shift(1, parseInt(rgb.substr(2,2),16));
|
||||
o.write_shift(1, parseInt(rgb.substr(4,2),16));
|
||||
o.write_shift(1, 0xFF);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.52 */
|
||||
function parse_FontFlags(data, length/*:number*/) {
|
||||
function parse_FontFlags(data, length/*:number*/, opts) {
|
||||
var d = data.read_shift(1);
|
||||
data.l++;
|
||||
var out = {
|
||||
fItalic: d & 0x2,
|
||||
fStrikeout: d & 0x8,
|
||||
/* fBold: d & 0x01 */
|
||||
fItalic: d & 0x02,
|
||||
/* fUnderline: d & 0x04 */
|
||||
fStrikeout: d & 0x08,
|
||||
fOutline: d & 0x10,
|
||||
fShadow: d & 0x20,
|
||||
fCondense: d & 0x40,
|
||||
@ -177,3 +251,17 @@ function parse_FontFlags(data, length/*:number*/) {
|
||||
};
|
||||
return out;
|
||||
}
|
||||
function write_FontFlags(font, o) {
|
||||
if(!o) o = new_buf(2);
|
||||
var grbit =
|
||||
(font.italic ? 0x02 : 0) |
|
||||
(font.strike ? 0x08 : 0) |
|
||||
(font.outline ? 0x10 : 0) |
|
||||
(font.shadow ? 0x20 : 0) |
|
||||
(font.condense ? 0x40 : 0) |
|
||||
(font.extend ? 0x80 : 0);
|
||||
o.write_shift(1, grbit);
|
||||
o.write_shift(1, 0);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
@ -1,40 +1,40 @@
|
||||
/* [MS-OLEPS] 2.2 PropertyType */
|
||||
{
|
||||
var VT_EMPTY = 0x0000;
|
||||
var VT_NULL = 0x0001;
|
||||
//var VT_EMPTY = 0x0000;
|
||||
//var VT_NULL = 0x0001;
|
||||
var VT_I2 = 0x0002;
|
||||
var VT_I4 = 0x0003;
|
||||
var VT_R4 = 0x0004;
|
||||
var VT_R8 = 0x0005;
|
||||
var VT_CY = 0x0006;
|
||||
var VT_DATE = 0x0007;
|
||||
var VT_BSTR = 0x0008;
|
||||
var VT_ERROR = 0x000A;
|
||||
//var VT_R4 = 0x0004;
|
||||
//var VT_R8 = 0x0005;
|
||||
//var VT_CY = 0x0006;
|
||||
//var VT_DATE = 0x0007;
|
||||
//var VT_BSTR = 0x0008;
|
||||
//var VT_ERROR = 0x000A;
|
||||
var VT_BOOL = 0x000B;
|
||||
var VT_VARIANT = 0x000C;
|
||||
var VT_DECIMAL = 0x000E;
|
||||
var VT_I1 = 0x0010;
|
||||
var VT_UI1 = 0x0011;
|
||||
var VT_UI2 = 0x0012;
|
||||
//var VT_DECIMAL = 0x000E;
|
||||
//var VT_I1 = 0x0010;
|
||||
//var VT_UI1 = 0x0011;
|
||||
//var VT_UI2 = 0x0012;
|
||||
var VT_UI4 = 0x0013;
|
||||
var VT_I8 = 0x0014;
|
||||
//var VT_I8 = 0x0014;
|
||||
var VT_UI8 = 0x0015;
|
||||
var VT_INT = 0x0016;
|
||||
var VT_UINT = 0x0017;
|
||||
//var VT_INT = 0x0016;
|
||||
//var VT_UINT = 0x0017;
|
||||
var VT_LPSTR = 0x001E;
|
||||
var VT_LPWSTR = 0x001F;
|
||||
//var VT_LPWSTR = 0x001F;
|
||||
var VT_FILETIME = 0x0040;
|
||||
var VT_BLOB = 0x0041;
|
||||
var VT_STREAM = 0x0042;
|
||||
var VT_STORAGE = 0x0043;
|
||||
var VT_STREAMED_Object = 0x0044;
|
||||
var VT_STORED_Object = 0x0045;
|
||||
var VT_BLOB_Object = 0x0046;
|
||||
//var VT_BLOB = 0x0041;
|
||||
//var VT_STREAM = 0x0042;
|
||||
//var VT_STORAGE = 0x0043;
|
||||
//var VT_STREAMED_Object = 0x0044;
|
||||
//var VT_STORED_Object = 0x0045;
|
||||
//var VT_BLOB_Object = 0x0046;
|
||||
var VT_CF = 0x0047;
|
||||
var VT_CLSID = 0x0048;
|
||||
var VT_VERSIONED_STREAM = 0x0049;
|
||||
//var VT_CLSID = 0x0048;
|
||||
//var VT_VERSIONED_STREAM = 0x0049;
|
||||
var VT_VECTOR = 0x1000;
|
||||
var VT_ARRAY = 0x2000;
|
||||
//var VT_ARRAY = 0x2000;
|
||||
|
||||
var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
|
||||
var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString
|
||||
@ -186,6 +186,7 @@ var XLSFillPattern = [
|
||||
function rgbify(arr) { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); }
|
||||
|
||||
/* [MS-XLS] 2.5.161 */
|
||||
/* [MS-XLSB] 2.5.75 */
|
||||
var XLSIcv = rgbify([
|
||||
/* Color Constants */
|
||||
0x000000,
|
||||
@ -197,7 +198,7 @@ var XLSIcv = rgbify([
|
||||
0xFF00FF,
|
||||
0x00FFFF,
|
||||
|
||||
/* Defaults */
|
||||
/* Overridable Defaults */
|
||||
0x000000,
|
||||
0xFFFFFF,
|
||||
0xFF0000,
|
||||
@ -258,8 +259,24 @@ var XLSIcv = rgbify([
|
||||
0x333399,
|
||||
0x333333,
|
||||
|
||||
/* Sheet */
|
||||
0xFFFFFF,
|
||||
0x000000
|
||||
/* Other entries to appease BIFF8/12 */
|
||||
0xFFFFFF, /* 0x40 icvForeground ?? */
|
||||
0x000000, /* 0x41 icvBackground ?? */
|
||||
0x000000, /* 0x42 icvFrame ?? */
|
||||
0x000000, /* 0x43 icv3D ?? */
|
||||
0x000000, /* 0x44 icv3DText ?? */
|
||||
0x000000, /* 0x45 icv3DHilite ?? */
|
||||
0x000000, /* 0x46 icv3DShadow ?? */
|
||||
0x000000, /* 0x47 icvHilite ?? */
|
||||
0x000000, /* 0x48 icvCtlText ?? */
|
||||
0x000000, /* 0x49 icvCtlScrl ?? */
|
||||
0x000000, /* 0x4A icvCtlInv ?? */
|
||||
0x000000, /* 0x4B icvCtlBody ?? */
|
||||
0x000000, /* 0x4C icvCtlFrame ?? */
|
||||
0x000000, /* 0x4D icvCtlFore ?? */
|
||||
0x000000, /* 0x4E icvCtlBack ?? */
|
||||
0x000000, /* 0x4F icvCtlNeutral */
|
||||
0x000000, /* 0x50 icvInfoBk ?? */
|
||||
0x000000 /* 0x51 icvInfoText ?? */
|
||||
]);
|
||||
|
||||
|
@ -55,7 +55,7 @@ function write_rels(rels)/*:string*/ {
|
||||
function add_rels(rels, rId, f, type, relobj)/*:number*/ {
|
||||
if(!relobj) relobj = {};
|
||||
if(!rels['!id']) rels['!id'] = {};
|
||||
if(rId < 0) for(rId = 1; rels['!id']['rId' + rId]; ++rId){}
|
||||
if(rId < 0) for(rId = 1; rels['!id']['rId' + rId]; ++rId){/* empty */}
|
||||
relobj.Id = 'rId' + rId;
|
||||
relobj.Type = type;
|
||||
relobj.Target = f;
|
||||
|
@ -39,7 +39,7 @@ function parse_cust_props(data/*:string*/, opts) {
|
||||
default:
|
||||
if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks);
|
||||
}
|
||||
} else if(x.substr(0,2) === "</") {
|
||||
} else if(x.substr(0,2) === "</") {/* empty */
|
||||
} else if(opts.WTF) throw new Error(x);
|
||||
}
|
||||
}
|
||||
|
@ -174,28 +174,25 @@ function parse_PropertySet(blob, PIDSI) {
|
||||
if(piddsi.n == "CodePage") switch(PropH[piddsi.n]) {
|
||||
case 0: PropH[piddsi.n] = 1252;
|
||||
/* falls through */
|
||||
case 10000: // OSX Roman
|
||||
case 1252: // Windows Latin
|
||||
|
||||
case 874: // SB Windows Thai
|
||||
case 1250: // SB Windows Central Europe
|
||||
case 1251: // SB Windows Cyrillic
|
||||
case 1253: // SB Windows Greek
|
||||
case 1254: // SB Windows Turkish
|
||||
case 1255: // SB Windows Hebrew
|
||||
case 1256: // SB Windows Arabic
|
||||
case 1257: // SB Windows Baltic
|
||||
case 1258: // SB Windows Vietnam
|
||||
|
||||
case 932: // DB Windows Japanese Shift-JIS
|
||||
case 936: // DB Windows Simplified Chinese GBK
|
||||
case 949: // DB Windows Korean
|
||||
case 950: // DB Windows Traditional Chinese Big5
|
||||
|
||||
case 1200: // UTF16LE
|
||||
case 1201: // UTF16BE
|
||||
case 65000: case -536: // UTF-7
|
||||
case 65001: case -535: // UTF-8
|
||||
case 874:
|
||||
case 932:
|
||||
case 936:
|
||||
case 949:
|
||||
case 950:
|
||||
case 1250:
|
||||
case 1251:
|
||||
case 1253:
|
||||
case 1254:
|
||||
case 1255:
|
||||
case 1256:
|
||||
case 1257:
|
||||
case 1258:
|
||||
case 10000:
|
||||
case 1200:
|
||||
case 1201:
|
||||
case 1252:
|
||||
case 65000: case -536:
|
||||
case 65001: case -535:
|
||||
set_cp(CodePage = PropH[piddsi.n]); break;
|
||||
default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
|
||||
}
|
||||
@ -262,7 +259,7 @@ function parse_PropertySetStream(file, PIDSI) {
|
||||
if(NumSets === 1) return rval;
|
||||
if(blob.l !== Offset1) throw new Error("Length mismatch 2: " + blob.l + " !== " + Offset1);
|
||||
var PSet1;
|
||||
try { PSet1 = parse_PropertySet(blob, null); } catch(e) { }
|
||||
try { PSet1 = parse_PropertySet(blob, null); } catch(e) {/* empty */}
|
||||
for(y in PSet1) rval[y] = PSet1[y];
|
||||
rval.FMTID = [FMTID0, FMTID1]; // TODO: verify FMTID0/1
|
||||
return rval;
|
||||
@ -363,7 +360,7 @@ function parse_XLUnicodeString2(blob, length, opts) {
|
||||
var parse_ControlInfo = parsenoop;
|
||||
|
||||
/* [MS-OSHARED] 2.3.7.6 URLMoniker TODO: flags */
|
||||
var parse_URLMoniker = function(blob, length) {
|
||||
var parse_URLMoniker = function(blob/*, length, opts*/) {
|
||||
var len = blob.read_shift(4), start = blob.l;
|
||||
var extra = false;
|
||||
if(len > 24) {
|
||||
|
@ -21,7 +21,7 @@ function parse_frtHeader(blob) {
|
||||
function parse_OptXLUnicodeString(blob, length, opts) { return length === 0 ? "" : parse_XLUnicodeString2(blob, length, opts); }
|
||||
|
||||
/* 2.5.158 */
|
||||
var HIDEOBJENUM = ['SHOWALL', 'SHOWPLACEHOLDER', 'HIDEALL'];
|
||||
//var HIDEOBJENUM = ['SHOWALL', 'SHOWPLACEHOLDER', 'HIDEALL'];
|
||||
var parse_HideObjEnum = parseuint16;
|
||||
|
||||
/* 2.5.344 */
|
||||
@ -99,35 +99,39 @@ function parse_FtCf(blob, length) {
|
||||
}
|
||||
|
||||
/* 2.5.140 - 2.5.154 and friends */
|
||||
function parse_FtSkip(blob, length) { blob.l += 2; blob.l += blob.read_shift(2); }
|
||||
var FtTab = {
|
||||
/*::[*/0x15/*::]*/: parse_FtCmo,
|
||||
/*::[*/0x13/*::]*/: parsenoop, /* FtLbsData */
|
||||
/*::[*/0x12/*::]*/: function(blob, length) { blob.l += 12; }, /* FtCblsData */
|
||||
/*::[*/0x11/*::]*/: function(blob, length) { blob.l += 8; }, /* FtRboData */
|
||||
/*::[*/0x10/*::]*/: parsenoop, /* FtEdoData */
|
||||
/*::[*/0x0F/*::]*/: parsenoop, /* FtGboData */
|
||||
/*::[*/0x0D/*::]*/: parse_FtNts, /* FtNts */
|
||||
/*::[*/0x0C/*::]*/: function(blob, length) { blob.l += 24; }, /* FtSbs */
|
||||
/*::[*/0x0B/*::]*/: function(blob, length) { blob.l += 10; }, /* FtRbo */
|
||||
/*::[*/0x0A/*::]*/: function(blob, length) { blob.l += 16; }, /* FtCbls */
|
||||
/*::[*/0x09/*::]*/: parsenoop, /* FtPictFmla */
|
||||
/*::[*/0x08/*::]*/: function(blob, length) { blob.l += 6; }, /* FtPioGrbit */
|
||||
/*::[*/0x07/*::]*/: parse_FtCf, /* FtCf */
|
||||
/*::[*/0x06/*::]*/: function(blob, length) { blob.l += 6; }, /* FtGmo */
|
||||
/*::[*/0x04/*::]*/: parsenoop, /* FtMacro */
|
||||
/*::[*/0x00/*::]*/: function(blob, length) { blob.l += 4; } /* FtEnding */
|
||||
/*::[*/0x00/*::]*/: parse_FtSkip, /* FtEnd */
|
||||
/*::[*/0x04/*::]*/: parse_FtSkip, /* FtMacro */
|
||||
/*::[*/0x05/*::]*/: parse_FtSkip, /* FtButton */
|
||||
/*::[*/0x06/*::]*/: parse_FtSkip, /* FtGmo */
|
||||
/*::[*/0x07/*::]*/: parse_FtCf, /* FtCf */
|
||||
/*::[*/0x08/*::]*/: parse_FtSkip, /* FtPioGrbit */
|
||||
/*::[*/0x09/*::]*/: parse_FtSkip, /* FtPictFmla */
|
||||
/*::[*/0x0A/*::]*/: parse_FtSkip, /* FtCbls */
|
||||
/*::[*/0x0B/*::]*/: parse_FtSkip, /* FtRbo */
|
||||
/*::[*/0x0C/*::]*/: parse_FtSkip, /* FtSbs */
|
||||
/*::[*/0x0D/*::]*/: parse_FtNts, /* FtNts */
|
||||
/*::[*/0x0E/*::]*/: parse_FtSkip, /* FtSbsFmla */
|
||||
/*::[*/0x0F/*::]*/: parse_FtSkip, /* FtGboData */
|
||||
/*::[*/0x10/*::]*/: parse_FtSkip, /* FtEdoData */
|
||||
/*::[*/0x11/*::]*/: parse_FtSkip, /* FtRboData */
|
||||
/*::[*/0x12/*::]*/: parse_FtSkip, /* FtCblsData */
|
||||
/*::[*/0x13/*::]*/: parse_FtSkip, /* FtLbsData */
|
||||
/*::[*/0x14/*::]*/: parse_FtSkip, /* FtCblsFmla */
|
||||
/*::[*/0x15/*::]*/: parse_FtCmo
|
||||
};
|
||||
function parse_FtArray(blob, length, ot) {
|
||||
var s = blob.l;
|
||||
var tgt = blob.l + length;
|
||||
var fts = [];
|
||||
while(blob.l < s + length) {
|
||||
while(blob.l < tgt) {
|
||||
var ft = blob.read_shift(2);
|
||||
blob.l-=2;
|
||||
try {
|
||||
fts.push(FtTab[ft](blob, s + length - blob.l));
|
||||
} catch(e) { blob.l = s + length; return fts; }
|
||||
fts.push(FtTab[ft](blob, tgt - blob.l));
|
||||
} catch(e) { blob.l = tgt; return fts; }
|
||||
}
|
||||
if(blob.l != s + length) blob.l = s + length; //throw new Error("bad Object Ft-sequence");
|
||||
if(blob.l != tgt) blob.l = tgt; //throw new Error("bad Object Ft-sequence");
|
||||
return fts;
|
||||
}
|
||||
|
||||
@ -158,7 +162,7 @@ function parse_BOF(blob, length) {
|
||||
function parse_InterfaceHdr(blob, length) {
|
||||
if(length === 0) return 0x04b0;
|
||||
var q;
|
||||
if((q=blob.read_shift(2))!==0x04b0){}
|
||||
if((q=blob.read_shift(2))!==0x04b0){/* empty */}
|
||||
return 0x04b0;
|
||||
}
|
||||
|
||||
@ -246,11 +250,16 @@ function parse_RecalcId(blob, length) {
|
||||
}
|
||||
|
||||
/* 2.4.87 */
|
||||
function parse_DefaultRowHeight(blob, length) {
|
||||
var f = blob.read_shift(2);
|
||||
var fl = {Unsynced:f&1,DyZero:(f&2)>>1,ExAsc:(f&4)>>2,ExDsc:(f&8)>>3};
|
||||
/* char is misleading, miyRw and miyRwHidden overlap */
|
||||
function parse_DefaultRowHeight(blob, length, opts) {
|
||||
var f = 0;
|
||||
if(!(opts && opts.biff == 2)) {
|
||||
f = blob.read_shift(2);
|
||||
}
|
||||
var miyRw = blob.read_shift(2);
|
||||
if((opts && opts.biff == 2)) {
|
||||
f = 1 - (miyRw >> 15); miyRw &= 0x7fff;
|
||||
}
|
||||
var fl = {Unsynced:f&1,DyZero:(f&2)>>1,ExAsc:(f&4)>>2,ExDsc:(f&8)>>3};
|
||||
return [fl, miyRw];
|
||||
}
|
||||
|
||||
@ -265,9 +274,17 @@ function parse_Window1(blob, length) {
|
||||
|
||||
/* 2.4.122 TODO */
|
||||
function parse_Font(blob, length, opts) {
|
||||
blob.l += 14;
|
||||
var name = parse_ShortXLUnicodeString(blob, 0, opts);
|
||||
return name;
|
||||
var o = {
|
||||
dyHeight: blob.read_shift(2),
|
||||
fl: blob.read_shift(2)
|
||||
};
|
||||
switch(opts && opts.biff || 8) {
|
||||
case 2: break;
|
||||
case 3: case 4: blob.l += 2; break;
|
||||
default: blob.l += 10; break;
|
||||
}
|
||||
o.name = parse_ShortXLUnicodeString(blob, 0, opts);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.4.149 */
|
||||
@ -299,8 +316,8 @@ var parse_BIFF2Format = parse_XLUnicodeString2;
|
||||
function parse_Dimensions(blob, length, opts) {
|
||||
var end = blob.l + length;
|
||||
var w = opts.biff == 8 || !opts.biff ? 4 : 2;
|
||||
var r = blob.read_shift(w), R = blob.read_shift(w),
|
||||
c = blob.read_shift(2), C = blob.read_shift(2);
|
||||
var r = blob.read_shift(w), R = blob.read_shift(w);
|
||||
var c = blob.read_shift(2), C = blob.read_shift(2);
|
||||
blob.l = end;
|
||||
return {s: {r:r, c:c}, e: {r:R, c:C}};
|
||||
}
|
||||
@ -549,11 +566,49 @@ function parse_MergeCells(blob, length) {
|
||||
}
|
||||
|
||||
/* 2.4.181 TODO: parse all the things! */
|
||||
function parse_Obj(blob, length) {
|
||||
function parse_Obj(blob, length, opts) {
|
||||
if(opts && opts.biff < 8) return parse_BIFF5Obj(blob, length, opts);
|
||||
var cmo = parse_FtCmo(blob, 22); // id, ot, flags
|
||||
var fts = parse_FtArray(blob, length-22, cmo[1]);
|
||||
return { cmo: cmo, ft:fts };
|
||||
}
|
||||
/* from older spec */
|
||||
var parse_BIFF5OT = [];
|
||||
parse_BIFF5OT[0x08] = function(blob, length, opts) {
|
||||
var tgt = blob.l + length;
|
||||
blob.l += 10; // todo
|
||||
var cf = blob.read_shift(2);
|
||||
blob.l += 4;
|
||||
var cbPictFmla = blob.read_shift(2);
|
||||
blob.l += 2;
|
||||
var grbit = blob.read_shift(2);
|
||||
blob.l += 4;
|
||||
var cchName = blob.read_shift(1);
|
||||
blob.l += cchName; // TODO: stName
|
||||
blob.l = tgt; // TODO: fmla
|
||||
return { fmt:cf };
|
||||
};
|
||||
|
||||
function parse_BIFF5Obj(blob, length, opts) {
|
||||
var cnt = blob.read_shift(4);
|
||||
var ot = blob.read_shift(2);
|
||||
var id = blob.read_shift(2);
|
||||
var grbit = blob.read_shift(2);
|
||||
var colL = blob.read_shift(2);
|
||||
var dxL = blob.read_shift(2);
|
||||
var rwT = blob.read_shift(2);
|
||||
var dyT = blob.read_shift(2);
|
||||
var colR = blob.read_shift(2);
|
||||
var dxR = blob.read_shift(2);
|
||||
var rwB = blob.read_shift(2);
|
||||
var dyB = blob.read_shift(2);
|
||||
var cbMacro = blob.read_shift(2);
|
||||
blob.l += 6;
|
||||
length -= 36;
|
||||
var fts = [];
|
||||
fts.push((parse_BIFF5OT[ot]||parsenoop)(blob, length, opts));
|
||||
return { cmo: [id, ot, grbit], ft:fts };
|
||||
}
|
||||
|
||||
/* 2.4.329 TODO: parse properly */
|
||||
function parse_TxO(blob, length, opts) {
|
||||
@ -684,7 +739,6 @@ var parse_StyleExt = parsenoop;
|
||||
|
||||
var parse_Window2 = parsenoop;
|
||||
|
||||
|
||||
var parse_Backup = parsebool; /* 2.4.14 */
|
||||
var parse_Blank = parse_XLSCell; /* 2.4.20 Just the cell */
|
||||
var parse_BottomMargin = parse_Xnum; /* 2.4.27 */
|
||||
@ -991,6 +1045,16 @@ var parse_BopPopCustom = parsenoop;
|
||||
var parse_Fbi2 = parsenoop;
|
||||
|
||||
/* --- Specific to versions before BIFF8 --- */
|
||||
function parse_ImData(blob, length, opts) {
|
||||
var tgt = blob.l + length;
|
||||
var cf = blob.read_shift(2);
|
||||
var env = blob.read_shift(2);
|
||||
var lcb = blob.read_shift(4);
|
||||
var o = {fmt:cf, env:env, len:lcb, data:blob.slice(blob.l,blob.l+lcb)};
|
||||
blob.l += lcb;
|
||||
return o;
|
||||
}
|
||||
|
||||
function parse_BIFF5String(blob) {
|
||||
var len = blob.read_shift(1);
|
||||
return blob.read_shift(len, 'sbcs-cont');
|
||||
@ -1037,7 +1101,7 @@ function parse_BIFF2FONTXTRA(blob, length) {
|
||||
blob.l += 1; // charset
|
||||
blob.l += 3; // unknown
|
||||
blob.l += 1; // font family
|
||||
blob.l += length - 9;
|
||||
blob.l += length - 13;
|
||||
}
|
||||
|
||||
/* TODO: parse rich text runs */
|
||||
|
@ -210,17 +210,23 @@ var SYLK = (function() {
|
||||
var Mval = 0, j;
|
||||
for (; ri !== records.length; ++ri) {
|
||||
Mval = 0;
|
||||
var record = records[ri].trim().split(";");
|
||||
var RT = record[0], val;
|
||||
switch(RT) {
|
||||
case 'P': if(record[1].charAt(0) == 'P') formats.push(records[ri].trim().substr(3).replace(/;;/g, ";"));
|
||||
var rstr=records[ri].trim(), record=rstr.split(";"), RT=record[0], val;
|
||||
if(rstr.length > 0) switch(RT) {
|
||||
case 'ID': break; /* header */
|
||||
case 'E': break; /* EOF */
|
||||
case 'B': break; /* dimensions */
|
||||
case 'O': break; /* options? */
|
||||
case 'P':
|
||||
if(record[1].charAt(0) == 'P')
|
||||
formats.push(rstr.substr(3).replace(/;;/g, ";"));
|
||||
break;
|
||||
case 'C': case 'F': for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
|
||||
case 'C':
|
||||
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
|
||||
case 'X': C = parseInt(record[rj].substr(1))-1; break;
|
||||
case 'Y':
|
||||
R = parseInt(record[rj].substr(1))-1; C = 0;
|
||||
for(j = arr.length; j <= R; ++j) arr[j] = [];
|
||||
break;
|
||||
case 'X': C = parseInt(record[rj].substr(1))-1; break;
|
||||
case 'K':
|
||||
val = record[rj].substr(1);
|
||||
if(val.charAt(0) === '"') val = val.substr(1,val.length - 2);
|
||||
@ -233,13 +239,27 @@ var SYLK = (function() {
|
||||
arr[R][C] = val;
|
||||
next_cell_format = null;
|
||||
break;
|
||||
case 'P':
|
||||
if(RT !== 'F') break;
|
||||
next_cell_format = formats[parseInt(record[rj].substr(1))];
|
||||
case 'E':
|
||||
/* formula = record[rj].substr(1); */
|
||||
break; /* TODO: formula */
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
} break;
|
||||
case 'F':
|
||||
for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
|
||||
case 'X': C = parseInt(record[rj].substr(1))-1; break;
|
||||
case 'Y':
|
||||
R = parseInt(record[rj].substr(1))-1; C = 0;
|
||||
for(j = arr.length; j <= R; ++j) arr[j] = [];
|
||||
break;
|
||||
case 'M': Mval = parseInt(record[rj].substr(1)) / 20; break;
|
||||
case 'F': break; /* ??? */
|
||||
case 'P':
|
||||
next_cell_format = formats[parseInt(record[rj].substr(1))];
|
||||
break;
|
||||
case 'S': break; /* cell style */
|
||||
case 'D': break; /* column */
|
||||
case 'N': break; /* font */
|
||||
case 'W':
|
||||
if(RT !== 'F') break;
|
||||
cw = record[rj].substr(1).split(" ");
|
||||
for(j = parseInt(cw[0], 10); j <= parseInt(cw[1], 10); ++j) {
|
||||
Mval = parseInt(cw[2], 10);
|
||||
@ -250,8 +270,10 @@ var SYLK = (function() {
|
||||
rowinfo[R] = {};
|
||||
if(Mval > 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); }
|
||||
else if(Mval == 0) rowinfo[R].hidden = true;
|
||||
break;
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
} break;
|
||||
default: break;
|
||||
default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
|
||||
}
|
||||
}
|
||||
if(rowinfo.length > 0) sht['!rows'] = rowinfo;
|
||||
@ -297,7 +319,7 @@ var SYLK = (function() {
|
||||
});
|
||||
}
|
||||
|
||||
function write_ws_rows_sylk(out, rows) {
|
||||
function write_ws_rows_sylk(out/*:Array<string>*/, rows/*:Array<RowInfo>*/) {
|
||||
rows.forEach(function(row, i) {
|
||||
var rec = "F;";
|
||||
if(row.hidden) rec += "M0;";
|
||||