Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations John Tel on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Can't get macro to run when data is changed. :( 2

Status
Not open for further replies.

cpjust

Programmer
Sep 23, 2003
2,132
US
Hi,
I'm new to VBA. I just need to do one very simple thing. I have an Excel file with QA test cases, and I want to be able to type P for pass or F for fail (or alternatively change the color to Green or Red), then have Excel automatically recalculate the number of tests that passed/failed and update the cells that contain those totals. I can get it to run if I manually tell it to run the function, but not automatically when a cell is changed.
Here is what I have so far:

Module1:
Code:
Option Explicit

Public xlApp As New CEventMod

Public Sub TrapAppEvents()
     Set xlApp.App = Application
End Sub


CEventMod:
Code:
Option Explicit
Public WithEvents App As Application

'Define these in each Sub.
Dim WHITE As Integer    ' = 0
Dim RED As Integer      ' = 3
Dim GREEN As Integer    ' = 4

Public Sub App_PassFail(ByVal Sh As Object, ByVal Target As Range)
  MsgBox ("App_PassFail() was called.")
    Dim numPass As Integer
    Dim numFail As Integer
    Dim numEmpty As Integer
    Dim row As Integer

    WHITE = 0
    RED = 3
    GREEN = 4

    For row = 3 To 23
        Cells(row, 3).Select

        If Selection.Interior.ColorIndex = GREEN Then
            numPass = numPass + 1
        ElseIf Selection.Interior.ColorIndex = RED Then
            numFail = numFail + 1
        Else
            numEmpty = numEmpty + 1
        End If
    Next row

    'Now display the results.
    Cells(3, 5).Value = numPass & " Tests Pass"
    Cells(3, 5).Font.Bold = True
    Cells(3, 5).Interior.ColorIndex = GREEN

    Cells(4, 5).Value = numFail & " Tests Fail"
    Cells(4, 5).Font.Bold = True
    Cells(4, 5).Interior.ColorIndex = RED

    Cells(5, 5).Value = numEmpty & " Tests Not Tested"
    Cells(5, 5).Font.Bold = True
    Cells(5, 5).Interior.ColorIndex = WHITE
End Sub

Private Sub App_SheetActivate(ByVal Sh As Object)
  MsgBox ("App_SheetActivate() was called.")
    Dim Target As Range
    Call App_PassFail(Sh, Target)
End Sub

Private Sub App_SheetCalculate(ByVal Sh As Object)
  MsgBox ("App_SheetCalculate() was called.")
    Dim Target As Range
    Call App_PassFail(Sh, Target)
End Sub

Private Sub App_SheetChange(ByVal Sh As Object, ByVal Target As Range)
  MsgBox ("App_SheetChange() was called.")
    Call App_PassFail(Sh, Target)
End Sub

Private Sub App_SheetDeactivate(ByVal Sh As Object)
  MsgBox ("App_SheetDeactivate() was called.")
    Dim Target As Range
    Call App_PassFail(Sh, Target)
End Sub

Private Sub App_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
  MsgBox ("App_SheetChange() was called.")
    Call App_SheetSelectionChange(Sh, Target)
End Sub

Private Sub App_WorkbookOpen(ByVal Wb As Workbook)
  MsgBox ("App_Workbook_Open() was called.")
    WHITE = 0
    RED = 3
    GREEN = 4
End Sub
As you can see, I've tried several events (even though I think I only need the Change event). What else do I need to do?
 
Why are you using a class module for this? Why not just use the worksheet event?? If you want it for all sheets, use the SheetActivate in the ThisWorkbook module. Post back if you need more help. Also, post the logic that goes to your code, that would help also.

Regards,
Zack Barresse

Simplicity is the ultimate sophistication. What is a MS MVP? PODA
- Leonardo da Vinci
 
Well like I said, I'm new to VBA... I have no idea what the difference is between a class module and a regular module...? VB confuses that hell out of me. That's why I usually stick to C++.
I was just copying some advice in one of the FAQs on this forum.
If you think a worksheet event will work, I'll give it a try. But first, what is a worksheet event and how do I use it? :p

I'm not sure what you mean by "the logic that goes with my code"? I posted my code, as well as what I'm trying to get it to do.
Basically, I have a column where I'll record a pass or fail ('P' or 'F', or by changing the background to Green or Red). The code I posted only checks the color -- I took out the text comparison for now. I want the macro to automatically update a cell that contains the number of tests that passed, as well as a cell that contains the number of tests that failed.
 
OK, I think I figured out what you meant by "Worksheet Event", and I got my macro working almost the way I want. The only things I can't get are these:
1. If I change the background color to Green or Red (without changing the text), the Change event doesn't fire.
2. If I enter a 'P' or 'F' and press Enter, I want it to activate the next cell below it. As you can see from the new code, I commented out the code that I believe should do this, but it gives me a "Method 'Range' of object '_Worksheet' failed" runtime error.

Code:
Option Explicit

'Define these in each Sub.
Dim WHITE As Integer    ' = 0
Dim RED As Integer      ' = 3
Dim GREEN As Integer    ' = 4

Public Sub PassFail()
    Dim numPass As Integer
    Dim numFail As Integer
    Dim numEmpty As Integer
    Dim row As Integer

    WHITE = 0
    RED = 3
    GREEN = 4

    'Disable events to prevent infinite loop.
    Application.EnableEvents = False

    'Check Pass/Fail status of each test.
    For row = 3 To 23
        Cells(row, 3).Select
        Dim data As String
        data = UCase(Selection.Value)

        If data = "P" Then
            Selection.Interior.ColorIndex = GREEN
        ElseIf data = "F" Then
            Selection.Interior.ColorIndex = RED
        ElseIf data = "" Then
            Selection.Interior.ColorIndex = WHITE
        Else
            MsgBox ("Invalid value entered: (" & Selection.Value & ")" & vbCrLf _
                    & "Only 'P' or 'F' are valid options.")
            data = ""
            Selection.Interior.ColorIndex = WHITE
        End If

        Selection.Value = data

        If Selection.Interior.ColorIndex = GREEN Then
            numPass = numPass + 1
        ElseIf Selection.Interior.ColorIndex = RED Then
            numFail = numFail + 1
        Else
            numEmpty = numEmpty + 1
        End If
    Next row

    'Now display the results.
    Cells(3, 5).Value = numPass & " Tests Pass"
    Cells(3, 5).Font.Bold = True
    Cells(3, 5).Interior.ColorIndex = GREEN

    Cells(4, 5).Value = numFail & " Tests Fail"
    Cells(4, 5).Font.Bold = True
    Cells(4, 5).Interior.ColorIndex = RED

    Cells(5, 5).Value = numEmpty & " Tests Not Tested"
    Cells(5, 5).Font.Bold = True
    Cells(5, 5).Interior.ColorIndex = WHITE

    'Now it's safe to re-enable events.
    Application.EnableEvents = True
End Sub


Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Column = 3 Then
        Call PassFail
        Target.Activate

'*** Method 'Range' of object '_Worksheet' failed ***
'        Range(Cells(Target.row + 1, Target.Column)).Activate
    End If
End Sub
 
You may try this:
Target.Offset(1, 0).Activate

Hope This Helps, PH.
Want to get great answers to your Tek-Tips questions? Have a look at FAQ219-2884 or FAQ181-2886
 
Hey, that works, woohoo! Thanks.
Now the only thing left is to find out if there's a way to get the Change Event (or some other event) to fire when I change the background color instead of the text.
 
Just out of curiosity though... Does anyone know why
Code:
Target.Offset(1, 0).Activate
works, but:
Code:
Range(Cells(Target.row + 1, Target.Column)).Activate
doesn't?
They look like they're doing the same thing.
 
and this ?

Range(Cells(Target.row + 1, Target.Column),cells(Target.row + 1, Target.Column)).Activate

There is NO event that will fire from a change of colour - the CHANGE event will fire when you enter / change text in a cell however....

Rgds, Geoff

We could learn a lot from crayons. Some are sharp, some are pretty and some are dull. Some have weird names and all are different colours but they all live in the same box.

Please read FAQ222-2244 before you ask a question
 
Why even try this Offset method?? If you have default settings, the selection should go down. In code, it would look like this ...

Code:
Target.Offset(1).Select

Also, you should pass the worksheet for your procedure in your change event ...


Code:
Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Column = 3 Then
        Call PassFail(Sheets(Target.Parent.Name))
    End If
End Sub

.. and the rest of your code can be referenced like so ..

Code:
Public Sub PassFail(wks As Worksheet)
    Dim numPass As Long, numFail As Long, numEmpty As Long, iRow As Long, data As String
    WHITE = 0
    RED = 3
    GREEN = 4
    Application.EnableEvents = False
    For row = 3 To 23
        data = UCase(wks.Cells(iRow, 3).Value)
        If data = "P" Then
            wks.Cells(iRow, 3).Interior.ColorIndex = GREEN
        ElseIf data = "F" Then
            wks.Cells(iRow, 3).Interior.ColorIndex = RED
        ElseIf data = "" Then
            wks.Cells(iRow, 3).Interior.ColorIndex = WHITE
        Else
            MsgBox ("Invalid value entered: (" & wks.Cells(iRow, 3).Value & ")" & vbCrLf _
                  & "Only 'P' or 'F' are valid options.")
            data = ""
            wks.Cells(iRow, 3).Interior.ColorIndex = WHITE
        End If
        wks.Cells(iRow, 3).Value = data
        If wks.Cells(iRow, 3).Interior.ColorIndex = GREEN Then
            numPass = numPass + 1
        ElseIf wks.Cells(iRow, 3).Interior.ColorIndex = RED Then
            numFail = numFail + 1
        Else
            numEmpty = numEmpty + 1
        End If
    Next row
    wks.Cells(3, 5).Value = numPass & " Tests Pass"
    wks.Cells(3, 5).Font.Bold = True
    wks.Cells(3, 5).Interior.ColorIndex = GREEN
    wks.Cells(4, 5).Value = numFail & " Tests Fail"
    wks.Cells(4, 5).Font.Bold = True
    wks.Cells(4, 5).Interior.ColorIndex = RED
    wks.Cells(5, 5).Value = numEmpty & " Tests Not Tested"
    wks.Cells(5, 5).Font.Bold = True
    wks.Cells(5, 5).Interior.ColorIndex = WHITE
    Application.EnableEvents = True
End Sub

No real reason to select anything.

HTH

Regards,
Zack Barresse

Simplicity is the ultimate sophistication. What is a MS MVP? PODA
- Leonardo da Vinci
 
cpjust said:
Now the only thing left is to find out if there's a way to get the Change Event (or some other event) to fire when I change the background color instead of the text.

No can do there buddy. You can only test for the same condition you would have to change those colors in the first place.

Regards,
Zack Barresse

Simplicity is the ultimate sophistication. What is a MS MVP? PODA
- Leonardo da Vinci
 
It seems to be working now without passing the worksheet to PassFail(). Is there any advantage of passing the worksheet also?

I had a feeling the color change event thing wouldn't work, but one can always hope. ;-)
 
The advantage to passing the worksheet is that there is no room for error. You're pretty safe because you're calling it from a worksheet event. In other cases this might not be so obvious. It's just good habit (IMHO).

As for the color change event, I'll be hoping right along with ya! :)

Regards,
Zack Barresse

Simplicity is the ultimate sophistication. What is a MS MVP? PODA
- Leonardo da Vinci
 
i know it's heresy on such a forum, but you're trying too hard.

you're thinking like a 3gl programmer (the best kind) but in this case you're trying to replicate through code things that are best left to excel.

[li]moving the focus when the user presses enter: go to tools, options, edit, move selection after enter; there is a dropdown.[/li]

[li]summing in a range based on the values in its cells: look into the COUNTA(), COUNTIF() and/or SUMIF() functions, they're groovy.[/li]

[li]changing the formatting of a cell based on its value: go to format, conditional formatting and have a play with that.[/li]

btw, if you want to see why using vba is bad when native excel will do, google "excel macro security" or go to ;)

mr s. <;)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top