En este tutorial les mostrare 3 formas para generar un Excel con la ayuda de la librería SheetJS. También haré uso de la Pokemon API para trabajar con datos reales.
Paso 1: Crear proyecto angular e instalar dependencia
Abrimos una consola CMD y ejecutamos el siguiente comando:
ng new simple-excel-report
Nos ubicamos en la carpeta del proyecto con el comando cd e instalamos la librería SheetJS ejecutando el siguiente comando:
npm i xlsx
Paso 2: Integrando Pokemon API
Para este caso solo haré uso del siguiente endpoint:
https://pokeapi.co/api/v2/pokemon/?limit=5&offset=0
Módulo para servicios compartidos
Crearemos nuestro SharedModule y en el servicio para consultar el API. Ejecutamos los siguientes comandos en la consola:
ng g module shared
ng g service shared/services/pokemon
Importar módulo HTTP
Ahora, en el archivo shared.module.ts importamos el HttpClientModule para poder realizar peticiones http:
/* shared.module.ts */
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http'
@NgModule({
declarations: [],
imports: [
CommonModule,
HttpClientModule
]
})
export class SharedModule { }
Interfaces
Dentro de la carpeta shared, crearemos una subcarpeta llamada interfaces y dentro de ella, el archivo pokemon-response.interface.ts, el cual tendrá el siguiente contenido:
/* pokemon-response.interface.ts */
export interface IPokemonResponse {
count: number;
next: string;
previous: string;
results: IPokemonInfo[]
}
export interface IPokemonInfo {
name: string;
url: string;
}
Crear consulta http
Abrimos el archivo pokemon.service.ts y en el constructor inyectamos el HttpClient de la siguiente manera:
constructor(private network: HttpClient) { }
Luego, creamos nuestro método getPokemonList para hacer la petición GET que traerá la lista de pokemones:
readonly API_BASE = 'https://pokeapi.co/api/v2';
getPokemonList(offset: number, limit: number): Observable<IPokemonResponse> {
const endpoint = `${this.API_BASE}/pokemon/?offset=${offset}&limit=${limit}`;
return this.network.get<IPokemonResponse>(endpoint);
}
Como podrán notar, agregamos 2 parámetros (offset y limit) en el método:
- offset: ID del pokemon inicial de la lista de respuesta
- limit: cantidad de pokemones subsiguientes al offset.
Paso 3: Servicio para generar reporte
Desde la consola, ejecutamos el siguiente comando para generar el servicio:
ng g service shared/services/excel-report
Forma #1: Configuración por default
Abrimos el archivo excel-report.service.ts y definimos el método generateDefaultReport:
generateDefaultReport(data: IPokemonInfo[], filename: string) {
let workbook = XLSX.utils.book_new();
let worksheet = XLSX.utils.json_to_sheet(data);
// first way to add a sheet
workbook.SheetNames.push('Hoja 1');
workbook.Sheets['Hoja 1'] = worksheet;
// second way to add a sheet
// XLSX.utils.book_append_sheet(workbook, worksheet, "Hoja 1")
XLSX.writeFileXLSX(workbook, filename, {});
}
Este método recibe 2 parámetros:
- data: Arreglo de objectos de tipo IPokemonInfo.
- filename: Nombre del archivo (Ej: mi_reporte.xlsx).
El problema con esta forma es que los headers (fila A1 del Excel) son asignados automáticamente y estos serán igual al nombre de los atributos del objeto. En otras palabras, nuestros headers serán name y url (atributos de IPokemonInfo).
Forma #2: Usando diccionario
Primero crearemos una interface con el nombre custom-header.interface.ts y con la siguiente estructura:
export interface ICustomHeader {
name: string;
key: string;
}
Esta interface nos ayudará a construir un diccionario relación, donde name es el nombre de la columna y key es el nombre del atributo de la interface IPokemonInfo. Ej:
- name: "Info URL"
- key: url Teniendo esta relación definida, podemos generar un excel con headers personalizados.
A continuación, abrimos el archivo excel-report.service.ts y definimos el método generateReportWithDict:
generateReportWithDict(customHeaders: ICustomHeader[], data: IPokemonInfo[], filename: string) {
let worksheetData: any[] = [];
Object(data).forEach( (item: any) => {
let worksheetItem = Object();
customHeaders.forEach( header => {
worksheetItem[header.name] = item[header.key];
})
worksheetData.push(worksheetItem)
})
// excel file
let workbook = XLSX.utils.book_new();
let worksheet = XLSX.utils.json_to_sheet(worksheetData);
XLSX.utils.book_append_sheet(workbook, worksheet, "Hoja 1")
XLSX.writeFileXLSX(workbook, filename, {});
}
Este método recibe 3 parámetros:
- customHeaders: Arreglo de objectos ICustomHeader.
- data: Arreglo de objectos de tipo IPokemonInfo.
- filename: Nombre del archivo (Ej: mi_reporte.xlsx).
Una de las ventajas de trabajar de esta forma es que nosotros podemos definir el orden de las columnas gracias a la relación name-key.
Forma #3: Usando un adapter
Creamos una carpeta adapter y dentro de ella, añadimos el archivo pokemon-report.class.ts con el siguiente contenido:
import { IPokemonInfo } from "../interfaces/pokemon-response.interface";
export interface IPokemonReport {
pokemonId: number;
pokemonName: string;
pokemonUrlInfo: string;
}
export class PokemonReportAdapter {
data: IPokemonReport[] = [];
constructor(pokemonList: IPokemonInfo[]) {
pokemonList.forEach( (pokemon, index) => {
const reportItem: IPokemonReport = {
pokemonId: index + 1,
pokemonName: pokemon.name,
pokemonUrlInfo: pokemon.url
}
this.data.push(reportItem);
})
}
}
Una ventaja de usar un adapter, es que podemos realizar operaciones y/o procesar los datos de nuestro objeto para posteriormente asignarlos en un nuevo modelo. En este caso, definimos una interface IPokemonReport que usaremos para generar un nuevo arreglo de datos a partir de nuestra data (IPokemonInfo).
Finalmente, abrimos el archivo excel-report.service.ts y definimos el método generateReportWithAdapter:
generateReportWithAdapter(headers: string[], data: IPokemonReport[], filename: string) {
let workbook = XLSX.utils.book_new();
let worksheet = XLSX.utils.json_to_sheet([], { header: headers });
XLSX.utils.sheet_add_json(worksheet, data, { origin: 'A2', skipHeader: true })
XLSX.utils.book_append_sheet(workbook, worksheet, "Hoja 1")
XLSX.writeFileXLSX(workbook, filename);
}
Este método recibe 3 parámetros:
- headers: Arreglo de string, donde cada item representa el header de cada columna.
- data: Arreglo de objectos de tipo IPokemonInfo
- filename: Nombre del archivo (Ej: mi_reporte.xlsx)
Una consideración importante respecto a esta forma es el orden en que se definen el nombre de los header ya que tienen que tener el mismo orden en que se definen los atributos de la nueva interface (IPokemonReport).
Espero les haya sido de utilidad este tutorial 👍.
Link del repositorio: simple-excel-report
Top comments (0)