MATTAR.Reporting est une bibliothèque C# .NET simple et légère pour générer des rapports à partir de gabarits (templates). Elle supporte trois modes de génération :
- PDF AcroForm — remplissage de champs de formulaire dans un PDF existant (via PdfSharpCore)
- HTML / PDF depuis template HTML — rendu Scriban + export PDF (via HtmlRenderer.PdfSharp, hors WASM)
- PDF depuis template MigraDoc DDL — rendu Scriban + MigraDocCore, 100 % compatible Blazor WebAssembly
Essayez la démo Blazor WebAssembly en ligne :
👉 Démo MATTAR.Reporting sur GitHub Pages
Cette démo interactive vous permet de :
- 📄 Générer des rapports PDF directement dans le navigateur
- 🌐 Générer du HTML à partir de templates
- 📋 Tester les 3 templates prédéfinis (Facture, Rapport Mensuel, Certificat)
- ⚡ Voir les résultats en temps réel
- 💾 Télécharger les documents générés
100% côté client - Aucune donnée n'est envoyée à un serveur.
Voir le code source : samples/Blazor-Wasm/
- ✅ Génération de rapports PDF à partir d'un template PDF contenant des champs de formulaire (AcroForm)
- ✅ Remplissage dynamique des champs via un dictionnaire
clé → valeur - ✅ Protection du document généré par mot de passe propriétaire
- ✅ Création automatique du dossier de sortie si inexistant
- ✅ Permissions de sécurité configurables (impression, annotations, extraction...)
- ✅ Génération de rapports depuis un template HTML avec remplacement de placeholders (via Scriban)
- ✅ Export PDF depuis un template HTML (via HtmlRenderer.PdfSharp, hors WASM)
- ✅ Génération PDF depuis un template MigraDoc DDL (via Scriban + MigraDocCore, compatible WASM)
- ✅ Support des images (injection base64 dans les rapports HTML, dessin sur les champs PDF)
- ✅ Support des tableaux dynamiques (collections de lignes injectées via Scriban)
- ✅ Compatible Blazor WebAssembly - Génération 100% côté client (v1.1.0+)
MATTAR.Reporting/
├── src/
│ ├── Interfaces/
│ │ └── IReport.cs # Interface commune à tous les générateurs de rapports
│ ├── PdfReport.cs # Implémentation PDF AcroForm (via PdfSharpCore)
│ ├── HtmlReport.cs # Implémentation HTML/PDF (via Scriban + HtmlRenderer.PdfSharp)
│ ├── MigraDocReport.cs # Implémentation MigraDoc DDL (compatible WASM)
│ └── MATTAR.Reporting.csproj # Projet de la bibliothèque (multi-target: net10.0 + net10.0-browser)
├── sample/
│ ├── Program.cs # Exemple d'utilisation console
│ ├── FACTURE.pdf # Template PDF exemple (AcroForm)
│ └── MATTAR.Reporting.Console.csproj
├── samples/
│ ├── Blazor-Wasm/ # Démo interactive Blazor WebAssembly
│ │ ├── Pages/
│ │ ├── Services/
│ │ └── MattarReportBlazor.csproj
│ └── MATTAR.Reporting.BlazorSample/ # Autre exemple Blazor
├── tests/
│ └── MATTAR.Reporting.Tests/ # Tests unitaires (xUnit + Shouldly)
│ ├── Fixtures/ # Fichiers de test (templates PDF, DDL...)
│ ├── PdfReportTests.cs
│ ├── HtmlReportTests.cs
│ └── MigraDocReportTests.cs
├── docs/ # Documentation (déployée sur GitHub Pages via Jekyll)
├── MATTAR.Reporting.sln
└── README.md
Disponible sur NuGet : https://www.nuget.org/packages/MATTAR.Reporting/
dotnet add package MATTAR.Reportinggit clone https://github.com/mattar-shadi/MATTAR.Reporting.git
cd MATTAR.Reporting
dotnet build- .NET 10.0 ou supérieur
- Dépendances NuGet (gérées automatiquement) :
PdfSharpCore1.3.67Scriban7.2.5MigraDocCore.DocumentObjectModel1.3.67MigraDocCore.Rendering1.3.67SixLabors.ImageSharp3.1.12HtmlRenderer.PdfSharp.NetStandard21.5.1.3(hors WASM uniquement)
Créez un fichier PDF contenant des champs de formulaire AcroForm (nommés). Ces noms seront utilisés comme clés dans le dictionnaire de données.
Vous pouvez créer des templates avec des logiciels comme LibreOffice, Adobe Acrobat, ou PDF-XChange Editor.
using MATTAR.Reporting;
IReport report = new PdfReport();
string templatePath = "templates/FACTURE.pdf";
string outputPath = $"Output/{DateTime.Now:yyyy-MM-dd}_FACTURE.pdf";
string generatedFilePath = report.GenerateReport(
templatePath,
outputPath,
new Dictionary<string, string?>
{
{ "Number", "F2231323" },
{ "CustomerNumber", "C12354" },
{ "JourneyNumber", "J2231323" },
{ "EntryNumber", "E31FF323" },
{ "Date", DateTime.Now.ToShortDateString() },
{ "Name", "MATTAR SASU" },
{ "Line1", "50 Avenue Pierre-George Latécoère" },
{ "ZipCode", "31520" },
{ "City", "RAMONVILLE-SAINT-AGNE (FRANCE)" },
{ "InvoiceLine1Description", "Stockage des marchandises (jour)" },
{ "InvoiceLine1UnitPrice", "45 000" },
{ "InvoiceLine1Qty", "2" },
{ "InvoiceLine1Total", "90 000" },
{ "TotalBeforeTax", "90 000" },
{ "TaxAmount", "17 100" },
{ "Total", "107 100" }
}
);
Console.WriteLine("Fichier généré : " + Path.GetFullPath(generatedFilePath));Créez un fichier HTML contenant des placeholders au format {{ NomDuChamp }} (syntaxe Scriban). Ces noms correspondent aux clés du dictionnaire de données.
using MATTAR.Reporting;
IReport htmlReport = new HtmlReport();
string templatePath = "templates/FACTURE.html";
// Générer un PDF depuis un template HTML
string outputPdfPath = $"Output/{DateTime.Now:yyyy-MM-dd}_FACTURE.pdf";
string generatedPdfPath = htmlReport.GenerateReport(
templatePath,
outputPdfPath,
new Dictionary<string, string?>
{
{ "Number", "F2231323" },
{ "Name", "MATTAR SASU" },
{ "Date", DateTime.Now.ToShortDateString() },
{ "Total", "107 100" }
}
);
// Générer un fichier HTML depuis un template HTML
string outputHtmlPath = $"Output/{DateTime.Now:yyyy-MM-dd}_FACTURE.html";
string generatedHtmlPath = htmlReport.GenerateReport(
templatePath,
outputHtmlPath,
new Dictionary<string, string?>
{
{ "Number", "F2231323" },
{ "Name", "MATTAR SASU" },
{ "Date", DateTime.Now.ToShortDateString() },
{ "Total", "107 100" }
}
);
Console.WriteLine("PDF généré : " + Path.GetFullPath(generatedPdfPath));
Console.WriteLine("HTML généré : " + Path.GetFullPath(generatedHtmlPath));Exemple de template HTML (FACTURE.html) :
<!DOCTYPE html>
<html>
<body>
<h1>Facture N° {{ Number }}</h1>
<p>Client : {{ Name }}</p>
<p>Date : {{ Date }}</p>
<p>Total : {{ Total }} €</p>
</body>
</html>Les placeholders suivent la syntaxe Scriban (
{{ clé }}). Toutes les clés du dictionnairedatassont disponibles dans le template.
Pour les environnements Blazor WebAssembly (où HtmlReport ne peut pas produire de PDF), utilisez MigraDocReport avec un template au format MigraDoc DDL combiné avec des placeholders Scriban :
using MATTAR.Reporting;
IReport migraReport = new MigraDocReport();
string generatedPath = migraReport.GenerateReport(
"templates/INVOICE.ddl",
"Output/INVOICE.pdf",
new Dictionary<string, string?>
{
{ "Number", "INV-001" },
{ "Name", "MATTAR SASU" },
{ "Date", DateTime.Now.ToShortDateString() },
{ "Total", "107 100" }
}
);Le paramètre optionnel tables permet d'injecter des collections de lignes dans les templates Scriban (HTML ou MigraDoc DDL) :
IReport htmlReport = new HtmlReport();
string generatedPath = htmlReport.GenerateReport(
"templates/RAPPORT.html",
"Output/RAPPORT.html",
new Dictionary<string, string?> { { "Title", "Rapport Mensuel" } },
tables: new Dictionary<string, IEnumerable<Dictionary<string, string?>>>
{
{
"Items", new[]
{
new Dictionary<string, string?> { { "Name", "Produit A" }, { "Qty", "10" }, { "Price", "500" } },
new Dictionary<string, string?> { { "Name", "Produit B" }, { "Qty", "5" }, { "Price", "200" } }
}
}
}
);Template HTML correspondant :
<table>
{{ for item in Items }}
<tr>
<td>{{ item.Name }}</td>
<td>{{ item.Qty }}</td>
<td>{{ item.Price }} €</td>
</tr>
{{ end }}
</table>Le paramètre optionnel images permet d'injecter des images dans les rapports générés.
Les images sont converties en URI base64 et injectées comme des variables Scriban. Utilisez-les directement dans l'attribut src d'une balise <img> :
IReport htmlReport = new HtmlReport();
string generatedPath = htmlReport.GenerateReport(
"templates/FACTURE.html",
"Output/FACTURE.html",
new Dictionary<string, string?>
{
{ "Number", "F2231323" },
{ "Name", "MATTAR SASU" }
},
ownerPassword: null,
images: new Dictionary<string, string?>
{
{ "Logo", "assets/logo.png" }
}
);Template HTML correspondant (FACTURE.html) :
<!DOCTYPE html>
<html>
<body>
<img src="{{ Logo }}" style="width:200px;" />
<h1>Facture N° {{ Number }}</h1>
<p>Client : {{ Name }}</p>
</body>
</html>Les types MIME reconnus automatiquement : .png, .jpg/.jpeg, .gif, .webp, .bmp.
Pour les templates PDF, les images sont dessinées directement sur la page aux coordonnées du champ AcroForm de type bouton poussoir (PdfPushButtonField) :
IReport pdfReport = new PdfReport();
string generatedPath = pdfReport.GenerateReport(
"templates/FACTURE.pdf",
"Output/FACTURE.pdf",
new Dictionary<string, string?>
{
{ "Number", "F2231323" }
},
ownerPassword: null,
images: new Dictionary<string, string?>
{
{ "Logo", "assets/logo.png" } // "Logo" doit être le nom d'un champ bouton dans le PDF
}
);Remarque : Si le champ n'existe pas ou n'est pas de type bouton poussoir, l'image est ignorée silencieusement. Si le fichier image est introuvable, une
FileNotFoundExceptionest levée.
Par défaut, le document PDF généré est protégé par un mot de passe propriétaire ("MATTAR.Reporting"). Les permissions appliquées sont :
| Permission | Valeur |
|---|---|
| Impression normale | ✅ Autorisé |
| Impression haute qualité | ✅ Autorisé |
| Annotations | ❌ Refusé |
| Remplissage de formulaires | ❌ Refusé |
| Extraction du contenu | ❌ Refusé |
| Modification du document | ❌ Refusé |
| Assemblage du document | ❌ Refusé |
Vous pouvez personnaliser le mot de passe en passant le paramètre ownerPassword :
report.GenerateReport(templatePath, outputPath, datas, ownerPassword: "MonMotDePasse");Pour désactiver la protection, passez ownerPassword: null ou ownerPassword: "".
Tous les générateurs implémentent l'interface commune suivante :
public interface IReport
{
string GenerateReport(
string templateDocPath,
string outputPathFile,
Dictionary<string, string?> datas,
string? ownerPassword = "MATTAR.Reporting",
Dictionary<string, string?>? images = null,
Dictionary<string, IEnumerable<Dictionary<string, string?>>>? tables = null
);
}| Paramètre | Type | Description |
|---|---|---|
templateDocPath |
string |
Chemin vers le fichier template (.pdf, .html, .ddl) |
outputPathFile |
string |
Chemin de destination du fichier généré |
datas |
Dictionary<string, string?> |
Champs texte à remplir (nom → valeur) |
ownerPassword |
string? |
Mot de passe propriétaire du PDF (optionnel) |
images |
Dictionary<string, string?>? |
Images à insérer (nom → chemin du fichier) |
tables |
Dictionary<string, IEnumerable<Dictionary<string, string?>>>? |
Tableaux dynamiques (nom → collection de lignes) |
Retour : le chemin du fichier généré (outputPathFile).
Les tests unitaires se trouvent dans tests/MATTAR.Reporting.Tests/ et utilisent xUnit et Shouldly.
# Lancer tous les tests
dotnet test
# Avec sortie détaillée
dotnet test --verbosity normal
# En mode Release
dotnet test --configuration Release --verbosity normalLes cas couverts incluent : template introuvable, valeurs null, création automatique du répertoire de sortie, protection par mot de passe, images manquantes ou inconnues, et tableaux dynamiques.
Le projet utilise quatre workflows GitHub Actions :
| Workflow | Déclencheur | Description |
|---|---|---|
CI - Build & Test (ci.yml) |
Push sur toutes les branches / PR vers main |
Build + tests automatiques |
Publish - NuGet (publish.yml) |
Manuel (workflow_dispatch) |
Publication du package sur NuGet.org (nécessite le secret NUGET_API_KEY) |
Deploy Blazor WASM (deploy-blazor-wasm.yml) |
Push sur main (changements dans samples/Blazor-Wasm/) |
Build et déploiement de la démo sur GitHub Pages |
Deploy GitHub Pages (pages.yml) |
Push sur main (changements dans docs/) |
Déploiement de la documentation via Jekyll |
Voir le dossier sample/ pour un exemple d'utilisation console complet.
Voir le dossier samples/Blazor-Wasm/ pour une implémentation complète avec :
- Interface utilisateur interactive
- Génération de PDF côté client (via
MigraDocReport) - Génération de HTML côté client (via
HtmlReport) - Téléchargement des documents générés
Démo en ligne : https://mattar-shadi.github.io/MATTAR.Reporting/samples/Blazor-Wasm/
PlatformNotSupportedException lors de la génération PDF depuis un template HTML en WASM
HtmlReport.GenerateReport(...) avec un fichier de sortie .pdf n'est pas supporté en Blazor WebAssembly. Utilisez MigraDocReport à la place pour générer des PDF en WASM :
// ❌ Ne fonctionne pas en WASM
IReport htmlReport = new HtmlReport();
htmlReport.GenerateReport("template.html", "output.pdf", datas);
// ✅ Fonctionne en WASM
IReport migraReport = new MigraDocReport();
migraReport.GenerateReport("template.ddl", "output.pdf", datas);FileNotFoundException sur le template
Vérifiez que le chemin du template est correct et que le fichier est bien accessible. Utilisez Path.GetFullPath(...) pour déboguer les chemins relatifs.
DirectoryNotFoundException sur le répertoire de sortie
La bibliothèque crée automatiquement le répertoire de sortie. Cette exception survient uniquement si un fichier (non dossier) existe déjà sur le chemin parent spécifié.
- Génération PDF via AcroForm
- Génération HTML (via Scriban + HtmlRenderer.PdfSharp)
- Support MigraDoc (DDL templates) compatible WASM
- Démo interactive Blazor WebAssembly
- Support des images dans les champs
- Support des tableaux dynamiques (via Scriban)
- Publication NuGet officielle
- Export PDF depuis template HTML avancé (mise en page complexe)
Ce projet est distribué sous licence MIT. Voir le fichier LICENSE pour plus de détails.
Les contributions sont les bienvenues !
- Forkez le dépôt
- Créez une branche pour votre fonctionnalité (
git checkout -b feature/ma-fonctionnalite) - Committez vos changements (
git commit -m 'feat: ajouter ma fonctionnalité') - Poussez vers la branche (
git push origin feature/ma-fonctionnalite) - Ouvrez une Pull Request
N'hésitez pas à ouvrir une issue pour signaler un bug ou proposer une amélioration.
- 📖 Documentation complète (GitHub Pages)
- 🔗 Package NuGet
- 🐛 Issues & Discussions
- 🎯 Démo interactive
Développé par mattar-shadi