Tracks
如果您写过不止几个 VBA 宏,十有八九遇到过需要检查某个单元格里是否包含某段文本的情形。在 VBA 中,InStr 是那种会被用到处都是的函数之一。它告诉您一段文本在另一段文本中的出现位置。您可以用它来检查单元格中是否存在某个文本、解析文本中的值,或驱动依赖文本模式的宏中的条件逻辑。
在本指南中,我会带您了解 InStr 的语法、几个示例、比较模式如何工作(这一点让人栽跟头的次数比想象中多),以及一些您会反复复用的模式。
我建议您先从我们的Excel 基础技能路径开始,打好基础后再进阶到 VBA;如果您已有一定经验,可以学习我们的高级 Excel 函数课程,进一步了解函数如何提升数据分析效率。
什么是 VBA InStr 函数?
InStr 是一个 VBA 函数,用于返回一个字符串在另一个字符串中第一次出现的位置。
其结果表现如下:
- 找到时,返回一个数字(匹配开始的位置)
- 未找到时,返回 0
例如,如果“cat”在某字符串中的位置是 5,您会得到 5。如果不存在,则得到 0。
VBA InStr 语法
以下是完整的 InStr 语法:
InStr([start], string1, string2, [compare])
其中:
-
start(可选):告诉 VBA 从哪里开始搜索。如果省略,VBA 从位置 1 开始。 -
string1(必需):要在其中搜索的完整文本。 -
string2(必需):您要查找的文本。 -
compare(可选):定义比较方式(是否区分大小写)。如果省略,VBA 使用默认比较模式,通常区分大小写。
注意,您可以忽略 start 和 compare 参数(InStr(string1, string2))以获得更简单的用法。但如果您决定使用 compare 参数,则也必须提供 start 参数。
VBA InStr 的工作原理
可以把 InStr 想象成从左到右逐个字符阅读一句话。
该函数从 string1 开始,扫描其内容,查找 string2 首次匹配的位置。一旦找到匹配就停止,并返回开始匹配的位置。
“匹配”位置很重要,因为 VBA 的计数从 1 开始,而不是 0。因此字符串的第一个字符是位置 1,第二个是 2,以此类推。
VBA InStr 返回值详解
理解 InStr 函数的结果很直接。您会得到以下两种之一:
-
正数:表示找到了匹配,该数字表示其起始位置。
-
0:表示在字符串中任何位置都未匹配
不过,如果您的输入字符串为 Null,函数会返回 Null。虽然在基础宏中可以忽略这一点,但需要注意,这种差异可能会悄无声息地破坏某个条件判断。
VBA InStr 基本示例
下面展示几个使用 VBA InStr 函数的示例。
在句子中查找单词
检查单词“before”是否出现在备注“Deliver before noon”中。
Sub Before()
Dim result As Integer
result = InStr("Deliver before noon", "before")
MsgBox result
End Sub
上述 VBA 的结果为 9,因为“before”从第 9 个字符开始。
检查某字符是否存在
要检查字符“0”是否存在于给定字符串中,使用以下 VBA:
Sub ChExist()
Dim result As Integer
result = InStr(“A1023”, “0”)
MsgBox result
End Sub
在此情形下,任何大于 0 的结果都表示已找到该字符。
从字符串开头开始搜索
若要从字符串开头搜索,无需指定起始位置,默认从 1 开始。除非您另行指定,否则每次都是这个默认值。
Sub ChExist()
Dim result As Integer
result = InStr("Report_2026_Final", "2026")
MsgBox result
End Sub
如何在 If 语句中使用 VBA InStr
处理真实的电子表格时,您要的不只是一个数字;您需要据此做出决策。最常见的做法是将 InStr 放在 If 语句中用于筛选数据。
在本教程中,我们将使用一个示例数据集 Orders,包含列:ID、CustomerName、Email、City 和 OrderNotes。
If InStr(...) > 0 Then
由于 InStr 在未找到任何内容时返回 0,因此当结果大于 0 时,表示找到了匹配。
在下例中,它查看第 5 列 OrderNotes。如果找到“Fragile”一词,就在第 6 列写入“Handle Carefully”。
Sub ChExist()
Dim i As Integer
' Loop through rows 2 to 51
For i = 2 To 51
' Check if the order notes mention "Fragile"
If InStr(Cells(i, 5).Value, "Fragile") > 0 Then
Cells(i, 6).Value = "Handle Carefully"
End If
Next i
End Sub
对关键词进行条件检查与文本筛选
您也可以使用 InStr 函数检查字符串中的关键词,尤其是当短语略有变化时。例如,下面的代码检查备注中是否包含“Call”(如“Call on arrival”或“Call before delivery”)。然后将其标记,并在第 6 列添加标签“Cal Customer”。
Sub ChExist()
Dim i As Integer
' Loop through rows 2 to 51
For i = 2 To 51
' Check if the order notes mention “Call”
If InStr(Cells(i, 5).Value, “Call”) > 0 Then
Cells(i, 6).Value = “Call Customer”
End If
Next i
End Sub
VBA InStr 的大小写敏感与比较模式
默认情况下,InStr 区分大小写(称为 vbBinaryCompare)。比如您搜索“chicago”,但数据为“Chicago”,InStr 会返回 0。
要解决这个问题,请使用 compare 参数,其中:
-
vbBinaryCompare(默认):区分大小写(“A”不等于“a”)。 -
vbTextCompare:不区分大小写,“A”与“a”相同。
在下面的示例中,InStr 返回 0,因为它在“Fragile items”中查找“小写”的“fragile”。
Sub CheckFragile()
Dim result As Integer
result = InStr(1, "Fragile items", "fragile", vbBinaryCompare)
MsgBox result
End Sub
不过,使用 vbTextCompare 进行相同搜索会忽略大小写并返回 1。
Sub CheckFragile()
Dim result As Integer
result = InStr(1, "Fragile items", "fragile", vbTextCompare)
MsgBox result
End Sub
带起始位置的 VBA InStr
有时您并不想从字符串开头开始搜索。start 参数告诉 VBA 从哪个位置开始搜索。
在下面的示例中,start 参数被设置为 10,因此 VBA 从第 10 个字符而不是第一个开始搜索。随后在字符串较后位置找到了 "delivery"。
Sub CheckUrgent()
Dim result As Integer
result = InStr(10, “Deliver before noon - urgent delivery”, “delivery”)
MsgBox result
End Sub
上述示例的结果为 31,即 "delivery" 的起始位置。
当您想要查找第二次出现的位置,或在处理重复模式时忽略已知前缀时,此方法很有用。
VBA InStr 与 InStrRev 的比较
如您所知,InStr 从左到右搜索;而 InStrRev 则从右到左搜索。
例如,我们用 InStrRev 来查找电子邮件中的最后一个点。结果是 18,也就是“com”前面的那个点的位置。
Sub CheckChr()
Dim result As Integer
result = InStrRev("john.jacobs@email.com", ".")
MsgBox result
End Sub
当您需要某项的最后一次出现位置,或在处理文件名、电子邮件或路径时,InStrRev 会更有用。
VBA InStr 的常见用例
现在我们已经看过 VBA InStr 函数的工作示例,接着看看常见用法。
检查单元格是否包含关键词
假设您有一份客户订单数据集,需要为特定处理标记订单。下面的代码查看 OrderNotes 列,并标记包含“noon”的任何内容。
Sub ChExist()
Dim i As Integer
' Loop through rows 2 to 51
For i = 2 To 51
If InStr(1, "Deliver before noon", "noon", vbTextCompare) > 0 Then
' Logic to mark as "Morning Delivery"
End If
Next i
End Sub
验证类似邮箱的文本
您还可以用 InStr 函数快速检查邮箱格式是否有效。例如,下面的代码检查邮箱是否包含 @,若包含则在第 6 列返回“Valid Email Format”。
Sub ValidateEmail()
Dim i As Integer
' Loop through rows 2 to 51
For i = 2 To 51
If InStr(Cells(i, 3).Value, "@") > 0 Then
Cells(i, 6).Value = "Valid Email Format"
End If
Next i
End Sub
检测逗号或连字符等分隔符
您可以使用 InStr 函数检查文本中是否存在连字符、逗号或斜杠。在下面的示例中,代码遍历 OrderNotes(E 列),检查文本中是否有逗号,然后在 F 列写入结果。
Sub ValidateEmail()
Dim i As Integer
Dim commaPos As Integer
Dim OrderNotes As String
For i = 2 To 51
OrderNotes = Cells(i, 5).Value
commaPos = InStr(1, OrderNotes, ",")
' If a comma exists, mark it
If commaPos > 0 Then
Cells(i, 6).Value = "Has comma"
Else
Cells(i, 6).Value = "No comma"
End If
Next i
End Sub
使用 VBA InStr 的常见错误
即便您是经验丰富的开发者,使用 InStr 函数时也可能遇到一些问题,导致代码表现异常。以下是我碰到过的常见问题及解决思路:
-
忘记 InStr 是从 1 开始计数:请始终记住位置从 1 开始,而不是 0。若您来自 Python 或 JavaScript,这一开始会有点别扭。
-
把 InStr 当作 True/False:记住
InStr不会返回True或False。如果要判断是否找到,必须检查结果是否> 0。 -
忽视大小写敏感性:如您所知,
InStr默认区分大小写。如果大小写不重要,请在compare参数中使用vbTextCompare说明。 -
混淆 string1 和 string2:务必记住,第一个参数是“在哪儿搜”,第二个参数是“搜什么”。如果像
InStr(SearchTerm, FullText)这样调用,您会一直得到0。
VBA InStr 与其他字符串函数对比
既然 InStr 通常用于定位字符串在文本中的位置,我们来将它与其他字符串函数进行比较。
InStr vs. Like
Like 运算符用于模式匹配。例如,下面的代码检查“Fragile”,但使用了通配符 *,表示“前后任意内容”。
Sub ChExist()
Dim i As Integer
' Loop through rows 2 to 51
For i = 2 To 51
If Cells(i, 5).Value Like "*Fragile*" Then
Cells(i, 6).Value = "Handle Carefully"
End If
Next i
End Sub
如果您只需要知道某段文本是否存在,用 InStr;当需要按复杂模式检查文本时,用 Like。
InStr vs. Replace
虽然您可以用 InStr 来改变单元格的整个值,但 Replace 函数用于替换单元格中的特定文本。
在下面的示例中,Replace 函数直接将文本中的“Fragile”替换为“Handle Carefully”。
Sub ReplaceOrder()
Dim i As Integer
For i = 2 To 51
Cells(i, 5).Value = Replace(Cells(i, 5).Value, "Fragile", "Handle Carefully")
Next i
End Sub
InStr vs. Mid
Mid 函数用于从字符串中提取文本。因此,您常会将 Mid 与 InStr 搭配使用:先获取位置,再进行提取。
下面的代码从数据集中的邮箱提取域名。InStr 函数找到邮箱中“@”出现的位置,然后 Mid 从其后开始提取。最后将域名写入 H 列。
Sub ExtractDomain()
Dim i As Integer
Dim pos As Integer
Dim domain As String
For i = 2 To 51
pos = InStr(1, Cells(i, 3).Value, "@")
If pos > 0 Then
domain = Mid(Cells(i, 3).Value, pos + 1)
Cells(i, 8).Value = domain
End If
Next i
End Sub
InStr vs.Split
Split 函数用于按指定分隔符将文本拆分为多段。
在下面的示例中,代码读取 A 列的每一行,检查是否含有逗号,然后将文本拆分为两部分。将 Name → 写入 B 列,将 City → 写入 C 列。
Sub SplitTextColumn()
Dim i As Integer
Dim lastRow As Integer
Dim parts As Variant
Dim text As String
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lastRow
text = Cells(i, 1).Value
' Only split if a comma exists
If InStr(1, text, ",") > 0 Then
parts = Split(text, ",")
Cells(i, 2).Value = parts(0) ' Name
Cells(i, 3).Value = parts(1) ' City
End If
Next i
End Sub
使用 VBA InStr 的最佳实践
为避免在 VBA 中出现错误,建议遵循以下最佳实践,这些做法为我节省了不少时间:
-
当大小写不重要时使用 vbTextCompare: 由于真实数据的大小写往往不一致,如果依赖默认的比较
参数,您可能会错过匹配。 -
与“If”结合以形成清晰逻辑: 尽量包含返回值的逻辑,因为
InStr本身只给一个数字。 -
检查 > 0,而非精确位置,除非您确实需要位置。
-
保持解析过程可读。不要在一行里堆叠过多函数。
结语
InStr 虽然简单,但您最终会在各处用到它。它给出一个字符串在另一个字符串中的位置,而这个数字会驱动 VBA 中大量决策:某物是否存在、从哪里开始提取、宏接下来该做什么。单独使用时,它只是一次搜索;与 Mid、Replace,甚至 Split 等函数结合时,它就成为真正完成工作的流程一部分。
参加我们的Excel 数据分析课程,掌握高级分析技能。另外,学习我们的Excel 进阶 Power Query课程,了解数据转换与 M 语言的使用。
常见问题解答
InStr 实际返回什么?
它会返回匹配开始的位置。如果未找到,返回 0。
InStr 是否区分大小写?
是的,InStr 默认区分大小写。”Fragile” 与 ”fragile” 会被视为不同。如果您不希望区分大小写,请使用 vbTextCompare。
InStr 从 1 开始计数是什么意思?
字符串中的第一个字符位置是 1,而不是 0。当您在其他函数中使用该结果时,这一点很重要。
如果其中一个值为 Null 会怎样?
结果也将为 Null,而不是 0。
InStr 和 InStrRev 有何区别?
InStr 从左到右搜索,而 InStrRev 从右到左开始。需要最后一次出现的位置时使用后者。