VLookup cannot find match - excel

I try to perform VlookUp using VBA. Specifically I want to find Open prices for each Date (picture attached). But my code fails to find any matches. I Guess i have messed up ranges for vlookup but I cannot find the mistake.
Sub VlookUp()
Dim goalsWs As Worksheet, dataWs As Worksheet
Dim goalsLastRow As Long, dataLastRow As Long, x As Long
Dim dataRng As Range
Set goalsWs = ThisWorkbook.Worksheets("[FULL_TABLE][1]")
Set dataWs = ThisWorkbook.Worksheets("BTC-USD")
goalsLastRow = goalsWs.Range("A" & Rows.Count).End(xlUp).Row
dataLastRow = dataWs.Range("A" & Rows.Count).End(xlUp).Row
Set dataRng = dataWs.Range("A2:G" & dataLastRow)
For x = 2 To goalsLastRow
On Error Resume Next
goalsWs.Range("B" & x).Value = Application.WorksheetFunction.VlookUp( _
goalsWs.Range("A" & x).Value, dataRng, 4, False)
Next x
End Sub
I want to find Open prices from BTC-USD for each Date in FULL_TABLE

The problem was in the data type " the Excel worksheet function gets confused with the array of VBA dates which are always US-centric.
As suggested convert the dates to intrinsic values which you can do simply with the Value2 property, eg x = Range("Source").Value2"
So simply adding (2) after (value) has fixed the problem
goalsWs.Range("A" & x).Value2, dataRng, 4, False)

Related

How does the VLOOKUP and VALUE syntax work in VBA?

Suppose that I have a range of data in Column A that is in text format, first I want to change the format of data to number/value.
The code I came up with is:
Method 1:
Sub Test123()
Dim data As String
Dim count As Integer
Dim rowNo As Integer
Dim answer As String
rowNo = Range("A1").End(xlDown).Row
For count = 2 To rowNo
data = Range("A" & count).Value
Range("B" & count).Formula = "=VLOOKUP(VALUE(data),Table1,2,FALSE)"
Next count
Method 2:
answer = Application.WorksheetFunction.VLookup(data2, Sheet1!Table1, 2, False)
Range("B" & count).Value = answer
The correct answer given by my tutor is
Range("B" & count).Formula = "=VLOOKUP(VALUE(A" & count & "),Table1,2,FALSE)"
Question 1: Why do my methods not working?
Question 2: I can't seem to figure out the underlying syntax VALUE(A" & count & ") here. Could anyone please help me to understand? Also, is there a repository where I can read more about these syntax?
Please, test the next way. The way of VLookup using will generate an array which will be dropped in the necessary range:
Sub Test123()
Dim sh As Worksheet, rowNo As Long, rngA As Range, rngB As Range
Dim rngTbl As Range, tbl As ListObject
Set sh = ActiveSheet
Set tbl = sh.ListObjects("Table25") 'my tested table...
'Please, use here your real one name!
Set rngTbl = tbl.DataBodyRange
rowNo = sh.Range("A" & sh.rows.count).End(xlUp).row
Set rngA = sh.Range("A2:A" & rowNo)
Set rngB = sh.Range("B2:B" & rowNo)
rngB.value = Application.VLookup(rngA, rngTbl, 2, False)
'If liking a more fancy way, to return what you want in case of
' no match (instead of `#N/A`), please uncomment the next line:
'rngB.value = Application.IfNa(Application.VLookup(rngA, rngTbl, 2, False), "Ups...")
End Sub
The above code should be considered as an improved version...
As mentioned in my comment, data is a simple string in the way you try it. It should be used in the next way: "=VLOOKUP(VALUE(" & data & "),Table1,2,FALSE)", to make the code considering data a variable...

My VBA code .Range is not working as intended

Column B9:B65 has a combobox in Sheet 1 that has values between A1 to K3 and L1 to W2 that a user can select from.
For example, the user can select values from A1,A2,A3,B1,B2,B3,.....,K1,K2,K3,L1,L2,M1,M2,N1,N2,O1,O2,.......,V1,V2,W1 and W2.
Not necessary be in sequence. Can be in any order but will always be between A1 to W2.
The data for this is in Sheet 2 in Column B2:B56.
My requirement is to have 2 separate buttons to clear contents of column B in Sheet 1.
First button should clear values A1 to K3 from any where in column B9:B65 in sheet 1
Second button should clear values L1 to W2 from any where in column B9:B65 in sheet 1
For First button, I wrote the code below referring google, as I am new to VBA.
'Define variables that are to be used in the program
Dim ws1 As Worksheet, ws2 As Worksheet
Dim ws1LastRow As Long, ws2LastRow As Long, x As Long
Dim ws2Rng As Range
Dim wsf As WorksheetFunction: Set wsf = Application.WorksheetFunction
Dim strData As String
'Set ws1 and ws2 variable to the respective worksheets.
Set ws1 = ThisWorkbook.Worksheets(1)
Set ws2 = ThisWorkbook.Worksheets(2)
'Assign values to ws1LastRow and ws2LastRow
ws1LastRow = ws1.Range("B" & Rows.Count).End(xlUp).Row
ws2LastRow = 34 'Hardcoded as A1 to K3 is in between B2:B34
'To display values assigned to the variables use Debug.Print and get the results displayed in Immediate Window that gets populated using 'Ctrl+G'
Debug.Print ws1LastRow
Debug.Print ws2LastRow
'Set ws2Rng with the range from ws2 sheet that you want to compare
Set ws2Rng = ws2.Range("B2:B" & ws2LastRow)
For x = 9 To ws1LastRow
On Error Resume Next 'To avoid 1004 error.
ws1.Range("B" & x).value = wsf.VLookup(ws1.Range("B" & x).value, ws2Rng, 2, 0)
'Used for Debugging
'strData = Join(wsf.Transpose(ws2Rng.value), ",")
'Debug.Print strData
If (ws1.Range("B" & x).value = wsf.VLookup(ws1.Range("B" & x).value, ws2Rng, 2, False)) Then
ws1.Range("B" & x).ClearContents ' I have to figure out a way to clearcontents of row 'B & x : K &
x' with single line operation.
'Debug.Print x
End If
Next x
End Sub
I want to clear content with single line such as ws1.Range("B" & x : "K" & x).ClearContents I am sure there is no such syntax but this is to give an idea of what I want to attain. Please suggest alternatives if any.
Debugging above code using F8, I found ws1.Range("B" & x).value = wsf.VLookup(ws1.Range("B" & x).value, ws2Rng, 2, 0) line Vlookup returns empty value so ws1.Range("B" & x).value = empty
I am stuck here and looking for a reason as to why my code doesn't work.
If there is more efficient way that meets the requirements, I will be more than happy to implement it. But at the same time I am curious to know the fault in this code.

Error returned while using Index and Match formula

I am trying to use Index and Match to lookup a value on another worksheet within the same workbook, but I keep getting an error returned. (error 2042) I know I can do this using a formula, (see pic) but I'd like to use code. Does anyone mind taking a look?
Dim WorkOrderDashboardCell As Range
Dim ProjectList As Worksheet
Dim ProjectNumber As String
Set ProjectList = Worksheets("Project List")
ProjectList.Activate
'We need to start by initializing values on the project list
With ProjectList
Dim LastRowProjectListSpreadsheet As Long
LastRowProjectListSpreadsheet = .Range("B" & Rows.Count).End(xlUp).Row
Dim ProjectListNumbers As Range
Set ProjectListNumbers = .Range("B2:B" & LastRowProjectListSpreadsheet)
Dim ProjectListProjectNumber As Integer
ProjectListProjectNumber = 2
End With
'Switch back to the Dashboard spreadsheet
DashBoard.Activate
Dim DashboardWorkOrderRange As Range
Set DashboardWorkOrderRange = DashBoard.Range("E17:E" & LastRowProjectListSpreadsheet)
For Each WorkOrderDashboardCell In Range("E17:E" & Rows.Count).End(xlUp).Row
ProjectNumber = Application.Index(ProjectListNumbers, Application.Match(WorkOrderDashboardCell, DashboardWorkOrderRange, 0))
Debug.Print ProjectNumber
Next
To use worksheet functions, use code like:
WorksheetFunction.Index
rather than:
Application.Index
You might also need to use the Address property of your ranges, like:
ProjectListNumbers.Address
I think this line here is incorrect:
For Each WorkOrderDashboardCell In Range("E17:E" & Rows.Count).End(xlUp).Row
You are trying to loop within a range, but this part of the aforementioned line returns a row number not a range of cells:
Range("E17:E" & Rows.Count).End(xlUp).Row
Change it to a range of cells.
Application.Match
In your code you are using
Set DashboardWorkOrderRange = DashBoard.Range("E17:E" & LastRowProjectListSpreadsheet) where LastRowProjectListSpreadsheet is possibly the wrong last row. Also you are using
For Each WorkOrderDashboardCell In Range("E17:E" & Rows.Count).End(xlUp).Row where Range("E17:E" & Rows.Count).End(xlUp).Row is a row (instead of a range). Finally you are using Application.Filter without testing the result of Application.Match. Some other issues are the unnecessary use of Activate and the use of long variable names the latter seriously affecting the readability of the code.
This is your code revised. When running it you will see that it makes little sense (mentioned in the comments).
I'm posting it for you only to maybe easier find out what you really want to do.
It is illustrating how the result of Application.Match should always be tested with IsNumeric (or IsError) and that you don't have to (in this case, should not) use Application.Index, but just the Cells property of the range object with the index returned by Application.Match, to return the desired value.
The Code
Option Explicit
Sub LittleSense()
Dim wb As Workbook: Set wb = ThisWorkbook ' Workbook containing this code.
Dim LastRow As Long
Dim plRng As Range
With wb.Worksheets("Project List")
LastRow = .Range("B" & .Rows.Count).End(xlUp).Row
Set plRng = .Range("B2:B" & LastRow)
End With
Dim dbRng As Range
With wb.Worksheet("Dashboard")
LastRow = .Range("E" & .Rows.Count).End(xlUp).Row
dbRng = .Range("E17:E" & LastRow)
End With
Dim cel As Range
Dim dbIndex As Variant
Dim plValue As Variant
For Each cel In dbRng.Cells
dbIndex = Application.Match(cel, dbRng, 0)
' You might as well do:
'dbIndex = dbIndex + 1
If IsNumeric(dbIndex) Then ' Not necessary: all values will be found.
plValue = plRng.Cells(dbIndex).Value
Debug.Print plValue & " (" & dbIndex & ")"
Else
' Not necessary: all values will be found.
Debug.Print "Not found " & "(""" & cel.Value & """)"
End If
Next cel
End Sub

want to convert Excel formula into VBA code

I wanted to convert below formula to VBA code.
=C1&"`"&K1&"`"&L1&"`"&J1
=VLOOKUP(M1,Data!$A:$J,9,)
=SUMPRODUCT(SUMIF(B1:B,B1,G1:G))
Currently i have enter this formula in 1st row and than copying this formula till the last row used which is taking lot time to apply formula because it has more than million row.
LR1 = Sheets("CRIMS").UsedRange.Rows.Count
Sheets("CRIMS").Range("M1:P1").AutoFill Destination:=Sheets("CRIMS").Range("M1:P" & LR1)
is there any way to convert this formula into VBA code?
For first formula the easiest way would be:
Range("M" & i).FormulaR1C1 = "=RC[-10]&""`""&K&""`""&L&""`""&J"
But for vlookup I prefer dictionaries/collections! It is much much faster.
If You have source data in Data sheet and You want to put that to CRIMS sheet to column M:
Sub vlookup()
Dim names As Range, values As Range
Dim lookupNames As Range, lookupValues As Range
Dim vlookupCol As Object
Dim lastRow As Long
Dim lastRow2 As Long
Dim objekt as Object
With Sheets("Data")
lastRow = Sheets("Data").Cells(Rows.Count, 1).End(xlUp).row
Set names = Sheets("Data").Range("A1:A" & lastRow)
Set values = Sheets("Data").Range("I1:A" & lastRow)
End With
Set objekt = BuildLookupCollection(names, values)
With Sheets("CRIMS")
lastRow2 = 1000000
Set lookupNames = .Range("M1:M" & lastRow)
Set lookupValues = .Range("N1:N" & lastRow)
End With
VLookupValues lookupNames, lookupValues, objekt
Set objekt = Nothing
End Sub
Function BuildLookupCollection(categories As Range, values As Range)
Dim vlookupCol As Object, i As Long
Set vlookupCol = CreateObject("Scripting.Dictionary")
On Error Resume Next
For i = 1 To categories.Rows.Count
Call vlookupCol.Add(CStr(categories(i)), values(i))
Next i
On Error GoTo 0
Set BuildLookupCollection = vlookupCol
End Function
Sub VLookupValues(lookupCategory As Range, lookupValues As Range, vlookupCol As Object)
Dim i As Long, resArr() As Variant
ReDim resArr(lookupCategory.Rows.Count, 1)
For i = 1 To lookupCategory.Rows.Count
resArr(i - 1, 0) = vlookupCol.Item(CStr(lookupCategory(i)))
Next i
lookupValues = resArr
End Sub
Quotation Marks need to be doubled in VBA
Try this:
For i = 1 To LR1
Range("M" & i).Formula = "=C" & i & "&""`""&K" & i & "&""`""&L" & i & "&""`""&J" & i
Range("N" & i).Formula = "=VLOOKUP(M" & i & ",Data!$A:$J,9,)"
Next i
(replace column letters with actual target column)
As mentioned in the comments Looping in this case is highly inefficient.
Use this Code to insert the formulas all at once. It still takes some time for 1 Milion rows though.
Range("M1:M" & LR1).Formula = "=C:C & ""`"" & K:K & ""`"" & L:L & ""`"" & J:J"
Range("N1:N" & LR1).Formula = "=VLOOKUP(M:M,Data!$A:$J,9,)"

Excel VBA offset function

I have an Excel file with information in column A and column B. Since these columns could vary in the number of rows I would like to use the function offset so that I could print the formula in one time as an array rather than looping over the formula per cell (the dataset contains almost 1 million datapoints).
My code is actually working the way I want it to be I only can't figure out how to print the code in Range(D1:D5). The outcome is now printed in Range(D1:H1). Anybody familiar how to use this offset within a for statement?
Sub checkOffset()
Dim example As Range
Dim sht As Worksheet
Dim LastRow As Long
Set sht = ThisWorkbook.Worksheets("Sheet1")
LastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
Set example = Range("A1:A1")
For i = 1 To LastRow
example.Offset(0, i + 2).Formula = "=SUM(A" & i & ":B" & i & ")"
Next i
End Sub
Using the Offset(Row, Column), you want to offset with the increment of row (i -1), and 3 columns to the right (from column "A" to column "D")
Try the modified code below:
Set example = Range("A1")
For i = 1 To LastRow
example.Offset(i - 1, 3).Formula = "=SUM(A" & i & ":B" & i & ")"
Next i
One way of outputting the formula in one step, without looping, to the entire range, is to use the R1C1 notation:
Edit: Code modified to properly qualify worksheet references
Option Explicit
Sub checkOffset()
Dim example As Range
Dim sht As Worksheet
Dim LastRow As Long
Set sht = ThisWorkbook.Worksheets("Sheet1")
With sht
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
Set example = .Range(.Cells(1, 1), .Cells(LastRow, 1))
End With
example.Offset(columnoffset:=3).FormulaR1C1 = "=sum(rc[-3],rc[-2])"
End Sub
You don't need to use VBA for this. Simply type =sum(A1:B1) in cell D1 and then fill it down.
If you're going to use VBA anyway, use this:
Sub checkOffset()
Dim example As Range
Dim sht As Worksheet
Dim LastRow As Long
Set sht = ThisWorkbook.Worksheets("Sheet1")
LastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
Set example = Range("A1:A1")
For i = 1 To LastRow
example.Offset(i - 1, 3).Formula = "=SUM(A" & i & ":B" & i & ")"
Next i
End Sub
The way offset works is with row offset, column offset. You want the column to always be fixed at 3 to the right.

Resources