KB0070: thinkcell が有効な場合、Excel マクロが遅いのはなぜですか?
VBA マクロでパフォーマンスの問題を引き起こす一般的な原因は、.Select 関数の使用です。Excel でセルが選択されるたびに、すべての Excel アドイン(thinkcell を含む)にこの選択変更イベントが通知されるため、マクロが大幅に遅くなります。マクロ レコーダーを使用して作成されたマクロでは、特にこの種の問題が発生しやすくなります。
Microsoft も、パフォーマンス向上のために VBA コードで .Select ステートメントを避けることを推奨しています:
- 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"("Faster VBA Macros" セクション内)。
例: .Select ステートメントの使用を避ける方法
次の簡単なマクロ 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
この関数は、ユーザーにセル範囲の指定を求める入力ボックスを開きます。 この関数は、範囲内のすべてのセルを移動します。 空でないセルが見つかると、そのセルの内容をクリップボードにコピーします。 この関数は、クリップボードの内容を後続のすべての空のセルに貼り付けます。
AutoFillTable は、セルの内容をコピーするためにクリップボードを使用します。 そのため、この関数では、操作対象の各セルを選択して、Excel がどのセルからコピーし、どのセルに貼り付けるべきかを認識できるようにする必要があります。 推奨される解決策は、次の関数 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 は、前の関数と比べて 2 つの重要な点が異なります。
- 最も重要なのは、セルを選択する必要がなくなったことです。 代わりに、空でないセルが見つかると、そのセルが変数
iCellMasterに保存されます。 その後、空のセルが見つかるたびに、iCellMasterのすべての内容がiCellにコピーされます。 - Visual Basic の言語機能
For Each … Nextを使用して、範囲内のすべてのセルを順に処理します。 これだけでも可読性の向上につながります。