Reportes.Mre.Pdfs 1.0.0

dotnet add package Reportes.Mre.Pdfs --version 1.0.0
                    
NuGet\Install-Package Reportes.Mre.Pdfs -Version 1.0.0
                    
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="Reportes.Mre.Pdfs" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Reportes.Mre.Pdfs" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Reportes.Mre.Pdfs" />
                    
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 Reportes.Mre.Pdfs --version 1.0.0
                    
#r "nuget: Reportes.Mre.Pdfs, 1.0.0"
                    
#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 Reportes.Mre.Pdfs@1.0.0
                    
#: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=Reportes.Mre.Pdfs&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Reportes.Mre.Pdfs&version=1.0.0
                    
Install as a Cake Tool

Reportes.Mre.Pdfs

Libreria .NET 7.0 para generacion de reportes PDF a partir de plantillas DOCX o HTML (ZIP). Reemplaza Aspose.Words de forma transparente, manteniendo el mismo contrato de codigo.

Instalacion

Dependencias NuGet

<PackageReference Include="DocumentFormat.OpenXml" Version="3.0.1" />
<PackageReference Include="Haukcode.DinkToPdf" Version="1.1.0" />
<PackageReference Include="Scriban" Version="5.9.0" />

DLL nativa (wkhtmltopdf)

La libreria requiere la DLL nativa de wkhtmltopdf para generar PDFs:

Plataforma Archivo Ubicacion
Windows x64 libwkhtmltox.dll Native/ o raiz del proyecto
Linux x64 libwkhtmltox.so Native/ o raiz del proyecto
macOS x64 libwkhtmltox.dylib Native/ o raiz del proyecto

El paquete Haukcode.DinkToPdf ya incluye las DLLs nativas para las 3 plataformas.


Uso basico

using Reportes.Mre.Pdfs;

// === Con plantilla DOCX ===
Document doc = new Document(@"Recursos\FORMATOFORMULARIO2024.docx");
ReportingEngine engine = new ReportingEngine();
engine.BuildReport(doc, dataSource, "data");
doc.Save(@"C:\temp\reporte.pdf");

// === Con plantilla ZIP (HTML) ===
Document doc = new Document(@"Recursos\Plantilla.zip");
ReportingEngine engine = new ReportingEngine();
engine.BuildReport(doc, dataSource, "data");
doc.Save(@"C:\temp\reporte.pdf");

El contrato es identico para ambos formatos. La extension del archivo (.docx o .zip) determina automaticamente el pipeline de procesamiento.


API publica

Document

namespace Reportes.Mre.Pdfs
{
    public class Document
    {
        // Crea un documento a partir de una plantilla DOCX o ZIP
        public Document(string filePath);

        // Guarda el documento procesado como PDF
        // Si la ruta tiene extension .docx, se cambia automaticamente a .pdf
        public void Save(string outputPath);
    }
}

ReportingEngine

namespace Reportes.Mre.Pdfs
{
    public class ReportingEngine
    {
        public ReportingEngine();

        // Procesa la plantilla con los datos proporcionados
        // dataSourceName es el nombre usado en la plantilla (ej: "data")
        public void BuildReport(Document doc, object dataSource, string dataSourceName);
    }
}

Plantillas DOCX

Sintaxis de marcadores

La libreria soporta la sintaxis de Aspose.Words Reporting Engine (LINQ):

Campos simples
<<[data.NombreCampo]>>

Ejemplo en el DOCX:

Nombre: <<[data.NombreCargo]>>
Categoria: <<[data.CategoriaPuesto]>>
Listas / Foreach
<<foreach [item in data.Lista]>>
  <<[item.Propiedad]>>
<</foreach>>

Ejemplo:

<<foreach [item in data.FuncionesPuesto]>>
  Funcion: <<[item.Funcion]>>
  Resultado: <<[item.Resultado]>>
  Porcentaje: <<[item.FuncionPuestoPorcentaje]>>
<</foreach>>
Foreach en tablas (expansion de filas)

Cuando un <<foreach>> esta dentro de una fila de tabla y referencia campos en otras celdas de la misma fila, la fila completa se duplica por cada elemento de la lista:

| <<foreach [item in data.Funciones]>><<[item.Nombre]>> | <<[item.Resultado]>> | <<[item.Porcentaje]>> |
| <</foreach>>                                                                                         |

Esto genera una fila por cada item de la coleccion.

Marcadores especiales
Marcador Descripcion
<<cellMerge>> Fusiona la celda con la anterior (colspan en HTML)
<<restartNum>> Reinicia numeracion de lista (se ignora en el PDF)

Estructura del DOCX

  • Body: Contenido principal con tablas, parrafos y marcadores
  • Header: Se extrae automaticamente y se repite en cada pagina del PDF
    • Soporta tablas, texto e imagenes
    • Las imagenes se convierten a base64 inline
  • Footer: Se extrae si existe

Formato de campos en el DOCX

Los campos pueden estar divididos entre multiples "Runs" de Word con diferentes formatos (bold, italic, font-size). La libreria los reassembla automaticamente antes de procesarlos.


Plantillas ZIP (HTML)

Estructura del ZIP

Plantilla.zip
  plantilla-body.html       <-- REQUERIDO: cuerpo del documento
  plantilla-header.html     <-- OPCIONAL: header repetible en cada pagina
  plantilla-footer.html     <-- OPCIONAL: footer (puede estar vacio)

Los archivos se detectan por nombre: cualquier archivo con body, header o footer en el nombre.

plantilla-body.html

Puede ser un fragmento HTML o un documento completo. Usa la misma sintaxis de marcadores Aspose, HTML-encoded:

<style>
  .tbl { width: 100%; border-collapse: collapse; font-size: 9.5pt; }
  .tbl td { border: 1px solid #5B9BD5; padding: 3pt 5pt; }
  .td-num { font-weight: bold; width: 6%; }
  .td-lbl { font-weight: bold; }
</style>

<table class="tbl">
  <tr>
    <td class="td-num">1.1</td>
    <td class="td-lbl">UBICACION</td>
    <td>&lt;&lt;[data.Ubicacion]&gt;&gt;</td>
  </tr>
</table>


<table class="tbl">
  <tr>
    <td>&lt;&lt;foreach [item in data.FuncionesPuesto]&gt;&gt;&lt;&lt;[item.Funcion]&gt;&gt;</td>
    <td>&lt;&lt;[item.Resultado]&gt;&gt;</td>
    <td>&lt;&lt;[item.FuncionPuestoPorcentaje]&gt;&gt;&lt;&lt;/foreach&gt;&gt;</td>
  </tr>
</table>

Nota: Los marcadores << y >> deben estar HTML-encoded como &lt;&lt; y &gt;&gt; en el HTML.

plantilla-header.html

Documento HTML completo que se usa como header repetible en cada pagina:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8"/>
  <style>
    .doc-header { width: 100%; border-collapse: collapse; }
    .doc-header td { border: 1px solid #5B9BD5; padding: 3px 5px; }
    .col-logo { width: 45%; text-align: center; }
    .col-titulo { width: 27%; text-align: center; }
    .col-version { width: 27%; text-align: center; }
  </style>
</head>
<body>
  <table class="doc-header">
    <tr>
      <td class="col-logo" rowspan="2">
        <img src="data:image/png;base64,..." />
        MINISTERIO DE RELACIONES EXTERIORES
      </td>
      <td class="col-titulo">
        <strong>MANUAL DE PUESTOS</strong><br/>
        POAI 2026
      </td>
      <td class="col-version">Version: GM-01.2026</td>
    </tr>
    <tr>
      <td></td>
      <td>Fecha Aprobacion: ___/___/2026</td>
    </tr>
  </table>
</body>
</html>

Las imagenes deben estar como base64 inline (data:image/png;base64,...).

Si el header usa un wrapper .pagina (estilo Puppeteer/Playwright), la libreria ajusta automaticamente los paddings para wkhtmltopdf.

plantilla-footer.html

Puede estar vacio o contener solo un comentario HTML si no se necesita footer:



DataSource (objeto de datos)

El dataSource puede ser cualquier objeto .NET. Las propiedades se acceden por nombre (PascalCase) desde la plantilla:

var dataSource = new
{
    // Campos simples
    Ubicacion = "SERVICIO CENTRAL",
    NombreCargo = "Analista Senior",
    CategoriaPuesto = "Profesional",
    NroItem = "1234",

    // Listas de objetos
    FuncionesPuesto = new List<FuncionPuestoDto>
    {
        new() { Funcion = "Elaborar planillas", Resultado = "Planillas aprobadas", FuncionPuestoPorcentaje = 30 },
        new() { Funcion = "Controlar asistencia", Resultado = "Reportes generados", FuncionPuestoPorcentaje = 20 },
    },

    // Objetos anidados
    Idiomas = new IdiomasDto
    {
        Extranjero = new List<IdiomaCodificadorDTO>
        {
            new() { Idioma = new() { Nombre = "Ingles" }, Nivel = new() { Nombre = "Intermedio" } }
        }
    },

    // Listas de strings
    GradoFormacion = new List<string> { "Licenciatura en Administracion", "Licenciatura en Derecho" }
};

Tipos soportados

Tipo Acceso en plantilla Ejemplo
string, int, decimal, etc. <<[data.Campo]>> <<[data.NombreCargo]>>
List<T> <<foreach [item in data.Lista]>> <<foreach [item in data.FuncionesPuesto]>>
Objetos anidados <<[data.Objeto.Propiedad]>> <<[data.Idiomas.Extranjero]>>
List<string> <<foreach [item in data.Lista]>><<[item]>> Items sin propiedad

Pipeline de procesamiento

Entrada (.docx o .zip)
         |
    [Document constructor]
         |
    +----+----+
    |         |
  DOCX       ZIP
    |         |
  OpenXML   Extraer 3 HTMLs
  -> HTML    |
    |        Decodificar &lt;&lt; -> <<
    |         |
    +----+----+
         |
  Convertir Aspose -> Scriban
  (<<[campo]>> -> {{ campo }})
  Promover loops a nivel fila
         |
    [ReportingEngine.BuildReport()]
         |
  Scriban procesa template + datos
  Aplicar cellMerge
         |
    [Document.Save()]
         |
  DinkToPdf genera PDF
  (header repetible en cada pagina)
         |
    Archivo PDF

Configuracion del PDF generado

Propiedad Valor
Formato A4 Portrait
DPI 300
Margenes Top: 12mm (45mm con header), Bottom/Left/Right: 12mm
Fuente base Segoe UI, Calibri, Verdana, Arial
Font-size base 8pt
Encoding UTF-8
IntelligentShrinking Desactivado
MinimumFontSize 7pt

Estructura del proyecto

Reportes.Mre.Pdfs/
  Reportes.Mre.Pdfs.csproj          .NET 7.0 Class Library
  Document.cs                        Clase publica principal
  ReportingEngine.cs                 Clase publica principal
  Core/
    DocxToHtmlConverter.cs           OpenXML -> HTML (con imagenes base64)
    ZipTemplateLoader.cs             Carga plantillas desde ZIP
    AsposeTemplateSyntaxParser.cs    Convierte Aspose -> Scriban
    TemplateProcessor.cs             Motor Scriban (datos -> HTML)
    PdfGenerator.cs                  DinkToPdf (HTML -> PDF)
  Models/
    ConversionContext.cs             Estado del pipeline
  Native/
    libwkhtmltox.dll                 DLL nativa (Windows x64)

Ejemplo completo

using Reportes.Mre.Pdfs;

// 1. Cargar plantilla (DOCX o ZIP)
Document doc = new Document(@"Recursos\FORMATOFORMULARIO2024.docx");

// 2. Preparar datos
var dataSource = new ForrmatoPoaiDto
{
    Ubicacion = "SERVICIO CENTRAL",
    LocalizacionGeografica = "La Paz, Bolivia",
    NombreCargo = "Analista de RRHH",
    CategoriaPuesto = "Profesional",
    NroItem = "1234",
    ObjetivoPuesto = "Gestionar procesos de administracion de personal",
    RelacionesIntrainstitucionales = new List<CodificadorDTO>
    {
        new() { Nombre = "Direccion de Asuntos Juridicos" },
        new() { Nombre = "Unidad Financiera" }
    },
    FuncionesPuesto = new List<FuncionPuestoDto>
    {
        new() { Funcion = "Elaborar planillas", Resultado = "Planillas aprobadas", FuncionPuestoPorcentaje = 30 }
    },
    Compentencias = new List<CompetenciaDto>
    {
        new() { Competencia = new() { Nombre = "Liderazgo" }, Descripcion = "Dirigir equipos de trabajo" }
    }
};

// 3. Procesar
ReportingEngine engine = new ReportingEngine();
engine.BuildReport(doc, dataSource, "data");

// 4. Generar PDF
doc.Save(@"C:\temp\POAI_output.pdf");

Migracion desde Aspose.Words

Antes (Aspose)

using Aspose.Words;
using Aspose.Words.Reporting;

Aspose.Words.License license = new Aspose.Words.License();
license.SetLicense(@"Recursos\License.txt");

Document doc = new Document(@"Recursos\FORMATOFORMULARIO2024.docx");
ReportingEngine engine = new ReportingEngine();
engine.BuildReport(doc, dataSource, "data");
doc.Save(path);  // genera DOCX

Despues (Reportes.Mre.Pdfs)

using Reportes.Mre.Pdfs;

// No requiere licencia
Document doc = new Document(@"Recursos\FORMATOFORMULARIO2024.docx");
ReportingEngine engine = new ReportingEngine();
engine.BuildReport(doc, dataSource, "data");
doc.Save(path);  // genera PDF (cambia .docx -> .pdf automaticamente)

Cambios necesarios en el codigo consumidor:

  1. Cambiar using Aspose.Words / using Aspose.Words.Reporting por using Reportes.Mre.Pdfs
  2. Eliminar las lineas de licencia Aspose
  3. La salida ahora es PDF en vez de DOCX

Notas importantes

  • Thread safety: El conversor PDF usa un SynchronizedConverter singleton (thread-safe)
  • Imagenes: Se extraen del DOCX (header/body) como base64 inline en el HTML
  • Headers repetibles: Se muestran en cada pagina del PDF via wkhtmltopdf
  • Foreach en tablas: Los loops que expanden filas se promueven automaticamente fuera del <tr>
  • Encoding: Siempre UTF-8
  • Archivos temporales: Los headers se guardan en archivos temporales que se eliminan automaticamente
Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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
1.0.0 142 3/18/2026

v1.0.0 - Release inicial
- Soporte de plantillas DOCX (OpenXML) y ZIP (HTML)
- Sintaxis Aspose compatible: campos simples, foreach, cellMerge
- Motor de templates Scriban
- Generacion PDF via DinkToPdf (wkhtmltopdf)
- Extraccion automatica de headers/footers/imagenes del DOCX
- Headers repetibles en cada pagina del PDF