dicas show delphi

DICAS

Visite a biblioteca de dicas da comunidade.

Saiba mais
sombra
Artigos Show Delphi

ARTIGOS

Abordagens detalhadas sobre assuntos diversos.

Saiba mais
sombra
iniciantes show delphi

INICIANTES

Aprenda a programar de um modo simples e fácil.

Saiba mais
sombra
downloads show delphi

DOWNLOADS

Acesse os materiais exclusivos aos membros.

Saiba mais
sombra
voltar

PARA QUEM GOSTA DE DELPHI

Stored Procedure e function ROUNDABNT para SQL Firebird

Fala galera do Show Delphi, tudo beleza?

Este dias estava tendo problemas com o uma nota de consumidor emitida e os dados salvos.
Percebi que tinha um caso em que o valor total do item era 1,365.

Para a NFC-e ia 1,36 e para o banco 1,37.

As configurações era para arredondar.

Ai estudando percebi que o arredondamento interno utilizado era conforme a ABNT e neste caso 1,345 fica 1,34.

Exemplo
de 0 a 4 na segunda casa, 5 na terceira arredonda para baixo,
5 a 9 na segunda casa, 5 arredonda para cima.

Como meu procedimento estava no banco, precisei uma forma de fazer este arredondamento via SQL.

E no caso estava utilizando o Firebird.

Para minha sorte encontrei uma function para firebird 3.0 e uma stored procedure para firebird 2.5.

Então vamos ao código!

FUNCTION – PARA FIREBIRD 3.0

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
CREATE OR ALTER FUNCTION ROUNDABNT (
AVALOR DOUBLE PRECISION,
ADECIMAIS SMALLINT)
RETURNS DOUBLE PRECISION
AS
DECLARE variable cDecimais VARCHAR(100);
DECLARE variable vlrstr VARCHAR(100);
DECLARE variable nSubsequente SMALLINT;
DECLARE variable posponto SMALLINT;
BEGIN
vlrstr = CAST(AVALOR AS VARCHAR(100));
posponto = POSITION('.',vlrstr);
cDecimais = SUBSTRING(vlrstr FROM posponto+1 FOR CHAR_LENGTH(vlrstr));
nSubsequente = ADECIMAIS+1;
IF (:ADECIMAIS < 1) THEN
RETURN TRUNC(AVALOR);
ELSE
IF (CHAR_LENGTH(cDecimais) <= :ADECIMAIS) THEN
RETURN AVALOR;
ELSE
BEGIN
IF ((CAST(SUBSTRING(cDecimais FROM nSubsequente FOR 1) AS INTEGER) > 5) OR
(CAST(SUBSTRING(cDecimais FROM nSubsequente FOR 1)AS DOUBLE PRECISION)  < 5))  THEN
RETURN ROUND(AVALOR,ADECIMAIS);
ELSE
IF (CAST(SUBSTRING(cDecimais FROM nSubsequente FOR 1)AS DOUBLE PRECISION) = 5) THEN
IF (MOD(CAST(SUBSTRING(cDecimais FROM ADECIMAIS FOR 1)AS DOUBLE PRECISION) ,2) <> 0) THEN
RETURN ROUND(AVALOR,ADECIMAIS);
ELSE
IF (CAST(SUBSTRING(cDecimais FROM nSubsequente+1 FOR 1)AS DOUBLE PRECISION) > 0) THEN
RETURN ROUND(AVALOR,ADECIMAIS);
ELSE
RETURN TRUNC(AVALOR,ADECIMAIS);
END
END

Exemplo de uso da function em firebird 3.0

1
2
3
4
5
6
7
8
9
10
SELECT
roundabnt(1.645, 2) AS exemplo1,
 
roundabnt(1.655, 2) AS exemplo2,
 
roundabnt(1.605, 2) AS exemplo3,
 
roundabnt(1.605, 2) AS exemplo4
 
FROM rdb$database

STORED PROCEDURE – PARA FIREBIRD 2.5

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
CREATE OR ALTER PROCEDURE SP_ROUNDABNT (
AVALOR DOUBLE PRECISION,
ADECIMAIS SMALLINT)
RETURNS
(
VALOR DOUBLE PRECISION
)
AS
DECLARE VARIABLE CDECIMAIS VARCHAR(100);
DECLARE VARIABLE VLRSTR VARCHAR(100);
DECLARE VARIABLE NSUBSEQUENTE SMALLINT;
DECLARE VARIABLE POSPONTO SMALLINT;
BEGIN
VLRSTR = CAST(AVALOR AS VARCHAR(100));
POSPONTO = POSITION('.',VLRSTR);
CDECIMAIS = SUBSTRING(VLRSTR FROM POSPONTO+1 FOR CHAR_LENGTH(VLRSTR));
NSUBSEQUENTE = ADECIMAIS+1;
IF (:ADECIMAIS < 1) THEN
BEGIN
VALOR = TRUNC(AVALOR);
SUSPEND;
exit;
END
ELSE
IF (CHAR_LENGTH(CDECIMAIS) <= :ADECIMAIS) THEN
BEGIN
VALOR = AVALOR;
SUSPEND;
exit;
END
ELSE
BEGIN
IF ((CAST(SUBSTRING(CDECIMAIS FROM NSUBSEQUENTE FOR 1) AS INTEGER) > 5) OR
(CAST(SUBSTRING(CDECIMAIS FROM NSUBSEQUENTE FOR 1)AS DOUBLE PRECISION)  < 5))  THEN
BEGIN
VALOR = ROUND(AVALOR,ADECIMAIS);
SUSPEND;
exit;
END
ELSE
IF (CAST(SUBSTRING(CDECIMAIS FROM NSUBSEQUENTE FOR 1)AS DOUBLE PRECISION) = 5) THEN
BEGIN
IF (MOD(CAST(SUBSTRING(CDECIMAIS FROM ADECIMAIS FOR 1)AS DOUBLE PRECISION) ,2) <> 0) THEN
BEGIN
VALOR = ROUND(AVALOR,ADECIMAIS);
SUSPEND;
exit;
END
ELSE IF (CAST(SUBSTRING(CDECIMAIS FROM NSUBSEQUENTE+1 FOR 1)AS DOUBLE PRECISION) > 0) THEN
BEGIN
VALOR = ROUND(AVALOR,ADECIMAIS);
SUSPEND;
exit;
END
ELSE
BEGIN
VALOR = TRUNC(AVALOR,ADECIMAIS);
SUSPEND;
exit;
END
END
END
END

Fonte Base: https://www.projetoacbr.com.br/forum/topic/9709-minha-pequena-contribui%C3%A7%C3%A3o-arredondamento-abnt/

Exemplo de uso da stored procedure em firebird 2.5

1
2
3
4
5
6
7
8
9
10
SELECT
(SELECT a.valor FROM SP_ROUNDABNT(1.645, 2) a) AS exemplo1,
 
(SELECT a.valor FROM SP_ROUNDABNT(1.655, 2) a) AS exemplo2,
 
(SELECT a.valor FROM SP_ROUNDABNT(1.605, 2) a) AS exemplo3,
 
(SELECT a.valor FROM SP_ROUNDABNT(1.605, 2) a) AS exemplo4
 
FROM rdb$database

Pessoal, os códigos acima foram muito úteis para mim e espero que ajude a todos.

Um abraço e até a próxima.

Valeu!

  • Giovani Da Cruz
  • 0 comentários
  • 27 de dezembro de 2019

Deixe um comentário

Ir ao topo

© 2024 Infus Soluções em Tecnologia - Todos os Direitos Reservados