Função que retorna o número de dias úteis entre duas datas utilizando AdvPL

Olá pessoal…

Hoje vou mostrar uma função desenvolvida que retorna o número de dias úteis entre duas datas utilizando a linguagem AdvPL.

AdvPL

AdvPL

Esta rotina para a contagem dos dias, desconsidera sábados, domingos e feriados (cadastrados na tabela 63 da SX5), então por exemplo, entre os dias 30/10/2016 até 05/11/2016, quantos dias são úteis?

A rotina no caso retorna 4, que representa o número de dias úteis entre as duas datas de referência.

Abaixo a rotina completa.

//Bibliotecas
#Include "Protheus.ch"

/*/{Protheus.doc} zDiasUteis
Função que retorna a quantidade de dias úteis entre duas datas
@author Atilio
@since 25/10/2016
@version 1.0
@type function
	@param dDtIni, date, Data inicial a ser considerada
	@param dDtFin, date, Data final a ser considerada
	@example u_zDiasUteis(sToD("20161001"), sToD("20161025"))
	u_zDiasUteis(FirstDate(dDataBase), LastDate(dDataBase))
	@obs Quanto as feriados, eles devem estar cadastrados na SX5, tabela "63"
/*/

User Function zDiasUteis(dDtIni, dDtFin)
	Local aArea    := GetArea()
	Local nDias    := 0
	Local dDtAtu   := sToD("")
	Default dDtIni := dDataBase
	Default dDtFin := dDataBase
	
	//Enquanto a data atual for menor ou igual a data final
	dDtAtu := dDtIni
	While dDtAtu <= dDtFin
		//Se a data atual for uma data Válida
		If dDtAtu == DataValida(dDtAtu) 
			nDias++
		EndIf
		
		dDtAtu := DaySum(dDtAtu, 1)
	EndDo
	
	RestArea(aArea)
Return nDias

Bom pessoal, por hoje é só.
Abraços e até a próxima.

Dan (Daniel Atilio)
Especialista em Engenharia de Software pela FIB. Entusiasta de soluções Open Source. E blogueiro nas horas vagas.

6 Responses

  1. Rodriog disse:

    Parabéns pelos posts, tem alguma funcao que retorno o 5. dia util do mes?

    • Dan_Atilio disse:

      Boa noite Rodrigo, tudo bem?
      De cabeça desconheço, o que você poderia fazer é:

      dDataRef := Date() //Pega a data de referência
      dPrimDia := FirstDate(dDataRef) //Pega o primeiro dia do mês
      d5Dias := DaySum(dPrimDia, 4) //Soma mais 4 dias no primeiro dia do mês
      dQuinto := DataValida(d5Dias)
      

      Seria +- assim eu acho.
      Um grande abraço.

  2. gabriel disse:

    Bom dia Dan, tudo certo?

    Gostaria de saber se você pode me auxiliar em um fonte aqui.

    Este fonte faz o totalizador por período definido nos parâmetros iniciais, gostaria de saber se tem como eu fazer o totalizador também pelas datas que constam neste período?

    Segue fonte:

    User Function IFINR028()

    Local vPerg := {}
    Private cNomRel := “IFINR028”
    Private rTitRel := “Relatório de Limite Extra”
    Private cPerg := PadR(cNomRel,Len(SX1->X1_GRUPO))

    aAdd(vPerg,{“Data de ?” ,”D”, 8, 0, “G”,,””}) //MV_PAR01
    aAdd(vPerg,{“Data até ?”,”D”, 8, 0, “G”,,””}) //MV_PAR02

    U_FtCriaSX1( cPerg, vPerg)

    If !Pergunte(cPerg,.T.)
    Return
    EndIf

    oReport := ReportDef()
    oReport:PrintDialog()

    Return

    ********************************
    Static Function ReportDef()
    ********************************
    Private oReport

    //*Sintaxe: TReport():New(cNome,cTitulo,cPerguntas,bBlocoCodigo,cDescricao)*/
    oReport := TReport():NEW(cNomRel, rTitRel, cPerg, {|oReport| Imprime(oReport)}, rTitRel, .F.)
    oReport:SetTotalInLine(.F.)
    oReport:SetLandscape(.T.)
    oReport:lParamPage := .F.

    oSec := TRSection():New(oReport , rTitRel , {} )

    TRCELL():NEW(oSec , “FILIAL” , “SZB”, “Filial”, , 2)
    TRCELL():NEW(oSec , “CONTRATO” , “SZB”, “Contrato”, , 15)
    TRCELL():NEW(oSec , “CODIGO” , “SZB”, “Codigo”, , 6)
    TRCELL():NEW(oSec , “LOJA” , “SZB”, “Loja”, , 3)
    TRCELL():NEW(oSec , “NOME” , “SZB”, “Nome”, , 60)
    TRCELL():NEW(oSec , “DATA_DO_LIMITE” , “SZB”, “Dta.do Limite”, , 8)
    TRCELL():NEW(oSec , “RESPOSAVEL” , “SZB”, “Resposavel”, , 25)
    TRCELL():NEW(oSec , “EMITENTE” , “SZB”, “Emitente”, , 20)
    TRCELL():NEW(oSec , “HISTORICO” , “SZB”, “Historico”, , 60)
    TRCELL():NEW(oSec , “VALOR_INSERIDO” , “SZB”, “Valor Inserido”, “@E 999,999,999.99”, 15)

    oBreak := TRBreak():New(oSec,oSec:Cell(“VALOR_INSERIDO”),,.T.)
    //TRFunction():New(oSecCab:Cell(“ZDA_QUANT”),/*cId*/,”COUNT” ,/*oBreak*/,”QUANTIDADE DE NOTAS”,/*cPicture*/,/*uFormula*/,.F. ,.T. ,.F. ,oSecCab)
    TRFunction():New(oSec:Cell(“VALOR_INSERIDO”),”Total Geral R$” ,”SUM”,oBreak,”Total R$”,”@E 999,999,999.99″,,.F.,.T.)

    oSec:SetLeftMargin(0)

    Return oReport

    ********************************
    Static Function IMPRIME(oReport)
    ********************************

    Local cAliTMP := GetNextAlias()
    Private oSec := oReport:Section(1)

    oReport:SetTitle(rTitRel+” de “+DtoC(MV_PAR01)+” até “+DtoC(MV_PAR02))

    oReport:Section(1):BeginQuery()

    If Select(“cAliTMP”) 0
    dbSelectArea(“cAliTMP”)
    dbCloseArea()
    EndIf

    BeginSQL alias cAliTMP

    SELECT ZB_FILIAL FILIAL,
    ZB_CONTRA CONTRATO,
    ZB_CLIENTE CODIGO,
    ZB_LOJCLI LOJA,
    A1_NOME NOME,
    SUBSTR(ZB_DATINC,7,2)||’/’||SUBSTR(ZB_DATINC,5,2)||’/’||SUBSTR(ZB_DATINC,1,4) DATA_DO_LIMITE,
    ZB_USERNAM RESPOSAVEL,
    UTL_RAW.CAST_TO_VARCHAR2(dbms_lob.substr(ZB_JUSTIF,100,1)) HISTORICO, //BUSCA AS INFORMACOES DE UM CAMPO MEMO
    ZB_VLADIC VALOR_INSERIDO
    FROM %table:SZB% ZB
    INNER JOIN SA1010 A1 ON A1_COD = ZB_CLIENTE
    AND ZB_LOJCLI = A1_LOJA
    AND A1.D_E_L_E_T_ = ‘ ‘
    WHERE ZB_FILIAL = %xFilial:SZB%
    AND ZB_DATINC BETWEEN %exp:MV_PAR01% and %exp:MV_PAR02%
    AND ZB.D_E_L_E_T_ = ‘ ‘
    ORDER BY ZB.ZB_DATINC DESC

    EndSql

    If Select(“cAliTMP”) 0
    dbSelectArea(“cAliTMP”)
    dbCloseArea()
    EndIf

    oReport:Section(1):EndQuery()
    oReport:Section(1):Print()

    If !Empty(cAliTMP) .and. Select(cAliTMP) 0
    dbSelectArea(cAliTMP)
    (cAliTMP)->(dbCloseArea())
    endif

    Return

    • Boa tarde Gabriel, tudo joia graças a Deus e você?

      Você precisa adicionar um TRBreak da coluna com o seu campo de Data, ai sempre que alterar o valor, ele irá quebrar o relatório.

      Ah, caso você seja um Assinante Premium, basta nos enviar uma mensagem no WhatsApp ou eMail que fica mais rápido para conversarmos.

      Um grande abraço.

      • gabriel disse:

        Boa Tarde Dan, bah voce me ajudou muito fiz o oBreak pela Data com isto cada vez que a data for diferente ele faz a quebra de linha e depois me joga o total dos valores.

        oBreak := TRBreak():New(oSec,oSec:Cell(“DATA_DO_LIMITE”),,.T.)
        TRFunction():New(oSec:Cell(“DATA_DO_LIMITE”),,,oBreak,,,,.F.,.T.)
        TRFunction():New(oSec:Cell(“VALOR_INSERIDO”),,”SUM”,oBreak,”Total R$”,”@E 999,999,999.99″,,.F.,.T.)

        Muito obrigado pela sua atenção. Precisar de alguma coisa que for do meu alcance estou a disposição.
        Abraço

Deixe uma resposta