鱼C论坛

 找回密码
 立即注册
查看: 63|回复: 1

VBA卡死

[复制链接]
发表于 2024-12-30 12:55:32 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在worksheet1里写了一个程序,在删除行的时候会卡死

Option Explicit

Dim IsDeleting As Boolean ' 全局变量,用于跟踪是否正在删除行


Private Sub Worksheet_Change(ByVal Target As Range)
    On Error GoTo ErrorHandler
    Application.EnableEvents = False '禁用事件,放置递归
    If IsDeleting Then
        GoTo ExitHandler
    End If

   
    Application.ScreenUpdating = False
   
   
    Dim KeyCell As Range
    Dim changedRow As Long
    Dim text As String
    Dim LastRowDest As Long
    Dim SearchRange As String
    ' Dim KeyCells As Range  ' 移除未使用的变量声明
   
    Dim FoundCell As Range
    Dim foundmatch As Boolean
    Dim i As Long
    Application.ScreenUpdating = False
   
   
  
    ' 设置工作表
    Dim wsSource As Worksheet
    Set wsSource = ThisWorkbook.Sheets("Sheet1")
   
    Dim wsDest As Worksheet
    Set wsDest = ThisWorkbook.Sheets("Sheet2")
   
    ' 如果是删除行操作,则跳过
    If IsDeletingRows(Target) Then
        GoTo ExitHandler
    End If

    ' 监控范围:B, C, D, E 列
    If Not Intersect(Target, wsSource.Range("B:E")) Is Nothing Then
        For Each KeyCell In Target  ' 遍历Target中的每个单元格
            changedRow = KeyCell.row  ' 修正:使用KeyCell.Row
            
            
           

                ' 如果行数大于3
                If changedRow > 3 Then
                    ' 清空该行的H, I, J, K单元格的数据
                    wsSource.Range("H" & changedRow & ":K" & changedRow).ClearContents
                    ' 取消背景颜色设置
                    wsSource.Range("H" & changedRow & ":K" & changedRow).Interior.Color = xlNone
   
                    ' 合并B, C, D, E列内容为一个字符串
                    Dim arrValues As Variant
                    arrValues = wsSource.Range("B" & changedRow & ":E" & changedRow).Value
                    text = Join(Application.Transpose(Application.Transpose(arrValues)), ",")
                    ' 第一个判断:无缝钢管且不含锌
                    If CheckBasicCondition_wfgg(text) Then
                        wsSource.Cells(changedRow, "H").Value = "无缝钢管"
                        ' 后续条件分析并赋值I, J列
                        AssignStandards_I_wfgg text, changedRow '改标准I列
                        AssignMaterials_K_wfgg text, changedRow '改材质K列
                        AssignDimensions_J_wfgg text, changedRow '改规格J列
                    End If
   
                    ' 第二个判断:无缝钢管且含锌
                    If CheckBasicCondition_dxwfgg(text) Then
                        wsSource.Cells(changedRow, "H").Value = "无缝钢管(镀锌)"
                    End If
                End If
            
        Next KeyCell
    End If
    ' 确定变动的单元格是否在H到K列
   
   
' 监控范围:H, I, J, K 列
    If Not Intersect(Target, wsSource.Range("J:J")) Is Nothing Then
        For Each KeyCell In Intersect(Target, wsSource.Range("J:J"))
            changedRow = KeyCell.row
            
            
            
                ' 如果行数大于3
                If changedRow > 3 Then
                    ' 清空该行的L单元格的数据
                    wsSource.Cells(changedRow, "L").ClearContents
                    
                    ' 确定查找范围
                    LastRowDest = wsDest.Cells(wsDest.Rows.Count, "B").End(xlUp).row
                    SearchRange = "B1:E" & LastRowDest
                    
                    ' 初始化匹配标志
                    foundmatch = False
                    
                    ' 在Sheet2的B到E列查找匹配的行
                    For i = 1 To LastRowDest
                        ' 比较Sheet1的H列与Sheet2的B列,I列与C列,J列与D列,K列与E列
                        If wsSource.Cells(changedRow, "H").Value = wsDest.Cells(i, "B").Value And _
                           wsSource.Cells(changedRow, "I").Value = wsDest.Cells(i, "C").Value And _
                           wsSource.Cells(changedRow, "J").Value = wsDest.Cells(i, "D").Value And _
                           wsSource.Cells(changedRow, "K").Value = wsDest.Cells(i, "E").Value Then
                            ' 如果找到匹配的行,复制Sheet2的F列值到Sheet1的L列
                            wsSource.Cells(changedRow, "L").Value = wsDest.Cells(i, "F").Value
                            foundmatch = True
                            Exit For ' 找到匹配后退出循环
                        End If
                    Next i
                    
                    ' 如果没有找到匹配的行,L列保持清空状态
                End If
            
        Next KeyCell
    End If
   
ExitHandler:
    Application.EnableEvents = True
    Application.ScreenUpdating = True
    Exit Sub

ErrorHandler:
    Resume ExitHandler
End Sub

' 辅助函数,用于检测是否正在进行删除行操作
Function IsDeletingRows(Target As Range) As Boolean
    IsDeletingRows = False
    On Error Resume Next
    Dim r As Range
    For Each r In Target.Rows
        If r.EntireRow.Hidden Then
            IsDeletingRows = True
            Exit Function
        End If
    Next r
    On Error GoTo 0
End Function

Sub DeleteRows(RowsToDelete As Variant)
    IsDeleting = True
    On Error Resume Next
    Dim r As Range
    For Each r In RowsToDelete
        Rows(r).Delete
    Next r
    On Error GoTo 0
    IsDeleting = False
End Sub



'无缝钢管,不含镀锌的判断
Function CheckBasicCondition_wfgg(ByVal text As String) As Boolean
  If InStr(text, "无缝") > 0 And InStr(text, "钢管") > 0 And (InStr(text, "锌") = 0 And InStr(text, "zinc") = 0 And InStr(text, "galv") = 0) Then
  CheckBasicCondition_wfgg = True
  Else
  CheckBasicCondition_wfgg = False
  End If
End Function

'镀锌无缝钢管的判断
Function CheckBasicCondition_dxwfgg(ByVal text As String) As Boolean
  If InStr(text, "无缝") > 0 And InStr(text, "钢管") > 0 And (InStr(text, "锌") > 0 Or InStr(text, "zinc") > 0 Or InStr(text, "galv") > 0) Then
  CheckBasicCondition_dxwfgg = True
  Else
  CheckBasicCondition_dxwfgg = False
  End If
End Function

Sub AssignStandards_I_wfgg(ByVal text As String, ByVal row As Long)
    Application.ScreenUpdating = False
    ' 根据文本内容,为I列 标准 赋值
    Dim wsSource As Worksheet
    Set wsSource = ThisWorkbook.Sheets("Sheet1")
   
    If InStr(text, "3405") > 0 Then
        wsSource.Cells(row, "I").Value = "SH/T3405"
        wsSource.Cells(row, "C").Interior.Color = xlNone
    ElseIf InStr(text, "36.10") > 0 Then
        wsSource.Cells(row, "I").Value = "ASME B36.10"
        wsSource.Cells(row, "C").Interior.Color = xlNone
    ElseIf InStr(text, "36.19") > 0 Then
        wsSource.Cells(row, "I").Value = "ASME B36.19"
        wsSource.Cells(row, "C").Interior.Color = xlNone
    ElseIf InStr(text, "20553") > 0 Then
        Select Case True
            Case InStr(text, "a") > 0
                wsSource.Cells(row, "I").Value = "HG/T20553(Ⅰa)"
                wsSource.Cells(row, "C").Interior.Color = xlNone
            Case InStr(text, "b") > 0
                wsSource.Cells(row, "I").Value = "HG/T20553(Ⅰb)"
                wsSource.Cells(row, "C").Interior.Color = xlNone
            Case InStr(text, "Ⅱ") > 0
                wsSource.Cells(row, "I").Value = "HG/T20553(Ⅱ)"
                wsSource.Cells(row, "C").Interior.Color = xlNone
            Case Else
                With wsSource.Cells(row, "C")
                     
                ' 设置背景颜色为黄色
                     .Interior.Color = RGB(255, 255, 0)
                    .Validation.Delete
                    .Validation.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
                    xlBetween, Formula1:="HG/T20553(Ⅰa),HG/T20553(Ⅱ),HG/T20553(Ⅰb)"
                End With
        End Select
        
    ElseIf InStr(text, "17395") > 0 Then
        Select Case True
            Case InStr(text, "Ⅰ") > 0
                wsSource.Cells(row, "I").Value = "GB/T17395(Ⅰ)"
                wsSource.Cells(row, "C").Interior.Color = xlNone
            Case InStr(text, "Ⅱ") > 0
                wsSource.Cells(row, "I").Value = "GB/T17395(Ⅱ)"
                wsSource.Cells(row, "C").Interior.Color = xlNone
            Case InStr(text, "Ⅲ") > 0
                wsSource.Cells(row, "I").Value = "GB/T17395(Ⅲ)"
                wsSource.Cells(row, "C").Interior.Color = xlNone
            Case Else
                With wsSource.Cells(row, "C")
                  
                ' 设置背景颜色为黄色
                     .Interior.Color = RGB(255, 255, 0)
                    .Validation.Delete
                    .Validation.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
                    xlBetween, Formula1:="GB/T17395(Ⅰ),GB/T17395(Ⅱ),GB/T17395(Ⅲ)"
                End With
            
        End Select
        
    Else
        ' 如果以上都没找到,设置下拉列表
        With wsSource.Cells(row, "C")
            
            ' 设置背景颜色为黄色
            .Interior.Color = RGB(255, 255, 0)
            .Validation.Delete
            .Validation.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
             xlBetween, Formula1:="SH/T3405,HG/T20553(Ⅰa),HG/T20553(Ⅱ),ASME B36.10,ASME B36.19,HG/T20553(Ⅰb)"
        End With
    End If
   
    Application.ScreenUpdating = True
End Sub

Sub AssignMaterials_K_wfgg(ByVal text As String, ByVal row As Long)
  ' 根据文本内容,为K列 材质 赋值
  Application.ScreenUpdating = False
  
  Dim wsSource As Worksheet
  Set wsSource = ThisWorkbook.Sheets("Sheet1")
  
  Select Case True
  Case InStr(text, "20") > 0 And InStr(text, "8163") > 0
    wsSource.Cells(row, "K").Value = "20-GB/T8163"
    wsSource.Cells(row, "E").Interior.Color = xlNone
  Case InStr(text, "20") > 0 And InStr(text, "9948") > 0
    wsSource.Cells(row, "K").Value = "20-GB/T9948"
    wsSource.Cells(row, "E").Interior.Color = xlNone
  Case InStr(text, "20") > 0 And InStr(text, "3087") > 0
    wsSource.Cells(row, "K").Value = "20-GB/T3087"
    wsSource.Cells(row, "E").Interior.Color = xlNone
  Case InStr(text, "20") > 0 And InStr(text, "5310") > 0
    wsSource.Cells(row, "K").Value = "20G-GB/T5310"
    wsSource.Cells(row, "E").Interior.Color = xlNone
  Case (InStr(text, "15Cr") > 0 Or InStr(text, "15cr") > 0) And InStr(text, "9948") > 0
    wsSource.Cells(row, "K").Value = "15CrMoG-GB/T9948"
    wsSource.Cells(row, "E").Interior.Color = xlNone
  Case InStr(text, "12Cr") > 0 Or InStr(text, "12cr") > 0
    wsSource.Cells(row, "K").Value = "12Cr1MoVG-GB/T5310"
    wsSource.Cells(row, "E").Interior.Color = xlNone
  Case (InStr(text, "15Cr") > 0 Or InStr(text, "15cr") > 0)
    wsSource.Cells(row, "K").Value = "15CrMo-GB/T5310"
    wsSource.Cells(row, "E").Interior.Color = xlNone
  Case InStr(text, "30403") > 0
    wsSource.Cells(row, "K").Value = "S30403-GB/T14976"
    wsSource.Cells(row, "E").Interior.Color = xlNone
  Case InStr(text, "316") > 0
    wsSource.Cells(row, "K").Value = "S31603-GB/T14976"
    wsSource.Cells(row, "E").Interior.Color = xlNone
  Case InStr(text, "310") > 0
    wsSource.Cells(row, "K").Value = "S31008-GB/T14976"
    wsSource.Cells(row, "E").Interior.Color = xlNone
  Case InStr(text, "2205") > 0
    wsSource.Cells(row, "K").Value = "S22053-GB/T14976"
    wsSource.Cells(row, "E").Interior.Color = xlNone
  Case InStr(text, "304") > 0 And InStr(text, "13296") > 0
    wsSource.Cells(row, "K").Value = "S30408-GB/T13296"
    wsSource.Cells(row, "E").Interior.Color = xlNone
  Case InStr(text, "304") > 0 And InStr(text, "312") > 0
    wsSource.Cells(row, "K").Value = "TP304-A312"
    wsSource.Cells(row, "E").Interior.Color = xlNone
  Case InStr(text, "304") > 0 And InStr(text, "30403") = 0
    wsSource.Cells(row, "K").Value = "S30408-GB/T14976"
    wsSource.Cells(row, "E").Interior.Color = xlNone
   Case Else
        With wsSource.Cells(row, "E")
            
        ' 设置背景颜色为黄色
             .Interior.Color = RGB(255, 255, 0)
            .Validation.Delete
            .Validation.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
            xlBetween, Formula1:="20-GB/T8163,20-GB/T3087,20G-GB/T5310,S30408-GB/T14976,S31603-GB/T14976,15CrMoG-GB/T5310,12Cr1MoVG-GB/T5310,S31008-GB/T14976,15CrMoG-GB/T9948,20-GB/T9948,S30403-GB/T14976,S22053-GB/T14976"
        End With
  End Select
  
  Application.ScreenUpdating = True
End Sub


Sub AssignDimensions_J_wfgg(ByVal text As String, ByVal row As Long)
    ' 根据文本内容,为J列 规格 赋值
    Dim wsSource As Worksheet
    Set wsSource = ThisWorkbook.Sheets("Sheet1")
   
    Dim regex As Object
    Dim matches As Object
    Dim matchPattern As String
   
    Application.ScreenUpdating = False
   

    matchPattern = "(\d+(\.\d+)?)\s*[xX×*]\s*(\d+(\.\d+)?)"

    ' 创建正则表达式对象
    Set regex = CreateObject("VBScript.RegExp")
    With regex
        .pattern = matchPattern
        .Global = False
        '.IgnoreCase = True
    End With

    ' 执行正则表达式匹配
    If regex.Test(text) Then
        Set matches = regex.Execute(text)
        ' 如果有匹配项,生成指定格式的字符串
        If matches.Count > 0 And (InStr(text, "3087") Or InStr(text, "5310")) And InStr(text, "20") Then
            wsSource.Cells(row, "J").Value = "Φ" & matches(0).SubMatches(0) & "x" & matches(0).SubMatches(2) & ",正火,NB/T47019"
         ElseIf matches.Count > 0 And (InStr(text, "Cr") Or InStr(text, "cr")) Then
            wsSource.Cells(row, "J").Value = "Φ" & matches(0).SubMatches(0) & "x" & matches(0).SubMatches(2) & ",正火+回火,NB/T47019"
         ElseIf matches.Count > 0 Then
            wsSource.Cells(row, "J").Value = "Φ" & matches(0).SubMatches(0) & "x" & matches(0).SubMatches(2)
        End If
        wsSource.Cells(row, "D").Interior.Color = xlNone
    Else
        With wsSource.Cells(row, "D")
            
        ' 设置背景颜色为黄色
             .Interior.Color = RGB(255, 255, 0)
        End With
        
    End If
   
    Application.ScreenUpdating = True
End Sub
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-12-30 13:19:41 | 显示全部楼层
VBA程序在删除行时卡死的原因可能有以下几点:

1. **事件递归**:在`Worksheet_Change`事件中,删除行可能会触发另一个`Worksheet_Change`事件,导致递归调用。虽然你已经使用`Application.EnableEvents = False`来防止递归,但在某些情况下,事件可能仍然会被触发。

2. **全局变量**:`IsDeleting`变量用于标识是否正在删除行,但在`DeleteRows`子程序中,可能没有正确地设置或重置这个变量,导致逻辑错误。

3. **隐藏行检测**:`IsDeletingRows`函数通过检测行是否隐藏来判断是否正在删除行,这种方法可能不够可靠。

以下是一些建议来解决这个问题:

- 确保在所有可能的退出路径中都正确地重置`Application.EnableEvents`和`IsDeleting`变量。
- 检查`IsDeletingRows`函数的逻辑,确保它能够准确地检测到删除行的操作。
- 在`DeleteRows`子程序中,确保在删除行之前和之后正确地设置和重置`IsDeleting`变量。

如果问题仍然存在,建议逐步调试代码,查看具体在哪一步出现了卡死的情况。


以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-30 16:26

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表