Branching Slides in PowerPoint (VBA) - vba

I am trying to create a back button but using hyperlinks it simply just takes me to the previous page and ends up in a loop... e.g. if I have slide 1 which has links to slide 3, 4 & 5 then slide 3 links to 6 & 7. If I'm currently on slide 7 and click back it successfully takes me back to slide 3 but then I want to click back and end up at slide 1 rather than back to slide 7 (hopefully I'm making some sense!).
I presume the only way for me to do this is with VBA can anyone give me some advice on best way to create a back button? (I'm using PowerPoint 2007)

I was struggling with a similar problem today and made a little "breadcrumb"- generator for powerpoint. There is no link feature yet, but you can implement it if you like:
Github Project
Essential parts of the code
Public Sub breadcrumbs(ByVal count As Integer, ByRef titles() As String)
Dim cntr As Integer
Dim content() As String
Dim margin As Integer
Dim width As Integer
'----------------------------
' Set Titles
content = titles
cntr = 0
' Set width
width = ((Application.ActivePresentation.PageSetup.SlideWidth - (margin * count * 2) - 20) / count) - 50
' Loop through all slides
For Each sld In Application.ActivePresentation.Slides
' generate breadcrumb for each title
For Each con In content
sld.Shapes.AddShape(1, (50 + (width * cntr)), 15, width, 50).TextFrame.TextRange.Text = con
cntr = cntr + 1
Next con
cntr = 0
Next sld
End Sub

It sounds like you want a 'breadcrumb trail' of visited slides, instead of a simple back button. Thus you need a way to preserve the trail.
This could be addressed with a dynamic array. New browsing would add records to the array. Your "Next" and "Previous" locations would be found by moving up or down the array. You'll have some mild logic puzzles. I hate to refer you a generic resource, but I'm out of specifics and an overview may be helpful.
UPDATE: I've wanted this in the past for MS Access, and thought I'd readily find a snippet solution. But now I go to search (thinking it will convert over for you easily as well), and I don't find anything. This is surprising because I imagine it would be fun to built. Or ... it's harder to build than I anticipate.

There is a really cumbersome way to do this in PPT directly with no programming. You'll need "forward-facing slides" and 2 sets of "backward-facing slides". Backwards ones are two types - direct-back and home-back. They can all be identical, but make the backward ones hidden (e.g. instead of "Slide 3" you'll need "Slide 3a" and "Slide 3b" and "Slide 3c".). They are hidden so that when you progress through normally, you won't see them, but when you link to them, they will appear. Your link list on the "a" slides should always point to the "b" slides and your "b" slides will point to the "c" slides. Your hyperlinks on "back button" on "a" slides should be "previous slide" and on the "c" slides should be "last slide viewed" and on "h" slides should be "first slide" (use 'action' to set this instead of 'hyperlink').
It takes a while to work through, but it can be done.

Related

Navigate to PPT Slide by its ID or Name instead of Number

ActivePresentation.SlideShowWindow.View.GotoSlide x requires us to enter the slide number, which is varying. If I refer it to Slide Number 3 and then move the position of Slide 3, the code wouldn't refer to that slide anymore.
How do I overcome this by referring to the SlideID or SlideName instead of Slide Number.
Thank you.
If I understand the question correctly, you want to be able to go to a particular slide in the presentation regardless of where it may appear in the presentation (ie because other slides have been added before it or it's been moved to a different position).
If so, you could tag the presentation with the slide's SlideID:
ActivePresentation.Tags.Add "IndexSlide", Cstr(lSlideID)
(where IndexSlide is any convenient name you've assigned to the slide; you can have multiple tags for different slides you want to track. And lSlideID is, of course, the slide's SlideID
You'd need to write a function to retrieve the slide's SlideIndex, given the SlideID and call it like so (aircode ... you might have to move/remove a paren or two):
ActivePresentationSlideShowWindow.View.GoToSlide ( _
SlideIndexFromSlideID(cLng(ActivePresentation.Tags("IndexSlide")))
This gets the tag named IndexSlide from the presentation which is the SlideID of IndexSlide, converts it to a Long (tags are strings), passes it to your SlideIndexFromSlideID function, which returns the slide's current SlideIndex ... for you to GoToSlide with.
[Later: adding the needed function for returning SlideIndex]
Function SlideIndexFromSlideID(lSlideID As Long) As Long
SlideIndexFromSlideID = ActivePresentation.Slides.FindBySlideID(lSlideID).SlideIndex
End Function

How to find the label of a shape on a Powerpoint slide

Can someone please point me in the right direction to finding the label Powerpoint uses for each shape, active x control, etc... I've researched till I'm blue in the face. Here's what I'm talking about:
I have a very simple slideshow that asks a question in a text box. Just below the question I placed an active x control text box to get the user's answer. All I want to do is take the answer and append it to a text file. Here's the code:
Public Sub WriteAnswerToFile(slideNum As Integer, shapeNum As String)
Dim filePath As String
Dim objFSO As FileSystemObject
Dim objFile As Variant
filePath = "C:\Batch Files\Powerpoint\ButtonPushes\AnswerFile.txt"
Const ForAppending = 8
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Batch Files\Powerpoint\ButtonPushes\AnswerFile.txt", ForAppending)
objFile.WriteLine (Application.ActivePresentation.Slides(slideNum).Shapes(shapeNum).TextFrame.TextRange)
objFile.Close
End Sub
From each slide, I pass the slide number and the shape designator to the sub routine. The shapeNum is a string because I found that it worked (no better reason than that) for me to pass something like "TextBox 1" as the param. It all works absolutely great if I know the Shape(designator); as in Shape(TextBox1). For the life of me I cannot figure out how to pass the text input by the user into the active x control text box. I have no idea what the designator is. The property sheet for the text input box calls it TextBox1. The Code sheet calls it TextBox1. When I pass that parameter, it prints the question I asked, not the answer, to my text file. I don't know how to call the input text box in my code.
My code prints "How did you hear about us?" to my text file when my code runs with Call WriteAnswerToFile(2, "TextBox 1"). I'm sure that textbox is called textbox 1; it's the first textbox on the slide. I just don't know what Powerpoint labels the user input box.
If there is some sort of Powerpoint scripting or layout page that will define all the shapes in the slidewhow, I'd sure like to be pointed that direction.
You just need to refer to the form part of the Object since this is not a normal shape.
objFile.WriteLine (Application.ActivePresentation.Slides(slideNum).Shapes(shapeNum).OLEFormat.Object.Text)
To clarify from your comment. I think that you have two "Text Box 1". One is "TextBox 1" (note the space) which is the normal textbox and the ActiveX control is "TextBox1" (no space).
If I create a new blank slide and first add a normal text box and then an ActiveX textbox and then run the following code:
For Each shp In Slide2.Shapes
Debug.Print shp.Name
Next shp
The Immediate window will show the following:
TextBox 1
TextBox1
By chance I happened to stumble upon the simplest answer to my question of "finding the label Powerpoint uses for each shape, active x control, etc.."
I am using the Office 16 (Office 365) suite that contains Powerpoint and would not be certain this feature is avaiable to other versions.
On the Home tab in Powerpoint there is an Editing submenu that contains a Select function. As pictured here:
When you click on Select, another submenu appears that shows a Selection Pane function. If you click on that, the selction pane shows up on the right hand of the screen. In that pane you will see all of the objects on the current slide and the names Powerpoint has given to each of them.
It shows there, the discrepancy I was having with calling TextBox(Space)1 and TextBox(NoSpace)1.
This works to be much more expedient for me to grab the name of the shape I want to call in my VBS Scripts.
I am thankful; however, for the time and frustration #Diederik Sieburgh saved me in allowing me to move forward with my project as it is now 2 weeks later that I stumbled upon this information.

How to assign Textshape 1 as the title?

With Office 2016 PPT, after sharing a PPT file and getting it back, it now has retained titles on the slides but they are now "TextShape 1", are in the correct location (top of slide), and do not show up as titles in the outline view, etc.
Merely resetting the slides overlays empty boxes.
How can I make "TextShape 1" on each of the slides to be seen as the Title for the respective slides? A redefinition? Add a new Title box with the content of "TextShape 1", and delete the old box?
Thanks for the views.
It was not easy as a vba-powerpoint beginner finding my way through the collections and terminology, and certainly time consuming, but I wrote a solution for the limited problem as presented.
You might think you could add a title object, but at least the way I tried, it complained that that could not be done with the current slide layout. I could not figure out how to designate a text box as a Title. So I used vba to set the formats to Titleonly for slides without one, copied the text into it, then deleted the old shape that was overlaid with the new one as below:
Attribute VB_Name = "Module1"
Sub newtitles()
Dim s As Variant
For s = 1 To ActivePresentation.Slides.Count
If Not ActivePresentation.Slides(s).Shapes.HasTitle Then
ActivePresentation.Slides(s).Layout = ppLayoutTitleOnly
' adds a title placeholder too; could not .addtitle to slide without a title in format
ActivePresentation.Slides(s).Shapes.Title.TextFrame.TextRange.Text = ActivePresentation.Slides(s).Shapes(1).TextFrame.TextRange.Text
ActivePresentation.Slides(s).Shapes(1).Delete ' remove redundant box
End If 'about title
Next ' slides
End Sub

How to show/hide data from a table in Powerpoint?

I'm trying to have several slides with tables, each table has 3 columns, the last column is the "reference value" and I want it to be hidden during the presentation and show it only by pressing a button or a hyperlink, each row individually. I think it's possible because I'm really new at coding and I have managed to do it by changing the cell's text format from white (which is the table's background color) to red, but I can only do it for all the tables at once, and I need individual values on each one of them. (I hope I'm making myself clear). This is what I have done so far:
Sub format()
Dim s As Slide
Dim oSh As Shape
Dim oTbl As Table
For Each s In ActivePresentation.Slides
For Each oSh In s.Shapes
If oSh.HasTable Then
Set oTbl = oSh.Table
With oTbl.Cell(2, 3).Shape.TextFrame.TextRange
.Text = "4500-9000"
.Font.Size = 12
.Font.Color = vbRed
End With
End If
Next
Next s
End Sub
But this will change the same cell on every table I have, I want it to change specific cells in specific tables one by one, since they all have different valued. I know I could do this with animations, but I'd rather do it this way.
EDIT: It would be great if, instead of pressing a button, I could get the data by hovering the pointer over the empty cell, and have it hidden away again when I hover the cursor off the cell.
In any case, whenever I do any change to the presentation during slideshow, the change will still be there at the end, which means It would only work once and then I would have to fix and hide all the values again, is there a way to restore the changes done during the presentation when it ends?
you could adpt your sub and call it from another procedure by passing a reference to the table and cell you want to process like this:
Sub FormatTableCell(oTbl As Shape, lRow As Long, lCol As Long)
With oTbl.Cell(lRow, lCol).Shape.TextFrame.TextRange
.Text = "4500-9000"
.Font.Size = 12
.Font.Color = vbRed
End With
End Sub
For example:
With ActivePresentation
FormatTableCell .Slides(1).Shapes("MyTable"), lRow:=1, lCol:=1
End With
Regarding the triggers for hover over and hover out, this is a tricky aspect of PowerPoint. There IS a trigger to run code when hovering over a shape but there is NOT a trigger for hovering out of a shape. To achieve the latter, you could put a transparent rectangle in the back layer of your slide and use that to spoof the hover out trigger by linking a hover over macro to it. Write your code and use the Insert / Action / Mouse Over function to trigger your VBA procedure with a signature like this:
Public Sub FormatThisTable(oTbl As Shape)
Note that this method only passes the shape (a table in your case) and not the cell the mouse is hovering over. The only way I can see you could achieve that would be to use a lot of very complex Windows APIs to detect the mouse cursor position relative to the table's on-screen coordinates.
Alternative approaches could either be to ungroup the table to a set of separate shapes or create cover shapes for each cell you need to show/hide and manage their visibility properties using the mouse in/out technique above.
For the last point, you will need to use application level events which requires code in a class module and this a good article to show you how:
http://www.pptfaq.com/FAQ00004_Make_your_VBA_code_in_PowerPoint_respond_to_events.htm
Step 1
Launch PowerPoint and open the PPTX file that contains the rows you want to hide. Click the appropriate slide in the Slides pane to the left of the screen.
Step 2
Double-click the spreadsheet on the slide, which will allow you to edit it. Select the rows that you want to hide. Click the “Home” tab and locate the “Cells” section. Click the “Format” option, which will display a list of available features.
Step 3
Place the pointer over the “Hide & Unhide” listing in the “Visibility” section. Click the “Hide Rows” option to hide the selected rows. Click outside the spreadsheet to return to the PowerPoint slide.

powerpoint, vba, generate a random number from a specific set

VBA - how can i generate a random number within the specific set 3,5,7,9,11,13.
these numbers represent slide numbers (destinations) which the user will be taken to when a button is clicked.
Edit: Modified to include a more comprehensive solution at request of OP
Objective: Randomly select one of six possible slide numbers to display following the click of a button.
Step 1: Code to randomize slide number selection
Map the target values into an array. Note the number of elements in the resultant array - in this case, 6. Generate a random integer from 1 to 6, and use that value as an index into the array, returning the value at that index position.
Something like the following (untested)
function randomSlideNumber() as Integer
Dim index
Dim targetValues(1 to 6) as Integer
targetValues(1) = 3
targetValues(2) = 5
targetValues(3) = 7
targetValues(4) = 9
targetValues(5) = 11
targetValues(6) = 13
index = Int(6 * Rnd + 1)
randomSlideNumber = targetValues(index)
end function
Step 2: Add slides to a Powerpoint presentation up to the number desired in the random selector
I'm assuming the OP already has at least 13 slides in his presentation :)
Step 3: Add an additional slide to the presentation, and add a CommandButton to it
With the new slide active in Powerpoint, click the 'Developer' tab.
Select a CommandButton from the Controls toolbar, and draw it onto the new slide.
Double-click the CommandButton. This should open the VBA editor with a stub Click event handler for the CommandButton, called CommandButton1_Click().
Modify the handler code as follows:
P
Private Sub CommandButton1_Click()
SlideShowWindows(1).View.GotoSlide randomSlideNumber
End Sub
Step 5: Start the slide show, using the slide with the new CommandButton as the starting point
With the new slide active, select the "Slide Show" tab from the ribbon bar
Click "From Current Slide" from the "Start Slide Show" bar.
Step 6: Click the CommandButton on the slide, and verify that the active slide changes to one of those returned by the randomSlideNumber() function
Voila! :)
Code Discussion
Note: This involves a little detail about the PowerPoint VBA object model.
Clicking the CommandButton in the slide created in Step 3 fires the CommandButtton1_Click() event handler created in Step 4. The event handler then goes to the current View of the first SlideShowWindow object SlideShowWindow(1).View, and calls the GotoSlide method of the View. The GotoSlide method expects a slide number as a parameter, which is provided by the call to the 'randomSlideNumber' function defined earlier. That function should return one of 3, 5, 7, 9, 11, or 13.
That should do the trick.
Caveats: There is obviously no error handling in this code; its addition is left as an exercise. Further, this has not been extensively tested against the very latest version of Powerpoint, but did work in the test shell I created.