MS-ACCESS: Multiple Filters - ms-access

I am trying to have a way to let the user click multiple checkboxes and lists, to filter a subform. When I try to use an AND statement, I get an error: Run-time rror '13': Type mismatch. I put an arrow to the line in question. Is an And statement not valid syntax for filtering this way?
Private Sub SearchB_Click()
If Me![CoreCB] = True Then
Me.Query1SF.Form.Filter = " IsDate([Core RS]) = True"
Me.Query1SF.Form.FilterOn = True
ElseIf Me![SiteCB] = True Then
Me.Query1SF.Form.Filter = " IsDate([Site RS]) = True"
Me.Query1SF.Form.FilterOn = True
If Not IsNull(SiteCombo.Value) Then
--> Me.Query1SF.Form.Filter = "[Location] = '" & Me.[SiteCombo].Value & "'" And " IsDate([Site RS]) = True" '!! THIS DOESN'T WORK
Me.Query1SF.Form.FilterOn = True
End If
ElseIf Me![SecurityCB] = True Then
Me.Query1SF.Form.Filter = " IsDate([Security]) = True"
Me.Query1SF.Form.FilterOn = True
End If
End Sub

String expression for form filter seems incorrect. Use below line
Me.Query1SF.Form.Filter = "[Location]='" & Me.[SiteCombo].Value & "' And IsDate([Site RS])=True"

Related

User Defined Shortcut Keys Fail to Fire Event (In Some Circumstances)

I'm working with MS Access 2007. I have an event mapped to a command button, which works as expected when it's clicked. I've also added an ampersand in the caption field for the button command, so users can use shortcut keys (in this case alt+s) to also fire the event.
Here is the command that's executed when the command button is clicked or, depending on which fields are in focus, alt+s is pressed:
Private Sub cmdSearch_Click()
If cmdSearch.Caption = "&Search Mode" Then
cmdDelete.Enabled = False
cmdGotoNew.Enabled = False
cmdMenu.Enabled = False
cmdLicHistory.Enabled = False
cmdComplaints.Enabled = False
cmdAddPrint.Enabled = False
cmdReceipts.Enabled = False
cmdLicensee.Enabled = False
cmdSearch.Caption = "Run &Search"
Me.Filter = "1 = 0"
Me.FilterOn = True
DoCmd.GoToRecord acDataForm, "frmLicense", acNewRec
Detail.BackColor = 12615808
Else
Dim cntrl As Control
Dim strFilter As String
For Each cntrl In Me.Controls
If TypeName(cntrl) = "Textbox" Or TypeName(cntrl) = "Combobox" Then
If Not Len(cntrl) = 0 Then
If Not Len(strFilter) = 0 Then strFilter = strFilter & "and "
strFilter = strFilter & cntrl.ControlSource & " like '*" & cntrl & "*' "
End If
End If
Next
If Not Len(strFilter) = 0 Then
DoCmd.DoMenuItem acFormBar, acEditMenu, acUndo, , acMenuVer70
End If
Me.Filter = strFilter
Me.FilterOn = True
DoCmd.GoToRecord acDataForm, "frmLicense", acFirst
cmdDelete.Enabled = True
cmdGotoNew.Enabled = True
cmdMenu.Enabled = True
cmdLicHistory.Enabled = True
cmdComplaints.Enabled = True
cmdAddPrint.Enabled = True
cmdReceipts.Enabled = True
cmdLicensee.Enabled = True
cmdSearch.Caption = "&Search Mode"
' Detail.BackColor = 12632256
Detail.BackColor = -2147483633 ' Grey
End If
End Sub
However, depending on which fields are in focus, the shortcut keys will fire or not fire. Fields that nested in option groups will fire; fields nested in a tab control will not fire.
Is this behavior expected? This is a form level event, so I'm inclined to say that it's not. Any advice on debugging this would be appreciated.

Access VBA Object Required Error, referencing Field in a Table for IF statement

I am getting an object required error and because that is so horribly vague, I am having trouble fixing it. I am trying to say: If the AssocID field is blank for this record, go through with the SQL statement, etc. If it's not, display a MsgBox and go to the next record. Here is my code.
Private Sub StartButton_Click()
DoCmd.SetWarnings False
Dim mySQL As String
GetID = Forms!frm_MainMenu!AssocIDBox
CurRecord = Forms!frm_EC_All![Loan#].Value
mySQL = "UPDATE tbl_Data SET tbl_Data.[AssocID] = " & GetID & " , tbl_Data.[tsStartAll] = Now WHERE tbl_Data.[Loan#] = " & CurRecord
'
'
'
If IsNull(tbl_Data.AssocID.Value) Then
DoCmd.RunSQL mySQL
DoCmd.SetWarnings True
Me.TimerActivatedLabel.visible = True
Me.Refresh
ClaimedMsg = MsgBox("Loan has been assigned to you.", vbOKOnly, "Loan Assigned")
If ClaimedMsg = vbOK Then
DoCmd.SetWarnings False
DoCmd.RunSQL "UPDATE tbl_Data SET tbl_Data.[tsHaveDocs] = Now WHERE tbl_Data.[Loan#] = " & CurRecord
DoCmd.SetWarnings True
End If
Else
AlreadyAssignedMsg = MsgBox("Loan has already been assigned. Press OK to move to the next loan.", vbOKOnly, "Already Assigned!")
If AlreadyAssignedMsg = vbOKOnly Then
DoCmd.GoToRecord , , acNext
End If
End If
End Sub
The error occurs on the If IsNull(etc) line. I've looked at a lot of other stuff but it either didn't apply or I didn't really understand what they were talking about. I'm still kind of a beginner. Thanks!
If, for some strange reason, you don't have tbl_Data.AssocID field as a controlsource for a textbox in your form, you can do this:
...
' Declare a string variable and set it to the value of the field
' I concatenate an empty string to be sure to have not a null
Dim AssocID as string
AssocID = Dlookup("AssocID","tbl_Data","[Loan#] = " & CurRecord) & ""
' Test the string variable
If AssocID = "" Then
...

Converting check boxes to words

I added check boxes to my MS Access form. Now I am trying to run a report based on those check boxes.
They are about 6 check boxes. How can I translate the check boxes from check marks to words?
An example of this would be on the form. Pizza toppings(onions,sausage,olives,cheese,chicken,mushrooms).
I need to be able to turn the check boxes from 6 individual check-boxes to make one toppings fields.
Also it is to late to change the table to use some form of list box.
Thank you.
Put a new text field into your report with a control source similar to the following:
=iif([onions],"Onions ", "") & iif([sausage],"Sausage ") & iif([olives],"Olives ","")
And so on...
If you would like to have commas in between the ingredients, you could also use something like the following:
=Concat(", ", iif([onions],"Onions", ""), iif([sausage],"Sausage"), iif([olives],"Olives ",""))
And put a Concat() function similar to this in one of your Modules:
Public Function Concat(Delimiter As String, ParamArray Strings()) As String
Dim s As Variant, ret As String
ret = ""
For Each s In Strings
If Not IsNull(s) And Not IsEmpty(s) And s <> "" Then
If ret = "" Then
ret = s
Else
ret = ret & Delimiter & s
End If
End If
Next
Concat = ret
End Function
You want something like this:
If chkTopping1 = True then MyTopping1 = "Bacon"
If chkTopping2 = True then MyTopping2 = "Sausage"
If chkTopping3 = True then MyTopping3 = "Pepperoni"
If chkTopping4 = True then MyTopping4 = "Mushrooms"
If chkTopping5 = True then MyTopping5 = "Meatballs"
If chkTopping6 = True then MyTopping6 = "Olives"
If Not IsNull(MyTopping1) then
AllToppings = MyTopping1 & ", "
If Not IsNull(MyTopping2) then
AllToppings = AllToppings & MyTopping2 & ", "
If Not IsNull(MyTopping3) then
AllToppings = AllToppings & MyTopping3 & ", "
If Not IsNull(MyTopping4) then
AllToppings = AllToppings & MyTopping4 & ", "
If Not IsNull(MyTopping5) then
AllToppings = AllToppings & MyTopping5 & ", "
If Not IsNull(MyTopping6) then
AllToppings = AllToppings & MyTopping6
AllToppings is now your text field. I'm positive there's a more graceful way to do this, but my brain is kinda burnt after a long day at the office.

VBA Compile error: Expected end of statement

I am trying to code a combo box in a form such that it automatically filters the options as the user types. I have a code but I keep getting a compile error. Here is my code:
Private Sub UTIL_FCLTY_ID_Change()
If Nz(Me.UTIL_FCLTY_ID.Text) = “” Then
Me.Form.Filter = “”
Me.FilterOn = False
ElseIf Me.UTIL_FCLTY_ID.ListIndex <> -1 Then
Me.Form.Filter = “[UTILITY FACILITY TYPE NAME:] = ‘” & _
Replace(Me.UTIL_FCLTY_ID.Text, “‘”, “””) & “‘”
Me.FilterOn = True
Else
Me.Form.Filter = “[UTILITY FACILITY TYPE NAME:] Like ‘*” & _
Replace(Me.UTIL_FCLTY_ID.Text, “‘”, “””) & “*'”
Me.FilterOn = True
End If
Me.UTIL_FCLTY_ID.SetFocus
Me.UTIL_FCLTY_ID.SelStart = Len(Me.UTIL_FCLTY_ID.Text)
End Sub
As #HansUp mentioned, you use non-standard quotes and non-standard apostrophe. Replace them with correct one.
Second issue is with this statement: """. VBA compiler sees it as "" " (empty string and unclosed quote). You need to use double quote inside quote to workaround it: """""
Finally your procedure should look like:
Private Sub UTIL_FCLTY_ID_Change()
If Nz(Me.UTIL_FCLTY_ID.Text) = "" Then
Me.Form.Filter = ""
Me.FilterOn = False
Exit Sub 'there's nothing to proceed ;)
End If
If Me.UTIL_FCLTY_ID.ListIndex <> -1 Then
Me.Form.Filter = "[UTILITY FACILITY TYPE NAME:] = '" & _
Replace(Me.UTIL_FCLTY_ID.Text, "'", """") & "'"
Me.FilterOn = True
Else
Me.Form.Filter = "[UTILITY FACILITY TYPE NAME:] Like '*" & _
Replace(Me.UTIL_FCLTY_ID.Text, "'", """") & "*'"
Me.FilterOn = True
End If
Me.UTIL_FCLTY_ID.SetFocus
Me.UTIL_FCLTY_ID.SelStart = Len(Me.UTIL_FCLTY_ID.Text)
End Sub

How to make the following code simpler with Arrays

This is by no means essential, but I would like to find out how to create more efficient code, and i'm sure this is far from efficient!
On the form disabled fields values are cleared before the form is saved.
The below code send a message to the user to inform them that they may lose some data if they leave a checkbox unchecked.
In the context of the form it all makes sense, i would just like to know a simpler methodology, i'm sure i could use an array somewhere but cant quite figure it out.
Dim couldLoseData As Boolean
Dim msgStr As String
couldLoseData = False
If (Me.chkInvSent = False) And (Not IsNull(Me.invoicedDate)) Then
couldLoseData = True
msgStr = "Invoice Sent"
End If
If (Me.chkFeePaid = False) And (Not IsNull(Me.datePaid)) Then
couldLoseData = True
If msgStr = "" Then
msgStr = "Claim Fee Paid"
Else
msgStr = msgStr & " / Claim Fee Paid"
End If
End If
If (Me.chkFeeLodged = False) And (Not IsNull(Me.lodgedDate)) Then
couldLoseData = True
If msgStr = "" Then
msgStr = "Fee Lodged"
Else
msgStr = msgStr & " / Fee Lodged"
End If
End If
If couldLoseData = True Then
If MsgBox("You will lose data in the following areas as the relevant checkboxes are unticked." & vbNewLine & vbNewLine & _
msgStr & vbNewLine & vbNewLine & "Do you wish to continue?", vbYesNo, dbNameOf) = vbNo Then
Cancel = True
End If
Else
'
'
'
' Procedure that gets carried out here
End If
No biggie but if any one could offer me a simpler solution it would be appreciated.
Cheers
Noel
I'm not sure why you think you should be using arrays. When it comes to the msgStr variable logic I would just put in the following:
msgStr = msgStr & "Invoice Sent / "
rather than the five lines of If msgstr = "" Then, etc, etc, End If lines.
Then at the end I would put in the following line
msgStr = lef(msgStr, len(msgStr) - 3) ' remove the trailing /
This then removes the trailing " / "
Purists will tell you that you should never add anything to a string you later remove. I say, so long as you leave a comment there for the next person who is reading your code, this reduces complexity of your preceding lines of code making it much easier to grasp exactly what is going on.
Whenever I'm looking for a value to be returned from a MsgBox I place the string creating in a separate line of code. Thus is much easier to see, at a glance, exactly what the code is doing.
strMsg = "You will lose data in the following areas as the relevant checkboxes are unticked." & vbNewLine & vbNewLine & _
msgStr & vbNewLine & vbNewLine & "Do you wish to continue?"
If MsgBox(strMsg, vbYesNo, dbNameOf) <> vbYes Then _
Cancel = True
If I'm only setting one value in the If statement, such as you show, I will also put in the _ and thus not require the End If.
I also prefer <> vbYes just in case something wonky should happen or if someone, not you of course, mucks with the msgbox options.
Why do you even allow the user to close the form when all the data fields have not been filled out?
Basically, to me, your logic is all in the wrong place. If you have a CLOSE button on your form (assuming you've gotten rid of the default Windows CLOSE X), you would not enable it until such time as all the data fields have been filled out appropriately.
The way I usually do this is to write a subroutine (or function) that checks all the fields that have to be filled out and enables the CLOSE button if everything is in order. Thus, the user CAN'T close the form until all the appropriate fields are filled out, except, perhaps, if you've provided a CANCEL button (in which case, you WANT to lose the data).
You don't need arrays but a simple helper method to simplify code and make it more reusable:
(just replace checkboxes and conditions in the following code)
Public Function ErrorChecker(assumption As Boolean, errorMessage As String, condition As Boolean, concatenate As Boolean) As String
Dim ret As String = [String].Empty
If Not assumption AndAlso condition Then
If concatenate Then
ret += " / "
End If
ret += errorMessage
End If
Return ret
End Function
Private Sub button1_Click(sender As Object, e As EventArgs)
Dim message As String = [String].Empty
message += ErrorChecker(checkBox1.Checked, "Error 1", value1 Is Nothing, False)
message += ErrorChecker(checkBox2.Checked, "Error 2", value2 Is Nothing, True)
message += ErrorChecker(checkBox3.Checked, "Error 3", value3 Is Nothing, True)
If message <> String.Empty Then
'messagebox
End If
End Sub
I've written a simple function to concatenate two strings that eliminates the need to worry about whether you need to strip anything off when you're done concatenating. Here's the function:
'-----------------------------------------------------------------------------
' Purpose : Concatenates two strings
' Usage : Dim MyList As String
' MyList = Conc(MyList, SomeValue)
' Notes : Eliminates the need to strip off the leading/trailing delimiter
' when building a string list
'-----------------------------------------------------------------------------
Function Conc(StartText As String, NextVal, _
Optional Delimiter As String = ", ") As String
If Len(StartText) = 0 Then
Conc = Nz(NextVal)
ElseIf Len(CStr(Nz(NextVal))) = 0 Then
Conc = StartText
Else
Conc = StartText & Delimiter & NextVal
End If
End Function
And here's how I'd rewrite your code using this function:
Dim msgStr As String
If (Me.chkInvSent = False) And (Not IsNull(Me.invoicedDate)) Then
msgStr = Conc(msgStr, "Invoice Sent", " / ")
End If
If (Me.chkFeePaid = False) And (Not IsNull(Me.datePaid)) Then
msgStr = Conc(msgStr, "Claim Fee Paid", " / ")
End If
If (Me.chkFeeLodged = False) And (Not IsNull(Me.lodgedDate)) Then
msgStr = Conc(msgStr, "Fee Lodged", " / ")
End If
If Len(msgStr) > 0 Then
If MsgBox("You will lose data in the following areas as the relevant checkboxes are unticked." & vbNewLine & vbNewLine & _
msgStr & vbNewLine & vbNewLine & "Do you wish to continue?", vbYesNo, dbNameOf) <> vbYes Then
Cancel = True
End If
Else
' Procedure that gets carried out here
End If
This is how I'd code it up
Dim couldLoseData As Boolean
Dim msgStr As String
Dim InvBoolean as boolean
Dim PaidBoolean as boolean
Dim LodgedBoolean as boolean
Dim response as integer
couldLoseData = False
InvBoolean = (Me.chkInvSent = False) And (Not IsNull(Me.invoicedDate))
PaidBoolean = (Me.chkFeePaid = False) And (Not IsNull(Me.datePaid))
LodgedBoolean = (Me.chkFeeLodged = False) And (Not IsNull(Me.lodgedDate))
couldLoseData = InvBoolean or PaidBoolean or LodgeBoolean
'if any one is true, there could be lost data.
if couldLoseData = false then
exit sub 'bail if nothing applies
'you may want a GOTO if there is stuff this sub needs to do regardless
end if
If InvBoolean = true then 'add phrase and move to new line
msgStr = msgStr & "Invoice Sent" & vbcrlf
end if
If PaidBoolean = true then 'add phrase and move to new line
msgStr = msgStr & "Claim Fee Paid" & vbcrlf
end if
If LodgedBoolean = true then 'add phrase and move to new line
msgStr = msgStr & "Fee Lodged" & vbcrlf
end if
If couldLoseData = True Then
msgStr = "You will lose data in the following areas as the relevant checkboxes are unticked." & vbcrlf & msgStr & vbcrlf
msgStr = msgStr & "Do you wish to continue?"
response = msgbox(msgstr, vbYesNo)
if response = vbno then
Cancel = True
End If
end if
If you really were looking to use an array:
Dim couldLoseData As Boolean
Dim msgStr As String
Dim ConditionsResponses(0 to 2,1)
Dim x as integer
Dim response as integer
couldLoseData = False
ConditionsResponses(0,0) = (Me.chkInvSent = False) And (Not IsNull(Me.invoicedDate))
ConditionsResponses(1,0) = (Me.chkFeePaid = False) And (Not IsNull(Me.datePaid))
ConditionsResponses(2,0) = (Me.chkFeeLodged = False) And (Not IsNull(Me.lodgedDate))
ConditionsResponses(0,1) = "Invoice Sent" & vbcrlf
ConditionsResponses(1,1) = "Claim Fee Paid" & vbcrlf
ConditionsResponses(2,1) = "Fee Lodged" & vbcrlf
couldLoseData = ConditionsResponses(0,0) or ConditionsResponses(0,0) or ConditionsResponses(0,0)
'if any one is true, there could be lost data.
for x = 0 to 2
if ConditionsResponses(x,0)= true then
msgStr = msgStr & ConditionsResponses(x,1)
end if
next x
If couldLoseData = True Then
msgStr = "You will lose data in the following areas as the relevant checkboxes are unticked." & vbcrlf & msgStr & vbcrlf
msgStr = msgStr & "Do you wish to continue?"
response = msgbox(msgstr, vbYesNo)
if response = vbno then
Cancel = True
End If
end if