Cayaqui.MPS.ExcelExport 0.9.1

dotnet add package Cayaqui.MPS.ExcelExport --version 0.9.1
                    
NuGet\Install-Package Cayaqui.MPS.ExcelExport -Version 0.9.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Cayaqui.MPS.ExcelExport" Version="0.9.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Cayaqui.MPS.ExcelExport" Version="0.9.1" />
                    
Directory.Packages.props
<PackageReference Include="Cayaqui.MPS.ExcelExport" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Cayaqui.MPS.ExcelExport --version 0.9.1
                    
#r "nuget: Cayaqui.MPS.ExcelExport, 0.9.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Cayaqui.MPS.ExcelExport@0.9.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Cayaqui.MPS.ExcelExport&version=0.9.1
                    
Install as a Cake Addin
#tool nuget:?package=Cayaqui.MPS.ExcelExport&version=0.9.1
                    
Install as a Cake Tool

Cayaqui.MPS.ExcelExport

Exporta colecciones de DTOs a .xlsx usando los atributos del paquete Cayaqui.MPS.Metadata. Simétrico a Cayaqui.MPS.ExcelImport — decorás tu DTO una sola vez y se importa/exporta con formato consistente.

Distribución propietaria — requiere contrato comercial con Cayaqui. Ver LICENSE.txt.

Dependencias: Cayaqui.MPS.Metadata (se registra automáticamente con AddMpsExcelExport) + licencia Syncfusion XlsIO.


CoverSheetSection agrega un área de footer al final de la portada con el logo corporativo Cayaqui (izquierda) y el texto "Powered by Cayaqui · MPS Project Suite" (derecha). Se activa pasando LogoOptions.MpsCompanyLogo en ExcelExportOptions.Logos.

var logos = new LogoOptions
{
    OwnerLogo      = new BytesLogo { Bytes = ownerLogoBytes },
    MpsCompanyLogo = new BytesLogo { Bytes = cayaquiLogoBytes }  // nuevo
};

var opts = new ExcelExportOptions
{
    Theme = theme,
    Logos = logos
};

v0.8.0 — Template corporativo: CoverSheetSection + ReportTheme

Sistema de branding unificado para workbooks profesionales. Un solo ReportTheme configura la portada, footer y tab color de todas las hojas.

var theme = new ReportTheme
{
    ReportTitle          = "Monthly Project Report",
    ProjectName          = "Talara U3 — Expansion",
    CompanyName          = "Cayaqui S.A.",
    PreparedBy           = "Project Controls Team",
    Version              = "1.0",
    ReportDate           = new DateTime(2026, 4, 30),
    ConfidentialityLabel = "CONFIDENCIAL",
    PrimaryColorHex      = "#0F2044",   // deep navy
    AccentColorHex       = "#C9961A",   // amber gold
    TitleFont            = "Calibri Light",
    BodyFont             = "Calibri"
};

var report = new ExcelReport()
    .AddCoverSheet()                    // portada corporativa oscura
    .AddEvmKpiStrip(new EvmKpiStripSection { Snapshot = kpiSnapshot })
    .AddEvmSCurveChart(new EvmSCurveChartSection { Points = sCurve, Bac = 10_000_000m })
    .AddCashflowChart(new CashflowChartSection { Points = cashflow });

var stream = await exporter.ExportAsync(report, new ExcelExportOptions { Theme = theme });

CoverSheetSection genera un sheet con:

  • Banda superior oscura (primary color) con logos cliente/Cayaqui
  • Título del reporte (26pt, Calibri Light) + nombre del proyecto + fecha
  • Franja de acento ámbar superior e inferior
  • Tabla de información: Proyecto / Empresa / Preparado por / Fecha / Versión / Clasificación

Footer automático aplicado a todas las hojas cuando Theme está configurado:

  • Izquierda: fecha del reporte (formato dd-MMM-yy)
  • Centro: ConfidentialityLabel (ej. "CONFIDENCIAL")
  • Derecha: "Página &P de &N"

Tab color: todas las hojas (excepto Cover) reciben PrimaryColorHex como color de pestaña.

ReportTheme.MpsCorporateDark es el preset default (deep navy #0F2044 + amber #C9961A). Se activa automáticamente cuando Theme = null en CoverSheetSection.

Propiedad Default
PrimaryColorHex "#0F2044" (deep navy)
AccentColorHex "#C9961A" (amber gold)
TitleFont "Calibri Light"
BodyFont "Calibri"
ConfidentialityLabel "CONFIDENCIAL"
Version "1.0"

Logos se configuran en ExcelExportOptions.Logos:

var options = new ExcelExportOptions
{
    Theme = theme,
    Logos = new LogoOptions
    {
        OwnerLogo  = new BytesLogo(ownerLogoBytes),
        CayaquiLogo = new BytesLogo(cayaquiLogoBytes)
    }
};

Sin breaking changes. Requiere Cayaqui.MPS.ReportModels ≥ 0.4.0.


v0.7.4 — R9C esquema actualizado

R9cReportSection ahora usa el nuevo esquema R9C: PO / CO / PC / Comprometido / Incurrido / Pagado / Trends / EAC / %Ejec. La columna Varianza fue eliminada. Totals row calcula %Ejec = sumIncurrido / sumEAC. Requiere Cayaqui.MPS.ReportModels ≥ 0.3.5.


v0.7.3 — 6 nuevas secciones EPC

6 nuevas secciones de project controls para ingeniería/procura:

var report = new ExcelReport()
    .AddTitle("Talara U3 · Cut-off 2026-04-30")
    .AddWbsBudgetTable(new WbsBudgetTableSection
    {
        Title = "Presupuesto WBS",
        Rows = new[]
        {
            new WbsBudgetRow("1.0",   "Ingeniería",       Level: 0, Bac: 5_000_000m, Ev: 4_200_000m, Ac: 4_500_000m, Eac: 5_357_143m, PercentComplete: 0.84m, Currency: "USD"),
            new WbsBudgetRow("1.1",   "Diseño básico",    Level: 1, Bac: 2_000_000m, Ev: 2_000_000m, Ac: 2_100_000m, Eac: 2_100_000m, PercentComplete: 1.00m, Currency: "USD"),
            new WbsBudgetRow("1.2",   "Diseño detalle",   Level: 1, Bac: 3_000_000m, Ev: 2_200_000m, Ac: 2_400_000m, Eac: 3_272_727m, PercentComplete: 0.73m, Currency: "USD"),
        }
    })
    .AddEngProgressTable(new EngProgressTableSection
    {
        Title = "Avance Ingeniería",
        Rows = new[]
        {
            new EngProgressRow("ENG-001", "Plano P&ID", "Proceso",
                PlanPct: 0.90m, ActualPct: 0.85m,
                PlannedCompletion: new DateTime(2026, 5, 15),
                ForecastCompletion: new DateTime(2026, 5, 22)),
        }
    })
    .AddLookaheadTable(new LookaheadTableSection
    {
        Title = "Lookahead 3 Semanas",
        Rows = new[]
        {
            new LookaheadRow("1.2.1", "Rev. planos estructurales", "J. Pérez",
                new DateTime(2026, 5, 19), new DateTime(2026, 5, 23),
                LookaheadStatus.InProgress),
        }
    })
    .AddEvmControlChart(new EvmControlChartSection
    {
        Title = "Control Chart SV/CV",
        Points = controlChartPoints   // IEnumerable<ControlChartPoint>
    })
    .AddRaciMatrix(new RaciMatrixSection
    {
        Title = "Matriz RACI",
        Items = new[]
        {
            new RaciEntry("Diseño básico", "Ing. Jefe",    RaciRole.Responsible),
            new RaciEntry("Diseño básico", "Gerente Proy", RaciRole.Accountable),
            new RaciEntry("Diseño básico", "Cliente",      RaciRole.Consulted),
        }
    })
    .AddPoRegister(new PoRegisterSection
    {
        Title = "Registro de Órdenes de Compra",
        Items = new[]
        {
            new PoEntry("PO-001", "Aceros del Sur", "Estructuras metálicas",
                450_000m, "USD", "Approved",
                IssueDate: new DateTime(2026, 3, 1),
                DeliveryDate: new DateTime(2026, 6, 30)),
        }
    });
Sección Sheet default Tipo Descripción
WbsBudgetTableSection "WBS Budget" tabla 9 cols Code / WBS Name (indentado) / BAC / EV / AC / EAC / CV / CPI / % Done. CV verde/rojo; CPI semáforo ≥0.95/0.85.
EngProgressTableSection "Eng Progress" tabla 8 cols Code / Title / Discipline / Plan% / Actual% / Deviation / Planned Date / Forecast Date. Deviation verde/rojo.
LookaheadTableSection "Lookahead" tabla 7 cols WBS Code / Activity / Responsible / Start / Finish / Status / Comments. Status coloreado.
EvmControlChartSection "EVM Control Chart" line chart SV (ámbar) y CV (azul) en el tiempo con línea cero de referencia.
RaciMatrixSection "RACI Matrix" tabla pivot Actividades × Roles. R=azul, A=púrpura, C=ámbar, I=neutro.
PoRegisterSection "PO Register" tabla 7 cols PO# / Supplier / Description / Amount (con currency) / Status / Issue Date / Delivery Date.

Requiere Cayaqui.MPS.ReportModels ≥ 0.3.3. Sin breaking changes.


v0.6.0 — Migración a ReportModels + 8 secciones Fase 2

Migración de DTOs a Cayaqui.MPS.ReportModels (nuevo peer-dependency, zero-dep): EvmKpiSnapshot, EvmSCurvePoint, CashflowPoint, BurndownPoint, R9cEntry, RiskItem+RiskView, VarianceRow, PhysicalProgressPoint, ProductionPoint. Los namespaces se mantienen via global usingsin breaking changes para consumers existentes. SemaforoColors y EvmChartPalette conservan sus APIs públicas y delegan internamente a ReportModels.

8 nuevas secciones Fase 2:

var report = new ExcelReport()
    .AddTitle("Talara U3 · Cut-off 2026-04-30")
    .AddContingencyDrawdown(new ContingencyDrawdownSection
    {
        Points = contingencyPoints, ControlDate = controlDate
    })
    .AddWaterfall(new WaterfallSection
    {
        Steps = new[]
        {
            new WaterfallStep("BAC", WaterfallStepKind.Total, 10_000_000m),
            new WaterfallStep("Contingencia usada", WaterfallStepKind.Subtract, 500_000m),
            new WaterfallStep("Reserva gestión", WaterfallStepKind.Subtract, 200_000m),
            new WaterfallStep("EAC pendiente", WaterfallStepKind.Forecast, 9_300_000m),
        }
    })
    .AddResourceHistogram(new ResourceHistogramSection
    {
        Buckets = resourceBuckets, CapacityLimit = 40m, CapacityUnit = "HH/mes"
    })
    .AddManagementReserveTracker(new ManagementReserveTrackerSection
    {
        Events = mrEvents, InitialReserve = 500_000m, Currency = "USD"
    })
    .AddTornadoChart(new TornadoChartSection { Items = tornadoItems, Currency = "USD" })
    .AddMilestoneStrip(new MilestoneStripSection { Milestones = milestones })
    .AddRiskRegisterTable(new RiskRegisterTableSection { Entries = riskRegister })
    .AddChangeOrderLog(new ChangeOrderLogSection { Entries = changeOrders, Currency = "USD" });
Sección Sheet Tipo Descripción
ContingencyDrawdownSection "Contingency" line chart Plan/Actual contingencia restante, optional ControlDate
WaterfallSection "Waterfall" stacked column Spacer invisible + color por WaterfallStepKind
ResourceHistogramSection "Resources" stacked column Pivote Period×Category + optional Capacity line
ManagementReserveTrackerSection "MR Tracker" tabla Eventos + running balance + semáforo
TornadoChartSection "Tornado" bar horizontal Low/High deviations ordenadas por range
MilestoneStripSection "Milestones" tabla Row coloring por MilestoneHealth
RiskRegisterTableSection "Risk Register" tabla 10 cols Score cell coloring
ChangeOrderLogSection "Change Orders" tabla 8 cols Status cell coloring

149 tests en MPS.Infrastructure.ExcelExport.Tests (todos passing). Sin breaking changes. Requiere Cayaqui.MPS.ReportModels ≥ 0.2.0.


v0.5.1 — Patch: paleta de curvas alineada con design system MPS

Fix de paleta en PhysicalProgressCurveSection y ProductionCurveSection. v0.5.0 publicaba con colores invertidos respecto al componente Blazor real (MPS.Components.Evm.PhysicalProgressCurve/ProductionCurve):

Sección Serie v0.5.0 (incorrecto) v0.5.1 (correcto)
Physical Progress Baseline #9CA3AF sin dash #44403C dashed
Physical Progress Actual #039855 (verde) #D92D20 (rojo) con markers
Physical Progress Forecast #F79D1E dashed #039855 (verde) dashed
Production Plan #2E5BFF (azul EVM) #7F56D9 (púrpura mining)
Production Actual #D92D20 (rojo) #0086C9 (cyan)
Production Nameplate #101828 (negro) #D92D20 (rojo dashed)

EvmChartPalette agrega 2 constantes públicas: Baseline (#44403C) y Cyan (#0086C9). +2 tests de regresión por sección. Sin breaking changes en API — solo cambia el output visual.


v0.5.0 — Mining + Risk extensions (3 secciones nuevas + sparklines inline)

3 nuevas secciones para los verticals mining production + risk QRA, plus sparklines opcionales inline en R9C / Schedule Variance:

var report = new ExcelReport()
    .AddTitle("Talara U3 · Mining cut-off 2026-04-30")
    .AddR9cReport(new R9cReportSection
    {
        Rows = r9c, Currency = "USD",
        TrendData = cpiHistory     // 👈 NEW v0.5 — agrega columna "Trend" con sparkline nativo
    })
    .AddMonteCarloHistogram(new MonteCarloHistogramSection
    {
        Samples = qraSamples, Bins = 30, Percentiles = new[] { 50, 80, 90 }
    })
    .AddPhysicalProgressCurve(new PhysicalProgressCurveSection
    {
        Points = progressPoints, ControlDate = controlDate, ShowGoalLine = true
    })
    .AddProductionCurve(new ProductionCurveSection
    {
        Points = production, NameplateRate = 5_000m, Unit = "t/día"
    });
Sección Output Contenido
MonteCarloHistogramSection sheet "Monte Carlo" IChart tipo Histogram + summary header (N, min, max, mean, P50/P80/P90) + tabla de samples ordenados. Bins configurables.
PhysicalProgressCurveSection sheet "Physical Progress" Hasta 4 series % (Baseline / Plan / Actual / Forecast) + opcional Goal horizontal en YMax (100%) + opcional ControlDate vertical stripline.
ProductionCurveSection sheet "Production" 2 series (Plan / Actual) + opcional NameplateRate horizontal stripline (techo de capacidad de planta).
R9cReportSection.TrendData y ScheduleVarianceTableSection.TrendData columna "Trend" inline Sparkline nativo Excel (IRange.SparklineGroups) por fila — celdas helper en columnas hidden a la derecha.

DTOs nuevos: PhysicalProgressPoint, ProductionPoint. Helper público: MonteCarloHistogramSection.Percentile(sortedSamples, p) (linear-interpolation NIST C=R7 — mismo método que numpy.percentile default).

Sin breaking changes. Sparklines son opcionales (TrendData = null mantiene el output v0.4.0 idéntico). +27 tests xUnit (120 total). Ver scripts/migrate-to-excelexport-0.5.0.md.

Out of scope (v0.6.0+): WaterfallChartSectionExcelChartType.Waterfall no existe en XlsIO 33.2.3 (solo Histogram / BoxAndWhisker / Funnel); el workaround con Column_Stacked queda para iteración futura.


v0.4.0 — Executive cut-off report completo (5 secciones nuevas + TableSection<T>)

Suma 5 secciones EVM y desbloquea TableSection<T> (refactor mínimo de ExcelExporter<T>). Ahora un cut-off mensual completo entra en un solo workbook:

var report = new ExcelReport()
    .AddTitle("Talara U3 · Cut-off 2026-04-30")
    .AddEvmKpiStrip(new EvmKpiStripSection { Snapshot = evmSnapshot })
    .AddEvmSCurveChart(new EvmSCurveChartSection { Points = evmPoints, Bac = 10_000_000m })
    .AddCashflowChart(new CashflowChartSection { Points = cashflow, CutOffDate = controlDate })
    .AddR9cReport(new R9cReportSection { Rows = r9c, Currency = "USD" })
    .AddRiskHeatmap(new RiskHeatmapSection { Risks = risks, View = RiskView.Inherente })
    .AddScheduleVariance(new ScheduleVarianceTableSection { Rows = variance, WarnThreshold = 5 })
    .AddBurndownChart(new BurndownChartSection { Points = burndown, TargetDate = goLive })
    .AddTable(controlAccounts, new TableSectionOptions { SheetName = "CAs" });

await using var stream = await ReportExporter.ExportAsync(report);
Sección Output Contenido
EvmKpiStripSection sheet "KPIs" Strip 8-cols (CPI/SPI/EV/AC/PV/BAC/EAC/VAC) con cell coloring semáforo via EvmThresholds (default 0.95/0.90/1.05/1.10).
R9cReportSection sheet "R9C" Reporte de 9 Columnas canónico (AACE 80R-13). 11 cols + freeze + autofilter + variance coloring + totals.
RiskHeatmapSection sheet "Risk Heatmap" + "Risks" Matriz Rows×Cols (default 5×5) con cell coloring por score; sheet anexo con tabla de risks. View configurable: Inherente/Residual/Objetivo.
ScheduleVarianceTableSection sheet "Schedule Variance" Tabla baseline/current/forecast + columna SV (días) calculada + cell coloring por WarnThreshold + indent visual jerárquico.
BurndownChartSection sheet "Burndown" IChart line con 2 series (Remaining vs Ideal calculado), opcional stripline TargetDate.
TableSection<T> sheet custom Cualquier colección tipada — delega al IExcelExporter<T> ya existente; respeta atributos de MPS.Metadata.

DTOs nuevos (sin dep en MPS.Components): EvmKpiSnapshot, R9cEntry, RiskItem + RiskView, VarianceRow, BurndownPoint, EvmThresholds, SemaforoColors.

ExcelExporter<T>.ExportAsync (v0.2.0) sigue intacto — el refactor extrajo RenderToSheetAsync interno reusable. Sin breaking changes. +44 tests xUnit (93 total). Ver scripts/migrate-to-excelexport-0.4.0.md.


v0.3.0 — Reportes con secciones + charts EVM nativos

Nueva API IExcelReportExporter para componer reportes multi-sheet con la Curva S de EVM y el Cashflow mensual + acumulado como IChart Excel nativos (no imágenes — refrescables y editables in-Excel):

@inject IExcelReportExporter ReportExporter

var report = new ExcelReport()
    .AddTitle("Talara U3 · Cut-off 2026-04-30")
    .AddEvmSCurveChart(new EvmSCurveChartSection
    {
        Points      = evmPoints,                  // PV, EV, AC, Forecast por mes
        Bac         = 10_000_000m,                // stripline horizontal
        ControlDate = new DateTime(2026, 4, 30),  // stripline vertical
        Currency    = "USD"
    })
    .AddCashflowChart(new CashflowChartSection
    {
        Points         = cashflowPoints,          // Plan, Actual, Forecast por mes
        CutOffDate     = new DateTime(2026, 4, 30),
        Currency       = "USD",
        ShowCumulative = true                     // 3 columnas + 3 líneas acumuladas (dual-axis)
    });

await using var stream = await ReportExporter.ExportAsync(report);

Output: workbook con sheet "Cover" (título + branding logos) + "Curva S" (4 series + striplines BAC/ControlDate) + "Cashflow" (combo dual-axis con 6 series + stripline CutOffDate).

DTOs propios del package (sin dependencia con MPS.Components):

public sealed record EvmSCurvePoint(DateTime Date, decimal? Pv, decimal? Ev, decimal? Ac, decimal? Forecast);
public sealed record CashflowPoint(DateTime Date, decimal Plan, decimal Actual, decimal Forecast);

Si tu data layer ya construye los del componente Blazor, mappeás con un LINQ (mismo shape, distinto namespace).

EvmChartPalette expone los colores canónicos (Plan, Earned, Actual, Forecast, Bac, CutOff) como Syncfusion.Drawing.Color reutilizables — paleta #2E5BFF Plan, #7F56D9 EV, #D92D20 Actual, #039855 Forecast. Forecast/EAC siempre dashed para indicar proyección. Las acumuladas las computa CumulativeBuilder con paridad tested vs MPS.Components.Evm.CashflowChart.BuildDisplayPoints — los valores que ves en Excel son los mismos que los del componente Blazor.

AddTable<T> queda para v0.4.0 (out of scope este release; los reportes que requieran tablas combinan IExcelExporter<T>.ExportAsync con IExcelReportExporter.ExportAsync por ahora).

Sin breaking changes. El IExcelExporter<T>.ExportAsync v0.2.0 sigue idéntico. Ver scripts/migrate-to-excelexport-0.3.0.md. +35 tests xUnit (49 total).


Instalación

dotnet add package Cayaqui.MPS.ExcelExport
builder.Services.AddMpsExcelExport();

Atributos consumidos

Atributo Efecto en el export
[Display(Name, Order, GroupName)] / [Label] Header de columna + orden
[Currency] / [Percentage] / [Date] / [Integer] / [DecimalFormat] / [Duration] Formato de celda nativo (number format string)
[Align] Horizontal alignment (Left/Center/Right)
[ColumnWidth(px)] Ancho de columna
[VisibleIn(RenderTargets.Web)] / [Hidden] Columna omitida del export si no incluye Excel
[Badge(BadgeKind.Success)] Background color de las celdas de la columna
[UpperCase] / [LowerCase] / [TitleCase] / [Truncate] Transform aplicado al string antes de escribir
[ImportIgnore] Excluida también del export (simetría)

[Mask] NO se aplica al export — exportar datos enmascarados sería un bug (pierde el valor original para ediciones). Se respeta el valor sin máscara para que Excel edite bien.

Convenciones importantes

[Percentage] — almacenar ratio 0.0–1.0

Excel interpreta el formato 0.0% multiplicando el valor por 100. Almacenar 75.6 en el DTO produciría 7560% en la celda. Convención correcta:

[Percentage(1)]
public decimal Cpi { get; set; }   // ← almacenar 0.756, NO 75.6

Al exportar, la celda se ve 75.6%. Al importar (round-trip), se recupera 0.756.

[Badge] con enum values — color por fila

Sobre una propiedad enum con [BadgeColor] en cada valor, cada fila recibe el color correspondiente al valor de esa fila:

public enum Status
{
    [BadgeColor(BadgeKind.Success)] Approved,
    [BadgeColor(BadgeKind.Error)]   Rejected
}

[Badge] public Status RowStatus { get; set; }
// En Excel: filas con Approved → verde, filas con Rejected → rojo

[Badge(BadgeKind.Success)] (FixedKind) → toda la columna del mismo color.

Uso

public sealed class InvoiceRow
{
    [Display(Name = "N°", Order = 1)]
    public int InvoiceNumber { get; set; }

    [Label("Cliente")] [Display(Order = 2)]
    public string CustomerName { get; set; } = "";

    [Currency("USD", 2)] [Align(TextAlign.Right)] [ColumnWidth(120)] [Display(Order = 3)]
    public decimal Amount { get; set; }

    [Date("dd-MMM-yyyy")] [Display(Order = 4)]
    public DateTime IssueDate { get; set; }

    [Badge(BadgeKind.Success)] [Display(Order = 5)]
    public bool IsPaid { get; set; }

    [Hidden]
    public int InternalId { get; set; }
}
public class InvoiceExportService(IExcelExporter<InvoiceRow> exporter)
{
    public async Task<Stream> GenerateAsync(IEnumerable<InvoiceRow> rows)
    {
        return await exporter.ExportAsync(rows, new ExcelExportOptions
        {
            SheetName = "Invoices",
            FreezeHeaderRow = true,
            AutoFilter = true,
            HeaderBackgroundColor = "#D9E1F2"
        });
    }
}

ExcelExportOptions

public sealed class ExcelExportOptions
{
    string SheetName = "Data";
    bool IncludeHeader = true;
    bool StyleHeader = true;                           // bold + background
    string HeaderBackgroundColor = "#D9E1F2";
    bool FreezeHeaderRow = true;
    bool AutoFilter = true;
    bool AutoFitColumns = false;                       // usa [ColumnWidth] cuando se declara
    CultureInfo Culture = CultureInfo.InvariantCulture;
}

Tipos nativos vs texto

El exporter respeta el tipo de .NET para que Excel los trate como datos reales (números son sumables, fechas son filtrables):

.NET Excel cell type
int, long, short, byte, decimal, double, float Number
bool Boolean
DateTime, DateTimeOffset, DateOnly DateTime (con format por [Date])
Enum Text (nombre del valor)
string Text (con transforms opcionales)

Round-trip Export → Import

var rows = new[] { new InvoiceRow { ... } };

await using var exported = await exporter.ExportAsync(rows);    // DTO → xlsx
var result = await importer.ImportAsync(exported);              // xlsx → DTO
// result.Rows[0] === rows[0] (values preserved)

Este roundtrip está cubierto por tests.

Tests

Proyecto MPS.Infrastructure.ExcelExport.Tests9 tests ✅:

  • Header + row values con types nativos (number, text, bool)
  • [Hidden] excluye columna
  • [Display(Order)] respeta orden declarado
  • [VisibleIn(Web)] (sin Excel flag) omite columna
  • [Currency] aplica number format a celdas
  • Header styled bold + freeze pane activa
  • Empty collection produce output sólo con header
  • Round-trip: Export → Import preserva valores (int, string, decimal)

Requisitos

  • .NET 10.0 o superior
  • Cayaqui.MPS.Metadata (auto-registrado con AddMpsExcelExport)
  • Licencia Syncfusion Essential Studio (XlsIO)
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.9.1 58 5/26/2026
0.9.0 30 5/26/2026
0.7.4 153 5/19/2026
0.7.3 82 5/19/2026
0.7.2 85 5/18/2026
0.7.1 83 5/18/2026
0.7.0 90 5/18/2026
0.6.0 89 5/18/2026
0.5.1 132 5/10/2026
0.5.0 91 5/10/2026
0.4.0 94 5/10/2026
0.3.0 92 5/10/2026
0.2.0 394 4/24/2026
0.1.1 107 4/24/2026
0.1.0 113 4/24/2026

0.9.1 — CoverSheetSection: logo aspect ratio preserved (fit-within maxW×maxH without distortion). 0.9.0 — CoverSheetSection Cayaqui company footer logo via LogoOptions.MpsCompanyLogo. 0.7.4 — R9cReportSection: esquema R9C actualizado (Incurrido/Pagado/Trends/EAC). Totals row usa sumIncurred/sumEac. Requiere ReportModels ≥ 0.3.5. 0.7.3 — 6 new sections: WbsBudgetTableSection, EngProgressTableSection, LookaheadTableSection, EvmControlChartSection (SV/CV line chart), RaciMatrixSection (pivot table), PoRegisterSection. 6 new fluent builder methods on ExcelReport.

0.7.2 — Fix: MPS.Licensing.dll incluido en lib/net10.0/ del .nupkg (faltaba en 0.7.0/0.7.1 → 502.5 en IIS).

0.7.1 — Fix: re-publicación de 0.7.0 con binarios correctos. Sin diferencia de API.

0.7.0 — Licensing: AddMpsExcelExport acepta licenseKey opcional (ECDSA P-256). Sin clave válida, el workbook generado incluye hoja de marca de agua y footer en cada pestaña. ExcelLicenseState registrado en DI. Sin breaking changes.

0.6.0 — Migración DTOs a Cayaqui.MPS.ReportModels (sin breaking changes) + 8 secciones Fase 2: ContingencyDrawdownSection, WaterfallSection, ResourceHistogramSection, ManagementReserveTrackerSection, TornadoChartSection, MilestoneStripSection, RiskRegisterTableSection, ChangeOrderLogSection. 149 tests. v0.5.1 — Patch: paleta de PhysicalProgressCurveSection y ProductionCurveSection alineada con MPS.Components Blazor. PhysicalProgressCurveSection: Baseline cambia de #9CA3AF a #44403C dashed (paridad), Actual cambia de verde #039855 a rojo #D92D20 con markers (era Forecast color), Forecast cambia de naranja #F79D1E a verde #039855 dashed (era Actual color). ProductionCurveSection: Plan cambia de #2E5BFF azul a #7F56D9 púrpura, Actual cambia de #D92D20 rojo a #0086C9 cyan, NameplateRate stripline cambia de #101828 negro a #D92D20 rojo dashed. EvmChartPalette agrega Baseline (#44403C) y Cyan (#0086C9) como constantes públicas. +2 tests de regresión. Suite total: 122. Sin breaking changes — solo afecta el output visual de los charts. v0.5.0 — Mining + Risk extensions. 3 secciones EVM nuevas: MonteCarloHistogramSection (output canonico de QRA con bins configurables y summary P50/P80/P90 — usa ExcelChartType.Histogram nativo), PhysicalProgressCurveSection (Baseline/Plan/Actual/Forecast en %, con goal line en YMax=100% opcional y ControlDate vertical stripline), ProductionCurveSection (Plan vs Actual mining + opcional NameplateRate horizontal stripline). Plus sparklines inline opcionales en R9cReportSection.TrendData y ScheduleVarianceTableSection.TrendData (IReadOnlyDictionary indexado por Code/WbsCode) usando IRange.SparklineGroups nativo de Excel — agrega una columna "Trend" con sparkline por fila. DTOs nuevos: PhysicalProgressPoint, ProductionPoint. Helper publico MonteCarloHistogramSection.Percentile (linear-interpolation NIST C=R7). Waterfall queda fuera de scope: ExcelChartType.Waterfall no existe en XlsIO 33.2.3, el workaround con Column_Stacked queda para v0.6.0. Sin breaking changes — sparklines opt-in via TrendData null. +27 tests xUnit (120 total). Ver scripts/migrate-to-excelexport-0.5.0.md. v0.4.0 — Executive cut-off report completo. Cinco secciones EVM nuevas: EvmKpiStripSection (strip CPI/SPI/EV/AC/PV/BAC/EAC/VAC con cell coloring semaforo via EvmThresholds), R9cReportSection (Reporte de 9 Columnas canonico AACE 80R-13 con 11 cols + variance coloring + totals), RiskHeatmapSection (matriz NxM con cell coloring por score + sheet anexo de Risks; view configurable Inherente/Residual/Objetivo), ScheduleVarianceTableSection (baseline/current/forecast + SV dias + threshold coloring + indent jerarquico), BurndownChartSection (Remaining vs Ideal + opcional TargetDate stripline). Y TableSection<T> desbloqueada — refactor minimo de ExcelExporter<T> extrayendo RenderToSheetAsync internal reusable, sin breaking. DTOs nuevos: EvmKpiSnapshot, R9cEntry, RiskItem + RiskView, VarianceRow, BurndownPoint, EvmThresholds, SemaforoColors. +44 tests xUnit (93 total). Sin breaking changes — IExcelExporter<T>.ExportAsync sigue identico. Ver scripts/migrate-to-excelexport-0.4.0.md. v0.3.0 — EVM charts nativos en .xlsx (Curva S + Cashflow), refrescables (no imagenes). Nueva API IExcelReportExporter con builder fluido ExcelReport: AddTitle/AddEvmSCurveChart/AddCashflowChart. EvmSCurveChartSection produce 4 series (PV/EV/AC/EAC) sobre IChart combo, con BAC stripline horizontal y ControlDate stripline vertical (ambos como series auxiliares 2-puntos con LinePattern.Dash). CashflowChartSection produce combo dual-axis: 3 columnas (Plan/Actual/Forecast en eje primario) + 3 lineas acumuladas (Plan cum/Actual cum/Forecast cum dashed en eje secundario), con CutOffDate stripline vertical. CumulativeBuilder reproduce con paridad tested la logica de MPS.Components.Evm.CashflowChart.BuildDisplayPoints (cumsum con anchor del Forecast cum en el ultimo Actual cum <= cutoff). Paleta canonica MPS: Plan #2E5BFF, EV #7F56D9, Actual #D92D20, Forecast #039855. AddTable<T> queda para v0.4.0. Sin breaking changes — IExcelExporter<T>.ExportAsync de v0.2.0 sigue identico. +35 tests xUnit (49 total). Ver scripts/migrate-to-excelexport-0.3.0.md. v0.2.0 — HideGridlines (default true) + ExcelExportOptions.Logos (Owner + Cayaqui logos). v0.1.1 — patches. v0.1.0 — Initial release: IExcelExporter<T> con Metadata-attribute-driven header labels, cell format, alignment, width, visibility, column order, badge-based background color.