No vídeo de hoje, vamos demonstrar em como criar uma tela com browse, onde ao digitar num get, fazemos o filtro dinamicamente através do keypress.
A dúvida de hoje, nos perguntaram, se seria possível em uma tela com um browse, enquanto o usuário digita, o browse já ir ser filtrado dinamicamente conforme as teclas pressionadas.
Pensando nisso, montamos esse exemplo, onde demonstramos em como usar a classe FWBrowse juntamente com um TGet e o método bGetKey.
Segue abaixo o vídeo exemplificando:
E abaixo o código fonte desenvolvido:
//Bibliotecas #Include "Totvs.ch" #Include "FWMVCDef.ch" /*/{Protheus.doc} User Function zVid0090 Lista de Produtos @author Atilio @since 26/02/2024 @version 1.0 @type function @obs Codigo gerado automaticamente pelo Autumn Code Maker @see http://autumncodemaker.com /*/ User Function zVid0090() Local aArea := FWGetArea() //Chama a tela fMontaTela() FWRestArea(aArea) Return /*/{Protheus.doc} fMontaTela Monta a tela com a marcação de dados @author Atilio @since 26/02/2024 @version 1.0 @type function @obs Codigo gerado automaticamente pelo Autumn Code Maker @see http://autumncodemaker.com /*/ Static Function fMontaTela() Local aArea := GetArea() Local aCampos := {} Local aColunas := {} Local cFontPad := 'Tahoma' Local oFontGrid := TFont():New(cFontPad, /*uPar2*/, -14) //Barra de Botões Local bBlocoOk := {|| lOk := .T., oDlgBrow:End()} Local bBlocoCan := {|| lOk := .F., oDlgBrow:End()} Local aOutrasAc := {} Local bBlocoIni := {|| EnchoiceBar(oDlgBrow, bBlocoOk, bBlocoCan, , aOutrasAc)} Private lOk := .F. //Janela e componentes Private oDlgBrow Private oPanGrid Private oFWBrowse Private oTempTable := Nil Private cAliasTmp := GetNextAlias() Private aRotina := MenuDef() //Tamanho da janela Private aTamanho := MsAdvSize() Private nJanLarg := aTamanho[5] Private nJanAltu := aTamanho[6] //Get da pesquisa Private oGetPesq, cGetPesq := Space(100) //Adiciona as colunas que serão criadas na temporária aAdd(aCampos, { 'B1_COD', 'C', TamSX3('B1_COD')[1], 0}) //Produto aAdd(aCampos, { 'B1_TIPO', 'C', TamSX3('B1_TIPO')[1], 0}) //Tipo aAdd(aCampos, { 'B1_UM', 'C', TamSX3('B1_UM')[1], 0}) //U.M. aAdd(aCampos, { 'B1_DESC', 'C', TamSX3('B1_DESC')[1], 0}) //Descrição //Cria a tabela temporária oTempTable:= FWTemporaryTable():New(cAliasTmp) oTempTable:SetFields( aCampos ) oTempTable:Create() //Popula a tabela temporária Processa({|| fPopula()}, 'Processando...') //Adiciona as colunas que serão exibidas no FWBrowse aColunas := fCriaCols() //Criando a janela oDlgBrow := TDialog():New(0, 0, nJanAltu, nJanLarg, 'Tela para Consulta de Dados - Autumn Code Maker', , , , , , /*nCorFundo*/, , , .T.) //Get de pesquisa oGetPesq := TGet():New(035, 003, {|u| Iif(PCount() > 0 , cGetPesq := u, cGetPesq)}, oDlgBrow, 150, 10, /*cPict*/, /*bValid*/, /*nClrFore*/, /*nClrBack*/, oFontGrid, , , .T.) oGetPesq:cPlaceHold := "Digite aqui código ou descrição do produto..." oGetPesq:bGetKey := {|self, cText, nKey| fKeyPress(self, cText, nKey)} //Dados oPanGrid := tPanel():New(050, 001, '', oDlgBrow, /*oFont*/, /*lCentered*/, /*uParam7*/, RGB(000,000,000), RGB(254,254,254), (nJanLarg/2) - 1, (nJanAltu/2) - 1) oFWBrowse := FWBrowse():New() oFWBrowse:DisableFilter() oFWBrowse:DisableConfig() oFWBrowse:DisableReport() oFWBrowse:DisableSeek() oFWBrowse:DisableSaveConfig() oFWBrowse:SetFontBrowse(oFontGrid) oFWBrowse:SetAlias(cAliasTmp) oFWBrowse:SetDataTable() oFWBrowse:SetEditCell(.T., {|| .T.}) oFWBrowse:lHeaderClick := .F. //Define as colunas, vincula ao painel e exibe oFWBrowse:SetColumns(aColunas) oFWBrowse:SetOwner(oPanGrid) oFWBrowse:Activate() oDlgBrow:Activate(, , , .T., , , bBlocoIni) If lOk //Aqui dentro desse if, será executado o usuário clicou no confirmar EndIf //Deleta a temporária e desativa a tela de marcação oTempTable:Delete() oFWBrowse:DeActivate() RestArea(aArea) Return /*/{Protheus.doc} fPopula Executa a query SQL e popula essa informação na tabela temporária usada no browse @author Atilio @since 26/02/2024 @version 1.0 @type function @obs Codigo gerado automaticamente pelo Autumn Code Maker @see http://autumncodemaker.com /*/ Static Function fPopula() Local cQryDados := '' //Popula a temporária com a query // Baixar a zExecQry nesse link - https://terminaldeinformacao.com/2021/04/21/como-fazer-um-update-via-advpl/ cQryDados := " INSERT INTO " + oTempTable:GetRealName() + " (B1_COD, B1_TIPO, B1_UM, B1_DESC) " + CRLF cQryDados += " SELECT B1_COD, B1_TIPO, B1_UM, B1_DESC FROM " + RetSQLName("SB1") + " SB1 WHERE B1_FILIAL = '" + FWxFilial("SB1") + "' AND SB1.D_E_L_E_T_ = ' ' " + CRLF u_zExecQry(cQryDados, .T.) Return /*/{Protheus.doc} fCriaCols Função que gera as colunas usadas no browse (similar ao antigo aHeader) @author Atilio @since 26/02/2024 @version 1.0 @type function @obs Codigo gerado automaticamente pelo Autumn Code Maker @see http://autumncodemaker.com /*/ Static Function fCriaCols() Local nAtual := 0 Local aColunas := {} 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 //[7] - Editável? .T. = sim, .F. = não //[8] - Código da Consulta Padrão //[9] - Bloco de Código usado na Validação (ex.: {|| fSuaValid()} ) aAdd(aEstrut, { 'B1_COD', 'Produto', 'C', TamSX3('B1_COD')[1], 0, '', .F., Nil, Nil}) aAdd(aEstrut, { 'B1_TIPO', 'Tipo', 'C', TamSX3('B1_TIPO')[1], 0, '', .F., Nil, Nil}) aAdd(aEstrut, { 'B1_UM', 'U.M.', 'C', TamSX3('B1_UM')[1], 0, '', .F., Nil, Nil}) aAdd(aEstrut, { 'B1_DESC', 'Descrição', 'C', TamSX3('B1_DESC')[1], 0, '', .F., Nil, Nil}) //Percorrendo todos os campos da estrutura For nAtual := 1 To Len(aEstrut) //Cria a coluna oColumn := FWBrwColumn():New() oColumn:SetData(&('{|| ' + cAliasTmp + '->' + 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]) //Se for ser possível ter o duplo clique para editar If aEstrut[nAtual][7] oColumn:SetEdit(.T.) oColumn:SetReadVar(aEstrut[nAtual][1]) //Se tiver Consulta Padrão If ! Empty(aEstrut[nAtual][8]) oColumn:xF3 := aEstrut[nAtual][8] EndIf //Se tiver Validação If ! Empty(aEstrut[nAtual][9]) oColumn:SetValid(aEstrut[nAtual][9]) EndIf EndIf //Adiciona a coluna aAdd(aColunas, oColumn) Next Return aColunas Static Function fKeyPress(oObjeto, cTextoComp, nKey) Local cProdFiltr := Upper(Alltrim(cTextoComp)) Local cFiltro := "" //Se tiver vazio o campo, marca o filtro para trazer tudo (CleanFilter às vezes não estava funcionando) If Empty(cProdFiltr) cFiltro := ".T." oFWBrowse:SetFilterDefault(cFiltro) Else //Se for algum caractere válido da tabela ASCII (até 255) // Ou for o Backspace (16777219) // Ou for o Delete (16777223) If nKey < 255 .Or. nKey == 16777219 .Or. nKey == 16777223 //Se o tamanho da string, passar de 3 caracteres If Len(cProdFiltr) > 3 //Monta o filtro por código ou descrição cFiltro := "'" + cProdFiltr + "' $ Upper((cAliasTmp)->B1_COD) .Or. " cFiltro += "'" + cProdFiltr + "' $ Upper((cAliasTmp)->B1_DESC) " oFWBrowse:SetFilterDefault(cFiltro) EndIf EndIf EndIf //Aciona o refresh, indo ao topo oFWBrowse:Refresh(.T.) Return
Links de Apoio:
Como validar o KeyPress em um TGet em AdvPL – https://terminaldeinformacao.com/2023/03/29/como-validar-o-keypress-em-um-tget-em-advpl/
Download da zExecQry – https://terminaldeinformacao.com/2021/04/21/como-fazer-um-update-via-advpl/
Bom pessoal, por hoje é só.
Abraços e até a próxima.