is there anyway to return multiple values from a vlookup? I would like col I in Sheet 1 to return multiple values to a cell, or is there another way of displaying this (would rather not pivot)?
Sheet 1 : has all my unique values (Col F, and returning values in Col I),
Sheet 3: Col A has duplicate string values which correspond to unique strings in Col B which are unique, including blanks.
EDIT
Sheet 1 or desired result :
Sheet 1: Current
Sheet 3 Current:
Current formula
=VLOOKUP(F2,Sheet3!A:B,2,FALSE)
Returns mostly 0's, due to the blanks or multiple values corresponding to the unique values.
In terms of VBA then, you have to change the code a bit from what was in the link I sent you. This should work:
Option Explicit
Function vlookupmulti(rngLookup As Variant, rngSource As Range, col As Double) As String
Dim d As Double, strCell As String
'Error if range has less columns than col
If rngSource.Columns.Count < col Then
vlookupmulti = CVErr(xlErrNA)
Exit Function
End If
'Loop through rows in the lookup column
For d = rngSource.Row To rngSource.Rows.Count
If rngLookup = Sheets(rngSource.Parent.Name).Cells(d, rngSource.Column).Value Then
strCell = Sheets(rngSource.Parent.Name).Cells(d, rngSource.Column + col - 1).Value
If Len(strCell) > 0 Then vlookupmulti = vlookupmulti & strCell & ", "
End If
Next d
'Remove comma at end
If Right(vlookupmulti, 2) = ", " Then
vlookupmulti = Left(vlookupmulti, Len(vlookupmulti) - 2)
End If
'Give error if no results
If vlookupmulti = "" Then
vlookupmulti = CVErr(xlErrNA)
End If
End Function
Related
I would like to filter values from "Column 1" if the corresponding value in "Column 2" is "B", but only if none of the identical (duplicate) values in Column 1 have a value of "A" in "Column 2".
To simplify, the output should be "2" and "4", since those are the only values that don't have a value of "A" in "Column 2" in any of their iterations in "Column 1".
I was able to do this in Excel using two dynamic formulas and XLOOKUP.
Via VBA I can do a For Each Loop that would filter all the values that have a value of "B" in Column 2 (in this case it would return all the values from "Column 1" except "3"), which isn't what I need.
Sub ChooseStatus()
Dim Sheet1 As Worksheet
Set Sheet1 = ThisWorkbook.Sheets("Sheet1")
'defining the area
lr = Sheet1.Cells(Rows.Count, 1).End(xlUp).Row
sr = Selection.Row
'defining categories
Item = Sheet1.Cells(sr, 1)
Status = Sheet1.Cells(sr, 2)
'loop
For i = 2 To lr
If Sheet1.Cells(i, 2) = "B" Then
Sheet1.Cells(i, 1).Interior.Color = rgbBlue
End If
Next i
End Sub
Item
Status
1
A
1
B
1
B
2
B
2
B
3
A
3
A
4
B
5
A
5
B
If you dispose of Excel version MS365 and its UNIQUE() function, you might try the following procedure Examplecall together with the user defined help functions GetFormula() and IsValid(). (If not there are many examples at SO how to get unique values in versions before).
This approach demonstrates also the use of the following frequent VBA functions
Worksheet.Evaluate
Filter
Replace
Join
Example call
Option Explicit ' force declarations at code module head
Sub ExampleCall()
With Sheet1 ' << change to wanted sheet Code(Name)
Dim rng As Range
Set rng = .Range("A2:B11") ' << change to wanted range (note the starting "."-point)
'a) get uniques array & provide for temporary results array
Dim uniques
uniques = .Evaluate(GetFormula(rng))
Dim results
results = uniques ' contains temporarily all uniques
End With
'b) mark all invalid items for deletion
Dim i As Long
For i = 1 To UBound(uniques)
If Not IsValid(uniques, i) Then results(i) = "$DEL$"
Next i
'c) remove marked items from results array
results = Filter(results, "$DEL$", False) ' negative filtering removes $DEL$ items
MsgBox Join(results, vbNewLine), vbInformation, "Found elements"
End Sub
Help functions
Function GetFormula(rng As Range, Optional Delim As String = "-") As String
'a) define column number within the passed range argument
Const ITEM As Long = 1, STATUS As Long = 2 '
If rng.Columns.Count < Application.Max(ITEM, STATUS) Then Exit Function ' provide for sufficient columns
'b) define formula pattern
Dim Pattern As String
Pattern = "transpose(Unique(X & """ & Delim & """ & Y))" ' get unique combined strings
'c) replace range references X and Y with address string
GetFormula = Replace(Replace(Pattern, _
"X", rng.Columns(ITEM).Address(0, 0)), _
"Y", rng.Columns(STATUS).Address(0, 0))
End Function
Function IsValid(uniques, no As Long, _
Optional Exclude As String = "A", _
Optional Delim As String = "-") As Boolean
'a) get prefix of element no (i.e. string part before hyphen)
Dim ItemPrefix As String
ItemPrefix = Split(uniques(no), "-")(0) ' isolate string part before "-" via Split()
'b) filter items to be excluded
Dim tmp
tmp = Filter(uniques, ItemPrefix & Delim & Exclude, True) ' positive filtering of term to be excluded
'c) if there are no found items then return True as function result
If UBound(tmp) = -1 Then ' upper boundary -1 indicates empty 0-based array
IsValid = True ' return positive function result
End If
End Function
I am concatenating every columns of the rows on excel sheet and I am already done with the concatenating of every columns.
My problem is I only need to concatenate the rows that does not contain letter T on column A starting row 3. please see image below
sample formula
=Sheet1!A3&Sheet1!B3&Sheet1!C3&Sheet1!D3&Sheet1!E3&Sheet1!F3&Sheet1!G3&Sheet1!H3&Sheet1!I3&Sheet1!J3&Sheet1!K3&Sheet1!L3&Sheet1!M3&Sheet1!N3&Sheet1
on that image, you can see the result below of the concatenated columns from the above details, but not all the time the rows to be concatenated there has the same number(like on the above image that has only 3 rows to be computed), do you know some code or formula for this matter?
You can try
=TEXTJOIN(A1:N1)
Or whatever your range should be.
But dynamically in VBA it done like this:
Dim row, col As Integer
Dim curStr As String
row = 1
col = 1
curStr = ""
Do While Sheets("Input").Cells(row, col) <> ""
Do While Sheets("Input").Cells(row, col) <> ""
curStr = curStr + Sheets("Input").Cells(row, col)
col = col + 1
Loop
col = 1
Sheets("Output").Cells(row, col) = curStr
row = row + 1
curStr = ""
Loop
Use this UDF - User Defined Function
Function conc(rangetoconc As Range) As String
Dim finalresult As String
Dim cell As Range
finalresult = vbNullString
If InStr(1, rangetoconc.Cells(1, 1), "T") = 0 Then
For Each cell In rangetoconc
If CStr(cell.Value) <> vbNullString And CStr(cell.Value) <> " " Then
finalresult = finalresult & CStr(cell.Value)
End If
Next
End If
conc = finalresult
End Function
I just figured out the answer to my question after reading some excel formula online.
=IF(A1="","",
IF(LEFT(A1,1)="T","",
IF('Sheet1'!A2<>"",'Sheet1'!A2&'Sheet1'!B2&'Sheet1'!C2&'Sheet1'!D2&'Sheet1'!E2&'Sheet1'!F2&'Sheet1'!G2&'Sheet1'!H2&'Sheet1'!I2&'Sheet1'!J2&'Sheet1'!K2&'Sheet1'!L2&'Sheet1'!M2&'Sheet1'!N2&'Sheet1'!O2&'Sheet1'!P2&'Sheet1'!Q2&'Sheet1'!R2&'Sheet1'!S2,"T "&MIN(ROW(A2:A3))+ROWS(A2)-3 & " sum of invoice "& SUM('Sheet1'!H:H))))
I need to retrieve the last but one row value in column A/B(Value in Date)
Ex1: Row 3 : last column is AB. I need Row 3 Column AA value (Date) in Row 3 Column C.
Ex 2: Row 4:last column in AS: I need Column AR value (date) in ROw 4 column C.
Ex 3:Row 5:last column in BC: I need Column BB value (date) in ROw 5 column C.
there can b one or 2 blank values.
Please let me know if there are any excel formula to tackle this scenario.
with iteration you could use an array-formula like: (for row 3)
=INDIRECT("R3C"&MAX(COLUMN(3:3)*(LEN(3:3)>0))-1, 0)
without you need to exclude the cell itself... having it at column C it would be something like: (for row 3)
=INDIRECT("R3C"&MAX(COLUMN($D3:$ZZ3)*(LEN($D3:$ZZ3)>0))-1, 0)
if you want to simply auto fill the formula down then replace the "R3C" with "R"&ROW()&"C"
The formulas shown here are array formulas and must be confirmed with Ctrl+Shift+Enter.
If you get inclined to VBA, you could try something like this:
' In C3 type =GetSecondLastColumnValue()
' This function will keep on checking values on column at a time to the right
' If 3 continuous empty cells are found, it will assume that there are no more
' columns with values after that. The last known cell with value will be identified
' and value of column just to its left will be plugged in to column C
Public Function GetSecondLastColumnValue()
Dim Looper As Integer
Looper = 1
Const NoOfContinuousEmptyColumns As Integer = 3
Dim m_Address As String, m_LastKnownColumnWithValue
m_Address = Selection.Address
m_LastKnownColumnWithValue = m_Address
Do
m_Address = Range(m_Address).Offset(0, 1).Address
If Range(m_Address).Value = "" Then
Looper = Looper + 1
If Looper > NoOfContinuousEmptyColumns Then Exit Do
Else
Looper = 1
m_LastKnownColumnWithValue = m_Address
End If
Loop
m_LastKnownColumnWithValue = Range(m_LastKnownColumnWithValue).Offset(0, -1).Address
GetSecondLastColumnValue = Range(m_LastKnownColumnWithValue).Value
End Function
Example:
A B C D E F
1 abc def ab cd
2 abc def xy zx st
In C1, type =GetSecondLastColumnValue () and it will be populated with ab.
In C2, type the same formula and it will be populated with zx
This is just an example of what you can do with VBA. Do NOT use this function in production. It is insanely greedy and slow. It's just an illustration.
This subroutine is much faster:
' This method keeps on going to far right till it reaches the end of the columns
' Then it comes back to the last column with value, and hops to the column to its left, and remembers its value
' That value goes in column C. It loops through all rows you specify in startrow and endrow
Sub PopulateColumnC()
Dim StartRow As Integer, EndRow As Integer, RowLoop As Integer
StartRow = 1
EndRow = 3
Dim m_Address As String
For RowLoop = StartRow To EndRow
Range("A" & RowLoop).Select
m_Address = Selection.Address
Do
Selection.End(xlToRight).Select
If m_Address = Selection.Address Then
Selection.End(xlToLeft).Select
Exit Do
Else
m_Address = Selection.Address
End If
Loop
m_Address = Range(Selection.Address).Offset(0, -1).Address
Range("C" & RowLoop).Value = Range(m_Address).Value
Next
End Sub
I have wbk1.worksheet(1) and wbk2.worksheet(1).
wbk1.worksheet(1) has a list of values in column A
wbk2.worksheet(2) has the same list of values that may occur multiple times in column A with a number value in the offset(0,1) cell.
I need to do an index or match to find all of values in wbk2 and sum all of the offset(0,1) values. Then take that sum and put it in the offset(0,1) cell in wbk1.worksheets(1).
Example:
Workbook 1, sheet 1
Column A Column B
value 1
value 2
value 3
Workbook 2, sheet 1
Column A Column B
value 1 15
value 2 2
value 1 3
value 1 12
End Result:
Workbook 1, sheet 1
Column A Column B
value 1 30
value 2 2
value 3 0
I've tried doing a for each loop, but I'm still a noob to vb, so clearly not doing something right:
For Each x In rngWbk1
Set cellrngwbk2 = wbk2.Worksheets(1).Cells.Find(What:=x, LookIn:=xlValues)
If Not cellrngwbk2 Is Nothing Then
For Each y In rngwbk1
If y = cellrngwbk2 Then
total = total + cellrngwbk2.Offset(0, 1).Value
Else
End If
Next y
x.Offset(0, 1).Value = total
total = 0 'resets total value for next x value
Else
End If
next x
If VBA is not a requirement, a simple =SUMIF() statement has the same effect.
The function would look something like this:
=SUMIF([Wbk2.xlsx]Sheet1!A2:A5,Table1[[#This Row],[ID]],[Wbk2.xlsx]Sheet1!B2:B5)
There is more efficient way. You can use SUMIF formula to calculate values and then rewrite formula with result values. If rngWbk1 corresponds to the values in column A in wbk1.worksheets(1), you can use following code:
Dim frm As String
Dim startCell As String
startCell = Replace(rngWbk1.Cells(1, 1).Offset(0, -1).Address, "$", "")
frm = "=SUMIF('[" & wbk2.Name & "]" & wbk2.Worksheets(1).Name & "'!A:A," & startCell & ", '[" & wbk2.Name & "]" & wbk2.Worksheets(1).Name & "'!B:B)"
With rngWbk1.Offset(0, 1)
.Formula = frm
.Calculate
.Value = .Value
End With
If rngWbk1 doesn't correspond values in column A, you need to adjust startCell in example to startCell = "A2" and change With rngWbk1.Offset(0, 1) to sth like With wbk1.Worksheets(1).Range("B1:B100")
I have data in (Sheet4) columns A to I:
I'm trying to compare data for all rows (Only on column A and B) to see if any of the rows is duplicated, if it is: excel should highlight both rows.
Example:
A B C......I
s 1 x
s 3 w
e 5 q
s 1 o
Row 1 and 4 should be highlighted as values are the same for column A and B.
I shouldn't modify the sheet (no modification to the columns or rows should be done to the sheet), and the number of rows is not always known (not the same for all files).
Is there an easy way (using macros) to do this???
This is an attempt I have tried, but it is increasing my file to 7MB!!!!! I'm sure there should be an easier way to compare rows for an unknown number of rows and just highlight the dupllicates if they exist:
Public Sub duplicate()
Dim errorsCount As Integer
Dim lastrow As Integer
Dim lastrow10 As Integer
errorsCount = 0
lastrow = Sheet4.Cells(Rows.Count, "A").End(xlUp).Row 'is the row number of the last non-blank cell in the specified column
lastrow10 = lastrow
Sheet10.Range("B1:B" & lastrow10).Value = Sheet4.Range("A1:A" & lastrow).Value
Set compareRange = Sheet10.Range(column + "2:" & Sheet10.Range(column + "2").End(xlDown).Address)
For Each a In Sheet10.Range(column + "2:" & Sheet10.Range(column + "2").End(xlDown).Address)
c = a.Value
If c <> Null Or c <> "" Then
If name = "testing" Then
If WorksheetFunction.CountIf(compareRange, c) > 1 Then
a.Interior.ColorIndex = 3
errorsCount = errorsCount + 1
End If
End If
End If
Next a
If errorsCount > 0 Then
MsgBox "Found " + CStr(errorsCount) + " errors"
Else
MsgBox " No errors found."
End If
End Sub
Silly answer to you.
J1 or just duplicate sheet.
J1 =CONCATENATE(A1,"#",B1) > drag down > J:J > conditional format > highlight cells rules > duplicate values.
(* replace the # to any string which you think not possible in the original A:A and B:B.)
I do this all the time.
To collect all duplicates just SORT with color.