<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>