Como saber em qual coluna foi clicado no FWBrowse

No artigo de hoje, vou mostrar como identificar em qual coluna foi clicado em uma grid usando FWBrowse.
Recentemente, estávamos conversando no Discord, e meu amigo Alison Kaique ( LinkedIn ) comentou que um método interessante no FWBrowse é o ColPos que retorna a coluna que foi clicado.

Pensando nisso, decidi montar um exemplo, ao dar duplo clique na grid, para exibir a informação (no caso você pode até adaptar o exemplo para mostrar um ParamBox ou algum outro recurso para atualizar a informação da grid).

Abaixo um print de exemplo:

Exemplo de duplo clique em uma coluna

E abaixo o código fonte desenvolvido:

#Include "Totvs.ch"
 
/*/{Protheus.doc} User Function zGrid
Visualizacao de Grupos de Produtos com FWBrowse e FWTemporaryTable com duplo clique
@type  Function
@author Atilio
@since  09/06/2021
@version version
/*/
 
User Function zGrid()
    Local aArea := GetArea()
    //Fontes
    Local cFontUti    := "Tahoma"
    Local oFontAno    := TFont():New(cFontUti,,-38)
    Local oFontSub    := TFont():New(cFontUti,,-20)
    Local oFontSubN   := TFont():New(cFontUti,,-20,,.T.)
    Local oFontBtn    := TFont():New(cFontUti,,-14)
    //Janela e componentes
    Private oDlgGrp
    Private oPanGrid
    Private oGetGrid
    Private aColunas := {}
    Private cAliasTab := "TMPSBM"
    //Tamanho da janela
    Private    aTamanho := MsAdvSize()
    Private    nJanLarg := aTamanho[5]
    Private    nJanAltu := aTamanho[6]
 
    //Cria a temporária
    oTempTable := FWTemporaryTable():New(cAliasTab)
     
    //Adiciona no array das colunas as que serão incluidas (Nome do Campo, Tipo do Campo, Tamanho, Decimais)
    aFields := {}
    aAdd(aFields, {"XXCODIGO", "C", TamSX3('BM_GRUPO')[01],   0})
    aAdd(aFields, {"XXDESCRI", "C", TamSX3('BM_DESC')[01],    0})
    aAdd(aFields, {"XXSTATUS", "C", TamSX3('BM_STATUS')[01],  0})
    aAdd(aFields, {"XXPROORI", "C", TamSX3('BM_PROORI')[01],  0})
    aAdd(aFields, {"XXTOTALP", "N", 18,                       0})
    aAdd(aFields, {"XXSBMREC", "N", 18,                       0})
     
    //Define as colunas usadas, adiciona indice e cria a temporaria no banco
    oTempTable:SetFields( aFields )
    oTempTable:AddIndex("1", {"XXCODIGO"} )
    oTempTable:Create()
 
    //Monta o cabecalho
    fMontaHead()
 
    //Montando os dados, eles devem ser montados antes de ser criado o FWBrowse
    FWMsgRun(, {|oSay| fMontDados(oSay) }, "Processando", "Buscando grupos")
 
    //Criando a janela
    DEFINE MSDIALOG oDlgGrp TITLE "Grupos de Produtos" FROM 000, 000  TO nJanAltu, nJanLarg COLORS 0, 16777215 PIXEL
        //Labels gerais
        @ 004, 003 SAY "FAT"                      SIZE 200, 030 FONT oFontAno  OF oDlgGrp COLORS RGB(149,179,215) PIXEL
        @ 004, 050 SAY "Listagem de"              SIZE 200, 030 FONT oFontSub  OF oDlgGrp COLORS RGB(031,073,125) PIXEL
        @ 014, 050 SAY "Grupos de Produtos"       SIZE 200, 030 FONT oFontSubN OF oDlgGrp COLORS RGB(031,073,125) PIXEL
 
        //Botões
        @ 006, (nJanLarg/2-001)-(0052*01) BUTTON oBtnFech  PROMPT "Fechar"        SIZE 050, 018 OF oDlgGrp ACTION (oDlgGrp:End())   FONT oFontBtn PIXEL
 
        //Dados
        @ 024, 003 GROUP oGrpDad TO (nJanAltu/2-003), (nJanLarg/2-003) PROMPT "Grupos (Para ver a legenda basta clicar duas vezes em alguma bolinha): " OF oDlgGrp COLOR 0, 16777215 PIXEL
        oGrpDad:oFont := oFontBtn
            oPanGrid := tPanel():New(033, 006, "", oDlgGrp, , , , RGB(000,000,000), RGB(254,254,254), (nJanLarg/2 - 13),     (nJanAltu/2 - 45))
            oGetGrid := FWBrowse():New()
            oGetGrid:DisableFilter()
            oGetGrid:DisableConfig()
            oGetGrid:DisableReport()
            oGetGrid:DisableSeek()
            oGetGrid:DisableSaveConfig()
            oGetGrid:SetFontBrowse(oFontBtn)
            oGetGrid:SetAlias(cAliasTab)
            oGetGrid:SetDataTable()
            oGetGrid:SetInsert(.F.)
            oGetGrid:SetDelete(.F., { || .F. })
            oGetGrid:lHeaderClick := .F.
            oGetGrid:AddLegend(cAliasTab + "->XXPROORI == '0'", "RED",    "Nao Original")
            oGetGrid:AddLegend(cAliasTab + "->XXPROORI == '1'", "GREEN",  "Original")
            oGetGrid:AddLegend("Empty(" + cAliasTab + "->XXPROORI)", "BLACK",  "Sem Classificacao")
            oGetGrid:SetColumns(aColunas)
            oGetGrid:SetOwner(oPanGrid)
            oGetGrid:SetDoubleClick( {|| fGrupo() } ) 
            oGetGrid:Activate()
    ACTIVATE MsDialog oDlgGrp CENTERED
 
    //Deleta a temporaria
    oTempTable:Delete()
 
    RestArea(aArea)
Return
 
Static Function fMontaHead()
    Local nAtual
    Local aHeadAux := {}
 
    //Adicionando colunas
    //[1] - Campo da Temporaria
    //[2] - Titulo
    //[3] - Tipo
    //[4] - Tamanho
    //[5] - Decimais
    //[6] - Máscara
    aAdd(aHeadAux, {"XXCODIGO", "Código",            "C", TamSX3('BM_GRUPO')[01],   0, ""})
    aAdd(aHeadAux, {"XXDESCRI", "Descricao",         "C", TamSX3('BM_DESC')[01],    0, ""})
    aAdd(aHeadAux, {"XXSTATUS", "Status Grupo",      "C", TamSX3('BM_STATUS')[01],  0, ""})
    aAdd(aHeadAux, {"XXPROORI", "Procedencia",       "C", TamSX3('BM_PROORI')[01],  0, ""})
    aAdd(aHeadAux, {"XXTOTALP", "Total de Produtos", "N", 18,                       0, "@E 999,999,999,999,999,999"})
    aAdd(aHeadAux, {"XXSBMREC", "SBM RecNo",         "N", 18,                       0, "@E 999,999,999,999,999,999"})
 
    //Percorrendo e criando as colunas
    For nAtual := 1 To Len(aHeadAux)
        oColumn := FWBrwColumn():New()
        oColumn:SetData(&("{|| " + cAliasTab + "->" + aHeadAux[nAtual][1] +"}"))
        oColumn:SetTitle(aHeadAux[nAtual][2])
        oColumn:SetType(aHeadAux[nAtual][3])
        oColumn:SetSize(aHeadAux[nAtual][4])
        oColumn:SetDecimal(aHeadAux[nAtual][5])
        oColumn:SetPicture(aHeadAux[nAtual][6])
        aAdd(aColunas, oColumn)
    Next
Return
 
Static Function fMontDados(oSay)
    Local aArea := GetArea()
    Local cQry  := ""
    Local nAtual := 0
    Local nTotal := 0
 
    //Zera a grid
    aColsGrid := {}
     
    //Montando a query
    oSay:SetText("Montando a consulta")
    cQry := " SELECT "                                                  + CRLF
    cQry += "     BM_GRUPO, "                                           + CRLF
    cQry += "     BM_DESC, "                                            + CRLF
    cQry += "     BM_STATUS, "                                          + CRLF
    cQry += "     BM_PROORI, "                                          + CRLF
    cQry += "     ( "                                                   + CRLF
    cQry += "         SELECT "                                          + CRLF
    cQry += "             COUNT(*) "                                    + CRLF
    cQry += "         FROM "                                            + CRLF
    cQry += "             " + RetSQLName('SB1') + " SB1 "               + CRLF
    cQry += "         WHERE "                                           + CRLF
    cQry += "             B1_FILIAL = '" + FWxFilial('SB1') + "' "      + CRLF
    cQry += "             AND B1_GRUPO = BM_GRUPO "                     + CRLF
    cQry += "             AND B1_MSBLQL != '1' "                        + CRLF
    cQry += "             AND SB1.D_E_L_E_T_ = ' ' "                    + CRLF
    cQry += "     ) AS TOT_PROD, "                                      + CRLF
    cQry += "     SBM.R_E_C_N_O_ AS SBMREC "                            + CRLF
    cQry += " FROM "                                                    + CRLF
    cQry += "     " + RetSQLName('SBM') + " SBM "                       + CRLF
    cQry += " WHERE "                                                   + CRLF
    cQry += "     BM_FILIAL = '" + FWxFilial('SBM') + "' "              + CRLF
    cQry += "     AND SBM.D_E_L_E_T_ = ' ' "                            + CRLF
    cQry += " ORDER BY "                                                + CRLF
    cQry += "     BM_GRUPO "                                            + CRLF
 
    //Executando a query
    oSay:SetText("Executando a consulta")
    PLSQuery(cQry, "QRY_SBM")
 
    //Se houve dados
    If ! QRY_SBM->(EoF())
        //Pegando o total de registros
        DbSelectArea("QRY_SBM")
        Count To nTotal
        QRY_SBM->(DbGoTop())
 
        //Enquanto houver dados
        While ! QRY_SBM->(EoF())
 
            //Muda a mensagem na regua
            nAtual++
            oSay:SetText("Adicionando registro " + cValToChar(nAtual) + " de " + cValToChar(nTotal) + "...")
 
            RecLock(cAliasTab, .T.)
                (cAliasTab)->XXCODIGO := QRY_SBM->BM_GRUPO
                (cAliasTab)->XXDESCRI := QRY_SBM->BM_DESC
                (cAliasTab)->XXSTATUS := QRY_SBM->BM_STATUS
                (cAliasTab)->XXPROORI := QRY_SBM->BM_PROORI
                (cAliasTab)->XXTOTALP := QRY_SBM->TOT_PROD
                (cAliasTab)->XXSBMREC := QRY_SBM->SBMREC
            (cAliasTab)->(MsUnlock())
 
            QRY_SBM->(DbSkip())
        EndDo
 
    Else
        MsgStop("Nao foi encontrado registros!", "Atencao")
 
        RecLock(cAliasTab, .T.)
            (cAliasTab)->XXCODIGO := ""
            (cAliasTab)->XXDESCRI := ""
            (cAliasTab)->XXSTATUS := ""
            (cAliasTab)->XXPROORI := ""
            (cAliasTab)->XXTOTALP := 0
            (cAliasTab)->XXSBMREC := 0
        (cAliasTab)->(MsUnlock())
    EndIf
    QRY_SBM->(DbCloseArea())
    (cAliasTab)->(DbGoTop())
 
    RestArea(aArea)
Return
 
Static Function fGrupo()
    Local lLegenda := .T. //.T. se tiver bolinha de legenda e .F. se não tiver, para poder subtrair da linha abaixo
    Local nColuna  := oGetGrid:ColPos() - Iif(lLegenda, 1, 0)
    Local cTitulo
    Local xConteu

    //Se for uma coluna válida (não for legenda)
    If nColuna != 0
        cTitulo  := Alltrim(aColunas[nColuna]:cTitle)
        xConteu  := eVal(aColunas[nColuna]:bData)

        //Tratativa se for numérico ou caractere para exibir como caractere
        If aColunas[nColuna]:cType == "N"
            xConteu := cValToChar(xConteu)
        ElseIf aColunas[nColuna]:cType == "D"
            xConteu := dToC(xConteu)
        EndIf

        MsgInfo("Estou no grupo: " + (cAliasTab)->XXCODIGO + CRLF + "Coluna: " + cTitulo + CRLF + "Conteudo: " + xConteu, "Atencao")
    EndIf
Return

Caso você use array, e seja necessário atualizar o conteúdo, poderia fazer algo nesse sentido:

//Pegando a linha e a coluna
nLinha := oGetGrid:At()
nColuna := oGetGrid:ColPos()

//Editando a variavel de aCols da grid na linha e coluna
aColsGrid[nLinha][nColuna] := "TST"

//Posicionando na linha que foi editada e forçando a atualização da tela
oGetGrid:GoTo(nLinha, .T.)

Bom pessoal, por hoje é só.

Abraços e até a próxima.

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

4 Responses

  1. Parabéns por mais um post meu amigo, como sempre qualidade no ensino e didática imprescindível.
    Abraço e Deus abençoe.

  2. Douglas disse:

    Showww !!! Esse é o Atilio, nunca coloca na gaveta os conhecimentos, parabéns e sucesso

Deixe uma resposta