updated demos [ci skip]
- frameworks: react, react-native, preact, next.js, weex, nuxt.js - deployments: nodejs server, duktape, chakra, electron, nw.js
This commit is contained in:
commit
0b29aa4c0f
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
SheetJS
|
||||
.next
|
22
Makefile
Normal file
22
Makefile
Normal file
@ -0,0 +1,22 @@
|
||||
.PHONY: react
|
||||
react: ## Simple server for react and clones
|
||||
python -mSimpleHTTPServer
|
||||
|
||||
.PHONY: next
|
||||
next: ## next.js demo
|
||||
# next doesn't support jsx extension
|
||||
mkdir -p pages
|
||||
cp sheetjs.jsx pages/sheetjs.js
|
||||
next
|
||||
|
||||
.PHONY: native
|
||||
native: ## Build react-native project
|
||||
bash ./native.sh
|
||||
|
||||
.PHONY: ios
|
||||
ios: native ## react-native ios sim
|
||||
cd SheetJS; react-native run-ios; cd -
|
||||
|
||||
.PHONY: android
|
||||
android: native ## react-native android sim
|
||||
cd SheetJS; react-native run-android; cd -
|
68
README.md
Normal file
68
README.md
Normal file
@ -0,0 +1,68 @@
|
||||
# React
|
||||
|
||||
The `xlsx.core.min.js` and `xlsx.full.min.js` scripts are designed to be dropped
|
||||
into web pages with script tags e.g.
|
||||
|
||||
```html
|
||||
<script src="xlsx.full.min.js"></script>
|
||||
```
|
||||
|
||||
The library can also be imported directly from JSX code with:
|
||||
|
||||
```js
|
||||
import * as XLSX from 'xlsx';
|
||||
```
|
||||
|
||||
This demo shows a simple JSX component transpiled in the browser using the 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`)
|
||||
- `preact` using the react compatibility library
|
||||
- `react-native` deployment for iOS and android
|
||||
|
||||
## Internal State
|
||||
|
||||
The simplest state representation is an array of arrays. To avoid having the
|
||||
table component depend on the library, the column labels are precomputed. The
|
||||
state in this demo is shaped like the following object:
|
||||
|
||||
```js
|
||||
{
|
||||
cols: [
|
||||
{ name: "A", key: 0 },
|
||||
{ name: "B", key: 1 },
|
||||
{ name: "C", key: 2 },
|
||||
],
|
||||
data: [
|
||||
[ "id", "name", "value" ],
|
||||
[ 1, "sheetjs", 7262 ]
|
||||
[ 2, "js-xlsx", 6969 ]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The appropriate state model is application-specific.
|
||||
|
||||
## React Native
|
||||
|
||||
<img src="screen.png" width="400px"/>
|
||||
|
||||
Reproducing the full project is straightforward:
|
||||
|
||||
```bash
|
||||
react-native init SheetJS
|
||||
cd SheetJS
|
||||
npm i -S xlsx react react-native react-native-table-component react-native-fs
|
||||
cp ../react-native.js index.ios.js
|
||||
cp ../react-native.js index.android.js
|
||||
react-native link
|
||||
```
|
||||
|
||||
This uses `react-native-fs` to read and write files on devices. The app will
|
||||
prompt before reading and after writing data. The printed location will be:
|
||||
|
||||
- android: path in the device filesystem
|
||||
- iOS simulator: local path to file
|
||||
- iOS device: a path accessible from iTunes App Documents view
|
40
index.html
Normal file
40
index.html
Normal file
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- xlsx.js (C) 2013-present SheetJS http://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@6/babel.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js"></script>
|
||||
<script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
|
||||
<script src="https://unpkg.com/file-saver/FileSaver.js"></script>
|
||||
<style>body, #app { height: 100%; };</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<h1><a href="http://sheetjs.com">SheetJS React Demo</a></h1>
|
||||
<br />
|
||||
<a href="https://github.com/SheetJS/js-xlsx">Source Code Repo</a><br />
|
||||
<a href="https://github.com/SheetJS/js-xlsx/issues">Issues? Something look weird? Click here and report an issue</a><br /><br />
|
||||
</div>
|
||||
<div id="app" class="container-fluid"></div>
|
||||
<script type="text/babel" src="sheetjs.jsx"></script>
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-36810333-1']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
<script type="text/babel">
|
||||
ReactDOM.render( <SheetJSApp />, document.getElementById('app') );
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
17
native.sh
Executable file
17
native.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -e SheetJS ]; then
|
||||
react-native init SheetJS
|
||||
cd SheetJS
|
||||
npm i -S xlsx react react-native react-native-table-component react-native-fs
|
||||
cd -
|
||||
fi
|
||||
if [ ! -e SheetJS/logo.png ]; then
|
||||
curl -O http://oss.sheetjs.com/assets/img/logo.png
|
||||
mv logo.png SheetJS/logo.png
|
||||
fi
|
||||
cp react-native.js SheetJS/index.ios.js
|
||||
cp react-native.js SheetJS/index.android.js
|
||||
cd SheetJS;
|
||||
react-native link
|
||||
cd -;
|
1
pages/.gitignore
vendored
Normal file
1
pages/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
sheetjs.js
|
26
pages/index.js
Normal file
26
pages/index.js
Normal file
@ -0,0 +1,26 @@
|
||||
import Head from 'next/head'
|
||||
import SheetJSApp from './sheetjs.js'
|
||||
export default () => (
|
||||
<div>
|
||||
<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@6/babel.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js"></script>
|
||||
<script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
|
||||
<script src="https://unpkg.com/file-saver/FileSaver.js"></script>
|
||||
<style jsx>{`
|
||||
body, #app { height: 100%; };
|
||||
`}</style>
|
||||
</Head>
|
||||
<div class="container-fluid">
|
||||
<h1><a href="http://sheetjs.com">SheetJS React Demo</a></h1>
|
||||
<br />
|
||||
<a href="https://github.com/SheetJS/js-xlsx">Source Code Repo</a><br />
|
||||
<a href="https://github.com/SheetJS/js-xlsx/issues">Issues? Something look weird? Click here and report an issue</a><br /><br />
|
||||
</div>
|
||||
<SheetJSApp />
|
||||
</div>
|
||||
)
|
42
preact.html
Normal file
42
preact.html
Normal file
@ -0,0 +1,42 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- xlsx.js (C) 2013-present SheetJS http://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@6/babel.min.js"></script>
|
||||
<script src="//unpkg.com/preact"></script>
|
||||
<script src="//unpkg.com/proptypes"></script>
|
||||
<script src="//unpkg.com/preact-compat"></script>
|
||||
<script>var React = preactCompat, ReactDOM = preactCompat;</script>
|
||||
<script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
|
||||
<script src="https://unpkg.com/file-saver/FileSaver.js"></script>
|
||||
<style>body, #app { height: 100%; };</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<h1><a href="http://sheetjs.com">SheetJS React Demo</a></h1>
|
||||
<br />
|
||||
<a href="https://github.com/SheetJS/js-xlsx">Source Code Repo</a><br />
|
||||
<a href="https://github.com/SheetJS/js-xlsx/issues">Issues? Something look weird? Click here and report an issue</a><br /><br />
|
||||
</div>
|
||||
<div id="app" class="container-fluid"></div>
|
||||
<script type="text/babel" src="sheetjs.jsx"></script>
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-36810333-1']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
<script type="text/babel">
|
||||
ReactDOM.render( <SheetJSApp />, document.getElementById('app') );
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
76
react-native.js
vendored
Normal file
76
react-native.js
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
|
||||
import * as XLSX from 'xlsx';
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { AppRegistry, StyleSheet, Text, View, Button, Alert, Image } from 'react-native';
|
||||
import { Table, Row, Rows } from 'react-native-table-component';
|
||||
import { writeFile, readFile, DocumentDirectoryPath } from 'react-native-fs'
|
||||
|
||||
const DDP = DocumentDirectoryPath + "/";
|
||||
|
||||
const make_cols = refstr => Array.from({length: XLSX.utils.decode_range(refstr).e.c + 1}, (x,i) => XLSX.utils.encode_col(i));
|
||||
|
||||
export default class SheetJS extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
data: [[1,2,3],[4,5,6]],
|
||||
cols: make_cols("A1:C2")
|
||||
};
|
||||
this.importFile = this.importFile.bind(this);
|
||||
this.exportFile = this.exportFile.bind(this);
|
||||
};
|
||||
importFile() {
|
||||
Alert.alert("Rename file to sheetjs.xlsx", "Copy to " + DDP, [
|
||||
{text: 'Cancel', onPress: () => {}, style: 'cancel' },
|
||||
{text: 'Import', onPress: () => {
|
||||
readFile(DDP + "sheetjs.xlsx", 'ascii').then((res) => {
|
||||
const wb = XLSX.read(res, {type:'binary'});
|
||||
const wsname = wb.SheetNames[0];
|
||||
const ws = wb.Sheets[wsname];
|
||||
const data = XLSX.utils.sheet_to_json(ws, {header:1});
|
||||
this.setState({ data: data, cols: make_cols(ws['!ref']) });
|
||||
}).catch((err) => { Alert.alert("importFile Error", "Error " + err.message); });
|
||||
}}
|
||||
]);
|
||||
}
|
||||
exportFile() {
|
||||
const ws = XLSX.utils.aoa_to_sheet(this.state.data);
|
||||
const wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, "SheetJS");
|
||||
const wbout = XLSX.write(wb, {type:"binary", bookType:"xlsx"});
|
||||
const file = DDP + "sheetjsw.xlsx";
|
||||
writeFile(file, wbout, 'ascii').then((res) =>{
|
||||
Alert.alert("exportFile success", "Exported to " + file);
|
||||
}).catch((err) => { Alert.alert("exportFile Error", "Error " + err.message); });
|
||||
};
|
||||
render() { return (
|
||||
<View style={styles.container}>
|
||||
<Image style={{width: 128, height: 128}} source={require('./logo.png')} />
|
||||
<Text style={styles.welcome}>SheetJS React Native Demo</Text>
|
||||
<Text style={styles.instructions}>Import Data</Text>
|
||||
<Button onPress={this.importFile} title="Import data from a spreadsheet" color="#841584" />
|
||||
<Text style={styles.instructions}>Export Data</Text>
|
||||
<Button disabled={!this.state.data.length} onPress={this.exportFile} title="Export data to XLSX" color="#841584" />
|
||||
|
||||
<Text style={styles.instructions}>Current Data</Text>
|
||||
<Table style={styles.table}>
|
||||
<Row data={this.state.cols} style={styles.thead} textStyle={styles.text}/>
|
||||
<Rows data={this.state.data} style={styles.tr} textStyle={styles.text}/>
|
||||
</Table>
|
||||
</View>
|
||||
); };
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF' },
|
||||
welcome: { fontSize: 20, textAlign: 'center', margin: 10 },
|
||||
instructions: { textAlign: 'center', color: '#333333', marginBottom: 5 },
|
||||
thead: { height: 40, backgroundColor: '#f1f8ff' },
|
||||
tr: { height: 30 },
|
||||
text: { marginLeft: 5 },
|
||||
table: { width: "100%" }
|
||||
});
|
||||
|
||||
AppRegistry.registerComponent('SheetJS', () => SheetJS);
|
BIN
screen.png
Normal file
BIN
screen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 KiB |
139
sheetjs.jsx
Normal file
139
sheetjs.jsx
Normal file
@ -0,0 +1,139 @@
|
||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
const SheetJSFT = [
|
||||
"xlsx", "xlsb", "xlsm", "xls", "xml", "csv", "txt", "ods", "fods", "uos", "sylk", "dif", "dbf", "prn", "qpw", "123", "wb*", "wq*", "html", "htm"
|
||||
].map(function(x) { return "." + x; }).join(",");
|
||||
|
||||
/*
|
||||
Simple HTML5 file drag-and-drop wrapper
|
||||
usage: <DragDropFile handleFile={handleFile}>...</DragDropFile>
|
||||
handleFile(file:File):void;
|
||||
*/
|
||||
class DragDropFile extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onDrop = this.onDrop.bind(this);
|
||||
};
|
||||
suppress(evt) { evt.stopPropagation(); evt.preventDefault(); };
|
||||
onDrop(evt) { evt.stopPropagation(); evt.preventDefault();
|
||||
const files = evt.dataTransfer.files;
|
||||
if(files && files[0]) this.props.handleFile(files[0]);
|
||||
};
|
||||
render() { return (
|
||||
<div onDrop={this.onDrop} onDragEnter={this.suppress} onDragOver={this.suppress}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
); };
|
||||
};
|
||||
|
||||
/*
|
||||
Simple HTML5 file input wrapper
|
||||
usage: <DataInput handleFile={callback} />
|
||||
handleFile(file:File):void;
|
||||
*/
|
||||
class DataInput extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
};
|
||||
handleChange(e) {
|
||||
const files = e.target.files;
|
||||
if(files && files[0]) this.props.handleFile(files[0]);
|
||||
};
|
||||
render() { return (
|
||||
<form className="form-inline">
|
||||
<div className="form-group">
|
||||
<label htmlFor="file">Spreadsheet</label>
|
||||
<input type="file" className="form-control" id="file" accept={SheetJSFT} onChange={this.handleChange} />
|
||||
</div>
|
||||
</form>
|
||||
); };
|
||||
}
|
||||
|
||||
/* generate an array of column objects */
|
||||
const make_cols = refstr => Array(XLSX.utils.decode_range(refstr).e.c + 1).fill(0).map((x,i) => ({name:XLSX.utils.encode_col(i), key:i}));
|
||||
|
||||
/*
|
||||
Simple HTML Table
|
||||
usage: <OutTable data={data} cols={cols} />
|
||||
data:Array<Array<any> >;
|
||||
cols:Array<{name:string, key:number|string}>;
|
||||
*/
|
||||
class OutTable extends React.Component {
|
||||
constructor(props) { super(props); };
|
||||
render() { return (
|
||||
<div className="table-responsive">
|
||||
<table className="table table-striped">
|
||||
<thead>
|
||||
<tr>{this.props.cols.map((c) => <th>{c.name}</th>)}</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{this.props.data.map(r => <tr>
|
||||
{this.props.cols.map(c => <td key={c.key}>{ r[c.key] }</td>)}
|
||||
</tr>)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
); };
|
||||
};
|
||||
|
||||
/* see Browser download file example in docs */
|
||||
function s2ab(s) {
|
||||
const buf = new ArrayBuffer(s.length);
|
||||
const view = new Uint8Array(buf);
|
||||
for (let i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
|
||||
return buf;
|
||||
}
|
||||
|
||||
class SheetJSApp extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
data: [], /* Array of Arrays e.g. [["a","b"],[1,2]] */
|
||||
cols: [] /* Array of column objects e.g. { name: "C", key: 2 } */
|
||||
};
|
||||
this.handleFile = this.handleFile.bind(this);
|
||||
this.exportFile = this.exportFile.bind(this);
|
||||
};
|
||||
handleFile(file/*:File*/) {
|
||||
/* Boilerplate to set up FileReader */
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
/* Parse data */
|
||||
const bstr = e.target.result;
|
||||
const wb = XLSX.read(bstr, {type:'binary'});
|
||||
/* Get first worksheet */
|
||||
const wsname = wb.SheetNames[0];
|
||||
const ws = wb.Sheets[wsname];
|
||||
/* Convert array of arrays */
|
||||
const data = XLSX.utils.sheet_to_json(ws, {header:1});
|
||||
/* Update state */
|
||||
this.setState({ data: data, cols: make_cols(ws['!ref']) });
|
||||
};
|
||||
reader.readAsBinaryString(file);
|
||||
};
|
||||
exportFile() {
|
||||
/* convert state to workbook */
|
||||
const ws = XLSX.utils.aoa_to_sheet(this.state.data);
|
||||
const wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, "SheetJS");
|
||||
/* generate XLSX file */
|
||||
const wbout = XLSX.write(wb, {type:"binary", bookType:"xlsx"});
|
||||
/* send to client */
|
||||
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "sheetjs.xlsx");
|
||||
};
|
||||
render() { return (
|
||||
<DragDropFile handleFile={this.handleFile}>
|
||||
<div className="row"><div className="col-xs-12">
|
||||
<DataInput handleFile={this.handleFile} />
|
||||
</div></div>
|
||||
<div className="row"><div className="col-xs-12">
|
||||
<button disabled={!this.state.data.length} className="btn btn-success" onClick={this.exportFile}>Export</button>
|
||||
</div></div>
|
||||
<div className="row"><div className="col-xs-12">
|
||||
<OutTable data={this.state.data} cols={this.state.cols} />
|
||||
</div></div>
|
||||
</DragDropFile>
|
||||
); };
|
||||
};
|
||||
|
||||
if(typeof module !== 'undefined') module.exports = SheetJSApp
|
Loading…
Reference in New Issue
Block a user