-
Notifications
You must be signed in to change notification settings - Fork 61
/
Copy pathReactHTMLTableToExcel.jsx
113 lines (94 loc) · 3.55 KB
/
ReactHTMLTableToExcel.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* global window, document, Blob */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
const propTypes = {
table: PropTypes.string.isRequired,
filename: PropTypes.string.isRequired,
sheet: PropTypes.string.isRequired,
id: PropTypes.string,
className: PropTypes.string,
buttonText: PropTypes.string,
};
const defaultProps = {
id: 'button-download-as-xls',
className: 'button-download',
buttonText: 'Download',
};
class ReactHTMLTableToExcel extends Component {
constructor(props) {
super(props);
this.handleDownload = this.handleDownload.bind(this);
}
static base64(s) {
return window.btoa(unescape(encodeURIComponent(s)));
}
static format(s, c) {
return s.replace(/{(\w+)}/g, (m, p) => c[p]);
}
handleDownload() {
if (!document) {
if (process.env.NODE_ENV !== 'production') {
console.error('Failed to access document object');
}
return null;
}
if (document.getElementById(this.props.table).nodeType !== 1 || document.getElementById(this.props.table).nodeName !== 'TABLE') {
if (process.env.NODE_ENV !== 'production') {
console.error('Provided table property is not html table element');
}
return null;
}
const table = document.getElementById(this.props.table).outerHTML;
const sheet = String(this.props.sheet);
const filename = `${String(this.props.filename)}.xls`;
const uri = 'data:application/vnd.ms-excel;base64,';
const template =
'<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-mic' +
'rosoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><meta cha' +
'rset="UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:Exce' +
'lWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/>' +
'</x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></' +
'xml><![endif]--></head><body>{table}</body></html>';
const context = {
worksheet: sheet || 'Worksheet',
table,
};
// If IE11
if (window.navigator.msSaveOrOpenBlob) {
const fileData = [
`${'<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-mic' + 'rosoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><meta cha' + 'rset="UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:Exce' + 'lWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/>' + '</x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></' + 'xml><![endif]--></head><body>'}${table}</body></html>`,
];
const blobObject = new Blob(fileData);
document.getElementById('react-html-table-to-excel').click()(() => {
window.navigator.msSaveOrOpenBlob(blobObject, filename);
});
return true;
}
const element = window.document.createElement('a');
element.href =
uri +
ReactHTMLTableToExcel.base64(
ReactHTMLTableToExcel.format(template, context),
);
element.download = filename;
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
return true;
}
render() {
return (
<button
id={this.props.id}
className={this.props.className}
type="button"
onClick={this.handleDownload}
>
{this.props.buttonText}
</button>
);
}
}
ReactHTMLTableToExcel.propTypes = propTypes;
ReactHTMLTableToExcel.defaultProps = defaultProps;
export default ReactHTMLTableToExcel;