Excel VBA FOR LOOP在第1000次崩溃

时间:2019-05-05 18:34:57

标签: excel vba

我正在尝试使用一些VBA代码复制一定范围的单元格并将其值粘贴到接下来的空行中2111次。

此操作成功粘贴到754507行,此后崩溃。

我在调试中看到它在第1000个循环处停止。

Option Explicit
Sub Paste_APIROWS()

Application.ScreenUpdating = False

Dim i As Long
Range("A2:H754").Copy
For i = 1 To 2111
    Range("A2:H754" & i).PasteSpecial Paste:=xlPasteValues
    Debug.Print i
    Next i

   Application.CutCopyMode = False

End Sub

我希望最终能有大约1589583行,但似乎只能得到其中的一半。

  

我收到的错误消息是“运行时错误'1004':对象'_Global'的方法'范围'失败”

任何建议将不胜感激。

非常感谢。

2 个答案:

答案 0 :(得分:4)

运行循环:

  1. i = 1时,范围是"A2:H7541"(行27,541
  2. i = 2时,范围是"A2:H7542"(行27,542
  3. i = 9时,范围是"A2:H7549"(行27,549
  4. i = 10时,范围是"A2:H75410"(行275,410
  5. i = 99时,范围是"A2:H75499"(行275,499
  6. i = 100时,范围是"A2:H754100"(行2754,100
  7. i = 900时,范围是"A2:H754900"(行2754,900
  8. i = 999时,范围是"A2:H754999"(行2754,999
  9. i = 1000时,范围是"A2:H7541000"(行27,541,000

请注意,i的每个值与每10次幂相乘时,行数将增加一个数量级:

  • i = 9i = 10,您从行7,54975,410
  • i = 99i = 100,您从行75,499754,100
  • i = 999i = 1000,您从行754,1007,541,000

还要注意,目标范围行始终为2-因此,在每次迭代中,您总是覆盖自己。

它崩溃是因为Excel电子表格(自Excel 2007起)不能超过1,048,576行,因此崩溃。限制为65,355在Excel 2007之前或在现代版本的Excel中使用非OOXML电子表格时。

  

我希望最终能有大约1,589,583行,但似乎只能得到其中的一半。

两件事:

  • Excel始终不支持1,589,583行(如上所述,最大值为1,048,576)。
  • 按照我上面的解释,您的逻辑无法正确计算复制目标范围。

导致错误的原因是使用字符串串联(即&运算符)而不是数字加法。

您要复制A2:H754范围内的单元格一些 2111 1930次-这实际上意味着您要这样做:

Const sourceRowLB =   2
Const sourceRowUB = 755 ' 755 not 754 because exclusive upper-bounds are easier to work with
Dim sourceRowCount = sourceRowUB - sourceRowLB

Dim lastCopyUB = 755

Dim sourceRangeExpr = GetRangeExpr( "A", sourceRowLB, "H", sourceRowUB ) ' Will be "A2:H754"
Range( sourceRangeExpr  ).Copy

Const loopCount As Integer = 1389 ' This cannot be 2111 because ( 2111 * 754 ) exceeds the maximum row count
For i = 1 ToloopCount ' Loop 1389 times

    ' Recompute the destination range:
    Dim destRowLB As Integer
    destRowLB = lastCopyUB
    Dim destRowUB As Integer
    destRowUB = destRowLB + sourceRowCount

    Dim rangeExpression As String
    rangeExpression = GetRangeExpr( "A", destRowLB, "H" & destRowUB )

    Range( rangeExpression ).PasteSpecial Paste:=xlPasteValues

    lastCopyUB = destRowUB

Next i

Function GetRangeExpr(startCol As String, startRow As Integer, endCol As String, endRowExclUB As Integer) As String

    GetRangeExpr = startCol  & CStr( destRowLB ) & ":" & endCol & CStr( endRowExclUB  - 1 ) ' We convert endRowExclUB to an inclusive upper-bound here

End Function

答案 1 :(得分:1)

以下是一些提示:

  1. 不需要像Range("A2:H754" & i)这样的字符串数学。更好的解决方案是从左上方的单元格使用.Cells(row, column)方法访问特定的单元格。
  2. 使用.Resize(row_count, column_count)方法将单元格扩展到表中。
  3. 最后,无需将剪贴板与.Copy.Paste方法一起使用,因为它速度慢且占用大量内存。使用直接分配到.Value属性中。

例如,要将位于A2下的1000×8单元格的表中的第178行复制到工作表的第一行,请使用以下

Range("A1").Resize(1,8).Value = Range("A2").Cells(178,1).Resize(1,8).Value

请注意,分配两侧的.Resize()完全匹配