forked from sheetjs/docs.sheetjs.com
305 lines
9.8 KiB
Markdown
305 lines
9.8 KiB
Markdown
|
### Generating JSON and JS Data
|
||
|
|
||
|
JSON and JS data tend to represent single worksheets. The utility functions in
|
||
|
this section work with single worksheets.
|
||
|
|
||
|
The ["Common Spreadsheet Format"](#common-spreadsheet-format) section describes
|
||
|
the object structure in more detail. `workbook.SheetNames` is an ordered list
|
||
|
of the worksheet names. `workbook.Sheets` is an object whose keys are sheet
|
||
|
names and whose values are worksheet objects.
|
||
|
|
||
|
The "first worksheet" is stored at `workbook.Sheets[workbook.SheetNames[0]]`.
|
||
|
|
||
|
**API**
|
||
|
|
||
|
_Create an array of JS objects from a worksheet_
|
||
|
|
||
|
```js
|
||
|
var jsa = XLSX.utils.sheet_to_json(worksheet, opts);
|
||
|
```
|
||
|
|
||
|
_Create an array of arrays of JS values from a worksheet_
|
||
|
|
||
|
```js
|
||
|
var aoa = XLSX.utils.sheet_to_json(worksheet, {...opts, header: 1});
|
||
|
```
|
||
|
|
||
|
The `sheet_to_json` utility function walks a workbook in row-major order,
|
||
|
generating an array of objects. The second `opts` argument controls a number of
|
||
|
export decisions including the type of values (JS values or formatted text). The
|
||
|
["JSON"](#json) section describes the argument in more detail.
|
||
|
|
||
|
By default, `sheet_to_json` scans the first row and uses the values as headers.
|
||
|
With the `header: 1` option, the function exports an array of arrays of values.
|
||
|
|
||
|
**Examples**
|
||
|
|
||
|
[`x-spreadsheet`](https://github.com/myliang/x-spreadsheet) is an interactive
|
||
|
data grid for previewing and modifying structured data in the web browser. The
|
||
|
[`xspreadsheet` demo](/demos/xspreadsheet) includes a sample script with the
|
||
|
`stox` function for converting from a workbook to x-spreadsheet data object.
|
||
|
<https://oss.sheetjs.com/sheetjs/x-spreadsheet> is a live demo.
|
||
|
|
||
|
<details>
|
||
|
<summary><b>Previewing data in a React data grid</b> (click to show)</summary>
|
||
|
|
||
|
[`react-data-grid`](https://npm.im/react-data-grid) is a data grid tailored for
|
||
|
react. It expects two properties: `rows` of data objects and `columns` which
|
||
|
describe the columns. For the purposes of massaging the data to fit the react
|
||
|
data grid API it is easiest to start from an array of arrays.
|
||
|
|
||
|
This demo starts by fetching a remote file and using `XLSX.read` to extract:
|
||
|
|
||
|
```js
|
||
|
import { useEffect, useState } from "react";
|
||
|
import DataGrid from "react-data-grid";
|
||
|
import { read, utils } from "xlsx";
|
||
|
|
||
|
const url = "https://oss.sheetjs.com/test_files/RkNumber.xls";
|
||
|
|
||
|
export default function App() {
|
||
|
const [columns, setColumns] = useState([]);
|
||
|
const [rows, setRows] = useState([]);
|
||
|
useEffect(() => {(async () => {
|
||
|
const wb = read(await (await fetch(url)).arrayBuffer(), { WTF: 1 });
|
||
|
|
||
|
/* use sheet_to_json with header: 1 to generate an array of arrays */
|
||
|
const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], { header: 1 });
|
||
|
|
||
|
/* see react-data-grid docs to understand the shape of the expected data */
|
||
|
setColumns(data[0].map((r) => ({ key: r, name: r })));
|
||
|
setRows(data.slice(1).map((r) => r.reduce((acc, x, i) => {
|
||
|
acc[data[0][i]] = x;
|
||
|
return acc;
|
||
|
}, {})));
|
||
|
})(); });
|
||
|
|
||
|
return <DataGrid columns={columns} rows={rows} />;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
</details>
|
||
|
|
||
|
<details>
|
||
|
<summary><b>Previewing data in a VueJS data grid</b> (click to show)</summary>
|
||
|
|
||
|
[`vue3-table-lite`](https://github.com/linmasahiro/vue3-table-lite) is a simple
|
||
|
VueJS 3 data table. It is featured [in the VueJS demo](/demos/vue/modify/).
|
||
|
|
||
|
</details>
|
||
|
|
||
|
<details>
|
||
|
<summary><b>Populating a database (SQL or no-SQL)</b> (click to show)</summary>
|
||
|
|
||
|
The [`database` demo](/demos/database/) includes examples of working with
|
||
|
databases and query results.
|
||
|
|
||
|
</details>
|
||
|
|
||
|
<details>
|
||
|
<summary><b>Numerical Computations with TensorFlow.js</b> (click to show)</summary>
|
||
|
|
||
|
[`@tensorflow/tfjs`](@tensorflow/tfjs) and other libraries expect data in simple
|
||
|
arrays, well-suited for worksheets where each column is a data vector. That is
|
||
|
the transpose of how most people use spreadsheets, where each row is a vector.
|
||
|
|
||
|
A single `Array#map` can pull individual named rows from `sheet_to_json` export:
|
||
|
|
||
|
```js
|
||
|
const XLSX = require("xlsx");
|
||
|
const tf = require('@tensorflow/tfjs');
|
||
|
|
||
|
const key = "age"; // this is the field we want to pull
|
||
|
const ages = XLSX.utils.sheet_to_json(worksheet).map(r => r[key]);
|
||
|
const tf_data = tf.tensor1d(ages);
|
||
|
```
|
||
|
|
||
|
All fields can be processed at once using a transpose of the 2D tensor generated
|
||
|
with the `sheet_to_json` export with `header: 1`. The first row, if it contains
|
||
|
header labels, should be removed with a slice:
|
||
|
|
||
|
```js
|
||
|
const XLSX = require("xlsx");
|
||
|
const tf = require('@tensorflow/tfjs');
|
||
|
|
||
|
/* array of arrays of the data starting on the second row */
|
||
|
const aoa = XLSX.utils.sheet_to_json(worksheet, {header: 1}).slice(1);
|
||
|
/* dataset in the "correct orientation" */
|
||
|
const tf_dataset = tf.tensor2d(aoa).transpose();
|
||
|
/* pull out each dataset with a slice */
|
||
|
const tf_field0 = tf_dataset.slice([0,0], [1,tensor.shape[1]]).flatten();
|
||
|
const tf_field1 = tf_dataset.slice([1,0], [1,tensor.shape[1]]).flatten();
|
||
|
```
|
||
|
|
||
|
The [`array` demo](demos/array/) shows a complete example.
|
||
|
|
||
|
</details>
|
||
|
|
||
|
|
||
|
### Generating HTML Tables
|
||
|
|
||
|
**API**
|
||
|
|
||
|
_Generate HTML Table from Worksheet_
|
||
|
|
||
|
```js
|
||
|
var html = XLSX.utils.sheet_to_html(worksheet);
|
||
|
```
|
||
|
|
||
|
The `sheet_to_html` utility function generates HTML code based on the worksheet
|
||
|
data. Each cell in the worksheet is mapped to a `<TD>` element. Merged cells
|
||
|
in the worksheet are serialized by setting `colspan` and `rowspan` attributes.
|
||
|
|
||
|
**Examples**
|
||
|
|
||
|
The `sheet_to_html` utility function generates HTML code that can be added to
|
||
|
any DOM element by setting the `innerHTML`:
|
||
|
|
||
|
```js
|
||
|
var container = document.getElementById("tavolo");
|
||
|
container.innerHTML = XLSX.utils.sheet_to_html(worksheet);
|
||
|
```
|
||
|
|
||
|
Combining with `fetch`, constructing a site from a workbook is straightforward:
|
||
|
|
||
|
<details>
|
||
|
<summary><b>Vanilla JS + HTML fetch workbook and generate table previews</b> (click to show)</summary>
|
||
|
|
||
|
```html
|
||
|
<body>
|
||
|
<style>TABLE { border-collapse: collapse; } TD { border: 1px solid; }</style>
|
||
|
<div id="tavolo"></div>
|
||
|
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
|
||
|
<script type="text/javascript">
|
||
|
(async() => {
|
||
|
/* fetch and parse workbook -- see the fetch example for details */
|
||
|
const workbook = XLSX.read(await (await fetch("sheetjs.xlsx")).arrayBuffer());
|
||
|
|
||
|
let output = [];
|
||
|
/* loop through the worksheet names in order */
|
||
|
workbook.SheetNames.forEach(name => {
|
||
|
|
||
|
/* generate HTML from the corresponding worksheets */
|
||
|
const worksheet = workbook.Sheets[name];
|
||
|
const html = XLSX.utils.sheet_to_html(worksheet);
|
||
|
|
||
|
/* add a header with the title name followed by the table */
|
||
|
output.push(`<H3>${name}</H3>${html}`);
|
||
|
});
|
||
|
/* write to the DOM at the end */
|
||
|
tavolo.innerHTML = output.join("\n");
|
||
|
})();
|
||
|
</script>
|
||
|
</body>
|
||
|
```
|
||
|
|
||
|
</details>
|
||
|
|
||
|
<details>
|
||
|
<summary><b>React fetch workbook and generate HTML table previews</b> (click to show)</summary>
|
||
|
|
||
|
It is generally recommended to use a React-friendly workflow, but it is possible
|
||
|
to generate HTML and use it in React with `dangerouslySetInnerHTML`:
|
||
|
|
||
|
```jsx
|
||
|
function Tabeller(props) {
|
||
|
/* the workbook object is the state */
|
||
|
const [workbook, setWorkbook] = React.useState(XLSX.utils.book_new());
|
||
|
|
||
|
/* fetch and update the workbook with an effect */
|
||
|
React.useEffect(() => { (async() => {
|
||
|
/* fetch and parse workbook -- see the fetch example for details */
|
||
|
const wb = XLSX.read(await (await fetch("sheetjs.xlsx")).arrayBuffer());
|
||
|
setWorkbook(wb);
|
||
|
})(); });
|
||
|
|
||
|
return workbook.SheetNames.map(name => (<>
|
||
|
<h3>name</h3>
|
||
|
<div dangerouslySetInnerHTML={{
|
||
|
/* this __html mantra is needed to set the inner HTML */
|
||
|
__html: XLSX.utils.sheet_to_html(workbook.Sheets[name])
|
||
|
}} />
|
||
|
</>));
|
||
|
}
|
||
|
```
|
||
|
|
||
|
The [`react` demo](demos/react) includes more React examples.
|
||
|
|
||
|
</details>
|
||
|
|
||
|
<details>
|
||
|
<summary><b>VueJS fetch workbook and generate HTML table previews</b> (click to show)</summary>
|
||
|
|
||
|
It is generally recommended to use a VueJS-friendly workflow, but it is possible
|
||
|
to generate HTML and use it in VueJS with the `v-html` directive:
|
||
|
|
||
|
```jsx
|
||
|
import { read, utils } from 'xlsx';
|
||
|
import { reactive } from 'vue';
|
||
|
|
||
|
const S5SComponent = {
|
||
|
mounted() { (async() => {
|
||
|
/* fetch and parse workbook -- see the fetch example for details */
|
||
|
const workbook = read(await (await fetch("sheetjs.xlsx")).arrayBuffer());
|
||
|
/* loop through the worksheet names in order */
|
||
|
workbook.SheetNames.forEach(name => {
|
||
|
/* generate HTML from the corresponding worksheets */
|
||
|
const html = utils.sheet_to_html(workbook.Sheets[name]);
|
||
|
/* add to state */
|
||
|
this.wb.wb.push({ name, html });
|
||
|
});
|
||
|
})(); },
|
||
|
/* this state mantra is required for array updates to work */
|
||
|
setup() { return { wb: reactive({ wb: [] }) }; },
|
||
|
template: `
|
||
|
<div v-for="ws in wb.wb" :key="ws.name">
|
||
|
<h3>{{ ws.name }}</h3>
|
||
|
<div v-html="ws.html"></div>
|
||
|
</div>`
|
||
|
};
|
||
|
```
|
||
|
|
||
|
The [`vuejs` demo](demos/vue) includes more React examples.
|
||
|
|
||
|
</details>
|
||
|
|
||
|
### Generating Single-Worksheet Snapshots
|
||
|
|
||
|
The `sheet_to_*` functions accept a worksheet object.
|
||
|
|
||
|
**API**
|
||
|
|
||
|
_Generate a CSV from a single worksheet_
|
||
|
|
||
|
```js
|
||
|
var csv = XLSX.utils.sheet_to_csv(worksheet, opts);
|
||
|
```
|
||
|
|
||
|
This snapshot is designed to replicate the "CSV UTF8 (`.csv`)" output type.
|
||
|
["Delimiter-Separated Output"](#delimiter-separated-output) describes the
|
||
|
function and the optional `opts` argument in more detail.
|
||
|
|
||
|
_Generate "Text" from a single worksheet_
|
||
|
|
||
|
```js
|
||
|
var txt = XLSX.utils.sheet_to_txt(worksheet, opts);
|
||
|
```
|
||
|
|
||
|
This snapshot is designed to replicate the "UTF16 Text (`.txt`)" output type.
|
||
|
["Delimiter-Separated Output"](#delimiter-separated-output) describes the
|
||
|
function and the optional `opts` argument in more detail.
|
||
|
|
||
|
_Generate a list of formulae from a single worksheet_
|
||
|
|
||
|
```js
|
||
|
var fmla = XLSX.utils.sheet_to_formulae(worksheet);
|
||
|
```
|
||
|
|
||
|
This snapshot generates an array of entries representing the embedded formulae.
|
||
|
Array formulae are rendered in the form `range=formula` while plain cells are
|
||
|
rendered in the form `cell=formula or value`. String literals are prefixed with
|
||
|
an apostrophe `'`, consistent with Excel's formula bar display.
|
||
|
|
||
|
["Formulae Output"](#formulae-output) describes the function in more detail.
|
||
|
|