PDFSharp i MigraDoc
Pierwsza publikacja tekstu: 6. września 2010 r.
Empira Software oferuje darmowe biblioteki służące do generowania plików PDF przez aplikacje korzystające z .NET framework. Pierwsza z nich, PDFsharp pozwala na niskopoziomowe tworzenie dokumentów, umożliwiając programiście kontrolę nad każdym rysowanym pikselem – podobnie jak ma to miejsce w przypadku interfejsu GDI+. MigraDoc operuje natomiast na wyższym poziomie abstrakcji, udostępniając klasy reprezentujące typowe elementy dokumentów znane z edytorów tekstu, m.in. akapity, tabele, wykresy, rozdziały itp. Biblioteka pozwala także generować dokumenty w formacie RTF oraz XPS; możliwe jest też wstawianie niskopoziomowych elementów PDFsharp-a do plików PDF tworzonych przez MigraDoc.
Przykładowy dokument z wykorzystaniem PDFSharp
Poniższy przykład demonstruje:
- ustawienie informacji o dokumencie i opcji zabezpieczeń,
- tworzenie czcionek i rysowanie tekstu,
- tworzenie prostych obiektów graficznych,
- dodawanie adnotacji i zakładek,
- tworzenie i zapisywanie dokumentu.
using System;
using System.Diagnostics;
using System.Drawing;
using PdfSharp;
using PdfSharp.Drawing;
using PdfSharp.Drawing.Layout;
using PdfSharp.Pdf;
using PdfSharp.Pdf.Security;
using PdfSharp.Pdf.Annotations;
namespace PDFExamples
{
class Example1
{
public static void Main (string[] args)
{
/* Nazwa wynikowego pliku PDF */
string filename = "example1.pdf";
/* Utworzenie obiektu reprezentującego dokument PDF */
PdfDocument document = new PdfDocument();
/* Ustawianie informacji o dokumencie */
PdfDocumentInformation docInfo = document.Info;
docInfo.Author = "domas.pl"; // autor
docInfo.Title = "Przykładowy dokument PDFSharp"; // tytuł
/* Ustawianie opcji zabezpieczeń dokumentu */
PdfSecuritySettings security = document.SecuritySettings;
security.UserPassword = "user"; // hasło użytkownika
security.OwnerPassword = "owner"; // hasło właściciela
security.PermitModifyDocument = false; // zabraniamy modyfikacji
security.PermitPrint = false; // zabraniamy drukowania
security.PermitFullQualityPrint = false; // zabraniamy drukowania w pełnej jakości, łączy się z PermitPrint
/* Dodanie strony do dokumentu */
PdfPage page = document.AddPage();
/* Utworzenie głównej zakładki dokumentu, pogrubionym tekstem w kolorze czerwonym */
PdfOutline outline = document.Outlines.Add("Dokument", page, true, PdfOutlineStyle.Bold, XColors.Red);
/* Pobranie kontekstu obszaru malowania strony */
XGraphics gfx = XGraphics.FromPdfPage(page);
/* Ustawianie opcje czcionek - kodowanie unicode oraz zagnieżdżanie czcionek stosowane zawsze - pozwala uniknąć problemów m.in. z polskimi ogonkami */
XPdfFontOptions fontOptions = new XPdfFontOptions(PdfFontEncoding.Unicode, PdfFontEmbedding.Always);
/* Utworzenie pogrubionej czcionki typu times o rozmiarze 20pt */
XFont fontTimes = new XFont("Times New Roman", 20.0f, XFontStyle.Bold, fontOptions);
/* Utworzenie obiektu formatera który będzie rysował tekst */
XTextFormatter textFormatter = new XTextFormatter(gfx);
/* Rysowanie czarnego tekstu czcionką times w określonym obszarze kreślenia (obiekt XRect) */
textFormatter.DrawString("Zażółć gęślą jaźń", fontTimes, XBrushes.Black,
new XRect(64.0f, 64.0f, page.Width, page.Height), XStringFormat.TopLeft);
XFont fontTahoma = new XFont("Tahoma", 36.0f, XFontStyle.Italic, fontOptions);
textFormatter.DrawString("W Szczebrzeszynie chrząszcz brzmi w trzcinie", fontTahoma, XBrushes.Red,
new XRect(60.0f, 128.0f, page.Width - 128.0f, page.Height),
XStringFormat.TopLeft);
/* Dodanie kolejnej strony do dokumentu */
PdfPage page2 = document.AddPage();
/* Dodanie podzakładki z odnośnikiem do drugiej strony - tekst kursywą w kolorze granatowym */
outline.Outlines.Add("Druga strona", page2, true, PdfOutlineStyle.Italic, XColors.Navy);
XGraphics gfx2 = XGraphics.FromPdfPage(page2);
XTextFormatter textFormatter2 = new XTextFormatter(gfx2);
XFont fontCourier = new XFont("Courier", 12.0f, XFontStyle.Regular);
/* Zdefiniowanie obszaru prostokątnego w którym będzie rysowany tekst; parametry to kolejno pozycje X i Y, szerokość i wysokość */
XRect textRect = new XRect(32.0f, 32.0f, page.Width / 2.0f - 32.0f, page.Height - 64.0f);
/* Wypełnienie podanego obszaru błękitnym tłem z ciemnoniebieską ramką */
gfx2.DrawRectangle(XPens.MidnightBlue, XBrushes.LightBlue, textRect);
/* Wstawienie do niego tekstu */
textFormatter2.DrawString(LoremIpsum.Generate(4), fontCourier, XBrushes.Blue,
textRect, XStringFormat.TopLeft);
/* Przykładowy element graficzny - "wykres kołowy" */
gfx2.DrawPie(XPens.Black, XBrushes.Yellow, new Rectangle(340, 56, 200, 200), 30.0f, 310.0f);
/* Adnotacja tekstowa */
PdfTextAnnotation textAnnotation = new PdfTextAnnotation();
textAnnotation.Title = "Komentarz do wykresu"; // tytuł
textAnnotation.Subject = "Wykres"; // temat
textAnnotation.Contents = "Pacman?"; // treść adnotacji
textAnnotation.Icon = PdfTextAnnotationIcon.Note; // typ ikony widocznej na stronie
textAnnotation.Color = XColors.LightYellow; // kolor pola adnotacji
textAnnotation.Opacity = 0.75f; // przeźroczystość
textAnnotation.Open = true; // adnotacja jest otwarta po otworzeniu dokumentu
/* Położenie i rozmiar okna adnotacji - konieczne jest odwzorowanie prostokąta z przestrzeni świata na przestrzeń strony; adnotacja jest umieszczana względem jej dolnego lewego rogu */
XRect annotationRect = gfx2.Transformer.WorldToDefaultPage(new XRect(new XPoint(340, 260), new XSize(30, 30)));
textAnnotation.Rectangle = new PdfRectangle(annotationRect);
/* Dodanie adnotacji do strony */
page2.Annotations.Add(textAnnotation);
/* Zapis dokumentu do pliku o podanej wcześniej nazwie */
document.Save(filename);
/* Otwarcie dokumentu w domyślnej przeglądarce */
Process.Start(filename);
}
}
}
Klasa LoremIpsum służy do generowania tekstu wypełniającego dokument:
using System;
using System.Text;
namespace PDFExamples
{
public class LoremIpsum
{
/* Funkcja zwraca ciąg znaków zawierający tekst "Lorem ipsum..." powielony zadaną ilość razy (http://pl.lipsum.com) */
public static string Generate(int count)
{
string text = "Lorem ipsum dolor sit amet, consectetur adipisicing " +
"elit, sed do eiusmod tempor incididunt ut labore et dolore magna " +
"aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " +
"laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure " +
"dolor in reprehenderit in voluptate velit esse cillum dolore eu " +
"fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " +
"proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; i++)
{
if (i != 0)
{
sb.Append("\n");
}
sb.Append(text);
}
return sb.ToString();
}
}
}
Biblioteka pozwala nie tylko na tworzenie dokumentów, ale też ich edycję: łączenie, dzielenie, zabezpieczanie, wyciąganie obrazów. Przykłady takich zastosowań można znaleźć na stronie projektu.
Przykładowy dokument z zastosowaniem MigraDoc
Przykład demonstruje:
- utworzenie i zapis dokumentu w formacie PDF,
- dodawanie nowych sekcji,
- ustawianie stylów dokumentu,
- dodawanie akapitów i zakładek,
- tworzenie i formatowanie tabeli,
- ustawianie zawartości stopki,
- wstawianie wykresów i obrazów.
using System;
using System.Diagnostics;
using System.Text;
using PdfSharp.Pdf;
using MigraDoc.DocumentObjectModel;
using MigraDoc.Rendering;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.DocumentObjectModel.Shapes.Charts;
using MigraDoc.DocumentObjectModel.Shapes;
namespace PDFExamples
{
class Example2
{
public static void Main(string[] args)
{
/* Nazwa wynikowego pliku PDF */
string filename = "example2.pdf";
/* Utworzenie nowego dokumentu */
Document document = new Document();
/* Dodanie nowej sekcji */
Section section = document.AddSection();
/* Ustawienie stylu domyślnego */
Style style = document.Styles[StyleNames.Normal];
style.Font.Name = "Times New Roman"; // nazwa czcionki
style.ParagraphFormat.SpaceAfter = new Unit(0.75f, UnitType.Centimeter); // wolne miejsce po akapicie
/* Ustawienie stylu tytułu poziomu pierwszego */
style = document.Styles[StyleNames.Heading1];
style.Font.Size = 24; // rozmiar czcionki
/* Dodanie akapitu z tytułem do utworzonej sekcji */
Paragraph paragraph = section.AddParagraph("Zażółć gęślą jaźń");
paragraph.Style = StyleNames.Heading1; // styl akapitu
paragraph.Format.Borders.Bottom.Color = Colors.Black; // czarna linia podkreślająca tekst na szerokość strony
/* Dodanie akapitu z tekstem */
paragraph = section.AddParagraph(LoremIpsum.Generate(1)); // normalna czcionka
paragraph.Format.Alignment = ParagraphAlignment.Justify; // wyjustowanie tekstu
paragraph.AddFormattedText(" " + LoremIpsum.Generate(1), TextFormat.Italic); // tekst kursywą
paragraph.AddFormattedText(" " + LoremIpsum.Generate(1), TextFormat.Bold | TextFormat.Italic); // tekst pogrubioną kursywą
/* Dodanie tekstu w ramce z kolorowym tłem */
paragraph = section.AddParagraph(LoremIpsum.Generate(1));
paragraph.Format.Shading.Color = Colors.LightBlue; // kolor wypełnienia
paragraph.Format.Borders.Width = 0.5f; // grubość obramowania
/* Utworzenie tabeli */
MigraDoc.DocumentObjectModel.Tables.Table table = section.AddTable();
table.Borders.Width = 0.75f; // grubość obramowania
table.Format.Font.Color = Colors.White; // kolor czcionki
/* Dodawanie kolumn do tabeli */
Column column = table.AddColumn(Unit.FromCentimeter(5.0f));
column.Format.Alignment = ParagraphAlignment.Right; // położenie tekstu
column.Shading.Color = Colors.Red; // kolor wypełnienia komórek kolumny
column = table.AddColumn(Unit.FromInch(2.0f));
column.Format.Alignment = ParagraphAlignment.Center;
column.Shading.Color = Colors.Green;
column = table.AddColumn(Unit.FromMillimeter(50.0f));
column.Format.Alignment = ParagraphAlignment.Left;
column.Shading.Color = Colors.Blue;
table.Rows.Height = 75.0f; // wysokość wierszy
/* Dodawanie wierszy do tabeli */
Row row = table.AddRow();
row.VerticalAlignment = VerticalAlignment.Top;
row.Cells[0].AddParagraph("red");
row.Cells[1].AddParagraph("green");
row.Cells[2].AddParagraph("blue");
row = table.AddRow();
row.VerticalAlignment = VerticalAlignment.Center;
row.Cells[0].AddParagraph("1");
row.Cells[0].MergeRight = 1; // komórka łączy się z jedną sąsiadującą komórką po prawej stronie
row.Cells[0].MergeDown = 1; // komórka z sąsiednią komórką po prawej stronie łączy się z analogicznymi komórkami w dolnym wierszu
row.Cells[1].AddParagraph("2");
row.Cells[2].AddParagraph("3");
row = table.AddRow();
row.VerticalAlignment = VerticalAlignment.Bottom;
row.Cells[0].AddParagraph("4");
row.Cells[1].AddParagraph("5");
row.Cells[2].AddParagraph("6");
/* Utworzenie stopki */
HeaderFooter footer = section.Footers.Primary;
paragraph = footer.AddParagraph("Wygenerowano ");
paragraph.AddDateField(); // dodanie pola daty i czasu
/* Utworzenie nowej sekcji dokumentu */
section = document.AddSection();
/* Tytuł nowej sekcji */
paragraph = section.AddParagraph("Wykres", "Heading1"); // tekst i jego styl
paragraph.AddBookmark("Wykres"); // nowa zakładka dokumentu
/* Utworzenie wykresu */
Chart chart = section.AddChart();
chart.Width = Unit.FromCentimeter(12.0f); // szerokość
chart.Height = Unit.FromInch(2.5f); // wysokość
/* Ustalenie pionowych serii danych */
Series series = chart.SeriesCollection.AddSeries();
series.Add(new double[] {1, 2, 7, 5, 13, 10}); // wartości
series.ChartType = ChartType.Column2D; // rodzaj wykresu
series.HasDataLabel = true; // rysuje etykiety
/* Ustalenie poziomych serii danych */
XSeries xseries = chart.XValues.AddXSeries();
for (int i=1; i<7; i++)
xseries.Add(i.ToString());
chart.XAxis.Title.Caption = "Miesiąc"; // etykieta
chart.XAxis.HasMajorGridlines = true; // rysuje poziome linie wykresu
chart.YAxis.MajorTickMark = TickMarkType.Cross; // znacznik po obu stronach lewej krawędzi wykresu
chart.YAxis.Title.Caption = "Sprzedaż";
chart.YAxis.HasMajorGridlines = true; // rysuje pionowe linie wykresu
paragraph = section.AddParagraph("Obrazek", "Heading1");
/* Utworzenie obrazka z pliku */
Image image = section.AddImage("pdfsharp.png");
image.Width = "8cm"; // szerokość
/* Utworzenie obiektu renderującego PDF */
PdfDocumentRenderer pdfDocRenderer = new PdfDocumentRenderer(true, PdfFontEmbedding.Always); // obsługa unicode, zagnieżdżanie czcionek zawsze
pdfDocRenderer.Document = document; // przypisanie dokumentu
pdfDocRenderer.RenderDocument(); // renderowanie
pdfDocRenderer.PdfDocument.Save(filename); // zapis
/* Otwarcie dokumentu w domyślnej przeglądarce */
Process.Start(filename);
}
}
}
Więcej przykładów do obejrzenia na stronie projektu.