Let's say I have a single table called "Customers". It contains 2 fields:
Name
Address
I want users to be able to select multiple records by selecting their names. For example something like having a list box containing all the names of the records in the database. I want users to be able to select multiple items like:
Dave Richardson
Bob Smith
Sophie Parker
And then only display records with these names in the report.
You can use the WhereCondition option of the DoCmd.OpenReport Method to filter your report as needed.
Const cstrReport As String = "YourReportNameHere"
Dim custNames As String
Dim lItem As Variant
Dim strWhereCondition As String
With Me.yourListBoxName
For Each lItem In .ItemsSelected
custNames = custNames & ",'" & Replace(.ItemData(lItem), "'", "''") & "'"
Next
End With
If Len(custNames) > 0 Then
custNames = Mid(custNames, 2)
strWhereCondition = "[Name] IN (" & custNames & ")"
End If
DoCmd.OpenReport ReportName:=cstrReport, View:=acViewPreview, _
WhereCondition:=strWhereCondition
Note this approach has features in common with PaulFrancis' answer. In fact, I copied his code and modified it. The key difference is that this approach does not require you to revise a saved query in order to filter the report.
The setup I would I have is, a Form with a SubForm and a ListBox, the Listbox will have the names of all your customers. So the RowSource would be,
SELECT
customerNameFieldName
FROM
yourTableName;
The Multi Select property will be setup to Extended. Then a button will have the following code that will generate the SQL for the SubForm's recordsource.
Private Sub buttonName_Click()
Dim lItem As Varaint, strSQL As String
Dim custNames As String, whereStr As String
Dim dbObj As dao.Database
Dim tmpQryDef As QueryDef
Set dbObj = CurrentDb()
For Each lItem In Me.yourListBoxName.ItemsSelected
custNames = custNames & "'" & Me.yourListBoxName.ItemData(lItem) & "', "
Next
Id Len(custNames) <> 0 Then
custNames = Left(custNames, Len(custNames) - 2)
whereStr = "WHERE customerNameFieldName IN (" & custNames & ")"
End If
strSQL = "SELECT someFields FROM someTable " & whereStr
Set tmpQryDef = dbObj.QueryDefs("Summary 3 Q1")
tmpQryDef.SQL = strSQL
DoCmd.OpenReport "yourReportName", acViewNormal
Set dbObj = Nothing
Set tmpQryDef = Nothing
End Sub
So now the SubForm will have the RecordSource based on all the information you have selected in the ListBox.
Related
Good morning,
I am helping to develop an interface via a Form in MS Access. We have a list box with various user values and the user should be able to select multiple values in the ListBox and then press the button to execute a query, returning only the rows whose Car Name is what was selected.
UPDATE - thanks to some great feedback on this forum, the primary issue was resolved. My secondary issue is now not being able to execute the query. When I try, I get the error that the query cannot be executed.
My code (as event procedure) for the button is:
Option Explicit
Private Sub btnSearchCars_Click()
MsgBox "Starting Sub"
Call QueryCars.myQuery
MsgBox "Ending Sub"
End Sub
Then, my QueryCars module looks like this:
Sub myQuery()
Dim strWhere As String
Dim strSQL As String
Dim varItem As Variant
For Each varItem in Forms!FormSelect!listCarID.SelectedItems
strWhere = strWhere & "'" & Forms!FormSelect!listCarID.ItemData(varItem) & "',"
Next
strWhere = Left(strWhere, Len(strWhere) -1)
strSQL = "SELECT tblBig.* FROM tblCars INNER JOIN tblBig ON tblCars.Car_ID = tblBig.Car_ID WHERE tblCars.Car_ID IN (" & strWhere & ");"
DoCmd.RunSQL strSQL
End Sub
My error is an "A RunSQL requires an argument of an SQL statement" error on the line.
DoCmd.RunSQL strSQL
I would really appreciate it if someone could help. All I am trying to do is take the values from the list box the user selects and use them as WHERE criteria in my query. I have searched various SO and Access forums all morning and have not found anything to help.
Thank you. Please let me know if you have any questions.
This isn't the perfect answer I was hoping to give you - but can't figure out how to use parameter queries in an IN command.
I'll assume that your listbox contains two columns of data and the CarID values are in the first column.
The main function is called ProcessQuery and accepts a reference to the listbox as an argument:
Public Sub ProcessQuery(myList As ListBox)
You can then call your code from the event on the listbox and pass it the listbox reference.
Private Sub btnSearchCars_Click()
ProcessQuery Me.listCarID
End Sub
The ProcessQuery procedure then looks at the first column to get the index numbers, constructs the SQL, opens the resulting recordset and pulls the info from each record.
Public Sub ProcessQuery(myList As ListBox)
Dim vItem As Variant
Dim IDList As String
Dim qdf As dao.QueryDef
Dim rst As dao.Recordset
For Each vItem In myList.ItemsSelected
'Column 0 is first column in listbox.
IDList = IDList & "'" & myList.Column(0, vItem) & "',"
Next vItem
'Removes the final ,
IDList = Left(IDList, Len(IDList) - 1)
'Create a temporary query definition & open the recordset.
Set qdf = CurrentDb.CreateQueryDef("", _
"SELECT tblBig.* FROM tblCars INNER JOIN tblBig ON tblCars.Car_ID = tblBig.Car_ID WHERE tblCars.Car_ID IN (" & IDList & ")")
Set rst = qdf.OpenRecordset
'Move through the recordset and output the first two fields from each record
'to the Immediate window.
With rst
If Not (.BOF And .EOF) Then
.MoveFirst
Do While Not .EOF
Debug.Print .Fields(0) & " - " & .Fields(1)
.MoveNext
Loop
End If
End With
End Sub
To display the query result as a datasheet you could use the following, but I'd prefer to use a stored query with a parameter for the IN. I'll try and figure that bit out.
Public Sub ProcessQuery(myList As ListBox)
Dim vItem As Variant
Dim IDList As String
Dim qdf As dao.QueryDef
Dim rst As dao.Recordset
For Each vItem In myList.ItemsSelected
'Column 0 is first column in listbox.
IDList = IDList & "'" & myList.Column(0, vItem) & "',"
Next vItem
'Removes the final ,
IDList = Left(IDList, Len(IDList) - 1)
'Create a temporary query definition & open the recordset.
Set qdf = CurrentDb.CreateQueryDef("TempQDF", _
"SELECT tblBig.* FROM tblCars INNER JOIN tblBig ON tblCars.Car_ID = tblBig.Car_ID WHERE tblCars.Car_ID IN (" & IDList & ")")
DoCmd.OpenQuery "TempQDF", acViewNormal
End Sub
I would suggest first taking a look at the actual WHERE clause being generated...keep a separate string variable to store it, and then dump it to the Immediate Window when it's generated.
I would also suggest creating a separate function to return values selected in a list box as an array. Something like:
Public Function getListBoxSelection(ctl As Access.ListBox) As Variant
Dim arr() As Variant
Dim varItem As Variant, i As Long
If ctl.ItemsSelected.Count > 0 Then
ReDim arr(0 To ctl.ItemsSelected.Count - 1)
i = 0
For Each varItem In ctl.ItemsSelected
arr(i) = ctl.ItemData(varItem)
i = i + 1
Next varItem
End If
getListBoxSelection = arr
End Function
Then, you would call it in SQL generation. Something like
whereClause = join(getListBoxSelection(me.listCarID), " AND ")
debug.Print whereClause
qdf.SQL = _
"select tblBig.* " & _
"from tblCars " & _
"inner join tblBig on tblCars.Cat_ID = tblBig.Car_ID " & _
"where tblCars.Card_ID in (" & whereClause & ")"
I can't work out where I am going wrong with my code. When the user selects a value in the combo box, i want it to go to the Consultants table and grab the default rate for that consultant and stick it in the Hourly Rate text box. This is the msg that I get when I update the combobox.
Private Sub cmbConsultant_Change()
Dim db As Database
Dim rs As DAO.Recordset ''Requires reference to Microsoft DAO x.x Library
Dim strSQL As String
strSQL = "defaultFee * FROM tblConsultants WHERE ID = """ & Me!cmbConsultant & """"
Set db = CurrentDb
Set rs = db.OpenRecordset(strSQL)
If rs.RecordCount > 0 Then
Me.txtHourlyRate = rs!CountOfEndDeviceType
Else
Me.txtHourlyRate = ""
End If
Set rs = Nothing
Set db = Nothing
End Sub
You could use DLookup for this - much simpler:
Private Sub cmbConsultant_Change()
Me!txtHourlyRate.Value = DLookup("defaultFee", "tblConsultants", "ID = '" & Me!cmbConsultant.Value & "'")
End Sub
However, most likely your ID is numeric, thus:
Private Sub cmbConsultant_Change()
Me!txtHourlyRate.Value = DLookup("defaultFee", "tblConsultants", "ID = " & Me!cmbConsultant.Value & "")
End Sub
I Think You need some SELECT Here
strSQL = "defaultFee * FROM tblConsultants WHERE ID = """ & Me!cmbConsultant & """"
It Should Be:
strSQL = "SELECT defaultFee AS [CountOfEndDeviceType] FROM tblConsultants WHERE ID = """ & Me!cmbConsultant & """"
Also Note, That [CountOfEndDeviceType] Must be a FieldName, SO I've put it in a Select statement.
I have two multiple select list boxes "Animal" and "State". These two list boxes are dependent on each other. For example, if i select "in" and "mi" in the state list box, the animal list box will only show animals that are in "in" and "mi".
My issue is i have the rowsource set to the query below which is assigned to the "on click" event in the animal list box. When i click in the animal list box it runs the query but it no longer allows me to select any animals.
How do i change the list box to allow me to select animals in the animal list box?
Private Sub animal_Click()
Dim Q As QueryDef
Dim DB As Database
Dim Criteria As String
Dim ctl As Control
Dim Itm As Variant
Dim ctl2 As Control
Dim ctl3 As Control
' Use for dynamic SQL statement'
Dim strSQL As String
Set ctl2 = Me![State]
For Each Itm In ctl2.ItemsSelected
If Len(Criteria2) = 0 Then
Criteria2 = Chr(34) & ctl2.ItemData(Itm) & Chr(34)
Else
Criteria2 = Criteria2 & "," & Chr(34) & ctl2.ItemData(Itm) & Chr(34)
End If
Next Itm
' Modify the Query.
Set DB = CurrentDb()
Set Q = DB.QueryDefs("animal")
' Modify the Query.
Set DB = CurrentDb()
Set Q = DB.QueryDefs("animal")
strSQL = "Select distinct(animal) From [table1] Where [table1].[type] In (" & "'Animal')"
If (Len(Criteria2) <> 0) Then ' Append State Criteria
strSQL = strSQL & " AND [table1].[state] IN (" & Criteria2 & ")"
End If
Q.SQL = strSQL
Q.Close
' Run the query.
'DoCmd.OpenQuery "animalquery"
Me.Animal.RowSource = strSQL
End Sub
I think i solved for this.
I originally changed "Private Sub animal_Click()" to "Private Sub animal_dblClick()" but this was resulting in an event procedure error.
I then changed it to "Private Sub animal_Enter()". When i enter the list box it runs the query while still allowing me to select items in the list box.
However, if someone has a different solution or know how to use the double click method. that would be great!
I'm trying to create a query in Access.
Let's say, for example, I have four fields: Numbers 1-26, Letters A-Z, 26 Names, and 26 Cities, so one record might be: 2, B, Jane, New York
I want to create and save a new query with:
the numbers field, the letters field, and the names field. I want the letters field to be filtered on "A" or "B", and the names field to have an expression so it's always 0.
This will become a loop, so it'll create 13 queries (A/B, C/D, etc).
It seems like having this process in VBA as opposed to the Access macro builder would be better since not only do I have to loop this process, but there are also 2 similar tables (same field names, different values) that I need to run it on.
You can run your queries in VBA using a recordset and then work with the data from there:
Sub YourQueries(ByVal pstrCol1 As String, ByVal pstrCol2 As String, ByVal pstrCol3 As String, ByVal pstrCol4 As String)
Dim rs As Recordset
Dim strSQL As String
' Change types above to match what's actually in the table
strSQL = "SELECT YourColumn1, YourColumn2, YourColumn3, YourColumn4 "
strSQL = strSQL & " WHERE "
strSQL = strSQL & "YourColumn1='" & pstrCol1 & "'"
strSQL = strSQL & " AND YourColumn1='" & pstrCol1 & "'"
strSQL = strSQL & " AND YourColumn1='" & pstrCol1 & "'"
strSQL = strSQL & " AND YourColumn1='" & pstrCol1 & "'"
Set rs = CurrentDb.OpenRecordset(strSQL, dbOpenSnapshot)
While Not rs.EOF
For i = 0 To 3
Debug.Print rs.Fields(i) & " is Column" & Format(i)
Next i
rs.MoveNext
Wend
rs.Close
Set rs = Nothing
End Sub
Database Structure:
UserName String
Location String
Price Number
Requirement:
I have listbox with some items into it say 100. The user will select only 10 randomly in the listbox (after changing the MULTISELECT to 2fmMultiselect property). I will have search button. Once I select and click Search, the total price of selected items has to be calculated and displayed.
My search code ( Thanks to Alex sir)
enter code here
Private Sub CommandButton4_Click()
Dim Cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sName As String
Set Cn = New ADODB.Connection
Cn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=d:\test2.accdb;Persist Security Info=False"
Cn.ConnectionTimeout = 40
Cn.Open
Set rs = New ADODB.Recordset
sName = Replace$(TextBox1.Text, "'", "''")
rs.Open "Select * from SampleTable where UserName = '" & sName & "'", Cn, adOpenForwardOnly, adLockReadOnly, adCmdText
If (rs.EOF) Then
MsgBox "no match"
Else
TextBox3.Text = rs("UserName") & " " & rs("Location")
rs.Close
End If
Set rs = Nothing
Cn.Close
Set Cn = Nothing
End Sub
That code was just to search and display in a textbox.
Now, I need to total the price of what all UserName field selected by the user from listbox.
Try this, but make sure the bound column in your list box is the ID field of your table.
Private Function SelectedListString(lstSelected As Access.ListBox) As String
'Loop though a list and get the IDs of all the selected items
'Assumes the bound column is the contains the ID field
Dim sList As String
Dim vSelected As Variant
With lstSelected
For Each vSelected In .ItemsSelected
sList = sList & .ItemData(vSelected) & ","
Next
End With
If sList <> "" Then sList = Left(sList, Len(sList) - 1) 'trim trailing coma
SelectedListString = sList
End Function
you can use the result in an IN statement in your SQL
Dim sSql As String
If myListbox.ItemsSelected.Count > 0 Then
sSql = "SELECT * FROM table WHERE IDField IN (" & SelectedListString(myListbox) & ")"
End If