NeutralinoJS 中的数据修改
NeutralinoJS 是一个现代桌面应用框架。NeutralinoJS 应用将平台原生浏览器工具与静态 Web 服务器配对。
¥NeutralinoJS is a modern desktop app framework. NeutralinoJS apps pair platform-native browser tools with a static web server.
SheetJS 是一个用于从电子表格读取和写入数据的 JavaScript 库。
¥SheetJS is a JavaScript library for reading and writing data from spreadsheets.
该演示使用 NeutralinoJS 和 SheetJS 从电子表格中提取数据并在应用中显示数据。我们将探索如何在 NeutralinoJS 应用中加载 SheetJS 并使用原生功能来读取和写入文件。
¥This demo uses NeutralinoJS and SheetJS to pull data from a spreadsheet and display the data in the app. We'll explore how to load SheetJS in a NeutralinoJS app and use native features to read and write files.
"完整示例" 部分涵盖了用于读取和写入工作簿的完整桌面应用。该应用将如下图所示:
¥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 独立脚本 添加到 index.html
入口点。
¥The SheetJS Standalone scripts
can be added to the index.html
entry point.
对于在窗口中运行的代码,必须在 NeutralinoJS neutralino.conf.json
设置文件 [^1] 中显式启用原生方法。
¥For code running in the window, native methods must be explicitly enabled in the
NeutralinoJS neutralino.conf.json
settings file[^1].
-
os.*
启用打开和保存对话框方法。¥
os.*
enables the open and save dialog methods. -
filesystem.*
允许读取和写入文件数据。¥
filesystem.*
enables reading and writing file data.
入门应用启用 os.*
,因此通常必须添加一行:
¥The starter app enables os.*
so typically one line must be added:
"nativeAllowList": [
"app.*",
"os.*",
"filesystem.*",
"debug.log"
],
读取文件
¥Reading Files
读取文件分为三个步骤:
¥There are three steps to reading files:
-
显示带有
Neutralino.os.showOpenDialog
[^2] 的打开文件对话框。此方法解析为选定的路径。¥Show an open file dialog with
Neutralino.os.showOpenDialog
[^2]. This method resolves to the selected path. -
从带有
Neutralino.filesystem.readBinaryFile
[^3] 的文件中读取原始数据。此方法解析为标准ArrayBuffer
。¥Read raw data from the file with
Neutralino.filesystem.readBinaryFile
[^3]. This method resolves to a standardArrayBuffer
. -
使用 SheetJS
read
方法 [^4] 解析数据。此方法返回一个 SheetJS 工作簿对象。¥Parse the data with the SheetJS
read
method[^4]. This method returns a SheetJS workbook object.
以下代码示例定义了一个函数 openFile
,该函数执行所有三个步骤并返回 SheetJS 工作簿对象:
¥The following code example defines a single function openFile
that performs
all three steps and returns a SheetJS workbook object:
const filters = [
{name: "Excel Binary Workbook", extensions: ["xls", "xlsb"]},
{name: "Excel Workbook", extensions: ["xls", "xlsx"]},
]
async function openFile() {
/* show open file dialog */
const [filename] = await Neutralino.os.showOpenDialog(
'Open a spreadsheet',
{ filters, multiSelections: false }
);
/* read data into an ArrayBuffer */
const ab = await Neutralino.filesystem.readBinaryFile(filename);
/* parse with SheetJS */
const wb = XLSX.read(ab);
return wb;
}
此时,标准 SheetJS 实用函数 [^5] 可以从工作簿对象中提取数据。该演示包含一个调用 sheet_to_html
[^6] 的按钮来生成 HTML TABLE 并添加到 DOM:
¥At this point, standard SheetJS utility functions[^5] can extract data from the
workbook object. The demo includes a button that calls sheet_to_html
[^6] to
generate an HTML TABLE and add to the DOM:
const open_button_callback = async() => {
const wb = await openFile();
/* get the first worksheet */
const ws = wb.Sheets[wb.SheetNames[0]];
/* get data from the first worksheet */
const html = XLSX.utils.sheet_to_html(ws);
/* display table */
document.getElementById('info').innerHTML = html;
};
写入文件
¥Writing Files
读取文件分为三个步骤:
¥There are three steps to reading files:
-
显示带有
Neutralino.os.showSaveDialog
[^7] 的文件对话框。此方法解析为选定的路径。¥Show a file dialog with
Neutralino.os.showSaveDialog
[^7]. This method resolves to the selected path. -
使用 SheetJS
write
方法 [^8] 写入数据。可以从选定的文件路径推断输出的书籍类型。使用buffer
输出类型 [^9],该方法返回一个与 NeutralinoJS 配合良好的Uint8Array
对象。¥Write the data with the SheetJS
write
method[^8]. The output book type can be inferred from the selected file path. Using thebuffer
output type[^9], the method returns aUint8Array
object that plays nice with NeutralinoJS. -
用
Neutralino.filesystem.writeBinaryFile
[^10] 写入文件。¥Write to file with
Neutralino.filesystem.writeBinaryFile
[^10].
以下代码示例定义了一个函数 saveFile
,该函数从 SheetJS 工作簿对象开始执行所有三个步骤:
¥The following code example defines a single function saveFile
that performs
all three steps starting from a SheetJS workbook object:
const filters = [
{name: "Excel Binary Workbook", extensions: ["xls", "xlsb"]},
{name: "Excel Workbook", extensions: ["xls", "xlsx"]},
]
async function saveFile(wb) {
/* show save file dialog */
const filename = await Neutralino.os.showSaveDialog(
'Save to file',
{ filters }
);
/* Generate workbook */
const bookType = filename.slice(filename.lastIndexOf(".") + 1);
const data = XLSX.write(wb, { bookType, type: "buffer" });
/* save data to file */
await Neutralino.filesystem.writeBinaryFile(filename, data);
}
该演示包括一个调用 table_to_book
[^11] 从 HTML 表生成工作簿对象的按钮:
¥The demo includes a button that calls table_to_book
[^11] to generate a
workbook object from the HTML table:
const save_button_callback = async() => {
/* get the table */
const tbl = document.getElementById('info').querySelector('table');
/* generate workbook from the table */
const wb = XLSX.utils.table_to_book(tbl);
await saveFile(wb);
}
完整示例
¥Complete Example
本 demo 在以下环境下进行了测试:
¥This demo was tested in the following environments:
操作系统和版本 | 架构 | 服务器 | 客户 | 日期 |
---|---|---|---|---|
macOS 14.4 | darwin-x64 | 5.0.0 | 5.0.1 | 2024-03-15 |
macOS 14.5 | darwin-arm | 5.1.0 | 5.1.0 | 2024-05-25 |
Windows 10 | win10-x64 | 5.1.0 | 5.1.0 | 2024-03-24 |
视窗 11 | win11-arm | 5.1.0 | 5.1.1 | 2024-05-28 |
Linux(全息操作系统) | linux-x64 | 5.0.0 | 5.0.1 | 2024-03-21 |
Linux(Debian) | linux-arm | 5.1.0 | 5.1.1 | 2024-05-28 |
在 win11-arm
上,Electron 运行器是一个正确的 ARM64 二进制文件,但 Electron Forge 生成的二进制文件是 x64。x64 二进制文件在 ARM 上的 Windows 中运行。
¥On win11-arm
, the Electron runner is a proper ARM64 binary but the binaries
generated by Electron Forge are x64. The x64 binaries run in Windows on ARM.
应用核心状态将是 HTML 表。读取文件会将表格添加到窗口中。写入文件会将表格解析为电子表格。
¥The app core state will be the HTML table. Reading files will add the table to the window. Writing files will parse the table into a spreadsheet.
Installation Notes (click to show)
NeutralinoJS uses portable-file-dialogs
[^12] to show open and save dialogs. On
Linux, Zenity or KDialog are require.
The last Debian test was run on a system using LXDE. KDialog is supported but must be explicitly installed:
sudo apt-get install kdialog
NeutralinoJS requires libwekit2gtk
. On Arch Linux-based platforms including
the Steam Deck, webkit2gtk
can be installed through the package manager:
sudo pacman -Syu webkit2gtk
-
创建一个新的 NeutralinoJS 应用:
¥Create a new NeutralinoJS app:
npx @neutralinojs/neu create sheetjs-neu
cd sheetjs-neu
-
下载 SheetJS Standalone 脚本并移至
sheetjs-neu
文件夹中的resources/js/
子目录:¥Download the SheetJS Standalone script and move to the
resources/js/
subdirectory in thesheetjs-neu
folder:
curl -L -o resources/js/xlsx.full.min.js https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js
-
将高亮的行添加到
nativeAllowList
中的neutralino.config.json
:¥Add the highlighted line to
neutralino.config.json
innativeAllowList
:
"nativeAllowList": [
"app.*",
"os.*",
"filesystem.*",
"debug.log"
],
配置文件中可能有多个 nativeAllowList
块。该行必须添加到第一个块。
¥There may be multiple nativeAllowList
blocks in the configuration file. The
line must be added to the first block.
-
将
resources/index.html
的内容替换为以下代码:¥Replace the contents of
resources/index.html
with the following code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SheetJS + NeutralinoJS</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="neutralinoapp">
<h1>SheetJS × NeutralinoJS</h1>
<button onclick="importData()">Import Data</button>
<button onclick="exportData()">Export Data</button>
<div id="info"></div>
</div>
<script src="js/neutralino.js"></script>
<!-- Load the browser build and make XLSX available to main.js -->
<script src="js/xlsx.full.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>
-
将以下代码附加到
resources/styles.css
以使表格居中:¥Append the following code to
resources/styles.css
to center the table:
#info {
width:100%;
text-align: unset;
}
table {
margin: 0 auto;
}
-
在
resources/js/main.js
的showInfo
方法中打印版本号:¥Print the version number in the
showInfo
method ofresources/js/main.js
:
function showInfo() {
document.getElementById('info').innerHTML = `
${NL_APPID} is running on port ${NL_PORT} inside ${NL_OS}
<br/><br/>
<span>server: v${NL_VERSION} . client: v${NL_CVERSION}</span>
<br/><br/>
<span>SheetJS version ${XLSX.version}</span>
`;
}
-
运行应用:
¥Run the app:
npx @neutralinojs/neu run
The app should print SheetJS Version 0.20.3
-
在
resources/js/main.js
的底部添加以下代码:¥Add the following code to the bottom of
resources/js/main.js
:
(async() => {
const ab = await (await fetch("https://xlsx.nodejs.cn/pres.numbers")).arrayBuffer();
const wb = XLSX.read(ab);
const ws = wb.Sheets[wb.SheetNames[0]];
document.getElementById('info').innerHTML = XLSX.utils.sheet_to_html(ws);
})();
-
关闭应用。再次运行应用:
¥Close the app. Run the app again:
npx @neutralinojs/neu run
应用加载时,主屏幕中应显示一个表格。
¥When the app loads, a table should show in the main screen.
-
将
importFile
和exportFile
添加到resources/js/main.js
的底部:¥Add
importFile
andexportFile
to the bottom ofresources/js/main.js
:
async function importData() {
/* show open dialog */
const [filename] = await Neutralino.os.showOpenDialog('Open a spreadsheet');
/* read data */
const ab = await Neutralino.filesystem.readBinaryFile(filename);
const wb = XLSX.read(ab);
/* make table */
const ws = wb.Sheets[wb.SheetNames[0]];
document.getElementById('info').innerHTML = XLSX.utils.sheet_to_html(ws);
}
async function exportData() {
/* show save dialog */
const filename = await Neutralino.os.showSaveDialog('Save to file');
/* make workbook */
const tbl = document.getElementById('info').querySelector("table");
const wb = XLSX.utils.table_to_book(tbl);
/* make file */
const bookType = filename.slice(filename.lastIndexOf(".") + 1);
const data = XLSX.write(wb, { bookType, type: "buffer" });
await Neutralino.filesystem.writeBinaryFile(filename, data);
}
-
关闭应用。再次运行应用:
¥Close the app. Run the app again:
npx @neutralinojs/neu run
应用加载后,单击 "导入文件" 按钮并选择电子表格以查看内容。
¥When the app loads, click the "Import File" button and select a spreadsheet to see the contents.
如果没有显示对话框,请参阅 "安装注意事项" 了解更多详细信息。在 Linux ARM64 上,必须安装 KDialog 或 Zenity。
¥If no dialog is displayed, see the "Installation Notes" for more details. On Linux ARM64, KDialog or Zenity must be installed.
点击 "导出文件",输入 SheetJSNeu.xlsx
,写入新文件。
¥Click "Export File" and enter SheetJSNeu.xlsx
to write a new file.
保存文件时,必须包含实际的文件扩展名。尝试另存为 SheetJSNeu
不会自动添加 .xlsx
扩展名!
¥When saving the file, the actual file extension must be included. Attempting to
save as SheetJSNeu
will not automatically add the .xlsx
extension!
-
构建生产应用:
¥Build production apps:
npx @neutralinojs/neu build
将在 dist
文件夹中创建特定于平台的程序:
¥Platform-specific programs will be created in the dist
folder:
平台 | 二进制文件路径 |
---|---|
darwin-arm | ./dist/sheetjs-neu/sheetjs-neu-mac_arm64 |
win11-arm | .\dist\sheetjs-neu\sheetjs-neu-win_x64.exe |
linux-arm | .\dist\sheetjs-neu\sheetjs-neu-linux_arm64 |
运行生成的应用并确认显示总统数据。
¥Run the generated app and confirm that Presidential data is displayed.
[^1]: 请参阅 NeutralinoJS 文档中的 nativeAllowList
¥See nativeAllowList
in the NeutralinoJS documentation
[^2]: 请参阅 NeutralinoJS 文档中的 os.showOpenDialog
¥See os.showOpenDialog
in the NeutralinoJS documentation
[^3]: 请参阅 NeutralinoJS 文档中的 filesystem.readBinaryFile
¥See filesystem.readBinaryFile
in the NeutralinoJS documentation
[^4]: 见 read
于 "读取文件"
[^5]: 见 "实用函数"
¥See "Utility Functions"
[^6]: 见 "HTML 表格输出" 于 "实用函数"
¥See "HTML Table Output" in "Utility Functions"
[^7]: 请参阅 NeutralinoJS 文档中的 os.showSaveDialog
¥See os.showSaveDialog
in the NeutralinoJS documentation
[^8]: 见 write
于 "写入文件"
[^9]: 见 "支持的输出格式"
¥See "Supported Output Formats"
[^10]: 请参阅 NeutralinoJS 文档中的 filesystem.writeBinaryFile
¥See filesystem.writeBinaryFile
in the NeutralinoJS documentation
[^11]: 见 "HTML 表格输入" 于 "实用函数"
¥See "HTML Table Input" in "Utility Functions"
[^12]: 参见【支持的 portable-file-dialogs
列表】(https://github.com/samhocevar/portable-file-dialogs#status)
¥See [the list of supported portable-file-dialogs
]
(https://github.com/samhocevar/portable-file-dialogs#status)