forked from sheetjs/sheetjs
		
	version bump 0.12.7: chrome extension
- `writeFile` support chrome extension (fixes #1051 h/t @atkinsam) - demo refresh
This commit is contained in:
		
							parent
							
								
									dc2128caca
								
							
						
					
					
						commit
						08bb7e6e60
					
				@ -90,24 +90,28 @@ prepend
 | 
			
		||||
prepended
 | 
			
		||||
repo
 | 
			
		||||
runtime
 | 
			
		||||
serverless
 | 
			
		||||
submodule
 | 
			
		||||
transpiled
 | 
			
		||||
 | 
			
		||||
 - demos/altjs/README.md
 | 
			
		||||
ChakraCore
 | 
			
		||||
Duktape
 | 
			
		||||
Goja
 | 
			
		||||
Nashorn
 | 
			
		||||
 | 
			
		||||
 - demos/angular/README.md
 | 
			
		||||
AngularJS
 | 
			
		||||
 
 | 
			
		||||
 - demos/angular2/README.md
 | 
			
		||||
NativeScript
 | 
			
		||||
angular-cli
 | 
			
		||||
 | 
			
		||||
 - demos/database/README.md
 | 
			
		||||
Knex
 | 
			
		||||
LowDB
 | 
			
		||||
MariaDB
 | 
			
		||||
MongoDB
 | 
			
		||||
MySQL
 | 
			
		||||
PostgreSQL
 | 
			
		||||
schemaless
 | 
			
		||||
@ -118,6 +122,9 @@ storages
 | 
			
		||||
Photoshop
 | 
			
		||||
minifier
 | 
			
		||||
 | 
			
		||||
 - demos/function/README.md
 | 
			
		||||
microservice
 | 
			
		||||
 | 
			
		||||
 - demos/headless/README.md
 | 
			
		||||
PhantomJS
 | 
			
		||||
SlimerJS
 | 
			
		||||
 | 
			
		||||
@ -212,10 +212,12 @@ The [`demos` directory](demos/) includes sample projects for:
 | 
			
		||||
**Platforms and Integrations**
 | 
			
		||||
- [`electron application`](demos/electron/)
 | 
			
		||||
- [`nw.js application`](demos/nwjs/)
 | 
			
		||||
- [`Chrome / Chromium extensions`](demos/chrome/)
 | 
			
		||||
- [`Adobe ExtendScript`](demos/extendscript/)
 | 
			
		||||
- [`Headless Browsers`](demos/headless/)
 | 
			
		||||
- [`canvas-datagrid`](demos/datagrid/)
 | 
			
		||||
- [`Swift JSC and other engines`](demos/altjs/)
 | 
			
		||||
- [`"serverless" functions`](demos/function/)
 | 
			
		||||
- [`internet explorer`](demos/oldie/)
 | 
			
		||||
 | 
			
		||||
### Optional Modules
 | 
			
		||||
 | 
			
		||||
@ -1 +1 @@
 | 
			
		||||
XLSX.version = '0.12.6';
 | 
			
		||||
XLSX.version = '0.12.7';
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,7 @@ function blobify(data) {
 | 
			
		||||
}
 | 
			
		||||
/* write or download file */
 | 
			
		||||
function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
 | 
			
		||||
	/*global IE_SaveFile, Blob, navigator, saveAs, URL, document, File */
 | 
			
		||||
	/*global IE_SaveFile, Blob, navigator, saveAs, URL, document, File, chrome */
 | 
			
		||||
	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; */
 | 
			
		||||
@ -21,9 +21,14 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
 | 
			
		||||
		/*:: declare var saveAs: any; */
 | 
			
		||||
		if(typeof saveAs !== 'undefined') return saveAs(blob, fname);
 | 
			
		||||
		if(typeof URL !== 'undefined' && typeof document !== 'undefined' && document.createElement && URL.createObjectURL) {
 | 
			
		||||
			var url = URL.createObjectURL(blob);
 | 
			
		||||
			/*:: declare var chrome: any; */
 | 
			
		||||
			if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
 | 
			
		||||
				if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
 | 
			
		||||
				return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
 | 
			
		||||
			}
 | 
			
		||||
			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);
 | 
			
		||||
 | 
			
		||||
@ -40,10 +40,12 @@ can be installed with Bash on Windows or with `cygwin`.
 | 
			
		||||
**Platforms and Integrations**
 | 
			
		||||
- [`electron application`](electron/)
 | 
			
		||||
- [`nw.js application`](nwjs/)
 | 
			
		||||
- [`Chrome / Chromium extensions`](chrome/)
 | 
			
		||||
- [`Adobe ExtendScript`](extendscript/)
 | 
			
		||||
- [`Headless Browsers`](headless/)
 | 
			
		||||
- [`canvas-datagrid`](datagrid/)
 | 
			
		||||
- [`Swift JSC and other engines`](altjs/)
 | 
			
		||||
- [`"serverless" functions`](function/)
 | 
			
		||||
- [`internet explorer`](oldie/)
 | 
			
		||||
 | 
			
		||||
[](https://github.com/SheetJS/js-xlsx)
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
.PHONY: all
 | 
			
		||||
all: duktape nashorn rhinojs swift
 | 
			
		||||
all: duktape nashorn rhinojs swift goja
 | 
			
		||||
 | 
			
		||||
.PHONY: base
 | 
			
		||||
base:
 | 
			
		||||
@ -25,6 +25,12 @@ swift: base ## swift demo
 | 
			
		||||
	swiftc SheetJSCore.swift main.swift -o SheetJSSwift
 | 
			
		||||
	./SheetJSSwift
 | 
			
		||||
 | 
			
		||||
.PHONY: goja
 | 
			
		||||
goja: base ## goja demo
 | 
			
		||||
	if [ ! -e xlsx.core.min.js ]; then cp ../../dist/xlsx.core.min.js .; fi
 | 
			
		||||
	go build goja.go
 | 
			
		||||
	for ext in xlsx xlsb biff8.xls xml.xls; do ./goja sheetjs.$$ext; done
 | 
			
		||||
 | 
			
		||||
.PHONY: chakra
 | 
			
		||||
chakra: base ## Chakra demo
 | 
			
		||||
	node -pe "fs.writeFileSync('payload.js', 'var payload = \"' + fs.readFileSync('sheetjs.xlsx').toString('base64') + '\";')"
 | 
			
		||||
 | 
			
		||||
@ -124,4 +124,33 @@ char *buf = (char *)duk_get_buffer_data(ctx, -1, sz);
 | 
			
		||||
duk_pop(ctx);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Goja
 | 
			
		||||
 | 
			
		||||
Goja is a pure Go implementation of ECMAScript 5.  As of this writing, there are
 | 
			
		||||
some issues with processing Unicode data, but the `xlsx.core.min.js` script can
 | 
			
		||||
be processed.  `[]byte` should be transformed to a binary string in the engine:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
/* read file */
 | 
			
		||||
data, _ := ioutil.ReadFile("sheetjs.xlsx")
 | 
			
		||||
 | 
			
		||||
/* load into engine */
 | 
			
		||||
vm.Set("buf", data)
 | 
			
		||||
 | 
			
		||||
/* convert to binary string */
 | 
			
		||||
_, _ = vm.RunString("var bstr = ''; for(var i = 0; i < buf.length; ++i) bstr += String.fromCharCode(buf[i]);")
 | 
			
		||||
 | 
			
		||||
/* parse */
 | 
			
		||||
wb, _ = vm.RunString("wb = XLSX.read(bstr, {type:'binary', cellNF:true});")
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
On the write side, `"base64"` strings can be decoded in Go:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
b64str, _ := vm.RunString("XLSX.write(wb, {type:'base64', bookType:'xlsx'})")
 | 
			
		||||
buf, _ := base64.StdEncoding.DecodeString(b64str.String())
 | 
			
		||||
_ = ioutil.WriteFile("sheetjs.xlsx", buf, 0644)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
[](https://github.com/SheetJS/js-xlsx)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										71
									
								
								demos/altjs/goja.go
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										71
									
								
								demos/altjs/goja.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	b64 "encoding/base64"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"github.com/dop251/goja"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func safe_run_file(vm *goja.Runtime, file string) {
 | 
			
		||||
	data, err := ioutil.ReadFile(file)
 | 
			
		||||
	if err != nil { panic(err) }
 | 
			
		||||
	src := string(data)
 | 
			
		||||
	_, err = vm.RunString(src)
 | 
			
		||||
	if err != nil { panic(err) }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func eval_string(vm *goja.Runtime, cmd string) goja.Value {
 | 
			
		||||
	v, err := vm.RunString(cmd)
 | 
			
		||||
	if err != nil { panic(err) }
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func write_type(vm *goja.Runtime, t string) {
 | 
			
		||||
	/* due to some wonkiness with array passing, use base64 */
 | 
			
		||||
	b64str := eval_string(vm, "XLSX.write(wb, {type:'base64', bookType:'" + t + "'})")
 | 
			
		||||
	buf, err := b64.StdEncoding.DecodeString(b64str.String());
 | 
			
		||||
	if err != nil { panic(err) }
 | 
			
		||||
	err = ioutil.WriteFile("sheetjsg." + t, buf, 0644)
 | 
			
		||||
	if err != nil { panic(err) }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	vm := goja.New()
 | 
			
		||||
 | 
			
		||||
	/* initialize */
 | 
			
		||||
	eval_string(vm, "if(typeof global == 'undefined') global = (function(){ return this; }).call(null);")
 | 
			
		||||
 | 
			
		||||
	/* load library */
 | 
			
		||||
	safe_run_file(vm, "shim.min.js")
 | 
			
		||||
	safe_run_file(vm, "xlsx.core.min.js")
 | 
			
		||||
 | 
			
		||||
	/* get version string */
 | 
			
		||||
	v := eval_string(vm, "XLSX.version")
 | 
			
		||||
	fmt.Printf("SheetJS library version %s\n", v)
 | 
			
		||||
 | 
			
		||||
	/* read file */
 | 
			
		||||
	data, err := ioutil.ReadFile(os.Args[1])
 | 
			
		||||
	if err != nil { panic(err) }
 | 
			
		||||
	vm.Set("buf", data)
 | 
			
		||||
	fmt.Printf("Loaded file %s\n", os.Args[1])
 | 
			
		||||
 | 
			
		||||
	/* parse workbook */
 | 
			
		||||
	eval_string(vm, "var bstr = ''; for(var i = 0; i < buf.length; ++i) bstr += String.fromCharCode(buf[i]);")
 | 
			
		||||
	eval_string(vm, "wb = XLSX.read(bstr, {type:'binary', cellNF:true});")
 | 
			
		||||
	eval_string(vm, "ws = wb.Sheets[wb.SheetNames[0]]")
 | 
			
		||||
 | 
			
		||||
	/* print CSV */
 | 
			
		||||
	csv := eval_string(vm, "XLSX.utils.sheet_to_csv(ws)")
 | 
			
		||||
	fmt.Printf("%s\n", csv)
 | 
			
		||||
 | 
			
		||||
	/* change cell A1 to 3 */
 | 
			
		||||
	eval_string(vm, "ws['A1'].v = 3; delete ws['A1'].w;")
 | 
			
		||||
 | 
			
		||||
	/* write file */
 | 
			
		||||
	//write_type(vm, "xlsb")
 | 
			
		||||
	//write_type(vm, "xlsx")
 | 
			
		||||
	write_type(vm, "xls")
 | 
			
		||||
	write_type(vm, "csv")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								demos/angular2/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								demos/angular2/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,2 +1,4 @@
 | 
			
		||||
dist
 | 
			
		||||
hooks
 | 
			
		||||
SheetJSIonic
 | 
			
		||||
SheetJSNS
 | 
			
		||||
 | 
			
		||||
@ -18,3 +18,13 @@ ionic:
 | 
			
		||||
ios android browser: ionic
 | 
			
		||||
	cd SheetJSIonic; ionic cordova emulate $@ </dev/null; cd -
 | 
			
		||||
 | 
			
		||||
.PHONY: nativescript
 | 
			
		||||
nativescript:
 | 
			
		||||
	bash ./nscript.sh
 | 
			
		||||
 | 
			
		||||
.PHONY: ns-ios ns-android
 | 
			
		||||
ns-ios: nativescript
 | 
			
		||||
	cd SheetJSNS; tns run ios; cd -
 | 
			
		||||
ns-android: nativescript
 | 
			
		||||
	cd SheetJSNS; tns run android; cd -
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -12,6 +12,7 @@ the data, and a button to export the data.
 | 
			
		||||
 | 
			
		||||
Other scripts in this demo show:
 | 
			
		||||
- `ionic` deployment for iOS, android, and browser
 | 
			
		||||
- `nativescript` deployment for iOS and android
 | 
			
		||||
 | 
			
		||||
## Array of Arrays
 | 
			
		||||
 | 
			
		||||
@ -151,4 +152,28 @@ let blob = new Blob([wbout], {type: 'application/octet-stream'});
 | 
			
		||||
this.file.writeFile(url, filename, blob, {replace: true});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## NativeScript
 | 
			
		||||
 | 
			
		||||
Reproducing the full project is a little bit tricky.  The included `nscript.sh`
 | 
			
		||||
script performs the necessary installation steps and adds the necessary shims
 | 
			
		||||
for `async` support.  Due to incompatibilities with NativeScript and TypeScript
 | 
			
		||||
definitions, apps should require the `xlsx.full.min.js` file directly:
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const XLSX = require("./xlsx.full.min.js");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The `ISO_8859_1` encoding from the text module specifies `"binary"` strings.
 | 
			
		||||
`fs.File#readText` and `fs.File#writeText` reads and writes files:
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
/* read a workbook */
 | 
			
		||||
const bstr: string = await file.readText(textModule.encoding.ISO_8859_1);
 | 
			
		||||
const wb = XLSX.read(bstr, { type: "binary" });
 | 
			
		||||
 | 
			
		||||
/* write a workbook */
 | 
			
		||||
const wbout: string = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });
 | 
			
		||||
await file.writeText(wbout, textModule.encoding.ISO_8859_1);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
[](https://github.com/SheetJS/js-xlsx)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										15
									
								
								demos/angular2/nscript.sh
									
									
									
									
									
										Executable file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										15
									
								
								demos/angular2/nscript.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
if [ ! -e SheetJSNS ]; then
 | 
			
		||||
	tns create SheetJSNS --template nativescript-template-ng-tutorial
 | 
			
		||||
	cd SheetJSNS
 | 
			
		||||
	tns plugin add nativescript-nodeify
 | 
			
		||||
	npm install xlsx
 | 
			
		||||
	cd app
 | 
			
		||||
	npm install xlsx
 | 
			
		||||
	cd ../..
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
cp ../../dist/xlsx.full.min.js SheetJSNS/
 | 
			
		||||
cp ../../dist/xlsx.full.min.js SheetJSNS/app/
 | 
			
		||||
cp nsmain.ts  SheetJSNS/app/main.ts
 | 
			
		||||
cp nscript.ts SheetJSNS/app/app.component.ts
 | 
			
		||||
							
								
								
									
										83
									
								
								demos/angular2/nscript.ts
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										83
									
								
								demos/angular2/nscript.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,83 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* vim: set ts=2: */
 | 
			
		||||
 | 
			
		||||
import { Component } from "@angular/core";
 | 
			
		||||
import * as dockModule from "tns-core-modules/ui/layouts/dock-layout";
 | 
			
		||||
import * as buttonModule from "tns-core-modules/ui/button";
 | 
			
		||||
import * as textModule from "tns-core-modules/text";
 | 
			
		||||
import * as dialogs from "ui/dialogs";
 | 
			
		||||
import * as fs from "tns-core-modules/file-system";
 | 
			
		||||
 | 
			
		||||
/* NativeScript does not support import syntax for npm modules */
 | 
			
		||||
const XLSX = require("./xlsx.full.min.js");
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: "my-app",
 | 
			
		||||
  template: `
 | 
			
		||||
    <GridLayout rows="auto, *, auto">
 | 
			
		||||
      <ActionBar row="0" title="SheetJS NativeScript Demo" class="action-bar"></ActionBar>
 | 
			
		||||
 | 
			
		||||
      <!-- data converted to HTML and rendered in web view -->
 | 
			
		||||
      <WebView row="1" src="{{html}}"></WebView>
 | 
			
		||||
 | 
			
		||||
      <DockLayout row="2" dock="bottom" stretchLastChild="false">
 | 
			
		||||
        <Button text="Import File" (tap)="import()" style="padding: 10px"></Button>
 | 
			
		||||
        <Button text="Export File" (tap)="export()" style="padding: 10px"></Button>
 | 
			
		||||
      </DockLayout>
 | 
			
		||||
    </GridLayout>
 | 
			
		||||
  `
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export class AppComponent {
 | 
			
		||||
  html: string = "";
 | 
			
		||||
  constructor() {
 | 
			
		||||
    const ws = XLSX.utils.aoa_to_sheet([[1,2],[3,4]]);
 | 
			
		||||
    this.html = XLSX.utils.sheet_to_html(ws);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /* Import button */
 | 
			
		||||
  async import() {
 | 
			
		||||
    const filename: string = "SheetJSNS.xlsx";
 | 
			
		||||
 | 
			
		||||
    /* find appropriate path */
 | 
			
		||||
    const target: fs.Folder = fs.knownFolders.documents() || fs.knownFolders.ios.sharedPublic();
 | 
			
		||||
    const url: string = fs.path.normalize(target.path + "///" + filename);
 | 
			
		||||
    const file: fs.File = fs.File.fromPath(url);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      /* get binary string */
 | 
			
		||||
      const bstr: string = await file.readText(textModule.encoding.ISO_8859_1);
 | 
			
		||||
 | 
			
		||||
      /* read workbook */
 | 
			
		||||
      const wb = XLSX.read(bstr, { type: "binary" });
 | 
			
		||||
 | 
			
		||||
      /* grab first sheet */
 | 
			
		||||
      const wsname: string = wb.SheetNames[0];
 | 
			
		||||
      const ws = wb.Sheets[wsname];
 | 
			
		||||
 | 
			
		||||
      /* update table */
 | 
			
		||||
      this.html = XLSX.utils.sheet_to_html(ws);
 | 
			
		||||
      dialogs.alert(`Attempting to read to SheetJSNS.xlsx in ${url}`);
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
      dialogs.alert(e.message);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /* Export button */
 | 
			
		||||
  async export() {
 | 
			
		||||
    const wb = XLSX.read(this.html, { type: "string" });
 | 
			
		||||
    const filename: string = "SheetJSNS.xlsx";
 | 
			
		||||
 | 
			
		||||
    /* generate binary string */
 | 
			
		||||
    const wbout: string = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });
 | 
			
		||||
 | 
			
		||||
    /* find appropriate path */
 | 
			
		||||
    const target: fs.Folder = fs.knownFolders.documents() || fs.knownFolders.ios.sharedPublic();
 | 
			
		||||
    const url: string = fs.path.normalize(target.path + "///" + filename);
 | 
			
		||||
    const file: fs.File = fs.File.fromPath(url);
 | 
			
		||||
 | 
			
		||||
    /* attempt to save binary string to file */
 | 
			
		||||
    await file.writeText(wbout, textModule.encoding.ISO_8859_1);
 | 
			
		||||
    dialogs.alert(`Wrote to SheetJSNS.xlsx in ${url}`);
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										65
									
								
								demos/angular2/nsmain.ts
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										65
									
								
								demos/angular2/nsmain.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
			
		||||
import { platformNativeScriptDynamic } from "nativescript-angular/platform";
 | 
			
		||||
import { AppModule } from "./app.module";
 | 
			
		||||
 | 
			
		||||
/*! ****************************************************************************
 | 
			
		||||
Code based on @Microsoft/tslib
 | 
			
		||||
 | 
			
		||||
Original license header:
 | 
			
		||||
 | 
			
		||||
Copyright (c) Microsoft Corporation. All rights reserved.
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
 | 
			
		||||
this file except in compliance with the License. You may obtain a copy of the
 | 
			
		||||
License at http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
THIS CODE IS PROVIDED ON AN AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 | 
			
		||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
 | 
			
		||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
 | 
			
		||||
MERCHANTABLITY OR NON-INFRINGEMENT.
 | 
			
		||||
 | 
			
		||||
See the Apache Version 2.0 License for specific language governing permissions
 | 
			
		||||
and limitations under the License.
 | 
			
		||||
***************************************************************************** */
 | 
			
		||||
 | 
			
		||||
// tslint:disable
 | 
			
		||||
if (!('__awaiter' in global)) {
 | 
			
		||||
  global['__awaiter'] = function (thisArg, _arguments, P, generator) {
 | 
			
		||||
    return new (P || (P = Promise))(function (resolve, reject) {
 | 
			
		||||
      function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
 | 
			
		||||
      function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
 | 
			
		||||
      function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
 | 
			
		||||
      step((generator = generator.apply(thisArg, _arguments || [])).next());
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (!('__generator' in global)) {
 | 
			
		||||
  global['__generator'] = function (thisArg, body) {
 | 
			
		||||
    var _: any = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
 | 
			
		||||
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
 | 
			
		||||
    function verb(n) { return function (v) { return step([n, v]); }; }
 | 
			
		||||
    function step(op) {
 | 
			
		||||
      if (f) throw new TypeError("Generator is already executing.");
 | 
			
		||||
      while (_) try {
 | 
			
		||||
        if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
 | 
			
		||||
        if (y = 0, t) op = [0, t.value];
 | 
			
		||||
        switch (op[0]) {
 | 
			
		||||
          case 0: case 1: t = op; break;
 | 
			
		||||
          case 4: _.label++; return { value: op[1], done: false };
 | 
			
		||||
          case 5: _.label++; y = op[1]; op = [0]; continue;
 | 
			
		||||
          case 7: op = _.ops.pop(); _.trys.pop(); continue;
 | 
			
		||||
          default:
 | 
			
		||||
            if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
 | 
			
		||||
            if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
 | 
			
		||||
            if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
 | 
			
		||||
            if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
 | 
			
		||||
            if (t[2]) _.ops.pop();
 | 
			
		||||
            _.trys.pop(); continue;
 | 
			
		||||
        }
 | 
			
		||||
        op = body.call(thisArg, _);
 | 
			
		||||
      } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
 | 
			
		||||
      if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
platformNativeScriptDynamic().bootstrapModule(AppModule);
 | 
			
		||||
							
								
								
									
										2
									
								
								demos/chrome/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								demos/chrome/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
xlsx.*.js
 | 
			
		||||
logo.png
 | 
			
		||||
							
								
								
									
										8
									
								
								demos/chrome/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										8
									
								
								demos/chrome/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
.PHONY: init
 | 
			
		||||
init:
 | 
			
		||||
	cp ../../dist/xlsx.full.min.js .
 | 
			
		||||
	if [ ! -e logo.png ]; then curl -O http://sheetjs.com/logo.png; fi
 | 
			
		||||
 | 
			
		||||
.PHONY: lint
 | 
			
		||||
lint:
 | 
			
		||||
	eslint content.js popup.js table.js
 | 
			
		||||
							
								
								
									
										89
									
								
								demos/chrome/README.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										89
									
								
								demos/chrome/README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,89 @@
 | 
			
		||||
# Chrome and Chromium
 | 
			
		||||
 | 
			
		||||
This library is compatible with Chrome and Chromium extensions and should just
 | 
			
		||||
work out of the box.  Specific API support is listed in the Chrome extensions
 | 
			
		||||
API documentation.
 | 
			
		||||
 | 
			
		||||
## Generating Downloads
 | 
			
		||||
 | 
			
		||||
The `writeFile` function works in a Chrome or Chromium extension:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
XLSX.writeFile(wb, "export.xlsx");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Under the hood, it uses the `chrome.downloads` API.  `"downloads"` permission
 | 
			
		||||
should be set in `manifest.json`:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
"permissions": [
 | 
			
		||||
  "downloads"
 | 
			
		||||
]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Content Script Table Scraping
 | 
			
		||||
 | 
			
		||||
`table_to_book` and `table_to_sheet` can help build workbooks from DOM tables:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
var tables = document.getElementsByTagName("table");
 | 
			
		||||
var wb = XLSX.utils.book_new();
 | 
			
		||||
for(var i = 0; i < tables.length; ++i) {
 | 
			
		||||
  var ws = XLSX.utils.table_to_sheet(tables[i]);
 | 
			
		||||
  XLSX.utils.book_append_sheet(wb, ws, "Table" + i);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Demo
 | 
			
		||||
 | 
			
		||||
The demo extension includes multiple features to demonstrate sample usage.
 | 
			
		||||
Production extensions should include proper error handling.
 | 
			
		||||
 | 
			
		||||
#### Table Exporter
 | 
			
		||||
 | 
			
		||||
The `content.js` content script converts a table in the DOM to workbook object
 | 
			
		||||
using the `table_to_book` utility function:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
// event page script trigger
 | 
			
		||||
chrome.tabs.sendMessage(tab.id);
 | 
			
		||||
// content script convert
 | 
			
		||||
var wb = XLSX.utils.table_to_book(elt);
 | 
			
		||||
// event page script callback
 | 
			
		||||
XLSX.writeFile(wb, "export.xlsx");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Since the workbook object is a plain JS object, the object is sent back to an
 | 
			
		||||
event page script which generates the file and attempts a download.
 | 
			
		||||
 | 
			
		||||
#### Bookmark Exporter
 | 
			
		||||
 | 
			
		||||
`chrome.bookmarks` API enables bookmark tree traversal.  The "Export Bookmarks"
 | 
			
		||||
button in the extension pop-up recursively walks the bookmark tree, pushes the
 | 
			
		||||
bookmark URLs into a data array, and exports into a simple spreadsheet:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* walk the bookmark tree */
 | 
			
		||||
function recurse_bookmarks(data, tree) {
 | 
			
		||||
  if(tree.url) data.push({Name: tree.title, Location: tree.url});
 | 
			
		||||
  (tree.children||[]).forEach(function(child) { recurse_bookmarks(data, child); });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* get bookmark data */
 | 
			
		||||
chrome.bookmarks.getTree(function(res) {
 | 
			
		||||
  /* load into an array */
 | 
			
		||||
  var data = [];
 | 
			
		||||
  res.forEach(function(t) { recurse_bookmarks(data, t); });
 | 
			
		||||
 | 
			
		||||
  /* create worksheet */
 | 
			
		||||
  var ws = XLSX.utils.json_to_sheet(data, { header: ['Name', 'Location'] });
 | 
			
		||||
 | 
			
		||||
  /* create workbook and export */
 | 
			
		||||
  var wb = XLSX.utils.book_new();
 | 
			
		||||
  XLSX.utils.book_append_sheet(wb, ws, 'Bookmarks');
 | 
			
		||||
  XLSX.writeFile(wb, "bookmarks.xlsx");
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[](https://github.com/SheetJS/js-xlsx)
 | 
			
		||||
							
								
								
									
										27
									
								
								demos/chrome/content.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										27
									
								
								demos/chrome/content.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* eslint-env browser */
 | 
			
		||||
/* global XLSX, chrome */
 | 
			
		||||
var coords = [0,0];
 | 
			
		||||
document.addEventListener('mousedown', function(mouse) {
 | 
			
		||||
	if(mouse && mouse.button == 2) coords = [mouse.clientX, mouse.clientY];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
chrome.runtime.onMessage.addListener(function(msg, sender, cb) {
 | 
			
		||||
	if(!msg && !msg['Sheet']) return;
 | 
			
		||||
	if(msg.Sheet == "JS") {
 | 
			
		||||
		var elt = document.elementFromPoint(coords[0], coords[1]);
 | 
			
		||||
		while(elt != null) {
 | 
			
		||||
			if(elt.tagName.toLowerCase() == "table") return cb(XLSX.utils.table_to_book(elt));
 | 
			
		||||
			elt = elt.parentElement;
 | 
			
		||||
		}
 | 
			
		||||
	} else if(msg.Sheet == "J5") {
 | 
			
		||||
		var tables = document.getElementsByTagName("table");
 | 
			
		||||
		var wb = XLSX.utils.book_new();
 | 
			
		||||
		for(var i = 0; i < tables.length; ++i) {
 | 
			
		||||
			var ws = XLSX.utils.table_to_sheet(tables[i]);
 | 
			
		||||
			XLSX.utils.book_append_sheet(wb, ws, "Table" + i);
 | 
			
		||||
		}
 | 
			
		||||
		return cb(wb);
 | 
			
		||||
	}
 | 
			
		||||
	cb(coords);
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										30
									
								
								demos/chrome/manifest.json
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										30
									
								
								demos/chrome/manifest.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
{
 | 
			
		||||
  "manifest_version": 2,
 | 
			
		||||
  "name": "SheetJS Demo",
 | 
			
		||||
  "description": "Sample Extension using SheetJS to interact with Chrome",
 | 
			
		||||
  "version": "0.0.1",
 | 
			
		||||
  "browser_action": {
 | 
			
		||||
    "default_popup": "popup.html",
 | 
			
		||||
    "default_icon": "logo.png"
 | 
			
		||||
  },
 | 
			
		||||
  "background": {
 | 
			
		||||
    "scripts": ["xlsx.full.min.js", "table.js"],
 | 
			
		||||
    "persistent": false
 | 
			
		||||
  },
 | 
			
		||||
  "content_scripts": [{
 | 
			
		||||
    "matches": ["<all_urls>"],
 | 
			
		||||
    "js": ["content.js", "xlsx.full.min.js"],
 | 
			
		||||
    "run_at": "document_end"
 | 
			
		||||
  }],
 | 
			
		||||
  "icons": {
 | 
			
		||||
    "16": "logo.png"
 | 
			
		||||
  },
 | 
			
		||||
  "permissions": [
 | 
			
		||||
    "activeTab",
 | 
			
		||||
    "<all_urls>",
 | 
			
		||||
    "bookmarks",
 | 
			
		||||
    "contextMenus",
 | 
			
		||||
    "downloads",
 | 
			
		||||
    "tabs"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								demos/chrome/popup.html
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										18
									
								
								demos/chrome/popup.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<!-- (C) 2013-present  SheetJS http://sheetjs.com -->
 | 
			
		||||
<!-- vim: set ts=2: -->
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
<title>SheetJS Chrome Extension Export Test</title>
 | 
			
		||||
<meta charset="utf-8" />
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<!-- SheetJS js-xlsx library -->
 | 
			
		||||
<script type="text/javascript" src="xlsx.full.min.js"></script>
 | 
			
		||||
 | 
			
		||||
<button type="button" id="sjsdownload">Export Bookmarks</button>
 | 
			
		||||
<a><div id="sjsversion">Version</div></a>
 | 
			
		||||
 | 
			
		||||
<script type="text/javascript" src="popup.js"></script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										31
									
								
								demos/chrome/popup.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										31
									
								
								demos/chrome/popup.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* eslint-env browser */
 | 
			
		||||
/* global XLSX, chrome */
 | 
			
		||||
document.getElementById('sjsversion').innerText = "SheetJS " + XLSX.version;
 | 
			
		||||
 | 
			
		||||
document.getElementById('sjsversion').addEventListener('click', function() {
 | 
			
		||||
  chrome.tabs.create({url: "https://sheetjs.com/"}); return false;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* recursively walk the bookmark tree */
 | 
			
		||||
function recurse_bookmarks(data, tree, path) {
 | 
			
		||||
  if(tree.url) data.push({Name: tree.title, Location: tree.url, Path:path});
 | 
			
		||||
  var T = path ? (path + "::" + tree.title) : tree.title;
 | 
			
		||||
  (tree.children||[]).forEach(function(C) { recurse_bookmarks(data, C, T); });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* export bookmark data */
 | 
			
		||||
document.getElementById('sjsdownload').addEventListener('click', function() {
 | 
			
		||||
  chrome.bookmarks.getTree(function(res) {
 | 
			
		||||
    var data = [];
 | 
			
		||||
    res.forEach(function(t) { recurse_bookmarks(data, t, ""); });
 | 
			
		||||
 | 
			
		||||
    /* create worksheet */
 | 
			
		||||
    var ws = XLSX.utils.json_to_sheet(data, { header: ['Name', 'Location', 'Path'] });
 | 
			
		||||
 | 
			
		||||
    /* create workbook and export */
 | 
			
		||||
    var wb = XLSX.utils.book_new();
 | 
			
		||||
    XLSX.utils.book_append_sheet(wb, ws, 'Bookmarks');
 | 
			
		||||
    XLSX.writeFile(wb, "bookmarks.xlsx");
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										43
									
								
								demos/chrome/table.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										43
									
								
								demos/chrome/table.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* eslint-env browser */
 | 
			
		||||
/* global XLSX, chrome */
 | 
			
		||||
chrome.runtime.onInstalled.addListener(function() {
 | 
			
		||||
	chrome.contextMenus.create({
 | 
			
		||||
		type: "normal",
 | 
			
		||||
		id: "sjsexport",
 | 
			
		||||
		title: "Export Table to XLSX",
 | 
			
		||||
		contexts: ["page", "selection"]
 | 
			
		||||
	});
 | 
			
		||||
	chrome.contextMenus.create({
 | 
			
		||||
		type: "normal",
 | 
			
		||||
		id: "sj5export",
 | 
			
		||||
		title: "Export All Tables in Page",
 | 
			
		||||
		contexts: ["page", "selection"]
 | 
			
		||||
	});
 | 
			
		||||
	chrome.contextMenus.onClicked.addListener(function(info/*, tab*/) {
 | 
			
		||||
		var mode = "";
 | 
			
		||||
		switch(info.menuItemId) {
 | 
			
		||||
			case 'sjsexport': mode = "JS"; break;
 | 
			
		||||
			case 'sj5export': mode = "J5"; break;
 | 
			
		||||
			default: return;
 | 
			
		||||
		}
 | 
			
		||||
		chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
 | 
			
		||||
			chrome.tabs.sendMessage(tabs[0].id, {Sheet:mode}, sjsexport_cb);
 | 
			
		||||
		});
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	chrome.contextMenus.create({
 | 
			
		||||
		id: "sjsabout",
 | 
			
		||||
		title: "About",
 | 
			
		||||
		contexts: ["browser_action"]
 | 
			
		||||
	});
 | 
			
		||||
	chrome.contextMenus.onClicked.addListener(function(info/*, tab*/) {
 | 
			
		||||
		if(info.menuItemId !== "sjsabout") return;
 | 
			
		||||
		chrome.tabs.create({url: "https://sheetjs.com/"});
 | 
			
		||||
	});
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function sjsexport_cb(wb) {
 | 
			
		||||
	if(!wb || !wb.SheetNames || !wb.Sheets) { console.log(wb); return alert("Error in exporting table"); }
 | 
			
		||||
	XLSX.writeFile(wb, "export.xlsx");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										89
									
								
								demos/database/FirebaseDemo.html
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										89
									
								
								demos/database/FirebaseDemo.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,89 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<!-- xlsx.js (C) 2013-present  SheetJS http://sheetjs.com -->
 | 
			
		||||
<!-- vim: set ts=2: -->
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 | 
			
		||||
<title>SheetJS Firebase Dump Demo</title>
 | 
			
		||||
<style>
 | 
			
		||||
a { text-decoration: none }
 | 
			
		||||
</style>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<pre>
 | 
			
		||||
<h3><a href="//sheetjs.com/">SheetJS</a> Firebase Dump Demo</h3>
 | 
			
		||||
<b>Example Code</b>
 | 
			
		||||
 | 
			
		||||
  /* ... connect to firebase */
 | 
			
		||||
  const database = firebase.database();
 | 
			
		||||
 | 
			
		||||
  /* import workbook */
 | 
			
		||||
  await database.ref('foo').set(workbook);
 | 
			
		||||
 | 
			
		||||
  /* change cells */
 | 
			
		||||
  database.ref('foo').update({
 | 
			
		||||
    "Sheets/Sheet1/A1": {"t": "s", "v": "J"},
 | 
			
		||||
    "Sheets/Sheet1/A2": {"t": "n", "v": 5},
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  /* export snapshot */
 | 
			
		||||
  const val = await database.ref('foo').once('value').val();
 | 
			
		||||
  XLSX.writeFile(wb, "firebase.xlsx");
 | 
			
		||||
 | 
			
		||||
</pre>
 | 
			
		||||
<script src="xlsx.full.min.js"></script>
 | 
			
		||||
<script src="https://www.gstatic.com/firebasejs/4.12.0/firebase.js"></script>
 | 
			
		||||
<script>
 | 
			
		||||
const Firebase = firebase;
 | 
			
		||||
const config = {
 | 
			
		||||
  credential: {
 | 
			
		||||
    getAccessToken: () => ({
 | 
			
		||||
      expires_in: 0,
 | 
			
		||||
      access_token: '',
 | 
			
		||||
    }),
 | 
			
		||||
  },
 | 
			
		||||
  databaseURL: 'ws://localhost:5555'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* make new workbook object from CSV */
 | 
			
		||||
const wb = XLSX.read('a,b,c\n1,2,3', {type:"binary"});
 | 
			
		||||
 | 
			
		||||
let P = Promise.resolve("sheetjs");
 | 
			
		||||
 | 
			
		||||
/* Connect to Firebase server and initialize collection */
 | 
			
		||||
P = P.then(async () => {
 | 
			
		||||
  Firebase.initializeApp(config);
 | 
			
		||||
  const database = Firebase.database();
 | 
			
		||||
  await database.ref('foo').set(null);
 | 
			
		||||
  return [database];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Insert entire workbook object into `foo` ref */
 | 
			
		||||
P = P.then(async ([database]) => {
 | 
			
		||||
  await database.ref('foo').set(wb);
 | 
			
		||||
  return [database];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Change cell A1 of Sheet1 to "J" and change A2 to 5 */
 | 
			
		||||
P = P.then(async ([database]) => {
 | 
			
		||||
  database.ref('foo').update({
 | 
			
		||||
    "Sheets/Sheet1/A1": {"t": "s", "v": "J"},
 | 
			
		||||
    "Sheets/Sheet1/A2": {"t": "n", "v": 5},
 | 
			
		||||
  });
 | 
			
		||||
  return [database];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Write to file */
 | 
			
		||||
P = P.then(async ([database]) => {
 | 
			
		||||
  const val = await database.ref('foo').once('value');
 | 
			
		||||
  const wb = await val.val();
 | 
			
		||||
  XLSX.writeFile(wb, "firebase.xlsx");
 | 
			
		||||
  console.log(csv);
 | 
			
		||||
  return [database];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Close connection */
 | 
			
		||||
P = P.then(async ([database]) => { database.app.delete(); });
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
</body>
 | 
			
		||||
							
								
								
									
										58
									
								
								demos/database/FirebaseTest.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										58
									
								
								demos/database/FirebaseTest.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,58 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* eslint-env node */
 | 
			
		||||
const XLSX = require('xlsx');
 | 
			
		||||
const assert = require('assert');
 | 
			
		||||
const Firebase = require('firebase-admin');
 | 
			
		||||
 | 
			
		||||
const config = {
 | 
			
		||||
	credential: {
 | 
			
		||||
		getAccessToken: () => ({
 | 
			
		||||
			expires_in: 0,
 | 
			
		||||
			access_token: '',
 | 
			
		||||
		}),
 | 
			
		||||
	},
 | 
			
		||||
	databaseURL: 'ws://localhost:5555'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* make new workbook object from CSV */
 | 
			
		||||
const wb = XLSX.read('a,b,c\n1,2,3', {type:"binary", raw:true});
 | 
			
		||||
 | 
			
		||||
let P = Promise.resolve("sheetjs");
 | 
			
		||||
 | 
			
		||||
/* Connect to Firebase server and initialize collection */
 | 
			
		||||
P = P.then(async () => {
 | 
			
		||||
	Firebase.initializeApp(config);
 | 
			
		||||
	const database = Firebase.database();
 | 
			
		||||
	await database.ref('foo').set(null);
 | 
			
		||||
	return [database];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Insert entire workbook object into `foo` ref */
 | 
			
		||||
P = P.then(async ([database]) => {
 | 
			
		||||
	await database.ref('foo').set(wb);
 | 
			
		||||
	return [database];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Change cell A1 of Sheet1 to "J" and change A2 to 5 */
 | 
			
		||||
P = P.then(async ([database]) => {
 | 
			
		||||
	database.ref('foo').update({
 | 
			
		||||
		"Sheets/Sheet1/A1": {"t": "s", "v": "J"},
 | 
			
		||||
		"Sheets/Sheet1/A2": {"t": "n", "v": 5},
 | 
			
		||||
	});
 | 
			
		||||
	return [database];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Write to file */
 | 
			
		||||
P = P.then(async ([database]) => {
 | 
			
		||||
	const val = await database.ref('foo').once('value');
 | 
			
		||||
	const wb = await val.val();
 | 
			
		||||
	XLSX.writeFile(wb, "firebase.xlsx");
 | 
			
		||||
	const ws = XLSX.readFile("firebase.xlsx").Sheets.Sheet1;
 | 
			
		||||
	const csv = XLSX.utils.sheet_to_csv(ws);
 | 
			
		||||
	assert.equal(csv, "J,b,c\n5,2,3\n");
 | 
			
		||||
	console.log(csv);
 | 
			
		||||
	return [database];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Close connection */
 | 
			
		||||
P = P.then(async ([database]) => { database.app.delete(); });
 | 
			
		||||
@ -13,4 +13,4 @@ lint: $(FILES)
 | 
			
		||||
 | 
			
		||||
.PHONY: clean
 | 
			
		||||
clean:
 | 
			
		||||
	rm -f *.db *.xlsx
 | 
			
		||||
	rm -f *.db *.xlsx *.csv
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										62
									
								
								demos/database/MongoDBCRUD.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										62
									
								
								demos/database/MongoDBCRUD.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* eslint-env node */
 | 
			
		||||
/* global Promise */
 | 
			
		||||
const XLSX = require('xlsx');
 | 
			
		||||
const SheetJSMongo = require("./SheetJSMongo");
 | 
			
		||||
const MongoClient = require('mongodb').MongoClient;
 | 
			
		||||
 | 
			
		||||
const url = 'mongodb://localhost:27017/sheetjs';
 | 
			
		||||
const db_name = 'sheetjs';
 | 
			
		||||
 | 
			
		||||
let P = Promise.resolve("sheetjs");
 | 
			
		||||
 | 
			
		||||
/* Connect to mongodb server */
 | 
			
		||||
P = P.then(async () => {
 | 
			
		||||
	const client = await MongoClient.connect(url);
 | 
			
		||||
	return [client];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Sample data table */
 | 
			
		||||
P = P.then(async ([client]) => {
 | 
			
		||||
	const db = client.db(db_name);
 | 
			
		||||
 | 
			
		||||
	try { await db.collection('pres').drop(); } catch(e) {}
 | 
			
		||||
	const pres = db.collection('pres');
 | 
			
		||||
	await pres.insertMany([
 | 
			
		||||
		{ name: "Barack Obama", idx: 44 },
 | 
			
		||||
		{ name: "Donald Trump", idx: 45 }
 | 
			
		||||
	], {ordered: true});
 | 
			
		||||
 | 
			
		||||
	try { await db.collection('fmts').drop(); } catch(e) {}
 | 
			
		||||
	const fmts = db.collection('fmts');
 | 
			
		||||
	await fmts.insertMany([
 | 
			
		||||
		{ ext: 'XLSB', ctr: 'ZIP', multi: 1 },
 | 
			
		||||
		{ ext: 'XLS',  ctr: 'CFB', multi: 1 },
 | 
			
		||||
		{ ext: 'XLML',             multi: 1 },
 | 
			
		||||
		{ ext: 'CSV',  ctr: 'ZIP', multi: 0 },
 | 
			
		||||
	], {ordered: true});
 | 
			
		||||
 | 
			
		||||
	return [client, pres, fmts];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Export database to XLSX */
 | 
			
		||||
P = P.then(async ([client, pres, fmts]) => {
 | 
			
		||||
	const wb = XLSX.utils.book_new();
 | 
			
		||||
	await SheetJSMongo.book_append_mongo(wb, pres, "pres");
 | 
			
		||||
	await SheetJSMongo.book_append_mongo(wb, fmts, "fmts");
 | 
			
		||||
	XLSX.writeFile(wb, "mongocrud.xlsx");
 | 
			
		||||
	return [client, pres, fmts];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Read the new file and dump all of the data */
 | 
			
		||||
P = P.then(() => {
 | 
			
		||||
	const wb = XLSX.readFile('mongocrud.xlsx');
 | 
			
		||||
	wb.SheetNames.forEach((n,i) => {
 | 
			
		||||
		console.log(`Sheet #${i+1}: ${n}`);
 | 
			
		||||
		const ws = wb.Sheets[n];
 | 
			
		||||
		console.log(XLSX.utils.sheet_to_csv(ws));
 | 
			
		||||
	});
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Close connection */
 | 
			
		||||
P.then(async ([client]) => { client.close(); });
 | 
			
		||||
							
								
								
									
										54
									
								
								demos/database/MongoDBTest.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										54
									
								
								demos/database/MongoDBTest.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* eslint-env node */
 | 
			
		||||
/* global Promise */
 | 
			
		||||
const XLSX = require('xlsx');
 | 
			
		||||
const assert = require('assert');
 | 
			
		||||
const MongoClient = require('mongodb').MongoClient;
 | 
			
		||||
 | 
			
		||||
const url = 'mongodb://localhost:27017/sheetjs';
 | 
			
		||||
const db_name = 'sheetjs';
 | 
			
		||||
 | 
			
		||||
/* make new workbook object from CSV */
 | 
			
		||||
const wb = XLSX.read('a,b,c\n1,2,3', {type:"binary", raw:true});
 | 
			
		||||
 | 
			
		||||
let P = Promise.resolve("sheetjs");
 | 
			
		||||
 | 
			
		||||
/* Connect to mongodb server and initialize collection */
 | 
			
		||||
P = P.then(async () => {
 | 
			
		||||
	const client = await MongoClient.connect(url);
 | 
			
		||||
	const db = client.db(db_name);
 | 
			
		||||
	try { await db.collection('wb').drop(); } catch(e) {}
 | 
			
		||||
	const coll = db.collection('wb');
 | 
			
		||||
	return [client, coll];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Insert entire workbook object as a document */
 | 
			
		||||
P = P.then(async ([client, coll]) => {
 | 
			
		||||
	const res = await coll.insertOne(wb);
 | 
			
		||||
	assert.equal(res.insertedCount, 1);
 | 
			
		||||
	return [client, coll];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Change cell A1 of Sheet1 to "J" and change A2 to 5 */
 | 
			
		||||
P = P.then(async ([client, coll]) => {
 | 
			
		||||
	const res = await coll.updateOne({}, { $set: {
 | 
			
		||||
		"Sheets.Sheet1.A1": {"t": "s", "v": "J"},
 | 
			
		||||
		"Sheets.Sheet1.A2": {"t": "n", "v": 5},
 | 
			
		||||
	}});
 | 
			
		||||
	assert.equal(res.matchedCount, 1);
 | 
			
		||||
	assert.equal(res.modifiedCount, 1);
 | 
			
		||||
	return [client, coll];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Write to file */
 | 
			
		||||
P = P.then(async ([client, coll]) => {
 | 
			
		||||
	const res = await coll.find({}).toArray();
 | 
			
		||||
	const wb = res[0];
 | 
			
		||||
	XLSX.writeFile(wb, "mongo.xlsx");
 | 
			
		||||
	const ws = XLSX.readFile("mongo.xlsx").Sheets.Sheet1;
 | 
			
		||||
	console.log(XLSX.utils.sheet_to_csv(ws));
 | 
			
		||||
	return [client, coll];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Close connection */
 | 
			
		||||
P.then(async ([client]) => { client.close(); });
 | 
			
		||||
@ -296,5 +296,45 @@ LowDB is a small schemaless database powered by `lodash`.  `_.get` and `_.set`
 | 
			
		||||
helper functions make storing metadata a breeze.  The included `SheetJSLowDB.js`
 | 
			
		||||
script demonstrates a simple adapter that can load and dump data.
 | 
			
		||||
 | 
			
		||||
### Document Databases
 | 
			
		||||
 | 
			
		||||
Since document databases are capable of holding more complex objects, they can
 | 
			
		||||
actually hold the underlying worksheet objects!  In some cases, where arrays are
 | 
			
		||||
supported, they can even hold the workbook object.
 | 
			
		||||
 | 
			
		||||
#### MongoDB
 | 
			
		||||
 | 
			
		||||
MongoDB is a popular document-oriented database engine.  `MongoDBTest.js` uses
 | 
			
		||||
MongoDB to hold a simple workbook and export to XLSX.
 | 
			
		||||
 | 
			
		||||
`MongoDBCRUD.js` follows the SQL examples using an idiomatic collection
 | 
			
		||||
structure.  Exporting and importing collections are straightforward:
 | 
			
		||||
 | 
			
		||||
<details>
 | 
			
		||||
	<summary><b>Example code</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* generate a worksheet from a collection */
 | 
			
		||||
const aoa = await db.collection('coll').find({}).toArray();
 | 
			
		||||
aoa.forEach((x) => delete x._id);
 | 
			
		||||
const ws = XLSX.utils.json_to_sheet(aoa);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* import data from a worksheet to a collection */
 | 
			
		||||
const aoa = XLSX.utils.sheet_to_json(ws);
 | 
			
		||||
await db.collection('coll').insertMany(aoa, {ordered: true});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Firebase
 | 
			
		||||
 | 
			
		||||
[`firebase-server`](https://www.npmjs.com/package/firebase-server) is a simple
 | 
			
		||||
mock Firebase server used in the tests, but the same code works in an external
 | 
			
		||||
Firebase deployment when plugging in the database connection info.
 | 
			
		||||
 | 
			
		||||
`FirebaseDemo.html` and `FirebaseTest.js` demonstrate a whole-workbook process.
 | 
			
		||||
The entire workbook object is persisted, a few cells are changed, and the stored
 | 
			
		||||
data is dumped and exported to XLSX.
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
[](https://github.com/SheetJS/js-xlsx)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										15
									
								
								demos/database/SheetJSMongo.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										15
									
								
								demos/database/SheetJSMongo.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* eslint-env node */
 | 
			
		||||
var XLSX = require("xlsx");
 | 
			
		||||
	
 | 
			
		||||
async function book_append_mongo(wb, coll, name) {
 | 
			
		||||
	const aoo = await coll.find({}).toArray();
 | 
			
		||||
	aoo.forEach((x) => delete x._id);
 | 
			
		||||
	const ws = XLSX.utils.json_to_sheet(aoo);
 | 
			
		||||
	XLSX.utils.book_append_sheet(wb, ws, name);
 | 
			
		||||
	return ws;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
	book_append_mongo
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										10
									
								
								demos/electron/.eslintrc
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										10
									
								
								demos/electron/.eslintrc
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
{
 | 
			
		||||
	"env": {
 | 
			
		||||
		"browser": true,
 | 
			
		||||
		"node": true
 | 
			
		||||
	},
 | 
			
		||||
	"parserOptions": {
 | 
			
		||||
		"ecmaVersion": 8
 | 
			
		||||
	},
 | 
			
		||||
	"plugins": [ "html", "json" ]
 | 
			
		||||
}
 | 
			
		||||
@ -3,6 +3,9 @@ init:
 | 
			
		||||
	mkdir -p node_modules
 | 
			
		||||
	cd node_modules; if [ ! -e xlsx ]; then ln -s ../../../ xlsx ; fi; cd -
 | 
			
		||||
 | 
			
		||||
.PHONY: lint
 | 
			
		||||
lint:
 | 
			
		||||
	eslint *.js
 | 
			
		||||
.PHONY: run
 | 
			
		||||
run:
 | 
			
		||||
	electron .
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,7 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/*global Uint8Array, console */
 | 
			
		||||
/* exported export_xlsx */
 | 
			
		||||
/* eslint no-use-before-define:0 */
 | 
			
		||||
var XLSX = require('xlsx');
 | 
			
		||||
var electron = require('electron').remote;
 | 
			
		||||
 | 
			
		||||
@ -60,7 +64,7 @@ var do_file = (function() {
 | 
			
		||||
 | 
			
		||||
(function() {
 | 
			
		||||
	var readf = document.getElementById('readf');
 | 
			
		||||
	function handleF(e) {
 | 
			
		||||
	function handleF(/*e*/) {
 | 
			
		||||
		var o = electron.dialog.showOpenDialog({
 | 
			
		||||
			title: 'Select a file',
 | 
			
		||||
			filters: [{
 | 
			
		||||
@ -97,3 +101,4 @@ var export_xlsx = (function() {
 | 
			
		||||
		electron.dialog.showMessageBox({ message: "Exported data to " + o, buttons: ["OK"] });
 | 
			
		||||
	};
 | 
			
		||||
})();
 | 
			
		||||
void export_xlsx;
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,4 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* from the electron quick-start */
 | 
			
		||||
var electron = require('electron');
 | 
			
		||||
var XLSX = require('xlsx');
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								demos/function/.eslintrc
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										7
									
								
								demos/function/.eslintrc
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
	"env": { "shared-node-browser":true },
 | 
			
		||||
	"parserOptions": {
 | 
			
		||||
		"ecmaVersion": 8
 | 
			
		||||
	},
 | 
			
		||||
	"plugins": [ "html", "json" ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								demos/function/AzureHTTPTrigger/function.json
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										17
									
								
								demos/function/AzureHTTPTrigger/function.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
			
		||||
{
 | 
			
		||||
  "disabled": false,
 | 
			
		||||
  "bindings": [
 | 
			
		||||
    {
 | 
			
		||||
      "authLevel": "function",
 | 
			
		||||
      "type": "httpTrigger",
 | 
			
		||||
      "direction": "in",
 | 
			
		||||
      "dataType": "binary",
 | 
			
		||||
      "name": "req"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "type": "http",
 | 
			
		||||
      "direction": "out",
 | 
			
		||||
      "name": "res"
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										45
									
								
								demos/function/AzureHTTPTrigger/index.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										45
									
								
								demos/function/AzureHTTPTrigger/index.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* eslint-env node */
 | 
			
		||||
// base64 sheetjs.xlsb | curl -F "data=@-;filename=test.xlsb" http://localhost:7262/api/AzureHTTPTrigger
 | 
			
		||||
 | 
			
		||||
const XLSX = require('xlsx');
 | 
			
		||||
const formidable = require('formidable');
 | 
			
		||||
const Readable = require('stream').Readable;
 | 
			
		||||
var fs = require('fs');
 | 
			
		||||
 | 
			
		||||
/* formidable expects the request object to be a stream */
 | 
			
		||||
const streamify = (req) => {
 | 
			
		||||
	if(typeof req.on !== 'undefined') return req;
 | 
			
		||||
	const s = new Readable();
 | 
			
		||||
	s._read = ()=>{};
 | 
			
		||||
	s.push(new Buffer(req.body));
 | 
			
		||||
	s.push(null);
 | 
			
		||||
	Object.assign(s, req);
 | 
			
		||||
	return s;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = (context, req) => {
 | 
			
		||||
	const form = new formidable.IncomingForm();
 | 
			
		||||
	form.parse(streamify(req), (err, fields, files) => {
 | 
			
		||||
		/* grab the first file */
 | 
			
		||||
		var f = Object.values(files)[0];
 | 
			
		||||
		if(!f) {
 | 
			
		||||
			context.res = { status: 400, body: "Must submit a file for processing!" };
 | 
			
		||||
		} else {
 | 
			
		||||
			/* since the file is Base64-encoded, read the file and parse as "base64" */
 | 
			
		||||
			const b64 = fs.readFileSync(f.path).toString();
 | 
			
		||||
			const wb = XLSX.read(b64, {type:"base64"});
 | 
			
		||||
 | 
			
		||||
			/* convert to specified output type -- default CSV */
 | 
			
		||||
			const ext = (fields.bookType || "csv").toLowerCase();
 | 
			
		||||
			const out = XLSX.write(wb, {type:"string", bookType:ext});
 | 
			
		||||
 | 
			
		||||
			context.res = {
 | 
			
		||||
				status: 200,
 | 
			
		||||
				headers: { "Content-Disposition": `attachment; filename="download.${ext}";` },
 | 
			
		||||
				body: out
 | 
			
		||||
			};
 | 
			
		||||
		}
 | 
			
		||||
		context.done();
 | 
			
		||||
	});
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										40
									
								
								demos/function/LambdaProxy/index.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										40
									
								
								demos/function/LambdaProxy/index.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* eslint-env node */
 | 
			
		||||
// base64 sheetjs.xlsb | curl -F "data=@-;filename=test.xlsb" http://localhost:3000/LambdaProxy
 | 
			
		||||
 | 
			
		||||
'use strict';
 | 
			
		||||
var XLSX = require('xlsx');
 | 
			
		||||
var Busboy = require('busboy');
 | 
			
		||||
 | 
			
		||||
exports.handler = function(event, context, callback) {
 | 
			
		||||
	/* set up busboy */
 | 
			
		||||
	var ctype = event.headers['Content-Type']||event.headers['content-type'];
 | 
			
		||||
	var bb = new Busboy({headers:{'content-type':ctype}});
 | 
			
		||||
 | 
			
		||||
	/* busboy is evented; accumulate the fields and files manually */
 | 
			
		||||
	var fields = {}, files = {};
 | 
			
		||||
	bb.on('error', function(err) { console.log('err', err); callback(err); });
 | 
			
		||||
	bb.on('field', function(fieldname, val) {fields[fieldname] = val });
 | 
			
		||||
	bb.on('file', function(fieldname, file, filename) {
 | 
			
		||||
		/* concatenate the individual data buffers */
 | 
			
		||||
		var buffers = [];
 | 
			
		||||
		file.on('data', function(data) { buffers.push(data); });
 | 
			
		||||
		file.on('end', function() { files[fieldname] = [Buffer.concat(buffers), filename]; });
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	/* on the finish event, all of the fields and files are ready */
 | 
			
		||||
	bb.on('finish', function() {
 | 
			
		||||
		/* grab the first file */
 | 
			
		||||
		var f = files[Object.keys(files)[0]];
 | 
			
		||||
		if(!f) callback(new Error("Must submit a file for processing!"));
 | 
			
		||||
 | 
			
		||||
		/* f[0] is a buffer, convert to string and interpret as Base64 */
 | 
			
		||||
		var wb = XLSX.read(f[0].toString(), {type:"base64"});
 | 
			
		||||
 | 
			
		||||
		/* grab first worksheet and convert to CSV */
 | 
			
		||||
		var ws = wb.Sheets[wb.SheetNames[0]];
 | 
			
		||||
		callback(null, { body: XLSX.utils.sheet_to_csv(ws) });
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	bb.end(event.body);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										18
									
								
								demos/function/LambdaProxy/template.yaml
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										18
									
								
								demos/function/LambdaProxy/template.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
AWSTemplateFormatVersion : '2010-09-09'
 | 
			
		||||
Transform: AWS::Serverless-2016-10-31
 | 
			
		||||
 | 
			
		||||
Description: Sample Lambda API Gateway Normalizer
 | 
			
		||||
Resources:
 | 
			
		||||
  LambdaProxy:
 | 
			
		||||
    Type: AWS::Serverless::Function
 | 
			
		||||
    Properties:
 | 
			
		||||
      Runtime: nodejs6.10
 | 
			
		||||
      Handler: index.handler
 | 
			
		||||
      BinaryMediaTypes: '*/*'
 | 
			
		||||
      Events:
 | 
			
		||||
        Api:
 | 
			
		||||
          Type: Api
 | 
			
		||||
          Properties:
 | 
			
		||||
            Path: /LambdaProxy
 | 
			
		||||
            Method: any
 | 
			
		||||
            BinaryMediaTypes: '*/*'
 | 
			
		||||
							
								
								
									
										28
									
								
								demos/function/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										28
									
								
								demos/function/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
.PHONY: microcule
 | 
			
		||||
microcule: mcstream.js
 | 
			
		||||
	microcule $<
 | 
			
		||||
 | 
			
		||||
.PHONY: aws
 | 
			
		||||
aws: lambda-proxy
 | 
			
		||||
 | 
			
		||||
.PHONY: lambda-proxy
 | 
			
		||||
lambda-proxy:
 | 
			
		||||
	cd LambdaProxy; mkdir -p node_modules; npm install xlsx busboy; sam local start-api; cd -
 | 
			
		||||
 | 
			
		||||
.PHONY: azure
 | 
			
		||||
azure:
 | 
			
		||||
	func start
 | 
			
		||||
 | 
			
		||||
.PHONY: azure-server
 | 
			
		||||
azure-server:
 | 
			
		||||
	mkdir -p /tmp/azurite
 | 
			
		||||
	azurite -l /tmp/azurite
 | 
			
		||||
 | 
			
		||||
FILES=$(filter-out xlsx.full.min.js,$(wildcard *.js)) $(wildcard *.html)
 | 
			
		||||
.PHONY: lint
 | 
			
		||||
lint: $(FILES)
 | 
			
		||||
	eslint $(FILES)
 | 
			
		||||
 | 
			
		||||
.PHONY: clean
 | 
			
		||||
clean:
 | 
			
		||||
	rm -f *.db *.xlsx *.csv
 | 
			
		||||
							
								
								
									
										123
									
								
								demos/function/README.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										123
									
								
								demos/function/README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,123 @@
 | 
			
		||||
# "Serverless" Functions
 | 
			
		||||
 | 
			
		||||
Because the library is pure JS, the hard work of reading and writing files can
 | 
			
		||||
be performed in the client browser or on the server side.  On the server side,
 | 
			
		||||
the mechanical process is essentially independent from the data parsing or
 | 
			
		||||
generation.  As a result, it is sometimes sensible to organize applications so
 | 
			
		||||
that the "last mile" conversion between JSON data and spreadsheet files is
 | 
			
		||||
independent from the main application.
 | 
			
		||||
 | 
			
		||||
The most obvious architecture would split off the JSON data conversion as a
 | 
			
		||||
separate microservice or application.  Since it is only needed when an import or
 | 
			
		||||
export is requested, and since the process itself is relatively independent from
 | 
			
		||||
the rest of a typical service, a "Serverless" architecture makes a great fit.
 | 
			
		||||
Since the "function" is separate from the rest of the application, it is easy to
 | 
			
		||||
integrate into a platform built in Java or Go or Python or another language!
 | 
			
		||||
 | 
			
		||||
This demo discusses general architectures and provides examples for popular
 | 
			
		||||
commercial systems and self-hosted alternatives.  The examples are merely
 | 
			
		||||
intended to demonstrate very basic functionality.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Simple Strategies
 | 
			
		||||
 | 
			
		||||
#### Data Normalization
 | 
			
		||||
 | 
			
		||||
Most programming languages and platforms can process CSV or JSON but can't use
 | 
			
		||||
XLS or XLSX or XLSB directly.  Form data from an HTTP POST request can be parsed
 | 
			
		||||
and contained files can be converted to CSV or JSON.  The `XLSX.stream.to_csv`
 | 
			
		||||
utility can stream rows to a standard HTTP response.  `XLSX.utils.sheet_to_json`
 | 
			
		||||
can generate an array of objects that can be fed to another service.
 | 
			
		||||
 | 
			
		||||
At the simplest level, a file on the filesystem can be converted using the bin
 | 
			
		||||
script that ships with the `npm` module:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
$ xlsx /path/to/uploads/file > /tmp/new_csv_file
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
From a utility script, workbooks can be converted in two lines:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
var workbook = XLSX.readFile("path/to/file.xlsb");
 | 
			
		||||
XLSX.writeFile(workbook, "output/path/file.csv");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The `mcstream.js` demo uses the `microcule` framework to show a simple body
 | 
			
		||||
converter.  It accepts raw data from a POST connection, parses as a workbook,
 | 
			
		||||
and streams back the first worksheet as CSV:
 | 
			
		||||
 | 
			
		||||
<details>
 | 
			
		||||
	<summary><b>Code Sketch</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const XLSX = require('xlsx');
 | 
			
		||||
 | 
			
		||||
module.exports = (hook) => {
 | 
			
		||||
	/* process_RS from the main README under "Streaming Read" section */
 | 
			
		||||
	process_RS(hook.req, (wb) => {
 | 
			
		||||
		hook.res.writeHead(200, { 'Content-Type': 'text/csv' });
 | 
			
		||||
		/* get first worksheet */
 | 
			
		||||
		const ws = wb.Sheets[wb.SheetNames[0]];
 | 
			
		||||
		/* generate CSV stream and pipe to response */
 | 
			
		||||
		const stream = XLSX.stream.to_csv(ws);
 | 
			
		||||
		stream.pipe(hook.res);
 | 
			
		||||
	});
 | 
			
		||||
};
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#### Report Generation
 | 
			
		||||
 | 
			
		||||
For an existing platform that already generates JSON or CSV or HTML output, it
 | 
			
		||||
is very easy to embellish output in an Excel-friendly XLSX file.  The
 | 
			
		||||
`XLSX.utils.sheet_add_json` and `XLSX.utils.sheet_add_aoa` functions can add
 | 
			
		||||
data rows to an existing worksheet:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
var ws = XLSX.utils.aoa_to_sheet([
 | 
			
		||||
	["Company Report"],
 | 
			
		||||
	[],
 | 
			
		||||
	["Item", "Cost"]
 | 
			
		||||
]);
 | 
			
		||||
XLSX.utils.sheet_add_json(ws, [
 | 
			
		||||
	{ item: "Coffee", cost: 5 },
 | 
			
		||||
	{ item: "Cake", cost: 20 }
 | 
			
		||||
], { skipHeader: true, origin: -1, header: ["item", "cost"] });
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Deployment Targets
 | 
			
		||||
 | 
			
		||||
The library is supported in Node versions starting from `0.8` as well as a
 | 
			
		||||
myriad of ES3 and ES5 compatible JS engines.  All major services use Node
 | 
			
		||||
versions beyond major release 4, so there should be no problem directly using
 | 
			
		||||
the library in those environments.
 | 
			
		||||
 | 
			
		||||
Note that most cloud providers proactively convert form data to UTF8 strings.
 | 
			
		||||
This is especially problematic when dealing with XLSX and XLSB files, as they
 | 
			
		||||
naturally contain codes that are not valid UTF8 characters.  As a result, these
 | 
			
		||||
demos specifically handle Base64-encoded files only.  To test on the command
 | 
			
		||||
line, use the `base64` tool to encode data before piping to `curl`:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
base64 test.xlsb | curl -F "data=@-;filename=test.xlsb" http://localhost/
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### AWS Lambda
 | 
			
		||||
 | 
			
		||||
Through the AWS Gateway API, Lambda functions can be triggered on HTTP requests.
 | 
			
		||||
The `LambdaProxy` example reads files from form data and converts to CSV.
 | 
			
		||||
 | 
			
		||||
When deploying on AWS, be sure to `npm install` locally and include the modules
 | 
			
		||||
in the ZIP file.
 | 
			
		||||
 | 
			
		||||
#### Azure Functions
 | 
			
		||||
 | 
			
		||||
Azure supports many types of triggers.  The `AzureHTTPTrigger` shows an example
 | 
			
		||||
HTTP trigger that converts the submitted file to CSV.
 | 
			
		||||
 | 
			
		||||
When deploying on Azure, be sure to install the module from the remote console,
 | 
			
		||||
as described in the "Azure Functions JavaScript developer guide".
 | 
			
		||||
							
								
								
									
										1
									
								
								demos/function/host.json
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										1
									
								
								demos/function/host.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
{ }
 | 
			
		||||
							
								
								
									
										11
									
								
								demos/function/local.settings.json
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										11
									
								
								demos/function/local.settings.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "IsEncrypted": false,
 | 
			
		||||
  "Values": {
 | 
			
		||||
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
 | 
			
		||||
    "AzureWebJobsDashboard": "UseDevelopmentStorage=true"
 | 
			
		||||
  },
 | 
			
		||||
  "Host": {
 | 
			
		||||
    "LocalHttpPort": 7262,
 | 
			
		||||
    "CORS": "*"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								demos/function/mcstream.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										22
									
								
								demos/function/mcstream.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* eslint-env node */
 | 
			
		||||
// cat file.xlsx | curl --header 'content-type: application/octet-stream' --data-binary @- "http://localhost:3000/"
 | 
			
		||||
const XLSX = require('xlsx');
 | 
			
		||||
 | 
			
		||||
const process_RS = (stream, cb) => {
 | 
			
		||||
  var buffers = [];
 | 
			
		||||
  stream.on('data', function(data) { buffers.push(data); });
 | 
			
		||||
  stream.on('end', function() {
 | 
			
		||||
    var buffer = Buffer.concat(buffers);
 | 
			
		||||
    var workbook = XLSX.read(buffer, {type:"buffer"});
 | 
			
		||||
    cb(workbook);
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = (hook) => {
 | 
			
		||||
	process_RS(hook.req, (wb) => {
 | 
			
		||||
		hook.res.writeHead(200, { 'Content-Type': 'text/csv' });
 | 
			
		||||
		const stream = XLSX.stream.to_csv(wb.Sheets[wb.SheetNames[0]]);
 | 
			
		||||
		stream.pipe(hook.res);
 | 
			
		||||
	});
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										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
											
										
									
								
							
							
								
								
									
										10
									
								
								dist/xlsx.extendscript.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										10
									
								
								dist/xlsx.extendscript.js
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -9141,7 +9141,7 @@ module.exports = ZStream;
 | 
			
		||||
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
 | 
			
		||||
var XLSX = {};
 | 
			
		||||
(function make_xlsx(XLSX){
 | 
			
		||||
XLSX.version = '0.12.6';
 | 
			
		||||
XLSX.version = '0.12.7';
 | 
			
		||||
var current_codepage = 1200, current_ansi = 1252;
 | 
			
		||||
/*global cptable:true */
 | 
			
		||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
 | 
			
		||||
@ -10980,7 +10980,7 @@ function blobify(data) {
 | 
			
		||||
}
 | 
			
		||||
/* write or download file */
 | 
			
		||||
function write_dl(fname, payload, enc) {
 | 
			
		||||
	/*global IE_SaveFile, Blob, navigator, saveAs, URL, document, File */
 | 
			
		||||
	/*global IE_SaveFile, Blob, navigator, saveAs, URL, document, File, chrome */
 | 
			
		||||
	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);
 | 
			
		||||
@ -10989,9 +10989,13 @@ if(typeof IE_SaveFile !== 'undefined') return IE_SaveFile(data, fname);
 | 
			
		||||
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 url = URL.createObjectURL(blob);
 | 
			
		||||
if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
 | 
			
		||||
				if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
 | 
			
		||||
				return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
 | 
			
		||||
			}
 | 
			
		||||
			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);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										32
									
								
								dist/xlsx.full.min.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										32
									
								
								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
											
										
									
								
							
							
								
								
									
										10
									
								
								dist/xlsx.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										10
									
								
								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.12.6';
 | 
			
		||||
XLSX.version = '0.12.7';
 | 
			
		||||
var current_codepage = 1200, current_ansi = 1252;
 | 
			
		||||
/*global cptable:true */
 | 
			
		||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
 | 
			
		||||
@ -1843,7 +1843,7 @@ function blobify(data) {
 | 
			
		||||
}
 | 
			
		||||
/* write or download file */
 | 
			
		||||
function write_dl(fname, payload, enc) {
 | 
			
		||||
	/*global IE_SaveFile, Blob, navigator, saveAs, URL, document, File */
 | 
			
		||||
	/*global IE_SaveFile, Blob, navigator, saveAs, URL, document, File, chrome */
 | 
			
		||||
	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);
 | 
			
		||||
@ -1852,9 +1852,13 @@ if(typeof IE_SaveFile !== 'undefined') return IE_SaveFile(data, fname);
 | 
			
		||||
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 url = URL.createObjectURL(blob);
 | 
			
		||||
if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
 | 
			
		||||
				if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
 | 
			
		||||
				return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
 | 
			
		||||
			}
 | 
			
		||||
			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);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										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
											
										
									
								
							@ -25,9 +25,11 @@ The [`demos` directory](demos/) includes sample projects for:
 | 
			
		||||
**Platforms and Integrations**
 | 
			
		||||
- [`electron application`](demos/electron/)
 | 
			
		||||
- [`nw.js application`](demos/nwjs/)
 | 
			
		||||
- [`Chrome / Chromium extensions`](demos/chrome/)
 | 
			
		||||
- [`Adobe ExtendScript`](demos/extendscript/)
 | 
			
		||||
- [`Headless Browsers`](demos/headless/)
 | 
			
		||||
- [`canvas-datagrid`](demos/datagrid/)
 | 
			
		||||
- [`Swift JSC and other engines`](demos/altjs/)
 | 
			
		||||
- [`"serverless" functions`](demos/function/)
 | 
			
		||||
- [`internet explorer`](demos/oldie/)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -203,10 +203,12 @@ The [`demos` directory](demos/) includes sample projects for:
 | 
			
		||||
**Platforms and Integrations**
 | 
			
		||||
- [`electron application`](demos/electron/)
 | 
			
		||||
- [`nw.js application`](demos/nwjs/)
 | 
			
		||||
- [`Chrome / Chromium extensions`](demos/chrome/)
 | 
			
		||||
- [`Adobe ExtendScript`](demos/extendscript/)
 | 
			
		||||
- [`Headless Browsers`](demos/headless/)
 | 
			
		||||
- [`canvas-datagrid`](demos/datagrid/)
 | 
			
		||||
- [`Swift JSC and other engines`](demos/altjs/)
 | 
			
		||||
- [`"serverless" functions`](demos/function/)
 | 
			
		||||
- [`internet explorer`](demos/oldie/)
 | 
			
		||||
 | 
			
		||||
### Optional Modules
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
	"name": "xlsx",
 | 
			
		||||
	"version": "0.12.6",
 | 
			
		||||
	"version": "0.12.7",
 | 
			
		||||
	"author": "sheetjs",
 | 
			
		||||
	"description": "SheetJS Spreadsheet data parser and writer",
 | 
			
		||||
	"keywords": [
 | 
			
		||||
 | 
			
		||||
@ -33,6 +33,10 @@ a { text-decoration: none }
 | 
			
		||||
 | 
			
		||||
- When available, modern browsers use `URL.createObjectURL`.
 | 
			
		||||
 | 
			
		||||
<b>Multiple Download Caveat</b>
 | 
			
		||||
 | 
			
		||||
Some browsers warn or block attempts to download multiple files.  Chrome content
 | 
			
		||||
settings support whitelisting domains for automatic multiple downloads.
 | 
			
		||||
</pre>
 | 
			
		||||
<script src="shim.js"></script>
 | 
			
		||||
<script src="xlsx.full.min.js"></script>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								xlsx.flow.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										11
									
								
								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.12.6';
 | 
			
		||||
XLSX.version = '0.12.7';
 | 
			
		||||
var current_codepage = 1200, current_ansi = 1252;
 | 
			
		||||
/*:: declare var cptable:any; */
 | 
			
		||||
/*global cptable:true */
 | 
			
		||||
@ -1914,7 +1914,7 @@ function blobify(data) {
 | 
			
		||||
}
 | 
			
		||||
/* write or download file */
 | 
			
		||||
function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
 | 
			
		||||
	/*global IE_SaveFile, Blob, navigator, saveAs, URL, document, File */
 | 
			
		||||
	/*global IE_SaveFile, Blob, navigator, saveAs, URL, document, File, chrome */
 | 
			
		||||
	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; */
 | 
			
		||||
@ -1926,9 +1926,14 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
 | 
			
		||||
		/*:: declare var saveAs: any; */
 | 
			
		||||
		if(typeof saveAs !== 'undefined') return saveAs(blob, fname);
 | 
			
		||||
		if(typeof URL !== 'undefined' && typeof document !== 'undefined' && document.createElement && URL.createObjectURL) {
 | 
			
		||||
			var url = URL.createObjectURL(blob);
 | 
			
		||||
			/*:: declare var chrome: any; */
 | 
			
		||||
			if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
 | 
			
		||||
				if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
 | 
			
		||||
				return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
 | 
			
		||||
			}
 | 
			
		||||
			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);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								xlsx.js
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										10
									
								
								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.12.6';
 | 
			
		||||
XLSX.version = '0.12.7';
 | 
			
		||||
var current_codepage = 1200, current_ansi = 1252;
 | 
			
		||||
/*global cptable:true */
 | 
			
		||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
 | 
			
		||||
@ -1843,7 +1843,7 @@ function blobify(data) {
 | 
			
		||||
}
 | 
			
		||||
/* write or download file */
 | 
			
		||||
function write_dl(fname, payload, enc) {
 | 
			
		||||
	/*global IE_SaveFile, Blob, navigator, saveAs, URL, document, File */
 | 
			
		||||
	/*global IE_SaveFile, Blob, navigator, saveAs, URL, document, File, chrome */
 | 
			
		||||
	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);
 | 
			
		||||
@ -1852,9 +1852,13 @@ if(typeof IE_SaveFile !== 'undefined') return IE_SaveFile(data, fname);
 | 
			
		||||
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 url = URL.createObjectURL(blob);
 | 
			
		||||
if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
 | 
			
		||||
				if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
 | 
			
		||||
				return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
 | 
			
		||||
			}
 | 
			
		||||
			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);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user