The manual






Access and automatic creation of other forms

Browse other forms

Suppose that at the level of a file follow-up, we want to calculate the time spent on this file, and that this one is filled in the form of a set of files whose type is 'temps_passe' and which contain a decimal type 'hours' field.
In the file file, we can calculate the total time spent 't' via a sequence of the type:

var Float t := 0
each_form type "temps_passe"
  field Float heures
  t := t+heures

The 'each_form' instruction (historically 'forms') allows you to browse all the other forms of the current page.
If, as in the previous example, we add the 'type' option to it, only the records of the corresponding type will be searched.
If we also want to browse the files contained in two levels of sub pages, we can write:

var Float t := 0
each_form type "temps_passe" child 2
  field Float heures
  t := t+heures

Sometimes, we want to find information common to all the files in a zone of the tree structure, which will be stored in a single file at the root of this zone. In the following example, we find the customer code in a 'customer' type form which contains a 'code' field, and it is stored in the local variable 'c' which will be used in the rest of the calculation:

var Str c
each_form type "client" parent 999
  field Float code
  c := code

You can also browse all the currently selected forms.
This assumes first of all that at the level of a report, in the 'Display' part, the 'Display the selection column' control has been positioned.
This then assumes that certain lines of the report have been checked,
then clicked on a button of a form containing a program with the following code sequence:

each_form selection
  field Str f1
  f1 := ""

Finally, we can browse all the forms of the current sheet (a sheet is an element of a stack):

each_form sheet
  field Str f1
  f1 := ""

The 'field' instruction allows you to specify the fields to which you want to access, as well as their type.
If the 'hours' field also exists in the current file, we will have a name collision problem, which we can work around by assigning a new name, for example 'h':

var Float t := 0
each_form type "temps_passe"
  field Float heures -> h
  t := t+h

Finally, in some cases, for example an expert system, we will want to browse all the files in order. We can then use the 'version' instruction to determine the type of the file and carry out the appropriate processing:

  if version:"temps_passe">0

When browsing other records, it is possible that the browsed records have changed over time, and that in fact certain fields do not exist in all cases. We can then test the existence of a field using the 'exists' function:

var Float t := 0
forms type "temps_passe"
  field Float heures
  field Float coef
  if exists:coef
    t := t*heures*coef
    t := t*heures

One last important note about the 'forms' instruction. When the program is executed after pressing a button, the fields of the browsed forms can be modified.

Pre-fill a field of a record using the other records on the page
     An example of using the 'each_form' instruction
     Provided an example showing how to pre-populate a form field using the other forms on the page.

Create other forms

It is the 'new_form' instruction that allows you to generate a new form.
Is available only if program execution is the result of pressing a button in the form, as opposed to the user modifying one of the form fields.

It contains a block that will be executed to allow you to modify certain fields of the new form. In the following example, we save the current date and time in the 'd' field of the new form.

new_form "identifiant_du_formulaire_a_recopier"
  field DateTime d
  d := datetime

The 'new_form' instruction accepts many options:

new_form "identifiant" copy_fields

Copies the fields of the form being executed to the new form (only if they are not empty in the form).
This option must be the last.

new_form "identifiant" before "identifiant_de_bloc"

Le nouveau formulaire sera créé juste au dessus du bloc spécifié.

new_form "identifiant" after "identifiant_de_bloc"

Le nouveau formulaire sera créé juste sous le bloc spécifié. 'below' est l'ancienne version de 'after'.

new_form "identifiant" page "identifiant_de_page"

The new form will be created at the bottom of the specified page.

new_form "identifiant" tail "identifiant_de_bloc"

The new form will be created at the bottom of the page containing the specified block.

new_form "identifiant" page "identifiant_de_page" subpage "id_sous_page_niveau_1" "titre de la sous page niveau 1" subpage "id_sous_page_niveau_2" "titre de la sous page niveau 2"

The new form will be placed in a two-level subtree of the specified page.
There is an old syntax for the 'subpage' parameter with a single string to follow instead of two, which specifies all the sublevels at once, using the '/' character as a separator, and effectively using l 'identifier as the subpage title, but this obsolete formulation mode is only kept for backward compatibility reasons.

var DateTime dt := ...
new_form "identifiant" page "identifiant_de_page" stack "identifiant_de_pile" date dt from "Expéditeur" subject "Titre de la feuille"

Lets you put the new form in a stack. The additional parameters 'date' 'from' and 'subject' are optional. In the past, 'subject' was noted as 'title'.
Finally we can insert 'subpage' parameters between the 'page' parameter and the 'stack' parameter, or we can omit the 'page' parameter if the stack is to be created at the bottom of the current page.

You can combine the 'page', 'subpage' and 'stack' or 'below' 'subpage' and 'stack' attributes, as well as 'copy_fields' with all the others.


new_form "identifiant" location "nom_de_la_position"

Used to place the new form in a position that will have been previously defined via the 'define_location' instruction. For example:

new_sheet stack "s"
  define_location "nom_de_la_position"

Form for entering a comment
     Use the 'new_form' instruction
     Shows how to allow comments to be entered in a Storga page without mastering edit mode, much like on a blog page.

Modify the content of another existing record

A fundamental rule to limit complexity in Storga applications is that the program of one form can access data from any other, but not modify it. The goal is to prevent files from being modified by a program we do not know where, i.e. that we notice that a field has changed, but that we cannot easily determine why .

There are two ways to get around this restriction.


The first is the 'each selection' instruction (void above) which reviews the different records that have been selected, either in organize mode, or more generally at the level of the selection column of a report. , before which we press the button that starts the execution of the program. In this case, the content of the selected records can be modified by the program of the record which contains the button.


The second is the sending of messages that we will see now.

Suppose that a form A must modify the content of a form B. It uses the 'compute_form' instruction to send it a message. For form B, it is a bit as if a button had been pressed by the user, except that the code of the button can also contain values \u200b\u200b(the parameters of the message, i.e. roughly the values \u200b\u200bto be recorded ).

The code of file A could be for example:

var Int i := ... # calcul la valeur à stocker dans la fiche B
var Str id := lookup_form_id ... # trouve l'identifiant de la fiche B
form id # sélectionne la fiche B
  compute_form "please_record_value "+string:i envoi le message à la fiche B

And that of sheet B:

if (button_name parse "please_record_value" (var Int i)) # la fiche B traite le message