이 페이지에는 자동 번역된 텍스트가 포함될 수 있습니다.

Table 컨테이너

가장 복잡한 데이터를 레이아웃하려면 Table 컨테이너를 사용하세요. 표는 PDF 문서에서 중요한 역할을 하며 명확성과 효율성을 향상시킵니다.

테이블은 데이터를 표시하기 위한 구조화된 형식을 제공합니다. 이를 통해 복잡한 세부 사항을 간결하고 시각적으로 매력적인 방식으로 표현할 수 있습니다. 긴 단락 대신 표를 사용하여 사실, 수치, 추세를 간결하게 표현할 수 있습니다.

잘 디자인된 표는 가독성을 높여줍니다. 열과 행을 정렬하여 독자의 시선을 안내하는 구조를 만듭니다. 배경, 테두리 및 글꼴 스타일을 사용하여 특정 셀이나 제목을 강조할 수 있습니다.

Table 컨테이너

LayoutContainer.Table 메서드를 호출하여 테이블 컨테이너를 가져옵니다. 그런 다음 컨테이너에 하나 이상의 열을 정의해야 합니다. 가장 간단한 경우에는 Cell 메서드를 여러 번 호출하여 모든 열과 행을 채울 수 있습니다.

열을 정의하고 표에 머리글 및/또는 바닥글을 추가하는 방법을 알아보려면 계속해서 읽어보세요. 이 텍스트에서는 Table 컨테이너의 다른 모든 기능도 설명합니다.

이 기사는 PDF 생성을 위한 Layout API 에 관한 시리즈의 일부입니다. API 를 처음 사용하는 경우 Layout API 시작하기 부분을 먼저 읽어보세요.

Docotic.Pdf 라이브러리 9.4.17467-dev 레이아웃 애드온 9.4.17467-dev
회귀 테스트 14,760건의 테스트 통과 총 NuGet 다운로드 4,415,970

열과 행

모든 테이블은 하나 이상의 열을 정의해야 합니다. 열을 정의하려면 Table.Columns 메서드를 사용하세요. 이 메서드는 Action<TableColumnContainer> 유형의 대리자를 허용합니다. 대리자 코드에서 제공된 개체의 메서드를 호출하여 테이블에 열을 추가합니다.

ConstantColumn 메서드는 정확한 포인트 수와 동일한 너비의 열을 추가합니다.

RelativeColumn 메서드는 상대 너비를 가진 열을 추가합니다. 이 메서드는 열이 차지해야 하는 부품 수를 허용합니다. 총 부품 수는 이 표의 모든 RelativeColumn 호출에 있는 모든 숫자의 합계입니다. 대부분 이 방법은 Row 컨테이너RelativeItem 과 동일하게 작동합니다. 자세한 설명은 링크를 읽어보시기 바랍니다.

행을 명시적으로 정의할 필요는 없습니다. 행 수는 열 및 셀 속성에 따라 달라집니다. 셀 수는 행 수에도 영향을 줄 수 있습니다. 테이블의 높이는 모든 행 높이의 합보다 클 수 있습니다. 행은 열 수보다 적은 수의 셀을 가질 수 있습니다. 그리고 열의 셀 수는 행 수보다 적을 수도 있습니다.

PdfDocumentBuilder.Create().Generate("table-basic.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.Size(300, 100);
        page.Content()
            .Padding(10)

            //.MinimalBox()

            .Border(b => b.Thickness(1).Color(new PdfRgbColor(250, 123, 5)))
            .Table(table =>
            {
                table.Columns(columns =>
                {
                    columns.ConstantColumn(100);
                    columns.RelativeColumn(1);
                    columns.RelativeColumn(3);
                });

                for (int i = 0; i < 10; i++)
                {
                    table.Cell()
                        .Border(b => b.Thickness(0.1))
                        .AlignCenter()
                        .Text($"Cell {i + 1}");
                }
            });
    });
});

table-basic.pdf 에서 코드 결과를 확인할 수 있습니다.

결과 PDF 에서 테이블은 상위 컨테이너 공간을 모두 차지합니다. 해당 영역을 덮을 셀이 충분하지 않은 경우에도 마찬가지입니다. 테이블 높이를 행 높이의 합으로 제한하려면 MinimalBox 호출의 주석 처리를 제거하세요.

코드는 세 개의 열을 정의하고 테이블에 10개의 셀을 추가합니다. 테이블은 셀을 차례로 배치하고 필요할 때 새 행을 추가합니다. 셀이 하나만 있는 행을 갖는 것은 전혀 문제가 되지 않습니다.

현재 페이지에 공간이 충분하지 않으면 테이블은 다음 페이지에 셀을 배치합니다. 추가된 셀 수를 늘려 이를 관찰할 수 있습니다.

세포

테이블 셀 작업을 위해 Layout API 가 제공하는 기능을 설명하겠습니다.

위치

테이블 셀을 생성하는 방법에는 두 가지가 있습니다:

  • 명시적인 위치 정보가 없는 경우
  • 적어도 부분적으로 지정된 위치

이전 섹션의 코드에서 첫 번째 방법을 사용했습니다. 매개변수를 허용하지 않는 Cell 메서드 오버로드를 호출합니다. 이 메서드는 마지막으로 추가된 셀 뒤의 열에 새 셀을 추가합니다. 오른쪽에 공백이 없으면 셀이 다음 행으로 이동합니다. RTL 모드에서 메서드는 마지막으로 추가된 셀 왼쪽에 공간이 있는지 확인합니다.

새 셀의 정확한 위치를 알고 있다면 Cell 메서드의 다른 오버로드를 사용하세요. Action<TableCell> 유형의 대리자를 허용하는 것입니다. 대리자 코드에서 제공된 개체의 RowIndexColumnIndex 메서드를 호출하여 셀 행과 인덱스를 지정합니다.

새 셀에는 행 또는 열 인덱스만 지정할 수 있습니다. 행 인덱스만 지정하는 경우 열 인덱스는 0입니다. 그 반대.

셀을 생성할 때 두 Cell 오버로드에 대한 호출을 순서에 관계없이 혼합할 수 있습니다.

이 기사의 다음 코드 예제에서는 다음 확장 메서드를 사용하겠습니다. 이렇게 하면 예제가 더 간결해지고 읽기 쉬워집니다.

static class LayoutHelpers
{
    public static TextSpan BoxWithText(this LayoutContainer cell, string caption)
        => cell.Border(b => b.Thickness(0.5))
            .Background(new PdfGrayColor(75))
            .ShowOnce()
            .MinWidth(50)
            .MinHeight(50)
            .Padding(10)
            .AlignCenter()
            .AlignMiddle()
            .Text(caption);
}

다음은 명시적으로 배치된 셀과 암시적으로 배치된 셀이 모두 포함된 테이블을 생성하는 예입니다. 셀에 스타일과 텍스트를 적용하기 위해 확장 방법을 사용했습니다. 셀 안의 숫자는 셀의 생성 순서를 반영합니다.

PdfDocumentBuilder.Create().Generate("table-cells.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.Size(300, 200);
        page.Content()
            .Padding(10)
            .MinimalBox()
            .Border(b => b.Thickness(0.1))
            .Table(table =>
            {
                table.Columns(columns =>
                {
                    for (int i = 0; i < 4; i++)
                        columns.RelativeColumn();
                });

                table.Cell().BoxWithText("1");
                table.Cell(c => c.RowIndex(1).ColumnIndex(1)).BoxWithText("2");
                table.Cell().BoxWithText("3");
                table.Cell(c => c.RowIndex(2).ColumnIndex(2)).BoxWithText("4");
                table.Cell(c => c.RowIndex(0).ColumnIndex(3)).BoxWithText("5");
            });
    });
});

table-cells.pdf 에서 코드 결과를 확인할 수 있습니다.

행 및 열 범위

셀은 여러 행 및/또는 여러 열에 걸쳐 있을 수 있습니다. 셀에 걸쳐 있는 행과 열의 수를 지정하려면 대리자를 허용하는 Cell 오버로드를 사용하세요.

PdfDocumentBuilder.Create().Generate("table-cellspans.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.Size(300, 150);
        page.Content()
            .Padding(10)
            .MinimalBox()
            .Border(b => b.Thickness(0.1))
            .Table(table =>
            {
                table.Columns(columns =>
                {
                    for (int i = 0; i < 4; i++)
                        columns.RelativeColumn();
                });

                table.Cell(c => c.RowSpan(2).ColumnSpan(2)).BoxWithText("1");
                table.Cell(c => c.ColumnSpan(2)).BoxWithText("2");
                table.Cell().BoxWithText("3");
                table.Cell().BoxWithText("4");
            });
    });
});

table-cellspans.pdf 에서 코드 결과를 확인할 수 있습니다.

겹치는

세포가 서로를 덮는 것이 가능합니다. 이런 일이 발생하면 생성 순서에 따라 어떤 셀이 다른 셀 위에 놓일지 정의됩니다.

셀이 두 개 이상의 열이나 행에 걸쳐 있으면 일부 겹치는 셀이 생길 수 있습니다. 또는 명시적으로나 암시적으로 셀 위치를 지정하는 경우도 있습니다.

PdfDocumentBuilder.Create().Generate("table-overlapping.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.Size(300, 300);
        page.Content()
            .Padding(10)
            .MinimalBox()
            .Border(b => b.Thickness(0.1))
            .Table(table =>
            {
                table.Columns(columns =>
                {
                    for (int i = 0; i < 4; i++)
                        columns.RelativeColumn();
                });

                for (int i = 0; i < 16; i++)
                    table.Cell().BoxWithText($"{i + 1}");

                table.Cell(c => c.RowIndex(2).ColumnIndex(1).ColumnSpan(3))
                    .Background(new PdfRgbColor(250, 123, 5), 50);
            });
    });
});

table-overlapping.pdf 에서 코드 결과를 확인할 수 있습니다.

아래쪽까지 연장

테이블 레이아웃이 복잡한 경우 페이징 메커니즘으로 인해 일부 열의 아래쪽에 공백이 생길 수 있습니다. 공백을 없애려면 ExtendCellsToBottom 메서드를 사용하세요. 이 메서드는 각 열의 마지막 셀을 확장하여 셀이 테이블 아래쪽에서 끝나도록 합니다.

다음 예에서 첫 번째 페이지는 기본 동작을 보여줍니다. 두 번째 페이지에서는 ExtendCellsToBottom 호출이 열에 어떤 영향을 미치는지 보여줍니다.

PdfDocumentBuilder.Create().Generate("table-extendcells.pdf", doc =>
{
    for (int take = 0; take < 2; take++)
    {
        doc.Pages(page =>
        {
            page.Size(300, 200);
            page.Content()
                .Padding(10)
                .MinimalBox()
                .Border(b => b.Thickness(0.1))
                .Table(table =>
                {
                    if (take != 0)
                        table.ExtendCellsToBottom();

                    table.Columns(columns =>
                    {
                        for (int i = 0; i < 4; i++)
                            columns.RelativeColumn();
                    });

                    table.Cell(c => c.RowIndex(0).ColumnIndex(0)).BoxWithText("1");
                    table.Cell(c => c.RowIndex(2).ColumnIndex(0)).BoxWithText("2");
                    table.Cell(c => c.RowIndex(1).ColumnIndex(1)).BoxWithText("3");
                    table.Cell(c => c.RowIndex(2).ColumnIndex(2)).BoxWithText("4");
                    table.Cell(c => c.RowIndex(1).ColumnIndex(3)).BoxWithText("5");
                });
        });
    }
});

table-extendcells.pdf 에서 코드 결과를 확인할 수 있습니다.

테이블에는 머리글과 바닥글이 있을 수 있습니다. HeaderFooter 메소드를 사용하여 해당 TableCellContainer 에 액세스하고 설정합니다. 컨테이너는 셀을 생성하는 Cell 메서드를 제공합니다. 이러한 방법은 기본 테이블 내용에 대한 방법과 정확히 동일하게 작동합니다.

머리글, 바닥글 및 기본 테이블 셀은 동일한 열 정의를 사용합니다. 그러나 세 개의 셀 컬렉션은 모두 독립적이며 서로 영향을 미치지 않습니다.

표가 한 페이지에 맞지 않으면 표가 차지하는 각 페이지에 머리글과 바닥글이 반복됩니다.

이전 예제에서는 BoxWithText 확장 메서드를 사용했습니다. 또한 다음 코드에는 WhiteBoxWithText 확장 메서드를 사용합니다.

static class LayoutHelpers
{
    public static TextSpan WhiteBoxWithText(
        this LayoutContainer cell, string caption, bool center = true)
    {
        return cell.Border(b => b.Thickness(0.5))
            .ShowOnce()
            .MinWidth(50)
            .MinHeight(50)
            .Padding(10)
            .Container(l => center ? l.AlignCenter() : l)
            .AlignMiddle()
            .Text(caption);
    }
}

다음 예에서는 헤더가 있는 테이블을 생성하는 방법을 보여줍니다. 나는 다섯 가지 필수 화학 원소가 포함된 표를 사용합니다. 각 원소의 이름과 녹는점은 섭씨와 켈빈도로 표시됩니다.

var elements = new (string Name, double Celsius, double Kelvin)[] {
    ("Oxygen", -218.79, 54.36),
    ("Carbon", double.NaN, double.NaN),
    ("Hydrogen", -259.16, 13.99),
    ("Nitrogen", -209.86, 63.23),
    ("Sulfur", 115.21, 388.36),
};

static string formatDouble(double val)
{
    return double.IsNaN(val)
        ? string.Empty
        : val.ToString(CultureInfo.InvariantCulture);
}

PdfDocumentBuilder.Create().Generate("table-header.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.Size(400, 500);
        page.Content()
            .Padding(10)
            .MinimalBox()
            .Border(b => b.Thickness(0.1))
            .Table(table =>
            {
                table.Columns(columns =>
                {
                    columns.RelativeColumn();
                    columns.ConstantColumn(100);
                    columns.ConstantColumn(100);
                });

                table.Header(header =>
                {
                    header.Cell(c => c.RowSpan(2)).BoxWithText("Chemical element");
                    header.Cell(c => c.ColumnSpan(2)).BoxWithText("Melting point");

                    header.Cell().BoxWithText("Celsius");
                    header.Cell().BoxWithText("Kelvin");
                });

                foreach (var (Name, Celsius, Kelvin) in elements)
                {
                    table.Cell().WhiteBoxWithText(Name, false);

                    table.Cell().WhiteBoxWithText(formatDouble(Celsius));
                    table.Cell().WhiteBoxWithText(formatDouble(Kelvin));
                }
            });
    });
});

table-header.pdf 에서 코드 결과를 확인할 수 있습니다.

샘플 코드

잠시 시간을 내어 PDF 문서에 표 추가 예시를 확인해 보세요. 또한 헤더가 있는 테이블을 생성하는 방법을 보여 주지만 확장 방법은 사용하지 않습니다. 그리고 VB.NET 버전도 있습니다.