Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
循环迭代问题的VBA_Vba_Excel_For Loop - Fatal编程技术网

循环迭代问题的VBA

循环迭代问题的VBA,vba,excel,for-loop,Vba,Excel,For Loop,在下面的代码中,我尝试检查2个日期值。如果存在,请计算BG列中的间隔天数。如果它们不存在或结果小于0,则删除该行 我遇到的问题是,一旦它删除了一行,它就会使用Next I,并直接跳过该行后面的内容。例:第1行和第2行缺少日期。第1行被删除。第2行被推到第1行。接下来是我,我们现在在第2行(第3行),跳过第2行的结果。使用i=i-1似乎会使我的程序崩溃。还有,有没有进一步的方法来提高我的代码的效率,使它能够更快地遍历大量的项目 Sub Func4() Dim N As Long, i As Lo

在下面的代码中,我尝试检查2个日期值。如果存在,请计算BG列中的间隔天数。如果它们不存在或结果小于0,则删除该行

我遇到的问题是,一旦它删除了一行,它就会使用Next I,并直接跳过该行后面的内容。例:第1行和第2行缺少日期。第1行被删除。第2行被推到第1行。接下来是我,我们现在在第2行(第3行),跳过第2行的结果。使用i=i-1似乎会使我的程序崩溃。还有,有没有进一步的方法来提高我的代码的效率,使它能够更快地遍历大量的项目

Sub Func4()

Dim N As Long, i As Long, j As Long, cnt As Long, date1 As Date, date2 As Date, date3 As Long ', iold As Long

N = Cells(Rows.Count, "A").End(xlUp).Row

j = 2
cnt = 0
For i = 2 To N 'main
    j = j + 1
    'iold = i
    If Not IsEmpty(Cells(i, "AB").Value) And Not IsEmpty(Cells(i, "AE").Value) Then
        date1 = Cells(i, "AB").Value 'AB=Entry Date
        date2 = Cells(i, "AE").Value 'AE=Rec'd
        date3 = Work_Days(date2, date1)
        cnt = cnt + 1

        If date3 >= 0 Then
            Cells(i, "BG").Value = date3

        Else
            Rows(i).EntireRow.Delete
            'i = i - 1 'HERE
        End If
    Else
        Rows(i).EntireRow.Delete
        'i = i - 1 'HERE
    End If

    'End If
    'If i = iold Then
Next i

'Else
'Next
'End If

End Sub
答复:

Sub Func4()
   Dim N As Long, i As Long, j As Long, cnt As Long, date1 As Date, date2 As Date, date3 As Long
    N = Cells(Rows.Count, "A").End(xlUp).Row
    j = 2
    For i = N To 2 Step -1
            j = j + 1

        If Not IsEmpty(Cells(i, "AB").Value) And Not IsEmpty(Cells(i, "AE").Value) Then
            date1 = Cells(i, "AB").Value 'AB=Entry Date
            date2 = Cells(i, "AE").Value 'AE=Rec'd
            date3 = Work_Days(date2, date1)
            cnt = cnt + 1
                If date3 >= 0 Then
                    Cells(i, "BG").Value = date3

                Else
                    Rows(i).EntireRow.Delete
                 End If
        Else
        Rows(i).EntireRow.Delete
        End If
        Next i

End Sub

将i=2的
改为N
改为
直到i>N
为止,并将
下一个i
改为
循环
(不要忘记事先指定
i=2
),然后对删除行下方的行进行注释

共产国际和Shai Rado在注释中回答了第一个问题:

始终反向循环项目,因为从范围中删除项目会将其余项目移回。通过反向循环,已删除的项目不会影响剩余的项目

第二个问题,为了加快速度,请阅读以下博文:

特别是以下部分: 在一次操作中读取/写入大块单元


如果您以数组的形式处理数据,并将数据读写到数组中(如本博客中的示例所示),那么速度会快得多。特别是对于成千上万的物品,这将是非常重要的

要解决第一个问题,可以反向运行循环。这样,删除只会移动已经迭代过的行

For i = N To 2 Step -1
第二个问题有点不确定。本指南对如何加快代码速度提出了一些建议:

本指南中与您的代码相关的几个项目对我来说最为突出

  • “禁用工作表屏幕更新”
在您的代码周围放置以下内容,特别是当您预期将删除很多行时

    Application.ScreenUpdating = False
    Application.ScreenUpdating = True
  • “避免过度访问工作表”
这最好是通过将列“AB”和“AE”读入一个数组,并在其中迭代,而不是在工作表上的单元格来实现。以下是实现这一目标的解决方案:


如果要删除行,则需要向后循环。如Comintern对i=N到2步骤1所说的
,谢谢你的提示!我从来没有这样想过。我似乎已经让它工作完美!请提交您的简单回答作为答案,我将奖励您分数!关键是,删除循环中的行会移动项目,导致您“错过”某些迭代。从循环项目列表中删除项目时,始终反向循环。我同意,在几乎所有情况下,您都应该反向循环,但并不总是-存在某些例外情况确保始终存在例外情况,但最佳做法是-在VBA中,从您迭代的集合中删除项目时,读取到始终-反向循环。请相信我,这是人们开始开发Office对象模型时犯的最大错误之一。所以,要小心教导刚起步的Office开发人员不要这样做
Dim Ar as Variant

Ar = Sheets("Sheet").Range("A1:A10000").Value