8 de mayo de 2013

Procedimiento que convierte un número a letras Oracle

Muchas veces  cuando se esta programando una solución informática surge la necesidad de expresar números en letras, como por ejemplo al presentar el concepto de una factura, de un cheque o sencillamente  leer números en formato literal.

Con el fin de hacer un poco más fácil esta tarea, les dejo el siguiente código en Oracle, el mismo es un procedimiento que convierte un número de entrada en letras. Puede ser modificarlo a su antojo y adaptado a sus necesidades. 

Espero que sea de utilidad a más de uno...


  1 /****************************************************************************/
  2 --PROCESAMIENTO QUE AL PASARLE UN NUMERO COMO PARÁMETRO LO CONVIERTE EN LETRAS
  3 /****************************************************************************/
  4         PROCEDURE PR_NUMEROS_A_LETRAS(
  5                                       numero in number
  6                                       )IS
  7   -----------------------------------------------
  8       --Declaracion de matrices--
  9   -----------------------------------------------
 10   TYPE LECTURA_UNIDADES IS VARRAY(200) OF VARCHAR2(50); 
 11   TYPE LECTURA_DECENAS IS VARRAY(200) OF VARCHAR2(50);
 12   TYPE LECTURA_CENTENAS IS VARRAY(200) OF VARCHAR2(50);
 13   TYPE LECTURA_MILLARES IS VARRAY(200) OF VARCHAR2(50);
 14   -----------------------------------------------
 15       --matriz para las unidades hasta el 19--
 16   -----------------------------------------------  
 17   M_Unidades LECTURA_UNIDADES := LECTURA_UNIDADES(
 18                          'UNO '  ,'DOS '  ,'TRES '
 19                         ,'CUATRO ' ,'CINCO ' ,'SEIS '
 20                         ,'SIETE ' ,'OCHO ' ,'NUEVE '
 21                         ,'DIEZ ' ,'ONCE ' ,'DOCE '
 22                         ,'TRECE ' ,'CATORCE ' ,'QUINCE '
 23                         ,'DIECISÉIS ','DIECISIETE ' 
 24                         ,'DIECIOCHO ','DIECINUEVE '
 25                                                   );
 26   -----------------------------------------------
 27       --matriz para las decenas--
 28   ----------------------------------------------- 
 29   M_Decenas LECTURA_DECENAS    :=  LECTURA_DECENAS(
 30                          'VEINTE ' ,'VEINTI' ,'TREINTA '
 31                         ,'CUARENTA ' ,'CINCUENTA '
 32                         ,'SESENTA ' ,'SETENTA '
 33                         ,'OCHENTA ' ,'NOVENTA '
 34                                         );
 35   -----------------------------------------------
 36       --matriz para las centenas--
 37   ----------------------------------------------- 
 38   M_Centenas LECTURA_CENTENAS     :=  LECTURA_CENTENAS(
 39                         'CIENTO ' ,'DOSCIENTOS ' ,'TRESCIENTOS '
 40                         ,'CUATROCIENTOS ' ,'QUINIENTOS '
 41                         ,'SEISCIENTOS ' ,'SETECIENTOS '
 42                         ,'OCHOCIENTOS ' ,'NOVECIENT0S '
 43                                                       );
 44   -----------------------------------------------
 45     --Declaración de variables--
 46   -----------------------------------------------
 47  millares varchar (50);
 48  letCentenas varchar2(50);
 49  letDecenas varchar2(50);
 50  letUnidades varchar2(50);
 51  texto varchar2(200);
 52  numeroAuxiliar varchar2(100);
 53  longitud_numero numeric;
 54  letras varchar2(200);
 55  grupo varchar2(3);
 56  cantGrupo numeric(1);
 57  decimales varchar2(200);
 58  enTexto varchar2(20);
 59  digitoDecena numeric;
 60  digitoUnidad numeric;
 
 61 BEGIN
 62   -----------------------------------------------
 63   --Inicialización de variables--
 64   ----------------------------------------------- 
 65   cantGrupo := 0;
 66   letras := '';
 67   texto := '';
 68   enTexto:=LTRIM(RTRIM(TO_CHAR(TRUNC(Numero), '999999999999'))); 
 69   enTexto:= LPAD(enTexto,12,'0');
 70   longitud_numero:=LENGTH(enTexto);--obtengo la longitud del numero
 71   --controla que el numero sea menor o igual de 12 posiciones y mayor que cero. 
 72   IF (longitud_numero = 12) AND (numero = 0) THEN
 73    -----------------------------------------------
 74    --divide el numero en cuatro grupos de tres digitos--
 75    ----------------------------------------------- 
 76    FOR I IN 1..TO_NUMBER(longitud_numero)/3 LOOP
 77     --inicializo ciertas variables cada vez que inicia un nuevo ciclo
 78     letUnidades:='';
 79     letDecenas:='';
 80     letCentenas:='';
 81     millares:='';
 82     grupo:= SUBSTR(enTexto,I*3-2,3); --Divido en grupos de tres dígito
 83     --obtenemos un numero auxiliar del grupo
 84     numeroAuxiliar := TO_NUMBER(TO_CHAR(TRUNC(grupo),'999'));
 85     cantGrupo := cantGrupo+1;  --controlamos la cantidad del grupo
 86     digitoDecena := TO_NUMBER(SUBSTR(TO_CHAR(grupo),2,2));--obtengo la decena
 87     digitoUnidad := TO_NUMBER(SUBSTR(TO_CHAR(grupo),3,1));--obtengo la unidad
 88     -----------------------------------------------------
 89     --SI SON CENTENAS EXTRAIGO EL VALOR DE LA CENTENA---
 90     ----------------------------------------------------
 91     IF LENGTH(TO_CHAR(numeroAuxiliar))=3 AND (TO_NUMBER(numeroAuxiliar)<> 0) THEN
 92      IF (numeroAuxiliar = 100) THEN
 93       letras:='CIEN ';
 94      ELSE
 95       letras := M_Centenas(TO_NUMBER(SUBSTR(TO_CHAR(numeroAuxiliar),1,1)));
 96      END IF;
 97      letCentenas := letras;
 98      numeroAuxiliar  := TO_NUMBER(substr(to_char(numeroAuxiliar), 2, 2));
 99     ND IF;
100     -----------------------------------------------------
101     --SI SON DECENAS EXTRAIGO EL VALOR DE LA DECENA------
102     -----------------------------------------------------
103     --obtengo el dígito de la unidad
104     digitoUnidad := TO_NUMBER(SUBSTR(TO_CHAR(numeroAuxiliar),2,1));
105     IF(TO_NUMBER(numeroAuxiliar)<> 0) THEN--si el numero no es cero
106       IF (numeroAuxiliar >= 20) THEN--si el valor es mayor o igual 20
107       --si el numero es igual a 20 asigna el valor de 20 en la matriz decena.
108         IF (numeroAuxiliar = 20) THEN
109           letras:= M_Decenas(TO_NUMBER(SUBSTR(TO_CHAR(numeroAuxiliar),1,1))-1);
110           letDecenas:= letras;
111         ELSE 
112           --si el número esta menor o igual a 29 obtiene la descripción de la 
              --decena y le asgina el valor a letras
113           IF (numeroAuxiliar <= 29) THEN
114             letras:= M_Decenas(TO_NUMBER(SUBSTR(TO_CHAR(numeroAuxiliar),1,1)));
115             letDecenas:= letras;
116             numeroAuxiliar:= TO_NUMBER(SUBSTR(TO_CHAR(numeroAuxiliar),2,3));
117           ELSE 
118             --si la unidad es diferente a cero la "y" entre el valor de la 
                --decena y la unidad
119             IF (digitoUnidad <> 0) THEN
120               letras:= M_Decenas(TO_NUMBER(SUBSTR(TO_CHAR(numeroAuxiliar),1,1)));
121               letDecenas:= letras||'Y ';
122               numeroAuxiliar:= TO_NUMBER(SUBSTR(TO_CHAR(numeroAuxiliar),2,3));
123              ELSE
124                --si es cero imprime solo la decena.
125                letras:= M_Decenas(TO_NUMBER(SUBSTR(TO_CHAR(numeroAuxiliar),1,1)));
126                letDecenas:= letras;
127                numeroAuxiliar:= TO_NUMBER(SUBSTR(TO_CHAR(numeroAuxiliar),2,3));
128              END IF;    
129            END IF;
130          END IF;
131         END IF;
132       END IF;
133      -----------------------------------------------------
134      --SI SON UNIDADES EXTRAIGO EL VALOR DE LA UNIDAD-----
135      -----------------------------------------------------          
136      IF (numeroAuxiliar <> 0) AND (numeroAuxiliar <= 19) THEN
137        IF LENGTH(TO_CHAR(numeroAuxiliar))=1 THEN
138          --Asigna la letra de la unidad al valor correspondiente.      
139          letras:=M_Unidades(TO_NUMBER(SUBSTR(TO_CHAR(numeroAuxiliar),1,1)));
140          letUnidades:=letras;
141        END IF;
142        IF LENGTH(TO_CHAR(numeroAuxiliar))=2 THEN
143          --Asigna la letra de la unidad al valor correspondiente.
144          letras:= M_Unidades(TO_NUMBER(SUBSTR(TO_CHAR(numeroAuxiliar),1,2)));
145          letUnidades:=letras;
146        END IF;
147       END IF;
148       -----------------------------------------------
149       --Controlando las unidades de mil y de millón--
150       -----------------------------------------------
151       IF (cantGrupo = 1) OR (cantGrupo = 3)THEN--si esta en el grupo 1 
            --o en el tres
152         millares := 'MIL';--imprime mil al final
153         IF (TO_NUMBER(GRUPO)= 1) THEN
154           letUnidades:='';-- no imprimo nada en las unidades
155         ELSE
156           IF(digitoUnidad=1)AND (digitoDecena <> 11)THEN
157             letUnidades:='UN ';--imprimo un en los casos indicados anteriormente
158           END IF;
159         END IF;
160         ELSE
161         --si el grupo es dos entonces son millones
162           IF (cantGrupo = 2) THEN
163             IF(TO_NUMBER(grupo) = 1) THEN
164               millares:='MILLÓN';
165               letUnidades:='UN ';
166             ELSE
167               IF(digitoDecena <> 11)AND(digitoUnidad = 1) THEN
168                 millares := 'MILLONES';
169                 letUnidades:='UN ';
170               ELSE
171                 millares:='MILLONES';
172               END IF;
173             END IF;
174           END IF;
175         END IF;
176         -----------------------------------------------------------------
177         --Evaluando cuando el grupo sea cero y en caso de ser lo limpio--
178         -----------------------------------------------------------------
179         IF (cantGrupo = 1) THEN
180           IF (to_number(grupo) = 0) THEN
181             millares:='';
182           END IF;
183         END IF;
184         IF (cantGrupo = 2) THEN
185           IF(to_number(grupo) = 0) THEN
186             letUnidades:='';
187             IF (numero > 999999999) THEN
188               millares:=millares;
189             ELSE
190               millares:='';
191             END IF;
192           END IF;
193         ELSE
194           IF(cantGrupo = 3) THEN
195             IF(to_number(grupo) = 0) THEN
196               millares:='';
197             END IF;
198           END IF;
199         END IF;
200         --voy imprimiendo la lectura de cada grupo
201         letras:=letCentenas||letDecenas||letUnidades||millares;
            --concateno la  lectura a texto por cada ciclo for
202         texto:=texto||' '||letras; 
203       END LOOP;--termina el ciclo
204       -----------------------------------------------------
205       --------------EVALUANDO SI HA DECIMALES--------------
206       -----------------------------------------------------
207       --Sí el número truncado es igual al numero digitado, no hay decimales
208       IF TRUNC(Numero) = Numero THEN
209         decimales := '';
210       ELSE--por lo demás
211       --obtenemos  el decimal y los dígito del decimal
212       decimales := SUBSTR(TO_CHAR(Numero,'999999999999.99'),15,2);
213       digitoDecena := TO_NUMBER(SUBSTR(TO_CHAR(DECIMALES),1,1));
214       digitoUnidad := TO_NUMBER(SUBSTR(TO_CHAR(DECIMALES),2,1));
215       --evalua que sea mayor que 20
216       IF (decimales >=20 ) THEN
217       --si el número es igual a 20 asigna el valor de 20 en la matriz decena.
218         IF (TO_NUMBER(decimales) = 20) THEN
219           letras:= M_Decenas(TO_NUMBER(SUBSTR(TO_CHAR(decimales),1,1))-1);
220           decimales:= letras;
221         ELSE 
222         --Si es menor o igual a 29 asigna la decena mas la unidad
223           IF (TO_NUMBER(decimales) <= 29) THEN
224             letras:= M_Decenas(TO_NUMBER(SUBSTR(TO_CHAR(decimales),1,1)))||
225             M_Unidades(TO_NUMBER(SUBSTR(TO_CHAR(digitoUnidad),1,1)));
226             decimales:= letras;
227           ELSE
228           --si la unidad es distinta a cero concatena la decena más el 
              --conector "y" más la unidad
229            IF (digitoUnidad <> 0) THEN
230              letras:= M_Decenas(TO_NUMBER(SUBSTR(TO_CHAR(decimales),1,1)));
231              decimales:= letras||'Y '|| 
                 M_Unidades(TO_NUMBER(SUBSTR(TO_CHAR(digitoUnidad),1,1)));
232            ELSE
233              --si es cero imprime solo la decena.
234              letras:= M_Decenas(TO_NUMBER(SUBSTR(TO_CHAR(decimales),1,1)));
235              decimales:= letras;
236            END IF;    
237          END IF;
238        END IF;
239      ELSE
240        decimales := M_Unidades(TO_NUMBER(SUBSTR(TO_CHAR(decimales),1,2)));
241      END IF;
242      decimales := 'CON '||decimales||' /00';
243    END IF;
244    -- Une los decimales al valor de devuelto
245    texto := texto || Decimales;          
246    DBMS_OUTPUT.PUT_LINE(texto);
247  ELSE
248    DBMS_OUTPUT.PUT_LINE('NUMERO FUERA DE RANGO');
249  END IF;
250  EXCEPTION
251     WHEN OTHERS THEN
252       dbms_output.put_line('IMPOSIBLE CONVERTIR EL NO.'||enTexto);
253 END PR_NUMEROS_A_LETRAS;

No hay comentarios:

Publicar un comentario