Aller au contenu

%RANGE

Intervalle de valeurs

Écrit un intervalle (une borne basse et une borne haute) pour tester avec in si une valeur y est comprise, bornes incluses.

Syntaxe

valeur IN %RANGE(bas : haut)
bas
Borne basse, incluse.
haut
Borne haute, incluse. Elle doit être supérieure ou égale à la borne basse.
Résultat
Une plage de valeurs, utilisable à droite d'un in : le test est vrai si la valeur est comprise entre bas et haut, ces deux valeurs comprises.

À quoi ça sert

Remplace le classique montant >= 0 and montant <= 999.99 par une écriture qui se lit d'un coup. Elle est très pratique dans un select pour classer un montant en tranches, ou pour tester qu'une date tombe dans une période.

Exemple 1 : Nombres et dates, bornes incluses

**free
// %RANGE avec IN : une valeur est-elle comprise entre deux bornes (incluses) ?
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s montant packed(9:2);
dcl-s jour    date inz(d'2026-09-30');

montant = 1000;
if montant in %range(0 : 1000);
  snd-msg '1000 est dans 0 a 1000 (borne incluse)';
endif;

montant = 1000.01;
if montant in %range(0 : 1000);
  snd-msg 'faux';
else;
  snd-msg '1000.01 est hors de 0 a 1000';
endif;

if jour in %range(d'2026-07-01' : d'2026-09-30');
  snd-msg 'Le 30/09 est dans le 3e trimestre';
endif;

// Les bornes dans le mauvais ordre : jamais vrai.
montant = 500;
if montant in %range(1000 : 0);
  snd-msg 'faux';
else;
  snd-msg '500 hors de 1000 a 0 (bornes inversees)';
endif;

// Tranches dans un select.
montant = 6500;
select;
  when montant in %range(0 : 999.99);
    snd-msg 'Tranche 1';
  when montant in %range(1000 : 4999.99);
    snd-msg 'Tranche 2';
  when montant in %range(5000 : 99999.99);
    snd-msg 'Tranche 3';
endsl;

*inlr = *on;

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

1000 est dans 0 a 1000 (borne incluse)
1000.01 est hors de 0 a 1000
Le 30/09 est dans le 3e trimestre
500 hors de 1000 a 0 (bornes inversees)
Tranche 3

1 000 est dans l'intervalle 0 à 1 000, mais 1 000,01 n'y est plus. Le 30 septembre est bien dans le troisième trimestre. Si les bornes sont écrites à l'envers (%range(1000 : 0)), le test n'est jamais vrai : 500 est hors de l'intervalle. Enfin, dans un select, chaque when … in %range désigne une tranche.

Exemple 2 : Du texte : ordre EBCDIC et bornes complètes

**free
// %RANGE sur du texte : l'ordre est celui de l'EBCDIC et la comparaison va jusqu'au bout.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s nom char(12);

nom = 'Dupont';
if nom in %range('A' : 'M');
  snd-msg nom + ' : dans A a M';
endif;

// "Martin" est plus grand que "M" : il sort de la plage.
nom = 'Martin';
if nom in %range('A' : 'M');
  snd-msg nom + ' : dans A a M';
else;
  snd-msg nom + ' : hors de A a M';
endif;

// Avec 'MZZZ' comme borne, Martin est dedans.
if nom in %range('A' : 'MZZZ');
  snd-msg nom + ' : dans A a MZZZ';
endif;

// En EBCDIC, les minuscules sont avant les majuscules.
nom = 'dupont';
if nom in %range('A' : 'M');
  snd-msg nom + ' : dans A a M';
else;
  snd-msg nom + ' : hors de A a M';
endif;

*inlr = *on;

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

Dupont       : dans A a M
Martin       : hors de A a M
Martin       : dans A a MZZZ
dupont       : hors de A a M

« Dupont » est entre A et M. « Martin » n'y est pas, alors que sa première lettre est M : le texte est comparé en entier, et « Martin » est plus grand que « M ». Avec la borne « MZZZ », il est dedans. Et « dupont » en minuscules est hors de A à M, car en EBCDIC les minuscules précèdent les majuscules.

Le piège

Pour du texte, la borne haute est un texte complet, pas une lettre. nom in %range('A' : 'M') exclut « Martin » et « Montpellier », qui sont plus grands que « M ». Pour tout ce qui commence par M, il faut une borne comme « MZZZ » (deuxième exemple). Les minuscules sortent aussi de l'intervalle : en EBCDIC, « dupont » est plus petit que « A ».

Autre piège : des bornes inversées ne provoquent aucune erreur, le test est simplement toujours faux.