さて..これがスティーブの「アグリー!」です。解決。
私のプロジェクトでは、形状の作成を制御したり制御したりしたくないため、それらに「タグ付け」することはできません。そのため、それらを識別するためのカスタム プレースホルダー名を使用しています。そのため、形状の名前は実際には [PlaceholderType] ## になります。
手順:
- すべての形状の位置を保存する
- スライド レイアウトをリセットする
- スライドの形状とマスター スライドの形状を一致させる
- すべての形状の位置を復元します。
注: シェイプ グループは使用しません。この手法は、グループ内をチェックする必要がある場合、さらに複雑になります。
これはそれを行い、mastershapename - shapename マッピングを返す関数です。
private Dictionary<string, string> GetShapeMasters(Powerpoint.Slide s)
{
Dictionary<string, string> shapeMasters = new Dictionary<string, string>();
List<ShapeLocation> shapeLocations = new List<ShapeLocation>();
//store locations
foreach (Powerpoint.Shape sh in s.Shapes)
{
shapeLocations.Add(new ShapeLocation()
{
Name = sh.Name,
Location = new System.Drawing.RectangleF(sh.Left, sh.Top, sh.Width, sh.Height)
});
}
//have powerpoint reset the slide
//ISSUE: this changes the names of placeholders without content.
s.CustomLayout = s.CustomLayout;
//compare slide and master
foreach (Powerpoint.Shape sh in s.Shapes)
{
foreach (Powerpoint.Shape msh in s.CustomLayout.Shapes)
{
if (IsShapeMaster(sh, msh))
{
shapeMasters[msh.Name] = sh.Name;
}
}
}
//restore locations
//TODO: might be replaced by undo
foreach (var shm in shapeLocations)
{
Powerpoint.Shape sh = null;
try
{
sh = s.Shapes[shm.Name];
}
catch
{
//Fails for renamed placeholder shapes.
//Have yet to find a decent way to check if a shape name exists.
}
//placeholders do not need to be restored anyway.
if (sh != null)
{
sh.Left = shm.Location.Left;
sh.Top = shm.Location.Top;
sh.Width = shm.Location.Width;
sh.Height = shm.Location.Height;
}
}
return shapeMasters;
}
これでできること
Dictionary<string, string> shapeMasters = GetShapeMasters(theSlide);
if(shapeMasters.ContainsKey(stringToSearch))
Powerpoint.Shape KnownShape = theSlide[shapeMasters[stringToSearch]];
そして、これは 2 つの形状を取り、それらが「等しい」かどうかをチェックする比較関数です。より正確にするために拡張することができます。
private bool IsShapeMaster(Powerpoint.Shape sh, Powerpoint.Shape msh)
{
return
sh.Left == msh.Left
&& sh.Top == msh.Top
&& sh.Width == msh.Width
&& sh.Height == msh.Height
&& sh.Type == msh.Type
&& sh.PlaceholderFormat.Type == msh.PlaceholderFormat.Type;
}
元の形状の場所を格納する小さなクラス
class ShapeLocation
{
public string Name;
public System.Drawing.RectangleF Location;
}
私もこれが好きではないので、提案を受け付けています。シェイプとプレースホルダーをリンクする方法は他にないようです。shape.MasterShape
私たちが見逃しているものは本当にありませんよね?