KB0070: Perché la macro di Excel è lenta quando thinkcell è attivato?
- Home
- Risorse
- Knowledge base
- KB0070
Un problema comune che può causare problemi di prestazioni nelle macro VBA è l'uso della funzione .Select. Ogni volta che una cella viene selezionata in Excel, ogni singolo componente aggiuntivo di Excel (incluso thinkcell) riceve una notifica di questo evento di modifica della selezione, rallentando notevolmente la macro. Le macro create usando il registratore di macro sono particolarmente soggette a questo tipo di problema.
Microsoft consiglia inoltre di evitare l'istruzione .Select nel codice VBA per migliorare le prestazioni:
- Blog di Office: Excel VBA Performance Coding Best Practices
- MSDN: Improving Performance in Excel 2007: "Reference Excel objects such as Range objects directly, without selecting or activating them" (in the section, "Faster VBA Macros").
Esempio: come evitare l'uso dell'istruzione .Select
Esaminiamo la seguente semplice macro 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
Questa funzione apre una casella di input che chiede all'utente di specificare un intervallo di celle. La funzione scorre tutte le celle dell'intervallo. Se trova una cella non vuota, copia il contenuto della cella negli Appunti. La funzione incolla il contenuto degli Appunti in ogni cella vuota successiva.
AutoFillTable usa gli Appunti per copiare il contenuto della cella. Pertanto, la funzione deve selezionare ogni cella manipolata in modo che Excel sappia da quale cella copiare e in quale cella incollare. La soluzione consigliata è mostrata nella seguente funzione AutoFillTable2:
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
AutoFillTable2 differisce dal suo predecessore in due aspetti importanti:
- Soprattutto, non deve più selezionare una cella. Invece, quando viene trovata una cella non vuota, questa cella viene memorizzata nella variabile
iCellMaster. Successivamente, ogni volta che viene trovata una cella vuota, tutto il contenuto diiCellMasterviene copiato iniCell. - Usa la funzionalità del linguaggio Visual Basic
For Each … Nextper visitare ogni cella dell'intervallo. Questo rappresenta già un miglioramento della leggibilità.