使用VBA代码验证Excel单元格内容

时间:2018-04-19 06:01:02

标签: excel vba excel-vba

我正在寻找一种解决方案来验证并突出显示我的单元格,以防错误。

我尝试了最有前途的解决方案:正则表达式。但仍然找不到我需要的模式。

我最近的尝试是这种模式:" [A-Z-0-9 _。] "这仅适用于单元格仅包含符号而不包含其他内容的情况,如果符号是字符串的一部分则不起作用。

问题是它没有捕获文本字符串中具有奇数字符的单元格:示例C4UNIT |或B $ GROUP。

规范单元格只能包含大写字符和两个允许的符号Dash - 和Underbar _

这是我的完整代码:

Function ValidateCellContent()

    Sheets("MTO DATA").Select

    Dim RangeToCheck As Range
    Dim CellinRangeToCheck As Range
    Dim CollNumberFirst As Integer
    Dim CollNumberLast As Integer
    Dim RowNumberFirst As Integer
    Dim RowNumberLast As Integer

    '--Start on Column "1" and Row "3"
    CollNumberFirst = 1
    RowNumberFirst = 3

    '--Find last Column used on row "2" (Write OMI Headings)
    CollNumberLast = Cells(2, Columns.count).End(xlToLeft).Column
    RowNumberLast = Cells(Rows.count, 1).End(xlUp).Row

    '--Set value of the used range of cell addresses like: "A3:K85"
    Set RangeToCheck = Range(Chr(64 + CollNumberFirst) & RowNumberFirst & ":" & Chr(64 + CollNumberLast) & RowNumberLast)
    Debug.Print "Cells used in active Range = " & (Chr(64 + CollNumberFirst) & RowNumberFirst & ":" & Chr(64 + CollNumberLast) & RowNumberLast)

    For Each CellinRangeToCheck In RangeToCheck
        Debug.Print "CellinRangeToCheck value = " & CellinRangeToCheck
        If Len(CellinRangeToCheck.Text) > 0 Then

            '--Non Printables (Space,Line Feed,Carriage Return)
            If InStr(CellinRangeToCheck, " ") _
                                        Or InStr(CellinRangeToCheck, Chr(10)) > 0 _
                                        Or InStr(CellinRangeToCheck, Chr(13)) > 0 Then
                CellinRangeToCheck.Font.Color = vbRed
                CellinRangeToCheck.Font.Bold = True

                '--Allowed Characters
            ElseIf Not CellinRangeToCheck.Text Like "*[A-Z-0-9_.]*" Then
                CellinRangeToCheck.Font.Color = vbRed
                CellinRangeToCheck.Font.Bold = True

            Else
                CellinRangeToCheck.Font.Color = vbBlack
                CellinRangeToCheck.Font.Bold = False

            End If
        End If

    Next CellinRangeToCheck

End Function

2 个答案:

答案 0 :(得分:0)

试试这个:

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)
'we want only validate when cell content changed, if whole range is involved (i.e. more than 1 cell) then exit sub
If Target.Cells.Count > 1 Then Exit Sub
'if there is error in a cell, also color it red
If IsError(Target) Then
    Target.Interior.ColorIndex = 3
    Exit Sub
End If
'validate cell with our function, if cell content is valid, it'll return True
'if it i    s not valid, then color cell red
If Not ValidateText(Target.Value) Then
    Target.Interior.ColorIndex = 3
End If
End Sub

Function ValidateText(ByVal txt As String) As Boolean
Dim i As Long, char As String
'loop through all characters in string
For i = 1 To Len(txt)
    char = Mid(txt, i, 1)
    If Not ((Asc(char) >= 65 And Asc(char) <= 90) Or char = "-" Or char = "_") Then
        'once we come upon invalid character, we can finish the function with False result
        ValidateText = False
        Exit Function
    End If
Next

ValidateText = True
End Function

答案 1 :(得分:0)

我原本以为你想用RegEx解决问题。根据您的评论,您似乎正在使用Like运算符。

Like运营商

虽然Like接受可能类似正则表达式的字符范围,但两者之间存在许多差异和相似之处:

  • Like使用!来否定字符范围,而不是RegEx中使用的^
  • Like在结束括号]后不允许/知道量词,因此始终匹配每对括号[]中的单个字符。要匹配多个字符,您需要添加字符范围括号的多个副本。
  • Like无法理解高级概念,例如捕获群组预测 / lookbehind
  • 可能更多的差异......

量词的不可用性使Like成为您问题的一个非常糟糕的地方。对于单元格文本中的每个字符,您总是需要一个字符范围进行比较。因此,我可以看到使用Like运算符的唯一方法如下:

Private Function IsTextValid(ByVal stringToValidate As String) As Boolean

    Dim CharValidationPattern As String
    CharValidationPattern = "[A-Z0-9._-]"

    Dim StringValidationPattern As String
    StringValidationPattern = RepeatString(CharValidationPattern, Len(stringToValidate))

    IsTextValid = stringToValidate Like StringValidationPattern

End Function

Private Function RepeatString(ByVal stringToRepeat As String, ByVal repetitions As Long) As String

    Dim Result As String
    Dim i As Long
    For i = 1 To repetitions
        Result = Result & stringToRepeat
    Next i
    RepeatString = Result

End Function

然后,您可以将要检查的文本传递给IsTextValid,如下所示:

If IsTextValid("A.ASDZ-054_93") Then Debug.Print "Hurray, it's valid!" 

根据您的评论,将一个小的Worksheet_Change事件放入相应工作表的工作表模块中。 (您还需要在上面放置上述两个功能。或者您可以将它们公开并将它们放在标准模块中。):

Private Sub Worksheet_Change(ByVal Target As Range)

    Dim ValidationRange As Range
    Set ValidationRange = Me.Range("A2:D5")
    Dim TargetCell As Range

    For Each TargetCell In Target.Cells

        ' Only work on cells falling into the ValidationRange
        If Not Intersect(TargetCell, ValidationRange) Is Nothing Then

            If IsTextValid(TargetCell.Text) Then
                TargetCell.Font.Color = vbBlack
                TargetCell.Font.Bold = False
            Else
                TargetCell.Font.Color = vbRed
                TargetCell.Font.Bold = True
            End If

        End If

    Next TargetCell

End Sub

正则表达式

如果您想继续沿着RegEx路走,请尝试以下表达式:

[^A-Z0-9_-]+

只要传入的字符串包含您不想要的一个或多个字符,它就会生成匹配。只有有效字符的所有单元格都不应返回匹配项。

<强>解释
A-Z将匹配所有大写字母,
0-9将匹配所有数字,
_-将匹配下划线和短划线符号 前面的^将取消整个字符集,这意味着RegEx只匹配集合中的字符而不是
以下+告诉RegEx引擎匹配上述集合中的一个或多个字符。如果在那里至少有一个非法字符,您只想匹配您的输入。如果有多个,它仍应匹配。

一旦到位,使系统适应不断变化的要求(被认为是合法的不同字符)就像在[括号]之间切换一些字符一样简单。

查看live example online