MatTableDataSource not showing data from file readed with exceljs lib

198 Views Asked by At

I'm trying to show data into a Mat Table from a xlsx file readed with exceljs library. I think i'm filling the MatTableDataSource correctly, but nothing is showing on the screen.

This is the TS code:

import { Component, OnInit, ViewChild } from '@angular/core'
import { MatPaginator } from '@angular/material/paginator'
import { MatTableDataSource } from '@angular/material/table'
import * as Excel from 'exceljs/dist/exceljs.min.js'


export interface Colaborador{
  Rut: string
  Rol: string
  Nombres: string
  Apellidos: string
  Departamento: string
  Empresa: string
  Cargo: string
  Existe: boolean
}

@Component({
  selector: 'app-trabajador-create-masive',
  templateUrl: './trabajador-create-masive.component.html',
  styleUrls: ['./trabajador-create-masive.component.css']
})
export class TrabajadorCreateMasiveComponent implements OnInit {
  
  listadoTrabajadores:MatTableDataSource<Colaborador>
  displayedColumns:string[] = ["Rut","Rol","Nombre","Departamento","Empresa","Cargo"]

  constructor() { }

  @ViewChild(MatPaginator, {static: true}) paginator: MatPaginator

  ngOnInit(): void { }

  procesarArchivo(event){
    const file=event.target.files[0]
    let fileData:Colaborador[]=[]

    fileData=this.leerArchivo(file)
    console.log(fileData)

    this.listadoTrabajadores = new MatTableDataSource(fileData)
    this.listadoTrabajadores.paginator=this.paginator
  }

  leerArchivo(Archivo):Colaborador[]{
    let fileData:Colaborador[]=[]
    const workbook = new Excel.Workbook()
    const arryBuffer = new Response(Archivo).arrayBuffer()

    arryBuffer.then(function (data) {
       workbook.xlsx.load(data).then(function () {
        const worksheet = workbook.getWorksheet(1)
        worksheet.eachRow(function (row, rowNumber) {
          if(rowNumber>1){
            fileData.push({
              Rut: row.getCell(1).toString(),
              Rol: row.getCell(2).toString(),
              Nombres: row.getCell(3).toString(),
              Apellidos: row.getCell(4).toString(),
              Departamento: row.getCell(5).toString(),
              Empresa: row.getCell(6).toString(),
              Cargo: row.getCell(7).toString(),
              Existe: false
            })
          }
        })
      })
    })
    
    return fileData
  }

}

The template code:

<table mat-table [dataSource]="listadoTrabajadores" style="width:90%;margin:0 auto;">
    <ng-container matColumnDef="Rut">
        <th mat-header-cell *matHeaderCellDef style="justify-content:center">Rut</th>
        <td mat-cell *matCellDef="let data"> {{ data.Rut | rut }} </td>
    </ng-container>

    <ng-container matColumnDef="Rol">
        <th mat-header-cell *matHeaderCellDef style="justify-content:center">Rol</th>
        <td mat-cell *matCellDef="let data"> {{ data.Rol }} </td>
    </ng-container>

    <ng-container matColumnDef="Nombre">
        <th mat-header-cell *matHeaderCellDef style="justify-content:center">Nombre</th>
        <td mat-cell *matCellDef="let data"> {{ data.Nombres }} {{ data.Apellidos }} </td>
    </ng-container>

    <ng-container matColumnDef="Departamento">
        <th mat-header-cell *matHeaderCellDef style="justify-content:center">Departamento</th>
        <td mat-cell *matCellDef="let data"> {{ data.Departamento }} </td>
    </ng-container>

    <ng-container matColumnDef="Empresa">
        <th mat-header-cell *matHeaderCellDef style="justify-content:center">Empresa</th>
        <td mat-cell *matCellDef="let data"> {{ data.Empresa }} </td>
    </ng-container>

    <ng-container matColumnDef="Cargo">
        <th mat-header-cell *matHeaderCellDef style="justify-content:center">Cargo</th>
        <td mat-cell *matCellDef="let data"> {{ data.Cargo }} </td>
    </ng-container>
    
    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let data; columns: displayedColumns;"></tr>
</table>
<mat-paginator [pageSizeOptions]="[20,50,100]" showFirstLastButtons></mat-paginator>

And this is what i'm seeing on the screen: enter image description here

I don't know what i'm doing wrong.

edit: here is an image of debugging procesarArchivo() with the subscribe method, retrieven no data from leerArchivo(), but console.log is showing data

debuggin procesarArchivo()

1

There are 1 best solutions below

3
Andrew Halil On

With the current code, the data source is being assigned an empty fileData array since function leerArchivo() returns after the data source is assigned.

Provided you have data loading from your Excel file into the arryBuffer and worksheet variables and your fileData array has populated data, then applying the following recommended minor change with one of the two equivalent methods as follows will remediate the issue:

Subscribe Method

a. Change the return type of your function leerArchivo() and return fileData as an observable as shown:

leerArchivo(Archivo): Observable<Colaborador[]> {
  let fileData: Colaborador[] = [];
  ..
  ..
  return of(fileData);
}

b. Apply the following changes to your procesarArchivo() method to subscribe to the leerArchivo() function:

procesarArchivo(event) {
  const file = event.target.files[0];
  let fileData: Colaborador[] = [];

  this.leerArchivo(file).subscribe((res) => {
    fileData = res;
    this.listadoTrabajadores = new MatTableDataSource(fileData);
    this.listadoTrabajadores.paginator = this.paginator;
    console.log(fileData);
  });
}

Async/Await

a. Make your function leerArchivo() asynchonous, change it's return type to a Promise and return fileData as a promise as shown:

async leerArchivo(Archivo): Promise<Colaborador[]> {
  let fileData: Colaborador[] = [];
  ...
  ...     
  return await Promise.resolve(fileData);
}

b. Apply the following changes to your procesarArchivo() method to invoke the leerArchivo() asynchronous function:

procesarArchivo(event) {
  const file = event.target.files[0];
  let fileData: Colaborador[] = [];
  this.leerArchivo(file).then((res) => {
    fileData = res;
    this.listadoTrabajadores = new MatTableDataSource(fileData);
    this.listadoTrabajadores.paginator = this.paginator;
    console.log(fileData);
  });
}

With the above changes your data source listadoTrabajadores for the Material table that is referenced within your component template will be correctly assigned with fileData after it has been retrieved from the Excel file.