forked from sheetjs/docs.sheetjs.com
222 lines
5.1 KiB
Markdown
222 lines
5.1 KiB
Markdown
|
---
|
||
|
title: Wails
|
||
|
pagination_prev: demos/mobile
|
||
|
pagination_next: demos/grid
|
||
|
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.
|
||
|
|
||
|
This demo was tested against Wails `v2.0.0-beta.44.2` on 2022 August 31 using
|
||
|
the Svelte TypeScript starter.
|
||
|
|
||
|
:::caution
|
||
|
|
||
|
Wails currently does not provide the equivalent of NodeJS `fs` module.
|
||
|
|
||
|
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 "Complete Example" creates an app that looks like the screenshot:
|
||
|
|
||
|
![SheetJS Wails MacOS screenshot](pathname:///wails/macos.png)
|
||
|
|
||
|
<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.
|
||
|
|
||
|
#### 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
|
||
|
|
||
|
Wails will automatically create `window.go.main.App.ReadFile` for use in JS:
|
||
|
|
||
|
```js title="frontend/src/App.svelte"
|
||
|
import { read, utils } from 'xlsx';
|
||
|
|
||
|
async function importFile(evt) {
|
||
|
// highlight-start
|
||
|
const b64 = window['go']['main']['App']['ReadFile']();
|
||
|
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
|
||
|
|
||
|
##### Go
|
||
|
|
||
|
Two Go functions will be exposed.
|
||
|
|
||
|
- `SaveFile` will show the file picker and return the path:
|
||
|
|
||
|
```go
|
||
|
import (
|
||
|
"context"
|
||
|
// highlight-start
|
||
|
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||
|
// highlight-end
|
||
|
)
|
||
|
|
||
|
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';
|
||
|
|
||
|
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 */
|
||
|
const path = await window['go']['main']['App']['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
|
||
|
}
|
||
|
```
|