Questions
- How should I correctly initialise GUI controls so that my example always works?
- Can I bind the checkbox status directly to the current dataset?
- like an expression:
id > 0
for checked and otherwise unchecked
Problem
Short:
Autochecking a checkbox when loading my form (in view mode) sometimes isn’t working.
Details:
I have a checkbox that is checked or unchecked depending on a foreign key being null or not. There is a drop down list that will be toggled active/inactive accordingly. The drop down list is also toggled when checking / unchecking the checkbox.
This works so far. But in some cases, which I CANNOT reproduce, it just doesn’t. When this happens it loads the default status for the checkbox (unchecked) and for the list (disabled). After a crash and restore it was always disabled until I opened the odb again some time later.
I think the GUI form might sometimes not be done initialising when I try to access the bound column. And then it just does not toggle the drop down list. But I don’t understand why that would happen.
Maybe I have to bind it to the MainForm loading instead of the form document opening? The problem testing a solution is that it happens very rarely. So I will not know if something worked or not. That’s why I hope someone has an idea or an example how this is usually done.
Example
I reused my dog database example (see my other question for DB details). It happens in this example too, just very rarely. I left my macro structure as close to the original as possible just in case variable scope is the reason. Hope it is not confusing.
How to reproduce (happens very rarely) :
- open “Dogs” form
- double click a dog without an owner (this will open the “Dog” form)
- apply an owner to the dog
- save and go back
- open any dog that has an owner
- the checkbox will be unchecked and the list will be disabled
- if it’s not disabled remove an owner from a dog, save, then go back to 2
- it can help to close the odb first, then go back to 1
Relevant Macros
Only some parts here. See example file for full macros. You can enable DEBUG_MODE
in utils if you want to see message box popups for each step.
utils
REM Return a form by name
Public Function GetGuiForm(formDocName As String, formName As String) As Object
Dim formDoc As Object
formDoc = ThisDatabaseDocument.FormDocuments.getByName(formDocName)
GetGuiForm = formDoc.Component.DrawPage.Forms.getByName(formName)
End Function
Public Function IsDoubleClick(event As Object) As Boolean
IsDoubleClick = event.ClickCount > 1
End Function
frm_dog
REM ***** BASIC *****
REM Form: Dog
Option Explicit
Option Compatible
Public Property Get FORM_NAME As String
Static thisName
thisName = "Dog"
FORM_NAME = thisName
End Property
Private Const GUI_FORM_MAIN = "MainForm"
Private Const GUI_CHK_OWNER = "chk_hasOwner"
Private Const GUI_LST_OWNERS = "lst_owners"
Private Const COLUMN_OWNER = "owner_id"
REM When opening the form
Sub OnLoad
utils.Debug("OnLoad called", "frm_dog:OnLoad")
utils.Maximise()
Init()
End Sub
REM Load filter data and set MainForm filter
Sub Init()
utils.Debug("Init called", "frm_dog::Init")
Dim sQuery As String
sQuery = "SELECT ""filter_int"" FROM ""_Filters"" WHERE ""filter_name"" = 'Forms_Dog'"
Dim oResult As Object
oResult = utils.SQL_getQueryResults(sQuery)
Dim dogId As Integer
While oResult.next
dogId = oResult.getInt(1)
Wend
utils.Debug("DogId from Filter: " & dogId, "frm_dog::Init")
Dim oMainForm As Object
oMainForm = utils.GetGuiForm(FORM_NAME, GUI_FORM_MAIN)
oMainForm.Filter = "dog_id = " & dogId
utils.Debug("Set MainForm filter to: " & oMainForm.Filter, "frm_dog::Init")
utils.Debug("Reloading MainForm now", "frm_dog::Init")
oMainForm.reload()
SetOwnerStatus()
End Sub
REM Go back to dogs overview
Sub SwitchToDogs()
utils.SwitchForm(FORM_NAME, frm_dogs.FORM_NAME)
End Sub
REM Check owner checkbox if this dog has an owner
Private Sub SetOwnerStatus()
utils.Debug("SetOwnerStatus called", "frm_dog::SetOwnerStatus")
Dim oMainForm As Object
oMainForm = utils.GetGuiForm(FORM_NAME, GUI_FORM_MAIN)
Dim chkOwner As Object
chkOwner = oMainForm.getByName(GUI_CHK_OWNER)
Dim bStatus As Boolean
Dim dataExists As Boolean
dataExists = oMainForm.Columns.hasByName(COLUMN_OWNER)
utils.Debug("MainForm column '" & COLUMN_OWNER & "' exists: " & dataExists, "frm_dog::SetOwnerStatus")
If dataExists Then
Dim colOwner As Object
colOwner = oMainForm.Columns.getByName(COLUMN_OWNER)
utils.Debug(COLUMN_OWNER & ".Value = " & colOwner.Value)
bStatus = (NOT colOwner.wasNull()) AND (NOT IsEmpty(colOwner.Value))
End If
Dim status As Integer
If bStatus Then status = 1
chkOwner.State = status
utils.Debug("Checkbox set to '" & status, "frm_dog::SetOwnerStatus")
If dataExists Then ToggleOwners()
End Sub
REM Enable/Disable dropdown list depending on checkbox status
Sub ToggleOwners()
utils.Debug("ToggleOwners called", "frm_dog::ToggleOwners")
CONST CHECKED = 1
Dim mainForm As Object
Dim lstOwners As Object
Dim chkOwner As Object
mainForm = utils.GetGuiForm(FORM_NAME, GUI_FORM_MAIN)
chkOwner = mainForm.getByName(GUI_CHK_OWNER)
lstOwners = mainForm.getByName(GUI_LST_OWNERS)
If chkOwner.State = CHECKED Then
utils.Debug("Owners checked, enabling dropdown list", "frm_dog::ToggleOwners")
lstOwners.Enabled = True
Else
utils.Debug("Owners unchecked, disabling dropdown list and clearing its value", "frm_dog::ToggleOwners")
lstOwners.Enabled = False
lstOwners.SelectedValue = ""
mainForm.Columns.getByName(COLUMN_OWNER).updateNull()
End If
End Sub
LO
Version: 7.1.3.2 (x64) / LibreOffice
OS: Win10