forked from sheetjs/sheetjs
version bump 0.11.19: browser writeFile
- IE6-9 ActiveX + VBScript shim - `writeFile` supported in browser - `oldie` demo for IE write strategies
This commit is contained in:
parent
edf7150ca8
commit
75845a0ca7
@ -36,7 +36,6 @@ CDNjs
|
||||
CommonJS
|
||||
Ethercalc
|
||||
ExtendScript
|
||||
FileSaver
|
||||
IndexedDB
|
||||
JavaScriptCore
|
||||
LocalStorage
|
||||
@ -58,6 +57,7 @@ webpack
|
||||
weex
|
||||
|
||||
# Other terms
|
||||
ActiveX
|
||||
APIs
|
||||
ArrayBuffer
|
||||
Base64
|
||||
@ -66,6 +66,7 @@ JS
|
||||
NoSQL
|
||||
README
|
||||
UTF-16
|
||||
VBScript
|
||||
XHR
|
||||
XMLHttpRequest
|
||||
bundler
|
||||
|
@ -4,6 +4,10 @@ This log is intended to keep track of backwards-incompatible changes, including
|
||||
but not limited to API changes and file location changes. Minor behavioral
|
||||
changes may not be included if they are not expected to break existing code.
|
||||
|
||||
## 0.11.19
|
||||
|
||||
* Error on empty workbook
|
||||
|
||||
## 0.11.16 (2017-12-30)
|
||||
|
||||
* XLS ANSI/CP separation
|
||||
|
94
README.md
94
README.md
@ -215,6 +215,7 @@ The [`demos` directory](demos/) includes sample projects for:
|
||||
- [`Headless Browsers`](demos/headless/)
|
||||
- [`canvas-datagrid`](demos/datagrid/)
|
||||
- [`Swift JSC and other engines`](demos/altjs/)
|
||||
- [`internet explorer`](demos/oldie/)
|
||||
|
||||
### Optional Modules
|
||||
|
||||
@ -339,7 +340,7 @@ var worksheet = XLSX.read(htmlstr, {type:'string'});
|
||||
<summary><b>Browser download file (ajax)</b> (click to show)</summary>
|
||||
|
||||
Note: for a more complete example that works in older browsers, check the demo
|
||||
at <http://oss.sheetjs.com/js-xlsx/ajax.html>). The <demos/xhr/> directory also
|
||||
at <http://oss.sheetjs.com/js-xlsx/ajax.html>). The [`xhr` demo](demos/xhr/)
|
||||
includes more examples with `XMLHttpRequest` and `fetch`.
|
||||
|
||||
```js
|
||||
@ -414,6 +415,8 @@ input_dom_element.addEventListener('change', handleFile, false);
|
||||
|
||||
</details>
|
||||
|
||||
More specialized cases, including mobile app file processing, are covered in the
|
||||
[included demos](demos/)
|
||||
|
||||
### Parsing Examples
|
||||
|
||||
@ -590,8 +593,7 @@ Assuming `workbook` is a workbook object:
|
||||
<details>
|
||||
<summary><b>nodejs write a file</b> (click to show)</summary>
|
||||
|
||||
`writeFile` is only available in server environments. Browsers have no API for
|
||||
writing arbitrary files given a path, so another strategy must be used.
|
||||
`XLSX.writeFile` uses `fs.writeFileSync` in server environments:
|
||||
|
||||
```js
|
||||
if(typeof require !== 'undefined') XLSX = require('xlsx');
|
||||
@ -603,7 +605,7 @@ XLSX.writeFile(workbook, 'out.xlsb');
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Browser add to web page</b> (click to show)</summary>
|
||||
<summary><b>Browser add TABLE element to page</b> (click to show)</summary>
|
||||
|
||||
The `sheet_to_html` utility function generates HTML code that can be added to
|
||||
any DOM element.
|
||||
@ -614,29 +616,10 @@ var container = document.getElementById('tableau');
|
||||
container.innerHTML = XLSX.utils.sheet_to_html(worksheet);
|
||||
```
|
||||
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Browser save file</b> (click to show)</summary>
|
||||
|
||||
Note: browser generates binary blob and forces a "download" to client. This
|
||||
example uses [FileSaver](https://github.com/eligrey/FileSaver.js/):
|
||||
|
||||
```js
|
||||
/* bookType can be any supported output type */
|
||||
var wopts = { bookType:'xlsx', bookSST:false, type:'array' };
|
||||
|
||||
var wbout = XLSX.write(workbook,wopts);
|
||||
|
||||
/* the saveAs call downloads a file on the local machine */
|
||||
saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx");
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Browser upload to server</b> (click to show)</summary>
|
||||
<summary><b>Browser upload file (ajax)</b> (click to show)</summary>
|
||||
|
||||
A complete example using XHR is [included in the XHR demo](demos/xhr/), along
|
||||
with examples for fetch and wrapper libraries. This example assumes the server
|
||||
@ -658,6 +641,65 @@ req.send(formdata);
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Browser save file</b> (click to show)</summary>
|
||||
|
||||
`XLSX.writeFile` wraps a few techniques for triggering a file save:
|
||||
|
||||
- `URL` browser API creates an object URL for the file, which the library uses
|
||||
by creating a link and forcing a click. It is supported in modern browsers.
|
||||
- `msSaveBlob` is an IE10+ API for triggering a file save.
|
||||
- `IE_FileSave` uses VBScript and ActiveX to write a file in IE6+ for Windows
|
||||
XP and Windows 7. The shim must be included in the containing HTML page.
|
||||
|
||||
There is no standard way to determine if the actual file has been downloaded.
|
||||
|
||||
```js
|
||||
/* output format determined by filename */
|
||||
XLSX.writeFile(workbook, 'out.xlsb');
|
||||
/* at this point, out.xlsb will have been downloaded */
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Browser save file (compatibility)</b> (click to show)</summary>
|
||||
|
||||
`XLSX.writeFile` techniques work for most modern browsers as well as older IE.
|
||||
For much older browsers, there are workarounds implemented by wrapper libraries.
|
||||
|
||||
[`FileSaver.js`](https://github.com/eligrey/FileSaver.js/) implements `saveAs`.
|
||||
Note: `XLSX.writeFile` will automatically call `saveAs` if available.
|
||||
|
||||
```js
|
||||
/* bookType can be any supported output type */
|
||||
var wopts = { bookType:'xlsx', bookSST:false, type:'array' };
|
||||
|
||||
var wbout = XLSX.write(workbook,wopts);
|
||||
|
||||
/* the saveAs call downloads a file on the local machine */
|
||||
saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx");
|
||||
```
|
||||
|
||||
[`Downloadify`](https://github.com/dcneiner/downloadify) uses a Flash SWF button
|
||||
to generate local files, suitable for environments where ActiveX is unavailable:
|
||||
|
||||
```js
|
||||
Downloadify.create(id,{
|
||||
/* other options are required! read the downloadify docs for more info */
|
||||
filename: "test.xlsx",
|
||||
data: function() { return XLSX.write(wb, {bookType:"xlsx", type:'base64'}); },
|
||||
append: false,
|
||||
dataType: 'base64'
|
||||
});
|
||||
```
|
||||
|
||||
The [`oldie` demo](demos/oldie/) shows an IE-compatible fallback scenario.
|
||||
|
||||
</details>
|
||||
|
||||
The [included demos](demos/) cover mobile apps and other special deployments.
|
||||
|
||||
### Writing Examples
|
||||
|
||||
- <http://sheetjs.com/demos/table.html> exporting an HTML table
|
||||
@ -705,7 +747,8 @@ Parse options are described in the [Parsing Options](#parsing-options) section.
|
||||
|
||||
`XLSX.write(wb, write_opts)` attempts to write the workbook `wb`
|
||||
|
||||
`XLSX.writeFile(wb, filename, write_opts)` attempts to write `wb` to `filename`
|
||||
`XLSX.writeFile(wb, filename, write_opts)` attempts to write `wb` to `filename`.
|
||||
In browser-based environments, it will attempt to force a client-side download.
|
||||
|
||||
`XLSX.writeFileAsync(filename, wb, o, cb)` attempts to write `wb` to `filename`.
|
||||
If `o` is omitted, the writer will use the third argument as the callback.
|
||||
@ -2015,6 +2058,7 @@ produces HTML output. The function takes an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :------: | :-------------------------------------------------- |
|
||||
|`id` | | Specify the `id` attribute for the `TABLE` element |
|
||||
|`editable` | false | If true, set `contenteditable="true"` for every TD |
|
||||
|`header` | | Override header (default `html body`) |
|
||||
|`footer` | | Override footer (default `/body /html`) |
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.11.18';
|
||||
XLSX.version = '0.11.19';
|
||||
|
@ -19,11 +19,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<string>*/ = []; for(var i = 0; i < data.length; ++i) o[i] = _chr(data[i]); return o.join("");
|
||||
}
|
||||
|
||||
function a2u(data/*:Array<number>*/)/*:Uint8Array*/ {
|
||||
if(typeof Uint8Array === 'undefined') throw new Error("Unsupported");
|
||||
return new Uint8Array(data);
|
||||
}
|
||||
|
||||
function ab2a(data/*:ArrayBuffer|Uint8Array*/)/*:Array<number>*/ {
|
||||
if(typeof ArrayBuffer == 'undefined') throw new Error("Unsupported");
|
||||
if(data instanceof ArrayBuffer) return ab2a(new Uint8Array(data));
|
||||
|
37
bits/19_fsutils.js
Normal file
37
bits/19_fsutils.js
Normal file
@ -0,0 +1,37 @@
|
||||
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");
|
||||
}
|
||||
|
@ -51,14 +51,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) { }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,6 +132,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 */
|
||||
}
|
||||
|
@ -833,7 +833,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); */
|
||||
}
|
||||
|
@ -84,9 +84,9 @@ var HTML_ = (function() {
|
||||
var preamble = "<tr>";
|
||||
return preamble + oo.join("") + "</tr>";
|
||||
}
|
||||
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<string>*/ = [];
|
||||
return out.join("") + '<table>';
|
||||
return out.join("") + '<table' + (o && o.id ? ' id="' + o.id + '"' : "") + '>';
|
||||
}
|
||||
var _BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
|
||||
var _END = '</body></html>';
|
||||
|
@ -100,7 +100,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);
|
||||
}
|
||||
|
||||
|
@ -6,12 +6,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;
|
||||
@ -23,8 +23,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);
|
||||
@ -37,7 +37,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); });
|
||||
@ -51,7 +51,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); });
|
||||
@ -70,7 +70,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);
|
||||
}
|
||||
|
@ -131,7 +131,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<string>*/ {
|
||||
|
@ -44,5 +44,6 @@ can be installed with Bash on Windows or with `cygwin`.
|
||||
- [`Headless Browsers`](headless/)
|
||||
- [`canvas-datagrid`](datagrid/)
|
||||
- [`Swift JSC and other engines`](altjs/)
|
||||
- [`internet explorer`](oldie/)
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
||||
|
@ -81,18 +81,15 @@ var ws = XLSX.utils.json_to_sheet(data);
|
||||
var wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, "Presidents");
|
||||
|
||||
/* write workbook (use type 'array' for ArrayBuffer) */
|
||||
var wbout = XLSX.write(wb, {bookType:'xlsx', type:'array'});
|
||||
|
||||
/* generate a download */
|
||||
saveAs(new Blob([wbout],{type:"application/octet-stream"}), "sheetjs.xlsx");
|
||||
/* write workbook and force a download */
|
||||
XLSX.writeFile(wb, "sheetjs.xlsx");
|
||||
```
|
||||
|
||||
|
||||
`SheetJSExportService` exposes export functions for `XLSB` and `XLSX`. Other
|
||||
formats are easily supported by changing the `bookType` variable. It grabs
|
||||
values from the grid, builds an array of arrays, generates a workbook and uses
|
||||
FileSaver to generate a download. By setting the `filename` and `sheetname`
|
||||
options in the ui-grid options, the output can be controlled.
|
||||
values from the grid, builds an array of arrays, generates a workbook and forces
|
||||
a download. By setting the `filename` and `sheetname` options in the ui-grid
|
||||
options, the output can be controlled.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
||||
|
3
demos/angular/SheetJS-angular.js
vendored
3
demos/angular/SheetJS-angular.js
vendored
@ -12,8 +12,7 @@ function SheetJSExportService(uiGridExporterService) {
|
||||
|
||||
var wb = XLSX.utils.book_new(), ws = uigrid_to_sheet(data, columns);
|
||||
XLSX.utils.book_append_sheet(wb, ws, sheetName);
|
||||
var wbout = XLSX.write(wb, wopts);
|
||||
saveAs(new Blob([wbout], { type: 'application/octet-stream' }), fileName);
|
||||
XLSX.writeFile(wb, fileName);
|
||||
}
|
||||
|
||||
var service = {};
|
||||
|
@ -13,10 +13,8 @@
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.0.0/ui-grid.js"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.0.0/ui-grid.css"/>
|
||||
|
||||
<!-- FileSaver shim for exporting files -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js"></script>
|
||||
|
||||
<!-- SheetJS js-xlsx library -->
|
||||
<script src="shim.js"></script>
|
||||
<script src="xlsx.full.min.js"></script>
|
||||
|
||||
<!-- SheetJS Service -->
|
||||
|
1
demos/angular/shim.js
vendored
Symbolic link
1
demos/angular/shim.js
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../../shim.js
|
@ -2,24 +2,27 @@
|
||||
angular:
|
||||
# Test Angular2 build
|
||||
cp package.json-angular2 package.json
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
if [ ! -e node_modules ]; then mkdir node_modules; fi
|
||||
if [ ! -e node_modules/xlsx ]; then cd node_modules; ln -s ../../../ xlsx; cd -; fi
|
||||
ng build
|
||||
npm run build
|
||||
|
||||
# Test Angular4 build
|
||||
cp package.json-angular4 package.json
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
if [ ! -e node_modules ]; then mkdir node_modules; fi
|
||||
if [ ! -e node_modules/xlsx ]; then cd node_modules; ln -s ../../../ xlsx; cd -; fi
|
||||
ng build
|
||||
npm run build
|
||||
|
||||
# Test Angular5 build
|
||||
cp package.json-angular5 package.json
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
if [ ! -e node_modules ]; then mkdir node_modules; fi
|
||||
if [ ! -e node_modules/xlsx ]; then cd node_modules; ln -s ../../../ xlsx; cd -; fi
|
||||
ng build
|
||||
npm run build
|
||||
|
||||
.PHONY: ionic
|
||||
ionic:
|
||||
|
@ -38,8 +38,7 @@ const wb: XLSX.WorkBook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
|
||||
|
||||
/* save to file */
|
||||
const wbout: string = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
|
||||
saveAs(new Blob([wbout]), 'SheetJS.xlsx');
|
||||
XLSX.writeFile(wb, 'SheetJS.xlsx');
|
||||
```
|
||||
|
||||
`sheet_to_json` with the option `header:1` makes importing simple:
|
||||
|
@ -5,7 +5,7 @@ if [ ! -e SheetJSIonic ]; then
|
||||
ionic cordova platform add browser </dev/null
|
||||
ionic cordova platform add ios </dev/null
|
||||
ionic cordova plugin add cordova-plugin-file </dev/null
|
||||
npm install --save @ionic-native/file file-saver
|
||||
npm install --save @ionic-native/file
|
||||
npm install --save xlsx
|
||||
|
||||
cp src/app/app.module.ts{,.bak}
|
||||
|
@ -5,7 +5,6 @@ import { Component } from '@angular/core';
|
||||
import * as XLSX from 'xlsx';
|
||||
|
||||
import { File } from '@ionic-native/file';
|
||||
import { saveAs } from 'file-saver';
|
||||
|
||||
type AOA = any[][];
|
||||
|
||||
@ -48,7 +47,7 @@ export class HomePage {
|
||||
this.data = <AOA>(XLSX.utils.sheet_to_json(ws, {header: 1}));
|
||||
};
|
||||
|
||||
write(): ArrayBuffer {
|
||||
write(): XLSX.WorkBook {
|
||||
/* generate worksheet */
|
||||
const ws: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet(this.data);
|
||||
|
||||
@ -56,9 +55,7 @@ export class HomePage {
|
||||
const wb: XLSX.WorkBook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, 'SheetJS');
|
||||
|
||||
/* save to ArrayBuffer */
|
||||
const wbout: ArrayBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
|
||||
return wbout;
|
||||
return wb;
|
||||
};
|
||||
|
||||
/* File Input element for browser */
|
||||
@ -91,17 +88,26 @@ export class HomePage {
|
||||
|
||||
/* Export button */
|
||||
async export() {
|
||||
const wbout: ArrayBuffer = this.write();
|
||||
const wb: XLSX.WorkBook = this.write();
|
||||
const filename: string = "SheetJSIonic.xlsx";
|
||||
const blob: Blob = new Blob([wbout], {type: 'application/octet-stream'});
|
||||
try {
|
||||
/* generate Blob */
|
||||
const wbout: ArrayBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
|
||||
const blob: Blob = new Blob([wbout], {type: 'application/octet-stream'});
|
||||
|
||||
/* find appropriate path for mobile */
|
||||
const target: string = this.file.documentsDirectory || this.file.externalDataDirectory || this.file.dataDirectory || '';
|
||||
const dentry = await this.file.resolveDirectoryUrl(target);
|
||||
const url: string = dentry.nativeURL || '';
|
||||
|
||||
/* attempt to save blob to file */
|
||||
await this.file.writeFile(url, filename, blob, {replace: true});
|
||||
alert(`Wrote to SheetJSIonic.xlsx in ${url}`);
|
||||
} catch(e) {
|
||||
if(e.message.match(/It was determined/)) saveAs(blob, filename);
|
||||
if(e.message.match(/It was determined/)) {
|
||||
/* in the browser, use writeFile */
|
||||
XLSX.writeFile(wb, filename);
|
||||
}
|
||||
else alert(`Error: ${e.message}`);
|
||||
}
|
||||
};
|
||||
|
@ -24,11 +24,10 @@
|
||||
|
||||
"rxjs": "^5.5.2",
|
||||
|
||||
"zone.js": "^0.8.14",
|
||||
"file-saver": "^1.3.3"
|
||||
"zone.js": "^0.8.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/cli": "1.5.0",
|
||||
"@angular/cli": "^1.5.3",
|
||||
"@angular/compiler-cli": "^5.0.0",
|
||||
"@angular/language-service": "^5.0.0",
|
||||
"@types/node": "~6.0.60",
|
||||
|
@ -24,8 +24,7 @@
|
||||
"reflect-metadata": "^0.1.8",
|
||||
"rxjs": "^5.0.2",
|
||||
"systemjs": "0.19.40",
|
||||
"zone.js": "^0.7.4",
|
||||
"file-saver": "^1.3.3"
|
||||
"zone.js": "^0.7.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/cli": "1.1.2",
|
||||
|
@ -24,8 +24,7 @@
|
||||
|
||||
"rxjs": "^5.1.0",
|
||||
|
||||
"zone.js": "^0.8.4",
|
||||
"file-saver": "^1.3.3"
|
||||
"zone.js": "^0.8.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/cli": "1.1.2",
|
||||
|
@ -24,11 +24,10 @@
|
||||
|
||||
"rxjs": "^5.5.2",
|
||||
|
||||
"zone.js": "^0.8.14",
|
||||
"file-saver": "^1.3.3"
|
||||
"zone.js": "^0.8.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/cli": "1.5.0",
|
||||
"@angular/cli": "^1.5.3",
|
||||
"@angular/compiler-cli": "^5.0.0",
|
||||
"@angular/language-service": "^5.0.0",
|
||||
"@types/node": "~6.0.60",
|
||||
|
@ -4,8 +4,6 @@ import { Component } from '@angular/core';
|
||||
|
||||
import * as XLSX from 'xlsx';
|
||||
|
||||
import { saveAs } from 'file-saver';
|
||||
|
||||
type AOA = any[][];
|
||||
|
||||
@Component({
|
||||
@ -57,7 +55,6 @@ export class SheetJSComponent {
|
||||
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
|
||||
|
||||
/* save to file */
|
||||
const wbout: ArrayBuffer = XLSX.write(wb, this.wopts);
|
||||
saveAs(new Blob([wbout], { type: 'application/octet-stream' }), this.fileName);
|
||||
XLSX.writeFile(wb, this.fileName);
|
||||
}
|
||||
}
|
||||
|
@ -9,42 +9,42 @@ var client = redis.createClient();
|
||||
|
||||
/* Sample data */
|
||||
var init = [
|
||||
["FLUSHALL", []],
|
||||
["SADD", ["birdpowers", "flight", "pecking"]],
|
||||
["SET", ["foo", "bar"]],
|
||||
["SET", ["baz", 0]],
|
||||
["RPUSH", ["friends", "sam", "alice", "bob"]],
|
||||
["ZADD", ["hackers", 1906, 'Grace Hopper', 1912, 'Alan Turing', 1916, 'Claude Shannon', 1940, 'Alan Kay', 1953, 'Richard Stallman', 1957, 'Sophie Wilson', 1965, 'Yukihiro Matsumoto', 1969, 'Linus Torvalds']],
|
||||
["SADD", ["superpowers", "flight", 'x-ray vision']],
|
||||
["HMSET", ["user:1000", "name", 'John Smith', "email", 'john.smith@example.com', "password", "s3cret", "visits", 1]],
|
||||
["HMSET", ["user:1001", "name", 'Mary Jones', "email", 'mjones@example.com', "password", "hidden"]]
|
||||
["FLUSHALL", []],
|
||||
["SADD", ["birdpowers", "flight", "pecking"]],
|
||||
["SET", ["foo", "bar"]],
|
||||
["SET", ["baz", 0]],
|
||||
["RPUSH", ["friends", "sam", "alice", "bob"]],
|
||||
["ZADD", ["hackers", 1906, 'Grace Hopper', 1912, 'Alan Turing', 1916, 'Claude Shannon', 1940, 'Alan Kay', 1953, 'Richard Stallman', 1957, 'Sophie Wilson', 1965, 'Yukihiro Matsumoto', 1969, 'Linus Torvalds']],
|
||||
["SADD", ["superpowers", "flight", 'x-ray vision']],
|
||||
["HMSET", ["user:1000", "name", 'John Smith', "email", 'john.smith@example.com', "password", "s3cret", "visits", 1]],
|
||||
["HMSET", ["user:1001", "name", 'Mary Jones', "email", 'mjones@example.com', "password", "hidden"]]
|
||||
];
|
||||
|
||||
const R = (()=>{
|
||||
const Rcache = {};
|
||||
const R_ = (n) => Rcache[n] || (Rcache[n] = util.promisify(client[n]).bind(client));
|
||||
return (n) => R_(n.toLowerCase());
|
||||
const Rcache = {};
|
||||
const R_ = (n) => Rcache[n] || (Rcache[n] = util.promisify(client[n]).bind(client));
|
||||
return (n) => R_(n.toLowerCase());
|
||||
})();
|
||||
|
||||
(async () => {
|
||||
for(var i = 0; i < init.length; ++i) await R(init[i][0])(init[i][1]);
|
||||
for(var i = 0; i < init.length; ++i) await R(init[i][0])(init[i][1]);
|
||||
|
||||
/* Export database to XLSX */
|
||||
var wb = await SheetJSRedis.redis_to_wb(R);
|
||||
var wb = await SheetJSRedis.redis_to_wb(R);
|
||||
XLSX.writeFile(wb, "redis.xlsx");
|
||||
|
||||
/* Import XLSX to database */
|
||||
await R("flushall")();
|
||||
await R("flushall")();
|
||||
var wb2 = XLSX.readFile("redis.xlsx");
|
||||
await SheetJSRedis.wb_to_redis(wb2, R);
|
||||
await SheetJSRedis.wb_to_redis(wb2, R);
|
||||
|
||||
/* Verify */
|
||||
assert.equal(await R("get")("foo"), "bar");
|
||||
assert.equal(await R("lindex")("friends", 1), "alice");
|
||||
assert.equal(await R("zscore")("hackers", "Claude Shannon"), 1916);
|
||||
assert.equal(await R("hget")("user:1000", "name"), "John Smith");
|
||||
assert.equal(await R("sismember")("superpowers", "flight"), "1");
|
||||
assert.equal(await R("sismember")("birdpowers", "pecking"), "1");
|
||||
/* Verify */
|
||||
assert.equal(await R("get")("foo"), "bar");
|
||||
assert.equal(await R("lindex")("friends", 1), "alice");
|
||||
assert.equal(await R("zscore")("hackers", "Claude Shannon"), 1916);
|
||||
assert.equal(await R("hget")("user:1000", "name"), "John Smith");
|
||||
assert.equal(await R("sismember")("superpowers", "flight"), "1");
|
||||
assert.equal(await R("sismember")("birdpowers", "pecking"), "1");
|
||||
|
||||
client.quit();
|
||||
client.quit();
|
||||
})();
|
||||
|
@ -6,68 +6,68 @@ const pair = (arr) => arr.map((x,i)=>!(i%2)&&[x,+arr[i+1]]).filter(x=>x);
|
||||
const keyify = (obj) => Object.keys(obj).map(x => [x, obj[x]]);
|
||||
|
||||
async function redis_to_wb(R) {
|
||||
var wb = XLSX.utils.book_new();
|
||||
var manifest = [], strs = [];
|
||||
var wb = XLSX.utils.book_new();
|
||||
var manifest = [], strs = [];
|
||||
|
||||
/* store strings in strs and keep note of other objects in manifest */
|
||||
var keys = await R("keys")("*"), type = "";
|
||||
for(var i = 0; i < keys.length; ++i) {
|
||||
type = await R("type")(keys[i]);
|
||||
switch(type) {
|
||||
case "string": strs.push({key:keys[i], value: await R("get")(keys[i])}); break;
|
||||
case "list": case "zset": case "set": case "hash": manifest.push({key:keys[i], type:type}); break;
|
||||
default: throw new Error("bad type " + type);
|
||||
}
|
||||
}
|
||||
/* store strings in strs and keep note of other objects in manifest */
|
||||
var keys = await R("keys")("*"), type = "";
|
||||
for(var i = 0; i < keys.length; ++i) {
|
||||
type = await R("type")(keys[i]);
|
||||
switch(type) {
|
||||
case "string": strs.push({key:keys[i], value: await R("get")(keys[i])}); break;
|
||||
case "list": case "zset": case "set": case "hash": manifest.push({key:keys[i], type:type}); break;
|
||||
default: throw new Error("bad type " + type);
|
||||
}
|
||||
}
|
||||
|
||||
/* add worksheets if relevant */
|
||||
if(strs.length > 0) {
|
||||
var wss = XLSX.utils.json_to_sheet(strs, {header: ["key", "value"], skipHeader:1});
|
||||
XLSX.utils.book_append_sheet(wb, wss, "_strs");
|
||||
}
|
||||
if(manifest.length > 0) {
|
||||
var wsm = XLSX.utils.json_to_sheet(manifest, {header: ["key", "type"]});
|
||||
XLSX.utils.book_append_sheet(wb, wsm, "_manifest");
|
||||
}
|
||||
for(i = 0; i < manifest.length; ++i) {
|
||||
var sn = "obj" + i;
|
||||
var aoa, key = manifest[i].key;
|
||||
switch((type=manifest[i].type)) {
|
||||
case "list":
|
||||
aoa = (await R("lrange")(key, 0, -1)).map(x => [x]); break;
|
||||
case "set":
|
||||
aoa = (await R("smembers")(key)).map(x => [x]); break;
|
||||
case "zset":
|
||||
aoa = pair(await R("zrange")(key, 0, -1, "withscores")); break;
|
||||
case "hash":
|
||||
aoa = keyify(await R("hgetall")(key)); break;
|
||||
default: throw new Error("bad type " + type);
|
||||
}
|
||||
XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet(aoa), sn);
|
||||
}
|
||||
return wb;
|
||||
/* add worksheets if relevant */
|
||||
if(strs.length > 0) {
|
||||
var wss = XLSX.utils.json_to_sheet(strs, {header: ["key", "value"], skipHeader:1});
|
||||
XLSX.utils.book_append_sheet(wb, wss, "_strs");
|
||||
}
|
||||
if(manifest.length > 0) {
|
||||
var wsm = XLSX.utils.json_to_sheet(manifest, {header: ["key", "type"]});
|
||||
XLSX.utils.book_append_sheet(wb, wsm, "_manifest");
|
||||
}
|
||||
for(i = 0; i < manifest.length; ++i) {
|
||||
var sn = "obj" + i;
|
||||
var aoa, key = manifest[i].key;
|
||||
switch((type=manifest[i].type)) {
|
||||
case "list":
|
||||
aoa = (await R("lrange")(key, 0, -1)).map(x => [x]); break;
|
||||
case "set":
|
||||
aoa = (await R("smembers")(key)).map(x => [x]); break;
|
||||
case "zset":
|
||||
aoa = pair(await R("zrange")(key, 0, -1, "withscores")); break;
|
||||
case "hash":
|
||||
aoa = keyify(await R("hgetall")(key)); break;
|
||||
default: throw new Error("bad type " + type);
|
||||
}
|
||||
XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet(aoa), sn);
|
||||
}
|
||||
return wb;
|
||||
}
|
||||
|
||||
/* convert worksheet aoa to specific redis type */
|
||||
const aoa_to_redis = {
|
||||
list: async (aoa, R, key) => await R("RPUSH")([key].concat(aoa.map(x=>x[0]))),
|
||||
zset: async (aoa, R, key) => await R("ZADD" )([key].concat(aoa.reduce((acc,x)=>acc.concat([+x[1], x[0]]), []))),
|
||||
hash: async (aoa, R, key) => await R("HMSET")([key].concat(aoa.reduce((acc,x)=>acc.concat(x), []))),
|
||||
set: async (aoa, R, key) => await R("SADD" )([key].concat(aoa.map(x=>x[0])))
|
||||
list: async (aoa, R, key) => await R("RPUSH")([key].concat(aoa.map(x=>x[0]))),
|
||||
zset: async (aoa, R, key) => await R("ZADD" )([key].concat(aoa.reduce((acc,x)=>acc.concat([+x[1], x[0]]), []))),
|
||||
hash: async (aoa, R, key) => await R("HMSET")([key].concat(aoa.reduce((acc,x)=>acc.concat(x), []))),
|
||||
set: async (aoa, R, key) => await R("SADD" )([key].concat(aoa.map(x=>x[0])))
|
||||
};
|
||||
async function wb_to_redis(wb, R) {
|
||||
if(wb.Sheets._strs) {
|
||||
var strs = XLSX.utils.sheet_to_json(wb.Sheets._strs, {header:1});
|
||||
for(var i = 0; i < strs.length; ++i) await R("SET")(strs[i]);
|
||||
}
|
||||
if(!wb.Sheets._manifest) return;
|
||||
var M = XLSX.utils.sheet_to_json(wb.Sheets._manifest);
|
||||
for(i = 0; i < M.length; ++i) {
|
||||
var aoa = XLSX.utils.sheet_to_json(wb.Sheets["obj" + i], {header:1});
|
||||
await aoa_to_redis[M[i].type](aoa, R, M[i].key);
|
||||
}
|
||||
if(wb.Sheets._strs) {
|
||||
var strs = XLSX.utils.sheet_to_json(wb.Sheets._strs, {header:1});
|
||||
for(var i = 0; i < strs.length; ++i) await R("SET")(strs[i]);
|
||||
}
|
||||
if(!wb.Sheets._manifest) return;
|
||||
var M = XLSX.utils.sheet_to_json(wb.Sheets._manifest);
|
||||
for(i = 0; i < M.length; ++i) {
|
||||
var aoa = XLSX.utils.sheet_to_json(wb.Sheets["obj" + i], {header:1});
|
||||
await aoa_to_redis[M[i].type](aoa, R, M[i].key);
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
redis_to_wb,
|
||||
wb_to_redis
|
||||
redis_to_wb,
|
||||
wb_to_redis
|
||||
};
|
||||
|
@ -49,9 +49,9 @@ function sheet_to_sql(ws, sname, mode) {
|
||||
|
||||
var out = [];
|
||||
|
||||
var BT = mode == "PGSQL" ? "" : "`";
|
||||
var Q = mode == "PGSQL" ? "'" : '"';
|
||||
var R = mode == "PGSQL" ? /'/g : /"/g;
|
||||
var BT = mode == "PGSQL" ? "" : "`";
|
||||
var Q = mode == "PGSQL" ? "'" : '"';
|
||||
var R = mode == "PGSQL" ? /'/g : /"/g;
|
||||
out.push("DROP TABLE IF EXISTS " + BT + sname + BT );
|
||||
out.push("CREATE TABLE " + BT + sname + BT + " (" + names.map(function(n, i) { return BT + n + BT + " " + (types[i]||"TEXT"); }).join(", ") + ");" );
|
||||
|
||||
|
@ -82,7 +82,8 @@ var ws = XLSX.utils.aoa_to_sheet(prep(grid.data));
|
||||
var wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, 'SheetJS');
|
||||
|
||||
/* .. generate download (see documentation for examples) .. */
|
||||
/* generate download */
|
||||
XLSX.writeFile(wb, "SheetJS.xlsx");
|
||||
```
|
||||
|
||||
## Additional Features
|
||||
|
@ -40,8 +40,7 @@ Use readAsBinaryString: (when available) <input type="checkbox" name="userabs" c
|
||||
<div id="htmlout"></div>
|
||||
<br />
|
||||
<script src="https://unpkg.com/canvas-datagrid/dist/canvas-datagrid.js"></script>
|
||||
<script type="text/javascript" src="https://rawgit.com/eligrey/Blob.js/master/Blob.js"></script>
|
||||
<script type="text/javascript" src="https://rawgit.com/eligrey/FileSaver.js/master/FileSaver.js"></script>
|
||||
<script src="shim.js"></script>
|
||||
<script src="xlsx.full.min.js"></script>
|
||||
<script>
|
||||
/*jshint browser:true */
|
||||
@ -151,11 +150,7 @@ var export_xlsx = (function() {
|
||||
XLSX.utils.book_append_sheet(new_wb, new_ws, 'SheetJS');
|
||||
|
||||
/* write file and trigger a download */
|
||||
var wbout = XLSX.write(new_wb, {bookType:'xlsx', bookSST:true, type:'array'});
|
||||
var fname = 'sheetjs.xlsx';
|
||||
try {
|
||||
saveAs(new Blob([wbout],{type:"application/octet-stream"}), fname);
|
||||
} catch(e) { if(typeof console != 'undefined') console.log(e, wbout); }
|
||||
XLSX.writeFile(new_wb, 'sheetjs.xlsx', {bookSST:true});
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
|
1
demos/datagrid/shim.js
Symbolic link
1
demos/datagrid/shim.js
Symbolic link
@ -0,0 +1 @@
|
||||
../../shim.js
|
@ -6,9 +6,9 @@ start:
|
||||
init:
|
||||
if [ ! -e .meteor ]; then meteor create .; fi;
|
||||
@npm install babel-runtime meteor-node-stubs
|
||||
@meteor add pfafman:filesaver check
|
||||
@meteor add check
|
||||
@mkdir -p node_modules; cd node_modules; ln -s ../../../ xlsx; cd -
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
@meteor npm run lint
|
||||
@meteor npm run lint
|
||||
|
@ -61,13 +61,9 @@ const html = document.getElementById('out').innerHTML;
|
||||
// SERVER SIDE
|
||||
const wb = XLSX.read(html, { type: 'binary' });
|
||||
// CLIENT SIDE
|
||||
const o = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
|
||||
saveAs(new Blob([o], {type:'application/octet-stream'}), 'sheetjs.xlsx');
|
||||
XLSX.writeFile(wb, 'sheetjs.xlsx');
|
||||
```
|
||||
|
||||
This demo uses the FileSaver library for writing files, installed through the
|
||||
[`pfafman:filesaver` wrapper](https://atmospherejs.com/pfafman/filesaver).
|
||||
|
||||
|
||||
## Setup
|
||||
|
||||
@ -76,7 +72,6 @@ This tree does not include the `.meteor` structure. Rebuild the project with:
|
||||
```bash
|
||||
meteor create .
|
||||
npm install babel-runtime meteor-node-stubs xlsx
|
||||
meteor add pfafman:filesaver
|
||||
meteor
|
||||
```
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
import XLSX from 'xlsx';
|
||||
/* note: saveAs is made available via the smart package */
|
||||
/* global saveAs */
|
||||
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { Template } from 'meteor/templating';
|
||||
@ -13,11 +11,12 @@ Template.sheetjs.events({
|
||||
/* "Browser file upload form element" from SheetJS README */
|
||||
const file = event.currentTarget.files[0];
|
||||
const reader = new FileReader();
|
||||
const rABS = !!reader.readAsBinaryString;
|
||||
reader.onload = function(e) {
|
||||
const data = e.target.result;
|
||||
const name = file.name;
|
||||
/* Meteor magic */
|
||||
Meteor.call('upload', data, name, function(err, wb) {
|
||||
Meteor.call(rABS ? 'uploadS' : 'uploadU', rABS ? data : new Uint8Array(data), name, function(err, wb) {
|
||||
if (err) throw err;
|
||||
/* load the first worksheet */
|
||||
const ws = wb.Sheets[wb.SheetNames[0]];
|
||||
@ -27,15 +26,14 @@ Template.sheetjs.events({
|
||||
document.getElementById('dnload').disabled = false;
|
||||
});
|
||||
};
|
||||
reader.readAsBinaryString(file);
|
||||
if(rABS) reader.readAsBinaryString(file); else reader.readAsArrayBuffer(file);
|
||||
},
|
||||
'click button' () {
|
||||
const html = document.getElementById('out').innerHTML;
|
||||
Meteor.call('download', html, function(err, wb) {
|
||||
if (err) throw err;
|
||||
/* "Browser download file" from SheetJS README */
|
||||
const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
|
||||
saveAs(new Blob([wbout], { type: 'application/octet-stream' }), 'sheetjs.xlsx');
|
||||
XLSX.writeFile(wb, 'sheetjs.xlsx');
|
||||
});
|
||||
},
|
||||
});
|
||||
|
@ -4,12 +4,17 @@ import { check } from 'meteor/check';
|
||||
import XLSX from 'xlsx';
|
||||
|
||||
Meteor.methods({
|
||||
upload: (bstr, name) => {
|
||||
/* read the data and return the workbook object to the frontend */
|
||||
/* read the data and return the workbook object to the frontend */
|
||||
uploadS: (bstr, name) => {
|
||||
check(bstr, String);
|
||||
check(name, String);
|
||||
return XLSX.read(bstr, { type: 'binary' });
|
||||
},
|
||||
uploadU: (ab, name) => {
|
||||
check(ab, Uint8Array);
|
||||
check(name, String);
|
||||
return XLSX.read(ab, { type: 'array' });
|
||||
},
|
||||
download: (html) => {
|
||||
check(html, String);
|
||||
let wb;
|
||||
|
70
demos/oldie/README.md
Normal file
70
demos/oldie/README.md
Normal file
@ -0,0 +1,70 @@
|
||||
# Internet Explorer
|
||||
|
||||
Despite the efforts to deprecate the pertinent operating systems, IE is still
|
||||
very popular, required for various government and corporate websites throughout
|
||||
the world. The modern download strategies are not available in older versions
|
||||
of IE, but there are alternative approaches.
|
||||
|
||||
## Strategies
|
||||
|
||||
#### IE10 and IE11 File API
|
||||
|
||||
As part of the File API implementation, IE10 and IE11 provide the `msSaveBlob`
|
||||
and `msSaveOrOpenBlob` functions to save blobs to the client computer. This
|
||||
approach is embedded in `XLSX.writeFile` and no additional shims are necessary.
|
||||
|
||||
#### Flash-based Download
|
||||
|
||||
It is possible to write to the file system using a SWF. `Downloadify` library
|
||||
implements one solution. Since a genuine click is required, there is no way to
|
||||
force a download. The demo generates a button for each desired output format.
|
||||
|
||||
#### ActiveX-based Download
|
||||
|
||||
Through the `Scripting.FileSystemObject` object model, a script in the VBScript
|
||||
scripting language can write to an arbitrary path on the filesystem. The shim
|
||||
includes a special `IE_SaveFile` function to write binary strings to file. It
|
||||
attempts to write to the Downloads folder or Documents folder or Desktop.
|
||||
|
||||
This approach can be triggered, but it requires the user to enable ActiveX. It
|
||||
is embedded as a strategy in `writeFile` and used only if the shim script is
|
||||
included in the page and the relevant features are enabled on the target system.
|
||||
|
||||
## Demo
|
||||
|
||||
The included demo starts from an array of arrays, generating an editable HTML
|
||||
table with `aoa_to_sheet` and adding it to the page:
|
||||
|
||||
```js
|
||||
var ws = XLSX.utils.aoa_to_sheet(aoa);
|
||||
var html_string = XLSX.utils.sheet_to_html(ws, { id: "table", editable: true });
|
||||
document.getElementById("container").innerHTML = html_string;
|
||||
```
|
||||
|
||||
The included download buttons use `table_to_book` to construct a new workbook
|
||||
based on the table and `writeFile` to force a download:
|
||||
|
||||
|
||||
```js
|
||||
var elt = document.getElementById('table');
|
||||
var wb = XLSX.utils.table_to_book(elt, { sheet: "Sheet JS" });
|
||||
XLSX.writeFile(wb, filename);
|
||||
```
|
||||
|
||||
The shim is included in the HTML page, unlocking the ActiveX pathway if enabled
|
||||
in browser settings.
|
||||
|
||||
The corresponding SWF buttons are displayed in environments where Flash is
|
||||
available and `Downloadify` is supported. The easiest solution involves writing
|
||||
to a Base64 string and passing to the library:
|
||||
|
||||
```js
|
||||
Downloadify.create(element_id, {
|
||||
/* the demo includes the other options required by Downloadify */
|
||||
filename: "test.xlsx",
|
||||
data: function() { return XLSX.write(wb, {bookType:"xlsx", type:'base64'}); },
|
||||
dataType: 'base64'
|
||||
});
|
||||
```
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)
|
1
demos/oldie/base64.min.js
vendored
Normal file
1
demos/oldie/base64.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(){function t(t){this.message=t}var r="undefined"!=typeof exports?exports:self,e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";t.prototype=new Error,t.prototype.name="InvalidCharacterError",r.btoa||(r.btoa=function(r){for(var o,n,a=String(r),i=0,c=e,d="";a.charAt(0|i)||(c="=",i%1);d+=c.charAt(63&o>>8-i%1*8)){if(n=a.charCodeAt(i+=.75),n>255)throw new t("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");o=o<<8|n}return d}),r.atob||(r.atob=function(r){var o=String(r).replace(/=+$/,"");if(o.length%4==1)throw new t("'atob' failed: The string to be decoded is not correctly encoded.");for(var n,a,i=0,c=0,d="";a=o.charAt(c++);~a&&(n=i%4?64*n+a:a,i++%4)?d+=String.fromCharCode(255&n>>(-2*i&6)):0)a=e.indexOf(a);return d})}();
|
BIN
demos/oldie/download.png
Executable file
BIN
demos/oldie/download.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
3
demos/oldie/downloadify.min.js
vendored
Executable file
3
demos/oldie/downloadify.min.js
vendored
Executable file
@ -0,0 +1,3 @@
|
||||
/* Downloadify 0.2 (c) 2009 by Douglas Neiner. Licensed under the MIT license */
|
||||
/* See http://github.com/dcneiner/Downloadify for license and more info */
|
||||
(function(){Downloadify=window.Downloadify={queue:{},uid:new Date().getTime(),getTextForSave:function(a){var b=Downloadify.queue[a];if(b)return b.getData();return""},getFileNameForSave:function(a){var b=Downloadify.queue[a];if(b)return b.getFilename();return""},getDataTypeForSave:function(a){var b=Downloadify.queue[a];if(b)return b.getDataType();return""},saveComplete:function(a){var b=Downloadify.queue[a];if(b)b.complete();return true},saveCancel:function(a){var b=Downloadify.queue[a];if(b)b.cancel();return true},saveError:function(a){var b=Downloadify.queue[a];if(b)b.error();return true},addToQueue:function(a){Downloadify.queue[a.queue_name]=a},getUID:function(a){if(a.id=="")a.id='downloadify_'+Downloadify.uid++;return a.id}};Downloadify.create=function(a,b){var c=(typeof(a)=="string"?document.getElementById(a):a);return new Downloadify.Container(c,b)};Downloadify.Container=function(d,e){var f=this;f.el=d;f.enabled=true;f.dataCallback=null;f.filenameCallback=null;f.data=null;f.filename=null;var g=function(){f.options=e;if(!f.options.append)f.el.innerHTML="";f.flashContainer=document.createElement('span');f.el.appendChild(f.flashContainer);f.queue_name=Downloadify.getUID(f.flashContainer);if(typeof(f.options.filename)==="function")f.filenameCallback=f.options.filename;else if(f.options.filename)f.filename=f.options.filename;if(typeof(f.options.data)==="function")f.dataCallback=f.options.data;else if(f.options.data)f.data=f.options.data;var a={queue_name:f.queue_name,width:f.options.width,height:f.options.height};var b={allowScriptAccess:'always'};var c={id:f.flashContainer.id,name:f.flashContainer.id};if(f.options.enabled===false)f.enabled=false;if(f.options.transparent===true)b.wmode="transparent";if(f.options.downloadImage)a.downloadImage=f.options.downloadImage;swfobject.embedSWF(f.options.swf,f.flashContainer.id,f.options.width,f.options.height,"10",null,a,b,c);Downloadify.addToQueue(f)};f.enable=function(){var a=document.getElementById(f.flashContainer.id);a.setEnabled(true);f.enabled=true};f.disable=function(){var a=document.getElementById(f.flashContainer.id);a.setEnabled(false);f.enabled=false};f.getData=function(){if(!f.enabled)return"";if(f.dataCallback)return f.dataCallback();else if(f.data)return f.data;else return""};f.getFilename=function(){if(f.filenameCallback)return f.filenameCallback();else if(f.filename)return f.filename;else return""};f.getDataType=function(){if(f.options.dataType)return f.options.dataType;return"string"};f.complete=function(){if(typeof(f.options.onComplete)==="function")f.options.onComplete()};f.cancel=function(){if(typeof(f.options.onCancel)==="function")f.options.onCancel()};f.error=function(){if(typeof(f.options.onError)==="function")f.options.onError()};g()};Downloadify.defaultOptions={swf:'media/downloadify.swf',downloadImage:'images/download.png',width:100,height:30,transparent:true,append:false,dataType:"string"}})();if(typeof(jQuery)!="undefined"){(function($){$.fn.downloadify=function(b){return this.each(function(){b=$.extend({},Downloadify.defaultOptions,b);var a=Downloadify.create(this,b);$(this).data('Downloadify',a)})}})(jQuery)};if(typeof(MooTools)!='undefined'){Element.implement({downloadify:function(a){a=$merge(Downloadify.defaultOptions,a);return this.store('Downloadify',Downloadify.create(this,a))}})};
|
BIN
demos/oldie/downloadify.swf
Executable file
BIN
demos/oldie/downloadify.swf
Executable file
Binary file not shown.
122
demos/oldie/index.html
Normal file
122
demos/oldie/index.html
Normal file
@ -0,0 +1,122 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- (C) 2013-present SheetJS http://sheetjs.com -->
|
||||
<!-- vim: set ts=2: -->
|
||||
<html>
|
||||
<head>
|
||||
<title>SheetJS JS-XLSX In-Browser HTML Table Export Demo</title>
|
||||
<meta charset="utf-8" />
|
||||
<style>
|
||||
.xport, .btn {
|
||||
display: inline;
|
||||
text-align:center;
|
||||
}
|
||||
a { text-decoration: none }
|
||||
#data-table, #data-table th, #data-table td { border: 1px solid black }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- SheetJS js-xlsx library -->
|
||||
<script type="text/javascript" src="shim.min.js"></script>
|
||||
<script type="text/javascript" src="xlsx.full.min.js"></script>
|
||||
|
||||
<!-- Downloadify Flash fallback for IE 9 and below if ActiveX is unavailable -->
|
||||
<!--[if lte IE 9]>
|
||||
<script type="text/javascript" src="swfobject.js"></script>
|
||||
<script type="text/javascript" src="downloadify.min.js"></script>
|
||||
<script type="text/javascript" src="base64.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<script>
|
||||
function doit(type, fn, dl) {
|
||||
var elt = document.getElementById('data-table');
|
||||
var wb = XLSX.utils.table_to_book(elt, {sheet:"Sheet JS"});
|
||||
return dl ?
|
||||
XLSX.write(wb, {bookType:type, bookSST:true, type: 'base64'}) :
|
||||
XLSX.writeFile(wb, fn || ('test.' + (type || 'xlsx')));
|
||||
}
|
||||
</script>
|
||||
<pre>
|
||||
<h3><a href="//sheetjs.com/">SheetJS</a> JS-XLSX In-Browser HTML Table Export Demo</h3>
|
||||
<b>Compatibility notes:</b>
|
||||
- Editable table leverages the HTML5 contenteditable feature, supported in most browsers.
|
||||
- IE6-9 requires ActiveX or Flash to download files.
|
||||
- iOS Safari file download may not work. <a href="http://git.io/ios_save">This is a known issue</a>.
|
||||
|
||||
<b>Editable Data Table:</b> (click a cell to edit it)
|
||||
</pre>
|
||||
<div id="container"></div>
|
||||
<script type="text/javascript">
|
||||
/* initial table */
|
||||
var aoa = [
|
||||
["This", "is", "a", "Test"],
|
||||
["வணக்கம்", "สวัสดี", "你好", "가지마"],
|
||||
[1, 2, 3, 4],
|
||||
["Click", "to", "edit", "cells"]
|
||||
];
|
||||
var ws = XLSX.utils.aoa_to_sheet(aoa);
|
||||
var html_string = XLSX.utils.sheet_to_html(ws, { id: "data-table", editable: true });
|
||||
document.getElementById("container").innerHTML = html_string;
|
||||
</script>
|
||||
<br />
|
||||
<pre><b>Export it!</b></pre>
|
||||
<table id="xport">
|
||||
<tr><td><pre>XLSX Excel 2007+ XML</pre></td><td>
|
||||
<p id="xportxlsx" class="xport"><input type="submit" value="Export to XLSX!" onclick="doit('xlsx');"></p>
|
||||
<p id="xlsxbtn" class="btn">Flash required for actually downloading the generated file.</p>
|
||||
</td></tr>
|
||||
<tr><td><pre>XLSB Excel 2007+ Binary</pre></td><td>
|
||||
<p id="xportxlsb" class="xport"><input type="submit" value="Export to XLSB!" onclick="doit('xlsb');"></p>
|
||||
<p id="xlsbbtn" class="btn">Flash required for actually downloading the generated file.</p>
|
||||
</td></tr>
|
||||
<tr><td><pre>XLS Excel 97-2004 Binary</pre></td><td>
|
||||
<p id="xportbiff8" class="xport"><input type="submit" value="Export to XLS!" onclick="doit('biff8', 'test.xls');"></p>
|
||||
<p id="biff8btn" class="btn">Flash required for actually downloading the generated file.</p>
|
||||
</td></tr>
|
||||
<tr><td><pre>ODS</pre></td><td>
|
||||
<p id="xportods" class="xport"><input type="submit" value="Export to ODS!" onclick="doit('ods');"></p>
|
||||
<p id="odsbtn" class="btn">Flash required for actually downloading the generated file.</p>
|
||||
</td></tr>
|
||||
<tr><td><pre>Flat ODS</pre></td><td>
|
||||
<p id="xportfods" class="xport"><input type="submit" value="Export to FODS!" onclick="doit('fods', 'test.fods');"></p>
|
||||
<p id="fodsbtn" class="btn">Flash required for actually downloading the generated file.</p>
|
||||
</td></tr>
|
||||
</table>
|
||||
<pre><b>Powered by the <a href="//sheetjs.com/opensource">community version of js-xlsx</a></b></pre>
|
||||
<script type="text/javascript">
|
||||
function tableau(pid, iid, fmt, ofile) {
|
||||
if(typeof Downloadify !== 'undefined') Downloadify.create(pid,{
|
||||
swf: 'downloadify.swf',
|
||||
downloadImage: 'download.png',
|
||||
width: 100,
|
||||
height: 30,
|
||||
filename: ofile, data: function() { return doit(fmt, ofile, true); },
|
||||
transparent: false,
|
||||
append: false,
|
||||
dataType: 'base64',
|
||||
onComplete: function(){ alert('Your File Has Been Saved!'); },
|
||||
onCancel: function(){ alert('You have cancelled the saving of this file.'); },
|
||||
onError: function(){ alert('You must put something in the File Contents or there will be nothing to save!'); }
|
||||
}); else document.getElementById(pid).innerHTML = "";
|
||||
}
|
||||
tableau('biff8btn', 'xportbiff8', 'biff8', 'test.xls');
|
||||
tableau('odsbtn', 'xportods', 'ods', 'test.ods');
|
||||
tableau('fodsbtn', 'xportfods', 'fods', 'test.fods');
|
||||
tableau('xlsbbtn', 'xportxlsb', 'xlsb', 'test.xlsb');
|
||||
tableau('xlsxbtn', 'xportxlsx', 'xlsx', 'test.xlsx');
|
||||
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-36810333-1']);
|
||||
_gaq.push(['_setDomainName', 'sheetjs.com']);
|
||||
_gaq.push(['_setAllowLinker', true]);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
1
demos/oldie/shim.min.js
vendored
Symbolic link
1
demos/oldie/shim.min.js
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../../dist/shim.min.js
|
4
demos/oldie/swfobject.js
Executable file
4
demos/oldie/swfobject.js
Executable file
File diff suppressed because one or more lines are too long
1
demos/oldie/xlsx.full.min.js
vendored
Symbolic link
1
demos/oldie/xlsx.full.min.js
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../../dist/xlsx.full.min.js
|
1
demos/react/.gitignore
vendored
1
demos/react/.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
SheetJS
|
||||
.next
|
||||
static/shim.js
|
||||
|
@ -4,8 +4,9 @@ react: ## Simple server for react and clones
|
||||
|
||||
.PHONY: next
|
||||
next: init ## next.js demo
|
||||
mkdir -p pages
|
||||
mkdir -p pages static
|
||||
cat nexthdr.js sheetjs.jsx > pages/sheetjs.js
|
||||
cp ../../shim.js static/shim.js
|
||||
next
|
||||
|
||||
.PHONY: native
|
||||
@ -24,4 +25,3 @@ android: native ## react-native android sim
|
||||
init: ## set up node_modules and symlink
|
||||
mkdir -p node_modules
|
||||
cd node_modules; if [ ! -e xlsx ]; then ln -s ../../../ xlsx; fi; cd -
|
||||
if [ ! -e node_modules/file-saver ]; then npm install file-saver; fi
|
||||
|
@ -9,8 +9,8 @@
|
||||
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js"></script>
|
||||
<script src="node_modules/xlsx/dist/shim.min.js"></script>
|
||||
<script src="node_modules/xlsx/dist/xlsx.full.min.js"></script>
|
||||
<script src="https://unpkg.com/file-saver/FileSaver.js"></script>
|
||||
<style>body, #app { height: 100%; };</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -1,3 +1,2 @@
|
||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
import XLSX from 'xlsx';
|
||||
import { saveAs } from 'file-saver';
|
||||
|
@ -6,6 +6,7 @@ export default () => (
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>SheetJS React Demo</title>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
|
||||
<script src="/static/shim.js"></script>
|
||||
<style jsx>{`
|
||||
body, #app { height: 100%; };
|
||||
`}</style>
|
||||
|
@ -4,20 +4,20 @@
|
||||
<html lang="en" style="height: 100%">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>SheetJS React Demo</title>
|
||||
<title>SheetJS Preact Demo</title>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
|
||||
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
|
||||
<script src="//unpkg.com/preact"></script>
|
||||
<script src="//unpkg.com/proptypes"></script>
|
||||
<script src="//unpkg.com/preact-compat"></script>
|
||||
<script>var React = preactCompat, ReactDOM = preactCompat;</script>
|
||||
<script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
|
||||
<script src="https://unpkg.com/file-saver/FileSaver.js"></script>
|
||||
<script src="node_modules/xlsx/dist/shim.min.js"></script>
|
||||
<script src="node_modules/xlsx/dist/xlsx.full.min.js"></script>
|
||||
<style>body, #app { height: 100%; };</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<h1><a href="http://sheetjs.com">SheetJS React Demo</a></h1>
|
||||
<h1><a href="http://sheetjs.com">SheetJS Preact Demo</a></h1>
|
||||
<br />
|
||||
<a href="https://github.com/SheetJS/js-xlsx">Source Code Repo</a><br />
|
||||
<a href="https://github.com/SheetJS/js-xlsx/issues">Issues? Something look weird? Click here and report an issue</a><br /><br />
|
||||
|
@ -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 (
|
||||
<DragDropFile handleFile={this.handleFile}>
|
||||
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
||||
|
84
demos/server/node.js
Normal file
84
demos/server/node.js
Normal file
@ -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 = [
|
||||
'<pre>',
|
||||
'<h3><a href="http://sheetjs.com/">SheetJS File Converter</a></h3>',
|
||||
'Upload a file to convert the contents to another format.',
|
||||
'',
|
||||
'<b>Form Fields</b>:',
|
||||
'- bookType: output format type (defaults to "XLSX")',
|
||||
'- basename: basename for output file (defaults to "download")',
|
||||
'',
|
||||
'<form method="POST" enctype="multipart/form-data" action="/">',
|
||||
'<input type="file" id="file" name="file"/>',
|
||||
'<select name="bookType">',
|
||||
[
|
||||
["xlsb", "XLSB"],
|
||||
["xlsx", "XLSX"],
|
||||
["xlsm", "XLSM"],
|
||||
["biff8", "BIFF8 XLS"],
|
||||
["biff5", "BIFF5 XLS"],
|
||||
["biff2", "BIFF2 XLS"],
|
||||
["xlml", "SSML 2003"],
|
||||
["ods", "ODS"],
|
||||
["fods", "Flat ODS"],
|
||||
["csv", "CSV"],
|
||||
["txt", "Unicode Text"],
|
||||
["sylk", "Symbolic Link"],
|
||||
["html", "HTML"],
|
||||
["dif", "DIF"],
|
||||
["dbf", "DBF"],
|
||||
["rtf", "RTF"],
|
||||
["prn", "Lotus PRN"],
|
||||
["eth", "Ethercalc"],
|
||||
].map(function(x) { return ' <option value="' + x[0] + '">' + x[1] + '</option>'; }).join("\n"),
|
||||
'</select>',
|
||||
'<input type="submit" value="Submit Form">',
|
||||
'</form>',
|
||||
'',
|
||||
'<b>Form code:</b>',
|
||||
'<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>',
|
||||
'',
|
||||
'<b>fetch Code:</b>',
|
||||
'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();',
|
||||
'</pre>'
|
||||
].join("\n");
|
||||
|
||||
extmap = {
|
||||
"biff2" : "xls",
|
||||
"biff5" : "xls",
|
||||
"biff8" : "xls",
|
||||
"xlml" : "xls"
|
||||
};
|
||||
console.log('listening on port ' + PORT);
|
@ -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 -
|
||||
|
@ -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" }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -7,8 +7,8 @@
|
||||
<!-- Vue 2 -->
|
||||
<script src="https://unpkg.com/vue@2.x"></script>
|
||||
|
||||
<!-- FileSaver shim for exporting files -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js"></script>
|
||||
<!-- Various shims -->
|
||||
<script src="shim.js"></script>
|
||||
|
||||
<!-- SheetJS js-xlsx library -->
|
||||
<script src="xlsx.full.min.js"></script>
|
||||
|
@ -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
|
||||
]
|
||||
}
|
||||
};
|
||||
|
@ -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 */
|
||||
|
1
demos/vue/shim.js
Symbolic link
1
demos/vue/shim.js
Symbolic link
@ -0,0 +1 @@
|
||||
../../shim.js
|
1
demos/vue/static/shim.js
Symbolic link
1
demos/vue/static/shim.js
Symbolic link
@ -0,0 +1 @@
|
||||
../shim.js
|
@ -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:
|
||||
|
2
dist/shim.min.js
generated
vendored
2
dist/shim.min.js
generated
vendored
File diff suppressed because one or more lines are too long
26
dist/xlsx.core.min.js
generated
vendored
26
dist/xlsx.core.min.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.core.min.map
generated
vendored
2
dist/xlsx.core.min.map
generated
vendored
File diff suppressed because one or more lines are too long
30
dist/xlsx.full.min.js
generated
vendored
30
dist/xlsx.full.min.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.full.min.map
generated
vendored
2
dist/xlsx.full.min.map
generated
vendored
File diff suppressed because one or more lines are too long
75
dist/xlsx.js
generated
vendored
75
dist/xlsx.js
generated
vendored
@ -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 = undefined;
|
||||
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 = "<tr>";
|
||||
return preamble + oo.join("") + "</tr>";
|
||||
}
|
||||
function make_html_preamble() {
|
||||
function make_html_preamble(ws, R, o) {
|
||||
var out = [];
|
||||
return out.join("") + '<table>';
|
||||
return out.join("") + '<table' + (o && o.id ? ' id="' + o.id + '"' : "") + '>';
|
||||
}
|
||||
var _BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
|
||||
var _END = '</body></html>';
|
||||
@ -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) {
|
||||
|
24
dist/xlsx.min.js
generated
vendored
24
dist/xlsx.min.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.min.map
generated
vendored
2
dist/xlsx.min.map
generated
vendored
File diff suppressed because one or more lines are too long
@ -29,4 +29,5 @@ The [`demos` directory](demos/) includes sample projects for:
|
||||
- [`Headless Browsers`](demos/headless/)
|
||||
- [`canvas-datagrid`](demos/datagrid/)
|
||||
- [`Swift JSC and other engines`](demos/altjs/)
|
||||
- [`internet explorer`](demos/oldie/)
|
||||
|
||||
|
@ -41,7 +41,7 @@ var worksheet = XLSX.read(htmlstr, {type:'string'});
|
||||
<summary><b>Browser download file (ajax)</b> (click to show)</summary>
|
||||
|
||||
Note: for a more complete example that works in older browsers, check the demo
|
||||
at <http://oss.sheetjs.com/js-xlsx/ajax.html>). The <demos/xhr/> directory also
|
||||
at <http://oss.sheetjs.com/js-xlsx/ajax.html>). The [`xhr` demo](demos/xhr/)
|
||||
includes more examples with `XMLHttpRequest` and `fetch`.
|
||||
|
||||
```js
|
||||
@ -116,6 +116,8 @@ input_dom_element.addEventListener('change', handleFile, false);
|
||||
|
||||
</details>
|
||||
|
||||
More specialized cases, including mobile app file processing, are covered in the
|
||||
[included demos](demos/)
|
||||
|
||||
### Parsing Examples
|
||||
|
||||
|
@ -8,8 +8,7 @@ Assuming `workbook` is a workbook object:
|
||||
<details>
|
||||
<summary><b>nodejs write a file</b> (click to show)</summary>
|
||||
|
||||
`writeFile` is only available in server environments. Browsers have no API for
|
||||
writing arbitrary files given a path, so another strategy must be used.
|
||||
`XLSX.writeFile` uses `fs.writeFileSync` in server environments:
|
||||
|
||||
```js
|
||||
if(typeof require !== 'undefined') XLSX = require('xlsx');
|
||||
@ -21,7 +20,7 @@ XLSX.writeFile(workbook, 'out.xlsb');
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Browser add to web page</b> (click to show)</summary>
|
||||
<summary><b>Browser add TABLE element to page</b> (click to show)</summary>
|
||||
|
||||
The `sheet_to_html` utility function generates HTML code that can be added to
|
||||
any DOM element.
|
||||
@ -32,29 +31,10 @@ var container = document.getElementById('tableau');
|
||||
container.innerHTML = XLSX.utils.sheet_to_html(worksheet);
|
||||
```
|
||||
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Browser save file</b> (click to show)</summary>
|
||||
|
||||
Note: browser generates binary blob and forces a "download" to client. This
|
||||
example uses [FileSaver](https://github.com/eligrey/FileSaver.js/):
|
||||
|
||||
```js
|
||||
/* bookType can be any supported output type */
|
||||
var wopts = { bookType:'xlsx', bookSST:false, type:'array' };
|
||||
|
||||
var wbout = XLSX.write(workbook,wopts);
|
||||
|
||||
/* the saveAs call downloads a file on the local machine */
|
||||
saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx");
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Browser upload to server</b> (click to show)</summary>
|
||||
<summary><b>Browser upload file (ajax)</b> (click to show)</summary>
|
||||
|
||||
A complete example using XHR is [included in the XHR demo](demos/xhr/), along
|
||||
with examples for fetch and wrapper libraries. This example assumes the server
|
||||
@ -76,6 +56,65 @@ req.send(formdata);
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Browser save file</b> (click to show)</summary>
|
||||
|
||||
`XLSX.writeFile` wraps a few techniques for triggering a file save:
|
||||
|
||||
- `URL` browser API creates an object URL for the file, which the library uses
|
||||
by creating a link and forcing a click. It is supported in modern browsers.
|
||||
- `msSaveBlob` is an IE10+ API for triggering a file save.
|
||||
- `IE_FileSave` uses VBScript and ActiveX to write a file in IE6+ for Windows
|
||||
XP and Windows 7. The shim must be included in the containing HTML page.
|
||||
|
||||
There is no standard way to determine if the actual file has been downloaded.
|
||||
|
||||
```js
|
||||
/* output format determined by filename */
|
||||
XLSX.writeFile(workbook, 'out.xlsb');
|
||||
/* at this point, out.xlsb will have been downloaded */
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Browser save file (compatibility)</b> (click to show)</summary>
|
||||
|
||||
`XLSX.writeFile` techniques work for most modern browsers as well as older IE.
|
||||
For much older browsers, there are workarounds implemented by wrapper libraries.
|
||||
|
||||
[`FileSaver.js`](https://github.com/eligrey/FileSaver.js/) implements `saveAs`.
|
||||
Note: `XLSX.writeFile` will automatically call `saveAs` if available.
|
||||
|
||||
```js
|
||||
/* bookType can be any supported output type */
|
||||
var wopts = { bookType:'xlsx', bookSST:false, type:'array' };
|
||||
|
||||
var wbout = XLSX.write(workbook,wopts);
|
||||
|
||||
/* the saveAs call downloads a file on the local machine */
|
||||
saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx");
|
||||
```
|
||||
|
||||
[`Downloadify`](https://github.com/dcneiner/downloadify) uses a Flash SWF button
|
||||
to generate local files, suitable for environments where ActiveX is unavailable:
|
||||
|
||||
```js
|
||||
Downloadify.create(id,{
|
||||
/* other options are required! read the downloadify docs for more info */
|
||||
filename: "test.xlsx",
|
||||
data: function() { return XLSX.write(wb, {bookType:"xlsx", type:'base64'}); },
|
||||
append: false,
|
||||
dataType: 'base64'
|
||||
});
|
||||
```
|
||||
|
||||
The [`oldie` demo](demos/oldie/) shows an IE-compatible fallback scenario.
|
||||
|
||||
</details>
|
||||
|
||||
The [included demos](demos/) cover mobile apps and other special deployments.
|
||||
|
||||
### Writing Examples
|
||||
|
||||
- <http://sheetjs.com/demos/table.html> exporting an HTML table
|
||||
|
@ -18,7 +18,8 @@ Parse options are described in the [Parsing Options](#parsing-options) section.
|
||||
|
||||
`XLSX.write(wb, write_opts)` attempts to write the workbook `wb`
|
||||
|
||||
`XLSX.writeFile(wb, filename, write_opts)` attempts to write `wb` to `filename`
|
||||
`XLSX.writeFile(wb, filename, write_opts)` attempts to write `wb` to `filename`.
|
||||
In browser-based environments, it will attempt to force a client-side download.
|
||||
|
||||
`XLSX.writeFileAsync(filename, wb, o, cb)` attempts to write `wb` to `filename`.
|
||||
If `o` is omitted, the writer will use the third argument as the callback.
|
||||
|
@ -310,6 +310,7 @@ produces HTML output. The function takes an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :------: | :-------------------------------------------------- |
|
||||
|`id` | | Specify the `id` attribute for the `TABLE` element |
|
||||
|`editable` | false | If true, set `contenteditable="true"` for every TD |
|
||||
|`header` | | Override header (default `html body`) |
|
||||
|`footer` | | Override footer (default `/body /html`) |
|
||||
|
@ -206,6 +206,7 @@ The [`demos` directory](demos/) includes sample projects for:
|
||||
- [`Headless Browsers`](demos/headless/)
|
||||
- [`canvas-datagrid`](demos/datagrid/)
|
||||
- [`Swift JSC and other engines`](demos/altjs/)
|
||||
- [`internet explorer`](demos/oldie/)
|
||||
|
||||
### Optional Modules
|
||||
|
||||
@ -316,7 +317,7 @@ var worksheet = XLSX.read(htmlstr, {type:'string'});
|
||||
|
||||
|
||||
Note: for a more complete example that works in older browsers, check the demo
|
||||
at <http://oss.sheetjs.com/js-xlsx/ajax.html>). The <demos/xhr/> directory also
|
||||
at <http://oss.sheetjs.com/js-xlsx/ajax.html>). The [`xhr` demo](demos/xhr/)
|
||||
includes more examples with `XMLHttpRequest` and `fetch`.
|
||||
|
||||
```js
|
||||
@ -384,6 +385,8 @@ input_dom_element.addEventListener('change', handleFile, false);
|
||||
```
|
||||
|
||||
|
||||
More specialized cases, including mobile app file processing, are covered in the
|
||||
[included demos](demos/)
|
||||
|
||||
### Parsing Examples
|
||||
|
||||
@ -540,8 +543,7 @@ dissemination. The second step is to actual share the data with the end point.
|
||||
Assuming `workbook` is a workbook object:
|
||||
|
||||
|
||||
`writeFile` is only available in server environments. Browsers have no API for
|
||||
writing arbitrary files given a path, so another strategy must be used.
|
||||
`XLSX.writeFile` uses `fs.writeFileSync` in server environments:
|
||||
|
||||
```js
|
||||
if(typeof require !== 'undefined') XLSX = require('xlsx');
|
||||
@ -563,22 +565,6 @@ container.innerHTML = XLSX.utils.sheet_to_html(worksheet);
|
||||
|
||||
|
||||
|
||||
|
||||
Note: browser generates binary blob and forces a "download" to client. This
|
||||
example uses [FileSaver](https://github.com/eligrey/FileSaver.js/):
|
||||
|
||||
```js
|
||||
/* bookType can be any supported output type */
|
||||
var wopts = { bookType:'xlsx', bookSST:false, type:'array' };
|
||||
|
||||
var wbout = XLSX.write(workbook,wopts);
|
||||
|
||||
/* the saveAs call downloads a file on the local machine */
|
||||
saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx");
|
||||
```
|
||||
|
||||
|
||||
|
||||
A complete example using XHR is [included in the XHR demo](demos/xhr/), along
|
||||
with examples for fetch and wrapper libraries. This example assumes the server
|
||||
can handle Base64-encoded files (see the demo for a basic nodejs server):
|
||||
@ -598,6 +584,59 @@ req.send(formdata);
|
||||
```
|
||||
|
||||
|
||||
|
||||
`XLSX.writeFile` wraps a few techniques for triggering a file save:
|
||||
|
||||
- `URL` browser API creates an object URL for the file, which the library uses
|
||||
by creating a link and forcing a click. It is supported in modern browsers.
|
||||
- `msSaveBlob` is an IE10+ API for triggering a file save.
|
||||
- `IE_FileSave` uses VBScript and ActiveX to write a file in IE6+ for Windows
|
||||
XP and Windows 7. The shim must be included in the containing HTML page.
|
||||
|
||||
There is no standard way to determine if the actual file has been downloaded.
|
||||
|
||||
```js
|
||||
/* output format determined by filename */
|
||||
XLSX.writeFile(workbook, 'out.xlsb');
|
||||
/* at this point, out.xlsb will have been downloaded */
|
||||
```
|
||||
|
||||
|
||||
|
||||
`XLSX.writeFile` techniques work for most modern browsers as well as older IE.
|
||||
For much older browsers, there are workarounds implemented by wrapper libraries.
|
||||
|
||||
[`FileSaver.js`](https://github.com/eligrey/FileSaver.js/) implements `saveAs`.
|
||||
Note: `XLSX.writeFile` will automatically call `saveAs` if available.
|
||||
|
||||
```js
|
||||
/* bookType can be any supported output type */
|
||||
var wopts = { bookType:'xlsx', bookSST:false, type:'array' };
|
||||
|
||||
var wbout = XLSX.write(workbook,wopts);
|
||||
|
||||
/* the saveAs call downloads a file on the local machine */
|
||||
saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx");
|
||||
```
|
||||
|
||||
[`Downloadify`](https://github.com/dcneiner/downloadify) uses a Flash SWF button
|
||||
to generate local files, suitable for environments where ActiveX is unavailable:
|
||||
|
||||
```js
|
||||
Downloadify.create(id,{
|
||||
/* other options are required! read the downloadify docs for more info */
|
||||
filename: "test.xlsx",
|
||||
data: function() { return XLSX.write(wb, {bookType:"xlsx", type:'base64'}); },
|
||||
append: false,
|
||||
dataType: 'base64'
|
||||
});
|
||||
```
|
||||
|
||||
The [`oldie` demo](demos/oldie/) shows an IE-compatible fallback scenario.
|
||||
|
||||
|
||||
The [included demos](demos/) cover mobile apps and other special deployments.
|
||||
|
||||
### Writing Examples
|
||||
|
||||
- <http://sheetjs.com/demos/table.html> exporting an HTML table
|
||||
@ -642,7 +681,8 @@ Parse options are described in the [Parsing Options](#parsing-options) section.
|
||||
|
||||
`XLSX.write(wb, write_opts)` attempts to write the workbook `wb`
|
||||
|
||||
`XLSX.writeFile(wb, filename, write_opts)` attempts to write `wb` to `filename`
|
||||
`XLSX.writeFile(wb, filename, write_opts)` attempts to write `wb` to `filename`.
|
||||
In browser-based environments, it will attempt to force a client-side download.
|
||||
|
||||
`XLSX.writeFileAsync(filename, wb, o, cb)` attempts to write `wb` to `filename`.
|
||||
If `o` is omitted, the writer will use the third argument as the callback.
|
||||
@ -1859,6 +1899,7 @@ produces HTML output. The function takes an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :------: | :-------------------------------------------------- |
|
||||
|`id` | | Specify the `id` attribute for the `TABLE` element |
|
||||
|`editable` | false | If true, set `contenteditable="true"` for every TD |
|
||||
|`header` | | Override header (default `html body`) |
|
||||
|`footer` | | Override footer (default `/body /html`) |
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xlsx",
|
||||
"version": "0.11.18",
|
||||
"version": "0.11.19",
|
||||
"author": "sheetjs",
|
||||
"description": "SheetJS Spreadsheet data parser and writer",
|
||||
"keywords": [
|
||||
|
27
shim.js
27
shim.js
@ -341,3 +341,30 @@ if(typeof Uint8Array !== 'undefined' && !Uint8Array.prototype.slice) Uint8Array.
|
||||
while(start <= --end) out[end - start] = this[end];
|
||||
return out;
|
||||
};
|
||||
|
||||
// VBScript + ActiveX fallback for IE5+
|
||||
var IE_SaveFile = (function() { try {
|
||||
if(typeof IE_SaveFile_Impl == "undefined") document.write([
|
||||
'<script type="text/vbscript" language="vbscript">',
|
||||
'IE_GetProfileAndPath_Key = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\"',
|
||||
'Function IE_GetProfileAndPath(key): Set wshell = CreateObject("WScript.Shell"): IE_GetProfileAndPath = wshell.RegRead(IE_GetProfileAndPath_Key & key): IE_GetProfileAndPath = wshell.ExpandEnvironmentStrings("%USERPROFILE%") & "!" & IE_GetProfileAndPath: End Function',
|
||||
'Function IE_SaveFile_Impl(FileName, payload): Dim data, plen, i, bit: data = CStr(payload): plen = Len(data): Set fso = CreateObject("Scripting.FileSystemObject"): fso.CreateTextFile FileName, True: Set f = fso.GetFile(FileName): Set stream = f.OpenAsTextStream(2, 0): For i = 1 To plen Step 3: bit = Mid(data, i, 2): stream.write Chr(CLng("&h" & bit)): Next: stream.Close: IE_SaveFile_Impl = True: End Function',
|
||||
'|/script>'.replace("|","<")
|
||||
].join("\r\n"));
|
||||
if(typeof IE_SaveFile_Impl == "undefined") return void 0;
|
||||
var IE_GetPath = (function() {
|
||||
var DDP1 = "";
|
||||
try { DDP1 = IE_GetProfileAndPath("{374DE290-123F-4565-9164-39C4925E467B}"); } catch(e) { try { DDP1 = IE_GetProfileAndPath("Personal"); } catch(e) { try { DDP1 = IE_GetProfileAndPath("Desktop"); } catch(e) { throw e; }}}
|
||||
var o = DDP1.split("!");
|
||||
DDP = o[1].replace("%USERPROFILE%", o[0]);
|
||||
return function(path) { return DDP + "\\" + path; };
|
||||
})();
|
||||
function fix_data(data) {
|
||||
var out = [];
|
||||
var T = typeof data == "string";
|
||||
for(var i = 0; i < data.length; ++i) out.push(("00"+(T ? data.charCodeAt(i) : data[i]).toString(16)).slice(-2));
|
||||
var o = out.join("|");
|
||||
return o;
|
||||
}
|
||||
return function(data, filename) { return IE_SaveFile_Impl(IE_GetPath(filename), fix_data(data)); };
|
||||
} catch(e) { return void 0; }})();
|
||||
|
40
test.js
40
test.js
@ -1,7 +1,9 @@
|
||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
/* vim: set ts=2: */
|
||||
/*jshint mocha:true */
|
||||
/* eslint-env mocha */
|
||||
/*global process, document, require */
|
||||
/*global ArrayBuffer, Uint8Array */
|
||||
/*::
|
||||
declare type EmptyFunc = (() => void) | null;
|
||||
declare type DescribeIt = { (desc:string, test:EmptyFunc):void; skip(desc:string, test:EmptyFunc):void; };
|
||||
@ -190,7 +192,6 @@ var MCPaths = pathit("mc", ["xlsx", "xlsb", "xls", "xml", "ods"]);
|
||||
var CSSPaths = pathit("css", ["xlsx", "xlsb", "xls", "xml"]);
|
||||
var NFPaths = pathit("nf", ["xlsx", "xlsb", "xls", "xml"]);
|
||||
var DTPaths = pathit("dt", ["xlsx", "xlsb", "xls", "xml"]);
|
||||
var NFPaths = pathit("nf", ["xlsx", "xlsb", "xls", "xml"]);
|
||||
var HLPaths = pathit("hl", ["xlsx", "xlsb", "xls", "xml"]);
|
||||
var ILPaths = pathit("il", ["xlsx", "xlsb", "xls", "xml", "ods", "xls5"]);
|
||||
var OLPaths = pathit("ol", ["xlsx", "xlsb", "xls", "ods", "xls5"]);
|
||||
@ -318,12 +319,11 @@ var wbtable = {};
|
||||
wbtable[dir + x] = wb;
|
||||
parsetest(x, wb, true);
|
||||
});
|
||||
fullex.forEach(function(ext, idx) {
|
||||
fullex.forEach(function(ext) {
|
||||
it(x + ' [' + ext + ']', function(){
|
||||
var wb = wbtable[dir + x];
|
||||
if(!wb) wb = X.readFile(dir + x, opts);
|
||||
wb = X.read(X.write(wb, {type:"buffer", bookType:ext.replace(/\./,"")}), {WTF:opts.WTF, cellNF: true});
|
||||
|
||||
parsetest(x, wb, ext.replace(/\./,"") !== "xlsb", ext);
|
||||
});
|
||||
});
|
||||
@ -471,7 +471,7 @@ describe('parse options', function() {
|
||||
[paths.cssxlsx /*, paths.cssxlsb, paths.cssxls, paths.cssxml*/].forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE, cellStyles:true});
|
||||
var found = false;
|
||||
each_sheet(wb, function(ws, i) { each_cell(ws, function(cell) {
|
||||
each_sheet(wb, function(ws/*::, i*/) { /*:: void i; */each_cell(ws, function(cell) {
|
||||
if(typeof cell.s !== 'undefined') return (found = true);
|
||||
}); });
|
||||
assert(found);
|
||||
@ -480,7 +480,7 @@ describe('parse options', function() {
|
||||
it('should not generate cell dates by default', function() {
|
||||
DTPaths.forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE});
|
||||
each_sheet(wb, function(ws, i) { each_cell(ws, function(cell) {
|
||||
each_sheet(wb, function(ws/*::, i*/) { /*:: void i; */each_cell(ws, function(cell) {
|
||||
assert(cell.t !== 'd');
|
||||
}); });
|
||||
});
|
||||
@ -489,7 +489,7 @@ describe('parse options', function() {
|
||||
DTPaths.forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE, cellDates: true, WTF:1});
|
||||
var found = false;
|
||||
each_sheet(wb, function(ws, i) { each_cell(ws, function(cell) {
|
||||
each_sheet(wb, function(ws/*::, i*/) { /*:: void i; */each_cell(ws, function(cell) {
|
||||
if(cell.t === 'd') return (found = true);
|
||||
}); });
|
||||
assert(found);
|
||||
@ -911,7 +911,7 @@ describe('parse features', function() {
|
||||
var wbs = [], wbs_no_slk = [];
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
wbs = CWPaths.map(function(n) { return X.read(fs.readFileSync(CWPaths[0]), {type:TYPE, cellStyles:true}); });
|
||||
wbs = CWPaths.map(function(n) { return X.read(fs.readFileSync(n), {type:TYPE, cellStyles:true}); });
|
||||
wbs_no_slk = wbs.slice(0, 5);
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
@ -1172,6 +1172,7 @@ describe('parse features', function() {
|
||||
'A3:A10', 'B3:B10', 'E1:E10', 'F6:F8', /* cols */
|
||||
'H1:J4', 'H10' /* blocks */
|
||||
];
|
||||
/*eslint-disable */
|
||||
var exp/*:Array<any>*/ = [
|
||||
{ patternType: 'darkHorizontal',
|
||||
fgColor: { theme: 9, raw_rgb: 'F79646' },
|
||||
@ -1198,6 +1199,7 @@ describe('parse features', function() {
|
||||
fgColor: { theme: 3, raw_rgb: 'EEECE1' },
|
||||
bgColor: { theme: 7, raw_rgb: '8064A2' } }
|
||||
];
|
||||
/*eslint-enable */
|
||||
ranges.forEach(function(rng) {
|
||||
it('XLS | ' + rng,function(){cmparr(rn2(rng).map(function(x){ return get_cell(wsxls,x).s; }));});
|
||||
it('XLSX | ' + rng,function(){cmparr(rn2(rng).map(function(x){ return get_cell(wsxlsx,x).s; }));});
|
||||
@ -1699,7 +1701,7 @@ describe('json output', function() {
|
||||
});
|
||||
it('should preserve values when column header is missing', function() {
|
||||
/*jshint elision:true */
|
||||
var _data = [[,"a","b",,"c"], [1,2,3,,5],[,3,4,5,6]];
|
||||
var _data = [[,"a","b",,"c"], [1,2,3,,5],[,3,4,5,6]]; // eslint-disable-line no-sparse-arrays
|
||||
/*jshint elision:false */
|
||||
var _ws = X.utils.aoa_to_sheet(_data);
|
||||
var json1 = X.utils.sheet_to_json(_ws, { raw: true });
|
||||
@ -1721,7 +1723,7 @@ var plaintext_val = [
|
||||
["B3", 's', " ", " "],
|
||||
["A3"]
|
||||
];
|
||||
function plaintext_test(wb, raw, t) {
|
||||
function plaintext_test(wb, raw) {
|
||||
var sheet = wb.Sheets[wb.SheetNames[0]];
|
||||
plaintext_val.forEach(function(x) {
|
||||
var cell = get_cell(sheet, x[0]);
|
||||
@ -1791,8 +1793,8 @@ describe('CSV', function() {
|
||||
assert.equal(cell.v.getMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
});
|
||||
it('should interpret values by default', function() { plaintext_test(X.read(csv_bstr, {type:"binary"}), false, false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(csv_str, {type:"string", raw:true}), true, false); });
|
||||
it('should interpret values by default', function() { plaintext_test(X.read(csv_bstr, {type:"binary"}), false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(csv_str, {type:"string", raw:true}), true); });
|
||||
it('should handle formulae', function() {
|
||||
var bb = '=,=1+1,="100"';
|
||||
var sheet = X.read(bb, {type:"binary"}).Sheets.Sheet1;
|
||||
@ -1921,9 +1923,9 @@ function get_dom_element(html) {
|
||||
|
||||
describe('HTML', function() {
|
||||
describe('input string', function(){
|
||||
it('should interpret values by default', function() { plaintext_test(X.read(html_bstr, {type:"binary"}), false, false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(html_bstr, {type:"binary", raw:true}), true, false); });
|
||||
it('should handle "string" type', function() { plaintext_test(X.read(html_str, {type:"string"}), false, false); });
|
||||
it('should interpret values by default', function() { plaintext_test(X.read(html_bstr, {type:"binary"}), false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(html_bstr, {type:"binary", raw:true}), true); });
|
||||
it('should handle "string" type', function() { plaintext_test(X.read(html_str, {type:"string"}), false); });
|
||||
it('should handle newlines correctly', function() {
|
||||
var table = "<table><tr><td>foo<br/>bar</td><td>baz</td></tr></table>";
|
||||
var wb = X.read(table, {type:"string"});
|
||||
@ -1931,8 +1933,8 @@ describe('HTML', function() {
|
||||
});
|
||||
});
|
||||
(domtest ? describe : describe.skip)('input DOM', function() {
|
||||
it('should interpret values by default', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str)), false, true); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str), {raw:true}), true, true); });
|
||||
it('should interpret values by default', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str)), false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str), {raw:true}), true); });
|
||||
it('should handle newlines correctly', function() {
|
||||
var table = get_dom_element("<table><tr><td>foo<br/>bar</td><td>baz</td></tr></table>");
|
||||
var ws = X.utils.table_to_sheet(table);
|
||||
@ -2030,14 +2032,14 @@ describe('corner cases', function() {
|
||||
});
|
||||
it('SSF', function() {
|
||||
X.SSF.format("General", "dafuq");
|
||||
assert.throws(function(x) { return X.SSF.format("General", {sheet:"js"});});
|
||||
assert.throws(function() { return X.SSF.format("General", {sheet:"js"});});
|
||||
X.SSF.format("b e ddd hh AM/PM", 41722.4097222222);
|
||||
X.SSF.format("b ddd hh m", 41722.4097222222);
|
||||
["hhh","hhh A/P","hhmmm","sss","[hhh]","G eneral"].forEach(function(f) {
|
||||
assert.throws(function(x) { return X.SSF.format(f, 12345.6789);});
|
||||
assert.throws(function() { return X.SSF.format(f, 12345.6789);});
|
||||
});
|
||||
["[m]","[s]"].forEach(function(f) {
|
||||
assert.doesNotThrow(function(x) { return X.SSF.format(f, 12345.6789);});
|
||||
assert.doesNotThrow(function() { return X.SSF.format(f, 12345.6789);});
|
||||
});
|
||||
});
|
||||
if(typeof JSON !== 'undefined') it('SSF oddities', function() {
|
||||
|
@ -439,7 +439,7 @@ smart_tags_2007.xlsx
|
||||
spout-xlsx_attack_billion_laughs.xlsx
|
||||
spout-xlsx_attack_quadratic_blowup.xlsx
|
||||
# spout-xlsx_file_corrupted.xlsx
|
||||
spout-xlsx_file_with_no_sheets_in_workbook_xml.xlsx
|
||||
# spout-xlsx_file_with_no_sheets_in_workbook_xml.xlsx # explicit error on RT
|
||||
# spout-xlsx_file_with_sheet_xml_not_matching_content_types.xlsx
|
||||
spout-xlsx_one_sheet_with_inline_strings.xlsx
|
||||
spout-xlsx_one_sheet_with_invalid_xml_characters.xlsx
|
||||
|
41
tests/core.js
generated
41
tests/core.js
generated
@ -1,7 +1,9 @@
|
||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
/* vim: set ts=2: */
|
||||
/*jshint mocha:true */
|
||||
/* eslint-env mocha */
|
||||
/*global process, document, require */
|
||||
/*global ArrayBuffer, Uint8Array */
|
||||
/*::
|
||||
declare type EmptyFunc = (() => void) | null;
|
||||
declare type DescribeIt = { (desc:string, test:EmptyFunc):void; skip(desc:string, test:EmptyFunc):void; };
|
||||
@ -17,6 +19,7 @@ describe('source',function(){it('should load',function(){X=require(modp);});});
|
||||
var DIF_XL = true;
|
||||
|
||||
var browser = typeof document !== 'undefined';
|
||||
// $FlowIgnore
|
||||
if(!browser) try { require('./shim'); } catch(e) { }
|
||||
|
||||
var opts = ({cellNF: true}/*:any*/);
|
||||
@ -189,7 +192,6 @@ var MCPaths = pathit("mc", ["xlsx", "xlsb", "xls", "xml", "ods"]);
|
||||
var CSSPaths = pathit("css", ["xlsx", "xlsb", "xls", "xml"]);
|
||||
var NFPaths = pathit("nf", ["xlsx", "xlsb", "xls", "xml"]);
|
||||
var DTPaths = pathit("dt", ["xlsx", "xlsb", "xls", "xml"]);
|
||||
var NFPaths = pathit("nf", ["xlsx", "xlsb", "xls", "xml"]);
|
||||
var HLPaths = pathit("hl", ["xlsx", "xlsb", "xls", "xml"]);
|
||||
var ILPaths = pathit("il", ["xlsx", "xlsb", "xls", "xml", "ods", "xls5"]);
|
||||
var OLPaths = pathit("ol", ["xlsx", "xlsb", "xls", "ods", "xls5"]);
|
||||
@ -317,12 +319,11 @@ var wbtable = {};
|
||||
wbtable[dir + x] = wb;
|
||||
parsetest(x, wb, true);
|
||||
});
|
||||
fullex.forEach(function(ext, idx) {
|
||||
fullex.forEach(function(ext) {
|
||||
it(x + ' [' + ext + ']', function(){
|
||||
var wb = wbtable[dir + x];
|
||||
if(!wb) wb = X.readFile(dir + x, opts);
|
||||
wb = X.read(X.write(wb, {type:"buffer", bookType:ext.replace(/\./,"")}), {WTF:opts.WTF, cellNF: true});
|
||||
|
||||
parsetest(x, wb, ext.replace(/\./,"") !== "xlsb", ext);
|
||||
});
|
||||
});
|
||||
@ -470,7 +471,7 @@ describe('parse options', function() {
|
||||
[paths.cssxlsx /*, paths.cssxlsb, paths.cssxls, paths.cssxml*/].forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE, cellStyles:true});
|
||||
var found = false;
|
||||
each_sheet(wb, function(ws, i) { each_cell(ws, function(cell) {
|
||||
each_sheet(wb, function(ws/*::, i*/) { /*:: void i; */each_cell(ws, function(cell) {
|
||||
if(typeof cell.s !== 'undefined') return (found = true);
|
||||
}); });
|
||||
assert(found);
|
||||
@ -479,7 +480,7 @@ describe('parse options', function() {
|
||||
it('should not generate cell dates by default', function() {
|
||||
DTPaths.forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE});
|
||||
each_sheet(wb, function(ws, i) { each_cell(ws, function(cell) {
|
||||
each_sheet(wb, function(ws/*::, i*/) { /*:: void i; */each_cell(ws, function(cell) {
|
||||
assert(cell.t !== 'd');
|
||||
}); });
|
||||
});
|
||||
@ -488,7 +489,7 @@ describe('parse options', function() {
|
||||
DTPaths.forEach(function(p) {
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE, cellDates: true, WTF:1});
|
||||
var found = false;
|
||||
each_sheet(wb, function(ws, i) { each_cell(ws, function(cell) {
|
||||
each_sheet(wb, function(ws/*::, i*/) { /*:: void i; */each_cell(ws, function(cell) {
|
||||
if(cell.t === 'd') return (found = true);
|
||||
}); });
|
||||
assert(found);
|
||||
@ -910,7 +911,7 @@ describe('parse features', function() {
|
||||
var wbs = [], wbs_no_slk = [];
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
wbs = CWPaths.map(function(n) { return X.read(fs.readFileSync(CWPaths[0]), {type:TYPE, cellStyles:true}); });
|
||||
wbs = CWPaths.map(function(n) { return X.read(fs.readFileSync(n), {type:TYPE, cellStyles:true}); });
|
||||
wbs_no_slk = wbs.slice(0, 5);
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
@ -1171,6 +1172,7 @@ describe('parse features', function() {
|
||||
'A3:A10', 'B3:B10', 'E1:E10', 'F6:F8', /* cols */
|
||||
'H1:J4', 'H10' /* blocks */
|
||||
];
|
||||
/*eslint-disable */
|
||||
var exp/*:Array<any>*/ = [
|
||||
{ patternType: 'darkHorizontal',
|
||||
fgColor: { theme: 9, raw_rgb: 'F79646' },
|
||||
@ -1197,6 +1199,7 @@ describe('parse features', function() {
|
||||
fgColor: { theme: 3, raw_rgb: 'EEECE1' },
|
||||
bgColor: { theme: 7, raw_rgb: '8064A2' } }
|
||||
];
|
||||
/*eslint-enable */
|
||||
ranges.forEach(function(rng) {
|
||||
it('XLS | ' + rng,function(){cmparr(rn2(rng).map(function(x){ return get_cell(wsxls,x).s; }));});
|
||||
it('XLSX | ' + rng,function(){cmparr(rn2(rng).map(function(x){ return get_cell(wsxlsx,x).s; }));});
|
||||
@ -1698,7 +1701,7 @@ describe('json output', function() {
|
||||
});
|
||||
it('should preserve values when column header is missing', function() {
|
||||
/*jshint elision:true */
|
||||
var _data = [[,"a","b",,"c"], [1,2,3,,5],[,3,4,5,6]];
|
||||
var _data = [[,"a","b",,"c"], [1,2,3,,5],[,3,4,5,6]]; // eslint-disable-line no-sparse-arrays
|
||||
/*jshint elision:false */
|
||||
var _ws = X.utils.aoa_to_sheet(_data);
|
||||
var json1 = X.utils.sheet_to_json(_ws, { raw: true });
|
||||
@ -1720,7 +1723,7 @@ var plaintext_val = [
|
||||
["B3", 's', " ", " "],
|
||||
["A3"]
|
||||
];
|
||||
function plaintext_test(wb, raw, t) {
|
||||
function plaintext_test(wb, raw) {
|
||||
var sheet = wb.Sheets[wb.SheetNames[0]];
|
||||
plaintext_val.forEach(function(x) {
|
||||
var cell = get_cell(sheet, x[0]);
|
||||
@ -1790,8 +1793,8 @@ describe('CSV', function() {
|
||||
assert.equal(cell.v.getMonth(), 2);
|
||||
assert.equal(cell.w, "2/3/14");
|
||||
});
|
||||
it('should interpret values by default', function() { plaintext_test(X.read(csv_bstr, {type:"binary"}), false, false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(csv_str, {type:"string", raw:true}), true, false); });
|
||||
it('should interpret values by default', function() { plaintext_test(X.read(csv_bstr, {type:"binary"}), false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(csv_str, {type:"string", raw:true}), true); });
|
||||
it('should handle formulae', function() {
|
||||
var bb = '=,=1+1,="100"';
|
||||
var sheet = X.read(bb, {type:"binary"}).Sheets.Sheet1;
|
||||
@ -1920,9 +1923,9 @@ function get_dom_element(html) {
|
||||
|
||||
describe('HTML', function() {
|
||||
describe('input string', function(){
|
||||
it('should interpret values by default', function() { plaintext_test(X.read(html_bstr, {type:"binary"}), false, false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(html_bstr, {type:"binary", raw:true}), true, false); });
|
||||
it('should handle "string" type', function() { plaintext_test(X.read(html_str, {type:"string"}), false, false); });
|
||||
it('should interpret values by default', function() { plaintext_test(X.read(html_bstr, {type:"binary"}), false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.read(html_bstr, {type:"binary", raw:true}), true); });
|
||||
it('should handle "string" type', function() { plaintext_test(X.read(html_str, {type:"string"}), false); });
|
||||
it('should handle newlines correctly', function() {
|
||||
var table = "<table><tr><td>foo<br/>bar</td><td>baz</td></tr></table>";
|
||||
var wb = X.read(table, {type:"string"});
|
||||
@ -1930,8 +1933,8 @@ describe('HTML', function() {
|
||||
});
|
||||
});
|
||||
(domtest ? describe : describe.skip)('input DOM', function() {
|
||||
it('should interpret values by default', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str)), false, true); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str), {raw:true}), true, true); });
|
||||
it('should interpret values by default', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str)), false); });
|
||||
it('should generate strings if raw option is passed', function() { plaintext_test(X.utils.table_to_book(get_dom_element(html_str), {raw:true}), true); });
|
||||
it('should handle newlines correctly', function() {
|
||||
var table = get_dom_element("<table><tr><td>foo<br/>bar</td><td>baz</td></tr></table>");
|
||||
var ws = X.utils.table_to_sheet(table);
|
||||
@ -2029,14 +2032,14 @@ describe('corner cases', function() {
|
||||
});
|
||||
it('SSF', function() {
|
||||
X.SSF.format("General", "dafuq");
|
||||
assert.throws(function(x) { return X.SSF.format("General", {sheet:"js"});});
|
||||
assert.throws(function() { return X.SSF.format("General", {sheet:"js"});});
|
||||
X.SSF.format("b e ddd hh AM/PM", 41722.4097222222);
|
||||
X.SSF.format("b ddd hh m", 41722.4097222222);
|
||||
["hhh","hhh A/P","hhmmm","sss","[hhh]","G eneral"].forEach(function(f) {
|
||||
assert.throws(function(x) { return X.SSF.format(f, 12345.6789);});
|
||||
assert.throws(function() { return X.SSF.format(f, 12345.6789);});
|
||||
});
|
||||
["[m]","[s]"].forEach(function(f) {
|
||||
assert.doesNotThrow(function(x) { return X.SSF.format(f, 12345.6789);});
|
||||
assert.doesNotThrow(function() { return X.SSF.format(f, 12345.6789);});
|
||||
});
|
||||
});
|
||||
if(typeof JSON !== 'undefined') it('SSF oddities', function() {
|
||||
|
40
tests/write.html
Normal file
40
tests/write.html
Normal file
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- (C) 2013-present SheetJS http://sheetjs.com -->
|
||||
<!-- vim: set ts=2: -->
|
||||
<html>
|
||||
<head>
|
||||
<title>SheetJS JS-XLSX In-Browser Export Demo</title>
|
||||
<meta charset="utf-8" />
|
||||
<style>
|
||||
a { text-decoration: none }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<pre>
|
||||
<h3><a href="//sheetjs.com/">SheetJS</a> JS-XLSX In-Browser Export Demo</h3>
|
||||
<b>Example Code</b>
|
||||
|
||||
/* Generate Workbook */
|
||||
var wb = XLSX.utils.book_new();
|
||||
var ws = XLSX.utils.aoa_to_sheet([["a","b"],[1,2,3]]);
|
||||
XLSX.utils.book_append_sheet(wb, ws, "SheetJS");
|
||||
|
||||
/* Trigger Download with `writeFile` */
|
||||
XLSX.writeFile(wb, "SheetJS.xlsb", {compression:true});
|
||||
|
||||
<b>Download Generation Methods:</b>
|
||||
|
||||
- IE6-9 require ActiveX and Windows Script support.
|
||||
The IE_SaveFile function from the included shim uses VBScript.
|
||||
|
||||
- IE10-11 use msSaveBlob API.
|
||||
|
||||
- When supported, `saveAs` will be used.
|
||||
|
||||
- When available, modern browsers use `URL.createObjectURL`.
|
||||
|
||||
</pre>
|
||||
<script src="shim.js"></script>
|
||||
<script src="xlsx.full.min.js"></script>
|
||||
<script src="write.js"></script>
|
||||
</body>
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
7
types/index.d.ts
vendored
7
types/index.d.ts
vendored
@ -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;
|
||||
|
||||
|
79
xlsx.flow.js
79
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<string>*/ = []; for(var i = 0; i < data.length; ++i) o[i] = _chr(data[i]); return o.join("");
|
||||
}
|
||||
|
||||
function a2u(data/*:Array<number>*/)/*:Uint8Array*/ {
|
||||
if(typeof Uint8Array === 'undefined') throw new Error("Unsupported");
|
||||
return new Uint8Array(data);
|
||||
}
|
||||
|
||||
function ab2a(data/*:ArrayBuffer|Uint8Array*/)/*:Array<number>*/ {
|
||||
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<any>*/ { 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 = "<tr>";
|
||||
return preamble + oo.join("") + "</tr>";
|
||||
}
|
||||
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<string>*/ = [];
|
||||
return out.join("") + '<table>';
|
||||
return out.join("") + '<table' + (o && o.id ? ' id="' + o.id + '"' : "") + '>';
|
||||
}
|
||||
var _BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
|
||||
var _END = '</body></html>';
|
||||
@ -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<string>*/ {
|
||||
|
75
xlsx.js
generated
75
xlsx.js
generated
@ -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 = "<tr>";
|
||||
return preamble + oo.join("") + "</tr>";
|
||||
}
|
||||
function make_html_preamble() {
|
||||
function make_html_preamble(ws, R, o) {
|
||||
var out = [];
|
||||
return out.join("") + '<table>';
|
||||
return out.join("") + '<table' + (o && o.id ? ' id="' + o.id + '"' : "") + '>';
|
||||
}
|
||||
var _BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
|
||||
var _END = '</body></html>';
|
||||
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user