Notifications
Clear all

Exercício de Array & dúvida de funcionamento do código.

14 Posts
5 Usuários
0 Reactions
2,677 Visualizações
(@finaljustice)
Posts: 91
Estimable Member
Topic starter
 

Bom dia,

Estou estudando e treinando declarar os objetos e programar de modo geral sem usar termos por exemplo "Activecell" "Select" e outros que embora sejam mais fáceis de usar e programar no começo, podem complicar a vida quando se quer criar uma userform em que o workbook fica escondido e somente o userform fica aberto.

Bom este exemplo que estou fazendo é bem simples e é só para testar conceito mesmo. (Para os que tiverem estudando / com dúvida de como fazer as seguintes operações estou deixando o código explicadinho).

O que gostaria de fazer:
1) Determinar o tamanho da variável array - OK
2) Redimensionar a variável - OK
3) Popular (puxar as informações) a variável array - incompleto
4) Popular um listbox com multiplas colunas na userform1 com as informações da array. OK

Consegui concluir isto até o item 3, porém incompleto.
Para os itens 1 & 2 embora tenha conseguido fazer, ele não está funcionando da maneira que eu esperava. Por exemplo, eu fiz o código pensando que eu tinha declarado os objetos etc de modo que não importasse qual sheet estivesse ativa, ele funcionaria. Não é o caso, pois se eu tentar rodar com a Sheet2 ativa, o erro "Erro de definição de aplicativo ou de definição de objeto" aparece, justamente o que eu achei que estava evitando.

Para o item 3, como vi que a parte 1 & 2 não estava funcionando como eu decidi fazer esse post, porém do jeito que dexei percebi que na verdade do jeito que declarei a variável array, ele começa no (0,0) como faço para (é necessário/ boa prática?) que a variável comece na posição (1,1)?

Para o item 4, percebi que o preenchimento está sempre "Comendo" uma coluna pois o array começa no (0,0) então acho que devo realmente começando na posição (1,1). Por exemplo, se tiver dados, da coluna A até M na userform só aparece A até a L.

Obrigado pela atenção, e ajuda.

Segue o código e o arquivo.

Att,
Luis

Sub ArrayTeste()
'declarar as variáveis
Dim Mylist() As Variant
Dim nrow As Integer
Dim ncol As Integer
Dim i As Integer, j As Integer
Dim rng As Range
Dim ws As Worksheet

'para uma variável array que não se sabe o tamanho, primeiro temos que identificar numero de colunas & linhas (ncol & nrow)
Set ws = ThisWorkbook.Sheets(1) 'coloquei aqui, pois achava que eu teria que usar tipo "ws.rng.Column" mas não da certo.
With ThisWorkbook.Sheets(1)
 Set rng = .Range("A1") 'Acho que é necessário uma referência para offset, deslocamento das células na montagem do array.
 nrow = .Range(Cells(1048576, rng.Column).End(xlUp), Cells(rng.Row, 256).End(xlToLeft)).Rows.Count
 ncol = .Range(Cells(1048576, rng.Column).End(xlUp), Cells(rng.Row, 256).End(xlToLeft)).Columns.Count
End With
'agora que se sabe o tamanho que terá seu array, redimenciona a variável.
ReDim Mylist(nrow, ncol)

'populando a variável array
For i = 1 To nrow
    For j = 1 To ncol
        Mylist(i, j) = rng.Offset(i - 1, j - 1) 'movendo pelas colunas
    Next j 'trocando de linha
Next i

'popular a userform com as informações da variável array.
With UserForm1
    .ListBox1.ColumnCount = ncol 'determinar o numero de colunas
    .ListBox1.ColumnWidths = 75 'determinar largura das colunas
    .ListBox1.List = Mylist 'popular as informações pra dentro da listbox
    .Show 'mostrar a userform.
End With

End Sub
 
Postado : 29/01/2015 10:31 am
(@gtsalikis)
Posts: 2373
Noble Member
 

Não olhei com calma, mas creio que...

Essa linha:
Mylist(i, j) = rng.Offset(i - 1, j - 1) 'movendo pelas colunas

Deveria ser assim:
Mylist(i, j) = rng.Offset(i - 1, j - 1).value 'movendo pelas colunas

 
Postado : 29/01/2015 10:34 am
(@finaljustice)
Posts: 91
Estimable Member
Topic starter
 

Não olhei com calma, mas creio que...

Essa linha:
Mylist(i, j) = rng.Offset(i - 1, j - 1) 'movendo pelas colunas

Deveria ser assim:
Mylist(i, j) = rng.Offset(i - 1, j - 1).value 'movendo pelas colunas

Obrigado por responder.

Está populando, o problema é que a variável array começa no (0,0), ai na hora de popular o listbox ele "come" uma coluna pq são 8 colunas mas como a array começa no 0 teria que ser 9 colunas, bem como o problema de se tiver na sheet 2 ocorre o erro.

Att,
luis

 
Postado : 29/01/2015 10:38 am
(@gtsalikis)
Posts: 2373
Noble Member
 

Então vc queria isso:

ReDim Mylist(1 To nrow, 1 To ncol)

 
Postado : 29/01/2015 10:42 am
(@fernandofernandes)
Posts: 43750
Illustrious Member
 

Para esse erro experimente assim:

Set ws = ThisWorkbook.Sheets(1) 'coloquei aqui, pois achava que eu teria que usar tipo "ws.rng.Column" mas não da certo.
With ws 
 Set rng = .Range("A1") 'Acho que é necessário uma referência para offset, deslocamento das células na montagem do array.
 nrow = .Range(.Cells(1048576, rng.Column).End(xlUp), .Cells(rng.Row, 256).End(xlToLeft)).Rows.Count
 ncol = .Range(.Cells(1048576, rng.Column).End(xlUp), .Cells(rng.Row, 256).End(xlToLeft)).Columns.Count
End With
'agora que se sabe o tamanho que terá seu array, redimenciona a variável.
ReDim Mylist(1 To nrow, 1 To ncol)
 
Postado : 29/01/2015 10:52 am
(@finaljustice)
Posts: 91
Estimable Member
Topic starter
 

Para esse erro experimente assim:

Set ws = ThisWorkbook.Sheets(1) 'coloquei aqui, pois achava que eu teria que usar tipo "ws.rng.Column" mas não da certo.
With ws 
 Set rng = .Range("A1") 'Acho que é necessário uma referência para offset, deslocamento das células na montagem do array.
 nrow = .Range(.Cells(1048576, rng.Column).End(xlUp), .Cells(rng.Row, 256).End(xlToLeft)).Rows.Count
 ncol = .Range(.Cells(1048576, rng.Column).End(xlUp), .Cells(rng.Row, 256).End(xlToLeft)).Columns.Count
End With
'agora que se sabe o tamanho que terá seu array, redimenciona a variável.
ReDim Mylist(1 To nrow, 1 To ncol)

Obrigado por responder!

Sim como o gtsalikis havia comentado, isso funcionou para corrigir a minha variável array.

Porém o que está errado para que ocorra um erro quando não estou na sheet 1, pois meu código só funciona quando estou com a sheet1 ativa, e pensei que da maneira que eu havia feito, ela funcionaria com qualquer sheet ativa.

Att,
Luis

 
Postado : 29/01/2015 12:22 pm
(@wagner-morel-vidal-nobre)
Posts: 4063
Famed Member
 

finaljustice,

Amigos,

Boa Tarde!

Deixa eu meter minha colher nessa sopa também!

Bom... você deve inserir seu código na procedure Private Sub Workbook_SheetActivate(ByVal Sh As Object) do seu Workbook. Desse modo, poderá executá-lo, independentemente de qual PLAN esteja ativa. Veja o exemplo no arquivo abaixo. Sempre que você selecionar uma plan, automaticamente será mostrado o valor que está na linha 2 e na coluna 5 da Plan que estiver selecionada.

 
Postado : 29/01/2015 1:34 pm
(@finaljustice)
Posts: 91
Estimable Member
Topic starter
 

finaljustice,

Amigos,

Boa Tarde!

Deixa eu meter minha colher nessa sopa também!

Bom... você deve inserir seu código na procedure Private Sub Workbook_SheetActivate(ByVal Sh As Object) do seu Workbook. Desse modo, poderá executá-lo, independentemente de qual PLAN esteja ativa. Veja o exemplo no arquivo abaixo. Sempre que você selecionar uma plan, automaticamente será mostrado o valor que está na linha 2 e na coluna 5 da Plan que estiver selecionada.

Boa tarde Wagner,
Obrigado por responder. Então essa procedimento que você exemplificou pelo o que eu entendi, ele roda a macro quando se muda de sheet correto?

O que eu estou tentando fazer é com que meu código rode independente de qual sheet esteja ativa, ele irá puxar as infos e rodar da sheet correta. Quero fazer isso porque no final quero esconder o workbook e só abrir a userform e sei que isso pode gerar erros se não está programado da maneira correta. Da maneira que eu escrevi, eu achei que eu não teria esse problema pois no código estava determiando:

With ThisWorkbook.Sheets(1)


End with

Então pelo o que eu tinha entendido, eu havia determinado que a informação deve sair da SHEET(1) independente da sheet ativa.

Att,
Luis

 
Postado : 29/01/2015 1:58 pm
(@fernandofernandes)
Posts: 43750
Illustrious Member
 

Luis, da maneira que propus, não foi apenas a modificação do array. Assim mesmo que estiver na sheet 2 ou tres irá carregar sem erro os dados da sheet 1.
Não era isso??

 
Postado : 29/01/2015 2:23 pm
(@finaljustice)
Posts: 91
Estimable Member
Topic starter
 

Luis, da maneira que propus, não foi apenas a modificação do array. Assim mesmo que estiver na sheet 2 ou tres irá carregar sem erro os dados da sheet 1.
Não era isso??

Olá Reinaldo, pelo oq percebi no seu código houve a mudança somente na linha do WITH e no ReDim correto?

Set ws = ThisWorkbook.Sheets(1) 'coloquei aqui, pois achava que eu teria que usar tipo "ws.rng.Column" mas não da certo.
With ws
 Set rng = .Range("A1") 'Acho que é necessário uma referência para offset, deslocamento das células na montagem do array.
 nrow = .Range(Cells(1048576, rng.Column).End(xlUp), Cells(rng.Row, 256).End(xlToLeft)).Rows.Count
 ncol = .Range(Cells(1048576, rng.Column).End(xlUp), Cells(rng.Row, 256).End(xlToLeft)).Columns.Count
End With
'agora que se sabe o tamanho que terá seu array, redimenciona a variável.
ReDim Mylist(1 To nrow, 1 To ncol)

Antes estava assim:

Set ws = ThisWorkbook.Sheets(1) 'coloquei aqui, pois achava que eu teria que usar tipo "ws.rng.Column" mas não da certo.
With ThisWorkbook.Sheets(1)
Set rng = .Range("A1") 'Acho que é necessário uma referência para offset, deslocamento das células na montagem do array.
nrow = .Range(Cells(1048576, rng.Column).End(xlUp), Cells(rng.Row, 256).End(xlToLeft)).Rows.Count
ncol = .Range(Cells(1048576, rng.Column).End(xlUp), Cells(rng.Row, 256).End(xlToLeft)).Columns.Count
End With
'agora que se sabe o tamanho que terá seu array, redimenciona a variável.
ReDim Mylist(nrow, ncol)

O ajuste no Array ficou perfeito, agora mesmo colocando o ws no with, não está funcionando se a sheet 2 estiver ativa e eu tentar rodar a macro.

Obrigado.
Luis

 
Postado : 29/01/2015 2:46 pm
(@finaljustice)
Posts: 91
Estimable Member
Topic starter
 

Luis, da maneira que propus, não foi apenas a modificação do array. Assim mesmo que estiver na sheet 2 ou tres irá carregar sem erro os dados da sheet 1.
Não era isso??

Desculpe Reinaldo,

Você estava correto, ficou faltando o "." antes do CELLS, agora está funcionando não importa qual sheet eu esteja!
Muito obrigado!

Para finalizar, como devo fazer se eu quiser formatar as informações inseridas na listbox? Por exemplo, as primeiras 3 colunas com string e as ultimas 3 com horários... Quando eu puxo meu array para popular o listbox, o que é string vem certinho, mas o horário vem sem formatação...

Coloquei um exemplo para mostrar o que quero dizer.

Obrigado pela atenção e tempo!
Luis

 
Postado : 29/01/2015 3:22 pm
(@edcronos)
Posts: 1006
Noble Member
 

ola, eu gosto muito de usar array "quase um viciado" apesar de não ter me aprofundado nas varias possibilidades

particularmente não gosto de usar "Offset"

sobre atribuir valores da planilha em um array
se as células forem continuas, voc pode atribuir os valores diretamente sem ser célula por célula

aArray = Range("A1:F16").value2

(Linha,Coluna)
aArray(1,1)-->>A1 --- aArray(1,2)-->>B1 --- aArray(1,3)-->>C1...
aArray(2,1)-->>A2 --- aArray(2,2)-->>B2 --- aArray(2,3)-->>C2...

A mesma coisa para gravar os valores de um array na planilha

Range("A1:F16").value2= aArray

nesse casso a array deve ser variant
Dim aArray() as variant

esse tipo de array sempre começa (1,1)
pode pegar valores de Range completa ou de apenas uma linha ou apenas uma coluna

aArray = Range("A1:A16").value2
aArray(Linha, coluna) --->> Linha vai de 1 a 16, coluna apena valor 1 "se colocar outro valor ai dar subscrito fora de intervalo (ou algo assim :P )"

tem muitas vantagens de se fazer assim

 
Postado : 29/01/2015 4:33 pm
(@edcronos)
Posts: 1006
Noble Member
 

usando .TEXT
aArray=Cells(1,1).Text

Sub ArrayTeste()
'declarar as variáveis
Dim Mylist() As Variant
Dim nrow As Integer
Dim ncol As Integer
Dim i As Integer, j As Integer
Dim rng As Range
Dim ws As Worksheet

'para uma variável array que não se sabe o tamanho, primeiro temos que identificar numero de colunas & linhas (ncol & nrow)
Set ws = ThisWorkbook.Sheets(1) 'coloquei aqui, pois achava que eu teria que usar tipo "ws.rng.Column" mas não da certo.
With ws
Set rng = .Range("A1") 'Acho que é necessário uma referência para offset, deslocamento das células na montagem do array.
nrow = .Range(.Cells(1048576, rng.Column).End(xlUp), .Cells(rng.Row, 256).End(xlToLeft)).Rows.Count
ncol = .Range(.Cells(1048576, rng.Column).End(xlUp), .Cells(rng.Row, 256).End(xlToLeft)).Columns.Count
End With
'agora que se sabe o tamanho que terá seu array, redimenciona a variável.
ReDim Mylist(1 To nrow, 1 To ncol)

'populando a variável array
For i = 1 To nrow
    For j = 1 To ncol
        Mylist(i, j) = rng.Offset(i - 1, j - 1).Text '  Usa o .TEXT para pegar os valores, então esses vão estar como na Planilha
    Next j 'trocando de linha
Next i

'popular a userform com as informações da variável array.
With UserForm1
    .ListBox1.ColumnCount = ncol 'determinar o numero de colunas
    .ListBox1.ColumnWidths = 75 'determinar largura das colunas
    .ListBox1.List = Mylist 'popular as informações pra dentro da listbox
    .Show 'mostrar a userform.
End With

End Sub

esse é para demonstrar como usar atribuição de valores diretos em um ARRay
infelizmente parece que o método direto não aceita a atribuição TEXT para pegar os valores

Sub ArrayTeste3()

Dim Mylist() As Variant
Dim PL As Long, PC As String

PL = 2 'primeira linha
PC = "A" 'primeira Coluna

With Sheets("Plan1")
Mylist = .Range(PC & PL, .Cells(Cells(1048576, PC).End(xlUp).Row, .Cells(PL, 256).End(xlToLeft).Column)).Value
End With

With UserForm1
    .ListBox1.ColumnCount = UBound(Mylist, 2) 'determinar o numero de colunas
    .ListBox1.ColumnWidths = 75 'determinar largura das colunas
 .ListBox1.List = Mylist

'Voce tbm poderia ter usado assim:
'    .ListBox1.List = Sheets("Plan1").Range(PC & PL, Sheets("Plan1").Cells(Sheets("Plan1").Cells(1048576, PC).End(xlUp).Row, Sheets("Plan1").Cells(PL, 256).End(xlToLeft).Column)).Value 'popular as informações pra dentro da listbox

    .Show 'mostrar a userform.
End With

End Sub
 
Postado : 29/01/2015 6:15 pm
(@finaljustice)
Posts: 91
Estimable Member
Topic starter
 

usando .TEXT
aArray=Cells(1,1).Text

Sub ArrayTeste()
'declarar as variáveis
Dim Mylist() As Variant
Dim nrow As Integer
Dim ncol As Integer
Dim i As Integer, j As Integer
Dim rng As Range
Dim ws As Worksheet

'para uma variável array que não se sabe o tamanho, primeiro temos que identificar numero de colunas & linhas (ncol & nrow)
Set ws = ThisWorkbook.Sheets(1) 'coloquei aqui, pois achava que eu teria que usar tipo "ws.rng.Column" mas não da certo.
With ws
Set rng = .Range("A1") 'Acho que é necessário uma referência para offset, deslocamento das células na montagem do array.
nrow = .Range(.Cells(1048576, rng.Column).End(xlUp), .Cells(rng.Row, 256).End(xlToLeft)).Rows.Count
ncol = .Range(.Cells(1048576, rng.Column).End(xlUp), .Cells(rng.Row, 256).End(xlToLeft)).Columns.Count
End With
'agora que se sabe o tamanho que terá seu array, redimenciona a variável.
ReDim Mylist(1 To nrow, 1 To ncol)

'populando a variável array
For i = 1 To nrow
    For j = 1 To ncol
        Mylist(i, j) = rng.Offset(i - 1, j - 1).Text '  Usa o .TEXT para pegar os valores, então esses vão estar como na Planilha
    Next j 'trocando de linha
Next i

'popular a userform com as informações da variável array.
With UserForm1
    .ListBox1.ColumnCount = ncol 'determinar o numero de colunas
    .ListBox1.ColumnWidths = 75 'determinar largura das colunas
    .ListBox1.List = Mylist 'popular as informações pra dentro da listbox
    .Show 'mostrar a userform.
End With

End Sub

esse é para demonstrar como usar atribuição de valores diretos em um ARRay
infelizmente parece que o método direto não aceita a atribuição TEXT para pegar os valores

Sub ArrayTeste3()

Dim Mylist() As Variant
Dim PL As Long, PC As String

PL = 2 'primeira linha
PC = "A" 'primeira Coluna

With Sheets("Plan1")
Mylist = .Range(PC & PL, .Cells(Cells(1048576, PC).End(xlUp).Row, .Cells(PL, 256).End(xlToLeft).Column)).Value
End With

With UserForm1
    .ListBox1.ColumnCount = UBound(Mylist, 2) 'determinar o numero de colunas
    .ListBox1.ColumnWidths = 75 'determinar largura das colunas
 .ListBox1.List = Mylist

'Voce tbm poderia ter usado assim:
'    .ListBox1.List = Sheets("Plan1").Range(PC & PL, Sheets("Plan1").Cells(Sheets("Plan1").Cells(1048576, PC).End(xlUp).Row, Sheets("Plan1").Cells(PL, 256).End(xlToLeft).Column)).Value 'popular as informações pra dentro da listbox

    .Show 'mostrar a userform.
End With

End Sub

Poxa, muito obrigado por responderEdcronos!

Acho demais ver como outras pessoas pensam e as diferentes maneiras que se pode fazer as coisas em VBA! Show! Muito obrigado pelas duas respostas ajudaram bastante!! Especialmente o ".Text", hehe lindo!

 
Postado : 30/01/2015 9:48 am