Andrew Siddel
Andrew Siddel

Reputation: 51

Stream editing OpenXml powerpoint presentation slides

I am trying to edit the XML stream of Powerpoint slides using OpenXml and Streamreader/Streamwriter.

For a word document, it's easy:

Imports System.IO
Imports DocumentFormat.OpenXml
Imports DocumentFormat.OpenXml.Packaging
Imports DocumentFormat.OpenXml.Presentation
Imports DocumentFormat.OpenXml.Wordprocessing

'  
'
'
' Open a word document
CurrentOpenDocument = WordprocessingDocument.Open(TheWordFileName, True)

' for a word document, this works

Using (CurrentOpenDocument)
    ' read the xml stream
    Dim sr As StreamReader = New StreamReader(CurrentOpenDocument.MainDocumentPart.GetStream)
    docText = sr.ReadToEnd
    ' do the substitutions here
    docText = DoSubstitutions(docText)

    ' write the modified xml stream
    Dim sw As StreamWriter = New StreamWriter(CurrentOpenDocument.MainDocumentPart.GetStream(FileMode.Create))
    Using (sw)
        sw.Write(docText)
    End Using

End Using

But for Powerpoint (presentations), I find that the inserted modified XML stream for the slideparts do not get saved:

Imports System.IO
Imports DocumentFormat.OpenXml
Imports DocumentFormat.OpenXml.Packaging
Imports DocumentFormat.OpenXml.Presentation
Imports DocumentFormat.OpenXml.Wordprocessing

'                    
'
' Open a powerpoint presentation 
CurrentOpenPresentation = PresentationDocument.Open(ThePowerpointFileName, True)

' for a powerpoint presentation, this doesn't work
Using (CurrentOpenPresentation)

    ' Get the presentation part of the presentation document.
    Dim pPart As PresentationPart = CurrentOpenPresentation.PresentationPart

    ' Verify that the presentation part and presentation exist.
    If pPart IsNot Nothing AndAlso pPart.Presentation IsNot Nothing Then
        ' Get the Presentation object from the presentation part.
        Dim pres As Presentation = pPart.Presentation

        ' Verify that the slide ID list exists.
        If pres.SlideIdList IsNot Nothing Then
            ' Get the collection of slide IDs from the slide ID list.
            Dim slideIds = pres.SlideIdList.ChildElements

            ' loop through each slide
            For Each sID In slideIds
                Dim slidePartRelationshipId As String = (TryCast(sID, SlideId)).RelationshipId
                Dim TheslidePart As SlidePart = CType(pPart.GetPartById(slidePartRelationshipId), SlidePart)
                ' If the slide exists...
                If TheslidePart.Slide IsNot Nothing Then

                    Dim sr As StreamReader = New StreamReader(TheslidePart.GetStream)
                    Using (sr)
                        docText = sr.ReadToEnd
                    End Using
                    docText = DoSubstitutions(docText)

                    Dim sw As StreamWriter = New StreamWriter(TheslidePart.GetStream(FileMode.Create))
                    Using (sw)
                        sw.Write(docText)
                    End Using

                End If
            Next
    End If
End Using

I've also tried iterating through the in-memory slideparts to check the XML stream, and they ARE changed.

It's just that this never gets saved back to the file in the dispose (end using) and no error exceptions are raised.

Has anyone else experienced this?

Upvotes: 2

Views: 576

Answers (1)

Andrew Siddel
Andrew Siddel

Reputation: 51

After about a week of messing around with this, I came upon the answer. It is to reference the slideparts from the collection instead of referencing via the relationship Id's, although I don't know why this works and the initial approach doesn't:

' This DOES work
Using (CurrentOpenPresentation)
    ' Get the presentation part of the presentation document.
    Dim pPart As PresentationPart = CurrentOpenPresentation.PresentationPart

    ' Verify that the presentation part and presentation exist.
    If pPart IsNot Nothing AndAlso pPart.Presentation IsNot Nothing Then

        ' reference each slide in turn and do the Substitution
        For Each s In pPart.SlideParts
            Dim sr As StreamReader = New StreamReader(s.GetStream)
            Using (sr)
                docText = sr.ReadToEnd
            End Using
            docText = DoSubstitutions(docText)

            Dim sw As StreamWriter = New StreamWriter(s.GetStream(FileMode.Create))
            Using (sw)
                sw.Write(docText)
            End Using
        Next
    End If
End Using

Upvotes: 2

Related Questions