FWMBrowse x Tabela Temporária x SX5


O exemplo a seguir, é uma demonstração do uso do componente FWMBrowse com alias temporário usando a tabela SX5. Usaremos apenas os includes TOTVS.CH e FWMVCDEF.CH

#include "totvs.ch"
#INCLUDE "FWMVCDEF.CH"

user function AGPE001()
    //Declarar variaveis locais
    Local aSeek   	:= {}
    Local aFields 	:= {}
    Local aIndex  	:= {}
    Local aFieFilter:= {}
    //Declarar variaveis privadas
    Private oBrowse 	:= Nil
    Private cCadastro := "Cadastro de Gestores"
    Private aRotina	 	:= Menudef()
    
    //Cria e popula a tabela temporária
    AGPE001TRB()

    //Campos que serão exibidos no browse
    Aadd(aFields,{"Tabela"		,"X5_TABELA" 	,TamSx3("X5_TABELA")[3] ,TamSx3("X5_TABELA")[1] ,TamSx3("X5_TABELA")[2] ,PESQPICT("SX5","X5_TABELA")})
    Aadd(aFields,{"Código"		,"X5_CHAVE"    	,TamSx3("X5_CHAVE")[3]  ,TamSx3("X5_CHAVE")[1]  ,TamSx3("X5_CHAVE")[2]  ,PESQPICT("SX5","X5_CHAVE")})
    Aadd(aFields,{"Nome"		,"X5_DESCRI"	,TamSx3("X5_DESCRI")[3]	,TamSx3("X5_DESCRI")[1]	,TamSx3("X5_DESCRI")[2]	,PESQPICT("SX5","X5_DESCRI")})
    Aadd(aFields,{"Localidade"	,"X5_DESCSPA"	,TamSx3("X5_DESCSPA")[3],3,0,PESQPICT("SX5","X5_DESCSPA")})
    Aadd(aFields,{"Desc.Local"	,"X5_DESCENG"	,TamSx3("X5_DESCENG")[3],TamSx3("X5_DESCENG")[1],TamSx3("X5_DESCENG")[2],PESQPICT("SX5","X5_DESCENG")})

    //Campos que irão compor a tela de filtro
    Aadd(aFieFilter,{"X5_CHAVE"		, "Código"  	, "C", TamSx3("X5_CHAVE")[1]  , 0,PESQPICT("SX5","X5_CHAVE")})
    Aadd(aFieFilter,{"X5_DESCRI"	, "Nome"		, "C", TamSx3("X5_DESCRI")[1] , 0,PESQPICT("SX5","X5_DESCRI")})
    Aadd(aFieFilter,{"X5_DESCSPA"	, "Localidade"	, "C", TamSx3("X5_DESCSPA")[1], 0,PESQPICT("SX5","X5_DESCSPA")})

    DbSelectArea("TRB")
    dbGoTop()

    //Campo da pesquisa
    Aadd(aSeek  , {"Código"		, {{"","C", TamSx3("X5_CHAVE")[1]	, TamSx3("X5_CHAVE")[1]	 , 1, "X5_CHAVE"}} } )
    Aadd(aSeek  , {"Nome"		, {{"","C", TamSx3("X5_DESCRI")[1]	, TamSx3("X5_DESCRI")[1] , 2, "X5_DESCRI"}} } )
    Aadd(aSeek  , {"Localidade"	, {{"","C", TamSx3("X5_DESCSPA")[1]	, TamSx3("X5_DESCSPA")[1], 3, "X5_DESCSPA"}} } )

    //Indice de pesquisa
    Aadd( aIndex, "X5_CHAVE" )
    Aadd( aIndex, "X5_DESCRI" )
    Aadd( aIndex, "X5_DESCSPA" )

    //aStruct := TRB->(DBStruct())
    //aStructCon := aClone(aStruct)

    oBrowse := FWMBrowse():New()
    oBrowse:SetDescription( cCadastro )
    oBrowse:SetAlias("TRB")
    oBrowse:SetQueryIndex(aIndex)
    oBrowse:SetTemporary(.T.)
    oBrowse:SetSeek(,aSeek)
    oBrowse:SetFields(aFields)
    oBrowse:SetTemporary(.T.)
    oBrowse:DisableConfig()
    oBrowse:SetFieldFilter(aFieFilter)
    oBrowse:SetFilterDefault("")
    oBrowse:SetDBFFilter(.T.)
    oBrowse:SetUseFilter(.T.)
    oBrowse:SetLocate()
    oBrowse:ForceQuitButton()
    oBrowse:Activate()
Return
  Criamos aqui os menus que serão apresentados
Static Function MenuDef()
    Local aRotina := {}
    ADD OPTION aRotina Title 'Pesquisar' 	Action 'PesqBrw'    OPERATION 1 ACCESS 0
    ADD OPTION aRotina Title 'Visualizar'   Action 'U_AGPE001A(2)' 	OPERATION 2 ACCESS 0
    ADD OPTION aRotina Title 'Incluir'      Action 'U_AGPE001A(3)' 	OPERATION 3 ACCESS 0
    ADD OPTION aRotina Title 'Alterar'      Action 'U_AGPE001A(4)' 	OPERATION 4 ACCESS 0
    ADD OPTION aRotina Title 'Excluir'      Action 'U_AGPE001A(5)'	OPERATION 5 ACCESS 0
Return( aRotina )
continua página 2 Aqui desenharemos a tela que será exibida na inclusão, alteração, visualização e exclusão. Existem outras formas de criar a janela, mas optamos por essa para poder mostrar mais comandos ADVPL
User Function AGPE001A(nOpc)
    Local cTabela := SPACE(TAMSX3("X5_TABELA")[1])
    Local cChave  := SPACE(TAMSX3("X5_CHAVE")[1])
    Local cDescri := SPACE(TAMSX3("X5_DESCRI")[1])
    Local cLocal  := SPACE(3)
    Local cLocalN := SPACE(TAMSX3("X5_DESCENG")[1])
    Local oChave
    Local oDescri
    Local oLocal
    Local oLocalN
    Local cTitulo := iif(nOpc==3,'Incluir',iif(nOpc==4,'Alterar','Excluir'))
    Local bOk  	  := {|| oDlg:End(), iif(nOpc==2,Nil,fGrava(M->cTabela,M->cChave,M->cDescri,M->cLocal,M->cLocalN,nOpc)) }
    Local bCancela:= {|| oDlg:End() }
    Local aButtons:= {}
    Local oPainel
    Local oLayer
    Local oTela1
    Static oDlg

    dbSelectArea("SX5")
    SX5->(dbSetOrder(1))
    if nOpc==3 //incluir
        cTabela := "ZL"
        cChave  := Ultimo()
        cDescri := SPACE(TAMSX3("X5_DESCRI")[1])
        cLocal  := SPACE(3)
        cLocalN := SPACE(TAMSX3("X5_DESCENG")[1])
    Else
        SX5->(dbGoTop())
        If SX5->(dbSeek(xFilial("SX5")+TRB->(X5_TABELA+X5_CHAVE)))
            cTabela := TRB->X5_TABELA
            cChave  := Alltrim(TRB->X5_CHAVE)
            cDescri := TRB->X5_DESCRI
            cLocal  := Substr(TRB->X5_DESCSPA,1,3)
            cLocalN := TRB->X5_DESCENG
        Else
            Alert("Registro não existe mais!!!!")
            Return .f.
        EndIf
    Endif
    DEFINE MSDIALOG oDlg TITLE cTitulo FROM 000, 000  TO 330, 600 COLORS CLR_BLACK, CLR_WHITE PIXEL
    oPainel:= tPanel():New(0,0,,oDlg,,,,,CLR_WHITE,100,030)
    oPainel:Align  := CONTROL_ALIGN_ALLCLIENT

    oLayer := FWLayer():New()
    oLayer:Init( oPainel, .F. )
    oLayer:AddLine( "LINE01", 95, .T. )
    oLayer:AddCollumn("BOX" ,100,,"LINE01" )
    oLayer:AddWindow( "BOX" , "PANEL01","Informe o nome do gestor",80, .F.,.F.,,"LINE01" ) 

    oTela1 := oLayer:GetWinPanel("BOX" ,"PANEL01","LINE01")
    oTabela:= tGet():New(005,005,{|u| if(PCount()>0,cTabela:=u,cTabela)}, oTela1 ,030,15,PESQPICT("SX3","X5_TABELA") ,{ || },CLR_BLACK,CLR_WHITE,,,,.T.,,, {|| .F. } ,,,,.F.,,"",'cTabela',,,,.T.,,,"Tabela: ",1 )
    oChave := tGet():New(005,040,{|u| if(PCount()>0,cChave :=u,cChave )}, oTela1 ,030,15,PESQPICT("SX3","X5_CHAVE")  ,{ || ExistChav("SX5", "ZL"+M->cChave ,1)},CLR_BLACK,CLR_WHITE,,,,.T.,,, {|| .F. } ,,,,.F.,,"",'cChave',,,,.T.,,,"Codigo: ",1 )
    oDescri:= tGet():New(035,005,{|u| if(PCount()>0,cDescri:=u,cDescri)}, oTela1 ,285,20,PESQPICT("SX3","X5_DESCRI") ,{ || },CLR_RED,CLR_WHITE,,,,.T.,,, {||IIF(nOpc==3.OR.nOpc==4,.T.,.F.) } ,,,,.F.,,"",'cDescri',,,,.T.,,,"Nome do Gestor: *",1 )
    oLocal := tGet():New(070,005,{|u| if(PCount()>0,cLocal:=u,cLocal)}	, oTela1 ,060,20,PESQPICT("SX3","X5_DESCSPA"),{ || cLocalN := POSICIONE("SYA",1,XFILIAL("SYA")+cLocal,"YA_DESCR"), oLocalN:Refresh() },CLR_BLACK,CLR_WHITE,,,,.T.,,, {||IIF(nOpc==3.OR.nOpc==4,.T.,.F.) } ,,,,.F.,,"SYA",'cLocal',,,,.T.,,,"Localidade: ",1 )
    oLocalN:= tGet():New(070,070,{|u| if(PCount()>0,cLocalN:=u,cLocalN)}, oTela1 ,220,20,PESQPICT("SX3","X5_DESCENG"),{ || },CLR_BLACK,CLR_WHITE,,,,.T.,,, {|| .F. } ,,,,.F.,,"",'cLocalN',,,,.T.,,,"Desc.Local: ",1 )

    ACTIVATE MSDIALOG oDlg ON INIT EnchoiceBar(oDlg,bOk,bCancela,,aButtons) CENTERED
Return
  A função abaixo, usamos para gravar na tabela SX5
Static Function fGrava(_cTabela,_cChave,_cDescri,_cLocal,_cLocalN,nOpc)
    Local lGrava := .F.
    Local cMsg   := ""

    If Empty(_cChave) .OR. Empty(_cDescri) //.OR. Empty(_cLocal)
        MsgStop("Campos obrigatorio em branco!")
        Return
    Endif

    dbSelectArea("SX5")
    SX5->(dbSetOrder(1))
    SX5->(dbGoTop())
    if nOpc==3 .OR. nOpc==4
        if nOpc==4 .AND. ExisteGestor(_cChave)
            if !MsgNoYes("O código do gesto já está em uso, tem certeza que deseja alterar o nome do Gestor?")
                Return()
            Endif
        Endif

        lGrava := !dbSeek(xFilial("SX5")+_cTabela+_cChave)
        RecLock("SX5",lGrava)
        SX5->X5_FILIAL := xFilial("SX5")
        SX5->X5_TABELA := _cTabela
        SX5->X5_CHAVE  := _cChave
        SX5->X5_DESCRI := _cDescri
        SX5->X5_DESCSPA:= _cLocal
        SX5->X5_DESCENG:= _cLocalN
        SX5->(MsUnlock())
        cMsg := "Registro salvo com sucesso!"
    Else

        IF ExisteGestor(_cChave)
            cMsg := "Problema: Não é possível excluir o gestor." + CRLF + CRLF +;
                    "Motivo: O gesto " + _cChave + " está em uso." + CRLF + CRLF +;
                    "Solução: Entre no cadastro de funcionários e filtre pelo campo 'Cod.Gestor' pesquisando com o código " + _cChave
        else
            If dbSeek(xFilial("SX5")+_cTabela+_cChave)
                Reclock("SX5",.F.)
                SX5->(dbDelete())
                SX5->(MsUnlock())
                cMsg := "Registro removido com sucesso!"
            ENDIF
        EndIf

    Endif
    MsgInfo(cMsg,"Aviso")
    AGPE001TRB()
    oBrowse:Refresh(.T.)
Return
  Criamos uma função via SQL para buscar o último código
Static Function Ultimo()
    Local cUltimo:= "000001"

    Local cTmpSX5 	:= GetNextAlias()

    IF SELECT(cTmpSX5) # 0
        (cTmpSX5)->(dbCloseArea())
    ENDIF
    BeginSql Alias cTmpSX5
        SELECT MAX(X5_CHAVE) ULTIMO
        FROM %Table:SX5% SX5
        WHERE SX5.D_E_L_E_T_ = ' '
        AND X5_FILIAL   = %xFilial:SX5%
        AND X5_TABELA 		= %Exp:"ZL"%
    EndSql

    dbSelectArea(cTmpSX5)
    If !(cTmpSX5)->(Eof())
        cUltimo := SOMA1((cTmpSX5)->ULTIMO)
    EndIf

Return cUltimo
continua página 3 A função abaixo é para montar a estrutura da tabela SX5 no browse e exibir o registros caso houver.
Static Function AGPE001TRB()
    Local aTam    := {}
    Local aCampos := {}
    Local cQuery  := ""

    If Select('TRB') > 0
        TRB->(dbCloseArea())
    Endif

    aTam:= TamSX3("X5_TABELA")
    Aadd(aCampos,{"X5_TABELA","C",aTam[1],aTam[2]})

    aTam:= TamSX3("X5_CHAVE")
    Aadd(aCampos,{"X5_CHAVE","C",aTam[1],aTam[2]})

    aTam:= TamSX3("X5_DESCRI")
    Aadd(aCampos,{"X5_DESCRI","C",aTam[1],aTam[2]})

    aTam:= TamSX3("X5_DESCSPA")
    Aadd(aCampos,{"X5_DESCSPA","C",aTam[1],aTam[2]})

    aTam:= TamSX3("X5_DESCENG")
    Aadd(aCampos,{"X5_DESCENG","C",aTam[1],aTam[2]})


    If (Select("TRB") <> 0)
        dbSelectArea("TRB")
        TRB->(dbCloseArea ())
    Endif

    cArqTRB := CriaTrab(aCampos,.T.)
    DbUseArea(.T.,,cArqTRB,"TRB",.T.)

    dbSelectArea( "TRB" )
    IndRegua( "TRB", cArqTRB+"1", "X5_CHAVE"  ,,,"Codigo" )
    IndRegua( "TRB", cArqTRB+"2", "X5_DESCRI" ,,,"Nome" )
    IndRegua( "TRB", cArqTRB+"3", "X5_DESCSPA",,,"Localidade" )
    dbClearIndex()
    dbSetIndex( cArqTRB+"1" + OrdBagExt() )
    dbSetIndex( cArqTRB+"2" + OrdBagExt() )
    dbSetIndex( cArqTRB+"3" + OrdBagExt() )
    TRB->(DbSetOrder(1))
    TRB->(DbGotop())

    cQuery := " SELECT X5_TABELA, X5_CHAVE, X5_DESCRI, X5_DESCSPA, X5_DESCENG "
    cQuery += " FROM " + RetSQLName("SX5") + " SX5"
    cQuery += " WHERE SX5.D_E_L_E_T_ = ' ' "
    cQuery += " AND X5_FILIAL = '" + xFilial("SX5") + "' "
    cQuery += " AND X5_TABELA = 'ZL' "
    cQuery += " AND X5_CHAVE <> '' "
    cQuery += " ORDER BY X5_CHAVE "

    If (Select("TRBSX5") <> 0)
        dbSelectArea("TRBSX5")
        TRBSX5->(dbCloseArea ())
    Endif

    cQuery := ChangeQuery(cQuery)
    DbUseArea(.T., "TOPCONN", TCGenQry(,,cQuery), 'TRBSX5', .F., .T.)

    DbSelectArea("TRBSX5")
    DbGotop()
    While TRBSX5->(!Eof())
        RecLock("TRB",.T.)
        TRB->X5_TABELA  := TRBSX5->X5_TABELA
        TRB->X5_CHAVE   := TRBSX5->X5_CHAVE
        TRB->X5_DESCRI  := TRBSX5->X5_DESCRI
        TRB->X5_DESCSPA := TRBSX5->X5_DESCSPA
        TRB->X5_DESCENG := TRBSX5->X5_DESCENG
        TRB->(MsUnLock())
        TRBSX5->(DbSkip())
    EndDo
    TRBSX5->(dbCloseArea())
Return
   
Static Function ExisteGestor(cCodigo)
    Local lRet := .F.
    Local cArea		:= GetArea()
    Local cTmpSRA 	:= GetNextAlias()

    IF SELECT(cTmpSRA) # 0
        (cTmpSRA)->(dbCloseArea())
    ENDIF
    BeginSql Alias cTmpSRA
                SELECT RA_ZZGESTO
                FROM %Table:SRA% SRA
                WHERE SRA.D_E_L_E_T_ = ' '
                AND RA_FILIAL   = %xFilial:SRA%
                AND RA_ZZGESTO	= %Exp:cCodigo%
    EndSql

    dbSelectArea(cTmpSRA)
    If (cTmpSRA)->(!Eof())
        lRet := .T.
    EndIf
    RestArea(cArea)
Return(lRet)
  Se conhece uma forma mais simples, compartilhe com a gente, Let's Share!