Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Firebird e Interbase
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 02-12-2011
[birmain] birmain is offline
Miembro Premium
 
Registrado: feb 2005
Ubicación: Albacete - España
Posts: 49
Poder: 0
birmain Va por buen camino
Aportación del código de un stored procedure para conversión literal de números

Un saludo a todos.
Aunque soy un veterano del Club Delphi apenas tengo intervenciones, puesto que me limito a pasarme de vez en cuando y leer los mensajes, y alguna vez he preguntado algo.
En este momento estoy migrando una aplicación desde FB 1.5 a 2.5.1 en Linux, por lo que me he tenido que plantear la migración de una librería UDF de mi propiedad a linux, recompilandola con Lazarus. Esto me hizo plantearme la conveniencia de seguir por ahí o portar toda esta librería a procedimientos almacenados, puesto que FB 2.5 es un tanto pijotero y estricto, sobre todo con los strings. Mi conclusión ha sido que migraré en su totalidad a procedimientos almacenados, puesto que FB 2.5 trae una buena colección de funciones internas, que facilitan dicha labor.

Como parte de dicha migración he concluido un procedimiento, que se basa a su vez en otro que permite conocer el literal de cualquier número, positivo o negativo, entero o fraccionario, con una determinada precisión (no mayor que 6). Para ello hay dos procedimientos:

1º IUDF_NUMERAL, que admite como parámetro un número entero positivo y devuelve el literal. Este es recursivo, y permite con las cadenas básicas componer cualquier número.

2º IUDF_NUMLITERAL, utiliza el anterior, y permite la entrada de cualquier número decimal de hasta precisión 6, y un parámetro que ajustará la precisión de salida. La salida es un número, positivo o negativo, entero o fraccionario, con la precisión solicitada, en formato literal.

Ahí va un script con el código:

Código SQL [-]

SET NAMES ISO8859_1;

SET CLIENTLIB 'C:\Program Files (x86)\Firebird\Firebird_2_5\bin\fbclient.dll';

CONNECT 'path base datos' USER 'SYSDBA' PASSWORD 'masterkey';

/* Fernando Gallego
   02 Nov 2011
   Albacete - España */



SET TERM ^ ; 



/******************************************************************************/
/***                           Stored Procedures                            ***/
/******************************************************************************/

CREATE PROCEDURE IUDF_NUMERAL (
    NUMERO INTEGER)
RETURNS (
    NUMERAL VARCHAR(500))
AS
BEGIN
  SUSPEND;
END^





CREATE PROCEDURE IUDF_NUMLITERAL (
    NUMERO DECIMAL(15,6),
    PREC SMALLINT)
RETURNS (
    LITERAL VARCHAR(500))
AS
BEGIN
  SUSPEND;
END^






SET TERM ; ^



/******************************************************************************/
/***                           Stored Procedures                            ***/
/******************************************************************************/


SET TERM ^ ;

ALTER PROCEDURE IUDF_NUMERAL (
    NUMERO INTEGER)
RETURNS (
    NUMERAL VARCHAR(500))
AS
declare variable UN varchar(10);
declare variable UNO varchar(10);
declare variable DOS varchar(10);
declare variable TRES varchar(10);
declare variable CUATRO varchar(10);
declare variable CINCO varchar(10);
declare variable SEIS varchar(10);
declare variable SIETE varchar(10);
declare variable OCHO varchar(10);
declare variable NUEVE varchar(10);
declare variable DIEZ varchar(10);
declare variable ONCE varchar(10);
declare variable DOCE varchar(10);
declare variable TRECE varchar(10);
declare variable CATORCE varchar(10);
declare variable QUINCE varchar(10);
declare variable DIECI varchar(10);
declare variable VEINT varchar(10);
declare variable TREINTA varchar(10);
declare variable CUARENTA varchar(10);
declare variable CINCUENTA varchar(10);
declare variable SESENTA varchar(10);
declare variable SETENTA varchar(10);
declare variable OCHENTA varchar(10);
declare variable NOVENTA varchar(10);
declare variable TOS varchar(10);
declare variable CIEN varchar(10);
declare variable CIENTOS varchar(10);
declare variable QUINIENTOS varchar(10);
declare variable SETE varchar(10);
declare variable NOVE varchar(10);
declare variable MIL varchar(10);
declare variable MILLON varchar(10);
declare variable MILLONES varchar(10);
declare variable SONMILES varchar(5);
declare variable Y varchar(5);
declare variable ESPACIO varchar(5);
declare variable RESUL_NUMERAL varchar(500);
declare variable RESUL_NUMERAL_MOD varchar(500);
declare variable RESUL_NUMERAL_DIV varchar(500);
declare variable UN_MILLON integer;
begin
  UN = 'UN';
  UNO = UN || 'O'; DOS = 'DOS'; TRES = 'TRES'; CUATRO = 'CUATRO'; CINCO = 'CINCO';
  SEIS = 'SEIS'; SIETE = 'SIETE'; OCHO = 'OCHO'; NUEVE = 'NUEVE'; NOVE = 'NOVE';
  DIEZ = 'DIEZ'; ONCE = 'ONCE'; DOCE = 'DOCE'; TRECE = 'TRECE';
  CATORCE = 'CATORCE'; QUINCE = 'QUINCE'; Y = ' Y '; ESPACIO = ' ';

  -- Lista de palabras compuestas
  DIECI = 'DIECI';  VEINT = 'VEINT';  TREINTA = 'TREINTA';
  CUARENTA = 'CUARENTA'; CINCUENTA = 'CINCUENTA'; SESENTA = 'SESENTA';
  SETENTA = 'SETENTA'; OCHENTA = 'OCHENTA'; NOVENTA = 'NOVENTA';
  TOS = 'TOS';
  CIEN = 'CIEN'; CIENTOS = CIEN || TOS;
  QUINIENTOS = 'QUINIEN' || TOS; SETE = 'SETE'; NOVE = 'NOVE';
  MIL = 'MIL';
  MILLON = 'MILLON';
  MILLONES = MILLON || 'ES';

  un_millon = 1000000;

  numeral = '';
 -- sonmiles = 'N';

  if (numero = 0) then
  begin
     numeral = '';
     exit;
  end else
     if (numero between 1 and 15) then
     begin
        if (numero = 1) then if (sonmiles = 'S') then numeral = un; else numeral = uno;
        if (numero = 2) then numeral = dos;
        if (numero = 3) then numeral = tres;
        if (numero = 4) then numeral = cuatro;
        if (numero = 5) then numeral = cinco;
        if (numero = 6) then numeral = seis;
        if (numero = 7) then numeral = siete;
        if (numero = 8) then numeral = ocho;
        if (numero = 9) then numeral = nueve;
        if (numero = 10) then numeral = diez;
        if (numero = 11) then numeral = once;
        if (numero = 12) then numeral = doce;
        if (numero = 13) then numeral = trece;
        if (numero = 14) then numeral = catorce;
        if (numero = 15) then numeral = quince;
     end
     if (numero between 16 and 19) then
     begin
        execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
        numeral = dieci || resul_numeral;
     end
     if (numero = 20) then numeral = veint || 'E';
     if (numero between 21 and 29) then
     begin
      execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
      numeral = veint || 'I' || resul_numeral;
     end
     if (numero between 30 and 99) then
     begin

         if (numero between 30 and 39) then
         begin
             execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
             numeral = treinta || y || resul_numeral;
         end

         if (numero between 40 and 49) then
         begin
             execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
             numeral = cuarenta || y || resul_numeral;
         end
         if (numero between 50 and 59) then
         begin
              execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
              numeral = cincuenta || y || resul_numeral;
         end
         if (numero between 60 and 69) then
         begin
              execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
              numeral = sesenta || y || resul_numeral;
         end
         if (numero between 70 and 79) then
         begin
              execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
              numeral = setenta || y || resul_numeral;
         end
         if (numero between 80 and 89) then
         begin
              execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
              numeral = ochenta || y || resul_numeral;
         end
         if (numero between 90 and 99) then
         begin
              execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
              numeral = noventa || y || resul_numeral;
         end
     end

     if (numero = 100) then numeral = cien;

     if (numero between 101 and 199) then
     begin
      execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
      numeral = cien || 'TO ' || resul_numeral;
     end

     if (numero >= 200) then
     begin
         if (numero = 0) then espacio = '';

         if (numero between 200 and 999) then
         begin
             if ((numero/100) = 2) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = dos || cientos || espacio || resul_numeral;
             end
             if ((numero/100) = 3) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = tres || cientos || espacio || resul_numeral;
             end
             if ((numero/100) = 4) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = cuatro || cientos || espacio || resul_numeral;
             end
             if ((numero/100) = 5) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = quinientos || espacio || resul_numeral;
             end
             if ((numero/100) = 6) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = seis || cientos || espacio || resul_numeral;
             end
             if ((numero/100) = 7) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = sete || cientos || espacio || resul_numeral;
             end
             if ((numero/100) = 8) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = ocho || cientos || espacio || resul_numeral;
             end
             if ((numero/100) = 9) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = nove || cientos || espacio || resul_numeral;
             end
         end

         if (numero > 999) then
         begin
             sonmiles = 'S';

             if (numero between 1000 and 1999) then
             begin
              execute procedure iudf_numeral(mod(numero, 1000)) returning_values(resul_numeral);
              numeral = mil || espacio || resul_numeral;
             end
    
             if (numero between 2000 and 9999) then
             begin
              execute procedure iudf_numeral(mod(numero, 1000)) returning_values(resul_numeral_mod);
              execute procedure iudf_numeral(numero/1000) returning_values(resul_numeral_div);
              numeral = resul_numeral_div || espacio || mil || espacio || resul_numeral_mod;
             end
        
             if (numero between 10000 and 999999) then
             begin
              execute procedure iudf_numeral(mod(numero, 1000)) returning_values(resul_numeral_mod);
              execute procedure iudf_numeral(numero/1000) returning_values(resul_numeral_div);
              numeral = resul_numeral_div || espacio || mil || espacio || resul_numeral_mod;
             end
        
             if (numero between 1000000 and 1999999) then
             begin
              execute procedure iudf_numeral(mod((numero-un_millon), 1000)) returning_values(resul_numeral_mod);
              execute procedure iudf_numeral((numero-un_millon)/1000) returning_values(resul_numeral_div);
              numeral = un || espacio || millon || espacio || resul_numeral_div || espacio || mil || espacio || resul_numeral_mod;
             end
        
             if (numero >= 2000000) then
             begin
              execute procedure iudf_numeral(mod(numero, 1000000)) returning_values(resul_numeral_mod);
              execute procedure iudf_numeral(numero/1000000) returning_values(resul_numeral_div);
              numeral = resul_numeral_div || espacio || millones || espacio || resul_numeral_mod;
             end

         end else sonmiles = 'N';
     end

    -- if (numero = 0) then numeral = 'CERO';

  suspend;
end^


ALTER PROCEDURE IUDF_NUMLITERAL (
    NUMERO DECIMAL(15,6),
    PREC SMALLINT)
RETURNS (
    LITERAL VARCHAR(500))
AS
declare variable PARTE_ENTERA integer;
declare variable PARTE_DECIMAL integer;
declare variable NUM float;
declare variable NEGATIVO varchar(10);
declare variable LITERAL_ENTERO varchar(500);
declare variable LITERAL_DECIMAL varchar(50);
declare variable NUM_CAD varchar(50);
declare variable POSDEC smallint;
begin
  if (numero < 0) then negativo = 'MENOS '; else negativo = '';
  numero = abs(numero);

  -- Bloque para impedir que la precisión con que se piden los decimales
  -- sea mayor que seis, y en todo caso, mayor que el número de decimales significativos
  if (prec > 6) then prec = 6;
  num_cad = cast(numero as varchar(50));
  posdec = position('.' in num_cad);
  if (posdec <> 0) then
  begin
     num_cad = substring(num_cad from posdec+1);
     num_cad = trim(trailing '0' from num_cad);
  end
  if (prec > char_length(num_cad)) then prec = char_length(num_cad);
  -- Fin del chequeo de la precisión

  -- Extracción de la parte entera y decimal
  parte_entera = floor(numero);
  num = round(numero, prec);
  num = num - parte_entera;
  parte_decimal = cast(num * power(10, prec) as integer);


  if ((parte_entera > 0) and (parte_decimal > 0)) then
  begin
     execute procedure iudf_numeral(parte_entera) returning_values(literal_entero);
     execute procedure iudf_numeral(parte_decimal) returning_values(literal_decimal);
     literal = negativo || literal_entero || ' CON ' || literal_decimal;
  end else
  if ((parte_entera > 0) and (parte_decimal = 0)) then
  begin
     execute procedure iudf_numeral(parte_entera) returning_values(literal_entero);
     literal = literal_entero;
  end else
  if ((parte_entera = 0) and (parte_decimal > 0)) then
  begin
     execute procedure iudf_numeral(parte_decimal) returning_values(literal_decimal);
     literal = 'CERO CON ' || literal_decimal;
  end else
  if ((parte_decimal = 0) and (parte_decimal = 0)) then literal = 'CERO';
  suspend;
end^



SET TERM ; ^

Si hay algo erróneo, por favor hacérmelo saber, en todo caso, que os resulte de provecho.
Un saludo.
Responder Con Cita
  #2  
Antiguo 02-12-2011
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.040
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Gracias por compartirlo
Responder Con Cita
  #3  
Antiguo 02-12-2011
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Muchas gracias por tu aporte birmain.

Saludos.
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #4  
Antiguo 02-12-2011
Avatar de guillotmarc
guillotmarc guillotmarc is offline
Miembro
 
Registrado: may 2003
Ubicación: Huelva
Posts: 2.638
Poder: 23
guillotmarc Va por buen camino
Excelente aporte.

Gracias.
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no).
Responder Con Cita
  #5  
Antiguo 02-12-2011
Avatar de marcoszorrilla
marcoszorrilla marcoszorrilla is offline
Capo
 
Registrado: may 2003
Ubicación: Cantabria - España
Posts: 11.221
Poder: 10
marcoszorrilla Va por buen camino
Excelente aportación.

Muchas gracias.
__________________
Guía de Estilo de los Foros
Cita:
- Ça c'est la caisse. Le mouton que tu veux est dedans.
Responder Con Cita
  #6  
Antiguo 02-12-2011
Avatar de guillotmarc
guillotmarc guillotmarc is offline
Miembro
 
Registrado: may 2003
Ubicación: Huelva
Posts: 2.638
Poder: 23
guillotmarc Va por buen camino
Que curioso.

Le he tenido que quitar los acentos a los comentarios para que me acepte crear los procedimientos almacenados.

Aparte de eso, parece funcionar perfectamente.

Gracias de nuevo por la aportación, Fernando.
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no).
Responder Con Cita
  #7  
Antiguo 03-12-2011
[birmain] birmain is offline
Miembro Premium
 
Registrado: feb 2005
Ubicación: Albacete - España
Posts: 49
Poder: 0
birmain Va por buen camino
Acentos y otras cosas.

Hola Marc, creo que el tema de los acentos en los comentarios se debe al juego de caracteres con que tengas definida la base de datos. A mi me dio problemas este asunto en la migración. Una vez migrado, fijando la metadata con el modificador corespondiente en GBak no me ha causado mas problemas. El conjunto de caracteres que tengo definido es ISO8859_1.

Por otra parte quiero decirte que en ocasiones he leído algunos comentarios tuyos, y veo que tienes una gran orientación didáctica, puesto que no pierdes ocasión de explicar las cosas ayudando a la gente. Te diré que una de las opiniones que más sopesé para pasar todas mis UDF a stored procedures es la tuya, que la he visto reflejada en varios post muy bien argumentada. Estoy contento de haberlo hecho, pero era muy tentador hacer una dll en pascal cuando uno no dominaba aún la esencia de los stored procedures.

Espero mantener conversaciones mas a menudo con vosotros, de los que estoy muy agradecido.

Un saludo.
Responder Con Cita
  #8  
Antiguo 03-12-2011
[birmain] birmain is offline
Miembro Premium
 
Registrado: feb 2005
Ubicación: Albacete - España
Posts: 49
Poder: 0
birmain Va por buen camino
Edad actual

Calcula la edad de una persona tal y como está convenido socialmente. (Hasta el cumpleaños no se incrementa la edad)

Código SQL [-]

SET NAMES ISO8859_1;

SET CLIENTLIB 'C:\Program Files (x86)\Firebird\Firebird_2_5\bin\fbclient.dll';

CONNECT 'cadena de conexion' USER 'SYSDBA' PASSWORD 'masterkey';





SET TERM ^ ; 



/******************************************************************************/
/***                           Stored Procedures                            ***/
/******************************************************************************/

CREATE PROCEDURE IUDF_EDAD (
    FECHANACIMIENTO DATE)
RETURNS (
    RESULTADO DECIMAL(15,4))
AS
BEGIN
  SUSPEND;
END^






SET TERM ; ^



/******************************************************************************/
/***                           Stored Procedures                            ***/
/******************************************************************************/


SET TERM ^ ;

ALTER PROCEDURE IUDF_EDAD (
    FECHANACIMIENTO DATE)
RETURNS (
    RESULTADO DECIMAL(15,4))
AS
declare variable bisiestos float;
declare variable anionacimiento integer;
declare variable anioactual integer;
declare variable dias_diferencia float;
begin
 anionacimiento = extract(year from fechanacimiento);
 anioactual = extract(year from current_date);
 bisiestos = 0;
 while (anionacimiento <= anioactual) do
 begin
          if ((mod(anionacimiento, 100)= 0) or
             (mod(anionacimiento, 400)= 0) or
             (mod(anionacimiento, 4)= 0)) then bisiestos = bisiestos + 1;
         anionacimiento = anionacimiento + 1;
 end
 dias_diferencia = datediff(day, fechanacimiento, current_date);
 resultado = (dias_diferencia - bisiestos)/365;
 resultado = floor(resultado);
 suspend;
end^



SET TERM ; ^
Responder Con Cita
  #9  
Antiguo 11-12-2011
[birmain] birmain is offline
Miembro Premium
 
Registrado: feb 2005
Ubicación: Albacete - España
Posts: 49
Poder: 0
birmain Va por buen camino
Corrección de bug

Pongo la corrección de un detalle, en el procedimiento IUDF_NUMLITERAL.
El problema se causa cuando hay una entrada decimal, p. ejemplo de prec 2, y esta termina en cero. Ejemplo: 14.20. La salida es: CATORCE CON DOS, en vez de CATORCE CON VEINTE.

Solución: Realizar el cambio siguiente

Código SQL [-]

poner esta -->      if (prec > 6) then prec = 2; -- Ponemos dos por defecto en caso de entrar una precisión mayor que seis
  -- Eliminar esta línea  if (prec > char_length(num_cad)) then prec = char_length(num_cad);
  -- Fin del chequeo de la precisión
Responder Con Cita
  #10  
Antiguo 11-12-2011
[birmain] birmain is offline
Miembro Premium
 
Registrado: feb 2005
Ubicación: Albacete - España
Posts: 49
Poder: 0
birmain Va por buen camino
Como después he corregido algunos detalles que afectan a los dos procedimientos, pongo a continuación el código de ambos, que ya creo está libre de bugs.

No tengais en cuenta mi anterior post, ya que la solución al problema era algo mas elaborada

Código SQL [-]

SET NAMES ISO8859_1;

SET CLIENTLIB 'C:\Program Files (x86)\Firebird\Firebird_2_5\bin\fbclient.dll';

CONNECT 'cadena de conexion' USER 'SYSDBA' PASSWORD '*****';





SET TERM ^ ; 



/******************************************************************************/
/***                           Stored Procedures                            ***/
/******************************************************************************/

CREATE PROCEDURE IUDF_NUMERAL (
    NUMERO INTEGER)
RETURNS (
    NUMERAL VARCHAR(500))
AS
BEGIN
  SUSPEND;
END^





CREATE PROCEDURE IUDF_NUMLITERAL (
    NUMERO DECIMAL(15,6),
    PREC SMALLINT)
RETURNS (
    LITERAL VARCHAR(500))
AS
BEGIN
  SUSPEND;
END^






SET TERM ; ^



/******************************************************************************/
/***                           Stored Procedures                            ***/
/******************************************************************************/


SET TERM ^ ;

ALTER PROCEDURE IUDF_NUMERAL (
    NUMERO INTEGER)
RETURNS (
    NUMERAL VARCHAR(500))
AS
declare variable UN varchar(10);
declare variable UNO varchar(10);
declare variable DOS varchar(10);
declare variable TRES varchar(10);
declare variable CUATRO varchar(10);
declare variable CINCO varchar(10);
declare variable SEIS varchar(10);
declare variable SIETE varchar(10);
declare variable OCHO varchar(10);
declare variable NUEVE varchar(10);
declare variable DIEZ varchar(10);
declare variable ONCE varchar(10);
declare variable DOCE varchar(10);
declare variable TRECE varchar(10);
declare variable CATORCE varchar(10);
declare variable QUINCE varchar(10);
declare variable DIECI varchar(10);
declare variable VEINT varchar(10);
declare variable TREINTA varchar(10);
declare variable CUARENTA varchar(10);
declare variable CINCUENTA varchar(10);
declare variable SESENTA varchar(10);
declare variable SETENTA varchar(10);
declare variable OCHENTA varchar(10);
declare variable NOVENTA varchar(10);
declare variable TOS varchar(10);
declare variable CIEN varchar(10);
declare variable CIENTOS varchar(10);
declare variable QUINIENTOS varchar(10);
declare variable SETE varchar(10);
declare variable NOVE varchar(10);
declare variable MIL varchar(10);
declare variable MILLON varchar(10);
declare variable MILLONES varchar(10);
declare variable SONMILES varchar(5);
declare variable Y varchar(5);
declare variable ESPACIO varchar(5);
declare variable RESUL_NUMERAL varchar(500);
declare variable RESUL_NUMERAL_MOD varchar(500);
declare variable RESUL_NUMERAL_DIV varchar(500);
declare variable UN_MILLON integer;
begin
  UN = 'UN';
  UNO = UN || 'O'; DOS = 'DOS'; TRES = 'TRES'; CUATRO = 'CUATRO'; CINCO = 'CINCO';
  SEIS = 'SEIS'; SIETE = 'SIETE'; OCHO = 'OCHO'; NUEVE = 'NUEVE'; NOVE = 'NOVE';
  DIEZ = 'DIEZ'; ONCE = 'ONCE'; DOCE = 'DOCE'; TRECE = 'TRECE';
  CATORCE = 'CATORCE'; QUINCE = 'QUINCE'; Y = ' Y '; ESPACIO = ' ';

  -- Lista de palabras compuestas
  DIECI = 'DIECI';  VEINT = 'VEINT';  TREINTA = 'TREINTA';
  CUARENTA = 'CUARENTA'; CINCUENTA = 'CINCUENTA'; SESENTA = 'SESENTA';
  SETENTA = 'SETENTA'; OCHENTA = 'OCHENTA'; NOVENTA = 'NOVENTA';
  TOS = 'TOS';
  CIEN = 'CIEN'; CIENTOS = CIEN || TOS;
  QUINIENTOS = 'QUINIEN' || TOS; SETE = 'SETE'; NOVE = 'NOVE';
  MIL = 'MIL';
  MILLON = 'MILLON';
  MILLONES = MILLON || 'ES';

  un_millon = 1000000;

  numeral = '';
 -- sonmiles = 'N';

  if (numero = 0) then
  begin
     numeral = '';
     exit;
  end else
     if (numero between 1 and 15) then
     begin
        if (numero = 1) then if (sonmiles = 'S') then numeral = un; else numeral = uno;
        if (numero = 2) then numeral = dos;
        if (numero = 3) then numeral = tres;
        if (numero = 4) then numeral = cuatro;
        if (numero = 5) then numeral = cinco;
        if (numero = 6) then numeral = seis;
        if (numero = 7) then numeral = siete;
        if (numero = 8) then numeral = ocho;
        if (numero = 9) then numeral = nueve;
        if (numero = 10) then numeral = diez;
        if (numero = 11) then numeral = once;
        if (numero = 12) then numeral = doce;
        if (numero = 13) then numeral = trece;
        if (numero = 14) then numeral = catorce;
        if (numero = 15) then numeral = quince;
     end
     if (numero between 16 and 19) then
     begin
        execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
        numeral = dieci || resul_numeral;
     end
     if (numero = 20) then numeral = veint || 'E';
     if (numero between 21 and 29) then
     begin
      execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
      numeral = veint || 'I' || resul_numeral;
     end
     if (numero between 30 and 99) then
     begin

         if (mod(numero, 10)=0) then y = '';

         if (numero between 30 and 39) then
         begin
             execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
             numeral = treinta || y || resul_numeral;
         end

         if (numero between 40 and 49) then
         begin
             execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
             numeral = cuarenta || y || resul_numeral;
         end
         if (numero between 50 and 59) then
         begin
              execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
              numeral = cincuenta || y || resul_numeral;
         end
         if (numero between 60 and 69) then
         begin
              execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
              numeral = sesenta || y || resul_numeral;
         end
         if (numero between 70 and 79) then
         begin
              execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
              numeral = setenta || y || resul_numeral;
         end
         if (numero between 80 and 89) then
         begin
              execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
              numeral = ochenta || y || resul_numeral;
         end
         if (numero between 90 and 99) then
         begin
              execute procedure iudf_numeral(mod(numero, 10)) returning_values(resul_numeral);
              numeral = noventa || y || resul_numeral;
         end
     end

     if (numero = 100) then numeral = cien;

     if (numero between 101 and 199) then
     begin
      execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
      numeral = cien || 'TO ' || resul_numeral;
     end

     if (numero >= 200) then
     begin
         if (numero = 0) then espacio = '';

         if (numero between 200 and 999) then
         begin
             if ((numero/100) = 2) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = dos || cientos || espacio || resul_numeral;
             end
             if ((numero/100) = 3) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = tres || cientos || espacio || resul_numeral;
             end
             if ((numero/100) = 4) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = cuatro || cientos || espacio || resul_numeral;
             end
             if ((numero/100) = 5) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = quinientos || espacio || resul_numeral;
             end
             if ((numero/100) = 6) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = seis || cientos || espacio || resul_numeral;
             end
             if ((numero/100) = 7) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = sete || cientos || espacio || resul_numeral;
             end
             if ((numero/100) = 8) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = ocho || cientos || espacio || resul_numeral;
             end
             if ((numero/100) = 9) then
             begin
                 execute procedure iudf_numeral(mod(numero, 100)) returning_values(resul_numeral);
                 numeral = nove || cientos || espacio || resul_numeral;
             end
         end

         if (numero > 999) then
         begin
             sonmiles = 'S';

             if (numero between 1000 and 1999) then
             begin
              execute procedure iudf_numeral(mod(numero, 1000)) returning_values(resul_numeral);
              numeral = mil || espacio || resul_numeral;
             end
    
             if (numero between 2000 and 9999) then
             begin
              execute procedure iudf_numeral(mod(numero, 1000)) returning_values(resul_numeral_mod);
              execute procedure iudf_numeral(numero/1000) returning_values(resul_numeral_div);
              numeral = resul_numeral_div || espacio || mil || espacio || resul_numeral_mod;
             end
        
             if (numero between 10000 and 999999) then
             begin
              execute procedure iudf_numeral(mod(numero, 1000)) returning_values(resul_numeral_mod);
              execute procedure iudf_numeral(numero/1000) returning_values(resul_numeral_div);
              numeral = resul_numeral_div || espacio || mil || espacio || resul_numeral_mod;
             end
        
             if (numero between 1000000 and 1999999) then
             begin
              execute procedure iudf_numeral(mod((numero-un_millon), 1000)) returning_values(resul_numeral_mod);
              execute procedure iudf_numeral((numero-un_millon)/1000) returning_values(resul_numeral_div);
              numeral = un || espacio || millon || espacio || resul_numeral_div || espacio || mil || espacio || resul_numeral_mod;
             end
        
             if (numero >= 2000000) then
             begin
              execute procedure iudf_numeral(mod(numero, 1000000)) returning_values(resul_numeral_mod);
              execute procedure iudf_numeral(numero/1000000) returning_values(resul_numeral_div);
              numeral = resul_numeral_div || espacio || millones || espacio || resul_numeral_mod;
             end

         end else sonmiles = 'N';
     end

    -- if (numero = 0) then numeral = 'CERO';

  suspend;
end^


ALTER PROCEDURE IUDF_NUMLITERAL (
    NUMERO DECIMAL(15,6),
    PREC SMALLINT)
RETURNS (
    LITERAL VARCHAR(500))
AS
declare variable PARTE_ENTERA integer;
declare variable PARTE_DECIMAL integer;
declare variable NUM float;
declare variable NEGATIVO varchar(10);
declare variable LITERAL_ENTERO varchar(500);
declare variable LITERAL_DECIMAL varchar(50);
declare variable NUM_CAD varchar(50);
declare variable POSDEC smallint;
declare variable DECIMAL_CAD varchar(10);
begin
  if (numero < 0) then negativo = 'MENOS '; else negativo = '';
  numero = abs(numero);


  if (prec > 6) then prec = 6;
  num_cad = cast(numero as varchar(50));
  posdec = position('.' in num_cad);
  if (posdec <> 0) then
  begin
     num_cad = substring(num_cad from posdec+1);
     num_cad = trim(trailing '0' from num_cad);
  end


  parte_entera = floor(numero);
  num = round(numero, prec);
  num = num - parte_entera;
  parte_decimal = cast(num * power(10, prec) as integer);

  decimal_cad = cast(parte_decimal as varchar(10));
  if (char_length(num_cad) > prec) then
  begin
      decimal_cad = rpad(decimal_cad, char_length(num_cad), '0');
      parte_decimal = cast(decimal_cad as integer);
  end

  if ((parte_entera > 0) and (parte_decimal > 0)) then
  begin
     execute procedure iudf_numeral(parte_entera) returning_values(literal_entero);
     execute procedure iudf_numeral(parte_decimal) returning_values(literal_decimal);
     literal = negativo || literal_entero || ' CON ' || literal_decimal;
  end else
  if ((parte_entera > 0) and (parte_decimal = 0)) then
  begin
     execute procedure iudf_numeral(parte_entera) returning_values(literal_entero);
     literal = literal_entero;
  end else
  if ((parte_entera = 0) and (parte_decimal > 0)) then
  begin
     execute procedure iudf_numeral(parte_decimal) returning_values(literal_decimal);
     literal = 'CERO CON ' || literal_decimal;
  end else
  if ((parte_decimal = 0) and (parte_decimal = 0)) then literal = 'CERO';
  suspend;
end^



SET TERM ; ^
Responder Con Cita
  #11  
Antiguo 16-07-2015
sam123 sam123 is offline
Registrado
NULL
 
Registrado: jul 2015
Posts: 6
Poder: 0
sam123 Va por buen camino
Conversion de Numeros a Letras... en Delphi

Buen dia

Gracias por la ayuda, el codigo que enviastes, logre ejecutarlo pero sigo igual no me convierte los centavos ejemplo
(125.10), solo me convierte... CIENTO VEINTICINCO...

lo que necesito es que me diga.. Ciento Veinticinco con 10 Centavos.....

si me envias ese mismo codigo con esas modificaciones

saludos

gracias
Responder Con Cita
  #12  
Antiguo 16-07-2015
sam123 sam123 is offline
Registrado
NULL
 
Registrado: jul 2015
Posts: 6
Poder: 0
sam123 Va por buen camino
Esta con error, conversion de numeros a letras

Estimado gracias por tu ayuda, pero ahora ya no convierte a letras todos los numeros, ejemplo 1425.50, solo convierte
MIL...esto despues de cambiar la linea..
if (prec > 6) then prec = 2
lo demas no ignora

saludos
Responder Con Cita
  #13  
Antiguo 16-07-2015
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola sam123.

Es curioso... A mi me funciona correctamente, al ejecutar:
Código SQL [-]
SELECT LITERAL FROM IUDF_NUMLITERAL(1425.50, 2)

Obtengo el resultado:
Cita:
MIL CUATROCIENTOS VEINTICINCO CON CINCUENTA
Si deseas la palabra "CENTAVOS" al final, solo tienes que concatenarla en el código del procedimiento almacenado IUDF_NUMLITERAL.

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....

Última edición por ecfisa fecha: 16-07-2015 a las 19:15:34.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Stored Procedure gluglu Conexión con bases de datos 16 24-02-2011 17:41:24
Aportacion Funcion para calcular dias : DaysForDate bitbow Varios 1 08-11-2010 20:49:24
Conversion de números donald shimoda Varios 7 07-10-2008 19:57:48
Stored Procedure genera codigo Carlos Hurtado Firebird e Interbase 2 19-10-2005 19:38:19
Stored Procedure tgsistemas SQL 1 27-02-2004 13:10:33


La franja horaria es GMT +2. Ahora son las 14:50:03.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi