Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RichApi.Error: GeneralException when loading shapes in PowerPoint Online #4906

Open
elegault opened this issue Sep 18, 2024 · 3 comments
Open
Labels
Area: PowerPoint Issue related to PowerPoint add-ins Type: product bug Bug in the Office Add-ins platform or Office JavaScript APIs

Comments

@elegault
Copy link

elegault commented Sep 18, 2024

Calling ShapeCollection.load() on a collection retrieved from SlideLayout.shapes causes a RichApi.Error: GeneralException in PowerPoint Online:

{
    "stack": "RichApi.Error: GeneralException\n    at new n (https://appsforoffice.microsoft.com/lib/1/hosted/powerpoint-web-16.00.js:26:319657)\n    at i.processRequestExecutorResponseMessage (https://appsforoffice.microsoft.com/lib/1/hosted/powerpoint-web-16.00.js:26:384274)\n    at https://appsforoffice.microsoft.com/lib/1/hosted/powerpoint-web-16.00.js:26:382336",
    "message": "GeneralException",
    "name": "RichApi.Error",
    "code": "GeneralException",
    "traceMessages": [],
    "innerError": null,
    "debugInfo": {
        "code": "GeneralException",
        "message": "GeneralException",
        "errorLocation": "SlideMasterCollection.getItem",
        "statement": "var slideMaster = slideMasters.getItem(...);",
        "surroundingStatements": [
            "var root = context.root;",
            "var slideMasters = root.slideMasters;",
            "// >>>>>",
            "var slideMaster = slideMasters.getItem(...);",
            "// <<<<<",
            "var layouts = slideMaster.layouts;",
            "var layout = layouts.getItem(...);",
            "var shapes = layout.shapes;",
            "shapes.load();"
        ],
        "fullStatements": [
            "Please enable config.extendedErrorLogging to see full statements."
        ]
    },
    "httpStatusCode": 500
}

The error does not occur in PowerPoint for Windows,

Your Environment

  • Platform: Office on the web]
  • Host: PowerPoint
  • Office version number: 16.0.18029.40507
  • Operating System: Windows 11
  • Browser (if using Office on the web): Edge 128.0.2739.79 (Official build) (64-bit)

Expected behavior

The ShapeCollection is loaded and available for enumeration.

Current behavior

The error listed above occurs.

Steps to reproduce

Load this script in Script Lab:

name: Log Slides and Masters
description: Logs metadata of the selected slides and its masters
host: POWERPOINT
api_set: {}
script:
  content: |
    $("#run").on("click", getSelectedSlideIndices);

    async function run() {
      await PowerPoint.run(async (context) => {
        //Get the selected slides
        const selectedSlides = await context.presentation.getSelectedSlides();

        selectedSlides.load("items/index");
        await context.sync();

        console.log(`${selectedSlides.items.length} selected slides`);
        console.dir(selectedSlides);

        //Loop through the selected slides and log the index and id of each slide
        for (let i = 0; i < selectedSlides.items.length; i++) {
          console.log(
            `Selected slide (${i + 1} of ${selectedSlides.items.length}; index ${i}) id: ${selectedSlides.items[i].id}`
          );
        }

        const allSlides = context.presentation.slides.load("slides");
        await context.sync();

        console.log(`allSlides.items.length: ${allSlides.items.length}`);
        console.dir(allSlides);

        for (let i = 0; i < allSlides.items.length; i++) {
          console.log(`Slide ${i + 1} id: ${allSlides.items[i].id}`);
        }
      });
    }

    async function getSelectedSlideIndices() {
      Office.context.document.getSelectedDataAsync(Office.CoercionType.SlideRange, getSelectedSlideIndicesCallBack);
    }

    async function getSelectedSlideIndicesCallBack(asyncResult) {
      if (asyncResult.status === Office.AsyncResultStatus.Failed) {
        console.error(asyncResult.error.message);
      } else {
        console.log(JSON.stringify(asyncResult.value, null, 4));

        const selectedSlideIds = {};

        //Loop through the asyncResult.value.slides array and store the id of each slide in the allSlidesList object
        asyncResult.value.slides.map((slide, index) => {
          selectedSlideIds[index] = slide.index;
        });

        //Loop through the asyncResult.value.slides array and create an array of objects with the id and index properties
        const selectedSlides = asyncResult.value.slides.map((slide, index) => {
          return { id: slide.id, index: slide.index };
        });

        await processSelection(selectedSlides);
      }

      async function processSelection(slideIndices) {
        await PowerPoint.run(async function(context) {
          console.log("Selected slide indices:");
          console.log(`Processing ${slideIndices.length} selected slides...`);

          //Loop through slideIndices object
          for (let i = 0; i < slideIndices.length; i++) {
            context.presentation.slides.load("slides");
            await context.sync();

            const slide = context.presentation.slides.getItemAt(slideIndices[i].index - 1);
            slide.load("id, layout, slideMaster");
            await context.sync();

            //Get the shapes in the layout
            const shapes = slide.shapes;
            shapes.load("type");
            await context.sync();

            console.log(
              `shapes.items.length: ${shapes.items.length}; slide index: ${slideIndices[i].index}; id: ${slide.id}`
            );

            for (let j = 0; j < shapes.items.length; j++) {
              shapes.items[j].load("name, id, textFrame");
              await context.sync();

              const textFrame = shapes.items[j].textFrame;
              const textRange = textFrame.textRange;

              textRange.load("text");
              await context.sync();

              console.log(
                `Shape ID: ${shapes.items[j].id}; Shape name: ${shapes.items[j].name}; Shape text: '${textRange.text}'`
              );
            }

            //Log the slide master's metadata
            const slideMaster = slide.slideMaster;

            slideMaster.load("id, name, layouts/items/name, layouts/items/id");
            await context.sync();

            // Loop through all slide masters to find the one that matches the current slide. We have to do this because of bugs in the API if we process collections directly from the slideMaster object from a slide
            const slideMasters = context.presentation.slideMasters.load("id, name, layouts/items/name, layouts/items/id");
            await context.sync();

            for (let i = 0; i < slideMasters.items.length; i++) {
              if (slideMasters.items[i].id !== slideMaster.id) {
                continue;
              }

              console.log(`Master name: ${slideMasters.items[i].name} (id ${slideMasters.items[i].id})`);

              // Log the name and ID of each slide layout in the slide master.
              const layoutsInMaster = slideMasters.items[i].layouts;

              // Log the count of layouts
              console.log(`Processing ${layoutsInMaster.items.length} layouts in master ${slideMasters.items[i].name}...`);

              for (let j = 0; j < layoutsInMaster.items.length; j++) {
                console.log("Layout name: " + layoutsInMaster.items[j].name + " Layout ID: " + layoutsInMaster.items[j].id);
                //Possible errors in PowerPoint Online!!
                try {
                  layoutsInMaster.items[j].load();
                  await context.sync();

                  // BUG 9/16/2024: Uncaught (in promise) RichApi.Error: GeneralException. But the shapes collection IS there
                  layoutsInMaster.items[j].shapes.load();
                  await context.sync();
                } catch (error) {
                  console.error("Error:", error);
                  return;
                }

                const shapes = layoutsInMaster.items[j].shapes;

                try {
                  console.log(shapes.items.length + " shape items in layout " + layoutsInMaster.items[j].name);
                } catch (error) {
                  console.error("Error:", error);
                  return;
                }

                //Loop through the shapes collection
                for (let s = 0; s < shapes.items.length; s++) {
                  console.log(`Shape name: ${shapes.items[s].name}; Shape ID: ${shapes.items[s].id}`);
                }
              }
            }
          }
        });
      }
    }
  language: typescript
template:
  content: |-
    <button id="run" class="ms-Button">
        <span class="ms-Button-label">Log Metadata for Selected Slides and their Slide Masters</span>
    </button>
  language: html
style:
  content: |-
    section.samples {
        margin-top: 20px;
    }

    section.samples .ms-Button, section.setup .ms-Button {
        display: block;
        margin-bottom: 5px;
        margin-left: 20px;
        min-width: 80px;
    }
  language: css
libraries: |
  https://appsforoffice.microsoft.com/lib/1/hosted/office.js
  @types/office-js

  [email protected]/dist/css/fabric.min.css
  [email protected]/dist/css/fabric.components.min.css

  [email protected]/client/core.min.js
  @types/core-js

  [email protected]
  @types/[email protected]

Provide additional details

  1. Open a PowerPoint presentation
  2. Select one or more slides
  3. Click the button in the Script Lab to run the provided script

EDIT: After some testing, it appears to be happening only with a presentation created from a custom template:
PresentationFromCustomTemplate.pptx

The error does not occur with a new, blank presentation from no template:
PresentationFromNoTemplate.pptx

@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs: triage 🔍 New issue, needs PM on rotation to triage ASAP label Sep 18, 2024
@EsterBergen
Copy link

@elegault - Thanks for sharing. Do you know if this error was always happening or if this is a new error/regression?

@EsterBergen EsterBergen added the Needs: author feedback Waiting for author (creator) of Issue to provide more info label Sep 18, 2024
@elegault
Copy link
Author

@elegault - Thanks for sharing. Do you know if this error was always happening or if this is a new error/regression?

I've never worked with the shapes collections before, so I don't know if it ever worked in PowerPoint Online.

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs: attention 👋 Waiting on Microsoft to provide feedback and removed Needs: author feedback Waiting for author (creator) of Issue to provide more info labels Sep 18, 2024
@EsterBergen EsterBergen added Type: product bug Bug in the Office Add-ins platform or Office JavaScript APIs Area: PowerPoint Issue related to PowerPoint add-ins and removed Needs: attention 👋 Waiting on Microsoft to provide feedback Needs: triage 🔍 New issue, needs PM on rotation to triage ASAP labels Sep 18, 2024
@elegault
Copy link
Author

I have isolated the cause: if I rename the "Fußzeilenplatzhalter 7" footer in the slide master of the custom template to anything that doesn't have the "ß" character, the exception is not thrown! So my guess is that it is a character encoding issue of some kind! Not sure what other special characters can cause this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: PowerPoint Issue related to PowerPoint add-ins Type: product bug Bug in the Office Add-ins platform or Office JavaScript APIs
Projects
None yet
Development

No branches or pull requests

2 participants