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