List of methods of a class in intellisense - 2 (1 Viewer)

KitaYama

Well-known member
Local time
Today, 23:27
Joined
Jan 6, 2022
Messages
1,541
I don't understand why you need to see a list of the form's methods.
A lot of reasons. For example preventing typo OR less keyboard strokes because you can select from a list.
And it's not only methods. If intellisense doesn't give you a list of methods, it also doesn't show the list of controls too. Wouldn't it be nice if you put a dot and select the name of a textbox or another control from a list instead of typing a long name?

The whole point of using this technique is because what you are doing doesn't change whether the data is in formA or formB. The code is in your module. It is just the data that is in formA and formB that you are referencing. Not any of the form's methods.
If I understand you correctly, I wonder why someone with several decades of experience in programming tells me this. There are a lot of cases that you pass a form to a function, and need to change some public methods declared in form's class module in the function. Is it rare for you? Isn't that why you can have a method (let/get) being declared public and not private? To be able to use them outside of form's module?
 
Last edited:

Pat Hartman

Super Moderator
Staff member
Local time
Today, 10:27
Joined
Feb 19, 2002
Messages
43,275
@KitaYama Shared code doesn't belong in a form's class module. That is what I think you are talking about. If you need to do something that affects data from multiple forms, the best solution is to extract the code to a standard module and pass in a form reference. Then the shared code module gets "data" from whatever form is passed in but it is not trying to run code that lives in some other form. One place I use this is to check security. Every form needs to use this code so it is in a standard module and I call it from the necessary events - BeforeUpdate, BeforeInsert, Open, BeforeDeleteConfirm. I pass an argument. And the shared code tells me if the user is authorised to perform the function I am asking about. The current user is known to the application so the code I am calling knows how to find it and I use the same location for that in all apps (the login form is never closed. It is just hidden so it keeps some data throughout the use of the application) so the code transfers without modification.

Executing code in a stand alone class module is a totally different thing. However, they should still be "black boxes". Each procedure should do only one thing (ie. be highly cohesive) and the arguments passed should be minimal (ie loosely coupled). Even though Forms are class modules, you can only reference objects in them if they are loaded. You might be able to reference code procedures but I would just never do this. Perhaps this is why you are seeing differences. Are you sure the form you are referencing is loaded?

I still wouldn't do it. I would move the common code to a standard module or if you prefer to a class module. The class module will give you the intellisense you are looking for. Just pay attention to coupling and cohesion as you create shared code. Aim for highly cohesive and loosely coupled to avoid cascading problems when code changes are needed.

When I need to share code within a form's class module, I move it out of the event procedure (where I probably originally put it) and move it to a function and call it from the events that need it. I never call an event procedure from any other place in the form's class module. Events fire when they are triggered. No one looking at your code later, including yourself will anticipate multiple uses of that code. That easily leads to code that will break the second use. Why do you think we cringe every time a new version of Access is released? Code changes in one procedure break other uses of that code. When your code is in a stand-alone procedure, it is obvious to all that it is being executed from some other procedure and so you always look for those and make sure that your code is compatible with all changes. I would be especially leary of executing form class module code from outside of the form. No one who follows you is ever going to expect the code in some form's "Current event" to be called from some other form - this is what decades of experience tells me.
 

KitaYama

Well-known member
Local time
Today, 23:27
Joined
Jan 6, 2022
Messages
1,541
@KitaYama Shared code doesn't belong in a form's class module. That is what I think you are talking about. If you need to do something that affects data from multiple forms, the best solution is to extract the code to a standard module and pass in a form reference. Then the shared code module gets "data" from whatever form is passed in but it is not trying to run code that lives in some other form. One place I use this is to check security. Every form needs to use this code so it is in a standard module and I call it from the necessary events - BeforeUpdate, BeforeInsert, Open, BeforeDeleteConfirm. I pass an argument. And the shared code tells me if the user is authorised to perform the function I am asking about. The current user is known to the application so the code I am calling knows how to find it and I use the same location for that in all apps (the login form is never closed. It is just hidden so it keeps some data throughout the use of the application) so the code transfers without modification.

Executing code in a stand alone class module is a totally different thing. However, they should still be "black boxes". Each procedure should do only one thing (ie. be highly cohesive) and the arguments passed should be minimal (ie loosely coupled). Even though Forms are class modules, you can only reference objects in them if they are loaded. You might be able to reference code procedures but I would just never do this. Perhaps this is why you are seeing differences. Are you sure the form you are referencing is loaded?

I still wouldn't do it. I would move the common code to a standard module or if you prefer to a class module. The class module will give you the intellisense you are looking for. Just pay attention to coupling and cohesion as you create shared code. Aim for highly cohesive and loosely coupled to avoid cascading problems when code changes are needed.

When I need to share code within a form's class module, I move it out of the event procedure (where I probably originally put it) and move it to a function and call it from the events that need it. I never call an event procedure from any other place in the form's class module. Events fire when they are triggered. No one looking at your code later, including yourself will anticipate multiple uses of that code. That easily leads to code that will break the second use. Why do you think we cringe every time a new version of Access is released? Code changes in one procedure break other uses of that code. When your code is in a stand-alone procedure, it is obvious to all that it is being executed from some other procedure and so you always look for those and make sure that your code is compatible with all changes. I would be especially leary of executing form class module code from outside of the form. No one who follows you is ever going to expect the code in some form's "Current event" to be called from some other form - this is what decades of experience tells me.
@Pat Hartman First of All, let me thank you for your explanation, your time and your will to help.
But honestly, I think either you didn't read #1 post, or my poor English failed to show my problem.
Let me put it this way.
Forget about everything said and posted above. Just imagine this one is the first post.

There's an attachment here. It contains two forms and one module. Each form has a button(btn) and textbox(txt).
Open either of them. No matter which one.
Click the button.
The code stops at the following function:
Code:
Public Function ClickTest(frm As Access.Form)
    Stop
    With frm

        .txt.SetFocus
        .btn.Visible = False
    End With
End Function

In the empty line after With frm , type a dot. The intellisense shows form's properties. But you can not find txt (the name of the textbox) or btn (the name of the button) in intellisense. All I need is to find a way the intellisense shows the object names too.
Do you have a method that shows all properties of the form and the objects in that form in intellisense?

@AHeyne I'm sorry but I'm too short in my free time and too busy with my job. I'm still reading and studying Implements to understand your method in depth and find a way not to loose all other forms properties in intellisense. I'll get back to you if I have more questions. Thanks again.
 

Attachments

  • Database1.accdb
    480 KB · Views: 22

Edgar_

Active member
Local time
Today, 09:27
Joined
Jul 8, 2023
Messages
430
This is what the interface proposed by @AHeyne would do for you. Interfaces are a "contract" or "blueprint" that other objects must follow. Notice the function in the module expects an interface, through polymorphism, any object that implements the interface can be passed to that function, in this case, the forms are implementing it.
 

Attachments

  • kya.accdb
    1.1 MB · Views: 35

KitaYama

Well-known member
Local time
Today, 23:27
Joined
Jan 6, 2022
Messages
1,541
This is what the interface proposed by @AHeyne would do for you. Interfaces are a "contract" or "blueprint" that other objects must follow. Notice the function in the module expects an interface, through polymorphism, any object that implements the interface can be passed to that function, in this case, the forms are implementing it.
Yes, but it's not exactly what I was looking for. The intellisense lacks forms properties.

In following image, myMethod is a custom method, MyText is a textbox (object) on the form, the others are forms properties and events etc.
They are all shown together. It's a collection of all of them.

2024-03-12_12-01-30.jpg


The intellisense in your sample database lacks form's properties. You're sacrificing all benefits of intellisense just to show two of them.

2024-03-12_12-08-07.jpg


I wanted to have the same result as my first image above, WHEN I'm passing a form to a function. I really don't know how to explain it better.
But to my understanding up to now, it seems it's not possible.

Anyhow, since it's not a big deal, you can forget about it.
Thanks.
 
Last edited:

Edgar_

Active member
Local time
Today, 09:27
Joined
Jul 8, 2023
Messages
430
Check the function again, I put the form in a different variable for your usage.

You seem to be looking for inheritance, but vba does not do that.
 

Edgar_

Active member
Local time
Today, 09:27
Joined
Jul 8, 2023
Messages
430
Nothing groundbreaking, but check the attached to see that you still get intellisense for the composition of the form and the two extra controls, according to the interface. Not in the way you wanted it, though, inheritance is not possible with VBA.

Code:
Public Function ClickTest(CustomFormControls As IKitayamaControls)
    
    With CustomFormControls
        .TheTextbox.SetFocus
        .TheTextbox.Value = "Hi"
        .TheButton.Visible = False
        .TheForm.Section(0).BackColor = RGB(255, 200, 200)
    End With
    
End Function
 

Attachments

  • kya2.accdb
    432 KB · Views: 25
Last edited:

Edgar_

Active member
Local time
Today, 09:27
Joined
Jul 8, 2023
Messages
430
I edited the previous response and the attachment to show how you could have intellisense for the form and the custom controls.
 

MarkK

bit cruncher
Local time
Today, 07:27
Joined
Mar 17, 2004
Messages
8,181
It may also be important to note in this discussion that the VBA TypeOf operator can distinguish if an object implements an interface. Say you have an Access.Form called Form_Form1 and it implements IKitayamaControls and INavBarHost, then the following code...
Code:
    Dim frm As New Form_Form1
    
    Debug.Print TypeOf frm Is Form
    Debug.Print TypeOf frm Is Form_Form1
    Debug.Print TypeOf frm Is IKitayamaControls
    Debug.Print TypeOf frm Is INavBarHost
...will print True four times to the immediate pane.
 

AHeyne

Registered User.
Local time
Today, 16:27
Joined
Jan 27, 2006
Messages
92
@MarkK: Thanks for pointing this out. I had only included 'TypeOf' and 'Typename' in my example database and did not explicitly mention them in the thread. (y)
 

Pat Hartman

Super Moderator
Staff member
Local time
Today, 10:27
Joined
Feb 19, 2002
Messages
43,275
But honestly, I think either you didn't read #1 post,
I did read it. You want to know how to see intellisense for the form and its control objects in your function in the standard module. Access doesn't supply it. I don't know if this is by design or simply an oversight. I checked all my apps that use the technique and I don't get it either. I should have made that clear in my reply. I'm guessing it has to do with late vs early binding. You may have run into this if you work in an environment where office versions are not standardized so you have to use late binding rather than early binding. One downside of that is intellisense is not available when you are automating Word or Excel or other Office app. You also can't reference their enums. The problem of course is that because you don't get intellisense, you don't get compile time errors which is very inconvenient when you are developing. That, I think is the real problem of the missing intellisense.

On the occasions where I had to use late binding, I developed using early binding where I had intellisense. Then I made my own variables to hold the enums I needed. Then I changed the code to late binding.

It never bothered me because I could still reference the controls as long as i knew their names. I was not poking around trying to figure out what the procedures needed. Each was very focused (highly cohesive) and never referenced more than a couple of controls.

Your thread title indicated a concern with methods rather than properties. That is what prompted my long winded reply about why I wouldn't use the methods of another form. I only ever reference data being displayed by a form.
 

Users who are viewing this thread

Top Bottom