在PowerPoint中按占位符名称处理形状

时间:2015-03-09 18:23:40

标签: vba powerpoint-vba

我正在尝试根据分配给CustomLayout.Shapes.Placeholder对象的已知 Name属性创建一个返回特定形状的函数。我不能使用形状.Name,因为即使从模板/布局创建幻灯片,也不会提前知道。

挑战似乎是自定义布局与实际幻灯片的关系。例如,当我迭代幻灯片的.CustomLayout.Shapes.Placeholders时,我可以通过它的.Name属性轻松识别特定的占位符。

如果我返回形状,它将是自定义布局占位符,会影响此布局上的所有幻灯片(例如,如果我将文本添加到此占位符,它使用此布局更新所有幻灯片!)。显然这是不可取的!

如果相反,我索引集合,并尝试从幻灯片的.Shapes.Placeholders返回该索引位置的形状,看起来它们没有保持相同的索引,即.Shapes.Placeholders(i) <> .CustomLayout.Shapes.Placholders(i) < / p>

尝试的解决方法:

我想我可以操纵自定义布局,为形状添加Tag。我尝试了,但由于同样的原因它失败了(即,CustomLayout.Shape在某种程度上不是与Slide.Shape“相同”的形状......)。在任何情况下,如果存在这样的事情,我希望避免使用“解决方法”来支持更合适的方法。

这是我到目前为止的功能:

Function GetShapeByPlaceholderName(sName As String, sld As Slide) As Object
Dim plchldrs As Placeholders
Dim shp As Shape
Dim ret As Shape
Dim i As Long

For Each shp In sld.CustomLayout.Shapes.Placeholders
    i = i + 1
    If shp.Name = sName Then
    '#### 
    '    This can easily identify the CustomLayout.Shapes.PLACEHOLDER
    '
    '    But I need to return the SHAPE in the Slide.Shapes collection
    '####

        '###
        Set ret = shp  'This will return the CustomLayout.Placeholder, which affects ALL slides

        '###
        'Set ret = sld.Shapes.Placeholders(i) 'the index of the Shapes.Placeholders is NOT the same

        '###
        'Set ret = sld.Shapes.Placeholders.FindByName(sName) 'This returns an error/specified shape name does not exist

        '###
        'Set ret = sld.Shapes.Placeholders.FindByName(i) 'This observes same failure that the index of the collections is not the same


        Exit For
    End If
Next

Set GetShapeByPlaceholderName = ret

End Function

3 个答案:

答案 0 :(得分:9)

我有一个潜在的解决方案。

问题是幻灯片母版上的页脚,页码和日期占位符。它们包含在幻灯片母版的占位符集合中,但是当创建单个幻灯片时,它们将成为幻灯片的自己属性(在.HeaderFooter属性下)。这会导致Master和幻灯片上的占位符数不同,并且因为这些占位符可能位于集合的中间,所以索引不会对齐。

因此,一种可能的解决方案是从Master中删除这三个占位符,方法是打开Slide Master并取消选中页脚复选框。如果这样做,您会发现Master和Slides上的占位符数相同,并且所有索引号都排成一行。您仍然无法使用SlideMaster.CustomLayouts(n).Shapes.Placeholders(m).Name属性访问实际幻灯片上的正确占位符。但是,一旦您知道占位符的索引(&#34; m&#34;在我的示例中的最后一句),您应该能够通过SlideObj.Shapes.PlaceHolders(m)访问幻灯片上的正确占位符。您可以先遍历SlideMaster.Shapes.PlaceHolders并存储索引供以后使用。

如果您需要页脚字段,只需将新的文本占位符添加到幻灯片母版,将它们放在幻灯片的底部,然后将页码,日期或固定文本插入其中。

要点:

  1. 取消选中您关注的所有幻灯片母版上的“页脚”复选框。不确定这是否可以以编程方式完成。

  2. 为每个幻灯片母版(自定义布局)迭代ActivePresentation.SlideMaster.CustomLayout(n).Shapes.Placeholders,查看.Name属性以查找您感兴趣的占位符。将其存储在数组中(将使用名称)占位符作为数组名称,因此如果占位符名称为&#34; datatable&#34;我将使用CustomLayout / Master上占位符的datatable [n])= index#。执行一次并将其存储在全局变量中。

  3. 如果要访问幻灯片上的占位符,请使用SM_index = SlideObj.CustomFormat.Index获取幻灯片的SlideMaster索引。然后访问占位符&#34; datatable&#34;使用SlideObj.Shapes.Placeholders(datatable [SM_index])

  4. 如果您的所有幻灯片只有一个SlideMaster,那么您不需要一个数组,而是可以使用一个简单的变量。

    如果您需要实际代码,请告诉我 - 但我希望您不要。如果这适用于您的真实世界项目,请告诉我。

答案 1 :(得分:2)

我目前的解决方法是执行以下操作:

Delcare一个模块级Dictionary对象,它根据幻灯片的CustomLayoutSlide.Shapes集合中每个占位符的已知索引创建一种哈希表。 (这是我在一次性子程序中通过简单的FOr / Next迭代获得的。)

由于我正在从模板构建幻灯片,我认为这是相对安全可靠的,但灵活(使用POTX 模板文件的整点应该是< em>易用性和灵活性......)。

Dim dictShapes As Object 'Dictionary

然后根据CustomLayout

建立它的程序
Sub SetShapeDict(cLayout as Object)

    Set dictShapes = CreateObject("Scripting.Dictionary")

    Select Case cLayout.Name
        Case "layout_one"
            dictShapes("chart RIGHT") = 1
            dictShapes("chart RIGHT title") = 2
            dictShapes("chart LEFT") = 5
            dictShapes("chart LEFT title") = 6
        Case "layout_two"
            dictShapes("chart RIGHT") = 1
            dictShapes("chart RIGHT title") = 2
            dictShapes("q text") = 4
            dictShapes("source text") = 5 
     End Select

 End Sub

我将此功能称为:

Dim shp as Object 'PowerPoint.Shape

Set shp = GetShapeByIndex(shp.Parent, dictShapes("chart RIGHT"))

字典初始化的方式是我可以传递一个字符串参数,它将返回形状的索引,所有应该工作。

Function GetShapeByIndex(chartSlide As Object, i As Long) As Object

    Dim ret
    Dim s As Long

    'if slide #1, there is no  "Slide Number Placeholder"
    ' this placeholder appears in the shapes' 3rd index for
    ' both Vertical Master no Background AND Horizontal Master

    If chartSlide.SlideNumber = 1 Then
        If i > 2 Then
            s = i - 1
        Else
            s = i
        End If
    Else
        s = i
    End If

    On Error Resume Next
    Set ret = chartSlide.Shapes(s)
    If Err.Number <> 0 Then Set ret = Nothing
    On Error GoTo 0

    Set GetShapeByIndex = ret

End Function

答案 2 :(得分:2)

我有另一种解决方法。我遍历幻灯片中的所有形状,并将它们与自定义布局中形状的某些形状属性进行比较。我采用宽度,高度和自动形状。如果它们完全相同,我在幻灯片中找到了相应的形状。

     For Each sh In sl.Shapes

        With sl.CustomLayout.Shapes("Name of shape in layout")
            If sh.Width = .Width And _
                sh.Height = .Height And _
                sh.AutoShapeType = .AutoShapeType Then
                bFound = True
                Exit For
            End If
        End With
    Next sh
    If bFound Then
        'sh is the shape you are looking for
    End If