pptx-automizer icon indicating copy to clipboard operation
pptx-automizer copied to clipboard

Duplicate slides / Re-import pptx files from pptx-automizer's output

Open Idriosiris opened this issue 8 months ago • 11 comments

Hello guys,

Having some issues with updating the content of a slide and getting back the new elements from the resulting presentation.

What we use to update the slides is something like below

`

slides.forEach((slide) => {
  const slideUpdates = updatesBySlide.get(slide.number);
  if (slideUpdates) {
    pres.addSlide(
      `${fileName}-template`,
      slide.number,
      (slideObj: ISlide) => {
        slideUpdates.forEach((update) => {
          const shape = slide.elements.find(
            (element) =>
              element.name === update.name &&
              Math.abs(element.position.x - update.emuPosition.x) < 1000 &&
              Math.abs(element.position.y - update.emuPosition.y) < 1000 &&
              Math.abs(element.position.cx - update.emuPosition.cx) <
                1000 &&
              Math.abs(element.position.cy - update.emuPosition.cy) < 1000
          );

          if (shape && shape.hasTextBody) {
            slideObj.modifyElement(update.name, [
              ModifyTextHelper.setText(update.textContent.join("\n")),
            ]);
          }
        });
      }
    );
  } else {
    // If no updates for this slide, still need to add it to maintain presentation structure
    pres.addSlide(`${fileName}-template`, slide.number);
  }
});

`

This seems to be working great and creating the correct pptx file when saving it like below

const outputPath = path.join(outputDir, fileName); await pres.write(fileName);

But when we try to pull out all the slides from the pptx with something like below:

`

const pres = automizer.load(fileName, `${fileName}-template`);

const presInfo = await pres.getInfo();
const slides = presInfo
  .slidesByTemplate(`${fileName}-template`)
  .map((slide) => {
    const slideNumber = slide.number;

    return {
      number: slide.number,
      name: slide.info.name,
      shapes: slide.elements
        .filter(
          (shape) =>
            shape.hasTextBody === true && shape.getText().length !== 0
        )
        .map((shape) => {
          const text = shape.getText();

          return {
            name: shape.name,
            type: shape.type,
            text: text,
            position: {
              x: shape.position.x,
              y: shape.position.y,
              cx: shape.position.cx,
              cy: shape.position.cy,
            },
          };
        }),
    };
  });

`

What I find is that the below has double the number of slides than what I expect which I think partially makes sense just that I was expecting for the old slides to not be kept especially as we use removeExistingSlides: true

presInfo.slidesByTemplate(${fileName}-template)

Any idea what am I misunderstanding?

Idriosiris avatar May 06 '25 13:05 Idriosiris

Hi @Idriosiris ! There is no misunderstanding, the slides are only removed from the slides list, but not at all removed from the archive.

I did some testing to re-use outputted files from pptx-automizer, but didn't succeed, too. You will need to manually save a file in PowerPoint once to be able to automizer.load it again, I'm so sorry! It's a dark secret you have discovered.

You could try and set cleanup: true flag besides removeExistingSlides: true, but I'm not sure if this really helps.

It's basically because getCreationIds() at xml-template-helper.ts finds the existing slides by their appearance in ppt/_rels/presentation.xml.rels, which isn't cleaned up.

singerla avatar May 06 '25 15:05 singerla

So we're saying that there is currently no way of modifying a pptx which was already edited via Automizer unless we open it in powerpoint and give it a manual save.

Are there any active hypothesis on how this could be fixed? Asking as this is a use-case that would be highly valuable for me and could put some time to getting it fixed.

Idriosiris avatar May 06 '25 21:05 Idriosiris

I did look at this very very briefly a while ago. It can definitely be done but it will require a couple of days of effort, I think.

MP70 avatar May 07 '25 09:05 MP70

I'll go deeper into this! Thanks, @Idriosiris , I will figure out what is required exactly.

singerla avatar May 08 '25 14:05 singerla

I'm sorry for the late response, @Idriosiris.

I was testing a little with modifying an already modified chart, which is now working with a little tweaking - unexpectedly. :)

I've created a branch and placed a ToDo at src/helper/xml-template-helper.ts.

The thing regarding your situation is: The slide list from pres.getInfo() is based on uncleaned relations that contain non-visible slides, too. It should be either: a.) remove unused slides on generation (my preferred) b.) use slides list from 'p:sldIdLst' in ppt/presentation.xml

I'm happy for comments!

singerla avatar May 28 '25 09:05 singerla

You can run yarn dev on the new branch for a happy dev experience!

singerla avatar May 28 '25 09:05 singerla

Hi mates, are there any updates from that?

Seems when enabling cleanup: true besides removeExistingSlides: true, we still cannot reimport to automizer anymore.

duchm1606 avatar Nov 12 '25 09:11 duchm1606

Hi @duchm1606 ! Is it possible to provide a generated pptx for testing? I was playing around, but all my test files can be re-imported...

singerla avatar Nov 13 '25 09:11 singerla

Hi @duchm1606 ! Is it possible to provide a generated pptx for testing? I was playing around, but all my test files can be re-imported...

@singerla https://wiki.documentfoundation.org/images/4/47/Extlst-test.pptx

Fyi maybe the file has lost the slide1 so it throw an error when loading again the file. Using buffer

const jszip = await automizer.getJSZip();
const modifiedBuffer = Buffer.from(await jszip.generateAsync({ type: 'nodebuffer' }));

duchm1606 avatar Nov 13 '25 10:11 duchm1606

Ok, I'm testing this:

  1. load the Extlst-test.pptx as root and add some slides to it.
  2. save as Extlst-test.mod.pptx
  3. create a new instance and load Extlst-test.mod.pptx, add some slides to it
  4. save as Extlst-test.mod.mod.pptx => Opens with PowerPoint complaining repair-message.

The slide you have sent contains a SmartArt, which is supported only for a few weeks now, I did not test this a lot. Might be related to this special SmartArt content?

I could not find an obvious problem in the mod.mod, any idea on how to target this?

singerla avatar Nov 13 '25 14:11 singerla

Can we try with a version removing this smart art first?

Have tried to modify text in the first slide, and export to buffer with two flags on. Right after that when I import back this as the template to automizer instance, I get an error that cannot find information of slide1. Checking the template info I see that the slide number start from 2.

Guess that when we cleanup the root template using removeExistingSlides: true and cleanup: true, the removing root's slide happen after the adding operations, making the new added ones start from a slide number other than 1

duchm1606 avatar Nov 13 '25 15:11 duchm1606