docs.sheetjs.com/docz/static/gdg/App.tsx
2023-02-07 04:28:15 -05:00

83 lines
3.1 KiB
TypeScript

import { useState, useCallback, useEffect, useRef, ChangeEvent } from 'react';
import { utils, read, writeFileXLSX, WorkBook } from 'xlsx';
import { DataEditor, GridCellKind, GridCell, GridColumn, Item, DataEditorRef, EditableGridCell } from '@glideapps/glide-data-grid';
import "@glideapps/glide-data-grid/dist/index.css";
// this will store the raw data objects
let data: any[] = [];
// this will store the header names
let header: string[] = [];
function App() {
const [cols, setCols] = useState<GridColumn[]>([]); // gdg column objects
const [rows, setRows] = useState<number>(0); // number of rows
const ref = useRef<DataEditorRef>(null); // gdg ref
// read/write between gdg and the backing data store
const getContent = useCallback((cell: Item): GridCell => {
const [col, row] = cell;
return {
kind: GridCellKind.Text,
allowOverlay: true,
readonly: false,
displayData: String(data[row]?.[header[col]]??""),
data: data[row]?.[header[col]],
};
}, []);
const onCellEdited = useCallback((cell: Item, newValue: EditableGridCell) => {
const [ col, row ] = cell;
data[row][header[col]] = newValue.data;
}, []);
// update the data store from a workbook object
const parse_wb = (wb: WorkBook) => {
const sheet = wb.Sheets[wb.SheetNames[0]];
data = utils.sheet_to_json<any>(sheet);
const range = utils.decode_range(sheet["!ref"]??"A1"); range.e.r = range.s.r;
header = utils.sheet_to_json<string[]>(sheet, {header: 1, range})[0];
setCols(header.map(h => ({title: h, id: h} as GridColumn)));
setRows(data.length);
if(data.length > 0) {
let cells = data.map(
(_,R) => Array.from({length:header.length}, (_,C) => ({cell: ([C,R] as Item)}))
).flat();
ref.current?.updateCells(cells);
}
};
// file input element onchange event handler
const onChange = useCallback(async (e: ChangeEvent<HTMLInputElement>) => {
if(!e.target?.files) return;
parse_wb(read(await e.target.files[0].arrayBuffer()));
}, []);
// when the component loads, fetch and display a sample workbook
useEffect(() => {
(async() => {
parse_wb(read(await (await fetch("https://sheetjs.com/pres.numbers")).arrayBuffer()));
})();
}, []);
// export data
const exportXLSX = useCallback(() => {
// generate worksheet using data with the order specified in the columns array
const ws = utils.json_to_sheet(data, {header: cols.map(c => c.id ?? c.title)});
// rewrite header row with titles
utils.sheet_add_aoa(ws, [cols.map(c => c.title ?? c.id)], {origin: "A1"});
// create workbook
const wb = utils.book_new();
utils.book_append_sheet(wb, ws, "Export"); // replace with sheet name
// download file
writeFileXLSX(wb, "sheetjs-gdg.xlsx");
}, []);
return ( <>
<input type="file" onChange={onChange} />
<button onClick={exportXLSX}><b>Export XLSX!</b></button>
<div className="App">
<DataEditor getCellContent={getContent} columns={cols} rows={rows} onCellEdited={onCellEdited} ref={ref}/>
</div>
<div id="portal"></div>
</>
)
}
export default App;