| 
									
										
										
										
											2023-04-30 12:27:09 +00:00
										 |  |  | --- | 
					
						
							|  |  |  | title: SvelteKit | 
					
						
							|  |  |  | pagination_prev: demos/net/index | 
					
						
							|  |  |  | pagination_next: demos/mobile/index | 
					
						
							|  |  |  | --- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import current from '/version.js'; | 
					
						
							| 
									
										
										
										
											2023-05-07 13:58:36 +00:00
										 |  |  | import CodeBlock from '@theme/CodeBlock'; | 
					
						
							| 
									
										
										
										
											2023-04-30 12:27:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | :::note | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo covers SvelteKit. The [Svelte demo](/docs/demos/frontend/svelte) | 
					
						
							|  |  |  | covers general client-side strategies. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo uses ["Base64 Loader"](/docs/demos/static/vitejs#base64-loader) | 
					
						
							|  |  |  | from the ViteJS demo. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SvelteKit projects use ViteJS under the hood. They expose the `vite.config.js` | 
					
						
							|  |  |  | script. The [ViteJS demo](/docs/demos/static/vitejs) examples work as expected! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The following diagram depicts the workbook waltz: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```mermaid | 
					
						
							|  |  |  | flowchart LR | 
					
						
							|  |  |  |   file[(workbook\nfile)] | 
					
						
							|  |  |  |   subgraph SheetJS operations | 
					
						
							|  |  |  |     base64(base64\nstring) | 
					
						
							| 
									
										
										
										
											2023-05-25 01:36:15 +00:00
										 |  |  |     aoo(array of\nobjects) | 
					
						
							| 
									
										
										
										
											2023-04-30 12:27:09 +00:00
										 |  |  |   end | 
					
						
							|  |  |  |   html{{HTML\nTABLE}} | 
					
						
							|  |  |  |   file --> |vite.config.js\ndata loader| base64 | 
					
						
							| 
									
										
										
										
											2023-05-25 01:36:15 +00:00
										 |  |  |   base64 --> |+page.server.js\nload function| aoo | 
					
						
							|  |  |  |   aoo --> |+page.svelte\ncomponent| html | 
					
						
							| 
									
										
										
										
											2023-04-30 12:27:09 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Integration
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `+page.server.js` scripts can be pre-rendered by exporting `prerender` from the | 
					
						
							|  |  |  | script. If the SheetJS operations are performed in the server script, only the | 
					
						
							|  |  |  | results will be added to the generated pages! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For static site generation, `@sveltejs/adapter-static` must be used. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Loader
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::note | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The ViteJS demo used the query `?b64` to identify files. To play nice with | 
					
						
							|  |  |  | SvelteKit, this demo matches the file extensions directly. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The loader should be added to `vite.config.js`. The code is nearly identical to | 
					
						
							|  |  |  | the ["Base64 Loader" ViteJS example.](/docs/demos/static/vitejs#base64-loader) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js title="vite.config.js" | 
					
						
							|  |  |  | import { sveltekit } from '@sveltejs/kit/vite'; | 
					
						
							|  |  |  | import { defineConfig } from 'vite'; | 
					
						
							|  |  |  | import { readFileSync } from 'fs'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default defineConfig({ | 
					
						
							|  |  |  |   assetsInclude: ['**/*.numbers', '**/*.xlsx'], | 
					
						
							|  |  |  |   plugins: [sveltekit(), { | 
					
						
							|  |  |  |     name: "sheet-base64", | 
					
						
							|  |  |  |     transform(code, id) { | 
					
						
							|  |  |  |       if(!id.match(/\.(numbers|xlsx)$/)) return; | 
					
						
							|  |  |  |       var data = readFileSync(id, "base64"); | 
					
						
							|  |  |  |       return `export default '${data}'`; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }] | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #### Types
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For VSCodium integration, types can be specified in `src/app.d.ts`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The example data loader returns Base64 strings. Declarations should be added for | 
					
						
							|  |  |  | each file extension supported in the loader: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```ts title="src/app.d.ts" | 
					
						
							|  |  |  | declare global { | 
					
						
							|  |  |  |   declare module '*.numbers' { | 
					
						
							|  |  |  |     const data: string; | 
					
						
							|  |  |  |     export default data; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   declare module '*.xlsx' { | 
					
						
							|  |  |  |     const data: string; | 
					
						
							|  |  |  |     export default data; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Data Processing
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For static sites, SheetJS operations should be run in `+page.server.js` . | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Assuming `pres.xlsx` is stored in the `data` directory from the project root, | 
					
						
							|  |  |  | the relative import | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | import b64 from "../../data/pres.xlsx" | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | will return a Base64 string which can be parsed in the script. The workbook | 
					
						
							|  |  |  | object can be post-processed using utility functions.  The following example | 
					
						
							|  |  |  | uses `sheet_to_json` to generate arrays of row objects for each worksheet. The | 
					
						
							|  |  |  | data presented to the page will be an object whose keys are worksheet names: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js title="src/routes/+page.server.js" | 
					
						
							|  |  |  | import b64 from "../../data/pres.xlsx"; | 
					
						
							|  |  |  | import { read, utils } from "xlsx"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export const prerender = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** @type {import('./$types').PageServerLoad} */ | 
					
						
							|  |  |  | export async function load({ params }) { | 
					
						
							|  |  |  |   const wb = read(b64); | 
					
						
							|  |  |  |   /** @type {[string, any[]][]} */ | 
					
						
							|  |  |  |   const data = wb.SheetNames.map(n => [n, utils.sheet_to_json(wb.Sheets[n])]); | 
					
						
							|  |  |  |   return Object.fromEntries(data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Data Rendering
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The shape of the data is determined by the loader. The example loader returns an | 
					
						
							|  |  |  | object whose keys are worksheet names and whose values are arrays of objects. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Using standard Svelte patterns, HTML tables can be generated from the data: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```html title="src/routes/+page.svelte" | 
					
						
							|  |  |  | <script> | 
					
						
							|  |  |  |   /** @type {import('./$types').PageData} */ | 
					
						
							|  |  |  |   export let data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* `pres` will be the data from Sheet1 */ | 
					
						
							|  |  |  |   /** @type {Array<{Name: string, Index: number}>}*/ | 
					
						
							|  |  |  |   export let pres = data["Sheet1"]; | 
					
						
							|  |  |  | </script> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <h1>Presidents</h1> | 
					
						
							|  |  |  | <table><thead><th>Name</th><th>Index</th></thead><tbody> | 
					
						
							|  |  |  |   {#each pres as p}<tr> | 
					
						
							|  |  |  |     <td>{p.Name}</td> | 
					
						
							|  |  |  |     <td>{p.Index}</td> | 
					
						
							|  |  |  |   </tr>{/each} | 
					
						
							|  |  |  | </tbody></table> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When built using `npm run build`, SvelteKit will perform the conversion and emit | 
					
						
							|  |  |  | a simple HTML table without any reference to the existing spreadsheet file! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Complete Example
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::note | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This demo was tested on 2023 April 30 using SvelteKit `1.15.9` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Initial Setup
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1) Create a new site: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm create svelte@latest sheetjs-svelte | 
					
						
							|  |  |  | cd sheetjs-svelte | 
					
						
							|  |  |  | npm i | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-01 01:27:02 +00:00
										 |  |  | When prompted: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - `Which Svelte app template?` select `Skeleton Project` | 
					
						
							|  |  |  | - `Add type checking with TypeScript?` select `Yes, using JavaScript with JSDoc` | 
					
						
							|  |  |  | - `Select additional options` press Enter (do not select options) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-30 12:27:09 +00:00
										 |  |  | 2) Fetch the example file [`pres.xlsx`](https://sheetjs.com/pres.xlsx) and move | 
					
						
							|  |  |  | to a `data` subdirectory in the root of the project: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | mkdir -p data | 
					
						
							|  |  |  | curl -Lo data/pres.xlsx https://sheetjs.com/pres.xlsx | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 3) Install the SheetJS library: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-07 13:58:36 +00:00
										 |  |  | <CodeBlock language="bash">{`\ | 
					
						
							| 
									
										
										
										
											2023-04-30 12:27:09 +00:00
										 |  |  | npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | 
					
						
							| 
									
										
										
										
											2023-05-07 13:58:36 +00:00
										 |  |  | </CodeBlock> | 
					
						
							| 
									
										
										
										
											2023-04-30 12:27:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 4) Replace the contents of `vite.config.js` with the contents of the code block | 
					
						
							|  |  |  | named [`vite.config.js` in the "Loader" section](#loader) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 5) Append the lines from [`src/app.d.ts` snippet in the "Types" section](#types) | 
					
						
							|  |  |  | to the `src/app.d.ts` file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 6) Replace the contents of `src/routes/+page.server.ts` with the contents of the | 
					
						
							|  |  |  | code block named [`src/routes/+page.server.ts` in "Data Processing"](#data-processing) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 7) Replace the contents of `src/routes/+page.svelte` with the contents of the | 
					
						
							|  |  |  | code block named [`src/routes/+page.svelte` in "Data Rendering"](#data-rendering) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Live Reload
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 8) Open `data/pres.xlsx` in a spreadsheet editor like Apple Numbers or Excel. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 9) Start the development server: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm run dev | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Open the displayed URL (typically `http://localhost:5173`) in a web browser and | 
					
						
							|  |  |  | observe that the data from the spreadsheet is displayed in the page. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 10) 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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Static Site
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 11) Stop the development server and install the static adapter: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							| 
									
										
										
										
											2023-05-07 13:58:36 +00:00
										 |  |  | npm i --save @sveltejs/adapter-static | 
					
						
							| 
									
										
										
										
											2023-04-30 12:27:09 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 12) Edit `svelte.config.js` to use the new adapter: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```diff title="svelte.config.js" | 
					
						
							|  |  |  | -import adapter from '@sveltejs/adapter-auto'; | 
					
						
							|  |  |  | +import adapter from '@sveltejs/adapter-static'; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 13) Build the static site: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm run build | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 14) Open a web browser and access the displayed URL (`http://localhost:8080`). | 
					
						
							|  |  |  | View the page source and confirm that the raw HTML table includes the data. |