This commit is contained in:
SheetJS 2023-04-08 04:42:15 -04:00
parent ef06aba826
commit 00d44fcfbb
4 changed files with 83 additions and 23 deletions

@ -10,10 +10,25 @@ sidebar_custom_props:
The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported
from the main entrypoint or any script in the project.
This demo will use the Quasar ViteJS starter project with VueJS and Cordova.
The "Complete Example" creates an app that looks like the screenshots below:
<table><thead><tr>
<th><a href="#demo">iOS</a></th>
<th><a href="#demo">Android</a></th>
</tr></thead><tbody><tr><td>
![iOS screenshot](pathname:///quasar/ios.png)
</td><td>
![Android screenshot](pathname:///quasar/and.png)
</td></tr></tbody></table>
### Integration Details
This demo will use the Quasar ViteJS starter project with VueJS and Cordova.
The complete solution uses `cordova-plugin-file` for file operations. It can
be installed like any other Cordova plugin:
@ -89,16 +104,18 @@ window.requestFileSystem(window.PERSISTENT, 0, function(fs) {
:::note
This demo was tested on an Intel Mac on 2022 August 14. Quasar version `2.7.7`.
The iOS simulator runs iOS 15.5 on an iPhone SE 3rd generation.
This demo was tested on an Intel Mac on 2023 April 08. `create-quasar@1.1.2`
was installed during app creation. The app used Quasar version `2.11.10`.
The iOS simulator runs iOS 16.2 on an iPhone 14 Pro Max.
The Android simulator runs Android 12.0 (S) API 31 on a Pixel 3.
:::
The demo draws from the ViteJS example. Familiarity with VueJS and TypeScript
is assumed.
<details><summary><b>Complete Example</b> (click to show)</summary>
0) Ensure all of the dependencies are installed. Install the CLI globally:
```bash
@ -189,28 +206,31 @@ then restart the development process.
:::
![Quasar Step 4](pathname:///mobile/quasar4.png)
5) Add the Dialog plugin to `quasar.config.js`:
```js title="quasar.config.js"
framework: {
config: {},
// ...
// Quasar plugins
// highlight-next-line
plugins: ['Dialog']
},
```
6) In the template section of `src/pages/IndexPage.vue`, add a Save button and
a Load file picker component at the bottom of the page:
6) In the template section of `src/pages/IndexPage.vue`, replace the example
with a Table, Save button and Load file picker component:
```html title="src/pages/IndexPage.vue"
<template>
<q-page class="row items-center justify-evenly">
<!-- highlight-start -->
<q-table :rows="todos" />
<q-btn-group>
<q-file label="Load File" filled label-color="orange" @input="updateFile"/>
<q-btn label="Save File" @click="saveFile" />
</q-btn-group>
<!-- highlight-end -->
</q-page>
<!-- highlight-end --> </q-page>
</template>
```
@ -223,7 +243,7 @@ This uses two functions that should be added to the component script:
// highlight-start
function saveFile() {
}
async function updateFile(v) {
async function updateFile(v: Event) {
}
return { todos, meta, saveFile, updateFile };
// highlight-end
@ -256,11 +276,11 @@ export default defineComponent({
// ...
// highlight-start
const $q = useQuasar();
function dialogerr(e) { $q.dialog({title: "Error!", message: e.message || String(e)}); }
function dialogerr(e: Error) { $q.dialog({title: "Error!", message: e.message || String(e)}); }
// highlight-end
function saveFile() {
}
async function updateFile(v) {
async function updateFile(v: Event) {
// highlight-start
try {
const files = (v.target as HTMLInputElement).files;
@ -268,7 +288,7 @@ export default defineComponent({
const wb = read(await files[0].arrayBuffer());
const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
const data = utils.sheet_to_json<any>(wb.Sheets[wb.SheetNames[0]]);
todos.value = data.map(row => ({id: row.Index, content: row.Name}));
} catch(e) { dialogerr(e); }
// highlight-end
@ -290,13 +310,11 @@ To test that reading works:
![Quasar Step 7 load file](pathname:///mobile/quasar7b.png)
Once selected, the screen should refresh with new contents:
![Quasar Step 7 new data](pathname:///mobile/quasar7c.png)
Once selected, the screen should refresh with new contents.
8) Wire up the `saveFile` function:
```js
```ts title="src/pages/IndexPage.vue"
function saveFile() {
// highlight-start
/* generate workbook from state */
@ -304,12 +322,13 @@ Once selected, the screen should refresh with new contents:
const wb = utils.book_new();
utils.book_append_sheet(wb, ws, "SheetJSQuasar");
const u8: Uint8Array = write(wb, {bookType: "xlsx", type: "buffer"});
const dir: string = $q.cordova.file.documentsDirectory || $q.cordova.file.externalApplicationStorageDirectory;
/* save to file */
window.requestFileSystem(window.PERSISTENT, 0, function(fs) {
try {
fs.root.getFile("SheetJSQuasar.xlsx", {create: true}, entry => {
const msg = `File stored at ${$q.cordova.file.documentsDirectory} ${entry.fullPath}`;
const msg = `File stored at ${dir} ${entry.fullPath}`;
entry.createWriter(writer => {
try {
const data = new Blob([u8], {type: "application/vnd.ms-excel"});
@ -377,5 +396,46 @@ id,content
46,Joseph Biden
```
</details>
**Android**
9) Create the Android project:
```bash
cd src-cordova
cordova platform add android
cd ..
```
10) Start the simulator:
```bash
quasar dev -m android
```
:::note
In local testing, the Quasar build process threw an error:
```
java.lang.IllegalArgumentException: Unsupported class file major version 63
```
This was resolved by rolling back to Java 1.8
:::
To test that reading works:
- Click and drag `pres.numbers` from a Finder window into the simulator.
- Tap "Load", tap the `≡` icon, tap "Downloads" and select `pres.numbers`.
To test that writing works:
- Tap "Save File". You will see a popup with a location.
- Pull the file from the simulator and verify the contents:
```bash
adb exec-out run-as org.sheetjs.quasar cat files/files/SheetJSQuasar.xlsx > /tmp/SheetJSQuasar.xlsx
npx xlsx-cli /tmp/SheetJSQuasar.xlsx
```

@ -107,7 +107,7 @@ this.file.writeFile(url, filename, blob, {replace: true});
This demo was tested on an Intel Mac on 2023 March 28 with Cordova.
The file integration uses `@ionic-native/file` version `5.36.0`.
The iOS simulator runs iOS 16.5 on an iPhone SE (3rd Generation).
The iOS simulator runs iOS 15.5 on an iPhone SE (3rd Generation).
The Android simulator runs Android 12.0 (S) API 31 on a Pixel 3.

BIN
docz/static/quasar/and.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
docz/static/quasar/ios.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB