Skip to content

Commit

Permalink
version bump 0.8.3: BIFF2 read/write
Browse files Browse the repository at this point in the history
- basic support for parsing BIFF2-4
- basic support for writing BIFF2
- cleaned up some bad substr uses for IE6 compatibility
- added flow type annotations for xlsx.flow.js
- added numerous null guards (fixes SheetJS#255 h/t @martinheidegger)
- README cleanup (fixes SheetJS#539 h/t @oliversalzburg)
- pin jszip to local version (closes SheetJS#408 h/t @limouri)

bower issues:

|  id  | author            | comment                                   |
|-----:|:------------------|:------------------------------------------|
| SheetJS#254 | @kkirsche         | fixes SheetJS#254 by removing version from json  |
| SheetJS#165 | @vincentcialdella | fixes SheetJS#165 by changing default script     |
| SheetJS#180 | @owencraig        | fixes SheetJS#180 by using xlsx.core.min.js      |

format issues:

|  id  | author            | comment                                   |
|-----:|:------------------|:------------------------------------------|
| SheetJS#271 | @morstaine        | fixes SheetJS#271 by reworking related parse fns |
| SheetJS#504 | @JanSchuermannPH  | fixes SheetJS#504 detect FullPaths h/t @Mithgol  |
| SheetJS#508 | @basma-emad       | fixes SheetJS#508 offending file used `x:` NS    |
  • Loading branch information
SheetJSDev committed Feb 10, 2017
1 parent 06670ae commit ab2eceb
Show file tree
Hide file tree
Showing 79 changed files with 12,662 additions and 10,963 deletions.
6 changes: 5 additions & 1 deletion .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,25 @@
.*/xlsxworker2.js
.*/jszip.js
.*/tests/.*
.*/demos/.*

.*/xlsx.flow.js
#.*/xlsx.flow.js
[include]
xlsxworker.flow.js
xlsxworker1.flow.js
xlsxworker2.flow.js
xlsx.flow.js
ods.flow.js
.*/bin/.*.njs
.*/demo/browser.flow.js

[libs]
bits/09_types.js
misc/flow.js
misc/flowdeps.js

[options]
module.file_ext=.js
module.file_ext=.njs
module.ignore_non_literal_requires=true
suppress_comment= \\(.\\|\n\\)*\\$FlowIgnore
2 changes: 2 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ tmp
*.prn
*.slk
*.socialcalc
*.XLS
*.xls
*.xlsb
*.xlsm
Expand All @@ -32,6 +33,7 @@ test.js
.gitmodules
.travis.yml
.flowconfig
*.flow.js
bits/
odsbits/
tests/
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ node_js:
- "0.8"
before_install:
- "npm install -g npm@next"
- "npm install -g mocha voc"
- "npm install -g mocha@2.x voc"
- "npm install blanket"
- "npm install xlsjs"
- "npm install coveralls mocha-lcov-reporter"
Expand Down
18 changes: 8 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ FLOWTARGET=$(LIB).flow.js
FLOWAUX=$(patsubst %.js,%.flow.js,$(AUXTARGETS))
AUXSCPTS=xlsxworker1.js xlsxworker2.js xlsxworker.js
FLOWTGTS=$(TARGET) $(AUXTARGETS) $(AUXSCPTS)
UGLIFYOPTS=--support-ie8

## Main Targets

Expand All @@ -34,7 +35,7 @@ bits/18_cfb.js: node_modules/cfb/dist/xlscfb.js

.PHONY: clean
clean: ## Remove targets and build artifacts
rm -f $(TARGET)
rm -f $(TARGET) $(FLOWTARGET)

.PHONY: clean-data
clean-data:
Expand All @@ -52,24 +53,21 @@ init: ## Initial setup for development
dist: dist-deps $(TARGET) bower.json ## Prepare JS files for distribution
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)"
uglifyjs $(UGLIFYOPTS) $(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)"
uglifyjs $(UGLIFYOPTS) $(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)"
uglifyjs $(UGLIFYOPTS) $(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: dist-deps
dist-deps: ods.js ## Copy dependencies for distribution
cp node_modules/codepage/dist/cpexcel.full.js dist/cpexcel.js
cp jszip.js dist/jszip.js
cp ods.js dist/ods.js
uglifyjs ods.js -o dist/ods.min.js --source-map dist/ods.min.map --preamble "$$(head -n 1 bits/00_header.js)"
uglifyjs $(UGLIFYOPTS) ods.js -o dist/ods.min.js --source-map dist/ods.min.map --preamble "$$(head -n 1 bits/00_header.js)"
misc/strip_sourcemap.sh dist/ods.min.js

bower.json: misc/_bower.json package.json
cat $< | sed 's/_VERSION_/'`grep version package.json | awk '{gsub(/[^0-9a-z\.-]/,"",$$2); print $$2}'`'/' > $@

.PHONY: aux
aux: $(AUXTARGETS)

Expand Down Expand Up @@ -108,7 +106,7 @@ lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks
flow: lint ## Run flow checker
@flow check --all --show-all-errors

.PHONY: cov cov-spin
.PHONY: cov
cov: misc/coverage.html ## Run coverage test

#* To run coverage tests for one format, make cov_<fmt>
Expand All @@ -120,7 +118,7 @@ $(COVFMT): cov_%:
misc/coverage.html: $(TARGET) test.js
mocha --require blanket -R html-cov -t 20000 > $@

.PHONY: coveralls coveralls-spin
.PHONY: coveralls
coveralls: ## Coverage Test + Send to coveralls.io
mocha --require blanket --reporter mocha-lcov-reporter -t 20000 | node ./node_modules/coveralls/bin/coveralls.js

Expand Down
54 changes: 34 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@ implementation from official specifications and related documents.
Supported read formats:

- Excel 2007+ XML Formats (XLSX/XLSM)
- Excel 2007+ Binary Format (XLSB)
- Excel 2007+ Binary Format (XLSB BIFF12)
- Excel 2003-2004 XML Format (XML "SpreadsheetML")
- Excel 97-2004 (XLS BIFF8)
- Excel 5.0/95 (XLS BIFF5)
- Excel 2.0/3.0/4.0 (XLS BIFF2/BIFF3/BIFF4)
- OpenDocument Spreadsheet (ODS)

Supported write formats:

- Excel 2007+ XML Formats (XLSX/XLSM)
- Excel 2007+ Binary Format (XLSB) nodejs only
- Excel 2.0 (XLS BIFF2, compatible with *every version* of Excel)
- Excel 2007+ XML Formats (XLSX/XLSM, compatible with Excel 2007+)
- Excel 2007+ Binary Format (XLSB, compatible with Excel 2007+)
- CSV (and general DSV)
- JSON and JS objects (various styles)
- OpenDocument Spreadsheet (ODS)
Expand All @@ -26,6 +28,7 @@ Source: <http://git.io/xlsx>

Paid support available through the [reinforcements program](http://sheetjs.com/reinforcements)


## Installation

With [npm](https://www.npmjs.org/package/xlsx):
Expand Down Expand Up @@ -198,11 +201,6 @@ function handleFile(e) {
input_dom_element.addEventListener('change', handleFile, false);
```

The readAsArrayBuffer form requires some preprocessing:

```js
```

## Working with the Workbook

The full object format is described later in this README.
Expand Down Expand Up @@ -277,10 +275,11 @@ XLSX.writeFile(workbook, 'out.xlsx');
/* at this point, out.xlsx is a file that you can distribute */
```

- write to binary string (using FileSaver.js):
- browser generate binary blob and "download" to client
(using [FileSaver.js](https://github.com/eligrey/FileSaver.js/) for download):

```js
/* bookType can be 'xlsx' or 'xlsm' or 'xlsb' */
/* bookType can be 'xlsx' or 'xlsm' or 'xlsb' or 'ods' */
var wopts = { bookType:'xlsx', bookSST:false, type:'binary' };

var wbout = XLSX.write(workbook,wopts);
Expand Down Expand Up @@ -508,28 +507,43 @@ The defaults are enumerated in bits/84\_defaults.js

The exported `write` and `writeFile` functions accept an options argument:

| Option Name | Default | Description |
| :---------- | ------: | :--------------------------------------------------- |
| cellDates | `false` | Store dates as type `d` (default is `n`) |
| bookSST | `false` | Generate Shared String Table ** |
| bookType | 'xlsx' | Type of Workbook ("xlsx" or "xlsm" or "xlsb") |
| compression | `false` | Use file compression for formats with ZIP containers |
| Option Name | Default | Description |
| :---------- | -------: | :-------------------------------------------------- |
| cellDates | `false` | Store dates as type `d` (default is `n`) |
| bookSST | `false` | Generate Shared String Table ** |
| bookType | `"xlsx"` | Type of Workbook (see below for supported formats) |
| sheet | `""` | Name of Worksheet for single-sheet formats ** |
| compression | `false` | Use ZIP compression for ZIP-based formats ** |

- `bookSST` is slower and more memory intensive, but has better compatibility
with older versions of iOS Numbers
- `bookType = 'xlsb'` is stubbed and far from complete
- The raw data is the only thing guaranteed to be saved. Formulae, formatting,
and other niceties may not be serialized (pending CSF standardization)
- `cellDates` only applies to XLSX output and is not guaranteed to work with
third-party readers. Excel itself does not usually write cells with type `d`
so non-Excel tools may ignore the data or blow up in the presence of dates.

Supported output formats (`bookType`):

| bookType | file ext | container | sheets | Description |
| :------- | -------: | :-------: | :----- |:---------------------------- |
| `xlsx` | `.xlsx` | ZIP | multi | Excel 2007+ XML Format |
| `xlsm` | `.xlsm` | ZIP | multi | Excel 2007+ Macro XML Format |
| `xlsb` | `.xlsb` | ZIP | multi | Excel 2007+ Binary Format |
| `ods` | `.ods` | ZIP | multi | OpenDocument Spreadsheet |
| `biff2` | `.xls` | none | single | Excel 2.0 Worksheet format |

- `compression` only applies to formats with ZIP containers.
- Formats that only support a single sheet require a `sheet` option specifying
the worksheet. If the string is empty, the first worksheet is used.

## Tested Environments

- NodeJS 0.8, 0.9, 0.10, 0.11, 0.12, 4.x, 5.x, 6.x, 7.x
- IE 6/7/8/9/10/11 using Base64 mode (IE10/11 using HTML5 mode)
- FF 18 using Base64 or HTML5 mode
- Chrome 24 using Base64 or HTML5 mode
- IE 6/7/8/9/10/11 (IE6-9 browsers require shims for interacting with client)
- Chrome 24+
- Safari 6+
- FF 18+

Tests utilize the mocha testing framework. Travis-CI and Sauce Labs links:

Expand Down
23 changes: 18 additions & 5 deletions bin/xlsx.njs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ program
.option('-B, --xlsb', 'emit XLSB to <sheetname> or <file>.xlsb')
.option('-M, --xlsm', 'emit XLSM to <sheetname> or <file>.xlsm')
.option('-X, --xlsx', 'emit XLSX to <sheetname> or <file>.xlsx')
.option('-Y, --ods', 'emit ODS to <sheetname> or <file>.ods')
.option('-2, --biff2','emit XLS to <sheetname> or <file>.xls (BIFF2)')
.option('-S, --formulae', 'print formulae')
.option('-j, --json', 'emit formatted JSON (all fields text)')
.option('-J, --raw-js', 'emit raw JS object (raw numbers)')
.option('-F, --field-sep <sep>', 'CSV field separator', ",")
.option('-R, --row-sep <sep>', 'CSV row separator', "\n")
.option('-n, --sheet-rows <num>', 'Number of rows to process (0=all rows)')
.option('--sst', 'generate sst')
.option('--sst', 'generate shared string table for XLS* formats')
.option('--compress', 'use compression when writing XLSX/M/B and ODS')
.option('--perf', 'do not generate output')
.option('--all', 'parse everything; XLS[XMB] write as much as possible')
.option('--dev', 'development mode')
Expand Down Expand Up @@ -104,11 +107,14 @@ if(program.listSheets) {
process.exit(0);
}

var wopts = {WTF:opts.WTF, bookSST:program.sst};
var wopts = ({WTF:opts.WTF, bookSST:program.sst}/*:any*/);
if(program.compress) wopts.compression = true;

if(program.xlsx) { X.writeFile(wb, sheetname || (filename + ".xlsx"), wopts); process.exit(0); }
if(program.xlsm) { X.writeFile(wb, sheetname || (filename + ".xlsm"), wopts); process.exit(0); }
if(program.xlsb) { X.writeFile(wb, sheetname || (filename + ".xlsb"), wopts); process.exit(0); }
/* full workbook formats */
['xlsx', 'xlsm', 'xlsb', 'ods'].forEach(function(m) { if(program[m]) {
X.writeFile(wb, sheetname || ((filename || "") + "." + m), wopts);
process.exit(0);
} });

var target_sheet = sheetname || '';
if(target_sheet === '') target_sheet = wb.SheetNames[0];
Expand All @@ -124,6 +130,13 @@ try {

if(program.perf) process.exit(0);

/* single worksheet XLS formats */
['biff2'].forEach(function(m) { if(program[m]) {
wopts.bookType = m;
X.writeFile(wb, sheetname || ((filename || "") + ".xls"), wopts);
process.exit(0);
} });

var oo = "";
if(!program.quiet) console.error(target_sheet);
if(program.formulae) oo = X.utils.get_formulae(ws).join("\n");
Expand Down
2 changes: 1 addition & 1 deletion bits/01_version.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
XLSX.version = '0.8.2';
XLSX.version = '0.8.3';
4 changes: 2 additions & 2 deletions bits/05_buf.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
var has_buf = (typeof Buffer !== 'undefined');

function new_raw_buf(len) {
function new_raw_buf(len/*:number*/) {
/* jshint -W056 */
return new (has_buf ? Buffer : Array)(len);
/* jshint +W056 */
}

function s2a(s) {
function s2a(s/*:string*/) {
if(has_buf) return new Buffer(s, "binary");
return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; });
}
Expand Down
9 changes: 9 additions & 0 deletions bits/09_types.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
/*::
declare type Block = any;
declare type BufArray = {
newblk(sz:number):Block;
next(sz:number):Block;
end():any;
push(buf:Block):void;
};
type RecordHopperCB = {(d:any, R:any, RT:number):?boolean;};
type EvertType = {[string]:string};
type EvertNumType = {[string]:number};
type EvertArrType = {[string]:Array<string>};
type StringConv = {(string):string};
*/
4 changes: 2 additions & 2 deletions bits/11_ssfutils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* map from xlml named formats to SSF TODO: localize */
var XLMLFormatMap = {
var XLMLFormatMap/*{[string]:string}*/ = ({
"General Number": "General",
"General Date": SSF._table[22],
"Long Date": "dddd, mmmm dd, yyyy",
Expand All @@ -16,5 +16,5 @@ var XLMLFormatMap = {
"Yes/No": '"Yes";"Yes";"No";@',
"True/False": '"True";"True";"False";@',
"On/Off": '"Yes";"Yes";"No";@'
};
}/*:any*/);

20 changes: 10 additions & 10 deletions bits/20_jsutils.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
function isval(x/*:?any*/)/*:boolean*/ { return x !== undefined && x !== null; }

function keys(o) { return Object.keys(o); }
function keys(o/*:any*/)/*:Array<any>*/ { return Object.keys(o); }

function evert_key(obj, key) {
var o = [], K = keys(obj);
function evert_key(obj/*:any*/, key/*:string*/)/*:EvertType*/ {
var o = ([]/*:any*/), K = keys(obj);
for(var i = 0; i !== K.length; ++i) o[obj[K[i]][key]] = K[i];
return o;
}

function evert(obj) {
var o = [], K = keys(obj);
function evert(obj/*:any*/)/*:EvertType*/ {
var o = ([]/*:any*/), K = keys(obj);
for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = K[i];
return o;
}

function evert_num(obj) {
var o = [], K = keys(obj);
function evert_num(obj/*:any*/)/*:EvertNumType*/ {
var o = ([]/*:any*/), K = keys(obj);
for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = parseInt(K[i],10);
return o;
}

function evert_arr(obj) {
var o = [], K = keys(obj);
function evert_arr(obj/*:any*/)/*:EvertArrType*/ {
var o/*:EvertArrType*/ = ([]/*:any*/), K = keys(obj);
for(var i = 0; i !== K.length; ++i) {
if(o[obj[K[i]]] == null) o[obj[K[i]]] = [];
o[obj[K[i]]].push(K[i]);
Expand All @@ -30,7 +30,7 @@ function evert_arr(obj) {
}

/* TODO: date1904 logic */
function datenum(v, date1904) {
function datenum(v/*:number*/, date1904/*:?boolean*/)/*:number*/ {
if(date1904) v+=1462;
var epoch = Date.parse(v);
return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
Expand Down
Loading

0 comments on commit ab2eceb

Please sign in to comment.