Reputation: 111
I'm trying to perform a VLookup where the column of the data I will be pulling can vary. How can I search for the column name instead of having to give a fixed column number?
Application.VLookup(.Cells(row, 1).value, Worksheets("Sheet1").Range("A2:Z" & lastRow_Sheet1), 4, 0)
Application.VLookup(.Cells(row, 1).value, Worksheets("Sheet1").Range("A2:Z" & lastRow_Sheet1), COLUMNNAME, 0)
I'm trying to get a MATCH function working here but am having no luck:
Application.VLookup(.Cells(row, 1).value, Worksheets("Sheet1").Range("A2:Z" & lastRow_Sheet1), WorksheetFunction.Match("Column Name", "A1:Z1", 0), 0)
Edit: Solution here
Application.VLookup(.Cells(row, 1).value, Worksheets("Sheet1").Range("A2:Z" & lastRow_Sheet1), WorksheetFunction.Match("Column Name", Range("A1:Z1"), 0), 0)
Upvotes: 2
Views: 998
Reputation: 54807
Match
instead of VLookup
You could use the following function to get the column number:
Function getTableColumnNumber( _
ByVal HeaderRange As Range, _
ByVal HeaderTitle As String) _
As Long
If Not HeaderRange Is Nothing Then
If Len(HeaderTitle) > 0 Then
Dim cIndex As Variant
cIndex = Application.Match(HeaderTitle, HeaderRange, 0)
If IsNumeric(cIndex) Then
getTableColumnNumber = cIndex
End If
End If
End If
End Function
Note that the column number is the 'n-th' column of the header range which is not necessarily the 'n-th' column of the worksheet (e.g. if the range starts in column C
).
An Example
Sheet1
) which usually contains unique data (green column).Sheet2
) where the yellow column is initially blank. It illustrates a case where VLookup
cannot work because the return values (yellow column) are to the left of the lookup values (green column).s
- Source, d
- Destination, l
- Lookup, m
- Match.Option Explicit
Sub matchValues()
Const sName As String = "Sheet1"
Const slHeader As String = "ID"
Const smHeader As String = "Value"
Const sCols As String = "A:Z"
Const sFirst As Long = 1
Const dName As String = "Sheet2"
Const dlHeader As String = "ID"
Const dmHeader As String = "Value"
Const dCols As String = "A:Z"
Const dFirst As String = 1
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim slrg As Range, smrg As Range
With wb.Worksheets(sName)
Dim shrg As Range: Set shrg = .Columns(sCols).Rows(sFirst)
Dim slCol As Long: slCol = getTableColumnNumber(shrg, slHeader)
If slCol = 0 Then Exit Sub
Dim smCol As Long: smCol = getTableColumnNumber(shrg, smHeader)
If smCol = 0 Then Exit Sub
Dim srg As Range: Set srg = getDataRange(shrg)
Set slrg = srg.Columns(slCol)
Set smrg = srg.Columns(smCol)
End With
Dim drg As Range
With wb.Worksheets(dName)
Dim dhrg As Range: Set dhrg = .Columns(dCols).Rows(dFirst)
Dim dlCol As Long: dlCol = getTableColumnNumber(dhrg, dlHeader)
If dlCol = 0 Then Exit Sub
Dim dmCol As Long: dmCol = getTableColumnNumber(dhrg, dmHeader)
If dmCol = 0 Then Exit Sub
Set drg = getDataRange(dhrg)
End With
Dim dCell As Range
Dim cIndex As Variant
For Each dCell In drg.Columns(dlCol).Cells
cIndex = Application.Match(dCell.Value, slrg, 0)
If IsNumeric(cIndex) Then
dCell.EntireRow.Columns(dmCol).Value = smrg.Cells(cIndex).Value
Else
dCell.EntireRow.Columns(dmCol).Value = "Not Found"
End If
Next dCell
End Sub
Function getTableColumnNumber( _
ByVal HeaderRange As Range, _
ByVal HeaderTitle As String) _
As Long
If Not HeaderRange Is Nothing Then
If Len(HeaderTitle) > 0 Then
Dim cIndex As Variant
cIndex = Application.Match(HeaderTitle, HeaderRange, 0)
If IsNumeric(cIndex) Then
getTableColumnNumber = cIndex
End If
End If
End If
End Function
Function getDataRange( _
ByVal HeaderRange As Range) _
As Range
If Not HeaderRange Is Nothing Then
With HeaderRange.Offset(1)
Dim lCell As Range
Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , xlByRows, xlPrevious)
If Not lCell Is Nothing Then
Set getDataRange = .Resize(lCell.Row - .Row + 1)
End If
End With
End If
End Function
Upvotes: 2