Трудно сказать, не видя структуру и структуру ваших данных и рабочей книги (в случае, если есть более простой / более эффективный способ того, что вы делаете). Но ниже приведены некоторые основные наблюдения.
Вероятно, вы должны использовать Range.AutoFilter
ниже (вместо того, чтобы проходить по десяткам тысяч строк по одной строке за раз). Затем скопируйте и вставьте Range.SpecialCells(xlCellTypeVisible)
в duplicateSheet
за один раз. Вам может потребоваться преобразовать ваши даты в двойные (с функцией CDbl()
) при указании критериев фильтра даты. (Вы также можете прочитать массив один раз. С массивом производительность может быть выше, но вам также придется писать больше кода.)
'Copy data to duplicate sheet
For i = 2 To finalRow
If (Cells(i, 17) >= startDate And Cells(i, 17) <= EndDate And Cells(i, 16) = Company And Cells(i, 9) = Targetperiod) Then
Range(Cells(i, 1), Cells(i, 19)).Copy
duplicateSheet.Range("a10000").End(xlUp).Offset(1, 21).PasteSpecial xlPasteValues
duplicateSheet.Range("a10000").End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
End If
Next i
Ниже вы назначаете то, что должно быть формулой массива как формула без массива, для каждой ячейки в столбце AM
(по одной строке за раз); затем выполните цикл снова (по одной строке за раз), чтобы превратить формулу без массива в формулу массива; затем выполните цикл снова (по одной строке за раз), чтобы преобразовать формулы в статические значения.
Есть ли причина, по которой вы не можете установить формулу массива для всего диапазона за один раз? Я верю, что Excel позаботится об относительных ссылках на ячейки для вас. Затем превратить формулы указанного диапазона в статические значения. (В качестве альтернативы вы можете прочитать значения диапазона в массив и вычислить условное значение MAX
в памяти. Но, как уже было сказано, вам нужно будет написать больше кода.)
Кроме того, некоторые новые версии Excel изначально имеют функцию MAXIFS
. Если у вас есть доступ к нему, попробуйте использовать это. Другое наблюдение состоит в том, что ваша формула массива относится ко всему столбцу. Возможно, стоит ограничить диапазон (т. Е. До последней использованной строки в этом столбце), поэтому вы смотрите только <100 тыс. Ячеек (например) вместо 1 млн. </p>
И последнее: конкатенация строк может быть дорогостоящей. Как правило, вы хотите использовать некоторую форму функции JOIN
при конкатенации, хотя я не уверен, насколько это повысит производительность, так как вы объединяете только два значения (для каждой итерации цикла).
'Below is for finding most recent observation and Target price.
d = 2
Do While duplicateSheet.Cells(d, 38).Value <> ""
duplicateSheet.Cells(d, 39).FormulaLocal = "=MAX(IF('Duplicate sheet'!n:n='Duplicate sheet'!Ai" & d & ";'Duplicate sheet'!q:q;))"
d = d + 1
Loop
Dim c As Range
For Each c In duplicateSheet.Range("Am2", "am" & Newduplicaterow)
c.FormulaArray = c.FormulaR1C1
Next c
d = 2
Do While duplicateSheet.Cells(d, 38).Value <> ""
duplicateSheet.Cells(d, 39).Value = duplicateSheet.Cells(d, 39).Value
duplicateSheet.Cells(d, 40).Value = duplicateSheet.Cells(d, 35) & ", " & duplicateSheet.Cells(d, 39)
d = d + 1
Loop
Вероятно, вы можете назначить приведенную ниже формулу всему диапазону за один раз. Следует отметить, что предоставление 0
в качестве третьего аргумента MATCH
означает, что вы выполняете линейный поиск (для каждой итерации цикла). Рассмотрите возможность использования словаря или коллекции для более быстрого поиска (словарь, вероятно, более удобен, так как имеет метод Exists
). В вашем случае, я думаю, что значения в столбце S
будут ключами, а значения в столбце D
будут соответствующими значениями ключей.
Кроме того, вы можете преобразовать весь диапазон в статические значения за один раз (вместо зацикливания по одной строке за раз).
d = 2
Do While duplicateSheet.Cells(d, 38).Value <> ""
duplicateSheet.Cells(d, 41).FormulaLocal = "=index('Duplicate sheet'!d:d;match('Duplicate sheet'!AN" & d & ";'Duplicate sheet'!s:s;0);0)"
duplicateSheet.Cells(d, 41).Value = duplicateSheet.Cells(d, 41).Value
d = d + 1
Loop
Надеюсь, это даст вам некоторые идеи о том, с чего начать.