Modify and replace embedded OLE Object

I’m trying to edit and replace embedded ole objects in presentations. I followed this instruction but it doesn’t work as I expected.

For example:

My pptx file has two embedded file a ppt and another pptx. There was no problem with the ppt I could edit and replace it but when I replaced the embedded pptx like this:

// Changing Ole frame object data
msout.Position = 0;
ole.ObjectData = msout.ToArray();

The replaced pptx Ole Object properties changed to this:

EmbeddedFileName: /ppt/embeddings/oleObject2.bin
EmbeddedFileExtension: .bin

(MS PowerPoint 2016 cannot handled this embedded file after the replace, when I extracted the embedded file manually and replaced the .bin extension to .pptx I could open and see the changes in the file)

The original was this:

EmbeddedFileName: /ppt/embeddings/oleObject2.bin
EmbeddedFileExtension: .pptx

Can I replace all kinds of Ole Object data using the ObjectData property?

I tried another method to replace Ole Objects:

  1. Get and edit the embedded file stream
  2. Add a new Ole Object to the original position with AddOleObjectFrame
  3. Remove the original Ole Object from the Slide

My problem with this, there will be the Changed Object image on the slide as you mentioned here. I wanted to change the image as it is in the example but there is no PictureId property in the IOleObjectFrame interface.

So my other question is: how could I change the added IOleObjectFrame image on the slide?

@erdeiga,
Thank you for the issue description. Could you also share a presentation sample for investigating the problem, please? It would be great to know the version of Aspose.Slides that you are using as well.

@Andrey_Potapov,
I attached the sample files, project and the requested infos.

When I replace the Ole objects there is no problem with the embedded ppt, doc and xls files but I cannot access the embedded pptx, docx, xlsx, pdf, png and txt files with MS Office.

Aspose.Slides 21.1
.Net Core 3.1
Linux environment

Sample files:
embeddedOleObjects.zip (1.8 MB)

Project:
ReplaceEmbeddedObjects.zip (3.3 KB)

@Andrey_Potapov,
My other question is how could I replace the picture that is belongs to the Ole object?

@erdeiga,
Thank you for the presentation samples, solution, and additional details. Did I understand correctly that the attached embeddedOleObjects.pptx file is the output file? Could you share the original PPTX file, please?
I am investigating your other questions.

The embeddedOleObjects.pptx and embeddedOleObjects.ppt are the input files.

PowerPoint cannot open the embedded oleObject2.bin (pptx) file from the attached embeddedOleObjects.pptx (before replacement). Could this file be already corrupted?

I created the test files with MS Office PowerPoint 2016 and added the embedded files like this:
Insert -> Object -> Insert Object -> Create from file

Maybe there is a compatibility issue?

If I use this code snippet before the replace I can extract the embedded files without any problem (only the embedded image is corrupted) so I assume that there is no problem with the main file.

private static void SaveOleObjectToFile(in OleObjectFrame oleObjectFrame)
        {
            var dir = Directory.CreateDirectory("extracted_files");
            string outPath = $"{dir.Name}{Path.DirectorySeparatorChar}extracted_{Guid.NewGuid()}{oleObjectFrame.EmbeddedFileExtension}";
            var data = oleObjectFrame.EmbeddedFileData;
            using FileStream fstr = new FileStream(outPath, FileMode.Create, FileAccess.Write);
            fstr.Write(data, 0, data.Length);
        }

@erdeiga,
I have investigated your solution. Your code doesn’t work because you are reading embedded data from the EmbeddedFileData property, but you are writing changed data to the ObjectData property. Soon I will inform you how to do it right and answer the rest of the questions.

1 Like

@Andrey_Potapov,
I managed to figure it out how to replace the Object changed image after I insert a new Ole Object to the a slide.

var newOleObject = embeddedOle.Slide.Shapes.AddOleObjectFrame(embeddedOle.X, embeddedOle.Y, embeddedOle.Width, embeddedOle.Height, redactedOleInfo);
//Replace Image that belong to the OleObject
if (!embeddedOle.IsObjectIcon)
{
    //Get first slide thumbnail
    Bitmap firstSlideAsImage = embeddedPresentation.Slides[0].GetThumbnail(1f, 1f);
    //Replace the image that belongs to the new oleObject
    newOleObject.SubstitutePictureFormat.Picture.Image.ReplaceImage(firstSlideAsImage);
}

//Remove old OleObject
embeddedOle.Slide.Shapes.Remove(embeddedOle);

But still it would be good to know how can I edit and replace an existing OleObjectFrame.EmbeddedFileData if it is possible.

@erdeiga,
I am glad to know that you have found that way. Thank you for your patience.

I have been requested the necessary information from our development team. I am still waiting for clarifications.

1 Like

@erdeiga,
At the moment, to change an existing OLE object, you need to remove it and create a new one. The next code examples can help you:

public static void Main()
{
    // create presentation with embedded PPTX and substitute image
    using (Presentation pres = new Presentation())
    {
        // add OLE frame
        IOleObjectFrame ole = pres.Slides[0].Shapes.AddOleObjectFrame(10, 10, 100, 100, new OleEmbeddedDataInfo
        {
            EmbeddedFileData = File.ReadAllBytes("embeddedOleObjects.pptx"),
            EmbeddedFileExtension = "pptx"
        });

        // open presentation to generate substitute image
        using (Presentation embeddedPres = new Presentation("embeddedOleObjects.pptx"))
        {
            // generate substitute image (first slide thumbnail)
            IPPImage substImage = pres.Images.AddImage(GetFirstSlideThumbnail(embeddedPres));
            // set substitute image
            ole.SubstitutePictureFormat.Picture.Image = substImage;
           
            pres.Save("pres.pptx", SaveFormat.Pptx);
        }
    }

    // replace OLE frame
    using (Presentation pres = new Presentation("pres.pptx"))
    {
        IOleObjectFrame oldOle = (IOleObjectFrame) pres.Slides[0].Shapes[0];
        pres.Slides[0].Shapes.Remove(oldOle);
       
        IOleObjectFrame newOle = pres.Slides[0].Shapes.AddOleObjectFrame(oldOle.X, oldOle.Y, oldOle.Width, oldOle.Height, new OleEmbeddedDataInfo
        {
            EmbeddedFileData = File.ReadAllBytes("embeddedOleObjects.ppt"),
            EmbeddedFileExtension = "ppt"
        });
       
        // generate substitute image
        using (Presentation embeddedPres = new Presentation("embeddedOleObjects.ppt"))
        {
            IPPImage substImage = pres.Images.AddImage(GetFirstSlideThumbnail(embeddedPres));
            newOle.SubstitutePictureFormat.Picture.Image = substImage;
           
            pres.Save("pres.pptx", SaveFormat.Pptx);
        }
    }
}

private static byte[] GetFirstSlideThumbnail(Presentation pres)
{
    using (MemoryStream stream = new MemoryStream())
    {
        using (Bitmap image = pres.Slides[0].GetThumbnail())
        {
            image.Save(stream, ImageFormat.Png);
        }

        return stream.ToArray();
    }
}

@Andrey_Potapov,
Thanks for your help!