Reputation: 51
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
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