Como atualizar um browse ao alternar de linha de outro browse | Ti Responde 0070

No vídeo de hoje, vamos demonstrar em como criar manualmente dois browses, sendo que ao mexer em um, o outro é atualizado.

A dúvida de hoje, nos perguntaram, como seria possível criar dois browses manualmente, sem usar MVC (setRelation) e sem usar a classe FWBrwRelation, mas sendo que ao mexer em um browse o outro seja atualizado.

 

Pensando nisso, montamos esse exemplo, onde temos dois FWMarkBrowse, mas só o da direita vai ter marcação. E no da esquerda, usamos o bChange, sendo que ao alternar entre as linhas o da direita será atualizado. Segue abaixo o vídeo exemplificando:

 

E abaixo o código fonte desenvolvido para exemplificar:

//Bibliotecas
#Include "TOTVS.ch"
#Include "TopConn.ch"

/*/{Protheus.doc} User Function zVid0070
Exemplo de um browse que atualiza o outro manualmente (sem usar MVC com SetRelation e sem usar FWBrwRelation)
@type  Function
@author Atilio
@since 13/11/2023
@obs Baixe o zExecQry nesse link - https://terminaldeinformacao.com/2021/04/21/como-fazer-um-update-via-advpl/
/*/

User Function zVid0070()
    Local aArea        := GetArea()
    Local cFontPad     := 'Tahoma'
    Local oFontGrid    := TFont():New(cFontPad,,-14)
    Local bBlocoOk     := {|| lOk := .T., fMostraMark(), oDlgMark:End()}
    Local bBlocoCan    := {|| lOk := .F., oDlgMark:End()}
    Local aOutrasAc    := {}
    Local bBlocoIni    := {|| EnchoiceBar(oDlgMark, bBlocoOk, bBlocoCan, , aOutrasAc)}
    Local lDimPixels   := .T.
    Local cJanTitulo   := "Estados x Cidades"
    Local lCentraliz   := .T.
    //Janela e componentes
    Private oDlgMark
    Private aRotina    := MenuDef()
    //Estado
    Private oPanelEst
    Private oMarkEst
    Private cAliasEst  := GetNextAlias()
    Private aCamposEst := {}
    Private oTmpTabEst := Nil
    Private aColunEst  := {}
    //Municipios
    Private oPanelMun
    Private oMarkMun
    Private cAliasMun  := GetNextAlias()
    Private aCamposMun := {}
    Private oTmpTabMun := Nil
    Private aColunMun  := {}
    //Tamanho da janela
    Private aTamanho   := MsAdvSize()
    Private nJanLarg   := aTamanho[5]
    Private nJanAltu   := aTamanho[6]
    Private nColMeio   := (nJanLarg/2) /2
     
    //Adiciona as colunas que serão criadas na temporária (estados)
    aAdd(aCamposEst, {'XX_SIGLA',  'C',  2, 0}) //Sigla do Estado (ex.: AC)
    aAdd(aCamposEst, {'XX_ESTADO', 'C', 30, 0}) //Nome do Estado (ex.: ACRE)

    //Cria a tabela temporária
    oTmpTabEst:= FWTemporaryTable():New(cAliasEst)
    oTmpTabEst:SetFields(aCamposEst)
    oTmpTabEst:Create()  

    //Adiciona as colunas que serão criadas na temporária (municipios)
    aAdd(aCamposMun, {'OK',        'C',   2, 0}) //Flag para marcação
    aAdd(aCamposMun, {'XX_SIGLA',  'C',   2, 0}) //Sigla do Estado (ex.: SP)
    aAdd(aCamposMun, {'XX_CODMUN', 'C',   5, 0}) //Código da Cidade (ex.: 06003)
    aAdd(aCamposMun, {'XX_NOME',   'C',  50, 0}) //Nome da Cidade (ex.: BAURU)

    //Cria a tabela temporária
    oTmpTabMun:= FWTemporaryTable():New(cAliasMun)
    oTmpTabMun:SetFields(aCamposMun)
    oTmpTabMun:Create()  

    //Popula as tabelas temporárias
    Processa({|| fPopula()}, 'Processando...')

    //Adiciona as colunas que serão exibidas no FWMarkBrowse
    fCriaCols()
     
    //Criando a janela
    oDlgMark := TDialog():New(0, 0, nJanAltu, nJanLarg, cJanTitulo, , , , , , /*nCorFundo*/, , , lDimPixels)
        //Dados dos Estados
        oPanelEst := tPanel():New(030, 001, '', oDlgMark, , , , RGB(000,000,000), RGB(254,254,254), nColMeio - 1,     (nJanAltu/2 - 1))
        oMarkEst := FWMarkBrowse():New()
        oMarkEst:SetAlias(cAliasEst)                
        oMarkEst:SetDescription('Estados')
        oMarkEst:DisableFilter()
        oMarkEst:DisableConfig()
        oMarkEst:DisableSeek()
        oMarkEst:DisableSaveConfig()
        oMarkEst:DisableReport()
        oMarkEst:SetFontBrowse(oFontGrid)
        //oMarkEst:SetFieldMark('OK')
        oMarkEst:SetTemporary(.T.)
        oMarkEst:SetColumns(aColunEst)
        //oMarkEst:AllMark() 
        oMarkEst:SetOwner(oPanelEst)
        oMarkEst:oBrowse:bChange := {|| fMudaLin()}
        oMarkEst:Activate()

        //Dados dos Municipios
        oPanelMun := tPanel():New(030, nColMeio + 1, '', oDlgMark, , , , RGB(000,000,000), RGB(254,254,254), (nJanLarg/2 -10),     (nJanAltu/2 - 1))
        oMarkMun := FWMarkBrowse():New()
        oMarkMun:SetAlias(cAliasMun)                
        oMarkMun:SetDescription('Municípios')
        oMarkMun:DisableFilter()
        oMarkMun:DisableConfig()
        oMarkMun:DisableSeek()
        oMarkMun:DisableSaveConfig()
        oMarkMun:DisableReport()
        oMarkMun:SetFontBrowse(oFontGrid)
        oMarkMun:SetFieldMark('OK')
        oMarkMun:SetTemporary(.T.)
        oMarkMun:SetColumns(aColunMun)
        //oMarkMun:AllMark() 
        oMarkMun:SetOwner(oPanelMun)
        oMarkMun:Activate()

    //Ativa e exibe a janela
    oDlgMark:Activate(, , , lCentraliz, , , bBlocoIni)
    
    //Deleta a temporária e desativa a tela de marcação
    oTmpTabEst:Delete()
    oTmpTabMun:Delete()
    oMarkEst:DeActivate()
    oMarkMun:DeActivate()
    
    RestArea(aArea)
Return

Static Function MenuDef()
    Local aRotina := {}
Return aRotina

Static Function fPopula()
    Local cQryUpd := ""

    //Vamos inserir todos os estados na temporária
    cQryUpd := ""
    cQryUpd += " INSERT INTO " + oTmpTabEst:GetRealName() + CRLF
    cQryUpd += " (XX_SIGLA, XX_ESTADO) " + CRLF
    cQryUpd += " SELECT X5_CHAVE, X5_DESCRI FROM " + RetSQLName("SX5") + " WHERE X5_TABELA = '12' ORDER BY X5_CHAVE "
    u_zExecQry(cQryUpd, .T.)

    //Vamos inserir todos os municipios na segunda temporária
    cQryUpd := ""
    cQryUpd += " INSERT INTO " + oTmpTabMun:GetRealName() + CRLF
    cQryUpd += " (XX_SIGLA, XX_CODMUN, XX_NOME) " + CRLF
    cQryUpd += " SELECT CC2_EST, CC2_CODMUN, CC2_MUN FROM CC2990 WHERE D_E_L_E_T_ = ' ' ORDER BY CC2_EST, CC2_CODMUN "
    u_zExecQry(cQryUpd, .T.)
Return

Static Function fCriaCols()
    Local nAtual   := 0 
    Local aEstrut  := {}
    Local oColumn
    
    //Adicionando campos que serão mostrados na tela
    //[1] - Campo da Temporaria
    //[2] - Titulo
    //[3] - Tipo
    //[4] - Tamanho
    //[5] - Decimais
    //[6] - Máscara
    aEstrut := {}
    aAdd(aEstrut, {'XX_SIGLA',  'Sigla',  'C',  2, 0, ''})
    aAdd(aEstrut, {'XX_ESTADO', 'Estado', 'C', 30, 0, ''})

    //Percorrendo todos os campos da estrutura
    For nAtual := 1 To Len(aEstrut)
        //Cria a coluna
        oColumn := FWBrwColumn():New()
        oColumn:SetData(&('{|| ' + cAliasEst + '->' + aEstrut[nAtual][1] +'}'))
        oColumn:SetTitle(aEstrut[nAtual][2])
        oColumn:SetType(aEstrut[nAtual][3])
        oColumn:SetSize(aEstrut[nAtual][4])
        oColumn:SetDecimal(aEstrut[nAtual][5])
        oColumn:SetPicture(aEstrut[nAtual][6])

        //Adiciona a coluna
        aAdd(aColunEst, oColumn)
    Next

    //Adicionando campos que serão mostrados na tela
    //[1] - Campo da Temporaria
    //[2] - Titulo
    //[3] - Tipo
    //[4] - Tamanho
    //[5] - Decimais
    //[6] - Máscara
    aEstrut := {}
    aAdd(aEstrut, {'XX_CODMUN', 'Codigo',    'C',  5, 0, ''})
    aAdd(aEstrut, {'XX_NOME',   'Município', 'C', 50, 0, ''})

    //Percorrendo todos os campos da estrutura
    For nAtual := 1 To Len(aEstrut)
        //Cria a coluna
        oColumn := FWBrwColumn():New()
        oColumn:SetData(&('{|| ' + cAliasMun + '->' + aEstrut[nAtual][1] +'}'))
        oColumn:SetTitle(aEstrut[nAtual][2])
        oColumn:SetType(aEstrut[nAtual][3])
        oColumn:SetSize(aEstrut[nAtual][4])
        oColumn:SetDecimal(aEstrut[nAtual][5])
        oColumn:SetPicture(aEstrut[nAtual][6])

        //Adiciona a coluna
        aAdd(aColunMun, oColumn)
    Next
Return

Static Function fMudaLin()
    Local cEstado := (cAliasEst)->XX_SIGLA
    Local cFiltro := cAliasMun + "->XX_SIGLA == '" + cEstado + "'"

    //Aplica o filtro no alias de municipios
    (cAliasMun)->(DbClearFilter())
    (cAliasMun)->(DbSetFilter({|| &(cFiltro)}, cFiltro))

    //Atualiza a grid de cidades
    If Type("oMarkMun") != "U"
        oMarkMun:Refresh(.T.)
    EndIf
Return

Static Function fMostraMark()
    Local cMensagem := ""
    Local cMarca    := oMarkMun:Mark()

    //Limpa o filtro dos municipios e posiciona no topo
    (cAliasMun)->(DbClearFilter())
    (cAliasMun)->(DbGoTop())

    //Percorre todos os registros
    While ! (cAliasMun)->(EoF())

        //Se o registro tiver marcado
        If oMarkMun:IsMark(cMarca)
            cMensagem += PadR((cAliasMun)->XX_SIGLA, 3) + "|" + (cAliasMun)->XX_CODMUN + "|" + (cAliasMun)->XX_NOME + "|" + CRLF
        EndIf

        (cAliasMun)->(DbSkip())
    EndDo

    //Se tiver mensagem
    If ! Empty(cMensagem)
        cMensagem := "Est" + "|" + PadR("Cod.", 5) + "|" + PadR("Cidade", 50) + "|" + CRLF + CRLF + cMensagem
        ShowLog(cMensagem)
    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.

10 Responses

  1. Antonio Costa Patini disse:

    muito top parabens atilio., eu fiz um destes em mvc com refresh automatico.

  2. EDSON CARLOS DOS SANTOS disse:

    muito bom esse video, Dantilio, manda muito bem ? Precisa desse exemplo em MVC, como seria?

  3. Rubem disse:

    Dan, boa noite!

    Quando tem somente 1 registro no primeiro browser não exibir no outro.

    Como faço para contornar isso ?

    • Bom dia Rubem, tudo joia?

      Acho que não entendi a dúvida. Levando em conta o exemplo do vídeo, se na grid da esquerda tiver apenas 1 registro, você quer que não mostre nada na grid da direita?

      Por exemplo, supondo que na grid da esquerda tivesse só o estado de SC, ai na da direita você não quer exibir nada?

      Se for isso, o que você pode fazer, é dar um Count To no alias da esquerda, se tiver apenas 1 registro, ai o seu filtro do DbSetFilter, você coloca algo que nunca vai ser “true”, tipo algo como 1 == 0, que dai o sistema não vai trazer nenhum registro.

      Tenha uma ótima e abençoada segunda feira.

      Um grande abraço.

  4. Rubem disse:

    Dan, bom dia!

    Obrigado por responde!

    Quando a temporária só tem um registro no browse principal parece que o bchange é só quando ele muda de linha e se tem uma só, na montagem ele não é chamado.

    • Bom dia Rubem, tudo joia?

      Ah entendi, sua grid da esquerda tem só um registro, e você precisa acionar o “refresh” da grid da direita.

      Depois de criar todos os objetos da tela, e antes do Activate da Dialog, você aciona o bloco de código de atualizar a linha da grid da esquerda. Por exemplo, se for o fonte do exemplo, ficaria assim:
      […]

      //Força o refresh para caso do alias da esquerda ter só 1 registro
      fMudaLin()

      //Ativa e exibe a janela
      oDlgMark:Activate(, , , lCentraliz, , , bBlocoIni)
      […]

      Tenha uma ótima e abençoada terça feira.

      Um grande abraço.

Deixe uma resposta

Terminal de Informação