I can't get the RowSource property of a list box to update via VBA. From another thread, I found the syntax, so I think this is correct. But, despite not failing, it doesn't do anything to the RowSource property (it remains blank). Below:
frmAddIngredient is the user form.
lbxIngredient is a listbox control in that form.
UniqueIngredients is one of the sheets in the workbook.
NumberOfItems is 1 (in this case).
It doesn't give an error, but it doesn't change anything, either. The form itself is not active at this time. This code is supposed to set up the form for later showing.
frmAddIngredient.lbxIngredient.RowSource = Sheets("UniqueIngredients").Range("A1:A" & CStr(NumberOfItems)).Address
The most recent code is
frmAddIngredient.lbxIngredient.RowSource = "=UniqueIngredients!A1:A1"
but, it still doesn't change anything in the actual form.
Also, can I add a new post, or do I have to continue editing this one and adding stuff?
What you want (as discussed in the comments on your question) is not possible. Setting something by code does not change it's property in the properties window and is only so until your project resets.
Consider a Userform with 2 buttons, with their original name and caption and then in a module paste these 2 subs.
Sub demo1()
UserForm1.CommandButton1.Caption = "Demo 1"
UserForm1.Show
End Sub
Sub demo2()
UserForm1.CommandButton2.Caption = "Demo 2"
UserForm1.Show
End Sub
When you run the first Sub demo1 Button 1's caption has changed but Button 2's caption has not.
Close the Userfom and now run demo2, you'll see that Button 1's caption is back to it's original hard set (properties window) name and that now Button 2 has a different name.
Related
During an import routine I am adding comments to faulty cells (e.g. rg.AddCommentThreaded "wrong data type")
In case there were errors (and therefore new comments) I would like to force the comments pane to be visible (via code). But I can't find a method/property what ever.
I looked into the application, workbook and windows-object ... nothing ...
Am I missing sth - or is there no way to show them via VBA?
The screenshot shows the button (in German) I want to activate.
There is also a button on the Review-tab that shows/hides the new comment pane.
Found the according idMso here: https://github.com/OfficeDev/office-fluent-ui-command-identifiers/blob/master/Office%20365/Semi-Annual/excelcontrols.xlsx. It is within the "GroupThreadedComments"
Sub showCommentsPane()
With Application.CommandBars
If .GetPressedMso("ShowThreadedComments") = False Then
.ExecuteMso "ShowThreadedComments"
End If
End With
End Sub
Is it possible to save changes to a Label Caption in a userform in Excel VBA, so that they are permanently saved, and only changed when you enter a new change?
I have checked, that the code is changing the caption, but I cannot get it to stick, so that it is still there next time I open the userform.
Thank you in advance
Private Sub cmdSubmit_Click()
'resets participants email and name
If Me.optProg.Value = True Then
Me.NameLabelProg.Caption = Me.CB_Part.Value
Me.MailLabelProg.Caption = Me.TB_Mail.Value
ElseIf Me.optTester.Value = True Then
Me.MailLabelTest.Caption = Me.CB_Part.Value
Me.NameLabelTest.Caption = Me.TB_Mail.Value
End If
End Sub
Check out this userform example and you'll find answers to many of your questions.
Source of userform
Forgive the lengthy answer initially, but there is a bit of a risk involved with making permanent changes to UserForms through VBA.
In order to change the caption of a Label (or UserForm or any other Control permanently, you will have to "Trust access to the VBA project object model" in order to do it via VBA code. Now, while this is possible it is not usually recommended because it can seriously put a user's PC at Risk should they encounter a Macro developed for nefarious purposes.
(To clarify in case the question is raised, your end user(s) will have to make this Trust setting change on their PC's as well . . . you cannot make the change on your PC, setup the code to work and then hand the file over to another user and have it work on their PC without them making the same change.)
There are methods to do this programmatically, but, this falls into the "nefarious Macro" rabbit hole and would need to be disclosed to the end user you are making this change. . . Research at your own risk.
If you are OK with putting yourself at risk, you can do it using VBA similar to the following snippet I found here. You will have to substitute your UserForm name and Label name as appropriate. I tested it on my own UserForm and it works as expected.
Sub Change_Userform()
ThisDocument.VBProject.VBComponents("Userform1").Designer.Controls("Label1").Caption = "Some new caption text"
End Sub
You will need to do some research on how to "Trust access to the VBA project object model" yourself and understand the risks to do this in order for the above code to work.
If I understand the intent of what you are trying to accomplish correctly though, you could achieve this effect without having to put yourself or your end user(s) at risk.
(Most end user(s) typically would not have direct access to the VBA Designer where they would see the UserForm's un-initialized environment.) To do this, you would have to place your code in the UserForm's event.
The following assumes your Me.optProg.Value and Me.optTester.Value are Option Buttons which a user would change. If you create a "Settings" sheet in the file, you can place values in the cells of this sheet and then hide it so the users do not modify them directly. Then, reference the values of the cells and change the appearances of the Option Buttons at the same time as the UserForm's launch. (Additionally, you can set the Click events of the Option Buttons to change the values of the same cells and provide that change to affect the UserForm's Initialize event when called, but this should get you going in the right direction.)
Sub UserForm_Initialize()
'The Range below is completely up to you.
'Since you are using Boolean True/False, a simple "1" or "0" _
is easy to use to make the changes.
If Thisworkbook.Sheets("Some_Settings").Range("A1").Value = "1" Then
Me.optProg.Value = True
Else
Me.optTester.Value = True
End If
'do some other code here as needed to finish initializing the UserForm
If Me.optProg.Value = True Then
Me.NameLabelProg.Caption = Me.CB_Part.Value
Me.MailLabelProg.Caption = Me.TB_Mail.Value
ElseIf Me.optTester.Value = True Then
Me.MailLabelTest.Caption = Me.CB_Part.Value
Me.NameLabelTest.Caption = Me.TB_Mail.Value
End If
End Sub
I am creating a userform using Excel VBA that is meant to be used to register some sales. The form looks like this:
As you may have noticed, I am using an image as a button. This is because the CommandButton included in VBA looks very outdated. However, using an image as a button also creates me a new error (or not, depending on how you see it) that is driving me crazy. The usual process for filling this is entering a product, a quantity, a price, a customer and clicking the button to save all the information to a worksheet. The payment textbox is only filled sometimes.
I created a data validation mechanism for all these fields, including the customer combobox. If the user types an invalid entry or leaves the field empty after clicking it, a message box appears. The code for that is the following:
Private Sub cmbCustomer_AfterUpdate()
If cmbCustomer.ListIndex > -1 Then
Else
MsgBox "Please choose a valid customer", vbExclamation
cmbCustomer.Value = ""
End If
End Sub
This works great for avoiding invalid entries. The tricky part is that, once the button is clicked, all the fields are automatically erased. The data is correctly saved, but if the last field used before clicking was cmbCustomer (or any other, actually, because all of them have a similar mechanism to avoid empty or invalid data) and the user decides to begin filling the form again starting by the product, the message box appears, because it is empty and the code detects the invalid entry. I know this is the expected behavior for my code, but this doesn't happen if I use a traditional CommandButton because when clicking it the focus goes to said button. If I use my image-based button the focus remains on the last text field used before clicking it.
One solution would be to override the message box in this specific situation (when saving the data). The second one would be to reset the focus of the form, or set focus to the image like what happens with a regular CommandButton. Any suggestions would be greatly appreciated.
You can do yourself what the traditional CommandButton does automatically: Set the focus where you want it:
Private Sub cmbCustomer_AfterUpdate()
If cmbCustomer.ListIndex > -1 Then
Else
MsgBox "Please choose a valid customer", vbExclamation
cmbCustomer.Value = ""
myButton.SetFocus
End If
End Sub
If SetFocus doesn't work, be mindful of where you are in the UI event chain: Why is my .setfocus ignored?
As mentioned in the comments, an image button can't acquire the focus. A transparent CommandButton behind it can be used as a proxy.
I have been playing around with form designs and now I have constructed a form, which is almost complete, just one problem left. Let me explain first:
Form is bound to a "Join Table", which has only 2 fields - ID from "Table1" and ID from "Table2". Based on those two fields I have added fields from "Table1" & "Table2", on same form. Then I have added 2 option buttons, 1 Combobox and 2 Subforms.
This allows me to watch records from two different tables that are joined, from each point of view - "Table1" or "Table2" view. I am selecting this views with Option buttons, which changes Combobox rowsource, so you can navigate to records from Combobox.
Here is code :
Private Sub OptButton0_Click()
If Me.OptButtonO.Value = True Then
Me.OptButton1.Value = False
Me.Cmbox.RowSource = "SELECT [Table1].[Field1], [Table1].[Field2], [Table1].[Field3] FROM Table1 ORDER BY [Field1];"
Me.Cmbox.SetFocus
Me.Cmbox = Me.Cmbox.ItemData(0)
End If
End Sub
Private Sub Cmbox_AfterUpdate()
If Me.OptButton0.Value = True Then
If IsNull(Me!Cmbox) Then Exit Sub
With Me.RecordsetClone
.FindFirst "[Field1] = " & Me!Cmbox
If Not .NoMatch Then
If Me.Dirty Then Me.Dirty = False
Me.MySubform.Width = 8280
Me.MySubform.SourceObject = "MySubform"
Me.Bookmark = .Bookmark
Else
Me.MySubform.Width = 8000
Me.MySubform.SourceObject = ""
End If
End With
Me.Cmbox.SetFocus
DoCmd.Requery
End If
End Sub
This posted code is only for one Option button, second one is same, just opposite. Now what is problem ?
Problem is that when I navigate through record via Combobox, click second Option button for another view AND THEN RETURN to same view, my subform results stays same as they were when I clicked another Option button, although Combobox listIndex is 0. If I select combobox Listindex from Combobox, code works again.
SO BASICALLY - I NEED CODE THAT WILL TRIGGER COMBOBOX CHANGE WHEN OPTION BUTTONS ARE CLICKED. It works when you're clicking in Combobox, but not when clicking in Option button.
I know It's complicated to understand, please take a look at code, and ask anything. Any help appreciated.
Another option: I had a similar issue: with an unbound combobox. In the '*_Change' event in a combobox, if I pick a value from the dropdown, the value is there; but if I delete the existing value, the prior value still shows up.
...
If Me.series_filter > "" Then
lstrMetric = lstrMetric & "and X.series_name = '" & Me.series_filter & "' "
End If
...
Me.Filter = Mid(lstrMetric, 5)
...
I have a dropdown for a filter on the form: picking a value is meant to set (or clear) the filter. It worked when I picked a value, but would not clear if I delete it.
I added a line to the start of the code to commit updates:
Me.dirty = false
The code now recognizes the null value when the combobox is cleared. This works in my case - of course it would be a problem if you didn't want any updated fields written to the database.
call the the combobox afterupdate event in the option button click event:
private sub optbutton0_click()
...
cmbox_afterupdate()
end sub
PS: Rather than having events for option buttons directly, you should put them in a frame, (even if you then have to make the frame transparent to stop it from appearing) and use the afterupdate or click events of the frame, whereby you can get the selected option button by option value:
private sub frame0_click()
select case frame0
case 0 'option button 0 is selected
...
case 1
...
end select
end sub
In Access, controls can be funny. I mean, when you change the option, you see it change, it changes on the screen... but the control doesn't always change its .value right away... meaning it doesn't Update. For a simpler illustration of this principle, create a textbox, type some stuff into it, and look at the textbox.value in the immediate window. Then, with the cursor still in the textbox, backspace some of it. Check the value again. Do that a few more times. Start including textbox.text in your tests. There are multiple ways around this, but it is most important to understand when controls actually update, so you can understand better when and which work arounds to use.
Now, in this situation, you typed 'click' every time when you referenced selecting an option. I think I will hold you to that. Personally, I use Tab and the arrow keys sometimes, which would be a slightly more complicated answer, but one you will be better equipped to solve yourself, after understanding the textbox example above. But, if you change AfterUpdate above to Click, you should be good.
That said, there are events besides mouse clicks that can activate the Click event. Usually not a problem, but since you are changing the look of your form, specifically the width, you may want to be aware that the subform width may flash back and forth sometimes while using your tool. Not often, probably won't be too much of an annoyance, but I might rethink why I needed to change width at all, or if there might be better triggers for it.
My question is basically answered in this post
But instead of the class code below:
Sub CmdEvents_Click()
MsgBox "Hello World"
End Sub
I need to run this code (it's just a sample, I want to use the name of the button clicked later in the program)
Sub CmdEvents_Click()
Dim mvCtrl As Control
Set mvCtrl = Me.ActiveControl
MsgBox mvCtrl.Name
End Sub
But this code above will NOT, by any means return correctly the Name of the button I just created in run time in the message box.
It returns "Button 6".... I did a search in my workbook and I don't even have this name.
I actually I modified the original code from the link above to get the names of the buttons all from a list. This way I can modify the list, thus modifying the name of the buttons, or caption if I want to. And this Button 6 doesn't even exists in my list.
I made some traps in my code, showing message boxes for the variable I use to get the button name from, and it's correct, it's carrying the string I want to name my button before it creates it.
Assuming you followed the post you linked to, your class instance already contains a variable CmdEvents which references the clicked button, so you can use
Msgbox CmdEvents.Name
If your code is different, it would be useful to post the relevant parts so we can see what's going on.