I'm using GemBox.Presentation and I'm creating a large table in my PPTX file. Similar to this example, e.g.:
PresentationDocument presentation = new PresentationDocument();
Slide slide = presentation.Slides.AddNew(SlideLayoutType.Custom);
int rowCount = 100;
int columnCount = 4;
int columnWidth = 5;
Table table = slide.Content.AddTable(1, 1, columnCount * columnWidth, 0, LengthUnit.Centimeter);
for (int i = 0; i < columnCount; i++)
table.Columns.AddNew(Length.From(5, LengthUnit.Centimeter));
for (int r = 0; r < rowCount; r++)
{
TableRow row = table.Rows.AddNew(0);
for (int c = 0; c < columnCount; c++)
{
TableCell cell = row.Cells.AddNew();
TextParagraph paragraph = cell.Text.AddParagraph();
TextRun run = paragraph.AddRun(string.Format("Cell {0}-{1}", r + 1, c + 1));
}
}
presentation.Save("output.pptx");
As expected, the table doesn't fit on the slide:
So I need to split this table into multiple tables or multiple slides so that each table fits on its slide and all rows are visible.
How can I do that?
How can I find if the new TableRow
will exceed the Slide
height?
If you have dynamic row heights (for instance, some cells may contain multiple lines of text), then you'll need to paginate the content.
For example, see the following:
table.Frame.FormatDrawing(new PaginatorOptions() { UpdateTableRowHeights = true });
DrawingLayout tableLayout = table.Frame.Layout;
double maxHeight = presentation.SlideSize.Height - tableLayout.Top;
double currentHeight = 0;
TableRowCollection sourceRows = table.Rows;
TableRowCollection newRows = null;
int currentRowIndex = 0;
// Split the main table into multiple new tables based on the row heights.
while (currentRowIndex < sourceRows.Count)
{
currentHeight += sourceRows[currentRowIndex].Height;
// Create new slide with new table.
if (currentHeight > maxHeight)
{
currentHeight = sourceRows[currentRowIndex].Height;
Slide newSlide = presentation.Slides.AddNew(SlideLayoutType.Blank);
Table newTable = newSlide.Content.AddTable(tableLayout.Left, tableLayout.Top, tableLayout.Width, 0);
foreach (var column in table.Columns)
newTable.Columns.AddClone(column);
newRows = newTable.Rows;
}
// Move row from the main table to a new table.
if (newRows != null)
{
newRows.AddClone(sourceRows[currentRowIndex]);
sourceRows.RemoveAt(currentRowIndex);
}
else
{
++currentRowIndex;
}
}
presentation.Save("output.pptx");
If you have constant row heights, like shown in your screenshot, then you can simplify this.
For example, like the following:
int rowsPerSlide = 16;
TableRowCollection rows = table.Rows;
DrawingLayout layout = table.Frame.Layout;
for (int t = 1, tablesCount = (int)Math.Ceiling(rows.Count / (double)rowsPerSlide); t < tablesCount; t++)
{
Slide newSlide = presentation.Slides.AddNew(SlideLayoutType.Blank);
Table newTable = newSlide.Content.AddTable(layout.Left, layout.Top, layout.Width, 0);
foreach (var column in table.Columns)
newTable.Columns.AddClone(column);
for (int r = rowsPerSlide, rowsCount = Math.Min(rowsPerSlide * 2, rows.Count); r < rowsCount; r++)
{
newTable.Rows.AddClone(rows[rowsPerSlide]);
rows.RemoveAt(rowsPerSlide);
}
}
presentation.Save("output.pptx");