InStr is overloaded by way of Variant parameters
The InStr
function has 4 optional parameters at design-time, but at least 2 arguments must be provided at run-time. The first 3 parameters to InStr
are all Variant
, which allows InStr
to support two different syntaxes and effectively mimic an overloaded function. That’s one of the reasons that String1
and String2
are defined as Variant
types and not as String
types. Start
could be a Long
, but it is a Variant
type too.
In the following 4 examples, x
is always assigned the value 4
Option 1 — Using the defined parameter order or name-meanings
The Function signature behaves as it is defined:
Function InStr([Start], [String1], [String2], [Compare As VbCompareMethod = vbBinaryCompare])
x = VBA.InStr(1, "food", "D", vbTextCompare) '4
x = VBA.InStr(Start:=1, String1:="food", String2:="D", Compare:=vbTextCompare) '4
Option 2 — Using the alternate order or name-meanings
The Function signature behaves as though it was defined like:
Function InStr([String1], [String2], , [Compare As VbCompareMethod = vbBinaryCompare])
Which in effect means that Start
should be used as if it is String1
and String1
should be used as if it is String2
. The String2
argument must be omitted, or you get a Type Mismatch
error.
x = VBA.InStr("food", "D", , vbTextCompare) '4
x = VBA.InStr(Start:="food", String1:="D", Compare:=vbTextCompare) '4
Using Named Parameters
But as you’ve discovered, the InStr
function suffers from Syntax and/or Compilation errors when using named parameters:
Syntax Error: Expected List Separator
When all of the parameters are named:
x = InStr(Start:=1, String1:="foo", String1:="foo", Compare:=vbBinaryCompare)
You get:
Syntax Error: Expected List Separator
Compile error: Object doesn’t support named arguments
When some of the parameters are named:
x = InStr(1, String1:="foo", String2:="foo", Compare:=vbBinaryCompare)
You get:
Compile error: Object doesn’t support named arguments
Same errors with StrComp function
The StrComp
function doesn’t appear to have any overloaded-type functionality, but it has the same problems with Syntax and Compilation errors:
x = StrComp(String1:="foo", String2:="foo", Compare:=vbBinaryCompare) 'Syntax Error: Expected List Separator???
x = StrComp("foo", String2:="foo", Compare:=vbBinaryCompare) 'Compile error: Object doesn't support named arguments
But as the OP has discovered, the error doesn’t occur with InStrRev
.
So, what do InStr
and StrComp
have in common that is different to InStrRev
and seemingly all other VBA functions?
Well, InStr
and StrComp
both share these features:
- The functions are defined in the first referenced Type Library
- The functions are defined in a TLB/COM module
- All parameters except the last are
Variant
type. - The last parameter is an
Enum
with a default value - The return value is a Variant
I can’t find any other functions in the VBA library that share those characteristics, so I suspect there’s a compilation bug related to those characteristics.
Qualifying the function fixes the problem!?!?
Both InStrRev
and StrComp
can be used with all/some named parameters, if the function is qualified by the library name or module name:
'InStr Vanilla usage:
x = Strings.InStr(Start:=1, String1:="food", String2:="D", Compare:=vbTextCompare) '4
x = VBA.InStr(Start:=1, String1:="food", String2:="D", Compare:=vbTextCompare) '4
'InStr Alternate usage:
x = Strings.InStr(Start:="food", String1:="D", Compare:=vbTextCompare) '4
x = VBA.InStr(Start:="food", String1:="D", Compare:=vbTextCompare) '4
'StrComp usage
x = Strings.StrComp(String1:="food", String2:="D", Compare:=vbTextCompare) '1
x = VBA.StrComp(String1:="food", String2:="D", Compare:=vbTextCompare) '1
Your understanding of the InStr
function is correct. Your assumption about the Str
function, however, is incorrect
The Str
function adds a leading space if there is no sign, so you are comparing a single character to two characters: " 0"
which will always be false.
When numbers are converted to strings, a leading space is always reserved for the sign of Number. If Number is positive, the returned string contains a leading space, and the plus sign is implied.
Use Cstr(i)
to avoid this,
If InStr(cell.Text, CStr(i)) <> 0 Then
or nest your Str
function within a Trim
:
If InStr(cell.Text, Trim(Str(i))) <> 0 Then
Note also that 0 = "0"
in VBA, so you technically don’t need to cast explicitly to string, though it’s probably a good habit.
If Instr(cell.Text, i) <> 0 Then ' <-- this should also work
Есть скрипт, примитивный, грузит массив с словами и каждое из слов ищет в подстроке s, но загвоздка в том, что InStr всегда возвращает 0 вне зависимости есть ли подстрока в s или нет. Вопрос, почему это может быть?
Dim A As Variant
Const strFileNameA = "C:UsersvpuhoffDesktopCatACatAbinDebugasdA.inf
Open strFileNameA For Input As #1
A = Split(Input$(LOF(1), #1), vbLf)
Close #1
Dim s2 As String
s2 = Trim(A(i))
If (InStr(1, s, s2) > 0) Then
1 / 1 / 0 Регистрация: 19.07.2018 Сообщений: 40 |
|
1 |
|
01.12.2018, 19:39. Показов 1495. Ответов 9
Ребята! Ну ладно еще когда речь идет о сложных логических конструкциях (чего-то недоучел), но базовые функции???! Недавно столкнулся с лабудой, от которой глаза на лоб полезли: созданная программа в среде VB.NET (2010) на 80% машин идет, но есть экземпляры, где она лагает — стал разбираться и локализовал причину на «неоднозначной» (!!!) работе функции, вынесенной в топик! При адекватной работе функция InStr() возвращает 1, но на некоторых машинах — 0! Не находит вхождения (( Что за чушь такая?! С чем это может быть связано и как ее, собаку, заставить ОДИНАКОВО работать везде (это — то же самое, что просить оператор умножения давать всегда «4» при подстановке двоек в качестве аргументов)… Просто жуть какая-то: может ли кто-либо предположить причины подобного поведения?
0 |
8927 / 4839 / 1885 Регистрация: 11.02.2013 Сообщений: 10,246 |
|
01.12.2018, 19:48 |
2 |
Что именно не находит? Поиск регистрозависимый? Что в аналогичных случаях даёт метод String.IndexOf?
1 |
1 / 1 / 0 Регистрация: 19.07.2018 Сообщений: 40 |
|
01.12.2018, 20:08 [ТС] |
3 |
вот маленький участок с данным событием: If i * j = 0 Then ТАК ВОТ. на немногочисленных машинах (примерно 20%) первая проверка вхождения дает 0 вместо 1!
0 |
8927 / 4839 / 1885 Регистрация: 11.02.2013 Сообщений: 10,246 |
|
01.12.2018, 20:29 |
4 |
В данном случае, даже не хочется разбираться что именно не так, потому что валидность URL нужно проверять иначе. А именно, методом Uri.IsWellFormedUriString.
1 |
1 / 1 / 0 Регистрация: 19.07.2018 Сообщений: 40 |
|
01.12.2018, 20:46 [ТС] |
5 |
спасибо за ответ)) … а вот мне разобраться хочется: потому что вопрос не в том, как правильно проверять валидность URL (это вообще к сути работы моей проги не имеет никакого отношения — так, промежуточный момент, который можно исключить), а в том, почему одна и та же цепочка операторов и функций VB.NET на одной машине (в одном окружении) дает один результат, а на другой — другой. Я могу одно сказать: если внешние условия могут влиять на результат (а такое нельзя исключить на 100%) — вводятся дополнительные параметры в оператор. В рассматриваемом таковой только один — тот самый «тип сравнения». Я пробовал и 0 и 1 — результат все тот же (не попробовал только 2 для полноты счастья)… Но за подсказки (использовать другой метод) — спасибо: на работе проверю в понедельник (т.к. на моей домашней машинке все работает нормально: я не могу спровоцировать описанную тут ситуацию).
0 |
Администратор 15613 / 12582 / 4989 Регистрация: 17.03.2014 Сообщений: 25,558 Записей в блоге: 1 |
|
02.12.2018, 19:17 |
6 |
gva62, проверь что в входной строке нет каких-то левых символов.
1 |
1 / 1 / 0 Регистрация: 19.07.2018 Сообщений: 40 |
|
03.12.2018, 13:54 [ТС] |
7 |
добрый день, OwenGlendower )) спасибо за Вашу реакцию на мои проблемы!
0 |
Администратор 15613 / 12582 / 4989 Регистрация: 17.03.2014 Сообщений: 25,558 Записей в блоге: 1 |
|
03.12.2018, 14:37 |
8 |
gva62, вместо msgbox лучше записать текст в файл и посмотреть данные в hex виде сравнив их с рабочей строкой. Возможно код у точки другой будет (это как пример).
0 |
COM‐пропагандист 763 / 720 / 139 Регистрация: 18.12.2014 Сообщений: 2,006 Записей в блоге: 4 |
|
04.02.2019, 10:06 |
9 |
Лучше приведите код.
0 |
68 / 58 / 15 Регистрация: 22.10.2012 Сообщений: 308 |
|
04.02.2019, 22:03 |
10 |
если эти 20% машин работают на windows XP то проблема может быть именно в операционках
0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
04.02.2019, 22:03 |
Помогаю со студенческими работами здесь Оператор «+» для типов «String» и «System.Windows.Forms.ComboBox.ObjectCollection» не определен Как написать регулярное выражение для выдергивания английских букв и символов: «+», «,», «:», «-«, » «, «!», «?» и «.» В зависимости от времени года «весна», «лето», «осень», «зима» определить погоду «тепло», «жарко», «холодно», «очень холодно»
Искать еще темы с ответами Или воспользуйтесь поиском по форуму: 10 |
Hi,
I’m working on a project that tracks daily changes in the prices and kinds of books. I get a data dump each day, which I extract into an Excel sheet and compare to the previous day’s. To track the changes, I start by creating a unique ID I call «primaryKey»
which is a concatenation of the book number, edition, and ISBN, each separated by a vertical line «|» symbol. I sort the data using this key and compare the data using VLookup (with 4th parameter True). Then, I use InStr to see if the book number is contained
in a primaryKey in yesterday’s data; if it is not, it must be a new book. However, there are times when InStr returns 0 even when the book number is present in the primaryKey. The issue is not spaces/empty characters, I checked this using the Len function
in a MsgBox.
Here’s a code snippet:
For j = 2 To jRow primaryKey = tData.Range("A" & j).Value If StrComp(book, CStr(tData.Range("F" & j).Value), vbTextCompare) <> 0 Then book = tData.Range("F" & j).Value If InStr(1, Application.VLookup(primaryKey, yData.Range("A:A"), 1, True), book & "|", vbTextCompare) > 0 Then 'MsgBox (primaryKey & " " & Len(primaryKey) & " " & book & "| " & Len(book) & " " & InStr(1, Application.VLookup(primaryKey, yData.Range("A:A"), 1, True), book & "|", vbTextCompare) & " Not New") newBook = False Else 'MsgBox (primaryKey & " " & Len(primaryKey) & " " & book & "| " & Len(book) & " " & InStr(1, Application.VLookup(primaryKey, yData.Range("A:A"), 1, True), book & "|", vbTextCompare)) Do tData.Range("A" & j & ":O" & j).Copy Destination:=newDelCons.Range("A" & newDelRow) newDelCons.Range("P" & newDelRow).Value = "New Book" newDelRow = newDelRow + 1 j = j + 1 Loop While InStr(1, tData.Range("A" & j).Value, book & "|", vbTextCompare) > 0 newBook = True j = j - 1 End If End If
Sometimes the InStr function correctly identifies when the book number is found in the primaryKey, other times it does not. Any ideas why?