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
Related
I had gotten my question answered by a colleague of mine, but I wanted to re-post here in case anyone else has the issue, and to pose the question, which you'll note at the end. The original post, if interested, is here: Original Post
Many thanks to all in the community here, particularly #Andre for your help!
It was strange, but when I did that, it kept trying to put in all my letters backwards. Example: If I searched "Smith", it would enter it as "htims". I'm sure it had something to do with the on click event, but I had a friend look at it and I think she cracked it! It looks like this (I've added a comment to what the new line(s) of code is/are):
First, the textbox click event whereby when you click the box, it clears the text and resets the search (no need for a reset button)
Private Sub txtSearch_Click()
Me.txtSearch.SetFocus 'new line of code
Me.txtSearch.Text = ""
Me.Requery
With Me.txtSearch
.SetFocus
.SelStart
End With
End Sub
This is the actual search, that will search multiple fields
Private Sub txtSearch_Change()
Dim strFilter As String
Dim sSearch As String
On Error Resume Next
If Me.txtSearch.Text <> "" Then
sSearch = "'*" & Replace(Me.txtSearch.Text, "'", "''") & "*'"
strFilter = "[Last_Name] Like " & sSearch & " OR [First_Name] Like " & sSearch & " OR [SSN] Like " & sSearch
Me.Filter = strFilter
Me.FilterOn = True
Else
Me.Filter = ""
Me.FilterOn = False
End If
If Me.Recordset.RecordCount = 0 Then 'new line of code
Me.Filter = "" 'new line of code
Me.FilterOn = False 'new line of code
Me.txtSearch.SetFocus 'new line of code
Me.txtSearch.Text = "" 'new line of code
Exit Sub 'new line of code
End If 'new line of code
With Me.txtSearch
.SetFocus
.SelStart = Len(Me.txtSearch.Text)
End With
End Sub
This seems to be working great. And while I'm considering this issue complete, I do have a question, if you could help me identify, why were the letters going in backwards when I replaced the .Text with a .Value?
Thank you all very much for your help!
First you need to change the Click event to Enter and scrap the .SetFocus since the control will have the focus:
Private Sub txtSearch_Enter()
With Me
.txtSearch.Value = ""
.Requery
End With
End Sub
Regarding the difference between .Text and .Value:
The .Text property updates with every keystroke you make where the .Value property gets updated only when the control loses focus.
On the Change event, you should check two things: a) the textbox has a value (.Text) to apply the filter and b) the recordcount to clear the filter if no records returned.
Private Sub txtSearch_Change()
Dim strFilter As String, sSearch As String
On Error Resume Next
With me
If .txtSearch.Text <> "" Then
sSearch = "'*" & Replace(.txtSearch.Text, "'", "''") & "*'"
strFilter = "[Last_Name] Like " & sSearch & " OR [First_Name] Like " & sSearch & " OR [SSN] Like " & sSearch
.Filter = strFilter
.FilterOn = True
End If
If .Recordset.RecordCount = 0 Then
.Filter = ""
.FilterOn = False
End If
End With
End Sub
The reason for the backward letters, was the .SelStart property where the cursor was jumping at the beginning every time you typed a letter, thus giving you the impression it was flipping the word backwards.
I have the code below (courtesy of allenbrowne, his info are in the code). When I am filtering using one of the columns (One_or_Two_Pearl) it is giving me a (Syntax error missing operator in query expression). I can not trace the problem as everything look fine. That column is defined as Text type and contains data (1, 2, NA). This problem is only occurring for this column, and when I debug the yellow mark is indicating the (Me.Filter = strWhere) part.
Thank you in advance for your help.
'http://allenbrowne.com/ser-62.html
'Purpose: This module illustrates how to create a search form, _
where the user can enter as many or few criteria as they wish, _
and results are shown one per line.
'Note: Only records matching ALL of the criteria are returned.
'Author: Allen Browne (allen#allenbrowne.com), June 2006.
Option Compare Database
Option Explicit
Private Sub cmdFilter_Click()
'Purpose: Build up the criteria string form the non-blank search boxes, and apply to the form's Filter.
'Notes: 1. We tack " AND " on the end of each condition so you can easily add more search boxes; _
we remove the trailing " AND " at the end.
' 2. The date range works like this: _
Both dates = only dates between (both inclusive. _
Start date only = all dates from this one onwards; _
End date only = all dates up to (and including this one).
Dim strWhere As String 'The criteria string.
Dim lngLen As Long 'Length of the criteria string to append to.
Const conJetDate = "\#mm\/dd\/yyyy\#" 'The format expected for dates in a JET query string.
'***********************************************************************
'Look at each search box, and build up the criteria string from the non-blank ones.
'***********************************************************************
'Text field example. Use quotes around the value in the string.
If Not IsNull(Me.cboxprojphase) Then
strWhere = strWhere & "([Project_Phase] = """ & Me.cboxprojphase & """) AND "
End If
'Another text field example. Use Like to find anywhere in the field.
If Not IsNull(Me.cboxcontract) Then
strWhere = strWhere & "([Contract] = """ & Me.cboxcontract & """) AND "
End If
'Number field example. Do not add the extra quotes.
If Not IsNull(Me.cboxdesigndpm) Then
strWhere = strWhere & "([Design_DPM] = """ & Me.cboxdesigndpm & """) AND "
End If
'Text field example. Use quotes around the value in the string.
If Not IsNull(Me.cboxadmupc) Then
strWhere = strWhere & "([ADM/UPC] = """ & Me.cboxadmupc & """) AND "
End If
'Text field example. Use quotes around the value in the string.
If Not IsNull(Me.cboxpearl) Then
strWhere = strWhere & "([One_or_Two_Pearl] = """ & Me.cboxpearl & """) "
End If
'***********************************************************************
'Chop off the trailing " AND ", and use the string as the form's Filter.
'***********************************************************************
'See if the string has more than 5 characters (a trailng " AND ") to remove.
lngLen = Len(strWhere) - 5
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 = Null
Case acCheckBox
ctl.Value = False
End Select
Next
'Remove the form's filter.
Me.FilterOn = False
Me.OrderByOn = False
End Sub
Private Sub Form_BeforeInsert(Cancel As Integer)
'To avoid problems if the filter returns no records, we did not set its AllowAdditions to No.
'We prevent new records by cancelling the form's BeforeInsert event instead.
'The problems are explained at http://allenbrowne.com/bug-06.html
Cancel = True
MsgBox "You cannot add new Records to the search form.", vbInformation, "Permission denied."
End Sub
Private Sub Form_Open(Cancel As Integer)
'Remove the single quote from these lines if you want to initially show no records.
'Me.Filter = "(False)"
'Me.FilterOn = True
Dim strURL As String
Dim objIE As Object
Dim arrSites(2) As String
Dim i As Integer
arrSites(0) = "http://google.com"
arrSites(1) = "http://google.com"
Set objIE = CreateObject("InternetExplorer.Application")
For i = 0 To 1 Step 1
strURL = arrSites(i)
If i = 0 Then
objIE.Navigate strURL
Else
objIE.Navigate2 strURL, 2048
End If
Next i
objIE.Visible = True
Set objIE = Nothing
'objIE.Quit
End Sub
Private Sub optSortorder_AfterUpdate()
If Me.optSortorder = 1 Then
Me.OrderBy = Me.cboSortField
Else
Me.OrderBy = Me.cboSortField & " DESC"
End If
Me.OrderByOn = True
End Sub
Both your problems are here:
strWhere = Left$(strWhere, lngLen)
'For debugging, remove the leading quote on the next line. Prints to Immediate Window (Ctrl+G).
'Debug.Print strWhere
Uncomment the Debug.Print line to see what is happening:
it tries to remove a trailing " AND " from your [One_or_Two_Pearl] line, but there is none.
This question was asked in the topic with a similar name earlier, but the answer provided didn't really indicate HOW those events would help determine whether somebody was typing in the combo box or selecting an item in the list. I think that it really answered the other question about how to determine when somebody was done typing, but without seeing the event handlers, I can't be sure.
Unfortunately, I'm new here and don't have enough reputation to post a comment asking for clarification, so I have to start a new question. Here's what I'm trying to do:
I have a form with a combo box in the Header and, as I type in the combo box, I want the characters that I've typed to be used as a filter on the Details part of the form. Both the combo box control source and the form's record source use the same query string.
I've tried numerous iterations of the code below, but I can't get it to work correctly.
Private Sub cmbAppName_Change()
Dim strApp As String
Dim nSelStart As Integer
Dim nSelLen As Integer
Dim nSelected As Integer
Dim strMsg As String
On Error GoTo ERR_SUB
strMsg = ""
Me.cmbAppName.SetFocus
' Get current selection details
nSelStart = Me.cmbAppName.SelStart
nSelLen = Me.cmbAppName.SelLength
nSelected = Me.cmbAppName.ListIndex
Me.cmbAppName.SetFocus
strApp = Nz(Me.cmbAppName.Text, "")
Debug.Print "Index = " & nSelected & "; SelStart = " & nSelStart & "; SelLen = " & nSelLen
If nSelected = -1 Then
Debug.Print "Change by typing: " & strApp
Else
Debug.Print "Change by list selection: " & strApp
End If
' Get the part of the text that the user has typed
If nSelStart > 0 Then
strApp = Left(strApp, nSelStart)
Debug.Print "App piece = '" & strApp & "'"
End If
' If there is text, set a filter (MatchAppName = InStr(strApp, datbase_column_value)
If strApp <> "" Then
Me.Filter = "MatchAppName('" & strApp & "', " & DCApplications_Application_Col & ") > 0"
Me.FilterOn = True
' Me.txtApplication.SetFocus
' Call DoCmd.FindRecord(strApp, acStart, False, acSearchAll, False, acCurrent, True)
' Me.cmbAppName.SetFocus
Else
Me.Filter = ""
Me.FilterOn = False
End If
EXIT_SUB:
' Restore the selection in the combo box's text box
Me.cmbAppName.SetFocus
Me.cmbAppName.SelStart = nSelStart
Me.cmbAppName.SelLength = nSelLen
Exit Sub
ERR_SUB:
If ERR.Number = 2185 Then
strApp = Nz(Me.cmbAppName.Value, "")
Me.cmbAppName.SetFocus
Debug.Print "Using " & strApp
Resume Next
End If
Me.Filter = ""
Me.FilterOn = False
Debug.Print ErrorMessage(ERR.Description, "cmbAppName_Change", ERR.Number, "Value = '" & Me.cmbAppName.Value & "'", False)
Resume EXIT_SUB
End Sub ' cmbAppName_Change
As you can see from the error handling code, I'd often get an error 2185 telling me that my control didn't have focus when using the Text property despite having a SetFocus call right before it.
If somebody selects from the list (either by clicking or moving the selection), I'd like to go to that record, but I at least need the above piece working first.
After searching the Web, I found out that a Details section with zero records causes the 2185 error. Apparently, filtering like that causes problems when all records are filtered out.
The solutions on the Web said that you can set the Allow Additions property of the form to True, but that always displays one row in the Details section. This can be especially confusing if the rows in the Details section contain controls, which will be displayed in the "addition" row. Also, I would still get an error typing additional characters after the one that caused the Details section to have zero records.
Eventually, I replaced the combo box with a simple text control to filter the Details section. When the Details section has rows, I turn Allow Additions off and make the controls visible; when it doesn't have rows, I turn Allow Additions on and hide the controls.
Here's the code that I used:
Private Sub txtApplicationFilter_Change()
Dim strApp As String
Dim nSelStart As Integer
Dim nSelLen As Integer
Dim strFilter As String
Dim strQuery As String
Dim strWhere As String
Dim nRecs As Integer
On Error GoTo ERR_SUB
' Save text selection
nSelStart = Me.txtApplicationFilter.SelStart
nSelLen = Me.txtApplicationFilter.SelLength
' Get application name typed and selection information
strApp = Nz(Me.txtApplicationFilter.Text, "")
strFilter = "[" & DCApplications_Application_Col & "] LIKE '*" & EscapeQuotes(strApp) & "*'"
nRecs = DCount("[" & DCApplications_Application_Col & "]", LocalTableName(DCApplications_Tab), strFilter)
' Kludge code to prevent various errors (like 2185) when no records are returned in the form
Call UpdateList(nRecs)
' Update the record source to reflect the filtered list of apps
strWhere = " WHERE APPS." & strFilter
strQuery = strSelect & strFrom & strWhere & strOrderBy
Me.RecordSource = strQuery
' 20200423 SHM: Restore or update filter to avoid issues with Delete and Backspace and applications with spaces in their names
Me.txtApplicationFilter.SetFocus
Me.txtApplicationFilter = strApp
Me.txtApplicationFilter.SelStart = nSelStart
Me.txtApplicationFilter.SelLength = nSelLen
EXIT_SUB:
Me.btnAddNew.enabled = (Nz(Me.txtApplicationFilter, "") <> "")
Exit Sub
ERR_SUB:
' NOTE: ErrorMessage is a helper function that basically displays a form displaying the error
Call ErrorMessage(ERR.Description, "txtApplicationFilter_Change", ERR.Number, "Filter = " & strApp & " Records = " & nRecs)
Resume EXIT_SUB
Resume Next
End Sub ' txtApplicationFilter_Change
Private Sub UpdateList(nRecs As Integer)
Dim bShowControls As Boolean
On Error GoTo ERR_SUB
bShowControls = (nRecs > 0)
' Kludge code to turn off checkbox control source
If bShowControls Then
strSelect = strSelectStart & ", (" & strAppUser & ") AS " & strCtrlSource
Me.chkTestedByMe.ControlSource = strCtrlSource
Else
strSelect = strSelectStart
Me.chkTestedByMe.ControlSource = ""
End If
' Kludge code to prevent various errors (like 2185) when no records are returned in the form
' Turning on AllowAdditions prevents errors when no records are returned.
' However, that puts an empty row in the form, but the controls are showing, so we have to hide them to prevent confusing the user.
Me.AllowAdditions = Not bShowControls
Me.btnAddExisting.visible = bShowControls
Me.chkTestedByMe.visible = bShowControls
EXIT_SUB:
Exit Sub
ERR_SUB:
Call ErrorMessage(ERR.Description, "UpdateList", ERR.Number, " Records = " & nRecs)
Resume EXIT_SUB
Resume Next
End Sub ' UpdateList
I would use a work around to settle this issue
A simple code bellow demonstrate the work around using Tag property of Combo Box and keypress event along with change event, I hope it can be applied in your code
Private Sub Combo2_Change()
If Combo2.Tag = 1 Then
Text4 = "change - from key"
Else
Text4 = "change - from select"
End If
Combo2.Tag = 0
End Sub
Private Sub Combo2_KeyPress(KeyAscii As Integer)
Combo2.Tag = 1
End Sub
Don't forget to set Tag property of Combo Box to 0 on design view to avoid error at comparing empty Tag with number
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
I have a master form which contains three list boxes and one sub form. I would like to build a routine which allows me to switch links between the sub form and the three list boxes. Is this possible? Or do i have to create three copies of the same sub form and hide two while one the other is activated?
To be practical, my form will work like this: The sub form contains a list of records of people participating in a project, their specific role, and which internal team they come from. I would like to use three list boxes to allow the user to filter this form by either:
(1) All participants coming from a certain team
(2) All participants by roles (titles)
(3) Filter by name of particants
Where I am short is on how to re-link the filter on the sub form so that it changes from list box to list box as the user passes from filter to filter.
Using Krish's suggestion below as a simple test i am trying the following code but am getting a compilation error message on the recordsource line stating that it is impossible to find the method or the data member.. Not sure what that means:
Private Sub lstRoles_AfterUpdate()
Dim SQL_GET As String
SQL_GET = "SELECT * from tblProjectGovernanceResources where ((role like '" & lstRoles.Value & "')"
Me.frmProjectGovernanceResources.RecordSource = SQL_GET
End Sub
you can retrieve the selected value from a listbox simply byt listbox1.value.
As Wayne G pointed. you would add a code in your listbox_after_update event to update your subform's recordsource.
something like:
dim SQL_GET as string
sql_get = "SELECT * from tbl_myTAble where ((condition like '" & listbox1.value & "') OR (condition2 like '"& listbox2.value &"') OR (condition3_number like "& listbox3.value &"))
me.mysubform.recordsource = sql_Get
obviously you need to improve this as per your requirements.
Try this and for a better answer, produce what you have coded so far..
I created some code for the easiest version possible. This means all of your listboxes have the 'multi select' property set to 'None' (this means you can't select multiple items in the list and you can't 'deselect' an item by clicking on it again. I did add some code at the end so you can see how a different multi-select option may work.
My form has three listboxes, a subform, and two buttons. One button will clear all selections in all listboxes. The other button applies the filter to the subform.
Option Compare Database
Option Explicit
'*** NOTE!!! THIS CODE ASSUMES YOU HAVE SET YOUR LISTBOX PROPERTY to 'NONE'.
' IF YOU SET 'MULTI SELECT' To 'SIMPLE' or 'EXTENDED', you MUST use different code to find all selected items.
Dim strWhereTeam As String
Dim strWhereRole As String
Dim strWhereParticipant As String
Private Sub cmdClear_Click()
' Clear all selections in all listboxes
Dim i As Integer
For i = 0 To Me.lstParticipant.ListCount 'Deselect ALL rows in Listbox
lstParticipant.Selected(i) = False
Next i
For i = 0 To Me.lstRole.ListCount 'Deselect ALL rows in Listbox
lstRole.Selected(i) = False
Next i
For i = 0 To Me.lstTeam.ListCount 'Deselect ALL rows in Listbox
lstTeam.Selected(i) = False
Next i
strWhereTeam = ""
strWhereRole = ""
strWhereParticipant = ""
Me.MySubForm.Form.Filter = "" ' Reste filter to NONE
Me.MySubForm.Form.FilterOn = False
End Sub
Private Sub cmdFilter_Click()
'Build Filter (concatenate three selections)
Dim strFilter As String
strFilter = ""
If strWhereTeam & "" <> "" Then
strFilter = strWhereTeam
If strWhereRole & "" <> "" Then
strFilter = strFilter & " AND " & strWhereRole
If strWhereParticipant & "" <> "" Then
strFilter = strFilter & " AND " & strWhereParticipant
End If
Else
If strWhereParticipant & "" <> "" Then
strFilter = strFilter & " AND " & strWhereParticipant
End If
End If
ElseIf strWhereRole & "" <> "" Then
strFilter = strWhereRole
If strWhereParticipant & "" <> "" Then
strFilter = strFilter & " AND " & strWhereParticipant
End If
ElseIf strWhereParticipant & "" <> "" Then
strFilter = strWhereParticipant
End If
If strFilter = "" Then
Me.MySubForm.Form.Filter = ""
Me.MySubForm.Form.FilterOn = False
Else
Me.MySubForm.Form.Filter = strFilter
Me.MySubForm.Form.FilterOn = True
End If
End Sub
Private Sub lstParticipant_Click()
strWhereParticipant = "[Participant] = '" & Me.lstParticipant.ItemData(Me.lstParticipant.ListIndex) & "'"
Debug.Print strWhereParticipant
End Sub
Private Sub lstRole_Click()
strWhereRole = "[Role] = '" & Me.lstRole.ItemData(Me.lstRole.ListIndex) & "'"
Debug.Print strWhereRole
End Sub
Private Sub lstTeam_Click()
If Me.lstTeam.MultiSelect <> 0 Then
MsgBox "You have set the 'Multi Select' property to either Simple or Extended. This code may not work!", vbOKOnly + vbCritical, "ListBox MultiSelect not 'None'"
End If
strWhereTeam = "[Team] = '" & Me.lstTeam.ItemData(Me.lstTeam.ListIndex) & "'"
Debug.Print strWhereTeam
'Simple_Code
End Sub
'' Sample code if set 'Multi Select' to 'Simple' or 'Extended'
'Sub Simple_Code()
' Dim var As Variant
' strWhereTeam = ""
' For Each var In Me.lstTeam.ItemsSelected
' strWhereTeam = strWhereTeam & "[Team] = '" & Me.lstTeam.ItemData(var) & "' OR "
' Next var
' strWhereTeam = "(" & left(strWhereTeam, Len(strWhereTeam) - 4) & ")"
' Debug.Print strWhereTeam
'End Sub
Thanks a lot! This did it all!
Private Sub lstRoles_AfterUpdate()
Dim SQL_GET As String
SQL_GET = "SELECT * from tblProjectGovernanceResources where ([role] = '" & lstRoles.Value & "')"
Me.frmProjectGovernanceResources.Form.RecordSource = SQL_GET
End Sub