VISION · Forge · SlideForge
Technische Dokumentation
Version 1.0 · .NET 8 · Namespace: VISION.Forge.SlideForge.* · Alle Abhängigkeiten MIT-lizenziert
Installation & Setup
NuGet Pakete
dotnet add package VISION.Forge.SlideForge dotnet add package VISION.Forge.SlideForge.Manipulation dotnet add package VISION.Forge.SlideForge.Rendering dotnet add package VISION.Forge.SlideForge.Charts dotnet add package VISION.Forge.SlideForge.Export
Projektstruktur
VISION.Forge.SlideForge.sln ├── VISION.Forge.SlideForge.Core Domain Models, Interfaces ├── VISION.Forge.SlideForge.OpenXml PPTX Parser ├── VISION.Forge.SlideForge.Pdf PDF Export ├── VISION.Forge.SlideForge.Rendering PNG/JPEG Renderer ├── VISION.Forge.SlideForge.Manipulation Editing + Template Engine ├── VISION.Forge.SlideForge.Charts SVG Chart Generation ├── VISION.Forge.SlideForge.Export HTML, SVG, XPS Export ├── VISION.Forge.SlideForge.Licensing RSA/JWT Lizenz-System ├── VISION.Forge.SlideForge.Api Öffentliche Fassade + DI └── VISION.Forge.SlideForge.Tests xUnit Test Suite
Abhängigkeiten (alle MIT)
| Paket | Version | Verwendung |
|---|---|---|
DocumentFormat.OpenXml | 3.0.2 | PPTX Parser |
PdfSharpCore | 1.3.65 | PDF Export |
SkiaSharp | 2.88.8 | Rendering & Fonts |
HarfBuzzSharp | 7.3.0 | Text Shaping |
System.IdentityModel.Tokens.Jwt | 7.6.2 | Lizenz-JWTs |
Lizenzierung
Aktivierung
Hinweis:
LicenseManager.Activate() muss einmalig beim Start der Anwendung aufgerufen werden, bevor SlideForge-Methoden genutzt werden.using VISION.Forge.SlideForge.Licensing; // Empfohlen: aus Environment Variable LicenseManager.Activate(Environment.GetEnvironmentVariable("SLIDEFORGE_KEY")!); // Ablaufdatum prüfen if (LicenseManager.GetExpiryWarning() is {} msg) logger.LogWarning(msg);
Trial-Modus
Ohne Aktivierung läuft SlideForge im Trial-Modus: max. 3 Folien pro Export, Wasserzeichen auf PDFs. Alle Features bleiben testbar.
OEM / SaaS Aktivierung
// SaaS / Docker / Kubernetes OemLicenseAdapter.ActivateSaas("SLIDEFORGE_LICENSE_KEY"); // Desktop-App (verschlüsselte Datei) OemLicenseAdapter.ActivateDesktop(); // Docker Secret OemLicenseAdapter.ActivateFromSecretFile("/run/secrets/slideforge-license"); // Automatisch (probiert alle Methoden in Reihenfolge) var result = OemLicenseAdapter.ActivateAuto();
Air-Gap kompatibel: Endkunden benötigen keine Internetverbindung. Lizenzen werden vollständig offline via RSA-4096/JWT validiert.
PPTX Parsen
using VISION.Forge.SlideForge.OpenXml.Parsing; var parser = PresentationParser.Create(); var doc = parser.Parse("deck.pptx"); // aus Datei var doc = parser.Parse(stream); // aus Stream var doc = await parser.ParseAsync("deck.pptx"); // Dokumentenmodell doc.Width; // Breite in Pixel (96 DPI) doc.Height; // Höhe in Pixel doc.SlideCount; // Anzahl Folien doc.Slides; // IReadOnlyList<SlideModel> foreach (var el in doc.Slides[0].Elements) { if (el is ShapeModel s) Console.WriteLine(s.Name); }
Manipulation
using VISION.Forge.SlideForge.Manipulation; using var m = PresentationManipulator.Open("deck.pptx"); // Folien verwalten m.AddSlide(layoutIndex: 0) .InsertSlide(index: 2) .RemoveSlide(index: 0) .MoveSlide(fromIndex: 3, toIndex: 1) .DuplicateSlide(index: 0); // Inhalt m.ReplaceText("{{Platzhalter}}", "Wert") .AddTextBox(slideIndex: 0, x:100, y:200, width:400, height:50, text: "Hallo") .AddImage(slideIndex: 0, imageData: pngBytes, x:50, y:50, width:200, height:150) .SaveToFile("ausgabe.pptx");
Template Engine
Split-Run Merger: PowerPoint speichert
{{token}} intern oft über mehrere XML-Runs. SlideForge führt diese automatisch zusammen – kein anderes Tool löst dieses Problem.| Syntax | Beschreibung |
|---|---|
{{name}} | Einfacher Wert |
{{kunde.adresse.ort}} | Verschachtelter Pfad |
{{umsatz | format:"N0"}} | Format-Filter |
{{#each liste}} / {{/each}} | Folie N-mal klonen |
{{#if bedingung}} / {{/if}} | Bedingter Inhalt |
{{#slideIf bedingung}} | Ganze Folie entfernen wenn false |
using VISION.Forge.SlideForge.Api; Presentation.Load("vorlage.pptx") .FillTemplate(new { KundenName = "Acme GmbH", Umsatz = 1_250_000m, Mitarbeiter = new[] { new { Name = "Alice", Rolle = "Engineering" }, new { Name = "Bob" , Rolle = "Design" }, } }) .ExportToPdf("bericht.pdf");
Tabellen-Datenbindung
using var m = PresentationManipulator.Open("vorlage.pptx"); m.BindTable(slideIndex: 2, "VerkaufsTabelle", daten, new TableBindOptions { OverflowMode = TableOverflowMode.ContinueOnNextSlide, RepeatHeaderOnContinuation = true, ContinuationTitleSuffix = " (Seite {page}/{total})", AlternatingRowColors = ("FFFFFF", "F3F4F6"), ColumnFormats = new() { [2] = "N0", [3] = "C2" }, SummaryRow = new() { [0] = "Gesamt", [2] = "SUM" }, NullPlaceholder = "–" }); m.SaveToFile("ausgabe.pptx");
PDF Export
using VISION.Forge.SlideForge.Api; Presentation.Load("deck.pptx") .ExportToPdf("ausgabe.pdf", pdf => pdf .ForPrint() .EmbedAllFonts() .WithMetadata(title: "Jahresbericht", author: "Max Mustermann"));
HTML · SVG · XPS Export
using VISION.Forge.SlideForge.Export; // HTML – self-contained, mit Navigation und Speaker Notes Exporter.Html.ExportToFile(doc, "praesentation.html"); // SVG – ein File pro Folie Exporter.Svg.ExportToDirectory(doc, "/ausgabe/svg/"); Exporter.Svg.ExportCombined(doc, "deck.svg"); // XPS – für Druckworkflows, ECMA-388 Exporter.Xps.ExportToFile(doc, "praesentation.xps"); Exporter.Xps.ExportToFile(doc, "druck.xps", XpsExportOptions.HighRes); byte[] xps = Exporter.Xps.ExportToBytes(doc);
PNG/JPEG Rendering
| Modus | Beschreibung |
|---|---|
Contain | Ganzes Bild sichtbar (Letterbox), Seitenverhältnis erhalten |
Cover | Füllt Box, Ränder gecroppt, Seitenverhältnis erhalten |
Stretch | Streckt auf genaue Boxgröße, verändert Seitenverhältnis |
FitWidth | Breite füllt Box, Höhe proportional |
FitHeight | Höhe füllt Box, Breite proportional |
Center | Native Größe, zentriert |
Tile | Kachelmuster |
UsePptxCrop | PowerPoint-eigener Crop-Wert |
using VISION.Forge.SlideForge.Rendering.Options; var renderer = SlideRenderer.Create(new RenderOptions { Dpi = 192, // Retina DefaultImageFitMode = ImageFitMode.Cover, ImageFitOverrides = new() { ["FirmenLogo"] = ImageFitMode.Contain, ["Profilfoto"] = ImageFitMode.Cover } }); foreach (var slide in renderer.RenderAll(doc)) using (slide) slide.SaveToFile($"slide{slide.SlideIndex+1}.png");
Charts (14 Typen)
using VISION.Forge.SlideForge.Charts; // Vertikal-Balken string svg = ChartFactory.Bar.Vertical(new[] { new DataPoint("Q1", 125_000), new DataPoint("Q2", 148_000), }, new ChartOptions { Title = "Quartalsumsatz", NumberFormat = "N0" }); // Donut mit Centertext string svg = ChartFactory.Donut.Build( slices, centerValue: "€ 1.2M", centerLabel: "Umsatz"); // KPI Gauge string kpi = ChartFactory.Gauge.Build( value: 78, min: 0, max: 100, label: "Kundenzufriedenheit", unit: "%"); // Speichern ChartFactory.SaveToFile(svg, "chart.svg");
Verfügbare Typen: Bar Vertical/Horizontal/Stacked · Line · Area · Pie · Donut · Gauge · Waterfall · Scatter · Bubble · Gantt · Heatmap · Radar
Connectors
using var m = PresentationManipulator.Open("diagramm.pptx"); // Auto-Routing zwischen Shapes m.ConnectShapes(slideIndex: 0, fromShapeId: 10, toShapeId: 20); // Org-Chart in einem Rutsch (Chaining) m.ConnectShapes(0, ceoId, ctoId) .ConnectShapes(0, ceoId, cfoId) .ConnectShapes(0, ctoId, devId, options: ConnectorOptions.Flowchart); m.SaveToFile("ausgabe.pptx");
Hyperlinks
m.AddHyperlinkToShape(0, shapeId: 5, HyperlinkTarget.Url("https://vision-software.io")); m.AddHyperlinkToText(0, shapeId: 5, searchText: "hier klicken", HyperlinkTarget.Email("info@acme.de", subject: "Anfrage")); // Alle Links inventarisieren var links = m.GetAllHyperlinks(); // Domain migrieren int count = m.UpdateHyperlinks("alte-domain.de", "neue-domain.de");
Passwortschutz
using VISION.Forge.SlideForge.Manipulation.Protection; // Vollverschlüsselung (AES-256-CBC, PBKDF2-SHA512) var enc = PresentationProtection.Encrypt(bytes, "Mein$tarkes#PW"); var dec = PresentationProtection.Decrypt(enc, "Mein$tarkes#PW"); // Bearbeitungsschutz (Datei lesbar, aber Passwort zum Bearbeiten) var gesperrt = PresentationProtection.ApplyEditingProtection(bytes, "PW"); bool ok = PresentationProtection.ValidatePassword(bytes, "PW");
Speaker Notes
m.SetNotes(0, "Folie 1: Auf Q3-Rückgang eingehen.\nZahlen aus CFO-Bericht."); m.AppendToNotes(0, "\n\nNachtrag: Neue Zahlen berücksichtigen."); string? n = m.GetNotes(0); var alle = m.GetAllNotes(); // Dictionary<int, string> m.ClearNotes(0);
Metadaten
var meta = m.GetMetadata(); m.SetMetadata(new PresentationMetadata { Title = "Q4 Jahresbericht 2024", Author = "Max Mustermann", Company = "VISION", Keywords= "Finanzen, Q4, 2024", Custom = { ["Projektnummer"] = "FIN-2024-Q4", ["Version"] = "1.2" } }); // Nur einzelne Felder ändern (Rest bleibt): m.UpdateMetadata(new PresentationMetadata { Company = "Neue GmbH" });
Kommentare
int id = m.AddComment(0, "Bitte Zahl prüfen", "Max", "max@acme.de", posX: 200, posY: 150); var alle = m.GetAllComments(); m.DeleteComment(slideIndex: 0, commentId: id); m.DeleteAllComments(); // alle Folien
Präsentationen zusammenführen
using var m = PresentationManipulator.Open("master.pptx"); m.AppendPresentation("intro.pptx") .AppendPresentation("finanzen.pptx") .AppendSlides("anhang.pptx", slideIndices: [0, 2]) .InsertPresentation("titelfolie.pptx", insertAt: 0) .SaveToFile("final.pptx");
OEM / SaaS Deployment
Für OEM-Lizenzen: Endkunden sehen ausschließlich dein Produkt – kein Hinweis auf VISION. Kontakt: sales@vision-software.io
// SaaS / Docker / Kubernetes // env: SLIDEFORGE_LICENSE_KEY=eyJhbGc... OemLicenseAdapter.ActivateSaas(); // Docker Secret // docker-compose: secrets: slideforge-license: external: true OemLicenseAdapter.ActivateFromSecretFile("/run/secrets/slideforge-license"); // Desktop-App: Installer schreibt Key einmalig OemLicenseAdapter.WriteDesktopLicenseFile(rawKey); OemLicenseAdapter.ActivateDesktop();
ASP.NET Core Integration
// Program.cs builder.Services.AddSlideForge(o => o.LicenseKey = builder.Configuration["SlideForge:Key"]); // Minimal API Endpoint app.MapGet("/export/{id}", async (int id, Db db) => { var daten = await db.GetReportData(id); using var ms = new MemoryStream(); await Task.Run(() => Presentation.Load("vorlage.pptx") .FillTemplate(daten) .ExportToPdf(ms)); ms.Position = 0; return Results.File(ms, "application/pdf", $"bericht-{id}.pdf"); });
Architektur
Namespace: VISION.Forge.SlideForge.*
SlideForgeDocument (Immutable Domain Model)
│
├── Slides[] → Elements[] (Shape, Image, Table)
├── Theme
└── Width / Height
Eingabe: PresentationParser → SlideForgeDocument
│
┌───────────┴──────────────┐
▼ ▼
PdfExporter SlideRenderer
(PdfSharpCore) (SkiaSharp)
│ │
PDF-Datei PNG/JPEG/SVG
Manipulation: PresentationManipulator
→ Arbeitet direkt auf OOXML-XML
→ Unbekannte Elemente bleiben erhalten
→ Fluente, chainbare API
VISION · SlideForge · © 2025 · support@vision-software.io