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

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)
Dim pPart As PackagePart = p.CreatePart(pURI, contentType,CompressionOption.Maximum)
Dim pPart As PackagePart = p.CreatePart(pURI, contentType,CompressionOption.Normal)
Dim pPart As PackagePart = p.CreatePart(pURI, contentType,CompressionOption.NotCompressed)
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 = ""
Shared relationshipNamespace As String = ""
Shared corePropertiesSchema As String = ""
Shared docPropsVTypes As String = ""
Shared slidePartNamespace As String = ""
Shared appPartNamespace As String = ""
Shared themePartNamespace As String = ""
Shared slidelayoutNamespace As String = ""
Shared slidemasterNamespace As String = ""
Shared mainpartNamespace As String = ""

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

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)

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)

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.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.

Comments (3)

  1. You’ll remember that a few days back I’ve posted a code snippet which demonstrates how to create a PowerPoint

  2. Doug Mahugh says:

    Open XML can help you skip school. I’ve covered in the past how ISVs, corporate developers, information