What i want to do is fairly simple.
I have a form in LibreOffice Base with a text box to enter some data and a button to execute a macro.
Now i want to get with the macro on the clicking button the entered value of the text box and print it with the Print("...") function.
This what i got so far. Not much, but maybe a start:
Sub TestMacro
dim oForm as object
dim oTextbox as object
dim content as object
oForm = thisComponent.drawpage.forms.getByName("form_a")
oTextbox = oForm.getByName("testbox")
content = oTextbox.getText()
Print(content)
End Sub
Any kind of help is appreciated!
I found the answer on my own. The key was to let the subroutine have a parameter as the macro is used on the execution on the button. Over the event you can get the Parent which is the form, from that on you can get the text box and the Current Value of it. Works just fine for me.
Here is the code
Sub TestMacro(oEvent as object)
DIM oForm AS OBJECT
DIM oField as object
DIM oTField as object
'gets the button
oTField = oEvent.Source.Model
'gets the parent of the button which is the form
oForm = oTField.Parent
'gets the text field based on its name
oField = oForm.getByName("testbox")
'prints the value of the textfield
Print(oField.getCurrentValue)
End Sub
Using Access2Base API will make it easy.
I have a project in VB6.
I have aprox 800 forms.
Can I open/load a form from a list or array.
For example something like this.
Dim I As Integer
Dim Name As String
Dim Forms() As String
Name = "Form1|Form2|Form3|Form4|Form5 ...."
Forms = Split(Name, "|")
For I = 0 To UBound(Forms)
Form(Forms(I)).Load
Next I
Be aware of that, there no loaded forms previously.
The following code will accomplish what you need.
Dim f As Form
Set f = Forms.Add("Form2")
f.Show vbModal, Me
In this example, a non-loaded form is dynamically added to the Forms collection and then shown to the user.
VB6 new form + 1 button
Option Explicit
Public I As Integer
Public Sub Command1_Click()
CreateForm
End Sub
Public Sub CreateForm()
Dim Form As Form
I = I + 1
Set Form = New Form1
Form.Caption = I
Form.Show
End Sub
If you click button in first form. they will create duplicate form with caption increase every time button click.
I have a sub which instantiates a new form, makes it visible. However the new form lasts only for a very brief moment. This is my code:
Private Sub txtProject_ID Click()
Dim frmReq as Form
Set frmReq = New Form_Request
frmReq.Visible = True
End Sub
I tried to set break points on this and found out the form becomes visible when I set its visibility to true. However it disappears as soon as the Sub ends.
Edit:
How to create multiple instances of the pop up form?
In Access VBA you use
DoCmd.OpenForm "Request"
If you need to open it invisible you do
DoCmd.OpenForm "Request", WindowMode:=acHidden
' Initialize stuff while invisible
Forms!Request!foo = "bar"
' show form
Forms!Request.Visible = True
To open multiple instances (would have helped to mention that in the question) and pass a parameter, create a public initialization function in the form:
Public Sub InitForm(ReqId As Long)
' e.g.
Me.Filter = "Request_ID = " & ReqId
Me.FilterOn = True
'show me
Me.Visible = True
End Sub
and call it like this (see bottom of https://msdn.microsoft.com/en-us/library/office/ff845819.aspx)
Option Compare Database
Option Explicit
' This variable must be on *module* level!
Dim frmReq as Form
Private Sub txtProject_ID Click()
Set frmReq = New Form_Request
Call frmReq.InitForm(Me!txtProject_ID)
End Sub
The variable/object of scope is limited to sub procedure so it needs to be form level.
I have text boxes on several forms in my application that have a "zoom" capability -- double-click on them and a pop-up form appears which you can resize and edit to your hearts content. This is coded via a class module "appZoomText" which acts as an 'event sink' for the text box events.
I'm trying to create a content menu and ribbon item which replicates the double click behaviour (for those of my users who don't read documentation but might wonder what a zoom icon does if they see it.)
On entry to a zoomable text box, this code is executed:
dim mclsZoomtext as appZoomtext
set mclsZoomtext = new appZoomtext
Set mclsZoomText.pTextBox = ActiveControl
In the class module, the following code is executed in Set pTextBox
Private WithEvents myTextBox As Access.TextBox
Set myTextBox = pTextBox
myTextBox.OnDblClick = "[Event Procedure]"
The double-click code for myTextBox is:
Private Sub myTextBox_DblClick(intCancel As Integer)
OpenZoomForm 'Opens the relevant form with the right contents -- works fine
End Sub
The relevant menu item is enabled in Set ptextBox and disabled when pTextBox is exited (this is working fine).
The code invoked when the context menu item is clicked is:
Public Function OnActionZoom() As Boolean
Dim ctl As Control
Set ctl = GetCurrentControl
'GetCurrentControl returns the current Control object on a form or subform and works fine
CallByName ctl.Parent, ctl.Name & "_DblClick", VbMethod
OnActionZoom = True
End Function
I get an error 2465 ("can't find the field referred to") on the CallByName line. I'm assuming that this is because the DblClick code is in the event sink not the form. ctl.parent and ctl.name are set correctly.
How can I code this to invoke the event sink code?
Update: I've tried creating an empty (Public) Field_DblClick sub in the form; doesn't help - this empty sub runs but the event in the class module doesn't fire. Neither does making myTextBox_DblClick Public instead of Private.
In this instance I could just invoke OpenZoomForm directly, or maybe I could have a single public instance of appZoomText that gets associated with different textboxes as required (I haven't tried this).
However, I need to use a similar method to create a menu item to drill-down in a number of comboboxes and textboxes -- double-clicking in the combo-box/textbox opens an edit form for the item in the ox -- but the edit form isn't always the same, and I can't have a single public instance of each event sink.
Similar code:
Combobox_Enter or TextBox_Enter:
dim mclsClass as ClassX
set mclsClass as new ClassX
set mclsClass.ComboBox = ActiveControl 'Or set mclsClass.textbox = activecontrol
in ClassX:
Private Withevents myComboBox as ComboBox
Public Property Set ComboBox (pctlComboBox as ComboBox)
set myComboBox = pctlComboBox
myComboBox.OnDblClick = "[Event Procedure]"
End Property
Private WithEvents myTextBox as TextBox
Public Property Set TextBox(pctltextBox as TextBox)
set myTextBox= pctltextBox
myTextBox.OnDblClick = "[Event Procedure]"
End Property
Public Sub myComboBox_DblClick(intCancel As Integer)
If Not IsNull(KeyID(myComboBox.Text)) Then 'Check that there is a record to edit
EditFormX(myComboBox) 'EditFormX depends on the Class
'Some more code in here depending on the user's edit
myComboBox.Requery
End If
End Sub
Public Sub mytextBox_DblClick(intCancel As Integer)
If Not IsNull(KeyID(myTextBox.Text)) Then 'Check that there is a record to edit
EditFormX(myTextBox) 'EditFormX depends on the Class
'Some more code in here depending on the user's edit
myTextBox.Requery
End If
End Sub
For CallByName to work, you need to ensure the following:
1) The method being called is public not private.
2) All required parameters are passed.
As such, you need to make the event handlers public (as you are now doing), and pass an additional argument to CallByName for the DblClick handers' Cancel parameter. Since you aren't doing anything with that parameter inside the methods themselves, passing just 0 will do:
CallByName Ctl.Parent, Ctl.Name + "_DblClick", 0
Update 1 - example of this working [note this proves too simple in the OP's case - see Update 2 below]
a) Create a new Access project.
b) Add a new blank form to the project, and a TextBox to the form.
c) Double click the text box's On DblClick event in the Properties window, choosing the Code Builder option if prompted.
d) Add the following code for the handler:
Private Sub Text1_DblClick(Cancel As Integer)
MsgBox "Hello World!"
End Sub
e) Amend the method's header so that it reads Public Sub not Private Sub
f) View (open) the form, and focus the text box by clicking inside it.
g) Go back into the VBA editor, and add a new standard module.
h) Add the following sub-routine to the module:
Sub Test()
Dim Ctl As Access.Control
Set Ctl = Screen.ActiveControl
CallByName Ctl.Parent, Ctl.Name + "_DblClick", VbMethod, 0
End Sub
i) With the caret inside the Test routine, press F5 or click the Run button
On this, the 'Hello World' message appears for me.
Update 2
With the use of WithEvents now explicit, a demo of something that may work in your situation:
1) In Access, create a new database and add a blank form to it.
2) Add a text box and a combo box to the form, and call then txtTest and cboTest; next, add three command buttons, calling them cmdCreateControllers, cmdDestroyControllers and cmdExecuteController respectively, and setting their captions to 'Create controllers', 'Destroy controllers' and 'Execute controller'. Also set cmdDestroyControllers and cmdExecuteController's Enabled properties to False.
3) In the VBA editor, add a class module, rename it IController, and add the following code:
Option Explicit
Sub Execute()
End Sub
This is our interface type (i.e., abstract class definition).
4) Via Tools|References..., add a reference to 'Microsoft Scripting Runtime', of whose Dictionary class we will shortly be using.
5) Add a standard module, and the following code to it:
Option Explicit
Private mControllers As New Scripting.Dictionary
Sub RegisterController(Obj As Object, Controller As IController)
mControllers.Add Obj, Controller
End Sub
Sub UnregisterController(Obj As Object)
mControllers.Remove Obj
End Sub
Function GetController(Obj As Object) As IController
Set GetController = mControllers(Obj)
End Function
Function IController_Initialize(Controller As IController, _
OldObj As Object, NewObj As Object) As Object
If Not (NewObj Is OldObj) Then
If Not (OldObj Is Nothing) Then UnregisterController OldObj
If Not (NewObj Is Nothing) Then RegisterController NewObj, Controller
End If
Set IController_Initialize = NewObj
End Function
The last function here is a helper one for IController implementations. Let's now create a couple -
6) Add another class module, rename it MyTextBoxController, and add the following code:
Option Explicit
Implements IController
Private WithEvents mTextBox As Access.TextBox
Property Set TextBox(NewValue As Access.TextBox)
Set mTextBox = IController_Initialize(Me, mTextBox, NewValue)
If Not (mTextBox Is Nothing) Then mTextBox.OnDblClick = "[Event Procedure]"
End Property
Private Sub mTextBox_DblClick(Cancel As Integer)
IController_Execute
End Sub
Private Sub IController_Execute()
MsgBox "Hello from the example text box controller!"
End Sub
7) Add another class module, rename it MyComboBoxController, and add the following code:
Option Explicit
Implements IController
Private WithEvents mComboBox As Access.ComboBox
Property Set ComboBox(NewValue As Access.ComboBox)
Set mComboBox = IController_Initialize(Me, mComboBox, NewValue)
If Not (mComboBox Is Nothing) Then mComboBox.OnDblClick = "[Event Procedure]"
End Property
Private Sub mComboBox_DblClick(Cancel As Integer)
IController_Execute
End Sub
Private Sub IController_Execute()
MsgBox "Hello from the example combo box controller!"
End Sub
8) Go back the form and handle cmdCreateControllers' Click event as thus:
Option Explicit
Private mTextBoxController As MyTextBoxController, mComboBoxController As MyComboBoxController
Private Sub cmdCreateControllers_Click()
If mTextBoxController Is Nothing Then Set mTextBoxController = New MyTextBoxController
Set mTextBoxController.TextBox = txtTest
If mComboBoxController Is Nothing Then Set mComboBoxController = New MyComboBoxController
Set mComboBoxController.ComboBox = cboTest
cmdDestroyControllers.Enabled = True
cmdExecuteController.Enabled = True
End Sub
9) Handle the other two buttons' Click events like this:
Private Sub cmdDestroyControllers_Click()
cmdCreateControllers.SetFocus
cmdDestroyControllers.Enabled = False
cmdExecuteController.Enabled = False
Set mTextBoxController.TextBox = Nothing
Set mComboBoxController.ComboBox = Nothing
End Sub
Private Sub cmdExecuteController_Click()
Dim Name As String
Name = InputBox("Enter the name of the control whose controller you want to execute:")
If Name = "" Then Exit Sub
GetController(Me.Controls(Name)).Execute ' add error handling as desired!
End Sub
10) Open the form, and double click either the text box or the combo box - nothing should happen.
11) Click Create Controllers, and double click again: a message box should show.
12) Click Execute Controller, and enter txtTest: a message box should again show.
13) Unhook the custom event sinks and unregister them as object controllers by clicking Destroy Controller; having done that, double clicking either of the subject controls should once more do nothing.
I've found the following works for the "zoomable" boxes, where the name of the relevant class and the textbox control within it are always the same.
Within the form:
Public mclsZoomText As appZoomText
and on entry to the control:
set mclsZoomtext = new appZoomtext
Set mclsZoomText.pTextBox = ActiveControl
Within the class:
Public WithEvents myTextBox As Access.TextBox
Public Sub myTextBox_DblClick(intCancel As Integer)
OpenZoomForm
End Sub
and when the zoom option is invoked from the menu:
Public Function OnActionZoom() As Boolean
Dim ctl As Control
dim intX as Integer
Set ctl = GetCurrentControl
'GetCurrentControl returns the current Control object on a form or subform
Call ctl.Parent.mclsZoomText.myTextBox_DblClick(intX)
OnActionZoom = True
End Function
For the more complex case this answer is excellent.
I'm trying to create a class that manages the events of a combo box in Access 2010. Here you have the code:
Class TestEvents
Public WithEvents cbMyCombo As Access.ComboBox
Public Property Get AssociatedCombo() As Access.ComboBox
Set AssociatedCombo = cbMyCombo
End Property
Public Sub cbMyCombo_Change()
MsgBox "Combo has changed!"
End Sub
Private Sub Class_Initialize()
Set cbMyCombo = Form_Form1.Combo1
End Sub
Form1 Code (Contains a combobox named Combo1)
Option Compare Database
Option Explicit
Private MyTestEvents As TestEvents
Private Sub Form_Load()
Set MyTestEvents = New TestEvents
MsgBox MyTestEvents.AssociatedCombo.Name
End Sub
When running the code, I get (as expected) a message with the combobox name (Combo1), so the TestEvents.AssociatedCombo property is pointing to the right object but nothing happens when I change the combo value. I would expect to get the message "Combo has changed".
Is there anything I'm doing wrong?
Thanks in advance for your help :)
By default events sunk for a form control are not raised in VBA at all; to enable them (and subsequently enable your WithEvents) you need to wire up each event you want to handle;
Set cbMyCombo = Form_Form1.Combo1 '//please put this in a property!
cbMyCombo.OnKeyDown = "[Event Procedure]"
cbMyCombo.OnBlaDeBla = "[Event Procedure]"
(Note that's the actual string value you need to set, not a placeholder/example)
You can also do this on the Events tab of the control properties.