diff --git a/.eslintrc b/.eslintrc index 686a33ea3ddef0f45c9d285ce65bafa6ce8004e0..d30937062ed979ba70e6cafd2e88af2a01a4e84a 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,10 +5,12 @@ "ecmaVersion": 3, }, "plugins": [ "html", "json" ], + "!extends": "eslint:recommended", "rules": { "no-use-before-define": [ 1, { "functions":false, "classes":true, "variables":false }], + "no-console": 0, "no-bitwise": 0, "curly": 0, "comma-style": [ 2, "last" ], diff --git a/README.md b/README.md index d56ea686455f960fe0dc1d1ef0e07e67a17d0c20..eb293aecb8dffbfd01de2104a71aa8341a0af6c6 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ Emphasis on parsing and writing robustness, cross-format feature compatibility with a unified JS representation, and ES3/ES5 browser compatibility back to IE6. This is the community version. We also offer a pro version with performance -enhancements and additional features by request. +enhancements, additional features by request, and dedicated support. + [**Pro Version**](http://sheetjs.com/pro) @@ -18,17 +19,33 @@ enhancements and additional features by request. [**Source Code**](http://git.io/xlsx) -[**File format support for known spreadsheet data formats:**](#file-formats) +[**Issues and Bug Reports**](https://github.com/sheetjs/js-xlsx/issues) -![circo graph of format support](formats.png) +[**Other General Support Issues**](https://discourse.sheetjs.com) + +[**File format support for known spreadsheet data formats:**](#file-formats)
- Graph Legend + Graph of supported formats (click to show) + +![circo graph of format support](formats.png) ![graph legend](legend.png)
+[**Browser Test**](http://oss.sheetjs.com/js-xlsx/tests/) + +[![Build Status](https://saucelabs.com/browser-matrix/sheetjs.svg)](https://saucelabs.com/u/sheetjs) + +[![Build Status](https://travis-ci.org/SheetJS/js-xlsx.svg?branch=master)](https://travis-ci.org/SheetJS/js-xlsx) +[![Build Status](https://semaphoreci.com/api/v1/sheetjs/js-xlsx/branches/master/shields_badge.svg)](https://semaphoreci.com/sheetjs/js-xlsx) +[![Coverage Status](http://img.shields.io/coveralls/SheetJS/js-xlsx/master.svg)](https://coveralls.io/r/SheetJS/js-xlsx?branch=master) +[![Dependencies Status](https://david-dm.org/sheetjs/js-xlsx/status.svg)](https://david-dm.org/sheetjs/js-xlsx) +[![NPM Downloads](https://img.shields.io/npm/dt/xlsx.svg)](https://npmjs.org/package/xlsx) +[![ghit.me](https://ghit.me/badge.svg?repo=sheetjs/js-xlsx)](https://ghit.me/repo/sheetjs/js-xlsx) +[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx) + ## Table of Contents
@@ -40,6 +57,7 @@ enhancements and additional features by request. * [JS Ecosystem Demos](#js-ecosystem-demos) * [Optional Modules](#optional-modules) * [ECMAScript 5 Compatibility](#ecmascript-5-compatibility) +- [Philosophy](#philosophy) - [Parsing Workbooks](#parsing-workbooks) * [Complete Examples](#complete-examples) * [Note on Streaming Read](#note-on-streaming-read) @@ -114,7 +132,6 @@ enhancements and additional features by request. * [Windows](#windows) - [License](#license) - [References](#references) -- [Badges](#badges) @@ -122,16 +139,16 @@ enhancements and additional features by request. ## Installation -With [npm](https://www.npmjs.org/package/xlsx): +In the browser, just add a script tag: -```bash -$ npm install xlsx +```html + ``` -In the browser: +With [npm](https://www.npmjs.org/package/xlsx): -```html - +```bash +$ npm install xlsx ``` With [bower](http://bower.io/search/?q=js-xlsx): @@ -194,6 +211,41 @@ To use the shim, add the shim before the script tag that loads xlsx.js: ``` +## Philosophy + +
+ Philosophy (click to show) + +Prior to SheetJS, APIs for processing spreadsheet files were format-specific. +Third-party libraries either supported one format, or they involved a separate +set of classes for each supported file type. Even though XLSB was introduced in +Excel 2007, nothing outside of SheetJS or Excel supported the format. + +To promote a format-agnostic view, js-xlsx starts from a pure-JS representation +that we call the ["Common Spreadsheet Format"](#common-spreadsheet-format). +Emphasizing a uniform object representation enables radical features like format +conversion (e.g. reading an XLSX template and saving as XLS) and circumvents the +"class trap". By abstracting the complexities of the various formats, tools +need not worry about the specific file type! + +A simple object representation combined with careful coding practices enables +use cases in older browsers and in alternative environments like ExtendScript +and Web Workers. It is always tempting to use the latest and greatest features, +but they tend to require the latest versions of browsers, limiting usability. + +Utility functions capture common use cases like generating JS objects or HTML. +Most simple operations should only require a few lines of code. More complex +operations generally should be straightforward to implement. + +Excel pushes the XLSX format as default starting in Excel 2007. However, there +are other formats with more appealing properties. For example, the XLSB format +is spiritually similar to XLSX but files often tend up taking less than half the +space and open much faster! Even though an XLSX writer is available, other +format writers are available so users can take advantage of the unique +characteristics of each format. + +
+ ## Parsing Workbooks For parsing, the first step is to read the file. This involves acquiring the @@ -505,7 +557,6 @@ Utilities are available in the `XLSX.utils` object: **Exporting:** - `sheet_to_json` converts a worksheet object to an array of JSON objects. - `sheet_to_row_object_array` is an alias that will be removed in the future. - `sheet_to_csv` generates delimiter-separated-values output. - `sheet_to_formulae` generates a list of the formulae (with value fallbacks). @@ -1008,17 +1059,14 @@ at index 164. The following example creates a custom format from scratch: ```js var tbl = {}; -XLSX.SSF.init_table(tbl); // <-- load builtin formats -tbl[164] = "\"T\"\ #0.00"; var wb = { - SSF: tbl, SheetNames: ["Sheet1"], Sheets: { Sheet1: { "!ref":"A1:C1", - A1: { t:"n", v:10000 }, // <-- General format - B1: { t:"n", v:10000, z: tbl[4] }, // <-- Builtin format - C1: { t:"n", v:10000, z: tbl[164] } // <-- Custom format + A1: { t:"n", v:10000 }, // <-- General format + B1: { t:"n", v:10000, z: "0%" }, // <-- Builtin format + C1: { t:"n", v:10000, z: "\"T\"\ #0.00" } // <-- Custom format } } } @@ -1439,8 +1487,8 @@ the output will be encoded in codepage `1200` and the BOM will be prepended. ### JSON -`XLSX.utils.sheet_to_json` and the alias `XLSX.utils.sheet_to_row_object_array` -generate different types of JS objects. The function takes an options argument: +`XLSX.utils.sheet_to_json` generates different types of JS objects. The function +takes an options argument: | Option Name | Default | Description | | :---------- | :------: | :-------------------------------------------------- | @@ -1834,6 +1882,9 @@ $ open -a Chromium.app http://localhost:8000/stress.html ### Tested Environments +
+ (click to show) + - NodeJS 0.8, 0.9, 0.10, 0.11, 0.12, 4.x, 5.x, 6.x, 7.x - IE 6/7/8/9/10/11 (IE6-9 browsers require shims for interacting with client) - Chrome 24+ @@ -1847,6 +1898,8 @@ Tests utilize the mocha testing framework. Travis-CI and Sauce Labs links: - for XLS\* modules - for XLS\* modules using Sauce Labs +
+ ### Test Files Test files are housed in [another repo](https://github.com/SheetJS/test_files). @@ -1980,20 +2033,3 @@ granted by the Apache 2.0 License are reserved by the Original Author. - Worksheet File Format (From Lotus) December 1984 -## Badges - -[![Build Status](https://saucelabs.com/browser-matrix/sheetjs.svg)](https://saucelabs.com/u/sheetjs) - -[![Build Status](https://travis-ci.org/SheetJS/js-xlsx.svg?branch=master)](https://travis-ci.org/SheetJS/js-xlsx) - -[![Build Status](https://semaphoreci.com/api/v1/sheetjs/js-xlsx/branches/master/shields_badge.svg)](https://semaphoreci.com/sheetjs/js-xlsx) - -[![Coverage Status](http://img.shields.io/coveralls/SheetJS/js-xlsx/master.svg)](https://coveralls.io/r/SheetJS/js-xlsx?branch=master) - -[![NPM Downloads](https://img.shields.io/npm/dt/xlsx.svg)](https://npmjs.org/package/xlsx) - -[![Dependencies Status](https://david-dm.org/sheetjs/js-xlsx/status.svg)](https://david-dm.org/sheetjs/js-xlsx) - -[![ghit.me](https://ghit.me/badge.svg?repo=sheetjs/js-xlsx)](https://ghit.me/repo/sheetjs/js-xlsx) - -[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx) diff --git a/bin/xlsx.njs b/bin/xlsx.njs index 9e1befc1687e7d4644ae1e0a605f3de68b19e2b5..9b10895ade33c7b44e6716d3c407f5e386388b3b 100755 --- a/bin/xlsx.njs +++ b/bin/xlsx.njs @@ -1,5 +1,6 @@ #!/usr/bin/env node /* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ +/* eslint-env node */ var n = "xlsx"; /* vim: set ts=2 ft=javascript: */ var X = require('../'); @@ -176,9 +177,9 @@ var oo = ""; var strm = false; if(!program.quiet) console.error(target_sheet); if(program.formulae) oo = X.utils.get_formulae(ws).join("\n"); -else if(program.json) oo = JSON.stringify(X.utils.sheet_to_row_object_array(ws)); -else if(program.rawJs) oo = JSON.stringify(X.utils.sheet_to_row_object_array(ws,{raw:true})); -else if(program.arrays) oo = JSON.stringify(X.utils.sheet_to_row_object_array(ws,{raw:true, header:1})); +else if(program.json) oo = JSON.stringify(X.utils.sheet_to_json(ws)); +else if(program.rawJs) oo = JSON.stringify(X.utils.sheet_to_json(ws,{raw:true})); +else if(program.arrays) oo = JSON.stringify(X.utils.sheet_to_json(ws,{raw:true, header:1})); else { strm = true; var stream = X.stream.to_csv(ws, {FS:program.fieldSep, RS:program.rowSep}); diff --git a/bits/00_header.js b/bits/00_header.js index 8eefc1d8c4eb1ef04ab15f4e0a32a79d3688a1a7..634a2d1b3b970f9b5d3f22b509b21966c5691c7d 100644 --- a/bits/00_header.js +++ b/bits/00_header.js @@ -3,5 +3,6 @@ /*jshint -W041 */ /*jshint funcscope:true, eqnull:true */ /*exported XLSX */ +/*global exports, module, require:false, process:false, Buffer:false */ var XLSX = {}; (function make_xlsx(XLSX){ diff --git a/bits/01_version.js b/bits/01_version.js index ddea91c9123f236d8a41370350a1b52fa596c0a8..566412f6531aadc263c6efe6c263eae76804d2cc 100644 --- a/bits/01_version.js +++ b/bits/01_version.js @@ -1 +1 @@ -XLSX.version = '0.9.13'; +XLSX.version = '0.10.0'; diff --git a/bits/02_codepage.js b/bits/02_codepage.js index 862803c555d737862dc784a0966778db14774201..2d7e77ebaa2115ed715f9ea7e4880d4c654407ef 100644 --- a/bits/02_codepage.js +++ b/bits/02_codepage.js @@ -1,8 +1,8 @@ -var current_codepage = 1200, current_cptable; +var current_codepage = 1200; /*:: declare var cptable:any; */ +/*global cptable:true */ if(typeof module !== "undefined" && typeof require !== 'undefined') { if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel.js'); - current_cptable = cptable[current_codepage]; } function reset_cp() { set_cp(1200); } var set_cp = function(cp) { current_codepage = cp; }; @@ -18,7 +18,7 @@ var debom = function(data/*:string*/)/*:string*/ { var _getchar = function _gc1(x) { return String.fromCharCode(x); }; if(typeof cptable !== 'undefined') { - set_cp = function(cp) { current_codepage = cp; current_cptable = cptable[cp]; }; + set_cp = function(cp) { current_codepage = cp; }; debom = function(data) { if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.substr(2))); } return data; diff --git a/bits/04_base64.js b/bits/04_base64.js index 2fc0636a600a53d7844e05bac6025e2cddf714d1..7050f436b3be269080bc75886385bd0ba06422d7 100644 --- a/bits/04_base64.js +++ b/bits/04_base64.js @@ -1,7 +1,7 @@ var Base64 = (function make_b64(){ var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; return { - encode: function(input/*:string*/, utf8)/*:string*/ { + encode: function(input/*:string*/)/*:string*/ { var o = ""; var c1, c2, c3, e1, e2, e3, e4; for(var i = 0; i < input.length; ) { @@ -18,7 +18,7 @@ var Base64 = (function make_b64(){ } return o; }, - decode: function b64_decode(input/*:string*/, utf8)/*:string*/ { + decode: function b64_decode(input/*:string*/)/*:string*/ { var o = ""; var c1, c2, c3; var e1, e2, e3, e4; diff --git a/bits/10_ssf.js b/bits/10_ssf.js index ccd13426fc40e6fc64aeb516c26073dba9c184e1..c179063e9c184584bb71217991d8ff4ff530889f 100644 --- a/bits/10_ssf.js +++ b/bits/10_ssf.js @@ -2,7 +2,7 @@ /*jshint -W041 */ var SSF = {}; var make_ssf = function make_ssf(SSF){ -SSF.version = '0.9.1'; +SSF.version = '0.9.2'; function _strrev(x/*:string*/)/*:string*/ { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; } function fill(c/*:string*/,l/*:number*/)/*:string*/ { var o = ""; while(o.length < l) o+=c; return o; } function pad0(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;} @@ -270,12 +270,14 @@ function write_num_exp(fmt/*:string*/, val/*:number*/)/*:string*/{ var o/*:string*/; var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1; if(fmt.match(/^#+0.0E\+0$/)) { + if(val == 0) return "0.0E+0"; + else if(val < 0) return "-" + write_num_exp(fmt, -val); var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E'); - var ee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E)%period; + var ee = Math.floor(Math.log(val)*Math.LOG10E)%period; if(ee < 0) ee += period; o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period); if(o.indexOf("e") === -1) { - var fakee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E); + var fakee = Math.floor(Math.log(val)*Math.LOG10E); if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee); else o += "E+" + (fakee - ee); while(o.substr(0,2) === "0.") { @@ -353,7 +355,7 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string if((r = fmt.match(/^(0*)\.(#*)$/))) { return sign + rnd(aval, r[2].length).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":"."); } - if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify(pad0r(aval,0)); + if((r = fmt.match(/^#{1,3},##0(\.?)$/))) return sign + commaify(pad0r(aval,0)); if((r = fmt.match(/^#,##0\.([#0]*0)$/))) { return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length); } @@ -401,7 +403,12 @@ function write_num_flt(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(flr(val)).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(ri,r[1].length); } switch(fmt) { + case "###,##0.00": return write_num_flt(type, "#,##0.00", val); + case "###,###": + case "##,###": case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : ""; + case "###,###.00": return write_num_flt(type, "###,##0.00",val).replace(/^0\./,"."); + case "#,###.00": return write_num_flt(type, "#,##0.00",val).replace(/^0\./,"."); default: } throw new Error("unsupported format |" + fmt + "|"); @@ -419,12 +426,14 @@ function write_num_exp2(fmt/*:string*/, val/*:number*/)/*:string*/{ var o/*:string*/; var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1; if(fmt.match(/^#+0.0E\+0$/)) { + if(val == 0) return "0.0E+0"; + else if(val < 0) return "-" + write_num_exp2(fmt, -val); var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E'); - var ee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E)%period; + var ee = Math.floor(Math.log(val)*Math.LOG10E)%period; if(ee < 0) ee += period; o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period); if(!o.match(/[Ee]/)) { - var fakee = Math.floor(Math.log(Math.abs(val))*Math.LOG10E); + var fakee = Math.floor(Math.log(val)*Math.LOG10E); if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee); else o += "E+" + (fakee - ee); o = o.replace(/\+-/,"-"); @@ -446,7 +455,7 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val); if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt.charAt(1)==' '?2:1),val); var o; - var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : ""; + var r/*:?Array*/, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : ""; if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length); if(fmt.match(/^[#?]+$/)) { o = (""+val); if(val === 0) o = ""; @@ -466,7 +475,7 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string if((r = fmt.match(/^(0*)\.(#*)$/))) { return sign + (""+aval).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":"."); } - if((r = fmt.match(/^#,##0(\.?)$/))) return sign + commaify((""+aval)); + if((r = fmt.match(/^#{1,3},##0(\.?)$/))) return sign + commaify((""+aval)); if((r = fmt.match(/^#,##0\.([#0]*0)$/))) { return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify((""+val)) + "." + fill('0',r[1].length); } @@ -482,12 +491,12 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string } var oa = ""; if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) { - ri = Math.min(r[4].length,7); + ri = Math.min(/*::String(*/r[4]/*::)*/.length,7); ff = frac(aval, Math.pow(10,ri)-1, false); o = "" + sign; - oa = write_num("n", r[1], ff[1]); + oa = write_num("n", /*::String(*/r[1]/*::)*/, ff[1]); if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0"; - o += oa + r[2] + "/" + r[3]; + o += oa + /*::String(*/r[2]/*::)*/ + "/" + /*::String(*/r[3]/*::)*/; oa = rpad_(ff[2],ri); if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa; o += oa; @@ -513,8 +522,12 @@ function write_num_int(type/*:string*/, fmt/*:string*/, val/*:number*/)/*:string return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify(""+val).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(0,r[1].length); } switch(fmt) { + case "###,###": + case "##,###": case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : ""; default: + if(fmt.slice(-3) == ".00") return write_num_int(type, fmt.slice(0,-3), val) + ".00"; + if(fmt.slice(-2) == ".0") return write_num_int(type, fmt.slice(0,-2), val) + ".0"; } throw new Error("unsupported format |" + fmt + "|"); } @@ -610,7 +623,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) { if(v < 0) return ""; if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; } o = c; while(++i -1) { o = (o.match(/\$([^-\[\]]*)/)||[])[1]||"$"; if(!fmt_is_date(fmt)) out[out.length] = {t:'t',v:o}; @@ -641,7 +655,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) { } /* falls through */ case '0': case '#': - o = c; while(++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1) o += c; + o = c; while(++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1 || c=='\\' && fmt.charAt(i+1) == "-" && i < fmt.length - 2 && "0#".indexOf(fmt.charAt(i+2))>-1) o += c; out[out.length] = {t:'n', v:o}; break; case '?': o = c; while(fmt.charAt(++i) === c) o+=c; @@ -705,7 +719,7 @@ function eval_fmt(fmt/*:string*/, v/*:any*/, opts/*:any*/, flen/*:number*/) { (c=out[jj].t) === "?" || c === "D" || (c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/') || out[i].t === '(' && (c === ' ' || c === 'n' || c === ')') || - c === 't' && (out[jj].v === '/' || '$€'.indexOf(out[jj].v) > -1 || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?') + c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?') )) { out[i].v += out[jj].v; out[jj] = {v:"", t:";"}; ++jj; @@ -819,7 +833,6 @@ function choose_fmt(f/*:string*/, v) { } function format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) { if(o == null) o = {}; - //fixopts(o != null ? o : (o=[])); var sfmt = ""; switch(typeof fmt) { case "string": diff --git a/bits/21_ziputils.js b/bits/21_ziputils.js index 13f30849e591efd97414b2de9a742aa295a0d77b..14aa2d3c15a185120913bd78372493431730e8d3 100644 --- a/bits/21_ziputils.js +++ b/bits/21_ziputils.js @@ -53,6 +53,7 @@ function getzipstr(zip, file/*:string*/, safe/*:?boolean*/)/*:?string*/ { var _fs, jszip; /*:: declare var JSZip:any; */ +/*global JSZip:true */ if(typeof JSZip !== 'undefined') jszip = JSZip; if (typeof exports !== 'undefined') { if (typeof module !== 'undefined' && module.exports) { diff --git a/bits/22_xmlutils.js b/bits/22_xmlutils.js index 7925da14e7f59ca68229c75d7a0538fbb1e50181..557729ad98f52a9742a35d9cf35243593649db0a 100644 --- a/bits/22_xmlutils.js +++ b/bits/22_xmlutils.js @@ -37,7 +37,7 @@ var encodings = { '&': '&' }; var rencoding = evert(encodings); -var rencstr = "&<>'\"".split(""); +//var rencstr = "&<>'\"".split(""); // TODO: CP remap (need to read file version to determine OS) var unescapexml/*:StringConv*/ = (function() { diff --git a/bits/26_crypto.js b/bits/26_crypto.js index 937d78d12eb510af64d4b3195d3925a2bfd698df..c41f62c9f52bdfa71a37b75f376c487e51bff1de 100644 --- a/bits/26_crypto.js +++ b/bits/26_crypto.js @@ -33,5 +33,6 @@ var make_offcrypto = function(O, _crypto) { }; }; /*:: declare var crypto:any; */ +/*global crypto:true */ make_offcrypto(OFFCRYPTO, typeof crypto !== "undefined" ? crypto : undefined); diff --git a/bits/28_binstructs.js b/bits/28_binstructs.js index 684c6bc8aeef34ec1d5a10343cc19a534735a63b..40631056920da53ebbdd62d190559e2d1f2493f9 100644 --- a/bits/28_binstructs.js +++ b/bits/28_binstructs.js @@ -1,8 +1,31 @@ +function write_UInt32LE(x/*:number*/, o) { + if(!o) o = new_buf(4); + o.write_shift(4, x); + return o; +} + +/* [MS-XLSB] 2.5.168 */ +function parse_XLWideString(data)/*:string*/ { + var cchCharacters = data.read_shift(4); + return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, 'dbcs'); +} +function write_XLWideString(data/*:string*/, o) { + var _null = false; if(o == null) { _null = true; o = new_buf(4+2*data.length); } + o.write_shift(4, data.length); + if(data.length > 0) o.write_shift(0, data, 'dbcs'); + return _null ? o.slice(0, o.l) : o; +} /* [MS-XLSB] 2.5.143 */ function parse_StrRun(data, length/*:?number*/) { return { ich: data.read_shift(2), ifnt: data.read_shift(2) }; } +function write_StrRun(run, o) { + if(!o) o = new_buf(4); + o.write_shift(2, run.ich || 0); + o.write_shift(2, run.ifnt || 0); + return o; +} /* [MS-XLSB] 2.1.7.121 */ function parse_RichStr(data, length/*:number*/)/*:XLString*/ { @@ -31,6 +54,17 @@ function write_RichStr(str/*:XLString*/, o/*:?Block*/)/*:Block*/ { write_XLWideString(str.t, o); return _null ? o.slice(0, o.l) : o; } +/* [MS-XLSB] 2.4.325 BrtCommentText (RichStr w/1 run) */ +var parse_BrtCommentText = parse_RichStr; +function write_BrtCommentText(str/*:XLString*/, o/*:?Block*/)/*:Block*/ { + /* TODO: formatted string */ + var _null = false; if(o == null) { _null = true; o = new_buf(23+4*str.t.length); } + o.write_shift(1,1); + write_XLWideString(str.t, o); + o.write_shift(4,1); + write_StrRun({ich:0,ifnt:0}, o); + return _null ? o.slice(0, o.l) : o; +} /* [MS-XLSB] 2.5.9 */ function parse_XLSBCell(data)/*:any*/ { @@ -65,18 +99,6 @@ function write_XLNullableWideString(data/*:string*/, o) { return _null ? o.slice(0, o.l) : o; } -/* [MS-XLSB] 2.5.168 */ -function parse_XLWideString(data)/*:string*/ { - var cchCharacters = data.read_shift(4); - return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, 'dbcs'); -} -function write_XLWideString(data/*:string*/, o) { - var _null = false; if(o == null) { _null = true; o = new_buf(4+2*data.length); } - o.write_shift(4, data.length); - if(data.length > 0) o.write_shift(0, data, 'dbcs'); - return _null ? o.slice(0, o.l) : o; -} - /* [MS-XLSB] 2.5.165 */ var parse_XLNameWideString = parse_XLWideString; var write_XLNameWideString = write_XLWideString; @@ -153,23 +175,75 @@ var RBErr = evert_num(BErr); function parse_BrtColor(data, length/*:number*/) { var out = {}; var d = data.read_shift(1); - out.fValidRGB = d & 1; - out.xColorType = d >>> 1; - out.index = data.read_shift(1); - out.nTintAndShade = data.read_shift(2, 'i'); - out.bRed = data.read_shift(1); - out.bGreen = data.read_shift(1); - out.bBlue = data.read_shift(1); - out.bAlpha = data.read_shift(1); + + var fValidRGB = d & 1; + var xColorType = d >>> 1; + + var index = data.read_shift(1); + var nTS = data.read_shift(2, 'i'); + var bR = data.read_shift(1); + var bG = data.read_shift(1); + var bB = data.read_shift(1); + var bAlpha = data.read_shift(1); + + switch(xColorType) { + case 0: out.auto = 1; break; + case 1: + out.index = index; + var icv = XLSIcv[index]; + /* automatic pseudo index 81 */ + if(icv) out.rgb = icv[0].toString(16) + icv[1].toString(16) + icv[2].toString(16); + break; + case 2: + /* if(!fValidRGB) throw new Error("invalid"); */ + out.rgb = bR.toString(16) + bG.toString(16) + bB.toString(16); + break; + case 3: out.theme = index; break; + } + if(nTS != 0) out.tint = nTS > 0 ? nTS / 32767 : nTS / 32768; + + return out; +} +function write_BrtColor(color, o) { + if(!o) o = new_buf(8); + if(!color||color.auto) { o.write_shift(4, 0); o.write_shift(4, 0); return o; } + if(color.index) { + o.write_shift(1, 0x02); + o.write_shift(1, color.index); + } else if(color.theme) { + o.write_shift(1, 0x06); + o.write_shift(1, color.theme); + } else { + o.write_shift(1, 0x05); + o.write_shift(1, 0); + } + var nTS = color.tint || 0; + if(nTS > 0) nTS *= 32767; + else if(nTS < 0) nTS *= 32768; + o.write_shift(2, nTS); + if(!color.rgb) { + o.write_shift(2, 0); + o.write_shift(1, 0); + o.write_shift(1, 0); + } else { + var rgb = (color.rgb || 'FFFFFF'); + o.write_shift(1, parseInt(rgb.substr(0,2),16)); + o.write_shift(1, parseInt(rgb.substr(2,2),16)); + o.write_shift(1, parseInt(rgb.substr(4,2),16)); + o.write_shift(1, 0xFF); + } + return o; } /* [MS-XLSB] 2.5.52 */ -function parse_FontFlags(data, length/*:number*/) { +function parse_FontFlags(data, length/*:number*/, opts) { var d = data.read_shift(1); data.l++; var out = { - fItalic: d & 0x2, - fStrikeout: d & 0x8, + /* fBold: d & 0x01 */ + fItalic: d & 0x02, + /* fUnderline: d & 0x04 */ + fStrikeout: d & 0x08, fOutline: d & 0x10, fShadow: d & 0x20, fCondense: d & 0x40, @@ -177,3 +251,17 @@ function parse_FontFlags(data, length/*:number*/) { }; return out; } +function write_FontFlags(font, o) { + if(!o) o = new_buf(2); + var grbit = + (font.italic ? 0x02 : 0) | + (font.strike ? 0x08 : 0) | + (font.outline ? 0x10 : 0) | + (font.shadow ? 0x20 : 0) | + (font.condense ? 0x40 : 0) | + (font.extend ? 0x80 : 0); + o.write_shift(1, grbit); + o.write_shift(1, 0); + return o; +} + diff --git a/bits/29_xlsenum.js b/bits/29_xlsenum.js index 2dcd187d3d8aaf4ae39e411de8cfa7eb757b2adb..7cc5004c3fd1d4173f58da66c4e83eb488c352e2 100644 --- a/bits/29_xlsenum.js +++ b/bits/29_xlsenum.js @@ -1,40 +1,40 @@ /* [MS-OLEPS] 2.2 PropertyType */ { - var VT_EMPTY = 0x0000; - var VT_NULL = 0x0001; + //var VT_EMPTY = 0x0000; + //var VT_NULL = 0x0001; var VT_I2 = 0x0002; var VT_I4 = 0x0003; - var VT_R4 = 0x0004; - var VT_R8 = 0x0005; - var VT_CY = 0x0006; - var VT_DATE = 0x0007; - var VT_BSTR = 0x0008; - var VT_ERROR = 0x000A; + //var VT_R4 = 0x0004; + //var VT_R8 = 0x0005; + //var VT_CY = 0x0006; + //var VT_DATE = 0x0007; + //var VT_BSTR = 0x0008; + //var VT_ERROR = 0x000A; var VT_BOOL = 0x000B; var VT_VARIANT = 0x000C; - var VT_DECIMAL = 0x000E; - var VT_I1 = 0x0010; - var VT_UI1 = 0x0011; - var VT_UI2 = 0x0012; + //var VT_DECIMAL = 0x000E; + //var VT_I1 = 0x0010; + //var VT_UI1 = 0x0011; + //var VT_UI2 = 0x0012; var VT_UI4 = 0x0013; - var VT_I8 = 0x0014; + //var VT_I8 = 0x0014; var VT_UI8 = 0x0015; - var VT_INT = 0x0016; - var VT_UINT = 0x0017; + //var VT_INT = 0x0016; + //var VT_UINT = 0x0017; var VT_LPSTR = 0x001E; - var VT_LPWSTR = 0x001F; + //var VT_LPWSTR = 0x001F; var VT_FILETIME = 0x0040; - var VT_BLOB = 0x0041; - var VT_STREAM = 0x0042; - var VT_STORAGE = 0x0043; - var VT_STREAMED_Object = 0x0044; - var VT_STORED_Object = 0x0045; - var VT_BLOB_Object = 0x0046; + //var VT_BLOB = 0x0041; + //var VT_STREAM = 0x0042; + //var VT_STORAGE = 0x0043; + //var VT_STREAMED_Object = 0x0044; + //var VT_STORED_Object = 0x0045; + //var VT_BLOB_Object = 0x0046; var VT_CF = 0x0047; - var VT_CLSID = 0x0048; - var VT_VERSIONED_STREAM = 0x0049; + //var VT_CLSID = 0x0048; + //var VT_VERSIONED_STREAM = 0x0049; var VT_VECTOR = 0x1000; - var VT_ARRAY = 0x2000; + //var VT_ARRAY = 0x2000; var VT_STRING = 0x0050; // 2.3.3.1.11 VtString var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString @@ -186,6 +186,7 @@ var XLSFillPattern = [ function rgbify(arr) { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); } /* [MS-XLS] 2.5.161 */ +/* [MS-XLSB] 2.5.75 */ var XLSIcv = rgbify([ /* Color Constants */ 0x000000, @@ -197,7 +198,7 @@ var XLSIcv = rgbify([ 0xFF00FF, 0x00FFFF, - /* Defaults */ + /* Overridable Defaults */ 0x000000, 0xFFFFFF, 0xFF0000, @@ -258,8 +259,24 @@ var XLSIcv = rgbify([ 0x333399, 0x333333, - /* Sheet */ - 0xFFFFFF, - 0x000000 + /* Other entries to appease BIFF8/12 */ + 0xFFFFFF, /* 0x40 icvForeground ?? */ + 0x000000, /* 0x41 icvBackground ?? */ + 0x000000, /* 0x42 icvFrame ?? */ + 0x000000, /* 0x43 icv3D ?? */ + 0x000000, /* 0x44 icv3DText ?? */ + 0x000000, /* 0x45 icv3DHilite ?? */ + 0x000000, /* 0x46 icv3DShadow ?? */ + 0x000000, /* 0x47 icvHilite ?? */ + 0x000000, /* 0x48 icvCtlText ?? */ + 0x000000, /* 0x49 icvCtlScrl ?? */ + 0x000000, /* 0x4A icvCtlInv ?? */ + 0x000000, /* 0x4B icvCtlBody ?? */ + 0x000000, /* 0x4C icvCtlFrame ?? */ + 0x000000, /* 0x4D icvCtlFore ?? */ + 0x000000, /* 0x4E icvCtlBack ?? */ + 0x000000, /* 0x4F icvCtlNeutral */ + 0x000000, /* 0x50 icvInfoBk ?? */ + 0x000000 /* 0x51 icvInfoText ?? */ ]); diff --git a/bits/31_rels.js b/bits/31_rels.js index 86c70889fa932f6cf19a99290b59161ff8e64a07..195bbce4643956121a975511ff9d79fedb622d64 100644 --- a/bits/31_rels.js +++ b/bits/31_rels.js @@ -55,7 +55,7 @@ function write_rels(rels)/*:string*/ { function add_rels(rels, rId, f, type, relobj)/*:number*/ { if(!relobj) relobj = {}; if(!rels['!id']) rels['!id'] = {}; - if(rId < 0) for(rId = 1; rels['!id']['rId' + rId]; ++rId){} + if(rId < 0) for(rId = 1; rels['!id']['rId' + rId]; ++rId){/* empty */} relobj.Id = 'rId' + rId; relobj.Type = type; relobj.Target = f; diff --git a/bits/35_custprops.js b/bits/35_custprops.js index 68f300b96f58e9e468525bfa77bfc66ba60ea7b1..8efcd1f6c67b15da535ec016004784fad4618b60 100644 --- a/bits/35_custprops.js +++ b/bits/35_custprops.js @@ -39,7 +39,7 @@ function parse_cust_props(data/*:string*/, opts) { default: if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks); } - } else if(x.substr(0,2) === " 24) { diff --git a/bits/39_xlsbiff.js b/bits/39_xlsbiff.js index cddd7e047cbc649f7db0f1e433fc1f36d3c3335c..38e3237ab48dfef75fff1f86711c6510f31f1ca2 100644 --- a/bits/39_xlsbiff.js +++ b/bits/39_xlsbiff.js @@ -21,7 +21,7 @@ function parse_frtHeader(blob) { function parse_OptXLUnicodeString(blob, length, opts) { return length === 0 ? "" : parse_XLUnicodeString2(blob, length, opts); } /* 2.5.158 */ -var HIDEOBJENUM = ['SHOWALL', 'SHOWPLACEHOLDER', 'HIDEALL']; +//var HIDEOBJENUM = ['SHOWALL', 'SHOWPLACEHOLDER', 'HIDEALL']; var parse_HideObjEnum = parseuint16; /* 2.5.344 */ @@ -99,35 +99,39 @@ function parse_FtCf(blob, length) { } /* 2.5.140 - 2.5.154 and friends */ +function parse_FtSkip(blob, length) { blob.l += 2; blob.l += blob.read_shift(2); } var FtTab = { - /*::[*/0x15/*::]*/: parse_FtCmo, - /*::[*/0x13/*::]*/: parsenoop, /* FtLbsData */ - /*::[*/0x12/*::]*/: function(blob, length) { blob.l += 12; }, /* FtCblsData */ - /*::[*/0x11/*::]*/: function(blob, length) { blob.l += 8; }, /* FtRboData */ - /*::[*/0x10/*::]*/: parsenoop, /* FtEdoData */ - /*::[*/0x0F/*::]*/: parsenoop, /* FtGboData */ - /*::[*/0x0D/*::]*/: parse_FtNts, /* FtNts */ - /*::[*/0x0C/*::]*/: function(blob, length) { blob.l += 24; }, /* FtSbs */ - /*::[*/0x0B/*::]*/: function(blob, length) { blob.l += 10; }, /* FtRbo */ - /*::[*/0x0A/*::]*/: function(blob, length) { blob.l += 16; }, /* FtCbls */ - /*::[*/0x09/*::]*/: parsenoop, /* FtPictFmla */ - /*::[*/0x08/*::]*/: function(blob, length) { blob.l += 6; }, /* FtPioGrbit */ - /*::[*/0x07/*::]*/: parse_FtCf, /* FtCf */ - /*::[*/0x06/*::]*/: function(blob, length) { blob.l += 6; }, /* FtGmo */ - /*::[*/0x04/*::]*/: parsenoop, /* FtMacro */ - /*::[*/0x00/*::]*/: function(blob, length) { blob.l += 4; } /* FtEnding */ + /*::[*/0x00/*::]*/: parse_FtSkip, /* FtEnd */ + /*::[*/0x04/*::]*/: parse_FtSkip, /* FtMacro */ + /*::[*/0x05/*::]*/: parse_FtSkip, /* FtButton */ + /*::[*/0x06/*::]*/: parse_FtSkip, /* FtGmo */ + /*::[*/0x07/*::]*/: parse_FtCf, /* FtCf */ + /*::[*/0x08/*::]*/: parse_FtSkip, /* FtPioGrbit */ + /*::[*/0x09/*::]*/: parse_FtSkip, /* FtPictFmla */ + /*::[*/0x0A/*::]*/: parse_FtSkip, /* FtCbls */ + /*::[*/0x0B/*::]*/: parse_FtSkip, /* FtRbo */ + /*::[*/0x0C/*::]*/: parse_FtSkip, /* FtSbs */ + /*::[*/0x0D/*::]*/: parse_FtNts, /* FtNts */ + /*::[*/0x0E/*::]*/: parse_FtSkip, /* FtSbsFmla */ + /*::[*/0x0F/*::]*/: parse_FtSkip, /* FtGboData */ + /*::[*/0x10/*::]*/: parse_FtSkip, /* FtEdoData */ + /*::[*/0x11/*::]*/: parse_FtSkip, /* FtRboData */ + /*::[*/0x12/*::]*/: parse_FtSkip, /* FtCblsData */ + /*::[*/0x13/*::]*/: parse_FtSkip, /* FtLbsData */ + /*::[*/0x14/*::]*/: parse_FtSkip, /* FtCblsFmla */ + /*::[*/0x15/*::]*/: parse_FtCmo }; function parse_FtArray(blob, length, ot) { - var s = blob.l; + var tgt = blob.l + length; var fts = []; - while(blob.l < s + length) { + while(blob.l < tgt) { var ft = blob.read_shift(2); blob.l-=2; try { - fts.push(FtTab[ft](blob, s + length - blob.l)); - } catch(e) { blob.l = s + length; return fts; } + fts.push(FtTab[ft](blob, tgt - blob.l)); + } catch(e) { blob.l = tgt; return fts; } } - if(blob.l != s + length) blob.l = s + length; //throw new Error("bad Object Ft-sequence"); + if(blob.l != tgt) blob.l = tgt; //throw new Error("bad Object Ft-sequence"); return fts; } @@ -158,7 +162,7 @@ function parse_BOF(blob, length) { function parse_InterfaceHdr(blob, length) { if(length === 0) return 0x04b0; var q; - if((q=blob.read_shift(2))!==0x04b0){} + if((q=blob.read_shift(2))!==0x04b0){/* empty */} return 0x04b0; } @@ -246,11 +250,16 @@ function parse_RecalcId(blob, length) { } /* 2.4.87 */ -function parse_DefaultRowHeight(blob, length) { - var f = blob.read_shift(2); - var fl = {Unsynced:f&1,DyZero:(f&2)>>1,ExAsc:(f&4)>>2,ExDsc:(f&8)>>3}; - /* char is misleading, miyRw and miyRwHidden overlap */ +function parse_DefaultRowHeight(blob, length, opts) { + var f = 0; + if(!(opts && opts.biff == 2)) { + f = blob.read_shift(2); + } var miyRw = blob.read_shift(2); + if((opts && opts.biff == 2)) { + f = 1 - (miyRw >> 15); miyRw &= 0x7fff; + } + var fl = {Unsynced:f&1,DyZero:(f&2)>>1,ExAsc:(f&4)>>2,ExDsc:(f&8)>>3}; return [fl, miyRw]; } @@ -265,9 +274,17 @@ function parse_Window1(blob, length) { /* 2.4.122 TODO */ function parse_Font(blob, length, opts) { - blob.l += 14; - var name = parse_ShortXLUnicodeString(blob, 0, opts); - return name; + var o = { + dyHeight: blob.read_shift(2), + fl: blob.read_shift(2) + }; + switch(opts && opts.biff || 8) { + case 2: break; + case 3: case 4: blob.l += 2; break; + default: blob.l += 10; break; + } + o.name = parse_ShortXLUnicodeString(blob, 0, opts); + return o; } /* 2.4.149 */ @@ -299,8 +316,8 @@ var parse_BIFF2Format = parse_XLUnicodeString2; function parse_Dimensions(blob, length, opts) { var end = blob.l + length; var w = opts.biff == 8 || !opts.biff ? 4 : 2; - var r = blob.read_shift(w), R = blob.read_shift(w), - c = blob.read_shift(2), C = blob.read_shift(2); + var r = blob.read_shift(w), R = blob.read_shift(w); + var c = blob.read_shift(2), C = blob.read_shift(2); blob.l = end; return {s: {r:r, c:c}, e: {r:R, c:C}}; } @@ -549,11 +566,49 @@ function parse_MergeCells(blob, length) { } /* 2.4.181 TODO: parse all the things! */ -function parse_Obj(blob, length) { +function parse_Obj(blob, length, opts) { + if(opts && opts.biff < 8) return parse_BIFF5Obj(blob, length, opts); var cmo = parse_FtCmo(blob, 22); // id, ot, flags var fts = parse_FtArray(blob, length-22, cmo[1]); return { cmo: cmo, ft:fts }; } +/* from older spec */ +var parse_BIFF5OT = []; +parse_BIFF5OT[0x08] = function(blob, length, opts) { + var tgt = blob.l + length; + blob.l += 10; // todo + var cf = blob.read_shift(2); + blob.l += 4; + var cbPictFmla = blob.read_shift(2); + blob.l += 2; + var grbit = blob.read_shift(2); + blob.l += 4; + var cchName = blob.read_shift(1); + blob.l += cchName; // TODO: stName + blob.l = tgt; // TODO: fmla + return { fmt:cf }; +}; + +function parse_BIFF5Obj(blob, length, opts) { + var cnt = blob.read_shift(4); + var ot = blob.read_shift(2); + var id = blob.read_shift(2); + var grbit = blob.read_shift(2); + var colL = blob.read_shift(2); + var dxL = blob.read_shift(2); + var rwT = blob.read_shift(2); + var dyT = blob.read_shift(2); + var colR = blob.read_shift(2); + var dxR = blob.read_shift(2); + var rwB = blob.read_shift(2); + var dyB = blob.read_shift(2); + var cbMacro = blob.read_shift(2); + blob.l += 6; + length -= 36; + var fts = []; + fts.push((parse_BIFF5OT[ot]||parsenoop)(blob, length, opts)); + return { cmo: [id, ot, grbit], ft:fts }; +} /* 2.4.329 TODO: parse properly */ function parse_TxO(blob, length, opts) { @@ -684,7 +739,6 @@ var parse_StyleExt = parsenoop; var parse_Window2 = parsenoop; - var parse_Backup = parsebool; /* 2.4.14 */ var parse_Blank = parse_XLSCell; /* 2.4.20 Just the cell */ var parse_BottomMargin = parse_Xnum; /* 2.4.27 */ @@ -991,6 +1045,16 @@ var parse_BopPopCustom = parsenoop; var parse_Fbi2 = parsenoop; /* --- Specific to versions before BIFF8 --- */ +function parse_ImData(blob, length, opts) { + var tgt = blob.l + length; + var cf = blob.read_shift(2); + var env = blob.read_shift(2); + var lcb = blob.read_shift(4); + var o = {fmt:cf, env:env, len:lcb, data:blob.slice(blob.l,blob.l+lcb)}; + blob.l += lcb; + return o; +} + function parse_BIFF5String(blob) { var len = blob.read_shift(1); return blob.read_shift(len, 'sbcs-cont'); @@ -1037,7 +1101,7 @@ function parse_BIFF2FONTXTRA(blob, length) { blob.l += 1; // charset blob.l += 3; // unknown blob.l += 1; // font family - blob.l += length - 9; + blob.l += length - 13; } /* TODO: parse rich text runs */ diff --git a/bits/40_harb.js b/bits/40_harb.js index b9898a919dee2dcdab534b14e6aa10cf7bb27579..5066631844fc25cea005564ed39c41a521d57df0 100644 --- a/bits/40_harb.js +++ b/bits/40_harb.js @@ -210,17 +210,23 @@ var SYLK = (function() { var Mval = 0, j; for (; ri !== records.length; ++ri) { Mval = 0; - var record = records[ri].trim().split(";"); - var RT = record[0], val; - switch(RT) { - case 'P': if(record[1].charAt(0) == 'P') formats.push(records[ri].trim().substr(3).replace(/;;/g, ";")); + var rstr=records[ri].trim(), record=rstr.split(";"), RT=record[0], val; + if(rstr.length > 0) switch(RT) { + case 'ID': break; /* header */ + case 'E': break; /* EOF */ + case 'B': break; /* dimensions */ + case 'O': break; /* options? */ + case 'P': + if(record[1].charAt(0) == 'P') + formats.push(rstr.substr(3).replace(/;;/g, ";")); break; - case 'C': case 'F': for(rj=1; rj 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); } else if(Mval == 0) rowinfo[R].hidden = true; + break; + default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr); } break; - default: break; + default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr); } } if(rowinfo.length > 0) sht['!rows'] = rowinfo; @@ -297,7 +319,7 @@ var SYLK = (function() { }); } - function write_ws_rows_sylk(out, rows) { + function write_ws_rows_sylk(out/*:Array*/, rows/*:Array*/) { rows.forEach(function(row, i) { var rec = "F;"; if(row.hidden) rec += "M0;"; @@ -318,6 +340,7 @@ var SYLK = (function() { if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']); if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']); + preamble.push("B;Y" + (r.e.r - r.s.r + 1) + ";X" + (r.e.c - r.s.c + 1) + ";D" + [r.s.c,r.s.r,r.e.c,r.e.r].join(" ")); for(var R = r.s.r; R <= r.e.r; ++R) { for(var C = r.s.c; C <= r.e.c; ++C) { var coord = encode_cell({r:R,c:C}); @@ -447,7 +470,7 @@ var PRN = (function() { function set_text_arr(data/*:string*/, arr/*:AOA*/, R/*:number*/, C/*:number*/) { if(data === 'TRUE') arr[R][C] = true; else if(data === 'FALSE') arr[R][C] = false; - else if(data === ""){} + else if(data === ""){/* empty */} else if(+data == +data) arr[R][C] = +data; else arr[R][C] = data; } @@ -485,29 +508,36 @@ var PRN = (function() { /* known sep */ if(str.substr(0,4) == "sep=" && str.charCodeAt(5) == 10) { sep = str.charAt(4); str = str.substr(6); } - /* TODO: actually determine the separator */ - if(str.substr(0,1024).indexOf("\t") == -1) sep = ","; else sep = "\t"; + else if(str.substr(0,1024).indexOf("\t") == -1) sep = ","; else sep = "\t"; var R = 0, C = 0, v = 0; var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0; - str = str.replace(/\r\n/g, "\n"); - for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) { - case 0x22: instr = !instr; break; - case sepcc: case 0x0a: if(instr) break; + str = str.replace(/\r\n/mg, "\n"); + function finish_cell() { var s = str.slice(start, end); var cell = ({}/*:any*/); if(s.charCodeAt(0) == 0x3D) { cell.t = 'n'; cell.f = s.substr(1); } else if(s == "TRUE") { cell.t = 'b'; cell.v = true; } else if(s == "FALSE") { cell.t = 'b'; cell.v = false; } - else if(!isNaN(v = parseFloat(s))) { cell.t = 'n'; cell.w = s; cell.v = v; } - else { cell.t = 's'; cell.v = s.replace(/^"/,"").replace(/"$/,"").replace(/""/g,'"'); } + else if(!isNaN(v = +s)) { cell.t = 'n'; cell.w = s; cell.v = v; } + else if(!isNaN(new Date(s).getDate())) { cell.t = 'd'; cell.v = parseDate(s); } + else { + cell.t = 's'; + if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"'); + cell.v = s; + } if(o.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = cell; } else ws[encode_cell({c:C,r:R})] = cell; start = end+1; if(range.e.c < C) range.e.c = C; if(range.e.r < R) range.e.r = R; - if(cc == sepcc) ++C; else { C = 0; ++R; } break; + if(cc == sepcc) ++C; else { C = 0; ++R; } + } + for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) { + case 0x22: if(instr || (end - start == 0)) instr = !instr; break; + case sepcc: case 0x0a: case 0x0d: if(!instr) finish_cell(); break; default: break; } + if(end - start > 0) finish_cell(); ws['!ref'] = encode_range(range); return ws; diff --git a/bits/43_sstbin.js b/bits/43_sstbin.js index 9d158acf60ff27895e244c1fe4b32f4b759e9b52..7904ad40b49623b04b731b8ed6254be642932557 100644 --- a/bits/43_sstbin.js +++ b/bits/43_sstbin.js @@ -22,8 +22,8 @@ function parse_sst_bin(data, opts)/*:SST*/ { pass = false; break; default: - if(R_n.indexOf("Begin") > 0){} - else if(R_n.indexOf("End") > 0){} + if(R_n.indexOf("Begin") > 0){/* empty */} + else if(R_n.indexOf("End") > 0){/* empty */} if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n); } }); diff --git a/bits/47_styxml.js b/bits/47_styxml.js index 61894ab15d93eb369db4e618a196838300b214d3..e9b7df34c79a42f2b6712251500e6689e3b93dd4 100644 --- a/bits/47_styxml.js +++ b/bits/47_styxml.js @@ -138,30 +138,47 @@ function parse_fonts(t, styles, themes, opts) { case '': case '': break; - /* 18.8.2 b CT_BooleanProperty */ - case '': font.bold = true; break; + /* 18.8.2 b CT_BooleanProperty */ + case '': font.bold = 1; break; /* 18.8.26 i CT_BooleanProperty */ - case '': font.italic = true; break; + case '': font.italic = 1; break; /* 18.4.13 u CT_UnderlineProperty */ - case '': font.underline = true; break; + case '': font.underline = 1; break; /* 18.4.10 strike CT_BooleanProperty */ - case '': font.strike = true; break; + case '': font.strike = 1; break; - /* 18.4.2 outline CT_BooleanProperty */ - case '': font.outline = true; break; + /* 18.4.2 outline CT_BooleanProperty */ + case '': font.outline = 1; break; /* 18.8.36 shadow CT_BooleanProperty */ - case '': font.shadow = true; break; + case '': font.shadow = 1; break; + + /* 18.8.12 condense CT_BooleanProperty */ + case '': font.condense = 1; break; + + /* 18.8.17 extend CT_BooleanProperty */ + case '': font.extend = 1; break; /* 18.4.11 sz CT_FontSize */ - case '': case '': break; /* 18.4.14 vertAlign CT_VerticalAlignFontProperty */ @@ -169,28 +186,39 @@ function parse_fonts(t, styles, themes, opts) { case '': case '': break; /* 18.8.18 family CT_FontFamily */ - case '': case '': break; /* 18.8.35 scheme CT_FontScheme */ case '': case '': break; - /* 18.4.1 charset CT_IntProperty TODO */ + /* 18.4.1 charset CT_IntProperty */ case '': case '': break; @@ -302,17 +330,18 @@ return function parse_sty_xml(data, themes, opts) { /* 18.8.23 fonts CT_Fonts ? */ if((t=data.match(fontsRegex))) parse_fonts(t, styles, themes, opts); - /* 18.8.21 fills CT_Fills */ + /* 18.8.21 fills CT_Fills ? */ if((t=data.match(fillsRegex))) parse_fills(t, styles, themes, opts); - /* 18.8.5 borders CT_Borders ? */ + /* 18.8.5 borders CT_Borders ? */ if((t=data.match(bordersRegex))) parse_borders(t, styles, themes, opts); - /* 18.8.9 cellStyleXfs CT_CellStyleXfs ? */ + /* 18.8.9 cellStyleXfs CT_CellStyleXfs ? */ /* 18.8.10 cellXfs CT_CellXfs ? */ if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts); + /* 18.8.8 cellStyles CT_CellStyles ? */ /* 18.8.15 dxfs CT_Dxfs ? */ /* 18.8.42 tableStyles CT_TableStyles ? */ /* 18.8.11 colors CT_Colors ? */ diff --git a/bits/48_stybin.js b/bits/48_stybin.js index 987ad9bd31da4271f6fca8da6390b5f90c9ab69d..bed89fc8467b318664403cd4d93012b558a13eba 100644 --- a/bits/48_stybin.js +++ b/bits/48_stybin.js @@ -4,33 +4,132 @@ function parse_BrtFmt(data, length/*:number*/) { var stFmtCode = parse_XLWideString(data,length-2); return [ifmt, stFmtCode]; } +function write_BrtFmt(i/*:number*/, f/*:string*/, o) { + if(!o) o = new_buf(6 + 4 * f.length); + o.write_shift(2, i); + write_XLWideString(f, o); + return o.length > o.l ? o.slice(0, o.l) : o; +} /* [MS-XLSB] 2.4.653 BrtFont TODO */ -function parse_BrtFont(data, length/*:number*/) { - var out = ({flags:{}}/*:any*/); - out.dyHeight = data.read_shift(2); - out.grbit = parse_FontFlags(data, 2); - out.bls = data.read_shift(2); - out.sss = data.read_shift(2); - out.uls = data.read_shift(1); - out.bFamily = data.read_shift(1); - out.bCharSet = data.read_shift(1); +function parse_BrtFont(data, length/*:number*/, opts) { + var out = ({}/*:any*/); + + out.sz = data.read_shift(2) / 20; + + var grbit = parse_FontFlags(data, 2, opts); + if(grbit.fCondense) out.condense = 1; + if(grbit.fExtend) out.extend = 1; + if(grbit.fShadow) out.shadow = 1; + if(grbit.fOutline) out.outline = 1; + if(grbit.fStrikeout) out.strike = 1; + if(grbit.fItalic) out.italic = 1; + + var bls = data.read_shift(2); + if(bls === 0x02BC) out.bold = 1; + + switch(data.read_shift(2)) { + /* case 0: out.vertAlign = "baseline"; break; */ + case 1: out.vertAlign = "superscript"; break; + case 2: out.vertAlign = "subscript"; break; + } + + var underline = data.read_shift(1); + if(underline != 0) out.underline = underline; + + var family = data.read_shift(1); + if(family > 0) out.family = family; + + var bCharSet = data.read_shift(1); + if(bCharSet > 0) out.charset = bCharSet; + data.l++; - out.brtColor = parse_BrtColor(data, 8); - out.bFontScheme = data.read_shift(1); + out.color = parse_BrtColor(data, 8); + + switch(data.read_shift(1)) { + /* case 0: out.scheme = "none": break; */ + case 1: out.scheme = "major"; break; + case 2: out.scheme = "minor"; break; + } + out.name = parse_XLWideString(data, length - 21); - out.flags.Bold = out.bls === 0x02BC; - out.flags.Italic = out.grbit.fItalic; - out.flags.Strikeout = out.grbit.fStrikeout; - out.flags.Outline = out.grbit.fOutline; - out.flags.Shadow = out.grbit.fShadow; - out.flags.Condense = out.grbit.fCondense; - out.flags.Extend = out.grbit.fExtend; - out.flags.Sub = out.sss & 0x2; - out.flags.Sup = out.sss & 0x1; return out; } +function write_BrtFont(font, o) { + if(!o) o = new_buf(25+4*32); + o.write_shift(2, font.sz * 20); + write_FontFlags(font, o); + o.write_shift(2, font.bold ? 0x02BC : 0x0190); + var sss = 0; + if(font.vertAlign == "superscript") sss = 1; + else if(font.vertAlign == "subscript") sss = 2; + o.write_shift(2, sss); + o.write_shift(1, font.underline || 0); + o.write_shift(1, font.family || 0); + o.write_shift(1, font.charset || 0); + o.write_shift(1, 0); + write_BrtColor(font.color, o); + var scheme = 0; + if(font.scheme == "major") scheme = 1; + if(font.scheme == "minor") scheme = 2; + o.write_shift(1, scheme); + write_XLWideString(font.name, o); + return o.length > o.l ? o.slice(0, o.l) : o; +} + +/* [MS-XLSB] 2.4.644 BrtFill */ +var XLSBFillPTNames = [ + "none", + "solid", + "mediumGray", + "darkGray", + "lightGray", + "darkHorizontal", + "darkVertical", + "darkDown", + "darkUp", + "darkGrid", + "darkTrellis", + "lightHorizontal", + "lightVertical", + "lightDown", + "lightUp", + "lightGrid", + "lightTrellis", + "gray125", + "gray0625" +]; +var rev_XLSBFillPTNames = evert(XLSBFillPTNames); +/* TODO: gradient fill representation */ +function write_BrtFill(fill, o) { + if(!o) o = new_buf(4*3 + 8*7 + 16*1); + var fls = rev_XLSBFillPTNames[fill.patternType]; + if(fls == null) fls = 0x28; + o.write_shift(4, fls); + var j = 0; + if(fls != 0x28) { + /* TODO: custom FG Color */ + write_BrtColor({auto:1}, o); + /* TODO: custom BG Color */ + write_BrtColor({auto:1}, o); + + for(; j < 12; ++j) o.write_shift(4, 0); + } else { + for(; j < 4; ++j) o.write_shift(4, 0); + + for(; j < 12; ++j) o.write_shift(4, 0); /* TODO */ + /* iGradientType */ + /* xnumDegree */ + /* xnumFillToLeft */ + /* xnumFillToRight */ + /* xnumFillToTop */ + /* xnumFillToBottom */ + /* cNumStop */ + /* xfillGradientStop */ + } + return o.length > o.l ? o.slice(0, o.l) : o; +} /* [MS-XLSB] 2.4.816 BrtXF */ function parse_BrtXF(data, length/*:number*/) { @@ -39,6 +138,62 @@ function parse_BrtXF(data, length/*:number*/) { parsenoop(data, length-4); return {ixfe:ixfeParent, ifmt:ifmt }; } +function write_BrtXF(data, ixfeP, o) { + if(!o) o = new_buf(16); + o.write_shift(2, ixfeP||0); + o.write_shift(2, data.numFmtId||0); + o.write_shift(2, 0); /* iFont */ + o.write_shift(2, 0); /* iFill */ + o.write_shift(2, 0); /* ixBorder */ + o.write_shift(1, 0); /* trot */ + o.write_shift(1, 0); /* indent */ + o.write_shift(1, 0); /* flags */ + o.write_shift(1, 0); /* flags */ + o.write_shift(1, 0); /* xfGrbitAtr */ + o.write_shift(1, 0); + return o; +} + +/* [MS-XLSB] 2.5.4 Blxf TODO */ +function write_Blxf(data, o) { + if(!o) o = new_buf(10); + o.write_shift(1, 0); /* dg */ + o.write_shift(1, 0); + o.write_shift(4, 0); /* color */ + o.write_shift(4, 0); /* color */ + return o; +} +/* [MS-XLSB] 2.4.299 BrtBorder TODO */ +function write_BrtBorder(border, o) { + if(!o) o = new_buf(51); + o.write_shift(1, 0); /* diagonal */ + write_Blxf(null, o); /* top */ + write_Blxf(null, o); /* bottom */ + write_Blxf(null, o); /* left */ + write_Blxf(null, o); /* right */ + write_Blxf(null, o); /* diag */ + return o.length > o.l ? o.slice(0, o.l) : o; +} + +/* [MS-XLSB] 2.4.755 BrtStyle TODO */ +function write_BrtStyle(style, o) { + if(!o) o = new_buf(12+4*10); + o.write_shift(4, style.xfId); + o.write_shift(2, 1); + o.write_shift(1, +style.builtinId); + o.write_shift(1, 0); /* iLevel */ + write_XLNullableWideString(style.name || "", o); + return o.length > o.l ? o.slice(0, o.l) : o; +} + +/* [MS-XLSB] 2.4.269 BrtBeginTableStyles */ +function write_BrtBeginTableStyles(cnt, defTableStyle, defPivotStyle) { + var o = new_buf(4+256*2*4); + o.write_shift(4, cnt); + write_XLNullableWideString(defTableStyle, o); + write_XLNullableWideString(defPivotStyle, o); + return o.length > o.l ? o.slice(0, o.l) : o; +} /* [MS-XLSB] 2.1.7.50 Styles */ function parse_sty_bin(data, themes, opts) { @@ -57,6 +212,9 @@ function parse_sty_bin(data, themes, opts) { break; case 0x002B: /* 'BrtFont' */ styles.Fonts.push(val); + if(val.color.theme != null && themes && themes.themeElements && themes.themeElements.clrScheme) { + val.color.rgb = rgb_tint(themes.themeElements.clrScheme[val.color.theme].rgb, val.color.tint || 0); + } break; case 0x0401: /* 'BrtKnownFonts' */ break; case 0x002D: /* 'BrtFill' */ break; @@ -98,20 +256,126 @@ function parse_sty_bin(data, themes, opts) { return styles; } +function write_FMTS_bin(ba, NF) { + if(!NF) return; + var cnt = 0; + [[5,8],[23,26],[41,44],[/*63*/57,/*66],[164,*/392]].forEach(function(r) { + for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) ++cnt; + }); + + if(cnt == 0) return; + write_record(ba, "BrtBeginFmts", write_UInt32LE(cnt)); + [[5,8],[23,26],[41,44],[/*63*/57,/*66],[164,*/392]].forEach(function(r) { + for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_record(ba, "BrtFmt", write_BrtFmt(i, NF[i])); + }); + write_record(ba, "BrtEndFmts"); +} + +function write_FONTS_bin(ba, data) { + var cnt = 1; + + if(cnt == 0) return; + write_record(ba, "BrtBeginFonts", write_UInt32LE(cnt)); + write_record(ba, "BrtFont", write_BrtFont({ + sz:12, + color: {theme:1}, + name: "Calibri", + family: 2, + scheme: "minor" + })); + /* 1*65491BrtFont [ACFONTS] */ + write_record(ba, "BrtEndFonts"); +} + +function write_FILLS_bin(ba, data) { + var cnt = 2; + + if(cnt == 0) return; + write_record(ba, "BrtBeginFills", write_UInt32LE(cnt)); + write_record(ba, "BrtFill", write_BrtFill({patternType:"none"})); + write_record(ba, "BrtFill", write_BrtFill({patternType:"gray125"})); + /* 1*65431BrtFill */ + write_record(ba, "BrtEndFills"); +} + +function write_BORDERS_bin(ba, data) { + var cnt = 1; + + if(cnt == 0) return; + write_record(ba, "BrtBeginBorders", write_UInt32LE(cnt)); + write_record(ba, "BrtBorder", write_BrtBorder({})); + /* 1*65430BrtBorder */ + write_record(ba, "BrtEndBorders"); +} + +function write_CELLSTYLEXFS_bin(ba, data) { + var cnt = 1; + write_record(ba, "BrtBeginCellStyleXFs", write_UInt32LE(cnt)); + write_record(ba, "BrtXF", write_BrtXF({ + numFmtId:0, + fontId:0, + fillId:0, + borderId:0 + }, 0xFFFF)); + /* 1*65430(BrtXF *FRT) */ + write_record(ba, "BrtEndCellStyleXFs"); +} + +function write_CELLXFS_bin(ba, data) { + write_record(ba, "BrtBeginCellXFs", write_UInt32LE(data.length)); + data.forEach(function(c) { write_record(ba, "BrtXF", write_BrtXF(c,0)); }); + /* 1*65430(BrtXF *FRT) */ + write_record(ba, "BrtEndCellXFs"); +} + +function write_STYLES_bin(ba, data) { + var cnt = 1; + + write_record(ba, "BrtBeginStyles", write_UInt32LE(1)); + write_record(ba, "BrtStyle", write_BrtStyle({ + xfId:0, + builtinId:0, + name:"Normal" + })); + /* 1*65430(BrtStyle *FRT) */ + write_record(ba, "BrtEndStyles"); +} + +function write_DXFS_bin(ba, data) { + var cnt = 0; + + write_record(ba, "BrtBeginDXFs", write_UInt32LE(cnt)); + /* *2147483647(BrtDXF *FRT) */ + write_record(ba, "BrtEndDXFs"); +} + +function write_TABLESTYLES_bin(ba, data) { + var cnt = 0; + + write_record(ba, "BrtBeginTableStyles", write_BrtBeginTableStyles(cnt, "TableStyleMedium9", "PivotStyleMedium4")); + /* *TABLESTYLE */ + write_record(ba, "BrtEndTableStyles"); +} + +function write_COLORPALETTE_bin(ba, data) { + return; + /* BrtBeginColorPalette [INDEXEDCOLORS] [MRUCOLORS] BrtEndColorPalette */ +} + /* [MS-XLSB] 2.1.7.50 Styles */ -function write_sty_bin(data, opts) { +function write_sty_bin(wb, opts) { var ba = buf_array(); write_record(ba, "BrtBeginStyleSheet"); - /* [FMTS] */ - /* [FONTS] */ - /* [FILLS] */ - /* [BORDERS] */ - /* CELLSTYLEXFS */ - /* CELLXFS*/ - /* STYLES */ - /* DXFS */ - /* TABLESTYLES */ - /* [COLORPALETTE] */ + write_FMTS_bin(ba, wb.SSF); + write_FONTS_bin(ba, wb); + write_FILLS_bin(ba, wb); + write_BORDERS_bin(ba, wb); + write_CELLSTYLEXFS_bin(ba, wb); + write_CELLXFS_bin(ba, opts.cellXfs); + write_STYLES_bin(ba, wb); + write_DXFS_bin(ba, wb); + write_TABLESTYLES_bin(ba, wb); + write_COLORPALETTE_bin(ba, wb); /* FRTSTYLESHEET*/ write_record(ba, "BrtEndStyleSheet"); return ba.end(); diff --git a/bits/49_theme.js b/bits/49_theme.js index 26b897881dfb4b3ea1a0c7f8db932b20d7f195c3..4590dffdf226352772800012a017121cc97d07a9 100644 --- a/bits/49_theme.js +++ b/bits/49_theme.js @@ -7,50 +7,41 @@ function parse_clrScheme(t, themes, opts) { (t[0].match(tagregex)||[]).forEach(function(x) { var y = parsexmltag(x); switch(y[0]) { + /* 20.1.6.2 clrScheme (Color Scheme) CT_ColorScheme */ case '': break; /* 20.1.2.3.32 srgbClr CT_SRgbColor */ - case '': - case '': - /* 20.1.4.1.10 dk2 (Dark 2) */ - case '': - case '': - /* 20.1.4.1.22 lt1 (Light 1) */ - case '': - case '': - /* 20.1.4.1.23 lt2 (Light 2) */ - case '': - case '': /* 20.1.4.1.1 accent1 (Accent 1) */ - case '': - case '': /* 20.1.4.1.2 accent2 (Accent 2) */ - case '': - case '': /* 20.1.4.1.3 accent3 (Accent 3) */ - case '': - case '': /* 20.1.4.1.4 accent4 (Accent 4) */ - case '': - case '': /* 20.1.4.1.5 accent5 (Accent 5) */ - case '': - case '': /* 20.1.4.1.6 accent6 (Accent 6) */ - case '': - case '': - /* 20.1.4.1.19 hlink (Hyperlink) */ - case '': - case '': + /* 20.1.4.1.9 dk1 (Dark 1) */ + /* 20.1.4.1.10 dk2 (Dark 2) */ /* 20.1.4.1.15 folHlink (Followed Hyperlink) */ - case '': - case '': + /* 20.1.4.1.19 hlink (Hyperlink) */ + /* 20.1.4.1.22 lt1 (Light 1) */ + /* 20.1.4.1.23 lt2 (Light 2) */ + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': if (y[0][1] === '/') { themes.themeElements.clrScheme.push(color); color = {}; diff --git a/bits/53_ccbin.js b/bits/53_ccbin.js index ac71efa16b48db198c834b1bc96c517405a1126b..7e8cd0561475f15ea8e14d25460845c827e9479c 100644 --- a/bits/53_ccbin.js +++ b/bits/53_ccbin.js @@ -22,8 +22,8 @@ function parse_cc_bin(data, opts) { out.push(val); break; default: - if((R_n||"").indexOf("Begin") > 0){} - else if((R_n||"").indexOf("End") > 0){} + if((R_n||"").indexOf("Begin") > 0){/* empty */} + else if((R_n||"").indexOf("End") > 0){/* empty */} else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n); } }); diff --git a/bits/55_vml.js b/bits/55_vml.js index 2c81891c1b08c649445949e426a2b1042a5510ed..e0bd8963b7cf00e9c50d49eb8a7c4b342e6cb75e 100644 --- a/bits/55_vml.js +++ b/bits/55_vml.js @@ -34,6 +34,7 @@ function write_comments_vml(rId, comments) { writetag('x:AutoFill', "False"), writetag('x:Row', String(c.r)), writetag('x:Column', String(c.c)), + '', '', '' ]); }); diff --git a/bits/58_cmntbin.js b/bits/58_cmntbin.js index c7b2cf0c6a7ca4f9c74f85ad9576cfaf782e8983..82ca18a56efe8a877c7a4e17178728882bad2b82 100644 --- a/bits/58_cmntbin.js +++ b/bits/58_cmntbin.js @@ -22,9 +22,6 @@ function write_BrtBeginComment(data, o) { /* [MS-XLSB] 2.4.324 BrtCommentAuthor */ var parse_BrtCommentAuthor = parse_XLWideString; -/* [MS-XLSB] 2.4.325 BrtCommentText */ -var parse_BrtCommentText = parse_RichStr; - /* [MS-XLSB] 2.1.7.8 Comments */ function parse_comments_bin(data, opts) { var out = []; @@ -57,8 +54,8 @@ function parse_comments_bin(data, opts) { default: - if((R_n||"").indexOf("Begin") > 0){} - else if((R_n||"").indexOf("End") > 0){} + if((R_n||"").indexOf("Begin") > 0){/* empty */} + else if((R_n||"").indexOf("End") > 0){/* empty */} else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n); } }); @@ -87,7 +84,7 @@ function write_comments_bin(data, opts) { c.iauthor = iauthor.indexOf(c.a); var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])}; write_record(ba, "BrtBeginComment", write_BrtBeginComment([range, c])); - if(c.t && c.t.length > 0) write_record(ba, "BrtCommentText", write_RichStr(c)); + if(c.t && c.t.length > 0) write_record(ba, "BrtCommentText", write_BrtCommentText(c)); write_record(ba, "BrtEndComment"); delete c.iauthor; }); diff --git a/bits/62_fxls.js b/bits/62_fxls.js index 569f45713379c1120924e9e85c57b0e328cacd83..a681db4cbf8f3e65375d567d56723eb8a241ba12 100644 --- a/bits/62_fxls.js +++ b/bits/62_fxls.js @@ -1,7 +1,7 @@ /* --- 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; } +function parseread1(blob) { blob.l+=1; return; } /* Rgce Helpers */ @@ -25,7 +25,7 @@ function parse_RgceArea(blob, length, opts) { 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]} }; } /* BIFF 2-5 encodes flags in the row field */ -function parse_RgceArea_BIFF2(blob, length, opts) { +function parse_RgceArea_BIFF2(blob/*, length, opts*/) { var r=parse_ColRelU(blob, 2), R=parse_ColRelU(blob, 2); var c=blob.read_shift(1); var C=blob.read_shift(1); @@ -33,7 +33,7 @@ function parse_RgceArea_BIFF2(blob, length, opts) { } /* 2.5.198.105 TODO */ -function parse_RgceAreaRel(blob, length, opts) { +function parse_RgceAreaRel(blob, length/*, opts*/) { var r=blob.read_shift(length == 12 ? 4 : 2), R=blob.read_shift(length == 12 ? 4 : 2); var c=parse_ColRelU(blob, 2); var C=parse_ColRelU(blob, 2); @@ -701,12 +701,12 @@ function stringify_formula(formula/*Array*/, range, cell/*:any*/, supbooks, var f = formula[0][ff]; //console.log("++",f, stack) switch(f[0]) { - /* 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; + case 'PtgUminus': /* 2.5.198.93 */ + stack.push("-" + stack.pop()); break; + case 'PtgUplus': /* 2.5.198.95 */ + stack.push("+" + stack.pop()); break; + case 'PtgPercent': /* 2.5.198.81 */ + stack.push(stack.pop() + "%"); break; case 'PtgAdd': /* 2.5.198.26 */ case 'PtgConcat': /* 2.5.198.43 */ @@ -723,10 +723,12 @@ function stringify_formula(formula/*Array*/, range, cell/*:any*/, supbooks, e1 = stack.pop(); e2 = stack.pop(); if(last_sp >= 0) { switch(formula[0][last_sp][1][0]) { - // $FlowIgnore - case 0: sp = fill(" ", formula[0][last_sp][1][1]); break; - // $FlowIgnore - case 1: sp = fill("\r", formula[0][last_sp][1][1]); break; + case 0: + // $FlowIgnore + sp = fill(" ", formula[0][last_sp][1][1]); break; + case 1: + // $FlowIgnore + sp = fill("\r", formula[0][last_sp][1][1]); break; default: sp = ""; // $FlowIgnore @@ -738,51 +740,46 @@ function stringify_formula(formula/*Array*/, range, cell/*:any*/, supbooks, stack.push(e2+PtgBinOp[f[0]]+e1); break; - /* 2.5.198.67 */ - case 'PtgIsect': + case 'PtgIsect': /* 2.5.198.67 */ e1 = stack.pop(); e2 = stack.pop(); stack.push(e2+" "+e1); break; - case 'PtgUnion': + case 'PtgUnion': /* 2.5.198.94 */ e1 = stack.pop(); e2 = stack.pop(); stack.push(e2+","+e1); break; - case 'PtgRange': + case 'PtgRange': /* 2.5.198.83 */ e1 = stack.pop(); e2 = stack.pop(); stack.push(e2+":"+e1); break; - /* 2.5.198.34 */ - case 'PtgAttrChoose': break; - /* 2.5.198.35 */ - case 'PtgAttrGoto': break; - /* 2.5.198.36 */ - case 'PtgAttrIf': break; - /* [MS-XLSB] 2.5.97.28 */ - case 'PtgAttrIfError': break; + case 'PtgAttrChoose': /* 2.5.198.34 */ + break; + case 'PtgAttrGoto': /* 2.5.198.35 */ + break; + case 'PtgAttrIf': /* 2.5.198.36 */ + break; + case 'PtgAttrIfError': /* [MS-XLSB] 2.5.97.28 */ + break; - /* 2.5.198.84 */ - case 'PtgRef': + case 'PtgRef': /* 2.5.198.84 */ type = f[1][0]; c = shift_cell_xls(f[1][1], _range, opts); stack.push(encode_cell_xls(c)); break; - /* 2.5.198.88 */ - case 'PtgRefN': + case 'PtgRefN': /* 2.5.198.88 */ type = f[1][0]; c = cell ? shift_cell_xls(f[1][1], cell, opts) : f[1][1]; stack.push(encode_cell_xls(c)); break; - case 'PtgRef3d': // TODO: lots of stuff + case 'PtgRef3d': /* 2.5.198.85 */ type = f[1][0]; ixti = /*::Number(*/f[1][1]/*::)*/; c = shift_cell_xls(f[1][2], _range, opts); sname = supbooks.SheetNames[ixti]; var w = sname; /* IE9 fails on defined names */ stack.push(sname + "!" + encode_cell_xls(c)); break; - /* 2.5.198.62 */ - case 'PtgFunc': - /* 2.5.198.63 */ - case 'PtgFuncVar': + case 'PtgFunc': /* 2.5.198.62 */ + case 'PtgFuncVar': /* 2.5.198.63 */ //console.log(f[1]); /* f[1] = [argc, func, type] */ var argc/*:number*/ = f[1][0], func/*:string*/ = f[1][1]; @@ -793,43 +790,38 @@ function stringify_formula(formula/*Array*/, range, cell/*:any*/, supbooks, 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(/*::String(*/f[1]/*::)*/); break; - /* 2.5.198.79 TODO: precision? */ - case 'PtgNum': stack.push(String(f[1])); break; - /* 2.5.198.89 */ - // $FlowIgnore - case 'PtgStr': stack.push('"' + f[1] + '"'); break; - /* 2.5.198.57 */ - case 'PtgErr': stack.push(/*::String(*/f[1]/*::)*/); break; - /* 2.5.198.31 TODO */ - case 'PtgAreaN': + case 'PtgBool': /* 2.5.198.42 */ + stack.push(f[1] ? "TRUE" : "FALSE"); break; + case 'PtgInt': /* 2.5.198.66 */ + stack.push(/*::String(*/f[1]/*::)*/); break; + case 'PtgNum': /* 2.5.198.79 TODO: precision? */ + stack.push(String(f[1])); break; + case 'PtgStr': /* 2.5.198.89 */ + // $FlowIgnore + stack.push('"' + f[1] + '"'); break; + case 'PtgErr': /* 2.5.198.57 */ + stack.push(/*::String(*/f[1]/*::)*/); break; + case 'PtgAreaN': /* 2.5.198.31 TODO */ type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts); stack.push(encode_range_xls((r/*:any*/), opts)); break; - /* 2.5.198.27 TODO: fixed points */ - case 'PtgArea': + case 'PtgArea': /* 2.5.198.27 TODO: fixed points */ type = f[1][0]; r = shift_range_xls(f[1][1], _range, opts); stack.push(encode_range_xls((r/*:any*/), opts)); break; - /* 2.5.198.28 */ - case 'PtgArea3d': // TODO: lots of stuff + case 'PtgArea3d': /* 2.5.198.28 TODO */ type = f[1][0]; ixti = /*::Number(*/f[1][1]/*::)*/; r = f[1][2]; sname = (supbooks && supbooks[1] ? supbooks[1][ixti+1] : "**MISSING**"); stack.push(sname + "!" + encode_range((r/*:any*/))); break; - /* 2.5.198.41 */ - case 'PtgAttrSum': + case 'PtgAttrSum': /* 2.5.198.41 */ stack.push("SUM(" + stack.pop() + ")"); break; - /* 2.5.198.37 */ - case 'PtgAttrSemi': break; + case 'PtgAttrSemi': /* 2.5.198.37 */ + break; - /* 2.5.97.60 TODO: do something different for revisions */ - case 'PtgName': + case 'PtgName': /* 2.5.97.60 TODO: revisions */ /* f[1] = type, 0, nameindex */ nameidx = f[1][2]; var lbl = (supbooks.names||[])[nameidx-1] || (supbooks[0]||[])[nameidx]; @@ -838,8 +830,7 @@ function stringify_formula(formula/*Array*/, range, cell/*:any*/, supbooks, stack.push(name); break; - /* 2.5.97.61 TODO: do something different for revisions */ - case 'PtgNameX': + case 'PtgNameX': /* 2.5.97.61 TODO: revisions */ /* f[1] = type, ixti, nameindex */ var bookidx/*:number*/ = (f[1][1]/*:any*/); nameidx = f[1][2]; var externbook; /* TODO: Properly handle missing values */ @@ -850,7 +841,7 @@ function stringify_formula(formula/*Array*/, range, cell/*:any*/, supbooks, } else { var pnxname = supbooks.SheetNames[bookidx]; var o = ""; - if(((supbooks[bookidx]||[])[0]||[])[0] == 0x3A01){} + if(((supbooks[bookidx]||[])[0]||[])[0] == 0x3A01){/* empty */} else if(((supbooks[bookidx]||[])[0]||[])[0] == 0x0401){ if(supbooks[bookidx][nameidx] && supbooks[bookidx][nameidx].itab > 0) { o = supbooks.SheetNames[supbooks[bookidx][nameidx].itab-1] + "!"; @@ -867,8 +858,7 @@ function stringify_formula(formula/*Array*/, range, cell/*:any*/, supbooks, stack.push(externbook.Name); break; - /* 2.5.198.80 */ - case 'PtgParen': + case 'PtgParen': /* 2.5.198.80 */ var lp = '(', rp = ')'; if(last_sp >= 0) { sp = ""; @@ -889,15 +879,13 @@ function stringify_formula(formula/*Array*/, range, cell/*:any*/, supbooks, } stack.push(lp + stack.pop() + rp); break; - /* 2.5.198.86 */ - case 'PtgRefErr': stack.push('#REF!'); break; + case 'PtgRefErr': /* 2.5.198.86 */ + stack.push('#REF!'); break; - /* 2.5.198.87 */ - case 'PtgRefErr3d': stack.push('#REF!'); break; + case 'PtgRefErr3d': /* 2.5.198.87 */ + stack.push('#REF!'); break; - /* */ - /* 2.5.198.58 TODO */ - case 'PtgExp': + case 'PtgExp': /* 2.5.198.58 TODO */ c = {c:f[1][1],r:f[1][0]}; var q = ({c: cell.c, r:cell.r}/*:any*/); if(supbooks.sharedf[encode_cell(c)]) { @@ -919,42 +907,37 @@ function stringify_formula(formula/*Array*/, range, cell/*:any*/, supbooks, } break; - /* 2.5.198.32 TODO */ - case 'PtgArray': + case 'PtgArray': /* 2.5.198.32 TODO */ stack.push("{" + stringify_array(f[1]) + "}"); break; - /* 2.5.198.70 TODO: confirm this is a non-display */ - case 'PtgMemArea': + case 'PtgMemArea': /* 2.5.198.70 TODO: confirm this is a non-display */ //stack.push("(" + f[2].map(encode_range).join(",") + ")"); break; - /* 2.5.198.38 */ - case 'PtgAttrSpace': - /* 2.5.198.39 */ - case 'PtgAttrSpaceSemi': + case 'PtgAttrSpace': /* 2.5.198.38 */ + case 'PtgAttrSpaceSemi': /* 2.5.198.39 */ last_sp = ff; break; - /* 2.5.198.92 TODO */ - case 'PtgTbl': break; + case 'PtgTbl': /* 2.5.198.92 TODO */ + break; - /* 2.5.198.71 */ - case 'PtgMemErr': break; + case 'PtgMemErr': /* 2.5.198.71 */ + break; - /* 2.5.198.74 */ - case 'PtgMissArg': + case 'PtgMissArg': /* 2.5.198.74 */ stack.push(""); break; - /* 2.5.198.29 */ - case 'PtgAreaErr': stack.push("#REF!"); break; + case 'PtgAreaErr': /* 2.5.198.29 */ + stack.push("#REF!"); break; - /* 2.5.198.30 */ - case 'PtgAreaErr3d': stack.push("#REF!"); break; + case 'PtgAreaErr3d': /* 2.5.198.30 */ + stack.push("#REF!"); break; - /* 2.5.198.72 TODO */ - case 'PtgMemFunc': break; + case 'PtgMemFunc': /* 2.5.198.72 TODO */ + break; default: throw new Error('Unrecognized Formula Token: ' + String(f)); } @@ -966,12 +949,14 @@ function stringify_formula(formula/*Array*/, range, cell/*:any*/, supbooks, /* note: some bad XLSB files omit the PtgParen */ case 4: _left = false; /* falls through */ - // $FlowIgnore - case 0: sp = fill(" ", f[1][1]); break; + case 0: + // $FlowIgnore + sp = fill(" ", f[1][1]); break; case 5: _left = false; /* falls through */ - // $FlowIgnore - case 1: sp = fill("\r", f[1][1]); break; + case 1: + // $FlowIgnore + sp = fill("\r", f[1][1]); break; default: sp = ""; // $FlowIgnore diff --git a/bits/66_wscommon.js b/bits/66_wscommon.js index d7ce1ebf188bc711e74358ea6be6cba53a2b4192..0e415bb2fc5af4d55dfa021e05f1e6faa7ce7fee 100644 --- a/bits/66_wscommon.js +++ b/bits/66_wscommon.js @@ -39,7 +39,16 @@ function default_margins(margins, mode) { function get_cell_style(styles, cell, opts) { var z = opts.revssf[cell.z != null ? cell.z : "General"]; - for(var i = 0, len = styles.length; i != len; ++i) if(styles[i].numFmtId === z) return i; + var i = 0x3c, len = styles.length; + if(z == null && opts.ssf) { + for(; i < 0x188; ++i) if(opts.ssf[i] == null) { + SSF.load(cell.z, i); + opts.ssf[i] = cell.z; + opts.revssf[cell.z] = z = i; + break; + } + } + for(i = 0; i != len; ++i) if(styles[i].numFmtId === z) return i; styles[len] = { numFmtId:z, fontId:0, @@ -77,7 +86,7 @@ function safe_format(p, fmtid, fillid, opts, themes, styles) { } catch(e) { if(opts.WTF) throw e; } if(fillid) try { p.s = styles.Fills[fillid]; - if (p.s.fgColor && p.s.fgColor.theme) { + if (p.s.fgColor && p.s.fgColor.theme && !p.s.fgColor.rgb) { p.s.fgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.fgColor.theme].rgb, p.s.fgColor.tint || 0); if(opts.WTF) p.s.fgColor.raw_rgb = themes.themeElements.clrScheme[p.s.fgColor.theme].rgb; } diff --git a/bits/68_wsbin.js b/bits/68_wsbin.js index 6f4a02aa595c605e078d8cb823b2de2781fdec15..6bd2cb5525201ac9149d4036a7411e528a83fc91 100644 --- a/bits/68_wsbin.js +++ b/bits/68_wsbin.js @@ -69,6 +69,9 @@ function write_row_header(ba, ws, range, R) { var parse_BrtWsDim = parse_UncheckedRfX; var write_BrtWsDim = write_UncheckedRfX; +/* [MS-XLSB] 2.4.813 BrtWsFmtInfo */ +//function write_BrtWsFmtInfo(ws, o) { } + /* [MS-XLSB] 2.4.815 BrtWsProp */ function parse_BrtWsProp(data, length) { var z = {}; @@ -78,8 +81,9 @@ function parse_BrtWsProp(data, length) { return z; } function write_BrtWsProp(str, o) { - if(o == null) o = new_buf(80+4*str.length); - for(var i = 0; i < 11; ++i) o.write_shift(1,0); + if(o == null) o = new_buf(84+4*str.length); + for(var i = 0; i < 3; ++i) o.write_shift(1,0); + write_BrtColor({auto:1}, o); o.write_shift(-4,-1); o.write_shift(-4,-1); write_XLSBCodeName(str, o); @@ -260,8 +264,8 @@ function write_BrtHLink(l, rId, o) { write_UncheckedRfX({s:decode_cell(l[0]), e:decode_cell(l[0])}, o); write_RelID("rId" + rId, o); var locidx = l[1].Target.indexOf("#"); - var location = locidx == -1 ? "" : l[1].Target.substr(locidx+1); - write_XLWideString(location || "", o); + var loc = locidx == -1 ? "" : l[1].Target.substr(locidx+1); + write_XLWideString(loc || "", o); write_XLWideString(l[1].Tooltip || "", o); write_XLWideString("", o); return o.slice(0, o.l); @@ -536,6 +540,7 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ { s['!margins'] = val; break; + /* case 'BrtUid' */ case 0x00AF: /* 'BrtAFilterDateGroupItem' */ case 0x0284: /* 'BrtActiveX' */ case 0x0271: /* 'BrtBigName' */ @@ -585,7 +590,6 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ { case 0x0413: /* 'BrtSparkline' */ case 0x01AC: /* 'BrtTable' */ case 0x00AA: /* 'BrtTop10Filter' */ - /* case 'BrtUid' */ case 0x0032: /* 'BrtValueMeta' */ case 0x0816: /* 'BrtWebExtension' */ case 0x01E5: /* 'BrtWsFmtInfo' */ @@ -601,8 +605,8 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ { case 0x0026: /* 'BrtACEnd' */ break; default: - if((R_n||"").indexOf("Begin") > 0){} - else if((R_n||"").indexOf("End") > 0){} + if((R_n||"").indexOf("Begin") > 0){/* empty */} + else if((R_n||"").indexOf("End") > 0){/* empty */} else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n); } }, opts); @@ -646,7 +650,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num } var o/*:any*/ = ({r:R, c:C}/*:any*/); /* TODO: cell style */ - //o.s = get_cell_style(opts.cellXfs, cell, opts); + o.s = get_cell_style(opts.cellXfs, cell, opts); if(cell.l) ws['!links'].push([encode_cell(o), cell.l]); if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]); switch(cell.t) { @@ -753,6 +757,11 @@ function write_WSVIEWS2(ba, ws) { write_record(ba, "BrtEndWsViews"); } +function write_WSFMTINFO(ba, ws) { + /* [ACWSFMTINFO] */ + //write_record(ba, "BrtWsFmtInfo", write_BrtWsFmtInfo(ws)); +} + function write_SHEETPROTECT(ba, ws) { if(!ws['!protect']) return; /* [BrtSheetProtectionIso] */ @@ -770,7 +779,7 @@ function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) { write_record(ba, "BrtWsProp", write_BrtWsProp(s)); write_record(ba, "BrtWsDim", write_BrtWsDim(r)); write_WSVIEWS2(ba, ws); - /* [WSFMTINFO] */ + write_WSFMTINFO(ba, ws); write_COLINFOS(ba, ws, idx, opts, wb); write_CELLTABLE(ba, ws, idx, opts, wb); /* [BrtSheetCalcProp] */ diff --git a/bits/73_wbbin.js b/bits/73_wbbin.js index 8a8a8051953c89c5e92224080f735429b5f512ca..23610d2222e5c35affe08738b92d353e7646b165 100644 --- a/bits/73_wbbin.js +++ b/bits/73_wbbin.js @@ -24,7 +24,7 @@ function parse_BrtWbProp(data, length) { return [dwThemeVersion, strName]; } function write_BrtWbProp(data, o) { - if(!o) o = new_buf(68); + if(!o) o = new_buf(72); o.write_shift(4, 0); o.write_shift(4, 0); write_XLSBCodeName("ThisWorkbook", o); @@ -85,6 +85,9 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ { break; case 0x040C: /* 'BrtNameExt' */ break; + /* case 'BrtModelTimeGroupingCalcCol' */ + /* case 'BrtRevisionPtr' */ + /* case 'BrtUid' */ case 0x0817: /* 'BrtAbsPath15' */ case 0x0216: /* 'BrtBookProtection' */ case 0x02A5: /* 'BrtBookProtectionIso' */ @@ -100,11 +103,9 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ { case 0x0299: /* 'BrtFnGroup' */ case 0x0850: /* 'BrtModelRelationship' */ case 0x084D: /* 'BrtModelTable' */ - /* case 'BrtModelTimeGroupingCalcCol' */ case 0x0225: /* 'BrtOleSize' */ case 0x0805: /* 'BrtPivotTableRef' */ case 0x0169: /* 'BrtPlaceholderName' */ - /* case 'BrtRevisionPtr' */ case 0x0254: /* 'BrtSmartTagType' */ case 0x029B: /* 'BrtSupAddin' */ case 0x0163: /* 'BrtSupBookSrc' */ @@ -113,7 +114,6 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ { case 0x081C: /* 'BrtTableSlicerCacheID' */ case 0x081B: /* 'BrtTableSlicerCacheIDs' */ case 0x0822: /* 'BrtTimelineCachePivotCacheID' */ - /* case 'BrtUid' */ case 0x018D: /* 'BrtUserBookView' */ case 0x009A: /* 'BrtWbFactoid' */ case 0x0099: /* 'BrtWbProp' */ @@ -132,8 +132,8 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ { case 0x0010: /* 'BrtFRTArchID$' */ break; default: - if((R_n||"").indexOf("Begin") > 0){} - else if((R_n||"").indexOf("End") > 0){} + if((R_n||"").indexOf("Begin") > 0){/* empty */} + else if((R_n||"").indexOf("End") > 0){/* empty */} else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n); } }, opts); diff --git a/bits/75_xlml.js b/bits/75_xlml.js index 3ec8e8c564405263385080a65dbebe44d693d7c0..07fab4c8a69b1e8827e370e306a87b1e095bd82c 100644 --- a/bits/75_xlml.js +++ b/bits/75_xlml.js @@ -530,7 +530,7 @@ function parse_xlml_xml(d, opts)/*:Workbook*/ { /* WorksheetOptions */ case 'WorksheetOptions': switch(Rn[3]) { case 'Visible': - if(Rn[0].slice(-2) === "/>"){} + if(Rn[0].slice(-2) === "/>"){/* empty */} else if(Rn[1]==="/") switch(str.slice(pidx, Rn.index)) { case "SheetHidden": wsprops.Hidden = 1; break; case "SheetVeryHidden": wsprops.Hidden = 2; break; @@ -729,12 +729,10 @@ function parse_xlml_xml(d, opts)/*:Workbook*/ { default: seen = false; } break; - /* Sorting */ case 'Sorting': - /* ConditionalFormatting */ case 'ConditionalFormatting': - /* DataValidation */ - case 'DataValidation': switch(Rn[3]) { + case 'DataValidation': + switch(Rn[3]) { case 'Range': break; case 'Type': break; case 'Min': break; @@ -889,7 +887,7 @@ function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workb if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) { /* Visible */ - if(!!wb.Workbook.Sheets[idx].Hidden) o.push(writextag("Visible", (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden"), {})); + if(wb.Workbook.Sheets[idx].Hidden) o.push(writextag("Visible", (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden"), {})); else { /* Selected */ for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break; diff --git a/bits/76_xls.js b/bits/76_xls.js index 44a0446b39856877af0a317e82f7aeb4b8a6f0d9..8ca3a90964f344f068d4de9968a3614ba3781d04 100644 --- a/bits/76_xls.js +++ b/bits/76_xls.js @@ -56,7 +56,7 @@ function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) { if(p.t === 'z') return; if(!p.XF) return; try { - var fmtid = p.XF.ifmt||0; + var fmtid = p.z || p.XF.ifmt || 0; if(opts.cellNF) p.z = SSF._table[fmtid]; } catch(e) { if(opts.WTF) throw e; } if(!opts || opts.cellText !== false) try { @@ -179,6 +179,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { var last_Rn = ''; var file_depth = 0; /* TODO: make a real stack */ var BIFF2Fmt = 0; + var BIFF2FmtTable = []; var FilterDatabases = []; /* TODO: sort out supbooks and process elsewhere */ var last_lbl; @@ -309,7 +310,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { out = options.dense ? [] : {}; } break; case 'BOF': { - if(opts.biff !== 8){} + if(opts.biff !== 8){/* empty */} else if(RecordType === 0x0009) opts.biff = 2; else if(RecordType === 0x0209) opts.biff = 3; else if(RecordType === 0x0409) opts.biff = 4; @@ -342,17 +343,20 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { case 'Number': case 'BIFF2NUM': case 'BIFF2INT': { if(out["!type"] == "chart") if(options.dense ? (out[val.r]||[])[val.c]: out[encode_cell({c:val.c, r:val.r})]) ++val.c; - temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:'n'}; + temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe]||{}, v:val.val, t:'n'}; + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; 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(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; 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(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; safe_format_xf(temp_val, options, wb.opts.Date1904); addcell({c:val.c, r:val.r}, temp_val, options); } break; @@ -360,6 +364,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { 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(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; safe_format_xf(temp_val, options, wb.opts.Date1904); addcell({c:j, r:val.r}, temp_val, options); } @@ -377,6 +382,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F; } else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); } + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; safe_format_xf(temp_val, options, wb.opts.Date1904); addcell(val.cell, temp_val, options); last_formula = val; @@ -389,6 +395,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { if(options.cellFormula) { temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts); } + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; safe_format_xf(temp_val, options, wb.opts.Date1904); addcell(last_formula.cell, temp_val, options); last_formula = null; @@ -419,11 +426,13 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { case 'LabelSst': temp_val=make_cell(sst[val.isst].t, val.ixfe, 's'); temp_val.XF = XFs[temp_val.ixfe]; + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; safe_format_xf(temp_val, options, wb.opts.Date1904); addcell({c:val.c, r:val.r}, temp_val, options); break; case 'Blank': if(options.sheetStubs) { temp_val = {ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'}; + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; safe_format_xf(temp_val, options, wb.opts.Date1904); addcell({c:val.c, r:val.r}, temp_val, options); } break; @@ -431,6 +440,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { for(var _j = val.c; _j <= val.C; ++_j) { var _ixfe = val.ixfe[_j-val.c]; temp_val= {ixfe:_ixfe, XF:XFs[_ixfe], t:'z'}; + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; safe_format_xf(temp_val, options, wb.opts.Date1904); addcell({c:_j, r:val.r}, temp_val, options); } @@ -439,6 +449,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { case 'Label': case 'BIFF2STR': temp_val=make_cell(val.val, val.ixfe, 's'); temp_val.XF = XFs[temp_val.ixfe]; + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; safe_format_xf(temp_val, options, wb.opts.Date1904); addcell({c:val.c, r:val.r}, temp_val, options); break; @@ -453,20 +464,23 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { SSF.load(val[1], val[0]); } break; case 'BIFF2FORMAT': { - SSF.load(val, BIFF2Fmt++); + BIFF2FmtTable[BIFF2Fmt++] = val; + for(var b2idx = 0; b2idx < BIFF2Fmt + 163; ++b2idx) if(SSF._table[b2idx] == val) break; + if(b2idx >= 163) SSF.load(val, BIFF2Fmt + 163); } 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 'ImData': opts.lastobj.ImData = 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) { cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})]; if(cc) cc.l = val[1]; - } + } } break; case 'HLinkTooltip': { for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR) @@ -611,24 +625,24 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { //console.log("Zoom Level:", val[0]/val[1],val); } break; case 'SheetExt': { - + /* empty */ } break; case 'SheetExtOptional': { - + /* empty */ } break; /* VBA */ case 'ObNoMacros': { - + /* empty */ } break; case 'ObProj': { - + /* empty */ } break; case 'CodeName': { - + /* empty */ } break; case 'GUIDTypeLib': { - + /* empty */ } break; case 'WOpt': break; // TODO: WTF? @@ -657,7 +671,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { /* Explicitly Ignored */ case 'Excel9File': break; case 'Units': break; - case 'InterfaceHdr': case 'Mms': case 'InterfaceEnd': case 'DSF': case 'BuiltInFnGroupCount': + case 'InterfaceHdr': case 'Mms': case 'InterfaceEnd': case 'DSF': case 'BuiltInFnGroupCount': break; /* View Stuff */ case 'Window1': case 'Window2': case 'HideObj': case 'GridSet': case 'Guts': case 'UserBView': case 'UserSViewBegin': case 'UserSViewEnd': @@ -724,13 +738,12 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { /* Drawing */ case 'ShapePropsStream': break; case 'MsoDrawing': case 'MsoDrawingGroup': case 'MsoDrawingSelection': break; - case 'ImData': break; /* Pub Stuff */ - case 'WebPub': case 'AutoWebPub': + case 'WebPub': case 'AutoWebPub': break; /* Print Stuff */ case 'HeaderFooter': case 'HFPicture': case 'PLV': - case 'HorizontalPageBreaks': case 'VerticalPageBreaks': + case 'HorizontalPageBreaks': case 'VerticalPageBreaks': break; /* Behavioral */ case 'Backup': case 'CompressPictures': case 'Compat12': break; @@ -779,11 +792,11 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { 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) {} + if(DSI) try { cfb.DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI); } catch(e) {/* empty */} /* [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) {} + if(SI) try { cfb.Summary = parse_PropertySetStream(SI, SummaryPIDSI); } catch(e) {/* empty */} } function parse_xlscfb(cfb/*:any*/, options/*:?ParseOpts*/)/*:Workbook*/ { diff --git a/bits/77_parsetab.js b/bits/77_parsetab.js index 05a188cc986e950b70a75b33aa37dbfcfbc26c30..f00a8003c6f27174ff8fc389e7202d888b316e1f 100644 --- a/bits/77_parsetab.js +++ b/bits/77_parsetab.js @@ -1192,9 +1192,10 @@ var XLSRecordEnum = { /*::[*/0x0007/*::]*/: { n:"String", f:parse_BIFF2STRING }, /*::[*/0x0008/*::]*/: { n:"BIFF2ROW", f:parsenoop }, /*::[*/0x000b/*::]*/: { n:"Index", f:parse_Index }, + /*::[*/0x0016/*::]*/: { n:"ExternCount", f:parsenoop }, /*::[*/0x001e/*::]*/: { n:"BIFF2FORMAT", f:parse_BIFF2Format }, /*::[*/0x001f/*::]*/: { n:"BIFF2FMTCNT", f:parsenoop }, /* 16-bit cnt of BIFF2FORMAT records */ - /*::[*/0x0016/*::]*/: { n:"ExternCount", f:parsenoop }, + /*::[*/0x0020/*::]*/: { n:"BIFF2COLINFO", f:parsenoop }, /*::[*/0x0021/*::]*/: { n:"Array", f:parse_Array }, /*::[*/0x0025/*::]*/: { n:"DefaultRowHeight", f:parse_DefaultRowHeight }, /*::[*/0x0032/*::]*/: { n:"BIFF2FONTXTRA", f:parse_BIFF2FONTXTRA }, @@ -1202,7 +1203,7 @@ var XLSRecordEnum = { /*::[*/0x0045/*::]*/: { n:"BIFF2FONTCLR", f:parsenoop }, /*::[*/0x0056/*::]*/: { n:"BIFF4FMTCNT", f:parsenoop }, /* 16-bit cnt, similar to BIFF2 */ /*::[*/0x007e/*::]*/: { n:"RK", f:parsenoop }, /* Not necessarily same as 0x027e */ - /*::[*/0x007f/*::]*/: { n:"ImData", f:parsenoop }, + /*::[*/0x007f/*::]*/: { n:"ImData", f:parse_ImData }, /*::[*/0x0087/*::]*/: { n:"Addin", f:parsenoop }, /*::[*/0x0088/*::]*/: { n:"Edg", f:parsenoop }, /*::[*/0x0089/*::]*/: { n:"Pub", f:parsenoop }, diff --git a/bits/80_parseods.js b/bits/80_parseods.js index 9b38b18a9042b7e887fce8308f6c43ef2683873e..0a949345c06a053ca06c331bd80fe3ea786db80b 100644 --- a/bits/80_parseods.js +++ b/bits/80_parseods.js @@ -312,7 +312,7 @@ var parse_content_xml = (function() { try { var AutoFilter = ods_to_csf_range_3D(parsexmltag(Rn[0])['target-range-address']); Sheets[AutoFilter[0]]['!autofilter'] = { ref: AutoFilter[1] }; - } catch(e) { } + } catch(e) {/* empty */} break; case 's': break; // @@ -362,7 +362,8 @@ var parse_content_xml = (function() { case 'sheet-name': // 7.3.9 break; - case 'event-listener': // TODO + case 'event-listener': + break; /* TODO: FODS Properties */ case 'initial-creator': case 'creation-date': diff --git a/bits/86_writezip.js b/bits/86_writezip.js index 4ee65472cfa649defd4e9c8ca3cb2404ddcde9eb..88c29495f3ed63fbe0ce5d30cb7b7d4656debd1c 100644 --- a/bits/86_writezip.js +++ b/bits/86_writezip.js @@ -9,6 +9,7 @@ function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ { make_ssf(SSF); SSF.load_table(wb.SSF); // $FlowIgnore opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0; + opts.ssf = wb.SSF; } opts.rels = {}; opts.wbrels = {}; opts.Strings = /*::((*/[]/*:: :any):SST)*/; opts.Strings.Count = 0; opts.Strings.Unique = 0; @@ -37,7 +38,7 @@ function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ { /*::if(!wb.Props) throw "unreachable"; */ f = "docProps/app.xml"; - if(wb.Props && wb.Props.SheetNames){} + if(wb.Props && wb.Props.SheetNames){/* empty */} else if(!wb.Workbook || !wb.Workbook.Sheets) wb.Props.SheetNames = wb.SheetNames; // $FlowIgnore else wb.Props.SheetNames = wb.SheetNames.map(function(x,i) { return [(wb.Workbook.Sheets[i]||{}).Hidden != 2, x];}).filter(function(x) { return x[0]; }).map(function(x) { return x[1]; }); @@ -126,5 +127,7 @@ function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ { zip.file("[Content_Types].xml", write_ct(ct, opts)); zip.file('_rels/.rels', write_rels(opts.rels)); zip.file('xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels)); + + delete opts.revssf; delete opts.ssf; return zip; } diff --git a/demos/browserify/browserify.html b/demos/browserify/browserify.html index 2c72df89ab2c465ef7c9e7ce5c1b4856ac1f0ad7..d391aa2c748f76b2ad79a9c35c85bba2a6d40899 100644 --- a/demos/browserify/browserify.html +++ b/demos/browserify/browserify.html @@ -141,7 +141,7 @@ function get_radio_value( radioName ) { function to_json(workbook) { var result = {}; workbook.SheetNames.forEach(function(sheetName) { - var roa = X.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]); + var roa = X.utils.sheet_to_json(workbook.Sheets[sheetName]); if(roa.length > 0){ result[sheetName] = roa; } diff --git a/demos/requirejs/requirejs.js b/demos/requirejs/requirejs.js index 0b303016b16701266644cfa9e126ae050e1e13b4..32918e1728102232c8a09becdcc10841843dee6c 100644 --- a/demos/requirejs/requirejs.js +++ b/demos/requirejs/requirejs.js @@ -41,7 +41,7 @@ function get_radio_value( radioName ) { function to_json(workbook) { var result = {}; workbook.SheetNames.forEach(function(sheetName) { - var roa = X.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]); + var roa = X.utils.sheet_to_json(workbook.Sheets[sheetName]); if(roa.length > 0){ result[sheetName] = roa; } diff --git a/demos/webpack/webpack.html b/demos/webpack/webpack.html index cd5674dfa0154c61c370d444209078494183882d..870bbd88856300b5e7e4e1164dd54d2348436f2b 100644 --- a/demos/webpack/webpack.html +++ b/demos/webpack/webpack.html @@ -141,7 +141,7 @@ function get_radio_value( radioName ) { function to_json(workbook) { var result = {}; workbook.SheetNames.forEach(function(sheetName) { - var roa = X.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]); + var roa = X.utils.sheet_to_json(workbook.Sheets[sheetName]); if(roa.length > 0){ result[sheetName] = roa; } diff --git a/dist/xlsx.core.min.js b/dist/xlsx.core.min.js index 03474bc07724aee623181e52d716d69494647996..6b60680caac93452ec5cdbdc868d0d18782aeb48 100644 Binary files a/dist/xlsx.core.min.js and b/dist/xlsx.core.min.js differ diff --git a/dist/xlsx.core.min.map b/dist/xlsx.core.min.map index 9991fa199cbb8e41835e0a5caacac531260fde3c..f4dfa95ac951082a14b6818b8e4c3d833a2530da 100644 Binary files a/dist/xlsx.core.min.map and b/dist/xlsx.core.min.map differ diff --git a/dist/xlsx.full.min.js b/dist/xlsx.full.min.js index 7685b9c6baf1d8a786c29c655a1e8b37e8d10d7e..aaccec35684de0486635faac930fba8b7c8a1a6a 100644 Binary files a/dist/xlsx.full.min.js and b/dist/xlsx.full.min.js differ diff --git a/dist/xlsx.full.min.map b/dist/xlsx.full.min.map index 9717011e1bbe6958a2c3b0f91ee7567d36bc47be..a1837f2e07b2a9e1076a4fe84af15760ea387012 100644 Binary files a/dist/xlsx.full.min.map and b/dist/xlsx.full.min.map differ diff --git a/dist/xlsx.js b/dist/xlsx.js index f3ab374b0805965eab18b17567b0f79606b5e70e..6a78a5836ba2404c3ba54de1e0f850c223419808 100644 Binary files a/dist/xlsx.js and b/dist/xlsx.js differ diff --git a/dist/xlsx.min.js b/dist/xlsx.min.js index 2eefee175cb0cc82d65f315abc9f29444b4bef0c..7f8861cb9009d31a1bd42d8b227602b4c15f3af9 100644 Binary files a/dist/xlsx.min.js and b/dist/xlsx.min.js differ diff --git a/dist/xlsx.min.map b/dist/xlsx.min.map index b2f0a3903b3006a12e6f81c01d03b7d8b77dd531..0a61ff981ac0438f230650ec34494dd41b0e06fc 100644 Binary files a/dist/xlsx.min.map and b/dist/xlsx.min.map differ diff --git a/docbits/00_intro.md b/docbits/00_intro.md index 9910fef115cb989aec8d5a0757f004c9277b9299..5126dde2844b1863fb06b498840a09f99320919e 100644 --- a/docbits/00_intro.md +++ b/docbits/00_intro.md @@ -6,7 +6,8 @@ Emphasis on parsing and writing robustness, cross-format feature compatibility with a unified JS representation, and ES3/ES5 browser compatibility back to IE6. This is the community version. We also offer a pro version with performance -enhancements and additional features by request. +enhancements, additional features by request, and dedicated support. + [**Pro Version**](http://sheetjs.com/pro) @@ -18,14 +19,30 @@ enhancements and additional features by request. [**Source Code**](http://git.io/xlsx) -[**File format support for known spreadsheet data formats:**](#file-formats) +[**Issues and Bug Reports**](https://github.com/sheetjs/js-xlsx/issues) -![circo graph of format support](formats.png) +[**Other General Support Issues**](https://discourse.sheetjs.com) + +[**File format support for known spreadsheet data formats:**](#file-formats)
- Graph Legend + Graph of supported formats (click to show) + +![circo graph of format support](formats.png) ![graph legend](legend.png)
+[**Browser Test**](http://oss.sheetjs.com/js-xlsx/tests/) + +[![Build Status](https://saucelabs.com/browser-matrix/sheetjs.svg)](https://saucelabs.com/u/sheetjs) + +[![Build Status](https://travis-ci.org/SheetJS/js-xlsx.svg?branch=master)](https://travis-ci.org/SheetJS/js-xlsx) +[![Build Status](https://semaphoreci.com/api/v1/sheetjs/js-xlsx/branches/master/shields_badge.svg)](https://semaphoreci.com/sheetjs/js-xlsx) +[![Coverage Status](http://img.shields.io/coveralls/SheetJS/js-xlsx/master.svg)](https://coveralls.io/r/SheetJS/js-xlsx?branch=master) +[![Dependencies Status](https://david-dm.org/sheetjs/js-xlsx/status.svg)](https://david-dm.org/sheetjs/js-xlsx) +[![NPM Downloads](https://img.shields.io/npm/dt/xlsx.svg)](https://npmjs.org/package/xlsx) +[![ghit.me](https://ghit.me/badge.svg?repo=sheetjs/js-xlsx)](https://ghit.me/repo/sheetjs/js-xlsx) +[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx) + diff --git a/docbits/10_install.md b/docbits/10_install.md index edce5d8bd7ba58bfc0b9090e89c31857a3d31bb6..ace8f8ea264feeb87dc1cf52b802bb64a1118d2e 100644 --- a/docbits/10_install.md +++ b/docbits/10_install.md @@ -1,15 +1,15 @@ ## Installation -With [npm](https://www.npmjs.org/package/xlsx): +In the browser, just add a script tag: -```bash -$ npm install xlsx +```html + ``` -In the browser: +With [npm](https://www.npmjs.org/package/xlsx): -```html - +```bash +$ npm install xlsx ``` With [bower](http://bower.io/search/?q=js-xlsx): diff --git a/docbits/15_phil.md b/docbits/15_phil.md new file mode 100644 index 0000000000000000000000000000000000000000..9d4c8a7c0000f93841528e928312ecf797ad1d6e --- /dev/null +++ b/docbits/15_phil.md @@ -0,0 +1,35 @@ +## Philosophy + +
+ Philosophy (click to show) + +Prior to SheetJS, APIs for processing spreadsheet files were format-specific. +Third-party libraries either supported one format, or they involved a separate +set of classes for each supported file type. Even though XLSB was introduced in +Excel 2007, nothing outside of SheetJS or Excel supported the format. + +To promote a format-agnostic view, js-xlsx starts from a pure-JS representation +that we call the ["Common Spreadsheet Format"](#common-spreadsheet-format). +Emphasizing a uniform object representation enables radical features like format +conversion (e.g. reading an XLSX template and saving as XLS) and circumvents the +"class trap". By abstracting the complexities of the various formats, tools +need not worry about the specific file type! + +A simple object representation combined with careful coding practices enables +use cases in older browsers and in alternative environments like ExtendScript +and Web Workers. It is always tempting to use the latest and greatest features, +but they tend to require the latest versions of browsers, limiting usability. + +Utility functions capture common use cases like generating JS objects or HTML. +Most simple operations should only require a few lines of code. More complex +operations generally should be straightforward to implement. + +Excel pushes the XLSX format as default starting in Excel 2007. However, there +are other formats with more appealing properties. For example, the XLSB format +is spiritually similar to XLSX but files often tend up taking less than half the +space and open much faster! Even though an XLSX writer is available, other +format writers are available so users can take advantage of the unique +characteristics of each format. + +
+ diff --git a/docbits/40_interface.md b/docbits/40_interface.md index dc0c803087c14bd31bac81d17b649349d7a77285..e50d697cd7418fee97898ea51abaa095a0dc6a02 100644 --- a/docbits/40_interface.md +++ b/docbits/40_interface.md @@ -38,7 +38,6 @@ Utilities are available in the `XLSX.utils` object: **Exporting:** - `sheet_to_json` converts a worksheet object to an array of JSON objects. - `sheet_to_row_object_array` is an alias that will be removed in the future. - `sheet_to_csv` generates delimiter-separated-values output. - `sheet_to_formulae` generates a list of the formulae (with value fallbacks). diff --git a/docbits/63_numfmt.md b/docbits/63_numfmt.md index d78b6f1d7f6a0d5a44eb1025771fcf9fa41ca057..4edc1579be610d9795533db9a0ca8ad601184452 100644 --- a/docbits/63_numfmt.md +++ b/docbits/63_numfmt.md @@ -15,17 +15,14 @@ at index 164. The following example creates a custom format from scratch: ```js var tbl = {}; -XLSX.SSF.init_table(tbl); // <-- load builtin formats -tbl[164] = "\"T\"\ #0.00"; var wb = { - SSF: tbl, SheetNames: ["Sheet1"], Sheets: { Sheet1: { "!ref":"A1:C1", - A1: { t:"n", v:10000 }, // <-- General format - B1: { t:"n", v:10000, z: tbl[4] }, // <-- Builtin format - C1: { t:"n", v:10000, z: tbl[164] } // <-- Custom format + A1: { t:"n", v:10000 }, // <-- General format + B1: { t:"n", v:10000, z: "0%" }, // <-- Builtin format + C1: { t:"n", v:10000, z: "\"T\"\ #0.00" } // <-- Custom format } } } diff --git a/docbits/82_util.md b/docbits/82_util.md index 83cd95f9478e9d4b7aba97562cf560832a22c976..aad8d8397c2d9feab0ed557616dd47384faf7dc2 100644 --- a/docbits/82_util.md +++ b/docbits/82_util.md @@ -135,8 +135,8 @@ the output will be encoded in codepage `1200` and the BOM will be prepended. ### JSON -`XLSX.utils.sheet_to_json` and the alias `XLSX.utils.sheet_to_row_object_array` -generate different types of JS objects. The function takes an options argument: +`XLSX.utils.sheet_to_json` generates different types of JS objects. The function +takes an options argument: | Option Name | Default | Description | | :---------- | :------: | :-------------------------------------------------- | diff --git a/docbits/90_test.md b/docbits/90_test.md index 490f784e58a65b217c91ce2c66a768cf3c0b0288..0e5cbff0969486af5688e7b685442d6ca9abe13d 100644 --- a/docbits/90_test.md +++ b/docbits/90_test.md @@ -61,6 +61,9 @@ $ open -a Chromium.app http://localhost:8000/stress.html ### Tested Environments +
+ (click to show) + - NodeJS 0.8, 0.9, 0.10, 0.11, 0.12, 4.x, 5.x, 6.x, 7.x - IE 6/7/8/9/10/11 (IE6-9 browsers require shims for interacting with client) - Chrome 24+ @@ -74,6 +77,8 @@ Tests utilize the mocha testing framework. Travis-CI and Sauce Labs links: - for XLS\* modules - for XLS\* modules using Sauce Labs +
+ ### Test Files Test files are housed in [another repo](https://github.com/SheetJS/test_files). diff --git a/docbits/99_badges.md b/docbits/99_badges.md deleted file mode 100644 index f8d2fb188f4cb640dc5ca4a92ee076bb478764b8..0000000000000000000000000000000000000000 --- a/docbits/99_badges.md +++ /dev/null @@ -1,17 +0,0 @@ -## Badges - -[![Build Status](https://saucelabs.com/browser-matrix/sheetjs.svg)](https://saucelabs.com/u/sheetjs) - -[![Build Status](https://travis-ci.org/SheetJS/js-xlsx.svg?branch=master)](https://travis-ci.org/SheetJS/js-xlsx) - -[![Build Status](https://semaphoreci.com/api/v1/sheetjs/js-xlsx/branches/master/shields_badge.svg)](https://semaphoreci.com/sheetjs/js-xlsx) - -[![Coverage Status](http://img.shields.io/coveralls/SheetJS/js-xlsx/master.svg)](https://coveralls.io/r/SheetJS/js-xlsx?branch=master) - -[![NPM Downloads](https://img.shields.io/npm/dt/xlsx.svg)](https://npmjs.org/package/xlsx) - -[![Dependencies Status](https://david-dm.org/sheetjs/js-xlsx/status.svg)](https://david-dm.org/sheetjs/js-xlsx) - -[![ghit.me](https://ghit.me/badge.svg?repo=sheetjs/js-xlsx)](https://ghit.me/repo/sheetjs/js-xlsx) - -[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx) diff --git a/index.html b/index.html index 97730c2327e5d624b7444999fc89c46d51dc83ad..659e319517edc003dca2a1040b784a34b70b973a 100644 --- a/index.html +++ b/index.html @@ -54,6 +54,9 @@ Use readAsBinaryString: (when available)