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.
muito top parabens atilio., eu fiz um destes em mvc com refresh automatico.
Grande Patini, bom dia, tudo joia?
Show de bola hein, deve ter ficado bem legal a customização.
Obrigado pelo comentário e feedback.
Tenha uma ótima e abençoada quarta feira.
Um grande abraço.
muito bom esse video, Dantilio, manda muito bem ? Precisa desse exemplo em MVC, como seria?
Bom dia Edson, tudo joia?
Opa, obrigado pelo feedback.
O passo 1 seria você criar uma Modelo X com duas grids. Nisso o passo 2, na ViewDef, você mostraria através de Vertical no lugar de Horizontal. E o passo 3, você poderia criar um campo do tipo Lógico no Configurador, ou criar um checkbox virtual.
Para o Passo 1, tem como você fazer, usando o Autumn Code Maker, segue vídeo de exemplo: https://www.youtube.com/watch?v=wchgSWP1FcI
Para o Passo 2, tem exemplo na aula 14 do curso de MVC: https://terminaldeinformacao.com/2022/04/22/curso-mvc-em-advpl/
Para o Passo 3, ou você cria um campo no Configurador do tipo Lógico (L) ou cria direto na tela, conforme esse exemplo: https://terminaldeinformacao.com/knowledgebase/campo-check-virtual-em-mvc/
Tenha uma ótima e abençoada sexta feira.
Um grande abraço.
bom dia Dantilio, paz, top demais, vou tentar, eu ja tenho criado o modelo x, agora quero chamar uma tela com divisao vertical com markbrownse nas duas, para poder fazer tela de conciliação, vou tentar aqui…com os seus toques, Deus abençoe…
Bom dia Edson, tudo joia?
Amém meu irmão.
Uma alternativa, como você já tem configurado a Modelo X, seria você incluir os campos no Configurador com o tipo Lógico (X3_TIPO igual a L), que ele ja cria para você na grid, como um CheckBox.
Tenha uma ótima e abençoada quinta feira.
Um grande abraço.
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.
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.
Daniel muchas gracias por el ejemplo, tiene usted un ejemplo donde en la grilla 2, pueda agregar lineas el usuario?
Gracias.
Bom dia Damian, tudo joia?
Opa, nós que agradecemos pelo comentário.
Tem um exemplo que você pode aproveitar, no link abaixo, veja a partir do “Abaixo o fonte da Grid dupla em MVC com cabeçalho FAKE”:
https://terminaldeinformacao.com/2020/07/03/migrando-do-msnewgetdados-para-fwbrowse-e-mvc
Tenha uma ótima e abençoada quinta feira.
Um grande abraço.