docs.sheetjs.com/docz/docs/03-demos/06-desktop/03-wails.md
2023-04-27 05:12:19 -04:00

6.3 KiB

title pagination_prev pagination_next sidebar_position sidebar_custom_props
Wails demos/mobile/index demos/data/index 3
summary
Webview + Go Backend

import current from '/version.js'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';

The NodeJS Module can be imported from JavaScript code.

The "Complete Example" creates an app that looks like the screenshot:

Win10 macOS Linux

Win10 screenshot

macOS screenshot

Linux screenshot

Integration Details

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. 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. The demo works around the issue by showing pickers in Go code.

:::

Reading Files

The file picker and reading operations can be combined in one Go function.

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

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 bindings for use in JS:

import { read, utils } from 'xlsx';
import { ReadFile } from '../wailsjs/go/main/App';

async function importFile(evt) {
// highlight-start
  const b64 = await 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

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.

  • SaveFile will show the file picker and return the path:
import (
  "context"
// highlight-next-line
  "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:
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:

import { utils, write } from 'xlsx';
import { SaveFile, WriteFile } from '../wailsjs/go/main/App';

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 SaveFile();

  /* generate base64 string based on the path */
  const b64 = write(wb, { bookType: path.slice(path.lastIndexOf(".")+1), type: "base64" });

  /* write to file */
  await WriteFile(b64, path);
}

Complete Example

:::note

This demo was tested against Wails v2.4.0 on 2023 March 18 using the Svelte TypeScript starter.

:::

  1. Read Wails "Getting Started" guide and install dependencies.

  2. Create a new Wails app:

wails init -n sheetjs-wails -t svelte-ts
  1. Enter the directory:
cd sheetjs-wails
  1. Install front-end dependencies:
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 ..
  1. Download source files:
  • Download app.go and replace app.go
  • Download App.svelte and replace frontend/src/App.svelte
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
  1. Build the app with
wails build

At the end, it will print the path to the generated program. Run the program!