Skip to main content

CapacitorJS

CapacitorJS

note

This demo was tested on an Intel Mac on 2022 August 26 with Svelte.

The iOS simulator runs iOS 15.5 on an iPhone 13 Pro Max.

Telemetry

Before starting this demo, manually disable telemetry. On Linux and MacOS:

npx @capacitor/cli telemetry off

To verify telemetry was disabled:

npx @capacitor/cli telemetry

Integration Details

This example uses Svelte, but the same principles apply to other frameworks.

Reading data

The standard HTML5 File Input element logic works in CapacitorJS:

<script>
import { read, utils } from 'xlsx';

let html = "";

/* show file picker, read file, load table */
async function importFile(evt) {
const f = evt.target.files[0];
const wb = read(await f.arrayBuffer());
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
html = utils.sheet_to_html(ws); // generate HTML and update state
}
</script>

<main>
<input type="file" on:change={importFile}/>
<div bind:this={tbl}>{@html html}</div>
</main>

Writing data

@capacitor/filesystem can write Base64 strings:

<script>
import { Filesystem, Directory } from '@capacitor/filesystem';
import { utils, writeXLSX } from 'xlsx';

let html = "";
let tbl;

/* get state data and export to XLSX */
async function exportFile() {
const elt = tbl.getElementsByTagName("TABLE")[0];
const wb = utils.table_to_book(elt);
/* generate Base64 string for Capacitor */
const data = writeXLSX(wb, { type: "base64" });
await Filesystem.writeFile({
data,
path: "SheetJSCap.xlsx",
directory: Directory.Documents
}); // write file
}

</script>

<main>
<button on:click={exportFile}>Export XLSX</button>
<div bind:this={tbl}>{@html html}</div>
</main>

Demo

Complete Example (click to show)

0) Disable telemetry as noted in the warning.

Follow the React Native demo to ensure iOS and Android sims are ready.

1) Create a new Svelte project:

npm create [email protected] sheetjs-cap -- --template svelte
cd sheetjs-cap

2) Install dependencies:

npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
npm i --save @capacitor/core @capacitor/cli @capacitor/ios @capacitor/filesystem

3) Create CapacitorJS structure:

npx cap init sheetjs-cap com.sheetjs.cap --web-dir=dist
npx cap add ios

4) Replace the contents of src/App.svelte with the following:

src/App.svelte
<script>
import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
import { onMount } from 'svelte';
import { read, utils, version, writeXLSX } from 'xlsx';

let html = "";
let tbl;

/* Fetch and update the state once */
onMount(async() => {
const f = await (await fetch("https://sheetjs.com/pres.xlsx")).arrayBuffer();
const wb = read(f); // parse the array buffer
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
html = utils.sheet_to_html(ws); // generate HTML and update state
});

/* get state data and export to XLSX */
async function exportFile() {
const elt = tbl.getElementsByTagName("TABLE")[0];
const wb = utils.table_to_book(elt);
/* generate Base64 string for Capacitor */
const data = writeXLSX(wb, { type: "base64" });
/* write */
await Filesystem.writeFile({
path: "SheetJSCap.xlsx",
data,
directory: Directory.Documents
});
}

/* show file picker, read file, load table */
async function importFile(evt) {
const f = evt.target.files[0];
const wb = read(await f.arrayBuffer());
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
html = utils.sheet_to_html(ws); // generate HTML and update state
}
</script>

<main>
<h3>SheetJS × CapacitorJS { version }</h3>
<input type="file" on:change={importFile}/>
<button on:click={exportFile}>Export XLSX</button>
<div bind:this={tbl}>{@html html}</div>
</main>

5) Test the app:

npm run build; npx cap sync; npx cap run ios

There are 3 steps: build the Svelte app, sync with CapacitorJS, and run sim. This sequence must be run every time to ensure changes are propagated.