Is SetFocus a Function? - vba

I saw this line of code txtNewCaption.SetFocus and was told that SetFocus is used as a sub
here but it is also a function. I also read online that the difference between a sub and a function is that a sub doesn't return any value but a function returns a value. I couldn't imagine what kind of value SetFoucs could return, so I searched quite some articles online about SetFocus but none of them gave me an example of SetFocus used as a function to return a value. I am assuming there is something inaccurate or wrong with either my understanding or what I was told.
Could you please help me to clarify the confusion?
Thank you!

Well, in this case and example, .setFocus is not a sub, nor is it a function.
A sub is a separate bit of code, you call it like
Call MySub
(or a shorter form skips the word "call" - it is optional)
eg:
MySub
Or, if there are parameters, you might go:
Call MySub(InvoiceNumber)
In the case of a function? That is again a external bit of code. You can use functions that return a value and IGNORE that return value.
So
MyVar = MyFunction()
And just like subs, the function can accept parameters:
MyVar = MyFunction(InvoiceNumber)
And as I noted, you can "ignore" the return value of a function like this:
MyFuncton InvoiceNumber
If you write as per above, the you are passing the value, but the return value of the function is not "placed" or put into anything. so you can "use" a function that returns a value. You also skip use of the () around the value you pass.
However, in the above two examples we are talking about VBA sub and functions YOU write.
SomeTextBox.SetFocus is NOT sub, nor is it a function.
What the above is called? It is called a Method of the object.
So, when you use Access objects, say record Sets, controls etc? Well that "object" will have what we call properties (usually things that you can set or get a value from).
So, for a text box, you have:
MyControl.Value = "Hello"
The above would set the value (text) of a text box to Hello. Thus ".value" is the property of that text box. It also happens to be the default property. So you can go:
MyControl = "Hello"
Now, if you go:
Msgbox("Value of MyControl = " & MyControl.Value)
So a property of a "thing" (a object) often can be set a value, and you can get (retrieve) a value. This is called a property.
However, these objects also have what are called methods. Methods are a "action" and are similar to a sub/function (but YOU did not write that method).
And such methods are "some code" that runs that is part of the object. So sometimes the difference between a property of a object, and a method of a object is "gray". Some methods can accept values and return values, but the distinction between the two (method and property) is that MORE then setting a value can occur with a method. (so it not just limited to get and set).
A "method" can be thought of some "action" and code. Use of that Method tends to be assumed that some code will run. (and it not your code in most cases - it is "code" attached to the built in object.
So
MyTextBox.SetFocus
It is a method of the text box control, or the given control in question. Not all controls necessary may have this "method".
So .SetFocus is not sub, not a function, but is in fact a method of the control in question.

Functions don't necessarily have to return a value. You can call functions just like you can call subs. Try for yourself: write a function, step through the function in a sub, and then check your locals window.
Functions have the added bonus of being able to return values, but don't have to.
EDIT: Aside from the need to return a value, I'm sure there is a reason to use one over the other, but I generally determine whether to use a sub or a function by the complexity of the task. I use functions to perform simple tasks and subs to perform more complex ones.

If you search the Microsoft Documentation (MSDN) for SetFocus, you will find it defined as:
method on a user-interface control object, moving the focus to it ... with no return value
(above quotation is not literally cited, but conveys the meaning)
SetFocus Method [Access 2003 VBA Language Reference]
TextBox.SetFocus method (Access)
SetFocus method (Microsoft Forms)
Function?
Thus it is not a function in VBA syntax.
Besides: a function's return value in VBA is optional. See VBA language reference: Function statement:
Optional. Return value of the Function.
Common method naming conventions
In most programming languages the common naming convention (case ignored) for methods apply:
use get (often without parameters) to return a value. Such methods are called getter or accessor.
use set (often with parameter as value to set) to set a new state (or value). Usually the have no return value, because the new value or state is predicted by the argument passed (their parameter). Such methods are called setter or mutator.
use is, has, exists, contains, starts, ends, etc. to return a boolean value. Such methods are used to check flags (on/off, true/false, yes/no).
use calculate, locate, indexOf, find, fetch, lookup, determine, etc. (often with parameters) to return a value resulting of some processing based on specified parameters (by some logical, mathematical algorithm or queried by data-retrieval)

Related

'Contains' is not a member of 'System.Web.UI.WebControls.TextBox'

I want to stop people sending us messages including the word "telegram".
I have a very old script in VB that uses sendmail. It has always worked fine. Now I am trying to add this:
Sub CheckTelegram()
'check for Telegram
If messagetext.Contains("telegram") Then
messagetext.BorderColor = Drawing.Color.Red
Else
But I receive an error:
Compiler Error Message: BC30456: 'Contains' is not a member of 'System.Web.UI.WebControls.TextBox'.
Can I not use .Contains() this way? I was expecting the border to go red if "telegram" was within the text box.
the TextBox class itself is not a text. You must access the Text property which is of type String:
If messagetext.Text.Contains("telegram") Then
' ^^^^
Because Contains is a method of the String class, not a method of the TextBox class.
Note that older VB versions (VB 6.0, VBA) had the concept of default properties. You could effectively call s = Me!TextBox1 and if s was typed as String, VB was smart enough to see that a TextBox could not be assigned to s and the Text or Value property was automatically retrieved.
VB.NET has a stronger typing and also wants you to do more things explicitly (especially if you have Option Strict On, what I urge you to do). This is better for the understanding of the code and leads to less programing errors. E.g., if you have a declaration Dim obj As Object then what should obj = Me!TextBox1 do? Assign the TextBox or TextBox.Text? Such an automatism can be very confusing.

How to use Form Controls in Modules

In my modules, I want to use my controls from my form. For example: I want to set focus on a textbox after a certain Sub.
My current solution is to make a subroutine to set all controls in a public variable (see below).
My questions:
What is the best practice? How do people usually do this?
When should I call my subroutine? (is it the first call in the FORM_LOAD sub?)
Public TBnr As TextBox
Public Sub controlsInitieren()
Set TBnr = Forms("frm_TreeView_Example").pstNr
End Sub
Well, as a general rule, while many platforms seperate out the UI part and the code part? Well, Access is quite much a different approach - it is standard fair to place the required code inside of the form "class" (all forms in Access are a "class", and you can even have muliple instances of the SAME form open more then one time).
So, in general, your code should be in the forms code (class) module.
However, you could and call a external routine.
So in the form, you could call your above routine like this:
Call MySetFocus(me, "NameOfControlToSetFocusTo")
And your sub would look like this:
Sub MySetFocus(f as form, sCtrl as string)
f(sCtrl).SetFocus
End Sub
However, as noted, the amount of code above is more code then simply in the forms code module going:
me.ControlName.SetFocus
However, while the above is a less then ideal example, passing the form "instance" (me) to a external sub or function allows you to referance any property or method or feature that exists in the form in an external routine.
So in place of say
me("LastName") = "Zoo"
In the above sample routine, you would and could go;
f("LastName") = "Zoo"
So any place you would and could use "me" in the form, you can use the form instance you passed from the form. As noted, it is a good idea to use "me", since as I noted, Access does allow multiple copies of the form to be opened at the same time - and thus your code can't distinguish between what form instance you are using unless you pass the current "in context" form. So like in JavaScript, using "this" ?
In access that current instance of the class object is "me", and you are free to pass that instance to any sub or function you want as per above.
The best practice is to use only procedures inside the form code. In such a case you refer to a text box control in this way: Me.Textbox1.SetFocus. If you want to set some controls properties during the form loading, you can do that in the frm_TreeView_Example_Initialize event;
They usually do it in the way I described at item 1;
If you want to use such a strange/unusual way you can do it calling the subroutine whenever you want. But, in order to set a specific property value of the form frm_TreeView_Example controls you can simply use frm_TreeView_Example.TextBox1.SetFocus. You can use this way of setting in a module procedure, even before the form has been shown. You can simply show it in that procedure code using at the end: frm_TreeView_Example.Show;

Iterate over COM collection without foreach or .Item()

I need to iterate over a COM collection within Matlab. In VB I could use For Each item In Collection; in Python I could use for item in Collection. But unfortunately such constructs are not available in Matlab, which uses a simple loop, something like this:
for index = 1 : Collection.Count
item = Collection.Item(index);
% now do something useful with the item
end
This works well in general. But in my particular Collection, .Item() only accepts a string (the item's name), not a numeric index. So the code snippet above fails, because I do not know the item names in advance, before iterating over the loop.
In VB I could do item = Collection(index), but this fails in Matlab, since Matlab understands this as "item is Collection number index". In other words, Collection(2) tries to access the 2nd collection, not the 2nd item within Collection. This is why we typically use .Item(index) in Matlab, but as I said above, this fails in my particular collection where Item only accepts strings.
So my question is: can I iterate over a COM collection without a foreach construct or an Item(index) method?
I can tell you how to do it in COM, but I have no knowledge if Matlab can do this.
There is a special property DISPID_NEWENUM, with the name _NewEnum. Retrieving this property gets a IUnknown interface. You can get an interface to an IEnumVARIANT via QueryInterface.
So simply ask for this interface. Then call the Next method and retrieve VARIANT by VARIANT from your enumeration until the return value is no longer S_OK. Usually S_FALSE is returned when the end of the collection is reached. I always use a count of 1 when I call Next.
So if MatLab can use other interfaces than IDispatch, it should be possible.

Is it possible to use a userform property to remove a item in a dictionnary?

So I am trying to remove an item in a dictionary with a dictionary key via a property in a userform. So far, I have succeed to add a new item in dictionary, count item in the dictionary and get an item with userform property. So all of this is functional but I can't get the remove (key) functional.
Here is the property in my userform. (maybe I should use a get property?):
Public Property Let Materialremove(ByVal PartNumber As String)
DicMaterial.Remove (PartNumber)
End Property
Here is how I call for my property:
If UBidStatus.Materialexists(PartNumber) Then
UBidStatus.Materialremove (PartNumber)
End If
I get a Compile error:
Invalid use of property in VBA
I agree with Doug Glancy, I think you should turn it into a function. I don't think your approach is a good one. The reason you are having problems is because you are trying to treat a property like a function. You can make the code work this way: UBidStatus.Materialremove = PartNumber but I strongly advise against that for the sake of the next developer who has to look at the code after you and figure out what it's saying because what you are trying to do makes no logical sense. You should turn the property into a function. You need the assignment operator to make the line work because that is the purpose of a Let property statement: to assign a value to a property. But since you are trying to force a property to act like a function, it doesn't make any sense when someone tries to read the code.

Variable's value doesn't change in coffeescript when using onclick

I have the following Coffeescript code:
for name, data of statistics
row = document.createElement 'tr'
row.onclick = ->
alert name
However, when I compile and run it (in the context of a large webpage), it alerts the same name, no matter what row I click on. It seems to be remembering the variable, as if it's constant.
What am I doing wrong?
EDIT:
I've discovered the issue, but I'm not sure how to go about fixing it: Javascript/Coffeescript does not evaluate the 'name' variable until the end of the loop is reached.
The functions that you are defining (and assigning to the row's onclick attribute) all have access to the same variable outside that function (name). At the end of the loop, name has one value (the last item in the loop, as you mention), so each of the onclick functions alerts that value.
You can fix this by binding 'name' to a value that doesn't change. This question presents one solution. This question has some useful background that's worth reading.