Using Dlookup with multiple criteria in a form - vba

I have a Form where I enter in my part number and part rev. I am trying to write some VBA so if I click a button on the form, it will search the query, which holds all the history of all the parts, for a part number as well as part rev match. Once it finds a matching part number and part rev, it autofills some information into the form for me.
Right now I have it returning data for a matching part number, but it gives the first data found, regardless of part rev, i.e. returns values that match another part number but different rev.
Sub FindPartNumber_Click()
DoCmd.OpenQuery "SavedQuotesQuery" 'runs query to find any matching part numbers
'confirms if part previously exists
If IsNull(DLookup("PartNumber", "SavedQuotesQuery", "'[PartNumber]=" & Me.PartNumber _
& " AND [PartRev]=" & Me.PartRev & "'")) Then
MsgBox "Part does not previously exist. Please manually enter its characteristics", _
vbOK 'and alerts user
DoCmd.Close 'close query
Exit Sub
End If
[PartName] = DLookup("PartName", "SavedQuotesQuery", "PartNumber='" & Me.PartNumber _
& "'")
[Length] = DLookup("Length", "SavedQuotesQuery", "PartNumber='" & Me.PartNumber & _
" And PartRev = " & Me.PartRev & "'")
DoCmd.Close 'close query
End Sub
Am I just struggling with the syntax of the two match criteria or is there something else going on here?

There are a lot of problems here. First off, the DoCmd.OpenQuery and DoCmd.Close are not doing what you seem to expect. Read up on the help file to learn how they should be used, but for our purposes it's enough for me to just say you do not need them here.
The problem you are having is that you are only providing half of your criteria in the PartName DLookup call. So instead of returning the PartName with matching PartNumber and PartRev, you are telling Access to return the PartName of the first record it finds with a matching PartNumber. Which one it returns is not actually defined if there is more than one match.
Try the following instead:
Sub FindPartNumber_Click()
Dim MyPartName As Variant, Criteria As String
Criteria = "PartNumber=""" & Me.PartNumber & """ AND " & _
"PartRev= """ & Me.PartRev & """"
'confirms if part previously exists
MyPartName = DLookup("PartName", "SavedQuotesQuery", Criteria)
If IsNull(MyPartName) Then
MsgBox "Part does not previously exist. Please manually enter its characteristics", vbOK 'and alerts user
Else
[PartName] = MyPartName
[Length] = DLookup("Length", "SavedQuotesQuery", Criteria)
End If
End Sub

Related

How to count and output rows in Access VBA [duplicate]

I am using DCount to help display an error message if the data signals an error. I have it working with one criteria where a number is equal to another number. Now I wanted to add another criteria in there where another field, ReturnDate (this field is Text not Date/Time) is equal to a hyphen (-).
I'm just not really sure how to format it. I have this:
If DCount("*", "CrewTable", "KitNumber=" & _
Me.AssignKit.Value And "ReturnDate=" & _
"-") > 0 Then
Cancel = True
MsgBox "Kit is already assigned!"
AssignKit = ""
AssignKit.SetFocus
Else
...
The error pops up with a 'Type Mistmatch' and the debugger highlights the whole statment from 'If -> Then' and has an error pointing to the line with the hyphen in the quotes.
If DCount("*", "CrewTable", "ReturnDate='-' AND KitNumber=" & _
Me.AssignKit.Value) > 0 Then
It's easier to troubleshoot DCount errors when you store its Criteria option in a string variable.
Dim strCriteria As String
strCriteria = "ReturnDate='-' AND KitNumber=" & Me.AssignKit.Value
Debug.Print strCriteria
If DCount("*", "CrewTable", strCriteria) > 0 Then
If you had used this approach, Access would have alerted you to the fact that the original code which built the Criteria string was invalid. That should make it clearer that the problem wasn't due to the If condition, and it wasn't exactly a DCount problem either ... it was a problem with string concatenation.
Me.AssignKit.Value & " And ReturnDate=" & _

Trying to Find Duplicate Records in Access Error

I am making a databse for a sports club,
When filling out a form, they input the facility ID, start time, end-time and date.
What I am trying to do is when they enter the end time box, the function scans through the entries on the 'Bookings' Table where all the data from this form is stored, to see if the facility is booked out at this time. ( For dtermining if it is booked out at a certain time, if the start time or the end time on table is between what is filled in on the form, an error is thrown
The code is shown below:
Private Sub EndNon_AfterUpdate()
Dim criteria As String
criteria = _
"Non-PlayingFacilityID= " & Me.NonPlayID.Value & " " & _
"Date(Non-PlayingFacility)= " & Me.DateNon.Value & _
" " & "AND [StartTime(Non-PlayingFacility)] Between Me.StartNon.Value And Me.EndNon.Value OR [EndTime(Non-PlayingFacility)] Between Me.StartNon.Value And Me.EndNon.Value "
If DCount("*", "Bookings", criteria) > 0 Then
MsgBox "Unfortunately, this facility is booked at this time"
Me.Undo
End If
End Sub
Syntax error is thrown when I run this, not sure why.
Any help would be much appreciated
It probably highlights this invalid syntax:
"Date(Non-PlayingFacility)= " & Me.DateNon.Value & _
Perhaps you mean:
"DateValue([Non-PlayingFacility])= " & Format(Me!DateNon.Value, "\#yyyy\/mm\/dd\#") & _
The remaining date comparisons need to be concatenated and formatted similarly.
Addendum - given the obscure field name:
"[Date(Non-PlayingFacility)]= " & Format(Me!DateNon.Value, "\#yyyy\/mm\/dd\#") & _
The format is needed to create a valid string expression in SQL for the date value. This is independent of a format applied for display.

How do I prompt for a CSV user input on my on-start event for my form?

at work, we're trying to build a database to get an output of all kinds of data from different excel tables (items in stock, sales per week, price, etc) into one table by using the ItemID as primary key for all the tables and as a user input for the queries.
My goal is to let the user enter multiple itemIDs seperated by commas and get back a table with multiple rows (one for each item).
I have now created a form with all the fields I need and have used one of my queries that I implemented before as my data source.
I'm trying to write some code for my On-Start event and have used an example someone posted online regarding entering multiple parameters:
Option Compare Database
Const record source = Query01
Private Sub Form_Open(Cancel As Integer)
Dim m As String
m = InputBox("Enter itemID (numeric), separated by comma", "itemID")
If m <> "" Then
Me.RecordSource = record_source & " where itemID in (" & m & ");"
Else
Me.RecordSource = record_source
End If
End Sub
For the line:
Me.RecordSource = record_source & " where SKU in (" & m & ");"
I get the error
Run-Time error '2580'
The record source 'where SKU in (" & m & ");' specified on this form or report does not exist.
Do I need to declare my record source differently in the second line? Do I need to somehow specify which table I get my "itemID" field out of? The Query01 that I put as my data source gets fields out of three different tables.
Thank you so much for your help!
Cheers!
I fixed my issue by using the Filter-method instead and just deleting the declaration in line 2 since the data source was already defined in the properties sheet before.
My VBA code:
Private Sub Form_Open(Cancel As Integer)
Dim m As String
m = InputBox("Enter itemID (numeric), separated by comma", "itemID")
If m <> "" Then
Me.Filter = "itemID in (" & m & ")"
Me.FilterOn = True
Else
Me.FilterOn = False
End If
End Sub
Hope this helps anyone encountering a similar problem.
Cheers!

Determining if Spreadsheet Entries Match Database Column Entries

One aspect of my project involves comparing the part number entered by the operator to a predetermined list of part numbers in a column in a database. Right now, my program is telling me that every part number entered in the spreadsheet (50+) does not match any in the database, which I've verified to be incorrect. I've checked that both the spreadsheet part number and the database part number are of string datatype. I've doublechecked that my looping logic is good, and to me seems like it should work. To the best of my knowledge there are no hidden characters in either the database cells or in the spreadsheet cells. I'm completely stumped at this point as to why my program doesn't detect any matches between the spreadsheet and the database. Below is the Sub containing the code for checking that the part numbers match:
Sub CheckPN()
'Connect to the E2 database
Call SetPNConnection
'Open a recordset
Set PNRecordset = New ADODB.Recordset
PNRecordset.Open "EstimRpt", PNConnection, adOpenKeyset, adLockOptimistic, adCmdTable
PNSQLCmd = "SELECT DISTINCT [PartNo] FROM EstimRpt;"
'Loop through data, comparing part numbers to E2 database part number records
TotalBadPNCount = 0
With PNRecordset
For DataRowCount = 2 To TrackingLastRow
PNCount = 0
Part_Number = Tracking.Sheets("Operator Data").Range("A" & DataRowCount).Value
'MsgBox "The datatype for " & Part_Number & " is " & VarType(Part_Number) & "."
Do Until .EOF
'MsgBox "The datatype for " & .Fields("PartNo").Value & " is " & VarType(.Fields("PartNo").Value) & "."
If Part_Number = .Fields("PartNo").Value Then
'If .Fields("PartNo").Value = Part_Number Then
MsgBox Part_Number & " is a match."
PNCount = PNCount + 1
End If
.MoveNext
Loop
If PNCount < 1 Then
MsgBox "The P/N " & Part_Number & " entered in cell A" & DataRowCount & " is incorrect. Please correctly enter the P/N and re-run the program."
TotalBadPNCount = TotalBadPNCount + 1
End If
Next DataRowCount
If TotalBadPNCount >= 1 Then
Exit Sub
End If
End With
PNRecordset.Close
Set PNRecordset = Nothing
PNConnection.Close
Set PNConnection = Nothing
End Sub
On a side note, I'd like to have the entire program stop executing if a part number doesn't match, not just the immediate sub. Currently, just this sub exits upon no part number matches.
Thanks for the help on both of these issues.
Jordan
I'd suggest not using a loop to compare records from your user-submitted dataset to your permanent table. Instead, load the user-submitted dataset into a temporary table in your DB, and use SQL to compare the 2 tables.
You can try something along these lines:
'Load spreadsheet into temp table
<your code here>
'open recordset in order to compare PartNos
Dim db As Database
Set db = CurrentDb
Dim rs As Recordset
sSQL = "select count(*) as [count] from temp " _
& " where temp.PartNo not in (select distinct EstimRpt.PartNo from EstimRpt)"
Set rs = db.OpenRecordset(sSQL)
ctRecords = rs![Count]
'if records are found in temp table that do not exist
'in the perm table, then end execution of everything.
if ctRecords > 0 then
End
else
'run the rest of your code
<your code here>
end if
'Drop temp table
<your code here>
I found my problem at long last. The comparing records between database and spreadsheet does work now. I had to make the following changes to my code:
Instead of:
Do Until .EOF
I needed:
Do Until .EOF = True
I also needed to add the following just after the For Loop declaration:
.MoveFirst
Now my code loops correctly.

How do I reference a value from a list box in Column(0) on click?

I have a list box that is populated based on a previous filter (a text box). This means there is no predefined number of items in the listbox so using the index is impossible.
What I am looking for is a way of selecting the value of column(0), as there are 3 columns in my list box, of the selected line that is clicked.
Private Sub listSource_Click()
Dim strSource As String
strSource = "SELECT [Product Code],[Stock Level],[Description] FROM [products/stock] " & _
"WHERE Mid([Product Code],1,5) = " & Me.listSource.Column(0).Value & ";"
Me.listResult.RowSource = strSource
Me.listResult = vbNullString
End Sub
What I think I need is just the small piece of code that is supposed to be where "Me.listSource.Column(0).Value" is.
Thanks in advance,
Bob P
I reckon you want:
strSource = "SELECT [Product Code],[Stock Level],[Description] " & _
"FROM [products/stock] " & _
"WHERE Mid([Product Code],1,5) = '" & Me.listSource & "';"
Note the single quotes before and after Me.listSource.
Me.listresult gives the bound column
you then have to append .Column(0),.Column(1) ... for other columns.
to find out which one of the list you need to be looking at, .ItemsSelected.Count will tell you how many are selected (1 for a simple list box), and .ItemsSelected(0) for the index to the first item selected, so, the complete line for the first column of the first selected line would be:
Me.listSource.ItemData(Me.ListSource.ItemsSelected(0))
You should be able to use Me.ListSource.Column(0) to get the value of the first column of the selected row.
Also see: Retrieve column values of the selected row of a multicolumn Access listbox