listbox vba : listcount doesn't update immediately - vba

Hello everyone and thanks in advance for the help.
Shortly: I have a textbox used to input a name to search. According to this "name", A listbox update with all the record found from a table (and following, cliking on the listbox I update a form).
Question: I want some actions (for example a msgbox...) when there are not records founds (I think that listbox.listcount is 1 in this case but often from the immediate windows is 0???).
"Menu" is the form that cointains Listbox and textbox, "globale" is a table and "nominativo" a field of globale.
So the code pass away (lbox.listcount doesn't update) and only if I set a break point it runs...
Mistery!!
My code ( I learned some development by myself).
Private Sub Comando156_Click() 'to make blank all the boxes
Me.RecordSource = ""
Me.Refresh
Testo129.Value = ""
Testo154.Value = ""
nomin_lbox.RowSource = ""
End Sub
Private Sub nomin_lbox_AfterUpdate()
chiave1 = nomin_lbox.Column(6)
sql1 = "SELECT * FROM globale WHERE (globale.id) =" & chiave1
Forms!menu.RecordSource = sql1
Forms!menu.Refresh
nomin_lbox.Requery
End Sub
Private Sub Testo129_AfterUpdate()
If Testo129 <> "" Then
chiave2 = Testo129
sql1 = "SELECT * FROM globale WHERE [nominativo] like'*" & chiave2 & "*'" & ""
nomin_lbox.RowSource = sql1
nomin_lbox.Requery
n_found = nomin_lbox.ListCount
If n_found = 1 Then
MsgBox "niente"
End If
Forms!menu.Refresh
Else
Me.RecordSource = "SELECT * FROM globale"
Me.Refresh
End If
End Sub`

Related

Get focus on unbound textbox when form returns no records

I'm a little stumped.
I've got an MS Access front end application for an SQL Server back end. I have an orders form with a list box that, when selected and a "Notes" button is clicked will open another form of notes. This is a continuous form and has a data source (linked table - a view) from the back end database.
When the notes button is clicked in the main orders form, it passes a filter and an OpenArgs string to the Notes form in this code:
Private Sub cmdItemNotes_Click()
Dim i As Integer
Dim ordLine As Boolean
Dim line As Integer
Dim args As String
If Me.lstOrders.ItemsSelected.count = 1 Then
ordLine = False
With Me.lstOrders
For i = 0 To .ListCount - 1
If .selected(i) Then
If .Column(16, i) = "Orders" Then
ordLine = True
line = .Column(0, i)
End If
End If
Next i
End With
If ordLine Then
args = "txtLineID|" & line & "|txtCurrentUser|" & DLookup("[User]", "tblUsers", "[Current] = -1") & "|txtSortNum|" & _
Nz(DMax("[SortNum]", "dbo_vwInvoiceItemNotesAll", "[LineID] = " & line), 0) + 1 & "|"
DoCmd.OpenForm "frmInvoiceItemNotes", , , "LineID = " & line, , , args
Else
'Potting order notes
End If
Else: MsgBox "Please select one item for notes."
End If
Here is my On Load code for the Notes form:
Private Sub Form_Load()
Dim numPipes As Integer
Dim ArgStr As String
Dim ctl As control
Dim ctlNam As String
Dim val As String
Dim i As Integer
ArgStr = Me.OpenArgs
numPipes = Len(ArgStr) - Len(Replace(ArgStr, "|", ""))
For i = 1 To (numPipes / 2)
ctlNam = Left(ArgStr, InStr(ArgStr, "|") - 1)
Set ctl = Me.Controls(ctlNam)
ArgStr = Right(ArgStr, Len(ArgStr) - (Len(ctlNam) + 1))
val = Left(ArgStr, InStr(ArgStr, "|") - 1)
ctl.Value = val
ArgStr = Right(ArgStr, Len(ArgStr) - (Len(val) + 1))
Next i
End Sub
This code executes fine. The form gets filtered to only see the records (notes) for the line selected back in the orders form.
Because this is editing a table in the back end, I use stored procedures in a pass through query to update the table, not bound controls. The bound controls in the continuous form are for displaying current records only. So... I have an unbound textbox (txtNewNote) in the footer of the form to type a new note, edit an existing note, or post a reply to an existing note.
As stated above, the form filters on load. Everything works great when records show. But when it filters to no records, the txtNewNote textbox behaves quite differently. For instance, I have a combo box to mention other users. Here is the code after update for the combo box:
Private Sub cmbMention_AfterUpdate()
Dim ment As String
If Me.txtNewNote = Mid(Me.txtNewNote.DefaultValue, 2, Len(Me.txtNewNote.DefaultValue) - 2) Then
Me.txtNewNote.Value = ""
End If
If Not IsNull(Me.cmbMention) Then
ment = " #" & Me.cmbMention & " "
If Not InStr(Me.txtNewNote, ment) > 0 Then
Me.txtNewNote = Me.txtNewNote & ment
End If
End If
With Me.txtNewNote
.SetFocus
.SelStart = Len(Nz(Me.txtNewNote, ""))
End With
End Sub
The problem occurs with the line
.SelStart = Len(Nz(Me.txtNewNote, ""))
When there are records to display, it works. When there are no records to display, it throws the Run-time error 2185 "You can't reference a property or method for a control unless the control has the focus."
Ironically, if I omit this line and make the .SetFocus the last line of code in the sub, the control is in focus with the entire text highlighted.
Why would an unbound textbox behave this way just because the filter does not show records?
Thanks!

Conditional formatting prevents combobox dropdown on continuous form

The following code filters the dropdown list of a combobox in a continuous subform and allows the user to move up and down the dropdown to select data
'Move through the dropdown using up/down arrow keys
Private Sub IngCombo_KeyDown(KeyCode As Integer, Shift As Integer)
Dim MsgBoxResponse As String
Select Case KeyCode
'Tab button is pressed with "" in the field. Access returns a warning message if not dealt with
Case 9 'Tab Button
If Me.IngCombo.Text = "" Then
MsgBoxResponse = MsgBox("Ingredient you entered is not in the list" & vbCrLf & "Would you like to try again?", vbYesNo, "Ingredient not recognised")
Select Case MsgBoxResponse
Case Is = 6
KeyCode = 0
Case Is = 7
KeyCode = 0
Me.Undo
End Select
End If
Case vbKeyDown
Me.IngCombo.Selected(Me.IngCombo.ListIndex + 1) = True
KeyCode = 0
Me.IngCombo.DropDown
Case vbKeyUp
Me.IngCombo.Selected(Me.IngCombo.ListIndex - 1) = True
KeyCode = 0
Me.IngCombo.DropDown
Case vbKeyEscape
Me.IngCombo.Text = ""
Me.Undo
End Select
End Sub
Private Sub IngCombo_KeyUp(KeyCode As Integer, Shift As Integer)
'Filter dropdown to match what the user has typed
'This combo's control source is the IngredientID, but the ID is hidden, hence the SQL selects both the ID and Ingredient text
Dim UserText As String
If Len(Me.IngCombo.Text) > 0 Then
UserText = Me.IngCombo.Text
Me.IngCombo.RowSource = "SELECT IngredientsTbl.IngredientID, IngredientsTbl.Ingredient " _
& "FROM IngredientsTbl WHERE (((IngredientsTbl.Ingredient) LIKE '*" & UserText & "*'));"
If Me.IngCombo.ListCount > 0 Then
Me.IngCombo.DropDown
End If
Else
Me.IngCombo.RowSource = "SELECT IngredientsTbl.IngredientID, IngredientsTbl.Ingredient " _
& "FROM IngredientsTbl;"
End If
End Sub
Private Sub IngCombo_LostFocus()
Me.IngCombo.RowSource = "SELECT IngredientsTbl.IngredientID, IngredientsTbl.Ingredient " _
& "FROM IngredientsTbl ORDER BY IngredientsTbl.Ingredient;"
End Sub
'If user types string that is found by the 'Key Up' routine above but is in the middle of a string i.e. 'milk' is typed and 'buttermilk' is highlighted
'Then pressing tab results in the not in list error
Private Sub IngCombo_NotInList(NewData As String, Response As Integer)
MsgBox "No ingredient matches your search", vbOKOnly, "Nothing Found"
Me.IngCombo = ""
Response = acDataErrContinue
End Sub
This works as intended.
I then add a conditional format, [text19]>50, to the ‘IngCombo’ combobox. This also works as intended but changes the behaviour of the 'IngCombo' combobox. The dropdown no longer appears, and when the user types in the ‘IngCombo’ field of a new record, it has the effect of filtering the text in the ‘IngCombo’ field of the other records of the continuous form. Eg if the user types ‘mint’, then records that contain mint in ‘IngCombo’ are shown, but all the others are blank.
The word ‘calculating’ appears momentarily in the bottom left, replacing the words 'form view' after a key is pressed. I assume this is the conditional formatting doing its work and disrupting the code, as ‘calculating’ does not appear when there is no conditional formatting.
Is there a way of maintaining the functionailty of the code and also having the conditional formating
Update after June7's comment that referenced Allen Browne code.Tried moving code into a Private Sub that is called from the combo's Change event
Private Sub IngCombo_Change()
Dim Cmbo As ComboBox
Set Cmbo = Me.IngCombo
Dim NewText As String
NewText = Cmbo.Text
Call ReloadIngCombo(NewText)
End Sub
Private Sub ReloadIngCombo(UserText As String)
If Len(UserText) > 1 Then
Me.IngCombo.RowSource = "SELECT IngredientsTbl.IngredientID, IngredientsTbl.Ingredient " _
& "FROM IngredientsTbl WHERE (((IngredientsTbl.Ingredient) LIKE '*" & UserText & "*'));"
If Me.IngCombo.ListCount > 0 Then
Me.IngCombo.DropDown
End If
Else
Me.IngCombo.RowSource = "SELECT IngredientsTbl.IngredientID, IngredientsTbl.Ingredient " _
& "FROM IngredientsTbl;"
End If
End Sub
This works as intended. Adding a conditional format to the combobox prevents the dropdowns being shown to the user

MS Access Form VBA Check Checkboxes, Before Checking Others?

I am working on an Access application, with a SQL back-end.
I have a form for people, where each person can need to have different things checked or unchecked. There are the following fields and corresponding controls on the form:
No Options (integer - boolean - checkbox)
Option A (integer - boolean - checkbox)
Option A Amount (money)
Option B (integer - boolean - checkbox)
Option B Amount (money)
Option C (integer - boolean - checkbox)
Option C Amount (money)
Option D (integer - boolean - checkbox)
Option D command button (opens popup form with option type drop down and amounts for multiple values to be entered).
My concern is that if someone checks one box, it can conflict with another checkbox or money fields.
If someone checks No Options, and one of the other options is checked, I have to uncheck those. I also need to 0 out their corresponding money field. If there are Option D "Other Option" records, in a linked table, then I need to delete those too, after I confirm with the user. I also want to disable the checkboxes and money/ command button controls for options A - D.
If I am unchecking No Options, then I need to enable all of that.
You can start to see how every time I check any of the No Options, or Options A - D, I have to check the state of No Options, and the option's corresponding money amount, to confirm the user wants to make this change.
To do that, I set up the following code for the No Options Before update:
Private Sub NoOptions_BeforeUpdate(Cancel As Integer)
Dim Msg, Style, Title
Dim delOLiensSQL
If Me.NoOptions = False Then
If (Me.OptionA = True Or Me.OptionB = True Or Me.OptionC = True Or Me.OptionD = True) Then
Msg = "You have chosen No Options, but one or more option is checked." & vbCrLf & _
"Choosing No Options will require removing all Lien amounts." & vbCrLf & _
"Would you like to change this Person to No Options?"
Style = vbYesNo
Title = "All Options Will Be Reset to 0 and False."
Response = MsgBox(Msg, Style, Title)
If Response = vbYes Then
If Nz(DLookup("ID", "tblPersonOtherOptionsD", "FKPerson = " & Me.ID), 0) Then
delOLiensSQL = "Delete From tblPersonOtherOptionsD Where FKPerson = " & Me.ID
DoCmd.RunSQL delOoptionssSQL, dbSeeChanges
End If
Me.OptionA = False
Me.OptionAAmount = 0
Me.OptionB = False
Me.OptionBAmount = 0
Me.OptionC = False
Me.OptionCAmount = 0
Me.OptionD = False
OptionsAllowPubFunc (False)
Else
Me.Undo
MsgBox "OK, we will leave everything as it is.", vbOKOnly, "Better Safe Than Sorry"
End If
Else
Me.NoOptions = True
End If
Else
Me.NoOptions = False
End If
End Sub
OptionsAllowPubFunc (False) is a public function which is the following:
Public Function PlaintiffLiensAllowed(Liens As Boolean)
Forms!frmPerson.OptionAAmount.Enabled = Liens
Forms!frmPerson.OptionBAmount.Enabled = Liens
Forms!frmPerson.OptionCAmount.Enabled = Liens
Forms!frmPerson.OptionDAmount.Enabled = Liens
End Function
I also set up Before Update public function for OptionA, OptionB, OptionC, OptionD as follows:
Public Function ChangeAOption(OptionCheck As Control, OptionAmount As Control, OptionName As String)
Dim Msg, Style, Title
Dim Msg2, Style2, Title2
If OptionCheck = True Then
If Nz(OptionAmount, 0) > 0 Then
Msg = "There is a " & OptionName & " Option amount. Unchecking " & OptionName & " Option, will require the amount to be 0." & vbCrLf & _
"Would you like to uncheck " & OptionName & " Option and make the amount 0?"
Style = vbYesNo
Title = "Confirm No " & OptionName & " Option."
Response = MsgBox(Msg, Style, Title)
If Response = vbYes Then
OptionAmount = 0
OptionCheck = False
Else
OptionCheck.Undo
MsgBox "Ok, we will leave it as is.", vbOKOnly, "Better Safe Than Sorry."
End If
Else
OptionCheck = False
End If
Else
If Forms!frmPerson.NoOptions = True Then
Msg2 = "No Options is Checked. Checking " & OptionName & " Options will require no Options to be unchecked." & vbCrLf & _
"Would you like to uncheck no Options?"
Style2 = vbYesNo
Title2 = "Confirm No Options False."
Response2 = MsgBox(Msg2, Style2, Title2)
If Response2 = vbYes Then
OptionsAllowPubFunc (True)
Forms!frmPerson.NoOptions = False
OptionCheck = True
Else
OptionCheck = True
End If
Else
OptionCheck = True
End If
End Function
I'm testing this, and when I try to check the No Options checkbox, changing it from false to true, I get a run-time error '-2147352567 (80020009)':
The macro or function set to BeforeUpdate or ValidationRule property
for this field is preventing the [People application] from saving data
in the field.
Anyone know what I'm doing wrong? Is there a more simple way to do this?
Thank you!!!
From my recent experience, when the Before Update event is triggered it uses the new value of the field in any calculations. So I'd expect you to want to start that main If statement like If Me.NoOptions = True Then.
I also don't believe you need the Else OptionCheck = True bits just before the End Ifs.
What may be causing a problem is you've called OptionsAllowPubFunc, but the function you've included in this question is actually called PlaintiffLiensAllowed - unless you have an identical function called OptionsAllowPubFunc, this'll give you an error.
Finally, I've never found me.undo to be especially helpful in this kind of context, but the Before Update gives you an out - just tell it to cancel using Cancel = True (or anything that isn't 0) and it'll not update the field and exit the sub.
You could also add in a bit to re-enable the option fields if they were un-checking the box.
Try running it as:
Private Sub NoOptions_BeforeUpdate(Cancel As Integer)
Dim Msg As String, Style As VbMsgBoxStyle, Title As String
Dim Response As VbMsgBoxResult, delOLiensSQL As String
If Me.NoOptions = True Then
If (Me.OptionA = True Or Me.OptionB = True Or Me.OptionC = True Or Me.OptionD = True) Then
Msg = "You have chosen No Options, but one or more option is checked." & vbCrLf & _
"Choosing No Options will require removing all Lien amounts." & vbCrLf & _
"Would you like to change this Person to No Options?"
Style = vbYesNo
Title = "All Options Will Be Reset to 0 and False."
Response = MsgBox(Msg, Style, Title)
If Response = vbYes Then
If Nz(DLookup("ID", "tblPersonOtherOptionsD", "FKPerson = " & Me.ID), 0) Then
delOLiensSQL = "Delete From tblPersonOtherOptionsD Where FKPerson = " & Me.ID
DoCmd.RunSQL delOoptionssSQL, dbSeeChanges
End If
Me.OptionA = False
Me.OptionAAmount = 0
Me.OptionB = False
Me.OptionBAmount = 0
Me.OptionC = False
Me.OptionCAmount = 0
Me.OptionD = False
PlaintiffLiensAllowed(False)
Else
MsgBox "OK, we will leave everything as it is.", vbOKOnly, "Better Safe Than Sorry"
Cancel = True
End If
End If
Else
PlaintiffLiensAllowed(True)
End If
End Sub

Include loop counter in object name [VBA]

Basically I wrote a code, which is to be used in userform. The thing is that userform is created by other macro (amount of checkboxes differs, depends how many words string strNamn contains, that is why userform must be created by macro).
I would like to, somehow, include loop counter in the line:
If UserForm1.CheckBox0.Value = True Then
to make it like this:
If UserForm1.CheckBox(i).Value = True Then
But it obviously doesn't work like this :(
Any suggestion how to declare checkbox to include the counter in the line?
Code in UserForm1 to execute macro looks like:
Private Sub cmd_1_Click()
Call clicker
End Sub
Macro code:
Sub clicker()
Dim strNamnOK As String
Dim strNamn As String
Dim strNamnA() As String
strNamn = "one, two, three, four"
strNamnA = Split(strNamn, ", ")
Dim intAmount As Integer
intAmount = UBound(strNamnA)
strNamnOK = ""
For i = 0 To intAmount
If UserForm1.CheckBox0.Value = True Then
strNamnOK = strNamnOK & " " & strNamnA(i)
End If
Next
strNamnOK = Left(strNamnOK, 12)
MsgBox strNamnOK
End Sub

.SetFocus from module VBA

I'm trying to set the focus in a form after update. When I do this within the forms class module I have no problem. However, I need to do this in a few forms so I'm trying to write it in the module. My problem is I can't get the .SetFocus to work unless I hardcode the form name within the class module. WHno is the name of the control I'm trying to set focus.
I have attempted a number of options and none seem to work.
Here is the sub. Everything works wonderfully except the .SetFocus procedure.
Sub ValidateWHNO()
Dim EnteredWHNO As Integer
Dim actForm As String
Dim deWHNO As Variant
msg As Integer
Dim ctrlWHNO As Control
EnteredWHNO = Screen.ActiveControl.Value
actForm = Screen.ActiveForm.Name
Set ctrlWHNO = [Forms]![frmEnterBookData]![WHno]
deWHNO = DLookup("[WHno]", "tblDataEntry", "[WHno] = " & EnteredWHNO)
If EnteredWHNO = deWHNO Then
msg = MsgBox("You have already entered " & EnteredWHNO & " as a WHNO. The next number is " & DMax("[WHno]", "tblDataEntry") + 1 & ", use this?", 4 + 64, "Already Used WHno!")
If msg = 6 Then
Screen.ActiveControl.Value = DMax("[WHno]", "tblDataEntry") + 1
Else
Screen.ActiveControl.Value = Null
ctrlWHNO.SetFocus 'CODE THAT WONT RUN
End If
End If
End Sub
I've tried a number of other methods to set focus, such as:
Forms(actForm).WHno.SetFocus,
Forms(actForm).Controls(WHno).SetFocus, Screen.ActiveControl.SetFocus
The current result is that if No is selected in the MsgBox, the value is cleared, but the focus moves to the next control.
Thanks in advanced for any help that may be offered.
Does the following make a difference?
Sub ValidateWHNO(frm as Access.Form)
Dim EnteredWHNO As Integer
Dim actForm As String
Dim deWHNO As Variant
msg As Integer
EnteredWHNO = frm.ActiveControl.Value
actForm = frm.Name
deWHNO = DLookup("[WHno]", "tblDataEntry", "[WHno] = " & EnteredWHNO)
If EnteredWHNO = deWHNO Then
msg = MsgBox("You have already entered " & EnteredWHNO & " as a WHNO. The next number is " & DMax("[WHno]", "tblDataEntry") + 1 & ", use this?", 4 + 64, "Already Used WHno!")
If msg = 6 Then
frm.ActiveControl.Value = DMax("[WHno]", "tblDataEntry") + 1
Else
frm.ActiveControl.Value = Null
frm![WHno].SetFocus
End If
End If
End Sub
And your call from each form would be:
VaidateWHNO Me
Instead of using a relative reference to the form (Screen.ActiveForm), the code passes the form reference through directly and uses that reference as the parent of the .setFocus method.