I have a set of custom layouts that are my approved corporate standard. There is one master and 11 custom layouts.
Because users will likely be pasting in old content, I am aware that any slides they paste in will bring their corresponding layouts with them. What is the best way to write a button that will remove any custom layouts that aren't part of the approved set?
The code I have is as follows, but it gives me an error that says "Slide (unknown member) : Invalid Request. Can't delete master."
ANY help gratefully received!
Dim oDesign As design
For Each oDesign In ActivePresentation.Designs
'if design name is CC standard then
If oDesign.Name = CCSMNAME$ Then
Dim oLayout As CustomLayout
'Check the name of each layout against the permitted set, delete any that are additional
For Each oLayout In oDesign.SlideMaster.CustomLayouts
If oLayout.Name <> "Title Slide (Basic)" Or oLayout.Name <> "Title Slide (Standard Stock Image)" Or oLayout.Name <> "Title Slide (Image - Right)" Or oLayout.Name <> "Agenda" Or oLayout.Name <> "Body/Content (Basic)" Or oLayout.Name <> "Report (Approval and Disclaimer)" Or oLayout.Name <> "Report Body/Content" Or oLayout.Name <> "Divider" Or oLayout.Name <> "Quals (Basic -Right)" Or oLayout.Name <> "Quals (Basic - Left)" Or oLayout.Name <> "Content and Closing" Then
oLayout.Delete
End If
Next oLayout
Else
'Else, the Design found is not the CC Master so delete it
'(This runs for all remaining masters)
oDesign.Delete
End If
Next oDesign
I am now using the following code - does anyone have any idea why instead of deleting all additional slide masters, it only deletes the next in the sequence and then exits?
Sub CleanupTemplate()
'Declare some variables
Dim oDesign As design
Dim oDesigns As Designs
Dim oLayout As CustomLayout
Dim masterCount As Long
Dim layoutCount As Long
Dim strInUse As String
On Error Resume Next
For Each oDesign In ActivePresentation.Designs
If oDesign.Name = CCSMNAME$ Then
MsgBox "The script has found " & oDesign.SlideMaster.CustomLayouts.Count & " layouts in the CC Master. There should be 11 in total. An integrity check will now run to remove any non-approved slide layouts."
'Loop through set backwards to keep integrity of data set when deleting
For layoutCount = oDesign.SlideMaster.CustomLayouts.Count To 1 Step -1
Set oLayout = oDesign.SlideMaster.CustomLayouts(layoutCount)
Err.Clear
'Check the name of each layout against the permitted set, delete any that are additional
If checkAllowed(oLayout) = False Then
oLayout.Delete
End If
If Err <> 0 Then
strInUse = strInUse & oLayout.Name & " , "
End If
Next layoutCount
MsgBox ("Any additional layouts deleted, cleanup of CC Master completed.")
Else
'Else, a Slide Master has been found that is not the CC Master so delete it
MsgBox ("An additional Slide Master named " & oDesign.Name & " that is not CC approved has been detected. It is not in use, so it will be removed.")
oDesign.Delete
End If
Next oDesign
'Alert the user to any foreign slide designs found that couldn't be deleted
If Len(strInUse) > 0 Then
MsgBox "The following slide designs seem to be either in use, or protected: " & Left(strInUse, Len(strInUse) - 1)
End If
End Sub
Function checkAllowed(olay As CustomLayout) As Boolean
Select Case olay.Name
Case Is = "Title Slide (Basic)", _
"Title Slide (Image - Right)", _
"Title Slide (Standard Stock Image)", _
"Agenda", "Body/Content (Basic)", _
"Report (Approval and Disclaimer)", _
"Report Body/Content", _
"Divider", _
"Quals (Basic - Right)", _
"Quals (Basic - Left)", _
"Contact and Closing"
'Return true if any of the above names are a match
checkAllowed = True
Case Else
'Return false if no match found
checkAllowed = False
End Select
End Function
When you delete members of a collection in a For/Next loop, you'll run into the same problem.
Consider a collection of three objects (slides, masters, apples, whatever)
For Each Object in Collection
If Object.MeetsSomeCondition Then
Object.Delete
End If
Next
So the first time through the loop, you delete an object.
The next time through the loop, the internal counter's looking for the second object in the collection, but since the collection only contains two objects now, it's actually looking at what WAS the third object.
The next time through the loop, the internal counter's looking for the third object, but since there are only two in the collection, you get an out of range error.
Instead, do this:
For X = Collection.Count to 1 Step -1
If condition then Collection(x).delete
Next