docs.sheetjs.com/docz/static/react/index.html
2022-10-20 14:47:25 -04:00

158 lines
5.8 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!-- sheetjs (C) 2013-present SheetJS https://sheetjs.com -->
<!-- vim: set ts=2: -->
<html lang="en" style="height: 100%">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>SheetJS React Demo</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script src="https://unpkg.com/react/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.production.min.js"></script>
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js"></script>
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
<style>body, #app { height: 100%; }</style>
</head>
<body>
<div class="container-fluid"><h1><a href="https://sheetjs.com">SheetJS × React Demo</a></h1><br /></div>
<div id="app" class="container-fluid"></div>
<script type="text/babel">
/* sheetjs (C) 2013-present SheetJS -- https://sheetjs.com */
/* Notes:
- usage: `ReactDOM.render( <SheetJSApp />, document.getElementById('app') );`
- xlsx.full.min.js is loaded in the head of the HTML page
- this script should be referenced with type="text/babel"
- babel.js in-browser transpiler should be loaded before this script
*/
const { read, writeFile } = XLSX;
const { decode_range, encode_col, sheet_to_json, aoa_to_sheet, book_new, book_append_sheet } = XLSX.utils;
/* generate an array of column objects */
const make_cols = refstr => Array.from({length: decode_range(refstr).e.c + 1}, (_, i) => ({ name: encode_col(i), key: i}));
/* main component */
function SheetJSApp() {
const [data, setData] = React.useState([]);
const [cols, setCols] = React.useState([]);
const handleFile = (file) => {
const reader = new FileReader();
reader.onload = (e) => {
/* Parse data */
const ab = e.target.result;
const wb = read(ab, { type: 'array' });
/* Get first worksheet */
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
/* Convert array of arrays */
const data = sheet_to_json(ws, { header: 1 });
/* Update state */
setData(data);
setCols(make_cols(ws['!ref']))
};
reader.readAsArrayBuffer(file);
}
const exportFile = () => {
/* convert state to workbook */
const ws = aoa_to_sheet(data);
const wb = book_new();
book_append_sheet(wb, ws, "SheetJS");
/* generate XLSX file and send to client */
writeFile(wb, "sheetjs.xlsx")
};
return (
<DragDropFile handleFile={handleFile}>
<div className="row"><div className="col-xs-12">
<DataInput handleFile={handleFile} />
</div></div>
<div className="row"><div className="col-xs-12">
{data.length ? <button className="btn btn-success" onClick={exportFile}>Export</button> : ""}
</div></div>
<div className="row"><div className="col-xs-12">
<OutTable data={data} cols={cols} />
</div></div>
</DragDropFile>
);
}
/* -------------------------------------------------------------------------- */
/*
Simple HTML5 file drag-and-drop wrapper
usage: <DragDropFile handleFile={handleFile}>...</DragDropFile>
handleFile(file:File):void;
*/
function DragDropFile({ handleFile, children }) {
const suppress = (e) => { e.stopPropagation(); e.preventDefault(); };
const handleDrop = (e) => {
e.stopPropagation(); e.preventDefault();
const files = e.dataTransfer.files;
if (files && files[0]) handleFile(files[0]);
};
return ( <div onDrop={handleDrop} onDragEnter={suppress} onDragOver={suppress}>{children}</div> );
}
/*
Simple HTML5 file input wrapper
usage: <DataInput handleFile={callback} />
handleFile(file:File):void;
*/
function DataInput({ handleFile }) {
const handleChange = (e) => {
const files = e.target.files;
if (files && files[0]) handleFile(files[0]);
};
return (
<form className="form-inline">
<div className="form-group">
<label htmlFor="file">Drag or choose a spreadsheet file</label><br />
<input type="file" className="form-control" id="file" accept={SheetJSFT} onChange={handleChange} />
</div>
</form>
)
}
/* list of supported file types */
const SheetJSFT = [
"xlsx", "xlsb", "xlsm", "xls", "xml", "csv", "txt", "ods", "fods", "uos", "sylk", "dif", "dbf", "prn", "qpw", "123", "wb*", "wq*", "html", "htm"
].map(x => `.${x}`).join(",");
/*
Simple HTML Table
usage: <OutTable data={data} cols={cols} />
data:Array<Array<any> >;
cols:Array<{name:string, key:number|string}>;
*/
function OutTable({ data, cols }) {
return (
<div className="table-responsive">
<table className="table table-striped">
<thead>
<tr>{cols.map((c) => <th key={c.key}>{c.name}</th>)}</tr>
</thead>
<tbody>
{data.map((r, i) => <tr key={i}>
{cols.map(c => <td key={c.key}>{r[c.key]}</td>)}
</tr>)}
</tbody>
</table>
</div>
);
}
/* React 18 uses ReactDOM.createRoot; < 18 should use ReactDOM.render */
const root_elt = document.getElementById('app');
if(typeof ReactDOM.createRoot !== "undefined") {
const root = ReactDOM.createRoot(root_elt);
root.render(<SheetJSApp/>);
} else {
ReactDOM.render(<SheetJSApp />, root_elt);
}
</script>
</body>
</html>