2022-08-31 06:46:03 +00:00
|
|
|
|
<script lang="ts">
|
|
|
|
|
import logo from './assets/logo.png'
|
|
|
|
|
import { onMount } from 'svelte';
|
|
|
|
|
import { read, utils, write, version } from 'xlsx';
|
2023-01-09 05:08:30 +00:00
|
|
|
|
import { ReadFile, SaveFile, WriteFile, ShowInfo, ShowError } from '../wailsjs/go/main/App';
|
2022-08-31 06:46:03 +00:00
|
|
|
|
|
2023-01-09 05:08:30 +00:00
|
|
|
|
/* this wrapper to SaveFile / WriteFile shows messages on error / success */
|
2022-08-31 06:46:03 +00:00
|
|
|
|
async function writeFile(wb) {
|
2023-01-09 05:08:30 +00:00
|
|
|
|
const path = await SaveFile();
|
|
|
|
|
if(!path) return await err("No file selected");
|
2022-08-31 06:46:03 +00:00
|
|
|
|
const b64 = write(wb, { bookType: path.slice(path.lastIndexOf(".")+1), type: "base64" });
|
2023-01-09 05:08:30 +00:00
|
|
|
|
await WriteFile(b64, path);
|
|
|
|
|
ShowInfo("Saved File", path);
|
2022-08-31 06:46:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-01-09 05:08:30 +00:00
|
|
|
|
/* this wrapper to ReadFile throws an error if no data was read */
|
2022-08-31 06:46:03 +00:00
|
|
|
|
async function readFile() {
|
2023-01-09 05:08:30 +00:00
|
|
|
|
const res = await ReadFile();
|
2022-08-31 06:46:03 +00:00
|
|
|
|
if(res.length == 0) throw "failed";
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function err(body, title = "") {
|
2023-01-09 05:08:30 +00:00
|
|
|
|
return ShowError(title, typeof body == "string" ? body : body.message);
|
2022-08-31 06:46:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let html = "";
|
|
|
|
|
let tbl;
|
|
|
|
|
|
|
|
|
|
/* Fetch and update the state once */
|
|
|
|
|
onMount(async() => {
|
2024-04-26 04:16:13 +00:00
|
|
|
|
const f = await (await fetch("https://docs.sheetjs.com/pres.xlsx")).arrayBuffer();
|
2022-08-31 06:46:03 +00:00
|
|
|
|
const wb = read(f); // parse the array buffer
|
|
|
|
|
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
|
|
|
|
|
// highlight-start
|
|
|
|
|
html = utils.sheet_to_html(ws); // generate HTML and update state
|
|
|
|
|
// highlight-end
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/* get state data and export to XLSX */
|
2023-01-09 05:08:30 +00:00
|
|
|
|
async function exportFile() {
|
2022-08-31 06:46:03 +00:00
|
|
|
|
const elt = tbl.getElementsByTagName("TABLE")[0];
|
|
|
|
|
const wb = utils.table_to_book(elt);
|
2023-01-09 05:08:30 +00:00
|
|
|
|
try { await writeFile(wb); } catch(e) { err(e); }
|
2022-08-31 06:46:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* show file picker, read file, load table */
|
|
|
|
|
async function importFile(evt) {
|
|
|
|
|
try {
|
|
|
|
|
const b64 = await readFile();
|
|
|
|
|
const wb = read(b64, { type: "base64" });
|
|
|
|
|
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
|
|
|
|
|
html = utils.sheet_to_html(ws); // generate HTML and update state
|
|
|
|
|
} catch(e) { err(e); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<main>
|
|
|
|
|
<img alt="Wails logo" id="logo" src="{logo}">
|
|
|
|
|
<div class="result" id="result">SheetJS × Wails {version}</div>
|
|
|
|
|
<button on:click={importFile}>Import File</button>
|
|
|
|
|
<button on:click={exportFile}>Export XLSX</button>
|
|
|
|
|
<div bind:this={tbl} class="ctr">{@html html}</div>
|
|
|
|
|
</main>
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
|
|
|
|
|
#logo {
|
|
|
|
|
display: block;
|
|
|
|
|
width: 25%;
|
|
|
|
|
height: 25%;
|
|
|
|
|
margin: auto;
|
|
|
|
|
padding: 10% 0 0;
|
|
|
|
|
background-position: center;
|
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
|
background-size: 100% 100%;
|
|
|
|
|
background-origin: content-box;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.result {
|
|
|
|
|
height: 24px;
|
|
|
|
|
line-height: 24px;
|
|
|
|
|
font-size: 24px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
margin: 1.5rem auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.ctr {
|
|
|
|
|
margin-left: auto;
|
|
|
|
|
margin-right: auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.input-box .btn {
|
|
|
|
|
width: 60px;
|
|
|
|
|
height: 30px;
|
|
|
|
|
line-height: 30px;
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
border: none;
|
|
|
|
|
margin: 0 0 0 20px;
|
|
|
|
|
padding: 0 8px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.input-box .btn:hover {
|
|
|
|
|
background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%);
|
|
|
|
|
color: #333333;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.input-box .input {
|
|
|
|
|
border: none;
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
outline: none;
|
|
|
|
|
height: 30px;
|
|
|
|
|
line-height: 30px;
|
|
|
|
|
padding: 0 10px;
|
|
|
|
|
background-color: rgba(240, 240, 240, 1);
|
|
|
|
|
-webkit-font-smoothing: antialiased;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.input-box .input:hover {
|
|
|
|
|
border: none;
|
|
|
|
|
background-color: rgba(255, 255, 255, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.input-box .input:focus {
|
|
|
|
|
border: none;
|
|
|
|
|
background-color: rgba(255, 255, 255, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
</style>
|