Cayaqui.MPS.ExcelExport 0.5.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package Cayaqui.MPS.ExcelExport --version 0.5.1
                    
NuGet\Install-Package Cayaqui.MPS.ExcelExport -Version 0.5.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.5.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.5.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.5.1
                    
#r "nuget: Cayaqui.MPS.ExcelExport, 0.5.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.5.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.5.1
                    
Install as a Cake Addin
#tool nuget:?package=Cayaqui.MPS.ExcelExport&version=0.5.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.

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 192 5/26/2026
0.9.0 81 5/26/2026
0.7.4 160 5/19/2026
0.7.3 89 5/19/2026
0.7.2 92 5/18/2026
0.7.1 89 5/18/2026
0.7.0 96 5/18/2026
0.6.0 96 5/18/2026
0.5.1 135 5/10/2026
0.5.0 94 5/10/2026
0.4.0 97 5/10/2026
0.3.0 95 5/10/2026
0.2.0 397 4/24/2026
0.1.1 110 4/24/2026
0.1.0 116 4/24/2026

0.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.