Randomly firing form event: Why?

Windows
Version 22H2 Build 19045.5608
LO
Version: 24.8.5.2 (X86_64) / LibreOffice Community
Build ID: fddf2685c70b461e7832239a0162a77216259f22
CPU threads: 2; OS: Windows 10 X86_64 (10.0 build 19045); UI render: Skia/Raster; VCL: win
Locale: en-US (en_US); UI: en-US
Calc: threaded

From the LibreOffice Base Guide, p. 457:

When a modified record is stored, there are two implementations involved named
org.openoffice.comp.svx.FormController and
com.sun.star.comp.forms.ODatabaseForm.

Each implementation causes the Before Record Action event to fire, so the event fires twice, sometimes. Only the FormController event fires consistently. For me, for the last couple of months, the ODatabaseForm hasn’t been firing at all. Tonight it suddenly started firing, generating some errors. That was easy to fix, but it left me wondering. Why does the ODatabaseForm event fire erratically, and what’s the point of having it fire at all if it doesn’t fire consistently?

My limited understanding is that LO Basic isn’t entirely thread safe.

The problem isn’t new, see for example:

https://www.developpez.net/forums/d1548759/logiciels/logiciels-libres-open-source/bureautique/openoffice-libreoffice/ordre-evenements-reentrance-macro-traitement-evemenents/

Re-entrant functions such as the one you highlight cause multiple firing, which can lead to desynchronisation, crashes and other generally unexpected behavior.

There doesn’t appear to be an easy way to solve the problem.

It is almost certainly a bug, which has unfortunately attracted little developer attention, probably because it is a complex area, and probably also considered to be a bit niche.

In macros i only use this:

IF oForm.ImplementationName = "org.openoffice.comp.svx.FormController" THEN
…
END IF

You could insert the code there and the boolean value will be set there also. If the boolean value is false it will EXIT FUNCTION. Also I know I could get the controls in the form with
oForm.Model.getString(oForm.Model.FindColumn("MyTablefield")). This only works with “org.openoffice.comp.svx.FormController” while
oForm.getString(oForm.FindColumn("MyTablefield")) will work with “com.sun.star.comp.forms.ODatabaseForm”.

1 Like

@iplaw67 I marked your response as the solution, since it gives me a hint about the source of the behavior. Rather than being intentional, the second event triggered by ODatabaseForm is the result of threads bumping into each other. And it happens erratically because that accidental interaction is unpredictable. Assuming I understand you correctly.

@RobertG I had a slightly more complicated If statement, but simpler is better if it’s reliable, so I’m trying your If statement.

I discovered that many of the methods available under ODatabaseForm don’t work under FormController. I haven’t been able to find anything on FormController, so the info about Form.Model is useful.

Thank you for your response.

Edit: After some thought, I deleted a code example because I realized that the conditions under which I tested it make the tests meaningless.

@RobertG Your If statement works for me as long as there’s no interaction between the Before Record Action macro and other code. The If statement protects the code in the event macro, but doesn’t protect code elsewhere. I have a macro that calls the form’s updateRow method, which triggers the Before Record Action event.

Here’s what is working for me when one event macro triggers another event macro:

	'Usually, the Before Record Action event fires once, but sometimes it fires twice.
	'If it fires twice, the 2nd time is triggered by ODatabaseForm & generates errors.
	If objEvent.Source.ImplementationName = "com.sun.star.comp.forms.ODatabaseForm" Then
		'W/out the following line, ODatabaseForm sometimes vetoes record actions triggered
		'by other macros.
		mcrAllowRecordAction = True
		'Usher ODatabaseForm to the exit before it causes any more trouble.
		Exit Function
	End If