Bagaimana cara memasukkan slide ke slide PowerPoint lain menggunakan OpenXML?

Aug 20 2020

Saya ingin mengambil slide PowerPoint ("sumber"), dan memasukkannya ke dalam slide PowerPoint lain ("target") yang sudah berisi beberapa konten, pada posisi tertentu di slide PowerPoint sumber.

Saya telah mencoba beberapa cara untuk meneliti kode yang melakukan ini, tetapi saya terus mendapatkan hasil untuk menggabungkan slide ke dalam presentasi PowerPoint, yang bukan itu yang saya inginkan. Saya ingin mengambil slide yang ada dan memasukkannya ke slide lain, seperti seseorang akan memasukkan gambar ke dalam slide yang sudah ada.

Saya memiliki kode yang ditulis oleh rekan kerja lain yang mengkloning semua elemen dari slide sumber, tetapi itu berbelit-belit dan menggunakan variasi kode yang berbeda untuk jenis elemen yang berbeda. Berikut adalah contoh perwakilan dari kode itu:

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

Kode berlanjut dengan yang lain-jika tangga yang mengandung blok kode untuk nama jenis elemen berakhir dengan .GroupShape, .GraphicFrame, .Shape, dan .ConnectionShape, menyimpulkan dengan mencakup semuanya lagi di bagian bawah.

Masalahnya adalah kode ini tidak memproses beberapa jenis objek dengan benar. Untuk satu hal, itu tidak memproses gambar sama sekali (mungkin karena beberapa di antaranya berasal dari versi PowerPoint yang lebih lama), dan ketika itu terjadi, itu melakukan hal-hal seperti mengubah warna gambar.

Apa yang saya harapkan adalah ada cara yang lebih mendasar (yaitu kode umum yang lebih sederhana) untuk menyematkan slide sumber PowerPoint ke yang lain, memperlakukannya seperti satu objek, tanpa melihat jenis elemen dalam sumber PowerPoint secara khusus.

Atau, bagaimana cara memproses gambar atau gambar dalam "bentuk" biasa yang tidak mengidentifikasi diri mereka sendiri secara spesifik sebagai gambar?

Jawaban

RobertHarvey Aug 25 2020 at 03:42

Ini adalah kode yang memecahkan masalah khusus yang saya jelaskan di atas:

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 + ")");
    }
}

Yang mana, ketika diterapkan untuk elementTypeName.EndsWith(".shape");menghasilkan hasil yang saya inginkan.

Untuk menyusun slide lengkap menjadi presentasi (yang tidak memerlukan beberapa mekanisme pembuatan yang kami lakukan), OpenXmlPowerTools adalah pendekatan yang jauh lebih baik.