Как вставить слайд в другой слайд PowerPoint с помощью OpenXML?

Aug 20 2020

Я хотел бы взять слайд PowerPoint («источник») и вставить его в другой слайд PowerPoint («цель»), который уже содержит некоторый контент, в определенной позиции на исходном слайде PowerPoint.

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

У меня есть код, написанный другим коллегой, который клонирует все элементы из исходного слайда, но он запутан и использует разные варианты кода для разных типов элементов. Вот типичный образец этого кода:

foreach (OpenXmlElement element in sourceSlide.CommonSlideData.ShapeTree.ChildElements.ToList())
{
    string elementTypeName = element.GetType().ToString();

    if (elementTypeName.EndsWith(".Picture"))
    {
        // Deep clone the element.
        elementClone = element.CloneNode(true);

        // Adjust the offsets so it is positioned correctly.
        ((Picture)elementClone).ShapeProperties.Transform2D.Offset.X += (Int64)shapeStruct.OffsetX;
        ((Picture)elementClone).ShapeProperties.Transform2D.Offset.Y += (Int64)shapeStruct.OffsetY;

        // Get the shape tree that we're adding the clone to and append to it.
        ShapeTree shapeTree = slideCard.CommonSlideData.ShapeTree;
        shapeTree.Append(elementClone);

        string rId = ((Picture)element).BlipFill.Blip.Embed.Value;

        ImagePart imagePart = (ImagePart)slideInstProc.SlidePart.GetPartById(rId);
        string contentType = imagePart.ContentType;

        // Locate the same object we cloned over to the slide.
        var blip = ((Picture)elementClone).BlipFill.Blip;

        slidePart = slideCard.SlidePart;

        try
        {
            ImagePart imagePart1 = slidePart.AddImagePart(contentType, rId);
            imagePart1.FeedData(imagePart.GetStream());
        }
        catch (XmlException)
        {
            //Console.WriteLine(xe.ToString());
            Console.WriteLine("Duplicate rId (" + rId + ")");
        }
    }
    if (elementTypeName.EndsWith(".GroupShape"))
    {
        ... etc

Код продолжается с другой, если лестница , содержащая блоки кода для имен типов элементов , заканчивающихся .GroupShape, .GraphicFrame, .Shape, и .ConnectionShape, заключив с Catchall еще на дне.

Проблема в том, что этот код некорректно обрабатывает некоторые типы объектов. Во-первых, он вообще не обрабатывает рисунки (возможно, потому, что некоторые из них взяты из более старой версии PowerPoint), а когда это происходит, он делает такие вещи, как изменение цвета рисунка.

Я надеялся, что существует более фундаментальный способ (то есть более простой общий код) для встраивания исходного слайда PowerPoint в другой, рассматривая его как единый объект, без особого рассмотрения типов элементов в исходном PowerPoint.

В качестве альтернативы, как можно было бы обрабатывать рисунки или изображения в обычных «формах», которые не идентифицируют себя конкретно как изображения?

Ответы

RobertHarvey Aug 25 2020 at 03:42

Это код, который решил конкретную проблему, которую я описал выше:

using A = DocumentFormat.OpenXml.Drawing;

foreach(A.BlipFill blipFill in shape.Descendants<A.BlipFill>())
{
    string rId = blipFill.Blip.Embed.Value;
    ImagePart imagePart = (ImagePart)slideInstProc.SlidePart.GetPartById(rId);
    string contentType = imagePart.ContentType;

    try
    {
        ImagePart imagePart1 = slidePart.AddImagePart(contentType, rId);
        imagePart1.FeedData(imagePart.GetStream());
    }
    catch (XmlException)
    {
        Console.WriteLine("Duplicate rId (" + rId + ")");
    }
}

Что в применении к elementTypeName.EndsWith(".shape");дает именно тот результат, который я хочу.

OpenXmlPowerTools - гораздо лучший подход для составления полных слайдов в презентацию (что не требует некоторых механизмов генерации, которые мы делаем) .