【问题标题】:Value of counter is not updating in a For Loop计数器的值未在 For 循环中更新
【发布时间】:2020-08-13 06:40:50
【问题描述】:

我在 Excel 文件的 B 列中有数据。我做了一个循环,如果 B 单元格中的值大于特定 (len1) 值,则代码将单元格 (Value-Len1) 值放在行末尾的新单元格中。

每次添加行时,我都会将计数器递增为 lastrow = lastrow+1。现在问题来了。最初在输入文件中我有 122 组数据。但是当 For 循环完成时,lastrow 的值变为 160,但循环在 122 处退出。为什么?任何帮助将不胜感激。

For i = 1 To lastrow Step 1
    If Range("B" & i).Value > len1 Then
        Range("A" & lastrow + 1).Value = Range("A" & i).Value
        Range("B" & lastrow + 1).Value = Range("B" & i).Value - len1
        Range("B" & i).Value = len1
        lastrow = lastrow + 1
    End If
Next

【问题讨论】:

  • Lastrow 的值为 122,所以这就是循环在那里退出的原因
  • “To”值仅在 For 循环开始时计算一次,因此在该点之后更改 lastrow 不会影响循环结束的时间。
  • 但是这个值最初是,在循环结束时 lastrow 的值是 160....所以循环应该一直持续到 160。
  • 另外一种更快的方法是将范围值导出到数组,然后进行比较。将最终输出存储到临时数组中并将其写回工作表。
  • @Abhay 就像蒂姆说的那样,For i = 1 To lastrow Step 1 被评估一次,所以循环不关心你在该行之后的Lastrow 的值,当i = 122 就是这样时它会停止.

标签: excel vba for-loop


【解决方案1】:

要获得您想要的行为,您需要一个 while 循环(或 do 循环)

i = 1
While i <= lastrow
    If Range("B" & i).Value > len1 Then
        lastrow = lastrow + 1
        Range("A" & lastrow).Value = Range("A" & i).Value
        Range("B" & lastrow).Value = Range("B" & i).Value - len1
        Range("B" & i).Value = len1
    End If
    i = i + 1
Wend

我用下面的sub 对其进行了测试:

Sub LoopBeyondLastRow()
    Dim i  As Long, lastrow As Long, len1 As Long
    
    len1 = 10
    
    With ThisWorkbook.Sheets("Sheet1")
        lastrow = .Cells(Rows.Count, "B").End(xlUp).Row
        
        i = 1
        While i <= lastrow
            If .Range("B" & i).Value > len1 Then
                lastrow = lastrow + 1
                .Range("A" & lastrow).Value = .Range("A" & i).Value
                .Range("B" & lastrow).Value = .Range("B" & i).Value - len1
                .Range("B" & i).Value = len1
            End If
            i = i + 1
        Wend
    End With
End Sub

请注意以下几点:

  • 在循环内部,我先增加了lastrow,然后在下面的两个语句中使用它(以减少加法操作的次数)
  • 在我的测试代码中,我添加了With ThisWorkbook.Sheets("Sheet1") 以完全限定所有范围。不这样做是许多有时很难查明的错误的根源。一个人应该养成这样的习惯:永远不要写RangeCells 之前没有一点.

【讨论】:

    【解决方案2】:

    更快的方法是将范围值导出到数组,然后进行比较。将最终输出存储到临时数组中并将其写回工作表。

    如果您想遵循您的方法,那么这就是您正在尝试的吗?我已经对代码进行了注释,因此您理解它应该没有问题。基本上,如果要重新检查在行尾添加的数据,则需要 2 个循环。

    Option Explicit
    
    Sub Sample()
        Dim ws As Worksheet
        Dim ComparisionValue As Long
        Dim countOfMatchedValues As Long
        Dim lRow As Long
        Dim i As Long
        Dim outputRow As Long
        Dim rng As Range
        
        '~~> Change this to the relevant sheet
        Set ws = Sheet1
        
        '~~> Change this to the relevant
        '~~> comparision value
        ComparisionValue = 122
        
        With ws
            '~~> Start an indefinite loop
            Do
                '~~> Find last row
                lRow = .Range("A" & .Rows.Count).End(xlUp).Row
                '~~> Fix the output row for the new data
                outputRow = lRow + 1
                
                '~~> Check if there are any matches for your condition
                countOfMatchedValues = Application.WorksheetFunction.CountIf( _
                .Range("B1:B" & lRow), ">" & ComparisionValue)
                
                '~~> If not then exit loop
                If countOfMatchedValues = 0 Then Exit Do
                
                '~~> Do your stuff
                For i = 1 To lRow
                    If .Range("B" & i).Value > ComparisionValue Then
                        .Range("A" & outputRow).Value = .Range("A" & i).Value
                        .Range("B" & outputRow).Value = .Range("B" & i).Value - ComparisionValue
                        .Range("B" & i).Value = ComparisionValue
                        outputRow = outputRow + 1
                    End If
                Next i
            Loop
        End With
    End Sub
    

    行动中

    【讨论】:

    • 不完全确定,但我认为他想要的行为如下:在您的样本中,B14 应评估为 278(即 400 - 122)。还应在稍后阶段在循环中检查,因此应将值 156(即 278 - 122)添加到范围的末尾。稍后添加另一个值 34(即 156 - 122)。这是以 400 开头的链将结束的地方,因为 34 小于 122。
    • 400=>278=>156=34(第 18 行)类似 `300=>178=>56(第 17 行)等等
    • 我现在已经测试了您的代码,它的工作方式与描述的完全相同:) 我对您的 giff 图像感到困惑,因为 B14 的值为 122(最终这是正确的值)。对不起我的错误。
    • @SiddharthRout 谢谢!你明白了!只有这个数字 13 被不必要地重复了。其余所有其他 5 个值 122,122,122,56,34 都是正确的。我会检查我的程序并回来!
    【解决方案3】:

    for 循环使用预定义的迭代次数。对于未知数量的迭代,您需要使用while 循环。

    您的代码使用的值是lastRow在解释时,并且永远不会再次更新。

    这类似于:

    lastRow = 1
    Debug.Print lastRow
    lastRow = lastRow + 1
    Debug.Print lastRow
    

    你会看到:

    1 2

    并且不是

    2 2

    因为一旦执行了第一条Debug 语句,更改lastRow 的值就不会再影响这个特定的输出。

    【讨论】:

      【解决方案4】:

      请测试下一段代码:

      Sub TestLoopAddedRowsInclusive()
        '..... your code defining LastRow and len1
        Dim lastRInit As Long
        lastRInit = LastRow
        For i = 1 To Rows.count
          If Range("B" & i).Value = "" And i >= lastRInit Then Exit For
          If Range("B" & i).Value > len1 Then
              Range("A" & LastRow + 1).Value = Range("A" & i).Value
              Range("B" & LastRow + 1).Value = Range("B" & i).Value - len1
              Range("B" & i).Value = len1
              LastRow = LastRow + 1
          End If
        Next
      End Sub
      

      【讨论】:

      • 整洁! If i &gt; LastRow Then Exit For 怎么样
      • @Super Symmetry:它也可以工作,即使LastRow 不断增加...我最初想到一个空单元格退出循环,然后想办法避免空单元格他的初始范围......而且,在这种情况下,它将再次迭代...... :)
      猜你喜欢
      • 2021-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-29
      相关资源
      最近更新 更多