RAN, ох уж мне эти мяу-макросы, покоя не дают, будоражат ум =) Как работает строка ниже? Согласно моему шаблону, если сказал "если", будь добр использовать логическое сравнение. Шаблон рвать будем?))
Для офиса младше 2007 [a65535] заменить на [A1048576].
SkyPro, точно надо увеличивать количество строк для более ранних офисов?
RAN, ох уж мне эти мяу-макросы, покоя не дают, будоражат ум =) Как работает строка ниже? Согласно моему шаблону, если сказал "если", будь добр использовать логическое сравнение. Шаблон рвать будем?))
Len("текст") даст либо положительное значение, что ВБА воспримет как True, либо 0, что воспримется, как False. Та же запись может выглядеть вот так: [vba]
Len("текст") даст либо положительное значение, что ВБА воспримет как True, либо 0, что воспримется, как False. Та же запись может выглядеть вот так: [vba]
SkyPro, пресвятая булева алгебра, из этого можно сделать целую кучу полезных выводов и применений...
Сделаем, как бы по школьному не звучало, проверочную работу.
[vba]
Код
Sub Autumn()
Dim X As Boolean
X = True: MsgBox X 'Shows "True" X = False: MsgBox X 'Shows "False" X = -1: MsgBox X 'Shows "True" X = 0: MsgBox X 'Shows "False" X = 1: MsgBox X 'Shows "True"
X = True: MsgBox X + X + X 'Shows -3
End Sub
[/vba] Спасибо, теперь понял, как работает решение RAN и Ваше. Кроме одного момента - Union?
SkyPro, пресвятая булева алгебра, из этого можно сделать целую кучу полезных выводов и применений...
Сделаем, как бы по школьному не звучало, проверочную работу.
[vba]
Код
Sub Autumn()
Dim X As Boolean
X = True: MsgBox X 'Shows "True" X = False: MsgBox X 'Shows "False" X = -1: MsgBox X 'Shows "True" X = 0: MsgBox X 'Shows "False" X = 1: MsgBox X 'Shows "True"
X = True: MsgBox X + X + X 'Shows -3
End Sub
[/vba] Спасибо, теперь понял, как работает решение RAN и Ваше. Кроме одного момента - Union?Rioran
Роман, Москва, voronov_rv@mail.ru Яндекс-Деньги: 41001312674279
Сообщение отредактировал Rioran - Среда, 25.06.2014, 13:51
Забирает в массив весь столбец (до последней заполненной ячейки). Сделано для ускорения на больших диапазонах. Проходит по всему массиву и собирает все пустые ячейки в один диапазон, после чего "одним выстрелом" удаляет.
Забирает в массив весь столбец (до последней заполненной ячейки). Сделано для ускорения на больших диапазонах. Проходит по всему массиву и собирает все пустые ячейки в один диапазон, после чего "одним выстрелом" удаляет.SkyPro
ограничение для Union по кол-ву несвязных диапазонов - то же самое, что и для SpecialCells. кстати, оно достаточно большое. 8192, если быть точным.
модифицировать код для SpecialCells с учетом ограничения не так уж и сложно. в любом случае, это будет многократно быстрее, чем тысячи Union'ов и уж, тем более, построчного удаления.
ограничение для Union по кол-ву несвязных диапазонов - то же самое, что и для SpecialCells. кстати, оно достаточно большое. 8192, если быть точным.
модифицировать код для SpecialCells с учетом ограничения не так уж и сложно. в любом случае, это будет многократно быстрее, чем тысячи Union'ов и уж, тем более, построчного удаления.ikki
помощь по Excel и VBA ikki@fxmail.ru, icq 592842413, skype alex.ikki
Каждый раз создавался столбец из 5000 ячеек, где каждая вторая ячейка пустая, остальные с единичками.
Лучший код предложил Ikki - уработал всё за секунду.
Код SkyPro отработал за 9 секунд, но отключение обновления экрана никак не отразилось на производительности в лучшую сторону.
Мой код из поста № 7, вдохновлённый некоторыми мыслями Ikki, отработал за 16 секунд, но "убийство" обновлений экрана сократило работу до 2-х секунд.
Пробовал запустить код SkyPro на 20'000 ячеек с половиной к удалению, но почувствовал себя так, словно запустил бесконечный цикл =) Прервал операцию. Интересно, почему так произошло... Если Union ограничен, то должно было выдать ошибку. Можете тоже потестить коды, генератор ячеек ниже:
[vba]
Код
Dim X As Long
For X = 1 To 5000 If X * 0.5 <> Int(X * 0.5) Then Cells(X, 1).Value = 1 Else Cells(X, 1).Value = "" Next X
End Sub
[/vba]
Провёл "краш-тест" предложенных в теме кодов.
Каждый раз создавался столбец из 5000 ячеек, где каждая вторая ячейка пустая, остальные с единичками.
Лучший код предложил Ikki - уработал всё за секунду.
Код SkyPro отработал за 9 секунд, но отключение обновления экрана никак не отразилось на производительности в лучшую сторону.
Мой код из поста № 7, вдохновлённый некоторыми мыслями Ikki, отработал за 16 секунд, но "убийство" обновлений экрана сократило работу до 2-х секунд.
Пробовал запустить код SkyPro на 20'000 ячеек с половиной к удалению, но почувствовал себя так, словно запустил бесконечный цикл =) Прервал операцию. Интересно, почему так произошло... Если Union ограничен, то должно было выдать ошибку. Можете тоже потестить коды, генератор ячеек ниже:
[vba]
Код
Dim X As Long
For X = 1 To 5000 If X * 0.5 <> Int(X * 0.5) Then Cells(X, 1).Value = 1 Else Cells(X, 1).Value = "" Next X
Sub ertert() On Error Resume Next Application.ScreenUpdating = False With Range("A1", Cells(Rows.Count, 1).End(xlUp)) .Sort Key1:=.Cells(1), Order1:=xlAscending .SpecialCells(4).EntireRow.Delete .Parent.UsedRange End With Application.ScreenUpdating = True End Sub
Sub ertert() On Error Resume Next Application.ScreenUpdating = False With Range("A1", Cells(Rows.Count, 1).End(xlUp)) .Sort Key1:=.Cells(1), Order1:=xlAscending .SpecialCells(4).EntireRow.Delete .Parent.UsedRange End With Application.ScreenUpdating = True End Sub
обещанная модификация макроса с учетом: - ограничений по кол-ву несвязных диапазонов; - "подлого" свойства SpecialCells, упомянутого Алексеем (Alex_ST).
[vba]
Код
Sub delrow() Const nBlock = 10 On Error Resume Next With Sheets(1) lr = .Cells(.Rows.Count, 1).End(xlUp).Row: i = lr + 1: n = nBlock Do While i > 2 If i > nBlock + 1 Then i = i - nBlock Else n = i - 2: i = 2 If n = 1 Then If Len(.Cells(i, 1)) = 0 Then .Rows(i).Delete Else .Cells(i, 1).Resize(n).SpecialCells(4).EntireRow.Delete End If Loop End With End Sub
[/vba]
значение nBlock нужно изменить. с учетом худшего варианта (пустые ячейки располагаются через одну) - не более 16384
обещанная модификация макроса с учетом: - ограничений по кол-ву несвязных диапазонов; - "подлого" свойства SpecialCells, упомянутого Алексеем (Alex_ST).
[vba]
Код
Sub delrow() Const nBlock = 10 On Error Resume Next With Sheets(1) lr = .Cells(.Rows.Count, 1).End(xlUp).Row: i = lr + 1: n = nBlock Do While i > 2 If i > nBlock + 1 Then i = i - nBlock Else n = i - 2: i = 2 If n = 1 Then If Len(.Cells(i, 1)) = 0 Then .Rows(i).Delete Else .Cells(i, 1).Resize(n).SpecialCells(4).EntireRow.Delete End If Loop End With End Sub
[/vba]
значение nBlock нужно изменить. с учетом худшего варианта (пустые ячейки располагаются через одну) - не более 16384ikki
помощь по Excel и VBA ikki@fxmail.ru, icq 592842413, skype alex.ikki
удаляет строки (в соответствии с постановкой задачи в текущей теме). блоками. в каждом блоке сначала проверяет - не равен ли его размер единице и тогда просто проверяет значение в ячейке если больше единицы - в текущем блоке пользуемся SpecialCells(4) и, если пустые ячейки найдутся, удаляем для них строки целиком если не найдутся - сработает обработка ошибок и мы просто перейдём к следующему блоку.
блоки перебираются снизу-вверх. размер блока - чем больше, тем лучше. но с учетом ограничения. поэтому 16384 - самое безопасное значение на любых таблицах. на сильно разреженных или, наоборот, плотно заполненных таблицах можно сделать побольше. но, во-первых, это довольно опасно. а, во-вторых, имеет смысл только для таблиц на сотни тысяч строк.
удаляет строки (в соответствии с постановкой задачи в текущей теме). блоками. в каждом блоке сначала проверяет - не равен ли его размер единице и тогда просто проверяет значение в ячейке если больше единицы - в текущем блоке пользуемся SpecialCells(4) и, если пустые ячейки найдутся, удаляем для них строки целиком если не найдутся - сработает обработка ошибок и мы просто перейдём к следующему блоку.
блоки перебираются снизу-вверх. размер блока - чем больше, тем лучше. но с учетом ограничения. поэтому 16384 - самое безопасное значение на любых таблицах. на сильно разреженных или, наоборот, плотно заполненных таблицах можно сделать побольше. но, во-первых, это довольно опасно. а, во-вторых, имеет смысл только для таблиц на сотни тысяч строк.ikki
помощь по Excel и VBA ikki@fxmail.ru, icq 592842413, skype alex.ikki
Sub deleteEmptyRows() Dim x, i&, delRa As Range x = Range("A1:A" & [a65535].End(xlUp).Row).Value For i = 1 To UBound(x) If x(i, 1) = "" Then If delRa Is Nothing Then Set delRa = Cells(i, 1) Else Set delRa = Union(Cells(i, 1), delRa) End If End If Next If Not delRa Is Nothing Then delRa.EntireRow.Delete End Sub
[/vba]
То что я искал.
SkyPro, отличный вариант, универсальный...
[vba]
Код
Sub deleteEmptyRows() Dim x, i&, delRa As Range x = Range("A1:A" & [a65535].End(xlUp).Row).Value For i = 1 To UBound(x) If x(i, 1) = "" Then If delRa Is Nothing Then Set delRa = Cells(i, 1) Else Set delRa = Union(Cells(i, 1), delRa) End If End If Next If Not delRa Is Nothing Then delRa.EntireRow.Delete End Sub
Вечер добрый форумчане! Хотел адаптировать код из сообщения №20 под свои нужды, но не понял, что происходит в цикле: [vba]
Код
For i = 1 To UBound(x) If x(i, 1) = "" Then If delRa Is Nothing Then Set delRa = Cells(i, 1) Else Set delRa = Union(Cells(i, 1), delRa) End If End If Next If Not delRa Is Nothing Then delRa.EntireRow.Delete End Sub
[/vba] А именно - delRa ведь пустой и после первого прохождения цикла он заполняется диапазоном из "x" - ведь так? а потом, что происходит после Else? Union как он срабатывает? почему не записать сразу после Then [vba]
Код
Set delRa = Union(Cells(i, 1), Cells(i, 1))
[/vba] Разве"Union(Cells(i, 1), delRa)" не равно "Union(Cells(i, 1), Cells(i, 1))"
Вечер добрый форумчане! Хотел адаптировать код из сообщения №20 под свои нужды, но не понял, что происходит в цикле: [vba]
Код
For i = 1 To UBound(x) If x(i, 1) = "" Then If delRa Is Nothing Then Set delRa = Cells(i, 1) Else Set delRa = Union(Cells(i, 1), delRa) End If End If Next If Not delRa Is Nothing Then delRa.EntireRow.Delete End Sub
[/vba] А именно - delRa ведь пустой и после первого прохождения цикла он заполняется диапазоном из "x" - ведь так? а потом, что происходит после Else? Union как он срабатывает? почему не записать сразу после Then [vba]
Код
Set delRa = Union(Cells(i, 1), Cells(i, 1))
[/vba] Разве"Union(Cells(i, 1), delRa)" не равно "Union(Cells(i, 1), Cells(i, 1))"Railord
Nil novi sub luna, так что - век живи, век учись!)
Сообщение отредактировал Railord - Вторник, 28.10.2014, 22:46