电子表格驱动的 Wails 应用
Wails 是一个用于构建桌面应用的现代工具包。Wails 应用将 Go 驱动的后端与 JavaScript 驱动的前端配对 [^1]。
¥Wails is a modern toolkit for building desktop apps. Wails apps pair a Go-powered backend with a JavaScript-powered frontend[^1].
SheetJS 是一个用于从电子表格读取和写入数据的 JavaScript 库。
¥SheetJS is a JavaScript library for reading and writing data from spreadsheets.
该演示使用 Wails 和 SheetJS 从电子表格中提取数据并在应用中显示数据。我们将探讨如何在 Wails 应用中加载 SheetJS 并在 JavaScript 前端和 Go 后端之间交换文件数据。
¥This demo uses Wails and SheetJS to pull data from a spreadsheet and display the data in the app. We'll explore how to load SheetJS in a Wails app and exchange file data between the JavaScript frontend and Go backend.
"完整示例" 部分涵盖了用于读取和写入工作簿的完整桌面应用。该应用将如下图所示:
¥The "Complete Example" section covers a complete desktop app to read and write workbooks. The app will look like the screenshots below:
Windows | macOS | Linux |
---|---|---|
集成详情
¥Integration Details
SheetJS NodeJS 模块 可以安装在 frontend
文件夹中并在前端脚本中导入。
¥The SheetJS NodeJS Module can be
installed in the frontend
folder and imported in frontend scripts.
Wails 目前不提供相当于 NodeJS fs
的模块。
¥Wails currently does not provide the equivalent of NodeJS fs
module.
原始文件数据的读写必须用原生 Go 代码实现。
¥Reading and writing raw file data must be implemented in native Go code.
该演示包含用于显示对话框以及读写文件的原生 Go 代码。在 Go 和 JavaScript 代码之间发送数据时,原始文件被编码为 Base64 字符串。
¥This demo includes native Go code for showing dialogs and reading and writing files. When sending data between Go and JavaScript code, the raw files are encoded as Base64 strings.
读取文件
¥Reading Files
当用户点击 "导入文件" 按钮时,前端告诉 Go 后端读取数据。用户将看到一个文件选择器来选择要读取的文件。Go 后端将读取数据,编码为 Base64 字符串,并将结果发送到前端。
¥When the user clicks the "Import File" button, the frontend tells the Go backend to read data. The user will be presented with a file picker to select a file to read. The Go backend will read the data, encode as a Base64 string, and send the result to the frontend.
前端将使用 SheetJS read
方法 [^2] 解析数据,使用 sheet_to_html
[^3] 生成 HTML 表格,并将表格显示在前端。
¥The frontend will parse the data using the SheetJS read
method[^2], generate
HTML tables with sheet_to_html
[^3], and display the tables on the frontend.
下图总结了这些步骤:
¥The following diagram summarizes the steps:
Go
Wails 运行时提供跨平台 OpenFileDialog
函数 [^4] 来显示文件选择器。Go 标准库提供了从所选文件 [^5] 读取数据并编码为 Base64 字符串 [^6] 的方法
¥The Wails runtime provides the cross-platform OpenFileDialog
function[^4] to
show a file picker. The Go standard library provides methods for reading data
from the selected file[^5] and encoding in a Base64 string[^6]
import (
"context"
"encoding/base64"
"os"
"github.com/wailsapp/wails/v2/pkg/runtime"
)
type App struct {
ctx context.Context
}
// ReadFile shows an open file dialog and returns the data as Base64 string
func (a *App) ReadFile() string {
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
data, err := os.ReadFile(selection)
if err != nil { return "" } // The demo app shows an error message
return base64.StdEncoding.EncodeToString(data)
}
JS
Wails 会自动创建在 JS 中使用的绑定。App
绑定模块将导出函数 ReadFile
。
¥Wails will automatically create bindings for use in JS. The App
binding module
will export the function ReadFile
.
以下示例使用 SvelteJS 框架:
¥The following example uses the SvelteJS framework:
import { read, utils } from 'xlsx';
import { ReadFile } from '../wailsjs/go/main/App';
async function importFile(evt) {
/* call the native Go function and receive a base64 string */
const b64 = await ReadFile();
/* parse the base64 string with SheetJS */
const wb = read(b64, { type: "base64" });
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
return utils.sheet_to_html(ws); // generate HTML table
}
写入文件
¥Writing Files
SheetJS write
方法 [^7] 可以以多种格式 [^8] 编写电子表格,包括 XLSX、XLSB、XLS 和 NUMBERS。它需要 bookType
选项。这意味着前端在创建文件之前需要知道输出文件名。
¥The SheetJS write
method[^7] can write spreadsheets in a number of formats[^8]
including XLSX, XLSB, XLS, and NUMBERS. It expects a bookType
option. This
means the frontend needs to know the output file name before creating the file.
当用户单击 "导出文件" 按钮时,前端会向 Go 后端询问输出文件名和路径。用户将看到一个文件选择器来选择输出文件夹和工作簿类型。后端会将名称发送到前端。
¥When the user clicks the "Export File" button, the frontend asks the Go backend for the output filename and path. The user will be presented with a file picker to select the output folder and workbook type. The backend will send the name to the frontend.
前端将使用 SheetJS table_to_book
方法 [^9] 从表生成工作簿对象。SheetJS write
方法 [^10] 将从数据生成一个 Base64 字符串。
¥The frontend will generate a workbook object from the table using the SheetJS
table_to_book
method[^9]. The SheetJS write
method[^10] will generate a
Base64 string from the data.
前端将 Base64 字符串发送到后端。后端会将数据写入所选文件夹中的文件中。
¥The frontend will send the Base64 string to the backend. The backend will write the data to a file in the selected folder.
Go
将公开两个 Go 函数。
¥Two Go functions will be exposed.
-
SaveFile
将显示文件选择器并返回路径。它将使用跨平台SaveFileDialog
功能 [^11]。¥
SaveFile
will show the file picker and return the path. It will use the cross-platformSaveFileDialog
function[^11].
import (
"context"
"github.com/wailsapp/wails/v2/pkg/runtime"
)
type App struct {
ctx context.Context
}
func (a *App) SaveFile() string {
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
在给定 Base64 字符串和文件路径的情况下执行文件写入。Go 标准库提供了解码 Base64 字符串 [^12] 并将数据写入文件系统 [^13] 的方法¥
WriteFile
performs the file write given a Base64 string and file path. The Go standard library provides methods for decoding Base64 strings[^12] and writing data to the filesystem[^13]
import (
"context"
"encoding/base64"
"os"
)
type App struct {
ctx context.Context
}
func (a *App) WriteFile(b64 string, path string) {
buf, _ := base64.StdEncoding.DecodeString(b64);
_ = os.WriteFile(path, buf, 0644);
}
JS
Wails 会自动创建在 JS 中使用的绑定。App
绑定模块将导出函数 SaveFile
和 WriteFile
。
¥Wails will automatically create bindings for use in JS. The App
binding module
will export the functions SaveFile
and WriteFile
.
以下示例使用 SvelteJS 框架:
¥The following example uses the SvelteJS framework:
import { utils, write } from 'xlsx';
import { SaveFile, WriteFile } from '../wailsjs/go/main/App';
async function exportFile(table_element) {
/* generate workbook */
const wb = utils.table_to_book(table_element);
/* show save picker and get path */
const path = await SaveFile();
/* get the file extension -> bookType */
const bookType = path.slice(path.lastIndexOf(".")+1);
/* generate base64 string */
const b64 = write(wb, { bookType: bookType, type: "base64" });
/* write to file */
await WriteFile(b64, path);
}
完整示例
¥Complete Example
本 demo 在以下环境下进行了测试:
¥This demo was tested in the following environments:
操作系统和版本 | 架构 | Wails | 日期 |
---|---|---|---|
macOS 14.4 | darwin-x64 | v2.8.0 | 2024-03-15 |
macOS 14.5 | darwin-arm | v2.8.2 | 2024-05-28 |
Windows 10 | win10-x64 | v2.8.0 | 2024-03-24 |
视窗 11 | win11-arm | v2.8.2 | 2024-05-28 |
Linux(全息操作系统) | linux-x64 | v2.8.0 | 2024-03-21 |
Linux(Debian) | linux-arm | v2.8.2 | 2024-05-28 |
-
阅读 Wails "入门" 指南 [^14] 并安装依赖。
¥Read the Wails "Getting Started" guide[^14] and install dependencies.
Installation Notes (click to show)
Wails will require:
After installing both, run the following command to install Wails:
go install github.com/wailsapp/wails/v2/cmd/wails@latest
Once that finishes, run the following command in a new terminal window:
wails doctor
On macOS and Linux, the PATH
environment variable must include ~/go/bin
. If
wails
cannot be found, run the following command in the terminal session:
export PATH="$PATH":~/go/bin
The output will include a # Diagnosis
section. It should display:
SUCCESS Your system is ready for Wails development!
If a required dependency is missing, it will be displayed.
None of the optional packages are required for building and running this demo.
On the Steam Deck (HoloOS), some dependencies must be reinstalled:
sudo pacman -Syu base-devel gtk3 glib2 pango harfbuzz cairo gdk-pixbuf2 atk libsoup
-
创建一个新的 Wails 应用:
¥Create a new Wails app:
wails init -n sheetjs-wails -t svelte-ts
cd sheetjs-wails
-
安装前端依赖:
¥Install front-end dependencies:
cd frontend
curl -o src/assets/logo.png https://sheetjs.com/sketch1024.png
npm i --save https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz
cd ..
-
下载源文件:
¥Download source files:
-
下载
app.go
并替换app.go
¥Download
app.go
and replaceapp.go
-
下载
App.svelte
并替换frontend/src/App.svelte
¥Download
App.svelte
and replacefrontend/src/App.svelte
curl -o app.go https://xlsx.nodejs.cn/wails/app.go
curl -o frontend/src/App.svelte https://xlsx.nodejs.cn/wails/App.svelte
-
构建应用:
¥Build the app:
wails build
它将打印生成的程序的路径(通常在 build/bin/
中)。
¥It will print the path to the generated program (typically in build/bin/
).
-
运行生成的应用。
¥Run the generated application.
测试
¥Testing
该程序将下载 pres.xlsx
并在表格中显示第一个工作表的内容。
¥The program will download pres.xlsx
and
display the contents of the first worksheet in a table.
要测试导出功能,请单击 "导出 XLSX"。该应用将询问文件名和位置。单击“保存”后,应用将导出到 XLSX。该文件可以在电子表格编辑器(例如 Excel)中打开。
¥To test export features, click "Export XLSX". The app will ask for a file name and location. After clicking Save, the app will export to XLSX. This file can be opened in a spreadsheet editor such as Excel.
[^1]: 请参阅 Wails 文档中的 "它是如何工作的?"。
¥See "How does it Work?" in the Wails documentation.
[^2]: 见 read
于 "读取文件"
[^3]: 见 sheet_to_html
于 "实用工具"
¥See sheet_to_html
in "Utilities"
[^4]: 请参阅 Wails 文档中的 OpenFileDialog
。
¥See OpenFileDialog
in the Wails documentation.
[^5]: 请参阅 Go 文档中的 ReadFile
¥See ReadFile
in the Go documentation
[^6]: 请参阅 Go 文档中的 EncodeToString
¥See EncodeToString
in the Go documentation
[^7]: 见 write
于 "写入文件"
[^8]: 见 "写入文件" 中的 "支持的输出格式" 类型
¥See "Supported Output Formats" type in "Writing Files"
[^9]: 见 "HTML 表格输入" 于 "实用工具"
¥See "HTML Table Input" in "Utilities"
[^10]: 见 write
于 "写入文件"
[^11]: 请参阅 Wails 文档中的 SaveFileDialog
。
¥See SaveFileDialog
in the Wails documentation.
[^12]: 请参阅 Go 文档中的 DecodeString
¥See DecodeString
in the Go documentation
[^13]: 请参阅 Go 文档中的 WriteFile
¥See WriteFile
in the Go documentation
[^14]: 请参阅 Wails 文档中的 "安装"。
¥See "Installation" in the Wails documentation.