ฉันจะแทรกสไลด์ลงในสไลด์ 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สุดท้ายกับการรับทั้งหมดอื่นที่ด้านล่าง

ปัญหาคือรหัสนี้ประมวลผลวัตถุบางประเภทไม่ถูกต้อง ประการหนึ่งมันไม่ได้ประมวลผลภาพวาดเลย (อาจเป็นเพราะบางส่วนมาจาก 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เป็นแนวทางที่ดีกว่ามาก