Olá! No artigo de hoje vamos mostrar uma dica de programação AdvPL e ensinar como colocar legenda na GetDados (seja uma MsGetDados ou MsNewGetDados).
O motivo para colocar uma legenda em listagens de registros no TOTVS Protheus é, além da estética, facilitar que o usuário identifique rapidamente o tipo ou situação de um registro que é apresentado. Isso auxilia a utilização diária de suas rotinas e agiliza os processos para o seu cliente.
Para isso, vamos utilizar um código-fonte de exemplo com diversas legendas diferentes para a sua listagem de registros. Veja um exemplo de tela:
Como funciona o Header de uma GetDados
Antes de mostrar o código, vamos entender um pouco sobre o funcionamento de uma GetDados.
O objeto da GetDados é composto sempre por duas partes principais: o aHeader e o aCols. Esses são nomes comuns para as variáveis de cabeçalho e linhas, respectivamente, além de ser o nome das propriedades do objeto. Explicando de forma simples, o aHeader é uma variável do tipo array que define quantas e quais as colunas que serão apresentadas e o aCols (também é um array) é o conteúdo dos registros que serão exibidos.
O aHeader é o responsável por descrever quantas colunas a sua grid terá e quais os tipos de dados que serão aceitos nessas colunas. O aCols é uma coleção de linhas no vetor onde cada linha terá a quantidade de posições igual ao tamanho do array aHeader. Ou seja, cada posição de uma linha do array aCols irá corresponder a uma coluna do aHeader.
Para ser mais exato, cada linha do aCols terá sempre o tamanho do aHeader + 1 posição. Essa última posição (ou coluna) é utilizada pelo objeto para determinar se aquele registro foi marcado para exclusão.
Após essa explicação fica mais fácil perceber que os registros (conteúdo do array aCols) devem seguir as colunas definidas pelo array do cabeçalho (o aHeader). Nesse cenário, o aHeader passa a ter função vital para o funcionamento do objeto GetDados: ele descreve as propriedades dos dados que serão exibidos, em cada coluna. É ele quem vai determinar qual o tamanho da informação, tipo de conteúdo (se caracter, numérico, data, booleano…), validações, consulta padrão, when… enfim, todas as opções disponíveis para o dicionário de dados SX3.
Estrutura do fonte de exemplo
Após essa explicação rápida (certamente ainda teremos muito mais artigos falando mais sobre GetDados 🙂 ), vamos para o nosso fonte de exemplo!
A estrutura do fonte é bem simples e completamente especializado no desenho de uma tela para listar os clientes (SA1) da base de dados, sem consultas SQL ou outras condições específicas, apenas para destacar a GetDados. Para tanto, separei o fonte em três funções: função principal (RXXXBMP), desenho e apresentação da tela (DesenhaTela) e preenchimento dos dados (DadosSA1).
A função principal é onde faríamos tratamentos e verificações antes da execução do resto da rotina. Por exemplo, colocar um pergunte para filtrar os resultados apresentados para o usuário, verificar se determinado campo ou tabela existe na base de dados, entre outros. Também, caso necessário, poderámos utilizar essa função de inicialização para definir variáveis de escopo amplo que seriam utilizadas por outras funções no mesmo código-fonte.
/* ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±± ±±ºPrograma ³RXXXBMP ºAutor ³Vinícius Gregório º Data ³ 23/07/14 º±± ±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±± ±±ºDesc. ³ Fonte de exemplo para criação de MsNewGetDados com legendasº±± ±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±± ±±ºUso ³ AcademiaERP º±± ±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ±± ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß */ User Function RXXXBMP() //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Declaração de variáveis³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Local aArea := GetArea() //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Espaço para verificações como: ³ //³1- Perguntes para servir como base para filtro³ //³2- Verificações de versões do RPO... ³ //³3- Etc ³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Chama a rotina filtrada com os logs³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ LjMsgRun(OemToAnsi("Aguarde, montando telas de consulta..."),,{|| DesenhaTela(),CLR_HRED}) RestArea(aArea) Return .T.
Conforme mencionei, deixei um espaço entre as variáveis e o retorno da função caso você queira fazer uma implementação de filtro ou outros tratamentos antes de começar a desenhar a tela. Após isso, fiz uma chamada simples para a função DesenhaTela(), encapsulando dentro da função LjMsgRun() que irá desenhar uma janela de transição simples.
/* ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±± ±±ºPrograma ³ DesenhaTela ºAutor ³Vinícius Gregório º Data ³ 12/05/14 º±± ±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±± ±±ºDesc. ³ Função responsável pela montagem e exibição da tela para o º±± ±±º ³ usuário. º±± ±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±± ±±ºUso ³ AcademiaERP º±± ±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ±± ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß */ Static Function DesenhaTela() //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Declaração de variáveis³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Local aArea := GetArea() Local nLoop := 0 Local nPosPadrao := 1 Local aSize := MsAdvSize() Local cTitDialog := "Listagem de clientes" Local nOpcA := 0 Local aBotao := {} Local oDlgVis, oFldDados //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Botões de visualizações das legendas.³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Local oBtnLSA1 := Nil //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Botões de pesquisa nos itens das getDados³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Local oPesqSA1 := Nil //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Variáveis da aba de ordens de serviço³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Private aColsSA1 := {} Private oGDSA1 := Nil Private aHeadSA1 := {} //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³cria os aHeaders e preenche todos os aCols³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ DadosSA1() //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Monta a tela principal³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ oDlgVis := MSDIALOG():New(aSize[2],aSize[1],aSize[6]-50,aSize[5]-50,cTitDialog,,,,,,,,,.T.) oFldDados := TFolder():New(015,005,{"Clientes"},,oDlgVis,,,,.T.,.T.,(oDlgVis:NCLIENTWIDTH/2)-10,(oDlgVis:NCLIENTHEIGHT/2)-30) //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Coloca a getDados com imagens³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ oGDSA1 := MsNewGetDados():New(000,000,(oFldDados:aDialogs[1]:nClientHeight/2)-20,oFldDados:aDialogs[1]:nClientWidth/2,/*GD_INSERT+GD_UPDATE+GD_DELETE*/0,,,,,,9999,,,,oFldDados:aDialogs[1],@aHeadSA1,@aColsSA1) ACTIVATE MSDIALOG oDlgVis CENTERED ON INIT EnchoiceBar(oDlgVis,{||nOpcA:=1,oDlgVis:End()},{||nOpcA:=0,oDlgVis:End()},,/*aBotao*/) //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Caso o usuário clique no OK³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ If nOpcA==1 //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Colocar aqui qualquer processamento posterior à confirmação da tela³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Endif RestArea(aArea) Return .T.
A função DesenhaTela() cria uma MsDialog (oDlgVis) utilizando as informações de posicionamento vindas da função MsAdvSize(), desenha um TFolder (aba) para conter a GetDados (oFldDados) e coloca uma MsNewGetDados (oGDSA1) dentro do folder. Essa GetDados desenhada irá receber as variáveis private aHeadSA1 e aColsSA1 para as suas especificações e registros, respectivamente.
Esse código é bem simples para quem está acostumado a desenhar telas e trabalhar com objetos no TOTVS Protheus. No entanto, é sempre um bom exemplo para trabalhar com o posicionamento relativo de objetos, utilizando as propriedades nClientHeight e nClientWidth dos objetos onde foram inseridos.
Para finalizar a tela, ativamos a MsDialog e recebemos o retorno através da variável nOpcA, onde nOpcA == 0 o usuário clicou em cancelar e nOpcA == 1 o usuário confirmou a tela.
A “sacada” para colocar legenda na GetDados
Passamos agora para a última função do fonte, responsável pela definição da estrutura do objeto e pelo dados que serão exibidos para o usuário. É aqui que definiremos que uma coluna da GetDados irá exibir uma imagem, no nosso caso, as legendas dos registros.
/* ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±± ±±ºPrograma ³DadosSA1 ºAutor ³Vinícius Gregório º Data ³ 12/05/14 º±± ±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±± ±±ºDesc. ³ Função de consulta dos registros na base de dados e º±± ±±º ³ preenchimento das estruturas para exibição em tela. º±± ±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±± ±±ºUso ³ AcademiaERP º±± ±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ±± ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß */ Static Function DadosSA1() //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Declaração de variáveis³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Local aArea := GetArea() //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Leds utilizados para as legendas das rotinas³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Local oGreen := LoadBitmap( GetResources(), "BR_VERDE") Local oRed := LoadBitmap( GetResources(), "BR_VERMELHO") Local oBlack := LoadBitmap( GetResources(), "BR_PRETO") Local oYellow := LoadBitmap( GetResources(), "BR_AMARELO") Local oBrown := LoadBitmap( GetResources(), "BR_MARROM") Local oBlue := LoadBitmap( GetResources(), "BR_AZUL") Local oOrange := LoadBitmap( GetResources(), "BR_LARANJA") Local oViolet := LoadBitmap( GetResources(), "BR_VIOLETA") Local oPink := LoadBitmap( GetResources(), "BR_PINK") Local oGray := LoadBitmap( GetResources(), "BR_CINZA") //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Monta o aHeader³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Aadd(aHeadSA1,{"OK",; "COR",; "@BMP",; 1,; 0,; .T.,; "",; "",; "",; "R",; "",; "",; .F.,; "V",; "",; "",; "",; ""}) dbSelectArea("SX3") SX3->( dbSetOrder(1) ) SX3->( dbSeek("SA1") ) While SX3->( !Eof()) .And. SX3->X3_ARQUIVO $ "SA1" If X3USO(X3_USADO) .And. cNivel >= X3_NIVEL Aadd(aHeadSA1,{ AllTrim(X3Titulo()),; SX3->X3_CAMPO,; SX3->X3_PICTURE,; SX3->X3_TAMANHO,; SX3->X3_DECIMAL,; SX3->X3_VALID,; SX3->X3_USADO,; SX3->X3_TIPO,; SX3->X3_F3,; SX3->X3_CONTEXT,; SX3->X3_CBOX,; SX3->X3_RELACAO,; SX3->X3_WHEN,; "V",; SX3->X3_VLDUSER,; SX3->X3_PICTVAR,; SX3->X3_OBRIGAT}) Endif SX3->(dbSkip()) EndDo dbSelectArea("SA1") dbSetOrder(1) dbGoTop() If !SA1->(EOF())//Verifica se a consulta retornou algum resultado //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Limpa o aCols ³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ aColsSA1 := {} Do While !EOF() //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Cria uma nova posição no aCols³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ aAdd(aColsSA1,Array(Len(aHeadSA1)+1)) //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Começamos o nLoop a partir do dois por causa³ //³da coluna de legenda ³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ For nLoop := 2 to Len(aHeadSA1) If aHeadSA1[nLoop][10] <> "V"//X3_CONTEXT aColsSA1[Len(aColsSA1)][nLoop] := SA1->&(aHeadSA1[nLoop][2]) EndIf Next nLoop //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Marca a legenda³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ If SA1->A1_EST=='EX' aColsSA1[Len(aColsSA1)][1] := oBlack ElseIf SA1->A1_EST=='SP' aColsSA1[Len(aColsSA1)][1] := oGreen ElseIf SA1->A1_EST=='RJ' aColsSA1[Len(aColsSA1)][1] := oYellow ElseIf SA1->A1_EST=='SC' aColsSA1[Len(aColsSA1)][1] := oBlue ElseIf SA1->A1_EST=='RN' aColsSA1[Len(aColsSA1)][1] := oBrown ElseIf SA1->A1_EST=='DF' aColsSA1[Len(aColsSA1)][1] := oOrange ElseIf SA1->A1_EST=='PA' aColsSA1[Len(aColsSA1)][1] := oViolet Else aColsSA1[Len(aColsSA1)][1] := oRed Endif aColsSA1[Len(aColsSA1)][Len(aHeadSA1)+1]:=.F. dbSelectArea("SA1") SA1->(dbSkip()) EndDo Else aColsSA1 := {} aAdd(aColsSA1,Array(Len(aHeadSA1)+1)) aColsSA1[Len(aColsSA1)][Len(aHeadSA1)+1]:=.F. Endif RestArea(aArea) Return .T.
Um dos pontos mais importantes nessa função são as variáveis declaradas. Elas são inicializadas com o resultado da função LoadBitmap(), que é responsável por carregar imagens para o objeto representado pela variável. Como parâmetro, estamos passando a função GetResources(), responsável por carregar as imagens já existentes na instalação do TOTVS Protheus. O segundo parâmetro da função determina qual o nome da imagem que estamos buscando e, nesse caso, determinamos as imagens que correspondem as legendas que encontramos em outras rotinas do sistema.
Após definir quais serão os objetos utilizados para a legenda, começamos a definir o nosso aHeader e, como a nossa primeira coluna será utilizada para legenda, definimos manualmente todas as posições da primeira linha desse array. A particularidade que define como colocar legenda na GetDados é a picture dessa linha ser preenchida como @BMP. Essa é a informação que define para o sistema que essa coluna irá apresentar uma imagem.
Logo em seguida, definimos o resto do array aHeader posicionando no dicionário de campo SX3, utilizando o índice 1 (X3_ARQUIVO), na tabela SA1 e, verificando controles de acesso através de X3USO (verifica se o campo está em utilização) e do nível do usuário (cNivel >= X3_NIVEL), incluimos todos os campos da tabela na estrutura.
Por fim, vem a parte de carregar o aCols com os registros dos clientes na base de dados e nessa parte existem diversos trechos importantes que serão explicados.
1- Adicionamos uma linha no array aColsSA1 para cada registro da tabela de SA1. O tamanho do array será igual o tamanho do aHeader da GetDados, representado pela variável aHeadSA1, e com uma posição a mais (para registrar quando um registro está marcado para exclusão);
//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Cria uma nova posição no aCols³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ aAdd(aColsSA1,Array(Len(aHeadSA1)+1))
2- Preenchemos o conteúdo de cada posição da nova linha do aCols, começando a partir da segunda posição. Isso acontece porque reservamos a primeira posição para colocar a legenda da linha.
Dentro do preenchimento, verificamos se a coluna atual não é de contexto virtual (o campo não existe diretamente na tabela). Para esses casos o correto seria carregar o campo com o seu inicializador padrão. Porém, para facilitar o exemplo e evitar exceções no código, optei por remover esse tratamento.
A definição do valor da coluna no aCols é feito através de uma macro da segunda propriedade da coluna atual do aHeader (X3_CAMPO). Como essa propriedade contém o nome do campo, podemos utilizar essa informação para pegar os valores necessários;
//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Começamos o nLoop a partir do dois por causa³ //³da coluna de legenda ³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ For nLoop := 2 to Len(aHeadSA1) If aHeadSA1[nLoop][10] <> "V"//X3_CONTEXT aColsSA1[Len(aColsSA1)][nLoop] := SA1->&(aHeadSA1[nLoop][2]) EndIf Next nLoop
3- Essa é a parte mais importante do código. É aqui que definimos qual legenda será apresentada para o usuário e, no nosso caso, decidir colocar as cláusulas que definem a imagem a ser exibida de acordo com o campo A1_EST (Estado) do cliente. Perceba que, uma vez que a coluna está definida para exibir imagens através do picture @BMP, podemos atribuir objetos de imagem a essa posição e a informação será exibida corretamente;
//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Marca a legenda³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ If SA1->A1_EST=='EX' aColsSA1[Len(aColsSA1)][1] := oBlack ElseIf SA1->A1_EST=='SP' aColsSA1[Len(aColsSA1)][1] := oGreen ElseIf SA1->A1_EST=='RJ' aColsSA1[Len(aColsSA1)][1] := oYellow ElseIf SA1->A1_EST=='SC' aColsSA1[Len(aColsSA1)][1] := oBlue ElseIf SA1->A1_EST=='RN' aColsSA1[Len(aColsSA1)][1] := oBrown ElseIf SA1->A1_EST=='DF' aColsSA1[Len(aColsSA1)][1] := oOrange ElseIf SA1->A1_EST=='PA' aColsSA1[Len(aColsSA1)][1] := oViolet Else aColsSA1[Len(aColsSA1)][1] := oRed Endif
Pronto! Você acabou de aprender como colocar legenda na GetDados ;). Para testar o fonte completo, realize o download aqui.
Vejam no vídeo abaixo a execução desse exemplo:
Caso tenha ficado com alguma dúvida, deixe-nos um comentário abaixo! Obrigado e até o próximo artigo.
Tive problema quando o array é maior que 15.000 itens. Tem alguma dica de como fazer? Tirar o array e usar uma tabela temporária…
Bom dia Wellder,
Sim, os arrays tem uma limitação séria com relação ao tamanho. Por ocuparem diretamente espaço na memória e não terem um índice para controlar o acesso rápido a determinadas posições, é sempre recomendado utilizar tabelas temporárias para os casos onde trabalhamos com muitas informações.
Abraços
Muito bom.
Gostei muito deste espaço.
Otimo,
Bom exemplo