How to split table to new PowerPoint slide when content flows off current slide using Open XML SDK 2.0

8.1k views Asked by At

I have a bunch of data that I need to export from a website to a PowerPoint presentation and have been using Open XML SDK 2.0 to perform this task. I have a PowerPoint presentation that I am putting through Open XML SDK 2.0 Productivity Tool to generate the template code that I can use to recreate the export.

On one of those slides I have a table and the requirement is to add data to that table and break that table across multiple slides if the table exceeds the bottom of the slide. The approach I have taken is to determine the height of the table and if it exceeds the height of the slide, move that new content into the next slide. I have read Bryan and Jones blog on adding repeating data to a PowerPoint slide, but my scenario is a little different. They use the following code:

A.Table tbl = current.Slide.Descendants<A.Table>().First();
A.TableRow tr = new A.TableRow();
tr.Height = heightInEmu;
tr.Append(CreateDrawingCell(imageRel + imageRelId));
tr.Append(CreateTextCell(category));
tr.Append(CreateTextCell(subcategory));
tr.Append(CreateTextCell(model));
tr.Append(CreateTextCell(price.ToString()));
tbl.Append(tr);
imageRelId++;

This won't work for me since they know what height to set the table row to since it will be the height of the image, but when adding in different amounts of text I do not know the height ahead of time so I just set tr.Heightto a default value. Here is my attempt at figuring at the table height:

   A.Table tbl = tableSlide.Slide.Descendants<A.Table>().First();
   A.TableRow tr = new A.TableRow();
   tr.Height = 370840L;
   tr.Append(PowerPointUtilities.CreateTextCell("This");
   tr.Append(PowerPointUtilities.CreateTextCell("is"));
   tr.Append(PowerPointUtilities.CreateTextCell("a"));
   tr.Append(PowerPointUtilities.CreateTextCell("test"));
   tr.Append(PowerPointUtilities.CreateTextCell("Test"));
   tbl.Append(tr);
   tableSlide.Slide.Save();

   long tableHeight = PowerPointUtilities.TableHeight(tbl);

Here are the helper methods:

public static A.TableCell CreateTextCell(string text)
{
    A.TableCell tableCell = new A.TableCell(
                            new A.TextBody(new A.BodyProperties(),
                            new A.Paragraph(new A.Run(new A.Text(text)))),
                            new A.TableCellProperties());
    return tableCell;
}

public static Int64Value TableHeight(A.Table table)
{
    long height = 0;

    foreach (var row in table.Descendants<A.TableRow>()
                             .Where(h => h.Height.HasValue))
    {
        height += row.Height.Value;
    }

    return height;
}

This correctly adds the new table row to the existing table, but when I try and get the height of the table, it returns the original height and not the new height. The new height meaning the default height I initially set and not the height after a large amount of text has been inserted. It seems the height only gets readjusted when it is opened in PowerPoint.

I have also tried accessing the height of the largest table cell in the row, but can't seem to find the right property to perform that task.

My question is how do you determine the height of a dynamically added table row since it doesn't seem to update the height of the row until it is opened in PowerPoint? Any other ways to determine when to split content to another slide while using Open XML SDK 2.0? I'm open to any suggestion on a better approach someone might have taken since there isn't much documentation on this subject.

1

There are 1 answers

3
Todd Main On

This is a really great question. One thing you can do is measure the height and width of the fonts in System.Drawing.Text and create a sort of pre-renderer in code to figure out if the text will cause the table to flow off-screen. There would be a bit to keep track of, like at what width will the fonts wrap and create a new line and then space between the lines and the margin of the cells. It would be a running total to keep track of the table height by the total number of lines it could contain with your font and it's size and your text plugged-in - and still stay within the bounds of the slide canvas. But once you have all of this, it should give you very good insight into whether or not you need a new slide.

This is a good article to learn how to measure rendered text in .NET: http://www.devsource.com/c/a/Languages/Text-Metrics-in-the-Net-Framework-Part-I/