【VBA】10.3 [emalabo式] ループ処理を作成する際のコーディングルールをマスターしよう!

目次

連続するセルに対してループ処理を作成する際の2つのコーディングのタイプを紹介!

連続するセルに対してループ処理を作成する際、プログラマーは以下の2つの方法のうち、いずれかでコーディングします
(この章では、タイプA・タイプBと命名します。)

次のコーディング例は、以下のケースを想定して作成したものです。

ケース1

  • 以下の表のA列に対して、2行目から最終行まで、1からの連番をセットする。
ループ処理作成用リスト

タイプA

Option Explicit

Sub set_number()

    Dim ws_employeelist As Worksheet
    Dim num_row As Long
    
    Application.ScreenUpdating = False
    
    Set ws_employeelist = ThisWorkbook.Worksheets("社員一覧")
    
    For num_row = 2 To ws_employeelist.Cells(Rows.Count, 2).End(xlUp).Row
        ws_employeelist.Range("A" & num_row) = num_row - 1
    Next num_row    
    
    ThisWorkbook.Save

    Application.ScreenUpdating = True

End Sub

タイプB

Option Explicit

Sub set_number()

    Dim ws_employeelist As Worksheet
    Dim num_row As Long
    
    Application.ScreenUpdating = False
    
    Set ws_employeelist = ThisWorkbook.Worksheets("社員一覧")
    
    For num_row = 2 To ws_employeelist.Cells(Rows.Count, 2).End(xlUp).Row
        ws_employeelist.Cells(num_row, 1) = num_row - 1
    Next num_row
    
    ThisWorkbook.Save

    Application.ScreenUpdating = True

End Sub

ケース1のタイプAとタイプBの比較結果

上記のタイプAとタイプBのソースコードで違いがあるのは、13行目の以下の箇所になります。

タイプARange(“A” & num_row)
タイプBCells(num_row, 1)

ループ処理を行う際に、2行目~最終行までを「num_row」というカウンターを使って繰り回すしてセルをずらしていく処理で、タイプAではRangeを使用し、タイプBではCellsを使用しています

この例ではそれほど大きな違いはなく、一概に優劣を付けられないため、次のような場合を検討してみます。

二重ループ処理のコーディング例

二重ループというのは、ループ処理の中にループ処理がある、入れ子構造のループ処理のことを指します。

Excelマクロで作成される二重ループでは、行に対するループ処理の中に、列のループ処理があるといった、行と列の入れ子構造の二重ループが想定されます。

次のコーディング例は、以下のケースを想定して作成したものです。

ケース2

  • 10行×10列の表領域の各セルに、1~100までの連番をセットした2つのワークシートを作成する。
  • 2つのワークシートの同一行・同一列のセルの値を取得して、その2つを比較した結果、値が異なる場合は、2つのワークシートの2つの該当セルの背景色を黄色にする。
  • なお、今回のケースでは、1~99までは同一の値だが、100個目のセルを「sheet1」は「100」、「sheet1」は「200」をセットし、背景色を黄色にするデータとなっている。

sheet1

sheet1

sheet2

sheet2

タイプA

Option Explicit

Sub compare_worksheets()

    Dim ws_sheet1 As Worksheet
    Dim ws_sheet2 As Worksheet
    Dim num_row As Long
    Dim num_col As Long
    Dim num_sheet1 As Long
    Dim num_sheet2 As Long
    
    Application.ScreenUpdating = False
    
    Set ws_sheet1 = ThisWorkbook.Worksheets(1)
    Set ws_sheet2 = ThisWorkbook.Worksheets(2)
    
    For num_row = 1 To 10
        'A列の処理
        num_sheet1 = ws_sheet1.Range("A" & num_row)
            
        num_sheet2 = ws_sheet2.Range("A" & num_row)
            
        If num_sheet1 <> num_sheet2 Then
            ws_sheet1.Range("A" & num_row).Interior.Color = vbYellow
        
            ws_sheet2.Range("A" & num_row).Interior.Color = vbYellow
        End If
    
        'B列の処理
        num_sheet1 = ws_sheet1.Range("B" & num_row)
            
        num_sheet2 = ws_sheet2.Range("B" & num_row)
            
        If num_sheet1 <> num_sheet2 Then
            ws_sheet1.Range("B" & num_row).Interior.Color = vbYellow
        
            ws_sheet2.Range("B" & num_row).Interior.Color = vbYellow
        End If
    
        'C列の処理
        num_sheet1 = ws_sheet1.Range("C" & num_row)
            
        num_sheet2 = ws_sheet2.Range("C" & num_row)
            
        If num_sheet1 <> num_sheet2 Then
            ws_sheet1.Range("C" & num_row).Interior.Color = vbYellow
        
            ws_sheet2.Range("C" & num_row).Interior.Color = vbYellow
        End If
    
        'D列の処理
        num_sheet1 = ws_sheet1.Range("D" & num_row)
            
        num_sheet2 = ws_sheet2.Range("D" & num_row)
            
        If num_sheet1 <> num_sheet2 Then
            ws_sheet1.Range("D" & num_row).Interior.Color = vbYellow
        
            ws_sheet2.Range("D" & num_row).Interior.Color = vbYellow
        End If
    
        'E列の処理
        num_sheet1 = ws_sheet1.Range("E" & num_row)
            
        num_sheet2 = ws_sheet2.Range("E" & num_row)
            
        If num_sheet1 <> num_sheet2 Then
            ws_sheet1.Range("E" & num_row).Interior.Color = vbYellow
        
            ws_sheet2.Range("E" & num_row).Interior.Color = vbYellow
        End If
    
        'F列の処理
        num_sheet1 = ws_sheet1.Range("F" & num_row)
            
        num_sheet2 = ws_sheet2.Range("F" & num_row)
            
        If num_sheet1 <> num_sheet2 Then
            ws_sheet1.Range("F" & num_row).Interior.Color = vbYellow
        
            ws_sheet2.Range("F" & num_row).Interior.Color = vbYellow
        End If
    
        'G列の処理
        num_sheet1 = ws_sheet1.Range("G" & num_row)
            
        num_sheet2 = ws_sheet2.Range("G" & num_row)
            
        If num_sheet1 <> num_sheet2 Then
            ws_sheet1.Range("G" & num_row).Interior.Color = vbYellow
        
            ws_sheet2.Range("G" & num_row).Interior.Color = vbYellow
        End If
    
        'H列の処理
        num_sheet1 = ws_sheet1.Range("H" & num_row)
            
        num_sheet2 = ws_sheet2.Range("H" & num_row)
            
        If num_sheet1 <> num_sheet2 Then
            ws_sheet1.Range("H" & num_row).Interior.Color = vbYellow
        
            ws_sheet2.Range("H" & num_row).Interior.Color = vbYellow
        End If
    
        'I列の処理
        num_sheet1 = ws_sheet1.Range("I" & num_row)
            
        num_sheet2 = ws_sheet2.Range("I" & num_row)
            
        If num_sheet1 <> num_sheet2 Then
            ws_sheet1.Range("I" & num_row).Interior.Color = vbYellow
        
            ws_sheet2.Range("I" & num_row).Interior.Color = vbYellow
        End If
    
        'J列の処理
        num_sheet1 = ws_sheet1.Range("J" & num_row)
            
        num_sheet2 = ws_sheet2.Range("J" & num_row)
            
        If num_sheet1 <> num_sheet2 Then
            ws_sheet1.Range("J" & num_row).Interior.Color = vbYellow
        
            ws_sheet2.Range("J" & num_row).Interior.Color = vbYellow
        End If
    Next num_row
    
    ThisWorkbook.Save
    
    Application.ScreenUpdating = True

End Sub

タイプB

Option Explicit

Sub compare_worksheets()

    Dim ws_sheet1 As Worksheet
    Dim ws_sheet2 As Worksheet
    Dim num_row As Long
    Dim num_col As Long
    Dim num_sheet1 As Long
    Dim num_sheet2 As Long
    
    Application.ScreenUpdating = False
    
    Set ws_sheet1 = ThisWorkbook.Worksheets(1)
    Set ws_sheet2 = ThisWorkbook.Worksheets(2)
    
    For num_row = 1 To 10
        For num_col = 1 To 10
            num_sheet1 = ws_sheet1.Cells(num_row, num_col)
            
            num_sheet2 = ws_sheet2.Cells(num_row, num_col)
            
            If num_sheet1 <> num_sheet2 Then
                ws_sheet1.Cells(num_row, num_col).Interior.Color = vbYellow
        
                ws_sheet2.Cells(num_row, num_col).Interior.Color = vbYellow
            End If
        Next num_col
    Next num_row
    
    ThisWorkbook.Save
    
    Application.ScreenUpdating = True

End Sub

ケース2のタイプAとタイプBの比較結果

タイプAはRangeを使用しているため、列をアルファベットで表現するしかなく、列に対してのループ処理ができないので、非常に冗長なソースコードとなっています

タイプBはCellsを使用しているため、行と列の入れ子構造の二重ループでのコーディングが可能なため、非常にシンプルなソースコードとなっています

今回は10列しかないため、タイプAでもコーディングが可能な数でしたが、対象の列数が非常に多い場合や、データのよって列数が変動する可能性がある場合などを想定すると、ケース2のような行と列の両方を繰り回しが発生するループ処理は、タイプAでの実装は、事実上不可能と考えられます。

一方、タイプBは行と列の数が多い場合でも変動する可能性がある場合でも、基本的にはケース2と同様のシンプルなソースコードで対応可能です。

[emalabo式] ループ処理を作成する際のコーディングルール

ケース2のタイプAとタイプBの比較結果の結論から、emalabo式のコーディングルールはタイプBを採用することといたします

この記事を書いた人

某IT企業に勤務。

2年間の休職を経て、一から独学でExcel VBAを習得し、半年でExcel VBA エキスパート資格のスタンダードに一発合格。

社内の非効率的な作業を効率化するExcelマクロの開発を、全行程まるっと一人で請け負い、これまでに約100個のExcelマクロを開発し、現在も増産中。

目次