Como criar uma Consulta Específica (F3) no Configurador

No artigo de hoje, vamos demonstrar em como criar uma consulta padrão (F3) mais amigável aos usuários, já fazendo o filtro ao apertar -TAB- na pesquisa.

Antes de mais nada, será necessário baixar o fonte zConsSQL ou zConsMark (se for uma consulta com marcação / markbrowse), abaixo os links para download:

 

  1. Vá no Configurador, acesse Base de Dados e depois Consultas Padrão
  2. Clique em Incluir

Cadastrando a consulta

 

  1. Defina Consulta Específica, coloque um nome e descrição para ela

Definindo como Específica

 

  1. Na expressão, acione a função (zConsSQL ou zConsMark dependendo de qual baixou), abaixo um exemplo passando a query buscando produto e descrição
u_zConsSQL("SELECT B1_COD, B1_DESC FROM SB1990 WHERE D_E_L_E_T_ = ' ' ", "B1_COD")
  1. Informe a tabela e no retorno, coloque a variável pública __cRetorno que é criada nessas funções citadas acima

Informando a função customizada e o retorno

 

  1. Agora basta você usar a consulta, colocar ela vinculada em perguntas e campos, abaixo um exemplo do funcionamento de filtro dela

Testando a consulta

 

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.

4 Responses

  1. Hiago Borges disse:

    é possível retornar mais que um campo?

    • Bom dia Hiago, tudo joia?

      Sim. No caso, na sua User Function por exemplo, você pode adicionar “;” entre os campos ao retornar e ai no seu fonte que for consultar, você trata a informação que vier junto com o ponto e vírgula.

      Tenha uma ótima e abençoada quarta feira.

      Um grande abraço.

  2. Bruno Domingos disse:

    Bom dia, Daniel, tudo bem?

    Achei bem legal essa tela e está ajudando bastante em alguns projetos.
    Em um cliente precisei implementar um botão “cópia” para copiar o produto e salvar. (fCopia)

    //Bibliotecas
    #Include “Protheus.ch”
    #Include “TopConn.ch”
    #INCLUDE “PROTHEUS.CH”
    #INCLUDE “APWIZARD.CH”
    #INCLUDE “FWADAPTEREAI.CH”
    #INCLUDE ‘FWMVCDEF.CH’
    #INCLUDE “TOPCONN.CH”

    //Constantes
    #Define STR_PULA Chr(13)+ Chr(10)

    /*/{Protheus.doc} zConsSQL
    Função para consulta genérica
    @author Daniel Atilio
    @since 15/12/2016
    @version 1.0
    @param cConsSQLM, Caracter, Consulta SQL
    @param cRetorM, Caracter, Campo que será retornado
    @param cAgrupM, Caracter, Group By do SQL
    @param cOrderM, Caracter, Order By do SQL
    @return lRetorn, retorno se a consulta foi confirmada ou não
    @example
    lOK := u_zConsSQL(“SELECT B1_COD, B1_DESC, B1_UM FROM SB1010 WHERE D_E_L_E_T_ = ‘ ‘ “, “B1_COD”, “”, “B1_COD”)

    u_zConsSQL(“SELECT * FROM ZA0990”, “ZA0_COD”, “”, “”)

    @obs O retorno da consulta é pública (__cRetorno) para ser usada em consultas específicas
    A consulta não pode ter ORDER BY, pois ele já é especificado em um parâmetro
    /*/

    User Function zConsSQL(cConsSQLM, cRetorM, cAgrupM, cOrderM)
    Local aArea := GetArea()
    Local nTamBtn := 50
    Local oGrpPesqui
    Local oGrpDados
    Local oGrpAcoes
    Local oBtnConf
    Local oBtnLimp
    Local oBtnCanc
    //Defaults
    Default cConsSQLM := “”
    Default cRetorM := “”
    Default cOrderM := “”
    //Privates
    Private cConsSQL := cConsSQLM
    Private cCampoRet := cRetorM
    Private cAgrup := cAgrupM
    Private cOrder := cOrderM
    Private nTamanRet := 0
    Private aStruAux := {}
    //MsNewGetDados
    Private oMsNew
    Private aHeadAux := {}
    Private aColsAux := {}
    //Tamanho da janela
    Private nJanLarg := 1500
    Private nJanAltu := 0800
    //Gets e Dialog
    Private oDlgEspe
    Private oGetPesq, cGetPesq := Space(100)
    //Retorno
    Private lRetorn := .F.
    Public __cRetorno := “”

    //Se tiver o alias em branco ou não tiver campos
    If Empty(cConsSQLM) .Or. Empty(cRetorM)
    MsgStop(“SQL e / ou retorno em branco!”, “Atenção”)
    Return lRetorn
    EndIf

    //Criando a estrutura para a MsNewGetDados
    fCriaMsNew()
    __cRetorno := Space(nTamanRet)

    //Criando a janela
    DEFINE MSDIALOG oDlgEspe TITLE “Consulta de Dados” FROM 000, 000 TO nJanAltu, nJanLarg COLORS 0, 16777215 PIXEL
    //Pesquisar
    @ 003, 003 GROUP oGrpPesqui TO 025, (nJanLarg/2)-3 PROMPT “Pesquisar: ” OF oDlgEspe COLOR 0, 16777215 PIXEL
    @ 010, 006 MSGET oGetPesq VAR cGetPesq SIZE (nJanLarg/2)-12, 010 OF oDlgEspe COLORS 0, 16777215 VALID (fVldPesq()) PIXEL

    //Dados
    @ 028, 003 GROUP oGrpDados TO (nJanAltu/2)-28, (nJanLarg/2)-3 PROMPT “Dados: ” OF oDlgEspe COLOR 0, 16777215 PIXEL
    oMsNew := MsNewGetDados():New( 035,; //nTop
    006,; //nLeft
    (nJanAltu/2)-31,; //nBottom
    (nJanLarg/2)-6,; //nRight
    GD_INSERT+GD_DELETE+GD_UPDATE,; //nStyle
    “AllwaysTrue()”,; //cLinhaOk
    ,; //cTudoOk
    “”,; //cIniCpos
    ,; //aAlter
    ,; //nFreeze
    999,; //nMax
    ,; //cFieldOK
    ,; //cSuperDel
    ,; //cDelOk
    oDlgEspe,; //oWnd
    aHeadAux,; //aHeader
    aColsAux)
    //aCols
    oMsNew:lActive := .F.
    oMsNew:oBrowse:blDblClick := {|| fConfirm()}

    //Populando os dados da MsNewGetDados
    fPopula()

    //Ações
    @ (nJanAltu/2)-25, 003 GROUP oGrpAcoes TO (nJanAltu/2)-3, (nJanLarg/2)-3 PROMPT “Ações: ” OF oDlgEspe COLOR 0, 16777215 PIXEL

    @ (nJanAltu/2)-19, (nJanLarg/2)-((nTamBtn*1)+06) BUTTON oBtnConf PROMPT “Confirmar” SIZE nTamBtn, 013 OF oDlgEspe ACTION(fConfirm()) PIXEL
    @ (nJanAltu/2)-19, (nJanLarg/2)-((nTamBtn*2)+09) BUTTON oBtnLimp PROMPT “Limpar” SIZE nTamBtn, 013 OF oDlgEspe ACTION(fLimpar()) PIXEL
    @ (nJanAltu/2)-19, (nJanLarg/2)-((nTamBtn*3)+12) BUTTON oBtnCanc PROMPT “Cancelar” SIZE nTamBtn, 013 OF oDlgEspe ACTION(fCancela()) PIXEL

    @ (nJanAltu/2)-19, (nJanLarg/2)-((nTamBtn*4)+15) BUTTON oBtnConf PROMPT “Copiar” SIZE nTamBtn, 013 OF oDlgEspe ACTION(fCopia()) PIXEL

    oMsNew:oBrowse:SetFocus()
    //Ativando a janela
    ACTIVATE MSDIALOG oDlgEspe CENTERED

    RestArea(aArea)
    Return lRetorn

    /*———————————————————————*
    | Func: fCriaMsNew |
    | Autor: Daniel Atilio |
    | Data: 15/12/2016 |
    | Desc: Função para criar a estrutura da MsNewGetDados |
    | Obs.: / |
    *———————————————————————*/

    Static Function fCriaMsNew()
    Local aAreaX3 := SX3->(GetArea())
    Local cQuery := “”
    Local nAtual := 0

    //Zerando o cabeçalho e a estrutura
    aHeadAux := {}
    aColsAux := {}

    //Monta a consulta e pega a estrutura
    cQuery := cConsSQL

    //Group By
    If !Empty(cAgrup)
    cQuery += cAgrup + STR_PULA
    EndIf

    //Order By
    cQuery += ” ORDER BY ” + STR_PULA
    If !Empty(cOrder)
    cQuery += ” “+cOrder
    Else
    cQuery += ” “+cCampoRet
    EndIf
    TCQuery cQuery New Alias “QRY_DAD”
    aStruAux := QRY_DAD->(DbStruct())
    QRY_DAD->(DbCloseArea())

    DbSelectArea(“SX3”)
    SX3->(DbSetOrder(2)) // Campo
    SX3->(DbGoTop())

    //Percorrendo os campos
    For nAtual := 1 To Len(aStruAux)
    cCampoAtu := aStruAux[nAtual][1]

    //Se coneguir posicionar no campo
    If SX3->(DbSeek(cCampoAtu))
    //Cabeçalho … Titulo Campo Mask Tamanho Dec Valid Usado Tip F3 CBOX
    aAdd(aHeadAux,{ X3Titulo(), cCampoAtu, PesqPict(SX3->X3_ARQUIVO, cCampoAtu), SX3->X3_TAMANHO, SX3->X3_DECIMAL, “.F.”, “.F.”, SX3->X3_TIPO, “”, “”})

    //Se o campo atual for retornar, aumenta o tamanho do retorno
    If cCampoAtu $ cCampoRet
    nTamanRet += SX3->X3_TAMANHO
    EndIf

    Else
    //Cabeçalho … Titulo Campo Mask Tamanho Dec Valid Usado Tip F3 CBOX
    aAdd(aHeadAux,{ Capital(StrTran(cCampoAtu, ‘_’, ‘ ‘)), cCampoAtu, “”, aStruAux[nAtual][3], aStruAux[nAtual][4], “.F.”, “.F.”, aStruAux[nAtual][2], “”, “”})

    //Se o campo atual for retornar, aumenta o tamanho do retorno
    If cCampoAtu $ cCampoRet
    nTamanRet += aStruAux[nAtual][3]
    EndIf
    EndIf
    Next

    RestArea(aAreaX3)
    Return

    /*———————————————————————*
    | Func: fPopula |
    | Autor: Daniel Atilio |
    | Data: 15/12/2016 |
    | Desc: Função que popula a tabela auxiliar da MsNewGetDados |
    | Obs.: / |
    *———————————————————————*/

    Static Function fPopula()
    Local cQuery := “”
    Local nAtual := 0
    aColsAux :={}
    nCampAux := 1

    //Faz a consulta
    cQuery := cConsSQL + STR_PULA

    //Se tiver Filtro
    If !Empty(cGetPesq)
    If ‘WHERE’ $ cQuery
    cQuery += ” AND ”
    Else
    cQuery += ” WHERE ”
    EndIf
    cQuery += ” ( ”
    For nAtual := 1 To Len(aStruAux)
    cCampoAtu := aStruAux[nAtual][1]
    If aStruAux[nAtual][2] == ‘C’
    cQuery += ” UPPER(“+cCampoAtu+”) LIKE ‘%”+Upper(Alltrim(cGetPesq))+”%’ OR”
    EndIf
    Next
    cQuery := SubStr(cQuery, 1, Len(cQuery)-2)
    cQuery += “)”+STR_PULA
    EndIf

    //Group By
    If !Empty(cAgrup)
    cQuery += cAgrup + STR_PULA
    EndIf

    //Order By
    cQuery += ” ORDER BY ” + STR_PULA
    If !Empty(cOrder)
    cQuery += ” “+cOrder
    Else
    cQuery += ” “+cCampoRet
    EndIf
    TCQuery cQuery New Alias “QRY_DAD”

    //Percorrendo a estrutura, procurando campos de data
    For nAtual := 1 To Len(aHeadAux)
    //Se for data
    If aHeadAux[nAtual][8] == “D”
    TCSetField(‘QRY_DAD’, aHeadAux[nAtual][2], ‘D’)
    //Se for data
    ElseIf aHeadAux[nAtual][8] == “N”
    TCSetField(‘QRY_DAD’, aHeadAux[nAtual][2], ‘N’, aHeadAux[nAtual][4], aHeadAux[nAtual][5])
    EndIf
    Next

    //Enquanto tiver dados
    While ! QRY_DAD->(EoF())
    nCampAux := 1
    aAux := {}
    //Percorrendo os campos e adicionando no acols e com o delet
    For nAtual := 1 To Len(aStruAux)
    cCampoAtu := aStruAux[nAtual][1]

    If aStruAux[nAtual][2] $ “N;D”
    aAdd(aAux, &(“QRY_DAD->”+cCampoAtu) )
    Else
    aAdd(aAux, cValToChar( &(“QRY_DAD->”+cCampoAtu) ))
    EndIf
    Next
    aAdd(aAux, .F.)

    aAdd(aColsAux, aClone(aAux))
    QRY_DAD->(DbSkip())
    EndDo
    QRY_DAD->(DbCloseArea())

    //Se não tiver dados, adiciona linha em branco
    If Len(aColsAux) == 0
    aAux := {}

    //Percorrendo os campos e adicionando no acols e com o delet
    For nAtual := 1 To Len(aStruAux)
    aAdd(aAux, ”)
    Next
    aAdd(aAux, .F.)

    aAdd(aColsAux, aClone(aAux))
    EndIf

    //Posiciona no topo e atualiza grid
    oMsNew:SetArray(aColsAux)
    oMsNew:oBrowse:Refresh()
    Return

    /*———————————————————————*
    | Func: fConfirm |
    | Autor: Daniel Atilio |
    | Data: 15/12/2016 |
    | Desc: Função de confirmação da rotina |
    | Obs.: / |
    *———————————————————————*/

    Static Function fConfirm()
    Local aAreaX3 := SX3->(GetArea())
    Local cAux := “”
    Local aColsNov := oMsNew:aCols
    Local nLinAtu := oMsNew:nAt
    Local nAtual

    //Percorrendo os campos
    For nAtual := 1 To Len(aHeadAux)
    cCampoAtu := aHeadAux[nAtual][2]

    //Se o campo atual for retornar, soma com o auxiliar
    If cCampoAtu $ cCampoRet
    cAux += aColsNov[nLinAtu][nAtual]
    EndIf
    Next

    //Setando o retorno conforme auxiliar e finalizando a tela
    lRetorn := .T.
    __cRetorno := cAux

    //Se tiver retorno
    If Len(__cRetorno) != 0
    //Se o tamanho for menor, adiciona
    If Len(__cRetorno) nTamanRet
    __cRetorno := SubStr(__cRetorno, 1, nTamanRet)
    EndIf
    EndIf

    oDlgEspe:End()
    RestArea(aAreaX3)
    Return

    /*———————————————————————*
    | Func: fLimpar |
    | Autor: Daniel Atilio |
    | Data: 15/12/2016 |
    | Desc: Função que limpa os dados da rotina |
    | Obs.: / |
    *———————————————————————*/

    Static Function fLimpar()
    //Zerando gets
    cGetPesq := Space(100)
    oGetPesq:Refresh()

    //Atualiza grid
    fPopula()

    //Setando o foco na pesquisa
    oGetPesq:SetFocus()
    Return

    /*———————————————————————*
    | Func: fCancela |
    | Autor: Daniel Atilio |
    | Data: 15/12/2016 |
    | Desc: Função de cancelamento da rotina |
    | Obs.: / |
    *———————————————————————*/

    Static Function fCancela()
    //Setando o retorno em branco e finalizando a tela
    lRetorn := .F.
    __cRetorno := Space(nTamanRet)
    oDlgEspe:End()
    Return

    /*———————————————————————*
    | Func: fVldPesq |
    | Autor: Daniel Atilio |
    | Data: 15/12/2016 |
    | Desc: Função que valida o campo digitado |
    | Obs.: / |
    *———————————————————————*/

    Static Function fVldPesq()
    Local lRet := .T.

    //Se tiver apóstrofo ou porcentagem, a pesquisa não pode prosseguir
    If “‘” $ cGetPesq //.Or. “%” $ cGetPesq
    lRet := .F.
    MsgAlert(“Pesquisa inválida!A pesquisa não pode ter .”, “Atenção”)
    EndIf

    //Se houver retorno, atualiza grid
    If lRet
    fPopula()
    EndIf
    Return lRet

    /*———————————————————————*
    | Func: fCopia |
    | Autor: Bruno Domingos |
    | Data: 26/09/2025 |
    | Desc: Função que copia o produto para alteração |
    | Obs.: /Botão cópia |
    *———————————————————————*/

    Static Function fCopia()
    Local aColsNov := oMsNew:aCols
    Local nLinAtu := oMsNew:nAt
    Local nCampo := 0
    Local cCodProduto := “”
    Local cChave := “”
    Local cCampoAtu := “”

    // Buscar o campo B1_COD na grid
    For nCampo := 1 To Len(aHeadAux)
    cCampoAtu := aHeadAux[nCampo][2]

    If Upper(AllTrim(cCampoAtu)) == “B1_COD”
    cCodProduto := AllTrim(aColsNov[nLinAtu][nCampo])
    Exit
    EndIf
    Next

    // Verifica se encontrou o código
    If Empty(cCodProduto)
    MsgStop(“Código do produto (B1_COD) não encontrado na seleção.”, “Erro”)
    Return
    EndIf

    // Monta a chave composta: xFilial + código
    cChave := xFilial(“SB1”) + cCodProduto

    // Posiciona no SB1
    DbSelectArea(“SB1”)
    If SB1->(DbSeek(cChave))
    // Executa a rotina de cópia do produto
    FWExecView(“Cópia de Produto”, “MATA010”, 9)
    Else
    MsgStop(“Produto com chave [” + cChave + “] não encontrado na SB1.”, “Erro”)
    EndIf
    Return

    • Bom dia Bruno, tudo joia graças a Deus e você?

      Opa, obrigado pelo comentário e pela contribuição, ficou show de bola.

      Esse lance de acionar o FWExecView pra copiar é uma mão na roda né, eu até postei essa semana no grupo do WhatsApp essa dica.

      Tenha um ótimo e abençoado fim de semana.

      Um forte abraço.

Deixe uma resposta

Terminal de Informação