Date lookup issue: Unable to get VLookup property of WorksheetFunction class - vba

I've tried almost everything in most of the other similar type questions but I can't seem to solve the runtime error. Help please!
What I want to achieve:
1) My macro is supposed to get date from report summary files that are created every day hence, it requires the user to input which date of report he wants the data from
2) I use the vlookup method to get the data from the relevant row and input it into the central workbook with the macro
3) Every part of the code works except using the date to Vlookup and it will give me this error message
4) I have tested the code using other text based lookup values and the whole macro works (i.e. i looked up the row which has the "Total" value so it looks up "Total" but i require the macro to look up the rows with the date as the look up value)
Addtional Info:
1) In the lookup file, the dates are in the format of "m/d/yyyy" but presented in the format of "dd-mmm-yy" (but i've tried both and they dont work)
Sub GetData()
Dim strDate As Date
strDate = InputBox("Input date of report to retrieve (Format: DD-MM-YYYY)", "Input Date", Format(Now(), "DD-MM-YYYY"))
If IsDate(strDate) Then
'there is some code here not relevant but basically i need to keep manipulating the date throughout the code
With ActiveSheet
Dim XstrDate
Dim Xfile As String
XstrDate = Format(strDate, "mmm DD, YYYY")
Xfile = "C:\...\...\...\Report " & XstrDate & ".xls"
Dim wb As Workbook
Dim ws As Worksheet
Dim rng As Range
Dim returnValue as Variant
Set wb = Application.Workbooks.Open(Xfile)
Set ws = wb.Worksheets("Summary")
Set rng = ws.Range("A:K")
Dim Xdate As String
Xdate = Format(XstrDate, "m/d/yyyy")
returnValue = Application.WorksheetFunction.VLookup(Xdate, rng, 2, 0)
'... more code
remember, i've tried looking up using the text in the same column and it returned me a value. So i suspect the problem lies with the date format or something
Any smart and kind soul want to offer some suggestions here:)

Excel internally stores dates as a Serial Number (e.g. 1/1/2014 = 41640), which you can observe yourself if you enter a date into a cell and then change the format to Number.
With this in mind it's unlikely that a VBA date and an Excel date can be matched using the VLookup function so in my experience the best solution is to convert your date into its serial number and then perform the VLookup on that value instead.
Dim Ndate As Long
Dim returnValue As Date
Ndate = DateSerial(<Year>, <Month>, <Day>)
returnValue = Application.WorksheetFunction.VLookup(Ndate, <rng>, <col>, False)
If you need to construct your DateSerial(...) function from a Date variable in VBA you can use the Year(<date>), Month(<date>), and Day(<date>) functions to break it down into the required components.
Note: I've tried this example in the format .VLookup(DateSerial(2014,1,1),...) and it still causes the same error, hence storing the return value of DateSerial in a numeric variable first.
Happy Coding!

I've taken a different approach and found another solution to this problem.
Rather than use Vlookup, this is the other method that bypass the problem of VLookup date format problem, (having defined vdate in previous statements)
Dim rnge As Range, i As Long
Sheets("Summary").Select
Columns("A:A").Select
Set rnge = Intersect(Selection, ActiveSheet.UsedRange)
If rnge Is Nothing Then
MsgBox "Date Not Found"
GoTo done
End If
For i = rnge.Count To 1 Step -1
If rnge.Cells(i).Value = vdate Then rnge.Cells(i).EntireRow.Copy _
Destination:=ThisWorkbook.Sheets("AnotherSheet").Range("A1")
Next
done:
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True

Related

VBA Form - Vlookup cell and assign value to that cell

Encountering an issue in a VBA regarding vlookup function.
I have 2 comboboxes and 6 Textboxs for user input.
I want to use a vlookup (or index,Match(),Match()) to look up a cell in a data table and assign the values from the textboxes to these cells.
When I run the code for what I believe should work, it is returning object errors.
Private Sub CommandButton2_Click()
Dim MonthlyTable As Range
Set MonthlyTable = Sheets("DATA Monthly").Range("A6:AE400")
Dim ColumnRef As Range
Set ColumnRef = Sheets("Drivers").Range("N11")
' Assign CB2 value to M11 cell reference so it can be converted to a column ref in N11.
Sheets("Drivers").Range("M11").Value = ComboBox2.Value
Dim CB1Value As String
CB1Value = "Joiners" & ComboBox1.Value
Dim CB2Value As String
CB2Value = ComboBox2.Value
MsgBox CB1Value & " " & CB2Value
Dim tb1value As Range
tb1value = Application.WorksheetFunction.VLookup(CB1Value, MonthlyTable, ColumnRef, False)
tb1value.Value = TextBox1.Value
Unload Me
End Sub
I am at a loss for what to do here as I feel like it should be this simple!
Thanks in advance.
Edit. Further digging indicates that you cannot select a cell you are vlookup'ing as this commands only returns a value it does not actually select the cell for my intents and purposes.
not really clear to me you actual aim, but just following up your desire as stated by:
I want to use a vlookup (or index,Match(),Match()) to look up a cell
in a data table and assign the values from the textboxes to these
cells
you may want to adopt the following technique:
Dim tb1value As Variant '<--| a variant can be assigned the result of Application.Match method and store an error to be properly cheeked for
tb1value = Application.Match(CB1Value, MonthlyTable.Column(1), 0) '<--| try finding an exact match for 'CB1Value' in the first column of your data range
If Not IsError(tblvalue) Then MonthlyTable(tb1value, columnRef.Value).Value = TextBox1.Value '<--| if successful then write 'TextBox1' value in data range cell in the same row of the found match and with `columnRef` range value as its column index
Excel uses worksheet functions to manipulate data, VBA has different tools, and when you find yourself setting cell values on a sheet via VBA so that some worksheet function can refer to them it is time to look for a true VBA solution. I suggest the following which, by the way, you might consider running on the Change event of Cbx2 instead of a command button.
Private Sub Solution_Click()
' 24 Mar 2017
Dim MonthlyTable As Range
Dim Rng As Range
Dim Lookup As String
Dim Done As Boolean
Set MonthlyTable = Sheets("DATA Monthly").Range("A2:AE400")
' take the lookup value from Cbx1
Lookup = ComboBox1.Value
Set Rng = MonthlyTable.Find(Lookup)
If Rng Is Nothing Then
MsgBox Chr(34) & Lookup & """ wasn't found.", vbInformation, "Invalid search"
Else
With ComboBox2
If .ListIndex < 0 Then
MsgBox "Please select a data type.", vbExclamation, "Missing specification"
Else
TextBox1.Value = MonthlyTable.Cells(Rng.Row, .ListIndex + 1)
Done = True
End If
End With
End If
If Done Then Unload Me
End Sub
There are two points that need explanation. First, the form doesn't close after a rejected entry. You would have to add a Cancel button to avoid an unwanted loop where the user can't leave the form until he enters something correct. Note that Done is set to True only when the search criterion was found And a value was returned, and the form isn't closed until Done = True.
Second, observe the use of the ListIndex property of Cbx2. All the items in that Cbx's dropdown are numbered from 0 and up. The ListIndex property tells which item was selected. It is -1 when no selection was made. If you list the captions of your worksheet columns in the dropdown (you might do this automatically when you initialise the form) there will be a direct relationship between the caption selected by the user (such as "Joiners") and the ListIndex. The first column of MonthlyTable will have the ListIndex 0. So you can convert the ListIndex into a column of MonthlyTable by adding 1.
I think it is better to use "find" in excell vba to select a cell instead of using vlookup or other methods.

Reading a barcode in excel to see if there is a match

I am working with Excel 2016. I have a smidgen of experience with VBA for applications, and some experience with programming.
I'm trying to take input from a barcode scanner, compare it to a column in a spreadsheet, and if there's a match, put a few characters and a date stamp in some cells (Initials and date, each in separate columns).
This question has a very similar use-case, and includes a code sample. I have tried the code sample and can't get it to work. At first, there was a problem with the array. Eventually I figured out you could do "C2:C8" and that seemed to work, though that's not documented anywhere (Probably part of a basics course/class, but not findable). There was an error about sub or function defined for Match(), so I enabled the Solver Add-in in the security center. That didn't fix it, so I found this forum post that explained Match wasn't a VBA function.
Now, I get an error after clicking the button "Run time error 1004, unable to get Match property of the WorksheetFunction class", clicking debug takes me to the same line.
Here is the code I have wound up with:
Private Sub CommandButton1_Click()
code = InputBox("Please scan a barcode and hit enter if you need to")
matchedCell = Application.WorksheetFunction.Match(code, Range("C2:C8"), 0)
matchedCell.Offset(0, 2) = Now
End Sub
This is incredibly frustrating because I thought this was a simple thing and already solved. Instead of working to solve the problem and build software, it seems I'm fighting syntax and/or the environment. What am I doing wrong?
two possibilities:
use Match() function of Application object
and store its returned value in a Variant variable to be checked for any error (if value not found)
Private Sub CommandButton1_Click()
Dim code As Variant
Dim matchedCell As Variant
code = InputBox("Please scan a barcode and hit enter if you need to")
matchedCell = Application.Match(code, Range("C2:C8"), 0)
If Not IsError(matchedCell) Then Range("C2:C8").Cells(matchedCell, 1).Offset(0, 2).Value = Now
End Sub
use Find() function of Range object
Private Sub CommandButton1_Click()
Dim code As Variant
Dim matchedCell As Range
code = InputBox("Please scan a barcode and hit enter if you need to")
Set matchedCell = Range("C2:C8").Find(what:=code, LookIn:=xlValues, lookat:=xlWhole, MatchCase:=True)
If Not matchedCell Is Nothing Then matchedCell.Offset(0, 2).Value = Now
End Sub
Use Application.Match , and continue running your code only if there is a successful Match.
Option Explicit
Private Sub CommandButton1_Click()
Dim MatchRow As Variant
Dim code As Variant
Dim matchedCell As Range
code = InputBox("Please scan a barcode and hit enter if you need to")
' verify that there is a successful match in the searched range
If Not IsError(Application.Match(code, Range("C2:C8"), 0)) Then
MatchRow = Application.Match(code, Range("C2:C8"), 0) '<-- get the row number
Set matchedCell = Range("C" & MatchRow + 1) '<-- set the range (add 1 row since you are starting from row 2)
matchedCell.Offset(0, 2).Value = Now
'option 2: without setting the range
Range("C" & MatchRow).Offset(1, 2).Value = Now
End If
End Sub

Object Required Error VBA Function

I've started to use Macros this weekend (I tend to pick up quickly in regards to computers). So far I've been able to get by with searching for answers when I have questions, but my understanding is so limited I'm to a point where I'm no longer understanding the answers. I am writing a function using VBA for Excel. I'd like the function to result in a range, that can then be used as a variable for another function later. This is the code that I have:
Function StartingCell() As Range
Dim cNum As Integer
Dim R As Integer
Dim C As Variant
C = InputBox("Starting Column:")
R = InputBox("Starting Row:")
cNum = Range(C & 1).Column
Cells(R, cNum).Select
The code up to here works. It selects the cell and all is well in the world.
Set StartingCell = Range(Cell.Address)
End Function
I suppose I have no idea how to save this location as the StartingCell(). I used the same code as I had seen in another very similar situation with the "= Range(Cell.Address)." But that's not working here. Any ideas? Do I need to give more information for help? Thanks for your input!
Edit: I forgot to add that I'm using the InputBox to select the starting cell because I will be reusing this code with multiple data sets and will need to put each data set in a different location, each time this will follow the same population pattern.
Thank you A.S.H & Shai Rado
I've updated the code to:
Function selectQuadrant() As Range
Dim myRange As Range
Set myRange = Application.InputBox(Prompt:="Enter a range: ", Type:=8)
Set selectQuadrant = myRange
End Function
This is working well. (It appears that text is supposed to show "Enter a range:" but it only showed "Input" for the InputBox. Possibly this could be because I'm on a Mac?
Anyhow. I was able to call the function and set it to a new variable in my other code. But I'm doing something similar to set a long (for a color) so I can select cells of a certain color within a range but I'm getting all kinds of Object errors here as well. I really don't understand it. (And I think I'm dealing with more issues because, being on a mac, I don't have the typical window to edit my macros. Just me, basically a text box and the internet.
So. Here also is the Function for the Color and the Sub that is using the functions. (I've edited both so much I'm not sure where I started or where the error is.)
I'm using the functions and setting the variables to equal the function results.
Sub SelectQuadrantAndPlanets()
Dim quadrant As Range
Dim planetColor As Long
Set quadrant = selectQuadrant()
Set planetColor = selectPlanetColor() '<This is the row that highlights as an error
Call selectAllPlanets(quadrant, planetColor)
End Sub
This is the function I'm using to select the color that I want to highlight within my range
I would alternately be ok with using the interior color from a range that I select, but I didn't know how to set the interior color as the variable so instead I went with the 1, 2 or 3 in the input box.
Function selectPlanetColor() As Long
Dim Color As Integer
Color = InputBox("What Color" _
& vbNewLine & "1 = Large Planets" _
& vbNewLine & "2 = Medium Planets" _
& vbNewLine & "3 = Small Planets")
Dim LargePlanet As Long
Dim MediumPLanet As Long
Dim smallPlanet As Long
LargePlanet = 5475797
MediumPlanet = 9620956
smallPlanet = 12893591
If Color = 1 Then
selectPlanetColor = LargePlanet
Else
If Color = 2 Then
selectPlanetColor = MediumPlanet
Else
If Color = 3 Then
selectPlanetColor = smallPlanet
End If
End If
End If
End Function
Any help would be amazing. I've been able to do the pieces individually but now drawing them all together into one sub that calls on them is not working out well for me. Thank you VBA community :)
It's much simpler. Just
Set StartingCell = Cells(R, C)
after getting the inputs, then End Function.
The magic of the Cells method is it accepts, for its second parameter, both a number or a character. That is:
Cells(3, 4) <=> Cells(3, "D")
and
Cells(1, 28) <=> Cells(3, "AB")
One more thing, you can prompt the user directly to enter a range, with just one input box, like this:
Dim myRange as Range
Set myRange = Application.InputBox(Prompt:="Enter a range: ", Type:=8)
The Type:=8 specifies the input prompted for is a Range.
Last thing, since you are in the learning process of VBA, avoid as much as possible:
using the Select and Activate stuff
using unqualified ranges. This refers to anywhere the methods Cells(..) or Range(..) appear without a dot . before them. That usually leads to some random issues, because they refer to the ActiveSheet, which means the behavior of the routine will depend on what is the active worksheet at the moment they run. Avoid this and always refer explicitly from which sheet you define the range.
Continuing your line of thought of selecting the Range bu Selecting the Column and Row using the InputBox, use the Application.InputBox and add the Type at the end to restrict the options of the user to the type you want (Type:= 1 >> String, Type:= 2 >> Number).
Function StartingCell Code
Function StartingCell() As Range
Dim cNum As Integer
Dim R As Integer
Dim C As Variant
C = Application.InputBox(prompt:="Starting Column:", Type:=2) '<-- type 2 inidcates a String
R = Application.InputBox(prompt:="Starting Row:", Type:=1) '<-- type 1 inidcates a Number
Set StartingCell = Range(Cells(R, C), Cells(R, C))
End Function
Sub TestFunc Code (to test the function)
Sub TestFunc()
Dim StartCell As Range
Dim StartCellAddress As String
Set StartCell = StartingCell '<-- set the Range address to a variable (using the function)
StartCellAddress = StartCell.Address '<-- read the Range address to a String
End Sub

Confusing dd/mm/yyyy and mm/dd/yyyy

I have a VBA script that opens up a bunch of CSV files, and compiles them into one summary report.
However, I'm having a problem where it reads in UK style dates (dd/mm/yyyy), then interprets them as US-style dates when it makes the copy, before display them as UK-style dates again!
So 4th of July in original sheet becomes 7th of April in the summary sheet - verified by changing cell format to display month name.
This is odd, as when you open up the CSV file in Excel, it correctly interprets the UK style date.
Copy is made using code like this
SummarySheet.Cells(Y,X).value = CSVSheet.Cells(W,Z).value
What is going on here?
You did not post the code as to how you are opening your CSV files -- that is the critical area. The dates need to be parsed properly BEFORE being entered on the worksheet. The following code will selects and then opens a file that has UK style dates in a single column, and properly parse them. You will need to adapt it to your particular requirements.
The FieldInfo argument is what does the work. The formatting of the Excel worksheet is "for show" so you can see an unambiguous date.
Option Explicit
Sub OpenUKcsv()
Dim sFile As String
Dim WB As Workbook
Dim WS As Worksheet
sFile = Application.GetOpenFilename()
Workbooks.OpenText Filename:=sFile, DataType:=xlDelimited, comma:=True, other:=False, _
fieldinfo:=Array(1, 4)
Set WB = ActiveWorkbook
Set WS = ActiveSheet
With WS.Columns(1)
.NumberFormat = "dd-mmm-yyyy"
.EntireColumn.AutoFit
End With
End Sub
You could use .Text (text displayed in Excel cell) or .Value2 (value without formatting) instead of .Value (value with formatting).
But I strongly suggest that you set the format of the cells that you use to what you expect to have at the end with .NumberFormat = "mm/dd/yyyy"
Or you could use CDate function :
SummarySheet.Cells(Y,X).value = CDate(CSVSheet.Cells(W,Z).value)
Or use an UDF with DateSerial :
Sub test_CMaster()
MsgBox ParseDate("4/7/15") & vbCrLf & CDate("4/7/15")
End Sub
Function ParseDate(ByVal DateInCell As String, Optional Separator As String = "/") As Date
Dim D() As String
D = Split(DateInCell, Separator)
ParseDate = DateSerial(D(UBound(D)), D(1), D(0))
End Function
Try using the Workbooks.OpenText() method instead and set the Local flag to True
Set csvWB = Workbooks.OpenText(Filename:=myCSVfile, Local:=True)
Here is the MSDN article on this method which says for the Local setting:
Specify True if regional settings of the machine should be used for separators, numbers and data formatting.
Maybe you can convert the CSV files to show dates as numbers, ie. 10th Nov 15 will show as 42318. Or add a separate column where B1 is =DATEVALUE(A1) and work with that.
When you create the summary report, import the numbers and convert them to date using CDate and Format. Something like this:
Sub test()
Range("A2:A4").NumberFormat = "m/d/yyyy"
Range("A2").Value = Format(CDate(Range("A1").Value), "dd.mm.yyyy")
Range("A3").Value = Format(CDate(Range("A1").Value), "mm.dd.yyyy")
Range("A4").Value = Format(CDate(Range("A1").Value), "Long Date")
End Sub
EDIT:
For better formatting (no need for NumberFormat, I think it will use your regional settings right away) and auto-setting the cell format to date-type, use this:
Sub test()
Dim sDate As Date
sDate = CDate(Range("A1").Value)
Range("A2").Value = DateSerial(Year(sDate), Month(sDate), Day(sDate))
End Sub
Result:
References:
http://www.techonthenet.com/excel/formulas/format_date.php
http://www.techonthenet.com/excel/formulas/cdate.php

Why am I getting this error: Object Variable or With block variable not set?

I have found out what causes this error but I cannot pinpoint where it is coming from in my code. I even tested this macro in a separate worksheet in excel and it worked but in this worksheet it is not working. Can anyone guess as to why or offer any workarounds? I put a comment on the line with the error. Assume data is put in correctly.
Private Sub CommandButton1_Click()
Dim startDate As Date, endDate As Date, reason As String, name As String
name = InputBox("Please enter the name of the SLG as appears in column 1 on the worksheet:")
startDate = InputBox("Please enter the start date in MM/DD/YYYY format:")
endDate = InputBox("Please enter the end date in MM/DD/YYYY format:")
reason = InputBox("Please short description for the absence:")
Dim rng1 As Range, columnNumberStart As Integer, rowNumber As Integer, columnNumberEnd As Integer, test1 As String, test2 As String
Worksheets("FY-15 Schedule").Activate
Set rng1 = ActiveSheet.UsedRange.Find(name)
rowNumber = rng1.Row
Set rng1 = ActiveSheet.UsedRange.Find(startDate)
columnNumberStart = rng1.Column 'Says Error is on this line
Set rng1 = ActiveSheet.UsedRange.Find(endDate)
columnNumberEnd = ActiveSheet.UsedRange.Find(endDate).Column
test1 = Cells(rowNumber, columnNumberStart).Address
test2 = Cells(rowNumber, columnNumberEnd).Address
Dim rng2 As Range
Set rng2 = Range(test1, test2)
rng2.Value = reason
End Sub
First, explicitly coerce the date from the inputbox input:
startDate = CDate(InputBox("Please enter the start date in MM/DD/YYYY format:"))
And do the same for the other date field.
Then, there is still possible source of this same error: when the .Find method has returned Nothing to the range object, (e.g., the date is not found/doesn't exist in the sheet) then you are essentially doing Nothing.Column, which is an error.
If the date does not exist in the sheet, this will always raise an error, which you could trap like this, or use GoTo statements to return to the inputbox, etc...
Set rng3 = ActiveSheet.UsedRange.Find(startDate)
If rng3 Is Nothing Then
MsgBox "Start date" & Cstr(startDate) & " not found!", vbInformation
Exit Sub
End If
columnNumberStart = rng1.Column
I figured it out! The problem was this: It was not finding the dates because the dates were being generated by a formula!! My first date was manually typed in but the rest of them were a fill series from the second cell which was A2=A1+1 and all the way down the line. I wanted it that way so the start date could be changed but for some reason excel was not recognizing those as dates!?! How weird?!?!
Problem solved though. What you said was correct about it not finding the date but appearance wise when looking at the spreadsheet it is there in plain sight but when looking at the cells their values were formulas.