У меня есть макрос для удаления пустых ячеек в каждой строке и смещения следующей ячейки влево. Код не показывает никаких ошибок, но ничего не делает.
Поскольку количество столбцов может меняться от строки к строке, я определил последнюю строку внутри цикла For Each.
Помощь с исправлением принята с благодарностью.
Sub RemoveBlankCells()
Dim rng As Range
Dim row As Range
Dim cell As Range
Dim lastCol As Long
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("ABC")
For Each row In ws.Rows
lastCol = ws.Cells(1, Columns.Count).End(xlToLeft).Column
Set rng = ws.Cells(1, lastCol)
For Each cell In rng.Cells
If cell.Value = "" Then
cell.Delete Shift:=xlToLeft
End If
Next cell
Next row
End Sub
r.Clear
на r.Delete Shift:=xlToLeft
и, возможно, еще какие-то адаптации, потому что он ищет формулы, а не пустые ячейки.
Спасибо @DarrenBartrup-Cook - это также объясняет плохую производительность. У вас есть рекомендация вместо For Each
?
Спасибо @Excellor - к сожалению, не с ws.UsedRange.Cells.SpecialCells(xlCellTypeBlanks)
- раньше пробовал UsedRange
, но безуспешно.
Попробуйте этот код. Он ограничивает его только заполненными строками - при условии, что в столбце A всегда что-то есть.
Public Sub RemoveBlankCells()
With ThisWorkbook.Worksheets("ABC")
'Assume there's always something in column 1.
Dim LastRow As Long
LastRow = .Cells(.Rows.Count, 1).End(xlUp).row
'Set reference to column A of the range to work on.
Dim SearchRange As Range
Set SearchRange = .Range(.Cells(1, 1), .Cells(LastRow, 1))
Dim rRow As Range
For Each rRow In SearchRange.EntireRow
'Find the last column number in the row.
Dim LastColumn As Long
LastColumn = .Cells(rRow.row, .Columns.Count).End(xlToLeft).Column
'Work backwards deleting cells - if you delete a cell in column 3 and move to column 4...
'column 4 has now become column 3 and that cell isn't checked.
Dim Counter As Long
For Counter = LastColumn To 1 Step -1
If .Cells(rRow.row, Counter) = "" Then .Cells(rRow.row, Counter).Delete Shift:=xlToLeft
Next Counter
Next rRow
End With
End Sub
Дальнейшее чтение:
With...End With заявление
Еще раз спасибо @Даррен Бартруп-Кук. Кажется, он идет прямо от If .Cells(rRow.row, Counter) = "" Then
к Next Counter
, т. е. пропускает .Cells(rRow.row, Counter).Delete Shift:=xlToLeft
Вы уверены, что эти ячейки пусты и не содержат пробелов? Добавьте Debug.Print .Cells(rRow.Row, Counter).Address & ": " & Len(.Cells(rRow.Row, Counter))
перед строкой IF
— будет напечатан адрес ячейки и количество символов (длина) в ячейке.
Спасибо - вот и все! 😳Пространства в клетках! Огромное вам спасибо - вы избавили меня от большого разочарования! 🙏🙏🙏
Вы можете обновить проверку в операторе IF на Trim(.Cells(rRow.Row, Counter))
, чтобы удалить все начальные и конечные пробелы.
Я добавил обрезку, чтобы решить проблему с пробелами: Dim cell As Range For Each cell In ActiveSheet.UsedRange.SpecialCells(xlCellTypeConstants) cell = WorksheetFunction.Trim(cell) Next cell
Этот код использует ActiveSheet.UsedRange. Собирает все пустые ячейки, а затем удаляет и сдвигает влево оставшиеся.
Sub delete_cells()
Dim todel As Range, cel as Range '*
For Each cel In ActiveSheet.UsedRange
If Len(cel) = 0 Then
If todel Is Nothing Then
Set todel = cel
Else
Set todel = Union(todel, cel)
End If
End If
Next cel
If Not todel is Nothing Then todel.Delete xlToLeft '*
End Sub
* по состоянию на VBasic2008 с комментарием
Улучшайтесь с помощью Dim todel As Range, cel As Range
и If Not todel Is Nothing Then todel.Delete xlShiftToLeft
.
Основной
Sub RemoveBlankCells()
Dim rg As Range
With ThisWorkbook.Sheets("ABC").Range("A1").CurrentRegion
Set rg = .Resize(.Rows.Count - 1).Offset(1) ' exclude headers
End With
RemoveRowBlanks rg
End Sub
Помощь
Sub RemoveRowBlanks(ByVal rg As Range)
If rg Is Nothing Then Exit Sub
Dim RowsCount As Long: RowsCount = rg.Rows.Count
Dim ColumnsCount As Long: ColumnsCount = rg.Columns.Count
Dim Data() As Variant:
If RowsCount + ColumnsCount = 2 Then
ReDim Data(1 To 1, 1 To 1): Data(1, 1) = rg.Value
Else
Data = rg.Value
End If
Dim Row As Long, sCol As Long, dCol As Long, IsNotSameColumn As Boolean
For Row = 1 To RowsCount
dCol = 0
IsNotSameColumn = False
For sCol = 1 To ColumnsCount
If Len(CStr(Data(Row, sCol))) > 0 Then
dCol = dCol + 1
If Not IsNotSameColumn Then
If dCol < sCol Then IsNotSameColumn = True
End If
If IsNotSameColumn Then
Data(Row, dCol) = Data(Row, sCol)
Data(Row, sCol) = Empty
End If
End If
Next sCol
Next Row
rg.Value = Data
End Sub
Попробуйте также этот компактный фрагмент кода. Это быстро и не требует итераций:
Sub testDeletEBlankCellsSlideLeft()
Dim rng As Range: Set rng = ActiveSheet.UsedRange
On Error Resume Next 'for the case of no any blank cells in sheet used range...
rng.SpecialCells(xlCellTypeBlanks).Delete xlToLeft
On Error GoTo 0
End Sub
ws.Cells(1, Columns.Count)
всегда будет просматривать строку 1, аws.Cells(1, lastCol)
всегда будет просматривать только последнюю ячейку в строке 1. ВашFor Each
всегда будет просматривать все строки — независимо от того, сколько из них заполнено данными, поэтому он будет проходить через все 1 048 576 строк, даже если есть только данные в строке 1.