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

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.

Related

Return Query Value Using VBA function in Access

I'm currently working on a project and I've been having trouble trying to get a function that is able to return the value of a query, which I do need in order to display it on a textbox.
The current code is like this:
Public Function rubrieknaamSQL() As String
Dim rst As DAO.Recordset
Dim strSQL As String
strSQL = "SELECT T_Train.trainPlate, T_Category.categoryName FROM T_Category INNER JOIN T_Train ON T_Category.id = T_Train.category_id WHERE (((T_Train.trainPlate)=[Forms]![F_Comboio]![Combo_Search_Comboio]));"
Set rst = CurrentDb.OpenRecordset(strSQL)
rubrieknaamSQL = rst!categoryName
rst.Close
End Function
I should say that the code is copied from other publisher and I do not own its rights. However, it still won't work when I try to run it and the error displayed goes like this:
Run-Time Error 3061 : Too few parameters. Expected 1
and it happens in Set rst command.
For a SELECT query to set a recordset object, concatenate variable:
" ... WHERE T_Train.trainPlate=" & [Forms]![F_Comboio]![Combo_Search_Comboio]
If trainPlate is a text field, need apostrophe delimiters (date/time field needs # delimiter):
" ... WHERE T_Train.trainPlate='" & [Forms]![F_Comboio]![Combo_Search_Comboio] & "'"
For more info about parameters in Access SQL constructed in VBA, review How do I use parameters in VBA in the different contexts in Microsoft Access?
There are ways to pull this single value without VBA.
make combobox RowSource an SQL that joins tables and textbox simply references combobox column by its index - index is 0 based so if categoryName field is in third column, its index is 2: =[Combo_Search_Comboio].Column(2)
include T_Category in form RecordSource and bind textbox to categoryName - set as Locked Yes and TabStop No
build a query object that joins tables without filter criteria and use DLookup() expression in textbox
=DLookup("categoryName", "queryname", "trainPlate='" & [Combo_Search_Comboio] & "'")

Setting listboxes in MS access form - row by row

I have a requirement in MS Access where a table is displayed as several rows in the form. I have created one form detail record(several fields) that will repeat for each row in the Table1. Lets say I have five columns in the Table1. Based on Column3 value, I would like to have a list of value for Column4 and Column5 during form_load. I have also created a separate Table2 to establish relationship between Column3, Column4 and Column5. I have set up Event procedure to populate the values using sub function. The challenge I have is, not being able to set up different listbox 'value list' for different rows. Any tips on populationg form fields IMRecomExIns and AmendReasonExIns by processing each row in Table1 would be a great help.
Private Sub IMRecomExIns_Click()
Dim CoverType As String
Dim ListRecomm As String
Dim ListAmend As String
Dim db As DAO.Database
Dim tablevar As Recordset
Set db = CurrentDb
Set tablevar = db.OpenRecordset("Table2")
CoverType = "*" & Me.CoverTypeExIns.Value & "*"
ListRecomm = ""
ListAmend = ""
If tablevar.EOF = False And tablevar.BOF = False Then
tablevar.MoveFirst
Do Until tablevar.EOF
If tablevar!CoverType Like CoverType Then
ListRecomm = tablevar!Recommendation
ListAmend = tablevar!AmendReason
tablevar.MoveLast
End If
tablevar.MoveNext
Loop
End If
Me.IMRecomExIns.RowSourceType = "Value list"
Me.IMRecomExIns.RowSource = ListRecomm
Me.AmendReasonExIns.RowSourceType = "Value list"
Me.AmendReasonExIns.RowSource = ListAmend
End Sub
1) I have stored all the value list in a single cell. For example tablevar!Recommendation will have all the values for Me.IMRecomExIns.RowSource, which means the output is will look like "Rec1";"Rec2";"Rec3";etc... Same applies for tablevar!AmendReason "AR1";"AR2';"AR3";ETC... Understand this is not the normalized form of storing data. I want to POC to work before building a full solution with normalized tables.
2) Answered earlier.. the rowsource will be set with all the possible values at the first match, so no point in going all the way to the end of the table
3) CoverTypeExIns is a string, Table 2 have many different possibilities such as "Mortgage Income" and "Family Income", however the Recommendation and Amendreason are same for all "Income" category that comes from Table1. Thats why the wildcard search.
My problem is not with setting the RowSource for a single row, but setting up RowSource for multiple occurrence in of the same IMRecommmendation and AmendReason in MS Access screen.
Here is the design view of the form. This form is linked to MS Access table. For multiple rows the Detail record will repeat itself as many times.
An example of two rows displayed in the screen.
I'm not sure exactly what you are asking/trying to do here.
I can see at several problems with the code that you have:
You are using tablevar.MoveLast in the loop, whic would automatically take you to the end of the recordset.
Also, you are not concatenating (joining together) ListRecomm/ListAmend, you are just setting them equal to a value, so each loop that matches will overwrite any previous value.
Finally, I am not sure what you are doing with trying to find CoverTypeExIns - you are using LIKE, which would indicate that it is text, but not wrapping the value in single quotes. If it is a numeric value, then you should be using "=".
However, rather than opening a recordset, looping it and checking for a match to build up a list of values, it is better to just set the RowSource of listboxes equal to a SQL string (effectively a query).
Something like (assuming CoverType is numeric):
Private Sub IMRecomExIns_Click()
Dim strSQL As String
strSQL = "SELECT Recommendation FROM Table2 WHERE CoverType=" & Me!CoverTypeExIns
Me!AmendReasonExIns.RowSource = strSQL
End Sub
I prefer to declare a string to hold the SQL statement rather than setting the .RowSource directly, as it makes troubleshooting easier.
Regards,
Based on the new information given, below is some VBA code that opens up a recordset based on the information entered in "Cover", and then sets the .RowSource property of the two combo boxes to be the value lists. In my example, don't bother setting the .RowSourceType, as this should be done at design time:
Private Sub IMRecomExIns_Click()
Dim db As DAO.Database
Dim rsData As DAO.Recordset
Dim strSQL As String
Set db = DBEngine(0)(0)
strSQL = "SELECT Recommendation, AmendReason FROM Table2 WHERE CoverType LIKE '*" & Me!cboCover & "*';"
Set rsData = db.OpenRecordset(strSQL)
If Not (rsData.BOF And rsData.EOF) Then
Me!IMRecomExIns.RowSource = rsData!Recommendation
Me!AmendReasonExIns.RowSource = rsData!AmendReason
End If
rsData.Close
Set rsData = Nothing
Set db = Nothing
End Sub
As I have previously stated, you should really normalize the design of your database now, rather than getting in so far that it requires a major re-write.
Regards,

Access Filter By Field

Just curious if filtering fields is a possibility in Access? Or if there is VBA code that allows the "Show" Box in the query to be checked or unchecked based on an if statement?
Basically I have about 80 fields in my database and I want to create a table with only 3 of them, based on a value in a combo box. 2 are always the same, and the 3rd would be based on a combo box.
Can I do that?
You could do this by altering the SQL of the query object you want to modify. So if your query object is named "qryMyQ", and your combo box object is named "cboDropDown", then the VBA would be the combo box's AfterUpdate event and would look like this:
Private Sub cboDropDown_AfterUpdate()
Dim qryDef As QueryDef
Dim sql As String
Set qryDef = CurrentDb.QueryDefs("qryMyQ")
sql = "SELECT [Column1], [Column2], [" & cboDropDown.Value & _
"] FROM yourTableName " & _
" WHERE [" & cboDropDown.Value & "] = ""applicable"""
Debug.Print sql 'This line will allow you to troubleshoot the SQL that is to be executed.'
qryDef.sql = sql
Set qryDef = Nothing
End Sub
Just a note here; but you'd want to make sure that users cannot add or edit the combo box options to avoid sql injections. Not sure how friendly your userbase is.

How can I add criteria based on a form field to an Access query?

How do I get an operator to work in a query criteria based on a form field. Ideally I would like it to be something like:
IIf([Afloat]="No",<[Forms]![DASF]![Text222],"")
When I remove the operator it finds anything exactly to the criteria in that field but the moment I try to put an operator like greater than or less than it does not work. I am trying to find all records less than the value in that form field.
Any advice on how I can fix this? Or is it not possible in MS Access?
QBF (Query By Form) can't accept operators in the formula. Your only option is to write the query on the fly. You can use the CreateQueryDef method to define the SQL in a specific query, and attach your form or report to the specific query name.
Something like:
Dim db as Database
Dim rec as Recordset
Dim qdf As QueryDef
Dim strSQL as String
Set db = CurrentDB
On Error Resume Next
'First, delete the query if it exists
db.QueryDefs.Delete "MyQueryName"
'Then, set up the query string
strSQL = "Select * From MyTable Where MyField < " & [Forms]![DASF]![Text222] & " and [Afloat] = 'No' "
strSQL = strSQL & "UNION "
strSQL = strSQL & "Select * From MyTable Where MyField = '' and [Afloat] <> 'No' "
'Now, recreate the query
Set qdf = db.CreateQueryDef("MyQueryName", strSQL)
DoCmd.OpenQuery qdf.Name
You could try changing the first criteria to:
>IIf([Afloat]="No",[Forms]![DASF]![Text222])
And then add a second criteria below it in the Or line:
=IIf([Afloat]<>"No","")
I ended up solving my problem by separating it into two separate queries. Below are my steps:
Instead of having a logical expression to decide I separated it into
FLOAT and NONFLOAT queries.
Then I created a command button to open
each query depending on the criteria in a combo box (yes or no).
Here is the code:
Private Sub Command2_Click()
DoCmd.SetWarnings False
If Me.Combo272 = "Yes" Then
DoCmd.OpenQuery "DASF_AGED_AS1_FLOAT", acViewNormal, acEdit
Else
DoCmd.OpenQuery "DASF_AGED_AS1_NONFLOAT", acViewNormal, acEdit
End If
End Sub
This created another problem, I was still unable to reference the txt boxes necessary for my query criteria. To solve this, I made all the text boxes unbound by using the below VBA to auto populate the text boxes based on another combo box. Here is the VBA I used:
Me.Text220 = DLookup("REGION", "TDD_TABLE", "[ID]= " & Me.Combo236)

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.