Home » excel » excel – Show MsgBox only once

excel – Show MsgBox only once

Posted by: admin May 14, 2020 Leave a comment

Questions:

I have a VBA script, that goes as follows:

1, it will run when particular sheet is selected

2, it will check if condition is True

3, if so, show MsgBox

Private Sub Worksheet_Activate()
Dim current As Double
current = Round(((Range("AJ9").Value / Range("AG9").Value) * 100), 1)
If Range("AJ9").Value / Range("AG9").Value < 0.15 Then
    MsgBox "Here is some message and some value: " & current & "%."
End If
End Sub

I want to show this MsgBox only first time, when user come to the sheet. Now it pops up every time user get to the sheet.
I have tried to use variable from different Sub, but it seems like it doesn’t work.

Public read As Boolean
Sub readValue(Optional readArg As Boolean)
   MsgBox readArg 
   read = (readArg Or False)
End Sub

and then I modified first Sub like this:

Private Sub Worksheet_Activate()
Dim current As Double
current = Round(((Range("AJ9").Value / Range("AG9").Value) * 100), 1)
Call readValue
If read = False Then
    If Range("AJ9").Value / Range("AG9").Value < 0.15 Then
        MsgBox "Here is some message and some value: " & current & "%."
        readValue read = True
    End If
End If

But the MsgBox readArg always says False. It’s like it isn’t sending value at all. Therefore MsgBox shows everytime user come to the sheet.

What am I doing wrong?

How to&Answers:

ByRef assignment of an Optional parameter makes the mechanism rather flakey, and the flag shouldn’t need to be Public.

Following execution, read is initialized with False, and then the Activate handler eventually runs; readValue doesn’t specify a default for its optional parameter, so the first invocation (Call readValue, …note that Call is redundant) pops a msgbox that says “False”, and then read = (readArg Or False) evaluates to False… and there’s the bug, because at this point you’d need the flag to be Trueunconditionally.

You’re on the right track, but it can be much simpler than that:

Option Explicit
Private alreadyPrompted As Boolean

Private Sub Worksheet_Activate()

    If alreadyPrompted Then Exit Sub

    If Range("AJ9").Value / Range("AG9").Value < 0.15 Then
        Dim current As Double
        current = Round(((Range("AJ9").Value / Range("AG9").Value) * 100), 1)

        MsgBox "Here is some message and some value: " & current & "%."
        alreadyPrompted = True

    End If
End Sub

Another way would be to make the flag a Static local; such declarations retain their value between procedure calls – be careful not to abuse it though, because this can easily become confusing:

Option Explicit

Private Sub Worksheet_Activate()
    Static alreadyPrompted As Boolean
    If alreadyPrompted Then Exit Sub

    If Range("AJ9").Value / Range("AG9").Value < 0.15 Then
        Dim current As Double
        current = Round(((Range("AJ9").Value / Range("AG9").Value) * 100), 1)

        MsgBox "Here is some message and some value: " & current & "%."
        alreadyPrompted = True

    End If
End Sub

Note that I’ve made the calculation of current conditional in both snippets, because the variable doesn’t need to be computed if the condition isn’t true in the first place.