I have a tab control object on my form. I want a function from within my form's vba module to be called when the tab control's on change event occurs.
I have a form with a module enabled.
I have a public function in the form module named "foo()"
I have a macro "bar" that is:
Runcode: "foo()"
I get an error that Access cannot find "foo()" despite being public. If I move "foo()" to a regular module then the macro can find it. Is there a way to use a macro to call functions from a form module since it's convenient because of the "me" keyword.
https://learn.microsoft.com/en-us/office/client-developer/access/desktop-database-reference/runcode-macro-action
"However, when this action runs in response to clicking a menu command on a form or report or in response to an event on a form or report, Access first looks for the function in the form's or report's class module and then in the standard modules."
It appears the solution is to navigate to the event box, click the "..." box, and then click "code builder."
This will create a private sub in your form module which you can then use to call your function.
Private Sub [tab control name]_Change()
Call foo()
End Sub
Related
My problem pertains to a COM add-in for Microsoft Excel. The use case is as follows: 1. User clicks the add-in's button on the ribbon. 2. A form window appears. 3. User interacts with the form window and clicks an OK button. 4. Various reports are generated, while a progress bar on the form window shows progress. 5. At the end of the process, the form window closes.
The process works as designed on the first run, but after the form window has been closed there is no way to start a new "session." From the user's perspective the add-in button becomes non-responsive. When run in debug mode from Visual Studio, clicking the add-in button a second time generates an error message: "Cannot access a disposed object."
Clearly something is wrong with the way I have hooked everything up, but I haven't been able to find a simple description of how to do it correctly. Here is what I have:
In a public class a number of public (or "global" variables) are declared; the form is also declared and instantiated here:
Public Class GlobalVariables
Public Shared FormInstance As New MyFormDesign
End Class
The reason for declaring the form as a public object is to be able to be able to send progress values from various different subs and functions. The GlobalVariables class is imported by all modules that require it.
Behind the ribbon button is a single line of code:
FormInstance.Show()
Clicking the button instantiates and shows the form as intended. To keep things simple we can ignore the bulk of the code; simply clicking the "Cancel" button will trigger the problem. The code behind the "Cancel" button is straightforward:
Me.Close()
GC.Collect()
After closing the form it is no longer possible to create a new instance, per the error message cited above.
I don't really understand what is going on here, but it looks to me like the GlobalVariables class, once created, persists until the end of the Excel session. If that is correct the problem could presumably be cured by instantiating the form in a standard module. Instead of attempting to revive a form that has been disposed, the add-in would just create a new instance each time the user clicks the button. But if I go that route I can't figure out how to send progress values from other subs back to the form. It seems like a Catch-22.
There has got to be a way to both (a) create the form as a public object, and (b) create and destroy a new instance each time the add-in is run. Right? What am I doing wrong?
It has been a long journey, but I finally found out how to build the functionality described in my question. I will post the answer here, as it may help others in the future.
The challenge was to declare a form as Public in order to make it accessible throughout the project, so that subs and functions can send progress updates back to the form.
The problem was that the form, when declared and instantiated as described in my question, can only be created once per Excel session.
The solution is to declare the form as Public without instantiating it, then access it via a Public ReadOnly Property.
First, declare FormInstance as a public variable without instantiating it:
Public FormInstance As MyFormDesign
Second, define a Public ReadOnly Property. This establishes a way to call the form:
Public ReadOnly Property CallMyForm() As MyFormDesign
Get
Return FormInstance
End Get
End Property
Third, the ribbon button's Click event instantiates and shows the form:
Private Sub Button1_Click(sender As Object, e As RibbonControlEventArgs) Handles Button1.Click
FormInstance = New MyFormDesign
FormInstance.Show()
End Sub
Now a new form instance will be created each time the ribbon button is clicked, but the form can still be accessed via the CallMyForm property.
Instead of ...
FormInstance.BackgroundWorker1.ReportProgress(i)
... we will use:
CallMyForm.BackgroundWorker1.ReportProgress(i)
This solves the conundrum laid out in the question.
I have a user control that I created with certain buttons, and I placed it within the main form, which already contains things like buttons and panels. I want to control(send messages) to these fields when I press the buttons in the user control, but I can't figure out the OOP implementation required to achieve this.
I was advised to create an Initialize(f as Mainform) in the user control code in order to keep an explicit reference to the main form, but I have not been able to control the fields of the main form.
How can this be achieved? I am using visual basic, btw.
Declare an event in the user control, and then write a handler for that event in the form.
In the control:
Event Zoomed()
In the control, to raise the event (call the handler):
RaiseEvent Zoomed()
and add the handler to the form:
Sub aview_zoomed() Handles aView.Zoomed
...
End Sub
Is there a way to disable the message (and have the document editable by default):
Server Document To modify document, click Edit Document followed by the button with text "Edit Document".
I cannot find a word setting to do this. In addition I cannot see a way to make a VB macro to do this with a key stroke. I have used a small autohotkey script to position the mouse and click this prompt, but this does not always work since it depends on the position of the window. it is impossible to use the tab key to get to this prompt.
I have to modify about 50+ documents a day from sharepoint, ideally I would like to combine this with another macro which does other automated processing for me. But I can't find a VB solution for clicking the Edit button.
Depending on your security settings (you mentioned that they were blocked), this may or may not work.
Create a new macro enabled template in your Word startup folder (usually at C:\Users[YourID]\AppData\Roaming\Microsoft\Word\STARTUP), and add a new class module. I called mine "AutoEditEnable". You can name it anything, but you'll need it to match how you declare it in the other module.
This code goes in the class:
Option Explicit
Private WithEvents app As Application
Private Sub Class_Initialize()
Set app = Application
End Sub
Private Sub app_ProtectedViewWindowOpen(ByVal PvWindow As ProtectedViewWindow)
PvWindow.Edit
End Sub
Basically, this will hook any Application events you need to - in this case the ProtectedViewWindowOpen event or the ProtectedViewWindowActivate event (either should work).
Put the following code in ThisDocument to grab a reference to it when your template loads:
Option Explicit
Private hook As AutoEditEnable
Private Sub Document_Open()
Set hook = New AutoEditEnable
End Sub
Close Word and restart it, then make sure your new template shows up as a loaded add-in.
I have a VB.NET program that adds code to the ThisDocument module in MS Word in the following way:
wrdDoc.VBProject.VBComponents("ThisDocument").CodeModule.AddFromString(sCode)
Which creates the following sub:
Public Sub Example_Click()
Msgbox "Working"
End Sub
I used to call this via the click event of a command button however it would be desirable call it from a ribbon button created as part of a COM Add-In.
I have been able to call global macros successfully in the Add-In by adding the following code to the button's click sub,.
Globals.TestWordApp.Application.Run("Macro1")
All attempts to run code contained within ThisDocument have failed however.
Any help would be greatly appreciated.
Application.Run runs macros.
Macros exist in modules, and ThisDocument is a class module.
Try creating a new module or use an existing module instead of ThisDocument.
Can I reach/access a form control object from a module in VB.NET ? I have a webbrowser in the Form , so my question is can i access it from a module (changing settings for example). I have no idea how to do this .
The control has to come in as a parameter. Since the Module behaves as a static (shared) class, it has no state or access to instance members natively.
Module MyModule
Public Shared Sub MyMethod(ByVal myControl as WebUserControl)
' do your mojo
End Sub
End Module
If you just want to have global access from the page level you can send the Page in, but you'll need to perform a recursive search for various controls and you won't have access to the rendered output, so databound controls such as GridViews or FormViews will not work the same way and will be subject to the event lifecycle.
Public Shared Sub MyMethod(ByVal myPage as Page)
End Sub