Взаимодействие с 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
мы пропали, не так ли?