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

Dav*_*ens 9 vba powerpoint-vba

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

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

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

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

尝试的解决方法:

以为我可以操纵自定义布局来添加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
Run Code Online (Sandbox Code Playgroud)

hpf*_*hpf 10

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

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

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

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

摘要:

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

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

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

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

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

  • 我觉得很傻.我写了"它有效",却未能真正检查它.因为我可以看到那里的文本,我无法想象MS会在DUMB中足以在textrange对象中没有文本.显然,微软已经让我失望了! (2认同)

Dav*_*ens 3

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

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

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

Dim dictShapes As Object 'Dictionary
Run Code Online (Sandbox Code Playgroud)

然后是建立它的程序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
Run Code Online (Sandbox Code Playgroud)

我这样称呼这个函数:

Dim shp as Object 'PowerPoint.Shape

Set shp = GetShapeByIndex(shp.Parent, dictShapes("chart RIGHT"))
Run Code Online (Sandbox Code Playgroud)

字典以这样的方式初始化,我可以传递一个字符串参数,它将返回形状的索引,这一切都应该起作用。

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
Run Code Online (Sandbox Code Playgroud)