"если не instr" не работает, как я думал, это должно быть в VBA

У меня есть лист со списком контрактов со столбцом для имени поставщика и один для даты окончания, я хочу сделать все пройденные даты красными, если контракт не от конкретного поставщика. Я ранее использовал InStr чтобы проверить, есть ли в ячейке строка внутри, так как я только начал с VBA, я подумал о вставке следующего в мой цикл

If Not InStr(LCase(Data.Cells(i, 4).Value), "flowserve") Then
    If CDate(Data.Cells(i, "h").Value) < Date Then _
        Data.Cells(i, "h").Font.Color = -16776961
End If

ожидая, что это будет окрашивать прошедшие даты контрактов, которые не имеют "flowserve" в названии поставщика. Но вместо этого кажется, что все прошедшие даты окрашены, как будто InStr не нашел ничего нигде.

Я тогда пытался сделать

If InStr(LCase(Data.Cells(i, 4).Value), "flowserve") Then
    'do nothing
Else
    If CDate(Data.Cells(i, "h").Value) < Date Then _
        Data.Cells(i, "h").Font.Color = -16776961
End If

и это работает, как я хотел, так что я предполагаю, что Not не работает, как я думал.

Теперь, даже если бы у меня было какое-то решение, я надеялся, что кто-нибудь сможет объяснить, что пошло не так в первом коде. Надеюсь, я был достаточно ясен.

всем заранее спасибо!

4 ответа

Решение

https://msdn.microsoft.com/en-us/library/8460tsh1%28v=vs.90%29.aspx

InStr возвращает значение не булево, попробуйте сравнить его со значением, которое оно возвращает.

If InStr(LCase(Data.Cells(i, 4).Value), "flowserve") = 0 Then
    If CDate(Data.Cells(i, "h").Value) < Date Then _
        Data.Cells(i, "h").Font.Color = -16776961
End If

Вы должны быть очень осторожны, используя Not с Integer значение. Смотрите следующие примеры:

Sub InStrTest()

Dim DataCellsTrue As String
Dim DataCellsFalse As String

DataCellsTrue = "flowserve"
DataCellsFalse = "haha"

Debug.Print InStr(LCase(DataCellsTrue), "flowserve") 'return 1
Debug.Print Not InStr(LCase(DataCellsTrue), "flowserve") 'return -2
Debug.Print CBool(InStr(LCase(DataCellsTrue), "flowserve")) 'return true
Debug.Print Not CBool(InStr(LCase(DataCellsTrue), "flowserve")) 'return false
Debug.Print InStr(LCase(DataCellsFalse), "flowserve") 'return 0
Debug.Print Not InStr(LCase(DataCellsFalse), "flowserve") 'return -1
Debug.Print CBool(InStr(LCase(DataCellsFalse), "flowserve")) 'return false
Debug.Print Not CBool(InStr(LCase(DataCellsFalse), "flowserve")) 'return true

End Sub

Не используйте логическое преобразование... вместо этого:

If InStr(LCase(Data.Cells(i, 4).Value), "flowserve") = 0 Then

Почему бы не создать свою собственную функцию, которая работает так, как вы ожидаете?

Public Function Contains(ByVal toSearch As String, ByVal toFind As String) As Boolean
    Contains = (Instr(toSearch, toFind) <> 0)
End Function

Тогда вы могли бы сказать,

If Not Contains(LCase(Data.Cells(i, 4).Value), "flowserve") Then
    If CDate(Data.Cells(i, "h").Value) < Date Then _
        Data.Cells(i, "h").Font.Color = -16776961
End If

и это работает именно так, как вы хотели.

Также обратите внимание, что вам не нужно LCase что-нибудь. Используйте опцию сравнения текста Instr вместо.

Public Function Contains(ByVal toSearch As String, ByVal toFind As String) As Boolean
    Contains = (Instr(1, toSearch, toFind, vbTextCompare) <> 0)
End Function

If Not Contains(Data.Cells(i, 4).Value, "flowserve") Then
    If CDate(Data.Cells(i, "h").Value) < Date Then _
        Data.Cells(i, "h").Font.Color = -16776961
End If
Другие вопросы по тегам