forked from sheetjs/sheetjs
Merge changes from upsteam
This commit is contained in:
commit
0b1a0408cb
15
.gitignore
vendored
15
.gitignore
vendored
@ -3,8 +3,19 @@ misc/coverage.html
|
||||
misc/prof.js
|
||||
v8.log
|
||||
tmp
|
||||
*.txt
|
||||
*.csv
|
||||
*.dif
|
||||
*.prn
|
||||
*.slk
|
||||
*.socialcalc
|
||||
*.xls
|
||||
*.xlsb
|
||||
*.xlsm
|
||||
*.xlsx
|
||||
*.xlsm
|
||||
*.xlsb
|
||||
lab/
|
||||
.idea/
|
||||
*.xml
|
||||
*.htm
|
||||
*.html
|
||||
*.sheetjs
|
||||
|
4
.jshintrc
Normal file
4
.jshintrc
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"bitwise": false,
|
||||
"curly": false
|
||||
}
|
@ -4,11 +4,20 @@ index.html
|
||||
misc/
|
||||
node_modules
|
||||
tmp
|
||||
*.txt
|
||||
*.csv
|
||||
*.dif
|
||||
*.prn
|
||||
*.slk
|
||||
*.socialcalc
|
||||
*.xls
|
||||
*.xlsb
|
||||
*.xlsm
|
||||
*.xlsx
|
||||
*.xml
|
||||
*.htm
|
||||
*.html
|
||||
*.sheetjs
|
||||
.gitignore
|
||||
.jshintrc
|
||||
CONTRIBUTING.md
|
||||
|
@ -1,8 +1,9 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.11"
|
||||
- "iojs"
|
||||
- "0.11.14"
|
||||
- "0.10"
|
||||
- "0.8"
|
||||
# - "0.8" # commented because of npm issue with camelcase
|
||||
before_install:
|
||||
- "npm install -g mocha"
|
||||
- "npm install blanket"
|
||||
|
@ -5,7 +5,7 @@ order to maintain that, every contributor must be vigilant.
|
||||
|
||||
There have been many projects in the past that have been very lax regarding
|
||||
licensing, and we are of the opinion that those are ticking timebombs and that
|
||||
no corporate product should depend on them.
|
||||
no commercial product should depend on them.
|
||||
|
||||
|
||||
# Required Reading
|
||||
@ -17,6 +17,17 @@ These are pretty short reads and emphasize the importance of proper licensing:
|
||||
- http://www.codinghorror.com/blog/2007/04/pick-a-license-any-license.html
|
||||
|
||||
|
||||
# Raising Issues
|
||||
|
||||
Issues should generally be accompanied by test files. Since github does not
|
||||
support attachments, the best method is to send files to <sheetjs@gmail.com>
|
||||
(subject line should contain issue number or message) or to share using some
|
||||
storage service. Unless expressly permitted, any attachments will not be
|
||||
shared or included in a test suite (although I will ask :)
|
||||
|
||||
If sending email to a gmail account is problematic, the <dev@sheetjs.com> email
|
||||
inbox is self-hosted.
|
||||
|
||||
# Pre-Contribution Checklist
|
||||
|
||||
Before thinking about contributing, make sure that:
|
||||
@ -27,7 +38,7 @@ Before thinking about contributing, make sure that:
|
||||
Corporation or a subsidiary
|
||||
|
||||
- You have not consulted any existing relevant codebase (if you have, please
|
||||
take note of which codebases were consulted).
|
||||
take note of which codebases were consulted).
|
||||
|
||||
If you cannot attest to each of these items, the best approach is to raise an
|
||||
issue. If it is a particularly high-priority issue, please drop an email to
|
||||
@ -45,9 +56,8 @@ Keep these in mind as you work:
|
||||
- You are working on your own time. Unless they explicitly grant permission,
|
||||
your employer may be the ultimate owner of your IP
|
||||
|
||||
|
||||
# Post-Contribution
|
||||
|
||||
Before contributions are merged, you will receive an email (at the address
|
||||
associated with the git commit) and will be asked to confirm the aforementioned
|
||||
items.
|
||||
items. Ensure that the email addresses associated with the commits is valid.
|
||||
|
2
LICENSE
2
LICENSE
@ -1,4 +1,4 @@
|
||||
Copyright (C) 2012-2014 SheetJS
|
||||
Copyright (C) 2012-2015 SheetJS
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
9
Makefile
9
Makefile
@ -1,5 +1,5 @@
|
||||
LIB=xlsx
|
||||
FMT=xlsx xlsm xlsb ods misc full
|
||||
FMT=xlsx xlsm xlsb ods xls xml misc full
|
||||
REQS=jszip.js
|
||||
ADDONS=dist/cpexcel.js
|
||||
AUXTARGETS=ods.js
|
||||
@ -17,6 +17,9 @@ $(TARGET): $(DEPS)
|
||||
bits/01_version.js: package.json
|
||||
echo "$(ULIB).version = '"`grep version package.json | awk '{gsub(/[^0-9a-z\.-]/,"",$$2); print $$2}'`"';" > $@
|
||||
|
||||
bits/18_cfb.js: node_modules/cfb/dist/xlscfb.js
|
||||
cp $^ $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(TARGET)
|
||||
@ -52,6 +55,7 @@ $(TESTFMT): test_%:
|
||||
.PHONY: lint
|
||||
lint: $(TARGET)
|
||||
jshint --show-non-errors $(TARGET) $(AUXTARGETS)
|
||||
jshint --show-non-errors package.json bower.json
|
||||
jscs $(TARGET) $(AUXTARGETS)
|
||||
|
||||
.PHONY: test-osx
|
||||
@ -88,8 +92,11 @@ dist: dist-deps $(TARGET) bower.json
|
||||
cp $(TARGET) dist/
|
||||
cp LICENSE dist/
|
||||
uglifyjs $(TARGET) -o dist/$(LIB).min.js --source-map dist/$(LIB).min.map --preamble "$$(head -n 1 bits/00_header.js)"
|
||||
misc/strip_sourcemap.sh dist/$(LIB).min.js
|
||||
uglifyjs $(REQS) $(TARGET) -o dist/$(LIB).core.min.js --source-map dist/$(LIB).core.min.map --preamble "$$(head -n 1 bits/00_header.js)"
|
||||
misc/strip_sourcemap.sh dist/$(LIB).core.min.js
|
||||
uglifyjs $(REQS) $(ADDONS) $(TARGET) -o dist/$(LIB).full.min.js --source-map dist/$(LIB).full.min.map --preamble "$$(head -n 1 bits/00_header.js)"
|
||||
misc/strip_sourcemap.sh dist/$(LIB).full.min.js
|
||||
|
||||
.PHONY: aux
|
||||
aux: $(AUXTARGETS)
|
||||
|
92
README.md
92
README.md
@ -1,8 +1,22 @@
|
||||
# xlsx
|
||||
|
||||
Parser and writer for Excel 2007+ (XLSX/XLSM/XLSB) files and parser for ODS.
|
||||
Pure-JS cleanroom implementation from the Office Open XML spec, [MS-XLSB], ODF
|
||||
specifications and related documents.
|
||||
Parser and writer for various spreadsheet formats. Pure-JS cleanroom
|
||||
implementation from official specifications and related documents.
|
||||
|
||||
Supported read formats:
|
||||
|
||||
- Excel 2007+ XML Formats (XLSX/XLSM)
|
||||
- Excel 2007+ Binary Format (XLSB)
|
||||
- Excel 2003-2004 XML Format (XML "SpreadsheetML")
|
||||
- Excel 97-2004 (XLS BIFF8)
|
||||
- Excel 5.0/95 (XLS BIFF5)
|
||||
- OpenDocument Spreadsheet (ODS)
|
||||
|
||||
Supported write formats:
|
||||
|
||||
- XLSX
|
||||
- CSV (and general DSV)
|
||||
- JSON and JS objects (various styles)
|
||||
|
||||
Demo: <http://oss.sheetjs.com/js-xlsx>
|
||||
|
||||
@ -10,7 +24,7 @@ Source: <http://git.io/xlsx>
|
||||
|
||||
## Installation
|
||||
|
||||
In [nodejs](https://www.npmjs.org/package/xlsx):
|
||||
With [npm](https://www.npmjs.org/package/xlsx):
|
||||
|
||||
npm install xlsx
|
||||
|
||||
@ -18,7 +32,7 @@ In the browser:
|
||||
|
||||
<script lang="javascript" src="dist/xlsx.core.min.js"></script>
|
||||
|
||||
In [bower](http://bower.io/search/?q=js-xlsx):
|
||||
With [bower](http://bower.io/search/?q=js-xlsx):
|
||||
|
||||
bower install js-xlsx
|
||||
|
||||
@ -27,7 +41,7 @@ CDNjs automatically pulls the latest version and makes all versions available at
|
||||
|
||||
## Optional Modules
|
||||
|
||||
The nodejs version automatically requires modules for additional features. Some
|
||||
The node version automatically requires modules for additional features. Some
|
||||
of these modules are rather large in size and are only needed in special
|
||||
circumstances, so they do not ship with the core. For browser use, they must
|
||||
be included directly:
|
||||
@ -56,7 +70,7 @@ To use the shim, add the shim before the script tag that loads xlsx.js:
|
||||
For parsing, the first step is to read the file. This involves acquiring the
|
||||
data and feeding it into the library. Here are a few common scenarios:
|
||||
|
||||
- nodejs readFile:
|
||||
- node readFile:
|
||||
|
||||
```
|
||||
if(typeof require !== 'undefined') XLSX = require('xlsx');
|
||||
@ -142,13 +156,32 @@ input_dom_element.addEventListener('change', handleFile, false);
|
||||
|
||||
## Working with the Workbook
|
||||
|
||||
This example walks through every cell of every sheet and dumps the values:
|
||||
The full object format is described later in this README.
|
||||
|
||||
This example extracts the value stored in cell A1 from the first worksheet:
|
||||
|
||||
```
|
||||
var first_sheet_name = workbook.SheetNames[0];
|
||||
var address_of_cell = 'A1';
|
||||
|
||||
/* Get worksheet */
|
||||
var worksheet = workbook.Sheets[first_sheet_name];
|
||||
|
||||
/* Find desired cell */
|
||||
var desired_cell = worksheet[address_of_cell];
|
||||
|
||||
/* Get the value */
|
||||
var desired_value = desired_cell.v;
|
||||
```
|
||||
|
||||
This example iterates through every nonempty of every sheet and dumps values:
|
||||
|
||||
```
|
||||
var sheet_name_list = workbook.SheetNames;
|
||||
sheet_name_list.forEach(function(y) {
|
||||
sheet_name_list.forEach(function(y) { /* iterate through sheets */
|
||||
var worksheet = workbook.Sheets[y];
|
||||
for (z in worksheet) {
|
||||
/* all keys that do not begin with "!" correspond to cell addresses */
|
||||
if(z[0] === '!') continue;
|
||||
console.log(y + "!" + z + "=" + JSON.stringify(worksheet[z].v));
|
||||
}
|
||||
@ -166,9 +199,9 @@ mode is provided for testing. On OSX you can get the base64 encoding with:
|
||||
|
||||
- <http://oss.sheetjs.com/js-xlsx/ajax.html> XMLHttpRequest
|
||||
|
||||
- <https://github.com/SheetJS/js-xlsx/blob/master/bin/xlsx.njs> nodejs
|
||||
- <https://github.com/SheetJS/js-xlsx/blob/master/bin/xlsx.njs> node
|
||||
|
||||
The nodejs version installs a binary `xlsx` which can read XLSX/XLSM/XLSB
|
||||
The node version installs a command line tool `xlsx` which can read spreadsheet
|
||||
files and output the contents in various formats. The source is available at
|
||||
`xlsx.njs` in the bin directory.
|
||||
|
||||
@ -220,7 +253,7 @@ Complete examples:
|
||||
|
||||
## Interface
|
||||
|
||||
`XLSX` is the exposed variable in the browser and the exported nodejs variable
|
||||
`XLSX` is the exposed variable in the browser and the exported node variable
|
||||
|
||||
`XLSX.version` is the version of the library (added by the build script).
|
||||
|
||||
@ -374,7 +407,8 @@ Special worksheet keys (accessible as `worksheet[key]`, each starting with `!`):
|
||||
`wb.Sheets[sheetname]` returns an object representing the worksheet.
|
||||
|
||||
`wb.Props` is an object storing the standard properties. `wb.Custprops` stores
|
||||
custom properties.
|
||||
custom properties. Since the XLS standard properties deviate from the XLSX
|
||||
standard, XLS parsing stores core properties in both places. .
|
||||
|
||||
|
||||
## Parsing Options
|
||||
@ -383,7 +417,7 @@ The exported `read` and `readFile` functions accept an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | ------: | :---------- |
|
||||
| cellFormula | true | Save formulae to the .f field |
|
||||
| cellFormula | true | Save formulae to the .f field ** |
|
||||
| cellHTML | true | Parse rich text and save HTML to the .h field |
|
||||
| cellNF | false | Save number format string to the .z field |
|
||||
| cellStyles | false | Save style/theme info to the .s field |
|
||||
@ -395,17 +429,24 @@ The exported `read` and `readFile` functions accept an options argument:
|
||||
| bookProps | false | If true, only parse enough to get book metadata ** |
|
||||
| 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 ** |
|
||||
|
||||
- `cellFormula` option only applies to formats that require extra processing to
|
||||
parse formulae (XLS/XLSB).
|
||||
- Even if `cellNF` is false, formatted text will be generated and saved to `.w`
|
||||
- In some cases, sheets may be parsed even if `bookSheets` is false.
|
||||
- `bookSheets` and `bookProps` combine to give both sets of information
|
||||
- `Deps` will be an empty object if `bookDeps` is falsy
|
||||
- `bookFiles` adds a `keys` array (paths in the ZIP) and a `files` hash (whose
|
||||
keys are paths and values are objects representing the files)
|
||||
- `bookFiles` behavior depends on file type:
|
||||
* `keys` array (paths in the ZIP) for ZIP-based formats
|
||||
* `files` hash (mapping paths to objects representing the files) for ZIP
|
||||
* `cfb` object for formats using CFB containers
|
||||
- `sheetRows-1` rows will be generated when looking at the JSON object output
|
||||
(since the header row is counted as a row when parsing the data)
|
||||
- `bookVBA` merely exposes the raw vba object. It does not parse the data.
|
||||
- `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.
|
||||
|
||||
The defaults are enumerated in bits/84_defaults.js
|
||||
|
||||
@ -502,7 +543,7 @@ Borders for merged areas are specified for each cell within the merged area. So
|
||||
|
||||
## Tested Environments
|
||||
|
||||
- NodeJS 0.8, 0.10 (latest release), 0.11 (unstable)
|
||||
- NodeJS 0.8, 0.10 (latest release), 0.11.14 (unstable), io.js
|
||||
- IE 6/7/8/9/10/11 using Base64 mode (IE10/11 using HTML5 mode)
|
||||
- FF 18 using Base64 or HTML5 mode
|
||||
- Chrome 24 using Base64 or HTML5 mode
|
||||
@ -521,7 +562,7 @@ Running `make init` will refresh the `test_files` submodule and get the files.
|
||||
|
||||
## Testing
|
||||
|
||||
`make test` will run the nodejs-based tests. To run the in-browser tests, clone
|
||||
`make test` will run the node-based tests. 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`):
|
||||
|
||||
@ -553,10 +594,6 @@ $ diff xlsx.js xlsx.new.js
|
||||
To produce the dist files, run `make dist`. The dist files are updated in each
|
||||
version release and should not be committed between versions.
|
||||
|
||||
## XLS Support
|
||||
|
||||
XLS is available in [js-xls](http://git.io/xls).
|
||||
|
||||
## License
|
||||
|
||||
Please consult the attached LICENSE file for details. All rights not explicitly
|
||||
@ -578,7 +615,18 @@ OSP-covered specifications:
|
||||
- [MS-XLSB]: Excel (.xlsb) Binary File Format
|
||||
- [MS-XLSX]: Excel (.xlsx) Extensions to the Office Open XML SpreadsheetML File Format
|
||||
- [MS-OE376]: Office Implementation Information for ECMA-376 Standards Support
|
||||
- [MS-CFB]: Compound File Binary File Format
|
||||
- [MS-XLS]: Excel Binary File Format (.xls) Structure Specification
|
||||
- [MS-ODATA]: Open Data Protocol (OData)
|
||||
- [MS-OFFCRYPTO]: Office Document Cryptography Structure
|
||||
- [MS-OLEDS]: Object Linking and Embedding (OLE) Data Structures
|
||||
- [MS-OLEPS]: Object Linking and Embedding (OLE) Property Set Data Structures
|
||||
- [MS-OSHARED]: Office Common Data Types and Objects Structures
|
||||
- [MS-OVBA]: Office VBA File Format Structure
|
||||
- [MS-CTXLS]: Excel Custom Toolbar Binary File Format
|
||||
- [MS-XLDM]: Spreadsheet Data Model File Format
|
||||
- [MS-EXSPXML3]: Excel Calculation Version 2 Web Service XML Schema
|
||||
- [XLS]: Microsoft Office Excel 97-2007 Binary File Format Specification
|
||||
|
||||
Open Document Format for Office Applications Version 1.2 (29 September 2011)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
/* xlsx.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
|
||||
/* xlsx.js (C) 2013-2015 SheetJS -- http://sheetjs.com */
|
||||
var n = "xlsx";
|
||||
/* vim: set ts=2 ft=javascript: */
|
||||
var X = require('../');
|
||||
@ -9,6 +9,7 @@ program
|
||||
.usage('[options] <file> [sheetname]')
|
||||
.option('-f, --file <file>', 'use specified workbook')
|
||||
.option('-s, --sheet <sheet>', 'print specified sheet (default first sheet)')
|
||||
.option('-p, --password <pw>', 'if file is encrypted, try with specified pw')
|
||||
.option('-l, --list-sheets', 'list sheet names and exit')
|
||||
.option('-o, --output <file>', 'output to specified file')
|
||||
.option('-B, --xlsb', 'emit XLSB to <sheetname> or <file>.xlsb')
|
||||
@ -67,6 +68,7 @@ if(!fs.existsSync(filename)) {
|
||||
var opts = {}, wb;
|
||||
if(program.listSheets) opts.bookSheets = true;
|
||||
if(program.sheetRows) opts.sheetRows = program.sheetRows;
|
||||
if(program.password) opts.password = program.password;
|
||||
if(program.xlsx || program.xlsm || program.xlsb) {
|
||||
opts.cellNF = true;
|
||||
if(program.output) sheetname = program.output;
|
||||
|
1
bits/.npmignore
Normal file
1
bits/.npmignore
Normal file
@ -0,0 +1 @@
|
||||
*.js
|
@ -1,5 +1,6 @@
|
||||
/* xlsx.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
|
||||
/* xlsx.js (C) 2013-2015 SheetJS -- http://sheetjs.com */
|
||||
/* vim: set ts=2: */
|
||||
/*jshint -W041 */
|
||||
/*jshint funcscope:true, eqnull:true */
|
||||
var XLSX = {};
|
||||
(function(XLSX){
|
||||
(function make_xlsx(XLSX){
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.7.12';
|
||||
XLSX.version = '0.8.0';
|
||||
|
@ -1,18 +1,23 @@
|
||||
var current_codepage = 1252, current_cptable;
|
||||
var current_codepage = 1200, current_cptable;
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
|
||||
if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel');
|
||||
current_cptable = cptable[current_codepage];
|
||||
}
|
||||
function reset_cp() { set_cp(1252); }
|
||||
function reset_cp() { set_cp(1200); }
|
||||
var set_cp = function(cp) { current_codepage = cp; };
|
||||
|
||||
function char_codes(data) { var o = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; }
|
||||
var debom_xml = function(data) { return data; };
|
||||
|
||||
var _getchar = function _gc1(x) { return String.fromCharCode(x); };
|
||||
if(typeof cptable !== 'undefined') {
|
||||
set_cp = function(cp) { current_codepage = cp; current_cptable = cptable[cp]; };
|
||||
debom_xml = function(data) {
|
||||
if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.substr(2))); }
|
||||
return data;
|
||||
};
|
||||
_getchar = function _gc2(x) {
|
||||
if(current_codepage === 1200) return String.fromCharCode(x);
|
||||
return cptable.utils.decode(current_codepage, [x&255,x>>8])[0];
|
||||
};
|
||||
}
|
||||
|
41
bits/04_base64.js
Normal file
41
bits/04_base64.js
Normal file
@ -0,0 +1,41 @@
|
||||
var Base64 = (function make_b64(){
|
||||
var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
return {
|
||||
encode: function(input, utf8) {
|
||||
var o = "";
|
||||
var c1, c2, c3, e1, e2, e3, e4;
|
||||
for(var i = 0; i < input.length; ) {
|
||||
c1 = input.charCodeAt(i++);
|
||||
c2 = input.charCodeAt(i++);
|
||||
c3 = input.charCodeAt(i++);
|
||||
e1 = c1 >> 2;
|
||||
e2 = (c1 & 3) << 4 | c2 >> 4;
|
||||
e3 = (c2 & 15) << 2 | c3 >> 6;
|
||||
e4 = c3 & 63;
|
||||
if (isNaN(c2)) { e3 = e4 = 64; }
|
||||
else if (isNaN(c3)) { e4 = 64; }
|
||||
o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4);
|
||||
}
|
||||
return o;
|
||||
},
|
||||
decode: function b64_decode(input, utf8) {
|
||||
var o = "";
|
||||
var c1, c2, c3;
|
||||
var e1, e2, e3, e4;
|
||||
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
||||
for(var i = 0; i < input.length;) {
|
||||
e1 = map.indexOf(input.charAt(i++));
|
||||
e2 = map.indexOf(input.charAt(i++));
|
||||
e3 = map.indexOf(input.charAt(i++));
|
||||
e4 = map.indexOf(input.charAt(i++));
|
||||
c1 = e1 << 2 | e2 >> 4;
|
||||
c2 = (e2 & 15) << 4 | e3 >> 2;
|
||||
c3 = (e3 & 3) << 6 | e4;
|
||||
o += String.fromCharCode(c1);
|
||||
if (e3 != 64) { o += String.fromCharCode(c2); }
|
||||
if (e4 != 64) { o += String.fromCharCode(c3); }
|
||||
}
|
||||
return o;
|
||||
}
|
||||
};
|
||||
})();
|
16
bits/05_buf.js
Normal file
16
bits/05_buf.js
Normal file
@ -0,0 +1,16 @@
|
||||
var has_buf = (typeof Buffer !== 'undefined');
|
||||
|
||||
function new_raw_buf(len) {
|
||||
/* jshint -W056 */
|
||||
return new (has_buf ? Buffer : Array)(len);
|
||||
/* jshint +W056 */
|
||||
}
|
||||
|
||||
function s2a(s) {
|
||||
if(has_buf) return new Buffer(s, "binary");
|
||||
return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; });
|
||||
}
|
||||
|
||||
var bconcat = function(bufs) { return [].concat.apply([], bufs); };
|
||||
|
||||
var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/;
|
20
bits/11_ssfutils.js
Normal file
20
bits/11_ssfutils.js
Normal file
@ -0,0 +1,20 @@
|
||||
/* map from xlml named formats to SSF TODO: localize */
|
||||
var XLMLFormatMap = {
|
||||
"General Number": "General",
|
||||
"General Date": SSF._table[22],
|
||||
"Long Date": "dddd, mmmm dd, yyyy",
|
||||
"Medium Date": SSF._table[15],
|
||||
"Short Date": SSF._table[14],
|
||||
"Long Time": SSF._table[19],
|
||||
"Medium Time": SSF._table[18],
|
||||
"Short Time": SSF._table[20],
|
||||
"Currency": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
|
||||
"Fixed": SSF._table[2],
|
||||
"Standard": SSF._table[4],
|
||||
"Percent": SSF._table[10],
|
||||
"Scientific": SSF._table[11],
|
||||
"Yes/No": '"Yes";"Yes";"No";@',
|
||||
"True/False": '"True";"True";"False";@',
|
||||
"On/Off": '"Yes";"Yes";"No";@'
|
||||
};
|
||||
|
383
bits/18_cfb.js
Normal file
383
bits/18_cfb.js
Normal file
@ -0,0 +1,383 @@
|
||||
var DO_NOT_EXPORT_CFB = true;
|
||||
/* cfb.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
|
||||
/* vim: set ts=2: */
|
||||
/*jshint eqnull:true */
|
||||
|
||||
/* [MS-CFB] v20130118 */
|
||||
var CFB = (function _CFB(){
|
||||
var exports = {};
|
||||
exports.version = '0.10.2';
|
||||
function parse(file) {
|
||||
var mver = 3; // major version
|
||||
var ssz = 512; // sector size
|
||||
var nmfs = 0; // number of mini FAT sectors
|
||||
var ndfs = 0; // number of DIFAT sectors
|
||||
var dir_start = 0; // first directory sector location
|
||||
var minifat_start = 0; // first mini FAT sector location
|
||||
var difat_start = 0; // first mini FAT sector location
|
||||
|
||||
var fat_addrs = []; // locations of FAT sectors
|
||||
|
||||
/* [MS-CFB] 2.2 Compound File Header */
|
||||
var blob = file.slice(0,512);
|
||||
prep_blob(blob, 0);
|
||||
|
||||
/* major version */
|
||||
var mv = check_get_mver(blob);
|
||||
mver = mv[0];
|
||||
switch(mver) {
|
||||
case 3: ssz = 512; break; case 4: ssz = 4096; break;
|
||||
default: throw "Major Version: Expected 3 or 4 saw " + mver;
|
||||
}
|
||||
|
||||
/* reprocess header */
|
||||
if(ssz !== 512) { blob = file.slice(0,ssz); prep_blob(blob, 28 /* blob.l */); }
|
||||
/* Save header for final object */
|
||||
var header = file.slice(0,ssz);
|
||||
|
||||
check_shifts(blob, mver);
|
||||
|
||||
// Number of Directory Sectors
|
||||
var nds = blob.read_shift(4, 'i');
|
||||
if(mver === 3 && nds !== 0) throw '# Directory Sectors: Expected 0 saw ' + nds;
|
||||
|
||||
// Number of FAT Sectors
|
||||
//var nfs = blob.read_shift(4, 'i');
|
||||
blob.l += 4;
|
||||
|
||||
// First Directory Sector Location
|
||||
dir_start = blob.read_shift(4, 'i');
|
||||
|
||||
// Transaction Signature
|
||||
blob.l += 4;
|
||||
|
||||
// Mini Stream Cutoff Size
|
||||
blob.chk('00100000', 'Mini Stream Cutoff Size: ');
|
||||
|
||||
// First Mini FAT Sector Location
|
||||
minifat_start = blob.read_shift(4, 'i');
|
||||
|
||||
// Number of Mini FAT Sectors
|
||||
nmfs = blob.read_shift(4, 'i');
|
||||
|
||||
// First DIFAT sector location
|
||||
difat_start = blob.read_shift(4, 'i');
|
||||
|
||||
// Number of DIFAT Sectors
|
||||
ndfs = blob.read_shift(4, 'i');
|
||||
|
||||
// Grab FAT Sector Locations
|
||||
for(var q, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */
|
||||
q = blob.read_shift(4, 'i');
|
||||
if(q<0) break;
|
||||
fat_addrs[j] = q;
|
||||
}
|
||||
|
||||
/** Break the file up into sectors */
|
||||
var sectors = sectorify(file, ssz);
|
||||
|
||||
sleuth_fat(difat_start, ndfs, sectors, ssz, fat_addrs);
|
||||
|
||||
/** Chains */
|
||||
var sector_list = make_sector_list(sectors, dir_start, fat_addrs, ssz);
|
||||
|
||||
sector_list[dir_start].name = "!Directory";
|
||||
if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
|
||||
sector_list[fat_addrs[0]].name = "!FAT";
|
||||
sector_list.fat_addrs = fat_addrs;
|
||||
sector_list.ssz = ssz;
|
||||
|
||||
/* [MS-CFB] 2.6.1 Compound File Directory Entry */
|
||||
var files = {}, Paths = [], FileIndex = [], FullPaths = [], FullPathDir = {};
|
||||
read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex);
|
||||
|
||||
build_full_paths(FileIndex, FullPathDir, FullPaths, Paths);
|
||||
|
||||
var root_name = Paths.shift();
|
||||
Paths.root = root_name;
|
||||
|
||||
/* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */
|
||||
var find_path = make_find_path(FullPaths, Paths, FileIndex, files, root_name);
|
||||
|
||||
return {
|
||||
raw: {header: header, sectors: sectors},
|
||||
FileIndex: FileIndex,
|
||||
FullPaths: FullPaths,
|
||||
FullPathDir: FullPathDir,
|
||||
find: find_path
|
||||
};
|
||||
} // parse
|
||||
|
||||
/* [MS-CFB] 2.2 Compound File Header -- read up to major version */
|
||||
function check_get_mver(blob) {
|
||||
// header signature 8
|
||||
blob.chk(HEADER_SIGNATURE, 'Header Signature: ');
|
||||
|
||||
// clsid 16
|
||||
blob.chk(HEADER_CLSID, 'CLSID: ');
|
||||
|
||||
// minor version 2
|
||||
var mver = blob.read_shift(2, 'u');
|
||||
|
||||
return [blob.read_shift(2,'u'), mver];
|
||||
}
|
||||
function check_shifts(blob, mver) {
|
||||
var shift = 0x09;
|
||||
|
||||
// Byte Order
|
||||
blob.chk('feff', 'Byte Order: ');
|
||||
|
||||
// Sector Shift
|
||||
switch((shift = blob.read_shift(2))) {
|
||||
case 0x09: if(mver !== 3) throw 'MajorVersion/SectorShift Mismatch'; break;
|
||||
case 0x0c: if(mver !== 4) throw 'MajorVersion/SectorShift Mismatch'; break;
|
||||
default: throw 'Sector Shift: Expected 9 or 12 saw ' + shift;
|
||||
}
|
||||
|
||||
// Mini Sector Shift
|
||||
blob.chk('0600', 'Mini Sector Shift: ');
|
||||
|
||||
// Reserved
|
||||
blob.chk('000000000000', 'Reserved: ');
|
||||
}
|
||||
|
||||
/** Break the file up into sectors */
|
||||
function sectorify(file, ssz) {
|
||||
var nsectors = Math.ceil(file.length/ssz)-1;
|
||||
var sectors = new Array(nsectors);
|
||||
for(var i=1; i < nsectors; ++i) sectors[i-1] = file.slice(i*ssz,(i+1)*ssz);
|
||||
sectors[nsectors-1] = file.slice(nsectors*ssz);
|
||||
return sectors;
|
||||
}
|
||||
|
||||
/* [MS-CFB] 2.6.4 Red-Black Tree */
|
||||
function build_full_paths(FI, FPD, FP, Paths) {
|
||||
var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length;
|
||||
var dad = new Array(pl), q = new Array(pl);
|
||||
|
||||
for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; }
|
||||
|
||||
for(; j < q.length; ++j) {
|
||||
i = q[j];
|
||||
L = FI[i].L; R = FI[i].R; C = FI[i].C;
|
||||
if(dad[i] === i) {
|
||||
if(L !== -1 /*NOSTREAM*/ && dad[L] !== L) dad[i] = dad[L];
|
||||
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
|
||||
}
|
||||
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
|
||||
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
|
||||
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
|
||||
}
|
||||
for(i=1; i !== pl; ++i) if(dad[i] === i) {
|
||||
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
|
||||
else if(L !== -1 && dad[L] !== L) dad[i] = dad[L];
|
||||
}
|
||||
|
||||
for(i=1; i < pl; ++i) {
|
||||
if(FI[i].type === 0 /* unknown */) continue;
|
||||
j = dad[i];
|
||||
if(j === 0) FP[i] = FP[0] + "/" + FP[i];
|
||||
else while(j !== 0) {
|
||||
FP[i] = FP[j] + "/" + FP[i];
|
||||
j = dad[j];
|
||||
}
|
||||
dad[i] = 0;
|
||||
}
|
||||
|
||||
FP[0] += "/";
|
||||
for(i=1; i < pl; ++i) {
|
||||
if(FI[i].type !== 2 /* stream */) FP[i] += "/";
|
||||
FPD[FP[i]] = FI[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* [MS-CFB] 2.6.4 */
|
||||
function make_find_path(FullPaths, Paths, FileIndex, files, root_name) {
|
||||
var UCFullPaths = new Array(FullPaths.length);
|
||||
var UCPaths = new Array(Paths.length), i;
|
||||
for(i = 0; i < FullPaths.length; ++i) UCFullPaths[i] = FullPaths[i].toUpperCase().replace(chr0,'').replace(chr1,'!');
|
||||
for(i = 0; i < Paths.length; ++i) UCPaths[i] = Paths[i].toUpperCase().replace(chr0,'').replace(chr1,'!');
|
||||
return function find_path(path) {
|
||||
var k;
|
||||
if(path.charCodeAt(0) === 47 /* "/" */) { k=true; path = root_name + path; }
|
||||
else k = path.indexOf("/") !== -1;
|
||||
var UCPath = path.toUpperCase().replace(chr0,'').replace(chr1,'!');
|
||||
var w = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath);
|
||||
if(w === -1) return null;
|
||||
return k === true ? FileIndex[w] : files[Paths[w]];
|
||||
};
|
||||
}
|
||||
|
||||
/** Chase down the rest of the DIFAT chain to build a comprehensive list
|
||||
DIFAT chains by storing the next sector number as the last 32 bytes */
|
||||
function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) {
|
||||
var q;
|
||||
if(idx === ENDOFCHAIN) {
|
||||
if(cnt !== 0) throw "DIFAT chain shorter than expected";
|
||||
} else if(idx !== -1 /*FREESECT*/) {
|
||||
var sector = sectors[idx], m = (ssz>>>2)-1;
|
||||
for(var i = 0; i < m; ++i) {
|
||||
if((q = __readInt32LE(sector,i*4)) === ENDOFCHAIN) break;
|
||||
fat_addrs.push(q);
|
||||
}
|
||||
sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs);
|
||||
}
|
||||
}
|
||||
|
||||
/** Follow the linked list of sectors for a given starting point */
|
||||
function get_sector_list(sectors, start, fat_addrs, ssz, chkd) {
|
||||
var sl = sectors.length;
|
||||
var buf, buf_chain;
|
||||
if(!chkd) chkd = new Array(sl);
|
||||
var modulus = ssz - 1, j, jj;
|
||||
buf = [];
|
||||
buf_chain = [];
|
||||
for(j=start; j>=0;) {
|
||||
chkd[j] = true;
|
||||
buf[buf.length] = j;
|
||||
buf_chain.push(sectors[j]);
|
||||
var addr = fat_addrs[Math.floor(j*4/ssz)];
|
||||
jj = ((j*4) & modulus);
|
||||
if(ssz < 4 + jj) throw "FAT boundary crossed: " + j + " 4 "+ssz;
|
||||
j = __readInt32LE(sectors[addr], jj);
|
||||
}
|
||||
return {nodes: buf, data:__toBuffer([buf_chain])};
|
||||
}
|
||||
|
||||
/** Chase down the sector linked lists */
|
||||
function make_sector_list(sectors, dir_start, fat_addrs, ssz) {
|
||||
var sl = sectors.length, sector_list = new Array(sl);
|
||||
var chkd = new Array(sl), buf, buf_chain;
|
||||
var modulus = ssz - 1, i, j, k, jj;
|
||||
for(i=0; i < sl; ++i) {
|
||||
buf = [];
|
||||
k = (i + dir_start); if(k >= sl) k-=sl;
|
||||
if(chkd[k] === true) continue;
|
||||
buf_chain = [];
|
||||
for(j=k; j>=0;) {
|
||||
chkd[j] = true;
|
||||
buf[buf.length] = j;
|
||||
buf_chain.push(sectors[j]);
|
||||
var addr = fat_addrs[Math.floor(j*4/ssz)];
|
||||
jj = ((j*4) & modulus);
|
||||
if(ssz < 4 + jj) throw "FAT boundary crossed: " + j + " 4 "+ssz;
|
||||
j = __readInt32LE(sectors[addr], jj);
|
||||
}
|
||||
sector_list[k] = {nodes: buf, data:__toBuffer([buf_chain])};
|
||||
}
|
||||
return sector_list;
|
||||
}
|
||||
|
||||
/* [MS-CFB] 2.6.1 Compound File Directory Entry */
|
||||
function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex) {
|
||||
var blob;
|
||||
var minifat_store = 0, pl = (Paths.length?2:0);
|
||||
var sector = sector_list[dir_start].data;
|
||||
var i = 0, namelen = 0, name, o, ctime, mtime;
|
||||
for(; i < sector.length; i+= 128) {
|
||||
blob = sector.slice(i, i+128);
|
||||
prep_blob(blob, 64);
|
||||
namelen = blob.read_shift(2);
|
||||
if(namelen === 0) continue;
|
||||
name = __utf16le(blob,0,namelen-pl);
|
||||
Paths.push(name);
|
||||
o = {
|
||||
name: name,
|
||||
type: blob.read_shift(1),
|
||||
color: blob.read_shift(1),
|
||||
L: blob.read_shift(4, 'i'),
|
||||
R: blob.read_shift(4, 'i'),
|
||||
C: blob.read_shift(4, 'i'),
|
||||
clsid: blob.read_shift(16),
|
||||
state: blob.read_shift(4, 'i')
|
||||
};
|
||||
ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2);
|
||||
if(ctime !== 0) {
|
||||
o.ctime = ctime; o.ct = read_date(blob, blob.l-8);
|
||||
}
|
||||
mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2);
|
||||
if(mtime !== 0) {
|
||||
o.mtime = mtime; o.mt = read_date(blob, blob.l-8);
|
||||
}
|
||||
o.start = blob.read_shift(4, 'i');
|
||||
o.size = blob.read_shift(4, 'i');
|
||||
if(o.type === 5) { /* root */
|
||||
minifat_store = o.start;
|
||||
if(nmfs > 0 && minifat_store !== ENDOFCHAIN) sector_list[minifat_store].name = "!StreamData";
|
||||
/*minifat_size = o.size;*/
|
||||
} else if(o.size >= 4096 /* MSCSZ */) {
|
||||
o.storage = 'fat';
|
||||
if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz);
|
||||
sector_list[o.start].name = o.name;
|
||||
o.content = sector_list[o.start].data.slice(0,o.size);
|
||||
prep_blob(o.content, 0);
|
||||
} else {
|
||||
o.storage = 'minifat';
|
||||
if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN) {
|
||||
o.content = sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size);
|
||||
prep_blob(o.content, 0);
|
||||
}
|
||||
}
|
||||
files[name] = o;
|
||||
FileIndex.push(o);
|
||||
}
|
||||
}
|
||||
|
||||
function read_date(blob, offset) {
|
||||
return new Date(( ( (__readUInt32LE(blob,offset+4)/1e7)*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7 ) - 11644473600)*1000);
|
||||
}
|
||||
|
||||
var fs;
|
||||
function readFileSync(filename, options) {
|
||||
if(fs === undefined) fs = require('fs');
|
||||
return parse(fs.readFileSync(filename), options);
|
||||
}
|
||||
|
||||
function readSync(blob, options) {
|
||||
switch(options !== undefined && options.type !== undefined ? options.type : "base64") {
|
||||
case "file": return readFileSync(blob, options);
|
||||
case "base64": return parse(s2a(Base64.decode(blob)), options);
|
||||
case "binary": return parse(s2a(blob), options);
|
||||
}
|
||||
return parse(blob);
|
||||
}
|
||||
|
||||
/** CFB Constants */
|
||||
var MSSZ = 64; /* Mini Sector Size = 1<<6 */
|
||||
//var MSCSZ = 4096; /* Mini Stream Cutoff Size */
|
||||
/* 2.1 Compound File Sector Numbers and Types */
|
||||
var ENDOFCHAIN = -2;
|
||||
/* 2.2 Compound File Header */
|
||||
var HEADER_SIGNATURE = 'd0cf11e0a1b11ae1';
|
||||
var HEADER_CLSID = '00000000000000000000000000000000';
|
||||
var consts = {
|
||||
/* 2.1 Compund File Sector Numbers and Types */
|
||||
MAXREGSECT: -6,
|
||||
DIFSECT: -4,
|
||||
FATSECT: -3,
|
||||
ENDOFCHAIN: ENDOFCHAIN,
|
||||
FREESECT: -1,
|
||||
/* 2.2 Compound File Header */
|
||||
HEADER_SIGNATURE: HEADER_SIGNATURE,
|
||||
HEADER_MINOR_VERSION: '3e00',
|
||||
MAXREGSID: -6,
|
||||
NOSTREAM: -1,
|
||||
HEADER_CLSID: HEADER_CLSID,
|
||||
/* 2.6.1 Compound File Directory Entry */
|
||||
EntryTypes: ['unknown','storage','stream','lockbytes','property','root']
|
||||
};
|
||||
|
||||
exports.read = readSync;
|
||||
exports.parse = parse;
|
||||
exports.utils = {
|
||||
ReadShift: ReadShift,
|
||||
CheckField: CheckField,
|
||||
prep_blob: prep_blob,
|
||||
bconcat: bconcat,
|
||||
consts: consts
|
||||
};
|
||||
|
||||
return exports;
|
||||
})();
|
||||
|
||||
if(typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO_NOT_EXPORT_CFB === 'undefined') { module.exports = CFB; }
|
@ -42,4 +42,3 @@ function cc2str(arr) {
|
||||
return o;
|
||||
}
|
||||
|
||||
var has_buf = (typeof Buffer !== 'undefined');
|
||||
|
@ -1,4 +1,4 @@
|
||||
var attregexg=/\b[\w:]+=["'][^"]*['"]/g;
|
||||
var attregexg=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
|
||||
var tagregex=/<[^>]*>/g;
|
||||
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
|
||||
function parsexmltag(tag, skip_root) {
|
||||
@ -31,17 +31,27 @@ var rencoding = evert(encodings);
|
||||
var rencstr = "&<>'\"".split("");
|
||||
|
||||
// TODO: CP remap (need to read file version to determine OS)
|
||||
var encregex = /&[a-z]*;/g, coderegex = /_x([\da-fA-F]+)_/g;
|
||||
function unescapexml(text){
|
||||
var s = text + '';
|
||||
return s.replace(encregex, function($$) { return encodings[$$]; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
|
||||
}
|
||||
var unescapexml = (function() {
|
||||
var encregex = /&[a-z]*;/g, coderegex = /_x([\da-fA-F]+)_/g;
|
||||
return function unescapexml(text){
|
||||
var s = text + '';
|
||||
return s.replace(encregex, function($$) { return encodings[$$]; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
|
||||
};
|
||||
})();
|
||||
|
||||
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
|
||||
function escapexml(text){
|
||||
var s = text + '';
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).substr(-4) + "_";});
|
||||
}
|
||||
|
||||
/* TODO: handle codepages */
|
||||
var xlml_fixstr = (function() {
|
||||
var entregex = /&#(\d+);/g;
|
||||
function entrepl($$,$1) { return String.fromCharCode(parseInt($1,10)); }
|
||||
return function xlml_fixstr(str) { return str.replace(entregex,entrepl); };
|
||||
})();
|
||||
|
||||
function parsexmlbool(value, tag) {
|
||||
switch(value) {
|
||||
case '1': case 'true': case 'TRUE': return true;
|
||||
@ -158,3 +168,4 @@ XMLNS.main = [
|
||||
'http://schemas.microsoft.com/office/excel/2006/main',
|
||||
'http://schemas.microsoft.com/office/excel/2006/2'
|
||||
];
|
||||
|
||||
|
@ -18,16 +18,39 @@ function readIEEE754(buf, idx, isLE, nl, ml) {
|
||||
|
||||
var __toBuffer, ___toBuffer;
|
||||
__toBuffer = ___toBuffer = function toBuffer_(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; };
|
||||
var __utf16le, ___utf16le;
|
||||
__utf16le = ___utf16le = function utf16le_(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join(""); };
|
||||
var __hexlify, ___hexlify;
|
||||
__hexlify = ___hexlify = function hexlify_(b,s,l) { return b.slice(s,(s+l)).map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); };
|
||||
var __utf8, ___utf8;
|
||||
__utf8 = ___utf8 = function(b,s,e) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
|
||||
var __lpstr, ___lpstr;
|
||||
__lpstr = ___lpstr = function lpstr_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
|
||||
var __lpwstr, ___lpwstr;
|
||||
__lpwstr = ___lpwstr = function lpwstr_(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
|
||||
var __double, ___double;
|
||||
__double = ___double = function(b, idx) { return readIEEE754(b, idx);};
|
||||
|
||||
var is_buf = function is_buf_a(a) { return Array.isArray(a); };
|
||||
if(has_buf) {
|
||||
__utf16le = function utf16le_b(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e); };
|
||||
__hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
|
||||
__lpstr = function lpstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
|
||||
__lpwstr = function lpwstr_b(b,i) { if(!Buffer.isBuffer(b)) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
|
||||
__utf8 = function utf8_b(s,e) { return this.toString('utf8',s,e); };
|
||||
__toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);};
|
||||
bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); };
|
||||
__double = function double_(b,i) { if(Buffer.isBuffer(b)) return b.readDoubleLE(i); return ___double(b,i); };
|
||||
is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); };
|
||||
}
|
||||
|
||||
/* from js-xls */
|
||||
if(typeof cptable !== 'undefined') {
|
||||
__utf16le = function(b,s,e) { return cptable.utils.decode(1200, b.slice(s,e)); };
|
||||
__utf8 = function(b,s,e) { return cptable.utils.decode(65001, b.slice(s,e)); };
|
||||
__lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";};
|
||||
__lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";};
|
||||
}
|
||||
|
||||
var __readUInt8 = function(b, idx) { return b[idx]; };
|
||||
var __readUInt16LE = function(b, idx) { return b[idx+1]*(1<<8)+b[idx]; };
|
||||
@ -35,20 +58,70 @@ var __readInt16LE = function(b, idx) { var u = b[idx+1]*(1<<8)+b[idx]; return (u
|
||||
var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
|
||||
var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
|
||||
|
||||
var ___unhexlify = function(s) { return s.match(/../g).map(function(x) { return parseInt(x,16);}); };
|
||||
var __unhexlify = typeof Buffer !== "undefined" ? function(s) { return Buffer.isBuffer(s) ? new Buffer(s, 'hex') : ___unhexlify(s); } : ___unhexlify;
|
||||
|
||||
function ReadShift(size, t) {
|
||||
var o="", oo=[], w, vv, i, loc;
|
||||
if(t === 'dbcs') {
|
||||
loc = this.l;
|
||||
if(has_buf && Buffer.isBuffer(this)) o = this.slice(this.l, this.l+2*size).toString("utf16le");
|
||||
else for(i = 0; i != size; ++i) { o+=String.fromCharCode(__readUInt16LE(this, loc)); loc+=2; }
|
||||
size *= 2;
|
||||
} else switch(size) {
|
||||
case 1: o = __readUInt8(this, this.l); break;
|
||||
case 2: o = (t === 'i' ? __readInt16LE : __readUInt16LE)(this, this.l); break;
|
||||
case 4: o = __readUInt32LE(this, this.l); break;
|
||||
case 8: if(t === 'f') { o = __double(this, this.l); break; }
|
||||
}
|
||||
var o="", oI, oR, oo=[], w, vv, i, loc;
|
||||
switch(t) {
|
||||
case 'dbcs':
|
||||
loc = this.l;
|
||||
if(has_buf && Buffer.isBuffer(this)) o = this.slice(this.l, this.l+2*size).toString("utf16le");
|
||||
else for(i = 0; i != size; ++i) { o+=String.fromCharCode(__readUInt16LE(this, loc)); loc+=2; }
|
||||
size *= 2;
|
||||
break;
|
||||
|
||||
case 'utf8': o = __utf8(this, this.l, this.l + size); break;
|
||||
case 'utf16le': size *= 2; o = __utf16le(this, this.l, this.l + size); break;
|
||||
|
||||
/* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */
|
||||
case 'lpstr': o = __lpstr(this, this.l); size = 5 + o.length; break;
|
||||
/* [MS-OLEDS] 2.1.5 LengthPrefixedUnicodeString */
|
||||
case 'lpwstr': o = __lpwstr(this, this.l); size = 5 + o.length; if(o[o.length-1] == '\u0000') size += 2; break;
|
||||
|
||||
case 'cstr': size = 0; o = "";
|
||||
while((w=__readUInt8(this, this.l + size++))!==0) oo.push(_getchar(w));
|
||||
o = oo.join(""); break;
|
||||
case 'wstr': size = 0; o = "";
|
||||
while((w=__readUInt16LE(this,this.l +size))!==0){oo.push(_getchar(w));size+=2;}
|
||||
size+=2; o = oo.join(""); break;
|
||||
|
||||
/* sbcs and dbcs support continue records in the SST way TODO codepages */
|
||||
case 'dbcs-cont': o = ""; loc = this.l;
|
||||
for(i = 0; i != size; ++i) {
|
||||
if(this.lens && this.lens.indexOf(loc) !== -1) {
|
||||
w = __readUInt8(this, loc);
|
||||
this.l = loc + 1;
|
||||
vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont');
|
||||
return oo.join("") + vv;
|
||||
}
|
||||
oo.push(_getchar(__readUInt16LE(this, loc)));
|
||||
loc+=2;
|
||||
} o = oo.join(""); size *= 2; break;
|
||||
|
||||
case 'sbcs-cont': o = ""; loc = this.l;
|
||||
for(i = 0; i != size; ++i) {
|
||||
if(this.lens && this.lens.indexOf(loc) !== -1) {
|
||||
w = __readUInt8(this, loc);
|
||||
this.l = loc + 1;
|
||||
vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont');
|
||||
return oo.join("") + vv;
|
||||
}
|
||||
oo.push(_getchar(__readUInt8(this, loc)));
|
||||
loc+=1;
|
||||
} o = oo.join(""); break;
|
||||
|
||||
default:
|
||||
switch(size) {
|
||||
case 1: oI = __readUInt8(this, this.l); this.l++; return oI;
|
||||
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;
|
||||
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;
|
||||
}}
|
||||
this.l+=size; return o;
|
||||
}
|
||||
|
||||
@ -69,9 +142,16 @@ function WriteShift(t, val, f) {
|
||||
this.l += size; return this;
|
||||
}
|
||||
|
||||
function CheckField(hexstr, fld) {
|
||||
var m = __hexlify(this,this.l,hexstr.length>>1);
|
||||
if(m !== hexstr) throw fld + 'Expected ' + hexstr + ' saw ' + m;
|
||||
this.l += hexstr.length>>1;
|
||||
}
|
||||
|
||||
function prep_blob(blob, pos) {
|
||||
blob.l = pos;
|
||||
blob.read_shift = ReadShift;
|
||||
blob.chk = CheckField;
|
||||
blob.write_shift = WriteShift;
|
||||
}
|
||||
|
||||
@ -80,7 +160,7 @@ function parsenoop(blob, length) { blob.l += length; }
|
||||
function writenoop(blob, length) { blob.l += length; }
|
||||
|
||||
function new_buf(sz) {
|
||||
var o = has_buf ? new Buffer(sz) : new Array(sz);
|
||||
var o = new_raw_buf(sz);
|
||||
prep_blob(o, 0);
|
||||
return o;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ function recordhopper(data, cb, opts) {
|
||||
while(data.l < data.length) {
|
||||
var RT = data.read_shift(1);
|
||||
if(RT & 0x80) RT = (RT & 0x7F) + ((data.read_shift(1) & 0x7F)<<7);
|
||||
var R = RecordEnum[RT] || RecordEnum[0xFFFF];
|
||||
var R = XLSBRecordEnum[RT] || XLSBRecordEnum[0xFFFF];
|
||||
tmpbyte = data.read_shift(1);
|
||||
length = tmpbyte & 0x7F;
|
||||
for(cntbyte = 1; cntbyte <4 && (tmpbyte & 0x80); ++cntbyte) length += ((tmpbyte = data.read_shift(1)) & 0x7F)<<(7*cntbyte);
|
||||
@ -49,7 +49,7 @@ function buf_array() {
|
||||
|
||||
function write_record(ba, type, payload, length) {
|
||||
var t = evert_RE[type], l;
|
||||
if(!length) length = RecordEnum[t].p || (payload||[]).length || 0;
|
||||
if(!length) length = XLSBRecordEnum[t].p || (payload||[]).length || 0;
|
||||
l = 1 + (t >= 0x80 ? 1 : 0) + 1 + length;
|
||||
if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l;
|
||||
var o = ba.next(l);
|
||||
|
21
bits/25_cellutils.js
Normal file
21
bits/25_cellutils.js
Normal file
@ -0,0 +1,21 @@
|
||||
/* XLS ranges enforced */
|
||||
function shift_cell_xls(cell, tgt) {
|
||||
if(tgt.s) {
|
||||
if(cell.cRel) cell.c += tgt.s.c;
|
||||
if(cell.rRel) cell.r += tgt.s.r;
|
||||
} else {
|
||||
cell.c += tgt.c;
|
||||
cell.r += tgt.r;
|
||||
}
|
||||
cell.cRel = cell.rRel = 0;
|
||||
while(cell.c >= 0x100) cell.c -= 0x100;
|
||||
while(cell.r >= 0x10000) cell.r -= 0x10000;
|
||||
return cell;
|
||||
}
|
||||
|
||||
function shift_range_xls(cell, range) {
|
||||
cell.s = shift_cell_xls(cell.s, range.s);
|
||||
cell.e = shift_cell_xls(cell.e, range.s);
|
||||
return cell;
|
||||
}
|
||||
|
35
bits/26_crypto.js
Normal file
35
bits/26_crypto.js
Normal file
@ -0,0 +1,35 @@
|
||||
var OFFCRYPTO = {};
|
||||
var make_offcrypto = function(O, _crypto) {
|
||||
var crypto;
|
||||
if(typeof _crypto !== 'undefined') crypto = _crypto;
|
||||
else if(typeof require !== 'undefined') {
|
||||
try { crypto = require('cry'+'pto'); }
|
||||
catch(e) { crypto = null; }
|
||||
}
|
||||
|
||||
O.rc4 = function(key, data) {
|
||||
var S = new Array(256);
|
||||
var c = 0, i = 0, j = 0, t = 0;
|
||||
for(i = 0; i != 256; ++i) S[i] = i;
|
||||
for(i = 0; i != 256; ++i) {
|
||||
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);
|
||||
for(c = 0; c != data.length; ++c) {
|
||||
i = (i + 1)&255;
|
||||
j = (j + S[i])%256;
|
||||
t = S[i]; S[i] = S[j]; S[j] = t;
|
||||
out[c] = (data[c] ^ S[(S[i]+S[j])&255]);
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
if(crypto) {
|
||||
O.md5 = function(hex) { return crypto.createHash('md5').update(hex).digest('hex'); };
|
||||
} else {
|
||||
O.md5 = function(hex) { throw "unimplemented"; };
|
||||
}
|
||||
};
|
||||
make_offcrypto(OFFCRYPTO, typeof crypto !== "undefined" ? crypto : undefined);
|
||||
|
@ -33,14 +33,14 @@ function write_RichStr(str, o) {
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.9 */
|
||||
function parse_Cell(data) {
|
||||
function parse_XLSBCell(data) {
|
||||
var col = data.read_shift(4);
|
||||
var iStyleRef = data.read_shift(2);
|
||||
iStyleRef += data.read_shift(1) <<16;
|
||||
var fPhShow = data.read_shift(1);
|
||||
return { c:col, iStyleRef: iStyleRef };
|
||||
}
|
||||
function write_Cell(cell, o) {
|
||||
function write_XLSBCell(cell, o) {
|
||||
if(o == null) o = new_buf(8);
|
||||
o.write_shift(-4, cell.c);
|
||||
o.write_shift(3, cell.iStyleRef === undefined ? cell.iStyleRef : cell.s);
|
||||
@ -50,7 +50,7 @@ function write_Cell(cell, o) {
|
||||
|
||||
|
||||
/* [MS-XLSB] 2.5.21 */
|
||||
function parse_CodeName (data, length) { return parse_XLWideString(data, length); }
|
||||
function parse_XLSBCodeName (data, length) { return parse_XLWideString(data, length); }
|
||||
|
||||
/* [MS-XLSB] 2.5.166 */
|
||||
function parse_XLNullableWideString(data) {
|
||||
@ -82,11 +82,12 @@ var write_RelID = write_XLNullableWideString;
|
||||
|
||||
|
||||
/* [MS-XLSB] 2.5.122 */
|
||||
/* [MS-XLS] 2.5.217 */
|
||||
function parse_RkNumber(data) {
|
||||
var b = data.slice(data.l, data.l+4);
|
||||
var fX100 = b[0] & 1, fInt = b[0] & 2;
|
||||
data.l+=4;
|
||||
b[0] &= 0xFC;
|
||||
b[0] &= 0xFC; // b[0] &= ~3;
|
||||
var RK = fInt === 0 ? __double([0,0,0,0,b[0],b[1],b[2],b[3]],0) : __readInt32LE(b,0)>>2;
|
||||
return fX100 ? RK/100 : RK;
|
||||
}
|
||||
@ -111,6 +112,7 @@ function write_UncheckedRfX(r, o) {
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.5.171 */
|
||||
/* [MS-XLS] 2.5.342 */
|
||||
function parse_Xnum(data, length) { return data.read_shift(8, 'f'); }
|
||||
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, 'f', data); }
|
||||
|
||||
|
265
bits/29_xlsenum.js
Normal file
265
bits/29_xlsenum.js
Normal file
@ -0,0 +1,265 @@
|
||||
/* [MS-OLEPS] 2.2 PropertyType */
|
||||
{
|
||||
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_BOOL = 0x000B;
|
||||
var VT_VARIANT = 0x000C;
|
||||
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_UI8 = 0x0015;
|
||||
var VT_INT = 0x0016;
|
||||
var VT_UINT = 0x0017;
|
||||
var VT_LPSTR = 0x001E;
|
||||
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_CF = 0x0047;
|
||||
var VT_CLSID = 0x0048;
|
||||
var VT_VERSIONED_STREAM = 0x0049;
|
||||
var VT_VECTOR = 0x1000;
|
||||
var VT_ARRAY = 0x2000;
|
||||
|
||||
var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
|
||||
var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString
|
||||
var VT_CUSTOM = [VT_STRING, VT_USTR];
|
||||
}
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */
|
||||
var DocSummaryPIDDSI = {
|
||||
0x01: { n: 'CodePage', t: VT_I2 },
|
||||
0x02: { n: 'Category', t: VT_STRING },
|
||||
0x03: { n: 'PresentationFormat', t: VT_STRING },
|
||||
0x04: { n: 'ByteCount', t: VT_I4 },
|
||||
0x05: { n: 'LineCount', t: VT_I4 },
|
||||
0x06: { n: 'ParagraphCount', t: VT_I4 },
|
||||
0x07: { n: 'SlideCount', t: VT_I4 },
|
||||
0x08: { n: 'NoteCount', t: VT_I4 },
|
||||
0x09: { n: 'HiddenCount', t: VT_I4 },
|
||||
0x0a: { n: 'MultimediaClipCount', t: VT_I4 },
|
||||
0x0b: { n: 'Scale', t: VT_BOOL },
|
||||
0x0c: { n: 'HeadingPair', t: VT_VECTOR | VT_VARIANT },
|
||||
0x0d: { n: 'DocParts', t: VT_VECTOR | VT_LPSTR },
|
||||
0x0e: { n: 'Manager', t: VT_STRING },
|
||||
0x0f: { n: 'Company', t: VT_STRING },
|
||||
0x10: { n: 'LinksDirty', t: VT_BOOL },
|
||||
0x11: { n: 'CharacterCount', t: VT_I4 },
|
||||
0x13: { n: 'SharedDoc', t: VT_BOOL },
|
||||
0x16: { n: 'HLinksChanged', t: VT_BOOL },
|
||||
0x17: { n: 'AppVersion', t: VT_I4, p: 'version' },
|
||||
0x1A: { n: 'ContentType', t: VT_STRING },
|
||||
0x1B: { n: 'ContentStatus', t: VT_STRING },
|
||||
0x1C: { n: 'Language', t: VT_STRING },
|
||||
0x1D: { n: 'Version', t: VT_STRING },
|
||||
0xFF: {}
|
||||
};
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.2.1.1 Summary Information Property Set PIDSI */
|
||||
var SummaryPIDSI = {
|
||||
0x01: { n: 'CodePage', t: VT_I2 },
|
||||
0x02: { n: 'Title', t: VT_STRING },
|
||||
0x03: { n: 'Subject', t: VT_STRING },
|
||||
0x04: { n: 'Author', t: VT_STRING },
|
||||
0x05: { n: 'Keywords', t: VT_STRING },
|
||||
0x06: { n: 'Comments', t: VT_STRING },
|
||||
0x07: { n: 'Template', t: VT_STRING },
|
||||
0x08: { n: 'LastAuthor', t: VT_STRING },
|
||||
0x09: { n: 'RevNumber', t: VT_STRING },
|
||||
0x0A: { n: 'EditTime', t: VT_FILETIME },
|
||||
0x0B: { n: 'LastPrinted', t: VT_FILETIME },
|
||||
0x0C: { n: 'CreatedDate', t: VT_FILETIME },
|
||||
0x0D: { n: 'ModifiedDate', t: VT_FILETIME },
|
||||
0x0E: { n: 'PageCount', t: VT_I4 },
|
||||
0x0F: { n: 'WordCount', t: VT_I4 },
|
||||
0x10: { n: 'CharCount', t: VT_I4 },
|
||||
0x11: { n: 'Thumbnail', t: VT_CF },
|
||||
0x12: { n: 'ApplicationName', t: VT_LPSTR },
|
||||
0x13: { n: 'DocumentSecurity', t: VT_I4 },
|
||||
0xFF: {}
|
||||
};
|
||||
|
||||
/* [MS-OLEPS] 2.18 */
|
||||
var SpecialProperties = {
|
||||
0x80000000: { n: 'Locale', t: VT_UI4 },
|
||||
0x80000003: { n: 'Behavior', t: VT_UI4 },
|
||||
0x72627262: {}
|
||||
};
|
||||
|
||||
(function() {
|
||||
for(var y in SpecialProperties) if(SpecialProperties.hasOwnProperty(y))
|
||||
DocSummaryPIDDSI[y] = SummaryPIDSI[y] = SpecialProperties[y];
|
||||
})();
|
||||
|
||||
/* [MS-XLS] 2.4.63 Country/Region codes */
|
||||
var CountryEnum = {
|
||||
0x0001: "US", // United States
|
||||
0x0002: "CA", // Canada
|
||||
0x0003: "", // Latin America (except Brazil)
|
||||
0x0007: "RU", // Russia
|
||||
0x0014: "EG", // Egypt
|
||||
0x001E: "GR", // Greece
|
||||
0x001F: "NL", // Netherlands
|
||||
0x0020: "BE", // Belgium
|
||||
0x0021: "FR", // France
|
||||
0x0022: "ES", // Spain
|
||||
0x0024: "HU", // Hungary
|
||||
0x0027: "IT", // Italy
|
||||
0x0029: "CH", // Switzerland
|
||||
0x002B: "AT", // Austria
|
||||
0x002C: "GB", // United Kingdom
|
||||
0x002D: "DK", // Denmark
|
||||
0x002E: "SE", // Sweden
|
||||
0x002F: "NO", // Norway
|
||||
0x0030: "PL", // Poland
|
||||
0x0031: "DE", // Germany
|
||||
0x0034: "MX", // Mexico
|
||||
0x0037: "BR", // Brazil
|
||||
0x003d: "AU", // Australia
|
||||
0x0040: "NZ", // New Zealand
|
||||
0x0042: "TH", // Thailand
|
||||
0x0051: "JP", // Japan
|
||||
0x0052: "KR", // Korea
|
||||
0x0054: "VN", // Viet Nam
|
||||
0x0056: "CN", // China
|
||||
0x005A: "TR", // Turkey
|
||||
0x0069: "JS", // Ramastan
|
||||
0x00D5: "DZ", // Algeria
|
||||
0x00D8: "MA", // Morocco
|
||||
0x00DA: "LY", // Libya
|
||||
0x015F: "PT", // Portugal
|
||||
0x0162: "IS", // Iceland
|
||||
0x0166: "FI", // Finland
|
||||
0x01A4: "CZ", // Czech Republic
|
||||
0x0376: "TW", // Taiwan
|
||||
0x03C1: "LB", // Lebanon
|
||||
0x03C2: "JO", // Jordan
|
||||
0x03C3: "SY", // Syria
|
||||
0x03C4: "IQ", // Iraq
|
||||
0x03C5: "KW", // Kuwait
|
||||
0x03C6: "SA", // Saudi Arabia
|
||||
0x03CB: "AE", // United Arab Emirates
|
||||
0x03CC: "IL", // Israel
|
||||
0x03CE: "QA", // Qatar
|
||||
0x03D5: "IR", // Iran
|
||||
0xFFFF: "US" // United States
|
||||
};
|
||||
|
||||
/* [MS-XLS] 2.5.127 */
|
||||
var XLSFillPattern = [
|
||||
null,
|
||||
'solid',
|
||||
'mediumGray',
|
||||
'darkGray',
|
||||
'lightGray',
|
||||
'darkHorizontal',
|
||||
'darkVertical',
|
||||
'darkDown',
|
||||
'darkUp',
|
||||
'darkGrid',
|
||||
'darkTrellis',
|
||||
'lightHorizontal',
|
||||
'lightVertical',
|
||||
'lightDown',
|
||||
'lightUp',
|
||||
'lightGrid',
|
||||
'lightTrellis',
|
||||
'gray125',
|
||||
'gray0625'
|
||||
];
|
||||
|
||||
function rgbify(arr) { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); }
|
||||
|
||||
/* [MS-XLS] 2.5.161 */
|
||||
var XLSIcv = rgbify([
|
||||
/* Color Constants */
|
||||
0x000000,
|
||||
0xFFFFFF,
|
||||
0xFF0000,
|
||||
0x00FF00,
|
||||
0x0000FF,
|
||||
0xFFFF00,
|
||||
0xFF00FF,
|
||||
0x00FFFF,
|
||||
|
||||
/* Defaults */
|
||||
0x000000,
|
||||
0xFFFFFF,
|
||||
0xFF0000,
|
||||
0x00FF00,
|
||||
0x0000FF,
|
||||
0xFFFF00,
|
||||
0xFF00FF,
|
||||
0x00FFFF,
|
||||
|
||||
0x800000,
|
||||
0x008000,
|
||||
0x000080,
|
||||
0x808000,
|
||||
0x800080,
|
||||
0x008080,
|
||||
0xC0C0C0,
|
||||
0x808080,
|
||||
0x9999FF,
|
||||
0x993366,
|
||||
0xFFFFCC,
|
||||
0xCCFFFF,
|
||||
0x660066,
|
||||
0xFF8080,
|
||||
0x0066CC,
|
||||
0xCCCCFF,
|
||||
|
||||
0x000080,
|
||||
0xFF00FF,
|
||||
0xFFFF00,
|
||||
0x00FFFF,
|
||||
0x800080,
|
||||
0x800000,
|
||||
0x008080,
|
||||
0x0000FF,
|
||||
0x00CCFF,
|
||||
0xCCFFFF,
|
||||
0xCCFFCC,
|
||||
0xFFFF99,
|
||||
0x99CCFF,
|
||||
0xFF99CC,
|
||||
0xCC99FF,
|
||||
0xFFCC99,
|
||||
|
||||
0x3366FF,
|
||||
0x33CCCC,
|
||||
0x99CC00,
|
||||
0xFFCC00,
|
||||
0xFF9900,
|
||||
0xFF6600,
|
||||
0x666699,
|
||||
0x969696,
|
||||
0x003366,
|
||||
0x339966,
|
||||
0x003300,
|
||||
0x333300,
|
||||
0x993300,
|
||||
0x993366,
|
||||
0x333399,
|
||||
0x333333,
|
||||
|
||||
/* Sheet */
|
||||
0xFFFFFF,
|
||||
0x000000
|
||||
]);
|
||||
|
8
bits/36_xlsprops.js
Normal file
8
bits/36_xlsprops.js
Normal file
@ -0,0 +1,8 @@
|
||||
function xlml_set_prop(Props, tag, val) {
|
||||
/* TODO: Normalize the properties */
|
||||
switch(tag) {
|
||||
case 'Description': tag = 'Comments'; break;
|
||||
}
|
||||
Props[tag] = val;
|
||||
}
|
||||
|
440
bits/38_xlstypes.js
Normal file
440
bits/38_xlstypes.js
Normal file
@ -0,0 +1,440 @@
|
||||
/* [MS-DTYP] 2.3.3 FILETIME */
|
||||
/* [MS-OLEDS] 2.1.3 FILETIME (Packet Version) */
|
||||
/* [MS-OLEPS] 2.8 FILETIME (Packet Version) */
|
||||
function parse_FILETIME(blob) {
|
||||
var dwLowDateTime = blob.read_shift(4), dwHighDateTime = blob.read_shift(4);
|
||||
return new Date(((dwHighDateTime/1e7*Math.pow(2,32) + dwLowDateTime/1e7) - 11644473600)*1000).toISOString().replace(/\.000/,"");
|
||||
}
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.1.4 Lpstr */
|
||||
function parse_lpstr(blob, type, pad) {
|
||||
var str = blob.read_shift(0, 'lpstr');
|
||||
if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3;
|
||||
return str;
|
||||
}
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.1.6 Lpwstr */
|
||||
function parse_lpwstr(blob, type, pad) {
|
||||
var str = blob.read_shift(0, 'lpwstr');
|
||||
if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3;
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.1.11 VtString */
|
||||
/* [MS-OSHARED] 2.3.3.1.12 VtUnalignedString */
|
||||
function parse_VtStringBase(blob, stringType, pad) {
|
||||
if(stringType === 0x1F /*VT_LPWSTR*/) return parse_lpwstr(blob);
|
||||
return parse_lpstr(blob, stringType, pad);
|
||||
}
|
||||
|
||||
function parse_VtString(blob, t, pad) { return parse_VtStringBase(blob, t, pad === false ? 0: 4); }
|
||||
function parse_VtUnalignedString(blob, t) { if(!t) throw new Error("dafuq?"); return parse_VtStringBase(blob, t, 0); }
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.1.9 VtVecUnalignedLpstrValue */
|
||||
function parse_VtVecUnalignedLpstrValue(blob) {
|
||||
var length = blob.read_shift(4);
|
||||
var ret = [];
|
||||
for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr');
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.1.10 VtVecUnalignedLpstr */
|
||||
function parse_VtVecUnalignedLpstr(blob) {
|
||||
return parse_VtVecUnalignedLpstrValue(blob);
|
||||
}
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.1.13 VtHeadingPair */
|
||||
function parse_VtHeadingPair(blob) {
|
||||
var headingString = parse_TypedPropertyValue(blob, VT_USTR);
|
||||
var headerParts = parse_TypedPropertyValue(blob, VT_I4);
|
||||
return [headingString, headerParts];
|
||||
}
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.1.14 VtVecHeadingPairValue */
|
||||
function parse_VtVecHeadingPairValue(blob) {
|
||||
var cElements = blob.read_shift(4);
|
||||
var out = [];
|
||||
for(var i = 0; i != cElements / 2; ++i) out.push(parse_VtHeadingPair(blob));
|
||||
return out;
|
||||
}
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.1.15 VtVecHeadingPair */
|
||||
function parse_VtVecHeadingPair(blob) {
|
||||
// NOTE: When invoked, wType & padding were already consumed
|
||||
return parse_VtVecHeadingPairValue(blob);
|
||||
}
|
||||
|
||||
/* [MS-OLEPS] 2.18.1 Dictionary (uses 2.17, 2.16) */
|
||||
function parse_dictionary(blob,CodePage) {
|
||||
var cnt = blob.read_shift(4);
|
||||
var dict = {};
|
||||
for(var j = 0; j != cnt; ++j) {
|
||||
var pid = blob.read_shift(4);
|
||||
var len = blob.read_shift(4);
|
||||
dict[pid] = blob.read_shift(len, (CodePage === 0x4B0 ?'utf16le':'utf8')).replace(chr0,'').replace(chr1,'!');
|
||||
}
|
||||
if(blob.l & 3) blob.l = (blob.l>>2+1)<<2;
|
||||
return dict;
|
||||
}
|
||||
|
||||
/* [MS-OLEPS] 2.9 BLOB */
|
||||
function parse_BLOB(blob) {
|
||||
var size = blob.read_shift(4);
|
||||
var bytes = blob.slice(blob.l,blob.l+size);
|
||||
if(size & 3 > 0) blob.l += (4 - (size & 3)) & 3;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* [MS-OLEPS] 2.11 ClipboardData */
|
||||
function parse_ClipboardData(blob) {
|
||||
// TODO
|
||||
var o = {};
|
||||
o.Size = blob.read_shift(4);
|
||||
//o.Format = blob.read_shift(4);
|
||||
blob.l += o.Size;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-OLEPS] 2.14 Vector and Array Property Types */
|
||||
function parse_VtVector(blob, cb) {
|
||||
/* [MS-OLEPS] 2.14.2 VectorHeader */
|
||||
/* var Length = blob.read_shift(4);
|
||||
var o = [];
|
||||
for(var i = 0; i != Length; ++i) {
|
||||
o.push(cb(blob));
|
||||
}
|
||||
return o;*/
|
||||
}
|
||||
|
||||
/* [MS-OLEPS] 2.15 TypedPropertyValue */
|
||||
function parse_TypedPropertyValue(blob, type, _opts) {
|
||||
var t = blob.read_shift(2), ret, opts = _opts||{};
|
||||
blob.l += 2;
|
||||
if(type !== VT_VARIANT)
|
||||
if(t !== type && VT_CUSTOM.indexOf(type)===-1) throw new Error('Expected type ' + type + ' saw ' + t);
|
||||
switch(type === VT_VARIANT ? t : type) {
|
||||
case 0x02 /*VT_I2*/: ret = blob.read_shift(2, 'i'); if(!opts.raw) blob.l += 2; return ret;
|
||||
case 0x03 /*VT_I4*/: ret = blob.read_shift(4, 'i'); return ret;
|
||||
case 0x0B /*VT_BOOL*/: return blob.read_shift(4) !== 0x0;
|
||||
case 0x13 /*VT_UI4*/: ret = blob.read_shift(4); return ret;
|
||||
case 0x1E /*VT_LPSTR*/: return parse_lpstr(blob, t, 4).replace(chr0,'');
|
||||
case 0x1F /*VT_LPWSTR*/: return parse_lpwstr(blob);
|
||||
case 0x40 /*VT_FILETIME*/: return parse_FILETIME(blob);
|
||||
case 0x41 /*VT_BLOB*/: return parse_BLOB(blob);
|
||||
case 0x47 /*VT_CF*/: return parse_ClipboardData(blob);
|
||||
case 0x50 /*VT_STRING*/: return parse_VtString(blob, t, !opts.raw && 4).replace(chr0,'');
|
||||
case 0x51 /*VT_USTR*/: return parse_VtUnalignedString(blob, t, 4).replace(chr0,'');
|
||||
case 0x100C /*VT_VECTOR|VT_VARIANT*/: return parse_VtVecHeadingPair(blob);
|
||||
case 0x101E /*VT_LPSTR*/: return parse_VtVecUnalignedLpstr(blob);
|
||||
default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + t);
|
||||
}
|
||||
}
|
||||
/* [MS-OLEPS] 2.14.2 VectorHeader */
|
||||
/*function parse_VTVectorVariant(blob) {
|
||||
var Length = blob.read_shift(4);
|
||||
|
||||
if(Length & 1 !== 0) throw new Error("VectorHeader Length=" + Length + " must be even");
|
||||
var o = [];
|
||||
for(var i = 0; i != Length; ++i) {
|
||||
o.push(parse_TypedPropertyValue(blob, VT_VARIANT));
|
||||
}
|
||||
return o;
|
||||
}*/
|
||||
|
||||
/* [MS-OLEPS] 2.20 PropertySet */
|
||||
function parse_PropertySet(blob, PIDSI) {
|
||||
var start_addr = blob.l;
|
||||
var size = blob.read_shift(4);
|
||||
var NumProps = blob.read_shift(4);
|
||||
var Props = [], i = 0;
|
||||
var CodePage = 0;
|
||||
var Dictionary = -1, DictObj;
|
||||
for(i = 0; i != NumProps; ++i) {
|
||||
var PropID = blob.read_shift(4);
|
||||
var Offset = blob.read_shift(4);
|
||||
Props[i] = [PropID, Offset + start_addr];
|
||||
}
|
||||
var PropH = {};
|
||||
for(i = 0; i != NumProps; ++i) {
|
||||
if(blob.l !== Props[i][1]) {
|
||||
var fail = true;
|
||||
if(i>0 && PIDSI) switch(PIDSI[Props[i-1][0]].t) {
|
||||
case 0x02 /*VT_I2*/: if(blob.l +2 === Props[i][1]) { blob.l+=2; fail = false; } break;
|
||||
case 0x50 /*VT_STRING*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
|
||||
case 0x100C /*VT_VECTOR|VT_VARIANT*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
|
||||
}
|
||||
if(!PIDSI && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; }
|
||||
if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i);
|
||||
}
|
||||
if(PIDSI) {
|
||||
var piddsi = PIDSI[Props[i][0]];
|
||||
PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true});
|
||||
if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + String(PropH[piddsi.n] & 0xFFFF);
|
||||
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
|
||||
set_cp(CodePage = PropH[piddsi.n]); break;
|
||||
default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
|
||||
}
|
||||
} else {
|
||||
if(Props[i][0] === 0x1) {
|
||||
CodePage = PropH.CodePage = parse_TypedPropertyValue(blob, VT_I2);
|
||||
set_cp(CodePage);
|
||||
if(Dictionary !== -1) {
|
||||
var oldpos = blob.l;
|
||||
blob.l = Props[Dictionary][1];
|
||||
DictObj = parse_dictionary(blob,CodePage);
|
||||
blob.l = oldpos;
|
||||
}
|
||||
} else if(Props[i][0] === 0) {
|
||||
if(CodePage === 0) { Dictionary = i; blob.l = Props[i+1][1]; continue; }
|
||||
DictObj = parse_dictionary(blob,CodePage);
|
||||
} else {
|
||||
var name = DictObj[Props[i][0]];
|
||||
var val;
|
||||
/* [MS-OSHARED] 2.3.3.2.3.1.2 + PROPVARIANT */
|
||||
switch(blob[blob.l]) {
|
||||
case 0x41 /*VT_BLOB*/: blob.l += 4; val = parse_BLOB(blob); break;
|
||||
case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]); break;
|
||||
case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]); break;
|
||||
case 0x03 /*VT_I4*/: blob.l += 4; val = blob.read_shift(4, 'i'); break;
|
||||
case 0x13 /*VT_UI4*/: blob.l += 4; val = blob.read_shift(4); break;
|
||||
case 0x05 /*VT_R8*/: blob.l += 4; val = blob.read_shift(8, 'f'); break;
|
||||
case 0x0B /*VT_BOOL*/: blob.l += 4; val = parsebool(blob, 4); break;
|
||||
case 0x40 /*VT_FILETIME*/: blob.l += 4; val = new Date(parse_FILETIME(blob)); break;
|
||||
default: throw new Error("unparsed value: " + blob[blob.l]);
|
||||
}
|
||||
PropH[name] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
blob.l = start_addr + size; /* step ahead to skip padding */
|
||||
return PropH;
|
||||
}
|
||||
|
||||
/* [MS-OLEPS] 2.21 PropertySetStream */
|
||||
function parse_PropertySetStream(file, PIDSI) {
|
||||
var blob = file.content;
|
||||
prep_blob(blob, 0);
|
||||
|
||||
var NumSets, FMTID0, FMTID1, Offset0, Offset1;
|
||||
blob.chk('feff', 'Byte Order: ');
|
||||
|
||||
var vers = blob.read_shift(2); // TODO: check version
|
||||
var SystemIdentifier = blob.read_shift(4);
|
||||
blob.chk(CFB.utils.consts.HEADER_CLSID, 'CLSID: ');
|
||||
NumSets = blob.read_shift(4);
|
||||
if(NumSets !== 1 && NumSets !== 2) throw "Unrecognized #Sets: " + NumSets;
|
||||
FMTID0 = blob.read_shift(16); Offset0 = blob.read_shift(4);
|
||||
|
||||
if(NumSets === 1 && Offset0 !== blob.l) throw "Length mismatch";
|
||||
else if(NumSets === 2) { FMTID1 = blob.read_shift(16); Offset1 = blob.read_shift(4); }
|
||||
var PSet0 = parse_PropertySet(blob, PIDSI);
|
||||
|
||||
var rval = { SystemIdentifier: SystemIdentifier };
|
||||
for(var y in PSet0) rval[y] = PSet0[y];
|
||||
//rval.blob = blob;
|
||||
rval.FMTID = FMTID0;
|
||||
//rval.PSet0 = PSet0;
|
||||
if(NumSets === 1) return rval;
|
||||
if(blob.l !== Offset1) throw "Length mismatch 2: " + blob.l + " !== " + Offset1;
|
||||
var PSet1;
|
||||
try { PSet1 = parse_PropertySet(blob, null); } catch(e) { }
|
||||
for(y in PSet1) rval[y] = PSet1[y];
|
||||
rval.FMTID = [FMTID0, FMTID1]; // TODO: verify FMTID0/1
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
function parsenoop2(blob, length) { blob.read_shift(length); return null; }
|
||||
|
||||
function parslurp(blob, length, cb) {
|
||||
var arr = [], target = blob.l + length;
|
||||
while(blob.l < target) arr.push(cb(blob, target - blob.l));
|
||||
if(target !== blob.l) throw new Error("Slurp error");
|
||||
return arr;
|
||||
}
|
||||
|
||||
function parslurp2(blob, length, cb) {
|
||||
var arr = [], target = blob.l + length, len = blob.read_shift(2);
|
||||
while(len-- !== 0) arr.push(cb(blob, target - blob.l));
|
||||
if(target !== blob.l) throw new Error("Slurp error");
|
||||
return arr;
|
||||
}
|
||||
|
||||
function parsebool(blob, length) { return blob.read_shift(length) === 0x1; }
|
||||
|
||||
function parseuint16(blob) { return blob.read_shift(2, 'u'); }
|
||||
function parseuint16a(blob, length) { return parslurp(blob,length,parseuint16);}
|
||||
|
||||
/* --- 2.5 Structures --- */
|
||||
|
||||
/* [MS-XLS] 2.5.14 Boolean */
|
||||
var parse_Boolean = parsebool;
|
||||
|
||||
/* [MS-XLS] 2.5.10 Bes (boolean or error) */
|
||||
function parse_Bes(blob) {
|
||||
var v = blob.read_shift(1), t = blob.read_shift(1);
|
||||
return t === 0x01 ? v : v === 0x01;
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.5.240 ShortXLUnicodeString */
|
||||
function parse_ShortXLUnicodeString(blob, length, opts) {
|
||||
var cch = blob.read_shift(1);
|
||||
var width = 1, encoding = 'sbcs-cont';
|
||||
var cp = current_codepage;
|
||||
if(opts && opts.biff >= 8) current_codepage = 1200;
|
||||
if(opts === undefined || opts.biff !== 5) {
|
||||
var fHighByte = blob.read_shift(1);
|
||||
if(fHighByte) { width = 2; encoding = 'dbcs-cont'; }
|
||||
}
|
||||
var o = cch ? blob.read_shift(cch, encoding) : "";
|
||||
current_codepage = cp;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.5.293 XLUnicodeRichExtendedString */
|
||||
function parse_XLUnicodeRichExtendedString(blob) {
|
||||
var cp = current_codepage;
|
||||
current_codepage = 1200;
|
||||
var cch = blob.read_shift(2), flags = blob.read_shift(1);
|
||||
var fHighByte = flags & 0x1, fExtSt = flags & 0x4, fRichSt = flags & 0x8;
|
||||
var width = 1 + (flags & 0x1); // 0x0 -> utf8, 0x1 -> dbcs
|
||||
var cRun, cbExtRst;
|
||||
var z = {};
|
||||
if(fRichSt) cRun = blob.read_shift(2);
|
||||
if(fExtSt) cbExtRst = blob.read_shift(4);
|
||||
var encoding = (flags & 0x1) ? 'dbcs-cont' : 'sbcs-cont';
|
||||
var msg = cch === 0 ? "" : blob.read_shift(cch, encoding);
|
||||
if(fRichSt) blob.l += 4 * cRun; //TODO: parse this
|
||||
if(fExtSt) blob.l += cbExtRst; //TODO: parse this
|
||||
z.t = msg;
|
||||
if(!fRichSt) { z.raw = "<t>" + z.t + "</t>"; z.r = z.t; }
|
||||
current_codepage = cp;
|
||||
return z;
|
||||
}
|
||||
|
||||
/* 2.5.296 XLUnicodeStringNoCch */
|
||||
function parse_XLUnicodeStringNoCch(blob, cch, opts) {
|
||||
var retval;
|
||||
var fHighByte = blob.read_shift(1);
|
||||
if(fHighByte===0) { retval = blob.read_shift(cch, 'sbcs-cont'); }
|
||||
else { retval = blob.read_shift(cch, 'dbcs-cont'); }
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* 2.5.294 XLUnicodeString */
|
||||
function parse_XLUnicodeString(blob, length, opts) {
|
||||
var cch = blob.read_shift(opts !== undefined && opts.biff > 0 && opts.biff < 8 ? 1 : 2);
|
||||
if(cch === 0) { blob.l++; return ""; }
|
||||
return parse_XLUnicodeStringNoCch(blob, cch, opts);
|
||||
}
|
||||
/* BIFF5 override */
|
||||
function parse_XLUnicodeString2(blob, length, opts) {
|
||||
if(opts.biff !== 5 && opts.biff !== 2) return parse_XLUnicodeString(blob, length, opts);
|
||||
var cch = blob.read_shift(1);
|
||||
if(cch === 0) { blob.l++; return ""; }
|
||||
return blob.read_shift(cch, 'sbcs-cont');
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.5.61 ControlInfo */
|
||||
var parse_ControlInfo = parsenoop;
|
||||
|
||||
/* [MS-OSHARED] 2.3.7.6 URLMoniker TODO: flags */
|
||||
var parse_URLMoniker = function(blob, length) {
|
||||
var len = blob.read_shift(4), start = blob.l;
|
||||
var extra = false;
|
||||
if(len > 24) {
|
||||
/* look ahead */
|
||||
blob.l += len - 24;
|
||||
if(blob.read_shift(16) === "795881f43b1d7f48af2c825dc4852763") extra = true;
|
||||
blob.l = start;
|
||||
}
|
||||
var url = blob.read_shift((extra?len-24:len)>>1, 'utf16le').replace(chr0,"");
|
||||
if(extra) blob.l += 24;
|
||||
return url;
|
||||
};
|
||||
|
||||
/* [MS-OSHARED] 2.3.7.8 FileMoniker TODO: all fields */
|
||||
var parse_FileMoniker = function(blob, length) {
|
||||
var cAnti = blob.read_shift(2);
|
||||
var ansiLength = blob.read_shift(4);
|
||||
var ansiPath = blob.read_shift(ansiLength, 'cstr');
|
||||
var endServer = blob.read_shift(2);
|
||||
var versionNumber = blob.read_shift(2);
|
||||
var cbUnicodePathSize = blob.read_shift(4);
|
||||
if(cbUnicodePathSize === 0) return ansiPath.replace(/\\/g,"/");
|
||||
var cbUnicodePathBytes = blob.read_shift(4);
|
||||
var usKeyValue = blob.read_shift(2);
|
||||
var unicodePath = blob.read_shift(cbUnicodePathBytes>>1, 'utf16le').replace(chr0,"");
|
||||
return unicodePath;
|
||||
};
|
||||
|
||||
/* [MS-OSHARED] 2.3.7.2 HyperlinkMoniker TODO: all the monikers */
|
||||
var parse_HyperlinkMoniker = function(blob, length) {
|
||||
var clsid = blob.read_shift(16); length -= 16;
|
||||
switch(clsid) {
|
||||
case "e0c9ea79f9bace118c8200aa004ba90b": return parse_URLMoniker(blob, length);
|
||||
case "0303000000000000c000000000000046": return parse_FileMoniker(blob, length);
|
||||
default: throw "unsupported moniker " + clsid;
|
||||
}
|
||||
};
|
||||
|
||||
/* [MS-OSHARED] 2.3.7.9 HyperlinkString */
|
||||
var parse_HyperlinkString = function(blob, length) {
|
||||
var len = blob.read_shift(4);
|
||||
var o = blob.read_shift(len, 'utf16le').replace(chr0, "");
|
||||
return o;
|
||||
};
|
||||
|
||||
/* [MS-OSHARED] 2.3.7.1 Hyperlink Object TODO: unify params with XLSX */
|
||||
var parse_Hyperlink = function(blob, length) {
|
||||
var end = blob.l + length;
|
||||
var sVer = blob.read_shift(4);
|
||||
if(sVer !== 2) throw new Error("Unrecognized streamVersion: " + sVer);
|
||||
var flags = blob.read_shift(2);
|
||||
blob.l += 2;
|
||||
var displayName, targetFrameName, moniker, oleMoniker, location, guid, fileTime;
|
||||
if(flags & 0x0010) displayName = parse_HyperlinkString(blob, end - blob.l);
|
||||
if(flags & 0x0080) targetFrameName = parse_HyperlinkString(blob, end - blob.l);
|
||||
if((flags & 0x0101) === 0x0101) moniker = parse_HyperlinkString(blob, end - blob.l);
|
||||
if((flags & 0x0101) === 0x0001) oleMoniker = parse_HyperlinkMoniker(blob, end - blob.l);
|
||||
if(flags & 0x0008) location = parse_HyperlinkString(blob, end - blob.l);
|
||||
if(flags & 0x0020) guid = blob.read_shift(16);
|
||||
if(flags & 0x0040) fileTime = parse_FILETIME(blob, 8);
|
||||
blob.l = end;
|
||||
var target = (targetFrameName||moniker||oleMoniker);
|
||||
if(location) target+="#"+location;
|
||||
return {Target: target};
|
||||
};
|
||||
|
||||
/* 2.5.178 LongRGBA */
|
||||
function parse_LongRGBA(blob, length) { var r = blob.read_shift(1), g = blob.read_shift(1), b = blob.read_shift(1), a = blob.read_shift(1); return [r,g,b,a]; }
|
||||
|
||||
/* 2.5.177 LongRGB */
|
||||
function parse_LongRGB(blob, length) { var x = parse_LongRGBA(blob, length); x[3] = 0; return x; }
|
||||
|
||||
|
917
bits/39_xlsbiff.js
Normal file
917
bits/39_xlsbiff.js
Normal file
@ -0,0 +1,917 @@
|
||||
/* --- MS-XLS --- */
|
||||
|
||||
/* 2.5.19 */
|
||||
function parse_XLSCell(blob, length) {
|
||||
var rw = blob.read_shift(2); // 0-indexed
|
||||
var col = blob.read_shift(2);
|
||||
var ixfe = blob.read_shift(2);
|
||||
return {r:rw, c:col, ixfe:ixfe};
|
||||
}
|
||||
|
||||
/* 2.5.134 */
|
||||
function parse_frtHeader(blob) {
|
||||
var rt = blob.read_shift(2);
|
||||
var flags = blob.read_shift(2); // TODO: parse these flags
|
||||
blob.l += 8;
|
||||
return {type: rt, flags: flags};
|
||||
}
|
||||
|
||||
|
||||
|
||||
function parse_OptXLUnicodeString(blob, length, opts) { return length === 0 ? "" : parse_XLUnicodeString2(blob, length, opts); }
|
||||
|
||||
/* 2.5.158 */
|
||||
var HIDEOBJENUM = ['SHOWALL', 'SHOWPLACEHOLDER', 'HIDEALL'];
|
||||
var parse_HideObjEnum = parseuint16;
|
||||
|
||||
/* 2.5.344 */
|
||||
function parse_XTI(blob, length) {
|
||||
var iSupBook = blob.read_shift(2), itabFirst = blob.read_shift(2,'i'), itabLast = blob.read_shift(2,'i');
|
||||
return [iSupBook, itabFirst, itabLast];
|
||||
}
|
||||
|
||||
/* 2.5.218 */
|
||||
function parse_RkRec(blob, length) {
|
||||
var ixfe = blob.read_shift(2);
|
||||
var RK = parse_RkNumber(blob);
|
||||
//console.log("::", ixfe, RK,";;");
|
||||
return [ixfe, RK];
|
||||
}
|
||||
|
||||
/* 2.5.1 */
|
||||
function parse_AddinUdf(blob, length) {
|
||||
blob.l += 4; length -= 4;
|
||||
var l = blob.l + length;
|
||||
var udfName = parse_ShortXLUnicodeString(blob, length);
|
||||
var cb = blob.read_shift(2);
|
||||
l -= blob.l;
|
||||
if(cb !== l) throw "Malformed AddinUdf: padding = " + l + " != " + cb;
|
||||
blob.l += cb;
|
||||
return udfName;
|
||||
}
|
||||
|
||||
/* 2.5.209 TODO: Check sizes */
|
||||
function parse_Ref8U(blob, length) {
|
||||
var rwFirst = blob.read_shift(2);
|
||||
var rwLast = blob.read_shift(2);
|
||||
var colFirst = blob.read_shift(2);
|
||||
var colLast = blob.read_shift(2);
|
||||
return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}};
|
||||
}
|
||||
|
||||
/* 2.5.211 */
|
||||
function parse_RefU(blob, length) {
|
||||
var rwFirst = blob.read_shift(2);
|
||||
var rwLast = blob.read_shift(2);
|
||||
var colFirst = blob.read_shift(1);
|
||||
var colLast = blob.read_shift(1);
|
||||
return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}};
|
||||
}
|
||||
|
||||
/* 2.5.207 */
|
||||
var parse_Ref = parse_RefU;
|
||||
|
||||
/* 2.5.143 */
|
||||
function parse_FtCmo(blob, length) {
|
||||
blob.l += 4;
|
||||
var ot = blob.read_shift(2);
|
||||
var id = blob.read_shift(2);
|
||||
var flags = blob.read_shift(2);
|
||||
blob.l+=12;
|
||||
return [id, ot, flags];
|
||||
}
|
||||
|
||||
/* 2.5.149 */
|
||||
function parse_FtNts(blob, length) {
|
||||
var out = {};
|
||||
blob.l += 4;
|
||||
blob.l += 16; // GUID TODO
|
||||
out.fSharedNote = blob.read_shift(2);
|
||||
blob.l += 4;
|
||||
return out;
|
||||
}
|
||||
|
||||
/* 2.5.142 */
|
||||
function parse_FtCf(blob, length) {
|
||||
var out = {};
|
||||
blob.l += 4;
|
||||
blob.cf = blob.read_shift(2);
|
||||
return out;
|
||||
}
|
||||
|
||||
/* 2.5.140 - 2.5.154 and friends */
|
||||
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 */
|
||||
};
|
||||
function parse_FtArray(blob, length, ot) {
|
||||
var s = blob.l;
|
||||
var fts = [];
|
||||
while(blob.l < s + length) {
|
||||
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; }
|
||||
}
|
||||
if(blob.l != s + length) blob.l = s + length; //throw "bad Object Ft-sequence";
|
||||
return fts;
|
||||
}
|
||||
|
||||
/* 2.5.129 */
|
||||
var parse_FontIndex = parseuint16;
|
||||
|
||||
/* --- 2.4 Records --- */
|
||||
|
||||
/* 2.4.21 */
|
||||
function parse_BOF(blob, length) {
|
||||
var o = {};
|
||||
o.BIFFVer = blob.read_shift(2); length -= 2;
|
||||
switch(o.BIFFVer) {
|
||||
case 0x0600: /* BIFF8 */
|
||||
case 0x0500: /* BIFF5 */
|
||||
case 0x0002: case 0x0007: /* BIFF2 */
|
||||
break;
|
||||
default: throw "Unexpected BIFF Ver " + o.BIFFVer;
|
||||
}
|
||||
blob.read_shift(length);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
/* 2.4.146 */
|
||||
function parse_InterfaceHdr(blob, length) {
|
||||
if(length === 0) return 0x04b0;
|
||||
var q;
|
||||
if((q=blob.read_shift(2))!==0x04b0) throw 'InterfaceHdr codePage ' + q;
|
||||
return 0x04b0;
|
||||
}
|
||||
|
||||
|
||||
/* 2.4.349 */
|
||||
function parse_WriteAccess(blob, length, opts) {
|
||||
if(opts.enc) { blob.l += length; return ""; }
|
||||
var l = blob.l;
|
||||
// TODO: make sure XLUnicodeString doesnt overrun
|
||||
var UserName = parse_XLUnicodeString(blob, 0, opts);
|
||||
blob.read_shift(length + l - blob.l);
|
||||
return UserName;
|
||||
}
|
||||
|
||||
/* 2.4.28 */
|
||||
function parse_BoundSheet8(blob, length, opts) {
|
||||
var pos = blob.read_shift(4);
|
||||
var hidden = blob.read_shift(1) >> 6;
|
||||
var dt = blob.read_shift(1);
|
||||
switch(dt) {
|
||||
case 0: dt = 'Worksheet'; break;
|
||||
case 1: dt = 'Macrosheet'; break;
|
||||
case 2: dt = 'Chartsheet'; break;
|
||||
case 6: dt = 'VBAModule'; break;
|
||||
}
|
||||
var name = parse_ShortXLUnicodeString(blob, 0, opts);
|
||||
if(name.length === 0) name = "Sheet1";
|
||||
return { pos:pos, hs:hidden, dt:dt, name:name };
|
||||
}
|
||||
|
||||
/* 2.4.265 TODO */
|
||||
function parse_SST(blob, length) {
|
||||
var cnt = blob.read_shift(4);
|
||||
var ucnt = blob.read_shift(4);
|
||||
var strs = [];
|
||||
for(var i = 0; i != ucnt; ++i) {
|
||||
strs.push(parse_XLUnicodeRichExtendedString(blob));
|
||||
}
|
||||
strs.Count = cnt; strs.Unique = ucnt;
|
||||
return strs;
|
||||
}
|
||||
|
||||
/* 2.4.107 */
|
||||
function parse_ExtSST(blob, length) {
|
||||
var extsst = {};
|
||||
extsst.dsst = blob.read_shift(2);
|
||||
blob.l += length-2;
|
||||
return extsst;
|
||||
}
|
||||
|
||||
|
||||
/* 2.4.221 TODO*/
|
||||
function parse_Row(blob, length) {
|
||||
var rw = blob.read_shift(2), col = blob.read_shift(2), Col = blob.read_shift(2), rht = blob.read_shift(2);
|
||||
blob.read_shift(4); // reserved(2), unused(2)
|
||||
var flags = blob.read_shift(1); // various flags
|
||||
blob.read_shift(1); // reserved
|
||||
blob.read_shift(2); //ixfe, other flags
|
||||
return {r:rw, c:col, cnt:Col-col};
|
||||
}
|
||||
|
||||
|
||||
/* 2.4.125 */
|
||||
function parse_ForceFullCalculation(blob, length) {
|
||||
var header = parse_frtHeader(blob);
|
||||
if(header.type != 0x08A3) throw "Invalid Future Record " + header.type;
|
||||
var fullcalc = blob.read_shift(4);
|
||||
return fullcalc !== 0x0;
|
||||
}
|
||||
|
||||
|
||||
var parse_CompressPictures = parsenoop2; /* 2.4.55 Not interesting */
|
||||
|
||||
|
||||
|
||||
/* 2.4.215 rt */
|
||||
function parse_RecalcId(blob, length) {
|
||||
blob.read_shift(2);
|
||||
return blob.read_shift(4);
|
||||
}
|
||||
|
||||
/* 2.4.87 */
|
||||
function parse_DefaultRowHeight (blob, length) {
|
||||
var f = blob.read_shift(2), miyRw;
|
||||
miyRw = blob.read_shift(2); // flags & 0x02 -> hidden, else empty
|
||||
var fl = {Unsynced:f&1,DyZero:(f&2)>>1,ExAsc:(f&4)>>2,ExDsc:(f&8)>>3};
|
||||
return [fl, miyRw];
|
||||
}
|
||||
|
||||
/* 2.4.345 TODO */
|
||||
function parse_Window1(blob, length) {
|
||||
var xWn = blob.read_shift(2), yWn = blob.read_shift(2), dxWn = blob.read_shift(2), dyWn = blob.read_shift(2);
|
||||
var flags = blob.read_shift(2), iTabCur = blob.read_shift(2), iTabFirst = blob.read_shift(2);
|
||||
var ctabSel = blob.read_shift(2), wTabRatio = blob.read_shift(2);
|
||||
return { Pos: [xWn, yWn], Dim: [dxWn, dyWn], Flags: flags, CurTab: iTabCur,
|
||||
FirstTab: iTabFirst, Selected: ctabSel, TabRatio: wTabRatio };
|
||||
}
|
||||
|
||||
/* 2.4.122 TODO */
|
||||
function parse_Font(blob, length, opts) {
|
||||
blob.l += 14;
|
||||
var name = parse_ShortXLUnicodeString(blob, 0, opts);
|
||||
return name;
|
||||
}
|
||||
|
||||
/* 2.4.149 */
|
||||
function parse_LabelSst(blob, length) {
|
||||
var cell = parse_XLSCell(blob);
|
||||
cell.isst = blob.read_shift(4);
|
||||
return cell;
|
||||
}
|
||||
|
||||
/* 2.4.148 */
|
||||
function parse_Label(blob, length, opts) {
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
var str = parse_XLUnicodeString(blob, length-6, opts);
|
||||
cell.val = str;
|
||||
return cell;
|
||||
}
|
||||
|
||||
/* 2.4.126 Number Formats */
|
||||
function parse_Format(blob, length, opts) {
|
||||
var ifmt = blob.read_shift(2);
|
||||
var fmtstr = parse_XLUnicodeString2(blob, 0, opts);
|
||||
return [ifmt, fmtstr];
|
||||
}
|
||||
|
||||
/* 2.4.90 */
|
||||
function parse_Dimensions(blob, length) {
|
||||
var w = length === 10 ? 2 : 4;
|
||||
var r = blob.read_shift(w), R = blob.read_shift(w),
|
||||
c = blob.read_shift(2), C = blob.read_shift(2);
|
||||
blob.l += 2;
|
||||
return {s: {r:r, c:c}, e: {r:R, c:C}};
|
||||
}
|
||||
|
||||
/* 2.4.220 */
|
||||
function parse_RK(blob, length) {
|
||||
var rw = blob.read_shift(2), col = blob.read_shift(2);
|
||||
var rkrec = parse_RkRec(blob);
|
||||
return {r:rw, c:col, ixfe:rkrec[0], rknum:rkrec[1]};
|
||||
}
|
||||
|
||||
/* 2.4.175 */
|
||||
function parse_MulRk(blob, length) {
|
||||
var target = blob.l + length - 2;
|
||||
var rw = blob.read_shift(2), col = blob.read_shift(2);
|
||||
var rkrecs = [];
|
||||
while(blob.l < target) rkrecs.push(parse_RkRec(blob));
|
||||
if(blob.l !== target) throw "MulRK read error";
|
||||
var lastcol = blob.read_shift(2);
|
||||
if(rkrecs.length != lastcol - col + 1) throw "MulRK length mismatch";
|
||||
return {r:rw, c:col, C:lastcol, rkrec:rkrecs};
|
||||
}
|
||||
|
||||
/* 2.5.20 2.5.249 TODO */
|
||||
function parse_CellStyleXF(blob, length, style) {
|
||||
var o = {};
|
||||
var a = blob.read_shift(4), b = blob.read_shift(4);
|
||||
var c = blob.read_shift(4), d = blob.read_shift(2);
|
||||
o.patternType = XLSFillPattern[c >> 26];
|
||||
o.icvFore = d & 0x7F;
|
||||
o.icvBack = (d >> 7) & 0x7F;
|
||||
return o;
|
||||
}
|
||||
function parse_CellXF(blob, length) {return parse_CellStyleXF(blob,length,0);}
|
||||
function parse_StyleXF(blob, length) {return parse_CellStyleXF(blob,length,1);}
|
||||
|
||||
/* 2.4.353 TODO: actually do this right */
|
||||
function parse_XF(blob, length) {
|
||||
var o = {};
|
||||
o.ifnt = blob.read_shift(2); o.ifmt = blob.read_shift(2); o.flags = blob.read_shift(2);
|
||||
o.fStyle = (o.flags >> 2) & 0x01;
|
||||
length -= 6;
|
||||
o.data = parse_CellStyleXF(blob, length, o.fStyle);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.4.134 */
|
||||
function parse_Guts(blob, length) {
|
||||
blob.l += 4;
|
||||
var out = [blob.read_shift(2), blob.read_shift(2)];
|
||||
if(out[0] !== 0) out[0]--;
|
||||
if(out[1] !== 0) out[1]--;
|
||||
if(out[0] > 7 || out[1] > 7) throw "Bad Gutters: " + out;
|
||||
return out;
|
||||
}
|
||||
|
||||
/* 2.4.24 */
|
||||
function parse_BoolErr(blob, length) {
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
var val = parse_Bes(blob, 2);
|
||||
cell.val = val;
|
||||
cell.t = (val === true || val === false) ? 'b' : 'e';
|
||||
return cell;
|
||||
}
|
||||
|
||||
/* 2.4.180 Number */
|
||||
function parse_Number(blob, length) {
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
var xnum = parse_Xnum(blob, 8);
|
||||
cell.val = xnum;
|
||||
return cell;
|
||||
}
|
||||
|
||||
var parse_XLHeaderFooter = parse_OptXLUnicodeString; // TODO: parse 2.4.136
|
||||
|
||||
/* 2.4.271 */
|
||||
function parse_SupBook(blob, length, opts) {
|
||||
var end = blob.l + length;
|
||||
var ctab = blob.read_shift(2);
|
||||
var cch = blob.read_shift(2);
|
||||
var virtPath;
|
||||
if(cch >=0x01 && cch <=0xff) virtPath = parse_XLUnicodeStringNoCch(blob, cch);
|
||||
var rgst = blob.read_shift(end - blob.l);
|
||||
opts.sbcch = cch;
|
||||
return [cch, ctab, virtPath, rgst];
|
||||
}
|
||||
|
||||
/* 2.4.105 TODO */
|
||||
function parse_ExternName(blob, length, opts) {
|
||||
var flags = blob.read_shift(2);
|
||||
var body;
|
||||
var o = {
|
||||
fBuiltIn: flags & 0x01,
|
||||
fWantAdvise: (flags >>> 1) & 0x01,
|
||||
fWantPict: (flags >>> 2) & 0x01,
|
||||
fOle: (flags >>> 3) & 0x01,
|
||||
fOleLink: (flags >>> 4) & 0x01,
|
||||
cf: (flags >>> 5) & 0x3FF,
|
||||
fIcon: flags >>> 15 & 0x01
|
||||
};
|
||||
if(opts.sbcch === 0x3A01) body = parse_AddinUdf(blob, length-2);
|
||||
//else throw new Error("unsupported SupBook cch: " + opts.sbcch);
|
||||
o.body = body || blob.read_shift(length-2);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.4.150 TODO */
|
||||
function parse_Lbl(blob, length, opts) {
|
||||
if(opts.biff < 8) return parse_Label(blob, length, opts);
|
||||
var target = blob.l + length;
|
||||
var flags = blob.read_shift(2);
|
||||
var chKey = blob.read_shift(1);
|
||||
var cch = blob.read_shift(1);
|
||||
var cce = blob.read_shift(2);
|
||||
blob.l += 2;
|
||||
var itab = blob.read_shift(2);
|
||||
blob.l += 4;
|
||||
var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
|
||||
var rgce = parse_NameParsedFormula(blob, target - blob.l, opts, cce);
|
||||
return {
|
||||
chKey: chKey,
|
||||
Name: name,
|
||||
rgce: rgce
|
||||
};
|
||||
}
|
||||
|
||||
/* 2.4.106 TODO: verify supbook manipulation */
|
||||
function parse_ExternSheet(blob, length, opts) {
|
||||
if(opts.biff < 8) return parse_ShortXLUnicodeString(blob, length, opts);
|
||||
var o = parslurp2(blob,length,parse_XTI);
|
||||
var oo = [];
|
||||
if(opts.sbcch === 0x0401) {
|
||||
for(var i = 0; i != o.length; ++i) oo.push(opts.snames[o[i][1]]);
|
||||
return oo;
|
||||
}
|
||||
else return o;
|
||||
}
|
||||
|
||||
/* 2.4.260 */
|
||||
function parse_ShrFmla(blob, length, opts) {
|
||||
var ref = parse_RefU(blob, 6);
|
||||
blob.l++;
|
||||
var cUse = blob.read_shift(1);
|
||||
length -= 8;
|
||||
return [parse_SharedParsedFormula(blob, length, opts), cUse];
|
||||
}
|
||||
|
||||
/* 2.4.4 TODO */
|
||||
function parse_Array(blob, length, opts) {
|
||||
var ref = parse_Ref(blob, 6);
|
||||
blob.l += 6; length -= 12; /* TODO: fAlwaysCalc */
|
||||
return [ref, parse_ArrayParsedFormula(blob, length, opts, ref)];
|
||||
}
|
||||
|
||||
/* 2.4.173 */
|
||||
function parse_MTRSettings(blob, length) {
|
||||
var fMTREnabled = blob.read_shift(4) !== 0x00;
|
||||
var fUserSetThreadCount = blob.read_shift(4) !== 0x00;
|
||||
var cUserThreadCount = blob.read_shift(4);
|
||||
return [fMTREnabled, fUserSetThreadCount, cUserThreadCount];
|
||||
}
|
||||
|
||||
/* 2.5.186 TODO: BIFF5 */
|
||||
function parse_NoteSh(blob, length, opts) {
|
||||
if(opts.biff < 8) return;
|
||||
var row = blob.read_shift(2), col = blob.read_shift(2);
|
||||
var flags = blob.read_shift(2), idObj = blob.read_shift(2);
|
||||
var stAuthor = parse_XLUnicodeString2(blob, 0, opts);
|
||||
if(opts.biff < 8) blob.read_shift(1);
|
||||
return [{r:row,c:col}, stAuthor, idObj, flags];
|
||||
}
|
||||
|
||||
/* 2.4.179 */
|
||||
function parse_Note(blob, length, opts) {
|
||||
/* TODO: Support revisions */
|
||||
return parse_NoteSh(blob, length, opts);
|
||||
}
|
||||
|
||||
/* 2.4.168 */
|
||||
function parse_MergeCells(blob, length) {
|
||||
var merges = [];
|
||||
var cmcs = blob.read_shift(2);
|
||||
while (cmcs--) merges.push(parse_Ref8U(blob,length));
|
||||
return merges;
|
||||
}
|
||||
|
||||
/* 2.4.181 TODO: parse all the things! */
|
||||
function parse_Obj(blob, length) {
|
||||
var cmo = parse_FtCmo(blob, 22); // id, ot, flags
|
||||
var fts = parse_FtArray(blob, length-22, cmo[1]);
|
||||
return { cmo: cmo, ft:fts };
|
||||
}
|
||||
|
||||
/* 2.4.329 TODO: parse properly */
|
||||
function parse_TxO(blob, length, opts) {
|
||||
var s = blob.l;
|
||||
try {
|
||||
blob.l += 4;
|
||||
var ot = (opts.lastobj||{cmo:[0,0]}).cmo[1];
|
||||
var controlInfo;
|
||||
if([0,5,7,11,12,14].indexOf(ot) == -1) blob.l += 6;
|
||||
else controlInfo = parse_ControlInfo(blob, 6, opts);
|
||||
var cchText = blob.read_shift(2);
|
||||
var cbRuns = blob.read_shift(2);
|
||||
var ifntEmpty = parse_FontIndex(blob, 2);
|
||||
var len = blob.read_shift(2);
|
||||
blob.l += len;
|
||||
//var fmla = parse_ObjFmla(blob, s + length - blob.l);
|
||||
|
||||
var texts = "";
|
||||
for(var i = 1; i < blob.lens.length-1; ++i) {
|
||||
if(blob.l-s != blob.lens[i]) throw "TxO: bad continue record";
|
||||
var hdr = blob[blob.l];
|
||||
var t = parse_XLUnicodeStringNoCch(blob, blob.lens[i+1]-blob.lens[i]-1);
|
||||
texts += t;
|
||||
if(texts.length >= (hdr ? cchText : 2*cchText)) break;
|
||||
}
|
||||
if(texts.length !== cchText && texts.length !== cchText*2) {
|
||||
throw "cchText: " + cchText + " != " + texts.length;
|
||||
}
|
||||
|
||||
blob.l = s + length;
|
||||
/* 2.5.272 TxORuns */
|
||||
// var rgTxoRuns = [];
|
||||
// for(var j = 0; j != cbRuns/8-1; ++j) blob.l += 8;
|
||||
// var cchText2 = blob.read_shift(2);
|
||||
// if(cchText2 !== cchText) throw "TxOLastRun mismatch: " + cchText2 + " " + cchText;
|
||||
// blob.l += 6;
|
||||
// if(s + length != blob.l) throw "TxO " + (s + length) + ", at " + blob.l;
|
||||
return { t: texts };
|
||||
} catch(e) { blob.l = s + length; return { t: texts||"" }; }
|
||||
}
|
||||
|
||||
/* 2.4.140 */
|
||||
var parse_HLink = function(blob, length) {
|
||||
var ref = parse_Ref8U(blob, 8);
|
||||
blob.l += 16; /* CLSID */
|
||||
var hlink = parse_Hyperlink(blob, length-24);
|
||||
return [ref, hlink];
|
||||
};
|
||||
|
||||
/* 2.4.141 */
|
||||
var parse_HLinkTooltip = function(blob, length) {
|
||||
var end = blob.l + length;
|
||||
blob.read_shift(2);
|
||||
var ref = parse_Ref8U(blob, 8);
|
||||
var wzTooltip = blob.read_shift((length-10)/2, 'dbcs-cont');
|
||||
wzTooltip = wzTooltip.replace(chr0,"");
|
||||
return [ref, wzTooltip];
|
||||
};
|
||||
|
||||
/* 2.4.63 */
|
||||
function parse_Country(blob, length) {
|
||||
var o = [], d;
|
||||
d = blob.read_shift(2); o[0] = CountryEnum[d] || d;
|
||||
d = blob.read_shift(2); o[1] = CountryEnum[d] || d;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.4.50 ClrtClient */
|
||||
function parse_ClrtClient(blob, length) {
|
||||
var ccv = blob.read_shift(2);
|
||||
var o = [];
|
||||
while(ccv-->0) o.push(parse_LongRGB(blob, 8));
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.4.188 */
|
||||
function parse_Palette(blob, length) {
|
||||
var ccv = blob.read_shift(2);
|
||||
var o = [];
|
||||
while(ccv-->0) o.push(parse_LongRGB(blob, 8));
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.4.354 */
|
||||
function parse_XFCRC(blob, length) {
|
||||
blob.l += 2;
|
||||
var o = {cxfs:0, crc:0};
|
||||
o.cxfs = blob.read_shift(2);
|
||||
o.crc = blob.read_shift(4);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
var parse_Style = parsenoop;
|
||||
var parse_StyleExt = parsenoop;
|
||||
|
||||
var parse_ColInfo = 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 */
|
||||
var parse_BuiltInFnGroupCount = parseuint16; /* 2.4.30 0x0E or 0x10 but excel 2011 generates 0x11? */
|
||||
var parse_CalcCount = parseuint16; /* 2.4.31 #Iterations */
|
||||
var parse_CalcDelta = parse_Xnum; /* 2.4.32 */
|
||||
var parse_CalcIter = parsebool; /* 2.4.33 1=iterative calc */
|
||||
var parse_CalcMode = parseuint16; /* 2.4.34 0=manual, 1=auto (def), 2=table */
|
||||
var parse_CalcPrecision = parsebool; /* 2.4.35 */
|
||||
var parse_CalcRefMode = parsenoop2; /* 2.4.36 */
|
||||
var parse_CalcSaveRecalc = parsebool; /* 2.4.37 */
|
||||
var parse_CodePage = parseuint16; /* 2.4.52 */
|
||||
var parse_Compat12 = parsebool; /* 2.4.54 true = no compatibility check */
|
||||
var parse_Date1904 = parsebool; /* 2.4.77 - 1=1904,0=1900 */
|
||||
var parse_DefColWidth = parseuint16; /* 2.4.89 */
|
||||
var parse_DSF = parsenoop2; /* 2.4.94 -- MUST be ignored */
|
||||
var parse_EntExU2 = parsenoop2; /* 2.4.102 -- Explicitly says to ignore */
|
||||
var parse_EOF = parsenoop2; /* 2.4.103 */
|
||||
var parse_Excel9File = parsenoop2; /* 2.4.104 -- Optional and unused */
|
||||
var parse_FeatHdr = parsenoop2; /* 2.4.112 */
|
||||
var parse_FontX = parseuint16; /* 2.4.123 */
|
||||
var parse_Footer = parse_XLHeaderFooter; /* 2.4.124 */
|
||||
var parse_GridSet = parseuint16; /* 2.4.132, =1 */
|
||||
var parse_HCenter = parsebool; /* 2.4.135 sheet centered horizontal on print */
|
||||
var parse_Header = parse_XLHeaderFooter; /* 2.4.136 */
|
||||
var parse_HideObj = parse_HideObjEnum; /* 2.4.139 */
|
||||
var parse_InterfaceEnd = parsenoop2; /* 2.4.145 -- noop */
|
||||
var parse_LeftMargin = parse_Xnum; /* 2.4.151 */
|
||||
var parse_Mms = parsenoop2; /* 2.4.169 -- Explicitly says to ignore */
|
||||
var parse_ObjProtect = parsebool; /* 2.4.183 -- must be 1 if present */
|
||||
var parse_Password = parseuint16; /* 2.4.191 */
|
||||
var parse_PrintGrid = parsebool; /* 2.4.202 */
|
||||
var parse_PrintRowCol = parsebool; /* 2.4.203 */
|
||||
var parse_PrintSize = parseuint16; /* 2.4.204 0:3 */
|
||||
var parse_Prot4Rev = parsebool; /* 2.4.205 */
|
||||
var parse_Prot4RevPass = parseuint16; /* 2.4.206 */
|
||||
var parse_Protect = parsebool; /* 2.4.207 */
|
||||
var parse_RefreshAll = parsebool; /* 2.4.217 -- must be 0 if not template */
|
||||
var parse_RightMargin = parse_Xnum; /* 2.4.219 */
|
||||
var parse_RRTabId = parseuint16a; /* 2.4.241 */
|
||||
var parse_ScenarioProtect = parsebool; /* 2.4.245 */
|
||||
var parse_Scl = parseuint16a; /* 2.4.247 num, den */
|
||||
var parse_String = parse_XLUnicodeString; /* 2.4.268 */
|
||||
var parse_SxBool = parsebool; /* 2.4.274 */
|
||||
var parse_TopMargin = parse_Xnum; /* 2.4.328 */
|
||||
var parse_UsesELFs = parsebool; /* 2.4.337 -- should be 0 */
|
||||
var parse_VCenter = parsebool; /* 2.4.342 */
|
||||
var parse_WinProtect = parsebool; /* 2.4.347 */
|
||||
var parse_WriteProtect = parsenoop; /* 2.4.350 empty record */
|
||||
|
||||
|
||||
/* ---- */
|
||||
var parse_VerticalPageBreaks = parsenoop;
|
||||
var parse_HorizontalPageBreaks = parsenoop;
|
||||
var parse_Selection = parsenoop;
|
||||
var parse_Continue = parsenoop;
|
||||
var parse_Pane = parsenoop;
|
||||
var parse_Pls = parsenoop;
|
||||
var parse_DCon = parsenoop;
|
||||
var parse_DConRef = parsenoop;
|
||||
var parse_DConName = parsenoop;
|
||||
var parse_XCT = parsenoop;
|
||||
var parse_CRN = parsenoop;
|
||||
var parse_FileSharing = parsenoop;
|
||||
var parse_Uncalced = parsenoop;
|
||||
var parse_Template = parsenoop;
|
||||
var parse_Intl = parsenoop;
|
||||
var parse_WsBool = parsenoop;
|
||||
var parse_Sort = parsenoop;
|
||||
var parse_Sync = parsenoop;
|
||||
var parse_LPr = parsenoop;
|
||||
var parse_DxGCol = parsenoop;
|
||||
var parse_FnGroupName = parsenoop;
|
||||
var parse_FilterMode = parsenoop;
|
||||
var parse_AutoFilterInfo = parsenoop;
|
||||
var parse_AutoFilter = parsenoop;
|
||||
var parse_Setup = parsenoop;
|
||||
var parse_ScenMan = parsenoop;
|
||||
var parse_SCENARIO = parsenoop;
|
||||
var parse_SxView = parsenoop;
|
||||
var parse_Sxvd = parsenoop;
|
||||
var parse_SXVI = parsenoop;
|
||||
var parse_SxIvd = parsenoop;
|
||||
var parse_SXLI = parsenoop;
|
||||
var parse_SXPI = parsenoop;
|
||||
var parse_DocRoute = parsenoop;
|
||||
var parse_RecipName = parsenoop;
|
||||
var parse_MulBlank = parsenoop;
|
||||
var parse_SXDI = parsenoop;
|
||||
var parse_SXDB = parsenoop;
|
||||
var parse_SXFDB = parsenoop;
|
||||
var parse_SXDBB = parsenoop;
|
||||
var parse_SXNum = parsenoop;
|
||||
var parse_SxErr = parsenoop;
|
||||
var parse_SXInt = parsenoop;
|
||||
var parse_SXString = parsenoop;
|
||||
var parse_SXDtr = parsenoop;
|
||||
var parse_SxNil = parsenoop;
|
||||
var parse_SXTbl = parsenoop;
|
||||
var parse_SXTBRGIITM = parsenoop;
|
||||
var parse_SxTbpg = parsenoop;
|
||||
var parse_ObProj = parsenoop;
|
||||
var parse_SXStreamID = parsenoop;
|
||||
var parse_DBCell = parsenoop;
|
||||
var parse_SXRng = parsenoop;
|
||||
var parse_SxIsxoper = parsenoop;
|
||||
var parse_BookBool = parsenoop;
|
||||
var parse_DbOrParamQry = parsenoop;
|
||||
var parse_OleObjectSize = parsenoop;
|
||||
var parse_SXVS = parsenoop;
|
||||
var parse_BkHim = parsenoop;
|
||||
var parse_MsoDrawingGroup = parsenoop;
|
||||
var parse_MsoDrawing = parsenoop;
|
||||
var parse_MsoDrawingSelection = parsenoop;
|
||||
var parse_PhoneticInfo = parsenoop;
|
||||
var parse_SxRule = parsenoop;
|
||||
var parse_SXEx = parsenoop;
|
||||
var parse_SxFilt = parsenoop;
|
||||
var parse_SxDXF = parsenoop;
|
||||
var parse_SxItm = parsenoop;
|
||||
var parse_SxName = parsenoop;
|
||||
var parse_SxSelect = parsenoop;
|
||||
var parse_SXPair = parsenoop;
|
||||
var parse_SxFmla = parsenoop;
|
||||
var parse_SxFormat = parsenoop;
|
||||
var parse_SXVDEx = parsenoop;
|
||||
var parse_SXFormula = parsenoop;
|
||||
var parse_SXDBEx = parsenoop;
|
||||
var parse_RRDInsDel = parsenoop;
|
||||
var parse_RRDHead = parsenoop;
|
||||
var parse_RRDChgCell = parsenoop;
|
||||
var parse_RRDRenSheet = parsenoop;
|
||||
var parse_RRSort = parsenoop;
|
||||
var parse_RRDMove = parsenoop;
|
||||
var parse_RRFormat = parsenoop;
|
||||
var parse_RRAutoFmt = parsenoop;
|
||||
var parse_RRInsertSh = parsenoop;
|
||||
var parse_RRDMoveBegin = parsenoop;
|
||||
var parse_RRDMoveEnd = parsenoop;
|
||||
var parse_RRDInsDelBegin = parsenoop;
|
||||
var parse_RRDInsDelEnd = parsenoop;
|
||||
var parse_RRDConflict = parsenoop;
|
||||
var parse_RRDDefName = parsenoop;
|
||||
var parse_RRDRstEtxp = parsenoop;
|
||||
var parse_LRng = parsenoop;
|
||||
var parse_CUsr = parsenoop;
|
||||
var parse_CbUsr = parsenoop;
|
||||
var parse_UsrInfo = parsenoop;
|
||||
var parse_UsrExcl = parsenoop;
|
||||
var parse_FileLock = parsenoop;
|
||||
var parse_RRDInfo = parsenoop;
|
||||
var parse_BCUsrs = parsenoop;
|
||||
var parse_UsrChk = parsenoop;
|
||||
var parse_UserBView = parsenoop;
|
||||
var parse_UserSViewBegin = parsenoop; // overloaded
|
||||
var parse_UserSViewEnd = parsenoop;
|
||||
var parse_RRDUserView = parsenoop;
|
||||
var parse_Qsi = parsenoop;
|
||||
var parse_CondFmt = parsenoop;
|
||||
var parse_CF = parsenoop;
|
||||
var parse_DVal = parsenoop;
|
||||
var parse_DConBin = parsenoop;
|
||||
var parse_Lel = parsenoop;
|
||||
var parse_XLSCodeName = parse_XLUnicodeString;
|
||||
var parse_SXFDBType = parsenoop;
|
||||
var parse_ObNoMacros = parsenoop;
|
||||
var parse_Dv = parsenoop;
|
||||
var parse_Index = parsenoop;
|
||||
var parse_Table = parsenoop;
|
||||
var parse_BigName = parsenoop;
|
||||
var parse_ContinueBigName = parsenoop;
|
||||
var parse_WebPub = parsenoop;
|
||||
var parse_QsiSXTag = parsenoop;
|
||||
var parse_DBQueryExt = parsenoop;
|
||||
var parse_ExtString = parsenoop;
|
||||
var parse_TxtQry = parsenoop;
|
||||
var parse_Qsir = parsenoop;
|
||||
var parse_Qsif = parsenoop;
|
||||
var parse_RRDTQSIF = parsenoop;
|
||||
var parse_OleDbConn = parsenoop;
|
||||
var parse_WOpt = parsenoop;
|
||||
var parse_SXViewEx = parsenoop;
|
||||
var parse_SXTH = parsenoop;
|
||||
var parse_SXPIEx = parsenoop;
|
||||
var parse_SXVDTEx = parsenoop;
|
||||
var parse_SXViewEx9 = parsenoop;
|
||||
var parse_ContinueFrt = parsenoop;
|
||||
var parse_RealTimeData = parsenoop;
|
||||
var parse_ChartFrtInfo = parsenoop;
|
||||
var parse_FrtWrapper = parsenoop;
|
||||
var parse_StartBlock = parsenoop;
|
||||
var parse_EndBlock = parsenoop;
|
||||
var parse_StartObject = parsenoop;
|
||||
var parse_EndObject = parsenoop;
|
||||
var parse_CatLab = parsenoop;
|
||||
var parse_YMult = parsenoop;
|
||||
var parse_SXViewLink = parsenoop;
|
||||
var parse_PivotChartBits = parsenoop;
|
||||
var parse_FrtFontList = parsenoop;
|
||||
var parse_SheetExt = parsenoop;
|
||||
var parse_BookExt = parsenoop;
|
||||
var parse_SXAddl = parsenoop;
|
||||
var parse_CrErr = parsenoop;
|
||||
var parse_HFPicture = parsenoop;
|
||||
var parse_Feat = parsenoop;
|
||||
var parse_DataLabExt = parsenoop;
|
||||
var parse_DataLabExtContents = parsenoop;
|
||||
var parse_CellWatch = parsenoop;
|
||||
var parse_FeatHdr11 = parsenoop;
|
||||
var parse_Feature11 = parsenoop;
|
||||
var parse_DropDownObjIds = parsenoop;
|
||||
var parse_ContinueFrt11 = parsenoop;
|
||||
var parse_DConn = parsenoop;
|
||||
var parse_List12 = parsenoop;
|
||||
var parse_Feature12 = parsenoop;
|
||||
var parse_CondFmt12 = parsenoop;
|
||||
var parse_CF12 = parsenoop;
|
||||
var parse_CFEx = parsenoop;
|
||||
var parse_AutoFilter12 = parsenoop;
|
||||
var parse_ContinueFrt12 = parsenoop;
|
||||
var parse_MDTInfo = parsenoop;
|
||||
var parse_MDXStr = parsenoop;
|
||||
var parse_MDXTuple = parsenoop;
|
||||
var parse_MDXSet = parsenoop;
|
||||
var parse_MDXProp = parsenoop;
|
||||
var parse_MDXKPI = parsenoop;
|
||||
var parse_MDB = parsenoop;
|
||||
var parse_PLV = parsenoop;
|
||||
var parse_DXF = parsenoop;
|
||||
var parse_TableStyles = parsenoop;
|
||||
var parse_TableStyle = parsenoop;
|
||||
var parse_TableStyleElement = parsenoop;
|
||||
var parse_NamePublish = parsenoop;
|
||||
var parse_NameCmt = parsenoop;
|
||||
var parse_SortData = parsenoop;
|
||||
var parse_GUIDTypeLib = parsenoop;
|
||||
var parse_FnGrp12 = parsenoop;
|
||||
var parse_NameFnGrp12 = parsenoop;
|
||||
var parse_HeaderFooter = parsenoop;
|
||||
var parse_CrtLayout12 = parsenoop;
|
||||
var parse_CrtMlFrt = parsenoop;
|
||||
var parse_CrtMlFrtContinue = parsenoop;
|
||||
var parse_ShapePropsStream = parsenoop;
|
||||
var parse_TextPropsStream = parsenoop;
|
||||
var parse_RichTextStream = parsenoop;
|
||||
var parse_CrtLayout12A = parsenoop;
|
||||
var parse_Units = parsenoop;
|
||||
var parse_Chart = parsenoop;
|
||||
var parse_Series = parsenoop;
|
||||
var parse_DataFormat = parsenoop;
|
||||
var parse_LineFormat = parsenoop;
|
||||
var parse_MarkerFormat = parsenoop;
|
||||
var parse_AreaFormat = parsenoop;
|
||||
var parse_PieFormat = parsenoop;
|
||||
var parse_AttachedLabel = parsenoop;
|
||||
var parse_SeriesText = parsenoop;
|
||||
var parse_ChartFormat = parsenoop;
|
||||
var parse_Legend = parsenoop;
|
||||
var parse_SeriesList = parsenoop;
|
||||
var parse_Bar = parsenoop;
|
||||
var parse_Line = parsenoop;
|
||||
var parse_Pie = parsenoop;
|
||||
var parse_Area = parsenoop;
|
||||
var parse_Scatter = parsenoop;
|
||||
var parse_CrtLine = parsenoop;
|
||||
var parse_Axis = parsenoop;
|
||||
var parse_Tick = parsenoop;
|
||||
var parse_ValueRange = parsenoop;
|
||||
var parse_CatSerRange = parsenoop;
|
||||
var parse_AxisLine = parsenoop;
|
||||
var parse_CrtLink = parsenoop;
|
||||
var parse_DefaultText = parsenoop;
|
||||
var parse_Text = parsenoop;
|
||||
var parse_ObjectLink = parsenoop;
|
||||
var parse_Frame = parsenoop;
|
||||
var parse_Begin = parsenoop;
|
||||
var parse_End = parsenoop;
|
||||
var parse_PlotArea = parsenoop;
|
||||
var parse_Chart3d = parsenoop;
|
||||
var parse_PicF = parsenoop;
|
||||
var parse_DropBar = parsenoop;
|
||||
var parse_Radar = parsenoop;
|
||||
var parse_Surf = parsenoop;
|
||||
var parse_RadarArea = parsenoop;
|
||||
var parse_AxisParent = parsenoop;
|
||||
var parse_LegendException = parsenoop;
|
||||
var parse_ShtProps = parsenoop;
|
||||
var parse_SerToCrt = parsenoop;
|
||||
var parse_AxesUsed = parsenoop;
|
||||
var parse_SBaseRef = parsenoop;
|
||||
var parse_SerParent = parsenoop;
|
||||
var parse_SerAuxTrend = parsenoop;
|
||||
var parse_IFmtRecord = parsenoop;
|
||||
var parse_Pos = parsenoop;
|
||||
var parse_AlRuns = parsenoop;
|
||||
var parse_BRAI = parsenoop;
|
||||
var parse_SerAuxErrBar = parsenoop;
|
||||
var parse_SerFmt = parsenoop;
|
||||
var parse_Chart3DBarShape = parsenoop;
|
||||
var parse_Fbi = parsenoop;
|
||||
var parse_BopPop = parsenoop;
|
||||
var parse_AxcExt = parsenoop;
|
||||
var parse_Dat = parsenoop;
|
||||
var parse_PlotGrowth = parsenoop;
|
||||
var parse_SIIndex = parsenoop;
|
||||
var parse_GelFrame = parsenoop;
|
||||
var parse_BopPopCustom = parsenoop;
|
||||
var parse_Fbi2 = parsenoop;
|
||||
|
||||
/* --- Specific to versions before BIFF8 --- */
|
||||
function parse_BIFF5String(blob) {
|
||||
var len = blob.read_shift(1);
|
||||
return blob.read_shift(len, 'sbcs-cont');
|
||||
}
|
||||
|
||||
/* BIFF2_??? where ??? is the name from [XLS] */
|
||||
function parse_BIFF2STR(blob, length, opts) {
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
++blob.l;
|
||||
var str = parse_XLUnicodeString2(blob, length-7, opts);
|
||||
cell.val = str;
|
||||
return cell;
|
||||
}
|
||||
|
||||
function parse_BIFF2NUM(blob, length, opts) {
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
++blob.l;
|
||||
var num = parse_Xnum(blob, 8);
|
||||
cell.val = num;
|
||||
return cell;
|
||||
}
|
||||
|
180
bits/44_offcrypto.js
Normal file
180
bits/44_offcrypto.js
Normal file
@ -0,0 +1,180 @@
|
||||
function _JS2ANSI(str) { if(typeof cptable !== 'undefined') return cptable.utils.encode(1252, str); return str.split("").map(function(x) { return x.charCodeAt(0); }); }
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.1.4 Version */
|
||||
function parse_Version(blob, length) {
|
||||
var o = {};
|
||||
o.Major = blob.read_shift(2);
|
||||
o.Minor = blob.read_shift(2);
|
||||
return o;
|
||||
}
|
||||
/* [MS-OFFCRYPTO] 2.3.2 Encryption Header */
|
||||
function parse_EncryptionHeader(blob, length) {
|
||||
var o = {};
|
||||
o.Flags = blob.read_shift(4);
|
||||
|
||||
// Check if SizeExtra is 0x00000000
|
||||
var tmp = blob.read_shift(4);
|
||||
if(tmp !== 0) throw 'Unrecognized SizeExtra: ' + tmp;
|
||||
|
||||
o.AlgID = blob.read_shift(4);
|
||||
switch(o.AlgID) {
|
||||
case 0: case 0x6801: case 0x660E: case 0x660F: case 0x6610: break;
|
||||
default: throw 'Unrecognized encryption algorithm: ' + o.AlgID;
|
||||
}
|
||||
parsenoop(blob, length-12);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.3.3 Encryption Verifier */
|
||||
function parse_EncryptionVerifier(blob, length) {
|
||||
return parsenoop(blob, length);
|
||||
}
|
||||
/* [MS-OFFCRYPTO] 2.3.5.1 RC4 CryptoAPI Encryption Header */
|
||||
function parse_RC4CryptoHeader(blob, length) {
|
||||
var o = {};
|
||||
var vers = o.EncryptionVersionInfo = parse_Version(blob, 4); length -= 4;
|
||||
if(vers.Minor != 2) throw 'unrecognized minor version code: ' + vers.Minor;
|
||||
if(vers.Major > 4 || vers.Major < 2) throw 'unrecognized major version code: ' + vers.Major;
|
||||
o.Flags = blob.read_shift(4); length -= 4;
|
||||
var sz = blob.read_shift(4); length -= 4;
|
||||
o.EncryptionHeader = parse_EncryptionHeader(blob, sz); length -= sz;
|
||||
o.EncryptionVerifier = parse_EncryptionVerifier(blob, length);
|
||||
return o;
|
||||
}
|
||||
/* [MS-OFFCRYPTO] 2.3.6.1 RC4 Encryption Header */
|
||||
function parse_RC4Header(blob, length) {
|
||||
var o = {};
|
||||
var vers = o.EncryptionVersionInfo = parse_Version(blob, 4); length -= 4;
|
||||
if(vers.Major != 1 || vers.Minor != 1) throw 'unrecognized version code ' + vers.Major + ' : ' + vers.Minor;
|
||||
o.Salt = blob.read_shift(16);
|
||||
o.EncryptedVerifier = blob.read_shift(16);
|
||||
o.EncryptedVerifierHash = blob.read_shift(16);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.3.7.1 Binary Document Password Verifier Derivation */
|
||||
function crypto_CreatePasswordVerifier_Method1(Password) {
|
||||
var Verifier = 0x0000, PasswordArray;
|
||||
var PasswordDecoded = _JS2ANSI(Password);
|
||||
var len = PasswordDecoded.length + 1, i, PasswordByte;
|
||||
var Intermediate1, Intermediate2, Intermediate3;
|
||||
PasswordArray = new_raw_buf(len);
|
||||
PasswordArray[0] = PasswordDecoded.length;
|
||||
for(i = 1; i != len; ++i) PasswordArray[i] = PasswordDecoded[i-1];
|
||||
for(i = len-1; i >= 0; --i) {
|
||||
PasswordByte = PasswordArray[i];
|
||||
Intermediate1 = ((Verifier & 0x4000) === 0x0000) ? 0 : 1;
|
||||
Intermediate2 = (Verifier << 1) & 0x7FFF;
|
||||
Intermediate3 = Intermediate1 | Intermediate2;
|
||||
Verifier = Intermediate3 ^ PasswordByte;
|
||||
}
|
||||
return Verifier ^ 0xCE4B;
|
||||
}
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.3.7.2 Binary Document XOR Array Initialization */
|
||||
var crypto_CreateXorArray_Method1 = (function() {
|
||||
var PadArray = [0xBB, 0xFF, 0xFF, 0xBA, 0xFF, 0xFF, 0xB9, 0x80, 0x00, 0xBE, 0x0F, 0x00, 0xBF, 0x0F, 0x00];
|
||||
var InitialCode = [0xE1F0, 0x1D0F, 0xCC9C, 0x84C0, 0x110C, 0x0E10, 0xF1CE, 0x313E, 0x1872, 0xE139, 0xD40F, 0x84F9, 0x280C, 0xA96A, 0x4EC3];
|
||||
var XorMatrix = [0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09, 0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF, 0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0, 0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40, 0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5, 0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A, 0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9, 0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0, 0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC, 0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10, 0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168, 0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C, 0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD, 0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC, 0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4];
|
||||
var Ror = function(Byte) { return ((Byte/2) | (Byte*128)) & 0xFF; };
|
||||
var XorRor = function(byte1, byte2) { return Ror(byte1 ^ byte2); };
|
||||
var CreateXorKey_Method1 = function(Password) {
|
||||
var XorKey = InitialCode[Password.length - 1];
|
||||
var CurrentElement = 0x68;
|
||||
for(var i = Password.length-1; i >= 0; --i) {
|
||||
var Char = Password[i];
|
||||
for(var j = 0; j != 7; ++j) {
|
||||
if(Char & 0x40) XorKey ^= XorMatrix[CurrentElement];
|
||||
Char *= 2; --CurrentElement;
|
||||
}
|
||||
}
|
||||
return XorKey;
|
||||
};
|
||||
return function(password) {
|
||||
var Password = _JS2ANSI(password);
|
||||
var XorKey = CreateXorKey_Method1(Password);
|
||||
var Index = Password.length;
|
||||
var ObfuscationArray = new_raw_buf(16);
|
||||
for(var i = 0; i != 16; ++i) ObfuscationArray[i] = 0x00;
|
||||
var Temp, PasswordLastChar, PadIndex;
|
||||
if((Index & 1) === 1) {
|
||||
Temp = XorKey >> 8;
|
||||
ObfuscationArray[Index] = XorRor(PadArray[0], Temp);
|
||||
--Index;
|
||||
Temp = XorKey & 0xFF;
|
||||
PasswordLastChar = Password[Password.length - 1];
|
||||
ObfuscationArray[Index] = XorRor(PasswordLastChar, Temp);
|
||||
}
|
||||
while(Index > 0) {
|
||||
--Index;
|
||||
Temp = XorKey >> 8;
|
||||
ObfuscationArray[Index] = XorRor(Password[Index], Temp);
|
||||
--Index;
|
||||
Temp = XorKey & 0xFF;
|
||||
ObfuscationArray[Index] = XorRor(Password[Index], Temp);
|
||||
}
|
||||
Index = 15;
|
||||
PadIndex = 15 - Password.length;
|
||||
while(PadIndex > 0) {
|
||||
Temp = XorKey >> 8;
|
||||
ObfuscationArray[Index] = XorRor(PadArray[PadIndex], Temp);
|
||||
--Index;
|
||||
--PadIndex;
|
||||
Temp = XorKey & 0xFF;
|
||||
ObfuscationArray[Index] = XorRor(Password[Index], Temp);
|
||||
--Index;
|
||||
--PadIndex;
|
||||
}
|
||||
return ObfuscationArray;
|
||||
};
|
||||
})();
|
||||
|
||||
/* [MS-OFFCRYPTO] 2.3.7.3 Binary Document XOR Data Transformation Method 1 */
|
||||
var crypto_DecryptData_Method1 = function(password, Data, XorArrayIndex, XorArray, O) {
|
||||
/* If XorArray is set, use it; if O is not set, make changes in-place */
|
||||
if(!O) O = Data;
|
||||
if(!XorArray) XorArray = crypto_CreateXorArray_Method1(password);
|
||||
var Index, Value;
|
||||
for(Index = 0; Index != Data.length; ++Index) {
|
||||
Value = Data[Index];
|
||||
Value ^= XorArray[XorArrayIndex];
|
||||
Value = ((Value>>5) | (Value<<3)) & 0xFF;
|
||||
O[Index] = Value;
|
||||
++XorArrayIndex;
|
||||
}
|
||||
return [O, XorArrayIndex, XorArray];
|
||||
};
|
||||
|
||||
var crypto_MakeXorDecryptor = function(password) {
|
||||
var XorArrayIndex = 0, XorArray = crypto_CreateXorArray_Method1(password);
|
||||
return function(Data) {
|
||||
var O = crypto_DecryptData_Method1(null, Data, XorArrayIndex, XorArray);
|
||||
XorArrayIndex = O[1];
|
||||
return O[0];
|
||||
};
|
||||
};
|
||||
|
||||
/* 2.5.343 */
|
||||
function parse_XORObfuscation(blob, length, opts, out) {
|
||||
var o = { key: parseuint16(blob), verificationBytes: parseuint16(blob) };
|
||||
if(opts.password) o.verifier = crypto_CreatePasswordVerifier_Method1(opts.password);
|
||||
out.valid = o.verificationBytes === o.verifier;
|
||||
if(out.valid) out.insitu_decrypt = crypto_MakeXorDecryptor(opts.password);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.4.117 */
|
||||
function parse_FilePassHeader(blob, length, oo) {
|
||||
var o = oo || {}; o.Info = blob.read_shift(2); blob.l -= 2;
|
||||
if(o.Info === 1) o.Data = parse_RC4Header(blob, length);
|
||||
else o.Data = parse_RC4CryptoHeader(blob, length);
|
||||
return o;
|
||||
}
|
||||
function parse_FilePass(blob, length, opts) {
|
||||
var o = { Type: blob.read_shift(2) }; /* wEncryptionType */
|
||||
if(o.Type) parse_FilePassHeader(blob, length-2, o);
|
||||
else parse_XORObfuscation(blob, length-2, opts, o);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
@ -62,3 +62,23 @@ function find_mdw(collw, coll) {
|
||||
if(MDW === MAX_MDW) MDW = DEF_MDW;
|
||||
}
|
||||
}
|
||||
|
||||
/* [MS-EXSPXML3] 2.4.54 ST_enmPattern */
|
||||
var XLMLPatternTypeMap = {
|
||||
"None": "none",
|
||||
"Solid": "solid",
|
||||
"Gray50": "mediumGray",
|
||||
"Gray75": "darkGray",
|
||||
"Gray25": "lightGray",
|
||||
"HorzStripe": "darkHorizontal",
|
||||
"VertStripe": "darkVertical",
|
||||
"ReverseDiagStripe": "darkDown",
|
||||
"DiagStripe": "darkUp",
|
||||
"DiagCross": "darkGrid",
|
||||
"ThickDiagCross": "darkTrellis",
|
||||
"ThinHorzStripe": "lightHorizontal",
|
||||
"ThinVertStripe": "lightVertical",
|
||||
"ThinReverseDiagStripe": "lightDown",
|
||||
"ThinHorzCross": "lightGrid"
|
||||
};
|
||||
|
||||
|
@ -190,6 +190,7 @@ function parse_borders(t, opts) {
|
||||
if (y.theme) sub_border.color.theme = y.theme;
|
||||
if (y.tint) sub_border.color.tint = y.tint;
|
||||
if (y.rgb) sub_border.color.rgb = y.rgb;
|
||||
if (y.auto) sub_border.color.auto = y.auto;
|
||||
break;
|
||||
case '<name/>':
|
||||
case '</name>':
|
||||
@ -275,7 +276,8 @@ function parse_cellXfs(t, opts) {
|
||||
case '<alignment/>':
|
||||
var alignment = {}
|
||||
if (y.vertical) { alignment.vertical = y.vertical;}
|
||||
if (y.horizontal) { alignment.horizontal = y.horizontal;}
|
||||
if (y.horizontal) { alignment.horizontal = y.horizontal;}
|
||||
if (y.textRotation != undefined) { alignment.textRotation = y.textRotation; }
|
||||
if (y.indent) { alignment.indent = y.indent; }
|
||||
if (y.wrapText) { alignment.wrapText = y.wrapText; }
|
||||
xf.alignment = alignment;
|
||||
|
78
bits/50_styxls.js
Normal file
78
bits/50_styxls.js
Normal file
@ -0,0 +1,78 @@
|
||||
/* [MS-XLS] 2.4.326 TODO: payload is a zip file */
|
||||
function parse_Theme(blob, length) {
|
||||
var dwThemeVersion = blob.read_shift(4);
|
||||
if(dwThemeVersion === 124226) return;
|
||||
blob.l += length-4;
|
||||
}
|
||||
|
||||
/* 2.5.49 */
|
||||
function parse_ColorTheme(blob, length) { return blob.read_shift(4); }
|
||||
|
||||
/* 2.5.155 */
|
||||
function parse_FullColorExt(blob, length) {
|
||||
var o = {};
|
||||
o.xclrType = blob.read_shift(2);
|
||||
o.nTintShade = blob.read_shift(2);
|
||||
switch(o.xclrType) {
|
||||
case 0: blob.l += 4; break;
|
||||
case 1: o.xclrValue = parse_IcvXF(blob, 4); break;
|
||||
case 2: o.xclrValue = parse_LongRGBA(blob, 4); break;
|
||||
case 3: o.xclrValue = parse_ColorTheme(blob, 4); break;
|
||||
case 4: blob.l += 4; break;
|
||||
}
|
||||
blob.l += 8;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.5.164 TODO: read 7 bits*/
|
||||
function parse_IcvXF(blob, length) {
|
||||
return parsenoop(blob, length);
|
||||
}
|
||||
|
||||
/* 2.5.280 */
|
||||
function parse_XFExtGradient(blob, length) {
|
||||
return parsenoop(blob, length);
|
||||
}
|
||||
|
||||
/* 2.5.108 */
|
||||
function parse_ExtProp(blob, length) {
|
||||
var extType = blob.read_shift(2);
|
||||
var cb = blob.read_shift(2);
|
||||
var o = [extType];
|
||||
switch(extType) {
|
||||
case 0x04: case 0x05: case 0x07: case 0x08:
|
||||
case 0x09: case 0x0A: case 0x0B: case 0x0D:
|
||||
o[1] = parse_FullColorExt(blob, cb); break;
|
||||
case 0x06: o[1] = parse_XFExtGradient(blob, cb); break;
|
||||
case 0x0E: case 0x0F: o[1] = blob.read_shift(cb === 5 ? 1 : 2); break;
|
||||
default: throw new Error("Unrecognized ExtProp type: " + extType + " " + cb);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.4.355 */
|
||||
function parse_XFExt(blob, length) {
|
||||
var end = blob.l + length;
|
||||
blob.l += 2;
|
||||
var ixfe = blob.read_shift(2);
|
||||
blob.l += 2;
|
||||
var cexts = blob.read_shift(2);
|
||||
var ext = [];
|
||||
while(cexts-- > 0) ext.push(parse_ExtProp(blob, end-blob.l));
|
||||
return {ixfe:ixfe, ext:ext};
|
||||
}
|
||||
|
||||
/* xf is an XF, see parse_XFExt for xfext */
|
||||
function update_xfext(xf, xfext) {
|
||||
xfext.forEach(function(xfe) {
|
||||
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 0x0d: break; /* text color */
|
||||
case 0x0e: break; /* font scheme */
|
||||
default: throw "bafuq" + xfe[0].toString(16);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
17
bits/61_fcommon.js
Normal file
17
bits/61_fcommon.js
Normal file
@ -0,0 +1,17 @@
|
||||
/* TODO: it will be useful to parse the function str */
|
||||
var rc_to_a1 = (function(){
|
||||
var rcregex = /(^|[^A-Za-z])R(\[?)(-?\d+|)\]?C(\[?)(-?\d+|)\]?/g;
|
||||
var rcbase;
|
||||
function rcfunc($$,$1,$2,$3,$4,$5) {
|
||||
var R = $3.length>0?parseInt($3,10)|0:0, C = $5.length>0?parseInt($5,10)|0:0;
|
||||
if(C<0 && $4.length === 0) C=0;
|
||||
if($4.length > 0) C += rcbase.c;
|
||||
if($2.length > 0) R += rcbase.r;
|
||||
return $1 + encode_col(C) + encode_row(R);
|
||||
}
|
||||
return function rc_to_a1(fstr, base) {
|
||||
rcbase = base;
|
||||
return fstr.replace(rcregex, rcfunc);
|
||||
};
|
||||
})();
|
||||
|
803
bits/62_fxls.js
Normal file
803
bits/62_fxls.js
Normal file
@ -0,0 +1,803 @@
|
||||
/* --- formula references point to MS-XLS --- */
|
||||
/* Small helpers */
|
||||
function parseread(l) { return function(blob, length) { blob.l+=l; return; }; }
|
||||
function parseread1(blob, length) { blob.l+=1; return; }
|
||||
|
||||
/* Rgce Helpers */
|
||||
|
||||
/* 2.5.51 */
|
||||
function parse_ColRelU(blob, length) {
|
||||
var c = blob.read_shift(2);
|
||||
return [c & 0x3FFF, (c >> 14) & 1, (c >> 15) & 1];
|
||||
}
|
||||
|
||||
/* 2.5.198.105 */
|
||||
function parse_RgceArea(blob, length) {
|
||||
var r=blob.read_shift(2), R=blob.read_shift(2);
|
||||
var c=parse_ColRelU(blob, 2);
|
||||
var C=parse_ColRelU(blob, 2);
|
||||
return { s:{r:r, c:c[0], cRel:c[1], rRel:c[2]}, e:{r:R, c:C[0], cRel:C[1], rRel:C[2]} };
|
||||
}
|
||||
|
||||
/* 2.5.198.105 TODO */
|
||||
function parse_RgceAreaRel(blob, length) {
|
||||
var r=blob.read_shift(2), R=blob.read_shift(2);
|
||||
var c=parse_ColRelU(blob, 2);
|
||||
var C=parse_ColRelU(blob, 2);
|
||||
return { s:{r:r, c:c[0], cRel:c[1], rRel:c[2]}, e:{r:R, c:C[0], cRel:C[1], rRel:C[2]} };
|
||||
}
|
||||
|
||||
/* 2.5.198.109 */
|
||||
function parse_RgceLoc(blob, length) {
|
||||
var r = blob.read_shift(2);
|
||||
var c = parse_ColRelU(blob, 2);
|
||||
return {r:r, c:c[0], cRel:c[1], rRel:c[2]};
|
||||
}
|
||||
|
||||
/* 2.5.198.111 */
|
||||
function parse_RgceLocRel(blob, length) {
|
||||
var r = blob.read_shift(2);
|
||||
var cl = blob.read_shift(2);
|
||||
var cRel = (cl & 0x8000) >> 15, rRel = (cl & 0x4000) >> 14;
|
||||
cl &= 0x3FFF;
|
||||
if(cRel !== 0) while(cl >= 0x100) cl -= 0x100;
|
||||
return {r:r,c:cl,cRel:cRel,rRel:rRel};
|
||||
}
|
||||
|
||||
/* Ptg Tokens */
|
||||
|
||||
/* 2.5.198.27 */
|
||||
function parse_PtgArea(blob, length) {
|
||||
var type = (blob[blob.l++] & 0x60) >> 5;
|
||||
var area = parse_RgceArea(blob, 8);
|
||||
return [type, area];
|
||||
}
|
||||
|
||||
/* 2.5.198.28 */
|
||||
function parse_PtgArea3d(blob, length) {
|
||||
var type = (blob[blob.l++] & 0x60) >> 5;
|
||||
var ixti = blob.read_shift(2);
|
||||
var area = parse_RgceArea(blob, 8);
|
||||
return [type, ixti, area];
|
||||
}
|
||||
|
||||
/* 2.5.198.29 */
|
||||
function parse_PtgAreaErr(blob, length) {
|
||||
var type = (blob[blob.l++] & 0x60) >> 5;
|
||||
blob.l += 8;
|
||||
return [type];
|
||||
}
|
||||
/* 2.5.198.30 */
|
||||
function parse_PtgAreaErr3d(blob, length) {
|
||||
var type = (blob[blob.l++] & 0x60) >> 5;
|
||||
var ixti = blob.read_shift(2);
|
||||
blob.l += 8;
|
||||
return [type, ixti];
|
||||
}
|
||||
|
||||
/* 2.5.198.31 */
|
||||
function parse_PtgAreaN(blob, length) {
|
||||
var type = (blob[blob.l++] & 0x60) >> 5;
|
||||
var area = parse_RgceAreaRel(blob, 8);
|
||||
return [type, area];
|
||||
}
|
||||
|
||||
/* 2.5.198.32 -- ignore this and look in PtgExtraArray for shape + values */
|
||||
function parse_PtgArray(blob, length) {
|
||||
var type = (blob[blob.l++] & 0x60) >> 5;
|
||||
blob.l += 7;
|
||||
return [type];
|
||||
}
|
||||
|
||||
/* 2.5.198.33 */
|
||||
function parse_PtgAttrBaxcel(blob, length) {
|
||||
var bitSemi = blob[blob.l+1] & 0x01; /* 1 = volatile */
|
||||
var bitBaxcel = 1;
|
||||
blob.l += 4;
|
||||
return [bitSemi, bitBaxcel];
|
||||
}
|
||||
|
||||
/* 2.5.198.34 */
|
||||
function parse_PtgAttrChoose(blob, length) {
|
||||
blob.l +=2;
|
||||
var offset = blob.read_shift(2);
|
||||
var o = [];
|
||||
/* offset is 1 less than the number of elements */
|
||||
for(var i = 0; i <= offset; ++i) o.push(blob.read_shift(2));
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.5.198.35 */
|
||||
function parse_PtgAttrGoto(blob, length) {
|
||||
var bitGoto = (blob[blob.l+1] & 0xFF) ? 1 : 0;
|
||||
blob.l += 2;
|
||||
return [bitGoto, blob.read_shift(2)];
|
||||
}
|
||||
|
||||
/* 2.5.198.36 */
|
||||
function parse_PtgAttrIf(blob, length) {
|
||||
var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0;
|
||||
blob.l += 2;
|
||||
return [bitIf, blob.read_shift(2)];
|
||||
}
|
||||
|
||||
/* 2.5.198.37 */
|
||||
function parse_PtgAttrSemi(blob, length) {
|
||||
var bitSemi = (blob[blob.l+1] & 0xFF) ? 1 : 0;
|
||||
blob.l += 4;
|
||||
return [bitSemi];
|
||||
}
|
||||
|
||||
/* 2.5.198.40 (used by PtgAttrSpace and PtgAttrSpaceSemi) */
|
||||
function parse_PtgAttrSpaceType(blob, length) {
|
||||
var type = blob.read_shift(1), cch = blob.read_shift(1);
|
||||
return [type, cch];
|
||||
}
|
||||
|
||||
/* 2.5.198.38 */
|
||||
function parse_PtgAttrSpace(blob, length) {
|
||||
blob.read_shift(2);
|
||||
return parse_PtgAttrSpaceType(blob, 2);
|
||||
}
|
||||
|
||||
/* 2.5.198.39 */
|
||||
function parse_PtgAttrSpaceSemi(blob, length) {
|
||||
blob.read_shift(2);
|
||||
return parse_PtgAttrSpaceType(blob, 2);
|
||||
}
|
||||
|
||||
/* 2.5.198.84 TODO */
|
||||
function parse_PtgRef(blob, length) {
|
||||
var ptg = blob[blob.l] & 0x1F;
|
||||
var type = (blob[blob.l] & 0x60)>>5;
|
||||
blob.l += 1;
|
||||
var loc = parse_RgceLoc(blob,4);
|
||||
return [type, loc];
|
||||
}
|
||||
|
||||
/* 2.5.198.88 TODO */
|
||||
function parse_PtgRefN(blob, length) {
|
||||
var ptg = blob[blob.l] & 0x1F;
|
||||
var type = (blob[blob.l] & 0x60)>>5;
|
||||
blob.l += 1;
|
||||
var loc = parse_RgceLocRel(blob,4);
|
||||
return [type, loc];
|
||||
}
|
||||
|
||||
/* 2.5.198.85 TODO */
|
||||
function parse_PtgRef3d(blob, length) {
|
||||
var ptg = blob[blob.l] & 0x1F;
|
||||
var type = (blob[blob.l] & 0x60)>>5;
|
||||
blob.l += 1;
|
||||
var ixti = blob.read_shift(2); // XtiIndex
|
||||
var loc = parse_RgceLoc(blob,4);
|
||||
return [type, ixti, loc];
|
||||
}
|
||||
|
||||
|
||||
/* 2.5.198.62 TODO */
|
||||
function parse_PtgFunc(blob, length) {
|
||||
var ptg = blob[blob.l] & 0x1F;
|
||||
var type = (blob[blob.l] & 0x60)>>5;
|
||||
blob.l += 1;
|
||||
var iftab = blob.read_shift(2);
|
||||
return [FtabArgc[iftab], Ftab[iftab]];
|
||||
}
|
||||
/* 2.5.198.63 TODO */
|
||||
function parse_PtgFuncVar(blob, length) {
|
||||
blob.l++;
|
||||
var cparams = blob.read_shift(1), tab = parsetab(blob);
|
||||
return [cparams, (tab[0] === 0 ? Ftab : Cetab)[tab[1]]];
|
||||
}
|
||||
|
||||
function parsetab(blob, length) {
|
||||
return [blob[blob.l+1]>>7, blob.read_shift(2) & 0x7FFF];
|
||||
}
|
||||
|
||||
/* 2.5.198.41 */
|
||||
var parse_PtgAttrSum = parseread(4);
|
||||
/* 2.5.198.43 */
|
||||
var parse_PtgConcat = parseread1;
|
||||
|
||||
/* 2.5.198.58 */
|
||||
function parse_PtgExp(blob, length) {
|
||||
blob.l++;
|
||||
var row = blob.read_shift(2);
|
||||
var col = blob.read_shift(2);
|
||||
return [row, col];
|
||||
}
|
||||
|
||||
/* 2.5.198.57 */
|
||||
function parse_PtgErr(blob, length) { blob.l++; return BErr[blob.read_shift(1)]; }
|
||||
|
||||
/* 2.5.198.66 TODO */
|
||||
function parse_PtgInt(blob, length) { blob.l++; return blob.read_shift(2); }
|
||||
|
||||
/* 2.5.198.42 */
|
||||
function parse_PtgBool(blob, length) { blob.l++; return blob.read_shift(1)!==0;}
|
||||
|
||||
/* 2.5.198.79 */
|
||||
function parse_PtgNum(blob, length) { blob.l++; return parse_Xnum(blob, 8); }
|
||||
|
||||
/* 2.5.198.89 */
|
||||
function parse_PtgStr(blob, length) { blob.l++; return parse_ShortXLUnicodeString(blob); }
|
||||
|
||||
/* 2.5.192.112 + 2.5.192.11{3,4,5,6,7} */
|
||||
function parse_SerAr(blob) {
|
||||
var val = [];
|
||||
switch((val[0] = blob.read_shift(1))) {
|
||||
/* 2.5.192.113 */
|
||||
case 0x04: /* SerBool -- boolean */
|
||||
val[1] = parsebool(blob, 1) ? 'TRUE' : 'FALSE';
|
||||
blob.l += 7; break;
|
||||
/* 2.5.192.114 */
|
||||
case 0x10: /* SerErr -- error */
|
||||
val[1] = BErr[blob[blob.l]];
|
||||
blob.l += 8; break;
|
||||
/* 2.5.192.115 */
|
||||
case 0x00: /* SerNil -- honestly, I'm not sure how to reproduce this */
|
||||
blob.l += 8; break;
|
||||
/* 2.5.192.116 */
|
||||
case 0x01: /* SerNum -- Xnum */
|
||||
val[1] = parse_Xnum(blob, 8); break;
|
||||
/* 2.5.192.117 */
|
||||
case 0x02: /* SerStr -- XLUnicodeString (<256 chars) */
|
||||
val[1] = parse_XLUnicodeString(blob); break;
|
||||
// default: throw "Bad SerAr: " + val[0]; /* Unreachable */
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/* 2.5.198.61 */
|
||||
function parse_PtgExtraMem(blob, cce) {
|
||||
var count = blob.read_shift(2);
|
||||
var out = [];
|
||||
for(var i = 0; i != count; ++i) out.push(parse_Ref8U(blob, 8));
|
||||
return out;
|
||||
}
|
||||
|
||||
/* 2.5.198.59 */
|
||||
function parse_PtgExtraArray(blob) {
|
||||
var cols = 1 + blob.read_shift(1); //DColByteU
|
||||
var rows = 1 + blob.read_shift(2); //DRw
|
||||
for(var i = 0, o=[]; i != rows && (o[i] = []); ++i)
|
||||
for(var j = 0; j != cols; ++j) o[i][j] = parse_SerAr(blob);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.5.198.76 */
|
||||
function parse_PtgName(blob, length) {
|
||||
var type = (blob.read_shift(1) >>> 5) & 0x03;
|
||||
var nameindex = blob.read_shift(4);
|
||||
return [type, 0, nameindex];
|
||||
}
|
||||
|
||||
/* 2.5.198.77 */
|
||||
function parse_PtgNameX(blob, length) {
|
||||
var type = (blob.read_shift(1) >>> 5) & 0x03;
|
||||
var ixti = blob.read_shift(2); // XtiIndex
|
||||
var nameindex = blob.read_shift(4);
|
||||
return [type, ixti, nameindex];
|
||||
}
|
||||
|
||||
/* 2.5.198.70 */
|
||||
function parse_PtgMemArea(blob, length) {
|
||||
var type = (blob.read_shift(1) >>> 5) & 0x03;
|
||||
blob.l += 4;
|
||||
var cce = blob.read_shift(2);
|
||||
return [type, cce];
|
||||
}
|
||||
|
||||
/* 2.5.198.72 */
|
||||
function parse_PtgMemFunc(blob, length) {
|
||||
var type = (blob.read_shift(1) >>> 5) & 0x03;
|
||||
var cce = blob.read_shift(2);
|
||||
return [type, cce];
|
||||
}
|
||||
|
||||
|
||||
/* 2.5.198.86 */
|
||||
function parse_PtgRefErr(blob, length) {
|
||||
var type = (blob.read_shift(1) >>> 5) & 0x03;
|
||||
blob.l += 4;
|
||||
return [type];
|
||||
}
|
||||
|
||||
/* 2.5.198.26 */
|
||||
var parse_PtgAdd = parseread1;
|
||||
/* 2.5.198.45 */
|
||||
var parse_PtgDiv = parseread1;
|
||||
/* 2.5.198.56 */
|
||||
var parse_PtgEq = parseread1;
|
||||
/* 2.5.198.64 */
|
||||
var parse_PtgGe = parseread1;
|
||||
/* 2.5.198.65 */
|
||||
var parse_PtgGt = parseread1;
|
||||
/* 2.5.198.67 */
|
||||
var parse_PtgIsect = parseread1;
|
||||
/* 2.5.198.68 */
|
||||
var parse_PtgLe = parseread1;
|
||||
/* 2.5.198.69 */
|
||||
var parse_PtgLt = parseread1;
|
||||
/* 2.5.198.74 */
|
||||
var parse_PtgMissArg = parseread1;
|
||||
/* 2.5.198.75 */
|
||||
var parse_PtgMul = parseread1;
|
||||
/* 2.5.198.78 */
|
||||
var parse_PtgNe = parseread1;
|
||||
/* 2.5.198.80 */
|
||||
var parse_PtgParen = parseread1;
|
||||
/* 2.5.198.81 */
|
||||
var parse_PtgPercent = parseread1;
|
||||
/* 2.5.198.82 */
|
||||
var parse_PtgPower = parseread1;
|
||||
/* 2.5.198.83 */
|
||||
var parse_PtgRange = parseread1;
|
||||
/* 2.5.198.90 */
|
||||
var parse_PtgSub = parseread1;
|
||||
/* 2.5.198.93 */
|
||||
var parse_PtgUminus = parseread1;
|
||||
/* 2.5.198.94 */
|
||||
var parse_PtgUnion = parseread1;
|
||||
/* 2.5.198.95 */
|
||||
var parse_PtgUplus = parseread1;
|
||||
|
||||
/* 2.5.198.71 */
|
||||
var parse_PtgMemErr = parsenoop;
|
||||
/* 2.5.198.73 */
|
||||
var parse_PtgMemNoMem = parsenoop;
|
||||
/* 2.5.198.87 */
|
||||
var parse_PtgRefErr3d = parsenoop;
|
||||
/* 2.5.198.92 */
|
||||
var parse_PtgTbl = parsenoop;
|
||||
|
||||
/* 2.5.198.25 */
|
||||
var PtgTypes = {
|
||||
0x01: { n:'PtgExp', f:parse_PtgExp },
|
||||
0x02: { n:'PtgTbl', f:parse_PtgTbl },
|
||||
0x03: { n:'PtgAdd', f:parse_PtgAdd },
|
||||
0x04: { n:'PtgSub', f:parse_PtgSub },
|
||||
0x05: { n:'PtgMul', f:parse_PtgMul },
|
||||
0x06: { n:'PtgDiv', f:parse_PtgDiv },
|
||||
0x07: { n:'PtgPower', f:parse_PtgPower },
|
||||
0x08: { n:'PtgConcat', f:parse_PtgConcat },
|
||||
0x09: { n:'PtgLt', f:parse_PtgLt },
|
||||
0x0A: { n:'PtgLe', f:parse_PtgLe },
|
||||
0x0B: { n:'PtgEq', f:parse_PtgEq },
|
||||
0x0C: { n:'PtgGe', f:parse_PtgGe },
|
||||
0x0D: { n:'PtgGt', f:parse_PtgGt },
|
||||
0x0E: { n:'PtgNe', f:parse_PtgNe },
|
||||
0x0F: { n:'PtgIsect', f:parse_PtgIsect },
|
||||
0x10: { n:'PtgUnion', f:parse_PtgUnion },
|
||||
0x11: { n:'PtgRange', f:parse_PtgRange },
|
||||
0x12: { n:'PtgUplus', f:parse_PtgUplus },
|
||||
0x13: { n:'PtgUminus', f:parse_PtgUminus },
|
||||
0x14: { n:'PtgPercent', f:parse_PtgPercent },
|
||||
0x15: { n:'PtgParen', f:parse_PtgParen },
|
||||
0x16: { n:'PtgMissArg', f:parse_PtgMissArg },
|
||||
0x17: { n:'PtgStr', f:parse_PtgStr },
|
||||
0x1C: { n:'PtgErr', f:parse_PtgErr },
|
||||
0x1D: { n:'PtgBool', f:parse_PtgBool },
|
||||
0x1E: { n:'PtgInt', f:parse_PtgInt },
|
||||
0x1F: { n:'PtgNum', f:parse_PtgNum },
|
||||
0x20: { n:'PtgArray', f:parse_PtgArray },
|
||||
0x21: { n:'PtgFunc', f:parse_PtgFunc },
|
||||
0x22: { n:'PtgFuncVar', f:parse_PtgFuncVar },
|
||||
0x23: { n:'PtgName', f:parse_PtgName },
|
||||
0x24: { n:'PtgRef', f:parse_PtgRef },
|
||||
0x25: { n:'PtgArea', f:parse_PtgArea },
|
||||
0x26: { n:'PtgMemArea', f:parse_PtgMemArea },
|
||||
0x27: { n:'PtgMemErr', f:parse_PtgMemErr },
|
||||
0x28: { n:'PtgMemNoMem', f:parse_PtgMemNoMem },
|
||||
0x29: { n:'PtgMemFunc', f:parse_PtgMemFunc },
|
||||
0x2A: { n:'PtgRefErr', f:parse_PtgRefErr },
|
||||
0x2B: { n:'PtgAreaErr', f:parse_PtgAreaErr },
|
||||
0x2C: { n:'PtgRefN', f:parse_PtgRefN },
|
||||
0x2D: { n:'PtgAreaN', f:parse_PtgAreaN },
|
||||
0x39: { n:'PtgNameX', f:parse_PtgNameX },
|
||||
0x3A: { n:'PtgRef3d', f:parse_PtgRef3d },
|
||||
0x3B: { n:'PtgArea3d', f:parse_PtgArea3d },
|
||||
0x3C: { n:'PtgRefErr3d', f:parse_PtgRefErr3d },
|
||||
0x3D: { n:'PtgAreaErr3d', f:parse_PtgAreaErr3d },
|
||||
0xFF: {}
|
||||
};
|
||||
/* These are duplicated in the PtgTypes table */
|
||||
var PtgDupes = {
|
||||
0x40: 0x20, 0x60: 0x20,
|
||||
0x41: 0x21, 0x61: 0x21,
|
||||
0x42: 0x22, 0x62: 0x22,
|
||||
0x43: 0x23, 0x63: 0x23,
|
||||
0x44: 0x24, 0x64: 0x24,
|
||||
0x45: 0x25, 0x65: 0x25,
|
||||
0x46: 0x26, 0x66: 0x26,
|
||||
0x47: 0x27, 0x67: 0x27,
|
||||
0x48: 0x28, 0x68: 0x28,
|
||||
0x49: 0x29, 0x69: 0x29,
|
||||
0x4A: 0x2A, 0x6A: 0x2A,
|
||||
0x4B: 0x2B, 0x6B: 0x2B,
|
||||
0x4C: 0x2C, 0x6C: 0x2C,
|
||||
0x4D: 0x2D, 0x6D: 0x2D,
|
||||
0x59: 0x39, 0x79: 0x39,
|
||||
0x5A: 0x3A, 0x7A: 0x3A,
|
||||
0x5B: 0x3B, 0x7B: 0x3B,
|
||||
0x5C: 0x3C, 0x7C: 0x3C,
|
||||
0x5D: 0x3D, 0x7D: 0x3D
|
||||
};
|
||||
(function(){for(var y in PtgDupes) PtgTypes[y] = PtgTypes[PtgDupes[y]];})();
|
||||
|
||||
var Ptg18 = {};
|
||||
var Ptg19 = {
|
||||
0x01: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
|
||||
0x02: { n:'PtgAttrIf', f:parse_PtgAttrIf },
|
||||
0x04: { n:'PtgAttrChoose', f:parse_PtgAttrChoose },
|
||||
0x08: { n:'PtgAttrGoto', f:parse_PtgAttrGoto },
|
||||
0x10: { n:'PtgAttrSum', f:parse_PtgAttrSum },
|
||||
0x20: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
|
||||
0x40: { n:'PtgAttrSpace', f:parse_PtgAttrSpace },
|
||||
0x41: { n:'PtgAttrSpaceSemi', f:parse_PtgAttrSpaceSemi },
|
||||
0xFF: {}
|
||||
};
|
||||
|
||||
/* 2.4.127 TODO */
|
||||
function parse_Formula(blob, length, opts) {
|
||||
var cell = parse_XLSCell(blob, 6);
|
||||
var val = parse_FormulaValue(blob,8);
|
||||
var flags = blob.read_shift(1);
|
||||
blob.read_shift(1);
|
||||
var chn = blob.read_shift(4);
|
||||
var cbf = "";
|
||||
if(opts.biff === 5) blob.l += length-20;
|
||||
else cbf = parse_XLSCellParsedFormula(blob, length-20, opts);
|
||||
return {cell:cell, val:val[0], formula:cbf, shared: (flags >> 3) & 1, tt:val[1]};
|
||||
}
|
||||
|
||||
/* 2.5.133 TODO: how to emit empty strings? */
|
||||
function parse_FormulaValue(blob) {
|
||||
var b;
|
||||
if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return [parse_Xnum(blob),'n'];
|
||||
switch(blob[blob.l]) {
|
||||
case 0x00: blob.l += 8; return ["String", 's'];
|
||||
case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return [b,'b'];
|
||||
case 0x02: b = blob[blob.l+2]; blob.l += 8; return [b,'e'];
|
||||
case 0x03: blob.l += 8; return ["",'s'];
|
||||
}
|
||||
}
|
||||
|
||||
/* 2.5.198.103 */
|
||||
function parse_RgbExtra(blob, length, rgce, opts) {
|
||||
if(opts.biff < 8) return parsenoop(blob, length);
|
||||
var target = blob.l + length;
|
||||
var o = [];
|
||||
for(var i = 0; i !== rgce.length; ++i) {
|
||||
switch(rgce[i][0]) {
|
||||
case 'PtgArray': /* PtgArray -> PtgExtraArray */
|
||||
rgce[i][1] = parse_PtgExtraArray(blob);
|
||||
o.push(rgce[i][1]);
|
||||
break;
|
||||
case 'PtgMemArea': /* PtgMemArea -> PtgExtraMem */
|
||||
rgce[i][2] = parse_PtgExtraMem(blob, rgce[i][1]);
|
||||
o.push(rgce[i][2]);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
length = target - blob.l;
|
||||
if(length !== 0) o.push(parsenoop(blob, length));
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 2.5.198.21 */
|
||||
function parse_NameParsedFormula(blob, length, opts, cce) {
|
||||
var target = blob.l + length;
|
||||
var rgce = parse_Rgce(blob, cce);
|
||||
var rgcb;
|
||||
if(target !== blob.l) rgcb = parse_RgbExtra(blob, target - blob.l, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* 2.5.198.3 TODO */
|
||||
function parse_XLSCellParsedFormula(blob, length, opts) {
|
||||
var target = blob.l + length;
|
||||
var rgcb, cce = blob.read_shift(2); // length of rgce
|
||||
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
|
||||
var rgce = parse_Rgce(blob, cce);
|
||||
if(length !== cce + 2) rgcb = parse_RgbExtra(blob, length - cce - 2, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* 2.5.198.118 TODO */
|
||||
function parse_SharedParsedFormula(blob, length, opts) {
|
||||
var target = blob.l + length;
|
||||
var rgcb, cce = blob.read_shift(2); // length of rgce
|
||||
var rgce = parse_Rgce(blob, cce);
|
||||
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
|
||||
if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* 2.5.198.1 TODO */
|
||||
function parse_ArrayParsedFormula(blob, length, opts, ref) {
|
||||
var target = blob.l + length;
|
||||
var rgcb, cce = blob.read_shift(2); // length of rgce
|
||||
if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
|
||||
var rgce = parse_Rgce(blob, cce);
|
||||
if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
|
||||
return [rgce, rgcb];
|
||||
}
|
||||
|
||||
/* 2.5.198.104 */
|
||||
function parse_Rgce(blob, length) {
|
||||
var target = blob.l + length;
|
||||
var R, id, ptgs = [];
|
||||
while(target != blob.l) {
|
||||
length = target - blob.l;
|
||||
id = blob[blob.l];
|
||||
R = PtgTypes[id];
|
||||
//console.log("ptg", id, R)
|
||||
if(id === 0x18 || id === 0x19) {
|
||||
id = blob[blob.l + 1];
|
||||
R = (id === 0x18 ? Ptg18 : Ptg19)[id];
|
||||
}
|
||||
if(!R || !R.f) { ptgs.push(parsenoop(blob, length)); }
|
||||
else { ptgs.push([R.n, R.f(blob, length)]); }
|
||||
}
|
||||
return ptgs;
|
||||
}
|
||||
|
||||
function mapper(x) { return x.map(function f2(y) { return y[1];}).join(",");}
|
||||
|
||||
/* 2.2.2 + Magic TODO */
|
||||
function stringify_formula(formula, range, cell, supbooks, opts) {
|
||||
if(opts !== undefined && opts.biff === 5) return "BIFF5??";
|
||||
var _range = range !== undefined ? range : {s:{c:0, r:0}};
|
||||
var stack = [], e1, e2, type, c, ixti, nameidx, r;
|
||||
if(!formula[0] || !formula[0][0]) return "";
|
||||
//console.log("--",cell,formula[0])
|
||||
for(var ff = 0, fflen = formula[0].length; ff < fflen; ++ff) {
|
||||
var f = formula[0][ff];
|
||||
//console.log("++",f, stack)
|
||||
switch(f[0]) {
|
||||
/* 2.2.2.1 Unary Operator Tokens */
|
||||
/* 2.5.198.93 */
|
||||
case 'PtgUminus': stack.push("-" + stack.pop()); break;
|
||||
/* 2.5.198.95 */
|
||||
case 'PtgUplus': stack.push("+" + stack.pop()); break;
|
||||
/* 2.5.198.81 */
|
||||
case 'PtgPercent': stack.push(stack.pop() + "%"); break;
|
||||
|
||||
/* 2.2.2.1 Binary Value Operator Token */
|
||||
/* 2.5.198.26 */
|
||||
case 'PtgAdd':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"+"+e1);
|
||||
break;
|
||||
/* 2.5.198.90 */
|
||||
case 'PtgSub':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"-"+e1);
|
||||
break;
|
||||
/* 2.5.198.75 */
|
||||
case 'PtgMul':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"*"+e1);
|
||||
break;
|
||||
/* 2.5.198.45 */
|
||||
case 'PtgDiv':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"/"+e1);
|
||||
break;
|
||||
/* 2.5.198.82 */
|
||||
case 'PtgPower':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"^"+e1);
|
||||
break;
|
||||
/* 2.5.198.43 */
|
||||
case 'PtgConcat':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"&"+e1);
|
||||
break;
|
||||
/* 2.5.198.69 */
|
||||
case 'PtgLt':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"<"+e1);
|
||||
break;
|
||||
/* 2.5.198.68 */
|
||||
case 'PtgLe':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"<="+e1);
|
||||
break;
|
||||
/* 2.5.198.56 */
|
||||
case 'PtgEq':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"="+e1);
|
||||
break;
|
||||
/* 2.5.198.64 */
|
||||
case 'PtgGe':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+">="+e1);
|
||||
break;
|
||||
/* 2.5.198.65 */
|
||||
case 'PtgGt':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+">"+e1);
|
||||
break;
|
||||
/* 2.5.198.78 */
|
||||
case 'PtgNe':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+"<>"+e1);
|
||||
break;
|
||||
|
||||
/* 2.2.2.1 Binary Reference Operator Token */
|
||||
/* 2.5.198.67 */
|
||||
case 'PtgIsect':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+" "+e1);
|
||||
break;
|
||||
case 'PtgUnion':
|
||||
e1 = stack.pop(); e2 = stack.pop();
|
||||
stack.push(e2+","+e1);
|
||||
break;
|
||||
case 'PtgRange': break;
|
||||
|
||||
/* 2.2.2.3 Control Tokens "can be ignored" */
|
||||
/* 2.5.198.34 */
|
||||
case 'PtgAttrChoose': break;
|
||||
/* 2.5.198.35 */
|
||||
case 'PtgAttrGoto': break;
|
||||
/* 2.5.198.36 */
|
||||
case 'PtgAttrIf': break;
|
||||
|
||||
|
||||
/* 2.5.198.84 */
|
||||
case 'PtgRef':
|
||||
type = f[1][0]; c = shift_cell_xls(decode_cell(encode_cell(f[1][1])), _range);
|
||||
stack.push(encode_cell(c));
|
||||
break;
|
||||
/* 2.5.198.88 */
|
||||
case 'PtgRefN':
|
||||
type = f[1][0]; c = shift_cell_xls(decode_cell(encode_cell(f[1][1])), cell);
|
||||
stack.push(encode_cell(c));
|
||||
break;
|
||||
case 'PtgRef3d': // TODO: lots of stuff
|
||||
type = f[1][0]; ixti = f[1][1]; c = shift_cell_xls(f[1][2], _range);
|
||||
stack.push(supbooks[1][ixti+1]+"!"+encode_cell(c));
|
||||
break;
|
||||
|
||||
/* Function Call */
|
||||
/* 2.5.198.62 */
|
||||
case 'PtgFunc':
|
||||
/* 2.5.198.63 */
|
||||
case 'PtgFuncVar':
|
||||
/* f[1] = [argc, func] */
|
||||
var argc = f[1][0], func = f[1][1];
|
||||
if(!argc) argc = 0;
|
||||
var args = stack.slice(-argc);
|
||||
stack.length -= argc;
|
||||
if(func === 'User') func = args.shift();
|
||||
stack.push(func + "(" + args.join(",") + ")");
|
||||
break;
|
||||
|
||||
/* 2.5.198.42 */
|
||||
case 'PtgBool': stack.push(f[1] ? "TRUE" : "FALSE"); break;
|
||||
/* 2.5.198.66 */
|
||||
case 'PtgInt': stack.push(f[1]); break;
|
||||
/* 2.5.198.79 TODO: precision? */
|
||||
case 'PtgNum': stack.push(String(f[1])); break;
|
||||
/* 2.5.198.89 */
|
||||
case 'PtgStr': stack.push('"' + f[1] + '"'); break;
|
||||
/* 2.5.198.57 */
|
||||
case 'PtgErr': stack.push(f[1]); break;
|
||||
/* 2.5.198.27 TODO: fixed points */
|
||||
case 'PtgArea':
|
||||
type = f[1][0]; r = shift_range_xls(f[1][1], _range);
|
||||
stack.push(encode_range(r));
|
||||
break;
|
||||
/* 2.5.198.28 */
|
||||
case 'PtgArea3d': // TODO: lots of stuff
|
||||
type = f[1][0]; ixti = f[1][1]; r = f[1][2];
|
||||
stack.push(supbooks[1][ixti+1]+"!"+encode_range(r));
|
||||
break;
|
||||
/* 2.5.198.41 */
|
||||
case 'PtgAttrSum':
|
||||
stack.push("SUM(" + stack.pop() + ")");
|
||||
break;
|
||||
|
||||
/* Expression Prefixes */
|
||||
/* 2.5.198.37 */
|
||||
case 'PtgAttrSemi': break;
|
||||
|
||||
/* 2.5.97.60 TODO: do something different for revisions */
|
||||
case 'PtgName':
|
||||
/* f[1] = type, 0, nameindex */
|
||||
nameidx = f[1][2];
|
||||
var lbl = supbooks[0][nameidx];
|
||||
var name = lbl.Name;
|
||||
if(name in XLSXFutureFunctions) name = XLSXFutureFunctions[name];
|
||||
stack.push(name);
|
||||
break;
|
||||
|
||||
/* 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;
|
||||
/* TODO: Properly handle missing values */
|
||||
if(supbooks[bookidx+1]) externbook = supbooks[bookidx+1][nameidx];
|
||||
else if(supbooks[bookidx-1]) externbook = supbooks[bookidx-1][nameidx];
|
||||
if(!externbook) externbook = {body: "??NAMEX??"};
|
||||
stack.push(externbook.body);
|
||||
break;
|
||||
|
||||
/* 2.2.2.4 Display Tokens */
|
||||
/* 2.5.198.80 */
|
||||
case 'PtgParen': stack.push('(' + stack.pop() + ')'); break;
|
||||
|
||||
/* 2.5.198.86 */
|
||||
case 'PtgRefErr': stack.push('#REF!'); break;
|
||||
|
||||
/* */
|
||||
/* 2.5.198.58 TODO */
|
||||
case 'PtgExp':
|
||||
c = {c:f[1][1],r:f[1][0]};
|
||||
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));
|
||||
}
|
||||
else {
|
||||
var fnd = false;
|
||||
for(e1=0;e1!=supbooks.arrayf.length; ++e1) {
|
||||
/* TODO: should be something like range_has */
|
||||
e2 = supbooks.arrayf[e1];
|
||||
if(c.c < e2[0].s.c || c.c > e2[0].e.c) continue;
|
||||
if(c.r < e2[0].s.r || c.r > e2[0].e.r) continue;
|
||||
stack.push(stringify_formula(e2[1], _range, q, supbooks, opts));
|
||||
}
|
||||
if(!fnd) stack.push(f[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
/* 2.5.198.32 TODO */
|
||||
case 'PtgArray':
|
||||
stack.push("{" + f[1].map(mapper).join(";") + "}");
|
||||
break;
|
||||
|
||||
/* 2.2.2.5 Mem Tokens */
|
||||
/* 2.5.198.70 TODO: confirm this is a non-display */
|
||||
case 'PtgMemArea':
|
||||
//stack.push("(" + f[2].map(encode_range).join(",") + ")");
|
||||
break;
|
||||
|
||||
/* 2.5.198.38 TODO */
|
||||
case 'PtgAttrSpace': break;
|
||||
|
||||
/* 2.5.198.92 TODO */
|
||||
case 'PtgTbl': break;
|
||||
|
||||
/* 2.5.198.71 */
|
||||
case 'PtgMemErr': break;
|
||||
|
||||
/* 2.5.198.74 */
|
||||
case 'PtgMissArg':
|
||||
stack.push("");
|
||||
break;
|
||||
|
||||
/* 2.5.198.29 TODO */
|
||||
case 'PtgAreaErr': break;
|
||||
|
||||
/* 2.5.198.31 TODO */
|
||||
case 'PtgAreaN': stack.push(""); break;
|
||||
|
||||
/* 2.5.198.87 TODO */
|
||||
case 'PtgRefErr3d': break;
|
||||
|
||||
/* 2.5.198.72 TODO */
|
||||
case 'PtgMemFunc': break;
|
||||
|
||||
default: throw 'Unrecognized Formula Token: ' + f;
|
||||
}
|
||||
//console.log("::",f, stack)
|
||||
}
|
||||
//console.log("--",stack);
|
||||
return stack[0];
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* [MS-XLSB] 2.5.97.4 CellParsedFormula TODO: use similar logic to js-xls */
|
||||
function parse_CellParsedFormula(data, length) {
|
||||
function parse_XLSBCellParsedFormula(data, length) {
|
||||
var cce = data.read_shift(4);
|
||||
return parsenoop(data, length-4);
|
||||
}
|
||||
|
1090
bits/64_ftab.js
Normal file
1090
bits/64_ftab.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -16,70 +16,70 @@ function parse_BrtWsProp(data, length) {
|
||||
var z = {};
|
||||
/* TODO: pull flags */
|
||||
data.l += 19;
|
||||
z.name = parse_CodeName(data, length - 19);
|
||||
z.name = parse_XLSBCodeName(data, length - 19);
|
||||
return z;
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.303 BrtCellBlank */
|
||||
function parse_BrtCellBlank(data, length) {
|
||||
var cell = parse_Cell(data);
|
||||
var cell = parse_XLSBCell(data);
|
||||
return [cell];
|
||||
}
|
||||
function write_BrtCellBlank(cell, val, o) {
|
||||
if(o == null) o = new_buf(8);
|
||||
return write_Cell(val, o);
|
||||
return write_XLSBCell(val, o);
|
||||
}
|
||||
|
||||
|
||||
/* [MS-XLSB] 2.4.304 BrtCellBool */
|
||||
function parse_BrtCellBool(data, length) {
|
||||
var cell = parse_Cell(data);
|
||||
var cell = parse_XLSBCell(data);
|
||||
var fBool = data.read_shift(1);
|
||||
return [cell, fBool, 'b'];
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.305 BrtCellError */
|
||||
function parse_BrtCellError(data, length) {
|
||||
var cell = parse_Cell(data);
|
||||
var cell = parse_XLSBCell(data);
|
||||
var fBool = data.read_shift(1);
|
||||
return [cell, fBool, 'e'];
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.308 BrtCellIsst */
|
||||
function parse_BrtCellIsst(data, length) {
|
||||
var cell = parse_Cell(data);
|
||||
var cell = parse_XLSBCell(data);
|
||||
var isst = data.read_shift(4);
|
||||
return [cell, isst, 's'];
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.310 BrtCellReal */
|
||||
function parse_BrtCellReal(data, length) {
|
||||
var cell = parse_Cell(data);
|
||||
var cell = parse_XLSBCell(data);
|
||||
var value = parse_Xnum(data);
|
||||
return [cell, value, 'n'];
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.311 BrtCellRk */
|
||||
function parse_BrtCellRk(data, length) {
|
||||
var cell = parse_Cell(data);
|
||||
var cell = parse_XLSBCell(data);
|
||||
var value = parse_RkNumber(data);
|
||||
return [cell, value, 'n'];
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.314 BrtCellSt */
|
||||
function parse_BrtCellSt(data, length) {
|
||||
var cell = parse_Cell(data);
|
||||
var cell = parse_XLSBCell(data);
|
||||
var value = parse_XLWideString(data);
|
||||
return [cell, value, 'str'];
|
||||
}
|
||||
|
||||
/* [MS-XLSB] 2.4.647 BrtFmlaBool */
|
||||
function parse_BrtFmlaBool(data, length, opts) {
|
||||
var cell = parse_Cell(data);
|
||||
var cell = parse_XLSBCell(data);
|
||||
var value = data.read_shift(1);
|
||||
var o = [cell, value, 'b'];
|
||||
if(opts.cellFormula) {
|
||||
var formula = parse_CellParsedFormula(data, length-9);
|
||||
var formula = parse_XLSBCellParsedFormula(data, length-9);
|
||||
o[3] = ""; /* TODO */
|
||||
}
|
||||
else data.l += length-9;
|
||||
@ -88,11 +88,11 @@ function parse_BrtFmlaBool(data, length, opts) {
|
||||
|
||||
/* [MS-XLSB] 2.4.648 BrtFmlaError */
|
||||
function parse_BrtFmlaError(data, length, opts) {
|
||||
var cell = parse_Cell(data);
|
||||
var cell = parse_XLSBCell(data);
|
||||
var value = data.read_shift(1);
|
||||
var o = [cell, value, 'e'];
|
||||
if(opts.cellFormula) {
|
||||
var formula = parse_CellParsedFormula(data, length-9);
|
||||
var formula = parse_XLSBCellParsedFormula(data, length-9);
|
||||
o[3] = ""; /* TODO */
|
||||
}
|
||||
else data.l += length-9;
|
||||
@ -101,11 +101,11 @@ function parse_BrtFmlaError(data, length, opts) {
|
||||
|
||||
/* [MS-XLSB] 2.4.649 BrtFmlaNum */
|
||||
function parse_BrtFmlaNum(data, length, opts) {
|
||||
var cell = parse_Cell(data);
|
||||
var cell = parse_XLSBCell(data);
|
||||
var value = parse_Xnum(data);
|
||||
var o = [cell, value, 'n'];
|
||||
if(opts.cellFormula) {
|
||||
var formula = parse_CellParsedFormula(data, length - 16);
|
||||
var formula = parse_XLSBCellParsedFormula(data, length - 16);
|
||||
o[3] = ""; /* TODO */
|
||||
}
|
||||
else data.l += length-16;
|
||||
@ -115,11 +115,11 @@ function parse_BrtFmlaNum(data, length, opts) {
|
||||
/* [MS-XLSB] 2.4.650 BrtFmlaString */
|
||||
function parse_BrtFmlaString(data, length, opts) {
|
||||
var start = data.l;
|
||||
var cell = parse_Cell(data);
|
||||
var cell = parse_XLSBCell(data);
|
||||
var value = parse_XLWideString(data);
|
||||
var o = [cell, value, 'str'];
|
||||
if(opts.cellFormula) {
|
||||
var formula = parse_CellParsedFormula(data, start + length - data.l);
|
||||
var formula = parse_XLSBCellParsedFormula(data, start + length - data.l);
|
||||
}
|
||||
else data.l = start + length;
|
||||
return o;
|
||||
|
699
bits/80_xlml.js
Normal file
699
bits/80_xlml.js
Normal file
@ -0,0 +1,699 @@
|
||||
var attregexg2=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
|
||||
var attregex2=/([\w:]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;
|
||||
var _chr = function(c) { return String.fromCharCode(c); };
|
||||
function xlml_parsexmltag(tag, skip_root) {
|
||||
var words = tag.split(/\s+/);
|
||||
var z = []; if(!skip_root) z[0] = words[0];
|
||||
if(words.length === 1) return z;
|
||||
var m = tag.match(attregexg2), y, j, w, i;
|
||||
if(m) for(i = 0; i != m.length; ++i) {
|
||||
y = m[i].match(attregex2);
|
||||
if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].substr(1,y[2].length-2);
|
||||
else {
|
||||
if(y[1].substr(0,6) === "xmlns:") w = "xmlns"+y[1].substr(6);
|
||||
else w = y[1].substr(j+1);
|
||||
z[w] = y[2].substr(1,y[2].length-2);
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
function xlml_parsexmltagobj(tag) {
|
||||
var words = tag.split(/\s+/);
|
||||
var z = {};
|
||||
if(words.length === 1) return z;
|
||||
var m = tag.match(attregexg2), y, j, w, i;
|
||||
if(m) for(i = 0; i != m.length; ++i) {
|
||||
y = m[i].match(attregex2);
|
||||
if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].substr(1,y[2].length-2);
|
||||
else {
|
||||
if(y[1].substr(0,6) === "xmlns:") w = "xmlns"+y[1].substr(6);
|
||||
else w = y[1].substr(j+1);
|
||||
z[w] = y[2].substr(1,y[2].length-2);
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
function xlml_format(format, value) {
|
||||
var fmt = XLMLFormatMap[format] || unescapexml(format);
|
||||
if(fmt === "General") return SSF._general(value);
|
||||
return SSF.format(fmt, value);
|
||||
}
|
||||
|
||||
function xlml_set_custprop(Custprops, Rn, cp, 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 "i8": case "string": case "fixed": case "uuid": case "bin.base64": break;
|
||||
default: throw "bad custprop:" + cp[0];
|
||||
}
|
||||
Custprops[unescapexml(Rn[3])] = val;
|
||||
}
|
||||
|
||||
function safe_format_xlml(cell, nf, o) {
|
||||
try {
|
||||
if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
|
||||
else if(nf === "General") {
|
||||
if(cell.t === 'n') {
|
||||
if((cell.v|0) === cell.v) cell.w = SSF._general_int(cell.v);
|
||||
else cell.w = SSF._general_num(cell.v);
|
||||
}
|
||||
else cell.w = SSF._general(cell.v);
|
||||
}
|
||||
else cell.w = xlml_format(nf||"General", cell.v);
|
||||
if(o.cellNF) cell.z = XLMLFormatMap[nf]||nf||"General";
|
||||
} catch(e) { if(o.WTF) throw e; }
|
||||
}
|
||||
|
||||
function process_style_xlml(styles, stag, opts) {
|
||||
if(opts.cellStyles) {
|
||||
if(stag.Interior) {
|
||||
var I = stag.Interior;
|
||||
if(I.Pattern) I.patternType = XLMLPatternTypeMap[I.Pattern] || I.Pattern;
|
||||
}
|
||||
}
|
||||
styles[stag.ID] = stag;
|
||||
}
|
||||
|
||||
/* TODO: there must exist some form of OSP-blessed spec */
|
||||
function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, o) {
|
||||
var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
|
||||
var interiors = [];
|
||||
if(sid === undefined && row) sid = row.StyleID;
|
||||
if(sid === undefined && csty) sid = csty.StyleID;
|
||||
while(styles[sid] !== undefined) {
|
||||
if(styles[sid].nf) nf = styles[sid].nf;
|
||||
if(styles[sid].Interior) interiors.push(styles[sid].Interior);
|
||||
if(!styles[sid].Parent) break;
|
||||
sid = styles[sid].Parent;
|
||||
}
|
||||
switch(data.Type) {
|
||||
case 'Boolean':
|
||||
cell.t = 'b';
|
||||
cell.v = parsexmlbool(xml);
|
||||
break;
|
||||
case 'String':
|
||||
cell.t = 's'; cell.r = xlml_fixstr(unescapexml(xml));
|
||||
cell.v = xml.indexOf("<") > -1 ? ss : cell.r;
|
||||
break;
|
||||
case 'DateTime':
|
||||
cell.v = (Date.parse(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
|
||||
if(cell.v !== cell.v) cell.v = unescapexml(xml);
|
||||
else if(cell.v >= 1 && cell.v<60) cell.v = cell.v -1;
|
||||
if(!nf || nf == "General") nf = "yyyy-mm-dd";
|
||||
/* falls through */
|
||||
case 'Number':
|
||||
if(cell.v === undefined) cell.v=+xml;
|
||||
if(!cell.t) cell.t = 'n';
|
||||
break;
|
||||
case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; cell.w = xml; break;
|
||||
default: cell.t = 's'; cell.v = xlml_fixstr(ss); break;
|
||||
}
|
||||
safe_format_xlml(cell, nf, o);
|
||||
if(o.cellFormula != null && cell.Formula) {
|
||||
cell.f = rc_to_a1(unescapexml(cell.Formula), base);
|
||||
cell.Formula = undefined;
|
||||
}
|
||||
if(o.cellStyles) {
|
||||
interiors.forEach(function(x) {
|
||||
if(!S.patternType && x.patternType) S.patternType = x.patternType;
|
||||
});
|
||||
cell.s = S;
|
||||
}
|
||||
cell.ixfe = cell.StyleID !== undefined ? cell.StyleID : 'Default';
|
||||
}
|
||||
|
||||
function xlml_clean_comment(comment) {
|
||||
comment.t = comment.v;
|
||||
comment.v = comment.w = comment.ixfe = undefined;
|
||||
}
|
||||
|
||||
function xlml_normalize(d) {
|
||||
if(has_buf && Buffer.isBuffer(d)) return d.toString('utf8');
|
||||
if(typeof d === 'string') return d;
|
||||
throw "badf";
|
||||
}
|
||||
|
||||
/* TODO: Everything */
|
||||
var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
|
||||
function parse_xlml_xml(d, opts) {
|
||||
var str = xlml_normalize(d);
|
||||
var Rn;
|
||||
var state = [], tmp;
|
||||
var sheets = {}, sheetnames = [], cursheet = {}, sheetname = "";
|
||||
var table = {}, cell = {}, row = {}, dtag, didx;
|
||||
var c = 0, r = 0;
|
||||
var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} };
|
||||
var styles = {}, stag = {};
|
||||
var ss = "", fidx = 0;
|
||||
var mergecells = [];
|
||||
var Props = {}, Custprops = {}, pidx = 0, cp = {};
|
||||
var comments = [], comment = {};
|
||||
var cstys = [], csty;
|
||||
xlmlregex.lastIndex = 0;
|
||||
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
|
||||
case 'Data':
|
||||
if(state[state.length-1][1]) break;
|
||||
if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]=="Comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, opts);
|
||||
else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; }
|
||||
break;
|
||||
case 'Cell':
|
||||
if(Rn[1]==='/'){
|
||||
if(comments.length > 0) cell.c = comments;
|
||||
if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== undefined) cursheet[encode_col(c) + encode_row(r)] = cell;
|
||||
if(cell.HRef) {
|
||||
cell.l = {Target:cell.HRef, tooltip:cell.HRefScreenTip};
|
||||
cell.HRef = cell.HRefScreenTip = undefined;
|
||||
}
|
||||
if(cell.MergeAcross || cell.MergeDown) {
|
||||
var cc = c + (parseInt(cell.MergeAcross,10)|0);
|
||||
var rr = r + (parseInt(cell.MergeDown,10)|0);
|
||||
mergecells.push({s:{c:c,r:r},e:{c:cc,r:rr}});
|
||||
}
|
||||
++c;
|
||||
if(cell.MergeAcross) c += +cell.MergeAcross;
|
||||
} else {
|
||||
cell = xlml_parsexmltagobj(Rn[0]);
|
||||
if(cell.Index) c = +cell.Index - 1;
|
||||
if(c < refguess.s.c) refguess.s.c = c;
|
||||
if(c > refguess.e.c) refguess.e.c = c;
|
||||
if(Rn[0].substr(-2) === "/>") ++c;
|
||||
comments = [];
|
||||
}
|
||||
break;
|
||||
case 'Row':
|
||||
if(Rn[1]==='/' || Rn[0].substr(-2) === "/>") {
|
||||
if(r < refguess.s.r) refguess.s.r = r;
|
||||
if(r > refguess.e.r) refguess.e.r = r;
|
||||
if(Rn[0].substr(-2) === "/>") {
|
||||
row = xlml_parsexmltag(Rn[0]);
|
||||
if(row.Index) r = +row.Index - 1;
|
||||
}
|
||||
c = 0; ++r;
|
||||
} else {
|
||||
row = xlml_parsexmltag(Rn[0]);
|
||||
if(row.Index) r = +row.Index - 1;
|
||||
}
|
||||
break;
|
||||
case 'Worksheet': /* TODO: read range from FullRows/FullColumns */
|
||||
if(Rn[1]==='/'){
|
||||
if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
|
||||
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;
|
||||
sheets[sheetname] = cursheet;
|
||||
} else {
|
||||
refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} };
|
||||
r = c = 0;
|
||||
state.push([Rn[3], false]);
|
||||
tmp = xlml_parsexmltag(Rn[0]);
|
||||
sheetname = tmp.Name;
|
||||
cursheet = {};
|
||||
mergecells = [];
|
||||
}
|
||||
break;
|
||||
case 'Table':
|
||||
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
|
||||
else if(Rn[0].slice(-2) == "/>") break;
|
||||
else {
|
||||
table = xlml_parsexmltag(Rn[0]);
|
||||
state.push([Rn[3], false]);
|
||||
cstys = [];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Style':
|
||||
if(Rn[1]==='/') process_style_xlml(styles, stag, opts);
|
||||
else stag = xlml_parsexmltag(Rn[0]);
|
||||
break;
|
||||
|
||||
case 'NumberFormat':
|
||||
stag.nf = xlml_parsexmltag(Rn[0]).Format || "General";
|
||||
break;
|
||||
|
||||
case 'Column':
|
||||
if(state[state.length-1][0] !== 'Table') break;
|
||||
csty = xlml_parsexmltag(Rn[0]);
|
||||
cstys[(csty.Index-1||cstys.length)] = csty;
|
||||
for(var i = 0; i < +csty.Span; ++i) cstys[cstys.length] = csty;
|
||||
break;
|
||||
|
||||
case 'NamedRange': break;
|
||||
case 'NamedCell': break;
|
||||
case 'B': break;
|
||||
case 'I': break;
|
||||
case 'U': break;
|
||||
case 'S': break;
|
||||
case 'Sub': break;
|
||||
case 'Sup': break;
|
||||
case 'Span': break;
|
||||
case 'Border': break;
|
||||
case 'Alignment': break;
|
||||
case 'Borders': break;
|
||||
case 'Font':
|
||||
if(Rn[0].substr(-2) === "/>") break;
|
||||
else if(Rn[1]==="/") ss += str.slice(fidx, Rn.index);
|
||||
else fidx = Rn.index + Rn[0].length;
|
||||
break;
|
||||
case 'Interior':
|
||||
if(!opts.cellStyles) break;
|
||||
stag.Interior = xlml_parsexmltag(Rn[0]);
|
||||
break;
|
||||
case 'Protection': break;
|
||||
|
||||
case 'Author':
|
||||
case 'Title':
|
||||
case 'Description':
|
||||
case 'Created':
|
||||
case 'Keywords':
|
||||
case 'Subject':
|
||||
case 'Category':
|
||||
case 'Company':
|
||||
case 'LastAuthor':
|
||||
case 'LastSaved':
|
||||
case 'LastPrinted':
|
||||
case 'Version':
|
||||
case 'Revision':
|
||||
case 'TotalTime':
|
||||
case 'HyperlinkBase':
|
||||
case 'Manager':
|
||||
if(Rn[0].substr(-2) === "/>") break;
|
||||
else if(Rn[1]==="/") xlml_set_prop(Props, Rn[3], str.slice(pidx, Rn.index));
|
||||
else pidx = Rn.index + Rn[0].length;
|
||||
break;
|
||||
case 'Paragraphs': break;
|
||||
|
||||
case 'Styles':
|
||||
case 'Workbook':
|
||||
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
|
||||
else state.push([Rn[3], false]);
|
||||
break;
|
||||
|
||||
case 'Comment':
|
||||
if(Rn[1]==='/'){
|
||||
if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
|
||||
xlml_clean_comment(comment);
|
||||
comments.push(comment);
|
||||
} else {
|
||||
state.push([Rn[3], false]);
|
||||
tmp = xlml_parsexmltag(Rn[0]);
|
||||
comment = {a:tmp.Author};
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Name': break;
|
||||
|
||||
case 'ComponentOptions':
|
||||
case 'DocumentProperties':
|
||||
case 'CustomDocumentProperties':
|
||||
case 'OfficeDocumentSettings':
|
||||
case 'PivotTable':
|
||||
case 'PivotCache':
|
||||
case 'Names':
|
||||
case 'MapInfo':
|
||||
case 'PageBreaks':
|
||||
case 'QueryTable':
|
||||
case 'DataValidation':
|
||||
case 'AutoFilter':
|
||||
case 'Sorting':
|
||||
case 'Schema':
|
||||
case 'data':
|
||||
case 'ConditionalFormatting':
|
||||
case 'SmartTagType':
|
||||
case 'SmartTags':
|
||||
case 'ExcelWorkbook':
|
||||
case 'WorkbookOptions':
|
||||
case 'WorksheetOptions':
|
||||
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
|
||||
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
|
||||
break;
|
||||
|
||||
default:
|
||||
var seen = true;
|
||||
switch(state[state.length-1][0]) {
|
||||
/* OfficeDocumentSettings */
|
||||
case 'OfficeDocumentSettings': switch(Rn[3]) {
|
||||
case 'AllowPNG': break;
|
||||
case 'RemovePersonalInformation': break;
|
||||
case 'DownloadComponents': break;
|
||||
case 'LocationOfComponents': break;
|
||||
case 'Colors': break;
|
||||
case 'Color': break;
|
||||
case 'Index': break;
|
||||
case 'RGB': break;
|
||||
case 'PixelsPerInch': break;
|
||||
case 'TargetScreenSize': break;
|
||||
case 'ReadOnlyRecommended': break;
|
||||
default: seen = false;
|
||||
} break;
|
||||
|
||||
/* ComponentOptions */
|
||||
case 'ComponentOptions': switch(Rn[3]) {
|
||||
case 'Toolbar': break;
|
||||
case 'HideOfficeLogo': break;
|
||||
case 'SpreadsheetAutoFit': break;
|
||||
case 'Label': break;
|
||||
case 'Caption': break;
|
||||
case 'MaxHeight': break;
|
||||
case 'MaxWidth': break;
|
||||
case 'NextSheetNumber': break;
|
||||
default: seen = false;
|
||||
} break;
|
||||
|
||||
/* ExcelWorkbook */
|
||||
case 'ExcelWorkbook': switch(Rn[3]) {
|
||||
case 'WindowHeight': break;
|
||||
case 'WindowWidth': break;
|
||||
case 'WindowTopX': break;
|
||||
case 'WindowTopY': break;
|
||||
case 'TabRatio': break;
|
||||
case 'ProtectStructure': break;
|
||||
case 'ProtectWindows': break;
|
||||
case 'ActiveSheet': break;
|
||||
case 'DisplayInkNotes': break;
|
||||
case 'FirstVisibleSheet': break;
|
||||
case 'SupBook': break;
|
||||
case 'SheetName': break;
|
||||
case 'SheetIndex': break;
|
||||
case 'SheetIndexFirst': break;
|
||||
case 'SheetIndexLast': break;
|
||||
case 'Dll': break;
|
||||
case 'AcceptLabelsInFormulas': break;
|
||||
case 'DoNotSaveLinkValues': break;
|
||||
case 'Date1904': break;
|
||||
case 'Iteration': break;
|
||||
case 'MaxIterations': break;
|
||||
case 'MaxChange': break;
|
||||
case 'Path': break;
|
||||
case 'Xct': break;
|
||||
case 'Count': break;
|
||||
case 'SelectedSheets': break;
|
||||
case 'Calculation': break;
|
||||
case 'Uncalced': break;
|
||||
case 'StartupPrompt': break;
|
||||
case 'Crn': break;
|
||||
case 'ExternName': break;
|
||||
case 'Formula': break;
|
||||
case 'ColFirst': break;
|
||||
case 'ColLast': break;
|
||||
case 'WantAdvise': break;
|
||||
case 'Boolean': break;
|
||||
case 'Error': break;
|
||||
case 'Text': break;
|
||||
case 'OLE': break;
|
||||
case 'NoAutoRecover': break;
|
||||
case 'PublishObjects': break;
|
||||
case 'DoNotCalculateBeforeSave': break;
|
||||
case 'Number': break;
|
||||
case 'RefModeR1C1': break;
|
||||
case 'EmbedSaveSmartTags': break;
|
||||
default: seen = false;
|
||||
} break;
|
||||
|
||||
/* WorkbookOptions */
|
||||
case 'WorkbookOptions': switch(Rn[3]) {
|
||||
case 'OWCVersion': break;
|
||||
case 'Height': break;
|
||||
case 'Width': break;
|
||||
default: seen = false;
|
||||
} break;
|
||||
|
||||
/* WorksheetOptions */
|
||||
case 'WorksheetOptions': switch(Rn[3]) {
|
||||
case 'Unsynced': break;
|
||||
case 'Visible': break;
|
||||
case 'Print': break;
|
||||
case 'Panes': break;
|
||||
case 'Scale': break;
|
||||
case 'Pane': break;
|
||||
case 'Number': break;
|
||||
case 'Layout': break;
|
||||
case 'Header': break;
|
||||
case 'Footer': break;
|
||||
case 'PageSetup': break;
|
||||
case 'PageMargins': break;
|
||||
case 'Selected': break;
|
||||
case 'ProtectObjects': break;
|
||||
case 'EnableSelection': break;
|
||||
case 'ProtectScenarios': break;
|
||||
case 'ValidPrinterInfo': break;
|
||||
case 'HorizontalResolution': break;
|
||||
case 'VerticalResolution': break;
|
||||
case 'NumberofCopies': break;
|
||||
case 'ActiveRow': break;
|
||||
case 'ActiveCol': break;
|
||||
case 'ActivePane': break;
|
||||
case 'TopRowVisible': break;
|
||||
case 'TopRowBottomPane': break;
|
||||
case 'LeftColumnVisible': break;
|
||||
case 'LeftColumnRightPane': break;
|
||||
case 'FitToPage': break;
|
||||
case 'RangeSelection': break;
|
||||
case 'PaperSizeIndex': break;
|
||||
case 'PageLayoutZoom': break;
|
||||
case 'PageBreakZoom': break;
|
||||
case 'FilterOn': break;
|
||||
case 'DoNotDisplayGridlines': break;
|
||||
case 'SplitHorizontal': break;
|
||||
case 'SplitVertical': break;
|
||||
case 'FreezePanes': break;
|
||||
case 'FrozenNoSplit': break;
|
||||
case 'FitWidth': break;
|
||||
case 'FitHeight': break;
|
||||
case 'CommentsLayout': break;
|
||||
case 'Zoom': break;
|
||||
case 'LeftToRight': break;
|
||||
case 'Gridlines': break;
|
||||
case 'AllowSort': break;
|
||||
case 'AllowFilter': break;
|
||||
case 'AllowInsertRows': break;
|
||||
case 'AllowDeleteRows': break;
|
||||
case 'AllowInsertCols': break;
|
||||
case 'AllowDeleteCols': break;
|
||||
case 'AllowInsertHyperlinks': break;
|
||||
case 'AllowFormatCells': break;
|
||||
case 'AllowSizeCols': break;
|
||||
case 'AllowSizeRows': break;
|
||||
case 'NoSummaryRowsBelowDetail': break;
|
||||
case 'TabColorIndex': break;
|
||||
case 'DoNotDisplayHeadings': break;
|
||||
case 'ShowPageLayoutZoom': break;
|
||||
case 'NoSummaryColumnsRightDetail': break;
|
||||
case 'BlackAndWhite': break;
|
||||
case 'DoNotDisplayZeros': break;
|
||||
case 'DisplayPageBreak': break;
|
||||
case 'RowColHeadings': break;
|
||||
case 'DoNotDisplayOutline': break;
|
||||
case 'NoOrientation': break;
|
||||
case 'AllowUsePivotTables': break;
|
||||
case 'ZeroHeight': break;
|
||||
case 'ViewableRange': break;
|
||||
case 'Selection': break;
|
||||
case 'ProtectContents': break;
|
||||
default: seen = false;
|
||||
} break;
|
||||
|
||||
/* PivotTable */
|
||||
case 'PivotTable': case 'PivotCache': switch(Rn[3]) {
|
||||
case 'ImmediateItemsOnDrop': break;
|
||||
case 'ShowPageMultipleItemLabel': break;
|
||||
case 'CompactRowIndent': break;
|
||||
case 'Location': break;
|
||||
case 'PivotField': break;
|
||||
case 'Orientation': break;
|
||||
case 'LayoutForm': break;
|
||||
case 'LayoutSubtotalLocation': break;
|
||||
case 'LayoutCompactRow': break;
|
||||
case 'Position': break;
|
||||
case 'PivotItem': break;
|
||||
case 'DataType': break;
|
||||
case 'DataField': break;
|
||||
case 'SourceName': break;
|
||||
case 'ParentField': break;
|
||||
case 'PTLineItems': break;
|
||||
case 'PTLineItem': break;
|
||||
case 'CountOfSameItems': break;
|
||||
case 'Item': break;
|
||||
case 'ItemType': break;
|
||||
case 'PTSource': break;
|
||||
case 'CacheIndex': break;
|
||||
case 'ConsolidationReference': break;
|
||||
case 'FileName': break;
|
||||
case 'Reference': break;
|
||||
case 'NoColumnGrand': break;
|
||||
case 'NoRowGrand': break;
|
||||
case 'BlankLineAfterItems': break;
|
||||
case 'Hidden': break;
|
||||
case 'Subtotal': break;
|
||||
case 'BaseField': break;
|
||||
case 'MapChildItems': break;
|
||||
case 'Function': break;
|
||||
case 'RefreshOnFileOpen': break;
|
||||
case 'PrintSetTitles': break;
|
||||
case 'MergeLabels': break;
|
||||
case 'DefaultVersion': break;
|
||||
case 'RefreshName': break;
|
||||
case 'RefreshDate': break;
|
||||
case 'RefreshDateCopy': break;
|
||||
case 'VersionLastRefresh': break;
|
||||
case 'VersionLastUpdate': break;
|
||||
case 'VersionUpdateableMin': break;
|
||||
case 'VersionRefreshableMin': break;
|
||||
case 'Calculation': break;
|
||||
default: seen = false;
|
||||
} break;
|
||||
|
||||
/* PageBreaks */
|
||||
case 'PageBreaks': switch(Rn[3]) {
|
||||
case 'ColBreaks': break;
|
||||
case 'ColBreak': break;
|
||||
case 'RowBreaks': break;
|
||||
case 'RowBreak': break;
|
||||
case 'ColStart': break;
|
||||
case 'ColEnd': break;
|
||||
case 'RowEnd': break;
|
||||
default: seen = false;
|
||||
} break;
|
||||
|
||||
/* AutoFilter */
|
||||
case 'AutoFilter': switch(Rn[3]) {
|
||||
case 'AutoFilterColumn': break;
|
||||
case 'AutoFilterCondition': break;
|
||||
case 'AutoFilterAnd': break;
|
||||
case 'AutoFilterOr': break;
|
||||
default: seen = false;
|
||||
} break;
|
||||
|
||||
/* QueryTable */
|
||||
case 'QueryTable': switch(Rn[3]) {
|
||||
case 'Id': break;
|
||||
case 'AutoFormatFont': break;
|
||||
case 'AutoFormatPattern': break;
|
||||
case 'QuerySource': break;
|
||||
case 'QueryType': break;
|
||||
case 'EnableRedirections': break;
|
||||
case 'RefreshedInXl9': break;
|
||||
case 'URLString': break;
|
||||
case 'HTMLTables': break;
|
||||
case 'Connection': break;
|
||||
case 'CommandText': break;
|
||||
case 'RefreshInfo': break;
|
||||
case 'NoTitles': break;
|
||||
case 'NextId': break;
|
||||
case 'ColumnInfo': break;
|
||||
case 'OverwriteCells': break;
|
||||
case 'DoNotPromptForFile': break;
|
||||
case 'TextWizardSettings': break;
|
||||
case 'Source': break;
|
||||
case 'Number': break;
|
||||
case 'Decimal': break;
|
||||
case 'ThousandSeparator': break;
|
||||
case 'TrailingMinusNumbers': break;
|
||||
case 'FormatSettings': break;
|
||||
case 'FieldType': break;
|
||||
case 'Delimiters': break;
|
||||
case 'Tab': break;
|
||||
case 'Comma': break;
|
||||
case 'AutoFormatName': break;
|
||||
case 'VersionLastEdit': break;
|
||||
case 'VersionLastRefresh': break;
|
||||
default: seen = false;
|
||||
} break;
|
||||
|
||||
/* Sorting */
|
||||
case 'Sorting':
|
||||
/* ConditionalFormatting */
|
||||
case 'ConditionalFormatting':
|
||||
/* DataValidation */
|
||||
case 'DataValidation': switch(Rn[3]) {
|
||||
case 'Range': break;
|
||||
case 'Type': break;
|
||||
case 'Min': break;
|
||||
case 'Max': break;
|
||||
case 'Sort': break;
|
||||
case 'Descending': break;
|
||||
case 'Order': break;
|
||||
case 'CaseSensitive': break;
|
||||
case 'Value': break;
|
||||
case 'ErrorStyle': break;
|
||||
case 'ErrorMessage': break;
|
||||
case 'ErrorTitle': break;
|
||||
case 'CellRangeList': break;
|
||||
case 'InputMessage': break;
|
||||
case 'InputTitle': break;
|
||||
case 'ComboHide': break;
|
||||
case 'InputHide': break;
|
||||
case 'Condition': break;
|
||||
case 'Qualifier': break;
|
||||
case 'UseBlank': break;
|
||||
case 'Value1': break;
|
||||
case 'Value2': break;
|
||||
case 'Format': break;
|
||||
default: seen = false;
|
||||
} break;
|
||||
|
||||
/* MapInfo (schema) */
|
||||
case 'MapInfo': case 'Schema': case 'data': switch(Rn[3]) {
|
||||
case 'Map': break;
|
||||
case 'Entry': break;
|
||||
case 'Range': break;
|
||||
case 'XPath': break;
|
||||
case 'Field': break;
|
||||
case 'XSDType': break;
|
||||
case 'FilterOn': break;
|
||||
case 'Aggregate': break;
|
||||
case 'ElementType': break;
|
||||
case 'AttributeType': break;
|
||||
/* These are from xsd (XML Schema Definition) */
|
||||
case 'schema':
|
||||
case 'element':
|
||||
case 'complexType':
|
||||
case 'datatype':
|
||||
case 'all':
|
||||
case 'attribute':
|
||||
case 'extends': break;
|
||||
|
||||
case 'row': break;
|
||||
default: seen = false;
|
||||
} break;
|
||||
|
||||
/* SmartTags (can be anything) */
|
||||
case 'SmartTags': break;
|
||||
|
||||
default: seen = false; break;
|
||||
}
|
||||
if(seen) break;
|
||||
/* CustomDocumentProperties */
|
||||
if(!state[state.length-1][1]) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
|
||||
if(state[state.length-1][0]==='CustomDocumentProperties') {
|
||||
if(Rn[0].substr(-2) === "/>") break;
|
||||
else if(Rn[1]==="/") xlml_set_custprop(Custprops, Rn, cp, str.slice(pidx, Rn.index));
|
||||
else { cp = Rn; pidx = Rn.index + Rn[0].length; }
|
||||
break;
|
||||
}
|
||||
if(opts.WTF) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
|
||||
}
|
||||
var out = {};
|
||||
if(!opts.bookSheets && !opts.bookProps) out.Sheets = sheets;
|
||||
out.SheetNames = sheetnames;
|
||||
out.SSF = SSF.get_table();
|
||||
out.Props = Props;
|
||||
out.Custprops = Custprops;
|
||||
return out;
|
||||
}
|
||||
|
||||
function parse_xlml(data, opts) {
|
||||
fix_read_opts(opts=opts||{});
|
||||
switch(opts.type||"base64") {
|
||||
case "base64": return parse_xlml_xml(Base64.decode(data), opts);
|
||||
case "binary": case "buffer": case "file": return parse_xlml_xml(data, opts);
|
||||
case "array": return parse_xlml_xml(data.map(_chr).join(""), opts);
|
||||
}
|
||||
}
|
||||
|
||||
function write_xlml(wb, opts) { }
|
||||
|
675
bits/81_xls.js
Normal file
675
bits/81_xls.js
Normal file
@ -0,0 +1,675 @@
|
||||
/* [MS-OLEDS] 2.3.8 CompObjStream */
|
||||
function parse_compobj(obj) {
|
||||
var v = {};
|
||||
var o = obj.content;
|
||||
|
||||
/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
|
||||
var l = 28, m;
|
||||
m = __lpstr(o, l);
|
||||
l += 4 + __readUInt32LE(o,l);
|
||||
v.UserType = m;
|
||||
|
||||
/* [MS-OLEDS] 2.3.1 ClipboardFormatOrAnsiString */
|
||||
m = __readUInt32LE(o,l); l+= 4;
|
||||
switch(m) {
|
||||
case 0x00000000: break;
|
||||
case 0xffffffff: case 0xfffffffe: l+=4; break;
|
||||
default:
|
||||
if(m > 0x190) throw new Error("Unsupported Clipboard: " + m.toString(16));
|
||||
l += m;
|
||||
}
|
||||
|
||||
m = __lpstr(o, l); l += m.length === 0 ? 0 : 5 + m.length; v.Reserved1 = m;
|
||||
|
||||
if((m = __readUInt32LE(o,l)) !== 0x71b2e9f4) return v;
|
||||
throw "Unsupported Unicode Extension";
|
||||
}
|
||||
|
||||
/* 2.4.58 Continue logic */
|
||||
function slurp(R, blob, length, opts) {
|
||||
var l = length;
|
||||
var bufs = [];
|
||||
var d = blob.slice(blob.l,blob.l+l);
|
||||
if(opts && opts.enc && opts.enc.insitu_decrypt) switch(R.n) {
|
||||
case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': break;
|
||||
default:
|
||||
if(d.length === 0) break;
|
||||
opts.enc.insitu_decrypt(d);
|
||||
}
|
||||
bufs.push(d);
|
||||
blob.l += l;
|
||||
var next = (XLSRecordEnum[__readUInt16LE(blob,blob.l)]);
|
||||
while(next != null && next.n === 'Continue') {
|
||||
l = __readUInt16LE(blob,blob.l+2);
|
||||
bufs.push(blob.slice(blob.l+4,blob.l+4+l));
|
||||
blob.l += 4+l;
|
||||
next = (XLSRecordEnum[__readUInt16LE(blob, blob.l)]);
|
||||
}
|
||||
var b = bconcat(bufs);
|
||||
prep_blob(b, 0);
|
||||
var ll = 0; b.lens = [];
|
||||
for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; }
|
||||
return R.f(b, b.length, opts);
|
||||
}
|
||||
|
||||
function safe_format_xf(p, opts, date1904) {
|
||||
if(!p.XF) return;
|
||||
try {
|
||||
var fmtid = p.XF.ifmt||0;
|
||||
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
|
||||
else if(fmtid === 0) {
|
||||
if(p.t === 'n') {
|
||||
if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
|
||||
else p.w = SSF._general_num(p.v);
|
||||
}
|
||||
else p.w = SSF._general(p.v);
|
||||
}
|
||||
else p.w = SSF.format(fmtid,p.v, {date1904:date1904||false});
|
||||
if(opts.cellNF) p.z = SSF._table[fmtid];
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
}
|
||||
|
||||
function make_cell(val, ixfe, t) {
|
||||
return {v:val, ixfe:ixfe, t:t};
|
||||
}
|
||||
|
||||
// 2.3.2
|
||||
function parse_workbook(blob, options) {
|
||||
var wb = {opts:{}};
|
||||
var Sheets = {};
|
||||
var out = {};
|
||||
var Directory = {};
|
||||
var found_sheet = false;
|
||||
var range = {};
|
||||
var last_formula = null;
|
||||
var sst = [];
|
||||
var cur_sheet = "";
|
||||
var Preamble = {};
|
||||
var lastcell, last_cell, cc, cmnt, rng, rngC, rngR;
|
||||
var shared_formulae = {};
|
||||
var array_formulae = []; /* TODO: something more clever */
|
||||
var temp_val;
|
||||
var country;
|
||||
var cell_valid = true;
|
||||
var XFs = []; /* XF records */
|
||||
var palette = [];
|
||||
var get_rgb = function getrgb(icv) {
|
||||
if(icv < 8) return XLSIcv[icv];
|
||||
if(icv < 64) return palette[icv-8] || XLSIcv[icv];
|
||||
return XLSIcv[icv];
|
||||
};
|
||||
var process_cell_style = function pcs(cell, line) {
|
||||
var xfd = line.XF.data;
|
||||
if(!xfd || !xfd.patternType) return;
|
||||
line.s = {};
|
||||
line.s.patternType = xfd.patternType;
|
||||
var t;
|
||||
if((t = rgb2Hex(get_rgb(xfd.icvFore)))) { line.s.fgColor = {rgb:t}; }
|
||||
if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; }
|
||||
};
|
||||
var addcell = function addcell(cell, line, options) {
|
||||
if(!cell_valid) return;
|
||||
if(options.cellStyles && line.XF && line.XF.data) process_cell_style(cell, line);
|
||||
lastcell = cell;
|
||||
last_cell = encode_cell(cell);
|
||||
if(range.s) {
|
||||
if(cell.r < range.s.r) range.s.r = cell.r;
|
||||
if(cell.c < range.s.c) range.s.c = cell.c;
|
||||
}
|
||||
if(range.e) {
|
||||
if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1;
|
||||
if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1;
|
||||
}
|
||||
if(options.sheetRows && lastcell.r >= options.sheetRows) cell_valid = false;
|
||||
else out[last_cell] = line;
|
||||
};
|
||||
var opts = {
|
||||
enc: false, // encrypted
|
||||
sbcch: 0, // cch in the preceding SupBook
|
||||
snames: [], // sheetnames
|
||||
sharedf: shared_formulae, // shared formulae by address
|
||||
arrayf: array_formulae, // array formulae array
|
||||
rrtabid: [], // RRTabId
|
||||
lastuser: "", // Last User from WriteAccess
|
||||
biff: 8, // BIFF version
|
||||
codepage: 0, // CP from CodePage record
|
||||
winlocked: 0, // fLockWn from WinProtect
|
||||
wtf: false
|
||||
};
|
||||
if(options.password) opts.password = options.password;
|
||||
var mergecells = [];
|
||||
var objects = [];
|
||||
var supbooks = [[]]; // 1-indexed, will hold extern names
|
||||
var sbc = 0, sbci = 0, sbcli = 0;
|
||||
supbooks.SheetNames = opts.snames;
|
||||
supbooks.sharedf = opts.sharedf;
|
||||
supbooks.arrayf = opts.arrayf;
|
||||
var last_Rn = '';
|
||||
var file_depth = 0; /* TODO: make a real stack */
|
||||
|
||||
/* explicit override for some broken writers */
|
||||
opts.codepage = 1200;
|
||||
set_cp(1200);
|
||||
|
||||
while(blob.l < blob.length - 1) {
|
||||
var s = blob.l;
|
||||
var RecordType = blob.read_shift(2);
|
||||
if(RecordType === 0 && last_Rn === 'EOF') break;
|
||||
var length = (blob.l === blob.length ? 0 : blob.read_shift(2)), y;
|
||||
var R = XLSRecordEnum[RecordType];
|
||||
if(R && R.f) {
|
||||
if(options.bookSheets) {
|
||||
if(last_Rn === 'BoundSheet8' && R.n !== 'BoundSheet8') break;
|
||||
}
|
||||
last_Rn = R.n;
|
||||
if(R.r === 2 || R.r == 12) {
|
||||
var rt = blob.read_shift(2); length -= 2;
|
||||
if(!opts.enc && rt !== RecordType) throw "rt mismatch";
|
||||
if(R.r == 12){ blob.l += 10; length -= 10; } // skip FRT
|
||||
}
|
||||
//console.error(R,blob.l,length,blob.length);
|
||||
var val;
|
||||
if(R.n === 'EOF') val = R.f(blob, length, opts);
|
||||
else val = slurp(R, blob, length, opts);
|
||||
var Rn = R.n;
|
||||
/* BIFF5 overrides */
|
||||
if(opts.biff === 5 || opts.biff === 2) switch(Rn) {
|
||||
case 'Lbl': Rn = 'Label'; break;
|
||||
}
|
||||
/* nested switch statements to workaround V8 128 limit */
|
||||
switch(Rn) {
|
||||
/* Workbook Options */
|
||||
case 'Date1904': wb.opts.Date1904 = val; break;
|
||||
case 'WriteProtect': wb.opts.WriteProtect = true; break;
|
||||
case 'FilePass':
|
||||
if(!opts.enc) blob.l = 0;
|
||||
opts.enc = val;
|
||||
if(opts.WTF) console.error(val);
|
||||
if(!options.password) throw new Error("File is password-protected");
|
||||
if(val.Type !== 0) throw new Error("Encryption scheme unsupported");
|
||||
if(!val.valid) throw new Error("Password is incorrect");
|
||||
break;
|
||||
case 'WriteAccess': opts.lastuser = val; break;
|
||||
case 'FileSharing': break; //TODO
|
||||
case 'CodePage':
|
||||
/* overrides based on test cases */
|
||||
if(val === 0x5212) val = 1200;
|
||||
else if(val === 0x8001) val = 1252;
|
||||
opts.codepage = val;
|
||||
set_cp(val);
|
||||
break;
|
||||
case 'RRTabId': opts.rrtabid = val; break;
|
||||
case 'WinProtect': opts.winlocked = val; break;
|
||||
case 'Template': break; // TODO
|
||||
case 'RefreshAll': wb.opts.RefreshAll = val; break;
|
||||
case 'BookBool': break; // TODO
|
||||
case 'UsesELFs': /* if(val) console.error("Unsupported ELFs"); */ break;
|
||||
case 'MTRSettings': {
|
||||
if(val[0] && val[1]) throw "Unsupported threads: " + val;
|
||||
} break; // TODO: actually support threads
|
||||
case 'CalcCount': wb.opts.CalcCount = val; break;
|
||||
case 'CalcDelta': wb.opts.CalcDelta = val; break;
|
||||
case 'CalcIter': wb.opts.CalcIter = val; break;
|
||||
case 'CalcMode': wb.opts.CalcMode = val; break;
|
||||
case 'CalcPrecision': wb.opts.CalcPrecision = val; break;
|
||||
case 'CalcSaveRecalc': wb.opts.CalcSaveRecalc = val; break;
|
||||
case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
|
||||
case 'Uncalced': break;
|
||||
case 'ForceFullCalculation': wb.opts.FullCalc = val; break;
|
||||
case 'WsBool': break; // TODO
|
||||
case 'XF': XFs.push(val); break;
|
||||
case 'ExtSST': break; // TODO
|
||||
case 'BookExt': break; // TODO
|
||||
case 'RichTextStream': break;
|
||||
case 'BkHim': break;
|
||||
|
||||
case 'SupBook': supbooks[++sbc] = [val]; sbci = 0; break;
|
||||
case 'ExternName': supbooks[sbc][++sbci] = val; break;
|
||||
case 'Index': break; // TODO
|
||||
case 'Lbl': supbooks[0][++sbcli] = val; break;
|
||||
case 'ExternSheet': supbooks[sbc] = supbooks[sbc].concat(val); sbci += val.length; break;
|
||||
|
||||
case 'Protect': out["!protect"] = val; break; /* for sheet or book */
|
||||
case 'Password': if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
|
||||
case 'Prot4Rev': case 'Prot4RevPass': break; /*TODO: Revision Control*/
|
||||
|
||||
case 'BoundSheet8': {
|
||||
Directory[val.pos] = val;
|
||||
opts.snames.push(val.name);
|
||||
} break;
|
||||
case 'EOF': {
|
||||
if(--file_depth) break;
|
||||
if(range.e) {
|
||||
out["!range"] = range;
|
||||
if(range.e.r > 0 && range.e.c > 0) {
|
||||
range.e.r--; range.e.c--;
|
||||
out["!ref"] = encode_range(range);
|
||||
range.e.r++; range.e.c++;
|
||||
}
|
||||
if(mergecells.length > 0) out["!merges"] = mergecells;
|
||||
if(objects.length > 0) out["!objects"] = objects;
|
||||
}
|
||||
if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out;
|
||||
out = {};
|
||||
} break;
|
||||
case 'BOF': {
|
||||
if(opts.biff !== 8);
|
||||
else if(val.BIFFVer === 0x0500) opts.biff = 5;
|
||||
else if(val.BIFFVer === 0x0002) opts.biff = 2;
|
||||
else if(val.BIFFVer === 0x0007) opts.biff = 2;
|
||||
if(file_depth++) break;
|
||||
cell_valid = true;
|
||||
out = {};
|
||||
if(opts.biff === 2) {
|
||||
if(cur_sheet === "") cur_sheet = "Sheet1";
|
||||
range = {s:{r:0,c:0},e:{r:0,c:0}};
|
||||
}
|
||||
else cur_sheet = (Directory[s] || {name:""}).name;
|
||||
mergecells = [];
|
||||
objects = [];
|
||||
} break;
|
||||
case 'Number': case 'BIFF2NUM': {
|
||||
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:'n'};
|
||||
if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
} break;
|
||||
case 'BoolErr': {
|
||||
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t};
|
||||
if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
} break;
|
||||
case 'RK': {
|
||||
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'};
|
||||
if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
} break;
|
||||
case 'MulRk': {
|
||||
for(var j = val.c; j <= val.C; ++j) {
|
||||
var ixfe = val.rkrec[j-val.c][0];
|
||||
temp_val= {ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'};
|
||||
if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:j, r:val.r}, temp_val, options);
|
||||
}
|
||||
} break;
|
||||
case 'Formula': {
|
||||
switch(val.val) {
|
||||
case 'String': last_formula = val; break;
|
||||
case 'Array Formula': throw "Array Formula unsupported";
|
||||
default:
|
||||
temp_val = {v:val.val, ixfe:val.cell.ixfe, t:val.tt};
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) temp_val.f = "="+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(val.cell, temp_val, options);
|
||||
last_formula = val;
|
||||
}
|
||||
} break;
|
||||
case 'String': {
|
||||
if(last_formula) {
|
||||
last_formula.val = val;
|
||||
temp_val = {v:last_formula.val, ixfe:last_formula.cell.ixfe, t:'s'};
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) temp_val.f = "="+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(last_formula.cell, temp_val, options);
|
||||
last_formula = null;
|
||||
}
|
||||
} break;
|
||||
case 'Array': {
|
||||
array_formulae.push(val);
|
||||
} break;
|
||||
case 'ShrFmla': {
|
||||
if(!cell_valid) break;
|
||||
//if(options.cellFormula) out[last_cell].f = stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
/* TODO: capture range */
|
||||
shared_formulae[encode_cell(last_formula.cell)]= val[0];
|
||||
} break;
|
||||
case 'LabelSst':
|
||||
//temp_val={v:sst[val.isst].t, ixfe:val.ixfe, t:'s'};
|
||||
temp_val=make_cell(sst[val.isst].t, val.ixfe, 's');
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
break;
|
||||
case 'Label': case 'BIFF2STR':
|
||||
/* Some writers erroneously write Label */
|
||||
temp_val=make_cell(val.val, val.ixfe, 's');
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(temp_val.XF) safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell({c:val.c, r:val.r}, temp_val, options);
|
||||
break;
|
||||
case 'Dimensions': {
|
||||
if(file_depth === 1) range = val; /* TODO: stack */
|
||||
} break;
|
||||
case 'SST': {
|
||||
sst = val;
|
||||
} break;
|
||||
case 'Format': { /* val = [id, fmt] */
|
||||
SSF.load(val[1], val[0]);
|
||||
} break;
|
||||
|
||||
case 'MergeCells': mergecells = mergecells.concat(val); break;
|
||||
|
||||
case 'Obj': objects[val.cmo[0]] = opts.lastobj = val; break;
|
||||
case 'TxO': opts.lastobj.TxO = val; break;
|
||||
|
||||
case 'HLink': {
|
||||
for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
|
||||
for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC)
|
||||
if(out[encode_cell({c:rngC,r:rngR})])
|
||||
out[encode_cell({c:rngC,r:rngR})].l = val[1];
|
||||
} break;
|
||||
case 'HLinkTooltip': {
|
||||
for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
|
||||
for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC)
|
||||
if(out[encode_cell({c:rngC,r:rngR})])
|
||||
out[encode_cell({c:rngC,r:rngR})].l.tooltip = val[1];
|
||||
} break;
|
||||
|
||||
/* Comments */
|
||||
case 'Note': {
|
||||
if(opts.biff <= 5 && opts.biff >= 2) break; /* TODO: BIFF5 */
|
||||
cc = out[encode_cell(val[0])];
|
||||
var noteobj = objects[val[2]];
|
||||
if(!cc) break;
|
||||
if(!cc.c) cc.c = [];
|
||||
cmnt = {a:val[1],t:noteobj.TxO.t};
|
||||
cc.c.push(cmnt);
|
||||
} break;
|
||||
|
||||
default: switch(R.n) { /* nested */
|
||||
case 'ClrtClient': break;
|
||||
case 'XFExt': update_xfext(XFs[val.ixfe], val.ext); break;
|
||||
|
||||
case 'NameCmt': break;
|
||||
case 'Header': break; // TODO
|
||||
case 'Footer': break; // TODO
|
||||
case 'HCenter': break; // TODO
|
||||
case 'VCenter': break; // TODO
|
||||
case 'Pls': break; // TODO
|
||||
case 'Setup': break; // TODO
|
||||
case 'DefColWidth': break; // TODO
|
||||
case 'GCW': break;
|
||||
case 'LHRecord': break;
|
||||
case 'ColInfo': break; // TODO
|
||||
case 'Row': break; // TODO
|
||||
case 'DBCell': break; // TODO
|
||||
case 'MulBlank': break; // TODO
|
||||
case 'EntExU2': break; // TODO
|
||||
case 'SxView': break; // TODO
|
||||
case 'Sxvd': break; // TODO
|
||||
case 'SXVI': break; // TODO
|
||||
case 'SXVDEx': break; // TODO
|
||||
case 'SxIvd': break; // TODO
|
||||
case 'SXDI': break; // TODO
|
||||
case 'SXLI': break; // TODO
|
||||
case 'SXEx': break; // TODO
|
||||
case 'QsiSXTag': break; // TODO
|
||||
case 'Selection': break;
|
||||
case 'Feat': break;
|
||||
case 'FeatHdr': case 'FeatHdr11': break;
|
||||
case 'Feature11': case 'Feature12': case 'List12': break;
|
||||
case 'Blank': break;
|
||||
case 'Country': country = val; break;
|
||||
case 'RecalcId': break;
|
||||
case 'DefaultRowHeight': case 'DxGCol': break; // TODO: htmlify
|
||||
case 'Fbi': case 'Fbi2': case 'GelFrame': break;
|
||||
case 'Font': break; // TODO
|
||||
case 'XFCRC': break; // TODO
|
||||
case 'Style': break; // TODO
|
||||
case 'StyleExt': break; // TODO
|
||||
case 'Palette': palette = val; break; // TODO
|
||||
case 'Theme': break; // TODO
|
||||
/* Protection */
|
||||
case 'ScenarioProtect': break;
|
||||
case 'ObjProtect': break;
|
||||
|
||||
/* Conditional Formatting */
|
||||
case 'CondFmt12': break;
|
||||
|
||||
/* Table */
|
||||
case 'Table': break; // TODO
|
||||
case 'TableStyles': break; // TODO
|
||||
case 'TableStyle': break; // TODO
|
||||
case 'TableStyleElement': break; // TODO
|
||||
|
||||
/* PivotTable */
|
||||
case 'SXStreamID': break; // TODO
|
||||
case 'SXVS': break; // TODO
|
||||
case 'DConRef': break; // TODO
|
||||
case 'SXAddl': break; // TODO
|
||||
case 'DConBin': break; // TODO
|
||||
case 'DConName': break; // TODO
|
||||
case 'SXPI': break; // TODO
|
||||
case 'SxFormat': break; // TODO
|
||||
case 'SxSelect': break; // TODO
|
||||
case 'SxRule': break; // TODO
|
||||
case 'SxFilt': break; // TODO
|
||||
case 'SxItm': break; // TODO
|
||||
case 'SxDXF': break; // TODO
|
||||
|
||||
/* Scenario Manager */
|
||||
case 'ScenMan': break;
|
||||
|
||||
/* Data Consolidation */
|
||||
case 'DCon': break;
|
||||
|
||||
/* Watched Cell */
|
||||
case 'CellWatch': break;
|
||||
|
||||
/* Print Settings */
|
||||
case 'PrintRowCol': break;
|
||||
case 'PrintGrid': break;
|
||||
case 'PrintSize': break;
|
||||
|
||||
case 'XCT': break;
|
||||
case 'CRN': break;
|
||||
|
||||
case 'Scl': {
|
||||
//console.log("Zoom Level:", val[0]/val[1],val);
|
||||
} break;
|
||||
case 'SheetExt': {
|
||||
|
||||
} break;
|
||||
case 'SheetExtOptional': {
|
||||
|
||||
} break;
|
||||
|
||||
/* VBA */
|
||||
case 'ObNoMacros': {
|
||||
|
||||
} break;
|
||||
case 'ObProj': {
|
||||
|
||||
} break;
|
||||
case 'CodeName': {
|
||||
|
||||
} break;
|
||||
case 'GUIDTypeLib': {
|
||||
|
||||
} break;
|
||||
|
||||
case 'WOpt': break; // TODO: WTF?
|
||||
case 'PhoneticInfo': break;
|
||||
|
||||
case 'OleObjectSize': break;
|
||||
|
||||
/* Differential Formatting */
|
||||
case 'DXF': case 'DXFN': case 'DXFN12': case 'DXFN12List': case 'DXFN12NoCB': break;
|
||||
|
||||
/* Data Validation */
|
||||
case 'Dv': case 'DVal': break;
|
||||
|
||||
/* Data Series */
|
||||
case 'BRAI': case 'Series': case 'SeriesText': break;
|
||||
|
||||
/* Data Connection */
|
||||
case 'DConn': break;
|
||||
case 'DbOrParamQry': break;
|
||||
case 'DBQueryExt': break;
|
||||
|
||||
/* Formatting */
|
||||
case 'IFmtRecord': break;
|
||||
case 'CondFmt': case 'CF': case 'CF12': case 'CFEx': break;
|
||||
|
||||
/* Explicitly Ignored */
|
||||
case 'Excel9File': break;
|
||||
case 'Units': break;
|
||||
case 'InterfaceHdr': case 'Mms': case 'InterfaceEnd': case 'DSF': case 'BuiltInFnGroupCount':
|
||||
/* View Stuff */
|
||||
case 'Window1': case 'Window2': case 'HideObj': case 'GridSet': case 'Guts':
|
||||
case 'UserBView': case 'UserSViewBegin': case 'UserSViewEnd':
|
||||
case 'Pane': break;
|
||||
default: switch(R.n) { /* nested */
|
||||
/* Chart */
|
||||
case 'Dat':
|
||||
case 'Begin': case 'End':
|
||||
case 'StartBlock': case 'EndBlock':
|
||||
case 'Frame': case 'Area':
|
||||
case 'Axis': case 'AxisLine': case 'Tick': break;
|
||||
case 'AxesUsed':
|
||||
case 'CrtLayout12': case 'CrtLayout12A': case 'CrtLink': case 'CrtLine': case 'CrtMlFrt': case 'CrtMlFrtContinue': break;
|
||||
case 'LineFormat': case 'AreaFormat':
|
||||
case 'Chart': case 'Chart3d': case 'Chart3DBarShape': case 'ChartFormat': case 'ChartFrtInfo': break;
|
||||
case 'PlotArea': case 'PlotGrowth': break;
|
||||
case 'SeriesList': case 'SerParent': case 'SerAuxTrend': break;
|
||||
case 'DataFormat': case 'SerToCrt': case 'FontX': break;
|
||||
case 'CatSerRange': case 'AxcExt': case 'SerFmt': break;
|
||||
case 'ShtProps': break;
|
||||
case 'DefaultText': case 'Text': case 'CatLab': break;
|
||||
case 'DataLabExtContents': break;
|
||||
case 'Legend': case 'LegendException': break;
|
||||
case 'Pie': case 'Scatter': break;
|
||||
case 'PieFormat': case 'MarkerFormat': break;
|
||||
case 'StartObject': case 'EndObject': break;
|
||||
case 'AlRuns': case 'ObjectLink': break;
|
||||
case 'SIIndex': break;
|
||||
case 'AttachedLabel': case 'YMult': break;
|
||||
|
||||
/* Chart Group */
|
||||
case 'Line': case 'Bar': break;
|
||||
case 'Surf': break;
|
||||
|
||||
/* Axis Group */
|
||||
case 'AxisParent': break;
|
||||
case 'Pos': break;
|
||||
case 'ValueRange': break;
|
||||
|
||||
/* Pivot Chart */
|
||||
case 'SXViewEx9': break; // TODO
|
||||
case 'SXViewLink': break;
|
||||
case 'PivotChartBits': break;
|
||||
case 'SBaseRef': break;
|
||||
case 'TextPropsStream': break;
|
||||
|
||||
/* Chart Misc */
|
||||
case 'LnExt': break;
|
||||
case 'MkrExt': break;
|
||||
case 'CrtCoopt': break;
|
||||
|
||||
/* Query Table */
|
||||
case 'Qsi': case 'Qsif': case 'Qsir': case 'QsiSXTag': break;
|
||||
case 'TxtQry': break;
|
||||
|
||||
/* Filter */
|
||||
case 'FilterMode': break;
|
||||
case 'AutoFilter': case 'AutoFilterInfo': break;
|
||||
case 'AutoFilter12': break;
|
||||
case 'DropDownObjIds': break;
|
||||
case 'Sort': break;
|
||||
case 'SortData': break;
|
||||
|
||||
/* Drawing */
|
||||
case 'ShapePropsStream': break;
|
||||
case 'MsoDrawing': case 'MsoDrawingGroup': case 'MsoDrawingSelection': break;
|
||||
case 'ImData': break;
|
||||
/* Pub Stuff */
|
||||
case 'WebPub': case 'AutoWebPub':
|
||||
|
||||
/* Print Stuff */
|
||||
case 'RightMargin': case 'LeftMargin': case 'TopMargin': case 'BottomMargin':
|
||||
case 'HeaderFooter': case 'HFPicture': case 'PLV':
|
||||
case 'HorizontalPageBreaks': case 'VerticalPageBreaks':
|
||||
/* Behavioral */
|
||||
case 'Backup': case 'CompressPictures': case 'Compat12': break;
|
||||
|
||||
/* Should not Happen */
|
||||
case 'Continue': case 'ContinueFrt12': break;
|
||||
|
||||
/* Future Records */
|
||||
case 'FrtFontList': case 'FrtWrapper': break;
|
||||
|
||||
/* BIFF5 records */
|
||||
case 'ExternCount': break;
|
||||
case 'RString': break;
|
||||
case 'TabIdConf': case 'Radar': case 'RadarArea': case 'DropBar': case 'Intl': case 'CoordList': case 'SerAuxErrBar': break;
|
||||
|
||||
default: switch(R.n) { /* nested */
|
||||
/* Miscellaneous */
|
||||
case 'SCENARIO': case 'DConBin': case 'PicF': case 'DataLabExt':
|
||||
case 'Lel': case 'BopPop': case 'BopPopCustom': case 'RealTimeData':
|
||||
case 'Name': break;
|
||||
default: if(options.WTF) throw 'Unrecognized Record ' + R.n;
|
||||
}}}}
|
||||
} else blob.l += length;
|
||||
}
|
||||
var sheetnamesraw = opts.biff === 2 ? ['Sheet1'] : Object.keys(Directory).sort(function(a,b) { return Number(a) - Number(b); }).map(function(x){return Directory[x].name;});
|
||||
var sheetnames = sheetnamesraw.slice();
|
||||
wb.Directory=sheetnamesraw;
|
||||
wb.SheetNames=sheetnamesraw;
|
||||
if(!options.bookSheets) wb.Sheets=Sheets;
|
||||
wb.Preamble=Preamble;
|
||||
wb.Strings = sst;
|
||||
wb.SSF = SSF.get_table();
|
||||
if(opts.enc) wb.Encryption = opts.enc;
|
||||
wb.Metadata = {};
|
||||
if(country !== undefined) wb.Metadata.Country = country;
|
||||
return wb;
|
||||
}
|
||||
|
||||
function parse_xlscfb(cfb, options) {
|
||||
if(!options) options = {};
|
||||
fix_read_opts(options);
|
||||
reset_cp();
|
||||
var CompObj, Summary, Workbook;
|
||||
if(cfb.find) {
|
||||
CompObj = cfb.find('!CompObj');
|
||||
Summary = cfb.find('!SummaryInformation');
|
||||
Workbook = cfb.find('/Workbook');
|
||||
} else {
|
||||
prep_blob(cfb, 0);
|
||||
Workbook = {content: cfb};
|
||||
}
|
||||
|
||||
if(!Workbook) Workbook = cfb.find('/Book');
|
||||
var CompObjP, SummaryP, WorkbookP;
|
||||
|
||||
if(CompObj) CompObjP = parse_compobj(CompObj);
|
||||
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");
|
||||
}
|
||||
|
||||
if(cfb.find) parse_props(cfb);
|
||||
|
||||
var props = {};
|
||||
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;
|
||||
return WorkbookP;
|
||||
}
|
||||
|
||||
/* TODO: WTF */
|
||||
function parse_props(cfb) {
|
||||
/* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
|
||||
var DSI = cfb.find('!DocumentSummaryInformation');
|
||||
if(DSI) try { cfb.DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI); } catch(e) {}
|
||||
|
||||
/* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
|
||||
var SI = cfb.find('!SummaryInformation');
|
||||
if(SI) try { cfb.Summary = parse_PropertySetStream(SI, SummaryPIDSI); } catch(e) {}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* [MS-XLSB] 2.3 Record Enumeration */
|
||||
var RecordEnum = {
|
||||
var XLSBRecordEnum = {
|
||||
0x0000: { n:"BrtRowHdr", f:parse_BrtRowHdr },
|
||||
0x0001: { n:"BrtCellBlank", f:parse_BrtCellBlank },
|
||||
0x0002: { n:"BrtCellRk", f:parse_BrtCellRk },
|
||||
@ -822,4 +822,409 @@ var RecordEnum = {
|
||||
0xFFFF: { n:"", f:parsenoop }
|
||||
};
|
||||
|
||||
var evert_RE = evert_key(RecordEnum, 'n');
|
||||
var evert_RE = evert_key(XLSBRecordEnum, 'n');
|
||||
|
||||
/* [MS-XLS] 2.3 Record Enumeration */
|
||||
var XLSRecordEnum = {
|
||||
0x0003: { n:"BIFF2NUM", f:parse_BIFF2NUM },
|
||||
0x0004: { n:"BIFF2STR", f:parse_BIFF2STR },
|
||||
0x0006: { n:"Formula", f:parse_Formula },
|
||||
0x0009: { n:'BOF', f:parse_BOF },
|
||||
0x000a: { n:'EOF', f:parse_EOF },
|
||||
0x000c: { n:"CalcCount", f:parse_CalcCount },
|
||||
0x000d: { n:"CalcMode", f:parse_CalcMode },
|
||||
0x000e: { n:"CalcPrecision", f:parse_CalcPrecision },
|
||||
0x000f: { n:"CalcRefMode", f:parse_CalcRefMode },
|
||||
0x0010: { n:"CalcDelta", f:parse_CalcDelta },
|
||||
0x0011: { n:"CalcIter", f:parse_CalcIter },
|
||||
0x0012: { n:"Protect", f:parse_Protect },
|
||||
0x0013: { n:"Password", f:parse_Password },
|
||||
0x0014: { n:"Header", f:parse_Header },
|
||||
0x0015: { n:"Footer", f:parse_Footer },
|
||||
0x0017: { n:"ExternSheet", f:parse_ExternSheet },
|
||||
0x0018: { n:"Lbl", f:parse_Lbl },
|
||||
0x0019: { n:"WinProtect", f:parse_WinProtect },
|
||||
0x001a: { n:"VerticalPageBreaks", f:parse_VerticalPageBreaks },
|
||||
0x001b: { n:"HorizontalPageBreaks", f:parse_HorizontalPageBreaks },
|
||||
0x001c: { n:"Note", f:parse_Note },
|
||||
0x001d: { n:"Selection", f:parse_Selection },
|
||||
0x0022: { n:"Date1904", f:parse_Date1904 },
|
||||
0x0023: { n:"ExternName", f:parse_ExternName },
|
||||
0x0026: { n:"LeftMargin", f:parse_LeftMargin },
|
||||
0x0027: { n:"RightMargin", f:parse_RightMargin },
|
||||
0x0028: { n:"TopMargin", f:parse_TopMargin },
|
||||
0x0029: { n:"BottomMargin", f:parse_BottomMargin },
|
||||
0x002a: { n:"PrintRowCol", f:parse_PrintRowCol },
|
||||
0x002b: { n:"PrintGrid", f:parse_PrintGrid },
|
||||
0x002f: { n:"FilePass", f:parse_FilePass },
|
||||
0x0031: { n:"Font", f:parse_Font },
|
||||
0x0033: { n:"PrintSize", f:parse_PrintSize },
|
||||
0x003c: { n:"Continue", f:parse_Continue },
|
||||
0x003d: { n:"Window1", f:parse_Window1 },
|
||||
0x0040: { n:"Backup", f:parse_Backup },
|
||||
0x0041: { n:"Pane", f:parse_Pane },
|
||||
0x0042: { n:'CodePage', f:parse_CodePage },
|
||||
0x004d: { n:"Pls", f:parse_Pls },
|
||||
0x0050: { n:"DCon", f:parse_DCon },
|
||||
0x0051: { n:"DConRef", f:parse_DConRef },
|
||||
0x0052: { n:"DConName", f:parse_DConName },
|
||||
0x0055: { n:"DefColWidth", f:parse_DefColWidth },
|
||||
0x0059: { n:"XCT", f:parse_XCT },
|
||||
0x005a: { n:"CRN", f:parse_CRN },
|
||||
0x005b: { n:"FileSharing", f:parse_FileSharing },
|
||||
0x005c: { n:'WriteAccess', f:parse_WriteAccess },
|
||||
0x005d: { n:"Obj", f:parse_Obj },
|
||||
0x005e: { n:"Uncalced", f:parse_Uncalced },
|
||||
0x005f: { n:"CalcSaveRecalc", f:parse_CalcSaveRecalc },
|
||||
0x0060: { n:"Template", f:parse_Template },
|
||||
0x0061: { n:"Intl", f:parse_Intl },
|
||||
0x0063: { n:"ObjProtect", f:parse_ObjProtect },
|
||||
0x007d: { n:"ColInfo", f:parse_ColInfo },
|
||||
0x0080: { n:"Guts", f:parse_Guts },
|
||||
0x0081: { n:"WsBool", f:parse_WsBool },
|
||||
0x0082: { n:"GridSet", f:parse_GridSet },
|
||||
0x0083: { n:"HCenter", f:parse_HCenter },
|
||||
0x0084: { n:"VCenter", f:parse_VCenter },
|
||||
0x0085: { n:'BoundSheet8', f:parse_BoundSheet8 },
|
||||
0x0086: { n:"WriteProtect", f:parse_WriteProtect },
|
||||
0x008c: { n:"Country", f:parse_Country },
|
||||
0x008d: { n:"HideObj", f:parse_HideObj },
|
||||
0x0090: { n:"Sort", f:parse_Sort },
|
||||
0x0092: { n:"Palette", f:parse_Palette },
|
||||
0x0097: { n:"Sync", f:parse_Sync },
|
||||
0x0098: { n:"LPr", f:parse_LPr },
|
||||
0x0099: { n:"DxGCol", f:parse_DxGCol },
|
||||
0x009a: { n:"FnGroupName", f:parse_FnGroupName },
|
||||
0x009b: { n:"FilterMode", f:parse_FilterMode },
|
||||
0x009c: { n:"BuiltInFnGroupCount", f:parse_BuiltInFnGroupCount },
|
||||
0x009d: { n:"AutoFilterInfo", f:parse_AutoFilterInfo },
|
||||
0x009e: { n:"AutoFilter", f:parse_AutoFilter },
|
||||
0x00a0: { n:"Scl", f:parse_Scl },
|
||||
0x00a1: { n:"Setup", f:parse_Setup },
|
||||
0x00ae: { n:"ScenMan", f:parse_ScenMan },
|
||||
0x00af: { n:"SCENARIO", f:parse_SCENARIO },
|
||||
0x00b0: { n:"SxView", f:parse_SxView },
|
||||
0x00b1: { n:"Sxvd", f:parse_Sxvd },
|
||||
0x00b2: { n:"SXVI", f:parse_SXVI },
|
||||
0x00b4: { n:"SxIvd", f:parse_SxIvd },
|
||||
0x00b5: { n:"SXLI", f:parse_SXLI },
|
||||
0x00b6: { n:"SXPI", f:parse_SXPI },
|
||||
0x00b8: { n:"DocRoute", f:parse_DocRoute },
|
||||
0x00b9: { n:"RecipName", f:parse_RecipName },
|
||||
0x00bd: { n:"MulRk", f:parse_MulRk },
|
||||
0x00be: { n:"MulBlank", f:parse_MulBlank },
|
||||
0x00c1: { n:'Mms', f:parse_Mms },
|
||||
0x00c5: { n:"SXDI", f:parse_SXDI },
|
||||
0x00c6: { n:"SXDB", f:parse_SXDB },
|
||||
0x00c7: { n:"SXFDB", f:parse_SXFDB },
|
||||
0x00c8: { n:"SXDBB", f:parse_SXDBB },
|
||||
0x00c9: { n:"SXNum", f:parse_SXNum },
|
||||
0x00ca: { n:"SxBool", f:parse_SxBool },
|
||||
0x00cb: { n:"SxErr", f:parse_SxErr },
|
||||
0x00cc: { n:"SXInt", f:parse_SXInt },
|
||||
0x00cd: { n:"SXString", f:parse_SXString },
|
||||
0x00ce: { n:"SXDtr", f:parse_SXDtr },
|
||||
0x00cf: { n:"SxNil", f:parse_SxNil },
|
||||
0x00d0: { n:"SXTbl", f:parse_SXTbl },
|
||||
0x00d1: { n:"SXTBRGIITM", f:parse_SXTBRGIITM },
|
||||
0x00d2: { n:"SxTbpg", f:parse_SxTbpg },
|
||||
0x00d3: { n:"ObProj", f:parse_ObProj },
|
||||
0x00d5: { n:"SXStreamID", f:parse_SXStreamID },
|
||||
0x00d7: { n:"DBCell", f:parse_DBCell },
|
||||
0x00d8: { n:"SXRng", f:parse_SXRng },
|
||||
0x00d9: { n:"SxIsxoper", f:parse_SxIsxoper },
|
||||
0x00da: { n:"BookBool", f:parse_BookBool },
|
||||
0x00dc: { n:"DbOrParamQry", f:parse_DbOrParamQry },
|
||||
0x00dd: { n:"ScenarioProtect", f:parse_ScenarioProtect },
|
||||
0x00de: { n:"OleObjectSize", f:parse_OleObjectSize },
|
||||
0x00e0: { n:"XF", f:parse_XF },
|
||||
0x00e1: { n:'InterfaceHdr', f:parse_InterfaceHdr },
|
||||
0x00e2: { n:'InterfaceEnd', f:parse_InterfaceEnd },
|
||||
0x00e3: { n:"SXVS", f:parse_SXVS },
|
||||
0x00e5: { n:"MergeCells", f:parse_MergeCells },
|
||||
0x00e9: { n:"BkHim", f:parse_BkHim },
|
||||
0x00eb: { n:"MsoDrawingGroup", f:parse_MsoDrawingGroup },
|
||||
0x00ec: { n:"MsoDrawing", f:parse_MsoDrawing },
|
||||
0x00ed: { n:"MsoDrawingSelection", f:parse_MsoDrawingSelection },
|
||||
0x00ef: { n:"PhoneticInfo", f:parse_PhoneticInfo },
|
||||
0x00f0: { n:"SxRule", f:parse_SxRule },
|
||||
0x00f1: { n:"SXEx", f:parse_SXEx },
|
||||
0x00f2: { n:"SxFilt", f:parse_SxFilt },
|
||||
0x00f4: { n:"SxDXF", f:parse_SxDXF },
|
||||
0x00f5: { n:"SxItm", f:parse_SxItm },
|
||||
0x00f6: { n:"SxName", f:parse_SxName },
|
||||
0x00f7: { n:"SxSelect", f:parse_SxSelect },
|
||||
0x00f8: { n:"SXPair", f:parse_SXPair },
|
||||
0x00f9: { n:"SxFmla", f:parse_SxFmla },
|
||||
0x00fb: { n:"SxFormat", f:parse_SxFormat },
|
||||
0x00fc: { n:"SST", f:parse_SST },
|
||||
0x00fd: { n:"LabelSst", f:parse_LabelSst },
|
||||
0x00ff: { n:"ExtSST", f:parse_ExtSST },
|
||||
0x0100: { n:"SXVDEx", f:parse_SXVDEx },
|
||||
0x0103: { n:"SXFormula", f:parse_SXFormula },
|
||||
0x0122: { n:"SXDBEx", f:parse_SXDBEx },
|
||||
0x0137: { n:"RRDInsDel", f:parse_RRDInsDel },
|
||||
0x0138: { n:"RRDHead", f:parse_RRDHead },
|
||||
0x013b: { n:"RRDChgCell", f:parse_RRDChgCell },
|
||||
0x013d: { n:"RRTabId", f:parse_RRTabId },
|
||||
0x013e: { n:"RRDRenSheet", f:parse_RRDRenSheet },
|
||||
0x013f: { n:"RRSort", f:parse_RRSort },
|
||||
0x0140: { n:"RRDMove", f:parse_RRDMove },
|
||||
0x014a: { n:"RRFormat", f:parse_RRFormat },
|
||||
0x014b: { n:"RRAutoFmt", f:parse_RRAutoFmt },
|
||||
0x014d: { n:"RRInsertSh", f:parse_RRInsertSh },
|
||||
0x014e: { n:"RRDMoveBegin", f:parse_RRDMoveBegin },
|
||||
0x014f: { n:"RRDMoveEnd", f:parse_RRDMoveEnd },
|
||||
0x0150: { n:"RRDInsDelBegin", f:parse_RRDInsDelBegin },
|
||||
0x0151: { n:"RRDInsDelEnd", f:parse_RRDInsDelEnd },
|
||||
0x0152: { n:"RRDConflict", f:parse_RRDConflict },
|
||||
0x0153: { n:"RRDDefName", f:parse_RRDDefName },
|
||||
0x0154: { n:"RRDRstEtxp", f:parse_RRDRstEtxp },
|
||||
0x015f: { n:"LRng", f:parse_LRng },
|
||||
0x0160: { n:"UsesELFs", f:parse_UsesELFs },
|
||||
0x0161: { n:"DSF", f:parse_DSF },
|
||||
0x0191: { n:"CUsr", f:parse_CUsr },
|
||||
0x0192: { n:"CbUsr", f:parse_CbUsr },
|
||||
0x0193: { n:"UsrInfo", f:parse_UsrInfo },
|
||||
0x0194: { n:"UsrExcl", f:parse_UsrExcl },
|
||||
0x0195: { n:"FileLock", f:parse_FileLock },
|
||||
0x0196: { n:"RRDInfo", f:parse_RRDInfo },
|
||||
0x0197: { n:"BCUsrs", f:parse_BCUsrs },
|
||||
0x0198: { n:"UsrChk", f:parse_UsrChk },
|
||||
0x01a9: { n:"UserBView", f:parse_UserBView },
|
||||
0x01aa: { n:"UserSViewBegin", f:parse_UserSViewBegin },
|
||||
0x01ab: { n:"UserSViewEnd", f:parse_UserSViewEnd },
|
||||
0x01ac: { n:"RRDUserView", f:parse_RRDUserView },
|
||||
0x01ad: { n:"Qsi", f:parse_Qsi },
|
||||
0x01ae: { n:"SupBook", f:parse_SupBook },
|
||||
0x01af: { n:"Prot4Rev", f:parse_Prot4Rev },
|
||||
0x01b0: { n:"CondFmt", f:parse_CondFmt },
|
||||
0x01b1: { n:"CF", f:parse_CF },
|
||||
0x01b2: { n:"DVal", f:parse_DVal },
|
||||
0x01b5: { n:"DConBin", f:parse_DConBin },
|
||||
0x01b6: { n:"TxO", f:parse_TxO },
|
||||
0x01b7: { n:"RefreshAll", f:parse_RefreshAll },
|
||||
0x01b8: { n:"HLink", f:parse_HLink },
|
||||
0x01b9: { n:"Lel", f:parse_Lel },
|
||||
0x01ba: { n:"CodeName", f:parse_XLSCodeName },
|
||||
0x01bb: { n:"SXFDBType", f:parse_SXFDBType },
|
||||
0x01bc: { n:"Prot4RevPass", f:parse_Prot4RevPass },
|
||||
0x01bd: { n:"ObNoMacros", f:parse_ObNoMacros },
|
||||
0x01be: { n:"Dv", f:parse_Dv },
|
||||
0x01c0: { n:"Excel9File", f:parse_Excel9File },
|
||||
0x01c1: { n:"RecalcId", f:parse_RecalcId, r:2},
|
||||
0x01c2: { n:"EntExU2", f:parse_EntExU2 },
|
||||
0x0200: { n:"Dimensions", f:parse_Dimensions },
|
||||
0x0201: { n:"Blank", f:parse_Blank },
|
||||
0x0203: { n:"Number", f:parse_Number },
|
||||
0x0204: { n:"Label", f:parse_Label },
|
||||
0x0205: { n:"BoolErr", f:parse_BoolErr },
|
||||
0x0207: { n:"String", f:parse_String },
|
||||
0x0208: { n:'Row', f:parse_Row },
|
||||
0x020b: { n:"Index", f:parse_Index },
|
||||
0x0221: { n:"Array", f:parse_Array },
|
||||
0x0225: { n:"DefaultRowHeight", f:parse_DefaultRowHeight },
|
||||
0x0236: { n:"Table", f:parse_Table },
|
||||
0x023e: { n:"Window2", f:parse_Window2 },
|
||||
0x027e: { n:"RK", f:parse_RK },
|
||||
0x0293: { n:"Style", f:parse_Style },
|
||||
0x0418: { n:"BigName", f:parse_BigName },
|
||||
0x041e: { n:"Format", f:parse_Format },
|
||||
0x043c: { n:"ContinueBigName", f:parse_ContinueBigName },
|
||||
0x04bc: { n:"ShrFmla", f:parse_ShrFmla },
|
||||
0x0800: { n:"HLinkTooltip", f:parse_HLinkTooltip },
|
||||
0x0801: { n:"WebPub", f:parse_WebPub },
|
||||
0x0802: { n:"QsiSXTag", f:parse_QsiSXTag },
|
||||
0x0803: { n:"DBQueryExt", f:parse_DBQueryExt },
|
||||
0x0804: { n:"ExtString", f:parse_ExtString },
|
||||
0x0805: { n:"TxtQry", f:parse_TxtQry },
|
||||
0x0806: { n:"Qsir", f:parse_Qsir },
|
||||
0x0807: { n:"Qsif", f:parse_Qsif },
|
||||
0x0808: { n:"RRDTQSIF", f:parse_RRDTQSIF },
|
||||
0x0809: { n:'BOF', f:parse_BOF },
|
||||
0x080a: { n:"OleDbConn", f:parse_OleDbConn },
|
||||
0x080b: { n:"WOpt", f:parse_WOpt },
|
||||
0x080c: { n:"SXViewEx", f:parse_SXViewEx },
|
||||
0x080d: { n:"SXTH", f:parse_SXTH },
|
||||
0x080e: { n:"SXPIEx", f:parse_SXPIEx },
|
||||
0x080f: { n:"SXVDTEx", f:parse_SXVDTEx },
|
||||
0x0810: { n:"SXViewEx9", f:parse_SXViewEx9 },
|
||||
0x0812: { n:"ContinueFrt", f:parse_ContinueFrt },
|
||||
0x0813: { n:"RealTimeData", f:parse_RealTimeData },
|
||||
0x0850: { n:"ChartFrtInfo", f:parse_ChartFrtInfo },
|
||||
0x0851: { n:"FrtWrapper", f:parse_FrtWrapper },
|
||||
0x0852: { n:"StartBlock", f:parse_StartBlock },
|
||||
0x0853: { n:"EndBlock", f:parse_EndBlock },
|
||||
0x0854: { n:"StartObject", f:parse_StartObject },
|
||||
0x0855: { n:"EndObject", f:parse_EndObject },
|
||||
0x0856: { n:"CatLab", f:parse_CatLab },
|
||||
0x0857: { n:"YMult", f:parse_YMult },
|
||||
0x0858: { n:"SXViewLink", f:parse_SXViewLink },
|
||||
0x0859: { n:"PivotChartBits", f:parse_PivotChartBits },
|
||||
0x085a: { n:"FrtFontList", f:parse_FrtFontList },
|
||||
0x0862: { n:"SheetExt", f:parse_SheetExt },
|
||||
0x0863: { n:"BookExt", f:parse_BookExt, r:12},
|
||||
0x0864: { n:"SXAddl", f:parse_SXAddl },
|
||||
0x0865: { n:"CrErr", f:parse_CrErr },
|
||||
0x0866: { n:"HFPicture", f:parse_HFPicture },
|
||||
0x0867: { n:'FeatHdr', f:parse_FeatHdr },
|
||||
0x0868: { n:"Feat", f:parse_Feat },
|
||||
0x086a: { n:"DataLabExt", f:parse_DataLabExt },
|
||||
0x086b: { n:"DataLabExtContents", f:parse_DataLabExtContents },
|
||||
0x086c: { n:"CellWatch", f:parse_CellWatch },
|
||||
0x0871: { n:"FeatHdr11", f:parse_FeatHdr11 },
|
||||
0x0872: { n:"Feature11", f:parse_Feature11 },
|
||||
0x0874: { n:"DropDownObjIds", f:parse_DropDownObjIds },
|
||||
0x0875: { n:"ContinueFrt11", f:parse_ContinueFrt11 },
|
||||
0x0876: { n:"DConn", f:parse_DConn },
|
||||
0x0877: { n:"List12", f:parse_List12 },
|
||||
0x0878: { n:"Feature12", f:parse_Feature12 },
|
||||
0x0879: { n:"CondFmt12", f:parse_CondFmt12 },
|
||||
0x087a: { n:"CF12", f:parse_CF12 },
|
||||
0x087b: { n:"CFEx", f:parse_CFEx },
|
||||
0x087c: { n:"XFCRC", f:parse_XFCRC, r:12 },
|
||||
0x087d: { n:"XFExt", f:parse_XFExt, r:12 },
|
||||
0x087e: { n:"AutoFilter12", f:parse_AutoFilter12 },
|
||||
0x087f: { n:"ContinueFrt12", f:parse_ContinueFrt12 },
|
||||
0x0884: { n:"MDTInfo", f:parse_MDTInfo },
|
||||
0x0885: { n:"MDXStr", f:parse_MDXStr },
|
||||
0x0886: { n:"MDXTuple", f:parse_MDXTuple },
|
||||
0x0887: { n:"MDXSet", f:parse_MDXSet },
|
||||
0x0888: { n:"MDXProp", f:parse_MDXProp },
|
||||
0x0889: { n:"MDXKPI", f:parse_MDXKPI },
|
||||
0x088a: { n:"MDB", f:parse_MDB },
|
||||
0x088b: { n:"PLV", f:parse_PLV },
|
||||
0x088c: { n:"Compat12", f:parse_Compat12, r:12 },
|
||||
0x088d: { n:"DXF", f:parse_DXF },
|
||||
0x088e: { n:"TableStyles", f:parse_TableStyles, r:12 },
|
||||
0x088f: { n:"TableStyle", f:parse_TableStyle },
|
||||
0x0890: { n:"TableStyleElement", f:parse_TableStyleElement },
|
||||
0x0892: { n:"StyleExt", f:parse_StyleExt },
|
||||
0x0893: { n:"NamePublish", f:parse_NamePublish },
|
||||
0x0894: { n:"NameCmt", f:parse_NameCmt },
|
||||
0x0895: { n:"SortData", f:parse_SortData },
|
||||
0x0896: { n:"Theme", f:parse_Theme, r:12 },
|
||||
0x0897: { n:"GUIDTypeLib", f:parse_GUIDTypeLib },
|
||||
0x0898: { n:"FnGrp12", f:parse_FnGrp12 },
|
||||
0x0899: { n:"NameFnGrp12", f:parse_NameFnGrp12 },
|
||||
0x089a: { n:"MTRSettings", f:parse_MTRSettings, r:12 },
|
||||
0x089b: { n:"CompressPictures", f:parse_CompressPictures },
|
||||
0x089c: { n:"HeaderFooter", f:parse_HeaderFooter },
|
||||
0x089d: { n:"CrtLayout12", f:parse_CrtLayout12 },
|
||||
0x089e: { n:"CrtMlFrt", f:parse_CrtMlFrt },
|
||||
0x089f: { n:"CrtMlFrtContinue", f:parse_CrtMlFrtContinue },
|
||||
0x08a3: { n:"ForceFullCalculation", f:parse_ForceFullCalculation },
|
||||
0x08a4: { n:"ShapePropsStream", f:parse_ShapePropsStream },
|
||||
0x08a5: { n:"TextPropsStream", f:parse_TextPropsStream },
|
||||
0x08a6: { n:"RichTextStream", f:parse_RichTextStream },
|
||||
0x08a7: { n:"CrtLayout12A", f:parse_CrtLayout12A },
|
||||
0x1001: { n:"Units", f:parse_Units },
|
||||
0x1002: { n:"Chart", f:parse_Chart },
|
||||
0x1003: { n:"Series", f:parse_Series },
|
||||
0x1006: { n:"DataFormat", f:parse_DataFormat },
|
||||
0x1007: { n:"LineFormat", f:parse_LineFormat },
|
||||
0x1009: { n:"MarkerFormat", f:parse_MarkerFormat },
|
||||
0x100a: { n:"AreaFormat", f:parse_AreaFormat },
|
||||
0x100b: { n:"PieFormat", f:parse_PieFormat },
|
||||
0x100c: { n:"AttachedLabel", f:parse_AttachedLabel },
|
||||
0x100d: { n:"SeriesText", f:parse_SeriesText },
|
||||
0x1014: { n:"ChartFormat", f:parse_ChartFormat },
|
||||
0x1015: { n:"Legend", f:parse_Legend },
|
||||
0x1016: { n:"SeriesList", f:parse_SeriesList },
|
||||
0x1017: { n:"Bar", f:parse_Bar },
|
||||
0x1018: { n:"Line", f:parse_Line },
|
||||
0x1019: { n:"Pie", f:parse_Pie },
|
||||
0x101a: { n:"Area", f:parse_Area },
|
||||
0x101b: { n:"Scatter", f:parse_Scatter },
|
||||
0x101c: { n:"CrtLine", f:parse_CrtLine },
|
||||
0x101d: { n:"Axis", f:parse_Axis },
|
||||
0x101e: { n:"Tick", f:parse_Tick },
|
||||
0x101f: { n:"ValueRange", f:parse_ValueRange },
|
||||
0x1020: { n:"CatSerRange", f:parse_CatSerRange },
|
||||
0x1021: { n:"AxisLine", f:parse_AxisLine },
|
||||
0x1022: { n:"CrtLink", f:parse_CrtLink },
|
||||
0x1024: { n:"DefaultText", f:parse_DefaultText },
|
||||
0x1025: { n:"Text", f:parse_Text },
|
||||
0x1026: { n:"FontX", f:parse_FontX },
|
||||
0x1027: { n:"ObjectLink", f:parse_ObjectLink },
|
||||
0x1032: { n:"Frame", f:parse_Frame },
|
||||
0x1033: { n:"Begin", f:parse_Begin },
|
||||
0x1034: { n:"End", f:parse_End },
|
||||
0x1035: { n:"PlotArea", f:parse_PlotArea },
|
||||
0x103a: { n:"Chart3d", f:parse_Chart3d },
|
||||
0x103c: { n:"PicF", f:parse_PicF },
|
||||
0x103d: { n:"DropBar", f:parse_DropBar },
|
||||
0x103e: { n:"Radar", f:parse_Radar },
|
||||
0x103f: { n:"Surf", f:parse_Surf },
|
||||
0x1040: { n:"RadarArea", f:parse_RadarArea },
|
||||
0x1041: { n:"AxisParent", f:parse_AxisParent },
|
||||
0x1043: { n:"LegendException", f:parse_LegendException },
|
||||
0x1044: { n:"ShtProps", f:parse_ShtProps },
|
||||
0x1045: { n:"SerToCrt", f:parse_SerToCrt },
|
||||
0x1046: { n:"AxesUsed", f:parse_AxesUsed },
|
||||
0x1048: { n:"SBaseRef", f:parse_SBaseRef },
|
||||
0x104a: { n:"SerParent", f:parse_SerParent },
|
||||
0x104b: { n:"SerAuxTrend", f:parse_SerAuxTrend },
|
||||
0x104e: { n:"IFmtRecord", f:parse_IFmtRecord },
|
||||
0x104f: { n:"Pos", f:parse_Pos },
|
||||
0x1050: { n:"AlRuns", f:parse_AlRuns },
|
||||
0x1051: { n:"BRAI", f:parse_BRAI },
|
||||
0x105b: { n:"SerAuxErrBar", f:parse_SerAuxErrBar },
|
||||
0x105c: { n:"ClrtClient", f:parse_ClrtClient },
|
||||
0x105d: { n:"SerFmt", f:parse_SerFmt },
|
||||
0x105f: { n:"Chart3DBarShape", f:parse_Chart3DBarShape },
|
||||
0x1060: { n:"Fbi", f:parse_Fbi },
|
||||
0x1061: { n:"BopPop", f:parse_BopPop },
|
||||
0x1062: { n:"AxcExt", f:parse_AxcExt },
|
||||
0x1063: { n:"Dat", f:parse_Dat },
|
||||
0x1064: { n:"PlotGrowth", f:parse_PlotGrowth },
|
||||
0x1065: { n:"SIIndex", f:parse_SIIndex },
|
||||
0x1066: { n:"GelFrame", f:parse_GelFrame },
|
||||
0x1067: { n:"BopPopCustom", f:parse_BopPopCustom },
|
||||
0x1068: { n:"Fbi2", f:parse_Fbi2 },
|
||||
|
||||
/* These are specified in an older version of the spec */
|
||||
0x0016: { n:"ExternCount", f:parsenoop },
|
||||
0x007e: { n:"RK", f:parsenoop }, /* Not necessarily same as 0x027e */
|
||||
0x007f: { n:"ImData", f:parsenoop },
|
||||
0x0087: { n:"Addin", f:parsenoop },
|
||||
0x0088: { n:"Edg", f:parsenoop },
|
||||
0x0089: { n:"Pub", f:parsenoop },
|
||||
0x0091: { n:"Sub", f:parsenoop },
|
||||
0x0094: { n:"LHRecord", f:parsenoop },
|
||||
0x0095: { n:"LHNGraph", f:parsenoop },
|
||||
0x0096: { n:"Sound", f:parsenoop },
|
||||
0x00a9: { n:"CoordList", f:parsenoop },
|
||||
0x00ab: { n:"GCW", f:parsenoop },
|
||||
0x00bc: { n:"ShrFmla", f:parsenoop }, /* Not necessarily same as 0x04bc */
|
||||
0x00c2: { n:"AddMenu", f:parsenoop },
|
||||
0x00c3: { n:"DelMenu", f:parsenoop },
|
||||
0x00d6: { n:"RString", f:parsenoop },
|
||||
0x00df: { n:"UDDesc", f:parsenoop },
|
||||
0x00ea: { n:"TabIdConf", f:parsenoop },
|
||||
0x0162: { n:"XL5Modify", f:parsenoop },
|
||||
0x01a5: { n:"FileSharing2", f:parsenoop },
|
||||
0x0218: { n:"Name", f:parsenoop },
|
||||
0x0223: { n:"ExternName", f:parse_ExternName },
|
||||
0x0231: { n:"Font", f:parsenoop },
|
||||
0x0406: { n:"Formula", f:parse_Formula },
|
||||
0x086d: { n:"FeatInfo", f:parsenoop },
|
||||
0x0873: { n:"FeatInfo11", f:parsenoop },
|
||||
0x0881: { n:"SXAddl12", f:parsenoop },
|
||||
0x08c0: { n:"AutoWebPub", f:parsenoop },
|
||||
0x08c1: { n:"ListObj", f:parsenoop },
|
||||
0x08c2: { n:"ListField", f:parsenoop },
|
||||
0x08c3: { n:"ListDV", f:parsenoop },
|
||||
0x08c4: { n:"ListCondFmt", f:parsenoop },
|
||||
0x08c5: { n:"ListCF", f:parsenoop },
|
||||
0x08c6: { n:"FMQry", f:parsenoop },
|
||||
0x08c7: { n:"FMSQry", f:parsenoop },
|
||||
0x08c8: { n:"PLV", f:parsenoop }, /* supposedly PLV for Excel 11 */
|
||||
0x08c9: { n:"LnExt", f:parsenoop },
|
||||
0x08ca: { n:"MkrExt", f:parsenoop },
|
||||
0x08cb: { n:"CrtCoopt", f:parsenoop },
|
||||
|
||||
0x0000: {}
|
||||
};
|
||||
|
||||
|
||||
|
@ -21,9 +21,10 @@ var fix_read_opts = fix_opts_func([
|
||||
['bookDeps', false], /* parse calculation chains */
|
||||
['bookSheets', false], /* only try to get sheet names (no Sheets) */
|
||||
['bookProps', false], /* only try to get properties (no Sheets) */
|
||||
['bookFiles', false], /* include raw file structure (keys, files) */
|
||||
['bookFiles', false], /* include raw file structure (keys, files, cfb) */
|
||||
['bookVBA', false], /* include vba raw data (vbaraw) */
|
||||
|
||||
['password',''], /* password */
|
||||
['WTF', false] /* WTF mode (throws errors) */
|
||||
]);
|
||||
|
||||
|
@ -1,10 +1,20 @@
|
||||
function readSync(data, opts) {
|
||||
function firstbyte(f,o) {
|
||||
switch((o||{}).type || "base64") {
|
||||
case 'buffer': return f[0];
|
||||
case 'base64': return Base64.decode(f.substr(0,12)).charCodeAt(0);
|
||||
case 'binary': return f.charCodeAt(0);
|
||||
case 'array': return f[0];
|
||||
default: throw new Error("Unrecognized type " + o.type);
|
||||
}
|
||||
}
|
||||
|
||||
function read_zip(data, opts) {
|
||||
var zip, d = data;
|
||||
var o = opts||{};
|
||||
if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
|
||||
switch(o.type) {
|
||||
case "base64": zip = new jszip(d, { base64:true }); break;
|
||||
case "binary": zip = new jszip(d, { base64:false }); break;
|
||||
case "binary": case "array": zip = new jszip(d, { base64:false }); break;
|
||||
case "buffer": zip = new jszip(d); break;
|
||||
case "file": zip=new jszip(d=_fs.readFileSync(data)); break;
|
||||
default: throw new Error("Unrecognized type " + o.type);
|
||||
@ -12,10 +22,27 @@ function readSync(data, opts) {
|
||||
return parse_zip(zip, o);
|
||||
}
|
||||
|
||||
function readSync(data, opts) {
|
||||
var zip, d = data, isfile = false, n;
|
||||
var o = opts||{};
|
||||
if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
|
||||
if(o.type == "file") { isfile = true; o.type = "buffer"; d = _fs.readFileSync(data); }
|
||||
switch((n = firstbyte(d, o))) {
|
||||
case 0xD0:
|
||||
if(isfile) o.type = "file";
|
||||
return parse_xlscfb(CFB.read(data, o), o);
|
||||
case 0x09: return parse_xlscfb(s2a(o.type === 'base64' ? Base64.decode(data) : data), o);
|
||||
case 0x3C: return parse_xlml(d, o);
|
||||
case 0x50:
|
||||
if(isfile) o.type = "file";
|
||||
return read_zip(data, opts);
|
||||
default: throw new Error("Unsupported file " + n);
|
||||
}
|
||||
}
|
||||
|
||||
function readFileSync(data, opts) {
|
||||
var o = opts||{}; o.type = 'file'
|
||||
var wb = readSync(data, o);
|
||||
wb.FILENAME = data;
|
||||
return wb;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
function writeSync(wb, opts) {
|
||||
function write_zip_type(wb, opts) {
|
||||
var o = opts||{};
|
||||
style_builder = new StyleBuilder(opts);
|
||||
|
||||
@ -12,14 +12,26 @@ function writeSync(wb, opts) {
|
||||
}
|
||||
}
|
||||
|
||||
function writeSync(wb, opts) {
|
||||
var o = opts||{};
|
||||
switch(o.bookType) {
|
||||
case 'xml': return write_xlml(wb, o);
|
||||
default: return write_zip_type(wb, o);
|
||||
}
|
||||
}
|
||||
|
||||
function writeFileSync(wb, filename, opts) {
|
||||
var o = opts||{}; o.type = 'file';
|
||||
|
||||
o.file = filename;
|
||||
switch(o.file.substr(-5).toLowerCase()) {
|
||||
case '.xlsx': o.bookType = 'xlsx'; break;
|
||||
case '.xlsm': o.bookType = 'xlsm'; break;
|
||||
case '.xlsb': o.bookType = 'xlsb'; break;
|
||||
}
|
||||
default: switch(o.file.substr(-4).toLowerCase()) {
|
||||
case '.xls': o.bookType = 'xls'; break;
|
||||
case '.xml': o.bookType = 'xml'; break;
|
||||
}}
|
||||
return writeSync(wb, o);
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,12 @@ function sheet_to_json(sheet, opts){
|
||||
for (R = r.s.r + offset; R <= r.e.r; ++R) {
|
||||
rr = encode_row(R);
|
||||
isempty = true;
|
||||
row = header === 1 ? [] : Object.create({ __rowNum__ : R });
|
||||
if(header === 1) row = [];
|
||||
else {
|
||||
row = {};
|
||||
if(Object.defineProperty) Object.defineProperty(row, '__rowNum__', {value:R, enumerable:false});
|
||||
else row.__rowNum__ = R;
|
||||
}
|
||||
for (C = r.s.c; C <= r.e.c; ++C) {
|
||||
val = sheet[cols[C] + rr];
|
||||
if(val === undefined || val.t === undefined) continue;
|
||||
@ -116,7 +121,7 @@ function sheet_to_json(sheet, opts){
|
||||
isempty = false;
|
||||
}
|
||||
}
|
||||
if(isempty === false) out[outi++] = row;
|
||||
if(isempty === false || header === 1) out[outi++] = row;
|
||||
}
|
||||
out.length = outi;
|
||||
return out;
|
||||
|
@ -192,7 +192,7 @@ if ((typeof 'module' != 'undefined' && typeof require != 'undefined') || (typeo
|
||||
if (attributes.alignment.vertical) { $alignment.attr('vertical', attributes.alignment.vertical);}
|
||||
if (attributes.alignment.indent) { $alignment.attr('indent', attributes.alignment.indent);}
|
||||
if (attributes.alignment.wrapText) { $alignment.attr('wrapText', attributes.alignment.wrapText);}
|
||||
if (attributes.alignment.textRotation) { $alignment.attr('textRotation', attributes.alignment.textRotation);}
|
||||
if (attributes.alignment.textRotation!=undefined) { $alignment.attr('textRotation', attributes.alignment.textRotation);}
|
||||
|
||||
$xf.append($alignment).attr('applyAlignment',1)
|
||||
|
||||
|
@ -1,7 +1,11 @@
|
||||
XLSX.parseZip = parse_zip;
|
||||
XLSX.read = readSync;
|
||||
XLSX.readFile = readFileSync;
|
||||
XLSX.parse_xlscfb = parse_xlscfb;
|
||||
XLSX.parse_zip = parse_zip;
|
||||
XLSX.read = readSync; //xlsread
|
||||
XLSX.readFile = readFileSync; //readFile
|
||||
XLSX.readFileSync = readFileSync;
|
||||
XLSX.write = writeSync;
|
||||
XLSX.writeFile = writeFileSync;
|
||||
XLSX.writeFileSync = writeFileSync;
|
||||
XLSX.utils = utils;
|
||||
XLSX.CFB = CFB;
|
||||
XLSX.SSF = SSF;
|
||||
|
@ -1 +1,2 @@
|
||||
})(typeof exports !== 'undefined' ? exports : XLSX);
|
||||
var XLS = XLSX;
|
||||
|
@ -2,7 +2,7 @@
|
||||
"name": "js-xlsx",
|
||||
"homepage": "https://github.com/SheetJS/js-xlsx",
|
||||
"main": "dist/xlsx.js",
|
||||
"version": "0.7.12",
|
||||
"version": "0.8.0",
|
||||
"ignore": [
|
||||
"bin",
|
||||
"bits",
|
||||
@ -11,10 +11,13 @@
|
||||
],
|
||||
"keywords": [
|
||||
"excel",
|
||||
"xls",
|
||||
"xml",
|
||||
"xlsx",
|
||||
"xlsm",
|
||||
"xlsb",
|
||||
"ods",
|
||||
"js-xls",
|
||||
"js-xlsx"
|
||||
]
|
||||
}
|
||||
|
2
dist/LICENSE
vendored
2
dist/LICENSE
vendored
@ -1,4 +1,4 @@
|
||||
Copyright (C) 2012-2014 SheetJS
|
||||
Copyright (C) 2012-2015 SheetJS
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
6
dist/ods.js
vendored
6
dist/ods.js
vendored
@ -15,6 +15,12 @@ var get_utils = function() {
|
||||
throw new Error("Cannot find XLSX utils");
|
||||
};
|
||||
var has_buf = (typeof Buffer !== 'undefined');
|
||||
|
||||
function cc2str(arr) {
|
||||
var o = "";
|
||||
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
|
||||
return o;
|
||||
}
|
||||
function getdata(data) {
|
||||
if(!data) return null;
|
||||
if(data.data) return data.data;
|
||||
|
17
dist/xlsx.core.min.js
vendored
17
dist/xlsx.core.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.core.min.map
vendored
2
dist/xlsx.core.min.map
vendored
File diff suppressed because one or more lines are too long
18
dist/xlsx.full.min.js
vendored
18
dist/xlsx.full.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.full.min.map
vendored
2
dist/xlsx.full.min.map
vendored
File diff suppressed because one or more lines are too long
6779
dist/xlsx.js
vendored
6779
dist/xlsx.js
vendored
File diff suppressed because one or more lines are too long
16
dist/xlsx.min.js
vendored
16
dist/xlsx.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.min.map
vendored
2
dist/xlsx.min.map
vendored
File diff suppressed because one or more lines are too long
61
index.html
61
index.html
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- xlsx.js (C) 2013-2014 SheetJS http://sheetjs.com -->
|
||||
<!-- xlsx.js (C) 2013-2015 SheetJS http://sheetjs.com -->
|
||||
<!-- vim: set ts=2: -->
|
||||
<html>
|
||||
<head>
|
||||
@ -21,7 +21,7 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<b>JS-XLSX (XLSX/XLSB/XLSM) Live Demo</b><br />
|
||||
<b>JS-XLSX (XLSX/XLSB/XLSM/XLS/XML) Live Demo</b><br />
|
||||
Output Format:
|
||||
<select name="format">
|
||||
<option value="csv" selected> CSV</option>
|
||||
@ -32,7 +32,7 @@ Output Format:
|
||||
<input type="radio" name="format" value="json"> JSON<br>
|
||||
<input type="radio" name="format" value="form"> FORMULAE<br> -->
|
||||
|
||||
<div id="drop">Drop an XLSX / XLSM / XLSB / ODS file here to see sheet data</div>
|
||||
<div id="drop">Drop an XLSX / XLSM / XLSB / ODS / XLS / XML file here to see sheet data</div>
|
||||
<p><input type="file" name="xlfile" id="xlf" /> ... or click here to select a file</p>
|
||||
<textarea id="b64data">... or paste a base64-encoding here</textarea>
|
||||
<input type="button" id="dotext" value="Click here to process the base64 text" onclick="b64it();"/><br />
|
||||
@ -50,6 +50,16 @@ Use readAsBinaryString: (when available) <input type="checkbox" name="userabs" c
|
||||
<!-- uncomment the next line here and in xlsxworker.js for ODS support -->
|
||||
<script src="dist/ods.js"></script>
|
||||
<script>
|
||||
var X = XLSX;
|
||||
var XW = {
|
||||
/* worker message */
|
||||
msg: 'xlsx',
|
||||
/* worker scripts */
|
||||
rABS: './xlsxworker2.js',
|
||||
norABS: './xlsxworker1.js',
|
||||
noxfer: './xlsxworker.js'
|
||||
};
|
||||
|
||||
var rABS = typeof FileReader !== "undefined" && typeof FileReader.prototype !== "undefined" && typeof FileReader.prototype.readAsBinaryString !== "undefined";
|
||||
if(!rABS) {
|
||||
document.getElementsByName("userabs")[0].disabled = true;
|
||||
@ -90,21 +100,21 @@ function s2ab(s) {
|
||||
return [v, b];
|
||||
}
|
||||
|
||||
function xlsxworker_noxfer(data, cb) {
|
||||
var worker = new Worker('./xlsxworker.js');
|
||||
function xw_noxfer(data, cb) {
|
||||
var worker = new Worker(XW.noxfer);
|
||||
worker.onmessage = function(e) {
|
||||
switch(e.data.t) {
|
||||
case 'ready': break;
|
||||
case 'e': console.error(e.data.d); break;
|
||||
case 'xlsx': cb(JSON.parse(e.data.d)); break;
|
||||
case XW.msg: cb(JSON.parse(e.data.d)); break;
|
||||
}
|
||||
};
|
||||
var arr = rABS ? data : btoa(fixdata(data));
|
||||
worker.postMessage({d:arr,b:rABS});
|
||||
}
|
||||
|
||||
function xlsxworker_xfer(data, cb) {
|
||||
var worker = new Worker(rABS ? './xlsxworker2.js' : './xlsxworker1.js');
|
||||
function xw_xfer(data, cb) {
|
||||
var worker = new Worker(rABS ? XW.rABS : XW.norABS);
|
||||
worker.onmessage = function(e) {
|
||||
switch(e.data.t) {
|
||||
case 'ready': break;
|
||||
@ -120,10 +130,10 @@ function xlsxworker_xfer(data, cb) {
|
||||
}
|
||||
}
|
||||
|
||||
function xlsxworker(data, cb) {
|
||||
function xw(data, cb) {
|
||||
transferable = document.getElementsByName("xferable")[0].checked;
|
||||
if(transferable) xlsxworker_xfer(data, cb);
|
||||
else xlsxworker_noxfer(data, cb);
|
||||
if(transferable) xw_xfer(data, cb);
|
||||
else xw_noxfer(data, cb);
|
||||
}
|
||||
|
||||
function get_radio_value( radioName ) {
|
||||
@ -138,7 +148,7 @@ function get_radio_value( radioName ) {
|
||||
function to_json(workbook) {
|
||||
var result = {};
|
||||
workbook.SheetNames.forEach(function(sheetName) {
|
||||
var roa = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
|
||||
var roa = X.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
|
||||
if(roa.length > 0){
|
||||
result[sheetName] = roa;
|
||||
}
|
||||
@ -149,7 +159,7 @@ function to_json(workbook) {
|
||||
function to_csv(workbook) {
|
||||
var result = [];
|
||||
workbook.SheetNames.forEach(function(sheetName) {
|
||||
var csv = XLSX.utils.sheet_to_csv(workbook.Sheets[sheetName]);
|
||||
var csv = X.utils.sheet_to_csv(workbook.Sheets[sheetName]);
|
||||
if(csv.length > 0){
|
||||
result.push("SHEET: " + sheetName);
|
||||
result.push("");
|
||||
@ -162,7 +172,7 @@ function to_csv(workbook) {
|
||||
function to_formulae(workbook) {
|
||||
var result = [];
|
||||
workbook.SheetNames.forEach(function(sheetName) {
|
||||
var formulae = XLSX.utils.get_formulae(workbook.Sheets[sheetName]);
|
||||
var formulae = X.utils.get_formulae(workbook.Sheets[sheetName]);
|
||||
if(formulae.length > 0){
|
||||
result.push("SHEET: " + sheetName);
|
||||
result.push("");
|
||||
@ -175,7 +185,7 @@ function to_formulae(workbook) {
|
||||
var tarea = document.getElementById('b64data');
|
||||
function b64it() {
|
||||
if(typeof console !== 'undefined') console.log("onload", new Date());
|
||||
var wb = XLSX.read(tarea.value, {type: 'base64',WTF:wtf_mode});
|
||||
var wb = X.read(tarea.value, {type: 'base64',WTF:wtf_mode});
|
||||
process_wb(wb);
|
||||
}
|
||||
|
||||
@ -203,22 +213,22 @@ function handleDrop(e) {
|
||||
rABS = document.getElementsByName("userabs")[0].checked;
|
||||
use_worker = document.getElementsByName("useworker")[0].checked;
|
||||
var files = e.dataTransfer.files;
|
||||
var i,f;
|
||||
for (i = 0, f = files[i]; i != files.length; ++i) {
|
||||
var f = files[0];
|
||||
{
|
||||
var reader = new FileReader();
|
||||
var name = f.name;
|
||||
reader.onload = function(e) {
|
||||
if(typeof console !== 'undefined') console.log("onload", new Date(), rABS, use_worker);
|
||||
var data = e.target.result;
|
||||
if(use_worker) {
|
||||
xlsxworker(data, process_wb);
|
||||
xw(data, process_wb);
|
||||
} else {
|
||||
var wb;
|
||||
if(rABS) {
|
||||
wb = XLSX.read(data, {type: 'binary'});
|
||||
wb = X.read(data, {type: 'binary'});
|
||||
} else {
|
||||
var arr = fixdata(data);
|
||||
wb = XLSX.read(btoa(arr), {type: 'base64'});
|
||||
wb = X.read(btoa(arr), {type: 'base64'});
|
||||
}
|
||||
process_wb(wb);
|
||||
}
|
||||
@ -246,22 +256,22 @@ function handleFile(e) {
|
||||
rABS = document.getElementsByName("userabs")[0].checked;
|
||||
use_worker = document.getElementsByName("useworker")[0].checked;
|
||||
var files = e.target.files;
|
||||
var i,f;
|
||||
for (i = 0, f = files[i]; i != files.length; ++i) {
|
||||
var f = files[0];
|
||||
{
|
||||
var reader = new FileReader();
|
||||
var name = f.name;
|
||||
reader.onload = function(e) {
|
||||
if(typeof console !== 'undefined') console.log("onload", new Date(), rABS, use_worker);
|
||||
var data = e.target.result;
|
||||
if(use_worker) {
|
||||
xlsxworker(data, process_wb);
|
||||
xw(data, process_wb);
|
||||
} else {
|
||||
var wb;
|
||||
if(rABS) {
|
||||
wb = XLSX.read(data, {type: 'binary'});
|
||||
wb = X.read(data, {type: 'binary'});
|
||||
} else {
|
||||
var arr = fixdata(data);
|
||||
wb = XLSX.read(btoa(arr), {type: 'base64'});
|
||||
wb = X.read(btoa(arr), {type: 'base64'});
|
||||
}
|
||||
process_wb(wb);
|
||||
}
|
||||
@ -273,6 +283,5 @@ function handleFile(e) {
|
||||
|
||||
if(xlf.addEventListener) xlf.addEventListener('change', handleFile, false);
|
||||
</script>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -11,10 +11,13 @@
|
||||
],
|
||||
"keywords": [
|
||||
"excel",
|
||||
"xls",
|
||||
"xml",
|
||||
"xlsx",
|
||||
"xlsm",
|
||||
"xlsb",
|
||||
"ods",
|
||||
"js-xls",
|
||||
"js-xlsx"
|
||||
]
|
||||
}
|
||||
|
104
misc/cfb.d.ts
vendored
Normal file
104
misc/cfb.d.ts
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
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;
|
||||
}
|
11
misc/strip_sourcemap.sh
Executable file
11
misc/strip_sourcemap.sh
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
# strip_sourcemap.sh -- strip sourcemaps from a JS file (missing from uglifyjs)
|
||||
# Copyright (C) 2014-2015 SheetJS
|
||||
|
||||
if [ $# -gt 0 ]; then
|
||||
if [ -e "$1" ]; then
|
||||
sed -i .sheetjs '/sourceMappingURL/d' "$1"
|
||||
fi
|
||||
else
|
||||
cat - | sed '/sourceMappingURL/d'
|
||||
fi
|
37
misc/xl.d.ts
vendored
37
misc/xl.d.ts
vendored
@ -1,3 +1,5 @@
|
||||
///<reference path='cfb.d.ts'/>
|
||||
|
||||
interface Cell {
|
||||
v;
|
||||
w?: string;
|
||||
@ -7,9 +9,25 @@ interface Cell {
|
||||
h?: string;
|
||||
c?: any;
|
||||
z?: string;
|
||||
ixfe?: number;
|
||||
}
|
||||
|
||||
interface Worksheet {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -23,10 +41,25 @@ interface Workbook {
|
||||
}
|
||||
|
||||
interface XLSX {
|
||||
verbose: Number;
|
||||
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;
|
||||
}
|
||||
|
6
ods.js
6
ods.js
@ -15,6 +15,12 @@ var get_utils = function() {
|
||||
throw new Error("Cannot find XLSX utils");
|
||||
};
|
||||
var has_buf = (typeof Buffer !== 'undefined');
|
||||
|
||||
function cc2str(arr) {
|
||||
var o = "";
|
||||
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
|
||||
return o;
|
||||
}
|
||||
function getdata(data) {
|
||||
if(!data) return null;
|
||||
if(data.data) return data.data;
|
||||
|
@ -1 +1,7 @@
|
||||
var has_buf = (typeof Buffer !== 'undefined');
|
||||
|
||||
function cc2str(arr) {
|
||||
var o = "";
|
||||
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
|
||||
return o;
|
||||
}
|
||||
|
12
package.json
12
package.json
@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "xlsx",
|
||||
"version": "0.7.12",
|
||||
"version": "0.8.0",
|
||||
"author": "sheetjs",
|
||||
"description": "Excel 2007+ spreadsheet (XLSB/XLSX/XLSM) and ODS parser and writer",
|
||||
"keywords": [ "excel", "xlsx", "xlsb", "xlsm", "ods", "office", "spreadsheet" ],
|
||||
"description": "Excel (XLSB/XLSX/XLSM/XLS/XML) and ODS spreadsheet parser and writer",
|
||||
"keywords": [ "excel", "xls", "xlsx", "xlsb", "xlsm", "ods", "office", "spreadsheet" ],
|
||||
"bin": {
|
||||
"xlsx": "./bin/xlsx.njs"
|
||||
},
|
||||
@ -20,14 +20,12 @@
|
||||
"devDependencies": {
|
||||
"mocha":"",
|
||||
"xlsjs":"",
|
||||
"uglify-js":"",
|
||||
"jasmine-node": "x"
|
||||
"uglify-js":""
|
||||
},
|
||||
"repository": { "type":"git", "url":"git://github.com/SheetJS/js-xlsx.git" },
|
||||
"scripts": {
|
||||
"pretest": "git submodule init && git submodule update",
|
||||
"test": "make test",
|
||||
"test-jasmine": "jasmine-node --verbose tests/"
|
||||
"test": "make test"
|
||||
},
|
||||
"config": {
|
||||
"blanket": {
|
||||
|
@ -12,6 +12,8 @@ function JSDateToExcelDate(inDate) {
|
||||
|
||||
var defaultCellStyle = { font: { name: "Verdana", sz: 11, color: "FF00FF88"}, fill: {fgColor: {rgb: "FFFFAA00"}}};
|
||||
|
||||
// test to see if everything on the left equals its counterpart on the right
|
||||
// but the right hand object may have other attributes which we might not care about
|
||||
function basicallyEquals(left, right) {
|
||||
if (Array.isArray(left) && Array.isArray(right)) {
|
||||
for (var i=0; i<left.length; i++) {
|
||||
@ -23,8 +25,10 @@ function basicallyEquals(left, right) {
|
||||
}
|
||||
else if (typeof left == 'object' && typeof right == 'object') {
|
||||
for (var key in left) {
|
||||
if (key != 'border' && key!='alignment' && key != 'bgColor') {
|
||||
if (key != 'bgColor') {
|
||||
if (!basicallyEquals(left[key], right[key] )) {
|
||||
if (JSON.stringify(left[key])=="{}" && right[key] == undefined) return true;
|
||||
if (JSON.stringify(right[key])=="{}" && left[key] == undefined) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -419,7 +423,7 @@ describe("Export styles", function () {
|
||||
"s": {
|
||||
"alignment": {
|
||||
"wrapText": 1,
|
||||
"alignment": "right",
|
||||
"horizontal": "right",
|
||||
"vertical": "center",
|
||||
"indent": 1
|
||||
}
|
||||
|
525
test.js
525
test.js
@ -1,4 +1,6 @@
|
||||
/* vim: set ts=2: */
|
||||
/*jshint loopfunc:true, eqnull:true */
|
||||
var X;
|
||||
var X; var XLSX = require('./')
|
||||
var modp = './';
|
||||
//var modp = 'xlsx';
|
||||
@ -11,7 +13,7 @@ if(process.env.WTF) {
|
||||
opts.cellStyles = true;
|
||||
}
|
||||
var fullex = [".xlsb", ".xlsm", ".xlsx"];
|
||||
var ex = fullex.slice(); ex.push(".ods");
|
||||
var ex = fullex.slice(); ex.push(".ods"); ex.push(".xls"); ex.push("xml");
|
||||
if(process.env.FMTS === "full") process.env.FMTS = ex.join(":");
|
||||
if(process.env.FMTS) ex=process.env.FMTS.split(":").map(function(x){return x[0]==="."?x:"."+x;});
|
||||
var exp = ex.map(function(x){ return x + ".pending"; });
|
||||
@ -30,40 +32,56 @@ function fixjson(x) { return x.replace(/[\r\n]+$/,""); }
|
||||
var dir = "./test_files/";
|
||||
|
||||
var paths = {
|
||||
cp1: dir + 'custom_properties.xlsx',
|
||||
cp2: dir + 'custom_properties.xlsb',
|
||||
css1: dir + 'cell_style_simple.xlsx',
|
||||
css2: dir + 'cell_style_simple.xlsb',
|
||||
cst1: dir + 'comments_stress_test.xlsx',
|
||||
cst2: dir + 'comments_stress_test.xlsb',
|
||||
fst1: dir + 'formula_stress_test.xlsx',
|
||||
fst2: dir + 'formula_stress_test.xlsb',
|
||||
fst3: dir + 'formula_stress_test.ods',
|
||||
fstb: dir + 'formula_stress_test.xlsb',
|
||||
hl1: dir + 'hyperlink_stress_test_2011.xlsx',
|
||||
hl2: dir + 'hyperlink_stress_test_2011.xlsb',
|
||||
lon1: dir + 'LONumbers.xlsx',
|
||||
mc1: dir + 'merge_cells.xlsx',
|
||||
mc2: dir + 'merge_cells.xlsb',
|
||||
mc3: dir + 'merge_cells.ods',
|
||||
nf1: dir + 'number_format.xlsm',
|
||||
nf2: dir + 'number_format.xlsb',
|
||||
dt1: dir + 'xlsx-stream-d-date-cell.xlsx',
|
||||
dt2: dir + 'xlsx-stream-d-date-cell.xlsb',
|
||||
swc1: dir + 'apachepoi_SimpleWithComments.xlsx',
|
||||
swc2: dir + '2013/apachepoi_SimpleWithComments.xlsx.xlsb'
|
||||
cpxls: dir + 'custom_properties.xls',
|
||||
cpxml: dir + 'custom_properties.xls.xml',
|
||||
cpxlsx: dir + 'custom_properties.xlsx',
|
||||
cpxlsb: dir + 'custom_properties.xlsb',
|
||||
cssxls: dir + 'cell_style_simple.xls',
|
||||
cssxml: dir + 'cell_style_simple.xml',
|
||||
cssxlsx: dir + 'cell_style_simple.xlsx',
|
||||
cssxlsb: dir + 'cell_style_simple.xlsb',
|
||||
cstxls: dir + 'comments_stress_test.xls',
|
||||
cstxml: dir + 'comments_stress_test.xls.xml',
|
||||
cstxlsx: dir + 'comments_stress_test.xlsx',
|
||||
cstxlsb: dir + 'comments_stress_test.xlsb',
|
||||
fstxls: dir + 'formula_stress_test.xls',
|
||||
fstxml: dir + 'formula_stress_test.xls.xml',
|
||||
fstxlsx: dir + 'formula_stress_test.xlsx',
|
||||
fstxlsb: dir + 'formula_stress_test.xlsb',
|
||||
fstods: dir + 'formula_stress_test.ods',
|
||||
hlxls: dir + 'hyperlink_stress_test_2011.xls',
|
||||
hlxml: dir + 'hyperlink_stress_test_2011.xml',
|
||||
hlxlsx: dir + 'hyperlink_stress_test_2011.xlsx',
|
||||
hlxlsb: dir + 'hyperlink_stress_test_2011.xlsb',
|
||||
lonxls: dir + 'LONumbers.xls',
|
||||
lonxlsx: dir + 'LONumbers.xlsx',
|
||||
mcxls: dir + 'merge_cells.xls',
|
||||
mcxml: dir + 'merge_cells.xls.xml',
|
||||
mcxlsx: dir + 'merge_cells.xlsx',
|
||||
mcxlsb: dir + 'merge_cells.xlsb',
|
||||
mcods: dir + 'merge_cells.ods',
|
||||
nfxls: dir + 'number_format.xls',
|
||||
nfxml: dir + 'number_format.xls.xml',
|
||||
nfxlsx: dir + 'number_format.xlsm',
|
||||
nfxlsb: dir + 'number_format.xlsb',
|
||||
dtxlsx: dir + 'xlsx-stream-d-date-cell.xlsx',
|
||||
dtxlsb: dir + 'xlsx-stream-d-date-cell.xlsb',
|
||||
swcxls: dir + 'apachepoi_SimpleWithComments.xls',
|
||||
swcxml: dir + '2011/apachepoi_SimpleWithComments.xls.xml',
|
||||
swcxlsx: dir + 'apachepoi_SimpleWithComments.xlsx',
|
||||
swcxlsb: dir + '2013/apachepoi_SimpleWithComments.xlsx.xlsb'
|
||||
};
|
||||
|
||||
var N1 = 'XLSX';
|
||||
var N2 = 'XLSB';
|
||||
|
||||
|
||||
var N3 = 'XLS';
|
||||
var N4 = 'XML';
|
||||
|
||||
function parsetest(x, wb, full, ext) {
|
||||
ext = (ext ? " [" + ext + "]": "");
|
||||
if(!full && ext) return;
|
||||
describe(x + ext + ' should have all bits', function() {
|
||||
var sname = dir + '2011/' + x + '.sheetnames';
|
||||
var sname = dir + '2011/' + x.substr(x.lastIndexOf('/')+1) + '.sheetnames';
|
||||
it('should have all sheets', function() {
|
||||
wb.SheetNames.forEach(function(y) { assert(wb.Sheets[y], 'bad sheet ' + y); });
|
||||
});
|
||||
@ -103,6 +121,12 @@ function parsetest(x, wb, full, ext) {
|
||||
if(!fs.existsSync(name)) name=(dir + root + '.xlsm.' + i + type);
|
||||
if(!fs.existsSync(name)) name=(dir + root + '.xls.' + i + type);
|
||||
}
|
||||
if(x.substr(-4) === ".xls") {
|
||||
root = x.slice(0,-4);
|
||||
if(!fs.existsSync(name)) name=(dir + root + '.xlsx.' + i + type);
|
||||
if(!fs.existsSync(name)) name=(dir + root + '.xlsm.' + i + type);
|
||||
if(!fs.existsSync(name)) name=(dir + root + '.xlsb.' + i + type);
|
||||
}
|
||||
return name;
|
||||
};
|
||||
describe(x + ext + ' should generate correct CSV output', function() {
|
||||
@ -146,12 +170,24 @@ function parsetest(x, wb, full, ext) {
|
||||
});
|
||||
});
|
||||
});
|
||||
if(fs.existsSync(dir + '2011/' + x + '.xml'))
|
||||
describe(x + ext + '.xml from 2011', function() {
|
||||
it('should parse', function() {
|
||||
var wb = X.readFile(dir + '2011/' + x + '.xml', opts);
|
||||
});
|
||||
});
|
||||
if(fs.existsSync(dir + '2013/' + x + '.xlsb'))
|
||||
describe(x + ext + '.xlsb from 2013', function() {
|
||||
it('should parse', function() {
|
||||
var wb = X.readFile(dir + '2013/' + x + '.xlsb', opts);
|
||||
});
|
||||
});
|
||||
if(fs.existsSync(dir + x + '.xml' + ext))
|
||||
describe(x + '.xml', function() {
|
||||
it('should parse', function() {
|
||||
var wb = X.readFile(dir + x + '.xml', opts);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var wbtable = {};
|
||||
@ -192,16 +228,16 @@ describe('parse options', function() {
|
||||
X = require(modp);
|
||||
});
|
||||
describe('cell', function() {
|
||||
it('should generate HTML by default', function() {
|
||||
var wb = X.readFile(paths.cst1);
|
||||
it('XLSX should generate HTML by default', function() {
|
||||
var wb = X.readFile(paths.cstxlsx);
|
||||
var ws = wb.Sheets.Sheet1;
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
assert(html_cell_types.indexOf(ws[addr].t) === -1 || ws[addr].h);
|
||||
});
|
||||
});
|
||||
it('should not generate HTML when requested', function() {
|
||||
var wb = X.readFile(paths.cst1, {cellHTML:false});
|
||||
it('XLSX should not generate HTML when requested', function() {
|
||||
var wb = X.readFile(paths.cstxlsx, {cellHTML:false});
|
||||
var ws = wb.Sheets.Sheet1;
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
@ -209,75 +245,84 @@ describe('parse options', function() {
|
||||
});
|
||||
});
|
||||
it('should generate formulae by default', function() {
|
||||
var wb = X.readFile(paths.fstb);
|
||||
var found = false;
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
if (!ws) { console.log("wb not defined"); console.log(paths.fstb); console.log(s); console.log(wb.SheetNames); }
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
if(typeof ws[addr].f !== 'undefined') return found = true;
|
||||
[paths.fstxls, paths.fstxlsb].forEach(function(p) {
|
||||
var wb = X.readFile(p);
|
||||
var found = false;
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
if(typeof ws[addr].f !== 'undefined') return (found = true);
|
||||
});
|
||||
});
|
||||
assert(found);
|
||||
});
|
||||
assert(found);
|
||||
});
|
||||
it('should not generate formulae when requested', function() {
|
||||
var wb =X.readFile(paths.fstb,{cellFormula:false});
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
assert(typeof ws[addr].f === 'undefined');
|
||||
[paths.fstxls, paths.fstxlsb].forEach(function(p) {
|
||||
var wb =X.readFile(p,{cellFormula:false});
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
assert(typeof ws[addr].f === 'undefined');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
it('should not generate number formats by default', function() {
|
||||
var wb = X.readFile(paths.nf1);
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
assert(typeof ws[addr].z === 'undefined');
|
||||
[paths.nfxls, paths.nfxlsx].forEach(function(p) {
|
||||
var wb = X.readFile(p);
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
assert(typeof ws[addr].z === 'undefined');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
it('should generate number formats when requested', function() {
|
||||
var wb = X.readFile(paths.nf1, {cellNF: true});
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
assert(ws[addr].t!== 'n' || typeof ws[addr].z !== 'undefined');
|
||||
[paths.nfxls, paths.nfxlsx].forEach(function(p) {
|
||||
var wb = X.readFile(p, {cellNF: true});
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
assert(ws[addr].t!== 'n' || typeof ws[addr].z !== 'undefined');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
it('should not generate cell styles by default', function() {
|
||||
var wb = X.readFile(paths.css1);
|
||||
[paths.cssxlsx, paths.cssxls, paths.cssxml].forEach(function(p) {
|
||||
var wb = X.readFile(p);
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
if (typeof ws[addr].s !== 'undefined') {
|
||||
console.log(paths.css1);
|
||||
}
|
||||
assert(typeof ws[addr].s === 'undefined');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
it('XLSX should generate cell styles when requested', function() {
|
||||
var wb = X.readFile(paths.css1, {cellStyles:true});
|
||||
it('should generate cell styles when requested', function() {
|
||||
/* TODO: XLS / XLML */
|
||||
[paths.cssxlsx, /*paths.cssxls, paths.cssxml*/].forEach(function(p) {
|
||||
var wb = X.readFile(p, {cellStyles:true});
|
||||
var found = false;
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
if(typeof ws[addr].s !== 'undefined') return found = true;
|
||||
if(typeof ws[addr].s !== 'undefined') return (found = true);
|
||||
});
|
||||
});
|
||||
assert(found);
|
||||
});
|
||||
});
|
||||
it('should not generate cell dates by default', function() {
|
||||
var wb = X.readFile(paths.dt1);
|
||||
var wb = X.readFile(paths.dtxlsx);
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
@ -287,7 +332,7 @@ describe('parse options', function() {
|
||||
});
|
||||
});
|
||||
it('XLSB should not generate cell dates', function() {
|
||||
var wb = X.readFile(paths.dt2, {cellDates: true});
|
||||
var wb = X.readFile(paths.dtxlsb, {cellDates: true});
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
@ -297,13 +342,13 @@ describe('parse options', function() {
|
||||
});
|
||||
});
|
||||
it('XLSX should generate cell dates when requested', function() {
|
||||
var wb = X.readFile(paths.dt1, {cellDates: true});
|
||||
var wb = X.readFile(paths.dtxlsx, {cellDates: true});
|
||||
var found = false;
|
||||
wb.SheetNames.forEach(function(s) {
|
||||
var ws = wb.Sheets[s];
|
||||
Object.keys(ws).forEach(function(addr) {
|
||||
if(addr[0] === "!" || !ws.hasOwnProperty(addr)) return;
|
||||
if(ws[addr].t === 'd') return found = true;
|
||||
if(ws[addr].t === 'd') return (found = true);
|
||||
});
|
||||
});
|
||||
assert(found);
|
||||
@ -311,19 +356,17 @@ describe('parse options', function() {
|
||||
});
|
||||
describe('sheet', function() {
|
||||
it('should not generate sheet stubs by default', function() {
|
||||
var wb = X.readFile(paths.mc1);
|
||||
assert.throws(function() { wb.Sheets.Merge.A2.v; });
|
||||
wb = X.readFile(paths.mc2);
|
||||
assert.throws(function() { wb.Sheets.Merge.A2.v; });
|
||||
wb = X.readFile(paths.mc3);
|
||||
assert.throws(function() { wb.Sheets.Merge.A2.v; });
|
||||
[paths.mcxlsx, paths.mcxlsb, paths.mcods, paths.mcxls, paths.mcxml].forEach(function(p) {
|
||||
var wb = X.readFile(p);
|
||||
assert.throws(function() { return wb.Sheets.Merge.A2.v; });
|
||||
});
|
||||
});
|
||||
it('should generate sheet stubs when requested', function() {
|
||||
var wb = X.readFile(paths.mc1, {sheetStubs:true});
|
||||
assert(typeof wb.Sheets.Merge.A2.t !== 'undefined');
|
||||
wb = X.readFile(paths.mc2, {sheetStubs:true});
|
||||
assert(typeof wb.Sheets.Merge.A2.t !== 'undefined');
|
||||
/* TODO: ODS */
|
||||
/* TODO: ODS/XLS/XML */
|
||||
[paths.mcxlsx, paths.mcxlsb /*, paths.mcods, paths.mcxls, paths.mcxml*/].forEach(function(p) {
|
||||
var wb = X.readFile(p, {sheetStubs:true});
|
||||
assert(typeof wb.Sheets.Merge.A2.t !== 'undefined');
|
||||
});
|
||||
});
|
||||
function checkcells(wb, A46, B26, C16, D2) {
|
||||
assert((typeof wb.Sheets.Text.A46 !== 'undefined') == A46);
|
||||
@ -332,84 +375,83 @@ describe('parse options', function() {
|
||||
assert((typeof wb.Sheets.Text.D2 !== 'undefined') == D2);
|
||||
}
|
||||
it('should read all cells by default', function() {
|
||||
var wb = X.readFile(paths.fst1);
|
||||
checkcells(wb, true, true, true, true);
|
||||
wb = X.readFile(paths.fst2);
|
||||
checkcells(wb, true, true, true, true);
|
||||
wb = X.readFile(paths.fst3);
|
||||
checkcells(wb, true, true, true, true);
|
||||
[paths.fstxlsx, paths.fstxlsb, paths.fstods, paths.fstxls, paths.fstxml].forEach(function(p) {
|
||||
checkcells(X.readFile(p), true, true, true, true);
|
||||
});
|
||||
});
|
||||
it('sheetRows n=20', function() {
|
||||
var wb = X.readFile(paths.fst1, {sheetRows:20});
|
||||
checkcells(wb, false, false, true, true);
|
||||
wb = X.readFile(paths.fst2, {sheetRows:20});
|
||||
checkcells(wb, false, false, true, true);
|
||||
wb = X.readFile(paths.fst3, {sheetRows:20});
|
||||
checkcells(wb, false, false, true, true);
|
||||
[paths.fstxlsx, paths.fstxlsb, paths.fstods, paths.fstxls, paths.fstxml].forEach(function(p) {
|
||||
checkcells(X.readFile(p, {sheetRows:20}), false, false, true, true);
|
||||
});
|
||||
});
|
||||
it('sheetRows n=10', function() {
|
||||
var wb = X.readFile(paths.fst1, {sheetRows:10});
|
||||
checkcells(wb, false, false, false, true);
|
||||
wb = X.readFile(paths.fst2, {sheetRows:10});
|
||||
checkcells(wb, false, false, false, true);
|
||||
wb = X.readFile(paths.fst3, {sheetRows:10});
|
||||
checkcells(wb, false, false, false, true);
|
||||
[paths.fstxlsx, paths.fstxlsb, paths.fstods, paths.fstxls, paths.fstxml].forEach(function(p) {
|
||||
checkcells(X.readFile(p, {sheetRows:10}), false, false, false, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('book', function() {
|
||||
it('bookSheets should not generate sheets', function() {
|
||||
var wb = X.readFile(paths.mc1, {bookSheets:true});
|
||||
assert(typeof wb.Sheets === 'undefined');
|
||||
var wb = X.readFile(paths.mc2, {bookSheets:true});
|
||||
assert(typeof wb.Sheets === 'undefined');
|
||||
[paths.mcxlsx, paths.mcxlsb, paths.mcxls, paths.mcxml].forEach(function(p) {
|
||||
var wb = X.readFile(p, {bookSheets:true});
|
||||
assert(typeof wb.Sheets === 'undefined');
|
||||
});
|
||||
});
|
||||
it('bookProps should not generate sheets', function() {
|
||||
var wb = X.readFile(paths.nf1, {bookProps:true});
|
||||
assert(typeof wb.Sheets === 'undefined');
|
||||
wb = X.readFile(paths.nf2, {bookProps:true});
|
||||
assert(typeof wb.Sheets === 'undefined');
|
||||
[paths.nfxlsx, paths.nfxlsb, paths.nfxls, paths.nfxml].forEach(function(p) {
|
||||
var wb = X.readFile(p, {bookProps:true});
|
||||
assert(typeof wb.Sheets === 'undefined');
|
||||
});
|
||||
});
|
||||
it('bookProps && bookSheets should not generate sheets', function() {
|
||||
var wb = X.readFile(paths.lon1, {bookProps:true, bookSheets:true});
|
||||
assert(typeof wb.Sheets === 'undefined');
|
||||
[paths.lonxlsx, paths.lonxls].forEach(function(p) {
|
||||
var wb = X.readFile(p, {bookProps:true, bookSheets:true});
|
||||
assert(typeof wb.Sheets === 'undefined');
|
||||
});
|
||||
});
|
||||
it('should not generate deps by default', function() {
|
||||
var wb = X.readFile(paths.fst1);
|
||||
assert(typeof wb.Deps === 'undefined' || !(wb.Deps.length>0));
|
||||
wb = X.readFile(paths.fst2);
|
||||
assert(typeof wb.Deps === 'undefined' || !(wb.Deps.length>0));
|
||||
[paths.fstxlsx, paths.fstxlsb, paths.fstxls, paths.fstxml].forEach(function(p) {
|
||||
var wb = X.readFile(p);
|
||||
assert(typeof wb.Deps === 'undefined' || !(wb.Deps && wb.Deps.length>0));
|
||||
});
|
||||
});
|
||||
it('bookDeps should generate deps', function() {
|
||||
var wb = X.readFile(paths.fst1, {bookDeps:true});
|
||||
assert(typeof wb.Deps !== 'undefined' && wb.Deps.length > 0);
|
||||
wb = X.readFile(paths.fst2, {bookDeps:true});
|
||||
assert(typeof wb.Deps !== 'undefined' && wb.Deps.length > 0);
|
||||
it('bookDeps should generate deps (XLSX/XLSB)', function() {
|
||||
[paths.fstxlsx, paths.fstxlsb].forEach(function(p) {
|
||||
var wb = X.readFile(p, {bookDeps:true});
|
||||
assert(typeof wb.Deps !== 'undefined' && wb.Deps.length > 0);
|
||||
});
|
||||
});
|
||||
var ckf = function(wb, fields, exists) { fields.forEach(function(f) {
|
||||
assert((typeof wb[f] !== 'undefined') == exists);
|
||||
}); };
|
||||
it('should not generate book files by default', function() {
|
||||
var wb = X.readFile(paths.fst1);
|
||||
var wb;
|
||||
wb = X.readFile(paths.fstxlsx);
|
||||
ckf(wb, ['files', 'keys'], false);
|
||||
wb = X.readFile(paths.fst2);
|
||||
wb = X.readFile(paths.fstxlsb);
|
||||
ckf(wb, ['files', 'keys'], false);
|
||||
wb = X.readFile(paths.fstxls);
|
||||
ckf(wb, ['cfb'], false);
|
||||
});
|
||||
it('bookFiles should generate book files', function() {
|
||||
var wb = X.readFile(paths.fst1, {bookFiles:true});
|
||||
var wb;
|
||||
wb = X.readFile(paths.fstxlsx, {bookFiles:true});
|
||||
ckf(wb, ['files', 'keys'], true);
|
||||
wb = X.readFile(paths.fst2, {bookFiles:true});
|
||||
wb = X.readFile(paths.fstxlsb, {bookFiles:true});
|
||||
ckf(wb, ['files', 'keys'], true);
|
||||
wb = X.readFile(paths.fstxls, {bookFiles:true});
|
||||
ckf(wb, ['cfb'], true);
|
||||
});
|
||||
it('should not generate VBA by default', function() {
|
||||
var wb = X.readFile(paths.nf1);
|
||||
var wb = X.readFile(paths.nfxlsx);
|
||||
assert(typeof wb.vbaraw === 'undefined');
|
||||
wb = X.readFile(paths.nf2);
|
||||
wb = X.readFile(paths.nfxlsb);
|
||||
assert(typeof wb.vbaraw === 'undefined');
|
||||
});
|
||||
it('bookVBA should generate vbaraw', function() {
|
||||
var wb = X.readFile(paths.nf1,{bookVBA:true});
|
||||
it('bookVBA should generate vbaraw (XLSX/XLSB)', function() {
|
||||
var wb = X.readFile(paths.nfxlsx,{bookVBA:true});
|
||||
assert(typeof wb.vbaraw !== 'undefined');
|
||||
wb = X.readFile(paths.nf2,{bookVBA:true});
|
||||
wb = X.readFile(paths.nfxlsb,{bookVBA:true});
|
||||
assert(typeof wb.vbaraw !== 'undefined');
|
||||
});
|
||||
});
|
||||
@ -417,61 +459,98 @@ describe('parse options', function() {
|
||||
|
||||
describe('input formats', function() {
|
||||
it('should read binary strings', function() {
|
||||
X.read(fs.readFileSync(paths.cst1, 'binary'), {type: 'binary'});
|
||||
X.read(fs.readFileSync(paths.cst2, 'binary'), {type: 'binary'});
|
||||
X.read(fs.readFileSync(paths.cstxlsx, 'binary'), {type: 'binary'});
|
||||
X.read(fs.readFileSync(paths.cstxlsb, 'binary'), {type: 'binary'});
|
||||
X.read(fs.readFileSync(paths.cstxls, 'binary'), {type: 'binary'});
|
||||
X.read(fs.readFileSync(paths.cstxml, 'binary'), {type: 'binary'});
|
||||
});
|
||||
it('should read base64 strings', function() {
|
||||
X.read(fs.readFileSync(paths.cst1, 'base64'), {type: 'base64'});
|
||||
X.read(fs.readFileSync(paths.cst2, 'base64'), {type: 'base64'});
|
||||
X.read(fs.readFileSync(paths.cstxls, 'base64'), {type: 'base64'});
|
||||
X.read(fs.readFileSync(paths.cstxml, 'base64'), {type: 'base64'});
|
||||
X.read(fs.readFileSync(paths.cstxlsx, 'base64'), {type: 'base64'});
|
||||
X.read(fs.readFileSync(paths.cstxlsb, 'base64'), {type: 'base64'});
|
||||
});
|
||||
it('should read buffers', function() {
|
||||
X.read(fs.readFileSync(paths.cst1), {type: 'buffer'});
|
||||
X.read(fs.readFileSync(paths.cst2), {type: 'buffer'});
|
||||
X.read(fs.readFileSync(paths.cstxls), {type: 'buffer'});
|
||||
X.read(fs.readFileSync(paths.cstxml), {type: 'buffer'});
|
||||
X.read(fs.readFileSync(paths.cstxlsx), {type: 'buffer'});
|
||||
X.read(fs.readFileSync(paths.cstxlsb), {type: 'buffer'});
|
||||
});
|
||||
it('should read array', function() {
|
||||
X.read(fs.readFileSync(paths.mcxls, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
|
||||
X.read(fs.readFileSync(paths.mcxml, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
|
||||
X.read(fs.readFileSync(paths.mcxlsx, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
|
||||
X.read(fs.readFileSync(paths.mcxlsb, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
|
||||
X.read(fs.readFileSync(paths.mcods, 'binary').split("").map(function(x) { return x.charCodeAt(0); }), {type:'array'});
|
||||
});
|
||||
it('should throw if format is unknown', function() {
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cst1), {type: 'dafuq'}); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cst2), {type: 'dafuq'}); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cstxls), {type: 'dafuq'}); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cstxml), {type: 'dafuq'}); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cstxlsx), {type: 'dafuq'}); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cstxlsb), {type: 'dafuq'}); });
|
||||
});
|
||||
it('should infer buffer type', function() {
|
||||
X.read(fs.readFileSync(paths.cst1));
|
||||
X.read(fs.readFileSync(paths.cst2));
|
||||
X.read(fs.readFileSync(paths.cstxls));
|
||||
X.read(fs.readFileSync(paths.cstxml));
|
||||
X.read(fs.readFileSync(paths.cstxlsx));
|
||||
X.read(fs.readFileSync(paths.cstxlsb));
|
||||
});
|
||||
it('should default to base64 type', function() {
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cst1, 'binary')); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cst2, 'binary')); });
|
||||
X.read(fs.readFileSync(paths.cst1, 'base64'));
|
||||
X.read(fs.readFileSync(paths.cst2, 'base64'));
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cstxls, 'binary')); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cstxml, 'binary')); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cstxlsx, 'binary')); });
|
||||
assert.throws(function() { X.read(fs.readFileSync(paths.cstxlsb, 'binary')); });
|
||||
X.read(fs.readFileSync(paths.cstxls, 'base64'));
|
||||
X.read(fs.readFileSync(paths.cstxml, 'base64'));
|
||||
X.read(fs.readFileSync(paths.cstxlsx, 'base64'));
|
||||
X.read(fs.readFileSync(paths.cstxlsb, 'base64'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('output formats', function() {
|
||||
var wb1, wb2;
|
||||
var wb1, wb2, wb3, wb4;
|
||||
before(function() {
|
||||
X = require(modp);
|
||||
wb1 = X.readFile(paths.cp1);
|
||||
wb2 = X.readFile(paths.cp2);
|
||||
wb1 = X.readFile(paths.cpxlsx);
|
||||
wb2 = X.readFile(paths.cpxlsb);
|
||||
wb3 = X.readFile(paths.cpxls);
|
||||
wb4 = X.readFile(paths.cpxml);
|
||||
});
|
||||
it('should write binary strings', function() {
|
||||
X.write(wb1, {type: 'binary'});
|
||||
X.write(wb2, {type: 'binary'});
|
||||
X.write(wb3, {type: 'binary'});
|
||||
X.write(wb4, {type: 'binary'});
|
||||
X.read(X.write(wb1, {type: 'binary'}), {type: 'binary'});
|
||||
X.read(X.write(wb2, {type: 'binary'}), {type: 'binary'});
|
||||
X.read(X.write(wb3, {type: 'binary'}), {type: 'binary'});
|
||||
X.read(X.write(wb4, {type: 'binary'}), {type: 'binary'});
|
||||
});
|
||||
it('should write base64 strings', function() {
|
||||
X.write(wb1, {type: 'base64'});
|
||||
X.write(wb2, {type: 'base64'});
|
||||
X.write(wb3, {type: 'base64'});
|
||||
X.write(wb4, {type: 'base64'});
|
||||
X.read(X.write(wb1, {type: 'base64'}), {type: 'base64'});
|
||||
X.read(X.write(wb2, {type: 'base64'}), {type: 'base64'});
|
||||
X.read(X.write(wb3, {type: 'base64'}), {type: 'base64'});
|
||||
X.read(X.write(wb4, {type: 'base64'}), {type: 'base64'});
|
||||
});
|
||||
it('should write buffers', function() {
|
||||
X.write(wb1, {type: 'buffer'});
|
||||
X.write(wb2, {type: 'buffer'});
|
||||
X.write(wb3, {type: 'buffer'});
|
||||
X.write(wb4, {type: 'buffer'});
|
||||
X.read(X.write(wb1, {type: 'buffer'}), {type: 'buffer'});
|
||||
X.read(X.write(wb2, {type: 'buffer'}), {type: 'buffer'});
|
||||
X.read(X.write(wb3, {type: 'buffer'}), {type: 'buffer'});
|
||||
X.read(X.write(wb4, {type: 'buffer'}), {type: 'buffer'});
|
||||
});
|
||||
it('should throw if format is unknown', function() {
|
||||
assert.throws(function() { X.write(wb1, {type: 'dafuq'}); });
|
||||
assert.throws(function() { X.write(wb2, {type: 'dafuq'}); });
|
||||
assert.throws(function() { X.write(wb3, {type: 'dafuq'}); });
|
||||
assert.throws(function() { X.write(wb4, {type: 'dafuq'}); });
|
||||
});
|
||||
});
|
||||
|
||||
@ -499,25 +578,24 @@ function deepcmp(x,y,k,m,c) {
|
||||
var s = k.indexOf(".");
|
||||
m = (m||"") + "|" + (s > -1 ? k.substr(0,s) : k);
|
||||
if(s < 0) return assert[c<0?'notEqual':'equal'](x[k], y[k], m);
|
||||
return deepcmp(x[k.substr(0,s)],y[k.substr(0,s)],k.substr(s+1),m,c)
|
||||
return deepcmp(x[k.substr(0,s)],y[k.substr(0,s)],k.substr(s+1),m,c);
|
||||
}
|
||||
|
||||
var styexc = [
|
||||
'A2|H10|bgColor.rgb',
|
||||
'F6|H1|patternType'
|
||||
]
|
||||
];
|
||||
var stykeys = [
|
||||
"patternType",
|
||||
"fgColor.rgb",
|
||||
"bgColor.rgb"
|
||||
];
|
||||
function diffsty(ws, r1,r2) {
|
||||
var c1 = ws[r1].s.fill, c2 = ws[r2].s.fill;
|
||||
var c1 = ws[r1].s, c2 = ws[r2].s;
|
||||
stykeys.forEach(function(m) {
|
||||
var c = -1;
|
||||
if(styexc.indexOf(r1+"|"+r2+"|"+m) > -1) c = 1;
|
||||
else if(styexc.indexOf(r2+"|"+r1+"|"+m) > -1) c = 1;
|
||||
|
||||
deepcmp(c1,c2,m,r1+","+r2,c);
|
||||
});
|
||||
}
|
||||
@ -526,10 +604,12 @@ describe('parse features', function() {
|
||||
it('should have comment as part of cell properties', function(){
|
||||
var X = require(modp);
|
||||
var sheet = 'Sheet1';
|
||||
var wb1=X.readFile(paths.swc1);
|
||||
var wb2=X.readFile(paths.swc2);
|
||||
var wb1=X.readFile(paths.swcxlsx);
|
||||
var wb2=X.readFile(paths.swcxlsb);
|
||||
var wb3=X.readFile(paths.swcxls);
|
||||
var wb4=X.readFile(paths.swcxml);
|
||||
|
||||
[wb1,wb2].map(function(wb) { return wb.Sheets[sheet]; }).forEach(function(ws, i) {
|
||||
[wb1,wb2,wb3,wb4].map(function(wb) { return wb.Sheets[sheet]; }).forEach(function(ws, i) {
|
||||
assert.equal(ws.B1.c.length, 1,"must have 1 comment");
|
||||
assert.equal(ws.B1.c[0].a, "Yegor Kozlov","must have the same author");
|
||||
assert.equal(ws.B1.c[0].t.replace(/\r\n/g,"\n").replace(/\r/g,"\n"), "Yegor Kozlov:\nfirst cell", "must have the concatenated texts");
|
||||
@ -542,40 +622,53 @@ describe('parse features', function() {
|
||||
describe('should parse core properties and custom properties', function() {
|
||||
var wb1, wb2;
|
||||
before(function() {
|
||||
X = require(modp);
|
||||
wb1 = X.readFile(paths.cp1);
|
||||
wb2 = X.readFile(paths.cp2);
|
||||
wb1 = X.readFile(paths.cpxlsx);
|
||||
wb2 = X.readFile(paths.cpxlsb);
|
||||
wb3 = X.readFile(paths.cpxls);
|
||||
wb4 = X.readFile(paths.cpxml);
|
||||
});
|
||||
|
||||
it(N1 + ' should parse core properties', function() { coreprop(wb1); });
|
||||
it(N2 + ' should parse core properties', function() { coreprop(wb2); });
|
||||
it(N3 + ' should parse core properties', function() { coreprop(wb3); });
|
||||
it(N4 + ' should parse core properties', function() { coreprop(wb4); });
|
||||
it(N1 + ' should parse custom properties', function() { custprop(wb1); });
|
||||
it(N2 + ' should parse custom properties', function() { custprop(wb2); });
|
||||
it(N3 + ' should parse custom properties', function() { custprop(wb3); });
|
||||
it(N4 + ' should parse custom properties', function() { custprop(wb4); });
|
||||
});
|
||||
|
||||
describe('sheetRows', function() {
|
||||
it('should use original range if not set', function() {
|
||||
var opts = {};
|
||||
var wb1 = X.readFile(paths.fst1, opts);
|
||||
var wb2 = X.readFile(paths.fst2, opts);
|
||||
[wb1, wb2].forEach(function(wb) {
|
||||
var wb1 = X.readFile(paths.fstxlsx, opts);
|
||||
var wb2 = X.readFile(paths.fstxlsb, opts);
|
||||
var wb3 = X.readFile(paths.fstxls, opts);
|
||||
var wb4 = X.readFile(paths.fstxml, opts);
|
||||
[wb1, wb2, wb3, wb4].forEach(function(wb) {
|
||||
assert.equal(wb.Sheets.Text["!ref"],"A1:F49");
|
||||
});
|
||||
});
|
||||
it('should adjust range if set', function() {
|
||||
var opts = {sheetRows:10};
|
||||
var wb1 = X.readFile(paths.fst1, opts);
|
||||
var wb2 = X.readFile(paths.fst2, opts);
|
||||
[wb1, wb2].forEach(function(wb) {
|
||||
var wb1 = X.readFile(paths.fstxlsx, opts);
|
||||
var wb2 = X.readFile(paths.fstxlsb, opts);
|
||||
var wb3 = X.readFile(paths.fstxls, opts);
|
||||
var wb4 = X.readFile(paths.fstxml, opts);
|
||||
/* TODO */
|
||||
[wb1, wb2 /*, wb3, wb4 */].forEach(function(wb) {
|
||||
assert.equal(wb.Sheets.Text["!fullref"],"A1:F49");
|
||||
assert.equal(wb.Sheets.Text["!ref"],"A1:F10");
|
||||
});
|
||||
});
|
||||
it('should not generate comment cells', function() {
|
||||
var opts = {sheetRows:10};
|
||||
var wb1 = X.readFile(paths.cst1, opts);
|
||||
var wb2 = X.readFile(paths.cst2, opts);
|
||||
[wb1, wb2].forEach(function(wb) {
|
||||
var wb1 = X.readFile(paths.cstxlsx, opts);
|
||||
var wb2 = X.readFile(paths.cstxlsb, opts);
|
||||
var wb3 = X.readFile(paths.cstxls, opts);
|
||||
var wb4 = X.readFile(paths.cstxml, opts);
|
||||
/* TODO */
|
||||
[wb1, wb2 /*, wb3, wb4 */].forEach(function(wb) {
|
||||
assert.equal(wb.Sheets.Sheet7["!fullref"],"A1:N34");
|
||||
assert.equal(wb.Sheets.Sheet7["!ref"],"A1");
|
||||
});
|
||||
@ -586,17 +679,23 @@ describe('parse features', function() {
|
||||
var wb1, wb2;
|
||||
before(function() {
|
||||
X = require(modp);
|
||||
wb1 = X.readFile(paths.mc1);
|
||||
wb2 = X.readFile(paths.mc2);
|
||||
wb3 = X.readFile(paths.mc3);
|
||||
wb1 = X.readFile(paths.mcxlsx);
|
||||
wb2 = X.readFile(paths.mcxlsb);
|
||||
wb3 = X.readFile(paths.mcods);
|
||||
wb4 = X.readFile(paths.mcxls);
|
||||
wb5 = X.readFile(paths.mcxml);
|
||||
});
|
||||
it('should have !merges', function() {
|
||||
assert(wb1.Sheets.Merge['!merges']);
|
||||
assert(wb2.Sheets.Merge['!merges']);
|
||||
assert(wb3.Sheets.Merge['!merges']);
|
||||
var m = [wb1, wb2, wb3].map(function(x) { return x.Sheets.Merge['!merges'].map(function(y) { return X.utils.encode_range(y); });});
|
||||
assert(wb4.Sheets.Merge['!merges']);
|
||||
assert(wb5.Sheets.Merge['!merges']);
|
||||
var m = [wb1, wb2, wb3, wb4, wb5].map(function(x) { return x.Sheets.Merge['!merges'].map(function(y) { return X.utils.encode_range(y); });});
|
||||
assert.deepEqual(m[0].sort(),m[1].sort());
|
||||
assert.deepEqual(m[0].sort(),m[2].sort());
|
||||
assert.deepEqual(m[0].sort(),m[3].sort());
|
||||
assert.deepEqual(m[0].sort(),m[4].sort());
|
||||
});
|
||||
});
|
||||
|
||||
@ -604,8 +703,10 @@ describe('parse features', function() {
|
||||
var wb1, wb2;
|
||||
before(function() {
|
||||
X = require(modp);
|
||||
wb1 = X.readFile(paths.hl1);
|
||||
wb2 = X.readFile(paths.hl2);
|
||||
wb1 = X.readFile(paths.hlxlsx);
|
||||
wb2 = X.readFile(paths.hlxlsb);
|
||||
wb3 = X.readFile(paths.hlxls);
|
||||
wb4 = X.readFile(paths.hlxml);
|
||||
});
|
||||
|
||||
function hlink(wb) {
|
||||
@ -621,14 +722,15 @@ describe('parse features', function() {
|
||||
|
||||
it(N1, function() { hlink(wb1); });
|
||||
it(N2, function() { hlink(wb2); });
|
||||
it(N3, function() { hlink(wb3); });
|
||||
it(N4, function() { hlink(wb4); });
|
||||
});
|
||||
|
||||
describe('should parse cells with date type (XLSX/XLSM)', function() {
|
||||
it('Must have read the date', function() {
|
||||
var wb, ws;
|
||||
X = require(modp);
|
||||
wb = X.readFile(paths.dt1);
|
||||
var sheetName = 'Sheet1';
|
||||
wb = X.readFile(paths.dtxlsx);
|
||||
ws = wb.Sheets[sheetName];
|
||||
var sheet = X.utils.sheet_to_row_object_array(ws);
|
||||
assert.equal(sheet[3]['てすと'], '2/14/14');
|
||||
@ -636,10 +738,9 @@ describe('parse features', function() {
|
||||
it('cellDates should not affect formatted text', function() {
|
||||
var wb1, ws1, wb2, ws2;
|
||||
var sheetName = 'Sheet1';
|
||||
X = require(modp);
|
||||
wb1 = X.readFile(paths.dt1);
|
||||
wb1 = X.readFile(paths.dtxlsx);
|
||||
ws1 = wb1.Sheets[sheetName];
|
||||
wb2 = X.readFile(paths.dt2);
|
||||
wb2 = X.readFile(paths.dtxlsb);
|
||||
ws2 = wb2.Sheets[sheetName];
|
||||
assert.equal(X.utils.sheet_to_csv(ws1),X.utils.sheet_to_csv(ws2));
|
||||
});
|
||||
@ -711,6 +812,7 @@ describe('parse features', function() {
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
|
||||
});
|
||||
|
||||
function seq(end, start) {
|
||||
@ -727,8 +829,8 @@ describe('roundtrip features', function() {
|
||||
describe('should parse core properties and custom properties', function() {
|
||||
var wb1, wb2, base = './tmp/cp';
|
||||
before(function() {
|
||||
wb1 = X.readFile(paths.cp1);
|
||||
wb2 = X.readFile(paths.cp2);
|
||||
wb1 = X.readFile(paths.cpxlsx);
|
||||
wb2 = X.readFile(paths.cpxlsb);
|
||||
fullex.forEach(function(p) {
|
||||
X.writeFile(wb1, base + '.xlsm' + p);
|
||||
X.writeFile(wb2, base + '.xlsb' + p);
|
||||
@ -745,7 +847,7 @@ describe('roundtrip features', function() {
|
||||
|
||||
describe('should preserve features', function() {
|
||||
it('merge cells', function() {
|
||||
var wb1 = X.readFile(paths.mc1);
|
||||
var wb1 = X.readFile(paths.mcxlsx);
|
||||
var wb2 = X.read(X.write(wb1, {type:'binary'}), {type:'binary'});
|
||||
var m1 = wb1.Sheets.Merge['!merges'].map(X.utils.encode_range);
|
||||
var m2 = wb2.Sheets.Merge['!merges'].map(X.utils.encode_range);
|
||||
@ -761,8 +863,8 @@ describe('roundtrip features', function() {
|
||||
var b = (n & 4) ? 'd' : 'n', di = b === 'd';
|
||||
var a = (n & 8) ? 'd' : 'n', dh = a === 'd';
|
||||
var f, sheet, addr;
|
||||
if(dh) { f = paths.dt1; sheet = 'Sheet1'; addr = 'B5'; }
|
||||
else { f = paths.nf1; sheet = '2011'; addr = 'J36'; }
|
||||
if(dh) { f = paths.dtxlsx; sheet = 'Sheet1'; addr = 'B5'; }
|
||||
else { f = paths.nfxlsx; sheet = '2011'; addr = 'J36'; }
|
||||
it('[' + a + '] -> (' + b + ') -> [' + c + '] -> (' + d + ')', function() {
|
||||
var wb1 = X.readFile(f, {cellNF: true, cellDates: di, WTF: opts.WTF});
|
||||
var wb2 = X.read(X.write(wb1, {type:'binary', cellDates:dj, WTF:opts.WTF}), {type:'binary', cellDates: dk, WTF: opts.WTF});
|
||||
@ -779,24 +881,17 @@ describe('roundtrip features', function() {
|
||||
else assert.equal(m[1].t, 'n');
|
||||
|
||||
if(m[0].t === m[1].t) assert.equal(m[0].v, m[1].v);
|
||||
else if(m[0].t === 'd') assert(Math.abs(datenum(new Date(m[0].v)) - m[1].v)) < .01; /* TODO: 1sec adjustment */
|
||||
else if(m[0].t === 'd') assert(Math.abs(datenum(new Date(m[0].v)) - m[1].v) < 0.01); /* TODO: 1sec adjustment */
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/* the XLSJS require should not cause the test suite to fail */
|
||||
var XLSJS;
|
||||
try {
|
||||
XLSJS = require('xlsjs');
|
||||
var xls = XLSJS.readFile('./test_files/formula_stress_test.xls');
|
||||
var xml = XLSJS.readFile('./test_files/formula_stress_test.xls.xml');
|
||||
} catch(e) { return; }
|
||||
describe('xlsjs conversions', function() { [
|
||||
describe('xls to xlsx conversions', function() { [
|
||||
['XLS', 'formula_stress_test.xls'],
|
||||
['XML', 'formula_stress_test.xls.xml']
|
||||
].forEach(function(w) {
|
||||
it('should be able to write ' + w[0] + ' files from xlsjs', function() {
|
||||
var xls = XLSJS.readFile('./test_files/' + w[1], {cellNF:true});
|
||||
it('should be able to write ' + w[0] + ' files', function() {
|
||||
var xls = X.readFile('./test_files/' + w[1], {cellNF:true});
|
||||
X.writeFile(xls, './tmp/' + w[1] + '.xlsx', {bookSST:true});
|
||||
X.writeFile(xls, './tmp/' + w[1] + '.xlsb', {bookSST:true});
|
||||
});
|
||||
@ -804,10 +899,12 @@ describe('roundtrip features', function() {
|
||||
});
|
||||
});
|
||||
|
||||
function password_file(x){return x.match(/^password.*\.xls$/); }
|
||||
var password_files = fs.readdirSync('test_files').filter(password_file);
|
||||
describe('invalid files', function() {
|
||||
describe('parse', function() { [
|
||||
['passwords', 'excel-reader-xlsx_error03.xlsx'],
|
||||
['XLS files', 'roo_type_excel.xlsx'],
|
||||
['password', 'apachepoi_password.xls'],
|
||||
['passwords', 'apachepoi_xor-encryption-abc.xls'],
|
||||
['DOC files', 'word_doc.doc']
|
||||
].forEach(function(w) { it('should fail on ' + w[0], function() {
|
||||
assert.throws(function() { X.readFile(dir + w[1]); });
|
||||
@ -815,14 +912,19 @@ describe('invalid files', function() {
|
||||
}); });
|
||||
});
|
||||
describe('write', function() {
|
||||
it('should pass', function() { X.write(X.readFile(paths.fst1), {type:'binary'}); });
|
||||
it('should pass -> XLSX', function() {
|
||||
X.write(X.readFile(paths.fstxlsb), {type:'binary'});
|
||||
X.write(X.readFile(paths.fstxlsx), {type:'binary'});
|
||||
X.write(X.readFile(paths.fstxls), {type:'binary'});
|
||||
X.write(X.readFile(paths.fstxml), {type:'binary'});
|
||||
});
|
||||
it('should pass if a sheet is missing', function() {
|
||||
var wb = X.readFile(paths.fst1); delete wb.Sheets[wb.SheetNames[0]];
|
||||
var wb = X.readFile(paths.fstxlsx); delete wb.Sheets[wb.SheetNames[0]];
|
||||
X.read(X.write(wb, {type:'binary'}), {type:'binary'});
|
||||
});
|
||||
['Props', 'Custprops', 'SSF'].forEach(function(t) {
|
||||
it('should pass if ' + t + ' is missing', function() {
|
||||
var wb = X.readFile(paths.fst1);
|
||||
var wb = X.readFile(paths.fstxlsx);
|
||||
assert.doesNotThrow(function() {
|
||||
delete wb[t];
|
||||
X.write(wb, {type:'binary'});
|
||||
@ -831,7 +933,7 @@ describe('invalid files', function() {
|
||||
});
|
||||
['SheetNames', 'Sheets'].forEach(function(t) {
|
||||
it('should fail if ' + t + ' is missing', function() {
|
||||
var wb = X.readFile(paths.fst1);
|
||||
var wb = X.readFile(paths.fstxlsx);
|
||||
assert.throws(function() {
|
||||
delete wb[t];
|
||||
X.write(wb, {type:'binary'});
|
||||
@ -912,9 +1014,9 @@ describe('json output', function() {
|
||||
it('should use column names if header == "A"', function() {
|
||||
var json = X.utils.sheet_to_json(ws, {header:'A'});
|
||||
assert.equal(json.length, data.length);
|
||||
assert.equal(json[1]['A'], true);
|
||||
assert.equal(json[2]['B'], "bar");
|
||||
assert.equal(json[3]['C'], "qux");
|
||||
assert.equal(json[1].A, true);
|
||||
assert.equal(json[2].B, "bar");
|
||||
assert.equal(json[3].C, "qux");
|
||||
assert.doesNotThrow(function() { seeker(json, "ABC", "sheetjs"); });
|
||||
assert.throws(function() { seeker(json, "ABCD", "sheetjs"); });
|
||||
assert.throws(function() { seeker(json, "ABC", "baz"); });
|
||||
@ -922,9 +1024,9 @@ describe('json output', function() {
|
||||
it('should use column labels if specified', function() {
|
||||
var json = X.utils.sheet_to_json(ws, {header:["O","D","I","N"]});
|
||||
assert.equal(json.length, data.length);
|
||||
assert.equal(json[1]['O'], true);
|
||||
assert.equal(json[2]['D'], "bar");
|
||||
assert.equal(json[3]['I'], "qux");
|
||||
assert.equal(json[1].O, true);
|
||||
assert.equal(json[2].D, "bar");
|
||||
assert.equal(json[3].I, "qux");
|
||||
assert.doesNotThrow(function() { seeker(json, "ODI", "sheetjs"); });
|
||||
assert.throws(function() { seeker(json, "ODIN", "sheetjs"); });
|
||||
assert.throws(function() { seeker(json, "ODIN", "baz"); });
|
||||
@ -990,4 +1092,27 @@ describe('corner cases', function() {
|
||||
}
|
||||
});
|
||||
});
|
||||
it('CFB', function() {
|
||||
var cfb = X.CFB.read(paths.swcxls, {type:"file"});
|
||||
var xls = X.parse_xlscfb(cfb);
|
||||
});
|
||||
it('codepage', function() {
|
||||
X.readFile(dir + "biff5/number_format_greek.xls");
|
||||
});
|
||||
});
|
||||
|
||||
describe('encryption', function() {
|
||||
password_files.forEach(function(x) {
|
||||
describe(x, function() {
|
||||
it('should throw with no password', function() {assert.throws(function() { X.readFile(dir + x); }); });
|
||||
it('should throw with wrong password', function() {assert.throws(function() { X.readFile(dir + x, {password:'passwor',WTF:opts.WTF}); }); });
|
||||
it('should recognize correct password', function() {
|
||||
try { X.readFile(dir + x, {password:'password',WTF:opts.WTF}); }
|
||||
catch(e) { if(e.message == "Password is incorrect") throw e; }
|
||||
});
|
||||
it.skip('should decrypt file', function() {
|
||||
var wb = X.readFile(dir + x, {password:'password',WTF:opts.WTF});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
694
tests.lst
694
tests.lst
@ -368,3 +368,697 @@ roo_type_excel.ods.pending
|
||||
roo_type_excelx.ods
|
||||
roo_whitespace.ods
|
||||
sushi.ods
|
||||
biff5/NumberFormatCondition.xls
|
||||
biff5/RkNumber.xls
|
||||
biff5/cell_style_simple.xls
|
||||
biff5/comments_stress_test.xls
|
||||
biff5/custom_properties.xls
|
||||
biff5/defined_names_simple.xls
|
||||
biff5/hyperlink_stress_test_2011.xls
|
||||
biff5/large_strings.xls.pending
|
||||
biff5/merge_cells.xls
|
||||
biff5/named_ranges_2011.xls
|
||||
biff5/number_format.xls
|
||||
biff5/number_format_estonian.xls
|
||||
biff5/number_format_greek.xls.pending
|
||||
biff5/number_format_vietnamese.xls
|
||||
biff5/pivot_table_test.xls
|
||||
biff5/rich_text_stress.xls
|
||||
biff5/sushi.xls
|
||||
biff5/text_and_numbers.xls
|
||||
comments_stress_test.xls.b64
|
||||
formula_stress_test.xls.b64
|
||||
A4X_2013.xls
|
||||
A4X_gnumeric.xls
|
||||
AutoFilter.xls
|
||||
BlankSheetTypes.xls
|
||||
ErrorTypes.xls
|
||||
LONumbers-2010.xls
|
||||
LONumbers-2011.xls
|
||||
LONumbers.xls
|
||||
NumberFormatCondition.xls
|
||||
RkNumber.xls
|
||||
apachepoi_12561-1.xls
|
||||
apachepoi_12561-2.xls
|
||||
apachepoi_12843-1.xls
|
||||
apachepoi_12843-2.xls
|
||||
apachepoi_13224.xls
|
||||
apachepoi_13796.xls
|
||||
apachepoi_14330-1.xls
|
||||
apachepoi_14330-2.xls
|
||||
apachepoi_14460.xls
|
||||
apachepoi_15228.xls
|
||||
apachepoi_15375.xls
|
||||
apachepoi_15556.xls
|
||||
apachepoi_15573.xls
|
||||
apachepoi_1900DateWindowing.xls
|
||||
apachepoi_1904DateWindowing.xls
|
||||
apachepoi_19599-1.xls
|
||||
apachepoi_19599-2.xls
|
||||
apachepoi_22742.xls
|
||||
apachepoi_24207.xls
|
||||
apachepoi_24215.xls
|
||||
apachepoi_25183.xls
|
||||
apachepoi_25695.xls
|
||||
apachepoi_26100.xls
|
||||
apachepoi_27272_1.xls
|
||||
apachepoi_27272_2.xls
|
||||
apachepoi_27349-vlookupAcrossSheets.xls
|
||||
apachepoi_27364.xls
|
||||
apachepoi_27394.xls
|
||||
apachepoi_27852.xls
|
||||
apachepoi_27933.xls
|
||||
apachepoi_28772.xls
|
||||
apachepoi_28774.xls
|
||||
apachepoi_29675.xls
|
||||
apachepoi_29942.xls
|
||||
apachepoi_29982.xls
|
||||
apachepoi_30070.xls
|
||||
apachepoi_30540.xls
|
||||
apachepoi_30978-alt.xls
|
||||
apachepoi_30978-deleted.xls
|
||||
apachepoi_31661.xls
|
||||
apachepoi_31749.xls
|
||||
apachepoi_31979.xls
|
||||
apachepoi_32822.xls
|
||||
apachepoi_33082.xls
|
||||
apachepoi_34775.xls
|
||||
apachepoi_35564.xls
|
||||
apachepoi_35565.xls
|
||||
apachepoi_36947.xls
|
||||
apachepoi_37376.xls
|
||||
apachepoi_37630.xls
|
||||
apachepoi_37684-1.xls
|
||||
apachepoi_37684-2.xls
|
||||
apachepoi_37684.xls
|
||||
apachepoi_39234.xls
|
||||
apachepoi_39512.xls
|
||||
apachepoi_39634.xls
|
||||
apachepoi_3dFormulas.xls
|
||||
apachepoi_40285.xls
|
||||
apachepoi_41139.xls
|
||||
apachepoi_41546.xls
|
||||
apachepoi_42016.xls
|
||||
apachepoi_42464-ExpPtg-bad.xls
|
||||
apachepoi_42464-ExpPtg-ok.xls
|
||||
apachepoi_42726.xls
|
||||
apachepoi_42844.xls
|
||||
apachepoi_43251.xls
|
||||
apachepoi_43493.xls
|
||||
apachepoi_43623.xls
|
||||
apachepoi_43902.xls
|
||||
apachepoi_44010-SingleChart.xls
|
||||
apachepoi_44010-TwoCharts.xls
|
||||
apachepoi_44167.xls
|
||||
apachepoi_44200.xls
|
||||
apachepoi_44201.xls
|
||||
apachepoi_44235.xls
|
||||
apachepoi_44297.xls
|
||||
apachepoi_44593.xls
|
||||
apachepoi_44636.xls
|
||||
apachepoi_44643.xls
|
||||
apachepoi_44693.xls
|
||||
apachepoi_44840.xls
|
||||
apachepoi_44861.xls
|
||||
apachepoi_44891.xls
|
||||
apachepoi_44958.xls
|
||||
apachepoi_45129.xls
|
||||
apachepoi_45290.xls
|
||||
apachepoi_45322.xls
|
||||
apachepoi_45365-2.xls
|
||||
apachepoi_45365.xls
|
||||
apachepoi_45492.xls
|
||||
apachepoi_45538_classic_Footer.xls
|
||||
apachepoi_45538_classic_Header.xls
|
||||
apachepoi_45538_form_Footer.xls
|
||||
apachepoi_45538_form_Header.xls
|
||||
apachepoi_45672.xls
|
||||
apachepoi_45720.xls
|
||||
apachepoi_45761.xls
|
||||
apachepoi_45784.xls
|
||||
apachepoi_46136-NoWarnings.xls
|
||||
apachepoi_46136-WithWarnings.xls
|
||||
apachepoi_46137.xls
|
||||
apachepoi_46250.xls
|
||||
apachepoi_46368.xls
|
||||
apachepoi_46445.xls
|
||||
apachepoi_46670_http.xls
|
||||
apachepoi_46670_local.xls
|
||||
apachepoi_46670_ref_airline.xls
|
||||
apachepoi_46904.xls
|
||||
apachepoi_47034.xls
|
||||
apachepoi_47154.xls
|
||||
apachepoi_47251.xls
|
||||
apachepoi_47251_1.xls
|
||||
apachepoi_47701.xls
|
||||
apachepoi_47847.xls
|
||||
apachepoi_47920.xls
|
||||
apachepoi_47924.xls
|
||||
apachepoi_48026.xls
|
||||
apachepoi_48180.xls
|
||||
apachepoi_48325.xls
|
||||
apachepoi_48703.xls
|
||||
apachepoi_48968.xls
|
||||
apachepoi_49096.xls
|
||||
apachepoi_49185.xls
|
||||
apachepoi_49219.xls
|
||||
apachepoi_49237.xls
|
||||
apachepoi_49524.xls
|
||||
apachepoi_49529.xls
|
||||
apachepoi_49581.xls
|
||||
apachepoi_49612.xls
|
||||
apachepoi_49751.xls
|
||||
apachepoi_49761.xls
|
||||
apachepoi_49896.xls
|
||||
apachepoi_49928.xls
|
||||
apachepoi_49931.xls
|
||||
apachepoi_50020.xls
|
||||
apachepoi_50298.xls
|
||||
apachepoi_50426.xls
|
||||
apachepoi_50756.xls
|
||||
apachepoi_50779_1.xls
|
||||
apachepoi_50779_2.xls
|
||||
apachepoi_50833.xls.pending
|
||||
apachepoi_50939.xls
|
||||
apachepoi_51143.xls
|
||||
apachepoi_51461.xls
|
||||
apachepoi_51498.xls
|
||||
apachepoi_51535.xls.pending
|
||||
apachepoi_51670.xls
|
||||
apachepoi_51675.xls
|
||||
apachepoi_51832.xls.pending
|
||||
apachepoi_52527.xls
|
||||
apachepoi_52575_main.xls
|
||||
apachepoi_52575_source.xls
|
||||
apachepoi_53404.xls
|
||||
apachepoi_53433.xls
|
||||
apachepoi_53446.xls
|
||||
apachepoi_53588.xls
|
||||
apachepoi_53691.xls
|
||||
apachepoi_53798_shiftNegative_TMPL.xls
|
||||
apachepoi_53972.xls
|
||||
apachepoi_53984.xls
|
||||
apachepoi_54016.xls
|
||||
apachepoi_54206.xls
|
||||
apachepoi_54500.xls
|
||||
apachepoi_54686_fraction_formats.xls
|
||||
apachepoi_55341_CellStyleBorder.xls
|
||||
apachepoi_55906-MultiSheetRefs.xls
|
||||
apachepoi_56325.xls
|
||||
apachepoi_56450.xls
|
||||
apachepoi_56482.xls
|
||||
apachepoi_56563a.xls
|
||||
apachepoi_56563b.xls
|
||||
apachepoi_56737.xls
|
||||
apachepoi_AbnormalSharedFormulaFlag.xls
|
||||
apachepoi_AreaErrPtg.xls
|
||||
apachepoi_BOOK_in_capitals.xls
|
||||
apachepoi_CodeFunctionTestCaseData.xls
|
||||
apachepoi_ColumnStyle1dp.xls
|
||||
apachepoi_ColumnStyle1dpColoured.xls
|
||||
apachepoi_ColumnStyleNone.xls
|
||||
apachepoi_ComplexFunctionTestCaseData.xls
|
||||
apachepoi_ContinueRecordProblem.xls
|
||||
apachepoi_DBCSHeader.xls
|
||||
apachepoi_DBCSSheetName.xls
|
||||
apachepoi_DateFormats.xls
|
||||
apachepoi_DeltaFunctionTestCaseData.xls
|
||||
apachepoi_DrawingAndComments.xls
|
||||
apachepoi_DrawingContinue.xls
|
||||
apachepoi_EmbeddedChartHeaderTest.xls
|
||||
apachepoi_Employee.xls
|
||||
apachepoi_ErrPtg.xls
|
||||
apachepoi_FactDoubleFunctionTestCaseData.xls
|
||||
apachepoi_ForShifting.xls
|
||||
apachepoi_FormatChoiceTests.xls
|
||||
apachepoi_Formatting.xls
|
||||
apachepoi_FormulaEvalTestData.xls
|
||||
apachepoi_FormulaRefs.xls
|
||||
apachepoi_FormulaSheetRange.xls
|
||||
apachepoi_HyperlinksOnManySheets.xls
|
||||
apachepoi_IfFormulaTest.xls
|
||||
apachepoi_ImRealFunctionTestCaseData.xls
|
||||
apachepoi_ImaginaryFunctionTestCaseData.xls
|
||||
apachepoi_IndexFunctionTestCaseData.xls
|
||||
apachepoi_IndirectFunctionTestCaseData.xls
|
||||
apachepoi_Intersection-52111.xls
|
||||
apachepoi_IntersectionPtg.xls
|
||||
apachepoi_IrrNpvTestCaseData.xls
|
||||
apachepoi_LookupFunctionsTestCaseData.xls
|
||||
apachepoi_MRExtraLines.xls
|
||||
apachepoi_MatchFunctionTestCaseData.xls
|
||||
apachepoi_MissingBits.xls
|
||||
apachepoi_NoGutsRecords.xls
|
||||
apachepoi_OddStyleRecord.xls
|
||||
apachepoi_PercentPtg.xls
|
||||
apachepoi_QuotientFunctionTestCaseData.xls
|
||||
apachepoi_RangePtg.xls
|
||||
apachepoi_ReadOnlyRecommended.xls
|
||||
apachepoi_ReferencePtg.xls
|
||||
apachepoi_RepeatingRowsCols.xls
|
||||
apachepoi_ReptFunctionTestCaseData.xls
|
||||
apachepoi_RomanFunctionTestCaseData.xls
|
||||
apachepoi_SampleSS.xls
|
||||
apachepoi_SharedFormulaTest.xls
|
||||
apachepoi_SheetWithDrawing.xls
|
||||
apachepoi_ShrinkToFit.xls
|
||||
apachepoi_Simple.xls
|
||||
apachepoi_SimpleChart.xls
|
||||
apachepoi_SimpleMultiCell.xls
|
||||
apachepoi_SimpleWithAutofilter.xls
|
||||
apachepoi_SimpleWithChoose.xls
|
||||
apachepoi_SimpleWithColours.xls
|
||||
apachepoi_SimpleWithComments.xls
|
||||
apachepoi_SimpleWithDataFormat.xls
|
||||
apachepoi_SimpleWithFormula.xls
|
||||
apachepoi_SimpleWithImages-mac.xls
|
||||
apachepoi_SimpleWithImages.xls
|
||||
apachepoi_SimpleWithPageBreaks.xls
|
||||
apachepoi_SimpleWithPrintArea.xls
|
||||
apachepoi_SimpleWithSkip.xls
|
||||
apachepoi_SimpleWithStyling.xls
|
||||
apachepoi_SingleLetterRanges.xls
|
||||
apachepoi_SolverContainerAfterSPGR.xls
|
||||
apachepoi_SquareMacro.xls
|
||||
apachepoi_StringContinueRecords.xls
|
||||
apachepoi_StringFormulas.xls
|
||||
apachepoi_SubtotalsNested.xls
|
||||
apachepoi_TestRandBetween.xls
|
||||
apachepoi_TwoSheetsNoneHidden.xls
|
||||
apachepoi_TwoSheetsOneHidden.xls
|
||||
apachepoi_UncalcedRecord.xls
|
||||
apachepoi_UnionPtg.xls
|
||||
apachepoi_WORKBOOK_in_capitals.xls
|
||||
apachepoi_WeekNumFunctionTestCaseData.xls
|
||||
apachepoi_WeekNumFunctionTestCaseData2013.xls
|
||||
apachepoi_WithChart.xls
|
||||
apachepoi_WithCheckBoxes.xls
|
||||
apachepoi_WithConditionalFormatting.xls
|
||||
apachepoi_WithEmbeddedObjects.xls
|
||||
apachepoi_WithExtendedStyles.xls
|
||||
apachepoi_WithFormattedGraphTitle.xls
|
||||
apachepoi_WithHyperlink.xls
|
||||
apachepoi_WithThreeCharts.xls
|
||||
apachepoi_WithTwoCharts.xls
|
||||
apachepoi_WithTwoHyperLinks.xls
|
||||
apachepoi_WrongFormulaRecordType.xls
|
||||
apachepoi_XRefCalc.xls
|
||||
apachepoi_XRefCalcData.xls
|
||||
apachepoi_atp.xls
|
||||
apachepoi_blankworkbook.xls
|
||||
apachepoi_bug_42794.xls
|
||||
apachepoi_colwidth.xls
|
||||
apachepoi_comments.xls
|
||||
apachepoi_countblankExamples.xls
|
||||
apachepoi_countifExamples.xls
|
||||
apachepoi_dg-text.xls
|
||||
apachepoi_drawings.xls
|
||||
apachepoi_duprich1.xls
|
||||
apachepoi_duprich2.xls
|
||||
apachepoi_dvEmpty.xls
|
||||
apachepoi_empty.xls
|
||||
apachepoi_ex41187-19267.xls
|
||||
apachepoi_ex42564-21435.xls
|
||||
apachepoi_ex42564-21503.xls
|
||||
apachepoi_ex42564-elementOrder.xls
|
||||
apachepoi_ex42570-20305.xls
|
||||
apachepoi_ex44921-21902.xls
|
||||
apachepoi_ex45046-21984.xls
|
||||
apachepoi_ex45582-22397.xls
|
||||
apachepoi_ex45672.xls
|
||||
apachepoi_ex45698-22488.xls.pending
|
||||
apachepoi_ex45978-extraLinkTableSheets.xls
|
||||
apachepoi_ex46548-23133.xls
|
||||
apachepoi_ex47747-sharedFormula.xls
|
||||
apachepoi_excel_with_embeded.xls
|
||||
apachepoi_excelant.xls.pending
|
||||
apachepoi_externalFunctionExample.xls
|
||||
apachepoi_finance.xls
|
||||
apachepoi_intercept.xls
|
||||
apachepoi_mirrTest.xls
|
||||
apachepoi_missingFuncs44675.xls
|
||||
apachepoi_mortgage-calculation.xls
|
||||
apachepoi_multibookFormulaA.xls
|
||||
apachepoi_multibookFormulaB.xls
|
||||
apachepoi_namedinput.xls
|
||||
apachepoi_noHeaderFooter47244.xls
|
||||
apachepoi_ole2-embedding.xls
|
||||
apachepoi_overlapSharedFormula.xls
|
||||
apachepoi_password.xls.pending
|
||||
apachepoi_rank.xls
|
||||
apachepoi_rk.xls
|
||||
apachepoi_shared_formulas.xls
|
||||
apachepoi_sumifformula.xls
|
||||
apachepoi_sumifs.xls
|
||||
apachepoi_templateExcelWithAutofilter.xls
|
||||
apachepoi_testArraysAndTables.xls
|
||||
apachepoi_testNames.xls
|
||||
apachepoi_testRRaC.xls
|
||||
apachepoi_testRVA.xls
|
||||
apachepoi_text.xls
|
||||
apachepoi_unicodeNameRecord.xls
|
||||
apachepoi_xor-encryption-abc.xls.pending
|
||||
apachepoi_yearfracExamples.xls
|
||||
calendar_stress_test.xls.pending
|
||||
cell_style_simple.xls
|
||||
comments_stress_test.xls
|
||||
custom_properties.xls
|
||||
defined_names_simple.xls
|
||||
formula_stress_test.xls
|
||||
formulae_test_simple.xls
|
||||
hyperlink_stress_test_2011.xls
|
||||
jxls-core_array.xls
|
||||
jxls-core_beandata.xls
|
||||
jxls-core_beanwithlist.xls
|
||||
jxls-core_doubleForEachOneRow.xls
|
||||
jxls-core_dynamicColumns.xls
|
||||
jxls-core_employeeNotes.xls
|
||||
jxls-core_expressions1.xls
|
||||
jxls-core_fixedsizelist.xls
|
||||
jxls-core_forOneRow.xls
|
||||
jxls-core_forOneRowMerge.xls
|
||||
jxls-core_forOneRowMerge2.xls
|
||||
jxls-core_forgroup.xls
|
||||
jxls-core_foriftag2.xls
|
||||
jxls-core_foriftag3.xls
|
||||
jxls-core_foriftag3OutTag.xls
|
||||
jxls-core_foriftagHor.xls
|
||||
jxls-core_foriftagOneRow.xls
|
||||
jxls-core_foriftagOneRow2.xls
|
||||
jxls-core_foriftagmerge.xls
|
||||
jxls-core_formatterbean.xls
|
||||
jxls-core_formula3.xls
|
||||
jxls-core_formula4.xls
|
||||
jxls-core_formulas.xls
|
||||
jxls-core_formulas2.xls
|
||||
jxls-core_grouping1.xls
|
||||
jxls-core_grouping2.xls
|
||||
jxls-core_grouping3.xls
|
||||
jxls-core_grouping4.xls
|
||||
jxls-core_groupingformulas.xls
|
||||
jxls-core_grouptag.xls
|
||||
jxls-core_hidesheets.xls
|
||||
jxls-core_iftag.xls
|
||||
jxls-core_iftagempty.xls
|
||||
jxls-core_jexl.xls
|
||||
jxls-core_mergecellslist.xls
|
||||
jxls-core_mergemultiplelistrows.xls
|
||||
jxls-core_multi-tab-template.xls
|
||||
jxls-core_multipleSheetList.xls
|
||||
jxls-core_multiplelistrows.xls
|
||||
jxls-core_outline.xls
|
||||
jxls-core_outtaginonerow.xls
|
||||
jxls-core_paralleltables.xls
|
||||
jxls-core_poiobjects.xls
|
||||
jxls-core_repeatedFormula.xls
|
||||
jxls-core_report.xls
|
||||
jxls-core_reportTimestamp.xls
|
||||
jxls-core_select.xls
|
||||
jxls-core_select2.xls
|
||||
jxls-core_severallistsinrow.xls
|
||||
jxls-core_severalpropertiesincell.xls
|
||||
jxls-core_simplebean.xls
|
||||
jxls-core_sqltagreport.xls
|
||||
jxls-core_stress.xls
|
||||
jxls-core_syntaxerror.xls
|
||||
jxls-core_twoIfTagsIn1Row.xls
|
||||
jxls-core_varstatus.xls
|
||||
jxls-examples_adjacentlists.xls
|
||||
jxls-examples_basictags.xls
|
||||
jxls-examples_chart.xls
|
||||
jxls-examples_colouring.xls
|
||||
jxls-examples_department.xls
|
||||
jxls-examples_dynamicolumns.xls
|
||||
jxls-examples_employees.xls
|
||||
jxls-examples_ex_temp.xls
|
||||
jxls-examples_grouping.xls
|
||||
jxls-examples_multiplelistrows.xls
|
||||
jxls-examples_report.xls
|
||||
jxls-examples_rowstyle.xls
|
||||
jxls-examples_stress1.xls
|
||||
jxls-examples_stress2.xls
|
||||
jxls-reader_departmentData.xls
|
||||
jxls-reader_employeesData.xls
|
||||
jxls-reader_emptyrowdata.xls
|
||||
jxls-reader_error1.xls
|
||||
jxls-reader_formulasData.xls
|
||||
jxls-reader_ids.xls
|
||||
jxls-src_adjacentlist_output.xls
|
||||
jxls-src_adjacentlists.xls
|
||||
jxls-src_basictags.xls
|
||||
jxls-src_basictags_output.xls
|
||||
jxls-src_chart.xls
|
||||
jxls-src_chart_output.xls
|
||||
jxls-src_colouring.xls
|
||||
jxls-src_colouring_output.xls
|
||||
jxls-src_department.xls
|
||||
jxls-src_department_output.xls
|
||||
jxls-src_departmentdata.xls
|
||||
jxls-src_dynamiccolumns_output.xls
|
||||
jxls-src_dynamiccolumns_template.xls
|
||||
jxls-src_employees.xls
|
||||
jxls-src_employees_output.xls
|
||||
jxls-src_grouping.xls
|
||||
jxls-src_grouping_output.xls
|
||||
jxls-src_hiddencolumn_output.xls
|
||||
jxls-src_multiplelistrows.xls
|
||||
jxls-src_multiplelistrows_output.xls
|
||||
jxls-src_report.xls
|
||||
jxls-src_report_output.xls
|
||||
jxls-src_rowstyle.xls
|
||||
jxls-src_rowstyle_output.xls
|
||||
large_strings.xls.pending
|
||||
libreoffice_calc_cell-value-validation.xls
|
||||
libreoffice_calc_chart-percent-stacked-with-line-chart.xls
|
||||
libreoffice_calc_chart-update-invisible-cells.xls
|
||||
libreoffice_calc_chart_complex-category-column-graph-repeating-values.xls
|
||||
libreoffice_calc_chart_complex-category-column-graph.xls
|
||||
libreoffice_calc_cjk-text_cell-justify-distributed-single.xls
|
||||
libreoffice_calc_cjk-text_cell-justify-distributed.xls
|
||||
libreoffice_calc_conditional-formatting.xls
|
||||
libreoffice_calc_csv-import_malformed-quotes.xls.pending
|
||||
libreoffice_calc_data-pilot_field-cell-format.xls
|
||||
libreoffice_calc_data-pilot_getpivotdata-cell-function.xls
|
||||
libreoffice_calc_data-pilot_named-range-as-data-source.xls
|
||||
libreoffice_calc_data-pilot_simple-range-as-data-source.xls
|
||||
libreoffice_calc_data-pilot_unlimited-data-fields.xls
|
||||
libreoffice_calc_dbf_numeric-field-with-zero.xls
|
||||
libreoffice_calc_drawing-object_connector-arrows.xls
|
||||
libreoffice_calc_drawing-object_rectangle-over-sized-rows-columns.xls
|
||||
libreoffice_calc_drawing-object_round-rectangle.xls
|
||||
libreoffice_calc_drawing-object_shapes.xls
|
||||
libreoffice_calc_equation-single.xls
|
||||
libreoffice_calc_external-ref_access-basic-range-func.xls
|
||||
libreoffice_calc_external-ref_access-basic-single-cell.xls
|
||||
libreoffice_calc_external-ref_access-basic-single-func.xls
|
||||
libreoffice_calc_external-ref_access-basic.xls
|
||||
libreoffice_calc_external-ref_circular-link-doc1.xls
|
||||
libreoffice_calc_external-ref_circular-link-doc2.xls
|
||||
libreoffice_calc_external-ref_extdata.xls
|
||||
libreoffice_calc_external-ref_range-name-extdata.xls
|
||||
libreoffice_calc_external-ref_range-name.xls
|
||||
libreoffice_calc_function_linest-excel.xls
|
||||
libreoffice_calc_function_logest-excel.xls
|
||||
libreoffice_calc_function_matrix_inline-array-single.xls
|
||||
libreoffice_calc_function_matrix_inline-arrays-softmaker.xls
|
||||
libreoffice_calc_function_matrix_inline-arrays.xls
|
||||
libreoffice_calc_function_n.xls
|
||||
libreoffice_calc_function_phonetic-richtext.xls
|
||||
libreoffice_calc_function_phonetic-single.xls
|
||||
libreoffice_calc_function_phonetic.xls
|
||||
libreoffice_calc_function_trend-growth-excel.xls
|
||||
libreoffice_calc_import-wrapped-text.xls
|
||||
libreoffice_calc_named-range_sheet-local.xls
|
||||
libreoffice_calc_outline_col-outline-nested.xls
|
||||
libreoffice_calc_outline_col-outline-single-left-button.xls
|
||||
libreoffice_calc_outline_col-outline-single.xls
|
||||
libreoffice_calc_outline_row-outline-nested.xls
|
||||
libreoffice_calc_outline_row-outline-single-top-button.xls
|
||||
libreoffice_calc_outline_row-outline-single.xls
|
||||
libreoffice_calc_print-layout_arial-10-1p.xls
|
||||
libreoffice_calc_print-layout_arial-10-2p.xls
|
||||
libreoffice_calc_print-layout_arial-11-1p.xls
|
||||
libreoffice_calc_print-layout_arial-11-2p.xls
|
||||
libreoffice_calc_print-layout_arial-12-1p.xls
|
||||
libreoffice_calc_print-layout_arial-8-1p.xls
|
||||
libreoffice_calc_print-layout_arial-9-1p.xls
|
||||
libreoffice_calc_string-number.xls
|
||||
libreoffice_calc_subtotals_two-on-one-sheet.xls
|
||||
libreoffice_calc_tab-color.xls
|
||||
libreoffice_calc_text-angled-with-border.xls
|
||||
libreoffice_calc_xls-import_300-worksheets.xls
|
||||
libreoffice_calc_xls-import_autofilter-range.xls
|
||||
libreoffice_calc_xls-import_cell-border-thickness.xls
|
||||
libreoffice_calc_xls-import_encryption_export-conditional-formatting.xls.pending
|
||||
libreoffice_calc_xls-import_paste-link_link.xls
|
||||
libreoffice_calc_xls-import_paste-link_src.xls
|
||||
libreoffice_calc_xls-import_pivot-cache-has-source.xls
|
||||
libreoffice_calc_xls-import_pivot-cache-no-source.xls
|
||||
libreoffice_calc_xls-import_pivot-dup-data-fields.xls
|
||||
libreoffice_calc_xls-import_pivot-layout-field-non-default.xls
|
||||
libreoffice_calc_xls-import_row-attributes_row-all-hidden.xls
|
||||
libreoffice_calc_xls-import_row-attributes_row-filtered.xls
|
||||
libreoffice_calc_xls-import_row-attributes_row-heights.xls
|
||||
libreoffice_calc_xls-import_row-attributes_row-tail-hidden-2.xls
|
||||
libreoffice_calc_xls-import_row-attributes_row-tail-hidden-last-row-visible.xls
|
||||
libreoffice_calc_xls-import_row-attributes_row-tail-hidden.xls
|
||||
libreoffice_calc_xls-import_row-attributes_row-top-bottom-hidden.xls
|
||||
libreoffice_calc_xls-import_shared-formula_1.xls
|
||||
libreoffice_calc_xls-import_shared-formulas-simple.xls
|
||||
merge_cells.xls
|
||||
named_ranges_2011.xls
|
||||
number_format.xls
|
||||
number_format_entities.xls
|
||||
number_format_russian.xls
|
||||
numfmt_1_russian.xls
|
||||
phonetic_text.xls
|
||||
phpexcel_bad_cfb_dir.xls
|
||||
pivot_table_named_range.xls
|
||||
pivot_table_test.xls
|
||||
pyExcelerator_P-0508-0000507647-3280-5298.xls
|
||||
pyExcelerator_chart1v8.xls
|
||||
pyExcelerator_excel2003.xls
|
||||
pyExcelerator_frmla.xls
|
||||
pyExcelerator_macro2v8.xls
|
||||
pyExcelerator_mini-mini.xls
|
||||
pyExcelerator_mini.xls
|
||||
pyExcelerator_oo14.xls
|
||||
rich_text_stress.xls
|
||||
roo_1900_base.xls
|
||||
roo_1904_base.xls
|
||||
roo_Bibelbund.xls
|
||||
roo_bad_excel_date.xls
|
||||
roo_bbu.xls
|
||||
roo_boolean.xls
|
||||
roo_borders.xls
|
||||
roo_bug-row-column-fixnum-float.xls
|
||||
roo_comments.xls
|
||||
roo_datetime.xls
|
||||
roo_datetime_floatconv.xls
|
||||
roo_emptysheets.xls
|
||||
roo_false_encoding.xls
|
||||
roo_formula.xls
|
||||
roo_formula_parse_error.xls
|
||||
roo_link.xls
|
||||
roo_matrix.xls
|
||||
roo_named_cells.xls
|
||||
roo_numbers1.xls
|
||||
roo_only_one_sheet.xls
|
||||
roo_paragraph.xls
|
||||
roo_prova.xls
|
||||
roo_simple_spreadsheet.xls
|
||||
roo_simple_spreadsheet_from_italo.xls
|
||||
roo_style.xls
|
||||
roo_time-test.xls
|
||||
roo_type_excelx.xls.pending
|
||||
roo_type_openoffice.xls.pending
|
||||
roo_whitespace.xls
|
||||
smart_tags_2007.xls
|
||||
sushi.xls
|
||||
text_and_numbers.xls
|
||||
write.xls
|
||||
xlrd_Formate.xls
|
||||
xlrd_formula_test_names.xls
|
||||
xlrd_formula_test_sjmachin.xls
|
||||
xlrd_issue20.xls
|
||||
xlrd_picture_in_cell.xls
|
||||
xlrd_profiles.xls
|
||||
xlrd_ragged.xls
|
||||
xlrd_xf_class.xls
|
||||
xlsx-stream-d-date-cell.xls
|
||||
AutoFilter.xml
|
||||
BlankSheetTypes.xml
|
||||
ErrorTypes.xml
|
||||
LONumbers-2010.xls.xml
|
||||
LONumbers-2010.xlsx.xml
|
||||
LONumbers-2011.xls.xml
|
||||
LONumbers-2011.xlsx.xml
|
||||
LONumbers.xls.xml
|
||||
NumberFormatCondition.xml
|
||||
RkNumber.xls.xml
|
||||
RkNumber.xlsb.xml
|
||||
RkNumber.xlsx.xml
|
||||
calendar_stress_test.xml.pending
|
||||
cell_style_simple.xml
|
||||
comments_stress_test.xls.xml
|
||||
comments_stress_test.xlsb.xml
|
||||
comments_stress_test.xlsx.xml
|
||||
custom_properties.xls.xml
|
||||
custom_properties.xlsb.xml
|
||||
custom_properties.xlsx.xml
|
||||
defined_names_simple.xml
|
||||
formula_stress_test.xls.xml
|
||||
formula_stress_test.xlsb.xml
|
||||
formula_stress_test.xlsx.xml
|
||||
formulae_test_simple.xml
|
||||
hyperlink_stress_test_2011.xml
|
||||
interview.xlsx.xml
|
||||
issue.xlsx.xml
|
||||
large_strings.xls.xml
|
||||
large_strings.xlsb.xml
|
||||
large_strings.xlsx.xml
|
||||
merge_cells.xls.xml
|
||||
merge_cells.xlsb.xml
|
||||
merge_cells.xlsx.xml
|
||||
mixed_sheets.xlsx.xml
|
||||
named_ranges_2011.xls.xml
|
||||
named_ranges_2011.xlsb.xml
|
||||
named_ranges_2011.xlsx.xml
|
||||
number_format.xls.xml
|
||||
number_format.xlsb.xml
|
||||
number_format.xlsm.xml
|
||||
number_format_entities.xml
|
||||
number_format_russian.xml
|
||||
numfmt_1_russian.xml
|
||||
oo34xml_cell_pattern.xml
|
||||
oo34xml_cellstyle.xml
|
||||
oo34xml_conditionalformat.xml
|
||||
oo34xml_dataformat.xml
|
||||
oo34xml_dataformat2.xml
|
||||
oo34xml_datarange.xml
|
||||
oo34xml_font.xml
|
||||
oo34xml_formula.xml
|
||||
oo34xml_headerfooter.xml
|
||||
oo34xml_merge.xml
|
||||
oo34xml_pagebreak.xml
|
||||
oo34xml_pagesheet.xml
|
||||
oo34xml_rowcolumn.xml
|
||||
oo34xml_solvsamp.xml
|
||||
phonetic_text.xml
|
||||
pivot_table_named_range.xml
|
||||
protect_stress_test_xml.xml
|
||||
rich_text_stress.xls.xml
|
||||
rich_text_stress.xlsb.xml
|
||||
rich_text_stress.xlsx.xml
|
||||
roo_Bibelbund.xml
|
||||
roo_bbu.xml
|
||||
roo_boolean.xml
|
||||
roo_borders.xml
|
||||
roo_bug-row-column-fixnum-float.xml
|
||||
roo_datetime.xml
|
||||
roo_datetime_floatconv.xml
|
||||
roo_emptysheets.xml
|
||||
roo_excel2003.xml
|
||||
roo_false_encoding.xml
|
||||
roo_formula.xml
|
||||
roo_formula_parse_error.xml
|
||||
roo_numbers1.xml
|
||||
roo_only_one_sheet.xml
|
||||
roo_paragraph.xml
|
||||
roo_simple_spreadsheet.xml
|
||||
roo_simple_spreadsheet_from_italo.xml
|
||||
roo_style.xml
|
||||
roo_time-test.xml
|
||||
roo_whitespace.xml
|
||||
smart_tags_2007.xml
|
||||
sushi.xml
|
||||
text_and_numbers.xml
|
||||
xlsx-stream-d-date-cell.xls.xml
|
||||
xlsx-stream-d-date-cell.xlsb.xml
|
||||
xlsx-stream-d-date-cell.xlsx.xml
|
||||
2011/apachepoi_53568.xlsx.xls
|
||||
2011/apachepoi_WithChartSheet.xlsx.xml
|
||||
2011/apachepoi_picture.xlsx.xml
|
||||
2011/apachepoi_styles.xlsx.xml
|
||||
2011/openpyxl_r_conditional-formatting.xlsx.xls
|
||||
2011/roo_file_item_error.xlsx.xml
|
||||
|
6393
xlsx.js
6393
xlsx.js
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
||||
/* xlsx.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
|
||||
/* xlsx.js (C) 2013-2015 SheetJS -- http://sheetjs.com */
|
||||
/* uncomment the next line for encoding support */
|
||||
//importScripts('dist/cpexcel.js');
|
||||
importScripts('jszip.js');
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* xlsx.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
|
||||
/* xlsx.js (C) 2013-2015 SheetJS -- http://sheetjs.com */
|
||||
/* uncomment the next line for encoding support */
|
||||
//importScripts('dist/cpexcel.js');
|
||||
importScripts('jszip.js');
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* xlsx.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
|
||||
/* xlsx.js (C) 2013-2015 SheetJS -- http://sheetjs.com */
|
||||
/* uncomment the next line for encoding support */
|
||||
//importScripts('dist/cpexcel.js');
|
||||
importScripts('jszip.js');
|
||||
|
Loading…
Reference in New Issue
Block a user