2 column layout over multiple pages

I have been trying multiple ways (In Apose.PDF for .Net 19.9.0) to get a 2 column layout (left being the header/section, and right being the content) over multiple pages in c#. However, each method I have tried is causing some issue.

1. Tables
This looked to be working fine until I realised that text was being intermittently cut off, even though rows were allowed to break across pages. There is a lot of content for each header/section and every method of using a table for the layout for large character counts has resulted in intermittent trimming of content text. Example below:

Aspose.Pdf.Table table = new Aspose.Pdf.Table();

table.Margin.Top = 10;
table.DefaultColumnWidth = ((PageWidth / 4) - 30).ToString();
table.DefaultCellPadding = new MarginInfo();
table.DefaultCellPadding.Left = 0;
table.DefaultCellPadding.Right = 0;
table.DefaultCellPadding.Top = 5;
table.DefaultCellPadding.Bottom = 5;
table.DefaultCellTextState.LineSpacing = 2;
table.DefaultCellTextState.FontSize = 11;

Aspose.Pdf.Row row = table.Rows.Add();
row.DefaultCellPadding = new MarginInfo();
row.DefaultCellPadding.Bottom = 12;

Aspose.Pdf.Cell cellHeader = row.Cells.Add("**Header/Section**");
cellHeader.VerticalAlignment = VerticalAlignment.Top;
cellHeader.Alignment = HorizontalAlignment.Left;
cellHeader.DefaultCellTextState.FontStyle = Aspose.Pdf.Text.FontStyles.Bold;

Aspose.Pdf.Cell cellContent = row.Cells.Add(**Content**);
cellContent.VerticalAlignment = VerticalAlignment.Top;
cellContent.Alignment = HorizontalAlignment.Left;
cellContent.ColSpan = 3;

foreach (Aspose.Pdf.Row row in table.Rows)
{
      row.IsRowBroken = true;
}

2. Floating text boxes
I tried using the following code, however - when the content went onto the next page, it displayed in the left column, rather than staying in the right column, even though I utilised FloatingBox.IsNeedRepeating = true and TextFragment.IsFirstParagraphInColumn = true:

Aspose.Pdf.FloatingBox box = new Aspose.Pdf.FloatingBox();

box.ColumnInfo.ColumnCount = 2;
box.ColumnInfo.ColumnSpacing = "5";
box.ColumnInfo.ColumnWidths = "110 350";

 page.Paragraphs.Add(box);

TextFragment text1 = new TextFragment("**Header/Section**");
text1.TextState.FontStyle = FontStyles.Bold;
box.Paragraphs.Add(text1);

TextFragment text2 = new TextFragment(**Content**);
text2.IsFirstParagraphInColumn = true;
box.Paragraphs.Add(text2);
box.IsNeedRepeating = true;

Can anyone help?

Thanks

Dan

@dandev

To create a two-column layout in Aspose.PDF for .NET where the left column contains headers/sections and the right column contains content, you can use tables effectively. However, it seems you are facing issues with text being cut off and content not aligning correctly across pages. Here are some suggestions to help you achieve the desired layout:

Using Tables

  1. Ensure Proper Row Height: Set a fixed row height for your table rows to prevent content from being cut off. You can also allow rows to break across pages by setting row.IsRowBroken = true; for each row.

  2. Column Widths: Define the column widths explicitly to ensure that the content fits well within the designated space. For example, you can set the widths to a ratio that suits your layout.

  3. Example Code:
    Here’s an example of how to set up a table for a two-column layout:

    Aspose.Pdf.Document doc = new Aspose.Pdf.Document();
    Aspose.Pdf.Page page = doc.Pages.Add();
    Aspose.Pdf.Table table = new Aspose.Pdf.Table();
    
    // Set column widths
    table.ColumnWidths = "150 400"; // Adjust widths as needed
    
    // Add rows and cells
    for (int i = 0; i < numberOfSections; i++)
    {
        Aspose.Pdf.Row row = table.Rows.Add();
        row.IsRowBroken = true; // Allow row to break across pages
    
        // Header/Section
        Aspose.Pdf.Cell cellHeader = row.Cells.Add("Header/Section " + (i + 1));
        cellHeader.VerticalAlignment = VerticalAlignment.Top;
        cellHeader.Alignment = HorizontalAlignment.Left;
    
        // Content
        Aspose.Pdf.Cell cellContent = row.Cells.Add("Content for section " + (i + 1));
        cellContent.VerticalAlignment = VerticalAlignment.Top;
        cellContent.Alignment = HorizontalAlignment.Left;
    }
    
    page.Paragraphs.Add(table);
    doc.Save("TwoColumnLayout.pdf");
    

Using Floating Boxes

If you prefer using floating boxes, ensure that the content is correctly aligned in the right column. You can set the IsNeedRepeating property to true for the header to ensure it appears on each page.

  1. Example Code:
    Here’s how you can set up a floating box:

    Aspose.Pdf.FloatingBox box = new Aspose.Pdf.FloatingBox();
    box.ColumnInfo.ColumnCount = 2;
    box.ColumnInfo.ColumnWidths = "150 400"; // Adjust widths as needed
    box.ColumnInfo.ColumnSpacing = "5";
    
    page.Paragraphs.Add(box);
    
    // Header/Section
    TextFragment header = new TextFragment("Header/Section");
    header.TextState.FontStyle = FontStyles.Bold;
    box.Paragraphs.Add(header);
    
    // Content
    TextFragment content = new TextFragment("Content goes here...");
    content.IsFirstParagraphInColumn = true; // Ensure it starts in the right column
    box.Paragraphs.Add(content);
    box.IsNeedRepeating = true; // Repeat header on new pages
    

Additional Tips

  • Debugging Content Cut-off: If content is still being cut off, check the overall page margins and ensure that the content fits within the defined widths.
  • Testing with Different Content Sizes: Test with varying lengths of content to see how the layout behaves and adjust the row heights or column widths accordingly.

By following these guidelines, you should be able to create a stable two-column layout that spans multiple pages without content being cut off or misaligned. If you continue to experience issues, consider reviewing the examples provided in the Aspose documentation for further insights.

Sources:
[1]: RenderTable.cs
[2]: ForceTableRenderingOnNewPage.java

Both methods have been followed correctly, I had hoped that the floating text box method would have generated what was required, but my code above produces the following:

msedge_0fgDOap2N6.png (32.2 KB)
msedge_oy25vRXP0l.png (5.9 KB)

@dandev
I’ll check this issue and write you about results as soon as possible

1 Like

Thank you very much :blush:

1 Like

@dandev
I checked the following solution with latest (24.11) version :

const string LongText = "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit, aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est, qui dolorem ipsum, quia dolor sit, amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt, ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla pariatur? At vero eos et accusamus et iusto odio dignissimos ducimus, qui blanditiis praesentium voluptatum deleniti atque corrupti, quos dolores et quas molestias excepturi sint, obcaecati cupiditate non provident, similique sunt in culpa, qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio, cumque nihil impedit, quo minus id, quod maxime placeat, facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet, ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat. ";
private static void table_issues()
{
    var doc = new Document();
//page 1 for first scenario, I tweaked a bit to see how it will work with content overflow 
//so I set height = width/4
    var page1 = doc.Pages.Add();
    page1.PageInfo.Margin = new MarginInfo()
    {
        Bottom = 0,
        Left = 0,
        Right = 0,
        Top = 0
    };
    page1.PageInfo.Height = page1.PageInfo.Width/4;
    Aspose.Pdf.Table table = new Aspose.Pdf.Table();
    table.Margin.Top = 10;
    table.DefaultColumnWidth = ((page1.PageInfo.Width / 4) - 30).ToString();
    table.DefaultCellPadding = new MarginInfo();
    table.DefaultCellPadding.Left = 0;
    table.DefaultCellPadding.Right = 0;
    table.DefaultCellPadding.Top = 5;
    table.DefaultCellPadding.Bottom = 5;
    table.DefaultCellTextState.LineSpacing = 2;
    table.DefaultCellTextState.FontSize = 11;

    Aspose.Pdf.Row row = table.Rows.Add();
    row.DefaultCellPadding = new MarginInfo();
    row.DefaultCellPadding.Bottom = 12;

    Aspose.Pdf.Cell cellHeader = row.Cells.Add("**Header/Section**");
    cellHeader.VerticalAlignment = VerticalAlignment.Top;
    cellHeader.Alignment = HorizontalAlignment.Left;
    cellHeader.DefaultCellTextState.FontStyle = Aspose.Pdf.Text.FontStyles.Bold;

    Aspose.Pdf.Cell cellContent = row.Cells.Add(LongText);
    cellContent.VerticalAlignment = VerticalAlignment.Top;
    cellContent.Alignment = HorizontalAlignment.Left;
    cellContent.ColSpan = 3;

    foreach (var r in table.Rows)
    {
        r.IsRowBroken = true;
    }
    page1.Paragraphs.Add(table);            
//page 2 for second one
    var page2 = doc.Pages.Add();
    page2.PageInfo.Margin = new MarginInfo()
    {
        Bottom = 0,
        Left = 0,
        Right = 0,
        Top = 0
    };
    page2.PageInfo.Height = page1.PageInfo.Width/4;
    Aspose.Pdf.FloatingBox box = new Aspose.Pdf.FloatingBox();

    box.ColumnInfo.ColumnCount = 2;
    box.ColumnInfo.ColumnSpacing = "5";
    box.ColumnInfo.ColumnWidths = "110 350";

    page2.Paragraphs.Add(box);

    TextFragment text1 = new TextFragment("**Header/Section**");
    text1.TextState.FontStyle = FontStyles.Bold;
    box.Paragraphs.Add(text1);

    TextFragment text2 = new TextFragment(LongText);
    text2.IsFirstParagraphInColumn = true;
    box.Paragraphs.Add(text2);
    box.IsNeedRepeating = true;
    doc.Save(OutputFolder + "tables_issues.pdf");
}

The result was following:
tables_issues.pdf (6.5 KB)

If I understood you correctly, at least first scenario works fine in latest version and thus it’s one of ways you can resolve this issue
The second one is though acting strangely, although the content isn’t cut, I’ll look into why the second one behaves in such way
Check if this suits you, please

Thank you for looking into this for me, if we are to use the table format would we need to pay for the new version or just update via Nuget? The issue is intermittent for text being cut off however for this method as it was dependent on the position of the row on the page. On some letters it was fine, on others with a larger header due to a bigger address it ended up being cut off.

Ideally I would like to use the floating box method if possible as it seems a much neater way to do it, and it looked like none of the content would be cut off from the initial tests that I have done - I just can’t understand why the columns change when the content goes onto a new page.

@dandev
We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): PDFNET-58835

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.

Nuget updating should work just fine; the license, as far as I know, just restricts some features of the product and shouldn’t be version-specific.
As for the floating box, I added a task; hopefully, it will be resolved shortly.
Just to clarify, do I understand correctly that you expect the FloatingBox to behave like a Table in the result file that I provided?

1 Like

Thank you Ilya.

That is correct yeah, the left column should just contain the header, and the right column should contain the content relating to that header - There will be multiple of these on the letters we generate for the project in question.

I have updated Aspose.PDF to 24.11.0 for this solution, but it says we will require a new license.

Dan

@dandev
I asked for explanation, as I was said, this is because license is usually supported for 2 years and then it requires a renewal
it seems that within this period you can update freely and then it asks to buy a new one

Yeah, we will need to purchase a new license once the fix has been released.

@dandev
Issue is registered, you’ll be notified in this discussion when it will be resolved

1 Like