Tengo implementado un procedimiento almacenado que hace justamente eso. Admite tres parámetros de entrada:
NUMERO DECIMAL(18,4)
LONGNUM INTEGER,
PREC SMALLINT
y devuelve
RESULTADO VARCHAR(100)
El primero obviamente es el número a formatear, el segundo es la longitud de la cadena resultante, o sea que justifica con espacios a la izquierda hasta completar esa longitud, y el tercero es la precisión decimal con la que se obtendrá la salida.
Ejemplo:
1456.279, 12, 2 daría :
'(cuatro espacios)1.456,28'
Este es el código del procedimiento almacenado:
Código SQL
[-]
SET SQL DIALECT 3;
SET NAMES NONE;
SET CLIENTLIB 'C:\Program Files (x86)\Firebird\Firebird_2_5\bin\fbclient.dll'; -- Poner aquí el path del cliente firebird
CREATE DATABASE 'cadena de conexión'
USER 'SYSDBA' PASSWORD 'masterkey'
PAGE_SIZE 8192
DEFAULT CHARACTER SET NONE COLLATION NONE;
SET TERM ^ ;
CREATE PROCEDURE IUDF_FORMATO_NUM (
NUMERO DECIMAL(18,4),
LONGNUM INTEGER,
PREC SMALLINT)
RETURNS (
RESULTADO VARCHAR(100))
AS
BEGIN
SUSPEND;
END^
SET TERM ; ^
SET TERM ^ ;
ALTER PROCEDURE IUDF_FORMATO_NUM (
NUMERO DECIMAL(18,4),
LONGNUM INTEGER,
PREC SMALLINT)
RETURNS (
RESULTADO VARCHAR(100))
AS
declare variable PARTE_ENTERA integer;
declare variable PARTE_DECIMAL integer;
declare variable NUM decimal(18,6);
declare variable NEGATIVO varchar(10);
declare variable NUM_CAD varchar(50);
declare variable POSDEC smallint;
declare variable J integer;
declare variable I integer;
declare variable PARTE_ENTERA_CAD varchar(100);
declare variable PARTE_DECIMAL_CAD varchar(20);
declare variable PARTE_ENTERA_CAD_REV varchar(100);
declare variable COMA varchar(5);
declare variable DECIMAL_CAD varchar(10);
begin
if (numero < 0) then negativo = '-'; else negativo = '';
numero = abs(numero);
coma = ',';
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
-- 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);
parte_entera_cad = cast(parte_entera as varchar(100));
parte_decimal_cad = cast(parte_decimal as varchar(10));
if (parte_decimal = 0) then parte_decimal_cad = lpad('', prec, '0');
parte_entera_cad_rev = '';
j = char_length(parte_entera_cad);
i = 0;
while (j >= 1) do
begin
i = i + 1;
parte_entera_cad_rev = parte_entera_cad_rev || substring(parte_entera_cad from j for 1);
if ((mod(i, 3)=0) and (j>1)) then parte_entera_cad_rev = parte_entera_cad_rev || '.';
j = j - 1;
end
resultado = negativo || reverse(parte_entera_cad_rev) || coma || parte_decimal_cad;
resultado = lpad(resultado, longnum, ' ');
suspend;
end^
SET TERM ; ^