Ajuda com soma numa variavel, diferença de valores?

07/07/2008

1

Pessoal tenho que somar um resultado de uma variavel aqui, mais esta com problemas de aumentar pra cima o valor.

Exemplo
é uma soma total

se estiver assim
valor nota ---- 5.783,63 ipi-------------------0,00 descontos----------0,00 total------------5.783,63


agora se estiver assim
valor nota ---- 5.577,93 ipi-----------------824,55 descontos--------128,15 total------------6.274,34 //errado


Se eu colocar uma função para arredondar pra baixo, funciona o segundo resultado
6.274,33 mais o primeiro fica assim 5.783,62

Então pessoal, preciso desta soma exata
O codigo é este aqui
{:Serve para arredondar valores, com duas
casas decimais mudando por exemplo de 0,165 para 0,16, ou seja sempre para baixo,
tem que declarar a unit math na uses da lib´s}
function TfrmEnvioemail.Min_Round(const AValue: Double;
  const ADigit: TRoundToRange): Double;
var
  LFactor: Double;
begin
  LFactor := IntPower(10, ADigit);
  Result := Trunc((AValue / LFactor) - 0.5) * LFactor;
end;

procedure TfrmEnvioemail.ppDetailBand1BeforePrint(Sender: TObject);
var
  TotUnit, TotIPI : double;
begin
  {if dsRelEnviaPed.DataSet.FieldByName(´DESCONTOS´).AsFloat = 0 then
     dsRelEnviaPed.DataSet.FieldByName(´DESCONTOS´).AsString := ´´;}
  {:Somas da banda DetailBand}
  TotUnit := ( dsRelEnviaPed.DataSet.FieldByName(´QTDE´).asFloat *
               dsRelEnviaPed.DataSet.FieldByName(´VL_UNITARIO´).AsCurrency );

  somaValorTotal.Value := (TotUnit * ((100 - dsRelEnviaPed.DataSet.FieldByName(´DESCONTOS´).AsFloat)/100));
  {soma indice ipi}
  TotIPI := ((somaValorTotal.Value * dsRelEnviaPed.DataSet.FieldByName(´indice_ipi´).AsFloat)/100);
  {:Soma o total dos produtos que vai na banda do Rodapé}
  SomaTotal.Value := (somaTotal.Value +  somaValorTotal.Value);
  {:Soma total do IPI}
  SomaIPI.Value   := (SomaIPI.Value + TotIPI);
  {:Soma total Descontos}
  SomaDesconto.Value := ( SomaDesconto.Value + (( dsRelEnviaPed.DataSet.FieldByName(´VL_UNITARIO´).AsCurrency *
                                 dsRelEnviaPed.DataSet.FieldByName(´DESCONTOS´).AsFloat)/100));
  {:Soma liquido}
 // SomaLiquido.Value := Min_Round(( SomaTotal.Value + SomaIPI.Value - SomaDesconto.Value ),-2);
 SomaLiquido.Value := (SomaTotal.Value + ( SomaIPI.Value - SomaDesconto.Value ));
end;



O problema de trazer o resultado final esta aqui
{:Soma liquido}
 // SomaLiquido.Value := Min_Round(( SomaTotal.Value + SomaIPI.Value - SomaDesconto.Value ),-2);
 SomaLiquido.Value := (SomaTotal.Value + ( SomaIPI.Value - SomaDesconto.Value )); 



Responder

Posts

07/07/2008

Aleriopreto

vc pode usar o StrtoFloat(formatfloat(´0.00´,valor)), ai ele quebra a variavel deixando somente a casa decimal que vc quer.


Responder
Olá amigo,

Fiz uma gambiarra aqui, a principio parece estar funcionando, mais não sei ainda, pois não testei em todos, apenas naqueles que eu vi a diferença

Olhe amigo
procedure TfrmEnvioemail.ppDetailBand1BeforePrint(Sender: TObject);
var
  TotUnit, TotIPI, TotLiquidoMax, TotLiquidoMin : double;
begin
  {:zera as variaveis antes de começar}
  TotLiquidoMax := 0;
  TotLiquidoMin := 0;
  {if dsRelEnviaPed.DataSet.FieldByName(´DESCONTOS´).AsFloat = 0 then
     dsRelEnviaPed.DataSet.FieldByName(´DESCONTOS´).AsString := ´´;}
  {:Somas da banda DetailBand}
  TotUnit := ( dsRelEnviaPed.DataSet.FieldByName(´QTDE´).asFloat *
               dsRelEnviaPed.DataSet.FieldByName(´VL_UNITARIO´).AsCurrency );

  somaValorTotal.Value := (TotUnit * ((100 - dsRelEnviaPed.DataSet.FieldByName(´DESCONTOS´).AsFloat)/100));
  {soma indice ipi}
  TotIPI := ((somaValorTotal.Value * dsRelEnviaPed.DataSet.FieldByName(´indice_ipi´).AsFloat)/100);
  {:Soma o total dos produtos que vai na banda do Rodapé}
  SomaTotal.Value := (somaTotal.Value +  somaValorTotal.Value);
  {:Soma total do IPI}
  SomaIPI.Value   := (SomaIPI.Value + TotIPI);
  {:Soma total Descontos}
  SomaDesconto.Value := ( SomaDesconto.Value + (( dsRelEnviaPed.DataSet.FieldByName(´VL_UNITARIO´).AsCurrency *
                                 dsRelEnviaPed.DataSet.FieldByName(´DESCONTOS´).AsFloat)/100));
  {:Soma liquido}
  SomaLiquido.Value := (SomaTotal.Value + ( SomaIPI.Value - SomaDesconto.Value ));
  TotLiquidoMax := SomaLiquido.Value;
  TotLiquidoMax := StrToFloat(FormatFloat(´0.0000´, TotLiquidoMax ) );
  TotLiquidoMin := SomaLiquido.Value;
  TotLiquidoMin := StrToFloat(FormatFloat(´0.00´, TotLiquidoMin ) );
  if TotLiquidoMax <> TotLiquidoMin then
     SomaLiquido.Value := Min_Round((TotLiquidoMax ),-2)
  else
     SomaLiquido.Value := ( TotLiquidoMin );
end;

Ou seja criei + duas variaveis e passei uma condição com if de comparação para dentro delas para verificar se ha diferença entre uma e outra

{:Soma liquido}
  SomaLiquido.Value := (SomaTotal.Value + ( SomaIPI.Value - SomaDesconto.Value ));
  TotLiquidoMax := SomaLiquido.Value;
  TotLiquidoMax := StrToFloat(FormatFloat(´0.0000´, TotLiquidoMax ) );
  TotLiquidoMin := SomaLiquido.Value;
  TotLiquidoMin := StrToFloat(FormatFloat(´0.00´, TotLiquidoMin ) );
  if TotLiquidoMax <> TotLiquidoMin then
     SomaLiquido.Value := Min_Round((TotLiquidoMax ),-2)
  else
     SomaLiquido.Value := ( TotLiquidoMin );


Bom amigo, vou ver aqui se assim vai funcionar.

Mais se alguem tiver uma idéia 100¬ sobre este problema de arredondamento estejam a vontade para postar.


Responder
Reparei que eles arrumaram esta função pelo menos esta diferente no BSD2006 e o Delphi7 meu aqui

Olhe no D7
function SimpleRoundTo(const AValue: Double; const ADigit: TRoundToRange = -2): Double;
var
  LFactor: Double;
begin
  LFactor := IntPower(10, ADigit);
  Result := Trunc((AValue / LFactor) + 0.5) * LFactor;
end;


e olhe no BDS2006
function SimpleRoundTo(const AValue: Double; const ADigit: TRoundToRange = -2): Double;
var
  LFactor: Double;
begin
  LFactor := IntPower(10, ADigit);
  if AValue < 0 then
    Result := Trunc((AValue / LFactor) - 0.5) * LFactor
  else
    Result := Trunc((AValue / LFactor) + 0.5) * LFactor;
end;



Eu não tinha reparado nisso, fiz esta função quando estava usando o D7 pq não retornava pra baixo, mais parece que eles arrumaram como estou vendo ai.

Vou testar então.

Qualquer coisa volto a postar.


Responder

07/07/2008

Edilcimar

já tentou usar o roundto()?


Responder
já tentou usar o roundto()?
Olá amigo, o roundTo ão serve para este processo, mais ja resolvi.

Obrigado.


Responder

08/07/2008

Luiz Henrique

Bom dia Adriano, tudo blz...

Tambem ja enfrentei este tipo de problema, consegui solucionar, padraonizando os arredondamentos com uma funcao que fiz aqui e nao deixo calculos de multiplicacao ou divisao para o banco ou componente de relatorio.
É enrolado mesmo...


Responder
[quote:7613986e0a=´Luiz Henrique´]Bom dia Adriano, tudo blz...

Tambem ja enfrentei este tipo de problema, consegui solucionar, padraonizando os arredondamentos com uma funcao que fiz aqui e nao deixo calculos de multiplicacao ou divisao para o banco ou componente de relatorio.
É enrolado mesmo...[/quote:7613986e0a]Olá [b:7613986e0a]Luiz Henrique[/b:7613986e0a], se vc puder passar o esquema da função ficarei grato.

Obrigado amigo.


Responder
creio que a melhor forma de fazer isso é colocar os valores calculados em variáveis distintas, já ´arredondados´.
por conta do arredondamento, não é possível fazer direto.

eu faria assim:
{Serve para arredondar valores, com duas casas decimais mudando,
 por exemplo de 0,165 para 0,16. ou seja sempre para baixo.
 tem que declarar a unit math na uses da lib´s}
function Min_Round(const AValue: Double;
  const ADigit: TRoundToRange): Double;
var
  LFactor: Double;
begin
  LFactor := IntPower(10, ADigit);
  Result := Trunc(AValue * LFactor) / LFactor;
end;


e gravaria cada valor já arredondado:
procedure TfrmEnvioemail.ppDetailBand1BeforePrint(Sender: TObject);
var
  TotUnit, TotIPI, Desconto: double;
begin
  {if dsRelEnviaPed.DataSet.FieldByName(´DESCONTOS´).AsFloat = 0 then
     dsRelEnviaPed.DataSet.FieldByName(´DESCONTOS´).AsString := ´´;}

  {:Somas da banda DetailBand}
  TotUnit :=
    Min_Round(
      dsRelEnviaPed.DataSet.FieldByName(´QTDE´).asFloat *
      dsRelEnviaPed.DataSet.FieldByName(´VL_UNITARIO´).AsCurrency, 2
    );

  somaValorTotal.Value :=
    Min_Round(
      TotUnit * ((100 - dsRelEnviaPed.DataSet.FieldByName(´DESCONTOS´).AsFloat)/100), 2
    );

  {:Soma indice ipi}
  TotIPI :=
    Min_Round(
      (somaValorTotal.Value * dsRelEnviaPed.DataSet.FieldByName(´indice_ipi´).AsFloat)/100, 2
    );

  {:Soma o total dos produtos que vai na banda do Rodapé}
  SomaTotal.Value := (somaTotal.Value +  somaValorTotal.Value);

  {:Soma total do IPI}
  SomaIPI.Value := SomaIPI.Value + TotIPI;

  {:Soma total Descontos}
  SomaDesconto.Value := SomaDesconto.Value + (TotUnit - somaValorTotal.Value);

  {:Soma liquido}
  SomaLiquido.Value := SomaTotal.Value + SomaIPI.Value;
end;



Responder

10/07/2008

Luiz Henrique

Bom dia Adriano,

Posto postar sim, so que tem um problema, uso algumas funcoes dentro dela tbm minha, mas vejo que vc nao é um ´iniciante´ e vai entender a funcao, qualquer coisa ai me avisa, desculpe se ela ta escrita meio ´esquisita´ e que é antiga e nao reescrevi ela novamente:

function Arredondar(__numero: variant; __tam, _dec: integer): variant;
var _bk_tam, __tam_nr: integer; __nr_real, __nr_dec,__vlr_p_a:real;
__bk_nr_dec: variant;
__string: string;

begin
__bk_nr_dec:= frac(__numero);
__string:= formatfloat(´#0.00000000´,__numero*10); //str((__bk_nr_dec*10):12:8,__string);
if (val(__string) <> val(´1´)) then begin
__nr_dec:= 0; //inicializa para
__string:= formatfloat(stringofchar(´´,__tam-1)+´0.´+stringofchar(´0´,_dec+1),__nr_dec);//__numero); //str(__nr_dec:__tam:_dec,__string); //montar real casa do dec parametro pedido;
__string:= trim(__string)+´1´; //soma valor que servira p/ajuste no arredondamento
__vlr_p_a:= val(__string);
__nr_dec:= frac(__numero)+__vlr_p_a;
__string:= formatfloat(stringofchar(´#´,__tam-1)+´0.´+
stringofchar(´0´,_dec+1),__nr_dec); //__numero); //str(__nr_dec:__tam:(_dec+1),__string);
__string:= sonumero(__string);

__tam_nr:= length(__string);

__string:= copy(__string,1,__tam_nr-1)+DecSep+copy(__string,__tam_nr,1);
__nr_real:= val(__string);
__nr_real:= round(__nr_real);
__string:= strzero(__nr_real,_dec);

if __nr_real = 100 then __numero:= int(__numero) + 1
else __numero:= int(__numero)+val(´0´+DecSep+trim(__string));
end;
result:= __numero;
end;

espero que ajude, t+


Responder
Olá [b:e8f5cc34d1]Luiz Henrique[/b:e8f5cc34d1], obrigado por responder, mais já tinha resolvido com a fórmula que o colega [b:e8f5cc34d1]emerson.en[/b:e8f5cc34d1] postou.

Vou analisar a sua formula amigo, pode ser que venha a me ajudar em outros calculos também.

Obrigado a todos.

Problema resolvido

Mudaram a resposta spambot, eu nem tinha visto...demorei para conseguir postar sem ler que tinham mudado :D


Responder
×
+1 DevUP
Acesso diário, +1 DevUP
Parabéns, você está investindo na sua carreira