需要MsgBox仅在表单上满足条件时才出现一次,并且命令按钮在MsgBox出现时消失

时间:2019-01-17 15:55:38

标签: excel vba

我有一个表单需要填写。但是,我为条件编写的代码似乎并不完整。即使满足条件,消息框也不会出现,满足条件时,消息框也不会消失。

当满足使消息框出现的条件时,我需要使消息框出现一次,并且命令按钮不可见。

请帮助。

Private Sub Worksheet_Change(ByVal Target As Range)                       
    Application.ScreenUpdating = False

    If Cells(12, 12) = "" Or Cells(14, 12) = "" Or Cells(16, 12) = "" Or Cells(18, 12) = "" Or Cells(20, 12) = "" Or Cells(22, 12) = "" Or Cells(24, 12) = "" Or Cells(26, 12) = "" Or Cells(28, 12) = "" Or Cells(30, 12) = "" Or Cells(47, 12) = "No" Then
        Range("L11").Select
        Me.CommandButton1.Visible = False

        If Cells(12, 12) = "Yes" Or Cells(14, 12) = "Yes" Or Cells(16, 12) = "Yes" Or Cells(18, 12) = "Yes" Or Cells(20, 12) = "Yes" Or Cells(22, 12) = "Yes" Or Cells(24, 12) = "Yes" Or Cells(26, 12) = "Yes" Or Cells(28, 12) = "Yes" Or Cells(30, 12) = "Yes" Then
            Me.CommandButton1.Visible = False
            'Prompt Msg Box
            MsgBox ("Please Fill In Box Below")
            Exit Sub
        End If
    Else  
        If Target.Range("$L$12") = "Yes" Or Target.Range("$L$14") = "Yes" Or Target.Range("$L$16") = "Yes" Or Target.Range("$L$18") = "Yes" Or Target.Range("$L$20") = "Yes" Or Target.Range("$L$22") = "Yes" Or Target.Range("$L$24") = "Yes" Or Target.Range("$L$26") = "Yes" Or Target.Range("$L$28") = "Yes" Or Target.Range("$L$30") = Yes And Range("B34").Characters.Count >= "5" Then
            Range("B34").Select
            Me.CommandButton1.Visible = True               
        ElseIf Cells(5, 4) > "" Or Cells(6, 4) > "" Or Cells(7, 4) > "" Or Cells(8, 4) > "" Or Cells(12, 12) = "No" Or Cells(14, 12) = "No" Or Cells(16, 12) = "No" Or Cells(18, 12) = "No" Or Cells(20, 12) = "No" Or Cells(22, 12) = "No" Or Cells(24, 12) = "No" Or Cells(28, 12) = "No" Or Cells(30, 12) = "No" Or Cells(47, 12) = "" Or Cells(47, 12) = "Yes" And Cells(49, 3) > "" Then
            Me.CommandButton1.Visible = True
            Application.ScreenUpdating = True
        Else
            Me.CommandButton1.Visible = False
            Application.ScreenUpdating = True
            Exit Sub
        End If
    End If
End Sub

1 个答案:

答案 0 :(得分:0)

  

Range.B34内的字符条件大于或等于5时不会出现

然后这个:

    If Target.Range("$L$12") = "Yes" Or _
       Target.Range("$L$14") = "Yes" Or  _
       Target.Range("$L$16") = "Yes" Or _
       Target.Range("$L$18") = "Yes" Or _
       Target.Range("$L$20") = "Yes" Or _
       Target.Range("$L$22") = "Yes" Or _
       Target.Range("$L$24") = "Yes" Or _
       Target.Range("$L$26") = "Yes" Or _
       Target.Range("$L$28") = "Yes" Or _
       Target.Range("$L$30") = Yes And _
       Range("B34").Characters.Count >= "5" _
 Then

由于这是一个Worksheet.Change处理程序,因此Target参数是对刚刚更改的单元格的引用。 Target.Range("$L$12")毫无意义,因为这与修改的单元格有关,与$L$12处的单元格无关。

Range("B34")看起来不错:它隐式Me.Range("B34"),即该特定工作表上的单元格$B$34

因此,我希望所有Target.Range(...) = "Yes"条件都不会达到True

这使得And操作也不会评估为True


让我们清理一下。从MatchesAny函数开始:

Public Function MatchesAny(ByVal value, ParamArray values()) As Boolean
    Dim i As Long
    For i = LBound(values) To UBound(values)
        If values(i) = value Then
            MatchesAny = True
            Exit Function
        End If
    Next
End Function

这将大大提高评估所有这些条件的效率:现在,一旦知道结果,我们就返回结果。另一方面,链接Or运算符会使If语句得到完全评估,然后VBA才能知道是否要输入条件块。

条件变为:

If Me.Range("B34").Characters.Count >= 5 And _
    MatchesAny("Yes", Me.Range("L12").Text, _
                      Me.Range("L14").Text, _
                      Me.Range("L16").Text, _
                      Me.Range("L18").Text, _
                      Me.Range("L20").Text, _
                      Me.Range("L22").Text, _
                      Me.Range("L24").Text, _
                      Me.Range("L26").Text, _ 
                      Me.Range("L28").Text, _
                      Me.Range("L30").Text) _
Then

请注意,这并不等效:在您的版本中,仅当L30为“是”时,B34中的字符数才有意义。在此版本中,B34中的字符数与其他单元格无关。这是因为逻辑运算符的工作方式:And的优先级高于Or,因此您的情况像foo Or (bar And baz),而我的情况像(foo Or bar) And baz,我相信这就是您的情况打算做。同样,文字5也不应该是"5",它是字符串文字-尽管可以进行隐式转换,但是这种隐式转换使事情变得比需要的更加混乱。

最不合格的Cells调用也令人困惑:为什么在一个地方将L12称为Range("$L$12"),而在另一个地方将Cells(12, 12)称为?

If Cells(12, 12) = "" Or _
   Cells(14, 12) = "" Or _
   Cells(16, 12) = "" Or _
   Cells(18, 12) = "" Or _
   Cells(20, 12) = "" Or _
   Cells(22, 12) = "" Or _
   Cells(24, 12) = "" Or _
   Cells(26, 12) = "" Or _
   Cells(28, 12) = "" Or _
   Cells(30, 12) = "" Or _
   Cells(47, 12) = "No" _
Then

我将使其使用相同的寻址方式(虽然可行,但一致性很重要),然后再次使用MatchesAny来缩短条件评估:

If Me.Range("L47").Text = "No" Or _
    MatchesAny("", Me.Range("L12").Text, _
                   Me.Range("L14").Text, _
                   Me.Range("L16").Text, _
                   Me.Range("L18").Text, _
                   Me.Range("L20").Text, _
                   Me.Range("L22").Text, _
                   Me.Range("L24").Text, _
                   Me.Range("L26").Text, _ 
                   Me.Range("L28").Text, _
                   Me.Range("L30").Text) _
Then

现在很明显,这两个条件会重复出现,我想出了一种进一步简化它的方法-假设我们将这组特定的单元格称为InputCells,那么类似的话就很有意义:

Private Function AnyInputCellMatches(ByVal matchValue As String) As Boolean
    AnyInputCellMatches = MatchesAny(matchValue, _
        Me.Range("L12").Text, _
        Me.Range("L14").Text, _
        Me.Range("L16").Text, _
        Me.Range("L18").Text, _
        Me.Range("L20").Text, _
        Me.Range("L22").Text, _
        Me.Range("L24").Text, _
        Me.Range("L26").Text, _ 
        Me.Range("L28").Text, _
        Me.Range("L30").Text)
End Function

现在我们有了这样的东西:

If AnyInputCellMatches("") Or Me.Range("L47").Text = "No" Then
    Me.CommandButton1.Visible = False
ElseIf AnyInputCellMatches("Yes") And Me.Range("B34").Characters.Count >= 5 Then
    Me.CommandButton1.Visible = True
End If

这样可以更轻松地判断某处是否存在问题,并且仅保留一个位置来维护需要检查的单元格列表。