Creating and modifying PowerPoint presentations (end-to-end sample)
We’re drawing our PowerPoint series to a close and it only makes sense to end with an “end-to-end” sample. See what I did there? We’ve covered the base objects and provided code samples. Today, I’ll tie them together in a single add-in that supports a specific business use case. This PowerPoint add-in does the following:
- Provides a custom PowerPoint ribbon
- Allows the user to quickly create new presentations
- from a library of company templates, or…
- create a blank presentation
- Allows the user to insert standard company content into the selected PowerPoint shape.
If you want to say to yourself that this list sounds vanilla, I’ll grant you that. However, I have a couple of surprises to mix things up:
- The custom ribbon will dynamically create ribbon buttons for each presentation template residing in a specific directory.
- The ribbon will also dynamically create ribbon buttons for standard content residing in an Access database.
These two items add just enough to make this a challenging add-in.
- Creating the PowerPoint add-in project
- Building the custom PowerPoint ribbon
- Creating a new presentation from template
- Create a blank presentation
- Modifying a presentation by working with external data
Creating the PowerPoint add-in project
For this sample, we will create an Add-in Express based COM add-in project that targets PowerPoint 2007 – 2013. If you want plan to actively follow along and build the sample, please open Visual Studio and complete the following steps:
- In the New Project dialog, select the ADX COM Add-in project.
- Name the project PPTSample and click the OK button.
- In the New Microsoft Office COM Add-in dialog, select Visual Basic project as the programming language (you can also choose C# or C++.NET for your development).
- Set the minimum supported Office version to Microsoft Office 2007 and click Next.
- Select Microsoft PowerPoint as the supported application and click next.
- Click Finish and you will soon have a COM add-in project in Visual Studio.
- Open AddinModule in design view.
We also need an ImageList control to contain the icons for the ribbon. Go ahead and add this control the AddInModule. Set the ImageSize property to 32, 32 and set the ColorDepth to Depth32Bit. You will need to add three, 32×32 icons to the ImageList’s Images collection. This is a sample add-in… pick something that amuses you.
You are now ready to build the custom PowerPoint ribbon’s UI using our world-famous visual designer.
Building the custom PowerPoint ribbon
For the custom ribbon you need to add an ADXRibbonTab control the AddinModule’s design surface. After you add it, click it to show its visual designer (if you don’t see it, you need to expand it by clicking the chevron in the lower right-hand corner of the design view.). Set the following properties for the ribbon:
- Name = CustomRibbon
- Caption = COMPANY TEMPLATES
- Ribbons = PowerPointPresentation
Now, use the following table to complete the ribbon design.
|Control||Parent||Properties & Values|
|ADXRibbonMenu||AdxRibbonGroup1||Name – mnuTemplatesCaption= Create a new presentation from a company-approved templateImageList=ImageList1Image=0
|ADXRibbonButton||AdxRibbonGroup1||Name – btnBlankPPTCaption= Blank TemplateImageList=ImageList1Image=3
|ADXRibbonMenu||AdxRibbonGroup1||Name – mnuStandardContentCaption= Insert standard contentImageList=ImageList1Image=1
Upon completion of these steps, the ribbon design should closely resemble this screenshot:
Populating the menu control
The ADXRibbonMenu control is the only ribbon control we can populate dynamically. When the user clicks the mnuTemplates control, we want the add-in to create buttons for each presentation it finds in the templates folder.
Const TEMPLATEPATH As String = "C:\[INSERT YOUR FOLDER PATH HERE] " Private Sub mnuTemplates_OnCreate(sender As Object, _ e As ADXRibbonCreateMenuEventArgs) Handles mnuTemplates.OnCreate e.Clear() Dim dir As New DirectoryInfo(TEMPLATEPATH) Dim files As FileInfo() = dir.GetFiles() For Each file As FileInfo In files 'add the controls to the menu If Not e.Contains(file.Name) Then Dim newBtn As ADXRibbonButton = New ADXRibbonButton newBtn.Id = file.Name newBtn.Caption = file.Name AddHandler newBtn.OnClick, AddressOf Me.TemplateButton_OnClick e.AddControl(newBtn) End If Next file End Sub
Before I explain this method, I have a couple of caveats. First, this is a sample so I don’t mind using a constant to specify my file path. Second, I assume every file in the folder is a PowerPoint file.
The OnCreate method of the ADXRibbonMenu control executes when the user clicks the control. It is the ideal time to change the menu if needed. In this event, the code looks in the templates folder (the TEMPLATEPATH constant) and loops through each file. For each file, the code checks if it already exists in the menu (e.Contains…). If the file is not already listed in the menu, the code creates a new ADXRibbonButton control, sets its properties, and adds it.
Notice the ID and Caption properties use the file name. Setting the ID in this way (filename and extension makes life easier later).
Thus, if the folder receives any new files, the next time the user clicks this menu, the new files will display in the menu.
Creating a new PowerPoint presentation from template
I bet you noticed I didn’t explain something from the above sample. That something is the call to AddHandler. This call creates an OnClick event for the newly added button and tells it to call a certain method. That method is the TemplateButton_OnClick method. By creating the event handler for the button, this event will execute when the user clicks one of the ribbon buttons residing in the mnuTemplates control.
Private Sub TemplateButton_OnClick(sender As Object, _ control As AddinExpress.MSO.IRibbonControl, pressed As Boolean) Dim ppt As PowerPoint.Presentation = Nothing Dim layout As PowerPoint.CustomLayout = Nothing ppt = OpenNewPPT(TEMPLATEPATH & control.Id) layout = ppt.Slides(1).CustomLayout ppt.Slides.AddSlide(1, layout) ppt.Slides.AddSlide(2, layout) If Not layout Is Nothing Then Marshal.ReleaseComObject(layout) If Not ppt Is Nothing Then Marshal.ReleaseComObject(ppt) End Sub
This method creates a new presentation file via a call to the OpenNewPPT function (explained below). Notice the path combines the TEMPLATEPATH constant along with the filename that is the control’s ID property.
Using the returned file, the method references the custom layout of the first slide then creates two additional slides with the same layout.
The OpenNewPPT function creates a new presentation file by opening the file corresponding to the clicked button.
Private Function OpenNewPPT(filePath As String) As PowerPoint.Presentation Dim newPPT As PowerPoint.Presentation = Nothing Dim ppts As PowerPoint.Presentations = PowerPointApp.Presentations newPPT = ppts.Open(filePath, _ Microsoft.Office.Core.MsoTriState.msoFalse, _ Microsoft.Office.Core.MsoTriState.msoTrue, _ Microsoft.Office.Core.MsoTriState.msoTrue) Marshal.FinalReleaseComObject(ppts) Return newPPT End Function
The function returns this opened file as its value. What happens next is up to the calling method.
Create a blank PowerPoint presentation
Templates are nice and can be a boon to productivity. But what if they inhibit creativity? What if the user is of the opinion that “My template is a blank piece of paper”? In this case, we need to satisfy this user and provide them with an easy way to create a blank presentation.
The btnBlankPPT‘s click event creates a new presentation and adds two slides to it.
Private Sub btnBlankPPT_OnClick(sender As Object, _ control As IRibbonControl, pressed As Boolean) Handles btnBlankPPT.OnClick Dim ppts As PowerPoint.Presentations = PowerPointApp.Presentations Dim ppt As PowerPoint.Presentation = Nothing Dim layout As PowerPoint.CustomLayout = Nothing Dim slide As PowerPoint.Slide = Nothing ppt = ppts.Add() layout = ppt.SlideMaster.CustomLayouts.Item(1) slide = ppt.Slides.AddSlide(1, layout) slide.Layout = PowerPoint.PpSlideLayout.ppLayoutTitleOnly slide = ppt.Slides.AddSlide(2, layout) slide.Layout = PowerPoint.PpSlideLayout.ppLayoutTextAndTwoObjects If Not slide Is Nothing Then Marshal.ReleaseComObject(slide) If Not layout Is Nothing Then Marshal.ReleaseComObject(layout) If Not ppt Is Nothing Then Marshal.ReleaseComObject(ppt) If Not ppts Is Nothing Then Marshal.ReleaseComObject(ppts) End Sub
This code is similar to creating a presentation from a template. The big difference is a blank presentation does not have any slides. To apply a custom layout to the new slides, we have to access the slide master. This sample does that and then applies the ppLayoutTitleOnly and ppLayoutTextAndTwoObjectslayout formats.
Modifying a presentation by working with external data
After creating a new presentation from a library of templates, it stands to reason the user might want to incorporate some standard content. The following code supports this scenario.
Add menu items using the database
Like the mnuTemplates control earlier, the mnuStandardContent control’s menu dynamically populates with ribbon buttons. In this case, the buttons represent strings of text that reside in an Access database. The table in the database is very simple and I’ll leave it to you to check it out in this article’s source code. Besides, the sample code reveals its structure.
The OnCreate event of the mnuStandardContent control retrieves items from the database, adds buttons to the ribbon menu, and adds the OnClick event handler to the newly created buttons.
Private Sub mnuStandardContent_OnCreate(sender As Object, _ e As ADXRibbonCreateMenuEventArgs) Handles mnuStandardContent.OnCreate e.Clear() Dim cnn As OleDbConnection = New OleDbConnection() cnn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" + _ "Data Source=C:\PPTSample\Templates\PresentationContent.accdb " + _ ";Persist Security Info=False;" Dim sql As String = "SELECT ItemID, ContentName, ContentValue " + _ "From StandardContent ORDER BY ContentName;" Dim cmd As OleDbCommand = New OleDbCommand(sql, cnn) cnn.Open() Dim reader As OleDbDataReader = cmd.ExecuteReader() If reader.HasRows Then While reader.Read If Not e.Contains(reader(1).ToString()) Then Dim newBtn As ADXRibbonButton = New ADXRibbonButton 'Make sure you use more than a single Char.s newBtn.Id = "ContentID" & reader(0).ToString() newBtn.Caption = reader(1).ToString() AddHandler newBtn.OnClick, AddressOf Me.ContentButton_OnClick e.AddControl(newBtn) End If End While End If End Sub
For this PowerPoint sample to work on your system, be sure to edit the connection string to point to correct database location.
Modify slides with external data
We are close to finished. As the last trick in our sample, we will edit the currently selected object by clicking on the standard content button options. When the user clicks the button, its OnClick event retrieves the content from the database and inserts it into the current object.
Private Sub ContentButton_OnClick(sender As Object, _ control As AddinExpress.MSO.IRibbonControl, pressed As Boolean) Dim id As Integer = Right(control.Id, Len(control.Id) - Len("ContentID")) Dim cnn As OleDbConnection = New OleDbConnection() cnn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" + _ "Data Source=C:\PPTSample\Templates\PresentationContent.accdb " + _ ";Persist Security Info=False;" Dim sql As String = "SELECT ContentValue From StandardContent " + _ "Where ItemID=" & id & ";" Dim cmd As OleDbCommand = New OleDbCommand(sql, cnn) cnn.Open() Dim reader As OleDbDataReader = cmd.ExecuteReader() Dim window As PowerPoint.DocumentWindow = PowerPointApp.ActiveWindow Dim selection As PowerPoint.Selection = window.Selection Dim reader As OleDbDataReader = cmd.ExecuteReader() If reader.HasRows Then While reader.Read Dim range As PowerPoint.TextRange = selection.TextRange If range IsNot Nothing Then range.Text = reader(0).ToString() Marshal.ReleaseComObject(range) End If End While End If Marshal.ReleaseComObject(selection) Marshal.ReleaseComObject(window) End Sub
The code identifies the correct database record by pulling the ID from the events control parameter. Remember, when we created the control, we inserted “ControlID” + the table record ID as the control’s ID parameter. Therefore, to find the record ID, we essentially remove “ControlID” from the string and we have the record ID.
With the record ID known, the code queries the database and inserts the text. BAM!
There is ton of stuff to be done with PowerPoint… so don’t neglect it! This sample is simple but it is based on a real-world example. Get out there and learn the PowerPoint object model and build something great.
This sample PowerPoint add-in was developed using Add-in Express for Office and .net: