VBA中For Each循环找到首个匹配项后提前退出问题求助
问题分析
循环提前终止的核心原因是:在遍历NR.RefersToRange.Columns(2).Cells的过程中修改行的隐藏状态,导致Excel对这个动态范围的引用发生变化,For Each循环无法继续遍历原本的所有单元格。另外,代码里的Else分支会强制取消非"Sunday"行的隐藏状态,这不仅可能偏离你“只隐藏匹配行”的需求,还会进一步干扰遍历流程。
修正方案
我们可以先将需要遍历的单元格范围提前固化为静态集合,避免动态范围受行隐藏状态的影响;同时调整逻辑,确保遍历不受操作干扰。
修正后的代码
Public Sub Test1() Dim NR As Name Dim CellCount As Integer Dim Cell As Range Dim targetColumn As Range ' 提前存储目标列范围 CellCount = 0 For Each NR In ThisWorkbook.Names If InStr(NR.Name, "Date") <> 0 Then ' 提前固化目标列的范围,避免行隐藏导致范围变化 Set targetColumn = NR.RefersToRange.Columns(2) ' 遍历固化后的范围里的每个单元格 For Each Cell In targetColumn.Cells If InStr(Cell.Text, "Sunday") = 1 Then CellCount = CellCount + 1 MsgBox CellCount ' 去掉多余括号,VBA中直接调用MsgBox无需括号 Cell.EntireRow.Hidden = True ' 若无需强制显示非Sunday的行,保留注释即可;若需要则取消注释 ' Else ' Cell.EntireRow.Hidden = False End If Next Cell End If Next NR End Sub
关键修改说明
- 固化目标范围:新增
targetColumn变量,提前将NR.RefersToRange.Columns(2)赋值给它,后续行隐藏操作不会影响遍历的集合,确保能遍历所有原始单元格。 - 简化MsgBox写法:去掉MsgBox后的括号,VBA中直接调用MsgBox时无需括号(仅当需要接收返回值时才需要)。
- 可选逻辑调整:注释掉Else分支,如果你确实需要强制显示非"Sunday"的行,可取消注释,此时遍历依然能正常完成。
额外优化建议
如果目标列是日期类型,推荐用日期函数判断而非文本匹配,可靠性更高:
' 替换原有的InStr判断为日期星期判断 If Weekday(Cell.Value, vbSunday) = 1 Then ' ... 后续隐藏等操作 End If
这种方式不受单元格显示格式影响,只要单元格值是日期,就能准确判断是否为周日。
内容的提问来源于stack exchange,提问作者Wayne C.
相关产品推荐
相关产品推荐

