0

I'm trying to create a moule where the user can upload an excel file an get data from the document. I'm using the js-xlsx library. Right now, with the next code, i'm getting the info on the console of my example file as a json:

$scope.ExcelExport= function (event) {

    var input = event.target;
    var reader = new FileReader();
    reader.onload = function(){
        var fileData = reader.result;
        var wb = XLSX.read(fileData, {type : 'binary'});

        wb.SheetNames.forEach(function(sheetName){
        var rowObj = XLSX.utils.sheet_to_json(wb.Sheets[sheetName]);
        $scope.jsonObj = rowObj;
        console.log($scope.jsonObj);
        })

    };
    reader.readAsBinaryString(input.files[0]);
    };

I know i have to save the document, but: there's a way to stored the readed info on my console and show it on the html view?

Per example, let's say that my example file have the next data in two columns:

Person | Job |(This is the header) Chuck | Developer| John | Teacher |

And i want to populate a table:

<div class="row">
<div class="col-lg-11">
    <form class="form-inline">
        <div class="am form-group">
        </div>
        <div class="container">
            <table class="table table-hover">
                <thead>
                <tr>
                    <th>Person</th>
                    <th>Job</th>
                </tr>
                </thead>
                <tbody>
                <tr ng-repeat="x in jsonObj">
                    <th>{{x.Person}}</th>
                    <th>{{x.Job}}</th>
                </tr>
                </tbody>
            </table>
        </div>
    </form>
</div>

I'm using angularjs and Javascript.

Thanx in advance!

georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • `reader.onload` callback is outside angular context. Need to tell angular to run a digest when you change scope values outside angular. Try calling $scope.$apply() – charlietfl Dec 13 '17 at 21:56
  • Thaks, i've tried and send me the next alert: `TypeError: Cannot read property 'charCodeAt' of null` – Chuck Villavicencio Dec 13 '17 at 22:28

1 Answers1

3

As charlietfl correctly pointed out, you have to call $scope.$apply() whenever you change something outside of angular.

As for the error TypeError: Cannot read property 'charCodeAt' of null, change:

var fileData = reader.result;

to

var fileData = input.result;

Here's how I'd organize this feature.

Your directive:

angular.module("app").directive("importSheetJs", function($parse) {
  return {
    link: function($scope, $elm, $attrs) {
      // Parse callback function from attribute
      var expressionHandler = $parse($attrs.onSheetLoad);

      // Pass upload event to callback    
      $elm.on("change", function(changeEvent) {
        var reader = new FileReader();
        reader.onload = function(e) {
          expressionHandler($scope, { e: e });
        };
        reader.readAsBinaryString(changeEvent.target.files[0]);
      });
    }
  };
});

Your controller:

angular.module("app").controller("MainController", function($scope) {
  $scope.loadWorksheet = function(e) {
    // Read Workbook
    var file = e.target.result;
    var workbook = XLSX.read(file, { type: "binary" });

    // Get the first worksheet as JSON
    var sheetName = workbook.SheetNames[0];
    $scope.sheet = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]);

    // Log it and update scope
    console.log(sheet);
    $scope.sheet = sheet;
    $scope.$apply(); // Need this to update angular with the changes
  };
});

Then in your html:

<input type="file" import-sheet-js="" on-sheet-load="loadWorksheet(e)" multiple="false" />  

Here's a working example on codepen