Oh yeah! O ComboBox é muito mais versátil do que se pensa e neste vídeo, tento mostrar um pouco disso.
#VBA
#ComboBox
Código utilizado:
PrivateSub CommandButton1_Click()
'MsgBox ComboBox1.List(ComboBox1.ListIndex, 1)
MsgBox ComboBox1.Value
EndSubPrivateSub UserForm_Initialize()
Dim Estados(1 To 5, 1 To 2) AsString' L C
Estados(1, 1) = "AC"
Estados(2, 1) = "BA"
Estados(3, 1) = "RJ"
Estados(4, 1) = "SP"
Estados(5, 1) = "SC"' L C
Estados(1, 2) = "Acre"
Estados(2, 2) = "Bahia"
Estados(3, 2) = "Rio de Janeiro"
Estados(4, 2) = "São Paulo"
Estados(5, 2) = "Santa Catarina"
ComboBox1.List = Estados
EndSub
Private Sub CommandButton1_Click()
'MsgBox ComboBox1.List(ComboBox1.ListIndex, 1)
MsgBox ComboBox1.Value
End Sub
Private Sub UserForm_Initialize()
Dim Estados(1 To 5, 1 To 2) As String
' L C
Estados(1, 1) = "AC"
Estados(2, 1) = "BA"
Estados(3, 1) = "RJ"
Estados(4, 1) = "SP"
Estados(5, 1) = "SC"
' L C
Estados(1, 2) = "Acre"
Estados(2, 2) = "Bahia"
Estados(3, 2) = "Rio de Janeiro"
Estados(4, 2) = "São Paulo"
Estados(5, 2) = "Santa Catarina"
ComboBox1.List = Estados
End Sub
Estou trazendo mais um modelo, utilizando os velhos controles ComboBox e ListBox.
Dessa vez, criei uma estrutura que nos possibilita pegar os dados de um desses dois controles e enviar para outro, conforme pode ser visto na imagem abaixo.
Outra dúvida muito comum na comunidade VBA. ComboBox Encadeados quer dizer que em dois ou mais ComboBoxes, ao atualizar os dados de um ComboBox, os outros são afetados. Isso é útil quando os dados entre eles estão relacionados, o que quase sempre é verdade.
No exemplo deste post, a relação dos dados será baseada na tradicional Produto e Categoria. A pasta de trabalho deve estar disposta em duas planilhas da seguinte forma:
É preciso que os dados da coluna NomeDaCategoria na planilha de Produtos estejam compatíveis com os da planlha Categorias, ou o filtro não funcionará.
Após isso, crie um UserForm com a seguinte “cara”:
Para que o código funcione sem precisar alterar nada, nomeie os campos da seguinte forma:
Em seguida, adicione o seguinte código o formulário:
PrivateSub ComboBoxCategorias_Change()
Call CarregaProdutos(Me.ComboBoxCategorias.List(Me.ComboBoxCategorias.ListIndex))
EndSubPrivateSub UserForm_Initialize()
Call CarregaCategorias
EndSubPrivateSub CarregaCategorias()
Dim linha AsInteger, coluna AsInteger
linha = 2
coluna = 1
Me.ComboBoxCategorias.Clear
With Sheets("Categorias")
DoWhileNot IsEmpty(.Cells(linha, coluna))
Me.ComboBoxCategorias.AddItem .Cells(linha, coluna).Value
linha = linha + 1
LoopEndWithEndSubPrivateSub CarregaProdutos(ByVal Categoria AsString)
Dim linha AsInteger, colunaProduto AsInteger, colunaCategoria AsInteger
linha = 2
colunaProduto = 1
colunaCategoria = 2
Me.ComboBoxProdutos.Clear
With Sheets("Produtos")
DoWhileNot IsEmpty(.Cells(linha, colunaProduto))
If .Cells(linha, colunaCategoria).Value = Categoria Then
Me.ComboBoxProdutos.AddItem .Cells(linha, colunaProduto).Value
EndIf
linha = linha + 1
LoopEndWithEndSub
Private Sub ComboBoxCategorias_Change()
Call CarregaProdutos(Me.ComboBoxCategorias.List(Me.ComboBoxCategorias.ListIndex))
End Sub
Private Sub UserForm_Initialize()
Call CarregaCategorias
End Sub
Private Sub CarregaCategorias()
Dim linha As Integer, coluna As Integer
linha = 2
coluna = 1
Me.ComboBoxCategorias.Clear
With Sheets("Categorias")
Do While Not IsEmpty(.Cells(linha, coluna))
Me.ComboBoxCategorias.AddItem .Cells(linha, coluna).Value
linha = linha + 1
Loop
End With
End Sub
Private Sub CarregaProdutos(ByVal Categoria As String)
Dim linha As Integer, colunaProduto As Integer, colunaCategoria As Integer
linha = 2
colunaProduto = 1
colunaCategoria = 2
Me.ComboBoxProdutos.Clear
With Sheets("Produtos")
Do While Not IsEmpty(.Cells(linha, colunaProduto))
If .Cells(linha, colunaCategoria).Value = Categoria Then
Me.ComboBoxProdutos.AddItem .Cells(linha, colunaProduto).Value
End If
linha = linha + 1
Loop
End With
End Sub
Execute o formulário e selecione uma categoria no primeiro ComboBox. Veja que no ComboBox de produtos são mostrados apenas aqueles que pertecem à categoria selecionada:
Obviamente existem várias formas de fazer o mesmo trabalho. Invente a sua, ou, faça o download do exemplo no link abaixo:
😉
Uma funcionalidade não nativa do VBA é a ordenação, seja lá ela qual for.
Ela comumente é necessária em Arrays e controles de lista, como ListBox e ComboBox. Métodos de ordenação existem aos montes. Neste caso, usarei o QuickSort, escrito pelo camarada Frederik do http://users.skynet.be/am044448/Programmeren/. O código abaixo faz a ordenação de um Array passado por parâmetro.
PrivateSub QuickSort(strArray() AsString, intBottom AsInteger, intTop AsInteger)
Dim strPivot AsString, strTemp AsStringDim intBottomTemp AsInteger, intTopTemp AsInteger
intBottomTemp = intBottom
intTopTemp = intTop
strPivot = strArray((intBottom + intTop) \ 2)
While (intBottomTemp <= intTopTemp)
While (strArray(intBottomTemp) < strPivot And intBottomTemp < intTop)
intBottomTemp = intBottomTemp + 1
Wend
While (strPivot < strArray(intTopTemp) And intTopTemp > intBottom)
intTopTemp = intTopTemp - 1
Wend
If intBottomTemp < intTopTemp Then
strTemp = strArray(intBottomTemp)
strArray(intBottomTemp) = strArray(intTopTemp)
strArray(intTopTemp) = strTemp
EndIfIf intBottomTemp <= intTopTemp Then
intBottomTemp = intBottomTemp + 1
intTopTemp = intTopTemp - 1
EndIf
Wend
'faz a chamada recursiva a si própria até que lista esteja preenchidaIf (intBottom < intTopTemp) Then QuickSort strArray, intBottom, intTopTemp
If (intBottomTemp < intTop) Then QuickSort strArray, intBottomTemp, intTop
EndSub
Private Sub QuickSort(strArray() As String, intBottom As Integer, intTop As Integer)
Dim strPivot As String, strTemp As String
Dim intBottomTemp As Integer, intTopTemp As Integer
intBottomTemp = intBottom
intTopTemp = intTop
strPivot = strArray((intBottom + intTop) \ 2)
While (intBottomTemp <= intTopTemp)
While (strArray(intBottomTemp) < strPivot And intBottomTemp < intTop)
intBottomTemp = intBottomTemp + 1
Wend
While (strPivot < strArray(intTopTemp) And intTopTemp > intBottom)
intTopTemp = intTopTemp - 1
Wend
If intBottomTemp < intTopTemp Then
strTemp = strArray(intBottomTemp)
strArray(intBottomTemp) = strArray(intTopTemp)
strArray(intTopTemp) = strTemp
End If
If intBottomTemp <= intTopTemp Then
intBottomTemp = intBottomTemp + 1
intTopTemp = intTopTemp - 1
End If
Wend
'faz a chamada recursiva a si própria até que lista esteja preenchida
If (intBottom < intTopTemp) Then QuickSort strArray, intBottom, intTopTemp
If (intBottomTemp < intTop) Then QuickSort strArray, intBottomTemp, intTop
End Sub
A função não tem um retorno, mas como um array passado por parâmetro para um função é sempre por referência, após a execução desta seu Array estará ordenado em ordem crescente.
Para testar o funcionamento da função, crie um userForm no VBA. Coloque nele um ListBox e um CommandButton, sem se preocupar com alterar seus nomes. Coloque no código do Form a função QuickSort mostrada acima, mais o código abaixo.
PrivateSub CommandButton1_Click()
Dim MyArray(12) AsStringDim i AsLong'caso não haja itens na lista, não é necessário fazer ordenaçãoIf ListBox1.ListCount <= 1 ThenExitSub'alimenta o arrayFor i = 0 To ListBox1.ListCount - 1
MyArray(i) = ListBox1.List(i, 0)
Next i
'ordena o array
QuickSort MyArray, LBound(MyArray), UBound(MyArray)
'limpa o listbox
ListBox1.Clear
'usa o array ordenado para preencher o listboxFor i = 1 ToUBound(MyArray)
ListBox1.AddItem MyArray(i)
Next i
EndSubPrivateSub UserForm_Initialize()
'preenche o listbox com os meses do anoFor i = 1 To 12
ListBox1.AddItem MonthName(i, False)
NextEndSub
Private Sub CommandButton1_Click()
Dim MyArray(12) As String
Dim i As Long
'caso não haja itens na lista, não é necessário fazer ordenação
If ListBox1.ListCount <= 1 Then Exit Sub
'alimenta o array
For i = 0 To ListBox1.ListCount - 1
MyArray(i) = ListBox1.List(i, 0)
Next i
'ordena o array
QuickSort MyArray, LBound(MyArray), UBound(MyArray)
'limpa o listbox
ListBox1.Clear
'usa o array ordenado para preencher o listbox
For i = 1 To UBound(MyArray)
ListBox1.AddItem MyArray(i)
Next i
End Sub
Private Sub UserForm_Initialize()
'preenche o listbox com os meses do ano
For i = 1 To 12
ListBox1.AddItem MonthName(i, False)
Next
End Sub
Ao executar o form da primeira vez, pode-se ver que o ListBox é preenchido com os meses do ano através da função MontName.
O código colocado no evento click do botão cria um array de string de tamanho 12, preenche o array com a lista de valores presente no listbox, ordena o array através da função QuickSort e re-preenche o listbox.
Uma forma bem simples de fazer ordenação em listas sempre precisar ficar re-pensando no código sempre que precisar.