Call SetFocus for a textbox with Excel VBA in Excel 2013 - vba

When I call SetFocus for my textbox, it throws this error:
Run-time error '438':
Object doesn't support this property or method.
Is SetFocus readily available in Excel 2013 or do I have to patch or update any component of my Excel?

I think Setfocus() probably never throw an error like that!!
Object doesn't support this property or method (Error 438)
This method or property does not exist for this OLE automation object. See the object's documentation for more information on the object and to check the spellings of properties and methods.
Here you have a method SetFocus(), So you need to know when this method does not exist!
In Office 2013 if object or one of its containers is not visible or enable, it throw this error:
Run-time error '2110':
Can't move focus to the control because it is invisible, not enabled, or of a type that does not accept the focus.
And as I tested making loop by raising Enter Event is also don't throw error, And also for similar using SetFocus() method:
Private Sub TextBox1_Enter()
TextBox2.SetFocus
End Sub
Private Sub TextBox2_Enter()
TextBox1.SetFocus
End Sub
And I can't figure any other reason !

Please see this answer: https://www.vbforums.com/showthread.php?646411-RESOLVED-How-can-I-make-setfocus-ot-Textbox-in-vba
You are using Excel after all, but you have the textbox on a worksheet rather than a userform.
Setfocus will work for textboxes on a Userform, but as you have discovered, not if they are on the actual worksheet.
Instead of setfocus try activate:
Private Sub CommandButton1_Click()
TextBox1.Activate
End Sub

Related

Excel VBA: Calling a ComboBox_Change located in another wb

When writing a VBA code, I tried to call a Combobox_Change Sub (not Private Sub), which is located in 'Sheet2' of another workbook called 'wb2'.
Call wb2.Sheet2.ComboBox_Change
However, the program returns the runtime error 438. Am I missing anything or can someone proovide a fix? Thanks!
Run-time error 438: Object doesn't support this property or method
Event handlers do one thing: they handle events. That's why they're Private: they never need to be explicitly invoked by any other code - they're invoked by their respective event source, period.
C++
C#
Delphi
If it's bad practice in every language I could be bothered to find a SO post about this for, then why would it be any different in VBA? Hint: it's not, the reasons why explicitly invoking an event handler is a bad idea, are completely language-agnostic (provided your language has a concept of "event").
Don't make them Public and then invoke them explicitly. Instead, have that other code toggle the state of the control, and let the control fire its event - assuming an ActiveX/MSForms control:
Dim ctrl As MSForms.ComboBox
Set ctrl = wb.Worksheets("Sheet2").OLEObjects("ComboBox1").Object
ctrl.Value = Not ctrl.Value
If you don't want to toggle the control's state, only to invoke its handler, then pull the handler's implementation out - instead of this:
Private Sub ComboBox_Change()
'do stuff
End Sub
Do this:
Private Sub ComboBox_Change()
DoStuff
End Sub
Public Sub DoStuff()
'do stuff
End Sub
And then invoke DoStuff like you would any other macro-in-another-workbook.
Note that the Call keyword is completely redundant.

Access function to hide controls on a form

ACCESS 2016
I am trying to create a function to hide controls that are passed to it.
I have a textbox called NextCheck. I have the function:
Public Function hideControl(ctrl As Control)
Set ctrl.Visible = False
End Function
And the Sub on the form below.
Private Sub testBtn_Click()
hideControl (Me.Nextcheck)
End Sub
When I run this I get a message
'run-time error '424' Object required
Can anyone point me in the right direction (I'm a novice with functions) as to what the problem is here. My understanding that the (Me.Nextcheck) was the object being passed to the function.
Thanks.

Passing a parameter to an event handler procedure

I am generating a scripting dictionary using one button on a userform, using it to populate a listbox, and then need to use that same dictionary using a second button on the form. I have declared my dictionary either using early binding as so:
Dim ISINDict As New Scripting.Dictionary
or late binding as so
Dim ISINDict as Object
...
Set ISINDict = CreateObject("Scripting.Dictionary")
When I try to pass the dictionary to the other button like so:
Private Sub OKButton_Click(ISINDict as Scripting.Dictionary) 'if early binding
Private Sub OKButton_Click(ISINDict as Object) 'if late binding
I get the following error: "Procedure declaration does not match description of event or procedure having the same name" on that line.
Any ideas what I'm doing wrong?
An event handler has a specific signature, owned by a specific interface: you can't change the signature, otherwise the member won't match the interface-defined signature and that won't compile - as you've observed.
Why is that?
Say you have a CommandButton class, which handles native Win32 messages and dispatches them - might look something like this:
Public Event Click()
Private Sub HandleNativeWin32Click()
RaiseEvent Click
End Sub
Now somewhere else in the code, you want to use that class and handle its Click event:
Private WithEvents MyButton As CommandButton
Private Sub MyButton_Click()
'button was clicked
End Sub
Notice the handler method is named [EventSource]_[EventName] - that's something hard-wired in VBA, and you can't change that. And if you try to make an interface with public members that have underscores in their names, you'll run into problems. That's why everything is PascalCase (without underscores) no matter where you look in the standard libraries.
So the compiler knows you're handling the MyButton.Click event, because there's a method named MyButton_Click. Then it looks at the parameters - if there's a mismatch, something is wrong: that parameter isn't on the interface, so how is the event provider going to supply that parameter?. So it throws a compile-time error, telling you you need to either make the signature match, or rename the procedure so that it doesn't look like it's handling MyButton.Click anymore.
When you drop a control onto a form, you're basically getting a Public WithEvents Button1 As CommandButton module-level variable, for free: that's how you can use Button1 in your code to refer to that specific button, and also how its Click handler procedure is named Button1_Click. Note that if you rename the button but not the handler, the procedure will no longer handle the button's Click event. You can use Rubberduck's refactor/rename tool on the form designer to correctly rename a control without breaking the code.
Variables in VBA can be in one of three scopes: global, module, or procedure level.
When you do:
Sub DoSomething()
Dim foo
End Sub
You're declaring a local-scope variable.
Every module has a declarations section at the top, where you can declare module-scope variables (and other things).
Option Explicit
Private foo
Sub DoSomething()
End Sub
Here foo is a module-scope variable: every single procedure in that module can access it - read and write.
So if you have data you want to pass between procedures and you can't alter their signatures, your next best option is to declare a module-scope variable.
[ignores global scope on purpose]
About As New - consider this:
Public Sub Test()
Dim foo As Collection
Set foo = New Collection
Set foo = Nothing
foo.Add 42
Debug.Print foo.Count
End Sub
This code blows up with run-time error 91 "object variable not set", because when foo.Add executes, foo's reference is Nothing, which means there's no valid object pointer to work with. Now consider this:
Public Sub Test()
Dim foo As New Collection
Set foo = Nothing
foo.Add 42
Debug.Print foo.Count
End Sub
This code outputs 1, because As New keeps the object alive in a weird, unintuitive and confusing way. Avoid As New where possible.
Declare the dictionary at the module level and fill it in button-1-click event handler. Then it can be simply re-used in button-2-click event handler. So there is no need to pass the dictionary to event handlers which is not possible either. HTH
Form module
Option Explicit
' Declare dictionary at the user form module level
Private ISINDict As Scripting.Dictionary
Private Sub CommandButton1_Click()
FillDictionary
End Sub
Private Sub CommandButton2_Click()
' Use the dictionary filled in event handler of CommandButton-1
End Sub
Private Sub FillDictionary()
With ISINDict
.Add "Key-1", "Itm-1"
.Add "Key-2", "Itm-2"
.Add "Key-3", "Itm-3"
End With
End Sub
Private Sub UserForm_Initialize()
Set ISINDict = New Scripting.Dictionary
End Sub

VBA Force variable affectation by reference

So I encouter some very weird problem in VBA which I believe is a "feature" of the language.
Right now the following code generates an error of type incompatibility:
Sub MyFoo()
Dim txtTest As TextBox
Set txtTest = frmFoo.txtExistingTextBox
End Sub
So I've come to the conclusion that somehow VBA tries to put the string value of frmFoo.txtExistingTextBox.Value in txtTest while I strictly want to get the TextBox control object.
I know that in some languages there is a way to define if you want or not do an affectation by reference instead of value, which would solve the problem here, but I have no idea how.
I know I could simply declare txtTest as Variant but I find this very unclean :-/
Thanks!
Your conclusion is wrong I'm afraid. The mismatch occurs because Excel's object library has a Textbox object, which is not the same as the MSForms textbox used on a userform. You should be using:
Sub MyFoo()
Dim txtTest As MSForms.TextBox
Set txtTest = frmFoo.txtExistingTextBox
End Sub
Set is always by reference. Try to declare the full type:
Private Sub UserForm_Click()
Dim control As MSForms.TextBox
Set control = Me.TextBox1
End Sub
It could also be a compilation issue. In that case, try to modify the module or rename it and run the code again.

Excel VBA - Assign value from UserForm ComboBox to Global Variable

I have a userform with a basic combobox and command button. When the user hits the command button, I want the UserForm to close, and the value of the combobox to be saved in a variable that can be accessed by a subroutine contained within "ThisWorkbook".
In the UserForm code:
Public employee_position As String
Public Sub CommandButton1_Click()
employee_position = Me.ComboBox1.Value
Unload Me
End Sub
In the "ThisWorkbook" Code
Private Sub GetUserFormValue()
Call Userform_Initialize
EmployeePosition.Show
MsgBox employee_position
End Sub
When "GetUserFormValue()" runs, the UserForm comes up, you can select a value in the combobox and press the command button, but when the MsgBox comes up, it displays "" (Nothing)
What am I doing wrong here?
When you Unload Me, I think you lose all information associated with the module (including the global variable). But if you use Me.Hide rather than Me.Unload, then you can access the value of the form after the routine returns. So try this:
-- userform code includes:
Public Sub CommandButton1_Click()
Me.Hide
End Sub
-- main module includes:
Private Sub GetUserFormValue()
Call Userform_Initialize
EmployeePosition.Show
MsgBox EmployeePosition.ComboBox1.Value
Unload EmployeePosition
End Sub
I think that should work.
I had the same problem, and this is how I resolved it:
If the main code is in a worksheet, and the variable is declared as public in that worksheet (e.g. in Microsoft Excel Objects -> Sheet1 (Sheet1)), the result from "Unload Me" cannot be passed from a UserForm to the worksheet code.
So to solve my problem, I inserted a new Module, and declared my public variable there. I didn't even have to move my code from the worksheet to the module... just the declaration of the public variable.
I hope this works for you too!
Andrew