Passing multiple criteria to query in access via VBA code - vba

I am working on a Access database that I inherited from the person working on it before me. I am novice at this and learning as I go along.
Background:
I am working with a database of experimental data.
I am trying to create a search and export form which will allow the the user to search for a particular data set and then export that to an excel sheet. It will also let the user filter the search so as to write only specific values into the excel file.
My data base has 2 main sub tables differentiating the kind of experiments.
I use a list box that allows the user to choose which table he/she wants to search.
based on this selection two additional listboxes get populated with the relevant options
the options are "Author Name" and a "Number ID"
Upto this point everything works
if table 1 is selected one set of author names and number ids are populated in the list boxes and the same is true if table 2 is selected.
the author name and also the number id list boxes are simple multiselect.
I loop over the list box selection to get all the values selected
I then create the SELECT and IN statement.
This works like a charm for the number id (when i execute with only 1 list box).
However I get an error if i try to create a query statement as follows:
SELECT * FROM tbl1 [Number_ID] IN (a,b,...) AND
SELECT * FROM tbl1 [AUTHOR_NAME] IN ("xyz", "abc",....)
where Number_ID is an Integer and
Author_Name is text

Solution:
strSQL = "SELECT * FROM tbl1 WHERE "
strWhere = "[Number_ID] IN (1, 2, 3, ...)"
strSQL = strSQL & strWhere
strSQL1 = " AND "
strWhere1 = "[Author_Name] IN ("xyz", "abc", ...)"
strSQL = strSQL & strSQL1 & strWhere1
This generates a query string as follows
"SELECT * FROM tbl1 WHERE [Number_ID] IN (1, 2, 3, ...) AND [Author_Name] IN
("xyz", "abc", ...)"
which can be passed to your qryDef variable to create a query.

Related

Is it possible to make a dynamic sql statement based on combobox.value in access?

I made a form in access with 2 different comboboxes. The user of
This tool can choose in combobox1: the table (which has to be filtered) and the second combobox2 is the criteria to be filtered( for example Language= “EN”) and the output of this query has to be located in tablex.
The problen what I have is that i cant find a solution for passing the value of the combobox1 to the sql statement. The second one is just like: where [language] = forms!form!combo2.value, but the part where i cant find a solution for is: select * from (combobox1 value)? How can i pass the combobox value as table name to be filtered? Can anyone please help me?
You can't have the table name in the WHERE clause of your query (there might be a hacky way to do it, but it should be discouraged at any case).
If you want to select data from 1 of a number of tables, your best bet is to generate SQL dynamically using VBA. One way to do this (especially if you want/need your query to open in Datasheet View for the end user) is to have a "dummy" query whose SQL you can populate using the form selections.
For example, let's say we have 2 tables: tTable1 and tTable2. Both of these tables have a single column named Language. You want the user to select data from either the first or second table, with an optional filter.
Create a form with 2 combo boxes: One for the tables, and one with the criteria selections. It sounds like you've already done this step.
Have a button on this form that opens the query. The code for this button's press event should look something like this:
Private Sub cmdRunQuery_Click()
Dim sSQL As String
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
If Not IsNull(Me.cboTableName.Value) Then
sSQL = "SELECT * FROM " & Me.cboTableName.Value
If Not IsNull(Me.cboFilter.Value) Then
sSQL = sSQL & vbNewLine & _
"WHERE Language=""" & Me.cboFilter & """"
End If
Set db = CurrentDb
Set qdf = db.QueryDefs("qDummyQuery")
qdf.SQL = sSQL
DoCmd.OpenQuery qdf.Name
End If
End Sub
Note how the SQL is being generated. Of course, using this method, you need to protect yourself from SQL injection: You should only allow predefined values in the combo box. But this serves as a proof of concept.
If you don't need to show the query results, you don't need to use the dummy query: You could just open a recordset based on the SQL and process that.
If you run the code in the afterupdate event of the combobox you can set an SQL statement like this:
Private Sub combobox2_AfterUpdate()
someGlobalVar = "Select * FROM " & me.combobox1.value & " WHERE language = " & _
me.combobox2.value
End Sub
And then call the global with the SQL string wherever you need it.

Writing Dynamic SQL Statement

I am very new to Microsoft Access.
I would like to select a column from a table based on the value of a parameter (i.e. my table has columns x, y and z and I have a chosencol parameter which is set by the user using a dropdown.
I can select one / all of the columns using a select command, however, I would like to do this using my parameter chosencol instead.
Having read around, I have found a number of references to using the SET and EXEC commands, however, entering them into the SQL command in Access just yields errors.
Please could someone advise me as to how I go about implementing a dynamic-sql query in Access (in fine detail as I think I am writing the commands in the wrong place at the moment...)
First I created an example table in Access.
Next, I created an example form to query your value. The dropdown is called 'chosencol'. Select a value from the Column Select dropdown and press the "Lookup Value" button.
Here is the code under the "Lookup Value" button's On Click event. A SQL statement is dynamically built with the column you chose. The column is renamed to [FieldName] to that it can by referenced.
Private Sub btnLookup_Click()
Dim rsLookup As New ADODB.Recordset
Dim strSQL As String
strSQL = "select " & chosencol.Value & " as [FieldName] from Table1 where ID=1"
rsLookup.Open strSQL, CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
If rsLookup.EOF = False Then
txtValue.SetFocus
txtValue.Text = rsLookup![FieldName]
End If
rsLookup.Close
End Sub
When the button is pushed, the value from whatever column you selected will be returned. For this simple example, I'm always returning row 1's data.
I'm pretty sure you can't do that in straight SQL. However, you can create the SQL string in VBA code and save it as a query.
CurrentDB.CreateQueryDef("MyQueryName", "SELECT " & chosencol & " FROM MyTable")
Now, MyQueryName will be a permanent query in your database and can be referenced wherever you want.
If chosencol is a multi-select dropdown, you'll have to read the selected values into an array and then write the array to one concatenated string and use that instead.

GUI using VBA in access. Recordset from query

Making GUI in Access with VBA (first time i saw it in this semester and it looks unusual for me). I got table Authors where i got columns author_id, last_name, first_name and table Books with columns author_id, book_name.
I got button on Form which on click should ask user to input author last name and then search and show all books of this author.
So I trying to find author id from Authors table and then from Books table show all books where author.author_id is equal to books.author_id.
I was thinking that i need to create temp query which contained author_id value and after that create record set with this query using SQLquery like "SELECT [Books].[book_name] AS [Bookname] FROM [Books] WHERE [Books].[author_id] = [test].[ID]" But i stucked here - I trying to just check if this thing working but it says there is an error 3061
Private Sub authorlist_Click()
Dim dbs As Database, authorsRS, booksRS As Recordset, queryStr, idbynameQuery, srchASurStr, strOutput, srId As String, qdf As QueryDef
Set dbs = CurrentDb()
srchASurStr = InputBox("Input author surname, please", , , 100, 100)
strQuery = "SELECT [Authors].[author_id] AS [ID] FROM [Authors] WHERE [Authors].[last_name] = " & srchASurStr & ""
Set authorsRS = dbs.OpenRecordset(strQuery, dbOpenSnapshot)
With dbs
Set qdf = .CreateQueryDef("test", strQuery)
DoCmd.OpenQuery "test"
.QueryDefs.Delete "test"
End With
End Sub
So could you help me please to understan what's wrong? And is there maybe more simple way to show all books of some author (maybe without using SQL querys)?
String values in an SQL statement need to be surrounded with single-quotes (') or double-quotes ("):
SELECT author_id FROM authors WHERE last_name = "Smith"
If written without the quotes:
SELECT author_id FROM authors WHERE last_name = Smith
Smith will be understood to be a field name and not a string value. So your code should look something like this:
'Chr returns a string from a character code. 34 is the code for "
strQuery = "SELECT author_id FROM authors WHERE last_name = " & Chr(34) & srchASurStr & Chr(34)
In VBA, you can escape double-quotes with a string by doubling them:
strQuery = "SELECT author_id FROM authors WHERE last_name = """ & srchASurStr & """"
SQL injection: Keep in mind that if the user inputs a string with " in it, there will probably be an error, as the resulting SQL statement has invalid syntax:
SELECT author_id FROM authors WHERE last_name = "Smi"th"
The right way to avoid this problem is to use parameters.
Some notes:
You can reference a form control within a query: [Forms]![FormName]![ControlName]. Thus, you can create a saved query that filters based on a form textbox, instead of using an inputbox.
Consider using a combobox to have the user select from a list, instead of having the user type free text. The combobox can have multiple columns, with the value of the combobox being the first column (author_id) and the displayed value being another expression (last_name or last_name & " " & first_name). If you set the ColumnWidths property to 0 (for the first column), the next column will be displayed
If you prefer to use a textbox, consider using the LIKE operator in your query, to display all authors whose last_name contains the user string:
SELECT author_id FROM authors WHERE last_name LIKE "%sm%"
will return Smith, Smythe, and Asmodeus.
I suggest you set up a form and subform. The form can contain author details and the subform can contain books by that author, you can further add a textbox that the user can fill in with part of the author name. You can then apply a filter to the main form to show all the authors with that name.
Me.Filter = "Author Like '*" & Me.Search & "*'"
Me.FilterOn = True
There are a number of variations on this, the user could select names from a combo or listbox. The form could be a continuous form with a filter / search in the header and so on.

hiding/showing multiple columns based on combo box in access

I have a form with a subform which contains upto 100 columns however i only need to see 5 of these columns at any one time. The columns I need to see are always First name and surname plus three other columns based on the choices made in the main form (columns have labels such as HT001, HT002 etc.). One column for each of the three combo boxes available. I have looked everywhere for a solution and keep finding
Me![mycontrol].columnhidden = false
which I can see how it works for one or two columns but my code would need to be rediculously long if each column needs this. In addition to the vast quantity of columns I have 12 different subforms which are choosen from using a select case procedure. I am looking for a simple solution as I am still very much learning VBA.
If you are using a datasheet, you can dynamically set the record source according to the selections made.
Me.RecordSource = "SELECT HT001, HT002 FROM MyTable"
You can refer to the combo box when building your sql:
Me.RecordSource = "SELECT HT001, " & Me.Combo1 & " FROM MyTable"
Some notes on using a listbox with a field list from a table.
You can set the row source type to Field list and the row source to the name of a table:
RowSource: Table1
RowSourceType: Field List
In order to select multiple fields, it is important to set the multiselect property:
MultiSelect : Simple
You can iterate through the selected items in code and build a field list for use in your sql:
For Each itm In Me.List0.ItemsSelected
strSelect = strSelect & "," & Me.List0.Column(0, itm)
Next
strSelect = Mid(strSelect, 2)
sSQL = "SELECT " & strSelect & " FROM Table1"

copying fields in access by a macro/button on a form

Good day
ms-access 2007
I have 2 sub-Datasheet's on my form,
One display a list of items.
the other is blank.
Is there a way by placing a button on the form "Copy/Add", it copies the highlighted field to a field in the blank data-sheet.
both field's are of the same type.
Thank you
Probably the easiest thing is to run an append query. Let us say the button is on the main form, you would need a little code on the lines of:
Set db = CurrentDB
strSQL = "INSERT INTO TableB (ID, SomeField) " _
& "SELECT ID, SomeField FROM TableA WHERE ID = " _
& Me.[NameOfSubformControl].Form.[NumericIDField]
db.Execute strSQL, dbFailOnError
You will need quotes if the ID field is not numeric.