1. Introduction▲
Cet outil permet de gérer toutes les LOV d'une application Oracle Forms9i de façon centralisée, sans manipulation des sources, ni compilation ni déploiement.
L'écran de LOV générique permet de restreindre la liste des valeurs à chaque caractère frappé selon la colonne de recherche indiquée par l'utilisateur
Un mode recherche globale permet de rechercher une valeur dans toutes les colonnes de la table liée
Générique parce qu'il s'adapte à toutes les LOV possibles de 2 à 9 colonnes
Dynamique car entièrement paramétré
- Position X et Y de l'écran
- Titre de la LOV
- Auto sélection des valeurs
- Libellé des colonnes
- Position des colonnes
- Largeur des colonnes
Personnalisable par l'utilisateur en lui permettant les actions suivantes
- Permutation des colonnes entre elles
- Redimensionnement des colonnes
- Choix de la colonne de recherche
- Enregistrement des préférences (une même LOV peut donc être représentée différemment selon l'utilisateur)
Le développeur dispose d'un écran Forms pour gérer les LOV de son application, permettant d'ajouter, modifier ou supprimer toute LOV du projet sans aucune intervention dans les modules sources.
Celui-ci affiche les modules, blocs et items de toute l'application.
Sur chaque item il est possible de définir une LOV avec les caractéristiques suivantes :
- Titre
- Clause Select
- Clause From
- Clause Where
- Clause Order by
- Position X, Y
- Auto affichage des lignes ramenées
- Lov pour Validation de l'item
Et pour chaque colonne de la LOV
- Position de la colonne
- Nom de la colonne
- Libellé de la colonne
- Largeur d'affichage de la colonne
- Nom de l'item de retour
- Clause restrictive sur la colonne qui peut contenir une référence à un autre item de la forme
Liste des concepts étudiés
-
Utilisation de Groupe d'enregistrements (Record group) et de LOV native
Ou comment à partir d'un unique groupe d'enregistrements et d'une unique LOV simuler n'importe quelle LOV de 2 à 9 colonnes avec adaptation des titres et largeur des colonnes.
- Création dynamique d'un groupe d'enregistrements
- Alimentation du groupe d'enregistrements
- Comptage des enregistrements
- Assignation du groupe d'enregistrements à une LOV native
- Adaptation des titres de colonne de la LOV
- Adaptation des largeurs de colonne de la LOV
- Affichage de la LOV de contrôle
-
Modification dynamique de l'affichage
- Affichage/masquage des objets
- Positionnement des objets (Items, Canvas, Windows)
- Redimensionnement des objets (Items, Canvas, Windows)
- Utilisation d'un Timer
- Gestion d'un menu POPUP
- Gestion d'un bloc basé sur une clause FROM
- Appel d'écran (CALL_FORM) avec passage de paramètres
- Navigation à l'intérieur des items d'un bloc
- Mécanisme de validation de l'item par LOV
- SQL dynamique natif pour alimenter la liste des valeurs depuis la procédure stockée ainsi que pour la validation des items
Remerciements▲
Chaleureux remerciements à Developpez.com et à l'équipe SGBD.
2. L'écran de LOV générique▲
Le titre de la LOV est affiché dans le libellé de la fenêtre
Le champ de saisie des caractères en haut à gauche a toujours le focus, permettant à l'utilisateur d'ajouter des lettres à chaque frappe au clavier et de réduire la liste
La colonne sur laquelle s'effectue la recherche est matérialisée par un fond gris (Colonne Nom dans l'exemple ci-dessus)
La navigation dans la liste de valeurs se fait soit avec la souris dans une des lignes affichées, soit en activant l'ascenseur vertical, soit avec les touches du clavier (UP, DOWN, SCROLL_UP, SCROLL_DOWN)
La sélection d'une ligne dans la liste se fait soit par un double clic sur la ligne, soit via le bouton OK
Possibilités de personnalisation
- Redimensionnement des colonnes
Pour redimensionner une colonne, il faut d'abord la sélectionner par un clic gauche sur la colonne.
Ensuite, un clic droit fait apparaître un menu popup
Dans ce menu, choisir l'option Dimensions
Sous la colonne sélectionnée apparaissent alors deux boutons permettant de réduire (-) ou d'augmenter (+) la largeur de la colonne
Les tailles minimum et maximum pour une colonne sont respectivement de 20 à 700 points.
Une fois la bonne dimension réglée, un clic sur n'importe quelle région de l'écran fait disparaître les deux boutons
- Changement de la colonne de recherche
Il est possible de sélectionner n'importe quelle colonne de la LOV pour effectuer la recherche.
La colonne de recherche est soulignée par un fond gris.
Pour changer la colonne de recherche, sélectionnez la colonne désirée par un clic gauche puis afficher le menu popup avec un clic droit
Clic gauche sur la colonne Fonction puis clic droit
Clic sur le sous-menu Colonne de recherche
La colonne de recherche est désormais Fonction.
D'ailleurs la frappe du caractère C dans le champ de saisie ramène bien les lignes dont la colonne Fonction commence par C
- Permutation des colonnes
Pour permuter les colonnes entre elles, sélectionner la colonne par un clic gauche puis afficher le menu popup avec un clic droit.
Sélectionner l'option de menu Déplacement, puis la sous-option Déplacer à droite ou Déplacer à gauche.
Dans l'exemple, nous choisissons de déplacer la colonne Fonction vers la gauche
La colonne Fonction a été permutée sur la gauche avec la colonne Nom
Le mode Recherche globale
Si le développeur a pris soin de définir une table principale sur cette LOV, la case à cocher Recherche Multicolonne est activable.
Ce mode permet de rechercher une occurrence dans toutes les colonnes de la table définie par le développeur (à l'exception des colonnes de type LONG, LONG RAW, RAW, BLOB et BFILE)
Pour activer le mode Recherche globale il suffit de cocher la case Recherche Multicolonne, de saisir l'occurrence dans le champ de saisie et de valider par la touche Tab ou Enter
Ce mode est pratique lorsque les colonnes affichées ne permettent pas à l'utilisateur d'identifier la ligne voulue, alors que ce dernier " se souvient " par contre d'une information saisie dans une autre colonne
Dans cet exemple (peu vraisemblable, mais c'est pour l'exemple) l'utilisateur a " oublié " le nom mais se souvient que le salaire est de 1215 euros.
Il clique donc sur la case Recherche Multicolonne, saisi 1215 dans le champ de saisie et presse la touche Tab du clavier.
Enregistrement des réglages
Si l'utilisateur souhaite conserver les réglages qu'il vient d'effectuer, afin de les retrouver automatiquement à la prochaine ouverture de cette LOV, il clique sur le bouton Sauver réglages
Suivant le même principe que la gestion des couleurs, ces nouveaux réglages ne sont valables que pour cet utilisateur. Tout autre utilisateur n'ayant pas modifié ses préférences verra cette LOV affichée avec les réglages par défaut.
Comment ça marche ?
Ouvrons le fichier source de l'écran et analysons le contenu
- Le canvas
Contenu du bloc associé au canvas
9 colonnes sont définies dans le bloc BLOC2 afin de supporter toute LOV possible de 2 à 9 colonnes.
Les items COL1 à COL9 sont de type Elément texte Char d'une longueur maxi de 512 caractères
Au chargement de la LOV seuls les items nécessaires seront affichés et disposés dans la fenêtre
Afin de pouvoir gérer la sélection des données depuis n'importe quelle requête dynamique, le bloc BLOC2 est basé sur une Interrogation de clause FROM
Voyons comment le bloc BLOC2 est configuré pour être alimenté par une Interrogation de clause FROM
La propriété Type de source de données est renseignée à Interrogation de clause FROM
La propriété Nom de source de données est valorisée avec la requête virtuelle : select '1','2','3','4','5','6','7','8' from dual
La propriété Colonnes de source de données permet de définir les items de réception
Le champ de saisie (P1), la boite à cocher (Recherche Multicolonne) ainsi que tous les boutons sont contenus dans le bloc CTRL
Le champ P1 reçoit la frappe de l'utilisateur
Le champ RECHERCHE permet de basculer en mode Recherche globale
Le bouton BT_OK valide la sélection dans la liste, retourne les valeurs et quitte la forme
Le bouton BT_QUITTER quitte la forme sans retour de valeur
Le bouton BT_SAUVE permet de sauvegarder en base les réglages de l'utilisateur
Les boutons PLUS et MOINS permettent le redimensionnement des colonnes
Comment faire défiler avec le clavier la liste des enregistrements ramenés alors que le focus est constamment sur le champ de saisie P1 ?
Regardons le contenu des triggers KEY-DOWN, KEY-UP, KEY-SRCDOWN et KEY-SCRUP définis sur l'item P1 et analysons le premier
-- Trigger KEY-DOWN --
Go_Block(
'BLOC2'
)
; -- déplacement sur le bloc BLOC2
Down ;
Go_Item(
'CTRL.P1'
)
; -- retour dans l'item :CTRL.P1
Simple, non ?
Mécanisme général du fonctionnement de l'écran GEN_LOV
La procédure Init_form() est appelée depuis le trigger WHEN-NEW-FORM-INSTANCE dès le chargement de l'écran
Elle commence par masquer les 9 items du bloc BLOC2
-- Masquage des champs --
For
I in
1
..9
Loop
Set_Item_Property(
'BLOC2.COL'
||
Ltrim
(
To_char
(
I )
)
, VISIBLE, PROPERTY_FALSE )
;
End
loop
;
- Positionne l'indicateur de modification à zéro
-- Indicateur de modification --
:CTRL.MODIF :=
0
;
- Désactive la case à cocher de la Recherche globale si aucune table n'est transmise via le paramètre : PARAMETER.PM$TABLE
-- Table en paramètre pour recherche globale ? --
If
:PARAMETER.PM$TABLE
Is
null
Then
Set_Item_Property(
'CTRL.RECHERCHE'
, ENABLED, PROPERTY_FALSE )
;
End
if
;
- Positionne la fenêtre en coordonnées X,Y selon les paramètres fournis
-- Position X,Y --
If
Nvl
(
:PARAMETER.POSX, 0
)
>
0
Then
Set_Window_Property(
'FENETRE1'
, X_POS, :PARAMETER.POSX )
;
End
if
;
If
Nvl
(
:PARAMETER.POSY, 0
)
>
0
Then
Set_Window_Property(
'FENETRE1'
, Y_POS, :PARAMETER.POSY )
;
End
if
;
- Lit dans la table LOV_ELEMENT_COLONNE les informations nécessaires à la gestion de la LOV
-- Lecture des colonnes de la LOV en table --
init_bloc_bl_col ;
Cette procédure permet de retrouver les colonnes, leur libellé, position et largeur
- Dimensionne, ordonne et affiche les colonnes nécessaires
-- Affichage des colonnes --
dessine_colonnes ;
PROCEDURE
Dessine_colonnes IS
LN
$PosX PLS_INTEGER
:=
:CTRL.POS_X ;
LN
$Long
PLS_INTEGER
;
LC$Item VARCHAR2
(
30
)
;
LN
$TCan PLS_INTEGER
:=
0
;
LN
$Max
PLS_INTEGER
;
LN
$larg PLS_INTEGER
;
LN
$Taille PLS_INTEGER
;
BEGIN
----------------------------------
-- Affiche les colonnes de la lov
-- et dimensionne la fenêtre
----------------------------------
LN
$TCan :=
325
; -- Taille minimum du canvas
LN
$Max
:=
LN
$PosX ; -- Largeur maxi du canvas
go_block(
'BL_COL'
)
;
First_record ; -- première colonne
Loop
-- pour chaque colonne
LC$ITEM :=
'BLOC2.'
||
:BL_COL.COLONNE ;
LN
$Long
:=
:BL_COL.Taille ; -- largeur de la colonne
LN
$Max
:=
LN
$Max
+
LN
$Long
; -- largeur canvas avec colonne
-- Ajuster la largueur du Canvas ? --
If
LN
$Max
>
LN
$TCan Then
LN
$TCan :=
LN
$Max
+
20
;
Set_Canvas_Property(
'CV_LOV'
, WIDTH, LN
$TCan )
; -- agrandissement du canvas
End
if
;
Set_Item_Property(
LC$Item, VISIBLE, PROPERTY_TRUE)
; -- affichage de la colonne
Set_Item_Property(
LC$Item, ENABLED, PROPERTY_TRUE)
;
Set_Item_Property(
LC$Item, NAVIGABLE, PROPERTY_TRUE)
;
Set_Item_Property(
LC$Item, UPDATE_ALLOWED, PROPERTY_TRUE)
;
Set_Item_Property(
LC$Item, WIDTH, :BL_COL.Taille)
; -- largeur de la colonne
Set_Item_Property(
LC$Item, NEXT_NAVIGATION_ITEM, :BL_COL.Suivant)
; -- item suivant
Set_Item_Property(
LC$Item, PREVIOUS_NAVIGATION_ITEM, :BL_COL.Precedent)
; -- item précédent
-- Coordonnée X de la colonne sur le canvas --
Set_Item_Property(
LC$Item, X_POS, LN
$PosX)
;
LN
$PosX :=
LN
$PosX +
LN
$Long
;
If
:system.last_record =
'TRUE'
Then
exit
;
End
if
;
Next_record ;
End
loop
;
If
LN
$Tcan <
325
Then
LN
$Larg :=
325
;
Elsif
LN
$Tcan >
600
Then
LN
$Larg :=
600
;
Else
LN
$Larg :=
LN
$Tcan ;
End
if
;
-- Adaptation de la largeur de la vue --
Set_View_Property(
'CV_LOV'
, WIDTH, LN
$TCan )
;
Set_View_Property(
'CV_LOV'
, VIEW_SIZE, LN
$TCan, 324
)
;
-- Adaptation de la largeur de la fenêtre (maxi 600 points) --
If
LN
$TCan <
600
Then
Set_Window_Property(
'FENETRE1'
, WIDTH, LN
$TCan )
;
Else
Set_Window_Property(
'FENETRE1'
, WIDTH, LN
$Larg )
;
End
if
;
END
;
- Met en relief la colonne de recherche
-- Mise en relief de la colonne de recherche --
Colore_colonne ;
PROCEDURE
COLORE_COLONNE IS
BEGIN
-- Colore la colonne de recherche --
If
:GLOBAL
.ANCCOLONNE is
not
null
Then
-- dé-grise l'ancienne colonne de recherche --
Set_Item_Property(
:GLOBAL
.ANCCOLONNE, VISUAL_ATTRIBUTE, 'VA_COL_NOSELECT'
)
;
End
if
;
-- grise la nouvelle colonne de recherche --
Set_Item_Property(
:CTRL.COL_RECH, VISUAL_ATTRIBUTE, 'VA_COL_SELECT'
)
;
END
;
La colorisation des items s'effectue via la définition d'un attribut visuel
- Active le temporisateur
-- Init du timer --
Init_timer ;
Le temporisateur est utilisé pour lancer l'exécution de la requête (execute_query) à un intervalle de temps exprimée en millisecondes, lue depuis la variable de package (PKG_GESTION_LOV.GN$Duree_Timer) afin de pouvoir être adaptée au plus juste de votre configuration.
Par défaut elle est de 800 millisecondes, ce qui permet à l'utilisateur de saisir plusieurs caractères avant le déclenchement du query
Le timer reste actif tant que le focus se trouve dans le champ de saisie (:CTRL.P1) et désactivé dès que l'on en sort
Lorsque le temporisateur est actif, le trigger de niveau forme WHEN-TIMER-EXPIRED se déclenche et exécute le code suivant :
Begin
If
:CTRL.P1 is
not
null
Then
if
:CTRL.P1 <>
nvl
(
:CTRL.PSAUV,'_'
)
Then
:CTRL.PSAUV :=
:CTRL.P1;
Execute_recherche ;
End
if
;
End
if
;
End
;
Pour lancer la recherche on vérifie que le champ de saisie n'est pas NULL et que sa valeur a été modifiée depuis le précédent query
Il faut noter que lorsque que l'on enclenche le mode Recherche globale, le temporisateur est désactivé puisque le query est déclenché manuellement par l'utilisateur lors de la frappe de la touche Tab ou Enter
Voici le code du trigger (WHEN-CHECKBOX-CHANGED) attaché à la boite à cocher :
If
:CTRL.RECHERCHE =
1
Then
-- recherche multicolonne --
Init_timer(
FALSE
)
; -- désactivation du timer --
:CTRL.P1 :=
''
; -- on vide le champ de saisie --
:CTRL.ACTION
:=
'W'
; -- word index --
Else
-- recherche monocolonne --
:CTRL.P1 :=
:CTRL.PSAUV ; -- on réalimente le champ de saisie avec l'ancienne valeur--
:CTRL.ACTION
:=
'N'
; -- recherche approchée --
Init_timer(
TRUE
)
; -- réactivation du timer --
End
if
;
go_item(
'CTRL.P1'
)
;
- Prérenseigne le champ de saisie en fonction du paramètre transmis et se positionne
-- Item de sélection des valeurs --
If
:PARAMETER.AUTO_SELECT =
'O'
Then
:CTRL.P1 :=
'%'
;
End
if
;
Go_item(
'CTRL.P1'
)
;
Si le développeur a configuré cette LOV pour afficher la sélection dès l'apparition de l'écran, on prérenseigne le champ de saisie avec le caractère %, sinon l'écran attend que l'utilisateur frappe un caractère pour lancer la recherche
Dimentionnement d'une colonne
Le choix de l'option Dimension du menu popup exécute la fonction Redim_colonne().
Celle-ci positionne (Set_Item_Property( …, X_POS/Y_POS) )et rend visible les boutons + et - en bas de la colonne concernée (Set_Item_Property ( …, VISIBLE, PROPERTY_TRUE ) ;)
Si l'utilisateur décide d'agrandir la colonne, un clic sur le bouton + exécute le code suivant :
Declare
LN
$T PLS_INTEGER
:=
Get_Item_Property(
:GLOBAL
.COLONNE, WIDTH )
;
LC$Col VARCHAR2
(
30
)
;
Begin
-- redimensionnement de la colonne --
-- plus 10 pixels --
If
LN
$T <
300
Then
LN
$T :=
LN
$T +
10
;
Set_Item_Property(
:GLOBAL
.COLONNE, WIDTH, LN
$T )
;
LC$Col :=
Substr
(
:GLOBAL
.COLONNE, instr
(
:GLOBAL
.COLONNE, '.'
)
+
1
, 30
)
;
Maj_Taille_Colonne(
LC$Col, LN
$T )
;
Dessine_colonnes ;
End
if
;
End
;
La taille de l'item est augmentée de 10 points, la procédure Maj_Taille_Colonnes() est invoquée pour mettre à jour les infos de la colonne sauvegardées dans le bloc caché BL_COL, puis l'écran est redessiné via la procédure Dessine_colonnes()
Lorsque l'utilisateur clique à l'extérieur d'un des deux boutons, ceux-ci sont masqués via le trigger de niveau forme WHEN-MOUSE-CLICK
-- Effacer les boutons de dimensionnement --
If
Nvl
(
:system.mouse_item,'_'
)
not
in
(
'CTRL.MOINS'
,'CTRL.PLUS'
)
Then
Set_Item_Property(
'CTRL.PLUS'
, VISIBLE, PROPERTY_FALSE )
;
Set_Item_Property(
'CTRL.MOINS'
, VISIBLE, PROPERTY_FALSE )
;
End
if
;
Sélection d'une valeur et retour à l'écran d'appel
Pour sélectionner une valeur, l'utilisateur clique sur la ligne de la liste puis sur le bouton Ok ou double clique sur la ligne, déclenchant l'appel de la procédure Selection_valeur(), dont voici le code :
PROCEDURE
Selection_valeur IS
LR_COL_LOV PKG_GESTION_LOV.TYPE_REC_LOV ;
Begin
-- Ligne selectionnee --
Go_block(
'BLOC2'
)
;
If
:system.record_status =
'QUERY'
Then
-- si la ligne n'est pas vide
-- RAZ des variables de retour --
PKG_GESTION_LOV.RAZ_Valeurs_LOV ;
LR_COL_LOV.COl1 :=
:BLOC2.COL1 ;
LR_COL_LOV.COl2 :=
:BLOC2.COL2 ;
LR_COL_LOV.COl3 :=
:BLOC2.COL3 ;
LR_COL_LOV.COl4 :=
:BLOC2.COL4 ;
LR_COL_LOV.COl5 :=
:BLOC2.COL5 ;
LR_COL_LOV.COl6 :=
:BLOC2.COL6 ;
LR_COL_LOV.COl7 :=
:BLOC2.COL7 ;
LR_COL_LOV.COl8 :=
:BLOC2.COL8 ;
LR_COL_LOV.COl9 :=
:BLOC2.COL9 ;
-- Mise à jour des variables de retour --
PKG_GESTION_LOV.MAJ_Valeurs_LOV(
LR_COL_LOV )
;
Exit_form(
NO_VALIDATE )
;
Else
Go_Item(
'CTRL.P1'
)
;
End
if
;
End
;
Les variables de retour, stockées dans le package sont d'abord effacées, puis valorisées avec celles de la ligne sélectionnée, permettant à l'écran d'appel de les traiter.
3. L'écran de gestion des LOV (INIT_LOV.FMB)▲
Il présente la liste des modules, blocs et items de votre application
Ces informations sont automatiquement enregistrées en table pour chacun de vos modules grâce à l'appel de procédure Init_referentiel_lov() qui se trouve en commentaire dans chaque trigger WHEN-NEW-FORM-INSTANCE
Pour renseigner l'ensemble de ces informations, il suffit de retirer le commentaire, exécuter le module, quitter et remettre le commentaire
En regard de chaque composant : module, bloc et item, vous pouvez saisir un libellé
Le canvas inférieur contient 3 onglets
Un onglet Items qui affiche la liste des items du bloc et du module sélectionné, un libellé libre ainsi qu'un rappel du format appliqué sur l'item
Un onglet LOV qui permet de définir les propriétés de la LOV attachée à l'item sélectionné
Nom table permet de définir le nom d'une table qui servira à la recherche globale
Validation permet de définir si la LOV doit servir a valider l'item en saisie
Auto select permet de définir si la LOV affichera la liste de sélection dès son affichage
PosX et PosY, facultatifs, permettent de positionner la LOV
Titre de la LOV permet d'indiquer le titre
Select reçoit la partie Select de la requête (sans le mot clé Select)
From reçoit la partie From de la requête (sans le mot clé From)
Where (facultatif) reçoit la partie Where de la requête (sans le mot clé Where)
Order by (facultatif) reçoit la partie Order by de la requête (sans le mot clé Order by)
La case à cocher Ok non modifiable indique si la LOV est valide et donc accessible à l'utilisateur
Tant que cette LOV n'est pas valide, elle ne sera ni visible ni utilisable pour l'utilisateur
Le bouton Afficher l'ordre select permet de visualiser la requête complète
Le bouton Contrôle de la syntaxe permet de vérifier la cohérence de la requête, d'alimenter les colonnes de l'onglet Colonnes LOV
Tant que vous n'avez pas la certitude que votre LOV s'exécutera correctement, il est inutile de répondre Oui pour la reconstruction des correspondances de colonne
(Cette opération remplace les définitions de colonnes de cette LOV dans la table LOV_ELEMENT_COLONNE et par conséquent les réglages utilisateurs éventuellement sauvegardés)
Et d'afficher dans une LOV native le résultat de la requête
Nous n'avons utilisé pour cela qu'un unique groupe d'enregistrement et une unique LOV native !
Pourtant nous pouvons représenter n'importe quelle LOV de 2 à 9 colonnes…
Dans cet exemple, nos 3 colonnes sont correctement affichées, dimensionnées et titrées
L'onglet Colonnes LOV permet de configurer chaque colonne de la LOV
Ordre permet d'ordonner l'affichage par défaut des colonnes
Colonne contient le nom de la colonne
Item de réception reçoit l'item qui devra recevoir la valeur de cette colonne
Rech permet de définir la colonne de recherche par défaut
Val permet de définir la colonne qui servira à valider l'item
(Les LOV natives de Forms ne permettent d'utiliser que la première colonne pour la validation des items. Ici, vous pouvez sélectionner n'importe laquelle)
Taille permet de définir la largeur d'affichage en caractères
Libellé colonne LOV permet de définir le libellé tel qu'il apparaîtra dans la LOV
Clause permet de définir une clause restrictive sur la colonne. Cette clause peut contenir une référence à un autre item de la forme (Placeholder). Dans ce cas, il doit se conformer à la syntaxe Forms :bloc.item (par exemple >2 ou bien = :bloc.item, ou n'importe quel ordre sql pouvant apparaître dans la clause Where)
Valeur de test permet de saisir la valeur de remplacement du placeholder (uniquement pour la validation de la LOV)
Rentrons dans le détail
La procédure Init_referentiel_lov(),présente dans le trigger WHEN-NEW-FORM-INSTANCE permet d'initialiser pour chaque forme les items qui la compose (cette procédure se trouve dans la librairie Forms LOV.PLL)
Le nom du module (Name_in( 'system.current_form' )) est enregistré dans la table LOV_MODULE
Begin
Insert
into
LOV_MODULE
(
NOM_MODULE
,LIBELLE
)
Values
(
LC$Module
,Null
)
;
Exception
When
DUP_VAL_ON_INDEX then
Null
;
End
;
Le traitement de l'exception DUP_VAL_ON_INDEX permet de faire l'économie d'un Select pour vérifier si l'item existe déjà.
On sélectionne le premier bloc de la forme avec l'instruction :
LC$Block
:=
Get_Form_Property(
LC$Module
, FIRST_BLOCK )
;
Et l'on boucle sur tous les blocs
While
LC$Block
is
not
null
Loop
-- pour chaque block --
Le nom du bloc est enregistré dans la table LOV_BLOCK
Begin
Insert
into
LOV_BLOCK
(
MOD_NOM_MODULE
,NOM_BLOCK
)
Values
(
LC$Module
,LC$Block
)
;
Exception
When
DUP_VAL_ON_INDEX then
Null
;
End
;
On se positionne sur le premier item du bloc avec l'instruction suivante :
LC$Item :=
Get_Block_Property(
LC$BLOCK
, FIRST_ITEM )
;
Puis l'on boucle sur tous les items de ce bloc
While
LC$Item is
not
null
Loop
-- Pour chaque item
On rejette les items de type BUTTON ou de type LONG
If
Get_Item_Property(
LC$Bitem, ITEM_TYPE )
<>
'BUTTON'
Then
LC$Type
:=
Get_Item_Property(
LC$Bitem, DATATYPE )
;
If
LC$Type
<>
'LONG'
Then
Le libellé de l'item est issu de son prompt
LC$Prompt
:=
Substr
(
Get_Item_Property(
LC$Bitem, PROMPT_TEXT )
, 1
, 80
)
;
Le format est également sauvegardé
LC$Format
:=
Get_Item_Property(
LC$Bitem, FORMAT_MASK )
;
Il servira à mettre en conformité de format la valeur de retour de la LOV
Et l'on enregistre chaque item dans la table LOV_ITEM
Begin
Insert
into
LOV_ITEM
(
MODULE
,BLOC
,ITEM
,LIBELLE
,ID
,ITEM_TYPE
,FORMAT
)
Values
(
LC$Module
,LC$Block
,LC$Item
,LC$Prompt
,SEQ_ITEM.NEXTVAL
,Decode
(
LC$Type
, 'CHAR'
, 'C'
, 'DATE'
, 'D'
, 'N'
)
,LC$Format
)
;
Exception
When
DUP_VAL_ON_INDEX then
Null
;
End
;
Un seul groupe d'enregistrement et une seule LOV native pour simuler n'importe quelle LOV de 2 à 9 colonnes ?
Comment cela fonctionne-t-il ?
Pour cela nous allons utiliser un groupe d'enregistrement construit dynamiquement
Si l'on peut construire dynamiquement un groupe d'enregistrement, il n'en va pas de même pour une LOV native
Celle-ci doit exister physiquement dans la forme
Puisque nous nous autorisons à gérer des LOV de 2 à 9 colonnes, il faut donc disposer d'une LOV native composée de 9 colonnes à laquelle nous associerons ensuite le groupe d'enregistrements, qui sera lui-même composé de 9 colonnes
Une LOV native LV_SYNTAXE est donc créée dans la forme composée de 9 colonnes COL1, COL2,...,COL9
Si la requête fait référence à moins de 9 colonnes, des colonnes NULL seront ajoutées au groupe d'enregistrement pour coïncider avec la LOV native de contrôle d'une part, et la procédure stockée qui renseigne également 9 colonnes d'autre part
Ouvrons la procédure Check_sql_order() du module INIT_LOV.FMB
Définissons une variable de type record_group
rg_name VARCHAR2
(
40
)
:=
'RG_SYNTAXE2'
;
rg_id RecordGroup;
Reconstituons l'ordre SQL complet et jetons-le en pâture au paquetage Oracle DBMS_SQL
------------------------------------------
-- Verifie que l'ordre SQL est conforme --
------------------------------------------
--
LC$Req :=
'Select '
||
CHR
(
10
)
||
:BL_LOV.ORDRE ||
CHR
(
10
)
||
' From '
||
CHR
(
10
)
||
:BL_LOV.FROM
;
If
:BL_LOV.FILTRE is
not
null
Then
LC$Req :=
LC$Req ||
CHR
(
10
)
||
' Where '
||
CHR
(
10
)
||
:BL_LOV.FILTRE ;
End
if
;
If
:BL_LOV.T_ORDERBY is
not
null
Then
LC$Req :=
LC$Req ||
CHR
(
10
)
||
' Order BY '
||
CHR
(
10
)
||
:BL_LOV.T_ORDERBY ;
End
if
;
LC$Req :=
Rtrim
(
LC$Req, ';'
)
;
Begin
c :=
dbms_sql.open_cursor;
dbms_sql.parse(
c,LC$Req, 1
)
;
d :=
dbms_sql.execute
(
c)
;
Exception
When
others
Then
dbms_sql.close_cursor(
c)
;
:BL_LOV.OK :=
'N'
;
Set_Alert_Property(
'AL_ERREUR'
, TITLE, 'Contrôle de l''ordre SQL'
)
;
Set_Alert_Property(
'AL_ERREUR'
, ALERT_MESSAGE_TEXT, 'Ordre SQL incorrect'
)
;
LN
$Cpt :=
Show_Alert(
'AL_ERREUR'
)
;
Raise
form_trigger_failure ;
End
;
dbms_sql.describe_columns2(
c, col_cnt, rec_tab)
;
dbms_sql.close_cursor(
c)
;
Si la requête ne franchit pas cette étape, c'est qu'elle est incorrecte
Nous rejetons également les colonnes de type LONG, LONGRAW, RAW et les LOBs
LB$Ret :=
TRUE
;
For
i IN
rec_tab.first
.. rec_tab.last
Loop
If
rec_tab(
i)
.col_type IN
(
8
,23
,24
,113
,114
)
Then
Set_Alert_Property(
'AL_ERREUR'
, TITLE, 'Contrôle de l''ordre SQL'
)
;
Set_Alert_Property(
'AL_ERREUR'
, ALERT_MESSAGE_TEXT, rec_tab(
i)
.col_name
||
' Colonnes LONG, LONGRAW, RAW, BLOB, BFILE non autorisées'
)
;
LN
$Cpt :=
Show_Alert(
'AL_ERREUR'
)
;
LB$Ret :=
FALSE
;
End
if
;
End
loop
;
If
not
LB$Ret Then
Raise
form_trigger_failure ;
End
if
;
Nous n'acceptons pas non plus les LOV de moins de 2 colonnes ou de plus de 9 colonnes
If
col_cnt <
2
or
col_cnt >
9
Then
Set_Alert_Property(
'AL_ERREUR'
, TITLE, 'Contrôle de l''ordre SQL'
)
;
Set_Alert_Property(
'AL_ERREUR'
,
ALERT_MESSAGE_TEXT, 'l''ordre SQL doit contenir entre 2 et 9 colonnes'
)
;
LN
$Cpt :=
Show_Alert(
'AL_ERREUR'
)
;
:BL_LOV.OK :=
'N'
;
Raise
form_trigger_failure ;
End
if
;
Nous ajoutons ensuite à la clause where les clauses éventuellement définies au niveau de chaque colonne de l'onglet Colonnes LOV
L'extraction des colonnes de la partie Select de l'ordre, ainsi que l'ajout éventuel des colonnes NULL manquantes sont réalisés par la procédure Build_Select_line()
Puis nous construisons notre groupe d'enregistrements dynamique à l'aide de la requête stockée dans la variable LC$Req
rg_id :=
Find_Group(
rg_name )
;
IF
Not
Id_Null(
rg_id)
THEN
Delete_group(
rg_id )
;
End
if
;
rg_id :=
Create_Group_From_Query(
rg_name, LC$Req )
;
errcode :=
Populate_Group(
rg_id )
;
Si cette étape est encore franchie et que nous avons répondu Oui à la demande de reconstruction des colonnes de la LOV, l'onglet Colonnes LOV est pré alimenté
Enfin nous associons à notre LOV native le groupe d'enregistrement fraîchement créé
Set_Lov_Property(
'LV_SYNTAXE'
, GROUP_NAME, rg_name )
;
Nous réglons les titre et largeur par défaut des colonnes
-- Mise a jour titre et largeur des colonnes --
For
i IN
rec_tab.first
..rec_tab.last
Loop
-- Titre --
Set_Lov_Column_Property(
'LV_SYNTAXE'
, i, TITLE, rec_tab(
i)
.col_name )
;
-- Largeur --
LN
$Pos :=
30
;
If
rec_tab(
i)
.col_type IN
(
1
,96
)
Then
If
rec_tab(
i)
.col_max_len >
30
Then
LN
$Pos :=
30
;
Else
LN
$Pos :=
rec_tab(
i)
.col_max_len ;
End
if
;
Elsif
rec_tab(
i)
.col_type =
2
Then
If
rec_tab(
i)
.col_precision =
0
Then
LN
$Pos :=
10
;
Else
LN
$Pos :=
rec_tab(
i)
.col_precision ;
End
if
;
Elsif
rec_tab(
i)
.col_type =
12
Then
LN
$Pos :=
12
;
Elsif
rec_tab(
i)
.col_type IN
(
112
,113
)
Then
LN
$Pos :=
30
;
End
if
;
LN
$Pos :=
LN
$Pos *
6
;
Set_Lov_Column_Property(
'LV_SYNTAXE'
, i, WIDTH, LN
$Pos )
;
End
loop
;
Masquons les colonnes inutiles (NULL) en positionnant leur largeur à 0
-- Masquage des colonnes non renseignées --
If
rec_tab.last
<
9
Then
For
i IN
rec_tab.last
+
1
..9
Loop
Set_Lov_Column_Property(
'LV_SYNTAXE'
, i, WIDTH, 0
)
;
End
loop
;
End
if
;
Et affichons la LOV native
LB$Ret :=
Show_Lov(
'LV_SYNTAXE'
)
;
Gestion des LOV
Nous avons défini une LOV sur notre item et vérifié que sa syntaxe est correcte
Que se passe-t-il lorsque l'utilisateur utilise son application ?
Lorsqu'une LOV native est présente sur un item de saisie, la barre d'état affiche l'indication "Liste de valeur…"
Lorsque cette LOV native est surchargée par une LOV générique, elle est automatiquement désactivée car devenue inutile.
Dans ce cas la barre d'état n'indique plus à l'utilisateur la présence d'une LOV disponible !
C'est pourquoi, au lancement de chaque forme, la procédure Init_item_lov() stockée dans la librairie LOV.PLL, est appelée depuis le trigger WHEN-NEW-FORM-INSTANCE
Cette procédure recherche pour l'écran en cours la liste des LOV génériques que vous avez définis, inhibe les éventuelles LOV natives concurrentes en fixant la propriété LOV_NAME à NULL
-- Désactivation de l'éventuelle LOV native --
Set_Item_Property(
LC$Item, LOV_NAME, ''
)
;
Set_Item_Property(
LC$Item, VALIDATE_FROM_LIST, PROPERTY_FALSE )
;
Et indique à l'utilisateur la présence de la LOV en ajoutant (LOV) à la fin du Hint…
C'est la raison pour laquelle il est impératif que la propriété Aide automatique de vos items soit positionnée à OUI !
Lorsqu'il s'agit d'une LOV de validation, l'indicateur (LOVV) est ajouté
L'utilisateur entre dans le champ de saisie et demande l'affichage de la LOV avec les touches Ctrl+L
Le trigger de niveau forme KEY-LISTVAL se déclenche et appelle la procédure Display_lov() stockée dans la librairie LOV.PLL
Celle-ci commence par vérifier qu'une LOV générique a été définie pour cet item
Si elle n'en trouve pas, elle vérifie qu'une LOV native existe et l'exécute. (ce système permet de conserver le fonctionnement des LOV natives que vous n'aurez pas jugé bon de surcharger)
Si elle trouve une LOV générique, elle récupère dans les tables les informations nécessaires, reconstruit la clause where à partir des clauses de colonne éventuellement définies dans l'onglet Colonnes LOV et appelle l'écran de LOV générique GEN_LOV via la procédure Call_gen_lov()
------------------------------
-- Appel de l'écran GEN_LOV --
------------------------------
PROCEDURE
CALL_GEN_LOV
(
PN$Item IN
NUMBER
,
PC$Table
IN
VARCHAR2
,
PC$Select
IN
VARCHAR2
,
PC$From
IN
VARCHAR2
,
PC$Where
IN
VARCHAR2
,
PC$Orderby IN
VARCHAR2
,
PC$Affiche IN
VARCHAR2
,
PN$PosX IN
NUMBER
,
PN$PosY IN
NUMBER
,
PC$Titre IN
VARCHAR2
)
IS
pl_id ParamList;
pl_name VARCHAR2
(
10
)
:=
'gen_lov'
;
BEGIN
-- Création de la liste de paramètres --
pl_id :=
Get_Parameter_List(
pl_name)
;
IF
NOT
Id_Null(
pl_id)
THEN
Destroy_Parameter_List(
pl_id)
;
End
if
;
pl_id :=
Create_Parameter_List(
pl_name)
;
IF
Id_Null(
pl_id)
THEN
Message(
'Erreur de création de liste de paramètres '
||
pl_name)
;
RAISE
Form_Trigger_Failure;
END
IF
;
-- Ajout des paramètres à la liste --
Add_Parameter(
pl_id,'UTI_ID'
,TEXT_PARAMETER, Name_in(
'PARAMETER.UTI_ID'
))
;
Add_Parameter(
pl_id,'ITEM_ID'
,TEXT_PARAMETER, PN$Item)
;
Add_Parameter(
pl_id,'PM$TABLE'
,TEXT_PARAMETER, PC$Table
)
;
Add_Parameter(
pl_id,'P_SELECT'
,TEXT_PARAMETER, PC$Select
)
;
Add_Parameter(
pl_id,'P_FROM'
,TEXT_PARAMETER, PC$From
)
;
Add_Parameter(
pl_id,'P_WHERE'
,TEXT_PARAMETER, PC$Where
)
;
Add_Parameter(
pl_id,'P_ORDERBY'
,TEXT_PARAMETER, PC$Orderby)
;
Add_Parameter(
pl_id,'TITRE'
,TEXT_PARAMETER, PC$Titre)
;
Add_Parameter(
pl_id,'AUTO_SELECT'
,TEXT_PARAMETER, PC$Affiche)
;
Add_Parameter(
pl_id,'POSX'
,TEXT_PARAMETER, PN$PosX)
;
Add_Parameter(
pl_id,'POSY'
,TEXT_PARAMETER, PN$PosY)
;
-- Appel de l'écran LOV générique --
CALL_FORM(
'GEN_LOV'
, NO_HIDE, DO_REPLACE, QUERY_ONLY, pl_id)
;
END
;
GEN_LOV est le nom de la forme appelée
NO_HIDE indique de ne pas masquer la forme appelante
DO_REPLACE remplace le menu de la forme appelante
QUERY_ONLY place l'écran appelé en mode non modifiable
pl_id est le nom de la liste des paramètres
Au retour, elle place les valeurs sélectionnées dans les différents items définis également dans l'onglet Colonne LOV
------------------------------
-- Récupération des valeurs --
------------------------------
T_VALEURS :=
PKG_GESTION_LOV.GET_Valeurs_LOV ;
-- Valorisation des items de retour --
If
Tab_col.first
is
not
null
Then
For
i IN
Tab_col.first
..Tab_col.last
Loop
If
Tab_col(
i)
.bloc_item_retour is
not
null
Then
Case
i
When
1
Then
LC$Valeur :=
T_VALEURS.col1 ;
When
2
Then
LC$Valeur :=
T_VALEURS.col2 ;
When
3
Then
LC$Valeur :=
T_VALEURS.col3 ;
When
4
Then
LC$Valeur :=
T_VALEURS.col4 ;
When
5
Then
LC$Valeur :=
T_VALEURS.col5 ;
When
6
Then
LC$Valeur :=
T_VALEURS.col6 ;
When
7
Then
LC$Valeur :=
T_VALEURS.col7 ;
When
8
Then
LC$Valeur :=
T_VALEURS.col8 ;
When
9
Then
LC$Valeur :=
T_VALEURS.col9 ;
End
case
;
If
LC$Valeur is
not
Null
Then
-- Copie de la valeur dans l'item --
Copy(
LC$Valeur, Tab_col(
i)
.bloc_item_retour )
;
End
if
;
End
if
;
End
loop
;
End
if
;
4. L'écran de test TEST_LOV.FMB▲
Une LOV générique a été définie sur l'item Date entrée
Pour tester la LOV et le retour des valeurs nous allons appeler la LOV depuis le champ Date entrée du premier enregistrement (CLARK)
Et sélectionner la ligne correspondant à Duboudin dont nous devrions récupérer la date d'entrée
Ce qui est bien le cas.
LOV de validation
Pour le cas particulier de l'utilisation des LOV génériques pour la validation des items, c'est cette fois le trigger de niveau forme WHEN-VALIDATE-ITEM qui entre en jeu
Ce trigger vérifie qu'une LOV générique est définie puis exécute la procédure Validate_Lov()
If
Instr
(
Get_Item_Property(
:system.trigger_item, HINT_TEXT )
, '(LOVV)'
)
>
0
Then
Validate_Lov ;
End
if
;
La requête est constituée de la manière suivante :
-- Constitution du Select --
LC$Ordre :=
'Select 1 From DUAL Where exists(Select '
;
If
Tab_col.first
is
not
null
Then
For
i IN
Tab_col.first
..Tab_col.last
Loop
If
Tab_col(
i)
.fl_val =
'O'
Then
-- Colonne de validation --
LC$Colonne :=
Tab_col(
i)
.colonne ;
LN
$ColType :=
Tab_col(
i)
.col_type ;
LC$Format
:=
Trim
(
Tab_col(
i)
.format
)
;
LC$Ordre :=
LC$Ordre ||
Tab_col(
i)
.colonne ;
exit
;
End
if
;
End
loop
;
End
if
;
Mise en conformité de format de la valeur à contrôler
-- Valeur du champ a controler --
LC$Champ :=
Name_In(
Name_In(
'system.cursor_item'
)
)
;
If
LN
$Coltype =
12
Then
-- Type DATE --
If
LC$Format
is
null
Then
LC$Champ :=
''''
||
LC$Champ ||
''''
;
Else
-- Format défini au niveau de l'item --
forms_ddl(
'ALTER SESSION SET NLS_DATE_FORMAT = '''
||
LC$Format
||
''''
)
;
LC$Champ :=
''''
||
To_char
(
To_date
(
LC$Champ, 'DD/MM/YYYY HH24:MI:SS'
)
,LC$Format
)
||
''''
;
End
if
;
Elsif
LN
$Coltype In
(
1
,96
)
Then
-- Type CHAR --
LC$Champ :=
''''
||
LC$Champ ||
''''
;
End
if
;
Ajout des clauses finales
-- Constitution du filtre --
If
LC$Where
is
not
null
Then
LC$Filtre :=
' Where '
||
LC$Where
;
End
if
;
IF
LC$Clause is
not
null
Then
LC$Filtre :=
LC$Filtre ||
' '
||
LC$Clause ;
End
if
;
If
Instr
(
Upper
(
LC$Filtre)
, 'WHERE'
)
>
0
Then
LC$Filtre :=
LC$Filtre ||
' And '
||
LC$Colonne ||
' = '
||
LC$Champ ;
Else
LC$Filtre :=
LC$Filtre ||
' Where '
||
LC$Colonne ||
' = '
||
LC$Champ ;
End
if
;
LC$Ordre :=
LC$Ordre ||
' FROM '
||
LC$From
||
LC$Filtre ||
')'
;
Et enfin soumission à la procédure stockée PKG_GESTION_LOV.Controle_Valeur
-- Test de la valeur --
If
PKG_GESTION_LOV.Controle_Valeur(
LC$Ordre )
=
0
Then
-- Valeur non trouvée appel de la LOV--
Affiche_lov ;
End
if
;
Un retour à zéro indique qu'aucune correspondance n'est trouvée et la LOV générique est affichée
Attention. Le trigger de niveau forme WHEN-VALIDATE-ITEM ne se déclenchera qu'après un trigger identique de niveau plus bas (bloc ou item).Si vous avez défini ce type de trigger sur l'item, il sera peut-être nécessaire de définir sa propriété Ordre d'exécution à la valeur Après (After)
5. Le paquetage PKG_GESTION_LOV▲
Il est constitué des variables globales et fonctions publiques suivantes
CREATE
OR
REPLACE
PACKAGE
Pkg_Gestion_Lov
AUTHID CURRENT_USER
IS
/*----------------------------------------*/
/* TYPES */
/*----------------------------------------*/
-- based-block record type
TYPE
TYPE_REC_LOV IS
RECORD
(
col1 VARCHAR2
(
512
)
,
col2 VARCHAR2
(
512
)
,
col3 VARCHAR2
(
512
)
,
col4 VARCHAR2
(
512
)
,
col5 VARCHAR2
(
512
)
,
col6 VARCHAR2
(
512
)
,
col7 VARCHAR2
(
512
)
,
col8 VARCHAR2
(
512
)
,
col9 VARCHAR2
(
512
)
)
;
-- records collection
TYPE
TYPE_TAB_LOV IS
TABLE
OF
TYPE_REC_LOV INDEX
BY
BINARY_INTEGER
;
-- return values record --
GR_COL_LOV TYPE_REC_LOV ;
-- Record type LOV --
TYPE
TYPE_COL_LOV IS
RECORD
(
LOV_ID LOV_ELEMENT_COLONNE.ID%
TYPE
,
LOV_ITEM LOV_ELEMENT_COLONNE.NOM_ITEM%
TYPE
,
LOV_COD_UTIL LOV_ELEMENT_COLONNE.UTL_ID%
TYPE
,
LOV_COL_TAB LOV_ELEMENT_COLONNE.NOM_COLONNE%
TYPE
,
LOV_POS LOV_ELEMENT_COLONNE.ORDRE%
TYPE
,
LOV_POS_INIT LOV_ELEMENT_COLONNE.ORDRE_INIT%
TYPE
,
LOV_PRECEDENT LOV_ELEMENT_COLONNE.NOM_ITEM_P%
TYPE
,
LOV_SUIVANT LOV_ELEMENT_COLONNE.NOM_ITEM_S%
TYPE
,
LOV_RECH LOV_ELEMENT_COLONNE.FL_RECH%
TYPE
,
LOV_TAILLE LOV_ELEMENT_COLONNE.TAILLE%
TYPE
)
;
-- table de record type LOV --
TYPE
TYPE_TAB_COL_LOV IS
TABLE
OF
TYPE_COL_LOV INDEX
BY
BINARY_INTEGER
;
-- Durée d'attente du timer en millisecondes --
GN$Duree_timer NUMBER
(
5
)
:=
800
;
-- Help screens path --
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --
-- Replace with your own machine/port/virtual directory --
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --
GC$Help_Path VARCHAR2
(
256
)
:=
'http://machine:port/forms90/html'
;
-- procedure d enregistrement des colonnes LOV --
PROCEDURE
P_Sauv_Col_LOV(
PT_COL_LOV IN
TYPE_TAB_COL_LOV )
;
-- Procedure de RAZ des valeurs de reception LOV --
PROCEDURE
RAZ_Valeurs_LOV ;
-- Procedure de MAJ des valeurs de reception LOV --
PROCEDURE
MAJ_Valeurs_LOV(
PR_COL_LOV IN
TYPE_REC_LOV )
;
-- Fonction de recuperation des valeurs de reception LOV --
FUNCTION
GET_Valeurs_LOV RETURN
TYPE_REC_LOV ;
-- Test de l'existence d'une valeur pour la validation par LOV --
FUNCTION
Controle_valeur (
PC$Select
IN
VARCHAR2
)
RETURN
PLS_INTEGER
;
FUNCTION
Get_Duree_Timer RETURN
NUMBER
;
FUNCTION
Get_Help_Path RETURN
VARCHAR2
;
END
;
Le type TYPE_TAB_LOV définit une table d'enregistrements composés de 9 champs de type Varchar2(512) qui alimentera l'écran GEN_LOV
La procédure P_Sauv_col_Lov permet d'enregistrer les préférences utilisateur
La procédure RAZ_Valeurs_Lov efface le tableau des valeurs de retour
La procédure MAJ_Valeurs_LOV renseigne le tableau des valeurs de retour
La procédure GET_Valeurs_LOV lit le tableau des valeurs de retour
La fonction Controle_Valeur permet de valider un item en vérifiant que la valeur de celui-ci appartient bien à la LOV
La fonction Get_Duree_Timer permet à l'écran GEN_LOV de récupérer le temps d'attente en millisecondes pour le timer.( Vous pouvez donc régler ce délai en fonction de votre environnement dans les spécifications du package sans intervenir dans l'écran GEN_LOV)
La fonction Get_Help_Path permet à l'écran GEN_LOV de récupérer le chemin d'accès aux fichiers d'aide en ligne
6. Liste et mise en place du matériel fourni▲
Copier et décompresser le fichierforms_lov.zip (790 Ko) dans un répertoire de votre station de travail
!!! Lisez le fichier install.htm !!!