| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | --- | 
					
						
							|  |  |  | title: Wails | 
					
						
							| 
									
										
										
										
											2023-01-05 23:33:49 +00:00
										 |  |  | pagination_prev: demos/mobile/index | 
					
						
							| 
									
										
										
										
											2023-01-10 00:31:37 +00:00
										 |  |  | pagination_next: demos/cloud/index | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | sidebar_position: 3 | 
					
						
							|  |  |  | sidebar_custom_props: | 
					
						
							|  |  |  |   summary: Webview + Go Backend | 
					
						
							|  |  |  | --- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import Tabs from '@theme/Tabs'; | 
					
						
							|  |  |  | import TabItem from '@theme/TabItem'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported | 
					
						
							|  |  |  | from JavaScript code. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The "Complete Example" creates an app that looks like the screenshot: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | <table><thead><tr> | 
					
						
							|  |  |  |   <th><a href="#complete-example">macOS</a></th> | 
					
						
							|  |  |  |   <th><a href="#complete-example">Linux</a></th> | 
					
						
							|  |  |  | </tr></thead><tbody><tr><td> | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  |  | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | </td><td> | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  |  | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | </td></tr></tbody></table> | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | ## Native Modules
 | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | All operations must be run from Go code.  This example passes Base64 strings. | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | :::caution | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | Wails currently does not provide the equivalent of NodeJS `fs` module.  All raw | 
					
						
							|  |  |  | file operations must be performed in Go code. | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | The HTML File Input Element does not show a file picker.  This is a known bug. | 
					
						
							|  |  |  | The demo works around the issue by showing pickers in Go code. | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | ::: | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ### Reading Files
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The file picker and reading operations can be combined in one Go function. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | ```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 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | #### Go
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```go | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  |   "context" | 
					
						
							|  |  |  | // highlight-start | 
					
						
							|  |  |  |   "encoding/base64" | 
					
						
							|  |  |  |   "io/ioutil" | 
					
						
							|  |  |  |   "github.com/wailsapp/wails/v2/pkg/runtime" | 
					
						
							|  |  |  | // highlight-end | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type App struct { | 
					
						
							|  |  |  |   ctx context.Context | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ReadFile shows an open file dialog and returns the data as Base64 string | 
					
						
							|  |  |  | func (a *App) ReadFile() string { | 
					
						
							|  |  |  |   // highlight-next-line | 
					
						
							|  |  |  |   selection, err := runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{ | 
					
						
							|  |  |  |     Title: "Select File", | 
					
						
							|  |  |  |     Filters: []runtime.FileFilter{ | 
					
						
							|  |  |  |       { DisplayName: "Excel Workbooks (*.xlsx)", Pattern: "*.xlsx", }, | 
					
						
							|  |  |  |       // ... more filters for more file types | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  |   if err != nil { return "" } // The demo app shows an error message | 
					
						
							|  |  |  |   // highlight-next-line | 
					
						
							|  |  |  |   data, err := ioutil.ReadFile(selection) | 
					
						
							|  |  |  |   if err != nil { return "" } // The demo app shows an error message | 
					
						
							|  |  |  |   // highlight-next-line | 
					
						
							|  |  |  |   return base64.StdEncoding.EncodeToString(data) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #### JS
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | Wails will automatically create bindings for use in JS: | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js title="frontend/src/App.svelte" | 
					
						
							|  |  |  | import { read, utils } from 'xlsx'; | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | import { ReadFile } from '../wailsjs/go/main/App'; | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | async function importFile(evt) { | 
					
						
							|  |  |  | // highlight-start | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  |   const b64 = await ReadFile(); | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  |   const wb = read(b64, { type: "base64" }); | 
					
						
							|  |  |  | // highlight-end | 
					
						
							|  |  |  |   const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet | 
					
						
							|  |  |  |   html = utils.sheet_to_html(ws); // generate HTML and update state | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Writing Files
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | There is a multi-part dance since the library needs the file extension. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1) Show the save file picker in Go, pass back to JS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 2) Generate the file data in JS, pass the data back to Go | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 3) Write to file in Go | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | ```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 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | ##### Go
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Two Go functions will be exposed. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - `SaveFile` will show the file picker and return the path: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```go | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  |   "context" | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | // highlight-next-line | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  |   "github.com/wailsapp/wails/v2/pkg/runtime" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type App struct { | 
					
						
							|  |  |  |   ctx context.Context | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (a *App) SaveFile() string { | 
					
						
							|  |  |  | // highlight-next-line | 
					
						
							|  |  |  |   selection, err := runtime.SaveFileDialog(a.ctx, runtime.SaveDialogOptions{ | 
					
						
							|  |  |  |     Title: "Select File", | 
					
						
							|  |  |  |     DefaultFilename: "SheetJSWails.xlsx", | 
					
						
							|  |  |  |     Filters: []runtime.FileFilter{ | 
					
						
							|  |  |  |       { DisplayName: "Excel Workbooks (*.xlsx)", Pattern: "*.xlsx", }, | 
					
						
							|  |  |  |       // ... more filters for more file types | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  |   if err != nil { return "" } // The demo app shows an error message | 
					
						
							|  |  |  |   return selection | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - `WriteFile` performs the file write given a Base64 string and file path: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```go | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  |   "context" | 
					
						
							|  |  |  | // highlight-start | 
					
						
							|  |  |  |   "encoding/base64" | 
					
						
							|  |  |  |   "io/ioutil" | 
					
						
							|  |  |  | // highlight-end | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type App struct { | 
					
						
							|  |  |  |   ctx context.Context | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (a *App) WriteFile(b64 string, path string) { | 
					
						
							|  |  |  |   // highlight-start | 
					
						
							|  |  |  |   buf, _ := base64.StdEncoding.DecodeString(b64); | 
					
						
							|  |  |  |   _ = ioutil.WriteFile(path, buf, 0644); | 
					
						
							|  |  |  |   // highlight-end | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #### JS
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Wails will automatically create bindings for use in JS: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | import { utils, write } from 'xlsx'; | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | import { SaveFile, WriteFile } from '../wailsjs/go/main/App'; | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | async function exportFile(wb) { | 
					
						
							|  |  |  |   /* generate workbook */ | 
					
						
							|  |  |  |   const elt = tbl.getElementsByTagName("TABLE")[0]; | 
					
						
							|  |  |  |   const wb = utils.table_to_book(elt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* show save picker and get path */ | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  |   const path = await SaveFile(); | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* generate base64 string based on the path */ | 
					
						
							|  |  |  |   const b64 = write(wb, { bookType: path.slice(path.lastIndexOf(".")+1), type: "base64" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* write to file */ | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  |   await WriteFile(b64, path); | 
					
						
							| 
									
										
										
										
											2023-01-05 03:57:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2023-01-09 05:08:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## 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! |