Inquiridor
ListBox com mais de 10 colunas.

Discussão Geral
-
Quando queremos popular uma ListBox com apenas um item e mais de 10 colunas recebemos um Erro em tempo de execução '380'.
ListBox1.AddItem 1 ListBox1.List(0, 1) = 2 ListBox1.List(0, 2) = 3 ListBox1.List(0, 3) = 4 ListBox1.List(0, 4) = 5 ListBox1.List(0, 5) = 6 ListBox1.List(0, 6) = 7 ListBox1.List(0, 7) = 8 ListBox1.List(0, 8) = 9 ListBox1.List(0, 9) = 10 'A partir daqui ocorrera o erro ListBox1.List(0, 10) = 11 ListBox1.List(0, 11) = 12 ListBox1.List(0, 12) = 13
Algumas pessoas utilizam a propriedade "RowSource" para contornar o erro, mas você terá que fazer referência a um intervalo de uma planilha.
ListBox1.RowSource = "A1:M1"
Caso você não queira utilizar um intervalo de uma planilha, com duas linhas de código você contorna esse problema.
Utilizando o mesmo código do inicio.
Antes de popular a ListBox faça referência a um intervalo de qualquer planilha que contenha mais de 10 colunas e logo limpe a ListiBox. Após fazer essa referência você não terá mais problema para popular a ListBox com 1 item e mais de 10 colunas.
ListBox1.List = Range("A1:AZ100").Value ListBox1.Clear ListBox1.AddItem 1 ListBox1.List(0, 1) = 2 ListBox1.List(0, 2) = 3 ListBox1.List(0, 3) = 4 ListBox1.List(0, 4) = 5 ListBox1.List(0, 5) = 6 ListBox1.List(0, 6) = 7 ListBox1.List(0, 7) = 8 ListBox1.List(0, 8) = 9 ListBox1.List(0, 9) = 10 ListBox1.List(0, 10) = 11 'Não ocorrera mais o erro ListBox1.List(0, 11) = 12 ListBox1.List(0, 12) = 13
Espero ter ajudado.
Renato MDSP
- Editado Renato MDSP terça-feira, 13 de março de 2018 11:53
Todas as Respostas
-
Renato boa noite.
Óbviamente que daria muito jeito que os Listbox permitissem mais que 10 colunas e numa das minhas pequenas apicações de VBA-Excel, para contornar esse obstáculo, concateno 2 colunas da planilha numa coluna do Listbox.
Habitualmente, o Listbox é útil para listar varios itens e é aí que ele é pratico. Permite exibir uma grande quantidade de itens num só objeto.
Agora, será que percebi bem quando você diz: "Quando queremos popular uma ListBox com apenas um item e mais de 10 colunas ... " ?
Você quer dizer popular um Listbox com apenas 1 linha para apresentação de dados?
Se sim qual o lado prático deste Listbox?
M_A_S_L
-
Já agora, como estamos num tópico de discussão, numa das minhas pesquisas sobre este assunto, encontrei esta rotina.
Ainda não a analisei, porque teria que alterar demasiadas coisas na minha aplicação, mas aqui fica a rotina para quem a quiser analisar.
Com os devidos créditos para Tomás Vasquez,
https://www.tomasvasquez.com.br/blog/microsoft-office/excel/vba-preenchendo-um-listbox-com-mais-de-10-colunas.
Private Sub UserForm_Initialize() Dim arrayItems() With Planilha1 ReDim arrayItems(1 To .UsedRange.Rows.Count, 1 To .UsedRange.Columns.Count) Me.ListBox1.ColumnCount = .UsedRange.Columns.Count For linha = 1 To .UsedRange.Rows.Count Me.ListBox1.AddItem For coluna = 1 To .UsedRange.Columns.Count arrayItems(linha, coluna) = .Cells(linha, coluna).Value Next coluna Next linha Me.ListBox1.List = arrayItems() End With End Sub
M_A_S_L
- Editado M_A_S_L sábado, 17 de março de 2018 16:32
-
Segue um exemplo de como eu utilizo.
Eu não costumo preencher uma listbox utilizando intervalos de planilha. Quando se trabalha com muitos dados a melhor coisa a se fazer é utilizar uma array para preencher a listbox.
O código a seguir preenche uma listbox e uma combobox(auxilio) com uma array(intervalo de planilha) e filtra os dados pesquisados em uma textbox em tempo real.
Eu utilizo uma combobox como bando de dados no lugar de uma planilha e uma array para devolver o resultado e preencher a listbox com os dados pesquisados.
Quando a pesquisa retorna apenas um item a array passa a ser Bidimensional. Ai que entra o motivo da discussão.
Nesse código, quando array retornar um item após a pesquisa, não ha necessidade de fazer a referência a uma planilha antes de utilizar o additem porque no evento Initialize do Userform já contém referência a um intervalo de uma planilha, mas quando eu preencho uma listbox com um resultado de uma query de um banco de dados, a referência a um intervalo de planilha não existe. Ocorrerá um erro na hora que eu fizer uma pesquisa, onde o retorno será apenas um item.
Private Sub UserForm_Initialize() dados = sBanco.Cells(1).CurrentRegion.Offset(1).Resize(sBanco.Cells(1).CurrentRegion.Rows.Count - 1).Value With UserForm1 .ListBox1.ColumnCount = UBound(dados, 2) .ListBox1.List = dados .ComboBox1.List = dados End With End Sub Private Sub TextBox1_Change() Dim textoDigitado As String lista_efetivo = Me.ComboBox1.List indice = 0 textoDigitado = Me.TextBox1 ReDim n(UBound(lista_efetivo), 11) For i = 0 To UBound(lista_efetivo) If InStr(1, UCase(lista_efetivo(i, 1)), UCase(textoDigitado)) <> 0 Then n(indice, 0) = lista_efetivo(i, 0) n(indice, 1) = lista_efetivo(i, 1) n(indice, 2) = lista_efetivo(i, 2) n(indice, 3) = lista_efetivo(i, 3) n(indice, 4) = lista_efetivo(i, 4) n(indice, 5) = lista_efetivo(i, 5) n(indice, 6) = lista_efetivo(i, 6) n(indice, 7) = lista_efetivo(i, 7) n(indice, 8) = lista_efetivo(i, 8) n(indice, 9) = lista_efetivo(i, 9) n(indice, 10) = lista_efetivo(i, 10) n(indice, 11) = lista_efetivo(i, 11) indice = indice + 1 End If Next If indice = 0 Then Me.ListBox1.Clear Exit Sub End If For lin = 0 To UBound(n) For col = 0 To UBound(n, 2) If IsNull(n(lin, col)) Then n(lin, col) = "" End If Next Next n = Application.Transpose(n) ReDim Preserve n(1 To 12, 1 To indice) n = Application.Transpose(n) On Error GoTo pula If UBound(n, 2) Then Me.ListBox1.Clear Me.ListBox1.List = n Exit Sub pula: Me.ListBox1.Clear Me.ListBox1.AddItem n(1) Me.ListBox1.List(0, 1) = n(2) Me.ListBox1.List(0, 2) = n(3) Me.ListBox1.List(0, 3) = n(4) Me.ListBox1.List(0, 4) = n(5) Me.ListBox1.List(0, 5) = n(6) Me.ListBox1.List(0, 6) = n(7) Me.ListBox1.List(0, 7) = n(8) Me.ListBox1.List(0, 8) = n(9) Me.ListBox1.List(0, 9) = n(10) Me.ListBox1.List(0, 10) = n(11) Me.ListBox1.List(0, 11) = n(12) End If End Sub
Renato MDSP
-
Eu tenho uma planilha com 20 mil linhas e 12 colunas.
Esse código demorou 27 segundo para preencher minha listbox.
Esse código faz o mesmo e demorou 0.11 segundos.
Não adianta preencher uma listbox com array sendo que para preencher a array é utilizado um loop em uma planilha. O resultado será o mesmo. O problema está no loop em planilha.
Private Sub UserForm_Initialize() Dim tempo As Double tempo = Timer dados = sBanco.Range("A1").CurrentRegion.Offset(1).Resize(sBanco.Range("A1").CurrentRegion.Rows.Count - 1).Value Me.ListBox1.ColumnCount = UBound(dados) Me.ListBox1.List = dados Debug.Print Timer - tempo End Sub
Renato MDSP
-
Renato,
podes ter toda a razão e eu não tenho conhecimentos nem capacidade para construir e até interpretar o teu código.
Apenas questionei a apresentação de dados em 1 linha só, pois queria entender o sentido prático dessa situação.
É óbio que o Listbox pode devolver um só resultado numa pesquisa, mas quando você diz:
"Quando queremos popular uma ListBox com apenas um item e mais de 10 colunas recebemos um Erro em tempo de execução '380'."
não entendi que se referia à devolução de resultados.
Para quem é apenas curioso e não trabalha habitualmente com folhas que possuam mais do que 1000 ou 1500 linhas, é óbvio que os ciclos são a forma preferencial de preencher o Listbox.
Para quem trabalha com folhas de 12000 linhas e mais, é óbvio que aí a forma de encarar o VBA se altera e passam a utilizar-se Coleções, Dicionários e outros objetos inseridos no Excell avançado, coisa que para mim ... é Grego.
Mas vou analisar o seu código e tentar percebê-lo pois nunca se sabe quando poderá ser útil. No entanto, (no caso do seu código), quando o Listbox tem que reagir ao Click também continua com a mesma rapidez?
Um abraço.
M_A_S_L
-
Pode questionar a vontade. O fórum foi criado para isso. O código foi um exemplo de como eu utilizo atualmente. Deve ter outras utilidades para outras pessoas.
Durantes minhas pesquisas na internet eu encontrei pessoas dizendo que não é possível preencher uma listbox com mais de 10 colunas. Fiquei com isso na cabeça.
Outro exemplo
Muitas pessoas usavam esse código para preencher uma listbox. No exemplos que eu encontrava a quantidade de coluna era sempre menor que 10, por isso sempre funcionava.
Esse código não trara nenhum erro por conta das linhas ListBox1.List = Range("A1:AA30").value e ListBox1.Clear. Se comentar essas linhas ocorrera um erro.
Private Sub UserForm_Initialize() ListBox1.List = Range("A1:AA30").Value ListBox1.Clear lin = 0 For Each i In Planilha1.Range("A1:A12") ListBox1.AddItem i.Offset(0, 1).Value ListBox1.List(lin, 1) = i.Offset(0, 2).Value ListBox1.List(lin, 2) = i.Offset(0, 3).Value ListBox1.List(lin, 3) = i.Offset(0, 4).Value ListBox1.List(lin, 4) = i.Offset(0, 5).Value ListBox1.List(lin, 5) = i.Offset(0, 6).Value ListBox1.List(lin, 6) = i.Offset(0, 7).Value ListBox1.List(lin, 7) = i.Offset(0, 8).Value ListBox1.List(lin, 8) = i.Offset(0, 9).Value ListBox1.List(lin, 9) = i.Offset(0, 10).Value ListBox1.List(lin, 10) = i.Offset(0, 11).Value ListBox1.List(lin, 11) = i.Offset(0, 12).Value lin = lin + 1 Next End Sub
Utilizar apenas array já ajuda muito. Loop em uma array é muito mais rápido que em uma planilha. A forma de escrever o loop é praticamente a mesma. Só trocar o objeto planilha pela array.
Obrigado pelos questionamentos M_A_S_L. Isso só fortalece o fórum.
Renato MDSP
-
Pode questionar a vontade. O fórum foi criado para isso. O código foi um exemplo de como eu utilizo atualmente. Deve ter outras utilidades para outras pessoas.
...
Utilizar apenas array já ajuda muito. Loop em uma array é muito mais rápido que em uma planilha. A forma de escrever o loop é praticamente a mesma. Só trocar o objeto planilha pela array.
Obrigado pelos questionamentos M_A_S_L. Isso só fortalece o fórum.
Renato MDSP
Renato.
Não tem que agradecer. Quem tem a possibilidade de aprender com os conhecimentos dos outros é que deve agradecer.
Infelizmente, grande parte dos utilizadores do forum, pretendem apenas que se lhes faça o trabalho. O meu caso, sem me achar melhor ou pior que os outros, só coloco questões quando esgotei todas as possibilidades. E há uma coisa que comigo nunca fica para trás, o agradecimento pela ajuda recebida.
O principal problema? Não nasci na era da informática e quando surgiu o primeiro ZX Spectrum já eu era adulto. Portanto, a minha formação informática é literalmente ZERO.
Tudo o que sei, (que não é muito), aprendi sozinho pesquisando e obtendo ajudas daí a minha dificuldade em compreender certas coisas.
Assim como muitas outras coisas, um array, ainda é segredo para mim, mas está na minha lista de pesquisas.
Como a capacidade de raciocínio e a vontade de aprender coisas novas estão cá, conforme a minha disponibilidade que não é muita, vou mais tarde ou mais cedo dedicar algum tempo a esse assunto, porque já me vi confrontado com o problema do tempo exagerado no carregamento de um Listbox, chegando mesmo a abrir aqui um tópico para tentar resolver isso. Porém, a ajuda não chegou.
Gradualmente e à medida das minhas necessidades, vou pesquisando, analiso os códigos, tento entendê-los e finalmente aplico-os.
Fazem falta no entanto neste tópico opiniões e pontos de vista de outros entendidos, bem como outras formas de apresentar linhas de código o que de certa forma, facilita o entendimento de certas matérias a leigos em VBA como é o meu caso.
Cumprimentos
M_A_S_L
- Editado M_A_S_L sexta-feira, 23 de março de 2018 18:25
-
A microsoft não facilitou a nossa vida ao trabalhar com array igual acontece em outras linguagens. É normal não optar por ela. Em outras linguagens a array possui propriedades e métodos. No VBA temos que pegar funções ou métodos emprestados de outros objetos e isso dificulta o entendimento.
Você não terá problemas em entender uma array. Você só precisa encontrar uma explicação que faça sentido pra você. Eu demorei um tempo para entender.
Qualquer dúvida estou a disposição. renatomdsp@gmail.com
Renato MDSP
- Editado Renato MDSP sexta-feira, 23 de março de 2018 18:48
-