Добрый вечер, Форумчане! Столкнулся с проблемой, прошу Вашей помощи! Есть файл с около 340 тыс. строк. Необходимо случайным образом примерно 40 тыс. строк выбрать и оставить, а остальные удалить. В прикрепленном файле, собственно, это и осуществляется. Проблема в том, что на реальном файле эксель виснет (к неудаче рабочий комп celerone & 2Gb оперативной памяти), в итоге через 40 минут отработки закладка программы на панели задач начинает дергаться будто предвещая конец, но нет. Пробовал ускорить: известно точное количество изначальных строк и столбцов, вставлял числами вместо поиска последних. В итоге уже через 5 минут закладка программы на панели задач начинает дергаться, и только... Можно ли как-то ускорить данный макрос, подскажите, пожалуйста?
[vba]
Код
Sub delete_rand()
ScreenUpdating = False Dim last_row As Long, last_col As Long
For i = 1 To last_row Cells(i, last_col + 1).Value = Int((17 - 1 + 1) * Rnd + 1) Next
For j = Cells(Rows.Count, 1).End(xlUp).Row To 1 Step -1 If Not Cells(j, last_col + 1) = 7 Or Cells(j, last_col + 1) = 11 Then Cells(j, last_col + 1).EntireRow.Delete End If Next
ScreenUpdating = True End Sub
[/vba]
Добрый вечер, Форумчане! Столкнулся с проблемой, прошу Вашей помощи! Есть файл с около 340 тыс. строк. Необходимо случайным образом примерно 40 тыс. строк выбрать и оставить, а остальные удалить. В прикрепленном файле, собственно, это и осуществляется. Проблема в том, что на реальном файле эксель виснет (к неудаче рабочий комп celerone & 2Gb оперативной памяти), в итоге через 40 минут отработки закладка программы на панели задач начинает дергаться будто предвещая конец, но нет. Пробовал ускорить: известно точное количество изначальных строк и столбцов, вставлял числами вместо поиска последних. В итоге уже через 5 минут закладка программы на панели задач начинает дергаться, и только... Можно ли как-то ускорить данный макрос, подскажите, пожалуйста?
[vba]
Код
Sub delete_rand()
ScreenUpdating = False Dim last_row As Long, last_col As Long
For i = 1 To last_row Cells(i, last_col + 1).Value = Int((17 - 1 + 1) * Rnd + 1) Next
For j = Cells(Rows.Count, 1).End(xlUp).Row To 1 Step -1 If Not Cells(j, last_col + 1) = 7 Or Cells(j, last_col + 1) = 11 Then Cells(j, last_col + 1).EntireRow.Delete End If Next
For j = Cells(Rows.Count, 1).End(xlUp).Row To 1 Step -1 If Not Cells(j, last_col + 1) = 7 Or Cells(j, last_col + 1) = 11 Then Cells(j, last_col + 1).EntireRow.Delete End If Next
[/vba]
меняем на это: [vba]
Код
dim rngGarb as range For j = Cells(Rows.Count, 1).End(xlUp).Row To 1 Step -1 If Not Cells(j, last_col + 1) = 7 Or Cells(j, last_col + 1) = 11 Then if rngGarb is nothing then set rngGarb = range("a" & j) else set rngGarb = union(range("a" & j), rngGarb) end if ''' Cells(j, last_col + 1).EntireRow.Delete End If Next
if not rngGarb is nothing then rngGarb.EntireRow.Delete end if
[/vba]
этот прием должен многократно сократить время выполнения
этот кусок: [vba]
Код
For j = Cells(Rows.Count, 1).End(xlUp).Row To 1 Step -1 If Not Cells(j, last_col + 1) = 7 Or Cells(j, last_col + 1) = 11 Then Cells(j, last_col + 1).EntireRow.Delete End If Next
[/vba]
меняем на это: [vba]
Код
dim rngGarb as range For j = Cells(Rows.Count, 1).End(xlUp).Row To 1 Step -1 If Not Cells(j, last_col + 1) = 7 Or Cells(j, last_col + 1) = 11 Then if rngGarb is nothing then set rngGarb = range("a" & j) else set rngGarb = union(range("a" & j), rngGarb) end if ''' Cells(j, last_col + 1).EntireRow.Delete End If Next
if not rngGarb is nothing then rngGarb.EntireRow.Delete end if
[/vba]
этот прием должен многократно сократить время выполненияСаня
Сообщение отредактировал Саня - Четверг, 26.01.2017, 00:58
Саня, супер! Все равно правда тормозит на больших объемах. Юнион - зараза та еще. Вот откопал от ZVI предполагаемое ускорение и ссылку (на 4 поста выше) http://www.planetaexcel.ru/forum....ge89799
rosko, вот здесь Вы пишете что-то странное (вернее, избыточное условие)
If Not Cells(j, last_col + 1) = 7 Or Cells(j, last_col + 1) = 11 Then
В переводе на русский - удаляем, если ячейка не равна 7 или если ячейка равна 11. Но если ячейка не равна 7, то нам уже все равно, равна ли она 11, мы в любом случае ее удаляем. Возможно, Вы хотели вот так (оставляем 7 и 11)? [vba]
Код
If Not Cells(j, last_col + 1) = 7 And Not Cells(j, last_col + 1) = 11 Then
[/vba] [vba]
Код
If Cells(j, last_col + 1) <> 7 And Cells(j, last_col + 1) <> 11 Then
[/vba] Как раз 340000 / 40000 = 17 / 2
Саня, супер! Все равно правда тормозит на больших объемах. Юнион - зараза та еще. Вот откопал от ZVI предполагаемое ускорение и ссылку (на 4 поста выше) http://www.planetaexcel.ru/forum....ge89799
rosko, вот здесь Вы пишете что-то странное (вернее, избыточное условие)
If Not Cells(j, last_col + 1) = 7 Or Cells(j, last_col + 1) = 11 Then
В переводе на русский - удаляем, если ячейка не равна 7 или если ячейка равна 11. Но если ячейка не равна 7, то нам уже все равно, равна ли она 11, мы в любом случае ее удаляем. Возможно, Вы хотели вот так (оставляем 7 и 11)? [vba]
Код
If Not Cells(j, last_col + 1) = 7 And Not Cells(j, last_col + 1) = 11 Then
[/vba] [vba]
Код
If Cells(j, last_col + 1) <> 7 And Cells(j, last_col + 1) <> 11 Then
Доброе время суток. Как мне кажется - лобовое решение не будет быстрым. Проще через вспомогательный массив признаков с последующей сортировкой строк (Excel использует устойчивую сортировку) по нему и последующим удалением.
[vba]
Код
Public Sub RandomDeleteRows() Dim i As Long, LRow As Long, LCol As Long Dim pSheet As Worksheet, randoms() As Long Dim randomCount As Long, onePos As Long
For i = 1 To randomCount onePos = CLng(Math.Rnd * (LRow - 2)) + 1 randoms(onePos, 1) = 1 Next pSheet.Range(pSheet.Cells(2, LCol + 1), pSheet.Cells(LRow, LCol + 1)).Value = randoms pSheet.Sort.SortFields.Clear pSheet.Sort.SortFields.Add Key:=pSheet.Cells(1, LCol + 1), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal With pSheet.Sort .SetRange pSheet.Range(pSheet.Cells(1, 1), pSheet.Cells(LRow, LCol + 1)) .Header = xlYes .MatchCase = False .Orientation = xlTopToBottom .SortMethod = xlPinYin .Apply End With LRow = pSheet.Range(pSheet.Cells(1, LCol + 1), pSheet.Cells(LRow, LCol + 1)).Find(What:=1).Row - 1 pSheet.Range(pSheet.Cells(2, 1), pSheet.Cells(LRow, 1)).EntireRow.Delete Shift:=xlShiftUp pSheet.Columns(LCol + 1).EntireColumn.Delete Shift:=xlShiftToLeft End Sub
[/vba]
Успехов.
Доброе время суток. Как мне кажется - лобовое решение не будет быстрым. Проще через вспомогательный массив признаков с последующей сортировкой строк (Excel использует устойчивую сортировку) по нему и последующим удалением.
[vba]
Код
Public Sub RandomDeleteRows() Dim i As Long, LRow As Long, LCol As Long Dim pSheet As Worksheet, randoms() As Long Dim randomCount As Long, onePos As Long
Я взял 300к строк с даными , правда формулой добавил рандомное значение в доп столбец для простоты, а потом через MS Query [vba]
Код
SELECT * FROM `TransList$` `TransList$` WHERE (`TransList$`.RND<>7 And `TransList$`.RND<>11)
[/vba] 10 сек не прошло на другом листе все без этих строк Вариант 2. Advanced Filter. с копией в другое место. с условиями <>7 и <>11 . Аналогично секунды. Хотя тот же обьем скриптом обрабатывался ооооочеь долго.
Оба варианта можно через скрипт организовать.
rosko, А вы поясните задачу исходную.
Я взял 300к строк с даными , правда формулой добавил рандомное значение в доп столбец для простоты, а потом через MS Query [vba]
Код
SELECT * FROM `TransList$` `TransList$` WHERE (`TransList$`.RND<>7 And `TransList$`.RND<>11)
[/vba] 10 сек не прошло на другом листе все без этих строк Вариант 2. Advanced Filter. с копией в другое место. с условиями <>7 и <>11 . Аналогично секунды. Хотя тот же обьем скриптом обрабатывался ооооочеь долго.
Оба варианта можно через скрипт организовать.bmv98rus
Замечательный Временно просто медведь , процентов на 20.
Сообщение отредактировал bmv98rus - Четверг, 26.01.2017, 10:04
bmv98rus, Саня, _Boroda_, спасибо Вам огромное! запустил, пока вот 52 минуты еще считает:) anvg, сразу не заметил Ваш код, сейчас опробую на другом пк!
bmv98rus, Саня, _Boroda_, спасибо Вам огромное! запустил, пока вот 52 минуты еще считает:) anvg, сразу не заметил Ваш код, сейчас опробую на другом пк!rosko
anvg, космос! отработал (правда на другом пк) меньше чем за полминуты. Единственно, я не понял как Вы отбираете строки (только понял, что Вы задаете долю, которую взять)
anvg, космос! отработал (правда на другом пк) меньше чем за полминуты. Единственно, я не понял как Вы отбираете строки (только понял, что Вы задаете долю, которую взять)rosko
А интересно, сколько будет работать этот код [vba]
Код
Sub delete_rand() Dim i&, x&, last_row&, last_col& Application.ScreenUpdating = False Dim last_row As Long, last_col As Long ThisWorkbook.Worksheets(1).Activate last_row = Cells(Rows.Count, 1).End(xlUp).Row last_col = Cells(1, Columns.Count).End(xlToLeft).Column For i = 2 To last_row x = Int((17 - 1 + 1) * Rnd + 1) If x <> 7 And x <> 11 Then Range(Cells(i, 1), Cells(i, last_col)).Clear Next Range(Cells(2, 1), Cells(last_row, last_col)).Sort Key1:=Range("A2"), Order1:=xlAscending, Header:=xlNo, _ OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _ DataOption1:=xlSortNormal Application.ScreenUpdating = True End Sub
[/vba]
А интересно, сколько будет работать этот код [vba]
Код
Sub delete_rand() Dim i&, x&, last_row&, last_col& Application.ScreenUpdating = False Dim last_row As Long, last_col As Long ThisWorkbook.Worksheets(1).Activate last_row = Cells(Rows.Count, 1).End(xlUp).Row last_col = Cells(1, Columns.Count).End(xlToLeft).Column For i = 2 To last_row x = Int((17 - 1 + 1) * Rnd + 1) If x <> 7 And x <> 11 Then Range(Cells(i, 1), Cells(i, last_col)).Clear Next Range(Cells(2, 1), Cells(last_row, last_col)).Sort Key1:=Range("A2"), Order1:=xlAscending, Header:=xlNo, _ OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _ DataOption1:=xlSortNormal Application.ScreenUpdating = True End Sub