How to make a function/sub available to all forms in a project? - vb.net

I have a sub that I want to be available to (or "callable from") all forms:
' Call some Sub from another form.
someSub()
I'm having difficulty finding examples online thus my suspicion that the crux of my issue may be terminological.
How?
Can anyone guide me as to what I should be looking at?:
Global Sub
Static Sub
Shared Sub
Private Sub
Where?
Where should I position my "universal" sub?:
Arbitrarily place it in one of the forms.
Create a code file and somehow integrate into it each form?

declare it as public Sub inside a Module
Public Module GlobalFunctions
Public Sub YourSub()
End Sub
End Module
hope this will help you

Make it public.
Public Sub MySub()
Then you can call it from every form.
Myform.MySub()

Related

VBA to Open MS Access Form Full Screen

I have problem with VBA Access database I want to open form full screen.
Let me know which property and code I use to do fix the issue.
I tried many script and codes.
Private Sub Form_Load()
Application.Forms = Xlmaximized
End Sub
For a form to maximize it is:
Private Sub Form_Load()
DoCmd.Maximize
End Sub
The application you should never force to be maximize. That would be to violate the user's control over the machine.
If for some reason you would like to violiate the user's control over the machine and maximize the application, you could do this too:
Private Sub Form_Load()
DoCmd.Maximize
Application.RunCommand acCmdAppMaximize
End Sub

Accessing Form controls from a module

I am trying to create a sub in a module that simply hides a lot of panels for a Form which is passed as a parameter to it. Basically, Ill have a button called students and a button called subjects and I want that when I click on the, lets says, students button ALL the panels I define in the function get hidden, and only the students panel remains visible.
When I run this code I get :
System.MissingMemberException: 'Public member 'pnlAlumnos' on type 'Ventana_Principal' not found.'
Code in my module
Module Modulo_Comportamiento_Ventanas
Public Sub Esconder_todos_los_paneles(ventana As Object)
ventana.pnlAlumnos.Hide()
ventana.pnlMaterias.Hide()
End Sub
End Module
Code on the main Form click
Private Sub btnAlumnos_Click(sender As Object, e As EventArgs) Handles btnAlumnos.Click
Esconder_todos_los_paneles(Me)
Me.pnlAlumnos.Show()
End Sub
How can I modify my code in order to being able access the panels and hiding them?
Thanks in advance!
Note : BTW, I know I can do this, but I want to know why it does not work the way I am doing it, I mean the below code looks horrible ( not that my other path looks any more nicer) :
Public Sub Esconder_todos_los_paneles()
WindowsApp1.Ventana_Principal.pnlAlumnos.Hide()
WindowsApp1.Ventana_Principal.pnlMaterias.Hide()
End Sub

Two events in one Sub

Private Sub btnBestellen_Enter()
Call bestelling()
End Sub
Private Sub btnBestellen_Click()
Call bestelling()
End Sub
I have two seperate subs here with the same code in it. Is there any possible way to make it into one sub? For example like this, of course this doesn't work.
Thank you in advance
Private Sub btnBestellen_Click,btnBestellen_Enter()
Call bestelling()
End Sub
Unfortunately not. VBA has no syntax for grouping Event Subs as you described.
The only work around would be to create a listener function that checks for your events manually. It would be down to you to catch them and handle them correctly. Although I'm guessing that would be out of scope here :)

Intellisense in private modules

Assume I have a module named Module1 with the following code:
Private Sub MyPrivateSub()
'do something
End Sub
Public Sub MyPublicSub()
'do something
End Sub
Public Sub test()
End Sub
If I place the cursor inside Test() and start typing "MyPrivateSub" or "MyPublicSub", I don't get any intellisense. I can type "Module1." (or "Me." if Module1 were a class module) to get an intellisense menu, but this only contains the public method MyPublicSub, as shown here:
Is there some way to get an intellisense menu for all members, public and private? I'm working on a project with modules that have many methods, and going up and down continually to copy/paste member names is time consuming.
Short answer
hit a combination of
CTRL+SPACE
and start typing the sub name like shown here
Long answer
Everything you do in programming matters. When you decide to make your sub/function/variable private you do that for a reason and you need to understand how this will affect the access level and "scope".
The scope of a member is dictated by its access level and in VBE anything that is private and qualified with it's parent member does not get intelli-sense. Simply, because you can't (are not supposed to be able to access it) from the outside.
Because your MyPrivateSub access level is Private you can't access it with intelli-sense through qualifying the module with Module1..
If you're starting from fresh, you can do the following:
for all your private sub function, name them into a standard format but as public function at the moment, for e.g.:
Public sub iamprivate_calDate ()
Public sub iamprivate_getsetfunction()
...
after you're completed with your macros, simply find and replace all your "Public sub iamprivate" into "Private sub " in your editor.

Executing function on hundreds of databases

I want to embed a simple piece of VBA Code in Access 2007. I need to execute this code on hundreds of different Access DBs, so I don't want to manually paste the code into each and every DB. Is it possible to do this? Maybe by way of an add-in?
Thanks
Karl
EDIT
I want to execute the following VBA code:
DoCmd.DeleteObject acTable, "LastNum"
DoCmd.TransferDatabase acLink, "ODBC Database", "ODBC;DSN=myDB;UID=User1;PWD=123;LANGUAGE=u s_english;" & "DATABASE=LastNumber", acTable, "LastNum", "LastNum"
How would I translate this into a VB addin?
The visual studio VB add-in template looks like this:
imports Extensibility
imports System.Runtime.InteropServices
<GuidAttribute("B61E2444-F46E-4591-A8BA-3D06A4E5D84C"), ProgIdAttribute("MyAddin1.Connect")> _
Public Class Connect
Implements Extensibility.IDTExtensibility2
Private applicationObject As Object
Private addInInstance As Object
Public Sub OnBeginShutdown(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnBeginShutdown
End Sub
Public Sub OnAddInsUpdate(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnAddInsUpdate
End Sub
Public Sub OnStartupComplete(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnStartupComplete
End Sub
Public Sub OnDisconnection(ByVal RemoveMode As Extensibility.ext_DisconnectMode, ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnDisconnection
End Sub
Public Sub OnConnection(ByVal application As Object, ByVal connectMode As Extensibility.ext_ConnectMode, ByVal addInInst As Object, ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnConnection
applicationObject = application
addInInstance = addInInst
End Sub
End Class
EDIT PART 2:
Ok, so I figured out I should do the following:
imports Extensibility
Imports System.Runtime.InteropServices
Imports Microsoft.Office.Core
Imports Access = Microsoft.Office.Interop.Access
<GuidAttribute("B61E2444-F46E-4591-A8BA-3D06A4E5D84C"), ProgIdAttribute("MyAddin1.Connect")> _
Public Class Connect
Implements Extensibility.IDTExtensibility2
Private applicationObject As Access.Application
Private addInInstance As Microsoft.Office.Core.COMAddIn
Public Sub OnBeginShutdown(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnBeginShutdown
End Sub
Public Sub OnAddInsUpdate(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnAddInsUpdate
End Sub
Public Sub OnStartupComplete(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnStartupComplete
End Sub
Public Sub OnDisconnection(ByVal RemoveMode As Extensibility.ext_DisconnectMode, ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnDisconnection
End Sub
Public Sub OnConnection(ByVal application As Object, ByVal connectMode As Extensibility.ext_ConnectMode, ByVal addInInst As Object, ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnConnection
applicationObject = CType(application, Access.Application)
addInInstance = CType(addInInst, Microsoft.Office.Core.COMAddIn)
' This line enables VBA to call back into this object.
addInInstance.Object = Me
End Sub
Public Sub ChangeLink()
applicationObject.DoCmd.DeleteObject(Access.AcObjectType.acTable, "LastPolNum")
applicationObject.DoCmd.TransferDatabase(Access.AcDataTransferType.acLink, "ODBC Database", "ODBC;DSN=ZACANTDB02;UID=EDIPolicyNumber;PWD=museum123;LANGUAGE=u s_english;" & "DATABASE=EDIPolicyNumber", Access.AcObjectType.acTable, "LastPolnum", "LastPolNum")
End Sub
End Class
Now what I want is to be able to execute ChangeLink() from Access. How do I do that?
Depending on what the code is for, there are (at least) two different ways to do this, without working at the VB Extensions level (which is where you'd copy and paste code, at least in VBA):
Make the code part of an add-in. It can then be loaded, and stay loaded and exposed, to any other application.
If the code is working on data only, consider writing a procedure that links and unlinks the table(s) in each mdb file that needs processing.
The advantage of #2 over #1 (and, indeed, over copying and pasting code) is that you can invoke your simple routine once, not hundreds of times.
EDIT:
There are two ways to invoke an add-in, depending on who is meant to invoke its functionality, and how.
Through the UI. Use this when you want an end user to be able to use it, especially practical for functionality you'll invoke often. How to:
a. Office button > Access options > Add-ins tab
b. If it's a .NET add-in (or any other non-Access add-in), choose COM Add-in from Manage dropdown. If it's Access, choose Access. Click go
c. Click Add button in the form that pops up, browse to the add-in.
You will still need to provide some sort of UI to it: a commandbar, a ribbon button, a form, something. That's a separate discussion
Through code. Use this if you're just wanting to invoke it as part of some other VBA procedure.
a. VBE window > Tools > References
b. Browse button
c. Change the dropdown in file of type if you're setting up an Access add-in.
You can then call the line of code directly, as if it were part of your current project. If you wish to be more explicit, you can also invoke it by library name: MyAddInName.ChangeLink
Seems to me that you don't need to run this code from the Access databases -- all you need to do is run it on all the databases.
To do that, you'd use DAO to open each database in turn, delete the table, then create the link. You'll have to do both of those steps with DAO (deleting from the TableDefs collection, and adding to it) rather than with DoCmd operations (which are unavailable through DAO).
Of course, if the databases are no accessible from a central location, you can't do this. But if that's the case, how would you alter the code or invoke an add-in?
Another way to use a library database is to use Application.Run:
Application.Run "\Server\PathToAddIn\MyLibrary.FixTables"
This assumes:
MyLibrary is an MDE/ACCDE.
in MyLibrary database is a subroutine or function called FixTables that runs the code you want to execute.
Indeed, with that method, you can actually use DoCmd, since the add-in is running within Access and in the context of the currently opened database.
However, note that some people seem to have difficulties executing add-ins in this fashion (I'm currently in a long discussion with somebody in another forum who can't seem to get it to work). I've been using this method for library databases for years and years and have had no problems (as long as you specify a full path), so I'm puzzled why the ones I'm discussing it with can't seem to make it work.