Обработка фигуры по имени заполнителя в PowerPoint

Я пытаюсь создать функцию, которая вернет определенную форму, основанную на известный свойство Name, присвоенное . Я не могу использовать форму .Name потому что это не известно заранее, еще при создании слайдов из шаблона/макета.

проблема заключается в том, как пользовательский макет связан с фактическим слайдом. Например, когда я повторяю слайд .CustomLayout.Shapes.Placeholders, Я могу легко определить конкретный заполнитель .Name собственность.

если я вернусь этой shape, это будет пользовательский заполнитель макета, который влияет на все слайды на этом макете (например, если я добавляю текст в этот заполнитель, он обновляет все слайды с помощью этого макета!). Очевидно, что это нежелательно!

если вместо этого я индексирую коллекцию и пытаюсь вернуть фигуру в этом положении индекса из.Shapes.Placeholders, похоже, что они не поддерживают тот же индекс, т. е. .Shapes.Placeholders(i) <> .CustomLayout.Shapes.Placholders(i)

попытка обойти:

думал, что я мог бы манипулировать пользовательским макетом, чтобы добавить Tag для фигуры. Я пробовал, и это не удается по тем же причинам (т. е. CustomLayout.Форма как-то не "такая же" форма, как слайд.Форма...). В любом случае, я надеюсь избежать "обходного пути" в пользу более правильного способа сделать это, если такая вещь существует.

это функция, которую я так далеко:

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 ответов


у меня есть потенциальное решение для вас.

проблема заключается в нижнем колонтитуле, номере страницы и заполнителях даты на мастере слайдов. Они включены в коллекцию заполнителей на мастере слайдов, но при создании отдельного слайда они становятся своими собственными свойствами слайда (под .HeaderFooter свойства). Это приводит к различному количеству заполнителей на ведущем устройстве и на слайдах, и поскольку эти заполнители могут находиться в середине коллекции, индексы не совпадают.

Итак, одним из возможных решений является удаление этих трех заполнителей из вашего мастера, что делается путем открытия мастера слайдов и снятия флажка нижнего колонтитула. Если вы сделаете это, вы обнаружите, что количество заполнителей на главном и на слайдах одинаковое, и все номера индексов выстраиваются в линию. Вы все еще не можете использовать SlideMaster.CustomLayouts(n).Shapes.Placeholders(m).Name свойство для доступа к правильному заполнителю на фактическом слайде. Однако, как только вы знаете индекс заполнителя ("m" в моем примере в последнем предложении), вы должны иметь доступ к правильному заполнителю на слайде через SlideObj.Shapes.PlaceHolders(m). Вы можете повторить через SlideMaster.Формы.Сначала заполнители и сохраните индекс для последующего использования.

Если вам нужны поля нижнего колонтитула, просто добавьте новые текстовые заполнители в мастер слайдов, поместите их в нижней части слайда, а затем вставьте в них номер страницы, дату или фиксированный текст.

резюме:

  1. снимите флажок нижние колонтитулы на всех мастерах слайдов, о которых вы заботитесь. Не уверен, что это можно сделать программно.

  2. перебираем ActivePresentation.SlideMaster.CustomLayout(n).Shapes.Placeholders для каждого из ваших мастеров слайдов (пользовательские макеты), глядя на .Name свойство, чтобы найти заполнитель(Ы), который вас интересует. Сохраните это в массиве (будет использовать имя заполнителя в качестве имени массива, поэтому, если имя заполнителя было "datatable", я бы использовал datatable[n])=индекс # заполнителя на CustomLayout/Master. Сделать это один раз и сохранить его в глобальной переменной.

  3. если вы хотите получить доступ к заполнителю на слайде, получите индекс SlideMaster для слайда с SM_index=SlideObj.CustomFormat.Индекс. Затем откройте заполнитель "datatable" с помощью SlideObj.Формы.Заполнители (datatable[SM_index])

если у вас есть только один SlideMaster для всех ваших слайдов, то вам не нужен массив и вместо этого можно использовать простую переменную.

если вам нужен настоящий код, дайте мне знать , но я ожидаю, что вы этого не сделаете. Дайте мне знать, если это сработает в вашем проекте реального мира.


мой текущий обходной путь должен сделать следующее:

Delcare модульного уровня Dictionary объект, который создает своего рода хэш-таблицы на основе слайда CustomLayout и известный индекс каждого заполнителя в Slide.Shapes коллекция. (Это я получаю через простую for / Next итерацию в подпрограмме throwaway).

так как я строю слайды из шаблона, я думаю, что это относительно безопасно и надежно, но не гибкий (весь пункт работы с файлы potx шаблон файлы простота использования и гибкости...).

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

У меня есть другое решение. Я перебираю все фигуры на слайде и сравниваю их с некоторыми свойствами фигуры в пользовательском макете. Я взял ширину, высоту и autoshapetype. Если они точно такие же, я нашел соответствующую форму на слайде.

     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