forked from sheetjs/docs.sheetjs.com
		
	vue
This commit is contained in:
		
							parent
							
								
									d4a38231dd
								
							
						
					
					
						commit
						2d5f8ebce4
					
				@ -27,6 +27,86 @@ suitable for a number of libraries.  When more advanced shapes are needed,
 | 
			
		||||
it is easier to munge the output of an array of arrays.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### x-spreadsheet
 | 
			
		||||
 | 
			
		||||
With a familiar UI, [`x-spreadsheet`](https://myliang.github.io/x-spreadsheet/)
 | 
			
		||||
is an excellent choice for developers looking for a modern editor.
 | 
			
		||||
 | 
			
		||||
[Click here for a live integration demo.](pathname:///xspreadsheet/)
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Full Exposition</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
**Obtaining the Library**
 | 
			
		||||
 | 
			
		||||
The `x-data-spreadsheet` NodeJS packages include a minified script that can be
 | 
			
		||||
directly inserted as a script tag.  The unpkg CDN also serves this script:
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<!-- x-spreadsheet stylesheet -->
 | 
			
		||||
<link rel="stylesheet" href="https://unpkg.com/x-data-spreadsheet/dist/xspreadsheet.css"/>
 | 
			
		||||
<!-- x-spreadsheet library -->
 | 
			
		||||
<script src="https://unpkg.com/x-data-spreadsheet/dist/xspreadsheet.js"></script>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
**Previewing and Editing Data**
 | 
			
		||||
 | 
			
		||||
The HTML document needs a container element:
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<div id="gridctr"></div>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Grid initialization is a one-liner:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
var grid = x_spreadsheet(document.getElementById("gridctr"));
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
`x-spreadsheet` handles the entire edit cycle. No intervention is necessary.
 | 
			
		||||
 | 
			
		||||
**SheetJS and x-spreadsheet**
 | 
			
		||||
 | 
			
		||||
The integration library can be downloaded from the SheetJS CDN:
 | 
			
		||||
 | 
			
		||||
[Development Use](https://cdn.sheetjs.com/xspreadsheet/xlsxspread.js)
 | 
			
		||||
 | 
			
		||||
[Production Use](https://cdn.sheetjs.com/xspreadsheet/xlsxspread.min.js)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
When used in a browser tag, it exposes two functions: `xtos` and `stox`.
 | 
			
		||||
 | 
			
		||||
- `stox(worksheet)` returns a data structure suitable for `grid.loadData`
 | 
			
		||||
- `xtos(data)` accepts the result of `grid.getData` and generates a workbook
 | 
			
		||||
 | 
			
		||||
_Reading Data_
 | 
			
		||||
 | 
			
		||||
The following snippet fetches a spreadsheet and loads the grid:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
(async() => {
 | 
			
		||||
  const ab = await (await fetch("https://sheetjs.com/pres.numbers")).arrayBuffer();
 | 
			
		||||
  grid.loadData(stox(XLSX.read(ab)));
 | 
			
		||||
})();
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The same pattern can be used in file input elements and other data sources.
 | 
			
		||||
 | 
			
		||||
_Writing Data_
 | 
			
		||||
 | 
			
		||||
The following snippet exports the grid data to a file:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* build workbook from the grid data */
 | 
			
		||||
XLSX.writeFile(xtos(grid.getData()), "SheetJS.xlsx");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
**Additional Features**
 | 
			
		||||
 | 
			
		||||
This demo barely scratches the surface.  The underlying grid component includes
 | 
			
		||||
many additional features that work with [SheetJS Pro](https://sheetjs.com/pro).
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
### Canvas DataGrid
 | 
			
		||||
 | 
			
		||||
After extensive testing, [`canvas-datagrid`](https://canvas-datagrid.js.org/demo.html)
 | 
			
		||||
@ -120,7 +200,6 @@ many additional features including massive data streaming, sorting and styling.
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Angular UI Grid
 | 
			
		||||
 | 
			
		||||
:::warning
 | 
			
		||||
@ -223,7 +302,7 @@ import { WorkSheet, utils } from 'xlsx';
 | 
			
		||||
 | 
			
		||||
type Row = any[];
 | 
			
		||||
 | 
			
		||||
function ws_to_rdg(rows: Row[]): WorkSheet {
 | 
			
		||||
function rdg_to_ws(rows: Row[]): WorkSheet {
 | 
			
		||||
  return utils.aoa_to_sheet(rows);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
@ -361,8 +440,135 @@ export default function App() {
 | 
			
		||||
4) run `npm start`.  When you load the dev page in the browser, it will attempt
 | 
			
		||||
to fetch <https://sheetjs.com/pres.numbers> and load the data.
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
The following screenshot was taken from the demo:
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
### vue3-table-lite
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was tested against `vue3-table-lite 1.2.4`, VueJS `3.2.37`, ViteJS
 | 
			
		||||
3.0.7, and `@vitejs/plugin-vue` 3.0.3 on 2022 August 18
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
[`vue3-table-lite`](https://vue3-lite-table.vercel.app/) is a data grid built
 | 
			
		||||
for Vue
 | 
			
		||||
 | 
			
		||||
[A complete example is included below.](#vte-demo)
 | 
			
		||||
 | 
			
		||||
#### Rows and Columns Bindings
 | 
			
		||||
 | 
			
		||||
`vue3-table-lite` presents two bindable attributes: an array of column metadata
 | 
			
		||||
(`columns`) and an array of objects representing the displayed data (`rows`).
 | 
			
		||||
Typically both are `ref` objects:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { ref } from "vue";
 | 
			
		||||
import VueTableLite from "vue3-table-lite/ts";
 | 
			
		||||
 | 
			
		||||
/* rows */
 | 
			
		||||
type Row = any[];
 | 
			
		||||
const rows = ref<Row[]>([]);
 | 
			
		||||
 | 
			
		||||
/* columns */
 | 
			
		||||
type Column = { field: string; label: string; };
 | 
			
		||||
const columns = ref<Column[]>([]);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <vue-table-lite :columns="columns" :rows="rows"></vue-table-lite>
 | 
			
		||||
</template>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
These can be mutated through the `value` property in Vue lifecycle methods:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
import { onMounted } from "vue";
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  columns.value = [ { field: "name", label: "Names" }];
 | 
			
		||||
  rows.value = [ { name: "SheetJS" }, { name: "VueJS" } ];
 | 
			
		||||
})
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The most generic data representation is an array of arrays. To sate the grid,
 | 
			
		||||
the columns must be objects whose `field` property is the stringified number:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
import { ref } from "vue";
 | 
			
		||||
import { utils } from 'xlsx';
 | 
			
		||||
 | 
			
		||||
/* generate row and column data */
 | 
			
		||||
function ws_to_vte(ws) {
 | 
			
		||||
  /* create an array of arrays */
 | 
			
		||||
  const rows = utils.sheet_to_json(ws, { header: 1 });
 | 
			
		||||
 | 
			
		||||
  /* create column array */
 | 
			
		||||
  const range = utils.decode_range(ws["!ref"]||"A1");
 | 
			
		||||
  const columns = Array.from({ length: range.e.c + 1 }, (_, i) => ({
 | 
			
		||||
    field: String(i), // VTE will access row["0"], row["1"], etc
 | 
			
		||||
    label: utils.encode_col(i), // the column labels will be A, B, etc
 | 
			
		||||
  }));
 | 
			
		||||
 | 
			
		||||
  return { rows, columns };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const rows = ref([]);
 | 
			
		||||
const columns = ref([]);
 | 
			
		||||
 | 
			
		||||
/* update refs */
 | 
			
		||||
function update_refs(ws) {
 | 
			
		||||
  const data = ws_to_vte(ws);
 | 
			
		||||
  rows.value = data.rows;
 | 
			
		||||
  columns.value = data.columns;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
In the other direction, a worksheet can be generated with `aoa_to_sheet`:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
import { utils } from 'xlsx';
 | 
			
		||||
 | 
			
		||||
const rows = ref([]);
 | 
			
		||||
 | 
			
		||||
function vte_to_ws(rows) {
 | 
			
		||||
  return utils.aoa_to_sheet(rows.value);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### VTE Demo
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Complete Example</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
1) Create a new ViteJS App using the Vue + TypeScript template:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm create vite@latest sheetjs-vue -- --template vue-ts
 | 
			
		||||
cd sheetjs-vue
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
2) Install dependencies:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm i
 | 
			
		||||
npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz vue3-table-lite
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
3) Download [`src/App.vue`](pathname:///vtl/App.vue) and replace the contents:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
cd src
 | 
			
		||||
rm -f App.vue
 | 
			
		||||
curl -LO https://docs.sheetjs.com/vtl/App.vue
 | 
			
		||||
cd ..
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
4) run `npm run dev`.  When you load the dev page in the browser, it will try
 | 
			
		||||
to fetch <https://sheetjs.com/pres.numbers> and load the data.
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
@ -434,7 +434,7 @@ ready, it will read the hardcoded test file and print the contents as CSV.
 | 
			
		||||
 | 
			
		||||
5) Run the script using the Hermes standalone binary:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
```bash
 | 
			
		||||
hermes xlsx.hermes.js
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@ -540,6 +540,93 @@ to `SheetJSwift.xlsx`. That file can be verified by opening in Excel / Numbers.
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
## JerryScript
 | 
			
		||||
 | 
			
		||||
JerryScript is a lightweight JavaScript engine designed for use in low-memory
 | 
			
		||||
environments like microcontrollers.  As part of the build suite, the project
 | 
			
		||||
generates a C library and a standalone CLI tool.
 | 
			
		||||
 | 
			
		||||
The simplest way to interact with the engine is to pass Base64 strings.
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
While applications should link against the official libraries, the standalone tool
 | 
			
		||||
is useful for verifying functionality.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
:::caution
 | 
			
		||||
 | 
			
		||||
This demo requires a much larger heap size than is normally used in JerryScript
 | 
			
		||||
deployments! In local testing, the following sizes were needed:
 | 
			
		||||
 | 
			
		||||
- 8192 (8M) for <https://sheetjs.com/pres.xlsx>
 | 
			
		||||
- 65536 (64M) for <https://sheetjs.com/pres.numbers>
 | 
			
		||||
 | 
			
		||||
This works on a Raspberry Pi.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Complete Example</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
Due to limitations of the standalone binary, this demo will encode a test file
 | 
			
		||||
as a Base64 string and directly add it to an amalgamated script.
 | 
			
		||||
 | 
			
		||||
0) Build the library and command line tool with required options:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
git clone --depth=1 https://github.com/jerryscript-project/jerryscript.git
 | 
			
		||||
cd jerryscript
 | 
			
		||||
python tools/build.py --error-messages=ON --logging=ON --mem-heap=8192 --cpointer-32bit=ON
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
1) Download the standalone script, shim, and test file:
 | 
			
		||||
 | 
			
		||||
<ul>
 | 
			
		||||
<li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li>
 | 
			
		||||
<li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js`}>shim.min.js</a></li>
 | 
			
		||||
<li><a href="https://sheetjs.com/pres.xlsx">pres.xlsx</a></li>
 | 
			
		||||
</ul>
 | 
			
		||||
 | 
			
		||||
2) Bundle the test file and create `payload.js`:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
node -e "fs.writeFileSync('payload.js', 'var payload = \"' + fs.readFileSync('pres.xlsx').toString('base64') + '\";')"
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
3) Create support scripts:
 | 
			
		||||
 | 
			
		||||
- `global.js` creates a `global` variable and defines a fake `console`:
 | 
			
		||||
 | 
			
		||||
```js title="global.js"
 | 
			
		||||
var global = (function(){ return this; }).call(null);
 | 
			
		||||
var console = { log: function(x) { print(x); } };
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
- `jerry.js` will call `XLSX.read` and `XLSX.utils.sheet_to_csv`:
 | 
			
		||||
 | 
			
		||||
```js title="jerry.js"
 | 
			
		||||
/* sheetjs (C) 2013-present  SheetJS -- http://sheetjs.com */
 | 
			
		||||
var wb = XLSX.read(payload, {type:'base64'});
 | 
			
		||||
console.log(XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]));
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
4) Create the amalgamation `xlsx.jerry.js`:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
cat global.js xlsx.full.min.js payload.js jerry.js > xlsx.jerry.js
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The final script defines `global` before loading the standalone library.  Once
 | 
			
		||||
ready, it will read the hardcoded test file and print the contents as CSV.
 | 
			
		||||
 | 
			
		||||
5) Run the script using the `jerry` standalone binary:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
build/bin/jerry xlsx.jerry.js; echo $?
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
## QuickJS
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
---
 | 
			
		||||
sidebar_position: 20
 | 
			
		||||
sidebar_position: 21
 | 
			
		||||
title: ReactJS
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,7 @@ Typically, some users will create a spreadsheet with source data that should be
 | 
			
		||||
loaded into the site.  This sheet will have known columns.  For example, our
 | 
			
		||||
[presidents sheet](https://sheetjs.com/pres.xlsx) has "Name" / "Index" columns:
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
This naturally maps to an array of typed objects, as in the TS example below:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										184
									
								
								docz/docs/03-demos/22-vue.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										184
									
								
								docz/docs/03-demos/22-vue.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,184 @@
 | 
			
		||||
---
 | 
			
		||||
sidebar_position: 22
 | 
			
		||||
title: VueJS
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
[VueJS](https://vuejs.org/) is a JS library for building user interfaces.
 | 
			
		||||
 | 
			
		||||
This demo tries to cover common Vue data flow ideas and strategies. Single-File
 | 
			
		||||
Components (SFC) and VueJS familiarity is assumed.
 | 
			
		||||
 | 
			
		||||
Other demos cover general VueJS deployments, including:
 | 
			
		||||
 | 
			
		||||
- [Static Site Generation powered by NuxtJS](./content#nuxtjs)
 | 
			
		||||
- [iOS and Android applications powered by Quasar](./mobile#quasar)
 | 
			
		||||
- [`vue3-table-lite` UI component](./grid#vue3-table-lite)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
 | 
			
		||||
[The "Frameworks" section](../getting-started/installation/frameworks) covers
 | 
			
		||||
installation with Yarn and other package managers.
 | 
			
		||||
 | 
			
		||||
The library can be imported directly from JS or JSX code with:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
import { read, utils, writeFile } from 'xlsx';
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Internal State
 | 
			
		||||
 | 
			
		||||
The various SheetJS APIs work with various data shapes.  The preferred state
 | 
			
		||||
depends on the application.
 | 
			
		||||
 | 
			
		||||
### Array of Objects
 | 
			
		||||
 | 
			
		||||
Typically, some users will create a spreadsheet with source data that should be
 | 
			
		||||
loaded into the site.  This sheet will have known columns.  For example, our
 | 
			
		||||
[presidents sheet](https://sheetjs.com/pres.xlsx) has "Name" / "Index" columns:
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
This naturally maps to an array of typed objects, as in the TS example below:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
import { read, utils } from 'xlsx';
 | 
			
		||||
 | 
			
		||||
interface President {
 | 
			
		||||
  Name: string;
 | 
			
		||||
  Index: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const f = await (await fetch("https://sheetjs.com/pres.xlsx")).arrayBuffer();
 | 
			
		||||
const wb = read(f);
 | 
			
		||||
const data = utils.sheet_to_json<President>(wb.Sheets[wb.SheetNames[0]]);
 | 
			
		||||
console.log(data);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
`data` will be an array of objects:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
[
 | 
			
		||||
  { Name: "Bill Clinton", Index: 42 },
 | 
			
		||||
  { Name: "GeorgeW Bush", Index: 43 },
 | 
			
		||||
  { Name: "Barack Obama", Index: 44 },
 | 
			
		||||
  { Name: "Donald Trump", Index: 45 },
 | 
			
		||||
  { Name: "Joseph Biden", Index: 46 }
 | 
			
		||||
]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
A component will typically map over the data. The following example generates
 | 
			
		||||
a TABLE with a row for each President:
 | 
			
		||||
 | 
			
		||||
```html title="src/SheetJSVueAoO.vue"
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref, onMounted } from "vue";
 | 
			
		||||
import { read, utils } from 'xlsx';
 | 
			
		||||
 | 
			
		||||
const rows = ref([]);
 | 
			
		||||
 | 
			
		||||
onMounted(async() => {
 | 
			
		||||
  /* Download from https://sheetjs.com/pres.numbers */
 | 
			
		||||
  const f = await fetch("https://sheetjs.com/pres.numbers");
 | 
			
		||||
  const ab = await f.arrayBuffer();
 | 
			
		||||
 | 
			
		||||
  /* parse workbook */
 | 
			
		||||
  const wb = read(ab);
 | 
			
		||||
 | 
			
		||||
  /* update data */
 | 
			
		||||
  rows.value = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <table><thead><th>Name</th><th>Index</th></thead><tbody>
 | 
			
		||||
    <tr v-for="(row, idx) in rows" :key="idx">
 | 
			
		||||
      <td>{{ row.Name }}</td>
 | 
			
		||||
      <td>{{ row.Index }}</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
  </tbody></table>
 | 
			
		||||
</template>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### HTML
 | 
			
		||||
 | 
			
		||||
The main disadvantage of the Array of Objects approach is the specific nature
 | 
			
		||||
of the columns.  For more general use, passing around an Array of Arrays works.
 | 
			
		||||
However, this does not handle merge cells well!
 | 
			
		||||
 | 
			
		||||
The `sheet_to_html` function generates HTML that is aware of merges and other
 | 
			
		||||
worksheet features.  VueJS `v-html` attribute allows assignment of `innerHTML`
 | 
			
		||||
attribute, effectively inserting the code into the page:
 | 
			
		||||
 | 
			
		||||
```html title="src/SheetJSVueHTML.vue"
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref, onMounted } from "vue";
 | 
			
		||||
import { read, utils } from 'xlsx';
 | 
			
		||||
 | 
			
		||||
const html = ref("");
 | 
			
		||||
 | 
			
		||||
onMounted(async() => {
 | 
			
		||||
  /* Download from https://sheetjs.com/pres.numbers */
 | 
			
		||||
  const f = await fetch("https://sheetjs.com/pres.numbers");
 | 
			
		||||
  const ab = await f.arrayBuffer();
 | 
			
		||||
 | 
			
		||||
  /* parse workbook */
 | 
			
		||||
  const wb = read(ab);
 | 
			
		||||
 | 
			
		||||
  /* update data */
 | 
			
		||||
  html.value = utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]);
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div v-html="html"></div>
 | 
			
		||||
</template>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Rows and Columns
 | 
			
		||||
 | 
			
		||||
Some data grids and UI components split worksheet state in two parts: an array
 | 
			
		||||
of column attribute objects and an array of row objects.  The former is used to
 | 
			
		||||
generate column headings and for indexing into the row objects.
 | 
			
		||||
 | 
			
		||||
The safest approach is to use an array of arrays for state and to generate
 | 
			
		||||
column objects that map to A1-style column headers.
 | 
			
		||||
 | 
			
		||||
The [Vue Table Lite demo](./grid#rows-and-columns-bindings) uses this approach
 | 
			
		||||
with the following column and row structure:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* rows are generated with a simple array of arrays */
 | 
			
		||||
rows.value = utils.sheet_to_json(worksheet, { header: 1 });
 | 
			
		||||
 | 
			
		||||
/* column objects are generated based on the worksheet range */
 | 
			
		||||
const range = utils.decode_range(ws["!ref"]||"A1");
 | 
			
		||||
columns.value = Array.from({ length: range.e.c + 1 }, (_, i) => ({
 | 
			
		||||
  /* for an array of arrays, the keys are "0", "1", "2", ... */
 | 
			
		||||
  field: String(i),
 | 
			
		||||
  /* column labels: encode_col translates 0 -> "A", 1 -> "B", 2 -> "C", ... */
 | 
			
		||||
  label: XLSX.utils.encode_col(i)
 | 
			
		||||
}));
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Legacy Deployments
 | 
			
		||||
 | 
			
		||||
[The Standalone Scripts](../getting-started/installation/standalone) play nice
 | 
			
		||||
with legacy deployments that do not use a bundler.
 | 
			
		||||
 | 
			
		||||
The legacy demos show a simple VueJS component.  It is written in ES5 syntax.
 | 
			
		||||
The pages are not minified and "View Source" should be used to inspect.
 | 
			
		||||
 | 
			
		||||
- [VueJS version 2](pathname:///vue/index2.html)
 | 
			
		||||
- [VueJS version 3](pathname:///vue/index3.html)
 | 
			
		||||
 | 
			
		||||
There is a shared component [`SheetJS-vue.js`](pathname:///vue/SheetJS-vue.js)
 | 
			
		||||
 | 
			
		||||
:::caution
 | 
			
		||||
 | 
			
		||||
The entire demo is designed to run in Internet Explorer and does not reflect
 | 
			
		||||
modern design patterns.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
@ -18,18 +18,18 @@ The demo projects include small runnable examples and short explainers.
 | 
			
		||||
 | 
			
		||||
### Frameworks
 | 
			
		||||
 | 
			
		||||
- [`Angular.JS`](./legacy#angularjs)
 | 
			
		||||
- [`Angular 2+ and Ionic`](https://github.com/SheetJS/SheetJS/tree/master/demos/angular2/)
 | 
			
		||||
- [`Knockout`](./legacy#knockout)
 | 
			
		||||
- [`React`](./react)
 | 
			
		||||
- [`VueJS`](https://github.com/SheetJS/SheetJS/tree/master/demos/vue/)
 | 
			
		||||
- [`VueJS`](./vue)
 | 
			
		||||
- [`Angular.JS`](./legacy#angularjs)
 | 
			
		||||
- [`Knockout`](./legacy#knockout)
 | 
			
		||||
 | 
			
		||||
### Front-End UI Components
 | 
			
		||||
 | 
			
		||||
- [`canvas-datagrid`](./grid#canvas-datagrid)
 | 
			
		||||
- [`x-spreadsheet`](https://github.com/SheetJS/SheetJS/tree/master/demos/xspreadsheet/)
 | 
			
		||||
- [`react-data-grid`](https://github.com/SheetJS/SheetJS/tree/master/demos/react/modify/)
 | 
			
		||||
- [`vue3-table-light`](https://github.com/SheetJS/SheetJS/tree/master/demos/vue/modify/)
 | 
			
		||||
- [`x-spreadsheet`](./grid#x-spreadsheet)
 | 
			
		||||
- [`react-data-grid`](./grid#react-data-grid)
 | 
			
		||||
- [`vue3-table-lite`](./grid#vue3-table-lite)
 | 
			
		||||
- [`angular-ui-grid`](./grid#angular-ui-grid)
 | 
			
		||||
 | 
			
		||||
### Platforms and Integrations
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* sheetjs (C) 2013-present  SheetJS -- http://sheetjs.com */
 | 
			
		||||
var XLSX = require('xlsx');
 | 
			
		||||
/*jshint browser:true */
 | 
			
		||||
/*global require */
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<!-- xlsx.js (C) 2013-present  SheetJS http://sheetjs.com -->
 | 
			
		||||
<!-- sheetjs (C) 2013-present  SheetJS http://sheetjs.com -->
 | 
			
		||||
<!-- vim: set ts=2: -->
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
/* sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
var XLSX = require('xlsx');
 | 
			
		||||
 | 
			
		||||
postMessage({t:"ready"});
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<!-- xlsx.js (C) 2013-present  SheetJS http://sheetjs.com -->
 | 
			
		||||
<!-- sheetjs (C) 2013-present  SheetJS http://sheetjs.com -->
 | 
			
		||||
<!-- vim: set ts=2: -->
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<!-- xlsx.js (C) 2013-present  SheetJS http://sheetjs.com -->
 | 
			
		||||
<!-- sheetjs (C) 2013-present  SheetJS http://sheetjs.com -->
 | 
			
		||||
<!-- vim: set ts=2: -->
 | 
			
		||||
<html ng-app="sjs">
 | 
			
		||||
<head>
 | 
			
		||||
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB  | 
@ -3,156 +3,156 @@
 | 
			
		||||
<!-- vim: set ts=2: -->
 | 
			
		||||
<html lang="en" style="height: 100%">
 | 
			
		||||
<head>
 | 
			
		||||
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 | 
			
		||||
	<title>SheetJS React Demo</title>
 | 
			
		||||
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
 | 
			
		||||
	<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
 | 
			
		||||
	<script src="https://unpkg.com/react/umd/react.production.min.js"></script>
 | 
			
		||||
	<script src="https://unpkg.com/react-dom/umd/react-dom.production.min.js"></script>
 | 
			
		||||
	<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js"></script>
 | 
			
		||||
	<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
 | 
			
		||||
	<style>body, #app { height: 100%; }</style>
 | 
			
		||||
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 | 
			
		||||
  <title>SheetJS React Demo</title>
 | 
			
		||||
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
 | 
			
		||||
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
 | 
			
		||||
  <script src="https://unpkg.com/react/umd/react.production.min.js"></script>
 | 
			
		||||
  <script src="https://unpkg.com/react-dom/umd/react-dom.production.min.js"></script>
 | 
			
		||||
  <script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js"></script>
 | 
			
		||||
  <script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
 | 
			
		||||
  <style>body, #app { height: 100%; }</style>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
	<div class="container-fluid"><h1><a href="http://sheetjs.com">SheetJS × React Demo</a></h1><br /></div>
 | 
			
		||||
	<div id="app" class="container-fluid"></div>
 | 
			
		||||
	<script type="text/babel">
 | 
			
		||||
		/* sheetjs (C) 2013-present  SheetJS -- http://sheetjs.com */
 | 
			
		||||
		/* Notes:
 | 
			
		||||
			 - usage: `ReactDOM.render( <SheetJSApp />, document.getElementById('app') );`
 | 
			
		||||
			 - xlsx.full.min.js is loaded in the head of the HTML page
 | 
			
		||||
			 - this script should be referenced with type="text/babel"
 | 
			
		||||
			 - babel.js in-browser transpiler should be loaded before this script
 | 
			
		||||
		*/
 | 
			
		||||
		const { read, writeFile } = XLSX;
 | 
			
		||||
		const { decode_range, encode_col, sheet_to_json, aoa_to_sheet, book_new, book_append_sheet } = XLSX.utils;
 | 
			
		||||
  <div class="container-fluid"><h1><a href="http://sheetjs.com">SheetJS × React Demo</a></h1><br /></div>
 | 
			
		||||
  <div id="app" class="container-fluid"></div>
 | 
			
		||||
  <script type="text/babel">
 | 
			
		||||
    /* sheetjs (C) 2013-present  SheetJS -- http://sheetjs.com */
 | 
			
		||||
    /* Notes:
 | 
			
		||||
       - usage: `ReactDOM.render( <SheetJSApp />, document.getElementById('app') );`
 | 
			
		||||
       - xlsx.full.min.js is loaded in the head of the HTML page
 | 
			
		||||
       - this script should be referenced with type="text/babel"
 | 
			
		||||
       - babel.js in-browser transpiler should be loaded before this script
 | 
			
		||||
    */
 | 
			
		||||
    const { read, writeFile } = XLSX;
 | 
			
		||||
    const { decode_range, encode_col, sheet_to_json, aoa_to_sheet, book_new, book_append_sheet } = XLSX.utils;
 | 
			
		||||
 | 
			
		||||
		/* generate an array of column objects */
 | 
			
		||||
		const make_cols = refstr => Array.from({length: decode_range(refstr).e.c + 1}, (_, i) => ({ name: encode_col(i), key: i}));
 | 
			
		||||
    /* generate an array of column objects */
 | 
			
		||||
    const make_cols = refstr => Array.from({length: decode_range(refstr).e.c + 1}, (_, i) => ({ name: encode_col(i), key: i}));
 | 
			
		||||
 | 
			
		||||
		/* main component */
 | 
			
		||||
		function SheetJSApp() {
 | 
			
		||||
			const [data, setData] = React.useState([]);
 | 
			
		||||
			const [cols, setCols] = React.useState([]);
 | 
			
		||||
    /* main component */
 | 
			
		||||
    function SheetJSApp() {
 | 
			
		||||
      const [data, setData] = React.useState([]);
 | 
			
		||||
      const [cols, setCols] = React.useState([]);
 | 
			
		||||
 | 
			
		||||
			const handleFile = (file) => {
 | 
			
		||||
				const reader = new FileReader();
 | 
			
		||||
				reader.onload = (e) => {
 | 
			
		||||
					/* Parse data */
 | 
			
		||||
					const ab = e.target.result;
 | 
			
		||||
					const wb = read(ab, { type: 'array' });
 | 
			
		||||
					/* Get first worksheet */
 | 
			
		||||
					const wsname = wb.SheetNames[0];
 | 
			
		||||
					const ws = wb.Sheets[wsname];
 | 
			
		||||
					/* Convert array of arrays */
 | 
			
		||||
					const data = sheet_to_json(ws, { header: 1 });
 | 
			
		||||
					/* Update state */
 | 
			
		||||
					setData(data);
 | 
			
		||||
					setCols(make_cols(ws['!ref']))
 | 
			
		||||
				};
 | 
			
		||||
				reader.readAsArrayBuffer(file);
 | 
			
		||||
			}
 | 
			
		||||
      const handleFile = (file) => {
 | 
			
		||||
        const reader = new FileReader();
 | 
			
		||||
        reader.onload = (e) => {
 | 
			
		||||
          /* Parse data */
 | 
			
		||||
          const ab = e.target.result;
 | 
			
		||||
          const wb = read(ab, { type: 'array' });
 | 
			
		||||
          /* Get first worksheet */
 | 
			
		||||
          const wsname = wb.SheetNames[0];
 | 
			
		||||
          const ws = wb.Sheets[wsname];
 | 
			
		||||
          /* Convert array of arrays */
 | 
			
		||||
          const data = sheet_to_json(ws, { header: 1 });
 | 
			
		||||
          /* Update state */
 | 
			
		||||
          setData(data);
 | 
			
		||||
          setCols(make_cols(ws['!ref']))
 | 
			
		||||
        };
 | 
			
		||||
        reader.readAsArrayBuffer(file);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
			const exportFile = () => {
 | 
			
		||||
				/* convert state to workbook */
 | 
			
		||||
				const ws = aoa_to_sheet(data);
 | 
			
		||||
				const wb = book_new();
 | 
			
		||||
				book_append_sheet(wb, ws, "SheetJS");
 | 
			
		||||
				/* generate XLSX file and send to client */
 | 
			
		||||
				writeFile(wb, "sheetjs.xlsx")
 | 
			
		||||
			};
 | 
			
		||||
      const exportFile = () => {
 | 
			
		||||
        /* convert state to workbook */
 | 
			
		||||
        const ws = aoa_to_sheet(data);
 | 
			
		||||
        const wb = book_new();
 | 
			
		||||
        book_append_sheet(wb, ws, "SheetJS");
 | 
			
		||||
        /* generate XLSX file and send to client */
 | 
			
		||||
        writeFile(wb, "sheetjs.xlsx")
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
			return (
 | 
			
		||||
				<DragDropFile handleFile={handleFile}>
 | 
			
		||||
					<div className="row"><div className="col-xs-12">
 | 
			
		||||
						<DataInput handleFile={handleFile} />
 | 
			
		||||
					</div></div>
 | 
			
		||||
					<div className="row"><div className="col-xs-12">
 | 
			
		||||
						{data.length ? <button className="btn btn-success" onClick={exportFile}>Export</button> : ""}
 | 
			
		||||
					</div></div>
 | 
			
		||||
					<div className="row"><div className="col-xs-12">
 | 
			
		||||
						<OutTable data={data} cols={cols} />
 | 
			
		||||
					</div></div>
 | 
			
		||||
				</DragDropFile>
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
      return (
 | 
			
		||||
        <DragDropFile handleFile={handleFile}>
 | 
			
		||||
          <div className="row"><div className="col-xs-12">
 | 
			
		||||
            <DataInput handleFile={handleFile} />
 | 
			
		||||
          </div></div>
 | 
			
		||||
          <div className="row"><div className="col-xs-12">
 | 
			
		||||
            {data.length ? <button className="btn btn-success" onClick={exportFile}>Export</button> : ""}
 | 
			
		||||
          </div></div>
 | 
			
		||||
          <div className="row"><div className="col-xs-12">
 | 
			
		||||
            <OutTable data={data} cols={cols} />
 | 
			
		||||
          </div></div>
 | 
			
		||||
        </DragDropFile>
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		/* -------------------------------------------------------------------------- */
 | 
			
		||||
    /* -------------------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
			Simple HTML5 file drag-and-drop wrapper
 | 
			
		||||
			usage: <DragDropFile handleFile={handleFile}>...</DragDropFile>
 | 
			
		||||
				handleFile(file:File):void;
 | 
			
		||||
		*/
 | 
			
		||||
    /*
 | 
			
		||||
      Simple HTML5 file drag-and-drop wrapper
 | 
			
		||||
      usage: <DragDropFile handleFile={handleFile}>...</DragDropFile>
 | 
			
		||||
        handleFile(file:File):void;
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
		function DragDropFile({ handleFile, children }) {
 | 
			
		||||
			const suppress = (e) => { e.stopPropagation(); e.preventDefault(); };
 | 
			
		||||
			const handleDrop = (e) => {
 | 
			
		||||
				e.stopPropagation(); e.preventDefault();
 | 
			
		||||
				const files = e.dataTransfer.files;
 | 
			
		||||
				if (files && files[0]) handleFile(files[0]);
 | 
			
		||||
			};
 | 
			
		||||
    function DragDropFile({ handleFile, children }) {
 | 
			
		||||
      const suppress = (e) => { e.stopPropagation(); e.preventDefault(); };
 | 
			
		||||
      const handleDrop = (e) => {
 | 
			
		||||
        e.stopPropagation(); e.preventDefault();
 | 
			
		||||
        const files = e.dataTransfer.files;
 | 
			
		||||
        if (files && files[0]) handleFile(files[0]);
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
			return ( <div onDrop={handleDrop} onDragEnter={suppress} onDragOver={suppress}>{children}</div> );
 | 
			
		||||
		}
 | 
			
		||||
      return ( <div onDrop={handleDrop} onDragEnter={suppress} onDragOver={suppress}>{children}</div> );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
			Simple HTML5 file input wrapper
 | 
			
		||||
			usage: <DataInput handleFile={callback} />
 | 
			
		||||
				handleFile(file:File):void;
 | 
			
		||||
		*/
 | 
			
		||||
    /*
 | 
			
		||||
      Simple HTML5 file input wrapper
 | 
			
		||||
      usage: <DataInput handleFile={callback} />
 | 
			
		||||
        handleFile(file:File):void;
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
		function DataInput({ handleFile }) {
 | 
			
		||||
			const handleChange = (e) => {
 | 
			
		||||
				const files = e.target.files;
 | 
			
		||||
				if (files && files[0]) handleFile(files[0]);
 | 
			
		||||
			};
 | 
			
		||||
    function DataInput({ handleFile }) {
 | 
			
		||||
      const handleChange = (e) => {
 | 
			
		||||
        const files = e.target.files;
 | 
			
		||||
        if (files && files[0]) handleFile(files[0]);
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
			return (
 | 
			
		||||
				<form className="form-inline">
 | 
			
		||||
					<div className="form-group">
 | 
			
		||||
						<label htmlFor="file">Drag or choose a spreadsheet file</label><br />
 | 
			
		||||
						<input type="file" className="form-control" id="file" accept={SheetJSFT} onChange={handleChange} />
 | 
			
		||||
					</div>
 | 
			
		||||
				</form>
 | 
			
		||||
			)
 | 
			
		||||
		}
 | 
			
		||||
		/* list of supported file types */
 | 
			
		||||
		const SheetJSFT = [
 | 
			
		||||
			"xlsx", "xlsb", "xlsm", "xls", "xml", "csv", "txt", "ods", "fods", "uos", "sylk", "dif", "dbf", "prn", "qpw", "123", "wb*", "wq*", "html", "htm"
 | 
			
		||||
		].map(x => `.${x}`).join(",");
 | 
			
		||||
      return (
 | 
			
		||||
        <form className="form-inline">
 | 
			
		||||
          <div className="form-group">
 | 
			
		||||
            <label htmlFor="file">Drag or choose a spreadsheet file</label><br />
 | 
			
		||||
            <input type="file" className="form-control" id="file" accept={SheetJSFT} onChange={handleChange} />
 | 
			
		||||
          </div>
 | 
			
		||||
        </form>
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
    /* list of supported file types */
 | 
			
		||||
    const SheetJSFT = [
 | 
			
		||||
      "xlsx", "xlsb", "xlsm", "xls", "xml", "csv", "txt", "ods", "fods", "uos", "sylk", "dif", "dbf", "prn", "qpw", "123", "wb*", "wq*", "html", "htm"
 | 
			
		||||
    ].map(x => `.${x}`).join(",");
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
			Simple HTML Table
 | 
			
		||||
			usage: <OutTable data={data} cols={cols} />
 | 
			
		||||
				data:Array<Array<any> >;
 | 
			
		||||
				cols:Array<{name:string, key:number|string}>;
 | 
			
		||||
		*/
 | 
			
		||||
		function OutTable({ data, cols }) {
 | 
			
		||||
			return (
 | 
			
		||||
				<div className="table-responsive">
 | 
			
		||||
					<table className="table table-striped">
 | 
			
		||||
						<thead>
 | 
			
		||||
							<tr>{cols.map((c) => <th key={c.key}>{c.name}</th>)}</tr>
 | 
			
		||||
						</thead>
 | 
			
		||||
						<tbody>
 | 
			
		||||
							{data.map((r, i) => <tr key={i}>
 | 
			
		||||
								{cols.map(c => <td key={c.key}>{r[c.key]}</td>)}
 | 
			
		||||
							</tr>)}
 | 
			
		||||
						</tbody>
 | 
			
		||||
					</table>
 | 
			
		||||
				</div>
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
    /*
 | 
			
		||||
      Simple HTML Table
 | 
			
		||||
      usage: <OutTable data={data} cols={cols} />
 | 
			
		||||
        data:Array<Array<any> >;
 | 
			
		||||
        cols:Array<{name:string, key:number|string}>;
 | 
			
		||||
    */
 | 
			
		||||
    function OutTable({ data, cols }) {
 | 
			
		||||
      return (
 | 
			
		||||
        <div className="table-responsive">
 | 
			
		||||
          <table className="table table-striped">
 | 
			
		||||
            <thead>
 | 
			
		||||
              <tr>{cols.map((c) => <th key={c.key}>{c.name}</th>)}</tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
              {data.map((r, i) => <tr key={i}>
 | 
			
		||||
                {cols.map(c => <td key={c.key}>{r[c.key]}</td>)}
 | 
			
		||||
              </tr>)}
 | 
			
		||||
            </tbody>
 | 
			
		||||
          </table>
 | 
			
		||||
        </div>
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		/* React 18 uses ReactDOM.createRoot; < 18 should use ReactDOM.render */
 | 
			
		||||
		const root_elt = document.getElementById('app');
 | 
			
		||||
		if(typeof ReactDOM.createRoot !== "undefined") {
 | 
			
		||||
			const root = ReactDOM.createRoot(root_elt);
 | 
			
		||||
			root.render(<SheetJSApp/>);
 | 
			
		||||
		} else {
 | 
			
		||||
			ReactDOM.render(<SheetJSApp />, root_elt);
 | 
			
		||||
		}
 | 
			
		||||
	</script>
 | 
			
		||||
    /* React 18 uses ReactDOM.createRoot; < 18 should use ReactDOM.render */
 | 
			
		||||
    const root_elt = document.getElementById('app');
 | 
			
		||||
    if(typeof ReactDOM.createRoot !== "undefined") {
 | 
			
		||||
      const root = ReactDOM.createRoot(root_elt);
 | 
			
		||||
      root.render(<SheetJSApp/>);
 | 
			
		||||
    } else {
 | 
			
		||||
      ReactDOM.render(<SheetJSApp />, root_elt);
 | 
			
		||||
    }
 | 
			
		||||
  </script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										219
									
								
								docz/static/vtl/App.vue
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										219
									
								
								docz/static/vtl/App.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,219 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
/*! sheetjs (C) SheetJS -- http://sheetjs.com */
 | 
			
		||||
import { ref, onMounted } from "vue";
 | 
			
		||||
import VueTableLite from "vue3-table-lite/ts";
 | 
			
		||||
import { read, utils, WorkSheet, writeFile } from "xlsx";
 | 
			
		||||
 | 
			
		||||
type DataSet = { [index: string]: WorkSheet; };
 | 
			
		||||
type Row = any[];
 | 
			
		||||
type RowCB = (row: Row) => string;
 | 
			
		||||
type Column = { field: string; label: string; display: RowCB; };
 | 
			
		||||
type RowCol = { rows: Row[]; cols: Column[]; };
 | 
			
		||||
 | 
			
		||||
const currFileName = ref<string>("");
 | 
			
		||||
const currSheet = ref<string>("");
 | 
			
		||||
const sheets = ref<string[]>([]);
 | 
			
		||||
const workBook = ref<DataSet>({} as DataSet);
 | 
			
		||||
const rows = ref<Row[]>([]);
 | 
			
		||||
const columns = ref<Column[]>([]);
 | 
			
		||||
 | 
			
		||||
const exportTypes: string[] = ["xlsx", "xlsb", "csv", "html"];
 | 
			
		||||
 | 
			
		||||
let cell = 0;
 | 
			
		||||
 | 
			
		||||
function resetCell() {
 | 
			
		||||
  cell = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const getRowsCols = ( data: DataSet, sheetName: string ): RowCol => ({
 | 
			
		||||
  rows: utils.sheet_to_json<Row>(data[sheetName], {header:1}),
 | 
			
		||||
  cols: Array.from({
 | 
			
		||||
    length: utils.decode_range(data[sheetName]["!ref"]||"A1").e.c + 1
 | 
			
		||||
  }, (_, i) => (<Column>{ field: String(i), label: utils.encode_col(i), display: makeDisplay(i) }))
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const makeDisplay = (col: number): RowCB => (row: Row) => `<span
 | 
			
		||||
  style="user-select: none; display: block"
 | 
			
		||||
  onblur="endEdit(event)" ondblclick="startEdit(event)"
 | 
			
		||||
  position="${Math.floor(cell++ / columns.value.length)}.${col}"
 | 
			
		||||
  onkeydown="endEdit(event)">${row?.[col] ?? " "}</span>`;
 | 
			
		||||
 | 
			
		||||
(window as any).startEdit = function (ev: MouseEvent) {
 | 
			
		||||
  (ev?.target as HTMLSpanElement).contentEditable = "true";
 | 
			
		||||
  (ev?.target as HTMLSpanElement).focus();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
(window as any).endEdit = function (ev: FocusEvent | KeyboardEvent) {
 | 
			
		||||
  if (typeof (ev as KeyboardEvent).key == "undefined" || (ev as KeyboardEvent).key === "Enter") {
 | 
			
		||||
    const pos = (ev.target as HTMLSpanElement)?.getAttribute("position")?.split(".");
 | 
			
		||||
    if(!pos) return;
 | 
			
		||||
 | 
			
		||||
    (ev?.target as HTMLSpanElement).contentEditable = "true";
 | 
			
		||||
 | 
			
		||||
    rows.value[+pos[0]][+pos[1]] = (ev.target as HTMLSpanElement).innerText;
 | 
			
		||||
 | 
			
		||||
    workBook.value[currSheet.value] = utils.json_to_sheet(rows.value, {
 | 
			
		||||
      header: columns.value.map((col: Column) => col.field),
 | 
			
		||||
      skipHeader: true,
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
async function importAB(ab: ArrayBuffer, name: string): Promise<void> {
 | 
			
		||||
  const data = read(ab);
 | 
			
		||||
 | 
			
		||||
  currFileName.value = name;
 | 
			
		||||
  currSheet.value = data.SheetNames?.[0];
 | 
			
		||||
  sheets.value = data.SheetNames;
 | 
			
		||||
  workBook.value = data.Sheets;
 | 
			
		||||
 | 
			
		||||
  selectSheet(currSheet.value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function importFile(ev: Event): Promise<void> {
 | 
			
		||||
  const file = (ev.target as HTMLInputElement)?.files?.[0];
 | 
			
		||||
  if(!file) return;
 | 
			
		||||
  await importAB(await file.arrayBuffer(), file.name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function exportFile(type: string): void {
 | 
			
		||||
  const wb = utils.book_new();
 | 
			
		||||
 | 
			
		||||
  sheets.value.forEach((sheet) => {
 | 
			
		||||
    utils.book_append_sheet(wb, workBook.value[sheet], sheet);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  writeFile(wb, `sheet.${type}`);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function selectSheet(sheet: string): void {
 | 
			
		||||
  const { rows: newRows, cols: newCols } = getRowsCols(workBook.value, sheet);
 | 
			
		||||
 | 
			
		||||
  resetCell();
 | 
			
		||||
 | 
			
		||||
  rows.value = newRows;
 | 
			
		||||
  columns.value = newCols;
 | 
			
		||||
  currSheet.value = sheet;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Download from https://sheetjs.com/pres.numbers */
 | 
			
		||||
onMounted(async() => {
 | 
			
		||||
  const response = await fetch("https://sheetjs.com/pres.numbers");
 | 
			
		||||
  await importAB(await response.arrayBuffer(), "pres.numbers");
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <header class="imp-exp">
 | 
			
		||||
    <div class="import">
 | 
			
		||||
      <input type="file" id="import" @change="importFile" />
 | 
			
		||||
      <label for="import">import</label>
 | 
			
		||||
    </div>
 | 
			
		||||
    <span v-if="currFileName">{{ currFileName }}</span>
 | 
			
		||||
    <div class="export" v-if="currFileName">
 | 
			
		||||
      <span>export</span>
 | 
			
		||||
      <ul>
 | 
			
		||||
        <li v-for="(type, idx) in exportTypes" :key="idx" @click="exportFile(type)">
 | 
			
		||||
          {{ `.${type}` }}
 | 
			
		||||
        </li>
 | 
			
		||||
      </ul>
 | 
			
		||||
    </div>
 | 
			
		||||
  </header>
 | 
			
		||||
  <div class="sheets">
 | 
			
		||||
    <span
 | 
			
		||||
      v-for="(sheet, idx) in sheets"
 | 
			
		||||
      :key="idx"
 | 
			
		||||
      @click="selectSheet(sheet)"
 | 
			
		||||
      :class="[currSheet === sheet ? 'selected' : '']"
 | 
			
		||||
    >
 | 
			
		||||
      {{ sheet }}
 | 
			
		||||
    </span>
 | 
			
		||||
  </div>
 | 
			
		||||
  <vue-table-lite :is-static-mode="true" :page-size="50" :columns="columns" :rows="rows"></vue-table-lite>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
.imp-exp {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
  padding: 0.5rem;
 | 
			
		||||
  font-family: mono;
 | 
			
		||||
  color: #212529;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.import {
 | 
			
		||||
  font-size: medium;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.import input {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  opacity: 0;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.import label {
 | 
			
		||||
  background-color: white;
 | 
			
		||||
  border: 1px solid;
 | 
			
		||||
  padding: 0.3rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.export:hover {
 | 
			
		||||
  border-bottom: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.export:hover ul {
 | 
			
		||||
  display: block;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.export span {
 | 
			
		||||
  padding: 0.3rem;
 | 
			
		||||
  border: 1px solid;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.export ul {
 | 
			
		||||
  display: none;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  z-index: 5;
 | 
			
		||||
  background-color: white;
 | 
			
		||||
  list-style: none;
 | 
			
		||||
  padding: 0.3rem;
 | 
			
		||||
  border: 1px solid;
 | 
			
		||||
  margin-top: 0.3rem;
 | 
			
		||||
  border-top: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.export ul li {
 | 
			
		||||
  padding: 0.3rem;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.export ul li:hover {
 | 
			
		||||
  background-color: lightgray;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.sheets {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  margin: 0.3rem;
 | 
			
		||||
  color: #212529;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.sheets span {
 | 
			
		||||
  border: 1px solid;
 | 
			
		||||
  padding: 0.5rem;
 | 
			
		||||
  margin: 0.3rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.sheets span:hover:not(.selected) {
 | 
			
		||||
  background-color: lightgray;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.selected {
 | 
			
		||||
  background-color: #343a40;
 | 
			
		||||
  color: white;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										60
									
								
								docz/static/vue/SheetJS-vue.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										60
									
								
								docz/static/vue/SheetJS-vue.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,60 @@
 | 
			
		||||
/* sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */
 | 
			
		||||
var SheetJSFT = [
 | 
			
		||||
  "xlsx", "xlsb", "xlsm", "xls", "xml", "csv", "txt", "ods", "fods", "uos", "sylk", "dif", "dbf", "prn", "qpw", "123", "wb*", "wq*", "html", "htm", "numbers"
 | 
			
		||||
].map(function(x) { return "." + x; }).join(",");
 | 
			
		||||
 | 
			
		||||
var SJSTemplate = [
 | 
			
		||||
  '<div>',
 | 
			
		||||
    '<input type="file" multiple="false" id="sheetjs-input" accept="' + SheetJSFT + '" @change="onchange" />',
 | 
			
		||||
    '<br/>',
 | 
			
		||||
    '<button type="button" id="export-table" style="visibility:hidden" @click="onexport">Export to XLSX</button>',
 | 
			
		||||
    '<br/>',
 | 
			
		||||
    '<div id="out-table"></div>',
 | 
			
		||||
  '</div>'
 | 
			
		||||
].join("");
 | 
			
		||||
var component_struct = {
 | 
			
		||||
  template: SJSTemplate,
 | 
			
		||||
  methods: {
 | 
			
		||||
    onchange: function(evt) {
 | 
			
		||||
      var files = evt.target.files;
 | 
			
		||||
      if (!files || files.length == 0) return;
 | 
			
		||||
 | 
			
		||||
      var file = files[0];
 | 
			
		||||
 | 
			
		||||
      var reader = new FileReader();
 | 
			
		||||
      reader.onload = function (e) {
 | 
			
		||||
        // get data
 | 
			
		||||
        var bytes = new Uint8Array(e.target.result);
 | 
			
		||||
 | 
			
		||||
        /* read workbook */
 | 
			
		||||
        var wb = XLSX.read(bytes);
 | 
			
		||||
 | 
			
		||||
        /* grab first sheet */
 | 
			
		||||
        var wsname = wb.SheetNames[0];
 | 
			
		||||
        var ws = wb.Sheets[wsname];
 | 
			
		||||
 | 
			
		||||
        /* generate HTML */
 | 
			
		||||
        var HTML = XLSX.utils.sheet_to_html(ws);
 | 
			
		||||
 | 
			
		||||
        /* update table */
 | 
			
		||||
        document.getElementById('out-table').innerHTML = HTML;
 | 
			
		||||
        /* show export button */
 | 
			
		||||
        document.getElementById('export-table').style.visibility = "visible";
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      reader.readAsArrayBuffer(file);
 | 
			
		||||
    },
 | 
			
		||||
    onexport: function(evt) {
 | 
			
		||||
      /* generate workbook object from table */
 | 
			
		||||
      var wb = XLSX.utils.table_to_book(document.getElementById('out-table').getElementsByTagName("TABLE")[0]);
 | 
			
		||||
      /* generate file and force a download*/
 | 
			
		||||
      XLSX.writeFile(wb, "sheetjs.xlsx");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
if(Vue.component) {
 | 
			
		||||
  Vue.component('html-preview', component_struct);
 | 
			
		||||
} else {
 | 
			
		||||
  var app = Vue.createApp({});
 | 
			
		||||
  app.component('html-preview', component_struct);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										56
									
								
								docz/static/vue/index2.html
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										56
									
								
								docz/static/vue/index2.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<!-- sheetjs (C) 2013-present  SheetJS http://sheetjs.com -->
 | 
			
		||||
<!-- vim: set ts=2: -->
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
  <title>SheetJS + VueJS2</title>
 | 
			
		||||
  <!-- Vue 2 -->
 | 
			
		||||
  <script src="https://unpkg.com/vue@2.x"></script>
 | 
			
		||||
 | 
			
		||||
  <script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js"></script>
 | 
			
		||||
  <script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
 | 
			
		||||
 | 
			
		||||
  <!-- SheetJS Vue components -->
 | 
			
		||||
  <script src="SheetJS-vue.js"></script>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
.grid1 {
 | 
			
		||||
  width: 500px;
 | 
			
		||||
  height: 400px;
 | 
			
		||||
};
 | 
			
		||||
</style>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<pre>
 | 
			
		||||
<b><a href="http://sheetjs.com">SheetJS + VueJS2 demo</a></b>
 | 
			
		||||
 | 
			
		||||
This demo shows a sample Vue component "html-preview" that:
 | 
			
		||||
- displays a file input that accepts a spreadsheet file
 | 
			
		||||
- draws the first worksheet of a submitted file as HTML
 | 
			
		||||
- presents an export button to generate XLSX files
 | 
			
		||||
 | 
			
		||||
<a href="https://obamawhitehouse.archives.gov/sites/default/files/omb/budget/fy2014/assets/receipts.xls">Sample Spreadsheet</a>
 | 
			
		||||
</pre>
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
  var _gaq = _gaq || [];
 | 
			
		||||
  _gaq.push(['_setAccount', 'UA-36810333-1']);
 | 
			
		||||
  _gaq.push(['_trackPageview']);
 | 
			
		||||
 | 
			
		||||
  (function() {
 | 
			
		||||
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
 | 
			
		||||
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
 | 
			
		||||
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
 | 
			
		||||
  })();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div id="app">
 | 
			
		||||
  <html-preview></html-preview>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<script lang="javascript">
 | 
			
		||||
if(Vue.component) var app = new Vue({ el: '#app' });
 | 
			
		||||
else app.mount('#app');
 | 
			
		||||
</script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										56
									
								
								docz/static/vue/index3.html
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										56
									
								
								docz/static/vue/index3.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<!-- sheetjs (C) 2013-present  SheetJS http://sheetjs.com -->
 | 
			
		||||
<!-- vim: set ts=2: -->
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
  <title>SheetJS + VueJS3</title>
 | 
			
		||||
  <!-- Vue 2 -->
 | 
			
		||||
  <script src="https://unpkg.com/vue@3.x"></script>
 | 
			
		||||
 | 
			
		||||
  <script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js"></script>
 | 
			
		||||
  <script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
 | 
			
		||||
 | 
			
		||||
  <!-- SheetJS Vue components -->
 | 
			
		||||
  <script src="SheetJS-vue.js"></script>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
.grid1 {
 | 
			
		||||
  width: 500px;
 | 
			
		||||
  height: 400px;
 | 
			
		||||
};
 | 
			
		||||
</style>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<pre>
 | 
			
		||||
<b><a href="http://sheetjs.com">SheetJS + VueJS3 demo</a></b>
 | 
			
		||||
 | 
			
		||||
This demo shows a sample Vue component "html-preview" that:
 | 
			
		||||
- displays a file input that accepts a spreadsheet file
 | 
			
		||||
- draws the first worksheet of a submitted file as HTML
 | 
			
		||||
- presents an export button to generate XLSX files
 | 
			
		||||
 | 
			
		||||
<a href="https://obamawhitehouse.archives.gov/sites/default/files/omb/budget/fy2014/assets/receipts.xls">Sample Spreadsheet</a>
 | 
			
		||||
</pre>
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
  var _gaq = _gaq || [];
 | 
			
		||||
  _gaq.push(['_setAccount', 'UA-36810333-1']);
 | 
			
		||||
  _gaq.push(['_trackPageview']);
 | 
			
		||||
 | 
			
		||||
  (function() {
 | 
			
		||||
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
 | 
			
		||||
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
 | 
			
		||||
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
 | 
			
		||||
  })();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div id="app">
 | 
			
		||||
  <html-preview></html-preview>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<script lang="javascript">
 | 
			
		||||
if(Vue.component) var app = new Vue({ el: '#app' });
 | 
			
		||||
else app.mount('#app');
 | 
			
		||||
</script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										142
									
								
								docz/static/xspreadsheet/index.html
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										142
									
								
								docz/static/xspreadsheet/index.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,142 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<!-- sheetjs (C) SheetJS http://sheetjs.com -->
 | 
			
		||||
<!-- vim: set ts=2: -->
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 | 
			
		||||
<title>SheetJS + x-spreadsheet Live Demo</title>
 | 
			
		||||
<style>
 | 
			
		||||
#drop{
 | 
			
		||||
  border:2px dashed #bbb;
 | 
			
		||||
  -moz-border-radius:5px;
 | 
			
		||||
  -webkit-border-radius:5px;
 | 
			
		||||
  border-radius:5px;
 | 
			
		||||
  padding:25px;
 | 
			
		||||
  text-align:center;
 | 
			
		||||
  font:20pt bold,"Vollkorn";color:#bbb
 | 
			
		||||
}
 | 
			
		||||
#b64data{
 | 
			
		||||
  width:100%;
 | 
			
		||||
}
 | 
			
		||||
a { text-decoration: none }
 | 
			
		||||
</style>
 | 
			
		||||
<!-- x-spreadsheet stylesheet -->
 | 
			
		||||
<link rel="stylesheet" href="https://unpkg.com/x-data-spreadsheet/dist/xspreadsheet.css"/>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<pre>
 | 
			
		||||
<b><a href="http://sheetjs.com">SheetJS Data Preview Live Demo</a></b>
 | 
			
		||||
 | 
			
		||||
<a href="https://github.com/myliang/x-spreadsheet">x-spreadsheet component library</a>
 | 
			
		||||
 | 
			
		||||
<a href="https://github.com/SheetJS/sheetjs">Source Code Repo</a>
 | 
			
		||||
<a href="https://github.com/SheetJS/sheetjs/issues">Issues?  Something look weird?  Click here and report an issue</a>
 | 
			
		||||
 | 
			
		||||
<div id="drop">Drop a spreadsheet file here to see sheet data</div>
 | 
			
		||||
<input type="file" name="xlfile" id="xlf" /> ... or click here to select a file
 | 
			
		||||
<textarea id="b64data">... or paste a base64-encoding here</textarea>
 | 
			
		||||
</pre>
 | 
			
		||||
<p><input type="submit" value="Export to XLSX!" id="xport" onclick="export_xlsx();"></p>
 | 
			
		||||
<div id="htmlout"></div>
 | 
			
		||||
<br />
 | 
			
		||||
<script src="https://unpkg.com/x-data-spreadsheet/dist/xspreadsheet.js"></script>
 | 
			
		||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js"></script>
 | 
			
		||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
 | 
			
		||||
<script src="https://cdn.sheetjs.com/xspreadsheet/xlsxspread.min.js"></script>
 | 
			
		||||
<script>
 | 
			
		||||
/*jshint browser:true */
 | 
			
		||||
/* eslint-env browser */
 | 
			
		||||
/* eslint no-use-before-define:0 */
 | 
			
		||||
/*global Uint8Array, Uint16Array, ArrayBuffer */
 | 
			
		||||
/*global XLSX */
 | 
			
		||||
 | 
			
		||||
var HTMLOUT = document.getElementById('htmlout');
 | 
			
		||||
var xspr = x_spreadsheet(HTMLOUT);
 | 
			
		||||
HTMLOUT.style.height = (window.innerHeight - 400) + "px";
 | 
			
		||||
HTMLOUT.style.width = (window.innerWidth - 50) + "px";
 | 
			
		||||
 | 
			
		||||
var process_wb = (function() {
 | 
			
		||||
  var XPORT = document.getElementById('xport');
 | 
			
		||||
 | 
			
		||||
  return function process_wb(wb) {
 | 
			
		||||
    /* convert to x-spreadsheet form */
 | 
			
		||||
    var data = stox(wb);
 | 
			
		||||
 | 
			
		||||
    /* update x-spreadsheet */
 | 
			
		||||
    xspr.loadData(data);
 | 
			
		||||
    XPORT.disabled = false;
 | 
			
		||||
 | 
			
		||||
    if(typeof console !== 'undefined') console.log("output", new Date());
 | 
			
		||||
  };
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
var do_file = (function() {
 | 
			
		||||
  return function do_file(files) {
 | 
			
		||||
    var f = files[0];
 | 
			
		||||
    var reader = new FileReader();
 | 
			
		||||
    reader.onload = function(e) {
 | 
			
		||||
      if(typeof console !== 'undefined') console.log("onload", new Date());
 | 
			
		||||
      var data = e.target.result;
 | 
			
		||||
      process_wb(XLSX.read(data));
 | 
			
		||||
    };
 | 
			
		||||
    reader.readAsArrayBuffer(f);
 | 
			
		||||
  };
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
(function() {
 | 
			
		||||
  var drop = document.getElementById('drop');
 | 
			
		||||
  if(!drop.addEventListener) return;
 | 
			
		||||
 | 
			
		||||
  function handleDrop(e) {
 | 
			
		||||
    e.stopPropagation();
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
    do_file(e.dataTransfer.files);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function handleDragover(e) {
 | 
			
		||||
    e.stopPropagation();
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
    e.dataTransfer.dropEffect = 'copy';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  drop.addEventListener('dragenter', handleDragover, false);
 | 
			
		||||
  drop.addEventListener('dragover', handleDragover, false);
 | 
			
		||||
  drop.addEventListener('drop', handleDrop, false);
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
(function() {
 | 
			
		||||
  var xlf = document.getElementById('xlf');
 | 
			
		||||
  if(!xlf.addEventListener) return;
 | 
			
		||||
  function handleFile(e) { do_file(e.target.files); }
 | 
			
		||||
  xlf.addEventListener('change', handleFile, false);
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
(function() {
 | 
			
		||||
  try {
 | 
			
		||||
    fetch("https://sheetjs.com/pres.numbers")
 | 
			
		||||
      .then(function(res) { return res.arrayBuffer(); })
 | 
			
		||||
      .then(function(ab) { process_wb(XLSX.read(ab)); });
 | 
			
		||||
  } catch(e) {}
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
function export_xlsx() {
 | 
			
		||||
  var new_wb = xtos(xspr.getData());
 | 
			
		||||
 | 
			
		||||
  /* write file and trigger a download */
 | 
			
		||||
  XLSX.writeFile(new_wb, 'sheetjs.xlsx', {});
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
/* eslint no-use-before-define:0 */
 | 
			
		||||
  var _gaq = _gaq || [];
 | 
			
		||||
  _gaq.push(['_setAccount', 'UA-36810333-1']);
 | 
			
		||||
  _gaq.push(['_trackPageview']);
 | 
			
		||||
 | 
			
		||||
  (function() {
 | 
			
		||||
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
 | 
			
		||||
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
 | 
			
		||||
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
 | 
			
		||||
  })();
 | 
			
		||||
</script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user