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.