Handsontable legacy
This commit is contained in:
parent
a881bc8924
commit
1241cd92d7
@ -39,6 +39,7 @@ This demo was tested in the following configurations:
|
||||
| NVIDIA RTX PRO 6000 (96 GB VRAM) + Ryzen Z2 Go (32 GB RAM) | `linux-x64` | Ollama | 2025-11-15 |
|
||||
| NVIDIA RTX 5090 (32 GB VRAM) + Ryzen AI Z2 Extreme (24 GB RAM) | `win11-x64` | `llama.cpp` | 2026-05-05 |
|
||||
| NVIDIA RTX 5090 (32 GB VRAM) + Ryzen Z2 Go (32 GB RAM) | `linux-x64` | Ollama | 2025-11-15 |
|
||||
| NVIDIA RTX 5060 Ti (16 GB VRAM) + Ryzen Z2 Extreme (32 GB RAM) | `win11-x64` | `llama.cpp` | 2026-06-05 |
|
||||
| AMD AI PRO R9700 (32 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | Ollama | 2026-01-17 |
|
||||
| AMD AI PRO R9700 (32 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | Ollama | 2026-01-17 |
|
||||
| AMD RX 9070 XT (16 GB VRAM) + Ryzen Z2 Go (32 GB RAM) | `win11-x64` | Ollama | 2026-01-17 |
|
||||
|
||||
228
docz/docs/03-demos/04-grid/05-handsontable.md
Normal file
228
docz/docs/03-demos/04-grid/05-handsontable.md
Normal file
@ -0,0 +1,228 @@
|
||||
---
|
||||
title: Handsontable
|
||||
pagination_prev: demos/frontend/index
|
||||
pagination_next: demos/net/index
|
||||
---
|
||||
|
||||
<head>
|
||||
<script src="https://cdn.jsdelivr.net/npm/handsontable@6.2.2/dist/handsontable.full.js"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable@6.2.2/dist/handsontable.full.css"/>
|
||||
</head>
|
||||
|
||||
import current from '/version.js';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
:::danger pass
|
||||
|
||||
**Handsontable has relicensed away from open source!**
|
||||
|
||||
The original MIT license still applies to version `6.2.2`.
|
||||
|
||||
After adding the new `licenseKey` requirement, basic integrations still work
|
||||
with version `17.1.0`.
|
||||
|
||||
:::
|
||||
|
||||
[Handsontable](https://handsontable.com/) is a robust JavaScript data grid.
|
||||
|
||||
The following live integrations use the standalone build:
|
||||
|
||||
- [Version `6.2.2` (MIT Licensed)](pathname:///handsontable/)
|
||||
- [Version `17.1.0` (Proprietary)](pathname:///handsontable/non-oss.html)
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Browser | Date |
|
||||
|:-------------|:-----------|
|
||||
| Chromium 148 | 2026-06-09 |
|
||||
| Safari 18.2 | 2026-06-09 |
|
||||
|
||||
:::
|
||||
|
||||
:::tip pass
|
||||
|
||||
This demo barely scratches the surface. The underlying grid component includes
|
||||
many additional features that work with [SheetJS Pro](https://sheetjs.com/pro).
|
||||
|
||||
:::
|
||||
|
||||
## Integration Details
|
||||
|
||||
[The "Frameworks" section](/docs/getting-started/installation/frameworks) covers
|
||||
installation with Yarn and other package managers.
|
||||
|
||||
Using the `npm` tool, the following command installs SheetJS and Handsontable:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz handsontable@6.2.2`}
|
||||
</CodeBlock>
|
||||
|
||||
Methods and components in both libraries can be loaded in pages using `import`:
|
||||
|
||||
```js
|
||||
import { read, utils, writeFile } from 'xlsx';
|
||||
import Handsontable from 'handsontable';
|
||||
import 'handsontable/dist/handsontable.css'
|
||||
```
|
||||
|
||||
:::info pass
|
||||
|
||||
Official framework wrapper packages (e.g. `@handsontable/react-wrapper`) should
|
||||
be used in greenfield projects, as they encapsulate best practices.
|
||||
|
||||
Due to framework volatility, the pre-baked integrations may not work with older
|
||||
versions of ReactJS.
|
||||
|
||||
:::
|
||||
|
||||
### Internal State
|
||||
|
||||
Handsontable uses [arrays of arrays](/docs/api/utilities/array#array-of-arrays)
|
||||
under the hood by default. This is the most flexible approach for processing
|
||||
arbitrary data.
|
||||
|
||||
If a schema is passed when the table is constructed, Handsontable will use
|
||||
[arrays of objects](/docs/api/utilities/array#arrays-of-objects) instead[^1].
|
||||
|
||||
### Reading Data
|
||||
|
||||
The SheetJS [`read`](/docs/api/parse-options) function processes file data and
|
||||
returns a [workbook object](/docs/csf/book). After selecting a worksheet, the
|
||||
[`sheet_to_json` method](/docs/api/utilities/array#array-output) can return an
|
||||
array of arrays or array of objects.
|
||||
|
||||
The result of `sheet_to_json` can be passed directly to the `loadData` method[^2]
|
||||
of a Handsontable instance.
|
||||
|
||||
The following snippet fetches a file, extracts data from the first worksheet,
|
||||
and passes the data to the grid:
|
||||
|
||||
```js
|
||||
import { read, utils } from 'xlsx';
|
||||
import Handsontable from 'handsontable';
|
||||
|
||||
/* `hot` is assumed to be the Handsontable instance */
|
||||
// const hot = new Handsontable(/* ... */);
|
||||
|
||||
async function fetch_and_view_first_sheet() {
|
||||
/* fetch and parse https://docs.sheetjs.com/pres.numbers */
|
||||
const file = await (await fetch("https://docs.sheetjs.com/pres.numbers")).arrayBuffer();
|
||||
const wb = read(file);
|
||||
|
||||
// highlight-start
|
||||
/* Generate an array of arrays from the first worksheet */
|
||||
const first_sheet = wb.Sheets[wb.SheetNames[0]];
|
||||
const aoa = utils.sheet_to_json(first_sheet, { header: 1 });
|
||||
|
||||
/* load data into Handsontable instance */
|
||||
hot.loadData(aoa);
|
||||
// highlight-end
|
||||
}
|
||||
```
|
||||
|
||||
### Writing Data
|
||||
|
||||
The `getData` method[^3] of a Handsontable instance returns the current data. By
|
||||
default, the method returns an array of arrays.
|
||||
|
||||
The SheetJS [`aoa_to_sheet`](/docs/api/utilities/array#array-of-arrays-input)
|
||||
method generates a worksheet object from the data. After creating a new workbook
|
||||
with [`book_new`](/docs/api/utilities/wb), [`writeFile`](/docs/api/write-options)
|
||||
|
||||
The following snippet pulls data from the grid and exports to `SheetJSHOT.xlsx`:
|
||||
|
||||
```js
|
||||
import { utils, writeFile } from 'xlsx';
|
||||
import Handsontable from 'handsontable';
|
||||
|
||||
function export_data_to_xlsx(hot) {
|
||||
/* pull data from the Handsontable instance */
|
||||
const aoa = hot.getData();
|
||||
|
||||
/* generate a SheetJS worksheet object */
|
||||
const ws = utils.aoa_to_sheet(aoa);
|
||||
|
||||
/* generate a single-sheet workbook and export to SheetJSHOT.xlsx */
|
||||
const wb = utils.book_new(ws, "Exported Data");
|
||||
writeFile(wb, "SheetJSHOT.xlsx");
|
||||
}
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
For framework-native state management, the recommended approach is to listen for
|
||||
grid events and explicitly update a separate copy of the data[^4].
|
||||
|
||||
:::
|
||||
|
||||
## Demo
|
||||
|
||||
This sample ReactJS-powered site uses SheetJS and Handsontable to display data
|
||||
from a [sample NUMBERS spreadsheet](pathname:///pres.numbers) and export data
|
||||
to a new file.
|
||||
|
||||
1) Create a new project from the ViteJS `react-ts` template:
|
||||
|
||||
```bash
|
||||
npm create vite@latest -- sheetjs-hot --template react-ts --no-interactive
|
||||
cd sheetjs-hot
|
||||
npm i
|
||||
```
|
||||
|
||||
2) Install SheetJS and Handsontable libraries:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz handsontable@6.2.2`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Start the dev server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
The terminal window will display a URL (typically `http://localhost:5173`).
|
||||
Open the URL with a web browser and confirm that a page loads.
|
||||
|
||||
4) Download [`App.tsx`](pathname:///handsontable/App.tsx) and replace `src/App.tsx`:
|
||||
|
||||
```bash
|
||||
curl -L -o src/App.tsx https://docs.sheetjs.com/handsontable/App.tsx
|
||||
```
|
||||
|
||||
#### Testing
|
||||
|
||||
5) Refresh the browser window. A grid and two buttons should be visible:
|
||||
|
||||

|
||||
|
||||
6) Press the "Fetch File" button. The grid will refresh with Presidential data:
|
||||
|
||||

|
||||
|
||||
7) Make some changes to the grid data.
|
||||
|
||||
:::note pass
|
||||
|
||||
Some statisticians believe President Grover Cleveland should be counted once.
|
||||
That would imply President Clinton should be index 41 and the indices of the
|
||||
other presidents should be decremented.
|
||||
|
||||
:::
|
||||
|
||||
Double-click on each cell in the Index column and decrement each value. The new
|
||||
values should be 41, 42, 43, 44, and 45, as shown in the screenshot below:
|
||||
|
||||

|
||||
|
||||
8) Click on the "Download" button. The browser should attempt to download a new
|
||||
spreadsheet (`SheetJSHOT.xlsx`). Save the file.
|
||||
|
||||
Open the generated file and verify the contents match the grid.
|
||||
|
||||
[^1]: See ["Array of Objects" in the "Data management"](https://handsontable.com/docs/javascript-data-grid/binding-to-data/#array-of-objects) section of the Handsontable documentation for more details.
|
||||
[^2]: See [`loadData`](https://handsontable.com/docs/javascript-data-grid/api/core/#loaddata) in the Handsontable API documentation for more details.
|
||||
[^3]: See [`getData`](https://handsontable.com/docs/javascript-data-grid/api/core/#getdata) in the Handsontable API documentation for more details.
|
||||
[^4]: See ["Events and hooks" in the "Data management"](https://handsontable.com/docs/javascript-data-grid/events-and-hooks/) section of the Handsontable documentation for more details.
|
||||
@ -54,6 +54,12 @@ through a special Export button. It handles the SheetJS operations internally.
|
||||
|
||||
**[The exposition has been moved to a separate page.](/docs/demos/grid/tabulator)**
|
||||
|
||||
#### Handsontable
|
||||
|
||||
[Click here for a live integration demo.](pathname:///handsontable/)
|
||||
|
||||
**[The exposition has been moved to a separate page.](/docs/demos/grid/handsontable)**
|
||||
|
||||
#### Angular UI Grid
|
||||
|
||||
:::danger pass
|
||||
|
||||
@ -21,8 +21,8 @@ MongoDB wire protocol.
|
||||
|
||||
:::
|
||||
|
||||
[FerretDB](https://www.ferretdb.com/) is an Apache 2.0-licensed document database
|
||||
that implements the MongoDB wire protocol using PostgreSQL or SQLite as the backend.
|
||||
[FerretDB](https://docs.ferretdb.io) is an Apache 2.0-licensed document database
|
||||
that implements the MongoDB wire protocol using a PostgreSQL or SQLite backend.
|
||||
|
||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
||||
data from spreadsheets.
|
||||
|
||||
@ -41,7 +41,7 @@ This demo was tested in the following deployments:
|
||||
|:---------------|:-------------|:-----------|:-----------|
|
||||
| macOS 15.3 | `darwin-x64` | 16.95.4 | 2025-04-17 |
|
||||
| macOS 14.5 | `darwin-arm` | 16.106.3 | 2026-05-05 |
|
||||
| Windows 11 | `win11-x64` | 365 (2506) | 2025-06-17 |
|
||||
| Windows 11 | `win11-x64` | 365 (2604) | 2026-06-05 |
|
||||
| Windows 11 | `win11-arm` | 365 (2503) | 2025-04-24 |
|
||||
|
||||
:::
|
||||
|
||||
45
docz/static/handsontable/App.tsx
Normal file
45
docz/static/handsontable/App.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { read, utils, writeFile } from 'xlsx';
|
||||
import Handsontable from 'handsontable';
|
||||
import 'handsontable/dist/handsontable.css'
|
||||
import './App.css';
|
||||
|
||||
function App() {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [hot, setHot] = useState<Handsontable>();
|
||||
|
||||
useEffect(() => {
|
||||
if(!ref || !ref.current) return;
|
||||
const _hot = new Handsontable(ref.current, {
|
||||
data: [ ["Sheet", "JS", ""], ["Hands", "on", "Table"] ],
|
||||
rowHeaders: true, colHeaders: true, height: 600, width: 800
|
||||
});
|
||||
setHot(_hot);
|
||||
return () => { if(hot && !hot.isDestroyed) hot.destroy() };
|
||||
}, []);
|
||||
|
||||
const fetchFile = async() => {
|
||||
const ab = await (await fetch("https://docs.sheetjs.com/pres.numbers")).arrayBuffer();
|
||||
const wb = read(ab);
|
||||
const ws = wb.Sheets[wb.SheetNames[0]];
|
||||
const aoa = utils.sheet_to_json<any[]>(ws, { header: 1 });
|
||||
hot.loadData(aoa);
|
||||
};
|
||||
|
||||
const download = async() => {
|
||||
if(!hot) return;
|
||||
const ws = utils.aoa_to_sheet(hot.getData());
|
||||
const wb = utils.book_new(ws);
|
||||
writeFile(wb, "SheetJSHOT.xlsx");
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<button onClick={fetchFile}>Fetch File</button>
|
||||
<button onClick={download}>Download</button>
|
||||
<div ref={ref}/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
164
docz/static/handsontable/index.html
Normal file
164
docz/static/handsontable/index.html
Normal file
@ -0,0 +1,164 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- sheetjs (C) SheetJS https://sheetjs.com -->
|
||||
<!-- vim: set ts=2: -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="robots" content="noindex"/>
|
||||
<title>SheetJS + Handsontable 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>
|
||||
<!-- Handsontable stylesheet -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable@6.2.2/dist/handsontable.full.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<pre>
|
||||
<b><a href="https://sheetjs.com">SheetJS + Handsontable Demo</a></b>
|
||||
|
||||
<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();" disabled></p>
|
||||
<div id="htmlout"></div>
|
||||
<br />
|
||||
<script src="https://cdn.jsdelivr.net/npm/handsontable@6.2.2/dist/handsontable.full.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>
|
||||
/*jshint browser:true */
|
||||
/* eslint-env browser */
|
||||
/* eslint no-use-before-define:0 */
|
||||
/*global Uint8Array, Uint16Array, ArrayBuffer */
|
||||
/*global XLSX, Handsontable */
|
||||
|
||||
var hot;
|
||||
|
||||
var process_wb = (function() {
|
||||
var XPORT = document.getElementById('xport');
|
||||
var HTMLOUT = document.getElementById('htmlout');
|
||||
|
||||
return function process_wb(wb) {
|
||||
/* get data */
|
||||
var ws = wb.Sheets[wb.SheetNames[0]];
|
||||
var data = XLSX.utils.sheet_to_json(ws, {header:1});
|
||||
|
||||
/* destroy existing instance if any */
|
||||
if(hot) hot.destroy();
|
||||
|
||||
/* create handsontable instance */
|
||||
hot = new Handsontable(HTMLOUT, {
|
||||
data: data,
|
||||
rowHeaders: true,
|
||||
colHeaders: true
|
||||
});
|
||||
|
||||
HTMLOUT.style.height = (window.innerHeight - 400) + "px";
|
||||
HTMLOUT.style.width = (window.innerWidth - 50) + "px";
|
||||
|
||||
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);
|
||||
})();
|
||||
|
||||
var export_xlsx = (function() {
|
||||
function prep(arr) {
|
||||
var out = [];
|
||||
for(var i = 0; i < arr.length; ++i) {
|
||||
if(!arr[i]) continue;
|
||||
if(Array.isArray(arr[i])) { out[i] = arr[i]; continue };
|
||||
var o = new Array();
|
||||
Object.keys(arr[i]).forEach(function(k) { o[+k] = arr[i][k] });
|
||||
out[i] = o;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
return function export_xlsx() {
|
||||
if(!hot) return;
|
||||
/* convert handsontable data to worksheet */
|
||||
var new_ws = XLSX.utils.aoa_to_sheet(prep(hot.getData()));
|
||||
|
||||
/* build workbook */
|
||||
var new_wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(new_wb, new_ws, 'SheetJS');
|
||||
|
||||
/* write file and trigger a download */
|
||||
XLSX.writeFile(new_wb, 'SheetJSHandsontableExport.xlsx', {bookSST:true});
|
||||
};
|
||||
})();
|
||||
|
||||
(async() => {
|
||||
const ab = await(await fetch("https://docs.sheetjs.com/pres.numbers")).arrayBuffer();
|
||||
process_wb(XLSX.read(ab));
|
||||
})();
|
||||
</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>
|
||||
BIN
docz/static/handsontable/intra.png
Normal file
BIN
docz/static/handsontable/intra.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
165
docz/static/handsontable/non-oss.html
Normal file
165
docz/static/handsontable/non-oss.html
Normal file
@ -0,0 +1,165 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- sheetjs (C) SheetJS https://sheetjs.com -->
|
||||
<!-- vim: set ts=2: -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="robots" content="noindex"/>
|
||||
<title>SheetJS + Handsontable 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>
|
||||
<!-- Handsontable stylesheet -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable@17.1.0/styles/handsontable.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<pre>
|
||||
<b><a href="https://sheetjs.com">SheetJS + Handsontable Demo</a></b>
|
||||
|
||||
<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();" disabled></p>
|
||||
<div id="htmlout"></div>
|
||||
<br />
|
||||
<script src="https://cdn.jsdelivr.net/npm/handsontable@17.1.0/dist/handsontable.full.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>
|
||||
/*jshint browser:true */
|
||||
/* eslint-env browser */
|
||||
/* eslint no-use-before-define:0 */
|
||||
/*global Uint8Array, Uint16Array, ArrayBuffer */
|
||||
/*global XLSX, Handsontable */
|
||||
|
||||
var hot;
|
||||
|
||||
var process_wb = (function() {
|
||||
var XPORT = document.getElementById('xport');
|
||||
var HTMLOUT = document.getElementById('htmlout');
|
||||
|
||||
return function process_wb(wb) {
|
||||
/* get data */
|
||||
var ws = wb.Sheets[wb.SheetNames[0]];
|
||||
var data = XLSX.utils.sheet_to_json(ws, {header:1});
|
||||
|
||||
/* destroy existing instance if any */
|
||||
if(hot) hot.destroy();
|
||||
|
||||
/* create handsontable instance */
|
||||
hot = new Handsontable(HTMLOUT, {
|
||||
data: data,
|
||||
rowHeaders: true,
|
||||
colHeaders: true,
|
||||
licenseKey: 'non-commercial-and-evaluation'
|
||||
});
|
||||
|
||||
HTMLOUT.style.height = (window.innerHeight - 400) + "px";
|
||||
HTMLOUT.style.width = (window.innerWidth - 50) + "px";
|
||||
|
||||
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);
|
||||
})();
|
||||
|
||||
var export_xlsx = (function() {
|
||||
function prep(arr) {
|
||||
var out = [];
|
||||
for(var i = 0; i < arr.length; ++i) {
|
||||
if(!arr[i]) continue;
|
||||
if(Array.isArray(arr[i])) { out[i] = arr[i]; continue };
|
||||
var o = new Array();
|
||||
Object.keys(arr[i]).forEach(function(k) { o[+k] = arr[i][k] });
|
||||
out[i] = o;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
return function export_xlsx() {
|
||||
if(!hot) return;
|
||||
/* convert handsontable data to worksheet */
|
||||
var new_ws = XLSX.utils.aoa_to_sheet(prep(hot.getData()));
|
||||
|
||||
/* build workbook */
|
||||
var new_wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(new_wb, new_ws, 'SheetJS');
|
||||
|
||||
/* write file and trigger a download */
|
||||
XLSX.writeFile(new_wb, 'SheetJSHandsontableExport.xlsx', {bookSST:true});
|
||||
};
|
||||
})();
|
||||
|
||||
(async() => {
|
||||
const ab = await(await fetch("https://docs.sheetjs.com/pres.numbers")).arrayBuffer();
|
||||
process_wb(XLSX.read(ab));
|
||||
})();
|
||||
</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>
|
||||
BIN
docz/static/handsontable/post.png
Normal file
BIN
docz/static/handsontable/post.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
BIN
docz/static/handsontable/pre.png
Normal file
BIN
docz/static/handsontable/pre.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
docz/static/mathematica/PasteEscapeString.png
Normal file
BIN
docz/static/mathematica/PasteEscapeString.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 301 KiB |
Loading…
Reference in New Issue
Block a user