How to apply this VBA to multiple PPT files in a folder - vba

I would like this particular code to be run on multiple powerpoint files in a folder. But it would be even better if it would open the powerpoint file, run this code below, save it and then open the next one. Any suggestions are welcome! I have been through code on this website, but can't seem to adapt it to my code below (e.g. this one Loop through files in a folder using VBA?)
LOOPING ATTEMPT
flag
Sub LoopThroughFiles()
Dim MyObj As Object, MySource As Object, file As Variant
file = Dir("c:\testfolder\")
While (file <> "")
If InStr(file, "test") > 0 Then
MsgBox "found " & file
Exit Sub
End If
file = Dir
Wend
End Sub
Existing Code
Option Explicit
' Selects the shape that support text which is closest to the top of the slide
' Written by Jamie Garroch of YOUpresent Ltd (http://youpresent.co.uk)
Sub SelectHigestTextShape()
Dim oSld As Slide
Dim oShp As Shape, oShpTop As Shape
Dim sShpTop As Single
On Error Resume Next
Set oSld = ActiveWindow.View.Slide
If Err Then Exit Sub
On Error GoTo 0
' Set the top to the bottom of the slide
sShpTop = ActivePresentation.PageSetup.SlideHeight
' Check each shape on the slide is positioned above the stored position
' Shapes not supporting text and placeholders are ignored
For Each oShp In oSld.Shapes
If oShp.Top < sShpTop And oShp.HasTextFrame And Not oShp.Type = msoPlaceholder Then
sShpTop = oShp.Top
Set oShpTop = oShp
End If
Next
' Select the topmost shape
If Not oShpTop Is Nothing Then oShpTop.Select msoTrue
ActiveWindow.Selection.ShapeRange.TextFrame.TextRange.ParagraphFormat.Alignment = ppAlignCenter
' Clean up
Set oSld = Nothing
Set oShp = Nothing
Set oShpTop = Nothing
End Sub

That's my code sample for the SelectHigestTextShape sub but I'm not sure it'll work the way you want for multiple files. The reason is that it was designed to SELECT a textbox object within the ACTIVE PRESENTATION using the ACTIVE VIEW. None of this exists when you loop through files in a folder as you'd need to open each one in turn but even then, what would be the point of selecting a shape only to close the presentation afterwards? I guess we really need to know the end goal. In the type of batch processing you're attempting, it would not be a good idea to select anything at all as that requires the object's view to be active which is a debugging nightmare and slows everything down a lot. If you want to do something with a particular object, it's much better to use a reference to it without requiring an active view or even an active window (you could open each file invisibly, process it and then close it).
This example will loop through a folder, open each presentation it finds (without a window), loop through all shapes on all slides, output a count of slides and shapes to the immediate pane, and then close the file:
' Loop through all PowerPoint files in a specified folder
' Open each and then loop through each shape of each slide
' Output a count of slides and shapes in immediate pane before closing the file
' Modified by Jamie Garroch of YOUpresent Ltd (http://youpresent.co.uk)
Sub LoopThroughPPTFiles()
Dim oPres As Presentation, oSld As Slide, oShp As Shape
Dim SldCount As Long, ShpCount As Long
Dim MyFile As String
Const MyFolder = "c:\testfolder\"
On Error GoTo errorhandler
MyFile = Dir(MyFolder)
While (MyFile <> "")
If Right(MyFile, 5) Like ".ppt*" Then
Set oPres = Presentations.Open(FileName:=MyFolder & MyFile, ReadOnly:=msoTrue, Untitled:=msoFalse, WithWindow:=msoFalse)
For Each oSld In oPres.Slides
SldCount = SldCount + 1
For Each oShp In oSld.Shapes
ShpCount = ShpCount + 1
Next
Next
Debug.Print oPres.Name & " has " & SldCount & " slide(s) and " & ShpCount & " shapes."
SldCount = 0: ShpCount = 0
oPres.Close
End If
MyFile = Dir
Wend
' clean up
Set oPres = Nothing: Set oSld = Nothing: Set oShp = Nothing
Exit Sub
errorhandler:
If Not oPres Is Nothing Then oPres.Close: Set oPres = Nothing
End Sub
You could use this to then examine the shapes after the "For Each oShp In oSld.Shapes" line to find the one positioned highest on the slide and then process it (without selecting it).

Related

Error: -2147188160 Slides.Item: Integer out of range.2 is not in in index's valid range of 1 to 1 VBA power point error

I'm trying to extract few specific slide numbers from each ppt and trying to paste them into a single ppt using VBA.But Im facing this error.Im quite new to VBA ,so it would be of great help how to proceed further.
Tried with the suggestions given in the link https://support.microsoft.com/en-us/help/285472/run-time-error-2147188160-on-activewindow-or-activepresentation-call-i#:~:text=This%20behavior%20is%20caused%20by,code%20will%20cause%20this%20error.
But it is not working
Thanks in Advance
My code is as follows:
Sub sample()
Dim objPresentation As Presentation
On Error GoTo ErrorHandler
Dim sListFileName As String
Dim sListFilePath As String
Dim iListFileNum As Integer
Dim sBuf As String
' EDIT THESE AS NEEDED
' name of file containing files to be inserted
sListFileName = "LIST2.TXT"
' backslash terminated path to folder containing list file:
sListFilePath = "path"
' Do we have a file open already?
If Not Presentations.Count > 0 Then
Exit Sub
End If
' If LIST.TXT file doesn't exist, create it
If Len(Dir$(sListFilePath & sListFileName)) = 0 Then
iListFileNum = FreeFile()
Open sListFilePath & sListFileName For Output As iListFileNum
' get file names
sBuf = Dir$(sListFilePath & "*.PPT")
While Not sBuf = ""
Print #iListFileNum, sBuf
sBuf = Dir$
Wend
Close #iListFileNum
End If
iListFileNum = FreeFile()
Open sListFilePath & sListFileName For Input As iListFileNum
' Process the list
While Not EOF(iListFileNum)
' Get a line from the list file
Line Input #iListFileNum, sBuf
' Verify that the file named on the line exists
If Dir$(sBuf) <> "" Then
Dim SlideArray As Variant
'Set variable to Active Presentation
Set OldPPT = ActivePresentation
'Create a brand new PowerPoint presentation
If PowerPoint.Application.Version >= 9 Then
'window must be visible
PowerPoint.Application.Visible = msoTrue
End If
Set NewPPT = Presentations.Add
InSlides = InputBox("List the slide numbers separated by commas:", "Slides", 2)
SlideArray = Split(InSlides, ",")
For x = 0 To UBound(SlideArray)
sld = CInt(SlideArray(x))
'Set variable to a specific slide
Set Old_sld = OldPPT.Slides(sld)
'Copy Old Slide
y = Old_sld.SlideIndex
Old_sld.Copy
'Paste Slide in new PowerPoint
NewPPT.Slides.Paste
Set New_sld = Application.ActiveWindow.View.Slide
'Bring over slides design
New_sld.Design = Old_sld.Design
'Bring over slides custom color formatting
New_sld.ColorScheme = Old_sld.ColorScheme
'Bring over whether or not slide follows Master Slide Layout (True/False)
New_sld.FollowMasterBackground = Old_sld.FollowMasterBackground
Next x
End If
Wend
Close #iListFileNum
MsgBox "DONE!"
NormalExit:
Exit Sub
ErrorHandler:
Call MsgBox("Error:" & vbCrLf & Err.Number & vbCrLf & Err.Description, _
vbOKOnly, "Error inserting files")
Resume NormalExit
End Sub

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

How to clear Slide Master of all information in PowerPoint using VBA?

I would like to open every PowerPoint (*.pptx) in current folder and clear the Slide Master of all images and text boxes and then save.
(It says my post is mostly code so I need to add more detail, so here is a quote by George Washington, "Associate with men of good quality if you esteem your own reputation; for it is better to be alone than in bad company")
New code
Sub DeleteSlideMasterShapes()
Dim i As Long
Dim shp As Shape
With ActivePresentation
For i = .Designs.Count To 1 Step -1
For Each shp In .Designs(i).SlideMaster.Shapes
shp.Delete
Next
Next i
End With
End Sub
Sub loopFiles()
Dim fso As New FileSystemObject
Dim fil As File
Dim fold As Folder
Dim yourfolder As String
Set fold = fso.GetFolder(Application.ActivePresentation.Path)
For Each fil In fold.Files
If InStr(1, fil.Name, ".pptx") > 0 Then
Application.Presentations.Open fil.Path
Call DeleteSlideMasterShapes
ActivePresentation.Save
ActivePresentation.Close
End If
Next fil
End Sub
Another approach, in case you want to delete all the shapes from all Slide Masters AND the master's layouts:
Sub DeleteSlideMasterShapes()
' Including shapes on layouts
Dim oDes As Design
Dim oLay As CustomLayout
With ActivePresentation
' For each slide master:
For Each oDes In .Designs
' Delete the shapes on the master
oDes.SlideMaster.Shapes.Range.Delete
' Then delete the shapes from each layout under
' the slide master:
For Each oLay In oDes.SlideMaster.CustomLayouts
oLay.Shapes.Range.Delete
Next
Next
End With
End Sub
Further to my comments, if you want to delete the slide master then use this
Sub DeleteSlideMaster()
Dim i As Long
With ActivePresentation
On Error Resume Next
For i = .Designs.Count To 1 Step -1
.Designs(i).SlideMaster.Delete
Next i
On Error GoTo 0
End With
End Sub
To delete Shapes of a slidemaster, use this
Sub DeleteSlideMasterShapes()
Dim i As Long
Dim shp As Shape
With ActivePresentation
For i = .Designs.Count To 1 Step -1
For Each shp In .Designs(i).SlideMaster.Shapes
shp.Delete
Next
Next i
End With
End Sub
If I have not understood your query then please feel free to ask

Powerpoint VBA Loop not looping through all slides

Bit of an issue, I have some VBA code that loops through all of the sheets in my ppt, loops through all of the shapes in each ppt, and deletes the ppt if a specific string of text is not found. It seems to work perfectly other than the code seems to stop looping for no reason. I have to hit F5 about 4 times for the code to loop through all the sheets. It could be something to do with my code so I thought I'd try the good people of Stackoverflow first.
Public Sub ExportMBR()
Dim oSld As Slide
Dim oShp As Shape
Dim strSearch As String
Dim i As Integer
strSearch = "R&T MBR"
i = 0
For Each oSld In ActivePresentation.Slides
Debug.Print (ActivePresentation.Slides.Count)
Debug.Print (oSld.Name)
For Each oShp In oSld.Shapes
If oShp.HasTextFrame Then
If oShp.TextFrame.TextRange.Find(strSearch) Is Nothing Then
Else
Debug.Print (oSld.Name & " Slide found")
i = i + 1
End If
End If
Next oShp
If i = 0 Then
Debug.Print (oSld.Name & " Deleting")
oSld.Delete
i = 0
End If
i = 0
Next oSld
myQ = "<afilepath>"
myName = myQ & "<anameformat>") & ".pptx"
ActivePresentation.SaveCopyAs myName
Call Shell("explorer.exe " & myQ, vbNormalFocus)
End Sub
There are 34 slides in my ppt, each run will loop through about 7 slides correctly identifying and deleting the slides I do not need, but then without any errors it will just stop looping and continue executing the rest of the code. The string is found on slides 17 and 18 if this makes a difference. I have added few bits extra to try and solve the problem like the debug.prints and the i = 0 but I just can't figure out what I'm doing wrong.
Many thanks in advance!
ppw
Whenever you delete any object within a collection as you loop through each object in that collection, you need to count backwards. So in these cases you cannot use the For Each oSld In ActivePresentation.Slides statement but do this instead:
Dim lCntr as Long
Dim oSld as Slide
For lCntr = ActivePresentation.Slides.Count to 1 Step -1
Set oSld = ActivePresentation.Slides(lCntr)
' Do your stuff here...
Set oSld = Nothing
Next
Download more free PowerPoint macros and add-ins at http://youpresent.co.uk
Because Find(strSearch) & oSld.Delete are at the same loop, you need to separate them !!
Address the slides which you want to del first and then del them.
For example: suppose that you have slide_1 & slide_2 & slide_3 and you want to del slide_1 & slide_2 & slide_3. Actually, your VBA only del slide_1 & slide_3.
In the loop For Each oSld In ActivePresentation.Slides, the finding sequence should be slide_1 => slide_2 => slide_3. However, the first loop cycle will del slide_1, the remaining slides count become 2 (slide_2 & slide_3), so second loop cycle will start from slide_3. That's the reason why.

Trouble with VBA Do While loop in macro to copy slide and change picture in powerpoint

I am attempting my first macro in powerpoint. I am simply trying to copy a 'reference' slide and replace one picture. I will do this for all pictures in a folder. The script I have adds all the slides, but then adds all the pictures to the final slide. I don't understand why this is the case since the Duplicate Slide code and the Add Picture code are in the same while loop. Can someone tell me why?
Sub LoopThroughFiles()
Dim StrFile As String
Dim Folder As String
Dim sld As Slide
Dim referencesld As Slide
Set referencesld = ActivePresentation.Slides(1)
Dim i As Integer
Dim shp As Shape
i = 1
Folder = "c:\E1B8\ScriptTesting\MISC\PPT\SampleData2\"
StrFile = Dir(Folder & "*")
Set referencesld = ActivePresentation.Slides(1)
Set shp = referencesld.Shapes(5)
Do While Len(StrFile) > 0
Debug.Print Folder & StrFile
referencesld.Duplicate
i = i + 1
Set sld = ActivePresentation.Slides(i)
With shp
sld.Shapes.AddPicture(Folder & StrFile, msoFalse, msoTrue, .Left, .Top, .Width, .Height).IncrementRotation 360#
End With
sld.Shapes(5).Delete
StrFile = Dir
Loop
End Sub
Thanks!!
You can use a variable when duplicating the slide, forget the "i" variable, it is not needed:
delete the lines
referencesld.Duplicate
i = i + 1
Set sld = ActivePresentation.Slides(i)
An insert "Set sld = referencesld.Duplicate" in the place
...
Debug.Print Folder & StrFile
Set sld = referencesld.Duplicate
With shp
sld.Shapes.AddPicture(Folder & StrFile, msoFalse, msoTrue, .Left, .Top, .Width, .Height).IncrementRotation 360#
End With
...
Untested
You can see "Duplicate" reference in http://msdn.microsoft.com/library/office/ff745804(v=office.15).aspx
Aside: I think it is weird to use the "with" keyword on the argument (shape) instead of the object you are working on (the slide).
[edited: Make it clear to understand what to do]
I hope to help.