在字符串中查找特定数字?

时间:2016-12-18 23:08:15

标签: excel string vba excel-vba excel-2007

这是我的数据示例,其中name位于单元格A1中。 C列不是数据的一部分,只是为了说明需要的内容。

name    cod     should be detected?
aa              no  
aa      14;15   no
aa      1;13;7  yes 
bb      8;9;1   yes 
bb      1;17    yes 
bb      11;21   no
cz      7;8     no  
cz      7;21    no
cz      8;1;20  yes 
db      1       yes 
db      13;1    yes 

我正在尝试编写一个宏来检测出现数字1的列cod。例如,我不想找到10,13,21,但是1。此列中填写的数字从1到21。

所有cod值都是字符串,但我想找到1的位置,即使它与字符串中的其他数字混合在一起。此列中的数字始终以;分隔,中间没有空格。

以下代码将产生错误的肯定

Dim N As Range
Dim msg As String

Sub cod1()

msg = ""

For Each N In Range("A2", Range("A2").End(xlDown))
    If InStr(1, N.Offset(, 1), 1, vbTextCompare) > 0 Then
                msg = msg & "Code 1 was not supposed to be in Cod column." & vbLf
            Exit For
    End If
Next N

    If Len(msg) > 1 Then
        MsgBox msg
    Else: MsgBox "There are no code 1 values in Cod column."
    End If

End Sub

见结果:

name    cod     should be detected? problem
aa              no  
aa      14;15   no                  false positive
aa      1;13;7  yes 
bb      8;9;1   yes 
bb      1;17    yes 
bb      11;21   no                  false positive
cz      7;8     no  
cz      7;21    no                  false positive
cz      8;1;20  yes 
db      1       yes 
db      13;1    yes 

以下代码将产生错误的否定

Dim N As Range
Dim msg As String

Sub cod2()

msg = ""

For Each N In Range("A2", Range("A2").End(xlDown))
    If InStr(1, N.Offset(, 1), 1, vbTextCompare) > 0 And _
        InStr(1, N.Offset(, 1), 10, vbTextCompare) = 0 And _
        InStr(1, N.Offset(, 1), 11, vbTextCompare) = 0 And _
        InStr(1, N.Offset(, 1), 12, vbTextCompare) = 0 And _
        InStr(1, N.Offset(, 1), 13, vbTextCompare) = 0 And _
        InStr(1, N.Offset(, 1), 14, vbTextCompare) = 0 And _
        InStr(1, N.Offset(, 1), 15, vbTextCompare) = 0 And _
        InStr(1, N.Offset(, 1), 16, vbTextCompare) = 0 And _
        InStr(1, N.Offset(, 1), 17, vbTextCompare) = 0 And _
        InStr(1, N.Offset(, 1), 18, vbTextCompare) = 0 And _
        InStr(1, N.Offset(, 1), 19, vbTextCompare) = 0 And _
        InStr(1, N.Offset(, 1), 21, vbTextCompare) = 0 Then
            msg = msg & "Code 1 was not supposed to be in Cod column." & vbLf
        Exit For
    End If
Next N

    If Len(msg) > 1 Then
        MsgBox msg
    Else: MsgBox "There are no code 1 values in Cod column."
    End If

End Sub

见结果:

name    cod     should be detected? problem
aa              no  
aa      14;15   no  
aa      1;13;7  yes                 false negative
bb      8;9;1   yes 
bb      1;17    yes                 false negative
bb      11;21   no  
cz      7;8;10  no  
cz      7;21    no  
cz      8;1;20  yes                 false negative
db      1       yes 
db      13;1    yes                 false negative

那么,只有在字符串中检测到数字1时,才能使消息框*出现?

  

*代码1不应该在Cod专栏中。

寻找适用于Excel 2007及更新版本的解决方案。

3 个答案:

答案 0 :(得分:2)

您可以使用Like运算符查找字符:

Dim N As Range
Dim msg As String

Sub cod1()

    Dim expression As String
    msg = ""

    For Each N In Range("A2", Range("A2").End(xlDown))
        expression = ";" & N.Offset(, 1) & ";"
        If expression Like "*;1;*" Then
           msg = msg & "Code 1 was not supposed to be in Cod column." & vbLf
        End If
    Next N

    If Len(msg) > 1 Then
        MsgBox msg
    Else
        MsgBox "There are no code 1 values in Cod column."
    End If

End Sub

答案 1 :(得分:1)

或者,您可以使用通用UDF(用户定义函数),使用任何分隔符检测单元格内是否存在任何值:

Public Function hasItem(ByVal r As Range, item As Variant, sep As String) As Boolean
    ar = Split(r.Text, sep)
    For Each x In ar
        If Trim(CStr(x)) = Trim(CStr(item)) Then
           hasItem = True
           Exit Function
        End If
    Next
End Function

将上述UDF放在代码模块Module1中,并在列C的单元格中使用它,例如在C1中:

=IF(hasItem(B1, 1, ";"), "yes", "no")

然后,您可以将其复制/粘贴到所有C单元格中。 此外,您可以在任何VBA代码中方便地使用该功能来显示所需的消息。

答案 2 :(得分:1)

此解决方案使用Split函数在列B中生成值数组,然后比较每个数组项。

Sub Test()
Dim rDta As Range, rRow As Range
Dim aRow As Variant, vItm As Variant
Dim sMsg As String, lRow As Long

    With ThisWorkbook.Sheets("DATA.3").Cells(1).CurrentRegion   'change as required
        Set rDta = .Offset(1).Resize(-1 + .Rows.Count)
    End With

    lRow = 1
    For Each rRow In rDta.Rows
        lRow = 1 + lRow
        aRow = Split(rRow.Cells(2).Value2, ";")
        For Each vItm In aRow
            If vItm = 1 Then
                If sMsg = vbNullString Then sMsg = "Code 1 was not supposed to be in Cod column of rows:"
                    sMsg = sMsg & vbLf & vbTab & lRow
                rRow.Cells(1, 3).Value = "Code 1 was not supposed to be in Cod column." 'Remove if required
    End If: Next: Next

    If sMsg = vbNullString Then sMsg = "There are no code 1 values in Cod column."
    MsgBox sMsg

End Sub