Diese Seite kann automatisch übersetzten Text enthalten.
Kurzanleitung zur C#-PDF-Generierung
Lesen Sie, wie Sie in Ihren .NET-Projekten PDF-Dateien wie Berichte, Rechnungen und Quittungen generieren. Erstellen Sie mit C# oder VB.NET ganz einfach PDF-Dokumente, indem Sie Strukturelemente zusammenstellen. Zu den Elementen gehören Kopfzeilen, Fußzeilen, Container, Tabellen, Absätze, Bilder und dergleichen. Die API unterteilt Inhalte automatisch in Seiten.
Einige andere Methoden zum Generieren von PDF-Dateien werden im Artikel PDF-Dokumente in C# und VB.NET erstellen beschrieben.
Wir bieten die Layout-API als kostenloses Add-on für die Docotic.Pdf-Bibliothek an. Sowohl die Bibliothek als auch das Layout-Add-on sind auf NuGet und auf unserer Website verfügbar. Holen Sie sich die Bibliothek, das Add-on und einen kostenlosen zeitlich begrenzten Lizenzschlüssel auf der Seite Laden Sie die C# .NET PDF-Bibliothek herunter.
9.5.17615-dev 9.5.17615-dev14,813 bestanden NuGet-Downloads insgesamt 4,924,084
Installation
Installieren Sie das BitMiracle.Docotic.Pdf.Layout-Paket von NuGet. Dies ist die einfachste und bequemste Möglichkeit, das Layout-Add-on zu installieren.
Alternativ können Sie auf unserer Website die ZIP-Datei mit den Binärdateien der Bibliothek herunterladen. Um die Layout-API zu verwenden, fügen Sie Verweise auf die folgenden DLLs aus dem ZIP-Paket hinzu:
BitMiracle.Docotic.Pdf.dll
Layout add-on/BitMiracle.Docotic.Pdf.Layout.dll
Die Vorgehensweise
Der Einstiegspunkt ist die Klasse
PdfDocumentBuilder. Um mit der Generierung
einer PDF-Datei zu beginnen, rufen Sie die Methode
Generate der Klasse auf. Die Methode
erfordert einen Delegaten vom Typ Action
<Document> als
einen ihrer Parameter. Die Bibliothek erwartet von Ihnen, dass Sie Dokumentinhalte im Delegaten
gestalten.
PdfDocumentBuilder.Create().Generate("output.pdf", (Document doc) =>
{
// Erstellen Sie hier Dokumentinhalte
});
Bei einem Dokument
-Objekt sollte der Delegat das Layout definieren. Die komplette Anlage besteht
aus kleineren Bausteinen. Beispiele für solche Blöcke sind Seiten, Kopf- und Fußzeilen, Container
und Textblöcke.
Viele Methodenaufrufe sind miteinander verkettet. Die Reihenfolge der Aufrufe in einer Kette ist wichtig. Hier ist ein Beispiel, das zeigt, wie Seiteninhalte in einigen verketteten Aufrufen eingerichtet werden.
PdfDocumentBuilder.Create()
.Generate("output.pdf", doc => doc.Pages(pages =>
{
pages.Content().Padding(24).AlignCenter().Text("Some text");
}));
Intellisense hilft Ihnen bei der Entdeckung der API. Probieren Sie die API selbst aus. Ich hoffe, Sie finden es einfach zu bedienen.
Hallo Welt!
Lassen Sie uns eine einfache Anwendung entwickeln, die gängige Bausteine in Aktion zeigt. Die App verwendet den oben genannten Ansatz.
Ich habe den vollständigen Anwendungscode in unser
Docotic.Pdf-Beispielcode-Repository eingefügt. Der Code für diesen Schritt befindet sich in der
Klasse HelloWorld
der Beispiel-App.
public void CreatePdf()
{
PdfDocumentBuilder.Create().Generate("hello.pdf", doc => doc.Pages(page =>
{
page.Content().Text("Hello, world!");
}));
}
Nicht viel Code, aber was passiert hier?
Lange Erklärung für den Funktionscode
Der Code erstellt eine Instanz des Dokument-Builders und fordert den Builder auf, hello.pdf
zu
generieren. Der Builder delegiert die Aufgabe des Dokumentinhaltslayouts an meinen Code.
Im Code des Delegaten fordere ich das Dokument auf, einige Seiten zu erstellen. Jetzt delegiert das Dokument die Aufgabe, den Inhalt der Seiten an meinen Code zu verteilen.
Im Delegaten für die Seiten greife ich auf den Layout-Container für den primären Inhalt der Seiten zu. Ich mache das, indem ich die Methode Content aufrufe. Der verkettete Aufruf von Text fügt dem Inhalt der Seiten den berühmten Textbereich hinzu.
Jetzt ist es an der Zeit, dass der Builder das Dokument mit einigen Seiten entsprechend dem bereitgestellten Layout generiert. Der Builder erstellt genau die Anzahl an Seiten, die erforderlich ist, um die Daten aufzunehmen, die ich dem Layout-Container für den primären Inhalt hinzugefügt habe. Reicht in diesem Fall eine Seite? Okay.
Bereiten Sie sich auf zukünftige Updates vor
Ich werde dem Code noch einige weitere Funktionen hinzufügen. Um die Weiterentwicklung der App komfortabler zu gestalten, habe ich den Code wie folgt geändert:
public void CreatePdf()
{
PdfDocumentBuilder.Create().Generate("hello.pdf", BuildDocument);
}
static void BuildDocument(Document doc)
{
doc.Pages(BuildPages);
}
static void BuildPages(PageLayout pages)
{
pages.Content().Text("Hello, world!");
}
Es sieht vielleicht unnötig aus, aber die Aufteilung des Codes in Methoden macht ihn zumindest lesbarer.
Der Beispielcode für diesen Schritt befindet sich in der Klasse HelloWorld2
von der
Beispiel-App.
Verwandte Ressourcen
Weitere Informationen zu Dokumenten, Seiten und Containern finden Sie in den folgenden Artikeln.
Schriftarten und Farben
Die Standardschriftart ist gut, aber ich werde zeigen, wie man eine andere verwendet. Die Hauptidee besteht darin, mithilfe einer Schriftart einen Textstil zu erstellen. Wenden Sie dann bei Bedarf einige optionale Eigenschaften auf den Stil an und verwenden Sie den Stil schließlich für einen Textbereich.
Sie können eine Schriftart aus der im Betriebssystem installierten Schriftartensammlung verwenden oder eine Schriftart aus einer Datei oder einem Stream laden.
Ich empfehle, die vordefinierten Stile zu überschreiben, indem Sie Typografie für das Dokument einrichten. Dies ist jedoch nicht erforderlich und Sie können Textstile direkt verwenden.
Der Beispielcode für diesen Schritt befindet sich in der Klasse HelloWorld3
von der
Beispiel-App. Nachfolgend sind die Teile aufgeführt, die sich gegenüber dem
vorherigen Schritt geändert haben.
static void BuildDocument(Document doc)
{
doc.Typography(t =>
{
t.Document = doc.TextStyleWithFont(SystemFont.Family("Calibri"));
});
doc.Pages(BuildPages);
}
static void BuildPages(PageLayout pages)
{
pages.Size(PdfPaperSize.A6);
pages.Margin(10);
BuildTextContent(pages.Content());
}
static void BuildTextContent(LayoutContainer content)
{
var colorAccented = new PdfRgbColor(56, 194, 10);
var styleAccented = TextStyle.Parent.FontColor(colorAccented);
content.Text(t =>
{
t.Span("Hello, ").Style(styleAccented);
t.Span("world!").Style(styleAccented.Underline());
});
}
Wie Sie sehen können, habe ich den Code für BuildDocument
und BuildPages
aktualisiert. Ich habe
auch eine neue Methode namens BuildTextContent
hinzugefügt.
In BuildDocument
erstelle ich einen Textstil aus der Systemschriftart namens „Calibri“. Dann lege
ich diesen Textstil als Standardtextstil für das Dokument fest.
Die Methode BuildPages
enthält jetzt Code zum Festlegen von Größe und Rand für alle Seiten.
Außerdem ruft die Methode BuildTextContent
auf und übergibt den Container für den primären Inhalt
der Seiten als Parameter.
Die Art und Weise, wie ich den Hauptinhalt aufbaue, ist jetzt anders. Ich verwende zwei Textbereiche und wende auf jeden Bereich unterschiedliche Textstile an. Tatsächlich verwenden beide Bereiche die Akzentfarbe, aber der zweite Bereich verfügt auch über eine Unterstreichung.
Der Code erzeugt ein PDF mit der benutzerdefinierten Textschriftart und -farbe. Wenn Ihr Ergebnis eine Testwarnung enthält, holen Sie sich bitte eine kostenlose, zeitlich begrenzte Lizenz auf der Bibliotheksseite Docotic.Pdf.
Kopf-und Fußzeile
Viele reale PDF-Dokumente wie Berichte oder Rechnungen enthalten Kopf- und Fußzeilen. Lassen Sie mich zeigen, wie man einer PDF-Datei Kopf- und Fußzeilen hinzufügt.
Der Beispielcode für diesen Schritt befindet sich in der Klasse HelloWorld4
von der
Beispiel-App. Nachfolgend sind die Teile aufgeführt, die sich gegenüber dem
vorherigen Schritt geändert haben.
static void BuildPages(PageLayout pages)
{
pages.Size(PdfPaperSize.A6);
pages.Margin(10);
BuildPagesHeader(pages.Header());
BuildPagesFooter(pages.Footer());
BuildTextContent(pages.Content());
}
static void BuildPagesHeader(LayoutContainer header)
{
header.TextStyle(TextStyle.Parent.FontSize(8))
.AlignRight()
.Text(t =>
{
t.Line($"Created by: {Environment.UserName}");
t.Line($"Date: {DateTime.Now}");
});
}
static void BuildPagesFooter(LayoutContainer footer)
{
footer.Height(20)
.Background(new PdfGrayColor(95))
.AlignCenter()
.Text(t => t.CurrentPageNumber());
}
Ich habe die Methode BuildPages
so geändert, dass sie BuildPagesHeader
mit dem Header-Container
als Parameter aufruft. Die Methode ruft auch BuildPagesFooter
auf und übergibt ihr den
Fußzeilencontainer.
Das resultierende PDF mit Kopf- und Fußzeile sieht definitiv eher wie ein professionelles PDF-Dokument aus.
Die Methode BuildPagesHeader
legt eine kleinere Schriftgröße für den Text fest. Ich verwende zwei
Zeilen für den Header-Inhalt: eine mit dem Namen des aktuellen Benutzers und die zweite mit dem
aktuellen Datum. Der Text ist rechtsbündig.
Bitte beachten Sie, dass ich keine explizite Größe für den Header vorgebe. Es nimmt die gesamte Seitenbreite abzüglich des linken und rechten Rands ein. Die Höhe hängt von der Höhe der Textzeilen ab.
Die Fußzeile ist ähnlich, außer dass ihre Höhe explizit angegeben wird. Und es wird eine Hintergrundfarbe darauf angewendet. Das Interessante daran ist, dass ich zum Einfügen der aktuellen Seitenzahl in die PDF-Fußzeile einfach die CurrentPageNumber-Methode verwenden kann. Alle Berechnungen erfolgen innerhalb der Bibliothek.
Bilder
Wie man so schön sagt, kann man durch die Verwendung eines Bildes viele Wörter einsparen. In einem Angebot oder einer Quittung werden Sie wahrscheinlich ein Logo Ihres Unternehmens oder ein anderes wichtiges Bild verwenden. Für diesen Beispielcode verwende ich nur einen gut aussehenden Code.
Die Datei befindet sich auf unserer Website, damit Sie sehen können, wie das resultierende PDF mit dem schönen Bild aussieht.
Um ein Bild zu verwenden, müssen Sie es zunächst dem Dokument hinzufügen. Die Bibliothek kann das
Bild aus einer Datei oder einem Stream lesen. Ich habe die Methode BuildDocument
geändert, um zu
zeigen, wie man dem Dokument ein Bild hinzufügt.
Der Beispielcode für diesen Schritt befindet sich in der Klasse HelloWorld5
von der
Beispiel-App. Nachfolgend sind die Teile aufgeführt, die sich gegenüber dem
vorherigen Schritt geändert haben.
static void BuildDocument(Document doc)
{
doc.Typography(t =>
{
t.Document = doc.TextStyleWithFont(SystemFont.Family("Calibri"));
});
var imageFile = new FileInfo("red-flowers-at-butterfly-world.jpg");
var image = doc.Image(imageFile);
doc.Pages(pages => {
BuildPages(pages);
pages.Content().Column(c =>
{
BuildTextContent(c.Item());
BuildImageContent(c.Item(), image);
});
});
}
static void BuildPages(PageLayout pages)
{
pages.Size(PdfPaperSize.A6);
pages.Margin(10);
BuildPagesHeader(pages.Header());
BuildPagesFooter(pages.Footer());
}
static void BuildImageContent(LayoutContainer content, Image image)
{
content.AlignCenter()
.PaddingVertical(20)
.Image(image);
}
Wie Sie sehen können, gibt es weitere Änderungen in der Methode BuildDocument
. Zuvor verwendete
der Code die Methode Text, um Text als
primären Inhalt für Seiten festzulegen. Dies geschieht immer noch in der Methode
BuildTextContent
. Jetzt möchte ich aber auch ein Bild im Inhalt.
Um sowohl den Text als auch das Bild im Hauptinhalt der Seiten zu haben, benötige ich einen
Container. Ich verwende den Container Column, um den Text
und das Bild vertikal nacheinander hinzuzufügen. Die Methode
Item des Spaltencontainers stellt einen
Untercontainer bereit. Ich verwende einen Aufruf der Methode Item
, um einen Container für den
Text abzurufen, und einen weiteren Aufruf, um einen Container für das Bild abzurufen.
Wie Sie sehen, habe ich BuildTextContent
kein bisschen verändert. Aber natürlich musste ich einen
Aufruf von BuildTextContent
aus der Methode BuildPages
entfernen.
BuildImageContent
erledigt in drei Zeilen eine wichtige Aufgabe. Es fügt das Bild mit etwas
Polsterung oben und unten hinzu. Außerdem wird das Bild auf der Seite zentriert.
Weitere Informationen zum Container Column und zu den Bildern finden Sie in den folgenden Artikeln.
Listen
Was ist eine Liste? Stellen wir es uns als eine Gruppe nummerierter Elemente vor, die untereinander geschrieben sind. Diese Idee schlägt eine Möglichkeit vor, eine Liste zu implementieren.
Der Beispielcode für diesen Schritt befindet sich in der Klasse HelloWorld6
von der
Beispiel-App. Nachfolgend sind die Teile aufgeführt, die sich gegenüber dem
vorherigen Schritt geändert haben.
static void BuildDocument(Document doc)
{
....
doc.Pages(pages => {
BuildPages(pages);
pages.Content().Column(c =>
{
BuildTextContent(c.Item());
BuildImageContent(c.Item(), image);
BuildListContent(c.Item());
});
});
}
static void BuildListContent(LayoutContainer content)
{
var dayNames = DateTimeFormatInfo.InvariantInfo.DayNames;
var dayNamesSpain = DateTimeFormatInfo.GetInstance(new CultureInfo("es-ES")).DayNames;
content.Column(column =>
{
for (int i = 0; i < dayNames.Length; i++)
{
column.Item().Row(row =>
{
row.Spacing(5);
row.AutoItem().Text($"{i + 1}.");
row.RelativeItem().Text(t => {
t.Line(dayNames[i]);
t.Line($"In Spain they call it {dayNamesSpain[i]}");
});
});
}
});
}
Die einzige Änderung in BuildDocument
ist der neue Methodenaufruf. Ich habe den Aufruf von
BuildListContent
nach dem BuildImageContent
-Aufruf hinzugefügt.
BuildListContent
erstellt die Liste als Zeilenspalte. In jeder Zeile gibt es zwei Elemente. Die
erste (links) ist für die Artikelnummer. Eine weitere (rechte) ist für den Artikeltext. Der Code
legt explizit den Abstand zwischen den Elementen in der Zeile fest.
Um Elemente anzuordnen, muss der Container Row vorher die Größe jedes Elements kennen oder berechnen. In diesem Beispiel verwende ich die Methoden AutoItem und RelativeItem. Als Ergebnis berechnet der Zeilencontainer die Breite, die erforderlich ist, um das erste Element aufzunehmen. Dann nutzt der Container die verbleibende verfügbare Breite für das zweite Element.
Nach dem Hinzufügen der Liste passt der Inhalt der resultierenden PDF-Datei nicht mehr auf eine Seite. Die Layout-API fügt automatisch die zweite Seite hinzu und platziert die Liste darauf. Sie können sehen, dass die API die Kopf- und Fußzeile auf der neuen Seite im PDF-Dokument mit mehreren Seiten wiederholt hat.
Weitere Informationen zu Listen finden Sie im Artikel Verbundbehälter.
Tabellen
Viele PDF-Dokumente enthalten Tabellen. Dies ist keine Überraschung, da Tabellen die Klarheit und Organisation der Daten verbessern. Lassen Sie mich zeigen, wie Sie mit der Layout-API eine Tabelle im PDF-Format erstellen.
Der Beispielcode für diesen Schritt befindet sich in der Klasse HelloWorld7
von der
Beispiel-App. Nachfolgend sind die Teile aufgeführt, die sich gegenüber dem
vorherigen Schritt geändert haben.
static void BuildDocument(Document doc)
{
....
doc.Pages(pages => {
BuildPages(pages);
pages.Content().Column(c =>
{
BuildTextContent(c.Item());
BuildImageContent(c.Item(), image);
BuildListContent(c.Item());
BuildTableContent(c.Item());
});
});
}
static void BuildTableContent(LayoutContainer content)
{
var color = new PdfGrayColor(75);
content.PaddingTop(20).Table(t =>
{
t.Columns(c =>
{
c.RelativeColumn(4);
c.RelativeColumn(1);
c.RelativeColumn(4);
});
t.Header(h =>
{
h.Cell().Background(color).Text("Month in 2024");
h.Cell().Background(color).Text("Days");
h.Cell().Background(color).Text("First Day");
});
for (int i = 0; i < 12; i++)
{
var stats = GetMonthStats(2024, i);
t.Cell().Text(stats.Item1);
t.Cell().Text(stats.Item2);
t.Cell().Text(stats.Item3);
}
});
}
static (string, string, string) GetMonthStats(int year, int monthIndex)
{
return (
DateTimeFormatInfo.InvariantInfo.MonthNames[monthIndex],
DateTime.DaysInMonth(year, monthIndex + 1).ToString(),
new DateTime(year, monthIndex + 1, 1).DayOfWeek.ToString()
);
}
Der Aufruf von BuildTableContent
ist die einzige Änderung in BuildDocument
.
In BuildTableContent
erstelle ich eine einfache Tabelle. Die Tabelle zeigt triviale Informationen
über Monate im Jahr 2024. Zunächst definiere ich drei Spalten mit relativen Breiten. Die Spalten
ganz links und ganz rechts sind viermal breiter als die Spalte in der Mitte.
Der Code definiert auch den Header für die Tabelle. Dies geschieht durch das Hinzufügen von Kopfzellen und das Festlegen von Text und Hintergrundfarbe für jede Zelle. Wenn die Tabelle nicht auf eine Seite passt, wird die Kopfzeile auf jeder von der Tabelle belegten Seite wiederholt. Sie können dies im resultierenden PDF-Dokument mit Tabelle sehen. Im Dokument beginnt die Tabelle auf der zweiten Seite und wird auf der dritten Seite fortgesetzt.
Ich verwende die einfache Schleife, um Zeilen zu bilden. Der Code in der Schleife beginnt mit dem Abrufen der Informationen zu jedem Monat. Anschließend werden drei Zellen hinzugefügt, die eine Informationszeile bilden.
Im Artikel Table-Container werden alle Funktionen des Table
-Containers ausführlicher erläutert.
Beispielcode
Oben habe ich einige der beliebtesten Funktionen der PDF-Generierung in C# vorgestellt. Ich empfehle Ihnen, die API weiter zu entdecken, indem Sie den folgenden Artikel lesen. Probieren Sie auch den Beispielcode aus dem Docotic.Pdf.Samples-Repository auf GitHub aus. Der Beispielcode für die Layout-API befindet sich im Layout-Ordner des Repositorys.
Sie können den Beispielcode als Codespielplatz verwenden. Auf diese Weise können Sie einige Ideen ausprobieren, ohne jedes Mal bei Null anfangen zu müssen.
Der gleiche Beispielcode befindet sich im Ordner Samples
des ZIP-Pakets. Es gibt zwei
Lösungsdateien. SamplesCSharp
ist für Beispielprojekte gedacht, die die Sprache C# verwenden. Und
SamplesVB.NET
ist für die VB.NET-Versionen.