Search code examples
vbapowerpoint

Macro to update shape color on click in PowerPoint


I am trying to create a macro that will toggle a shape's color upon clicking. I've assigned the macro below to a shape, and it should execute with a click. However, when I click, nothing happens. Do I need to name the shape something specific? or is there something wrong in the VB language?

Sub ChangeShapeColour(ByRef oShp As Shape)
    Dim oSh As Shape
    ' IF the shape's .Fill.ForeColor.RGB = red color:
        If oSh.Fill.ForeColor.RGB = RGB(199, 70, 52) Then
    ' Change it to green:
        oSh.Fill.ForeColor.RGB = RGB(117, 156, 108)

        End If
        
    ' IF the shape's .Fill.ForeColor.RGB = green color:
        If oSh.Fill.ForeColor.RGB = RGB(117, 156, 108) Then
    ' Change it to red:
        oSh.Fill.ForeColor.RGB = RGB(199, 70, 52)
        
        End If


End Sub

Solution

  • Toggle Shape Color

    • For those new to PowerPoint, in the Insert tab under the Illustration group, there are Action Buttons at the bottom of the Shapes menu that can utilize (call) the following codes as they are.

    The Issue

    • In the sub's signature, shp As Shape already means Dim shp As Shape so you mustn't do it again inside the sub.
    • It makes no difference whether you add ByVal or ByRef since an object is always passed ByRef in VBA.
    • By introducing two variables and a With statement, you can make your code more readable:
    Sub ToggleShapeColorYourCode(shp As Shape)
        
        Dim Red As Long: Red = RGB(199, 70, 52) ' some red color
        Dim Green As Long: Green = RGB(117, 156, 108) ' some green color
        
        With shp.Fill.ForeColor
            
            If .RGB = Red Then .RGB = Green
            If .RGB = Green Then .RGB = Red
            
            ' With the previous two 'If' statements you are implying the following:
            
            If .RGB <> Red And .RGB <> Green Then ' it's neither
                ' do nothing!?
            End If
        
        End With
    
    End Sub
    
    • The logic of your code yields the following: If the shape is green, make it red.
    • How?
      • If the shape is green, the 1st statement will ignore it while the 2nd statement will make it red.
      • If the shape is red, the 1st statement will make it green, while the 2nd statement will make it red again i.e. it will remain red forever at the cost of the resources needed to make the two conversions happen.
    • There is a third implicit (hidden) condition (case) that you may have forgotten about i.e. when the color is neither red nor green. In this case, nothing will happen i.e. the current shape's color will remain forever.
    • You have to decide what should happen in this case. In the continuation, I have opted for Red.

    The Fix

    • You must introduce an ElseIf and/or an Else clause into the If statement. Alternatively, you can use the IIF function or the Select Case statement.

    1.) If Long

    Sub ToggleShapeColorIFLong(shp As Shape)
        
        Dim Red As Long: Red = RGB(199, 70, 52) ' some red color
        Dim Green As Long: Green = RGB(117, 156, 108) ' some green color
        
        With shp.Fill.ForeColor
            If .RGB = Red Then
                .RGB = Green
            ElseIf .RGB = Green Then
                .RGB = Red
            Else ' it is neither
                .RGB = Red ' or Green, your choice
            End If
        End With
    
    End Sub
    

    2.) If Short

    Sub ToggleShapeColorIfShort(shp As Shape)
        
        Dim Red As Long: Red = RGB(199, 70, 52) ' some red color
        Dim Green As Long: Green = RGB(117, 156, 108) ' some green color
        
        With shp.Fill.ForeColor
            If .RGB = Red Then
                .RGB = Green
            Else ' it is not red
                .RGB = Red
            End If
        End With
    
    End Sub
    

    3.) IF Shorter

    Sub ToggleShapeColorIfShort(shp As Shape)
        
        Dim Red As Long: Red = RGB(199, 70, 52) ' some red color
        Dim Green As Long: Green = RGB(117, 156, 108) ' some green color
        
        With shp.Fill.ForeColor
            If .RGB = Red Then .RGB = Green Else .RGB = Red
        End With
    
    End Sub
    

    4.) IIF

    Sub ChangeShapeColorIIf(ByVal shp As Shape)
        
        Dim Red As Long: Red = RGB(199, 70, 52)
        Dim Green As Long: Green = RGB(117, 156, 108)
        
        With shp.Fill.ForeColor
            .RGB = IIf(.RGB = Red, Green, Red)
        End With
    
    End Sub
    

    5.) Select Long

    Sub ToggleShapeColorCaseElse(shp As Shape)
        
        Dim Red As Long: Red = RGB(199, 70, 52) ' some red color
        Dim Green As Long: Green = RGB(117, 156, 108) ' some green color
        
        With shp.Fill.ForeColor
            Select Case .RGB
                Case Red: .RGB = Green
                Case Green: .RGB = Red
                Case Else: .RGB = Red ' or Green, your choice
            End Select
        End With
    
    End Sub
    

    6.) Select Short

    Sub ToggleShapeColorCase(shp As Shape)
        
        Dim Red As Long: Red = RGB(199, 70, 52) ' some red color
        Dim Green As Long: Green = RGB(117, 156, 108) ' some green color
        
        With shp.Fill.ForeColor
            Select Case .RGB
                Case Red: .RGB = Green
                Case Else: .RGB = Red
            End Select
        End With
    
    End Sub