Combobox e Dropdown, na prática
Nota importante: para ter acesso aos vídeos e arquivos exemplos deste site, adquira um dos planos apresentados abaixo. Você pode comprar em até 5x no Cartão de Crédito, através do Paypal.
Veja como comprar e saiba mais sobre o material oferecido, clicando aqui.
Se você acompanhou os tutoriais anteriores, já sabe que é possível alterarmos as ribbons, em tempo de execução, utilizando os atributos gets (getVisible, getEnabled, getLabel, ...).
Agora, você aprenderá a usar os atributos gets, pertinentes aos controles Combobox e Dropdown, com o objetivo de preencher a lista, de forma dinâmica. Serão apresentados dois exemplos práticos:
- a montagem de uma lista de relatórios;
- a montagem de uma lista de clientes, que servirá de filtragem para um formulário.
Qual é a diferença de um controle Combobox para um controle Dropdown ?
A diferença está no fato de que no controle Combobox , podemos entrar com um valor, que esteja ou não presente na lista, o que já não é permitido no Dropdown. E na programação há uma pequena vantagem no emprego do Combobox, por ele permitir o uso direto do valor da lista. Já no Dropdown o valor retornado é o índice na lista. Mas isso não é fator impeditivo de se usar o Dropdown.
Compare os dois controles no código XML:
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="fncRibbon">
<ribbon startFromScratch="true">
<tabs>
<tab id = "guia1" label = "ComboBox e DropDown ">
<group id = "gr1" label = "ComboBox e DropDown" >
<comboBox id = "cbx1" label = "Combo dinâmico"
getItemCount = "fncGetItemCountCbx"
getItemLabel = "fncGetItemLabelCbx"
onChange = "fncOnChangeCbx"
/>
<labelControl id = "lb1" label = "----------------------------------------------" />
<dropDown id = "dd1" label = "Drop dinâmico"
getItemCount = "fncGetItemCountDrop"
getItemLabel = "fncGetItemLabelDrop"
onAction="fncOnActionDrop"
/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Observe que a diferença está apenas nos atributos que executam um evento de ação. O atributo OnAction para o Dropdown e o atributo OnChange para o controle Combobox.
Agora, veja o resultado do código XML:
Vamos começar demonstrando a técnica de preenchimento dinâmico da lista, usando o controle Dropdown.
Mecânica do preenchimento: o atributo getItemCount informa para o controle Dropdown a quantidade de itens que terá a lista. O controle Dropdown usa esta informação para disparar o atributo geItemLabel o número de vezes necessárias para se obter os nomes (labels) que irão compor a lista.
Tanto a quantidade de itens quanto os nomes que irão preencher a lista serão capturados de uma tabela.
Observe bem os campos da tabela utilizada:
O campo Descricao será usado para o preenchimento da lista. E a ordem desta lista será controlada pelo campo idx.
O primeiro get a ser disparado pela Dropdown é o getItemCount que irá capturar o número máximo de itens da lista e que corresponde ao número total de registros da tabela.
Observe a função fncGetItemCountDrop.
Sub fncGetItemCountDrop(control As IRibbonControl, ByRef count) 'Informa ao Dropdown, através da variável count, a quantidade de registros da
'tabela tblListaRelatorios, que será a quantidade máxima de linhas do Dropdown. count = DCount("*", "tblListaRelatorios") End Sub
E para que serve o argumento Control na função acima? É utilizado para o caso de termos mais de um controle Dropdown nas ribbons. Veja como fica a função para se controlar mais de um Dropdown:
Sub fncGetItemCountDrop(control As IRibbonControl, ByRef count) Select case control.id
case "dd1" 'Nome de um controle Dropdown
count = DCount("*", "NomeDatabela")
case "dd2" 'Nome de outro controle Dropdown
'Informa ao dropdown, através da variável count, a quantidade de
'registros da tabela tblListaRelatorios, que será a quantidade máxima
'de linhas do dropdown. count = DCount("*", "tblListaRelatorios")
end select End Sub
Agora que o controle Dropdown sabe da quantidade total de itens que terá a lista, irá capturar cada um dos itens (label), através do atributo getItemLabel.
Observe a função fncGetItemLabelDrop() que o get irá disparar para buscar os labels:
Sub fncGetItemlabelDrop(control As IRibbonControl, index As Integer, ByRef label)
'Informa ao Dropdown, através do argumento label, o nome do relatório armazenado
'na tabela tblListarelatorios.
'idx é um número exclusivo para cada relatório que deverá coincidir com a
'posição(index) no Dropdown.
label = DLookup("descricao", "tblComboDinamica", "idx =" & index)
End Sub
A nossa tabela exemplo tem 4 registros, que foi o número informado para o controle Dropdown. Este por sua vez irá passar pela função fncGetItemLabelDrop() 4 vezes. Isso mesmo! A função será chamada a quantidade de vezes que tiver o comprimento da lista! E cada vez que o controle passar pelo função, o argumento index será incrementado de 1 (iindex + 1). Começando sempre do zero(0).
Assim ficou fácil carregarmos o label correspondente, bastando sincronizar o argumento index com o campo idx da tabela.
Veja a lista carregada:
Para completar, vejamos o atributo onAction, que irá dar funcionalidade ao controle Dropdown. A função disparada por este atributo é a fncOnActiondrop().
Sub fncOnActionDrop(control As IRibbonControl,selectedId As String,selectedIndex As Integer)
Dim strNomeRelatorio as string
'o argumento selectedIndex traz o número do item que foi selecionado pelo usuário
strNomeRelatorio = DLookup("relatorio", "tblListaRelatorios", "idx =" & selectedIndex)
DoCmd.OpenReport strNomeRelatorio, acViewPreview
'Refaz a lista, limpando assim a caixa dropdown
objRibbon.InvalidateControl ("dd1")
End Sub
O nome do relatório é capturado pela função DLookup(). Veja que capturamos o nome do relatório que corresponde ao número selectedIndex e que deverá coincidir com o campo idx.
E quanto ao controle Combox ?
Tudo igualzinho, exceto pelo atributo de chamada onChange e que fará disparar a função fncOnChangeCbx:
Sub fncOnChangeCbx(control As IRibbonControl, strText As String)
dim strNomeRelatorio as string
'O argumento strText possui o valor digitado ou selecionado do combobox.
'Usamos este valor como filtragem da função Dlookup() para capturarmos da tabela
'o nome exato do relatório a ser aberto.
strNomeRelatorio = dlookup("relatório","tblListaRelatorios","descricao='" & strText & "'")
DoCmd.OpenReport strNomeRelatorio, acViewPreview
objRibbon.InvalidateControl ("cbx1")
End Sub
Este foi um caso bem simples, em que a tabela tinha um número de registros bem reduzido e com isso foi possível numerar manualmente o campo idx, que determina a ordem em que as informações do campo Descricao serão carregadas na lista do controle.
Já para uma tabela, com uma quantidade de registros grande e dinâmica, o uso do campo idx, obviamente, se torna inviável. A questão é resolvida de uma forma relativamente simples, que consiste em capturar os registros da tabela, ordená-los na forma desejada e armazená-los, temporariamente, na memória do computador, através do uso de uma variável do tipo Array. Esta passagem das informações para a memória é feita na função fncGetItemCountCbx, pois ela é disparada antes da função fncGetItemLabelCbx, que carrega os nomes para a lista.
Antes de prosseguirmos , entenda um pouco sobre variáveis do tipo Arrays.
As Arrays são variáveis que consistem em uma coleção de valores, chamados elementos do Array. Exemplo:
Dim strNomeCliente(20) as string
Esta instrução cria um Array de 21 elementos, cada um sendo uma variável de string convencional. Você cria 21 elementos porque o primeiro elemento de uma Array é o elemento zero (0). Iremos armazenar uma informação específica em cada um dos elementos. Exemplo:
strNomeCliente(0) = "Avelino Sampaio"
strNomeCliente(1) = "Pontocom Informática"
...
strNomeCliente(20) = "Maestro Tecnologia"
Temos aqui o nome Avelino Sampaio armazenado no elemento 0 e o nome Pontocom armazenado no elemento 1. Se quisermos capturar o nome Avelino Sampaio da variável, basta indicarmos o seu elemento. Exemplo :
label = strNomeCliente(0)
Podemos alterar a quantidade de elementos da variável dinamicamente , através da instrução ReDim. Isto nos permitirá determinar o número exato de elementos utilizados, que será igual ao número de registros utilizados:
reDim strNomeCliente(Número de registro da tabela) as string
Preste bem atenção no código utilizado, que irá capturar os nomes dos clientes para a variável strNomeCliente
Sub fncGetItemCountCbx(control As IRibbonControl, ByRef count)
Dim rs As DAO.Recordset
Dim strSql As String
Dim j As Long
' Para o combobox do formulário frmClientes, faremos aqui duas tarefas:
' 1ª - Informar a quantidade de itens da lista para o Combobox.
' 2ª - Armazenar na memória do computador, os nomes dos clientes, que irão preencher
' a lista do controle Combobox.
' Este conteúdo da memória será utilizado na função fncGetItemLabelCbx que será
' disparada logo a seguir.
'Monta uma consulta da tabela tblClientes para se obter os registros ordenados
'pelo nome do cliente.
strSql = "SELECT cli_nome FROM tblClientes ORDER BY cli_nome;"
'Abre a consulta
Set rs = CurrentDb.OpenRecordset(strSql)
rs.MoveLast: rs.MoveFirst
' Informa ao Combobox, através do argumento Count, a quantidade de itens que
' serão utilizados.
count = rs.RecordCount
'determina a quantidade de elementos que a variável irá armazenar
ReDim strNomeCliente(rs.RecordCount) As String
'Aqui é passado para variável strNomeCliente() o nome dos clientes, registro por registro.
j = 0
Do While Not rs.EOF
strNomeCliente(j) = rs!cli_Nome
j = j + 1
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
End Select
End Sub
Agora o Combobox sabe quantos nomes terá que carregar na lista e passará pela função fncGetItemlabelCbx a quantidade de vezes necessárias para carregar os nomes na lista. Veja como ficou super simples a função:
Sub fncGetItemlabelCbx(control As IRibbonControl,index As Integer, ByRef label) 'A combobox passará por esta função a quantidade de vezes igual ao número de
'registro informado na função acima. E cada vez que passar por aqui irá
'incrementando o argumento Index (index + 1) label = strNomeCliente(index) End Sub
Observe que estamos capturando os valores armazenados na variável strNomeCliente() e o argumento Index determina qual o valor a ser capturado. A captura está sendo realizada em seqüência. StrNomeCliente(0), strNomeCliente(1), strNomeCliente(2), ..., strNomeCliente(n). Os nomes se apresentarão em ordem alfabética, pois determinamos isto na ordenação da consulta.
Como usamos o valor selecionado da lista, para realizar a filtragem no formulário ?
A função fncOnChangeCbx, traz no argumento strText, o valor selecionado na lista. Com isto podemos usar o nome do cliente para realizar a filtragem. Acompanhe o código:
Sub fncOnChangeCbx(control As IRibbonControl, strText As String) 'Usamos o método filter para filtragem do formulário.
'strText traz o nome do cliente, selecionado pelo usuário.
Forms!frmClientes.Filter = "cli_nome='" & strText & "'" Forms!frmClientes.FilterOn = True
'Refaz e atualiza a lista do combobox para uma nova pesquisa. objRibbon.InvalidateControl ("cbx1") End Sub
Veja, o controle Combobox, usado para a filtragem do formulário:
Segue o exemplo para download , com os dois casos acima:
Sucesso nos seus estudos!
Artigos Relacionadoss
MontaRibbons v.4.0 - Assistente completo para criar ribbons no Access
Vídeo - Criando ribbons (parte 3) - Uso dos Gets
11 comentários madson braz 07/05/2022 16:49:07 Como ficaria duas comboboxes em cascata? onde o conteúdo da segunda é preenchido de acordo com o que for selecionado na primeira? é possível? Avelino Sampaio 04/06/2021 05:24:55 Ismael, tem um erro que cometi no projeto que está causando a falha. Como temos duas ribbons é necessário criarmos duas variáveis, para armazenamento em memória. Veja abaixo: Option Compare Database Public objRibbonCbx As IRibbonUI Public objRibbonCliente As IRibbonUI ----------------------------------------------------------------------------- Public Sub fncRibbonCbx(ribbon As IRibbonUI) On Error Resume Next Set objRibbonCbx = ribbon End Sub --------------------------------------------------------------------------- Public Sub fncRibbonCliente(ribbon As IRibbonUI) On Error Resume Next Set objRibbonCliente = ribbon End Sub Ao usar o invalidate, basta então especificar a variável correspondente: objRibbonCbx.InvalidateControl ("dd_Juntas") Baixe novamente o arquivo exemplo, que já está com as correções. Sucesso! Ismael 03/06/2021 22:37:29 Avelino, Usei o código conforme abaixo. O dropdown funcionou bem, mas após abrir o relatório, mesmo existindo a função invalidatecontrol, continua selecionado o item q foi aberto dentro do dropdown. '******************************************************************* ' funções para os controles DropDown '******************************************************************** Sub fncGetItemCountDrop(control As IRibbonControl, ByRef count) 'Informa ao dropDown, através do argumento count, a quantidade de registros da 'tabela tblListaRelatorios, que será a quantidade de linhas do dropDown. Select Case control.Id Case "dd_juntas" count = DCount("*", "Tbl_DropDown") End Select End Sub Sub fncGetItemlabelDrop(control As IRibbonControl, index As Integer, ByRef label) 'Informa ao dropdown, através do argumento label, o nome do relatório armazenado na tabela tblListarelatorios. 'idx é um número exclusivo para cada relatório que deverá coincidir com a posição(index) no dropdown. Select Case control.Id Case "dd_juntas" label = DLookup("descricao", "Tbl_DropDown", "idx =" & index) End Select End Sub Sub fncOnActionDrop(control As IRibbonControl, selectedId As String, selectedIndex As Integer) Dim strNomeRelatorio As String Select Case control.Id Case "dd_juntas" strNomeRelatorio = DLookup("relatorio", "Tbl_DropDown", "idx =" & selectedIndex) DoCmd.OpenReport strNomeRelatorio, acViewPreview DoCmd.Maximize 'Refaz a lista, limpando assim a caixa dropdown objRibbon.InvalidateControl ("dd_Juntas") End Select End Sub Ismael 03/06/2021 17:00:37 Avelino, Como fazer para mais de um dropbox, usando o mesmo código? Lelson Barbosa 17/04/2021 15:12:34 Avelino, Muito obrigado era mesmo disso que precisava. Avelino Sampaio 14/04/2021 09:29:33 Lelson, Veja se o exemplo abaixo atende: Sub fncOnChangeCbx(control As IRibbonControl, strText As String) select case strText case "RelatórioXyz" Docmd.OpenReport "NomeRelatório",,, "peça = '" & me!NomeDaPeça & "'" case else ' end select End Sub Sucesso! Lelson Barbosa 08/04/2021 10:24:07 Avelino, em um dos meu formulários usei uma combox, por exemplo categorias de peças, mas ai quando eu peço o relatorio de uma peça ele não reconhece o campo categoria e ai eu percebi que tinha de efetuar uma consulta e deu certo, o problema é que esta consulta mostra o relatório de todas as peças quando quero apenas de uma peça específica. Espero ter sido claro, agradeço desde já. Hephraim BF 20/01/2021 10:46:11 Muito bom! Avelino a minha situação é a seguinte: Quero utilizar as combos ou os dropdowns para selecionar valores que serão utilizados como critérios de filtragem dos dados dos meus forms e relatórios. Por exemplo: Vou utilizar 3 combos ou dropdowns. Escola: Tipo: Ano Irei preencher e depois clicar no botão visualizar ou imprimir para exibir os dados ou imprimi-los, tem como fazer isso? Johnny-Blumenau/SC 15/11/2020 19:17:03 e mais...a fartura de comentários no código só facilita o aprendizado do iniciante e a compreensão de novas rotinas para aqueles com maior conhecimento. Johnny-Blumenau/SC 15/11/2020 19:14:43 Beleza pura Avelino. Era o que eu precisava. Como havia lhe descrito anteriormente, implementei combo de pesquisa no form pois tive problemas para integra-la apartir da ribbon. Parabéns mais uma vez ! MARCIO MELO - RJ 15/11/2020 15:35:18 Melhor do que eu esperava, pois foi incrementado na própria ribbon, nos dando mais essa abrangência para enriquecer nossa tela... Tenho uns BD super simples que irei fazer utilidade desse recurso, deixando a tela mais limpa ainda... rsrs Forte abraço! obrigado por mais essa aula Sou mais Brasil! |