forked from sheetjs/docs.sheetjs.com
		
	frontend
This commit is contained in:
		
							parent
							
								
									e27218f52a
								
							
						
					
					
						commit
						8171c10af4
					
				| @ -123,7 +123,7 @@ The module also ships with `xlsx.mjs` for use with `import`.  The `mjs` version | ||||
| does not automatically load native node modules, so they must be added manually: | ||||
| 
 | ||||
| ```js | ||||
| import * as XLSX from 'xlsx/xlsx.mjs'; | ||||
| import * as XLSX from 'xlsx'; | ||||
| 
 | ||||
| /* load 'fs' for readFile and writeFile support */ | ||||
| import * as fs from 'fs'; | ||||
|  | ||||
| @ -213,7 +213,7 @@ import Tabs from '@theme/Tabs'; | ||||
| import TabItem from '@theme/TabItem'; | ||||
| 
 | ||||
| <Tabs> | ||||
|   <TabItem value="browser" label="Browser"> | ||||
|   <TabItem value="browser" label="Web Browser"> | ||||
| 
 | ||||
| Save the following script to `snippet.html` and open the page.  The page must be | ||||
| hosted (no `file:///` access). | ||||
| @ -251,13 +251,13 @@ hosted (no `file:///` access). | ||||
|   worksheet["!cols"] = [ { wch: max_width } ]; | ||||
| 
 | ||||
|   /* create an XLSX file and try to save to Presidents.xlsx */ | ||||
|   XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true })); | ||||
|   XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); | ||||
| })(); | ||||
| </script> | ||||
| <body> | ||||
| ``` | ||||
|   </TabItem> | ||||
|   <TabItem value="nodejs" label="NodeJS"> | ||||
|   <TabItem value="nodejs" label="Command-Line (NodeJS)"> | ||||
| 
 | ||||
| Install the dependencies: | ||||
| 
 | ||||
| @ -297,10 +297,12 @@ const XLSX = require("xlsx"); | ||||
|   worksheet["!cols"] = [ { wch: max_width } ]; | ||||
| 
 | ||||
|   /* create an XLSX file and try to save to Presidents.xlsx */ | ||||
|   XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true })); | ||||
|   XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); | ||||
| })(); | ||||
| ``` | ||||
| 
 | ||||
| :::caution | ||||
| 
 | ||||
| Native `fetch` support was added in NodeJS 18.  For older versions of NodeJS, | ||||
| the script will throw an error `fetch is not defined`.  A third-party library | ||||
| like `axios` presents a similar API for fetching data: | ||||
| @ -310,7 +312,7 @@ like `axios` presents a similar API for fetching data: | ||||
| Install the dependencies: | ||||
| 
 | ||||
| ```bash | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz axios | ||||
| ``` | ||||
| 
 | ||||
| The differences in the script are highlighted below. | ||||
| @ -348,13 +350,17 @@ const axios = require("axios"); | ||||
|   worksheet["!cols"] = [ { wch: max_width } ]; | ||||
| 
 | ||||
|   /* create an XLSX file and try to save to Presidents.xlsx */ | ||||
|   XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true })); | ||||
|   XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); | ||||
| })(); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
|   </TabItem> | ||||
| ::: | ||||
| 
 | ||||
| <details><summary><b>Other Server-Side Platforms</b> (click to show)</summary> | ||||
| 
 | ||||
| <Tabs> | ||||
|   <TabItem value="deno" label="Deno"> | ||||
| 
 | ||||
| Save the following script to `snippet.ts` and run with | ||||
| @ -390,7 +396,7 @@ const max_width = rows.reduce((w: number, r: any) => Math.max(w, r.name.length), | ||||
| worksheet["!cols"] = [ { wch: max_width } ]; | ||||
| 
 | ||||
| /* create an XLSX file and try to save to Presidents.xlsx */ | ||||
| XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true })); | ||||
| XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); | ||||
| ``` | ||||
| 
 | ||||
|   </TabItem> | ||||
| @ -431,9 +437,184 @@ const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); | ||||
| worksheet["!cols"] = [ { wch: max_width } ]; | ||||
| 
 | ||||
| /* create an XLSX file and try to save to Presidents.xlsx */ | ||||
| XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true })); | ||||
| XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); | ||||
| ``` | ||||
| 
 | ||||
|   </TabItem> | ||||
| </Tabs> | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
|   </TabItem> | ||||
| 
 | ||||
|   <TabItem value="desktop" label="Desktop App"> | ||||
| 
 | ||||
| Save the following script to `snippet.html`: | ||||
| 
 | ||||
| ```html title="snippet.html" | ||||
| <body> | ||||
| <script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script> | ||||
| <script> | ||||
| (async() => { | ||||
|   /* fetch JSON data and parse */ | ||||
|   const url = "https://sheetjs.com/data/executive.json"; | ||||
|   const raw_data = await (await fetch(url)).json(); | ||||
| 
 | ||||
|   /* filter for the Presidents */ | ||||
|   const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); | ||||
| 
 | ||||
|   /* flatten objects */ | ||||
|   const rows = prez.map(row => ({ | ||||
|     name: row.name.first + " " + row.name.last, | ||||
|     birthday: row.bio.birthday | ||||
|   })); | ||||
| 
 | ||||
|   /* generate worksheet and workbook */ | ||||
|   const worksheet = XLSX.utils.json_to_sheet(rows); | ||||
|   const workbook = XLSX.utils.book_new(); | ||||
|   XLSX.utils.book_append_sheet(workbook, worksheet, "Dates"); | ||||
| 
 | ||||
|   /* fix headers */ | ||||
|   XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); | ||||
| 
 | ||||
|   /* calculate column width */ | ||||
|   const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); | ||||
|   worksheet["!cols"] = [ { wch: max_width } ]; | ||||
| 
 | ||||
|   /* create an XLSX file and try to save to Presidents.xlsx */ | ||||
|   XLSX.writeFile(workbook, "Presidents.xlsx", { compression: true }); | ||||
| })(); | ||||
| </script> | ||||
| <body> | ||||
| ``` | ||||
| 
 | ||||
| Save the following to `package.json`: | ||||
| 
 | ||||
| ```json title="package.json" | ||||
| { | ||||
|   "name": "sheetjs-nwjs", | ||||
|   "author": "sheetjs", | ||||
|   "version": "0.0.0", | ||||
|   "main": "snippet.html", | ||||
|   "dependencies": { | ||||
|     "nw": "~0.66.0", | ||||
|     "xlsx": "https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz" | ||||
|   } | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| Install dependencies and build the app: | ||||
| 
 | ||||
| ```bash | ||||
| npm i | ||||
| npx -p nw-builder nwbuild --mode=build . | ||||
| ``` | ||||
| 
 | ||||
| Run the generated app in the `build\sheetjs-nwjs` folder.  It will show a save | ||||
| dialog box. After selecting a path, the app will write the file. | ||||
| 
 | ||||
|   </TabItem> | ||||
|   <TabItem value="mobile" label="Mobile App"> | ||||
| 
 | ||||
| :::caution | ||||
| 
 | ||||
| This demo runs in iOS and requires a Macintosh computer with Xcode installed. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| :::note Initial Setup | ||||
| 
 | ||||
| Follow the [Environment Setup](https://reactnative.dev/docs/environment-setup) | ||||
| of the React Native documentation before testing the demo. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| Create a new project by running the following commands in the Terminal: | ||||
| 
 | ||||
| ```bash | ||||
| npx react-native init SheetJSPres --version="0.70.6" | ||||
| cd SheetJSPres | ||||
| 
 | ||||
| npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz react-native-blob-util@0.17.1 | ||||
| 
 | ||||
| mkdir -p patches | ||||
| curl -L -o patches/react-native+0.70.6.patch https://github.com/facebook/react-native/files/10356761/react-native%2B0.70.6.patch | ||||
| npx patch-package | ||||
| 
 | ||||
| cd ios | ||||
| pod install | ||||
| cd .. | ||||
| ``` | ||||
| 
 | ||||
| Save the following to `App.js` in the project: | ||||
| 
 | ||||
| ```js title="App.js" | ||||
| import React from 'react'; | ||||
| import { Alert, Button, SafeAreaView, Text, View } from 'react-native'; | ||||
| import { utils, version, write } from 'xlsx'; | ||||
| import RNFetchBlob from 'react-native-blob-util'; | ||||
| 
 | ||||
| const make_workbook = async() => { | ||||
|   /* fetch JSON data and parse */ | ||||
|   const url = "https://sheetjs.com/data/executive.json"; | ||||
|   const raw_data = await (await fetch(url)).json(); | ||||
| 
 | ||||
|   /* filter for the Presidents */ | ||||
|   const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez")); | ||||
| 
 | ||||
|   /* flatten objects */ | ||||
|   const rows = prez.map(row => ({ | ||||
|     name: row.name.first + " " + row.name.last, | ||||
|     birthday: row.bio.birthday | ||||
|   })); | ||||
| 
 | ||||
|   /* generate worksheet and workbook */ | ||||
|   const worksheet = utils.json_to_sheet(rows); | ||||
|   const workbook = utils.book_new(); | ||||
|   utils.book_append_sheet(workbook, worksheet, "Dates"); | ||||
| 
 | ||||
|   /* fix headers */ | ||||
|   utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" }); | ||||
| 
 | ||||
|   /* calculate column width */ | ||||
|   const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10); | ||||
|   worksheet["!cols"] = [ { wch: max_width } ]; | ||||
| 
 | ||||
|   /* React Native does not support `writeFile`. This is a low-level write ! */ | ||||
| 
 | ||||
|   /* write workbook to buffer */ | ||||
|   const buf = write(workbook, {type:'buffer', bookType:"xlsx"}); | ||||
| 
 | ||||
|   /* write buffer to file */ | ||||
|   const filename = RNFetchBlob.fs.dirs.DocumentDir + "/Presidents.xlsx"; | ||||
|   await RNFetchBlob.fs.writeFile(filename, Array.from(buf), 'ascii'); | ||||
| 
 | ||||
|   return file; | ||||
| }; | ||||
| 
 | ||||
| const App = () => ( <SafeAreaView><View style={{ marginTop: 32, padding: 24 }}> | ||||
|   <Text style={{ fontSize: 24, fontWeight: 'bold' }}>SheetJS {version} Export Demo</Text> | ||||
|   <Button title='Press to Export' onPress={async() => { | ||||
|     try { | ||||
|       const filename = await make_workbook(); | ||||
|       Alert.alert("Export Finished", `Exported to ${filename}`); | ||||
|     } catch(err) { | ||||
|       Alert.alert("Export Error", `Error ${err.message||err}`); | ||||
|     } | ||||
|   }}/> | ||||
| </View></SafeAreaView> ); | ||||
| 
 | ||||
| export default App; | ||||
| ``` | ||||
| 
 | ||||
| Test the app in the iOS simulator: | ||||
| 
 | ||||
| ```bash | ||||
| npm run ios | ||||
| ``` | ||||
| 
 | ||||
| After clicking "Press to Export", the app will show an alert with the location | ||||
| to the generated file. | ||||
| 
 | ||||
|   </TabItem> | ||||
| </Tabs> | ||||
| @ -13,54 +13,26 @@ import TabItem from '@theme/TabItem'; | ||||
| The [Standalone scripts](/docs/getting-started/installation/standalone) can be | ||||
| referenced in a `SCRIPT` tag from the entry point HTML page. | ||||
| 
 | ||||
| This demo was tested against NW.js 0.66.0. | ||||
| This demo was tested against NW.js 0.66.0 on 2022 January 07. | ||||
| 
 | ||||
| <details><summary><b>Complete Example</b> (click to show)</summary> | ||||
| The "Complete Example" creates an app that looks like the screenshots below: | ||||
| 
 | ||||
| 1) Create a `package.json` file that specifies the entry point: | ||||
| <table><thead><tr> | ||||
|   <th><a href="#complete-example">macOS</a></th> | ||||
|   <th><a href="#complete-example">Linux</a></th> | ||||
| </tr></thead><tbody><tr><td> | ||||
| 
 | ||||
| ```json title="package.json" | ||||
| { | ||||
|   "name": "sheetjs-nwjs", | ||||
|   "author": "sheetjs", | ||||
|   "version": "0.0.0", | ||||
|   "main": "index.html", | ||||
|   "dependencies": { | ||||
|     "nw": "~0.66.0", | ||||
|     "xlsx": "https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz" | ||||
|   } | ||||
| } | ||||
| ``` | ||||
|  | ||||
| 
 | ||||
| 2) Download [`index.html`](pathname:///nwjs/index.html) into the same folder. | ||||
| </td><td> | ||||
| 
 | ||||
| :::caution | ||||
|  | ||||
| 
 | ||||
| Right-click the link and select "Save Link As...".  Left-clicking the link will | ||||
| try to load the page in your browser.  The goal is to save the file contents. | ||||
| </td></tr></tbody></table> | ||||
| 
 | ||||
| ::: | ||||
| ## Integration Details | ||||
| 
 | ||||
| 3) Run `npm install` to install dependencies | ||||
| 
 | ||||
| 4) To verify the app works, run in the test environment: | ||||
| 
 | ||||
| ``` | ||||
| npx nw . | ||||
| ``` | ||||
| 
 | ||||
| The app will show and you should be able to verify reading and writing by using | ||||
| the file input element to select a spreadsheet and clicking the export button. | ||||
| 
 | ||||
| 5) To build a standalone app, run the builder: | ||||
| 
 | ||||
| ``` | ||||
| npx -p nw-builder nwbuild --mode=build . | ||||
| ``` | ||||
| 
 | ||||
| This will generate the standalone app in the `build\sheetjs-nwjs\` folder. | ||||
| 
 | ||||
| </details> | ||||
| NW.js provides solutions for reading and writing files. | ||||
| 
 | ||||
| ### Reading data | ||||
| 
 | ||||
| @ -119,7 +91,7 @@ input.addEventListener('change',function(e){ | ||||
|   /* highlight-next-line */ | ||||
|   var wbout = XLSX.write(workbook, {type:'buffer', bookType:"xlsx"}); | ||||
|   /* highlight-next-line */ | ||||
|   fs.writeFile(filename, wbout, function(err) { | ||||
|   require("fs").writeFile(filename, wbout, function(err) { | ||||
|     if(!err) return alert("Saved to " + filename); | ||||
|     alert("Error: " + (err.message || err)); | ||||
|   }); | ||||
| @ -127,3 +99,48 @@ input.addEventListener('change',function(e){ | ||||
| 
 | ||||
| input.click(); | ||||
| ``` | ||||
| 
 | ||||
| ## Complete Example | ||||
| 
 | ||||
| 1) Create a `package.json` file that specifies the entry point: | ||||
| 
 | ||||
| ```json title="package.json" | ||||
| { | ||||
|   "name": "sheetjs-nwjs", | ||||
|   "author": "sheetjs", | ||||
|   "version": "0.0.0", | ||||
|   "main": "index.html", | ||||
|   "dependencies": { | ||||
|     "nw": "~0.66.0", | ||||
|     "xlsx": "https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz" | ||||
|   } | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 2) Download [`index.html`](pathname:///nwjs/index.html) into the same folder. | ||||
| 
 | ||||
| :::caution | ||||
| 
 | ||||
| Right-click the link and select "Save Link As...".  Left-clicking the link will | ||||
| try to load the page in your browser.  The goal is to save the file contents. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| 3) Run `npm install` to install dependencies | ||||
| 
 | ||||
| 4) To verify the app works, run in the test environment: | ||||
| 
 | ||||
| ```bash | ||||
| npx nw . | ||||
| ``` | ||||
| 
 | ||||
| The app will show and you should be able to verify reading and writing by using | ||||
| the file input element to select a spreadsheet and clicking the export button. | ||||
| 
 | ||||
| 5) To build a standalone app, run the builder: | ||||
| 
 | ||||
| ```bash | ||||
| npx -p nw-builder nwbuild --mode=build . | ||||
| ``` | ||||
| 
 | ||||
| This will generate the standalone app in the `build\sheetjs-nwjs\` folder. | ||||
| @ -13,71 +13,56 @@ import TabItem from '@theme/TabItem'; | ||||
| The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported | ||||
| from JavaScript code. | ||||
| 
 | ||||
| This demo was tested against Wails `v2.0.0-beta.44.2` on 2022 August 31 using | ||||
| the Svelte TypeScript starter. | ||||
| The "Complete Example" creates an app that looks like the screenshot: | ||||
| 
 | ||||
| <table><thead><tr> | ||||
|   <th><a href="#complete-example">macOS</a></th> | ||||
|   <th><a href="#complete-example">Linux</a></th> | ||||
| </tr></thead><tbody><tr><td> | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| </td><td> | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| </td></tr></tbody></table> | ||||
| 
 | ||||
| ## Native Modules | ||||
| 
 | ||||
| All operations must be run from Go code.  This example passes Base64 strings. | ||||
| 
 | ||||
| :::caution | ||||
| 
 | ||||
| Wails currently does not provide the equivalent of NodeJS `fs` module. | ||||
| Wails currently does not provide the equivalent of NodeJS `fs` module.  All raw | ||||
| file operations must be performed in Go code. | ||||
| 
 | ||||
| The HTML File Input Element does not show a file picker.  This is a known bug. | ||||
| 
 | ||||
| All raw file operations must be performed in Go code. | ||||
| The demo works around the issue by showing pickers in Go code. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| 
 | ||||
| The "Complete Example" creates an app that looks like the screenshot: | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| <details><summary><b>Complete Example</b> (click to show)</summary> | ||||
| 
 | ||||
| 0) [Read Wails "Getting Started" guide and install dependencies.](https://wails.io/docs/gettingstarted/installation) | ||||
| 
 | ||||
| 1) Create a new Wails app: | ||||
| 
 | ||||
| ```bash | ||||
| wails init -n sheetjs-wails -t svelte-ts | ||||
| ``` | ||||
| 
 | ||||
| 2) Enter the directory: | ||||
| 
 | ||||
| ```bash | ||||
| cd sheetjs-wails | ||||
| ``` | ||||
| 
 | ||||
| 3) Install front-end dependencies: | ||||
| 
 | ||||
| ```bash | ||||
| cd frontend | ||||
| curl -L -o src/assets/logo.png https://sheetjs.com/sketch1024.png | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz | ||||
| cd .. | ||||
| ``` | ||||
| 
 | ||||
| 4) Download source files: | ||||
| 
 | ||||
| - Download [`app.go`](pathname:///wails/app.go) and replace `app.go` | ||||
| - Download [`App.svelte`](pathname:///wails/App.svelte) and replace | ||||
|   `frontend/src/App.svelte` | ||||
| 
 | ||||
| 5) Build the app with | ||||
| 
 | ||||
| ```bash | ||||
| wails build | ||||
| ``` | ||||
| 
 | ||||
| At the end, it will print the path to the generated program. Run the program! | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| All operations must be run from Go code.  This example passes Base64 strings. | ||||
| 
 | ||||
| ### Reading Files | ||||
| 
 | ||||
| The file picker and reading operations can be combined in one Go function. | ||||
| 
 | ||||
| ```mermaid | ||||
| sequenceDiagram | ||||
|   autonumber | ||||
|   actor User | ||||
|   participant JS | ||||
|   participant Go | ||||
|   User->>JS: click button | ||||
|   JS->>Go: ask for data | ||||
|   Note over Go: Show Open Dialog | ||||
|   Note over Go: Read File Bytes | ||||
|   Note over Go: Generate Base64 | ||||
|   Go->>JS: return data | ||||
|   Note over JS: Parse data | ||||
|   Note over JS: Display Table | ||||
|   JS->>User: app shows data | ||||
| ``` | ||||
| 
 | ||||
| #### Go | ||||
| 
 | ||||
| ```go | ||||
| @ -115,14 +100,15 @@ func (a *App) ReadFile() string { | ||||
| 
 | ||||
| #### JS | ||||
| 
 | ||||
| Wails will automatically create `window.go.main.App.ReadFile` for use in JS: | ||||
| Wails will automatically create bindings for use in JS: | ||||
| 
 | ||||
| ```js title="frontend/src/App.svelte" | ||||
| import { read, utils } from 'xlsx'; | ||||
| import { ReadFile } from '../wailsjs/go/main/App'; | ||||
| 
 | ||||
| async function importFile(evt) { | ||||
| // highlight-start | ||||
|   const b64 = window['go']['main']['App']['ReadFile'](); | ||||
|   const b64 = await ReadFile(); | ||||
|   const wb = read(b64, { type: "base64" }); | ||||
| // highlight-end | ||||
|   const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet | ||||
| @ -140,6 +126,24 @@ There is a multi-part dance since the library needs the file extension. | ||||
| 
 | ||||
| 3) Write to file in Go | ||||
| 
 | ||||
| ```mermaid | ||||
| sequenceDiagram | ||||
|   autonumber | ||||
|   actor User | ||||
|   participant JS | ||||
|   participant Go | ||||
|   User->>JS: click button | ||||
|   JS->>Go: ask for path | ||||
|   Note over Go: Show Save Dialog | ||||
|   Go->>JS: path to save file | ||||
|   Note over JS: write workbook | ||||
|   JS->>Go: base64-encoded bytes | ||||
|   Note over Go: decode data | ||||
|   Note over Go: write to file | ||||
|   Go->>JS: write finished | ||||
|   JS->>User: alert | ||||
| ``` | ||||
| 
 | ||||
| ##### Go | ||||
| 
 | ||||
| Two Go functions will be exposed. | ||||
| @ -149,9 +153,8 @@ Two Go functions will be exposed. | ||||
| ```go | ||||
| import ( | ||||
|   "context" | ||||
| // highlight-start | ||||
| // highlight-next-line | ||||
|   "github.com/wailsapp/wails/v2/pkg/runtime" | ||||
| // highlight-end | ||||
| ) | ||||
| 
 | ||||
| type App struct { | ||||
| @ -202,6 +205,7 @@ Wails will automatically create bindings for use in JS: | ||||
| 
 | ||||
| ```js | ||||
| import { utils, write } from 'xlsx'; | ||||
| import { SaveFile, WriteFile } from '../wailsjs/go/main/App'; | ||||
| 
 | ||||
| async function exportFile(wb) { | ||||
|   /* generate workbook */ | ||||
| @ -209,13 +213,59 @@ async function exportFile(wb) { | ||||
|   const wb = utils.table_to_book(elt); | ||||
| 
 | ||||
|   /* show save picker and get path */ | ||||
|   const path = await window['go']['main']['App']['SaveFile'](); | ||||
|   const path = await SaveFile(); | ||||
| 
 | ||||
|   /* generate base64 string based on the path */ | ||||
|   const b64 = write(wb, { bookType: path.slice(path.lastIndexOf(".")+1), type: "base64" }); | ||||
| 
 | ||||
|   /* write to file */ | ||||
|   await window['go']['main']['App']['WriteFile'](b64, path); | ||||
|   // The demo shows a success message at this point | ||||
|   await WriteFile(b64, path); | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ## Complete Example | ||||
| 
 | ||||
| This demo was tested against Wails `v2.3.1` on 2023 January 08 using | ||||
| the Svelte TypeScript starter. | ||||
| 
 | ||||
| 0) [Read Wails "Getting Started" guide and install dependencies.](https://wails.io/docs/gettingstarted/installation) | ||||
| 
 | ||||
| 1) Create a new Wails app: | ||||
| 
 | ||||
| ```bash | ||||
| wails init -n sheetjs-wails -t svelte-ts | ||||
| ``` | ||||
| 
 | ||||
| 2) Enter the directory: | ||||
| 
 | ||||
| ```bash | ||||
| cd sheetjs-wails | ||||
| ``` | ||||
| 
 | ||||
| 3) Install front-end dependencies: | ||||
| 
 | ||||
| ```bash | ||||
| cd frontend | ||||
| curl -L -o src/assets/logo.png https://sheetjs.com/sketch1024.png | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz | ||||
| cd .. | ||||
| ``` | ||||
| 
 | ||||
| 4) Download source files: | ||||
| 
 | ||||
| - Download [`app.go`](pathname:///wails/app.go) and replace `app.go` | ||||
| - Download [`App.svelte`](pathname:///wails/App.svelte) and replace | ||||
|   `frontend/src/App.svelte` | ||||
| 
 | ||||
| ```bash | ||||
| curl -L -o app.go https://docs.sheetjs.com/wails/app.go | ||||
| curl -L -o frontend/src/App.svelte https://docs.sheetjs.com/wails/App.svelte | ||||
| ``` | ||||
| 
 | ||||
| 5) Build the app with | ||||
| 
 | ||||
| ```bash | ||||
| wails build | ||||
| ``` | ||||
| 
 | ||||
| At the end, it will print the path to the generated program. Run the program! | ||||
|  | ||||
| @ -292,7 +292,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz better-sqlite3 | ||||
| import Database from "better-sqlite3"; | ||||
| 
 | ||||
| /* Load SheetJS library */ | ||||
| import * as XLSX from 'xlsx/xlsx.mjs'; | ||||
| import * as XLSX from 'xlsx'; | ||||
| import * as fs from 'fs'; | ||||
| XLSX.set_fs(fs); | ||||
| 
 | ||||
| @ -342,7 +342,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz | ||||
| import { Database } from "bun:sqlite"; | ||||
| 
 | ||||
| /* Load SheetJS library */ | ||||
| import * as XLSX from 'xlsx/xlsx.mjs'; | ||||
| import * as XLSX from 'xlsx'; | ||||
| import * as fs from 'fs'; | ||||
| XLSX.set_fs(fs); | ||||
| 
 | ||||
| @ -817,7 +817,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz mongodb | ||||
| 3) Save the following to `SheetJSMongoCRUD.mjs` (the key step is highlighted): | ||||
| 
 | ||||
| ```js title="SheetJSMongoCRUD.mjs" | ||||
| import { writeFile, set_fs, utils } from 'xlsx/xlsx.mjs'; | ||||
| import { writeFile, set_fs, utils } from 'xlsx'; | ||||
| import * as fs from 'fs'; set_fs(fs); | ||||
| import { MongoClient } from 'mongodb'; | ||||
| 
 | ||||
|  | ||||
| @ -1,5 +1,8 @@ | ||||
| --- | ||||
| title: Angular | ||||
| pagination_prev: demos/server | ||||
| pagination_next: demos/aws | ||||
| sidebar_position: 1 | ||||
| --- | ||||
| 
 | ||||
| import Tabs from '@theme/Tabs'; | ||||
| @ -1,5 +1,8 @@ | ||||
| --- | ||||
| title: ReactJS | ||||
| pagination_prev: demos/server | ||||
| pagination_next: demos/aws | ||||
| sidebar_position: 2 | ||||
| --- | ||||
| 
 | ||||
| [ReactJS](https://reactjs.org/) is a JS library for building user interfaces. | ||||
| @ -1,5 +1,8 @@ | ||||
| --- | ||||
| title: VueJS | ||||
| pagination_prev: demos/server | ||||
| pagination_next: demos/aws | ||||
| sidebar_position: 3 | ||||
| --- | ||||
| 
 | ||||
| [VueJS](https://vuejs.org/) is a JS library for building user interfaces. | ||||
| @ -1,5 +1,8 @@ | ||||
| --- | ||||
| title: Svelte | ||||
| pagination_prev: demos/server | ||||
| pagination_next: demos/aws | ||||
| sidebar_position: 4 | ||||
| --- | ||||
| 
 | ||||
| [Svelte](https://svelte.dev/) is a JS library for building user interfaces. | ||||
| @ -1,5 +1,10 @@ | ||||
| --- | ||||
| title: Bundlers | ||||
| pagination_prev: demos/server | ||||
| pagination_next: demos/aws | ||||
| sidebar_position: 8 | ||||
| sidebar_custom_props: | ||||
|   skip: 1 | ||||
| --- | ||||
| 
 | ||||
| import current from '/version.js'; | ||||
| @ -116,7 +121,7 @@ yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | ||||
| 
 | ||||
| ```js title="bun.js" | ||||
| // highlight-next-line | ||||
| import * as XLSX from 'xlsx/xlsx.mjs'; | ||||
| import * as XLSX from 'xlsx'; | ||||
| // highlight-next-line | ||||
| import * as fs from 'fs'; | ||||
| // highlight-next-line | ||||
| @ -211,7 +216,7 @@ yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | ||||
| 
 | ||||
| ```js title="esbrowser.js" | ||||
| // highlight-next-line | ||||
| import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs'; | ||||
| import { utils, version, writeFileXLSX } from 'xlsx'; | ||||
| 
 | ||||
| (async() => { | ||||
| /* fetch JSON data and parse */ | ||||
| @ -289,7 +294,7 @@ yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | ||||
| 
 | ||||
| ```js title="esbnode.js" | ||||
| // highlight-next-line | ||||
| import { set_fs, utils, version, writeFile } from 'xlsx/xlsx.mjs'; | ||||
| import { set_fs, utils, version, writeFile } from 'xlsx'; | ||||
| // highlight-next-line | ||||
| import * as fs from 'fs'; | ||||
| // highlight-next-line | ||||
| @ -496,7 +501,7 @@ yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} rollup @r | ||||
| 
 | ||||
| ```js title="index.js" | ||||
| // highlight-next-line | ||||
| import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs'; | ||||
| import { utils, version, writeFileXLSX } from 'xlsx'; | ||||
| 
 | ||||
| document.getElementById("xport").addEventListener("click", async() => { | ||||
| /* fetch JSON data and parse */ | ||||
| @ -590,7 +595,7 @@ yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | ||||
| 
 | ||||
| ```js title="index.js" | ||||
| // highlight-next-line | ||||
| import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs'; | ||||
| import { utils, version, writeFileXLSX } from 'xlsx'; | ||||
| 
 | ||||
| document.getElementById("xport").addEventListener("click", async() => { | ||||
| /* fetch JSON data and parse */ | ||||
| @ -1116,7 +1121,7 @@ yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | ||||
| 
 | ||||
| ```js title="index.js" | ||||
| // highlight-next-line | ||||
| import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs'; | ||||
| import { utils, version, writeFileXLSX } from 'xlsx'; | ||||
| 
 | ||||
| document.getElementById("xport").addEventListener("click", async() => { | ||||
| /* fetch JSON data and parse */ | ||||
| @ -1276,7 +1281,7 @@ yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | ||||
| 
 | ||||
| ```js title="index.js" | ||||
| // highlight-next-line | ||||
| import { utils, version, writeFileXLSX } from 'xlsx/xlsx.mjs'; | ||||
| import { utils, version, writeFileXLSX } from 'xlsx'; | ||||
| 
 | ||||
| document.getElementById("xport").addEventListener("click", async() => { | ||||
| /* fetch JSON data and parse */ | ||||
| @ -1,5 +1,10 @@ | ||||
| --- | ||||
| title: Legacy Frameworks | ||||
| pagination_prev: demos/server | ||||
| pagination_next: demos/aws | ||||
| sidebar_position: 9 | ||||
| sidebar_custom_props: | ||||
|   skip: 1 | ||||
| --- | ||||
| 
 | ||||
| import current from '/version.js'; | ||||
							
								
								
									
										5
									
								
								docz/docs/03-demos/10-frontend/_category_.json
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										5
									
								
								docz/docs/03-demos/10-frontend/_category_.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| { | ||||
|   "label": "Web Frameworks", | ||||
|   "position": 10, | ||||
|   "collapsed": false | ||||
| } | ||||
							
								
								
									
										56
									
								
								docz/docs/03-demos/10-frontend/index.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										56
									
								
								docz/docs/03-demos/10-frontend/index.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | ||||
| --- | ||||
| title: Web Frameworks | ||||
| pagination_prev: demos/server | ||||
| pagination_next: demos/aws | ||||
| --- | ||||
| 
 | ||||
| import DocCardList from '@theme/DocCardList'; | ||||
| import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; | ||||
| 
 | ||||
| Web frameworks help provide structure to modern web applications. Opinionated | ||||
| structures help keep development teams aligned and make code reuse viable. | ||||
| 
 | ||||
| SheetJS libraries are written in pure JavaScript and are readily integrated in | ||||
| web applications using any framework.  As each framework has its own ecosystem, | ||||
| the demos focus on how SheetJS data concepts map to common ecosystem patterns. | ||||
| 
 | ||||
| ### Web Frameworks | ||||
| 
 | ||||
| Demos for popular frameworks are included in separate pages: | ||||
| 
 | ||||
| <ul>{useCurrentSidebarCategory().items.filter(item => !item?.customProps?.skip).map((item, index) => { | ||||
|   const listyle = (item.customProps?.icon) ? { | ||||
|     listStyleImage: `url("${item.customProps.icon}")` | ||||
|   } : {}; | ||||
|   return (<li style={listyle} {...(item.customProps?.class ? {className: item.customProps.class}: {})}> | ||||
|     <a href={item.href}>{item.label}</a>{item.customProps?.summary && (" - " + item.customProps.summary)} | ||||
|   </li>); | ||||
| })}</ul> | ||||
| 
 | ||||
| Legacy frameworks including old AngularJS are covered [in the "Legacy" section](/docs/demos/frontend/legacy). | ||||
| 
 | ||||
| :::note Recommendation | ||||
| 
 | ||||
| It is strongly recommended to use a framework.  While modern websites can be | ||||
| built without frameworks, the framework ecosystems have battle-tested solutions | ||||
| for organizing data, page updates / routing, and other common problems. | ||||
| 
 | ||||
| It is strongly recommended to stick with familiar frameworks. Teams well-versed | ||||
| in Angular should continue using Angular.  Teams well-versed in React should | ||||
| continue using React.  For common problems, there are official or community | ||||
| solutions using any framework. | ||||
| 
 | ||||
| Greenfield projects can be built with any framework.  The popular frameworks | ||||
| have large ecosystems and many talented developers for hire.  At the time of | ||||
| writing, React has the largest developer pool and module ecosystem. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| ### Bundlers and Tooling | ||||
| 
 | ||||
| Modern web applications are designed to be woven using CommonJS or ECMAScript | ||||
| modules. A "bundler" will combine application code and modules to produce a | ||||
| final website that can be deployed. | ||||
| 
 | ||||
| [The "Bundler" subsection](/docs/demos/frontend/bundler) covers a number of | ||||
| common bundlers and build tools. | ||||
| @ -1,5 +1,6 @@ | ||||
| --- | ||||
| title: Amazon Web Services | ||||
| pagination_prev: demos/frontend/index | ||||
| --- | ||||
| 
 | ||||
| AWS is a Cloud Services platform which includes traditional virtual machine | ||||
|  | ||||
| @ -72,7 +72,7 @@ For Node ESM, `fs` must be loaded manually: | ||||
| 
 | ||||
| ```js | ||||
| import * as fs from "fs"; | ||||
| import { readFile, set_fs } from "xlsx/xlsx.mjs"; | ||||
| import { readFile, set_fs } from "xlsx"; | ||||
| set_fs(fs); | ||||
| 
 | ||||
| const workbook = readFile("test.xlsx"); | ||||
| @ -479,7 +479,7 @@ const url = "https://oss.sheetjs.com/test_files/formula_stress_test.xlsx"; | ||||
| Bun has native support for `fetch`.  Using the [NodeJS package](/docs/getting-started/installation/nodejs): | ||||
| 
 | ||||
| ```js | ||||
| import * as XLSX from 'xlsx/xlsx.mjs'; | ||||
| import * as XLSX from 'xlsx'; | ||||
| /* load the codepage support library for extended support with older formats  */ | ||||
| import * as cptable from 'xlsx/dist/cpexcel.full.mjs'; | ||||
| XLSX.set_cptable(cptable); | ||||
|  | ||||
| @ -185,7 +185,7 @@ For Node ESM, `fs` must be loaded manually: | ||||
| 
 | ||||
| ```js | ||||
| import * as fs from "fs"; | ||||
| import { writeFile, set_fs } from "xlsx/xlsx.mjs"; | ||||
| import { writeFile, set_fs } from "xlsx"; | ||||
| set_fs(fs); | ||||
| 
 | ||||
| /* output format determined by filename */ | ||||
| @ -199,7 +199,7 @@ As with Node ESM, `fs` must be loaded manually: | ||||
| 
 | ||||
| ```js | ||||
| import * as fs from "fs"; | ||||
| import { writeFile, set_fs } from "xlsx/xlsx.mjs"; | ||||
| import { writeFile, set_fs } from "xlsx"; | ||||
| set_fs(fs); | ||||
| 
 | ||||
| /* output format determined by filename */ | ||||
|  | ||||
| @ -171,6 +171,13 @@ const config = { | ||||
|         { from: '/docs/demos/excel', to: '/docs/demos/' }, | ||||
|         { from: '/docs/getting-started/demos/', to: '/docs/demos/' }, | ||||
|         { from: '/docs/getting-started/demos/excel', to: '/docs/demos/' }, | ||||
|         /* frontend */ | ||||
|         { from: '/docs/demos/angular', to: '/docs/demos/frontend/angular/' }, | ||||
|         { from: '/docs/demos/react', to: '/docs/demos/frontend/react/' }, | ||||
|         { from: '/docs/demos/svelte', to: '/docs/demos/frontend/svelte/' }, | ||||
|         { from: '/docs/demos/vue', to: '/docs/demos/frontend/vue/' }, | ||||
|         { from: '/docs/demos/bundler', to: '/docs/demos/frontend/bundler/' }, | ||||
|         { from: '/docs/demos/legacy', to: '/docs/demos/frontend/legacy/' }, | ||||
|       ] | ||||
|     }] | ||||
|   ] | ||||
|  | ||||
| @ -4,6 +4,7 @@ | ||||
| <html> | ||||
| <head> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
| <meta name="robots" content="noindex"> | ||||
| <title>SheetJS Live Demo</title> | ||||
| <style> | ||||
| #drop{ | ||||
|  | ||||
| @ -4,6 +4,7 @@ | ||||
| <html> | ||||
| <head> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
| <meta name="robots" content="noindex"> | ||||
| <title>SheetJS NW.js Demo</title> | ||||
| <style> | ||||
| #drop{ | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								docz/static/nwjs/nwl.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/nwjs/nwl.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 284 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docz/static/nwjs/nwm.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/nwjs/nwm.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 189 KiB | 
| @ -2,6 +2,11 @@ | ||||
| <!-- sheetjs (C) 2013-present  SheetJS https://sheetjs.com --> | ||||
| <!-- vim: set ts=2: --> | ||||
| <html lang="en" style="height: 100%"> | ||||
| <head> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
| <meta name="robots" content="noindex"> | ||||
| <title>SheetJS fetch Demo</title> | ||||
| </head> | ||||
| <body> | ||||
| <style>TABLE { border-collapse: collapse; } TD { border: 1px solid; }</style> | ||||
| <script src="https://unpkg.com/react@17/umd/react.development.js"></script> | ||||
|  | ||||
| @ -2,22 +2,26 @@ | ||||
| import logo from './assets/logo.png' | ||||
| import { onMount } from 'svelte'; | ||||
| import { read, utils, write, version } from 'xlsx'; | ||||
| import { ReadFile, SaveFile, WriteFile, ShowInfo, ShowError } from '../wailsjs/go/main/App'; | ||||
| 
 | ||||
| /* this wrapper to SaveFile / WriteFile shows messages on error / success */ | ||||
| async function writeFile(wb) { | ||||
|   const path = await window['go']['main']['App']['SaveFile'](); | ||||
|   const path = await SaveFile(); | ||||
|   if(!path) return await err("No file selected"); | ||||
|   const b64 = write(wb, { bookType: path.slice(path.lastIndexOf(".")+1), type: "base64" }); | ||||
|   await window['go']['main']['App']['WriteFile'](b64, path); | ||||
|   window['go']['main']['App']['ShowInfo']("Saved File", path); | ||||
|   await WriteFile(b64, path); | ||||
|   ShowInfo("Saved File", path); | ||||
| } | ||||
| 
 | ||||
| /* this wrapper to ReadFile throws an error if no data was read */ | ||||
| async function readFile() { | ||||
|   const res = await window['go']['main']['App']['ReadFile'](); | ||||
|   const res = await ReadFile(); | ||||
|   if(res.length == 0) throw "failed"; | ||||
|   return res; | ||||
| } | ||||
| 
 | ||||
| async function err(body, title = "") { | ||||
|   return window['go']['main']['App']['ShowError'](title, typeof body == "string" ? body : body.message); | ||||
|   return ShowError(title, typeof body == "string" ? body : body.message); | ||||
| } | ||||
| 
 | ||||
| let html = ""; | ||||
| @ -34,10 +38,10 @@ onMount(async() => { | ||||
| }); | ||||
| 
 | ||||
| /* get state data and export to XLSX */ | ||||
| function exportFile() { | ||||
| async function exportFile() { | ||||
|   const elt = tbl.getElementsByTagName("TABLE")[0]; | ||||
|   const wb = utils.table_to_book(elt); | ||||
|   try { writeFile(wb); } catch(e) { err(e); } | ||||
|   try { await writeFile(wb); } catch(e) { err(e); } | ||||
| } | ||||
| 
 | ||||
| /* show file picker, read file, load table */ | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								docz/static/wails/linux.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/wails/linux.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 302 KiB | 
		Loading…
	
		Reference in New Issue
	
	Block a user