Creating a Open XML PowerPoint presentation from scratch using System.IO.Packaging

Creating a Open XML PowerPoint presentation from scratch using System.IO.Packaging

  • Comments 3

Here is how I’ve got to create this sample – One of my customer had a similar requirement when I tried to search a sample for him to demonstrate, I couldn’t find one (blame it on my searching capabilities or whatever .. )

While creating a sample there are a few titbits that I came to know -

1)  In order to create a valid presentation you’ve got to have following parts - presentation, slide, slideLayout, slideMaster and theme

2) By default when you create a package using Packaging API it’s NOT compressed. To have a compressed package you need to specify compression option in CreatePart. Something like this   …

Dim pPart As PackagePart = p.CreatePart(pURI, contentType,CompressionOption.Fast)
'or
Dim pPart As PackagePart = p.CreatePart(pURI, contentType,CompressionOption.Maximum)
'or
Dim pPart As PackagePart = p.CreatePart(pURI, contentType,CompressionOption.Normal)
'or
Dim pPart As PackagePart = p.CreatePart(pURI, contentType,CompressionOption.NotCompressed)
'or
Dim pPart As PackagePart = p.CreatePart(pURI, contentType,CompressionOption.SuperFast)

 

The real fun part here is – you can have different parts compressed in different CompressionOption (that implies that I can have a few parts compressed and a few parts uncompressed!) – well at least this is what my testing says.

Here is the code snippet (the code is dependent on a few xmlfiles which are attached as a zip)-

 

Public Class Form1

#Region "NamespaceConstants"
Private Structure constants
Dim dummy
Shared presentationmlNamespace As String = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
Shared relationshipNamespace As String = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
Shared corePropertiesSchema As String = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
Shared docPropsVTypes As String = "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"
Shared slidePartNamespace As String = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide"
Shared appPartNamespace As String = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"
Shared themePartNamespace As String = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"
Shared slidelayoutNamespace As String = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout"
Shared slidemasterNamespace As String = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster"
Shared mainpartNamespace As String = "http://schemas.openxmlformats.org/presentationml/2006/main"

Shared mainPartContentType As String = "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"
Shared slidePartContentType As String = "application/vnd.openxmlformats-officedocument.presentationml.slide+xml"
Shared slideLayoutContentType As String = "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"
Shared appPartContentType As String = "application/vnd.openxmlformats-officedocument.extended-properties+xml"
Shared corePartContentType As String = "application/vnd.openxmlformats-package.core-properties+xml"
Shared themePartContentType As String = "application/vnd.openxmlformats-officedocument.theme+xml"
Shared slidemasterContentType As String = "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml"

End Structure


#End Region


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Using myPackage As Package = Package.Open("C:\somepath\GuineaPig.pptx", FileMode.Create, FileAccess.ReadWrite, FileShare.None)




'Add package parts app,core and doc
Dim docPart As PackagePart = CreateBasicPart(New StreamReader("C:\somepath\presentation.xml").BaseStream, myPackage, "ppt/presentation.xml", constants.mainPartContentType, constants.presentationmlNamespace)
'end add


'add other *required* parts slide,slidemaster,theme,slidelayout
'
Dim pp() As PackagePart

'add slide part

pp = New PackagePart() {docPart}
Dim slidePart As PackagePart = CreateExtendedPart(myPackage, "C:\somepath\slide1.xml", "ppt/slides/slide1.xml", constants.slidePartContentType, constants.slidePartNamespace, pp)
AdjustPartXML("//p:sldIdLst/p:sldId/@r:id", docPart, constants.slidePartNamespace)

'end add slide part

'add theme part

pp = New PackagePart() {docPart}
Dim themePart As PackagePart = CreateExtendedPart(myPackage, "C:\somepath\theme1.xml", "ppt/theme/theme1.xml", constants.themePartContentType, constants.themePartNamespace, pp)
'end add theme part

'add slide layout part
pp = New PackagePart() {slidePart}
Dim slidelayoutPart As PackagePart = CreateExtendedPart(myPackage, "C:\somepath\slidelayout1.xml", "ppt/slideLayouts/slideLayout1.xml", constants.slideLayoutContentType, constants.slidelayoutNamespace, pp)
'end add slide layout part

'add slide layout part
pp = New PackagePart() {docPart, slidelayoutPart}
Dim slidemasterPart As PackagePart = CreateExtendedPart(myPackage, "C:\somepath\slidemaster1.xml", "ppt/slideMasters/slideMaster1.xml", constants.slidemasterContentType, constants.slidemasterNamespace, pp)
AdjustPartXML("//p:sldMasterIdLst/p:sldMasterId/@r:id", docPart, constants.slidemasterNamespace)
'end add slide layout part

'add other *required* parts slide,slidemaster,theme,slidelayout

'add other relationships
AddRelationship(slidemasterPart, themePart, constants.themePartNamespace)
AddRelationship(slidemasterPart, slidelayoutPart, constants.slidelayoutNamespace)
AdjustPartXML("//p:sldLayoutIdLst/p:sldLayoutId/@r:id", slidemasterPart, constants.slidelayoutNamespace)
'end add other relationships


End Using


Me.Close()
End Sub
Public Sub AdjustPartXML(ByVal xpath As String, ByVal p As PackagePart, ByVal relationship As String)
Dim nt As New NameTable
Dim nsManager As New XmlNamespaceManager(nt)
nsManager.AddNamespace("p", constants.mainpartNamespace)
nsManager.AddNamespace("r", constants.relationshipNamespace)
Dim adoc As New XmlDocument(nt)

adoc.Load(p.GetStream())
If Not IsNothing(adoc.SelectSingleNode(xpath, nsManager)) Then
For Each r As PackageRelationship In p.GetRelationshipsByType(relationship)
adoc.SelectSingleNode(xpath, nsManager).Value = r.Id
adoc.Save(p.GetStream(FileMode.Create, FileAccess.ReadWrite))
Next r
End If
End Sub
Private Sub AddRelationship(ByVal frompart As PackagePart, ByVal topart As PackagePart, ByVal relationship As String)
frompart.CreateRelationship(topart.Uri, TargetMode.Internal, relationship)
End Sub
Private Function CreateExtendedPart(ByVal p As Package, ByVal filename As String, ByVal uri As String, ByVal contenttype As String, ByVal relationship As String, ByVal relatewith() As PackagePart) As PackagePart
Dim xmlDoc As New XmlDocument, xmlFile As New XmlDocument

Dim pURI As Uri = PackUriHelper.CreatePartUri(New Uri(uri, UriKind.Relative))
Dim pPart As PackagePart = p.CreatePart(pURI, contenttype)


For Each pp As PackagePart In relatewith
pp.CreateRelationship(pPart.Uri, TargetMode.Internal, relationship)
Next

xmlDoc.Load(filename)
xmlDoc.Save(pPart.GetStream(FileMode.Create, FileAccess.Write))
xmlDoc = Nothing
Return pPart
End Function


Private Function CreateBasicPart(ByVal fileStream As Stream, ByVal pptPackage As Package, ByVal uri As String, ByVal contentType As String, ByVal relType As String) As PackagePart

Dim documentUri As Uri = PackUriHelper.CreatePartUri(New Uri(uri, UriKind.Relative))

Dim documentPart As PackagePart = pptPackage.CreatePart(documentUri, contentType)

pptPackage.CreateRelationship(documentPart.Uri, TargetMode.Internal, relType)

Dim xmlDoc As New XmlDocument

xmlDoc.Load(fileStream)
xmlDoc.Save(documentPart.GetStream(FileMode.Create, FileAccess.Write))


Return documentPart
End Function


End Class

 

Never mind my naming conventions or using structure as a hack – look at the juice :)

By the way – when you work with Open XML one of the great help is sample documents from OpenXMLDeveloper

Whenever I get more time, I’ll expand this code snippet in a more or less generic sample. Keep watching

 



 

Not responsible for errors in content, meaning, tact, or judgment. Live and let live. Toes go in first. I didn't do it. Enjoy.

Attachment: supportfiles.zip
Leave a Comment
  • Please add 8 and 7 and type the answer here:
  • Post
Page 1 of 1 (3 items)