Criando um calendário em tela através da FWCalendar – Maratona AdvPL e TL++ 209

Nesse vídeo demonstraremos a utilização da classe FWCalendar, que serve para criar um calendário em uma dialog.

Abaixo o código fonte desenvolvido para o exemplo em vídeo acima:

//Bibliotecas
#Include "TOTVS.ch"
 
//Posições do array dos agendamentos do calendário
#Define ID         1 // Id do Celula
#Define OBJETO     2 // Objeto de Tela
#Define DATADIA    3 // Data Completa da Celula
#Define DIA        4 // Dia Ref. Data da Celula
#Define MES        5 // Mes Ref. Data da Celula
#Define ANO        6 // Ano Ref. Data da Celula
#Define NSEMANO    7 // Semana do Ano Ref. Data da Celula
#Define NSEMMES    8 // Semana do Mes Ref. Data da Celula
#Define ATIVO      9 // É celula referente a um dia ativo
#Define FOOTER    10 // É celula referente ao rodape
#Define HEADER    11 // É celula referente ao Header
#Define SEMANA    12 // É celula referente a semana
#Define BGDefault 13 // Cor de BackGround da Celula
 
/*/{Protheus.doc} User Function zExe209
Tela de agendamentos do Telemarketing
@type  Function
@author Atilio
@since 20/02/2023
@version 1.0
@see https://tdn.totvs.com/display/public/framework/FWCalendar
@obs 
    
    **** Apoie nosso projeto, se inscreva em https://www.youtube.com/TerminalDeInformacao ****
/*/
 
User Function zExe209()
    Local aArea := GetArea()
    Private aSize := MsAdvSize(.F.)
 
    fMontaTela()
 
    RestArea(aArea)
Return
 
Static Function fMontaTela()
    Local nCorFundo     := 16777215
    Local nLargBtn      := 50
    //Data
    Private dDtIni := Date()
    Private cMes   := StrZero(Month(dDtIni), 2)
    Private cAno   := StrZero(Year(dDtIni),  4)
    //Objetos e componentes
    Private oDlgTmk
    Private oFwLayer
    Private oPanTitulo
    Private oPanCalend
    Private oPanPreMon
    Private oPanNexMon
    Private oPanSair
    Private oMesAtual
    Private cMesAno
    Private cTitHtml
    //Cabeçalho
    Private oSayModulo, cSayModulo := 'FAT'
    Private oSayTitulo, cSayTitulo := 'Calendário de Agendamentos'
    Private oSaySubTit, cSaySubTit := 'Clique com o botão direito para registrar agendamentos'
    //Tamanho da janela
    Private nJanLarg := aSize[5]
    Private nJanAltu := aSize[6]
    //Fontes
    Private cFontUti    := "Tahoma"
    Private oFontMod    := TFont():New(cFontUti, , -38)
    Private oFontSub    := TFont():New(cFontUti, , -20)
    Private oFontSubN   := TFont():New(cFontUti, , -20, , .T.)
    Private oFontBtn    := TFont():New(cFontUti, , -14)
    Private oFontSay    := TFont():New(cFontUti, , -12)
    //Variáveis usadas para atualização das informações
    Private aInfoDia
    Private nSelecao
    Private cTextoSel
    Private nPosCell
 
    //Cria a janela
    DEFINE MSDIALOG oDlgTmk TITLE "Agendamentos Telemarketing"  FROM 0, 0 TO nJanAltu, nJanLarg PIXEL
 
        //Criando a camada
        oFwLayer := FwLayer():New()
        oFwLayer:init(oDlgTmk,.F.)
 
        //Adicionando 3 linhas, a de título, a superior e a do calendário
        oFWLayer:addLine("TIT", 10, .F.)
        oFWLayer:addLine("SUP", 05, .F.)
        oFWLayer:addLine("CAL", 85, .F.)
 
        //Adicionando as colunas das linhas
        oFWLayer:addCollumn("HEADERTEXT",   050, .T., "TIT")
        oFWLayer:addCollumn("BLANKBTN",     040, .T., "TIT")
        oFWLayer:addCollumn("BTNSAIR",      010, .T., "TIT")
        oFWLayer:addCollumn("BLANKSUP1",    015, .T., "SUP")
        oFWLayer:addCollumn("BTNPREVMONTH", 020, .T., "SUP")
        oFWLayer:addCollumn("TITLE",        030, .T., "SUP")
        oFWLayer:addCollumn("BTNNEXTMONTH", 020, .T., "SUP")
        oFWLayer:addCollumn("COLCAL",       100, .T., "CAL")
 
        //Criando os paineis
        oPanTitulo := oFWLayer:GetColPanel("TITLE",        "SUP")
        oPanCalend := oFWLayer:GetColPanel("COLCAL",       "CAL")
        oPanPreMon := oFWLayer:GetColPanel("BTNPREVMONTH", "SUP")
        oPanNexMon := oFWLayer:GetColPanel("BTNNEXTMONTH", "SUP")
        oPanSair := oFWLayer:GetColPanel("BTNSAIR",      "TIT")
        oPanHeader := oFWLayer:GetColPanel("HEADERTEXT",   "TIT")
 
        //Títulos e SubTítulos
        oSayModulo := TSay():New(004, 003, {|| cSayModulo}, oPanHeader, "", oFontMod,  , , , .T., RGB(149, 179, 215), , 200, 30, , , , , , .F., , )
        oSayTitulo := TSay():New(004, 045, {|| cSayTitulo}, oPanHeader, "", oFontSub,  , , , .T., RGB(031, 073, 125), , 200, 30, , , , , , .F., , )
        oSaySubTit := TSay():New(014, 045, {|| cSaySubTit}, oPanHeader, "", oFontSubN, , , , .T., RGB(031, 073, 125), , 300, 30, , , , , , .F., , )
 
        //Criando os botões
        oBtnEnd := TButton():New(006, 001, "Fechar",             oPanSair, {|| oDlgTmk:End()}, nLargBtn, 018, , oFontBtn, , .T., , , , , , )
 
        //Cria o calendário
        oCalend := FWCalendar():New( VAL(cMes), VAL(cAno) )
        oCalend:aNomeCol    := { 'Domingo'    , 'Segunda' , 'Terça' , 'Quarta' , 'Quinta'    , 'Sexta' , 'Sábado' , 'Semana'}    //'Domingo'    # 'Segunda' # 'Terça' # 'Quarta' # 'Quinta'    # 'Sexta' # 'Sábado' # 'Semana'
        oCalend:lWeekColumn := .F.
        oCalend:lFooterLine := .F.
        oCalend:bLClicked   := {|| }
        oCalend:bLDblClick  := {|| }
        oCalend:bRClicked   := {|aInfo, oObj, nRow, nCol| fCliqueDir(aInfo, oObj, nRow, nCol) }
        fCalendFont()
        oCalend:Activate( oPanCalend )
 
        //Criando o Say com o mês Atual
        oMesAtual := TSay():New(0, 0, {|| }, oPanTitulo, , , , , , .T., 20, 20, , , , , , , , .T.)
        oMesAtual:Align := CONTROL_ALIGN_ALLCLIENT
        oMesAtual:nClrPane := nCorFundo
        fMesAno(Val(cMes), Val(cAno))
 
        //Criando o botão do Mês Anterior
        @ 0, 0 BTNBMP oPrevMonth Resource "PMSSETAESQ" Size 80, 90 Of oPanPreMon Pixel
        oPrevMontht:cToolTip := "Mes Anterior"    //"Mes Anterior"
        oPrevMonth:bAction  := { || FwMsgRun(Nil, {|| fMudaMes(oPanCalend, oCalend, 2 )}, Nil, "Montando calendário...") }    //"Montando calendário..."
        oPrevMonth:Align    := CONTROL_ALIGN_RIGHT
 
        //Criando o botão do Próximo Mês
        @ 0, 0 BTNBMP oNextMonth Resource "PMSSETADIR" Size 90, 90 Of oPanNexMon Pixel
        oNextMonth:cToolTip := "Proximo Mes"    //"Proximo Mes"
        oNextMonth:bAction  := { || FwMsgRun(Nil, {|| fMudaMes(oPanCalend, oCalend, 1 )}, Nil, "Montando calendário...") }    //"Montando calendário..."
        oNextMonth:Align    := CONTROL_ALIGN_LEFT
    Activate MsDialog oDlgTmk Centered
Return
 
/*
    Função que muda de mês
*/
 
Static Function fMudaMes(oPan, oCalend, nOp)
    Local nMonth    := oCalend:nMes
    Local nYear     := oCalend:nAno
    Default    nOp        := 1
 
    //Se for a seta ->, incrementa um mês
    If nOp == 1
        If nMonth == 12
            nMonth := 01
            nYear += 1
        Else
            nMonth := nMonth += 1
        EndIf
 
    //Se for a seta <-, diminui um mês
    ElseIf nOp == 2
        If nMonth == 01
            nMonth := 12
            nYear -= 1
        Else
            nMonth := nMonth -= 1
        EndIf
    EndIf
 
    //Define o calendário e seta o título
    oCalend:SetCalendar( oPan, cValToChar(nMonth), cValToChar(nYear) )
    fMesAno(nMonth, nYear)
Return
 
/*
    Função que define o texto do título em cima do calendário
*/
 
Static Function fMesAno(nMonth, nYear)
    cMesAno := Capital(MesExtenso(nMonth)) + " / " + cValToChar(nYear)
    cTitHtml := fTitHTML(cMesAno)
    oMesAtual:SetText( cTitHtml )
 
    //Chama a busca de informações para definir as informações no calendário
    fBuscaInfo()
Return Nil
 
/*
    Função que transforma o título no formato html
*/
 
Static Function fTitHTML(cMesAno)
    Local cRet := ''
    cRet += '

' cRet += '' + cMesAno + '' cRet += '

' Return cRet /* Função que define o primeiro calendário com a fonte Tahom */ Static Function fCalendFont() oCalend:aFontDay[1] := cFontUti oCalend:aFontDayHead[1] := cFontUti oCalend:aFontDayText[1] := cFontUti oCalend:aFontFooter[1] := cFontUti oCalend:aFontFsFer[1] := cFontUti oCalend:aFontHeader[1] := cFontUti oCalend:aFontOff[1] := cFontUti oCalend:aFontToday[1] := cFontUti oCalend:aFontWeek[1] := cFontUti oCalend:cHtmlDay := StrTran(oCalend:cHtmlDay, "MS Sans Serif", cFontUti) oCalend:cHtmlDayOff := StrTran(oCalend:cHtmlDayOff, "MS Sans Serif", cFontUti) oCalend:cHtmlFooter := StrTran(oCalend:cHtmlFooter, "MS Sans Serif", cFontUti) oCalend:cHtmlHeader := StrTran(oCalend:cHtmlHeader, "MS Sans Serif", cFontUti) oCalend:cHtmlToday := StrTran(oCalend:cHtmlToday, "MS Sans Serif", cFontUti) oCalend:cHtmlWeek := StrTran(oCalend:cHtmlWeek, "MS Sans Serif", cFontUti) oCalend:cHtmlWeekend := StrTran(oCalend:cHtmlWeekend, "MS Sans Serif", cFontUti) Return /* Função que busca as informações e atualiza a agenda */ Static Function fBuscaInfo() Local nCell Local nDia For nCell := 1 To (Len(oCalend:aCell) - 10) nDia := oCalend:aCell[nCell][DIA] // Dia //nMes := oCalend:aCell[nCell][MES] // Mês //nAno := oCalend:aCell[nCell][ANO] // Ano //Se for um dia útil If oCalend:aCell[nCell][ATIVO] .And. nDia == 10 aItens := {} aAdd(aItens, "000001 - Cliente A") aAdd(aItens, "000002 - Cliente B") aAdd(aItens, "000003 - Cliente C") //Define as informações da célula oCalend:SetInfo(oCalend:aCell[nCell][ID], aClone(aItens)) EndIf //Se for um dia útil If oCalend:aCell[nCell][ATIVO] //Definindo o nome do dia no calendário dDataAtu := oCalend:aCell[nCell][DATADIA] cObsText := "" cDia := StrZero(Day(dDataAtu), 2) //Se a data não for válida If DataValida(dDataAtu) != dDataAtu //Se for domingo ou sábado, será FDS senão será FERIADO If Dow(dDataAtu) == 1 .Or. Dow(dDataAtu) == 7 cObsText := "FDS" Else cObsText := "FERIADO" EndIf //Define o título da célula cHtml := '

' + cDia + ' - ' + cObsText + '

' oCalend:aCell[nCell][OBJETO]:oEditTitle:cTitle := cHtml Else //Define o título da célula cHtml := '

' + cDia + '

' oCalend:aCell[nCell][OBJETO]:oEditTitle:cTitle := cHtml EndIf EndIf Next Return /* Função que mostra PopUp, ao clicar com o botão direito */ Static Function fCliqueDir(aInfo, oObj, nRow, nCol) Local cClassName := Upper(Alltrim(oObj:ClassName())) Local oMenu Local oMenuItem := {} Local aOpcoes := {} Local nOpcao := 0 Local dData := aInfo[DATADIA] aInfoDia := aInfo nSelecao := aInfo[OBJETO]:nSelectedIndex cTextoSel := "" nPosCell := aScan(oCalend:aCell, {|x| AllTrim(Upper(x[1])) == aInfo[1]}) //Somente se estiver dentro do ListBox If cClassName == "TLISTBOX" aAdd(aOpcoes, {"Novo Agendamento", {|| fPopOpcao(3, dData)}}) //Se houver linhas, terá outras opções If nSelecao != 0 aAdd(aOpcoes, {"Visualizar Agendamento", {|| fPopOpcao(2, dData)}}) aAdd(aOpcoes, {"Alterar Agendamento", {|| fPopOpcao(4, dData)}}) aAdd(aOpcoes, {"Excluir Agendamento", {|| fPopOpcao(5, dData)}}) cTextoSel := aInfo[OBJETO]:oListBoxContent:aItems[nSelecao] Endif EndIf //Criando o menu e os itens MENU oMenu POPUP For nOpcao := 1 To Len(aOpcoes) aAdd( oMenuItem, MenuAddItem(aOpcoes[nOpcao][1], , , .T., , , , oMenu, aOpcoes[nOpcao][2], , , , , {|| .T.}) ) Next ENDMENU oMenu:Activate(nRow, nCol, oObj) Return Static Function fPopOpcao(nOpcao, dData) Local aPergs := {} Local cTexto := "" Local cEditCli := ".F." Local cCliente := Space(TamSX3('A1_COD')[1]) Local cLoja := Space(TamSX3('A1_LOJA')[1]) Local cObserv := "" Default nOpcao := 3 Default dData := Date() //Define o texto If nOpcao == 3 cEditCli := ".T." cTexto := "Inclusão de Agendamento" Else cEditCli := ".F." If nOpcao == 2 cTexto := "Visualização de Agendamento" ElseIf nOpcao == 4 cTexto := "Alteração de Agendamento" ElseIf nOpcao == 5 cTexto := "Exclusão de Agendamento" EndIf cCliente := SubStr(cTextoSel, 1, 6) cLoja := "01" cTexto += " (" + SubStr(cTextoSel, 10, Len(cTextoSel)) + ")" EndIf //Adiciona os parâmetros aAdd(aPergs, {09, cTexto, 200, 40, .T.}) aAdd(aPergs, {01, "Data", dData, "", ".T.", "", ".F.", 80, .T.}) aAdd(aPergs, {01, "Cliente", cCliente, "", ".T.", "SA1", cEditCli, 80, .T.}) aAdd(aPergs, {01, "Loja", cLoja, "", ".T.", "", cEditCli, 80, .T.}) aAdd(aPergs, {11, "Histórico", cObserv, ".T.", ".T.", .T.}) //Se a pergunta for confirmada If ParamBox(aPergs, "Informe os parâmetros", , , , , , , , , .F., .F.) cCliente := MV_PAR03 cLoja := MV_PAR04 cObserv := MV_PAR05 cNomeCli := Posicione('SA1', 1, FWxFilial('SA1') + cCliente + cLoja, "A1_NOME") //Se for inclusão, adiciona no calendário If nOpcao == 3 aItens := aClone(aInfoDia[OBJETO]:oListBoxContent:aItems) aAdd(aItens, cCliente + " - " + SubStr(cNomeCli, 1, 15)) oCalend:SetInfo(oCalend:aCell[nPosCell][ID], aClone(aItens)) //Se for exclusãoRetira o elemento do array e depois define no calendário ElseIf nOpcao == 5 aItens := aClone(aInfoDia[OBJETO]:oListBoxContent:aItems) aDel(aItens, nSelecao) aSize(aItens, Len(aItens) - 1) oCalend:SetInfo(oCalend:aCell[nPosCell][ID], aClone(aItens)) EndIf EndIf Return

Bom pessoal, por hoje é só.

Abraços e até a próxima

Dan (Daniel Atilio)
Cristão de ramificação protestante. Especialista em Engenharia de Software pela FIB, graduado em Banco de Dados pela FATEC Bauru e técnico em informática pelo CTI da Unesp. Entusiasta de soluções Open Source e blogueiro nas horas vagas. Autor e mantenedor do portal Terminal de Informação.

Deixe uma resposta

Terminal de Informação