Notifications
Clear all

Limpar as Variáveis da Memória

5 Posts
3 Usuários
2 Reactions
10.6 K Visualizações
Kaleo_rs
(@kaleo_rs)
Posts: 0
Trusted Member
Topic starter
 

Blz pessoal.

Alguém poderia me dar a dica de como limpar/liberar/apagar as variáveis que as vários MACROS que vão sendo executadas. Estou achando que é isso.

Vou executando as macros, nem sempre elas são na mesma sequencia. Chega em determinado momento que ao executar um outro processo começa a ficar MUITO LENTO, onde sou obrigado a fechar o excel, para que o processo que ocorre em segundos não leve minutos.

Espero que tenha solução.

 
Postado : 22/07/2020 10:00 am
Wagner Morel
(@wagner-morel-vidal-nobre)
Posts: 0
Illustrious Member
 

Kaleo_rs,

 

Bom dia!

 

Se você acha que é esse o problema, então, deve, ao final de cada módulo, antes da linha End Sub, usar da segvuinte forma para libertar a memória das variáveis:

'Quanto for variável inteira
Teste = 0
'Quando for variável double
Teste = 0.00
'Quando for variável string
Teste = ""
'Quando for variável de objeto
Set Teste = Nothing
 
E por aí vai... veja também outros tipos de variáveis.

Desenvolvo pequenas soluções em VBA Excel a valores que variam entre R$ 50,00 a R$ 200,00. Se te interessar, entre no meu instagran (vba_excel_desenvolvimento)

Atenciosamente
Wagner Morel

 
Postado : 22/07/2020 10:52 am
EdsonBR
(@edsonbr)
Posts: 1057
Noble Member
 

Bom dia, @Kaleo_rs

A principal dica seria um bom planejamento de seu projeto, especialmente se forem códigos longos/complexos. Atenção redobrada em pontos onde são criados objetos (CreateObject, Dim XXX As New YYY, Set XXX = New YYY) especialmente se forem tipo Application e objetos externos. Os Applications normalmente ficam invisíveis e mesmo setando as variáveis para Nothing ao final, se eles não forem explicitamente fechados (geralmente métodos .Quit/.Close/.Exit) acabam por irem se acumulando várias instâncias na memória.

Além de setar os objetos para Nothing nos pontos de saída, inclusive em tratamentos de erro (Set XXX = Nothing), apagar matrizes (Erase Z) também é boa prática, especialmente se forem Tipos Definidos pelo usuário (Type ... End Type).

Além disso, ao longo de compilação após compilação, principalmente durante a fase de testes, um monte de lixo vai ficando acumulado e tende a dar problemas, principalmente porque as rotinas são interrompidas no meio para ajustes, não chegando no final (End Sub) e portanto não despejando-os. Para isso, tem um suplemento gratuito bem antigo (1999) e bem conceituado do Rob Bovey que faz uma faxina no código, sem alterá-lo. Eu uso ele frequentemente:

VBA Code Cleaner

 
Postado : 22/07/2020 10:54 am
Kaleo_rs
(@kaleo_rs)
Posts: 0
Trusted Member
Topic starter
 

@edsonbr Entendi, mas não sei bem como fazer.... Sou do tipo que vai na internet aprende e aplico.

* Atenção redobrada em pontos onde são criados objetos (CreateObject, Dim XXX As New YYY, Set XXX = New YYY) especialmente se forem tipo Application e objetos externos...... PERGUNTA: seria só colocar = Nothing

* Os Applications normalmente ficam invisíveis e mesmo setando as variáveis para Nothing ao final, se eles não forem explicitamente fechados (geralmente métodos .Quit/.Close/.Exit) acabam por irem se acumulando várias instâncias na memória...... PERGUNTA: isso não compreendi o que você explicou.

* Além de setar os objetos para Nothing nos pontos de saída, inclusive em tratamentos de erro (Set XXX = Nothing), apagar matrizes (Erase Z) também é boa prática, especialmente se forem Tipos Definidos pelo usuário (Type ... End Type)..... PERGUNTA: Aqui ficou tranquilo. 

 
Postado : 22/07/2020 10:07 pm
Wagner Morel reacted
EdsonBR
(@edsonbr)
Posts: 1057
Noble Member
 

Um exemplo pra melhor entendimento:

Digamos que vc tenha 3 documentos Word no disco A: Teste1.docx, Teste2.docx e Teste3.docx. À partir do Excel, vc quer abrir cada um deles, escrever alguma coisa, salvar e fechar.
A pior maneira em relação ao uso de variáveis seria assim:

Sub PéssimaEscolha()
  Dim i As Integer, wdApp As Object
For i = 1 To 3
Set wdApp = CreateObject("Word.Application")
With wdApp.Documents.Open("A:\Teste" & i & ".docx")
.Range.Text = "Olá Mundo" & i
.Save
.Close
End With
Next i
End Sub

O código iria rodar e fazer o que queria, embora vc nem veria o Word aparecer. Mas várias coisas não estão certas (ou pelo menos deveriam ser melhoradas) :

  • Criar múltiplas instâncias do Word Application dentro do laço For...Next:
    Vc não precisa abrir 3 Words em paralelo para abrir os 3 arquivos, pois os arquivos são abertos sequencialmente (em série) e fechados para só então abrir outro. Portanto a linha Set wdApp = CreateObject("Word.Application") deve vir fora do laço, antes da linha For i = 1 To 3. Isso também deixa o código bem mais rápido e com menor uso de recursos da sua máquina.
    Um detalhe: o método .Close acima não fecha o Aplicativo Word e sim o Documento que foi aberto.
  • Não fechar o(s) objeto(s) após consumi-lo(s):
    Se após rodar o código anterior vc abrir o Gerenciador de Tarefas do Windows (CTRL+SHIFT+ESC) vai perceber que existem 3 aplicativos Word ainda abertos na memória, embora invisíveis. Estão ali, catatônicos, consumindo memória e não servindo pra nada, pois vc está sem acesso a eles (para eliminá-los clique com o direito sobre cada um e escolha Finalizar Tarefa).
    Mesmo se após a linha .Close vc tivesse atribuído Set wdApp = Nothing, isso teria liberado a variável wdApp da memória, mas o aplicativo Word continuaria rodando. Então esvaziar a variável é necessário, mas não suficiente.
    O que faltou ali foi Fechar o Word com o método Quit (wdApp.Quit)
  • Não extinguir a variável de objeto wdApp após consumi-la:
    Há uma certa polêmica em relação a isso, pois há os que defendem que seria desnecessário, uma vez que o próprio VBA libera as variáveis quando chega no End Sub/Function ou Exit Sub/Function. E há os que consideram uma boa prática fazê-lo sempre, geralmente no final da rotina ou após seu último uso (Set wdApp = Nothing). Em códigos pequenos, com baixa frequência de uso costumo dispensar. Mas nos de maior responsabilidade, sempre uso essa prática.

Então uma versão melhorada do código ficaria assim:

Sub AgoraMelhorou()
Dim i As Integer, wdApp As Object
Set wdApp = CreateObject("Word.Application")
For i = 1 To 3
With wdApp.Documents.Open("A:\Teste" & i & ".docx")
.Range.Text = "Olá Mundo" & i
.Close
End With
Next i
wdApp.Quit
Set wdApp = Nothing
End Sub

 
Postado : 23/07/2020 2:31 am
Wagner Morel reacted