VBA Excel Search, Filter Based on Key Values, RetriveValueFromKey() (Sample Code and Download)

RetriveValueFromKey() is a function that I’ve written. It searches records for a specific set of keys. If the keys are matched then that record is copied to a specific location. The code for the function is written below. I would appreciate if you are using this code to give reference to my blog. You can download the full code here:

Jump To:

Option Explicit


'Searches a column of values to find the target string. If
'found the value in the value column is printed in the output
'location specified
'strKeys() : Values to search for
'wrksheet_Key : sheet to look for strKey and Values
'row_Key : row to start searching for key
'column_Key() : column you can find the keys in
'column_Value() : columns you can find the values in
'wrksheet_output : worksheet to print values
'row_output : row to start printing output in
'column_Output : column to start printing output in
'Return Value: The number of data printed in the output column
'arrColumnMap: An array, mapping the columns in the value worksheet
'to the columns they are supposed to go in the output
' worksheet. The first map value should be smallest
Public Function RetrieveValueFromKey(ByRef strKeys() As Variant, _
ByRef wrksheet_Key As Worksheet, ByVal row_Key As Integer, _
ByRef column_Keys() As Integer, ByRef column_Value() As Integer, _
ByRef wrksheet_Output As Worksheet, ByVal row_Output As Integer, _
ByRef arrColumnMap() As Integer) As Integer

Dim count_Key As Integer
Dim count_OutputRows As Integer
Dim count_OutputColumns As Integer
Dim i As Integer
Dim arrTemp() As Variant
Dim strRange As String
Dim strColumn As String
Dim flagMatch As Boolean
Dim j As Integer
Dim arrTempColumnToAdd() As Variant
Dim arrKeyRangeData() As Variant
Dim arrValueRangeData() As Variant
Dim arrOutputRangeData() As Variant

count_Key = Get_Count(row_Key, column_Keys(1), wrksheet_Key, True)
ReDim arrKeyRangeData(1 To count_Key, 1 To UBound(strKeys))
ReDim arrValueRangeData(1 To count_Key, 1 To UBound(column_Value))

If count_Key <> 0 Then
    strRange = "=" + wrksheet_Key.Name + "!"
    strColumn = Get_Alphabet(column_Keys(1))
    strRange = strRange + strColumn + Strings.Trim(Str(row_Key)) + ":" + _
    strColumn + Strings.Trim(Str(row_Key + count_Key - 1))
    arrTempColumnToAdd = Range(strRange).Value
   
    Call Add_Column(arrKeyRangeData, arrTempColumnToAdd, 1)
    For i = 2 To UBound(column_Keys)
        strColumn = Get_Alphabet(column_Keys(i))
        strRange = "=" + wrksheet_Key.Name + "!"

        strRange = strRange + strColumn + Strings.Trim(Str(row_Key)) + ":" _
        + strColumn + Strings.Trim(Str(row_Key + count_Key - 1))
        arrTempColumnToAdd = Range(strRange).Value
        Call Add_Column(arrKeyRangeData, arrTempColumnToAdd, i)
    Next i
   
    strRange = "=" + wrksheet_Key.Name + "!"
    strColumn = Get_Alphabet(column_Value(1))
    strRange = strRange + strColumn + Strings.Trim(Str(row_Key)) + ":" + _
    strColumn + Strings.Trim(Str(row_Key + count_Key - 1))
    arrTempColumnToAdd = Range(strRange).Value
   
    Call Add_Column(arrValueRangeData, arrTempColumnToAdd, 1)
    For i = 2 To UBound(column_Value)
   
        strColumn = Get_Alphabet(column_Value(i))
        strRange = "=" + wrksheet_Key.Name + "!"

        strRange = strRange + strColumn + Strings.Trim(Str(row_Key)) + ":" + _
        strColumn + Strings.Trim(Str(row_Key + count_Key - 1))
        arrTempColumnToAdd = Range(strRange).Value
        Call Add_Column(arrValueRangeData, arrTempColumnToAdd, i)
    Next i
End If

count_OutputRows = Get_Count(row_Output, arrColumnMap(1), wrksheet_Output, True)
count_OutputColumns = Get_Count(row_Output - 1, arrColumnMap(1), wrksheet_Output, False)
Call Clear_Column(row_Output, arrColumnMap(1), count_OutputRows, _
count_OutputColumns, wrksheet_Output)

If count_Key <> 0 Then
    ReDim arrOutputRangeData(1 To count_Key, 1 To UBound(column_Value))
    count_OutputRows = 1
End If

For i = 1 To count_Key
    flagMatch = True
    For j = 1 To UBound(column_Keys)
        If arrKeyRangeData(i, j) <> strKeys(j) Then
           flagMatch = False
        End If
    Next j
   
    If flagMatch = True Then
        For j = 1 To UBound(arrValueRangeData, 2)
           arrOutputRangeData(count_OutputRows, j) = arrValueRangeData(i, j)
           
        Next j
        count_OutputRows = count_OutputRows + 1
    End If
Next i
   
count_OutputRows = count_OutputRows - 1

arrOutputRangeData = Trim_Array(arrOutputRangeData, count_OutputRows)
'arrOutputColumn = TransposeArray(arrOutputColumn)

For i = 1 To UBound(arrOutputRangeData, 2)
    wrksheet_Output.Range(wrksheet_Output.Cells(row_Output, arrColumnMap(i)), _
        wrksheet_Output.Cells(row_Output + count_OutputRows - 1, _
        arrColumnMap(i))).Value2 = Get_ColumnFrom2DArray(arrOutputRangeData, i)
Next i

RetrieveValueFromKey = count_OutputRows
End Function

'Retrieves the amount of data at a spcefic column
'intRow: Row to start searching for data
'intColumn: Column to start searching for data
'wrksheet: worksheet to start searching for data
Private Function Get_Count(ByVal intRow As Integer, ByVal intColumn As Integer, ByRef wrkSheet As Worksheet, _
ByVal flagCountRows As Boolean) As Integer
Dim i As Integer
Dim flag As Boolean

i = 1
flag = True
While flag = True
    If flagCountRows = True Then
        If wrkSheet.Cells(i + intRow - 1, intColumn) <> "" Then
           i = i + 1
        Else
           flag = False
        End If
    Else
        If wrkSheet.Cells(intRow, intColumn + i - 1) <> "" Then
           i = i + 1
        Else
           flag = False
        End If
    End If
Wend

Get_Count = i - 1
End Function

'''
'Returns the alphabet associated with the column
'intNumber: The column number
'Return Value: Alphabet associated with the column number
Private Function Get_Alphabet(ByVal intNumber As Integer) As String
Get_Alphabet = Strings.Trim(Chr(intNumber + 64))
End Function

'Adds a column to an existing 2D array
'arrTotal: The array that the column will be added to
'arrColumn: The column that will be added to the 2D array
'intColumnIndex: The index which the column will be inserted
Private Sub Add_Column(ByRef arrTotal() As Variant, ByRef arrColumn() As Variant, ByVal intColumnIndex As Integer)
Dim i As Integer
For i = 1 To UBound(arrTotal)
    arrTotal(i, intColumnIndex) = arrColumn(i, 1)
Next i
End Sub

'Clears the content of a column starting from a specific row, with a set amount of date
'intRow: Row to start clearing data from
'intColumn: Column to start clearing data from
'countData: The amount of data to clear
'wkrsheet: Worksheet to clear the data from
Private  Sub Clear_Column(ByVal intRow As Integer, ByVal intColumn As Integer, ByVal countROws As Integer, _
ByVal countColumns As Integer, ByRef wrkSheet As Worksheet)
If countROws <> 0 Then
        wrkSheet.Range(wrkSheet.Cells(intRow, intColumn), wrkSheet.Cells(intRow + countROws - 1, intColumn + countColumns - 1)) = ""
End If
End Sub

'Copyes the values in the first part of the array to a new array
'arrInput: Array to take values from
'intCount: Amount of elements to take
'Return Value: The new array
Private Function Trim_Array(ByRef ArrInput() As Variant, ByVal intCount As Integer) As Variant()
Dim i As Integer
Dim arrTemp() As Variant
Dim j As Integer

ReDim arrTemp(1 To intCount, 1 To UBound(ArrInput, 2))
For i = 1 To intCount
    For j = 1 To UBound(ArrInput, 2)
           arrTemp(i, j) = ArrInput(i, j)
    Next j
Next i
Trim_Array = arrTemp
End Function
'''
'Returns a column from a 2d array
'arrInput: The array to retreive the column array from
'intColumn: The column index to retreive
'Return Value: The column needed
Private  Function Get_ColumnFrom2DArray(ByRef ArrInput() As Variant, ByVal intColumn As Integer) As Variant()
Dim i As Integer
Dim arrTemp() As Variant
ReDim arrTemp(1 To UBound(ArrInput), 1 To 1)
For i = 1 To UBound(ArrInput)
    arrTemp(i, 1) = ArrInput(i, intColumn)
Next i

Get_ColumnFrom2DArray = arrTemp
End Function

Input Parameters:

strKeys()This is an array of string values. Each of these values is a key. The function checks the set of records for these keys. If the keys are found, then it will accept that record.

wrksheet_Key: The worksheet where the records can be found.

row_Key: The row where the records start.

column_Keys(): This is an array with column indices where the keys can be found in:

column_Value(): This is an array with column indices where the values you wish to copy can be found in.

wrkSheet_Output: The worksheet where the results are printed in.

row_Output: The row where the outputs should start printing at.

arrColumnMap(): This is an array which maps the columns specified by column_Value() to a column in the output worksheet.

Return Value: The number of records matched.

Example1:

Assume you have the following records:

Records

The records are written in sheet2 therefor:

Dim wrkSheet_Key As Worksheet
Set wrkSheet_Key = Sheet2

The records start from row 3:

Dim row_Key As Integer
row_Key = 3

Lets say we only need the schools in the US:

Dim strKeys(1 To 1) As String
strKeys(1) = “Us”

 The index for the country column is 3:

Dim column_Keys(1 To 1) As Integer
column_Keys(1) = 3

Lets say we want the results to be printed in Sheet1 Exactly the way it is in sheet2:

Dim row_Output As Integer
Dim wrksheet_Output As Worksheet
Dim column_Values(1 To 5) As Integer
Dim arrColumnMap(1 To 5) As Integer


row_Output = 3
wrksheet_Output = Sheet1
column_Values(1) = 2
column_Values(2) = 3
column_Values(3) = 4
column_Values(4) = 5
column_Values(5) = 6

arrColumnMap(1) = 2
arrColumnMap(2) = 3
arrColumnMap(3) = 4
arrColumnMap(4) = 5
arrColumnMap(5) = 6

After calling the function the results is:

Dim intPrint As Integer
intPrint = RetrieveValueFromKey(strKeys(), wrkSheet_Key, row_Key, _
column_Keys(), column_Value(), wrksheet_Output, row_Output, _
arrColumnMap())

Records matched

Example2:

In this example we will assume that not only are we looking for US Schools, but we also want the schools to be in california. Changes would only be applied to column_Keys() and str_Keys():

Sub Example2()

Dim wrksheet_Key As Worksheet
Set wrksheet_Key = Sheet2

Dim row_Key As Integer
row_Key = 3

Dim strKeys(1 To 2) As Variant
strKeys(1) = "US"
strKeys(2) = "California"

Dim column_Keys(1 To 2) As Integer
column_Keys(1) = 3
column_Keys(2) = 4

Dim row_Output As Integer
Dim wrksheet_Output As Worksheet
Dim column_Value(1 To 5) As Integer
Dim arrColumnMap(1 To 5) As Integer


row_Output = 3
Set wrksheet_Output = Sheet1
column_Value(1) = 2
column_Value(2) = 3
column_Value(3) = 4
column_Value(4) = 5
column_Value(5) = 6

arrColumnMap(1) = 2
arrColumnMap(2) = 3
arrColumnMap(3) = 4
arrColumnMap(4) = 5
arrColumnMap(5) = 6

Dim intPrint As Integer
intPrint = RetrieveValueFromKey(strKeys(), wrksheet_Key, row_Key, _
column_Keys(), column_Value(), wrksheet_Output, row_Output, _
arrColumnMap())
End Sub

Result:

Records matched 2

Example 3:

In this example we will assume that we want the price to appear in the first column in the output sheet, and the rest of the values to appear after that. Also we don't want the country column to appear in the output:


Sub
Example3()

Dim wrksheet_Key As Worksheet
Set wrksheet_Key = Sheet2

Dim row_Key As Integer
row_Key = 3

Dim strKeys(1 To 2) As Variant
strKeys(1) = "US"
strKeys(2) = "California"

Dim column_Keys(1 To 2) As Integer
column_Keys(1) = 3
column_Keys(2) = 4

Dim row_Output As Integer
Dim wrksheet_Output As Worksheet
Dim column_Value(1 To 4) As Integer
Dim arrColumnMap(1 To 4) As Integer

row_Output = 3
Set wrksheet_Output = Sheet1
column_Value(1) = 2
column_Value(2) = 4
column_Value(3) = 5
column_Value(4) = 6

arrColumnMap(1) = 2
arrColumnMap(2) = 3
arrColumnMap(3) = 4
arrColumnMap(4) = 1

Dim intPrint As Integer
intPrint = RetrieveValueFromKey(strKeys(), wrksheet_Key, row_Key, _
column_Keys(), column_Value(), wrksheet_Output, row_Output, _
arrColumnMap())
End Sub

Result:

Records matched 3

You can download the full code here. I would appreciate if you are using this code to give reference to my blog.
If you need assistance with your code, or you are looking to hire a VBA programmer feel free to contact me. Also please visit my website www.software-solutions-online.com

One thought on “VBA Excel Search, Filter Based on Key Values, RetriveValueFromKey() (Sample Code and Download)”

  1. Martin says:

    I want use same code to filter data from multiple workbooks.
    but how to do that?

Leave a Reply

Your email address will not be published. Required fields are marked *