Взаимодействие с PowerPoint: получение заполнителя по имени, указанному в мастере

В моем PowerPoint AddIn я хочу получить доступ к фигурам на слайдах. Фигуры являются заполнителями, определенными в пользовательских макетах в слайдмастере.

Когда я добавляю слайд на основе пользовательского макета, фигуры просто получают названия "заполнитель 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.

Мастер с именами, определенными для заполнителей:Снимок мастера

Презентация, где имена, определенные в master, потеряны:Скриншот презентации

Проблема: Как получить элемент в презентации по имени, указанному в мастере?

1 ответ

Ну, вот Стив "Гадкий!" решение.

Для моего проекта я не имею и не хочу контролировать создание фигур, поэтому я не могу пометить их. Вот почему у меня есть собственное имя заполнителя для их идентификации, поэтому имена фигур действительно будут [PlaceholderType] ##.

Шаги:

  • хранить места всех форм
  • сбросить макет слайда
  • совмещать формы слайдов и основные формы слайдов
  • восстановить местоположение всех форм.

Примечание: я не использую группы форм. эта техника будет намного сложнее, если вы делаете, и вам нужно проверить внутри групп.

Это функция, которая делает это и возвращает сопоставление masterhapename - 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 мы пропали, не так ли?

Другие вопросы по тегам