Подскажите, как можно оптимизировать цикл по заполнению ячеек, поскольку сейчас выполнение макроса занимает от 3 до 5 мин. Как можно его ускорить, либо быть может заменить имеющийся цикл For next на другую более быструю структуру.
Смысл работы нижеприведенного макроса следующий - заполнение нескольких диапозонов на Листе значениями, рассчитанными суммеслимн, которые берём из данных с другого листа. Проблема в скорости выполнения макроса.
Ниже приведена часть макроса, которую надо оптимизировать. [vba]
Код
Option Explicit Sub Rachet()
Dim k As Integer, i As Integer, j As Integer Dim a, b, c, d, e As Range Dim Sum(1 To 18) As Long Dim sheet1, sheet2 As Worksheet
Set sheet1 = Worksheets("Cash flow") Set sheet2 = Worksheets("Реестр операций") Set a = sheet2.Range("H3:H999000") Set b = sheet2.Range("F3:F999000") Set c = sheet2.Range("C3:C999000") Set d = sheet2.Range("L3:L999000") Set e = sheet2.Range("G3:G999000")
For j = 1 To 70 k = 3 For i = 4 To 35 Sum(1) = Application.WorksheetFunction.SumIfs(a, b, sheet1.Cells(j + 7, 3), c, sheet1.Cells(2, k + 1), d, "*" & sheet1.Cells(j + 7, 2) & "*") Cells(j + 7, i) = Sum(1)
Подскажите, как можно оптимизировать цикл по заполнению ячеек, поскольку сейчас выполнение макроса занимает от 3 до 5 мин. Как можно его ускорить, либо быть может заменить имеющийся цикл For next на другую более быструю структуру.
Смысл работы нижеприведенного макроса следующий - заполнение нескольких диапозонов на Листе значениями, рассчитанными суммеслимн, которые берём из данных с другого листа. Проблема в скорости выполнения макроса.
Ниже приведена часть макроса, которую надо оптимизировать. [vba]
Код
Option Explicit Sub Rachet()
Dim k As Integer, i As Integer, j As Integer Dim a, b, c, d, e As Range Dim Sum(1 To 18) As Long Dim sheet1, sheet2 As Worksheet
Set sheet1 = Worksheets("Cash flow") Set sheet2 = Worksheets("Реестр операций") Set a = sheet2.Range("H3:H999000") Set b = sheet2.Range("F3:F999000") Set c = sheet2.Range("C3:C999000") Set d = sheet2.Range("L3:L999000") Set e = sheet2.Range("G3:G999000")
For j = 1 To 70 k = 3 For i = 4 To 35 Sum(1) = Application.WorksheetFunction.SumIfs(a, b, sheet1.Cells(j + 7, 3), c, sheet1.Cells(2, k + 1), d, "*" & sheet1.Cells(j + 7, 2) & "*") Cells(j + 7, i) = Sum(1)
Приложил файл - он содержит 2 листа : 1) Реестр операция - он содержит исходные данные 2) Cash flow - на него выводятся значения из Реестра операций с помощью формулы Суммеслимн (диапазоны суммирования "Поступления", "Списания", диапазоны условий - "Статья затрат / ДДС", "Вид деят-ти", "Мес.", условия содержатся на листе Реестр операций в столбцах B и C.
Т. к. объем вложений ограничен, пришлось удалить из файла сам макрос. Ниже полная версия кода.
Приложил файл - он содержит 2 листа : 1) Реестр операция - он содержит исходные данные 2) Cash flow - на него выводятся значения из Реестра операций с помощью формулы Суммеслимн (диапазоны суммирования "Поступления", "Списания", диапазоны условий - "Статья затрат / ДДС", "Вид деят-ти", "Мес.", условия содержатся на листе Реестр операций в столбцах B и C.
Т. к. объем вложений ограничен, пришлось удалить из файла сам макрос. Ниже полная версия кода.
У меня создается впечатление, что вы пытаетесь макросом считать то, что вам быстрее и проще посчитает сводная. Ну или Power Query. А уж вид вашей таблички на листе CashFlow мне подозрительно напоминает один из видов PowerPivot
Хотя, если у вас в источнике данных не миллион строк, а хотя бы 100к - то можно и макрос попробовать "оптимизировать". Хотя бы только за счет "урезания бобра" до реального размера строчек с данными и отказа от кучи суммеслимн(), да ещё и несколько раз считающих разные условия по одним и тем же диапазонам... хотя полсе этого, опять ,приходим к вопросу " а все же не задействовать ли DAX и PowerQuery" и т.д.
У меня создается впечатление, что вы пытаетесь макросом считать то, что вам быстрее и проще посчитает сводная. Ну или Power Query. А уж вид вашей таблички на листе CashFlow мне подозрительно напоминает один из видов PowerPivot
Хотя, если у вас в источнике данных не миллион строк, а хотя бы 100к - то можно и макрос попробовать "оптимизировать". Хотя бы только за счет "урезания бобра" до реального размера строчек с данными и отказа от кучи суммеслимн(), да ещё и несколько раз считающих разные условия по одним и тем же диапазонам... хотя полсе этого, опять ,приходим к вопросу " а все же не задействовать ли DAX и PowerQuery" и т.д.AndreTM
Конечно руками с помощью тех же сводных или использования формул заполнить данную форму можно легко. Но интересна именно автоматизация процесса расчета и заполнения данного отчета К сожалению о Power Pivot слышал только краем уха и поэтому нет представления о его функционале...
Немного порывшись на форумах, нашел еще один способ заполнения (наподобие сводной). Вот то, что у меня получилось адаптировать к моей таблице.
Но мне надо еще вставить одно условие по последнему столбцу "Вид операции". [vba]
Код
Sub RaschetN2() Dim x, y(), i&, k&, n&, rw&, cl& Dim mn, yr, s$ mn = Array("январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь") yr = Array(2015, 2016, 2017) 'можно, например, так: yr = Array(2016, 2017, 2018, 2019) x = Sheets("Реестр операций").Range("A2").CurrentRegion.Value ReDim y(1 To UBound(x) + 2, 1 To (UBound(mn) + 1) * (UBound(yr) + 1) + 1)
With CreateObject("Scripting.Dictionary") .CompareMode = 1: k = 1 For n = 0 To UBound(yr) 'years For i = 0 To UBound(mn) 'months k = k + 1: .Item(mn(i) & yr(n)) = k '"месяц&год" - номер столбца y(1, k) = yr(n): y(2, k) = mn(i) Next i Next n
cl = 1: k = 2 For i = 3 To UBound(x) If .Exists(x(i, 7)) Then rw = .Item(x(i, 7)) Else k = k + 1: .Item(x(i, 7)) = k y(k, 1) = x(i, 7): rw = k End If
s = x(i, 3) & x(i, 4) If .Exists(s) Then cl = .Item(s) End If y(rw, cl) = y(rw, cl) + x(i, 9) Next i End With
With Sheets("Cash flow") .Range("C3").CurrentRegion.ClearContents .Range("C3").Resize(k, UBound(y, 2)).Value = y() .Activate End With End Sub
[/vba]
Конечно руками с помощью тех же сводных или использования формул заполнить данную форму можно легко. Но интересна именно автоматизация процесса расчета и заполнения данного отчета К сожалению о Power Pivot слышал только краем уха и поэтому нет представления о его функционале...
Немного порывшись на форумах, нашел еще один способ заполнения (наподобие сводной). Вот то, что у меня получилось адаптировать к моей таблице.
Но мне надо еще вставить одно условие по последнему столбцу "Вид операции". [vba]
Код
Sub RaschetN2() Dim x, y(), i&, k&, n&, rw&, cl& Dim mn, yr, s$ mn = Array("январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь") yr = Array(2015, 2016, 2017) 'можно, например, так: yr = Array(2016, 2017, 2018, 2019) x = Sheets("Реестр операций").Range("A2").CurrentRegion.Value ReDim y(1 To UBound(x) + 2, 1 To (UBound(mn) + 1) * (UBound(yr) + 1) + 1)
With CreateObject("Scripting.Dictionary") .CompareMode = 1: k = 1 For n = 0 To UBound(yr) 'years For i = 0 To UBound(mn) 'months k = k + 1: .Item(mn(i) & yr(n)) = k '"месяц&год" - номер столбца y(1, k) = yr(n): y(2, k) = mn(i) Next i Next n
cl = 1: k = 2 For i = 3 To UBound(x) If .Exists(x(i, 7)) Then rw = .Item(x(i, 7)) Else k = k + 1: .Item(x(i, 7)) = k y(k, 1) = x(i, 7): rw = k End If
s = x(i, 3) & x(i, 4) If .Exists(s) Then cl = .Item(s) End If y(rw, cl) = y(rw, cl) + x(i, 9) Next i End With
With Sheets("Cash flow") .Range("C3").CurrentRegion.ClearContents .Range("C3").Resize(k, UBound(y, 2)).Value = y() .Activate End With End Sub