如何逐行读取angular2上的csv文件

时间:2017-10-14 12:34:35

标签: javascript jquery angular typescript csv

我正在用angular2编写一个应用程序,它在html中输入一个简单输入的csv文件:

<input type='file' name='userFile' id='file' >

我可以访问component.ts上的文件:

ngOnInit() {

   var input = (<HTMLInputElement>document.getElementById("file"));
   input.addEventListener("change", function(event) {
      var files = input.files;
      var len = files.length;

         if (len) {
          console.log("Filename: " + files[0].name);
          console.log("Type: " + files[0].type);
          console.log("Size: " + files[0].size + " bytes");

         }

      }, false);

}

如何逐个单元格读取使用typescript,javascript或jquery上传的csv文件? (这是最好的方法)。

5 个答案:

答案 0 :(得分:5)

以下是角度方式的示例实现:

@Component({
  selector: 'app-my-file',
  template: `
   <div class="form-group">
        <input type="file" (change)="onFileSelect($event.target)" name="myfile">
   </div>
  `,
  styles: [``]
})
export class YourComponent implements OnInit {

    csvContent: string;

    constructor(){}
    ngOnInit(){
    }

    onFileLoad(fileLoadedEvent) {
            const textFromFileLoaded = fileLoadedEvent.target.result;              
            this.csvContent = textFromFileLoaded;     
            // alert(this.csvContent);
    }

    onFileSelect(input: HTMLInputElement) {

      const files = input.files;
      var content = this.csvContent;    
      if (files && files.length) {
         /*
          console.log("Filename: " + files[0].name);
          console.log("Type: " + files[0].type);
          console.log("Size: " + files[0].size + " bytes");
          */

          const fileToRead = files[0];

          const fileReader = new FileReader();
          fileReader.onload = this.onFileLoad;

          fileReader.readAsText(fileToLoad, "UTF-8");
      }

    }
}

Try it on StackBlitz

答案 1 :(得分:3)

csv2Array(fileInput: any){
//read file from input
this.fileReaded = fileInput.target.files[0];

let reader: FileReader = new FileReader();
reader.readAsText(this.fileReaded);

reader.onload = (e) => {
  let csv: string = reader.result;
  let allTextLines = csv.split(/\r|\n|\r/);
  let headers = allTextLines[0].split(',');
  let lines = [];

  for (let i = 0; i < allTextLines.length; i++) {
    // split content based on comma
    let data = allTextLines[i].split(',');
    if (data.length === headers.length) {
      let tarr = [];
      for (let j = 0; j < headers.length; j++) {
        tarr.push(data[j]);
      }

      // log each row to see output 
      console.log(tarr);
      lines.push(tarr);
    }
  }
  // all rows in the csv file 
  console.log(">>>>>>>>>>>>>>>>>", lines);
} }

答案 2 :(得分:2)

除了asmmahmud's answer之外,我还想添加如何实际解析文件内容的方法,以便在数组(带有TypeScript的Angular)中具有行和列。添加属性:

parsedCsv: string[][];

在他的示例中为班级YourComponent。 然后,如下更新onFileLoad事件:

onFileLoad(fileLoadedEvent): void {
 const csvSeparator = ';';
 const textFromFileLoaded = fileLoadedEvent.target.result;
 this.csvContent = textFromFileLoaded;
 // alert(textFromFileLoaded);

 const txt = textFromFileLoaded;
 const csv = [];
 const lines = txt.split('\n');
 lines.forEach(element => {
   const cols: string[] = element.split(csvSeparator);
   csv.push(cols);
 });
 this.parsedCsv = csv;
 // console.log(this.parsedCsv);
}

现在,在二维数组parsedCsv中(第1维是行,第2维是列),您具有已解析的CSV及其行和列。您可以根据需要更换分隔符-默认为分号。

示例:

包含的文件

  

A; B; C   
1; 2,300; 3   
4; 5.5; 6

parsedCsv

中产生以下数据结构

ExampleContent

您可以看到,如果您的文件包含列标题,那么数据将从行索引1开始,否则(无列标题)则从行索引0开始。

Updated Stackblitz Example

注意::在Stackblitz上,我添加了以下几行,以便您了解数组的填充方式:

  // demo output as alert
  var output: string="";
  csv.forEach(row => {
    output += "\n";
    var colNo = 0;
    row.forEach(col => {
      if (colNo>0) output += " | ";
      output += col;
      colNo++;
    });
  });
  alert(output);

答案 3 :(得分:0)

我找到了提取文字的方法:

var rows = text.split("\n");
console.log("Row 0 " + rows[0]);
console.log("Row 1 " + rows[1]);
console.log("Row 2 " + rows[2]);
var row1 = rows[0].split(";");
console.log("Value 0,0 " + row1[0]);
console.log("Value 0,1 " + row1[1]);
console.log("Value 0,2 " + row1[2]);

然后使用将单独的行和单元格拆分为数组:

const sleep = n => () => new Promise(resolve => setTimeout(resolve, n));

*如果单元格包含“;”,则此代码无法正常工作字符,不是我申请的情况。

答案 4 :(得分:0)

我写了一个函数作为 Promise

  /**
   * Returns the CSV file content as a string.
   * New lines are separated by '\n' inside the string.
   * @param file 
   */
  public async readCSVFile(file: File): Promise<string | ArrayBuffer> {
    return new Promise<string | ArrayBuffer>((resolve, reject) => {
      const reader = new FileReader();

      reader.onload = e => {
        return resolve((e.target as FileReader).result);
      };
      reader.onerror = e => {
        console.error(`FileReader failed on file ${file.name}.`);
        return reject(null);
      };

      if (!file) {
        console.error('No file to read.');
        return reject(null);
      }
      reader.readAsText(file);
    });
  }

你可以这样使用

this.readCSVFile(myCsvFile).then((fileContents) => {
      //fileContents --> CSV file content as a string
 });

而且,如果你正在与像 ñ 这样的西班牙字符战斗,这对我有用

reader.readAsText(file, 'ISO-8859-3');