0

I am trying to port some existing VBA code to C#. One routine controls the indentation of bullet items, and is roughly:

indentStep = 13.5
For Each parag In shp.TextRange.Paragraphs()
    parag.Parent.Ruler.Levels(parag.IndentLevel).FirstMargin = indentStep * (parag.IndentLevel - 1)
    parag.Parent.Ruler.Levels(parag.IndentLevel).LeftMargin = indentStep * (parag.IndentLevel)
Next parag

The code works, but appears to be spooky black magic. In particular, each time a particular ruler's margins are set ALL NINE rulers margins are actually set. But somehow the appropriate information is being set. Unfortunately, when you do the same thing in C#, the results change. The following code has no visible effect:

const float kIndentStep = 13.5f;
foreach (PowerPoint.TextRange pg in shp.TextFrame.TextRange.Paragraphs())
{
pg.Parent.Ruler.Levels[pg.IndentLevel].FirstMargin = kIndentStep * (pg.IndentLevel - 1);
pg.Parent.Ruler.LevelS[pg.IndentLevel].LeftMargin = kIndentStep * pg.IndentLevel;
}

1 Answers1

0

This appears to be a limitation/bug when automating PowerPoint from C#. I confirm it works with VBA.

I do see an effect after the code runs: it changes the first level with each run so that, at the end, the first level has the settings that should have been assigned to the last level to be processed, but none of the other levels appear to be affected, visibly. I do see a change in the values returned during code execution, but that's all.

If the code changes only one, specific level for the text frame, it works. The problem occurs only when attempting to change multiple levels.

I tried various approaches, including late-binding (PInvoke) and putting the change in a separate procedure, but the result was always the same.

Here's my last iteration

Microsoft.Office.Interop.PowerPoint.Application pptApp = (Microsoft.Office.Interop.PowerPoint.Application) System.Runtime.InteropServices.Marshal.GetActiveObject("Powerpoint.Application"); // new Microsoft.Office.Interop.PowerPoint.Application();
//Change indent level of text
const float kIndentStep = 13.5f;
Microsoft.Office.Interop.PowerPoint.Shape shp = pptApp.ActivePresentation.Slides[2].Shapes[2];
Microsoft.Office.Interop.PowerPoint.TextFrame tf = shp.TextFrame;
object oTf = tf;
int indentLevelLast = 0;
foreach (Microsoft.Office.Interop.PowerPoint.TextRange pg in tf.TextRange.Paragraphs(-1, -1))
{
    int indentLevel = pg.IndentLevel;
    if (indentLevel > indentLevelLast)
    {
        Microsoft.Office.Interop.PowerPoint.RulerLevel rl = tf.Ruler.Levels[indentLevel];
        object oRl = rl;
        System.Diagnostics.Debug.Print(pg.Text + ": " + indentLevel + ", " + rl.FirstMargin.ToString() + ", " + rl.LeftMargin.ToString()) ;
        object fm = oRl.GetType().InvokeMember("FirstMargin", BindingFlags.SetProperty, null, oRl, new object[] {kIndentStep * (indentLevel - 1)});
        //rl.FirstMargin = kIndentStep * (indentLevel - 1);
        object lm = oRl.GetType().InvokeMember("LeftMargin", BindingFlags.SetProperty, null, oRl, new object[] { kIndentStep * (indentLevel) });
        //rl.LeftMargin = kIndentStep * indentLevel;
        indentLevelLast = indentLevel;
        System.Diagnostics.Debug.Print(pg.Text + ": " + indentLevel + ", " + tf.Ruler.Levels[indentLevel].FirstMargin.ToString() + ", " + tf.Ruler.Levels[indentLevel].LeftMargin.ToString()) ;
        rl = null;
    }
}

FWIW neither code snippet provided in the question compiles. The VBA snippet is missing .TextFrame. The C# snippet doesn't like Parent.Ruler so I had to change it to TextFrame.Ruler.

Cindy Meister
  • 25,071
  • 21
  • 34
  • 43