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
.