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([]); // gdg column objects const [rows, setRows] = useState(0); // number of rows const ref = useRef(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(sheet); const range = utils.decode_range(sheet["!ref"]??"A1"); range.e.r = range.s.r; header = utils.sheet_to_json(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) => { 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 ( <>
) } export default App;