Home » excel » vba – Excel: Concatenate last non empty cells in a column

vba – Excel: Concatenate last non empty cells in a column

Posted by: admin May 14, 2020 Leave a comment

Questions:

Since my previous post was closed, but the problem remains, I’ll rephrase it here. I’ve came up with the following:

Function JoinLastInColIfEmpty(range_ As Range, delim_ As String)
    Dim cell As Range, result As String, current As String

    For Each cell In range_
        current = LastNonEmptyInCol(cell)
        If current <> "" Then
            result = result & current & delim_
        End If
    Next

    If Not IsEmpty(result) Then
        result = Left(result, Len(result) - Len(delim_))
    End If

    JoinLastInColIfEmpty = result
End Function

Function LastNonEmptyInCol(cell_ As Range)
    Dim tmp As Range
    tmp = cell_ '<< The problem occurs here
    Do Until Not IsEmpty(tmp) Or tmp.Row = 1
        tmp = tmp.Offset(-1, 0)
    Loop
    LastNonEmptyInCol = tmp.Value
End Function

The problem is that the function never ends, so my questions are:

  • What is wrong with my script?
  • What should I do to solve my problem?
How to&Answers:

To answer your direct question, there are a couple of errors in LastNonEmptyInCol

Function LastNonEmptyInCol(cell_ As Range)
    On Error Resume Next
    Dim tmp As Range
    Set tmp = cell_ '<< The problem occurs here  ' <<<<< use Set
    Do Until Not IsEmpty(tmp) Or tmp.Row = 1     ' <<<<< use tmp not cell_
        Set tmp = tmp.Offset(-1, 0)              ' <<<<< use Set 
    Loop
    LastNonEmptyInCol = tmp.Value
End Function

That said, I think it is a very inefficient solution, and does not quite solve your stated problem

results will be

    A  |  B  |  C  |  D  | Concat
  -----+-----+-----+-----+---------
    1  |  2  |  X  |  5  | 12X5
       |     |  f  |  3  | 12f3
       |  5  |  R  |  12 | 15R12
    Z  |  3  |  T  |     | Z3T12
       |  G  |     |     | ZGT12

Here’s another version which might be better

Function MyJoinLastInColIfEmpty(range_ As Range, delim_ As String)
    Dim vData As Variant
    Dim cl As Range
    Dim i As Long
    Dim result As Variant

    vData = range_

    For i = 1 To UBound(vData, 2)
        If vData(1, i) = "" Then
            Set cl = range_.Cells(1, i).End(xlUp)
            If cl <> "" Then
                vData(1, i) = cl.Value
            End If
        Else
            Exit For
        End If
    Next
    For i = 1 To UBound(vData, 2)
        result = result & vData(1, i) & delim_
    Next

    MyJoinLastInColIfEmpty = Left(result, Len(result) - Len(delim_))
End Function

Answer:

I did not really try to understand the whole thing, but since tmp is an (range) object, you must use
Set tmp = ....

Answer:

With help rows/columns this can be achieved with formulas:

-Placed in cell F1 array entered (Ctrl+Shift+Enter) then scrolled to however many cells you have:

{=INDEX(A$1:A1,MAX(IF(ISBLANK(A$1:A1),0,ROW(A$1:A1))))}

-Placed in cell K1, refers to first cell in F1, no need for array here.

=IF(ISBLANK(A1),IF(SUM(NOT(ISBLANK(INDEX($A1:A1,0)))+0)>0,"",F1),F1)

-Placed wherever you want the results. MCONCAT is a UDF function found in a free Add-in written in C++, CONCATENATE is Excel’s built in formula.

=MConCat(K1:N1) or =CONCATENATE(K1,L1,M1,N1)

My personal preference would be the VBA way though. I’m sure someone smarter than me could come up with some better formulas.