Forum Discussion

Netrix650's avatar
Netrix650
Copper Contributor
Feb 01, 2023
Solved

VBA code to change (revert) Cell Colour when clicking out of cell (ie not the active cell)

Hi all, Quite new to VBA so always looking for better ways to do "stuff" and found some interesting code on this site already. I have some code relating to an office floorplan that I have construct...
  • SnowMan55's avatar
    Feb 06, 2023

    Netrix650 << β€¦ when I click away from it >>

    The Excel object model does not support just a Click event (it does support DoubleClick and RightClick events), so it appears that you should use the SelectionChange event of the "floor" worksheets.  (So you will advance from writing macro code to writing event handler code, and get more experience with VBA objects.)  Such code is also written using the Visual Basic Editor (VBE), which offers some additional object-oriented assistance, as you will see below.

     

    If you were modeling just one floor, or otherwise were using just one "floor" worksheet, you could do handle this more simply.  But to handle "green cells" on multiple spreadsheets at once…

     

    Your FindDesk procedure needs some modifications, as here:

    Sub FindDesk()
    
        Dim deskNo  As String
        Dim objSheet    As Worksheet
        
        '----   Grab the user-specified desk identifier.
        deskNo = ActiveCell.Value
        'MsgBox deskNo
        
        '----   Select the worksheet that should contain that desk identifier,
        '       based on a floor number encoded at its start.
        '       If the identifier is "not valid", warn the user and exit.
        If Left(deskNo, 1) = 1 Then
            Set objSheet = Sheets("First floor")
        ElseIf Left(deskNo, 1) = 2 Then
            Set objSheet = Sheets("Second floor")
        ElseIf Left(deskNo, 1) = 4 Then
            Set objSheet = Sheets("Fourth floor")
        Else
            Call MsgBox(deskNo & " is not a recognized identifier." _
                , vbExclamation Or vbOKOnly)
            Exit Sub
        End If
        objSheet.Select
        
        '----   Locate the next cell (there probably should be just one) that
        '       contains the desk identifier.
        '   [I would expect an error handler to be enabled here, if not earlier,
        '   unless other code ensures that the deskNo will be found.]
        Cells.Find(What:=deskNo, After:=ActiveCell, LookIn:=xlFormulas2, LookAt:= _
            xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
            , SearchFormat:=False).Activate
        
        'NEED CODE HERE TO REVERT CELL TO ORIGINAL BACKGROUND WHEN IT IS NOT THE ACTIVE CELL
        '   [This is probably not the place to do that.  After all, doing that
        '   here would mean you would have to call this procedure again to clear
        '   the highlighting.
        '   However, this is the place to capture the cell's address or reference,
        '   and its about-to-be-changed color.]
        Call CallByName(objSheet, "CaptureCurrentStuff", VbMethod, ActiveCell)
        
        '----   Highlight that cell in green.  [You can replace vbGreen with the
        '       RGB function for some lighter or mixed-color shade.]
        ActiveCell.Interior.Color = vbGreen
        
        '----   Clean up.
        Set objSheet = Nothing
    
    End Sub

    You will note that:

     

    • You can include comments!  Those are good for others, and for yourself in weeks/months/years to come when you have to look at the code again.  And this becomes more important as the code (almost inevitably) becomes more complex.
    • By rearranging the code, you don't need three copies of the Cells.Find statement.

     

    Then open the code window for one of your "floor" worksheets.  You should see "(General)" in the dropdown at upper left and "(Declarations)" in the upper right.  Select "Worksheet" from the former, and VBE will automatically start the code for an event handler; it chooses "SelectionChanged" by default when you don't already have other event handlers.  Code to place in this module should eventually look like this (although the order of the two procedures does not matter):

    Option Explicit
    
    
        '====   WORKSHEET-SCOPE VARIABLES
        Private m_PriorDeskCell     As Range
        Private m_PriorDeskColor    As Long
    
    
    Public Sub CaptureCurrentStuff(ByRef iobjActiveCell As Range)
    
        '----   Create a worksheet-scope object reference to that cell;
        '       copy the properties that are to be retained.
        Set m_PriorDeskCell = iobjActiveCell
        m_PriorDeskColor = iobjActiveCell.Interior.Color
    
    End Sub
    
    
    Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    
        '----   Clear the highlighting, if any, from the prior
        '       active range.
        If m_PriorDeskCell Is Nothing Then
            'No action is needed.
        Else
            '  --   Reset the color.
            m_PriorDeskCell.Interior.Color = m_PriorDeskColor
            '  --   Destroy the object reference.
            Set m_PriorDeskCell = Nothing
        End If
    
    End Sub

     

    Repeat as needed for each "floor" worksheet.

     

    I am attaching a workbook with this code for you to experiment with.

Resources