Эта страница может содержать автоматически переведенный текст.
Как верстать PDF-страницы
Метод PdfDocumentBuilder.Generate предоставляет делегату объект типа Document. Используйте метод Pages этого объекта, чтобы создавать страницы документа. Методу нужно передать делегат, который принимает параметр типа PageLayout.

Одного вызова метода достаточно, если все страницы в PDF-документе имеют одинаковую разметку. Если в документе нужны разные разметки, используйте несколько вызовов метода Pages. Например, вы можете вызвать метод один раз, чтобы сверстать титульную страницу. Затем вызовите метод еще раз, чтобы описать основную часть отчета.
Каждый вызов Pages создает как минимум одну страницу. Созданная страница может быть пустой, если для нее не задано содержимое.
Эта статья входит в серию о Layout API для генерации PDF. Если вы еще не знакомы с API, сначала прочитайте раздел Начало работы с Layout API.
Слоты содержимого
Чтобы описать разметку страниц, используйте предопределенные контейнеры. Я также называю их слотами содержимого. Доступ к этим контейнерам можно получить, вызывая методы объекта PageLayout.
Есть три основных слота: Content, Header и Footer. И два слота для дополнительного содержимого: Background и Foreground. По умолчанию все пять контейнеров пусты и не занимают места на странице. Вы распределяете содержимое страницы между слотами в соответствии со своими требованиями.
Прочитайте статью Контейнеры и их содержимое, чтобы узнать, как верстать страницы с помощью контейнеров.
Верхний и нижний колонтитулы
Неудивительно, что содержимое верхнего и нижнего колонтитулов помещается в слоты Header и Footer соответственно. API повторяет эти слоты над и под основным содержимым на каждой сгенерированной странице. Layout API никогда не разбивает содержимое верхнего или нижнего колонтитула между страницами. Вы получите LayoutException, если верхний или нижний колонтитул не помещается на странице.
Основное содержимое
Основное содержимое страницы, например изображения, таблицы и текст, помещается в слот Content. Layout API автоматически разбивает это содержимое на страницы.
В следующем коде простой текст назначается всем основным слотам содержимого. Код также задает для слотов цвета фона.
PdfDocumentBuilder.Create().Generate("pages-main-slots.pdf", doc => doc.Pages(pages => {
pages.Header()
.Text("This text goes to the header")
.BackgroundColor(new PdfRgbColor(66, 135, 245));
pages.Content()
.Text("The main content goes in this slot")
.BackgroundColor(new PdfRgbColor(242, 233, 206));
pages.Footer()
.Text("This is the footer contents")
.BackgroundColor(new PdfRgbColor(194, 192, 188));
}));
Посмотрите результат кода в pages-main-slots.pdf.
Как видите, каждый слот занимает только часть страницы. Точная область зависит от содержимого внутри слота. Слот Header прижимается к верхней части страницы. Слот Content начинается сразу после Header. Слот Footer прижимается к нижней части.
Дополнительное содержимое
Background и Foreground предоставляют контейнеры, которые можно использовать для водяных знаков, наложений и фонов. Все содержимое в слоте Background располагается ниже верхнего колонтитула, нижнего колонтитула и основного содержимого страницы. Содержимое в слоте Foreground перекрывает все, что добавлено на страницу.
Эти контейнеры занимают всю страницу. Это их уникальная особенность. API повторяет их содержимое на каждой сгенерированной странице. Точно так же, как это делается для контейнеров верхнего и нижнего колонтитулов.
Я добавил несколько строк к коду выше, чтобы показать, как использовать контейнеры Foreground и Background.
PdfDocumentBuilder.Create().Generate("pages-all-slots.pdf", doc => doc.Pages(pages => {
// ...
pages.Background()
.Background(new PdfRgbColor(208, 227, 204));
pages.Foreground()
.Rotate(45)
.Text(new string(' ', 30) + "Your watermark could go here, in the foreground");
}));
Для контейнера Background я не задаю никакого текста или чего-либо еще. Я указываю только цвет фона. Все, что находится ниже верхнего колонтитула, основного содержимого и нижнего колонтитула, будет отображаться этим оттенком зеленого.
Я поворачиваю содержимое контейнера Foreground и добавляю в него текст. Из-за начальных пробелов текст не перекрывает содержимое верхнего или нижнего колонтитула. Содержимое всех контейнеров видно на странице.
Вы можете увидеть результат кода в pages-all-slots.pdf.
Настройки
До сих пор все фрагменты кода были сосредоточены на контейнерах, из которых состоят страницы. Пора посмотреть, как можно настраивать сами страницы, а не их слоты содержимого.
Чтобы настраивать страницы, используйте методы класса PageLayout. Помните, что объект PageLayout может описывать более одной страницы. Вызовы методов будут влиять на все описываемые вами страницы.
Размер
Пожалуй, самое базовое значение — размер страницы. Вы можете использовать метод Size, чтобы задать один из предопределенных размеров страниц. Доступны все привычные размеры, такие как A4, Ledger или конверт Monarch.
При необходимости можно задать ориентацию страниц. Также можно указать собственный размер страницы, передав ее ширину и высоту в пунктах.
Поля
Поля страницы могут повышать удобство чтения, эстетичность и общую композицию страниц.
Задайте все поля одним и тем же значением в пунктах с помощью метода Margin. Используйте методы MarginVertical и MarginHorizontal, чтобы задать только вертикальные или только горизонтальные поля. Используйте методы MarginLeft/Top/Right/Bottom, чтобы задавать каждое поле независимо.
Стиль текста
Layout API предоставляет класс TextStyle для создания стилей текста. Вы создаете стили и применяете их к тексту, чтобы добиться нужного внешнего вида.
Бывают случаи, когда большая часть текста на страницах использует один и тот же стиль. Вы можете задать этот стиль как стиль текста по умолчанию для страниц. Стиль по умолчанию влияет на весь текст в основных слотах содержимого. Но вы можете переопределять стиль по умолчанию для отдельных элементов. Просто примените другой стиль к фрагментам текста, которые должны выглядеть иначе.
PdfDocumentBuilder.Create().Generate("pages-text-styles.pdf", doc =>
{
var defaultStyle = TextStyle.Parent.FontSize(30);
var tightSpacing = TextStyle.Parent.LetterSpacing(-0.1);
doc.Pages(pages =>
{
pages.TextStyle(defaultStyle);
pages.Content().Text(t =>
{
t.Line("This line uses the default text style.");
t.Line("This line uses a tight letter spacing.").Style(tightSpacing);
t.Line("This line uses the default text style, again.");
});
});
});
Вы можете увидеть результат кода в pages-text-styles.pdf.
Обратите внимание, что можно задать стили текста для всего документа с помощью метода Document.Typography. Каждое свойство класса Typography определяет стиль для конкретного сценария использования. Эти стили переопределяют стиль, заданный методом PageLayout.TextStyle. Например, свойство Typography.Body переопределяет стиль по умолчанию для текста в контейнерах Content.
Направление содержимого
Есть языки, которые пишутся справа налево. Layout API отлично обрабатывает текст на таких языках. Но направление текста нужно задавать явно.
Если большая часть текста на страницах написана на языке с направлением справа налево, вы можете задать его как направление содержимого страниц по умолчанию. После этого можно будет указывать другое направление для любого контейнера на страницах.
PdfDocumentBuilder.Create().Generate("pages-content-direction.pdf", doc =>
{
var defaultTextStyle = doc.TextStyleWithFont(SystemFont.Family("Calibri"));
doc.Pages(pages =>
{
pages.Size(PdfPaperSize.A6).TextStyle(defaultTextStyle);
pages.ContentFromRightToLeft();
pages.Content().Column(column =>
{
column.Item()
.ContentFromLeftToRight()
.Text("There are languages written from right to left.");
column.Item()
.Text("هناك لغات تكتب من اليمين إلى اليسار.");
column.Item()
.Text("יש שפות שנכתבות מימין לשמאל.");
});
});
});
В приведенном выше коде я задаю направление содержимого справа налево по умолчанию. Для контейнера с английской версией фразы я меняю направление на слева направо. Вы можете увидеть результат кода в pages-content-direction.pdf.
Номера страниц
При генерации PDF Layout API автоматически вычисляет номер текущей страницы. Он также вычисляет общее число страниц в документе. Номера можно получить, вызывая методы CurrentPageNumber и PageCount любого текстового контейнера. Независимо от того, находится ли контейнер в верхнем колонтитуле, нижнем колонтитуле или в слоте основного содержимого.
PdfDocumentBuilder.Create().Generate("pages-page-numbers.pdf", doc => doc.Pages(pages =>
{
pages.Content().Text(t =>
{
t.Span("This line is on page ");
t.CurrentPageNumber();
t.Line();
t.Line("Check the footer.");
});
pages.Footer().Row(r =>
{
r.AutoItem().Text("Created with Docotic.Pdf Layout API");
r.RelativeItem(2).Text(t =>
{
t.AlignRight();
t.Span("Page ");
t.CurrentPageNumber();
t.Span(" of ");
t.PageCount();
});
});
}));
Результат кода находится в pages-page-numbers.pdf.
Оба метода возвращают экземпляр TextPageNumber, который можно использовать для форматирования номеров.
Добавление верхнего и нижнего колонтитула в PDF-документы показывает, как применить пользовательское форматирование к номерам страниц.
Примеры кода
У нас есть несколько примеров приложений, которые подробнее рассматривают упомянутые возможности. Пожалуйста, потратьте время и ознакомьтесь с ними.