Numeros a letras

__TOC__
These functions takes a number as argument and returns a spanish string representing the number.
Estas funciones reciben un número como argumento y retorna su representación en palabras.
=== Función fu_numero_letras (numero numeric) RETURNS text ===
Esta función fue publicada por Javier Bermúdez en 
CREATE OR REPLACE FUNCTION fu_numero_letras(numero numeric) RETURNS text AS
$body$
DECLARE
 lnEntero INTEGER;
 lcRetorno TEXT;
 lnTerna INTEGER;
 lcMiles TEXT;
 lcCadena TEXT;
 lnUnidades INTEGER;
 lnDecenas INTEGER;
 lnCentenas INTEGER;
 lnFraccion INTEGER;
 lnSw INTEGER;
BEGIN
 lnEntero := FLOOR(numero)::INTEGER;--Obtenemos la parte Entera
 lnFraccion := FLOOR(((numero - lnEntero) * 100))::INTEGER;--Obtenemos la Fraccion del Monto
 lcRetorno := ;
 lnTerna := 1;
 IF lnEntero > 0 THEN
 lnSw := LENGTH(lnEntero);
 WHILE lnTerna <= lnSw LOOP
 -- Recorro terna por terna
 lcCadena = ;
 lnUnidades = lnEntero % 10;
 lnEntero = CAST(lnEntero/10 AS INTEGER);
 lnDecenas = lnEntero % 10;
 lnEntero = CAST(lnEntero/10 AS INTEGER);
 lnCentenas = lnEntero % 10;
 lnEntero = CAST(lnEntero/10 AS INTEGER);
 -- Analizo las unidades
 SELECT
 CASE /* UNIDADES */
 WHEN lnUnidades = 1 AND lnTerna = 1 THEN 'UNO ' || lcCadena
 WHEN lnUnidades = 1 AND lnTerna <> 1 THEN 'UN ' || lcCadena
 WHEN lnUnidades = 2 THEN 'DOS ' || lcCadena
 WHEN lnUnidades = 3 THEN 'TRES ' || lcCadena
 WHEN lnUnidades = 4 THEN 'CUATRO ' || lcCadena
 WHEN lnUnidades = 5 THEN 'CINCO ' || lcCadena
 WHEN lnUnidades = 6 THEN 'SEIS ' || lcCadena
 WHEN lnUnidades = 7 THEN 'SIETE ' || lcCadena
 WHEN lnUnidades = 8 THEN 'OCHO ' || lcCadena
 WHEN lnUnidades = 9 THEN 'NUEVE ' || lcCadena
 ELSE lcCadena
 END INTO lcCadena;
 /* UNIDADES */
 -- Analizo las decenas
 SELECT
 CASE /* DECENAS */
 WHEN lnDecenas = 1 THEN
 CASE lnUnidades
 WHEN 0 THEN 'DIEZ '
 WHEN 1 THEN 'ONCE '
 WHEN 2 THEN 'DOCE '
 WHEN 3 THEN 'TRECE '
 WHEN 4 THEN 'CATORCE '
 WHEN 5 THEN 'QUINCE '
 ELSE 'DIECI' || lcCadena
 END
 WHEN lnDecenas = 2 AND lnUnidades = 0 THEN 'VEINTE ' || lcCadena
 WHEN lnDecenas = 2 AND lnUnidades <> 0 THEN 'VEINTI' || lcCadena
 WHEN lnDecenas = 3 AND lnUnidades = 0 THEN 'TREINTA ' || lcCadena
 WHEN lnDecenas = 3 AND lnUnidades <> 0 THEN 'TREINTA Y ' || lcCadena
 WHEN lnDecenas = 4 AND lnUnidades = 0 THEN 'CUARENTA ' || lcCadena
 WHEN lnDecenas = 4 AND lnUnidades <> 0 THEN 'CUARENTA Y ' || lcCadena
 WHEN lnDecenas = 5 AND lnUnidades = 0 THEN 'CINCUENTA ' || lcCadena
 WHEN lnDecenas = 5 AND lnUnidades <> 0 THEN 'CINCUENTA Y ' || lcCadena
 WHEN lnDecenas = 6 AND lnUnidades = 0 THEN 'SESENTA ' || lcCadena
 WHEN lnDecenas = 6 AND lnUnidades <> 0 THEN 'SESENTA Y ' || lcCadena
 WHEN lnDecenas = 7 AND lnUnidades = 0 THEN 'SETENTA ' || lcCadena
 WHEN lnDecenas = 7 AND lnUnidades <> 0 THEN 'SETENTA Y ' || lcCadena
 WHEN lnDecenas = 8 AND lnUnidades = 0 THEN 'OCHENTA ' || lcCadena
 WHEN lnDecenas = 8 AND lnUnidades <> 0 THEN 'OCHENTA Y ' || lcCadena
 WHEN lnDecenas = 9 AND lnUnidades = 0 THEN 'NOVENTA ' || lcCadena
 WHEN lnDecenas = 9 AND lnUnidades <> 0 THEN 'NOVENTA Y ' || lcCadena
 ELSE lcCadena
 END INTO lcCadena; /* DECENAS */
 -- Analizo las centenas
 SELECT
 CASE /* CENTENAS */
 WHEN lnCentenas = 1 AND lnUnidades = 0 AND lnDecenas = 0 THEN 'CIEN ' || lcCadena
 WHEN lnCentenas = 1 AND NOT(lnUnidades = 0 AND lnDecenas = 0) THEN 'CIENTO ' || lcCadena
 WHEN lnCentenas = 2 THEN 'DOSCIENTOS ' || lcCadena
 WHEN lnCentenas = 3 THEN 'TRESCIENTOS ' || lcCadena
 WHEN lnCentenas = 4 THEN 'CUATROCIENTOS ' || lcCadena
 WHEN lnCentenas = 5 THEN 'QUINIENTOS ' || lcCadena
 WHEN lnCentenas = 6 THEN 'SEISCIENTOS ' || lcCadena
 WHEN lnCentenas = 7 THEN 'SETECIENTOS ' || lcCadena
 WHEN lnCentenas = 8 THEN 'OCHOCIENTOS ' || lcCadena
 WHEN lnCentenas = 9 THEN 'NOVECIENTOS ' || lcCadena
 ELSE lcCadena
 END INTO lcCadena;/* CENTENAS */
 -- Analizo la terna
 SELECT
 CASE /* TERNA */
 WHEN lnTerna = 1 THEN lcCadena
 WHEN lnTerna = 2 AND (lnUnidades + lnDecenas + lnCentenas <> 0) THEN lcCadena || ' MIL '
 WHEN lnTerna = 3 AND (lnUnidades + lnDecenas + lnCentenas <> 0) AND
 lnUnidades = 1 AND lnDecenas = 0 AND lnCentenas = 0 THEN lcCadena || ' MILLON '
 WHEN lnTerna = 3 AND (lnUnidades + lnDecenas + lnCentenas <> 0) AND
 NOT (lnUnidades = 1 AND lnDecenas = 0 AND lnCentenas = 0) THEN lcCadena || ' MILLONES '
 WHEN lnTerna = 4 AND (lnUnidades + lnDecenas + lnCentenas <> 0) THEN lcCadena || ' MIL MILLONES '
 ELSE ''
 END INTO lcCadena;/* TERNA */
 --Retornamos los Valores Obtenidos
 lcRetorno = lcCadena || lcRetorno;
 lnTerna = lnTerna + 1;
 END LOOP;
 END IF;
 IF lnTerna = 1 THEN
 lcRetorno := 'CERO';
 END IF;
 lcRetorno := RTRIM(lcRetorno) || ' CON ' || LTRIM(lnFraccion) || '/100 NUEVOS SOLES';
RETURN lcRetorno;
END;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;
 
COMMENT ON FUNCTION fu_numero_letras(numero numeric)
IS 'Funcion para Convertir el Monto Numerico a Letras';
=== Función f_convnl(num numeric) RETURNS character varying ===
Otra función con el mismo propósito utilizando otra técnica de programación.
Autora: Conxita Marín
CREATE FUNCTION f_convnl(num numeric) RETURNS character varying
 AS $$
-- Función que devuelve la cadena de texto en castellano que corresponde a un número.
-- Parámetros: número con 2 decimales, máximo 999.999.999,99.
DECLARE	
	d varchar[];
	f varchar[];
	g varchar[];
	numt varchar;
	txt varchar;
	a integer;
	a1 integer;
	a2 integer;
	n integer;
	p integer;
	negativo boolean;
BEGIN
	-- Máximo 999.999.999,99
	if num > 999999999.99 then
		return '---';
	end if;
	txt = ;
	d = array[' un',' dos',' tres',' cuatro',' cinco',' seis',' siete',' ocho',' nueve',' diez',' once',' doce',' trece',' catorce',' quince',
		' dieciseis',' diecisiete',' dieciocho',' diecinueve',' veinte',' veintiun',' veintidos', ' veintitres', ' veinticuatro', ' veinticinco',
		' veintiseis',' veintisiete',' veintiocho',' veintinueve'];
	f = array [,,' treinta',' cuarenta',' cincuenta',' sesenta',' setenta',' ochenta', ' noventa'];
	g= array [' ciento',' doscientos',' trescientos',' cuatrocientos',' quinientos',' seiscientos',' setecientos',' ochocientos',' novecientos'];
	numt = lpad((num::numeric(12,2))::text,12,'0');
	if strpos(numt,'-') > 0 then
	 negativo = true;
	else
	 negativo = false;
	end if;
	numt = translate(numt,'-','0');
	numt = translate(numt,'.,',);
	-- Trato 4 grupos: millones, miles, unidades y decimales
	p = 1;
	for i in 1..4 loop
		if i < 4 then
			n = substring(numt::text from p for 3);
		else
			n = substring(numt::text from p for 2);
		end if;
		p = p + 3;
		if i = 4 then
			if txt = then
				txt = ' cero';
			end if;
			if n > 0 then
			-- Empieza con los decimales
				txt = txt || ' con';
			end if;
		end if;
		-- Centenas 
		if n > 99 then
			a = substring(n::text from 1 for 1);
			a1 = substring(n::text from 2 for 2);
			if a = 1 then
				if a1 = 0 then
					txt = txt || ' cien';
				else
					txt = txt || ' ciento';
				end if;
			else
				txt = txt || g[a];
			end if;
		else
			a1 = n;
		end if;
		-- Decenas
		a = a1;
		if a > 0 then
			if a < 30 then
				if a = 21 and (i = 3 or i = 4) then
					txt = txt || ' veintiuno';
				elsif n = 1 and i = 2 then
					txt = txt; 
				elsif a = 1 and (i = 3 or i = 4)then
					txt = txt || ' uno';
				else
					txt = txt || d[a];
				end if;
			else
				a1 = substring(a::text from 1 for 1);
				a2 = substring(a::text from 2 for 1);
				if a2 = 1 and (i = 3 or i = 4) then
						txt = txt || f[a1] || ' y' || ' uno';
				else
					if a2 <> 0 then
						txt = txt || f[a1] || ' y' || d[a2];
					else
						txt = txt || f[a1];
					end if;
				end if;
			end if;
		end if;
		if n > 0 then
			if i = 1 then
				if n = 1 then
					txt = txt || ' millón';
				else
					txt = txt || ' millones';
				end if;
			elsif i = 2 then
				txt = txt || ' mil';
			end if;		
		end if;
	end loop;
	txt = ltrim(txt);
	if negativo = true then
	 txt= '-' || txt;
	end if;
 RETURN txt;
END;
$$
 LANGUAGE plpgsql;
=== Con el módulo Perl Lingua::ES::Numeros ===
CREATE OR REPLACE num2pal(numeric) RETURNS text LANGUAGE plperlu as $$
use Lingua::ES::Numeros;
$obj = new Lingua::ES::Numeros('FORMATO' => 'con %s.');
return $obj->real($_[0]);
$$;
Category:PL/pgSQL
Category:PL/Perl
Category:Español