Cómo transformar las respuestas de API en informes de Excel en C#
En el mundo actual impulsado por los datos, las empresas dependen en gran medida de las API REST para el intercambio de datos. Sin embargo, muchos interesados prefieren consumir estos datos en formato Excel para análisis e informes. Esta guía demuestra cómo construir una aplicación completa en C# que:
- Se conecta a API REST
- Recupera datos de respuesta en JSON
- Convierte los datos en informes de Excel con formato profesional
- Agrega visualización con gráficos y tablas
Valor Empresarial
Esta solución ofrece un valor significativo al:
- Automatizar los procesos de extracción de datos manuales y creación de informes
- Asegurar la precisión de los datos al eliminar la copia manual
- Proporcionar un formato de informe consistente
- Permitir la generación programada de informes
Guía de Implementación Paso a Paso
Paso 1: Crear una Nueva Aplicación en C#
Comienza creando una nueva aplicación de consola:
dotnet new console -n ApiToExcelReporter
cd ApiToExcelReporter
Paso 2: Instalar Paquetes Requeridos
Agrega los paquetes de NuGet necesarios:
dotnet add package Aspose.Cells
dotnet add package Newtonsoft.Json
dotnet add package RestSharp
Paso 3: Implementar el Cliente de la API REST
Crea un servicio para la comunicación con la API:
using RestSharp;
using Newtonsoft.Json;
using System;
using System.Threading.Tasks;
public class ApiService
{
private readonly RestClient _client;
public ApiService(string baseUrl)
{
_client = new RestClient(baseUrl);
}
public async Task<T> GetApiDataAsync<T>(string endpoint, string apiKey = null)
{
var request = new RestRequest(endpoint, Method.Get);
// Agregar autenticación si es necesario
if (!string.IsNullOrEmpty(apiKey))
{
request.AddHeader("Authorization", $"Bearer {apiKey}");
}
var response = await _client.ExecuteAsync(request);
if (response.IsSuccessful)
{
return JsonConvert.DeserializeObject<T>(response.Content);
}
throw new Exception($"La llamada a la API falló: {response.ErrorMessage}");
}
}
Paso 4: Procesar Datos de Respuesta JSON
Agrega una clase para procesar los datos JSON:
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
public class DataProcessor
{
public List<Dictionary<string, object>> FlattenJsonData(string jsonData)
{
var results = new List<Dictionary<string, object>>();
JToken token = JToken.Parse(jsonData);
// Manejar diferentes estructuras JSON
if (token is JArray array)
{
foreach (var item in array)
{
results.Add(FlattenObject(item));
}
}
else if (token is JObject obj)
{
// Para datos anidados como {"data": [{...}, {...}]}
var dataToken = obj["data"] as JArray;
if (dataToken != null)
{
foreach (var item in dataToken)
{
results.Add(FlattenObject(item));
}
}
else
{
results.Add(FlattenObject(obj));
}
}
return results;
}
private Dictionary<string, object> FlattenObject(JToken token)
{
var result = new Dictionary<string, object>();
FillDictionary(result, token, "");
return result;
}
private void FillDictionary(Dictionary<string, object> dict, JToken token, string prefix)
{
switch (token.Type)
{
case JTokenType.Object:
foreach (var prop in token.Children<JProperty>())
{
FillDictionary(dict, prop.Value,
string.IsNullOrEmpty(prefix) ? prop.Name : $"{prefix}.{prop.Name}");
}
break;
case JTokenType.Array:
int index = 0;
foreach (var item in token.Children())
{
FillDictionary(dict, item, $"{prefix}[{index}]");
index++;
}
break;
default:
dict[prefix] = ((JValue)token).Value;
break;
}
}
}
Paso 5: Convertir a Excel con Aspose.Cells
Implementa la conversión a Excel:
using Aspose.Cells;
using Aspose.Cells.Utility;
using System;
using System.Collections.Generic;
using System.IO;
public class ExcelReportGenerator
{
public void GenerateReport(string jsonData, string outputPath)
{
// Crear un nuevo libro de trabajo
Workbook workbook = new Workbook();
Worksheet sheet = workbook.Worksheets[0];
// Configurar opciones de diseño JSON
JsonLayoutOptions options = new JsonLayoutOptions
{
ArrayAsTable = true,
ConvertNumericOrDate = true,
IgnoreNull = true
};
// Hacer que los encabezados sean negritas
options.TitleStyle = new CellsFactory().CreateStyle();
options.TitleStyle.Font.IsBold = true;
// Importar datos JSON
JsonUtility.ImportData(jsonData, sheet.Cells, 0, 0, options);
// Ajustar automáticamente las columnas
sheet.AutoFitColumns();
// Guardar el libro de trabajo
workbook.Save(outputPath);
}
public void GenerateReportFromObjects(List<Dictionary<string, object>> data, string outputPath)
{
Workbook workbook = new Workbook();
Worksheet sheet = workbook.Worksheets[0];
// Agregar encabezados si hay datos
if (data.Count > 0)
{
int col = 0;
foreach (var key in data[0].Keys)
{
// Agregar encabezado con estilo
Cell cell = sheet.Cells[0, col];
cell.PutValue(key);
Style style = cell.GetStyle();
style.Font.IsBold = true;
cell.SetStyle(style);
col++;
}
// Agregar filas de datos
for (int row = 0; row < data.Count; row++)
{
col = 0;
foreach (var value in data[row].Values)
{
sheet.Cells[row + 1, col].PutValue(value);
col++;
}
}
}
// Formatear como una tabla
if (data.Count > 0)
{
int lastRow = data.Count;
int lastCol = data[0].Count - 1;
var tableRange = sheet.Cells.CreateRange(0, 0, lastRow + 1, lastCol + 1);
sheet.ListObjects.Add(tableRange, "DataTable");
}
// Ajustar automáticamente las columnas
sheet.AutoFitColumns();
// Guardar el libro de trabajo
workbook.Save(outputPath);
}
}
Paso 6: Agregar Formato Profesional
Mejora la salida de Excel con un estilo profesional:
public void ApplyProfessionalFormatting(Workbook workbook)
{
Worksheet sheet = workbook.Worksheets[0];
// Crear un estilo para el título
Style titleStyle = workbook.CreateStyle();
titleStyle.Font.Size = 14;
titleStyle.Font.IsBold = true;
titleStyle.HorizontalAlignment = TextAlignmentType.Center;
// Agregar un título al informe
sheet.Cells.Merge(0, 0, 1, sheet.Cells.MaxColumn + 1);
Cell titleCell = sheet.Cells[0, 0];
titleCell.PutValue("Informe de Datos de API - " + DateTime.Now.ToString("yyyy-MM-dd"));
titleCell.SetStyle(titleStyle);
// Insertar una fila en blanco después del título
sheet.Cells.InsertRow(1);
// Aplicar colores alternos a las filas de datos
Style evenRowStyle = workbook.CreateStyle();
evenRowStyle.ForegroundColor = Color.FromArgb(240, 240, 240);
evenRowStyle.Pattern = BackgroundType.Solid;
int dataStartRow = 3; // Contando el título y la fila en blanco
int lastRow = sheet.Cells.MaxRow;
for (int row = dataStartRow; row <= lastRow; row += 2)
{
for (int col = 0; col <= sheet.Cells.MaxColumn; col++)
{
sheet.Cells[row, col].SetStyle(evenRowStyle);
}
}
// Agregar encabezado y pie de página
sheet.PageSetup.SetHeader(1, "&\"Arial,Bold\"&14Informe de API");
sheet.PageSetup.SetFooter(1, "Página &P de &N");
// Configurar opciones de impresión
sheet.PageSetup.Orientation = PageOrientationType.Landscape;
sheet.PageSetup.FitToPagesWide = 1;
sheet.PageSetup.TopMargin = 0.5;
sheet.PageSetup.LeftMargin = 0.5;
sheet.PageSetup.RightMargin = 0.5;
sheet.PageSetup.BottomMargin = 0.5;
}
Paso 7: Agregar Visualización de Datos
Mejora el informe con gráficos:
public void AddChartVisualization(Workbook workbook, int dataColumn)
{
Worksheet sheet = workbook.Worksheets[0];
Worksheet chartSheet = workbook.Worksheets.Add("Análisis de Gráficos");
// Obtener el rango de datos (saltar la fila de encabezado)
int lastRow = sheet.Cells.MaxRow;
int nameColumn = 0; // Suponiendo que la primera columna tiene nombres/categorías
// Agregar un gráfico
int chartIndex = chartSheet.Charts.Add(ChartType.Column, 2, 2, 20, 10);
Chart chart = chartSheet.Charts[chartIndex];
// Establecer el rango de datos para el gráfico
chart.NSeries.Add($"Sheet1!B2:B{lastRow + 1}", true);
chart.NSeries.CategoryData = $"Sheet1!A2:A{lastRow + 1}";
// Establecer el título del gráfico y otras propiedades
chart.Title.Text = "Análisis de Datos";
chart.Legend.Position = LegendPositionType.Bottom;
// Personalización adicional del gráfico
chart.NSeries[0].Area.ForegroundColor = Color.FromArgb(79, 129, 189);
chart.PlotArea.Area.ForegroundColor = Color.White;
// Agregar etiquetas de datos
chart.NSeries[0].DataLabels.IsValueShown = true;
chart.NSeries[0].DataLabels.Position = DataLabelPositionType.OutsideEnd;
}
Paso 8: Integrar Todo
Crea el programa principal que une todo:
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
try
{
// Configurar el endpoint de la API
string baseUrl = "https://api.example.com";
string endpoint = "/data/endpoint";
string apiKey = "tu-clave-api"; // Si es necesario
// Conectar a la API y obtener datos
Console.WriteLine("Conectando a la API...");
var apiService = new ApiService(baseUrl);
var jsonData = await apiService.GetApiDataAsync<string>(endpoint, apiKey);
Console.WriteLine("Datos recuperados con éxito");
// Generar informe en Excel
Console.WriteLine("Generando informe en Excel...");
var reportGenerator = new ExcelReportGenerator();
// Opción 1: Conversión directa de JSON a Excel
string outputPath = "InformeApi_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".xlsx";
reportGenerator.GenerateReport(jsonData, outputPath);
// Opción 2: Procesar JSON y crear informe mejorado
// var processor = new DataProcessor();
// var processedData = processor.FlattenJsonData(jsonData);
// reportGenerator.GenerateReportFromObjects(processedData, outputPath);
Console.WriteLine($"Informe guardado en {outputPath}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
Manejo de Diferentes Estructuras de Respuesta de API
Las API REST devuelven datos en varios formatos. Aquí se explica cómo manejar estructuras comunes:
1. Array de Objetos
[
{ "id": 1, "name": "Producto A", "price": 29.99 },
{ "id": 2, "name": "Producto B", "price": 49.99 }
]
Para esta estructura, utiliza:
JsonLayoutOptions options = new JsonLayoutOptions();
options.ArrayAsTable = true;
JsonUtility.ImportData(jsonData, sheet.Cells, 0, 0, options);
2. Objeto Anidado con Array de Datos
{
"status": "success",
"data": [
{ "id": 1, "name": "Producto A", "price": 29.99 },
{ "id": 2, "name": "Producto B", "price": 49.99 }
]
}
Usa la clase DataProcessor para extraer el array “data”, o:
// Analizar con Newtonsoft.Json
JObject jsonObj = JObject.Parse(jsonData);
JArray dataArray = (JArray)jsonObj["data"];
// Convertir a cadena e importar
string dataArrayJson = dataArray.ToString();
JsonUtility.ImportData(dataArrayJson, sheet.Cells, 0, 0, options);
3. Arrays y Objetos Anidados
{
"categories": [
{
"name": "Electrónica",
"products": [
{ "id": 1, "name": "Portátil", "price": 999.99 },
{ "id": 2, "name": "Teléfono", "price": 699.99 }
]
},
{
"name": "Libros",
"products": [
{ "id": 3, "name": "Novela", "price": 14.99 }
]
}
]
}
Para estructuras complejas, crea múltiples hojas de trabajo:
// Analizar el JSON
JObject root = JObject.Parse(jsonData);
JArray categories = (JArray)root["categories"];
// Crear una hoja de trabajo para cada categoría
foreach (var category in categories)
{
string categoryName = category["name"].ToString();
Worksheet sheet = workbook.Worksheets.Add(categoryName);
// Obtener e importar el array de productos
JArray products = (JArray)category["products"];
JsonUtility.ImportData(products.ToString(), sheet.Cells, 0, 0, options);
}
Llevándolo al Siguiente Nivel: Informes Programados
Para automatizar la generación de informes, agrega capacidades de programación:
// Instalar paquete de Programador de Tareas
// dotnet add package TaskScheduler
using Microsoft.Win32.TaskScheduler;
public void ScheduleDailyReportGeneration(string appPath)
{
using (TaskService ts = new TaskService())
{
// Crear una nueva tarea
TaskDefinition td = ts.NewTask();
td.RegistrationInfo.Description = "Generación Diaria de Informe de Datos de API";
// Crear un disparador que se activará diariamente a las 7 a.m.
td.Triggers.Add(new DailyTrigger { StartBoundary = DateTime.Today.AddHours(7) });
// Crear una acción que ejecutará la aplicación
td.Actions.Add(new ExecAction(appPath));
// Registrar la tarea en la carpeta raíz
ts.RootFolder.RegisterTaskDefinition("InformeDiarioApi", td);
}
}
Características Avanzadas a Considerar
- Entrega por correo electrónico - Enviar automáticamente informes por correo electrónico
- Integración de múltiples API - Combinar datos de múltiples API
- Informes basados en plantillas - Usar plantillas de Excel para una marca consistente
- Creación de paneles - Generar paneles interactivos en Excel
- Seguimiento y reporte de errores - Registrar problemas e informar sobre éxito/fallo
Siguiendo esta guía, has creado una robusta aplicación en C# que automatiza el proceso de recuperación de datos de API y los convierte en informes de Excel profesionales, ahorrando tiempo, asegurando precisión y entregando valor empresarial.