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
.
ngx-export-as
?ngx-export-as
es una librería para Angular que permite exportar cualquier elemento HTML del DOM en múltiples formatos:
.xls
, .xlsx
).png
, .jpg
).txt
).doc
, .docx
)Esta librería exporta el contenido visual del DOM, es decir, lo que se muestra en pantalla.
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.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
A continuación, vamos a mostrar cómo exportar una tabla de Angular Material con ambas librerías.
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;
}
}
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`);
}
}
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.
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.
ngx-export-as
ngx-export-as
xlsx + file-saver
xlsx + file-saver
Puedes encontrar el código completo de este ejemplo en el siguiente repositorio de GitHub:
🔗 Repositorio en GitHub: exportMatTable
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.