Search code examples
javascriptangularjscsvxlsinput-type-file

Generate array from CSV file selected by input type file


I want to read the CSV file that I upload using input type file and feed its data into an array.

I'm using Angularjs with input type file to read a CSV, xls or xlsx file as follows:

HTML:

<input class="btn btn-default col-xs-6" type="file" accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" onchange="angular.element(this).scope().checkFormat(this.files)">

JavaScript/AngularJS:

$scope.checkFormat = function(files) {
        var fd = new FormData();
        //Take the first selected file
        fd.append("file", files[0]);
}

How can I read this CSV file row by row and push each row into an array?


Solution

  • The best way it to make a directive with such functionality (say we call it csvUpload and use it like this <csv-upload ng-model="myData">) - this way it will be reusable and you won't have to implement this logic in, possibly, many controllers. It's quite convenient too: once you have it you just choose a file and, bam, have your data on $scope.myData :)

    This is how I did it:

    (To transform csv to json I'm using quite well estabilished https://github.com/mholt/PapaParse library but you could parse the csv string to json by yourself. I would not recommend it though ;)

    .directive('csvUpload', function () {
      return {
        restrict: 'E',
        template: '<input type="file" onchange="angular.element(this).scope().handleFiles(this.files)">',
        require: 'ngModel',
        scope: {},
        link: function (scope, element, attrs, ngModel) {
          scope.handleFiles = function (files) {
            Papa.parse(files[0], {
              dynamicTyping: true,
              complete: function(results) {
                // you can transform the uploaded data here if necessary
                // ...
                ngModel.$setViewValue(results);
              }
            });
          };
    
        }
      };
    });