Exportar Tablas en Angular Material: Comparativa Entre ngx-export-as y xlsx + file-save para Excel, PDF y más

Exportar Tablas en Angular Material: Comparativa Entre ngx-export-as y xlsx + file-save para Excel, PDF y más

Exportar Tablas en Angular Material: Comparativa Entre ngx-export-as y xlsx + file-save para Excel, PDF y más

Cuando trabajamos con Angular y Angular Material, uno de los componentes más comunes es la tabla (<mat-table>), ideal para mostrar grandes volúmenes de datos con paginación, ordenamiento y filtros. Sin embargo, surge la necesidad de permitir a los usuarios exportar esa tabla a formatos como PDF, Excel o imagen.

En este artículo, compararemos dos soluciones actuales y mantenidas para exportar tablas en Angular Material: ngx-export-as y una combinación flexible usando xlsx + file-saver, en reemplazo del ahora deprecado mat-table-exporter.


📚 Tabla de Contenidos


❓ ¿Qué es ngx-export-as?

ngx-export-as es una librería para Angular que permite exportar cualquier elemento HTML del DOM en múltiples formatos:

  • PDF
  • Excel (.xls, .xlsx)
  • CSV
  • JSON
  • Imagen (.png, .jpg)
  • Texto (.txt)
  • Word (.doc, .docx)

Esta librería exporta el contenido visual del DOM, es decir, lo que se muestra en pantalla.

❓ ¿Qué es xlsx + file-save?

Esta combinación se ha vuelto estándar para exportar datos tabulares como Excel en Angular. En lugar de exportar el DOM, exporta los datos directamente desde la lógica del componente o servicio, lo cual es más eficiente y preciso.

  • xlsx: convierte los datos a hojas de cálculo.
  • file-saver: descarga el archivo generado en el navegador.

🧰 Instalación

Para ambas librerías, se pueden instalar fácilmente usando npm.

Para ngx-export-as:

npm install ngx-export-as

Para xlsx y file-saver:

npm install xlsx file-saver

Importamos sus respectivos módulos en el archivo app.module.ts de Angular:

import { ExportAsModule } from 'ngx-export-as';

@NgModule({
  imports: [
    ...,
    ExportAsModule,
  ]
})
export class AppModule {}

Para Versiones superiores a Angular > 17 importamos en los imports del app.component.ts

@Component({
  selector: 'app-root',
  imports: [
    ExportAsModule,
    MatPaginatorModule,
    MatTableModule,
    MatButtonModule,
  ],
  providers: [
    PersonaService,
    ExportServiceNgxService,
    ExcelService
  ],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})

Añadimos angular material

ng add @angular/material

🧪 Ejemplo práctico: exportar una mat-table

A continuación, vamos a mostrar cómo exportar una tabla de Angular Material con ambas librerías.

Interfaz y Mock Data

persona.model.ts define el modelo de datos de una persona, que es lo que vamos a mostrar en nuestra tabla.

export interface Persona {
  id: number;
  nombre: string;
  edad: number;
  email: string;
}

✅ ¿Por qué es importante? Usar interfaces en TypeScript nos permite tipar nuestros datos y beneficiarnos de autocompletado, verificación en tiempo de compilación y mayor claridad en el código.

creamos un archivo data.service.ts para poblar nuestra tabla sin depender de un backend real,basicamente es un servicio que genera una lista ficticia de personas.

import { Injectable } from '@angular/core';
import { Persona } from './persona.model';

@Injectable({ providedIn: 'root' })
export class DataService {
  generarPersonas(cantidad: number = 200): Persona[] {
    const personas: Persona[] = [];
    for (let i = 1; i <= cantidad; i++) {
      personas.push({
        id: i,
        nombre: `Persona ${i}`,
        edad: 18 + (i % 50),
        email: `persona${i}@ejemplo.com`,
      });
    }
    return personas;
  }
}

Servicio de exportación

export.ngx.ts este servicio utiliza la librería ngx-export-as para exportar cualquier elemento del DOM en formatos como PDF, PNG o Excel. Aísla la lógica de exportación en un servicio reutilizable. Así mantenemos limpio nuestro componente y facilitamos el mantenimiento del código.

import { Injectable } from '@angular/core';
import {ExportAsService} from 'ngx-export-as';

@Injectable({
  providedIn: 'root'
})
export class ExportNgxService {

  constructor(private exportAsService: ExportAsService) { }

  exportar(tipo: 'pdf' | 'xls' | 'png', elementId: string, nombreArchivo: string): void {
    const config = {
      type: tipo,
      elementIdOrContent: elementId,
      download: true
    };
    this.exportAsService.save(config, nombreArchivo).subscribe(() => {
      console.log(`Exportado como  ${tipo}`);
    })
  }
}

excel.service.ts este servicio utiliza las librerías xlsx y file-saver para exportar datos en formato Excel (.xlsx). Convierte arrays de objetos en hojas de cálculo y genera archivos descargables directamente desde el navegador. Al encapsular esta lógica, mantenemos el componente principal más limpio y reutilizamos fácilmente la funcionalidad de exportación en toda la app.

import { Injectable } from '@angular/core';
import * as XLSX from 'xlsx';
import * as FileSaver from 'file-saver';

@Injectable({
  providedIn: 'root'
})
export class ExcelService<T> {

  exportarExcel(data: T[], nombreArchivo: string):void{
    const worksheet = XLSX.utils.json_to_sheet(data);
    const workbook = { Sheets: {data: worksheet}, SheetNames: ['data']}
    const buffer = XLSX.write(workbook, {bookType: 'xlsx', type: 'array'});
    const blob = new Blob([buffer], {type: 'application/octet-stream'});
    FileSaver.saveAs(blob, `${nombreArchivo}.xlsx`);
  }
}

Componente principal

app.component.ts aquí es donde todo se conecta: se generan los datos, se aplica la paginación de Angular Material y se invocan los métodos de exportación.

import {AfterViewInit, Component, ViewChild} from '@angular/core';
import {ExportAsModule} from 'ngx-export-as';
import {MatTableDataSource, MatTableModule} from '@angular/material/table';
import {Persona} from './models/persona';
import {ExportNgxService} from './services/export-ngx.service';
import {ExcelService} from './services/excel.service';
import {PersonaService} from './services/persona.service';
import {MatPaginator, MatPaginatorModule} from '@angular/material/paginator';
import {MatButtonModule} from '@angular/material/button';

@Component({
  selector: 'app-root',
  imports: [
    ExportAsModule,
    MatPaginatorModule,
    MatTableModule,
    MatButtonModule,
  ],
  providers: [
    PersonaService,
    ExportNgxService,
    ExcelService
  ],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent implements AfterViewInit {
  title = 'export-example-angular';

  columnas: string[] = ['id', 'nombre', 'edad', 'email'];
  dataSource = new MatTableDataSource<Persona>()

  @ViewChild(MatPaginator) paginator !: MatPaginator

  constructor(
    private personaService: PersonaService,
    private exportServiceNgx: ExportNgxService,
    private excelService: ExcelService<Persona>) {
    this.dataSource.data = this.personaService.generarPersonas();
  }

  ngAfterViewInit(): void {
    this.dataSource.paginator = this.paginator;
  }

  exportarNgx(tipo: 'pdf' | 'xls' | 'png'): void {
    this.exportServiceNgx.exportar(tipo, 'tablaExportar', 'tabla-personas');
  }

  exportarExcelXlsx(): void {
    this.excelService.exportarExcel(this.dataSource.filteredData, 'personas')
  }

}

finalmente, app.component.html contiene tanto la tabla como los botones para exportar. Notá que uno usa ngx-export-as y el otro usa xlsx + file-save.

<div>
  <button mat-raised-button color="primary" (click)="exportarNgx('pdf')">
    Exportar PDF (ngx-export-as)
  </button>

  <button mat-raised-button color="accent" (click)="exportarExcelXlsx()">
    Exportar Excel (xlsx)
  </button>
</div>

<div>
  <table mat-table [dataSource]="dataSource" class="mat-elevation-z8" id="tablaExportar">
      <ng-container matColumnDef="id">
        <th mat-header-cell *matHeaderCellDef>ID</th>
        <td mat-cell *matCellDef="let persona">{{persona.id}}</td>
      </ng-container>

    <ng-container matColumnDef="nombre">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Nombre </th>
      <td mat-cell *matCellDef="let persona"> {{ persona.nombre }} </td>
    </ng-container>

    <ng-container matColumnDef="edad">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Edad </th>
      <td mat-cell *matCellDef="let persona"> {{ persona.edad }} </td>
    </ng-container>

    <ng-container matColumnDef="email">
      <th mat-header-cell *matHeaderCellDef> Email </th>
      <td mat-cell *matCellDef="let persona"> {{ persona.email }} </td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="columnas"></tr>
    <tr mat-row *matRowDef="let row; columns: columnas;"></tr>
  </table>

  <mat-paginator [pageSize]="10" showFirstLastButtons></mat-paginator>
</div>

🧠 ¿Qué se destaca aquí?

El elemento #tablaExportar es clave para que ngx-export-as sepa qué parte del DOM exportar.


💡 Tips y recomendaciones

  • Si trabajas con ngx-export-as, ten en cuenta que solo exporta lo visible en pantalla, por lo que los datos en tablas con paginación no se exportarán a menos que todos los datos estén visibles.

  • ngx-export-as exporta solo lo visible en pantalla (ideal para PDF o imagen).

  • xlsx + file-saver trabaja con los datos directamente, por lo que exporta todo, incluso con paginación.

  • Combinar ambas soluciones te da lo mejor de ambos mundos.


✅ Ventajas y Desventajas

Ventajas de ngx-export-as

  • Más formatos disponibles (PDF, imágenes, Excel, etc.).
  • Exportación visual del DOM (lo que ves es lo que obtienes).

Desventajas de ngx-export-as

  • No exporta tablas con paginación de manera sencilla (solo exporta lo visible).
  • Requiere que el contenido esté completamente visible en pantalla.

Ventajas de xlsx + file-saver

  • Ligero, rápido y escalable para grandes datasets.
  • Exporta todos los datos, no solo lo visible.

Desventajas de xlsx + file-saver

  • Solo exporta a Excel.
  • No exporta estilos visuales.

📦 Repositorio con el Ejemplo

Puedes encontrar el código completo de este ejemplo en el siguiente repositorio de GitHub:

🔗 Repositorio en GitHub: exportMatTable


🔚 Conclusión

Si solo necesitas exportar tablas en formatos como Excel o CSV y deseas soporte para tablas paginadas, xlsx + file-saver es la opción más robusta y mantenida hoy en día. Sin embargo, si necesitas una exportación más flexible y visual (con soporte para más formatos), ngx-export-as sigue siendo muy útil. Ambas soluciones pueden convivir en un mismo proyecto.