Skip to content

Commit

Permalink
version bump 0.12.1: BIFF5 features
Browse files Browse the repository at this point in the history
- BIFF5 write number formats and other features
- XLSX/XLSB/BIFF8 Suppress "Number stored as Text" errors
- codename awareness (fixes SheetJS#992 h/t @samusstrike)
- updated CFB to 1.0.3
- demo refresh
  • Loading branch information
SheetJSDev authored and saarCiklum committed Aug 20, 2020
1 parent f661b12 commit d05909f
Show file tree
Hide file tree
Showing 62 changed files with 2,606 additions and 1,833 deletions.
1 change: 1 addition & 0 deletions .spelling
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ APIs
ArrayBuffer
Base64
Booleans
FileReader
JS
NoSQL
README
Expand Down
36 changes: 25 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,8 @@ function handleFile(e) {
input_dom_element.addEventListener('change', handleFile, false);
```

The [`oldie` demo](demos/oldie/) shows an IE-compatible fallback scenario.

</details>

More specialized cases, including mobile app file processing, are covered in the
Expand Down Expand Up @@ -850,11 +852,13 @@ for(var R = range.s.r; R <= range.e.r; ++R) {

### Cell Object

Cell objects are plain JS objects with keys and values following the convention:

| Key | Description |
| --- | ---------------------------------------------------------------------- |
| `v` | raw value (see Data Types section for more info) |
| `w` | formatted text (if applicable) |
| `t` | cell type: `b` Boolean, `n` Number, `e` error, `s` String, `d` Date |
| `t` | type: `b` Boolean, `e` Error, `n` Number, `d` Date, `s` Text, `z` Stub |
| `f` | cell formula encoded as an A1-style string (if applicable) |
| `F` | range of enclosing array if formula is array formula (if applicable) |
| `r` | rich text encoding (if applicable) |
Expand All @@ -874,11 +878,18 @@ array range. Other cells in the range will omit the `f` field.

#### Data Types

The raw value is stored in the `v` field, interpreted based on the `t` field.
The raw value is stored in the `v` value property, interpreted based on the `t`
type property. This separation allows for representation of numbers as well as
numeric text. There are 6 valid cell types:

Type `b` is the Boolean type. `v` is interpreted according to JS truth tables.

Type `e` is the Error type. `v` holds the number and `w` holds the common name:
| Type | Description |
| :--: | :-------------------------------------------------------------------- |
| `b` | Boolean: value interpreted as JS `boolean` |
| `e` | Error: value is a numeric code and `w` property stores common name ** |
| `n` | Number: value is a JS `number` ** |
| `d` | Date: value is a JS `Date` object or string to be parsed as Date ** |
| `s` | Text: value interpreted as JS `string` and written as text ** |
| `z` | Stub: blank stub cell that is ignored by data processing utilities ** |

<details>
<summary><b>Error values and interpretation</b> (click to show)</summary>
Expand Down Expand Up @@ -907,14 +918,17 @@ Since JSON does not have a natural Date type, parsers are generally expected to
store ISO 8601 Date strings like you would get from `date.toISOString()`. On
the other hand, writers and exporters should be able to handle date strings and
JS Date objects. Note that Excel disregards timezone modifiers and treats all
dates in the local timezone. js-xlsx does not correct for this error.
dates in the local timezone. The library does not correct for this error.

Type `s` is the String type. Values are explicitly stored as text. Excel will
interpret these cells as "number stored as text". Generated Excel files
automatically suppress that class of error, but other formats may elicit errors.

Type `s` is the String type. `v` should be explicitly stored as a string to
avoid possible confusion.
Type `z` represents blank stub cells. They are generated in cases where cells
have no assigned value but hold comments or other metadata. They are ignored by
the core library data processing utility functions. By default these cells are
not generated; the parser `sheetStubs` option must be set to `true`.

Type `z` represents blank stub cells. These do not have any data or type, and
are not processed by any of the core library functions. By default these cells
will not be generated; the parser `sheetStubs` option must be set to `true`.

#### Dates

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.12.0';
XLSX.version = '0.12.1';
40 changes: 40 additions & 0 deletions bits/11_ssfutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,46 @@ var XLMLFormatMap/*{[string]:string}*/ = ({
"On/Off": '"Yes";"Yes";"No";@'
}/*:any*/);

var SSFImplicit/*{[number]:string}*/ = ({
"5": '"$"#,##0_);\\("$"#,##0\\)',
"6": '"$"#,##0_);[Red]\\("$"#,##0\\)',
"7": '"$"#,##0.00_);\\("$"#,##0.00\\)',
"8": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
"23": 'General', "24": 'General', "25": 'General', "26": 'General',
"27": 'm/d/yy', "28": 'm/d/yy', "29": 'm/d/yy', "30": 'm/d/yy', "31": 'm/d/yy',
"32": 'h:mm:ss', "33": 'h:mm:ss', "34": 'h:mm:ss', "35": 'h:mm:ss',
"36": 'm/d/yy',
"41": '_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)',
"42": '_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)',
"43": '_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)',
"44": '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)',
"50": 'm/d/yy', "51": 'm/d/yy', "52": 'm/d/yy', "53": 'm/d/yy', "54": 'm/d/yy',
"55": 'm/d/yy', "56": 'm/d/yy', "57": 'm/d/yy', "58": 'm/d/yy',
"59": '0',
"60": '0.00',
"61": '#,##0',
"62": '#,##0.00',
"63": '"$"#,##0_);\\("$"#,##0\\)',
"64": '"$"#,##0_);[Red]\\("$"#,##0\\)',
"65": '"$"#,##0.00_);\\("$"#,##0.00\\)',
"66": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
"67": '0%',
"68": '0.00%',
"69": '# ?/?',
"70": '# ??/??',
"71": 'm/d/yy',
"72": 'm/d/yy',
"73": 'd-mmm-yy',
"74": 'd-mmm',
"75": 'mmm-yy',
"76": 'h:mm',
"77": 'h:mm:ss',
"78": 'm/d/yy h:mm',
"79": 'mm:ss',
"80": '[h]:mm:ss',
"81": 'mmss.0'
}/*:any*/);

/* dateNF parse TODO: move to SSF */
var dateNFregex = /[dD]+|[mM]+|[yYeE]+|[Hh]+|[Ss]+/g;
function dateNF_regex(dateNF/*:string|number*/)/*:RegExp*/ {
Expand Down
8 changes: 4 additions & 4 deletions bits/18_cfb.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type CFBFiles = {[n:string]:CFBEntry};
/* [MS-CFB] v20130118 */
var CFB = (function _CFB(){
var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
exports.version = '1.0.2';
exports.version = '1.0.3';
/* [MS-CFB] 2.6.4 */
function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
var L = l.split("/"), R = r.split("/");
Expand Down Expand Up @@ -353,14 +353,14 @@ function read_directory(dir_start/*:number*/, sector_list/*:SectorList*/, sector
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)/*:any*/);
prep_blob(o.content, 0);
} else {
o.storage = 'minifat';
if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) {
if(o.size < 0) o.size = 0;
else if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) {
o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini]||{}).data);
prep_blob(o.content, 0);
}
}
if(o.content) prep_blob(o.content, 0);
files[name] = o;
FileIndex.push(o);
}
Expand Down
2 changes: 1 addition & 1 deletion bits/20_jsutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ function keys(o/*:any*/)/*:Array<any>*/ { return Object.keys(o); }

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];
for(var i = 0; i !== K.length; ++i) if(o[obj[K[i]][key]] == null) o[obj[K[i]][key]] = K[i];
return o;
}

Expand Down
2 changes: 1 addition & 1 deletion bits/23_binutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ function WriteShift(t/*:number*/, val/*:string|number*/, f/*:?string*/)/*:any*/
} return this;
} else if(f === 'utf16le') {
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
var end/*:number*/ = this.l + t;
var end/*:number*/ = Math.min(this.l + t, this.length);
for(i = 0; i < Math.min(val.length, t); ++i) {
var cc = val.charCodeAt(i);
this[this.l++] = (cc & 0xff);
Expand Down
15 changes: 6 additions & 9 deletions bits/28_binstructs.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function write_StrRun(run, o) {
return o;
}

/* [MS-XLSB] 2.1.7.121 */
/* [MS-XLSB] 2.5.121 */
function parse_RichStr(data, length/*:number*/)/*:XLString*/ {
var start = data.l;
var flags = data.read_shift(1);
Expand All @@ -54,7 +54,7 @@ function write_RichStr(str/*:XLString*/, o/*:?Block*/)/*:Block*/ {
write_XLWideString(str.t, o);
return _null ? o.slice(0, o.l) : o;
}
/* [MS-XLSB] 2.4.325 BrtCommentText (RichStr w/1 run) */
/* [MS-XLSB] 2.4.328 BrtCommentText (RichStr w/1 run) */
var parse_BrtCommentText = parse_RichStr;
function write_BrtCommentText(str/*:XLString*/, o/*:?Block*/)/*:Block*/ {
/* TODO: formatted string */
Expand Down Expand Up @@ -108,8 +108,7 @@ var parse_RelID = parse_XLNullableWideString;
var write_RelID = write_XLNullableWideString;


/* [MS-XLSB] 2.5.122 */
/* [MS-XLS] 2.5.217 */
/* [MS-XLS] 2.5.217 ; [MS-XLSB] 2.5.122 */
function parse_RkNumber(data)/*:number*/ {
var b = data.slice(data.l, data.l+4);
var fX100 = (b[0] & 1), fInt = (b[0] & 2);
Expand Down Expand Up @@ -137,7 +136,6 @@ function parse_RfX(data /*::, length*/)/*:Range*/ {
cell.e.c = data.read_shift(4);
return cell;
}

function write_RfX(r/*:Range*/, o) {
if(!o) o = new_buf(16);
o.write_shift(4, r.s.r);
Expand All @@ -151,13 +149,12 @@ function write_RfX(r/*:Range*/, o) {
var parse_UncheckedRfX = parse_RfX;
var write_UncheckedRfX = write_RfX;

/* [MS-XLSB] 2.5.171 */
/* [MS-XLS] 2.5.342 */
/* [MS-XLS] 2.5.342 ; [MS-XLSB] 2.5.171 */
/* TODO: error checking, NaN and Infinity values are not valid Xnum */
function parse_Xnum(data/*::, length*/) { return data.read_shift(8, 'f'); }
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); }

/* [MS-XLSB] 2.5.198.2 */
/* [MS-XLSB] 2.5.97.2 */
var BErr = {
/*::[*/0x00/*::]*/: "#NULL!",
/*::[*/0x07/*::]*/: "#DIV/0!",
Expand All @@ -171,7 +168,7 @@ var BErr = {
};
var RBErr = evert_num(BErr);

/* [MS-XLSB] 2.4.321 BrtColor */
/* [MS-XLSB] 2.4.324 BrtColor */
function parse_BrtColor(data/*::, length*/) {
var out = {};
var d = data.read_shift(1);
Expand Down
2 changes: 1 addition & 1 deletion bits/29_xlsenum.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ var XLSFillPattern = [
function rgbify(arr) { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); }

/* [MS-XLS] 2.5.161 */
/* [MS-XLSB] 2.5.75 */
/* [MS-XLSB] 2.5.75 Icv */
var XLSIcv = rgbify([
/* Color Constants */
0x000000,
Expand Down
3 changes: 1 addition & 2 deletions bits/30_ctype.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
/* Parts enumerated in OPC spec, MS-XLSB and MS-XLSX */
/* 12.3 Part Summary <SpreadsheetML> */
/* 14.2 Part Summary <DrawingML> */
/* [MS-XLSX] 2.1 Part Enumerations */
/* [MS-XLSB] 2.1.7 Part Enumeration */
/* [MS-XLSX] 2.1 Part Enumerations ; [MS-XLSB] 2.1.7 Part Enumeration */
var ct2type/*{[string]:string}*/ = ({
/* Workbook */
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": "workbooks",
Expand Down
7 changes: 4 additions & 3 deletions bits/38_xlstypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ function parse_PropertySet(blob, PIDSI) {
}

/* [MS-OLEPS] 2.21 PropertySetStream */
function parse_PropertySetStream(file, PIDSI) {
function parse_PropertySetStream(file, PIDSI, clsid) {
var blob = file.content;
if(!blob) return ({}/*:any*/);
prep_blob(blob, 0);
Expand All @@ -223,7 +223,8 @@ function parse_PropertySetStream(file, PIDSI) {

/*var vers = */blob.read_shift(2); // TODO: check version
var SystemIdentifier = blob.read_shift(4);
blob.chk(CFB.utils.consts.HEADER_CLSID, 'CLSID: ');
var CLSID = blob.read_shift(16);
if(CLSID !== CFB.utils.consts.HEADER_CLSID && CLSID !== clsid) throw new Error("Bad PropertySet CLSID " + CLSID);
NumSets = blob.read_shift(4);
if(NumSets !== 1 && NumSets !== 2) throw new Error("Unrecognized #Sets: " + NumSets);
FMTID0 = blob.read_shift(16); Offset0 = blob.read_shift(4);
Expand Down Expand Up @@ -274,7 +275,7 @@ function parse_Bes(blob/*::, length*/) {
function write_Bes(v, t/*:string*/, o) {
if(!o) o = new_buf(2);
o.write_shift(1, +v);
o.write_shift(1, t == 'e' ? 1 : 0);
o.write_shift(1, ((t == 'e') ? 1 : 0));
return o;
}

Expand Down
Loading

0 comments on commit d05909f

Please sign in to comment.