Страницы: 1
RSS
Удаление строк по условию
 
Добрый день, возникла идея уменьшить кол-во строк в таблице. (ежедневная выгрузка из базы данных - переделать выгрузку нет возможности)
Нашел простой макрос и чуточку доработал чтобы он искал только значения в одном столбце.
Но потребовалась еще 1 доработка.
если в D5 стоит ноль то строка удаляется.
Но мне необходимо еще одно условие прописать, чтобы D5 не удалялась т.к. в ячейке справа Е5 стоит значение больше нуля.
В принципе получается нужно удалять только те строки в которых значения D#+E#=0 (додумался пока писал пост)
Как прописать это условие в макрос? и можно ли его оптимизировать, ему приходится удалять примерно 1 700 строк из 15 000 и как я понял он их все в оперативку сначала собирает и когда соберет удаляет, Excel при этом зависает минут на 3-5.
Код
Sub УдалениеСтрокПоУсловию()
    Dim ra As Range, delra As Range, ТекстДляПоиска As String
    Application.ScreenUpdating = False    ' отключаем обновление экрана

    ТекстДляПоиска = "0"    ' удаляем строки с таким текстом

    ' перебираем все строки в используемом диапазоне листа
    For Each ra In Range("D2:D20").Cells
        ' если в строке найден искомый текст
        If Not ra.Find(ТекстДляПоиска, , xlValues, xlPart) Is Nothing Then
            ' добавляем строку в диапазон для удаления
            If delra Is Nothing Then Set delra = ra Else Set delra = Union(delra, ra)
        End If
    Next
    ' если подходящие строки найдены - удаляем их
    If Not delra Is Nothing Then delra.EntireRow.Delete
End Sub
 
Пока сделал скрытие строк, чтоб можно было проверить. Если всё в порядке, то замените на удаление.
Код
Sub delRows()
Dim arr, i&, lstr&
lstr = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lstr
    If Not IsNull(Range(Cells(i, 4), Cells(i, 5)).Text) Then Rows(i).EntireRow.Hidden = True
Next
End Sub
"..Сладку ягоду рвали вместе, горьку ягоду я одна."
 
Скрывало все строки, переделал на удаление, 2 строку не удаляет (по нумерации Excel)
если еще раз запустить макрос - 2 строка удаляется
Код
Sub delRows()
Dim arr, i&, lstr&
lstr = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lstr
    If Not IsNull(Range(Cells(i, 4), Cells(i, 5)).Text) Then Rows(i).EntireRow.Delete
Next
End Sub
 
Два варианта: 1) С первого листа переносит на 2 лист. 2) на 3 листе перезаписывает данные убирая лишнее!
"Все гениальное просто, а все простое гениально!!!"
 
вариант
Код
Sub Udalenie_00_strok()
Dim rr As Range, mS()
Application.ScreenUpdating = False
mS = Range("D2:E" & Cells(Rows.Count, 1).End(xlUp).Row).Value
For i = 1 To UBound(mS)
   If mS(i, 1) = 0 And mS(i, 2) = 0 Then ' или mS(i, 1) + mS(i, 2) = 0
      If rr Is Nothing Then
          Set rr = Cells(i + 1, 4)
      Else
          Set rr = Union(rr, Cells(i + 1, 4))
      End If
    End If
Next
rr.EntireRow.Delete
Application.ScreenUpdating = True
End Sub
Изменено: V - 30.08.2017 13:58:37
 
Код
Sub www()
    On Error Resume Next
    With [a1].CurrentRegion
        .AutoFilter 4, "0": .AutoFilter 5, "0"
        .Offset(1).SpecialCells(12).EntireRow.Delete
        .AutoFilter
    End With
End Sub
Я сам - дурнее всякого примера! ...
 
Цитата
venom51 написал:
2 строку не удаляет
Удалять нужно при обратном цикле, т.е.
For i = lstr to 2
"..Сладку ягоду рвали вместе, горьку ягоду я одна."
 
Владимир,  step -1 упустил. ;)
 
Вот вы разошлись то, я теперь не знаю из чего выбрать, все тестить приходиться на скорость обработки. Взял пока вариант от  V
 
Вариант от kuklp  лучше - фильтр, нет цикла.
"..Сладку ягоду рвали вместе, горьку ягоду я одна."
 
Владимир, только вот по времени выполнения одно и тоже получается почему то) на боевой таблице всмысле) до секунд не засекаю) чисто на глаз)  
Изменено: venom51 - 30.08.2017 14:29:39
 
venom51, У вас таблица боевая с формулами или только значения?
"Все гениальное просто, а все простое гениально!!!"
 
Быстрей наверное, будет так:
Код
Sub www()
    Dim i&, a, n&, j&
    With [a1].CurrentRegion
        a = .Value
        .ClearContents
    End With
    n = 1
    For i = 2 To UBound(a)
        If a(i, 4) <> 0 Or a(i, 5) <> 0 Then
            n = n + 1
            For j = 1 To UBound(a, 2)
                a(n, j) = a(i, j)
            Next
        End If
    Next
    [a1].Resize(n, UBound(a, 2)) = a
End Sub
Я сам - дурнее всякого примера! ...
 
Nordheim,с формулами
 
kuklp, вот это было нереально быстро после всех моих предыдущих проб) формулы стали значениями) в принципе не критично и возможно даже лучше) размер файла в 3 раза меньше стал)
 
Если с формулами, то вариант с перебором в массивах не подойдет, только если нет разницы формулы в таблице или посчитанные значения.
Попробуйте в процедуре где удаляются строки
Это в начало:
Код
 Application.Calculation = xlCalculationManual
это в конец
Код
 Application.Calculation = xlCalculationAutomatic
м.б. побыстрее будет.
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
venom51 написал:
kuklp , вот это было нереально быстро
Я вам аналогичный макрос в файле прикрепил :)
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim, мне было сложно его под основную таблицу переделать(
Изменено: venom51 - 30.08.2017 14:56:49
 
Цитата
venom51 написал:
формулы стали значениями
можно сделать так, чтоб формулы остались. В один массив взять формулы, а во второй значения. И на основании значений двигать формулы. А если в столбцах 4 и 5 значения, то надо заменить одно слово в макросе и будет счастье.
Я сам - дурнее всякого примера! ...
 
Тут только Лист3 нужно заменить на Sheets(имя листа) а переделывать ничего не нужно!
Код
Sub test1()
Dim arr(), iarr(), lrow&, lcolumn&
Dim i&, j&, icount&, x&
With Лист3
    lrow = .Cells(.Rows.Count, 1).End(xlUp).Row
    lcolumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
    arr = .Range(.[a2], .Cells(lrow, lcolumn)).Value
    .Range(.[a2], .Cells(lrow, lcolumn)).ClearContents
    For i = 1 To UBound(arr)
        If arr(i, 4) <> 0 Or arr(i, 5) <> 0 Then icount = icount + 1
    Next i
    ReDim iarr(1 To icount, 1 To UBound(arr, 2))
    For i = 1 To UBound(arr)
        If arr(i, 4) <> 0 Or arr(i, 5) <> 0 Then
            x = x + 1
            For j = 1 To UBound(arr, 2)
                iarr(x, j) = arr(i, j)
            Next j
        End If
    Next i
    .[a2].Resize(UBound(iarr), UBound(iarr, 2)) = iarr
End With
End Sub
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim,ну столбцы у меня на основе не 4 и 5 как в примере, а 7 и 8 )
спасибо за помощь
Изменено: venom51 - 30.08.2017 15:26:48
 
Так это в  любой процедуре, здесь представленной, нужно менять 4 и 5 на 7 и 8. Кроме макроса из сообщения №5, там нужно менять диапазон просмотра.
"Все гениальное просто, а все простое гениально!!!"
Страницы: 1
Наверх