【问题标题】:Excel VBA FOR LOOP Crashing on 1000th TimeExcel VBA FOR LOOP 在第 1000 次崩溃
【发布时间】:2019-05-06 15:49:35
【问题描述】:

我正在尝试使用一些 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'的方法'范围'失败”

任何建议将不胜感激。

非常感谢。

【问题讨论】:

  • 你是说Range("A2:H" & CStr(754+i)).PasteSpecial Paste:=xlPasteValues

标签: excel vba


【解决方案1】:

在脑海中运行循环:

  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 行,因此崩溃。在 Excel 2007 之前或在现代版本的 Excel 中使用非 OOXML 电子表格时,限制为 65,355

我预计最终会有大约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

【讨论】:

  • @chrisneilsen derp!谢谢你指出这一点。我已经重写了我的答案。
【解决方案2】:

这里有一些提示:

  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() 的值非常匹配在分配的两边。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多