Alterar função para...
 
Notifications
Clear all

Alterar função para minimizar lentidão.

4 Posts
2 Usuários
0 Reactions
1,042 Visualizações
(@ikardoso)
Posts: 0
New Member
Topic starter
 

Bom dia a todos.

Venho pedir a costumeira ajuda dos colegas para tentar implementar a seguinte situação:

Possuo uma planilha com uma função personalizada cujo código retirei deste site: http://www.remkoweijnen.nl/blog/2007/11 ... rom-excel/

Segue código:

Option Explicit
Function GetAdsProp(ByVal SearchField As String, ByVal SearchString As String, ByVal ReturnField As String) As String
    Dim strDomain As String
    strDomain = GetObject("LDAP://rootDSE").Get("defaultNamingContext")
    
    Dim objConnection As ADODB.Connection
    Set objConnection = CreateObject("ADODB.Connection")
    objConnection.Open "Provider=ADsDSOObject;"
        
    Dim objCommand As ADODB.Command
    Set objCommand = CreateObject("ADODB.Command")
    objCommand.ActiveConnection = objConnection
        
    objCommand.CommandText = _
        "<LDAP://" & strDomain & ">;(&(objectCategory=User)" & _
        "(" & SearchField & "=" & SearchString & "));" & SearchField & "," & ReturnField & ";subtree"
 
    Dim objRecordSet As ADODB.Recordset
    Set objRecordSet = objCommand.Execute
    
    If objRecordSet.RecordCount = 0 Then
        GetAdsProp = "Não Localizado"
               
    Else
        GetAdsProp = objRecordSet.Fields(ReturnField)
        
    End If
    
    objConnection.Close
    
    Set objRecordSet = Nothing
    Set objCommand = Nothing
    Set objConnection = Nothing
     
End Function


Este código recupera atraves de uma função as informações de usuário contidas no active directory.Funciona da seguinte forma:
Crie um módulo no vba e copie o código, em seguida se faz necessário adicionar a referencia Microsoft Activex Data Objects 6.1 Library
No meu caso eu precisei também habiltar as conexões na central de confiabilidade.

Feito isso, imagine que na coluna "A1" eu tenha o login de um determinado usuário. Como exemplo vamos imaginar um login qualquer:

M123456

Então, para recupar por exemplo o nome do usuário atraves do login (M123456) na coluna "B" digito a seguinte função =GetAdsProp("sAMAccountName";A1;"displayName")

O retorno na coluna "B" seria o nome correpondente ao Login de M123456. Até aí OK, está funcionando perfeitamente.

O problema é que, conforme vou populando está planilha a mesma vai ficando extremamente lenta, e ao abrir a planilha pela primeira vez piora, isto porque ao abrir a planilha por exemplo com 300 usuários a função novamente busca a informação de todos os usuários contidos nela no Active Directory novamente.

Por isso peço a ajuda para encontrar uma maneira de implentar essa função onde após ela retornar a informação do usuário (neste caso o nome) ela seja desativa para não causar essa extrema lentidão, Exemplo:

Enquanto célula "A1" for vazia = função ativa em "B2"

Se celula "A1" contiver dados (no caso o login do usuário)
> executa função em "B2"
> Recupera a informação do usuário
> desativa a função mantendo somente os valores recuperados em "B2"

Espero ter sido claro e desde já agradeço a atenção e ajuda de sempre.
abs

 
Postado : 24/02/2016 5:35 am
(@fernandofernandes)
Posts: 43750
Illustrious Member
 

Como ela é uma UDF, dificilmente vc vai conseguir mexer no disparo dela na hora do recálculo...
Sugiro duas opções:
1) Coloque na primeira linha da função:

Application.Volatile False

Dizem que isso torna a função não disparável mtas vezes. Mas nunca vi muita vantagem.

2) Esse é um dos poucos casos em que usar variável pública é muito bem vindo. Eu criaria um dicionário público! Daí editaria a sua UDF para verificar se o nome já existe no dicionário, e puxá-lo de lá, ao invés de rodar toda a rotina novamente !
Isso não desliga a função, mas impede que ela rode tudo de novo, pq guarda os resultados num dicionário. Isso tb não resolve a performance do momento de abertura, visto que na abertura o dicionário está vazio.
Ficaria assim:

Option Explicit

Public Dicionario As Object                                                                             'FF

Public Function GetAdsProp(ByVal SearchField As String, _
                           ByVal SearchString As String, _
                           ByVal ReturnField As String) As String
Dim strDomain       As String
Dim objConnection   As ADODB.Connection
Dim objCommand      As ADODB.Command
Dim objRecordSet    As ADODB.Recordset
    
    If Dicionario Is Nothing Then Set Dicionario = VBA.CreateObject("Scripting.Dictionary")             'FF
    
    If Dicionario.EXISTS(SearchString) Then                                                             'FF
        GetAdsProp = Dicionario(SearchString)                                                           'FF
    Else                                                                                                'FF
        strDomain = GetObject("LDAP://rootDSE").Get("defaultNamingContext")
        
        Set objConnection = CreateObject("ADODB.Connection")
        objConnection.Open "Provider=ADsDSOObject;"
        
        Set objCommand = CreateObject("ADODB.Command")
        objCommand.ActiveConnection = objConnection
        
        objCommand.CommandText = "<LDAP://" & strDomain & ">;(&(objectCategory=User)" & "(" & SearchField & "=" & SearchString & "));" & SearchField & "," & ReturnField & ";subtree"
        
        Set objRecordSet = objCommand.Execute
        
        
        If objRecordSet.RecordCount = 0 Then
            GetAdsProp = "Não Localizado"
        
        Else
            GetAdsProp = objRecordSet.Fields(ReturnField)
            Dicionario.Add SearchString, GetAdsProp
        
        End If
        
        objConnection.Close
        
        Set objRecordSet = Nothing
        Set objCommand = Nothing
        Set objConnection = Nothing
    End If                                                                                              'FF
    
End Function

O que vc poderia fazer com o conceito do dicionário, é, pegar o dicionário das células, e verificar se o item está em branco e assim, rodar e atualizar o dicionário. Caso contrário, devolver o conteúdo do dicionário. Mas este código necessita de mais tempo do que tenho disponível agora... Então veja se o código acima funciona!

 
Postado : 24/02/2016 6:31 am
(@ikardoso)
Posts: 0
New Member
Topic starter
 

Bom dia meu caro.
Pois é, tentei algumas coisas aqui mas sem sucesso, no momento da abertura da planilha trava tudo.
De qualquer forma obrigado pela ajuda.
abs

 
Postado : 16/03/2016 5:07 am
(@fernandofernandes)
Posts: 43750
Illustrious Member
 

Poste seu arquivo

 
Postado : 16/03/2016 5:45 am