Aller au contenu

%TLOOKUP

Chercher dans une table

Cherche une valeur dans une table (un tableau dont le nom commence par TAB) et positionne l'élément courant, ce qui permet de lire au même endroit dans une table jumelle.

Syntaxe

%TLOOKUP(valeur : table {: table-jumelle})
%TLOOKUPLT(valeur : table {: table-jumelle})
%TLOOKUPLE(valeur : table {: table-jumelle})
%TLOOKUPGE(valeur : table {: table-jumelle})
%TLOOKUPGT(valeur : table {: table-jumelle})
valeur
Ce qu'on cherche, du même type que les éléments de la table.
table
La table où chercher. Son nom doit commencer par TAB, sinon la compilation échoue (RNF0597).
table-jumelle
Facultatif : une seconde table, déclarée avec alt(table). Si la valeur est trouvée, son élément courant est positionné au même rang.
Résultat
Un indicateur : *on si la valeur est trouvée, *off sinon. La table (et la table jumelle) désignée sans indice donne ensuite l'élément courant.

À quoi ça sert

Les tables sont l'ancienne façon de regrouper des données de référence chargées avec le programme : une ville et son forfait de port, un seuil et sa remise. On cherche dans la première table, et le taux correspondant est immédiatement lu dans la seconde, sans calculer de position.

Pour un tableau ordinaire, dont le nom ne commence pas par TAB, on utilise %LOOKUP, qui renvoie une position.

Exemple 1 : Forfait de port par ville

**free
// %TLOOKUP : chercher dans une table et lire l'element correspondant d'une table jumelle.
ctl-opt dftactgrp(*no) actgrp(*new);

// Le nom d'une table commence par TAB. Les donnees viennent de la fin du source.
dcl-s tabvill char(12) dim(3) ctdata perrcd(1);
dcl-s tabport packed(5:2) dim(3) alt(tabvill);
dcl-s trouve ind;

trouve = %tlookup('Lyon' : tabvill : tabport);
snd-msg 'Lyon    trouve=' + %char(trouve) + ' port=' + %char(tabport);

trouve = %tlookup('Brest' : tabvill : tabport);
snd-msg 'Brest   trouve=' + %char(trouve) + ' port=' + %char(tabport);

// Ville absente : rien n'est trouve, mais la table garde son element courant.
trouve = %tlookup('Paris' : tabvill : tabport);
snd-msg 'Paris   trouve=' + %char(trouve) + ' port=' + %char(tabport) +
        ' ville=[' + tabvill + ']';

*inlr = *on;
**ctdata tabvill
Montpellier 01250
Lyon        01800
Brest       02450

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Lyon    trouve=1 port=18.00
Brest   trouve=1 port=24.50
Paris   trouve=0 port=24.50 ville=[Brest       ]

La table tabvill est chargée depuis les données à la fin du source (**ctdata) ; tabport est sa jumelle (alt) et se lit dans la même ligne de données : 12 caractères pour la ville, puis 5 chiffres pour le forfait (01800 vaut 18,00). Après un %tlookup réussi, écrire tabport sans indice donne le forfait de la ville trouvée.

Regardez la dernière ligne : pour Paris, absente de la table, l'indicateur est à 0, mais tabport vaut toujours 24,50 et tabvill Brest. C'est le piège décrit plus bas.

Exemple 2 : Tranches de remise avec LE

**free
// %TLOOKUPLE : tranche de remise d'une table triee, lue dans la table jumelle.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s tabseuil packed(7:0) dim(4) ctdata perrcd(1) ascend;
dcl-s tabrem   packed(4:2) dim(4) alt(tabseuil);
dcl-s trouve ind;
dcl-s montant packed(9:2);

montant = 6500.00;
trouve = %tlookuple(montant : tabseuil : tabrem);
snd-msg 'Commande ' + %char(montant) + ' : trouve=' + %char(trouve) +
        ' seuil=' + %char(tabseuil) + ' remise=' + %char(tabrem) + ' %';

montant = 150.00;
trouve = %tlookuple(montant : tabseuil : tabrem);
snd-msg 'Commande ' + %char(montant) + ' : trouve=' + %char(trouve) +
        ' seuil=' + %char(tabseuil) + ' remise=' + %char(tabrem) + ' %';

montant = 98000.00;
trouve = %tlookuple(montant : tabseuil : tabrem);
snd-msg 'Commande ' + %char(montant) + ' : trouve=' + %char(trouve) +
        ' seuil=' + %char(tabseuil) + ' remise=' + %char(tabrem) + ' %';

// GE : premier seuil qui atteint ou depasse le montant.
trouve = %tlookupge(3000.00 : tabseuil);
snd-msg 'GE 3000 : trouve=' + %char(trouve) + ' seuil=' + %char(tabseuil);

*inlr = *on;
**ctdata tabseuil
00000000000
00010000250
00050000500
00200001000

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Commande 6500.00 : trouve=1 seuil=5000 remise=5.00 %
Commande 150.00 : trouve=1 seuil=0 remise=.00 %
Commande 98000.00 : trouve=1 seuil=20000 remise=10.00 %
GE 3000 : trouve=1 seuil=5000

La table des seuils est triée et déclarée ascend. %tlookuple trouve le plus grand seuil inférieur ou égal au montant : 6 500 tombe dans la tranche 5 000 (remise 5 %), 150 dans la tranche 0, 98 000 dans la tranche 20 000 (10 %). Avec %tlookupge(3000 : …), on obtient au contraire le premier seuil qui atteint ou dépasse 3 000, soit 5 000.

Le piège

Quand la valeur n'est pas trouvée, la table garde son élément courant précédent. Le premier exemple le montre : après la recherche de Paris, tabport contient encore le forfait de Brest. Si on lit la table sans avoir testé le résultat, on utilise une valeur qui n'a rien à voir avec la recherche.

Il faut donc toujours écrire if %tlookup(…) avant d'utiliser la table. Le même comportement s'observe avec LE, GE, GT et LT quand rien ne convient.