DEV Community

Brian D. Baker
Brian D. Baker

Posted on • Updated on

Weirdness with TextRange2 objects inside PowerPoint Tables

I was working with TextRange2.BoundLeft and TextRange2.BoundTop when I noticed the behavior of those 2 properties is different depending on whether the TextRange2 is in a normal Shape object or inside a table. For TR2s inside normal Shape objects, .BoundTop and .BoundLeft give the distance from the top and left sides of the slide, but for TR2s inside tables, they give the distance from the top left corner of the table.

That should be easy to fix, right? All you have to do is get the Shape object for the table containing the TextRange2 in question, then add its .Top and .Left to the TextRange2's .BoundTop and .BoundLeft.

But there's another challenge here. Getting the table Shape object containing the TextRange2 you already have.

Normally, PowerPoint TextRange2 objects have a property .Parent that you can use to go up the presentation DOM to the TextFrame2 that contains them, and likewise TextFrame2 objects have a property Parent that lets you access the shape that contains them ... except if the TextRange2 object is inside of a table. Then it has no Parent property. Even trying to test if .Parent is Nothing triggers an error.

The only workaround I know of is to select the TextRange2 object in question (using the .Select method), then get the Shape that contains the TextRange2 from ActiveWindow.Selection.ShapeRange(1). Unfortunately, that only gets you halfway there, to the cell Shape object containing the TextRange2. Also, while the cell Shape object's .Parent property works, it behaves counterintuitively; it returns the Shape object that contains the entire table.

To get to the Shape object for the table, you have to use the .Select trick again, this time calling it on the Shape object for the cell. Then ActiveWindow.Selection.ShapeRange(1) gets you to the Shape object for the table.

Code looks like something like the following to get the table. In my application I have this split across a couple of functions with error handlers and a selection buffer to restore whatever was originally selected before the function calls.

Public Function GetTableShapeAncestorOfTR2(ByRef tr2 As TextRange2) As Shape
    Dim cellShape as Shape
    tr2.Select
    Set cellShape = ActiveWindow.Selection.ShapeRange.Item(1)
    cellShape.Select
    Set GetTableShapeAncestorOfTR2 = ActiveWindow.Selection.ShapeRange.Item(1)
End Function
Enter fullscreen mode Exit fullscreen mode

Top comments (0)