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

1

5

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.

Gimble answered 14/4, 2010 at 14:13 Comment(2)
Yeah I mean this was the path I was going down, but did not have any luck. Looking more for a working example with code.Gimble
@Otaku: I never found a solution to this issue and since time was an issue on my project we decided to just let the data flow off the slide and make the end user reformat the data.Gimble
B
1

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/

Betti answered 4/7, 2010 at 23:31 Comment(3)
I would think you would need to keep track of the initial position of the table on the slide too as a starting height. I've tried to perform this task, but couldn't get consistent results since the height of the table didn't seem to change until ppt rendered it. Any code you could post to see if I missed something?Gimble
@amurra: Unfortunately I don't have any sample code - I image it would be a fair amount of work and code to solve the issue, but this is how I would approach it. The main issue with the Open XML SDK is that it doesn't provide any rendering information - I imagine if you were trying this task from VBA or VSTO, you'd be able to develop a solution much faster by just looking at the slide canvas height and compare the table top+ height to see if it's off page and if so, remove the last row and start the next slide with it.Betti
@amurra: I stumbled upon a good article about measuring text in .NET that would be helpful the recommendation above. Link above.Betti

© 2022 - 2024 — McMap. All rights reserved.