This commit is contained in:
SheetJS 2023-02-12 03:15:17 -05:00
parent 4a2314409e
commit 02c42e79a5
9 changed files with 142 additions and 115 deletions

@ -33,46 +33,6 @@ The "Complete Example" creates an app that looks like the screenshots below:
Electron presents a `fs` module. The `require('xlsx')` call loads the CommonJS
module, so `XLSX.readFile` and `XLSX.writeFile` work in the renderer thread.
### Writing Files
[`XLSX.writeFile`](/docs/api/write-options) writes workbooks to the file system.
`showSaveDialog` shows a Save As dialog and returns the selected file name:
```js
/* from the renderer thread */
const electron = require('@electron/remote');
/* this function will show the save dialog and try to write the workbook */
async function exportFile(workbook) {
/* show Save As dialog */
const result = await electron.dialog.showSaveDialog({
title: 'Save file as',
filters: [{
name: "Spreadsheets",
extensions: ["xlsx", "xls", "xlsb", /* ... other formats ... */]
}]
});
/* write file */
// highlight-next-line
XLSX.writeFile(workbook, result.filePath);
}
```
:::note
In older versions of Electron, `showSaveDialog` returned the path directly:
```js
var dialog = require('electron').remote.dialog;
function exportFile(workbook) {
var result = dialog.showSaveDialog();
XLSX.writeFile(workbook, result);
}
```
:::
### Reading Files
Electron offers 3 different ways to read files, two of which use Web APIs.
@ -171,6 +131,46 @@ function importFile(workbook) {
:::
### Writing Files
[`XLSX.writeFile`](/docs/api/write-options) writes workbooks to the file system.
`showSaveDialog` shows a Save As dialog and returns the selected file name:
```js
/* from the renderer thread */
const electron = require('@electron/remote');
/* this function will show the save dialog and try to write the workbook */
async function exportFile(workbook) {
/* show Save As dialog */
const result = await electron.dialog.showSaveDialog({
title: 'Save file as',
filters: [{
name: "Spreadsheets",
extensions: ["xlsx", "xls", "xlsb", /* ... other formats ... */]
}]
});
/* write file */
// highlight-next-line
XLSX.writeFile(workbook, result.filePath);
}
```
:::note
In older versions of Electron, `showSaveDialog` returned the path directly:
```js
var dialog = require('electron').remote.dialog;
function exportFile(workbook) {
var result = dialog.showSaveDialog();
XLSX.writeFile(workbook, result);
}
```
:::
## Complete Example
:::note

@ -13,8 +13,6 @@ import TabItem from '@theme/TabItem';
The [Standalone scripts](/docs/getting-started/installation/standalone) can be
referenced in a `SCRIPT` tag from the entry point HTML page.
This demo was tested against NW.js 0.66.0 on 2023 January 07.
The "Complete Example" creates an app that looks like the screenshots below:
<table><thead><tr>
@ -34,7 +32,7 @@ The "Complete Example" creates an app that looks like the screenshots below:
NW.js provides solutions for reading and writing files.
### Reading data
### Reading Files
The standard HTML5 `FileReader` techniques from the browser apply to NW.js!
@ -64,7 +62,7 @@ async function handleFile(e) {
document.getElementById("xlf").addEventListener("change", handleFile, false);
```
### Writing data
### Writing Files
File input elements with the attribute `nwsaveas` show UI for saving a file. The
standard trick is to generate a hidden file input DOM element and "click" it.
@ -102,6 +100,12 @@ input.click();
## Complete Example
:::note
This demo was tested against NW.js 0.66.0 on 2023 January 07.
:::
1) Create a `package.json` file that specifies the entry point:
```json title="package.json"

@ -28,7 +28,7 @@ The "Complete Example" creates an app that looks like the screenshot:
</td></tr></tbody></table>
## Native Modules
## Integration Details
All operations must be run from Go code. This example passes Base64 strings.
@ -225,9 +225,13 @@ async function exportFile(wb) {
## Complete Example
:::note
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:

@ -28,7 +28,7 @@ The "Complete Example" creates an app that looks like the screenshot:
</td></tr></tbody></table>
## Native Modules
## Integration Details
:::note
@ -123,7 +123,11 @@ async function saveFile(wb) {
## Complete Example
This demo was tested against Tauri `v1.2.3` on 2023 January 21.
:::note
This demo was tested against Tauri `v1.2.3` on 2023 February 12.
:::
0) [Read Tauri "Getting Started" guide and install dependencies.](https://tauri.app/v1/guides/getting-started/prerequisites)

@ -13,7 +13,22 @@ import TabItem from '@theme/TabItem';
The [Standalone build](/docs/getting-started/installation/standalone) can be added
to the entry `index.html`
This demo was tested against "binaries" `4.7.0` and "client" `3.6.0`
The "Complete Example" creates an app that looks like the screenshot:
<table><thead><tr>
<th><a href="#complete-example">macOS</a></th>
<th><a href="#complete-example">Linux</a></th>
</tr></thead><tbody><tr><td>
![macOS screenshot](pathname:///neu/macos.png)
</td><td>
![Linux screenshot](pathname:///neu/linux.png)
</td></tr></tbody></table>
## Integration Details
:::note
@ -35,10 +50,6 @@ The starter already enables `os` so typically one line must be added:
],
```
The "Complete Example" creates an app that looks like the screenshot:
![SheetJS NeutralinoJS MacOS screenshot](pathname:///neu/macos.png)
:::caution
At the time of writing, `filters` did not work as expected on MacOS. They have
@ -46,7 +57,67 @@ been omitted in the example and commented in the code snippets
:::
<details><summary><b>Complete Example</b> (click to show)</summary>
### Reading Files
There are two steps to reading files: obtaining a path and reading binary data:
```js
const filters = [
{name: "Excel Binary Workbook", extensions: ["xlsb"]},
{name: "Excel Workbook", extensions: ["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;
}
```
This method can be called from a button click or other event.
### Writing Files
There are two steps to writing files: obtaining a path and writing binary data:
```js
const filters = [
{name: "Excel Binary Workbook", extensions: ["xlsb"]},
{name: "Excel Workbook", extensions: ["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);
}
```
## Complete Example
:::note
This demo was tested on 2023 February 12 with "binaries" `4.7.0` and "client" `3.6.0`
:::
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.
@ -187,60 +258,3 @@ npx @neutralinojs/neu run
```
Platform-specific programs will be created in the `dist` folder.
</details>
### Reading Files
There are two steps to reading files: obtaining a path and reading binary data:
```js
const filters = [
{name: "Excel Binary Workbook", extensions: ["xlsb"]},
{name: "Excel Workbook", extensions: ["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;
}
```
This method can be called from a button click or other event.
### Writing Files
There are two steps to writing files: obtaining a path and writing binary data:
```js
const filters = [
{name: "Excel Binary Workbook", extensions: ["xlsb"]},
{name: "Excel Workbook", extensions: ["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);
}
```

BIN
docz/static/neu/linux.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

@ -75,9 +75,9 @@ try {
<img src="https://sheetjs.com/sketch128.png" class="logo" alt="SheetJS" />
SheetJS × Tauri {{ ver }}</a></h1>
<button type="button" @click="openFile()">Load Data</button> or
<button type="button" @click="saveFile()">Save Data</button>
<p><b>Data from {{ origin }}</b></p>
<div class="centre"><button type="button" @click="openFile()">Load Data</button> or
<button type="button" @click="saveFile()">Save Data</button></div>
<p class="centre"><b class="centre">Data from {{ origin }}</b></p>
<table class="center"><tbody>
<tr v-for="(row, index) in data" v-bind:key="index">
<td v-for="(cell, col) in row" v-bind:key="col">
@ -90,9 +90,9 @@ try {
<style scoped>
.logo {
padding: 0px;
height: 64px; width: 64px;
vertical-align: text-top;
will-change: filter;
vertical-align: middle;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
@ -100,6 +100,7 @@ try {
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
.centre { text-align: center; }
table.center {
margin-left: auto;
margin-right: auto;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 KiB

After

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

After

Width:  |  Height:  |  Size: 208 KiB