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

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.

Related

VBA - Output Slide Name to a text box PowerPoint

I am trying to copy the slide name (not the title) for a slide to appear within a text box on the same slide. I can get the entire list of slide names to output to an external file or appear in the Immediate Window. Is there some sort of copy/paste syntax or isolated output that will work?
The expectation for stackoverflow questions is that you show your working code, so people can see what you've tried, adding context to the question that you're asking. However maybe try something like this, which simply adds a textbox containing the slide name to each slide:
Option Explicit
Public Sub SlideNames()
Dim WorkSlide As Slide
Dim WorkTextBox As Shape
For Each WorkSlide In Application.ActivePresentation.Slides
Set WorkTextBox = WorkSlide.Shapes.AddTextbox(msoTextOrientationHorizontal, 10, 10, 100, 20)
WorkTextBox.TextFrame.TextRange.Text = WorkSlide.Name
Next
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.

Running a VBA script from a button after selecting a chart

I’m running Excel 2010 on Windows 7.
I have four charts on a worksheet. What I want to do is select one of the charts and then click a button to open the ‘Format Axis’ dialogue box. I found the following code online to open the dialogue box. If I select a chart and then run the code from the toolbar (Developer tab, Macros, select macro, press ‘Run’), it works well.
Sub formatXAxis1()
ActiveChart.Axes(xlCategory).Select
Application.CommandBars.ExecuteMso "ChartFormatSelection"
End Sub
The trouble I have is when the VBA script is assigned to a button. If I use a shape as the button, I get “Run-time error ‘91’: Object variable or With block variable not set”. I get the same error if I use an ActiveX Command Button. However, with a Form Control button it works as expected. The only problem with this solution is that it is not possible to change the background colour of the button so it looks out of place against the other macro calling buttons on the worksheet.
I'm guessing that in the first two cases (shape and ActiveX buttons), VBA drops or loses the chart selection when I press the button – even though the chart still appears selected on screen. Is there a fix for this, or am I doing something wrong?
For an ActiveX button, in the Properties set the property
TakeFocusOnClick
to False. That will cause Selection to keep on the chart rather than switch to the button and your code should work. The color can also be changed from the properties box, though you probably already know that.
You need to reference the chart by name. So either have 4 buttons (one for each chart), or ask the user to input the name of the chart, then:
Dim co as ChartObject
Dim c as Chart
Dim NameOfChart as String
NameOfChart = Inputbox("Enter name of chart")
Set co = ActiveSheet.ChartObjects(NameOfChart)
Set c = co.chart
c.Axes(xlCategory).Select
Application.CommandBars.ExecuteMso "ChartFormatSelection"

How to reset Excel internal button count?

I have an an Excel sheet that uses VBA to generate some form control buttons on the fly.
the buttons are cleared and then new buttons are created.
I have noticed that even though old buttons are deleted Excel is keeping an internal register of each button. New buttons have button name of over 11K
I don't know if there is some sort of limit excel will allow for this and I don't want to run out of buttons.
I am not sure if this growing registry of buttons past is causing the file size to grow.
I would like to be able to reset the increment back to 0
Anyone have any idea how I can go back to button_0 ? (without starting a whole new Excel sheet)
Seems internal button count is sheet specific. Solution is to copy sheet, rename old sheet, then rename new sheet to old sheet name. Then delete old sheet. Viola! button count reset.
I found the answer somewhere in a forum, but I couldn't retrace it.
You could also pragmatically create the button by a function/sub-routine as a workaround.
Example: below function adds a button and limits the count to a fixed number (in my case, it is the total buttons available).
In my sheet, the first button is named "Button 687" (before I use the macro) and the second button is named "Button 2".
But, it is quite not dynamic when you want to add Drop Down or other form control etc. Macro recording helps you figure out the syntax, methods and properties of the form control you want to add though.
I am not sure why "buttons" is not listed in Properties/Methods after you typed "Activesheet." but Activesheet.Buttons(1).Name or Activesheet.buttons.add are valid codes.
Public Sub Add_Button(ButtonLabel$, ButtonSize#, BFontSize#, BFontName$)
Dim Button__ As Object
Dim One_Unit#: Per_Unit = Application.CentimetersToPoints(1)
'Creates a button at the sheet's first cell (row 1, col 1) with the height and width being 1cm.
Set Button__ = ActiveSheet.Buttons.Add(1, 1, One_Unit, One_Unit)
'button count will be restricted to the number set by user.
With Button__
.Name = "Button " & ActiveSheet.Buttons.Count
With .Characters
.Text = UCase(BLabel)
.Font.Name = BFontName
.Font.Size = BFontSize
End With
End With
End Sub
Sub AddAButton()
Add_Button BLabel:="SAVE"
Debug.Print ActiveSheet.Buttons(ActiveSheet.Buttons.Count).Name
End Sub

Branching Slides in PowerPoint (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.