react-modify demo [ci skip]

Co-authored-by: SheetJS <dev@sheetjs.com>
This commit is contained in:
0xc0Der 2022-03-11 13:38:20 +00:00
parent b60d45087b
commit cd95666494
10 changed files with 240 additions and 1 deletions

@ -10,16 +10,18 @@ into web pages with script tags:
The library can also be imported directly from JSX code with:
```js
import XLSX from 'xlsx';
import { read, utils, writeFileXLSX } from 'xlsx';
```
This demo shows a simple React component transpiled in the browser using Babel
standalone library. Since there is no standard React table model, this demo
settles on the array of arrays approach.
Other scripts in this demo show:
- server-rendered React component (with `next.js`)
- `react-native` deployment for iOS and android
- [`react-data-grid` reading, modifying, and writing files](modify/)
## How to run

23
modify/.gitignore vendored Normal file

@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

10
modify/README.md Normal file

@ -0,0 +1,10 @@
# react-modify
This demo shows import and export with the `react-data-grid` table component.
In the project directory, you can run:
```bash
$ npm install
$ npm start
```

36
modify/package.json Normal file

@ -0,0 +1,36 @@
{
"name": "react-modify-demo",
"dependencies": {
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"react": "^17.0.2",
"react-data-grid": "^7.0.0-beta.11",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"typescript": "^4.1.2",
"xlsx": "^0.18.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

@ -0,0 +1,107 @@
import React, { useState, ChangeEvent } from "react";
import DataGrid, { TextEditor } from "react-data-grid";
import { read, utils, WorkSheet, writeFile } from "xlsx";
import "../styles/App.css";
type Row = any[]; /*{
[index: string]: string | number;
};*/
type Column = {
key: string;
name: string;
editor: typeof TextEditor;
};
type DataSet = {
[index: string]: WorkSheet;
};
function getRowsCols(
data: DataSet,
sheetName: string
): {
rows: Row[];
columns: Column[];
} {
const rows: Row[] = utils.sheet_to_json(data[sheetName], {header:1});
let columns: Column[] = [];
for (let row of rows) {
const keys: string[] = Object.keys(row);
if (keys.length > columns.length) {
columns = keys.map((key) => {
return { key, name: utils.encode_col(+key), editor: TextEditor };
});
}
}
return { rows, columns };
}
export default function App() {
const [rows, setRows] = useState<Row[]>([]);
const [columns, setColumns] = useState<Column[]>([]);
const [workBook, setWorkBook] = useState<DataSet>({} as DataSet);
const [sheets, setSheets] = useState<string[]>([]);
const [current, setCurrent] = useState<string>("");
const exportTypes = ["xlsx", "xlsb", "csv", "html"];
function selectSheet(name: string, reset = true) {
if(reset) workBook[current] = utils.json_to_sheet(rows, {
header: columns.map((col: Column) => col.key),
skipHeader: true
});
const { rows: new_rows, columns: new_columns } = getRowsCols(workBook, name);
setRows(new_rows);
setColumns(new_columns);
setCurrent(name);
}
async function handleFile(ev: ChangeEvent<HTMLInputElement>): Promise<void> {
const file = await ev.target.files?.[0]?.arrayBuffer();
const data = read(file);
setWorkBook(data.Sheets);
setSheets(data.SheetNames);
}
function saveFile(ext: string): void {
const wb = utils.book_new();
sheets.forEach((n) => {
utils.book_append_sheet(wb, workBook[n], n);
});
writeFile(wb, "sheet." + ext);
}
return (
<>
<input type="file" onChange={handleFile} />
<div className="flex-cont">
{sheets.map((sheet) => (
<button key={sheet} onClick={(e) => selectSheet(sheet)}>
{sheet}
</button>
))}
</div>
<div className="flex-cont">
<b>Current Sheet: {current}</b>
</div>
<DataGrid columns={columns} rows={rows} onRowsChange={setRows} />
<div className="flex-cont">
{exportTypes.map((ext) => (
<button key={ext} onClick={() => saveFile(ext)}>
export [.{ext}]
</button>
))}
</div>
</>
);
}

12
modify/src/index.tsx Normal file

@ -0,0 +1,12 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import './styles/index.css';
ReactDOM.render(
<React.StrictMode>
<App/>
</React.StrictMode>,
document.getElementById('root')
);

1
modify/src/react-app-env.d.ts vendored Normal file

@ -0,0 +1 @@
/// <reference types="react-scripts" />

14
modify/src/styles/App.css Normal file

@ -0,0 +1,14 @@
input {
margin: 0.5rem;
}
.flex-cont {
display: flex;
margin: 0.5rem;
justify-content: center;
}
.flex-cont button {
margin: 0.3rem;
padding: 0.2rem;
}

@ -0,0 +1,8 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

26
modify/tsconfig.json Normal file

@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}