Por que minha macro do Excel fica lenta quando o think-cell está ativado?
Um problema comum que pode causar falhas de desempenho em macros VBA é o uso da função .Select
. Sempre que uma célula é selecionada no Excel, todos os suplementos do Excel (incluindo o think-cell) são notificados sobre esse evento de alteração da seleção, o que desacelera a macro consideravelmente. Especialmente as macros criadas usando o gravador de macros são propícias a esse tipo de problema.
- Blog oficial: "Qual é o caminho mais rápido para examinar um grande intervalo no Excel?"
- MSDN: Melhorando o desempenho no Excel 2007: "Faça referência a objetos no Excel, como Intervalo de objetos, diretamente, sem selecioná-los ou ativá-los" (na seção, "VBA Macros mais rápidos").
Exemplo: Como evitar o uso da declaração .Select
Vejamos a seguinte macro simples AutoFillTable
:
Sub AutoFillTable()
Dim iRange As Excel.Range
Set iRange = Application.InputBox(prompt:="Enter range", Type:=8)
Dim nCount As Integer
nCount = iRange.Cells.Count
For i = 1 To nCount
Selection.Copy
If iRange.Cells.Item(i).Value = "" Then
iRange.Cells.Item(i).Range("A1").Select
ActiveSheet.Paste
Else
iRange.Cells.Item(i).Range("A1").Select
End If
Next
End Sub
Essa função abre uma caixa de entrada que pede ao usuário que especifique um intervalo de células. A função move todas as células no intervalo. Se encontrar uma célula que não está vazia, ela copia o conteúdo da célula para a área de transferência. A função cola o conteúdo da área de transferência para todas as células vazias subsequentes.
A AutoFillTable
usa a área de transferência para copiar o conteúdo da célula. Assim, a função precisa selecionar cada célula que é manipulada, para que o Excel saiba a partir de que célula deve copiar e para que célula deve colar. A solução recomendada é mostrada na função AutoFillTable2
a seguir:
Sub AutoFillTable2()
Dim iRange As Excel.Range
Set iRange = Application.InputBox(prompt:="Enter range", Type:=8)
Dim iCellMaster As Excel.Range
For Each iCell In iRange.Cells
If iCell.Value = "" Then
If Not iCellMaster Is Nothing Then
iCellMaster.Copy (iCell)
End If
Else
Set iCellMaster = iCell
End If
Next iCell
End Sub
A AutoFillTable2
difere de sua predecessora em duas formas importantes:
- Mais importante, já não é necessário selecionar uma célula. Em vez disso, quando uma célula é encontrada não estando vazia, essa célula é armazenada na variável
iCellMaster
. Portanto, sempre que uma célula vazia é encontrada, todo o conteúdo daiCellMaster
é copiado naiCell
. - Ela utiliza o recurso da linguagem Visual Basic
For Each … Next
para visitar cada célula na faixa. Isso já é uma melhoria para a legibilidade.