Эта страница может содержать автоматически переведенный текст.

Как верстать страницы PDF

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

Разметка страниц PDF

Одного вызова метода достаточно, если все страницы вашего PDF-документа имеют одинаковый макет. Если в вашем документе разные макеты, используйте более одного вызова метода Pages. Например, вы можете вызвать метод один раз, чтобы разметить титульную страницу. Затем снова вызвать метод, чтобы описать тело отчета.

Каждый вызов Pages создает как минимум одну страницу. Созданная страница может быть пустой, если для нее не предусмотрено никакого контента.

Эта статья - часть серии статей про Layout API для генерации PDF-файлов. Если вы новичок в работе с API, то сначала прочитайте часть Начало работы с Layout API.

Библиотека Docotic.Pdf 9.3.17105-dev Дополнение Layout 9.3.17105-dev
Регрессионные тесты 14,681 прошло Всего загрузок NuGet 4,234,061

Слоты контента

Для описания макета страниц используйте заранее определенные контейнеры. Я также называю их слотами контента. Вы можете получить доступ к этим контейнерам, вызвав методы объекта 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 Envelope.

При желании вы можете указать ориентацию страниц. Можно установить собственный размер страницы, указав ее ширину и высоту в пунктах.

Поля

Поля страницы могут способствовать удобочитаемости, эстетике и общей композиции ваших страниц.

Установите для всех полей одинаковое значение в пунктах, используя метод Margin. Используйте методы MarginVertical и MarginHorizontal, чтобы установить только вертикальные или горизонтальные поля. Используйте методы MarginLeft/Top/Right/Bottom, чтобы указать каждое поле независимо.

Стиль текста

API Layout предоставляет класс 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. Например, свойство 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-документы показано, как применить пользовательское форматирование к номерам страниц.

Примеры кода

У нас есть несколько тестовых приложений, которые более подробно описывают вышеупомянутые функции. Пожалуйста, потратьте некоторое время на то, чтобы заглянуть в их код.