Cayaqui.MPS.WordExport 0.1.3

There is a newer version of this package available.
See the version list below for details.
dotnet add package Cayaqui.MPS.WordExport --version 0.1.3
                    
NuGet\Install-Package Cayaqui.MPS.WordExport -Version 0.1.3
                    
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.WordExport" Version="0.1.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Cayaqui.MPS.WordExport" Version="0.1.3" />
                    
Directory.Packages.props
<PackageReference Include="Cayaqui.MPS.WordExport" />
                    
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.WordExport --version 0.1.3
                    
#r "nuget: Cayaqui.MPS.WordExport, 0.1.3"
                    
#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.WordExport@0.1.3
                    
#: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.WordExport&version=0.1.3
                    
Install as a Cake Addin
#tool nuget:?package=Cayaqui.MPS.WordExport&version=0.1.3
                    
Install as a Cake Tool

Cayaqui.MPS.WordExport

Genera documentos Word (.docx) para reportes EVM programáticamente, usando Syncfusion.DocIO. Cada sección implementa IWordDocSection y agrega una sección paginada a un WordDocument existente. Todas las secciones aplican estilo Heading1 para que Word genere automáticamente la Tabla de Contenido.

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

Dependencias: Cayaqui.MPS.ReportModels (DTOs y paleta MPS) + licencia Syncfusion DocIO.


Setup

1 — Agregar el package

<PackageReference Include="Cayaqui.MPS.WordExport" Version="0.1.3" />

Con Central Package Management (Directory.Packages.props):


<PackageVersion Include="Cayaqui.MPS.WordExport" Version="0.1.3" />


<PackageReference Include="Cayaqui.MPS.WordExport" />

2 — Registrar la licencia Syncfusion

En Program.cs, antes de var builder = WebApplication.CreateBuilder(args):

Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense(
    Environment.GetEnvironmentVariable("SYNCFUSION_LICENSE_KEY")
    ?? builder.Configuration["Syncfusion:LicenseKey"]
    ?? throw new InvalidOperationException("Falta SYNCFUSION_LICENSE_KEY"));

Si ya registrás la licencia para otros paquetes Syncfusion (ej: Blazor), no repitas la llamada — una sola cubre toda la suite.

Local dev: dotnet user-secrets set "Syncfusion:LicenseKey" "<KEY>"
CI/Prod: env var SYNCFUSION_LICENSE_KEY o Azure Key Vault.

3 — Registrar en DI

using MPS.Infrastructure.WordExport;

builder.Services.AddMpsWordExport(
    licenseKey: builder.Configuration["MPS:WordExportLicenseKey"]
                ?? Environment.GetEnvironmentVariable("MPS_WORD_EXPORT_LICENSE_KEY"));

Esto registra como singleton:

  • IWordReportContextWordReportContext (opciones default; ver sección "Opciones" para personalizar)
  • IWordReportExporterWordReportExporter

Sin licenseKey válida, el footer de cada sección del .docx muestra texto en rojo. Con licencia, muestra texto gris discreto.

4 — Usings (Blazor)

En _Imports.razor:

@using MPS.Infrastructure.WordExport
@using MPS.Infrastructure.WordExport.Evm
@using MPS.Infrastructure.ReportModels.Evm

Uso

Web API — endpoint de descarga

app.MapGet("/api/reports/evm", async (IWordReportExporter exporter, CancellationToken ct) =>
{
    var report = new WordReport()
        .AddTitle("Reporte EVM — Proyecto Demo", "Período Mayo 2026")
        .AddTableOfContents()
        .AddEvmKpiStrip(new EvmKpiStripDocSection
        {
            Snapshot = new EvmKpiSnapshot(
                Ev: 4_500_000m, Pv: 5_000_000m, Ac: 4_800_000m,
                Bac: 20_000_000m, Eac: 21_333_333m,
                PrevEv: 4_000_000m, PrevPv: 4_500_000m, PrevAc: 4_300_000m)
        })
        .AddEvmSCurveChart(new EvmSCurveChartDocSection
        {
            Points = [
                new(new DateTime(2026, 1, 1), Pv: 1_000_000m, Ev:   900_000m, Ac:   950_000m),
                new(new DateTime(2026, 2, 1), Pv: 2_500_000m, Ev: 2_200_000m, Ac: 2_400_000m),
                new(new DateTime(2026, 3, 1), Pv: 4_000_000m, Ev: 3_500_000m, Ac: 3_700_000m),
                new(new DateTime(2026, 4, 1), Pv: 5_000_000m, Ev: 4_500_000m, Ac: 4_800_000m),
            ],
            Bac         = 20_000_000m,
            ControlDate = new DateTime(2026, 4, 30),
        })
        .AddMilestoneStrip(new MilestoneStripDocSection
        {
            Milestones = [
                new("Ingeniería 30%",  new DateTime(2026, 2, 28), MilestoneHealth.Done),
                new("Ingeniería 60%",  new DateTime(2026, 4, 30), MilestoneHealth.OnTime),
                new("Procura crítica", new DateTime(2026, 6, 30), MilestoneHealth.AtRisk, Critical: true),
            ]
        });

    await using var stream = await exporter.ExportAsync(report, ct);
    var bytes = ((MemoryStream)stream).ToArray();
    return Results.File(bytes,
        contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        fileDownloadName: $"evm-{DateTime.Today:yyyy-MM-dd}.docx");
});

Blazor — botón de descarga

@inject IWordReportExporter WordExporter
@inject IJSRuntime JS

<button @onclick="Descargar">Descargar Word</button>

@code {
    private async Task Descargar()
    {
        var report = new WordReport()
            .AddTitle("Reporte EVM", "Mayo 2026")
            .AddTableOfContents()
            .AddEvmKpiStrip(new EvmKpiStripDocSection { Snapshot = ... });

        await using var stream = await WordExporter.ExportAsync(report);
        var bytes = ((MemoryStream)stream).ToArray();
        using var dotnetStream = new DotNetStreamReference(new MemoryStream(bytes));
        await JS.InvokeVoidAsync("downloadFileFromStream",
            $"reporte-{DateTime.Today:yyyy-MM-dd}.docx",
            dotnetStream);
    }
}

Helper JS en wwwroot/js/download.js:

window.downloadFileFromStream = async (fileName, streamRef) => {
    const bytes = await streamRef.arrayBuffer();
    const blob = new Blob([bytes], { type: "application/octet-stream" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = fileName; a.click();
    URL.revokeObjectURL(url);
};

<script src="js/download.js"></script>

Opciones de estilo

Para personalizar colores de encabezados de tabla y accent de gráficos, reemplazá el registro default:

builder.Services.AddMpsWordExport(licenseKey: "...");

// Sobrescribir el contexto con opciones custom
builder.Services.AddSingleton<IWordReportContext>(_ =>
    new WordReportContext(new WordReportOptions
    {
        HeaderBackgroundColor = "#0D3349",
        AccentColor           = "#1E6FBF",
        Typography = new WordTypographyOptions
        {
            BodyFontName    = "Calibri",
            TableFontName   = "Calibri",
            NumericFontName = "Consolas",
        }
    }));

Secciones disponibles

Tablas

Sección Output Contenido
TitleDocSection párrafo Título + subtítulo del informe.
TableOfContentsDocSection campo TOC Tabla de contenido automática.
EvmKpiStripDocSection tabla 8 cols CPI/SPI/EV/AC/PV/BAC/EAC/VAC. Semáforo + fila delta.
R9cTableDocSection tabla 11 cols Reporte 9 columnas AACE 80R-13 con variance coloring.
RiskHeatmapDocSection tabla grid 5×5 + tabla anexo Score coloring + listado de riesgos.
ScheduleVarianceDocSection tabla Baseline/Current/Forecast + SV días.
MilestoneStripDocSection tabla 5 cols Hitos coloreados por MilestoneHealth.
ChangeOrderLogDocSection tabla 8 cols Log de órdenes de cambio.
RiskRegisterTableDocSection tabla 9 cols Registro de riesgos con score coloring.
WaterfallDocSection tabla 3 cols Cascada Label/Valor/Acumulado por WaterfallStepKind.
ManagementReserveTrackerDocSection tabla + line chart Eventos de reserva + gráfico de balance.
WbsBudgetTableDocSection tabla 9 cols WBS jerárquico con BAC/EV/AC/EAC/CV/CPI/% Done. CPI=EV/AC. Indenta por Level.
EngProgressTableDocSection tabla 8 cols Code/Title/Discipline, Plan%/Actual%/Desviación, Planned Date/Forecast Date. Desviación en verde/rojo.
LookaheadTableDocSection tabla 7 cols WBS/Activity/Responsible/Start/Finish, LookaheadStatus con coloring, Comments.
RaciMatrixDocSection tabla pivot Actividades × Roles. R=azul, A=púrpura, C=ámbar, I=neutro.
PoRegisterDocSection tabla 7 cols PO#/Supplier/Description/Amount/Status/Issue Date/Delivery Date.

Gráficos

Sección Chart Contenido
EvmSCurveChartDocSection line PV/EV/AC/Forecast + líneas BAC y ControlDate.
CashflowChartDocSection column + line Columnas Plan/Actual/Forecast + acumuladas opcionales.
BurndownChartDocSection line Remaining + Ideal calculado.
PhysicalProgressCurveDocSection line % Baseline/Plan/Actual/Forecast.
ProductionCurveDocSection line Plan/Actual + NameplateRate opcional.
MonteCarloHistogramDocSection column Bins + summary stats (N, P50/P80/P90).
ContingencyDrawdownDocSection line Contingencia restante Plan vs Actual.
TornadoChartDocSection bar horizontal Low/High deviations por factor de riesgo.
ResourceHistogramDocSection column stacked Period × Category + Capacity line opcional.
EvmControlChartDocSection line SV (ámbar) y CV (azul) en el tiempo.

Secciones custom

Implementá IWordDocSection para agregar tus propias secciones al flujo:

public sealed class FirmasDocSection : IWordDocSection
{
    public Task RenderAsync(WordDocument document, IWordReportContext context,
        CancellationToken ct = default)
    {
        var body = context.AddSection(document);

        var heading = (WParagraph)body.AddParagraph();
        heading.ApplyStyle(BuiltinStyle.Heading1);
        heading.AppendText("Firmas y Aprobaciones");

        // ... agregar tabla de firmas
        return Task.CompletedTask;
    }
}

// Uso en el builder
var report = new WordReport()
    .AddTitle("Mi Reporte")
    .AddTableOfContents();

report.Sections.Add(new FirmasDocSection());  // sección custom al final

Notas técnicas

  • Cada sección agrega un WSection con SectionBreakCode.NewPage (excepto la primera).
  • Los encabezados usan BuiltinStyle.Heading1 para el outline de TOC automático.
  • WordReportExporter llama UpdateDocumentFields() antes de guardar — el TOC se resuelve automáticamente. En LibreOffice, actualizar manualmente al abrir.
  • Colores de series line: usar SerieFormat.LineProperties.LineColor. SerieFormat.Fill.ForeColor aplica sólo a series Column/Bar.
  • El helper JS downloadFileFromStream espera 2 argumentos: (fileName, streamRef) — no pasar contentType como tercer argumento.
  • El footer de cada sección lleva texto de watermark: gris con licencia válida, rojo sin ella.
  • Target framework: net10.0. No compatible con .NET 9 o anterior.

Release Notes

0.1.3

6 nuevas secciones EPC: WbsBudgetTableDocSection (9 cols, CPI=EV/AC, indentación WBS), EngProgressTableDocSection (8 cols, desviación coloreada), LookaheadTableDocSection (7 cols, LookaheadStatus), EvmControlChartDocSection (SV/CV line chart), RaciMatrixDocSection (pivot Activity×Role con RACI coloring), PoRegisterDocSection (7 cols). Requiere Cayaqui.MPS.ReportModels ≥ 0.3.3.

0.1.2

Fix TypeLoadException en despliegues IIS con múltiples paquetes MPS (WordLicenseState no encontrado). Solución: MPS.Licensing.dll bumped a AssemblyVersion 2.0.0.0 — .NET siempre carga la versión más alta cuando múltiples copies están presentes.

0.1.1

Initial release con 20 secciones (10 tablas + 9 gráficos + TOC). Setup vía AddMpsWordExport(licenseKey).

0.1.0

Scaffold: contratos IWordDocSection, IWordReportContext, IWordReportExporter, WordReport builder fluido.

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.3.1 170 5/26/2026
0.3.0 82 5/26/2026
0.1.5 167 5/19/2026
0.1.4 83 5/19/2026
0.1.3 86 5/19/2026
0.1.2 94 5/19/2026
0.1.1 84 5/19/2026
0.1.0 94 5/19/2026

0.1.3 — 6 new doc sections: WbsBudgetTableDocSection, EngProgressTableDocSection, LookaheadTableDocSection, EvmControlChartDocSection (SV/CV line chart), RaciMatrixDocSection (pivot table), PoRegisterDocSection. 6 new fluent builder methods on WordReport.
0.1.2 — fix: bump MPS.Licensing assembly version to 2.0.0.0 so .NET picks the correct version when multiple Cayaqui.MPS.* packages bundle different copies of MPS.Licensing.dll (TypeLoadException on WordLicenseState).
0.1.1 — docs: expand PackageReadme with full consumer setup guide (DI registration, Web API + Blazor download examples, custom sections, style options). No code changes.
0.1.0 — Scaffold: IWordDocSection, IWordReportContext, WordReportContext, WordReportOptions, WordReport, WordReportExporter. 20 EVM doc sections (19 EVM + TOC). Heading outline for auto-generated Table of Contents.