Макрос для удаления пустых ячеек в строке

У меня есть макрос для удаления пустых ячеек в каждой строке и смещения следующей ячейки влево. Код не показывает никаких ошибок, но ничего не делает.

Поскольку количество столбцов может меняться от строки к строке, я определил последнюю строку внутри цикла 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
ws.Cells(1, Columns.Count) всегда будет просматривать строку 1, а ws.Cells(1, lastCol) всегда будет просматривать только последнюю ячейку в строке 1. Ваш For Each всегда будет просматривать все строки — независимо от того, сколько из них заполнено данными, поэтому он будет проходить через все 1 048 576 строк, даже если есть только данные в строке 1.
Darren Bartrup-Cook 13.08.2024 14:08
Этот может помочь , изменить r.Clear на r.Delete Shift:=xlToLeft и, возможно, еще какие-то адаптации, потому что он ищет формулы, а не пустые ячейки.
Excellor 13.08.2024 14:15

Спасибо @DarrenBartrup-Cook - это также объясняет плохую производительность. У вас есть рекомендация вместо For Each?

cdfj 13.08.2024 14:21

Спасибо @Excellor - к сожалению, не с ws.UsedRange.Cells.SpecialCells(xlCellTypeBlanks) - раньше пробовал UsedRange, но безуспешно.

cdfj 13.08.2024 14:28
Преобразование HTML-таблицы в профессиональный документ Excel
Преобразование HTML-таблицы в профессиональный документ Excel
Это самый простой способ создания Excel из HTML-таблицы.
Импорт excel в laravel в базу данных
Импорт excel в laravel в базу данных
Здравствуйте, дорогой читатель, в этой статье я расскажу практическим и быстрым способом, как импортировать файл Excel в вашу базу данных с помощью...
1
4
51
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Попробуйте этот код. Он ограничивает его только заполненными строками - при условии, что в столбце 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

cdfj 13.08.2024 14:52

Вы уверены, что эти ячейки пусты и не содержат пробелов? Добавьте Debug.Print .Cells(rRow.Row, Counter).Address & ": " & Len(.Cells(rRow.Row, Counter)) перед строкой IF — будет напечатан адрес ячейки и количество символов (длина) в ячейке.

Darren Bartrup-Cook 13.08.2024 14:58

Спасибо - вот и все! 😳Пространства в клетках! Огромное вам спасибо - вы избавили меня от большого разочарования! 🙏🙏🙏

cdfj 13.08.2024 15:04

Вы можете обновить проверку в операторе IF на Trim(.Cells(rRow.Row, Counter)), чтобы удалить все начальные и конечные пробелы.

Darren Bartrup-Cook 13.08.2024 15:09

Я добавил обрезку, чтобы решить проблему с пробелами: Dim cell As Range For Each cell In ActiveSheet.UsedRange.SpecialCells(xlCellTypeConstants) cell = WorksheetFunction.Trim(cell) Next cell

cdfj 13.08.2024 15:27

Этот код использует 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.

VBasic2008 13.08.2024 15:43

Удалить пробелы в строках

Основной

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

Другие вопросы по теме