Удаление пустых строк с помощью кода VBA из всего задействованного диапазона рабочего листа Excel и из отдельного заданного диапазона.
Главный секрет удаления пустых строк кодом VBA Excel – это построчный просмотр диапазона или отдельного столбца снизу вверх, что исключает возможность при удалении найденных пустых строк получить бесконечный цикл и зависание программы.
Удаление пустых строк в используемом диапазоне
Рассмотрим удаление пустых строк из всего используемого диапазона на рабочем листе. Это может быть как таблица, так и любые наборы данных и произвольные записи, внутри которых присутствуют пустые строки, от которых надо избавиться.
Определить границы используемого диапазона на рабочем листе из кода VBA Excel нам поможет последняя ячейка используемого диапазона: Cells.SpecialCells(xlLastCell)
.
Самый простой код удаления пустых строк
Сначала определяем номер строки последней ячейки задействованного на рабочем листе диапазона. Затем, с этой строки начинаем построчный просмотр используемого диапазона снизу вверх с поиском и удалением пустых строк.
Пример кода VBA Excel для активного листа:
Sub Primer1() Dim n As Long, i As Long ‘Определяем номер строки последней ячейки ‘используемого диапазона на рабочем листе n = Cells.SpecialCells(xlLastCell).Row ‘Ищем и удаляем пустые строки For i = n To 1 Step —1 If Rows(i).Text = «» Then Rows(i).Delete Next End Sub |
То же самое, но с указанием книги и рабочего листа:
Sub Primer2() Dim n As Long, i As Long With ThisWorkbook.Worksheets(«Лист1») n = .Cells.SpecialCells(xlLastCell).Row For i = n To 1 Step —1 If .Rows(i).Text = «» Then .Rows(i).Delete Next End With End Sub |
Программа определения времени выполнения макроса показала, что этот код отработал в диапазоне из 3000 строк за 17,5 секунд.
Улучшенный код удаления пустых строк
Предыдущий код VBA Excel анализирует на наличие текста каждую строку по всей длине в пределах рабочего листа. Эта процедура проверяет каждую строку по длине только в переделах используемого диапазона:
Sub Primer3() Dim n As Long, i As Long, myRange As Range ‘Присваиваем объектной переменной ссылку на диапазон от первой ячейки ‘рабочего листа до последней ячейки используемого диапазона Set myRange = Range(Range(«A1»), Cells.SpecialCells(xlLastCell)) With myRange n = .Rows.Count For i = n To 1 Step —1 If .Rows(i).Text = «» Then .Rows(i).Delete Next End With End Sub |
Программа определения времени выполнения макроса показала, что этот код отработал в диапазоне из 3000 строк за 13,3 секунды.
Удаление строк по пустым ячейкам
Иногда может появиться необходимость удалить не только полностью пустые строки, но и строки с пустыми ячейками в определенном столбце. Тогда следует действовать так:
Sub Primer4() Dim n As Long, i As Long n = Cells.SpecialCells(xlLastCell).Row For i = n To 1 Step —1 If Cells(i, 1).Text = «» Then Rows(i).Delete Next End Sub |
или так:
Sub Primer5() Dim n As Long, i As Long, myRange As Range Set myRange = Range(Range(«A1»), Cells.SpecialCells(xlLastCell)) With myRange n = .Rows.Count For i = n To 1 Step —1 If .Cells(i, 1).Text = «» Then .Rows(i).Delete Next End With End Sub |
В этих примерах поиск пустой ячейки производится в первом столбце: Cells(i, 1)
.
Удаление пустых строк в заданном диапазоне
Процедуры VBA Excel для удаления пустых строк из заданного диапазона рассмотрим на примере объекта Selection
, который можно заменить на любой диапазон, указанный явно.
Удаление полностью пустых строк в пределах заданного диапазона:
Sub Primer6() Dim n As Long, i As Long With Selection n = .Rows.Count For i = n To 1 Step —1 If .Rows(i).Text = «» Then .Rows(i).Delete Next End With End Sub |
Удаление строк по пустым ячейкам в одном из столбцов:
Sub Primer7() Dim n As Long, i As Long With Selection n = .Rows.Count For i = n To 1 Step —1 If .Cells(i, 1).Text = «» Then .Rows(i).Delete Next End With End Sub |
hk1209 Пользователь Сообщений: 271 |
#1 30.01.2014 11:39:19 всем доброго времени суток
спасибо за потраченное драгоценное время Изменено: hk1209 — 30.01.2014 20:05:32 |
||
Hugo Пользователь Сообщений: 23253 |
Чтож Вы с строкой сравниваете дату? Или там тоже строка, а не дата? |
hk1209 Пользователь Сообщений: 271 |
|
wowick Пользователь Сообщений: 972 |
А сравниваете вы ее с ТЕКСТОМ «20.11.2013»… В экселе, как и во-многих других средах программирования в кавычках подразумевает текстовый формат. Если автоматизировать бардак, то получится автоматизированный бардак. |
Sanja Пользователь Сообщений: 14838 |
#5 30.01.2014 11:51:07 Попробуйте так
Согласие есть продукт при полном непротивлении сторон. |
||
Hugo Пользователь Сообщений: 23253 |
То что там дата — это ещё не факт. Видали мы всяких дат… Пока не докажете — не поверю |
hk1209 Пользователь Сообщений: 271 |
#7 30.01.2014 12:32:37 Sanja спасибо за подсказку
долго выполняется |
||
Sanja Пользователь Сообщений: 14838 |
#8 30.01.2014 12:44:02 Для ускорения выполнения кода отключите автоматический пересчет:
в конце процедуры включить:
так определяется
номер последней строки с данными в 9-м столбце:
Изменено: Sanja — 30.01.2014 12:45:13 Согласие есть продукт при полном непротивлении сторон. |
||||||
Hugo Пользователь Сообщений: 23253 |
4. Обрабатывать массивы, а не ячейки — на листе только удалять строки, да и тут можно это делать один раз сразу с группой. P.S.Упустил — Dim rw As Date — это ошибка! Изменено: Hugo — 30.01.2014 12:57:32 |
hk1209 Пользователь Сообщений: 271 |
#10 30.01.2014 13:52:19 Sanja & Hugo спасибо за подсказку и потраченное драгоценное время
Знаю что там не правильно, но не могу понять где именно Изменено: hk1209 — 30.01.2014 20:06:26 |
||
The_Prist Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
#11 30.01.2014 14:02:46 Cells(Rows.Count, 9).End(xlUp).Row < CDate(«20.11.2013») Hugo совсем иное советовал..
И уже в цикле:
С массивами чуть сложнее в понимании, но на Вашем примере было бы так:
P.S. И оформляйте коды тегами. Значок «<…>» среди кнопок вверху при создании сообщения. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
||||||
Hugo Пользователь Сообщений: 23253 |
Супербыстрое удаление строк от ZVI есть тут: http://www.sql.ru/forum/actualthread.aspx?tid=722758 Можно использовать и в этой задаче. |
hk1209 Пользователь Сообщений: 271 |
#13 30.01.2014 14:24:29 The_Prist спасибо за потраченное драгоценное время и советы (включая код) |
In this Article
- Delete Entire Row or Column
- Delete Multiple Rows or Columns
- Delete Blank / Empty Rows
- Delete Row if Cell is Blank
- Delete Row Based on Cell Value
- More Delete Row and Column Examples
- Delete Duplicate Rows
- Delete Table Rows
- Delete Filtered Rows
- Delete Rows in Range
- Delete Selected Rows
- Delete Last Row
- Delete Columns by Number
This tutorial will demonstrate different ways to delete rows and columns in Excel using VBA.
Delete Entire Row or Column
To delete an entire row in VBA use this line of code:
Rows(1).Delete
Notice we use the Delete method to delete a row.
Instead of referencing the Rows Object, you can reference rows based on their Range Object with EntireRow:
Range("a1").EntireRow.Delete
Similarly to delete an entire column, use these lines of code:
Columns(1).Delete
Range("a1").EntireColumn.Delete
Delete Multiple Rows or Columns
Using the same logic, you can also delete multiple rows at once:
Rows("1:3").Delete
or columns:
Columns("A:C").Delete
Notice here we reference the specific row and column numbers / letters surrounded by quotations.
Of course, you can also reference the EntireRow of a range:
Range("a1:a10").EntireRow.Delete
Note: The examples below only demonstrate deleting rows, however as you can see above, the syntax is virtually identically to delete columns.
Delete Blank / Empty Rows
This example will delete a row if the entire row is blank:
Sub DeleteRows_EntireRowBlank()
Dim cell As Range
For Each cell In Range("b2:b20")
If Application.WorksheetFunction.CountA(cell.EntireRow) = 0 Then
cell.EntireRow.Delete
End If
Next cell
End Sub
It makes use of the Excel worksheet function: COUNTA.
Delete Row if Cell is Blank
This will delete a row if specific column in that row is blank (in this case column B):
Range("b3:b20").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Delete Row Based on Cell Value
This will loop through a range, and delete rows if a certain cell value in that row says “delete”.
Sub DeleteRowswithSpecificValue()
Dim cell As Range
For Each cell In Range("b2:b20")
If cell.Value = "delete" Then
cell.EntireRow.Delete
End If
Next cell
End Sub
More Delete Row and Column Examples
VBA Coding Made Easy
Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!
Learn More
Delete Duplicate Rows
This code will delete all duplicate rows in a range:
Range("b2:c100").RemoveDuplicates Columns:=2
Notice we set Columns:=2. This tells VBA to check both the first two columns of data when considering if rows are duplicates. A duplicate is only found when both columns have duplicate values.
If we had set this to 1, only the first row would’ve been checked for duplicate values.
Delete Table Rows
This code will delete the second row in a Table by referencing ListObjects.
ThisWorkbook.Sheets("Sheet1").ListObjects("list1").ListRows(2).Delete
Delete Filtered Rows
To delete only rows that are visible after filtering:
Range("b3:b20").SpecialCells(xlCellTypeVisible).EntireRow.Delete
VBA Programming | Code Generator does work for you!
Delete Rows in Range
This code will delete all rows in range:
Range("a1:a10").EntireRow.Delete
Delete Selected Rows
This code will delete all selected rows:
Selection.EntireRow.Delete
Delete Last Row
This will delete the last used row in column B:
Cells(Rows.Count, 2).End(xlUp).EntireRow.Delete
By changing 2 to 1, you can delete the last used row in column A, etc.:
Cells(Rows.Count, 1).End(xlUp).EntireRow.Delete
Delete Columns by Number
To delete a column by it’s number, use a code like this:
Columns (2).Delete
First, let me say categorically that there is nothing wrong with loops — they certainly have their place!
Recently we were presented with the below situation:
400000 | Smith, John| 2.4 | 5.66| =C1+D1
400001 | Q, Suzy | 4.6 | 5.47| =C2+D2
400002 | Schmoe, Joe| 3.8 | 0.14| =C3+D3
Blank | | | | #VALUE
Blank | | | | #VALUE
The OP wanted to delete rows where Column A is blank, but there is a value in Column E.
I suggest that this is an example where we could make use of SpecialCells and a temporary Error Column to identify the rows to be deleted.
Consider that you might add a column H to try and identify those rows; in that row you could use a formula like below:
=IF(AND(A:A="",E:E<>""),"DELETE THIS ROW","LEAVE THIS ROW")
now, it is possible get that formula to put an error in the rows where I test returns True. The reason we would do this is a feature of Excel called SpecialCells.
In Excel select any empty cell, and in the formula bar type
=NA()
Next, hit F5 or CTRL+G (Go to… on the Edit menu) then click the Special button to show the SpecialCells dialog.
In that dialog, click the radio next to ‘Formulas’ and underneath, clear the checkboxes so that only Errors is selected. Now click OK
Excel should have selected all the cells in the worksheet with an Error (#N/A) in them.
The code below takes advantage of this trick by creating a formula in column H that will put an #N/A in all the rows you want to delete, then calling SpecialCells to find the rows, and clear (delete) them…
Sub clearCells()
'
Dim sFormula As String
'
' this formula put's an error if the test returns true,
' so we can use SpecialCells function to highlight the
' rows to be deleted!
Create a formula that will return #NA when the formula returns TRUE
sFormula = "=IF(AND(A:A="""",E:E<>""""),NA(),"""")"
Put that formula in Column H, to find the rows that are to be deleted…
Range("H5:H" & Range("E65536").End(xlUp).Row).Formula = sFormula
Now use SpecialCells to highlight the rows to be deleted:
Range("H5:H" & Range("E65536").End(xlUp).Row).SpecialCells(xlCellTypeFormulas, xlErrors).entirerow.select
This line of code would highlight just Column A by using OFFSET in case instead of deleting the entire row, you wanted to put some text in, or clear it
Range("H5:H" & Range("E65536").End(xlUp).Row).SpecialCells(xlCellTypeFormulas, xlErrors).Offset(0, -7).select
and the below line of code will delete thhe entire row because we can
Range("H5:H" & Range("E65536").End(xlUp).Row).SpecialCells(xlCellTypeFormulas, xlErrors).EntireRow.Delete shift:=xlup
' clean up the formula
Range("H5:H" & Range("E65536").End(xlUp).Row).Clear
'
End Sub
BTW, it’s also possible WITH A LOOP if you really want one
One more thing, before Excel 2010 there was a limit of 8192 rows (I think because this feature went all the way back to 8-bit versions of Excel maybe)
The VBA legend Ron de Bruin (on whose website I first picked up this technique, among others) has something to say about this
Philip
Добрый день.
Подскажите пожалуйста, задача следующая:
Необходимо пройтись по всем рядам таблицы.
Если в колонке А стоит «-» и в колонке В стоит «-«, то данную строку необходимо удалить.
Можно ли реализовать данную задачу через макросы?
Спасибо.
7 ответов
37K
06 марта 2013 года
freets
97 / / 15.10.2010
Конечно можно. Ставишь на запись макрос, выполняешь какие нужно действия(удаление строки), останавливаешь запись. Открываешь Макросы->Изменить и смотришь какой код получился.
Будет примерно так:
Код:
Rows(«1:1»).Select //выделяем первую строку
Selection.Delete Shift:=xlUp //удаляем со сдвигом вверх
только добавь нужное условие и всё.
88K
06 марта 2013 года
Vanderlog
4 / / 06.03.2013
А как правильно организовать перебор всех элементов, и, собственно, если не трудно то условие скажите как задать?
37K
06 марта 2013 года
freets
97 / / 15.10.2010
Код:
Sub Macros()
Dim rw As Long
For rw = 1 To 100
If Cells(rw, «A»).Value = «-« And Cells(rw, «B»).Value = «-« Then
Rows(rw & «:» & rw).Delete Shift:=xlUp
End If
Next rw
End Sub
88K
06 марта 2013 года
Vanderlog
4 / / 06.03.2013
Работает, но почему-то за один проход не справляется. Причем строк меньше 100. 10 строк удаляет за 4 прохода. Что может останавливать скрипт?
275
06 марта 2013 года
pashulka
985 / / 19.09.2004
Вообще-то, при удалении строки необходимо уменьшать счётчик, ибо в противном случае могут остаться строки, содержащие «-» (разумеется, если «-» содержатся в смежных ячейках) или начать удаление снизу вверх, т.е.
Код:
Private Sub Test()
Application.ScreenUpdating = False
Dim rw&
For rw = 100 To 1 Step -1
If Cells(rw, 1) = «-» And Cells(rw, 2) = «-» Then Rows(rw).Delete
Next
Application.ScreenUpdating = True
End Sub
88K
06 марта 2013 года
Vanderlog
4 / / 06.03.2013
Все верно, при переборе снизу вверх работает корректно. Спасибо всем!
275
22 марта 2013 года
pashulka
985 / / 19.09.2004
Чуть не забыл если в дальнейшем потребуется проверять наличие «-» в большем количестве столбцов, чем сейчас, то вместо увеличения And или дополнительного цикла по столбцам, можно программно воспользоваться стандартной функцией рабочего листа =СЧЁТЕСЛИ() (см. листинг)
Код:
Private Sub Test2()
Dim rw&, ws As Worksheet
Set ws = ActiveSheet
With Application
.ScreenUpdating = False
For rw = 100 To 1 Step -1
If .CountIf(ws.Cells(rw, «A»).Resize(, 2), «-«) = 2 Then ws.Rows(rw).Delete
Next
.ScreenUpdating = True
End With
End Sub
P.S. Разумеется номер последней заполненной строки мы можем определять программно.