How to stop automatic saving of records in Base

I have a subform in Base and would like to require a “Save” button be pressed to ensure that updates are intended and also to allow some basic validation (such as a numeric field being positive). However, when a new row is selected in the main form I see that the row in the subform is saved to the database without confirmation.

This confuses me because the Developer’s guide says that “If the cursor is moved to a different row before calling updateRow(), the update is lost. The update can be canceled by calling cancelRowUpdates()”.

I have tried writing a macro to catch the “before record change” events on both the main and the subforms but I find that the change is already committed to the database when these events are fired.

Any help would be appreciated.

LO 5.1.3.2

–Tony

What you are looking at in the Developers Guide is the manipulation of a data set (think Query) using macros. The cursor referred to here is the field/record currently pointed to within the record set - very similar to the position of the mouse cursor within a table control or control field.

Although not quite clear, it appears your form has two table controls. For sake of argument, Form contains the Master table and the sub-Form contains a table related to the Master. When you select a Master record, the related records appear in the sub-form control. The updating of tables are independent of each other. If in the sub-table you enter data in a new row and BEFORE advancing to another new row you select a different row in the Master table, the sub-table will not be updated. However, once you advance to a new row in the sub-table control, that record is updated.

Depending upon what you are trying to validate in each field, most can be accomplished through settings within the properties for each column in the table control. If this is not enough (hardly ever the case) and you actually need to control the checking through macros, the task is not easy. Using an event such as ‘Before record change’ actually occurs even when loading records into the table (ie: starting the form, or changing Master record selection’). Instead, you might need to look at individual fields by triggering an event such as ‘When receiving focus’ or ‘When losing focus’.

Using a ‘Save’ button is not very different. You would typically set the sub-form with individual fields (as opposed to a table control) and set the ‘Execute action’ event of the button to run your code for validation and update.

Again it is hard to tell what validation you want that can’t be handled without code.

As @Ratslinger said in his reply the section of the Developers Guide you referred to does not relate to the manipulation of data using Forms. It does refer to using a Macro to run a query. The query in the macro produces a result set (named rs in the Guide) which can then be used to manipulate the data,

My apologies for the tardy response, partiularly after the prompt response.

I thought I had asked a perfectly simple question but the two replies indicate that I have not. Ratsinger has correctly surmized my issue when he says “once you advance to a new row in the sub-table control, that record is updated.” In my case the movement to the new row in the sub-table is precipitated by a movement in the parent table but that is not particularly relevant,

This default behaviour is what I wanted to supress. I only wanted the update (or insertion) to come from an explicit button press.

My problem was one of English language semantics. Suppose a cursor is pointing to the second row in a resultset. I interprested “before record change” to mean “before a change in the contents of the current row”, i.e. the updateRow or insertRow call. However, “record change” actually means movement of the cursor wthin the result set, say to the first or third row. What I needed to do was to write a macro to catche the “before record action” event. This turned out to be non-trivial since the macro is actually fired twice, once with the controller as the source and once with the form.

This is the code I wrote that sort of did the job, but USE IT AT YOUR OWN RISK:

function BeforeRecordAction(event) ' USE AT YOUR OWN RISK
With event.source
	If .supportsservice("com.sun.star.form.runtime.FormController") Then
		if .currentcontrol.model.classid = com.sun.star.form.FormComponentType.COMMANDBUTTON then
			BeforeRecordAction = true ' Button update OK
		else
			BeforeRecordAction = false ' Updates initiated by row movement disallowed
		end if
	else
		BeforeRecordAction = true ' Not controller so ignore
	end if
End With

End Function

However, this seems to confuse the BASIC framework, as does trying to veto row movements with “before record change”. It looks like BASIC does not expect you to use event handlers to veto these sorts of things although supressing mouse click and keyboard events seems to be OK.

My advice to any would-be developers that want users to explictly confirm or cancel changes is to either use a dialogue box or write the whole application in Java. If you don’t like either of those options try simplifying the form to exclude subforms and minimizing the extent to which the BASIC framework can get itself confused.

Every form and subform has its own BeforeRecordAction. So you can assign different sub to every form and subform. Of course you can use the same sub to all and distinguish them in code, using the event.source. Be sure to understand that these events are for all forms included in form navigator. There may exist many MainForm’es if widgets were copied from other forms.