【问题标题】:Simple loop iterating over row of ActiveCell in VBA简单循环遍历 VBA 中的 ActiveCell 行
【发布时间】:2015-07-09 03:13:36
【问题描述】:

我正在用 VBA 编写一个非常基本的宏,这是我第一次在其中编写任何东西,所以我很挣扎。我完全知道我需要做什么的逻辑,我只是​​还没有得到 VBA 的语法。如果该行中的第一个单元格包含特定的子字符串,我想遍历该行中的每个单元格。 在 for 循环中,如果该单元格不为空,我想将该子字符串附加到行中每个单元格的末尾。我没有通过我的 for 循环声明

Sub changeRow()
Dim txt As String
txt = Cells(ActiveCell.Row, 1)
   If InStr(1, txt, "123") > 0 Then
    For Each b In Range(Rows(ActiveCell.Row).Select)
        If Len(b.Value) > 0 Then
            b.Value = b.Value & " 123"
        End If
    Next b
End If    
End Sub

【问题讨论】:

  • 声明中的b 是什么,应该是Range
  • 是的,对于糟糕的变量命名感到抱歉。我假设 b 应该是每次迭代时选择的单元格。
  • 如果您在列中有标题,那么您也可以使用.AutoFilter 过滤搜索字符串上的单元格,然后遍历过滤后的范围。那会快得多!想象一下。您的 Excel 列有 50k 条记录。假设只有两个单元格有123。在当前场景中,您的循环将运行 50k 次以检查单元格是否具有123。如果您使用自动过滤器,那么您的循环将只运行 2 次!!!

标签: vba excel


【解决方案1】:

一种方式

Sub changeRow()
  Const sTxt        As String = "123"
  Dim cell          As Range

  With Cells(ActiveCell.Row, "A")
    If VarType(.Value) = vbString Then
      If InStr(.Value, sTxt) Then
        For Each cell In .EntireRow.SpecialCells(xlCellTypeConstants, xlTextValues)
          cell.Value = cell.Value & " " & sTxt
        Next cell
      End If
    End If
  End With
End Sub

这也会将“123”添加到找到它的单元格中,但不会添加到包含数字或公式的单元格中。

编辑:上面的代码中有一个严重的错误。它应该测试 col A 中的单元格不包含公式:

Sub changeRow()
  Const sTxt        As String = "123"
  Dim cell          As Range

  With Cells(ActiveCell.Row, "A")
    If VarType(.Value) = vbString And Not .HasFormula Then
      If InStr(.Value, sTxt) Then
        For Each cell In .EntireRow.SpecialCells(xlCellTypeConstants, xlTextValues)
          cell.Value = cell.Value & " " & sTxt
        Next cell
      End If
    End If
  End With
End Sub

否则 SpecialCells 行可能会产生运行时错误。

【讨论】:

  • 我喜欢使用SpecialCells。当然,测试它不是 Nothing 总是好的。
  • @Doug:如果测试的第一个单元格确实是文字字符串,则无需测试运行时错误。这就是编辑的重点。 @Xonal:不客气。
【解决方案2】:

这在不引入任何新变量的情况下满足您的要求(尽管我确实将无意义的“b”更改为 cell:

Sub changeRow()
Dim txt As String
Dim cell As Excel.Range

txt = ActiveCell.EntireRow.Cells(1)
If InStr(1, txt, "123") > 0 Then
    For Each cell In Intersect(ActiveCell.EntireRow, ActiveCell.Parent.UsedRange)
        If Len(cell.Value) > 0 Then
            cell.Value = cell.Value & " 123"
        End If
    Next cell
End If
End Sub

它也不会留下任何不合格的变量范围,这是个好主意。通常你会通过引入像ws 这样的变量来引用你正在处理的工作表来避免这种情况。但是这段代码很简单,并且基于Activecell,所以我只使用了Activecell.Parent

【讨论】:

    【解决方案3】:

    我看到您已经找到了解决方案。我只是坚持“您是 VBA 新手”这一事实。如果您有疑问,请随时发表评论。保留大部分原始逻辑,

    '-- this line is very important, it keeps "in order" to write code
    '-- Forces explicit declaration of all variables in a file, or allows implicit declarations of variables.
    '-- please explore on that
    Option Explicit
    
    '-- writing this with more comments since you said you are new to VBA
    Sub changeRow()
    Dim ws As Worksheet
    Dim b As Range
    Dim activeRange As Range
    Dim fullRange As Range
    Dim lastColumn As Long
    Dim txt As String
    
        '-- set current sheet into a reference object variable called WS
        Set ws = ActiveWorkbook.Sheets("Sheet1")
        '-- similarly the range you plan to start the validation
        Set activeRange = ws.Range("B2")
        txt = activeRange.Value2
    
        '-- get last column in the row, 2 refers to rows 2 where you have data
        lastColumn = ws.Cells(2, ws.Columns.Count).End(xlToLeft).Column
        '-- get range until the last column in the row
        Set fullRange = Sheets("Sheet1").Range("B2").Resize(, lastColumn)
    
        '-- this allows you to view the Address of this range in the Immediate Window, just to make sure you get the desired range right
        Debug.Print fullRange.Address
    
        If InStr(1, txt, "123") > 0 Then
            '-- iterating through each range in full range that we specified above
            For Each b In fullRange
                '-- there's no need to check this because when InStr() fails,
                '-- the compiler will not come to this validation!
                If Len(b.Value) > 0 Then
                    '-- b.Offset(3) refers to 3 rows down from cell B2 which is B5
                    '-- output into 5th row for demonstration purpose
                    '-- you may set it back to b.Value per your requirement.
                    '-- Please explore offset property of Range object
                    b.Offset(3).Value = b.Value & " 123"
                End If
            Next b
       End If
    
       '-- release the memory allocated to these reference object variables
       '-- the order is: first ranges, then worksheet
       Set activeRange = Nothing
       Set fullRange = Nothing
       Set ws = Nothing
    
    End Sub
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-28
      • 2014-04-13
      • 2016-07-16
      • 2022-01-22
      相关资源
      最近更新 更多