【问题标题】:How do I loop through each intersection instead of intersection area?如何循环通过每个交叉口而不是交叉口区域?
【发布时间】:2021-12-17 10:54:53
【问题描述】:

目前我的代码将跟踪是否在列 C:E 和目标行之间的交叉区域中输入了某些内容。因此,如果我在 C2:E2 中输入数据,只要该范围内的所有单元格都有数据,工作表更改事件就会运行。

工作表更改事件将捕获日期、工作表名称和条目日志。那么问题是,如果一个多行的区域受到影响,即 C2:E6,它将根据受影响的行数在多行上捕获数据。如何调整代码,以便当多行受到影响时,即 C2:E6,它将捕获多个条目 - C2:E2 - C3:E3 - C4:E4 - C5:E5 - C6-E6。

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)
    
    Const fRow As Long = 2
    Const cCols As String = "C:E"
    
    Dim SheetName As String
    Dim lngth As Range
    Dim LogSearchRange As Range, R As Range
    Dim Findstr As Range
    
    
    Dim crg As Range
    Set crg = Columns(cCols).Resize(Rows.Count - fRow + 1).Offset(fRow - 1)
    Dim irg As Range: Set irg = Intersect(crg, Target)
    
    SheetName = ActiveSheet.Name
    
    
    If irg Is Nothing Then Exit Sub
    
    Dim srg As Range: Set srg = Intersect(irg.EntireRow, crg)
    Debug.Print srg.Address(0, 0)
    Application.EnableEvents = False
    
    Dim arg As Range
    Dim rrg As Range
    Dim RowString As String
    Dim AreaString As String
    
    AreaString = srg.Address(False, False)
    RowString = SheetName & "!" & AreaString
    
    With Sheets("Log")
    Set LogSearchRange = Application.Intersect(.UsedRange, .Columns(3))
    Set Findstr = LogSearchRange.Find(What:=RowString, LookAt:=xlWhole)
    
    For Each arg In srg.Areas
        For Each rrg In arg.Rows
            If Application.CountBlank(rrg) = 0 And Findstr Is Nothing Then
              
            With Sheets("Log")
            .Cells(1, 1).End(xlDown).Offset(1).Value = Format(Date, "dd/mm/yyyy")
            .Cells(1, 2).End(xlDown).Offset(1).Value = ActiveSheet.Name
            .Cells(1, 2).End(xlDown).Offset(0, 1) = RowString
            End With
            Else
                If Application.CountBlank(srg) = 3 Then
                
                
                    With Worksheets("Log")
                    Set LogSearchRange = Application.Intersect(.UsedRange, .Columns(3))
                    Set R = LogSearchRange.Find(What:=RowString, LookAt:=xlWhole)
                    If Not R Is Nothing Then
                    R.EntireRow.Delete Shift:=xlUp
                    End If
                    End With
                
                End If
            End If
        Next rrg
    Next arg
    End With
    
SafeExit:
     
    If Not Application.EnableEvents Then
        Application.EnableEvents = True
      
    End If
    
    Exit Sub

End Sub

【问题讨论】:

  • 因此,如果Target 范围与“A:C”相交,但Target 范围超过“C:C”列是否要记录/“捕获”整个 Target 范围内容,而不仅仅是交叉点?
  • 不,重点是只捕获 C:E 的交集,而是将每一行单独捕获为新条目,而不是捕获整个多行区域。
  • 您是否只希望从列“A:C”开始并以“E:E”结束的范围?您的实际代码将事件限制为仅触发“A:C”列。基于什么代码来“决定”记录范围的每一行的时刻?

标签: excel vba intersection


【解决方案1】:

工作表更改修改

  • 如果C:E 列中的任何单元格发生更改,这将触发事件,第一行除外。它将遍历从列C 到列E 的所有单元格的行范围。如果行范围内的所有单元格都不为空,则仅当条目不存在时才会在日志工作表中创建一个日志条目。如果行范围内的所有单元格均为空白,则使用行“地址”,它将尝试查找日志条目并删除其整行。
Option Explicit

' Since you're not writing to the source worksheet (Me, ActiveSheet),
' you don't need to disable events.

Private Sub Worksheet_Change(ByVal Target As Range)
    
    Const fRow As Long = 2
    Const cCols As String = "C:E"
    
    Const dName As String = "Log"
    Const dCol As String = "A"
    Const dcCol As String = "C"
    
    Dim crg As Range
    Set crg = Columns(cCols).Resize(Rows.Count - fRow + 1).Offset(fRow - 1)
    Dim irg As Range: Set irg = Intersect(crg, Target)

    If irg Is Nothing Then Exit Sub
    
    Dim srg As Range: Set srg = Intersect(irg.EntireRow, crg)
    Dim sName As String: sName = Me.Name
     
    Dim dws As Worksheet: Set dws = Me.Parent.Worksheets(dName)
    Dim dfCell As Range: Dim ddcrg As Range: Set ddcrg = dws.Columns(dcCol)
    
    Dim arg As Range
    Dim rrg As Range
    Dim srAddress As String
    Dim ddFound As Range
    
    For Each arg In srg.Areas
        For Each rrg In arg.Rows
            srAddress = sName & "!" & rrg.Address(0, 0)
            Set ddFound = ddcrg.Find(srAddress, , xlFormulas, xlWhole)
            If Application.CountBlank(rrg) = 0 Then ' no blanks
                If ddFound Is Nothing Then ' not found in the log
                    Set dfCell = dws.Cells(dws.Rows.Count, dCol) _
                        .End(xlUp).Offset(1)
                    ' While developing the code, it is always better to use ...
                    'dfCell.Value = Format(Now, "dd/mm/yyyy hh:mm:ss")
                    ' ...since you don't want to wait for days for a change.
                    dfCell.Value = Format(Date, "dd/mm/yyyy")
                    dfCell.Offset(, 1).Value = Me.Name
                    dfCell.Offset(, 2).Value = srAddress
                End If
            ElseIf Application.CountBlank(srg) = 3 Then ' all blanks
                If Not ddFound Is Nothing Then ' found in the log
                    ddFound.EntireRow.Delete Shift:=xlShiftUp
                End If
            'Else ' Neither no blanks, nor all blanks
            End If
        Next rrg
    Next arg
    
End Sub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-15
    • 2023-03-12
    • 1970-01-01
    • 2017-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多