Search code examples
vbapowerpoint

Clicking on a shape and displaying its text on the random slide it takes me to


I want to click on a shape, with text in it, and have it take me to a random slide. On that random slide, I want the text from the shape I clicked on to be displayed.

My code takes me to a random slide, but won't display the text.

Dim lowestSlide As Integer
Dim highestSlide As Integer
Dim r As Integer

Sub PlayGame(lowestSlide As Integer, highestSlide As Integer)
    RandomSlide lowestSlide, highestSlide
    SlideShowWindows(1).View.GotoSlide (r)
    AddLetterToSlide
End Sub

Sub RandomSlide(lowestSlide As Integer, highestSlide As Integer)
    Dim slideCount As Integer
    slideCount = highestSlide - lowestSlide + 1
    
    'Create an array to keep track of which slides have already been shown
    Dim chosenSlides() As Boolean
    ReDim chosenSlides(1 To slideCount)
    
    'Begin with all slides set as not chosen
    Dim i As Integer
    For i = 1 To slideCount
        chosenSlides(i) = False
    Next
    
    'Choose a random slide that hasn't been chosen yet
    Dim chosenSlide As Integer
    Do
        chosenSlide = Int(slideCount * Rnd + 1)
    Loop While chosenSlides(chosenSlide)
    
    'Mark the chosen slide as chosen
    chosenSlides(chosenSlide) = True
    
    'Map the chosen slide number to the corresponding slide number in the PPT
    r = chosenSlide + lowestSlide - 1
End Sub

Sub Easy()
    PlayGame 21, 30
End Sub

Sub AddLetterToSlide()
    Dim selectedShape As shape
    Set selectedShape = Application.ActiveWindow.Selection.ShapeRange(1)
    Dim selectedLetter As String
    selectedLetter = Left(selectedShape.Name, 1)
    InsertLetterOrNumber selectedLetter
End Sub

Sub InsertLetterOrNumber(selectedLetter As String)
    'Add a new textbox to the slide
    Dim newTextbox As shape
    Set newTextbox = ActivePresentation.Slides(r).Shapes.AddTextbox(Orientation:=msoTextOrientationHorizontal, Left:=ActivePresentation.Slides(r).Master.Width - (5 * 72), _
        Top:=0, Width:=5 * 72, Height:=2 * 72)
    
    'Set the textbox properties
    With newTextbox
        .Line.ForeColor.RGB = RGB(0, 0, 0) 'Black border
        .Fill.ForeColor.RGB = RGB(255, 255, 255) 'White background
        .TextFrame.TextRange.Text = selectedLetter 'Text to display
        .TextFrame.TextRange.Font.Name = "Arial" 'Font name
        .TextFrame.TextRange.Font.Size = 24 'Font size
        .TextFrame.TextRange.Find.Color.RGB = RGB(0, 0, 0) 'Font color
        .TextFrame.TextRange.Font.Bold = msoTrue
        .TextFrame.TextRange.Font.Italic = msoTrue
        .TextFrame.TextRange.Paragraphs.ParagraphFormat.Alignment = ppAlignRight 'Align text to the right
        .ZOrder msoBringToFront 'Bring textbox to front
    End With
End Sub

Let's say I click on a shape, named A, containing the letter A.
When that shape is clicked, it runs the macro Easy().

I want to

  1. Store that shape's name as 'selectedLetter'
  2. Pick a random slide within the range of the marco chosen, in this example, 21 to 30
  3. Use an array to keep track of previously chosen slides so that the same slide isn't shown twice
  4. Go to that slide
  5. Create a shape in the top-right, and inside that shape, write the value of 'selectedLetter'

I tried changing the order the subroutines are executed in. I tried a textbox instead of a shape. I tried using existing shapes and textboxes instead of trying to create them.

I know that Dim newTextbox As shape should be Dim newTextbox As Shape. Everytime I try to fix it, it changes back to shape.

I forget why I have three Dim variables set as global variables. Probably a troubleshooting attempt that didn't work.


Solution

  • Here's a basic example:

    Option Explicit
    
    Dim colSlides As Collection
    
    'initialize slides collection from slide 2 to slide 20
    Sub Reset()
        Dim i As Long
        Set colSlides = New Collection
        For i = 2 To 20
            colSlides.Add ActivePresentation.Slides(i)
        Next i
    End Sub
    
    'called from shapes on slide #1
    ' `shp` will be the clicked-on shape
    Sub Play(shp As Shape)
        Dim pick As Long, sld As Slide
        
        Debug.Print shp.Name
        pick = RandBetween(1, colSlides.Count)  'pick from the remaining slides
        Debug.Print pick
        Set sld = colSlides(pick)               'reference selected slide
        colSlides.Remove pick                   '...and remove it from the collection
        
        SlideShowWindows(1).View.GotoSlide sld.SlideIndex
        With sld.Shapes.AddTextbox(msoOrientationHorizontal, 10, 10, 300, 50)
            'copy the text from the clicked-on shape into the slide
            .TextFrame.TextRange.Text = shp.TextFrame.TextRange.Text
        End With
        
    End Sub
    
    'return a whole number between `vLow` and `vHigh`
    Function RandBetween(vLow As Long, vHigh As Long)
        RandBetween = Int(vLow + (vHigh - vLow + 1) * Rnd())
    End Function