image gauche logo Clairinfo image droite

Version du : 28/01/2007

TUTORIAL PARADOX POUR WINDOWS

Leçon 7- La programmation des requêtes, la gestion des états

Introduction :

Les leçons précédentes nous ont permis de définir un schéma des données à gérer, nous avons construit les tables dans Paradox puis nous avons construit le menu de notre application et et les écrans permettant de gérer les clients et les produits. Nous allons maintenant nous intéresser aux éditions programmées. Nous allons construire une fiche permettant à l'utilisateur de choisir sa forme d'édition (liste, étiquette...) et ses critères d'extraction.

Créer une nouvelle fiche EdClient.fsl :

- Nous connaissons maintenant la démarche.
- Mettons lui un titre clair comme "Edition des clients"
- Positionnons notre code standard d'ouverture dans la méthode Open

Cette fiche n'aura pas de table dans son modèle relationnel mais de simples champs non définis permettant à l'utilisateur de préciser ses critères d'éditions. Elle pourrait ressembler à ceci :

Il s'agit essentiellement d'une boite contenant un champ non défini de type "liste déroulante" (Combo) avec comme valeurs les diiférentes formes d'éditions souhaitées , par exemple ici :

Liste simplifiée
Liste détaillée
Etiquettes (Avery L7160)

Nous nommons ce champ TypeEdition. Nous avons par ailleurs 3 autres champs non définis classiques et les labels correspondants. Nous nommons ces 3 champs : CodeClient , Nom et CodePostal afin de pouvoir les joindre facilement en OPAL. Enfin, encore 1 combo pour offrir le choix du tri de l'édition avec comme valeur :

Par CodeClient
Par ordre alphabétique

Puis nous trouvons une case à cocher (un des types possibles pour un champ) que nous nommons "Export" et qui est elle aussi un champ non défini. L'objectif est d'offrir la possibillité à l'utilisateur d'exporter la sélection qu'il s'apprête à faire dans un format standard , DBase, que tous les logiciels reconnaissent (notamment Excel). Ce champ a deux valeurs possibles : "O" si la case est cochée et "N" sinon. Ceci se définit dans les propriétés du champ de type Case à cocher (Définir les valeurs, comme pour les listes déroulantes).

Nous avons enfin 2 boutons dont l'un , Annuler, se contente de fermer la fiche avec la méthode close().

Créer une requête dynamiquement par programmation :

- Implantez le code suivant pour le bouton Valider (événement Pushbutton) :

method pushButton(var eventInfo Event)
Var
 R Query
 sCli,sNom,sCp,sSort String
EndVar

;// Vérifications

if TypeEdition.isBlank() then
 msgStop("Attention !","Veuillez choisir une forme d'édition.")
 return
endif

;// Traitement phase 1 extraction

message("Extraction des données...")

if CodeClient<>"" then sCli=CodeClient else sCli="" endif
if Nom<>"" then sNom=Nom else sNom="" endif
if CodePostal<>"" then sCp=CodePostal else sCp="" endif

switch
case TypeTri="Par CodeClient" : sSort="SORT: :App:Client.DB->\"CodeClient\""
case TypeTri="Par ordre alphabétique" : sSort="SORT: :App:Client.DB->\"Nom\""
otherwise : sSort=""
endswitch

R = Query

~sSort

:App:Client.DB | CodeClient | Nom | Adresse1 | Adresse2 | CodePostal |
               | Check ~sCli | Check ~sNom | Check | Check | Check ~sCp |

:App:Client.DB | Ville | Audit | Notes |
               | Check | Check | Check |

EndQuery

if not ExecuteQBE(R,":Priv:Reponse") then
 errorshow("Impossible d'exécuter la requête.")
 return
endif

;// Traitement phase 2 - Exporter la réponse

if Export="O" then

 SetMouseShape(MouseWait)
 message("Export en cours...")

 if not copy(":Priv:Reponse.db",":Priv:Client.dbf") then
  errorshow("L'export du fichier n'a pu se faire.")
 endif

endif

;// Traitement phase 3 - Enregistrer les critères de l'édition

WriteEnvironmentString("CodeClient",sCli)
WriteEnvironmentString("Nom",sNom)
WriteEnvironmentString("CodePostal",sCp)
WriteEnvironmentString("OrdreTri",TypeTri)

;// Traitement phase 4 - Lancer l'édition

message("Edition en cours...")
Lib.open(":App:Lib")

switch
case TypeEdition="Liste simplifiée" :
 Lib.ConstMenu(":App:LCli1")
case TypeEdition="Liste détaillée" :
 Lib.ConstMenu(":App:LCli2")
case TypeEdition="Etiquettes (Avery L7160)" :
 Lib.ConstMenu(":App:EtiqCli")
endswitch

Lib.close()

endmethod

Bon, quelques explications ?

On commence par définir les variables nécessaires. Ici, nouveauté, nous allons utiliser une variable de type Query. Ce type permet de contrôler en OPAL tout ce qui concerne les requêtes QBE (Query By Example / Requête par l'exemple) de Paradox. Précision importante : Paradox peut également gérer les requêtes SQL (Structured Query Language). La technique présentée ici qui consiste à créer par programmation la chaîne de texte du QBE pourrait tout à fait être employée pour construire une requête SQL (également une chaîne texte).

QBE ou SQL that is the question :

Il faut savoir que seul le BDE 32 bit offre 2 parseurs QBE et SQL séparés. (Le parseur est un interpréteur qui convertit la chaîne reçue en primitive d'accès du moteur de base de données). Pour toutes les versions 16 bits (jusqu'à la version 7-16) le SQL était toujours converti en QBE avant d'être transmis au BDE.

Depuis la version 7-32 , Paradox bénéficie donc d'un parseur dédié pour le SQL et effectivement le "SQL Local " du BDE 32 bit permet des choses impossibles en QBE (exemple : appliquer un UPPER dans une requête d'UPDATE pour transformer en majuscules tout ou partie des valeurs d'un champ) mais à l'inverse certaines actions possibles en QBE ne sont pas réalisables en SQL (exemple : recherche partielle sur un mémo en casse insensitive).

Pour résumer sur ce point :

- Vous connaissez déjà le SQL ou vous allez utiliser Paradox comme Accès client à une base de données Client/Serveur (Oracle, DB2,Informix,SQL Serveur,Interbase,MySQL...) ? Autant n'utiliser que le SQL puisque ces serveurs ne comprennent que cela. Dans ce dernier cas le BDE fait l'inverse .Il convertit les instructions QBE en SQL.

- Vous avez des traitements particulièrements longs ? Le mieux est alors de tester les deux types de requêtes pour utiliser le plus performant au coup par coup. Eh oui ! Il n'y a pas vraiment de règle, certaines requêtes sont plus rapides en QBE d'autres en SQL (si les index sont correctement utilisés)...

- Vous débutez sur Paradox et vous ne connaissez pas le langage SQL ? Le QBE est parfait. Simple, très performant. Vous vous y ferez très vite. Si vous souhaitez apprendre le SQL il existe de très nombreuses ressources sur le net. Vous trouverez d'ailleurs sur notre site plusieurs documentations sur SQL.

Puis nous définissons quelques variables String qui vont nous permettre de construire dynamiquement notre QBE. Après avoir vérifié que l'utilisateur a bien spécifié une forme d'édition, nous affectons à nos variables précédentes les éventuelles valeurs saisies dans les champs non définis de la fiche. Cette étape apparemment inutile est nécessaire car les variables utilisées dans les requêtes doivent avoir un type déterminé. Je vous recommande de n'utiliser que le type String pour passer vos paramètres, même pour des dates par exemple. Nous nous assurons que ces variables seront toujours initialisées (éventuellement à blanc, "", si rien n'a été saisi en critère.)

Puis nous nous occupons du tri de la réponse en traitant les différents cas possibles. Remarquez le caractère d'échappement (\) nécessaire pour intégrer un guillemet dans notre chaîne.

Puis vient la requête proprement dite. Le plus magique se passe à ce niveau car vous n'avez pas à taper celle-ci...
En effet le plus simple est souvent de préparer sa requête en interactif dans Paradox puis de la sauvegarder par exemple sous le nom "Essai.qbe". Dans le code il suffit de taper "R = " puis de demander Menu Edition / Coller Depuis , de charger le fichier "Essai.qbe" et de constater le miracle. Paradox vous a intégré la requête sous forme de chaîne de texte. Il ne reste plus qu'à modifier ce qui doit l'être , en l'occurrence, introduire nos paramètres.

Comme vous pouvez le constater il suffit de placer un tilde (~) avant le nom du paramètre et c'est tout, Paradox se chargeant à l'exécution de remplacer le paramètre par sa valeur. Cool non ? Puis nous exécutons la requête en spécifiant le nom de la table réponse souhaitée. Ce point est très important pour éviter tout souci entre les versions françaises et US de Paradox qui ne nomment pas de la même façon la table réponse issue en standard d'une requête de sélection. Rappelez-vous qu'à de rares exceptions près le runtime de Paradox est toujours en version US...

Puis en quelques lignes (une en fait !) nous réalisons un export au format DBase de notre table réponse si l'utilisateur l'a demandé. Magique Paradox !

Sauvegarder les critères d'édition :

Il est important de pouvoir afficher sur les éditions, en plus de la date d'édition et des numéros de page, les critères d'édition spécifiés par l'utilisateur.

Pour cela il existe deux grandes possibilités, l'utilisation d'une petite table dédiée propre à chaque utilsateur, donc dans le répertoire privé ou l'utilisation de variables d'environnement. Cette dernière option est très pratique car elle ne nécessite pas de table supplémentaire. Quant à la syntaxe, difficile de trouver plus simple. Ces variables seront disponibles comme par magie sur nos éditions par un simple champ calculé.

Exemple : ReadEnvironmentString("CodeClient") dans un champ calculé sur une édition permettra d'afficher le critère CodeClient sauvegardé ici.

Ouvrir et contrôler un état à l'écran :

Les lignes suivantes se chargent d'ouvrir l'état souhaité à l'écran mais afin de bien contrôler les menus affichés nous utilisons la fonction ConstMenu de notre bibliothèque (décrite à la leçon 4). Appeler une fonction de notre bibliothèque n'est pas difficile, on ouvre la bibliothèque puis on appelle la méthode en la préfixant par la variable de type Library. Puis on ferme la bibliothèque (on peut aussi la gérer globalement au niveau fiche dans l'open/close).

Rappel : Il convient de déclarer une variable (ici "Lib") de type Library et de déclarer la ou les méthodes que nous allons utiliser dans la fiche dans le bloc uses de la fiche. Personnellement je déclare la variable Lib également au niveau Fiche pour pouvoir facilement accéder à la librairie de n'importe quelle méthode.

A titre d'exercice je vous laisse construire la fiche EdProduit qui offrira le même type de fonctionnalités."Idéalement on duplique la fiche et l'on ne modifie que ce qui change mais évidemment si le but est d'apprendre il vaut mieux tout recréer de zéro..."

Haut de page    Précédent    Suivant

© Copyright 2000-2007 , Clairinfo ® , http://www.clairinfo.fr