ナレッジベース KB0070

think-cellをアクティブにするとExcelのマクロが鈍化する

VBA マクロにおいてパフォーマンス問題が発生する一般的な原因として、.Select 関数の使用があります。Excel でセルを選択するたびに、それぞれの Excel アドイン (think-cell を含む) に対してこの選択対象変更イベントが通知されるため、マクロの動作が著しく低下します。特にマクロ レコーダーを使用して作成されたマクロでは、このタイプの問題が発生しがちです。

Microsoftも、パフォーマンスを改善するためにVBAコードで.Selectステートメントを避けるよう推奨しています。

例:.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 つ重要な違いがあります:

  1. 最も重要なのは、セルを選択する必要がないという点です。代わりに、空でないセルが見つかった場合、このセルは iCellMaster 変数に保存されます。その後、空のセルが見つかるたびに、iCellMaster のコンテンツはすべて iCell にコピーされます。
  2. これは Visual Basic 言語機能 For Each … Next を使用して、範囲内のすべてのセルにアクセスします。この時点ですでに読みやすさが改善されています。

共有する