0

I am trying to Upload an excel file at client side in AngularJS UI Grid using SheetJS. The code works fine in Chrome and Firefox, but on IE it gives the following error Object doesn't support property or method 'readAsBinaryString'

I tried various solution on stack overflow like using readAsBinaryArray or readAsText instead of using readAsBinaryString but I am unable to solve my problem.

I am sharing my code below it consists of 3 files: index.html, app.js and main.css

Code for index.html is as below

  <!DOCTYPE html>
    <html ng-app="app">

  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=11" />
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-Control" content="no-cache">
    <meta http-equiv="Expires" content="Sat, 01 Dec 2001 00:00:00 GMT">
    <link data-require="bootstrap-css@*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.js"></script>
    <script src="https://cdn.rawgit.com/SheetJS/js-xlsx/v0.8.0/dist/xlsx.full.min.js"></script>
    <script src="https://cdn.rawgit.com/SheetJS/js-xlsx/v0.8.0/dist/ods.js"></script>
    <script src="https://github.com/SheetJS/js-xlsx/blob/master/shim.js"></script>
    <script src="http://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/release/3.0.0-rc.22/ui-grid.min.js"></script>
    <link rel="stylesheet" href="http://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/release/3.0.0-rc.22/ui-grid.min.css" />
    <link rel="stylesheet" href="css/main.css" type="text/css" />
  </head>

  <body>
    <div ng-controller="MainCtrl as vm">

      <div id="grid1" ui-grid="vm.gridOptions" class="grid">
        <div class="grid-msg-overlay" ng-show="!vm.gridOptions.data.length">
          <div class="msg">
            <div class="center">
              <span class="muted">Select Excel File</span>
              <br />
              <input ng-attr-type="{{'file'}}" accept=".xls,.xlsx,.csv" fileread="" opts="vm.gridOptions" multiple="false" />
            </div>
          </div>
        </div>
      </div>
          <br />
          <br />
          <button type="button" class="btn btn-success" ng-    click="vm.reset()">Reset Grid</button>
          <span>  </span>

         <button type="button" class="btn btn-success" ng-click="">Save</button>

    </div>
    <script src="js/app.js"></script>
  </body>

   </html>

Code for app.js is as below

 (function (angular) {
    "use strict";

    angular.module('app', ['ui.grid']).controller('MainCtrl', ['$scope',          function ($scope) {
     var vm = this;
     vm.gridOptions = {};

     vm.reset = reset;

    function reset() {
      vm.gridOptions.data = [];
      vm.gridOptions.columnDefs = [];
     }   
    }])


    .directive("fileread", [function () {
    return {
    scope: {
      opts: '='
    },
      link: function ($scope, $elm, $attrs) {
      $elm.on('change', function (changeEvent) {
        var reader = new FileReader();

        reader.onload = function (evt) {
          $scope.$apply(function () {
            var data = evt.target.result;

            var workbook = XLSX.read(data, {type: 'binary'});

            var headerNames = XLSX.utils.sheet_to_json(   workbook.Sheets[workbook.SheetNames[0]], { header: 1 })[0];

            var data = XLSX.utils.sheet_to_json( workbook.Sheets[workbook.SheetNames[0]]);

            $scope.opts.columnDefs = [];
            headerNames.forEach(function (h) {
              $scope.opts.columnDefs.push({ field: h });
            });

            $scope.opts.data = data;

            $elm.val(null);
          });
        };

        reader.readAsBinaryString(changeEvent.target.files[0]);
      });
     }
    }
    }]);

Code for main.css

body { 
 padding: 20px;
 }

 .grid {
 width: 100%;
 height: 250px;
 }

 .grid-msg-overlay {
 position: absolute;
 top: 0;
 bottom: 0;
 width: 100%;
 background: rgba(0, 0, 0, 0.4);
 }

 .grid-msg-overlay .msg {
 opacity: 1;
 position: absolute;
 top: 20%;
 left: 20%;
 width: 60%;
 height: 50%;
 background-color: #eee;
 border-radius: 4px;
 border: 1px solid #555;
 text-align: center;
 font-size: 24px;
 display: table;
 }

 .grid-msg-overlay .msg > .center {
 display: table-cell;
 vertical-align: middle;
 }

.grid input[type="file"] {
font-size: 14px;
display: inline-block;
}

Please can someone help me to understand how can I resolve this issue

1 Answer 1

0

IE does not implement the FileReader readAsBinaryString() method. However, as per the SheetJS documentation, you can test for support, and fallback to readAsArrayBuffer() instead.

var readAsBinary = "readAsBinaryString" in FileReader;
if (readAsBinary) {
  reader.readAsBinaryString(changeEvent.target.files[0]);
} else {
  reader.readAsArrayBuffer(changeEvent.target.files[0]);
}

Then in the unload method you have to handle the result as follows:

var workbook;
if (readAsBinary) {
  workbook = XLSX.read(data, {type: 'binary'});
} else {
  function fixdata(data) {
    var o = "", l = 0, w = 10240;
    for(; l<data.byteLength/w; ++l) o+=String.fromCharCode.apply(null,new Uint8Array(data.slice(l*w,l*w+w)));
    o+=String.fromCharCode.apply(null, new Uint8Array(data.slice(l*w)));
    return o;
  }
  workbook = XLSX.read(btoa(fixdata(data)), {type: 'base64'});
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.