Função busca loop c...
 
Notifications
Clear all

Função busca loop cells, loop array ou find

7 Posts
2 Usuários
0 Reactions
1,608 Visualizações
(@edcronos)
Posts: 1006
Noble Member
Topic starter
 

ola

estou fazendo algumas funções que vão fazer buscas em ranges definidas em tabelas,
e essas ranges podem chegar a ter mais de 6000 linhas e muito mais de 40 colunas

como vai ser uma função para para cada tipo de informação
e serão juntadas umas as outras em formulas para se ter o esperado ou até usadas sozinhas
estão ficando muito grandes.

tipo essa que ainda não terminei,
ela vai retornar o numero da linha onde tem um valor que busco
buscando para baixo ou para cima a partir de uma linha inicial
para então outras funções ou macros me retornar a informação que preciso dessa linha
"linha inteira, valor de coluna de algum setor, proxima linha do setor..." isso vai me tornar capaz de conseguir qualquer tipo de informação da planilha.

Public Function Linha_Val(Nome_Plan As String, Numero_do_Setor As Long, Valor, linha_inicial As Long, _
        cima1_baixo2 As Long, Optional ByVal coluu As Long)
    With Sheets(Nome_Plan)
        Cq = .Cells(20, Numero_do_Setor).Value2
        Ci1 = .Cells(1, .Cells(17, Numero_do_Setor).Value2).Column
        If coluu = 0 Then

            Li = .Cells(10, 5).Value2
            Li = .Cells(Li, Ci1).End(xlDown).row
            Lf = .Cells(Rows.Count, Ci1).End(xlUp).row

            If cima1_baixo2 = 1 Then
                For L = linha_inicial To Li Step -1
                    For C = 1 To Cq
                        If Valor = .Cells(L, C).Value2 Then GoTo Fimn
                    Next: Next
            End If
            If cima1_baixo2 = 2 Then
                For L = linha_inicial To Lf
                    For C = 1 To Cq
                        If Valor = .Cells(L, C).Value2 Then GoTo Fimn
                    Next: Next
            End If
        Else

            C = coluu
            If C > 0 And C <= Cq Then

                If cima1_baixo2 = 1 Then
                    For L = linha_inicial To Li Step -1
                        If Valor = .Cells(L, C).Value2 Then GoTo Fimn
                    Next
                End If
                If cima1_baixo2 = 2 Then
                    For L = linha_inicial To Lf
                        If Valor = .Cells(L, C).Value2 Then GoTo Fimn
                    Next
                End If
            End If

        End If
    End With

Fimn:
    Linha_Val = L
End Function

Em um caso desse como ficaria mais rapido,?
como proceder ou estruturar a função ?

sei que cada um tem suas preferências e limitações ou necessidade
eu por exemplo não uso mais find, offset ,odeio resize e evito ou nem uso formulas matriciais

quando são muitas buscas consecutivas no lugar de find eu uso varredura em um array,
mas usar cells em varreduras quando a planilha não tem formulas e formatações condicionais tbm é bem rápido
e nesse caso eu uso uma plan auxiliar ou tiro a formatação condicional e depois reaplico, oq tbm vale para caso de redimensionamento da planilha para não desmembrar as formatações.

mas e para funções ?

Até

Somente é impossíveis até que alguém faça
A logica está presa na irracionalidade humana, e morta nos que se consideram donos da verdade.

"ALGUM MODERADOR ME EXPULSE DO FÓRUM POR FAVOR"

 
Postado : 06/12/2014 9:21 am
Reinaldo
(@rlm)
Posts: 246
Estimable Member
 

Não sei se entendi direito, mas a função que colocou, não creio que possa se mais veloz.
Pode, mesmo em função, incluir sua range em um array ou coleção, se julgar mais rápido.
Me parece que houve uma inversão entre Li e Lf, mas não sei dizer por não poder ver na pratica
Porem a função pode ser simplificada um pouco (creio eu).Poderia ficar algo +/- assim:

Public Function Linha_Val(Nome_Plan As String, Numero_do_Setor As Long, Valor, linha_inicial As Long, _
                          cima1_baixo2 As Long, Optional ByVal coluu As Long)
With Sheets(Nome_Plan)
    
Cq = .Cells(20, Numero_do_Setor).Value2
Ci1 = .Cells(1, .Cells(17, Numero_do_Setor).Value2).Column
    
If coluu = 0 Then
    If cima1_baixo2 = 2 Then
        Lf = .Cells(Rows.Count, Ci1).End(xlUp).Row
        st = 1
    Else
        Lf = .Cells(10, 5).Value2
        Lf = .Cells(Lf, Ci1).End(xlDown).Row
        st = -1
    End If

    For L = linha_inicial To Lf Step st
        For C = 1 To Cq
            If Valor = .Cells(L, C).Value2 Then GoTo Fimn
        Next
    Next
Else
    If coluu <= Cq Then
        For L = linha_inicial To Lf Step st
            If Valor = .Cells(L,coluu).Value2 Then GoTo Fimn
        Next
    End If
End If
End With

Fimn:
    Linha_Val = L
End Function

Reinaldo

 
Postado : 06/12/2014 11:17 am
(@edcronos)
Posts: 1006
Noble Member
Topic starter
 

essa função em questão eu terminei
pelo menos está retornando o numero da linha que tem o valor procurado
apesar de achar que poderia ficar melhor

Public Function Linha_Val(ByVal Nome_Plan As String, ByVal Numero_do_Setor As Long, ByVal Valor, ByVal linha_inicial As Long, _
        ByVal cima1_baixo2 As Long, Optional ByVal coluu As Long) As Long
    With Sheets(Nome_Plan)
        Cq = .Cells(20, Numero_do_Setor).Value2
        Ci1 = Cells(1, .Cells(17, Numero_do_Setor).Value2).Column
        Cq = Ci1 + Cq
        Li = .Cells(.Cells(10, 5).Value2, Ci1).End(xlDown).row
        Lf = .Cells(Rows.Count, Ci1).End(xlUp).row
        If coluu = 0 Then
            If cima1_baixo2 = 1 Then
                For L = linha_inicial To Li Step -1
                    For C = Ci1 To Cq
                        If Valor = .Cells(L, C).Value2 Then GoTo Fimn
                    Next: Next
            End If

            If cima1_baixo2 = 2 Then
                For L = linha_inicial To Lf
                    For C = Ci1 To Cq
                        If Valor = .Cells(L, C).Value2 Then GoTo Fimn
                    Next: Next
            End If
        Else
            C = Ci1 + coluu - 1
            If C > 0 And C <= Cq Then
                If cima1_baixo2 = 1 Then
                    For L = linha_inicial To Li Step -1
                        If Valor = .Cells(L, C).Value2 Then GoTo Fimn
                    Next
                End If
                If cima1_baixo2 = 2 Then
                    For L = linha_inicial To Lf
                        If Valor = .Cells(L, C).Value2 Then GoTo Fimn
                    Next
                End If

            End If
        End If
    End With

Fimn:
    Linha_Val = L
End Function

mas acho que essa ordem de entrada de parametros está um pouco confusa

(ByVal Nome_Plan As String, ByVal Numero_do_Setor As Long, ByVal Valor, ByVal linha_inicial As Long,  ByVal cima1_baixo2 As Long, Optional ByVal coluu As Long)

Linha_Val(Nome_Plan; Numero_do_Setor ; Valor; linha_inicial ;cima1_baixo2; Optional coluu;)

seria algo como:
ABA; Range; Valor Procurado; Linha inicial; Direção; Opcional "coluna"

se alguem tiver alguma sugestão, dica ou critica

ainda estou pesando em usar um array na busca e testar a velocidade
com find creio não ficar legal por causa dos parâmetros já embutidos na função apesar de simplificar o codigo.

Somente é impossíveis até que alguém faça
A logica está presa na irracionalidade humana, e morta nos que se consideram donos da verdade.

"ALGUM MODERADOR ME EXPULSE DO FÓRUM POR FAVOR"

 
Postado : 06/12/2014 11:29 am
(@edcronos)
Posts: 1006
Noble Member
Topic starter
 

ola Reinaldo,
eu ainda estava estruturando a função então estava tudo bagunçado e com quase tudo errado
quando vc mandou a resposta eu estava escrevendo a de cima e ficou parado aqui e quado mandei vc já tinha mandando a sua
ou dar um olhada e ver o que posso aproveitar.

Somente é impossíveis até que alguém faça
A logica está presa na irracionalidade humana, e morta nos que se consideram donos da verdade.

"ALGUM MODERADOR ME EXPULSE DO FÓRUM POR FAVOR"

 
Postado : 06/12/2014 11:38 am
(@edcronos)
Posts: 1006
Noble Member
Topic starter
 

sobre
li = linha de cima "linha inicial da range"
lf = linha de baixo "linha final da range"
linha_inicial= linha onde começa a leitura

For linha_inicial To LF
"= busca de cima para baixo a partir da (linha_inicial)"

isso por que já estou acostumado com a estrutura das outras macro que fiz
já usei array para fazer buscas
uma delas compara 2 duas ranges procurando repetidos
viewtopic.php?f=21&t=12297#p66453
"função conta repetidos 2 range Edcronos.rar"
não testei usando loops em cells, então não sei se num caso assim fica mais rapido ou não, mas dessa vez como é para mim vou testar

vc pegou bem rapido o modo de simplificar a macro pelo que ela estava
estou até pensando em te pedi para ver se tem como otimizar uma magro minha :D

até

Somente é impossíveis até que alguém faça
A logica está presa na irracionalidade humana, e morta nos que se consideram donos da verdade.

"ALGUM MODERADOR ME EXPULSE DO FÓRUM POR FAVOR"

 
Postado : 06/12/2014 12:34 pm
(@edcronos)
Posts: 1006
Noble Member
Topic starter
 

Para facilitar os testes e o entendimento
fiz uma planilha de exemplo

tem muitos pontos que precisam melhorar
mas acho que estou no caminho
se alguem puder ajudar

Somente é impossíveis até que alguém faça
A logica está presa na irracionalidade humana, e morta nos que se consideram donos da verdade.

"ALGUM MODERADOR ME EXPULSE DO FÓRUM POR FAVOR"

 
Postado : 06/12/2014 2:24 pm
(@edcronos)
Posts: 1006
Noble Member
Topic starter
 

bem, pelos varios testes que fiz

se o valor está próximo não faz diferença em cells e array
mas se forem varias buscas consecutivas e o valor estiver longe array é muito mais rápido
isso pq o vba procura direto na memora sem pedir informação ao excel a cada celula

pelo menos com array parece que a planilha fica mais leve
não fiz contagem de tempo pq o intuito era testar o fluxo da planilha usando varias formulas com função

Somente é impossíveis até que alguém faça
A logica está presa na irracionalidade humana, e morta nos que se consideram donos da verdade.

"ALGUM MODERADOR ME EXPULSE DO FÓRUM POR FAVOR"

 
Postado : 07/12/2014 5:49 pm