MS Access filter form to open report to specific records - sql

I'm trying to create a form, ReportSearch that has multiple comboboxes and textboxes that will allow the user to narrow down the results shown on the report. Not all fields would have to be used in the search.
On click the following code will ask for the parameter value to be entered for the specific IDs used. If I just click OK without entering anything in the MsgBox the report will be opened with no records.
Private Sub cmdFilter_Click()
Dim strWhere As String
Dim lngLen As Long
Const conJetDate = "\#mm\/dd\/yy\#"
If Not IsNull(Me.cboSearchJob) Then
strWhere = strWhere & "(Job.id = " & Me.cboSearchJob & ") AND "
End If
If Not IsNull(Me.cboSearchEmployee) Then
strWhere = strWhere & "(Employee.ID = " & Me.cboSearchEmployee & ") AND "
End If
If Not IsNull(Me.cboSearchService) Then
strWhere = strWhere & "(Service.ID = " & Me.cboSearchService & ") AND "
End If
If Not IsNull(Me.tboStartDate) Then
strWhere = strWhere & "(DateWorked >= " & Format(Me.tboStartDate, conJetDate) & ") AND "
End If
If Not IsNull(Me.tboEndDate) Then
strWhere = strWhere & "(DateWorked < " & Format(Me.tboEndDate + 1, conJetDate) & ") AND "
End If
lngLen = Len(strWhere) - 5
If lngLen <= 0 Then
MsgBox "No Results", vbInformation, "No Search Available."
Else
strWhere = Left$(strWhere, lngLen)
DoCmd.OpenReport "JobReport", acViewPreview
Reports!JobReport.Filter = strWhere
Reports!JobReport.FilterOn = True
End If
End Sub
For the report I'm using
SELECT [Employees].[FirstName] & " " & [Employees].[LastName] AS EmployeeName, Jobs.JobName, Equipment.Model, Service.Service, Labor.Labor, EmployeeWorkLog.LaborHours, EmployeeWorkLog.EquipmentHours, EmployeeWorkLog.Notes, EmployeeWorkLog.DateWorked, Service.ID
FROM Service RIGHT JOIN (Labor RIGHT JOIN (Jobs RIGHT JOIN (Equipment RIGHT JOIN (Employees RIGHT JOIN EmployeeWorkLog ON Employees.ID = EmployeeWorkLog.EmployeeID) ON Equipment.ID = EmployeeWorkLog.EquipmentID) ON Jobs.ID = EmployeeWorkLog.JobID) ON Labor.ID = EmployeeWorkLog.LaborID) ON Service.ID = EmployeeWorkLog.ServiceID
ORDER BY [Employees].[FirstName] & " " & [Employees].[LastName];
At this point I'm at a complete loss.
Obviously there is something that I'm missing here. Let me know in what way I need to modify this code to get it to open my report JobReport filtered based on my form ReportSearch.
Thanks.

A report isn't dynamic like a form, you can't filter it after it has been opened. When a report is opened in print preview, it reads its data, does the layout and formatting, then it's completely static.
To open a report with filtered data, use the WhereCondition parameter of DoCmd.OpenReport:
DoCmd.OpenReport "JobReport", acViewPreview, WhereCondition:=strWhere

Related

Filter form records by date range using two unbound text boxes

Good afternoon.
I have a continuous form which I want to allow the user to filter by using unbound boxes in the form header. See screenshot of form below:
Form Design View
I can filter error type (Unbound: cboErrorType) and responsibility (Unbound: cboResponsibility) without any issues, but I cannot get the date range to work (Records outside of the selected date range are being returned). Please see screenshot:
Form - filtered
Please see my code below:
Private Sub cmdFilter_Click()
Dim strWhere As String
Dim lngLen As Long
Const conJetDate = "\#dd\/mm\/yyyy\#"
If Not IsNull(Me.cboErrorType) Then
strWhere = strWhere & "([ErrorType] = """ & Me.cboErrorType & """) AND "
End If
If Not IsNull(Me.cboResponsibility) Then
strWhere = strWhere & "([Decision] = """ & Me.cboResponsibility & """) AND "
End If
If Not IsNull(Me.txtStartDate) Then
strWhere = strWhere & "([Date of Error] >= " & Format(Me.txtStartDate, conJetDate) & ") AND "
End If
If Not IsNull(Me.txtEndDate) Then
strWhere = strWhere & "([Date of Error] < " & Format(Me.txtEndDate + 1, conJetDate) & ") AND "
End If
lngLen = Len(strWhere) - 5
If lngLen <= 0 Then
MsgBox "No criteria", vbInformation, "Nothing to do."
Else
strWhere = Left$(strWhere, lngLen)
'Debug.Print strWhere
Me.Filter = strWhere
Me.FilterOn = True
End If
End Sub
I am removing the filters with the following code:
Private Sub cmdResetFilter_Click()
Dim ctl As Control
For Each ctl In Me.Section(acHeader).Controls
Select Case ctl.ControlType
Case acTextBox, acComboBox
ctl.value = Null
End Select
Next
Me.FilterOn = False
End Sub
Please can someone suggest a solution?
If further information is required, let me know and I will oblige.
Many thanks.
The date format must be either the "reverse" US format (mm/dd/yyyy) or the ISO format (which also works for ADO). So try:
Const conJetDate = "\#yyyy\/mm\/dd\#"

Checking Null Value in Access VBA recordset throws null exception?

I have tried this every different way, and it was working yesterday, so I really don't know what changed.
I import a spreadsheet to a temp table in an Access app. Then I set that to be the dao.recordset, and start looping through. I check for the ID to not be null and if not go through checking fields for values, and updating as appropriate. the minute I hit a null, I get a system error "94 - invalid use of null"
It doesn't offer a debug, but I have debugs throughout my code, so I can see where it fails. It fails when I do this check: If IsNull(rstImportCList("columnx")) = False Then
I have tried nz(rstImportCList("columnx"),"") <> "" I have tried rstImportCList("columnx") is not null, and everything else I can think of. Why is the check that is supposed to prevent this error, causing this error?
Edit:
This is the beginning where I declare the recordset I can't get past doing anything with the recordset field.
Dim db As DAO.Database
Dim rstImportCList As DAO.Recordset
Dim RSsql As String
Set db = CurrentDb()
RSsql = "Select * from tblTempImportCList"
Set rstImportCList = db.OpenRecordset(RSsql)
If rstImportCList.EOF Then Exit Sub
Do While Not rstImportCList.EOF
whether I try to check
IsNull(rstImportCList("xyz").Value) = False
or
nz(rstImportCList("xyz").Value,"") <> ""
or
dim x as string
x = rstImportCList!xyz.value
I get the same error 94 invalid use of null.
Any idea why this is?
--edit with more code.
I took some time to take a the beginning and some of each section of the code, so I could make it generic and see if anyone can help. Here is what I am working on. The Code1 and Code2 parts don't seem to be the issue. Sometimes it fails on a null value in a Yes/No column (I'm just looking for Y but the value is null), sometimes on the notes being null. It's not consistent, which is why I'm having a hard time nailing down the issue.
Private Sub cmdImportList_Click()
On Error GoTo cmdImportExcel_Click_err:
Dim fdObj As FileDialog
Set fdObj = Application.FileDialog(msoFileDialogFilePicker)
Dim varfile As Variant
Dim importCT As Integer
Dim dbu As DAO.Database
Dim cBadXVal, cBadYVal As Integer
Dim preNotes As String
Dim RSsql As String
Dim uNotesql, uVal1sql, uVal2sql As String
Dim db As DAO.Database
Dim rstImportCList As DAO.Recordset
Dim CheckB4Import As Integer
CheckB4Import = MsgBox("Are you SURE the sheet you are importing has the following column names in the same order:" & vbCrLf & vbCrLf & _
"IDName/ First/ Mid/ Last/ Sfx/ Age/ Telephone/ Code1/ Code2/ YN1/ YN2/ NY3/ Notes/ AsYN1edTo" & vbCrLf & vbCrLf & _
"AND that there are NO empty rows or empty columns?" & vbCrLf & vbCrLf & _
"Click OK to proceed, Click CANCEL to go double-check your CallSheet before importing.", vbOKCancel, "WITH GREAT POWER COMES GREAT RESPONSIBILITY TO QC DATA")
If CheckB4Import = vbOK Then
CurrentDb.Execute "DELETE * FROM tblTempImportCList", dbFailOnError
With fdObj
'CAN ONLY SELECT 1 FILE
.allowmultiselect = False
.Filters.Clear
.Filters.Add "Excel 2007+", "*.xlsx"
.Title = "Please select the completed list to import:"
.Show
If .SelectedItems.Count = 1 Then
varfile = .SelectedItems(1)
DoCmd.TransferSpreadsheet acImport, , "tblTempImportCList", varfile, True, "Sheet1!"
cBadXVal = DLookup("BadXCount", "qryImpCheckBadXVal")
Debug.Print "cBadXVal - " & cBadXVal
If cBadXVal <> 0 Then
DoCmd.OpenForm "frmImportError", acNormal
Forms!frmImportError.Form.lblErrorMsg.Caption = _
"Oh No! Your list import failed!" & vbCrLf & _
cBadXVal & " X values are not valid." & vbCrLf & _
"Don't worry. You can fix your sheet and re-import!" & vbCrLf & _
"Would you like to open the documentation for the valid codes" & vbCrLf & _
"Or are you all set?"
End If
cBadYVal = DLookup("BadYCount", "qryImpCheckBadYVal")
Debug.Print "cBadYVal - " & cBadYVal
If cBadYVal <> 0 Then
DoCmd.OpenForm "frmImportError", acNormal
Forms!frmImportError.Form.lblErrorMsg.Caption = _
"Oh No! Your list import failed!" & vbCrLf & _
cBadYVal & " YN1 values are not valid." & vbCrLf & _
"Don't worry. You can fix your sheet and re-import!" & vbCrLf & _
"Would you like to open the documentation for the valid codes" & vbCrLf & _
"Or are you all set?"
Exit Sub
End If
Else
MsgBox "No file was selected. Try again!", vbCritical, "Uh-oh Spaghettios!"
End If
End With
'PASSED CHECKS
Set db = CurrentDb()
RSsql = "Select * from tblTempImportCList"
Set rstImportCList = db.OpenRecordset(RSsql)
If rstImportCList.EOF Then Exit Sub
Debug.Print "got here"
Do While Not rstImportCList.EOF
Debug.Print "Start Processing: " & Nz(rstImportCList("IDName").Value, "")
'GET NOTES ALREADY ON RECORD
If Nz(rstImportCList("IDName").Value, "") <> "" Then
Debug.Print "got past if IDName is not null"
If Nz(rstImportCList("Notes").Value, "") <> "" Then
Debug.Print "got past if notes is not null"
preNotes = Replace(Nz(DLookup("Notes", "tblVFileImport", "IDName = " & rstImportCList("IDName").Value), ""), """", "")
'UPDATE NOTES
If Nz(preNotes, "") <> "" Then
uNotesql = "Update tblVFileImport SET tblVFileImport.Notes = '" & preNotes & "; " & Replace(Nz(rstImportCList("Notes").Value, ""), """", "") & "' " & _
"WHERE tblVFileImport.IDName = " & rstImportCList("IDName").Value
'debug.print "Notes"
'debug.print "uNotesql - " & uNotesql
Else
uNotesql = "Update tblVFileImport SET tblVFileImport.Notes = '" & Replace(Nz(rstImportCList("Notes").Value, ""), """", "") & "' " & _
"WHERE tblVFileImport.IDName = " & rstImportCList("IDName").Value
End If
RunMySql (uNotesql)
'DoCmd.RunSQL (uNotesql), dbFailOnError
End If
If Nz(rstImportCList("YN1").Value, "") = "Y" Then
'UPDATE YN1
uYN1sql = "Update tblVFileImport SET tblVFileImport.YN1 = '" & rstImportCList("YN1") & "', tblVFileImport.callprocessed = 'Y' " & _
"WHERE tblVFileImport.IDName = " & rstImportCList("IDName")
Debug.Print "YN1 = Y or y"
Debug.Print "uYN1sql - " & uYN1sql
RunMySql (uYN1sql)
'DoCmd.RunSQL (uYN1sql), dbFailOnError
End If
If Nz(rstImportCList("YN2").Value, "") = "Y" Then
'UPDATE YN2
uYN2sql = "Update tblVFileImport SET tblVFileImport.YN2 = '" & rstImportCList("YN2") & "', tblVFileImport.callprocessed = 'Y' " & _
"WHERE tblVFileImport.IDName = " & rstImportCList("IDName")
Debug.Print "YN2 = Y or y"
Debug.Print "uYN2sql - " & uYN2sql
RunMySql (uYN2sql)
'DoCmd.RunSQL (uYN2sql), dbFailOnError
End If
'START Code1 PROCESSING
If Nz(rstImportCList("Code1").Value, "") <> "" Then
'Code1 Case abc
vdispo = DLookup("Code1", "tblvFileImport", "IDName = " & rstImportCList("IDName"))
If rstImportCList("Code1") = "ABC" Then
Debug.Print "Dispo Case ABC"
'DELETE RECORD
dMDsql = "DELETE from tblVFileImport " & _
"WHERE tblVFileImport.IDName = " & rstImportCList("IDName")
Debug.Print "dMDsql - " & dMDsql
RunMySql (dMDsql)
'DoCmd.RunSQL (dMDsql), dbFailOnError
'Code1 Case DEF OR GHI OR JKL
ElseIf Nz(rstImportCList("Code1"), "") = "DEF" Or Nz(rstImportCList("Code1"), "") = "GHI" Or Nz(rstImportCList("Code1"), "") = "JKL" Then
Debug.Print "Dispo Case DEF OR GHI OR JKL "
'IF DEF
If rstImportCList("Code1") = "DEF" Then
'IF CELL SAME - UPDATE NULL
ccellsame = DLookup("IDName", "tblVFileImport", "IDName = " & rstImportCList("IDName") & " AND nz(Cell,'') = Phone ")
If ccellsame = rstImportCList("IDName") Then
uCellsql = "Update tblVFileImport SET tblVFileImport.Cell = NULL, tblVFileImport.CellString = NULL, tblVFileImport.mobileflag = NULL " & _
"WHERE tblVFileImport.IDName = " & rstImportCList("IDName")
Debug.Print "uCellsql - " & uCellsql
RunMySql (uCellsql)
'DoCmd.RunSQL (uCellsql), dbFailOnError
End If
End If
End If
End If
End If
Debug.Print "End Processing: " & rstImportCList("IDName")
rstImportCList.MoveNext
Loop
Debug.Print "Finished Looping"
rstImportCList.Close
importCT = DCount("IDName", "tblTempImportCList")
MsgBox importCT & " Records imported for list.", vbOKOnly, "List Processed"
Else
MsgBox "Good Call. Check twice, import once!", vbOKOnly, "Better Safe Than Sorry"
End If
Exit Sub
cmdImportExcel_Click_err:
Select Case Err.Number
Case Else
Call MsgBox(Err.Number & " – " & Err.Description, vbCritical + vbOKOnly, "System Error …")
End Select
End Sub
Any suggestions are greatly appreciated. I'm 1/2 tempted to suck this into a SQL table and just execute a stored procedure. I can get it to work in there, I think.
If IsNull(rstImportCList("columnx").Value) Then
otherwise you're checking if the Field object itself is null.
https://learn.microsoft.com/en-us/office/client-developer/access/desktop-database-reference/field-object-dao#:~:text=To%20refer%20to,Fields(%22name%22)
This is a case where relying on a default property (in this case Value) causes problems.

Search Query Works First Time but subsequent runs get run-time error 3075 extra ) in query expression

I have gone through all previous questions asked and even tried the solutions but to no avail so here's my dilemna. I have used a search query from Allenbrowne which was initially great. However, I wanted to add to the search criteria which again I have done and when searching for the first time I got the results I was looking for. I now use a different code to remove all the search criteria and to unfilter the form (split form). Again everything works. Now I want to search again either using the same of different parameters and this time I get the run-time error 3075 stating that I have an extra ) in the query expression. I have even looked up the query to see where this extra ) is but to no avail. The code is as follows and it errors on Me.Filter = strWhere. I have also provided the reset filter when clearing the search screen and wanting to start a new search. Any help would really be appreciated.
Option Compare Database
Option Explicit
Private Sub cmdFilter_Click()
Dim strWhere As String 'The criteria string.
Dim lngLen As Long 'Length of the criteria string to append to.
'***********************************************************************
'Look at each search box, and build up the criteria string from the non-blank ones.
'***********************************************************************
If Not IsNull(Me.txtCustID) Then
strWhere = strWhere & "([Customer_ID] = " & Me.txtCustID & ") AND "
End If
If Not IsNull(Me.txtJobID) Then
strWhere = strWhere & "([Job_ID] = " & Me.txtJobID & ") AND "
End If
If Not IsNull(Me.txtName) Then
strWhere = strWhere & "([Name] Like ""*" & Me.txtName & "*"") AND "
End If
If Not IsNull(Me.TxtPostcode) Then
strWhere = strWhere & "([Postcode] = ""*" & Me.TxtPostcode & "*"") AND "
End If
If Not IsNull(Me.txtCompany) Then
strWhere = strWhere & "([CompanyName] Like ""*" & Me.txtCompany & "*"") AND "
End If
If Not IsNull(Me.txtLocation) Then
strWhere = strWhere & "([Location] Like ""*" & Me.txtLocation & "*"") AND "
End If
If Not IsNull(Me.CboStatus) Then
strWhere = strWhere & "([Status] = " & Me.CboStatus & ") AND "
End If
If Not IsNull(Me.CboSource) Then
strWhere = strWhere & "([EnquirySource] = " & Me.CboSource & ") AND "
End If
'See if the string has more than 4 characters (a trailng " AND ") to remove.
lngLen = Len(strWhere) - 4
If lngLen <= 0 Then 'Nah: there was nothing in the string.
MsgBox "No criteria", vbInformation, "Nothing to do."
Else 'Yep: there is something there, so remove the " AND " at the end.
strWhere = Left$(strWhere, lngLen)
'For debugging, remove the leading quote on the next line. Prints to Immediate Window (Ctrl+G).
Debug.Print strWhere
'Finally, apply the string as the form's Filter.
Me.Filter = strWhere
Me.FilterOn = True
End If
End Sub
Private Sub cmdReset_Click()
'Purpose: Clear all the search boxes in the Form Header, and show all records again.
Dim ctl As Control
'Clear all the controls in the Form Header section.
For Each ctl In Me.Section(acHeader).Controls
Select Case ctl.ControlType
Case acTextBox, acComboBox
ctl.Value = ""
Case acCheckBox
ctl.Value = False
End Select
Next
'Remove the form's filter.
Me.FilterOn = False
End Sub
See this ctl.Value = "" in cmdReset_Click()? I would guess that when you clear the controls, one of them is ending up a zero-length string, but your test in building the filter is for null, not zero-length strings, so something, most likely one of the numerics, is ending up somefield=<blank>. Try:
ctl.Value = Null
As an aside, there is no point in using equals with a wild card:
strWhere = strWhere & "([Postcode] = ""*" & Me.TxtPostcode & "*"") AND "
Should be:
strWhere = strWhere & "([Postcode] Like ""*" & Me.TxtPostcode & "*"") AND "
Or
strWhere = strWhere & "([Postcode] = """ & Me.TxtPostcode & """) AND "

Ms-Access how to use a query with a parameter inside a form

I have an SQL query with a question(alert like) that pops up every time I open it...
For every value inserted in that question you get diffrent result.
I Want to be able to use that query in my form with a combo-box...
I don't know how to exceute the query with the parameter from within the form....
I have no problem using VBA, just tell me how to call the query with the parameter
Thanks,
Fingerman
I usually use my filtering forms using the following principles:
1) I first create a query that includes all the fields I want to display and all the fields I want to filter on. It can use more than one table. I do not set any criteria (WHERE clause) in this query unless there is a condition that always needs to be applied no matter what.
2) Next I create a datasheet form based on this query and I save it, giving it a name that indicates that it's a subform.
3) Next I create an unbound main form and add unbound controls such as textboxes, combos, listboxes, checkboxes, etc. that will be used to filter the different fields. One control can potentially allow a user to search on more than one field depending how you write your filtering routine in VBA.
4) Now it's time to write code on the main form to make this all work. Basically, the code needs to check to see if there are values in any of the controls and if so, it creates a WHERE clause (without the WHERE keyword) and at the very end it sets the subform's filter property and turns the subform's FilterOn property to TRUE.
Here's some example code. This was taken from the sample database I've made just to demonstrate filtering (see below). This example does not use fuzzy searches (asterisks) and each control on the main form only filters one field on the subform.
Private Sub cmdFilter_Click()
'You can also call the FilterSubForm function on a control's AfterUpdate event.
Call FilterSubform
End Sub
Private Sub FilterSubform()
Dim strFilter As String
'Note: We have to wrap field names in brackets if they contain spaces or
'special characters. These fields are in Northwind Traders 2007 from Microsoft
'I would never consider naming my fields with spaces or special characters
'in them.
'Company
If Nz(Me.txtCompany, "") <> "" Then
strFilter = strFilter & "Company = '" & PQ(Me.txtCompany) & "' And "
End If
'First Name
If Nz(Me.txtFirstName, "") <> "" Then
strFilter = strFilter & "[First Name] = '" & PQ(Me.txtFirstName) & "' AND "
End If
'Last Name
If Nz(Me.txtLastName, "") <> "" Then
strFilter = strFilter & "[Last Name] = '" & PQ(Me.txtLastName) & "' AND "
End If
'Business Phone
If Nz(Me.txtBusinessPhone, "") <> "" Then
strFilter = strFilter & "[Business Phone] = '" & PQ(Me.txtBusinessPhone) & "' AND "
End If
'City
If Nz(Me.cboCity, "") <> "" Then
strFilter = strFilter & "City = '" & PQ(Me.cboCity) & "' AND "
End If
'State/Province
If Nz(Me.cboStateProvince, "") <> "" Then
strFilter = strFilter & "[State/Province] = '" & PQ(Me.cboStateProvince) & "' AND "
End If
'Order Date
If Nz(Me.txtOrderDate, "") <> "" Then
If IsDate(Me.txtOrderDate) = True Then
strFilter = strFilter & "[Order Date] = #" & Me.txtOrderDate & "# AND "
End If
End If
'Ship Name
If Nz(Me.txtShipName, "") <> "" Then
strFilter = strFilter & "[Ship Name] = '" & PQ(Me.txtShipName) & "' AND "
End If
'Ship City
If Nz(Me.txtShipCity, "") <> "" Then
strFilter = strFilter & "[Ship City] = '" & PQ(Me.txtShipCity) & "' AND "
End If
'Ship State/Province
If Nz(Me.cboShipStateProvince, "") <> "" Then
strFilter = strFilter & "[Ship State/Province] = '" & PQ(Me.cboShipStateProvince) & "' AND "
End If
'Product Code
If Nz(Me.cboProductCode, "") <> "" Then
strFilter = strFilter & "[Product Code] = '" & PQ(Me.cboProductCode) & "' AND "
End If
'Quantity
If Nz(Me.txtQuantity, "") <> "" Then
If IsNumeric(Me.txtQuantity) = True Then
strFilter = strFilter & "Quantity = " & Me.txtQuantity & " AND "
End If
End If
If Right(strFilter, 5) = " AND " Then strFilter = Left(strFilter, Len(strFilter) - 5)
If strFilter <> "" Then
Me.subformOrderSearch.Form.Filter = strFilter
Me.subformOrderSearch.Form.FilterOn = True
Else
'Clear the filter
Me.subformOrderSearch.Form.Filter = ""
Me.subformOrderSearch.Form.FilterOn = False
End If
End Sub
Private Function PQ(s As String) As String
'This function is used to "pad quotes" for SQL
PQ = Replace(s, "'", "''")
End Function
I've put together a sample database that has several different examples all building on what I've posted here. You can download this database here:
http://www.utteraccess.com/forum/Search-filtering-Examples-t1968063.html
After some Searching, I have came across this:
http://www.techrepublic.com/blog/msoffice/run-a-parameter-query-within-an-access-form/701
It is not what I wanted, But it is a great solution...
I will wait, if no one gets a better answer, I'll accept my own (As much as I hate doing that).

Access 2007 VBA & SQL - Update a Subform pointed at a dynamically created query

Abstract:
I'm using VB to recreate a query each time a user selects one of 3 options from a drop down menu, which appends the WHERE clause If they've selected anything from the combo boxes. I then am attempting to get the information displayed on the form to refresh thereby filtering what is displayed in the table based on user input.
1) Dynamically created query using VB.
Private Sub BuildQuery()
' This sub routine will redefine the subQryAllJobsQuery based on input from
' the user on the Management tab.
Dim strQryName As String
Dim strSql As String ' Main SQL SELECT statement
Dim strWhere As String ' Optional WHERE clause
Dim qryDef As DAO.QueryDef
Dim dbs As DAO.Database
strQryName = "qryAllOpenJobs"
strSql = "SELECT * FROM tblOpenJobs"
Set dbs = CurrentDb
' In case the query already exists we should deleted it
' so that we can rebuild it. The ObjectExists() function
' calls a public function in GlobalVariables module.
If ObjectExists("Query", strQryName) Then
DoCmd.DeleteObject acQuery, strQryName
End If
' Check to see if anything was selected from the Shift
' Drop down menu. If so, begin the where clause.
If Not IsNull(Me.cboShift.Value) Then
strWhere = "WHERE tblOpenJobs.[Shift] = '" & Me.cboShift.Value & "'"
End If
' Check to see if anything was selected from the Department
' drop down menu. If so, append or begin the where clause.
If Not IsNull(Me.cboDepartment.Value) Then
If IsNull(strWhere) Then
strWhere = strWhere & " AND tblOpenJobs.[Department] = '" & Me.cboDepartment.Value & "'"
Else
strWhere = "WHERE tblOpenJobs.[Department] = '" & Me.cboDepartment.Value & "'"
End If
End If
' Check to see if anything was selected from the Date
' field. If so, append or begin the Where clause.
If Not IsNull(Me.txtDate.Value) Then
If Not IsNull(strWhere) Then
strWhere = strWhere & " AND tblOpenJobs.[Date] = '" & Me.txtDate.Value & "'"
Else
strWhere = "WHERE tblOpenJobs.[Date] = '" & Me.txtDate.Value & "'"
End If
End If
' Concatenate the Select and the Where clause together
' unless all three parameters are null, in which case return
' just the plain select statement.
If IsNull(Me.cboShift.Value) And IsNull(Me.cboDepartment.Value) And IsNull(Me.txtDate.Value) Then
Set qryDef = dbs.CreateQueryDef(strQryName, strSql)
Else
strSql = strSql & " " & strWhere
Set qryDef = dbs.CreateQueryDef(strQryName, strSql)
End If
End Sub
2) Main Form where the user selects items from combo boxes.
picture of the main form and sub form
http://i48.tinypic.com/25pjw2a.png
3) Subform pointed at the query created in step 1.
Chain of events:
1) User selects item from drop down list on the main form.
2) Old query is deleted, new query is generated (same name).
3) Subform pointed at query does not update, but if you open the query by itself the correct results are displayed.
Name of the Query: qryAllOpenJobs
name of the subform: subQryAllOpenJobs
Also, the Row Source of subQryAllOpenJobs = qryAllOpenJobs
Name of the main form: frmManagement
I think you have your logic on the Department drop down check backwards.
You have it checking if strWhere is null, then if it is, you concatenate strWhere with the value of cboDepartment.
You should be doing what you are for Date.
' Check to see if anything was selected from the Department
' drop down menu. If so, append or begin the where clause.
If Not IsNull(Me.cboDepartment.Value) Then
If Not IsNull(strWhere) Then
strWhere = strWhere & " AND tblOpenJobs.[Department] = '" & Me.cboDepartment.Value & "'"
Else
strWhere = "WHERE tblOpenJobs.[Department] = '" & Me.cboDepartment.Value & "'"
End If
End If
You may also want to do:
If Nz(strWhere,"") = "" then
Instead of just doing IsNull so that you catch the zero-length string in addition to a null variable.
As for setting the recordsource, use something along the lines of
Me.sfrmJobs.Form.RecordSource = strSQL
where sfrmJobs is the name of your subform.
An empty string is not the same thing as Null. When you declare a String variable such as this:
Dim strWhere As String
strWhere is initialized as an empty string (or "zero length string"). That value is sometimes referred to as a null string, and there is even a VBA constant, vbNullString, which represents the empty string. However, regardless of which name you use, the empty string variable is not Null. Furthermore a VBA String variable can never be Null. For example, this code will cause error 94, 'Invalid use of Null':
Dim strWhere As String
strWhere = Null
The reason I am emphasizing this point is because your code tests whether strWhere is Null. That is a logic flaw because strWhere will never be Null. For example, I don't believe this condition can ever be True:
If IsNull(strWhere) Then
If you want a test to determine when strWhere has not had a value assigned to it (it's still an empty string), use the Len function:
If Len(strWhere) = 0 Then
Here is a different approach for BuildQuery. It assumes the data type for your [Date] field is String (as your original code suggests). If [Date] is actually Date/Time data type, this code will not work. Also, please note that Date is a reserved word (see Problem names and reserved words in Access). I enclosed the field name in square brackets to avoid ambiguity. If it were my own database, I would change the field name instead.
Private Sub BuildQuery()
'* Update subform RecordSource based on input from *'
'* the user on the Management tab. *'
Dim strSql As String ' Main SQL SELECT statement '
Dim strWhere As String ' Optional WHERE clause '
Dim i As Integer
Dim strControl As String
Dim strField As String
strSql = "SELECT * FROM tblOpenJobs AS oj"
strWhere = vbNullString
For i = 1 To 3
Select Case i
Case 1
strControl = "cboShift"
strField = "Shift"
Case 2
strControl = "cboDepartment"
strField = "Department"
Case 3
strControl = "txtDate"
strField = "[Date]"
End Select
If Not IsNull(Me.Controls(strControl).Value) Then
strWhere = strWhere & _
IIf(Len(strWhere) > 0, " AND ", "") & _
"oj." & strField & " = '" & _
Me.Controls(strControl).Value & "'"
End If
Next i
If Len(strWhere) > 0 Then
strSql = strSql & " WHERE " & strWhere
End If
'* use the name of the subform CONTROL for sfrmJobs *'
'* (may not be the name of the subform) *'
Me.sfrmJobs.Form.RecordSource = strSql
End Sub
My solution is below in three parts. (1) Build Query, (2) Main Form, (3) Subform.
`Private Sub OpenJobsQuery()
' This sub will construct the query on the front page for the user
' based on who they are and what they select from the combo boxes above
' the table for filtering by redefining the rowsource of the subform
' subQryOpenJobs
Dim strSql As String ' Main SQL SELECT statement
Dim strWhere As String ' Where clause containing user specified parameters.
strSql = "SELECT * FROM tblOpenJobs"
strWhere = ""
' Check to see if anything was selected from the Shift
' combo box. If so, begin the Where clause.
If Not IsNull(Me.cboOpenJobShift.Value) Then
strWhere = "WHERE tblOpenJobs.[Shift] = '" & Me.cboOpenJobShift.Value & "'"
End If
' Check to see if anything was selected from the Department
' combo box. If so, append or begin the where clause.
If Not IsNull(Me.cboOpenJobDepartment.Value) Then
If strWhere = "" Then
strWhere = "WHERE tblOpenJobs.[Department] = '" & Me.cboOpenJobDepartment.Value & "'"
Else
strWhere = strWhere & " AND tblOpenJobs.[Department] = '" & Me.cboOpenJobDepartment.Value & "'"
End If
End If
' Check to see if anything was selected from the Date
' field. If so, append or begin the Where clause.
If Not IsNull(Me.cboOpenJobDate.Value) Then
If strWhere = "" Then
strWhere = "WHERE tblOpenJobs.[JobDate] = #" & Me.cboOpenJobDate.Value & "#"
Else
strWhere = strWhere & " AND tblOpenJobs.[JobDate] = #" & Me.cboOpenJobDate.Value & "#"
End If
Else
' If nothing was entered in the date field, make sure the user
' only sees future jobs.
If strWhere = "" Then
strWhere = "WHERE tblOpenJobs.[JobDate] > #" & FormatDateTime(Date, vbShortDate) & "#"
Else
strWhere = strWhere & " AND tblOpenJobs.[JobDate] > #" & FormatDateTime(Date, vbShortDate) & "#"
End If
End If
' Always include as part of the where clause, a section that
' will narrow the results based on who the user is
If strWhere = "" Then
strWhere = "WHERE tblOpenJobs.[OpenJobID] Not In " & _
"(SELECT tblSignUps.[OpenJobID] FROM tblSignUps WHERE tblSignUps.[EUID] = '" & strEUID & "');"
Else
strWhere = strWhere & " AND tblOpenJobs.[OpenJobID] Not In " & _
"(SELECT tblSignUps.[OpenJobID] FROM tblSignUps WHERE tblSignUps.[EUID] = '" & strEUID & "');"
End If
' Concatenate the Select and the Where clause together
strSql = strSql & " " & strWhere
' Set the recordsource of the subform to the SQL query generated
' and refresh the form.
Me.subQryOpenJobs.Form.RecordSource = strSql
' In addition, synchronize the JobID's in the Edit Job box to match those
' filtered by this Build Query.
Me.cboSelectJOBID.RowSource = "SELECT tblOpenJobs.[OpenJobID] FROM tblOpenJobs" & " " & strWhere
Me.Refresh
End Sub`
(2) Main Form. http://j.imagehost.org/view/0385/Form. and (3) the subform is populated as shown in the BuildQuery() sub to construct the query based on what the user selects from the drop down filters and the input boxes on the right of the form. The data in the table itself is inaccessible to the user, this is just for them to reference.