1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
| CREATE OR REPLACE FUNCTION STO_F_TRANSFO_EAN128( chaine IN VARCHAR2)
RETURN VARCHAR2
IS
/* Fonction pour transformer une chaine de caractere en chaine code 128 en PL/SQL */
/* Traduction de la fonction VB de Grandzebu par Nicolas Fanchamps en PL/SQL */
ind INT := 1; /* Indice d'avancement dans la chaine de caractère */
checksum INT; /* Caractère de vérification de la chaine codée */
mini INT; /* nbr de caractères numériques en suivant */
dummy INT; /* Traitement de 2 caractères à la fois */
tableB BOOLEAN; /* Booleen pour vérifier si on doit utiliser la table B du code 128 */
code128 VARCHAR2(100); /* Chaine codée */
longueur INT; /* Longueur de la chaine à coder pour valeur max de la boucle */
BEGIN
code128 := '';
longueur := LENGTH(chaine);
--###############################################
--# Première partie : vérification de la chaine #
--###############################################
IF longueur IS NULL
THEN
RETURN ('Chaine vide!!!');
ELSE --Vérification de la validité de la chaine
FOR ind IN 1 .. longueur
LOOP
IF ASCII(SUBSTR(chaine, ind, 1)) < 32
OR ASCII(SUBSTR(chaine, ind, 1)) > 126
THEN
RETURN ('Chaine invalide!!!');
END IF;
END LOOP;
END IF;
--##############################################
--# Deuxieme partie : encodage de la chaine en #
--# optimisant l'usage des table B et C #
--##############################################
tableB := TRUE;
WHILE ind <= longueur
LOOP
IF tableB = TRUE
THEN
--Voir si c'est intéressant de passer en table C
--Oui pour 4 chiffres au début ou a la fin, sinon pour 6 chiffres (repassage en B)
IF ind = 1 OR ind + 3 = longueur
THEN mini := 4;
ELSE mini := 6;
END IF;
--TestNum : si les caractères à partir de ind sont numériques, alors on passe en table C
IF LENGTH(SUBSTR(chaine, ind))
- NVL( LENGTH(LTRIM(SUBSTR(chaine, ind), '0123456789')),0) >= mini
THEN
IF ind = 1
THEN --Débuter sur la table C
code128 := CHR(205);
ELSE --Commuter sur la table C
code128 := code128 || CHR(199);
END IF;
tableB := FALSE;
ELSE
IF ind = 1
THEN --Débuter sur la table B
code128 := CHR(204);
END IF;
END IF;
END IF;
IF tableB = FALSE
THEN --On est sur la table C, on va essayer de traiter 2 chiffres
IF LENGTH(SUBSTR(chaine, ind))
- NVL( LENGTH(LTRIM(SUBSTR(chaine, ind), '0123456789')),0) >= 2
THEN --OK Pour 2 chiffres, les traiter
dummy := TO_NUMBER(SUBSTR(chaine, ind, 2));
IF (dummy < 95)
THEN
dummy := dummy + 32;
ELSE
dummy := dummy + 100;
END IF;
code128 := code128 || CHR(dummy);
ind := ind + 2;
ELSE
--On n'a pas deux chiffres, retourner en table B
code128 := code128 || CHR(200);
tableB := TRUE;
END IF;
END IF;
IF tableB = TRUE
THEN
code128 := code128 || SUBSTR(chaine, ind, 1);
ind := ind + 1;
END IF;
END LOOP;
--Calcul de la clef de controle
FOR ind IN 1 .. LENGTH(code128)
LOOP
dummy := ASCII(SUBSTR(code128, ind, 1));
IF dummy < 127
THEN dummy := dummy - 32;
ELSE dummy := dummy - 100;
END IF;
IF ind = 1
THEN checksum := dummy;
END IF;
checksum := MOD(checksum + (ind-1) * dummy, 103);
END LOOP;
--Calcul du code ascii de la clef de controle
IF checksum < 95
THEN checksum := checksum + 32;
ELSE checksum := checksum + 100;
END IF;
--Ajout de la clef et du STOP a la fin de la chaine codée
code128 := code128 || CHR(checksum) || CHR(206);
RETURN code128;
END;
/ |
Partager