Excel VBA для крушения в 1000-й раз - PullRequest
1 голос
/ 05 мая 2019

Я пытаюсь использовать некоторый код 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 »: сбой метода« Range »для объекта« Глобальный »

Любой совет будет принят с благодарностью.

Большое спасибо.

Ответы [ 2 ]

4 голосов
/ 05 мая 2019

Запустите цикл в своей голове:

  1. Когда i = 1, тогда диапазон составляет "A2:H7541" (строки 2 до 7,541)
  2. Когда i = 2, тогда диапазон составляет "A2:H7542" (строки 2 до 7,542)
  3. Когда i = 9, то диапазон составляет "A2:H7549" (строки 2 до 7,549)
  4. Когда i = 10, то диапазон составляет "A2:H75410" (строки 2 до 75,410)
  5. Когда i = 99, то диапазон составляет "A2:H75499" (строки 2 до 75,499)
  6. Если i = 100, то диапазон составляет "A2:H754100" (строки 2 - 754,100)
  7. Когда i = 900, диапазон равен "A2:H754900" (Строки 2 - 754,900)
  8. Когда i = 999, то диапазон составляет "A2:H754999" (строки 2 - 754,999)
  9. Когда i = 1000, тодиапазон равен "A2:H7541000" (строки 2 - 7,541,000)

Обратите внимание, что каждое значение i пересекает каждую десятую степень, а число строк увеличивается на порядок:

  • От i = 9 до i = 10 вы переходите от ряда 7,549 к 75,410
  • От i = 99 до i = 100 вы переходите от ряда75,499 до 754,100
  • От i = 999 до i = 1000 вы переходите от строки 754,100 к 7,541,000

Также обратите внимание, что строка целевого диапазона всегда2 - поэтому на каждой итерации вы всегда перезаписываете себя.

Сбой из-за того, что электронные таблицы Excel (начиная с Excel 2007) не могут превышать 1,048,576 строк, что приводит к сбою.Ограничение составляет 65,355 до Excel 2007 или при использовании электронной таблицы не-OOXML в современных версиях Excel).

Я ожидаю, что в конце будет около 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 голос
/ 06 мая 2019

Вот несколько подсказок:

  1. Нет необходимости выполнять строковую математику, например Range("A2:H754" & i). Лучшее решение - начать с верхней левой ячейки, используя метод .Cells(row, column) для доступа к определенной ячейке.
  2. Разверните ячейку в таблице, используя метод .Resize(row_count, column_count).
  3. Наконец, нет необходимости использовать буфер обмена с методами .Copy или .Paste, если это медленно и требует много памяти. Используйте прямое назначение в свойство .Value.

Например, чтобы скопировать 178-ю строку из таблицы с ячейками 1000 × 8, расположенной под A2, в первую строку листа, используйте следующую команду:

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

Обратите внимание, что .Resize() значения сильно совпадают по обе стороны от назначения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...