make drop-down fields dependent of each other - ms-access

I set-up a form with with project details and want to implement several drop-down options to filter project properties. These are "project-name", "customer" and "product". I want to make them dependent on each other. So when I select a particular customer, I only want to be able to choose from products which are related to the customer.
So far I was able to set-up each drop-down for each project property but they are not dependet of each other, but always show all available options. Can someone help me out with dependent drop-down fields?
Selection fields as they are now
Edit: Table layout upon request:
Rows/format
-Project ID/Number
-Customer/String
-Product/String
-Project-name/String
-Comment/String
-Feature 1/String

One way of doing this to to use "cascading" combo boxes, so the user moves from the top combo box towards the bottom one, each time narrowing the range available to them.
Your VBA code would look something like this:
Private Sub cboCustomer_AfterUpdate()
Dim strSQL As String
If Len(Me!cboCustomer) > 0 Then
strSQL = "SELECT DISTINCT Product FROM tblProject " _
& " WHERE Customer='" & Me!cboCustomer & "' " _
& " ORDER BY Product ASC;"
Me!cboProduct.RowSource = strSQL
Else
strSQL = "SELECT DISTINCT Product FROM tblProject ORDER BY Product ASC;"
End If
End Sub
Private Sub cboProject_AfterUpdate()
Dim strSQL As String
If Len(Me!cboProject) > 0 Then
strSQL = "SELECT DISTINCT Customer FROM tblProject " _
& " WHERE ProjectID=" & Me!cboProject _
& " ORDER BY Customer ASC;"
Me!cboCustomer.RowSource = strSQL
strSQL = "SELECT DISTINCT Product FROM tblProject " _
& " WHERE ProjectID=" & Me!cboProject _
& " ORDER BY Product ASC;"
Me!cboProduct.RowSource = strSQL
Else
Me!cboCustomer.RowSource = "SELECT DISTINCT Customer FROM tblProject ORDER BY Customer ASC;"
Me!cboProduct.RowSource = "SELECT DISTINCT Product FROM tblProject ORDER BY Product ASC;"
End If
End Sub
Regards,

Related

SELECT Queries in Access VBA

I have an Access database consisting of two tables, Individuals & Pairs. Individuals consists two columns; 'Bird_ID' and 'Parents_Pair_number' and Pairs consists of three columns; 'Pair', 'Female_ID' and 'Male_ID'. 'Parents_Pair_number' and 'Pair' have a Many-to-one relationship. Via this relation one can check the parents of an individual.
But now I was thinking of making automatized family trees using a form. My plan was to make a field (Bird_ID_Field) in which you can find a certain individual and that other fields such as Father, Mother, Fathers father etc. etc. would auto-fill based on that entry.
I tried to auto-fill the Father_ID (Field) using the following VBA code:
Dim strSQL As String
Dim strBird_ID As String
If Bird_ID_Field <> "" Then
strBird_ID = Bird_ID_Field
strSQL = "SELECT Pairs.[Male_ID] " & _
"FROM Pairs " & _
"WHERE PAIR = (SELECT Individuals.[Parents_Pair_number] FROM Individuals WHERE Individuals.[Bird_ID]= '" & strBird_ID & "');"
DoCmd.OpenQuery strSQL
Father_ID = strSQL
End If
But after updating the Bird_ID_Field I get the following error: Microsoft Access can't find the object ''.
Do you have any idea what's wrong?
Thanks in forward!
Jeroen
You should use recordsets:
Dim rst As Recordset
Dim strSQL As String
If Nz(Bird_ID_Field,"") <> "" Then
strBird_ID = Nz(Bird_ID_Field, "")
strSQL = "SELECT Pairs.[Male_ID] " & _
"FROM Pairs " & _
"WHERE PAIR = (SELECT Individuals.[Parents_Pair_number] FROM Individuals WHERE Individuals.[Bird_ID]= '" & strBird_ID & "');"
Set rst = CurrentDb.OpenRecordset(strSQL)
If rst.RecordCount > 0 Then
Father_ID = rst![Male_ID]
End If
End If
rst.Close
Set rst = Nothing
And also I would recommend to use JOIN for tables joining instead of subquery.

MS Access - Data selection has changed

I have a small, but elusive problem:
In MS Access, I have a single result form. On this form I have a list. This list is a subselect based on the ID of the main form. How can I capture the row change, and so update my list?
I am NOT looking for Insert / Update Statements! I have them galore, and they work fine, but do not help me unless each row is updated before / as soon as changing rows.
In my example, the list is Genres for a selected Film.
Private Sub film_name_AfterUpdate()
Dim strNewRecord As String
Dim film_id As Integer
If IsNull(Forms!Films!film_id) Then
GoTo cmdNoRecord_Error
Else:
film_id = Forms!Films!film_id
strNewRecord = "SELECT qry_film_genres.gen_name FROM qry_film_genres " _
& " WHERE film_id = " _
& film_id & " ORDER BY qry_film_genres.gen_name"
Me.Genre_List.RowSource = strNewRecord
End If
Exit Sub
cmdNoRecord_Error:
MsgBox "Please Select a Film."
Exit Sub
End Sub
You just need to use the film_id Change event. I'm assuming the 'film_id' field is on the parent form, and a subform is where the 'Genre_List' control lives.
EG:
Private Sub film_id_Change()
If Not IsNull(Me.film_id) Then
Me.CHILDFORM.Genre_List.RowSource = "SELECT qry_film_genres.gen_name FROM qry_film_genres " _
& " WHERE film_id = " & Me.film_id & " ORDER BY qry_film_genres.gen_name"
End If
End Sub

How to retrieve a specific value from a Table with SQL in VBA

I am trying to access a specific value (CompanyNr) from the TABLE 1 and store it into a variable. To later use it to access the Company name from TABLE 2
MY TABLE EXAMPLES:
TABLE 1 (Contacts):
ID , CompanyNr , Contact
TABLE 2 (Companies):
CompanyNr , Company
I have a ComboBox for Contacts. And I when I select someone from the ComboBox, I want to automaticly filter out Companies in which the selected Contact works.
I have tried like this:
MY CODE:
CompNr = "SELECT [Contacts].[ID], [Contacts].[CompanyNr] FROM Contacts " & _
"WHERE [Contacts].[ID] = " & ContactNrCombo.Value & " ORDER BY [Contact];"
MsgBox "Company Nr:" & CompNr
sq11 = "SELECT [Companies].[CompanyNr], [Companies].[Company] FROM Companies " & _
"WHERE [Companies].[CompanyNr] = " & CompNr & "ORDER BY [Company]; "
But the MsgBox says:
CompNr = SELECT [Contacts].[ID], [Contacts].[CompanyNr] FROM Contacts WHERE [Contacts].[ID] = 255 ORDER BY [Contact]
Yet I need to get a certain value for CompanyNr (like 50 for example) so that I can use it in my other SQL Statement to filter from TABLE 2.
I am new to SQL statements, I just found the above one as an example on internet and thought I could use it. But it didn`t work well.
Any help would be appreciated
You can try something like the following,
Set con = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
con.Open "Provider=..." 'Your Connectionstring
rs.Open "SELECT [Contacts].[ID], [Contacts].[CompanyNr] FROM Contacts " & _
"WHERE [Contacts].[ID] = " & ContactNrCombo.Value & " ORDER BY [Contact]", con, 1,3
'Assuming there is only one company number per contact
rs.MoveFirst
CompNr = rs.Fields("CompanyNr").Value
rs.Open "SELECT [Companies].[CompanyNr], [Companies].[Company] FROM Companies " & _
"WHERE [Companies].[CompanyNr] = " & CompNr & "ORDER BY [Company]", con, 1,3
'If you want to paste the second sql query in excel use this
Sheets("Sheet1").Range("A1").CopyFromRecordset rs
rs.Close
con.Close
Set con = Nothing

VBA Access - Multiple Tables count by date

We'd like to count from an Access database that has multiple tables - about 50.
We need to count from 1 column in each table that is 'QCPASS' This is a check box - if a product passed the box was checked if failed then not. We need to count both for EACH table, also allowing the user to specify a date range from a date column that exists in every table.
I've tried this with a query but I am told the query is unable to select, count and do the date range. Any VBA help would be great.
Exporting to Excel would be great, but any results would be fine. Here is the query I created that counts in a column from each table passes and failures. I can't iterate with a query either, so VBA seems the way to go:
SELECT "Table1" , Count('qcpass') AS column
FROM 5000028
GROUP BY [5000028].qcpass
union
SELECT "Table2",count('qcpass')
FROM 5000029
Group By [5000029].qcpass;
You can traverse the full TableDefs collection in your database, and create a query using VBA.
A word of warning: The TableDefs collection has the Access database system tables, so you need to skip this. A way I suggest you is to check for a specific table name prefix (it is noted in the code below).
public sub createMyBigUnionQuery()
dim db as DAO.database(), tbl as DAO.tableDef
dim strSQL as string, i as integer
set db = currentdb()
i = 1
for each tbl in db.TableDefs
if left(tbl.name, 1) = "5" then ' Check for a table name prefix
if i = 1 then
' The final spaces are important
strSQL = "select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"group by qcpass "
else
' The final spaces are important
strSQL = strSQL & " union all " & _
"select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"group by qcpass "
end if
i = i + 1
end if
next tbl
db.createQueryDef "qryYourFinalQuery", strSQL
db.close
exit sub
Notice that you can define any valid query you want. Take this as a hint, and tweak it to fit your specific needs.
Hope this helps you
Adressing #HansUp comment, if you need to filter your data by date, you have two options:
Include the where condition on every select created by the procedure
Include the date field in your query and group by it, and create a second query to filter the data you need from the created query.
I would personally go with option 1, and here is a sample code:
public sub createMyBigUnionQueryWithDates(d0 as date, d1 as date)
dim db as DAO.database(), tbl as DAO.tableDef
dim strSQL as string, i as integer
set db = currentdb()
i = 1
for each tbl in db.TableDefs
if left(tbl.name, 1) = "5" then ' Check for a table name prefix
if i = 1 then
' The final spaces are important
strSQL = "select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"where rowDate between " & cDbl(d0) & " and " &cDbl(d1) & " " & _
"group by qcpass "
else
' The final spaces are important
strSQL = strSQL & " union all " & _
"select '" & tbl.Name & "' as table, count(qcpass) as column " & _
"from [" & tbl.Name & "] " & _
"where rowDate between " & cDbl(d0) & " and " &cDbl(d1) & " " & _
"group by qcpass "
end if
i = i + 1
end if
next tbl
db.createQueryDef "qryYourOtherFinalQuery", strSQL
db.close
exit sub
The reason I use cDbl(d0) is because Access dates are sensitive to regional settings, and I've had a lot of headaches dealing with it. Access (and many other Microsoft products) store dates as floating-point numbers (the integer part is the date, and the decimal part is the time).
Another word of warning: If your dates don't include time, then the between condition will work. But if they do include time, then I recommend you change the where condition to this:
"where rowDate >= " & cDbl(d0) & " and rowDate < " & cDbl(d1 + 1)"

Crosstab query with date criteria

I have created a crosstab query as below
TRANSFORM Nz(Sum([debit]*[GeneralExpenses]),0) AS mOmomeya
SELECT Expenses.sName, Expenses.ArName
FROM (GL INNER JOIN Expenses ON GL.ID = Expenses.glID) INNER JOIN Transactions ON GL.GL = Transactions.GL
GROUP BY Expenses.sName, Expenses.ArName
PIVOT Month([ddate]);
what I want to do is to add a criteria to the [dDate] field from a form text input to match the date that I entered, but I received error while doing this as below
any idea what's wrong?
Hmmm, there definitely seems to be something a little bit different about crosstab queries. The straight SELECT query...
SELECT expenses.*
FROM expenses
WHERE (((expenses.ddate) Between [Forms]![main]![DateFrom] And [Forms]![main]![DateTo]));
...works fine, but the crosstab query...
TRANSFORM Sum(expenses.expenses) AS SumOfexpenses
SELECT expenses.onduty
FROM expenses
WHERE (((expenses.ddate) Between [Forms]![main]![DateFrom] And [Forms]![main]![DateTo]))
GROUP BY expenses.onduty
PIVOT Month(ddate);
...fails with the error message you cited. One workaround would be to rebuild the SQL for the query before using it:
Dim qdf As DAO.QueryDef
Set qdf = CurrentDb.QueryDefs("yourCrosstab")
qdf.SQL = _
"TRANSFORM Nz(Sum([debit]*[GeneralExpenses]),0) AS mOmomeya " & _
"SELECT Expenses.sName, Expenses.ArName " & _
"FROM (GL INNER JOIN Expenses ON GL.ID = Expenses.glID) INNER JOIN Transactions ON GL.GL = Transactions.GL " & _
"WHERE (((ddate) " & _
"Between #" & Format(CDate([Forms]![main]![DateFrom]), "yyyy-mm-dd") & "# " & _
"And #" & Format(CDate([Forms]![main]![DateTo]), "yyyy-mm-dd") & "#)) " & _
"GROUP BY Expenses.sName, Expenses.ArName " & _
"PIVOT Month(ddate);"
Set qdf = Nothing
DoCmd.OpenQuery "yourCrosstab" '' or whatever you want to do with it
The problem is that crosstab querys require the form parameter for each form. Right click on gray space and select parameter. Put in the forms and data type.