VBA-运行excel宏需要很长时间

VBA-运行excel宏需要很长时间,excel,vba,Excel,Vba,我正在运行这个宏,它可能会花费很长时间,或者我编写它的方式有问题。我不熟悉Excel宏,我似乎不知道如何更好地编写它,以免使我的电脑崩溃 子测试() 屏幕更新=真 将maxRows设置为整数 maxRows=2332 对于i=maxRows到2步骤-1 '如果单元格为空,请删除该行 '否则,删除行的第一个单元格并切换到 如果单元格(i,2).Value=”“则 第(i)行。删除 其他的 单元格(i,1)。删除 如果结束 接下来我 屏幕更新=错误 端接头 一般来说,无论何时使用delete,最好在

我正在运行这个宏,它可能会花费很长时间,或者我编写它的方式有问题。我不熟悉
Excel宏
,我似乎不知道如何更好地编写它,以免使我的电脑崩溃

子测试()
屏幕更新=真
将maxRows设置为整数
maxRows=2332
对于i=maxRows到2步骤-1
'如果单元格为空,请删除该行
'否则,删除行的第一个单元格并切换到
如果单元格(i,2).Value=”“则
第(i)行。删除
其他的
单元格(i,1)。删除
如果结束
接下来我
屏幕更新=错误
端接头

一般来说,无论何时使用
delete
,最好在所有情况下只执行一次。然而,在OP的情况下,有两种情况是分开的——删除整行和只删除一个单元格。因此,
delete
方法可以使用两次:

Sub TestMe()

    Dim maxRows As Long: maxRows = 2332
    Dim myRangeRows As Range
    Dim myRangeCells As Range

    Dim i As Long
    For i = maxRows To 2 Step -1
        With Worksheets(1)
            If .Cells(i, 2) = "" Then
                If myRangeRows Is Nothing Then
                    Set myRangeRows = .Rows(i)
                Else
                    Set myRangeRows = Union(.Rows(i), myRangeRows)
                End If
            Else
                If myRangeCells Is Nothing Then
                    Set myRangeCells = .Cells(i, 1)
                Else
                    Set myRangeCells = Union(.Cells(i, 1), myRangeCells)
                End If
            End If
        End With
    Next i

    If Not myRangeRows Is Nothing Then myRangeRows.Delete
    If Not myRangeCells Is Nothing Then myRangeCells.Delete

End Sub
此外,每当Excel中的单元格被这样引用时,
单元格(i,2).Value
,则引用的是
ActiveSheet
或代码所在的工作表。因此,明确提及工作表是一种很好的做法,如本例所示:

With Worksheets(1)
    If .Cells(i, 2) = "" Then

通常,无论何时使用
delete
,最好只执行一次,对于所有情况。然而,在OP的情况下,有两种情况是分开的——删除整行和只删除一个单元格。因此,
delete
方法可以使用两次:

Sub TestMe()

    Dim maxRows As Long: maxRows = 2332
    Dim myRangeRows As Range
    Dim myRangeCells As Range

    Dim i As Long
    For i = maxRows To 2 Step -1
        With Worksheets(1)
            If .Cells(i, 2) = "" Then
                If myRangeRows Is Nothing Then
                    Set myRangeRows = .Rows(i)
                Else
                    Set myRangeRows = Union(.Rows(i), myRangeRows)
                End If
            Else
                If myRangeCells Is Nothing Then
                    Set myRangeCells = .Cells(i, 1)
                Else
                    Set myRangeCells = Union(.Cells(i, 1), myRangeCells)
                End If
            End If
        End With
    Next i

    If Not myRangeRows Is Nothing Then myRangeRows.Delete
    If Not myRangeCells Is Nothing Then myRangeCells.Delete

End Sub
此外,每当Excel中的单元格被这样引用时,
单元格(i,2).Value
,则引用的是
ActiveSheet
或代码所在的工作表。因此,明确提及工作表是一种很好的做法,如本例所示:

With Worksheets(1)
    If .Cells(i, 2) = "" Then

我不认为屏幕更新背后的逻辑先是正确的,然后是错误的。你确定不想把它颠倒过来吗?除此之外,我没有看到任何问题,您可能还想检查IsEmpty(单元格(I,2)),但我不认为这会导致您的问题。您还应该尝试使用工作表对象,而不是使用通用单元格和行对象。尝试使用Long作为变量而不是整数,但这与此问题无关。那么您的意思是使用
ActiveSheet.Cells(i,2)
?是的,您可以这样做,但最好避免使用ActiveSheet,因为将来您可以从工作表外部使用宏,这是一种良好的做法,调暗新工作表对象并使用该对象进行操作。将我的工作表设置为工作表。设置mySheet=ThisWorkbook.Sheets(“sheetnameastring”)。然后使用该工作表的行和单元格对象,例如:mySheet.Cells(i,2)或mySheet.Rows(i).Delete。谢谢您的建议。我设法将运行时间从
10+秒和可能的崩溃时间
减少到
3-4秒。我有web应用背景,我们说任何花费
1秒或更长时间的事情都太慢了。但是在这里,我想我可以忍受
3秒
。你也检查过应用程序了吗。屏幕更新?我相信你想先把它设置为False,然后在完成后再设置为True。如果你还没有这样做的话,它可能会进一步加快速度。我不认为屏幕更新背后的逻辑是先对后错。你确定不想把它颠倒过来吗?除此之外,我没有看到任何问题,您可能还想检查IsEmpty(单元格(I,2)),但我不认为这会导致您的问题。您还应该尝试使用工作表对象,而不是使用通用单元格和行对象。尝试使用Long作为变量而不是整数,但这与此问题无关。那么您的意思是使用
ActiveSheet.Cells(i,2)
?是的,您可以这样做,但最好避免使用ActiveSheet,因为将来您可以从工作表外部使用宏,这是一种良好的做法,调暗新工作表对象并使用该对象进行操作。将我的工作表设置为工作表。设置mySheet=ThisWorkbook.Sheets(“sheetnameastring”)。然后使用该工作表的行和单元格对象,例如:mySheet.Cells(i,2)或mySheet.Rows(i).Delete。谢谢您的建议。我设法将运行时间从
10+秒和可能的崩溃时间
减少到
3-4秒。我有web应用背景,我们说任何花费
1秒或更长时间的事情都太慢了。但是在这里,我想我可以忍受
3秒
。你也检查过应用程序了吗。屏幕更新?我相信你想先把它设置为False,然后在完成后再设置为True。如果你还没有这样做,它可能会进一步加速。你认为是什么导致了他的错误?我相信它在引用单元格和行对象之前没有使用sheet对象。但是我还没有测试过。我的假设正确吗?@Lorne-不知道。这个假设可能是好的,但可能还有很多其他原因,例如,有一个
工作表\u Change
事件,它以某种方式对删除的代码“播放”,并以某种方式运行另一个过程,这需要很多时间。再次阅读您的编辑,我认为我的问题的答案是“否”。删除泛型行或单元格对象不会导致问题,只要他在活动工作表上,我的推理就大错特错了。谢谢你,我有点新,还在学习。你认为是什么导致了他的错误?我相信它在引用单元格和行对象之前没有使用sheet对象。但是我还没有测试过。我的假设正确吗?@Lorne-不知道。这个假设可能是好的,但可能还有很多其他原因,例如,有一个
工作表\u Change
事件,它以某种方式对删除的代码“播放”,并以某种方式运行另一个过程,这需要很多时间。再次阅读您的编辑,我认为我的问题的答案是“否”。删除泛型行或单元格对象不会导致问题,因为