8.6 KiB
sidebar_position | title | hide_table_of_contents |
---|---|---|
2 | Troubleshooting | true |
Here are some common errors and their resolutions. This is not comprehensive. The issue tracker has a wealth of information and user-contributed examples.
Many of these errors have been fixed in newer releases! Ensure that the latest version of the library is being used. Some legacy endpoints are out of date. Review the Installation instructions.
If issues are not covered in the docs or the issue tracker, or if a solution is not discussed in the documentation, we would appreciate a bug report.
:::info Special Thanks
Special thanks to the early adopters and users for discovering and sharing many workarounds and solutions!
:::
Errors
"Aw Snap!" or "Oops, an error has occurred!"
Browsers have strict memory limits and large spreadsheets can exceed the limits.
When processing very large files is a must, consider running processes in the server with NodeJS or some other server-side technology.
If the files are small, please report to our issue tracker
SCRIPT5022: DataCloneError
IE10 does not properly support Transferable
.
Object doesn't support property or method 'slice'
IE does not implement Uint8Array#slice
. An implementation is included in the
shim script. Check the "Standalone" Installation note
TypeError: f.substr is not a function
Some Google systems use the base64url
encoding. base64url
and base64
are
different encodings. A simple regular expression can translate the data:
var wb = XLSX.read(b64.replace(/_/g, "/").replace(/-/g, "+"), {type:'base64'});
Error: Cannot read property '0' of undefined
FileReader#readAsText
will corrupt binary data including XLSX, XLSB, XLS, and
other binary spreadsheet files.
Applications should use FileReader#readAsArrayBuffer
or Blob#arrayBuffer
.
Examples are included in "User Submissions"
Applications specifically targeting legacy browsers like IE10 should use
FileReader#readAsBinaryString
to read the data and call XLSX.read
using the
binary
type.
Unsupported file undefined
when reading ArrayBuffer objects
Old versions of the library did not automatically detect ArrayBuffer
objects.
Workaround (click to show)
:::warning Legacy workaround
This solution is not recommended for production deployments. Native support
for ArrayBuffer
was added in library version 0.9.9
.
:::
After reading data with FileReader#readAsArrayBuffer
, manually translate to
binary string and call XLSX.read
with type "binary"
document.getElementById('file-object').addEventListener("change", function(e) {
var files = e.target.files,file;
if (!files || files.length == 0) return;
file = files[0];
var fileReader = new FileReader();
fileReader.onload = function (e) {
var filename = file.name;
// pre-process data
var binary = "";
var bytes = new Uint8Array(e.target.result);
var length = bytes.byteLength;
for (var i = 0; i < length; i++) {
binary += String.fromCharCode(bytes[i]);
}
// call 'xlsx' to read the file
var oFile = XLSX.read(binary, {type: 'binary', cellDates:true, cellStyles:true});
};
fileReader.readAsArrayBuffer(file);
});
Browser is stuck!
By default, operations run in the main renderer context and block the browser from updating. Web Workers offload the hard work to separate contexts, freeing up the renderer to update.
Strange exported file names in the web browser
JS and the DOM API do not have a standard approach for creating files. There was
a saveAs
proposal
but it was abandoned in 2014.
The library integrates a number of platform-specific techniques for different
environments. In modern web browsers, the library uses the download
attribute.
Third party libraries like FileSaver
provide an implementation of saveAs
and may help in some cases.
FileSaver.js integration (click to show)
Standalone Build
<script src="https://unpkg.com/file-saver@2.0.5/dist/FileSaver.js"></script>
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
<!-- XLSX.writeFile will use the FileSaver `saveAs` implementation -->
Frameworks and Bundlers
At the time of writing, file-saver@2.0.5
leaks saveAs
to the global scope,
so merely importing the module works:
import FileSaver from 'file-saver'; // as a side effect, `saveAs` is visible
import { writeFile } from 'xlsx'; // writeFile will use the global `saveAs`
Data Issues
Generated XLSX files are very large!
By default, compression is disabled. Set the option compression: true
in the
write
or writeFile
options object. For example:
XLSX.writeFile(workbook, "export.xlsx", { compression: true });
CSV and XLS files with Chinese or Japanese characters look garbled
The ESM build, used in tools like Webpack and in Deno, does not include the codepage tables by default. The "Frameworks and Bundlers" section explains how to load support.
DBF files with Chinese or Japanese characters have underscores
As mentioned in the previous answer, codepage tables must be loaded.
When reading legacy files that do not include character set metadata, the
codepage
option controls the codepage. Common values:
codepage |
Description |
---|---|
874 | Windows Thai |
932 | Japanese Shift-JIS |
936 | Simplified Chinese GBK |
950 | Traditional Chinese Big5 |
1200 | UTF-16 Little Endian |
1252 | Windows Latin 1 |
When writing files in legacy formats like DBF, the default codepage 1252 will be used. The codepage option will override the setting. Any characters missing from the character set will be replaced with underscores.
Worksheet only includes one row of data
Some third-party writer tools will not update the dimensions records in XLSX or XLS or XLSB exports. SheetJS utility functions will skip values not in range.
The following helper function will recalculate the range:
function update_sheet_range(ws) {
var range = {s:{r:Infinity, c:Infinity},e:{r:0,c:0}};
Object.keys(ws).filter(function(x) { return x.charAt(0) != "!"; }).map(XLSX.utils.decode_cell).forEach(function(x) {
range.s.c = Math.min(range.s.c, x.c); range.s.r = Math.min(range.s.r, x.r);
range.e.c = Math.max(range.e.c, x.c); range.e.r = Math.max(range.e.r, x.r);
});
ws['!ref'] = XLSX.utils.encode_range(range);
}
More Code Snippets (click to show)
set_sheet_range
changes a sheet's range given a general target spec that can include only the start or end cell:
/* given the old range and a new range spec, produce the new range */
function change_range(old, range) {
var oldrng = XLSX.utils.decode_range(old), newrng;
if(typeof range == "string") {
if(range.charAt(0) == ":") newrng = {e:XLSX.utils.decode_cell(range.substr(1))};
else if(range.charAt(range.length - 1) == ":") newrng = {s:XLSX.utils.decode_cell(range.substr(0, range.length - 1))};
else newrng = XLSX.utils.decode_range(range);
} else newrng = range;
if(newrng.s) {
if(newrng.s.c != null) oldrng.s.c = newrng.s.c;
if(newrng.s.r != null) oldrng.s.r = newrng.s.r;
}
if(newrng.e) {
if(newrng.e.c != null) oldrng.e.c = newrng.e.c;
if(newrng.e.r != null) oldrng.e.r = newrng.e.r;
}
return XLSX.utils.encode_range(oldrng);
}
/* call change_sheet and modify worksheet */
function set_sheet_range(sheet, range) {
sheet['!ref'] = change_range(sheet['!ref'], range);
}
Adding a cell to a range
function range_add_cell(range, cell) {
var rng = XLSX.utils.decode_range(range);
var c = typeof cell == 'string' ? XLSX.utils.decode_cell(cell) : cell;
if(rng.s.r > c.r) rng.s.r = c.r;
if(rng.s.c > c.c) rng.s.c = c.c;
if(rng.e.r < c.r) rng.e.r = c.r;
if(rng.e.c < c.c) rng.e.c = c.c;
return XLSX.utils.encode_range(rng);
}
range_add_cell("A1:C3","B2")
function add_to_sheet(sheet, cell) {
sheet['!ref'] = range_add_cell(sheet['!ref'], cell);
}