Question

I am using xlsx.core.min.js to upload excel files to SP and pass their contents to a new list. I have it working in Edge but it will not work in IE 11.

The first console error I received was "Object doesn't support property or method 'charCodeAt'"

I read about the compatibility issues with .readAsArrayBuffer() and replaced it. Then I started receiving the error "Object doesn't support property or method 'readAsBinaryString'"

**note: using only .readAsArrayBuffer() resulted in the original 'charCodeAt' console error **

How can I get this code working? Thank you in advance!

function ExportToTable() {
            var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.xlsx|.xls)$/;
            /*Checks whether the file is a valid excel file*/
            if (regex.test($("#excelfile").val().toLowerCase())) {
                var xlsxflag = false; 
     /*Flag for checking whether excel is .xls format or .xlsx format*/
            if ($("#excelfile").val().toLowerCase().indexOf(".xlsx") > 0) {
                xlsxflag = true;
            }
            /*Checks whether the browser supports HTML5*/
            if (typeof (FileReader) != "undefined") {
                var reader = new FileReader();
                reader.onload = function (e) {
                    var data = e.target.result;
                    /*Converts the excel data in to object*/
                    if (xlsxflag) {
                        var workbook = XLSX.read(data, { type: 'binary' });
                    }
                    else {
                        var workbook = XLS.read(data, { type: 'binary' });
                    }
                    /*Gets all the sheetnames of excel in to a variable*/
                    var sheet_name_list = workbook.SheetNames;

                    var cnt = 0; /*This is used for restricting the script to consider only first sheet of excel*/
                    sheet_name_list.forEach(function (y) { /*Iterate through all sheets*/
                        /*Convert the cell value to Json*/
                        if (xlsxflag) {
                            var exceljson = XLSX.utils.sheet_to_json(workbook.Sheets[y]);
                        }
                        else {
                            var exceljson = XLS.utils.sheet_to_row_object_array(workbook.Sheets[y]);
                        }
                        //alert (exceljson.length + " ----" + cnt);
                        if (exceljson.length > 0 && cnt == 0) {
                            BindTable(exceljson, '#exceltable');
                            cnt++;
                        }
                    });
                    $('#exceltable').show();
                }
                if (xlsxflag) {/*If excel file is .xlsx extension than creates a Array Buffer from excel*/
                    reader.readAsArrayBuffer($("#excelfile")[0].files[0]);
                }
                else {
                    reader.readAsBinaryString($("#excelfile")[0].files[0]);
                }
            }
            else {
               // alert("Sorry! Your browser does not support HTML5!");
           }
        }
        else {
           // alert("Please upload a valid Excel file!");
        }

    }
Was it helpful?

Solution

Try using readAsDataUrl instead of readAsBinaryString. readAsBinaryString was originally in the specification, then removed, and then added back for backward comparability. As a result, it wasn't implemented in IE.

Ref: FileReader.readAsBinaryString()

Now I'm guessing that xlsx.core.min.js isn't going to know what to do with a data url and is expecting binary. So you'll have to do the decoding before doing the XLSX.read or XLS.read, and then pass the decoded binary to whichever read. If I'm wrong, and there is some way to change { type: 'binary' } to something that indicates a type of data url, you should just do that.

But if that's not an option, here's a helper function I used with a similar problem to convert a data url to binary:

/**
 * Convert a base64 encoded data url to binary.
 * @input {string} - either a base 64 encoded string or a base64
 * encoded data url.
 * @mime_type {string} - parsed from the data url if possible, 
 * otherwise this is is used, and defaults to 
 * 'application/octet-stream'
 * @returns {Blob} - the decoded binary.
 */
var dataUri2Blob = function(input, mime_type) {
    var result;

    // if not a data url, assume the input is the bytes and 
    // then mimeType is passed, or hard code the 
    // 'application/octet-stream' (which may not work)
    var bytes = input;
    var mimeType = mime_type || "application/octet-stream";

    // if it looks like a data url, parse the bytes and 
    // mimeType from it
    if(input.match(/^data:[-+\w]+\/[-+\w]+;base64,/i)) {
        bytes = atob(input.split(',')[1]);
        mimeType = input.split(',')[0].
            split(':')[1].
            split(';')[0];
    }

    // create an array buffer and decode the bytes to it
    var buffer = new ArrayBuffer(bytes.length);
    var uia = new Uint8Array(buffer);
    for (var i = 0; i < bytes.length; i++) {
        uia[i] = bytes.charCodeAt(i);
    }

    try {
        // create a data view and instantiate a new Blob
        // by mime type
        var dataView = new DataView(buffer);
        result = new Blob([dataView], {
            type: mimeType
        });
    } catch (e) {
        // Old browser, need to use blob builder, including 
        // all versions of internet explorer
        window.BlobBuilder = window.BlobBuilder ||
            window.WebKitBlobBuilder ||
            window.MozBlobBuilder ||
            window.MSBlobBuilder;

        if (window.BlobBuilder) {
            // if there is a blob builder, append the array 
            // buffer to it and get the contents by mime type.
            var blobBuilder = new BlobBuilder();
            blobBuilder.append(buffer);
            result = blobBuilder.getBlob(mimeType);
        }
    }

    return result;
};

Now to use it, you'd just take pass the data url to it like:

var binary = dataUri2Blob(e.target.result);

You don't need to specify the mime_type because it will be parsed from the data url. And you now pass (binary) into which ever XSL(X).read method.

Ref: Answer to TypeError: Object doesn't support property or method 'charCodeAt'

Licensed under: CC-BY-SA with attribution
Not affiliated with sharepoint.stackexchange
scroll top