Legacy Frameworks
Over the years, many frameworks have been released. Some were popular years ago but have waned in recent years. There are still many deployments using these frameworks and it is oftentimes easier to continue maintenance than to rewrite using modern web techniques.
SheetJS libraries strive to maintain broad browser and JS engine compatibility.
Integration
The SheetJS Standalone scripts
can be referenced in a SCRIPT
tag from an HTML page. For legacy deployments,
the shim script must be loaded first:
<!-- SheetJS version 0.20.3 `shim.min.js` -->
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/shim.min.js"></script>
<!-- SheetJS version 0.20.3 `xlsx.full.min.js` -->
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js"></script>
<script>
/* display SheetJS version */
if(typeof console == "object" && console.log) console.log(XLSX.version);
else if(typeof alert != "undefined") alert(XLSX.version);
else document.write(XLSX.version);
</script>
Internet Explorer
Internet Explorer is unmaintained and users should consider modern browsers. The SheetJS testing grid still includes IE and should work.
The modern upload and download strategies are not available in older versions of IE, but there are approaches using ActiveX or Flash.
Complete Example (click to show)
This demo includes all of the support files for the Flash and ActiveX methods.
- Download the SheetJS Standalone script and shim script. Move both files to the project directory:
The ZIP includes the demo HTML file as well as the Downloadify support files.
Extract the contents to the same folder as the scripts from step 1
- Start a HTTP server:
npx -y http-server .
- Access the
index.html
from a machine with Internet Explorer.
Other Live Demos (click to show)
The hosted solutions may not work in older versions of Windows. For testing, demo pages should be downloaded and hosted using a simple HTTP server.
https://oss.sheetjs.com/sheetjs/ajax.html uses XMLHttpRequest to download test files and convert to CSV
https://oss.sheetjs.com/sheetjs/ demonstrates reading files with FileReader
.
Older versions of IE do not support HTML5 File API but do support Base64.
On MacOS you can get the Base64 encoding with:
$ <target_file base64 | pbcopy
On Windows XP and up you can get the Base64 encoding using certutil
:
> certutil -encode target_file target_file.b64
(note: You have to open the file and remove the header and footer lines)
Upload Strategies
IE10 and IE11 support the standard HTML5 FileReader API:
function handle_fr(e) {
var f = e.target.files[0];
var reader = new FileReader();
reader.onload = function(e) {
var wb = XLSX.read(e.target.result);
process_wb(wb); // DO SOMETHING WITH wb HERE
};
reader.readAsArrayBuffer(f);
}
input_dom_element.addEventListener('change', handle_fr, false);
Blob#arrayBuffer
is not supported in IE!
ActiveX Upload
Through the Scripting.FileSystemObject
object model, a script in the VBScript
scripting language can read from an arbitrary path on the file system. The shim
includes a special IE_LoadFile
function to read binary data from files. This
should be called from a file input onchange
event:
var input_dom_element = document.getElementById("file");
function handle_ie() {
/* get data from selected file */
var path = input_dom_element.value;
var bstr = IE_LoadFile(path);
/* read workbook */
var wb = XLSX.read(bstr, {type: 'binary'});
/* DO SOMETHING WITH workbook HERE */
}
input_dom_element.attachEvent('onchange', handle_ie);
Download Strategies
As part of the File API implementation, IE10 and IE11 provide the msSaveBlob
and msSaveOrOpenBlob
functions to save blobs to the client computer. This
approach is embedded in XLSX.writeFile
and no additional shims are necessary.
Flash-based Download
It is possible to write to the file system using a SWF file. Downloadify
1
implements one solution. Since a genuine click is required, there is no way to
force a download. The safest data type is Base64:
Downloadify.create(element_id, {
/* Downloadify boilerplate */
swf: 'downloadify.swf',
downloadImage: 'download.png',
width: 100, height: 30,
transparent: false, append: false,
/* Key parameters */
filename: "test.xlsx",
dataType: 'base64',
data: function() { return XLSX.write(wb, { bookType: "xlsx", type: 'base64' }); }
});
ActiveX Download
Through the Scripting.FileSystemObject
object model, a script in the VBScript
scripting language can write to an arbitrary path on the filesystem. The shim
includes a special IE_SaveFile
function to write binary strings to file. It
attempts to write to the Downloads folder or Documents folder or Desktop.
This approach does not require user interaction, but ActiveX must be enabled. It
is embedded as a strategy in writeFile
and used only if the shim script is
included in the page and the relevant features are enabled on the target system.
Frameworks
Dojo Toolkit
The exposition has been moved to a separate page.
KnockoutJS
KnockoutJS was a popular MVVM framework.
The Live demo shows a view model that is updated with file data and exported to spreadsheets.
Full Exposition (click to show)
State
Arrays of arrays are the simplest data structure for representing worksheets.
var aoa = [
[1, 2], // A1 = 1, B1 = 2
[3, 4] // A1 = 3, B1 = 4
];
ko.observableArray
should be used to create the view model:
function ViewModel() {
/* use an array of arrays */
this.aoa = ko.observableArray([ [1,2], [3,4] ]);
}
/* create model */
var model = new ViewModel();
ko.applyBindings(model);
XLSX.utils.sheet_to_json
with header: 1
generates data for the model:
/* starting from a `wb` workbook object, pull first worksheet */
var ws = wb.Sheets[wb.SheetNames[0]];
/* convert the worksheet to an array of arrays */
var aoa = XLSX.utils.sheet_to_json(ws, {header:1});
/* update model */
model.aoa(aoa);
XLSX.utils.aoa_to_sheet
generates worksheets from the model:
var aoa = model.aoa();
var ws = XLSX.utils.aoa_to_sheet(aoa);
Data Binding
data-bind="foreach: ..."
provides a simple approach for binding to TABLE
:
<table data-bind="foreach: aoa">
<tr data-bind="foreach: $data">
<td><span data-bind="text: $data"></span></td>
</tr>
</table>
Unfortunately the nested "foreach: $data"
binding is read-only. A two-way
binding is possible using the $parent
and $index
binding context properties:
<table data-bind="foreach: aoa">
<tr data-bind="foreach: $data">
<td><input data-bind="value: $parent[$index()]" /></td>
</tr>
</table>