3

在我的 PowerPoint 插件中,我想访问幻灯片上的形状。形状是在幻灯片母版的自定义布局中定义的占位符。

当我添加基于自定义布局的幻灯片时,形状只是被命名为“占位符 1”、“占位符 2”……

有没有办法通过主人给出的名字来获取占位符?

目前我正在使用以下代码搜索形状:

public static Shape GetShape(string stringToSearch, Shapes shapes) {

        foreach (Shape shape in shapes) {

            if (shape.Name == stringToSearch) {
                return shape;
            }

            // Search Groups
            if (shape.Type == MsoShapeType.msoGroup) {
                foreach (Shape childshape in shape.GroupItems) {
                    if (childshape.Name == stringToSearch) {
                        return childshape;
                    }
                }
            }
        }

        throw new KeyNotFoundException("No Shape found");
}

更新:也许为了更清楚,这是 PowerPoint-Presentation 的结构。

为占位符定义名称的大师: 大师的截图

在 master 中定义的名称丢失的演示文稿: 演示文稿截图

问题:如何通过主文件中定义的名称获取演示文稿中的元素?

4

1 回答 1

0

好吧..这是史蒂夫的“丑陋!” 解决方案。

对于我的项目,我既没有也不想控制形状的创建,所以我不能“标记”它们。这就是为什么我有一个自定义占位符名称来识别它们,所以形状的名称确实是 [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]];

这是比较函数,它采用两种形状并检查它们是否“相等”。可以扩展以使其更精确。

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我们缺少的东西,是吗?

于 2014-01-18T19:24:16.130 回答