forked from sheetjs/docs.sheetjs.com
		
	knex
This commit is contained in:
		
							parent
							
								
									e197ed24c8
								
							
						
					
					
						commit
						059a1a3783
					
				@ -15,7 +15,7 @@ Other demos cover general React deployments, including:
 | 
			
		||||
- [Static Site Generation powered by NextJS](/docs/demos/static/nextjs)
 | 
			
		||||
- [iOS and Android applications powered by React Native](/docs/demos/mobile/reactnative)
 | 
			
		||||
- [Desktop application powered by React Native Windows + macOS](/docs/demos/desktop/reactnative)
 | 
			
		||||
- [React Data Grid UI component](/docs/demos/grid#react-data-grid)
 | 
			
		||||
- [React Data Grid UI component](/docs/demos/grid/rdg)
 | 
			
		||||
- [Glide Data Grid UI component](/docs/demos/grid/gdg)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										127
									
								
								docz/docs/03-demos/02-grid/11-rdg.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										127
									
								
								docz/docs/03-demos/02-grid/11-rdg.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,127 @@
 | 
			
		||||
---
 | 
			
		||||
title: React Datagrid
 | 
			
		||||
pagination_prev: demos/frontend/index
 | 
			
		||||
pagination_next: demos/net/index
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was last tested on 2023 April 18 with `react-data-grid 7.0.0-beta.28`,
 | 
			
		||||
`create-react-app` 5.0.1 and React 18.2.0.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
The demo creates a site that looks like the screenshot below:
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
## Integration Details
 | 
			
		||||
 | 
			
		||||
#### Rows and Columns state
 | 
			
		||||
 | 
			
		||||
`react-data-grid` state consists of an Array of column metadata and an Array of
 | 
			
		||||
row objects. Typically both are defined in state:
 | 
			
		||||
 | 
			
		||||
```jsx
 | 
			
		||||
import DataGrid, { Column } from "react-data-grid";
 | 
			
		||||
 | 
			
		||||
export default function App() {
 | 
			
		||||
  const [rows, setRows] = useState([]);
 | 
			
		||||
  const [columns, setColumns] = useState([]);
 | 
			
		||||
 | 
			
		||||
  return ( <DataGrid columns={columns} rows={rows} onRowsChange={setRows} /> );
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The most generic data representation is an array of arrays. To sate the grid,
 | 
			
		||||
columns must be objects whose `key` property is the index converted to string:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
import { WorkSheet, utils } from 'xlsx';
 | 
			
		||||
import { textEditor, Column } from "react-data-grid";
 | 
			
		||||
 | 
			
		||||
type Row = any[];
 | 
			
		||||
type AOAColumn = Column<Row>;
 | 
			
		||||
type RowCol = { rows: Row[]; columns: AOAColumn[]; };
 | 
			
		||||
 | 
			
		||||
function ws_to_rdg(ws: WorkSheet): RowCol {
 | 
			
		||||
  /* 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) => ({
 | 
			
		||||
    key: String(i), // RDG will access row["0"], row["1"], etc
 | 
			
		||||
    name: utils.encode_col(i), // the column labels will be A, B, etc
 | 
			
		||||
    editor: textEditor // enable cell editing
 | 
			
		||||
  }));
 | 
			
		||||
 | 
			
		||||
  return { rows, columns }; // these can be fed to setRows / setColumns
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
In the other direction, a worksheet can be generated with `aoa_to_sheet`:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
import { WorkSheet, utils } from 'xlsx';
 | 
			
		||||
 | 
			
		||||
type Row = any[];
 | 
			
		||||
 | 
			
		||||
function rdg_to_ws(rows: Row[]): WorkSheet {
 | 
			
		||||
  return utils.aoa_to_sheet(rows);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::caution
 | 
			
		||||
 | 
			
		||||
When the demo was last refreshed, row array objects were preserved.  This was
 | 
			
		||||
not the case in a later release.  The row arrays must be re-created.
 | 
			
		||||
 | 
			
		||||
The snippet defines a `arrayify` function that creates arrays if necessary.
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
import { WorkSheet, utils } from 'xlsx';
 | 
			
		||||
 | 
			
		||||
type Row = any[];
 | 
			
		||||
 | 
			
		||||
// highlight-start
 | 
			
		||||
function arrayify(rows: any[]): Row[] {
 | 
			
		||||
  return rows.map(row => {
 | 
			
		||||
    var length = Object.keys(row).length;
 | 
			
		||||
    for(; length > 0; --length) if(row[length-1] != null) break;
 | 
			
		||||
    return Array.from({length, ...row});
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
// highlight-end
 | 
			
		||||
 | 
			
		||||
function rdg_to_ws(rows: Row[]): WorkSheet {
 | 
			
		||||
  return utils.aoa_to_sheet(arrayify(rows));
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
## Demo
 | 
			
		||||
 | 
			
		||||
1) Create a new TypeScript `create-react-app` app:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npx create-react-app sheetjs-rdg --template typescript
 | 
			
		||||
cd sheetjs-rdg
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
2) Install dependencies:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz react-data-grid
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
3) Download [`App.tsx`](pathname:///rdg/App.tsx) and replace `src/App.tsx`.
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
curl -L -o src/App.tsx https://docs.sheetjs.com/rdg/App.tsx
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
4) run `npm start`.  When you load the page in the browser, it will attempt to
 | 
			
		||||
   fetch <https://sheetjs.com/pres.numbers> and load the data.
 | 
			
		||||
@ -91,129 +91,7 @@ with other buttons and components on the page.
 | 
			
		||||
 | 
			
		||||
### React Data Grid
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was tested against `react-data-grid 7.0.0-beta.15`, React 18.2.0,
 | 
			
		||||
and `create-react-app` 5.0.1 on 2022 August 16.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
<!-- spellchecker-disable -->
 | 
			
		||||
 | 
			
		||||
#### RDG Demo
 | 
			
		||||
 | 
			
		||||
<!-- spellchecker-enable -->
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Complete Example</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
1) Create a new TypeScript `create-react-app` app:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npx create-react-app sheetjs-cra --template typescript
 | 
			
		||||
cd sheetjs-cra
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
2) Install dependencies:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz react-data-grid
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
3) Download [`App.tsx`](pathname:///rdg/App.tsx) and replace `src/App.tsx`.
 | 
			
		||||
 | 
			
		||||
4) run `npm start`.  When you load the page in the browser, it will attempt to
 | 
			
		||||
   fetch <https://sheetjs.com/pres.numbers> and load the data.
 | 
			
		||||
 | 
			
		||||
The following screenshot was taken from the demo:
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
#### Rows and Columns state
 | 
			
		||||
 | 
			
		||||
`react-data-grid` state consists of an Array of column metadata and an Array of
 | 
			
		||||
row objects. Typically both are defined in state:
 | 
			
		||||
 | 
			
		||||
```jsx
 | 
			
		||||
import DataGrid, { Column } from "react-data-grid";
 | 
			
		||||
 | 
			
		||||
export default function App() {
 | 
			
		||||
  const [rows, setRows] = useState([]);
 | 
			
		||||
  const [columns, setColumns] = useState([]);
 | 
			
		||||
 | 
			
		||||
  return ( <DataGrid columns={columns} rows={rows} onRowsChange={setRows} /> );
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The most generic data representation is an array of arrays. To sate the grid,
 | 
			
		||||
columns must be objects whose `key` property is the index converted to string:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
import { WorkSheet, utils } from 'xlsx';
 | 
			
		||||
import { textEditor, Column } from "react-data-grid";
 | 
			
		||||
 | 
			
		||||
type Row = any[];
 | 
			
		||||
type AOAColumn = Column<Row>;
 | 
			
		||||
type RowCol = { rows: Row[]; columns: AOAColumn[]; };
 | 
			
		||||
 | 
			
		||||
function ws_to_rdg(ws: WorkSheet): RowCol {
 | 
			
		||||
  /* 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) => ({
 | 
			
		||||
    key: String(i), // RDG will access row["0"], row["1"], etc
 | 
			
		||||
    name: utils.encode_col(i), // the column labels will be A, B, etc
 | 
			
		||||
    editor: textEditor // enable cell editing
 | 
			
		||||
  }));
 | 
			
		||||
 | 
			
		||||
  return { rows, columns }; // these can be fed to setRows / setColumns
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
In the other direction, a worksheet can be generated with `aoa_to_sheet`:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
import { WorkSheet, utils } from 'xlsx';
 | 
			
		||||
 | 
			
		||||
type Row = any[];
 | 
			
		||||
 | 
			
		||||
function rdg_to_ws(rows: Row[]): WorkSheet {
 | 
			
		||||
  return utils.aoa_to_sheet(rows);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::caution
 | 
			
		||||
 | 
			
		||||
When the demo was last refreshed, row array objects were preserved.  This was
 | 
			
		||||
not the case in a later release.  The row arrays must be re-created.
 | 
			
		||||
 | 
			
		||||
The snippet defines a `arrayify` function that creates arrays if necessary.
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
import { WorkSheet, utils } from 'xlsx';
 | 
			
		||||
 | 
			
		||||
type Row = any[];
 | 
			
		||||
 | 
			
		||||
// highlight-start
 | 
			
		||||
function arrayify(rows: any[]): Row[] {
 | 
			
		||||
  return rows.map(row => {
 | 
			
		||||
    var length = Object.keys(row).length;
 | 
			
		||||
    for(; length > 0; --length) if(row[length-1] != null) break;
 | 
			
		||||
    return Array.from({length, ...row});
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
// highlight-end
 | 
			
		||||
 | 
			
		||||
function rdg_to_ws(rows: Row[]): WorkSheet {
 | 
			
		||||
  return utils.aoa_to_sheet(arrayify(rows));
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
**[The exposition has been moved to a separate page.](/docs/demos/grid/rdg)**
 | 
			
		||||
 | 
			
		||||
### Glide Data Grid
 | 
			
		||||
 | 
			
		||||
@ -222,7 +100,7 @@ function rdg_to_ws(rows: Row[]): WorkSheet {
 | 
			
		||||
### Material UI Data Grid
 | 
			
		||||
 | 
			
		||||
Material UI Data Grid and React Data Grid share many state patterns and idioms.
 | 
			
		||||
Differences from ["React Data Grid"](#react-data-grid) will be highlighted.
 | 
			
		||||
Differences from ["React Data Grid"](/docs/demos/grid/rdg) will be highlighted.
 | 
			
		||||
 | 
			
		||||
[A complete example is included below.](#muidg-demo)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -103,7 +103,7 @@ from the `"Presidents"` sheet:
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This was tested against `lume v1.15.3` on 2023 March 14.
 | 
			
		||||
This was tested against `lume v1.16.2` on 2023 April 18.
 | 
			
		||||
 | 
			
		||||
This example uses the Nunjucks template format. Lume plugins support additional
 | 
			
		||||
template formats, including Markdown and JSX.
 | 
			
		||||
@ -156,8 +156,16 @@ curl -L -o _data/pres.numbers https://sheetjs.com/pres.numbers
 | 
			
		||||
deno task lume --serve
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
To verify it works, access http://localhost:3000 from your web browser.
 | 
			
		||||
Adding a new row and saving `pres.numbers` should refresh the data
 | 
			
		||||
To verify it works, access http://localhost:3000 from your web browser. Open
 | 
			
		||||
`_data/pres.numbers` and add a new row to the bottom of the sheet. The page will
 | 
			
		||||
refresh and show the new contents.
 | 
			
		||||
 | 
			
		||||
:::caution
 | 
			
		||||
 | 
			
		||||
There is a known bug with Deno hot reloading.  If the page does not refresh
 | 
			
		||||
automatically, upgrade with `deno upgrade` and restart the development server.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
5) Stop the server (press `CTRL+C` in the terminal window) and run
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -143,66 +143,7 @@ types and other database minutiae.
 | 
			
		||||
 | 
			
		||||
**Knex**
 | 
			
		||||
 | 
			
		||||
The result of a `SELECT` statement is an array of objects:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const aoo = await connection.select("*").from("DataTable");
 | 
			
		||||
const worksheet = XLSX.utils.json_to_sheet(aoa);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Knex wraps primitive types when creating a table. `generate_sql` takes a `knex`
 | 
			
		||||
connection object and uses the API:
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Generating a Table</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
// define mapping between determined types and Knex types
 | 
			
		||||
const PG = { "n": "float", "s": "text", "b": "boolean" };
 | 
			
		||||
 | 
			
		||||
async function generate_sql(knex, ws, wsname) {
 | 
			
		||||
 | 
			
		||||
  // generate an array of objects from the data
 | 
			
		||||
  const aoo = XLSX.utils.sheet_to_json(ws);
 | 
			
		||||
 | 
			
		||||
  // types will map column headers to types, while hdr holds headers in order
 | 
			
		||||
  const types = {}, hdr = [];
 | 
			
		||||
 | 
			
		||||
  // loop across each row object
 | 
			
		||||
  aoo.forEach(row =>
 | 
			
		||||
    // Object.entries returns a row of [key, value] pairs.  Loop across those
 | 
			
		||||
    Object.entries(row).forEach(([k,v]) => {
 | 
			
		||||
 | 
			
		||||
      // If this is first time seeing key, mark unknown and append header array
 | 
			
		||||
      if(!types[k]) { types[k] = "?"; hdr.push(k); }
 | 
			
		||||
 | 
			
		||||
      // skip null and undefined
 | 
			
		||||
      if(v == null) return;
 | 
			
		||||
 | 
			
		||||
      // check and resolve type
 | 
			
		||||
      switch(typeof v) {
 | 
			
		||||
        case "string": // strings are the broadest type
 | 
			
		||||
          types[k] = "s"; break;
 | 
			
		||||
        case "number": // if column is not string, number is the broadest type
 | 
			
		||||
          if(types[k] != "s") types[k] = "n"; break;
 | 
			
		||||
        case "boolean": // only mark boolean if column is unknown or boolean
 | 
			
		||||
          if("?b".includes(types[k])) types[k] = "b"; break;
 | 
			
		||||
        default: types[k] = "s"; break; // default to string type
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  await knex.schema.dropTableIfExists(wsname);
 | 
			
		||||
  await knex.schema.createTable(wsname, (table) => { hdr.forEach(h => { table[PG[types[h]] || "text"](h); }); });
 | 
			
		||||
  for(let i = 0; i < aoo.length; ++i) {
 | 
			
		||||
    if(!aoo[i] || !Object.keys(aoo[i]).length) continue;
 | 
			
		||||
    try { await knex.insert(aoo[i]).into(wsname); } catch(e) {}
 | 
			
		||||
  }
 | 
			
		||||
  return knex;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
**[The exposition has been moved to a separate page.](/docs/demos/data/knex)**
 | 
			
		||||
 | 
			
		||||
### Other SQL Databases
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										170
									
								
								docz/docs/03-demos/07-data/14-knex.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										170
									
								
								docz/docs/03-demos/07-data/14-knex.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,170 @@
 | 
			
		||||
---
 | 
			
		||||
title: Knex SQL Builder
 | 
			
		||||
pagination_prev: demos/desktop/index
 | 
			
		||||
pagination_next: demos/local/index
 | 
			
		||||
sidebar_custom_props:
 | 
			
		||||
  sql: true
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was last tested on 2023 April 19 with Knex 2.4.2 and `better-sqlite`.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
## Integration Details
 | 
			
		||||
 | 
			
		||||
#### Importing Data
 | 
			
		||||
 | 
			
		||||
`sheet_to_json` generates an array of objects. An `INSERT` statement can be
 | 
			
		||||
generated from each row object using `knex.insert`:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const aoo = XLSX.utils.sheet_to_json(ws);
 | 
			
		||||
for(let i = 0; i < aoo.length; ++i) await knex.insert(aoo[i]).into(table_name);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Exporting Data
 | 
			
		||||
 | 
			
		||||
The result of a `SELECT` statement is an array of objects:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const aoo = await knex.select("*").from(table_name);
 | 
			
		||||
const worksheet = XLSX.utils.json_to_sheet(aoo);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Complete Example
 | 
			
		||||
 | 
			
		||||
1) Install dependencies:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz knex better-sqlite3
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
2) Download the [test file](https://sheetjs.com/pres.numbers)
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
curl -LO https://sheetjs.com/pres.numbers
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
3) Save the following utility script to `sheetjsknex.js`:
 | 
			
		||||
 | 
			
		||||
```js title="sheetjsknex.js"
 | 
			
		||||
const XLSX = require("xlsx");
 | 
			
		||||
 | 
			
		||||
// define mapping between determined types and Knex types
 | 
			
		||||
const PG = { "n": "float", "s": "text", "b": "boolean" };
 | 
			
		||||
 | 
			
		||||
async function ws_to_knex(knex, ws, table_name) {
 | 
			
		||||
 | 
			
		||||
  // generate an array of objects from the data
 | 
			
		||||
  const aoo = XLSX.utils.sheet_to_json(ws);
 | 
			
		||||
 | 
			
		||||
  // types will map column headers to types, while hdr holds headers in order
 | 
			
		||||
  const types = {}, hdr = [];
 | 
			
		||||
 | 
			
		||||
  // loop across each row object
 | 
			
		||||
  aoo.forEach(row =>
 | 
			
		||||
    // Object.entries returns a row of [key, value] pairs.  Loop across those
 | 
			
		||||
    Object.entries(row).forEach(([k,v]) => {
 | 
			
		||||
 | 
			
		||||
      // If this is first time seeing key, mark unknown and append header array
 | 
			
		||||
      if(!types[k]) { types[k] = "?"; hdr.push(k); }
 | 
			
		||||
 | 
			
		||||
      // skip null and undefined
 | 
			
		||||
      if(v == null) return;
 | 
			
		||||
 | 
			
		||||
      // check and resolve type
 | 
			
		||||
      switch(typeof v) {
 | 
			
		||||
        case "string": // strings are the broadest type
 | 
			
		||||
          types[k] = "s"; break;
 | 
			
		||||
        case "number": // if column is not string, number is the broadest type
 | 
			
		||||
          if(types[k] != "s") types[k] = "n"; break;
 | 
			
		||||
        case "boolean": // only mark boolean if column is unknown or boolean
 | 
			
		||||
          if("?b".includes(types[k])) types[k] = "b"; break;
 | 
			
		||||
        default: types[k] = "s"; break; // default to string type
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  await knex.schema.dropTableIfExists(table_name);
 | 
			
		||||
 | 
			
		||||
  // use column type info to create table
 | 
			
		||||
  await knex.schema.createTable(table_name, (table) => { hdr.forEach(h => { table[PG[types[h]] || "text"](h); }); });
 | 
			
		||||
 | 
			
		||||
  // insert each non-empty row object
 | 
			
		||||
  for(let i = 0; i < aoo.length; ++i) {
 | 
			
		||||
    if(!aoo[i] || !Object.keys(aoo[i]).length) continue;
 | 
			
		||||
    try { await knex.insert(aoo[i]).into(table_name); } catch(e) {}
 | 
			
		||||
  }
 | 
			
		||||
  return knex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function knex_to_ws(knex, table_name) {
 | 
			
		||||
  const aoo = await knex.select("*").from(table_name);
 | 
			
		||||
  return XLSX.utils.json_to_sheet(aoo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = { ws_to_knex, knex_to_ws };
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
4) Save the following to `SheetJSKnexTest.js`:
 | 
			
		||||
 | 
			
		||||
```js title="SheetJSKnexTest.js"
 | 
			
		||||
const { ws_to_knex, knex_to_ws } = require("./sheetjsknex");
 | 
			
		||||
const Knex = require('knex');
 | 
			
		||||
 | 
			
		||||
/* read file and get first worksheet */
 | 
			
		||||
const XLSX = require("xlsx");
 | 
			
		||||
const oldwb = XLSX.readFile("pres.numbers");
 | 
			
		||||
const wsname = oldwb.SheetNames[0];
 | 
			
		||||
const oldws = oldwb.Sheets[wsname];
 | 
			
		||||
 | 
			
		||||
(async() => {
 | 
			
		||||
  /* open connection to SheetJSKnex.db */
 | 
			
		||||
  let knex = Knex({ client: 'better-sqlite3', connection: { filename: "SheetJSKnex.db" } });
 | 
			
		||||
  try {
 | 
			
		||||
    /* load data into database and close connection */
 | 
			
		||||
    await ws_to_knex(knex, oldws, "Test_Table");
 | 
			
		||||
  } finally { knex.destroy(); }
 | 
			
		||||
 | 
			
		||||
  /* reconnect to SheetJSKnex.db */
 | 
			
		||||
  knex = Knex({ client: 'better-sqlite3', connection: { filename: "SheetJSKnex.db" } });
 | 
			
		||||
  try {
 | 
			
		||||
    /* get data from db */
 | 
			
		||||
    const aoo = await knex.select("*").from("Test_Table");
 | 
			
		||||
 | 
			
		||||
    /* export to file */
 | 
			
		||||
    const newws = await knex_to_ws(knex, "Test_Table");
 | 
			
		||||
    const newwb = XLSX.utils.book_new();
 | 
			
		||||
    XLSX.utils.book_append_sheet(newwb, newws, "Export");
 | 
			
		||||
    XLSX.writeFile(newwb, "SheetJSKnex.xlsx");
 | 
			
		||||
  } finally { knex.destroy(); }
 | 
			
		||||
})();
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This script will read `pres.numbers` and load data into a table `Test_Table`.
 | 
			
		||||
The SQLite database will be saved to `SheetJSKnex.db`.
 | 
			
		||||
 | 
			
		||||
After closing the connection, the script will make a new connection and export
 | 
			
		||||
data to `SheetJSKnex.xlsx`.
 | 
			
		||||
 | 
			
		||||
5) Run the script:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
node SheetJSKnexTest.js
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The script will generate two artifacts:
 | 
			
		||||
 | 
			
		||||
`SheetJSKnex.xlsx` can be opened in a spreadsheet app or tested in the terminal:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npx xlsx-cli SheetJSKnex.xlsx
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
`SheetJSKnex.db` can be verified with the `sqlite3` command line tool:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
sqlite3 SheetJSKnex.db 'select * from Test_Table'
 | 
			
		||||
```
 | 
			
		||||
@ -258,7 +258,7 @@ console.log(utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]));
 | 
			
		||||
 | 
			
		||||
```js title="SheetJSWriteToAzure.mjs"
 | 
			
		||||
import { BlobServiceClient } from "@azure/storage-blob";
 | 
			
		||||
import { read, utils } from "xlsx";
 | 
			
		||||
import { write, utils } from "xlsx";
 | 
			
		||||
 | 
			
		||||
/* replace these constants */
 | 
			
		||||
const connStr = "<REPLACE WITH CONNECTION STRING>";
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@ available as a global. A JS stub can expose methods from AppleScript scripts.
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was last tested on 2022 April 18 in macOS Monterey.
 | 
			
		||||
This demo was last tested on 2023 April 18 in macOS Monterey.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
@ -218,7 +218,7 @@ extractResult(res)
 | 
			
		||||
 | 
			
		||||
on getContext()
 | 
			
		||||
  set UnixPath to POSIX path of ((path to me as text) & "::")
 | 
			
		||||
  set libpath to POSIX path of (UnixPath & "xlsx.shim.js")
 | 
			
		||||
  set libpath to POSIX path of (UnixPath & "xlsx.stub.js")
 | 
			
		||||
  set {src, err} to current application's NSString's stringWithContentsOfFile:libpath encoding:(current application's NSISOLatin1StringEncoding) |error|:(reference)
 | 
			
		||||
 | 
			
		||||
  set lang to current application's OSALanguage's languageForName:"JavaScript"
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,7 @@ run in the web browser, demos will include interactive examples.
 | 
			
		||||
 | 
			
		||||
- [`canvas-datagrid`](/docs/demos/grid/cdg)
 | 
			
		||||
- [`x-spreadsheet`](/docs/demos/grid/xs)
 | 
			
		||||
- [`react-data-grid`](/docs/demos/grid#react-data-grid)
 | 
			
		||||
- [`react-data-grid`](/docs/demos/grid/rdg)
 | 
			
		||||
- [`glide-data-grid`](/docs/demos/grid/gdg)
 | 
			
		||||
- [`vue3-table-lite`](/docs/demos/grid#vue3-table-lite)
 | 
			
		||||
- [`angular-ui-grid`](/docs/demos/grid#angular-ui-grid)
 | 
			
		||||
@ -70,6 +70,8 @@ run in the web browser, demos will include interactive examples.
 | 
			
		||||
- [`Excel JavaScript API`](/docs/demos/extensions/excelapi)
 | 
			
		||||
- [`ExtendScript for Adobe Apps`](/docs/demos/extensions/extendscript)
 | 
			
		||||
- [`Chrome and Chromium Extensions`](/docs/demos/extensions/chromium)
 | 
			
		||||
- [`Google Sheets + Apps Script`](/docs/demos/extensions/gsheet)
 | 
			
		||||
- [`AppleScript and OSA`](/docs/demos/extensions/osa)
 | 
			
		||||
 | 
			
		||||
### Cloud Platforms
 | 
			
		||||
 | 
			
		||||
@ -116,10 +118,13 @@ run in the web browser, demos will include interactive examples.
 | 
			
		||||
### Other Programming Languages
 | 
			
		||||
 | 
			
		||||
- [`JavaScript Engines`](/docs/demos/engines)
 | 
			
		||||
- [`Duktape (C)`](/docs/demos/engines/duktape)
 | 
			
		||||
- [`Duktape (C / Perl)`](/docs/demos/engines/duktape)
 | 
			
		||||
- [`JavaScriptCore (Swift)`](/docs/demos/engines/jsc)
 | 
			
		||||
- [`Rhino (Java)`](/docs/demos/engines/rhino)
 | 
			
		||||
- [`Nashorn (Java)`](/docs/demos/engines/nashorn)
 | 
			
		||||
- [`Goja (Go)`](/docs/demos/engines/goja)
 | 
			
		||||
- [`ChakraCore (C++)`](/docs/demos/engines/chakra)
 | 
			
		||||
- [`QuickJS (C)`](/docs/demos/engines/quickjs)
 | 
			
		||||
- [`ExecJS (Ruby)`](/docs/demos/engines/rb)
 | 
			
		||||
- [`JavaScript::Engine (Perl)`](/docs/demos/engines/perl)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -605,7 +605,7 @@ previewing and modifying structured data in the web browser.
 | 
			
		||||
  </TabItem>
 | 
			
		||||
  <TabItem value="react" label="React">
 | 
			
		||||
 | 
			
		||||
[`react-data-grid`](/docs/demos/grid#react-data-grid) is a data grid built for
 | 
			
		||||
[`react-data-grid`](/docs/demos/grid/rdg) is a data grid built for
 | 
			
		||||
React. It uses two properties: `rows` of data objects and `columns` which
 | 
			
		||||
describe the columns.  The grid API can play nice with an array of arrays.
 | 
			
		||||
 | 
			
		||||
@ -616,6 +616,8 @@ import { useEffect, useState } from "react";
 | 
			
		||||
import DataGrid from "react-data-grid";
 | 
			
		||||
import { read, utils } from "xlsx";
 | 
			
		||||
 | 
			
		||||
import 'react-data-grid/lib/styles.css';
 | 
			
		||||
 | 
			
		||||
const url = "https://oss.sheetjs.com/test_files/RkNumber.xls";
 | 
			
		||||
 | 
			
		||||
export default function App() {
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@ import React, { useEffect, useState, ChangeEvent } from "react";
 | 
			
		||||
import DataGrid, { textEditor, Column } from "react-data-grid";
 | 
			
		||||
import { read, utils, WorkSheet, writeFile } from "xlsx";
 | 
			
		||||
 | 
			
		||||
import 'react-data-grid/lib/styles.css';
 | 
			
		||||
import './App.css';
 | 
			
		||||
 | 
			
		||||
type DataSet = { [index: string]: WorkSheet; };
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user