Search using multiple criteria - sql

I have two textboxes I want to search a table. I am putting the search through a query which I believe to be the issue. the code should take the criteria from both textboxes and search one table. after that the rest of the textboxes will fill with the recordset the is closest to the search.
I get a error at RstRecSet.MoveLast I get a compile error that says no current record. I do have a record like what I type into the box its not picking it up though
When I add in the exact name of the record it finds it no problem. It's almost as if it's treating the like operator as if it were a =.
Here is my code:
Private Sub Command514_Click()
'DoCmd.Close
'DoCmd.OpenForm "frmContacts", acNormal
Set RstRecSet = Nothing
Set db = CurrentDb
Dim searchNum As String
Dim searchName As String
searchNum = txtGroupNr
searchName = txtGroupName
On Error Resume Next
If IsNull(txtGroupNr) Or txtGroupNr = "" Then
Me.txtGroupName.BackColor = vbRed
Forms!frmGroupHeader!txtGroupNr.SetFocus
Else
'strSearchICN = txtGroupNr
Set db = CurrentDb
Me.txtGroupName.BackColor = vbWhite
Set RstRecSet = db.OpenRecordset("Select * from tblGroupHeader Where GroupNum Like '" & searchNum & "' And GroupName Like '" & searchName & "';", dbOpenDynaset)
RstRecSet.MoveLast
intMaxCount = RstRecSet.RecordCount
RstRecSet.MoveFirst
' Exit Sub
End If
If RstRecSet.EOF Then
Me.txtGroupName.BackColor = vbRed
Forms!frmGroupHeader!txtGroupNr.SetFocus
Else
Call DisplayFields
End If
End Sub
Here is the solution:
Private Sub Command514_Click()
'DoCmd.Close
'DoCmd.OpenForm "frmContacts", acNormal
Set RstRecSet = Nothing
Set db = CurrentDb
Dim searchGroup As String
Dim searchName As String
If IsNull(txtgroupSearch) Or txtgroupSearch = "" Then
Me.txtGroupName.BackColor = vbRed
Forms!frmGroupHeader!txtGroupNr.SetFocus
Else
'searchNum = txtGroupNr
searchGroup = txtgroupSearch
Set db = CurrentDb
Me.txtGroupName.BackColor = vbWhite
Set RstRecSet = db.OpenRecordset("Select * from tblGroupHeader Where groupName like '*" & searchGroup & "*' or groupNum like '*" & searchGroup & "*';", dbOpenDynaset)
If RstRecSet.EOF And RstRecSet.BOF Then
MsgBox ("NO RECORDS!")
Exit Sub
End If
RstRecSet.MoveLast
intMaxCount = RstRecSet.RecordCount
RstRecSet.MoveFirst
' Exit Sub
End If
If RstRecSet.EOF Then
Me.txtGroupName.BackColor = vbRed
Forms!frmGroupHeader!txtGroupNr.SetFocus
Else
Call DisplayFields
End If
End Sub

I believe the problem is in your SQL. The error suggests that you have no records. Before calling .MoveLast on the recordset you could put in a quick test with:
If RstRecSet.EOF and RstRecSet.BOF Then
msgbox("NO RECORDS!")
exit sub
End if
Back to the SQL. You wrote "Select * from tblGroupHeader Where GroupNum and GroupName Like '" & searchNum & GroupName & "';" which, if you chose "1" as the GroupNum and "Physics" as the Groupname, would come out to something like Select * from tblGroupHeader Where GroupNum and GroupName Like '1Physics'; Which makes no sense
Instead: "Select * from tblGroupHeader Where GroupNum Like '" & searchNum & "' and GroupName Like '" & GroupName & "';" Which would look like Select * from tblGroupHeader Where GroupNum Like '1' and GroupName Like 'Physics';
I've found it helpful to put my SQL into a variable first and then write that variable to the Immediates window with a Debug.Print SQL so that I can just copy and paste back into my database to make sure that everything makes sense.

Related

Search all records in subform from main form

I have a button that can search locations in all records in a table in the subform.
But it seems to show all records that have the [Location] in them instead of only records with the specific location entered in the textbox.
But once I've done my search, I can't seem revert the form to the original clear state, so that I can go back to searching other things.
Private Sub StartSearch2_Click()
Dim rs As Recordset
Dim strSQL As String
strSQL = "select * from [FormTable] where [Location]='" & Me.LocSearch & "'"
Set rs = CurrentDb.OpenRecordset(strSQL, dbOpenDynaset)
If Not rs.BOF And Not rs.EOF Then
Set Me.Recordset = rs
Else
MsgBox "No record found", vbOKOnly + vbInformation, "Sorry"
Me.RecordSource = strOriginalSQL
End If
Me.LocSearch = Null
End Sub
Another approach is to not change the Record Source of your form and instead set the Filter property.
Set the Record Source to FormTable. You can do this in the form designer.
Then set the Filter with
Me.Filter = "Location='" & Me.LocSearch & "'"
Me.FilterOn = True
You can clear the filter with
Me.Filter = ""
Me.FilterOn = False
If you want to filter a subform, you can do this from the main form with
With Me!mysubform.Form
.Filter = "Location='" & Me.LocSearch & "'"
.FilterOn = True
End With
It is a good idea to escape any single quotes in the search string
Me.Filter = "Location='" & Replace(Me.LocSearch, "'", "''") & "'"

Difficulty using SELECT statement in VBA

I'm trying to set command buttons to enter data into a table. If the record already exists I want the button to update it, and if it does not the button needs to create it. Here's a sample of what the table looks like
ID scenarioID reductionID Impact Variable Variable Impact
1 1 1 Safety 4
2 1 1 Environmental 2
3 1 1 Financial 1
In order to accurately locate records, it needs to search for the specific impact variable paired with the scenarioID. I'm trying to use a select statement, but DoCmd.RunSQL doesn't work for select statements, and I'm not sure how else to do it.
Here's the code. I left DoCmd.SQL in front of the select statement for lack of anything else to place there for now.
Private Sub Var1R1_Click() 'Stores appropriate values in tImpact upon click
'Declaring database and setting recordset
Dim db As Database
Dim rs As Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("tImpact")
'Declaring Variable as Scenario Choice combobox value
Dim Sc As Integer
Sc = Schoice.Value
'Stores impact variable
Dim impvar1 As String
'Desired impact variable for column 1
impvar1 = DLookup("impactVariable", "tImpactVars", "ID = 1")
DoCmd.RunSQL "SELECT * FROM tImpact WHERE [Impact Variable] = " & impvar1 & " AND scenarioID = " & Sc
If rs.EOF Then
DoCmd.RunSQL "INSERT INTO tImpact(scenarioID, [Impact Variable], [Variable Impact])" & "VALUES (" & Sc & ", " & impvar1 & ", 1)"
MsgBox "Record Added", vbOKOnly
Else
db.Execute "UPDATE tImpact SET [Variable Impact] = 1 WHERE [Impact Variable] = " & impvar1 & " AND scenarioID = " & Sc
MsgBox "Record Updated", vbOKOnly
End If
End Sub
If anyone can tell me how to get that SELECT statement to run, or another way of doing this, that would be great.
Any help is greatly appreciated!
You can use a recordset. In this case a recordset is better, since you only execute the SQL one time, if it returns a record, you "edit" and if not then you "add" with the SAME reocrdset. This approach is FAR less code, and the values you set into the reocrdset does not require messy quotes or delimiters etc.
eg:
scenaridID = 1 ' set this to any number
impvar1 = "Safety" ' set this to any string
updateTo = "Financial"
strSQL = "select * from tImpact where [Impact Variable] = '" & impvar1 & "'" & _
" AND scenaridID = " & scenaridID
Set rst = CurrentDb.OpenRecordset(strSQL)
With rst
If .RecordCount = 0 Then
' add the reocrd
.AddNew
Else
.Edit
End If
!scenaridID = scenarid
![Impact Variable] = impvar1
![Variable Impact] = 1
.Update
End With
rst.Close
So you can use the same code for the update and the edit. It just a question if you add or edit.
Use OpenRecordset and retrieve the ID for the record if it exists.
Private Sub Command0_Click()
Dim aLookup(1 To 3) As String
Dim aAction(1 To 3) As String
Dim rs As Recordset
Dim db As Database
'Replace these two constants with where you get the information on your form
Const sIMPVAR As String = "Financial"
Const lSCENID As Long = 1
'Build the SQL to find the ID if it exists
aLookup(1) = "SELECT ID FROM tImpact"
aLookup(2) = "WHERE ScenarioID = " & lSCENID
aLookup(3) = "AND ImpactVariable = """ & sIMPVAR & """"
'Run the sql to find the id
Set db = CurrentDb
Set rs = db.OpenRecordset(Join(aLookup, Space(1)))
If rs.BOF And rs.EOF Then 'it doesn't exist, so build the insert statement
aAction(1) = "INSERT INTO tImpact"
aAction(2) = "(ScenarioID, ImpactVariable, VariableImpact)"
aAction(3) = "VALUES (" & lSCENID & ", '" & sIMPVAR & "', 1)"
Else 'it does exist, so build the update statement
aAction(1) = "UPDATE tImpact"
aAction(2) = "SET VariableImpact = 1"
aAction(3) = "WHERE ID = " & rs.Fields(0).Value
End If
'Run the action query
db.Execute Join(aAction, Space(1))
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub

MS Access - SQL Query for Max Date

I am creating a schedule calendar which has been working great, but I want to adjust the SQL so that it only shows when the next job has to be done. I was thinking the best way to achieve this would be via the MAX() function, however when i run the code Access doesn't seem to like it.
Public Sub LoadArray()
'This sub loads an array with the relevant variables from a query
Dim db As Database
Dim rs As Recordset
Dim rsFiltered As Recordset
Dim strQuery As String
Dim i As Integer
Dim Text23 As Integer
On Error GoTo ErrorHandler
Text23 = Forms.frmPreventativeMenu.Form.CompanyName.Value
strQuery = "SELECT tblWMYReports.Company, tblWMYReports.Machine, MAX(tblWMYReports.NextDate), tblWMYReports.WMY " _
& "FROM tblWMYReports " _
& "WHERE (((tblWMYReports.Company)= " & Text23 & " ));"
Set db = CurrentDb
Set rs = db.OpenRecordset(strQuery)
With rs
If Not rs.BOF And Not rs.EOF Then
'Ensures the recordset contains records
For i = 0 To UBound(MyArray)
'Will loop through the array and use dates to filter down the query
'It firsts checks that the second column has true for its visible property
If MyArray(i, 1) = True Then
.Filter = "[NextDate]=" & MyArray(i, 0)
'To filter you must open a secondary recordset and
'Use that as the basis for a query
'This makes sense as you are building a query on a query
Set rsFiltered = .OpenRecordset
If Not rsFiltered.BOF And Not rsFiltered.EOF Then
'If the recordset is not empty then you are able
'to extract the text from the values provided
Do While Not rsFiltered.EOF = True
MyArray(i, 2) = MyArray(i, 2) & vbNewLine & DLookup("MachineName", "tblMachine", "MachineID=" & rsFiltered!Machine)
MyArray(i, 2) = MyArray(i, 2) & " - " & DLookup("WMY", "tblWMY", "ID=" & rsFiltered!WMY)
rsFiltered.MoveNext
Loop
End If
End If
Next i
End If
.Close
End With
ExitSub:
Set db = Nothing
Set rs = Nothing
Exit Sub
ErrorHandler:
MsgBox "There has been an error. Please reload the form.", , "Error"
Resume ExitSub
End Sub
You are going to aggregate one column with an aggregate function like Sum(), Max(), Count() or similar, then every other column that isn't being aggregated must show up in the SQL's GROUP BY clause:
strQuery = "SELECT tblWMYReports.Company, tblWMYReports.Machine, MAX(tblWMYReports.NextDate), tblWMYReports.WMY " _
& "FROM tblWMYReports " _
& "WHERE (((tblWMYReports.Company)= " & Text23 & " )) " _
& "GROUP BY tblWMYReports.Company, tblWMYReports.Machine, tblWMYReports.WMY;"
I can't guarantee that is going to do what you want it to, since I'm not familiar with your data, code, or application, but it should get you through the error.
You must use a properly formatted string expression for the date value:
.Filter = "[NextDate] = #" & Format(MyArray(i, 0), "yyyy\/mm\/dd") & "#"

multi-combo box search with VBA

I am currently having this issue of my search not working correctly. The idea is to have the user click on different fields and have them assigned to textboxes and then be searched against. Above is what the UI currently looks like in the form and the code is attached below. For example, when I pick firstName as the field 1 and Title as field 2, enter the text "joe" into field 1 into
and "student" into the respective text boxes and then hit search, it shows all of the student results instead of that single row of data in the table. I am thinking this is could be an issue of the combo boxes not being synchronized, where let's say if cbo1 and cbo2 declare fields, then those repsective text fields become filtered. cboField, cboField2 and cboField3 are all combo boxes and command_21 is a search button and command_28 is a show all records. I am very new to this still and am not entirely sure. Any help is appreciated. Thanks in advance
Option Compare Database
Private Sub cboField_Enter()
Dim oRS As DAO.Recordset, i As Integer
If Me.Form.FilterOn = True Then DoCmd.ShowAllRecords
Set oRS = Me.RecordsetClone
cboField.RowSourceType = "Value List"
cboField.RowSource = ""
For i = 0 To oRS.Fields.Count - 1
If oRS.Fields(i).Type = dbText Then cboField.AddItem oRS.Fields(i).Name
Next i
End Sub
Private Sub cboField2_Enter()
Dim rs As DAO.Recordset, i As Integer
If Me.Form.FilterOn = True Then DoCmd.ShowAllRecords
Set rs = Me.RecordsetClone
cboField2.RowSourceType = "Value List"
cboField2.RowSource = ""
For i = 0 To rs.Fields.Count - 1
If rs.Fields(i).Type = dbText Then cboField2.AddItem rs.Fields(i).Name
Next i
End Sub
Private Sub cboField3_Enter()
Dim rs As DAO.Recordset, i As Integer
If Me.Form.FilterOn = True Then DoCmd.ShowAllRecords
Set rs = Me.RecordsetClone
cboField2.RowSourceType = "Value List"
cboField2.RowSource = ""
For i = 0 To rs.Fields.Count - 1
If rs.Fields(i).Type = dbText Then cboField2.AddItem rs.Fields(i).Name
Next i
End Sub
Private Sub Command21_Click()
Dim sfilter As String, oRS As DAO.Recordset
Dim sfilter2 As String, rs As DAO.Recordset
If IsNull(cboField) And IsNull(cboField2) And IsNull(cboField3) Then
DoCmd.ShowAllRecords
MsgBox "select a field"
Exit Sub
End If
If Not IsNull(cboField) Then
sfilter = cboField & " LIKE '" & txtBox & "*'"
DoCmd.ApplyFilter , sfilter
End If
If Not IsNull(cboField2) Then
sfilter2 = cboField2 & " LIKE '" & txtBox2 & "*'"
DoCmd.ApplyFilter , sfilter2
End If
If Not IsNull(cboField3) Then
sfilter3 = cboField3 & " LIKE '" & txtBox3 & "*'"
DoCmd.ApplyFilter , sfilter3
End If
Set oRS = Me.RecordsetClone
Set rs = Me.RecordsetClone
If oRS.RecordCount And rs.RecordCount = 0 Then
MsgBox " no record matches"
DoCmd.ShowAllRecords
End If
End Sub
Private Sub Command28_Click()
DoCmd.ShowAllRecords
End Sub

Selecting Random Record and Marking Record As Being Used

So, the following selects a random team to be used. Once selected, I mark this team being as used as an X in the Used field with a update query later on. For the most it works, but after running this a handful of times, I start to get duplicated teams, even with them being marked as X.
What else am I missing to accomplish this?
Here is the SQL statement:
SELECT TOP 1 RandomTeams.[Team Name], RandomTeams.Used
FROM RandomTeams
WHERE (((RandomTeams.Used) Is Null))
ORDER BY Rnd(TeamID);
Here's how I'm handling the updates to mark a team as being used, which is working as expected, I have no issues here when marking with an X:
Text214.Text contains the team name that is being used
strTeam = (Chr(34) + Text214.Text + (Chr(34)))
strSQLUpdateTeams = "UPDATE RandomTeams SET Used = 'X' WHERE [Team Name] = " & strTeam
DoCmd.SetWarnings (WarningsOff)
DoCmd.RunSQL strSQLUpdateTeams
As a test, how about just throwing the following code into a module, then execute it and see what happens. BTW, how are you resetting [Used]?
Sub Test_Teams()
Dim strSQL As String
Dim strTeam As String
Dim strSQLUpdateTeams As String
Dim dbs As DAO.Database
Dim rs As DAO.recordSet
Set dbs = CurrentDb
If MsgBox("Do you want to reset all 'Used' flags?", vbYesNo, "Reset?") = vbYes Then
strSQL = "update RandomTeams set [Used] = null;"
dbs.Execute strSQL
End If
MyLoop:
strSQL = "SELECT TOP 1 RandomTeams.[Team Name], RandomTeams.Used " & _
"FROM RandomTeams " & _
"WHERE (((RandomTeams.Used) Is Null)) " & _
"ORDER BY Rnd(TeamID);"
Set rs = dbs.OpenRecordset(strSQL)
If Not rs.EOF Then
strTeam = rs![Team Name]
Debug.Print "Found Team: " & strTeam
Else
MsgBox "EOF! No more teams."
rs.Close
Set rs = Nothing
dbs.Close
Set dbs = Nothing
Exit Sub
End If
strTeam = (Chr(34) + rs![Team Name] + (Chr(34)))
rs.Close
Set rs = Nothing
strSQLUpdateTeams = "UPDATE RandomTeams SET [Used] = 'X' WHERE [Team Name] = " & strTeam
Debug.Print strSQLUpdateTeams
'DoCmd.SetWarnings (WarningsOff)
'DoCmd.RunSQL strSQLUpdateTeams
dbs.Execute strSQLUpdateTeams
If dbs.RecordsAffected <> 1 Then
MsgBox "Whoa! Not good! Update failed!"
End If
GoTo MyLoop
End Sub