0

I have a small console program that I'm writing that uses the Open XML SDK 2.0. I basically just want to get all pictures on a PowerPoint slide. When I run the program, though, I get the following error:

Cannot access part because parent package was closed.

My ppt only has one slide with one image. This is just a prototype program. I'm not familiar with Open XML SDK 2.0, so I'm not sure what this error is telling me and how to fix it. I'm hoping someone can point me in the right direction. Here is my code:

using System;
using System.Collections.Generic;
using DocumentFormat.OpenXml.Presentation;
using A = DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml;
using System.Text;
using System.Data;
using System.Linq;
namespace OpenXmlDemo
{
    public class Program
    {
        static void Main(string[] args)
        {
            var file = @"C:\Users\kjennings\Desktop\Test PPTs\This is the Title - Copy.pptx";
            var index = 0;
            var slidePart = GetSlidePart(file, index);
            var images = slidePart.Slide.Descendants<Picture>().Select(p => p); // error occurs here

            foreach (var image in images)
            {
                // Just placeholder code below.  It never makes it here.
                var pic = image;
            }
        }

        public static SlidePart GetSlidePart(string docName, int slideIndex)
        {
            using (var ppt = PresentationDocument.Open(docName, false))
            {
                // Get the relationship ID of the first slide.
                var presentationPart = ppt.PresentationPart;

                // Verify that the presenation part and the presenation exist,
                if (presentationPart != null && presentationPart.Presentation != null)
                {
                    var presentation = presentationPart.Presentation;

                    if (presentation.SlideIdList != null)
                    {
                        var slideIds = presentation.SlideIdList.ChildElements;

                        if (slideIndex < slideIds.Count)
                        {
                            // Get the relationship ID of the slide.
                            var slidePartRelationship = (slideIds[slideIndex] as SlideId).RelationshipId;

                            // Get the specified slide part from the relationship ID.
                            var slidePart = (SlidePart)presentationPart.GetPartById(slidePartRelationship);

                            return slidePart;
                        }
                    }
                }

                // No slide found.
                return null;
            }
        }
    }
}
Kevin
  • 4,798
  • 19
  • 73
  • 120

1 Answers1

2

The using statement in GetSlidePart is closing the document. From the documentation for PresentationDocument.Dispose:

Flushes and saves the content, closes the document, and releases all resources.

If you refactor the opening of the document to outside of GetSlidePart your code should work as expected:

static void Main(string[] args)
{
    var file = @"C:\Users\kjennings\Desktop\Test PPTs\This is the Title - Copy.pptx";
    var index = 0;

    //open the document here for use throughout the application
    using (var ppt = PresentationDocument.Open(file, false))
    {
        var slidePart = GetSlidePart(ppt, index);
        var images = slidePart.Slide.Descendants<Picture>().Select(p => p);

        foreach (var image in images)
        {
            // Just placeholder code below.  It now gets here...
            var pic = image;
        }
    }
}

//pass the open document in here...
public static SlidePart GetSlidePart(PresentationDocument ppt, int slideIndex)
{
    // Get the relationship ID of the first slide.
    var presentationPart = ppt.PresentationPart;

    // Verify that the presenation part and the presenation exist,
    if (presentationPart != null && presentationPart.Presentation != null)
    {
        var presentation = presentationPart.Presentation;

        if (presentation.SlideIdList != null)
        {
            var slideIds = presentation.SlideIdList.ChildElements;

            if (slideIndex < slideIds.Count)
            {
                // Get the relationship ID of the slide.
                var slidePartRelationship = (slideIds[slideIndex] as SlideId).RelationshipId;

                // Get the specified slide part from the relationship ID.
                var slidePart = (SlidePart)presentationPart.GetPartById(slidePartRelationship);

                return slidePart;
            }
        }
    }

    // No slide found.
    return null;
}
petelids
  • 12,305
  • 3
  • 47
  • 57