Есть ли ограничение на количество ячеек, которые может содержать объект диапазона? - PullRequest
3 голосов
/ 04 июня 2019

У меня есть лист с примерно 300'000 строками, часть которого необходимо удалить.

Я заполняю массив номерами строк и выполняю процедуру удаления строк в этом массиве:

Sub Start()
'...

b = 0 
ReDim arr(b)

For i = LRow To 2 Step -1
    If .Cells(i, "L").Value = "" then
        ReDim Preserve arr(b)
        arr(b) = i
        b = b + 1
    End If
Next i

.Range("A" & Join(arr, ",A")).EntireRow.Delete

'...
End Sub

С кодом выше, arr в конечном итоге содержит около 68 000 номеров строк.

На строке, которая должна удалить эти строки, я получаю ошибку

Ошибка метода 'Range' объекта '_Worksheet'

Это также происходит, когда я пытаюсь выбрать их вместо их удаления.

Получение части выходных данных от функции Join выполняется, как ожидается, например:

.Range("A" & "2465,A2457,A2432,A2428,A2410,A2405,A2376,A2372,A2358,A2354").EntireRow.Delete

Что приводит к сбою кода? Есть ли предел для объекта Range, о котором я не знаю?

Ответы [ 3 ]

4 голосов
/ 04 июня 2019

Это способ:

Sub Start()
    '...

    Dim DeleteRange As Range

    For i = LRow To 2 Step -1
        If .Cells(i, "L").Value = "" Then
            If DeleteRange Is Nothing Then
                Set DeleteRange = .Cells(i, "A")
            Else
                Set DeleteRange = Union(DeleteRange, .Cells(i, "A"))
            End If
        End If
    Next i

    DeleteRange.EntireRow.Delete

    '...

End Sub

Подумайте, как вам нужно, он должен работать так, как вы говорите:

.Range("A" & "2465,A2457,A2432,A2428,A2410,A2405,A2376,A2372,A2358,A2354").EntireRow.Delete Пока ваш диапазон не превышает 255 символов,Если он не просто проверяет, какое значение для: "A" & Join(arr, ",A"), возможно, что-то не так или отсутствует.

Редактировать: Другой способ сделать это

Sub Start()
    '...

    Dim arrData
    Dim j As Long

    b = 1

    arr = .UsedRange.Value
    ReDim arrData(1 To UBound(arr), 1 To UBound(arr, 2))
    For i = 1 To UBound(arr)
        If arr(i, 12) <> vbNullString Then
            For j = 1 To UBound(arrData, 2)
                arrData(b, j) = arr(i, j)
            Next j
            b = b + 1
        End If
    Next i

    .UsedRange = arrData

'...
End Sub
3 голосов
/ 04 июня 2019

Для ссылки Range существует ограничение в 255 символов, которое вы превзошли на дрожжах; В частности,

"A" & "2465,A2457,A2432,A2428,A2410,A2405,A2376,A2372,A2358,A2354..."

может содержать не более 255 символов.

Это можно проверить с помощью простого теста:

Sub Test()
    Dim arr(1 To 40) As String
    Dim arr2(1 To 80) As String

    Dim i As Long

    For i = LBound(arr) To UBound(arr)
        arr(i) = CStr(i)
    Next i

    For i = LBound(arr2) To UBound(arr2)
        arr2(i) = CStr(i)
    Next i

    Debug.Print Len("A" & Join(arr, ",A")) ' returns 150
    Debug.Print Len("A" & Join(arr2, ",A")) ' returns 310

    Range("A" & Join(arr, ",A")).EntireRow.Delete ' works
    Range("A" & Join(arr2, ",A")).EntireRow.Delete ' fails
End Sub

Union или решение в виде массива, как уже предлагалось, являются альтернативами.

0 голосов
/ 04 июня 2019

Альтернативный объединяющий массив Подход с функцией объединения

Перебор диапазонов через VBA занимает много времени, удаление через EntireRow с использованием объединения происходит быстро, поэтому комбинация обоих вместо сбора всехОстальные значения столбцов кажутся подходящими:

Sub DeleteEmptyRows()
With ThisWorkbook.Worksheets("Nonsens")
' assign column data to 2-dim array
  Dim v, lrow&: lrow = .Range("L" & Rows.Count).End(xlUp).Row
  v = .Range("L1:L" & lrow)                     ' start from top to get correct row numbers later
' check first empty cell
  Dim currRow&, delRng As Range
  For currRow = 2 To UBound(v)
      If v(currRow, 1) = vbNullString Then
           Set delRng = .Range("A" & currRow)
           Exit For
      End If
  Next currRow
' collect rest via UNION function
  For currRow = currRow To UBound(v)
      If v(currRow, 1) = vbNullString Then Set delRng = Union(delRng, .Range("A" & currRow))
  Next currRow
' delete entire rows in range set
  If Not delRng Is Nothing Then delRng.EntireRow.Delete

End With

End Sub

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