Loop through all check boxed and add specific slides to array - vba

I would like to make an array (Set Selected_slds = ActivePresentation.Slides.Range) of slides. The slides are to be part of an array that can be selected from a number of Check boxes. So, the idea of the code I would like to write is:
Dim k As Integer
Dim list_of_slides As Array
Dim Selected_slds As SlideRange
For k = 1 To Count(CheckBoxs)
If CheckBox(k) = True Then
add.slide(k) to list_of_slides
End If
Next
Set Selected_slds = list_of_slides
The above is part of a longer code, where Selected_slds is used.
What I have done so far is this:
Sub Test()
Dim oSh As Shape
Dim oSl As Slide
Dim k As Integer
' Look at each shape on each slide in the active pres
For Each oSl In ActivePresentation.Slides
For Each oSh In oSl.Shapes
' Is the shape a control?
If oSh.Type = msoOLEControlObject Then
' Is it a checkbox?
If InStr(UCase(oSh.OLEFormat.ProgID), "FORMS.CHECKBOX") > 0 Then
' BINGO, found what we're after, so ...
If oSh.OLEFormat.Object.Value = True Then
MsgBox "Checked"
ElseIf oSh.OLEFormat.Object.Value = False Then
MsgBox "Uncheked"
End If
End If
End If
Next ' Shape
Next ' Slide
End Sub
Which works, but I am not sure what to do, to get it to do what I am looking for. It is coded in power point.

Related

How to group all objects on a slide, which can be grouped, and resize the group?

How do I group all objects (or "shapes"?) on a slide and resize that group?
Subsequently the "big" group should be ungrouped.
My attempt fails with "function expected":
Sub Group_And_Resize()
Dim Sld As Slide
With Sld.Shapes
With .SelectAll.Group //Error here
.Width = 907
End With
End With
End Sub
By manual experimentation, I learned that some objects (or "shapes"?) cannot be added to a group, such as slide numbers which are automatically generated. Is there any possibility to exclude those from the selection?
If you want to group the shapes together first and then set the overall width to 907, you can use this code:
Sub Group_And_Resize()
Dim Sld As Slide, a As Variant, i As Integer
Set Sld = ActivePresentation.Slides(1) ' your slide
ReDim a(1 To Sld.Shapes.Count)
For i = LBound(a) To UBound(a)
a(i) = Sld.Shapes(i).Name
Next
Sld.Shapes.Range(a).Group.Width = 907
End Sub
If you want to make the width of each of the shapes on the slide = 907, you can use the following code:
Sub Group_And_Resize()
Dim Sld As Slide
Set Sld = ActivePresentation.Slides(1) ' your slide
Sld.Shapes.Range.Width = 907
End Sub
This is based on Алексей Р's answer but solves a few problems and also is more generic. It allows calling the routine on any slide in the active presentation and setting the width to any desired value. See comments for more details.
Sub Test()
With ActivePresentation
Call Group_And_Resize(.Slides(1), 200)
End With
End Sub
Sub Group_And_Resize(Sld As Slide, sngWidth As Single)
Dim a As Variant, i As Long ' Array indices are longs, not integers
Dim oGroup As Shape
' Call NonPlaceholderShapeCount to get number of
' shapes that are not placeholders, since placeholders
' cannot be grouped. Use that to ReDim the array:
ReDim a(1 To NonPlaceholderShapeCount(Sld))
For i = LBound(a) To UBound(a)
' Again, make sure we don't try to group placeholders
If Not Sld.Shapes(i).Type = msoPlaceholder Then
a(i) = Sld.Shapes(i).Name
End If
Next
' Get a reference to the new group
' since we need to set several properties on it
Set oGroup = Sld.Shapes.Range(a).Group
' This ensures that the group (and its shapes)
' aren't distorted:
oGroup.LockAspectRatio = True
' and finally, set the width
oGroup.Width = sngWidth
End Sub
Function NonPlaceholderShapeCount(Sld As Slide) As Long
' Returns the number of non-placeholder shapes on Sld
Dim x As Long
Dim lCount As Long
With Sld
For x = 1 To .Shapes.Count
If Not .Shapes(x).Type = msoPlaceholder Then
lCount = lCount + 1
End If
Next
End With
NonPlaceholderShapeCount = lCount
End Function

Issues with Textboxes Individually Hyperlinked to Slide with Matching Titles

I have put together an e-learning module. I am still very new at vba though. I am trying to make a dynamic main menu which contains multiple text boxes. If the text in a text box matches the title of a slide, that shape should then then be hyperlinked to the corresponding slide. Ideally, the text boxes on the Main Menu would contain the names of Sections and hyperlink to the first slide in the named section, but I couldn't figure that out, so instead I made the title of the first slide in each section match the text. I've searched and searched and gotten as close as I could. I am hoping someone can help me finish it. I have gotten past several errors, and have the text hyperlinked, however all linked take the user to the last slide in the presentation instead of the proper slide. Thank you in advance for any guidance!!
Here is the code:
Sub TestMe()
'Original Source: http://www.steverindsberg.com/pptlive/FAQ00056.htm
Dim aSl As Slide 'active slide
Dim dSl As Slide 'destination slide
Dim Slde As Slide
Dim oSh As Shape
Dim aSl_ID As Integer
Dim aSl_Index As Integer
Dim dSl_ID As Integer
Dim dSl_Index As Integer
Dim sTextToFind As String
Dim hypstart As String
Dim Titl As String
Set aSl = Application.ActiveWindow.View.Slide 'active slide
aSl_Index = Application.ActiveWindow.View.Slide.SlideIndex 'active slide index
' Set ActiveSld_Index =
' Set DestinationSld_ID = oSl.SlideID
' Set DestinationSld_Index = oSl.SlideIndex
For Each oSh In aSl.Shapes
'If IsSafeToTouchText(oSh) = True Then
sTextToFind = oSh.TextFrame.TextRange.Text
'loop through slides looking for a title that matches the text box value
On Error Resume Next
Set dSl = FindSlideByTitle(sTextToFind)
' get the information required for the hyperlink
dSl_ID = CStr(dSl.SlideID)
dSl_Index = CStr(dSl.SlideIndex)
' find the text string in the body
hypstart = InStr(1, sTextToFind, sTextToFind, 1)
'make the text a hyperlink
With oSh.TextFrame.TextRange.Characters(hypstart, Len(sTextToFind)).ActionSettings(ppMouseClick).Hyperlink
.SubAddress = dSl_ID & "," & dSl_Index & "," & sTextToFind
End With
'End If
Next oSh
End Sub
Public Function FindSlideByTitle(sTextToFind As String) As Slide
'Source: http://www.steverindsberg.com/pptlive/FAQ00056.htm
Dim oSl As Slide
Dim oSh As Shape
With ActivePresentation
For Each oSl In .Slides
For Each oSh In oSl.Shapes
With oSh
'If .HasTextFrame Then
'If Not .TextFrame.TextRange.Text Is Nothing Then
'myPres.Slides(1).Shapes.Title.TextFrame.TextRange
On Error Resume Next
If UCase(.TextFrame.TextRange.Text) = UCase(sTextToFind) Then
'If UCase(.TextRange.Text) = UCase(sTextToFind) Then
Set FindSlideByTitle = oSl
'End If
End If
'End If
End With
Next
Next
End With
End Function
Public Function IsSafeToTouchText(pShape As Shape) As Boolean
'Source: http://www.steverindsberg.com/pptlive/FAQ00056.htm
On Error GoTo ErrorHandler
If pShape.HasTextFrame Then
If pShape.TextFrame.HasText Then
' Errors here if it's a bogus shape:
If Len(pShape.TextFrame.TextRange.Text) > 0 Then
' it's safe to touch it
IsSafeToTouchText = True
Exit Function
End If ' Length > 0
End If ' HasText
End If ' HasTextFrame
Normal_Exit:
IsSafeToTouchText = False
Exit Function
ErrorHandler:
IsSafeToTouchText = False
Exit Function
End Function
Here is the revised code. I have gone in circles and am now stuck. Any suggestions are much appreciated!
After I restored the original function (FindSlideByTitle), I kept getting an error on got an error on .textframe.textrange, making me think that the type of shape I used on my slide (freeform) needed TextFrame2, so I edited that, which fixed the error, but since then I've not been able to make the hyperlink work and have tried instead to use GoTo Slide by including the parent.
I even tried making an array of all freeform shapes on the slide, but I'm still new at this and perhaps I don't fully understand the concepts yet. As it currently stands, I don't get any errors, however, when I click one of the shapes, the shape's appearance changes from the click, but it doesn't go anywhere.
I have also included an image of the actual slide.
Sub TestLinkShapesToSlideTitles()
Dim aSl, dSl, oSl As Slide 'active slide, destination slide
Dim oSh As PowerPoint.Shape
Dim aSl_ID, dSl_ID As Integer
Dim aSl_Index, dSl_Index As Long
Dim dSl_Title, hypstart, Titl As String
Dim sTextToFind As String
Dim numshapes, numFreeformShapes As Long
Dim FreeformShpArray As Variant
Dim ShpRange As Object
Dim oPres As Presentation
Set aSl = Application.ActiveWindow.View.Slide 'active slide
aSl_Index = Application.ActiveWindow.View.Slide.SlideIndex 'active slide index
''''''''''''''''''''''''''''
'In this section I tried to make an array of all the freeform shapes on the slide, thinking that would help.
With aSl.Shapes
numshapes = .Count
'Continues if there are Freeform shapes on the slide
If numshapes > 1 Then
numFreeformShapes = 0
ReDim FreeformShpArray(1 To numshapes)
For i = 1 To numshapes
'Counts the number of Freeform Shapes on the Slide
If .Item(i).Type = msoFreeformShape Then
numFreeformShapes = numFreeformShapes + 1
FreeformShpArray(numFreeformShapes) = .Item(i).Name
End If
Next
'Adds Freeform Shapes to ShapeRange
If numFreeformShapes > 1 Then
ReDim Preserve FreeformShpArray(1 To numFreeformShapes)
Set ShpRange = .Range(FreeformShpArray)
'asRange.Distribute msoDistributeHorizontally, False
End If
End If
End With
''''''''''''''''''''''''''
On Error Resume Next
'Loop through all the shapes on the active slide
For Each oSh In aSl.Shapes
If oSh.Type = msoFreeform Then 'oSh.Type = 5
'If oSh.HasTextFrame Then
If oSh.TextFrame2.HasText Then 'results in -1
With oSh
sTextToFind = .TextFrame2.TextRange.Characters
'sTextToFind results in "Where to Begin"
'.TextFrame2.TextRange.Characters results in "Learn the Lingo", which is the shape after Where to Begin.
End With
End If
'End If
'If IsSafeToTouchText(oSh) = True Then
'With oSh.TextFrame
'sTextToFind = .TextRange.Characters.Text
'loop through slides looking for a title that matches the text box value
'For Each oSl In ActivePresentation.Slides
'If oSl.Shapes.HasTitle Then
'Titl = Slde.Shapes.Title.TextFrame.TextRange <<<<< I kept getting the error here...
On Error Resume Next
Set dSl = FindSlideByTitle_Original(sTextToFind)
' get the information required for the hyperlink
dSl_Title = dSl.Shapes.Title.TextFrame.TextRange
dSl_ID = dSl.SlideID
dSl_Index = dSl.SlideIndex
With oSh
.ActionSettings(ppMouseClick).Parent.Parent.View.GoToSlide dSl_Index, msoFalse 'Go to slide and don't reset animations
End With
' find the text string in the body
'hypstart = InStr(1, sTextToFind, dSl_Title, 1)
'make the text a hyperlink
'With oSh.TextFrame.TextRange.Characters(hypstart, Len(sTextToFind)).ActionSettings(ppMouseClick).Hyperlink
'.SubAddress = dSl_ID & "," & dSl_Index & "," & sTextToFind
'End With
'End With
End If
'End If
Next oSh
End Sub
Public Function FindSlideByTitle_Original(sTextToFind As String) As Slide
'Source: https://stackoverflow.com/questions/25038952/vba-powerpoint-select-a-slide-by-name
Dim oSl As Slide
For Each oSl In ActivePresentation.Slides
With oSl.Shapes.Title.TextFrame
If .HasText Then
If UCase(.TextRange.Text) = UCase(sTextToFind) Then
Set FindSlideByTitle_Original = oSl
End If
End If
End With
Next
End Function

Select a defined range of slides through textboxes

I want to select a range of slides in Powerpoint by vba. For Excel you simply write
Range("A1:A100")
I want to select from slide number 5 to 10, how do I code that? My code just selects two slides:
ActivePresentation.Slides.Range(Array(5,10)).Select
Here is an example. This will depend on which type of Text box you are using. I am assuming standard textbox you select which is a shape. I am using some test textboxes which you would need to adjust to suit your needs.
You call the sub SelectSlides to generate the array of slides numbers for the slides to select between the two text box numbers.
You use the Range method to return any number of shapes or slides.
To specify an array of integers or strings for Index, you can use the Array function or, I believe, pass an array into the Range.
I will be upfront, whilst this worked once, powerpoint the crashed and since then the code has selected only the last item.
However, you can assign ppt.Slides.Range(slidesArray) to a Slides object and work with that e.g.
Dim slidesObject As Slides
Set slidesObject = ppt.Slides.Range(slidesArray)
Code:
Option Explicit
Public Sub SelectSlideArray()
Dim ppt As Presentation
Dim sld As Slide
Dim textBox1 As Shape
Dim textBox2 As Shape
Set ppt = ActivePresentation
Set sld = ppt.Slides(1) ' slide with text boxes in
Set textBox1 = sld.Shapes("TextBox 3") 'change as required
Set textBox2 = sld.Shapes("TextBox 4") 'change as required
textBox1.TextFrame.TextRange = 5 ' you can say TextRange.Text but .Text is defaut
textBox2.TextFrame.TextRange = 10
Dim startSlideNumber As Integer
Dim endSlideNumber As Integer
startSlideNumber = Int(textBox1.TextFrame.TextRange)
endSlideNumber = Int(textBox2.TextFrame.TextRange)
SelectSlides ppt, startSlideNumber, endSlideNumber
'PrintShapeNames sld
End Sub
Public Sub SelectSlides(ByVal ppt As Presentation, ByVal startSlideNumber As Long, ByVal endSlideNumber As Long)
Dim outputSlideNumber As Long
outputSlideNumber = startSlideNumber
If ppt.Slides.Count < endSlideNumber Then
MsgBox "You don't have enough slides in the presentation!"
End
ElseIf endSlideNumber < startSlideNumber Then
MsgBox "End slide is before start slide!"
End
Else
Dim slidesArray()
ReDim slidesArray(0 To endSlideNumber - startSlideNumber)
Dim currentSlide As Long
For currentSlide = LBound(slidesArray) To UBound(slidesArray)
slidesArray(currentSlide) = outputSlideNumber
outputSlideNumber = outputSlideNumber + 1
Next currentSlide
End If
ppt.Slides.Range(slidesArray).Select
End Sub
Private Sub PrintShapeNames(ByVal sld As Slide)
Dim shp As Shape
For Each shp In sld.Shapes
Debug.Print shp.Name
Next shp
End Sub

VBA PowerPoint slide Title

I am working on a custom tool that generates customized Instructor notes for a given presentation. I am having a problem where I am processing a presentation where a slide basically has no Title object on it Then I run through the code it is bi-passing my if statements with .
I have reduced the code to the basics to make it as easy as possible.
My test lesson has a normal slide with the text place holder filled out, the next slide is a logo slide with no title text box, just a copyright information and logo, (this is the slide that is having issues) and then another slide where the title place holder is present, but left blank.
How do I check the individual slide to make sure that the title placeholder exists?
Public Sub GetTitle()
Dim pres As Presentation 'PowerPoint presentation
Dim sld As Slide 'Individual slide
Dim shp As Shape 'EIAG Text Shape
Dim ShpType As String 'Shape Type
Dim SldTitle As String 'Slide TITLE
'Go through each slide object
Set pres = ActivePresentation
For Each sld In ActivePresentation.Slides.Range
On Error Resume Next
If sld.Shapes(1).PlaceholderFormat.Type = ppPlaceholderCenterTitle Or sld.Shapes(1).PlaceholderFormat.Type = ppPlaceholderTitle Then
If sld.Shapes.Title.TextFrame.TextRange <> "" Then
SldTitle = sld.Shapes.Title.TextFrame.TextRange
Debug.Print SldTitle & " - Slide: " & CStr(sld.SlideNumber)
Else
Debug.Print "BLANK TITLE - Slide: " & CStr(sld.SlideNumber)
End If
Else
ShpType = sld.Shapes.Item(1).Type
Debug.Print ShpType & "Not Processed There is no Title object"
End If
Next sld
End Sub
You can use the HastTitle method of the Shapes Collection to check if a slide has a title placeholder:
If sld.Shapes.HasTitle then
You should also not rely on the title placeholder being shape 1 and rather loop through all shapes on the slide, checking each one as follows:
Option Explicit
' Function to return an array of title texts from a presentation
' Written by Jamie Garroch at http://youpresent.co.uk
' Inputs : None
' Outputs : Array of title strings
Function GetTitlesArr() As Variant
Dim oSld As Slide
Dim oShp As Shape
Dim iCounter As Integer
Dim arrTitles() As String
For Each oSld In ActivePresentation.Slides
For Each oShp In oSld.Shapes
With oShp
If .Type = msoPlaceholder Then
Select Case .PlaceholderFormat.Type
Case ppPlaceholderCenterTitle, ppPlaceholderTitle
ReDim Preserve arrTitles(iCounter)
arrTitles(iCounter) = oShp.TextFrame.TextRange.Text
iCounter = iCounter + 1
End Select
End If
End With
Next
Next
GetTitlesArr = arrTitles
End Function

How not to count page numbers for hidden slides in PPT?

In presentation mode, I want only unhidden slides to appear with consecutive page numbers. How can I avoid that hidden slides are counted?
Thank you Steve. I found an answer to my question elsewhere. The function below allows you to avoid that hidden slides are interfering with the slide numbers of unhidden slides in presentation mode.
Sub Number_NonHidden()
'For v.2007 onwards only
Dim osld As Slide
Dim objSN As Shape
Dim lngNum As Long
'check all slides
For Each osld In ActivePresentation.Slides
'Is it hidden
If osld.SlideShowTransition.Hidden Then
osld.HeadersFooters.SlideNumber.Visible = False
Else
osld.HeadersFooters.SlideNumber.Visible = True
Set objSN = getNumber(osld)
lngNum = lngNum + 1
If Not objSN Is Nothing Then ' there is a number placeholder
objSN.TextFrame.TextRange = CStr(lngNum + 1)
End If
End If
Next osld
End Sub
Function getNumber(thisSlide As Slide) As Shape
For Each getNumber In thisSlide.Shapes
If getNumber.Type = msoPlaceholder Then
If getNumber.PlaceholderFormat.Type = ppPlaceholderSlideNumber Then
'it's the slide number
Exit Function
End If
End If
Next getNumber
End Function
In order to avoid that the title slide is numbered insert lngNum = -1 as follows and delete the slide number box in the master title slide.
'check all slides
lngNum = -1
For Each osld In ActivePresentation.Slides
In VBA you'd do something like this:
Sub CountSlides()
Dim oSl As Slide
Dim x As Long
For Each oSl In ActivePresentation.Slides
If Not oSl.SlideShowTransition.Hidden Then
x = x + 1
End If
Next
MsgBox x
End Sub
In other words, if the SlideShowTransition.Hidden property of the slide is True, don't count it.