К продолжению прошлой темы, прошу подсказать что делаю не так при делении данных по листам, привожу готовый макрос, благодарю Hugo, при малом количестве по полю Код работает вроде правильно, но если увеличиваю количество строк до 200 тыс. и условий деления по листам до 10 ( в коде прописано условие "сумма" или "количество", я добавляю еще варианты условий) он перестает отрабатывать, оставляет листы не заполненными.
Добрый день,
К продолжению прошлой темы, прошу подсказать что делаю не так при делении данных по листам, привожу готовый макрос, благодарю Hugo, при малом количестве по полю Код работает вроде правильно, но если увеличиваю количество строк до 200 тыс. и условий деления по листам до 10 ( в коде прописано условие "сумма" или "количество", я добавляю еще варианты условий) он перестает отрабатывать, оставляет листы не заполненными.ssm
Добрый день. Явно что-то делаете не так. Ибо если в существующем коде переставить строки вот так:
[vba]
Код
a = Sheets("сумма").Range("A5").CurrentRegion.Rows(1).Resize(2).Value ReDim b(1 To col.Count, 1 To 6) For i = 1 To col.Count b(i, 1) = col(i) For ii = 2 To UBound(a, 2) t = b(i, 1) & "|" & a(2, ii) & "|" & a(1, ii) b(i, ii) = .Item(t) Next Next Sheets("сумма").Range("A6").Resize(UBound(b), UBound(b, 2)) = b
a = Sheets("количество").Range("A5").CurrentRegion.Rows(1).Resize(2).Value ReDim b1(1 To col.Count, 1 To 6) For i = 1 To col.Count b1(i, 1) = col(i) For ii = 2 To UBound(a, 2) t = b1(i, 1) & "|" & a(2, ii) & "|" & a(1, ii) b1(i, ii) = .Item(t) Next Next Sheets("количество").Range("A6").Resize(UBound(b1), UBound(b1, 2)) = b1
[/vba]
видно что можно обойтись одним таким блоком, и одним массивом b, нужно только вывести это в подпроцедуру и менять название листа, и если сработает для одного листа, то сработает и для всех таких же других.
Добрый день. Явно что-то делаете не так. Ибо если в существующем коде переставить строки вот так:
[vba]
Код
a = Sheets("сумма").Range("A5").CurrentRegion.Rows(1).Resize(2).Value ReDim b(1 To col.Count, 1 To 6) For i = 1 To col.Count b(i, 1) = col(i) For ii = 2 To UBound(a, 2) t = b(i, 1) & "|" & a(2, ii) & "|" & a(1, ii) b(i, ii) = .Item(t) Next Next Sheets("сумма").Range("A6").Resize(UBound(b), UBound(b, 2)) = b
a = Sheets("количество").Range("A5").CurrentRegion.Rows(1).Resize(2).Value ReDim b1(1 To col.Count, 1 To 6) For i = 1 To col.Count b1(i, 1) = col(i) For ii = 2 To UBound(a, 2) t = b1(i, 1) & "|" & a(2, ii) & "|" & a(1, ii) b1(i, ii) = .Item(t) Next Next Sheets("количество").Range("A6").Resize(UBound(b1), UBound(b1, 2)) = b1
[/vba]
видно что можно обойтись одним таким блоком, и одним массивом b, нужно только вывести это в подпроцедуру и менять название листа, и если сработает для одного листа, то сработает и для всех таких же других.Hugo
Private Sub подпроцедура(лист, col, dic As Object) Dim a, b, i&, ii&, t$
Sheets(лист).Range("A6:M13").ClearContents a = Sheets(лист).Range("A5").CurrentRegion.Rows(1).Resize(2).Value ReDim b(1 To col.Count, 1 To 6) For i = 1 To col.Count b(i, 1) = col(i) For ii = 2 To UBound(a, 2) t = b(i, 1) & "|" & a(2, ii) & "|" & a(1, ii) b(i, ii) = dic.Item(t) Next Next Sheets(лист).Range("A6").Resize(UBound(b), UBound(b, 2)) = b
End Sub
[/vba] И даже можно имена листов загнать в массив и перебирать его - будет ещё проще.
Вот например: [vba]
Код
Option Explicit
Sub кол() Dim a(), i&, ii&, t$, col As New Collection Dim dic As Object Set dic = CreateObject("scripting.dictionary") With dic .comparemode = 1
a = Sheets("данные").Range("A1").CurrentRegion.Value
On Error Resume Next For i = 2 To UBound(a) col.Add a(i, 1), Trim(a(i, 1)) t = a(i, 1) & "|" & a(i, 4) & "|" & "сумма" .Item(t) = .Item(t) + a(i, 3) t = a(i, 1) & "|" & a(i, 4) & "|" & "количество" .Item(t) = .Item(t) + a(i, 2) Next On Error GoTo 0
Private Sub подпроцедура(лист, col, dic As Object) Dim a, b, i&, ii&, t$
Sheets(лист).Range("A6:M13").ClearContents a = Sheets(лист).Range("A5").CurrentRegion.Rows(1).Resize(2).Value ReDim b(1 To col.Count, 1 To 6) For i = 1 To col.Count b(i, 1) = col(i) For ii = 2 To UBound(a, 2) t = b(i, 1) & "|" & a(2, ii) & "|" & a(1, ii) b(i, ii) = dic.Item(t) Next Next Sheets(лист).Range("A6").Resize(UBound(b), UBound(b, 2)) = b
End Sub
[/vba] И даже можно имена листов загнать в массив и перебирать его - будет ещё проще.Hugo
Sub кол() Dim a(), i&, x&, t$, col As New Collection Dim dic As Object, arr
Set dic = CreateObject("scripting.dictionary") arr = Split("количество сумма") With dic .comparemode = 1
a = Sheets("данные").Range("A1").CurrentRegion.Value
On Error Resume Next For i = 2 To UBound(a) col.Add a(i, 1), Trim(a(i, 1)) For x = 0 To UBound(arr) t = a(i, 1) & "|" & a(i, 4) & "|" & arr(x) .Item(t) = .Item(t) + a(i, x + 2) Next Next On Error GoTo 0
For x = 0 To UBound(arr) подпроцедура arr(x), col, dic Next
End With End Sub
Private Sub подпроцедура(лист, col, dic As Object) Dim a, b, i&, ii&, t$
With Sheets(лист).Range("A5").CurrentRegion .Rows(3).Resize(.Rows.Count - 2).ClearContents End With
a = Sheets(лист).Range("A5").CurrentRegion.Rows(1).Resize(2).Value ReDim b(1 To col.Count, 1 To 6) For i = 1 To col.Count b(i, 1) = col(i) For ii = 2 To UBound(a, 2) t = b(i, 1) & "|" & a(2, ii) & "|" & a(1, ii) If dic.exists(t) Then b(i, ii) = dic.Item(t) Next Next Sheets(лист).Range("A6").Resize(UBound(b), UBound(b, 2)) = b
End Sub
[/vba]
Только вот на практике диапазон "A6:M13" думаю нужно корректировать динамически. Можно привязываться к тому же Sheets(лист).Range("A5").CurrentRegion - изменил код.
Итоговый вариант, подправил массив arr
[vba]
Код
Option Explicit
Sub кол() Dim a(), i&, x&, t$, col As New Collection Dim dic As Object, arr
Set dic = CreateObject("scripting.dictionary") arr = Split("количество сумма") With dic .comparemode = 1
a = Sheets("данные").Range("A1").CurrentRegion.Value
On Error Resume Next For i = 2 To UBound(a) col.Add a(i, 1), Trim(a(i, 1)) For x = 0 To UBound(arr) t = a(i, 1) & "|" & a(i, 4) & "|" & arr(x) .Item(t) = .Item(t) + a(i, x + 2) Next Next On Error GoTo 0
For x = 0 To UBound(arr) подпроцедура arr(x), col, dic Next
End With End Sub
Private Sub подпроцедура(лист, col, dic As Object) Dim a, b, i&, ii&, t$
With Sheets(лист).Range("A5").CurrentRegion .Rows(3).Resize(.Rows.Count - 2).ClearContents End With
a = Sheets(лист).Range("A5").CurrentRegion.Rows(1).Resize(2).Value ReDim b(1 To col.Count, 1 To 6) For i = 1 To col.Count b(i, 1) = col(i) For ii = 2 To UBound(a, 2) t = b(i, 1) & "|" & a(2, ii) & "|" & a(1, ii) If dic.exists(t) Then b(i, ii) = dic.Item(t) Next Next Sheets(лист).Range("A6").Resize(UBound(b), UBound(b, 2)) = b
End Sub
[/vba]
Только вот на практике диапазон "A6:M13" думаю нужно корректировать динамически. Можно привязываться к тому же Sheets(лист).Range("A5").CurrentRegion - изменил код.Hugo
Да, чуть ошибся, не потестил на пустом листе... А зачем оно нужно - ну ведь у Вас в коде есть очистка диапазона. Но не привязана к данным - вдруг их там будет больше?
Да, чуть ошибся, не потестил на пустом листе... А зачем оно нужно - ну ведь у Вас в коде есть очистка диапазона. Но не привязана к данным - вдруг их там будет больше?Hugo
Hugo, я о том что ваш кусок файла так же растягивается на заполненный диапазон данными и очищает его. Просто, я, программированием VBA занимаюсь по необходимости когда совсем прижмет из-за объем данных и формулы уже не справляются:) Только сейчас с вашей помощью начал понимать как работает Resize:) Большое спасибо что вы есть, и есть кто может поделиться опытом.
Hugo, я о том что ваш кусок файла так же растягивается на заполненный диапазон данными и очищает его. Просто, я, программированием VBA занимаюсь по необходимости когда совсем прижмет из-за объем данных и формулы уже не справляются:) Только сейчас с вашей помощью начал понимать как работает Resize:) Большое спасибо что вы есть, и есть кто может поделиться опытом.ssm
Сообщение отредактировал ssm - Понедельник, 15.06.2020, 20:16