Usando a classe FWMarkBrowse com tabela temporária
Muitos amigos tem me perguntado em como montar uma tela usando MarkBrowse com tabela temporária. E pra ser honesto no começo é meio chato, mas depois que você pega o jeito, fica muito fácil trabalhar com a classe FWMarkBrowse, principalmente se você estiver trabalhando com tabelas existente, mas trabalhar com tabela temporária não é difícil, só dá um trabalhinho extra.
A classe FWMarkBrowse fornece um objeto do tipo grade, com botões laterais e uma coluna com a opção de marca e desmarca. Esta classe pode ser usada dentro de uma janela ou outro componente tipo Panel, ou simplesmente pode ser a própria janela que será aberta.
Para saber mais acesse http://tdn.totvs.com/display/public/PROT/FWMarkBrowse
Então vamos ao que interessa, irei mostrar um simples exemplo onde irei exibir uma janela, onde está tela teremos botões, filtro, configurações extras da tela e pesquisa. O exemplo que irei postar, poderia ficar mais resumido em relação a codificação, mas para ficar mais claro, deixe o fonte o mais completo e detalhado.
1 2 3 |
//Irei incluir algumas bibliotecas #INCLUDE "PROTHEUS.CH" #INCLUDE "FWMVCDEF.CH" |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
//Iniciar a rotina User Function MCFG0006I() //Declarar variáveis locais Local oColumn Local aCampos := {} Local aColumns := {} Local cArqTrb Local cIndice1, cIndice2, cIndice3,cIndice4 := "" Local nX Local lMarcar := .F. Local aSeek := {} Local bKeyF12 := {|| U_MCFG006M(),oBrowse:SetInvert(.F.),oBrowse:Refresh(),oBrowse:GoTop(.T.) } //Programar a tecla F12 //Declarar variáveis privadas Private oBrowse := Nil Private cCadastro := "Usuários do Sistema" Private aRotina := Menudef() //Se for criar menus via MenuDef //Criar a tabela temporária AAdd(aCampos,{"TR_OK" ,"C",002,0}) //Este campo será usado para marcar/desmarcar AAdd(aCampos,{"TR_ST" ,"C",001,0}) AAdd(aCampos,{"TR_ID" ,"C",006,0}) AAdd(aCampos,{"TR_NOME" ,"C",050,0}) AAdd(aCampos,{"TR_LOGIN","C",020,0}) AAdd(aCampos,{"TR_CARGO","C",050,0}) AAdd(aCampos,{"TR_DEPTO","C",050,0}) AAdd(aCampos,{"TR_EMAIL","C",150,0}) AAdd(aCampos,{"TR_SUPER","C",006,0}) AAdd(aCampos,{"TR_POS" ,"N",012,0}) //Se o alias estiver aberto, fechar para evitar erros com alias aberto If (Select("TRB") <> 0) dbSelectArea("TRB") TRB->(dbCloseArea ()) Endif //A função CriaTrab() retorna o nome de um arquivo de trabalho que ainda não existe e dependendo dos parâmetros passados, pode criar um novo arquivo de trabalho. cArqTrb := CriaTrab(aCampos,.T.) //Criar indices cIndice1 := Alltrim(CriaTrab(,.F.)) cIndice2 := cIndice1 cIndice3 := cIndice1 cIndice4 := cIndice1 cIndice1 := Left(cIndice1,5) + Right(cIndice1,2) + "A" cIndice2 := Left(cIndice2,5) + Right(cIndice2,2) + "B" cIndice3 := Left(cIndice3,5) + Right(cIndice3,2) + "C" cIndice4 := Left(cIndice4,5) + Right(cIndice4,2) + "D" //Se indice existir excluir If File(cIndice1+OrdBagExt()) FErase(cIndice1+OrdBagExt()) EndIf If File(cIndice2+OrdBagExt()) FErase(cIndice2+OrdBagExt()) EndIf If File(cIndice3+OrdBagExt()) FErase(cIndice3+OrdBagExt()) EndIf If File(cIndice4+OrdBagExt()) FErase(cIndice4+OrdBagExt()) EndIf //A função dbUseArea abre uma tabela de dados na área de trabalho atual ou na primeira área de trabalho disponível dbUseArea(.T.,,cArqTrb,"TRB",Nil,.F.) //A função IndRegua cria um índice temporário para o alias especificado, podendo ou não ter um filtro IndRegua("TRB", cIndice1, "TR_NOME" ,,, "Indice Nome...") IndRegua("TRB", cIndice2, "TR_LOGIN",,, "Indice Login...") IndRegua("TRB", cIndice3, "TR_EMAIL",,, "Indice E-mail...") IndRegua("TRB", cIndice4, "TR_ID" ,,, "Indice ID...") //Fecha todos os índices da área de trabalho corrente. dbClearIndex() //Acrescenta uma ou mais ordens de determinado índice de ordens ativas da área de trabalho. dbSetIndex(cIndice1+OrdBagExt()) dbSetIndex(cIndice2+OrdBagExt()) dbSetIndex(cIndice3+OrdBagExt()) dbSetIndex(cIndice4+OrdBagExt()) //Popular tabela temporária, irei colocar apenas um unico registro If RecLock("TRB",.t.) TRB->TR_OK := " " TRB->TR_ST := "S" //situação TRB->TR_ID := "000000" TRB->TR_NOME := "Administrador" TRB->TR_LOGIN := "Admin" TRB->TR_CARGO := "Administrador" TRB->TR_DEPTO := "Depto TI" TRB->TR_EMAIL := "administrador@empresa.com" TRB->TR_SUPER := "" TRB->TR_POS := 1 MsUnLock() Endif TRB->(DbGoTop()) If TRB->(!Eof()) //Irei criar a pesquisa que será apresentada na tela aAdd(aSeek,{"Nome" ,{{"","C",050,0,"Nome" ,"@!"}} } ) aAdd(aSeek,{"Login" ,{{"","C",006,0,"Login" ,"@!"}} } ) aAdd(aSeek,{"E-mail",{{"","C",100,0,"E-mail",""}} } ) aAdd(aSeek,{"ID" ,{{"","C",006,0,"ID" ,"@!"}} } ) //Agora iremos usar a classe FWMarkBrowse oBrowse:= FWMarkBrowse():New() oBrowse:SetDescription(cCadastro) //Titulo da Janela oBrowse:SetParam(bKeyF12) // Seta tecla F12 oBrowse:SetAlias("TRB") //Indica o alias da tabela que será utilizada no Browse oBrowse:SetFieldMark("TR_OK") //Indica o campo que deverá ser atualizado com a marca no registro oBrowse:oBrowse:SetDBFFilter(.T.) oBrowse:oBrowse:SetUseFilter(.T.) //Habilita a utilização do filtro no Browse oBrowse:oBrowse:SetFixedBrowse(.T.) oBrowse:SetWalkThru(.F.) //Habilita a utilização da funcionalidade Walk-Thru no Browse oBrowse:SetAmbiente(.T.) //Habilita a utilização da funcionalidade Ambiente no Browse oBrowse:SetTemporary() //Indica que o Browse utiliza tabela temporária oBrowse:oBrowse:SetSeek(.T.,aSeek) //Habilita a utilização da pesquisa de registros no Browse oBrowse:oBrowse:SetFilterDefault("") //Indica o filtro padrão do Browse //Permite adicionar legendas no Browse oBrowse:AddLegend("TR_ST=='N'","GREEN" ,"Usuários Liberados") oBrowse:AddLegend("TR_ST=='S'","RED" ,"Usuários Bloqueados") //Adiciona uma coluna no Browse em tempo de execução oBrowse:SetColumns(MCFG006TIT("TR_ID" ,"ID" ,03,"@!",0,010,0)) oBrowse:SetColumns(MCFG006TIT("TR_NOME" ,"Nome" ,04,"@!",1,080,0)) oBrowse:SetColumns(MCFG006TIT("TR_LOGIN","Login" ,05,"@!",1,040,0)) oBrowse:SetColumns(MCFG006TIT("TR_CARGO","Cargo" ,06,"@!",1,050,0)) oBrowse:SetColumns(MCFG006TIT("TR_DEPTO","Depto" ,07,"@!",1,100,0)) oBrowse:SetColumns(MCFG006TIT("TR_EMAIL","E-mail" ,08,"",1,100,0)) oBrowse:SetColumns(MCFG006TIT("TR_SUPER","Superior" ,09,"@!",1,020,0)) oBrowse:SetColumns(MCFG006TIT("TR_POS" ,"RECNO" ,11,"@E9999999",2,20,0)) //Adiciona botoes na janela oBrowse:AddButton("Enviar Mensagem" , { || U_MCFG006M()},,,, .F., 2 ) oBrowse:AddButton("Detalhes" , { || MsgRun('Coletando dados de usuário(s)','Relatório',{|| U_RCFG0005() }) },,,, .F., 2 ) oBrowse:AddButton("Legenda" , { || MCFG006LEG()},,,, .F., 2 ) //Indica o Code-Block executado no clique do header da coluna de marca/desmarca oBrowse:bAllMark := { || MCFG6Invert(oBrowse:Mark(),lMarcar := !lMarcar ), oBrowse:Refresh(.T.) } //Método de ativação da classe oBrowse:Activate() oBrowse:oBrowse:Setfocus() //Seta o foco na grade Else Return EndIf //Limpar o arquivo temporário If !Empty(cArqTrb) Ferase(cArqTrb+GetDBExtension()) Ferase(cArqTrb+OrdBagExt()) cArqTrb := "" TRB->(DbCloseArea()) Endif Return(.T.) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//Função para marcar/desmarcar todos os registros do grid Static Function MCFG6Invert(cMarca,lMarcar) Local cAliasSD1 := 'TRB' Local aAreaSD1 := (cAliasSD1)->( GetArea() ) dbSelectArea(cAliasSD1) (cAliasSD1)->( dbGoTop() ) While !(cAliasSD1)->( Eof() ) RecLock( (cAliasSD1), .F. ) (cAliasSD1)->TR_OK := IIf( lMarcar, cMarca, ' ' ) MsUnlock() (cAliasSD1)->( dbSkip() ) EndDo RestArea( aAreaSD1 ) Return .T. |
1 2 3 4 5 6 7 8 9 |
//Caso crie os botões por função, abaixo seque um exemplo Static Function MenuDef() Local aRot := {} ADD OPTION aRot TITLE "Enviar Mensagem" ACTION "U_MCFG006M()" OPERATION 6 ACCESS 0 ADD OPTION aRot TITLE "Detalhes" ACTION "MsgRun('Coletando dados de usuário(s)','Relatório',{|| U_RCFG0005() })" OPERATION 6 ACCESS 0 //ADD OPTION aRot TITLE "Legenda" ACTION "" OPERATION 6 ACCESS 0 Return(Aclone(aRot)) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
//Função para criar as colunas do grid Static Function MCFG006TIT(cCampo,cTitulo,nArrData,cPicture,nAlign,nSize,nDecimal) Local aColumn Local bData := {||} Default nAlign := 1 Default nSize := 20 Default nDecimal:= 0 Default nArrData:= 0 If nArrData > 0 bData := &("{||" + cCampo +"}") //&("{||oBrowse:DataArray[oBrowse:At(),"+STR(nArrData)+"]}") EndIf /* Array da coluna [n][01] Título da coluna [n][02] Code-Block de carga dos dados [n][03] Tipo de dados [n][04] Máscara [n][05] Alinhamento (0=Centralizado, 1=Esquerda ou 2=Direita) [n][06] Tamanho [n][07] Decimal [n][08] Indica se permite a edição [n][09] Code-Block de validação da coluna após a edição [n][10] Indica se exibe imagem [n][11] Code-Block de execução do duplo clique [n][12] Variável a ser utilizada na edição (ReadVar) [n][13] Code-Block de execução do clique no header [n][14] Indica se a coluna está deletada [n][15] Indica se a coluna será exibida nos detalhes do Browse [n][16] Opções de carga dos dados (Ex: 1=Sim, 2=Não) */ aColumn := {cTitulo,bData,,cPicture,nAlign,nSize,nDecimal,.F.,{||.T.},.F.,{||.T.},NIL,{||.T.},.F.,.F.,{}} Return {aColumn} |
1 2 3 4 5 6 7 8 9 10 11 |
//Função para criar a tela de legenda Static Function MCFG006LEG() Local oLegenda := FWLegend():New() oLegenda:Add( '', 'BR_VERDE' , "Usuários Liberados" ) oLegenda:Add( '', 'BR_VERMELHO', "Usuários Bloqueados") oLegenda:Activate() oLegenda:View() oLegenda:DeActivate() Return Nil |
Agora, como identificar se o registro está selecionado?
Para isso é necessário verificar (neste exemplo) o campo TR_OK, ele é responsável em receber a marcação
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//Na sua função, você poderia fazer assim: TRB->( DbSetOrder(1) ) TRB->( DbGoTop() ) nCont:=0 While !TRB->(Eof()) If !Empty(TRB->TR_OK) //Se diferente de vazio, é porque foi marcado cPara += Alltrim(TRB->TR_EMAIL)+";" nCont++ Endif TRB->( dbSkip() ) EndDo if nCont == 0 Alert("Selecione pelo menos um usuario!") return Endif |
Simples o uso da função, não é mesmo?
Activate AddButton AddFilter AddLegend AddMarkColumns AddStatusColumns AllMark FWMarkBrowse Grade Grid protheus SetAlias SetAllMark SetUseFilter
2 comentários
Sabia que quando você coloca a biblioteca TOTVS.ch não é necessário adicionar a Protheus.ch? A TOTVS.ch é apenas um alias (apelido) para a Protheus.ch.
Veja nesse link o arquivo TOTVS.ch descriptografado: https://github.com/imsys/Protheus-Include/blob/master/include/totvs.ch
Muito obrigado pelos artigos maravilhosos! Tem me ajudado muito!
Bom dia Guilherme, obrigado pelo comentário, é força do habito, as vezes copiando e colando parte de outro fonte, vem algumas variaveis ou includes, rsrs
abraços,