[Solved] Referencing form controls from macro's
-
- Posts: 6
- Joined: Fri Feb 25, 2011 4:38 am
[Solved] Referencing form controls from macro's
I keep going round the help and faq's in circles here. I'm exploring using OOo Base. I've called a macro from a form and want to read a text box from it, that's all. Help keeps pointing me to using dialogs, which doesn't seem to mention addressing forms.
I've done lots of programming over 25 years, in lots of languages, I'm finding this incredibly frustrating.
I've done lots of programming over 25 years, in lots of languages, I'm finding this incredibly frustrating.
Last edited by BrianSwatton on Sat Feb 26, 2011 12:44 am, edited 1 time in total.
OpenOffice 3.3.0 on Windows XP
Re: Referencing form controls from macro's
An essential tool for writing macros is an object inspection tool like mri. Then you can see the properties and methods of each object. Here is an example of a macro called by the After Record Change event of a form that gets the string showing in a text box.
Code: Select all
Sub ForumMacro(oEv)
oForm = oEv.Source
oTextBox = oForm.getByName("txtSAMPLE_GROUP")
TextBoxString = oTextBox.string
end Sub
OpenOffice 4.1 on Windows 10 and Linux Mint
If your question is answered, please go to your first post, select the Edit button, and add [Solved] to the beginning of the title.
If your question is answered, please go to your first post, select the Edit button, and add [Solved] to the beginning of the title.
Re: Referencing form controls from macro's
Does this help at all?
AOO 4.1.x; LO 4.2.x; Windows 7/8 64-bit
Warning: Avoid embedded databases --> Solution: Adopt a portable 'split database' folder
Soli Deo gloria
Warning: Avoid embedded databases --> Solution: Adopt a portable 'split database' folder
Soli Deo gloria
-
- Posts: 6
- Joined: Fri Feb 25, 2011 4:38 am
Re: Referencing form controls from macro's
Hi,
Thanks for answering both of you.
FJCC, I had found Event.Source by accident before, and found I could use that, but only to reference the textbox where the event happened, nothing else (the macro is called by the change event in a textbox).
So, if I use GetByName() with what is returned by Event.Source, as in your example, I get "property or method not found" error for GetByName. Presumably because it is being applied to a textbox and not a form.
DACM, Reading the link you posted, I was amazed I had not seen "Parent" before anywhere in the help, this looked like being the answer, but when I used lines like :
Sub CheckPN(oEv)
Frm=oEv.Parent
' or
Frm=oEv.Source.Parent
I get "no property or method found" for parent for either line.
I think part of my problem with gaining understanding is not yet finding a list of standard objects and the methods and properties they have, as well as heirarchies. I will see what else I can glean from the link you sent anyway.
I'm not sure how much more time I will spend on this, I'm quite busy. I was hoping I could get Basic to do some straightforward stuff with a simple parts database, but got stuck at the first fence. I've spent many, many hours trying to get some clue from the help in progam and online.
Thanks again
Thanks for answering both of you.
FJCC, I had found Event.Source by accident before, and found I could use that, but only to reference the textbox where the event happened, nothing else (the macro is called by the change event in a textbox).
So, if I use GetByName() with what is returned by Event.Source, as in your example, I get "property or method not found" error for GetByName. Presumably because it is being applied to a textbox and not a form.
DACM, Reading the link you posted, I was amazed I had not seen "Parent" before anywhere in the help, this looked like being the answer, but when I used lines like :
Sub CheckPN(oEv)
Frm=oEv.Parent
' or
Frm=oEv.Source.Parent
I get "no property or method found" for parent for either line.
I think part of my problem with gaining understanding is not yet finding a list of standard objects and the methods and properties they have, as well as heirarchies. I will see what else I can glean from the link you sent anyway.
I'm not sure how much more time I will spend on this, I'm quite busy. I was hoping I could get Basic to do some straightforward stuff with a simple parts database, but got stuck at the first fence. I've spent many, many hours trying to get some clue from the help in progam and online.
Thanks again
OpenOffice 3.3.0 on Windows XP
Re: Referencing form controls from macro's
This is where the MRI tool can help you a lot. If the macro is being called from a text box you may have to get to the form with code likeI think part of my problem with gaining understanding is not yet finding a list of standard objects and the methods and properties they have, as well as heirarchies.
Code: Select all
oForm = oEv.Source.Model.Parent
OpenOffice 4.1 on Windows 10 and Linux Mint
If your question is answered, please go to your first post, select the Edit button, and add [Solved] to the beginning of the title.
If your question is answered, please go to your first post, select the Edit button, and add [Solved] to the beginning of the title.
-
- Posts: 6
- Joined: Fri Feb 25, 2011 4:38 am
Re: Referencing form controls from macro's
Ok I've just got MRI, and am now looking at it. By the looks of it, it may take me a little while to work out what is going on.
I can't help thinking this seems to be getting incredibly complicated for such a straightforward task. I thought maybe I was approaching it from the wrong angle.
I will persist though, and will mark this thread solved when it is.
Thanks
I can't help thinking this seems to be getting incredibly complicated for such a straightforward task. I thought maybe I was approaching it from the wrong angle.
I will persist though, and will mark this thread solved when it is.
Thanks
OpenOffice 3.3.0 on Windows XP
Re: Referencing form controls from macro's
Hi Brian,
You can use oEvent.Source to access the Control but you need to be aware that oEvent can point to different objects depending on what event it is and sometimes even code attached to the same event can have oEvent point to different oblects when the event is triggered from different controllers. MRI is very useful here.
You can usually use
to get the form object, unless you want to refer to a different form.
Or you can use
to refer to a hard coded form name.
Be aware that there are a couple of different 'form' objects and you need to specify the actual name of your form object.
By default the forms are called "MainForm". You can check by using the Form Navigator while in form design.
You can also rename "MainForm" using form navigator. (Right click).
Once you have the form object, you can use
and then
Or you can use
to do it in 1 step.
Note that the .Text property doesn't apply to controls for all data types. Use MRI to find out what properties exist for your control.
For controls on subforms:
You can use oEvent.Source to access the Control but you need to be aware that oEvent can point to different objects depending on what event it is and sometimes even code attached to the same event can have oEvent point to different oblects when the event is triggered from different controllers. MRI is very useful here.
You can usually use
Code: Select all
oForm = ThisComponent.DrawPage.Forms.getByIndex(0)
Or you can use
Code: Select all
oForm = ThisComponent.DrawPage.Forms.GetByName("myFormName")
Be aware that there are a couple of different 'form' objects and you need to specify the actual name of your form object.
By default the forms are called "MainForm". You can check by using the Form Navigator while in form design.
You can also rename "MainForm" using form navigator. (Right click).
Once you have the form object, you can use
Code: Select all
oControl = oForm.GetByName("myControlName") to reference the Control object
Code: Select all
oControl.Text to reference the value of string controls
Code: Select all
oForm.GetByName("myControlName").Text
Note that the .Text property doesn't apply to controls for all data types. Use MRI to find out what properties exist for your control.
For controls on subforms:
Code: Select all
oForm = ThisComponent.DrawPage.Forms.getByIndex(0)
oSubForm = oForm.GetByName("SubForm") ' Assuming you haven't renamed your SubForm
oTablemodel=oSubForm.getbyname("SubForm_Grid") ' Assuming you haven't renamed your SubForm_Grid
oControl = oTablemodel.GetByName("myControlName")
Open Office 3.3.0 RC10, Windows 7 (64bit)
-
- Posts: 6
- Joined: Fri Feb 25, 2011 4:38 am
Re: Referencing form controls from macro's
Thanks for all the help. I have solved the original issue by using "model" with "parent" which I hadn't seen before.
Sub CheckPN(Event)
CallObj=Event.Source
Frm=CallObj.Model.Parent
Once I had the form I was fine, able to access other objects with GetByName.
I guess I have a lot to find out about still. I have no idea what the "Model" means yet.
i've been playing with MRI and, while I was able to navigate through objects and methods, I never once understood what actual object I was looking at.
Sub CheckPN(Event)
CallObj=Event.Source
Frm=CallObj.Model.Parent
Once I had the form I was fine, able to access other objects with GetByName.
I guess I have a lot to find out about still. I have no idea what the "Model" means yet.
i've been playing with MRI and, while I was able to navigate through objects and methods, I never once understood what actual object I was looking at.
OpenOffice 3.3.0 on Windows XP
-
- Volunteer
- Posts: 828
- Joined: Fri Nov 30, 2007 10:58 am
- Location: Scotland
Re: [Solved] Referencing form controls from macro's
With the help of Hanya I developed for my own use a macro library to help the display by MRI of the properties and methods of form controls. It can be run from a form document in either edit or direct mode. When run it displays a form control tree similar to that used by the 'form navigator'. Double clicking the name of any form or form control in the list automatically runs an MRI scan on the 'model' of that object and on its 'view' if the object has one. It greatly simplifies the task of finding what properties or methods might be available. I store the library in 'My Macros' and call its 'Main' routine from an icon on the toolbar of the form document.I have no idea what the "Model" means yet.
i've been playing with MRI and, while I was able to navigate through objects and methods, I never once understood what actual object I was looking at.
You use it at your own risk, but do please come back if you have any problems or find errors in its application. Though some routines at the end seem to be empty they must be included to avoid errors arising from the mouse and button event listeners.
Code: Select all
REM Control Tree Code
REM ***** BASIC *****
REM I owe a debt of gratitude to Hanya for the Tree Control code as well as for the MRI extension.
REM All the remaining errors and bugs, however, are entirely my responsibility.
REM The Main macro can be run from a Form Document open (in either edit or run mode).
REM Best called from an icon added to the standard toolbar saved in the OOoBase:Form design
REM It displays a dialog similar to that of the Form Navigator. Double clicking any control on the
REM list will run MRI on that control's model and where available on its view. A single click will
REM select a control from the list and MRI can then be run by selecting the MRI button.
REM Unless the auto close check box has been selected, the dialog and Tree Control will remain
REM open to permit MRI to be run on further controls.
REM ****************************************************************************
Dim oDoc As Object
Dim oDocCtrl As Object
Dim oForms As Object
Dim oDialog As Object
Sub Main
oDoc = ThisComponent
oDocCtrl=oDoc.GetCurrentController()
If oDoc.supportsService("com.sun.star.text.TextDocument") Then
oForms = oDoc.getDrawPage().getForms()
ElseIf oDoc.supportsService("com.sun.star.sheet.SpreadsheetDocument") Then
' Spreadsheet needs problem about active sheet changing
oForms = oDoc.getCurrentController().getActiveSheet().getDrawPage().getForms()
Else MsgBox("This is neither a Writer nor a Calc document - Macro will abort",0) : Exit Sub
End If
' create dialog
oDialog = CreateUnoService("com.sun.star.awt.UnoControlDialog")
oDialogModel = CreateUnoService("com.sun.star.awt.UnoControlDialogModel")
oDialogModel.setPropertyValues( _
Array("Height", "PositionX", "PositionY", "Width","Title"), _
Array(200, 50, 50, 130, "Double Click to run MRI") )
oDialog.setModel(oDialogModel)
' AutoClose check box
oCheckModel = oDialogModel.createInstance("com.sun.star.awt.UnoControlCheckBoxModel")
oCheckModel.setPropertyValues(_
Array("Height", "Label", "PositionX", "PositionY", "State", "Width"), _
Array(13, "Auto Close", 1, 187, 0, 40))
oDialogModel.insertByName("AutoClose", oCheckModel)
' Close Button
oCloseBtnModel = oDialogModel.createInstance("com.sun.star.awt.UnoControlButtonModel")
oCloseBtnModel.setPropertyValues(_
Array("Height", "Label", "PositionX", "PositionY", "PushButtonType", "Width"), _
Array(13, "~Close", 94, 187, com.sun.star.awt.PushButtonType.CANCEL, 35))
oDialogModel.insertByName("CloseBtn", oCloseBtnModel)
' MRI Button
oMRIBtnModel = oDialogModel.createInstance("com.sun.star.awt.UnoControlButtonModel")
oMRIBtnModel.setPropertyValues(_
Array("Height", "Label", "PositionX", "PositionY", "PushButtonType", "Width"), _
Array(13, "~MRI", 58, 187, com.sun.star.awt.PushButtonType.STANDARD, 35))
oDialogModel.insertByName("MRIBtn", oMRIBtnModel)
' create tree control
oTreeModel = oDialogModel.createInstance("com.sun.star.awt.tree.TreeControlModel")
oTreeModel.setPropertyValues( _
Array("Height", "PositionX", "PositionY", "SelectionType", "ShowsRootHandles", "Width"), _
Array(186, 1, 1, com.sun.star.view.SelectionType.SINGLE, False, 128) )
oDialogModel.insertByName("Tree", oTreeModel)
oTree = oDialog.getControl("Tree")
oTreeDataModel = CreateUnoService("com.sun.star.awt.tree.MutableTreeDataModel")
' make new tree model structure
oTreeDataModel = CreateUnoService( _
"com.sun.star.awt.tree.MutableTreeDataModel")
' top node
oRootNode = oTreeDataModel.createNode("Forms", true)
oRootNode.setCollapsedGraphicURL("private:graphicrepository/res/sx18013.png")
oRootNode.setExpandedGraphicURL("private:graphicrepository/res/sx18013.png")
' set data to the root
oTreeDataModel.setRoot(oRootNode)
oTreeModel.DataModel = oTreeDataModel
AddChildren(oForms, oTreeDataModel, oRootNode)
oDialog.setVisible(True)
oButtonListener = CreateUnoListener("ButtonPush_", "com.sun.star.awt.XActionListener")
oMRIBtn = oDialog.getControl("MRIBtn").addActionListener(oButtonListener)
oTree.expandNode(oRootNode) ' expand after dialog visible
ExpandAllNodes(oTree, oRootNode)
oMouseListener = CreateUnoListener("Mouse_", "com.sun.star.awt.XMouseListener")
oTree.addMouseListener(oMouseListener)
oDialog.execute()
oTree.removeMouseListener(oMouseListener)
CloseDialog()
End Sub
Sub CloseDialog()
If oDialog.getControl("AutoClose").State = 1 Then
oDialog.endExecute()
Endif
End Sub
Function GetFormControl(oForms As Object, oNode As Object) As Object
Dim oControl As Object
Dim sNames() As String
While NOT IsNull(oNode)
n = UBound(sNames) +1
ReDim Preserve sNames(n)
sNames(n) = CStr(oNode.getDisplayValue())
oNode = oNode.getParent()
WEND
' find control
oControl = oForms
For i = UBound(sNames) -1 to 0 step -1
oControl = oControl.getByName(sNames(i))
Next
GetFormControl = oControl
End Function
Sub SelectControl(oForms As Object, oNode As Object) As Object
oControl = GetFormControl(oForms, oNode)
If IsNull(oControl) Then Exit Sub
oDoc.getCurrentController().select(oControl)
End Sub
Sub OpenWithMRI(oForms As Object, oControl As Object)
oControl = GetFormControl(oForms, oControl)
If IsNull(oControl) Then Exit Sub
Globalscope.BasicLibraries.loadLibrary("MRILib")
MRILib.Mri(oControl)
REM Views not available for Columns in Grid Control, Hidden Controls, Forms or Sub-Forms
if oControl.Parent.ImplementationName = "com.sun.star.comp.forms.OGridControlModel" Then Exit Sub
If oControl.ImplementationName = "com.sun.star.comp.forms.ODatabaseForm" OR _
oControl.ImplementationName = "com.sun.star.comp.forms.OFormsCollection" OR _
oControl.ImplementationName = "com.sun.star.comp.forms.OHiddenModel" then Exit Sub
REM Document's Controller and Form Control's Model gives Form Control's View
oView = oDocCtrl.GetControl(oControl)
If NOT ISNULL(oView) then MRI oView
End Sub
Sub Mouse_mousePressed(oEv As com.sun.star.awt.MouseEvent)
If oEv.Buttons = com.sun.star.awt.MouseButton.RIGHT Then
oTree = oEv.Source.getContext().getControl("Tree")
oNearNode = oTree.getClosestNodeForLocation(oEv.X,oEv.Y)
If IsNull(oNearNode) Then Exit Sub
aRect = CreateUnoStruct("com.sun.star.awt.Rectangle")
aRect.X = oEv.X + oTree.PosSize.X
aRect.Y = oEv.Y + oTree.PosSize.Y
oPopup = CreateUnoService("stardiv.vcl.PopupMenu")'"com.sun.star.awt.PopupMenu")
oPopup.insertItem(1, "Select", 0, 0)
oPopup.insertItem(2, "MRI", 0, 1)
oPopup.setCommand(1, "select")
oPopup.setCommand(2, "mri")
n = oPopup.execute(oTree.getContext().getPeer(), aRect, _
com.sun.star.awt.PopupMenuDirection.EXECUTE_DEFAULT)
If n > 0 Then
sCommand = oPopup.getCommand(n)
Select Case sCommand
Case "select"
SelectControl(oForms, oNearNode)
Case "mri"
OpenWithMRI(oForms, oNearNode)
End Select
CloseDialog()
End If
End If
End Sub
Sub Mouse_mouseReleased(oEv)
If oEv.Buttons = com.sun.star.awt.MouseButton.LEFT and oEv.ClickCount = 2 Then
oTree = oEv.Source.getContext().getControl("Tree")
oNearNode = oTree.getClosestNodeForLocation(oEv.X,oEv.Y)
If IsNull(oNearNode) Then Exit Sub
OpenWithMRI(oForms, oNearNode)
CloseDialog
End If
End Sub
Sub ButtonPush_actionPerformed(oEv As com.sun.star.awt.ActionEvent)
' get selected item
Dim oSelected() As Object
oTree = oEv.Source.getContext().getControl("Tree")
oSelected = oTree.getSelection()
If IsArray(oSelected) Then
Exit Sub
Else
OpenWithMRI(oForms, oSelected(0))
CloseDialog
End If
End Sub
Sub AddChildren( oContainer As Object, oDataModel As Object, oParent As Object )
For i = 0 To oContainer.getCount() - 1 step 1
oModel = oContainer.getByIndex(i)
sName = oModel.getName()
sImageURL = GetImageURL(oModel.getServiceName())
If HasUnoInterfaces(oModel, _
"com.sun.star.container.XContainer") Then
oChild = oDataModel.createNode(sName, true)
AddChildren(oContainer.getByName(sName), oDataModel, oChild)
Else
oChild = oDataModel.createNode(sName, false)
End If
oChild.setExpandedGraphicURL(sImageURL)
oChild.setCollapsedGraphicURL(sImageURL)
oParent.appendChild(oChild)
Next
End Sub
Sub ExpandAllNodes(oTree As Object, oParent)
For i = 0 To oParent.getChildCount() - 1 step 1
oChild = oParent.getChildAt(i)
oTree.expandNode(oChild)
If oChild.getChildCount() > 0 Then
ExpandAllNodes(oTree, oChild)
End If
Next
End Sub
Function GetImageURL(sServiceName As String) As String
Dim sName As String
sControlService = Mid(sServiceName, 28) 'stardiv.one.form.component.Form
sServices = Array(_
"CheckBox", "ComboBox", "CommandButton", _
"CurrencyField", "DateField", "Edit", "FileControl", _
"FixedText", "Form", "FormattedField", _
"Grid", "GroupBox", "HiddenControl", _
"ImageButton", "ImageControl", "ListBox", _
"NumericField", "PatternField", "RadioButton", _
"TextField", "TimeField", _
".NavigationToolBar", ".SpinButton", ".ScrollBar")
sNames = Array(_
"sx10596", "sx10601", "sx10594", _
"sx10707", "sx10704", "sx10599", "sx10605", _
"sx10597", "sx10593", "sx10728", _
"sx10603", "sx10598", "sx18022", _
"sx10604", "sx10710", "sx10600", _
"sx10706", "sx10708", "sx10595", _
"sx10599", "sx10705", _
"sx10607", "sx10769", "sx10768")
For i = 0 To UBound(sServices) step 1
If sServices(i) = sControlService Then
sName = sNames(i)
Exit For
End If
Next
GetImageURL = "private:graphicrepository/res/" & sName & ".png"
End Function
Sub Mouse_mouseEntered(ev)
End Sub
Sub Mouse_mouseExited(ev)
End Sub
Sub Mouse_disposing(ev)
End Sub
Sub ButtonPush_dispose(oEv)
End Sub
When this issue has been resolved, it would help other users of the forum if you add the word - [Solved] - to the Subject line of your 1st post (edit button top right).
AOOo 4.1.5 & LO 6 on MS Windows 10 MySQL and HSQLDB
AOOo 4.1.5 & LO 6 on MS Windows 10 MySQL and HSQLDB
-
- Posts: 6
- Joined: Fri Feb 25, 2011 4:38 am
Re: [Solved] Referencing form controls from macro's
That's a big help thanks, I've just run it up and can at least know what I'm looking at now
OpenOffice 3.3.0 on Windows XP