Crea un informe trimestral de ventas en Excel en C# (XLSX) con Xceed Workbooks para .NET

La fusión de archivos DOCX en C# parece sencilla hasta que surgen conflictos de estilo, encabezados y colisiones en la numeración. Este tutorial muestra cómo fusionar documentos de Word mediante programación con Xceed Words para .NET utilizando InsertDocument, saltos de sección y flujos de trabajo basados en plantillas.

Este tutorial muestra cómo crear un informe trimestral de ventas en formato XLSX utilizando C# y Xceed Workbooks para .NET. Cargarás datos de transacciones en una hoja de cálculo, aplicarás formatos numéricos y estilos condicionales, agregarás fórmulas SUM y AVERAGE, y guardarás el archivo con un encabezado congelado. Estos mismos patrones se pueden adaptar a paquetes financieros de varias hojas, resúmenes de tipo tabla dinámica y exportaciones programadas desde ASP.NET Core. Entre las alternativas en este ámbito se encuentran EPPlus y ClosedXML; en la sección de ventajas y desventajas se compara cuándo es más adecuado usar cada una. Al final, tendrás un ejemplo que funciona y una lista de verificación para los informes de producción.

Los equipos de finanzas piden lo mismo cada trimestre: un archivo de Excel limpio con totales, desgloses regionales y formato que sobreviva a un reenvío al director financiero. Cuando necesitas crear un archivo de salida de Excel con .NET que se envíe a usuarios reales, OpenXML puro se siente como escribir en ensamblador. El SDK de Open XML de Microsoft funciona, pero te obliga a modelar partes, relaciones y cadenas compartidas manualmente.

Xceed Workbooks para .NET se encarga de esa infraestructura y expone una API de celdas y estilos que puedes leer de un vistazo. Este tutorial crea un informe de ventas funcional a partir de una lista de transacciones, aplica formato numérico y resaltado en negrita condicional, escribe celdas con fórmulas y guarda el resultado. El mismo código se ejecuta en .NET Framework 4.6.1+, .NET 6, .NET 8 y .NET 9.

Antes de escribir código, instala el paquete de Xceed.Workbooks.NET en NuGet. La versión de prueba de 45 días funciona sin clave de licencia, por lo que puedes ejecutar la muestra completa a continuación tan pronto como el paquete se restaure.

¿Por qué Xceed Workbooks para .NET para informes de ventas?

Los informes de ventas tienen tres propiedades que perjudican a las bibliotecas poco flexibles: recuentos de filas variables, tipos de datos mixtos por columna y partes interesadas que reformatean el archivo después de la entrega. Por lo tanto, la biblioteca que elija tiene que escribir objetos de Excel reales, no CSV con extensión .xlsx.

Xceed Workbooks para .NET escribe el formato OOXML SpreadsheetML definido en ECMA-376, lo que significa que Excel, LibreOffice, Google Sheets y Power BI abren el archivo sin advertencias. Las celdas conservan sus tipos nativos, las fórmulas se recalculan al abrir y los estilos se mantienen correctamente. Las alternativas en este espacio incluyen EPPlus y ClosedXML; ambas son opciones sólidas, y la sección cerca del final de este artículo describe cuándo encaja cada una.

Qué contiene el informe final

La muestra produce una única hoja de cálculo llamada Ventas Q4. Contiene una fila de encabezado fija, seis columnas de datos (Fecha, Región, Representante de ventas, Producto, Unidades, Ingresos), una fila de totales con fórmulas SUM, una celda con el ingreso promedio y las filas en las que los ingresos superan un umbral resaltadas en negrita. Esto cubre aproximadamente el 80% de lo que los usuarios de negocios solicitan antes de pedir gráficos.

Configuración del proyecto y el modelo de datos

Crea un proyecto de consola que apunte a .NET 8 y agrega la referencia del paquete. Los comandos de la CLI son sencillos:

Comandos de terminal

dotnet new console -n SalesReport
cd SalesReport
dotnet add package Xceed.Workbooks.NET

A continuación, define el registro de la transacción. Los registros son concisos e inmutables, lo que coincide con la forma en que los pipelines de informes suelen pasar los datos:

Registro de transacción de venta

usando System;
using System.Collections.Generic;
usando Xceed.Workbooks.NET;

registro público SalesTransaction(
  Fecha,
  string Región,
  Representante de ventas,
  string Producto,
  int Unidades,
  decimal Ingresos);

Para la demostración, genere transacciones en memoria. En producción, esta lista provendrá de EF Core, Dapper o una llamada a servicio; el código del informe a continuación no se preocupa de dónde se originan las filas.

XLSX C#: cómo escribir el encabezado y los datos

La API de Workbooks refleja cómo una persona describe una hoja de cálculo: abre un libro, toma una hoja de trabajo, establece los valores de las celdas por referencia A1. Aquí está la primera mitad del generador de informes, que escribe el título, los encabezados de columna y las filas de datos:

BuildReport: título, encabezados, filas

public static void BuildReport(List data, string path)
{
  usando (var workbook = Workbook.Create(path))
  {
    var sheet = workbook.Worksheets[0];

    // Fila de título
    sheet.Cells["A1"].Value = "Informe de ventas T4";
    sheet.Cells["A1"].Style.Font.Bold = true;
    sheet.Cells["A1"].Style.Font.Size = 16;

    // Fila de encabezado en la fila 3
    string[] encabezados = { "Fecha", "Región", "Representante de Ventas", "Producto", "Unidades", "Ingresos" };
    for (int c = 0; c < headers.Length; c++)
    {
      var cell = sheet.Cells[2, c];
      celda.Valor = encabezados[c];
      cell.Estilo.Fuente.Negrita = verdadero;
    }

    // Filas de datos a partir de la fila 4 (índice 3)
    for (int r = 0; r < data.Count; r++)
    {
      var tx = data[r];
      int fila = 3 + r;
      sheet.Cells[row, 0].Value = tx.Date;
      hoja.Cells[fila, 1].Value = tx.Region;
      sheet.Cells[row, 2].Value = tx.Vendedor;
      hoja.Cells[fila, 3].Value = tx.Producto;
      sheet.Cells[row, 4].Value = tx.Unidades;
      sheet.Cells[row, 5].Value = tx.Ingresos;
    }

    workbook.Guardar();
  }
}

Por qué los tipos nativos son importantes

Los valores de fecha y hora y decimales pasan directamente. Excel los ve como tipos de fecha y número nativos porque la biblioteca escribe el token de tipo de celda correcto, no una representación de cadena. En consecuencia, la ordenación y el filtrado dentro de Excel funcionan como se esperaba.

Formato, totales y salida con estilo

Los números brutos sin formato fallan la prueba del CFO. El siguiente bloque agrega una fila de totales, formato de moneda en la columna de ingresos, un formato de fecha en la columna A y un resaltado en negrita en las filas de altos ingresos. Agregue esta sección antes de la llamada workbook.Save():

Formatos + negrita condicional + totales + promedio

// Aplicar formato de fecha a la columna A y moneda a la columna F
int primeraFilaDatos = 3;
int últimaFilaDatos = 2 + data.Count;

for (int row = firstDataRow; row <= lastDataRow; row++)
{
  sheet.Cells[row, 0].Style.CustomFormat = "yyyy-mm-dd";
  sheet.Cells[row, 5].Style.CustomFormat = "$#,##0.00";

  // Resaltar filas donde los ingresos > 5000
  si (data[fila - primeraFilaDeDatos].Ingresos > 5000m)
  {
    sheet.Cells[row, 5].Style.Font.Bold = true;
  }
}

// Fila de totales
int filaTotal = ultimaFilaDeDatos + 2;
sheet.Cells[totalsRow, 3].Value = "Totales";
sheet.Cells[totalsRow, 3].Style.Font.Bold = true;
hoja.Celdas[filaDeTotales, 4].Fórmula = $"=SUMA(E{primeraFilaDeDatos + 1}:E{últimaFilaDeDatos + 1})";
hoja.Celdas[filaDeTotales, 5].Fórmula = $"=SUMA(F{primeraFilaDeDatos + 1}:F{últimaFilaDeDatos + 1})";
hoja.Celdas[filaDeTotales, 5].Estilo.FormatoPersonalizado = "$#,##0.00";

// Ingreso promedio de la celda debajo de los totales
sheet.Cells[totalsRow + 1, 3].Value = "Ingresos Promedio";
hoja.Celdas[filaDeTotales + 1, 5].Fórmula = $"=PROMEDIO(F{primeraFilaDeDatos + 1}:F{últimaFilaDeDatos + 1})";
sheet.Cells[totalsRow + 1, 5].Style.CustomFormat = "$#,##0.00";

Las fórmulas se mantienen correctas después de las ediciones

La propiedad Formula escribe una fórmula real de Excel. Cuando el usuario abre el archivo, Excel calcula los totales. Por lo tanto, el archivo se mantiene correcto incluso si un revisor edita manualmente una celda de ingresos; la SUMA se actualiza en tiempo real.

Ejecutando la muestra

Conecta un pequeño `Main` que genere datos de demostración y llame a la función. Ejecuta con `dotnet run` y abre `SalesReport.xlsx`:

Programa.Principal

public static void Main()
{
  var data = new List<SalesTransaction>
  {
    new(new DateTime(2024, 10, 3), "Este", "Alice", "Pro Plan", 12, 7200m),
    new(new DateTime(2024, 10, 5), "Oeste", "Ben", "Starter", 5, 1250m),
    nuevo(nueva Fecha(2024, 11, 12), "Este", "Alice", "Enterprise", 3, 9450m)
  };

  GenerarInforme(datos, "SalesReport.xlsx");
  Console.WriteLine("Reporte escrito.");
}

Usando Xceed Workbooks para .NET en ASP.NET Core

La mayoría de los equipos quieren que este informe se sirva desde un endpoint HTTP en lugar de una aplicación de consola. El patrón es idéntico, pero en lugar de una ruta de archivo, escriba el libro de trabajo en un MemoryStream y devuélvalo como un resultado de archivo. Consulte la documentación de manejo de archivos de ASP.NET Core para obtener orientación sobre el streaming de respuestas.

Endpoint del controlador: devolver ventas-q4.xlsx

[HttpGet("reportes/ventas")]
public IActionResult GetSalesReport()
{
  var data = _service.GetQuarterlyTransactions();
  var stream = new MemoryStream();

  usando (var workbook = Workbook.Create(stream))
  {
    // (misma lógica de construcción que BuildReport)
    workbook.Guardar();
  }

  stream.Position = 0;
  devuelve Archivo(flujo,
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,
    "ventas-t4.xlsx");
}

Nota de compatibilidad

Porque Xceed Workbooks se dirige a .NET Standard 2.0 in addition to modern .NET, the same controller pattern works in legacy .NET Framework Web API projects as well as .NET 8 minimal APIs.

When to choose which library

Choosing a spreadsheet library is a fit problem, not a ranking problem. Here is a neutral summary of the most common options:

  • Xceed Workbooks for .NET: commercial, supported, predictable cell/style API, paid license for production with a 45-day trial. Good when you need vendor support and a stable API surface.
  • EPPlus: dual-licensed (commercial for business use since v5), mature feature set, large community.
  • ClosedXML: MIT-licensed wrapper over the Open XML SDK, free, active community on GitHub.
  • Other commercial libraries: several options exist, each with strengths in conversion fidelity, charting, and integrations.

Pick the library that matches your licensing model, your support expectations, and the breadth of Excel features you need. For Xceed customers already shipping DataGrid for WPF or Words for .NET, sharing a single vendor and license model often outweighs marginal feature differences.

Practical tips and pitfalls

A few habits keep production reports stable:

Production checklist

  • Wrap workbook creation in a using block. The library buffers data until Save(); disposing flushes everything and releases the underlying stream.
  • Set styles after writing values when looping. Style assignment is per-cell; setting it once per cell avoids repeated allocations.
  • Prefer formulas over precomputed values for totals. Users edit reports; live formulas keep totals correct.
  • Stream to MemoryStream for HTTP responses. Writing to disk and re-reading wastes IO and complicates cleanup.
  • Guard against empty datasets. If the input list is empty, write a single “No data” row instead of producing a zero-row sheet that confuses Excel filters.

Ship the sales report this sprint

Download Xceed Workbooks for .NET and run the sample above with a 45-day trial—no license key required.

Preguntas más frecuentes

How do I .NET create Excel file output without installing Office?

Xceed Workbooks for .NET writes the OOXML XLSX format directly, so the host machine does not need Microsoft Office, Excel Interop, or any COM components. The library works in Windows containers, Linux containers, and Azure App Service.

Does Xceed Workbooks for .NET support formulas?

Yes. Set the Formula property on a cell to any valid Excel formula string (for example, =SUM(F4:F23)). Excel evaluates the formula when the user opens the file, and standard functions like SUM, AVERAGE, IF, and VLOOKUP all work as written.

What .NET versions are supported?

The Xceed.Workbooks.NET package targets .NET Standard 2.0, which means it runs on .NET Framework 4.6.1 and later, .NET Core 2.0+, and all modern .NET versions including .NET 6, .NET 8, and .NET 9.

Can I create multiple worksheets in one XLSX C# file?

Yes. Call workbook.Worksheets.Add("SheetName") to add additional sheets. Each worksheet exposes the same Cells indexer, so the building code from this article applies unchanged to multi-sheet financial packs.

How does the trial license work?

The 45-day trial runs without any license key code. After purchase, set the license key once at application startup. The library otherwise behaves identically during and after the trial period.

How do I read an existing XLSX file?

Use Workbook.Load(path) instead of Workbook.Create. Then access workbook.Worksheets[0].Cells["A1"].Value to read values. The same API supports modify-and-save round trips on existing files.

Echa un vistazo a la biblioteca de palabras y PDF de Xceed paquete