-
+
Source Code Repo
Issues? Something look weird? Click here and report an issue
diff --git a/demos/react/sheetjs.jsx b/demos/react/sheetjs.jsx
index c8216b9..4da567f 100644
--- a/demos/react/sheetjs.jsx
+++ b/demos/react/sheetjs.jsx
@@ -18,10 +18,11 @@ class SheetJSApp extends React.Component {
handleFile(file/*:File*/) {
/* Boilerplate to set up FileReader */
const reader = new FileReader();
+ const rABS = !!reader.readAsBinaryString;
reader.onload = (e) => {
/* Parse data */
const bstr = e.target.result;
- const wb = XLSX.read(bstr, {type:'binary'});
+ const wb = XLSX.read(bstr, {type:rABS ? 'binary' : 'array'});
/* Get first worksheet */
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
@@ -30,17 +31,15 @@ class SheetJSApp extends React.Component {
/* Update state */
this.setState({ data: data, cols: make_cols(ws['!ref']) });
};
- reader.readAsBinaryString(file);
+ if(rABS) reader.readAsBinaryString(file); else reader.readAsArrayBuffer(file);
};
exportFile() {
/* convert state to workbook */
const ws = XLSX.utils.aoa_to_sheet(this.state.data);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "SheetJS");
- /* generate XLSX file */
- const wbout = XLSX.write(wb, {type:"array", bookType:"xlsx"});
- /* send to client */
- saveAs(new Blob([wbout],{type:"application/octet-stream"}), "sheetjs.xlsx");
+ /* generate XLSX file and send to client */
+ XLSX.writeFile(wb, "sheetjs.xlsx")
};
render() { return (
@@ -137,4 +136,8 @@ const SheetJSFT = [
].map(function(x) { return "." + x; }).join(",");
/* generate an array of column objects */
-const make_cols = refstr => Array(XLSX.utils.decode_range(refstr).e.c + 1).fill(0).map((x,i) => ({name:XLSX.utils.encode_col(i), key:i}));
+const make_cols = refstr => {
+ let o = [], C = XLSX.utils.decode_range(refstr).e.c + 1;
+ for(var i = 0; i < C; ++i) o[i] = {name:XLSX.utils.encode_col(i), key:i}
+ return o;
+};
diff --git a/demos/server/README.md b/demos/server/README.md
index 2930e57..99308bf 100644
--- a/demos/server/README.md
+++ b/demos/server/README.md
@@ -33,6 +33,23 @@ var buf = fs.readFileSync("sheetjs.xlsx");
var wb = XLSX.read(buf, {type:'buffer'});
```
+### Responding to Form Uploads
+
+Using `formidable`, files uploaded to forms are stored to temporary files that
+can be read with `readFile`:
+
+```js
+/* within the server callback function(request, response) { */
+var form = new formidable.IncomingForm();
+form.parse(req, function(err, fields, files) {
+ var f = files[Object.keys(files)[0]];
+ var workbook = XLSX.readFile(f.path);
+ /* DO SOMETHING WITH workbook HERE */
+});
+```
+
+The `node.js` demo shows a plain HTTP server that accepts file uploads and
+converts data to requested output format.
### Example servers
diff --git a/demos/server/node.js b/demos/server/node.js
new file mode 100644
index 0000000..7b54d37
--- /dev/null
+++ b/demos/server/node.js
@@ -0,0 +1,84 @@
+/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
+
+var http = require('http');
+var XLSX = require('xlsx');
+var formidable = require('formidable');
+var html = "";
+var PORT = 3000;
+
+var extmap = {};
+
+var server = http.createServer(function(req, res) {
+ if(req.method !== 'POST') return res.end(html);
+ var form = new formidable.IncomingForm();
+ form.parse(req, function(err, fields, files) {
+ var f = files[Object.keys(files)[0]];
+ var wb = XLSX.readFile(f.path);
+ var ext = (fields.bookType || "xlsx").toLowerCase();
+ res.setHeader('Content-Disposition', 'attachment; filename="download.' + (extmap[ext] || ext) + '";');
+ res.end(XLSX.write(wb, {type:"buffer", bookType:ext}));
+ });
+}).listen(PORT);
+
+html = [
+'',
+'',
+'Upload a file to convert the contents to another format.',
+'',
+'Form Fields:',
+'- bookType: output format type (defaults to "XLSX")',
+'- basename: basename for output file (defaults to "download")',
+'',
+'
',
+'',
+'Form code:',
+'<form method="POST" enctype="multipart/form-data" action="/">',
+'<input type="file" id="file" name="file"/>',
+'<select name="bookType">',
+'<!-- options here -->',
+'</select>',
+'<input type="submit" value="Submit Form">',
+'</form>',
+'',
+'fetch Code:',
+'var blob = new Blob("1,2,3\\n4,5,6".split("")); // original file',
+'var fd = new FormData();',
+'fd.set("data", blob, "foo.bar");',
+'fd.set("bookType", "xlsb");',
+'var res = await fetch("/", {method:"POST", body:fd});',
+'var data = await res.arrayBuffer();',
+''
+].join("\n");
+
+extmap = {
+ "biff2" : "xls",
+ "biff5" : "xls",
+ "biff8" : "xls",
+ "xlml" : "xls"
+};
+console.log('listening on port ' + PORT);
diff --git a/demos/typescript/Makefile b/demos/typescript/Makefile
index 3ba92c6..13c67d4 100644
--- a/demos/typescript/Makefile
+++ b/demos/typescript/Makefile
@@ -1,3 +1,9 @@
.PHONY: all
all:
npm run build
+
+.PHONY: init
+init:
+ mkdir -p node_modules
+ npm install typescript
+ cd node_modules; ln -s ../../../ xlsx; cd -
diff --git a/demos/vue/README.md b/demos/vue/README.md
index 4380d50..78c90fe 100644
--- a/demos/vue/README.md
+++ b/demos/vue/README.md
@@ -101,8 +101,8 @@ The scripts should be treated as external resources in `nuxt.config.js`:
module.exports = {
head: {
script: [
- { src: "https://unpkg.com/xlsx/dist/xlsx.full.min.js" }, // library
- { src: "https://unpkg.com/file-saver/FileSaver.js" } // saveAs shim
+ { src: "https://unpkg.com/xlsx/dist/shim.min.js" },
+ { src: "https://unpkg.com/xlsx/dist/xlsx.full.min.js" }
]
}
};
diff --git a/demos/vue/SheetJS-vue.js b/demos/vue/SheetJS-vue.js
index 0e6c546..e508434 100644
--- a/demos/vue/SheetJS-vue.js
+++ b/demos/vue/SheetJS-vue.js
@@ -55,11 +55,8 @@ Vue.component('html-preview', {
onexport: function(evt) {
/* generate workbook object from table */
var wb = XLSX.utils.table_to_book(document.getElementById('out-table'));
- /* get binary string as output */
- var wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
-
- /* force a download */
- saveAs(new Blob([wbout], { type: 'application/octet-stream' }), "sheetjs.xlsx");
+ /* generate file and force a download*/
+ XLSX.writeFile(wb, "sheetjs.xlsx");
}
}
});
diff --git a/demos/vue/index.html b/demos/vue/index.html
index 3957bfe..67cdaa6 100644
--- a/demos/vue/index.html
+++ b/demos/vue/index.html
@@ -7,8 +7,8 @@
-
-
+
+
diff --git a/demos/vue/nuxt.config.js b/demos/vue/nuxt.config.js
index b02cf96..9fddd9c 100644
--- a/demos/vue/nuxt.config.js
+++ b/demos/vue/nuxt.config.js
@@ -1,9 +1,10 @@
module.exports = {
head: {
script: [
- // { src: "https://unpkg.com/xlsx/dist/xlsx.full.min.js" }, // CDN
- { src: "xlsx.full.min.js" }, // development
- { src: "https://unpkg.com/file-saver/FileSaver.js" }
+ // { src: "https://unpkg.com/xlsx/dist/shim.min.js" }, // CDN
+ // { src: "https://unpkg.com/xlsx/dist/xlsx.full.min.js" } // CDN
+ { src: "shim.js" }, // development
+ { src: "xlsx.full.min.js" } // development
]
}
};
diff --git a/demos/vue/pages/index.vue b/demos/vue/pages/index.vue
index 14537d4..0dedc48 100644
--- a/demos/vue/pages/index.vue
+++ b/demos/vue/pages/index.vue
@@ -66,10 +66,8 @@ export default {
const ws = XLSX.utils.aoa_to_sheet(this.data);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "SheetJS");
- /* generate X file */
- const wbout = XLSX.write(wb, {type:"array", bookType:"xlsx"});
- /* send to client */
- saveAs(new Blob([wbout],{type:"application/octet-stream"}), "sheetjs.xlsx");
+ /* generate file and send to client */
+ XLSX.writeFile(wb, "sheetjs.xlsx");
},
_file(file) {
/* Boilerplate to set up FileReader */
diff --git a/demos/vue/shim.js b/demos/vue/shim.js
new file mode 120000
index 0000000..7ec5819
--- /dev/null
+++ b/demos/vue/shim.js
@@ -0,0 +1 @@
+../../shim.js
\ No newline at end of file
diff --git a/demos/vue/static/shim.js b/demos/vue/static/shim.js
new file mode 120000
index 0000000..d672390
--- /dev/null
+++ b/demos/vue/static/shim.js
@@ -0,0 +1 @@
+../shim.js
\ No newline at end of file
diff --git a/demos/xhr/README.md b/demos/xhr/README.md
index aaa80dd..cea1924 100644
--- a/demos/xhr/README.md
+++ b/demos/xhr/README.md
@@ -87,7 +87,7 @@ The upload portion only differs in the actual request command:
superagent.post("/upload").send(fd);
```
-### superagent Wrapper Library
+### axios Wrapper Library
The `axios` library presents a Promise interface. The axios demo uses a single
promise, but for production deployments it may make sense to separate parsing:
diff --git a/dist/shim.min.js b/dist/shim.min.js
index ef31ade..e240a7f 100644
--- a/dist/shim.min.js
+++ b/dist/shim.min.js
@@ -1,2 +1,2 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
-if(!Object.keys){Object.keys=function(){var r=Object.prototype.hasOwnProperty,t=!{toString:null}.propertyIsEnumerable("toString"),e=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],n=e.length;return function(i){if(typeof i!=="object"&&typeof i!=="function"||i===null)throw new TypeError("Object.keys called on non-object");var o=[];for(var f in i){if(r.call(i,f))o.push(f)}if(t){for(var a=0;a>>0;if(typeof r!="function")throw new TypeError;var n=[];var i=arguments[1];for(var o=0;o>>0;if(typeof r!=="function")throw new TypeError;var n=arguments.length>=2?arguments[1]:void 0;for(var i=0;i>>0;if(typeof r!=="function"){throw new TypeError(r+" is not a function")}if(t){e=t}n=new Array(f);i=0;while(i>>0;t=+t||0;if(Math.abs(t)===Infinity){t=0}if(t<0){t+=e;if(t<0){t=0}}for(;t=e||r>=t){return new ArrayBuffer(0)}var n=Math.min(e-r,t-r);var i=new ArrayBuffer(n);var o=new Uint8Array(i);o.set(new Uint8Array(this,r,n));return i}}(function(){var r=typeof exports!="undefined"?exports:typeof self!="undefined"?self:$.global;var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";function e(r){this.message=r}e.prototype=new Error;e.prototype.name="InvalidCharacterError";r.btoa||(r.btoa=function(r){var n=String(r);for(var i,o,f=0,a=t,s="";n.charAt(f|0)||(a="=",f%1);s+=a.charAt(63&i>>8-f%1*8)){o=n.charCodeAt(f+=3/4);if(o>255){throw new e("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.")}i=i<<8|o}return s});r.atob||(r.atob=function(r){var n=String(r).replace(/[=]+$/,"");if(n.length%4==1){throw new e("'atob' failed: The string to be decoded is not correctly encoded.")}for(var i=0,o,f,a=0,s="";f=n.charAt(a++);~f&&(o=i%4?o*64+f:f,i++%4)?s+=String.fromCharCode(255&o>>(-2*i&6)):0){f=t.indexOf(f)}return s})})();if(!Date.prototype.toISOString){(function(){function r(r){if(r<10){return"0"+r}return r}Date.prototype.toISOString=function(){return this.getUTCFullYear()+"-"+r(this.getUTCMonth()+1)+"-"+r(this.getUTCDate())+"T"+r(this.getUTCHours())+":"+r(this.getUTCMinutes())+":"+r(this.getUTCSeconds())+"."+(this.getUTCMilliseconds()/1e3).toFixed(3).slice(2,5)+"Z"}})()}if(typeof Uint8Array!=="undefined"&&!Uint8Array.prototype.slice)Uint8Array.prototype.slice=function(r,t){if(r<0){r+=this.length;if(r<0)r=0}if(r>=this.length)return new Uint8Array(0);if(t==null)t=this.length;if(t<0){t+=this.length;if(t<0)t=0}if(t>this.length)t=this.length;var e=new Uint8Array(t-r);while(r<=--t)e[t-r]=this[t];return e};
\ No newline at end of file
+if(!Object.keys){Object.keys=function(){var t=Object.prototype.hasOwnProperty,r=!{toString:null}.propertyIsEnumerable("toString"),e=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],n=e.length;return function(i){if(typeof i!=="object"&&typeof i!=="function"||i===null)throw new TypeError("Object.keys called on non-object");var o=[];for(var a in i){if(t.call(i,a))o.push(a)}if(r){for(var f=0;f>>0;if(typeof t!="function")throw new TypeError;var n=[];var i=arguments[1];for(var o=0;o>>0;if(typeof t!=="function")throw new TypeError;var n=arguments.length>=2?arguments[1]:void 0;for(var i=0;i>>0;if(typeof t!=="function"){throw new TypeError(t+" is not a function")}if(r){e=r}n=new Array(a);i=0;while(i>>0;r=+r||0;if(Math.abs(r)===Infinity){r=0}if(r<0){r+=e;if(r<0){r=0}}for(;r=e||t>=r){return new ArrayBuffer(0)}var n=Math.min(e-t,r-t);var i=new ArrayBuffer(n);var o=new Uint8Array(i);o.set(new Uint8Array(this,t,n));return i}}(function(){var t=typeof exports!="undefined"?exports:typeof self!="undefined"?self:$.global;var r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";function e(t){this.message=t}e.prototype=new Error;e.prototype.name="InvalidCharacterError";t.btoa||(t.btoa=function(t){var n=String(t);for(var i,o,a=0,f=r,l="";n.charAt(a|0)||(f="=",a%1);l+=f.charAt(63&i>>8-a%1*8)){o=n.charCodeAt(a+=3/4);if(o>255){throw new e("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.")}i=i<<8|o}return l});t.atob||(t.atob=function(t){var n=String(t).replace(/[=]+$/,"");if(n.length%4==1){throw new e("'atob' failed: The string to be decoded is not correctly encoded.")}for(var i=0,o,a,f=0,l="";a=n.charAt(f++);~a&&(o=i%4?o*64+a:a,i++%4)?l+=String.fromCharCode(255&o>>(-2*i&6)):0){a=r.indexOf(a)}return l})})();if(!Date.prototype.toISOString){(function(){function t(t){if(t<10){return"0"+t}return t}Date.prototype.toISOString=function(){return this.getUTCFullYear()+"-"+t(this.getUTCMonth()+1)+"-"+t(this.getUTCDate())+"T"+t(this.getUTCHours())+":"+t(this.getUTCMinutes())+":"+t(this.getUTCSeconds())+"."+(this.getUTCMilliseconds()/1e3).toFixed(3).slice(2,5)+"Z"}})()}if(typeof Uint8Array!=="undefined"&&!Uint8Array.prototype.slice)Uint8Array.prototype.slice=function(t,r){if(t<0){t+=this.length;if(t<0)t=0}if(t>=this.length)return new Uint8Array(0);if(r==null)r=this.length;if(r<0){r+=this.length;if(r<0)r=0}if(r>this.length)r=this.length;var e=new Uint8Array(r-t);while(t<=--r)e[r-t]=this[r];return e};var IE_SaveFile=function(){try{if(typeof IE_SaveFile_Impl=="undefined")document.write(['
+
+
+
diff --git a/tests/write.js b/tests/write.js
index dd1c28e..abb48b8 100644
--- a/tests/write.js
+++ b/tests/write.js
@@ -1,7 +1,9 @@
/* writing feature test -- look for TEST: in comments */
/* vim: set ts=2 ft=javascript: */
-var ext = !!process.argv[2];
+if(typeof console === 'undefined') console = {log: function(){}};
+
+var ext = typeof process !== 'undefined' && !!process.argv[2];
/* original data */
var data = [
@@ -191,9 +193,21 @@ var filenames = [
['sheetjs.prn']
];
+var OUT = ["base64", "binary", "string", "array"];
+if(typeof Buffer !== 'undefined') OUT.push("buffer");
filenames.forEach(function(r) {
- /* write file */
- XLSX.writeFile(wb, r[0], r[1]);
- /* test by reading back files */
- XLSX.readFile(r[0]);
+ /* write file */
+ XLSX.writeFile(wb, r[0], r[1]);
+ /* test by reading back files */
+ if(typeof process !== 'undefined') XLSX.readFile(r[0]);
+
+ var ext = r[1] && r[1].bookType || r[0].split(".")[1];
+ ext = {"htm":"html"}[ext] || ext;
+ OUT.forEach(function(type) {
+ if(type == "string" && ["xlsx", "xlsm", "xlsb", "xlam", "biff8", "biff5", "xla", "ods", "dbf"].indexOf(ext) > -1) return;
+ if(type == "array" && ["xlsx", "xlsm", "xlsb", "xlam", "ods"].indexOf(ext) > -1 && typeof Uint8Array === 'undefined') return;
+ var datout = XLSX.write(wb, {type: type, bookType: ext, sheet:r[1] && r[1].sheet || null});
+ XLSX.read(datout, {type:type});
+ if(type == "array") console.log(ext, datout);
+ });
});
diff --git a/types/index.d.ts b/types/index.d.ts
index 4d65b20..5417128 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -10,11 +10,11 @@ export const SSF: any;
/** CFB Library */
export const CFB: any;
-/** Attempts to read filename and parse */
+/** NODE ONLY! Attempts to read filename and parse */
export function readFile(filename: string, opts?: ParsingOptions): WorkBook;
/** Attempts to parse data */
export function read(data: any, opts?: ParsingOptions): WorkBook;
-/** NODE ONLY! Attempts to write workbook data to filename */
+/** Attempts to write or download workbook data to file */
export function writeFile(data: WorkBook, filename: string, opts?: WritingOptions): any;
/** Attempts to write the workbook data */
export function write(data: WorkBook, opts?: WritingOptions): any;
@@ -602,6 +602,9 @@ export interface OriginOption {
}
export interface Sheet2HTMLOpts {
+ /** TABLE element id attribute */
+ id?: string;
+
/** Add contenteditable to every cell */
editable?: boolean;
diff --git a/xlsx.flow.js b/xlsx.flow.js
index 6f8a053..01894f0 100644
--- a/xlsx.flow.js
+++ b/xlsx.flow.js
@@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
-XLSX.version = '0.11.18';
+XLSX.version = '0.11.19';
var current_codepage = 1200, current_ansi = 1252;
/*:: declare var cptable:any; */
/*global cptable:true */
@@ -141,11 +141,16 @@ function s2ab(s/*:string*/) {
return buf;
}
-function arr2str(data/*:any*/)/*:string*/ {
+function a2s(data/*:any*/)/*:string*/ {
if(Array.isArray(data)) return data.map(_chr).join("");
var o/*:Array*/ = []; for(var i = 0; i < data.length; ++i) o[i] = _chr(data[i]); return o.join("");
}
+function a2u(data/*:Array*/)/*:Uint8Array*/ {
+ if(typeof Uint8Array === 'undefined') throw new Error("Unsupported");
+ return new Uint8Array(data);
+}
+
function ab2a(data/*:ArrayBuffer|Uint8Array*/)/*:Array*/ {
if(typeof ArrayBuffer == 'undefined') throw new Error("Unsupported");
if(data instanceof ArrayBuffer) return ab2a(new Uint8Array(data));
@@ -1853,6 +1858,43 @@ return exports;
})();
if(typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO_NOT_EXPORT_CFB === 'undefined') { module.exports = CFB; }
+var _fs;
+if(typeof require !== 'undefined') try { _fs = require('fs'); } catch(e) {}
+
+/* normalize data for blob ctor */
+function blobify(data) {
+ if(typeof data === "string") return s2ab(data);
+ if(Array.isArray(data)) return a2u(data);
+ return data;
+}
+/* write or download file */
+function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
+ /*global IE_SaveFile, Blob, navigator, saveAs, URL, document */
+ if(typeof _fs !== 'undefined' && _fs.writeFileSync) return enc ? _fs.writeFileSync(fname, payload, enc) : _fs.writeFileSync(fname, payload);
+ var data = (enc == "utf8") ? utf8write(payload) : payload;
+ /*:: declare var IE_SaveFile: any; */
+ if(typeof IE_SaveFile !== 'undefined') return IE_SaveFile(data, fname);
+ if(typeof Blob !== 'undefined') {
+ var blob = new Blob([blobify(data)], {type:"application/octet-stream"});
+ /*:: declare var navigator: any; */
+ if(typeof navigator !== 'undefined' && navigator.msSaveBlob) return navigator.msSaveBlob(blob, fname);
+ /*:: declare var saveAs: any; */
+ if(typeof saveAs !== 'undefined') return saveAs(blob, fname);
+ if(typeof URL !== 'undefined' && typeof document !== 'undefined' && document.createElement && URL.createObjectURL) {
+ var a = document.createElement("a");
+ if(a.download != null) {
+ var url = URL.createObjectURL(blob);
+ /*:: if(document.body == null) throw new Error("unreachable"); */
+ a.download = fname; a.href = url; document.body.appendChild(a); a.click();
+ /*:: if(document.body == null) throw new Error("unreachable"); */ document.body.removeChild(a);
+ if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
+ return url;
+ }
+ }
+ }
+ throw new Error("cannot initiate download");
+}
+
function keys(o/*:any*/)/*:Array*/ { return Object.keys(o); }
function evert_key(obj/*:any*/, key/*:string*/)/*:EvertType*/ {
@@ -2045,14 +2087,13 @@ function getzipstr(zip, file/*:string*/, safe/*:?boolean*/)/*:?string*/ {
try { return getzipstr(zip, file); } catch(e) { return null; }
}
-var _fs, jszip;
+var jszip;
/*:: declare var JSZip:any; */
/*global JSZip:true */
if(typeof JSZip !== 'undefined') jszip = JSZip;
-if (typeof exports !== 'undefined') {
- if (typeof module !== 'undefined' && module.exports) {
+if(typeof exports !== 'undefined') {
+ if(typeof module !== 'undefined' && module.exports) {
if(typeof jszip === 'undefined') jszip = require('./jszip.js');
- try { _fs = require('fs'); } catch(e) { }
}
}
@@ -13378,6 +13419,7 @@ function check_wb_names(N) {
}
function check_wb(wb) {
if(!wb || !wb.SheetNames || !wb.Sheets) throw new Error("Invalid Workbook");
+ if(!wb.SheetNames.length) throw new Error("Workbook is empty");
check_wb_names(wb.SheetNames);
/* TODO: validate workbook */
}
@@ -14821,7 +14863,7 @@ function parse_xlml(data/*:RawBytes|string*/, opts)/*:Workbook*/ {
switch(opts.type||"base64") {
case "base64": return parse_xlml_xml(Base64.decode(data), opts);
case "binary": case "buffer": case "file": return parse_xlml_xml(data, opts);
- case "array": return parse_xlml_xml(arr2str(data), opts);
+ case "array": return parse_xlml_xml(a2s(data), opts);
}
/*:: throw new Error("unsupported type " + opts.type); */
}
@@ -17641,9 +17683,9 @@ var HTML_ = (function() {
var preamble = "";
return preamble + oo.join("") + "
";
}
- function make_html_preamble(/*::ws:Worksheet, R:Range, o:Sheet2HTMLOpts*/)/*:string*/ {
+ function make_html_preamble(ws/*:Worksheet*/, R/*:Range*/, o/*:Sheet2HTMLOpts*/)/*:string*/ {
var out/*:Array*/ = [];
- return out.join("") + '';
+ return out.join("") + '';
}
var _BEGIN = 'SheetJS Table Export';
var _END = '';
@@ -19010,7 +19052,6 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
case 0x0A: case 0x0D: case 0x20: return read_plaintext_raw(d, o);
}
if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
- if(0x20>n[0]||n[0]>0x7F) throw new Error("Unsupported file " + n.join("|"));
return read_prn(data, d, o, str);
}
@@ -19026,12 +19067,12 @@ function write_zip_type(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:any*/ {
switch(o.type) {
case "base64": oopts.type = "base64"; break;
case "binary": oopts.type = "string"; break;
- case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
+ case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files");
case "buffer":
- case "file": oopts.type = "nodebuffer"; break;
+ case "file": oopts.type = has_buf ? "nodebuffer" : "string"; break;
default: throw new Error("Unrecognized type " + o.type);
}
- if(o.type === "file") return _fs.writeFileSync(o.file, z.generate(oopts));
+ if(o.type === "file") return write_dl(o.file, z.generate(oopts));
var out = z.generate(oopts);
// $FlowIgnore
return o.type == "string" ? utf8read(out) : out;
@@ -19043,8 +19084,8 @@ function write_cfb_type(wb/*:Workbook*/, opts/*:?WriteOpts*/)/*:any*/ {
switch(o.type) {
case "base64": case "binary": break;
case "buffer": case "array": o.type = ""; break;
- case "file": return _fs.writeFileSync(o.file, CFB.write(cfb, {type:'buffer'}));
- case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
+ case "file": return write_dl(o.file, CFB.write(cfb, {type:has_buf ? 'buffer' : ""}));
+ case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files");
default: throw new Error("Unrecognized type " + o.type);
}
return CFB.write(cfb, o);
@@ -19057,7 +19098,7 @@ function write_string_type(out/*:string*/, opts/*:WriteOpts*/, bom/*:?string*/)/
case "base64": return Base64.encode(utf8write(o));
case "binary": return utf8write(o);
case "string": return out;
- case "file": return _fs.writeFileSync(opts.file, o, 'utf8');
+ case "file": return write_dl(opts.file, o, 'utf8');
case "buffer": {
if(has_buf) return new Buffer(o, 'utf8');
else return write_string_type(o, {type:'binary'}).split("").map(function(c) { return c.charCodeAt(0); });
@@ -19071,7 +19112,7 @@ function write_stxt_type(out/*:string*/, opts/*:WriteOpts*/)/*:any*/ {
case "base64": return Base64.encode(out);
case "binary": return out;
case "string": return out; /* override in sheet_to_txt */
- case "file": return _fs.writeFileSync(opts.file, out, 'binary');
+ case "file": return write_dl(opts.file, out, 'binary');
case "buffer": {
if(has_buf) return new Buffer(out, 'binary');
else return out.split("").map(function(c) { return c.charCodeAt(0); });
@@ -19090,7 +19131,7 @@ function write_binary_type(out, opts/*:WriteOpts*/)/*:any*/ {
// $FlowIgnore
for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]);
return opts.type == 'base64' ? Base64.encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr;
- case "file": return _fs.writeFileSync(opts.file, out);
+ case "file": return write_dl(opts.file, out);
case "buffer": return out;
default: throw new Error("Unrecognized type " + opts.type);
}
@@ -19293,7 +19334,7 @@ function sheet_to_txt(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/) {
var s = sheet_to_csv(sheet, opts);
if(typeof cptable == 'undefined' || opts.type == 'string') return s;
var o = cptable.utils.encode(1200, s, 'str');
- return "\xff\xfe" + o;
+ return String.fromCharCode(255) + String.fromCharCode(254) + o;
}
function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array*/ {
diff --git a/xlsx.js b/xlsx.js
index 6e53d16..893da3f 100644
--- a/xlsx.js
+++ b/xlsx.js
@@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
-XLSX.version = '0.11.18';
+XLSX.version = '0.11.19';
var current_codepage = 1200, current_ansi = 1252;
/*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@@ -140,11 +140,16 @@ function s2ab(s) {
return buf;
}
-function arr2str(data) {
+function a2s(data) {
if(Array.isArray(data)) return data.map(_chr).join("");
var o = []; for(var i = 0; i < data.length; ++i) o[i] = _chr(data[i]); return o.join("");
}
+function a2u(data) {
+ if(typeof Uint8Array === 'undefined') throw new Error("Unsupported");
+ return new Uint8Array(data);
+}
+
function ab2a(data) {
if(typeof ArrayBuffer == 'undefined') throw new Error("Unsupported");
if(data instanceof ArrayBuffer) return ab2a(new Uint8Array(data));
@@ -1782,6 +1787,39 @@ return exports;
})();
if(typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO_NOT_EXPORT_CFB === 'undefined') { module.exports = CFB; }
+var _fs;
+if(typeof require !== 'undefined') try { _fs = require('fs'); } catch(e) {}
+
+/* normalize data for blob ctor */
+function blobify(data) {
+ if(typeof data === "string") return s2ab(data);
+ if(Array.isArray(data)) return a2u(data);
+ return data;
+}
+/* write or download file */
+function write_dl(fname, payload, enc) {
+ /*global IE_SaveFile, Blob, navigator, saveAs, URL, document */
+ if(typeof _fs !== 'undefined' && _fs.writeFileSync) return enc ? _fs.writeFileSync(fname, payload, enc) : _fs.writeFileSync(fname, payload);
+ var data = (enc == "utf8") ? utf8write(payload) : payload;
+if(typeof IE_SaveFile !== 'undefined') return IE_SaveFile(data, fname);
+ if(typeof Blob !== 'undefined') {
+ var blob = new Blob([blobify(data)], {type:"application/octet-stream"});
+if(typeof navigator !== 'undefined' && navigator.msSaveBlob) return navigator.msSaveBlob(blob, fname);
+if(typeof saveAs !== 'undefined') return saveAs(blob, fname);
+ if(typeof URL !== 'undefined' && typeof document !== 'undefined' && document.createElement && URL.createObjectURL) {
+ var a = document.createElement("a");
+ if(a.download != null) {
+ var url = URL.createObjectURL(blob);
+a.download = fname; a.href = url; document.body.appendChild(a); a.click();
+document.body.removeChild(a);
+ if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
+ return url;
+ }
+ }
+ }
+ throw new Error("cannot initiate download");
+}
+
function keys(o) { return Object.keys(o); }
function evert_key(obj, key) {
@@ -1973,13 +2011,12 @@ function getzipstr(zip, file, safe) {
try { return getzipstr(zip, file); } catch(e) { return null; }
}
-var _fs, jszip;
+var jszip;
/*global JSZip:true */
if(typeof JSZip !== 'undefined') jszip = JSZip;
-if (typeof exports !== 'undefined') {
- if (typeof module !== 'undefined' && module.exports) {
+if(typeof exports !== 'undefined') {
+ if(typeof module !== 'undefined' && module.exports) {
if(typeof jszip === 'undefined') jszip = require('./jszip.js');
- try { _fs = require('fs'); } catch(e) { }
}
}
@@ -13286,6 +13323,7 @@ function check_wb_names(N) {
}
function check_wb(wb) {
if(!wb || !wb.SheetNames || !wb.Sheets) throw new Error("Invalid Workbook");
+ if(!wb.SheetNames.length) throw new Error("Workbook is empty");
check_wb_names(wb.SheetNames);
/* TODO: validate workbook */
}
@@ -14723,7 +14761,7 @@ function parse_xlml(data, opts) {
switch(opts.type||"base64") {
case "base64": return parse_xlml_xml(Base64.decode(data), opts);
case "binary": case "buffer": case "file": return parse_xlml_xml(data, opts);
- case "array": return parse_xlml_xml(arr2str(data), opts);
+ case "array": return parse_xlml_xml(a2s(data), opts);
}
}
@@ -17536,9 +17574,9 @@ var HTML_ = (function() {
var preamble = "";
return preamble + oo.join("") + "
";
}
- function make_html_preamble() {
+ function make_html_preamble(ws, R, o) {
var out = [];
- return out.join("") + '';
+ return out.join("") + '';
}
var _BEGIN = 'SheetJS Table Export';
var _END = '';
@@ -18899,7 +18937,6 @@ function readSync(data, opts) {
case 0x0A: case 0x0D: case 0x20: return read_plaintext_raw(d, o);
}
if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
- if(0x20>n[0]||n[0]>0x7F) throw new Error("Unsupported file " + n.join("|"));
return read_prn(data, d, o, str);
}
@@ -18915,12 +18952,12 @@ function write_zip_type(wb, opts) {
switch(o.type) {
case "base64": oopts.type = "base64"; break;
case "binary": oopts.type = "string"; break;
- case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
+ case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files");
case "buffer":
- case "file": oopts.type = "nodebuffer"; break;
+ case "file": oopts.type = has_buf ? "nodebuffer" : "string"; break;
default: throw new Error("Unrecognized type " + o.type);
}
- if(o.type === "file") return _fs.writeFileSync(o.file, z.generate(oopts));
+ if(o.type === "file") return write_dl(o.file, z.generate(oopts));
var out = z.generate(oopts);
// $FlowIgnore
return o.type == "string" ? utf8read(out) : out;
@@ -18932,8 +18969,8 @@ function write_cfb_type(wb, opts) {
switch(o.type) {
case "base64": case "binary": break;
case "buffer": case "array": o.type = ""; break;
- case "file": return _fs.writeFileSync(o.file, CFB.write(cfb, {type:'buffer'}));
- case "string": throw new Error("'string' output type invalid for '" + o.bookType + ' files');
+ case "file": return write_dl(o.file, CFB.write(cfb, {type:has_buf ? 'buffer' : ""}));
+ case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files");
default: throw new Error("Unrecognized type " + o.type);
}
return CFB.write(cfb, o);
@@ -18946,7 +18983,7 @@ function write_string_type(out, opts, bom) {
case "base64": return Base64.encode(utf8write(o));
case "binary": return utf8write(o);
case "string": return out;
- case "file": return _fs.writeFileSync(opts.file, o, 'utf8');
+ case "file": return write_dl(opts.file, o, 'utf8');
case "buffer": {
if(has_buf) return new Buffer(o, 'utf8');
else return write_string_type(o, {type:'binary'}).split("").map(function(c) { return c.charCodeAt(0); });
@@ -18960,7 +18997,7 @@ function write_stxt_type(out, opts) {
case "base64": return Base64.encode(out);
case "binary": return out;
case "string": return out; /* override in sheet_to_txt */
- case "file": return _fs.writeFileSync(opts.file, out, 'binary');
+ case "file": return write_dl(opts.file, out, 'binary');
case "buffer": {
if(has_buf) return new Buffer(out, 'binary');
else return out.split("").map(function(c) { return c.charCodeAt(0); });
@@ -18979,7 +19016,7 @@ function write_binary_type(out, opts) {
// $FlowIgnore
for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]);
return opts.type == 'base64' ? Base64.encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr;
- case "file": return _fs.writeFileSync(opts.file, out);
+ case "file": return write_dl(opts.file, out);
case "buffer": return out;
default: throw new Error("Unrecognized type " + opts.type);
}
@@ -19182,7 +19219,7 @@ function sheet_to_txt(sheet, opts) {
var s = sheet_to_csv(sheet, opts);
if(typeof cptable == 'undefined' || opts.type == 'string') return s;
var o = cptable.utils.encode(1200, s, 'str');
- return "\xff\xfe" + o;
+ return String.fromCharCode(255) + String.fromCharCode(254) + o;
}
function sheet_to_formulae(sheet) {