Skip to content

Commit

Permalink
version bump 0.6.6: updates
Browse files Browse the repository at this point in the history
- updated SSF to 0.5.6
- updated CSV output (h/t @vratiu)
- some cell types now include .w formatted text
  • Loading branch information
SheetJSDev committed Feb 11, 2014
1 parent d453e12 commit 6a8df59
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 29 deletions.
61 changes: 61 additions & 0 deletions CONTRIBUTING.md
@@ -0,0 +1,61 @@
# Contributing

The SheetJS Libraries should be free and clear to use in your projects. In
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.


# Required Reading

These are pretty short reads and emphasize the importance of proper licensing:

- https://github.com/kennethreitz/tablib/issues/114 (discussion of other tools)

- 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 :)

# Pre-Contribution Checklist

Before thinking about contributing, make sure that:

- You are not, nor have ever been, an employee of Microsoft Corporation.

- You have not signed any NDAs or Shared Source Agreements with Microsoft
Corporation or a subsidiary

- You have not consulted any existing relevant codebase (if you have, please
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
<sheetjs@gmail.com> and it will be prioritized.


# Intra-Contribution

Keep these in mind as you work:

- Your contributions are your original work. Take note of any resources you
consult in the process (and be extra careful not to use unlicensed code on
the internet.

- 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.
40 changes: 26 additions & 14 deletions README.md
Expand Up @@ -14,41 +14,48 @@ In the browser:

## Usage

The node version installs a binary `xls2csv` which can read XLS files and output the contents in various formats. The source is available at `xls2csv.njs` in the bin directory.

See <http://oss.sheetjs.com/js-xls/> for a browser example.

See `bin/xls2csv` for a node example.

Simple usage (gets the value of cell A1 of sheet Sheet1):

var XLS = require('xlsjs');
var xls = XLS.readFile('test.xls');
var Sheet1A1 = xls.Sheets['Sheet1']['A1'].v;

The node version installs a binary `xls2csv` which can read XLS files and output the contents in various formats. The source is available at `xls2csv.njs` in the bin directory.

See <http://oss.sheetjs.com/js-xls/> for a browser example.

Some helper functions in `XLS.utils` generate different views of the sheets:

- `XLS.utils.sheet_to_csv` generates CSV
- `XLS.utils.sheet_to_row_object_array` interprets sheets as tables with a header column and generates an array of objects
- `XLS.utils.get_formulae` generates a list of formulae

## Notes
For more details:

`CFB` refers to the Microsoft Compound File Binary Format, a container format for XLS as well as DOC and other pre-OOXML data formats.
- `bin/xls2csv.njs` is a tool for node
- `index.html` is the live demo
- `bits/80_xls.js` contains the logic for generating CSV and JSON from sheets

The mechanism is split into a CFB parser (which scans through the file and produces concrete data chunks) and a Workbook parser (which does excel-specific parsing).
## Cell Object Description

`.SheetNames` is an ordered list of the sheets in the workbook

`.Sheets[sheetname]` returns a data structure representing the sheet

`.Sheets[sheetname][address].v` returns the value of the specified cell and `.Sheets[sheetname][address].t` returns the type of the cell (constrained to the enumeration `ST_CellType` as documented in page 4215 of ISO/IEC 29500-1:2012(E) )
`.Sheets[sheetname][address]` returns the specified cell:

For more details:
- `.v` : the raw value of the cell
- `.w` : the formatted text of the cell (if applicable)
- `.t` : the type of the cell (constrained to the enumeration `ST_CellType` as documented in page 4215 of ISO/IEC 29500-1:2012(E) )
- `.f` : the formula of the cell (if applicable)

- `bin/xls2csv.njs` is a tool for node
- `index.html` is the live demo
- `bits/80_xls.js` contains the logic for generating CSV and JSON from sheets
For dates, `.v` holds the raw date code from the sheet and `.w` holds the text

## Other Notes

`CFB` refers to the Microsoft Compound File Binary Format, a container format for XLS as well as DOC and other pre-OOXML data formats.

The mechanism is split into a CFB parser (which scans through the file and produces concrete data chunks) and a Workbook parser (which does excel-specific parsing).

## Test Files

Expand All @@ -62,6 +69,10 @@ Tests utilize the mocha testing framework. Travis-CI and Sauce Labs links:
- <https://travis-ci.org/SheetJS/SheetJS.github.io> for XLS* modules
- <https://saucelabs.com/u/sheetjs> for XLS* modules using Sauce Labs

## Contributing

Due to the precarious nature of the Open Specifications Promise, it is very important to ensure code is cleanroom. Consult CONTRIBUTING.md

## XLSX/XLSM/XLSB Support

XLSX/XLSM/XLSB support is available in [js-xlsx](https://github.com/SheetJS/js-xlsx).
Expand Down Expand Up @@ -98,3 +109,4 @@ ISO/IEC 29500:2012(E) "Information technology — Document description and proce
[![Coverage Status](https://coveralls.io/repos/SheetJS/js-xls/badge.png?branch=master)](https://coveralls.io/r/SheetJS/js-xls?branch=master)

[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/4ee4284bf2c638cff8ed705c4438a686 "githalytics.com")](http://githalytics.com/SheetJS/js-xls)

2 changes: 1 addition & 1 deletion bits/01_version.js
@@ -1 +1 @@
XLS.version = '0.6.5';
XLS.version = '0.6.6';
17 changes: 12 additions & 5 deletions bits/10_ssf.js
Expand Up @@ -5,7 +5,7 @@ var _strrev = function(x) { return String(x).split("").reverse().join("");};
function fill(c,l) { return new Array(l+1).join(c); }
function pad(v,d,c){var t=String(v);return t.length>=d?t:(fill(c||0,d-t.length)+t);}
function rpad(v,d,c){var t=String(v);return t.length>=d?t:(t+fill(c||0,d-t.length));}
SSF.version = '0.5.5';
SSF.version = '0.5.6';
/* Options */
var opts_fmt = {};
function fixopts(o){for(var y in opts_fmt) if(o[y]===undefined) o[y]=opts_fmt[y];}
Expand Down Expand Up @@ -212,13 +212,19 @@ var write_num = function(type, fmt, val) {
if(fmt.indexOf("E") > -1) {
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
if(fmt == '##0.0E+0') {
var period = fmt.length - 5;
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
var ee = (Number(val.toExponential(0).substr(2+(val<0))))%period;
if(ee < 0) ee += period;
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
if(!o.match(/[Ee]/)) {
var fakee = (Number(val.toExponential(0).substr(2+(val<0))));
if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
else throw "missing E |" + o;
else o += "E+" + (fakee - ee);
while(o.substr(0,2) === "0.") {
o = o[0] + o.substr(2,period) + "." + o.substr(2+period);
o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0.");
}
o = o.replace(/\+-/,"-");
}
o = o.replace(/^([+-]?)([0-9]*)\.([0-9]*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
} else o = val.toExponential(idx);
Expand All @@ -233,6 +239,7 @@ var write_num = function(type, fmt, val) {
var myn = (rnd - base*den), myd = den;
return sign + (base?base:"") + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad(myn,r[1].length," ") + r[2] + "/" + r[3] + pad(myd,r[4].length));
}
if(fmt.match(/^#+0+$/)) fmt = fmt.replace(/#/g,"");
if(fmt.match(/^00+$/)) return (val<0?"-":"")+pad(Math.round(aval),fmt.length);
if(fmt.match(/^[#?]+$/)) return String(Math.round(val)).replace(/^0$/,"");
if((r = fmt.match(/^#*0+\.(0+)/))) {
Expand Down Expand Up @@ -343,7 +350,7 @@ function eval_fmt(fmt, v, opts, flen) {
out.push({t:'D', v:o}); break;
case ' ': out.push({t:c,v:c}); ++i; break;
default:
if(",$-+/():!^&'~{}<>=".indexOf(c) === -1)
if(",$-+/():!^&'~{}<>=".indexOf(c) === -1)
throw 'unrecognized character ' + fmt[i] + ' in ' + fmt;
out.push({t:'t', v:c}); ++i; break;
}
Expand All @@ -367,7 +374,7 @@ function eval_fmt(fmt, v, opts, flen) {
out[i].t = 't'; break;
case 'n': case '(': case '?':
var jj = i+1;
while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (" t".indexOf(out[jj].t) > -1 && "?t".indexOf((out[jj+1]||{}).t)>-1 && (out[jj+1].t == '?' || out[jj+1].v == '/')) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || out[jj].v == '$' || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) {
while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (" t".indexOf(out[jj].t) > -1 && "?t".indexOf((out[jj+1]||{}).t)>-1 && (out[jj+1].t == '?' || out[jj+1].v == '/')) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || '$€'.indexOf(out[jj].v) > -1 || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) {
out[i].v += out[jj].v;
delete out[jj]; ++jj;
}
Expand Down
9 changes: 9 additions & 0 deletions bits/80_xls.js
Expand Up @@ -263,14 +263,23 @@ function parse_workbook(blob) {
} break;
case 'Number': {
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:'n'};
if(temp_val.XF) try {
temp_val.w=SSF.format(temp_val.XF.ifmt||0, temp_val.v);
} catch(e) { }
addline({c:val.c, r:val.r}, temp_val);
} break;
case 'BoolErr': {
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t};
if(temp_val.XF) try {
temp_val.w=SSF.format(temp_val.XF.ifmt||0, temp_val.v);
} catch(e) { }
addline({c:val.c, r:val.r}, temp_val);
} break;
case 'RK': {
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'};
if(temp_val.XF) try {
temp_val.w=SSF.format(temp_val.XF.ifmt||0, temp_val.v);
} catch(e) { }
addline({c:val.c, r:val.r}, temp_val);
} break;
case 'MulRk': {
Expand Down
4 changes: 2 additions & 2 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "xlsjs",
"version": "0.6.5",
"version": "0.6.6",
"author": "sheetjs",
"description": "(one day) a full-featured XLS parser and writer. For now, primitive parser",
"keywords": [ "xls", "office", "excel", "spreadsheet" ],
Expand All @@ -10,7 +10,7 @@
"main": "./xls",
"dependencies": {
"cfb":">=0.8.0",
"ssf":"",
"ssf":"~0.5.6",
"codepage":"",
"commander":""
},
Expand Down
2 changes: 1 addition & 1 deletion test_files
Submodule test_files updated 256 files
28 changes: 22 additions & 6 deletions xls.js
Expand Up @@ -3,7 +3,7 @@
/*jshint eqnull:true, funcscope:true */
var XLS = {};
(function(XLS){
XLS.version = '0.6.5';
XLS.version = '0.6.6';
if(typeof module !== "undefined" && typeof require !== 'undefined') {
if(typeof cptable === 'undefined') var cptable = require('codepage');
var current_codepage = 1252, current_cptable = cptable[1252];
Expand Down Expand Up @@ -216,7 +216,7 @@ var _strrev = function(x) { return String(x).split("").reverse().join("");};
function fill(c,l) { return new Array(l+1).join(c); }
function pad(v,d,c){var t=String(v);return t.length>=d?t:(fill(c||0,d-t.length)+t);}
function rpad(v,d,c){var t=String(v);return t.length>=d?t:(t+fill(c||0,d-t.length));}
SSF.version = '0.5.5';
SSF.version = '0.5.6';
/* Options */
var opts_fmt = {};
function fixopts(o){for(var y in opts_fmt) if(o[y]===undefined) o[y]=opts_fmt[y];}
Expand Down Expand Up @@ -423,13 +423,19 @@ var write_num = function(type, fmt, val) {
if(fmt.indexOf("E") > -1) {
var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
if(fmt == '##0.0E+0') {
var period = fmt.length - 5;
var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
var ee = (Number(val.toExponential(0).substr(2+(val<0))))%period;
if(ee < 0) ee += period;
o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
if(!o.match(/[Ee]/)) {
var fakee = (Number(val.toExponential(0).substr(2+(val<0))));
if(o.indexOf(".") === -1) o = o[0] + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
else throw "missing E |" + o;
else o += "E+" + (fakee - ee);
while(o.substr(0,2) === "0.") {
o = o[0] + o.substr(2,period) + "." + o.substr(2+period);
o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0.");
}
o = o.replace(/\+-/,"-");
}
o = o.replace(/^([+-]?)([0-9]*)\.([0-9]*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
} else o = val.toExponential(idx);
Expand All @@ -444,6 +450,7 @@ var write_num = function(type, fmt, val) {
var myn = (rnd - base*den), myd = den;
return sign + (base?base:"") + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad(myn,r[1].length," ") + r[2] + "/" + r[3] + pad(myd,r[4].length));
}
if(fmt.match(/^#+0+$/)) fmt = fmt.replace(/#/g,"");
if(fmt.match(/^00+$/)) return (val<0?"-":"")+pad(Math.round(aval),fmt.length);
if(fmt.match(/^[#?]+$/)) return String(Math.round(val)).replace(/^0$/,"");
if((r = fmt.match(/^#*0+\.(0+)/))) {
Expand Down Expand Up @@ -554,7 +561,7 @@ function eval_fmt(fmt, v, opts, flen) {
out.push({t:'D', v:o}); break;
case ' ': out.push({t:c,v:c}); ++i; break;
default:
if(",$-+/():!^&'~{}<>=".indexOf(c) === -1)
if(",$-+/():!^&'~{}<>=".indexOf(c) === -1)
throw 'unrecognized character ' + fmt[i] + ' in ' + fmt;
out.push({t:'t', v:c}); ++i; break;
}
Expand All @@ -578,7 +585,7 @@ function eval_fmt(fmt, v, opts, flen) {
out[i].t = 't'; break;
case 'n': case '(': case '?':
var jj = i+1;
while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (" t".indexOf(out[jj].t) > -1 && "?t".indexOf((out[jj+1]||{}).t)>-1 && (out[jj+1].t == '?' || out[jj+1].v == '/')) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || out[jj].v == '$' || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) {
while(out[jj] && ("?D".indexOf(out[jj].t) > -1 || (" t".indexOf(out[jj].t) > -1 && "?t".indexOf((out[jj+1]||{}).t)>-1 && (out[jj+1].t == '?' || out[jj+1].v == '/')) || out[i].t == '(' && (out[jj].t == ')' || out[jj].t == 'n') || out[jj].t == 't' && (out[jj].v == '/' || '$€'.indexOf(out[jj].v) > -1 || (out[jj].v == ' ' && (out[jj+1]||{}).t == '?')))) {
out[i].v += out[jj].v;
delete out[jj]; ++jj;
}
Expand Down Expand Up @@ -4796,14 +4803,23 @@ function parse_workbook(blob) {
} break;
case 'Number': {
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:'n'};
if(temp_val.XF) try {
temp_val.w=SSF.format(temp_val.XF.ifmt||0, temp_val.v);
} catch(e) { }
addline({c:val.c, r:val.r}, temp_val);
} break;
case 'BoolErr': {
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t};
if(temp_val.XF) try {
temp_val.w=SSF.format(temp_val.XF.ifmt||0, temp_val.v);
} catch(e) { }
addline({c:val.c, r:val.r}, temp_val);
} break;
case 'RK': {
temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'};
if(temp_val.XF) try {
temp_val.w=SSF.format(temp_val.XF.ifmt||0, temp_val.v);
} catch(e) { }
addline({c:val.c, r:val.r}, temp_val);
} break;
case 'MulRk': {
Expand Down

0 comments on commit 6a8df59

Please sign in to comment.