同一工作表内两段VBA代码运行异常求助:第一段触发第二段调试
问题分析与解决方案
看起来你遇到的核心问题是两个Worksheet_Change逻辑互相干扰,加上代码里的几个细节问题导致第一段代码失效、触发第二段调试。我帮你拆解下问题点,再给出修复后的完整代码:
主要问题点
- 递归触发事件:第一段代码里修改了
Monitoring和coordonnées工作表的内容(插入行、写入单元格),这会再次触发Worksheet_Change事件,导致代码反复执行,不仅干扰第一段逻辑,还会意外触发第二段代码的判断。 - 错误处理逻辑不当:第一段的错误处理里不管有没有错误都会调用
CopyHighlightedData_Click,这个外部过程可能干扰当前事件的执行,而且错误后没有正确重置错误状态。 - 未处理多单元格修改:第二段代码直接用
Target = "oui",如果用户一次性修改多个单元格(比如粘贴),这行代码会直接报错进入调试。 - 变量类型不合理:用
Integer存储行号,当工作表行数超过32767时会溢出,应该用Long类型。
修复后的完整代码
Option Explicit Private Sub Worksheet_Change(ByVal Target As Range) ' 关闭事件触发,防止修改工作表时递归调用 Application.EnableEvents = False On Error GoTo Cleanup ' 统一错误处理,确保事件最后能恢复 ' --- 第一段代码:复制名称到其他工作表 --- If Target.Column = 2 Or Target.Column = 3 Then Dim wsSuiviDeProjet As Worksheet Set wsSuiviDeProjet = ThisWorkbook.Sheets("SuiviDeProjet") Dim NewRowCount As Long NewRowCount = Target.Row ' 检查当前行的B和C列是否都有内容 If wsSuiviDeProjet.Cells(NewRowCount, 2).Value <> "" And wsSuiviDeProjet.Cells(NewRowCount, 3).Value <> "" Then Dim wsMonitoring As Worksheet Set wsMonitoring = ThisWorkbook.Sheets("Monitoring") Dim wsCoordonnées As Worksheet Set wsCoordonnées = ThisWorkbook.Sheets("coordonnées") ' 处理Monitoring工作表的逻辑 If wsSuiviDeProjet.Cells(NewRowCount, 3).Value = "oui" Then Dim LastRowMonitoringSheet As Long LastRowMonitoringSheet = wsMonitoring.Cells(wsMonitoring.Rows.Count, 1).End(xlUp).Row Dim dataExists As Boolean dataExists = False Dim ii As Long For ii = 2 To LastRowMonitoringSheet If wsMonitoring.Cells(ii, 1).Value = wsSuiviDeProjet.Cells(NewRowCount, 2).Value Then dataExists = True Exit For End If Next ii If Not dataExists Then ' 插入新行 wsMonitoring.Rows(LastRowMonitoringSheet + 1).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove ' 写入数据到新行 wsMonitoring.Cells(LastRowMonitoringSheet + 1, 1).Value = wsSuiviDeProjet.Cells(NewRowCount, 2).Value End If End If ' 处理coordonnées工作表的逻辑 Dim LastRowCoordinatesSheet As Long LastRowCoordinatesSheet = wsCoordonnées.Cells(wsCoordonnées.Rows.Count, 1).End(xlUp).Row Dim dataExistsM As Boolean dataExistsM = False Dim i As Long For i = 5 To LastRowCoordinatesSheet If wsCoordonnées.Cells(i, 1).Value = wsSuiviDeProjet.Cells(NewRowCount, 2).Value Then dataExistsM = True Exit For End If Next i If Not dataExistsM Then wsCoordonnées.Cells(LastRowCoordinatesSheet + 1, 1).Value = wsSuiviDeProjet.Cells(NewRowCount, 2).Value ' MsgBox ("data inserted in COORDINATES SHEET") End If End If ' 如果你确实需要调用这个过程,建议移到错误处理外,或者确认它不会触发事件 ' Call CopyHighlightedData_Click End If ' --- 第二段代码:D列为"oui"时清除对应AE列 --- If Not Intersect(Target, Me.Range("D:D")) Is Nothing Then ' 处理多单元格修改的情况 Dim cell As Range For Each cell In Intersect(Target, Me.Range("D:D")) If UCase(cell.Value) = "OUI" Then ' 不区分大小写,更健壮 Me.Range("AE" & cell.Row).ClearContents ' 用ClearContents只清除内容,保留格式 End If Next cell End If Cleanup: ' 恢复事件触发 Application.EnableEvents = True ' 如果有错误,提示错误信息 If Err.Number <> 0 Then MsgBox "代码执行出错: " & Err.Description, vbExclamation Err.Clear End If End Sub
关键优化说明
- 防止递归:在代码开头关闭
Application.EnableEvents,最后在Cleanup块恢复,避免修改工作表时反复触发事件。 - 统一错误处理:用一个
Cleanup标签确保不管有没有错误,事件都会恢复,同时捕获错误信息方便调试。 - 处理多单元格修改:第二段代码遍历每个修改的单元格,避免多单元格时的报错。
- 变量类型修正:把所有行号变量从
Integer改为Long,避免行数过多时溢出。 - 调整插入行逻辑:原来的插入行位置有误,应该在
LastRowMonitoringSheet + 1插入,而不是LastRowMonitoringSheet,这样不会覆盖最后一行的数据。 - 移除强制调用外部过程:原来错误处理里的
Call CopyHighlightedData_Click会强制触发其他逻辑,如果你确实需要调用,建议确认它不会再次触发Worksheet_Change,或者也在那个过程里关闭事件。
测试的时候,建议先备份你的工作簿,然后替换代码,再分别测试两段逻辑,应该就能正常运行了。
内容的提问来源于stack exchange,提问作者Chadi N
相关产品推荐
相关产品推荐

