VB编译错误:End If无对应Block If(含嵌套Do While)
VBA编译错误“End If without block If”的解决办法
你的代码核心问题出在Do循环的语法错误,导致编译器解析混乱,才触发了End If相关的错误提示。
问题点拆解
你写的Do循环结构不符合VBA语法规范:
Do ' 循环内容 While Not error_rng Is Nothing
正确的Do...While循环必须加上Loop关键字,结构应为Do...Loop While。因为循环结构不完整,编译器无法正确识别代码块边界,才会误判End If的匹配关系。
另外代码还有两个容易踩坑的细节:
- 变量声明不规范:原代码
Dim search_rng, error_range, result_range, result As range里,只有最后一个result是Range类型,前面三个变量默认是Variant类型,需要逐个声明类型。 - Find循环死循环风险:原代码里没有更新
error_rng的逻辑,找到第一个匹配项后会一直循环,需要添加FindNext来查找下一个匹配值,同时记录第一个匹配地址避免重复循环。
修正后的完整代码
Function GetBOMEntriesWithoutRM() As Variant Dim tbl As ListObject Dim search_rng As Range, error_rng As Range, result_rng As Range, result As Range Dim dict As New Dictionary Dim sht As Worksheet ' 补充声明sht变量 On Error GoTo Fail For Each sht In ThisWorkbook.Worksheets ' 先判断工作表是否存在表对象,避免报错 If sht.ListObjects.Count > 0 Then Set tbl = sht.ListObjects(1) If tbl.Name Like "tbBOM*" Then Set result_rng = tbl.ListColumns("Item").DataBodyRange Set search_rng = tbl.ListColumns("RMIndex").DataBodyRange Set error_rng = search_rng.Find(What:=CVErr(xlErrNA), LookIn:=xlValues) If Not error_rng Is Nothing Then Dim firstAddr As String firstAddr = error_rng.Address ' 记录第一个匹配地址,避免循环重复 Do Set result = Intersect(error_rng.EntireRow, result_rng) ' 建议存单元格值而非单元格对象,避免后续引用问题 If Not dict.Exists(result.Cells(1).Value) Then dict.Add result.Cells(1).Value, result.Cells(1).Value End If Set error_rng = search_rng.FindNext(error_rng) Loop While Not error_rng Is Nothing And error_rng.Address <> firstAddr End If End If End If Next sht GetBOMEntriesWithoutRM = dict.Items() Exit Function Fail: GetBOMEntriesWithoutRM = 0 End Function
额外说明
- 使用字典前,需要在VBA编辑器的「工具」→「引用」里勾选Microsoft Scripting Runtime,否则会报错。
- 原代码中字典存的是单元格对象,改为存单元格值能避免后续引用失效的问题。
内容的提问来源于stack exchange,提问作者ebrahim alfardan
相关产品推荐
相关产品推荐

