Solved, I made a "MATCH" mistake, thanks all!
I have uncertain number of worksheets every time with uncertain name, but my target worksheet to search is always the 3rd last one
so in VBA I did this UDF:
Function SHEETNAME() As String
Dim L As Long
L = ThisWorkbook.Worksheets.Count
SHEETNAME = Sheets(L - 2).Name
End Function
therefore, calling =SHEETNAME() in my spreadsheet will always return the name of my target worksheet
then unfortunately, the exact value I need is 1 row below what I can reach with VLookup (3rd column)
=VLOOKUP($K$2,INDIRECT("'" & sheetname() & "'!"&"A2:X30"), 3, 0) <--- I need 1 row below this result
so I converted the formula to INDEX + MATCH
=INDEX(INDIRECT("'" & sheetname() & "'!" & "A2:X30"),MATCH($K$2,INDIRECT("'" & sheetname() & "'!" & "A2:A30"),0)+1,3)
somehow, the result of MATCH($K$2,INDIRECT("'" & sheetname() & "'!" & "A2:A30"),0) from F9 is N/A, why....
From A:X you want the third column's value in your VLOOKUP so it's INDEX(C:C, ...) or INDEX(A:X, ..., 3). The VLOOKUP always uses the first column for the lookup so it's going o be MATCH(K2, A:A, 0).
=INDEX(INDIRECT("'" & sheetname() & "'!A2:X30"), MATCH($K$2, INDIRECT("'" & sheetname() & "'!A2:A30"), 0)+1, 3)
Don't complicate INDIRECT strings with $. Nothing is going to change the string.
Related
I am using variable ranges, and want to insert those ranges into a formula that can be saved in a document that does not use VBA.
Do I have to use a with statement?
My If Statement works until I try and insert a relative range. I searched and didn't see much on this, so this issue is probably so simply I am an idiot.
The program will be doing things all over the worksheet, so relative coding is needed. The number of items in the range changes with each iteration. I will be using an end range integer [myRange] for the number instead of 10, but I wanted to simplify what I am struggling with into the smallest steps.
Dim Test As String
Test = "=IF(COUNTIF(" & ActiveCell.Offset(1, 0).Address & ":" & ActiveCell.Offset(10, 0).Address & "" _
& ")," & """Not Complete""" & "," & "" & """"")"
ActiveCell.Formula = Test
Desired output in target cell:
"=IF(COUNTIF($J$3:$J$12),"Not Complete","")"
As mentioned in comments, your COUNTIF statement is currently invalid. What are you counting in the range J3:J12? This needs to be added (in place of "CRITERIA" in below solution) before your equation will be valid
Test = "=IF(COUNTIF(" _
& ActiveCell.Offset(1).Resize(10).Address(True, True) _
& ",""CRITERIA""), ""Not Complete"", """")"
If you want your output to actually have the quotes you can output
Chr(34) & Test & Chr(34) which seems cleaner than wrapping the whole string in quotes from a readability point of view IMO
I have a small macro program that matches values between two worksheets (big data).
I'm using Application.Match method to find the match of a certain value in another worksheet.
The problem is, when I try to assign a row variable on the range, the result gets Row 1 instead of Row 7 where the exact match is.
Application.Match(data1, Worksheets("Data").Range("O" & lRowRange & ":O" & lLastRow), 0)`
lRowRange = 5
If Not IsError(Application.Match(data1, Worksheets("Data").Range("O" & lRowRange & ":O" & lLastRow), 0)) Then
lMatchFound = Application.WorksheetFunction.Match(data1, Worksheets("Data").Range("O" & lRowRange & ":O" & lLastRow), 0)
sDataFound = Sheets("Data").Cells(lMatchFound, 15)
End if
I'm not using LOOP statements to find the match because the worksheets contain large amount of data.
Hope you could help me out. Thanks in advance.
You are looking for a match in O5:O10. If your searched text is in O5, then your match function give you a '1', because it is found in the first cell of your range.
Use
sDataFound = Sheets("Data").Cells(lMatchFound + lRowRange - 1, 15)
and you will be fine.
I have the following formula in excel (created by me in the past),
=IFERROR(INDEX(Tasks!$H$2:$H$65536;SMALL(IF(A2=Tasks!$A$2:$A$65536;ROW(Tasks!$A$2:$A$65536)-ROW(Tasks!$A$2)+1);ROW($1:$1)));"")
The formula is working as I wanted, but in each and every month the a columns are changing, so for example what was Column "A" here can be Column "C" next month and so the number of rows are changing. I'm trying to modify the formula that I don't have to adjust month by month.
For this first I found a VBA script online:
Function Col_Letter(lngCol As Long) As String
Dim vArr
vArr = Split(Cells(1, lngCol).Address(True, False), "$")
Col_Letter = vArr(0)
End Function
So after if I type for example:
=Col_Letter(COLUMN(Table8[[#Headers];[ID]])) it will give me Letter "B" as this header can be found in "B" Column.
So using the advantage of this VBA script I was trying to create a formula what will adjust the column letter in the original formula every time.
So this formula:
=("Tasks!" & "$" & Col_Letter(COLUMN(Table32[[#Headers];[Owned By]])) & "$" & "2" & ":" & "$" & Col_Letter(COLUMN(Table32[[#Headers];[Owned By]])) & "$" & ROW(INDEX(Table32;1;1))+ROWS(Table32)-1) is giving me this as the result Tasks!$H$2:$H$65536.
what is part of the formula so I think it's good.
This is the whole formula I was trying to re-create in this manner:
=Index((("Tasks!" & "$" & Col_Letter(COLUMN(Table32[[#Headers];[Owned By]])) & "$" & ROW() & ":" & "$" & Col_Letter(COLUMN(Table32[[#Headers];[Owned By]])) & "$" & ROW(INDEX(Table32;1;1))+ROWS(Table32)-1);SMALL(IF((((Col_Letter(COLUMN(Table8[[#Headers];[ID]])) & ROW()) & "=" & (("Tasks!" & "$" & Col_Letter(COLUMN(Table32[[#Headers];[ID]])) & "$" & "2"& ":" & "$" & Col_Letter(COLUMN(Table32[[#Headers];[ID]])) & "$" & ROW(INDEX(Table32;1;1))+ROWS(Table32)-1))));Row((("Tasks!" & "$" & Col_Letter(COLUMN(Table32[[#Headers];[ID]])) & "$" & "2"& ":" & "$" & Col_Letter(COLUMN(Table32[[#Headers];[ID]])) & "$" & ROW(INDEX(Table32;1;1))+ROWS(Table32)-1)))-ROW(("Tasks!" & "$" & Col_Letter(COLUMN(Table32[[#Headers];[ID]])) & "$" & "2"))+1);ROWS($1:$1))))
Excel Tables have the potential of resolving such questions easily. Since the Columns can be referred by their names, you do not have to worry where they are located. And likewise, since you reference the data by column name but not row number, your reference will be covering all of the rows within that Table, no matter how many rows are added or deleted.
So as a start, try converting your range to Table by selecting it and use Insert / Table. After this you should convert your formula to contain Table references rather than cell references.
I've seen several questions asked around using INDEX MATCH on multiple criteria within VBA, but they all seem to revolve around pasting a formula into a cell.
I'm looping thru a ListObject and trying to do a lookup on 3 criteria on a diff sheet, but I want the value pasted into the cell not the formula. I've tried using various combos of Application.Index, Application.WorksheetFunction.Index, Application.Match, Application.WorksheetFunction.Match and Evaluate() but I'm still getting #Value! (when I don't get a an Error). Some of what I've tried below (it's prob a very simple mistake I'm making).
wsSrc has the following ranges as part of a ListObject and I want to paste the result onto wsDest.
rngDate = Range("Table24[date]") 'Date
rngFrom = Range("Table24[from]") 'String
rngTo = Range("Table24[to]") 'String
rngLookup = Range("Table24[lookup]") 'Double
Based on a combination of a Date, From and To I want to lookup a value in rngLookup.
I've tried:
Application.Index(rngLookup.Address, _
Application.Match(strDate & "USD" & strTo, _
rngDate.Address & rngFrom.Address & rngTo.Address))
I've also tried:
x = wsSrc.Evaluate("INDEX(" & rngLookup.Address & _
",MATCH(" & strDate & "USD" & strTo & "," & _
rngDate.Address & "&" & rngFrom.Address & "&" & rngTo.Address)
I've even tried converting the date using CStr(CDate()) which works on in Excel, but not in the VBA.
No joy on either, any thoughts? Again, to confirm I want just the value not the formula pasted into a cell.
This worked for me using a table and columns of the same name:
Dim sht As Worksheet, dt, sFrom, sTo
Set sht = ActiveSheet ' e.g.
dt = DateSerial(2017, 12, 18)
sFrom = "B"
sTo = "C"
Debug.Print sht.Evaluate( _
"INDEX(Table24[lookup],MATCH(1," & _
"(Table24[date]=" & (dt * 1) & ")*" & _
"(Table24[from]=""" & sFrom & """)*" & _
"(Table24[to]=""" & sTo & """),0))")
Assumes your table's dates are actual dates and not strings.
Can somebody help me to write this formula in excel VBA?
=IF(ISERROR(VLOOKUP(A3,Temp!$A$3:$A$595,1,FALSE)),A3,"0")
My code is getting stuck with :"syntax error"
Sub checkDuplitems()
Application.ScreenUpdating = False
Const top As Integer = 3
Dim bottom As Long
bottom = Sheets("Temp").Cells(Rows.Count, top).End(xlUp).row
With ThisWorkbook.Sheets("trash").Range("A" & top & ":A" & bottom)
.Formula = "=IF(ISERROR(VLOOKUP(A" & top & ",Temp!$B$" & top & ":$B$" & bottom & _
",1,FALSE)),A" & top & ", & '" 0" & ," '")"
.Value = .Value
.SortSpecial
End With
'Call something...
End Sub
You have a concatenation problem in the second line of the .Formula line.
To emulate the formula you have at the top of your question (which is wrong incidentally because you should be pointing to $B$3:$B$595 or something like that because your look up cell A3 should not be inside the VLOOKUP range).
Try this new .Formula line:-
.Formula = "=IF(ISERROR(VLOOKUP(A" & top & ",Temp!$B$" & top & ":$B$" & bottom & _
",1,FALSE)),A" & top & ", " & "0)"
Are you sure you want to use top as both the starting row in column A and the column to get the bottom row from the Temp worksheet? The important column on the Temp worksheet is column B (i.e. 2) not C (i.e. 3).
If you are putting formula(s) into Trash!A3:A595 that reference Trash!A3:A595 then these are circular references and cannot be resolved under normal conditions. I'll put the formulas into column Z.
If you are operating with Excel 2007 or newer then I would humbly propose this alternate that uses the worksheet's IFERROR function and does not attempt to make text out of the 0 returned value.
Const top As Integer = 3
Dim bottom As Long
bottom = Sheets("Temp").Cells(Rows.Count, "B").End(xlUp).Row '<~~change here
With ThisWorkbook.Sheets("trash")
With .Range("Z" & top, .Cells(Rows.Count, "A").End(xlUp).Offset(0, 25))
.Formula = "=IFERROR(VLOOKUP(A" & top & ", Temp!$B$" & top & ":$B$" & bottom & _
", 1, FALSE), 0)" '<~~ big change here
.Value = .Value
End With
End With
It is also curious as to why the number of rows of formulas in the Trash worksheet must be governed by the number of rows of data in the Temp worksheet. I would have thought that the number of values in column A of the Trash sheet should govern how many formulas go into the Trash worksheet.