Demo refresh
This commit is contained in:
parent
467af52e4f
commit
d953a625a2
@ -302,7 +302,7 @@
|
||||
<Cell><Data ss:Type="String">Rust</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
|
||||
|
@ -99,7 +99,7 @@
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"> </Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
|
||||
<Cell ss:StyleID="s16"><Data ss:Type="String"> </Data></Cell>
|
||||
</Row>
|
||||
|
@ -123,7 +123,7 @@ This demo was last tested in the following deployments:
|
||||
|:-------------|:---------|:-----------|
|
||||
| `darwin-x64` | `1.2.8` | 2025-03-31 |
|
||||
| `darwin-arm` | `1.2.7` | 2025-03-30 |
|
||||
| `win11-x64` | `1.1.42` | 2024-12-22 |
|
||||
| `win11-x64` | `1.2.8` | 2025-04-17 |
|
||||
| `win11-arm` | `1.2.3` | 2025-02-23 |
|
||||
| `linux-x64` | `1.1.40` | 2024-12-19 |
|
||||
| `linux-arm` | `1.2.2` | 2025-02-16 |
|
||||
|
@ -35,7 +35,7 @@ This demo was tested in the following configurations:
|
||||
|
||||
| Platform | Architecture | Date |
|
||||
|:------------------------------------------------------------------|:-------------|:-----------|
|
||||
| NVIDIA RTX 4090 (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2025-03-06 |
|
||||
| NVIDIA RTX 4090 (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2025-04-17 |
|
||||
| NVIDIA RTX 4090 (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-01-28 |
|
||||
| AMD RX 7900 XTX (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2025-01-12 |
|
||||
| AMD RX 7900 XTX (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-01-29 |
|
||||
@ -853,7 +853,7 @@ npm i --save https://sheet.lol/balls/xlsx-${current}.tgz`}
|
||||
4) Install dependencies:
|
||||
|
||||
```bash
|
||||
npm i --save @langchain/core@0.3.42 langchain@0.3.19 @langchain/ollama@0.2.0 peggy@3.0.2
|
||||
npm i --save @langchain/core@0.3.44 langchain@0.3.21 @langchain/ollama@0.2.0 peggy@3.0.2
|
||||
```
|
||||
|
||||
:::note pass
|
||||
@ -862,7 +862,7 @@ In some test runs, there were error messages relating to dependency and peer
|
||||
dependency versions. The `--force` flag will suppress version mismatch errors:
|
||||
|
||||
```bash
|
||||
npm i --save @langchain/core@0.3.42 langchain@0.3.19 @langchain/ollama@0.2.0 peggy@3.0.2 --force
|
||||
npm i --save @langchain/core@0.3.44 langchain@0.3.21 @langchain/ollama@0.2.0 peggy@3.0.2 --force
|
||||
```
|
||||
|
||||
:::
|
||||
|
@ -295,7 +295,9 @@ This demo was tested in the following deployments:
|
||||
|
||||
| Architecture | Date |
|
||||
|:-------------|:-----------|
|
||||
| `darwin-x64` | 2025-04-17 |
|
||||
| `darwin-arm` | 2024-10-15 |
|
||||
| `win11-x64` | 2025-04-17 |
|
||||
|
||||
:::
|
||||
|
||||
|
@ -127,11 +127,14 @@ That approach is not explored in this demo.
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| NodeJS | Date | Dependencies |
|
||||
|:----------|:-----------|:------------------------------------|
|
||||
| `18.20.3` | 2024-06-30 | ExpressJS 4.19.2 + Formidable 2.1.2 |
|
||||
| `20.15.0` | 2024-06-30 | ExpressJS 4.19.2 + Formidable 2.1.2 |
|
||||
| `22.3.0` | 2024-06-30 | ExpressJS 4.19.2 + Formidable 2.1.2 |
|
||||
| NodeJS | Date | ExpressJS |
|
||||
|:----------|:-----------|:----------|
|
||||
| `18.20.8` | 2025-04-17 | `5.1.0` |
|
||||
| `20.18.0` | 2025-04-17 | `5.1.0` |
|
||||
| `22.14.0` | 2025-04-17 | `5.1.0` |
|
||||
| `18.20.8` | 2025-04-17 | `4.21.2` |
|
||||
| `20.18.0` | 2025-04-17 | `4.21.2` |
|
||||
| `22.14.0` | 2025-04-17 | `4.21.2` |
|
||||
|
||||
:::
|
||||
|
||||
|
@ -49,10 +49,11 @@ flowchart LR
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| SvelteJS | Kit | Date |
|
||||
|:-----------------|:---------|:-----------|
|
||||
| `4.2.17` | `2.5.10` | 2024-06-03 |
|
||||
| `5.0.0-next.149` | `2.5.10` | 2024-06-03 |
|
||||
| SvelteJS | Kit | Date |
|
||||
|:----------|:---------|:-----------|
|
||||
| `5.27.2` | `2.20.7` | 2025-04-17 |
|
||||
| `4.2.19` | `2.5.10` | 2025-04-17 |
|
||||
| `3.59.2` | `1.30.4` | 2025-04-17 |
|
||||
|
||||
:::
|
||||
|
||||
@ -189,7 +190,35 @@ When this demo was last tested, SvelteKit required NodeJS major version 20.
|
||||
1) Create a new site:
|
||||
|
||||
```bash
|
||||
npm create svelte@latest sheetjs-svelte
|
||||
mkdir -p sheetjs-svelte
|
||||
cd sheetjs-svelte
|
||||
npx sv create
|
||||
```
|
||||
|
||||
When prompted:
|
||||
|
||||
- `Where would you like your project to be created?`: press <kbd>Enter</kbd>
|
||||
- `Which template would you like?` select `SvelteKit minimal`
|
||||
- `Add type checking with TypeScript?` select `Yes, using JavaScript with JSDoc`
|
||||
- `What would you like to add to your project?` press <kbd>Enter</kbd> (do not select options)
|
||||
- `Which package manager do you want to install dependencies with?`: select `npm` and press <kbd>Enter</kbd>
|
||||
|
||||
<details>
|
||||
<summary><b>Older SvelteJS versions</b> (click to show)</summary>
|
||||
|
||||
The following commands create SvelteJS projects for older versions:
|
||||
|
||||
**SvelteJS 3.x**
|
||||
|
||||
```bash
|
||||
npm create svelte@4 sheetjs-svelte
|
||||
```
|
||||
|
||||
|
||||
**SvelteJS 4.x**
|
||||
|
||||
```bash
|
||||
npm create svelte@6 sheetjs-svelte
|
||||
```
|
||||
|
||||
When prompted:
|
||||
@ -198,19 +227,21 @@ When prompted:
|
||||
- `Add type checking with TypeScript?` select `Yes, using JavaScript with JSDoc`
|
||||
- `Select additional options` press <kbd>Enter</kbd> (do not select options)
|
||||
|
||||
:::note pass
|
||||
|
||||
To test the Svelte 5 beta, select `Try the Svelte 5 preview (unstable!)`
|
||||
|
||||
:::
|
||||
|
||||
2) Enter the project folder and install dependencies:
|
||||
After creating the project, enter the project folder and install dependencies:
|
||||
|
||||
```bash
|
||||
cd sheetjs-svelte
|
||||
npm i
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
2) Install dependencies:
|
||||
|
||||
```bash
|
||||
npm i
|
||||
```
|
||||
|
||||
3) Fetch the example file [`pres.xlsx`](https://docs.sheetjs.com/pres.xlsx) and
|
||||
move to a `data` subdirectory in the root of the project:
|
||||
|
||||
@ -311,6 +342,14 @@ observe that the data from the spreadsheet is displayed in the page.
|
||||
11) In the spreadsheet, set cell A7 to `SheetJS Dev` and cell B7 to `47`. Save
|
||||
the file. After saving, the browser should automatically refresh with new data.
|
||||
|
||||
:::caution pass
|
||||
|
||||
**Live reloading may not work in newer projects!**
|
||||
|
||||
If the page does not reload, manually refresh the page.
|
||||
|
||||
:::
|
||||
|
||||
### Static Site
|
||||
|
||||
12) Stop the development server and install the static adapter:
|
||||
|
@ -45,16 +45,16 @@ This demo was tested in the following environments:
|
||||
|
||||
| OS | Device | Quasar | Date |
|
||||
|:-----------|:--------------------|:---------|:-----------|
|
||||
| Android 30 | NVIDIA Shield | `2.16.4` | 2024-06-09 |
|
||||
| iOS 15.1 | iPad Pro | `2.16.4` | 2024-06-09 |
|
||||
| Android 34 | NVIDIA Shield | `2.18.1` | 2025-04-17 |
|
||||
| iOS 15.1 | iPad Pro | `2.18.1` | 2025-04-17 |
|
||||
|
||||
**Simulators**
|
||||
|
||||
| OS | Device | Quasar | Dev Platform | Date |
|
||||
|:-----------|:--------------------|:---------|:-------------|:-----------|
|
||||
| Android 34 | Pixel 3a | `2.16.4` | `darwin-arm` | 2024-06-09 |
|
||||
| iOS 17.5 | iPhone SE (3rd gen) | `2.16.4` | `darwin-arm` | 2024-06-09 |
|
||||
| Android 35 | Pixel 3a | `2.16.9` | `win11-x64` | 2024-08-20 |
|
||||
| Android 35 | Pixel 9 Pro XL | `2.18.1` | `darwin-arm` | 2025-04-17 |
|
||||
| iOS 18.2 | iPhone 16 Pro Max | `2.18.1` | `darwin-arm` | 2025-04-17 |
|
||||
| Android 36 | Pixel 9 Pro XL | `2.18.1` | `win11-x64` | 2025-04-17 |
|
||||
|
||||
:::
|
||||
|
||||
@ -167,13 +167,23 @@ window.requestFileSystem(window.PERSISTENT, 0, function(fs) {
|
||||
The demo draws from the ViteJS example. Familiarity with VueJS and TypeScript
|
||||
is assumed.
|
||||
|
||||
### Platform Setup
|
||||
|
||||
0) Ensure all of the dependencies are installed. Install the CLI globally:
|
||||
|
||||
```bash
|
||||
npm i -g @quasar/cli cordova
|
||||
```
|
||||
|
||||
(you may need to run `sudo npm i -g` if there are permission issues)
|
||||
:::note pass
|
||||
|
||||
In some systems, the command must be run as the root user:
|
||||
|
||||
```bash
|
||||
sudo npm i -g @quasar/cli cordova
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
<details>
|
||||
<summary><b>Installation Notes</b> (click to show)</summary>
|
||||
@ -182,6 +192,8 @@ Quasar requires Java 17
|
||||
|
||||
</details>
|
||||
|
||||
### Base Project
|
||||
|
||||
1) Create a new app:
|
||||
|
||||
```bash
|
||||
@ -194,14 +206,12 @@ When prompted:
|
||||
|
||||
- "What would you like to build?": `App with Quasar CLI, let's go!`
|
||||
- "Project folder": `SheetJSQuasar`
|
||||
- "Pick Quasar version": `Quasar v2 (Vue 3 | latest and greatest)`
|
||||
- "Pick script type": `Typescript`
|
||||
- "Pick Quasar App CLI variant": `Quasar App CLI with Vite 2 (stable | v1)`
|
||||
- "Pick Quasar App CLI variant": `Quasar App CLI with Vite`
|
||||
- "Package name": (press <kbd>Enter</kbd>, it will use the default `sheetjsquasar`)
|
||||
- "Project product name": `SheetJSQuasar`
|
||||
- "Project description": `SheetJS + Quasar`
|
||||
- "Author": (press <kbd>Enter</kbd>, it will use Git settings)
|
||||
- "Pick a Vue component style": `Composition API`
|
||||
- "Pick a Vue component style": `Composition API with <script setup>`
|
||||
- "Pick your CSS preprocessor": `None`
|
||||
- "Check the features needed for your project": Deselect everything (scroll down to each selected item and press <kbd>Space</kbd>)
|
||||
- "Install project dependencies": `Yes, use npm`
|
||||
@ -221,17 +231,96 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
|
||||
```bash
|
||||
npx cordova telemetry off
|
||||
npx quasar mode add cordova
|
||||
npx quasar mode remove capacitor
|
||||
```
|
||||
|
||||
When prompted, enter the app id `org.sheetjs.quasar`.
|
||||
|
||||
It will create a new `src-cordova` folder. Continue in that folder:
|
||||
4) Add the Dialog plugin to the `plugins` array in `quasar.config.ts`:
|
||||
|
||||
```js title="quasar.config.ts (edit highlighted line)"
|
||||
// Quasar plugins
|
||||
// highlight-next-line
|
||||
plugins: ['Dialog']
|
||||
```
|
||||
|
||||
5) Download [`IndexPage.vue`](pathname:///quasar/IndexPage.vue) and replace the
|
||||
existing page script `src/pages/IndexPage.vue`:
|
||||
|
||||
```bash
|
||||
curl -L -o src/pages/IndexPage.vue https://docs.sheetjs.com/quasar/IndexPage.vue
|
||||
```
|
||||
|
||||
### Android
|
||||
|
||||
6) Create the Android project:
|
||||
|
||||
```bash
|
||||
cd src-cordova
|
||||
npx cordova platform add android
|
||||
npx cordova plugin add cordova-plugin-wkwebview-engine
|
||||
npx cordova plugin add cordova-plugin-file
|
||||
cd ..
|
||||
```
|
||||
|
||||
7) Start the simulator:
|
||||
|
||||
```bash
|
||||
npx quasar dev -m cordova -T android
|
||||
```
|
||||
|
||||
If prompted to select an external IP, press <kbd>Enter</kbd>.
|
||||
|
||||
:::caution pass
|
||||
|
||||
If the app is blank or not refreshing, delete the app and close the simulator,
|
||||
then restart the development process.
|
||||
|
||||
:::
|
||||
|
||||
:::info pass
|
||||
|
||||
In some test runs, the command failed with a Gradle error
|
||||
|
||||
```
|
||||
Could not find an installed version of Gradle either in Android Studio,
|
||||
or on your system to install the gradle wrapper. Please include gradle
|
||||
in your path, or install Android Studio
|
||||
```
|
||||
|
||||
[Gradle](https://gradle.org/) (the complete version) must be extracted and the
|
||||
`bin` folder must be added to the user PATH variable. After adding to PATH,
|
||||
launch a new PowerShell or Command Prompt window and run the command.
|
||||
|
||||
:::
|
||||
|
||||
To test that reading works:
|
||||
|
||||
- Download https://docs.sheetjs.com/pres.numbers
|
||||
- Open the Downloads folder in Finder or Explorer
|
||||
- Click and drag `pres.numbers` from the window into the simulator.
|
||||
- Tap "Load File", 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
|
||||
```
|
||||
|
||||
### iOS
|
||||
|
||||
8) Create the iOS project:
|
||||
|
||||
```bash
|
||||
cd src-cordova
|
||||
npx cordova platform add ios
|
||||
npx cordova plugin add cordova-plugin-wkwebview-engine
|
||||
npx cordova plugin add cordova-plugin-file
|
||||
cd ..
|
||||
```
|
||||
|
||||
:::note pass
|
||||
@ -246,13 +335,7 @@ npx cordova plugin add cordova-plugin-file
|
||||
|
||||
:::
|
||||
|
||||
Return to the project directory:
|
||||
|
||||
```bash
|
||||
cd ..
|
||||
```
|
||||
|
||||
4) Enable file sharing and make the documents folder visible in the iOS app.
|
||||
9) Enable file sharing and make the documents folder visible in the iOS app.
|
||||
The following lines must be added to `src-cordova/platforms/ios/SheetJSQuasar/SheetJSQuasar-Info.plist`:
|
||||
|
||||
```xml title="src-cordova/platforms/ios/SheetJSQuasar/SheetJSQuasar-Info.plist (add to file)"
|
||||
@ -270,10 +353,10 @@ The following lines must be added to `src-cordova/platforms/ios/SheetJSQuasar/Sh
|
||||
(The root element of the document is `plist` and it contains one `dict` child)
|
||||
|
||||
|
||||
5) Start the development server:
|
||||
10) Start the development server:
|
||||
|
||||
```bash
|
||||
npx quasar dev -m ios
|
||||
npx quasar dev -m cordova -T ios
|
||||
```
|
||||
|
||||
If prompted to select an external IP, press <kbd>Enter</kbd>.
|
||||
@ -285,52 +368,6 @@ then restart the development process.
|
||||
|
||||
:::
|
||||
|
||||
6) Add the Dialog plugin to `quasar.config.js`:
|
||||
|
||||
```js title="quasar.config.js (add highlighted line)"
|
||||
framework: {
|
||||
config: {},
|
||||
// ...
|
||||
// Quasar plugins
|
||||
// highlight-next-line
|
||||
plugins: ['Dialog']
|
||||
},
|
||||
```
|
||||
|
||||
7) 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 (change highlighted lines)"
|
||||
<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>
|
||||
</template>
|
||||
```
|
||||
|
||||
This uses two functions that should be added to the component script:
|
||||
|
||||
```ts title="src/pages/IndexPage.vue (add highlighted lines)"
|
||||
const meta = ref<Meta>({
|
||||
totalCount: 1200
|
||||
});
|
||||
// highlight-start
|
||||
function saveFile() {
|
||||
}
|
||||
async function updateFile(v: Event) {
|
||||
}
|
||||
return { todos, meta, saveFile, updateFile };
|
||||
// highlight-end
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
The app should now show two buttons at the bottom:
|
||||
|
||||

|
||||
@ -342,38 +379,6 @@ then restart the development process.
|
||||
|
||||
:::
|
||||
|
||||
8) Wire up the `updateFile` function:
|
||||
|
||||
```ts title="src/pages/IndexPage.vue (add highlighted lines)"
|
||||
import { defineComponent, ref } from 'vue';
|
||||
// highlight-start
|
||||
import { read, write, utils } from 'xlsx';
|
||||
import { useQuasar } from 'quasar';
|
||||
// highlight-end
|
||||
|
||||
export default defineComponent({
|
||||
// ...
|
||||
// highlight-start
|
||||
const $q = useQuasar();
|
||||
function dialogerr(e: Error) { $q.dialog({title: "Error!", message: e.message || String(e)}); }
|
||||
// highlight-end
|
||||
function saveFile() {
|
||||
}
|
||||
async function updateFile(v: Event) {
|
||||
// highlight-start
|
||||
try {
|
||||
const files = (v.target as HTMLInputElement).files;
|
||||
if(!files || files.length == 0) return;
|
||||
|
||||
const wb = read(await files[0].arrayBuffer());
|
||||
|
||||
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
|
||||
}
|
||||
```
|
||||
|
||||
To test that reading works:
|
||||
|
||||
- Download https://docs.sheetjs.com/pres.numbers
|
||||
@ -391,46 +396,11 @@ To test that reading works:
|
||||
|
||||
Once selected, the screen should refresh with new contents.
|
||||
|
||||
9) Wire up the `saveFile` function:
|
||||
|
||||
```ts title="src/pages/IndexPage.vue (add highlighted lines)"
|
||||
function saveFile() {
|
||||
// highlight-start
|
||||
/* generate workbook from state */
|
||||
const ws = utils.json_to_sheet(todos.value);
|
||||
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 ${dir} ${entry.fullPath}`;
|
||||
entry.createWriter(writer => {
|
||||
try {
|
||||
const data = new Blob([u8], {type: "application/vnd.ms-excel"});
|
||||
writer.onwriteend = () => {
|
||||
try {
|
||||
$q.dialog({title: "Success!", message: msg});
|
||||
} catch(e) { dialogerr(e); }
|
||||
};
|
||||
writer.onerror = dialogerr;
|
||||
writer.write(data);
|
||||
} catch(e) { dialogerr(e); }
|
||||
}, dialogerr);
|
||||
}, dialogerr);
|
||||
} catch(e) { dialogerr(e) }
|
||||
}, dialogerr);
|
||||
// highlight-end
|
||||
}
|
||||
```
|
||||
|
||||
The page should revert to the old contents.
|
||||
|
||||
To test that writing works:
|
||||
|
||||
- Close the app in the simulator and re-launch the app.
|
||||
|
||||
- Click "Save File". You will see a popup with a location:
|
||||
|
||||

|
||||
@ -475,121 +445,23 @@ id,content
|
||||
46,Joseph Biden
|
||||
```
|
||||
|
||||
**Android**
|
||||
### Android Device
|
||||
|
||||
10) Create the Android project:
|
||||
11) Close all open emulators and simulators.
|
||||
|
||||
12) Disconnect any iOS or Android devices connected to the computer.
|
||||
|
||||
13) Connect the Android device to the computer.
|
||||
|
||||
14) Start the dev process:
|
||||
|
||||
```bash
|
||||
cd src-cordova
|
||||
cordova platform add android
|
||||
cd ..
|
||||
```
|
||||
|
||||
11) Start the simulator:
|
||||
|
||||
```bash
|
||||
quasar dev -m android
|
||||
npx quasar dev -m cordova -T android
|
||||
```
|
||||
|
||||
If prompted to select an external IP, press <kbd>Enter</kbd>.
|
||||
|
||||
:::caution pass
|
||||
|
||||
If the app is blank or not refreshing, delete the app and close the simulator,
|
||||
then restart the development process.
|
||||
|
||||
:::
|
||||
|
||||
:::warning pass
|
||||
|
||||
On Windows, the command failed with a Gradle error
|
||||
|
||||
```
|
||||
Could not find an installed version of Gradle either in Android Studio,
|
||||
or on your system to install the gradle wrapper. Please include gradle
|
||||
in your path, or install Android Studio
|
||||
```
|
||||
|
||||
[Gradle](https://gradle.org/) (the complete version) must be extracted and the
|
||||
`bin` folder must be added to the user PATH variable. After adding to PATH,
|
||||
launch a new PowerShell or Command Prompt window and run the command.
|
||||
|
||||
:::
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
**iOS Device**
|
||||
|
||||
12) Close all open emulators and simulators.
|
||||
|
||||
13) Disconnect any iOS or Android devices connected to the computer.
|
||||
|
||||
14) Connect the iOS device to the computer.
|
||||
|
||||
15) Open the Xcode project:
|
||||
|
||||
```bash
|
||||
open src-cordova/platforms/ios/SheetJSQuasar.xcodeproj
|
||||
```
|
||||
|
||||
Select "SheetJSQuasar" in the Navigator. In the main pane, select "Signing &
|
||||
Capabilities" and ensure a Team is selected. Save and close the project.
|
||||
|
||||
16) Start the dev process:
|
||||
|
||||
```bash
|
||||
quasar dev -m ios
|
||||
```
|
||||
|
||||
If prompted to select an external IP, press <kbd>Enter</kbd>.
|
||||
|
||||
17) Test the application:
|
||||
|
||||
- Press the Home button (or swipe up with one finger) and switch to Safari.
|
||||
- Download https://docs.sheetjs.com/pres.numbers
|
||||
- Press the Home button (or swipe up with one finger) and select the `SheetJSQuasar` app
|
||||
- Tap the "Load" button, then select "Choose File" and select the downloaded `pres.numbers`
|
||||
|
||||
The table will update with new data.
|
||||
|
||||
- Tap "Save File"
|
||||
- Press the Home button (or swipe up with one finger) and switch to Files.
|
||||
- Tap `<` until the main "Browse" window is displayed, then select "On My iPhone"
|
||||
- Look for the "SheetJSQuasar" folder and tap `SheetJSQuasar.xlsx`.
|
||||
|
||||
If Numbers is installed on the device, it will display the contents of the new file.
|
||||
|
||||
**Android Device**
|
||||
|
||||
18) Close all open emulators and simulators.
|
||||
|
||||
19) Disconnect any iOS or Android devices connected to the computer.
|
||||
|
||||
20) Connect the Android device to the computer.
|
||||
|
||||
21) Start the dev process:
|
||||
|
||||
```bash
|
||||
quasar dev -m android
|
||||
```
|
||||
|
||||
If prompted to select an external IP, press <kbd>Enter</kbd>.
|
||||
|
||||
22) Test the application:
|
||||
15) Test the application:
|
||||
|
||||
- Press the Home button (or swipe up with one finger) and switch to Browser.
|
||||
- Download https://docs.sheetjs.com/pres.numbers
|
||||
@ -606,6 +478,48 @@ methods ("Storage Access Framework") that are not implemented in Quasar.
|
||||
:::
|
||||
|
||||
|
||||
### iOS Device
|
||||
|
||||
16) Close all open emulators and simulators.
|
||||
|
||||
17) Disconnect any iOS or Android devices connected to the computer.
|
||||
|
||||
18) Connect the iOS device to the computer.
|
||||
|
||||
19) Open the Xcode project:
|
||||
|
||||
```bash
|
||||
open src-cordova/platforms/ios/SheetJSQuasar.xcodeproj
|
||||
```
|
||||
|
||||
Select "SheetJSQuasar" in the Navigator. In the main pane, select "Signing &
|
||||
Capabilities" and ensure a Team is selected. Save and close the project.
|
||||
|
||||
20) Start the dev process:
|
||||
|
||||
```bash
|
||||
npx quasar dev -m cordova -T ios
|
||||
```
|
||||
|
||||
If prompted to select an external IP, press <kbd>Enter</kbd>.
|
||||
|
||||
11) Test the application:
|
||||
|
||||
- Press the Home button (or swipe up with one finger) and switch to Safari.
|
||||
- Download https://docs.sheetjs.com/pres.numbers
|
||||
- Press the Home button (or swipe up with one finger) and select the `SheetJSQuasar` app
|
||||
- Tap the "Load" button, then select "Choose File" and select the downloaded `pres.numbers`
|
||||
|
||||
The table will update with new data.
|
||||
|
||||
- Tap "Save File"
|
||||
- Press the Home button (or swipe up with one finger) and switch to Files.
|
||||
- Tap `<` until the main "Browse" window is displayed, then select "On My iPhone"
|
||||
- Look for the "SheetJSQuasar" folder and tap `SheetJSQuasar.xlsx`.
|
||||
|
||||
If Numbers is installed on the device, it will display the contents of the new file.
|
||||
|
||||
|
||||
[^1]: See ["File Picker"](https://quasar.dev/vue-components/file-picker) in the Quasar documentation.
|
||||
[^2]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^3]: See ["SheetJS Data Model"](/docs/csf/) for more details on workbooks, worksheets, and other concepts.
|
||||
|
@ -62,15 +62,16 @@ This demo was tested in the following environments:
|
||||
|:-----------|:--------------------|:-------|:-------------|:-----------|
|
||||
| Android 34 | Pixel 3a | B | `darwin-arm` | 2025-03-30 |
|
||||
| iOS 18.2 | iPhone SE (3rd gen) | B | `darwin-arm` | 2025-03-30 |
|
||||
| Android 36 | Pixel 9 Pro XL | A | `win11-x64` | 2025-04-17 |
|
||||
|
||||
<details>
|
||||
<summary><b>Configurations</b> (click to show)</summary>
|
||||
|
||||
Configuration A:
|
||||
|
||||
- Ionic: `@ionic/angular 8.2.0`, `@ionic/angular-toolkit 11.0.1`
|
||||
- Cordova: `cordova-lib@12.0.1`, `android 13.0.0, ios 7.1.0`
|
||||
- File Integration: `@awesome-cordova-plugins/file` version `6.7.0`
|
||||
- Ionic: `@ionic/angular 8.5.2`, `@ionic/angular-toolkit 12.1.1`
|
||||
- Cordova: `cordova-lib@12.0.2`, `android 14.0.0`
|
||||
- File Integration: `@awesome-cordova-plugins/file` version `6.16.0`
|
||||
|
||||
Configuration B:
|
||||
|
||||
@ -394,6 +395,11 @@ In the `application` tag, add the attribute `android:requestLegacyExternalStorag
|
||||
ionic cordova emulate android
|
||||
```
|
||||
|
||||
If prompted to share pseudonymous usage data with Google, type <kbd>N</kbd> and
|
||||
press <kbd>Enter</kbd> to opt out.
|
||||
|
||||
If prompted to share anonymous usage data with Cordova, type <kbd>N</kbd>.
|
||||
|
||||
When the app is loaded, a list of Presidents should be displayed. This list is
|
||||
dynamically generated by fetching and parsing a test file.
|
||||
|
||||
@ -433,7 +439,7 @@ In a test run, the output showed a Pixel 3a with the following details:
|
||||
// highlight-next-line
|
||||
Name: Pixel_3a_API_34
|
||||
Device: pixel_3a (Google)
|
||||
Path: /Users/SheetJS/.android/avd/Pixel_4_API_33.avd
|
||||
Path: /Users/SheetJS/.android/avd/Pixel_3a_API_34.avd
|
||||
```
|
||||
|
||||
The Ionic command accepts a `--target` flag. Pass the emulator name:
|
||||
@ -460,6 +466,8 @@ On macOS, this issue was resolved by installing Gradle with Homebrew manager:
|
||||
brew install gradle
|
||||
```
|
||||
|
||||
In Windows, Gradle must be installed manually[^11]
|
||||
|
||||
:::
|
||||
|
||||
:::danger pass
|
||||
@ -681,3 +689,4 @@ the file with the new line.
|
||||
[^8]: See [`write` in "Writing Files"](/docs/api/write-options)
|
||||
[^9]: See ["Developing for iOS"](https://ionic-docs-o31kiyk8l-ionic1.vercel.app/docs/v6/developing/ios) and ["Developing for Android"](https://ionic-docs-o31kiyk8l-ionic1.vercel.app/docs/v6/developing/android). The Ionic team removed these pages from the official docs site and recommend the `vercel.app` docs site.
|
||||
[^10]: See the [JDK Archive](https://jdk.java.net/archive/) for Java 17 JDK download links.
|
||||
[^11]: See ["Installing manually"](https://gradle.org/install/#manually) in the Gradle documentation.
|
@ -39,6 +39,7 @@ This demo was tested in the following deployments:
|
||||
|
||||
| OS and Version | Architecture | Excel | Date |
|
||||
|:---------------|:-------------|:-----------|:-----------|
|
||||
| macOS 15.3 | `darwin-x64` | 16.95.4 | 2025-04-17 |
|
||||
| macOS 14.5 | `darwin-arm` | 16.81 | 2024-12-22 |
|
||||
| Windows 11 | `win11-x64` | 365 (2501) | 2025-01-19 |
|
||||
|
||||
@ -57,13 +58,7 @@ Excel 365 before running the demo.
|
||||
The Office Add-in CLI collects telemetry by default. It can be disabled:
|
||||
|
||||
```js
|
||||
npx office-addin-usage-data off
|
||||
```
|
||||
|
||||
The setting can be verified by running:
|
||||
|
||||
```js
|
||||
npx office-addin-usage-data list
|
||||
npx -y office-addin-usage-data off
|
||||
```
|
||||
|
||||
:::
|
||||
@ -156,7 +151,7 @@ after testing is finished.
|
||||
3) Disable telemetry:
|
||||
|
||||
```bash
|
||||
npx office-addin-usage-data off
|
||||
npx -y office-addin-usage-data off
|
||||
```
|
||||
|
||||
4) Install dependencies:
|
||||
@ -165,21 +160,31 @@ npx office-addin-usage-data off
|
||||
npm i -g yo bower generator-office
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
In some systems, the command must be run with the root user:
|
||||
|
||||
```bash
|
||||
sudo npm i -g yo bower generator-office
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Creating a new Add-in
|
||||
|
||||
5) Run the generator:
|
||||
|
||||
```bash
|
||||
npx yo office
|
||||
npx -y yo office
|
||||
```
|
||||
|
||||
The generator will ask a few questions:
|
||||
|
||||
- "Choose a project type": "Excel Custom Functions using a Shared Runtime"
|
||||
- "Choose a project type": Select `Excel Custom Functions using a Shared Runtime`
|
||||
|
||||
- "Choose a script type": "JavaScript",
|
||||
- "Choose a script type": Select `JavaScript`
|
||||
|
||||
- "What do you want to name your add-in?": "SheetJSImport"
|
||||
- "What do you want to name your add-in?": Type `SheetJSImport` and press <kbd>Enter</kbd>
|
||||
|
||||
The generator will create the project and install dependencies.
|
||||
|
||||
@ -237,7 +242,7 @@ npm start
|
||||
|
||||
### Integrating the SheetJS Library
|
||||
|
||||
10) Install the SheetJS library in the project
|
||||
10) Install the SheetJS library in the project:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
|
||||
|
@ -25,9 +25,10 @@ library to export a bitfield table from Apple Numbers to a XLSX workbook.
|
||||
|
||||
This demo was tested by SheetJS users in the following deployments:
|
||||
|
||||
| Architecture | Ghidra | Date |
|
||||
|:-------------|:---------|:-----------|
|
||||
| `darwin-arm` | `11.13.1`| 2025-03-17 |
|
||||
| Architecture | Ghidra | Date |
|
||||
|:-------------|:----------|:-----------|
|
||||
| `darwin-x64` | `11.13.1` | 2025-04-17 |
|
||||
| `darwin-arm` | `11.13.1` | 2025-03-17 |
|
||||
|
||||
:::
|
||||
|
||||
@ -229,7 +230,7 @@ const src = decomp.getDecompiledFunction().getC();
|
||||
## Complete Demo
|
||||
|
||||
In this demo, we will inspect the `_TSTCellToCellStorage` method within the
|
||||
`TSTables` framework of Apple Numbers 14.2. This particular method handles
|
||||
`TSTables` framework of Apple Numbers 14.4. This particular method handles
|
||||
serialization of cells to the NUMBERS file format.
|
||||
|
||||
The implementation has a number of blocks which look like the following script:
|
||||
|
@ -1114,6 +1114,7 @@ This demo was tested in the following deployments:
|
||||
|:-------------|:--------|:-----------|
|
||||
| `darwin-x64` | `2.2.1` | 2025-03-31 |
|
||||
| `darwin-arm` | `2.2.1` | 2025-03-31 |
|
||||
| `win11-x64` | `2.2.1` | 2025-04-17 |
|
||||
|
||||
:::
|
||||
|
||||
|
@ -78,7 +78,7 @@ Spreadsheet applications commonly display file properties in separate windows:
|
||||
|
||||
:::note pass
|
||||
|
||||
When this demo was last tested, Apple Numbers 14.2 did not support file
|
||||
When this demo was last tested, Apple Numbers 14.4 did not support file
|
||||
properties in the XLSX import and export codecs.
|
||||
|
||||
:::
|
||||
|
@ -66,7 +66,7 @@ format has a limit of 2048 rows, so data after the 2048th row will not be saved.
|
||||
|:------------------------------------------|:-----------|---------:|---------:|
|
||||
| Excel 2007+ XML Formats (XLSX/XLSM) |`XFD1048576`| 16384 | 1048576 |
|
||||
| Excel 2007+ Binary Format (XLSB BIFF12) |`XFD1048576`| 16384 | 1048576 |
|
||||
| Numbers 14.2 (NUMBERS) |`ALL1000000`| 1000 | 1000000 |
|
||||
| Numbers 14.4 (NUMBERS) |`ALL1000000`| 1000 | 1000000 |
|
||||
| Quattro Pro 9+ (QPW) |`IV1000000 `| 256 | 1000000 |
|
||||
| Excel 97-2004 (XLS BIFF8) |`IV65536 `| 256 | 65536 |
|
||||
| Excel 5.0/95 (XLS BIFF5) |`IV16384 `| 256 | 16384 |
|
||||
@ -202,7 +202,7 @@ XLR also includes a `WksSSWorkBook` stream similar to Lotus FM3/FMT files.
|
||||
|
||||
iWork 2013 (Numbers 3.0 / Pages 5.0 / Keynote 6.0) switched from a proprietary
|
||||
XML-based format to the current file format based on the iWork Archive (IWA).
|
||||
This format has been used up through the current release (Numbers 14.2) as well
|
||||
This format has been used up through the current release (Numbers 14.4) as well
|
||||
as the iCloud.com web interface to Numbers.
|
||||
|
||||
The parser focuses on extracting raw data from tables. Numbers technically
|
||||
|
@ -60,7 +60,7 @@ src.split(/[\r\n]+/).reduce((acc,row,i) => {
|
||||
const aoo = offset.map((name, idx) => ({
|
||||
Mask: "0x" + (1 << idx).toString(16),
|
||||
"Internal Name": name.replace(/^PTR_s_|_[0-9a-f]*$/g,"").replace(/[A-Z]/g, " $&").toLowerCase().replace(/ i d/, " ID")
|
||||
}));
|
||||
})).filter(x => x);
|
||||
|
||||
/* create worksheet */
|
||||
const ws = json_to_sheet(aoo);
|
||||
|
68
docz/static/quasar/IndexPage.vue
Normal file
68
docz/static/quasar/IndexPage.vue
Normal file
@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<q-page class="row items-center justify-evenly">
|
||||
<q-table :rows="todos" />
|
||||
<q-btn-group>
|
||||
<q-file v-model="file" label="Load File" filled label-color="orange" @input="updateFile"/>
|
||||
<q-btn label="Save File" @click="saveFile" />
|
||||
</q-btn-group>
|
||||
</q-page>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { read, write, utils } from 'xlsx';
|
||||
import { useQuasar } from 'quasar';
|
||||
import type { Todo } from 'components/models';
|
||||
|
||||
const $q = useQuasar();
|
||||
|
||||
const todos = ref<Todo[]>([
|
||||
{ id: 1, content: 'ct1' },
|
||||
{ id: 2, content: 'ct2' },
|
||||
{ id: 3, content: 'ct3' },
|
||||
{ id: 4, content: 'ct4' },
|
||||
{ id: 5, content: 'ct5' }
|
||||
]);
|
||||
const file = ref<File>();
|
||||
|
||||
function dialogerr(e: any) { $q.dialog({title: "Error!", message: e?.message || String(e)}); }
|
||||
function saveFile() {
|
||||
/* generate workbook from state */
|
||||
const ws = utils.json_to_sheet(todos.value);
|
||||
const wb = utils.book_new(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 ${dir} ${entry.fullPath}`;
|
||||
entry.createWriter(writer => {
|
||||
try {
|
||||
const data = new Blob([u8], {type: "application/vnd.ms-excel"});
|
||||
writer.onwriteend = () => {
|
||||
try {
|
||||
$q.dialog({title: "Success!", message: msg});
|
||||
} catch(e) { dialogerr(e); }
|
||||
};
|
||||
writer.onerror = dialogerr;
|
||||
writer.write(data);
|
||||
} catch(e) { dialogerr(e); }
|
||||
}, dialogerr);
|
||||
}, dialogerr);
|
||||
} catch(e) { dialogerr(e) }
|
||||
}, dialogerr);
|
||||
}
|
||||
async function updateFile(v: Event) {
|
||||
try {
|
||||
const files = (v.target as HTMLInputElement).files;
|
||||
if(!files || files.length == 0 || !files[0]) return;
|
||||
|
||||
const wb = read(await files[0].arrayBuffer());
|
||||
|
||||
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); }
|
||||
}
|
||||
</script>
|
@ -3,13 +3,12 @@
|
||||
|
||||
cd /tmp
|
||||
rm -rf sheetjs-worker
|
||||
. ~/.bashrc ## This is apparently needed in macos
|
||||
|
||||
mkdir sheetjs-worker
|
||||
cd sheetjs-worker
|
||||
echo '{ "type": "module" }' > package.json
|
||||
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz express@4.18.2 formidable@2.1.2
|
||||
|
||||
cat >worker.js <<EOF
|
||||
/* load the worker_threads module */
|
||||
import { parentPort } from 'node:worker_threads';
|
||||
@ -70,11 +69,16 @@ app.post('/', (req, res, next) => {
|
||||
app.listen(7262, () => { console.log(\`Example app listening on port 7262\`); });
|
||||
EOF
|
||||
|
||||
# this version uses `n` to cycle through node versions
|
||||
for n in 18 20 22; do
|
||||
sudo n $n
|
||||
node --version
|
||||
npx -y concurrently -k 'node main.mjs' 'sleep 2; curl -X POST -F upload=@pres.numbers http://localhost:7262/ -J -O'
|
||||
npx -y xlsx-cli SheetJSPool.xlsx
|
||||
rm -f SheetJSPool.xlsx
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz formidable@2.1.2
|
||||
for express in 4.21.2 5.1.0; do
|
||||
npm i --save express@$express
|
||||
npm ls | grep express
|
||||
# this version uses `nvm` to cycle through node versions
|
||||
for n in 18 20 22; do
|
||||
nvm use $n
|
||||
node --version
|
||||
npx -y concurrently -k 'node main.mjs' 'sleep 2; curl -X POST -F upload=@pres.numbers http://localhost:7262/ -J -O'
|
||||
npx -y xlsx-cli SheetJSPool.xlsx
|
||||
rm -f SheetJSPool.xlsx
|
||||
done
|
||||
done
|
||||
|
Loading…
Reference in New Issue
Block a user