Pass Multiple Values and Get Selected Results In A Cell - excel

I am new with Excel VBA and trying to use it for a scenario in an Excel work book. I am trying to do a multiple value search in a cell and that should be highlighted. Say I've these ids - 1001, 1002, so in the specific cell these values should be highlighted or searched. I am not sure how can I use List<> in VBA but in C#, I can do the following:
List<string> aLst = new List<string>();
aLst.Add("1001");
aLst.Add("1002");
So with the list, I can iterate the ids and get the results matched. I was looking into the following VBA code and it gets one value as parameter. Then checks the matched one:
Function SingleCellExtract(Lookupvalue As String, LookupRange As Range, ColumnNumber As Integer)
Dim i As Long
Dim Result As String
For i = 1 To LookupRange.Columns(1).Cells.Count
If LookupRange.Cells(i, 1) = Lookupvalue Then
Result = Result & " " & LookupRange.Cells(i, ColumnNumber) & ","
End If
Next i
SingleCellExtract = Left(Result, Len(Result) – 1)
End Function
Here is the link that I am following: Excel VBA
So any way that I can use List<> and search the required values highlighted in the excel sheet?
Sample:
Id - Name
1001 John
1002 Jack

So copy this function into a new module.
Then you can access either via another function or procedure or through an excel formula in a cell like =MultiCellExtract(A2:A3;A2:B3;2)
' LookupValuesRange is an Excel Range of cells
Public Function MultiCellExtract(LookupValuesRange As Range, LookupRange As Range, ColumnNumber As Integer) As String
Dim cellValue As Range
Dim i As Long
Dim Result As String
For Each cellValue In LookupValuesRange
For i = 1 To LookupRange.Columns(1).Cells.Count
If LookupRange.Cells(i, 1) = cellValue.Value Then
Result = Result & " " & LookupRange.Cells(i, ColumnNumber) & ","
End If
Next i
Next cellValue
MultiCellExtract = Left(Result, Len(Result) - 1)
End Function
Let me know if it helps or we can adjust it.

Related

Using Excel Proper Function with exception | Excel

Essentially I have multiple strings within my Excel Spreadsheet that are structured the following way:
JOHN-MD-HOPKINS
REC-PW-RESIN
I would like to use the proper function but exclude the part of the string that is within the dashes (-).
The end result should look like the following:
John-MD-Hopkins
Rec-PW-Resin
Is there an excel formula that is capable of doing this?
You may need to create your own VBA function to do this, that checks if there are two hyphens in the data, and if so converts the first and last words to proper case without touching the middle word, otherwise just converts the string to proper case.
Paste the following into a module within Excel:
Function fProperCase(strData As String) As String
Dim aData() As String
aData() = Split(strData, "-")
If UBound(aData) - LBound(aData) = 2 Then ' has two hyphens in the original data
fProperCase = StrConv(aData(LBound(aData)), vbProperCase) & "-" & aData(LBound(aData) + 1) & "-" & StrConv(aData(UBound(aData)), vbProperCase)
Else ' just do a normal string conversion to proper case
fProperCase = StrConv(strData, vbProperCase)
End If
End Function
Then, in your worksheet, you can use this just as you would any built-in formula, so if "JOHN-MD-HOPKINS" is in cell A1, you would use this as a formula in another cell:
=fProperCase(A1)
Which would display John-MD-Hopkins as required.
EDITED CODE
As the requirement is to leave the second word, then this modified VBA function, which "walks" the array should work instead:
Function fProperCase2(strData As String) As String
Dim aData() As String
Dim lngLoop1 As Long
aData() = Split(strData, "-")
For lngLoop1 = LBound(aData) To UBound(aData)
If (lngLoop1 = LBound(aData) + 1) And (lngLoop1 <> UBound(aData)) Then
aData(lngLoop1) = aData(lngLoop1)
Else
aData(lngLoop1) = StrConv(aData(lngLoop1), vbProperCase)
End If
Next lngLoop1
fProperCase2 = Join(aData, "-")
End Function
It basically looks to see if the array element being dealt with is the second (lngLoop1=LBound(aData)+1) and also not the last (lngLoop1<>UBound(aData)).
Regards,

VBA code to scan through a comma separated value in a cell and retrieve lookup value

I have a scenario where I have to read through values in one cell which is comma separated and retrieve only values from that array to match with a particular lookup value. For eg:
So what I need is a function to retrieve all Task(or any other issuetype which could vary) from row 2 Links column
expected result: Against A2 I want to retrieve A4 and A6
This is something I modified so that you could customize it to any lookup value
Function GetLinkedItem(link As String, targetLinkType As String)
Dim temp(0 To 0) As String
GetLinkedItem = "None"
If Trim(link) = "" Then Exit Function
Dim links() As String, i As Long
links = Split(link, ",")
For i = 0 To UBound(links)
'select the links that are targetLinkType
Dim j As Long
j = GetRow(Trim(links(i)))
If Sheets("Data").Cells(j, ISUUETYPE_COL) = targetLinkType Then
temp(0) = temp(0) & " " & Sheets("Data").Cells(j, ID_COL) & ","
End If
GetLinkedItem = Join(temp, ",")
Next i
End Function
You can create a UDF to perform this lookup. In a new module in your VBE, paste the following:
Function getTasks(tasklist As Range, availabletasks As Range) As String
'tasklist is the incoming array in Column C
'availabletasks is the stuff in Column A
'Array for output
Dim tasks() As String: ReDim tasks(0 To 0)
'Loop through each item in taslist using an array
For Each task In Split(tasklist.Value, ", ")
'Search availabletasks
If Not availabletasks.Find(task) Is Nothing Then
'pop the array
If tasks(0) <> "" Then ReDim Preserve tasks(0 To UBound(tasks) + 1)
tasks(UBound(tasks)) = task
End If
Next
'Return what we found
getTasks = Join(tasks, ", ")
End Function
Now in your spreadsheet you can use this function just like a regular formula:
=getTasks(C1,$A$1:$A$6)
Where C1 has the list like A4, A25, A22, A6, A29, A42 and $A$1:$A$6 are just like your example Column A. This will return A4, A6
Thanks so much. I added the code in a new module and used the function as formula. I was getting just 1 value instead of 2(Just got A4 and not A6).

How to return name list using excel formula?

Data is:
-|-A--|-B-|
1|BAT | 5 |
2|CAT | 2 |
3|RAT | 4 |
I want formula that gives name list of animal if value in columns B > 3.
From example Result is BAT,RAT.
Here is one of the approach using you can get what you looking for. BUT you need to use VBA help to achieve this by creating user defined function.
To implement user defined function in excel:
1. Press Alt-F11 to open visual basic editor
2. Click Module on the Insert menu
3. Copy and paste below metioned user defined function
4. Exit visual basic editor
Here is the function:
Function Lookup_concat(Search_in_col As Range, Return_val_col As Range)
Dim i As Long
Dim result As String
For i = 1 To Search_in_col.Count
If Search_in_col.Cells(i, 1) > 3 Then
If result = "" Then
result = Return_val_col.Cells(i, 1).Value
Else
result = result & ", " & Return_val_col.Cells(i, 1).Value
End If
End If
Next
Lookup_concat = Trim(result)
End Function
And now in cell C1, paste the formula:
=Lookup_concat(B2:B4,A2:A4)
And this will return BAT, RAT.
Explaination of user defined function:
Lookup_concat(Search_in_column, Concatenate_values_in_column)
Looks for a value which is greater than 3 in a column and then returns values in the same rows from a column you specify, concatenated into a single cell.
Following the VB approach as smartly suggested by #Nelly27281, I propose the following function with works with variables for the criteria, range, input and output columns making it more flexible.
'Variables Type Description Sample
'sCriteria String The criteria to search for “>3”
'rInput Range The whole range to work with A1:B4
'bColSearch Byte Column within the rInput range to search for using “sCriteria” 2
'bColOutput Byte Column within the rInput range to obtain the output value 1
'blHasHdr Boolean (Optional) True if the “rinput” range has header, default is false 1
Public Function rSearch_sOutput(sCriteria As String, _
rInput As Range, bColSearch As Byte, bColOutput As Byte, Optional blHasHdr As Boolean)
Dim sOutput As String
Dim L As Long, L0 As Long
Rem Set Output String
L0 = IIf(blHasHdr, 2, 1)
With rInput
For L = L0 To .Rows.Count
If Application.Evaluate(.Columns(bColSearch).Cells(L).Value2 & sCriteria) Then
If sOutput = Empty Then
sOutput = .Columns(bColOutput).Cells(L).Value2
Else
sOutput = sOutput & ", " & .Columns(bColOutput).Cells(L).Value2
End If: End If: Next: End With
Rem Set Results
rSearch_sOutput = sOutput
End Function
To use it enter the following formula:
=rSearch_sOutput(">3",A1:B4,2,1,1)

Excel Index Match - List All Results

I am using the following Index Match function to get the name of a company where the spend data matches that of which I type into cell BF17.
=INDEX($AM$16:$BB$16,MATCH(BF17,AM17:BB17,0))
What I want to be able to do is list multiple results within the same cell and separate these with a comma.
Does anyone know if this is possible and if so can someone please show me how?
Thanks
Code:
Insert this code in a module in your workbook:
Public Function hLookupList(KeyVal, Vals As Range, Ret As Range) As String
Dim i As Long
Dim vw As Worksheet
Dim rw As Worksheet
Dim RetStr As String
Application.Volatile True
Set vw = Vals.Worksheet
Set rw = Ret.Worksheet
If Vals.Rows.Count > 1 Then
hLookupList = "Too Many Value Rows Selected!"
Exit Function
End If
If Ret.Rows.Count > 1 Then
hLookupList = "Too Many Return Rows Selected!"
Exit Function
End If
If Vals.Columns.Count <> Ret.Columns.Count Then
hLookupList = "Value Range and Return Range must be the same size!"
Exit Function
End If
For i = Vals.Column To Vals.Column + Vals.Columns.Count - 1
If vw.Cells(Vals.Row, i) = KeyVal Then
RetStr = RetStr & rw.Cells(Ret.Row, Ret.Column + i - 1) & ", "
End If
Next i
hLookupList = Left(RetStr, Len(RetStr) - 2)
End Function
Then:
Insert this in the cell where you want your list: =hLookupList(BF17, $AM$16:$BB$16, $AM$17:$BB$17)
Unfortunately there is no built-in way to make a vlookup or index/match function return an array. You could do it with a custom formula or if you know there are a limited number of results, a few nested lookups. Lewiy at mrexcel.com wrote a great custom function that I use, which can be found here. This function can be slow if you are looking up a large number of rows.
Since you are looking up columns and want commas separating the results instead of spaces, you will need to modify the code as follows:
Function MYVLOOKUP(lookupval, lookuprange As Range, indexcol As Long)
Dim r As Range
Dim result As String
result = ""
For Each r In lookuprange
If r = lookupval Then
result = result & "," & r.offSet(indexcol, 0)
End If
Next r
result = Right(result, Len(result) - 1)
MYVLOOKUP = result
End Function
Your formula would then be =MYVLOOKUP(BF17,AM17:BB17,-1)
If you want a space after the comma (in the results), change:
result = result & "," & r.offSet(indexcol, 0)
to
result = result & ", " & r.offSet(indexcol, 0)
If you haven't used custom functions before, hit Alt + F11 when in Excel to bring up the VBE, and add a new module to the workbook you are working on (Insert --> Module). Just copy and paste this code in there. I would recommend Paste Special --> Values before sending the workbook to anyone. Let me know if you have any questions implementing it!

excel vlookup with multiple results

I am trying to use a vlookup or similar function to search a worksheet, match account numbers, then return a specified value. My problem is there are duplicate account numbers and I would like the result to concatenate the results into one string.
Acct No CropType
------- ---------
0001 Grain
0001 OilSeed
0001 Hay
0002 Grain
Is in the first worksheet, on the 2nd worksheet I have the Acct No with other information and I need to get all the matching results into one column on the 2nd worksheet ie. "Grain Oilseed Hay"
Here is a function that will do it for you. It's a little different from Vlookup in that you will only give it the search column, not the whole range, then as the third parameter you will tell it how many columns to go left (negative numbers) or right (positive) in order to get your return value.
I also added the option to use a seperator, in your case you will use " ". Here is the function call for you, assuming the first row with Acct No. is A and the results is row B:
=vlookupall("0001", A:A, 1, " ")
Here is the function:
Function VLookupAll(ByVal lookup_value As String, _
ByVal lookup_column As range, _
ByVal return_value_column As Long, _
Optional seperator As String = ", ") As String
Dim i As Long
Dim result As String
For i = 1 To lookup_column.Rows.count
If Len(lookup_column(i, 1).text) <> 0 Then
If lookup_column(i, 1).text = lookup_value Then
result = result & (lookup_column(i).offset(0, return_value_column).text & seperator)
End If
End If
Next
If Len(result) <> 0 Then
result = Left(result, Len(result) - Len(seperator))
End If
VLookupAll = result
End Function
Notes:
I made ", " the default seperator for results if you don't enter one.
If there is one or more hits, I added some checking at the end to
make sure the string doesn't end with an extra seperator.
I've used A:A as the range since I don't know your range, but
obviously it's faster if you enter the actual range.
One way to do this would be to use an array formula to populate all of the matches into a hidden column and then concatenate those values into your string for display:
=IFERROR(INDEX(cropTypeValues,SMALL(IF(accLookup=accNumValues,ROW(accNumValues)-MIN(ROW(accNumValues))+1,""),ROW(A1))),"")
cropTypeValues: Named range holding the list of your crop types.
accLookup: Named range holding the account number to lookup.
accNumValues: Named range holding the list of your account
numbers.
Enter as an array formula (Ctrl+Shift+Enter) and then copy down as far as necessary.
Let me know if you need any part of the formula explaining.
I've just had a similar problem and I have looked up similar solutions for a long time, nothing really convinced me though. Either you had to write a macro, or some special function, while yet, for my needs the easiest solution is to use a pivot table in e.g. Excel.
If you create a new pivot table from your data and first add "Acct No" as row label and then add "CropType" as RowLabel you will have a very nice grouping that lists for each account all the crop types. It won't do that in a single cell though.
Here is my code which even better than an excel vlookup because you can choose to criterie colum, and for sure a separator (Carriege return too)...
Function Lookup_concat(source As String, tableau As Range, separator As String, colSRC As Integer, colDST As Integer) As String
Dim i, y As Integer
Dim result As String
If separator = "CRLF" Then
separator = Chr(10)
End If
y = tableau.Rows.Count
result = ""
For i = 1 To y
If (tableau.Cells(i, colSRC) = source) Then
If result = "" Then
result = tableau.Cells(i, colDST)
Else
result = result & separator & tableau.Cells(i, colDST)
End If
End If
Next
Lookup_concat = result
End Function
And a gift, you can make also a lookup on multiple element of the same cell (based on the same separator). Really usefull
Function Concat_Lookup(source As String, tableau As Range, separator As String, colSRC As Integer, colDST As Integer) As String
Dim i, y As Integer
Dim result As String
Dim Splitted As Variant
If separator = "CRLF" Then
separator = Chr(10)
End If
Splitted = split(source, separator)
y = tableau.Rows.Count
result = ""
For i = 1 To y
For Each word In Splitted
If (tableau.Cells(i, colSRC) = word) Then
If result = "" Then
result = tableau.Cells(i, colDST)
Else
Dim Splitted1 As Variant
Splitted1 = split(result, separator)
If IsInArray(tableau.Cells(i, colDST), Splitted1) = False Then
result = result & separator & tableau.Cells(i, colDST)
End If
End If
End If
Next
Next
Concat_Lookup = result
End Function
Previous sub needs this function
Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
IsInArray = (UBound(Filter(arr, stringToBeFound)) > -1)
End Function
Function VLookupAll(vValue, rngAll As Range, iCol As Integer, Optional sSep As String = ", ")
Dim rCell As Range
Dim rng As Range
On Error GoTo ErrHandler
Set rng = Intersect(rngAll, rngAll.Columns(1))
For Each rCell In rng
If rCell.Value = vValue Then
VLookupAll = VLookupAll & sSep & rCell.Offset(0, iCol - 1).Value
End If
Next rCell
If VLookupAll = "" Then
VLookupAll = CVErr(xlErrNA)
Else
VLookupAll = Right(VLookupAll, Len(VLookupAll) - Len(sSep))
End If
ErrHandler:
If Err.Number <> 0 Then VLookupAll = CVErr(xlErrValue)
End Function
Use like this:
=VLookupAll(K1, A1:C25, 3)
to look up all occurrences of the value of K1 in the range A1:A25 and to return the corresponding values from column C, separated by commas.
If you want to sum values, you can use SUMIF, for example
=SUMIF(A1:A25, K1, C1:C25)
to sum the values in C1:C25 where the corresponding values in column A equal the value of K1.
ALL D BEST.

Resources