2016-12-18 4 views
1

Это образец моих данных, где 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 

Я пытаюсь написать макрос, чтобы обнаружить на колонке cod, где появляется номер 1. Например, я не хочу найти 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 не должен находиться в колонке трески.


Ищет решение, которое работает с Excel 2007 и более новыми версиями.

ответ

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 
+0

Все 3 ответа (ThunderFrame, A.S.H и EEM), которые имели разные подходы, хорошо работали в моих образцах и фактических данных (+1 для всех них). Затем я принимаю это, потому что структура кода была похожа на то, что я уже использовал. –

1

В качестве альтернативы, вы можете иметь общий UDF (User-Defined Function), который определяет существование любого значения внутри ячейки, используя любые сепаратор:

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 для отображения требуемых сообщений.

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 
Смежные вопросы