Ajuda - Busca - Membros - Calendário
Versão Completa: (Resolvido) Calculo de Dados - Dias Uteis - Função Jonas
Fórum Script Brasil > Programação & Desenvolvimento > Delphi, Kylix
Eder
Jonas caso for você quem ver este tópico, não sei se fiz o correto postar o probleminha aqui, mas em fim, se puderes me ajudar ou outro colega.
seguinte.

Na função:

CODE
function Dias_Uteis(DataI, DataF:TDate):Integer;
var contador, i, n :Integer; DataR : Tdate;
begin
   n := 0;
   if DataI > DataF then
      begin
         result  := 0;
         exit;
      end;

   Contador := 0;
   while (DataI <= DataF) do
   begin
      if ((DayOfWeek(DataI) <> 1) and (DayOfWeek(DataI) <> 7)) then
         Inc(Contador);

      for i := 0 to Form1.ComboBox1.Items.Count-1 do
         begin
            DataR := strtodate(Form1.ComboBox1.Items.Strings[i]);
            if DataR = int(DataI) then
               n := n + 1;
         end;

      DataI := DataI + 1;
   end;
   result := Contador-n;
end;


procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
begin
   i := Dias_Uteis(DateTimePicker1.Date ,DateTimePicker2.Date);
   showmessage('Total de dias úteis no período : ' + inttostr(i));
end;

Eu estou usando sua função no relatorio, porem como eu tenho que contar sempre diminuindo o primeiro dia util então inseri um -1 na linha:
   result := Contador-n-1;


Neste caso ele sempre diminue 1.

O problema é quando o primeiro dia cai num sabado ou domingo, neste caso ele faz a conta incorretamente.
Exemplo: se a primeira data for sabado dia 06-02 e a ultima data for 08-02 segunda ele deveria contar 1 dia util, porem ta contando 0.
Pela seu codigo original ele conta correto pois eu to diminuindo 1 na função.

tentei fazer um if mas não deu certo. pois se não for final de semana tem que ser assim:
QUOTE
result := Contador-n-1;
mas se for final de semana tem que ser assim:
QUOTE
result := Contador-n;


Como eu poderia contornar este problema?

Muito Obrigado

Jhonas
QUOTE
O problema é quando o primeiro dia cai num sabado ou domingo, neste caso ele faz a conta incorretamente.
Exemplo: se a primeira data for sabado dia 06-02 e a ultima data for 08-02 segunda ele deveria contar 1 dia util, porem ta contando 0.
CODE
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    DateTimePicker1: TDateTimePicker;
    DateTimePicker2: TDateTimePicker;
    Button1: TButton;
    ComboBox1: TComboBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

function Dias_Uteis(DataI, DataF:TDate):Integer;
var contador, i, n :Integer; DataR : Tdate;
begin
   n := 0;
   if DataI > DataF then
      begin
         result  := 0;
         exit;
      end;

   Contador := 0;
   while (DataI <= DataF) do
   begin
      if ((DayOfWeek(DataI) <> 1) and (DayOfWeek(DataI) <> 7)) then
         Inc(Contador);

      for i := 0 to Form1.ComboBox1.Items.Count-1 do
         begin
            DataR := strtodate(Form1.ComboBox1.Items.Strings[i]);
            if DataR = int(DataI) then
               n := n + 1;
         end;

      DataI := DataI + 1;
   end;
   result := Contador-n;
end;


procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
begin
   i := Dias_Uteis(DateTimePicker1.Date ,DateTimePicker2.Date);
   showmessage('Total de dias úteis no período : ' + inttostr(i));
end;


end.


Eder ... a função funciona corretamente

exemplo:

QUOTE
DateTimePicker1 = 06/03/2010

DateTimePicker2 = 08/03/2010

Total de dias úteis no período : 1



QUOTE
DateTimePicker1 = 07/03/2010

DateTimePicker2 = 08/03/2010

Total de dias úteis no período : 1


abraço
Eder
Bom Dia!
Sim Jonas, a função é show de bola.
você não entendeu a minha dúvida.

Eu estou usando a sua função para contar quantos dias eu levo para entregar uma mercadoria(transportadora).
então eu coleto a mercadoria num dia e entrego em outro dia.
O problema é que eu não posso contar o dia da coleta da mercadoria então na sua função em fiz assim nesta linha:
CODE
result := Contador-n-1;//note que inclui um -1 ai funciona menos um dia certinho.


Só que ai esbarrei num problema quando a coleta acontece num sabado ou domingo e a entrega ocorre na segunda ele não conta 1 dia e sim 0zero dia.

Como eu poderia contornar este problema....

Acredito que um IF resolveria o problema> tipo SE SABADO OU DOMINGO USA result := Contador-n; SENÃO result := Contador-n-1;

mas não to conseguindo montar este if, fiz alguns mas não obedece.

O que você acha?

Agradecido, Abraço.
Jhonas
QUOTE
Acredito que um IF resolveria o problema> tipo SE SABADO OU DOMINGO USA result := Contador-n; SENÃO result := Contador-n-1;
E é isso mesmo ....

QUOTE
mas não to conseguindo montar este if


Eder ... é muito facil fazer isso ...

CODE
function Dias_Uteis(DataI, DataF:TDate):Integer;
var contador, i, n, d :Integer; DataR : Tdate;
begin
   n := 0;
   d := 0;
   if DataI > DataF then
      begin
         result  := 0;
         exit;
      end;

   Contador := 0;
   while (DataI <= DataF) do
   begin
      if ((DayOfWeek(DataI) <> 1) and (DayOfWeek(DataI) <> 7)) then
         Inc(Contador);

      if contador > 1 then d := 1;

      for i := 0 to Form1.ComboBox1.Items.Count-1 do
         begin
            DataR := strtodate(Form1.ComboBox1.Items.Strings[i]);
            if DataR = int(DataI) then
               n := n + 1;
         end;

      DataI := DataI + 1;
   end;
   result := Contador-n-d;
end;


OBS: Precisa melhorar seu raciocínio lógico .rs


abraço
Douglas Soares
Eder, só pra deixar claro, se você quiser saber qual dia da semana você está, você usa a função DayOfWeek, segue um exemplo:

if (DayOfWeek(Date) = 7) or (DayOfWeek(Date) = 1) then
ShowMessage('HOJE É SABADO OU DOMINGO')
else
ShowMessage('HOJE É UM DIA DE SEMANA');

Date é a data do PC, você pode por qualquer componente de data ali...

caso não sabia...

1 = Domingo
2 = Segunda-Feira
3 = Terça-Feira
4 = Quarta-Feira
5 = Quinta-Feira
6 = Sexta-Feira
7 = Sabado

hehe

Abraços
Eder
Jonas, testei a sua idéia porem não ta dando certo:

06-02 a 08-02 = 1 deveria ser 1 este esta correto
06-02 a 09-02 = 1 deveria ser 2 segunda e terça
06-02 a 10-02 = 2 deveria ser 3 segunda, terça e quarta
06-02 a 11-02 = 3 deveria ser 4 segunda, terça, quarta e quinta


Ontem também fiz alguns if´s diferente do seu e também dava algo distorcido.

Será porque eu to chamando a função no OnPrint de um QrLabel?
CODE
i := Dias_Uteis(Query1DATA_EMISSAO.AsDateTime ,Query1ULT_OCORR_DATA.AsDateTime);
   VALUE:= inttostr(i);


Grato


Jhonas
Eder... aqui esta correto de acordo com o seu racicinio

QUOTE
DateTimePicker1 = 06/03/2010

DateTimePicker2 = 08/03/2010

Total de dias úteis no período : 1
QUOTE
DateTimePicker1 = 06/03/2010

DateTimePicker2 = 09/03/2010

Total de dias úteis no período : 1


QUOTE
DateTimePicker1 = 06/03/2010

DateTimePicker2 = 10/03/2010

Total de dias úteis no período : 2
QUOTE
DateTimePicker1 = 06/03/2010

DateTimePicker2 = 11/03/2010

Total de dias úteis no período : 3


Experimente sem o Time

CODE
i := Dias_Uteis(Query1DATA_EMISSAO.AsDate ,Query1ULT_OCORR_DATA.AsDate);
   VALUE:= inttostr(i);


abraço
Eder
Jonas, eu fiz este teste abaixo na sua função alterada e não funciona da o mesmo resultado:

CODE
Function Dias_Uteis(DataI, DataF:TDate):Integer;
var contador, i, n, d :Integer; DataR : Tdate;
begin
   n := 0;
   d := 0;
   if DataI > DataF then
      begin
         result  := 0;
         exit;
      end;

   Contador := 0;
   while (DataI <= DataF) do
   begin
      if ((DayOfWeek(DataI) <> 1) and (DayOfWeek(DataI) <> 7)) then
         Inc(Contador);

      if contador > 1 then d := 1;

      for i := 0 to Form1.ComboBox1.Items.Count-1 do
         begin
            DataR := strtodate(Form1.ComboBox1.Items.Strings[i]);
            if DataR = int(DataI) then
               n := n + 1;
         end;

      DataI := DataI + 1;
   end;
   result := Contador-n-d;
end;



procedure TForm1.BitBtn1Click(Sender: TObject);
var i : integer;
begin
   i := Dias_Uteis(DateTimePicker1.Date ,DateTimePicker2.Date);
   showmessage('Total de dias úteis no período : ' + inttostr(i));
end;

end.

Da este resultado igual ao relatorio no quick, ou seja, tirar o TIME não resolveria wacko.gif

Douglas, SIM EU fi

mas ai a função também não responde, ela diz que é SEMANA mas o if aponta FINAL DE SEMANA wacko.gif

VEJA A FUNÇÃO:

CODE
function Dias_Uteis(DataI, DataF:TDate):Integer;
var contador, i, n :Integer; DataR : Tdate;
Var Tipo:string;
begin
   n := 0;
   if DataI > DataF then
      begin
         result  := 0;
         exit;
      end;

   Contador := 0;
   while (DataI <= DataF) do
   begin
         Tipo:='';
      if ((DayOfWeek(DataI) <> 1) and (DayOfWeek(DataI) <> 7)) then
         Inc(Contador);
      if ((DayOfWeek(DataI) = 1) or (DayOfWeek(DataI) = 7)) then
         Tipo:='FSEMANA';

      for i := 0 to Form1.ComboBox1.Items.Count-1 do
         begin
            DataR := strtodate(Form1.ComboBox1.Items.Strings[i]);
            if DataR = int(DataI) then
               n := n + 1;
         end;

      DataI := DataI + 1;
   end;
   if Tipo = 'FSEMANA' Then
   begin
   result := Contador-n; //aqui tira um dia
   showmessage('FINAL DE SEMANA');
   end
   else
   begin
   result := Contador-n-1;  //aqui não
   showmessage('SEMANA');
   end;

   end;



Obrigado pessoal. wacko.gif
Jhonas
QUOTE
Jonas, eu fiz este teste abaixo na sua função alterada e não funciona da o mesmo resultado:


Eder... não sei o que voce esta fazendo de errado, mas os testes que fiz aqui estão corretos.

abraço
Eder
CODE
Eder... não sei o que voce esta fazendo de errado, mas os testes que fiz aqui estão corretos.


Mas Jonas eu estou fazendo igual ao seu, nem estou jogando no meu relatorio montei o esqueminha aqui no delphi, ou seja, peguei a sua função + o codigo do botão + os datetimer´s e mais nada.

Note que estou sempre pegando o dia 06-02 um sabado.
seu eu pegar qualquer dia da semana diferente do sabado e domingo ai da certo, tipo:

QUOTE
10-02 a 12-02 = 2
10-02 a 13-02 = 3
QUOTE
agora faz o teste do dia 13-02 sabado a dia 16-02(terça) o resultado da 1 dia, porem o correto é 2 dias


Pode ver que ta dando incorreto.

Abraço


Jhonas
Veja que fiz o código baseado nisso:

QUOTE
06-02 a 08-02 = 1 deveria ser 1 este esta correto
06-02 a 09-02 = 1 deveria ser 2 segunda e terça
06-02 a 10-02 = 2 deveria ser 3 segunda, terça e quarta
06-02 a 11-02 = 3 deveria ser 4 segunda, terça, quarta e quinta
depois voce coloca isso

QUOTE
agora faz o teste do dia 13-02 sabado a dia 16-02(terça) o resultado da 1 dia, porem o correto é 2 dias


Se tivesse colocado isso no inicio já tinha sido solucionado

veja como fica o codigo


CODE
Function Dias_Uteis(DataI, DataF:TDate):Integer;
var contador, i, n, d :Integer; DataR : Tdate;
begin
   n := 0;
   d := 0;
   if DataI > DataF then
      begin
         result  := 0;
         exit;
      end;

   Contador := 0;
   while (DataI <= DataF) do
   begin
      if ((DayOfWeek(DataI) <> 1) and (DayOfWeek(DataI) <> 7)) then
         Inc(Contador)
      else
         d := d + 1;

      for i := 0 to Form1.ComboBox1.Items.Count-1 do
         begin
            DataR := strtodate(Form1.ComboBox1.Items.Strings[i]);
            if DataR = int(DataI) then
               n := n + 1;
         end;

      DataI := DataI + 1;
   end;
   if d = 0 then
      result := Contador-n-1
   else
      result := (Contador-n-d)+d;
end;



procedure TForm1.BitBtn1Click(Sender: TObject);
var i : integer;
begin
   i := Dias_Uteis(DateTimePicker1.Date ,DateTimePicker2.Date);
   showmessage('Total de dias úteis no período : ' + inttostr(i));
end;


abraço
Eder
Perfeito Jonas, Calculou certinho.
Muito Obrigado pelo esforço.

Grande Abraço
Eder
QUOTE
Perfeito Jonas, Calculou certinho.


Achei que tava tudo certinho, no exemplo que citei realmente ta calculando correto, mas agora fiz outros testes com outras datas e deu resultado incorreto:

CODE
08-02 A 13-02 = 5 CORRETO É 4
08-02 A 23-02 =11 CORRETO É 10
15-02 A 24-02 = 8 CORRETO É 7


Ta dando um a mais.
Achei que tava resolvido, blush.gif

Se meche num lugar acaba afetando o outro, não ta facil, não

Grato

Jhonas
Acho que agora resolve

CODE
Function Dias_Uteis(DataI, DataF:TDate):Integer;
var contador, i, n :Integer; DataR : Tdate;
begin
   n := 0;

   if DataI > DataF then
      begin
         result  := 0;
         exit;
      end;

   Contador := 0;
   while (DataI <= DataF) do
   begin
      if ((DayOfWeek(DataI) <> 1) and (DayOfWeek(DataI) <> 7)) then
         Inc(Contador);

      for i := 0 to Form1.ComboBox1.Items.Count-1 do
         begin
            DataR := strtodate(Form1.ComboBox1.Items.Strings[i]);
            if DataR = int(DataI) then
               n := n + 1;
         end;

      DataI := DataI + 1;
   end;

   case DayOfWeek(Form1.DateTimePicker1.Date) of
     1: result := (Contador-n);
     7: result := (Contador-n);
   else
     result := (Contador-n-1);
   end;

end;


abraço
Eder
QUOTE
Acho que agora resolve

Sim, agora sim, fiz um monte de testes e realmente rodou certinho o relatório, ficou muito Bom e completo.
Espero não achar mais nenhum promeminha blush.gif .
Jonas, valeu a Força.
Abraços. biggrin.gif

Esta é uma versão simplificada de nosso conteúdo principal. Para ver a versão completa com maiores informações, formatação e imagens, por favor clique aqui.
Invision Power Board © 2001-2012 Invision Power Services, Inc.