新しいビットマップ_イメージ__3_

【EXCEL VBA】セル範囲を2次元配列に入れる理由と方法について

こんにちは

普段のVBA業務でこんな風なプログラムを組んだことはありませんか??

Sub CommandButton1_Click() 'ボタンクリック時
    Dim i As long
    
    With Worksheets("Sheet1")
        For i=1 to 100
            If .cells(i,1) = "OK" then’もしセル内がOKの場合
               .cells(i,2) = "OKです"
            else
                .cells(i,2) = "NOです"
            end if
        next
    End With

end sub

画像1

↑のプログラムはSheet1内のA列1~100行がOKの時B列はOKです、

それ以外はNOですと入力するプログラムです

100行程度なら処理に問題はありません。

ここでどれくらいの処理時間がかかっているか確認しましょう。

始めと終わりに 「Debug.Print  Time」を入れます

   Debug.Print Time & "←開始時間"
   
   Dim i As Long
   With Worksheets("Sheet1")
       For i = 1 To 100
           If .Cells(i, 1) = "OK" Then'もしセル内がOKの場合
               .Cells(i, 2) = "OKです"
              Else
               .Cells(i, 2) = "NOです"
           End If
       Next
   End With
   
   Debug.Print Time & "←終了時間"

実行すると、イミディエイトウィンドウに時間が表示されます

(イミディエイトウィンドウは”表示””タブ→イミディエイトウィンドウ)

画像2

一秒以下で実行されました。早いですね。

しかしここで行数を増やしてみましょう。5万行くらいに

Private Sub CommandButton1_Click()
   Debug.Print Time & "←開始時間"
   
   Dim i As Long
   With Worksheets("Sheet1")
       For i = 1 To 50000'5万行に!
           If .Cells(i, 1) = "OK" Then 'もしセル内がOKの場合
               .Cells(i, 2) = "OKです"
              Else
               .Cells(i, 2) = "NOです"
           End If
       Next
   End With
   
   Debug.Print Time & "←終了時間"
   
End Sub

結果は3秒

画像3

先ほどよりも遅くなりましたね。3秒かかりました。

次に以下のプログラムを試してください

   
   Debug.Print Time & "←開始時間"

  Dim Array_Data As Variant
   With Worksheets("Sheet1")
   Array_Data = .Range("A1", .Cells(50000, 2))
       
       For i = 1 To UBound(Array_Data)
           If Array_Data(i, 1) = "OK" Then
               Array_Data(i, 2) = "OKです"
           Else
               Array_Data(i, 2) = "NOです"
           End If
       Next
       
    .Range("A1", .Cells(50000, 2)) = Array_Data
   
   End With
   
   Debug.Print Time & "←終了時間"

結果は以下のようになりました

画像4

先ほどよりも早いです。2秒短縮できています。

こちらのプログラムは配列に一度入れてから処理を行い、配列ごと一気にセル範囲に貼り付けています。

配列に入れて処理をするメリットは処理時間を短縮してVBAを軽くすることができます


各行ごとに必要な解説していきます

Dim Array_Data As Variant

まず配列の要素を定義します。

要素数が変わるような場合の配列の型定義においてVariantは便利です。

今回は要素数は変わりませんが、自分は配列定義の時はVariantをよく使います。(ホントはだめかも)


Array_Data = .Range("A1", .Cells(50000, 2))

ここがキモです。

Variant型で定義した配列にセル範囲を格納しています

こちらの場合、セル"A1"を始点とし、cells(50000,2)→”B50000"セルを終点とした範囲を配列に格納します。

分かりやすく図で解説すると、

画像5

のように配列内にデータが格納されています。

もし確認したい場合、VBAのウィンドの左をクリックしてカーソル前の行まで実行する状態にします。

画像6

実行後一時停止されたらメニュータブの表示、ローカルウィンドを起動します

以下のように配列データ内を確認すると、データが入っているかどうかわかります

画像7



つぎにfor文内処理です

最初のプログラムでは毎回セルに処理アクセスしていましたが、こちらのプログラムでは配列内にアクセスしています。

For i = 1 To UBound(Array_Data)
           If Array_Data(i, 1) = "OK" Then
               Array_Data(i, 2) = "OKです"
           Else
               Array_Data(i, 2) = "NOです"
           End If
       Next

先ほどセル範囲を格納した配列内をFor文でOK、NOの判別をします。



   .Range("A1", .Cells(50000, 2)) = Array_Data

最後に配列データをセル範囲に貼り付けて終了です。

変数をそのままセル範囲に格納しています。




まとめ

セルへのアクセスの際に配列を使うことで処理が早くなります。

今回は例題でセル数は少なかったですが、セル数が多ければ多いほど配列で処理した方が早いです。(経験談)

2次元配列で考えると難しい!ってなるかもしれませんが、圧倒的に配列の方がいいので慣れましょう


以上










この記事が気に入ったらサポートをしてみませんか?