excel - Returning First Non-Blank Cell in a Row - Stack Overflow

admin2025-05-01  1

I'm a VBA rookie looking to write some code that will return the value of the first non-blank cell in a row spanning 5 columns of data. I found a mrexcel article that contains exactly what I'm looking to achieve but I'm having a hard time translating the Excel formula to VBA.

/

I had mild success with a basic If-Then statement but that only works if the column directly to the right is not empty; if the column directly to the right is blank the code carries over the blank. I'd like the code to run on the same row, moving right until a non-empty column is reached.

Sub test()
    
    lRow = Cells(Rows.Count, "D").End(xlUp).Row

    For i = 2 To lRow
        If IsEmpty(Cells(i, 7).Value) Then
            Cells(i, 7).Value = Cells(i, 8).Value
        ElseIf IsEmpty(Cells(i, 8).Value) Then
            Cells(i, 7).Value = Cells(i, 9).Value
        End If
    Next

End Sub

I'm a VBA rookie looking to write some code that will return the value of the first non-blank cell in a row spanning 5 columns of data. I found a mrexcel article that contains exactly what I'm looking to achieve but I'm having a hard time translating the Excel formula to VBA.

https://www.mrexcel.com/excel-tips/find-the-first-non-blank-value-in-a-row/

I had mild success with a basic If-Then statement but that only works if the column directly to the right is not empty; if the column directly to the right is blank the code carries over the blank. I'd like the code to run on the same row, moving right until a non-empty column is reached.

Sub test()
    
    lRow = Cells(Rows.Count, "D").End(xlUp).Row

    For i = 2 To lRow
        If IsEmpty(Cells(i, 7).Value) Then
            Cells(i, 7).Value = Cells(i, 8).Value
        ElseIf IsEmpty(Cells(i, 8).Value) Then
            Cells(i, 7).Value = Cells(i, 9).Value
        End If
    Next

End Sub
Share Improve this question edited Jan 2 at 18:50 VBasic2008 55.5k5 gold badges20 silver badges36 bronze badges asked Jan 2 at 18:26 user29028421user29028421 211 bronze badge 2
  • 1 The formula in the linked post writes the leftmost non-empty value of each row of the range C2:K12 to the corresponding row of column A. 1.) Where do you want to return the results? 2.) What are your columns? For example, 1.) G2:GLastRow and 2.) G2:KLastRow. Or what is the formula for your specific requirement? – VBasic2008 Commented Jan 2 at 18:44
  • Thanks for taking a look. I too want to return the leftmost non-empty value in a row of the range G2:KLastRow. 1) I'd like to ideally bring the leftmost non-empty value to column G so column G would be a column of continuous values. I would delete columns H-K following this process. 2) G2:KLastRow – user29028421 Commented Jan 2 at 19:17
Add a comment  | 

2 Answers 2

Reset to default 1

Copy/Move Leftmost Values in Rows

Copy

Sub CopyLeftMost()
    
    ' Define constants.
    Const FIRST_ROW As Long = 2
    Const LAST_ROW_COLUMN As Long = 4 ' make sure this column is populated!
    Const FIRST_COLUMN As Long = 7
    Const COLUMNS_COUNT As Long = 5
    Const RESULT_COLUMN As Long = 7
    Const NOT_AVAILABLE_VALUE As Variant = "#N/A"
    
    ' Reference the worksheet.
    Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
    
    ' Retrieve the last populated row.
    Dim LastRow As Long:
    LastRow = ws.Cells(ws.Rows.Count, LAST_ROW_COLUMN).End(xlUp).Row

    ' Declare addtional variables.
    Dim Value As Variant, r As Long, c As Long, IsFound As Boolean
     
    ' Loop through the rows...
    For r = FIRST_ROW To LastRow
        IsFound = False ' reset the flag for each row
        ' Loop through the columns...
        For c = 1 To COLUMNS_COUNT
            ' Retrieve the value from each column of the current row.
            Value = ws.Cells(r, FIRST_COLUMN + c - 1).Value
            ' Either...
            If Not IsEmpty(Value) Then ' is not empty
            ' ... or
            'If Len(CStr(Value)) > 0 Then ' is not blank
                IsFound = True ' since the condition is met...
                Exit For ' ... there is no need to check anymore
            End If
        Next c
        If IsFound Then ' condition met
            ws.Cells(r, RESULT_COLUMN).Value = Value
        Else ' condition not met
            ws.Cells(r, RESULT_COLUMN).Value = NOT_AVAILABLE_VALUE
        End If
    Next r
    
    MsgBox "Copied left most values.", vbInformation

End Sub

Move

  • This one is more flexible and efficient and includes clearing the values in all but the first column.

Sub MoveValuesToTheLeft()
    
    ' Define constants.
    Const NOT_AVAILABLE_VALUE As Variant = "#N/A"
    Const FIRST_ROW_ADDRESS As String = "G2:K2"
    
    ' Reference the worksheet.
    Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
    
    ' Declare additional variables.
    Dim rg As Range, lcell As Range, RowsCount As Long, ColumnsCount As Long
    
    ' Reference the range and retrieve its number of rows and columns.
    With ws.Range(FIRST_ROW_ADDRESS)
        ColumnsCount = .Columns.Count
        Set rg = .Resize(ws.Rows.Count - .Row + 1) ' i.e. G2:K1048576
        Set lcell = rg.Find("*", , xlFormulas, , xlByRows, xlPrevious)
        If lcell Is Nothing Then Exit Sub ' no data (highly unlikely)
        RowsCount = lcell.Row - .Row + 1
        Set rg = .Resize(RowsCount)
    End With
    
    ' Return the values of the range in an array.
    Dim Data() As Variant: Data = rg.Value
 
    ' Declare addtional variables.
    Dim Value As Variant, r As Long, c As Long, IsFound As Boolean
     
    ' Loop through the rows...
    For r = 1 To RowsCount
        IsFound = False ' reset the flag for each row
        ' Loop through the columns...
        For c = 1 To ColumnsCount
            ' Retrieve the value from each column of the current row.
            Value = Data(r, c)
            ' Either...
            If Not IsEmpty(Value) Then ' is not empty
            ' ... or
            'If Len(CStr(Value)) > 0 Then ' is not blank
                IsFound = True ' since the condition is met...
                Exit For ' ... there is no need to check anymore
            End If
        Next c
        ' Move value to the left.
        If IsFound Then ' condition met
            Data(r, 1) = Value
        Else ' condition not met
            Data(r, 1) = NOT_AVAILABLE_VALUE
        End If
    Next r
    
    ' Write the resulting values from the first array column to the worksheet.
    rg.Columns(1).Value = Data
    
    ' Clear all but the first column.
    rg.Resize(, ColumnsCount - 1).Offset(, 1).ClearContents
    
    ' Inform.
    MsgBox "Moved values to the left.", vbInformation

End Sub

Your code needs a slight mod with the usage of the End property of the Range object.

Sub test()
    
    lRow = Cells(Rows.count, "D").End(xlUp).Row

    For i = 2 To lRow
        If IsEmpty(Cells(i, 7).Value) Then
        '    Cells(i, 7).Value = Cells(i, 8).Value
        'ElseIf IsEmpty(Cells(i, 8).Value) Then
        '    Cells(i, 7).Value = Cells(i, 9).Value
            Cells(i, 7) = Cells(i, 7).End(xlToRight)
            Range("H" & i & ":K" & i).Clear
        End If
    Next

End Sub
转载请注明原文地址:http://www.anycun.com/QandA/1746103076a91708.html