none
ListBox com mais de 10 colunas. RRS feed

  • 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
    segunda-feira, 12 de março de 2018 02:11

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

    sexta-feira, 16 de março de 2018 23:27
  • 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
    sábado, 17 de março de 2018 16:31
  • 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

    domingo, 18 de março de 2018 16:27
  • 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

    domingo, 18 de março de 2018 16:41
  • 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

    domingo, 18 de março de 2018 17:46
  • 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

    sexta-feira, 23 de março de 2018 14:19
  • 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
    sexta-feira, 23 de março de 2018 18:23
  • 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
    sexta-feira, 23 de março de 2018 18:47
  • Agradecido pelo código.
    Como você não declarou a variável dados, fiquei confuso de como a declarar.

    Instrutor de informática em gráficos avançados e dinâmicos, usando fórmulas e formulários

    domingo, 12 de agosto de 2018 13:03