Notifications
Clear all

Macro roda e excel apresenta problema de memória

15 Posts
3 Usuários
0 Reactions
2,075 Visualizações
(@faboalves)
Posts: 0
New Member
Topic starter
 

Olá amigos. Escrevi uma macro que copia os dados de uma planilha (LogNota) localizado na pasta documentos Públicos e repete isso até 10.000 vezes por execução. Entretanto, a macro está travando e as vezes apresenta problema de memória insuficiente. Ao acompanhar a execução da macro com o gerenciado de tarefa aberto, percebi que a memória utilizada pelo excel vai subindo até 140 +- antes de travar.
Alguém pode me ajudar com isso, por favor? Se possível explicar onde estou errando.
Muito obrigado.
Obs: O arquivo LogNota.XML deve estar no caminho c:userspublicdocuments

 
Postado : 16/02/2018 7:22 am
(@fernandofernandes)
Posts: 43750
Illustrious Member
 

Bom dia faboalves,

Não li todo o código, mas vê se pelo menos o problema de memória vai resolver:

Option Explicit

Dim WSD         As Worksheet    'Planilha Dashboard
Dim WSO         As Worksheet    'Planilha Logordem

Dim WTN         As Workbook     'Arquivo temporário LogNota
Dim WTO         As Workbook     'Arquivo temporário LogOrdem

Dim WSOS        As Worksheet    'Planilha SAP Log Ordem

'Global strNota  As String       'Número da nota atual da pesquis

Public Sub AtualizarLogNotas()
Dim WSN                 As Worksheet    'Planilha LogNota
Dim strNota             As String
Dim LinhaFinalNota      As Long
Dim i                   As Long
Dim ii                  As Long

    Application.ScreenUpdating = False
    
    Set WSD = ThisWorkbook.Sheets("Dashboard")
    Set WSN = ThisWorkbook.Sheets("LogNota")
    Set WSO = ThisWorkbook.Sheets("LogOrdem")

    LinhaFinalNota = WSD.Cells(Rows.Count, 4).End(xlUp).Row
    ii = 0

    For i = 12 To LinhaFinalNota
        strNota = WSD.Cells(i, 4)
        Call CopiarLogNota(strNota, WSN)
        ii = ii + 1
'        strNota = Empty
'        LinhaFinalNota = Empty
    Next i
    
    Set WSD = Nothing
    Set WSN = Nothing
    Set WSO = Nothing
    
    Application.ScreenUpdating = True
    
    MsgBox "Script concluído com sucesso!"

End Sub

Public Sub CopiarLogNota(ByVal strNota As String, WSN As Worksheet)
Dim WSNS                As Worksheet    'Planilha SAP Log Nota
Dim LinhaFinalLogNota1  As Long
Dim LinhaFinalLogNota2  As Long

    Workbooks.Open ("C:UsersPublicDocumentsLogNota.XML")
    
'    Set WSN = ThisWorkbook.Sheets("LogNota")
    Set WSNS = Workbooks("LogNota.XML").Sheets(1)
    
    LinhaFinalLogNota1 = WSN.Cells(Rows.Count, 4).End(xlUp).Row
'    Application.ScreenUpdating = False

    If LinhaFinalLogNota1 = 2 Then
        LinhaFinalLogNota1 = LinhaFinalLogNota1
    Else
        LinhaFinalLogNota1 = LinhaFinalLogNota1 + 1
    End If
    
    WSNS.Range("a1", Range("a1").End(xlDown).End(xlToRight)).Copy Destination:=WSN.Range("B" & LinhaFinalLogNota1)
    LinhaFinalLogNota2 = WSN.Cells(Rows.Count, 4).End(xlUp).Row
    WSN.Range("A" & LinhaFinalLogNota1, "A" & LinhaFinalLogNota2).Value = strNota
    
    Workbooks("LogNota.XML").Close SaveChanges:=False

'    Set WSN = Nothing
    Set WSNS = Nothing
    
'    strNota = Clear
'    LinhaFinalLogNota1 = Clear
'    LinhaFinalLogNota2 = Clear
'    Application.ScreenUpdating = True

End Sub

Qualquer coisa da o grito.
Abraço

 
Postado : 16/02/2018 8:21 am
(@faboalves)
Posts: 0
New Member
Topic starter
 

Bom dia Bernardooooooooo!,

Desde já, muito obrigado pela sua atenção e ajuda. Rodei como você orientou e o problema de memória continuou. Refiz o código sem as declarações de objetos e mantive suas alterações no código que também não funcionaram.

    Public Sub AtualizarLogNotas()

        Dim strNota             As String
        Dim LinhaFinalNota      As Long
        Dim i                   As Long
        Dim ii                  As Long
    
        Application.ScreenUpdating = False
        
        LinhaFinalNota = ThisWorkbook.Sheets("Dashboard").Cells(Rows.Count, 4).End(xlUp).Row
        
'        Call OpenSAPConn
        
        ii = 0
    
    
        For i = 12 To LinhaFinalNota
        
            strNota = ThisWorkbook.Sheets("Dashboard").Cells(i, 4)
        
            If ii = 100 Then
    
                ThisWorkbook.Save
                
                Call CloseSAPConn(Session)
                
'                Call OpenSAPConn
            
                ii = 0
        
            Else
              
'                Call LogAcaoNota(strNota)
                
                Call CopiarLogNota(strNota)
                
        End If
            
                ii = ii + 1
                
        Next i
        
        Application.ScreenUpdating = True
       
        MsgBox "Script concluído com sucesso!"

    End Sub
Public Sub CopiarLogNota(ByVal strNota As String)

    Dim LinhaFinalLogNota1  As Long
    Dim LinhaFinalLogNota2  As Long
    Dim buf(1 To 16384) As Variant
    Dim i As Long
    Const strFilePath As String = "c:userspublicdocumentsLogNota.XML"
    LinhaFinalLogNota1 = ThisWorkbook.Sheets("LogNota").Cells(Rows.Count, 2).End(xlUp).Row

    With Application
        .ScreenUpdating = False
        .DisplayAlerts = False
    End With
    
    For i = 1 To 16384
        buf(i) = Array(i, 2)
    Next
    Workbooks.OpenText Filename:=strFilePath, DataType:=xlDelimited, Comma:=True, FieldInfo:=buf
    Erase buf
    ActiveSheet.UsedRange.Copy ThisWorkbook.Sheets("LogNota").Range("B" & LinhaFinalLogNota1)
    ActiveWorkbook.Close False
    With Application
        .ScreenUpdating = True
        .DisplayAlerts = True
    End With
    LinhaFinalLogNota2 = ThisWorkbook.Sheets("LogNota").Cells(Rows.Count, 4).End(xlUp).Row
    ThisWorkbook.Sheets("LogNota").Range("A" & LinhaFinalLogNota1, "A" & LinhaFinalLogNota2).Value = strNota
   
   
End Sub
 
Postado : 19/02/2018 5:30 am
(@faboalves)
Posts: 0
New Member
Topic starter
 

Vamos lá pessoal.. Alguém pode ter outra ideia do que está acontecendo?
Abs,

 
Postado : 19/02/2018 9:54 am
(@edsonbr)
Posts: 0
New Member
 

Boa tarde, faboalves

Tem muitas coisas que estão desnecessárias em seu código mas o que mais está prejudicando a performance é a repetição de algumas tarefas dentro do laço for-next milhares de vezes sem necessidade.

Por exemplo, vc abre o workbook LogNotas.xlm, atribui à varável, copia o intervalo, cola tudo, fecha o workbook, zera a variável... tudo isso milhares de vezes. essas operações com arquivos são grandes consumidoras de recursos nesse processo.

Como o intervalo é sempre o mesmo, bastaria abrir, copiar para a área de transferência e só a colagem ficaria no laço de repetição. Terminou tudo, fecha o arquivo somente ao final.

Outro grande inimigo da performance é Colar geral, incluindo formatação, fórmulas, formatos de números, etc... Como vc tem uma base com campos consistentes, colar somente valores já seria suficiente. Se desejar, poderá via código, formatar seus dados ao final de todo o código. É bem mais rápido.

Por último, também muito importante, evite colar seus dados num intervalo em que já tem um objeto tabela. Converta em intervalo primeiro, rode o código e transforme em tabela ao final, se for necessário.

Se puder lançar os dados numa planilha limpa, sem nada de formatação seria bem mais rápido.

Com essas mudanças, fiz um teste aqui, de início levava 14 min 35seg. Removendo o abrir e fechar do arquivo no loop, caiu para 4 min 10seg. Removendo o objeto tabela e formatações, o tempo final ficou em 0 min 29 seg.

 
Postado : 19/02/2018 2:11 pm
(@faboalves)
Posts: 0
New Member
Topic starter
 

Caro Edson,

Muito obrigado. Se torna necessário abrir o arquivo LogNota.xml pois cada uma das notas tem o seu próprio log. Esse log eu tiro do SAP ERP e monto uma pedido base no Excel para elaborar os relatórios semanalmente. O ideal é que eu copiasse sem abrir o arquivo. Se souberem como sou um aluno esforçado hehehe. Vou seguir suas orientações e coloco o resultado. Abs

 
Postado : 19/02/2018 4:26 pm
(@edsonbr)
Posts: 0
New Member
 

... Se torna necessário abrir o arquivo LogNota.xml

Sim, faboalves, o arquivo XML está sendo aberto mas num nível mais acima. Entre uma chamada e outra, o fluxo do programa não sofre nenhuma alteração então pode ser aberto na rotina-pai e não em cada item do laço.

...Vou seguir suas orientações e coloco o resultado. Abs

Boa sorte... ;)

 
Postado : 19/02/2018 4:34 pm
(@faboalves)
Posts: 0
New Member
Topic starter
 

Senhores,

Com relação a memória, observei que o Excel está aumentando muito rápido a utilização da memória e trava. Infelizmente preciso abrir a planilha LogNota para cada uma nota. É isso tem comprometido o desempenho. Gostaria de uma ajuda no sentido de identificar pq a memória não está sendo liberada, mesmo quando eu coloco empyt no final dos laços de repetição. Obrigado.. Se alguém tiver alguma macro que faz algo parecido se esteja funcionando, se puder compartilhar eu agradeço.

 
Postado : 21/02/2018 6:00 pm
(@fernandofernandes)
Posts: 43750
Illustrious Member
 

Cara, aqui não tenho esse problema.

O XML será sempre o mesmo?
Juro que ainda não entendi a necessidade de abrir o XML tantas vezes.
Aqui roda normal, ele está limpando da memória normalmente.
Já tentou rodar em outra máquina?

Dá uma olhada nesse anexo e vê se ele resolve o seu problema e executa como precisa.

Qualquer coisa da o grito.
Abraço

 
Postado : 22/02/2018 8:47 am
(@faboalves)
Posts: 0
New Member
Topic starter
 

Preciso abrir muitas vezes pq o Sap gera um arquivo de log para cada nota. É a ideia é abrir o log, copiar os dados e consolidar todos os pogs em uma única planilha

 
Postado : 22/02/2018 10:13 am
(@fernandofernandes)
Posts: 43750
Illustrious Member
 

Deu uma olhada nesse último anexo que fiz? Ele faz como você precisa?
Se faz, não precisa abrir tantas vezes. Como pode ver, foi necessário abrir apenas uma única vez.

O que chama de arquivo de log? Os XMLs?
Fiz somente para as notas.

 
Postado : 22/02/2018 10:17 am
(@fernandofernandes)
Posts: 43750
Illustrious Member
 

Ou você nos enviou o caso da nota para resolvermos o caso das Ordens?

 
Postado : 22/02/2018 11:01 am
(@faboalves)
Posts: 0
New Member
Topic starter
 

não... os dois são iguais.. resolvendo um o outro funciona também...

 
Postado : 22/02/2018 11:44 am
(@fernandofernandes)
Posts: 43750
Illustrious Member
 

Então resolvi os dois?

 
Postado : 22/02/2018 11:47 am
(@faboalves)
Posts: 0
New Member
Topic starter
 

Caro Bernardo,

Resolveu em partes. Pois o seu código abre o arquivo e copia antes da estutura de repetição. Abrir o arquivo várias vezes na estrutura de repatição se faz necessário devido a dinâmica do sistema. Este código conversa com o sistema SAP na empresa onde trabalho, e em cada repetição ele busca o log de ação da nota no SAP ERP , que gera o arquivo LogNota.xml várias vezes sobrescrevendo o anterior. E desse forma o banco de dados vai se esruturando.

obs: esta forma é necessária por não haver uma consulta em lote, somente indivualmente, nota por nota.

Eu pensei em criar uma consulta de dados, pois assim o arquivo não precisa estar aberto, entretanto, o teste se mostrou ineficiente. A macro não espera a conclusão da consulta e se atropela, sem contar que a memória vai lá em cima também.

abs

 
Postado : 27/02/2018 6:31 pm