#excel #vba
#excel #vba
Вопрос:
У меня есть электронная таблица с приблизительно 45 000 строками. В настоящее время я перебираю столбец и нацеливаюсь на любые ячейки со значением 0. Эти номера строк сохраняются в массиве. Затем я перебираю этот массив и изменяю другую ячейку на основе значения массива. У меня есть 5000 строк со значениями, которые необходимо переназначить, и на выполнение этого сегмента кода уходит более часа (сохранение номеров строк в массив занимает всего несколько секунд). Есть идеи о том, как заставить код работать быстрее? Вот код:
'Initialize array
Dim myArray() As Variant
Dim x As Long
'Looks for the last row on the "Dates" sheet
Dim lastRow As Long
With ThisWorkbook.Sheets("Dates")
lastRow = .Cells(.Rows.Count, "C").End(xlUp).Row 1
End With
Dim i As Integer
i = 2
Dim uCounter As Integer
'Loop through all the dates on the "Dates" sheet
While i <= lastRow
'Each date has a counter next to it
uCounter = Worksheets("Dates").Range("B" amp; i).Value
Dim uDate As String
'Store the date as a string
uDate = Worksheets("Dates").Range("C" amp; i).Value
Dim startRow As Long, endRow As Long
'Finds the first and last instance of the date on the CERF Data page (45,000 rows)
With Sheets("CERF Data")
startRow = .Range("AN:AN").Find(what:=uDate, after:=.Range("AN1"), LookIn:=xlValues).Row
endRow = .Range("AN:AN").Find(what:=uDate, after:=.Range("AN1"), LookIn:=xlValues, searchdirection:=xlPrevious).Row
End With
Dim j As Long
For j = startRow To endRow
'If the cell in column BB is 0, and the counter is above 0 save row number to array, j being the variable representing row number
If Sheets("CERF Data").Range("BB" amp; j).Value = 0 And uCounter > 0 Then
'save row number to array
ReDim Preserve myArray(x)
myArray(x) = j
x = x 1
'decrement counter by 1
uCounter = uCounter - 1
End If
If uCounter = 0 Then Exit For
Next j
i = i 1
Wend
Dim y As Long
'Loop through the array and assign a value of 2 to all the rows in the array for column AS
For y = LBound(myArray) To UBound(myArray)
Sheets("CERF Data").Range("AS" amp; myArray(y)).Value = 2
Next y
Спасибо!
Комментарии:
1. Мы не сможем помочь вам без вашего кода.
2. Без кода… Почему бы вам просто не получить весь лист в массиве и не проверить свои критерии, если они совпадают, вы можете напрямую изменить все, что вам нужно в массиве, и вставить это обратно на лист. Это займет всего несколько секунд.
3. Опубликовал код. Неплохая идея, я попробую.
4. @Djaenike На самом деле я бы сделал то же самое, что и Дамиан, но убедитесь, что вы читаете только используемый диапазон (содержащий данные), а не весь лист. В противном случае вы читаете много пустых ячеек.
5. Некоторая полезная информация о создании массивов из диапазона листов
Ответ №1:
Без дополнительной информации это то, что я могу вам предоставить:
Просто 1 цикл по всем строкам, один раз, проверяя, находится ли значение в столбце BB = 0 и дата в пределах вашего диапазона дат:
Option Explicit
Sub Test()
Dim arr, i As Long, DictDates As Scripting.Dictionary
arr = ThisWorkbook.Sheets("CERF Data").UsedRange.Value
Set DictDates = New Scripting.Dictionary 'You need the Microsoft Scripting Runtime Reference for this to work
'Create a dictionary with all the dates you must check
With ThisWorkbook.Sheets("Dates")
LastRow = .Cells(.Rows.Count, 3).End(xlUp).Row
For i = 2 To LastRow
If Not DictDates.Exists(CDate(.Cells(i, 3))) Then DictDates.Add CDate(.Cells(i, 3)), 1
Next i
End With
'Only one loop through the whole array
For i = 1 To UBound(arr)
If arr(i, 54) = 0 And DictDates.Exists(CDate(arr(i, 40))) Then 'check your 2 criterias, date and value = 0
arr(i, 45) = 2 'input the value 2 on the column "AS"
End If
Next i
ThisWorkbook.Sheets("CERF Data").UsedRange.Value = arr
End Sub