Условие Instr не работает с 2 или более условиями - PullRequest
3 голосов
/ 08 ноября 2011

У меня есть следующее условие INSTR в Excel VBA, которое не работает (все время)

STR_TEXT="SKU1234 $100/10'  $200/20'"  ' < example string

IF INSTR(STR_TEXT,"/10'") AND INSTR(STR_TEXT,"/20'") THEN
  ' code
ELSE
  ' code
END IF

По какой-то неясной причине кажется, что он не может проверить оба условия, поэтому первый IF, даже если оба условия совпадают, не работает и переходит к ELSE.

Работает следующее:

STR_TEXT="SKU1234 $100/10'  $200/20'"  ' < example string

IF INSTR(STR_TEXT,"/10'") THEN
       IF INSTR(STR_TEXT,"/20'") THEN
               ' code
       END IF
ELSE
  ' code
END IF

Как видите, если я разделяю условия на первом IF, оно работает. Но я бы предпочел, чтобы оба условия были в одном и том же IF, поскольку код «чище».

Кто-нибудь знает, почему и / или как это исправить, не помещая IF внутри другого IF?

Ответы [ 4 ]

10 голосов
/ 08 ноября 2011

Другие ответы указывают на самую важную вещь, которая заключается в том, что InStr фактически возвращает числовую позицию одной строки в другой (или 0, если нужная строка не найдена).Как говорится, вы должны проверять условие <result> > 0 в вашем If утверждении.Я просто расскажу, в чем причина вашего наблюдения, что ваш тест «не работает ( все время )».Это хороший шанс насладиться древней I- <3-BASIC удивительностью. </p>

Что происходит, так это в данном случае (подробнее см. Ниже) "VBA" And оператор (и Or и т. д.) на самом деле является побитовым оператором, а не логическим .То есть, если вы передадите ему два целочисленных операнда, он будет выполнять побитовую обработку And и вернет полученное целое число.Например, 42 And 99 оценивается как 34, потому что (в двоичном формате) 0101010 And 1100011 равно 0100010.

Теперь, обычно, если вы используете значения VBA Boolean, And работает как логическийоператор.Это связано с тем, что в VBA константа True равна числовому значению -1, а False равна числовому нулю.Поскольку VBA представляет -1 как двоичное число со всеми установленными битами и ноль как двоичное число со всеми очищенными битами, вы можете видеть, что двоичные операции становятся эквивалентными логическим операциям.-1 And <something> всегда равняется <something>.Но если вы просто передадите старые числа в And, вы получите обратно число, и оно не всегда будет числовым значением, равным константам True или False.

Рассмотрим простой пример (набранный в окне Immediate):

x="abc"
?Instr(x,"a")
 1 
?Instr(x,"b")
 2 
?Instr(x,"c")
 3 
?(Instr(x,"a") and Instr(x, "b"))
 0 
?(Instr(x,"a") and Instr(x, "c"))
 1 

Теперь напомним, что оператор If VBA обрабатывает любой ненулевой числовой аргумент так же, как True, инулевой числовой аргумент совпадает с False.Когда вы соберете все это вместе, вы обнаружите, что инструкция вашего примера:

IF INSTR(STR_TEXT,"/10'") AND INSTR(STR_TEXT,"/20'") THEN 

будет иногда выбирать первое условие, а иногда и второе, в зависимости от того, что находится в искомой строке.Это потому, что иногда побитовая операция And возвращает ноль, а иногда - ненулевой.Точный результат будет зависеть от точного положения найденных строк, и это явно не то, что вы ожидаете.Так что это , почему совет, который вы уже получили, имеет значение в деталях.

РЕДАКТИРОВАТЬ: Как отметил Хью Аллен в этом комментарии:

Оператор VBA «И» вычисляет второй аргумент, когда первый равен false?

Оператор VBA And действительно возвращает Boolean значения обоих его операндов Boolean.Поэтому говорить, что это побитовый оператор, не совсем правильно.Это правильно для этой проблемы, хотя.Кроме того, тот факт, что он может действовать как побитовый оператор, означает, что он не может действовать как "нормальный", чисто логический оператор.Например, поскольку он должен оценивать оба операнда, чтобы определить, являются ли они числами или нет, он не может закорачивать.

4 голосов
/ 08 ноября 2011

EXMAPLE:

if instr(str_Text,"/10'") > 0 AND instr(str_text,"/20'") > 0 then

Тим говорит, что функция instr возвращает позицию в строке первого экземпляра искомой строки ..

, поэтому в вашемпример: 13 возвращается для instr (str_Text, "/ 10 ').

Когда VBA читает вашу версию instr (str_text," / 10; ") (без> 0), тогда он видитчто результат не равен 1 (что означает «истина»), поэтому он всегда попадает в другое)

1 голос
/ 08 ноября 2011

Instr () возвращает числовой результат: если он> 0, то проверяемая строка содержит искомую строку.

Sub Test()

    Dim str_text As String

    str_text = "SKU1234 $100/10'  $200/20'" ' < example string

    If InStr(str_text, "/10'") > 0 And InStr(str_text, "/20'") > 0 Then
        MsgBox "Both"
    Else
        MsgBox "Only one, or none"
    End If

End Sub
0 голосов
/ 04 августа 2017

Функция INSTR вернет индекс sub-string, который вы пытаетесь найти в string.

Таким образом, следующее будет давать числовое значение вместо boolean value:

INSTR(STR_TEXT,"/10'")

Чтобы исправить это, используйте следующее, которое даст ответ boolean, который требуется, еслисостояние:

INSTR(STR_TEXT,"/10'") > 0 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...