项目

QuestPDF 页面

这个容器包含多个与页面相关的插槽。

主插槽

主插槽(HeaderContentFooter)可用于指定页面内容:

  • Header 元素始终位于每个页面的顶部。
  • Content 元素绘制在 HeaderFooter 之间的空间中。
  • Footer 元素始终位于每个页面的底部。
.Page(page =>
{
    page.MarginHorizontal(40);
    page.MarginVertical(60);

    page.Header()
        .Height(60)
        .Background(Colors.Grey.Lighten1)
        .AlignCenter()
        .AlignMiddle()
        .Text("Header");

    page.Content()
        .Background(Colors.Grey.Lighten2)
        .AlignCenter()
        .AlignMiddle()
        .Text("Content");

    page.Footer()
        .Height(30)
        .Background(Colors.Grey.Lighten1)
        .AlignCenter()
        .AlignMiddle()
        .Text("Footer");
});
请注意!当头部和底部元素的高度之和大于页面总高度时,没有足够的空间容纳内容,此时会抛出布局异常。

示例

水印插槽

水印插槽(背景和前景)可用于分别在主要内容背后或前方添加内容。

.Page(page =>
{
    page.Size(PageSizes.A4);
    page.Margin(1, Unit.Inch);
    page.DefaultTextStyle(TextStyle.Default.FontSize(16));
    page.PageColor(Colors.White);

    const string transparentBlue = "#662196f3";

    page.Background()
        .AlignTop()
        .ExtendHorizontal()
        .Height(200)
        .Background(transparentBlue);

    page.Foreground()
        .AlignBottom()
        .ExtendHorizontal()
        .Height(250)
        .Background(transparentBlue);

    page.Header()
        .Text("Background and foreground")
        .Bold().FontColor(Colors.Blue.Darken2).FontSize(36);

    page.Content().PaddingVertical(25).Column(column =>
    {
        column.Spacing(25);

        foreach (var i in Enumerable.Range(0, 100))
            column.Item().Background(Colors.Grey.Lighten2).Height(75);
    });
});

示例

考虑一个更复杂的例子,它在实际内容旁边添加额外的视觉元素。这可以通过水印插槽轻松实现:

document.Page(page =>
{
    const float horizontalMargin = 1.5f;
    const float verticalMargin = 1f;

    page.Size(PageSizes.A4);
    page.MarginVertical(verticalMargin, Unit.Inch);
    page.MarginHorizontal(horizontalMargin, Unit.Inch);

    page.Background()
        .PaddingVertical(verticalMargin, Unit.Inch)
        .RotateRight()
        .Decoration(decoration =>
        {
            decoration.Before().RotateRight().RotateRight().Element(DrawSide);
            decoration.Content().Extend();
            decoration.After().Element(DrawSide);

            void DrawSide(IContainer container)
            {
                container
                    .Height(horizontalMargin, Unit.Inch)
                    .AlignMiddle()
                    .Row(row =>
                    {
                        row.AutoItem().PaddingRight(16).Text("COMPANY NAME").FontSize(16).FontColor(Colors.Red.Medium);
                        row.RelativeItem().PaddingTop(12).ExtendHorizontal().LineHorizontal(2).LineColor(Colors.Red.Medium);
                    });
            }
        });

    page.Content().Column(column =>
    {
        column.Spacing(25);

        foreach (var i in Enumerable.Range(1, 100))
            column.Item().Background(Colors.Grey.Lighten2).Height(75).AlignCenter().AlignMiddle().Text(i.ToString()).FontSize(16);
    });
});

这将产生以下结果:

示例

页面设置

可以创建一个文档,其中包含具有不同设置的页面。例如,以下代码插入一张 A4 页面,然后是一张 A3 页面,两者具有不同的边距:

public class StandardReport : IDocument
{
    // 元数据

    public void Compose(IDocumentContainer container)
    {
        container
            .Page(page =>
            {
                page.MarginVertical(80);
                page.MarginHorizontal(100);
                page.PageColor(Colors.Grey.Medium); // 透明是默认值
                page.Size(PageSizes.A3);

                page.Header().Element(ComposeHeader);
                page.Content().Element(ComposeBigContent);
                page.Footer().AlignCenter().PageNumber();
            })
            .Page(page =>
            {
                // 您可以在文档中指定多个页面类型,具有独立配置
                page.Margin(50)
                page.Size(PageSizes.A4);

                page.Header().Element(ComposeHeader);
                page.Content().Element(ComposeSmallContent);
                page.Footer().AlignCenter().PageNumber();
            });
    }

    // 内容实现
}

您很容易更改页面方向,如下所示:

// 默认为纵向
page.Size(PageSizes.A3);

// 显式纵向方向
page.Size(PageSizes.A3.Portrait());

// 改为横向方向
page.Size(PageSizes.A3.Landscape());

连续页面大小

可以定义具有已知宽度但动态高度的页面大小。在下面的示例中,生成的页面具有恒定宽度(等于 A4 页面的宽度,但其高度取决于内容:

public class StandardReport : IDocument
{
    // 元数据

    public void Compose(IDocumentContainer container)
    {
        container
            .Page(page =>
            {
                page.MarginVertical(40);
                page.MarginHorizontal(60);

                page.ContinuousSize(PageSizes.A4.Width);

                page.Header().Element(ComposeHeader);
                page.Content().Element(ComposeContent);
                page.Footer().AlignCenter().PageNumber();
            });
    }

    // 内容实现
}
由于实际布局限制,最大页面高度限制为 14400 点(约 5 米)。

全局文本样式

QuestPDF 库提供了一组默认样式,用于应用于文本。

.Text("使用库默认样式的文本")

您可以通过提供附加参数来调整文本样式:

.Text("红色粗体大小为 20 的文本").FontSize(20).SemiBold()

上述选项覆盖了默认样式。为了获得更多控制,您可以在文档中设置默认文本样式。请注意,所有更改都是累积的,如以下示例所示:

public class SampleReport : IDocument
{
    public DocumentMetadata GetMetadata() => new DocumentMetadata();

    public void Compose(IDocumentContainer container)
    {
        container.Page(page =>
        {
            // 在这一系列页面中,所有文本的大小为 20
            page.DefaultTextStyle(TextStyle.Default.FontSize(20));

            page.Margin(20);
            page.Size(PageSizes.A4);
            page.PageColor(Colors.White);

            page.Content().Column(column =>
            {
                column.Item().Text(Placeholders.Sentence());

                column.Item().Text(text =>
                {
                    // 文本块内的文本此外还加粗
                    text.DefaultTextStyle(x => x.SemiBold());

                    text.Line(Placeholders.Sentence());

                    // 此文本的大小为 20,但也有粗体和红色
                    text.Span(Placeholders.Sentence()).FontColor(Colors.Red.Medium);
                });
            });
        });
    }
}

示例

全局内容方向(从右到左)

可以全局指定整个文档的内容方向。

提示: 要了解更多关于内容方向的工作原理,请阅读有关ContentDirection元素的文档。

document.Page(page =>
{
    // 默认设置
    page.ContentFromLeftToRight();

    // 可选的从右到左模式
    page.ContentFromRightToLeft();
});

进一步的示例如下:

document.Page(page =>
{
    page.Size(PageSizes.A5);
    page.Margin(20);
    page.PageColor(Colors.White);
    
    page.DefaultTextStyle(x => x.FontFamily("Calibri").FontSize(20));
    page.ContentFromRightToLeft();
    
    page.Content().Column(column =>
    {
        column.Spacing(20);

        column.Item()
            .Text("مثال على الفاتورة") // example invoice
            .FontSize(32).FontColor(Colors.Blue.Darken2).SemiBold();
        
        column.Item().Table(table =>
        {
            table.ColumnsDefinition(columns =>
            {
                columns.RelativeColumn();
                columns.ConstantColumn(75);
                columns.ConstantColumn(100);
            });

            table.Cell().Element(HeaderStyle).Text("وصف السلعة"); // item description
            table.Cell().Element(HeaderStyle).Text("كمية"); // quantity
            table.Cell().Element(HeaderStyle).Text("سعر"); // price

            var items = new[]
            {
                "دورة البرمجة", // programming course
                "دورة تصميم الرسومات", // graphics design course
                "تحليل وتصميم الخوارزميات", // analysis and design of algorithms
            };
            
            foreach (var item in items)
            {
                var price = Placeholders.Random.NextDouble() * 100;
                                    
                table.Cell().Text(item);
                table.Cell().Text(Placeholders.Random.Next(1, 10));
                table.Cell().Text($"USD${price:F2}");
            }

            static IContainer HeaderStyle(IContainer x) => x.BorderBottom(1).PaddingVertical(5);
        });
    });
});

在本文档中