Excel运行宏后没有响应

时间:2013-02-24 17:53:20

标签: excel excel-vba excel-2007 vba

我使用下面的代码将列从一个工作表复制到另一个工作表,然后用空值替换空白单元格:

'Copying If Employee
sourceSheet.Activate
Range(Cells(2, 7), Cells(Rows.Count, 7).End(xlUp)).Select
Selection.Copy
destSheet.Activate
Range("E2", Cells(Rows.Count, 7)).PasteSpecial

For Each cell In Range("E2", Cells(Rows.Count, 5))
If Len(cell.Value) = 0 Then
    cell.Value = "No"
End If

当我用Range("E2", Cells(500,5))替换for语句时,它工作正常。

可能是什么问题?我无法弄明白。任何人都可以帮我这个吗?

3 个答案:

答案 0 :(得分:8)

Excel 2007有1,048,576行。

  1. 你的每个循环必须经过一百万个单元格,并且每次必须将一个单元格(包含其所有属性)加载到内存中。这种不断加载和卸载单元对象非常耗费资源。

  2. 每次将值No分配给单元格时,Excel都会重新计算工作表,刷新屏幕并可能触发工作表/工作簿/单元格事件。所有这一切都在评估下一个细胞到下一个细胞之前。除非您拥有大量数据,否则在此示例中将会发生几十万次。

  3. 500个单元格数量要少得多,可以毫无问题地处理。

    修改

    获取最后一行。

    如果您想获取包含数据的最后一个可见行,请使用:

    With Workbooks(myWorkbook).Worksheets(myWorksheet)
       LastRow = .Cells(.Rows.Count, "E").End(xlUp).Row
    End With
    

    如果您想获取包含数据的最后一行,无论它是可见还是隐藏,请使用:

    With Workbooks(myWorkbook).Worksheets(myWorksheet)
       LastRow =.Range("E2").EntireColumn.Find("*", .Cells(1, .Range("E2").Column), , , xlByRows, xlPrevious).Row
    End With
    

    了解更多信息Rondebruin有一个很好的网站,其中包含有关确定las行/列的详细信息。

答案 1 :(得分:2)

尝试

For Each cell In Range("E2", Cells(destSheet.UsedRange.Rows.Count, 5))
If Len(cell.Value) = 0 Then
    cell.Value = "No"
End If

或更优雅(可能更快),

Dim calcStatus As XlCalculation
calcStatus = Application.Calculation

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual

For Each cell In Range("E2:E" & destSheet.UsedRange.Rows.Count)
If Len(cell.Value) = 0 Then
    cell.Value = "No"
End If    

Application.Calculation = calcStatus
Application.ScreenUpdating = True

答案 2 :(得分:2)

正如Cabierberach正确指出的那样,你当前的例程循环超过1M行。除了他和JustinJDavies解决方案之外,请考虑这个黑客:

如果要在每次值为0时显示No的单元格,您只需更改格式,而不是将值No设置为0。通过将此自定义格式应用于单元格,可以在没有宏的情况下完成此操作:0,-0,"No",@。您可能需要使用默认格式替换0 - 有关自定义数字格式的详细说明,请参阅this link

如果你想在VBA中这样做,这一行就足够了:

Range("E2:E" & Cells(Rows.Count, 1).End(xlUp).Row).CustomFormat = "0,0,""No"",@"