Trying to Find Duplicate Records in Access Error - vba

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.

Related

Why does my SQL statement not find a match with the WHERE statement below?

I'm attempting to pull data from my MS Access database via an Excel SQL statement. It does NOT give me any errors, however it also does not pull the data I'm searching for.
If items(u, 1) is text (ex. 308-203BL), then it works perfectly.
I've tried both comparing them as text and as numerical, but neither way find any matches when items(u, 1) is 19310.
This compares it as text...
LEFT(Item," & Len(items(u, 1)) & ") = '" & items(u, 1) & "'"
this compares it as numerical...
VAL(LEFT(Item," & Len(items(u, 1))) & ") = " & items(u, 1)
I have verified that there are records in the DB that match the given criteria.
items() is an array populated from a 1 column table on the sheet by items = Range("Items").Value.
Using these two SKU's as examples, the first working, the second not, the array would be as follows. .
SKU by SKU, they're fed into the SQL as below.
With the input in the example, the output I receive is an array populated only the sales for the second item. The order I put the SKU's in the table doesn't change that result. I have tested it with multiple SKU's, and no matter how many I use, it returns the proper information, with the exception of not returning any results for any numerical SKU's.
The field for Item in the DB is a short text, which is why I used '" & items(u, 1) & "'" to convert the SKU to text when I was trying to match it as text, and Val() to convert the field to a value when trying to match it as a number. Both gave me 0 record counts in the function, but did not give me a data type error.
Below is the portion of my code which determines the SQL string, and a bit afterwords which basically stuffs it into a UDF which pulls the info from the DB and puts it into an array for me. Aside from not finding a match when items(u,1) is numerical, it works perfectly.
DBString = "SELECT Invoice, Line, Inv_Date, Sales_Order, SOLine, SO_Date, CustID, Item, Part_Description, Ship_Qty, Price, Ext_Sales FROM `" & Year(tabledate) & "-" & Format(tabledate, "mm") & "` WHERE Inv_Date BETWEEN #" & Sdate & "# AND #" & Edate & "# AND LEFT(Item," & Len(items(u, 1)) & ") = '" & items(u, 1) & "'"
SalesHolder = PullFromDB(DBString, SGMDB)
I've also tried the below code instead, to force it to compare as a number instead of text, which also doesn't give me any errors, but doesn't find a match.
DBString = "SELECT Invoice, Line, Inv_Date, Sales_Order, SOLine, SO_Date, CustID, Item, Part_Description, Ship_Qty, Price, Ext_Sales FROM `" & Year(tabledate) & "-" & Format(tabledate, "mm") & "` WHERE Inv_Date BETWEEN #" & Sdate & "# AND #" & Edate & "# AND VAL(LEFT(Item," & Len(items(u, 1))) & ") = " & items(u, 1)
SalesHolder = PullFromDB(DBString, SGMDB)
Below is the UDF itself which pulls the info from the DB. It works quite nicely.
Function PullFromDB(DBStr As String, DBLoc As String) As Variant
Dim TheDB As Recordset, DBHolder() As Variant
Set TheDB = OpenDatabase(DBLoc).OpenRecordset(DBStr)
If TheDB.RecordCount = 0 Then GoTo theexit
TheDB.MoveLast
TheDB.MoveFirst
ReDim DBHolder(0 To TheDB.RecordCount, 1 To TheDB.Fields.Count) As Variant
For k = 1 To UBound(DBHolder, 2)
TheDB.MoveFirst
For j = 0 To UBound(DBHolder)
If j = 0 Then
DBHolder(j, k) = TheDB.Fields(k - 1).Name
Else
DBHolder(j, k) = TheDB.Fields(k - 1).Value
TheDB.MoveNext
End If
Next j
Next k
theexit:
TheDB.Close
Set TheDB = Nothing
PullFromDB = DBHolder
On Error GoTo -1
End Function
The expected result is to populate the array SalesHolder with the information that matches the criteria.
What am I missing? I'm going blind trying to find it.
Thank you all for your responses to this, it turns out I was completely hunting for the wrong problem. The code I posted was actually correct, the issue was with the format of Inv_Date field in the DB. I had mistakenly entered the last couple of months as text instead of date, so the WHERE Inv_Date BETWEEN #" & Sdate & "# AND #" & Edate & "# portion of my SQL didn't match anything.
I hadn't identified that this was the issue earlier due to the timing of the sales of the SKU's themselves, which was purely coincidence. When I expanded the dates range, I found that it did return results for the numerical SKU, but both numerical and text SKU's cut off two months ago.
Thank you again!

Insert list of pictures from datatable into MS Access database, VB.NET

I have a datatable containing several records. Each row of the datatable has a field that stores picture. When I loop through the datatable rows to insert them into a table of a database, every field of the row is saved correctly; but for every record, the picture in the first row of the datatable is saved. I traced the code and it does hit the lines that access and try to save the pictures in each row of the datatable. I am using VB.NET and the database is MS Access.
My code looks like this:
For Each dr As DataRow In dt.Rows
cmd.CommandText = "INSERT INTO Table1 (" & _
"[ID], " & _
"[Name], " & _
"[BDate], " & _
…….
"[TelNo], " & _
"[Photo]) " & _
" VALUES(" & _
dr("ID") & ", '" & _
dr("Name") & "', " & _
dr("BDate") & ", '" & _
…….
dr("TelNo") & "', " & _
img & ")"
cmd.Parameters.Add(img, OleDb.OleDbType.Binary).Value = dr("Photo")
cmd.ExecuteNonQuery()
Next
The code does exactly what you ask:
In your loop, all fields are varying following the values in your dataset row because you do this for each : dr(thefield)
except for the image because you just do this : img
It is thus always the same image.
You should have something like dr(image) (but I doubt it work as simply)
I find the answer myself. The problem is rather subtle. In OleDbCommands, parameters are not named. Parameters are represented by ? (the question mark). In the code snippet of my question, the variable img has the value of ?, which is assigned by a statement before the loop. The value of parameters MUST be provided in the order of their appearance. I my case, there is only one parameter and I provide a single parameter by the statement:
cmd.Parameters.Add(img, OleDb.OleDbType.Binary).Value = dr("Photo")
However, in each iteration of the loop, another parameter will be added. For the second record, the actual value of the parameter will be the second parameter , the third record will have its value at the third place, etc. Since in OleDbCommands values for parameters are identified by their order, and since there is only one parameter in my case, the picture provided first (i.e. that of the first record) is always used.
Hence the question boils down to ‘How can I provide a single parameter in each iteration?’ And the answer is to remove the parameter added by each iteration by including this precious statement:
cmd.Parameters.Clear()
as the last statement in the loop.
Sorry for the lengthy explanation.

Remove time from datetimepicker

I tried doing
senddate.Value = Format(senddate.Value, "mm/dd/yyyy")
sstartdate.Value = Format(sstartdate.Value, "mm/dd/yyyy")
MsgBox(senddate.Value & " " & sstartdate.Value)
but the messagebox still returns the time as well. (message box is there for diagnostic purposes, though it also passes the time to the SQL string as well.)
I tried switching the date time pickers to custom format and it didn't work. Any ideas?
I need to turn it into a short, simple date so that I can input it into an SQL Access BETWEEN query
senddate.Value = Format(senddate.Value, "MM/dd/yyyy")
sstartdate.Value = Format(sstartdate.Value, "MM/dd/yyyy")
MsgBox(senddate.Value & " " & sstartdate.Value).ToString
the month part should be in capital lettrs.

Using Dlookup with multiple criteria in a form

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

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